diff --git a/CHANGELOG.md b/CHANGELOG.md index bfeeac1..8ba1bac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [unreleased] +## [v0.2.14] ### Added - `--isolates` parameter that will run the ResFinder tool on the final assembly to output antimicrobial resistance genes. - Configuration for running demo data in AWS diff --git a/bin/workflow_glue/report.py b/bin/workflow_glue/report.py index e9f3a04..446a49d 100755 --- a/bin/workflow_glue/report.py +++ b/bin/workflow_glue/report.py @@ -63,7 +63,7 @@ def get_flye_stats(sample_names, flye_dir, flye_suffix): return flye_out -def gather_sample_files(sample_names, denovo_mode, prokka_mode, resfinder_mode): +def gather_sample_files(sample_names, denovo_mode, prokka_mode): """Collect files required for the report per sample and make sure they exist.""" sample_files = {} subdirs_and_suffixes = { @@ -86,13 +86,15 @@ def gather_sample_files(sample_names, denovo_mode, prokka_mode, resfinder_mode): file_type in ("total_depth", "fwd_depth", "rev_depth") or (file_type == "variants" and not denovo_mode) or (file_type == "prokka" and prokka_mode) - or (file_type == "resfinder" and resfinder_mode) ): if not os.path.exists(file): raise ValueError( f"Required file '{file_type}' missing " f"for sample '{sample_name}'." ) + elif (file_type == "resfinder"): + if not os.path.exists(file): + file = None else: # this covers the cases when files are not needed (e.g. `variants` when # doing a de-novo assembly) @@ -282,7 +284,7 @@ def main(args): # Gather stats files for each sample (will be used by the various report sections # below) sample_files = gather_sample_files( - args.sample_ids, args.denovo, args.prokka, args.resfinder) + args.sample_ids, args.denovo, args.prokka) with report.add_section("Genome coverage", "Depth"): html_tags.p( @@ -362,12 +364,16 @@ def main(args): else None ) # now the indel length histogram - indel_lengths_df = bcf_stats["IDD"].query("sample == @sample") - indel_hist = ( - get_indel_length_histogram(indel_lengths_df) - if not indel_lengths_df.empty - else None - ) + indel_hist = None + if ( + "IDD" in bcf_stats + and not ( + indel_lengths_df := bcf_stats["IDD"].query( + "sample == @sample" + ) + ).empty + ): + indel_hist = get_indel_length_histogram(indel_lengths_df) with Grid(): if subst_heatmap is not None: EZChart(subst_heatmap, "epi2melabs") @@ -416,11 +422,20 @@ def main(args): with tabs.add_dropdown_menu(): for name, files in sample_files.items(): with tabs.add_dropdown_tab(name): - resfinder_df = pd.read_csv( - files["resfinder"], sep='\t').rename( - columns=lambda col: col[0].upper() + col[1:] - ) - DataTable.from_pandas(resfinder_df, use_index=False) + if files["resfinder"] is None: + html_raw(""" + + Resfinder did not work for this sample. + Please check that species and reference parameters are relevant + to the sample. + """) + else: + + resfinder_df = pd.read_csv( + files["resfinder"], sep='\t').rename( + columns=lambda col: col[0].upper() + col[1:] + ) + DataTable.from_pandas(resfinder_df, use_index=False) report.write(args.output) logger.info(f"Report written to {args.output}.") diff --git a/main.nf b/main.nf index 0ace5da..1629d4d 100644 --- a/main.nf +++ b/main.nf @@ -53,7 +53,6 @@ process deNovo { tuple val(meta), path("${meta.alias}.draft_assembly.fasta.gz"), path("${meta.alias}_flye_stats.tsv") script: """ - echo memory: $task.memory flye --nano-raw reads.fastq.gz --out-dir output --threads "${task.cpus}" mv output/assembly.fasta "./${meta.alias}.draft_assembly.fasta" mv output/assembly_info.txt "./${meta.alias}_flye_stats.tsv" diff --git a/modules/local/amr.nf b/modules/local/amr.nf index 19f78dc..19e8bf6 100644 --- a/modules/local/amr.nf +++ b/modules/local/amr.nf @@ -2,15 +2,15 @@ process resfinderAcquiredOnly { label "amr" - containerOptions '--entrypoint=""' + errorStrategy 'ignore' input: tuple val(meta), path("input_genome.fasta.gz") output: - tuple val(meta), path("${meta.alias}_resfinder_results") + tuple val(meta), path("${meta.alias}_resfinder_results"), optional: true script: """ gunzip -c input_genome.fasta.gz > input_genome.fasta - python -m resfinder --acquired -ifa input_genome.fasta --outputPath ${meta.alias}_resfinder_results + python -m resfinder --acquired -ifa input_genome.fasta --outputPath ${meta.alias}_resfinder_results || exit 0 """ } @@ -32,7 +32,7 @@ process processResfinderAquired { process resfinderFull { label "amr" - containerOptions '--entrypoint=""' + errorStrategy 'ignore' input: tuple val(meta), path("input_genome.fasta.gz") val species @@ -54,7 +54,7 @@ process resfinderFull { -s "${species_input}" \ --point \ -ifa input_genome.fasta \ - --disinfectant + --disinfectant || exit 0 """ } diff --git a/nextflow.config b/nextflow.config index da6abc9..543fe19 100644 --- a/nextflow.config +++ b/nextflow.config @@ -54,7 +54,7 @@ manifest { description = 'Assembly, variant calling, and annotation of bacterial genomes.' mainScript = 'main.nf' nextflowVersion = '>=20.10.0' - version = 'v0.2.13' + version = 'v0.2.14' } epi2melabs { @@ -83,6 +83,7 @@ process { } withLabel:amr { container = "genomicepidemiology/resfinder:${params.resfinder_version}" + containerOptions = {workflow.profile == "standard" ? "--entrypoint=''" : ""} } shell = ['/bin/bash', '-euo', 'pipefail'] }