Compare commits

20 Commits
Author SHA1 Message Date
dr. M.S. (Matthijs) Berends b74501663b Merge branch 'main' into breakpoints 2026-11-09 22:11:08 +01:00
dr. M.S. (Matthijs) Berends 591c044b13 Merge branch 'main' into breakpoints 2026-11-09 21:59:09 +01:00
dr. M.S. (Matthijs) Berends af344f58f1 Merge branch 'main' into breakpoints 2026-11-09 21:53:58 +01:00
dr. M.S. (Matthijs) Berends fdc31345a6 Merge branch 'main' into breakpoints
# Conflicts:
#	NEWS.md
2026-11-09 21:30:10 +01:00
dr. M.S. (Matthijs) Berends 95756d224d Merge branch 'main' into breakpoints
# Conflicts:
#	DESCRIPTION
#	NEWS.md
#	R/sysdata.rda
#	data/antibiotics.rda
#	data/antimicrobials.rda
2026-11-09 20:46:50 +01:00
dr. M.S. (Matthijs) Berends a108548cd4 Merge remote-tracking branch 'origin/main' into breakpoints 2026-11-04 19:26:35 +01:00
dr. M.S. (Matthijs) Berends 361dfc28f7 Apply the EUCAST breakpoints of Vibrio to the species that EUCAST states only
The Vibrio sheet (v12.0 to v16.1) states: "Breakpoints are valid for V. alginolyticus, V. cholerae, V. fluvialis, V. parahaemolyticus and V. vulnificus." The rows of the genus are therefore replaced by rows of these species, with the statement in the note. Other species and isolates identified at genus level give NA, or use PK/PD breakpoints in EUCAST 2022-2023. CLSI is unchanged.

Any other wording of "breakpoints are valid for" now stops the script, so that a new statement cannot be missed.
2026-11-03 17:14:15 +01:00
dr. M.S. (Matthijs) Berends 81f5aaa7b8 Make anaerobes more specific than a Gram stain in rank_index
Anaerobes now have rank_index 5.5 (5.6 for a blocking row), and a Gram stain stays at 6. They had the same rank, so the order of sites could make the Gram-negative row with site Parenteral (CLSI Table 2B-5) precede the anaerobe row without a site (CLSI Table 2J), e.g., for ceftriaxone in B. fragilis.

A rebuild changes rank_index in 884 rows and nothing else.
2026-11-03 08:37:55 +01:00
dr. M.S. (Matthijs) Berends e7077081b9 Set the order of sites in as.sir(), and add the veterinary sites
Sites now go from systemic, IV, meningitis, endocarditis, pneumonia and mastitis to UTI, topical and screen. A breakpoint without a site takes the position of "other", as both mean any site that is not listed next to it. A second site breaks a tie on the first one.

The veterinary sites are now fixed codes as well: mastitis (includes Mammary gland), respiratory, metritis, genital, soft tissue and wounds (includes Abscesses). Sites that are part of each other do not contradict.

site = "other" now leaves out every breakpoint limited to an indication, and prefers a breakpoint without a site.

A rebuild of clinical_breakpoints with this order gives the same data, so the same blocking rows stay.
2026-11-02 20:20:05 +01:00
dr. M.S. (Matthijs) Berends 414f41ba22 Rebuild clinical_breakpoints, and add the NEWS entries and version bump for this PR
The rebuild uses the WHONET files of today, and holds the changes of #326, #327, #328, #329 and #331. The files in data-raw/datasets are not regenerated yet.
2026-11-02 18:27:17 +01:00
dr. M.S. (Matthijs) Berends d904ea5afb Merge remote-tracking branch 'origin/main' into breakpoints 2026-11-02 18:26:08 +01:00
dr. M.S. (Matthijs) Berends fbdfb0a071 Keep only EUCAST blocking rows that have an effect on as.sir() (#326)
The new internal blocking_row_is_needed() defines this: as.sir() must give another result without the row, so the definition follows the fallback path of as.sir() itself. The build removes all rows without an effect, and the new strict test checks all rows of the latest guideline, and for all years that a blocking row has a breakpoint to block.

This replaces the separate taxonomic comparison, handles the points of the review on this pruning, and keeps the sites of blocking rows, which `site` in as.sir() now uses.
2026-11-02 18:26:08 +01:00
dr. M.S. (Matthijs) Berends 472c84d20d Capture more EUCAST breakpoints from the Notes, using regular expressions only (#329)
Added: the oxacillin disk for S. pseudintermedius and related species, the oxacillin MIC for coagulase-negative staphylococci, mupirocin for nasal decolonisation, and meropenem in other infections for N. meningitidis. The Bacteroides statement is now matched as a pattern, and other wording stops the script.

The script documents why statements are left out, e.g., the oxacillin statements for S. aureus, S. lugdunensis and S. saprophyticus are hedged ("mostly methicillin resistant"), unlike those for cefoxitin.
2026-11-02 17:47:28 +01:00
dr. M.S. (Matthijs) Berends 2c98dac7ae Store all screening breakpoints under screening agents, and add these agents to antimicrobials (#328)
Implements the decisions ticked in #328, and the behaviour specified in https://github.com/msberends/AMR/pull/339#issuecomment-6577438074: `include_screening` now defaults to NULL, using screening breakpoints for screening agents only. With TRUE, a regular agent also takes these breakpoints, and with FALSE a screening agent gives NA with a note.

- antimicrobials gains 13 screening agents, e.g. GEN-S, ERY-S and STR1-S
- GEH and STH rows move to GEN-S and STR1-S, and as.sir() keeps accepting both codes
- Topical cut-off values move to -S agents with site "Topical"
- WHONET-based rows move as ticked, including CLSI cefoxitin for staphylococci and pefloxacin for Salmonella, and EUCAST 2012-2018 cefoxitin MIC
- Clinical breakpoints that EUCAST also allows as a screening test get a copy under the -S agent
2026-11-02 17:31:46 +01:00
dr. M.S. (Matthijs) Berends fab20c5eaa Leave EUCAST breakpoints in brackets out of clinical_breakpoints, and document where they are kept (#327)
as.sir() treats them as absent, so it can use PK/PD breakpoints or, for unknown `uti`, UTI breakpoints. The values stay available in data-raw/breakpoints_eucast_raw.csv, to which the manual now points. Organisms that a table excludes stay excluded, since these have their own blocking rows.

This also fixes the change for unknown `uti` of the previous commit: a blocking row only gives way to an actual UTI breakpoint, not to a UTI row without breakpoints.
2026-11-02 17:03:47 +01:00
dr. M.S. (Matthijs) Berends 4c4a7d4392 Add site to as.sir(), and use UTI breakpoints for unknown uti if no other breakpoint exists
`site` takes fixed codes, e.g. "meningitis" or "iv", and can be a column. With `site = NA`, any fitting breakpoint can apply, from most to least systemic. With a site set, breakpoints for contradicting sites are left out, while a breakpoint without a site still applies, and the result is NA if only contradicting sites exist, without falling back to PK/PD. `uti = TRUE` stays available and equals `site = "uti"`. Every choice is noted in sir_interpretation_history(), including the site that was used.

For unknown `uti`, a blocking row without a UTI status no longer overrides a UTI breakpoint at the same taxonomic level. A `uti` vector mixing NA with TRUE or FALSE no longer gives an error.

Veterinary sites are not part of the fixed codes yet, and are treated as breakpoints without a site.
2026-11-02 16:59:07 +01:00
dr. M.S. (Matthijs) Berends 5eed396dce Store EUCAST MIC breakpoints exactly as published, and compare dilutions in as.sir() (#331)
The reproduction script no longer maps MIC breakpoints to AMR:::COMMON_MIC_VALUES, and also keeps the off-scale S breakpoint of 0.001 mg/L. as.sir() compares through the new internal mic_dilution_level(), so that e.g. an MIC of 0.032 and a breakpoint of 0.03 are the same dilution, and shows the published breakpoints in sir_interpretation_history().

Every parsed breakpoint now holds the address of its workbook cell in breakpoints_eucast_raw, and the script stops if a second reading of the workbooks with readxl does not find the value in that cell.

The data sets are rebuilt once, at the end of this PR.
2026-11-02 16:56:51 +01:00
dr. M.S. (Matthijs) Berends 844e2581ee Test that Morganella is interpreted as reported, not as M. morganii (#330)
No code change was needed. Morganella follows Enterobacterales, except for imipenem and imipenem-relebactam, for which EUCAST gives rows for Morganellaceae or Morganella.
2026-11-02 16:55:36 +01:00
dr. M.S. (Matthijs) Berends 724a94a48f Add a tool to compare as.sir() results between builds, and apply the Bacteroides extension to zone diameters
The new compare_clinical_breakpoints.R compares the interpretations of two builds, and fails on any change that is not explained. A rebuild of main with pinned WHONET files reproduces all rows of clinical_breakpoints and microorganisms.codes.

The filter on MIC rows in the scope extensions is removed, since these now join on the method of each statement. It kept the DISK rows of the Bacteroides statement from being copied.
2026-11-02 16:55:36 +01:00
Erwin Hassing 3132811fd2 Fix EUCAST bracket handling, redundant blockers and Bacteroides scope 2026-10-30 15:38:14 +01:00
46 changed files with 26332 additions and 38029 deletions

No files matched your search

+2 -2
View File
@@ -1,6 +1,6 @@
Package: AMR
Version: 3.1.0.9022
Date: 2026-11-14
Date: 2026-11-09
Title: Antimicrobial Resistance Data Analysis
Description: Functions to simplify and standardise antimicrobial resistance (AMR)
data analysis and to work with microbial and antimicrobial properties by
@@ -73,4 +73,4 @@ License: GPL-2 | file LICENSE
Encoding: UTF-8
LazyData: true
Roxygen: list(markdown = TRUE)
Config/roxygen2/version: 8.1.1
Config/roxygen2/version: 8.1.0
+26 -1
View File
@@ -2,18 +2,43 @@
This version fixes a critical bug in WISCA that biased all coverage estimates of `wisca()` and `antibiogram(..., wisca = TRUE)` downwards since AMR 3.0.0. Users are strongly advised to re-run their WISCA analyses.
It also adds a `site` argument to `as.sir()`, stores EUCAST MIC breakpoints exactly as published, stores all screening breakpoints under screening agents, removes EUCAST's breakpoints in brackets, and only keeps blocking rows that have an effect.
### Breaking
* All explicit screening breakpoints in `clinical_breakpoints` moved to screening agents, e.g., from `FOX` to `FOX-S`, including the high-level aminoglycoside tests (`GEH` and `STH` to `GEN-S` and `STR1-S`), the topical cut-off values of EUCAST, and the CLSI surrogate tests of cefoxitin for staphylococci and pefloxacin for *Salmonella*. Use `as.sir(..., include_screening = TRUE)` to interpret a regular agent with these breakpoints; `GEH` and `STH` stay valid input (#328)
* `include_screening` in `as.sir()` now defaults to `NULL`, using screening breakpoints for screening agents only. `include_screening = FALSE` now also returns `NA`, with a note, for a screening agent (#328)
* EUCAST's breakpoints in brackets are no longer in `clinical_breakpoints`. They were blocking rows, so `as.sir()` can now use PK/PD breakpoints or the breakpoints of a broader taxon instead, e.g., for aminoglycosides in EUCAST 2020-2023. They stay available in [`data-raw/breakpoints_eucast_raw.csv`](https://github.com/msberends/AMR/blob/main/data-raw/breakpoints_eucast_raw.csv) (#327)
* EUCAST breakpoints of *Vibrio* now apply only to the species that EUCAST states: *V. alginolyticus*, *V. cholerae*, *V. fluvialis*, *V. parahaemolyticus* and *V. vulnificus*. Other species and isolates identified at genus level now give `NA`, or use PK/PD breakpoints in EUCAST 2022-2023
* With unknown `uti`, a blocking row without UTI status no longer overrides a UTI breakpoint at the same taxonomic level, e.g., amikacin in *Acinetobacter* now gives S or R instead of `NA`, which is noted in `sir_interpretation_history()`. Use `uti = FALSE` to prevent this
* If several breakpoints fit and no `site` is set, `as.sir()` now takes the one for the most systemic site, instead of the first one in the data set. This means, e.g., that a meningitis breakpoint now precedes a non-meningitis breakpoint, such as for benzylpenicillin in *S. pneumoniae*. Use `site` to choose another one
* `mo_shortname()` now returns the serovar for *Salmonella* serovars, e.g., `"S. Typhi"` and `"S. Goldcoast"` instead of `"S. enterica"`. As this is the default for `bug_drug_combinations()` and short names in `antibiogram()`, serovars are no longer merged in their results. Use `FUN = function(x) paste(mo_genus(x), mo_species(x))` in `bug_drug_combinations()` to group them by species (#341)
* `mo_shortname()` now returns e.g. `"S. Group B"` for *Salmonella* groups instead of the abbreviations of streptococci, such as `"GBS"`, so that they are no longer merged with streptococci in `bug_drug_combinations()` and `antibiogram()`. *Streptococcus* groups E, I, J and L are now also abbreviated, e.g., `"GES"`, and `"B_STRPT_ABCG"` now returns `"S. Group A, B, C, G"` instead of the malformed `"GA, B, C, GS"` (#341)
* `mdro()` now applies the rule for *Salmonella* Typhi in the EUCAST guidelines, i.e., resistance to carbapenems (and fluoroquinolones in `"EUCAST3.1"`). This rule never applied before, so these isolates were wrongly classified as negative (#341)
### New
* **Site of infection**
* `as.sir()` gained the argument `site`, in fixed codes such as `"meningitis"`, `"iv"`, `"uti"` and, for animals, `"mastitis"` and `"respiratory"`, which can also be a column name. A breakpoint for a contradicting site is left out, a breakpoint without a site still applies, and the result is `NA` if only contradicting sites are available, without using PK/PD breakpoints. `"other"` takes a breakpoint for other infections or without a site, and leaves out those limited to an indication. `uti = TRUE` stays available and equals `site = "uti"`
* `sir_interpretation_history()` now holds the site of the breakpoint used, and notes every assumption about sites
* **Screening agents**
* 13 screening agents in the `antimicrobials` data set: `CHL-S`, `CIP-S`, `COL-S`, `ERY-S`, `FUS-S`, `GEN-S`, `LVX-S`, `MUP-S`, `NEO-S`, `OFX-S`, `RTP-S`, `STR1-S` and `TOB-S` (#328)
* EUCAST clinical breakpoints that can also be used as a screening test, e.g., erythromycin for staphylococci, have a copy under the screening agent (#328)
* **EUCAST breakpoints stated in the Notes** (#329)
* Oxacillin disk for *S. pseudintermedius* and related species, and oxacillin MIC for coagulase-negative staphylococci, under `OXA-S`
* Mupirocin for nasal decolonisation of *S. aureus*
* Meropenem in other infections than meningitis for *N. meningitidis* in EUCAST 2021
* **Taxonomic names in plots**
* New function `labels_taxonomy()` to print taxonomic names in axis and legend labels in italics, which can directly be used as labeller in `ggplot2` (e.g., `scale_x_discrete(labels = labels_taxonomy)`) and in base R plots
* `italicise_taxonomy()` gained `type = "plotmath"`, which returns an expression vector for titles, axes and legends in plots
* All plotting functions now print taxonomic names in italics using `labels_taxonomy()`: the facets and titles of `autoplot()` and `plot()` for antibiograms, the legend of `wisca_plot()` (which previously italicised all its entries, including e.g. "CoNS"), the axes, legends and facets of `ggplot_sir()` and `facet_sir()`, the labels and legend of `ggplot_pca()`, and the subtitles of `plot()` and `autoplot()` for MIC and disk diffusion values (which previously italicised the whole name, e.g. "Coagulase-negative Staphylococcus (CoNS)")
### Changed
* SIR interpretation (`as.sir()`)
* MIC breakpoints are compared as dilutions, so that e.g. an MIC of 0.032 and a breakpoint of 0.03 mg/L are the same (#331)
* A `uti` vector mixing `NA` with `TRUE` or `FALSE` no longer gives an error
* `clinical_breakpoints` data set
* EUCAST MIC breakpoints are stored exactly as published, e.g., 0.03 instead of 0.032, and 0.001 instead of 0.0001 (#331)
* Blocking rows of EUCAST 2019-2026 that have no effect on `as.sir()` were removed, 12 243 in total (#326)
* The breakpoints of *Bacteroides* now also apply to zone diameters of *Parabacteroides*, *Phocaeicola dorei* and *Phocaeicola vulgatus* (#329)
* `italicise_taxonomy()`
* Species and subspecies names are now only italicised after a genus, an abbreviated genus, or another species or subspecies name, so that ordinary words such as "coli" or "major" stay upright. *Salmonella* serovars (such as Typhimurium) and groups are no longer italicised, and "subsp.", "ssp." and "var." stay upright between italicised names
* Fixed punctuation being italicised along with taxonomic names, e.g., `"(S. aureus)"` now gives `"(*S. aureus*)"` instead of `"(S. *aureus)*"`
@@ -25,6 +50,7 @@ This version fixes a critical bug in WISCA that biased all coverage estimates of
* `ggplot_sir()` now splits the plot by antimicrobial if there is more than one and the antimicrobial is not shown in the plot, e.g., with `x = "species"`, as their bars were previously stacked on top of each other. This uses `facet = "antibiotic"` if `facet` is not set, and otherwise a grid of `facet` by antimicrobial
* `ggplot_pca()`
* Fixed an error when setting `groups` together with `labels`, and setting `groups` without `labels` now colours the points by these groups instead of using them as labels, as documented
* *Morganella* is interpreted as reported, with the breakpoints of Enterobacterales or Morganellaceae and not of *M. morganii*, which is now tested (#330)
* WISCA (`wisca()` and `antibiogram(..., wisca = TRUE)`)
* Fixed a critical bug that systematically underestimated the coverage of every WISCA since AMR 3.0.0. Pathogens absent from a syndromic group, and pathogens without any test result for a regimen, were still included in the model with only prior information: each added a prior weight of 1 to the pathogen incidence, and untested pathogens kept their full incidence weight while counting as about 50% susceptible. The bias was largest for stratified analyses (e.g., up to 14 percentage points for meropenem in random strata of `example_isolates`). Now, only pathogens that occur in a group and have at least one test result for the regimen are included. Please re-run all WISCA analyses (#337)
* `retrieve_wisca_parameters()` now returns only the parameters actually used in the model, and `n_total` in the `long_numeric` attribute now counts only isolates of the pathogens included for that regimen
@@ -35,7 +61,6 @@ This version fixes a critical bug in WISCA that biased all coverage estimates of
* Species groups and complexes are now listed for every antimicrobial to which all their species are intrinsically resistant. This adds 62 bug-drug combinations for the *Burkholderia cepacia* complex, coryneform bacteria, the *Enterobacter cloacae* complex (e.g., amoxicillin and amoxicillin/clavulanic acid), the *Klebsiella pneumoniae* complex, and coagulase-negative staphylococci, which affects `mo_is_intrinsic_resistant()`, `not_intrinsic_resistant()`, and the priors of `wisca()` (#338)
### Other
* The documentation of `first_isolate()` now explains how to determine first isolates per any additional variable using `dplyr::group_by()`, and the bias this introduces when that variable is related to resistance (#345)
* The manual index on the website was rewritten to improve findability, with sections ordered by task and a filter field
* Fixed the link to the copyright section and added MycoBank as a taxonomy source in the *Welcome to AMR* vignette (#325)
+1 -1
View File
@@ -51,7 +51,7 @@
#' - For many plotting functions (e.g., for MIC or disk diffusion values), supplying `mo` and `ab` enables automatic SIR-based interpretative colouring. These colours are derived from [as.sir()] in the background and therefore depend on the active `guideline` setting, which again uses `r AMR::clinical_breakpoints$guideline[1]` if not set explicitly.
#' * `AMR_ignore_pattern` \cr A [regular expression][base::regex] to ignore (i.e., make `NA`) any match given in [as.mo()] and all [`mo_*`][mo_property()] functions.
#' * `AMR_include_PKPD` \cr A [logical] to use in [as.sir()], to indicate that PK/PD clinical breakpoints must be applied as a last resort - the default is `TRUE`.
#' * `AMR_include_screening` \cr A [logical] to use in [as.sir()], to indicate that clinical breakpoints for screening are allowed - the default is `FALSE`.
#' * `AMR_include_screening` \cr A [logical] to use in [as.sir()], to indicate that clinical breakpoints for screening are allowed - the default is `NULL`, using these for screening agents only, such as `FOX-S`. See [as.sir()].
#' * `AMR_interpretive_rules` \cr A [character] to set the default types of rules for [interpretive_rules()], [eucast_rules()] and [clsi_rules()], must be one or more of: `"breakpoints"`, `"expected_phenotypes"`, `"expert"`, `"other"`, `"custom"`, `"all"`, and defaults to `c("breakpoints", "expected_phenotypes")`. This option replaces the old option `AMR_eucastrules`.
#' * `AMR_keep_synonyms` \cr A [logical] to use in [as.mo()] and all [`mo_*`][mo_property()] functions, to indicate if old, previously valid taxonomic names must be preserved and not be corrected to currently accepted names. The default is `FALSE`.
#' * `AMR_locale` \cr A [character] to set the language for the `AMR` package, can be one of these supported language names or [ISO 639-1 codes](https://en.wikipedia.org/wiki/ISO_639-1): `r vector_or(paste0(sapply(LANGUAGES_SUPPORTED_NAMES, function(x) x[[1]]), " (" , LANGUAGES_SUPPORTED, ")"), quotes = FALSE, sort = FALSE)`. The default is the current system language (if supported, English otherwise).
+4 -2
View File
@@ -298,7 +298,7 @@
#' - `method`\cr Testing method, either `r vector_or(clinical_breakpoints$method, documentation = TRUE)`
#' - `site`\cr Body site for which the breakpoint must be applied, e.g. "Oral" or "Respiratory"
#' - `mo`\cr Microbial ID, see [as.mo()]
#' - `rank_index`\cr Taxonomic rank index of `mo`, used to choose the most specific breakpoint (the lowest index): 1 for subspecies and infraspecies, 2 for species, 2.5 for species groups (e.g., *Streptococcus* group A), 3 for genus, 4 for family, 5 for order, 6 for other groups (e.g., Gram-negative or anaerobic bacteria), and 7 for non-species related (PK-PD) breakpoints. Blocking rows (see *Details*) have the rank index of their organism + 0.1, e.g., 2.6 for a species group, so that a breakpoint for the same organism always takes precedence.
#' - `rank_index`\cr Taxonomic rank index of `mo`, used to choose the most specific breakpoint (the lowest index): 1 for subspecies and infraspecies, 2 for species, 2.5 for species groups (e.g., *Streptococcus* group A), 3 for genus, 4 for family, 5 for order, 5.5 for anaerobic bacteria, 6 for other groups (e.g., Gram-negative bacteria), and 7 for non-species related (PK-PD) breakpoints. Blocking rows (see *Details*) have the rank index of their organism + 0.1, e.g., 2.6 for a species group, so that a breakpoint for the same organism always takes precedence.
#' - `ab`\cr Antimicrobial code as used by this package, EARS-Net and WHONET, see [as.ab()]
#' - `ref_tbl`\cr Info about where the guideline rule can be found
#' - `disk_dose`\cr Dose of the used disk diffusion method
@@ -314,7 +314,9 @@
#' The default is `"human"`, which can also be set with the package option [`AMR_breakpoint_type`][AMR-options]. Use [`as.sir(..., breakpoint_type = ...)`][as.sir()] to interpret raw data using a specific breakpoint type, e.g. `as.sir(..., breakpoint_type = "ECOFF")` to use ECOFFs.
#'
#' ### Blocking Rows
#' Where EUCAST lists an organism but gives no breakpoint for it (e.g. "IE", "-", "Note", breakpoints in brackets, an organism excluded with "except", or no S category for a zone diameter), [as.sir()] must not fall back to the breakpoint of a broader taxon, such as the breakpoint for *Vibrio* spp. where EUCAST gives "IE" for *V. fluvialis*. Such cases are included as "blocking rows": rows in which `breakpoint_S` and `breakpoint_R` are both `NA` and the `note` starts with `"[No breakpoint]"` followed by the reason. [as.sir()] returns `NA` for these. This currently applies to `r format(sum(is.na(clinical_breakpoints$breakpoint_S) & is.na(clinical_breakpoints$breakpoint_R)), big.mark = " ")` rows. Remove them with `subset(clinical_breakpoints, !is.na(breakpoint_S))` if only actual breakpoints are needed.
#' Where EUCAST lists an organism but gives no breakpoint for it (e.g. "IE", "-", "Note", an organism excluded with "except", or no S category for a zone diameter), [as.sir()] must not fall back to the breakpoint of a broader taxon, such as the breakpoint for *Vibrio* spp. where EUCAST gives "IE" for *V. fluvialis*. Such cases are included as "blocking rows": rows in which `breakpoint_S` and `breakpoint_R` are both `NA` and the `note` starts with `"[No breakpoint]"` followed by the reason. [as.sir()] returns `NA` for these. This currently applies to `r format(sum(is.na(clinical_breakpoints$breakpoint_S) & is.na(clinical_breakpoints$breakpoint_R)), big.mark = " ")` rows. Remove them with `subset(clinical_breakpoints, !is.na(breakpoint_S))` if only actual breakpoints are needed.
#'
#' **EUCAST's breakpoints in brackets** are not in this data set. EUCAST bases these on ECOFFs, and states that reporting S or I should be avoided. [as.sir()] therefore treats them as absent, and can use PK/PD breakpoints or, for unknown UTI status, UTI breakpoints instead. All bracketed values are kept in the [raw import of the EUCAST tables](https://github.com/msberends/AMR/blob/main/data-raw/breakpoints_eucast_raw.csv) (column `is_bracketed`).
#'
#' Where another guideline has no S category for a zone diameter, such as CLSI for fluconazole in *C. glabrata* (SDD and R only), only `breakpoint_R` is given, and the `note` starts with `"[No S category]"`. [as.sir()] then returns R where applicable, and `NA` otherwise.
#'
-12
View File
@@ -130,18 +130,6 @@
#'
#'
#' The default method is phenotype-based (using `type = "points"`) and episode-based (using `episode_days = 365`). This makes sure that every genus-species combination is selected per patient once per year, while taking into account all antimicrobial test results. If no antimicrobial test results are available in the data set, only the episode-based method is applied at default.
#'
#' ## First isolates per additional variable
#'
#' To determine first isolates separately for the values of any additional variable, such as a ward, a specimen group, a molecular marker or a locally defined classification, group the data with [dplyr::group_by()] before calling [first_isolate()]. Every group is then handled as a separate data set, so the selection, including the start of every episode, is determined per patient, genus-species combination and group value. This works with all methods described above:
#'
#' ```r
#' your_data %>%
#' group_by(ward) %>%
#' mutate(first = first_isolate())
#' ```
#'
#' Be aware that grouping on a variable that is related to antimicrobial resistance, such as a resistance mechanism or the output of [mdro()], retains more isolates of patients whose isolates change category. This deviates from CLSI M39 and generally leads to an overestimation of resistance, as the selection then depends on the outcome that is being estimated.
#' @rdname first_isolate
#' @seealso [key_antimicrobials()]
#' @export
+14
View File
@@ -56,6 +56,20 @@ COMMON_MIC_VALUES <- c(
1024, 2048, 4096
)
# Guidelines publish the twofold dilutions below 0.125 mg/L in rounded notations, e.g., EUCAST prints 0.03 for the dilution that this package holds as 0.032, while laboratories may report 0.03, 0.031, 0.03125 or 0.032. These all denote one dilution. This returns the value of that dilution in COMMON_MIC_VALUES, and leaves all other values as they are.
mic_dilution_level <- function(x) {
notation <- c(
0.0039, 0.0078, 0.015, 0.0156, 0.03, 0.031, 0.0313, 0.03125, 0.06, 0.063, 0.0625, 0.12
)
level <- c(
0.004, 0.008, 0.016, 0.016, 0.032, 0.032, 0.032, 0.032, 0.064, 0.064, 0.064, 0.125
)
x <- as.double(x)
hit <- match(x, notation)
x[!is.na(hit)] <- level[hit[!is.na(hit)]]
x
}
#' Transform Input to Minimum Inhibitory Concentrations (MIC)
#'
#' This transforms vectors to a new class [`mic`], which treats the input as decimal numbers, while maintaining operators (such as ">=") and only allowing valid MIC values known to the field of (medical) microbiology.
+296 -28
View File
@@ -41,6 +41,7 @@ VALID_SIR_LEVELS <- c("S", "SDD", "I", "R", "NI", "WT", "NWT", "NS")
#' @param uti (Urinary Tract Infection) a vector (or column name) with [logical]s (`TRUE` or `FALSE`) to specify whether a UTI specific interpretation from the guideline should be chosen. For using [as.sir()] on a [data.frame], this can also be a column containing [logical]s or when left blank, the data set will be searched for a column 'specimen', and rows within this column containing 'urin' (such as 'urine', 'urina') will be regarded isolates from a UTI. If `uti` is `NA` (unknown), non-UTI breakpoints are preferred, and UTI breakpoints are only used if no non-UTI breakpoints exist for the drug-bug combination, which is noted in [sir_interpretation_history()]. With `uti = FALSE`, UTI breakpoints are never used. See *Examples*.
#' @inheritParams first_isolate
#' @param guideline A guideline name (or column name) to use for SIR interpretation. Defaults to `r AMR::clinical_breakpoints$guideline[1]` (the latest implemented EUCAST guideline in the [AMR::clinical_breakpoints] data set), but can be set with the package option [`AMR_guideline`][AMR-options]. Currently supports EUCAST (`r min(as.integer(gsub("[^0-9]", "", subset(AMR::clinical_breakpoints, guideline %like% "EUCAST")$guideline)))`-`r max(as.integer(gsub("[^0-9]", "", subset(AMR::clinical_breakpoints, guideline %like% "EUCAST")$guideline)))`) and CLSI (`r min(as.integer(gsub("[^0-9]", "", subset(AMR::clinical_breakpoints, guideline %like% "CLSI")$guideline)))`-`r max(as.integer(gsub("[^0-9]", "", subset(AMR::clinical_breakpoints, guideline %like% "CLSI")$guideline)))`), see *Details*. Using a column name allows for straightforward interpretation of historical data, which must be analysed in the context of, for example, different years.
#' @param site The site or route that the isolate is interpreted for: a [character] vector or a column name, in the fixed codes `"systemic"`, `"iv"`, `"meningitis"`, `"endocarditis"`, `"pneumonia"`, `"mastitis"`, `"respiratory"`, `"metritis"`, `"genital"`, `"intestinal"`, `"other"`, `"non-meningitis"`, `"non-endocarditis"`, `"non-pneumonia"`, `"extraintestinal"`, `"soft tissue"`, `"skin"`, `"wounds"`, `"inhaled"`, `"oral"`, `"prophylaxis"`, `"uti"` and `"topical"`, which can be combined with a comma, e.g. `"iv, meningitis"`. If `site` is `NA` (default), any breakpoint matching all other criteria can apply, taken from most to least systemic site in the order just given; a breakpoint without a site takes the position of `"other"`, as both mean any site that is not listed next to it. If `site` is set, a breakpoint for a contradicting site is left out, e.g. `"meningitis"` leaves out `Non-meningitis`, while a breakpoint without a site still applies. `"other"` leaves out every breakpoint limited to an indication, and prefers a breakpoint without a site. Related sites do not contradict each other: `"pneumonia"` and `"respiratory"`, `"metritis"` and `"genital"`, and `"soft tissue"`, `"skin"` and `"wounds"`. The code `"mastitis"` includes `Mammary gland`, and `"wounds"` includes `Abscesses`. The result is `NA` if only contradicting sites are available, also when PK/PD breakpoints exist. All choices are noted in [sir_interpretation_history()].
#' @param capped_mic_handling A [character] string that controls how MIC values with a cap (i.e., starting with `<`, `<=`, `>`, or `>=`) are interpreted. Supports the following options:
#'
#' `"none"`
@@ -65,7 +66,7 @@ VALID_SIR_LEVELS <- c("S", "SDD", "I", "R", "NI", "WT", "NWT", "NS")
#' @param as_wt_nwt A [logical] to return `"WT"`/`"NWT"` instead of `"S"`/`"R"`. Defaults to `TRUE` when using ECOFFs, i.e., when `breakpoint_type` is set to `"ECOFF"`.
#' @param add_intrinsic_resistance *(only useful when using a EUCAST guideline)* a [logical] to indicate whether intrinsic antibiotic resistance must also be considered for applicable bug-drug combinations, meaning that e.g. ampicillin will always return "R" in *Klebsiella* species. Determination is based on the [intrinsic_resistant] data set, that itself is based on `r format_eucast_version_nr(3.3)`.
#' @param substitute_missing_r_breakpoint A [logical] to indicate that a missing clinical breakpoints for R (resistant) must be substituted with R - the default is `FALSE`. Some (especially CLSI) breakpoints only have a breakpoint for S, meaning that the outcome can only be `"S"` or `NA`. Setting this to `TRUE` will convert the `NA`s in these cases to `"R"`. Can also be set with the package option [`AMR_substitute_missing_r_breakpoint`][AMR-options].
#' @param include_screening A [logical] to indicate that clinical breakpoints for screening are allowed - the default is `FALSE`. Can also be set with the package option [`AMR_include_screening`][AMR-options].
#' @param include_screening A [logical] to indicate that clinical breakpoints for screening are allowed. At default (`NULL`, can be set with the package option [`AMR_include_screening`][AMR-options]), these are only used for screening agents, e.g. `FOX-S`, but not for regular agents, e.g. `FOX`. Use `TRUE` to also use them for regular agents (with `FOX` then taking the breakpoints of `FOX-S`), and `FALSE` to never use them, which gives `NA` with a note for a screening agent.
#' @param include_PKPD A [logical] to indicate that PK/PD clinical breakpoints must be applied as a last resort - the default is `TRUE`. Can also be set with the package option [`AMR_include_PKPD`][AMR-options].
#' @param breakpoint_type The type of breakpoints to use, either `r vector_or(clinical_breakpoints$type, documentation = TRUE)`. ECOFF stands for Epidemiological Cut-Off values. The default is `"human"`, which can also be set with the package option [`AMR_breakpoint_type`][AMR-options]. If `host` is set to values of veterinary species, this will automatically be set to `"animal"`.
#' @param host A vector (or column name) with [character]s to indicate the host. Only useful for veterinary breakpoints, as it requires `breakpoint_type = "animal"`. The values can be any text resembling the animal species, even in any of the `r length(LANGUAGES_SUPPORTED)` supported languages of this package. For foreign languages, be sure to set the language with [set_AMR_locale()] (though it will be automatically guessed based on the system language).
@@ -663,7 +664,7 @@ as.sir.mic <- function(x,
add_intrinsic_resistance = FALSE,
reference_data = AMR::clinical_breakpoints,
substitute_missing_r_breakpoint = getOption("AMR_substitute_missing_r_breakpoint", FALSE),
include_screening = getOption("AMR_include_screening", FALSE),
include_screening = getOption("AMR_include_screening", NULL),
include_PKPD = getOption("AMR_include_PKPD", TRUE),
breakpoint_type = getOption("AMR_breakpoint_type", "human"),
host = NULL,
@@ -671,6 +672,7 @@ as.sir.mic <- function(x,
verbose = FALSE,
info = interactive(),
conserve_capped_values = NULL,
site = NULL,
...) {
as_sir_method(
method_short = "mic",
@@ -693,6 +695,7 @@ as.sir.mic <- function(x,
verbose = verbose,
info = info,
conserve_capped_values = conserve_capped_values,
site = site,
...
)
}
@@ -708,13 +711,14 @@ as.sir.disk <- function(x,
add_intrinsic_resistance = FALSE,
reference_data = AMR::clinical_breakpoints,
substitute_missing_r_breakpoint = getOption("AMR_substitute_missing_r_breakpoint", FALSE),
include_screening = getOption("AMR_include_screening", FALSE),
include_screening = getOption("AMR_include_screening", NULL),
include_PKPD = getOption("AMR_include_PKPD", TRUE),
breakpoint_type = getOption("AMR_breakpoint_type", "human"),
host = NULL,
language = get_AMR_locale(),
verbose = FALSE,
info = interactive(),
site = NULL,
...) {
as_sir_method(
method_short = "disk",
@@ -736,6 +740,7 @@ as.sir.disk <- function(x,
language = language,
verbose = verbose,
info = info,
site = site,
...
)
}
@@ -753,7 +758,7 @@ as.sir.data.frame <- function(x,
add_intrinsic_resistance = FALSE,
reference_data = AMR::clinical_breakpoints,
substitute_missing_r_breakpoint = getOption("AMR_substitute_missing_r_breakpoint", FALSE),
include_screening = getOption("AMR_include_screening", FALSE),
include_screening = getOption("AMR_include_screening", NULL),
include_PKPD = getOption("AMR_include_PKPD", TRUE),
breakpoint_type = getOption("AMR_breakpoint_type", "human"),
host = NULL,
@@ -761,7 +766,8 @@ as.sir.data.frame <- function(x,
verbose = FALSE,
info = interactive(),
parallel = FALSE,
conserve_capped_values = NULL) {
conserve_capped_values = NULL,
site = NULL) {
meet_criteria(x, allow_class = "data.frame") # will also check for dimensions > 0
meet_criteria(col_mo, allow_class = "character", is_in = colnames(x), allow_NULL = TRUE)
meet_criteria(guideline, allow_class = "character")
@@ -771,7 +777,7 @@ as.sir.data.frame <- function(x,
meet_criteria(add_intrinsic_resistance, allow_class = "logical", has_length = 1)
meet_criteria(reference_data, allow_class = "data.frame")
meet_criteria(substitute_missing_r_breakpoint, allow_class = "logical", has_length = 1)
meet_criteria(include_screening, allow_class = "logical", has_length = 1)
meet_criteria(include_screening, allow_class = "logical", has_length = 1, allow_NULL = TRUE)
meet_criteria(include_PKPD, allow_class = "logical", has_length = 1)
meet_criteria(breakpoint_type, allow_class = "character", is_in = reference_data$type, has_length = 1)
meet_criteria(host, allow_class = c("character", "factor"), allow_NULL = TRUE, allow_NA = TRUE)
@@ -871,6 +877,15 @@ as.sir.data.frame <- function(x,
}
}
# -- sites
col_site <- NULL
if (is.character(site) && length(site) == 1 && site %in% colnames(x)) {
col_site <- site
site <- as.character(x[, col_site, drop = TRUE])
} else if (!is.null(site) && !length(site) %in% c(1, nrow(x))) {
stop_("argument {.arg site} must be of length 1, of length `nrow(x)`, or a single column name of {.arg x}")
}
i <- 0
ab_cols <- colnames(x)[vapply(FUN.VALUE = logical(1), x, function(y) {
i <<- i + 1
@@ -881,6 +896,9 @@ as.sir.data.frame <- function(x,
if (!is.null(col_uti) && ab == col_uti) {
return(FALSE)
}
if (!is.null(col_site) && ab == col_site) {
return(FALSE)
}
if (length(sel) == 0 || (length(sel) > 0 && ab %in% sel)) {
# columns already carrying an AMR class are always included
y_bak <- x.bak[, ab, drop = TRUE]
@@ -1001,6 +1019,7 @@ as.sir.data.frame <- function(x,
ab = ab_col,
guideline = guideline,
uti = if (length(uti) > 1L) uti[row_idx] else uti,
site = if (length(site) > 1L) site[row_idx] else site,
capped_mic_handling = capped_mic_handling,
as_wt_nwt = as_wt_nwt,
add_intrinsic_resistance = add_intrinsic_resistance,
@@ -1036,6 +1055,7 @@ as.sir.data.frame <- function(x,
ab = ab_col,
guideline = guideline,
uti = if (length(uti) > 1L) uti[row_idx] else uti,
site = if (length(site) > 1L) site[row_idx] else site,
as_wt_nwt = as_wt_nwt,
add_intrinsic_resistance = add_intrinsic_resistance,
reference_data = reference_data,
@@ -1237,6 +1257,157 @@ convert_host <- function(x, lang = NULL) {
x_out
}
# Sites in clinical_breakpoints and in the `site` argument, from most to least systemic. Every value in the `site` column consists of one or more of these, see sir_site_tokens(). A breakpoint without a site takes the same position as "other": both mean any site that is not listed next to it. That single position gives both meanings: below "meningitis", as "other" then means non-meningitis, and above "uti", as "other" then means non-UTI.
SIR_SITE_ORDER <- c("systemic", "iv", "meningitis", "endocarditis", "pneumonia", "mastitis", "respiratory", "metritis", "genital", "intestinal", "other", "non-meningitis", "non-endocarditis", "non-pneumonia", "extraintestinal", "soft tissue", "skin", "wounds", "inhaled", "oral", "prophylaxis", "uti", "topical", "screen")
# all notations in the `site` column of clinical_breakpoints and of the `site` argument
SIR_SITE_PATTERNS <- c(
systemic = "systemic( infections)?",
iv = "(iv|intravenous|parenteral)",
meningitis = "meningitis",
endocarditis = "endocarditis",
pneumonia = "((community-acquired )?pneumonia)",
mastitis = "(mastitis|mammary gland)",
respiratory = "respiratory",
metritis = "metritis",
genital = "genital",
intestinal = "intestinal",
other = "other( infections)?",
`non-meningitis` = "non-meningitis",
`non-endocarditis` = "non-endocarditis",
`non-pneumonia` = "non-pneumonia",
extraintestinal = "extraintestinal",
`soft tissue` = "soft tissue",
skin = "skin",
wounds = "(wounds?|abscess(es)?)",
inhaled = "inhaled",
oral = "oral",
prophylaxis = "prophylaxis",
uti = "(uti|urine|(uncomplicated )?urinary tract infection|infections originating from the urinary tract)",
topical = "topical",
screen = "screen"
)
# sites of which one is part of the other, or which are hard to tell apart, and so do not contradict each other
SIR_SITE_RELATED <- list(c("pneumonia", "respiratory"), c("metritis", "genital"), c("soft tissue", "skin", "wounds"))
# parts of the `site` column that do not say anything about where a breakpoint applies
SIR_SITE_NOT_A_SITE <- c("liposomal", "investigational agent")
sir_site_parts <- function(x) {
if (is.na(x)) {
return(character(0))
}
trimws(strsplit(tolower(as.character(x)), ",", fixed = TRUE)[[1]])
}
sir_site_tokens <- function(x) {
parts <- sir_site_parts(x)
names(SIR_SITE_PATTERNS)[vapply(SIR_SITE_PATTERNS, function(p) any(grepl(paste0("^", p, "$"), parts)), logical(1))]
}
# for the `site` argument: returns the codes per element, as one string, and does not accept anything unknown
sir_site_normalise <- function(x) {
x <- as.character(x)
unique_x <- unique(x)
normalised <- vapply(unique_x, function(value) {
if (is.na(value)) {
return(NA_character_)
}
tokens <- sir_site_tokens(value)
unknown <- setdiff(sir_site_parts(value), c(tokens, SIR_SITE_NOT_A_SITE))
unknown <- unknown[!vapply(unknown, function(u) any(vapply(SIR_SITE_PATTERNS, function(p) grepl(paste0("^", p, "$"), u), logical(1))), logical(1))]
if (length(unknown) > 0 || length(tokens) == 0) {
stop_("Unknown value in {.arg site}: ", vector_and(value, quotes = TRUE), ". It must be one or more of ", vector_or(setdiff(names(SIR_SITE_PATTERNS), "screen"), quotes = TRUE, sort = FALSE), ", combined with a comma.", call = FALSE)
}
paste(tokens, collapse = ",")
}, character(1), USE.NAMES = FALSE)
normalised[match(x, unique_x)]
}
# the sites of the user, with the sites that are related to them
sir_site_expand <- function(tokens) {
unique(c(tokens, unlist(SIR_SITE_RELATED[vapply(SIR_SITE_RELATED, function(related) any(tokens %in% related), logical(1))])))
}
# whether a breakpoint with these sites does not contradict the sites set by the user
sir_site_fits <- function(breakpoint_tokens, user_tokens) {
negated <- function(tokens) sub("^non-", "", tokens[startsWith(tokens, "non-")])
if (any(negated(breakpoint_tokens) %in% user_tokens) || any(negated(user_tokens) %in% breakpoint_tokens)) {
return(FALSE)
}
# a systemic infection can be any indication, but not one limited to the urinary tract
if (("systemic" %in% breakpoint_tokens && "uti" %in% user_tokens) || ("uti" %in% breakpoint_tokens && "systemic" %in% user_tokens)) {
return(FALSE)
}
indications <- c("meningitis", "endocarditis", "pneumonia", "mastitis", "respiratory", "metritis", "genital", "uti", "intestinal", "extraintestinal", "soft tissue", "skin", "wounds", "prophylaxis")
# "other" is any site that is not listed, so it contradicts every breakpoint that is limited to an indication
if ("other" %in% user_tokens && !any(user_tokens %in% indications) && any(breakpoint_tokens %in% indications)) {
return(FALSE)
}
groups <- list(route = c("iv", "oral", "topical", "inhaled"), indication = indications)
user_tokens <- sir_site_expand(user_tokens)
for (group in groups) {
from_user <- intersect(user_tokens, group)
from_breakpoint <- intersect(breakpoint_tokens, group)
if (length(from_user) > 0 && length(from_breakpoint) > 0 && !any(from_user %in% from_breakpoint)) {
return(FALSE)
}
}
TRUE
}
# whether a breakpoint holds one of the sites that the user set, where "other" is also a breakpoint without a site
sir_site_given <- function(breakpoint_tokens, user_tokens) {
any(breakpoint_tokens %in% sir_site_expand(user_tokens)) || ("other" %in% user_tokens && length(breakpoint_tokens) == 0)
}
# The position in SIR_SITE_ORDER, of the most systemic site if there are more. The other sites are the decimals, so that "Intravenous, Meningitis" comes before "Intravenous, Non-meningitis".
sir_site_rank <- function(x) {
tokens <- sir_site_tokens(x)
if (length(tokens) == 0) {
return(as.double(match("other", SIR_SITE_ORDER)))
}
ranks <- sort(match(tokens, SIR_SITE_ORDER))
sum(ranks / 100^(seq_along(ranks) - 1))
}
# Whether a blocking row has any effect, which is the definition used for clinical_breakpoints (#326): as.sir() must give another result without it. This takes one row number and the rows of one guideline, agent and method.
blocking_row_is_needed <- function(i, breakpoints) {
row <- breakpoints[i, , drop = FALSE]
others <- breakpoints[-i, , drop = FALSE]
values <- c(others$breakpoint_S, others$breakpoint_R)
values <- values[!is.na(values)]
if (length(values) == 0) {
return(FALSE)
}
if (row$method == "MIC") {
input <- as.mic(sort(unique(pmax(0.001, c(0.001, 512, values / 2, values, values * 2)))))
} else {
input <- as.disk(sort(unique(pmin(50, c(6, 50, values - 1, values, values + 1)))))
}
sir <- function(reference_data, uti, site) {
as.character(suppressMessages(suppressWarnings(as.sir(input,
mo = as.character(row$mo), ab = as.character(row$ab), guideline = row$guideline, uti = uti, site = site,
reference_data = reference_data, info = FALSE
))))
}
row_site <- if (is.na(row$site) || length(sir_site_tokens(row$site)) == 0) NA_character_ else c(NA_character_, paste(setdiff(sir_site_tokens(row$site), "screen"), collapse = ","))
row_site <- unique(row_site[is.na(row_site) | nzchar(row_site)])
for (uti in list(NA, FALSE, TRUE)) {
for (site in row_site) {
if (isTRUE(uti) && !is.na(site) && !grepl("uti", site, fixed = TRUE) && !isTRUE(row$uti)) {
next
}
if (isFALSE(uti) && !is.na(site) && grepl("uti", site, fixed = TRUE)) {
next
}
if (!identical(sir(breakpoints, uti, site), sir(others, uti, site))) {
return(TRUE)
}
}
}
FALSE
}
as_sir_method <- function(method_short,
method_long,
x,
@@ -1257,6 +1428,7 @@ as_sir_method <- function(method_short,
verbose,
info,
conserve_capped_values = NULL,
site = NULL,
...) {
if (isTRUE(conserve_capped_values)) {
deprecation_warning(old = "conserve_capped_values", new = "capped_mic_handling", fn = "as.sir", is_argument = TRUE)
@@ -1267,12 +1439,13 @@ as_sir_method <- function(method_short,
meet_criteria(ab, allow_class = c("ab", "character"), has_length = c(1, length(x)), .call_depth = -2)
meet_criteria(guideline, allow_class = "character", has_length = c(1, length(x)), .call_depth = -2)
meet_criteria(uti, allow_class = c("logical", "character"), has_length = c(1, length(x)), allow_NULL = TRUE, allow_NA = TRUE, .call_depth = -2)
meet_criteria(site, allow_class = c("logical", "character", "factor"), has_length = c(1, length(x)), allow_NULL = TRUE, allow_NA = TRUE, .call_depth = -2)
meet_criteria(capped_mic_handling, allow_class = "character", has_length = 1, is_in = c("none", "conservative", "standard", "lenient"), .call_depth = -2)
meet_criteria(as_wt_nwt, allow_class = "logical", has_length = 1, .call_depth = -2)
meet_criteria(add_intrinsic_resistance, allow_class = "logical", has_length = 1, .call_depth = -2)
meet_criteria(reference_data, allow_class = "data.frame", .call_depth = -2)
meet_criteria(substitute_missing_r_breakpoint, allow_class = "logical", has_length = 1, .call_depth = -2)
meet_criteria(include_screening, allow_class = "logical", has_length = 1, .call_depth = -2)
meet_criteria(include_screening, allow_class = "logical", has_length = 1, allow_NULL = TRUE, .call_depth = -2)
meet_criteria(include_PKPD, allow_class = "logical", has_length = 1, .call_depth = -2)
reference_data <- check_reference_data(reference_data, .call_depth = -2)
meet_criteria(breakpoint_type, allow_class = "character", is_in = reference_data$type, has_length = 1, .call_depth = -2)
@@ -1468,6 +1641,20 @@ as_sir_method <- function(method_short,
if (length(uti) == 1) {
uti <- rep(uti, length(x))
}
# get site, from a column or as given, in the fixed codes of sir_site_tokens()
if (!is.null(current_df) && length(site) == 1 && !is.na(site) && as.character(site) %in% colnames(current_df)) {
site <- current_df[[as.character(site)]]
}
site <- sir_site_normalise(if (is.null(site)) NA_character_ else site)
if (length(site) == 1) {
site <- rep(site, length(x))
}
# a UTI as site is the same as `uti = TRUE`, which stays available for backward compatibility
site_is_uti <- !is.na(site) & grepl("(^|,)uti(,|$)", site)
if (any(site_is_uti & uti %in% FALSE)) {
stop_("Arguments {.arg site} and {.arg uti} contradict each other: `site` indicates a urinary tract infection, while `uti = FALSE`.", call = FALSE)
}
uti[site_is_uti] <- TRUE
if (isTRUE(add_intrinsic_resistance) && guideline_coerced %unlike% "EUCAST") {
if (isTRUE(info) && message_not_thrown_before("as.sir", "intrinsic")) {
message_("{.help [{.fun as.sir}](AMR::as.sir)}: using {.arg add_intrinsic_resistance} is only useful when using EUCAST guidelines, since the rules for intrinsic resistance are based on EUCAST.")
@@ -1511,17 +1698,29 @@ as_sir_method <- function(method_short,
method_coerced <- toupper(method)
ab_coerced <- as.ab(ab, info = FALSE)
# which agents hold the breakpoints of the requested agents: the high-level aminoglycoside tests have two codes, and screening breakpoints are also for the regular agent if the user allows this
ab_lookup <- function(ab_requested) {
ab_requested <- as.character(ab_requested)
ab_stored <- ab_requested
ab_stored[ab_stored == "GEH"] <- "GEN-S"
ab_stored[ab_stored == "STH"] <- "STR1-S"
from <- c(ab_requested, ab_requested)
to <- c(ab_stored, if (isTRUE(include_screening)) ifelse(endsWith(ab_stored, "-S"), ab_stored, paste0(ab_stored, "-S")) else ab_stored)
unique(data.frame(from = from, to = to, stringsAsFactors = FALSE))
}
ab_coerced_lookup <- ab_lookup(ab_coerced)
if (!custom_breakpoints_set) {
breakpoints <- reference_data %pm>%
subset(guideline %in% guideline_coerced & method == method_coerced & ab %in% ab_coerced)
subset(guideline %in% guideline_coerced & method == method_coerced & ab %in% ab_coerced_lookup$to)
if (any(ab_coerced == "AMX") && nrow(breakpoints[breakpoints$ab == "AMX", , drop = FALSE]) == 0) {
ab_coerced[ab_coerced == "AMX"] <- "AMP"
ab_coerced_lookup <- ab_lookup(ab_coerced)
breakpoints <- reference_data %pm>%
subset(guideline %in% guideline_coerced & method == method_coerced & ab %in% ab_coerced)
subset(guideline %in% guideline_coerced & method == method_coerced & ab %in% ab_coerced_lookup$to)
}
} else {
breakpoints <- reference_data %pm>%
subset(method == method_coerced & ab %in% ab_coerced)
subset(method == method_coerced & ab %in% ab_coerced_lookup$to)
}
@@ -1534,6 +1733,7 @@ as_sir_method <- function(method_short,
ab = ab,
result = NA_sir_,
uti = uti,
site = site,
host = host,
stringsAsFactors = FALSE
)
@@ -1573,7 +1773,7 @@ as_sir_method <- function(method_short,
df$input_clean <- as.disk(df$input_clean)
}
df_unique <- unique(df[, c("guideline", "mo", "ab", "uti", "host"), drop = FALSE])
df_unique <- unique(df[, c("guideline", "mo", "ab", "uti", "site", "host"), drop = FALSE])
mo_grams <- suppressWarnings(suppressMessages(mo_gramstain(df_unique$mo, language = NULL, keep_synonyms = FALSE)))
# get all breakpoints, use humans as backup for animals
@@ -1584,10 +1784,23 @@ as_sir_method <- function(method_short,
breakpoints <- breakpoints %pm>%
subset(type %in% breakpoint_type_lookup)
is_screening_row <- function(df) {
df$site %like% "screen" | df$ref_tbl %like% "screen" | as.character(df$ab) %like% "-S$"
}
screening_left_out <- FALSE
if (isFALSE(include_screening)) {
# remove screening rules from the breakpoints table
breakpoints <- breakpoints %pm>%
subset(site %unlike% "screen" & ref_tbl %unlike% "screen")
# remove screening rules from the breakpoints table, on explicit request also for a screening agent
screening_left_out <- any(is_screening_row(breakpoints) & as.character(breakpoints$ab) %like% "-S$")
breakpoints <- breakpoints[!is_screening_row(breakpoints), , drop = FALSE]
} else if (is.null(include_screening)) {
# at default, screening breakpoints are only for an agent that indicates screening itself
breakpoints <- breakpoints[!is_screening_row(breakpoints) | as.character(breakpoints$ab) %like% "-S$", , drop = FALSE]
}
# the breakpoints are from here on known by the requested agent
if (nrow(breakpoints) > 0) {
for (j in rev(seq_len(nrow(ab_coerced_lookup)))) {
breakpoints$ab[as.character(breakpoints$ab) == ab_coerced_lookup$to[j]] <- ab_coerced_lookup$from[j]
}
}
if (isFALSE(include_PKPD)) {
# remove PKPD rules from the breakpoints table
@@ -1610,6 +1823,35 @@ as_sir_method <- function(method_short,
has_progress_bar <- !is.null(import_fn("progress_bar", "progress", error_on_fail = FALSE)) && nrow(df_unique) >= 10
on.exit(close(p))
if (isTRUE(screening_left_out) && nrow(breakpoints) == 0) {
# a note, as this may be by accident
message_("Returning NAs for ", vector_and(unique(as.character(ab_coerced)), quotes = TRUE), ": this is a screening agent, while `include_screening = FALSE` leaves out screening breakpoints.")
out <- data.frame(
datetime = rep(Sys.time(), nrow(df)),
index = seq_len(nrow(df)),
method = rep(method_coerced, nrow(df)),
ab_given = ab.bak,
mo_given = as.character(mo.bak),
host_given = as.character(host),
input_given = as.character(df$input_original),
ab = as.character(df$ab),
mo = as.character(df$mo),
host = as.character(df$host),
input = as.character(df$input_clean),
outcome = rep(NA_sir_, nrow(df)),
notes = rep("Screening breakpoints were left out, since `include_screening = FALSE`.", nrow(df)),
guideline = df$guideline,
ref_table = rep(NA_character_, nrow(df)),
uti = df$uti,
breakpoint_S_R = rep(NA_character_, nrow(df)),
site = rep(NA_character_, nrow(df)),
stringsAsFactors = FALSE
)
AMR_env$sir_interpretation_history <- rbind_AMR(AMR_env$sir_interpretation_history, out[!is.na(out$input_given), , drop = FALSE])
load_mo_uncertainties(metadata_mo)
return(rep(NA_sir_, nrow(df)))
}
if (nrow(breakpoints) == 0) {
# apparently no breakpoints found
if (isTRUE(info)) {
@@ -1637,12 +1879,11 @@ as_sir_method <- function(method_short,
ab_current <- df_unique[i, "ab", drop = TRUE]
host_current <- df_unique[i, "host", drop = TRUE]
uti_current <- df_unique[i, "uti", drop = TRUE]
site_current <- df_unique[i, "site", drop = TRUE]
notes_current <- character(0)
rows <- which(as.character(df$mo) == mo_current & df$ab == ab_current & df$host == host_current & df$guideline == guideline_current)
if (!is.na(uti_current)) {
# also filter on UTIs
rows <- rows[df$uti[rows] == uti_current]
}
# also filter on UTIs and sites, of which NA is a value on its own
rows <- rows[df$uti[rows] %in% uti_current & df$site[rows] %in% site_current]
if (length(rows) == 0) {
# this can happen if a host is unavailable, just continue with the next one, since a note about hosts having NA are already given at this point
@@ -1807,6 +2048,7 @@ as_sir_method <- function(method_short,
ref_table = vectorise_log_entry(NA_character_, length(rows)),
uti = vectorise_log_entry(uti_current, length(rows)),
breakpoint_S_R = vectorise_log_entry(NA_character_, length(rows)),
site = vectorise_log_entry(NA_character_, length(rows)),
stringsAsFactors = FALSE
)
out <- subset(out, !is.na(input_given))
@@ -1815,17 +2057,28 @@ as_sir_method <- function(method_short,
next
}
# if the user set a site, keep only the breakpoints that do not contradict it (a breakpoint without a site always fits); PK/PD breakpoints are no fallback for a breakpoint that exists for other sites only
if (!is.na(site_current)) {
site_tokens_current <- strsplit(site_current, ",", fixed = TRUE)[[1]]
site_fits <- vapply(breakpoints_current$site, function(s) sir_site_fits(sir_site_tokens(s), site_tokens_current), logical(1), USE.NAMES = FALSE)
if (any(!site_fits)) {
breakpoints_current <- breakpoints_current[site_fits & as.character(breakpoints_current$mo) != "UNKNOWN", , drop = FALSE]
}
}
# if the user explicitly set uti, keep only those rows
uti_assumed <- FALSE
if (!is.na(uti_current)) {
breakpoints_current <- breakpoints_current[breakpoints_current$uti == uti_current, , drop = FALSE]
} else if (any(breakpoints_current$uti %in% TRUE)) {
# uti is unknown: non-UTI rows take precedence over UTI rows, and UTI rows are only used if there are no non-UTI rows. A non-UTI breakpoint applies at any taxonomic level, but a non-UTI row without breakpoints (a 'blocking row', e.g. for EUCAST's breakpoints in brackets) only applies if it is at least as specific as the UTI rows: the blocking row of e.g. Enterobacterales must not override the UTI breakpoint given for E. coli itself.
# uti is unknown: non-UTI rows take precedence over UTI rows, and UTI rows are only used if there are no non-UTI rows. A non-UTI breakpoint applies at any taxonomic level, but a non-UTI row without breakpoints (a 'blocking row') is no breakpoint, so it only applies if it is more specific than the UTI rows: at the same level or above, it does not override a UTI breakpoint.
# taxonomic level without the 0.1 that a blocking row adds to its rank_index, e.g. 3.1 -> 3 and 2.6 -> 2.5
taxonomic_level <- round(breakpoints_current$rank_index * 2) / 2
is_blocking <- is.na(breakpoints_current$breakpoint_S) & is.na(breakpoints_current$breakpoint_R)
is_uti <- breakpoints_current$uti %in% TRUE
too_broad <- !is_uti & is_blocking & taxonomic_level > min(taxonomic_level[is_uti])
# a UTI row without breakpoints is no breakpoint either, so it does not take precedence over anything
is_uti_breakpoint <- is_uti & !is_blocking
too_broad <- !is_uti & is_blocking & any(is_uti_breakpoint) & taxonomic_level >= suppressWarnings(min(taxonomic_level[is_uti_breakpoint]))
breakpoints_current <- breakpoints_current[!too_broad, , drop = FALSE]
if (any(!breakpoints_current$uti %in% TRUE)) {
if (length(unique(breakpoints_current$site)) > 1) {
@@ -1848,9 +2101,14 @@ as_sir_method <- function(method_short,
levels = c("FALSE", "NA", "TRUE")
)
# sort on host and taxonomic rank first, then by UTI
# (this will e.g. prefer 'species' breakpoints over 'order' breakpoints)
breakpoints_current <- breakpoints_current[order(breakpoints_current$rank_index, uti_index), , drop = FALSE]
# sort on taxonomic rank first (this will e.g. prefer 'species' breakpoints over 'order' breakpoints), within a rank on the site that the user set, then on whether it is a blocking row, on most to least systemic site, and finally on UTI
site_tokens_current <- if (is.na(site_current)) character(0) else strsplit(site_current, ",", fixed = TRUE)[[1]]
site_not_given <- vapply(breakpoints_current$site, function(s) !sir_site_given(sir_site_tokens(s), site_tokens_current), logical(1), USE.NAMES = FALSE)
if (length(site_tokens_current) == 0) {
site_not_given[] <- FALSE
}
site_rank <- vapply(breakpoints_current$site, sir_site_rank, double(1), USE.NAMES = FALSE)
breakpoints_current <- breakpoints_current[order(round(breakpoints_current$rank_index * 2) / 2, site_not_given, breakpoints_current$rank_index, site_rank, uti_index), , drop = FALSE]
# throw messages for different body sites
site <- breakpoints_current[1L, "site", drop = FALSE] # this is the one we'll take
@@ -1865,8 +2123,8 @@ as_sir_method <- function(method_short,
notes_current, "\n",
paste0("Breakpoints for ", font_bold(ab_formatted), " in ", mo_formatted, " are only available for (uncomplicated) urinary tract infections (UTI) - assuming `uti = TRUE`. Use `uti = FALSE` to prevent this.")
)
} else if (nrow(breakpoints_current) > 1 && length(unique(breakpoints_current$site)) > 1 && all(breakpoints_current$uti == FALSE, na.rm = TRUE) && message_not_thrown_before("as.sir", "siteOther", mo_current, ab_current)) {
# breakpoints for multiple body sites available
} else if (nrow(breakpoints_current) > 1 && length(unique(breakpoints_current$site)) > 1 && all(breakpoints_current$uti == FALSE, na.rm = TRUE)) {
# breakpoints for multiple body sites available, noted for every interpretation so that sir_interpretation_history() shows it
notes_current <- paste0(
notes_current, "\n",
paste0("Multiple breakpoints available for ", font_bold(ab_formatted), " in ", mo_formatted, " - assuming ", site, ".")
@@ -1906,9 +2164,18 @@ as_sir_method <- function(method_short,
)
}
# EUCAST indicates that there is no S category with an off-scale S breakpoint of 0.001 mg/L (stored as 0.0001 in
# clinical_breakpoints), so that wild-type isolates are I; capped MICs such as "<=0.5" must then not be S or NI (#295)
# clinical_breakpoints holds breakpoints as published, so keep these for sir_interpretation_history() (#331)
breakpoint_S_R_published <- paste0(breakpoints_current[, "breakpoint_S", drop = TRUE], "-", breakpoints_current[, "breakpoint_R", drop = TRUE])
# EUCAST indicates that there is no S category with an off-scale S breakpoint of 0.001 mg/L, so that wild-type isolates are I, also below that value; capped MICs such as "<=0.5" must then not be S or NI (#295)
no_S_category <- method == "mic" & isTRUE(breakpoints_current$breakpoint_S <= 0.001)
if (method == "mic") {
# compare dilutions, not their notation, e.g. an MIC of 0.032 and a breakpoint of 0.03 are the same dilution (#331)
breakpoints_current$breakpoint_S <- mic_dilution_level(breakpoints_current$breakpoint_S)
breakpoints_current$breakpoint_R <- mic_dilution_level(breakpoints_current$breakpoint_R)
if (guideline_current %like% "EUCAST" && !custom_breakpoints_set && isTRUE(breakpoints_current$breakpoint_S == 0.001)) {
breakpoints_current$breakpoint_S <- 0.0001
}
}
middle_sir <- if (isTRUE(breakpoints_current$is_SDD)) as.sir("SDD") else as.sir("I")
clsi_closed_R <- !custom_breakpoints_set & guideline_current %like% "CLSI"
capped_low_not_R <- (as.character(input_original) %like% "^<[0-9]" & as.double(input_clean) <= breakpoints_current$breakpoint_R) |
@@ -2097,7 +2364,8 @@ as_sir_method <- function(method_short,
guideline = vectorise_log_entry(guideline_current, length(rows)),
ref_table = vectorise_log_entry(breakpoints_current[, "ref_tbl", drop = TRUE], length(rows)),
uti = vectorise_log_entry(breakpoints_current[, "uti", drop = TRUE], length(rows)),
breakpoint_S_R = vectorise_log_entry(paste0(breakpoints_current[, "breakpoint_S", drop = TRUE], "-", breakpoints_current[, "breakpoint_R", drop = TRUE]), length(rows)),
breakpoint_S_R = vectorise_log_entry(breakpoint_S_R_published, length(rows)),
site = vectorise_log_entry(breakpoints_current[, "site", drop = TRUE], length(rows)),
stringsAsFactors = FALSE
)
out <- subset(out, !is.na(input_given))
BIN
View File
Binary file not shown.
+1 -1
View File
@@ -15,7 +15,7 @@ Overview:
- Generates **antibiograms** - WISCA for empiric coverage estimates, or
traditional/syndromic for AMR surveillance
- Provides the **full microbiological taxonomy** of ~103 000 distinct
species and extensive info of ~630 antimicrobial drugs
species and extensive info of ~640 antimicrobial drugs
- Applies **CLSI 2011-2026** and **EUCAST 2011-2026** clinical and
veterinary breakpoints, and ECOFFs, for MIC and disk zone
interpretation
@@ -0,0 +1,158 @@
# ==================================================================== #
# TITLE: #
# AMR: An R Package for Working with Antimicrobial Resistance Data #
# #
# SOURCE CODE: #
# https://github.com/msberends/AMR #
# #
# PLEASE CITE THIS SOFTWARE AS: #
# Berends MS, Luz CF, Friedrich AW, et al. (2022). #
# AMR: An R Package for Working with Antimicrobial Resistance Data. #
# Journal of Statistical Software, 104(3), 1-31. #
# https://doi.org/10.18637/jss.v104.i03 #
# #
# Developed at the University of Groningen and the University Medical #
# Center Groningen in the Netherlands, in collaboration with many #
# colleagues from around the world, see our website. #
# #
# This R package is free software; you can freely use and distribute #
# it for both personal and commercial purposes under the terms of the #
# GNU General Public License version 2.0 (GNU GPL-2), as published by #
# the Free Software Foundation. #
# We created this package for both routine data analysis and academic #
# research and it was publicly released in the hope that it will be #
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR data analysis: https://amr-for-r.org #
# ==================================================================== #
# Compares the results of as.sir() between two builds of clinical_breakpoints, so that every changed interpretation is seen and explained, instead of only the changed rows.
#
# Each step runs from the command line, and a snapshot is made with the code and the data of the package folder that it is given, so that changes to as.sir() are compared as well:
#
# Rscript compare_clinical_breakpoints.R grid <grid.rds> <pkg_folder_old> <pkg_folder_new>
# Rscript compare_clinical_breakpoints.R snapshot <grid.rds> <pkg_folder> <snapshot.rds> [cores]
# Rscript compare_clinical_breakpoints.R diff <old.rds> <new.rds> <changes.csv> [explain.R]
#
# The file explain.R must define explain_change(), which takes the data.frame of changes and returns one reason per row (NA if unexplained). The diff step exits with status 1 if any change remains unexplained.
suppressPackageStartupMessages(library(dplyr))
# Species that test the fallback to a broader breakpoint, on top of the organisms that are in the table for an agent and method. These cover the exceptions and extensions that EUCAST and CLSI state in their tables.
sentinels <- c(
"Escherichia coli", "Klebsiella pneumoniae", "Klebsiella aerogenes", "Proteus mirabilis", "Morganella", "Morganella morganii", "Salmonella enterica", "Shigella flexneri", "Enterobacter cloacae", "Serratia marcescens", "Yersinia enterocolitica",
"Pseudomonas aeruginosa", "Pseudomonas putida", "Acinetobacter baumannii", "Stenotrophomonas maltophilia", "Burkholderia pseudomallei", "Burkholderia cepacia",
"Staphylococcus aureus", "Staphylococcus epidermidis", "Staphylococcus saprophyticus", "Staphylococcus lugdunensis", "Enterococcus faecalis", "Enterococcus faecium",
"Streptococcus pneumoniae", "Streptococcus pyogenes", "Streptococcus agalactiae", "Streptococcus mitis", "Haemophilus influenzae", "Haemophilus parainfluenzae", "Moraxella catarrhalis", "Neisseria gonorrhoeae", "Neisseria meningitidis",
"Listeria monocytogenes", "Campylobacter jejuni", "Pasteurella multocida", "Vibrio cholerae", "Aeromonas hydrophila", "Kingella kingae", "Corynebacterium diphtheriae", "Nocardia asteroides", "Bacillus anthracis", "Bacillus cereus", "Brucella melitensis",
"Bacteroides fragilis", "Bacteroides", "Parabacteroides distasonis", "Phocaeicola vulgatus", "Prevotella bivia", "Clostridioides difficile", "Clostridium perfringens", "Cutibacterium acnes",
"Candida albicans", "Aspergillus fumigatus"
)
load_breakpoints <- function(pkg) {
env <- new.env()
load(file.path(pkg, "data", "clinical_breakpoints.rda"), envir = env)
as.data.frame(env$clinical_breakpoints, stringsAsFactors = FALSE)
}
# One line per guideline, agent and method, with the organisms and the values to test: every breakpoint, one step to either side of it, and both ends of the scale
make_grid <- function(pkg_old, pkg_new) {
suppressMessages(devtools::load_all(pkg_new, quiet = TRUE))
sentinel_mo <- as.character(as.mo(sentinels, info = FALSE))
bind_rows(load_breakpoints(pkg_old), load_breakpoints(pkg_new)) |>
filter(type == "human") |>
mutate(across(c(guideline, method, ab, mo, site), as.character)) |>
group_by(guideline, ab, method) |>
summarise(
has_screening = any(grepl("screen", site, ignore.case = TRUE)),
mo = list(unique(c(setdiff(mo, "UNKNOWN"), sentinel_mo))),
breakpoints = list(unique(c(as.double(breakpoint_S), as.double(breakpoint_R)))),
.groups = "drop"
) |>
mutate(value = Map(test_values, breakpoints, method)) |>
select(-breakpoints)
}
test_values <- function(breakpoints, method) {
breakpoints <- breakpoints[!is.na(breakpoints)]
if (method == "MIC") {
sort(unique(c(0.001, 512, breakpoints / 2, breakpoints, breakpoints * 2)))
} else {
sort(unique(c(6, 50, breakpoints - 1, breakpoints, breakpoints + 1)))
}
}
snapshot_key <- function(key) {
screening <- if (key$has_screening) c(FALSE, TRUE) else FALSE
combinations <- expand.grid(
mo = key$mo[[1]], value = key$value[[1]], uti = c(NA, FALSE, TRUE), include_screening = screening,
stringsAsFactors = FALSE
)
out <- lapply(split(combinations, paste(combinations$uti, combinations$include_screening)), function(part) {
uti <- part$uti[1]
# keep the interpretation log per row, it shows which breakpoint was used
invisible(sir_interpretation_history(clean = TRUE))
x <- if (key$method == "MIC") as.mic(part$value) else as.disk(part$value)
part$sir <- as.character(suppressWarnings(suppressMessages(as.sir(
x,
mo = part$mo, ab = key$ab, guideline = key$guideline, uti = uti, include_screening = part$include_screening[1], info = FALSE
))))
used <- as.data.frame(sir_interpretation_history(clean = TRUE), stringsAsFactors = FALSE)
part$breakpoint_used <- used$breakpoint_S_R[match(seq_len(nrow(part)), used$index)]
part$ref_table <- used$ref_table[match(seq_len(nrow(part)), used$index)]
part
})
bind_rows(out) |> mutate(guideline = key$guideline, ab = key$ab, method = key$method)
}
make_snapshot <- function(grid, pkg, cores = 1L) {
suppressMessages(devtools::load_all(pkg, quiet = TRUE))
keys <- split(grid, seq_len(nrow(grid)))
results <- parallel::mclapply(keys, function(key) {
tryCatch(snapshot_key(key), error = function(e) data.frame(guideline = key$guideline, ab = key$ab, method = key$method, error = conditionMessage(e)))
}, mc.cores = cores, mc.preschedule = FALSE)
bind_rows(results)
}
compare_snapshots <- function(old, new) {
by <- c("guideline", "ab", "method", "mo", "value", "uti", "include_screening")
full_join(old, new, by = by, suffix = c("_old", "_new")) |>
filter(
paste(sir_old) != paste(sir_new) | paste(breakpoint_used_old) != paste(breakpoint_used_new)
)
}
args <- commandArgs(trailingOnly = TRUE)
if (length(args) > 0) {
if (args[1] == "grid") {
saveRDS(make_grid(args[3], args[4]), args[2])
} else if (args[1] == "snapshot") {
cores <- if (length(args) >= 5) as.integer(args[5]) else 1L
snapshot <- make_snapshot(readRDS(args[2]), args[3], cores)
if ("error" %in% colnames(snapshot) && any(!is.na(snapshot$error))) {
print(snapshot |> filter(!is.na(error)) |> distinct(guideline, ab, method, error) |> head(50))
stop("the snapshot has errors, see above")
}
saveRDS(snapshot, args[4])
message("Snapshot of ", nrow(snapshot), " interpretations saved")
} else if (args[1] == "diff") {
old <- readRDS(args[2])
new <- readRDS(args[3])
message("Compared: ", nrow(old), " and ", nrow(new), " interpretations")
changes <- compare_snapshots(old, new)
changes$reason <- NA_character_
if (length(args) >= 5) {
source(args[5], local = TRUE)
changes$reason <- explain_change(changes)
}
write.csv(changes, args[4], row.names = FALSE, na = "")
print(as.data.frame(changes |> count(reason, guideline)), row.names = FALSE)
message(nrow(changes), " changes, of which ", sum(is.na(changes$reason)), " unexplained")
if (anyNA(changes$reason)) {
quit(save = "no", status = 1)
}
} else {
stop("unknown step: ", args[1])
}
}
@@ -931,6 +931,32 @@ antimicrobials <- antimicrobials |>
)
# add the screening agents of #328, for all explicit screening tests in clinical_breakpoints; agreed by the maintainer in that issue
for (agent in c("CHL", "CIP", "COL", "ERY", "FUS", "GEN", "LVX", "MUP", "NEO", "OFX", "RTP", "STR1", "TOB")) {
antimicrobials <- antimicrobials |>
mutate(ab = as.character(ab)) |>
bind_rows(
antimicrobials |>
mutate(ab = as.character(ab)) |>
filter(ab == agent) |>
mutate(
abbreviations = list(paste(tolower(ab), "screen")),
ab = paste0(ab, "-S"),
name = paste(name, "screening test"),
cid = NA,
atc = list(character(0)),
atc_group1 = NA_character_,
atc_group2 = NA_character_,
synonyms = list(character(0)),
oral_ddd = NA_real_,
oral_units = NA_character_,
iv_ddd = NA_real_,
iv_units = NA_character_,
loinc = list(character(0))
)
)
}
# add pretomanid
antimicrobials <- antimicrobials %>%
mutate(ab = as.character(ab)) %>%
@@ -720,7 +720,8 @@ breakpoints_new <- breakpoints_new |>
mo_rank(mo, keep_synonyms = TRUE) == "genus" ~ 3,
mo_rank(mo, keep_synonyms = TRUE) == "family" ~ 4,
mo_rank(mo, keep_synonyms = TRUE) == "order" ~ 5,
mo != "UNKNOWN" ~ 6, # for B_ANAER, etc.
grepl("^B_ANAER", as.character(mo)) ~ 5.5, # anaerobes are more specific than a Gram stain
mo != "UNKNOWN" ~ 6, # for B_GRAMN, etc.
TRUE ~ 7
) +
# a breakpoint of the same organism always precedes its blocking row
@@ -729,6 +730,61 @@ breakpoints_new <- breakpoints_new |>
arrange(desc(guideline), mo, ab, type, host, method)
clinical_breakpoints <- merge_eucast_breakpoints(breakpoints_new, breakpoints_eucast, eucast_coverage)
# Screening tests ----
# Every explicit screening test is stored under its screening agent, so that it can never be taken for a breakpoint of the regular agent (#328). The EUCAST rows from its own tables already are, see reproduction_of_clinical_breakpoints_eucast.R. This takes care of the WHONET-based rows, as decided in #328:
# - all rows with a site that states screening
# - high-level aminoglycoside tests: GEH and STH to GEN-S and STR1-S (as.sir() keeps accepting GEH and STH)
# - cefoxitin MIC for S. aureus and S. lugdunensis in EUCAST 2012-2018, which from 2019 on is labelled as screening
# - CLSI surrogate tests: cefoxitin for staphylococci, and pefloxacin for Salmonella
# EUCAST 2011-2013 rows without a label stay under the regular agent, also as decided in #328.
screening_year <- as.integer(gsub("[^0-9]", "", clinical_breakpoints$guideline))
screening_genus <- mo_genus(clinical_breakpoints$mo, keep_synonyms = TRUE, language = NULL)
is_human <- clinical_breakpoints$type == "human"
is_screening <- (!is.na(clinical_breakpoints$site) & grepl("screen", clinical_breakpoints$site, ignore.case = TRUE) & !grepl("-S$", as.character(clinical_breakpoints$ab))) |
(is_human & clinical_breakpoints$guideline %like% "EUCAST" & screening_year %in% 2012:2018 & clinical_breakpoints$ab == "FOX" & clinical_breakpoints$method == "MIC" & as.character(clinical_breakpoints$mo) %in% c("B_STPHY_AURS", "B_STPHY_LGDN")) |
(is_human & clinical_breakpoints$guideline %like% "CLSI" & clinical_breakpoints$ab == "FOX" & screening_genus %in% "Staphylococcus") |
(is_human & clinical_breakpoints$guideline %like% "CLSI" & screening_year >= 2015 & clinical_breakpoints$ab == "PEF" & screening_genus %in% "Salmonella")
message("NOTE: ", sum(is_screening), " WHONET-based row(s) moved to their screening agent")
clinical_breakpoints$ab <- as.character(clinical_breakpoints$ab)
clinical_breakpoints$ab[is_screening] <- paste0(clinical_breakpoints$ab[is_screening], "-S")
clinical_breakpoints$ab[clinical_breakpoints$ab == "GEH"] <- "GEN-S"
clinical_breakpoints$ab[clinical_breakpoints$ab == "STH"] <- "STR1-S"
if (any(!clinical_breakpoints$ab %in% AMR::antimicrobials$ab)) {
stop("agent(s) missing from the antimicrobials data set: ", toString(unique(clinical_breakpoints$ab[!clinical_breakpoints$ab %in% AMR::antimicrobials$ab])))
}
clinical_breakpoints$ab <- as.ab(clinical_breakpoints$ab)
# Blocking rows ----
# A blocking row of EUCAST only stays if it has an effect: as.sir() must give another result without it (#326). This uses as.sir() itself, so that it follows the same fallback path. The most specific rows are compared first, so that of two blocking rows on one path, the row that is needed stays. The build stops if this leaves any row without an effect.
is_pruned_group <- clinical_breakpoints$type == "human" & grepl("EUCAST 20(19|2[0-9])", clinical_breakpoints$guideline)
blocking_key <- paste(clinical_breakpoints$guideline, clinical_breakpoints$ab, clinical_breakpoints$method)
keys_with_blocking <- unique(blocking_key[is_pruned_group & is.na(clinical_breakpoints$breakpoint_S) & is.na(clinical_breakpoints$breakpoint_R)])
keep_per_key <- parallel::mclapply(keys_with_blocking, function(key) {
rows <- which(is_pruned_group & blocking_key == key)
group <- clinical_breakpoints[rows, , drop = FALSE]
kept <- rep(TRUE, nrow(group))
for (i in order(group$rank_index)) {
if (is.na(group$breakpoint_S[i]) && is.na(group$breakpoint_R[i])) {
position <- sum(kept[seq_len(i)])
if (!AMR:::blocking_row_is_needed(position, group[kept, , drop = FALSE])) {
kept[i] <- FALSE
}
}
}
rows[!kept]
}, mc.cores = 8L, mc.preschedule = FALSE)
if (any(vapply(keep_per_key, inherits, logical(1), what = "try-error"))) {
print(keep_per_key[vapply(keep_per_key, inherits, logical(1), what = "try-error")][[1]])
stop("pruning blocking rows failed, see above")
}
rows_without_effect <- unlist(keep_per_key)
message("NOTE: ", length(rows_without_effect), " blocking row(s) of EUCAST removed, since as.sir() gives the same results without them")
if (length(rows_without_effect) > 0) {
clinical_breakpoints <- clinical_breakpoints[-rows_without_effect, , drop = FALSE]
}
rm(is_pruned_group, blocking_key, keys_with_blocking, keep_per_key, rows_without_effect)
usethis::use_data(clinical_breakpoints, overwrite = TRUE, compress = "xz", version = 2)
rm(clinical_breakpoints)
devtools::load_all(".")
@@ -53,7 +53,8 @@ devtools::load_all()
# parsing so that every one of them can be reviewed
parse_log <- new.env()
parse_log$disk_dose_inherited <- NULL
parse_log$mic_scope_extensions <- NULL
parse_log$scope_extensions <- NULL
parse_log$scope_restrictions <- NULL
parse_log$no_breakpoints_determined <- NULL
# ==============================================================================
@@ -469,6 +470,11 @@ resolve_notes <- function(notes_list, mic_super, disk_super, abbreviations = lis
# ==============================================================================
# 4. Cell helpers
# ==============================================================================
# The address of a cell in a workbook, e.g. "B12", kept with every parsed breakpoint so that it can be verified against its source
cell_address <- function(r, c) {
paste0(LETTERS[c], r)
}
get_cell <- function(df, r, c) {
hit <- df[df$row == r & df$col == c, ]
if (nrow(hit) == 0) {
@@ -494,7 +500,7 @@ parse_bp <- function(txt) {
t <- trimws(txt)
# placeholders such as "-" (susceptibility testing not recommended), "IE"
# or "Note" are kept as they are: the cleanup turns them into blocking rows
# Parenthesised values like "(2)" are EUCAST's "breakpoints in brackets" (see is_bracketed_bp()). They are kept as they are in the raw file, so that they remain distinguishable from clinical breakpoints. The cleanup turns them into blocking rows as well, with breakpoint_S and breakpoint_R set to NA and the bracketed values stated in the note (see "Blocking rows"). Like any blocking row, it is left out of clinical_breakpoints where the organism has a (non-screening) breakpoint of its own for the same agent, method and UTI status (see "Pruning blocking rows").
# Parenthesised values like "(2)" are EUCAST's "breakpoints in brackets" (see is_bracketed_bp()). The raw data retain these values and their EUCAST definition. They are excluded before clinical breakpoint cleanup, so they do not generate blocking rows or prevent PK-PD fallback.
t
}
@@ -604,16 +610,18 @@ parse_sheet <- function(xlsx_path, sheet_name, abbreviations = list()) {
# --- Parse rich text for cols A:I ---
parsed <- parse_cells(cells |> filter(col >= 1, col <= 9), formats)
# --- Statements extending MIC breakpoints to another species ---
# --- Statements extending breakpoints to other organisms ---
# The H. influenzae sheet states (v9.0-v16.1): "In the absence of specific
# breakpoints, the H. influenzae MIC breakpoints can be applied to H.
# parainfluenzae." This applies to MIC breakpoints only, not to zone
# diameters. Such statements are logged here (with the sheet's own text)
# and applied in the cleanup section, see `parse_log$mic_scope_extensions`.
# and applied in the cleanup section, see `parse_log$scope_extensions`.
# Any other "breakpoints can be applied to <species>" statement that this
# pattern does not recognise stops the script, so that it is not missed.
sheet_text <- unique(parsed$full_text[!is.na(parsed$full_text) & parsed$col == 1])
scope_pattern <- "In the absence of specific breakpoints, the ([A-Z])\\. ([a-z]+) MIC ?breakpoints can be applied to ([A-Z])\\. ([a-z]+)\\."
bacteroides_pattern <- "Breakpoints for Bacteroides spp\\. are also valid for Parabacteroides spp\\. and for Phocaeicola dorei/vulgatus"
vibrio_pattern <- "Breakpoints are valid for V\\. alginolyticus, V\\. cholerae, V\\. fluvialis, V\\. parahaemolyticus and V\\. vulnificus\\."
for (txt in sheet_text) {
txt_squished <- gsub("\\s+", " ", txt)
m <- regmatches(txt_squished, regexec(scope_pattern, txt_squished))[[1]]
@@ -621,16 +629,16 @@ parse_sheet <- function(xlsx_path, sheet_name, abbreviations = list()) {
sheet_title <- trimws(get_cell(parsed, 1, 1)$base)
genus <- sub("\\s.*$", "", sheet_title)
if (substr(genus, 1, 1) != m[2] || m[2] != m[4]) {
stop("parse_sheet(): MIC scope statement on sheet '", sheet_name, "' does not match the sheet's genus '", genus, "': ", m[1])
stop("parse_sheet(): scope statement on sheet '", sheet_name, "' does not match the sheet's genus '", genus, "': ", m[1])
}
parse_log$mic_scope_extensions <- rbind(
parse_log$mic_scope_extensions,
parse_log$scope_extensions <- rbind(
parse_log$scope_extensions,
data.frame(
guideline = ver$guideline, sheet = sheet_name,
from_text = paste(genus, m[3]), to_text = paste(genus, m[5]), statement = m[1]
from_text = paste(genus, m[3]), to_text = paste(genus, m[5]), statement = m[1], method = "MIC"
)
)
} else if (grepl("breakpoints can (also )?be applied to [A-Z]\\.", txt_squished)) {
} else if (grepl("breakpoints can (also )?be applied to [A-Z]\\.|breakpoints for .* are also valid for|breakpoints are (only )?valid for [A-Z]\\.", txt_squished, ignore.case = TRUE) && !grepl(paste0(bacteroides_pattern, "|", vibrio_pattern), txt_squished)) {
stop(
"parse_sheet(): unrecognised statement about applying breakpoints to another species on sheet '",
sheet_name, "': ", substr(txt_squished, 1, 300)
@@ -638,6 +646,43 @@ parse_sheet <- function(xlsx_path, sheet_name, abbreviations = list()) {
}
}
# EUCAST extends the Bacteroides breakpoints to these taxa, for both methods. Any other wording of such a statement stops the script, see above.
statement <- sheet_text[grepl(bacteroides_pattern, gsub("\\s+", " ", sheet_text))]
if (length(statement) > 0) {
extension <- expand.grid(
to_text = c("Parabacteroides", "Phocaeicola dorei", "Phocaeicola vulgatus"),
method = c("MIC", "DISK"), stringsAsFactors = FALSE
)
parse_log$scope_extensions <- bind_rows(
parse_log$scope_extensions,
extension |>
mutate(
guideline = ver$guideline,
sheet = sheet_name,
from_text = "Bacteroides",
statement = regmatches(gsub("\\s+", " ", statement[1]), regexpr(paste0(bacteroides_pattern, "[^.]*\\."), gsub("\\s+", " ", statement[1])))
)
)
}
# EUCAST limits the Vibrio breakpoints to these species, for both methods, so the rows of the genus are replaced by rows of these species in the cleanup section. Any other wording of such a statement stops the script, see above.
statement <- sheet_text[grepl(vibrio_pattern, gsub("\\s+", " ", sheet_text))]
if (length(statement) > 0) {
extension <- expand.grid(
to_text = c("Vibrio alginolyticus", "Vibrio cholerae", "Vibrio fluvialis", "Vibrio parahaemolyticus", "Vibrio vulnificus"),
method = c("MIC", "DISK"), stringsAsFactors = FALSE
)
statement <- regmatches(gsub("\\s+", " ", statement[1]), regexpr(vibrio_pattern, gsub("\\s+", " ", statement[1])))
parse_log$scope_extensions <- bind_rows(
parse_log$scope_extensions,
extension |> mutate(guideline = ver$guideline, sheet = sheet_name, from_text = "Vibrio", statement = statement)
)
parse_log$scope_restrictions <- bind_rows(
parse_log$scope_restrictions,
data.frame(guideline = ver$guideline, sheet = sheet_name, from_text = "Vibrio")
)
}
# --- Detect header rows (col 2 contains "MIC breakpoint") ---
header_rows <- parsed |>
filter(col == 2, grepl("MIC breakpoint", base_text, fixed = TRUE)) |>
@@ -982,6 +1027,8 @@ parse_sheet <- function(xlsx_path, sheet_name, abbreviations = list()) {
disk_dose = NA_character_,
breakpoint_S = s_val,
breakpoint_R = r_val,
source_S = cell_address(r, 2),
source_R = cell_address(r, 3),
is_bracketed = is_bracketed_bp(mic_s$base) || is_bracketed_bp(mic_r$base),
note = mic_note
)
@@ -1007,6 +1054,8 @@ parse_sheet <- function(xlsx_path, sheet_name, abbreviations = list()) {
disk_dose = disk_dose,
breakpoint_S = s_val,
breakpoint_R = r_val,
source_S = cell_address(r, 6),
source_R = cell_address(r, 7),
is_bracketed = is_bracketed_bp(disk_s$base) || is_bracketed_bp(disk_r$base),
note = disk_note
)
@@ -1146,6 +1195,7 @@ parse_topical_sheet <- function(xlsx_path, abbreviations = list()) {
ab = ab_name,
disk_dose = NA_character_,
breakpoint_S = mic_val, breakpoint_R = mic_val,
source_S = cell_address(od$mic_row, col_idx), source_R = cell_address(od$mic_row, col_idx),
is_bracketed = is_bracketed_bp(mic_cell$base),
note = mic_note
)
@@ -1167,6 +1217,7 @@ parse_topical_sheet <- function(xlsx_path, abbreviations = list()) {
ab = ab_name,
disk_dose = ab_dose,
breakpoint_S = disk_val, breakpoint_R = disk_val,
source_S = cell_address(od$disk_row, col_idx), source_R = cell_address(od$disk_row, col_idx),
is_bracketed = is_bracketed_bp(disk_cell$base),
note = disk_note
)
@@ -1324,6 +1375,8 @@ parse_yeast_sheet <- function(xlsx_path, sheet_name, abbreviations = list()) {
disk_dose = NA_character_,
breakpoint_S = s_val,
breakpoint_R = r_val,
source_S = cell_address(r, sb$s_col),
source_R = cell_address(r, sb$r_col),
is_bracketed = is_bracketed_bp(s_cell$base) || is_bracketed_bp(r_cell$base),
note = note_text
)
@@ -1534,6 +1587,44 @@ if (!is.null(parse_log$disk_dose_inherited)) {
print(parse_log$disk_dose_inherited)
}
# Every parsed value must be in the workbook cell that it is said to come from. This reads the workbooks a second time with another package than the parser, so that it does not share the parser's assumptions. Note references are superscript text in the same cell, hence the comparison with the start of the cell.
verify_raw_against_workbooks <- function(raw) {
files <- list.files("data-raw", pattern = "^v_[0-9.]+_.*Breakpoint_Tables[.]xlsx$", full.names = TRUE)
file_of_version <- function(version, file_desc) {
hit <- files[grepl(paste0("v_0?", version, "_"), basename(files), fixed = FALSE) & grepl("Antifungal", basename(files), fixed = TRUE) == grepl("Antifungal", file_desc, fixed = TRUE)]
if (length(hit) != 1) stop("no single workbook found for version ", version, " (", file_desc, ")")
hit
}
keys <- distinct(raw, version, file_desc, sheet)
for (i in seq_len(nrow(keys))) {
rows <- raw[raw$version == keys$version[i] & raw$file_desc == keys$file_desc[i] & raw$sheet == keys$sheet[i], , drop = FALSE]
sheet <- suppressMessages(as.data.frame(readxl::read_excel(
file_of_version(keys$version[i], keys$file_desc[i]),
sheet = keys$sheet[i], col_names = FALSE, col_types = "text", .name_repair = "minimal", range = readxl::cell_limits(c(1, 1), c(NA, NA))
)))
cell_text <- function(address) {
r <- as.integer(sub("^[A-Z]+", "", address))
c <- match(sub("[0-9]+$", "", address), LETTERS)
vapply(seq_along(address), function(j) {
if (r[j] > nrow(sheet) || c[j] > ncol(sheet)) NA_character_ else trimws(gsub("\\s+", " ", sheet[r[j], c[j]]))
}, character(1))
}
for (side in c("S", "R")) {
value <- trimws(rows[[paste0("breakpoint_", side)]])
has_value <- !is.na(value) & nzchar(value)
text <- cell_text(rows[[paste0("source_", side)]])
# numbers can be stored as numeric cells, read as text with a different notation
matches <- startsWith(coalesce(text, ""), coalesce(value, "")) | (suppressWarnings(as.numeric(text)) %in% suppressWarnings(as.numeric(value)))
if (any(has_value & !matches)) {
print(cbind(rows[has_value & !matches, c("guideline", "sheet", "mo", "ab", "method", paste0("breakpoint_", side), paste0("source_", side))], in_cell = text[has_value & !matches]))
stop("parsed breakpoint(s) not found in the workbook cell that they come from, see above")
}
}
}
invisible(TRUE)
}
verify_raw_against_workbooks(breakpoints_eucast_raw)
saveRDS(breakpoints_eucast_raw, "data-raw/breakpoints_eucast_raw.rds")
write.csv(breakpoints_eucast_raw, "data-raw/breakpoints_eucast_raw.csv", row.names = FALSE, eol = "\n")
@@ -1980,8 +2071,7 @@ split_mo_list_one <- function(s, sheet_genus_fallback) {
# organism (e.g. for another route, or a screening breakpoint when
# as.sir(..., include_screening = TRUE)) always takes precedence. Blocking rows
# arise from:
# 1. cells with "IE", "-", "Note", "IP", "NA" or "ND", and EUCAST's
# breakpoints in brackets (see is_bracketed_bp());
# 1. cells with "IE", "-", "Note", "IP", "NA" or "ND";
# 2. organisms excluded with "except" or "other than", e.g. "Bacillus spp.
# except B. anthracis" or "Klebsiella spp. (except K. aerogenes)";
# 3. restrictions in the notes, see eucast_note_rules;
@@ -2008,10 +2098,11 @@ blocking_note <- function(reason, note) {
}
breakpoints_eucast <- breakpoints_eucast_raw |>
# Exclude bracketed values before generating blockers, including scope blockers.
filter(!is_bracketed) |>
mutate(
is_blocker = is_bracketed | (!is_bp_value(breakpoint_S) & !is_bp_value(breakpoint_R)),
is_blocker = !is_bp_value(breakpoint_S) & !is_bp_value(breakpoint_R),
note = case_when(
is_bracketed ~ blocking_note(paste0("EUCAST gives breakpoints in brackets only (S ", breakpoint_S, ", R ", breakpoint_R, ")"), note),
is_blocker ~ blocking_note(paste0(
"EUCAST gives ",
coalesce(
@@ -2204,8 +2295,18 @@ breakpoints_eucast <- breakpoints_eucast |>
# also fixes a source cell missing a space before "(", e.g. "Meropenem(indications..."
ab_input = gsub("\\s*\\(.*$", "", ab),
ab_input = trimws(sub("\\s+(iv|i\\.v\\.|oral)$", "", ab_input, ignore.case = TRUE)),
ab = as.ab(ab_input)
)
ab = as.ab(ab_input),
# every screening test is stored under its screening agent (e.g. FOX-S), so that it can never be taken for a breakpoint of the regular agent (#328)
is_screening_row = !is.na(site) & grepl("Screen", site, fixed = TRUE),
ab = as.ab(if_else(is_screening_row, paste0(as.character(ab), "-S"), as.character(ab))),
# the agent now holds the screening meaning; the topical cut-off values remain distinguishable from systemic screening tests by their site
site = if_else(site %in% "Topical, Screen", "Topical", site)
) |>
select(-is_screening_row)
if (any(!is.na(breakpoints_eucast$ab_input) & grepl("Screen", breakpoints_eucast$site, fixed = TRUE) & is.na(breakpoints_eucast$ab))) {
print(distinct(filter(breakpoints_eucast, grepl("Screen", site, fixed = TRUE), is.na(ab)), ab_input))
stop("screening agent(s) missing from the antimicrobials data set, see above")
}
# ab_previously_coerced also logs every intermediate word-by-word fallback
# as.ab() tries internally while resolving a route-suffixed name (e.g. for
@@ -2305,10 +2406,10 @@ taxon_contains <- function(broad, narrow) {
broad == as.character(as.mo(mo_order(narrow, keep_synonyms = TRUE), info = FALSE)) |
broad %in% AMR::microorganisms.groups$mo_group[AMR::microorganisms.groups$mo == as.character(narrow)]
}
to_blocker <- function(df, reason) {
to_blocker <- function(df, reason, site = NA_character_) {
df |> mutate(
is_blocker = TRUE, breakpoint_S = NA_character_, breakpoint_R = NA_character_,
site = NA_character_, note = blocking_note(reason, note)
site = site, note = blocking_note(reason, note)
)
}
for (i in seq_len(nrow(eucast_note_rules))) {
@@ -2386,6 +2487,11 @@ for (i in seq_len(nrow(eucast_note_rules))) {
# staphylococci except S. epidermidis and S. lugdunensis" then applies to
# the identified CoNS species (one row per species), while the CoNS group
# itself (an isolate only identified as CoNS) gets 25 mm.
# 4. The oxacillin disk for staphylococci in which cefoxitin is less predictive, e.g. S. pseudintermedius: "Use the oxacillin 1 ug disk with zone diameter breakpoints S>=20, R<20 mm". Stored under OXA-S.
# 5. The oxacillin MIC for coagulase-negative staphylococci: "For coagulase-negative staphylococci other than S. saprophyticus and S. lugdunensis, the oxacillin MIC in methicillin resistant isolates is >0.25 mg/L". Stored under OXA-S, with blocking rows for these two species. The oxacillin statements for S. aureus, S. lugdunensis and S. saprophyticus read "mostly methicillin resistant", and are hedged, unlike the cefoxitin statements.
# 6. Mupirocin for nasal decolonisation of S. aureus: "Breakpoints for nasal decontamination S <=1, R >256 mg/L (S >=30, R <18 mm for the mupirocin 200 ug disk)". Stored under MUP, not as a screening test, with site "Topical".
# 7. Meropenem for N. meningitidis in other infections: "The meningitis breakpoint can be used to categorise meropenem for other serious infections".
# Not taken over: statements about a surrogate agent without an agent of its own in this package (kanamycin for amikacin), provisional values (pretomanid), statements about wild-type populations, about countries that prefer another approach, and about inferring other agents.
# Statements that are not breakpoints, such as ECOFFs ("There are no clinical
# breakpoints but acquired resistance (indicated by MIC >1 mg/L) should be
# excluded") or hedged ones ("... with oxacillin MIC values >2 mg/L are mostly
@@ -2396,13 +2502,13 @@ derived_rows <- list()
hlar_rows <- breakpoints_eucast |>
filter(
grepl("Negative test: Isolates with (gentamicin|streptomycin) MIC \u2264", note),
ab %in% c("GEN", "STR1"), site %in% "Screen"
ab %in% c("GEN-S", "STR1-S"), site %in% "Screen"
)
for (r in seq_len(nrow(hlar_rows))) {
row <- hlar_rows[r, ]
# the note of a row can also hold the test for the other agent, so the
# agent is taken from the row itself
agent <- c(GEN = "gentamicin", STR1 = "streptomycin")[as.character(row$ab)]
agent <- c("GEN-S" = "gentamicin", "STR1-S" = "streptomycin")[as.character(row$ab)]
if (is.na(agent)) stop("unexpected agent for a high-level aminoglycoside screening test: ", row$ab)
neg <- regmatches(row$note, regexec(paste0("Negative test: Isolates with ", agent, " MIC \u2264([0-9]+) mg/L(?: or a zone diameter \u2265([0-9]+) mm)?"), row$note, perl = TRUE))[[1]]
pos <- regmatches(row$note, regexec(paste0("Positive test: Isolates with ", agent, " MIC >([0-9]+) mg/L(?: or a zone diameter <([0-9]+) mm)?"), row$note, perl = TRUE))[[1]]
@@ -2413,14 +2519,29 @@ for (r in seq_len(nrow(hlar_rows))) {
if (!nzchar(value)) next # e.g. no zone diameter given in this version
derived_rows[[length(derived_rows) + 1]] <- row |>
mutate(
ab = as.ab(if (agent == "gentamicin") "GEH" else "STH"), site = NA_character_, is_blocker = FALSE,
site = "Screen", is_blocker = FALSE,
breakpoint_S = value, breakpoint_R = value,
note = sub("^\\[No breakpoint\\][^|]*(\\| )?", "", note)
)
}
# EUCAST states that some clinical breakpoints can also be used as a screening test, e.g. "Erythromycin can be used to screen for macrolide resistance in staphylococci". These stay under the regular agent, with a copy under the screening agent (#328).
also_screening <- breakpoints_eucast |>
filter(
!is_blocker, !grepl("-S$", as.character(ab)), !site %in% c("Screen", "Topical"),
(ab == "ERY" & grepl("Erythromycin can be used to screen", note, fixed = TRUE)) |
(ab == "TCY" & grepl("Tetracycline can be used to screen", note, fixed = TRUE)) |
(ab == "PEN" & grepl("Benzylpenicillin( 1 unit| \\(MIC or disk diffusion\\))? can be used to screen", note)) |
(ab == "NAL" & grepl("nalidixic acid disk diffusion test can be used to screen", note, fixed = TRUE)) |
(ab == "NOR" & grepl("norfloxacin disk diffusion test can be used to screen", note, fixed = TRUE))
) |>
mutate(ab = as.ab(paste0(as.character(ab), "-S")), site = "Screen")
message("NOTE: ", nrow(also_screening), " clinical breakpoint row(s) copied to their screening agent, as EUCAST also allows them as a screening test")
breakpoints_eucast <- breakpoints_eucast |>
bind_rows(also_screening)
fox_mic <- breakpoints_eucast |>
filter(
ab == "FOX", method == "MIC",
ab == "FOX-S", method == "MIC",
grepl("S\\. aureus and S\\. lugdunensis with cefoxitin MIC values >[0-9]+ mg/L and S\\. saprophyticus with cefoxitin MIC values >[0-9]+ mg/L are methicillin resistant", note)
) |>
distinct(guideline, .keep_all = TRUE)
@@ -2435,22 +2556,72 @@ for (r in seq_len(nrow(fox_mic))) {
)
}
}
strip_blocking_note <- function(x) sub("^\\[No breakpoint\\][^|]*(\\| )?", "", x)
squish <- function(x) gsub("\\s+", " ", x)
# 4. the oxacillin disk, for the organisms of the row with this note
oxa_disk_rule <- "Use the oxacillin 1 .?g disk with zone diameter breakpoints S\u2265([0-9]+), R<([0-9]+) mm"
oxa_disk <- breakpoints_eucast |>
filter(ab == "FOX-S", method == "DISK", grepl(oxa_disk_rule, squish(note))) |>
distinct(guideline, mo, .keep_all = TRUE)
for (r in seq_len(nrow(oxa_disk))) {
m <- regmatches(squish(oxa_disk$note[r]), regexec(oxa_disk_rule, squish(oxa_disk$note[r])))[[1]]
derived_rows[[length(derived_rows) + 1]] <- oxa_disk[r, ] |>
mutate(ab = as.ab("OXA-S"), site = "Screen", disk_dose = "1 mcg", is_blocker = FALSE, breakpoint_S = m[2], breakpoint_R = m[3], note = strip_blocking_note(note))
}
# 5. the oxacillin MIC for coagulase-negative staphylococci, except two species
oxa_mic_rule <- "For coagulase-negative staphylococci other than S\\. saprophyticus and S\\. lugdunensis, the oxacillin MIC in methicillin resistant (isolates|strains) is >([0-9.]+) mg/L"
oxa_mic <- breakpoints_eucast |>
filter(ab == "OXA", method == "MIC", grepl(oxa_mic_rule, squish(note))) |>
distinct(guideline, .keep_all = TRUE)
for (r in seq_len(nrow(oxa_mic))) {
m <- regmatches(squish(oxa_mic$note[r]), regexec(oxa_mic_rule, squish(oxa_mic$note[r])))[[1]]
row <- oxa_mic[r, ] |>
mutate(ab = as.ab("OXA-S"), site = "Screen", mo = as.mo("B_STPHY_CONS"), is_blocker = FALSE, breakpoint_S = m[3], breakpoint_R = m[3], note = strip_blocking_note(note))
derived_rows[[length(derived_rows) + 1]] <- row
for (sp in c("B_STPHY_SPRP", "B_STPHY_LGDN")) {
derived_rows[[length(derived_rows) + 1]] <- row |>
mutate(mo = as.mo(sp), is_blocker = TRUE, breakpoint_S = NA_character_, breakpoint_R = NA_character_, note = blocking_note(paste0("EUCAST: '", m[1], "'"), NA_character_))
}
}
# 6. mupirocin for nasal decolonisation; both notations of the zone diameters occur
mupirocin_rule <- "Breakpoints for nasal de[a-z]+[^(]*S \u2264([0-9]+), R >([0-9]+) mg/L \\((?:disk diffusion with mupirocin 200 .?g disk )?S \u2265([0-9]+), R <([0-9]+) mm"
mupirocin_rows <- breakpoints_eucast |>
filter(ab == "MUP-S", site %in% "Topical", grepl("Breakpoints for nasal de", squish(note), fixed = TRUE))
for (r in seq_len(nrow(mupirocin_rows))) {
m <- regmatches(squish(mupirocin_rows$note[r]), regexec(mupirocin_rule, squish(mupirocin_rows$note[r])))[[1]]
if (length(m) != 5) stop("unexpected wording of the mupirocin breakpoints in the note of ", mupirocin_rows$guideline[r], ": ", substr(mupirocin_rows$note[r], 1, 300))
values <- if (mupirocin_rows$method[r] == "MIC") m[2:3] else m[4:5]
derived_rows[[length(derived_rows) + 1]] <- mupirocin_rows[r, ] |>
mutate(ab = as.ab("MUP"), breakpoint_S = values[1], breakpoint_R = values[2])
}
# 7. meropenem for N. meningitidis
meropenem_rule <- "The meningitis breakpoint can be used to categorise meropenem for other serious infections"
meropenem_rows <- breakpoints_eucast |>
filter(ab == "MEM", is_blocker, !site %in% "Meningitis", grepl(meropenem_rule, squish(note), fixed = TRUE))
for (r in seq_len(nrow(meropenem_rows))) {
row <- meropenem_rows[r, ]
source_row <- breakpoints_eucast |>
filter(guideline == row$guideline, ab == "MEM", mo == row$mo, method == row$method, site %in% "Meningitis", !is_blocker)
if (nrow(source_row) != 1) stop("expected one breakpoint for meningitis in ", row$guideline, " for ", row$mo)
derived_rows[[length(derived_rows) + 1]] <- row |>
mutate(is_blocker = FALSE, breakpoint_S = source_row$breakpoint_S, breakpoint_R = source_row$breakpoint_R, note = strip_blocking_note(note))
}
if (length(derived_rows) > 0) {
derived <- bind_rows(derived_rows)
message(
"NOTE: ", nrow(derived), " screening breakpoint row(s) taken from the notes (",
"NOTE: ", nrow(derived), " breakpoint row(s) taken from the notes (",
paste(unique(paste(derived$guideline, derived$ab, derived$method)), collapse = ", "), ")"
)
breakpoints_eucast <- bind_rows(breakpoints_eucast, derived)
}
cons_rule <- "If coagulase-negative staphylococci are not identified to species level, use zone diameter breakpoints S\u2265([0-9]+), R<([0-9]+) mm"
for (g in unique(breakpoints_eucast$guideline[grepl(cons_rule, breakpoints_eucast$note) & breakpoints_eucast$ab == "FOX" & breakpoints_eucast$method == "DISK"])) {
rows <- which(breakpoints_eucast$guideline == g & breakpoints_eucast$ab == "FOX" & breakpoints_eucast$method == "DISK" &
for (g in unique(breakpoints_eucast$guideline[grepl(cons_rule, breakpoints_eucast$note) & breakpoints_eucast$ab == "FOX-S" & breakpoints_eucast$method == "DISK"])) {
rows <- which(breakpoints_eucast$guideline == g & breakpoints_eucast$ab == "FOX-S" & breakpoints_eucast$method == "DISK" &
breakpoints_eucast$mo == "B_STPHY_CONS" & !breakpoints_eucast$is_blocker)
if (length(rows) != 1) stop("expected one cefoxitin zone diameter row for coagulase-negative staphylococci in ", g)
m <- regmatches(breakpoints_eucast$note[rows], regexec(cons_rule, breakpoints_eucast$note[rows]))[[1]]
if (length(m) != 3 || m[2] != m[3]) stop("unexpected cefoxitin rule for unidentified CoNS in ", g)
own_rows <- unique(as.character(breakpoints_eucast$mo[breakpoints_eucast$guideline == g & breakpoints_eucast$ab == "FOX" &
own_rows <- unique(as.character(breakpoints_eucast$mo[breakpoints_eucast$guideline == g & breakpoints_eucast$ab == "FOX-S" &
breakpoints_eucast$method == "DISK" & breakpoints_eucast$mo != "B_STPHY_CONS"]))
members <- setdiff(as.character(AMR::microorganisms.groups$mo[AMR::microorganisms.groups$mo_group == "B_STPHY_CONS"]), own_rows)
species_rows <- breakpoints_eucast[rep(rows, length(members)), ]
@@ -2483,20 +2654,21 @@ if (any(is.na(table_scope$table_mo) | table_scope$table_mo == "UNKNOWN")) {
}
scope_blockers <- breakpoints_eucast |>
filter(sheet != "Topical agents", !grepl("^PK", sheet)) |>
distinct(guideline, sheet, table_organism, ab, method, .keep_all = TRUE) |>
distinct(guideline, sheet, table_organism, ab, method, site, .keep_all = TRUE) |>
inner_join(table_scope, by = c("guideline", "sheet", "table_organism"), relationship = "many-to-many") |>
mutate(mo = table_mo, note = NA_character_) |>
select(-table_mo) |>
to_blocker("EUCAST lists this agent in this table for other organisms only")
select(-table_mo)
scope_blockers <- to_blocker(scope_blockers, "EUCAST lists this agent in this table for other organisms only", site = scope_blockers$site)
breakpoints_eucast <- bind_rows(breakpoints_eucast, scope_blockers)
# Apply the statements that extend MIC breakpoints to another species (see
# parse_sheet(), "Statements extending MIC breakpoints to another species"):
# the MIC rows of the source species on that sheet are copied for the target
# Apply statements extending breakpoints to other organisms (see
# parse_sheet(), "Statements extending breakpoints to other organisms"):
# rows of the source organism and specified method are copied for the target
# species, with EUCAST's statement in the note. A breakpoint that the source
# gives for the target species itself always takes precedence.
if (!is.null(parse_log$mic_scope_extensions)) {
scope_ext <- parse_log$mic_scope_extensions |>
if (!is.null(parse_log$scope_extensions)) {
scope_ext <- parse_log$scope_extensions |>
distinct() |>
mutate(
from_mo = as.character(as.mo(from_text, info = FALSE)),
@@ -2504,13 +2676,12 @@ if (!is.null(parse_log$mic_scope_extensions)) {
)
if (anyNA(scope_ext$from_mo) || anyNA(scope_ext$to_mo) || any(c(scope_ext$from_mo, scope_ext$to_mo) == "UNKNOWN")) {
print(scope_ext)
stop("species in a MIC scope statement could not be resolved, see above")
stop("organisms in a scope statement could not be resolved, see above")
}
scope_rows <- breakpoints_eucast |>
filter(method == "MIC") |>
mutate(mo_chr = as.character(mo)) |>
inner_join(scope_ext |> select(guideline, sheet, mo_chr = from_mo, to_mo, statement),
by = c("guideline", "sheet", "mo_chr")
inner_join(scope_ext |> select(guideline, sheet, method, mo_chr = from_mo, to_mo, statement),
by = c("guideline", "sheet", "method", "mo_chr"), relationship = "many-to-many"
) |>
mutate(
mo = as.mo(to_mo),
@@ -2524,14 +2695,25 @@ if (!is.null(parse_log$mic_scope_extensions)) {
)
) |>
select(-mo_chr, -to_mo, -statement) |>
anti_join(breakpoints_eucast |> filter(method == "MIC"), by = c("guideline", "mo", "ab", "method", "site"))
anti_join(breakpoints_eucast, by = c("guideline", "mo", "ab", "method", "site"))
message(
"NOTE: ", nrow(scope_rows), " MIC breakpoint row(s) added following EUCAST's statement(s): ",
"NOTE: ", nrow(scope_rows), " breakpoint row(s) added following EUCAST's statement(s): ",
paste(unique(paste0(scope_ext$guideline, " ", scope_ext$from_text, " -> ", scope_ext$to_text)), collapse = ", ")
)
breakpoints_eucast <- bind_rows(breakpoints_eucast, scope_rows)
}
# A statement that limits breakpoints to certain species means that the rows of the genus do not apply to its other species, so these rows go, now that the species have their own
if (!is.null(parse_log$scope_restrictions)) {
restricted <- paste(parse_log$scope_restrictions$guideline, parse_log$scope_restrictions$sheet, as.character(as.mo(parse_log$scope_restrictions$from_text, info = FALSE)))
rows <- paste(breakpoints_eucast$guideline, breakpoints_eucast$sheet, as.character(breakpoints_eucast$mo)) %in% restricted
message("NOTE: ", sum(rows), " breakpoint row(s) of a genus removed following EUCAST's statement(s), in ", paste(unique(parse_log$scope_restrictions$guideline), collapse = ", "))
if (sum(rows) == 0 || !setequal(parse_log$scope_restrictions$guideline, paste("EUCAST", 2022:2026))) {
stop("unexpected result for the statement limiting the breakpoints of Vibrio to certain species")
}
breakpoints_eucast <- breakpoints_eucast[!rows, , drop = FALSE]
}
# Organisms for which EUCAST has not determined breakpoints at all ("EUCAST
# has not determined breakpoints for Burkholderia cepacia complex organisms",
# likewise L. pneumophila) must not be interpreted with the non-species
@@ -2572,32 +2754,18 @@ breakpoints_eucast <- breakpoints_eucast |>
# cannot introduce NAs (blocking rows are NA by design)
breakpoint_S = as.numeric(breakpoint_S),
breakpoint_R = as.numeric(breakpoint_R),
# EUCAST's "arbitrary, off scale" MIC breakpoint S <= 0.001 mg/L (from
# v10.0 on) is meant to categorise wild-type isolates as "I", not "S".
# MICs of 0.0005 mg/L and below do occur in vitro, so, as before, it is
# stored as 0.0001 mg/L to keep such isolates out of "S".
breakpoint_S = if_else(method == "MIC" & !is.na(breakpoint_S) & breakpoint_S == 0.001, 0.0001, breakpoint_S),
# same definition as used for the WHONET-based rows
uti = !is.na(site) & site %like% "(UTI|urinary|urine)",
is_SDD = FALSE # EUCAST has no "susceptible, dose dependent" category (CLSI-only concept)
) |>
# EUCAST prints the twofold dilutions below 0.125 mg/L rounded, e.g. 0.03 and
# 0.06 for 0.03125 and 0.0625, while this package (as.mic(), and the WHONET-
# based breakpoints of all other guidelines) uses 0.032 and 0.064. Since
# as.sir() compares values literally, an MIC of 0.064 would otherwise fall
# above an S breakpoint of 0.06. MIC breakpoints are therefore set to the
# package's dilution level they denote; a value that is not close to any
# dilution level stops the script. The raw data keep EUCAST's notation.
# MIC breakpoints are stored exactly as EUCAST publishes them, e.g. 0.03 and not 0.032, including the off-scale S <= 0.001 mg/L (#331). as.sir() takes care of different notations of the same dilution, see AMR:::mic_dilution_level(). A value that is not close to any dilution level stops the script.
mutate(across(c(breakpoint_S, breakpoint_R), function(x) {
if (!all(method %in% c("MIC", "DISK"))) stop("unexpected method")
is_mic <- method == "MIC" & !is.na(x)
levels <- AMR:::COMMON_MIC_VALUES
nearest <- vapply(x[is_mic], function(z) levels[which.min(abs(log2(z) - log2(levels)))], numeric(1))
off_level <- abs(log2(x[is_mic]) - log2(nearest)) > 0.15
off_level <- !AMR:::mic_dilution_level(x[is_mic]) %in% AMR:::COMMON_MIC_VALUES
if (any(off_level)) {
stop("MIC breakpoint(s) not on a dilution level: ", paste(unique(x[is_mic][off_level]), collapse = ", "))
}
x[is_mic] <- nearest
x
})) |>
# Greek symbols and EM dash symbols are not allowed by CRAN, so replace them with ASCII:
@@ -2627,17 +2795,17 @@ if (nrow(unresolved_mo) > 0 || nrow(unresolved_ab) > 0) {
}
# Pruning blocking rows ----
# A blocking row is only needed where its organism has no (non-screening) breakpoint of its own for that agent, method and UTI status, and blocking rows for the PK-PD table ("UNKNOWN") have no function. UTI status is part of the comparison, so that a breakpoint for UTI only does not remove the blocking row for other infections, e.g. Acinetobacter spp. and amikacin since v14.0: breakpoints in brackets for systemic infections, a breakpoint for infections originating from the urinary tract. Of several blocking rows for the same organism, agent, method and UTI status, the first is kept. Blocking rows for UTI keep their site, so that they remain distinguishable from the blocking row for other infections.
# A blocking row is not needed where its organism has a breakpoint of its own for the same agent, method and UTI status, and blocking rows for the PK-PD table ("UNKNOWN") have no function. UTI status is part of the comparison, so that a breakpoint for UTI only does not remove the blocking row for other infections. Of several blocking rows for the same organism, agent, method, UTI status and site, the first is kept. All other blocking rows without any effect are removed in reproduction_of_clinical_breakpoints.R, by comparing the results of as.sir() with and without them (#326).
has_own_bp <- breakpoints_eucast |>
filter(!is_blocker, !grepl("screen", site, ignore.case = TRUE)) |>
filter(!is_blocker) |>
distinct(guideline, type, host, mo, ab, method, uti)
breakpoints_eucast <- bind_rows(
breakpoints_eucast |> filter(!is_blocker),
breakpoints_eucast |>
filter(is_blocker, mo != "UNKNOWN") |>
anti_join(has_own_bp, by = c("guideline", "type", "host", "mo", "ab", "method", "uti")) |>
distinct(guideline, type, host, mo, ab, method, uti, .keep_all = TRUE) |>
mutate(site = if_else(uti, site, NA_character_), disk_dose = NA_character_)
distinct(guideline, type, host, mo, ab, method, uti, site, .keep_all = TRUE) |>
mutate(disk_dose = NA_character_)
)
breakpoints_eucast <- breakpoints_eucast |>
@@ -2645,7 +2813,8 @@ breakpoints_eucast <- breakpoints_eucast |>
mutate(
rank_index = case_when(
mo == "UNKNOWN" ~ 7, # the PK-PD table, as for the WHONET-based rows
is.na(mo_rank(mo, keep_synonyms = TRUE)) ~ 6, # for B_GRAMN, B_ANAER, B_ANAER-NEG, etc.
grepl("^B_ANAER", as.character(mo)) ~ 5.5, # anaerobes are more specific than a Gram stain
is.na(mo_rank(mo, keep_synonyms = TRUE)) ~ 6, # for B_GRAMN, etc.
mo_rank(mo, keep_synonyms = TRUE) %like% "(infra|sub)" ~ 1,
mo_rank(mo, keep_synonyms = TRUE) == "species" ~ 2,
mo_rank(mo, keep_synonyms = TRUE) == "species group" ~ 2.5,
+1 -1
View File
@@ -1 +1 @@
81db4bcdb760c4028a188437289e9f54
7bb0d7533000dd60d71dd2eb4297e4e8
File diff suppressed because it is too large. Load diff
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
bbd1671f1e29c7510e23471aeb3245d3
ba5a4275785b07c1c2507ade4813e79e
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+13
View File
@@ -140,11 +140,13 @@
"CED" 38103 "Cephradine" "Cephalosporins (1st gen.),Cephalosporins,Beta-lactams" "NA" "Other beta-lactam antibacterials" "First-generation cephalosporins" "cephra,cfra,cfrd" "anspor,cefradin,cefradina,cefradine,cefradinum,cekodin,cephradin,ecosporina,eskacef,infexin,megacef,sefril,velocef,velosef" "168-5,169-3,170-1,171-9,18902-7,55646-4"
"CTO" 71402 "Cetocycline" "Tetracyclines" "NA" "NA" "cetocyline,cetotetrine,chelocardin" "NA"
"CHL" 5959 "Chloramphenicol" "Phenicols" "D06AX02,D10AF03,G01AA05,J01BA01,QD06AX02,QD10AF03,QG01AA05,QJ01BA01,QJ51BA01,QS01AA01,QS02AA01,QS03AA08,S01AA01,S02AA01,S03AA08" "Amphenicols" "Amphenicols" "c,chl,chlo,chlora,cl" "alficetyn,ambofen,amphicol,amseclor,anacetin,aquamycetin,austracil,austracol,biocetin,biophenicol,catilan,chemicetin,chemicetina,chlomin,chlomycol,chloramex,chloramfenikol,chloramficin,chloramfilin,chloramphenicole,chloramphenicolum,chloramsaar,chlorasol,chlorbiotic,chloricol,chlornitromycin,chloroamphenicol,chlorocaps,chlorocid,chlorocide,chlorocin,chlorocol,chlorofair,chloromax,chloromycetin,chloromycetny,chloromyxin,chloronitrin,chloroptic,chlorovules,cidocetine,ciplamycetin,cloramfen,cloramfenicol,cloramfenicolo,cloramficin,cloramicol,cloramidina,cloranfenicol,cloroamfenicolo,clorocyn,cloromisan,clorosintex,comycetin,cylphenicol,desphen,detreomycin,detreomycine,dextramycin,dextromycetin,doctamicina,econochlor,embacetin,emetren,enteromycetin,erbaplast,ertilen,farmicetina,globenicol,glorous,gloveticol,halcetin,halomycetin,hortfenicol,intramycetin,isicetin,ismicetina,isophenicol,juvamycetin,kamaver,kemicetina,kemicetine,kloramfenikol,klorita,laevomycetinum,leukamycin,leukomyan,leukomycin,levocin,levomicetina,levomitsetin,levomycetin,levoplast,levosin,levovetin,loromisan,loromisin,mastiphen,maybridge,mediamycetine,medichol,micloretin,micochlorine,micoclorina,microcetina,mychel,mycinol,myclocin,mycochlorin,novochlorocap,novomycetin,novophenicol,ocuphenicol,oftalent,oleomycetin,opclor,opelor,ophthochlor,ophthocort,ophtochlor,optomycin,otachron,otophen,pantovernil,paraxin,pentamycetin,petnamycetin,quemicetina,rivomycin,romphenil,ronphenil,septicol,sificetina,sintomicetin,sintomicetina,soluthor,stanomycetin,synthomycetin,synthomycetine,synthomycine,syntomycin,tevcocin,tevcosin,tifomycin,tifomycine,tiromycetin,treomicetina,tyfomycine,unimycetin,veticol,viceton" 3 "g" 3 "g" "15101-9,16603-3,16604-1,172-7,173-5,174-3,175-0,18903-5,25247-8,29214-4,29346-4,29347-2,3455-3,7001-1"
"CHL-S" "Chloramphenicol screening test" "Phenicols" "" "chl screen" "" ""
"CTE" 54675777 "Chlortetracycline" "Tetracyclines" "A01AB21,D06AA02,J01AA03,QA01AB21,QD06AA02,QG51AA08,QJ01AA03,QJ51AA03,QS01AA02,S01AA02" "Tetracyclines" "Tetracyclines" "chltet" "acronize,alexomycin,aueromycin,aureocarmyl,aureociclina,aureocina,aureocycline,aureomycin,aureomykoin,aurofac,auxeomycin,biomitsin,biomycin,chlormax,chlorotetracycline,chlortetracyclinum,chrysomykine,clorocipan,clortetraciclina,clortetrin,declomycin,declostatin,deganol,demeclor,demeplus,demetraciclina,demetraclin,detracin,detravis,diuciclin,duomycin,elkamicina,flamycin,isphamycin,ledermicina,ledermycin,ledermycine,mexocine,novotriclina,pennchlor,perciclina,periciclina,sumaclina,uromycin,veraciclina" 1 "g" "176-8,177-6,178-4,179-2,18904-3,55655-5,87600-3"
"CIC" 19003 "Ciclacillin" "Penicillins,Beta-lactams" "NA" "cyclac" "bastcillin,calthor,ciclacilina,ciclacilline,ciclacillinum,ciclacillum,citosarin,cyclacillin,cyclapen,noblicil,orfilina,peamezin,syngacillin,ultracillin,vastcillin,vipicil,wyvital" "NA"
"CIX" "Ciclopirox" "Antifungals" "D01AE14,G01AX12,QD01AE14,QG01AX12" "Antifungals for topical use" "Other antifungals for topical use" "cipx" "NA" "NA"
"CIN" 2762 "Cinoxacin" "Quinolones" "J01MB06,QJ01MB06" "Quinolone antibacterials" "Other quinolones" "cino,cinoxa,cnox" "cinobac,cinobactin,cinoxacine,cinoxacino,cinoxacinum,clinoxacin,noxigram,uronorm" 1 "g" "180-0,181-8,182-6,183-4,18905-0,55656-3"
"CIP" 2764 "Ciprofloxacin" "Fluoroquinolones,Quinolones" "J01MA02,QJ01MA02,QS01AE03,QS02AA15,QS03AA07,S01AE03,S02AA15,S03AA07" "Quinolone antibacterials" "Fluoroquinolones" "ci,cip,cipr,ciprof,cp" "alcipro,bacquinor,baflox,belmacina,bernoflox,catex,cenin,ceprimax,cetraxal,ciflan,ciflosin,cifloxin,cilab,cilox,ciloxan,cipad,ciplus,ciprecu,ciprenit,ciprine,ciprinol,cipro,ciprobay,ciprocinal,ciprocinol,ciprodar,ciproflox,ciprofloxacina,ciprofloxacine,ciprofloxacino,ciprofloxacinum,ciprofur,ciprogis,ciproktan,ciprolin,ciprolon,cipromycin,cipronex,ciprooxacin,cipropol,ciproquinol,ciprowin,ciproxan,ciproxin,ciproxina,ciproxine,ciriax,citeral,citopcin,cixan,corsacin,cunesin,cycin,cyprobay,cyproxan,disfabac,felixene,fimoflox,flociprin,floxacipron,flunas,globuce,inkamil,ipiflox,italnik,keefloxin,linhaliq,loxacid,loxan,lypro,megaflox,microgan,nixin,novidat,novoquin,ofitin,oftacilox,ophaflox,otiprio,phaproxin,piprol,plenolyt,probiox,proflaxin,proksi,proquin,proxacin,quinoflox,quinolid,quintor,quipro,rancif,renator,roflazin,roxytal,sepcen,septicide,septocipro,siprogut,sophixin,spitacin,strox,suiflox,superocin,supraflox,uritent,utiminx,velmonit,zumaflox" 1 "g" 0.8 "g" "101500-7,14031-9,14032-7,14058-2,14059-0,184-2,185-9,186-7,187-5,18906-8,20377-8,23621-6,25180-1,25181-9,25188-4,25189-2,25248-6,34636-1,3484-3,42644-5,55194-5,7002-9"
"CIP-S" "Ciprofloxacin screening test" "Fluoroquinolones,Quinolones" "" "cip screen" "" ""
"CIM" "Ciprofloxacin/metronidazole" "Fluoroquinolones,Quinolones" "J01RA10,QJ01RA10" "Combinations of antibacterials" "Combinations of antibacterials" "NA" "NA" "NA"
"CIO" "Ciprofloxacin/ornidazole" "Fluoroquinolones,Quinolones" "J01RA12,QJ01RA12" "Combinations of antibacterials" "Combinations of antibacterials" "NA" "NA" "NA"
"CIT" "Ciprofloxacin/tinidazole" "Fluoroquinolones,Quinolones" "J01RA11,QJ01RA11" "Combinations of antibacterials" "Combinations of antibacterials" "NA" "NA" "NA"
@@ -161,6 +163,7 @@
"CTR" 2812 "Clotrimazole" "Antifungals" "A01AB18,D01AC01,G01AF02,QA01AB18,QD01AC01,QG01AF02,QJ02AB90" "clot" "alevazol,bisphenyl,canesten,canestene,canestine,canifug,chlotrimazole,clomatin,clotrimaderm,clotrimazol,clotrimazolum,coltrimazole,cutistad,diphenylmethane,empecid,esparol,femmesil,footlogix,fortinia,gynix,imidazole,jidesheng,klotrimazole,lakesia,lombazol,lombazole,lombazolum,lotrimax,lotrimin,monobaycuten,mycelax,mycelex,mycofug,mycosporin,mykosporin,nalbix,otomax,pedesil,pedisafe,ringworm,stiemazol,tibatin,trimysten,trivagizole" "10653-4,10654-2,18909-2,54177-1,55663-9"
"CLO" 6098 "Cloxacillin" "Isoxazolylpenicillins,Penicillins,Beta-lactams" "J01CF02,QJ01CF02,QJ51CF02,QS01AA90" "Beta-lactam antibacterials, penicillins" "Beta-lactamase resistant penicillins" "clox,cloxac" "ankerbin,austrastaph,biocloxin,brispen,chloroxacillin,ciclex,clocil,clossacillina,cloxacilina,cloxacillinanhydrous,cloxacilline,cloxacillinsalt,cloxacillinum,cloxapen,constaphyl,dariclox,dichlorstapenor,diclocil,dicloxacillinhydrate,diflor,digloxilline,dynapen,ekvacillin,gelstaph,novapen,noxaben,orbenin,pathocil,stampen,staphybiotic,syntarpen,syntarpensalt,tegopen" 2 "g" 2 "g" "16628-0,18910-0,196-6,197-4,198-2,199-0,25250-2,55664-7"
"COL" 5311054 "Colistin" "Polymyxins" "A07AA10,J01XB01,QA07AA10,QJ01XB01,QJ51XB01" "Other antibacterials" "Polymyxins" "cl,coli,colist,cs,cst,ct" "colimycin,colisticin,colisticina,colistina,colistine,colistinum,colobreathe,colomycin,kangdisu,kolimitsin,kolimycin,promixin,sogecoli,totazina" 9 "MU" 9 "MU" "16645-4,18912-6,204-8,205-5,206-3,207-1,29493-4,33333-6"
"COL-S" "Colistin screening test" "Polymyxins" "" "col screen" "" ""
"COP" "Colistin/polysorbate" "Other" "NA" "NA" "NA" "NA"
"CYC" 6234 "Cycloserine" "Oxazolidinones" "J04AB01,QJ04AB01" "Drugs for treatment of tuberculosis" "Antibiotics" "cycl,cyclos" "cicloserina,closina,cyclorin,cycloserin,cycloserinum,farmiserina,levcicloserina,levcycloserine,levcycloserinum,micoserina,miroserina,miroseryn,novoserin,oxamicina,oxamycin,seromycin,tebemicina,wasserina" 0.75 "g" "16702-3,18914-2,212-1,213-9,214-7,215-4,23608-3,25207-2,25208-0,25209-8,25251-0,3519-6,55667-0"
"DAL" 23724878 "Dalbavancin" "Lipoglycopeptides,Glycopeptides,Peptides" "J01XA04,QJ01XA04" "Other antibacterials" "Glycopeptide antibacterials" "dalb,dalbav" "dalbavancina,dalvance,xydalba,zeven" 1.5 "g" "41688-3,41689-1,41690-9,41734-5"
@@ -187,6 +190,7 @@
"ERV" 54726192 "Eravacycline" "Tetracyclines" "J01AA13,QJ01AA13" "Tetracyclines" "Tetracyclines" "erav" "xerava" 0.14 "g" "100049-6,85423-2,93767-2"
"ETP" 150610 "Ertapenem" "Carbapenems,Beta-lactams" "J01DH03,QJ01DH03" "Other beta-lactam antibacterials" "Carbapenems" "erta,ertape,etp" "ertapenemsalt,invanz" 1 "g" "101486-9,35799-6,35800-2,35801-0,35802-8"
"ERY" 12560 "Erythromycin" "Macrolides" "D10AF02,J01FA01,QD10AF02,QJ01FA01,QJ51FA01,QS01AA17,S01AA17" "Macrolides, lincosamides and streptogramins" "Macrolides" "e,em,ery,ery32,eryt,eryth" "abboticin,abomacetin,acneryne,acnesol,aknemycin,aknin,benzamycin,derimer,deripil,dotycin,dumotrycin,emgel,emuvin,emycin,endoeritrin,erecin,erisone,eritomicina,eritrocina,eritromicina,ermycin,eryacne,eryacnen,erycen,erycette,erycinum,eryderm,erydermer,erygel,eryhexal,erymax,erymed,erysafe,erytab,erythro,erythroderm,erythrogran,erythroguent,erythromast,erythromid,erythromycine,erythromycinum,erytop,erytrociclin,ilocaps,ilosone,iloticina,ilotycin,inderm,latotryd,lederpax,mephamycin,mercina,oftamolets,pantoderm,pantodrin,pantomicina,pharyngocin,primacine,propiocine,proterytrin,retcin,robimycin,sansac,spotex,staticin,stiemicyn,stiemycin,tiprocin,torlamicina,wemid" 2 "g" 1 "g" "100050-4,11576-6,12298-6,16829-4,16830-2,18919-1,18920-9,20380-2,232-9,233-7,234-5,235-2,236-0,23633-1,237-8,238-6,239-4,25224-7,25275-9,3597-2,7009-4"
"ERY-S" "Erythromycin screening test" "Macrolides" "" "ery screen" "" ""
"ETH" 14052 "Ethambutol" "Antimycobacterials" "J04AK02,QJ04AK02" "Drugs for treatment of tuberculosis" "Other drugs for treatment of tuberculosis" "emb,etha,ethamb" "aethambutolum,dadibutol,diambutol,etambutol,etambutolo,ethambutolum,myambutol,purderal,servambutol,tibutol" 1.2 "g" 1.2 "g" "100051-2,16841-9,18921-7,20381-0,23625-7,240-2,241-0,242-8,243-6,25187-6,25194-2,25195-9,25230-4,25404-5,3607-9,42645-2,42646-0,55154-9,55674-6,56025-0,7010-2,89491-5"
"ETI" 456476 "Ethambutol/isoniazid" "Antimycobacterials" "J04AM03,QJ04AM03" "Drugs for treatment of tuberculosis" "Combinations of drugs for treatment of tuberculosis" "NA" "NA" "NA"
"ETI1" 2761171 "Ethionamide" "Antimycobacterials" "J04AD03,QJ04AD03" "Drugs for treatment of tuberculosis" "Thiocarbamide derivatives" "ethi,ethion" "aethionamidum,aetina,aetiva,amidazin,amidazine,atina,ethimide,ethina,ethinamide,ethionamidum,ethioniamide,ethylisothiamide,ethyonomide,etimid,etiocidan,etionamid,etionamida,etionamide,etioniamid,etionid,etionizin,etionizina,etionizine,fatoliamid,iridocin,iridozin,isothin,isotiamida,itiocide,nicotion,nisotin,nizotin,rigenicid,sertinon,teberus,thianid,thianide,thioamide,thiodine,thiomid,thioniden,tianid,tiomid,trecator,trekator,trescatyl,trescazide,tubenamide,tubermin,tuberoid,tuberoson" 0.75 "g" "16099-4,16845-0,18922-5,20382-8,23617-4,25183-5,25196-7,25198-3,25231-2,41693-3,42647-8,42648-6,7011-0,96110-2"
@@ -211,11 +215,13 @@
"FUR" 6870646 "Furazidin" "Nitrofurans" "J01XE03,QJ01XE03" "Other antibacterials" "Nitrofuran derivatives" "NA" "akritoin,furagin,furaginum,furamag,furazidine,hydantoin" 0.3 "g" "NA"
"FRZ" 5323714 "Furazolidone" "Nitrofurans" "G01AX06,QG01AX06,QJ01XE90" "furazo" "bifuron,corizium,coryzium,diafuron,enterotoxon,furall,furanzolidone,furaxon,furaxone,furazolidine,furazolidon,furazolidona,furazolidonum,furazolum,furidon,furmethoxadone,furovag,furoxal,furoxane,furoxon,furoxone,furozolidine,giardil,giarlam,medaron,neftin,nicolen,nifulidone,nifuran,nifurazolidone,nifurazolidonum,nitrofuradoxon,nitrofurazolidone,nitrofurazolidonum,nitrofuroxon,optazol,ortazol,puradin,roptazol,sclaventerol,tikofuran,topazone,trichofuron,tricofuron,tricoron,trifurox,viofuragyn" "69574-2,87794-4"
"FUS" 3000226 "Fusidic acid" "Fusidanes" "D06AX01,D09AA02,J01XC01,QD06AX01,QD09AA02,QJ01XC01,QS01AA13,S01AA13" "Other antibacterials" "Steroid antibacterials" "fa,fusaci,fusi" "flucidin,fucidate,fucidina,fucidine,fucithalmic,fusidate,fusidicacid,fusidin,fusidine,taksta" 1.5 "g" 1.5 "g" "NA"
"FUS-S" "Fusidic acid screening test" "Fusidanes" "" "fus screen" "" ""
"GAM" 59364992 "Gamithromycin" "Macrolides" "QJ01FA95" "NA" "zactran" "100054-6,88376-9,88378-5"
"GRN" 124093 "Garenoxacin" "Fluoroquinolones,Quinolones" "J01MA19,QJ01MA19" "gareno" "ganefloxacin,garenfloxacin" 0.4 "g" "35811-9,35812-7,35813-5"
"GAT" 5379 "Gatifloxacin" "Fluoroquinolones,Quinolones" "J01MA16,QJ01MA16,QS01AE06,S01AE06" "Quinolone antibacterials" "Fluoroquinolones" "gati,gatifl" "acorafloxacin,avarofloxacin,balofloxacin,balofox,bazucin,bilimin,bonoq,gaity,gatiflo,gatifloxacine,gatifloxcin,gatilox,gatiquin,gatispan,kinome,tequin,tymer,zymar,zymaxid,zymer" 0.4 "g" 0.4 "g" "31036-7,31038-3,31040-9,31042-5,41494-6"
"GEM" 9571107 "Gemifloxacin" "Fluoroquinolones,Quinolones" "J01MA15,QJ01MA15" "Quinolone antibacterials" "Fluoroquinolones" "gemifl" "factiv,gemifioxacin,gemifloxacine,gemifloxacino,gemifloxacinum" 0.32 "g" 0.2 "g" "35814-3,35815-0,35816-8,41697-4"
"GEN" 3467 "Gentamicin" "Aminoglycosides" "D06AX07,J01GB03,QA07AA91,QD06AX07,QG01AA91,QG51AA04,QJ01GB03,QJ51GB03,QS01AA11,QS02AA14,QS03AA06,S01AA11,S02AA14,S03AA06" "Aminoglycoside antibacterials" "Other aminoglycosides" "cn,ge1000,ge2000,gen,gen128,gen500,gent,genta1,gentam,gm" "centicin,cidomycin,garamicin,garamycin,gentacycol,gentamicina,gentamicine,gentamicins,gentamicinum,gentamycins,gentamycinum,gentocin,lyramycin,oksitselanim,septigen,septocin" 0.24 "g" "101494-3,13561-6,13562-4,15106-8,18928-2,18929-0,22746-2,22747-0,266-7,267-5,268-3,269-1,31091-2,31092-0,31093-8,35668-3,35817-6,3663-2,3664-0,3665-7,39082-3,47109-4,50630-3,59379-8,7016-9,7017-7,7018-5,80971-5,88111-0,89481-6"
"GEN-S" "Gentamicin screening test" "Aminoglycosides" "" "gen screen" "" ""
"GEH" "Gentamicin-high" "Aminoglycosides" "NA" "gehi,gehl,genta high,gentamicin high" "NA" "18929-0,35817-6,7017-7,7018-5"
"GEP" 25101874 "Gepotidacin" "Other" "J01XX13,QJ01XX13" "NA" "gepotidacina,gepotidacine" "NA"
"GRX" 72474 "Grepafloxacin" "Fluoroquinolones,Quinolones" "J01MA11,QJ01MA11" "Quinolone antibacterials" "Fluoroquinolones" "grep,grepaf" "grepafloxacine,grepafloxacino,lungaskin,raxar,vaxar" 0.4 "g" "21316-5,23638-0,23639-8,35818-4"
@@ -248,6 +254,7 @@
"LMU" 25185057 "Lefamulin" "Other" "J01XX12,QJ01XX12" "NA" "lefamulinacetate,xenleta" "85425-7,99281-8"
"LEN" 65646 "Lenampicillin" "Penicillins,Beta-lactams" "NA" "NA" "lenampicilina,lenampicilline,lenampicillinum,takacillin,valacillin,varacillin" "NA"
"LVX" 149096 "Levofloxacin" "Fluoroquinolones,Quinolones" "J01MA12,QJ01MA12,QS01AE05,S01AE05" "Quinolone antibacterials" "Fluoroquinolones" "le,lev,levo,levofl,lvx" "aeroquin,cravit,dextrofloxacin,dynaquin,elequine,iquix,levaquin,levofiexacin,levofloxacine,levofloxacino,levofloxacinum,loxof,ofloxcacin,oftaquix,quinsair,quixin,tavanic,unibiotic,venaxan" 0.5 "g" 0.5 "g" "101501-5,20396-8,20629-2,21367-8,21368-6,30532-6,30533-4,48173-9,53716-7,7026-8,76040-5,76041-3,76042-1"
"LVX-S" "Levofloxacin screening test" "Fluoroquinolones,Quinolones" "" "lvx screen" "" ""
"LEO" "Levofloxacin/ornidazole" "Fluoroquinolones,Quinolones" "J01RA05,QJ01RA05" "Combinations of antibacterials" "Combinations of antibacterials" "NA" "NA" "NA"
"LND" 9850038 "Levonadifloxacin" "Fluoroquinolones,Quinolones" "J01MA24,QJ01MA24" "NA" "NA" "NA"
"LSP" "Linco-spectin" "Other" "NA" "lincomycin/spectinomycin" "NA" "NA"
@@ -286,6 +293,7 @@
"MRN" 70374 "Morinamide" "Antimycobacterials" "J04AK04,QJ04AK04" "Drugs for treatment of tuberculosis" "Other drugs for treatment of tuberculosis" "NA" "morfazinamide,morfazinammide,morfgazinamide,morinamida,morinamidum,morphazinamid,morphazinamide,piazofolina,piazolin,piazolina" "NA"
"MFX" 152946 "Moxifloxacin" "Fluoroquinolones,Quinolones" "J01MA14,QJ01MA14,QS01AE07,S01AE07" "Quinolone antibacterials" "Fluoroquinolones" "mox,moxi,moxifl,mxf" "actira,actura,avalox,avelox,avolex,izilox,moxeza,moxifloxacine,moxifloxacino,octegra,vegamox,vigamox,zimoxin" 0.4 "g" 0.4 "g" "31037-5,31039-1,31041-7,31043-3,41502-6,43751-7,45223-5,76043-9,76044-7,76045-4,80540-8,88707-5,93497-6,96112-8"
"MUP" 446596 "Mupirocin" "Other" "D06AX09,QD06AX09,QR01AX06,R01AX06" "mup,mupi,mupiro" "bactoderm,bactroban,centany,mupirocina,mupirocine,mupirocinum,plasimine,turixin" "20389-3,35822-6,35823-4,60542-8,60543-6,7033-4"
"MUP-S" "Mupirocin screening test" "Other" "" "mup screen" "" ""
"NAC" 73386748 "Nacubactam" "Beta-lactamase inhibitors" "NA" "NA" "NA" "NA"
"NAD" 4410 "Nadifloxacin" "Fluoroquinolones,Quinolones" "D10AF05,QD10AF05" "NA" "acuatim,nadifloxacine,nadifloxacino,nadifloxacinum,nadixa,nadoxin" "NA"
"NAF" 8982 "Nafcillin" "Penicillins,Beta-lactams" "J01CF06,QJ01CF06" "nafcil" "nafcil,nafcilin,nafcilina,nafcillinanhydrous,nafcilline,nafcillinhydrate,nafcillinmonohydrate,nafcillinsalt,nafcillinum,naftopen,nallpen,naphcillin,naphthicillin,unipen" 3 "g" "10993-4,18951-4,25232-0,346-7,347-5,348-3,349-1,41704-8"
@@ -295,6 +303,7 @@
"NAR" 65452 "Narasin" "Ionophores" "QP51BB04" "narasi" "monteban,narasine,narasino,narasinum,skycis" "87570-8"
"NEM" 11993740 "Nemonoxacin" "Fluoroquinolones,Quinolones" "J01MB08,QJ01MB08" "Quinolone antibacterials" "Other quinolones" "NA" "NA" "NA"
"NEO" "Neomycin" "Aminoglycosides" "A01AB08,A07AA01,B05CA09,D06AX04,J01GB05,QA01AB08,QA07AA01,QB05CA09,QD06AX04,QJ01GB05,QR02AB01,QS01AA03,QS02AA07,QS03AA01,R02AB01,S01AA03,S02AA07,S03AA01" "Aminoglycoside antibacterials" "Other aminoglycosides" "neom,neomyc" "NA" 5 "g" 1 "g" "10995-9,18953-0,25262-7,354-1,355-8,356-6,357-4,41705-5"
"NEO-S" "Neomycin screening test" "Aminoglycosides" "" "neo screen" "" ""
"NET" 441306 "Netilmicin" "Aminoglycosides" "J01GB07,QJ01GB07,QS01AA23,S01AA23" "Aminoglycoside antibacterials" "Other aminoglycosides" "neti,netilm" "netillin,netilmicina,netilmicine,netilmicinum,netilyn,netira,netromicine,netromycin,nettacin,ntromicine,ntromycin,vectacin,zetamicin" 0.35 "g" 0.35 "g" "18954-8,25263-5,358-2,359-0,360-8,361-6,3848-9,3849-7,3850-5,47385-0,59565-2,59566-0,59567-8,7035-9"
"NIC" 9507 "Nicarbazin" "Other" "NA" "NA" "nicarb,nicarbasin,nicarbazine,nicarmix,nicoxin,nicrazin,nicrazine,nirazin" "NA"
"NIF" 71946 "Nifuroquine" "Fluoroquinolones,Quinolones" "NA" "NA" "abimasten,nifuroquina,nifuroquinum,quinaldofur" "NA"
@@ -311,6 +320,7 @@
"NOV" 54675769 "Novobiocin" "Aminocoumarins" "QJ01XX95" "novo,novobi" "albadry,albamix,albamycin,biotexin,cardelmycin,cardelmycinsalt,cathocin,cathomycin,inabiocin,novobiocina,novobiocine,novobiocinsalt,novobiocinum,robiocina,sirbiocina,spheromycin,stilbiocina,streptonivicin,streptonivicinsalt,vulcamicina,vulcamycin,vulkamycin" "17378-1,18957-1,370-7,371-5,372-3,373-1,41706-3"
"NYS" 6433272 "Nystatin" "Ionophores,Antifungals" "A07AA02,D01AA01,G01AA01,QA07AA02,QD01AA01,QG01AA01" "nyst,nystan" "biofanal,diastatin,herniocid,moronal,myconystatin,mycostatin,mykostatyna,nilstat,nistatin,nistatina,nyotran,nystan,nystatyna,nystavescent,nystex" 1.5 "MU" "10697-1,10698-9,18958-9,35824-2,55689-4"
"OFX" 4583 "Ofloxacin" "Fluoroquinolones,Quinolones" "J01MA01,QJ01MA01,QS01AE01,QS02AA16,S01AE01,S02AA16" "Quinolone antibacterials" "Fluoroquinolones" "of,ofl,oflo,ofloxa,ofx" "exocin,exocine,flobacin,floxil,floxin,monoflocet,oflocet,ofloxacina,ofloxacine,ofloxacino,ofloxacinum,ofloxaxin,oxaldin,tarivid,visiren,zanocin" 0.4 "g" 0.4 "g" "18959-7,20384-4,23948-3,25264-3,374-9,375-6,376-4,377-2,3877-8,41408-6,41409-4,41410-2,42653-6,7038-3,72168-8"
"OFX-S" "Ofloxacin screening test" "Fluoroquinolones,Quinolones" "" "ofx screen" "" ""
"OOR" "Ofloxacin/ornidazole" "Fluoroquinolones,Quinolones" "J01RA09,QJ01RA09" "Combinations of antibacterials" "Combinations of antibacterials" "NA" "NA" "NA"
"OLE" 72493 "Oleandomycin" "Macrolides" "J01FA05,QJ01FA05" "Macrolides, lincosamides and streptogramins" "Macrolides" "oleand" "amimycin,landomycin,matromycin,oleandomicina,oleandomycine,oleandomycinum,romicil" 1 "g" "18960-5,378-0,379-8,380-6,381-4,55690-2"
"OMC" 54697325 "Omadacycline" "Tetracyclines" "J01AA15,QJ01AA15" "NA" "amadacycline" 0.3 "g" 0.1 "g" "73594-4,73616-5,73639-7"
@@ -371,6 +381,7 @@
"RAM" 16132338 "Ramoplanin" "Glycopeptides,Peptides" "NA" "ramopl" "NA" "41710-5,41711-3,41712-1,41737-8"
"RZM" 10993211 "Razupenem" "Carbapenems,Beta-lactams" "NA" "razupe" "NA" "73590-2,73612-4,73635-5"
"RTP" 6918462 "Retapamulin" "Pleuromutilins" "D06AX13,QD06AX13" "Antibiotics for topical use" "Other antibiotics for topical use" "ret" "altabax,altargo,rebapamulin,retapamulina" "NA"
"RTP-S" "Retapamulin screening test" "Pleuromutilins" "" "rtp screen" "" ""
"RZF" "Rezafungin" "Antifungals" "NA" "NA" "NA" "NA"
"RBC" 44631912 "Ribociclib" "Antifungals" "L01EF02,QL01EF02" "Antimycotics for systemic use" "Triazole derivatives" "ribo" "kisqali" 0.45 "g" "NA"
"RST" 33042 "Ribostamycin" "Aminoglycosides" "J01GB10,QJ01GB10" "Aminoglycoside antibacterials" "Other aminoglycosides" "NA" "exaluren,hetangmycin,ribastamin,ribostamicina,ribostamycine,ribostamycinum,vistamycin,xylostatin" 1 "g" "NA"
@@ -406,6 +417,7 @@
"SPM" "Spiramycin/metronidazole" "Other" "J01RA04,QJ01RA04" "Combinations of antibacterials" "Combinations of antibacterials" "NA" "NA" "NA"
"STR" "Streptoduocin" "Aminoglycosides" "J01GA02,QJ01GA02" "Aminoglycoside antibacterials" "Streptomycins" "NA" "NA" 1 "g" "NA"
"STR1" 19649 "Streptomycin" "Aminoglycosides" "A07AA04,J01GA01,QA07AA04,QJ01GA01" "Aminoglycoside antibacterials" "Streptomycins" "s,st1000,st2000,stm,str,stre,strept" "agrept,agrimycin,chemform,estreptomicina,gerox,neodiestreptopab,strepcen,streptomicina,streptomycine,streptomycinum,streptomyzin" 1 "g" "18982-9,18983-7,20462-8,23626-5,25185-0,25205-6,25206-4,35841-6,4039-4,42658-5,42659-3,459-8,460-6,461-4,462-2,46719-1,48177-0,6933-6,7048-2,7049-0,96114-4"
"STR1-S" "Streptomycin screening test" "Aminoglycosides" "" "str1 screen" "" ""
"STH" "Streptomycin-high" "Aminoglycosides" "NA" "sthi,sthl,strepto high,streptomycin high" "NA" "18983-7,35841-6,6933-6,7049-0"
"STI" "Streptomycin/isoniazid" "Antimycobacterials" "J04AM01,QJ04AM01" "Drugs for treatment of tuberculosis" "Combinations of drugs for treatment of tuberculosis" "NA" "NA" "NA"
"SUL" 130313 "Sulbactam" "Beta-lactamase inhibitors" "J01CG01,QJ01CG01" "Beta-lactam antibacterials, penicillins" "Beta-lactamase inhibitors" "sulbac" "betamaze,sulbactamum" 1 "g" "41716-2,41717-0,41718-8,41739-4"
@@ -484,6 +496,7 @@
"TXC" 65788 "Tioxacin" "Fluoroquinolones,Quinolones" "NA" "NA" "tioxacine,tioxacino,tioxacinum" "NA"
"TIZ" 394397 "Tizoxanide" "Other" "NA" "NA" "NA" "73585-2,73607-4,73629-8"
"TOB" 36294 "Tobramycin" "Aminoglycosides" "J01GB01,QJ01GB01,QS01AA12,S01AA12" "Aminoglycoside antibacterials" "Other aminoglycosides" "nn,tm,to,tob,tobr,tobram" "aktob,bethkis,distobram,gotabiotic,kitabis,nebcin,nebicin,nebramycin,tenebrimycin,tenemycin,tobacin,tobracin,tobradex,tobradistin,tobralex,tobramaxin,tobramicin,tobramicina,tobramitsetin,tobramycetin,tobramycine,tobramycinum,tobrased,tobrex" 0.24 "g" "101496-8,13584-8,17808-7,18996-9,22750-4,22751-2,22752-0,25227-0,25800-4,31094-6,31095-3,31096-1,35239-3,35670-9,4057-6,4058-4,4059-2,507-4,508-2,509-0,50927-3,510-8,52962-8,59380-6,7055-7,80966-5"
"TOB-S" "Tobramycin screening test" "Aminoglycosides" "" "tob screen" "" ""
"TOH" "Tobramycin-high" "Aminoglycosides" "NA" "tobra high,tobramycin high,tohl" "NA" "NA"
"TFX" 5517 "Tosufloxacin" "Fluoroquinolones,Quinolones" "J01MA22,QJ01MA22,QS01AE09,S01AE09" "tosufl" "NA" 0.45 "g" "100061-1,76146-0"
"TMP" 5578 "Trimethoprim" "Trimethoprims" "J01EA01,QJ01EA01,QJ51EA01" "Sulfonamides and trimethoprim" "Trimethoprim and derivatives" "t,tmp,tr,tri,trim,w" "abaprim,anitrim,antrima,antrimox,bacdan,bacidal,bacide,bacin,bacterial,bacticel,bactifor,bactoprim,bactramin,bencole,bethaprim,biosulten,briscotrim,chemotrin,colizole,conprim,cotrimel,deprim,dosulfin,duocide,esbesul,espectrin,euctrim,exbesul,fermagex,fortrim,futin,ikaprim,infectotrimet,instalac,kombinax,lagatrim,lastrim,lescot,monoprim,monotrim,monotrimin,novotrimel,omstat,pancidim,proloprim,protrin,purbal,resprim,roubac,roubal,salvatrim,setprin,sinotrim,stopan,streptoplus,sugaprim,sulfamar,sulfoxaprim,sulthrim,sultrex,syraprim,tiempe,trimethioprim,trimethoprime,trimethoprimum,trimethopriom,trimetoprim,trimetoprima,trimexol,trimezol,trimogal,trimono,trimopan,triprim,trisul,trisulcom,trisulfam,trisural,uretrim,urobactrim,utetrin,velaten,wellcoprim,wellcoprin,xeroprim,zamboprim" 0.4 "g" 0.4 "g" "101495-0,11005-6,17747-7,18997-7,18998-5,20387-7,23614-1,23631-5,25273-4,32342-8,4079-0,4080-8,4081-6,511-6,512-4,513-2,514-0,515-7,516-5,517-3,518-1,55584-7,7056-5,7057-3,80552-3,80973-1"
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large. Load diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+2 -2
View File
@@ -10,7 +10,7 @@
- Generates **antibiograms** - WISCA for empiric coverage estimates, or
traditional/syndromic for AMR surveillance
- Provides the **full microbiological taxonomy** of ~103 000 distinct
species and extensive info of ~630 antimicrobial drugs
species and extensive info of ~640 antimicrobial drugs
- Applies **CLSI 2011-2026** and **EUCAST 2011-2026** clinical and
veterinary breakpoints, and ECOFFs, for MIC and disk zone
interpretation
@@ -60,7 +60,7 @@ in scientific research.
After installing this package, R knows [**~103 000 distinct microbial
species**](./reference/microorganisms.html) (updated October 2026) and
all [**~630 antimicrobial and antiviral
all [**~640 antimicrobial and antiviral
drugs**](./reference/antimicrobials.html) by name and code (including
ATC, EARS-Net, ASIARS-Net, PubChem, LOINC and SNOMED CT), and knows all
about valid SIR and MIC values. The integral clinical breakpoint
+1 -1
View File
@@ -26,7 +26,7 @@ This is an overview of all the package-specific options you can set in the \code
}
\item \code{AMR_ignore_pattern} \cr A \link[base:regex]{regular expression} to ignore (i.e., make \code{NA}) any match given in \code{\link[=as.mo]{as.mo()}} and all \code{\link[=mo_property]{mo_*}} functions.
\item \code{AMR_include_PKPD} \cr A \link{logical} to use in \code{\link[=as.sir]{as.sir()}}, to indicate that PK/PD clinical breakpoints must be applied as a last resort - the default is \code{TRUE}.
\item \code{AMR_include_screening} \cr A \link{logical} to use in \code{\link[=as.sir]{as.sir()}}, to indicate that clinical breakpoints for screening are allowed - the default is \code{FALSE}.
\item \code{AMR_include_screening} \cr A \link{logical} to use in \code{\link[=as.sir]{as.sir()}}, to indicate that clinical breakpoints for screening are allowed - the default is \code{NULL}, using these for screening agents only, such as \code{FOX-S}. See \code{\link[=as.sir]{as.sir()}}.
\item \code{AMR_interpretive_rules} \cr A \link{character} to set the default types of rules for \code{\link[=interpretive_rules]{interpretive_rules()}}, \code{\link[=eucast_rules]{eucast_rules()}} and \code{\link[=clsi_rules]{clsi_rules()}}, must be one or more of: \code{"breakpoints"}, \code{"expected_phenotypes"}, \code{"expert"}, \code{"other"}, \code{"custom"}, \code{"all"}, and defaults to \code{c("breakpoints", "expected_phenotypes")}. This option replaces the old option \code{AMR_eucastrules}.
\item \code{AMR_keep_synonyms} \cr A \link{logical} to use in \code{\link[=as.mo]{as.mo()}} and all \code{\link[=mo_property]{mo_*}} functions, to indicate if old, previously valid taxonomic names must be preserved and not be corrected to currently accepted names. The default is \code{FALSE}.
\item \code{AMR_locale} \cr A \link{character} to set the language for the \code{AMR} package, can be one of these supported language names or \href{https://en.wikipedia.org/wiki/ISO_639-1}{ISO 639-1 codes}: English (en), Arabic (ar), Bengali (bn), Chinese (zh), Czech (cs), Danish (da), Dutch (nl), Finnish (fi), French (fr), German (de), Greek (el), Hindi (hi), Indonesian (id), Italian (it), Japanese (ja), Korean (ko), Norwegian (no), Polish (pl), Portuguese (pt), Romanian (ro), Russian (ru), Spanish (es), Swahili (sw), Swedish (sv), Turkish (tr), Ukrainian (uk), Urdu (ur), or Vietnamese (vi). The default is the current system language (if supported, English otherwise).
+1 -1
View File
@@ -12,7 +12,7 @@ The \code{AMR} package is a peer-reviewed, \href{https://amr-for-r.org/#copyrigh
This work was published in the Journal of Statistical Software (Volume 104(3); \doi{10.18637/jss.v104.i03}) and formed the basis of two PhD theses (\doi{10.33612/diss.177417131} and \doi{10.33612/diss.192486375}).
After installing this package, R knows \href{https://amr-for-r.org/reference/microorganisms.html}{\strong{~103 000 distinct microbial species}} (updated April 2026) and all \href{https://amr-for-r.org/reference/antimicrobials.html}{\strong{~630 antimicrobial and antiviral drugs}} by name and code (including ATC, EARS-Net, ASIARS-Net, PubChem, LOINC and SNOMED CT), and knows all about valid SIR and MIC values. The integral clinical breakpoint guidelines from CLSI 2011-2026 and EUCAST 2011-2026 are included, even with epidemiological cut-off (ECOFF) values. It supports and can read any data format, including WHONET data. This package works on Windows, macOS and Linux with all versions of R since R-3.0 (April 2013). \strong{It was designed to work in any setting, including those with very limited resources}. It was created for both routine data analysis and academic research at the Faculty of Medical Sciences of the \href{https://www.rug.nl}{University of Groningen} and the \href{https://www.umcg.nl}{University Medical Center Groningen}.
After installing this package, R knows \href{https://amr-for-r.org/reference/microorganisms.html}{\strong{~103 000 distinct microbial species}} (updated April 2026) and all \href{https://amr-for-r.org/reference/antimicrobials.html}{\strong{~640 antimicrobial and antiviral drugs}} by name and code (including ATC, EARS-Net, ASIARS-Net, PubChem, LOINC and SNOMED CT), and knows all about valid SIR and MIC values. The integral clinical breakpoint guidelines from CLSI 2011-2026 and EUCAST 2011-2026 are included, even with epidemiological cut-off (ECOFF) values. It supports and can read any data format, including WHONET data. This package works on Windows, macOS and Linux with all versions of R since R-3.0 (April 2013). \strong{It was designed to work in any setting, including those with very limited resources}. It was created for both routine data analysis and academic research at the Faculty of Medical Sciences of the \href{https://www.rug.nl}{University of Groningen} and the \href{https://www.umcg.nl}{University Medical Center Groningen}.
The \code{AMR} package is available in English, Arabic, Bengali, Chinese, Czech, Danish, Dutch, Finnish, French, German, Greek, Hindi, Indonesian, Italian, Japanese, Korean, Norwegian, Polish, Portuguese, Romanian, Russian, Spanish, Swahili, Swedish, Turkish, Ukrainian, Urdu, and Vietnamese. Antimicrobial drug (group) names and colloquial microorganism names are provided in these languages.
}
+6 -6
View File
@@ -247,7 +247,7 @@ The \code{\link[=not_intrinsic_resistant]{not_intrinsic_resistant()}} function c
\section{Full list of supported (antimicrobial) classes}{
\itemize{
\item \code{\link[=aminoglycosides]{aminoglycosides()}} can select: \cr amikacin (AMK), amikacin/fosfomycin (AKF), apramycin (APR), arbekacin (ARB), astromicin (AST), bekanamycin (BEK), dibekacin (DKB), framycetin (FRM), gentamicin (GEN), gentamicin-high (GEH), habekacin (HAB), hygromycin (HYG), isepamicin (ISE), kanamycin (KAN), kanamycin-high (KAH), kanamycin/cephalexin (KAC), kasugamycin (KAS), micronomicin (MCR), neomycin (NEO), netilmicin (NET), pentisomicin (PIM), plazomicin (PLZ), propikacin (PKA), ribostamycin (RST), sisomicin (SIS), streptoduocin (STR), streptomycin (STR1), streptomycin-high (STH), tobramycin (TOB), and tobramycin-high (TOH)
\item \code{\link[=aminoglycosides]{aminoglycosides()}} can select: \cr amikacin (AMK), amikacin/fosfomycin (AKF), apramycin (APR), arbekacin (ARB), astromicin (AST), bekanamycin (BEK), dibekacin (DKB), framycetin (FRM), gentamicin (GEN), gentamicin screening test (GEN-S), gentamicin-high (GEH), habekacin (HAB), hygromycin (HYG), isepamicin (ISE), kanamycin (KAN), kanamycin-high (KAH), kanamycin/cephalexin (KAC), kasugamycin (KAS), micronomicin (MCR), neomycin (NEO), neomycin screening test (NEO-S), netilmicin (NET), pentisomicin (PIM), plazomicin (PLZ), propikacin (PKA), ribostamycin (RST), sisomicin (SIS), streptoduocin (STR), streptomycin (STR1), streptomycin screening test (STR1-S), streptomycin-high (STH), tobramycin (TOB), tobramycin screening test (TOB-S), and tobramycin-high (TOH)
\item \code{\link[=aminopenicillins]{aminopenicillins()}} can select: \cr amoxicillin (AMX), amoxicillin/clavulanic acid (AMC), and ampicillin (AMP)
\item \code{\link[=antifungals]{antifungals()}} can select: \cr amorolfine (AMO), amphotericin B (AMB), amphotericin B-high (AMH), anidulafungin (ANI), butoconazole (BUT), caspofungin (CAS), ciclopirox (CIX), clotrimazole (CTR), econazole (ECO), fluconazole (FLU), flucytosine (FCT), fosfluconazole (FFL), griseofulvin (GRI), hachimycin (HCH), ibrexafungerp (IBX), isavuconazole (ISV), isoconazole (ISO), itraconazole (ITR), ketoconazole (KET), manogepix (MGX), micafungin (MIF), miconazole (MCZ), nystatin (NYS), oteseconazole (OTE), pimaricin (PMR), posaconazole (POS), rezafungin (RZF), ribociclib (RBC), sulconazole (SUC), terbinafine (TRB), terconazole (TRC), and voriconazole (VOR)
\item \code{\link[=antimycobacterials]{antimycobacterials()}} can select: \cr 4-aminosalicylic acid (AMA), calcium aminosalicylate (CLA), capreomycin (CAP), clofazimine (CLF), delamanid (DLM), enviomycin (ENV), ethambutol (ETH), ethambutol/isoniazid (ETI), ethionamide (ETI1), isoniazid (INH), isoniazid/sulfamethoxazole/trimethoprim/pyridoxine (IST), morinamide (MRN), p-aminosalicylic acid (PAS), pretomanid (PMD), protionamide (PTH), pyrazinamide (PZA), rifabutin (RIB), rifampicin (RIF), rifampicin/ethambutol/isoniazid (REI), rifampicin/isoniazid (RFI), rifampicin/pyrazinamide/ethambutol/isoniazid (RPEI), rifampicin/pyrazinamide/isoniazid (RPI), rifamycin (RFM), rifapentine (RFP), sodium aminosalicylate (SDA), streptomycin/isoniazid (STI), terizidone (TRZ), thioacetazone (TAT), thioacetazone/isoniazid (THI1), tiocarlide (TCR), and viomycin (VIO)
@@ -260,22 +260,22 @@ The \code{\link[=not_intrinsic_resistant]{not_intrinsic_resistant()}} function c
\item \code{\link[=cephalosporins_3rd]{cephalosporins_3rd()}} can select: \cr cefcapene (CCP), cefcapene pivoxil (CCX), cefdinir (CDR), cefditoren (DIT), cefditoren pivoxil (DIX), cefetamet (CAT), cefetamet pivoxil (CPI), cefixime (CFM), cefmenoxime (CMX), cefodizime (DIZ), cefoperazone (CFP), cefoperazone/sulbactam (CSL), cefotaxime (CTX), cefotaxime screening test (CTX-S), cefotaxime/clavulanic acid (CTC), cefotaxime/sulbactam (CTS), cefotiam hexetil (CHE), cefovecin (FOV), cefpimizole (CFZ), cefpiramide (CPM), cefpodoxime (CPD), cefpodoxime proxetil (CPX), cefpodoxime/clavulanic acid (CDC), cefsulodin (CFS), ceftazidime (CAZ), ceftazidime/avibactam (CZA), ceftazidime/clavulanic acid (CCV), cefteram (CEM), cefteram pivoxil (CPL), ceftibuten (CTB), ceftibuten/avibactam (CTA), ceftiofur (TIO), ceftizoxime (CZX), ceftizoxime alapivoxil (CZP), ceftriaxone (CRO), ceftriaxone/beta-lactamase inhibitor (CEB), and latamoxef (LTM)
\item \code{\link[=cephalosporins_4th]{cephalosporins_4th()}} can select: \cr cefepime (FEP), cefepime/amikacin (CFA), cefepime/clavulanic acid (CPC), cefepime/enmetazobactam (FPE), cefepime/nacubactam (FNC), cefepime/taniborbactam (FTA), cefepime/tazobactam (FPT), cefepime/zidebactam (FPZ), cefetecol (CCL), cefoselis (CSE), cefozopran (ZOP), cefpirome (CPO), and cefquinome (CEQ)
\item \code{\link[=cephalosporins_5th]{cephalosporins_5th()}} can select: \cr ceftaroline (CPT), ceftaroline/avibactam (CPA), ceftobiprole (BPR), ceftobiprole medocaril (CFM1), and ceftolozane/tazobactam (CZT)
\item \code{\link[=fluoroquinolones]{fluoroquinolones()}} can select: \cr besifloxacin (BES), ciprofloxacin (CIP), ciprofloxacin/metronidazole (CIM), ciprofloxacin/ornidazole (CIO), ciprofloxacin/tinidazole (CIT), clinafloxacin (CLX), danofloxacin (DAN), delafloxacin (DFX), difloxacin (DIF), enoxacin (ENX), enrofloxacin (ENR), finafloxacin (FIN), fleroxacin (FLE), garenoxacin (GRN), gatifloxacin (GAT), gemifloxacin (GEM), grepafloxacin (GRX), lascufloxacin (LSC), levofloxacin (LVX), levofloxacin/ornidazole (LEO), levonadifloxacin (LND), lomefloxacin (LOM), marbofloxacin (MAR), metioxate (MXT), miloxacin (MIL), moxifloxacin (MFX), nadifloxacin (NAD), nemonoxacin (NEM), nifuroquine (NIF), nitroxoline (NTR), norfloxacin (NOR), norfloxacin screening test (NOR-S), norfloxacin/metronidazole (NME), norfloxacin/tinidazole (NTI), ofloxacin (OFX), ofloxacin/ornidazole (OOR), orbifloxacin (ORB), pazufloxacin (PAZ), pefloxacin (PEF), pefloxacin screening test (PEF-S), pradofloxacin (PRA), premafloxacin (PRX), prulifloxacin (PRU), rufloxacin (RFL), sarafloxacin (SAR), sitafloxacin (SIT), sparfloxacin (SPX), temafloxacin (TMX), tilbroquinol (TBQ), tioxacin (TXC), tosufloxacin (TFX), and trovafloxacin (TVA)
\item \code{\link[=fluoroquinolones]{fluoroquinolones()}} can select: \cr besifloxacin (BES), ciprofloxacin (CIP), ciprofloxacin screening test (CIP-S), ciprofloxacin/metronidazole (CIM), ciprofloxacin/ornidazole (CIO), ciprofloxacin/tinidazole (CIT), clinafloxacin (CLX), danofloxacin (DAN), delafloxacin (DFX), difloxacin (DIF), enoxacin (ENX), enrofloxacin (ENR), finafloxacin (FIN), fleroxacin (FLE), garenoxacin (GRN), gatifloxacin (GAT), gemifloxacin (GEM), grepafloxacin (GRX), lascufloxacin (LSC), levofloxacin (LVX), levofloxacin screening test (LVX-S), levofloxacin/ornidazole (LEO), levonadifloxacin (LND), lomefloxacin (LOM), marbofloxacin (MAR), metioxate (MXT), miloxacin (MIL), moxifloxacin (MFX), nadifloxacin (NAD), nemonoxacin (NEM), nifuroquine (NIF), nitroxoline (NTR), norfloxacin (NOR), norfloxacin screening test (NOR-S), norfloxacin/metronidazole (NME), norfloxacin/tinidazole (NTI), ofloxacin (OFX), ofloxacin screening test (OFX-S), ofloxacin/ornidazole (OOR), orbifloxacin (ORB), pazufloxacin (PAZ), pefloxacin (PEF), pefloxacin screening test (PEF-S), pradofloxacin (PRA), premafloxacin (PRX), prulifloxacin (PRU), rufloxacin (RFL), sarafloxacin (SAR), sitafloxacin (SIT), sparfloxacin (SPX), temafloxacin (TMX), tilbroquinol (TBQ), tioxacin (TXC), tosufloxacin (TFX), and trovafloxacin (TVA)
\item \code{\link[=glycopeptides]{glycopeptides()}} can select: \cr avoparcin (AVO), bleomycin (BLM), dalbavancin (DAL), norvancomycin (NVA), oritavancin (ORI), ramoplanin (RAM), teicoplanin (TEC), teicoplanin-macromethod (TCM), telavancin (TLV), vancomycin (VAN), vancomycin-macromethod (VAM), and zorbamycin (ZOR)
\item \code{\link[=ionophores]{ionophores()}} can select: \cr lasalocid (LAS), monensin sodium (MON), narasin (NAR), nystatin (NYS), and salinomycin (SAL)
\item \code{\link[=isoxazolylpenicillins]{isoxazolylpenicillins()}} can select: \cr cloxacillin (CLO), dicloxacillin (DIC), flucloxacillin (FLC), meticillin (MET), oxacillin (OXA), and oxacillin screening test (OXA-S)
\item \code{\link[=lincosamides]{lincosamides()}} can select: \cr clindamycin (CLI), clindamycin inducible screening test (CLI-S), lincomycin (LIN), and pirlimycin (PRL)
\item \code{\link[=lipoglycopeptides]{lipoglycopeptides()}} can select: \cr dalbavancin (DAL), oritavancin (ORI), and telavancin (TLV)
\item \code{\link[=macrolides]{macrolides()}} can select: \cr acetylmidecamycin (ACM), acetylspiramycin (ASP), azithromycin (AZM), clarithromycin (CLR), clindamycin inducible screening test (CLI-S), dirithromycin (DIR), erythromycin (ERY), flurithromycin (FLR1), gamithromycin (GAM), josamycin (JOS), kitasamycin (KIT), meleumycin (MEL), midecamycin (MID), miocamycin (MCM), nafithromycin (ZWK), oleandomycin (OLE), pirlimycin (PRL), primycin (PRM), rokitamycin (ROK), roxithromycin (RXT), solithromycin (SOL), spiramycin (SPI), telithromycin (TLT), tildipirosin (TIP), tilmicosin (TIL), troleandomycin (TRL), tulathromycin (TUL), tylosin (TYL), and tylvalosin (TYL1)
\item \code{\link[=macrolides]{macrolides()}} can select: \cr acetylmidecamycin (ACM), acetylspiramycin (ASP), azithromycin (AZM), clarithromycin (CLR), clindamycin inducible screening test (CLI-S), dirithromycin (DIR), erythromycin (ERY), erythromycin screening test (ERY-S), flurithromycin (FLR1), gamithromycin (GAM), josamycin (JOS), kitasamycin (KIT), meleumycin (MEL), midecamycin (MID), miocamycin (MCM), nafithromycin (ZWK), oleandomycin (OLE), pirlimycin (PRL), primycin (PRM), rokitamycin (ROK), roxithromycin (RXT), solithromycin (SOL), spiramycin (SPI), telithromycin (TLT), tildipirosin (TIP), tilmicosin (TIL), troleandomycin (TRL), tulathromycin (TUL), tylosin (TYL), and tylvalosin (TYL1)
\item \code{\link[=monobactams]{monobactams()}} can select: \cr aztreonam (ATM), aztreonam/avibactam (AZA), aztreonam/nacubactam (ANC), carumonam (CAR), and tigemonam (TMN)
\item \code{\link[=nitrofurans]{nitrofurans()}} can select: \cr furazidin (FUR), furazolidone (FRZ), nifurtoinol (NFR), nitrofurantoin (NIT), and nitrofurazone (NIZ)
\item \code{\link[=oxazolidinones]{oxazolidinones()}} can select: \cr cadazolid (CDZ), cycloserine (CYC), linezolid (LNZ), tedizolid (TZD), and thiacetazone (THA)
\item \code{\link[=penicillins]{penicillins()}} can select: \cr amoxicillin (AMX), amoxicillin/clavulanic acid (AMC), amoxicillin/sulbactam (AXS), ampicillin (AMP), ampicillin/sulbactam (SAM), apalcillin (APL), aspoxicillin (APX), azidocillin (AZD), azlocillin (AZL), bacampicillin (BAM), benzathine benzylpenicillin (BNB), benzathine phenoxymethylpenicillin (BNP), benzylpenicillin (PEN), benzylpenicillin screening test (PEN-S), carbenicillin (CRB), carindacillin (CRN), ciclacillin (CIC), clometocillin (CLM), cloxacillin (CLO), dicloxacillin (DIC), epicillin (EPC), flucloxacillin (FLC), hetacillin (HET), lenampicillin (LEN), mecillinam (MEC), metampicillin (MTM), meticillin (MET), mezlocillin (MEZ), mezlocillin/sulbactam (MSU), nafcillin (NAF), oxacillin (OXA), oxacillin screening test (OXA-S), penamecillin (PNM), penicillin/novobiocin (PNO), penicillin/sulbactam (PSU), pheneticillin (PHE), phenoxymethylpenicillin (PHN), piperacillin (PIP), piperacillin/sulbactam (PIS), piperacillin/tazobactam (TZP), piridicillin (PRC), pivampicillin (PVM), pivmecillinam (PME), procaine benzylpenicillin (PRB), propicillin (PRP), sarmoxicillin (SRX), sulbenicillin (SBC), sultamicillin (SLT6), talampicillin (TAL), temocillin (TEM), ticarcillin (TIC), and ticarcillin/clavulanic acid (TCC)
\item \code{\link[=peptides]{peptides()}} can select: \cr avoparcin (AVO), bacitracin (BAC), bleomycin (BLM), dalbavancin (DAL), daptomycin (DAP), norvancomycin (NVA), oritavancin (ORI), ramoplanin (RAM), teicoplanin (TEC), teicoplanin-macromethod (TCM), telavancin (TLV), thiostrepton (THS), vancomycin (VAN), vancomycin-macromethod (VAM), and zorbamycin (ZOR)
\item \code{\link[=phenicols]{phenicols()}} can select: \cr chloramphenicol (CHL), florfenicol (FLR), and thiamphenicol (THI)
\item \code{\link[=phenicols]{phenicols()}} can select: \cr chloramphenicol (CHL), chloramphenicol screening test (CHL-S), florfenicol (FLR), and thiamphenicol (THI)
\item \code{\link[=phosphonics]{phosphonics()}} can select: \cr amikacin/fosfomycin (AKF) and fosfomycin (FOS)
\item \code{\link[=polymyxins]{polymyxins()}} can select: \cr colistin (COL), polymyxin B (PLB), and polymyxin B/polysorbate 80 (POP)
\item \code{\link[=quinolones]{quinolones()}} can select: \cr besifloxacin (BES), cinoxacin (CIN), ciprofloxacin (CIP), ciprofloxacin/metronidazole (CIM), ciprofloxacin/ornidazole (CIO), ciprofloxacin/tinidazole (CIT), clinafloxacin (CLX), danofloxacin (DAN), delafloxacin (DFX), difloxacin (DIF), enoxacin (ENX), enrofloxacin (ENR), finafloxacin (FIN), fleroxacin (FLE), flumequine (FLM), garenoxacin (GRN), gatifloxacin (GAT), gemifloxacin (GEM), grepafloxacin (GRX), lascufloxacin (LSC), levofloxacin (LVX), levofloxacin/ornidazole (LEO), levonadifloxacin (LND), lomefloxacin (LOM), marbofloxacin (MAR), metioxate (MXT), miloxacin (MIL), moxifloxacin (MFX), nadifloxacin (NAD), nalidixic acid (NAL), nalidixic acid screening test (NAL-S), nemonoxacin (NEM), nifuroquine (NIF), nitroxoline (NTR), norfloxacin (NOR), norfloxacin screening test (NOR-S), norfloxacin/metronidazole (NME), norfloxacin/tinidazole (NTI), ofloxacin (OFX), ofloxacin/ornidazole (OOR), orbifloxacin (ORB), oxolinic acid (OXO), ozenoxacin (OZN), pazufloxacin (PAZ), pefloxacin (PEF), pefloxacin screening test (PEF-S), pipemidic acid (PPA), piromidic acid (PIR), pradofloxacin (PRA), premafloxacin (PRX), prulifloxacin (PRU), rosoxacin (ROS), rufloxacin (RFL), sarafloxacin (SAR), sitafloxacin (SIT), sparfloxacin (SPX), temafloxacin (TMX), tilbroquinol (TBQ), tioxacin (TXC), tosufloxacin (TFX), and trovafloxacin (TVA)
\item \code{\link[=polymyxins]{polymyxins()}} can select: \cr colistin (COL), colistin screening test (COL-S), polymyxin B (PLB), and polymyxin B/polysorbate 80 (POP)
\item \code{\link[=quinolones]{quinolones()}} can select: \cr besifloxacin (BES), cinoxacin (CIN), ciprofloxacin (CIP), ciprofloxacin screening test (CIP-S), ciprofloxacin/metronidazole (CIM), ciprofloxacin/ornidazole (CIO), ciprofloxacin/tinidazole (CIT), clinafloxacin (CLX), danofloxacin (DAN), delafloxacin (DFX), difloxacin (DIF), enoxacin (ENX), enrofloxacin (ENR), finafloxacin (FIN), fleroxacin (FLE), flumequine (FLM), garenoxacin (GRN), gatifloxacin (GAT), gemifloxacin (GEM), grepafloxacin (GRX), lascufloxacin (LSC), levofloxacin (LVX), levofloxacin screening test (LVX-S), levofloxacin/ornidazole (LEO), levonadifloxacin (LND), lomefloxacin (LOM), marbofloxacin (MAR), metioxate (MXT), miloxacin (MIL), moxifloxacin (MFX), nadifloxacin (NAD), nalidixic acid (NAL), nalidixic acid screening test (NAL-S), nemonoxacin (NEM), nifuroquine (NIF), nitroxoline (NTR), norfloxacin (NOR), norfloxacin screening test (NOR-S), norfloxacin/metronidazole (NME), norfloxacin/tinidazole (NTI), ofloxacin (OFX), ofloxacin screening test (OFX-S), ofloxacin/ornidazole (OOR), orbifloxacin (ORB), oxolinic acid (OXO), ozenoxacin (OZN), pazufloxacin (PAZ), pefloxacin (PEF), pefloxacin screening test (PEF-S), pipemidic acid (PPA), piromidic acid (PIR), pradofloxacin (PRA), premafloxacin (PRX), prulifloxacin (PRU), rosoxacin (ROS), rufloxacin (RFL), sarafloxacin (SAR), sitafloxacin (SIT), sparfloxacin (SPX), temafloxacin (TMX), tilbroquinol (TBQ), tioxacin (TXC), tosufloxacin (TFX), and trovafloxacin (TVA)
\item \code{\link[=rifamycins]{rifamycins()}} can select: \cr rifabutin (RIB), rifampicin (RIF), rifampicin/ethambutol/isoniazid (REI), rifampicin/isoniazid (RFI), rifampicin/pyrazinamide/ethambutol/isoniazid (RPEI), rifampicin/pyrazinamide/isoniazid (RPI), rifamycin (RFM), and rifapentine (RFP)
\item \code{\link[=spiropyrimidinetriones]{spiropyrimidinetriones()}} can select: \cr zoliflodacin (ZFD)
\item \code{\link[=streptogramins]{streptogramins()}} can select: \cr ostreogrycin (OST), pristinamycin (PRI), quinupristin/dalfopristin (QDA), and virginiamycine (VIR)
+3 -3
View File
@@ -5,9 +5,9 @@
\alias{antimicrobials}
\alias{antibiotics}
\alias{antivirals}
\title{Data Sets with 626 Antimicrobial Drugs}
\title{Data Sets with 639 Antimicrobial Drugs}
\format{
\subsection{For the \link{antimicrobials} data set: a \link[tibble:tibble]{tibble} with 506 observations and 14 variables:}{
\subsection{For the \link{antimicrobials} data set: a \link[tibble:tibble]{tibble} with 519 observations and 14 variables:}{
\itemize{
\item \code{ab}\cr antimicrobial ID as used in this package (such as \code{AMC}), using the official EARS-Net (European Antimicrobial Resistance Surveillance Network) codes where available. \emph{\strong{This is a unique identifier.}}
\item \code{cid}\cr Compound ID as found in PubChem. \emph{\strong{This is a unique identifier.}}
@@ -50,7 +50,7 @@ LOINC:
}
}
An object of class \code{deprecated_amr_dataset} (inherits from \code{tbl_df}, \code{tbl}, \code{data.frame}) with 506 rows and 14 columns.
An object of class \code{deprecated_amr_dataset} (inherits from \code{tbl_df}, \code{tbl}, \code{data.frame}) with 519 rows and 14 columns.
An object of class \code{tbl_df} (inherits from \code{tbl}, \code{data.frame}) with 120 rows and 11 columns.
}
+10 -5
View File
@@ -47,7 +47,7 @@ is_sir_eligible(x, threshold = 0.05)
reference_data = AMR::clinical_breakpoints,
substitute_missing_r_breakpoint = getOption("AMR_substitute_missing_r_breakpoint",
FALSE),
include_screening = getOption("AMR_include_screening", FALSE),
include_screening = getOption("AMR_include_screening", NULL),
include_PKPD = getOption("AMR_include_PKPD", TRUE),
breakpoint_type = getOption("AMR_breakpoint_type", "human"),
host = NULL,
@@ -55,6 +55,7 @@ is_sir_eligible(x, threshold = 0.05)
verbose = FALSE,
info = interactive(),
conserve_capped_values = NULL,
site = NULL,
...
)
@@ -69,13 +70,14 @@ is_sir_eligible(x, threshold = 0.05)
reference_data = AMR::clinical_breakpoints,
substitute_missing_r_breakpoint = getOption("AMR_substitute_missing_r_breakpoint",
FALSE),
include_screening = getOption("AMR_include_screening", FALSE),
include_screening = getOption("AMR_include_screening", NULL),
include_PKPD = getOption("AMR_include_PKPD", TRUE),
breakpoint_type = getOption("AMR_breakpoint_type", "human"),
host = NULL,
language = get_AMR_locale(),
verbose = FALSE,
info = interactive(),
site = NULL,
...
)
@@ -91,7 +93,7 @@ is_sir_eligible(x, threshold = 0.05)
reference_data = AMR::clinical_breakpoints,
substitute_missing_r_breakpoint = getOption("AMR_substitute_missing_r_breakpoint",
FALSE),
include_screening = getOption("AMR_include_screening", FALSE),
include_screening = getOption("AMR_include_screening", NULL),
include_PKPD = getOption("AMR_include_PKPD", TRUE),
breakpoint_type = getOption("AMR_breakpoint_type", "human"),
host = NULL,
@@ -99,7 +101,8 @@ is_sir_eligible(x, threshold = 0.05)
verbose = FALSE,
info = interactive(),
parallel = FALSE,
conserve_capped_values = NULL
conserve_capped_values = NULL,
site = NULL
)
sir_interpretation_history(clean = FALSE)
@@ -165,7 +168,7 @@ The default \code{"standard"} setting ensures cautious handling of uncertain val
\item{substitute_missing_r_breakpoint}{A \link{logical} to indicate that a missing clinical breakpoints for R (resistant) must be substituted with R - the default is \code{FALSE}. Some (especially CLSI) breakpoints only have a breakpoint for S, meaning that the outcome can only be \code{"S"} or \code{NA}. Setting this to \code{TRUE} will convert the \code{NA}s in these cases to \code{"R"}. Can also be set with the package option \code{\link[=AMR-options]{AMR_substitute_missing_r_breakpoint}}.}
\item{include_screening}{A \link{logical} to indicate that clinical breakpoints for screening are allowed - the default is \code{FALSE}. Can also be set with the package option \code{\link[=AMR-options]{AMR_include_screening}}.}
\item{include_screening}{A \link{logical} to indicate that clinical breakpoints for screening are allowed. At default (\code{NULL}, can be set with the package option \code{\link[=AMR-options]{AMR_include_screening}}), these are only used for screening agents, e.g. \code{FOX-S}, but not for regular agents, e.g. \code{FOX}. Use \code{TRUE} to also use them for regular agents (with \code{FOX} then taking the breakpoints of \code{FOX-S}), and \code{FALSE} to never use them, which gives \code{NA} with a note for a screening agent.}
\item{include_PKPD}{A \link{logical} to indicate that PK/PD clinical breakpoints must be applied as a last resort - the default is \code{TRUE}. Can also be set with the package option \code{\link[=AMR-options]{AMR_include_PKPD}}.}
@@ -179,6 +182,8 @@ The default \code{"standard"} setting ensures cautious handling of uncertain val
\item{conserve_capped_values}{Deprecated, use \code{capped_mic_handling} instead.}
\item{site}{The site or route that the isolate is interpreted for: a \link{character} vector or a column name, in the fixed codes \code{"systemic"}, \code{"iv"}, \code{"meningitis"}, \code{"endocarditis"}, \code{"pneumonia"}, \code{"mastitis"}, \code{"respiratory"}, \code{"metritis"}, \code{"genital"}, \code{"intestinal"}, \code{"other"}, \code{"non-meningitis"}, \code{"non-endocarditis"}, \code{"non-pneumonia"}, \code{"extraintestinal"}, \code{"soft tissue"}, \code{"skin"}, \code{"wounds"}, \code{"inhaled"}, \code{"oral"}, \code{"prophylaxis"}, \code{"uti"} and \code{"topical"}, which can be combined with a comma, e.g. \code{"iv, meningitis"}. If \code{site} is \code{NA} (default), any breakpoint matching all other criteria can apply, taken from most to least systemic site in the order just given; a breakpoint without a site takes the position of \code{"other"}, as both mean any site that is not listed next to it. If \code{site} is set, a breakpoint for a contradicting site is left out, e.g. \code{"meningitis"} leaves out \code{Non-meningitis}, while a breakpoint without a site still applies. \code{"other"} leaves out every breakpoint limited to an indication, and prefers a breakpoint without a site. Related sites do not contradict each other: \code{"pneumonia"} and \code{"respiratory"}, \code{"metritis"} and \code{"genital"}, and \code{"soft tissue"}, \code{"skin"} and \code{"wounds"}. The code \code{"mastitis"} includes \verb{Mammary gland}, and \code{"wounds"} includes \code{Abscesses}. The result is \code{NA} if only contradicting sites are available, also when PK/PD breakpoints exist. All choices are noted in \code{\link[=sir_interpretation_history]{sir_interpretation_history()}}.}
\item{col_mo}{Column name of the names or codes of the microorganisms (see \code{\link[=as.mo]{as.mo()}}) - the default is the first column of class \code{\link{mo}}. Values will be coerced using \code{\link[=as.mo]{as.mo()}}.}
\item{parallel}{A \link{logical} to indicate if parallel computing must be used, defaults to \code{FALSE}. Requires the \code{\link[future.apply:future_lapply]{future.apply}} package. \strong{A non-sequential \code{\link[future:plan]{future::plan()}} must already be active before setting \code{parallel = TRUE}} — for example, \code{future::plan(future::multisession)}. An error is thrown if \code{parallel = TRUE} is used without a plan set by the user. Parallelism distributes columns (and optionally row batches) across workers; it is most beneficial when there are many antibiotic columns and a large number of rows.}
+5 -3
View File
@@ -5,7 +5,7 @@
\alias{clinical_breakpoints}
\title{Data Set with Clinical Breakpoints for SIR Interpretation}
\format{
A \link[tibble:tibble]{tibble} with 61 389 observations and 15 variables:
A \link[tibble:tibble]{tibble} with 48 764 observations and 15 variables:
\itemize{
\item \code{guideline}\cr Name of the guideline
\item \code{type}\cr Breakpoint type, either \code{"ECOFF"}, \code{"animal"}, or \code{"human"}
@@ -13,7 +13,7 @@ A \link[tibble:tibble]{tibble} with 61 389 observations and 15 variables:
\item \code{method}\cr Testing method, either \code{"DISK"} or \code{"MIC"}
\item \code{site}\cr Body site for which the breakpoint must be applied, e.g. "Oral" or "Respiratory"
\item \code{mo}\cr Microbial ID, see \code{\link[=as.mo]{as.mo()}}
\item \code{rank_index}\cr Taxonomic rank index of \code{mo}, used to choose the most specific breakpoint (the lowest index): 1 for subspecies and infraspecies, 2 for species, 2.5 for species groups (e.g., \emph{Streptococcus} group A), 3 for genus, 4 for family, 5 for order, 6 for other groups (e.g., Gram-negative or anaerobic bacteria), and 7 for non-species related (PK-PD) breakpoints. Blocking rows (see \emph{Details}) have the rank index of their organism + 0.1, e.g., 2.6 for a species group, so that a breakpoint for the same organism always takes precedence.
\item \code{rank_index}\cr Taxonomic rank index of \code{mo}, used to choose the most specific breakpoint (the lowest index): 1 for subspecies and infraspecies, 2 for species, 2.5 for species groups (e.g., \emph{Streptococcus} group A), 3 for genus, 4 for family, 5 for order, 5.5 for anaerobic bacteria, 6 for other groups (e.g., Gram-negative bacteria), and 7 for non-species related (PK-PD) breakpoints. Blocking rows (see \emph{Details}) have the rank index of their organism + 0.1, e.g., 2.6 for a species group, so that a breakpoint for the same organism always takes precedence.
\item \code{ab}\cr Antimicrobial code as used by this package, EARS-Net and WHONET, see \code{\link[=as.ab]{as.ab()}}
\item \code{ref_tbl}\cr Info about where the guideline rule can be found
\item \code{disk_dose}\cr Dose of the used disk diffusion method
@@ -49,7 +49,9 @@ The default is \code{"human"}, which can also be set with the package option \co
\subsection{Blocking Rows}{
Where EUCAST lists an organism but gives no breakpoint for it (e.g. "IE", "-", "Note", breakpoints in brackets, an organism excluded with "except", or no S category for a zone diameter), \code{\link[=as.sir]{as.sir()}} must not fall back to the breakpoint of a broader taxon, such as the breakpoint for \emph{Vibrio} spp. where EUCAST gives "IE" for \emph{V. fluvialis}. Such cases are included as "blocking rows": rows in which \code{breakpoint_S} and \code{breakpoint_R} are both \code{NA} and the \code{note} starts with \code{"[No breakpoint]"} followed by the reason. \code{\link[=as.sir]{as.sir()}} returns \code{NA} for these. This currently applies to 15 660 rows. Remove them with \code{subset(clinical_breakpoints, !is.na(breakpoint_S))} if only actual breakpoints are needed.
Where EUCAST lists an organism but gives no breakpoint for it (e.g. "IE", "-", "Note", an organism excluded with "except", or no S category for a zone diameter), \code{\link[=as.sir]{as.sir()}} must not fall back to the breakpoint of a broader taxon, such as the breakpoint for \emph{Vibrio} spp. where EUCAST gives "IE" for \emph{V. fluvialis}. Such cases are included as "blocking rows": rows in which \code{breakpoint_S} and \code{breakpoint_R} are both \code{NA} and the \code{note} starts with \code{"[No breakpoint]"} followed by the reason. \code{\link[=as.sir]{as.sir()}} returns \code{NA} for these. This currently applies to 2 398 rows. Remove them with \code{subset(clinical_breakpoints, !is.na(breakpoint_S))} if only actual breakpoints are needed.
\strong{EUCAST's breakpoints in brackets} are not in this data set. EUCAST bases these on ECOFFs, and states that reporting S or I should be avoided. \code{\link[=as.sir]{as.sir()}} therefore treats them as absent, and can use PK/PD breakpoints or, for unknown UTI status, UTI breakpoints instead. All bracketed values are kept in the \href{https://github.com/msberends/AMR/blob/main/data-raw/breakpoints_eucast_raw.csv}{raw import of the EUCAST tables} (column \code{is_bracketed}).
Where another guideline has no S category for a zone diameter, such as CLSI for fluconazole in \emph{C. glabrata} (SDD and R only), only \code{breakpoint_R} is given, and the \code{note} starts with \code{"[No S category]"}. \code{\link[=as.sir]{as.sir()}} then returns R where applicable, and \code{NA} otherwise.
}
+8 -8
View File
@@ -101,7 +101,7 @@ x
These 43 antimicrobial groups are allowed in the rules (case-insensitive) and can be used in any combination:
\itemize{
\item aminocoumarins\cr(clorobiocin, novobiocin, and penicillin/novobiocin)
\item aminoglycosides\cr(amikacin, amikacin/fosfomycin, apramycin, arbekacin, astromicin, bekanamycin, dibekacin, framycetin, gentamicin, gentamicin-high, habekacin, hygromycin, isepamicin, kanamycin, kanamycin-high, kanamycin/cephalexin, kasugamycin, micronomicin, neomycin, netilmicin, pentisomicin, plazomicin, propikacin, ribostamycin, sisomicin, streptoduocin, streptomycin, streptomycin-high, tobramycin, and tobramycin-high)
\item aminoglycosides\cr(amikacin, amikacin/fosfomycin, apramycin, arbekacin, astromicin, bekanamycin, dibekacin, framycetin, gentamicin, gentamicin screening test, gentamicin-high, habekacin, hygromycin, isepamicin, kanamycin, kanamycin-high, kanamycin/cephalexin, kasugamycin, micronomicin, neomycin, neomycin screening test, netilmicin, pentisomicin, plazomicin, propikacin, ribostamycin, sisomicin, streptoduocin, streptomycin, streptomycin screening test, streptomycin-high, tobramycin, tobramycin screening test, and tobramycin-high)
\item aminopenicillins\cr(amoxicillin, amoxicillin/clavulanic acid, and ampicillin)
\item antifungals\cr(amorolfine, amphotericin B, amphotericin B-high, anidulafungin, butoconazole, caspofungin, ciclopirox, clotrimazole, econazole, fluconazole, flucytosine, fosfluconazole, griseofulvin, hachimycin, ibrexafungerp, isavuconazole, isoconazole, itraconazole, ketoconazole, manogepix, micafungin, miconazole, nystatin, oteseconazole, pimaricin, posaconazole, rezafungin, ribociclib, sulconazole, terbinafine, terconazole, and voriconazole)
\item antimycobacterials\cr(4-aminosalicylic acid, calcium aminosalicylate, capreomycin, clofazimine, delamanid, enviomycin, ethambutol, ethambutol/isoniazid, ethionamide, isoniazid, isoniazid/sulfamethoxazole/trimethoprim/pyridoxine, morinamide, p-aminosalicylic acid, pretomanid, protionamide, pyrazinamide, rifabutin, rifampicin, rifampicin/ethambutol/isoniazid, rifampicin/isoniazid, rifampicin/pyrazinamide/ethambutol/isoniazid, rifampicin/pyrazinamide/isoniazid, rifamycin, rifapentine, sodium aminosalicylate, streptomycin/isoniazid, terizidone, thioacetazone, thioacetazone/isoniazid, tiocarlide, and viomycin)
@@ -116,25 +116,25 @@ These 43 antimicrobial groups are allowed in the rules (case-insensitive) and ca
\item cephalosporins_4th\cr(cefepime, cefepime/amikacin, cefepime/clavulanic acid, cefepime/enmetazobactam, cefepime/nacubactam, cefepime/taniborbactam, cefepime/tazobactam, cefepime/zidebactam, cefetecol, cefoselis, cefozopran, cefpirome, and cefquinome)
\item cephalosporins_5th\cr(ceftaroline, ceftaroline/avibactam, ceftobiprole, ceftobiprole medocaril, and ceftolozane/tazobactam)
\item cephalosporins_except_caz\cr(cefacetrile, cefaclor, cefadroxil, cefalexin, cefaloridine, cefalotin, cefamandole, cefapirin, cefatrizine, cefazedone, cefazolin, cefcapene, cefcapene pivoxil, cefdinir, cefditoren, cefditoren pivoxil, cefepime, cefepime/amikacin, cefepime/clavulanic acid, cefepime/enmetazobactam, cefepime/nacubactam, cefepime/taniborbactam, cefepime/tazobactam, cefepime/zidebactam, cefetamet, cefetamet pivoxil, cefetecol, cefetrizole, cefiderocol, cefixime, cefmenoxime, cefmetazole, cefodizime, cefonicid, cefoperazone, cefoperazone/sulbactam, ceforanide, cefoselis, cefotaxime, cefotaxime screening test, cefotaxime/clavulanic acid, cefotaxime/sulbactam, cefotetan, cefotiam, cefotiam hexetil, cefovecin, cefoxitin, cefoxitin screening test, cefozopran, cefpimizole, cefpiramide, cefpirome, cefpodoxime, cefpodoxime proxetil, cefpodoxime/clavulanic acid, cefprozil, cefquinome, cefroxadine, cefsulodin, cefsumide, ceftaroline, ceftaroline/avibactam, ceftazidime/avibactam, ceftazidime/clavulanic acid, cefteram, cefteram pivoxil, ceftezole, ceftibuten, ceftibuten/avibactam, ceftiofur, ceftizoxime, ceftizoxime alapivoxil, ceftobiprole, ceftobiprole medocaril, ceftolozane/tazobactam, ceftriaxone, ceftriaxone/beta-lactamase inhibitor, cefuroxime, cefuroxime axetil, cephradine, latamoxef, and loracarbef)
\item fluoroquinolones\cr(besifloxacin, ciprofloxacin, ciprofloxacin/metronidazole, ciprofloxacin/ornidazole, ciprofloxacin/tinidazole, clinafloxacin, danofloxacin, delafloxacin, difloxacin, enoxacin, enrofloxacin, finafloxacin, fleroxacin, garenoxacin, gatifloxacin, gemifloxacin, grepafloxacin, lascufloxacin, levofloxacin, levofloxacin/ornidazole, levonadifloxacin, lomefloxacin, marbofloxacin, metioxate, miloxacin, moxifloxacin, nadifloxacin, nemonoxacin, nifuroquine, nitroxoline, norfloxacin, norfloxacin screening test, norfloxacin/metronidazole, norfloxacin/tinidazole, ofloxacin, ofloxacin/ornidazole, orbifloxacin, pazufloxacin, pefloxacin, pefloxacin screening test, pradofloxacin, premafloxacin, prulifloxacin, rufloxacin, sarafloxacin, sitafloxacin, sparfloxacin, temafloxacin, tilbroquinol, tioxacin, tosufloxacin, and trovafloxacin)
\item fusidanes\cr(fusidic acid)
\item fluoroquinolones\cr(besifloxacin, ciprofloxacin, ciprofloxacin screening test, ciprofloxacin/metronidazole, ciprofloxacin/ornidazole, ciprofloxacin/tinidazole, clinafloxacin, danofloxacin, delafloxacin, difloxacin, enoxacin, enrofloxacin, finafloxacin, fleroxacin, garenoxacin, gatifloxacin, gemifloxacin, grepafloxacin, lascufloxacin, levofloxacin, levofloxacin screening test, levofloxacin/ornidazole, levonadifloxacin, lomefloxacin, marbofloxacin, metioxate, miloxacin, moxifloxacin, nadifloxacin, nemonoxacin, nifuroquine, nitroxoline, norfloxacin, norfloxacin screening test, norfloxacin/metronidazole, norfloxacin/tinidazole, ofloxacin, ofloxacin screening test, ofloxacin/ornidazole, orbifloxacin, pazufloxacin, pefloxacin, pefloxacin screening test, pradofloxacin, premafloxacin, prulifloxacin, rufloxacin, sarafloxacin, sitafloxacin, sparfloxacin, temafloxacin, tilbroquinol, tioxacin, tosufloxacin, and trovafloxacin)
\item fusidanes\cr(fusidic acid and fusidic acid screening test)
\item glycopeptides\cr(avoparcin, bleomycin, dalbavancin, norvancomycin, oritavancin, ramoplanin, teicoplanin, teicoplanin-macromethod, telavancin, vancomycin, vancomycin-macromethod, and zorbamycin)
\item glycopeptides_except_lipo\cr(avoparcin, bleomycin, norvancomycin, ramoplanin, teicoplanin, teicoplanin-macromethod, vancomycin, vancomycin-macromethod, and zorbamycin)
\item ionophores\cr(lasalocid, monensin sodium, narasin, nystatin, and salinomycin)
\item isoxazolylpenicillins\cr(cloxacillin, dicloxacillin, flucloxacillin, meticillin, oxacillin, and oxacillin screening test)
\item lincosamides\cr(clindamycin, clindamycin inducible screening test, lincomycin, and pirlimycin)
\item lipoglycopeptides\cr(dalbavancin, oritavancin, and telavancin)
\item macrolides\cr(acetylmidecamycin, acetylspiramycin, azithromycin, clarithromycin, clindamycin inducible screening test, dirithromycin, erythromycin, flurithromycin, gamithromycin, josamycin, kitasamycin, meleumycin, midecamycin, miocamycin, nafithromycin, oleandomycin, pirlimycin, primycin, rokitamycin, roxithromycin, solithromycin, spiramycin, telithromycin, tildipirosin, tilmicosin, troleandomycin, tulathromycin, tylosin, and tylvalosin)
\item macrolides\cr(acetylmidecamycin, acetylspiramycin, azithromycin, clarithromycin, clindamycin inducible screening test, dirithromycin, erythromycin, erythromycin screening test, flurithromycin, gamithromycin, josamycin, kitasamycin, meleumycin, midecamycin, miocamycin, nafithromycin, oleandomycin, pirlimycin, primycin, rokitamycin, roxithromycin, solithromycin, spiramycin, telithromycin, tildipirosin, tilmicosin, troleandomycin, tulathromycin, tylosin, and tylvalosin)
\item monobactams\cr(aztreonam, aztreonam/avibactam, aztreonam/nacubactam, carumonam, and tigemonam)
\item nitrofurans\cr(furazidin, furazolidone, nifurtoinol, nitrofurantoin, and nitrofurazone)
\item oxazolidinones\cr(cadazolid, cycloserine, linezolid, tedizolid, and thiacetazone)
\item penicillins\cr(amoxicillin, amoxicillin/clavulanic acid, amoxicillin/sulbactam, ampicillin, ampicillin/sulbactam, apalcillin, aspoxicillin, azidocillin, azlocillin, bacampicillin, benzathine benzylpenicillin, benzathine phenoxymethylpenicillin, benzylpenicillin, benzylpenicillin screening test, carbenicillin, carindacillin, ciclacillin, clometocillin, cloxacillin, dicloxacillin, epicillin, flucloxacillin, hetacillin, lenampicillin, mecillinam, metampicillin, meticillin, mezlocillin, mezlocillin/sulbactam, nafcillin, oxacillin, oxacillin screening test, penamecillin, penicillin/novobiocin, penicillin/sulbactam, pheneticillin, phenoxymethylpenicillin, piperacillin, piperacillin/sulbactam, piperacillin/tazobactam, piridicillin, pivampicillin, pivmecillinam, procaine benzylpenicillin, propicillin, sarmoxicillin, sulbenicillin, sultamicillin, talampicillin, temocillin, ticarcillin, and ticarcillin/clavulanic acid)
\item peptides\cr(avoparcin, bacitracin, bleomycin, dalbavancin, daptomycin, norvancomycin, oritavancin, ramoplanin, teicoplanin, teicoplanin-macromethod, telavancin, thiostrepton, vancomycin, vancomycin-macromethod, and zorbamycin)
\item phenicols\cr(chloramphenicol, florfenicol, and thiamphenicol)
\item phenicols\cr(chloramphenicol, chloramphenicol screening test, florfenicol, and thiamphenicol)
\item phosphonics\cr(amikacin/fosfomycin and fosfomycin)
\item pleuromutilins\cr(retapamulin and tiamulin)
\item polymyxins\cr(colistin, polymyxin B, and polymyxin B/polysorbate 80)
\item quinolones\cr(besifloxacin, cinoxacin, ciprofloxacin, ciprofloxacin/metronidazole, ciprofloxacin/ornidazole, ciprofloxacin/tinidazole, clinafloxacin, danofloxacin, delafloxacin, difloxacin, enoxacin, enrofloxacin, finafloxacin, fleroxacin, flumequine, garenoxacin, gatifloxacin, gemifloxacin, grepafloxacin, lascufloxacin, levofloxacin, levofloxacin/ornidazole, levonadifloxacin, lomefloxacin, marbofloxacin, metioxate, miloxacin, moxifloxacin, nadifloxacin, nalidixic acid, nalidixic acid screening test, nemonoxacin, nifuroquine, nitroxoline, norfloxacin, norfloxacin screening test, norfloxacin/metronidazole, norfloxacin/tinidazole, ofloxacin, ofloxacin/ornidazole, orbifloxacin, oxolinic acid, ozenoxacin, pazufloxacin, pefloxacin, pefloxacin screening test, pipemidic acid, piromidic acid, pradofloxacin, premafloxacin, prulifloxacin, rosoxacin, rufloxacin, sarafloxacin, sitafloxacin, sparfloxacin, temafloxacin, tilbroquinol, tioxacin, tosufloxacin, and trovafloxacin)
\item pleuromutilins\cr(retapamulin, retapamulin screening test, and tiamulin)
\item polymyxins\cr(colistin, colistin screening test, polymyxin B, and polymyxin B/polysorbate 80)
\item quinolones\cr(besifloxacin, cinoxacin, ciprofloxacin, ciprofloxacin screening test, ciprofloxacin/metronidazole, ciprofloxacin/ornidazole, ciprofloxacin/tinidazole, clinafloxacin, danofloxacin, delafloxacin, difloxacin, enoxacin, enrofloxacin, finafloxacin, fleroxacin, flumequine, garenoxacin, gatifloxacin, gemifloxacin, grepafloxacin, lascufloxacin, levofloxacin, levofloxacin screening test, levofloxacin/ornidazole, levonadifloxacin, lomefloxacin, marbofloxacin, metioxate, miloxacin, moxifloxacin, nadifloxacin, nalidixic acid, nalidixic acid screening test, nemonoxacin, nifuroquine, nitroxoline, norfloxacin, norfloxacin screening test, norfloxacin/metronidazole, norfloxacin/tinidazole, ofloxacin, ofloxacin screening test, ofloxacin/ornidazole, orbifloxacin, oxolinic acid, ozenoxacin, pazufloxacin, pefloxacin, pefloxacin screening test, pipemidic acid, piromidic acid, pradofloxacin, premafloxacin, prulifloxacin, rosoxacin, rufloxacin, sarafloxacin, sitafloxacin, sparfloxacin, temafloxacin, tilbroquinol, tioxacin, tosufloxacin, and trovafloxacin)
\item rifamycins\cr(rifabutin, rifampicin, rifampicin/ethambutol/isoniazid, rifampicin/isoniazid, rifampicin/pyrazinamide/ethambutol/isoniazid, rifampicin/pyrazinamide/isoniazid, rifamycin, and rifapentine)
\item spiropyrimidinetriones\cr(zoliflodacin)
\item streptogramins\cr(ostreogrycin, pristinamycin, quinupristin/dalfopristin, and virginiamycine)
+6 -6
View File
@@ -96,7 +96,7 @@ You can define antimicrobial groups instead of single antimicrobials for the rul
All 43 antimicrobial selectors are supported for use in the rules:
\itemize{
\item \code{\link[=aminoglycosides]{aminoglycosides()}} can select: \cr amikacin, amikacin/fosfomycin, apramycin, arbekacin, astromicin, bekanamycin, dibekacin, framycetin, gentamicin, gentamicin-high, habekacin, hygromycin, isepamicin, kanamycin, kanamycin-high, kanamycin/cephalexin, kasugamycin, micronomicin, neomycin, netilmicin, pentisomicin, plazomicin, propikacin, ribostamycin, sisomicin, streptoduocin, streptomycin, streptomycin-high, tobramycin, and tobramycin-high
\item \code{\link[=aminoglycosides]{aminoglycosides()}} can select: \cr amikacin, amikacin/fosfomycin, apramycin, arbekacin, astromicin, bekanamycin, dibekacin, framycetin, gentamicin, gentamicin screening test, gentamicin-high, habekacin, hygromycin, isepamicin, kanamycin, kanamycin-high, kanamycin/cephalexin, kasugamycin, micronomicin, neomycin, neomycin screening test, netilmicin, pentisomicin, plazomicin, propikacin, ribostamycin, sisomicin, streptoduocin, streptomycin, streptomycin screening test, streptomycin-high, tobramycin, tobramycin screening test, and tobramycin-high
\item \code{\link[=aminopenicillins]{aminopenicillins()}} can select: \cr amoxicillin, amoxicillin/clavulanic acid, and ampicillin
\item \code{\link[=antifungals]{antifungals()}} can select: \cr amorolfine, amphotericin B, amphotericin B-high, anidulafungin, butoconazole, caspofungin, ciclopirox, clotrimazole, econazole, fluconazole, flucytosine, fosfluconazole, griseofulvin, hachimycin, ibrexafungerp, isavuconazole, isoconazole, itraconazole, ketoconazole, manogepix, micafungin, miconazole, nystatin, oteseconazole, pimaricin, posaconazole, rezafungin, ribociclib, sulconazole, terbinafine, terconazole, and voriconazole
\item \code{\link[=antimycobacterials]{antimycobacterials()}} can select: \cr 4-aminosalicylic acid, calcium aminosalicylate, capreomycin, clofazimine, delamanid, enviomycin, ethambutol, ethambutol/isoniazid, ethionamide, isoniazid, isoniazid/sulfamethoxazole/trimethoprim/pyridoxine, morinamide, p-aminosalicylic acid, pretomanid, protionamide, pyrazinamide, rifabutin, rifampicin, rifampicin/ethambutol/isoniazid, rifampicin/isoniazid, rifampicin/pyrazinamide/ethambutol/isoniazid, rifampicin/pyrazinamide/isoniazid, rifamycin, rifapentine, sodium aminosalicylate, streptomycin/isoniazid, terizidone, thioacetazone, thioacetazone/isoniazid, tiocarlide, and viomycin
@@ -109,22 +109,22 @@ All 43 antimicrobial selectors are supported for use in the rules:
\item \code{\link[=cephalosporins_3rd]{cephalosporins_3rd()}} can select: \cr cefcapene, cefcapene pivoxil, cefdinir, cefditoren, cefditoren pivoxil, cefetamet, cefetamet pivoxil, cefixime, cefmenoxime, cefodizime, cefoperazone, cefoperazone/sulbactam, cefotaxime, cefotaxime screening test, cefotaxime/clavulanic acid, cefotaxime/sulbactam, cefotiam hexetil, cefovecin, cefpimizole, cefpiramide, cefpodoxime, cefpodoxime proxetil, cefpodoxime/clavulanic acid, cefsulodin, ceftazidime, ceftazidime/avibactam, ceftazidime/clavulanic acid, cefteram, cefteram pivoxil, ceftibuten, ceftibuten/avibactam, ceftiofur, ceftizoxime, ceftizoxime alapivoxil, ceftriaxone, ceftriaxone/beta-lactamase inhibitor, and latamoxef
\item \code{\link[=cephalosporins_4th]{cephalosporins_4th()}} can select: \cr cefepime, cefepime/amikacin, cefepime/clavulanic acid, cefepime/enmetazobactam, cefepime/nacubactam, cefepime/taniborbactam, cefepime/tazobactam, cefepime/zidebactam, cefetecol, cefoselis, cefozopran, cefpirome, and cefquinome
\item \code{\link[=cephalosporins_5th]{cephalosporins_5th()}} can select: \cr ceftaroline, ceftaroline/avibactam, ceftobiprole, ceftobiprole medocaril, and ceftolozane/tazobactam
\item \code{\link[=fluoroquinolones]{fluoroquinolones()}} can select: \cr besifloxacin, ciprofloxacin, ciprofloxacin/metronidazole, ciprofloxacin/ornidazole, ciprofloxacin/tinidazole, clinafloxacin, danofloxacin, delafloxacin, difloxacin, enoxacin, enrofloxacin, finafloxacin, fleroxacin, garenoxacin, gatifloxacin, gemifloxacin, grepafloxacin, lascufloxacin, levofloxacin, levofloxacin/ornidazole, levonadifloxacin, lomefloxacin, marbofloxacin, metioxate, miloxacin, moxifloxacin, nadifloxacin, nemonoxacin, nifuroquine, nitroxoline, norfloxacin, norfloxacin screening test, norfloxacin/metronidazole, norfloxacin/tinidazole, ofloxacin, ofloxacin/ornidazole, orbifloxacin, pazufloxacin, pefloxacin, pefloxacin screening test, pradofloxacin, premafloxacin, prulifloxacin, rufloxacin, sarafloxacin, sitafloxacin, sparfloxacin, temafloxacin, tilbroquinol, tioxacin, tosufloxacin, and trovafloxacin
\item \code{\link[=fluoroquinolones]{fluoroquinolones()}} can select: \cr besifloxacin, ciprofloxacin, ciprofloxacin screening test, ciprofloxacin/metronidazole, ciprofloxacin/ornidazole, ciprofloxacin/tinidazole, clinafloxacin, danofloxacin, delafloxacin, difloxacin, enoxacin, enrofloxacin, finafloxacin, fleroxacin, garenoxacin, gatifloxacin, gemifloxacin, grepafloxacin, lascufloxacin, levofloxacin, levofloxacin screening test, levofloxacin/ornidazole, levonadifloxacin, lomefloxacin, marbofloxacin, metioxate, miloxacin, moxifloxacin, nadifloxacin, nemonoxacin, nifuroquine, nitroxoline, norfloxacin, norfloxacin screening test, norfloxacin/metronidazole, norfloxacin/tinidazole, ofloxacin, ofloxacin screening test, ofloxacin/ornidazole, orbifloxacin, pazufloxacin, pefloxacin, pefloxacin screening test, pradofloxacin, premafloxacin, prulifloxacin, rufloxacin, sarafloxacin, sitafloxacin, sparfloxacin, temafloxacin, tilbroquinol, tioxacin, tosufloxacin, and trovafloxacin
\item \code{\link[=glycopeptides]{glycopeptides()}} can select: \cr avoparcin, bleomycin, dalbavancin, norvancomycin, oritavancin, ramoplanin, teicoplanin, teicoplanin-macromethod, telavancin, vancomycin, vancomycin-macromethod, and zorbamycin
\item \code{\link[=ionophores]{ionophores()}} can select: \cr lasalocid, monensin sodium, narasin, nystatin, and salinomycin
\item \code{\link[=isoxazolylpenicillins]{isoxazolylpenicillins()}} can select: \cr cloxacillin, dicloxacillin, flucloxacillin, meticillin, oxacillin, and oxacillin screening test
\item \code{\link[=lincosamides]{lincosamides()}} can select: \cr clindamycin, clindamycin inducible screening test, lincomycin, and pirlimycin
\item \code{\link[=lipoglycopeptides]{lipoglycopeptides()}} can select: \cr dalbavancin, oritavancin, and telavancin
\item \code{\link[=macrolides]{macrolides()}} can select: \cr acetylmidecamycin, acetylspiramycin, azithromycin, clarithromycin, clindamycin inducible screening test, dirithromycin, erythromycin, flurithromycin, gamithromycin, josamycin, kitasamycin, meleumycin, midecamycin, miocamycin, nafithromycin, oleandomycin, pirlimycin, primycin, rokitamycin, roxithromycin, solithromycin, spiramycin, telithromycin, tildipirosin, tilmicosin, troleandomycin, tulathromycin, tylosin, and tylvalosin
\item \code{\link[=macrolides]{macrolides()}} can select: \cr acetylmidecamycin, acetylspiramycin, azithromycin, clarithromycin, clindamycin inducible screening test, dirithromycin, erythromycin, erythromycin screening test, flurithromycin, gamithromycin, josamycin, kitasamycin, meleumycin, midecamycin, miocamycin, nafithromycin, oleandomycin, pirlimycin, primycin, rokitamycin, roxithromycin, solithromycin, spiramycin, telithromycin, tildipirosin, tilmicosin, troleandomycin, tulathromycin, tylosin, and tylvalosin
\item \code{\link[=monobactams]{monobactams()}} can select: \cr aztreonam, aztreonam/avibactam, aztreonam/nacubactam, carumonam, and tigemonam
\item \code{\link[=nitrofurans]{nitrofurans()}} can select: \cr furazidin, furazolidone, nifurtoinol, nitrofurantoin, and nitrofurazone
\item \code{\link[=oxazolidinones]{oxazolidinones()}} can select: \cr cadazolid, cycloserine, linezolid, tedizolid, and thiacetazone
\item \code{\link[=penicillins]{penicillins()}} can select: \cr amoxicillin, amoxicillin/clavulanic acid, amoxicillin/sulbactam, ampicillin, ampicillin/sulbactam, apalcillin, aspoxicillin, azidocillin, azlocillin, bacampicillin, benzathine benzylpenicillin, benzathine phenoxymethylpenicillin, benzylpenicillin, benzylpenicillin screening test, carbenicillin, carindacillin, ciclacillin, clometocillin, cloxacillin, dicloxacillin, epicillin, flucloxacillin, hetacillin, lenampicillin, mecillinam, metampicillin, meticillin, mezlocillin, mezlocillin/sulbactam, nafcillin, oxacillin, oxacillin screening test, penamecillin, penicillin/novobiocin, penicillin/sulbactam, pheneticillin, phenoxymethylpenicillin, piperacillin, piperacillin/sulbactam, piperacillin/tazobactam, piridicillin, pivampicillin, pivmecillinam, procaine benzylpenicillin, propicillin, sarmoxicillin, sulbenicillin, sultamicillin, talampicillin, temocillin, ticarcillin, and ticarcillin/clavulanic acid
\item \code{\link[=peptides]{peptides()}} can select: \cr avoparcin, bacitracin, bleomycin, dalbavancin, daptomycin, norvancomycin, oritavancin, ramoplanin, teicoplanin, teicoplanin-macromethod, telavancin, thiostrepton, vancomycin, vancomycin-macromethod, and zorbamycin
\item \code{\link[=phenicols]{phenicols()}} can select: \cr chloramphenicol, florfenicol, and thiamphenicol
\item \code{\link[=phenicols]{phenicols()}} can select: \cr chloramphenicol, chloramphenicol screening test, florfenicol, and thiamphenicol
\item \code{\link[=phosphonics]{phosphonics()}} can select: \cr amikacin/fosfomycin and fosfomycin
\item \code{\link[=polymyxins]{polymyxins()}} can select: \cr colistin, polymyxin B, and polymyxin B/polysorbate 80
\item \code{\link[=quinolones]{quinolones()}} can select: \cr besifloxacin, cinoxacin, ciprofloxacin, ciprofloxacin/metronidazole, ciprofloxacin/ornidazole, ciprofloxacin/tinidazole, clinafloxacin, danofloxacin, delafloxacin, difloxacin, enoxacin, enrofloxacin, finafloxacin, fleroxacin, flumequine, garenoxacin, gatifloxacin, gemifloxacin, grepafloxacin, lascufloxacin, levofloxacin, levofloxacin/ornidazole, levonadifloxacin, lomefloxacin, marbofloxacin, metioxate, miloxacin, moxifloxacin, nadifloxacin, nalidixic acid, nalidixic acid screening test, nemonoxacin, nifuroquine, nitroxoline, norfloxacin, norfloxacin screening test, norfloxacin/metronidazole, norfloxacin/tinidazole, ofloxacin, ofloxacin/ornidazole, orbifloxacin, oxolinic acid, ozenoxacin, pazufloxacin, pefloxacin, pefloxacin screening test, pipemidic acid, piromidic acid, pradofloxacin, premafloxacin, prulifloxacin, rosoxacin, rufloxacin, sarafloxacin, sitafloxacin, sparfloxacin, temafloxacin, tilbroquinol, tioxacin, tosufloxacin, and trovafloxacin
\item \code{\link[=polymyxins]{polymyxins()}} can select: \cr colistin, colistin screening test, polymyxin B, and polymyxin B/polysorbate 80
\item \code{\link[=quinolones]{quinolones()}} can select: \cr besifloxacin, cinoxacin, ciprofloxacin, ciprofloxacin screening test, ciprofloxacin/metronidazole, ciprofloxacin/ornidazole, ciprofloxacin/tinidazole, clinafloxacin, danofloxacin, delafloxacin, difloxacin, enoxacin, enrofloxacin, finafloxacin, fleroxacin, flumequine, garenoxacin, gatifloxacin, gemifloxacin, grepafloxacin, lascufloxacin, levofloxacin, levofloxacin screening test, levofloxacin/ornidazole, levonadifloxacin, lomefloxacin, marbofloxacin, metioxate, miloxacin, moxifloxacin, nadifloxacin, nalidixic acid, nalidixic acid screening test, nemonoxacin, nifuroquine, nitroxoline, norfloxacin, norfloxacin screening test, norfloxacin/metronidazole, norfloxacin/tinidazole, ofloxacin, ofloxacin screening test, ofloxacin/ornidazole, orbifloxacin, oxolinic acid, ozenoxacin, pazufloxacin, pefloxacin, pefloxacin screening test, pipemidic acid, piromidic acid, pradofloxacin, premafloxacin, prulifloxacin, rosoxacin, rufloxacin, sarafloxacin, sitafloxacin, sparfloxacin, temafloxacin, tilbroquinol, tioxacin, tosufloxacin, and trovafloxacin
\item \code{\link[=rifamycins]{rifamycins()}} can select: \cr rifabutin, rifampicin, rifampicin/ethambutol/isoniazid, rifampicin/isoniazid, rifampicin/pyrazinamide/ethambutol/isoniazid, rifampicin/pyrazinamide/isoniazid, rifamycin, and rifapentine
\item \code{\link[=spiropyrimidinetriones]{spiropyrimidinetriones()}} can select: \cr zoliflodacin
\item \code{\link[=streptogramins]{streptogramins()}} can select: \cr ostreogrycin, pristinamycin, quinupristin/dalfopristin, and virginiamycine
-12
View File
@@ -162,18 +162,6 @@ Key antimicrobials are internally selected using the \code{\link[=key_antimicrob
The default method is phenotype-based (using \code{type = "points"}) and episode-based (using \code{episode_days = 365}). This makes sure that every genus-species combination is selected per patient once per year, while taking into account all antimicrobial test results. If no antimicrobial test results are available in the data set, only the episode-based method is applied at default.
}
\subsection{First isolates per additional variable}{
To determine first isolates separately for the values of any additional variable, such as a ward, a specimen group, a molecular marker or a locally defined classification, group the data with \code{\link[dplyr:group_by]{dplyr::group_by()}} before calling \code{\link[=first_isolate]{first_isolate()}}. Every group is then handled as a separate data set, so the selection, including the start of every episode, is determined per patient, genus-species combination and group value. This works with all methods described above:
\if{html}{\out{<div class="sourceCode r">}}\preformatted{your_data \%>\%
group_by(ward) \%>\%
mutate(first = first_isolate())
}\if{html}{\out{</div>}}
Be aware that grouping on a variable that is related to antimicrobial resistance, such as a resistance mechanism or the output of \code{\link[=mdro]{mdro()}}, retains more isolates of patients whose isolates change category. This deviates from CLSI M39 and generally leads to an overestimation of resistance, as the selection then depends on the outcome that is being estimated.
}
}
\examples{
# `example_isolates` is a data set available in the AMR package.
+154
View File
@@ -601,6 +601,157 @@ test_that("microorganisms.codes: unique codes for existing names", {
expect_true(all(is.na(microorganisms.codes$source) | grepl("^WHONET \\(.+\\)$", microorganisms.codes$source)))
})
test_that("clinical_breakpoints: screening tests are under screening agents (#328)", {
skip_on_cran()
cb <- as.data.frame(clinical_breakpoints, stringsAsFactors = FALSE)
ab <- as.character(cb$ab)
year <- as.integer(gsub("[^0-9]", "", cb$guideline))
is_regular <- !grepl("-S$", ab)
# no regular agent has a screening site
expect_false(any(is_regular & grepl("screen", cb$site, ignore.case = TRUE)))
expect_true(all(c("FOX-S", "OXA-S", "NAL-S", "NOR-S", "PEF-S", "PEN-S", "TCY-S", "ERY-S", "GEN-S", "STR1-S", "CIP-S", "MUP-S") %in% ab))
# all codes of screening agents are valid, without an ATC code
screening_agents <- subset(AMR::antimicrobials, grepl("-S$", ab))
expect_true(all(unique(ab[!is_regular]) %in% screening_agents$ab))
expect_true(all(grepl("screening test$", screening_agents$name)))
# the two high-level codes hold no rows themselves, and are still valid
expect_false(any(ab %in% c("GEH", "STH")))
expect_true(all(c("GEH", "STH") %in% AMR::antimicrobials$ab))
# topical cut-off values
# (mupirocin also has actual breakpoints for nasal decolonisation, #329)
topical <- cb[cb$site %in% "Topical" & !as.character(cb$ab) %in% "MUP", , drop = FALSE]
expect_true(all(grepl("-S$", as.character(topical$ab))))
expect_false(any(cb$site %in% "Topical, Screen"))
# explicit lists: moved
human <- cb$type == "human"
expect_false(any(human & cb$guideline %like% "EUCAST" & year %in% 2012:2018 & ab == "FOX" & cb$method == "MIC" & as.character(cb$mo) %in% c("B_STPHY_AURS", "B_STPHY_LGDN")))
expect_false(any(human & cb$guideline %like% "CLSI" & ab == "FOX" & mo_genus(cb$mo, keep_synonyms = TRUE, language = NULL) %in% "Staphylococcus"))
expect_false(any(human & cb$guideline %like% "CLSI" & year >= 2015 & ab == "PEF" & mo_genus(cb$mo, keep_synonyms = TRUE, language = NULL) %in% "Salmonella"))
# explicit list: stays under the regular agent, also as decided in the issue
expect_true(any(human & cb$guideline == "EUCAST 2013" & ab == "NAL" & cb$method == "DISK"))
expect_true(any(human & cb$guideline == "CLSI 2026" & ab == "OXA" & as.character(cb$mo) == "B_STRPT_PNMN" & cb$method == "DISK"))
# rows that are a clinical breakpoint and a screen are under both (from EUCAST 2023)
ery <- function(agent) cb[human & cb$guideline == "EUCAST 2026" & ab == agent & as.character(cb$mo) == "B_MRXLL_CTRR" & cb$method == "DISK", c("breakpoint_S", "breakpoint_R"), drop = FALSE]
expect_true(nrow(ery("ERY")) > 0)
expect_identical(unname(as.list(ery("ERY-S"))), unname(as.list(ery("ERY"))))
})
test_that("clinical_breakpoints: every blocking row of EUCAST has an effect (#326)", {
skip_on_cran()
cb <- as.data.frame(clinical_breakpoints, stringsAsFactors = FALSE)
cb <- cb[cb$type == "human" & grepl("EUCAST 20(19|2[0-9])", cb$guideline), , drop = FALSE]
is_blocking <- is.na(cb$breakpoint_S) & is.na(cb$breakpoint_R)
key <- paste(cb$guideline, cb$ab, cb$method)
# a blocking row needs a breakpoint to block, for all years
has_breakpoint <- key %in% key[!is_blocking]
wrong <- unique(key[is_blocking & !has_breakpoint])
expect_true(length(wrong) == 0, info = paste("no breakpoints to block:", toString(utils::head(wrong, 20))))
# and as.sir() must give another result without it, for the latest guideline; all years are checked during the build
latest <- paste0("EUCAST ", max(as.integer(gsub("[^0-9]", "", cb$guideline))))
for (k in unique(key[is_blocking & cb$guideline == latest])) {
group <- cb[key == k, , drop = FALSE]
for (i in which(is.na(group$breakpoint_S) & is.na(group$breakpoint_R))) {
expect_true(blocking_row_is_needed(i, group), info = paste(k, group$mo[i], group$site[i]))
}
}
# the definition itself, on a constructed set of rows
rows <- cb[cb$guideline == latest & as.character(cb$ab) == "CTX" & cb$method == "MIC" & as.character(cb$mo) == "B_VIBRI_CHLR" & cb$type == "human", , drop = FALSE][1, ]
rows$mo <- as.mo("Vibrio", info = FALSE)
rows$rank_index <- 3
blocker <- rows
blocker$mo <- as.mo("Vibrio fluvialis", info = FALSE)
blocker$rank_index <- 2.1
blocker$breakpoint_S <- NA_real_
blocker$breakpoint_R <- NA_real_
group <- rbind(rows, blocker)
expect_true(blocking_row_is_needed(2, group))
expect_false(blocking_row_is_needed(1, blocker))
})
test_that("clinical_breakpoints: EUCAST breakpoints of Vibrio are for the species that EUCAST states", {
skip_on_cran()
cb <- as.data.frame(clinical_breakpoints, stringsAsFactors = FALSE)
cb$mo <- as.character(cb$mo)
cb <- cb[cb$type == "human" & cb$guideline %in% paste("EUCAST", 2022:2026), , drop = FALSE]
species <- as.character(as.mo(c("Vibrio alginolyticus", "Vibrio cholerae", "Vibrio fluvialis", "Vibrio parahaemolyticus", "Vibrio vulnificus"), info = FALSE))
vibrio <- cb[grepl("^B_VIBRI", cb$mo), , drop = FALSE]
expect_identical(sort(unique(vibrio$mo)), sort(species))
has_values <- !is.na(vibrio$breakpoint_S) | !is.na(vibrio$breakpoint_R)
expect_true(all(grepl("Breakpoints are valid for V. alginolyticus", vibrio$note[has_values], fixed = TRUE)))
# all species have the same breakpoints per year, apart from the IE of cefotaxime for V. fluvialis
key <- paste(vibrio$guideline, vibrio$ab, vibrio$method, vibrio$breakpoint_S, vibrio$breakpoint_R)[has_values & !(vibrio$ab == "CTX")]
expect_true(all(table(key) == 5))
expect_false(any(has_values & vibrio$ab == "CTX" & vibrio$mo == as.character(as.mo("Vibrio fluvialis", info = FALSE))))
})
test_that("clinical_breakpoints: EUCAST breakpoints stated in the Notes (#329)", {
skip_on_cran()
cb <- as.data.frame(clinical_breakpoints, stringsAsFactors = FALSE)
cb <- cb[cb$type == "human", , drop = FALSE]
bp <- function(guideline, ab, mo, method, site = NULL) {
x <- cb[cb$guideline == guideline & as.character(cb$ab) == ab & as.character(cb$mo) == as.character(as.mo(mo, info = FALSE)) & cb$method == method, , drop = FALSE]
if (!is.null(site)) {
x <- x[x$site %in% site, , drop = FALSE]
}
c(x$breakpoint_S, x$breakpoint_R)
}
# oxacillin disk for S. pseudintermedius and related species
expect_identical(bp("EUCAST 2019", "OXA-S", "S. pseudintermedius", "DISK"), c(20, 20))
expect_identical(bp("EUCAST 2026", "OXA-S", "S. pseudintermedius", "DISK"), c(20, 20))
# oxacillin MIC for coagulase-negative staphylococci, not for the species excluded by EUCAST
expect_identical(bp("EUCAST 2026", "OXA-S", "B_STPHY_CONS", "MIC"), c(0.25, 0.25))
expect_identical(bp("EUCAST 2026", "OXA-S", "S. lugdunensis", "MIC"), c(NA_real_, NA_real_))
expect_identical(bp("EUCAST 2026", "OXA-S", "S. saprophyticus", "MIC"), c(NA_real_, NA_real_))
# hedged statements are not taken over
expect_false(any(as.character(cb$ab) == "OXA-S" & as.character(cb$mo) == "B_STPHY_AURS" & cb$method == "MIC" & !is.na(cb$breakpoint_R)))
# mupirocin for nasal decolonisation, which changed over the years
expect_identical(bp("EUCAST 2023", "MUP", "S. aureus", "MIC", "Topical"), c(1, 256))
expect_identical(bp("EUCAST 2023", "MUP", "S. aureus", "DISK", "Topical"), c(30, 18))
expect_identical(bp("EUCAST 2026", "MUP", "S. aureus", "MIC", "Topical"), c(1, 1))
expect_identical(bp("EUCAST 2026", "MUP", "S. aureus", "DISK", "Topical"), c(30, 30))
# meropenem in other infections than meningitis for N. meningitidis, stated in EUCAST 2021
expect_identical(bp("EUCAST 2021", "MEM", "N. meningitidis", "MIC", "Non-meningitis"), c(0.25, 0.25))
# Bacteroides extends to these taxa for both methods, unlike H. influenzae, which extends for MIC only
for (g in paste("EUCAST", 2023:2026)) {
for (to in c("Parabacteroides", "Phocaeicola dorei", "Phocaeicola vulgatus")) {
for (m in c("MIC", "DISK")) {
from_rows <- cb[cb$guideline == g & as.character(cb$mo) == "B_BCTRD" & cb$method == m & !is.na(cb$breakpoint_S), , drop = FALSE]
to_rows <- cb[cb$guideline == g & as.character(cb$mo) == as.character(as.mo(to, info = FALSE)) & cb$method == m & !is.na(cb$breakpoint_S), , drop = FALSE]
expect_true(nrow(from_rows) > 0, info = paste(g, m))
expect_true(all(as.character(from_rows$ab) %in% as.character(to_rows$ab)), info = paste(g, to, m))
}
}
}
expect_false(any(as.character(cb$mo) == "B_HMPHL_PRNF" & cb$method == "DISK" & cb$guideline %like% "EUCAST 202" & !is.na(cb$breakpoint_S)))
})
test_that("clinical_breakpoints: no EUCAST breakpoints in brackets (#327)", {
skip_on_cran()
expect_false(any(grepl("brackets", clinical_breakpoints$note, fixed = TRUE)))
expect_false(any(grepl("[( )]", clinical_breakpoints$note, fixed = TRUE)))
# e.g., systemic amikacin for Enterobacterales in EUCAST 2026, with only the breakpoint for infections originating from the urinary tract left
amk <- subset(clinical_breakpoints, guideline == "EUCAST 2026" & type == "human" & ab == "AMK" & method == "MIC" & mo == "B_[ORD]_ENTRBCTR")
expect_identical(nrow(amk), 1L)
expect_true(amk$uti)
})
test_that("clinical_breakpoints: EUCAST MIC breakpoints are stored as published (#331)", {
skip_on_cran()
cb <- as.data.frame(clinical_breakpoints, stringsAsFactors = FALSE)
cb <- cb[cb$type == "human" & cb$method == "MIC" & cb$guideline %like% "EUCAST" & cb$ref_tbl %like% "file: ", , drop = FALSE]
expect_true(nrow(cb) > 0)
# these notations do not occur in the EUCAST Clinical Breakpoint Tables
published_as <- c("0.032" = 0.032, "0.064" = 0.064, "0.0001" = 0.0001)
for (value in names(published_as)) {
wrong <- which(cb$breakpoint_S == published_as[value] | cb$breakpoint_R == published_as[value])
expect_true(length(wrong) == 0, info = paste("EUCAST MIC breakpoint", value, "in", paste(unique(cb$guideline[wrong]), collapse = ", ")))
}
# but those as published do, e.g., benzylpenicillin for group A streptococci in v16.1
expect_true(any(cb$breakpoint_S == 0.03, na.rm = TRUE))
expect_true(any(cb$breakpoint_S == 0.06, na.rm = TRUE))
expect_true(any(cb$breakpoint_S == 0.001, na.rm = TRUE))
})
test_that("clinical_breakpoints: consistent and unambiguous", {
skip_on_cran()
cb <- clinical_breakpoints
@@ -623,6 +774,9 @@ test_that("clinical_breakpoints: consistent and unambiguous", {
expected <- c("subspecies" = 1, "species" = 2, "species group" = 2.5, "genus" = 3, "family" = 4, "order" = 5)[rank]
wrong <- which(!is.na(expected) & floor(cb$rank_index * 2) / 2 != expected & cb$rank_index != expected)
expect_true(length(wrong) == 0, info = paste("rank_index does not match the rank:", describe_mo(unique(cb$mo[wrong]))))
# anaerobes are more specific than a Gram stain, with or without the 0.1 of a blocking row
expect_true(all(cb$rank_index[grepl("^B_ANAER", cb$mo)] %in% c(5.5, 5.6)))
expect_true(all(cb$rank_index[cb$mo %in% c("B_GRAMN", "B_GRAMP")] %in% c(6, 6.1)))
})
test_that("antimicrobials: unique and well-formed", {
+248 -6
View File
@@ -433,7 +433,7 @@ test_that("test-sir.R", {
)
# an S category remains unaffected, e.g. EUCAST CIP in E. coli (S <= 0.25, R > 0.5)
expect_equal(
suppressMessages(as.sir(as.mic(c("<=0.5", "<0.5", "<=0.25")), mo = "Escherichia coli", ab = "CIP", guideline = "EUCAST 2026", capped_mic_handling = "standard")),
suppressMessages(as.sir(as.mic(c("<=0.5", "<0.5", "<=0.25")), mo = "Escherichia coli", ab = "CIP", guideline = "EUCAST 2026", capped_mic_handling = "standard", site = "non-meningitis")),
as.sir(c("NI", "S", "S"))
)
# capped values must not be forced to S or R if there is no breakpoint (blocking row, here: EUCAST CIP in S. aureus in brackets only)
@@ -638,9 +638,231 @@ test_that("custom reference_data: host = NA acts as host-agnostic fallback", {
expect_equal(as.character(result), "R")
})
test_that("as.sir() uses screening breakpoints as specified (#328)", {
skip_on_cran()
sir <- function(ab, ...) {
as.character(suppressMessages(suppressWarnings(as.sir(as.disk(20), mo = "S. aureus", ab = ab, guideline = "EUCAST 2026", info = FALSE, ...))))
}
expect_identical(sir("FOX"), NA_character_)
expect_false(is.na(sir("FOX-S")))
expect_false(is.na(sir("FOX-S", include_screening = TRUE)))
expect_false(is.na(sir("FOX", include_screening = TRUE)))
expect_identical(sir("FOX", include_screening = TRUE), sir("FOX-S"))
expect_identical(sir("FOX", include_screening = FALSE), NA_character_)
expect_identical(sir("FOX-S", include_screening = FALSE), NA_character_)
# with a note, as this may be by accident
expect_message(as.sir(as.disk(20), mo = "S. aureus", ab = "FOX-S", guideline = "EUCAST 2026", include_screening = FALSE, info = FALSE), "include_screening")
sir_interpretation_history(clean = TRUE)
sir("FOX-S", include_screening = FALSE)
sir_history <- sir_interpretation_history(clean = TRUE)
expect_match(sir_history$notes, "include_screening = FALSE", fixed = TRUE)
})
test_that("as.sir() takes the site of a breakpoint into account", {
skip_on_cran()
sir <- function(x, mo, ab, ..., guideline = "EUCAST 2026") {
as.character(suppressMessages(suppressWarnings(as.sir(x, mo = mo, ab = ab, guideline = guideline, info = FALSE, ...))))
}
# every site in the data set, for humans and for animals, must be known, so that none can be overlooked
sites <- unique(clinical_breakpoints$site[!is.na(clinical_breakpoints$site)])
for (s in sites) {
known <- vapply(setdiff(sir_site_parts(s), SIR_SITE_NOT_A_SITE), function(part) length(sir_site_tokens(part)) == 1, logical(1))
expect_true(all(known), info = s)
}
expect_identical(sort(names(SIR_SITE_PATTERNS)), sort(SIR_SITE_ORDER))
expect_identical(
SIR_SITE_ORDER,
c("systemic", "iv", "meningitis", "endocarditis", "pneumonia", "mastitis", "respiratory", "metritis", "genital", "intestinal", "other", "non-meningitis", "non-endocarditis", "non-pneumonia", "extraintestinal", "soft tissue", "skin", "wounds", "inhaled", "oral", "prophylaxis", "uti", "topical", "screen")
)
# the fixed codes, all other values give an error
expect_identical(sir_site_normalise(c("Meningitis", "iv, meningitis", NA)), c("meningitis", "iv,meningitis", NA))
expect_error(as.sir(as.mic(1), mo = "E. coli", ab = "AMC", site = "brain", info = FALSE))
expect_error(as.sir(as.mic(1), mo = "E. coli", ab = "AMC", site = "uti", uti = FALSE, info = FALSE))
# contradictions: only with a site in the same group, or a negation
expect_false(sir_site_fits("non-meningitis", "meningitis"))
expect_false(sir_site_fits("meningitis", "non-meningitis"))
expect_false(sir_site_fits("pneumonia", "meningitis"))
expect_false(sir_site_fits("oral", "iv"))
expect_true(sir_site_fits(character(0), "meningitis"))
expect_true(sir_site_fits("iv", "meningitis"))
expect_true(sir_site_fits(c("iv", "meningitis"), "meningitis"))
expect_true(sir_site_fits("non-endocarditis", "meningitis"))
expect_true(sir_site_fits("systemic", "meningitis"))
expect_false(sir_site_fits("systemic", "uti"))
# veterinary sites: the same rules, where sites that are part of each other do not contradict
expect_identical(sir_site_tokens("Mammary gland"), "mastitis")
expect_identical(sir_site_tokens("Wounds, abscesses"), "wounds")
expect_false(sir_site_fits("mastitis", "respiratory"))
expect_false(sir_site_fits("respiratory", "uti"))
expect_true(sir_site_fits("respiratory", "pneumonia"))
expect_true(sir_site_fits("pneumonia", "respiratory"))
expect_true(sir_site_fits("metritis", "genital"))
expect_true(sir_site_fits(c("skin", "soft tissue"), "wounds"))
# "other" means any site not listed: it fits no breakpoint limited to an indication, but it does fit the rest
expect_false(sir_site_fits("meningitis", "other"))
expect_false(sir_site_fits("uti", "other"))
expect_false(sir_site_fits("mastitis", "other"))
expect_true(sir_site_fits(character(0), "other"))
expect_true(sir_site_fits("other", "other"))
expect_true(sir_site_fits("non-meningitis", "other"))
expect_true(sir_site_fits("iv", "other"))
expect_true(sir_site_given(character(0), "other"))
expect_false(sir_site_given(character(0), "uti"))
# site = NA takes the most systemic site, also compared to a breakpoint without a site
expect_true(sir_site_rank("Systemic infections") < sir_site_rank("Intravenous"))
expect_true(sir_site_rank("Intravenous") < sir_site_rank("Meningitis"))
expect_true(sir_site_rank("Pneumonia") < sir_site_rank("Mastitis"))
expect_identical(sir_site_rank("Mastitis"), sir_site_rank("Mammary gland"))
expect_true(sir_site_rank("Mastitis") < sir_site_rank("Intestinal"))
# "other" and no site are one position: below meningitis, and above UTI
expect_identical(sir_site_rank(NA), sir_site_rank("Other infections"))
expect_true(sir_site_rank("Meningitis") < sir_site_rank("Other infections"))
expect_true(sir_site_rank("Other infections") < sir_site_rank("Uncomplicated urinary tract infection"))
expect_true(sir_site_rank("Intestinal") < sir_site_rank(NA))
expect_true(sir_site_rank(NA) < sir_site_rank("Non-meningitis"))
expect_true(sir_site_rank("Oral") < sir_site_rank("Uncomplicated urinary tract infection"))
# a second site breaks a tie on the first one
expect_true(sir_site_rank("Intravenous, Meningitis") < sir_site_rank("Intravenous, Non-meningitis"))
expect_true(sir_site_rank("Intravenous, Non-meningitis") < sir_site_rank("Meningitis"))
# the order of sites does not make a Gram stain precede the more specific anaerobes: CLSI Table 2J, not Table 2B-5
expect_identical(sir(as.mic(16), "Bacteroides fragilis", "CRO", guideline = "CLSI 2022"), "S")
# and it does make a meningitis breakpoint precede a non-meningitis breakpoint of another taxon of the same rank
expect_identical(sir(as.mic(0.25), "Streptococcus agalactiae", "PEN", guideline = "EUCAST 2024"), "R")
# "other" in as.sir(): takes the breakpoint for other infections, or without a site
expect_identical(sir(as.mic(0.25), "Streptococcus pneumoniae", "PEN", site = "other", guideline = "EUCAST 2012"), "I")
expect_identical(sir(as.mic(0.25), "Streptococcus pneumoniae", "PEN", site = "meningitis", guideline = "EUCAST 2012"), "R")
# only breakpoints limited to an indication: no result
expect_identical(sir(as.mic(1), "Escherichia coli", "NTR", site = "other"), NA_character_)
# veterinary: per site for the host, and no result for another site
vet <- function(x, mo, ab, ...) {
sir(x, mo, ab, guideline = "CLSI 2026", breakpoint_type = "animal", host = "cattle", ...)
}
expect_identical(vet(as.mic(2), "Staphylococcus aureus", "KAC", site = "mastitis"), "S")
expect_identical(vet(as.mic(32), "Staphylococcus aureus", "KAC", site = "mastitis"), "R")
expect_identical(vet(as.mic(2), "Staphylococcus aureus", "KAC", site = "meningitis"), NA_character_)
# S. pneumoniae and benzylpenicillin, with breakpoints for meningitis and for other infections
pen <- as.mic(0.25)
expect_identical(sir(pen, "Streptococcus pneumoniae", "PEN", site = "meningitis"), "R")
expect_identical(sir(pen, "Streptococcus pneumoniae", "PEN", site = "non-meningitis"), "I")
expect_identical(sir(pen, "Streptococcus pneumoniae", "PEN"), "R")
sir_interpretation_history(clean = TRUE)
sir(pen, "Streptococcus pneumoniae", "PEN")
history <- sir_interpretation_history(clean = TRUE)
expect_match(history$site, "Meningitis", fixed = TRUE)
expect_match(history$notes, "Multiple breakpoints available", fixed = TRUE)
# amoxicillin in Enterobacterales: per route
amx <- as.mic(4)
expect_identical(sir(amx, "Escherichia coli", "AMX", site = "iv"), "S")
expect_identical(sir(amx, "Escherichia coli", "AMX"), "S")
# only breakpoints for other sites: no result, and no fallback to PK/PD
expect_identical(sir(as.mic(1), "Escherichia coli", "NTR", site = "meningitis"), NA_character_)
expect_identical(sir(as.mic(1), "Escherichia coli", "NTR", site = "uti"), "S")
expect_identical(sir(as.mic(1), "Escherichia coli", "NTR", uti = TRUE), "S")
# vectorised, also in combination with uti, of which NA, TRUE and FALSE can be mixed
expect_identical(
sir(as.mic(c(0.25, 0.25)), "Streptococcus pneumoniae", "PEN", site = c("meningitis", "non-meningitis")),
c("R", "I")
)
expect_identical(
sir(as.mic(c(16, 16, 16)), "Escherichia coli", "NTR", uti = c(NA, TRUE, FALSE)),
c("S", "S", NA)
)
# on a data.frame, with a column name and with fixed values, without treating the column as an antimicrobial
df <- data.frame(mo = "Streptococcus pneumoniae", PEN = as.mic(c(0.25, 0.25)), where = c("meningitis", "non-meningitis"), stringsAsFactors = FALSE)
out <- suppressMessages(suppressWarnings(as.sir(df, col_mo = "mo", guideline = "EUCAST 2026", site = "where", info = FALSE)))
expect_identical(as.character(out$PEN), c("R", "I"))
expect_identical(out$where, df$where)
out <- suppressMessages(suppressWarnings(as.sir(df, col_mo = "mo", guideline = "EUCAST 2026", site = "non-meningitis", info = FALSE)))
expect_identical(as.character(out$PEN), c("I", "I"))
})
test_that("MIC breakpoints are compared as dilutions, not as their notation (#331)", {
skip_on_cran()
sir <- function(x, mo, ab, guideline = "EUCAST 2026") {
as.character(suppressMessages(suppressWarnings(as.sir(as.mic(x), mo = mo, ab = ab, guideline = guideline, info = FALSE))))
}
# the published value is the stored value
pen <- subset(clinical_breakpoints, guideline == "EUCAST 2026" & type == "human" & method == "MIC" & ab == "PEN" & mo == "B_STRPT_GRPA")
expect_identical(unique(pen$breakpoint_S), 0.03)
# all notations of this dilution are S, the next dilution is not
expect_identical(sir(c(0.03, 0.031, 0.03125, 0.032), "Streptococcus pyogenes", "PEN"), rep("S", 4))
expect_identical(sir(0.064, "Streptococcus pyogenes", "PEN"), "R")
# the same for an R breakpoint, in the notation of the guideline and of the laboratory
expect_identical(mic_dilution_level(c(0.03, 0.032, 0.06, 0.064, 0.12, 0.125, 0.19, 3)), c(0.032, 0.032, 0.064, 0.064, 0.125, 0.125, 0.19, 3))
# the off-scale S breakpoint is stored as published, and never leads to S
cip <- subset(clinical_breakpoints, guideline == "EUCAST 2026" & type == "human" & method == "MIC" & ab == "CIP" & mo == "B_PSDMN" & is.na(site))
expect_identical(unique(cip$breakpoint_S), 0.001)
expect_identical(sir(c(0.0005, 0.001, 0.25), "Pseudomonas aeruginosa", "CIP"), c("I", "I", "I"))
# the log shows the published breakpoint
sir_interpretation_history(clean = TRUE)
sir(0.032, "Streptococcus pyogenes", "PEN")
expect_identical(sir_interpretation_history(clean = TRUE)$breakpoint_S_R, "0.03-0.03")
})
test_that("Morganella is interpreted as reported, not as M. morganii (#330)", {
skip_on_cran()
cb <- as.data.frame(clinical_breakpoints, stringsAsFactors = FALSE)
cb <- cb[cb$type == "human" & cb$guideline %like% "EUCAST", , drop = FALSE]
cb[] <- lapply(cb, function(x) if (is.numeric(x) || is.logical(x)) x else as.character(x))
order_code <- "B_[ORD]_ENTRBCTR"
family_code <- "B_[FAM]_MORGNLLC"
genus_code <- "B_MRGNL"
species_code <- "B_MRGNL_MRGN"
key <- function(df) paste(df$guideline, df$ab, df$method)
sir <- function(mo, k) {
x <- cb[key(cb) == k & cb$mo %in% c(order_code, family_code, genus_code, species_code), , drop = FALSE]
bp <- unique(c(x$breakpoint_S, x$breakpoint_R))
bp <- bp[!is.na(bp)]
if (x$method[1] == "MIC") {
input <- as.mic(sort(unique(pmax(0.001, c(0.001, 512, bp / 2, bp, bp * 2)))))
} else {
input <- as.disk(sort(unique(pmin(50, c(6, 50, bp - 1, bp, bp + 1)))))
}
as.character(suppressMessages(suppressWarnings(
as.sir(input, mo = mo, ab = x$ab[1], guideline = x$guideline[1], uti = FALSE, info = FALSE)
)))
}
# EUCAST's exceptions for the genus are only for agents that it excludes for Morganella as a whole
genus_rows <- cb[cb$mo == genus_code, , drop = FALSE]
expect_true(all(genus_rows$ab == "IMR"))
expect_true(all(is.na(genus_rows$breakpoint_S) & is.na(genus_rows$breakpoint_R)))
# the exceptions for M. morganii itself do not apply to the genus, which follows Enterobacterales
species_only <- setdiff(key(cb[cb$mo == species_code, ]), key(cb[cb$mo %in% c(family_code, genus_code), ]))
expect_true(length(species_only) > 0)
for (k in species_only) {
expect_identical(sir(genus_code, k), sir(order_code, k), info = k)
expect_false(identical(sir(species_code, k), sir(order_code, k)), info = k)
}
# the exceptions for the family do apply to the genus, as to any other member of the family
family_only <- setdiff(key(cb[cb$mo == family_code, ]), key(cb[cb$mo %in% c(species_code, genus_code), ]))
expect_true(length(family_only) > 0)
for (k in family_only) {
expect_identical(sir(genus_code, k), sir(family_code, k), info = k)
expect_identical(sir("Providencia stuartii", k), sir(family_code, k), info = k)
}
# a current example: imipenem has its own breakpoints for Morganellaceae, including Morganella
expect_identical(as.character(suppressMessages(as.sir(as.mic(2), mo = "Morganella", ab = "IPM", guideline = "EUCAST 2026", info = FALSE))), "I")
expect_identical(as.character(suppressMessages(as.sir(as.mic(2), mo = "Klebsiella oxytoca", ab = "IPM", guideline = "EUCAST 2026", info = FALSE))), "S")
})
test_that("EUCAST blocking rows prevent falling back to broader breakpoints", {
skip_on_cran()
sir <- function(x, mo, ab, guideline, include_screening = FALSE, uti = NA) {
sir <- function(x, mo, ab, guideline, include_screening = NULL, uti = NA) {
as.character(suppressMessages(suppressWarnings(
as.sir(x, mo = mo, ab = ab, guideline = guideline, include_screening = include_screening, uti = uti)
)))
@@ -648,6 +870,11 @@ test_that("EUCAST blocking rows prevent falling back to broader breakpoints", {
# IE for V. fluvialis, while Vibrio spp. has breakpoints
expect_identical(sir(as.mic(0.125), "Vibrio fluvialis", "CTX", "EUCAST 2026"), NA_character_)
expect_identical(sir(as.mic(0.125), "Vibrio cholerae", "CTX", "EUCAST 2026"), "S")
# breakpoints of Vibrio are for 5 species only, so not for other species or for the genus, which can only have PK/PD
expect_identical(sir(as.mic(0.125), "Vibrio parahaemolyticus", "CIP", "EUCAST 2026"), "S")
expect_identical(sir(as.mic(0.125), "Vibrio harveyi", "CIP", "EUCAST 2026"), NA_character_)
expect_identical(sir(as.mic(0.125), "Vibrio", "CIP", "EUCAST 2026"), NA_character_)
expect_identical(sir(as.mic(0.125), "Vibrio harveyi", "CIP", "EUCAST 2023"), "S")
# fosfomycin zone diameter breakpoints apply to E. coli only
expect_identical(sir(as.disk(25), "Klebsiella pneumoniae", "FOS", "EUCAST 2019"), NA_character_)
expect_identical(sir(as.disk(25), "Escherichia coli", "FOS", "EUCAST 2019"), "S")
@@ -665,7 +892,7 @@ test_that("EUCAST blocking rows prevent falling back to broader breakpoints", {
# H. influenzae MIC breakpoints apply to H. parainfluenzae, zone diameters do not
expect_identical(sir(as.mic(0.5), "Haemophilus parainfluenzae", "CIP", "EUCAST 2026"), "R")
expect_identical(sir(as.disk(30), "Haemophilus parainfluenzae", "CIP", "EUCAST 2026"), NA_character_)
# cefoxitin screen: CoNS not identified to species level use S >= 25 mm
# cefoxitin screen: CoNS not identified to species level use S >= 25 mm, also with the regular agent if allowed (#328)
expect_identical(sir(as.disk(23), "B_STPHY_CONS", "FOX", "EUCAST 2026", include_screening = TRUE), "R")
expect_identical(sir(as.disk(23), "Staphylococcus hominis", "FOX", "EUCAST 2026", include_screening = TRUE), "S")
expect_identical(sir(as.disk(26), "Staphylococcus epidermidis", "FOX", "EUCAST 2026", include_screening = TRUE), "R")
@@ -676,12 +903,27 @@ test_that("EUCAST blocking rows prevent falling back to broader breakpoints", {
expect_identical(sir(as.mic(0.0005), "Pseudomonas aeruginosa", "CIP", "EUCAST 2026"), "I")
# EUCAST's 0.06 mg/L is the dilution 0.0625, i.e. 0.064 in this package
expect_identical(sir(as.mic(0.064), "Haemophilus influenzae", "LVX", "EUCAST 2026"), "S")
# high-level gentamicin resistance (screening test given in the notes)
# high-level gentamicin resistance (screening test given in the notes), under both codes (#328)
expect_identical(sir(as.mic(256), "Enterococcus faecium", "GEH", "EUCAST 2026"), "R")
# breakpoints in brackets for systemic infections are not replaced by the UTI breakpoint if uti is unknown
expect_identical(sir(as.mic(4), "Acinetobacter baumannii", "AMK", "EUCAST 2026"), NA_character_)
expect_identical(sir(as.mic(256), "Enterococcus faecium", "GEN-S", "EUCAST 2026"), "R")
# breakpoints in brackets are not in the data set (#327), so a UTI breakpoint is used if uti is unknown and nothing else is available, which is noted every time
sir_interpretation_history(clean = TRUE)
expect_identical(sir(as.mic(4), "Acinetobacter baumannii", "AMK", "EUCAST 2026"), "S")
sir_history <- sir_interpretation_history(clean = TRUE)
expect_match(sir_history$notes, "only available for (uncomplicated) urinary tract infections", fixed = TRUE)
expect_identical(sir(as.mic(4), "Acinetobacter baumannii", "AMK", "EUCAST 2026", uti = FALSE), NA_character_)
expect_identical(sir(as.mic(4), "Acinetobacter baumannii", "AMK", "EUCAST 2026", uti = TRUE), "S")
# without a breakpoint in brackets, PK-PD breakpoints apply if EUCAST has these, as in EUCAST 2023 for aminoglycosides
sir_interpretation_history(clean = TRUE)
expect_identical(sir(as.mic(0.5), "Escherichia coli", "AMK", "EUCAST 2023", uti = FALSE), "S")
sir_history <- sir_interpretation_history(clean = TRUE)
expect_match(sir_history$ref_table, "PK PD", fixed = TRUE)
# and the breakpoints of a broader taxon for another route, of which the site is noted
sir_interpretation_history(clean = TRUE)
expect_identical(sir(as.mic(4), "Enterococcus faecalis", "AMX", "EUCAST 2026", uti = FALSE), "S")
expect_identical(sir_interpretation_history(clean = TRUE)$site, "Intravenous")
# an organism that a table excludes stays excluded, also if EUCAST has breakpoints in brackets for it
expect_identical(sir(as.mic(1), "Bacillus anthracis", "VAN", "EUCAST 2026"), NA_character_)
# UTI breakpoints are only used for unknown uti if there are no non-UTI breakpoints, which is noted every time
for (i in 1:2) {
sir_interpretation_history(clean = TRUE)