1
0
mirror of https://github.com/msberends/AMR.git synced 2026-04-01 00:16:05 +02:00

21 Commits

Author SHA1 Message Date
Claude
9f73571832 Replace all "in \funcname()\:" with {.help [{.fun funcname}](AMR::funcname)}
Converts all "in `funcname()`:" prefixes in warning_()/message_()/stop_()
calls to the full {.help} link format for clickable help in supported
terminals. Also fixes adjacent backtick argument names to {.arg}.

Files changed: ab.R, ab_property.R, av.R, av_property.R, antibiogram.R,
key_antimicrobials.R, mdro.R, mic.R, mo.R, plotting.R

https://claude.ai/code/session_01XHWLohiSTdZvCutwD7ag2b
2026-03-20 14:30:26 +00:00
d28671c34d fixes 2026-03-20 15:17:34 +01:00
Claude
51f689b069 Pre-evaluate inline expressions, add format_inline_(), fix print.ab
- All bare {variable}/{expression} in message_()/warning_()/stop_() calls
  are now pre-evaluated via paste0(), so users without cli/glue never see
  raw template syntax (mo_source.R, first_isolate.R, join_microorganisms.R,
  antibiogram.R, atc_online.R)
- Add format_inline_() helper: formats a cli-markup string and returns it
  (not emits it), using cli::format_inline() when available and cli_to_plain()
  otherwise
- Rewrite .onAttach to use format_inline_() for all packageStartupMessage
  calls; also adds {.topic} link and {.code} markup for option names
- print.ab: pre-evaluate function_name via paste0 (no .envir needed),
  apply highlight_code() to each example bullet for R syntax highlighting
- join_microorganisms: pre-evaluate {type} and {nrow(...)} expressions

https://claude.ai/code/session_01XHWLohiSTdZvCutwD7ag2b
2026-03-19 10:39:26 +00:00
Claude
1dabd4df3d Replace bare backticks with cli inline markup across all messaging calls
- {.arg} for argument names in stop_/warning_/message_ calls
- {.cls} after "of class" text in format_class() and elsewhere
- {.fun} for function names (replaces `fn()` pattern)
- {.pkg} for tidyverse package names (dplyr, ggplot2)
- {.code} for code literals (TRUE, FALSE, expressions)
- Rewrite print.ab: use cli named-vector with * bullets and code
  highlighting when cli >= 3.0.0; keep plain-text fallback otherwise
- Fix typo in as.sir(): "of must be" -> "or must be"
- switch sir.R verbose notes from message() to message_()

https://claude.ai/code/session_01XHWLohiSTdZvCutwD7ag2b
2026-03-19 08:35:26 +00:00
Claude
5173009625 Limit push trigger to main in code-coverage workflow
Same fix as check-recent: push: branches: '**' caused the workflow to
run twice per PR commit (once for push, once for pull_request). Restricting
push to [main] ensures coverage runs only once per PR update.

https://claude.ai/code/session_01XHWLohiSTdZvCutwD7ag2b
2026-03-19 07:42:42 +00:00
Claude
80e267f0d1 Limit push trigger to main in check-recent workflow
push: branches: '**' caused both the push event (9-worker matrix) and
the pull_request event (1-worker matrix) to fire simultaneously on every
PR commit. Restricting push to [main] means PR pushes only trigger the
pull_request path (1 worker), while direct pushes to main still get the
full 9-worker matrix.

https://claude.ai/code/session_01XHWLohiSTdZvCutwD7ag2b
2026-03-19 07:40:09 +00:00
Claude
05d3ca941f Replace glue-style dynamic markup with paste0() construction
{.field {variable}} and {.cls {variable}} patterns rely on glue
evaluation which is not safe in a zero-dependency package. Replace
all four occurrences with paste0("{.field ", var, "}") so the value
is baked into the markup string before reaching message_()/stop_().

https://claude.ai/code/session_01XHWLohiSTdZvCutwD7ag2b
2026-03-19 07:29:04 +00:00
Claude
ec310ed76b Apply {.topic}, {.cls}, and {.field} markup in sir.R messaging
- 'clinical_breakpoints' (dataset): {.code} -> {.topic [clinical_breakpoints](AMR::clinical_breakpoints)}
- "is of class" context: extract bad_col/bad_cls/exp_cls vars and use {.cls} + {.field} in glue syntax
- Column references in as.sir() messages: font_bold(col) with surrounding quotes -> {.field {col}}

https://claude.ai/code/session_01XHWLohiSTdZvCutwD7ag2b
2026-03-19 07:24:09 +00:00
Claude
3e4983ff93 Replace single-quoted literals in messaging calls with cli markup
Converted bare 'value' strings inside stop_(), warning_(), message_()
to appropriate cli markup:
- {.val}: option values ('drug', 'dose', 'administration', 'SDD', 'logbook')
- {.cls}: class names ('sir', 'mo')
- {.field}: column names ('mo' in mo_source)
- {.code}: object/dataset names ('clinical_breakpoints')

Files changed: ab_from_text.R, av_from_text.R, sir.R, sir_calc.R, mo_source.R

https://claude.ai/code/session_01XHWLohiSTdZvCutwD7ag2b
2026-03-18 23:36:53 +00:00
Claude
7218812c99 Update NEWS.md to continuous log + add concise style rules to CLAUDE.md
NEWS.md is now a single continuous log under one heading per dev series,
not a new section per version bump. CLAUDE.md documents: only replace
line 1 (heading), append new entries, keep them extremely concise with
no trailing full stop.

Merged 9035 and 9036 entries into one section; condensed verbose 9036
bullets; added CI workflow change entry.

https://claude.ai/code/session_01XHWLohiSTdZvCutwD7ag2b
2026-03-18 23:23:20 +00:00
Claude
eae14d44bf Restrict dev-versions and old-tinytest CI to main branch only
Both workflows were triggering on every push to every branch.
Narrowed push trigger to [main] so they only run after merging,
not on every feature/PR branch push.

https://claude.ai/code/session_01XHWLohiSTdZvCutwD7ag2b
2026-03-18 23:09:02 +00:00
Claude
11c175ae19 Slim CI matrix for PRs to ubuntu-latest / r-release only
For pull requests, check-recent now runs a single job (ubuntu-latest,
r-release) via a setup job that emits the matrix as JSON. On push and
schedule the full matrix is unchanged (devel + release on all OSes,
oldrel-1 through oldrel-4).

Also removed the pull_request trigger from check-recent-dev-pkgs; the
dev-packages check only needs to run on push/schedule.

https://claude.ai/code/session_01XHWLohiSTdZvCutwD7ag2b
2026-03-18 23:06:36 +00:00
Claude
ec3b12b937 Fix regexec() calls: remove perl=TRUE unsupported in older R
regexec() only gained the perl argument in R 4.1.0. The CI matrix
covers oldrel-1 through oldrel-4 (R 3.x/4.0.x), so perl=TRUE caused
an 'unused argument' error on every message_() call in those
environments.

All four affected regexec() calls use POSIX-extended compatible
patterns, so dropping perl=TRUE is safe.

https://claude.ai/code/session_01XHWLohiSTdZvCutwD7ag2b
2026-03-18 22:56:44 +00:00
Claude
5ecbc9001e Fix {.topic} to use required pkg::topic format with display text
{.topic} in cli requires a package-qualified topic reference to generate
a valid x-r-help:pkg::topic URI. Bare {.topic AMR-options} produced a
malformed x-r-help:AMR-options URI (no package prefix).

Use the [display_text](pkg::topic) form throughout:
  {.topic [AMR-options](AMR::AMR-options)}
  {.topic [AMR-deprecated](AMR::AMR-deprecated)}

The hyphen in the topic name is fine as a URI string even though
AMR::AMR-options is not a valid R symbol expression.

The fallback handler in format_message() already handles the [text](uri)
form by extracting the display text, so plain-text output is unchanged.

https://claude.ai/code/session_01XHWLohiSTdZvCutwD7ag2b
2026-03-18 22:47:38 +00:00
Claude
8760c6d85a Add {.topic} markup for non-function help page references
Replace {.code ?AMR-options} and backtick-style ?AMR-options / ?AMR-deprecated
references with proper {.topic AMR-options} / {.topic AMR-deprecated} cli markup
in count.R, interpretive_rules.R, proportion.R, and zz_deprecated.R.

Add {.topic} fallback handler to format_message() in aa_helper_functions.R:
plain-text environments render {.topic foo} as ?foo, and the [text](topic)
link form extracts just the display text (same pattern as {.help}).

Also convert remaining backtick function/arg references in proportion.R to
{.help [{.fun ...}](AMR::...)}, {.arg}, and {.code} markup for consistency.

Note: zzz.R intentionally keeps the backtick form since its startup message
goes through packageStartupMessage() which bypasses our cli infrastructure.

https://claude.ai/code/session_01XHWLohiSTdZvCutwD7ag2b
2026-03-18 22:41:43 +00:00
Claude
3928a3de55 Fix {.help} markup to use correct cli link format [{.fun fn}](AMR::fn)
Replace all instances of {.help AMR::fn}() (incorrect format with manual
parentheses outside the link) with {.help [{.fun fn}](AMR::fn)} which is
the correct cli hyperlink syntax: the display text [{.fun fn}] renders the
function name with parentheses automatically, and (AMR::fn) is the link target.

Also update the plain-text fallback handler in aa_helper_functions.R to
extract the display text from the [text](topic) markdown link format,
so that non-cli environments show just the function name (e.g. `fn()`),
not the raw link markup.

Dynamic cases in amr_selectors.R and mo_property.R also updated.

https://claude.ai/code/session_01XHWLohiSTdZvCutwD7ag2b
2026-03-18 22:37:46 +00:00
Claude
10c00ff606 Implement cli::code_highlight() for R code examples in messages (issue #191)
Add highlight_code() helper that wraps cli::code_highlight() when cli >= 3.0.0
is available, falling back to plain code otherwise. Apply it to all inline
R code examples embedded in message/warning/stop strings across the package.

Also convert remaining backtick-quoted function and argument references in
messaging calls to proper cli markup: {.help AMR::fn}(), {.arg arg},
{.code expr}, and {.pkg pkg} throughout ab.R, ab_from_text.R, av_from_text.R,
amr_selectors.R, count.R, custom_antimicrobials.R, custom_microorganisms.R,
interpretive_rules.R, mo.R, mo_property.R, sir.R, sir_calc.R.

Fixes #191

https://claude.ai/code/session_01XHWLohiSTdZvCutwD7ag2b
2026-03-18 22:23:39 +00:00
Claude
b7edf3e548 Require cli >= 3.0.0 for cli_inform/cli_warn/cli_abort availability checks
cli_inform, cli_warn, and cli_abort were introduced in cli 3.0.0.
Add min_version = "3.0.0" (as character) to all four pkg_is_available("cli")
checks so older cli versions fall back to base R messaging.

https://claude.ai/code/session_01XHWLohiSTdZvCutwD7ag2b
2026-03-18 22:14:30 +00:00
Claude
0cc154257a Qualify all {.help} tags with AMR:: and convert backtick ?func references
- Add AMR:: namespace prefix and trailing () to all {.help} cli markup
  so they render as clickable help links (e.g. {.help AMR::as.sir}())
- Convert `?funcname` backtick-quoted help references to {.help AMR::funcname}()
  in aa_helper_functions.R, custom_eucast_rules.R, interpretive_rules.R,
  key_antimicrobials.R, mo.R, plotting.R, resistance_predict.R, and sir.R
- Skipped `?proportion` in sir_calc.R as 'proportion' is not exported

https://claude.ai/code/session_01XHWLohiSTdZvCutwD7ag2b
2026-03-18 20:06:52 +00:00
Claude
4798d2c55e Replace {.fun} with {.help} for all exported functions in messaging
All function names referenced via {.fun …} in cli-style messages are
exported in NAMESPACE, so {.help …} is the appropriate markup — it
renders as a clickable help link rather than plain function styling.

https://claude.ai/code/session_01XHWLohiSTdZvCutwD7ag2b
2026-03-18 16:06:30 +00:00
Claude
ad31fba556 Modernise messaging infrastructure with cli support
Rewrites message_(), warning_(), stop_() to use cli::cli_inform(),
cli::cli_warn(), and cli::cli_abort() when the cli package is available,
with a fully functional plain-text fallback for environments without cli.

Key changes:
- New cli_to_plain() helper converts cli inline markup ({.fun}, {.arg},
  {.val}, {.field}, {.cls}, {.pkg}, {.href}, {.url}, etc.) to readable
  plain-text equivalents for the non-cli fallback path
- word_wrap() simplified: drops add_fn, ANSI re-index algorithm, RStudio
  link injection, and operator spacing hack; returns pasted input unchanged
  when cli is available
- stop_() no longer references AMR_env$cli_abort; uses pkg_is_available()
  directly; passes sys.call() objects to cli::cli_abort() call= argument
- Removed add_fn parameter from message_(), warning_(), and word_wrap()
- All call sites across R/ updated: add_fn arguments removed, some paste0-
  based string construction converted to cli glue syntax ({.fun as.mo},
  {.arg col_mo}, {n} results, etc.)
- cli already listed in Suggests; no DESCRIPTION dependency changes needed

https://claude.ai/code/session_01XHWLohiSTdZvCutwD7ag2b
2026-03-18 12:10:17 +00:00
60 changed files with 534 additions and 6241 deletions

View File

@@ -1,6 +1,6 @@
Package: AMR
Version: 3.0.1.9041
Date: 2026-03-30
Version: 3.0.1.9039
Date: 2026-03-19
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
@@ -63,8 +63,7 @@ Suggests:
tidyselect,
tinytest,
vctrs,
xml2,
usethis
xml2
VignetteBuilder: knitr,rmarkdown
URL: https://amr-for-r.org, https://github.com/msberends/AMR
BugReports: https://github.com/msberends/AMR/issues

14
NEWS.md
View File

@@ -1,7 +1,6 @@
# AMR 3.0.1.9041
# AMR 3.0.1.9039
### New
* Support for clinical breakpoints of 2026 of both CLSI and EUCAST, by adding all of their over 5,700 new clinical breakpoints to the `clinical_breakpoints` data set for usage in `as.sir()`. EUCAST 2026 is now the new default guideline for all MIC and disk diffusion interpretations.
* Integration with the **tidymodels** framework to allow seamless use of SIR, MIC and disk data in modelling pipelines via `recipes`
- `step_mic_log2()` to transform `<mic>` columns with log2, and `step_sir_numeric()` to convert `<sir>` columns to numeric
- New `tidyselect` helpers:
@@ -24,7 +23,6 @@
* Fixed a bug in `as.ab()` where certain AB codes containing "PH" or "TH" (such as `ETH`, `MTH`, `PHE`, `PHN`, `STH`, `THA`, `THI1`) would incorrectly return `NA` when combined in a vector with any untranslatable value (#245)
* Fixed a bug in `antibiogram()` for when no antimicrobials are set
* Fixed a bug in `as.sir()` where for numeric input the arguments `S`, `I`, and `R` would not be considered (#244)
* Fixed a bug in plotting MIC values when `keep_operators = "all"`
* Fixed some foreign translations of antimicrobial drugs
* Fixed a bug for printing column names to the console when using `mutate_at(vars(...), as.mic)` (#249)
* Fixed a bug to disregard `NI` for susceptibility proportion functions
@@ -32,7 +30,10 @@
* Fixed SIR and MIC coercion of combined values, e.g. `as.sir("<= 0.002; S") ` or `as.mic("S; 0.002")` (#252)
### Updates
* Extensive `cli` integration for better message handling and clickable links in messages and warnings (#191, #265)
* Replaced all bare backtick-quoted text in `message_()`, `warning_()`, and `stop_()` calls with proper cli inline markup (`{.arg}`, `{.cls}`, `{.fun}`, `{.pkg}`, `{.code}`); rewrote `print.ab` to use a cli named-vector with `*` bullets and code highlighting when cli is available
* Added `format_inline_()` helper that formats a cli-markup string and returns it (rather than emitting it), using `cli::format_inline()` when available and `cli_to_plain()` otherwise; used this in `.onAttach` to replace the duplicated cli/non-cli startup message pattern
* All inline `{variable}` / `{expression}` in messaging calls are now pre-evaluated via `paste0()`, so users without cli or glue never see raw template syntax
* All `"in `funcname()`:"` patterns in `warning_()`/`message_()`/`stop_()` replaced with `{.help [{.fun funcname}](AMR::funcname)}` for clickable help links
* `mdro()` now infers resistance for a _missing_ base drug column from an _available_ corresponding drug+inhibitor combination showing resistance (e.g., piperacillin is absent but required, while piperacillin/tazobactam available and resistant). Can be set with the new argument `infer_from_combinations`, which defaults to `TRUE` (#209). Note that this can yield a higher MDRO detection (which is a good thing as it has become more reliable).
* `susceptibility()` and `resistance()` gained the argument `guideline`, which defaults to EUCAST, for interpreting the 'I' category correctly.
* Added to the `antimicrobials` data set: cefepime/taniborbactam (`FTA`), ceftibuten/avibactam (`CTA`), clorobiocin (`CLB`), kasugamycin (`KAS`), ostreogrycin (`OST`), taniborbactam (`TAN`), thiostrepton (`THS`), xeruborbactam (`XER`), and zorbamycin (`ZOR`)
@@ -47,6 +48,11 @@
* Removed the `"inverse"` option, which has now become redundant
* `ab_group()` now returns values consist with the AMR selectors (#246)
* Added two new `NA` objects, `NA_ab_` and `NA_mo_`, analogous to base R's `NA_character_` and `NA_integer_`, for use in pipelines that require typed missing values
* `message_()`, `warning_()`, `stop_()` now use `cli` markup when available, with plain-text fallback; removed `add_fn` parameter from `message_()`, `warning_()`, `word_wrap()`
* New internal `cli_to_plain()` converts `cli` markup to plain text for non-cli path
* All internal call sites updated to `cli` glue syntax
* CI dev-version and old-tinytest workflows now only run on `main` branch pushes
* Single-quoted literal values in messaging calls replaced with `{.val}`, `{.cls}`, `{.field}`, or `{.code}` markup throughout
# AMR 3.0.1

View File

@@ -253,9 +253,12 @@ search_type_in_df <- function(x, type, info = TRUE, add_col_prefix = TRUE) {
# WHONET support
found <- sort(colnames(x)[colnames_formatted %like_case% "^(specimen date|specimen_date|spec_date)"])
if (!inherits(pm_pull(x, found), c("Date", "POSIXct"))) {
stop_("Found column {.field ", font_bold(found), "} to be used as input for {.arg ", ifelse(add_col_prefix, "col_", ""), type,
"}, but this column contains no valid dates. Transform its values to valid dates first.",
call = FALSE
stop(
font_red(paste0(
"Found column '", font_bold(found), "' to be used as input for `", ifelse(add_col_prefix, "col_", ""), type,
"`, but this column contains no valid dates. Transform its values to valid dates first."
)),
call. = FALSE
)
}
} else if (any(vapply(FUN.VALUE = logical(1), x, function(x) inherits(x, c("Date", "POSIXct"))))) {
@@ -302,7 +305,7 @@ search_type_in_df <- function(x, type, info = TRUE, add_col_prefix = TRUE) {
# this column should contain logicals
if (!is.logical(x[, found, drop = TRUE])) {
message_(
"Column {.field ", font_bold(found), "} found as input for {.arg ", ifelse(add_col_prefix, "col_", ""), type,
"Column '", font_bold(found), "' found as input for {.arg ", ifelse(add_col_prefix, "col_", ""), type,
"}, but this column does not contain {.code TRUE}/{.code FALSE} values and was ignored."
)
found <- NULL
@@ -314,9 +317,9 @@ search_type_in_df <- function(x, type, info = TRUE, add_col_prefix = TRUE) {
if (!is.null(found) && isTRUE(info)) {
if (message_not_thrown_before("search_in_type", type)) {
msg <- paste0("Using column {.field ", font_bold(found), "} as input for {.arg ", ifelse(add_col_prefix, "col_", ""), type, "}.")
msg <- paste0("Using column '", font_bold(found), "' as input for `", ifelse(add_col_prefix, "col_", ""), type, "`.")
if (type %in% c("keyantibiotics", "keyantimicrobials", "specimen")) {
msg <- paste(msg, "Use {.arg ", paste0(ifelse(add_col_prefix, "col_", ""), type), "= FALSE} to prevent this.")
msg <- paste(msg, "Use", font_bold(paste0(ifelse(add_col_prefix, "col_", ""), type), "= FALSE"), "to prevent this.")
}
message_(msg)
}
@@ -380,6 +383,27 @@ pkg_is_available <- function(pkg, also_load = FALSE, min_version = NULL) {
isTRUE(out)
}
highlight_code <- function(code) {
if (pkg_is_available("cli", min_version = "3.0.0")) {
cli::code_highlight(code)
} else {
code
}
}
# Format a cli-markup string for output, with a plain-text fallback when cli is
# unavailable. Unlike message_() / warning_() / stop_(), this function returns
# the formatted string rather than emitting it, so it can be passed to any
# output function (e.g. packageStartupMessage()).
format_inline_ <- function(...) {
msg <- paste0(c(...), collapse = "")
if (pkg_is_available("cli", min_version = "3.0.0")) {
cli::format_inline(msg)
} else {
cli_to_plain(msg, envir = parent.frame())
}
}
import_fn <- function(name, pkg, error_on_fail = TRUE) {
if (isTRUE(error_on_fail)) {
stop_ifnot_installed(pkg)
@@ -405,30 +429,6 @@ import_fn <- function(name, pkg, error_on_fail = TRUE) {
)
}
highlight_code <- function(code) {
if (pkg_is_available("cli", min_version = "3.0.0")) {
cli::code_highlight(code)
} else {
code
}
}
# Format a cli-markup string for output, with a plain-text fallback when cli is
# unavailable. Unlike message_() / warning_() / stop_(), this function returns
# the formatted string rather than emitting it, so it can be passed to any
# output function (e.g. packageStartupMessage()).
format_inline_ <- function(...) {
msg <- paste0(c(...), collapse = "")
if (pkg_is_available("cli", min_version = "3.0.0")) {
if (!cli::ansi_has_hyperlink_support()) {
msg <- simplify_help_markup(msg)
}
cli::format_inline(msg)
} else {
cli_to_plain(msg, envir = parent.frame())
}
}
# Convert cli glue markup to plain text for the non-cli fallback path.
# Called by message_(), warning_(), and stop_() when cli is not available.
cli_to_plain <- function(msg, envir = parent.frame()) {
@@ -552,46 +552,15 @@ word_wrap <- function(...,
gsub("(\n| )+$", "", wrapped)
}
simplify_help_markup <- function(msg) {
# {.help [{.fun fn}](pkg::fn)} -> {.code fn()}
# {.help [display](topic)} -> {.code display}
msg <- gsub(
"\\{\\.help \\[\\{\\.fun ([^}]+)\\}\\]\\([^)]+\\)\\}",
"{.code \\1()}",
msg,
perl = TRUE
)
msg <- gsub(
"\\{\\.help \\[([^]]+)\\]\\([^)]+\\)\\}",
"{.code \\1}",
msg,
perl = TRUE
)
# {.topic [display](topic)} -> {.code ?display}
msg <- gsub(
"\\{\\.topic \\[([^]]+)\\]\\([^)]+\\)\\}",
"{.code ?\\1}",
msg,
perl = TRUE
)
msg
}
message_ <- function(...,
appendLF = TRUE,
as_note = TRUE) {
if (pkg_is_available("cli", min_version = "3.0.0")) {
msg <- paste0(c(...), collapse = "")
if (!cli::ansi_has_hyperlink_support()) {
msg <- simplify_help_markup(msg)
}
if (isTRUE(as_note)) {
cli::cli_inform(c("i" = msg), .envir = parent.frame())
} else if (isTRUE(appendLF)) {
cli::cli_inform(msg, .envir = parent.frame())
} else {
# This mirrors what rlang::inform() does internally (cat() to stderr), so it behaves consistently with cli_inform() output
cat(format_inline_(msg), file = stderr())
cli::cli_inform(msg, .envir = parent.frame())
}
} else {
plain_msg <- cli_to_plain(paste0(c(...), collapse = ""), envir = parent.frame())
@@ -604,9 +573,6 @@ warning_ <- function(...,
call = FALSE) {
if (pkg_is_available("cli", min_version = "3.0.0")) {
msg <- paste0(c(...), collapse = "")
if (!cli::ansi_has_hyperlink_support()) {
msg <- simplify_help_markup(msg)
}
cli::cli_warn(msg, .envir = parent.frame())
} else {
plain_msg <- cli_to_plain(paste0(c(...), collapse = ""), envir = parent.frame())
@@ -619,9 +585,6 @@ warning_ <- function(...,
# - wraps text to never break lines within words (plain-text fallback)
stop_ <- function(..., call = TRUE) {
msg <- paste0(c(...), collapse = "")
if (!cli::ansi_has_hyperlink_support()) {
msg <- simplify_help_markup(msg)
}
if (pkg_is_available("cli", min_version = "3.0.0")) {
if (isTRUE(call)) {
call_obj <- sys.call(-1)
@@ -1098,7 +1061,7 @@ get_current_data <- function(arg_name, call) {
} else {
examples <- ""
}
stop_("this function must be used inside a {.pkg dplyr} verb or {.cls data.frame} call",
stop_("this function must be used inside a {.pkg dplyr} verb or {.code data.frame} call",
examples,
call = call
)

30
R/ab.R
View File

@@ -484,7 +484,7 @@ as.ab <- function(x, flag_multiple_results = TRUE, language = get_AMR_locale(),
}
message_(
"Antimicrobial translation was uncertain for ", examples,
". If required, use {.help [{.fun add_custom_antimicrobials}](AMR::add_custom_antimicrobials)} to add custom entries."
". If required, use `add_custom_antimicrobials()` to add custom entries."
)
}
}
@@ -529,7 +529,7 @@ NA_ab_ <- set_clean_class(NA_character_,
#' @rawNamespace if(getRversion() >= "3.0.0") S3method(pillar::pillar_shaft, ab)
pillar_shaft.ab <- function(x, ...) {
out <- trimws(format(x))
out[is.na(x)] <- pillar::style_na(NA)
out[is.na(x)] <- font_na(NA)
# add the names to the drugs as mouse-over!
if (in_rstudio()) {
@@ -556,25 +556,25 @@ print.ab <- function(x, ...) {
function_name <- attributes(x)$amr_selector
if (pkg_is_available("cli", min_version = "3.0.0")) {
cli::cli_inform(c(
"i" = paste0("This {.cls ab} vector was retrieved using {.fun ", function_name, "}, which should normally be used inside a {.pkg dplyr} verb or {.cls data.frame} call, e.g.:"),
paste0("\u00a0\u00a0", AMR_env$bullet_icon, " ", highlight_code(paste0("your_data %>% select(", function_name, "())"))),
paste0("\u00a0\u00a0", AMR_env$bullet_icon, " ", highlight_code(paste0("your_data %>% select(column_a, column_b, ", function_name, "())"))),
paste0("\u00a0\u00a0", AMR_env$bullet_icon, " ", highlight_code(paste0("your_data %>% filter(any(", function_name, "() == \"R\"))"))),
paste0("\u00a0\u00a0", AMR_env$bullet_icon, " ", highlight_code(paste0("your_data[, ", function_name, "()]"))),
paste0("\u00a0\u00a0", AMR_env$bullet_icon, " ", highlight_code(paste0("your_data[, c(\"column_a\", \"column_b\", ", function_name, "())]")))
"i" = paste0("This {.cls ab} vector was retrieved using {.fun ", function_name, "}, which should normally be used inside a {.pkg dplyr} verb or {.code data.frame} call, e.g.:"),
"*" = highlight_code(paste0("your_data %>% select(", function_name, "()")),
"*" = highlight_code(paste0("your_data %>% select(column_a, column_b, ", function_name, "()")),
"*" = highlight_code(paste0("your_data %>% filter(any(", function_name, "() == \"R\"))")),
"*" = highlight_code(paste0("your_data[, ", function_name, "()]")),
"*" = highlight_code(paste0("your_data[, c(\"column_a\", \"column_b\", ", function_name, "())]"))
))
} else {
message(word_wrap(paste0(
"This 'ab' vector was retrieved using `", function_name, "()`, which should normally be used inside a dplyr verb or data.frame call, e.g.:\n",
"\u00a0\u00a0", AMR_env$bullet_icon, " your_data %>% select(", function_name, "())\n",
"\u00a0\u00a0", AMR_env$bullet_icon, " your_data %>% select(column_a, column_b, ", function_name, "())\n",
"\u00a0\u00a0", AMR_env$bullet_icon, " your_data %>% filter(any(", function_name, "() == \"R\"))\n",
"\u00a0\u00a0", AMR_env$bullet_icon, " your_data[, ", function_name, "()]\n",
"\u00a0\u00a0", AMR_env$bullet_icon, " your_data[, c(\"column_a\", \"column_b\", ", function_name, "())]"
" ", AMR_env$bullet_icon, " your_data %>% select(", function_name, "())\n",
" ", AMR_env$bullet_icon, " your_data %>% select(column_a, column_b, ", function_name, "())\n",
" ", AMR_env$bullet_icon, " your_data %>% filter(any(", function_name, "() == \"R\"))\n",
" ", AMR_env$bullet_icon, " your_data[, ", function_name, "()]\n",
" ", AMR_env$bullet_icon, " your_data[, c(\"column_a\", \"column_b\", ", function_name, "())]"
), as_note = TRUE))
}
}
cat(format_inline_("Class {.cls ab}\n"))
cat("Class 'ab'\n")
print(as.character(x), quote = FALSE)
}
@@ -718,7 +718,7 @@ get_translate_ab <- function(translate_ab) {
} else {
translate_ab <- tolower(translate_ab)
stop_ifnot(translate_ab %in% colnames(AMR::antimicrobials),
"invalid value for {.arg translate_ab}, this must be a column name of the {.help [antimicrobials](AMR::antimicrobials)} data set\n",
"invalid value for {.arg translate_ab}, this must be a column name of the {.topic [antimicrobials](AMR::antimicrobials)} data set\n",
"or {.code TRUE} (equals {.val name}) or {.code FALSE} to not translate at all.",
call = FALSE
)

View File

@@ -678,7 +678,7 @@ not_intrinsic_resistant <- function(only_sir_columns = FALSE, col_mo = NULL, ver
agents <- ab_in_data[ab_in_data %in% names(vars_df_R[which(vars_df_R)])]
if (length(agents) > 0 &&
message_not_thrown_before("not_intrinsic_resistant", sort(agents))) {
agents_formatted <- paste0("{.field ", font_bold(agents, collapse = NULL), "}")
agents_formatted <- paste0("'", font_bold(agents, collapse = NULL), "'")
agents_names <- ab_name(names(agents), tolower = TRUE, language = NULL)
need_name <- generalise_antibiotic_name(agents) != generalise_antibiotic_name(agents_names)
agents_formatted[need_name] <- paste0(agents_formatted[need_name], " (", agents_names[need_name], ")")
@@ -722,7 +722,7 @@ amr_select_exec <- function(function_name,
if (any(untreatable %in% names(ab_in_data))) {
if (message_not_thrown_before(function_name, "amr_class", "untreatable")) {
warning_(
"in {.help [{.fun ", function_name, "}](AMR::", function_name, ")}: some drugs were ignored since they cannot be used for treatment: ",
"in `", function_name, "()`: some drugs were ignored since they cannot be used for treatment: ",
vector_and(
ab_name(names(ab_in_data)[names(ab_in_data) %in% untreatable],
language = NULL,
@@ -797,14 +797,14 @@ amr_select_exec <- function(function_name,
if (only_treatable == TRUE) {
if (message_not_thrown_before(function_name, "amr_class", "untreatable")) {
message_(
"in {.help [{.fun ", function_name, "}](AMR::", function_name, ")}: ",
"in `", function_name, "()`: ",
vector_and(
paste0(
ab_name(abx[abx %in% untreatable],
language = NULL,
tolower = TRUE
),
" ({.field ", font_bold(abx[abx %in% untreatable], collapse = NULL), "})"
" (`", abx[abx %in% untreatable], "`)"
),
quotes = FALSE,
sort = TRUE,
@@ -837,10 +837,10 @@ amr_select_exec <- function(function_name,
#' @export
#' @noRd
print.amr_selector <- function(x, ...) {
warning_("It should never be needed to print an antimicrobial selector class. Are you using {.pkg data.table}? Then add the argument {.arg with = FALSE}, see our examples at {.help [{.fun amr_selector}](AMR::amr_selector)}.",
warning_("It should never be needed to print an antimicrobial selector class. Are you using {.pkg data.table}? Then add the argument {.code with = FALSE}, see our examples at {.help [{.fun amr_selector}](AMR::amr_selector)}.",
immediate = TRUE
)
cat(format_inline_("Class {.cls amr_selector}\n"))
cat("Class 'amr_selector'\n")
print(as.character(x), quote = FALSE)
}
@@ -937,7 +937,7 @@ any.amr_selector_any_all <- function(..., na.rm = FALSE) {
if (length(e1) > 1) {
message_(
"Assuming a filter on ", type, " ", length(e1), " ", gsub("[\\(\\)]", "", fn_name),
". Wrap around {.fun all} or {.fun any} to prevent this note."
". Wrap around `all()` or `any()` to prevent this note."
)
}
}
@@ -962,7 +962,7 @@ any.amr_selector_any_all <- function(..., na.rm = FALSE) {
if (length(e1) > 1) {
message_(
"Assuming a filter on ", type, " ", length(e1), " ", gsub("[\\(\\)]", "", fn_name),
". Wrap around {.fun all} or {.fun any} to prevent this note."
". Wrap around `all()` or `any()` to prevent this note."
)
}
}
@@ -1071,12 +1071,12 @@ message_agent_names <- function(function_name, agents, ab_group = NULL, examples
message_("No antimicrobial drugs of class '", ab_group, "' found", examples, ".")
}
} else {
agents_formatted <- paste0("{.field ", font_bold(agents, collapse = NULL), "}")
agents_formatted <- paste0("'", font_bold(agents, collapse = NULL), "'")
agents_names <- ab_name(names(agents), tolower = TRUE, language = NULL)
need_name <- generalise_antibiotic_name(agents) != generalise_antibiotic_name(agents_names)
agents_formatted[need_name] <- paste0(agents_formatted[need_name], " (", agents_names[need_name], ")")
message_(
"For {.help [", function_name, "(",
"For `", function_name, "(",
ifelse(function_name == "amr_class",
paste0("\"", amr_class_args, "\""),
ifelse(!is.null(call),
@@ -1084,7 +1084,7 @@ message_agent_names <- function(function_name, agents, ab_group = NULL, examples
""
)
),
")](AMR::", function_name, ")} using ",
")` using ",
ifelse(length(agents) == 1, "column ", "columns "),
vector_and(agents_formatted, quotes = FALSE, sort = FALSE)
)

View File

@@ -180,7 +180,7 @@ atc_online_property <- function(atc_code,
colnames(out) <- gsub("^atc.*", "atc", tolower(colnames(out)))
if (length(out) == 0) {
message_("{.help [{.fun atc_online_property}](AMR::atc_online_property)}: no properties found for ATC ", atc_code[i], ". Please check {.href ", atc_url, " this WHOCC webpage}.")
message_("in {.help [{.fun atc_online_property}](AMR::atc_online_property)}: no properties found for ATC ", atc_code[i], ". Please check {.href ", atc_url, " this WHOCC webpage}.")
returnvalue[i] <- NA
next
}

6
R/av.R
View File

@@ -511,8 +511,8 @@ is.av <- function(x) {
#' @rawNamespace if(getRversion() >= "3.0.0") S3method(pillar::pillar_shaft, av)
pillar_shaft.av <- function(x, ...) {
out <- trimws(format(x))
out[!is.na(x)] <- gsub("+", pillar::style_subtle("+"), out[!is.na(x)], fixed = TRUE)
out[is.na(x)] <- pillar::style_na(NA)
out[!is.na(x)] <- gsub("+", font_subtle("+"), out[!is.na(x)], fixed = TRUE)
out[is.na(x)] <- font_na(NA)
create_pillar_column(out, align = "left", min_width = 4)
}
@@ -526,7 +526,7 @@ type_sum.av <- function(x, ...) {
#' @export
#' @noRd
print.av <- function(x, ...) {
cat(format_inline_("Class {.cls av}\n"))
cat("Class 'av'\n")
print(as.character(x), quote = FALSE)
}

View File

@@ -84,7 +84,7 @@ bug_drug_combinations <- function(x,
col_mo <- search_type_in_df(x = x, type = "mo")
stop_if(is.null(col_mo), "{.arg col_mo} must be set")
} else {
stop_ifnot(col_mo %in% colnames(x), "column {.field ", font_bold(col_mo), "} ({.arg col_mo}) not found")
stop_ifnot(col_mo %in% colnames(x), "column '", col_mo, "' ({.arg col_mo}) not found")
}
x.bak <- x

View File

@@ -166,5 +166,5 @@ clear_custom_antimicrobials <- function() {
n2 <- nrow(AMR_env$AB_lookup)
AMR_env$custom_ab_codes <- character(0)
AMR_env$ab_previously_coerced <- AMR_env$ab_previously_coerced[which(AMR_env$ab_previously_coerced$ab %in% AMR_env$AB_lookup$ab), , drop = FALSE]
message_("Cleared ", nr2char(n - n2), " custom record", ifelse(n - n2 > 1, "s", ""), " from the internal {.help [antimicrobials](AMR::antimicrobials)} data set.")
message_("Cleared ", nr2char(n - n2), " custom record", ifelse(n - n2 > 1, "s", ""), " from the internal {.topic [antimicrobials](AMR::antimicrobials)} data set.")
}

View File

@@ -235,9 +235,9 @@ print.custom_mdro_guideline <- function(x, ...) {
for (i in seq_len(length(x))) {
rule <- x[[i]]
rule$query <- format_custom_query_rule(rule$query)
cat("\u00a0\u00a0", i, ". ", font_bold("If "), font_blue(rule$query), font_bold(" then: "), font_red(rule$value), "\n", sep = "")
cat(" ", i, ". ", font_bold("If "), font_blue(rule$query), font_bold(" then: "), font_red(rule$value), "\n", sep = "")
}
cat("\u00a0\u00a0", i + 1, ". ", font_bold("Otherwise: "), font_red(paste0("Negative")), "\n", sep = "")
cat(" ", i + 1, ". ", font_bold("Otherwise: "), font_red(paste0("Negative")), "\n", sep = "")
cat("\nUnmatched rows will return ", font_red("NA"), ".\n", sep = "")
if (isTRUE(attributes(x)$as_factor)) {
cat("Results will be of class 'factor', with ordered levels: ", paste0(attributes(x)$values, collapse = " < "), "\n", sep = "")
@@ -260,7 +260,7 @@ run_custom_mdro_guideline <- function(df, guideline, info) {
)
if (identical(qry, "error")) {
warning_("in {.help [{.fun custom_mdro_guideline}](AMR::custom_mdro_guideline)}: rule ", i,
" ({.code ", as.character(guideline[[i]]$query), "}) was ignored because of this error message: ",
" (`", as.character(guideline[[i]]$query), "`) was ignored because of this error message: ",
AMR_env$err_msg,
call = FALSE
)

View File

@@ -128,7 +128,7 @@
#' }
add_custom_microorganisms <- function(x) {
meet_criteria(x, allow_class = "data.frame")
stop_ifnot("genus" %in% tolower(colnames(x)), "{.arg x} must contain column {.code genus}.")
stop_ifnot("genus" %in% tolower(colnames(x)), "{.arg x} must contain column 'genus'.")
add_MO_lookup_to_AMR_env()

View File

@@ -119,9 +119,9 @@ as.disk <- function(x, na.rm = FALSE) {
sort() %pm>%
vector_and(quotes = TRUE)
cur_col <- get_current_column()
warning_("in {.help [{.fun as.disk}](AMR::as.disk)}: ", na_after - na_before, " result",
warning_("in {.fun as.disk}: ", na_after - na_before, " result",
ifelse(na_after - na_before > 1, "s", ""),
ifelse(is.null(cur_col), "", paste0(" in column {.field ", font_bold(cur_col, collapse = NULL), "}")),
ifelse(is.null(cur_col), "", paste0(" in column '", cur_col, "'")),
" truncated (",
round(((na_after - na_before) / length(x)) * 100),
"%) that were invalid disk zones: ",
@@ -162,7 +162,7 @@ is.disk <- function(x) {
#' @rawNamespace if(getRversion() >= "3.0.0") S3method(pillar::pillar_shaft, disk)
pillar_shaft.disk <- function(x, ...) {
out <- trimws(format(x))
out[is.na(x)] <- pillar::style_na(NA)
out[is.na(x)] <- font_na(NA)
create_pillar_column(out, align = "right", width = 2)
}
@@ -170,7 +170,7 @@ pillar_shaft.disk <- function(x, ...) {
#' @export
#' @noRd
print.disk <- function(x, ...) {
cat(format_inline_("Class {.cls disk}\n"))
cat("Class 'disk'\n")
print(as.integer(x), quote = FALSE)
}

View File

@@ -333,7 +333,7 @@ first_isolate <- function(x = NULL,
check_columns_existance <- function(column, tblname = x) {
if (!is.null(column)) {
stop_ifnot(column %in% colnames(tblname),
"Column {.code ", column, "} not found.",
"Column '{column}' not found.",
call = FALSE
)
}
@@ -554,7 +554,7 @@ first_isolate <- function(x = NULL,
format(sum(x$newvar_mo == "UNKNOWN", na.rm = TRUE),
decimal.mark = decimal.mark, big.mark = big.mark
),
" isolates with a microbial ID 'UNKNOWN' (in column {.field ", font_bold(col_mo), "})"
" isolates with a microbial ID 'UNKNOWN' (in column '", font_bold(col_mo), "')"
)
}
x[which(x$newvar_mo == "UNKNOWN"), "newvar_first_isolate"] <- include_unknown
@@ -565,7 +565,7 @@ first_isolate <- function(x = NULL,
"Excluding ", format(sum(is.na(x$newvar_mo), na.rm = TRUE),
decimal.mark = decimal.mark, big.mark = big.mark
),
" isolates with a microbial ID `NA` (in column {.field ", font_bold(col_mo), "})"
" isolates with a microbial ID `NA` (in column '", font_bold(col_mo), "')"
)
}
x[which(is.na(x$newvar_mo)), "newvar_first_isolate"] <- FALSE

View File

@@ -86,7 +86,7 @@ guess_ab_col <- function(x = NULL, search_string = NULL, verbose = FALSE, only_s
} else {
if (isTRUE(verbose)) {
message_(
"Using column {.field ", font_bold(ab_result), "} as input for ", search_string,
"Using column '", font_bold(ab_result), "' as input for ", search_string,
" (", ab_name(search_string, language = NULL, tolower = TRUE), ")."
)
}
@@ -146,7 +146,7 @@ get_column_abx <- function(x,
meet_criteria(only_sir_columns, allow_class = "logical", has_length = 1)
meet_criteria(sort, allow_class = "logical", has_length = 1)
if (isTRUE(info) && message_not_thrown_before("get_column_abx", colnames(x))) {
if (isTRUE(info)) {
message_("Auto-guessing columns suitable for analysis", appendLF = FALSE, as_note = FALSE)
}
@@ -275,7 +275,7 @@ get_column_abx <- function(x,
for (i in seq_len(length(out))) {
if (isTRUE(verbose) && !out[i] %in% duplicates) {
message_(
"Using column {.field ", font_bold(out[i]), "} as input for ", names(out)[i],
"Using column '", font_bold(out[i]), "' as input for ", names(out)[i],
" (", ab_name(names(out)[i], tolower = TRUE, language = NULL), ")."
)
}
@@ -284,7 +284,7 @@ get_column_abx <- function(x,
if (names(out)[i] != already_set_as) {
message_(
paste0(
"Column {.field ", font_bold(out[i]), "} will not be used for ",
"Column '", font_bold(out[i]), "' will not be used for ",
names(out)[i], " (", suppressMessages(ab_name(names(out)[i], tolower = TRUE, language = NULL, fast_mode = TRUE)), ")",
", as this antimicrobial has already been set."
)

View File

@@ -329,7 +329,7 @@ interpretive_rules <- function(x,
if (!"AMP" %in% names(cols_ab) && "AMX" %in% names(cols_ab)) {
# ampicillin column is missing, but amoxicillin is available
if (isTRUE(info)) {
message_("Using column {.field ", font_bold(cols_ab[names(cols_ab) == "AMX"]), "} as input for ampicillin since many EUCAST rules depend on it.")
message_("Using column '", cols_ab[names(cols_ab) == "AMX"], "' as input for ampicillin since many EUCAST rules depend on it.")
}
cols_ab <- c(cols_ab, c(AMP = unname(cols_ab[names(cols_ab) == "AMX"])))
}
@@ -510,8 +510,8 @@ interpretive_rules <- function(x,
## Set base to R where base + enzyme inhibitor is R ----
rule_current <- paste0(
ab_enzyme$base_name[i], " ({.field ", font_bold(col_base), "}) = R if ",
tolower(ab_enzyme$enzyme_name[i]), " ({.field ", font_bold(col_enzyme), "}) = R"
ab_enzyme$base_name[i], " (`", col_base, "`) = R if ",
tolower(ab_enzyme$enzyme_name[i]), " (`", col_enzyme, "`) = R"
)
if (isTRUE(info)) {
cat(word_wrap(rule_current,
@@ -551,8 +551,8 @@ interpretive_rules <- function(x,
## Set base + enzyme inhibitor to S where base is S ----
rule_current <- paste0(
ab_enzyme$enzyme_name[i], " ({.field ", font_bold(col_enzyme), "}) = S if ",
tolower(ab_enzyme$base_name[i]), " ({.field ", font_bold(col_base), "}) = S"
ab_enzyme$enzyme_name[i], " (`", col_enzyme, "`) = S if ",
tolower(ab_enzyme$base_name[i]), " (`", col_base, "`) = S"
)
if (isTRUE(info)) {
@@ -662,9 +662,9 @@ interpretive_rules <- function(x,
if (ab %in% names(cols_ab) && !ab_s %in% names(cols_ab)) {
if (isTRUE(info)) {
message_(
"Using column {.field ", font_bold(cols_ab[names(cols_ab) == ab]),
"} as ", ab_name(ab_s, language = NULL, tolower = TRUE),
" since a column {.code ", ab_s, "} is missing but required for the chosen rules"
"Using column '", cols_ab[names(cols_ab) == ab],
"' as ", ab_name(ab_s, language = NULL, tolower = TRUE),
" since a column '", ab_s, "' is missing but required for the chosen rules"
)
}
cols_ab <- c(cols_ab, stats::setNames(unname(cols_ab[names(cols_ab) == ab]), ab_s))
@@ -806,7 +806,7 @@ interpretive_rules <- function(x,
")$"
)
} else if (like_is_one_of != "like") {
stop("invalid value for column {.field like.is.one_of}", call. = FALSE)
stop("invalid value for column 'like.is.one_of'", call. = FALSE)
}
if (is.na(source_antibiotics)) {

View File

@@ -476,7 +476,7 @@ mdro <- function(x = NULL,
if (!"AMP" %in% names(cols_ab) && "AMX" %in% names(cols_ab)) {
# ampicillin column is missing, but amoxicillin is available
if (isTRUE(info)) {
message_("Using column {.field ", font_bold(cols_ab[names(cols_ab) == "AMX"]), "} as input for ampicillin since many MDRO rules depend on it.")
message_("Using column '", cols_ab[names(cols_ab) == "AMX"], "' as input for ampicillin since many MDRO rules depend on it.")
}
cols_ab <- c(cols_ab, c(AMP = unname(cols_ab[names(cols_ab) == "AMX"])))
}

27
R/mic.R
View File

@@ -72,7 +72,7 @@ COMMON_MIC_VALUES <- c(
#' ```
#' x <- random_mic(10)
#' x
#' #> Class <mic>
#' #> Class 'mic'
#' #> [1] 16 1 8 8 64 >=128 0.0625 32 32 16
#'
#' is.factor(x)
@@ -89,7 +89,7 @@ COMMON_MIC_VALUES <- c(
#'
#' ```
#' x[x > 4]
#' #> Class <mic>
#' #> Class 'mic'
#' #> [1] 16 8 8 64 >=128 32 32 16
#'
#' df <- data.frame(x, hospital = "A")
@@ -174,7 +174,7 @@ as.mic <- function(x, na.rm = FALSE, keep_operators = "all", round_to_next_log2
keep_operators <- "none"
}
if (any(is.mic(x)) && (keep_operators == "all" || !any(x %like% "[>=<]", na.rm = TRUE))) {
if (is.mic(x) && (keep_operators == "all" || !any(x %like% "[>=<]", na.rm = TRUE))) {
if (isTRUE(round_to_next_log2)) {
x <- roundup_to_nearest_log2(x)
}
@@ -269,9 +269,9 @@ as.mic <- function(x, na.rm = FALSE, keep_operators = "all", round_to_next_log2
sort() %pm>%
vector_and(quotes = TRUE)
cur_col <- get_current_column()
warning_("in {.help [{.fun as.mic}](AMR::as.mic)}: ", na_after - na_before, " result",
warning_("in {.fun as.mic}: ", na_after - na_before, " result",
ifelse(na_after - na_before > 1, "s", ""),
ifelse(is.null(cur_col), "", paste0(" in column {.field ", font_bold(cur_col, collapse = NULL), "}")),
ifelse(is.null(cur_col), "", paste0(" in column '", cur_col, "'")),
" truncated (",
round(((na_after - na_before) / length(x)) * 100),
"%) that were invalid MICs: ",
@@ -322,12 +322,11 @@ NA_mic_ <- set_clean_class(factor(NA, levels = VALID_MIC_LEVELS, ordered = TRUE)
#' @export
rescale_mic <- function(x, mic_range, keep_operators = "edges", as.mic = TRUE, round_to_next_log2 = FALSE) {
meet_criteria(mic_range, allow_class = c("numeric", "integer", "logical", "mic"), has_length = 2, allow_NA = TRUE, allow_NULL = TRUE)
if (is.numeric(mic_range)) {
mic_range <- trimws(format(mic_range, scientific = FALSE))
mic_range <- gsub("[.]0+$", "", mic_range)
mic_range[mic_range == "NA"] <- NA_character_
} else if (any(is.mic(mic_range))) {
} else if (is.mic(mic_range)) {
mic_range <- as.character(mic_range)
}
stop_ifnot(
@@ -449,12 +448,16 @@ pillar_shaft.mic <- function(x, ...) {
crude_numbers <- as.double(x)
operators <- gsub("[^<=>]+", "", as.character(x))
# colourise operators
operators[!is.na(operators) & operators != ""] <- pillar::style_subtle(operators[!is.na(operators) & operators != ""])
operators[!is.na(operators) & operators != ""] <- font_silver(operators[!is.na(operators) & operators != ""], collapse = NULL)
out <- trimws(paste0(operators, trimws(format(crude_numbers))))
out[is.na(x)] <- pillar::style_na(NA)
out[is.na(x)] <- font_na(NA)
# make trailing zeroes less visible
out[out %like% "[.]"] <- gsub("([.]?0+)$", pillar::style_subtle("\\1"), out[out %like% "[.]"], perl = TRUE)
if (is_dark()) {
fn <- font_silver
} else {
fn <- font_white
}
out[out %like% "[.]"] <- gsub("([.]?0+)$", fn("\\1"), out[out %like% "[.]"], perl = TRUE)
create_pillar_column(out, align = "right", width = max(nchar(font_stripstyle(out))))
}
@@ -472,7 +475,7 @@ type_sum.mic <- function(x, ...) {
#' @export
#' @noRd
print.mic <- function(x, ...) {
cat(format_inline_("Class {.cls mic}"))
cat("Class 'mic'")
if (!identical(levels(x), VALID_MIC_LEVELS)) {
cat(font_red(" with an outdated or altered structure - convert with `as.mic()` to update"))
}

28
R/mo.R
View File

@@ -249,7 +249,7 @@ as.mo <- function(x,
if (length(which(ind)) > 0 && isTRUE(info) && message_not_thrown_before("as.mo_microorganisms.codes", is.na(out), toupper(x))) {
message_(
"Retrieved value", ifelse(sum(ind) > 1, "s", ""),
" from the {.help [microorganisms.codes](AMR::microorganisms.codes)} data set for ", vector_and(paste0("{.val ", toupper(x)[ind], "}"), quotes = FALSE), "."
" from the `microorganisms.codes` data set for ", vector_and(toupper(x)[ind]), "."
)
}
# From SNOMED ----
@@ -502,7 +502,7 @@ as.mo <- function(x,
)
if (any(out %in% AMR_env$MO_lookup$mo[match(post_Becker, AMR_env$MO_lookup$fullname)])) {
if (message_not_thrown_before("as.mo", "becker")) {
warning_("in {.help [{.fun as.mo}](AMR::as.mo)}: Becker ", font_italic("et al."), " (2014, 2019, 2020) does not contain these species named after their publication: ",
warning_("in {.fun as.mo}: Becker ", font_italic("et al."), " (2014, 2019, 2020) does not contain these species named after their publication: ",
vector_and(font_italic(gsub("Staphylococcus", "S.", post_Becker, fixed = TRUE), collapse = NULL), quotes = FALSE),
". Categorisation to CoNS/CoPS was taken from the original scientific publication(s).",
immediate = TRUE, call = FALSE
@@ -648,13 +648,13 @@ pillar_shaft.mo <- function(x, ...) {
add_MO_lookup_to_AMR_env()
out <- trimws(format(x))
# grey out the kingdom (part until first "_")
out[!is.na(x)] <- gsub("^([A-Z]+_)(.*)", paste0(pillar::style_subtle("\\1"), "\\2"), out[!is.na(x)], perl = TRUE)
out[!is.na(x)] <- gsub("^([A-Z]+_)(.*)", paste0(font_subtle("\\1"), "\\2"), out[!is.na(x)], perl = TRUE)
# and grey out every _
out[!is.na(x)] <- gsub("_", pillar::style_subtle("_"), out[!is.na(x)])
out[!is.na(x)] <- gsub("_", font_subtle("_"), out[!is.na(x)])
# markup NA and UNKNOWN
out[is.na(x)] <- pillar::style_na(" NA")
out[x == "UNKNOWN"] <- pillar::style_na(" UNKNOWN")
out[is.na(x)] <- font_na(" NA")
out[x == "UNKNOWN"] <- font_na(" UNKNOWN")
# markup manual codes
out[x %in% AMR_env$MO_lookup$mo & !x %in% AMR::microorganisms$mo] <- font_blue(out[x %in% AMR_env$MO_lookup$mo & !x %in% AMR::microorganisms$mo], collapse = NULL)
@@ -673,20 +673,20 @@ pillar_shaft.mo <- function(x, ...) {
(!is.null(df) && !all(unlist(df[, which(mo_cols), drop = FALSE]) %in% all_mos))) {
# markup old mo codes
out[!x %in% all_mos] <- font_italic(
pillar::style_na(x[!x %in% all_mos],
font_na(x[!x %in% all_mos],
collapse = NULL
),
collapse = NULL
)
# throw a warning with the affected column name(s)
if (!is.null(mo_cols)) {
col <- paste0("Column ", vector_or(paste0("{.field ", font_bold(colnames(df)[mo_cols], collapse = NULL), "}"), quotes = TRUE, sort = FALSE))
col <- paste0("Column ", vector_or(colnames(df)[mo_cols], quotes = TRUE, sort = FALSE))
} else {
col <- "The data"
}
warning_(
col, " contains old MO codes (from a previous AMR package version). ",
"Please update your MO codes with {.help [{.fun as.mo}](AMR::as.mo)}.",
"Please update your MO codes with `as.mo()`.",
call = FALSE
)
}
@@ -783,7 +783,7 @@ get_skimmers.mo <- function(column) {
#' @noRd
print.mo <- function(x, print.shortnames = FALSE, ...) {
add_MO_lookup_to_AMR_env()
cat(format_inline_("Class {.cls mo}\n"))
cat("Class 'mo'\n")
x_names <- names(x)
if (is.null(x_names) & print.shortnames == TRUE) {
x_names <- tryCatch(mo_shortname(x, ...), error = function(e) NULL)
@@ -793,7 +793,7 @@ print.mo <- function(x, print.shortnames = FALSE, ...) {
if (!all(x %in% c(AMR_env$MO_lookup$mo, NA))) {
warning_(
"Some MO codes are from a previous AMR package version. ",
"Please update the MO codes with {.help [{.fun as.mo}](AMR::as.mo)}.",
"Please update the MO codes with `as.mo()`.",
call = FALSE
)
}
@@ -827,7 +827,7 @@ as.data.frame.mo <- function(x, ...) {
if (!all(x %in% c(AMR_env$MO_lookup$mo, NA))) {
warning_(
"The data contains old MO codes (from a previous AMR package version). ",
"Please update your MO codes with {.help [{.fun as.mo}](AMR::as.mo)}."
"Please update your MO codes with `as.mo()`."
)
}
nm <- deparse1(substitute(x))
@@ -977,8 +977,8 @@ print.mo_uncertainties <- function(x, n = 10, ...) {
out <- paste0(
paste0(
"", strrep(font_grey("-"), times = getOption("width", 100) - 1), "\n",
"{.val ", x[i, ]$original_input, "}",
"", strrep(font_grey("-"), times = getOption("width", 100)), "\n",
'"', x[i, ]$original_input, '"',
" -> ",
paste0(
font_bold(italicise(x[i, ]$fullname)),

View File

@@ -270,6 +270,7 @@ mo_shortname <- function(x, language = get_AMR_locale(), keep_synonyms = getOpti
}
#' @rdname mo_property
#' @export
mo_subspecies <- function(x, language = get_AMR_locale(), keep_synonyms = getOption("AMR_keep_synonyms", FALSE), ...) {
@@ -1042,7 +1043,7 @@ find_mo_col <- function(fn) {
)
if (!is.null(df) && !is.null(mo) && is.data.frame(df)) {
if (message_not_thrown_before(fn = fn)) {
message_("Using column {.field ", font_bold(mo), "} as input for {.help [{.fun ", fn, "}](AMR::", fn, ")}")
message_("Using column '", font_bold(mo), "' as input for {.help [{.fun ", fn, "}](AMR::", fn, ")}")
}
return(df[, mo, drop = TRUE])
} else {

View File

@@ -75,7 +75,7 @@
#'
#' ```
#' as.mo("lab_mo_ecoli")
#' #> Class <mo>
#' #> Class 'mo'
#' #> [1] B_ESCHR_COLI
#'
#' mo_genus("lab_mo_kpneumoniae")
@@ -85,7 +85,7 @@
#' as.mo(c("Escherichia coli", "E. coli", "lab_mo_ecoli"))
#' #> NOTE: Translation to one microorganism was guessed with uncertainty.
#' #> Use mo_uncertainties() to review it.
#' #> Class <mo>
#' #> Class 'mo'
#' #> [1] B_ESCHR_COLI B_ESCHR_COLI B_ESCHR_COLI
#' ```
#'
@@ -108,7 +108,7 @@
#' #> NOTE: Updated mo_source file '/Users/me/mo_source.rds' (0.3 kB) from
#' #> '/Users/me/Documents/ourcodes.xlsx' (9 kB), columns
#' #> "Organisation XYZ" and "mo"
#' #> Class <mo>
#' #> Class 'mo'
#' #> [1] B_ESCHR_COLI
#'
#' mo_genus("lab_Staph_aureus")
@@ -289,7 +289,7 @@ check_validity_mo_source <- function(x, refer_to_name = "`reference_df`", stop_o
}
if (!"mo" %in% colnames(x)) {
if (stop_on_error == TRUE) {
stop_(refer_to_name, " must contain a column {.code mo}", call = FALSE)
stop_(refer_to_name, " must contain a column {.field mo}", call = FALSE)
} else {
return(FALSE)
}
@@ -313,14 +313,14 @@ check_validity_mo_source <- function(x, refer_to_name = "`reference_df`", stop_o
}
if (colnames(x)[1] != "mo" && nrow(x) > length(unique(x[, 1, drop = TRUE]))) {
if (stop_on_error == TRUE) {
stop_(refer_to_name, " contains duplicate values in column {.field ", font_bold(colnames(x)[1]), "}", call = FALSE)
stop_(refer_to_name, " contains duplicate values in column '", colnames(x)[1], "'", call = FALSE)
} else {
return(FALSE)
}
}
if (colnames(x)[2] != "mo" && nrow(x) > length(unique(x[, 2, drop = TRUE]))) {
if (stop_on_error == TRUE) {
stop_(refer_to_name, " contains duplicate values in column {.field ", font_bold(colnames(x)[2]), "}", call = FALSE)
stop_(refer_to_name, " contains duplicate values in column '", colnames(x)[2], "'", call = FALSE)
} else {
return(FALSE)
}

View File

@@ -262,11 +262,11 @@ create_scale_mic <- function(aest, keep_operators, mic_range = NULL, ...) {
}
mics <- rescale_mic(x = as.double(as.mic(df[[aest_val]])), keep_operators = "none", mic_range = NULL, as.mic = TRUE)
if (!is.null(self$mic_values_rescaled) && any(mics < min(self$mic_values_rescaled, na.rm = TRUE) | mics > max(self$mic_values_rescaled, na.rm = TRUE), na.rm = TRUE)) {
warning_("The value for {.field ", font_bold(aest_val), "} is outside the plotted MIC range, consider using/updating the {.arg mic_range} argument in {.fun scale_", aest, "_mic}.")
warning_("The value for {.field ", aest_val, "} is outside the plotted MIC range, consider using/updating the {.arg mic_range} argument in {.fun scale_", aest, "_mic}.")
}
out[[aest_val]] <- log2(as.double(mics))
} else {
self$mic_values_rescaled <- rescale_mic(x = as.character(df[[aest]]), keep_operators = keep_operators, mic_range = mic_range, as.mic = TRUE)
self$mic_values_rescaled <- rescale_mic(x = as.double(as.mic(df[[aest]])), keep_operators = keep_operators, mic_range = mic_range, as.mic = TRUE)
# create new breaks and labels here
lims <- range(self$mic_values_rescaled, na.rm = TRUE)
# support inner and outer 'mic_range' settings (e.g., the data ranges 0.5-8 and 'mic_range' is set to 0.025-32)
@@ -280,21 +280,11 @@ create_scale_mic <- function(aest, keep_operators, mic_range = NULL, ...) {
ind_max <- which(COMMON_MIC_VALUES >= lims[2])[which.min(abs(COMMON_MIC_VALUES[COMMON_MIC_VALUES >= lims[2]] - lims[2]))] # Closest index where COMMON_MIC_VALUES >= lims[2]
self$mic_values_levels <- as.mic(COMMON_MIC_VALUES[ind_min:ind_max])
if (length(unique(self$mic_values_levels)) > 1) {
if (keep_operators == "all" && !all(self$mic_values_rescaled %in% self$mic_values_levels, na.rm = TRUE)) {
self$mic_values_levels <- unique(sort(c(self$mic_values_levels, self$mic_values_rescaled)))
# collision = same log2 position, but different string labels
log_positions <- log2(as.double(self$mic_values_levels))
dup_positions <- log_positions[duplicated(log_positions) | duplicated(log_positions, fromLast = TRUE)]
colliding_labels <- as.character(self$mic_values_levels)[log_positions %in% dup_positions]
self$warn_keep_all_operators <- length(unique(colliding_labels)) > 1
} else if (keep_operators == "edges") {
if (keep_operators %in% c("edges", "all") && length(unique(self$mic_values_levels)) > 1) {
self$mic_values_levels[1] <- paste0("<=", self$mic_values_levels[1])
self$mic_values_levels[length(self$mic_values_levels)] <- paste0(">=", self$mic_values_levels[length(self$mic_values_levels)])
}
}
self$mic_values_log <- log2(as.double(self$mic_values_rescaled))
if (aest == "y" && "group" %in% colnames(df)) {
@@ -322,26 +312,7 @@ create_scale_mic <- function(aest, keep_operators, mic_range = NULL, ...) {
}
scale$labels <- function(..., self) {
if (is.null(self$mic_breaks_set)) {
if (isTRUE(self$warn_keep_all_operators)) {
lookup <- tapply(
as.character(self$mic_values_rescaled),
self$mic_values_log,
function(x) paste(unique(x), collapse = ", ")
)
level_log <- as.character(log2(as.double(self$mic_values_levels)))
if (any(grepl(", ", lookup))) {
warning_("Using {.arg keep_operators = \"all\"} caused MIC values with different operators to share the same log2 position on the axis. These have been combined into a single label (e.g., {.val ", lookup[grepl(", ", lookup)][1], "}).", call = FALSE)
}
ifelse(
level_log %in% names(lookup),
lookup[level_log],
as.character(self$mic_values_levels)
)
} else {
self$mic_values_levels
}
} else {
breaks <- tryCatch(scale$breaks(), error = function(e) NULL)
if (!is.null(breaks)) {
@@ -441,7 +412,7 @@ create_scale_sir <- function(aesthetics, colours_SIR, language, eucast_I, ...) {
scale$labels <- function(x) {
stop_ifnot(all(x %in% c(levels(NA_sir_), "SI", "IR", NA)),
"Apply `scale_", aesthetics[1], "_sir()` to a variable of class {.cls sir}, see {.help [{.fun as.sir}](AMR::as.sir)}.",
"Apply `scale_", aesthetics[1], "_sir()` to a variable of class 'sir', see {.help [{.fun as.sir}](AMR::as.sir)}.",
call = FALSE
)
x <- as.character(x)

View File

@@ -346,7 +346,7 @@ sir_confidence_interval <- function(...,
if (n < minimum) {
warning_("Introducing NA: ",
ifelse(n == 0, "no", paste("only", n)),
" results available for {.help [{.fun sir_confidence_interval}](AMR::sir_confidence_interval)} (whilst {.arg minimum = ", minimum, "}).",
" results available for `sir_confidence_interval()` (`minimum` = ", minimum, ").",
call = FALSE
)
if (is.character(out)) {

View File

@@ -150,7 +150,7 @@ resistance_predict <- function(x,
}
stop_ifnot(
col_date %in% colnames(x),
"column {.code ", col_date, "} not found"
"column '", col_date, "' not found"
)
year <- function(x) {

99
R/sir.R
View File

@@ -471,7 +471,7 @@ is_sir_eligible <- function(x, threshold = 0.05) {
if (!is.na(ab)) {
# this is a valid antibiotic drug code
message_(
"Column {.field ", font_bold(cur_col), "} is SIR eligible (despite only having empty values), since it seems to be ",
"Column '", font_bold(cur_col), "' is SIR eligible (despite only having empty values), since it seems to be ",
ab_name(ab, language = NULL, tolower = TRUE), " (", ab, ")"
)
return(TRUE)
@@ -601,7 +601,7 @@ as.sir.default <- function(x,
ifelse(length(out7) > 0, paste0("7 as \"", out7, "\""), NA_character_),
ifelse(length(out8) > 0, paste0("8 as \"", out8, "\""), NA_character_)
)
message_("{.help [{.fun as.sir}](AMR::as.sir)}: Interpreting input value ", vector_and(out[!is.na(out)], quotes = FALSE, sort = FALSE))
message_("in {.help [{.fun as.sir}](AMR::as.sir)}: Interpreting input value ", vector_and(out[!is.na(out)], quotes = FALSE, sort = FALSE))
}
if (na_before != na_after) {
@@ -612,7 +612,7 @@ as.sir.default <- function(x,
cur_col <- get_current_column()
warning_("in {.help [{.fun as.sir}](AMR::as.sir)}: ", na_after - na_before, " result",
ifelse(na_after - na_before > 1, "s", ""),
ifelse(is.null(cur_col), "", paste0(" in column {.field ", font_bold(cur_col, collapse = NULL), "}")),
ifelse(is.null(cur_col), "", paste0(" in column '", cur_col, "'")),
" truncated (",
round(((na_after - na_before) / length(x)) * 100),
"%) that were invalid antimicrobial interpretations: ",
@@ -759,10 +759,6 @@ as.sir.data.frame <- function(x,
meet_criteria(max_cores, allow_class = c("numeric", "integer"), has_length = 1)
x.bak <- x
if (isTRUE(info) && message_not_thrown_before("as.sir", "sir_interpretation_history")) {
message_("Run {.help [{.fun sir_interpretation_history}](AMR::sir_interpretation_history)} afterwards to retrieve a logbook with all details of the breakpoint interpretations.\n\n")
}
if (tryCatch(length(list(...)) > 0, error = function(e) TRUE)) {
sel <- colnames(pm_select(x, ...))
} else {
@@ -839,7 +835,7 @@ as.sir.data.frame <- function(x,
message_(
"Assuming value", plural[1], " ",
vector_and(col_values, quotes = TRUE),
" in column ", paste0("{.field ", font_bold(col_specimen), "}"), " reflect", plural[2], " ", plural[3], "urinary tract infection", plural[1],
" in column ", paste0("{.field ", col_specimen, "}"), " reflect", plural[2], " ", plural[3], "urinary tract infection", plural[1],
".\n Use `as.sir(uti = FALSE)` to prevent this."
)
}
@@ -861,7 +857,7 @@ as.sir.data.frame <- function(x,
return(FALSE)
}
if (length(sel) == 0 || (length(sel) > 0 && ab %in% sel)) {
ab_coerced <- suppressWarnings(as.ab(ab, info = FALSE))
ab_coerced <- suppressWarnings(as.ab(ab, info = info))
if (is.na(ab_coerced) || (length(sel) > 0 & !ab %in% sel)) {
# not even a valid AB code
return(FALSE)
@@ -911,11 +907,6 @@ as.sir.data.frame <- function(x,
}
}
if (isTRUE(info)) {
message_(as_note = FALSE) # empty line
message_("Processing columns:", as_note = FALSE)
}
run_as_sir_column <- function(i) {
ab_col <- ab_cols[i]
out <- list(result = NULL, log = NULL)
@@ -978,12 +969,12 @@ as.sir.data.frame <- function(x,
return(out)
} else if (types[i] == "sir") {
ab <- ab_col
ab_coerced <- suppressWarnings(as.ab(ab, info = FALSE))
ab_coerced <- suppressWarnings(as.ab(ab, info = info))
show_message <- FALSE
if (!all(x[, ab, drop = TRUE] %in% c("S", "SDD", "I", "R", "NI", NA), na.rm = TRUE)) {
show_message <- TRUE
if (isTRUE(info)) {
message_("\u00a0\u00a0", AMR_env$bullet_icon, " Cleaning values in column ", paste0("{.field ", font_bold(ab), "}"), " (",
message_("Cleaning values in column ", paste0("{.field ", ab, "}"), " (",
ifelse(ab_coerced != toupper(ab), paste0(ab_coerced, ", "), ""),
ab_name(ab_coerced, tolower = TRUE, info = info), ")... ",
appendLF = FALSE,
@@ -993,7 +984,7 @@ as.sir.data.frame <- function(x,
} else if (!is.sir(x.bak[, ab, drop = TRUE])) {
show_message <- TRUE
if (isTRUE(info)) {
message_("\u00a0\u00a0", AMR_env$bullet_icon, " Assigning class {.cls sir} to already clean column ", paste0("{.field ", font_bold(ab), "}"), " (",
message_("Assigning class {.cls sir} to already clean column ", paste0("{.field ", ab, "}"), " (",
ifelse(ab_coerced != toupper(ab), paste0(ab_coerced, ", "), ""),
ab_name(ab_coerced, tolower = TRUE, language = NULL, info = info), ")... ",
appendLF = FALSE,
@@ -1003,7 +994,7 @@ as.sir.data.frame <- function(x,
}
result <- as.sir.default(x = as.character(x[, ab, drop = TRUE]))
if (show_message == TRUE && isTRUE(info)) {
message_(font_green_bg("\u00a0OK\u00a0"), as_note = FALSE)
message(font_green_bg(" OK "))
}
out$result <- result
out$log <- NULL
@@ -1015,7 +1006,7 @@ as.sir.data.frame <- function(x,
if (isTRUE(parallel) && n_cores > 1 && length(ab_cols) > 1) {
if (isTRUE(info)) {
message_(as_note = FALSE)
message()
message_("Running in parallel mode using ", n_cores, " out of ", get_n_cores(Inf), " cores, on columns ", vector_and(font_bold(ab_cols, collapse = NULL), quotes = "'", sort = FALSE), "...", as_note = FALSE, appendLF = FALSE)
}
if (.Platform$OS.type == "windows" || getRversion() < "4.0.0") {
@@ -1035,15 +1026,15 @@ as.sir.data.frame <- function(x,
result_list <- parallel::mclapply(seq_along(ab_cols), run_as_sir_column, mc.cores = n_cores)
}
if (isTRUE(info)) {
message_(font_green_bg("\u00aDONE\u00a"), as_note = FALSE)
message_(as_note = FALSE)
message_(font_green_bg(" DONE "), as_note = FALSE)
message()
message_("Run {.help [{.fun sir_interpretation_history}](AMR::sir_interpretation_history)} to retrieve a logbook with all details of the breakpoint interpretations.")
}
} else {
# sequential mode (non-parallel)
if (isTRUE(info) && n_cores > 1 && NROW(x) * NCOL(x) > 10000) {
# give a note that parallel mode might be better
message_(as_note = FALSE)
message()
message_("Running in sequential mode. Consider setting {.arg parallel} to {.code TRUE} to speed up processing on multiple cores.\n")
}
# this will contain a progress bar already
@@ -1230,7 +1221,7 @@ as_sir_method <- function(method_short,
host <- convert_host(host, lang = language)
if (any(is.na(host) & !is.na(host.bak)) && isTRUE(info) && message_not_thrown_before("as.sir", "missing_hosts")) {
warning_("The following animal host(s) could not be coerced: ", vector_and(host.bak[is.na(host) & !is.na(host.bak)]), immediate = TRUE)
message_(as_note = FALSE) # new line
message() # new line
}
# TODO add a switch to turn this off? In interactive sessions perhaps ask the user. Default should be On.
# if (breakpoint_type == "animal" && isTRUE(info) && message_not_thrown_before("as.sir", "host_missing_breakpoints")) {
@@ -1255,7 +1246,7 @@ as_sir_method <- function(method_short,
# get mo
if (!is.null(current_df) && length(mo) == 1 && mo %in% colnames(current_df)) {
mo_var_found <- paste0(" based on column {.field ", font_bold(mo), "}")
mo_var_found <- paste0(" based on column '", font_bold(mo), "'")
mo <- current_df[[mo]]
} else if (length(mo) != length(x)) {
mo_var_found <- ""
@@ -1271,7 +1262,7 @@ as_sir_method <- function(method_short,
silent = TRUE
)
if (!is.null(df) && !is.null(mo) && is.data.frame(df)) {
mo_var_found <- paste0(" based on column {.field ", font_bold(mo), "}")
mo_var_found <- paste0(" based on column '", font_bold(mo), "'")
mo <- df[, mo, drop = TRUE]
}
},
@@ -1324,7 +1315,7 @@ as_sir_method <- function(method_short,
}
ab.bak <- trimws2(ab)
ab <- suppressWarnings(as.ab(ab, info = FALSE))
ab <- suppressWarnings(as.ab(ab, info = info))
if (!is.null(list(...)$mo.bak)) {
mo.bak <- list(...)$mo.bak
} else {
@@ -1360,12 +1351,12 @@ as_sir_method <- function(method_short,
}
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.")
message_("in {.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.")
}
}
# format agents ----
agent_formatted <- paste0("{.field ", font_bold(ab.bak, collapse = NULL), "}")
agent_formatted <- paste0("'", font_bold(ab.bak, collapse = NULL), "'")
agent_name <- ab_name(ab, tolower = TRUE, language = NULL, info = info)
same_ab <- generalise_antibiotic_name(ab) == generalise_antibiotic_name(agent_name)
same_ab.bak <- generalise_antibiotic_name(ab.bak) == generalise_antibiotic_name(agent_name)
@@ -1381,7 +1372,7 @@ as_sir_method <- function(method_short,
)
# this intro text will also be printed in the progress bar if the `progress` package is installed
intro_txt <- paste0(
"\u00a0\u00a0", AMR_env$bullet_icon, " Interpreting ", method_long, ": ", ifelse(isTRUE(list(...)$is_data.frame), "column ", ""),
"Interpreting ", method_long, ": ", ifelse(isTRUE(list(...)$is_data.frame), "column ", ""),
ifelse(length(unique(agent_formatted)) == 1, unique(agent_formatted), paste0(vector_and(agent_formatted, quotes = FALSE, sort = FALSE))),
mo_var_found,
ifelse(identical(reference_data, AMR::clinical_breakpoints),
@@ -1399,7 +1390,7 @@ as_sir_method <- function(method_short,
rise_warning <- FALSE
rise_notes <- FALSE
method_coerced <- toupper(method)
ab_coerced <- as.ab(ab, info = FALSE)
ab_coerced <- as.ab(ab, info = info)
if (identical(reference_data, AMR::clinical_breakpoints)) {
breakpoints <- reference_data %pm>%
@@ -1496,14 +1487,14 @@ as_sir_method <- function(method_short,
# only print intro under 10 items, otherwise progressbar will print this and then it will be printed double
message_(intro_txt, appendLF = FALSE, as_note = FALSE)
}
p <- progress_ticker(n = nrow(df_unique), n_min = 10, title = intro_txt, only_bar_percent = TRUE)
p <- progress_ticker(n = nrow(df_unique), n_min = 10, title = font_blue(intro_txt), only_bar_percent = TRUE)
has_progress_bar <- !is.null(import_fn("progress_bar", "progress", error_on_fail = FALSE)) && nrow(df_unique) >= 10
on.exit(close(p))
if (nrow(breakpoints) == 0) {
# apparently no breakpoints found
if (isTRUE(info)) {
message_(font_grey_bg(font_black(" NO BREAKPOINTS ")), as_note = FALSE)
message(font_grey_bg(font_black(" NO BREAKPOINTS ")))
}
load_mo_uncertainties(metadata_mo)
@@ -1729,7 +1720,7 @@ as_sir_method <- function(method_short,
pm_filter(uti == FALSE)
notes_current <- paste0(
notes_current, "\n",
paste0("Breakpoints for UTI ", font_bold("and"), " non-UTI available for ", ab_formatted, " in ", mo_formatted, " - assuming ", site, ". Use argument `uti` to set which isolates are from urine. See `?as.sir`.")
paste0("Breakpoints for UTI ", font_bold("and"), " non-UTI available for ", ab_formatted, " in ", mo_formatted, " - assuming ", site, ". Use argument {.arg uti} to set which isolates are from urine. See {.help [{.fun as.sir}](AMR::as.sir)}.")
)
} 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
@@ -1919,7 +1910,7 @@ as_sir_method <- function(method_short,
host = vectorise_log_entry(breakpoints_current[, "host", drop = TRUE], length(rows)),
input = vectorise_log_entry(as.character(input_clean), length(rows)),
outcome = vectorise_log_entry(as.sir(new_sir), length(rows)),
notes = font_stripstyle(notes_current),
notes = font_stripstyle(notes_current), # vectorise_log_entry(paste0(font_stripstyle(notes_current), collapse = "\n"), length(rows)),
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)),
@@ -1944,9 +1935,9 @@ as_sir_method <- function(method_short,
notes <- notes[!trimws2(notes) %in% c("", NA_character_)]
if (length(notes) > 0) {
if (isTRUE(rise_warning)) {
message_(font_rose_bg("\u00a0WARNING\u00a0"), as_note = FALSE)
message(font_rose_bg(" WARNING "))
} else {
message_(font_yellow_bg("\u00a0NOTE\u00a0"), as_note = FALSE)
message(font_yellow_bg(" NOTE "))
}
notes <- unique(notes)
# if (isTRUE(verbose) || length(notes) == 1 || NROW(AMR_env$sir_interpretation_history) == 0) {
@@ -1955,10 +1946,10 @@ as_sir_method <- function(method_short,
message_(notes[i], as_note = FALSE)
}
} else {
# message_(word_wrap("\u00a0\u00a0", AMR_env$bullet_icon, " There were multiple notes. Print or View `sir_interpretation_history()` to examine them, or use `as.sir(..., verbose = TRUE)` next time to directly print them here.", add_fn = font_black))
# message(word_wrap(" ", AMR_env$bullet_icon, " There were multiple notes. Print or View `sir_interpretation_history()` to examine them, or use `as.sir(..., verbose = TRUE)` next time to directly print them here.", add_fn = font_black))
}
} else {
message_(font_green_bg("\u00a0OK\u00a0"), as_note = FALSE)
message(font_green_bg(" OK "))
}
}
@@ -2010,19 +2001,15 @@ pillar_shaft.sir <- function(x, ...) {
if (has_colour()) {
# colours will anyway not work when has_colour() == FALSE,
# but then the indentation should also not be applied
out[is.na(x)] <- pillar::style_subtle(" NA")
out[x == "S"] <- font_green_bg(" S ") # has font_black internally
out[x == "SDD"] <- font_green_lighter_bg(" SDD ") # has font_black internally
if (getOption("AMR_guideline", "EUCAST")[1] == "EUCAST") {
out[x == "I"] <- font_green_lighter_bg(" I ") # has font_black internally
} else {
out[x == "I"] <- font_orange_bg(" I ") # has font_black internally
}
out[x == "R"] <- font_rose_bg(" R ") # has font_black internally
out[x == "NI"] <- font_grey_bg(font_black(" NI ", adapt = FALSE))
out[x == "WT"] <- font_green_bg(" WT ") # has font_black internally
out[x == "NWT"] <- font_rose_bg(" NWT ") # has font_black internally
out[x == "NS"] <- font_rose_bg(" NS ") # has font_black internally
out[is.na(x)] <- font_grey(" NA")
out[x == "S"] <- font_green_bg(" S ")
out[x == "SDD"] <- font_green_lighter_bg(" SDD ")
out[x == "I"] <- font_orange_bg(" I ")
out[x == "R"] <- font_rose_bg(" R ")
out[x == "NI"] <- font_grey_bg(font_black(" NI "))
out[x == "WT"] <- font_green_bg(font_black(" WT "))
out[x == "NWT"] <- font_rose_bg(font_black(" NWT "))
out[x == "NS"] <- font_rose_bg(font_black(" NS "))
}
create_pillar_column(out, align = "left", width = 5)
}
@@ -2080,10 +2067,10 @@ freq.sir <- function(x, ...) {
# this prevents the requirement for putting the dependency in Imports:
#' @rawNamespace if(getRversion() >= "3.0.0") S3method(skimr::get_skimmers, sir)
get_skimmers.sir <- function(column) {
# TODO #170 add here in AMR 3.1.0 details about guideline
# TODO add here in AMR 3.1.0 details about guideline
skimr::sfl(
skim_type = "sir",
# guideline = function(x) "EUCAST 2026", # or "Multiple"
# guideline = function(x) "EUCAST 2025", # or "Multiple"
# origin = function(x) "MIC", # or "Multiple"
count_S = count_S,
count_I = count_I,
@@ -2100,7 +2087,7 @@ get_skimmers.sir <- function(column) {
#' @noRd
print.sir <- function(x, ...) {
x_name <- deparse(substitute(x))
cat(format_inline_("Class {.cls sir}\n"))
cat("Class 'sir'\n")
# TODO for #170
# if (!is.null(attributes(x)$guideline) && !all(is.na(attributes(x)$guideline))) {
# cat(font_blue(word_wrap("These values were interpreted using ",
@@ -2239,13 +2226,13 @@ check_reference_data <- function(reference_data, .call_depth) {
class_sir <- vapply(FUN.VALUE = character(1), AMR::clinical_breakpoints, function(x) paste0("<", class(x), ">", collapse = " and "))
class_ref <- vapply(FUN.VALUE = character(1), reference_data, function(x) paste0("<", class(x), ">", collapse = " and "))
if (!all(names(class_sir) == names(class_ref))) {
stop_("{.arg reference_data} must have the same column names as the {.help [clinical_breakpoints](AMR::clinical_breakpoints)} data set.", call = .call_depth)
stop_("{.arg reference_data} must have the same column names as the {.topic [clinical_breakpoints](AMR::clinical_breakpoints)} data set.", call = .call_depth)
}
if (!all(class_sir == class_ref)) {
bad_col <- names(class_ref[class_sir != class_ref][1])
bad_cls <- gsub("<|>", "", class_ref[class_sir != class_ref][1])
exp_cls <- gsub("<|>", "", class_sir[class_sir != class_ref][1])
stop_("{.arg reference_data} must be the same structure as the {.help [clinical_breakpoints](AMR::clinical_breakpoints)} data set. Column ", paste0("{.field ", font_bold(bad_col, collapse = NULL), "}"), " is of class ", paste0("{.cls ", bad_cls, "}"), ", but should be of class ", paste0("{.cls ", exp_cls, "}"), call = .call_depth)
stop_("{.arg reference_data} must be the same structure as the {.topic [clinical_breakpoints](AMR::clinical_breakpoints)} data set. Column ", paste0("{.field ", bad_col, "}"), " is of class ", paste0("{.cls ", bad_cls, "}"), ", but should be of class ", paste0("{.cls ", exp_cls, "}"), call = .call_depth)
}
}
}

View File

@@ -204,7 +204,7 @@ sir_calc <- function(...,
ifelse(denominator == 0, "no", paste("only", denominator)),
" results available",
data_vars,
" (whilst {.arg minimum = ", minimum, "}).",
" (`minimum` = ", minimum, ").",
call = FALSE
)
fraction <- NA_real_

View File

@@ -15,7 +15,7 @@ Overview:
even WISCA
- Provides the **full microbiological taxonomy** of ~79 000 distinct
species and extensive info of ~620 antimicrobial drugs
- Applies **CLSI 2011-2026** and **EUCAST 2011-2026** clinical and
- Applies **CLSI 2011-2025** and **EUCAST 2011-2025** clinical and
veterinary breakpoints, and ECOFFs, for MIC and disk zone
interpretation
- Corrects for duplicate isolates, **calculates** and **predicts** AMR

View File

@@ -37,11 +37,6 @@ devtools::load_all()
# BE SURE TO RUN data-raw/_reproduction_scripts/reproduction_of_microorganisms.groups.R FIRST TO GET THE GROUPS!
# For non-interactive use
if (!interactive()) {
View <- glimpse
}
# READ DATA ----
# files are retrieved from https://github.com/AClark-WHONET/AMRIE
@@ -51,21 +46,21 @@ file_organisms <- file.path(github_repo, "Organisms.txt")
file_breakpoints <- file.path(github_repo, "Breakpoints.txt")
file_antibiotics <- file.path(github_repo, "Antibiotics.txt")
whonet_organisms_raw <- read_tsv(file_organisms, na = c("", "NA", "-"), show_col_types = FALSE, guess_max = Inf) |>
whonet_organisms <- read_tsv(file_organisms, na = c("", "NA", "-"), show_col_types = FALSE, guess_max = Inf) |>
# remove old taxonomic names
filter(TAXONOMIC_STATUS == "C") |>
mutate(ORGANISM_CODE = toupper(WHONET_ORG_CODE))
whonet_breakpoints_raw <- read_tsv(file_breakpoints, na = c("", "NA", "-"), show_col_types = FALSE, guess_max = Inf) |>
whonet_breakpoints <- read_tsv(file_breakpoints, na = c("", "NA", "-"), show_col_types = FALSE, guess_max = Inf) |>
filter(GUIDELINES %in% c("CLSI", "EUCAST"))
whonet_antibiotics_raw <- read_tsv(file_antibiotics, na = c("", "NA", "-"), show_col_types = FALSE, guess_max = Inf) |>
whonet_antibiotics <- read_tsv(file_antibiotics, na = c("", "NA", "-"), show_col_types = FALSE, guess_max = Inf) |>
arrange(WHONET_ABX_CODE) |>
distinct(WHONET_ABX_CODE, .keep_all = TRUE)
# MICROORGANISMS WHONET CODES ----
whonet_organisms <- whonet_organisms_raw |>
whonet_organisms <- whonet_organisms |>
select(ORGANISM_CODE, ORGANISM, SPECIES_GROUP, GBIF_TAXON_ID) |>
mutate(
# this one was called Issatchenkia orientalis, but it should be:
@@ -115,13 +110,6 @@ organisms <- matched |> transmute(code = toupper(ORGANISM_CODE), group = SPECIES
mutate(name = mo_name(mo, keep_synonyms = TRUE)) |>
arrange(code)
# self-defined codes in the MO table must be retained
existing_codes <- microorganisms$fullname[microorganisms$fullname %like% ".* \\("]
existing_codes <- gsub(".*\\((.*)\\)", "\\1", existing_codes)
organisms <- organisms |>
filter(!code %in% existing_codes)
# some subspecies exist, while their upper species do not, add them as the species level:
subspp <- organisms |>
filter(mo_species(mo, keep_synonyms = TRUE) == mo_subspecies(mo, keep_synonyms = TRUE) &
@@ -151,10 +139,9 @@ organisms <- organisms |> filter(code != "XXX")
# 2023-07-08 SGM is also Strep gamma in WHONET, must only be Slowly-growing Mycobacterium
# 2024-06-14 still the case
# 2025-04-20 still the case
# 2026-03-27 still the case, but fixed using `existing_codes` above
organisms |> filter(code == "SGM")
# organisms <- organisms |>
# filter(!(code == "SGM" & name %like% "Streptococcus"))
organisms <- organisms |>
filter(!(code == "SGM" & name %like% "Streptococcus"))
# this must be empty:
organisms$code[organisms$code |> duplicated()]
@@ -175,7 +162,7 @@ microorganisms.codes2 <- microorganisms.codes |>
# new codes:
microorganisms.codes2$code[which(!microorganisms.codes2$code %in% microorganisms.codes$code)]
mo_name(microorganisms.codes2$mo[which(!microorganisms.codes2$code %in% microorganisms.codes$code)], keep_synonyms = TRUE)
microorganisms.codes <- microorganisms.codes2 |> distinct()
microorganisms.codes <- microorganisms.codes2
# Run this part to update ASIARS-Net:
# 2024-06-14: file not available anymore
@@ -214,15 +201,10 @@ devtools::load_all()
# now that we have the correct MO codes, get the breakpoints and convert them
whonet_breakpoints_raw |>
whonet_breakpoints |>
count(GUIDELINES, BREAKPOINT_TYPE) |>
pivot_wider(names_from = BREAKPOINT_TYPE, values_from = n) |>
janitor::adorn_totals(where = c("row", "col"))
whonet_breakpoints_raw |>
filter(YEAR == format(Sys.Date(), "%Y")) |>
count(GUIDELINES, YEAR, BREAKPOINT_TYPE) |>
pivot_wider(names_from = BREAKPOINT_TYPE, values_from = n) |>
janitor::adorn_totals(where = c("row", "col"))
# compared to current
AMR::clinical_breakpoints |>
count(GUIDELINES = gsub("[^a-zA-Z]", "", guideline), type) |>
@@ -231,7 +213,7 @@ AMR::clinical_breakpoints |>
as.data.frame() |>
janitor::adorn_totals(where = c("row", "col"))
breakpoints <- whonet_breakpoints_raw |>
breakpoints <- whonet_breakpoints |>
mutate(code = toupper(ORGANISM_CODE)) |>
left_join(bind_rows(microorganisms.codes |> filter(!code %in% c("ALL", "GEN")),
# GEN (Generic) and ALL (All) are PK/PD codes
@@ -251,7 +233,7 @@ breakpoints <- breakpoints |>
# and these ones have unknown antibiotics according to WHONET itself:
breakpoints |>
filter(!WHONET_ABX_CODE %in% whonet_antibiotics_raw$WHONET_ABX_CODE) |>
filter(!WHONET_ABX_CODE %in% whonet_antibiotics$WHONET_ABX_CODE) |>
count(GUIDELINES, WHONET_ABX_CODE) |>
mutate(ab = as.ab(WHONET_ABX_CODE, fast_mode = TRUE),
ab_name = ab_name(ab))
@@ -314,7 +296,7 @@ breakpoints_new[which(breakpoints_new$method == "DISK"), "breakpoint_R"] <- as.d
# regarding animal breakpoints, CLSI has adults and foals for horses, but only for amikacin - only keep adult horses
breakpoints_new |>
filter(host %like% "foal") |>
count(guideline, host, ab)
count(guideline, host)
breakpoints_new <- breakpoints_new |>
filter(host %unlike% "foal") |>
mutate(host = ifelse(host %like% "horse", "horse", host))
@@ -322,7 +304,7 @@ breakpoints_new <- breakpoints_new |>
# FIXES FOR WHONET ERRORS ----
m <- unique(as.double(as.mic(levels(as.mic(1)))))
# WHONET has no >1024 but instead uses 1025, 513, and 129, so as.mic() cannot be used to clean.
# WHONET has no >1024 but instead uses 1025, 513, etc, so as.mic() cannot be used to clean.
# instead, raise these one higher valid MIC factor level:
breakpoints_new |> filter(method == "MIC" & (!breakpoint_S %in% c(m, NA))) |> distinct(breakpoint_S)
breakpoints_new |> filter(method == "MIC" & (!breakpoint_R %in% c(m, NA))) |> distinct(breakpoint_R)
@@ -336,7 +318,6 @@ anyNA(breakpoints_new$breakpoint_S)
# a lot of R breakpoints are missing, but for CLSI this is required and can be set using as.sir(..., substitute_missing_r_breakpoint = TRUE/FALSE, ...)
# 2025-04-20/ For EUCAST, this should not be the case, only happens to old guideline now it seems
# 2026-03-27/ Now 2026 is in it as well, but making R same to S is fine
breakpoints_new |>
filter(method == "MIC" & guideline %like% "EUCAST" & is.na(breakpoint_R)) |>
count(guideline)
@@ -344,15 +325,10 @@ breakpoints_new[which(breakpoints_new$method == "MIC" & breakpoints_new$guidelin
# fix streptococci in WHONET table of EUCAST: Strep A, B, C and G must only include these groups and not all streptococci:
# 2026-03-27/ Only erroneous in EUCAST until 2024, it's fixed for 2025 and 2026, but we need to fix this historically too
breakpoints_new$mo[breakpoints_new$guideline %like% "EUCAST" & breakpoints_new$mo == "B_STRPT" & breakpoints_new$ref_tbl %like% "^strep.* a.* b.*c.*g"] <- as.mo("B_STRPT_ABCG")
breakpoints_new$mo[breakpoints_new$mo == "B_STRPT" & breakpoints_new$ref_tbl %like% "^strep.* a.* b.*c.*g"] <- as.mo("B_STRPT_ABCG")
# Haemophilus same error (must only be H. influenzae)
# 2026-03-27/ Only erroneous in EUCAST until 2024, it's fixed for 2025 and 2026, but we need to fix this historically too
breakpoints_new$mo[breakpoints_new$guideline %like% "EUCAST" & breakpoints_new$mo == "B_HMPHL" & breakpoints_new$ref_tbl %like% "^h.* influenzae"] <- as.mo("B_HMPHL_INFL")
breakpoints_new$mo[breakpoints_new$mo == "B_HMPHL" & breakpoints_new$ref_tbl %like% "^h.* influenzae"] <- as.mo("B_HMPHL_INFL")
# EUCAST says that for H. parainfluenzae the H. influenza rules can be used, so add them
breakpoints_new |>
filter(method == "MIC" & guideline %like% "EUCAST" & mo %like% as.mo("B_HMPHL")) |>
count(guideline, mo)
breakpoints_new <- breakpoints_new |>
bind_rows(
breakpoints_new |>
@@ -369,17 +345,6 @@ breakpoints_new |> filter(mo == as.mo("Streptococcus viridans") & ab == "GEH")
breakpoints_new <- breakpoints_new |> filter(!(mo == as.mo("Streptococcus viridans") & ab == "GEN"))
# Nitrofurantoin in Staph (EUCAST) only applies to S. saprophyticus, while WHONET has the DISK correct but the MIC on genus level
breakpoints_new$mo[breakpoints_new$mo == "B_STPHY" & breakpoints_new$ab == "NIT" & breakpoints_new$guideline %like% "EUCAST"] <- as.mo("B_STPHY_SPRP")
# WHONET contains breakpoint for EUCAST that are not actually in EUCAST:
# IPM in M. morganii is not in it since v10
wrong <- with(breakpoints_new, guideline %like% "EUCAST" & ab == "IPM" & mo == as.mo("M. morganii") & ref_tbl != "ECOFF")
breakpoints_new |> filter(wrong)
breakpoints_new <- breakpoints_new |> filter(!wrong)
# Breakpoints for COPS were part of EUCAST until v11
wrong <- with(breakpoints_new, guideline %like% "EUCAST" & mo == as.mo("CoPS") & ref_tbl != "ECOFF")
breakpoints_new |> filter(wrong)
breakpoints_new <- breakpoints_new |> filter(!wrong)
# WHONET sets the 2023 breakpoints for SAM to MIC of 16/32 for Enterobacterales, should be MIC 8/32 like AMC (see issue #123 on github.com/msberends/AMR)
# 2024-02-22/ fixed now
@@ -424,7 +389,7 @@ breakpoints_new |>
filter(id %in% .$id[which(duplicated(id))]) |>
arrange(desc(guideline)) |>
View()
# 2024-06-19/ mostly ECOFFs, but there's no explanation in the whonet_breakpoints_raw df, we have to remove duplicates
# 2024-06-19/ mostly ECOFFs, but there's no explanation in the whonet_breakpoints file, we have to remove duplicates
# 2025-04-20/ same, most important one seems M. tuberculosis in CLSI (also in 2025)
breakpoints_new <- breakpoints_new |>
distinct(guideline, type, host, method, site, mo, ab, uti, .keep_all = TRUE)
@@ -433,9 +398,9 @@ breakpoints_new <- breakpoints_new |>
# CHECKS AND SAVE TO PACKAGE ----
# check again
breakpoints_new |> filter(guideline == "EUCAST 2026", ab == "AMC", mo == "B_[ORD]_ENTRBCTR", method == "MIC")
breakpoints_new |> filter(guideline == "EUCAST 2025", ab == "AMC", mo == "B_[ORD]_ENTRBCTR", method == "MIC")
# compare with current version
clinical_breakpoints |> filter(guideline == "EUCAST 2025", ab == "AMC", mo == "B_[ORD]_ENTRBCTR", method == "MIC")
clinical_breakpoints |> filter(guideline == "EUCAST 2024", ab == "AMC", mo == "B_[ORD]_ENTRBCTR", method == "MIC")
# must have "human" and "ECOFF"
breakpoints_new |> filter(mo == "B_STRPT_PNMN", ab == "AMP", guideline == "EUCAST 2020", method == "MIC")

View File

@@ -1 +1 @@
c43a990cf91f959913d207e5a85e2bd5
c7062e60fa4fbc2eee233044d15903ce

File diff suppressed because it is too large Load Diff

View File

@@ -2832,7 +2832,6 @@
"FU-" "B_FSBCTR"
"FUA.SP" "F_FUSRM"
"FUL" "B_FSBCTR_ULCR"
"FUO" "F_FUSRM_OXYS"
"FUR" "F_FUSRM"
"FUROXY" "F_FUSRM_OXYS"
"FURPET" "F_FUSRM_PTRL"
@@ -2937,7 +2936,6 @@
"GLO.SP" "B_GLBCT"
"GLOSAN" "B_GLBCT_SNGN"
"GLOSPP" "B_GLBCT"
"GLS" "B_GLSSR"
"GM+" "B_GRAMP"
"GM-" "B_GRAMN"
"GMO" "B_GEMLL_MRBL"
@@ -3028,6 +3026,7 @@
"HABSPP" "B_HMTBC"
"HAC" "B_AGGRG_ACTN"
"HACEK" "B_HACEK"
"HACEK" "B_HACEK"
"HAE" "B_HMPHL"
"HAE.SP" "B_HMPHL"
"HAEAEG" "B_HMPHL_AEGY"
@@ -3123,7 +3122,7 @@
"HPL" "B_HMPHL_PRPH"
"HPO" "F_OGATA"
"HPOSPP" "F_HNDRS_ASTR"
"HPR" "B_GLSSR_PRSS"
"HPR" "B_HMPHL_PRSS"
"HPU" "B_HLCBCT_PLLR"
"HPY" "B_HLCBCT_PYLR"
"HRB" "B_HRBSP"
@@ -3472,7 +3471,6 @@
"LQU" "B_LGNLL_QTRN"
"LRC" "B_LPTSP_INTR"
"LRE" "B_LCTBC_RETR"
"LRF" "B_LCTCC_RFFN"
"LRI" "B_LMNRL_RCHR"
"LRU" "B_LGNLL_RBRL"
"LSA" "B_LCTBC_SLVR"
@@ -3762,7 +3760,6 @@
"MNE" "B_MYCBC_NERM"
"MNL" "B_MRXLL_NNLQ"
"MNO" "B_MYCBC_NNCH"
"MNT" "B_MYCBC"
"MNV" "B_MNNHM_VRGN"
"MO-" "B_MRXLL"
"MO.BOV" "B_MRXLL_BOVS"
@@ -4298,7 +4295,6 @@
"PAT.SP" "B_PANTO"
"PAU" "B_SLMNL_ENTR_ENTR"
"PAV" "B_AVBCT_AVIM"
"PBA" "B_PSDCL_ALBA"
"PBC" "B_PRVTL_BCCL"
"PBE" "B_PSTRL_BTTY"
"PBI" "B_PRBCT"
@@ -4595,7 +4591,6 @@
"PSA" "F_PSDLL"
"PSA.SP" "F_PSDLL"
"PSASPP" "F_PSDLL"
"PSB" "B_PSDCL"
"PSC" "F_PSDCH"
"PSCSPP" "B_PSDCL"
"PSD" "B_STPHY_PSDN"
@@ -4711,7 +4706,6 @@
"RAH.SP" "B_RHNLL"
"RAHAQU" "B_RHNLL_AQTL"
"RAHSPP" "B_RHNLL"
"RAI" "B_RLSTN_INSD"
"RAK" "B_RTTSA_AKAR"
"RAL" "B_RLSTN"
"RAL.SP" "B_RLSTN"
@@ -4806,7 +4800,6 @@
"ROD" "B_RDNTB"
"RODPNE" "B_RDNTB_PNMT"
"RODSPP" "B_RDNTB"
"ROK" "B_ROTHI_KRST"
"ROL" "F_RHZPS_MCRS"
"ROM" "B_RSMNS"
"ROMMUC" "B_RSMNS"
@@ -5049,10 +5042,8 @@
"SAV" "B_SLMNL_ARCH"
"SB2" "B_STRPT_BOVS"
"SBA" "B_SLMNL_BRLL"
"SBC" "B_SLBCL"
"SBE" "B_SHWNL_BNTH"
"SBG" "B_SLMNL_BNGR"
"SBI" "B_SLBCL_SLVS"
"SBL" "B_SLMNL_BLCK"
"SBM" "B_SLMNL_BVSM"
"SBN" "B_SLMNL_BBRG"
@@ -5087,7 +5078,6 @@
"SCS" "F_SCLCB_CNST"
"SCT" "B_STRPT_CNST"
"SCU" "B_STPHY_CRNS"
"SCV" "F_SCPLR_VCLS"
"SCY" "F_SCYTL"
"SCYSPP" "F_SCYTL"
"SD1" "B_SHGLL_DYSN"
@@ -5666,7 +5656,6 @@
"TAYSPP" "B_TYLRL"
"TBE" "F_GTRCH_RDLL"
"TBESPP" "F_TRCHS"
"TBH" "F_TRCHP_BNHM"
"TBN" "B_TRPRL_BRNR"
"TCA" "F_DBRYM_CHVL"
"TCASPP" "F_CANDD"
@@ -5852,8 +5841,6 @@
"TYASPP" "F_TRCHP"
"TYE" "P_TRYPN_JNSN"
"TYI" "F_TRCHP_INDT"
"TYM" "B_TRPHR"
"TYW" "B_TRPHR_WHPP"
"ULO" "F_ULCLD"
"UNK" "UNKNOWN"
"UPEC" "B_ESCHR_COLI"
@@ -5863,7 +5850,6 @@
"UREPAR" "B_URPLS_PRVM"
"URESPP" "B_URPLS"
"UREURE" "B_URPLS_URLY"
"URP" "B_URPLS_PRVM"
"UUR" "B_URPLS_URLY"
"V.ALG" "B_VIBRI_ALGN"
"V.CHO" "B_VIBRI_CHLR"

View File

@@ -1 +1 @@
6ef98bb1bcd27052fde453bb12c0b285
986d5110a46bbf297ebaeb4dd5179fff

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -10,7 +10,7 @@
even WISCA
- Provides the **full microbiological taxonomy** of ~79 000 distinct
species and extensive info of ~620 antimicrobial drugs
- Applies **CLSI 2011-2026** and **EUCAST 2011-2026** clinical and
- Applies **CLSI 2011-2025** and **EUCAST 2011-2025** clinical and
veterinary breakpoints, and ECOFFs, for MIC and disk zone
interpretation
- Corrects for duplicate isolates, **calculates** and **predicts** AMR
@@ -68,7 +68,7 @@ species**](./reference/microorganisms.html) (updated June 2024) and all
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
guidelines from CLSI 2011-2026 and EUCAST 2011-2026 are included, even
guidelines from CLSI 2011-2025 and EUCAST 2011-2025 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). **It
@@ -171,14 +171,14 @@ example_isolates %>%
select(bacteria,
aminoglycosides(),
carbapenems())
#> Using column mo as input for `mo_fullname()`
#> Using column mo as input for `mo_is_gram_negative()`
#> Using column mo as input for `mo_is_intrinsic_resistant()`
#> Using column 'mo' as input for `mo_fullname()`
#> Using column 'mo' as input for `mo_is_gram_negative()`
#> Using column 'mo' as input for `mo_is_intrinsic_resistant()`
#> Determining intrinsic resistance based on 'EUCAST Expected Resistant
#> Phenotypes' v1.2 (2023). This note will be shown once per session.
#> For `aminoglycosides()` using columns GEN (gentamicin), TOB (tobramycin), AMK
#> (amikacin), and KAN (kanamycin)
#> For `carbapenems()` using columns IPM (imipenem) and MEM (meropenem)
#> For `aminoglycosides()` using columns 'GEN' (gentamicin), 'TOB'
#> (tobramycin), 'AMK' (amikacin), and 'KAN' (kanamycin)
#> For `carbapenems()` using columns 'IPM' (imipenem) and 'MEM' (meropenem)
#> # A tibble: 35 × 7
#> bacteria GEN TOB AMK KAN IPM MEM
#> <chr> <sir> <sir> <sir> <sir> <sir> <sir>
@@ -215,9 +215,9 @@ output format automatically (such as markdown, LaTeX, HTML, etc.).
``` r
antibiogram(example_isolates,
antimicrobials = c(aminoglycosides(), carbapenems()))
#> For `aminoglycosides()` using columns GEN (gentamicin), TOB (tobramycin), AMK
#> (amikacin), and KAN (kanamycin)
#> For `carbapenems()` using columns IPM (imipenem) and MEM (meropenem)
#> For `aminoglycosides()` using columns 'GEN' (gentamicin), 'TOB'
#> (tobramycin), 'AMK' (amikacin), and 'KAN' (kanamycin)
#> For `carbapenems()` using columns 'IPM' (imipenem) and 'MEM' (meropenem)
```
| Pathogen | Amikacin | Gentamicin | Imipenem | Kanamycin | Meropenem | Tobramycin |
@@ -344,15 +344,15 @@ out <- example_isolates %>%
# calculate AMR using resistance(), over all aminoglycosides and polymyxins:
summarise(across(c(aminoglycosides(), polymyxins()),
resistance))
#> For `aminoglycosides()` using columns GEN (gentamicin), TOB (tobramycin), AMK
#> (amikacin), and KAN (kanamycin)
#> For `polymyxins()` using column COL (colistin)
#> For `aminoglycosides()` using columns 'GEN' (gentamicin), 'TOB'
#> (tobramycin), 'AMK' (amikacin), and 'KAN' (kanamycin)
#> For `polymyxins()` using column 'COL' (colistin)
#> Warning: There was 1 warning in `summarise()`.
#> In argument: `across(c(aminoglycosides(), polymyxins()), resistance)`.
#> In group 3: `ward = "Outpatient"`.
#> Caused by warning:
#> ! Introducing NA: only 23 results available for KAN in group: ward = "Outpatient"
#> (whilst `minimum = 30`).
#> ! Introducing NA: only 23 results available for KAN in group: ward =
#> "Outpatient" (`minimum` = 30).
out
#> # A tibble: 3 × 6
#> ward GEN TOB AMK KAN COL

View File

@@ -18,14 +18,14 @@ This is an overview of all the package-specific options you can set in the \code
\item \code{AMR_custom_ab} \cr A file location to an RDS file, to use custom antimicrobial drugs with this package. This is explained in \code{\link[=add_custom_antimicrobials]{add_custom_antimicrobials()}}.
\item \code{AMR_custom_mo} \cr A file location to an RDS file, to use custom microorganisms with this package. This is explained in \code{\link[=add_custom_microorganisms]{add_custom_microorganisms()}}.
\item \code{AMR_eucastrules} \cr A \link{character} to set the default types of rules for \code{\link[=eucast_rules]{eucast_rules()}} function, must be one or more of: \code{"breakpoints"}, \code{"expert"}, \code{"other"}, \code{"custom"}, \code{"all"}, and defaults to \code{c("breakpoints", "expert")}.
\item \code{AMR_guideline} \cr A \link{character} to set the default guideline used throughout the \code{AMR} package wherever a \code{guideline} argument is available. This option is used as the default in e.g. \code{\link[=as.sir]{as.sir()}}, \code{\link[=resistance]{resistance()}}, \code{\link[=susceptibility]{susceptibility()}}, \code{\link[=interpretive_rules]{interpretive_rules()}} and many plotting functions. \strong{While unset}, the AMR package uses the latest implemented EUCAST guideline (currently EUCAST 2026).
\item \code{AMR_guideline} \cr A \link{character} to set the default guideline used throughout the \code{AMR} package wherever a \code{guideline} argument is available. This option is used as the default in e.g. \code{\link[=as.sir]{as.sir()}}, \code{\link[=resistance]{resistance()}}, \code{\link[=susceptibility]{susceptibility()}}, \code{\link[=interpretive_rules]{interpretive_rules()}} and many plotting functions. \strong{While unset}, the AMR package uses the latest implemented EUCAST guideline (currently EUCAST 2025).
\itemize{
\item For \code{\link[=as.sir]{as.sir()}}, this determines which clinical breakpoint guideline is used to interpret MIC values and disk diffusion diameters. It can be either the guideline name (e.g., \code{"CLSI"} or \code{"EUCAST"}) or the name including a year (e.g., \code{"CLSI 2019"}). Supported guidelines are EUCAST 2011 to 2026, and CLSI 2011 to 2026.
\item For \code{\link[=as.sir]{as.sir()}}, this determines which clinical breakpoint guideline is used to interpret MIC values and disk diffusion diameters. It can be either the guideline name (e.g., \code{"CLSI"} or \code{"EUCAST"}) or the name including a year (e.g., \code{"CLSI 2019"}). Supported guidelines are EUCAST 2011 to 2025, and CLSI 2011 to 2025.
\item For \code{\link[=resistance]{resistance()}} and \code{\link[=susceptibility]{susceptibility()}}, this setting determines how the \code{"I"} (Intermediate / Increased exposure) category is handled in calculations. Under CLSI, \code{"I"} is considered \emph{resistant} in susceptibility calculations; under EUCAST, \code{"I"} is considered \emph{susceptible} in susceptibility calculations. Explicitly setting this option ensures reproducible AMR proportion estimates.
\item For \code{\link[=interpretive_rules]{interpretive_rules()}}, this determines which guideline-specific interpretive (expert) rules are applied to antimicrobial test results, either EUCAST or CLSI.
\item For many plotting functions (e.g., for MIC or disk diffusion values), supplying \code{mo} and \code{ab} enables automatic SIR-based interpretative colouring. These colours are derived from \code{\link[=as.sir]{as.sir()}} in the background and therefore depend on the active \code{guideline} setting, which again uses EUCAST 2026 if not set explicitly.
\item For many plotting functions (e.g., for MIC or disk diffusion values), supplying \code{mo} and \code{ab} enables automatic SIR-based interpretative colouring. These colours are derived from \code{\link[=as.sir]{as.sir()}} in the background and therefore depend on the active \code{guideline} setting, which again uses EUCAST 2025 if not set explicitly.
}
\item \code{AMR_guideline} \cr A \link{character} to set the default guideline for interpreting MIC values and disk diffusion diameters with \code{\link[=as.sir]{as.sir()}}. Can be only the guideline name (e.g., \code{"CLSI"}) or the name with a year (e.g. \code{"CLSI 2019"}). The default to the latest implemented EUCAST guideline, currently \code{"EUCAST 2026"}. Supported guideline are currently EUCAST (2011-2026) and CLSI (2011-2026).
\item \code{AMR_guideline} \cr A \link{character} to set the default guideline for interpreting MIC values and disk diffusion diameters with \code{\link[=as.sir]{as.sir()}}. Can be only the guideline name (e.g., \code{"CLSI"}) or the name with a year (e.g. \code{"CLSI 2019"}). The default to the latest implemented EUCAST guideline, currently \code{"EUCAST 2025"}. Supported guideline are currently EUCAST (2011-2025) and CLSI (2011-2025).
\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_substitute_missing_r_breakpoint} \cr A \link{logical} to use in \code{\link[=as.sir]{as.sir()}}, to indicate that missing R breakpoints must be substituted with \code{"R"} - the default is \code{FALSE}.

View File

@@ -32,7 +32,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{~79 000 distinct microbial species}} (updated June 2024) and all \href{https://amr-for-r.org/reference/antimicrobials.html}{\strong{~620 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{~79 000 distinct microbial species}} (updated June 2024) and all \href{https://amr-for-r.org/reference/antimicrobials.html}{\strong{~620 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-2025 and EUCAST 2011-2025 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.
}

View File

@@ -50,13 +50,13 @@ Ordered \link{factor} with additional class \code{\link{mic}}, that in mathemati
This transforms vectors to a new class \code{\link{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.
}
\details{
To interpret MIC values as SIR values, use \code{\link[=as.sir]{as.sir()}} on MIC values. It supports guidelines from EUCAST (2011-2026) and CLSI (2011-2026).
To interpret MIC values as SIR values, use \code{\link[=as.sir]{as.sir()}} on MIC values. It supports guidelines from EUCAST (2011-2025) and CLSI (2011-2025).
This class for MIC values is a quite a special data type: formally it is an ordered \link{factor} with valid MIC values as \link{factor} levels (to make sure only valid MIC values are retained), but for any mathematical operation it acts as decimal numbers:
\if{html}{\out{<div class="sourceCode">}}\preformatted{x <- random_mic(10)
x
#> Class <mic>
#> Class 'mic'
#> [1] 16 1 8 8 64 >=128 0.0625 32 32 16
is.factor(x)
@@ -72,7 +72,7 @@ median(x)
This makes it possible to maintain operators that often come with MIC values, such ">=" and "<=", even when filtering using \link{numeric} values in data analysis, e.g.:
\if{html}{\out{<div class="sourceCode">}}\preformatted{x[x > 4]
#> Class <mic>
#> Class 'mic'
#> [1] 16 8 8 64 >=128 32 32 16
df <- data.frame(x, hospital = "A")

View File

@@ -16,11 +16,11 @@
\source{
For interpretations of minimum inhibitory concentration (MIC) values and disk diffusion diameters:
\itemize{
\item \strong{CLSI M39: Analysis and Presentation of Cumulative Antimicrobial Susceptibility Test Data}, 2011-2026, \emph{Clinical and Laboratory Standards Institute} (CLSI). \url{https://clsi.org/standards/products/microbiology/documents/m39/}.
\item \strong{CLSI M100: Performance Standard for Antimicrobial Susceptibility Testing}, 2011-2026, \emph{Clinical and Laboratory Standards Institute} (CLSI). \url{https://clsi.org/standards/products/microbiology/documents/m100/}.
\item \strong{CLSI VET01: Performance Standards for Antimicrobial Disk and Dilution Susceptibility Tests for Bacteria Isolated From Animals}, 2019-2026, \emph{Clinical and Laboratory Standards Institute} (CLSI). \url{https://clsi.org/standards/products/veterinary-medicine/documents/vet01/}.
\item \strong{EUCAST Breakpoint tables for interpretation of MICs and zone diameters}, 2011-2026, \emph{European Committee on Antimicrobial Susceptibility Testing} (EUCAST). \url{https://www.eucast.org/bacteria/clinical-breakpoints-and-interpretation/clinical-breakpoint-tables/}.
\item \strong{WHONET} as a source for machine-reading the clinical breakpoints (\href{https://amr-for-r.org/reference/clinical_breakpoints.html#imported-from-whonet}{read more here}), 1989-2026, \emph{WHO Collaborating Centre for Surveillance of Antimicrobial Resistance}. \url{https://whonet.org/}.
\item \strong{CLSI M39: Analysis and Presentation of Cumulative Antimicrobial Susceptibility Test Data}, 2011-2025, \emph{Clinical and Laboratory Standards Institute} (CLSI). \url{https://clsi.org/standards/products/microbiology/documents/m39/}.
\item \strong{CLSI M100: Performance Standard for Antimicrobial Susceptibility Testing}, 2011-2025, \emph{Clinical and Laboratory Standards Institute} (CLSI). \url{https://clsi.org/standards/products/microbiology/documents/m100/}.
\item \strong{CLSI VET01: Performance Standards for Antimicrobial Disk and Dilution Susceptibility Tests for Bacteria Isolated From Animals}, 2019-2025, \emph{Clinical and Laboratory Standards Institute} (CLSI). \url{https://clsi.org/standards/products/veterinary-medicine/documents/vet01/}.
\item \strong{EUCAST Breakpoint tables for interpretation of MICs and zone diameters}, 2011-2025, \emph{European Committee on Antimicrobial Susceptibility Testing} (EUCAST). \url{https://www.eucast.org/bacteria/clinical-breakpoints-and-interpretation/clinical-breakpoint-tables/}.
\item \strong{WHONET} as a source for machine-reading the clinical breakpoints (\href{https://amr-for-r.org/reference/clinical_breakpoints.html#imported-from-whonet}{read more here}), 1989-2025, \emph{WHO Collaborating Centre for Surveillance of Antimicrobial Resistance}. \url{https://whonet.org/}.
}
}
\usage{
@@ -94,7 +94,7 @@ Otherwise: arguments passed on to methods.}
\item{ab}{A vector (or column name) with \link{character}s that can be coerced to a valid antimicrobial drug code with \code{\link[=as.ab]{as.ab()}}.}
\item{guideline}{A guideline name (or column name) to use for SIR interpretation. Defaults to EUCAST 2026 (the latest implemented EUCAST guideline in the \link{clinical_breakpoints} data set), but can be set with the package option \code{\link[=AMR-options]{AMR_guideline}}. Currently supports EUCAST (2011-2026) and CLSI (2011-2026), see \emph{Details}. Using a column name allows for straightforward interpretation of historical data, which must be analysed in the context of, for example, different years.}
\item{guideline}{A guideline name (or column name) to use for SIR interpretation. Defaults to EUCAST 2025 (the latest implemented EUCAST guideline in the \link{clinical_breakpoints} data set), but can be set with the package option \code{\link[=AMR-options]{AMR_guideline}}. Currently supports EUCAST (2011-2025) and CLSI (2011-2025), see \emph{Details}. Using a column name allows for straightforward interpretation of historical data, which must be analysed in the context of, for example, different years.}
\item{uti}{(Urinary Tract Infection) a vector (or column name) with \link{logical}s (\code{TRUE} or \code{FALSE}) to specify whether a UTI specific interpretation from the guideline should be chosen. For using \code{\link[=as.sir]{as.sir()}} on a \link{data.frame}, this can also be a column containing \link{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. See \emph{Examples}.}
@@ -162,7 +162,7 @@ Ordered \link{factor} with new class \code{sir}
\description{
Clean up existing SIR values, or interpret minimum inhibitory concentration (MIC) values and disk diffusion diameters according to EUCAST or CLSI. \code{\link[=as.sir]{as.sir()}} transforms the input to a new class \code{\link{sir}}, which is an ordered \link{factor} containing the levels \code{S}, \code{SDD}, \code{I}, \code{R}, \code{NI}.
Breakpoints are currently implemented from EUCAST 2011-2026 and CLSI 2011-2026, see \emph{Details}. All breakpoints used for interpretation are available in our \link{clinical_breakpoints} data set.
Breakpoints are currently implemented from EUCAST 2011-2025 and CLSI 2011-2025, see \emph{Details}. All breakpoints used for interpretation are available in our \link{clinical_breakpoints} data set.
}
\details{
\emph{Note: The clinical breakpoints in this package were validated through, and imported from, \href{https://whonet.org}{WHONET}. The public use of this \code{AMR} package has been endorsed by both CLSI and EUCAST. See \link{clinical_breakpoints} for more information.}
@@ -215,12 +215,12 @@ as.sir(your_data, ..., parallel = TRUE)
For interpreting MIC values as well as disk diffusion diameters, currently implemented guidelines are:
\itemize{
\item For \strong{clinical microbiology}: EUCAST 2011-2026 and CLSI 2011-2026;
\item For \strong{veterinary microbiology}: EUCAST 2021-2026 and CLSI 2019-2026;
\item For \strong{ECOFFs} (Epidemiological Cut-off Values): EUCAST 2020-2026 and CLSI 2022-2026.
\item For \strong{clinical microbiology}: EUCAST 2011-2025 and CLSI 2011-2025;
\item For \strong{veterinary microbiology}: EUCAST 2021-2025 and CLSI 2019-2025;
\item For \strong{ECOFFs} (Epidemiological Cut-off Values): EUCAST 2020-2025 and CLSI 2022-2025.
}
The \code{guideline} argument must be set to e.g., \code{"EUCAST 2026"} or \code{"CLSI 2026"}. By simply using \code{"EUCAST"} (the default) or \code{"CLSI"} as input, the latest included version of that guideline will automatically be selected. Importantly, using a column name of your data instead, allows for straightforward interpretation of historical data that must be analysed in the context of, for example, different years.
The \code{guideline} argument must be set to e.g., \code{"EUCAST 2025"} or \code{"CLSI 2025"}. By simply using \code{"EUCAST"} (the default) or \code{"CLSI"} as input, the latest included version of that guideline will automatically be selected. Importantly, using a column name of your data instead, allows for straightforward interpretation of historical data that must be analysed in the context of, for example, different years.
You can set your own data set using the \code{reference_data} argument. The \code{guideline} argument will then be ignored.

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 45 797 observations and 14 variables:
A \link[tibble:tibble]{tibble} with 40 217 observations and 14 variables:
\itemize{
\item \code{guideline}\cr Name of the guideline
\item \code{type}\cr Breakpoint type, either "ECOFF", "animal", or "human"
@@ -20,7 +20,7 @@ A \link[tibble:tibble]{tibble} with 45 797 observations and 14 variables:
\item \code{breakpoint_S}\cr Lowest MIC value or highest number of millimetres that leads to "S"
\item \code{breakpoint_R}\cr Highest MIC value or lowest number of millimetres that leads to "R", can be \code{NA}
\item \code{uti}\cr A \link{logical} value (\code{TRUE}/\code{FALSE}) to indicate whether the rule applies to a urinary tract infection (UTI)
\item \code{is_SDD}\cr A \link{logical} value (\code{TRUE}/\code{FALSE}) to indicate whether the intermediate range between "S" and "R" should be interpreted as "SDD", instead of "I". This currently applies to 72 breakpoints.
\item \code{is_SDD}\cr A \link{logical} value (\code{TRUE}/\code{FALSE}) to indicate whether the intermediate range between "S" and "R" should be interpreted as "SDD", instead of "I". This currently applies to 48 breakpoints.
}
}
\usage{
@@ -31,9 +31,9 @@ Data set containing clinical breakpoints to interpret MIC and disk diffusion to
These breakpoints are currently implemented:
\itemize{
\item For \strong{clinical microbiology}: EUCAST 2011-2026 and CLSI 2011-2026;
\item For \strong{veterinary microbiology}: EUCAST 2021-2026 and CLSI 2019-2026;
\item For \strong{ECOFFs} (Epidemiological Cut-off Values): EUCAST 2020-2026 and CLSI 2022-2026.
\item For \strong{clinical microbiology}: EUCAST 2011-2025 and CLSI 2011-2025;
\item For \strong{veterinary microbiology}: EUCAST 2021-2025 and CLSI 2019-2025;
\item For \strong{ECOFFs} (Epidemiological Cut-off Values): EUCAST 2020-2025 and CLSI 2022-2025.
}
Use \code{\link[=as.sir]{as.sir()}} to transform MICs or disks measurements to SIR values.

View File

@@ -3,9 +3,9 @@
\docType{data}
\name{microorganisms.codes}
\alias{microorganisms.codes}
\title{Data Set with 6 050 Common Microorganism Codes}
\title{Data Set with 6 036 Common Microorganism Codes}
\format{
A \link[tibble:tibble]{tibble} with 6 050 observations and 2 variables:
A \link[tibble:tibble]{tibble} with 6 036 observations and 2 variables:
\itemize{
\item \code{code}\cr Commonly used code of a microorganism. \emph{\strong{This is a unique identifier.}}
\item \code{mo}\cr ID of the microorganism in the \link{microorganisms} data set

View File

@@ -58,7 +58,7 @@ It has now created a file \code{"~/mo_source.rds"} with the contents of our Exce
And now we can use it in our functions:
\if{html}{\out{<div class="sourceCode">}}\preformatted{as.mo("lab_mo_ecoli")
#> Class <mo>
#> Class 'mo'
#> [1] B_ESCHR_COLI
mo_genus("lab_mo_kpneumoniae")
@@ -68,7 +68,7 @@ mo_genus("lab_mo_kpneumoniae")
as.mo(c("Escherichia coli", "E. coli", "lab_mo_ecoli"))
#> NOTE: Translation to one microorganism was guessed with uncertainty.
#> Use mo_uncertainties() to review it.
#> Class <mo>
#> Class 'mo'
#> [1] B_ESCHR_COLI B_ESCHR_COLI B_ESCHR_COLI
}\if{html}{\out{</div>}}
@@ -89,7 +89,7 @@ If we edit the Excel file by, let's say, adding row 4 like this:
#> NOTE: Updated mo_source file '/Users/me/mo_source.rds' (0.3 kB) from
#> '/Users/me/Documents/ourcodes.xlsx' (9 kB), columns
#> "Organisation XYZ" and "mo"
#> Class <mo>
#> Class 'mo'
#> [1] B_ESCHR_COLI
mo_genus("lab_Staph_aureus")

View File

@@ -201,7 +201,7 @@ This package contains more functions that extend the \code{ggplot2} package, to
The interpretation of "I" will be named "Increased exposure" for all EUCAST guidelines since 2019, and will be named "Intermediate" in all other cases.
For interpreting MIC values as well as disk diffusion diameters, the default guideline is EUCAST 2026, unless the package option \code{\link[=AMR-options]{AMR_guideline}} is set. See \code{\link[=as.sir]{as.sir()}} for more information.
For interpreting MIC values as well as disk diffusion diameters, the default guideline is EUCAST 2025, unless the package option \code{\link[=AMR-options]{AMR_guideline}} is set. See \code{\link[=as.sir]{as.sir()}} for more information.
}
}
\examples{

View File

@@ -219,6 +219,7 @@ test_that("test-eucast_rules.R", {
expect_inherits(eucast_dosage(c("tobra", "genta", "cipro")), "data.frame")
x <- custom_eucast_rules(
AMC == "R" & genus == "Klebsiella" ~ aminopenicillins == "R",
AMC == "I" & genus == "Klebsiella" ~ aminopenicillins == "I",

View File

@@ -272,6 +272,8 @@ test_that("test-mo.R", {
)
x <- as.mo("Sta. aur")
# many hits
expect_output(print(mo_uncertainties()))
# no viruses
expect_equal(suppressWarnings(as.mo("Virus")), as.mo("UNKNOWN"))

View File

@@ -120,7 +120,7 @@ test_that("test-sir.R", {
# allow for guideline length > 1
expect_equal(
AMR:::get_guideline(c("CLSI", "CLSI", "CLSI2023", "EUCAST", "EUCAST2020"), AMR::clinical_breakpoints),
c("CLSI 2026", "CLSI 2026", "CLSI 2023", "EUCAST 2026", "EUCAST 2020")
c("CLSI 2025", "CLSI 2025", "CLSI 2023", "EUCAST 2025", "EUCAST 2020")
)
# these are used in the script

View File

@@ -36,7 +36,6 @@ test_that("test-zzz.R", {
# functions used by import_fn()
import_functions <- c(
"%chin%" = "data.table",
"ansi_has_hyperlink_support" = "cli",
"anti_join" = "dplyr",
"as.data.table" = "data.table",
"as_tibble" = "tibble",
@@ -80,12 +79,6 @@ test_that("test-zzz.R", {
"freq.default" = "cleaner",
"percentage" = "cleaner",
# cli
"ansi_has_hyperlink_support" = "cli",
"cli_abort" = "cli",
"cli_inform" = "cli",
"cli_warn" = "cli",
"code_highlight" = "cli",
"format_inline" = "cli",
"symbol" = "cli",
# curl
"has_internet" = "curl",
@@ -131,8 +124,6 @@ test_that("test-zzz.R", {
"availableCores" = "parallelly",
# pillar
"pillar_shaft" = "pillar",
"style_na" = "pillar",
"style_subtle" = "pillar",
"tbl_format_footer" = "pillar",
"tbl_sum" = "pillar",
"type_sum" = "pillar",
@@ -170,9 +161,7 @@ test_that("test-zzz.R", {
"vec_math" = "vctrs",
"vec_ptype2" = "vctrs",
"vec_ptype_abbr" = "vctrs",
"vec_ptype_full" = "vctrs",
# usethis
"use_course" = "usethis"
"vec_ptype_full" = "vctrs"
)
import_functions <- c(import_functions, call_functions)