diff --git a/DESCRIPTION b/DESCRIPTION index d04216eb..83a80995 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: AMR -Version: 2.0.0.9033 -Date: 2023-07-10 +Version: 2.0.0.9034 +Date: 2023-07-11 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 diff --git a/NEWS.md b/NEWS.md index a01e4dbb..11b9b081 100755 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,4 @@ -# AMR 2.0.0.9033 +# AMR 2.0.0.9034 ## New * Clinical breakpoints and intrinsic resistance of EUCAST 2023 and CLSI 2023 have been added for `as.sir()`. EUCAST 2023 (v13.0) is now the new default guideline for all MIC and disks diffusion interpretations @@ -15,7 +15,7 @@ ## Changed * Updated algorithm of `as.mo()` by giving more weight to fungi * `mo_rank()` now returns `NA` for 'unknown' microorganisms (`B_ANAER`, `B_ANAER-NEG`, `B_ANAER-POS`, `B_GRAMN`, `B_GRAMP`, `F_FUNGUS`, `F_YEAST`, and `UNKNOWN`) -* When printing MO codes in a tibble, a mouse-hover now shows the full name of the microorganism +* When printing microorganism or antibiotic codes in a tibble, a mouse-hover now shows the full name of the code * Plots for MIC and disk diffusion values: * Now have settable arguments for breakpoint type and PK/PD, like `as.sir()` * Will now contain the name of the guideline table in the subtitle of the plot diff --git a/R/aa_helper_functions.R b/R/aa_helper_functions.R index 42692e1e..8fea58d6 100755 --- a/R/aa_helper_functions.R +++ b/R/aa_helper_functions.R @@ -501,8 +501,19 @@ word_wrap <- function(..., } # format backticks + if (pkg_is_available("cli") && + tryCatch(getExportedValue("isAvailable", ns = asNamespace("rstudioapi"))(), error = function(e) return(FALSE))) { + parts <- strsplit(msg, "`", fixed = TRUE)[[1]] + cmds <- parts %in% paste0(ls(envir = asNamespace("AMR")), "()") + # functions with a dot are not allowed: https://github.com/rstudio/rstudio/issues/11273#issuecomment-1156193252 + parts[cmds & parts %like% "[.]"] <- font_url(url = paste0("ide:help:AMR::", gsub("()", "", parts[cmds & parts %like% "[.]"], fixed = TRUE)), + txt = parts[cmds & parts %like% "[.]"]) + parts[cmds & parts %unlike% "[.]"] <- font_url(url = paste0("ide:run:AMR::", parts[cmds & parts %unlike% "[.]"]), + txt = parts[cmds & parts %unlike% "[.]"]) + msg <- paste0(parts, collapse = "`") + } msg <- gsub("`(.+?)`", font_grey_bg("\\1"), msg) - + # clean introduced whitespace between fullstops msg <- gsub("[.] +[.]", "..", msg) # remove extra space that was introduced (e.g. "Smith et al. , 2022") diff --git a/R/ab.R b/R/ab.R index fee9b68b..e302dbea 100755 --- a/R/ab.R +++ b/R/ab.R @@ -545,6 +545,13 @@ is.ab <- function(x) { pillar_shaft.ab <- function(x, ...) { out <- trimws(format(x)) out[is.na(x)] <- font_na(NA) + + # add the names to the drugs as mouse-over! + if (tryCatch(isTRUE(getExportedValue("ansi_has_hyperlink_support", ns = asNamespace("cli"))()), error = function(e) FALSE)) { + out[!is.na(x)] <- font_url(url = ab_name(x[!is.na(x)], language = NULL), + txt = out[!is.na(x)]) + } + create_pillar_column(out, align = "left", min_width = 4) } diff --git a/R/sir.R b/R/sir.R index 5956b4ee..15266d64 100755 --- a/R/sir.R +++ b/R/sir.R @@ -741,6 +741,10 @@ as_sir_method <- function(method_short, check_reference_data(reference_data, .call_depth = -2) meet_criteria(breakpoint_type, allow_class = "character", is_in = reference_data$type, has_length = 1, .call_depth = -2) + if (message_not_thrown_before("as.sir", "sir_interpretation_history")) { + message_("Run `sir_interpretation_history()` afterwards to retrieve a logbook with all the details of the breakpoint interpretations.\n\n") + } + # for dplyr's across() cur_column_dplyr <- import_fn("cur_column", "dplyr", error_on_fail = FALSE) if (!is.null(cur_column_dplyr) && tryCatch(is.data.frame(get_current_data("ab", call = 0)), error = function(e) FALSE)) { @@ -879,7 +883,7 @@ as_sir_method <- function(method_short, rise_warning <- FALSE rise_note <- FALSE method_coerced <- toupper(method) - ab_coerced <- ab + ab_coerced <- as.ab(ab) if (identical(reference_data, AMR::clinical_breakpoints)) { breakpoints <- reference_data %pm>% @@ -945,10 +949,10 @@ as_sir_method <- function(method_short, new_sir <- rep(NA_sir_, length(rows)) # find different mo properties, as fast as possible - mo_current_genus <- AMR_env$MO_lookup$mo[match(AMR_env$MO_lookup$genus[match(mo_current, AMR_env$MO_lookup$mo)], AMR_env$MO_lookup$genus)] - mo_current_family <- AMR_env$MO_lookup$mo[match(AMR_env$MO_lookup$family[match(mo_current, AMR_env$MO_lookup$mo)], AMR_env$MO_lookup$family)] - mo_current_order <- AMR_env$MO_lookup$mo[match(AMR_env$MO_lookup$order[match(mo_current, AMR_env$MO_lookup$mo)], AMR_env$MO_lookup$order)] - mo_current_class <- AMR_env$MO_lookup$mo[match(AMR_env$MO_lookup$class[match(mo_current, AMR_env$MO_lookup$mo)], AMR_env$MO_lookup$class)] + mo_current_genus <- AMR_env$MO_lookup$mo[match(AMR_env$MO_lookup$genus[match(mo_current, AMR_env$MO_lookup$mo)], AMR_env$MO_lookup$fullname)] + mo_current_family <- AMR_env$MO_lookup$mo[match(AMR_env$MO_lookup$family[match(mo_current, AMR_env$MO_lookup$mo)], AMR_env$MO_lookup$fullname)] + mo_current_order <- AMR_env$MO_lookup$mo[match(AMR_env$MO_lookup$order[match(mo_current, AMR_env$MO_lookup$mo)], AMR_env$MO_lookup$fullname)] + mo_current_class <- AMR_env$MO_lookup$mo[match(AMR_env$MO_lookup$class[match(mo_current, AMR_env$MO_lookup$mo)], AMR_env$MO_lookup$fullname)] mo_current_rank <- AMR_env$MO_lookup$rank[match(mo_current, AMR_env$MO_lookup$mo)] mo_current_name <- AMR_env$MO_lookup$fullname[match(mo_current, AMR_env$MO_lookup$mo)] if (mo_current %in% AMR::microorganisms.groups$mo) { @@ -1064,17 +1068,17 @@ as_sir_method <- function(method_short, data.frame( datetime = rep(Sys.time(), length(rows)), index = rows, - ab_input = rep(ab.bak, length(rows)), - ab_guideline = rep(ab_coerced, length(rows)), - mo_input = rep(mo.bak[match(mo_current, df$mo)][1], length(rows)), - mo_guideline = rep(breakpoints_current[, "mo", drop = TRUE], length(rows)), + ab_user = rep(ab.bak, length(rows)), + mo_user = rep(mo.bak[match(mo_current, df$mo)][1], length(rows)), + ab = rep(ab_coerced, length(rows)), + mo = rep(breakpoints_current[, "mo", drop = TRUE], length(rows)), + input = as.double(values), + outcome = as.sir(new_sir), + method = rep(method_coerced, length(rows)), + breakpoint_S_R = rep(paste0(breakpoints_current[, "breakpoint_S", drop = TRUE], "-", breakpoints_current[, "breakpoint_R", drop = TRUE]), length(rows)), guideline = rep(guideline_coerced, length(rows)), ref_table = rep(breakpoints_current[, "ref_tbl", drop = TRUE], length(rows)), uti = rep(breakpoints_current[, "uti", drop = TRUE], length(rows)), - method = rep(method_coerced, length(rows)), - input = as.double(values), - outcome = as.sir(new_sir), - breakpoint_S_R = rep(paste0(breakpoints_current[, "breakpoint_S", drop = TRUE], "-", breakpoints_current[, "breakpoint_R", drop = TRUE]), length(rows)), stringsAsFactors = FALSE ) ) @@ -1114,8 +1118,6 @@ sir_interpretation_history <- function(clean = FALSE) { message_("No results to return. Run `as.sir()` on MIC values or disk diffusion zones first to see a 'logbook' data set here.") return(invisible(NULL)) } - out$ab_guideline <- as.ab(out$ab_guideline) - out$mo_guideline <- as.mo(out$mo_guideline) out$outcome <- as.sir(out$outcome) # keep stored for next use if (isTRUE(clean)) { diff --git a/R/sysdata.rda b/R/sysdata.rda index f74fb9ad..974ea73b 100755 Binary files a/R/sysdata.rda and b/R/sysdata.rda differ diff --git a/R/zzz.R b/R/zzz.R index 8f53b25a..c1b76bb1 100755 --- a/R/zzz.R +++ b/R/zzz.R @@ -58,18 +58,19 @@ AMR_env$av_previously_coerced <- data.frame( AMR_env$sir_interpretation_history <- data.frame( datetime = Sys.time()[0], index = integer(0), - ab_input = character(0), - ab_guideline = set_clean_class(character(0), c("ab", "character")), - mo_input = character(0), - mo_guideline = set_clean_class(character(0), c("mo", "character")), - guideline = character(0), - ref_table = character(0), - method = character(0), + ab_user = character(0), + mo_user = character(0), + ab = set_clean_class(character(0), c("ab", "character")), + mo = set_clean_class(character(0), c("mo", "character")), input = double(0), outcome = NA_sir_[0], + method = character(0), breakpoint_S_R = character(0), + guideline = character(0), + ref_table = character(0), stringsAsFactors = FALSE ) + AMR_env$custom_ab_codes <- character(0) AMR_env$custom_mo_codes <- character(0) AMR_env$is_dark_theme <- NULL diff --git a/inst/tinytest/test-data.R b/inst/tinytest/test-data.R index f928d99a..e17711c4 100644 --- a/inst/tinytest/test-data.R +++ b/inst/tinytest/test-data.R @@ -38,6 +38,8 @@ expect_identical(class(antibiotics$ab), c("ab", "character")) # check cross table reference expect_true(all(microorganisms.codes$mo %in% microorganisms$mo)) expect_true(all(example_isolates$mo %in% microorganisms$mo)) +expect_true(all(microorganisms.groups$mo %in% microorganisms$mo)) +expect_true(all(microorganisms.groups$mo_group %in% microorganisms$mo)) expect_true(all(clinical_breakpoints$mo %in% microorganisms$mo)) expect_true(all(clinical_breakpoints$ab %in% antibiotics$ab)) expect_true(all(intrinsic_resistant$mo %in% microorganisms$mo)) diff --git a/inst/tinytest/test-sir.R b/inst/tinytest/test-sir.R index 887835c7..62606df1 100644 --- a/inst/tinytest/test-sir.R +++ b/inst/tinytest/test-sir.R @@ -108,6 +108,18 @@ if (AMR:::pkg_is_available("skimr", min_version = "2.0.0", also_load = TRUE)) { expect_equal(as.sir(c("", "-", NA, "NULL")), c(NA_sir_, NA_sir_, NA_sir_, NA_sir_)) +mics <- as.mic(2 ^ c(-2:5)) # 0.25 to 32 in factors of 2 +expect_identical(as.character(as.sir(mics, mo = "Enterobacterales", ab = "AMC", guideline = "EUCAST 2022", + uti = FALSE, include_PKPD = FALSE)), + c("S", "S", "S", "S", "S", "S", "R", "R")) +expect_identical(as.character(as.sir(mics, mo = "Enterobacterales", ab = "AMC", guideline = "EUCAST 2022", + uti = TRUE, include_PKPD = FALSE)), + c("S", "S", "S", "S", "S", "S", "S", "S")) +expect_identical(as.character(as.sir(mics, mo = "Escherichia coli", ab = "AMC", guideline = "EUCAST 2022", + uti = FALSE, include_PKPD = FALSE)), + c("S", "S", "S", "S", "S", "S", "R", "R")) + + # S. pneumoniae/ampicillin in EUCAST 2020: 0.5-2 ug/ml (R is only > 2) expect_equal(suppressMessages( as.character( diff --git a/man/AMR.Rd b/man/AMR.Rd index 48d89359..0f4b2845 100644 --- a/man/AMR.Rd +++ b/man/AMR.Rd @@ -32,7 +32,7 @@ The \code{AMR} package is a \href{https://msberends.github.io/AMR/#copyright}{fr This work was published in the Journal of Statistical Software (Volume 104(3); \doi{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://msberends.github.io/AMR/reference/microorganisms.html}{\strong{~52 000 microorganisms}} (updated december 2022) and all \href{https://msberends.github.io/AMR/reference/antibiotics.html}{\strong{~600 antibiotic, antimycotic 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 and EUCAST 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}, in collaboration with non-profit organisations \href{https://www.certe.nl}{Certe Medical Diagnostics and Advice Foundation} and \href{https://www.umcg.nl}{University Medical Center Groningen}. +After installing this package, R knows \href{https://msberends.github.io/AMR/reference/microorganisms.html}{\strong{~52 000 microorganisms}} (updated December 2022) and all \href{https://msberends.github.io/AMR/reference/antibiotics.html}{\strong{~600 antibiotic, antimycotic 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 and EUCAST 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}, in collaboration with non-profit organisations \href{https://www.certe.nl}{Certe Medical Diagnostics and Advice Foundation} and \href{https://www.umcg.nl}{University Medical Center Groningen}. The \code{AMR} package is available in English, Chinese, Czech, Danish, Dutch, Finnish, French, German, Greek, Italian, Japanese, Norwegian, Polish, Portuguese, Romanian, Russian, Spanish, Swedish, Turkish, and Ukrainian. Antimicrobial drug (group) names and colloquial microorganism names are provided in these languages. }