1
0
mirror of https://github.com/msberends/AMR.git synced 2025-02-22 23:50:04 +01:00

(v2.1.1.9152) MIC plot fix

This commit is contained in:
dr. M.S. (Matthijs) Berends 2025-02-18 08:07:02 +01:00
parent ef02f4a7f2
commit 671d657fd8
No known key found for this signature in database
11 changed files with 50 additions and 23 deletions

View File

@ -1,6 +1,6 @@
Package: AMR Package: AMR
Version: 2.1.1.9151 Version: 2.1.1.9152
Date: 2025-02-15 Date: 2025-02-18
Title: Antimicrobial Resistance Data Analysis Title: Antimicrobial Resistance Data Analysis
Description: Functions to simplify and standardise antimicrobial resistance (AMR) Description: Functions to simplify and standardise antimicrobial resistance (AMR)
data analysis and to work with microbial and antimicrobial properties by data analysis and to work with microbial and antimicrobial properties by

View File

@ -1,4 +1,4 @@
# AMR 2.1.1.9151 # AMR 2.1.1.9152
*(this beta version will eventually become v3.0. We're happy to reach a new major milestone soon, which will be all about the new One Health support! Install this beta using [the instructions here](https://msberends.github.io/AMR/#latest-development-version).)* *(this beta version will eventually become v3.0. We're happy to reach a new major milestone soon, which will be all about the new One Health support! Install this beta using [the instructions here](https://msberends.github.io/AMR/#latest-development-version).)*
@ -64,6 +64,7 @@ This package now supports not only tools for AMR data analysis in clinical setti
* Added Tigemonam (`TNM`), a monobactam * Added Tigemonam (`TNM`), a monobactam
* MICs * MICs
* Added as valid levels: 4096, 6 powers of 0.0625, and 5 powers of 192 (192, 384, 576, 768, 960) * Added as valid levels: 4096, 6 powers of 0.0625, and 5 powers of 192 (192, 384, 576, 768, 960)
* Fixed a bug in `as.mic()` that failed translation of scientifically formatted numbers
* Added new argument `keep_operators` to `as.mic()`. This can be `"all"` (default), `"none"`, or `"edges"`. This argument is also available in the new `rescale_mic()` and `scale_*_mic()` functions. * Added new argument `keep_operators` to `as.mic()`. This can be `"all"` (default), `"none"`, or `"edges"`. This argument is also available in the new `rescale_mic()` and `scale_*_mic()` functions.
* Comparisons of MIC values are now more strict. For example, `>32` is higher than (and never equal to) `32`. Thus, `as.mic(">32") == as.mic(32)` now returns `FALSE`, and `as.mic(">32") > as.mic(32)` now returns `TRUE`. * Comparisons of MIC values are now more strict. For example, `>32` is higher than (and never equal to) `32`. Thus, `as.mic(">32") == as.mic(32)` now returns `FALSE`, and `as.mic(">32") > as.mic(32)` now returns `TRUE`.
* Sorting of MIC values (using `sort()`) was fixed in the same manner; `<0.001` now gets sorted before `0.001`, and `>0.001` gets sorted after `0.001`. * Sorting of MIC values (using `sort()`) was fixed in the same manner; `<0.001` now gets sorted before `0.001`, and `>0.001` gets sorted after `0.001`.

View File

@ -1,6 +1,6 @@
Metadata-Version: 2.2 Metadata-Version: 2.2
Name: AMR Name: AMR
Version: 2.1.1.9151 Version: 2.1.1.9152
Summary: A Python wrapper for the AMR R package Summary: A Python wrapper for the AMR R package
Home-page: https://github.com/msberends/AMR Home-page: https://github.com/msberends/AMR
Author: Matthijs Berends Author: Matthijs Berends

Binary file not shown.

Binary file not shown.

View File

@ -2,7 +2,7 @@ from setuptools import setup, find_packages
setup( setup(
name='AMR', name='AMR',
version='2.1.1.9151', version='2.1.1.9152',
packages=find_packages(), packages=find_packages(),
install_requires=[ install_requires=[
'rpy2', 'rpy2',

28
R/mic.R
View File

@ -43,9 +43,14 @@ VALID_MIC_LEVELS <- c(t(vapply(FUN.VALUE = character(length(VALID_MIC_LEVELS)),
c("<", "<=", "", ">=", ">"), c("<", "<=", "", ">=", ">"),
paste0, paste0,
VALID_MIC_LEVELS))) VALID_MIC_LEVELS)))
COMMON_MIC_VALUES <- c(0.001, 0.002, 0.004, 0.008, 0.016, 0.032, 0.064, COMMON_MIC_VALUES <- c(0.0001, 0.0002, 0.0005,
0.125, 0.25, 0.5, 1, 2, 4, 8, 16, 32, 0.001, 0.002, 0.004, 0.008,
64, 128, 256, 512, 1024) 0.016, 0.032, 0.064,
0.125, 0.25, 0.5,
1, 2, 4, 8,
16, 32, 64,
128, 256, 512,
1024, 2048, 4096)
#' Transform Input to Minimum Inhibitory Concentrations (MIC) #' Transform Input to Minimum Inhibitory Concentrations (MIC)
#' #'
@ -158,7 +163,7 @@ as.mic <- function(x, na.rm = FALSE, keep_operators = "all") {
if (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 (!identical(levels(x), VALID_MIC_LEVELS)) { if (!identical(levels(x), VALID_MIC_LEVELS)) {
# from an older AMR version - just update MIC factor levels # might be from an older AMR version - just update MIC factor levels
x <- set_clean_class(factor(as.character(x), levels = VALID_MIC_LEVELS, ordered = TRUE), x <- set_clean_class(factor(as.character(x), levels = VALID_MIC_LEVELS, ordered = TRUE),
new_class = c("mic", "ordered", "factor")) new_class = c("mic", "ordered", "factor"))
} }
@ -184,20 +189,19 @@ as.mic <- function(x, na.rm = FALSE, keep_operators = "all") {
# comma to period # comma to period
x <- gsub(",", ".", x, fixed = TRUE) x <- gsub(",", ".", x, fixed = TRUE)
# transform scientific notation
x[x %like% "[-]?[0-9]+([.][0-9]+)?e[-]?[0-9]+"] <- as.double(x[x %like% "[-]?[0-9]+([.][0-9]+)?e[-]?[0-9]+"])
# transform Unicode for >= and <= # transform Unicode for >= and <=
x <- gsub("\u2264", "<=", x, fixed = TRUE) x <- gsub("\u2264", "<=", x, fixed = TRUE)
x <- gsub("\u2265", ">=", x, fixed = TRUE) x <- gsub("\u2265", ">=", x, fixed = TRUE)
# remove other invalid characters # remove other invalid characters
x <- gsub("[^a-zA-Z0-9.><= ]+", "", x, perl = TRUE) x <- gsub("[^a-zA-Z0-9.><= -]+", "", x, perl = TRUE)
# remove space between operator and number ("<= 0.002" -> "<=0.002")
x <- gsub("(<|=|>) +", "\\1", x, perl = TRUE)
# transform => to >= and =< to <= # transform => to >= and =< to <=
x <- gsub("=<", "<=", x, fixed = TRUE) x <- gsub("=<", "<=", x, fixed = TRUE)
x <- gsub("=>", ">=", x, fixed = TRUE) x <- gsub("=>", ">=", x, fixed = TRUE)
# Remove leading == and = # Remove leading == and =
x <- gsub("^=+", "", x) x <- gsub("^=+", "", x)
# retrieve signs and remove them from input
x_signs <- trimws(gsub("[^>=<]", "", x))
x <- trimws(gsub("[>=<]", "", x))
# dots without a leading zero must start with 0 # dots without a leading zero must start with 0
x <- gsub("([^0-9]|^)[.]", "\\10.", x, perl = TRUE) x <- gsub("([^0-9]|^)[.]", "\\10.", x, perl = TRUE)
# values like "<=0.2560.512" should be 0.512 # values like "<=0.2560.512" should be 0.512
@ -217,6 +221,12 @@ as.mic <- function(x, na.rm = FALSE, keep_operators = "all") {
x[x %like% "[.]"] <- gsub("0+$", "", x[x %like% "[.]"]) x[x %like% "[.]"] <- gsub("0+$", "", x[x %like% "[.]"])
# never end with dot # never end with dot
x <- gsub("[.]$", "", x, perl = TRUE) x <- gsub("[.]$", "", x, perl = TRUE)
# remove scientific notation
x[x %like% "[0-9]e[-]?[0-9]"] <- trimws(format(suppressWarnings(as.double(x[x %like% "[0-9]e[-]?[0-9]"])), scientific = FALSE))
# add signs again
x <- paste0(x_signs, x)
# remove NAs introduced by format()
x <- gsub("(NA)+", "", x)
# trim it # trim it
x <- trimws2(x) x <- trimws2(x)

View File

@ -237,20 +237,33 @@ create_scale_mic <- function(aest, keep_operators, mic_range = NULL, ...) {
"In `scale_", aest, "_mic()`, `limits` cannot be combined with `mic_range`, as they working identically. Use `mic_range` OR `limits`.", call = FALSE) "In `scale_", aest, "_mic()`, `limits` cannot be combined with `mic_range`, as they working identically. Use `mic_range` OR `limits`.", call = FALSE)
mic_range <- args$limits mic_range <- args$limits
} }
# do not take these arguments into account, as they will be overwritten and seem to allow weird behaviour # do not take these arguments into account, as they will be overwritten and seem to allow weird behaviour if set anyway
args[c("aesthetics", "trans", "transform", "transform_df", "breaks", "labels", "limits")] <- NULL args[c("aesthetics", "trans", "transform", "transform_df", "breaks", "labels", "limits")] <- NULL
scale <- do.call(ggplot_fn, args) scale <- do.call(ggplot_fn, args)
scale$transform <- function(x) { scale$transform <- function(x) {
as.double(rescale_mic(x = as.double(x), keep_operators = , "labels", mic_range = mic_range, as.mic = TRUE)) as.double(rescale_mic(x = as.double(x), keep_operators = keep_operators, mic_range = mic_range, as.mic = TRUE))
} }
scale$transform_df <- function(self, df) { scale$transform_df <- function(self, df) {
self$`.values_rescaled` <- rescale_mic(x = as.double(df[[aest]]), keep_operators = keep_operators, mic_range = mic_range, as.mic = TRUE) self$`.values_rescaled` <- rescale_mic(x = as.double(df[[aest]]), keep_operators = keep_operators, mic_range = mic_range, as.mic = TRUE)
self$`.values_levels` <- levels(rescale_mic(x = as.double(df[[aest]]), keep_operators = keep_operators, mic_range = mic_range, as.mic = FALSE))
if (length(self$`.values_levels`) > 6 & "0.025" %in% self$`.values_levels`) { # create new breaks and labels here
# TODO weird levelling out leading to 0.025 being redundant lims <- range(self$`.values_rescaled`)
self$`.values_levels` <- self$`.values_levels`[self$`.values_levels` != "0.025"] if (!is.na(mic_range[1]) && mic_range[1] < lims[1]) {
lims[1] <- mic_range[1]
} }
if (!is.na(mic_range[2]) && mic_range[2] > lims[2]) {
lims[2] <- mic_range[2]
}
ind_min <- which(COMMON_MIC_VALUES <= lims[1])[which.min(abs(COMMON_MIC_VALUES[COMMON_MIC_VALUES <= lims[1]] - lims[1]))] # Closest index where COMMON_MIC_VALUES <= lims[1]
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$`.values_levels` <- as.mic(COMMON_MIC_VALUES[ind_min:ind_max])
if (keep_operators %in% c("edges", "all") && length(self$`.values_levels`) > 1) {
self$`.values_levels`[1] <- paste0("<=", self$`.values_levels`[1])
self$`.values_levels`[length(self$`.values_levels`)] <- paste0(">=", self$`.values_levels`[length(self$`.values_levels`)])
}
self$`.values_log` <- log2(as.double(self$`.values_rescaled`)) self$`.values_log` <- log2(as.double(self$`.values_rescaled`))
if (aest == "y" && "group" %in% colnames(df)) { if (aest == "y" && "group" %in% colnames(df)) {
df$group <- as.integer(factor(df$x)) df$group <- as.integer(factor(df$x))

View File

@ -1,6 +1,6 @@
This knowledge base contains all context you must know about the AMR package for R. You are a GPT trained to be an assistant for the AMR package in R. You are an incredible R specialist, especially trained in this package and in the tidyverse. This knowledge base contains all context you must know about the AMR package for R. You are a GPT trained to be an assistant for the AMR package in R. You are an incredible R specialist, especially trained in this package and in the tidyverse.
First and foremost, you are trained on version 2.1.1.9151. Remember this whenever someone asks which AMR package version youre at. First and foremost, you are trained on version 2.1.1.9152. Remember this whenever someone asks which AMR package version youre at.
Below are the contents of the file, the file, and all the files (documentation) in the package. Every file content is split using 100 hypens. Below are the contents of the file, the file, and all the files (documentation) in the package. Every file content is split using 100 hypens.
---------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------

View File

@ -27,12 +27,15 @@
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ # # how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== # # ==================================================================== #
# used in multiple functions, also in plotting
expect_true(all(as.mic(COMMON_MIC_VALUES) %in% VALID_MIC_LEVELS))
expect_true(all(paste0("<=", as.mic(COMMON_MIC_VALUES)) %in% VALID_MIC_LEVELS))
expect_true(all(paste0(">=", as.mic(COMMON_MIC_VALUES)) %in% VALID_MIC_LEVELS))
expect_true(as.mic(8) == as.mic("8")) expect_true(as.mic(8) == as.mic("8"))
expect_true(as.mic("1") > as.mic("<=0.0625")) expect_true(as.mic("1") > as.mic("<=0.0625"))
expect_true(as.mic("1") < as.mic(">=32")) expect_true(as.mic("1") < as.mic(">=32"))
expect_true(is.mic(as.mic(8))) expect_true(is.mic(as.mic(8)))
# expect_true(as.mic(1024) < as.mic(">1024"))
# expect_true(as.mic("<1024") > as.mic("1024"))
expect_equal(as.double(as.mic(">=32")), 32) expect_equal(as.double(as.mic(">=32")), 32)