From b9b0df27ec4f3ea1e786dfa903f58f780998855a Mon Sep 17 00:00:00 2001 From: Fredrik Boulund Date: Tue, 2 Feb 2021 12:55:00 +0100 Subject: [PATCH] Merge 0.4.1 (#155) * Update version to 0.4.1-dev * Update CircleCI badge in README to monitor develop branch * Add Singularity deffile for stag-mwc env * Add Singularity image for main env up to kraken2 * Add link to Singularity bind docs * Add stag-mwc-main singularity image to all rules that require it * Add Singularity images for biobakery and assembly * Set rule threads from cluster_config if defined * Update CHANGELOG * Docs: Update module intro paragraph, closes #151 * Add {cluster.extra} to slurm-submit.py script call * Update CHANGELOG * Fix typo in kraken2 rules * the host removal script was ignoring it's flag in config.yaml * Update CHANGELOG * Update CHANGELOG * Tweak docs, update changelog, prepare for release * Amrplusplus (#156) * amrplusplus * amrplusplus scripts * added scripts * changed input in config.yaml Co-authored-by: Fredrik Boulund * default db empty Co-authored-by: Fredrik Boulund * db -> megares Co-authored-by: Fredrik Boulund * annotation --> megares_annotation Co-authored-by: Fredrik Boulund * added amrplusplus to circleci * updated CHANGELOG.md * updated amrplusplus in config.yaml * added amrplusplus to modules.rst * updated amrplusplus.smk * added license and removed bin dir * updated modules.rst * added align_to_amr * fixed default database * amrplusplus db empty in conf * indentations * clarification regarding database * Update docs/source/modules.rst Co-authored-by: Fredrik Boulund * Update rules/antibiotic_resistance/amrplusplus.smk Co-authored-by: Fredrik Boulund * Update docs/source/modules.rst grammar Co-authored-by: Fredrik Boulund * Update CHANGELOG.md Co-authored-by: Fredrik Boulund * added bwa to stag-mwc.yaml * added conda environment * amrplusplus exectuable with conda * amrplusplus executable with conda * samtools version 1.10 * amrplusplus conda executable * added amrplusplus.yaml to not break stag-mwc.yaml dependencies * removed amrplusplus dependencies because they broke it * now using amrplusplus.yaml for conda instead of stag-mwc.yaml Co-authored-by: Fredrik Boulund Co-authored-by: Aron Arzoomand * Change report generation call (#161) * Change report generation call Ignore additional arguments to snakemake when creating report, Intended to avoid shell escaping issue with complex arguments to e.g. Singularity, issue #160 * removed snakemake_call * added report generation workaround * report generation Co-authored-by: Fredrik Boulund * report generation Co-authored-by: Fredrik Boulund * indentation Co-authored-by: Aron Arzoomand <51719360+AroArz@users.noreply.github.com> * Slurm profile for CTMR UCP environment (#159) * First draft for CTMR UCP cluster profile * Remove references to rackham profile, remove account check * Updated resource requests for all rules * Final tweaks * Rename ctmr_ucp profile to ctmr_gandalf * Fix yml-yaml typo * Fix incorrectly named singularity images * Remove --use prefix for argument to metawrap * Add missing singularity container to create_kaiju_krona_plot * added dbdir and threads for align_to_amr * Disable area plot for Kaiju * Minor updates to docs (#162) * Update badge URL in README Co-authored-by: Kristaps Co-authored-by: Aron Arzoomand <51719360+AroArz@users.noreply.github.com> Co-authored-by: Aron Arzoomand Co-authored-by: AroArz --- .circleci/config.yml | 3 +- CHANGELOG.md | 30 +++ README.md | 14 +- Snakefile | 10 +- cluster_configs/ctmr_gandalf/config.yaml | 8 + .../ctmr_gandalf/ctmr_gandalf.yaml | 90 +++++++ .../ctmr_gandalf/slurm-jobscript.sh | 3 + cluster_configs/ctmr_gandalf/slurm-status.py | 61 +++++ cluster_configs/ctmr_gandalf/slurm-submit.py | 147 +++++++++++ cluster_configs/rackham/config.yaml | 2 +- cluster_configs/rackham/rackham.yaml | 37 ++- config.yaml | 16 +- docs/source/conf.py | 4 +- docs/source/faq.rst | 4 +- docs/source/index.rst | 2 +- docs/source/installation.rst | 10 +- docs/source/modules.rst | 35 ++- docs/source/running.rst | 62 ++++- envs/Singularity.amrplusplus | 55 +++++ envs/Singularity.assembly | 30 +++ envs/Singularity.biobakery | 30 +++ envs/Singularity.stag-mwc | 50 ++++ envs/amrplusplus.yaml | 8 + envs/metaphlan2.yaml | 2 +- rules/antibiotic_resistance/amrplusplus.smk | 232 ++++++++++++++++++ rules/antibiotic_resistance/groot.smk | 10 +- rules/assembly/metawrap.smk | 18 +- rules/functional_profiling/humann2.smk | 10 +- rules/mappers/bbmap.smk | 8 +- rules/mappers/bowtie2.smk | 8 +- rules/multiqc/multiqc.smk | 2 + rules/naive/bbcountunique.smk | 4 +- rules/naive/sketch_compare.smk | 8 +- rules/preproc/host_removal.smk | 8 +- rules/preproc/preprocessing_summary.smk | 2 + rules/preproc/read_quality.smk | 6 +- rules/publications.py | 1 + rules/taxonomic_profiling/kaiju.smk | 16 +- rules/taxonomic_profiling/kraken2.smk | 54 +++- rules/taxonomic_profiling/metaphlan2.smk | 12 +- scripts/amrplusplus/LICENSE | 21 ++ scripts/amrplusplus/amr_long_to_wide.py | 67 +++++ scripts/amrplusplus/rarefaction | Bin 0 -> 187912 bytes scripts/amrplusplus/resistome | Bin 0 -> 159688 bytes 44 files changed, 1123 insertions(+), 77 deletions(-) create mode 100644 cluster_configs/ctmr_gandalf/config.yaml create mode 100644 cluster_configs/ctmr_gandalf/ctmr_gandalf.yaml create mode 100755 cluster_configs/ctmr_gandalf/slurm-jobscript.sh create mode 100755 cluster_configs/ctmr_gandalf/slurm-status.py create mode 100755 cluster_configs/ctmr_gandalf/slurm-submit.py create mode 100644 envs/Singularity.amrplusplus create mode 100644 envs/Singularity.assembly create mode 100644 envs/Singularity.biobakery create mode 100644 envs/Singularity.stag-mwc create mode 100644 envs/amrplusplus.yaml create mode 100644 rules/antibiotic_resistance/amrplusplus.smk create mode 100644 scripts/amrplusplus/LICENSE create mode 100755 scripts/amrplusplus/amr_long_to_wide.py create mode 100755 scripts/amrplusplus/rarefaction create mode 100755 scripts/amrplusplus/resistome diff --git a/.circleci/config.yml b/.circleci/config.yml index 8f1da02..c1ec32e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -71,7 +71,8 @@ jobs: sed -i 's/kraken2: False/kraken2: True/' config.yaml sed -i 's/metaphlan2: False/metaphlan2: True/' config.yaml sed -i 's/humann2: False/humann2: True/' config.yaml - sed -i 's/antibiotic_resistance: False/antibiotic_resistance: True/' config.yaml + sed -i 's/groot: False/groot: True/' config.yaml + sed -i 's/amrplusplus: False/amrplusplus: True/' config.yaml sed -i 's/assembly: False/assembly: True/' config.yaml sed -i 's/binning: False/binning: True/' config.yaml sed -i 's|db_path: \"\"|db_path: \"db/hg19\"|' config.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index 0674e73..bef22fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,36 @@ files), and the patch version is typically incremented for any set of changes committed to the master branch that does not trigger any of the aforementioned situations. +## [0.4.1] Unreleased +### Added +- Created Singularity images for all conda environments. Run with + `--use-singularity` (do not combine with `--use-conda`). +- New cluster profile "pseudo-rules" for anonymous rules for mappers: `bbmap` + and `bowtie2` can now accept threads from `n` in the cluster profile. They + still use the time allocation for the `__default__` rule, however. +- Added possibility to use `extra:` to define additional arguments passed on to + Slurm submissions. Useful to request e.g. fat nodes with `extra: "-C fat"` +- Added custom reimplementation of AMRPlusPlus v2.0 which can be executed with + either `--use-singularity` or `--use-conda`. + +### Fixed +- The host removal module now correctly identifies setting `host_removal: False` + in the config file. Thank you chrsb! + +### Changed +- Do not combine `--use-singularity` with `--use-conda` anymore. The new + Singularity images already contain all dependencies. +- All rules now define the number of threads from cluster_config if defined. + Old defaults are still used for local execution. +- The shebang of `area_plot.py` has been changed to work in more environments. +- Implemented workaround for error caused by automatic report generation when + using Singularity. +- Disabled taxonomic area plot for Kaiju outputs due to issues processing the + output files. + +### Removed + + ## [0.4.0] 2020-02-18 ### Added - Added resource limiter for HUMAnN2 due to its intense use of huge temporary diff --git a/README.md b/README.md index e7c348c..7160fed 100644 --- a/README.md +++ b/README.md @@ -20,8 +20,11 @@ Go to https://stag-mwc.readthedocs.org for the full documentation. [Snakemake](https://snakemake.readthedocs.io) are required to be able to use StaG-mwc. Most people would probably want to install [Miniconda](https://conda.io/miniconda.html) and install Snakemake into their -base environment. Conda will automatically install the required versions of -all tools required to run StaG-mwc. +base environment. When running StaG with the `--use-conda` or +`--use-singularity` flags, all dependencies are managed automatically. If +using conda it will automatically install the required versions of all tools +required to run StaG-mwc. There is no need to combine the flags: the +Singularity images already contain all required dependencies. ### Step 1: Clone workflow To use StaG-mwc, you need a local copy of the workflow repository. Start by @@ -58,11 +61,16 @@ Make sure you edit the Slurm project account in documentation](https://snakemake.readthedocs.io) for further details on how to run Snakemake workflows on other types of cluster resources. +Note that in all examples above, `--use-conda` and essentially be replaced +with `--use-singularity` to run in Singularity containers instead of using a +locally installed conda. Read more about it under the Running section in the +docs. ## Testing A very basic continuous integration test is currently in place. It merely validates the syntax by trying to let Snakemake build the dependency graph if -all outputs are activated. +all outputs are activated. Suggestions for how to improve the automated +testing of StaG-mwc are very welcome! ## Contributing diff --git a/Snakefile b/Snakefile index fbedfee..a0590f5 100644 --- a/Snakefile +++ b/Snakefile @@ -16,8 +16,7 @@ min_version("5.5.4") from rules.publications import publications -stag_version = "0.4.0" -singularity: "docker://continuumio/miniconda3:4.7.10" +stag_version = "0.4.1" onstart: print("\n".join([ @@ -76,6 +75,7 @@ include: "rules/functional_profiling/humann2.smk" # Antibiotic resistance ############################# include: "rules/antibiotic_resistance/groot.smk" +include: "rules/antibiotic_resistance/amrplusplus.smk" ############################# # Mappers @@ -153,12 +153,10 @@ onsuccess: Path("citations.rst").unlink() Path("citations.rst").symlink_to(citation_filename) - snakemake_call = " ".join(argv) - shell("{snakemake_call} --unlock".format(snakemake_call=snakemake_call)) + shell("{snakemake_call} --unlock".format(snakemake_call=argv[0])) shell("{snakemake_call} --report {report}-{datetime}.html".format( - snakemake_call=snakemake_call, + snakemake_call=argv[0], report=config["report"], datetime=report_datetime, ) ) - diff --git a/cluster_configs/ctmr_gandalf/config.yaml b/cluster_configs/ctmr_gandalf/config.yaml new file mode 100644 index 0000000..7f08cd1 --- /dev/null +++ b/cluster_configs/ctmr_gandalf/config.yaml @@ -0,0 +1,8 @@ +jobscript: "cluster_configs/ctmr_gandalf/slurm-jobscript.sh" +cluster: "cluster_configs/ctmr_gandalf/slurm-submit.py --time {cluster.time} --error {cluster.stderr} --output {cluster.stdout} --job-name '{cluster.jobname}' {cluster.extra}" +cluster-status: "cluster_configs/ctmr_gandalf/slurm-status.py" +cluster-config: "cluster_configs/ctmr_gandalf/ctmr_gandalf.yaml" +max-jobs-per-second: 10 +max-status-checks-per-second: 10 +local-cores: 1 +jobs: 999 diff --git a/cluster_configs/ctmr_gandalf/ctmr_gandalf.yaml b/cluster_configs/ctmr_gandalf/ctmr_gandalf.yaml new file mode 100644 index 0000000..2c540bc --- /dev/null +++ b/cluster_configs/ctmr_gandalf/ctmr_gandalf.yaml @@ -0,0 +1,90 @@ +# Cluster config file for StaG-mwc for use on CTMR UCP +__default__: + account: "bio" + partition: "ctmr" + extra: "" + time: "03:00:00" + n: 2 + stderr: "slurm_logs/slurm-{rule}-{wildcards}.stderr" + stdout: "slurm_logs/slurm-{rule}-{wildcards}.stdout" + jobname: "[{rule}]: {wildcards}" + + +############################# +# Pre-processing +############################# +fastp: + n: 8 + time: "01:00:00" +remove_host: + n: 8 + time: "01:00:00" +bbcountunique: + n: 4 + time: "00:45:00" + +############################# +# Naive comparisons +############################# +sketch: + n: 8 + time: "00:20:00" + +############################# +# Taxonomic profiling +############################# +kaiju: + n: 10 + time: "02:00:00" +kraken2: + n: 10 + time: "02:00:00" +metaphlan2: + n: 8 + time: "01:30:00" +bracken: + n: 2 + time: "01:00:00" + +############################# +# Functional profiling +############################# +humann2: + n: 12 + time: "12:00:00" + +############################# +# Antibiotic resistance +############################# +groot_align: + n: 8 + time: "01:00:00" +align_to_amr: + n: 10 + time: "04:00:00" + +############################# +# Mappers +############################# +bbmap: + n: 10 + time: "02:00:00" +bowtie2: + n: 10 + time: "02:00:00" + +############################# +# Assembly +############################# +assembly: + n: 20 + time: "05:00:00" +assembly: + n: 20 + time: "05:00:00" +consolidate_bins: + n: 20 + time: "05:00:00" +blobology: + n: 20 + time: "05:00:00" diff --git a/cluster_configs/ctmr_gandalf/slurm-jobscript.sh b/cluster_configs/ctmr_gandalf/slurm-jobscript.sh new file mode 100755 index 0000000..391741e --- /dev/null +++ b/cluster_configs/ctmr_gandalf/slurm-jobscript.sh @@ -0,0 +1,3 @@ +#!/bin/bash +# properties = {properties} +{exec_job} diff --git a/cluster_configs/ctmr_gandalf/slurm-status.py b/cluster_configs/ctmr_gandalf/slurm-status.py new file mode 100755 index 0000000..ad98697 --- /dev/null +++ b/cluster_configs/ctmr_gandalf/slurm-status.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +import re +import subprocess as sp +import shlex +import sys +import time +import logging +logger = logging.getLogger("__name__") + +STATUS_ATTEMPTS = 20 + +jobid = sys.argv[1] + +for i in range(STATUS_ATTEMPTS): + try: + sacct_res = sp.check_output(shlex.split("sacct -P -b -j {} -n".format(jobid))) + res = {x.split("|")[0]: x.split("|")[1] for x in sacct_res.decode().strip().split("\n")} + break + except sp.CalledProcessError as e: + logger.error("sacct process error") + logger.error(e) + except IndexError as e: + pass + # Try getting job with scontrol instead in case sacct is misconfigured + try: + sctrl_res = sp.check_output(shlex.split("scontrol -o show job {}".format(jobid))) + m = re.search("JobState=(\w+)", sctrl_res.decode()) + res = {jobid: m.group(1)} + break + except sp.CalledProcessError as e: + logger.error("scontrol process error") + logger.error(e) + if i >= STATUS_ATTEMPTS - 1: + print("failed") + exit(0) + else: + time.sleep(1) + +status = res[jobid] + +if (status.startswith("BOOT_FAIL")): + print("failed") +elif (status.startswith("CANCELLED")): + print("failed") +elif (status.startswith("COMPLETED")): + print("success") +elif (status.startswith("DEADLINE")): + print("failed") +elif (status.startswith("FAILED")): + print("failed") +elif (status.startswith("NODE_FAIL")): + print("failed") +elif (status.startswith("PREEMPTED")): + print("failed") +elif (status.startswith("TIMEOUT")): + print("failed") +# Unclear whether SUSPENDED should be treated as running or failed +elif (status.startswith("SUSPENDED")): + print("failed") +else: + print("running") diff --git a/cluster_configs/ctmr_gandalf/slurm-submit.py b/cluster_configs/ctmr_gandalf/slurm-submit.py new file mode 100755 index 0000000..3050c19 --- /dev/null +++ b/cluster_configs/ctmr_gandalf/slurm-submit.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python3 +import sys +import re +import argparse +import subprocess +from pathlib import Path + +from snakemake.utils import read_job_properties + +parser = argparse.ArgumentParser(add_help=False) +parser.add_argument( + "--help", help="Display help message.", action="store_true") +parser.add_argument( + "positional", action="append", + nargs="?", metavar="POS", + help="additional arguments not in slurm parser group to pass to sbatch") + +# A subset of SLURM-specific arguments +slurm_parser = parser.add_argument_group("slurm-specific arguments") +slurm_parser.add_argument( + "-a", "--array", help="job array index values") +slurm_parser.add_argument( + "-A", "--account", help="charge job to specified account") +slurm_parser.add_argument( + "--begin", help="defer job until HH:MM MM/DD/YY") +slurm_parser.add_argument( + "-c", "--cpus-per-task", help="number of cpus required per task") +slurm_parser.add_argument( + "-d", "--dependency", + help="defer job until condition on jobid is satisfied") +slurm_parser.add_argument( + "-D", "--workdir", help="set working directory for batch script") +slurm_parser.add_argument( + "-e", "--error", help="file for batch script's standard error") +slurm_parser.add_argument( + "-J", "--job-name", help="name of job") +slurm_parser.add_argument( + "--mail-type", help="notify on state change: BEGIN, END, FAIL or ALL") +slurm_parser.add_argument( + "--mail-user", help="who to send email notification for job state changes") +slurm_parser.add_argument( + "-n", "--ntasks", help="number of tasks to run") +slurm_parser.add_argument( + "-N", "--nodes", help="number of nodes on which to run (N = min[-max])") +slurm_parser.add_argument( + "-o", "--output", help="file for batch script's standard output") +slurm_parser.add_argument( + "-p", "--partition", help="partition requested") +slurm_parser.add_argument( + "-q", "--qos", help="quality of service") +slurm_parser.add_argument( + "-Q", "--quiet", help="quiet mode (suppress informational messages)") +slurm_parser.add_argument( + "-t", "--time", help="time limit") +slurm_parser.add_argument( + "--wrap", help="wrap command string in a sh script and submit") +slurm_parser.add_argument( + "-C", "--constraint", help="specify a list of constraints") +slurm_parser.add_argument( + "--mem", help="minimum amount of real memory") + +args = parser.parse_args() + +if args.help: + parser.print_help() + sys.exit(0) + +jobscript = sys.argv[-1] +job_properties = read_job_properties(jobscript) + +extras = "" +if args.positional: + for m in args.positional: + if m is not None: + extras = extras + " " + m + +arg_dict = dict(args.__dict__) + + +# Process resources +if "resources" in job_properties: + resources = job_properties["resources"] + if arg_dict["time"] is None: + if "runtime" in resources: + arg_dict["time"] = resources["runtime"] + elif "walltime" in resources: + arg_dict["time"] = resources["walltime"] + if "mem" in resources and arg_dict["mem"] is None: + arg_dict["mem"] = resources["mem"] + +# Threads +if "threads" in job_properties: + arg_dict["ntasks"] = job_properties["threads"] + +opt_keys = {"array", "account", "begin", "cpus_per_task", + "depedency", "workdir", "error", "job_name", "mail_type", + "mail_user", "ntasks", "nodes", "output", "partition", + "quiet", "time", "wrap", "constraint", "mem"} + +# Set default partition +if arg_dict["partition"] is None: + # partitions and SLURM - If not specified, the default behavior is to + # allow the slurm controller to select the default partition as + # designated by the system administrator. + opt_keys.remove("partition") + +# NOT APPLICABLE FOR CTMR UCP +#### Set default account +###if arg_dict["account"] is None: +### raise Exception("Cannot submit Slurm jobs without account!") + +# Ensure output folder for Slurm log files exist +# This is a bit hacky; it will try to create the folder +# for every Slurm submission... +if "output" in arg_dict: + stdout_folder = Path(arg_dict["output"]).parent + stdout_folder.mkdir(exist_ok=True, parents=True) +if "error" in arg_dict: + stdout_folder = Path(arg_dict["error"]).parent + stdout_folder.mkdir(exist_ok=True, parents=True) + +opts = "" +for k, v in arg_dict.items(): + if k not in opt_keys: + continue + if v is not None: + opts += " --{} \"{}\" ".format(k.replace("_", "-"), v) + +if arg_dict["wrap"] is not None: + cmd = "sbatch {opts}".format(opts=opts) +else: + cmd = "sbatch {opts} {extras}".format(opts=opts, extras=extras) + +try: + res = subprocess.run(cmd, check=True, shell=True, stdout=subprocess.PIPE) +except subprocess.CalledProcessError as e: + raise e + +# Get jobid +res = res.stdout.decode() +try: + m = re.search("Submitted batch job (\d+)", res) + jobid = m.group(1) + print(jobid) +except Exception as e: + print(e) + raise diff --git a/cluster_configs/rackham/config.yaml b/cluster_configs/rackham/config.yaml index 3e0d6ed..239f492 100644 --- a/cluster_configs/rackham/config.yaml +++ b/cluster_configs/rackham/config.yaml @@ -1,5 +1,5 @@ jobscript: "cluster_configs/rackham/slurm-jobscript.sh" -cluster: "cluster_configs/rackham/slurm-submit.py --account {cluster.account} --partition {cluster.partition} --ntasks {cluster.n} --time {cluster.time} --error {cluster.stderr} --output {cluster.stdout} --job-name '{cluster.jobname}'" +cluster: "cluster_configs/rackham/slurm-submit.py --account {cluster.account} --partition {cluster.partition} --ntasks {cluster.n} --time {cluster.time} --error {cluster.stderr} --output {cluster.stdout} --job-name '{cluster.jobname}' {cluster.extra}" cluster-status: "cluster_configs/rackham/slurm-status.py" cluster-config: "cluster_configs/rackham/rackham.yaml" max-jobs-per-second: 10 diff --git a/cluster_configs/rackham/rackham.yaml b/cluster_configs/rackham/rackham.yaml index 45298e4..a836de3 100644 --- a/cluster_configs/rackham/rackham.yaml +++ b/cluster_configs/rackham/rackham.yaml @@ -30,16 +30,6 @@ sketch: n: 2 time: "00:20:00" -############################# -# Mappers -############################# -bbmap: - n: 8 - time: "02:00:00" -bowtie2: - n: 8 - time: "02:00:00" - ############################# # Taxonomic profiling ############################# @@ -52,6 +42,9 @@ kraken2: metaphlan2: n: 8 time: "01:30:00" +bracken: + n: 2 + time: "01:00:00" ############################# # Functional profiling @@ -66,10 +59,32 @@ humann2: groot_align: n: 6 time: "01:00:00" +align_to_amr: + n: 10 + time: "04:00:00" + +############################# +# Mappers +############################# +bbmap: + n: 8 + time: "02:00:00" +bowtie2: + n: 8 + time: "02:00:00" ############################# # Assembly ############################# -megahit: +assembly: + n: 20 + time: "05:00:00" +assembly: + n: 20 + time: "05:00:00" +consolidate_bins: + n: 20 + time: "05:00:00" +blobology: n: 20 time: "05:00:00" diff --git a/config.yaml b/config.yaml index 42a0d56..5a04898 100644 --- a/config.yaml +++ b/config.yaml @@ -35,7 +35,9 @@ taxonomic_profile: metaphlan2: False functional_profile: humann2: False -antibiotic_resistance: False +antibiotic_resistance: + groot: False + amrplusplus: True mappers: bbmap: False bowtie2: False @@ -124,6 +126,17 @@ groot: covcutoff: 0.97 # Coverage cutoff for groot report lowcov: False # Report ARGs with no 5' or 3' coverage. Overrides covcutoff. +amrplusplus: + megares: + fasta: "" # Leave as "" to run with megares_modified_database_v2.00.fasta or specify database path + annotation: "" # Leave as "" to run with megares_modified_annotations_v2.00.csv or specify annotations path + rarefaction: + min: "5" # Starting rarefaction level + max: "100" # Ending rarefaction level + skip: "5" # Number of levels to skip + samples: "1" # Number of iterations to sample at + resistome: + threshold: "80" # Resistome threshold ######################### # Mappers @@ -162,4 +175,3 @@ metawrap: universal: "--universal" # Use universal marker genes minimum_completion: 70 maximum_contamination: 10 - diff --git a/docs/source/conf.py b/docs/source/conf.py index f32c1f8..21e0f43 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -56,9 +56,9 @@ # built documents. # # The short X.Y version. -version = '0.4.0' +version = '0.4.1' # The full version, including alpha/beta/rc tags. -release = '0.4.0-beta1' +release = '0.4.1' # reStructuredText prolog contains a string of reStructuredText that will be # included at the beginning of every source file that is read. diff --git a/docs/source/faq.rst b/docs/source/faq.rst index d080afe..f944aec 100644 --- a/docs/source/faq.rst +++ b/docs/source/faq.rst @@ -13,8 +13,8 @@ both the read QC step and the host removal steps if you need to. In order to do so, we must "trick" Snakemake into thinking that those rules have already been performed. The rules for read QC and host removal are configured with bypasses so that if the user sets ``host_removal: False`` or ``qc_reads: False``, those -steps will be bypassed by creating symlinks to directly to the input files in -the respective output directories. +steps will be bypassed by creating symlinks directly to the input files in the +respective output directories. Skip host removal diff --git a/docs/source/index.rst b/docs/source/index.rst index 5fc0ad7..cc8e420 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -8,7 +8,7 @@ The StaG metagenomic workflow collaboration (mwc) is a Snakemake implementation of a general metagenomic analysis workflow. It started out as a joint project between The Center for Translational Microbiome Research (`CTMR`_) at Karolinska Institutet in Stockholm and Fredrik Bäckhed's `research group`_ at -Sahlgrenska in Gothenburg, but has since evolved into the default workflow for +Sahlgrenska in Gothenburg, and has since evolved into the default workflow for metagenomics analyses used at CTMR. .. _CTMR: https://ki.se/en/research/centre-for-translational-microbiome-research-ctmr diff --git a/docs/source/installation.rst b/docs/source/installation.rst index c01624c..6bd4325 100644 --- a/docs/source/installation.rst +++ b/docs/source/installation.rst @@ -55,13 +55,13 @@ This will clone the repo into a folder called ``stag-mwc`` inside your current working directory. You will manage all workflow-related business from inside this folder (i.e. configuring and running the workflow). +The intended way of working with |full_name| is that you download/clone a +complete copy of the repository for each analysis you intend to make. That way, +the local copy you have will remain after the analysis has been run, so you can +go back and see exactly what was run, and how. This forms the basis of how +Snakemake enables traceability and reproducibility. Congratulations *************** You have now installed |full_name|. -The intended way of working with |full_name|, is that you download/clone a -complete copy of the repository for each analysis you intend to make. That way, -the local copy you have will remain after the analysis has been run, so you can -go back and see exactly what was run, and how. This forms the basis of how -Snakemake enables traceability and reproducibility. diff --git a/docs/source/modules.rst b/docs/source/modules.rst index ea1a7cc..30ed873 100644 --- a/docs/source/modules.rst +++ b/docs/source/modules.rst @@ -13,13 +13,15 @@ .. _SAF format: http://bioinf.wehi.edu.au/featureCounts/ .. _MEGAHIT: https://github.com/voutcn/megahit .. _MultiQC: https://multiqc.info/ +.. _amrplusplus: https://megares.meglab.org/amrplusplus/latest/html/what_AMR++_produces.html +.. _megares: https://megares.meglab.org/ Modules ======= |full_name| is a workflow framework that connects several other tools. The basic assumption is that all analyses start with a quality control of the -sequencing reads (using `FastQC`_), followed by host sequence removal (using -`BBMap`_). This section of the documentation aims to describe useful details +sequencing reads (using `FastP`_), followed by host sequence removal (using +`Kraken2`_). This section of the documentation aims to describe useful details about the separate tools that are used in |full_name|. The following subsections describe the function of each module included in @@ -252,6 +254,35 @@ The read lengths input to `groot`_ must conform to the settings used during `groot`_ database construction. The length window can be configured in the config file. +AMRPlusPlus_v2 +------- +:Tool: `amrplusplus`_ +:Output folder: ``amrplusplus`` + +`amrplusplus`_ will align reads to `megares`_ antibiotic resistance gene database to +produce antibiotic resistance gene profiles. Output is structured as:: + + ├ AlignToAMR + │ └ .amr.alignment.sam + ├ RunResistome + │ ├ .class.tsv + │ ├ .gene.tsv + │ ├ .group.tsv + │ └ .mech.tsv + ├ ResistomeResults + │ └ AMR_analytic_matrix.csv + ├ RunRarefaction + │ ├ .class.tsv + │ ├ .gene.tsv + │ ├ .group.tsv + │ └ .mech.tsv + +``AMR_analytic_matrix.csv`` contains aggregated results of gene counts for all samples +aligned against `megares`_, based on the threshold set in ``config.yaml``. Pasting a gene name +or accession number into the database will provide detailed information and links to +published papers. + +`amrplusplus`_ can be executed with either ``--use-singularity`` or ``--use-conda`` settings. Mappers ******* diff --git a/docs/source/running.rst b/docs/source/running.rst index 47b92ad..14e1aa5 100644 --- a/docs/source/running.rst +++ b/docs/source/running.rst @@ -56,10 +56,11 @@ is:: snakemake --use-conda --cores N -where ``N`` is the maximum number of cores you want to allow for the workflow. -Snakemake will automatically reduce the number of cores available to individual -steps to this limit. Another variant of ``--cores`` is called ``--jobs``, they -are equivalent. +where ``N`` is the maximum number of cores you want to allow for the +workflow. Snakemake will automatically reduce the number of cores available +to individual steps to this limit. Another variant of ``--cores`` is called +``--jobs``, which you might encounter occassionally. The two commands are +equivalent. .. note:: @@ -81,6 +82,26 @@ instruct snakemake to keep going even if a job should fail, e.g. maybe the taxonomic profiling step will fail for a sample if the sample contains no assignable reads after quality filtering (extreme example). +If you are having trouble running |full_name| with conda, try with +Singularity. There are pre-built Singularity images that are ready to use +with |full_name|. In order to prevent exhausting the project's quota on +Singularity Hub please use ``--singularity-prefix`` to specify a folder where +Snakemake can download and re-use the downloaded Singularity images. The +command to run |full_name| with Singularity instead of conda is:: + + snakemake --use-singularity --singularity-prefix /path/to/prefix/folder --dryrun + +There are some additional details that need to be considered when using +Singularity instead of conda, most notably that you will have to specify bind +paths (specifying-bind-paths_) so that your reference databases are +accessible from within the containers when running |full_name|. It might look +something like this:: + + snakemake --use-singularity --singularity-prefix /path/to/prefix/folder --singularity-args "-B /home/username/databases" + +The above example assumes you have entered paths to your databases in +``config.yaml`` with a base path like the one shown in the above command +(e.g. ``/home/username/databases/kraken2/kraken2_human/``). Running on cluster resources **************************** @@ -93,10 +114,35 @@ Slurm project account), as well as the number of CPUs, time, and memory requirements for each individual step. Snakemake uses this information when submitting jobs to the cluster scheduler. +When running on a cluster it will likely work best if you run StaG using +Singularity. The workflow comes preconfigured to download and use containers +from Singularity hub. To use Singularity launch Snakemake with the +``--use-singularity`` argument. + +.. _specifying-bind-paths: https://sylabs.io/guides/3.5/user-guide/bind_paths_and_mounts.html#specifying-bind-paths + +.. note:: + + Do not combine ``--use-conda`` with ``--use-singularity``. + + It is important that you do not download the Singularity images from + Singularity hub too often due to quota limitations. To prevent |full_name| + from downloading the image again between several projects you can use the + ``--singularity-prefix`` to specify a directory where Snakemake can store + the downloaded images for reuse between projects. + + Paths to databases need to be located so that they are accessible from + inside the Singularity containers. It's easiest if they are all available + from the same folder, so you can bind the main database folder into the + Singularity container with e.g. ``--singularity-args "-B /db"``. Note that + database paths need to specified in the config file so that the paths are + correct from inside the Singularity container. Read more about specifying + bind paths in the official Singularity docs: specifying-bind-paths_. + To run |full_name| on e.g. UPPMAX's Rackham, run the following command from inside the workflow repository directory:: - snakemake --use-conda --profile cluster_configs/rackham + snakemake --use-singularity --singularity-prefix /path/to/prefix/folder --singularity-args "-B /proj/uppstore2017086/db" --profile cluster_configs/rackham This will make Snakemake submit each workflow step as a separate cluster job using the CPU and time requirements specified in ``rackham.yaml`` inside the @@ -119,12 +165,6 @@ files before restarting pipeline using:: (base)$ rm -rfv .snakemake/metadata -.. note:: - - When running on a cluster it can speed up node initialization if you run - using Singularity containers and conda combined. This is done by running - snakemake with both the `--use-conda` and `--use-singularity` arguments. - Execution report **************** diff --git a/envs/Singularity.amrplusplus b/envs/Singularity.amrplusplus new file mode 100644 index 0000000..0b7a457 --- /dev/null +++ b/envs/Singularity.amrplusplus @@ -0,0 +1,55 @@ +Bootstrap: docker +From: debian:jessie-slim + +#Includes trimmomatic, samtools, bwa, bedtools, vcftools, htslib, kraken2, SNPfinder, freebayes, bbmap + +%environment + export LC_ALL=C + +%post + apt update \ + && apt install -y --no-install-recommends \ + build-essential ca-certificates sudo tcsh\ + git make automake autoconf openjdk-7-jre wget gzip unzip sed\ + zlib1g-dev curl libbz2-dev locales libncurses5-dev liblzma-dev libcurl4-openssl-dev software-properties-common apt-transport-https\ + python3-pip python3-docopt python3-pytest python-dev python3-dev\ + libcurl4-openssl-dev libssl-dev zlib1g-dev fonts-texgyre \ + gcc g++ gfortran libblas-dev liblapack-dev dos2unix libstdc++6\ + r-base-core r-recommended hmmer\ + && rm -rf /var/lib/apt/lists/* + + + wget -c https://repo.continuum.io/archive/Anaconda3-2020.02-Linux-x86_64.sh + sh Anaconda3-2020.02-Linux-x86_64.sh -bfp /usr/local + + # add bioconda channels + conda config --add channels defaults + conda config --add channels conda-forge + conda config --add channels bioconda + + # install bulk of bioinformatic tools using conda + conda create -n AmrPlusPlus_env python=3 trimmomatic bwa samtools bedtools freebayes bbmap vcftools htslib kraken2 + + . /usr/local/bin/activate AmrPlusPlus_env + + #ln -s /usr/local/envs/AmrPlusPlus_env/bin/* /usr/local/bin/ + + #Still experimenting with how to change $PATH location. + echo 'export PATH=$PATH:/usr/local/envs/AmrPlusPlus_env/bin/' >> $SINGULARITY_ENVIRONMENT + + # SNPfinder + cd /usr/local + git clone https://github.com/cdeanj/snpfinder.git + cd snpfinder + make + cp snpfinder /usr/local/bin + cd / + + # Make sure all the tools have the right permissions to use the tools + chmod -R 777 /usr/local/ + +%test + +%labels + Author meglab-metagenomics + version amrplusplus_v2 diff --git a/envs/Singularity.assembly b/envs/Singularity.assembly new file mode 100644 index 0000000..7d29927 --- /dev/null +++ b/envs/Singularity.assembly @@ -0,0 +1,30 @@ +Bootstrap: docker +From: continuumio/miniconda3 + +%help + Singularity image containing the conda environment defined in + assembly.yaml. + + To build, run: + sudo singularity build stag-mwc-assembly.simg Singularity.assembly + +%files + assembly.yaml + +%labels + AUTHOR boulund + VERSION 1.0 + CONDA_ENV /opt/conda/envs/assembly + +%environment + PATH=/opt/conda/envs/stag-mwc-assembly/bin:/opt/conda/bin:$PATH + export PATH + +%post + # Install stag-mwc-assembly conda environment + /opt/conda/bin/conda env create -f assembly.yaml --force + /opt/conda/bin/conda clean --yes --all + +%runscript + exec echo "$@" + diff --git a/envs/Singularity.biobakery b/envs/Singularity.biobakery new file mode 100644 index 0000000..df16f22 --- /dev/null +++ b/envs/Singularity.biobakery @@ -0,0 +1,30 @@ +Bootstrap: docker +From: continuumio/miniconda3 + +%help + Singularity image containing the conda environment defined in + humann2.yaml. + + To build, run: + sudo singularity build stag-mwc-biobakery.simg Singularity.biobakery + +%files + humann2.yaml + +%labels + AUTHOR boulund + VERSION 1.0 + CONDA_ENV /opt/conda/envs/stag-mwc-biobakery + +%environment + PATH=/opt/conda/envs/stag-mwc-biobakery/bin:/opt/conda/bin:$PATH + export PATH + +%post + # Install stag-mwc-biobakery conda environment + /opt/conda/bin/conda env create -f humann2.yaml --force + /opt/conda/bin/conda clean --yes --all + +%runscript + exec echo "$@" + diff --git a/envs/Singularity.stag-mwc b/envs/Singularity.stag-mwc new file mode 100644 index 0000000..a86cb05 --- /dev/null +++ b/envs/Singularity.stag-mwc @@ -0,0 +1,50 @@ +Bootstrap: docker +From: continuumio/miniconda3 + +%help + Singularity image containing the conda environment defined in + stag-mwc.yaml. + + To build, run: + sudo singularity build stag-mwc.simg Singularity.stag-mwc + + Note that the Kraken2 package installed through conda is ignored in favor + of one built and installed from source, due to issues with the conda + package giving segfaults. + +%files + stag-mwc.yaml + +%labels + AUTHOR boulund + VERSION 1.0 + CONDA_ENV /opt/conda/envs/stag-mwc-main + KRAKEN2_BUILD SOURCE_v2.0.8-beta + +%environment + PATH=/opt/kraken2-2.0.8-beta:/opt/conda/envs/stag-mwc-main/bin:/opt/conda/bin:$PATH + export PATH + +%post + # Install stag-mwc-main conda environment + /opt/conda/bin/conda env create -f stag-mwc.yaml --force + /opt/conda/bin/conda clean --yes --all + + # Install Kraken2 from source; the conda version segafaults. + apt-get update && apt-get -y install \ + wget \ + zlib1g-dev \ + make \ + g++ + wget \ + https://github.com/DerrickWood/kraken2/archive/v2.0.8-beta.tar.gz \ + --output-document kraken2-2.0.8-beta.tar.gz + tar -xvf kraken2-2.0.8-beta.tar.gz + mkdir -pv /opt/kraken2-2.0.8-beta + cd kraken2-2.0.8-beta + ./install_kraken2.sh /opt/kraken2-2.0.8-beta + rm -rfv kraken2-2.0.8-beta* + +%runscript + exec echo "$@" + diff --git a/envs/amrplusplus.yaml b/envs/amrplusplus.yaml new file mode 100644 index 0000000..7375e3e --- /dev/null +++ b/envs/amrplusplus.yaml @@ -0,0 +1,8 @@ +name: amrplusplus +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - samtools=1.10 + - bwa=0.7.17 diff --git a/envs/metaphlan2.yaml b/envs/metaphlan2.yaml index 1c3fe98..2315e06 100644 --- a/envs/metaphlan2.yaml +++ b/envs/metaphlan2.yaml @@ -1,4 +1,4 @@ -name: stag-mwc-biobakery +name: stag-mwc-metaphlan2 channels: - bioconda - conda-forge diff --git a/rules/antibiotic_resistance/amrplusplus.smk b/rules/antibiotic_resistance/amrplusplus.smk new file mode 100644 index 0000000..7a1be6a --- /dev/null +++ b/rules/antibiotic_resistance/amrplusplus.smk @@ -0,0 +1,232 @@ +# vim: syntax=python expandtab tabstop=4 +# AMRPlusPlus v2.0 snakemake integration +# Aron Arzoomand 2020-08-12 + +from pathlib import Path, PurePath +from snakemake.exceptions import WorkflowError + + + +localrules: + get_local_megares, + build_amr_index, + + +amrplusplus_config=config["amrplusplus"] +if config["antibiotic_resistance"]["amrplusplus"]: + if not Path(amrplusplus_config["megares"]["fasta"]).exists(): + err_message = "No database exists at: '{}' !\n".format(amrplusplus_config["megares"]["fasta"]) + err_message += "Specify the path in the amrplusplus section of config.yaml.\n" + err_message += "If you want to run with the default megares_modified_database_v2.00.fasta, leave it as \"\"" + raise WorkflowError(err_message) + if not Path(amrplusplus_config["megares"]["annotation"]).exists(): + err_message = "No annotations exists at: '{}' !\n".format(amrplusplus_config["megares"]["annotation"]) + err_message += "Specify the path in the amrplusplus section of config.yaml.\n" + err_message += "If you want to run with the default megares_modified_annotations_v2.00.csv, leave it as \"\"" + raise WorkflowError(err_message) + + amrplusplus_outputs = f"{OUTDIR}/amrplusplus/ResistomeResults/AMR_analytics_matrix.csv" + all_outputs.append(amrplusplus_outputs) + + citations.add(publications["AMRPlusPlus2"]) + + +MEGARES_FASTA = f"{config['dbdir']}/amrplusplus/megares_modified_database_v2.00.fasta" +MEGARES_ANNOT = f"{config['dbdir']}/amrplusplus/megares_modified_annotations_v2.00.csv" + + +rule get_local_megares: + """Get the Megares_2.0 database and annotations""" + output: + megares_db_local=f"{MEGARES_FASTA}", + megares_annot_local=f"{MEGARES_ANNOT}", + log: + stdout=f"{LOGDIR}/amrplusplus/get_local_megares.stdout.log", + stderr=f"{LOGDIR}/amrplusplus/get_local_megares.stderr.log", + shadow: + "shallow" + singularity: + "shub://meglab-metagenomics/amrplusplus_v2" + params: + megares_db=amrplusplus_config["megares"]["fasta"] or f"{MEGARES_FASTA}" + shell: + """ + wget -O {output.megares_db_local} https://raw.githubusercontent.com/meglab-metagenomics/amrplusplus_v2/master/data/amr/megares_modified_database_v2.00.fasta + wget -O {output.megares_annot_local} https://raw.githubusercontent.com/meglab-metagenomics/amrplusplus_v2/master/data/amr/megares_modified_annotations_v2.00.csv + """ + +rule build_amr_index: + """Build megares index""" + input: + megares_db=amrplusplus_config["megares"]["fasta"] or f"{MEGARES_FASTA}" + output: + amb=f"{amrplusplus_config['megares']['fasta']}.amb" if amrplusplus_config["megares"]["fasta"] else f"{MEGARES_FASTA}.amb", + ann=f"{amrplusplus_config['megares']['fasta']}.ann" if amrplusplus_config["megares"]["fasta"] else f"{MEGARES_FASTA}.ann", + bwt=f"{amrplusplus_config['megares']['fasta']}.bwt" if amrplusplus_config["megares"]["fasta"] else f"{MEGARES_FASTA}.bwt", + pac=f"{amrplusplus_config['megares']['fasta']}.pac" if amrplusplus_config["megares"]["fasta"] else f"{MEGARES_FASTA}.pac", + sa=f"{amrplusplus_config['megares']['fasta']}.sa" if amrplusplus_config["megares"]["fasta"] else f"{MEGARES_FASTA}.sa", + log: + stdout=f"{LOGDIR}/amrplusplus/build_amr.index.stdout.log", + stderr=f"{LOGDIR}/amrplusplus/build_amr.index.stderr.log", + shadow: + "shallow" + conda: + "../../envs/amrplusplus.yaml" + singularity: + "shub://meglab-metagenomics/amrplusplus_v2" + shell: + """ + bwa index {input.megares_db} \ + 2> {log.stderr} \ + > {log.stdout} + """ + +rule align_to_amr: + """BWA to align host filtered reads to Megares_2.0 database""" + input: + R1=f"{OUTDIR}/host_removal/{{sample}}_1.fq.gz", + R2=f"{OUTDIR}/host_removal/{{sample}}_2.fq.gz", + amb=f"{amrplusplus_config['megares']['fasta']}.amb" if amrplusplus_config["megares"]["fasta"] else f"{MEGARES_FASTA}.amb", + ann=f"{amrplusplus_config['megares']['fasta']}.ann" if amrplusplus_config["megares"]["fasta"] else f"{MEGARES_FASTA}.ann", + bwt=f"{amrplusplus_config['megares']['fasta']}.bwt" if amrplusplus_config["megares"]["fasta"] else f"{MEGARES_FASTA}.bwt", + pac=f"{amrplusplus_config['megares']['fasta']}.pac" if amrplusplus_config["megares"]["fasta"] else f"{MEGARES_FASTA}.pac", + sa=f"{amrplusplus_config['megares']['fasta']}.sa" if amrplusplus_config["megares"]["fasta"] else f"{MEGARES_FASTA}.sa", + output: + alignment=f"{OUTDIR}/amrplusplus/AlignToAMR/{{sample}}.amr.alignment.sam" + log: + stdout=f"{LOGDIR}/amrplusplus/{{sample}}.align_to_amr.stdout.log", + stderr=f"{LOGDIR}/amrplusplus/{{sample}}.align_to_amr.stderr.log", + shadow: + "shallow" + conda: + "../../envs/amrplusplus.yaml" + singularity: + "shub://meglab-metagenomics/amrplusplus_v2" + threads: + cluster_config["align_to_amr"]["n"] if "align_to_amr" in cluster_config else 10 + params: + megares_db=amrplusplus_config["megares"]["fasta"] or f"{MEGARES_FASTA}" + shell: + """ + bwa mem \ + {params.megares_db} \ + {input.R1} \ + {input.R2} \ + -t {threads} \ + -R '@RG\\tID:{wildcards.sample}\\tSM:{wildcards.sample}' > {output.alignment} + """ + +rule run_resistome: + """Annotate alignments""" + input: + alignment=f"{OUTDIR}/amrplusplus/AlignToAMR/{{sample}}.amr.alignment.sam", + output: + gene=f"{OUTDIR}/amrplusplus/RunResistome/{{sample}}.gene.tsv", + group=f"{OUTDIR}/amrplusplus/RunResistome/{{sample}}.group.tsv", + mech=f"{OUTDIR}/amrplusplus/RunResistome/{{sample}}.mechanism.tsv", + klass=f"{OUTDIR}/amrplusplus/RunResistome/{{sample}}.class.tsv", + type=f"{OUTDIR}/amrplusplus/RunResistome/{{sample}}.type.tsv", + log: + stdout=f"{LOGDIR}/amrplusplus/{{sample}}.run_resistome.stdout.log", + stderr=f"{LOGDIR}/amrplusplus/{{sample}}.run_resistome.stderr.log", + shadow: + "shallow" + conda: + "../../envs/amrplusplus.yaml" + singularity: + "shub://meglab-metagenomics/amrplusplus_v2" + params: + script="scripts/amrplusplus/resistome", + threshold=amrplusplus_config["resistome"]["threshold"], + megares_db=amrplusplus_config["megares"]["fasta"] or f"{MEGARES_FASTA}", + megares_annot=amrplusplus_config["megares"]["annotation"] or f"{MEGARES_ANNOT}", + shell: + """ + {params.script} \ + -ref_fp {params.megares_db} \ + -annot_fp {params.megares_annot} \ + -sam_fp {input.alignment} \ + -gene_fp {output.gene} \ + -group_fp {output.group} \ + -mech_fp {output.mech} \ + -class_fp {output.klass} \ + -type_fp {output.type} \ + -t {params.threshold} \ + 2> {log.stderr} \ + > {log.stdout} + """ + +rule run_rarefaction: + """Running rarefaction""" + input: + alignment=f"{OUTDIR}/amrplusplus/AlignToAMR/{{sample}}.amr.alignment.sam", + output: + gene=f"{OUTDIR}/amrplusplus/RunRarefaction/{{sample}}.gene.tsv", + group=f"{OUTDIR}/amrplusplus/RunRarefaction/{{sample}}.group.tsv", + mech=f"{OUTDIR}/amrplusplus/RunRarefaction/{{sample}}.mechanism.tsv", + klass=f"{OUTDIR}/amrplusplus/RunRarefaction/{{sample}}.class.tsv", + type=f"{OUTDIR}/amrplusplus/RunRarefaction/{{sample}}.type.tsv", + log: + stdout=f"{LOGDIR}/amrplusplus/{{sample}}.run_rarefaction.stdout.log", + stderr=f"{LOGDIR}/amrplusplus/{{sample}}.run_rarefaction.stderr.log", + shadow: + "shallow" + conda: + "../../envs/amrplusplus.yaml" + singularity: + "shub://meglab-metagenomics/amrplusplus_v2" + params: + megares_db=amrplusplus_config["megares"]["fasta"] or f"{MEGARES_FASTA}", + megares_annot=amrplusplus_config["megares"]["annotation"] or f"{MEGARES_ANNOT}", + script="scripts/amrplusplus/rarefaction", + min=amrplusplus_config["rarefaction"]["min"], + max=amrplusplus_config["rarefaction"]["max"], + skip=amrplusplus_config["rarefaction"]["skip"], + samples=amrplusplus_config["rarefaction"]["samples"], + threshold=amrplusplus_config["resistome"]["threshold"], + shell: + """ + {params.script} \ + -ref_fp {params.megares_db} \ + -sam_fp {input.alignment} \ + -annot_fp {params.megares_annot} \ + -gene_fp {output.gene} \ + -group_fp {output.group} \ + -mech_fp {output.mech} \ + -class_fp {output.klass} \ + -type_fp {output.type} \ + -min {params.min} \ + -max {params.max} \ + -skip {params.skip} \ + -samples {params.samples} \ + -t {params.threshold} \ + 2> {log.stderr} \ + > {log.stdout} + """ + +rule resistome_results: + """Creating matrix of all gene hits""" + input: + gene_resistome=expand(f"{OUTDIR}/amrplusplus/RunResistome/{{sample}}.gene.tsv", sample=SAMPLES), + gene_rarefaction=expand(f"{OUTDIR}/amrplusplus/RunRarefaction/{{sample}}.gene.tsv", sample=SAMPLES), + output: + AMR_matrix=f"{OUTDIR}/amrplusplus/ResistomeResults/AMR_analytics_matrix.csv" + log: + stdout=f"{LOGDIR}/amrplusplus/resistome_results.stdout.log", + stderr=f"{LOGDIR}/amrplusplus/resistome_results.stderr.log", + shadow: + "shallow" + conda: + "../../envs/amrplusplus.yaml" + singularity: + "shub://meglab-metagenomics/amrplusplus_v2" + params: + script="scripts/amrplusplus/amr_long_to_wide.py" + shell: + """ + python3 {params.script} \ + -i {input.gene_resistome} \ + -o {output.AMR_matrix} \ + 2> {log.stderr} \ + > {log.stdout} + """ diff --git a/rules/antibiotic_resistance/groot.smk b/rules/antibiotic_resistance/groot.smk index 614f363..54c7532 100644 --- a/rules/antibiotic_resistance/groot.smk +++ b/rules/antibiotic_resistance/groot.smk @@ -10,7 +10,7 @@ localrules: groot_db_path = Path(config["groot"]["index"]) -if config["antibiotic_resistance"]: +if config["antibiotic_resistance"]["groot"]: if not Path(groot_db_path).exists(): err_message = "No groot database found at: '{}'!\n".format(groot_db_path) err_message += "Specify the DB path in the groot section of config.yaml.\n" @@ -37,6 +37,8 @@ rule create_groot_index: "shallow" conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" params: dbdir=DBDIR/"groot/", db=groot_config["db"], @@ -76,8 +78,10 @@ rule groot_align: "shallow" conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" threads: - 8 + cluster_config["groot_align"]["n"] if "groot_align" in cluster_config else 8 params: index=groot_config["index"], minlength=groot_config["minlength"], @@ -115,6 +119,8 @@ rule groot_report: "shallow" conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" threads: 1 params: diff --git a/rules/assembly/metawrap.smk b/rules/assembly/metawrap.smk index b9ef959..878bf54 100644 --- a/rules/assembly/metawrap.smk +++ b/rules/assembly/metawrap.smk @@ -46,8 +46,10 @@ rule assembly: "shallow" conda: "../../envs/assembly.yaml" + singularity: + "shub://ctmrbio/stag-mwc:assembly" threads: - 20 + cluster_config["assembly"]["n"] if "assembly" in cluster_config else 20 params: outdir=lambda w: f"{OUTDIR}/metawrap/assembly/{mw_config['assembler']}/{w.sample}", assembler=mw_config["assembler"], @@ -60,7 +62,7 @@ rule assembly: -o {params.outdir} \ -t {threads} \ -m {params.memory} \ - --use-{params.assembler} \ + --{params.assembler} \ 2> {log.stderr} \ > {log.stdout} """ @@ -83,8 +85,10 @@ rule binning: "shallow" conda: "../../envs/assembly.yaml" + singularity: + "shub://ctmrbio/stag-mwc:assembly" threads: - 20 + cluster_config["binning"]["n"] if "binning" in cluster_config else 20 params: outdir=lambda w: f"{OUTDIR}/metawrap/binning/{mw_config['assembler']}/{w.sample}", universal=mw_config["universal"], @@ -122,8 +126,10 @@ rule consolidate_bins: "shallow" conda: "../../envs/assembly.yaml" + singularity: + "shub://ctmrbio/stag-mwc:assembly" threads: - 20 + cluster_config["consolidate_bins"]["n"] if "consolidate_bins" in cluster_config else 20 params: outdir=lambda w: f"{OUTDIR}/metawrap/consolidated_bins/{w.sample}", minimum_completion=mw_config["minimum_completion"], @@ -158,8 +164,10 @@ rule blobology: "shallow" conda: "../../envs/assembly.yaml" + singularity: + "shub://ctmrbio/stag-mwc:assembly" threads: - 20 + cluster_config["blobology"]["n"] if "blobology" in cluster_config else 20 params: outdir=lambda w: f"{OUTDIR}/metawrap/blobology/{w.sample}", shell: diff --git a/rules/functional_profiling/humann2.smk b/rules/functional_profiling/humann2.smk index b23f379..cf953c1 100644 --- a/rules/functional_profiling/humann2.smk +++ b/rules/functional_profiling/humann2.smk @@ -45,6 +45,8 @@ rule download_humann2_databases: "shallow" conda: "../../envs/humann2.yaml" + singularity: + "shub://ctmrbio/stag-mwc:biobakery" params: dbdir=config["dbdir"]+"/humann2" shell: @@ -70,8 +72,10 @@ rule humann2: "shallow" conda: "../../envs/humann2.yaml" + singularity: + "shub://ctmrbio/stag-mwc:biobakery" threads: - 20 + cluster_config["humann2"]["n"] if "humann2" in cluster_config else 20 resources: humann2=1 params: @@ -118,6 +122,8 @@ rule normalize_humann2_tables: "shallow" conda: "../../envs/humann2.yaml" + singularity: + "shub://ctmrbio/stag-mwc:biobakery" threads: 1 params: @@ -167,6 +173,8 @@ rule join_humann2_tables: "shallow" conda: "../../envs/humann2.yaml" + singularity: + "shub://ctmrbio/stag-mwc:biobakery" threads: 1 params: diff --git a/rules/mappers/bbmap.smk b/rules/mappers/bbmap.smk index 171c3a8..d274a39 100644 --- a/rules/mappers/bbmap.smk +++ b/rules/mappers/bbmap.smk @@ -68,8 +68,10 @@ for bbmap_config in config["bbmap"]: "shallow" conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" threads: - 8 + cluster_config["bbmap"]["n"] if "bbmap" in cluster_config else 8 params: db_path=bbmap_config["db_path"], min_id=bbmap_config["min_id"], @@ -113,6 +115,8 @@ for bbmap_config in config["bbmap"]: "shallow" conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" threads: 1 params: @@ -149,6 +153,8 @@ for bbmap_config in config["bbmap"]: "shallow" conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" threads: 4 params: diff --git a/rules/mappers/bowtie2.smk b/rules/mappers/bowtie2.smk index e332f0f..4d72049 100644 --- a/rules/mappers/bowtie2.smk +++ b/rules/mappers/bowtie2.smk @@ -67,7 +67,7 @@ for bt2_config in config["bowtie2"]: index=bt2_config["db_prefix"], extra=bt2_config["extra"], threads: - 8 + cluster_config["bowtie2"]["n"] if "bowtie2" in cluster_config else 8 wrapper: "0.23.1/bio/bowtie2/align" @@ -87,6 +87,8 @@ for bt2_config in config["bowtie2"]: "shallow" conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" shell: """ pileup.sh \ @@ -120,6 +122,8 @@ for bt2_config in config["bowtie2"]: "shallow" conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" threads: 1 params: @@ -156,6 +160,8 @@ for bt2_config in config["bowtie2"]: "shallow" conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" threads: 4 params: diff --git a/rules/multiqc/multiqc.smk b/rules/multiqc/multiqc.smk index 4f69f53..f232395 100644 --- a/rules/multiqc/multiqc.smk +++ b/rules/multiqc/multiqc.smk @@ -18,6 +18,8 @@ if config["multiqc_report"]: "shallow" conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" threads: 1 params: diff --git a/rules/naive/bbcountunique.smk b/rules/naive/bbcountunique.smk index e155272..af4d118 100644 --- a/rules/naive/bbcountunique.smk +++ b/rules/naive/bbcountunique.smk @@ -27,9 +27,11 @@ if config["naive"]["assess_depth"]: shadow: "shallow" threads: - 2 + cluster_config["bbcountunique"]["n"] if "bbcountunique" in cluster_config else 2 conda: "../../envs/stag-mwc.yaml", + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" params: interval=config["bbcountunique"]["interval"] shell: diff --git a/rules/naive/sketch_compare.smk b/rules/naive/sketch_compare.smk index 313299e..ae5318e 100644 --- a/rules/naive/sketch_compare.smk +++ b/rules/naive/sketch_compare.smk @@ -29,8 +29,10 @@ rule sketch: "shallow" conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" threads: - 4 + cluster_config["sketch"]["n"] if "sketch" in cluster_config else 4 shell: """ sketch.sh \ @@ -54,6 +56,8 @@ rule compare_sketches: "shallow" conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" shell: """ comparesketch.sh \ @@ -79,6 +83,8 @@ rule plot_sample_similarity: stderr=str(LOGDIR/"sketch_compare/sample_similarity_plot.stderr.log"), conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" shell: """ scripts/plot_sketch_comparison_heatmap.py \ diff --git a/rules/preproc/host_removal.smk b/rules/preproc/host_removal.smk index e53d951..4d90624 100644 --- a/rules/preproc/host_removal.smk +++ b/rules/preproc/host_removal.smk @@ -6,7 +6,7 @@ from pathlib import Path from snakemake.exceptions import WorkflowError rh_config = config["remove_host"] -if rh_config: +if config["host_removal"]: db_path = Path(config["remove_host"]["db_path"]) if not Path(db_path/"taxo.k2d").is_file(): err_message = "Cannot find database for host sequence removal at: '{}/*.k2d'!\n".format(db_path) @@ -45,8 +45,10 @@ if rh_config: "shallow" conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" threads: - 8 + cluster_config["remove_host"]["n"] if "remove_host" in cluster_config else 8 params: db=rh_config["db_path"], confidence=rh_config["confidence"], @@ -97,6 +99,8 @@ if rh_config: "shallow" conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" threads: 1 shell: diff --git a/rules/preproc/preprocessing_summary.smk b/rules/preproc/preprocessing_summary.smk index de5128b..f3fece9 100644 --- a/rules/preproc/preprocessing_summary.smk +++ b/rules/preproc/preprocessing_summary.smk @@ -34,6 +34,8 @@ rule preprocessing_summary: stderr=str(LOGDIR/"preprocessing_summary.log"), conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" threads: 1 shell: diff --git a/rules/preproc/read_quality.smk b/rules/preproc/read_quality.smk index e021666..a732a29 100644 --- a/rules/preproc/read_quality.smk +++ b/rules/preproc/read_quality.smk @@ -1,6 +1,6 @@ # vim: syntax=python expandtab # Read pre-processing -#TODO: Remove superfluous str conversions of paths in expand and log statements +# TODO: Remove superfluous str conversions of paths in expand and log statements # when Snakemake is pathlib compatible. if config["qc_reads"]: @@ -30,8 +30,10 @@ if config["qc_reads"]: "shallow" conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" threads: - 4 + cluster_config["fastp"]["n"] if "fastp" in cluster_config else 4 params: extra=fastp_config["extra"], shell: diff --git a/rules/publications.py b/rules/publications.py index cfe7896..01641ec 100644 --- a/rules/publications.py +++ b/rules/publications.py @@ -6,6 +6,7 @@ "Bracken": "Lu J, Breitwieser FP, Thielen P, Salzberg SL (2017). Bracken: estimating species abundance in metagenomics data. PeerJ Computer Science 3:e104. https://doi.org/10.7717/peerj-cs.104", "CONCOCT": "Alneberg, J., Bjarnason, B.S., de Bruijn, I., Schirmer, M., Quick, J., Ijaz, U.Z., Lahti, L., Loman, N.J, Andersson, A.F, Quince, C. (2014). Binning metagenomic contigs by coverage and composition. Nature Methods, https://doi.org/10.1038/nmeth.3103", "GROOT": "Rowe WPM, Winn MD (2018). Indexed variation graphs for efficient and accurate resistome profiling. Bioinformatics, Volume 34, Issue 21. https://doi.org/10.1093/bioinformatics/bty387", + "AMRPlusPlus2": "Doster E, Lakin S, Dean C, Wlfe C, Young J, Boucher C et al. (2019). MEGAREs 2.0: a database for classification of antimicrobial drug, biocide and metal resistance determinants in metagenomic sequence data. Nucleic Acids Research, Volume 48, Issue D1, 08 January 2020, Pages D561–D569, https://doi.org/10.1093/nar/gkz1010", "HUMAnN2": "Franzosa EA*, McIver LJ*, et al. (2018). Species-level functional profiling of metagenomes and metatranscriptomes. Nat Methods 15: 962-968. https://doi.org/10.1038/s41592-018-0176-y", "Kaiju": "Menzel, P., Ng, K. L., & Krogh, A. (2016). Fast and sensitive taxonomic classification for metagenomics with Kaiju. Nature communications, 7, 11257. Available online at: https://github.com/bioinformatics-centre/kaiju", "Kraken2": "Wood, D.E., Lu, J., & Langmead, B. (2019). Improved metagenomic analysis with Kraken 2. Genome biology, 20, 257. https://doi.org/10.1186/s13059-019-1891-0", diff --git a/rules/taxonomic_profiling/kaiju.smk b/rules/taxonomic_profiling/kaiju.smk index de44c00..90a618e 100644 --- a/rules/taxonomic_profiling/kaiju.smk +++ b/rules/taxonomic_profiling/kaiju.smk @@ -35,7 +35,7 @@ if config["taxonomic_profile"]["kaiju"]: all_outputs.extend(kaiju_reports) all_outputs.append(kaiju_krona) all_outputs.append(kaiju_joined_table) - all_outputs.append(kaiju_area_plot) + #all_outputs.append(kaiju_area_plot) # Buggy in stag 4.1 citations.add(publications["Kaiju"]) citations.add(publications["Krona"]) @@ -70,9 +70,11 @@ rule kaiju: shadow: "shallow" threads: - 4 + cluster_config["kaiju"]["n"] if "kaiju" in cluster_config else 4 conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" params: db=kaiju_config["db"], nodes=kaiju_config["nodes"], @@ -112,6 +114,8 @@ rule kaiju2krona: names=kaiju_config["names"], conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" shell: """ kaiju2krona \ @@ -131,6 +135,8 @@ rule create_kaiju_krona_plot: "shallow" conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" shell: """ ktImportText \ @@ -152,6 +158,8 @@ rule kaiju_report: names=kaiju_config["names"], conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" shell: """ kaiju2table \ @@ -181,6 +189,8 @@ rule join_kaiju_reports: value_column=kaiju_config["value_column"], conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" shell: """ scripts/join_tables.py \ @@ -203,6 +213,8 @@ rule kaiju_area_plot: str(LOGDIR/"kaiju/area_plot.log") conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" shell: """ scripts/area_plot.py \ diff --git a/rules/taxonomic_profiling/kraken2.smk b/rules/taxonomic_profiling/kraken2.smk index dc6d52f..78e11c6 100644 --- a/rules/taxonomic_profiling/kraken2.smk +++ b/rules/taxonomic_profiling/kraken2.smk @@ -85,9 +85,11 @@ rule kraken2: shadow: "shallow" threads: - 4 + cluster_config["kraken2"]["n"] if "kraken2" in cluster_config else 4 conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" params: db=kraken2_config["db"], confidence=kraken2_config["confidence"], @@ -116,9 +118,11 @@ rule kraken_mpa_style: log: str(LOGDIR/"kraken2/{sample}.mpa_style.log") threads: - 2 + 1 conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" shell: """ kreport2mpa.py \ @@ -140,9 +144,11 @@ rule join_kraken2_mpa: log: str(LOGDIR/"kraken2/join_kraken2_mpa_tables.log") threads: - 2 + 1 conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" params: value_column="reads", feature_column="taxon_name", @@ -168,6 +174,8 @@ rule kraken2_area_plot: str(LOGDIR/"kraken2/area_plot.kraken2.log") conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" shell: """ scripts/area_plot.py \ @@ -191,6 +199,8 @@ rule combine_kreports: "shallow" conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" shell: """ scripts/KrakenTools/combine_kreports.py \ @@ -214,6 +224,8 @@ rule kreport2krona: 1 conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" shell: """ scripts/KrakenTools/kreport2krona.py \ @@ -234,6 +246,8 @@ rule create_kraken2_krona_plot: "shallow" conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" shell: """ ktImportText \ @@ -283,11 +297,13 @@ rule bracken_kreport: log: str(LOGDIR/"kraken2/{sample}.bracken.log") threads: - 2 + cluster_config["bracken"]["n"] if "bracken" in cluster_config else 2 shadow: "shallow" conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" params: kmer_distrib=kraken2_config["bracken"]["kmer_distrib"], thresh=kraken2_config["bracken"]["thresh"], @@ -314,9 +330,11 @@ rule bracken_all_levels: shadow: # shadow required because est_abundance.py always creates the "shallow" # sample-level output file with fixed filename: {sample}_bracken.kreport threads: - 2 + cluster_config["bracken"]["n"] if "bracken" in cluster_config else 2 conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" params: kmer_distrib=kraken2_config["bracken"]["kmer_distrib"], thresh=kraken2_config["bracken"]["thresh"], @@ -340,9 +358,11 @@ rule bracken_mpa_style: log: str(LOGDIR/"kraken2/{sample}.bracken.mpa_style.log") threads: - 2 + 1 conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" shell: """ kreport2mpa.py \ @@ -364,9 +384,11 @@ rule join_bracken_mpa: log: str(LOGDIR/"kraken2/join_bracken_mpa_tables.log") threads: - 2 + 1 conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" params: value_column="reads", feature_column="taxon_name", @@ -392,6 +414,8 @@ rule bracken_area_plot: str(LOGDIR/"kraken2/area_plot.bracken.log") conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" shell: """ scripts/area_plot.py \ @@ -412,9 +436,11 @@ rule join_bracken: log: str(LOGDIR/"kraken2/join_bracken_tables.{level}.log") threads: - 2 + 1 conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" params: value_column="fraction_total_reads", feature_column="name", @@ -442,6 +468,8 @@ rule bracken2krona: "shallow" conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" shell: """ scripts/KrakenTools/kreport2krona.py \ @@ -462,6 +490,8 @@ rule create_bracken_krona_plot: "shallow" conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" shell: """ ktImportText \ @@ -478,9 +508,11 @@ rule filter_bracken: log: str(LOGDIR/"kraken2/{sample}.{level}.filter_bracken.log") threads: - 2 + 1 conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" params: filter_bracken="scripts/KrakenTools/filter_bracken.out.py", include=kraken2_config["filter_bracken"]["include"], @@ -506,9 +538,11 @@ rule join_bracken_filtered: log: str(LOGDIR/"kraken2/join_bracken_tables.{level}.log") threads: - 2 + 1 conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" params: value_column="fraction_total_reads", feature_column="name", diff --git a/rules/taxonomic_profiling/metaphlan2.smk b/rules/taxonomic_profiling/metaphlan2.smk index d75fa3a..ad27e97 100644 --- a/rules/taxonomic_profiling/metaphlan2.smk +++ b/rules/taxonomic_profiling/metaphlan2.smk @@ -51,8 +51,10 @@ rule metaphlan2: "shallow" conda: "../../envs/metaphlan2.yaml" + singularity: + "shub://ctmrbio/stag-mwc:biobakery" threads: - 5 + cluster_config["metaphlan2"]["n"] if "metaphlan2" in cluster_config else 5 params: bt2_db_dir=mpa_config["bt2_db_dir"], bt2_index=mpa_config["bt2_index"], @@ -117,6 +119,8 @@ rule combine_metaphlan2_tables: "shallow" conda: "../../envs/metaphlan2.yaml" + singularity: + "shub://ctmrbio/stag-mwc:biobakery" threads: 1 shell: @@ -137,6 +141,8 @@ rule metaphlan2_area_plot: str(LOGDIR/"metaphlan2/area_plot.log") conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" shell: """ scripts/area_plot.py \ @@ -161,6 +167,8 @@ rule plot_metaphlan2_heatmap: "shallow" conda: "../../envs/stag-mwc.yaml" + singularity: + "shub://ctmrbio/stag-mwc:stag-mwc" threads: 1 params: @@ -196,6 +204,8 @@ rule create_metaphlan2_krona_plots: "shallow" conda: "../../envs/metaphlan2.yaml" + singularity: + "shub://ctmrbio/stag-mwc:biobakery" threads: 1 shell: diff --git a/scripts/amrplusplus/LICENSE b/scripts/amrplusplus/LICENSE new file mode 100644 index 0000000..f0f3790 --- /dev/null +++ b/scripts/amrplusplus/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Chris Dean + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/scripts/amrplusplus/amr_long_to_wide.py b/scripts/amrplusplus/amr_long_to_wide.py new file mode 100755 index 0000000..0d4d1ca --- /dev/null +++ b/scripts/amrplusplus/amr_long_to_wide.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python3 + +__author__ = "Steven Lakin" +__copyright__ = "" +__credits__ = ["Steven Lakin"] +__version__ = "" +__maintainer__ = "lakinsm" +__email__ = "lakinsm@colostate.edu" +__status__ = "Cows go moo." + +import argparse +import sys + +amr_level_names = {0: 'Class', 1: 'Mechanism', 2: 'Group'} + +def parse_cmdline_params(cmdline_params): + info = "" + parser = argparse.ArgumentParser(description=info) + parser.add_argument('-i', '--input_files', nargs='+', required=True, + help='Use globstar to pass a list of files, (Ex: *.tsv)') + parser.add_argument('-o', '--output_file', required=True, + help='Output file name for writing the AMR_analytic_matrix.csv file') + return parser.parse_args(cmdline_params) + +def amr_load_data(file_name_list): + samples = {} + labels = set() + for file in file_name_list: + with open(file, 'r') as f: + data = f.read().split('\n')[1:] + for entry in data: + if not entry: + continue + entry = entry.split('\t') + sample = entry[0].split('.')[0] + count = float(entry[2]) + gene_name = entry[1] + try: + samples[sample][gene_name] = count + except KeyError: + try: + samples[sample].setdefault(gene_name, count) + except KeyError: + samples.setdefault(sample, {gene_name: count}) + labels.add(gene_name) + return samples, labels + +def output_amr_analytic_data(outfile, S, L): + with open(outfile, 'w') as amr: + local_sample_names = [] + for sample, dat in S.items(): + local_sample_names.append(sample) + amr.write(','.join(local_sample_names) + '\n') + for label in L: + local_counts = [] + amr.write(label + ',') + for local_sample in local_sample_names: + if label in S[local_sample]: + local_counts.append(str(S[local_sample][label])) + else: + local_counts.append(str(0)) + amr.write(','.join(local_counts) + '\n') + +if __name__ == '__main__': + opts = parse_cmdline_params(sys.argv[1:]) + S, L = amr_load_data(opts.input_files) + output_amr_analytic_data(opts.output_file, S, L) diff --git a/scripts/amrplusplus/rarefaction b/scripts/amrplusplus/rarefaction new file mode 100755 index 0000000000000000000000000000000000000000..4ad5ecaa5a53196e656ecda48e058b4cce23e774 GIT binary patch literal 187912 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 z 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

ilyk%tp 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

    )j2|QE7c3xua({ncN`>HO1E+quXB?;3 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 b{XBr^o93%14X>#C|Erx#HP*So`RV;XO?wWG literal 0 HcmV?d00001