From e3b6c649b02c9ee1c928e678f2e69068ee69828d Mon Sep 17 00:00:00 2001 From: Jody Phelan Date: Mon, 13 May 2024 11:47:11 +0100 Subject: [PATCH 01/20] add drugs to collate variants --- tbprofiler/collate.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tbprofiler/collate.py b/tbprofiler/collate.py index c31b0ae..85de3d0 100644 --- a/tbprofiler/collate.py +++ b/tbprofiler/collate.py @@ -32,6 +32,7 @@ def add_result(self, result: ProfileResult) -> None: self.samples2variants[result.id].add(key) d = var.model_dump() d['sample'] = result.id + d['drugs'] = ";".join([x['drug'] for x in var.drugs]) if hasattr(var,'drugs')>0 else "-" self.variant_rows.append(d) def get_frequency(self,key: Tuple[str,str,str]) -> float: return self.variant_frequencies.get(key,0.0) @@ -39,7 +40,7 @@ def get_variant_list(self) -> List[Tuple[str,str]]: return list(self.variant2samples.keys()) def write_dump(self,filename: str) -> None: with open(filename,"w") as O: - fields = ["sample","gene_name","change","freq","type"] + fields = ["sample","gene_name","change","freq","type","drugs"] writer = csv.DictWriter(O,fieldnames=fields) writer.writeheader() for row in self.variant_rows: From 2d2efaafb22d3b7f4331ede150c67a7fe505d2e1 Mon Sep 17 00:00:00 2001 From: Jody Phelan Date: Mon, 13 May 2024 11:48:13 +0100 Subject: [PATCH 02/20] bump version --- tbprofiler/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tbprofiler/__init__.py b/tbprofiler/__init__.py index 42791e3..dea95d3 100644 --- a/tbprofiler/__init__.py +++ b/tbprofiler/__init__.py @@ -7,4 +7,4 @@ from .snp_dists import * from .phylo import * -__version__ = "6.2.1" +__version__ = "6.2.2" From 32d4c27ec5429cf08b8d690b46a5109c0d708379 Mon Sep 17 00:00:00 2001 From: Jody Phelan Date: Thu, 23 May 2024 15:41:49 +0100 Subject: [PATCH 03/20] bug fix for spoligo --- tbprofiler/models.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tbprofiler/models.py b/tbprofiler/models.py index 9a30d77..8530971 100644 --- a/tbprofiler/models.py +++ b/tbprofiler/models.py @@ -79,9 +79,9 @@ class Spacer(BaseModel): class Spoligotype(BaseModel): binary: str octal: str - family: str - SIT: str - countries: str + family: Optional[str] + SIT: Optional[str] + countries: Optional[str] spacers: List[Spacer] def __repr__(self) -> str: From 67ac8f8684cd533e655d7bed532015fe7b91a37c Mon Sep 17 00:00:00 2001 From: Jody Phelan Date: Fri, 7 Jun 2024 15:44:20 +0100 Subject: [PATCH 04/20] add macos env --- macOS-latest.txt | 290 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 290 insertions(+) create mode 100644 macOS-latest.txt diff --git a/macOS-latest.txt b/macOS-latest.txt new file mode 100644 index 0000000..ef8b1e3 --- /dev/null +++ b/macOS-latest.txt @@ -0,0 +1,290 @@ +# This file may be used to create an environment using: +# $ conda create --name --file +# platform: osx-64 +@EXPLICIT +https://conda.anaconda.org/conda-forge/osx-64/libjpeg-turbo-2.1.4-hb7f2c08_0.tar.bz2 +https://conda.anaconda.org/bioconda/osx-64/seqkit-2.5.0-h527b516_0.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/tree-2.1.1-h0dc2134_0.conda +https://conda.anaconda.org/conda-forge/osx-64/bc-1.07.1-h0d85af4_0.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h0d85af4_4.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.19.1-h0dc2134_0.conda +https://conda.anaconda.org/conda-forge/osx-64/ca-certificates-2024.2.2-h8857fd0_0.conda +https://conda.anaconda.org/conda-forge/osx-64/isa-l-2.30.0-h0d85af4_4.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/jpeg-9e-hac89ed1_2.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/libbrotlicommon-1.0.9-hb7f2c08_9.conda +https://conda.anaconda.org/conda-forge/osx-64/libcxx-16.0.6-hd57cbcb_0.conda +https://conda.anaconda.org/conda-forge/osx-64/libdeflate-1.13-h775f41a_0.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-haf1e3a3_1.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/libffi-3.4.2-h0d85af4_5.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.17-hac89ed1_0.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/libogg-1.3.4-h35c211d_1.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/libopus-1.3.1-hc929b4f_1.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/libsodium-1.0.18-hbcb3906_1.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/libuuid-2.38.1-hb7f2c08_0.conda +https://conda.anaconda.org/conda-forge/osx-64/libwebp-base-1.3.1-h0dc2134_0.conda +https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.2.13-h8a1eda9_5.conda +https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-17.0.6-hb6ac08f_0.conda +https://conda.anaconda.org/bioconda/osx-64/mafft-7.520-h2413b67_2.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/mpi-1.0-openmpi.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.4-hf0c8a7f_0.conda +https://conda.anaconda.org/conda-forge/osx-64/oniguruma-6.9.8-hac89ed1_0.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/perl-5.32.1-4_h0dc2134_perl5.conda +https://conda.anaconda.org/conda-forge/osx-64/pthread-stubs-0.4-hc929b4f_1001.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.10-3_cp310.conda +https://conda.anaconda.org/conda-forge/noarch/tzdata-2023c-h71feb2d_0.conda +https://conda.anaconda.org/conda-forge/osx-64/xorg-libxau-1.0.11-h0dc2134_0.conda +https://conda.anaconda.org/conda-forge/osx-64/xorg-libxdmcp-1.1.3-h35c211d_0.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/yaml-0.2.5-h0d85af4_2.tar.bz2 +https://conda.anaconda.org/bioconda/osx-64/bedtools-2.31.0-h6372da2_2.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/gettext-0.21.1-h8a4c099_0.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/htop-3.2.2-h908806b_0.conda +https://conda.anaconda.org/conda-forge/osx-64/icu-70.1-h96cf925_0.tar.bz2 +https://conda.anaconda.org/bioconda/osx-64/iqtree-2.2.2.7-hd98611f_2.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/jq-1.6-hc929b4f_1000.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/lerc-4.0.0-hb486fe8_0.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/libbrotlidec-1.0.9-hb7f2c08_9.conda +https://conda.anaconda.org/conda-forge/osx-64/libbrotlienc-1.0.9-hb7f2c08_9.conda +https://conda.anaconda.org/conda-forge/osx-64/libcbor-0.9.0-he49afe7_0.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/libedit-3.1.20191231-h0678c8f_2.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/libgfortran5-12.2.0-he409387_31.conda +https://conda.anaconda.org/conda-forge/osx-64/libllvm13-13.0.1-h64f94b2_2.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/libpng-1.6.39-ha978bb4_0.conda +https://conda.anaconda.org/conda-forge/osx-64/libprotobuf-3.20.3-hbc0c0cd_0.conda +https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.42.0-h58db7d2_0.conda +https://conda.anaconda.org/conda-forge/osx-64/libvorbis-1.3.7-h046ec9c_0.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/libxcb-1.13-h0d85af4_1004.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/ncbi-datasets-cli-15.16.2-h694c41f_0.conda +https://conda.anaconda.org/conda-forge/osx-64/nspr-4.35-hea0b92c_0.conda +https://conda.anaconda.org/conda-forge/osx-64/openjdk-17.0.3-h7d26f99_8.conda +https://conda.anaconda.org/conda-forge/osx-64/openssl-1.1.1w-h8a1eda9_0.conda +https://conda.anaconda.org/conda-forge/osx-64/pandoc-3.1.3-h9d075a6_0.conda +https://conda.anaconda.org/conda-forge/osx-64/parallel-20230522-h694c41f_0.conda +https://conda.anaconda.org/conda-forge/osx-64/pcre2-10.40-h1c4e4bc_0.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h9e318b2_1.conda +https://conda.anaconda.org/bioconda/noarch/samclip-0.4.0-hdfd78af_1.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.12-h5dbffcc_0.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/zeromq-4.3.4-he49afe7_1.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/zlib-1.2.13-h8a1eda9_5.conda +https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.2-h829000d_7.conda +https://conda.anaconda.org/conda-forge/osx-64/boost-cpp-1.74.0-h8b082ac_8.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/brotli-bin-1.0.9-hb7f2c08_9.conda +https://conda.anaconda.org/bioconda/osx-64/bwa-0.7.17-h45fc8d7_11.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/capnproto-0.10.4-hae21831_0.conda +https://conda.anaconda.org/bioconda/osx-64/dsk-2.2.0-ha92aebf_2.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/freetype-2.12.1-h3f81eb7_1.conda +https://conda.anaconda.org/bioconda/osx-64/k8-0.2.5-hdf58011_4.tar.bz2 +https://conda.anaconda.org/bioconda/osx-64/kmc-3.2.1-hc4bba69_3.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/krb5-1.20.1-h0165f36_0.conda +https://conda.anaconda.org/conda-forge/osx-64/libclang-13.0.1-default_h255f2f3_1.conda +https://conda.anaconda.org/conda-forge/osx-64/libfido2-1.11.0-h875bebe_0.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/libgfortran-5.0.0-11_3_0_h97931a8_31.conda +https://conda.anaconda.org/conda-forge/osx-64/libglib-2.76.4-hc62aa5d_0.conda +https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.51.0-h0dd9d14_0.conda +https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.10.0-h7535e13_3.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/libtiff-4.4.0-h5e0c7b4_3.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.10.3-h201ad9d_4.conda +https://conda.anaconda.org/conda-forge/osx-64/mysql-common-8.0.32-h7ebae80_0.conda +https://conda.anaconda.org/conda-forge/osx-64/mysql-connector-c-6.1.11-h0f02589_1007.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/nss-3.89-h78b00b3_0.conda +https://conda.anaconda.org/conda-forge/osx-64/python-3.10.8-h4150a38_0_cpython.conda +https://conda.anaconda.org/bioconda/osx-64/snp-sites-2.5.1-h45fc8d7_4.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/appnope-0.1.3-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/attrs-23.1.0-pyh71513ae_1.conda +https://conda.anaconda.org/conda-forge/noarch/backcall-0.2.0-pyh9f0ad1d_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/backports-1.0-pyhd8ed1ab_3.conda +https://conda.anaconda.org/conda-forge/noarch/bitstring-3.1.9-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/brotli-1.0.9-hb7f2c08_9.conda +https://conda.anaconda.org/conda-forge/osx-64/brotli-python-1.0.9-py310h7a76584_9.conda +https://conda.anaconda.org/conda-forge/noarch/cachetools-4.2.4-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.2.0-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/cycler-0.11.0-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/debugpy-1.6.7-py310h7a76584_0.conda +https://conda.anaconda.org/conda-forge/noarch/decorator-5.1.1-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/docutils-0.20.1-py310h2ec42d9_3.conda +https://conda.anaconda.org/conda-forge/noarch/entrypoints-0.4-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.1.2-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/execnet-2.0.2-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/executing-1.2.0-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/filelock-3.12.2-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/flit-core-3.9.0-pyhd8ed1ab_0.conda +https://conda.anaconda.org/bioconda/noarch/gatk4-4.4.0.0-py36hdfd78af_0.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/glib-tools-2.76.4-h7d26f99_0.conda +https://conda.anaconda.org/conda-forge/noarch/idna-3.4-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/ipython_genutils-0.2.0-py_1.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/jupyterlab_widgets-3.0.8-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/osx-64/kiwisolver-1.4.5-py310h88cfcbd_0.conda +https://conda.anaconda.org/conda-forge/osx-64/lcms2-2.14-h90f4b2a_0.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/libcurl-7.87.0-haf73cf8_0.conda +https://conda.anaconda.org/conda-forge/osx-64/libllvm15-15.0.7-h7001e86_1.conda +https://conda.anaconda.org/conda-forge/osx-64/libopenblas-0.3.23-openmp_h429af6e_0.conda +https://conda.anaconda.org/conda-forge/osx-64/libpq-15.1-hdbdeef1_3.conda +https://conda.anaconda.org/conda-forge/osx-64/libxslt-1.1.37-h5d22bc9_0.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/markupsafe-2.1.3-py310h6729b98_0.conda +https://conda.anaconda.org/bioconda/osx-64/minimap2-2.26-h45fc8d7_1.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/mistune-3.0.0-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/munkres-1.1.4-pyh9f0ad1d_0.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/mysql-libs-8.0.32-hc37e033_0.conda +https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.5.6-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/openjpeg-2.5.0-h5d0d7b0_1.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/openmpi-4.1.2-hd3cd54c_0.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/openssh-9.1p1-hdbdeef1_1.conda +https://conda.anaconda.org/conda-forge/noarch/packaging-23.1-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/palettable-3.3.3-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/parso-0.8.3-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/pickleshare-0.7.5-py_1003.tar.bz2 +https://conda.anaconda.org/bioconda/noarch/pilon-1.24-hdfd78af_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/pkgutil-resolve-name-1.3.10-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/pluggy-1.2.0-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/ply-3.11-py_1.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.17.1-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/osx-64/psutil-5.9.5-py310h90acd4f_0.conda +https://conda.anaconda.org/conda-forge/noarch/ptyprocess-0.7.0-pyhd3deb0d_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.2-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/pycparser-2.21-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/pygments-2.15.1-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/pyparsing-3.0.9-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.17.1-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/python-json-logger-2.0.7-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2023.3-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/pytz-2023.3.post1-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/osx-64/pyyaml-6.0-py310h90acd4f_5.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/pyzmq-25.1.0-py310h998be00_0.conda +https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/rpds-py-0.8.10-py310h3461e44_0.conda +https://conda.anaconda.org/conda-forge/noarch/setuptools-68.0.0-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/six-1.16.0-pyh6c4a22f_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.0-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/bioconda/noarch/snpeff-5.1-hdfd78af_2.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.3.2.post1-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/threadpoolctl-3.2.0-pyha21a80b_0.conda +https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/tomli-w-1.0.0-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/tornado-6.3.2-py310h6729b98_0.conda +https://conda.anaconda.org/conda-forge/noarch/traitlets-5.9.0-pyhd8ed1ab_0.conda +https://conda.anaconda.org/bioconda/noarch/trimmomatic-0.39-hdfd78af_2.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.7.1-pyha770c72_0.conda +https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/bioconda/osx-64/ucsc-fatovcf-426-ha55e18d_0.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/unicodedata2-15.0.0-py310h90acd4f_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-py_1.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.6.1-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/wheel-0.40.0-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/widgetsnbextension-4.0.8-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/zipp-3.16.2-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/anyio-3.7.1-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/asttokens-2.2.1-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/backports.functools_lru_cache-1.6.5-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/beautifulsoup4-4.12.2-pyha770c72_0.conda +https://conda.anaconda.org/conda-forge/noarch/bleach-6.0.0-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/osx-64/cffi-1.15.1-py310ha78151a_3.conda +https://conda.anaconda.org/conda-forge/noarch/comm-0.1.3-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/osx-64/coverage-7.4.0-py310hb372a2b_0.conda +https://conda.anaconda.org/conda-forge/osx-64/curl-7.87.0-haf73cf8_0.conda +https://conda.anaconda.org/conda-forge/noarch/deprecation-2.1.0-pyh9f0ad1d_0.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/fonttools-4.42.1-py310h6729b98_0.conda +https://conda.anaconda.org/conda-forge/osx-64/glib-2.76.4-h7d26f99_0.conda +https://conda.anaconda.org/bioconda/osx-64/htslib-1.16-h567f53e_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-6.8.0-pyha770c72_0.conda +https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.0.0-pyhd8ed1ab_1.conda +https://conda.anaconda.org/conda-forge/noarch/jedi-0.18.2-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.2-pyhd8ed1ab_1.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/joblib-1.3.0-pyhd8ed1ab_1.conda +https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.2.2-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/libblas-3.9.0-17_osx64_openblas.conda +https://conda.anaconda.org/conda-forge/osx-64/libclang13-15.0.7-default_h953c2e9_2.conda +https://conda.anaconda.org/conda-forge/osx-64/lxml-4.9.2-py310h0b20c97_0.conda +https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.1.6-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/overrides-7.3.1-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/pexpect-4.8.0-pyh1a96a4e_2.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/pillow-9.2.0-py310hffcf78b_3.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/pip-23.1.2-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/osx-64/pyobjc-core-9.2-py310hef2d279_0.conda +https://conda.anaconda.org/bioconda/osx-64/pysam-0.20.0-py310h958c131_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.0-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.8.2-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/qtpy-2.3.1-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/referencing-0.29.1-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/screed-1.1.2-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/osx-64/sip-6.7.9-py310h9e9d8ca_0.conda +https://conda.anaconda.org/conda-forge/noarch/terminado-0.17.1-pyhd1c38e8_0.conda +https://conda.anaconda.org/conda-forge/noarch/tinycss2-1.2.1-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/tqdm-4.65.0-pyhd8ed1ab_1.conda +https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.7.1-hd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/urllib3-2.0.3-pyhd8ed1ab_1.conda +https://conda.anaconda.org/bioconda/osx-64/usher-0.6.2-hdcdf62d_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.6.0-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/osx-64/argon2-cffi-bindings-21.2.0-py310h90acd4f_3.tar.bz2 +https://conda.anaconda.org/bioconda/osx-64/delly-1.1.6-h69f7742_0.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/gstreamer-1.22.4-h840fbdc_1.conda +https://conda.anaconda.org/conda-forge/noarch/importlib_metadata-6.8.0-hd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2023.6.1-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/jupyter_server_terminals-0.4.4-pyhd8ed1ab_1.conda +https://conda.anaconda.org/bioconda/noarch/krona-2.8.1-pl5321hdfd78af_1.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/libcblas-3.9.0-17_osx64_openblas.conda +https://conda.anaconda.org/conda-forge/osx-64/liblapack-3.9.0-17_osx64_openblas.conda +https://conda.anaconda.org/conda-forge/noarch/platformdirs-3.8.1-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/osx-64/pydantic-core-2.14.6-py310h0e083fb_1.conda +https://conda.anaconda.org/conda-forge/osx-64/pyobjc-framework-cocoa-9.2-py310hef2d279_0.conda +https://conda.anaconda.org/conda-forge/osx-64/pyqt5-sip-12.11.0-py310h415000c_3.conda +https://conda.anaconda.org/conda-forge/noarch/pytest-cov-4.1.0-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/pytest-xdist-3.5.0-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/python-docx-0.8.11-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda +https://conda.anaconda.org/bioconda/osx-64/samtools-1.16.1-h7e39424_1.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.2-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.2.6-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-21.3.0-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/docxtpl-0.11.5-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/flit-3.9.0-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/osx-64/gsl-2.7-h93259b0_0.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/gst-plugins-base-1.22.4-hb5d3a86_1.conda +https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.18.3-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/osx-64/jupyter_core-5.3.1-py310h2ec42d9_0.conda +https://conda.anaconda.org/bioconda/osx-64/lofreq-2.1.5-py310h74bfb37_8.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/numpy-1.25.2-py310h7451ae0_0.conda +https://conda.anaconda.org/conda-forge/noarch/pooch-1.7.0-pyha770c72_3.conda +https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.39-pyha770c72_0.conda +https://conda.anaconda.org/conda-forge/noarch/pydantic-2.5.3-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/send2trash-1.8.2-pyhd1c38e8_0.conda +https://conda.anaconda.org/bioconda/osx-64/tabixpp-1.1.0-h9d30fad_11.tar.bz2 +https://conda.anaconda.org/bioconda/osx-64/bcftools-1.16-h83fc8ca_1.tar.bz2 +https://conda.anaconda.org/conda-forge/osx-64/contourpy-1.1.0-py310h88cfcbd_0.conda +https://conda.anaconda.org/conda-forge/noarch/jupyter_client-8.3.0-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/jupyter_events-0.6.3-pyhd8ed1ab_0.conda +https://conda.anaconda.org/bioconda/osx-64/mash-2.3-hf785b45_2.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/nbformat-5.9.1-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/osx-64/pandas-2.1.1-py310h5262a37_1.conda +https://conda.anaconda.org/conda-forge/noarch/prompt_toolkit-3.0.39-hd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/osx-64/qt-main-5.15.8-h1d3b3f8_6.conda +https://conda.anaconda.org/conda-forge/osx-64/scipy-1.11.1-py310h3900cf1_0.conda +https://conda.anaconda.org/bioconda/osx-64/vcflib-1.0.3-h86e66d2_2.tar.bz2 +https://conda.anaconda.org/bioconda/osx-64/freebayes-1.3.6-h9c5939b_2.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/ipython-8.14.0-pyhd1c38e8_0.conda +https://conda.anaconda.org/conda-forge/osx-64/matplotlib-base-3.7.2-py310h475a17b_0.conda +https://conda.anaconda.org/conda-forge/noarch/nbclient-0.8.0-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/osx-64/pyqt-5.15.7-py310hdd03f62_3.conda +https://conda.anaconda.org/conda-forge/osx-64/scikit-learn-1.4.0-py310h38ce860_0.conda +https://conda.anaconda.org/conda-forge/noarch/ipykernel-6.24.0-pyh5fb750a_0.conda +https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.6.0-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/osx-64/sourmash-minimal-4.8.3-py310h3461e44_0.conda +https://conda.anaconda.org/conda-forge/noarch/ipywidgets-8.0.7-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/jupyter_console-6.6.3-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/jupyter_server-2.7.0-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/nbconvert-pandoc-7.6.0-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/qtconsole-base-5.4.3-pyha770c72_0.conda +https://conda.anaconda.org/bioconda/noarch/sourmash-4.8.3-hdfd78af_0.tar.bz2 +https://conda.anaconda.org/conda-forge/noarch/nbconvert-7.6.0-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.3-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/qtconsole-5.4.3-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/nbclassic-1.0.0-pyhb4ecaf3_1.conda +https://conda.anaconda.org/conda-forge/noarch/notebook-6.5.4-pyha770c72_0.conda +https://conda.anaconda.org/conda-forge/osx-64/jupyter-1.0.0-py310h2ec42d9_8.conda From 3428202688483df6ccf8efa71de80c9aba2da501 Mon Sep 17 00:00:00 2001 From: Jody Phelan Date: Fri, 21 Jun 2024 16:38:29 +0200 Subject: [PATCH 05/20] adding in depth to txt output --- tbprofiler/text.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tbprofiler/text.py b/tbprofiler/text.py index 9dbad98..8de812c 100644 --- a/tbprofiler/text.py +++ b/tbprofiler/text.py @@ -127,9 +127,9 @@ def write_text( summary_table = pp.get_dr_summary(result.dr_variants,conf) text_strings["notes"] = "\n".join(result.notes) text_strings["dr_report"] = pp.dict_list2text(summary_table,sep=sep) - text_strings["dr_var_report"] = pp.object_list2text(result.dr_variants,mappings={"pos":"Genome Position","gene_id":"Locus Tag",'gene_name':'Gene name',"type":"Variant type","change":"Change","freq":"Estimated fraction","drugs.drug":"Drug","drugs.confidence":"Confidence","drugs.comment":"Comment"},sep=sep) - text_strings["other_var_report"] = pp.object_list2text(result.other_variants,mappings={"pos":"Genome Position","gene_id":"Locus Tag",'gene_name':'Gene name',"type":"Variant type","change":"Change","freq":"Estimated fraction","annotation.drug":"Gene associated drug","annotation.confidence":"Confidence","annotation.comment":"Comment"},sep=sep) - text_strings["qc_fail_var_report"] = pp.object_list2text(result.qc_fail_variants,mappings={"pos":"Genome Position","gene_id":"Locus Tag",'gene_name':'Gene name',"type":"Variant type","change":"Change","freq":"Estimated fraction","annotation.drug":"Gene associated drug","annotation.confidence":"Confidence","annotation.comment":"Comment"},sep=sep) + text_strings["dr_var_report"] = pp.object_list2text(result.dr_variants,mappings={"pos":"Genome Position","gene_id":"Locus Tag",'gene_name':'Gene name',"type":"Variant type","change":"Change","depth": "Depth","freq":"Estimated fraction","drugs.drug":"Drug","drugs.confidence":"Confidence","drugs.comment":"Comment"},sep=sep) + text_strings["other_var_report"] = pp.object_list2text(result.other_variants,mappings={"pos":"Genome Position","gene_id":"Locus Tag",'gene_name':'Gene name',"type":"Variant type","change":"Change","depth": "Depth","freq":"Estimated fraction","annotation.drug":"Gene associated drug","annotation.confidence":"Confidence","annotation.comment":"Comment"},sep=sep) + text_strings["qc_fail_var_report"] = pp.object_list2text(result.qc_fail_variants,mappings={"pos":"Genome Position","gene_id":"Locus Tag",'gene_name':'Gene name',"type":"Variant type","change":"Change","depth": "Depth","freq":"Estimated fraction","annotation.drug":"Gene associated drug","annotation.confidence":"Confidence","annotation.comment":"Comment"},sep=sep) text_strings["coverage_report"] = result.get_qc() text_strings['lineage_report'] = pp.object_list2text(result.lineage,mappings={"lineage":"Lineage","fraction":"Fraction","family":"Family","rd":"rd"},sep=sep)#result.lineage) text_strings['strain'] = result.sub_lineage From 4c50d84efd00d0b0a0dc3b385c81f487efb336fe Mon Sep 17 00:00:00 2001 From: Jody Phelan Date: Fri, 21 Jun 2024 16:39:18 +0200 Subject: [PATCH 06/20] fix for #366 --- tbprofiler/collate.py | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/tbprofiler/collate.py b/tbprofiler/collate.py index 85de3d0..ce890dc 100644 --- a/tbprofiler/collate.py +++ b/tbprofiler/collate.py @@ -169,8 +169,32 @@ def generate_itol_config(rows: List[dict], drugs: list, prefix: str) -> None: prefix : str Prefix for output files """ - all_lineage_cols = {"lineage1":"#104577","lineage2":"#ab2323","lineage3":"#18a68c","lineage4":"#f68e51","lineage5":"#7cb5d2","lineage6":"#fde05e","lineage7":"#bc94b7","lineage8":"#ccc9e7","lineage9":"#bd9391","Animal strains":"#f8e0c8","Other":"#000000","Not called": "#ffffff"} - lineage_aggregation = {"": "Not called","M.caprae":"Animal strains","M.bovis":"Animal strains","M.orygis":"Animal strains"} + all_lineage_cols = { + "lineage1":"#104577", + "lineage2":"#ab2323", + "lineage3":"#18a68c", + "lineage4":"#f68e51", + "lineage5":"#7cb5d2", + "lineage6":"#fde05e", + "lineage7":"#bc94b7", + "lineage8":"#ccc9e7", + "lineage9":"#bd9391", + "Animal strains":"#f8e0c8", + "Other":"#000000", + "Not called": "#ffffff" + } + + lineage_aggregation = { + "": "Not called", + "La1": "Animal strains", + "La2": "Animal strains", + "La3": "Animal strains", + "M.canetti":"Other", + "M.caprae":"Animal strains", + "M.bovis":"Animal strains", + "M.orygis":"Animal strains" + } + lineage_dict = {r['sample']:lineage_aggregation.get(r["main_lineage"],r["main_lineage"]) if ";" not in r["main_lineage"] else "Other" for r in rows} lineages_present = set(lineage_dict.values()) lineage_cols = {key:val for key,val in all_lineage_cols.items() if key in lineages_present} From 389ae5b2a6097eabebb71fcbf7d9b39b0b6d45c7 Mon Sep 17 00:00:00 2001 From: Jody Phelan Date: Sun, 23 Jun 2024 10:58:36 +0200 Subject: [PATCH 07/20] improve docx output --- tb-profiler | 20 ++++++ tbprofiler/docx.py | 152 ++++++++++++++++++++++++++++++++++--------- tbprofiler/output.py | 4 +- 3 files changed, 146 insertions(+), 30 deletions(-) diff --git a/tb-profiler b/tb-profiler index e71e1dc..f03c90f 100644 --- a/tb-profiler +++ b/tb-profiler @@ -17,6 +17,21 @@ from tqdm import tqdm import logging from rich.logging import RichHandler +import importlib +import pkgutil + +discovered_plugins = { + name: importlib.import_module(name) + for finder, name, ispkg + in pkgutil.iter_modules() + if name.startswith('tbprofiler_') +} + +docx_plugins = { + plugin.docx.__docx_template_name__:plugin for plugin in discovered_plugins.values() + if hasattr(plugin, 'docx') +} + __softwarename__ = 'tbprofiler' @@ -356,6 +371,7 @@ output.add_argument('--txt',action="store_true",help="Add text output") output.add_argument('--text_template','--text-template',type=str,help='Jinja2 formatted template for output') output.add_argument('--docx',action="store_true",help="Add docx output") output.add_argument('--docx_template','--docx-template',help="Supply custom template for --docx output") +output.add_argument('--docx_plugin','--docx-plugin',choices=list(docx_plugins),help="Use a plugin template for --docx output") output.add_argument('--add_columns','--add-columns',default=None,type=str,help="Add additional columns found in the mutation database to the text and csv results") output.add_argument('--add_mutation_metadata','--add-mutation-metadata',action="store_true",help=argparse.SUPPRESS) output.add_argument('--dir','-d',default=".",help='Storage directory') @@ -468,6 +484,7 @@ parser_sub.add_argument('--txt',action="store_true",help="Add text output") parser_sub.add_argument('--csv',action="store_true",help="Add CSV output") parser_sub.add_argument('--docx',action="store_true",help="Add docx output. This requires docxtpl to be installed") parser_sub.add_argument('--docx_template','--docx-template',help="Supply custom template for --docx output") +parser_sub.add_argument('--docx_plugin','--docx-plugin',choices=list(docx_plugins),help="Use a plugin template for --docx output") parser_sub.add_argument('--text_template','--text-template',type=str,help='Jinja2 formatted template for output') parser_sub.add_argument('--db',default='tbdb',help='Mutation panel name') parser_sub.add_argument('--external_db','--external-db',type=str,help='Path to db files prefix (overrides "--db" parameter)') @@ -584,6 +601,9 @@ if hasattr(args, 'func'): if args.conf is None: logging.error("Can't find the database %s. Please run 'tb-profiler create_db' to create the database or specify another using the '--external_db' flag" % args.db) raise SystemExit + + args.plugins = docx_plugins + args.func(args) else: parser.print_help(sys.stderr) diff --git a/tbprofiler/docx.py b/tbprofiler/docx.py index 21a03fb..0b3a94b 100644 --- a/tbprofiler/docx.py +++ b/tbprofiler/docx.py @@ -1,49 +1,143 @@ import sys from docxtpl import DocxTemplate from collections import defaultdict - +from .models import ProfileResult +from docx import Document +from typing import List +from copy import deepcopy +import logging def sanitize(d): d = d.replace("-","_") return d +def cache_cells(tab) -> List[List[str]]: + _cells = tab._cells + numcols = len(tab.columns) + cells = [] + for row in tab.rows: + rowcells = [] + for i in range(numcols): + rowcells.append(_cells.pop(0)) + cells.append(rowcells) + return cells + +def merge_cells(filename: str) -> None: + doc = Document(filename) + + def _merge_cells(tab, rows: List[int], column: int): + + if column >= len(tab.columns) - 1: + return + if len(rows)==1: + return + c1 = tab.cell(rows[0], column) + c2 = tab.cell(rows[-1], column) + + for r in rows[1:]: + tab.cell(r, column).text = "" + cm = c1.merge(c2) + + values_in_next_column = set([tab.rows[r].cells[column+1].text for r in rows]) + for val in values_in_next_column: + rows_with_val = [r for r in rows if tab.c[r][column+1].text == val] + _merge_cells(tab, rows_with_val, column+1) + + for tab in doc.tables: + logging.info(f"Merging cells in table {tab}") + tab.c = cache_cells(tab) + values_in_next_column = set([tab.rows[r].cells[0].text for r in range(1, len(tab.rows))]) + for val in values_in_next_column: + rows_with_val = [r for r in range(1, len(tab.rows)) if tab.c[r][0].text == val] + + _merge_cells(tab, rows_with_val, 0) + + doc.save(filename) -def write_docx(result,conf,outfile,template_file = None): + + +def write_docx(result: ProfileResult,conf,outfile,template_file = None, plugin = None): if template_file is None: template_file = sys.prefix+"/share/tbprofiler/default_template.docx" - data = result.model_dump() - drug_variants = defaultdict(list) - confidence = defaultdict(list) - for var in data['dr_variants']: - for d in var['drugs']: - if d['type']=='drug_resistance': - drug_variants[d['drug']].append(f"{var['gene_name']}_{var['change']}") - confidence[d['drug']].append(d['confidence']) + + if plugin: + variables = plugin.docx.create_output(result, conf) + + else: + + dr_variant_table = [] + comments = [] + + for var in result.dr_variants: + for drug in var.drugs: + mutation = var.change if len(var.change) < 15 else var.change[:11]+"..."+var.change[-3:] + if drug['comment'] not in comments and len(drug['comment']): + comments.append(drug['comment']) + dr_variant_table.append({ + 'drug': drug['drug'], + 'gene': var.gene_name, + 'mutation': mutation, + 'depth': var.depth, + 'frequency': round(var.freq * 100,2), + 'confidence': drug['confidence'], + 'comment': comments.index(drug['comment'])+1 if len(drug['comment']) else "" + }) + drugs_found = set([x['drug'] for x in dr_variant_table]) + for drug in conf['drugs']: + if drug not in drugs_found: + dr_variant_table.append({ + 'drug': drug, + 'gene': "", + 'mutation': "", + 'depth': "", + 'frequency': "", + 'confidence': "", + 'comment': "" + }) + + gene_qc = [] + for item in result.qc.target_qc: + gene_qc.append({ + 'status': 'ok' if item.percent_depth_pass>0.9 else 'fail', + 'gene': item.target, + 'median_depth': item.median_depth, + 'percent_depth_pass': item.percent_depth_pass, + }) + dr_variant_table = sorted(dr_variant_table,key=lambda x: conf['drugs'].index(x['drug'])) - variables = { - 'date':data['timestamp'].strftime("%d %b %Y"), - 'sublineage': data['sub_lineage'], - 'resistant_drugs': ", ".join([d.capitalize() for d in conf['drugs'] if d in drug_variants]), - 'version': data['pipeline']['software_version'], - 'sensitive': True if data['drtype'] == "Sensitive" else False, - 'mdr': True if data['drtype'] in ("MDR-TB","Pre-XDR-TB") else False, - 'xdr': True if data['drtype'] in "XDR-TB" else False, - 'resistant': True if data['drtype'] in ("Other","RR-TB","HR-TB") else False, - 'drtype': data['drtype'], - 'd': data, - } + other_variants_table = [] + for var in result.other_variants: + for ann in var.annotation: + other_variants_table.append({ + 'gene': var.gene_name, + 'mutation': var.change, + 'depth': var.depth, + 'frequency': round(var.freq * 100,2), + 'drug': ann['drug'], + 'confidence': ann['confidence'], + }) + + data = result.model_dump() + variables = { + 'date':data['timestamp'].strftime("%d %b %Y"), + 'sublineage': data['sub_lineage'], + 'version': data['pipeline']['software_version'], + 'drtype': data['drtype'], + 'd': data, + 'dr_variants_table': dr_variant_table, + 'other_variants_table': other_variants_table, + 'comments': comments, + 'gene_qc': gene_qc + } - for d in conf['drugs']: - variables[sanitize(d)+"_variants"] = ", ".join(drug_variants[d]) if len(drug_variants[d])>0 else "Not found" - variables[sanitize(d)+"_confidence"] = ", ".join(confidence[d]) if len(drug_variants[d])>0 else "-" - variables[sanitize(d)+"_interpretation"] = "Resistance" if len(drug_variants[d])>0 else "-" + doc = DocxTemplate(template_file) + doc.render(variables) + doc.save(outfile) - doc = DocxTemplate(template_file) - doc.render(variables) - doc.save(outfile) \ No newline at end of file + merge_cells(outfile) \ No newline at end of file diff --git a/tbprofiler/output.py b/tbprofiler/output.py index fb0b2ce..317df59 100644 --- a/tbprofiler/output.py +++ b/tbprofiler/output.py @@ -22,4 +22,6 @@ def write_outputs(args,result: ProfileResult,template_file: str = None): write_text(result,args.conf,csv_output,sep=",",template_file = template_file) if args.docx: logging.info(f"Writing docx file: {docx_output}") - write_docx(result,args.conf,docx_output,template_file = args.docx_template) \ No newline at end of file + if args.docx_plugin: + args.docx_plugin = args.plugins[args.docx_plugin] + write_docx(result,args.conf,docx_output,template_file = args.docx_template, plugin = args.docx_plugin) \ No newline at end of file From d048c1e8d4aa67db77c04b83415f7ea608e33ce7 Mon Sep 17 00:00:00 2001 From: Jody Phelan Date: Sun, 23 Jun 2024 11:07:24 +0200 Subject: [PATCH 08/20] remove verbose --- tbprofiler/docx.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tbprofiler/docx.py b/tbprofiler/docx.py index 0b3a94b..0925f09 100644 --- a/tbprofiler/docx.py +++ b/tbprofiler/docx.py @@ -44,7 +44,6 @@ def _merge_cells(tab, rows: List[int], column: int): _merge_cells(tab, rows_with_val, column+1) for tab in doc.tables: - logging.info(f"Merging cells in table {tab}") tab.c = cache_cells(tab) values_in_next_column = set([tab.rows[r].cells[0].text for r in range(1, len(tab.rows))]) for val in values_in_next_column: From 1be0fcd204f9eb3345f4ed460d4e622d44e22bcc Mon Sep 17 00:00:00 2001 From: Jody Phelan Date: Sun, 23 Jun 2024 13:49:41 +0200 Subject: [PATCH 09/20] add debug --- tb-profiler | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tb-profiler b/tb-profiler index f03c90f..d33320c 100644 --- a/tb-profiler +++ b/tb-profiler @@ -349,6 +349,7 @@ def int_2_or_more(arg): parser = argparse.ArgumentParser(description='tb-profiler: a tool to predict drug resistance and infer lineages',formatter_class=ArgumentDefaultsRichHelpFormatter,add_help=False) parser.add_argument('--version', action='version', version="tb-profiler version %s" % tbp.__version__) parser.add_argument('--logging',type=str.upper,default="INFO",choices=["DEBUG","INFO","WARNING","ERROR","CRITICAL"],help='Logging level') +parser.add_argument('--debug',action='store_true',help=argparse.SUPPRESS) subparsers = parser.add_subparsers(help="Task to perform") # Profile # @@ -408,6 +409,7 @@ algorithm.add_argument('--ram',default=2,help='Maximum memory to use',type=int) other=parser_sub.add_argument_group("Other options") other.add_argument('--logging',type=str.upper,default="INFO",choices=["DEBUG","INFO","WARNING","ERROR","CRITICAL"],help='Logging level') +other.add_argument('--debug',action='store_true',help=argparse.SUPPRESS) other.add_argument('--delly_vcf','--delly-vcf',help=argparse.SUPPRESS) other.add_argument('--supplementary_bam','--supplementary-bam',help=argparse.SUPPRESS) other.add_argument('--no_clean','--no-clean', action='store_true',help=argparse.SUPPRESS) @@ -434,6 +436,7 @@ parser_sub.add_argument('--no_clean','--no-clean', action='store_true',help=argp parser_sub.add_argument('--temp',help="Temp firectory to process all files",type=str,default=".") parser_sub.add_argument('--version', action='version', version="tb-profiler version %s" % tbp.__version__) parser_sub.add_argument('--logging',type=str.upper,default="INFO",choices=["DEBUG","INFO","WARNING","ERROR","CRITICAL"],help='Logging level') +parser_sub.add_argument('--debug',action='store_true',help=argparse.SUPPRESS) parser_sub.set_defaults(func=main_lineage) parser_sub = subparsers.add_parser('spoligotype', help='Profile spoligotype', formatter_class=ArgumentDefaultsRichHelpFormatter) @@ -458,6 +461,7 @@ parser_sub.add_argument('--ram',default=2,type=int_2_or_more,help='Maximum memor parser_sub.add_argument('--temp',help="Temp firectory to process all files",type=str,default=".") parser_sub.add_argument('--version', action='version', version="tb-profiler version %s" % tbp.__version__) parser_sub.add_argument('--logging',type=str.upper,default="INFO",choices=["DEBUG","INFO","WARNING","ERROR","CRITICAL"],help='Logging level') +parser_sub.add_argument('--debug',action='store_true',help=argparse.SUPPRESS) parser_sub.set_defaults(func=main_spoligotype) parser_sub = subparsers.add_parser('collate', help='Collate results form multiple samples together', formatter_class=ArgumentDefaultsRichHelpFormatter) @@ -475,6 +479,7 @@ parser_sub.add_argument('--no_clean','--no-clean', action='store_true',help=argp parser_sub.add_argument('--temp',help="Temp firectory to process all files",type=str,default=".") parser_sub.add_argument('--version', action='version', version="tb-profiler version %s" % tbp.__version__) parser_sub.add_argument('--logging',type=str.upper,default="INFO",choices=["DEBUG","INFO","WARNING","ERROR","CRITICAL"],help='Logging level') +parser_sub.add_argument('--debug',action='store_true',help=argparse.SUPPRESS) parser_sub.set_defaults(func=main_collate) @@ -494,6 +499,7 @@ parser_sub.add_argument('--suspect',action="store_true",help=argparse.SUPPRESS) parser_sub.add_argument('--temp',help="Temp firectory to process all files",type=str,default=".") parser_sub.add_argument('--version', action='version', version="tb-profiler version %s" % tbp.__version__) parser_sub.add_argument('--logging',type=str.upper,default="INFO",choices=["DEBUG","INFO","WARNING","ERROR","CRITICAL"],help='Logging level') +parser_sub.add_argument('--debug',action='store_true',help=argparse.SUPPRESS) parser_sub.set_defaults(func=main_reformat) parser_sub = subparsers.add_parser('create_db', help='Generate the files required to run tb-profiler', formatter_class=ArgumentDefaultsRichHelpFormatter) @@ -520,6 +526,7 @@ parser_sub.add_argument('--no_clean','--no-clean', action='store_true',help=argp parser_sub.add_argument('--temp',help="Temp firectory to process all files",type=str,default=".") parser_sub.add_argument('--version', action='version', version="tb-profiler version %s" % tbp.__version__) parser_sub.add_argument('--logging',type=str.upper,default="INFO",choices=["DEBUG","INFO","WARNING","ERROR","CRITICAL"],help='Logging level') +parser_sub.add_argument('--debug',action='store_true',help=argparse.SUPPRESS) parser_sub.set_defaults(func=main_create_db) parser_sub = subparsers.add_parser('load_library', help='Load new library', formatter_class=ArgumentDefaultsRichHelpFormatter) @@ -529,6 +536,7 @@ parser_sub.add_argument('--no_clean','--no-clean', action='store_true',help=argp parser_sub.add_argument('--temp',help="Temp firectory to process all files",type=str,default=".") parser_sub.add_argument('--version', action='version', version="tb-profiler version %s" % tbp.__version__) parser_sub.add_argument('--logging',type=str.upper,default="INFO",choices=["DEBUG","INFO","WARNING","ERROR","CRITICAL"],help='Logging level') +parser_sub.add_argument('--debug',action='store_true',help=argparse.SUPPRESS) parser_sub.set_defaults(func=main_load_library) parser_sub = subparsers.add_parser('update_tbdb', help='Pull the latest tbdb library and load', formatter_class=ArgumentDefaultsRichHelpFormatter) @@ -542,6 +550,7 @@ parser_sub.add_argument('--no_clean','--no-clean', action='store_true',help=argp parser_sub.add_argument('--temp',help="Temp firectory to process all files",type=str,default=".") parser_sub.add_argument('--version', action='version', version="tb-profiler version %s" % tbp.__version__) parser_sub.add_argument('--logging',type=str.upper,default="INFO",choices=["DEBUG","INFO","WARNING","ERROR","CRITICAL"],help='Logging level') +parser_sub.add_argument('--debug',action='store_true',help=argparse.SUPPRESS) parser_sub.set_defaults(func=main_update_tbdb) parser_sub = subparsers.add_parser('batch', help='Run tb-profiler for several samples', formatter_class=ArgumentDefaultsRichHelpFormatter) @@ -554,6 +563,7 @@ parser_sub.add_argument('--no_clean','--no-clean', action='store_true',help=argp parser_sub.add_argument('--temp',help="Temp firectory to process all files",type=str,default=".") parser_sub.add_argument('--version', action='version', version="tb-profiler version %s" % tbp.__version__) parser_sub.add_argument('--logging',type=str.upper,default="INFO",choices=["DEBUG","INFO","WARNING","ERROR","CRITICAL"],help='Logging level') +parser_sub.add_argument('--debug',action='store_true',help=argparse.SUPPRESS) parser_sub.set_defaults(func=main_batch) parser_sub = subparsers.add_parser('list_db', help='List loaded databases', formatter_class=ArgumentDefaultsRichHelpFormatter) @@ -562,6 +572,7 @@ parser_sub.add_argument('--no_clean','--no-clean', action='store_true',help=argp parser_sub.add_argument('--temp',help="Temp firectory to process all files",type=str,default=".") parser_sub.add_argument('--version', action='version', version="tb-profiler version %s" % tbp.__version__) parser_sub.add_argument('--logging',type=str.upper,default="INFO",choices=["DEBUG","INFO","WARNING","ERROR","CRITICAL"],help='Logging level') +parser_sub.add_argument('--debug',action='store_true',help=argparse.SUPPRESS) parser_sub.set_defaults(func=main_list_db) parser_sub = subparsers.add_parser('version', help='Output program version and exit', formatter_class=ArgumentDefaultsRichHelpFormatter) @@ -570,6 +581,7 @@ parser_sub.add_argument('--no_clean','--no-clean', action='store_true',help=argp parser_sub.add_argument('--temp',help="Temp firectory to process all files",type=str,default=".") parser_sub.add_argument('--version', action='version', version="tb-profiler version %s" % tbp.__version__) parser_sub.add_argument('--logging',type=str.upper,default="INFO",choices=["DEBUG","INFO","WARNING","ERROR","CRITICAL"],help='Logging level') +parser_sub.add_argument('--debug',action='store_true',help=argparse.SUPPRESS) parser_sub.set_defaults(func=main_version) From 9764fa6d3abc794e87ea8de86527fff67bd573eb Mon Sep 17 00:00:00 2001 From: Jody Phelan Date: Sun, 23 Jun 2024 14:30:04 +0200 Subject: [PATCH 10/20] update docx --- tbprofiler/docx.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/tbprofiler/docx.py b/tbprofiler/docx.py index 0925f09..fb4dc5e 100644 --- a/tbprofiler/docx.py +++ b/tbprofiler/docx.py @@ -95,14 +95,15 @@ def write_docx(result: ProfileResult,conf,outfile,template_file = None, plugin = }) gene_qc = [] - for item in result.qc.target_qc: - - gene_qc.append({ - 'status': 'ok' if item.percent_depth_pass>0.9 else 'fail', - 'gene': item.target, - 'median_depth': item.median_depth, - 'percent_depth_pass': item.percent_depth_pass, - }) + if 'target_qc' in result.qc: + for item in result.qc.target_qc: + + gene_qc.append({ + 'status': 'ok' if item.percent_depth_pass>0.9 else 'fail', + 'gene': item.target, + 'median_depth': item.median_depth, + 'percent_depth_pass': item.percent_depth_pass, + }) dr_variant_table = sorted(dr_variant_table,key=lambda x: conf['drugs'].index(x['drug'])) From e2620a576fc96fe05ddc12ea0100c4be2eec44e1 Mon Sep 17 00:00:00 2001 From: Jody Phelan Date: Mon, 24 Jun 2024 15:31:38 +0200 Subject: [PATCH 11/20] update conda env --- conda/linux-latest.txt | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/conda/linux-latest.txt b/conda/linux-latest.txt index a8cf8c0..8a4c057 100644 --- a/conda/linux-latest.txt +++ b/conda/linux-latest.txt @@ -2,9 +2,8 @@ # $ conda create --name --file # platform: linux-64 @EXPLICIT -https://conda.anaconda.org/bioconda/linux-64/seqkit-2.8.0-h9ee0642_0.tar.bz2 https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 -https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2024.2.2-hbcca054_0.conda +https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2024.6.2-hbcca054_0.conda https://conda.anaconda.org/t/no-15126f85-4dce-4462-b48d-9bc580ca6641/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 https://conda.anaconda.org/t/no-15126f85-4dce-4462-b48d-9bc580ca6641/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 https://conda.anaconda.org/t/no-15126f85-4dce-4462-b48d-9bc580ca6641/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 @@ -13,6 +12,7 @@ https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-h41732ed_0 https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-13.2.0-h7e041cc_4.conda https://conda.anaconda.org/t/no-15126f85-4dce-4462-b48d-9bc580ca6641/conda-forge/linux-64/mpi-1.0-openmpi.tar.bz2 https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.10-4_cp310.conda +https://conda.anaconda.org/bioconda/linux-64/seqkit-2.8.2-h9ee0642_0.tar.bz2 https://conda.anaconda.org/conda-forge/noarch/tzdata-2023d-h0c530f3_0.conda https://conda.anaconda.org/t/no-15126f85-4dce-4462-b48d-9bc580ca6641/conda-forge/noarch/fonts-conda-forge-1-0.tar.bz2 https://conda.anaconda.org/conda-forge/linux-64/libgomp-13.2.0-h807b86a_4.conda @@ -49,7 +49,7 @@ https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.cond https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-hd590300_5.conda https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.4-h59595ed_2.conda https://conda.anaconda.org/conda-forge/linux-64/oniguruma-6.9.9-hd590300_0.conda -https://conda.anaconda.org/conda-forge/linux-64/openssl-3.2.1-hd590300_0.conda +https://conda.anaconda.org/conda-forge/linux-64/openssl-3.3.1-h4ab18f5_0.conda https://conda.anaconda.org/conda-forge/linux-64/pixman-0.43.2-h59595ed_0.conda https://conda.anaconda.org/t/no-15126f85-4dce-4462-b48d-9bc580ca6641/conda-forge/linux-64/pthread-stubs-0.4-h36c2ea0_1001.tar.bz2 https://conda.anaconda.org/t/no-15126f85-4dce-4462-b48d-9bc580ca6641/bioconda/linux-64/wfa2-lib-2.3.4-h4ac6f70_0.tar.bz2 @@ -115,7 +115,7 @@ https://conda.anaconda.org/conda-forge/noarch/bitstring-3.1.9-pyhd8ed1ab_0.tar.b https://conda.anaconda.org/conda-forge/linux-64/brotli-1.1.0-hd590300_1.conda https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.1.0-py310hc6cd4ac_1.conda https://conda.anaconda.org/conda-forge/noarch/cachetools-4.2.4-pyhd8ed1ab_0.tar.bz2 -https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/certifi-2024.6.2-pyhd8ed1ab_0.conda https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 https://conda.anaconda.org/conda-forge/noarch/cycler-0.12.1-pyhd8ed1ab_0.conda @@ -138,10 +138,8 @@ https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.0-h488ebb8_3.conda https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda https://conda.anaconda.org/conda-forge/noarch/pycparser-2.21-pyhd8ed1ab_0.tar.bz2 https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda -https://conda.anaconda.org/conda-forge/noarch/pyparsing-3.1.2-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/pyparsing-3.1.1-pyhd8ed1ab_0.conda https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 -https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2023.4-pyhd8ed1ab_0.conda -https://conda.anaconda.org/conda-forge/noarch/pytz-2023.4-pyhd8ed1ab_0.conda https://conda.anaconda.org/conda-forge/noarch/setuptools-69.0.3-pyhd8ed1ab_0.conda https://conda.anaconda.org/t/no-15126f85-4dce-4462-b48d-9bc580ca6641/conda-forge/noarch/six-1.16.0-pyh6c4a22f_0.tar.bz2 https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 @@ -154,8 +152,9 @@ https://conda.anaconda.org/t/no-15126f85-4dce-4462-b48d-9bc580ca6641/conda-forge https://conda.anaconda.org/t/no-15126f85-4dce-4462-b48d-9bc580ca6641/conda-forge/linux-64/xorg-libxt-1.3.0-hd590300_1.conda https://conda.anaconda.org/t/no-15126f85-4dce-4462-b48d-9bc580ca6641/conda-forge/linux-64/cairo-1.18.0-h3faef2a_0.conda https://conda.anaconda.org/conda-forge/linux-64/cffi-1.16.0-py310h2fee648_0.conda +https://conda.anaconda.org/conda-forge/linux-64/curl-8.5.0-hca28451_0.conda https://conda.anaconda.org/conda-forge/noarch/deprecation-2.1.0-pyh9f0ad1d_0.tar.bz2 -https://conda.anaconda.org/conda-forge/linux-64/fonttools-4.49.0-py310h2372a71_0.conda +https://conda.anaconda.org/conda-forge/linux-64/fonttools-4.47.2-py310h2372a71_0.conda https://conda.anaconda.org/bioconda/linux-64/htslib-1.19.1-h81da01d_0.tar.bz2 https://conda.anaconda.org/bioconda/noarch/itol-config-0.1.0-pyhdfd78af_0.tar.bz2 https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda @@ -172,11 +171,12 @@ https://conda.anaconda.org/conda-forge/noarch/python-docx-1.1.0-pyhd8ed1ab_0.con https://conda.anaconda.org/conda-forge/noarch/screed-1.1.3-pyhd8ed1ab_0.conda https://conda.anaconda.org/conda-forge/noarch/tqdm-4.66.1-pyhd8ed1ab_0.conda https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.9.0-hd8ed1ab_0.conda -https://conda.anaconda.org/conda-forge/noarch/urllib3-2.1.0-pyhd8ed1ab_0.conda +https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.0-pyhd8ed1ab_0.conda https://conda.anaconda.org/t/no-15126f85-4dce-4462-b48d-9bc580ca6641/conda-forge/linux-64/xorg-libxi-1.7.10-h7f98852_0.tar.bz2 https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.6.0-pyhd8ed1ab_0.conda https://conda.anaconda.org/bioconda/linux-64/delly-1.2.6-hb7e2ac5_0.tar.bz2 https://conda.anaconda.org/t/no-15126f85-4dce-4462-b48d-9bc580ca6641/conda-forge/noarch/docxtpl-0.11.5-pyhd8ed1ab_0.tar.bz2 +https://conda.anaconda.org/conda-forge/linux-64/git-2.43.0-pl5321h7bc287a_0.conda https://conda.anaconda.org/t/no-15126f85-4dce-4462-b48d-9bc580ca6641/conda-forge/linux-64/gsl-2.7-he838d99_0.tar.bz2 https://conda.anaconda.org/conda-forge/linux-64/harfbuzz-8.3.0-h3d44ed6_0.conda https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.3-py310hb13e2d6_0.conda @@ -191,17 +191,18 @@ https://conda.anaconda.org/conda-forge/linux-64/contourpy-1.2.0-py310hd41b1e2_0. https://conda.anaconda.org/t/no-15126f85-4dce-4462-b48d-9bc580ca6641/bioconda/linux-64/lofreq-2.1.5-py310h47ef89e_10.tar.bz2 https://conda.anaconda.org/bioconda/linux-64/mash-2.3-ha9a2dd8_3.tar.bz2 https://conda.anaconda.org/t/no-15126f85-4dce-4462-b48d-9bc580ca6641/conda-forge/linux-64/openjdk-17.0.8-hbf40d96_2.conda -https://conda.anaconda.org/conda-forge/linux-64/pandas-2.2.0-py310hcc13569_0.conda https://conda.anaconda.org/conda-forge/noarch/pydantic-2.6.0-pyhd8ed1ab_0.conda https://conda.anaconda.org/conda-forge/noarch/rich-argparse-1.4.0-pyhd8ed1ab_0.conda https://conda.anaconda.org/conda-forge/linux-64/scipy-1.12.0-py310hb13e2d6_2.conda https://conda.anaconda.org/t/no-15126f85-4dce-4462-b48d-9bc580ca6641/bioconda/linux-64/tabixpp-1.1.2-hd68fcf3_1.tar.bz2 https://conda.anaconda.org/t/no-15126f85-4dce-4462-b48d-9bc580ca6641/bioconda/noarch/gatk4-4.4.0.0-py36hdfd78af_0.tar.bz2 -https://conda.anaconda.org/conda-forge/linux-64/matplotlib-base-3.8.3-py310h62c0568_0.conda +https://conda.anaconda.org/conda-forge/linux-64/matplotlib-base-3.8.2-py310h62c0568_0.conda https://conda.anaconda.org/t/no-15126f85-4dce-4462-b48d-9bc580ca6641/bioconda/noarch/pilon-1.24-hdfd78af_0.tar.bz2 https://conda.anaconda.org/bioconda/noarch/snpeff-5.2-hdfd78af_0.tar.bz2 https://conda.anaconda.org/t/no-15126f85-4dce-4462-b48d-9bc580ca6641/bioconda/noarch/trimmomatic-0.39-hdfd78af_2.tar.bz2 https://conda.anaconda.org/bioconda/linux-64/vcflib-1.0.9-h146fbdb_4.tar.bz2 https://conda.anaconda.org/bioconda/linux-64/freebayes-1.3.6-hb0f3ef8_7.tar.bz2 -https://conda.anaconda.org/conda-forge/linux-64/sourmash-minimal-4.8.6-py310h373cc83_0.conda -https://conda.anaconda.org/bioconda/noarch/sourmash-4.8.6-hdfd78af_0.tar.bz2 \ No newline at end of file +https://conda.anaconda.org/conda-forge/linux-64/sourmash-minimal-4.8.5-py310h373cc83_0.conda +https://conda.anaconda.org/bioconda/noarch/sourmash-4.8.5-hdfd78af_0.tar.bz2 +https://conda.anaconda.org/bioconda/noarch/pathogen-profiler-4.2.0-pyh7cba7a3_0.tar.bz2 +https://conda.anaconda.org/bioconda/noarch/tb-profiler-6.2.1-pyhdfd78af_0.tar.bz2 \ No newline at end of file From fc2d0fd4f606ad94d5bcb66af449f961ad511156 Mon Sep 17 00:00:00 2001 From: Jody Phelan Date: Thu, 4 Jul 2024 08:37:48 +0200 Subject: [PATCH 12/20] variant calling classes --- tb-profiler | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tb-profiler b/tb-profiler index d33320c..9917680 100644 --- a/tb-profiler +++ b/tb-profiler @@ -346,6 +346,13 @@ def int_2_or_more(arg): return i + + +variant_callers = subclasses = [cls.__software__ for cls in pp.variant_calling.VariantCaller.__subclasses__()] + + + + parser = argparse.ArgumentParser(description='tb-profiler: a tool to predict drug resistance and infer lineages',formatter_class=ArgumentDefaultsRichHelpFormatter,add_help=False) parser.add_argument('--version', action='version', version="tb-profiler version %s" % tbp.__version__) parser.add_argument('--logging',type=str.upper,default="INFO",choices=["DEBUG","INFO","WARNING","ERROR","CRITICAL"],help='Logging level') @@ -387,7 +394,7 @@ filtering.add_argument('--sv_len','--sv-len',default="100000,50000",type=str,hel algorithm=parser_sub.add_argument_group("Algorithm options") algorithm.add_argument('--mapper',default="bwa", choices=["bwa","minimap2","bowtie2","bwa-mem2"],help="Mapping tool to use. If you are using nanopore or pacbio data it will default to minimap2",type=str) -algorithm.add_argument('--caller',default="freebayes", choices=["bcftools","gatk","freebayes","pilon","lofreq"],help="Variant calling tool to use.",type=str) +algorithm.add_argument('--caller',default="freebayes", choices=variant_callers,help="Variant calling tool to use.",type=str) algorithm.add_argument('--calling_params','--calling-params',type=str,help='Override default parameters for variant calling') algorithm.add_argument('--kmer_counter','--kmer-counter',default='kmc',choices=["kmc","dsk"],type=str,help="Kmer counter") algorithm.add_argument('--coverage_tool','--coverage-tool',default='samtools',choices=["samtools","bedtools"],type=str,help="Kmer counter") From 889f2aacfaa3c464ec67bafcf6d1f0efcbdbfcd7 Mon Sep 17 00:00:00 2001 From: Jody Phelan Date: Thu, 4 Jul 2024 08:59:56 +0200 Subject: [PATCH 13/20] style --- tb-profiler | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tb-profiler b/tb-profiler index 9917680..adac1bf 100644 --- a/tb-profiler +++ b/tb-profiler @@ -348,7 +348,7 @@ def int_2_or_more(arg): -variant_callers = subclasses = [cls.__software__ for cls in pp.variant_calling.VariantCaller.__subclasses__()] +variant_callers = [cls.__software__ for cls in pp.variant_calling.VariantCaller.__subclasses__()] From bc23fd95ed42831cd2874b47ef4e0f126c6932c7 Mon Sep 17 00:00:00 2001 From: Jody Phelan Date: Thu, 4 Jul 2024 09:03:21 +0200 Subject: [PATCH 14/20] bug --- tb-profiler | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tb-profiler b/tb-profiler index adac1bf..3687324 100644 --- a/tb-profiler +++ b/tb-profiler @@ -2,6 +2,7 @@ import sys import pathogenprofiler as pp from pathogenprofiler import TempFilePrefix +import pathogenprofiler.variant_calling as vc import argparse from rich_argparse import ArgumentDefaultsRichHelpFormatter import json @@ -348,7 +349,7 @@ def int_2_or_more(arg): -variant_callers = [cls.__software__ for cls in pp.variant_calling.VariantCaller.__subclasses__()] +variant_callers = [cls.__software__ for cls in vc.VariantCaller.__subclasses__()] From e5893adfcffe6b9ef30786a489d300ccb3d1ba8b Mon Sep 17 00:00:00 2001 From: Jody Phelan Date: Thu, 4 Jul 2024 10:01:27 +0200 Subject: [PATCH 15/20] add --debug --- tb-profiler | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tb-profiler b/tb-profiler index 3687324..bfb1069 100644 --- a/tb-profiler +++ b/tb-profiler @@ -595,6 +595,8 @@ parser_sub.set_defaults(func=main_version) args = parser.parse_args() +if args.debug: + args.logging = "DEBUG" logging.basicConfig( level=args.logging, format="%(message)s", datefmt="[%X]", handlers=[RichHandler()] ) From a9f39c15d402336f5c5c5a6e62d5dc8e0ab8c49a Mon Sep 17 00:00:00 2001 From: Jody Phelan Date: Fri, 5 Jul 2024 09:46:53 +0200 Subject: [PATCH 16/20] text output bugfix --- tbprofiler/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tbprofiler/models.py b/tbprofiler/models.py index 8530971..69eba1b 100644 --- a/tbprofiler/models.py +++ b/tbprofiler/models.py @@ -114,7 +114,7 @@ def get_qc(self): def get_missing_pos(self,sep="\t"): if isinstance(self.qc, (BamQC,)): - text = dict_list2text(self.qc.missing_positions,mappings={"pos":"Genome Position","annotation.gene":"Gene","annotation.variant":"Variant", "depth":"Depth"},sep=sep) + text = object_list2text(self.qc.missing_positions,mappings={"pos":"Genome Position","annotation.gene":"Gene","annotation.variant":"Variant", "depth":"Depth"},sep=sep) else: text = "Not available for input data type" return text From 609801beeb917ed8d5fec400d22b0da87133aa8e Mon Sep 17 00:00:00 2001 From: Jody Phelan Date: Fri, 5 Jul 2024 10:54:35 +0200 Subject: [PATCH 17/20] add version to schema --- tbprofiler/models.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tbprofiler/models.py b/tbprofiler/models.py index 69eba1b..8d01c52 100644 --- a/tbprofiler/models.py +++ b/tbprofiler/models.py @@ -4,6 +4,7 @@ from pathogenprofiler.models import BamQC, FastaQC, VcfQC, Variant, DrVariant, BarcodePosition from datetime import datetime +__model_schema_version__ = '1.0' class Lineage(BaseModel): @@ -59,6 +60,7 @@ class Result(BaseModel): db_version : dict TBProfiler database version """ + schema_version: str = __model_schema_version__ id: str timestamp: datetime = Field(default_factory=datetime.now) pipeline: Pipeline From 14e51ffa7285ee48b4ac7241350c35d33582b283 Mon Sep 17 00:00:00 2001 From: Jody Phelan Date: Fri, 5 Jul 2024 15:18:48 +0200 Subject: [PATCH 18/20] update schema version --- tbprofiler/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tbprofiler/models.py b/tbprofiler/models.py index 8d01c52..0dd9323 100644 --- a/tbprofiler/models.py +++ b/tbprofiler/models.py @@ -4,7 +4,7 @@ from pathogenprofiler.models import BamQC, FastaQC, VcfQC, Variant, DrVariant, BarcodePosition from datetime import datetime -__model_schema_version__ = '1.0' +__model_schema_version__ = '1.0.0' class Lineage(BaseModel): From bda746ebe897362e1083b1535a0cce04efe92207 Mon Sep 17 00:00:00 2001 From: Jody Phelan Date: Tue, 16 Jul 2024 13:21:27 +0100 Subject: [PATCH 19/20] add variant calling classes --- tb-profiler | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tb-profiler b/tb-profiler index bfb1069..85de7cd 100644 --- a/tb-profiler +++ b/tb-profiler @@ -396,7 +396,13 @@ filtering.add_argument('--sv_len','--sv-len',default="100000,50000",type=str,hel algorithm=parser_sub.add_argument_group("Algorithm options") algorithm.add_argument('--mapper',default="bwa", choices=["bwa","minimap2","bowtie2","bwa-mem2"],help="Mapping tool to use. If you are using nanopore or pacbio data it will default to minimap2",type=str) algorithm.add_argument('--caller',default="freebayes", choices=variant_callers,help="Variant calling tool to use.",type=str) + algorithm.add_argument('--calling_params','--calling-params',type=str,help='Override default parameters for variant calling') +for cls in vc.VariantCaller.__subclasses__(): + if hasattr(cls,"__cli_params__"): + for a in cls.__cli_params__: + algorithm.add_argument(*a['args'],**a['kwargs']) + algorithm.add_argument('--kmer_counter','--kmer-counter',default='kmc',choices=["kmc","dsk"],type=str,help="Kmer counter") algorithm.add_argument('--coverage_tool','--coverage-tool',default='samtools',choices=["samtools","bedtools"],type=str,help="Kmer counter") algorithm.add_argument('--suspect',action="store_true",help="Use the suspect suite of tools to add ML predictions") @@ -427,6 +433,7 @@ other.add_argument('--version', action='version', version="tb-profiler version % parser_sub.set_defaults(func=main_profile) + parser_sub = subparsers.add_parser('lineage', help='Profile only lineage', formatter_class=ArgumentDefaultsRichHelpFormatter) parser_sub.add_argument('--bam','-a',required=True, help='BAM file. Make sure it has been generated using the H37Rv genome (GCA_000195955.2)') parser_sub.add_argument('--prefix','-p',default="tbprofiler",help='Sample prefix') From f66729f8416bd2dc0cf51a0b9aec100aeefa3c31 Mon Sep 17 00:00:00 2001 From: Jody Phelan Date: Tue, 16 Jul 2024 15:21:20 +0100 Subject: [PATCH 20/20] update version --- tbprofiler/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tbprofiler/__init__.py b/tbprofiler/__init__.py index dea95d3..5441640 100644 --- a/tbprofiler/__init__.py +++ b/tbprofiler/__init__.py @@ -7,4 +7,4 @@ from .snp_dists import * from .phylo import * -__version__ = "6.2.2" +__version__ = "6.3.0"