From ad1d637fff53cf481bb28181eb0e719abaf24cfd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 3 Jul 2026 17:14:20 +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.9082-py3-none-any.whl | Bin 0 -> 13406 bytes dist/amr-3.0.1.9082.tar.gz | Bin 0 -> 12648 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.9082-py3-none-any.whl create mode 100644 dist/amr-3.0.1.9082.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..4cb6031e8 --- /dev/null +++ b/AMR.egg-info/PKG-INFO @@ -0,0 +1,254 @@ +Metadata-Version: 2.4 +Name: AMR +Version: 3.0.1.9082 +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.9082-py3-none-any.whl b/dist/amr-3.0.1.9082-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..47cce00c6f44f7ef5d99d9d51ff739340798ff8d GIT binary patch literal 13406 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 literal 0 HcmV?d00001 diff --git a/dist/amr-3.0.1.9082.tar.gz b/dist/amr-3.0.1.9082.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..103b92015a6c91e0a19e517c1db2e0176c7949ce GIT binary patch literal 12648 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