From ceb2af6b6c25a3fa864179be0444cd79fbe792fb Mon Sep 17 00:00:00 2001 From: Matthew Wells Date: Mon, 18 Dec 2023 13:45:13 -0600 Subject: [PATCH 001/148] added initial iridanext default --- nextflow.config | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/nextflow.config b/nextflow.config index 43ae2475..4b010f89 100644 --- a/nextflow.config +++ b/nextflow.config @@ -969,6 +969,21 @@ profiles { plugins { id 'nf-validation' id 'nf-prov' + id 'nf-iridanext' +} + + +iridanext { + enabled = true + output { + path = "${params.outdir}/iridanext.output.json.gz" + overwrite = true + files { + samples = [ + "**/assembly/polished/pilon/fasta/*.fasta.gz" + ] + } + } } prov { From e1c6957acb301e6485297862fdc5bfb0e84a09ce Mon Sep 17 00:00:00 2001 From: Matthew Wells Date: Fri, 2 Feb 2024 15:15:09 -0600 Subject: [PATCH 002/148] upgraded checkm resources to high --- modules/local/checkm_lineagewf.nf | 2 +- nextflow.config | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/local/checkm_lineagewf.nf b/modules/local/checkm_lineagewf.nf index 455346f4..1e55cada 100644 --- a/modules/local/checkm_lineagewf.nf +++ b/modules/local/checkm_lineagewf.nf @@ -3,7 +3,7 @@ process CHECKM_LINEAGEWF { tag "$meta.id" - label 'process_medium' + label 'process_high' container "${workflow.containerEngine == 'singularity' || workflow.containerEngine == 'apptainer' ? task.ext.containers.get('singularity') : task.ext.containers.get('docker')}" input: diff --git a/nextflow.config b/nextflow.config index 4b010f89..6f8ca2ab 100644 --- a/nextflow.config +++ b/nextflow.config @@ -979,8 +979,9 @@ iridanext { path = "${params.outdir}/iridanext.output.json.gz" overwrite = true files { + idkey = "id" samples = [ - "**/assembly/polished/pilon/fasta/*.fasta.gz" + "**/*" ] } } From f5147f8940363252b9c22054e0f5e5920dbcaf87 Mon Sep 17 00:00:00 2001 From: Eric Marinier Date: Wed, 28 Feb 2024 12:32:08 -0600 Subject: [PATCH 003/148] Adding samplesheet --- tests/data/samplesheets/samplesheet-campy-staph.csv | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 tests/data/samplesheets/samplesheet-campy-staph.csv diff --git a/tests/data/samplesheets/samplesheet-campy-staph.csv b/tests/data/samplesheets/samplesheet-campy-staph.csv new file mode 100644 index 00000000..c1666504 --- /dev/null +++ b/tests/data/samplesheets/samplesheet-campy-staph.csv @@ -0,0 +1,2 @@ +sample,fastq_1,fastq_2,long_reads,assembly +CSE,https://github.com/phac-nml/mikrokondo/raw/integration-testing/tests/data/reads/campy-staph1.fq.gz,https://github.com/phac-nml/mikrokondo/raw/integration-testing/tests/data/reads/campy-staph2.fq.gz,, From b4a7f9aabf4d925b2cd0c0074364eb9436a1c025 Mon Sep 17 00:00:00 2001 From: Eric Marinier Date: Wed, 28 Feb 2024 12:32:49 -0600 Subject: [PATCH 004/148] Update main.nf.test --- tests/main.nf.test | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/tests/main.nf.test b/tests/main.nf.test index 3a1d7c7b..8349bb29 100644 --- a/tests/main.nf.test +++ b/tests/main.nf.test @@ -8,19 +8,17 @@ nextflow_workflow { when { params { - input = "samplesheet-staph.csv" + input = "https://github.com/phac-nml/mikrokondo/raw/integration-testing/tests/data/samplesheets/samplesheet-campy-staph.csv" platform = "illumina" outdir = "results" - mash.mash_sketch = "campy-staph-ecoli.msh" - r_contaminants.mega_mm2_idx = "campy.mmi" + mash.mash_sketch = "https://github.com/phac-nml/mikrokondo/raw/integration-testing/tests/data/databases/campy-staph-ecoli.msh" + r_contaminants.mega_mm2_idx = "https://github.com/phac-nml/mikrokondo/raw/integration-testing/tests/data/databases/campy.mmi" skip_bakta = true skip_staramr = true skip_mobrecon = true skip_checkm = true skip_raw_read_metrics = true skip_polishing = true - max_memory = "4.GB" - max_cpus = 2 } workflow { """ From 7f66c4b86c908e344b25e93abf9e390df3973fc2 Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 28 Feb 2024 12:58:30 -0600 Subject: [PATCH 005/148] Very simple functioning integration test. --- bin/report_summaries.py | 0 nf-test.config | 4 ++++ tests/main.nf.test | 12 +++++++----- 3 files changed, 11 insertions(+), 5 deletions(-) mode change 100644 => 100755 bin/report_summaries.py diff --git a/bin/report_summaries.py b/bin/report_summaries.py old mode 100644 new mode 100755 diff --git a/nf-test.config b/nf-test.config index 5f163f2d..9c9f3ab0 100644 --- a/nf-test.config +++ b/nf-test.config @@ -6,4 +6,8 @@ config { profile "docker" withTrace false + stage { + symlink "nextflow_schema.json" + } + } diff --git a/tests/main.nf.test b/tests/main.nf.test index 8349bb29..3c67acda 100644 --- a/tests/main.nf.test +++ b/tests/main.nf.test @@ -9,10 +9,13 @@ nextflow_workflow { when { params { input = "https://github.com/phac-nml/mikrokondo/raw/integration-testing/tests/data/samplesheets/samplesheet-campy-staph.csv" - platform = "illumina" outdir = "results" - mash.mash_sketch = "https://github.com/phac-nml/mikrokondo/raw/integration-testing/tests/data/databases/campy-staph-ecoli.msh" - r_contaminants.mega_mm2_idx = "https://github.com/phac-nml/mikrokondo/raw/integration-testing/tests/data/databases/campy.mmi" + + platform = "illumina" + + mash { mash_sketch = "https://github.com/phac-nml/mikrokondo/raw/integration-testing/tests/data/databases/campy-staph-ecoli.msh" } + r_contaminants { mega_mm2_idx = "https://github.com/phac-nml/mikrokondo/raw/integration-testing/tests/data/databases/campy.mmi" } + skip_bakta = true skip_staramr = true skip_mobrecon = true @@ -22,8 +25,7 @@ nextflow_workflow { } workflow { """ - // define inputs of the workflow here. Example: - // input[0] = file("test-file.txt") + // define inputs of the workflow here. """ } } From c0beae5858fce7b0d9f2d71eeea2fdce5c49b4b1 Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 28 Feb 2024 13:51:01 -0600 Subject: [PATCH 006/148] Adding some specific asserts. --- tests/main.nf.test | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/main.nf.test b/tests/main.nf.test index 3c67acda..411ba8dd 100644 --- a/tests/main.nf.test +++ b/tests/main.nf.test @@ -32,6 +32,17 @@ nextflow_workflow { then { assert workflow.success + assert path("$launchDir/results").exists() + + // parse output json file + def json_string = path("$launchDir/results/SummaryReport/final_report.json").readLines().join("\n") + def json_parser = new groovy.json.JsonSlurper() + def json = json_parser.parseText(json_string) + + assert json.CSE.CSE.FastP.summary.sequencing.equals("paired end (150 cycles + 150 cycles)") + assert json.CSE.CSE.FastP.summary.before_filtering.total_reads.equals(248) + assert json.CSE.CSE.FastP.filtering_result.passed_filter_reads.equals(248) + assert json.CSE.CSE.FastP.insert_size.peak.equals(196) } } From 6fe181fb8b7aeb8b083ca2b5e9ad04f8dd0823c4 Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 29 Feb 2024 14:38:33 -0600 Subject: [PATCH 007/148] Switching to pipeline test. --- nf-test.config | 4 ---- tests/main.nf.test | 11 ++++------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/nf-test.config b/nf-test.config index 9c9f3ab0..5f163f2d 100644 --- a/nf-test.config +++ b/nf-test.config @@ -6,8 +6,4 @@ config { profile "docker" withTrace false - stage { - symlink "nextflow_schema.json" - } - } diff --git a/tests/main.nf.test b/tests/main.nf.test index 411ba8dd..0953597b 100644 --- a/tests/main.nf.test +++ b/tests/main.nf.test @@ -1,8 +1,7 @@ -nextflow_workflow { +nextflow_pipeline { name "Full Integration Tests for MIKROKONDO" script "main.nf" - workflow "MIKROKONDO" test("Should run without failures") { @@ -22,11 +21,9 @@ nextflow_workflow { skip_checkm = true skip_raw_read_metrics = true skip_polishing = true - } - workflow { - """ - // define inputs of the workflow here. - """ + + max_memory = "2.GB" + max_cpus = 1 } } From 17902044f3f94bf304e59aa522f6b03aaf48fb3c Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 29 Feb 2024 14:42:49 -0600 Subject: [PATCH 008/148] Updating data locations to dev. --- tests/main.nf.test | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/main.nf.test b/tests/main.nf.test index 0953597b..202330c2 100644 --- a/tests/main.nf.test +++ b/tests/main.nf.test @@ -7,13 +7,13 @@ nextflow_pipeline { when { params { - input = "https://github.com/phac-nml/mikrokondo/raw/integration-testing/tests/data/samplesheets/samplesheet-campy-staph.csv" + input = "https://github.com/phac-nml/mikrokondo/raw/dev/tests/data/samplesheets/samplesheet-campy-staph.csv" outdir = "results" platform = "illumina" - mash { mash_sketch = "https://github.com/phac-nml/mikrokondo/raw/integration-testing/tests/data/databases/campy-staph-ecoli.msh" } - r_contaminants { mega_mm2_idx = "https://github.com/phac-nml/mikrokondo/raw/integration-testing/tests/data/databases/campy.mmi" } + mash { mash_sketch = "https://github.com/phac-nml/mikrokondo/raw/dev/tests/data/databases/campy-staph-ecoli.msh" } + r_contaminants { mega_mm2_idx = "https://github.com/phac-nml/mikrokondo/raw/dev/tests/data/databases/campy.mmi" } skip_bakta = true skip_staramr = true From e62432396637612277b685e494e39139a8a3748b Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 29 Feb 2024 14:59:47 -0600 Subject: [PATCH 009/148] Cleaning up JSON parsing. --- tests/main.nf.test | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/main.nf.test b/tests/main.nf.test index 202330c2..a1c3c60a 100644 --- a/tests/main.nf.test +++ b/tests/main.nf.test @@ -32,9 +32,7 @@ nextflow_pipeline { assert path("$launchDir/results").exists() // parse output json file - def json_string = path("$launchDir/results/SummaryReport/final_report.json").readLines().join("\n") - def json_parser = new groovy.json.JsonSlurper() - def json = json_parser.parseText(json_string) + def json = path("$launchDir/results/SummaryReport/final_report.json").json assert json.CSE.CSE.FastP.summary.sequencing.equals("paired end (150 cycles + 150 cycles)") assert json.CSE.CSE.FastP.summary.before_filtering.total_reads.equals(248) From 7bdb797569c7c05d96a67c19b33496895693314a Mon Sep 17 00:00:00 2001 From: Eric Date: Mon, 4 Mar 2024 10:22:20 -0600 Subject: [PATCH 010/148] Updating test (failing to assembly). --- tests/data/databases/campy-staph-ecoli.msh | Bin 24824 -> 24800 bytes tests/main.nf.test | 14 +++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/data/databases/campy-staph-ecoli.msh b/tests/data/databases/campy-staph-ecoli.msh index 40b6be03923bbd5a1516475342f9a9778b3d72ec..86ad830791878aba0d6427d1732c331e0f91210a 100644 GIT binary patch delta 541 zcmZvZzfOce5Qi7S7@m9^k_LAwg+837(~ijm?Fu%PO3}5*7+8qKT~u`UDpC zCN#G964pM(l@0=iY@B4WGhcR-FTdSxr0_ ztHpLWcz~sXPtY&D;!7<)hJ&{TzQeiSe?62A@}+g=XjL6)hCZGk*KtlUNonF^Gj<#c zhw**Du743ru}K65*O-8CK)HD%LP9Y$Zv|@RTp*)0U1yPxP%Ac>&8Po}futV^3$_ z9ELbfSW27R>Wu6NQf)}p{~6kxc<=+ngO^~}Sx1Bg5Dr46+`CiC&&7#Sdg{6I E1HwqPfdBvi delta 565 zcmaKoKTpCy7>BPl3_36q2f1|C(rYQSCMGr)#l%2JU?=4`ZLy_I|ByH_yO=b70T%~1 zBcFiLFW~GKaA)*w!Ki4w<$a&`a(B=D-WI}gA(TXf&@d}$+am!wBp^4l=#B{E6j0jA zZl!ElDc=C(!w0B`V)iO!PnGf`zzz&wpgxOtd&2IF*?xFk8`+6nYthqzk}p#+beU}O z!0NSOXG#W_d=mIBlP@MV>QFeNl7=P|O!K?EU}&?1M|jM~>BPlxI*dd4lRC6dF(IU3 z;3I7H>5Ss0q8P-)%!vX&hy$PRV;1Np93HvMac4F>=7D7r$@u($sD*D1?G|b1`X4TFVu#L85u(-A?}@EB7s=a= z$cpcvRdU^C(}a__mtP9mv4F8O#&#NUDC_LjRAgsps{UVA^LO#8I={D$tMjgOR{a3# CzoIAr diff --git a/tests/main.nf.test b/tests/main.nf.test index a1c3c60a..e70422cd 100644 --- a/tests/main.nf.test +++ b/tests/main.nf.test @@ -3,7 +3,7 @@ nextflow_pipeline { name "Full Integration Tests for MIKROKONDO" script "main.nf" - test("Should run without failures") { + test("Should fail to assembly due to too few reads.") { when { params { @@ -15,6 +15,10 @@ nextflow_pipeline { mash { mash_sketch = "https://github.com/phac-nml/mikrokondo/raw/dev/tests/data/databases/campy-staph-ecoli.msh" } r_contaminants { mega_mm2_idx = "https://github.com/phac-nml/mikrokondo/raw/dev/tests/data/databases/campy.mmi" } + fastp { args { illumina = "-Q"} } + min_reads = 100 + mash { min_kmer = 1 } + skip_bakta = true skip_staramr = true skip_mobrecon = true @@ -38,6 +42,14 @@ nextflow_pipeline { assert json.CSE.CSE.FastP.summary.before_filtering.total_reads.equals(248) assert json.CSE.CSE.FastP.filtering_result.passed_filter_reads.equals(248) assert json.CSE.CSE.FastP.insert_size.peak.equals(196) + assert json.CSE.CSE.FastP.filtering_result.low_quality_reads.equals(0) + + //assert json.CSE.meta.metagenomic.equals(false) // Currently, this is "null". + assert json.CSE.meta.assembly.equals(false) + assert json.CSE.meta.hybrid.equals(false) + assert json.CSE.meta.single_end.equals(false) + assert json.CSE.meta.merge.equals(false) + assert json.CSE.meta.downsampled.equals(false) } } From a9480621286639a22bbe9f442b7b2b7c448afa14 Mon Sep 17 00:00:00 2001 From: Eric Date: Mon, 4 Mar 2024 11:41:26 -0600 Subject: [PATCH 011/148] Adding test data for small assembly. --- tests/data/reads/1_R1.fq.gz | Bin 0 -> 17054 bytes tests/data/reads/1_R2.fq.gz | Bin 0 -> 17369 bytes .../samplesheets/samplesheet-small-assembly.csv | 2 ++ 3 files changed, 2 insertions(+) create mode 100644 tests/data/reads/1_R1.fq.gz create mode 100644 tests/data/reads/1_R2.fq.gz create mode 100644 tests/data/samplesheets/samplesheet-small-assembly.csv diff --git a/tests/data/reads/1_R1.fq.gz b/tests/data/reads/1_R1.fq.gz new file mode 100644 index 0000000000000000000000000000000000000000..ccad56f8083d999598b0d5849cbfbba31aa3dae9 GIT binary patch literal 17054 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 b`1aE_a0MUXQRfu+1xjC2v&VA==FR^AT!mXO literal 0 HcmV?d00001 diff --git a/tests/data/reads/1_R2.fq.gz b/tests/data/reads/1_R2.fq.gz new file mode 100644 index 0000000000000000000000000000000000000000..da4ef09e6c851eb2f06814827911a127283adf06 GIT binary patch literal 17369 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 Date: Mon, 4 Mar 2024 14:36:08 -0600 Subject: [PATCH 012/148] Update samplesheet-small-assembly.csv --- tests/data/samplesheets/samplesheet-small-assembly.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/data/samplesheets/samplesheet-small-assembly.csv b/tests/data/samplesheets/samplesheet-small-assembly.csv index 5b3ac944..bab98509 100644 --- a/tests/data/samplesheets/samplesheet-small-assembly.csv +++ b/tests/data/samplesheets/samplesheet-small-assembly.csv @@ -1,2 +1,2 @@ sample,fastq_1,fastq_2,long_reads,assembly -short,/home/eric/projects/mikrokondo/tests/data/reads/1_R1.fq.gz,/home/eric/projects/mikrokondo/tests/data/reads/1_R2.fq.gz,, +short,https://github.com/phac-nml/mikrokondo/raw/integration-testing/tests/data/reads/1_R1.fq.gz,https://github.com/phac-nml/mikrokondo/raw/integration-testing/tests/data/reads/1_R2.fq.gz,, From f92322d2a328dc74437eb749fd016bfaf40556c7 Mon Sep 17 00:00:00 2001 From: Eric Date: Tue, 5 Mar 2024 08:50:53 -0600 Subject: [PATCH 013/148] Adding assembly test. --- tests/main.nf.test | 55 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/tests/main.nf.test b/tests/main.nf.test index e70422cd..44c658b1 100644 --- a/tests/main.nf.test +++ b/tests/main.nf.test @@ -49,7 +49,60 @@ nextflow_pipeline { assert json.CSE.meta.hybrid.equals(false) assert json.CSE.meta.single_end.equals(false) assert json.CSE.meta.merge.equals(false) - assert json.CSE.meta.downsampled.equals(false) + assert json.CSE.meta.downsampled.equals(false) + } + + } + + test("Should run without failure.") { + + when { + params { + input = "https://raw.githubusercontent.com/phac-nml/mikrokondo/integration-testing/tests/data/samplesheets/samplesheet-small-assembly.csv" + outdir = "results" + + platform = "illumina" + + mash { mash_sketch = "https://github.com/phac-nml/mikrokondo/raw/dev/tests/data/databases/campy-staph-ecoli.msh" } + r_contaminants { mega_mm2_idx = "https://github.com/phac-nml/mikrokondo/raw/dev/tests/data/databases/campy.mmi" } + + fastp { args { illumina = "-Q"} } + min_reads = 100 + mash { min_kmer = 1 } + + skip_bakta = true + skip_staramr = true + skip_mobrecon = true + skip_checkm = true + skip_raw_read_metrics = true + skip_polishing = true + + max_memory = "2.GB" + max_cpus = 1 + } + } + + then { + assert workflow.success + assert path("$launchDir/results").exists() + + // parse output json file + def json = path("$launchDir/results/SummaryReport/final_report.json").json + + assert json.short.short.FastP.summary.sequencing.equals("paired end (250 cycles + 250 cycles)") + assert json.short.short.FastP.summary.before_filtering.total_reads.equals(950) + assert json.short.short.FastP.filtering_result.passed_filter_reads.equals(950) + assert json.short.short.FastP.filtering_result.low_quality_reads.equals(0) + assert json.short.short.FastP.insert_size.peak.equals(347) + + //assert json.short.meta.metagenomic.equals(false) // Currently, this is "null". + assert json.short.meta.assembly.equals(false) + assert json.short.meta.hybrid.equals(false) + assert json.short.meta.single_end.equals(false) + assert json.short.meta.merge.equals(false) + assert json.short.meta.downsampled.equals(false) + + assert json.short.short.AssemblyCompleted.equals(true) } } From e0e409c3037e0e0fc73777122896aa9538f2f9ce Mon Sep 17 00:00:00 2001 From: Eric Date: Tue, 5 Mar 2024 09:00:20 -0600 Subject: [PATCH 014/148] Adding troubleshooting information. --- docs/troubleshooting/FAQ.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/troubleshooting/FAQ.md b/docs/troubleshooting/FAQ.md index 3003cb6a..a60b4969 100644 --- a/docs/troubleshooting/FAQ.md +++ b/docs/troubleshooting/FAQ.md @@ -77,3 +77,8 @@ Sometimes the resume features of Nextflow don't work completely. The above error - CheckM exit code 1, could not find concatenated.tree or concatentated.pplacer.json - This is a sign that CheckM has run out of memory, make sure you are using your desired executor. You may need to adjust configuration settings. + +### QUAST fails with a read-only error + +- `[Errno 30] Read-only file system: '/usr/local/lib/python3.9/site-packages/quast_libs/gridss'` + - This issue appears to be related to QUAST trying to download GRIDSS for structural variant detection and this action being incompatible with the container used to run QUAST. You may be able to resolve this be adding `--no-sv` as a QUAST command-line flag in Mikrokondo's `nextflow.config`, or by switching your container platform to singularity. Errors were observed with `apptainer version 1.2.3`, which were resolved by switching to singularity (`singularity-ce version 3.9.5` and `singularity-ce version a948062` resolved the issue). From db877d7bebcdcfbb8db982707a01ec87214a74fa Mon Sep 17 00:00:00 2001 From: Eric Date: Tue, 5 Mar 2024 10:07:41 -0600 Subject: [PATCH 015/148] Adding assembly checks. --- tests/main.nf.test | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/main.nf.test b/tests/main.nf.test index 44c658b1..6c6d4a80 100644 --- a/tests/main.nf.test +++ b/tests/main.nf.test @@ -103,6 +103,10 @@ nextflow_pipeline { assert json.short.meta.downsampled.equals(false) assert json.short.short.AssemblyCompleted.equals(true) + assert json.short.short.QUAST."0"."Total length (>= 0 bp)".equals("4949") + assert json.short.short.QUAST."0"."Largest contig".equals("4949") + assert json.short.short.QUAST."0"."GC (%)".equals("52.96") + assert json.short.short.QUAST."0"."Avg. coverage depth".equals("47") } } From 09de660af8fc947e5189d2882c00092bfac0de4c Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 6 Mar 2024 13:38:29 -0600 Subject: [PATCH 016/148] Adding a few more checks. --- tests/main.nf.test | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/main.nf.test b/tests/main.nf.test index 6c6d4a80..e57d8de0 100644 --- a/tests/main.nf.test +++ b/tests/main.nf.test @@ -49,7 +49,10 @@ nextflow_pipeline { assert json.CSE.meta.hybrid.equals(false) assert json.CSE.meta.single_end.equals(false) assert json.CSE.meta.merge.equals(false) - assert json.CSE.meta.downsampled.equals(false) + assert json.CSE.meta.downsampled.equals(false) + + def assembly_path = "$launchDir/results/assembly/length_filtered_contigs/short_filtered.fasta.gz" + assert path(assembly_path).exists().equals(false) } } @@ -107,6 +110,13 @@ nextflow_pipeline { assert json.short.short.QUAST."0"."Largest contig".equals("4949") assert json.short.short.QUAST."0"."GC (%)".equals("52.96") assert json.short.short.QUAST."0"."Avg. coverage depth".equals("47") + + def assembly_path = "$launchDir/results/assembly/length_filtered_contigs/short_filtered.fasta.gz" + assert path(assembly_path).exists() + + // parse assembly file + def assembly_header = path(assembly_path).linesGzip[0] + assert assembly_header.equals(">NODE_1_length_4949_cov_23.917254") } } From e16967ef825b161f0df7c752e544452f1ab93525 Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 6 Mar 2024 14:39:47 -0600 Subject: [PATCH 017/148] Fixing typo, adding directory check. --- tests/main.nf.test | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/main.nf.test b/tests/main.nf.test index e57d8de0..7082b4c6 100644 --- a/tests/main.nf.test +++ b/tests/main.nf.test @@ -51,8 +51,11 @@ nextflow_pipeline { assert json.CSE.meta.merge.equals(false) assert json.CSE.meta.downsampled.equals(false) - def assembly_path = "$launchDir/results/assembly/length_filtered_contigs/short_filtered.fasta.gz" + def assembly_path = "$launchDir/results/assembly/length_filtered_contigs/CSE_filtered.fasta.gz" assert path(assembly_path).exists().equals(false) + + def contigs_path = "$launchDir/results/assembly/length_filtered_contigs" + assert path(contigs_path).exists().equals(false) } } From 2e64feddf6650818f248ae649cd3411e735f1901 Mon Sep 17 00:00:00 2001 From: Eric Marinier Date: Wed, 6 Mar 2024 15:00:27 -0600 Subject: [PATCH 018/148] Updating URIs --- tests/data/samplesheets/samplesheet-small-assembly.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/data/samplesheets/samplesheet-small-assembly.csv b/tests/data/samplesheets/samplesheet-small-assembly.csv index bab98509..bc658f43 100644 --- a/tests/data/samplesheets/samplesheet-small-assembly.csv +++ b/tests/data/samplesheets/samplesheet-small-assembly.csv @@ -1,2 +1,2 @@ sample,fastq_1,fastq_2,long_reads,assembly -short,https://github.com/phac-nml/mikrokondo/raw/integration-testing/tests/data/reads/1_R1.fq.gz,https://github.com/phac-nml/mikrokondo/raw/integration-testing/tests/data/reads/1_R2.fq.gz,, +short,https://github.com/phac-nml/mikrokondo/raw/dev/tests/data/reads/1_R1.fq.gz,https://github.com/phac-nml/mikrokondo/raw/dev/tests/data/reads/1_R2.fq.gz,, From 522f8c27cfe3e65af24c60dc7eab3362fec2597d Mon Sep 17 00:00:00 2001 From: Eric Marinier Date: Wed, 6 Mar 2024 15:01:24 -0600 Subject: [PATCH 019/148] Updating URIs --- tests/main.nf.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/main.nf.test b/tests/main.nf.test index 7082b4c6..90dd0b93 100644 --- a/tests/main.nf.test +++ b/tests/main.nf.test @@ -64,7 +64,7 @@ nextflow_pipeline { when { params { - input = "https://raw.githubusercontent.com/phac-nml/mikrokondo/integration-testing/tests/data/samplesheets/samplesheet-small-assembly.csv" + input = "https://raw.githubusercontent.com/phac-nml/mikrokondo/dev/tests/data/samplesheets/samplesheet-small-assembly.csv" outdir = "results" platform = "illumina" From af33c9067a11927e48210607ad4db89b6693acc6 Mon Sep 17 00:00:00 2001 From: Matthew Wells Date: Wed, 6 Mar 2024 15:06:24 -0600 Subject: [PATCH 020/148] incorporated iridanext plugin --- conf/irida_next.config | 30 ++++++++++++++++++++++++++++++ nextflow.config | 17 ++--------------- 2 files changed, 32 insertions(+), 15 deletions(-) create mode 100644 conf/irida_next.config diff --git a/conf/irida_next.config b/conf/irida_next.config new file mode 100644 index 00000000..462d14d8 --- /dev/null +++ b/conf/irida_next.config @@ -0,0 +1,30 @@ +/* +IRIDANext plugin configuration + +*/ + + +iridanext { + enabled = true + output { + path = "${params.outdir}/iridanext.output.json.gz" + overwrite = true + validate = false + files { + idkey = "id" + global = [] + samples = [ + "**/assembly/length_filtered_contigs/*_filtered.fasta.gz", + "**/SummaryReport/*_flattened.json", + ] + } + metadata { + samples { + flatten = true + json { + path = "**/SummaryReport/final_report_flattened.json" + } + } + } + } +} diff --git a/nextflow.config b/nextflow.config index 32314abd..e5794239 100644 --- a/nextflow.config +++ b/nextflow.config @@ -925,23 +925,10 @@ plugins { //id 'nf-validation@2.0.0' id 'nf-validation@1.1.3' id 'nf-prov' - id 'nf-iridanext' + id 'nf-iridanext@0.2.0' } - -iridanext { - enabled = true - output { - path = "${params.outdir}/iridanext.output.json.gz" - overwrite = true - files { - idkey = "id" - samples = [ - "**/*" - ] - } - } -} +includeConfig 'conf/irida_next.config' prov { enabled = true From f63f60429ec11e834d6e0c1c26aa26354161a73f Mon Sep 17 00:00:00 2001 From: Matthew Wells Date: Wed, 6 Mar 2024 15:09:23 -0600 Subject: [PATCH 021/148] updated changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5cd08d8e..305d6698 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 Initial release of mk-kondo/mikrokondo, created with the [nf-core](https://nf-co.re/) template. ### `Added` +Incorporated IRIDANext plug-in Upgraded nf-validation to latest version 2.0.0 From 066b1a322fb47df98775e13ee806056c87f2a6fc Mon Sep 17 00:00:00 2001 From: Aaron Petkau Date: Thu, 7 Mar 2024 09:31:02 -0600 Subject: [PATCH 022/148] Updating what to store for iridanext --- conf/irida_next.config | 69 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 3 deletions(-) mode change 100644 => 100755 conf/irida_next.config diff --git a/conf/irida_next.config b/conf/irida_next.config old mode 100644 new mode 100755 index 462d14d8..e7d41420 --- a/conf/irida_next.config +++ b/conf/irida_next.config @@ -12,15 +12,78 @@ iridanext { validate = false files { idkey = "id" - global = [] + global = [ + "**/SummaryReport/final_report.json" + ] samples = [ "**/assembly/length_filtered_contigs/*_filtered.fasta.gz", - "**/SummaryReport/*_flattened.json", - ] + "**/assembly/quality/quast/*/*.pdf", + "**/assembly/7GeneMLST/*.json", + "**/assembly/taxon_determination/mash/*.taxa.screen", + "**/subtyping/ectyper/*/output.tsv", + "**/annotations/abricate/*.txt", + "**/annotations/mobrecon/*/mobtyper_results.txt", + "**/StarAMR/*/summary.tsv", + "**/StarAMR/*/detailed_summary.tsv", + "**/StarAMR/*/results.xlsx", + ] } metadata { samples { flatten = true + keep = [ + "QualityAnalysis.raw_average_quality.status", + "QualityAnalysis.raw_average_quality.message", + "QualityAnalysis.raw_average_quality.field", + "QualityAnalysis.raw_average_quality.low", + "QualityAnalysis.average_coverage.status", + "QualityAnalysis.average_coverage.message", + "QualityAnalysis.average_coverage.field", + "QualityAnalysis.average_coverage.low", + "QualityAnalysis.n50_value.status", + "QualityAnalysis.n50_value.message", + "QualityAnalysis.n50_value.field", + "QualityAnalysis.n50_value.low", + "QualityAnalysis.nr_contigs.status", + "QualityAnalysis.nr_contigs.message", + "QualityAnalysis.nr_contigs.field", + "QualityAnalysis.nr_contigs.low", + "QualityAnalysis.length.status", + "QualityAnalysis.length.message", + "QualityAnalysis.length.field", + "QualityAnalysis.length.low", + "QualityAnalysis.checkm_contamination.status", + "QualityAnalysis.checkm_contamination.message", + "QualityAnalysis.checkm_contamination.field", + "QualityAnalysis.checkm_contamination.low", + "QCStatus", + "QCSummary", + "MeetsReadThreshold", + "MashMeta", + "SeqtkBaseCount", + "AssemblyCompleted", + "MaxContigToShort", + "QUAST.0.# contigs", + "QUAST.0.Largest contig", + "QUAST.0.Total length", + "QUAST.0.Reference length", + "QUAST.0.Estimated reference length", + "QUAST.0.GC (%)", + "QUAST.0.Reference GC (%)", + "QUAST.0.N50", + "QUAST.0.NG50", + "QUAST.0.N90", + "QUAST.0.NG90", + "QUAST.0.auN", + "QUAST.0.auNG", + "QUAST.0.L50", + "QUAST.0.LG50", + "QUAST.0.L90", + "QUAST.0.LG90", + "SpeciesTopHit", + "DetectedGenomeSizeDepth", + "FixedGenomeSizeDepth", + ] json { path = "**/SummaryReport/final_report_flattened.json" } From b52831ccc906cb32ae42957812a00fc088e91e01 Mon Sep 17 00:00:00 2001 From: Aaron Petkau Date: Thu, 7 Mar 2024 10:54:53 -0600 Subject: [PATCH 023/148] Adding tests for iridanext output --- conf/irida_next.config | 1 + tests/main.nf.test | 12 ++++++++++++ tests/nextflow.config | 3 +++ 3 files changed, 16 insertions(+) diff --git a/conf/irida_next.config b/conf/irida_next.config index e7d41420..391a47df 100755 --- a/conf/irida_next.config +++ b/conf/irida_next.config @@ -26,6 +26,7 @@ iridanext { "**/StarAMR/*/summary.tsv", "**/StarAMR/*/detailed_summary.tsv", "**/StarAMR/*/results.xlsx", + "**/SummaryReport/*_flattened.json", ] } metadata { diff --git a/tests/main.nf.test b/tests/main.nf.test index 90dd0b93..a356a6c1 100644 --- a/tests/main.nf.test +++ b/tests/main.nf.test @@ -4,6 +4,7 @@ nextflow_pipeline { script "main.nf" test("Should fail to assembly due to too few reads.") { + tag "fail_assembly" when { params { @@ -61,6 +62,7 @@ nextflow_pipeline { } test("Should run without failure.") { + tag "succeed_assembly" when { params { @@ -120,6 +122,16 @@ nextflow_pipeline { // parse assembly file def assembly_header = path(assembly_path).linesGzip[0] assert assembly_header.equals(">NODE_1_length_4949_cov_23.917254") + + // compare IRIDA Next JSON output + def iridanext_json = path("$launchDir/results/iridanext.output.json").json + def iridanext_global = iridanext_json.files.global + def iridanext_samples = iridanext_json.files.samples + def iridanext_metadata = iridanext_json.metadata.samples + assert iridanext_global.findAll { it.path == "SummaryReport/final_report.json" }.size() == 1 + assert iridanext_samples.short.findAll { it.path == "assembly/length_filtered_contigs/short_filtered.fasta.gz" }.size() == 1 + assert iridanext_metadata.short."QUAST.0.Total length" == "4949" + assert iridanext_metadata.short."QUAST.0.N50" == "4949" } } diff --git a/tests/nextflow.config b/tests/nextflow.config index f41cebbb..6e7b5d64 100644 --- a/tests/nextflow.config +++ b/tests/nextflow.config @@ -6,3 +6,6 @@ params.max_memory = "2.GB" params.max_cpus = 1 + +/* Remove gzipping on JSON output for testing/asserts on file contents */ +iridanext.output.path = "${params.outdir}/iridanext.output.json" From 8abdba152d3b4edcb9ce085168023064b8dcfd3b Mon Sep 17 00:00:00 2001 From: Aaron Petkau Date: Thu, 7 Mar 2024 12:07:48 -0600 Subject: [PATCH 024/148] Added github linting tasks --- .github/workflows/linting.yml | 69 +++++++++++ .github/workflows/linting.yml.orig | 108 ------------------ ...g_comment.yml.orig => linting_comment.yml} | 6 +- 3 files changed, 72 insertions(+), 111 deletions(-) create mode 100644 .github/workflows/linting.yml delete mode 100644 .github/workflows/linting.yml.orig rename .github/workflows/{linting_comment.yml.orig => linting_comment.yml} (76%) diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml new file mode 100644 index 00000000..073e1876 --- /dev/null +++ b/.github/workflows/linting.yml @@ -0,0 +1,69 @@ +name: nf-core linting +# This workflow is triggered on pushes and PRs to the repository. +# It runs the `nf-core lint` and markdown lint tests to ensure +# that the code meets the nf-core guidelines. +on: + push: + branches: + - dev + pull_request: + release: + types: [published] + +jobs: + pre-commit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + + - name: Set up Python 3.11 + uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 + with: + python-version: 3.11 + cache: "pip" + + - name: Install pre-commit + run: pip install pre-commit + + - name: Run pre-commit + run: pre-commit run --all-files + + nf-core: + runs-on: ubuntu-latest + steps: + - name: Check out pipeline code + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + + - name: Install Nextflow + uses: nf-core/setup-nextflow@v1 + + - uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 + with: + python-version: "3.11" + architecture: "x64" + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install nf-core + + - name: Run nf-core lint + env: + GITHUB_COMMENTS_URL: ${{ github.event.pull_request.comments_url }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_PR_COMMIT: ${{ github.event.pull_request.head.sha }} + run: nf-core -l lint_log.txt lint --dir ${GITHUB_WORKSPACE} --markdown lint_results.md + + - name: Save PR number + if: ${{ always() }} + run: echo ${{ github.event.pull_request.number }} > PR_number.txt + + - name: Upload linting log file artifact + if: ${{ always() }} + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4 + with: + name: linting-logs + path: | + lint_log.txt + lint_results.md + PR_number.txt diff --git a/.github/workflows/linting.yml.orig b/.github/workflows/linting.yml.orig deleted file mode 100644 index 858d622e..00000000 --- a/.github/workflows/linting.yml.orig +++ /dev/null @@ -1,108 +0,0 @@ -name: nf-core linting -# This workflow is triggered on pushes and PRs to the repository. -# It runs the `nf-core lint` and markdown lint tests to ensure -# that the code meets the nf-core guidelines. -on: - push: - branches: - - dev - pull_request: - release: - types: [published] - -jobs: - EditorConfig: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - uses: actions/setup-node@v3 - - - name: Install editorconfig-checker - run: npm install -g editorconfig-checker - - - name: Run ECLint check - run: editorconfig-checker -exclude README.md $(find .* -type f | grep -v '.git\|.py\|.md\|json\|yml\|yaml\|html\|css\|work\|.nextflow\|build\|nf_core.egg-info\|log.txt\|Makefile') - - Prettier: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - uses: actions/setup-node@v3 - - - name: Install Prettier - run: npm install -g prettier - - - name: Run Prettier --check - run: prettier --check ${GITHUB_WORKSPACE} - - PythonBlack: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - name: Check code lints with Black - uses: psf/black@stable - - # If the above check failed, post a comment on the PR explaining the failure - - name: Post PR comment - if: failure() - uses: mshick/add-pr-comment@v1 - with: - message: | - ## Python linting (`black`) is failing - - To keep the code consistent with lots of contributors, we run automated code consistency checks. - To fix this CI test, please run: - - * Install [`black`](https://black.readthedocs.io/en/stable/): `pip install black` - * Fix formatting errors in your pipeline: `black .` - - Once you push these changes the test should pass, and you can hide this comment :+1: - - We highly recommend setting up Black in your code editor so that this formatting is done automatically on save. Ask about it on Slack for help! - - Thanks again for your contribution! - repo-token: ${{ secrets.GITHUB_TOKEN }} - allow-repeats: false - - nf-core: - runs-on: ubuntu-latest - steps: - - name: Check out pipeline code - uses: actions/checkout@v3 - - - name: Install Nextflow - uses: nf-core/setup-nextflow@v1 - - - uses: actions/setup-python@v4 - with: - python-version: "3.7" - architecture: "x64" - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install nf-core - - - name: Run nf-core lint - env: - GITHUB_COMMENTS_URL: ${{ github.event.pull_request.comments_url }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GITHUB_PR_COMMIT: ${{ github.event.pull_request.head.sha }} - run: nf-core -l lint_log.txt lint --dir ${GITHUB_WORKSPACE} --markdown lint_results.md - - - name: Save PR number - if: ${{ always() }} - run: echo ${{ github.event.pull_request.number }} > PR_number.txt - - - name: Upload linting log file artifact - if: ${{ always() }} - uses: actions/upload-artifact@v3 - with: - name: linting-logs - path: | - lint_log.txt - lint_results.md - PR_number.txt diff --git a/.github/workflows/linting_comment.yml.orig b/.github/workflows/linting_comment.yml similarity index 76% rename from .github/workflows/linting_comment.yml.orig rename to .github/workflows/linting_comment.yml index 67c82e0f..b706875f 100644 --- a/.github/workflows/linting_comment.yml.orig +++ b/.github/workflows/linting_comment.yml @@ -1,4 +1,4 @@ -name: nf-core linting comments +name: nf-core linting comment # This workflow is triggered after the linting action is complete # It posts an automated comment to the PR, even if the PR is coming from a fork @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Download lint results - uses: dawidd6/action-download-artifact@v2 + uses: dawidd6/action-download-artifact@f6b0bace624032e30a85a8fd9c1a7f8f611f5737 # v3 with: workflow: linting.yml workflow_conclusion: completed @@ -21,7 +21,7 @@ jobs: run: echo "pr_number=$(cat linting-logs/PR_number.txt)" >> $GITHUB_OUTPUT - name: Post PR comment - uses: marocchino/sticky-pull-request-comment@v2 + uses: marocchino/sticky-pull-request-comment@331f8f5b4215f0445d3c07b4967662a32a2d3e31 # v2 with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} number: ${{ steps.pr_number.outputs.pr_number }} From 30035f845372d25383d5937861a4057e3ee0c8ea Mon Sep 17 00:00:00 2001 From: Aaron Petkau Date: Thu, 7 Mar 2024 12:08:50 -0600 Subject: [PATCH 025/148] Removed unneeded github actions --- .github/workflows/branch.yml.bak | 44 --------------------- .github/workflows/fix-linting.yml.orig | 55 -------------------------- 2 files changed, 99 deletions(-) delete mode 100644 .github/workflows/branch.yml.bak delete mode 100644 .github/workflows/fix-linting.yml.orig diff --git a/.github/workflows/branch.yml.bak b/.github/workflows/branch.yml.bak deleted file mode 100644 index e8f8e3d4..00000000 --- a/.github/workflows/branch.yml.bak +++ /dev/null @@ -1,44 +0,0 @@ -name: nf-core branch protection -# This workflow is triggered on PRs to master branch on the repository -# It fails when someone tries to make a PR against the nf-core `master` branch instead of `dev` -on: - pull_request_target: - branches: [master] - -jobs: - test: - runs-on: ubuntu-latest - steps: - # PRs to the nf-core repo master branch are only ok if coming from the nf-core repo `dev` or any `patch` branches - - name: Check PRs - if: github.repository == 'mk-kondo/mikrokondo' - run: | - { [[ ${{github.event.pull_request.head.repo.full_name }} == mk-kondo/mikrokondo ]] && [[ $GITHUB_HEAD_REF = "dev" ]]; } || [[ $GITHUB_HEAD_REF == "patch" ]] - - # If the above check failed, post a comment on the PR explaining the failure - # NOTE - this doesn't currently work if the PR is coming from a fork, due to limitations in GitHub actions secrets - - name: Post PR comment - if: failure() - uses: mshick/add-pr-comment@v1 - with: - message: | - ## This PR is against the `master` branch :x: - - * Do not close this PR - * Click _Edit_ and change the `base` to `dev` - * This CI test will remain failed until you push a new commit - - --- - - Hi @${{ github.event.pull_request.user.login }}, - - It looks like this pull-request is has been made against the [${{github.event.pull_request.head.repo.full_name }}](https://github.com/${{github.event.pull_request.head.repo.full_name }}) `master` branch. - The `master` branch on nf-core repositories should always contain code from the latest release. - Because of this, PRs to `master` are only allowed if they come from the [${{github.event.pull_request.head.repo.full_name }}](https://github.com/${{github.event.pull_request.head.repo.full_name }}) `dev` branch. - - You do not need to close this PR, you can change the target branch to `dev` by clicking the _"Edit"_ button at the top of this page. - Note that even after this, the test will continue to show as failing until you push a new commit. - - Thanks again for your contribution! - repo-token: ${{ secrets.GITHUB_TOKEN }} - allow-repeats: false diff --git a/.github/workflows/fix-linting.yml.orig b/.github/workflows/fix-linting.yml.orig deleted file mode 100644 index 05037e3b..00000000 --- a/.github/workflows/fix-linting.yml.orig +++ /dev/null @@ -1,55 +0,0 @@ -name: Run prettier checks -on: - issue_comment: - types: [created] - -jobs: - deploy: - # Only run if comment is on a PR with the main repo, and if it contains the magic keywords - if: > - contains(github.event.comment.html_url, '/pull/') && - contains(github.event.comment.body, '@nf-core-bot fix linting') && - github.repository == 'mk-kondo/mikrokondo' - runs-on: ubuntu-latest - steps: - # Use the @nf-core-bot token to check out so we can push later - - uses: actions/checkout@v3 - with: - token: ${{ secrets.nf_core_bot_auth_token }} - - # Action runs on the issue comment, so we don't get the PR by default - # Use the gh cli to check out the PR - - name: Checkout Pull Request - run: gh pr checkout ${{ github.event.issue.number }} - env: - GITHUB_TOKEN: ${{ secrets.nf_core_bot_auth_token }} - - - uses: actions/setup-node@v3 - - - name: Install Prettier - run: npm install -g prettier @prettier/plugin-php - - # Check that we actually need to fix something - - name: Run 'prettier --check' - id: prettier_status - run: | - if prettier --check ${GITHUB_WORKSPACE}; then - echo "result=pass" >> $GITHUB_OUTPUT - else - echo "result=fail" >> $GITHUB_OUTPUT - fi - - - name: Run 'prettier --write' - if: steps.prettier_status.outputs.result == 'fail' - run: prettier --write ${GITHUB_WORKSPACE} - - - name: Commit & push changes - if: steps.prettier_status.outputs.result == 'fail' - run: | - git config user.email "core@nf-co.re" - git config user.name "nf-core-bot" - git config push.default upstream - git add . - git status - git commit -m "[automated] Fix linting with Prettier" - git push From 7dd3fbc893adc9baf38347c918dac29a759453f0 Mon Sep 17 00:00:00 2001 From: Aaron Petkau Date: Thu, 7 Mar 2024 12:10:33 -0600 Subject: [PATCH 026/148] Added template entry --- .nf-core.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.nf-core.yml b/.nf-core.yml index 83adc299..b39cc6ca 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -13,3 +13,5 @@ lint: - manifest.homePage multiqc_config: - report_comment +template: + prefix: phac-nml From ca467523a0585bf5d77246bc3464071b71c9cd72 Mon Sep 17 00:00:00 2001 From: Aaron Petkau Date: Thu, 7 Mar 2024 12:50:47 -0600 Subject: [PATCH 027/148] Ran linter --- modules.json | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/modules.json b/modules.json index 17a98c1a..c1c7abe1 100644 --- a/modules.json +++ b/modules.json @@ -9,6 +9,16 @@ "branch": "master", "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c", "installed_by": ["modules"] + }, + "fastqc": { + "branch": "master", + "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c", + "installed_by": ["modules"] + }, + "multiqc": { + "branch": "master", + "git_sha": "c8e35eb2055c099720a75538d1b8adb3fb5a464c", + "installed_by": ["modules"] } } } From d3d6888edf3b1aac54211dc324cf467c678ee6f4 Mon Sep 17 00:00:00 2001 From: Aaron Petkau Date: Thu, 7 Mar 2024 13:18:35 -0600 Subject: [PATCH 028/148] Ignoring many linting issues --- .gitattributes | 1 - .github/workflows/branch.yml | 44 ++++++++++++++++++++++++++++++++++++ .github/workflows/ci.yml | 2 +- .nf-core.yml | 36 +++++++++++++++++++++-------- pyproject.toml | 19 ++++++++++------ 5 files changed, 83 insertions(+), 19 deletions(-) create mode 100644 .github/workflows/branch.yml diff --git a/.gitattributes b/.gitattributes index 316d6d70..7a2dabc2 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,4 +2,3 @@ *.nf.test linguist-language=nextflow modules/nf-core/** linguist-generated subworkflows/nf-core/** linguist-generated - diff --git a/.github/workflows/branch.yml b/.github/workflows/branch.yml new file mode 100644 index 00000000..a691a282 --- /dev/null +++ b/.github/workflows/branch.yml @@ -0,0 +1,44 @@ +name: nf-core branch protection +# This workflow is triggered on PRs to master branch on the repository +# It fails when someone tries to make a PR against the `main` branch instead of `dev` +on: + pull_request_target: + branches: [main] + +jobs: + test: + runs-on: ubuntu-latest + steps: + # PRs to the nf-core repo master branch are only ok if coming from the nf-core repo `dev` or any `patch` branches + - name: Check PRs + if: github.repository == 'phac-nml/mikrokondo' + run: | + { [[ ${{github.event.pull_request.head.repo.full_name }} == phac-nml/mikrokondo ]] && [[ $GITHUB_HEAD_REF == "dev" ]]; } || [[ $GITHUB_HEAD_REF == "patch" ]] + + # If the above check failed, post a comment on the PR explaining the failure + # NOTE - this doesn't currently work if the PR is coming from a fork, due to limitations in GitHub actions secrets + - name: Post PR comment + if: failure() + uses: mshick/add-pr-comment@b8f338c590a895d50bcbfa6c5859251edc8952fc # v2 + with: + message: | + ## This PR is against the `main` branch :x: + + * Do not close this PR + * Click _Edit_ and change the `base` to `dev` + * This CI test will remain failed until you push a new commit + + --- + + Hi @${{ github.event.pull_request.user.login }}, + + It looks like this pull-request is has been made against the [${{github.event.pull_request.head.repo.full_name }}](https://github.com/${{github.event.pull_request.head.repo.full_name }}) `main` branch. + The `main` branch on nf-core repositories should always contain code from the latest release. + Because of this, PRs to `main` are only allowed if they come from the [${{github.event.pull_request.head.repo.full_name }}](https://github.com/${{github.event.pull_request.head.repo.full_name }}) `dev` branch. + + You do not need to close this PR, you can change the target branch to `dev` by clicking the _"Edit"_ button at the top of this page. + Note that even after this, the test will continue to show as failing until you push a new commit. + + Thanks again for your contribution! + repo-token: ${{ secrets.GITHUB_TOKEN }} + allow-repeats: false diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b645bd1e..e8dd8095 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: strategy: matrix: NXF_VER: - - "23.04.0" + - "22.10.1" - "latest-everything" steps: - name: Check out pipeline code diff --git a/.nf-core.yml b/.nf-core.yml index b39cc6ca..15b1d8d2 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -1,17 +1,33 @@ repository_type: pipeline lint: files_exist: - - CODE_OF_CONDUCT.md - - assets/nf-core-mikrokondo_logo_light.png - - docs/images/nf-core-mikrokondo_logo_light.png - - docs/images/nf-core-mikrokondo_logo_dark.png - - .github/ISSUE_TEMPLATE/config.yml - - .github/workflows/awstest.yml - - .github/workflows/awsfulltest.yml + - CODE_OF_CONDUCT.md + - assets/nf-core-mikrokondo_logo_light.png + - docs/images/nf-core-mikrokondo_logo_light.png + - docs/images/nf-core-mikrokondo_logo_dark.png + - .github/ISSUE_TEMPLATE/config.yml + - .github/workflows/awstest.yml + - .github/workflows/awsfulltest.yml + - docs/output.md + - docs/README.md + - docs/usage.md nextflow_config: - - manifest.name - - manifest.homePage + - manifest.name + - manifest.homePage multiqc_config: - - report_comment + - report_comment + - assets/multiqc_config.yml + files_unchanged: + - LICENSE + - .github/CONTRIBUTING.md + - .github/ISSUE_TEMPLATE/bug_report.yml + - .github/ISSUE_TEMPLATE/feature_request.yml + - .github/PULL_REQUEST_TEMPLATE.md + - .github/workflows/branch.yml + - assets/email_template.html + - assets/email_template.txt + - assets/sendmail_template.txt + - .gitignore + schema_params: template: prefix: phac-nml diff --git a/pyproject.toml b/pyproject.toml index 0d62beb6..56110621 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,10 +1,15 @@ -# Config file for Python. Mostly used to configure linting of bin/check_samplesheet.py with Black. +# Config file for Python. Mostly used to configure linting of bin/*.py with Ruff. # Should be kept the same as nf-core/tools to avoid fighting with template synchronisation. -[tool.black] +[tool.ruff] line-length = 120 -target_version = ["py37", "py38", "py39", "py310"] +target-version = "py38" +cache-dir = "~/.cache/ruff" -[tool.isort] -profile = "black" -known_first_party = ["nf_core"] -multi_line_output = 3 +[tool.ruff.lint] +select = ["I", "E1", "E4", "E7", "E9", "F", "UP", "N"] + +[tool.ruff.lint.isort] +known-first-party = ["nf_core"] + +[tool.ruff.lint.per-file-ignores] +"__init__.py" = ["E402", "F401"] From ed2aa810601eac54a31bb31b31aca2334c7fb370 Mon Sep 17 00:00:00 2001 From: Aaron Petkau Date: Thu, 7 Mar 2024 13:48:16 -0600 Subject: [PATCH 029/148] Ignoring nearly errored linting now --- .nf-core.yml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/.nf-core.yml b/.nf-core.yml index 15b1d8d2..38d28a5b 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -11,12 +11,6 @@ lint: - docs/output.md - docs/README.md - docs/usage.md - nextflow_config: - - manifest.name - - manifest.homePage - multiqc_config: - - report_comment - - assets/multiqc_config.yml files_unchanged: - LICENSE - .github/CONTRIBUTING.md @@ -28,6 +22,8 @@ lint: - assets/email_template.txt - assets/sendmail_template.txt - .gitignore - schema_params: + schema_params: False + nextflow_config: False + multiqc_config: False template: prefix: phac-nml From a4ffdfce48dd6202ce874cb3eb3027899c2dd282 Mon Sep 17 00:00:00 2001 From: Aaron Petkau Date: Thu, 7 Mar 2024 13:54:25 -0600 Subject: [PATCH 030/148] Revert dumpsoftwareversions back to version defined by commit --- modules/nf-core/custom/dumpsoftwareversions/main.nf | 7 ------- .../dumpsoftwareversions/templates/dumpsoftwareversions.py | 3 +-- 2 files changed, 1 insertion(+), 9 deletions(-) mode change 100644 => 100755 modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py diff --git a/modules/nf-core/custom/dumpsoftwareversions/main.nf b/modules/nf-core/custom/dumpsoftwareversions/main.nf index 0a7a6f55..3df21765 100644 --- a/modules/nf-core/custom/dumpsoftwareversions/main.nf +++ b/modules/nf-core/custom/dumpsoftwareversions/main.nf @@ -21,11 +21,4 @@ process CUSTOM_DUMPSOFTWAREVERSIONS { script: def args = task.ext.args ?: '' template 'dumpsoftwareversions.py' - - stub: - """ - touch software_versions.yml - touch software_versions_mqc.yml - touch versions.yml - """ } diff --git a/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py b/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py old mode 100644 new mode 100755 index e55b8d43..da033408 --- a/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py +++ b/modules/nf-core/custom/dumpsoftwareversions/templates/dumpsoftwareversions.py @@ -4,11 +4,10 @@ """Provide functions to merge multiple versions.yml files.""" +import yaml import platform from textwrap import dedent -import yaml - def _make_versions_html(versions): """Generate a tabular HTML output of all versions for MultiQC.""" From ffe1ffe400de6c080acc67a99f4676888eefadd5 Mon Sep 17 00:00:00 2001 From: ChristyPeterson Date: Wed, 6 Mar 2024 14:28:25 -0600 Subject: [PATCH 031/148] updates to README, CHANGELOG --- CHANGELOG.md | 1 + README.md | 111 +++++++++++++++++++++++++++++++++------------------ 2 files changed, 74 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5cd08d8e..952a4d0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 Initial release of mk-kondo/mikrokondo, created with the [nf-core](https://nf-co.re/) template. ### `Added` +Updated docs to include awesome-page plugin and restructured readme. Upgraded nf-validation to latest version 2.0.0 diff --git a/README.md b/README.md index 5c3f53cf..3f6d560a 100644 --- a/README.md +++ b/README.md @@ -8,31 +8,50 @@ [![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/) +# Introduction + ## What is mikrokondo? + Mikrokondo is a tidy workflow for performing routine bioinformatic tasks like, read pre-processing, assessing contamination, assembly and quality assessment of assemblies. It is easily configurable, provides dynamic dispatch of species specific workflows and produces common outputs. ## Is mikrokondo right for me? -Mikrokondo takes in either, Illumina, Nanopore or Pacbio data (Pacbio data only partially tested). You can also use mikrokondo for hybrid assemblies or even pass it pre-assembled genomes to handle annotation for you. Additionally, mikrokondo required minimal upfront knowledge of your sample. -# Installation +Mikrokondo is purpose built to provide sequencing and clinical laboratories with an all encompassing workflow to provide a standardized workflow that can provide the initial quality assessment of sequencing reads and assemblies, and initial pathogen-specific typing. It has been designed to be configurable so that new tools and quality metrics can be easily incorporated into the workflow to allow for automation of these routine tasks regardless of pathogen of interest. It currently accepts Illumina, Nanopore or Pacbio (Pacbio data only partially tested) sequencing data. It is capable of hybrid assembly or accepting pre-assembled genomes. + +This workflow will detect what pathogen(s) is present and apply the applicable metrics and genotypic typing where appropriate, generating easy to read and understand reports. If your group is regularly sequencing or analyzing genomic sequences, implementation of this workflow will automate the hands-on time time usually required for these common bioinformatic tasks. + +## Citation + +This software (currently unpublished) can be cited as: + +- Wells, M. "mikrokondo" Github + +An extensive list of references for the tools used by the pipeline can be found in the [`CITATIONS.md`](CITATIONS.md) file. + +### Contact +[Matthew Wells] : -## Installing Nextflow -Nextflow is required to run mikrokondo, but fortunately it is not too hard to install (Linux is required). The instructions for installing Nextflow can be found at either resource: [Nextflow Home](https://www.nextflow.io/) or [Nextflow Documentation](https://www.nextflow.io/docs/latest/getstarted.html#installation) +# Installing mikrokondo -## Container Engine -Nextflow and Mikrokondo only supports running the pipeline using containers such as: Docker, Singularity (now apptainer), podman, gitpod, shifter and charliecloud. Currently only usage with Singularity has been fully tested, (Docker and Apptainer have only been partially tested) but support for each of the container services exists. Note: Singularity was adopted by the Linux Foundation and is now called Apptainer. Singularity still exists, but it is likely newer installs will use Apptainer. +## Step 1: Installing Nextflow + +Nextflow is required to run mikrokondo (requires Linux), and instructions for its installation can be found at either: [Nextflow Home](https://www.nextflow.io/) or [Nextflow Documentation](https://www.nextflow.io/docs/latest/getstarted.html#installation) + +## Step 2: Choose a Container Engine + +Nextflow and Mikrokondo only supports running the pipeline using containers such as: Docker, Singularity (now apptainer), podman, gitpod, shifter and charliecloud. Currently only usage with Singularity has been fully tested, (Docker and Apptainer have only been partially tested) but support for each of the container services exists. + +>[!Note] +>Singularity was adopted by the Linux Foundation and is now called Apptainer. Singularity still exists, but it is likely newer installs will use Apptainer. + +### Docker or Singularity? -## Docker or Singularity? Docker or Singularity (Apptainer) Docker requires root privileges which can can make it a hassle to install on computing clusters (there are work arounds). Apptainer/Singularity does not, so running the pipeline using Apptainer/Singularity is the recommended method for running the pipeline. -### Issues -Containers are not perfect, below is a list of some issues you may face using containers in mikrokondo, fixes for each issue will be detailed here as they are identified. -- Exit code 137, likely means your docker container used to much memory. +## Step 3: Install dependencies -## Dependencies -Besides the Nextflow run time (requires Java), and container engine the dependencies required by mikrokondo are fairly minimal requiring only Python 3.10 (more recent Python versions will work as well) to run. Currently mikrokondo has been tested with fully with Singularity (partially with Apptainer, containers all work not all workflow paths tested) and partially tested with Docker (not all workflow paths tested). **Dependencies can be installed with Conda (e.g. Nextflow and Python)**. To download the pipeline run: -`git clone https://github.com/phac-nml/mikrokondo.git` +Besides the Nextflow run time (requires Java), and container engine the dependencies required by mikrokondo are fairly minimal requiring only Python 3.10 (more recent Python versions will work as well) to run. ### Dependencies listed @@ -41,20 +60,16 @@ Besides the Nextflow run time (requires Java), and container engine the dependen - Container service (Docker, Singularity, Apptainer have been tested) - The source code: `git clone https://github.com/phac-nml/mikrokondo.git` -# Usage -Please check out the documentation for usage instructions here: [docs](https://phac-nml.github.io/mikrokondo/) - -Under the usage section you can find example commands, instructions for configuration and a reference to a utility script to reduce command line bloat! - +## Step 4: Further resources to download -## Resources to download - [GTDB Mash Sketch](https://zenodo.org/record/8408361): required for speciation and determination if sample is metagenomic - [Decontamination Index](https://zenodo.org/record/8408557): Required for decontamination of reads (it is simply a minimap2 index) - [Kraken2 nt database](https://benlangmead.github.io/aws-indexes/k2): Required for binning of metagenommic data and is an alternative to using Mash for speciation - [Bakta database](https://zenodo.org/record/7669534): Running Bakta is optional and there is a light database option, however the full one is recommended. You will have to unzip and un-tar the database for usage. You can skip running Bakta however making the requirement of downloading this database **optional**. - [StarAMR database](https://github.com/phac-nml/staramr#database-build): Running StarAMR is optional and requires downloading the StarAMR databases. Also if you wish to avoid downloading the database, the container for StarAMR has a database included which mikrokondo will default to using if one is not specified making this requirement **optional**. -### Fields to update with resources +### Configuration and settings: + The above downloadable resources must be updated in the following places in your `nextflow.config`. The spots to update in the params section of the `nextflow.config` are listed below: ``` @@ -86,7 +101,36 @@ staramr { ``` +# Getting Started +## Usage + +``` +nextflow run main.nf --input PATH_TO_SAMPLE_SHEET --outdir OUTPUT_DIR --platform SEQUENCING_PLATFORM -profile CONTAINER_TYPE +``` + +Please check out the documentation for complete usage instructions here: [docs](https://phac-nml.github.io/mikrokondo/) + +Under the usage section you can find example commands, instructions for configuration and a reference to a utility script to reduce command line bloat! + +### Data Input/formats + +Mikrokondo requires two things as input: +1. **Sample files** - fastq and fasta must be in gzip format +2. **Sample sheet** - this FOFN (file of file names) contains sample names and allows user to combine read-sets. The following header fields are accepted: + - sample + - fastq_1 + - fastq_2 + - long_reads + - assembly + +For more information see the [useage docs](https://phac-nml.github.io/mikrokondo/usage/useage/). + +### Output/Results + +Explanation of how to interpret and/or export data. Include an example table of output if applicable with columns explained. + ## Run example data + Three test profile with example data are provided and can be run like so: - Assembly test profile: `nextflow run main.nf -profile test_assembly, --outdir ` @@ -117,30 +161,19 @@ nf-test test Add `--profile singularity` to switch from using docker by default to using singularity. -## TODOs +## Troubleshooting and FAQs: -- [ ] Add Shigella detection to GTDB sketch -- [x] allow autodetect of pointfinder db -- [ ] Add export of parameters after pipeline runs -- [ ] Provide a script for database downloads -- [ ] Update details in documentation -- [ ] Wait for allele caller -- [x] Upload test data +For a list of common issues or errors and their solutions, please read our [FAQ section](https://phac-nml.github.io/mikrokondo/troubleshooting/FAQ/). -## Enhancements +## References -- Swap Seqtk with Rasusa for down sampling -- Integrate nf-validate -- Trim pilon prefix added to contigs by pilon - -## Citations +An extensive list of references for the tools used by the pipeline can be found in the [`CITATIONS.md`](CITATIONS.md) file. - - +## Legal and Compliance Information: - +Copyright Government of Canada 2023 -An extensive list of references for the tools used by the pipeline can be found in the [`CITATIONS.md`](CITATIONS.md) file. +Written by: National Microbiology Laboratory, Public Health Agency of Canada This pipeline uses code and infrastructure developed and maintained by the [nf-core](https://nf-co.re) community, reused here under the [MIT license](https://github.com/nf-core/tools/blob/master/LICENSE). @@ -149,3 +182,5 @@ This pipeline uses code and infrastructure developed and maintained by the [nf-c > Philip Ewels, Alexander Peltzer, Sven Fillinger, Harshil Patel, Johannes Alneberg, Andreas Wilm, Maxime Ulysse Garcia, Paolo Di Tommaso & Sven Nahnsen. > > _Nat Biotechnol._ 2020 Feb 13. doi: [10.1038/s41587-020-0439-x](https://dx.doi.org/10.1038/s41587-020-0439-x). + +## Updates and Release Notes: From f24c83355897fa7d14ef464d9dd97e80ab88b1e8 Mon Sep 17 00:00:00 2001 From: Aaron Petkau Date: Thu, 7 Mar 2024 13:57:32 -0600 Subject: [PATCH 032/148] Removed some default values --- nextflow_schema.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/nextflow_schema.json b/nextflow_schema.json index 88d67768..1a05f3d0 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -2043,7 +2043,6 @@ "properties": { "kraken.db": { "type": "string", - "default": "/Drives/W/Projects/Project_Matthew_Wells/GSP/MikroKondo/mikrokondo/databases/k2_standard_20220607/", "description": "Path to Kraken2 database (do not use symlinks)" }, "kraken.classified_suffix": { @@ -2216,7 +2215,6 @@ }, "mash.mash_sketch": { "type": "string", - "default": "/Drives/W/Projects/Project_Matthew_Wells/GSP/MikroKondo/mikrokondo/databases/GTDBSketch_20231003.msh", "hidden": true }, "mash.sketch_ext": { @@ -2253,7 +2251,6 @@ }, "r_contaminants.mega_mm2_idx": { "type": "string", - "default": "/Drives/W/Projects/Project_Matthew_Wells/GSP/MikroKondo/mikrokondo/databases/PhiPacHum_m2.idx", "hidden": true }, "r_contaminants.mm2_illumina": { @@ -2792,7 +2789,6 @@ }, "bakta.db": { "type": "string", - "default": "/Drives/W/Projects/Project_Matthew_Wells/GSP/MikroKondo/mikrokondo/databases/db-light", "hidden": true }, "bakta.args": { From 8002e9210c4bc88c84afcdaedd75302f66a11ed7 Mon Sep 17 00:00:00 2001 From: ChristyPeterson Date: Thu, 7 Mar 2024 14:00:44 -0600 Subject: [PATCH 033/148] Added awesome-page plug in and .pages files for docs nav --- .pages | 6 ++++++ docs/usage/.pages | 7 +++++++ 2 files changed, 13 insertions(+) create mode 100644 .pages create mode 100644 docs/usage/.pages diff --git a/.pages b/.pages new file mode 100644 index 00000000..8a838442 --- /dev/null +++ b/.pages @@ -0,0 +1,6 @@ +nav: + - index.md + - usage + - troubleshooting + - workflows + - subworkflows \ No newline at end of file diff --git a/docs/usage/.pages b/docs/usage/.pages new file mode 100644 index 00000000..e4bd5925 --- /dev/null +++ b/docs/usage/.pages @@ -0,0 +1,7 @@ +nav: + - installation.md + - useage.md + - examples.md + - Utilities.md + - configuration.md + - tool_params.md \ No newline at end of file From 7e567e50064f4f99a73363876c80f23860ab7705 Mon Sep 17 00:00:00 2001 From: Aaron Petkau Date: Thu, 7 Mar 2024 15:57:40 -0600 Subject: [PATCH 034/148] Added pre commit config --- .pre-commit-config.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..af57081f --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,10 @@ +repos: + - repo: https://github.com/pre-commit/mirrors-prettier + rev: "v3.1.0" + hooks: + - id: prettier + - repo: https://github.com/editorconfig-checker/editorconfig-checker.python + rev: "2.7.3" + hooks: + - id: editorconfig-checker + alias: ec From b36cfd0e35cac9e463458812558046920642346f Mon Sep 17 00:00:00 2001 From: Aaron Petkau Date: Thu, 7 Mar 2024 16:00:36 -0600 Subject: [PATCH 035/148] Ignore pre-commit --- .github/workflows/linting.yml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 073e1876..ec151a53 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -11,22 +11,22 @@ on: types: [published] jobs: - pre-commit: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + # pre-commit: + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - - name: Set up Python 3.11 - uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 - with: - python-version: 3.11 - cache: "pip" + # - name: Set up Python 3.11 + # uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 + # with: + # python-version: 3.11 + # cache: "pip" - - name: Install pre-commit - run: pip install pre-commit + # - name: Install pre-commit + # run: pip install pre-commit - - name: Run pre-commit - run: pre-commit run --all-files + # - name: Run pre-commit + # run: pre-commit run --all-files nf-core: runs-on: ubuntu-latest From cb2f14d3d71e6067c54c1300a3fe7d1e37eb2f02 Mon Sep 17 00:00:00 2001 From: Aaron Petkau Date: Thu, 7 Mar 2024 16:05:47 -0600 Subject: [PATCH 036/148] Added linting to files_unchanged --- .nf-core.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.nf-core.yml b/.nf-core.yml index 38d28a5b..b03bcea5 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -18,6 +18,7 @@ lint: - .github/ISSUE_TEMPLATE/feature_request.yml - .github/PULL_REQUEST_TEMPLATE.md - .github/workflows/branch.yml + - .github/workflows/linting.yml - assets/email_template.html - assets/email_template.txt - assets/sendmail_template.txt From e1692090e36e9049d52eb5e5a94cbce8e6624d6f Mon Sep 17 00:00:00 2001 From: Aaron Petkau Date: Thu, 7 Mar 2024 16:13:42 -0600 Subject: [PATCH 037/148] Adjusted minimum nextflow version --- .github/workflows/ci.yml | 2 +- nextflow.config | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e8dd8095..b645bd1e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: strategy: matrix: NXF_VER: - - "22.10.1" + - "23.04.0" - "latest-everything" steps: - name: Check out pipeline code diff --git a/nextflow.config b/nextflow.config index 955e9598..bb7f6bb7 100644 --- a/nextflow.config +++ b/nextflow.config @@ -981,7 +981,7 @@ manifest { homePage = 'https://github.com/phac-nml/mikrokondo' description = """Mikrokondo beta""" mainScript = 'main.nf' - nextflowVersion = '!>=22.10.1' + nextflowVersion = '!>=23.04.0' version = '1.0dev' doi = '' } From 9a63c0a1e362a814228bb9e16cef29cfda805525 Mon Sep 17 00:00:00 2001 From: Aaron Petkau Date: Thu, 7 Mar 2024 16:23:54 -0600 Subject: [PATCH 038/148] Adjust nextflow badge in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5c3f53cf..059b6ab3 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ -[![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A522.10.1-23aa62.svg)](https://www.nextflow.io/) +[![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A523.04.0-23aa62.svg)](https://www.nextflow.io/) [![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?labelColor=000000&logo=docker)](https://www.docker.com/) [![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/) From e6edb11c7c3792ac75a61aa6f53588d758bcbcb2 Mon Sep 17 00:00:00 2001 From: Aaron Petkau Date: Thu, 7 Mar 2024 16:36:11 -0600 Subject: [PATCH 039/148] Enable pre-commit but adjust to only run on one file --- .github/workflows/linting.yml | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index ec151a53..dcc661ef 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -11,22 +11,23 @@ on: types: [published] jobs: - # pre-commit: - # runs-on: ubuntu-latest - # steps: - # - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + pre-commit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - # - name: Set up Python 3.11 - # uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 - # with: - # python-version: 3.11 - # cache: "pip" + - name: Set up Python 3.11 + uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 + with: + python-version: 3.11 + cache: "pip" - # - name: Install pre-commit - # run: pip install pre-commit + - name: Install pre-commit + run: pip install pre-commit - # - name: Run pre-commit - # run: pre-commit run --all-files + - name: Run pre-commit + #run: pre-commit run --all-files + run: pre-commit run --files README.md nf-core: runs-on: ubuntu-latest From d440e7b95aba3c78c82cab2f353660ab53d55fd5 Mon Sep 17 00:00:00 2001 From: Aaron Petkau Date: Thu, 7 Mar 2024 16:43:48 -0600 Subject: [PATCH 040/148] Removed unneeded github action --- .github/workflows/stub.yml.orig | 46 --------------------------------- 1 file changed, 46 deletions(-) delete mode 100644 .github/workflows/stub.yml.orig diff --git a/.github/workflows/stub.yml.orig b/.github/workflows/stub.yml.orig deleted file mode 100644 index 56b0a80c..00000000 --- a/.github/workflows/stub.yml.orig +++ /dev/null @@ -1,46 +0,0 @@ -name: Stub Run -# This workflow runs the pipeline with the minimal test dataset to check that it completes without any syntax errors -on: - push: - branches: - - dev - - main - workflow_run: - workflows: ["nf-core linting"] - #pull_request: - #release: - # types: [published] - -env: - NXF_ANSI_LOG: false - -concurrency: - group: "${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}" - cancel-in-progress: true - -jobs: - test: - name: Run pipeline with test data - # Only run on push if this is the nf-core dev branch (merged PRs) - #if: "${{ github.event_name != 'push' || (github.event_name == 'push' && github.repository == 'mk-kondo/mikrokondo') }}" - runs-on: ubuntu-latest - strategy: - matrix: - NXF_VER: - - "22.10.1" - - "latest-everything" - steps: - - name: Check out pipeline code - uses: actions/checkout@v3 - - - name: Install Nextflow - uses: nf-core/setup-nextflow@v1 - with: - version: "${{ matrix.NXF_VER }}" - - - name: Run pipeline with test data - # TODO nf-core: You can customise CI pipeline run tests as required - # For example: adding multiple test runs with different parameters - # Remember that you can parallelise this by using strategy.matrix - run: | - nextflow run ${GITHUB_WORKSPACE} -profile test_stub -stub-run --outdir ./results From 9319a7b6f0409f39463899cd1bf101b9a4d8b05d Mon Sep 17 00:00:00 2001 From: ChristyPeterson Date: Fri, 8 Mar 2024 14:35:43 -0600 Subject: [PATCH 041/148] continued docs updates: fixed nav, included mermaid workflow diagram and coding, wrote output section --- README.md | 13 +++++- .pages => docs/.pages | 0 docs/images/mikrokondo_mermaid.svg | 1 + docs/index.md | 2 +- docs/usage/useage.md | 40 ++++++++++++++---- docs/workflows/CleanAssemble.md | 6 +-- docs/workflows/PostAssembly.md | 10 ++--- utils/mikrokondo_mermaid.js | 66 ++++++++++++++++++++++++++++++ 8 files changed, 119 insertions(+), 19 deletions(-) rename .pages => docs/.pages (100%) create mode 100644 docs/images/mikrokondo_mermaid.svg create mode 100644 utils/mikrokondo_mermaid.js diff --git a/README.md b/README.md index 3f6d560a..75d14b4c 100644 --- a/README.md +++ b/README.md @@ -127,7 +127,18 @@ For more information see the [useage docs](https://phac-nml.github.io/mikrokondo ### Output/Results -Explanation of how to interpret and/or export data. Include an example table of output if applicable with columns explained. +All output files will be written into the `outdir` (specified by the user). More explicit tool results can be found in both the [Workflow](workflows/CleanAssemble/) and [Subworkflow](subworkflows/) sections of the docs. Here is a brief description of the outdir structure: + +- **annotations** - dir containing all annotation tool output. +- **assembly** - dir containing all assembly tool related output, including quality, 7 gene MLST and taxon determination. +- **pipeline_info** - dir containing all pipeline related information including software versions used and execution reports. +- **ReadQuality** - dir containing all read tool related output, including contamination, fastq, mash, and subsampled read sets (when present) +- **subtyping** - dir containing all subtyping tool related output, including SISTR, ECtyper, etc. +- **SummaryReport** - dir containing collated results files for all tools, including: + - Individual sample flatted json reports + - **final_report** - All tool results for all samples in both .json (including a flattened version) and .tsv format +- **bco.json** - data providence file generated from the nf-prov plug-in +- **manifest.json** - data providence file generated from the nf-prov plug-in ## Run example data diff --git a/.pages b/docs/.pages similarity index 100% rename from .pages rename to docs/.pages diff --git a/docs/images/mikrokondo_mermaid.svg b/docs/images/mikrokondo_mermaid.svg new file mode 100644 index 00000000..1bce78d5 --- /dev/null +++ b/docs/images/mikrokondo_mermaid.svg @@ -0,0 +1 @@ +
Annotate genome
Subtype genome
Determine species
Bin contigs
QC assemblies
Polish assemblies
Hybrid assembly
Assemble reads
QCread
set assembly flag
to `metagenomic`
Legend
Subworkflow
Workflow
Module
Decision
Bakta annotate
Annotate genome
Abricate
Parse mash/kraken2
Subtype genome
SEROTYPING TOOL
ECtyper
Lissero
ShigeFinder
SISTR
SPAtyper
Kleborate
Locidex
Determine species
Default
Mash screen
Metagenomic
Kraken
Kraken
Bin contigs
Bin contigs
Quast
QC assemblies
CheckM
LineageWF
7 gene MLST
Filter Quast
Illumina
Polish assemblies
Pilon iterate
Pacbio/nanopore
Medaka polish
Default
Hybrid assembly
Flye assemble
Bandage image
Create contig index
(Minimap2 index)
Generate SAM
(Minimap2 map)
Racon polish
Pilon interate
Unicycler
Unicycler assemble
Bandage image
Bandage image
Assemble reads
Illumina
Spades assemble
Pacbio/nanopore
Flye assemble
Create contig index
(Minimap2 index)
Generate SAM
(Minimap2 map)
Racon polish
Remove contaminants
(Minimap2)
QC reads / clean reads
Fastp
parse Fastp
trimming
estimate coverage
(kat_hist)
Subsample
(seqTK_sample)
Contamination check
(Mash screen)
Separate reads
(parse Mash)
Check input
Reads
Assembly
CleanAssemble
Metagenomic
Long read
or hybrid
short read
Isolate
Post assembly
Isolate
Metagenomic
\ No newline at end of file diff --git a/docs/index.md b/docs/index.md index 30a49434..1b2741aa 100644 --- a/docs/index.md +++ b/docs/index.md @@ -15,4 +15,4 @@ This workflow will detect what pathogen(s) is present and apply the applicable m ## Workflow Schematics (Subject to change) -![Pipeline](images/20230921_Mikrokondo-worflow2.png "Workflow") +![Pipeline](images/mikrokondo_mermaid.svg "Workflow") diff --git a/docs/usage/useage.md b/docs/usage/useage.md index 5063519f..02c465be 100644 --- a/docs/usage/useage.md +++ b/docs/usage/useage.md @@ -1,6 +1,20 @@ # Running MikroKondo -### Samplesheet +## Useage + +MikroKondo can be run like most other nextflow pipelines. The most basic usage is as follows: +`nextflow run main.nf --input PATH_TO_SAMPLE_SHEET --outdir OUTPUT_DIR --platform SEQUENCING_PLATFORM -profile CONTAINER_TYPE` + +Many parameters can be altered or accessed from the command line. For a full list of parameters to be altered please refer to the `nextflow.config` file in the repo. + +## Input + +This pipeline requires the following as input: + +### Sample files (gzip) +This pipeline requires sample files to be gzipped (symlinks may be problematic). + +### Samplesheet (CSV) Mikrokondo requires a sample sheet to be run. This FOFN (file of file names) contains the samples names and allows a user to combine read-sets based on that name if provided. The sample-sheet can utilize the following header fields: - sample @@ -9,7 +23,6 @@ Mikrokondo requires a sample sheet to be run. This FOFN (file of file names) con - long_reads - assembly -**The sample sheet must be in csv format and sample files must be gzipped** Example layouts for different sample-sheets include: @@ -37,12 +50,8 @@ _Starting with assembly only_ |------|--------| |sample_name|path_to_assembly| -## Useage -MikroKondo can be run like most other nextflow pipelines. The most basic usage is as follows: -`nextflow run main.nf --input PATH_TO_SAMPLE_SHEET --outdir OUTPUT_DIR --platform SEQUENCING_PLATFORM -profile CONTAINER_TYPE` - -Many parameters can be altered or accessed from the command line. For a full list of parameters to be altered please refer to the `nextflow.config` file in the repo. +## Command line arguments > **Note:** All the below settings can be permanently changed in the `nextflow.config` file within the `params` section. For example, to permanently set a nanopore chemistry and use Kraken for speciation: ``` @@ -50,8 +59,6 @@ Many parameters can be altered or accessed from the command line. For a full lis --nanopore_chemistry "r1041_e82_400bps_hac_v4.2.0" // Note the quotes used here ``` -### Common command line arguments - #### Nf-core boiler plate options - `--publish_dir_mode`: Method used to save pipeline results to output directory @@ -118,3 +125,18 @@ Different container services can be specified from the command line when running - `slurm_p true`: slurm execurtor will be used. - `slurm_profile STRING`: a string to allow the user to specify which slurm partition to use. + +## Output + +All output files will be written into the `outdir` (specified by the user). More explicit tool results can be found in both the [Workflow](/workflows/CleanAssemble/) and [Subworkflow](/subworkflows/assemble_reads/) sections of the docs. Here is a brief description of the outdir structure: + +- **annotations** - dir containing all annotation tool output. +- **assembly** - dir containing all assembly tool related output, including quality, 7 gene MLST and taxon determination. +- **pipeline_info** - dir containing all pipeline related information including software versions used and execution reports. +- **ReadQuality** - dir containing all read tool related output, including contamination, fastq, mash, and subsampled read sets (when present) +- **subtyping** - dir containing all subtyping tool related output, including SISTR, ECtyper, etc. +- **SummaryReport** - dir containing collated results files for all tools, including: + - Individual sample flatted json reports + - **final_report** - All tool results for all samples in both .json (including a flattened version) and .tsv format +- **bco.json** - data providence file generated from the nf-prov plug-in +- **manifest.json** - data providence file generated from the nf-prov plug-in \ No newline at end of file diff --git a/docs/workflows/CleanAssemble.md b/docs/workflows/CleanAssemble.md index defd6e6c..a4877694 100644 --- a/docs/workflows/CleanAssemble.md +++ b/docs/workflows/CleanAssemble.md @@ -11,7 +11,7 @@ ## Steps -1. **[QC reads](subworkflows/clean_reads)** subworkflow steps in brief are listed below, for further information see [clean_reads.nf](subworkflows/local/clean_reads.nf) +1. **[QC reads](/subworkflows/clean_reads)** subworkflow steps in brief are listed below, for further information see [clean_reads.nf](https://github.com/phac-nml/mikrokondo/blob/main/subworkflows/local/clean_reads.nf) - Reads are checked for known sequencing contamination - Quality metrics are calculated - Reads are trimmed @@ -19,9 +19,9 @@ - Read set subsampled to set level (OPTIONAL) - Read set is assessed to be either an isolate or metagenomic sample (from presence of multiple taxa) -2. **[Assemble reads](/subworkflows/assemble_reads)** using the `params.platform` flag, read sets will be diverted to either the assemble_reads (short reads) or hybrid_assembly (short and/or long reads) workflow. Though the data is handled differently in eash subworklow, both generate a contigs file and a bandage image, with an option of initial polishing via Racon. See [assemble_reads.nf](subworkflows/local/assemble_reads.nf) and [hybrid_assembly.nf](subworkflows/local/hybrid_assembly.nf) subworkflow pages for more details. +2. **[Assemble reads](/subworkflows/assemble_reads)** using the `params.platform` flag, read sets will be diverted to either the assemble_reads (short reads) or hybrid_assembly (short and/or long reads) workflow. Though the data is handled differently in eash subworklow, both generate a contigs file and a bandage image, with an option of initial polishing via Racon. See [assemble_reads.nf](https://github.com/phac-nml/mikrokondo/blob/main/subworkflows/local/assemble_reads.nf) and [hybrid_assembly.nf](https://github.com/phac-nml/mikrokondo/blob/main/subworkflows/local/hybrid_assembly.nf) subworkflow pages for more details. -3. **[Polish assembles](/subworkflows/polish_assemblies)** (OPTIONAL) Polishing of contigs can be added [polish_assemblies.nf](subworkflows/local/polish_assemblies.nf). To make changes to the default workflow, see setting 'optional flags' page. +3. **[Polish assembles](/subworkflows/polish_assemblies)** (OPTIONAL) Polishing of contigs can be added [polish_assemblies.nf](https://github.com/phac-nml/mikrokondo/blob/main/subworkflows/local/polish_assemblies.nf). To make changes to the default workflow, see setting 'optional flags' page. ## Input - Next generation sequencing reads: diff --git a/docs/workflows/PostAssembly.md b/docs/workflows/PostAssembly.md index fd884c66..d518fdff 100644 --- a/docs/workflows/PostAssembly.md +++ b/docs/workflows/PostAssembly.md @@ -13,11 +13,11 @@ This workflow is triggered in two ways: 1. when assemblies are used for initial - `subtype_genome.nf` ## Steps -1. **Determine type** using the `metagenomic_samples` flag, this workflow will direct assemblies to the following two paths: - a. Isolate: proceeds to step 2. - b. Metagenomic: runs the following two modules before proceeding to step 2. - i. [kraken2.nf](modules/local/kraken.nf) runs kraken 2 on contigs - ii. [bin_kraken2.nf](modules/local/bin_kraken2.nf) bins contigs to respective genus level taxa +1. **Determine type** using the `metagenomic_samples` flag, this workflow will direct assemblies to the following two paths: + 1. Isolate: proceeds to step 2. + 2. Metagenomic: runs the following two modules before proceeding to step 2. + 1. [kraken.nf](https://github.com/phac-nml/mikrokondo/blob/main/modules/local/kraken.nf) runs kraken2 on contigs + 2. [bin_kraken2.nf](https://github.com/phac-nml/mikrokondo/blob/main/modules/local/bin_kraken2.nf) bins contigs to respective genus level taxa 2. **[QC assemblies](/subworkflows/qc_assembly)** (OPTIONAL) runs quast and assigns quality metrics to generated assemblies 3. **[Determine species](/subworkflows/determine_species)** (OPTIONAL) runs classifier tool (default: [Mash](https://github.com/marbl/Mash)) to determine sample or binned species 4. **[Subtype genome](/subworkflows/subtype_genome)** (OPTIONAL) species specific subtyping tools are launched using a generated MASH screen report. diff --git a/utils/mikrokondo_mermaid.js b/utils/mikrokondo_mermaid.js new file mode 100644 index 00000000..e226d211 --- /dev/null +++ b/utils/mikrokondo_mermaid.js @@ -0,0 +1,66 @@ +flowchart LR + CI(Check input):::lightGreen --> R((Reads)); + CI --> A((Assembly)); + R --> CA(CleanAssemble):::pink; + CA --> QC(QC reads / clean reads):::lightGreen; + QC --> QC1("Remove contaminants
(Minimap2)"):::orange; + QC1 --> QC2(Fastp):::orange; + QC2 --> QC3(parse Fastp
trimming):::orange; + QC3 --> QC4("estimate coverage
(kat_hist)"):::orange; + QC4 --> QC5("Subsample
(seqTK_sample)"):::orange; + QC5 --> QC6("Contamination check
(Mash screen)"):::orange; + QC6 --> QC7("Separate reads
(parse Mash)"):::orange; + QC --> SR((short read)); + SR --> I((Isolate)); + SR --> M((Metagenomic)); + I --> AR(Assemble reads):::lightGreen; + AR --> AR1(Bandage image):::orange; + AR1 --> AR2((Illumina)); + AR2 --> AR22(Spades assemble):::orange; + AR1 --> AR3((Pacbio/nanopore)); + AR3 --> AR32(Flye assemble):::orange; + AR22 --> HAD3; + AR32 --> HAD3; + M -->|"set assembly flag
to `metagenomic`"| AR; + QC --> H((Long read
or hybrid)); + H --> HA(Hybrid assembly):::lightGreen; + HA --> HAD((Default)); + HAD --> HAD1(Flye assemble):::orange; + HAD1 --> HAD2(Bandage image):::orange; + HAD2 --> HAD3("Create contig index
(Minimap2 index)"):::orange; + HAD3 --> HAD4("Generate SAM
(Minimap2 map)"):::orange; + HAD4 --> HAD5(Racon polish):::orange; + HAD5 --> HAD6(Pilon interate):::orange; + HA --> HAU((Unicycler)); + HAU --> HAU1(Unicycler assemble):::orange; + HAU1 --> HAU2(Bandage image):::orange; + QC7 --> PA(Polish assemblies):::lightGreen; + HAD6 --> PA; + HAU2 --> PA; + PA --> PAI((Illumina)); + PAI --> PAI1(Pilon iterate):::orange; + PA --> PAN((Pacbio/nanopore)); + PAN --> PAN1(Medaka polish):::orange; + PAI1 --> PASS(Post assembly):::pink; + PAN1 --> PASS; + A --> PASS; + PASS --> I1((Isolate)); + PASS --> M1((Metagenomic)); + I1 --> QCA(QC assemblies):::lightGreen; + + + subgraph legend [Legend] + direction LR; + wk(Workflow):::pink --> sw(Subworkflow):::lightGreen; + sw --> m(Module):::orange; + d((Decision)); + end + + + + + + + classDef lightGreen fill:#0ABC9B,stroke:#0ABC9B,stroke-width:2px,rx:10px,ry:10px; + classDef pink fill:#F681CB,stroke:#F681CB,stroke-width:2px,rx:10px,ry:10px; + classDef orange fill:#F2B581,stroke:#F2B581,stroke-width:2px,rx:10px,ry:10px; From 9bd65a48d3b876d955fa8e0a9b6e3956db7c9954 Mon Sep 17 00:00:00 2001 From: Aaron Petkau Date: Fri, 8 Mar 2024 16:17:39 -0600 Subject: [PATCH 042/148] Ignores pre-commit check on README for now --- .github/workflows/linting.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index dcc661ef..fff238b2 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -27,7 +27,7 @@ jobs: - name: Run pre-commit #run: pre-commit run --all-files - run: pre-commit run --files README.md + run: pre-commit run --files nf-test.config nf-core: runs-on: ubuntu-latest From 1531af31733b3f815bfb6d4a8f490250d7f4a3e8 Mon Sep 17 00:00:00 2001 From: Aaron Petkau Date: Fri, 8 Mar 2024 16:56:43 -0600 Subject: [PATCH 043/148] Adding tests from assembled genomes --- .../GCA_000947975.1_ASM94797v1_genomic.fna.gz | Bin 0 -> 1644628 bytes .../samplesheet-test-from-assemblies.csv | 2 + tests/main.nf.test | 20 +++++++ tests/pipelines/main.from_assemblies.nf.test | 52 ++++++++++++++++++ 4 files changed, 74 insertions(+) create mode 100644 tests/data/genomes/ecoli/GCA_000947975.1_ASM94797v1_genomic.fna.gz create mode 100644 tests/data/samplesheets/samplesheet-test-from-assemblies.csv create mode 100644 tests/pipelines/main.from_assemblies.nf.test diff --git a/tests/data/genomes/ecoli/GCA_000947975.1_ASM94797v1_genomic.fna.gz b/tests/data/genomes/ecoli/GCA_000947975.1_ASM94797v1_genomic.fna.gz new file mode 100644 index 0000000000000000000000000000000000000000..4f5d9a5cda0e040992b5b0b24f809367a90452db GIT binary patch literal 1644628 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