From 2b62c557ae409008b3fd158473be8cb5dbf1ee1e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 20 Aug 2026 12:30:29 +0000 Subject: [PATCH] Python wrapper update --- AMR.egg-info/PKG-INFO | 254 +++++++ AMR.egg-info/SOURCES.txt | 12 + AMR.egg-info/dependency_links.txt | 1 + AMR.egg-info/requires.txt | 3 + AMR.egg-info/top_level.txt | 1 + AMR/__init__.py | 249 +++++++ AMR/_engine.py | 93 +++ AMR/beta.py | 22 + AMR/datasets.py | 54 ++ AMR/functions.py | 984 +++++++++++++++++++++++++++ README.md | 226 ++++++ dist/amr-3.0.1.9087-py3-none-any.whl | Bin 0 -> 13407 bytes dist/amr-3.0.1.9087.tar.gz | Bin 0 -> 12655 bytes setup.py | 27 + 14 files changed, 1926 insertions(+) create mode 100644 AMR.egg-info/PKG-INFO create mode 100644 AMR.egg-info/SOURCES.txt create mode 100644 AMR.egg-info/dependency_links.txt create mode 100644 AMR.egg-info/requires.txt create mode 100644 AMR.egg-info/top_level.txt create mode 100644 AMR/__init__.py create mode 100644 AMR/_engine.py create mode 100644 AMR/beta.py create mode 100644 AMR/datasets.py create mode 100644 AMR/functions.py create mode 100755 README.md create mode 100644 dist/amr-3.0.1.9087-py3-none-any.whl create mode 100644 dist/amr-3.0.1.9087.tar.gz create mode 100644 setup.py diff --git a/AMR.egg-info/PKG-INFO b/AMR.egg-info/PKG-INFO new file mode 100644 index 000000000..8bc02eda9 --- /dev/null +++ b/AMR.egg-info/PKG-INFO @@ -0,0 +1,254 @@ +Metadata-Version: 2.4 +Name: AMR +Version: 3.0.1.9087 +Summary: A Python wrapper for the AMR R package +Home-page: https://github.com/msberends/AMR +Author: Matthijs Berends +Author-email: m.s.berends@umcg.nl +License: GPL 2 +Project-URL: Bug Tracker, https://github.com/msberends/AMR/issues +Classifier: Programming Language :: Python :: 3 +Classifier: Operating System :: OS Independent +Requires-Python: >=3.6 +Description-Content-Type: text/markdown +Requires-Dist: rpy2 +Requires-Dist: numpy +Requires-Dist: pandas +Dynamic: author +Dynamic: author-email +Dynamic: classifier +Dynamic: description +Dynamic: description-content-type +Dynamic: home-page +Dynamic: license +Dynamic: project-url +Dynamic: requires-dist +Dynamic: requires-python +Dynamic: summary + + +The `AMR` package for R is a powerful tool for antimicrobial resistance (AMR) analysis. It provides extensive features for handling microbial and antimicrobial data. However, for those who work primarily in Python, we now have a more intuitive option available: the [`AMR` Python package](https://pypi.org/project/AMR/). + +This Python package is a wrapper around the `AMR` R package. It uses the `rpy2` package internally. Despite the need to have R installed, Python users can now easily work with AMR data directly through Python code. + +# Prerequisites + +This package was only tested with a [virtual environment (venv)](https://docs.python.org/3/library/venv.html). You can set up such an environment by running: + +```python +# linux and macOS: +python -m venv /path/to/new/virtual/environment + +# Windows: +python -m venv C:\path\to\new\virtual\environment +``` + +Then you can [activate the environment](https://docs.python.org/3/library/venv.html#how-venvs-work), after which the venv is ready to work with. + +# Install AMR + +1. Since the Python package is available on the official [Python Package Index](https://pypi.org/project/AMR/), you can just run: + + ```bash + pip install AMR + ``` + +2. Make sure you have R installed. There is **no need to install the `AMR` R package**, as it will be installed automatically. + + For Linux: + + ```bash + # Ubuntu / Debian + sudo apt install r-base + # Fedora: + sudo dnf install R + # CentOS/RHEL + sudo yum install R + ``` + + For macOS (using [Homebrew](https://brew.sh)): + + ```bash + brew install r + ``` + + For Windows, visit the [CRAN download page](https://cran.r-project.org) to download and install R. + +# Examples of Usage + +## Cleaning Taxonomy + +Here’s an example that demonstrates how to clean microorganism and drug names using the `AMR` Python package: + +```python +import pandas as pd +import AMR + +# Sample data +data = { + "MOs": ['E. coli', 'ESCCOL', 'esco', 'Esche coli'], + "Drug": ['Cipro', 'CIP', 'J01MA02', 'Ciproxin'] +} +df = pd.DataFrame(data) + +# Use AMR functions to clean microorganism and drug names +df['MO_clean'] = AMR.mo_name(df['MOs']) +df['Drug_clean'] = AMR.ab_name(df['Drug']) + +# Display the results +print(df) +``` + +| MOs | Drug | MO_clean | Drug_clean | +|-------------|-----------|--------------------|---------------| +| E. coli | Cipro | Escherichia coli | Ciprofloxacin | +| ESCCOL | CIP | Escherichia coli | Ciprofloxacin | +| esco | J01MA02 | Escherichia coli | Ciprofloxacin | +| Esche coli | Ciproxin | Escherichia coli | Ciprofloxacin | + +### Explanation + +* **mo_name:** This function standardises microorganism names. Here, different variations of *Escherichia coli* (such as "E. coli", "ESCCOL", "esco", and "Esche coli") are all converted into the correct, standardised form, "Escherichia coli". + +* **ab_name**: Similarly, this function standardises antimicrobial names. The different representations of ciprofloxacin (e.g., "Cipro", "CIP", "J01MA02", and "Ciproxin") are all converted to the standard name, "Ciprofloxacin". + +## Calculating AMR + +```python +import AMR +import pandas as pd + +df = AMR.example_isolates +result = AMR.resistance(df["AMX"]) +print(result) +``` + +``` +[0.59555556] +``` + +## Generating Antibiograms + +One of the core functions of the `AMR` package is generating an antibiogram, a table that summarises the antimicrobial susceptibility of bacterial isolates. Here’s how you can generate an antibiogram from Python: + +```python +result2a = AMR.antibiogram(df[["mo", "AMX", "CIP", "TZP"]]) +print(result2a) +``` + +| Pathogen | Amoxicillin | Ciprofloxacin | Piperacillin/tazobactam | +|-----------------|-----------------|-----------------|--------------------------| +| CoNS | 7% (10/142) | 73% (183/252) | 30% (10/33) | +| E. coli | 50% (196/392) | 88% (399/456) | 94% (393/416) | +| K. pneumoniae | 0% (0/58) | 96% (53/55) | 89% (47/53) | +| P. aeruginosa | 0% (0/30) | 100% (30/30) | None | +| P. mirabilis | None | 94% (34/36) | None | +| S. aureus | 6% (8/131) | 90% (171/191) | None | +| S. epidermidis | 1% (1/91) | 64% (87/136) | None | +| S. hominis | None | 80% (56/70) | None | +| S. pneumoniae | 100% (112/112) | None | 100% (112/112) | + + +```python +result2b = AMR.antibiogram(df[["mo", "AMX", "CIP", "TZP"]], mo_transform = "gramstain") +print(result2b) +``` + +| Pathogen | Amoxicillin | Ciprofloxacin | Piperacillin/tazobactam | +|----------------|-----------------|------------------|--------------------------| +| Gram-negative | 36% (226/631) | 91% (621/684) | 88% (565/641) | +| Gram-positive | 43% (305/703) | 77% (560/724) | 86% (296/345) | + + +In this example, we generate an antibiogram by selecting various antibiotics. + +## Taxonomic Data Sets Now in Python! + +As a Python user, you might like that the most important data sets of the `AMR` R package, `microorganisms`, `antimicrobials`, `clinical_breakpoints`, and `example_isolates`, are now available as regular Python data frames: + +```python +AMR.microorganisms +``` + +| mo | fullname | status | kingdom | gbif | gbif_parent | gbif_renamed_to | prevalence | +|--------------|------------------------------------|----------|----------|-----------|-------------|-----------------|------------| +| B_GRAMN | (unknown Gram-negatives) | unknown | Bacteria | None | None | None | 2.0 | +| B_GRAMP | (unknown Gram-positives) | unknown | Bacteria | None | None | None | 2.0 | +| B_ANAER-NEG | (unknown anaerobic Gram-negatives) | unknown | Bacteria | None | None | None | 2.0 | +| B_ANAER-POS | (unknown anaerobic Gram-positives) | unknown | Bacteria | None | None | None | 2.0 | +| B_ANAER | (unknown anaerobic bacteria) | unknown | Bacteria | None | None | None | 2.0 | +| ... | ... | ... | ... | ... | ... | ... | ... | +| B_ZYMMN_POMC | Zymomonas pomaceae | accepted | Bacteria | 10744418 | 3221412 | None | 2.0 | +| B_ZYMPH | Zymophilus | synonym | Bacteria | None | 9475166 | None | 2.0 | +| B_ZYMPH_PCVR | Zymophilus paucivorans | synonym | Bacteria | None | None | None | 2.0 | +| B_ZYMPH_RFFN | Zymophilus raffinosivorans | synonym | Bacteria | None | None | None | 2.0 | +| F_ZYZYG | Zyzygomyces | unknown | Fungi | None | 7581 | None | 2.0 | + +```python +AMR.antimicrobials +``` + +| ab | cid | name | group | oral_ddd | oral_units | iv_ddd | iv_units | +|-----|-------------|----------------------|----------------------------|----------|------------|--------|----------| +| AMA | 4649.0 | 4-aminosalicylic acid| Antimycobacterials | 12.00 | g | NaN | None | +| ACM | 6450012.0 | Acetylmidecamycin | Macrolides/lincosamides | NaN | None | NaN | None | +| ASP | 49787020.0 | Acetylspiramycin | Macrolides/lincosamides | NaN | None | NaN | None | +| ALS | 8954.0 | Aldesulfone sodium | Other antibacterials | 0.33 | g | NaN | None | +| AMK | 37768.0 | Amikacin | Aminoglycosides | NaN | None | 1.0 | g | +| ... | ... | ... | ... | ... | ... | ... | ... | +| VIR | 11979535.0 | Virginiamycine | Other antibacterials | NaN | None | NaN | None | +| VOR | 71616.0 | Voriconazole | Antifungals/antimycotics | 0.40 | g | 0.4 | g | +| XBR | 72144.0 | Xibornol | Other antibacterials | NaN | None | NaN | None | +| ZID | 77846445.0 | Zidebactam | Other antibacterials | NaN | None | NaN | None | +| ZFD | NaN | Zoliflodacin | None | NaN | None | NaN | None | + + +# Installation Channels + +## Stable Release (CRAN) + +The default `AMR` Python package uses the latest stable version of the `AMR` R package, published on CRAN. After running `pip install AMR`, import it as usual: + +```python +import AMR + +AMR.example_isolates +``` + +## Development Version (GitHub) + +To use the latest development version of the `AMR` R package (sourced directly from GitHub), import the `beta` sub-package and alias it as `AMR`: + +```python +import AMR.beta as AMR + +AMR.example_isolates +``` + +Aliasing with `as AMR` keeps all downstream code identical to the stable import. Switching between the stable release and the development version requires changing only the import line — nothing else in your script needs to change. + +# SIR Classification with `as_sir()` + +## Using `enforce_method` + +The `as_sir()` function in R uses S3 method dispatch to select the correct calculation method based on the input class: `` for MIC values and `` for disk diffusion values. Because Python objects do not carry R class attributes through the `rpy2` bridge, this automatic dispatch may not resolve correctly. + +To explicitly specify the input type, use the `enforce_method` argument: + +```python +# Treat the column as MIC values — maps to R's as.sir.mic() +AMR.as_sir(df["MIC_col"], mo="E. coli", ab="AMX", guideline="EUCAST", enforce_method="mic") + +# Treat the column as disk diffusion values — maps to R's as.sir.disk() +AMR.as_sir(df["disk_col"], mo="E. coli", ab="AMX", guideline="EUCAST", enforce_method="disk") +``` + +Without `enforce_method`, R falls back to class-based dispatch on the raw Python input, which may fail or return unexpected results. Always supply `enforce_method` when calling `as_sir()` from Python. + +# Conclusion + +With the `AMR` Python package, Python users can now effortlessly call R functions from the `AMR` R package. This eliminates the need for complex `rpy2` configurations and provides a clean, easy-to-use interface for antimicrobial resistance analysis. The examples provided above demonstrate how this can be applied to typical workflows, such as standardising microorganism and antimicrobial names or calculating resistance. + +By just running `import AMR`, users can seamlessly integrate the robust features of the R `AMR` package into Python workflows. + +Whether you're cleaning data or analysing resistance patterns, the `AMR` Python package makes it easy to work with AMR data in Python. diff --git a/AMR.egg-info/SOURCES.txt b/AMR.egg-info/SOURCES.txt new file mode 100644 index 000000000..617d18f78 --- /dev/null +++ b/AMR.egg-info/SOURCES.txt @@ -0,0 +1,12 @@ +README.md +setup.py +AMR/__init__.py +AMR/_engine.py +AMR/beta.py +AMR/datasets.py +AMR/functions.py +AMR.egg-info/PKG-INFO +AMR.egg-info/SOURCES.txt +AMR.egg-info/dependency_links.txt +AMR.egg-info/requires.txt +AMR.egg-info/top_level.txt \ No newline at end of file diff --git a/AMR.egg-info/dependency_links.txt b/AMR.egg-info/dependency_links.txt new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/AMR.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/AMR.egg-info/requires.txt b/AMR.egg-info/requires.txt new file mode 100644 index 000000000..fb2bcf682 --- /dev/null +++ b/AMR.egg-info/requires.txt @@ -0,0 +1,3 @@ +rpy2 +numpy +pandas diff --git a/AMR.egg-info/top_level.txt b/AMR.egg-info/top_level.txt new file mode 100644 index 000000000..18f3926f7 --- /dev/null +++ b/AMR.egg-info/top_level.txt @@ -0,0 +1 @@ +AMR diff --git a/AMR/__init__.py b/AMR/__init__.py new file mode 100644 index 000000000..741874607 --- /dev/null +++ b/AMR/__init__.py @@ -0,0 +1,249 @@ +import sys + +_DATASETS = frozenset({ + 'example_isolates', 'microorganisms', + 'antimicrobials', 'clinical_breakpoints' +}) + +class _AMRModule(type(sys.modules[__name__])): + """Lazy-loading module: nothing runs until an attribute is accessed.""" + + def __getattr__(self, name): + if name in _DATASETS: + from .datasets import get + return get(name, source="cran") + try: + from . import functions + return getattr(functions, name) + except AttributeError: + raise AttributeError( + f"module 'AMR' has no attribute '{name}'") + +sys.modules[__name__].__class__ = _AMRModule +from .functions import custom_eucast_rules +from .functions import ab_class +from .functions import ab_selector +from .functions import ab_from_text +from .functions import ab_name +from .functions import ab_cid +from .functions import ab_synonyms +from .functions import ab_tradenames +from .functions import ab_group +from .functions import ab_atc +from .functions import ab_atc_group1 +from .functions import ab_atc_group2 +from .functions import ab_loinc +from .functions import ab_ddd +from .functions import ab_ddd_units +from .functions import ab_info +from .functions import ab_url +from .functions import ab_property +from .functions import add_custom_antimicrobials +from .functions import clear_custom_antimicrobials +from .functions import add_custom_microorganisms +from .functions import clear_custom_microorganisms +from .functions import age +from .functions import age_groups +from .functions import all_sir +from .functions import all_sir_predictors +from .functions import all_mic +from .functions import all_mic_predictors +from .functions import all_disk +from .functions import all_disk_predictors +from .functions import step_mic_log2 +from .functions import step_sir_numeric +from .functions import amr_course +from .functions import wisca +from .functions import antibiogram +from .functions import retrieve_wisca_parameters +from .functions import wisca_plot +from .functions import aminoglycosides +from .functions import aminopenicillins +from .functions import antifungals +from .functions import antimycobacterials +from .functions import betalactams +from .functions import betalactams_with_inhibitor +from .functions import carbapenems +from .functions import cephalosporins +from .functions import cephalosporins_1st +from .functions import cephalosporins_2nd +from .functions import cephalosporins_3rd +from .functions import cephalosporins_4th +from .functions import cephalosporins_5th +from .functions import fluoroquinolones +from .functions import glycopeptides +from .functions import ionophores +from .functions import isoxazolylpenicillins +from .functions import lincosamides +from .functions import lipoglycopeptides +from .functions import macrolides +from .functions import monobactams +from .functions import nitrofurans +from .functions import oxazolidinones +from .functions import penicillins +from .functions import peptides +from .functions import phenicols +from .functions import phosphonics +from .functions import polymyxins +from .functions import quinolones +from .functions import rifamycins +from .functions import spiropyrimidinetriones +from .functions import streptogramins +from .functions import sulfonamides +from .functions import tetracyclines +from .functions import trimethoprims +from .functions import ureidopenicillins +from .functions import amr_class +from .functions import amr_selector +from .functions import administrable_per_os +from .functions import administrable_iv +from .functions import not_intrinsic_resistant +from .functions import as_ab +from .functions import is_ab +from .functions import ab_reset_session +from .functions import as_av +from .functions import is_av +from .functions import as_disk +from .functions import is_disk +from .functions import as_mic +from .functions import is_mic +from .functions import rescale_mic +from .functions import mic_p50 +from .functions import mic_p90 +from .functions import as_mo +from .functions import is_mo +from .functions import mo_uncertainties +from .functions import mo_renamed +from .functions import mo_failures +from .functions import mo_reset_session +from .functions import mo_cleaning_regex +from .functions import as_sir +from .functions import is_sir +from .functions import is_sir_eligible +from .functions import sir_interpretation_history +from .functions import atc_online_property +from .functions import atc_online_groups +from .functions import atc_online_ddd +from .functions import atc_online_ddd_units +from .functions import av_from_text +from .functions import av_name +from .functions import av_cid +from .functions import av_synonyms +from .functions import av_tradenames +from .functions import av_group +from .functions import av_atc +from .functions import av_loinc +from .functions import av_ddd +from .functions import av_ddd_units +from .functions import av_info +from .functions import av_url +from .functions import av_property +from .functions import availability +from .functions import bug_drug_combinations +from .functions import count_resistant +from .functions import count_susceptible +from .functions import count_S +from .functions import count_SI +from .functions import count_I +from .functions import count_IR +from .functions import count_R +from .functions import count_all +from .functions import n_sir +from .functions import count_df +from .functions import custom_interpretive_rules +from .functions import custom_mdro_guideline +from .functions import export_ncbi_biosample +from .functions import first_isolate +from .functions import filter_first_isolate +from .functions import g_test +from .functions import is_new_episode +from .functions import ggplot_pca +from .functions import ggplot_sir +from .functions import geom_sir +from .functions import guess_ab_col +from .functions import interpretive_rules +from .functions import eucast_rules +from .functions import clsi_rules +from .functions import eucast_dosage +from .functions import italicise_taxonomy +from .functions import italicize_taxonomy +from .functions import inner_join_microorganisms +from .functions import left_join_microorganisms +from .functions import right_join_microorganisms +from .functions import full_join_microorganisms +from .functions import semi_join_microorganisms +from .functions import anti_join_microorganisms +from .functions import key_antimicrobials +from .functions import all_antimicrobials +from .functions import kurtosis +from .functions import like +from .functions import mdro +from .functions import brmo +from .functions import mrgn +from .functions import mdr_tb +from .functions import mdr_cmi2012 +from .functions import eucast_exceptional_phenotypes +from .functions import mean_amr_distance +from .functions import amr_distance_from_row +from .functions import mo_matching_score +from .functions import mo_name +from .functions import mo_fullname +from .functions import mo_shortname +from .functions import mo_subspecies +from .functions import mo_species +from .functions import mo_genus +from .functions import mo_family +from .functions import mo_order +from .functions import mo_class +from .functions import mo_phylum +from .functions import mo_kingdom +from .functions import mo_domain +from .functions import mo_type +from .functions import mo_status +from .functions import mo_pathogenicity +from .functions import mo_gramstain +from .functions import mo_is_gram_negative +from .functions import mo_is_gram_positive +from .functions import mo_is_yeast +from .functions import mo_is_intrinsic_resistant +from .functions import mo_oxygen_tolerance +from .functions import mo_is_anaerobic +from .functions import mo_morphology +from .functions import mo_snomed +from .functions import mo_ref +from .functions import mo_authors +from .functions import mo_year +from .functions import mo_lpsn +from .functions import mo_mycobank +from .functions import mo_gbif +from .functions import mo_rank +from .functions import mo_taxonomy +from .functions import mo_synonyms +from .functions import mo_current +from .functions import mo_group_members +from .functions import mo_info +from .functions import mo_url +from .functions import mo_property +from .functions import pca +from .functions import theme_sir +from .functions import labels_sir_count +from .functions import resistance +from .functions import susceptibility +from .functions import sir_confidence_interval +from .functions import proportion_R +from .functions import proportion_IR +from .functions import proportion_I +from .functions import proportion_SI +from .functions import proportion_S +from .functions import proportion_df +from .functions import sir_df +from .functions import random_mic +from .functions import random_disk +from .functions import random_sir +from .functions import resistance_predict +from .functions import sir_predict +from .functions import ggplot_sir_predict +from .functions import skewness +from .functions import top_n_microorganisms +from .functions import reset_AMR_locale +from .functions import translate_AMR diff --git a/AMR/_engine.py b/AMR/_engine.py new file mode 100644 index 000000000..cc6c5d9ff --- /dev/null +++ b/AMR/_engine.py @@ -0,0 +1,93 @@ +import os +import sys +import importlib.metadata as metadata + +# Get the path to the virtual environment +venv_path = sys.prefix +r_lib_path = os.path.join(venv_path, "R_libs") +os.makedirs(r_lib_path, exist_ok=True) + +# Set environment variable before importing rpy2 +os.environ['R_LIBS_SITE'] = r_lib_path + +from rpy2 import robjects +from rpy2.robjects.vectors import StrVector +from rpy2.robjects.packages import importr, isinstalled + +# Import base and utils once +base = importr('base') +utils = importr('utils') + +# Silence R console output entirely +robjects.r('suppressMessages(suppressWarnings(sink(tempfile())))') +base._libPaths(r_lib_path) + +_installed_source = None + +def _r_version(): + """Return the currently installed AMR R package version, or None.""" + try: + return str(robjects.r( + f'as.character(packageVersion("AMR", lib.loc = "{r_lib_path}"))')[0]) + except Exception: + return None + +def _py_version(): + """Return the Python AMR package version from metadata, or empty string.""" + try: + return str(metadata.version('AMR')) + except metadata.PackageNotFoundError: + return '' + +def _install_cran(): + """Install AMR from CRAN into the isolated library.""" + print("AMR: Installing from CRAN...", flush=True) + utils.install_packages( + 'AMR', + repos='https://cloud.r-project.org', + lib=r_lib_path, + quiet=True + ) + +def _install_github(): + """Install AMR development version from GitHub into the isolated library.""" + print("AMR: Installing development version from GitHub...", flush=True) + utils.install_packages( + StrVector(['remotes', 'desc']), + repos='https://cloud.r-project.org', + lib=r_lib_path, + quiet=True + ) + remotes = importr('remotes', lib_loc=r_lib_path) + remotes.install_github('msberends/AMR', lib=r_lib_path, quiet=True) + +def ensure_amr(source="cran"): + """Ensure AMR is installed from the requested source. Idempotent per source.""" + global _installed_source + + if _installed_source == source: + return + + install_fn = _install_github if source == "github" else _install_cran + + if not isinstalled('AMR', lib_loc=r_lib_path): + install_fn() + else: + # Check for version mismatch and update if needed + r_ver = _r_version() + py_ver = _py_version() + if r_ver != py_ver: + try: + install_fn() + except Exception as e: + print(f"AMR: Could not update ({e})", flush=True) + + print(f"AMR: R package version {_r_version()} ready.", flush=True) + _installed_source = source + +def restore_sink(): + """Restore R console output after setup is complete.""" + try: + robjects.r('sink()') + except Exception: + pass diff --git a/AMR/beta.py b/AMR/beta.py new file mode 100644 index 000000000..df55d4f81 --- /dev/null +++ b/AMR/beta.py @@ -0,0 +1,22 @@ +import sys + +_DATASETS = frozenset({ + 'example_isolates', 'microorganisms', + 'antimicrobials', 'clinical_breakpoints' +}) + +class _BetaModule(type(sys.modules[__name__])): + """Lazy-loading module: installs AMR from GitHub on first access.""" + + def __getattr__(self, name): + if name in _DATASETS: + from .datasets import get + return get(name, source="github") + try: + from . import functions + return getattr(functions, name) + except AttributeError: + raise AttributeError( + f"module 'AMR.beta' has no attribute '{name}'") + +sys.modules[__name__].__class__ = _BetaModule diff --git a/AMR/datasets.py b/AMR/datasets.py new file mode 100644 index 000000000..1c84065e7 --- /dev/null +++ b/AMR/datasets.py @@ -0,0 +1,54 @@ +import pandas as pd +from rpy2 import robjects +from rpy2.robjects.conversion import localconverter +from rpy2.robjects import default_converter, numpy2ri, pandas2ri + +from ._engine import ensure_amr, restore_sink + +_cache = {} +_loaded_source = None + +def _load_datasets(source="cran"): + """Load all AMR datasets into the module cache.""" + global _loaded_source + + if _cache and _loaded_source == source: + return + + if _cache and _loaded_source != source: + _cache.clear() + + ensure_amr(source) + + with localconverter(default_converter + numpy2ri.converter + pandas2ri.converter): + _cache['example_isolates'] = _load_example_isolates() + _cache['microorganisms'] = robjects.r( + 'AMR::microorganisms[, !sapply(AMR::microorganisms, is.list)]') + _cache['antimicrobials'] = robjects.r( + 'AMR::antimicrobials[, !sapply(AMR::antimicrobials, is.list)]') + _cache['clinical_breakpoints'] = robjects.r( + 'AMR::clinical_breakpoints[, !sapply(AMR::clinical_breakpoints, is.list)]') + + restore_sink() + _loaded_source = source + +def _load_example_isolates(): + df = robjects.r(''' + df <- AMR::example_isolates + df[] <- lapply(df, function(x) { + if (inherits(x, c("Date", "POSIXt", "factor"))) { + as.character(x) + } else { + x + } + }) + df <- df[, !sapply(df, is.list)] + df + ''') + df['date'] = pd.to_datetime(df['date']) + return df + +def get(name, source="cran"): + """Retrieve a dataset by name, installing AMR if needed.""" + _load_datasets(source) + return _cache[name] diff --git a/AMR/functions.py b/AMR/functions.py new file mode 100644 index 000000000..d8eef8f9b --- /dev/null +++ b/AMR/functions.py @@ -0,0 +1,984 @@ +import functools +import rpy2.robjects as robjects +from rpy2.robjects.packages import importr +from rpy2.robjects.vectors import StrVector, FactorVector, IntVector, FloatVector, DataFrame +from rpy2.robjects.conversion import localconverter +from rpy2.robjects import default_converter, numpy2ri, pandas2ri +import pandas as pd +import numpy as np + +from ._engine import ensure_amr + +# Ensure AMR is available before importing it in R +ensure_amr("cran") +amr_r = importr('AMR') + +def convert_to_r(value): + """Convert Python lists/tuples to typed R vectors. + + rpy2's default_converter passes Python lists to R as R lists, not as + character/numeric vectors. This causes element-wise type-check functions + such as is.mic(), is.sir(), and is.disk() to return a logical vector + rather than a single logical, breaking R's scalar && operator. + + This helper converts Python lists and tuples to the appropriate R vector + type based on the element types, so R always receives a proper vector.""" + if isinstance(value, (list, tuple)): + if len(value) == 0: + return StrVector([]) + # bool must be checked before int because bool is a subclass of int + if all(isinstance(v, bool) for v in value): + return robjects.vectors.BoolVector(value) + if all(isinstance(v, int) for v in value): + return IntVector(value) + if all(isinstance(v, float) for v in value): + return FloatVector(value) + if all(isinstance(v, str) for v in value): + return StrVector(value) + # Mixed types: coerce all to string + return StrVector([str(v) for v in value]) + return value + +def convert_to_python(r_output): + # Check if it's a StrVector (R character vector) + if isinstance(r_output, StrVector): + return list(r_output) # Convert to a Python list of strings + + # Check if it's a FactorVector (R factor) + elif isinstance(r_output, FactorVector): + return list(r_output) # Convert to a list of integers (factor levels) + + # Check if it's an IntVector or FloatVector (numeric R vectors) + elif isinstance(r_output, (IntVector, FloatVector)): + return list(r_output) # Convert to a Python list of integers or floats + + # Check if it's a pandas-compatible R data frame + elif isinstance(r_output, (pd.DataFrame, DataFrame)): + return r_output # Return as pandas DataFrame (already converted by pandas2ri) + + # Check if the input is a NumPy array and has a string data type + if isinstance(r_output, np.ndarray) and np.issubdtype(r_output.dtype, np.str_): + return r_output.tolist() # Convert to a regular Python list + + # Fall-back + return r_output + +def r_to_python(r_func): + """Decorator that converts Python list/tuple inputs to typed R vectors, + runs the rpy2 function under a localconverter, and converts the output + to a Python type.""" + @functools.wraps(r_func) + def wrapper(*args, **kwargs): + args = tuple(convert_to_r(a) for a in args) + kwargs = {k: convert_to_r(v) for k, v in kwargs.items()} + with localconverter(default_converter + numpy2ri.converter + pandas2ri.converter): + return convert_to_python(r_func(*args, **kwargs)) + return wrapper +@r_to_python +def custom_eucast_rules(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.custom_eucast_rules(*args, **kwargs) +@r_to_python +def ab_class(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.ab_class(*args, **kwargs) +@r_to_python +def ab_selector(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.ab_selector(*args, **kwargs) +@r_to_python +def ab_from_text(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.ab_from_text(*args, **kwargs) +@r_to_python +def ab_name(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.ab_name(x, *args, **kwargs) +@r_to_python +def ab_cid(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.ab_cid(x, *args, **kwargs) +@r_to_python +def ab_synonyms(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.ab_synonyms(x, *args, **kwargs) +@r_to_python +def ab_tradenames(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.ab_tradenames(x, *args, **kwargs) +@r_to_python +def ab_group(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.ab_group(x, *args, **kwargs) +@r_to_python +def ab_atc(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.ab_atc(x, *args, **kwargs) +@r_to_python +def ab_atc_group1(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.ab_atc_group1(x, *args, **kwargs) +@r_to_python +def ab_atc_group2(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.ab_atc_group2(x, *args, **kwargs) +@r_to_python +def ab_loinc(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.ab_loinc(x, *args, **kwargs) +@r_to_python +def ab_ddd(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.ab_ddd(x, *args, **kwargs) +@r_to_python +def ab_ddd_units(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.ab_ddd_units(x, *args, **kwargs) +@r_to_python +def ab_info(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.ab_info(x, *args, **kwargs) +@r_to_python +def ab_url(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.ab_url(x, *args, **kwargs) +@r_to_python +def ab_property(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.ab_property(x, *args, **kwargs) +@r_to_python +def add_custom_antimicrobials(x): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.add_custom_antimicrobials(x) +@r_to_python +def clear_custom_antimicrobials(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.clear_custom_antimicrobials(*args, **kwargs) +@r_to_python +def add_custom_microorganisms(x): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.add_custom_microorganisms(x) +@r_to_python +def clear_custom_microorganisms(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.clear_custom_microorganisms(*args, **kwargs) +@r_to_python +def age(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.age(x, *args, **kwargs) +@r_to_python +def age_groups(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.age_groups(x, *args, **kwargs) +@r_to_python +def all_sir(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.all_sir(*args, **kwargs) +@r_to_python +def all_sir_predictors(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.all_sir_predictors(*args, **kwargs) +@r_to_python +def all_mic(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.all_mic(*args, **kwargs) +@r_to_python +def all_mic_predictors(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.all_mic_predictors(*args, **kwargs) +@r_to_python +def all_disk(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.all_disk(*args, **kwargs) +@r_to_python +def all_disk_predictors(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.all_disk_predictors(*args, **kwargs) +@r_to_python +def step_mic_log2(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.step_mic_log2(*args, **kwargs) +@r_to_python +def step_sir_numeric(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.step_sir_numeric(*args, **kwargs) +@r_to_python +def amr_course(github_repo, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.amr_course(github_repo, *args, **kwargs) +@r_to_python +def wisca(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.wisca(*args, **kwargs) +@r_to_python +def antibiogram(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.antibiogram(*args, **kwargs) +@r_to_python +def retrieve_wisca_parameters(wisca_model, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.retrieve_wisca_parameters(wisca_model, *args, **kwargs) +@r_to_python +def wisca_plot(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.wisca_plot(*args, **kwargs) +@r_to_python +def aminoglycosides(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.aminoglycosides(*args, **kwargs) +@r_to_python +def aminopenicillins(only_sir_columns = False, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.aminopenicillins(only_sir_columns = False, *args, **kwargs) +@r_to_python +def antifungals(only_sir_columns = False, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.antifungals(only_sir_columns = False, *args, **kwargs) +@r_to_python +def antimycobacterials(only_sir_columns = False, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.antimycobacterials(only_sir_columns = False, *args, **kwargs) +@r_to_python +def betalactams(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.betalactams(*args, **kwargs) +@r_to_python +def betalactams_with_inhibitor(only_sir_columns = False, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.betalactams_with_inhibitor(only_sir_columns = False, *args, **kwargs) +@r_to_python +def carbapenems(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.carbapenems(*args, **kwargs) +@r_to_python +def cephalosporins(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.cephalosporins(*args, **kwargs) +@r_to_python +def cephalosporins_1st(only_sir_columns = False, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.cephalosporins_1st(only_sir_columns = False, *args, **kwargs) +@r_to_python +def cephalosporins_2nd(only_sir_columns = False, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.cephalosporins_2nd(only_sir_columns = False, *args, **kwargs) +@r_to_python +def cephalosporins_3rd(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.cephalosporins_3rd(*args, **kwargs) +@r_to_python +def cephalosporins_4th(only_sir_columns = False, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.cephalosporins_4th(only_sir_columns = False, *args, **kwargs) +@r_to_python +def cephalosporins_5th(only_sir_columns = False, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.cephalosporins_5th(only_sir_columns = False, *args, **kwargs) +@r_to_python +def fluoroquinolones(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.fluoroquinolones(*args, **kwargs) +@r_to_python +def glycopeptides(only_sir_columns = False, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.glycopeptides(only_sir_columns = False, *args, **kwargs) +@r_to_python +def ionophores(only_sir_columns = False, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.ionophores(only_sir_columns = False, *args, **kwargs) +@r_to_python +def isoxazolylpenicillins(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.isoxazolylpenicillins(*args, **kwargs) +@r_to_python +def lincosamides(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.lincosamides(*args, **kwargs) +@r_to_python +def lipoglycopeptides(only_sir_columns = False, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.lipoglycopeptides(only_sir_columns = False, *args, **kwargs) +@r_to_python +def macrolides(only_sir_columns = False, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.macrolides(only_sir_columns = False, *args, **kwargs) +@r_to_python +def monobactams(only_sir_columns = False, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.monobactams(only_sir_columns = False, *args, **kwargs) +@r_to_python +def nitrofurans(only_sir_columns = False, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.nitrofurans(only_sir_columns = False, *args, **kwargs) +@r_to_python +def oxazolidinones(only_sir_columns = False, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.oxazolidinones(only_sir_columns = False, *args, **kwargs) +@r_to_python +def penicillins(only_sir_columns = False, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.penicillins(only_sir_columns = False, *args, **kwargs) +@r_to_python +def peptides(only_sir_columns = False, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.peptides(only_sir_columns = False, *args, **kwargs) +@r_to_python +def phenicols(only_sir_columns = False, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.phenicols(only_sir_columns = False, *args, **kwargs) +@r_to_python +def phosphonics(only_sir_columns = False, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.phosphonics(only_sir_columns = False, *args, **kwargs) +@r_to_python +def polymyxins(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.polymyxins(*args, **kwargs) +@r_to_python +def quinolones(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.quinolones(*args, **kwargs) +@r_to_python +def rifamycins(only_sir_columns = False, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.rifamycins(only_sir_columns = False, *args, **kwargs) +@r_to_python +def spiropyrimidinetriones(only_sir_columns = False, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.spiropyrimidinetriones(only_sir_columns = False, *args, **kwargs) +@r_to_python +def streptogramins(only_sir_columns = False, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.streptogramins(only_sir_columns = False, *args, **kwargs) +@r_to_python +def sulfonamides(only_sir_columns = False, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.sulfonamides(only_sir_columns = False, *args, **kwargs) +@r_to_python +def tetracyclines(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.tetracyclines(*args, **kwargs) +@r_to_python +def trimethoprims(only_sir_columns = False, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.trimethoprims(only_sir_columns = False, *args, **kwargs) +@r_to_python +def ureidopenicillins(only_sir_columns = False, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.ureidopenicillins(only_sir_columns = False, *args, **kwargs) +@r_to_python +def amr_class(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.amr_class(*args, **kwargs) +@r_to_python +def amr_selector(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.amr_selector(*args, **kwargs) +@r_to_python +def administrable_per_os(only_sir_columns = False, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.administrable_per_os(only_sir_columns = False, *args, **kwargs) +@r_to_python +def administrable_iv(only_sir_columns = False, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.administrable_iv(only_sir_columns = False, *args, **kwargs) +@r_to_python +def not_intrinsic_resistant(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.not_intrinsic_resistant(*args, **kwargs) +@r_to_python +def as_ab(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.as_ab(*args, **kwargs) +@r_to_python +def is_ab(x): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.is_ab(x) +@r_to_python +def ab_reset_session(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.ab_reset_session(*args, **kwargs) +@r_to_python +def as_av(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.as_av(x, *args, **kwargs) +@r_to_python +def is_av(x): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.is_av(x) +@r_to_python +def as_disk(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.as_disk(x, *args, **kwargs) +@r_to_python +def is_disk(x): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.is_disk(x) +@r_to_python +def as_mic(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.as_mic(x, *args, **kwargs) +@r_to_python +def is_mic(x): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.is_mic(x) +@r_to_python +def rescale_mic(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.rescale_mic(*args, **kwargs) +@r_to_python +def mic_p50(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mic_p50(x, *args, **kwargs) +@r_to_python +def mic_p90(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mic_p90(x, *args, **kwargs) +@r_to_python +def as_mo(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.as_mo(*args, **kwargs) +@r_to_python +def is_mo(x): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.is_mo(x) +@r_to_python +def mo_uncertainties(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_uncertainties(*args, **kwargs) +@r_to_python +def mo_renamed(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_renamed(*args, **kwargs) +@r_to_python +def mo_failures(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_failures(*args, **kwargs) +@r_to_python +def mo_reset_session(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_reset_session(*args, **kwargs) +@r_to_python +def mo_cleaning_regex(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_cleaning_regex(*args, **kwargs) +@r_to_python +def as_sir(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.as_sir(x, *args, **kwargs) +@r_to_python +def is_sir(x): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.is_sir(x) +@r_to_python +def is_sir_eligible(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.is_sir_eligible(x, *args, **kwargs) +@r_to_python +def sir_interpretation_history(clean): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.sir_interpretation_history(clean) +@r_to_python +def atc_online_property(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.atc_online_property(*args, **kwargs) +@r_to_python +def atc_online_groups(atc_code, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.atc_online_groups(atc_code, *args, **kwargs) +@r_to_python +def atc_online_ddd(atc_code, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.atc_online_ddd(atc_code, *args, **kwargs) +@r_to_python +def atc_online_ddd_units(atc_code, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.atc_online_ddd_units(atc_code, *args, **kwargs) +@r_to_python +def av_from_text(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.av_from_text(*args, **kwargs) +@r_to_python +def av_name(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.av_name(x, *args, **kwargs) +@r_to_python +def av_cid(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.av_cid(x, *args, **kwargs) +@r_to_python +def av_synonyms(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.av_synonyms(x, *args, **kwargs) +@r_to_python +def av_tradenames(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.av_tradenames(x, *args, **kwargs) +@r_to_python +def av_group(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.av_group(x, *args, **kwargs) +@r_to_python +def av_atc(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.av_atc(x, *args, **kwargs) +@r_to_python +def av_loinc(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.av_loinc(x, *args, **kwargs) +@r_to_python +def av_ddd(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.av_ddd(x, *args, **kwargs) +@r_to_python +def av_ddd_units(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.av_ddd_units(x, *args, **kwargs) +@r_to_python +def av_info(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.av_info(x, *args, **kwargs) +@r_to_python +def av_url(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.av_url(x, *args, **kwargs) +@r_to_python +def av_property(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.av_property(x, *args, **kwargs) +@r_to_python +def availability(tbl, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.availability(tbl, *args, **kwargs) +@r_to_python +def bug_drug_combinations(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.bug_drug_combinations(*args, **kwargs) +@r_to_python +def count_resistant(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.count_resistant(*args, **kwargs) +@r_to_python +def count_susceptible(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.count_susceptible(*args, **kwargs) +@r_to_python +def count_S(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.count_S(*args, **kwargs) +@r_to_python +def count_SI(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.count_SI(*args, **kwargs) +@r_to_python +def count_I(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.count_I(*args, **kwargs) +@r_to_python +def count_IR(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.count_IR(*args, **kwargs) +@r_to_python +def count_R(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.count_R(*args, **kwargs) +@r_to_python +def count_all(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.count_all(*args, **kwargs) +@r_to_python +def n_sir(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.n_sir(*args, **kwargs) +@r_to_python +def count_df(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.count_df(*args, **kwargs) +@r_to_python +def custom_interpretive_rules(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.custom_interpretive_rules(*args, **kwargs) +@r_to_python +def custom_mdro_guideline(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.custom_mdro_guideline(*args, **kwargs) +@r_to_python +def export_ncbi_biosample(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.export_ncbi_biosample(*args, **kwargs) +@r_to_python +def first_isolate(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.first_isolate(*args, **kwargs) +@r_to_python +def filter_first_isolate(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.filter_first_isolate(*args, **kwargs) +@r_to_python +def g_test(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.g_test(x, *args, **kwargs) +@r_to_python +def is_new_episode(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.is_new_episode(x, *args, **kwargs) +@r_to_python +def ggplot_pca(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.ggplot_pca(*args, **kwargs) +@r_to_python +def ggplot_sir(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.ggplot_sir(*args, **kwargs) +@r_to_python +def geom_sir(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.geom_sir(*args, **kwargs) +@r_to_python +def guess_ab_col(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.guess_ab_col(*args, **kwargs) +@r_to_python +def interpretive_rules(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.interpretive_rules(*args, **kwargs) +@r_to_python +def eucast_rules(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.eucast_rules(*args, **kwargs) +@r_to_python +def clsi_rules(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.clsi_rules(*args, **kwargs) +@r_to_python +def eucast_dosage(ab, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.eucast_dosage(ab, *args, **kwargs) +@r_to_python +def italicise_taxonomy(string, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.italicise_taxonomy(string, *args, **kwargs) +@r_to_python +def italicize_taxonomy(string, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.italicize_taxonomy(string, *args, **kwargs) +@r_to_python +def inner_join_microorganisms(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.inner_join_microorganisms(x, *args, **kwargs) +@r_to_python +def left_join_microorganisms(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.left_join_microorganisms(x, *args, **kwargs) +@r_to_python +def right_join_microorganisms(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.right_join_microorganisms(x, *args, **kwargs) +@r_to_python +def full_join_microorganisms(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.full_join_microorganisms(x, *args, **kwargs) +@r_to_python +def semi_join_microorganisms(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.semi_join_microorganisms(x, *args, **kwargs) +@r_to_python +def anti_join_microorganisms(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.anti_join_microorganisms(x, *args, **kwargs) +@r_to_python +def key_antimicrobials(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.key_antimicrobials(*args, **kwargs) +@r_to_python +def all_antimicrobials(x = None, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.all_antimicrobials(x = None, *args, **kwargs) +@r_to_python +def kurtosis(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.kurtosis(x, *args, **kwargs) +@r_to_python +def like(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.like(x, *args, **kwargs) +@r_to_python +def mdro(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mdro(*args, **kwargs) +@r_to_python +def brmo(x = None, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.brmo(x = None, *args, **kwargs) +@r_to_python +def mrgn(x = None, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mrgn(x = None, *args, **kwargs) +@r_to_python +def mdr_tb(x = None, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mdr_tb(x = None, *args, **kwargs) +@r_to_python +def mdr_cmi2012(x = None, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mdr_cmi2012(x = None, *args, **kwargs) +@r_to_python +def eucast_exceptional_phenotypes(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.eucast_exceptional_phenotypes(*args, **kwargs) +@r_to_python +def mean_amr_distance(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mean_amr_distance(x, *args, **kwargs) +@r_to_python +def amr_distance_from_row(amr_distance, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.amr_distance_from_row(amr_distance, *args, **kwargs) +@r_to_python +def mo_matching_score(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_matching_score(x, *args, **kwargs) +@r_to_python +def mo_name(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_name(*args, **kwargs) +@r_to_python +def mo_fullname(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_fullname(*args, **kwargs) +@r_to_python +def mo_shortname(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_shortname(*args, **kwargs) +@r_to_python +def mo_subspecies(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_subspecies(*args, **kwargs) +@r_to_python +def mo_species(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_species(*args, **kwargs) +@r_to_python +def mo_genus(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_genus(*args, **kwargs) +@r_to_python +def mo_family(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_family(*args, **kwargs) +@r_to_python +def mo_order(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_order(*args, **kwargs) +@r_to_python +def mo_class(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_class(*args, **kwargs) +@r_to_python +def mo_phylum(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_phylum(*args, **kwargs) +@r_to_python +def mo_kingdom(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_kingdom(*args, **kwargs) +@r_to_python +def mo_domain(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_domain(*args, **kwargs) +@r_to_python +def mo_type(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_type(*args, **kwargs) +@r_to_python +def mo_status(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_status(*args, **kwargs) +@r_to_python +def mo_pathogenicity(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_pathogenicity(*args, **kwargs) +@r_to_python +def mo_gramstain(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_gramstain(*args, **kwargs) +@r_to_python +def mo_is_gram_negative(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_is_gram_negative(*args, **kwargs) +@r_to_python +def mo_is_gram_positive(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_is_gram_positive(*args, **kwargs) +@r_to_python +def mo_is_yeast(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_is_yeast(*args, **kwargs) +@r_to_python +def mo_is_intrinsic_resistant(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_is_intrinsic_resistant(*args, **kwargs) +@r_to_python +def mo_oxygen_tolerance(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_oxygen_tolerance(*args, **kwargs) +@r_to_python +def mo_is_anaerobic(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_is_anaerobic(*args, **kwargs) +@r_to_python +def mo_morphology(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_morphology(*args, **kwargs) +@r_to_python +def mo_snomed(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_snomed(*args, **kwargs) +@r_to_python +def mo_ref(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_ref(*args, **kwargs) +@r_to_python +def mo_authors(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_authors(*args, **kwargs) +@r_to_python +def mo_year(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_year(*args, **kwargs) +@r_to_python +def mo_lpsn(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_lpsn(*args, **kwargs) +@r_to_python +def mo_mycobank(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_mycobank(*args, **kwargs) +@r_to_python +def mo_gbif(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_gbif(*args, **kwargs) +@r_to_python +def mo_rank(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_rank(*args, **kwargs) +@r_to_python +def mo_taxonomy(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_taxonomy(*args, **kwargs) +@r_to_python +def mo_synonyms(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_synonyms(*args, **kwargs) +@r_to_python +def mo_current(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_current(x, *args, **kwargs) +@r_to_python +def mo_group_members(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_group_members(*args, **kwargs) +@r_to_python +def mo_info(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_info(*args, **kwargs) +@r_to_python +def mo_url(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_url(*args, **kwargs) +@r_to_python +def mo_property(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.mo_property(*args, **kwargs) +@r_to_python +def pca(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.pca(*args, **kwargs) +@r_to_python +def theme_sir(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.theme_sir(*args, **kwargs) +@r_to_python +def labels_sir_count(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.labels_sir_count(*args, **kwargs) +@r_to_python +def resistance(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.resistance(*args, **kwargs) +@r_to_python +def susceptibility(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.susceptibility(*args, **kwargs) +@r_to_python +def sir_confidence_interval(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.sir_confidence_interval(*args, **kwargs) +@r_to_python +def proportion_R(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.proportion_R(*args, **kwargs) +@r_to_python +def proportion_IR(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.proportion_IR(*args, **kwargs) +@r_to_python +def proportion_I(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.proportion_I(*args, **kwargs) +@r_to_python +def proportion_SI(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.proportion_SI(*args, **kwargs) +@r_to_python +def proportion_S(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.proportion_S(*args, **kwargs) +@r_to_python +def proportion_df(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.proportion_df(*args, **kwargs) +@r_to_python +def sir_df(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.sir_df(*args, **kwargs) +@r_to_python +def random_mic(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.random_mic(*args, **kwargs) +@r_to_python +def random_disk(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.random_disk(*args, **kwargs) +@r_to_python +def random_sir(size = None, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.random_sir(size = None, *args, **kwargs) +@r_to_python +def resistance_predict(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.resistance_predict(*args, **kwargs) +@r_to_python +def sir_predict(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.sir_predict(*args, **kwargs) +@r_to_python +def ggplot_sir_predict(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.ggplot_sir_predict(*args, **kwargs) +@r_to_python +def skewness(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.skewness(x, *args, **kwargs) +@r_to_python +def top_n_microorganisms(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.top_n_microorganisms(*args, **kwargs) +@r_to_python +def reset_AMR_locale(*args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.reset_AMR_locale(*args, **kwargs) +@r_to_python +def translate_AMR(x, *args, **kwargs): + """Please see our website of the R package for the full manual: https://amr-for-r.org""" + return amr_r.translate_AMR(x, *args, **kwargs) diff --git a/README.md b/README.md new file mode 100755 index 000000000..0e944d21f --- /dev/null +++ b/README.md @@ -0,0 +1,226 @@ + +The `AMR` package for R is a powerful tool for antimicrobial resistance (AMR) analysis. It provides extensive features for handling microbial and antimicrobial data. However, for those who work primarily in Python, we now have a more intuitive option available: the [`AMR` Python package](https://pypi.org/project/AMR/). + +This Python package is a wrapper around the `AMR` R package. It uses the `rpy2` package internally. Despite the need to have R installed, Python users can now easily work with AMR data directly through Python code. + +# Prerequisites + +This package was only tested with a [virtual environment (venv)](https://docs.python.org/3/library/venv.html). You can set up such an environment by running: + +```python +# linux and macOS: +python -m venv /path/to/new/virtual/environment + +# Windows: +python -m venv C:\path\to\new\virtual\environment +``` + +Then you can [activate the environment](https://docs.python.org/3/library/venv.html#how-venvs-work), after which the venv is ready to work with. + +# Install AMR + +1. Since the Python package is available on the official [Python Package Index](https://pypi.org/project/AMR/), you can just run: + + ```bash + pip install AMR + ``` + +2. Make sure you have R installed. There is **no need to install the `AMR` R package**, as it will be installed automatically. + + For Linux: + + ```bash + # Ubuntu / Debian + sudo apt install r-base + # Fedora: + sudo dnf install R + # CentOS/RHEL + sudo yum install R + ``` + + For macOS (using [Homebrew](https://brew.sh)): + + ```bash + brew install r + ``` + + For Windows, visit the [CRAN download page](https://cran.r-project.org) to download and install R. + +# Examples of Usage + +## Cleaning Taxonomy + +Here’s an example that demonstrates how to clean microorganism and drug names using the `AMR` Python package: + +```python +import pandas as pd +import AMR + +# Sample data +data = { + "MOs": ['E. coli', 'ESCCOL', 'esco', 'Esche coli'], + "Drug": ['Cipro', 'CIP', 'J01MA02', 'Ciproxin'] +} +df = pd.DataFrame(data) + +# Use AMR functions to clean microorganism and drug names +df['MO_clean'] = AMR.mo_name(df['MOs']) +df['Drug_clean'] = AMR.ab_name(df['Drug']) + +# Display the results +print(df) +``` + +| MOs | Drug | MO_clean | Drug_clean | +|-------------|-----------|--------------------|---------------| +| E. coli | Cipro | Escherichia coli | Ciprofloxacin | +| ESCCOL | CIP | Escherichia coli | Ciprofloxacin | +| esco | J01MA02 | Escherichia coli | Ciprofloxacin | +| Esche coli | Ciproxin | Escherichia coli | Ciprofloxacin | + +### Explanation + +* **mo_name:** This function standardises microorganism names. Here, different variations of *Escherichia coli* (such as "E. coli", "ESCCOL", "esco", and "Esche coli") are all converted into the correct, standardised form, "Escherichia coli". + +* **ab_name**: Similarly, this function standardises antimicrobial names. The different representations of ciprofloxacin (e.g., "Cipro", "CIP", "J01MA02", and "Ciproxin") are all converted to the standard name, "Ciprofloxacin". + +## Calculating AMR + +```python +import AMR +import pandas as pd + +df = AMR.example_isolates +result = AMR.resistance(df["AMX"]) +print(result) +``` + +``` +[0.59555556] +``` + +## Generating Antibiograms + +One of the core functions of the `AMR` package is generating an antibiogram, a table that summarises the antimicrobial susceptibility of bacterial isolates. Here’s how you can generate an antibiogram from Python: + +```python +result2a = AMR.antibiogram(df[["mo", "AMX", "CIP", "TZP"]]) +print(result2a) +``` + +| Pathogen | Amoxicillin | Ciprofloxacin | Piperacillin/tazobactam | +|-----------------|-----------------|-----------------|--------------------------| +| CoNS | 7% (10/142) | 73% (183/252) | 30% (10/33) | +| E. coli | 50% (196/392) | 88% (399/456) | 94% (393/416) | +| K. pneumoniae | 0% (0/58) | 96% (53/55) | 89% (47/53) | +| P. aeruginosa | 0% (0/30) | 100% (30/30) | None | +| P. mirabilis | None | 94% (34/36) | None | +| S. aureus | 6% (8/131) | 90% (171/191) | None | +| S. epidermidis | 1% (1/91) | 64% (87/136) | None | +| S. hominis | None | 80% (56/70) | None | +| S. pneumoniae | 100% (112/112) | None | 100% (112/112) | + + +```python +result2b = AMR.antibiogram(df[["mo", "AMX", "CIP", "TZP"]], mo_transform = "gramstain") +print(result2b) +``` + +| Pathogen | Amoxicillin | Ciprofloxacin | Piperacillin/tazobactam | +|----------------|-----------------|------------------|--------------------------| +| Gram-negative | 36% (226/631) | 91% (621/684) | 88% (565/641) | +| Gram-positive | 43% (305/703) | 77% (560/724) | 86% (296/345) | + + +In this example, we generate an antibiogram by selecting various antibiotics. + +## Taxonomic Data Sets Now in Python! + +As a Python user, you might like that the most important data sets of the `AMR` R package, `microorganisms`, `antimicrobials`, `clinical_breakpoints`, and `example_isolates`, are now available as regular Python data frames: + +```python +AMR.microorganisms +``` + +| mo | fullname | status | kingdom | gbif | gbif_parent | gbif_renamed_to | prevalence | +|--------------|------------------------------------|----------|----------|-----------|-------------|-----------------|------------| +| B_GRAMN | (unknown Gram-negatives) | unknown | Bacteria | None | None | None | 2.0 | +| B_GRAMP | (unknown Gram-positives) | unknown | Bacteria | None | None | None | 2.0 | +| B_ANAER-NEG | (unknown anaerobic Gram-negatives) | unknown | Bacteria | None | None | None | 2.0 | +| B_ANAER-POS | (unknown anaerobic Gram-positives) | unknown | Bacteria | None | None | None | 2.0 | +| B_ANAER | (unknown anaerobic bacteria) | unknown | Bacteria | None | None | None | 2.0 | +| ... | ... | ... | ... | ... | ... | ... | ... | +| B_ZYMMN_POMC | Zymomonas pomaceae | accepted | Bacteria | 10744418 | 3221412 | None | 2.0 | +| B_ZYMPH | Zymophilus | synonym | Bacteria | None | 9475166 | None | 2.0 | +| B_ZYMPH_PCVR | Zymophilus paucivorans | synonym | Bacteria | None | None | None | 2.0 | +| B_ZYMPH_RFFN | Zymophilus raffinosivorans | synonym | Bacteria | None | None | None | 2.0 | +| F_ZYZYG | Zyzygomyces | unknown | Fungi | None | 7581 | None | 2.0 | + +```python +AMR.antimicrobials +``` + +| ab | cid | name | group | oral_ddd | oral_units | iv_ddd | iv_units | +|-----|-------------|----------------------|----------------------------|----------|------------|--------|----------| +| AMA | 4649.0 | 4-aminosalicylic acid| Antimycobacterials | 12.00 | g | NaN | None | +| ACM | 6450012.0 | Acetylmidecamycin | Macrolides/lincosamides | NaN | None | NaN | None | +| ASP | 49787020.0 | Acetylspiramycin | Macrolides/lincosamides | NaN | None | NaN | None | +| ALS | 8954.0 | Aldesulfone sodium | Other antibacterials | 0.33 | g | NaN | None | +| AMK | 37768.0 | Amikacin | Aminoglycosides | NaN | None | 1.0 | g | +| ... | ... | ... | ... | ... | ... | ... | ... | +| VIR | 11979535.0 | Virginiamycine | Other antibacterials | NaN | None | NaN | None | +| VOR | 71616.0 | Voriconazole | Antifungals/antimycotics | 0.40 | g | 0.4 | g | +| XBR | 72144.0 | Xibornol | Other antibacterials | NaN | None | NaN | None | +| ZID | 77846445.0 | Zidebactam | Other antibacterials | NaN | None | NaN | None | +| ZFD | NaN | Zoliflodacin | None | NaN | None | NaN | None | + + +# Installation Channels + +## Stable Release (CRAN) + +The default `AMR` Python package uses the latest stable version of the `AMR` R package, published on CRAN. After running `pip install AMR`, import it as usual: + +```python +import AMR + +AMR.example_isolates +``` + +## Development Version (GitHub) + +To use the latest development version of the `AMR` R package (sourced directly from GitHub), import the `beta` sub-package and alias it as `AMR`: + +```python +import AMR.beta as AMR + +AMR.example_isolates +``` + +Aliasing with `as AMR` keeps all downstream code identical to the stable import. Switching between the stable release and the development version requires changing only the import line — nothing else in your script needs to change. + +# SIR Classification with `as_sir()` + +## Using `enforce_method` + +The `as_sir()` function in R uses S3 method dispatch to select the correct calculation method based on the input class: `` for MIC values and `` for disk diffusion values. Because Python objects do not carry R class attributes through the `rpy2` bridge, this automatic dispatch may not resolve correctly. + +To explicitly specify the input type, use the `enforce_method` argument: + +```python +# Treat the column as MIC values — maps to R's as.sir.mic() +AMR.as_sir(df["MIC_col"], mo="E. coli", ab="AMX", guideline="EUCAST", enforce_method="mic") + +# Treat the column as disk diffusion values — maps to R's as.sir.disk() +AMR.as_sir(df["disk_col"], mo="E. coli", ab="AMX", guideline="EUCAST", enforce_method="disk") +``` + +Without `enforce_method`, R falls back to class-based dispatch on the raw Python input, which may fail or return unexpected results. Always supply `enforce_method` when calling `as_sir()` from Python. + +# Conclusion + +With the `AMR` Python package, Python users can now effortlessly call R functions from the `AMR` R package. This eliminates the need for complex `rpy2` configurations and provides a clean, easy-to-use interface for antimicrobial resistance analysis. The examples provided above demonstrate how this can be applied to typical workflows, such as standardising microorganism and antimicrobial names or calculating resistance. + +By just running `import AMR`, users can seamlessly integrate the robust features of the R `AMR` package into Python workflows. + +Whether you're cleaning data or analysing resistance patterns, the `AMR` Python package makes it easy to work with AMR data in Python. diff --git a/dist/amr-3.0.1.9087-py3-none-any.whl b/dist/amr-3.0.1.9087-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..59fc5fbaee784989c0587582c6ea44a3a8e983d2 GIT binary patch literal 13407 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 literal 0 HcmV?d00001 diff --git a/dist/amr-3.0.1.9087.tar.gz b/dist/amr-3.0.1.9087.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..97d15912b9dc679260ff2db63b555ad4b407b075 GIT binary patch literal 12655 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