[med-svn] [Git][med-team/resfinder][upstream] New upstream version 4.3.0

Andreas Tille (@tille) gitlab at salsa.debian.org
Sun Feb 26 16:20:54 GMT 2023



Andreas Tille pushed to branch upstream at Debian Med / resfinder


Commits:
40f6a94d by Andreas Tille at 2023-02-26T17:13:31+01:00
New upstream version 4.3.0
- - - - -


18 changed files:

- CHANGELOG.md
- DEV_SETUP.md
- Dockerfile_no_dbs
- dockerfile
- src/resfinder/__init__.py
- src/resfinder/cge/config.py
- src/resfinder/cge/output/gene_result.py
- src/resfinder/cge/output/phenotype_result.py
- src/resfinder/cge/output/std_results.py
- src/resfinder/cge/phenotype2genotype/res_profile.py
- src/resfinder/cge/pointfinder.py
- src/resfinder/run_resfinder.py
- tests/resfinder/cge/output/test_gene_result.md
- tests/resfinder/cge/output/test_phenotype_result.md
- tests/resfinder/cge/output/test_std_results.md
- tests/resfinder/cge/phenotype2genotype/test_isolate.md
- tests/resfinder/cge/test_config.md
- + tests/resfinder/test_run_resfinder.md


Changes:

=====================================
CHANGELOG.md
=====================================
@@ -5,6 +5,22 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
+## [4.3.0] - 2023-02-09
+
+### Added
+
+- JSON output now contains the 'software_exec' class. It contains the command used to invoke ResFinder and the value of all parameters.
+- JSON output now contains 'grades' for 'seq_regions' and 'phenotypes' corresponding to the colors known from the web tool: dark green, green, grey is 3, 2, 1, respectively. Phenotypes can also be 0 if no resistance features was found. Phenotype grades will as for the webtool be the highest grade of the resistance features found.
+
+### Changed
+
+- It is no longer necessary to set the flag --ignore_missing_species if '--species other' is set
+
+### Fixed
+
+- Case where species "other" is chosen and pointfinder is run causing error phenodb.mut_type_is_defined not found
+- Alignments in json output to include missing gene parts in query string
+
 ## [4.2.5] - 2023-01-23
 
 ### Fixed


=====================================
DEV_SETUP.md
=====================================
@@ -49,8 +49,14 @@ cd /path/to/resfinder/
 # Run ResFinder
 pdm run resfinder -h
 
+# Some tests requires the following environmental variables to be set
+export CGE_BLASTN="/path/to/blastn"
+export CGE_RESFINDER_RESGENE_DB="/path/to/resfinder_db"
+export CGE_RESFINDER_RESPOINT_DB="/path/to/pointfinder_db"
+export CGE_DISINFINDER_DB="/path/to/disinfinder_db"
+
 # Run ResFinder tests
-pdm run tests
+pdm run test
 
 ```
 


=====================================
Dockerfile_no_dbs
=====================================
@@ -20,7 +20,7 @@ RUN cd /usr/src/; \
     rm -rf kma/;
 
 # Install ResFinder
-RUN pip install --no-cache-dir resfinder==4.2.1
+RUN pip install --no-cache-dir resfinder==4.3.0
 
 # Setup environment
 RUN cd /; \


=====================================
dockerfile
=====================================
@@ -20,7 +20,7 @@ RUN cd /usr/src/; \
     cd ..; \
     rm -rf kma/;
 
-ENV RESFINDER_VERSION 4.2.5
+ENV RESFINDER_VERSION 4.3.0
 
 # Install ResFinder
 RUN pip install --no-cache-dir resfinder==$RESFINDER_VERSION


=====================================
src/resfinder/__init__.py
=====================================
@@ -1 +1 @@
-__version__ = '4.2.5'
+__version__ = '4.3.0'


=====================================
src/resfinder/cge/config.py
=====================================
@@ -103,7 +103,7 @@ class Config():
     def get_species(in_species, species_def_filepath):
         out_species = in_species
         if(in_species is not None and in_species.lower() == "other"):
-            out_species = None
+            out_species = "other"
         elif(in_species is not None):
             out_species = in_species.lower()
 
@@ -235,7 +235,8 @@ class Config():
             sys.exit("ERROR: Chromosomal point mutations cannot be located if "
                      "no species has been provided. Please provide species "
                      "using the --species option.")
-        elif(not self.species and args.ignore_missing_species):
+        elif((not self.species and args.ignore_missing_species)
+                or self.species.lower() == 'other'):
             self.point = False
             return
 


=====================================
src/resfinder/cge/output/gene_result.py
=====================================
@@ -6,7 +6,7 @@ from ..phenotype2genotype.res_profile import PhenoDB
 
 
 class GeneResult(dict):
-    def __init__(self, res_collection, res, db_name, conf=None):
+    def __init__(self, res_collection, res, db_name, conf=None, alignments=None):
         """
             Input:
                 res_collection: Result object created by the cgelib package.
@@ -41,9 +41,18 @@ class GeneResult(dict):
         self["notes"] = []
 
         if conf and conf.output_aln:
-            self["query_string"] = res["query_string"]
-            self["alignment_string"] = res["homo_string"]
-            self["ref_string"] = res["sbjct_string"]
+            for ab_class, hits in alignments.gene_align_query.items():
+                ab_class_keys = list(hits.keys())
+                hit_key = next(key for key in ab_class_keys
+                               if key.startswith(self["ref_id"]))
+                hit_class = ab_class
+                break
+
+            self["query_string"] = alignments.gene_align_query[hit_class][
+                hit_key]
+            self["alignment_string"] = alignments.gene_align_homo[hit_class][
+                hit_key]
+            self["ref_string"] = alignments.gene_align_sbjct[hit_class][hit_key]
 
         # BLAST coverage formatted results
         coverage = res.get("coverage", None)
@@ -54,10 +63,21 @@ class GeneResult(dict):
             coverage = float(coverage) * 100
         self["coverage"] = coverage
 
+        self["grade"] = GeneResult.calc_gene_grade(coverage=self["coverage"], identity=self["identity"])
+
         self.remove_NAs()
         uniqueness = self._get_unique_gene_key(res_collection)
         self["key"] = uniqueness
 
+    @staticmethod
+    def calc_gene_grade(coverage: float, identity: float) -> int:
+        if coverage == 100.0 and identity == 100.0:
+            return 3
+        elif coverage == 100.0:
+            return 2
+        else:
+            return 1
+
     def remove_NAs(self):
         """
             Remove all entries containing NA og None as values.


=====================================
src/resfinder/cge/output/phenotype_result.py
=====================================
@@ -14,6 +14,7 @@ class PhenotypeResult(dict):
         self["amr_resistant"] = False
         self["amr_species_relevant"] = PhenotypeResult.get_amr_relevance(
             antibiotic.name, isolate)
+        self["grade"] = 0
 
     @staticmethod
     def get_amr_relevance(ab, isolate):
@@ -60,6 +61,14 @@ class PhenotypeResult(dict):
                 pheno_keys.append(self["key"])
             feat_result["phenotypes"] = pheno_keys
 
+            # Compare the grade of the feature with what is already recorded,
+            # keep the greater value.
+            # seq_variations has not grade value as it will always be 3
+            feat_grade = feat_result.get("grade", 3)
+            if feat_grade > self["grade"]:
+                self["grade"] = feat_grade
+
+
         # Add unique PMIDs to feature results
         if(feature.pmids is not None):
             for pmid in feature.pmids:


=====================================
src/resfinder/cge/output/std_results.py
=====================================
@@ -44,7 +44,7 @@ class ResFinderResultHandler():
 
             Method loads the given res_collection with results from res.
         """
-        for db_name, db in res.items():
+        for db_name, db in res.results.items():
             if(db_name == "excluded"):
                 continue
 
@@ -52,14 +52,13 @@ class ResFinderResultHandler():
                 continue
 
             for unique_id, hit_db in db.items():
-                if(unique_id in res["excluded"]):
+                if(unique_id in res.results["excluded"]):
                     continue
                 gene_result = GeneResult(res_collection, hit_db, ref_db_name,
-                                         conf)
+                                         conf, res)
 
                 add_gene_result_if_key_not_None(gene_result, res_collection)
 
-
     @staticmethod
     def load_res_profile(res_collection, isolate, amr_abbreviations):
         """


=====================================
src/resfinder/cge/phenotype2genotype/res_profile.py
=====================================
@@ -43,6 +43,10 @@ class PhenoDB(dict):
             eprint("ERROR: No phenotype database files where specified.")
             quit(1)
 
+        # mut_type_is_defined indicates the new pointfinder db with AA/NUC
+        # instead of DNA/RNA
+        self.mut_type_is_defined = False
+
         if(acquired_file):
             self.load_acquired_db(acquired_file)
 
@@ -51,9 +55,7 @@ class PhenoDB(dict):
             self.load_disinfectant_db(disinf_file)
 
         if(point_file):
-            # mut_type_is_defined indicates the new db with AA/NUC
-            # instead of DNA/RNA
-            self.mut_type_is_defined = False
+
             if os.path.basename(point_file) == "resistens-overview.txt":
                 self.load_point_old_db(point_file)
             else:


=====================================
src/resfinder/cge/pointfinder.py
=====================================
@@ -395,7 +395,7 @@ class PointFinder(CGEFinder):
                     # Should only be one hit (the best)
                     for hit_key, entry in hits.items():
                         known_muts = PointFinder._get_known_mis_matches(
-                            hit_key, entry["mis_matches"], phenodb)
+                            entry['sbjct_header'], entry["mis_matches"], phenodb)
                         entry["mis_matches"] = known_muts
                         gene_hits["mis_matches"] = known_muts
                 except AttributeError:
@@ -412,11 +412,8 @@ class PointFinder(CGEFinder):
 
     @staticmethod
     def _get_known_mis_matches(entry_key, mis_matches, phenodb):
-        try:
-            gene_ref_id = entry_key.split(":")[2]
-        except:
-            gene_ref_id = entry_key
-        gene_db_id = gene_ref_id.replace("_", ";;")
+
+        gene_db_id = entry_key.replace("_", ";;")
         known = []
         for mis_match in mis_matches:
             if mis_match[0] != 'sub':


=====================================
src/resfinder/run_resfinder.py
=====================================
@@ -6,6 +6,7 @@ import subprocess
 from argparse import ArgumentParser
 import pickle
 import json
+import hashlib
 
 from cgelib.output.result import Result
 from cgelib.utils.loaders_mixin import LoadersMixin
@@ -30,6 +31,23 @@ def eprint(*args, **kwargs):
     print(*args, file=sys.stderr, **kwargs)
 
 
+def get_software_exec_res(conf: Config) -> dict:
+    software_exec_res = {
+        "type": "software_exec",
+        "command": " ".join(sys.argv),
+        "parameters": get_call_parameters(conf)
+    }
+    software_exec_res["key"] = hashlib.sha1(
+        bytes(software_exec_res["command"], 'UTF-8')).hexdigest()
+    return software_exec_res
+
+
+def get_call_parameters(conf: Config) -> dict:
+    parameters = vars(conf).copy()
+    del (parameters['amr_abbreviations'])
+    return parameters
+
+
 def main():
 
     # version = read_version("VERSION")
@@ -206,13 +224,16 @@ def main():
     }
     std_result.add(**init_result_data)
 
-    if(conf.acquired):
+    if conf.acquired:
         std_result.init_database("ResFinder", conf.db_path_res)
-    if(conf.point):
+    if conf.point:
         std_result.init_database("PointFinder", conf.db_path_point_root)
-    if(conf.disinf):
+    if conf.disinf:
         std_result.init_database("DisinFinder", conf.db_path_disinf)
 
+    std_result.add_class(cl="software_executions", **
+                         get_software_exec_res(conf))
+
     # Load genotype to phenotype database
     res_pheno_db = PhenoDB(
         abclassdef_file=conf.abclassdef_file,
@@ -226,7 +247,7 @@ def main():
     # ResFinder
     ##########################################################################
 
-    if(conf.acquired is True):
+    if conf.acquired is True:
 
         blast_results = None
         kma_run = None
@@ -238,7 +259,7 @@ def main():
                                     notes=conf.db_notes_file,
                                     db_path_kma=conf.db_path_res_kma)
 
-        if(conf.inputfasta):
+        if (conf.inputfasta):
             blast_results = acquired_finder.blast(
                 inputfile=conf.inputfasta,
                 out_path=conf.outPath_res_blast,
@@ -256,12 +277,12 @@ def main():
                                           software="ResFinder")
 
             ResFinderResultHandler.standardize_results(std_result,
-                                                       blast_results.results,
+                                                       blast_results,
                                                        "ResFinder",
                                                        conf)
 
         else:
-            if(conf.nanopore):
+            if (conf.nanopore):
                 kma_run = acquired_finder.kma(
                     inputfile_1=conf.inputfastq_1,
                     inputfile_2=conf.inputfastq_2,
@@ -301,13 +322,13 @@ def main():
                                           software="ResFinder")
 
             ResFinderResultHandler.standardize_results(std_result,
-                                                       kma_run.results,
+                                                       kma_run,
                                                        "ResFinder",
                                                        conf)
     ##########################################################################
     # DisinFinder
     ##########################################################################
-    if(conf.disinf is True):
+    if (conf.disinf is True):
 
         blast_results = None
         kma_run = None
@@ -319,7 +340,7 @@ def main():
                                   notes=conf.db_notes_disinf_file,
                                   db_path_kma=conf.db_path_disinf_kma)
 
-        if(conf.inputfasta):
+        if (conf.inputfasta):
             blast_results = disinf_finder.blast(
                 inputfile=conf.inputfasta,
                 out_path=conf.outPath_disinf_blast,
@@ -337,12 +358,12 @@ def main():
                                         software="DisinFinder")
 
             ResFinderResultHandler.standardize_results(std_result,
-                                                       blast_results.results,
+                                                       blast_results,
                                                        "DisinFinder",
                                                        conf)
 
         else:
-            if(conf.nanopore):
+            if (conf.nanopore):
                 kma_run = disinf_finder.kma(
                     inputfile_1=conf.inputfastq_1,
                     inputfile_2=conf.inputfastq_2,
@@ -382,14 +403,14 @@ def main():
                                         software="DisinFinder")
 
             ResFinderResultHandler.standardize_results(std_result,
-                                                       kma_run.results,
+                                                       kma_run,
                                                        "DisinFinder",
                                                        conf)
     ##########################################################################
     # PointFinder
     ##########################################################################
 
-    if(conf.point):
+    if (conf.point):
 
         blast_results = None
         kma_run = None
@@ -400,7 +421,7 @@ def main():
                              ignore_indels=conf.ignore_indels,
                              ignore_stop_codons=conf.ignore_stop_codons)
 
-        if(conf.inputfasta):
+        if (conf.inputfasta):
 
             method = PointFinder.TYPE_BLAST
 
@@ -415,7 +436,7 @@ def main():
         else:
 
             method = PointFinder.TYPE_KMA
-            if(conf.nanopore):
+            if (conf.nanopore):
                 kma_run = finder.kma(inputfile_1=conf.inputfastq_1,
                                      inputfile_2=conf.inputfastq_2,
                                      out_path=conf.outPath_point_kma,
@@ -445,15 +466,15 @@ def main():
 
             results = kma_run.results
 
-        if(conf.specific_gene):
+        if (conf.specific_gene):
             results = PointFinder.discard_from_dict(
                 in_dict=results, wanted_list=conf.specific_gene)
 
-        if(method == PointFinder.TYPE_BLAST):
+        if (method == PointFinder.TYPE_BLAST):
             results_pnt = finder.find_best_seqs(results, conf.pf_gene_cov)
         else:
             results_pnt = results[finder.species]
-            if(results_pnt == "No hit found"):
+            if (results_pnt == "No hit found"):
                 results_pnt = {}
             else:
                 results_pnt["excluded"] = results["excluded"]
@@ -482,11 +503,11 @@ def main():
     isolate = Isolate(name=conf.sample_name, species=conf.species,
                       amr_panel_file=conf.db_panels_file)
 
-    if(conf.acquired or conf.disinf):
+    if (conf.acquired or conf.disinf):
         isolate.load_finder_results(std_table=std_result,
                                     phenodb=res_pheno_db,
                                     type="seq_regions")
-    if(conf.point):
+    if (conf.point):
         isolate.load_finder_results(std_table=std_result,
                                     phenodb=res_pheno_db,
                                     type="seq_variations")
@@ -495,7 +516,7 @@ def main():
     ResFinderResultHandler.load_res_profile(std_result, isolate,
                                             conf.amr_abbreviations)
 
-    if(conf.out_json):
+    if (conf.out_json):
         std_result_file = conf.out_json
     else:
         std_result_file = "{}/{}.json".format(
@@ -507,7 +528,7 @@ def main():
     pheno_profile_str = isolate.profile_to_str_table(header=True)
 
     # TODO: REMOVE THE NEED FOR THE PICKLED FILE
-    if(conf.pickle):
+    if (conf.pickle):
         isolate_pickle = open("{}/isolate.p".format(conf.outputPath), "wb")
         pickle.dump(isolate, isolate_pickle, protocol=2)
 
@@ -515,7 +536,7 @@ def main():
     with open(pheno_table_file, 'w') as fh:
         fh.write(pheno_profile_str)
 
-    if(conf.species is not None):
+    if (conf.species is not None):
         # Apply AMR panel
         input_amr_panels = "{}/phenotype_panels.txt".format(conf.db_path_res)
         res_sum_table = ResSumTable(pheno_profile_str)
@@ -527,8 +548,9 @@ def main():
         # If specified species does not have an associated panel, just ignore it
         # and exit.
         except PanelNameError:
-            eprint("Warning: No panel was detected for the species: {}"
-                   .format(conf.species))
+            if conf.species != 'other':
+                eprint("Warning: No panel was detected for the species: {}"
+                       .format(conf.species))
             sys.exit()
 
         amr_panel_filename = conf.species.replace(" ", "_")
@@ -542,5 +564,6 @@ def main():
 
     return 0
 
+
 if __name__ == '__main__':
     sys.exit(main())


=====================================
tests/resfinder/cge/output/test_gene_result.md
=====================================
@@ -70,15 +70,28 @@ results from a ResFinder hit.
 
 ## Methods
 
+### calc_gene_grade(coverage: float, identity: float) -> int
+
+```python
+
+>>> GeneResult.calc_gene_grade(coverage=100, identity=100)
+3
+>>> GeneResult.calc_gene_grade(coverage=100, identity=22.5)
+2
+>>> GeneResult.calc_gene_grade(coverage=10.1, identity=0)
+1
+
+```
+
 ### remove_NAs()
 
 ```python
 
-res["test_NA"] = "NA"
-res["test_None"] = None
-res.remove_NAs()
-assert("test_NA" not in res)
-assert("test_None" not in res)
+>>> gene_result_blast["test_NA"] = "NA"
+>>> gene_result_blast["test_None"] = None
+>>> gene_result_blast.remove_NAs()
+>>> assert("test_NA" not in gene_result_blast)
+>>> assert("test_None" not in gene_result_blast)
 
 ```
 


=====================================
tests/resfinder/cge/output/test_phenotype_result.md
=====================================
@@ -71,7 +71,8 @@
 ...  "ref_acc": "KF986263",
 ...  "ref_start_pos": 1,
 ...  "ref_end_pos": 100,
-...  "ref_database": ["ResFinder-unknown"]
+...  "ref_database": ["ResFinder-unknown"],
+...  "grade": 1
 ... }
 
 >>> gyra = {
@@ -91,7 +92,8 @@
 ...   'query_start_pos': 1,
 ...   'query_end_pos': 2628,
 ...   'ref_database': ['PointFinder-a2b2ce4'],
-...   'coverage': 100.0
+...   'coverage': 100.0,
+...   'grade': 2
 ... }
 
 >>> pg81d = {
@@ -211,8 +213,12 @@ True
 ['blaOXA-384;;1;;KF986263']
 >>> res["phenotypes"]["carbapenem"]["amr_classes"]
 ['beta-lactam']
+>>> res["phenotypes"]["carbapenem"]["grade"]
+1
 >>> res["seq_regions"]["blaOXA-384;;1;;KF986263"]["phenotypes"]
 ['carbapenem']
+>>> res["seq_regions"]["blaOXA-384;;1;;KF986263"]["grade"]
+1
 
 >>> pheno2 = PhenotypeResult(ab_m1, isolate)
 >>> pheno2.set_resistant(True)


=====================================
tests/resfinder/cge/output/test_std_results.md
=====================================
@@ -56,6 +56,8 @@ hit.
 
 >>> from cgelib.output.result import Result
 >>> from src.resfinder.cge.output.gene_result import GeneResult
+>>> from cgecore.blaster.blaster import Blaster
+>>> import os
 
 >>> res = Result.init_software_result(name="ResFinder", gitdir=".")
 >>> res.init_database("ResFinder", ".")
@@ -73,24 +75,13 @@ Here a dummy hit (obtained using KMA) is created, named rf\_dat\_kma. It is stor
 rf\_custom\_kma.
 
 ```python
+import tempfile
 
->>> rf_dat_kma = {}
->>> rf_dat_kma["sbjct_header"] = "blaOXA-384_1_KF986263"
->>> rf_dat_kma["perc_ident"] = 97
->>> rf_dat_kma["HSP_length"] = 100
->>> rf_dat_kma["sbjct_length"] = 90
->>> rf_dat_kma["sbjct_start"] = 1
->>> rf_dat_kma["sbjct_end"] = 90
->>> rf_dat_kma["contig_name"] = "NA"
->>> rf_dat_kma["query_start"] = "NA"
->>> rf_dat_kma["query_end"] = "NA"
->>> rf_dat_kma["perc_coverage"] = 100
->>> rf_dat_kma["depth"] = 21
-
->>> rf_custom_kma = {}
->>> rf_custom_kma["excluded"] = {}
->>> rf_custom_kma["aminoglycoside"] = "No hit found"
->>> rf_custom_kma["beta-lactam"] = {"unique_hit_key": rf_dat_kma}
+>>> resfinder_db_path = os.environ["CGE_RESFINDER_RESGENE_DB"]
+>>> blast_path = os.environ["CGE_BLASTN"]
+>>> rf_custom_kma = Blaster(inputfile="tests/data/test_isolate_01.fa", databases=["beta-lactam"], db_path=resfinder_db_path, out_path="tests/tmp_out", blast=blast_path)
+... #doctest: +ELLIPSIS
+Found...
 
 ```
 
@@ -207,7 +198,7 @@ PointFinder-...
 
 >>> for k in res["seq_regions"]:
 ...   print(k)
-blaOXA-384;;1;;KF986263
+blaB-2;;1;;AF189300
 
 ```
 
@@ -247,9 +238,9 @@ Create Isolate object
 >>> from src.resfinder.cge.output.std_results import PointFinderResultHandler
 >>> ResFinderResultHandler.load_res_profile(res, isolate, amr_abbreviations)
 >>> res["phenotypes"]["ampicillin"]["seq_regions"]
-[]
+['blaB-2;;1;;AF189300']
 >>> res["result_summary"]
-'UBE'
+'AMO_AMP_TIC'
 
 ```
 
@@ -271,7 +262,7 @@ PointFinder-...
 
 >>> for k in res["seq_regions"]:
 ...   print(k)
-blaOXA-384;;1;;KF986263
+blaB-2;;1;;AF189300
 gyrA;;1;;CP073768.1
 
 >>> for k in res["seq_variations"]:
@@ -345,6 +336,6 @@ gyrA;;1;;CP073768.1;;82;;g
 
 >>> sum_str = ResFinderResultHandler.create_amr_summary_str(res, amr_abbreviations)
 >>> sum_str
-'AML_IMI_UBE'
+'AMO_AMP_AML_IMI_TIC'
 
 ```


=====================================
tests/resfinder/cge/phenotype2genotype/test_isolate.md
=====================================
@@ -72,23 +72,31 @@ std_results test documentation.
 
 ```python
 
->>> rf_dat_kma = {}
->>> rf_dat_kma["sbjct_header"] = "blaOXA-384_1_KF986263"
->>> rf_dat_kma["perc_ident"] = 97
->>> rf_dat_kma["HSP_length"] = 100
->>> rf_dat_kma["sbjct_length"] = 90
->>> rf_dat_kma["sbjct_start"] = 1
->>> rf_dat_kma["sbjct_end"] = 90
->>> rf_dat_kma["contig_name"] = "NA"
->>> rf_dat_kma["query_start"] = "NA"
->>> rf_dat_kma["query_end"] = "NA"
->>> rf_dat_kma["perc_coverage"] = 100
->>> rf_dat_kma["depth"] = 21
-
->>> rf_custom_kma = {}
->>> rf_custom_kma["excluded"] = {}
->>> rf_custom_kma["aminoglycoside"] = "No hit found"
->>> rf_custom_kma["beta-lactam"] = {"unique_hit_key": rf_dat_kma}
+# >>> rf_dat_kma = {}
+# >>> rf_dat_kma["sbjct_header"] = "blaOXA-384_1_KF986263"
+# >>> rf_dat_kma["perc_ident"] = 97
+# >>> rf_dat_kma["HSP_length"] = 100
+# >>> rf_dat_kma["sbjct_length"] = 90
+# >>> rf_dat_kma["sbjct_start"] = 1
+# >>> rf_dat_kma["sbjct_end"] = 90
+# >>> rf_dat_kma["contig_name"] = "NA"
+# >>> rf_dat_kma["query_start"] = "NA"
+# >>> rf_dat_kma["query_end"] = "NA"
+# >>> rf_dat_kma["perc_coverage"] = 100
+# >>> rf_dat_kma["depth"] = 21
+# 
+# >>> rf_custom_kma = {}
+# >>> rf_custom_kma["excluded"] = {}
+# >>> rf_custom_kma["aminoglycoside"] = "No hit found"
+# >>> rf_custom_kma["beta-lactam"] = {"unique_hit_key": rf_dat_kma}
+>>> from cgecore.blaster.blaster import Blaster
+>>> import os
+>>> import tempfile
+
+>>> resfinder_db_path = os.environ["CGE_RESFINDER_RESGENE_DB"]
+>>> rf_custom_kma = Blaster(inputfile="tests/data/test_isolate_01.fa", databases=["beta-lactam"], db_path=resfinder_db_path, out_path="tests/tmp_out")
+... #doctest: +ELLIPSIS
+Found...
 
 >>> gyrA_kma_hit = {}
 >>> gyrA_kma_hit["sbjct_header"] = "gyrA_1_CP073768.1"
@@ -182,7 +190,7 @@ False
 >>> isolate.load_finder_results(std_table=res, phenodb=res_pheno_db,
 ...                             type="seq_variations")
 
->>> isolate["blaOXA-384_KF986263"][0].ab_class.pop()
+>>> isolate["blaB-2_AF189300"][0].ab_class.pop()
 'beta-lactam'
 >>> isolate["gyrA;;1;;CP073768.1_81_d"][0].ref_codon
 'ggt'
@@ -211,9 +219,9 @@ False
 
 ```python
 
->>> feat_res_dict = res["seq_regions"]["blaOXA-384;;1;;KF986263"]
+>>> feat_res_dict = res["seq_regions"]["blaB-2;;1;;AF189300"]
 >>> Isolate.get_phenodb_id(feat_res_dict, "seq_regions")
-('blaOXA-384_KF986263', '')
+('blaB-2_AF189300', '')
 
 >>> feat_res_dict = res["seq_variations"]["gyrA;;1;;CP073768.1;;81;;d"]
 >>> Isolate.get_phenodb_id(feat_res_dict, "seq_variations")


=====================================
tests/resfinder/cge/test_config.md
=====================================
@@ -70,7 +70,7 @@
 >>> args.point = False
 >>> conf = Config(args)
 >>> print(conf.species)
-None
+other
 >>> conf.amr_abbreviations["Amoxicillin"][0]
 'AMO'
 
@@ -156,7 +156,7 @@ SystemExit: ERROR: Path not found: /file/not/found
 'escherichia coli'
 
 >>> str(Config.get_species("Other", species_def_filepath))
-'None'
+'other'
 
 
 ```


=====================================
tests/resfinder/test_run_resfinder.md
=====================================
@@ -0,0 +1,73 @@
+# PointFinder class tests
+
+This is only testing a very small fraction of the run_resfinder.
+
+## Setup
+
+```python
+
+>>> from src.resfinder.run_resfinder import *
+>>> from src.resfinder.cge.config import Config
+
+>>> class DummyArgs():
+...     def __init__(self):
+...         self.inputfasta = None
+...         self.inputfastq = None
+...         self.outputPath = "./tests/tmp_out/"
+...         self.blastPath = None
+...         self.kmaPath = None
+...         self.species = None
+...         self.ignore_missing_species = None
+...         self.db_path_res = None
+...         self.db_path_res_kma = None
+...         self.databases = None
+...         self.acquired = True
+...         self.acq_overlap = None
+...         self.min_cov = None
+...         self.threshold = None
+...         self.point = True
+...         self.db_path_point = None
+...         self.db_path_point_kma = None
+...         self.specific_gene = None
+...         self.unknown_mut = None
+...         self.min_cov_point = None
+...         self.threshold_point = None
+...         self.ignore_indels = None
+...         self.ignore_stop_codons = None
+...         self.pickle = False
+...         self.nanopore = False
+...         self.out_json = None
+...         self.disinfectant = False
+...         self.db_path_disinf = None
+...         self.db_path_disinf_kma = None
+...         self.output_aln = False
+...         self.species = "ecoli"
+
+>>> args = DummyArgs()
+>>> conf = Config(args)
+
+```
+
+## get_call_parameters(conf: Config) -> dict
+
+```python
+
+>>> parameters = get_call_parameters(conf=conf)
+>>> parameters["species"]
+'escherichia coli'
+>>> parameters["acquired"]
+True
+
+```
+
+## get_software_exec_res(conf: Config) -> dict
+
+```python
+
+>>> soft_exec = get_software_exec_res(conf=conf)
+>>> soft_exec["type"]
+'software_exec'
+>>> len(soft_exec["key"])
+40
+
+```



View it on GitLab: https://salsa.debian.org/med-team/resfinder/-/commit/40f6a94da50fb636e91422e7fb57543645689957

-- 
View it on GitLab: https://salsa.debian.org/med-team/resfinder/-/commit/40f6a94da50fb636e91422e7fb57543645689957
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20230226/4229b216/attachment-0001.htm>


More information about the debian-med-commit mailing list