From 504a042fbafeafb53d9990293845d009853494b8 Mon Sep 17 00:00:00 2001 From: "Matthijs S. Berends" Date: Tue, 12 Mar 2019 12:19:27 +0100 Subject: [PATCH] uncertainty levels, new WHONET codes --- DESCRIPTION | 4 +- NEWS.md | 28 +- R/data.R | 2 +- R/like.R | 2 +- R/mo.R | 299 +++++++++++------- R/zzz.R | 35 +- data/microorganisms.codes.rda | Bin 24009 -> 26668 bytes docs/LICENSE-text.html | 2 +- docs/articles/benchmarks.html | 76 ++--- .../figure-html/unnamed-chunk-5-1.png | Bin 28565 -> 28781 bytes docs/articles/index.html | 2 +- docs/authors.html | 2 +- docs/index.html | 2 +- docs/news/index.html | 164 +++++----- docs/reference/as.mo.html | 32 +- docs/reference/filter_ab_class.html | 2 +- docs/reference/index.html | 2 +- docs/reference/like.html | 2 +- docs/reference/microorganisms.codes.html | 4 +- man/as.mo.Rd | 27 +- man/microorganisms.codes.Rd | 2 +- tests/testthat/test-mo.R | 5 +- 22 files changed, 402 insertions(+), 292 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 7c259842..b7a7e584 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: AMR -Version: 0.5.0.9021 -Date: 2019-03-09 +Version: 0.5.0.9022 +Date: 2019-03-12 Title: Antimicrobial Resistance Analysis Authors@R: c( person( diff --git a/NEWS.md b/NEWS.md index a8cedcf8..77b96a89 100755 --- a/NEWS.md +++ b/NEWS.md @@ -24,7 +24,7 @@ We've got a new website: [https://msberends.gitlab.io/AMR](https://msberends.git * Support for data from [WHONET](https://whonet.org/) and [EARS-Net](https://ecdc.europa.eu/en/about-us/partnerships-and-networks/disease-and-laboratory-networks/ears-net) (European Antimicrobial Resistance Surveillance Network): * Exported files from WHONET can be read and used in this package. For functions like `first_isolate()` and `eucast_rules()`, all parameters will be filled in automatically. * This package now knows all antibiotic abbrevations by EARS-Net (which are also being used by WHONET) - the `antibiotics` data set now contains a column `ears_net`. - * The function `as.mo()` now knows all WHONET species abbreviations too, because more than 1,600 microbial abbreviations were added to the `microorganisms.codes` data set. + * The function `as.mo()` now knows all WHONET species abbreviations too, because almost 2,000 microbial abbreviations were added to the `microorganisms.codes` data set. * New filters for antimicrobial classes. Use these functions to filter isolates on results in one of more antibiotics from a specific class: ```r filter_aminoglycosides() @@ -100,8 +100,29 @@ We've got a new website: [https://msberends.gitlab.io/AMR](https://msberends.git * Functions `atc_ddd()` and `atc_groups()` have been renamed `atc_online_ddd()` and `atc_online_groups()`. The old functions are deprecated and will be removed in a future version. * Function `guess_mo()` is now deprecated in favour of `as.mo()` and will be removed in future versions * Function `guess_atc()` is now deprecated in favour of `as.atc()` and will be removed in future versions -* Improvements for `as.mo()`:\ - * Incoercible results will now be considered 'unknown', MO code `UNKNOWN`. Properties of these will be translated on foreign systems in all language already previously supported: German, Dutch, French, Italian, Spanish and Portuguese: +* Improvements for `as.mo()`: + * Now handles incorrect spelling like `i` instead of `y` and `f` instead of `ph`: + ```r + # mo_fullname() uses as.mo() internally + + mo_fullname("Sthafilokockus aaureuz") + #> [1] "Staphylococcus aureus" + + mo_fullname("S. klossi") + #> [1] "Staphylococcus kloosii" + ``` + * Uncertainty of the algorithm is now divided into four levels, 0 to 3, where the default `allow_uncertain = TRUE` is equal to uncertainty level 2. Run `?as.mo` for more info about these levels. + ```r + # equal: + as.mo(..., allow_uncertain = TRUE) + as.mo(..., allow_uncertain = 2) + + # also equal: + as.mo(..., allow_uncertain = FALSE) + as.mo(..., allow_uncertain = 0) + ``` + Using `as.mo(..., allow_uncertain = 3)` could lead to very unreliable results. + * Incoercible results will now be considered 'unknown', MO code `UNKNOWN`. On foreign systems, properties of these will be translated to all languages already previously supported: German, Dutch, French, Italian, Spanish and Portuguese: ```r mo_genus("qwerty", language = "es") # Warning: @@ -164,6 +185,7 @@ We've got a new website: [https://msberends.gitlab.io/AMR](https://msberends.git * Automatic parameter filling for `mdro()`, `key_antibiotics()` and `eucast_rules()` * Updated examples for resistance prediction (`resistance_predict()` function) * Fix for `as.mic()` to support more values ending in (several) zeroes +* if using different lengths of pattern and x in `%like%`, it will now return the call #### Other * Updated licence text to emphasise GPL 2.0 and that this is an R package. diff --git a/R/data.R b/R/data.R index 3bfacf79..ace145ef 100755 --- a/R/data.R +++ b/R/data.R @@ -188,7 +188,7 @@ catalogue_of_life <- list( #' Translation table for microorganism codes #' #' A data set containing commonly used codes for microorganisms, from laboratory systems and WHONET. Define your own with \code{\link{set_mo_source}}. -#' @format A \code{\link{data.frame}} with 4,731 observations and 2 variables: +#' @format A \code{\link{data.frame}} with 5,171 observations and 2 variables: #' \describe{ #' \item{\code{certe}}{Commonly used code of a microorganism} #' \item{\code{mo}}{ID of the microorganism in the \code{\link{microorganisms}} data set} diff --git a/R/like.R b/R/like.R index 7e3f4d08..f606c986 100755 --- a/R/like.R +++ b/R/like.R @@ -56,7 +56,7 @@ like <- function(x, pattern) { if (length(pattern) > 1) { if (length(x) != length(pattern)) { pattern <- pattern[1] - warning('only the first element of argument `pattern` used for `%like%`', call. = FALSE) + warning('only the first element of argument `pattern` used for `%like%`', call. = TRUE) } else { # x and pattern are of same length, so items with each other res <- vector(length = length(pattern)) diff --git a/R/mo.R b/R/mo.R index 5cfc5b9b..953b6aac 100755 --- a/R/mo.R +++ b/R/mo.R @@ -21,7 +21,7 @@ #' Transform to microorganism ID #' -#' Use this function to determine a valid microorganism ID (\code{mo}). Determination is done using intelligent rules and the complete taxonomic kingdoms Archaea, Bacteria, Protozoa, Viruses and most microbial species from the kingdom Fungi (see Source), so the input can be almost anything: a full name (like \code{"Staphylococcus aureus"}), an abbreviated name (like \code{"S. aureus"}), an abbreviation known in the field (like \code{"MRSA"}), or just a genus. You could also \code{\link{select}} a genus and species column, zie Examples. +#' Use this function to determine a valid microorganism ID (\code{mo}). Determination is done using intelligent rules and the complete taxonomic kingdoms Bacteria, Chromista, Protozoa, Archaea, Viruses, and most microbial species from the kingdom Fungi (see Source). The input can be almost anything: a full name (like \code{"Staphylococcus aureus"}), an abbreviated name (like \code{"S. aureus"}), an abbreviation known in the field (like \code{"MRSA"}), or just a genus. Please see Examples. #' @param x a character vector or a \code{data.frame} with one or two columns #' @param Becker a logical to indicate whether \emph{Staphylococci} should be categorised into Coagulase Negative \emph{Staphylococci} ("CoNS") and Coagulase Positive \emph{Staphylococci} ("CoPS") instead of their own species, according to Karsten Becker \emph{et al.} [1]. #' @@ -29,7 +29,7 @@ #' @param Lancefield a logical to indicate whether beta-haemolytic \emph{Streptococci} should be categorised into Lancefield groups instead of their own species, according to Rebecca C. Lancefield [2]. These \emph{Streptococci} will be categorised in their first group, e.g. \emph{Streptococcus dysgalactiae} will be group C, although officially it was also categorised into groups G and L. #' #' This excludes \emph{Enterococci} at default (who are in group D), use \code{Lancefield = "all"} to also categorise all \emph{Enterococci} as group D. -#' @param allow_uncertain a logical to indicate whether the input should be checked for less possible results, see Details +#' @param allow_uncertain a logical (\code{TRUE} or \code{FALSE}) or a value between 0 and 3 to indicate whether the input should be checked for less possible results, see Details #' @param reference_df a \code{data.frame} to use for extra reference when translating \code{x} to a valid \code{mo}. See \code{\link{set_mo_source}} and \code{\link{get_mo_source}} to automate the usage of your own codes (e.g. used in your analysis or organisation). #' @rdname as.mo #' @aliases mo @@ -58,9 +58,9 @@ #' \strong{Intelligent rules} \cr #' This function uses intelligent rules to help getting fast and logical results. It tries to find matches in this order: #' \itemize{ -#' \item{Taxonomic kingdom: it first searches in Bacteria, then Fungi, then Protozoa} -#' \item{Human pathogenic prevalence: it first searches in more prevalent microorganisms, then less prevalent ones (see section \emph{Microbial prevalence of pathogens in humans})} #' \item{Valid MO codes and full names: it first searches in already valid MO code and known genus/species combinations} +#' \item{Human pathogenic prevalence: it first searches in more prevalent microorganisms, then less prevalent ones (see \emph{Microbial prevalence of pathogens in humans} below)} +#' \item{Taxonomic kingdom: it first searches in Bacteria/Chromista, then Fungi, then Protozoa, then Viruses} #' \item{Breakdown of input values: from here it starts to breakdown input values to find possible matches} #' } #' @@ -73,15 +73,19 @@ #' This means that looking up human pathogenic microorganisms takes less time than looking up human non-pathogenic microorganisms. #' #' \strong{Uncertain results} \cr -#' When using \code{allow_uncertain = TRUE} (which is the default setting), it will use additional rules if all previous rules failed to get valid results. These are: +#' The algorithm can additionally use three different levels of uncertainty to guess valid results. The default is \code{allow_uncertain = TRUE}, which is uqual to uncertainty level 2. Using \code{allow_uncertain = FALSE} will skip all of these additional rules: #' \itemize{ -#' \item{It tries to look for previously accepted (but now invalid) taxonomic names} -#' \item{It strips off values between brackets and the brackets itself, and re-evaluates the input with all previous rules} -#' \item{It strips off words from the end one by one and re-evaluates the input with all previous rules} -#' \item{It strips off words from the start one by one and re-evaluates the input with all previous rules} -#' \item{It tries to look for some manual changes which are not (yet) published to the Catalogue of Life (like \emph{Propionibacterium} being \emph{Cutibacterium})} +#' \item{(uncertainty level 1): It tries to look for only matching genera} +#' \item{(uncertainty level 1): It tries to look for previously accepted (but now invalid) taxonomic names} +#' \item{(uncertainty level 1): It tries to look for some manual changes which are not (yet) published to the Catalogue of Life (like \emph{Propionibacterium} being \emph{Cutibacterium})} +#' \item{(uncertainty level 2): It strips off values between brackets and the brackets itself, and re-evaluates the input with all previous rules} +#' \item{(uncertainty level 2): It strips off words from the end one by one and re-evaluates the input with all previous rules} +#' \item{(uncertainty level 3): It strips off words from the start one by one and re-evaluates the input with all previous rules} +#' \item{(uncertainty level 3): It tries any part of the name} #' } #' +#' You can also use e.g. \code{as.mo(..., allow_uncertain = 1)} to only allow up to level 1 uncertainty. +#' #' Examples: #' \itemize{ #' \item{\code{"Streptococcus group B (known as S. agalactiae)"}. The text between brackets will be removed and a warning will be thrown that the result \emph{Streptococcus group B} (\code{B_STRPT_GRB}) needs review.} @@ -96,7 +100,7 @@ #' Use \code{mo_renamed()} to get a vector with all values that could be coerced based on an old, previously accepted taxonomic name. #' #' \strong{Microbial prevalence of pathogens in humans} \cr -#' The intelligent rules takes into account microbial prevalence of pathogens in humans. It uses three groups and every (sub)species is in the group it matches first. These groups are: +#' The intelligent rules takes into account microbial prevalence of pathogens in humans. It uses three groups and all (sub)species are in only one group. These groups are: #' \itemize{ #' \item{1 (most prevalent): class is Gammaproteobacteria \strong{or} genus is one of: \emph{Enterococcus}, \emph{Staphylococcus}, \emph{Streptococcus}.} #' \item{2: phylum is one of: Proteobacteria, Firmicutes, Actinobacteria, Sarcomastigophora \strong{or} genus is one of: \emph{Aspergillus}, \emph{Bacteroides}, \emph{Candida}, \emph{Capnocytophaga}, \emph{Chryseobacterium}, \emph{Cryptococcus}, \emph{Elisabethkingia}, \emph{Flavobacterium}, \emph{Fusobacterium}, \emph{Giardia}, \emph{Leptotrichia}, \emph{Mycoplasma}, \emph{Prevotella}, \emph{Rhodotorula}, \emph{Treponema}, \emph{Trichophyton}, \emph{Ureaplasma}.} @@ -130,6 +134,7 @@ #' as.mo("S aureus") #' as.mo("Staphylococcus aureus") #' as.mo("Staphylococcus aureus (MRSA)") +#' as.mo("Sthafilokkockus aaureuz") # handles incorrect spelling #' as.mo("MRSA") # Methicillin Resistant S. aureus #' as.mo("VISA") # Vancomycin Intermediate S. aureus #' as.mo("VRSA") # Vancomycin Resistant S. aureus @@ -202,8 +207,8 @@ as.mo <- function(x, Becker = FALSE, Lancefield = FALSE, allow_uncertain = TRUE, ) } else if (all(x %in% AMR::microorganisms$mo) - & isFALSE(Becker) - & isFALSE(Lancefield)) { + & isFALSE(Becker) + & isFALSE(Lancefield)) { y <- x } else if (all(tolower(x) %in% microorganismsDT$fullname_lower) @@ -284,6 +289,15 @@ exec_as.mo <- function(x, Becker = FALSE, Lancefield = FALSE, fullname = character(0), mo = character(0)) failures <- character(0) + if (isTRUE(allow_uncertain)) { + # default to uncertainty level 2 + allow_uncertain <- 2 + } else { + allow_uncertain <- as.integer(allow_uncertain) + if (!allow_uncertain %in% c(0:3)) { + stop("`allow_uncertain` must be a number between 0 (none) and 3 (all), or TRUE (= 2) or FALSE (= 0).", call. = FALSE) + } + } x_input <- x # already strip leading and trailing spaces x <- trimws(x, which = "both") @@ -387,6 +401,7 @@ exec_as.mo <- function(x, Becker = FALSE, Lancefield = FALSE, # remove spp and species x <- trimws(gsub(" +(spp.?|ssp.?|sp.? |ss ?.?|subsp.?|subspecies|biovar |serovar |species)", " ", x_backup, ignore.case = TRUE), which = "both") + x_backup_without_spp <- x x_species <- paste(x, "species") # translate to English for supported languages of mo_property x <- gsub("(Gruppe|gruppe|groep|grupo|gruppo|groupe)", "group", x, ignore.case = TRUE) @@ -400,12 +415,21 @@ exec_as.mo <- function(x, Becker = FALSE, Lancefield = FALSE, x <- gsub("(alpha|beta|gamma) ha?emoly", "\\1-haemoly", x) # remove genus as first word x <- gsub("^Genus ", "", x) + # allow characters that resemble others + x <- gsub("[iy]+", "[iy]+", x, ignore.case = TRUE) + x <- gsub("[sz]+", "[sz]+", x, ignore.case = TRUE) + x <- gsub("(c|k|q|qu)+", "(c|k|q|qu)+", x, ignore.case = TRUE) + x <- gsub("(ph|f|v)+", "(ph|f|v)+", x, ignore.case = TRUE) + x <- gsub("(th|t)+", "(th|t)+", x, ignore.case = TRUE) + x <- gsub("a+", "a+", x, ignore.case = TRUE) + x <- gsub("e+", "e+", x, ignore.case = TRUE) + x <- gsub("o+", "o+", x, ignore.case = TRUE) # but spaces before and after should be omitted x <- trimws(x, which = "both") x_trimmed <- x x_trimmed_species <- paste(x_trimmed, "species") - x_trimmed_without_group <- gsub(" group$", "", x_trimmed, ignore.case = TRUE) + x_trimmed_without_group <- gsub(" gro.u.p$", "", x_trimmed, ignore.case = TRUE) # remove last part from "-" or "/" x_trimmed_without_group <- gsub("(.*)[-/].*", "\\1", x_trimmed_without_group) # replace space and dot by regex sign @@ -423,6 +447,7 @@ exec_as.mo <- function(x, Becker = FALSE, Lancefield = FALSE, # cat(paste0('x_withspaces_end_only "', x_withspaces_end_only, '"\n')) # cat(paste0('x_withspaces_start_end "', x_withspaces_start_end, '"\n')) # cat(paste0('x_backup "', x_backup, '"\n')) + # cat(paste0('x_backup_without_spp "', x_backup_without_spp, '"\n')) # cat(paste0('x_trimmed "', x_trimmed, '"\n')) # cat(paste0('x_trimmed_species "', x_trimmed_species, '"\n')) # cat(paste0('x_trimmed_without_group "', x_trimmed_without_group, '"\n')) @@ -440,12 +465,19 @@ exec_as.mo <- function(x, Becker = FALSE, Lancefield = FALSE, next } - if (any(x_trimmed[i] %in% c(NA, "", "xxx", "con"))) { + found <- microorganismsDT[fullname_lower %in% tolower(c(x_backup[i], x_backup_without_spp[i])), ..property][[1]] + # most probable: is exact match in fullname + if (length(found) > 0) { + x[i] <- found[1L] + next + } + + if (any(x_backup_without_spp[i] %in% c(NA, "", "xxx", "con"))) { x[i] <- NA_character_ next } - if (tolower(x_trimmed[i]) %in% c("other", "none", "unknown")) { + if (tolower(x_backup_without_spp[i]) %in% c("other", "none", "unknown")) { # empty and nonsense values, ignore without warning x[i] <- microorganismsDT[mo == "UNKNOWN", ..property][[1]] next @@ -472,7 +504,7 @@ exec_as.mo <- function(x, Becker = FALSE, Lancefield = FALSE, next } - if (x_trimmed[i] %like% "virus") { + if (x_backup_without_spp[i] %like% "virus") { # there is no fullname like virus, so don't try to coerce it x[i] <- microorganismsDT[mo == "UNKNOWN", ..property][[1]] failures <- c(failures, x_backup[i]) @@ -481,100 +513,100 @@ exec_as.mo <- function(x, Becker = FALSE, Lancefield = FALSE, # translate known trivial abbreviations to genus + species ---- if (!is.na(x_trimmed[i])) { - if (toupper(x_trimmed[i]) %in% c('MRSA', 'MSSA', 'VISA', 'VRSA')) { + if (toupper(x_backup_without_spp[i]) %in% c('MRSA', 'MSSA', 'VISA', 'VRSA')) { x[i] <- microorganismsDT[mo == 'B_STPHY_AUR', ..property][[1]][1L] next } - if (toupper(x_trimmed[i]) %in% c('MRSE', 'MSSE')) { + if (toupper(x_backup_without_spp[i]) %in% c('MRSE', 'MSSE')) { x[i] <- microorganismsDT[mo == 'B_STPHY_EPI', ..property][[1]][1L] next } - if (toupper(x_trimmed[i]) == "VRE" - | x_trimmed[i] %like% '(enterococci|enterokok|enterococo)[a-z]*?$') { + if (toupper(x_backup_without_spp[i]) == "VRE" + | x_backup_without_spp[i] %like% '(enterococci|enterokok|enterococo)[a-z]*?$') { x[i] <- microorganismsDT[mo == 'B_ENTRC', ..property][[1]][1L] next } - if (toupper(x_trimmed[i]) %in% c("EHEC", "EPEC", "EIEC", "STEC", "ATEC")) { + if (toupper(x_backup_without_spp[i]) %in% c("EHEC", "EPEC", "EIEC", "STEC", "ATEC")) { x[i] <- microorganismsDT[mo == 'B_ESCHR_COL', ..property][[1]][1L] next } - if (toupper(x_trimmed[i]) == 'MRPA') { + if (toupper(x_backup_without_spp[i]) == 'MRPA') { # multi resistant P. aeruginosa x[i] <- microorganismsDT[mo == 'B_PSDMN_AER', ..property][[1]][1L] next } - if (toupper(x_trimmed[i]) == 'CRS' - | toupper(x_trimmed[i]) == 'CRSM') { + if (toupper(x_backup_without_spp[i]) == 'CRS' + | toupper(x_backup_without_spp[i]) == 'CRSM') { # co-trim resistant S. maltophilia x[i] <- microorganismsDT[mo == 'B_STNTR_MAL', ..property][[1]][1L] next } - if (toupper(x_trimmed[i]) %in% c('PISP', 'PRSP', 'VISP', 'VRSP')) { + if (toupper(x_backup_without_spp[i]) %in% c('PISP', 'PRSP', 'VISP', 'VRSP')) { # peni I, peni R, vanco I, vanco R: S. pneumoniae x[i] <- microorganismsDT[mo == 'B_STRPT_PNE', ..property][[1]][1L] next } - if (x_trimmed[i] %like% '^G[ABCDFGHK]S$') { + if (x_backup_without_spp[i] %like% '^G[ABCDFGHK]S$') { # Streptococci, like GBS = Group B Streptococci (B_STRPT_GRB) - x[i] <- microorganismsDT[mo == gsub("G([ABCDFGHK])S", "B_STRPT_GR\\1", x_trimmed[i], ignore.case = TRUE), ..property][[1]][1L] + x[i] <- microorganismsDT[mo == gsub("G([ABCDFGHK])S", "B_STRPT_GR\\1", x_backup_without_spp[i], ignore.case = TRUE), ..property][[1]][1L] next } - if (x_trimmed[i] %like% '(streptococ|streptokok).* [ABCDFGHK]$') { + if (x_backup_without_spp[i] %like% '(streptococ|streptokok).* [ABCDFGHK]$') { # Streptococci in different languages, like "estreptococos grupo B" - x[i] <- microorganismsDT[mo == gsub(".*(streptococ|streptokok|estreptococ).* ([ABCDFGHK])$", "B_STRPT_GR\\2", x_trimmed[i], ignore.case = TRUE), ..property][[1]][1L] + x[i] <- microorganismsDT[mo == gsub(".*(streptococ|streptokok|estreptococ).* ([ABCDFGHK])$", "B_STRPT_GR\\2", x_backup_without_spp[i], ignore.case = TRUE), ..property][[1]][1L] next } - if (x_trimmed[i] %like% 'group [ABCDFGHK] (streptococ|streptokok|estreptococ)') { + if (x_backup_without_spp[i] %like% 'group [ABCDFGHK] (streptococ|streptokok|estreptococ)') { # Streptococci in different languages, like "Group A Streptococci" - x[i] <- microorganismsDT[mo == gsub(".*group ([ABCDFGHK]) (streptococ|streptokok|estreptococ).*", "B_STRPT_GR\\1", x_trimmed[i], ignore.case = TRUE), ..property][[1]][1L] + x[i] <- microorganismsDT[mo == gsub(".*group ([ABCDFGHK]) (streptococ|streptokok|estreptococ).*", "B_STRPT_GR\\1", x_backup_without_spp[i], ignore.case = TRUE), ..property][[1]][1L] next } # CoNS/CoPS in different languages (support for German, Dutch, Spanish, Portuguese) ---- - if (x[i] %like% '[ck]oagulas[ea] negatie?[vf]' + if (x_backup_without_spp[i] %like% '[ck]oagulas[ea] negatie?[vf]' | x_trimmed[i] %like% '[ck]oagulas[ea] negatie?[vf]' - | x[i] %like% '[ck]o?ns[^a-z]?$') { + | x_backup_without_spp[i] %like% '[ck]o?ns[^a-z]?$') { # coerce S. coagulase negative x[i] <- microorganismsDT[mo == 'B_STPHY_CNS', ..property][[1]][1L] next } - if (x[i] %like% '[ck]oagulas[ea] positie?[vf]' + if (x_backup_without_spp[i] %like% '[ck]oagulas[ea] positie?[vf]' | x_trimmed[i] %like% '[ck]oagulas[ea] positie?[vf]' - | x[i] %like% '[ck]o?ps[^a-z]?$') { + | x_backup_without_spp[i] %like% '[ck]o?ps[^a-z]?$') { # coerce S. coagulase positive x[i] <- microorganismsDT[mo == 'B_STPHY_CPS', ..property][[1]][1L] next } - if (x[i] %like% 'gram[ -]?neg.*' + if (x_backup_without_spp[i] %like% 'gram[ -]?neg.*' | x_trimmed[i] %like% 'gram[ -]?neg.*') { - # coerce S. coagulase positive + # coerce Gram negatives x[i] <- microorganismsDT[mo == 'B_GRAMN', ..property][[1]][1L] next } - if (x[i] %like% 'gram[ -]?pos.*' + if (x_backup_without_spp[i] %like% 'gram[ -]?pos.*' | x_trimmed[i] %like% 'gram[ -]?pos.*') { - # coerce S. coagulase positive + # coerce Gram positives x[i] <- microorganismsDT[mo == 'B_GRAMP', ..property][[1]][1L] next } - if (grepl("[sS]almonella [A-Z][a-z]+ ?.*", x_trimmed[i], ignore.case = FALSE)) { - if (x_trimmed[i] %like% "Salmonella group") { + if (grepl("[sS]almonella [A-Z][a-z]+ ?.*", x_backup_without_spp[i], ignore.case = FALSE)) { + if (x_backup_without_spp[i] %like% "Salmonella group") { # Salmonella Group A to Z, just return S. species for now x[i] <- microorganismsDT[mo == 'B_SLMNL', ..property][[1]][1L] - notes <- c(notes, - magenta(paste0("Note: ", - italic("Salmonella"), " ", trimws(gsub("Salmonella", "", x_trimmed[i])), - " was considered ", - italic("Salmonella species"), - " (B_SLMNL)"))) + options(mo_renamed = c(getOption("mo_renamed"), + magenta(paste0("Note: ", + italic("Salmonella"), " ", trimws(gsub("Salmonella", "", x_backup_without_spp[i])), + " was considered ", + italic("Salmonella species"), + " (B_SLMNL)")))) } else { # Salmonella with capital letter species like "Salmonella Goettingen" - they're all S. enterica x[i] <- microorganismsDT[mo == 'B_SLMNL_ENT', ..property][[1]][1L] - notes <- c(notes, - magenta(paste0("Note: ", - italic("Salmonella"), " ", trimws(gsub("Salmonella", "", x_trimmed[i])), - " was considered a subspecies of ", - italic("Salmonella enterica"), - " (B_SLMNL_ENT)"))) + options(mo_renamed = c(getOption("mo_renamed"), + magenta(paste0("Note: ", + italic("Salmonella"), " ", trimws(gsub("Salmonella", "", x_backup_without_spp[i])), + " was considered a subspecies of ", + italic("Salmonella enterica"), + " (B_SLMNL_ENT)")))) } next } @@ -588,8 +620,8 @@ exec_as.mo <- function(x, Becker = FALSE, Lancefield = FALSE, x[i] <- found[1L] next } - if (nchar(x_trimmed[i]) >= 6) { - found <- microorganismsDT[fullname_lower %like% paste0(x_withspaces_start_only[i], "[a-z]+ species"), ..property][[1]] + if (nchar(x_backup_without_spp[i]) >= 6) { + found <- microorganismsDT[fullname_lower %like% paste0("^", x_backup_without_spp[i], "[a-z]+"), ..property][[1]] if (length(found) > 0) { x[i] <- found[1L] next @@ -621,7 +653,7 @@ exec_as.mo <- function(x, Becker = FALSE, Lancefield = FALSE, } # allow no codes less than 4 characters long, was already checked for WHONET above - if (nchar(x_trimmed[i]) < 4) { + if (nchar(x_backup_without_spp[i]) < 4) { x[i] <- microorganismsDT[mo == "UNKNOWN", ..property][[1]] failures <- c(failures, x_backup[i]) next @@ -633,22 +665,23 @@ exec_as.mo <- function(x, Becker = FALSE, Lancefield = FALSE, c.x_trimmed_without_group, d.x_withspaces_start_end, e.x_withspaces_start_only, - f.x_withspaces_end_only) { + f.x_withspaces_end_only, + g.x_backup_without_spp) { - found <- data_to_check[fullname_lower %in% tolower(c(a.x_backup, b.x_trimmed)), ..property][[1]] - # most probable: is exact match in fullname + # try probable: trimmed version of fullname ---- + found <- data_to_check[fullname_lower %in% tolower(g.x_backup_without_spp), ..property][[1]] if (length(found) > 0) { return(found[1L]) } - - found <- data_to_check[fullname_lower == tolower(c.x_trimmed_without_group), ..property][[1]] - if (length(found) > 0) { + found <- data_to_check[fullname_lower %like% b.x_trimmed + | fullname_lower %like% c.x_trimmed_without_group, ..property][[1]] + if (length(found) > 0 & nchar(g.x_backup_without_spp) >= 6) { return(found[1L]) } # try any match keeping spaces ---- found <- data_to_check[fullname %like% d.x_withspaces_start_end, ..property][[1]] - if (length(found) > 0 & nchar(b.x_trimmed) >= 6) { + if (length(found) > 0 & nchar(g.x_backup_without_spp) >= 6) { return(found[1L]) } @@ -658,7 +691,7 @@ exec_as.mo <- function(x, Becker = FALSE, Lancefield = FALSE, return(found[1L]) } found <- data_to_check[fullname %like% e.x_withspaces_start_only, ..property][[1]] - if (length(found) > 0 & nchar(b.x_trimmed) >= 6) { + if (length(found) > 0 & nchar(g.x_backup_without_spp) >= 6) { return(found[1L]) } @@ -671,12 +704,12 @@ exec_as.mo <- function(x, Becker = FALSE, Lancefield = FALSE, # try splitting of characters in the middle and then find ID ---- # only when text length is 6 or lower # like esco = E. coli, klpn = K. pneumoniae, stau = S. aureus, staaur = S. aureus - if (nchar(b.x_trimmed) <= 6) { - x_length <- nchar(b.x_trimmed) + if (nchar(g.x_backup_without_spp) <= 6) { + x_length <- nchar(g.x_backup_without_spp) x_split <- paste0("^", - b.x_trimmed %>% substr(1, x_length / 2), + g.x_backup_without_spp %>% substr(1, x_length / 2), '.* ', - b.x_trimmed %>% substr((x_length / 2) + 1, x_length)) + g.x_backup_without_spp %>% substr((x_length / 2) + 1, x_length)) found <- data_to_check[fullname %like% x_split, ..property][[1]] if (length(found) > 0) { return(found[1L]) @@ -701,7 +734,8 @@ exec_as.mo <- function(x, Becker = FALSE, Lancefield = FALSE, c.x_trimmed_without_group = x_trimmed_without_group[i], d.x_withspaces_start_end = x_withspaces_start_end[i], e.x_withspaces_start_only = x_withspaces_start_only[i], - f.x_withspaces_end_only = x_withspaces_end_only[i]) + f.x_withspaces_end_only = x_withspaces_end_only[i], + g.x_backup_without_spp = x_backup_without_spp[i]) if (!empty_result(x[i])) { next } @@ -712,7 +746,8 @@ exec_as.mo <- function(x, Becker = FALSE, Lancefield = FALSE, c.x_trimmed_without_group = x_trimmed_without_group[i], d.x_withspaces_start_end = x_withspaces_start_end[i], e.x_withspaces_start_only = x_withspaces_start_only[i], - f.x_withspaces_end_only = x_withspaces_end_only[i]) + f.x_withspaces_end_only = x_withspaces_end_only[i], + g.x_backup_without_spp = x_backup_without_spp[i]) if (!empty_result(x[i])) { next } @@ -723,7 +758,8 @@ exec_as.mo <- function(x, Becker = FALSE, Lancefield = FALSE, c.x_trimmed_without_group = x_trimmed_without_group[i], d.x_withspaces_start_end = x_withspaces_start_end[i], e.x_withspaces_start_only = x_withspaces_start_only[i], - f.x_withspaces_end_only = x_withspaces_end_only[i]) + f.x_withspaces_end_only = x_withspaces_end_only[i], + g.x_backup_without_spp = x_backup_without_spp[i]) if (!empty_result(x[i])) { next } @@ -752,31 +788,23 @@ exec_as.mo <- function(x, Becker = FALSE, Lancefield = FALSE, } # check for uncertain results ---- - if (allow_uncertain == TRUE) { + uncertain_fn <- function(a.x_backup, +b.x_trimmed, + c.x_withspaces_start_end, +d.x_withspaces_start_only, + f.x_withspaces_end_only, +g.x_backup_without_spp) { - uncertain_fn <- function(a.x_backup, b.x_trimmed, c.x_withspaces_start_end, d.x_withspaces_start_only, f.x_withspaces_end_only) { + if (allow_uncertain == 0) { + # do not allow uncertainties + return(NA_character_) + } - # (1) look for genus only, part of name ---- - if (nchar(b.x_trimmed) > 4 & !b.x_trimmed %like% " ") { - if (!grepl("^[A-Z][a-z]+", b.x_trimmed, ignore.case = FALSE)) { - # not when input is like Genustext, because then Neospora would lead to Actinokineospora - found <- microorganismsDT[fullname_lower %like% paste(b.x_trimmed, "species"), ..property][[1]] - if (length(found) > 0) { - x[i] <- found[1L] - uncertainties <<- rbind(uncertainties, - data.frame(uncertainty = 2, - input = a.x_backup, - fullname = microorganismsDT[mo == found[1L], fullname][[1]], - mo = found[1L])) - return(x) - } - } - } - - # (2) look again for old taxonomic names, now for G. species ---- + if (allow_uncertain >= 1) { + # (1) look again for old taxonomic names, now for G. species ---- found <- microorganisms.oldDT[fullname %like% c.x_withspaces_start_end | fullname %like% d.x_withspaces_start_only] - if (NROW(found) > 0 & nchar(b.x_trimmed) >= 6) { + if (NROW(found) > 0 & nchar(g.x_backup_without_spp) >= 6) { if (property == "ref") { # when property is "ref" (which is the case in mo_ref, mo_authors and mo_year), return the old value, so: # mo_ref("Chlamydia psittaci) = "Page, 1968" (with warning) @@ -798,7 +826,7 @@ exec_as.mo <- function(x, Becker = FALSE, Lancefield = FALSE, return(x) } - # (3) not yet implemented taxonomic changes in Catalogue of Life ---- + # (2) not yet implemented taxonomic changes in Catalogue of Life ---- found <- suppressMessages(suppressWarnings(exec_as.mo(TEMPORARY_TAXONOMY(b.x_trimmed), clear_options = FALSE, allow_uncertain = FALSE))) if (!empty_result(found)) { found_result <- found @@ -810,12 +838,31 @@ exec_as.mo <- function(x, Becker = FALSE, Lancefield = FALSE, mo = found_result[1L])) return(found[1L]) } + } + + if (allow_uncertain >= 2) { + # (3) look for genus only, part of name ---- + if (nchar(g.x_backup_without_spp) > 4 & !b.x_trimmed %like% " ") { + if (!grepl("^[A-Z][a-z]+", b.x_trimmed, ignore.case = FALSE)) { + # not when input is like Genustext, because then Neospora would lead to Actinokineospora + found <- microorganismsDT[fullname_lower %like% paste(b.x_trimmed, "species"), ..property][[1]] + if (length(found) > 0) { + x[i] <- found[1L] + uncertainties <<- rbind(uncertainties, + data.frame(uncertainty = 2, + input = a.x_backup, + fullname = microorganismsDT[mo == found[1L], fullname][[1]], + mo = found[1L])) + return(x) + } + } + } # (4) strip values between brackets ---- a.x_backup_stripped <- gsub("( *[(].*[)] *)", " ", a.x_backup) a.x_backup_stripped <- trimws(gsub(" +", " ", a.x_backup_stripped)) found <- suppressMessages(suppressWarnings(exec_as.mo(a.x_backup_stripped, clear_options = FALSE, allow_uncertain = FALSE))) - if (!empty_result(found) & nchar(b.x_trimmed) >= 6) { + if (!empty_result(found) & nchar(g.x_backup_without_spp) >= 6) { found_result <- found found <- microorganismsDT[mo == found, ..property][[1]] uncertainties <<- rbind(uncertainties, @@ -828,26 +875,30 @@ exec_as.mo <- function(x, Becker = FALSE, Lancefield = FALSE, # (5) try to strip off one element from end and check the remains ---- x_strip <- a.x_backup %>% strsplit(" ") %>% unlist() - if (length(x_strip) > 1 & nchar(b.x_trimmed) >= 6) { + if (length(x_strip) > 1) { for (i in 1:(length(x_strip) - 1)) { x_strip_collapsed <- paste(x_strip[1:(length(x_strip) - i)], collapse = " ") - found <- suppressMessages(suppressWarnings(exec_as.mo(x_strip_collapsed, clear_options = FALSE, allow_uncertain = FALSE))) - if (!empty_result(found)) { - found_result <- found - found <- microorganismsDT[mo == found, ..property][[1]] - uncertainties <<- rbind(uncertainties, - data.frame(uncertainty = 2, - input = a.x_backup, - fullname = microorganismsDT[mo == found_result[1L], fullname][[1]], - mo = found_result[1L])) - return(found[1L]) + if (nchar(x_strip_collapsed) >= 4) { + found <- suppressMessages(suppressWarnings(exec_as.mo(x_strip_collapsed, clear_options = FALSE, allow_uncertain = FALSE))) + if (!empty_result(found)) { + found_result <- found + found <- microorganismsDT[mo == found, ..property][[1]] + uncertainties <<- rbind(uncertainties, + data.frame(uncertainty = 2, + input = a.x_backup, + fullname = microorganismsDT[mo == found_result[1L], fullname][[1]], + mo = found_result[1L])) + return(found[1L]) + } } } } + } + if (allow_uncertain >= 3) { # (6) try to strip off one element from start and check the remains ---- x_strip <- a.x_backup %>% strsplit(" ") %>% unlist() - if (length(x_strip) > 1 & nchar(b.x_trimmed) >= 6) { + if (length(x_strip) > 1 & nchar(g.x_backup_without_spp) >= 6) { for (i in 2:(length(x_strip))) { x_strip_collapsed <- paste(x_strip[i:length(x_strip)], collapse = " ") found <- suppressMessages(suppressWarnings(exec_as.mo(x_strip_collapsed, clear_options = FALSE, allow_uncertain = FALSE))) @@ -868,7 +919,7 @@ exec_as.mo <- function(x, Becker = FALSE, Lancefield = FALSE, found <- microorganismsDT[fullname %like% f.x_withspaces_end_only] if (nrow(found) > 0) { found_result <- found[["mo"]] - if (!empty_result(found_result)) { + if (!empty_result(found_result) & nchar(g.x_backup_without_spp) >= 6) { found <- microorganismsDT[mo == found_result[1L], ..property][[1]] uncertainties <<- rbind(uncertainties, data.frame(uncertainty = 3, @@ -878,16 +929,21 @@ exec_as.mo <- function(x, Becker = FALSE, Lancefield = FALSE, return(found[1L]) } } - - # didn't found in uncertain results too - return(NA_character_) } - x[i] <- uncertain_fn(x_backup[i], x_trimmed[i], x_withspaces_start_end[i], x_withspaces_start_only[i], x_withspaces_end_only[i]) - if (!empty_result(x[i])) { - next - } + # didn't found in uncertain results too + return(NA_character_) } + x[i] <- uncertain_fn(x_backup[i], + x_trimmed[i], + x_withspaces_start_end[i], + x_withspaces_start_only[i], + x_withspaces_end_only[i], + x_backup_without_spp[i]) + if (!empty_result(x[i])) { + next + } + # not found ---- x[i] <- microorganismsDT[mo == "UNKNOWN", ..property][[1]] @@ -899,19 +955,19 @@ exec_as.mo <- function(x, Becker = FALSE, Lancefield = FALSE, failures <- failures[!failures %in% c(NA, NULL, NaN)] if (length(failures) > 0 & clear_options == TRUE) { options(mo_failures = sort(unique(failures))) - plural <- c("value", "it", "is") + plural <- c("value", "it", "was") if (n_distinct(failures) > 1) { - plural <- c("values", "them", "are") + plural <- c("values", "them", "were") } total_failures <- length(x_input[x_input %in% failures & !x_input %in% c(NA, NULL, NaN)]) total_n <- length(x_input[!x_input %in% c(NA, NULL, NaN)]) - msg <- paste0("\n", nr2char(n_distinct(failures)), " unique ", plural[1], + msg <- paste0(nr2char(n_distinct(failures)), " unique ", plural[1], " (^= ", percent(total_failures / total_n, round = 1, force_zero = TRUE), ") could not be coerced and ", plural[3], " considered 'unknown'") if (n_distinct(failures) <= 10) { msg <- paste0(msg, ": ", paste('"', unique(failures), '"', sep = "", collapse = ', ')) } - msg <- paste0(msg, ". Use mo_failures() to review ", plural[2], ".") + msg <- paste0(msg, ". Use mo_failures() to review ", plural[2], ". Edit the `allow_uncertain` parameter if needed (see ?as.mo).") warning(red(msg), call. = FALSE, immediate. = TRUE) # thus will always be shown, even if >= warnings @@ -1026,7 +1082,7 @@ exec_as.mo <- function(x, Becker = FALSE, Lancefield = FALSE, } empty_result <- function(x) { - x %in% c(NA, "UNKNOWN") + all(x %in% c(NA, "UNKNOWN")) } TEMPORARY_TAXONOMY <- function(x) { @@ -1124,6 +1180,9 @@ mo_uncertainties <- function() { #' @export #' @noRd print.mo_uncertainties <- function(x, ...) { + if (NROW(x) == 0) { + return(NULL) + } cat(paste0(bold(nrow(x), "unique result(s) guessed with uncertainty:"), "\n(1 = ", green("renamed"), ", 2 = ", yellow("uncertain"), diff --git a/R/zzz.R b/R/zzz.R index 78dccdcf..6d4a87df 100755 --- a/R/zzz.R +++ b/R/zzz.R @@ -25,28 +25,25 @@ backports::import(pkgname) # register data - if (!all(c("microorganismsDT", "microorganisms.oldDT") %in% ls(envir = asNamespace("AMR")))) { + microorganisms.oldDT <- as.data.table(AMR::microorganisms.old) + microorganisms.oldDT$fullname_lower <- tolower(microorganisms.oldDT$fullname) + setkey(microorganisms.oldDT, col_id, fullname) - microorganisms.oldDT <- as.data.table(AMR::microorganisms.old) - microorganisms.oldDT$fullname_lower <- tolower(microorganisms.oldDT$fullname) - setkey(microorganisms.oldDT, col_id, fullname) + assign(x = "microorganisms", + value = make(), + envir = asNamespace("AMR")) - assign(x = "microorganisms", - value = make(), - envir = asNamespace("AMR")) + assign(x = "microorganismsDT", + value = make_DT(), + envir = asNamespace("AMR")) - assign(x = "microorganismsDT", - value = make_DT(), - envir = asNamespace("AMR")) + assign(x = "microorganisms.oldDT", + value = microorganisms.oldDT, + envir = asNamespace("AMR")) - assign(x = "microorganisms.oldDT", - value = microorganisms.oldDT, - envir = asNamespace("AMR")) - - assign(x = "mo_codes_v0.5.0", - value = make_trans_tbl(), - envir = asNamespace("AMR")) - } + assign(x = "mo_codes_v0.5.0", + value = make_trans_tbl(), + envir = asNamespace("AMR")) } #' @importFrom dplyr mutate case_when @@ -88,8 +85,8 @@ make_DT <- function() { microorganismsDT <- as.data.table(make()) microorganismsDT$fullname_lower <- tolower(microorganismsDT$fullname) setkey(microorganismsDT, - kingdom, prevalence, + kingdom, fullname) microorganismsDT } diff --git a/data/microorganisms.codes.rda b/data/microorganisms.codes.rda index e5254a13174244e0b239c7ef7ba07372f196fd03..8b7b005eb92bbd2be744b5ec00ef1b359e81d187 100644 GIT binary patch literal 26668 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 HCY(peZHw!9 literal 24009 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 A>i_@% diff --git a/docs/LICENSE-text.html b/docs/LICENSE-text.html index f4aca6a7..5e593eff 100644 --- a/docs/LICENSE-text.html +++ b/docs/LICENSE-text.html @@ -78,7 +78,7 @@ AMR (for R) - 0.5.0.9021 + 0.5.0.9022 diff --git a/docs/articles/benchmarks.html b/docs/articles/benchmarks.html index 6848bcaa..9f9c9b39 100644 --- a/docs/articles/benchmarks.html +++ b/docs/articles/benchmarks.html @@ -40,7 +40,7 @@ AMR (for R) - 0.5.0.9021 + 0.5.0.9022 @@ -192,7 +192,7 @@

Benchmarks

Matthijs S. Berends

-

09 March 2019

+

12 March 2019

@@ -217,14 +217,14 @@ times = 10) print(S.aureus, unit = "ms", signif = 3) #> Unit: milliseconds -#> expr min lq mean median uq max neval -#> as.mo("sau") 16.60 16.60 25.2 16.80 18.00 58.3 10 -#> as.mo("stau") 31.60 31.80 44.8 32.40 72.20 76.7 10 -#> as.mo("staaur") 16.60 16.60 26.4 16.70 17.30 71.9 10 -#> as.mo("STAAUR") 16.50 16.60 16.6 16.60 16.70 16.8 10 -#> as.mo("S. aureus") 24.50 24.60 29.0 24.70 25.00 66.6 10 -#> as.mo("S. aureus") 24.30 24.60 24.6 24.60 24.70 24.9 10 -#> as.mo("Staphylococcus aureus") 7.45 7.47 11.9 7.53 7.97 50.0 10 +#> expr min lq mean median uq max neval +#> as.mo("sau") 16.70 16.8 25.70 17.00 19.60 59.7 10 +#> as.mo("stau") 39.10 39.2 43.70 39.30 40.60 80.4 10 +#> as.mo("staaur") 16.70 16.8 24.60 17.00 18.20 58.9 10 +#> as.mo("STAAUR") 16.70 16.7 22.70 16.80 17.20 74.5 10 +#> as.mo("S. aureus") 29.70 29.7 46.70 29.80 71.30 110.0 10 +#> as.mo("S. aureus") 29.60 29.7 36.10 29.70 33.10 83.7 10 +#> as.mo("Staphylococcus aureus") 7.03 7.1 7.14 7.14 7.17 7.3 10

In the table above, all measurements are shown in milliseconds (thousands of seconds). A value of 5 milliseconds means it can determine 200 input values per second. It case of 100 milliseconds, this is only 10 input values per second. The second input is the only one that has to be looked up thoroughly. All the others are known codes (the first one is a WHONET code) or common laboratory codes, or common full organism names like the last one. Full organism names are always preferred.

To achieve this speed, the as.mo function also takes into account the prevalence of human pathogenic microorganisms. The downside is of course that less prevalent microorganisms will be determined less fast. See this example for the ID of Thermus islandicus (B_THERMS_ISL), a bug probably never found before in humans:

-

That takes 7.8 times as much time on average. A value of 100 milliseconds means it can only determine ~10 different input values per second. We can conclude that looking up arbitrary codes of less prevalent microorganisms is the worst way to go, in terms of calculation performance. Full names (like Thermus islandicus) are almost fast - these are the most probable input from most data sets.

+#> expr min lq mean median uq max neval +#> as.mo("theisl") 417.0 419.0 450.0 460.0 464.0 474 10 +#> as.mo("THEISL") 415.0 416.0 443.0 458.0 460.0 468 10 +#> as.mo("T. islandicus") 281.0 281.0 299.0 285.0 325.0 352 10 +#> as.mo("T. islandicus") 292.0 298.0 341.0 336.0 340.0 495 10 +#> as.mo("Thermus islandicus") 66.2 66.5 75.5 66.9 68.2 112 10 +

That takes 10.9 times as much time on average. A value of 100 milliseconds means it can only determine ~10 different input values per second. We can conclude that looking up arbitrary codes of less prevalent microorganisms is the worst way to go, in terms of calculation performance. Full names (like Thermus islandicus) are almost fast - these are the most probable input from most data sets.

In the figure below, we compare Escherichia coli (which is very common) with Prevotella brevis (which is moderately common) and with Thermus islandicus (which is very uncommon):

par(mar = c(5, 16, 4, 2)) # set more space for left margin text (16)
 
@@ -286,9 +286,9 @@
                          times = 10)
 print(run_it, unit = "ms", signif = 3)
 #> Unit: milliseconds
-#>            expr min  lq mean median  uq max neval
-#>  mo_fullname(x) 734 810  840    817 860 973    10
-

So transforming 500,000 values (!!) of 50 unique values only takes 0.82 seconds (817 ms). You only lose time on your unique input values.

+#> expr min lq mean median uq max neval +#> mo_fullname(x) 794 834 863 844 876 1050 10 +

So transforming 500,000 values (!!) of 50 unique values only takes 0.84 seconds (844 ms). You only lose time on your unique input values.

+#> A 10.900 11.100 11.200 11.200 11.300 11.400 10 +#> B 27.300 27.900 28.300 28.000 28.100 31.500 10 +#> C 0.319 0.326 0.472 0.563 0.568 0.579 10

So going from mo_fullname("Staphylococcus aureus") to "Staphylococcus aureus" takes 0.0006 seconds - it doesn’t even start calculating if the result would be the same as the expected resulting value. That goes for all helper functions:

+#> A 0.308 0.332 0.396 0.393 0.457 0.498 10 +#> B 0.349 0.376 0.419 0.444 0.462 0.467 10 +#> C 0.351 0.398 0.529 0.555 0.628 0.702 10 +#> D 0.302 0.330 0.378 0.381 0.424 0.465 10 +#> E 0.282 0.329 0.371 0.374 0.384 0.539 10 +#> F 0.281 0.354 0.364 0.366 0.402 0.444 10 +#> G 0.275 0.309 0.347 0.351 0.380 0.420 10 +#> H 0.279 0.306 0.356 0.363 0.404 0.411 10

Of course, when running mo_phylum("Firmicutes") the function has zero knowledge about the actual microorganism, namely S. aureus. But since the result would be "Firmicutes" too, there is no point in calculating the result. And because this package ‘knows’ all phyla of all known bacteria (according to the Catalogue of Life), it can just return the initial value immediately.

+#> en 16.61 17.17 17.23 17.28 17.38 17.56 10 +#> de 28.83 28.85 29.31 29.50 29.63 29.67 10 +#> nl 29.08 29.44 33.71 29.65 29.72 71.15 10 +#> es 28.86 29.52 38.07 29.70 30.60 72.14 10 +#> it 28.71 29.48 34.04 29.63 31.28 71.09 10 +#> fr 29.32 29.47 41.44 29.53 62.86 73.16 10 +#> pt 29.05 29.43 33.93 29.62 30.93 71.00 10

Currently supported are German, Dutch, Spanish, Italian, French and Portuguese.

diff --git a/docs/articles/benchmarks_files/figure-html/unnamed-chunk-5-1.png b/docs/articles/benchmarks_files/figure-html/unnamed-chunk-5-1.png index a6412a798cca5cac189aa7e58cb5fb38b1aaf306..22db0a14018333c66f04b9d57411c88afdd5f27e 100644 GIT binary patch literal 28781 zcmeFZbyQqWv?iJahaka&LvVMOH16&iAVA~p-XXyP1eYLh=@o?NXW>@C@3hXsHkXY zXiuL$MMp=+z`(%7#KgkFdiLxYHa0d64h}9ZE*>5pK0ZDH0RbT);q&LuiHL}ZiHS)_ zNJvRZ$;ima$;l}wC@3i@si>%4ym&!PO-(~XLrY6bM@L6bPtU->z{tqR#KgqR%*?{V z!ph3Z#>U3Z&d$NX!O6+V#l^+V&CSEZ!^_Ld$H&Ld&o3Y#ASfs(BqSs(EG!}-A}T5> zCMNds4qobp%tE;D{r?0PXU|?WqXlP_)WNd6~Vq)^@)hkm| zQ!_I&b93|8uU}hOSXf$GT3J~Efk10(Ya1IITU%Q@J3D)Odj|&xM@L5|CnslTXBQV2 zS65dzH#c{8cMlH_Pft%TFE4LzZyz5YUteE8KRL!RODP3kwU2ii(Phi%UvMN=r-2%F4>i%fEd2Qc+P+Sy@?CRaISGT~kw2TU%RK zS65$O-_X#|*x1Fw?9>+9?9?;jW#7#tjgKp;ayL&L+vBO@cDqoZSEW8>rF6B84Ylao_Z zQ`6JaGcz-@v$Jz^bMy1_3kwUse*IcpTwGdOT3%jWSy@?KU0qvSTVG$_*x1wJUlu&IzB#zLZK%oC#R>UXJ=>U=jRs}7nhfpS65fp z*Vi{UH@CO9cXxM7UyS@=a{$FjR?qd(Bht|OpT{w)hZc_>Q9P291ZaAt?_{8);C9Z1 z26FjUA${pZcljJNyWv9tl7+<{XsI*%Gd#*?dU{mkoG|)Ox-J}?#13Mbd6OiH&yi3))%>tQvhkS=A-)&fm5S=4u!jos@48tz~3xZ5bnnV2KN(*fhbx zt|i%E6v~cVRY(Zdk{Ufw9QlwQmzy%g3l}vF_7W~vB{%E zZNy)E^+OfX;h2JeK5LAFt_G<=Mv{03q7C>i56O1tfnXsRMgD0`6F`7RKtMjD$pt+i z0)~Ogr1%Lrak&qPi@@Ez#N_TewUvzTrA}`b$dl)9Hx^E3B+p-W?s}GAoA~Wz2i{mr zfjWC9c7{2hMt>=zbpADFfku8Ojiz?=%O11asOtKnC7H~)@ztU~lRW0M+xi@x!^bvh z*`2%}>uk(TH%a+{*E2eaylPJm$=Yr(%Spoql{jhj>D19|)Oh5CXzjYX&DdwXb&AJ( zr$I3DUr0l~NuS{QG_|%}hvSTB+G1YmRHxmB2i6p%%QvmaNI-trTCD&_XyzOg^>cF@ zi?2Vub4lcCOC~Y~r$fjuKxC&;YNffy?9acORBjBs*v;>NryP(o7>ig>jwHUz7&nZG zb6wKP(tRIcd@+=}qWSf`3A%55lw38A@*91f8k==enq^awt+zeSJI=hK7%}aKO*Z7c zk@sWWfqEHq`S{v+#>fZvsUrQz(O8U2=RVY*6e{>_Z8<7&IBr}Oq2&zMUZpqYE&0{f zY7)@79KdXK%T^|oNKkZxYnB03BIYp>G&MF5kf{ewDkp(jQGhFHD; z&+F1`UEh8Wxi0EY_r7b@SX+fRKfA0Wf?8Xw3(71n-~Qvd?f@XGcyIPYX}}JVb^H^8 zB43}5rk9c@8%PydE4l!K@eSbo$aMW7agCbZ%WTjK{Vnx+kxxR?m`;XNgc(qK1DZ3$ zhK)p<)JuD!{9Y7aK(|YF6-W4H$Osr;Yj^sBLtOMrf zv`G3#2X$Lw68!OY6L-I6A%9D{mA}-pNWN9ubG!M*HMTg~_IM$}NIRKq6q|i{FXrV<2P^!^pHs zaDmJ4`hqSdidB(*12RcxVq7xbjaXogy&LlV-ozOJ17%MQv)k9B?v;m|OP5V)6iEcx z;P8bnx=3>ej$5r_3^Q=6JfujCJ;ZZ~M$3Y}6{N!@M$O*I z6PGg**QH$Dq*ks+r~G<;_ujF*H!y)~t-5<`r{_y`>P-d%Sj(!r*#2!Is}?^Ij`<%W zlr5M9{9BrHW75es?fe?4!_)uO0P(*WXw?%?n$BWyJXKe?Eg@W`^_IAyztfuHk(`Rd zKi$(A2pUmBtS-$)yCgsA!nH6jX|7P3s_&ZJ_wUKvvYE^zEEVv^cz?b2z! ze?1YP=|kw7XN|QlL=<0`^b7}~=5yNT3;~x*I;h3KS}T6t)(Jn|VJ& zO*=;~HfV8tJ-lk9FTo6cBMPBy%&-mOMLXAAZxT?edJU&I4 z|9)Ll6I!6xPQrI!PS9XExr)G!QAvIstKqMM)A>(SUx}rZG26A9ROzIAbzzo4&E zf1{}CvHM<|ljTWmc{WO8RHapL<+{7Kd2(g8u_AL*1w|_#0pXhou6Y6=E>vFPwoRPl zu^{1DrPkYW0Jeba4S*aX7UYgd@@eFqDFC2$|pujlM0yk zvGJ@4L%)fWIWl`zN1bW6zjXyAK8oci!q@3Fm;99{bmqeYREBY|xq?&kLYT&pn;Azm z0Vlf@RCTx+$LvzHZ}ZLA2MhKYqWA&HV;Z&j#6L;~W43x%&G!9LaBt}81m4tse%3N( zAdOe;(!eYY;i_R>sRK?`zRd_So6!)k&N3Zrd-pc#YMAe%3{58&u$V)R^0%KzXse|J zZ=W9(H!5~5p4VTL(eC6U-OtT1oN6$$d^{b$Lh+HBGAEJ|Iv|;$4j5|X7+-rjg+gE3 zqP-8KK2k&ZG=?#*PkLf7+_G@Av$bkH>6w z%sNA~==Z$?C<4Kjgt(}zg`zt0L#%)fVw<^q6R*|tMC%5AJFu6327Yh=8reg;;){}~ zRW@f%c3$W(xvg!)VS7v+VS}u1WYHwf;E^l=K+9rKKx2n~cqN`{Au`k~;a=FdGtrDO z{WT>Ido;%e7hDL3(=4SJtS5#}C+Dt}2 z-m)rME2^Wwd;$njVN&(b@(gZ1e2%^R^?PsFg(Gw8t4>#l-QBe>hI+=m_hqfJ#O{{& zf}j7;Dw+yRI4R(DGdenpqVdE;$$#iLi*d70Oba3gu#`j|igI^7I1-nM6_R|GBvIlC) z=fWFX$UgZTTT!P^IITpAwBrU6k-Eu;yzz5$H23(wsVWANRe$G@WB9D4HRC}&KYW~n zhD;h06S;4*WbA`}zi?H7C9M3P&)t}=*SBo#QiqH7pxos|XrYIK@YiIn_>b4&VJ)+$ zZ7cDiT^bgPp?}sEb^2sn@;y+U68ryDm%ZlV(l9(9ZeVaIApQrb&=7PU__eZxK zU{+vu6nd4l-2y{PMEMemrclIs#8<{BFHOp~1^KMe3qbhB+GN1+Oh@EG6#cgFWyHm- zDwU{PrNk0bN8M-`j9RR9VZ75{7POHuk5gCOF5=z&!K{8fLCghn!}f27qX3NNn+}mW z=73-2S$RiiYZ&&r&igEpWEV}VzlRdxlQib4>F!S67N^ z8dAL1o3&TQJQ)@`7K(9*H58p5>V)Kc3uBC(MF=ofvi0Pr^1BwCguF)xO0q^lpt5)v zVHriB-w;IkA9?V9In4hAyDRkeURHdwCT^*LG5E-RLc7yT!2_#hZ8_v(IW_&@FHqyV{NU||v2kf#>6LB5|& zp71wg3!IPBx5Z&k9_E)Pya+b7kztsmY!m>t2)_@i9A?==M!F~-(_WZqKa9iwhd|ES*ljyCNWF`--pnB_s%Z>6B z*A1)})K}_~gA50sO+r|_LXPkvNn7c06?i#~IL7iSJv8^>6Taz-@lN@iXQKo8_`QC} zn;$g|9uZaWhoS_qDvlHFGC@r+S*z;#T(9{+mf2Lg6YEi+3rX~Y1sLp2t{k#TX$Uu! zzPl*}nac<_p08S$op`7=Fip-!wuOqHAFYq62v=p>?eY|OZn_*H9Fqr}&h>10#KDuI z3br#p&eV>tVcw7x;%4$B8t?}s&&^587odCB5k2OM8At+!Jav^&TEANoSCI?K28;AI z9V68Z{IubHHM9pb-b^4v*nCTR*{`Sb%)m=Xm07cla8kJG`-;7Kmkf^J8ZL$*9*f%P zj{|MJ6Co82{?BMG+`*bgko=Jt+w{zZlO?NOJ7Rf3Bo^d}PX|%I8o_NsWc*7dhiyN_ zfq=ZCL+#fuO3zaDx*B|k#&*R#vx}+gRUyU}VYdQ~2SsUksrVuyGq?u&*wD&$qng5rJwa=JE~siwU^7Rn0sE&T)Dn%-f5r$>Ev&<67rov!x89;Ny|$Kt@`of{4=u zPjVn8^cEm5@)2dWZ1g#5$k%rRp0pAcq~5#Fjh8okx^UXELHP+p5~2LODtT!Ybvw=upa zNDAkGhg1X*j96%oTa)6EI!E>$^E+I?4T6a`SP-YSbekuWr3PU}mR3!;yLc3Q9&uxp z*{?mZB>>PhctNtjpkRYJlf+GrITfp2aPoJZ%o z$H!)_B}6XN8wl+%$kdjU#@}lMIQ#bT-Hz+QIwSl{SQ&`h`9%e4Cy?I3J-N0Jg&BNe&x`o|=60c>b)JFxgV_RFt24>k3d=+|Ko-ZetYR~1H4@XhZRL8`1- zT1S`TF^3+@gusO8YxAvm&*1qL{g={zH+pTPl zlz(9yt}=mBjiCbcbp<6zjZ-zdb{Ln$U}w8%3yEm>8*b|E)P}Z6NnUB%eFJq(KpTbI zu#Ccz%dF1ZSH<~}nX!rtueu@$W0Q=tS-yLddb7GE!Q-J$7c(pHrE_A$S5Y0mMgYI+ zn>oy1b%!t(NDkWWKS@F!W^=lrtN-?~{cw2OU>Z*nEghwC6v}tQObi>^_292R4H7n2 z{G^PZKpCP4vgGH3vAL8tV^!3UkiwL3Us zXXLgZ{E&TzZ4;H-*_fE7ebz#7E?sX9pUMYgsTPk)+qnvGQ`ed2EJ^!QEpk25NxF1V=+n=76L1 z4ty2njq>0%A2s_mQ)0+y*-4SI^F!NbkK*GV+V&(^WYb^EZmn;WAKL34Y6@YoJ|gLE zKyG2%v1SQvqfNgl{nI>ctRnXiE2{|B3t)JD&U14%5gPnzw_S(OT3=qLw^04qUM zHCRaGv~N*m7gEZAT9r+BGH{a-ScF08Rte1}1L92UDq~zOp9x!P(I$E+C0@1-HvRmm zjP6{8=1&t08z@>|^kYmoMNsr8l9^PTE@XI%Z+BWJ?@jGxX~E4xwTD-3PpWqBP9M6! zGicbxaQy3f7NDu1(;CyA$oZ;KsjBW+%=f_Q?5|4XpU>8j~@!`D2SLL#2- zMv!ke2t{ft)9R~ULZJpFNPP`&ZFgkd!C;XH;MCC3_jlT>)*xdpmzv6UR!)(yJ~sIYqdHoE!hO@3V3cP z5MW11K3X{tEkt2OJ=r#LBo0}BG6fCyeUrub&oI&N8|x(1b=D%M+WTsE(bm1~0~lt_ z=H)36-H0ltX{TW}Iw`*V4ym;D*6Pr?$HP= zc6J40E$3iur}vwM`9u|-*o^rl@GLt-*#ws@_shD-Q_AjQQhFdZAw6)gGQh3457Fq8 zKP?c1Un|O9CS&TO9SQKXj_Gz|1!nIonzC@AMW@<%y}A>eWEpm623CC3Xyle<+7LBO ztmT}URdoUE_jO=xi{Pt5sM%E^fHipT8UvuGmmX>YKda&cDnd$44(_&T!o*&+hs=0e z{{{~bD1eTwWW@i8?shXbg3=Q>1XAEUrtczdV+rYiLN@>JM|PPhXR`L50Ib$@zWpZL zh$cqhy2e5XNx(hXo5gjTFI%BODdhQcm%M_2QYdnN^V_}u{Ojy9C=YDeICG=KrsP4q zPvQ!J@G&yA3=MaJ+vp_1MDDYktSD(%`}Ya{|7?)B$N;!g*Kf?Py?VLDdfzh{HuUT8 z{L78OnmKfJtNWzM!3S_#(jBwH$n+j!Vbwis{Qcej^RHeikTyS^8B$7jSPA7EeIMl# zxoR>EK3z&O(}a#s40UAte6+ zoNlwCeQ3~9#x)J1NPsg>yv}`HOwsar-NKfIX}lS{?88mge=2~f@DPdW*agOfFs7T^tvg-{dCw6?Bx#OWn!oTBPpe@n_jmYs_SLb$Q4Qi$NqXr3N~tv9?SIou=Fs%$F>ycWPodU;ngqqU?!ztPx({mYuinhppcd{WJ$BXSLj zu9m2BDM)N#*+4=~e13}-P^$j}ozygM%sw*u!!o+>V7@4h7yvMVu|GgQD@a#76(rS^ z>z%LRgPTX-vB76$BxPr+my*bY$UC^l?)@?0a3~~N;4PevltO|CXS0^}&49*yl%+dh zfX!yu7{V4w?tjc&Jv*PhTENpQXtpEv-aFRnUEM$jzP0c7#5q*1H1uZQHnQUvEw}nw z2SWlI=Ms?w)lT-+DsqRF;9iwyb!agTnTRWnMe-d}96r)X&^BJHnEkBq11bU`Wxpo~ zModqK#DdX{wW_E_#CTuolAL!gMxG!&U*Cl-DXTQV3b7aDh zjWX>Aqy;3eg4ObWJ;g-3#Q(+XKCwOp%yMat$#bks`q9is5|ASzj=Y*PBu7ZOZ;*;V z|4Y3t-0|LpRGJ=@o67CrJr~B|C(msYGLY`B{q3yPqD|k&YoqS(pr&Vy-)eB^3E=T- z&-;T#AO@lazPvc~Mul9sy18Rwjt7br*T23-CMvxF@8h*mREK{^IStD8&0D#l47tlb z%g*Bdid~2${piJNH=GvpBmG{w-6fPWo0?14c6Nbm)afP2k`J{@oO3ia$2^`JHPZJJ ze;S6qX&?z(CWn=0ciaev#$;j?H;0#(kw5*hA|JR-VUD&n7*u94fUt6$L;8*(+>6@u zRAYcmC-P@=`RWSb5PD_6P(cDLQ??L;=hn1*`|**G{WmFu8ws>un%k$*n&r+$#it5A z+u*g*$CtJvE6I-o6O73pbrtKqsP2s~0^^XT4M@K79u`NP$Ac;$6FbyzzUHY#nZm(u zL!bj6);hJc3_~J8d+!?fUh0*eyBdeZ@Sqdny0ILiQe;U7U_vXHUi@^64S4Z-pS%g;P}pjsx5AU6GtmXRlv0OY~nwrg>s~F=o2L zb4r3XGU0gl=zLdsPOqw1hAKFey%|=pG@-Y8r*D&!F#&Hhsf-8ZC$XON#v%GdxaX)| zP0X=}aM7XH|5poeLA=Xlz3sVi$95u3Idh!{6+rj85H(XL~wOvUsxG> zI7~i*cM+S*XdMyBa7{2Q;AU!as)Bm+CscxRcZhiB<-+vFccoO?LK#iqhH*oEJO~-Y z0o6|a?%DHt?eQ*4m|M@J3iz=}(gyzW0zNqqDR1kzPoAPURL11{KyqxVS^eq~3b#Xh z`W1)XtRMwKX0UmHq`AeJR!@x%HU<60^x{aklH1(-IM*au1#aoNmWpqNx(Vi1EOW${ z5y3*iLhu(PwSTz*K_JOYjXjoIs8tDS*lrDk&yrDxxK2h#@lHrN+1q6=a#~WF?WKQ5 zs7EaO*X&JU^zYEp;HyZb*XFN5FGKO9AkU|^t}ocrUrkh8zJrBv_+OWM1iR>&j zQs3F+_aN41YNA^*Fb09F+>nExn#|yc_ugBmwfe9tRwKx9bj7G0`_SSA zM2qc`)~OkKndE^m^h6C}rI^OOd8CIqIeYbG4tSQ|u1Hf}kai462al}GR*L7zxl$Sg z@jlB3xAqO(LfkTu5NGz@cQ&~~COQ;t3^xu;1Jva6fmMeeYc?nyS}5(KIzAIPrBz<> z-v~0JpyImOe<4CPX}0MVJxn+`44mFf0mu( z#<8%4J%eH!LG;Nx5Mu&Hf_z$q_4ICpRjy;p@ZZmWHuD7v!uSV{2V;aMLJRtNQ)@Y= z%Ev8dMGKMFU{CGKb@cog3-Z_UOxbt*h5;Wt*}7D}0_p@GR%PO+@MJpij#3CL>aEUd z73bkuI0nKMU@1B7iAWm_k{RslQfoR;w6b&GZ~=d{s2xHCv(1eL1Eutxcz?KeTE%#&TSBqeS7=fa1!LWxYd2D9 zX^)3vGfPW`raWn|&;ZyNiQH>_FI zP-H;7%vET+VcXxoY^aO9;Df8m567_Y&(edeNsK&yW|R>JTdDQE*h8SMcdd>iCDO{{ z_-Ply2B?J609|h>3Gke)7}@nwG(HfT{n3c76_&6@U>yFC&8p{%LJQD|$lAT(5Rij! zApth%{KSrbD?cYUWYK%bk6rDN+w=65tRMM2#Nj|2GB8^A4zl*@87DN}F&^9>`e}s7 zv_K`~v=aO_*=1CrAX}jr*V*7>y}}ngJ)4}fi8A+(=ZL6{yjUzk`kBRsi3KP={XfQf z7^{EyDZSMg8GhFjP7O+OIN4)TaS_hSSHUd_X-*oC&;@LlN`|+L2|+#l$U_!ievR)j z?EI=#u&FY(4QGg+UPz#UVDAj1t$j>4?KTlofWVSqGQx{s=$0cgaoQl`;O7D>=Yg1e@2V(XKl#dO+`^*-Z+F;tOL%`0e;RN@!_6E6(qP>F$^R z24&h+@8u_`Ry{rVl9YR;|DrqWaa(btEBeo z*M}qCjom-A$;fl_jk5BctQ^a6$gLj@-ETbao_zLQRNyVEZRoK&z4CADYkE(nj>O4+ z^?DzxUuaOy6?6>xwZ$|b0E9sOl^~QdLt0W*x zb!Lvj9sk}cOcZ^rJyzD+e$1LVls_CM0gO^8_g`bz68`Fb^7vCEqb&*;yMr;jSu-M= zFf_w|ZkG&6^bGw^m%A9^u2(cdRg~SO*59I6p^Ct4Bak3hRZ@G!|GH z%n&93`|mcP?%&fEce{@QkZG-6koiqIx41~}u!N~LEY2f$Mehd{HBB??_~8AoX8@C! z8T&J}2O5}nd0$mS#^o*)h5gXpQ?4TS5eVn1$j=6JFYq*=&yS=l0yjbfa{p#t8uQCF zZ2`5A#~@XV_jn<@_<>n2B~nH)Xwy!T*vmt9S;swpnj#ZhGtG%BItI;?bVUs?{rP*J z-_?T+yEFR4%XSo-BeKYzdzytajt7_t^^{HrcMi(kszm>NUw>zylY-}YIafHDto1x^ z1QV!?^-u=K}?Dl)=BJ-BuT}_W2=XLqJTayKWI>1?jnC>7TSy`;i*(YEkGK(d?))^`5v9c3C2W-?}Bj=tx#O*9U4pYBF!WG$C1^S zV_4MxMI;i@X{7b7M?w0c9I8+d+3 z(`}3b{=SxoXKp(jvZVbZ+F)VCJ}sZ*+hXnOQGS5V3fw{muN_Zk>?@!f8G^LIYD{&# zJ9e8K_WKX7-8Ao5=JZ`bttxj&S9$5SZT1%`ChtIHL|MvqIWc?m0#@NEjD+rIU8t_6 zL%ta`ZjQgWc)aPHLeG!zAc}04BndMb<8X7>9_@=#;;!X6AYSq}6}fDWMiS;X^}gXb zgKiOlBokl8q`tvRIj{V4BX%JhC65M_ zorI<7f$ILSG*sWqU(P%i+L{omRbm3X$o-S_$)#|F8y<)uTal8p9b6ji4#*tPeI`F+ z?*0@X6rH+M&v}8{O}vH9gw5p!==S{9CxTc(2dn>%g@VeOBsqs9oBH>H2>}Ysc%^vZ zKjoN#n^cP!_Gfm#P&aF+;IbvcFF!tS*P_v_Drk5_0?;Ekq`C&}aE zB_X}RNxq599D1KeGeY14BaLK@AU@^Q@g~LQU$CJPFFj|7wT$`ZK2r(uL-XUBQ63sq zwhhS;eU|py>+fMnq%2}%K&?#LI-VCgOvOK_j(K{OloW^=>0p`n#<8Yy;h%?oNw*S# zH0%Ou1W!TZGaO)|(HxyL*lPDx9db28-8klp1yO7n^DXr&u45+|I+bn)eC{8X>%FPmWw zgVi(E?rfr;@kq>lY^#yfC+)p8(y3#x*(#pTo5*}Xc#W^M`++`)f|5Hr32O{Zg3l!TZfWZ#4 z8UK6Kdq1GXh_Zo*qd1`3b?Z|!8-|B+!V-QamK)V?%=y0nrTq^y;mqp5#$r@{eYm22 zrhAXzVQKO@eoP)olYhaOy6%3?{Rf{FNb~+*IrD#?L;qiQFH5~~gvo?qu7X@>dOsjL z2sc^774_9_-KM+flspeo_7-q?Y*u0`^vmhH4@4pV=urOZQT}&dMV}_rbQ7NC*ds+~ zlqbGRD(t9YGe&^E;#CvFFqcAId?+7nd~bj9+944~ijV?%wOyCyj-JrjrlXN!qdu7M zUuk1(Gs%zH)#TJ5zqJV;B4OcXKl zqT$Nj3O~tjYPb9VZ>{m6y@lPyX<$qfVXn22LodJ`Y05soAtxZ~un(uaxpJxSWL0aE ziP9LB40KL^7wMf?bkHj$Ed}(6{0&Sn==s>l=X17b{sFC9)<7>Ord6dPs zrlp)8pWYQ`FTG=G!n5Qi_BsnNw|X)7)G;HRr6SG^i%oylCdllP7^lw#Ic@-e_N|7& zPiG3{Qt(Z>1ajRYeFrz9cq|ocHvs04*zn(?z}lzD;ke$@r`jHPc32?|Ha|D@gNI-6 z01R_3Y~s&98q8!ELhz$tkaw^_al3;pcQk!LYBa*PnuI%0XnN`nJ+6wEIBJ_d(|Fb_ z=zRxL70DAMkTKGXHyREv$e1XR>w_~TdmG!4m@`oV78|T@g505l=V*>(3%If-<*(-` z13In-TU`&|Q#Rm(L>=HGy87xrW6@7HJ=!c#X{wCec$3(38|D4-cGAG|6uSyhi_tqW zNJ{@^1;oqOT9r$3(?vJoK;b$zI+04XpV z8VJvRB*UOq@d#-2DS4Z&zeAGose>E73Y!BN#fwj`k|bW?yUo4~ONaM+jp`Ux1C9(1 zfALz(6OU@Mz3Z_4pq)c^kDZ>nq0pxHsCjE($sLhUd?KNF9G2%F z?QuWXD$Z{h(i1LrhfF`B*-2l;qHc;;HKQVF8r6rGh6Gr{YC!scdIG{amh`Lbtf2){ zRdLwino`OhY0<1JvJG<`X_qNM8a;;Fgsgv~&e@14$m=i$XByQ{5^IrtvGXHjADl(m zP51jWy(ADMdUpUz>uc|^`LOgy4J_#uY7&D(GOCE4$bj%wuFI=>?rKIQg_r<3k3>Rz zj$X=dgM+CS`LE3#>6y$}6~auw;LefpKbYL_h}q^ZCht9}Nge)gVDg?a(<-o1)IIc0 z5sWR!U=c&?ODw|6rqBnAP8Y3y8zTO!#U~g^P%u3CSbkKXm(qzECJ-3XzIb8!)v<3? z6pobva}$K|LWA(_`djH*F%#s&$H4^90-TQD#L+baA*DwtaNV)luB96%|Dcu+08p9bN%NT4Vo@?2VQINW_KlEM@yr_L~M)2`R zm#k|8dFQ;G#$XXxVrf5#>mcnzq)DFz${`wn09xtxX5!sXy;$$mBkiv#b;}CG`R%Aef$-gK)~QJ&Zhboj@46J!y$vLPRmKPG_w#p*cY zF}b%Fd$qScc5CPLQu=ZTq#}CwyKW#TqkKuc(RLDFQ3tQF4R>Y(PLXP75-jK5K7H;Y z4G;<=&?-E6RQRXM@<#*rUDkkIgJNQmksRJrK%Wifnsljsduq7#FbRHv$dHB0Xcr<5 zRW7=uI+v{cmF*5YK(|D|GJ>&y1xL8F=^6*m;<{|-ZCEKR+aa+mywjWkXmyywSVKy& z4V!JhWFav9&(3M5Da!`J5(AW`5=?x3W`AhAI)hQa{$}Uk3gZp-k`#z#LzXrTsB=Ni zeqmL(ku}Nl2nNfIC}*;FGtmtxTeM$Oxc&HaAvw6DN?cC=rSUTX+o(iC&}OE90zfFT zfIvm~<=XGwCN_&d#hba(W%DC8^e8F{9kvnsE>8wl2SpC9yjVHFu>c%Lh}YR}eD@_N8zD zF=4C`a_^$Ro}pu@F4inEz3+g6w4?>edWqB>Z14t*#YA57 z(}=0R{vDqWP9V&F1sF5PdR^Kxa$RM)Vq+0y@VeEqtkBw8VpS3wpl~K|mKeAwmX&{J zW`d$vYdyydjO;>s+&|h>IAK#~`SGnF3B8wk>U;kBt!k~q)rYl_$${ggwBlFh(Dq<( z9V|`0!)baays40((jA2`g~3`pd4Cg5w54pZbl)6K*07+s$uG z(-B!v?1s_RY3wi5Abj4nh)fdC-jeud{_2oH0iffE&ra!l?yddQIZPDv<&P+6D3sXx znOpYWCPR{-%hEN%h%(zF$7%b%h*qqiN6avsvb2dgp#k0ABEN=z2V&!vme5$`H&me z%|$<4eed9gd%qcg3776C9vlEuV#DC05$!!@0%N{C52BJue!RhcVbqfF5N_Ovt$J0U~6@AL^945^_2ZR#M=^vnqI zBm|!xWFfYhzuCh4r)G2?AvUFl95^}RB{+Vh4If)E^U=8AKM&_Ik8uT`S?oF)qjvt5 zf_(q_n=E*xvaR=DvA$h;$o@YN1ek34f5Y_@)LL9m84;mFGCq%`{^nk}Gl`~;rJVu2 zG~Gd=Dk(!z6__T(8R6}Q2F<-Vhe zP>J>@WId4!9}W!tTcOw)gKZ2)&0MJNFocse_QUSWisF9S#btKwJglS#IlD&|!jD-- zx(N1{SUtfN^0#Ucw8N1;#POEIueYF2* zkQ`ozxW?YaFMoLm$m*GYXoHK{zC{kpTElpb6@tA=Gx!dp&(pA>2NVG8)Y$ITC`k*7 zIMEm+^cX2{6y@~Yi!U|_yuKI?^Q}OM%?8g|q8wDGRpV4sJbgUfIBrIYb)Q2Q(6&lM zU{T{Y*NI59pY&9sT>?5^mG5=XO40y90iL(N#s&2H5t*k+`FmsmV9$fa(d`esuK)UI0WIBMMW#A7cp;?EwgSg+dxei#%o_|aB;k%S7?w@yA5=OIE`$0`C zGu$ZCxZUy)e7I-6vqH++1`V`n$u=f6<9!l#*ib?KI)|Dy@PZiL#m6{p*`A4$;P;*7 zp9*DoYB9e7p~+>ynwHB7lp&N9aOA&J^3#m|hZ+09VsUxfj0_GF*vl-)Ib6wijV3T?FeZ=Gyeg`(Br}T#_qsqnt2;@buwp00eB}sLFL9)z z!cd&A6Cw_y8$2^&lQuTyAZy^aHW7PT<^U9b3a<#^Qb@>}v{))AYD$l&e%VE2vHn#o zkla8&L7i|p53fB)LQ&7G#AwlYF=;(vT10023QFus-wUru?L=c>Tl=q6spJ?|DKNYaE+6So!`=#sO}>4GQ|~! z={p8EgtqCL=P!W8{3r;e_tuI1kvDx-hXph?dPTHXoNtEKZFxTJbUyP&u{nGTTl%6K zZzsl~?YWvM6VW37qSp1AZsGpb$OuI89E-I0c^VenV_fK;io|->QG@bd_LFc_6XU}7 z%bmxY>i~T2LQf1~L+O9Qnrtj4_hqHui;mKg;qdzw%Rnp@uB5`a4#8qLosCLQxY*~G z8oLpC;5Pp_D4H~Eayk0;DPfTxY5x4g2CfWVC?u!>K{n)L_oE_-y z6Cp+P5&J>(7c$aL*EJdE&8c<)5CnTOTf#R=LPFLZB@HZ=F)4YM0{agVNnwQ`HBZM9 zb^`qTQ9Xq-L{W`+&nKS9M-Ap&EgPZdJB36dM?WpAT!sAa~Iks+s9mIlKZ8 zv=8J9rc<9_`5KwFe|y6e`j>a}ifI%z98H~|z)0p)Jc ztSw72b+4mPyjW(iS)32sYZ;=!dz-yr2cCIvS@!KBXeMdL2kHmpigJB6p>p4I8x;?`;)@(C`A5mvd3I<%28 zXMlQsBO!^h4N=oootq4iL`ec8J&7s)S!dR)`Jim#`1qh~YC}xhma5r&XaD6c>Z2^g zAebtW@lI1djHm5G9c(Q}ofeFigVe%hpD+n_awudi$ySs*bIp%Sl(=HD|FqN*9>ax( z3M`(%hQiFX(XDBii~eP|2v_HimJp?e?CL(2@{pr|&klCtIq>q3`$HIHz~i8w3QLX` zT@^7+_k|Zw#w`Rg)s8o8D}^ZTQ3s&LhGrZ7!if~z%`e;!{9Mq(Yfpq=PfBMD2}k<2 zM`aq}U!%)qMrM|=4NY8;E6fD*)wb_zlsE*xUQLaC{G%(}C>U}@P7=&Kdtf7)q%Fov zDHx0mHU576{ZV`})k*NAl`$=Tb@j@wXsH8|`_GS%5q)FqaCnxdk*v#HE?n#eX~K~4 zalINnYrms7i*zpl9a-49g-152)^;&W@kBWeQ#{eczh^|d{CVR$pOz3DZ1K~UI#*oZ zNS%9^o}RD5Dzx+NM1U?t;X+bqi8dJ9O^S$fbo-1gwLD6T_sMDZ3iUIn3wYI-MnMsu z(Vb2z8Lb<3e%Ddbu`dZS@a>PpsTxPWm-jf9jru(f+eQc6GuH}T9 zu6l4VU`IQ|AUaRt?e$gYft%5bAiBiCvj>q=-*1tVy?(9tlLLou{GSBwcfsA{MeTja zjMh%^cv>gc$4SI=U`w}RBEsA!V?f<@t71hN%YtDVU8ZR0)|d)rDAzXM4@SY;Py6u` zRMdDN8sMf|#b27&qWKTad$Rbz@*>KAv%DN4&tB%uua2I$Mqzd}cC5*rTIp5>{gP)}JgZX!+uwK( z@5$bm)L$l=l);p`AbkAKgDri{p7C4xe7Rz(Xk($H0{GQmDl)Xsmfq-p<@i*PWJ3*m z5NMV*pD2B~%;BLBL*n4XuHTo_-_lM0oDSAm`5RtLNyE0Ni4;QVhkG_r zUWue)pEhL!o#|@EeLy2iULKZ=TyxR)#{`gJ$#OV4a3NE2HmE~=bKJV%w*so{nDao_ z{_Lw&LLI>IzAkjnJ z8P!zRr4>+6dXu7n6a}OsJ(OUmg7hW`SdgZG^coP5jv&1Xk&d*NE-kz&5NZfYuhK(k zhTbzb=)2x;=9?e$$XOv$Aq`_Bs39bI-od^X#j@h7Dt0`Hi`#VDQQl^U3Ay zbTlcuI8eLmM1`K{LAb&{>nZ+qSP(t{_r705+*VwtaB@>+qD7!oHIk}7UNLBF@fKzY$PiUxTl@;0UL|^ss@pjk` z9c04CtCt2@kf@nUc{49wcom>^~8Tn6RRQ~MCZd2o-slqu(oym-p|kFBjfDnw5S}I zIm6D9u%nwr+OG_=^Bgw{e&i9WS4^1+yS<5h14Cpgv|GpW1=Ue*MoTG@E_2|x5lO#h zw9PMCln_G%t1vRh2aMYL#DT`pD1-(OFM-O}Y!n0byR*-ZLJp3$G2B^WI&ora$dR*8 zR$a7|K<%$hZcXT`*qeUGg(Vd}Xws7Srn61#@=TOL?QvU)4hm^PAX|2u7mcA+2*pE8 z2WKGM)gzowSf1YdGaDVMrjX1aYH)x ze=AZdA1$QKmffwqrCxz&Ts;98SNC0_FOwruA~r-~(;pz}|8s(t>$L87MhntreyO&K zAo(5Nn@*kWoXioIzWZ2uS*XI+RrlCAx9?FwS&i09oAc^r@9AM-aw5u`_aRGm^QsYN z8;wKl!5p>P@2PgEPPuabF`cYJ{l|3Dqub>#UCX*Asx?|K_(bb?szJ3!al1Zu@k~+; zIi8tkY&5O$D!Ngz@3~vOX>__f!qN_AC3dHhYG=cBM>s`#v&fEYmDM-%zYnMC6W2&i$EQ_4QCmvPu)F;h$E}8ChJ#F`x9TKNsPWVk2mqX?+d&qLjZ#! z%$Hc%K3j$z{kQnVhH*8i6r|L$mknK>V}iH{5J4wN=-#F|>$2}1me^tmQ;ajI!vDNn;Pjzr_$%p_wfi@>3U>4Ca< zLxoUiqq|xg=^y~@^XvLcrI-tyJ^S~VnNy0tL`=f))W+X38N;3E=3}rgY@bpO^Kd}( zpFlJA0(I1r=tQL5ox&&=eHlpt#>3piB9jX>g5P^~6K;!f(5w4ApKVb>6fq6vL~j^v z7d`aw3jqC)we#VwGSSn?gb`nOV9W=BZ-^|jh{w*VgM+evqg>e2}nDW?>-yFu|Tb zx%mLdH9JpbZyS9Cw(=zW+NNrsvxEF;5uL6o#H9D;d_j7r&@HM^GvdkUFV(O5#WV@p zoGST*HBSolsF=gt4)wwhTD)3~wh%QhzvicScWcrXa}J6qwsPQH0ikuEyvK7c(qbE? zB=0{B#E&_^aE=iMlLBjHCG{?DsdJW`IH@UUHmf)kL~K&Aj=L(Q!MD#~^AG;sLyZGt z{^&;R@?a^;3h-E{Rzyew?=4k;(IcBA+>7D}4_3Mz;apgM{T=5hpR6Wo^L8ALI(M;b z-S#odPwh`IX}I*oIYvkNH?1G&g^ym^tqRy}%7x2&{$CSr1<6!k4l{iNgh+i7~KXtE|NnVlB2ATPjrSiEKkpMcA-2o#3 zhG~Yf1ekI1UE(V-y4iEWDG>k%ujrvW&<8i@`f#yxPBAx~~==~uZvZV}y(c$9suT#7)FgA2}Sb~9$@%?n{; z^Yz2{17A(P!#_NtN_qvw+~&Q)Rg10%ow+@wJ^c#0k9^1>5DKvLRHA$@Dv_>mGqnWv z4=%j_lO@Q{W8$2pC*8U`*MIVcMHtXV&t7_*ez3JE)xJ=?I4-lAv{+kDgeZD3`snr@ zTVU3^o$x`D4>UkVsF@3Iftp#hxy;&Mj}Z8z7c-wu6lfpz)Et#^0a|wdQPi!iRr|x$ zMRE7xLRo=6AA^k!!<;4%_#|{%h=eUyhi=EpZuOSk=G|}$vPab0!E?SfuNGg2OBT`M zvtgYXVQD^5A^qt)jN2Z5cJmHgKvjSXn?Wa6#z_vji~cGKP%8skb29Lz{&e5(@TL~Z z&b}cF>GQnBr|*n07ohw-cT+TrPFF@qGDBVUGhqPS=uBQXuKN}!9#98*)<8xn&F_7n zCQp1y?5;QWLahAVZP|rv>p2ouJC>gnQnjShOaxff$%$`oRBf=NYf5&jw04{Bf6|+F zc|M&EPPw7UO^wrGAZqy~`GH?u(S#Vjz3F$J8i!f?O$ylm!XGa|0sJwtNdJo<7kv%m z9$J#T^sSKbB}Hy2m9O3|eoPLrLq)e}cVw$!xii*Ri#-gUU3yj5SMGJfi*|Y^Bs512 z)El_xP27CjN%M2k@WlY6R>o_M&Gy%t(TRdY(U&kGTQSNXYPP{WXs%Qpi#&_DB&LXo zNokI`E100)$#PE6HQt#|YDX*5+;v`0>HW!n%Ya@NTxoh|fX|lo%jk$sFXtF9+n}eb zwmQqE>Sxa=Q(O$iDh@`GUDZTZg4m|x3SQ@UW6qUd?fl39Airj}8m~5t%Y_n_0 zgHRXi@sbd9tWH-p>Qf7yzi^@glVBFuGt&QiUpw}Q3}+eF4>H8ixP#AAXh$F4n<^+8 z4dt*ldC2X`tAIr4NC7*B5$cL0dqZ&x1JP4t>oyF?9N*=NfX#?Jf`CTQa;wk8Duz%! zwkeclDt#a4uL#jxOBJLk0HV6OBfhMTErzxBBIx4{Dd}?`NR=sd`xJ^;k1C%yxw_q( z74JkU`dpUzffifw-!vj_uXj`=nH?I4KaTlAwL83-vi&OM*NyZhx+U~5?BZ=jRSaRJ zc9mw%7r2g4eUv+>sAug>)-@mTcmvconbKlxtsd1*GMfJYpg&IEWy^ht@?mn1T?8)k zX6>Bk9yaO8WBGt*)S+za>OYHNA;#4MD{)Re@K#G%VyXFDOV1W>XJ(aA1rCfQxen#* zGnnkVT>odh{6e&*Kvhjz4L<|l`N@0~JfBOeYZo@fKl@bQ^=yS>n7E_Aob z*7H|{>IR=~*cQuMY5vN@8TifOAEBJkl3qPGB85`&jC02CS>Aal$v*A7^h}J@R4DiT ziRs&PLj)T^HiHW1`g$alZZ*`%Ss7%sZJ$3j?lkNz1ir8rs@D-S3b& z)sflWMZO+9iDR=d*$-`98W$3RG*U?BKCx7&J#vifSh->uED5H_}pgeTU#j`+-ZB z&u++pgRadE#Wc@$4me`CCuK0#g& zgGJpRxQV7?DPGL+>v_vh^REdveh@AE`7!KDclE%}Z+fVA7Y4vrf`%do$Ek`5I8qtg z?yJ+W=Im|1m;`-<}5YXO1i*g?D2HavHgTTmwE| zonmGt{ibn~(;K~h%gdE)DJ@fr6tTFvTk+RzZ^B}zY@dbf+9iw6oFyftlZUiYNSLtc zErU=UO9hi~V>YCNRLKsl+`1ppxGlWkCw3JoN$+HgEzLs5Pq}wy43~^N8a8=MKlnVu z&rAbX;+=Wmx;sp5;d1zCpym4(Z8^DXPBQPe6-idfq?;(Uw-nU2^R;|h#Vc}tSR>Bt zbkE^l)+wDS_a6&}zGV(4#N$$1!Mwrt7-S=IFYvTNZI6&c?%+zzlQk0wcx8dv{DHF2 z4S})pt%nZBF8cNI&o+RPq+4^}#IG$}HEn$Gp)4OaB&+4O`~dP|RfQkge@b|4nIYNi zX*g9R{lc|%^Qv3ULtpy^j@XR*)V6sl2og6CBPVwX^aD$d3GWL20us#ytzQpdP86(#9{GtT+ z`BxL1J!~=qg(yV_OZdtDMTrp+)c3VOkJHC5ZW0l^%^MIwX%Ev8Ks&UxcgA2}fk9zr zA#~W`Bl2mFkY{kaLBy;MfyFWZs}H%(un~u`ty=`-?j&OIDm`HB(jMIRMb9j>t0F=X z7AIzUdE9I5QO_t&exNWYCK$|Vw?igIMF@Dzj_=n0f8yAWh)+ zPDC;{30TMiFMr`gU8F`oCK01z4WtMM6GLEuKS|ucL^6y7gZE3jRkLb3a=pV=>>MKT8=-XH5Mm=^=2AOEw?Vw$7sX1f_>$CqpkR=RZ{= z(-?#MbTHM5b8CNEmuvMcV#@L7Z3<{Us4ma``9X$>V{L3=VX*lwHKqmTvTnP{;u~Z z445-tJ$n^CJaA=zcASW=6jhk@Y<{o~_r^&(6+HhCpFf$^z_*8)BdfvWe?vu~<@U+?d!^qWlIvT~V!H|aaAr1}GUeeV* z1^E6!L+uG`WN7MsHe2yM>@?Md3uK%4cLbPspVGp&4)%t>-&i+*)77(gr&Kk6Ur^nD zF8K1g&9&u1EPuOu_)&Iuq>V=%RBq2Jxbuw{&=Ia)y*unEoej}AyD^Q}3`!x2gHPxG z@TLKGAT448N)l>!2;a&t^_BBnLD|OjA1hRJLgtQ&t(vXmpU$w@#;QSp<=_X{IL^{E zB`i|b^l*5~mxq~V>1=+r?YA$L0=MR`#2r2MRbrx9)g#-k+$;dvjQ3!1B-*3?%3JPn zOi4}xtzkLrPc{_bTD=2WiyF??X(seU{T<{vUS6qDO=PbWTr?@`ydJn0F8T({Nu36bSm}t3 z5^wEEvL1C{sJ*`O2GacO{h`{*JvwIxaX?Q^z;TR^NL9C(?wl?5s5@E!={ zFMfUNDia|~x7M6PcBMKol0?klxTf=2Lyy1`+l=R(X<#lYLqzwp3%c%dlXp%AJL*)@ zMdiNlPMMS7s>@HU^Pu+@N3q6*wpAzIGU92%x&E;oDTWUL2TEsMGtOpv#*M+dWez_9 z#oD~kpV#k-ep=TW{X@OUP&yuqNN2zF&UXrz$2jNS5hQ6Gc4bN%n@?IUlm?Kx zSWt)29a!F1CSv}$azxVj_=QcJr9sw*O-?jHt%hBifT*qNJGmT+O5G;9Z5*LC`MZys zfSqxw>oXd~;b4fkd3JCe6Q@hSBGZvPu|uv4FQU(l!jBK-t<3VYaHlZ7vc>4*3>iKO z9{wrkVQ7R$e(iYKCXi%o)}b71X)WwGZ^n>cu4m$mIShPBACxX zKt2Sw_Pw;?6Zf4DfAuRv*2?J)L2Qtd_o=_ex=m|JF9u1)v}5#6j*hHS|483%J9c>4 zs%=-_nXGcV=~v(?*X2xRs2cLNehoKra|R6k+rpS0MMf+W&I;(O!EY0CaoEp$;lgb( zg;KCGLh%sGVlrCqzfQL{Tb@L4E2Tem_P-W}zsxIj>k=Ue%34s+PkhgF_X@vt_}%nX z{zHy~tPrK1LktZqf5L~>WriS* z@Pm~#bM$iBKJ~#NxH?k5Dl^asPM5-tN!dbRIf4ULpHU7$289+oTD{J6CPFCTW01UJ z>13b>S85aQlZXwPIhP`9As5kmXqt;*4|2pe8OyqhivsOBIyiByFR3AQ_^ktrle8d-?elz*(leyKRiS!4Ye_Qw4FLn7u2V#=_K zVEz9mjleyFTfsHbk@q|!N~H&uQPkA7H?KA24JHvW2Lk()YedWg_-~G_O)<(HCJdXB z(GOGl^dQyC-Dvl+?&cLgEtFpt_3ddMa33Ov2sZB~ z%`e6@E_S#c8SXPX?+v&h* z+~L|L#i|5TN0ruCkK~fXq{7|(lJ<@OA?bos9%9$){tdOZB>>v6)tY^hw6D8wo<3vm zxR)*vT(${1eVg=hUr}N8eM`<}<0F{43I_oJd0Wq2)Uswmg7uV}VQ{B9v60$tUi%28 zWc6Ocnul*+&lKEi^*t$)s@S{iAaxIHc}LF1&wV;=shskfgM0SF(JS?St63R>m?uNu z){A^aoBT1Mpk#CB$X>f9Ygg?!3*%}3?ZYMV1hZyhhf-=LuhVWb6^#m^hk=4D5j?;? zQm7y7nLNgpma-R3)zFMda7t$|yOv(u>nQoa>InB-@P;M33nnh-nM{o6X>f13WO}8W zd@)K!r?Ir(LiS`-t3TIYYhfX!8q~b?YN-d2O~-T`)|=1WM=-N4UDTkyP!*hZy3r;3 z*kWFuMi(E#tiWW_>R2sH386i|ruDhm1ZDq(hCeKqpVEem zS+1{NYZz_Fn9vQl{q0%CvyuQRyUCQ618AIlpG9!*bye0rN6#{P^tZV1H^5}sqS)aZ zD>3zn*vaVXmTFERK<%g&o(28?LPEE$hC|fnSmS95& zYtu!};zn+|HWikZco^Fdn#<6{{ql8V=&8A+-h%S#oTL)m#@|j(9dq?~uxCXXQNxmN zv%!x2%F%PHdPnc8^e$o~famW__+KpG&Z7 z$?&51SPHhU8=i+;FEUdK1?`XXi*n%lF2`y6l8M$|&z{*>ZAclTf2$-$#2jv%3eLbD zw_VP7tBlxTu>E>)YEElE5p+0$kd0|<&zhH5GUD8xNeyJ37wM!%FCI#Ml=|fapC)XE zTDo{rN=I5|ja$e|g;8!6%ie=>5K*?|8Z@#sTbyVAiMm{GOg|jDk}ada zUu=as5=^7iXzbs6qAtiueF@(iL6pk2xZxoK|NfMLo2F&pw2oK1Yw#|Uce&~mNFZRS zcI<_Odwa4f_ZW508L=fQX2QgoFeD0G>Q~f{cuef`WpIii(DYhK`Q@ z^yyO!3=B+6Oe`!cY;5dj&z|An;Naro;^E=p- zlao_WP*74*K7an4ii+yRix@Q!wlq$R#sL~QBhS@ zRZ~+_S6A22(9qP>)Y8(@*4Eb1(b3h_)zj0{*Vi{NFfcSUG%_+WHa0dfF?s#^wW+D8 znVFfnxw(afg{7sXm6esXwY80n&6_uGY;A4r?Ck9A?HwE(9335-S64STH+Oe;4-XGdPfsr|FK=&eA0HoIUtd2zKYxG!fPjF&z`&rOAP@)?931@q z{re9eK79Q6F(f49)2C0Np`l@6VV^&L4i68Hh=_=cjEstk`ts$=*RNl{eft(29UT)B z6B`>F7Z(>FAD@trkeHa5l$4a5oSc%9lA4;DmX?;Do(=|sGcqzVGc&WYva++Yb8>QW zb93|Z^78ZZ3knJf3k!>iii(SiOG-*gOH0ej%F4^jD=I1~D=Vw2svr({T5k&)5S(Xp|y@$vDAiHXU{$*HNS z>FMd2nVH$y*}1v7`T6;Ug@wh%#igaC<>lp-m6g@i)wQ*?_4W0Qjg8IC&8@Ai?d|QI zot@p?-MziN{r&xegM;6{e;*zm9vvMWA0MBboSdGXo}HbYpPye`TwGpWUR_;XUtizc z+}z&Y-re2Z-`_8n8~MT30P0&gJr_7Q@{org_^7o*OE|daaPm?>P0y6wR8(Jr&fAby z0V-^S_t#$}0a(h?c+aHJ5D?UvC;%m|8P!$QiWwN>q@|t-7jzkpSXK$jN1ZQK@LMRiW>(an%3+ z*ZMYi>rGXt6fYTwck9kK zmRkxq@%-`Cj|R{-C9Pp>fKl+zKk!aG{Z>-SwWth= z{4Q%{Nenoyn}$3kBN0a_!Fm3DJqq~NcK z>9(ETdKwR1#6c>t=T^z6oxa8rb@h#Wv-j*iOsA^#ko{y-Lx9kC2ZhAv5Q1RWkUdlV z#*WN%U-06(%R6?Yb(|#4DFsS-1tC9Mj_JN{q0T80lG|QY17S15iM@>GIOT}j!=(wCsk)HHK8(6;`3>>086rNwt$tDV-(+e z&1Ult&tStMlLURK-LDxux<&W=z|0hn@S7nE=4=+X3bS5VH=+y^7l6C<_}dYJ^XBUnEq z<20BX1+E};Ze_Cz64g&^O0#qHaoaC&>!^653w|}ZBzB|X~6LZ|HZ0(gbs$O*E63|=FnD3kw_FmfN zyK@?5WCJ$Zb^t_%lgBKnqhP5hC>%e^wIx-iYupr=;>gd~G zag&$yLYpW99BPj;4&=K_u0QZM_bG45H8;`m%WACXyJ9ja+%quC_Sy8I;5_f=C6sI8 zVlcu`fKEjfY_XSAwJu%b(Yhyn^>1gWojnX+$>~Zv4gF5aGPd7%dkvu7&t}IO!`1Uh z#COZ$salBBjw2kAX~ZkJ`wT`9-lM5DA4hw_B;l`dofwEB9oRBKn zuy-HS{6C~~$Zx)Hg$+x=^yO@MWzAdjpfp=^F`XE1--hhZWG8t^OplX>U&ndZ>-wF! zDdJtGLkrTgt~th)qS^7MoWqmVBE~({D3gt_K+d|-F1ym=Pa?>>K6-IgoJ?n~&fokZ zZc00@7taHyzgxX$W~LIi-e}40-76Uoim3FsAddDp!Z>9)Gd=WA#Eu zV1O6`mbp=LBG-U+?NuTHhae45uv;>3Ni$N+WLgiZ82{Ogom7pB$v)kAK9X=SL4sxzxFm)T9rmoM@K~}-K8!fEJT$C=K`DKarQj#50Ww!wBqLkl%v8Tq z0*4)Bc6i#FiE+dH8L=h!+Px@6%IWW-Ut6@DzdB-0cPAjB{OO5wVy;svG1s_@u$jdb zS-Rq#rp7s^@55I04avxH(5zH_M2wg(c|EMq%Rjc{`qt#SbV&!g6LBIfQ=w#x@XGc8 z{kSI{SnAPD?&(pwv^mm*Ib{6Sw1sAM@3}e7^L(&vp*!9hxu5l1?3FC;akHCfH+{6& z*l6=p%7y59>2`R=W_4&{3fc?Vdzra$&IIYGpZ(vbO1flzQ8>vDUP*~tYEcj3&P(h;Q z?RAPWez(#I>kh@FD>8OIHDxqN3rv8__nZqa zoV$P`0e4l0)i^7sg%ic%S zHfxN>{)>R=v2#_C#0iL>xgGFC|2&_D1)k$ltDFNBPg8ZQkv!ti{ryGJ^*@rz`v}1% z?#1j5G~A4?!^s(2dKnjxjfjC_YvJA{wSlvGeFLwi>yMzT)Pe>tnPk?eWdy>e4ua1F z=z>6Dh2Aw;hlQzxCgPhuzMK~tN^^bXK-iLbi!QiBNZIXif4!OAyuLzH0Q=Va%&>ge z&@dk_`=wl(qrul#5hR|nd7xjh45vTgW3Wja#OL(sCrhO~^ZaT~8&b?_wHm%bc%B^;<`gdbYENRc$UtX6@xTQwde1whq z5HUMMYA8PTHK>MixlZPCV~oE0KKE7XGj?>@&Qf0|WRbB&v<*R96LTDf{JKI}Awl$k zo6|wXg_Y=vblW83k5AE(MkUUg&!FTJ3r#0w2gsK`F37yab;nm9&Tow_x*M4lcjqkm z=C6KtZ=vT#R(g#g)(*BVo#8uq-umU%6_}Ckw;p1#*9}%ObJD#DMnjoY4t!Ya)e;r9 zaA-+iro|hgmwqGB!h^x61sJN(YMh6MZ~!A_7(e;HfAIe^nEwadPHQOA@*ErIS=!L5 zP6&ujYiR8`4d)GgunCOLXo?VK-hX&61KfKh0<_7lvf5D9O8%7gvTBF6jli_(2}H{z-q`7fYJ*@SZRmN->*TiIsCup z-?P4f=5>zra=j(w@E=H4ehj!a?y1bUNlUMx6H0-^L*TJEClWS>iS_f?>L335JM=RU z9FX>pwmF|~rdyWsz1Mu$`~NkS%C?Te`geD*oG?XP&veY|D`G(HS4T4#LsX!)V`XON#+S^GWZh;{^u#n-#fY7F&&?u1?r zdDQ(z6+9a+ZkdyvZ(NwXTCTrNzvZsNkOHM^i=AwW_1QKM!pc|V%g=$b0~Q$Qg5%Fv zv92%(d4UIw6=@v!F>dXAVMi15-VNR66^b=#*O#t_LA;JiW%F7iBB=Oyt~Org^H6ty zn?9y~9aowTXSJ-Fqw@xQ)dX$o8+(8^;~Mjm+QJ#HUINyY)KFPGJS<~kb~W#XpEYhI z6e6b)p4xWk{Idx-gk-Os1~oPi zF+x;`^q!_1YFssREH5Ffrd$-cj8@p6yDOd3Dyl+FEff5rN{7*{wC%m)QZJ3o-Y7vE zKaw<@oP!??sg5nL2D!C*4QJ-NqJ zTd5AvQEO?Hqdb1%@g~IYtry3~-|y!5qAX2s0;)Sm=`)ABdFGO_fxwVhV;jMDU7($= zTDW%;qWDXrHXN1Qhh+B)M%cG9ua+6j@4FQz1O`f1POssrZBm+?W_{?X-roKS z|KvHi(>BXxhvK*WPu9)sbxmcs`NNS+98O?ssf^GpPVd2Jgk7xK zoGeUi;u3r+fd6#4gR5|QN@t|~aTiU@IDdkQZ!L1~3D29^%Og^rMN4~%w6V!K>- z7w|K(5t6>9`$SnRG{KvElF=dV)+bk9vBOBsgK}|%2qXQw$MCnJrU9=*6Y({MoGFKK z8iTxzmvAUG^|rO_kzVp~$c}zt2M(Qk${)|;5VoR3gBuaO&J2%Z^>+_SN`zFW0IOZ&Gdx`9z@4UdbR?zh9I|$ISkJpMPuaI5`VIM zbo=VCK?Js6q6^5F$F`H{;64(#box~k(j(fkZ%Q`EF7|vuKTx4{DzsSFLthIxg2^RojgKwZ&|Ip^1N519V1q$IQ!IlkCWEg29r#w$FXqdsX~ZhvF8hkxCd$ z=J=tWwhq3(Ts+#ya7B){)A zAibV$KlO?Ev=v6bOd9{%cHoo-wg*yKzWfbN^yOi*i47(tJX05WDOBNU3k-Mysr;dHA!6&-JRYE99W$ zj#+FYIB8d*4h;Sw&q6s+Qg;3e324WnJ&+QQ5S9b%WYa zEaw^x9fJ*t$(ynyWd&H+w^l&EIflkldVw;|ee8~P>$O|zheeG^5jDTwdw0sZ9My`0 zCYZhJ-Y@p_9jf3sww$kswJp%DXyNYl*q(if|IU`K^OyHS$Xd#TtW_?2tFq9nWd)UA z&)9&>tz+>YSOVPC$xo}CDH_CnTW;wDY(=E35!+|i9G{xnc578oi0WZ z2ZlsflC35NSgh*RAsNl%O-6r-mVx#K@-{}W@aWl(raryt%<@VH`OBYx!y2i?K#n2y ztxoST6Tz`FN4v@Ow`ZkQ#?rsW4-QB(59fvkocq#ybQ1VsgBxZ$RdLn#QJX*?WX$DV z?R6JcAt z|G+OnNHOIMZ>w7T79~?0ICel`Xh$u@An)|cjC+FR4Z1#KvxijjO(u07zwu1OX3e0lug_S zM7C|fB0-+XD!c#n2LZZfZ-r#F|DIr`Kp4MbS9*LeskZXRTQs9-4yez<g!4rl9401RpHK&(PfIElhPC%8|LL^xcUsj|@?4(=?(q3x}u(sHoX{NIH-v(!QU zkxwt1F`?c1xlM^+}rEWv}VyxdZm!xLA!M7J*p~Ri0l5Dx(#QX z|AuBizI~T`()6~Z+-wY8ut0WY_z3yll<|ReZ0h&ben_y$?f{JwS1PGiO#_-4Nhhwb z6#mS*3H@AZyXdd)(7k_lgyME%m6qA&%|z`dCE}dax#W89%5Q&tM?m7cA;j_r9~&7= z=}}7dXB$9=wnFC!3+EGeN|P9YKG7_jt%%3II;B*=DF3THUAiCpUc2$ZGRE%)v}*4h zJi5&MZ*Oh`ZW+vnG&`;CXen_Q4T@5?^S zWRLX_;?VlSbc*Aj$h}-Rk?-Nq8mv73PY`b`Ey4H)y%w{#MGdKW_QRa>iJnrx!^PM` zoSgFrdxN~CVU2}P)^5P>DptQ>9Vl3^K4*c<&j(rNL5f{|*5AKf@1!7|VxvsAnIUD{ z(oUIp_j}K0H{oFNbRr29H3X!m)UO1`GB5kRQoulM*kH$mkGyrVG82tMq`y4Z5?%fN zIq2#KUAXO&l!mOMB{>E#*zUdQnNHOs9KMO!ZtnP%MCO6P!p*d~_1U}oJX#iDBh~=z1HL}>F*SxQO`=x$x+=cGUh$4HEm{w0 z(U1FDnBh;hdDKG=S6+4b5}ghN$oB?dbsjLyNaJ9_BtcUc)K+i(AE9=vISguRqx}=q z#^9G(XfDHro|CekdWyb{R;_Ew5rLJ;J9=Z(+BTi4XDctog>JKrM3#&lv;z=`GUye7=$NbpvP|^+8*=IzbD+`< z-Oj^>_Tq@xD1HEc@k{g)2-W-ykX&)}hd?a4-u$zGO1}BQg6NC_BK04tP@aChwkLZo z$>y(K5Gy4hh9CEh*;fAM5~(*4xxJH6U_sPR)R;Pli-^!$T5ofYdg}}f7$M=;o1M?_ zi8#TxYK1fnTFsNZ2JTWWlZv|L`~Z)>ld!EEJYOoHfja@W2l&7aO}CogHJtU_l#r~6~^ z`D550yTBuSImoDGu+nhYEN*zTtQWssEx9c(#t~ zamFch0E-QWXuF>4t8H4azkq4j%Cm*JlXd1(+f`0(zJRD^05a>t6O?Szh_BqHvuTks_0zKk1?u(TvxII;R$b#y8{?0<)U*#aQMf zsZc@27U&fVLPOlNzQm0Gf~A!#gRct2&}; zL~NCjOeu3xM2>WL3Mra(Sv9d7tKF!Nsmx;b5>;+T02tvueL}$D+>BtJya=d;pHcLi=q!>EZaYVuG+3a zwyBVvwiA@-e~wt|NZc0)2cPn>Yh(7dRJr83JSjc9S549?UDU+BhW6Q5H9(4p_RsQmK&Q z@kO1k=x4JtP^XmXh`$o3$E?#&-Yg%#sR!(dawn@DjxlcKXUH~N-ydA2Q=4)abWTl= ze@YzFy^V4g%iLRk)$LmkCp&xWwZ#{e9$wr@yh)9Ui06u-8W$|=(lcH47PX;?v7DZY zJ^~zHu~S667X~Vy@ExJ)726)T7;Kr+CPP~+5P z(Fo!BkMHuOvI5-?X@lx$WT|YrOr! zZcUE_$V|FZ)GmB*r8kYfSsYJ$tGihLnokW%SU*uq%&uT7>UK!BXDP2!cLmsi;}*hUSJAX(~0 z5*rUz3Qd8lp5_>%uyPq|^lM07`WY$#Q%Xq*>y_z!EU1;;x1 zkK0X_ZaaL#e(+JrRHG+-NrDZ-f4NBDs_GuENxm?C@_o$lk7nVjsw_1&TwI(RRjU2K zt-#>mcPI^~Xde%CEVgsm6Cy--{9LO^{%{!b7|Gw3Z6uUCp#7AV*CJ>QuO7Oi3I%3> zb6{pNSn$XnKyd_*@8Y59>;KgPgUy@&su#ac*5))I-Co`W4t#O_qg`yi4)3wk5&_-u zZ_NJF!<0aRG3w1~BJ6VFZx0GD>PU$`a^Z)ho=I?)@W?_|DzpaI&J**_yY`UMl3774oywS-82Lpi$PXXlm zk7~otBPALnO7b(HPsq9KH*jnf zbWvy_mT~j7DilW&b_$+)%F&@nx1*Saj4&|M)$<9=tZ?+~mONpjk@F!k!CBv<-P<9* zrRr$d;mIGdVUN(Ym|CCW#2^ub3G1qvS(N)kNW;0y@-3cg=l=!AnnycP@6~zgs8xF$ z!>ZpUgd4@cK+(i$oO#mn)nSKQ*n6Awu$YbEqDN6%9O{fgf6mm>?f2AMHa1TdGT;^ulQGq>SOofgbie=})SkI|s)*`zt+jhbM;mxw;gzW;vbQz@MA-G_#Zhg^lk zQ_3PL$tV*UBZU)+(yIV5#DiVR(x+qxNYouyS&<0z zPnoG~Jj(2A(ISDkCy5NgD`5q)`9}49KMj+yAT1V$VtXIApHwrjHf ze#nGAPP;ii;usR!GSi5#vFdsyt`w)DF_3#OKY_Y=9TDek=(eOJle*MKQgk;ZXMs>w1#gf0DGut?SmjOOu&xyau7@BZ$)BMtJSL! zrbs9wE+BIA-hJmouF12VcnAPzmIe|DJg}i$u`)`$GFWk|QkcUeTJzt*IXM=;jlwZQ zMM|}`v8RLY`$fPBD@+f95c1nX^P>1o-lqT~c}?l9ydV?A+ooQdc>`;jKJ=hBR%e%i z{^{jn!0dDILgX;-znMc3>JR-gRTz2SVxW*;{)Jbq~DmALMjr9f< z3^jKp!SkW8sc~x_@RZZ(Ho~(f_Ur^UjzuB51(j$I>$OQwZ(O&TG8&u5mXcBN$WjP|1w&yxMJ5HWi26+J3YH9< zlU%YLjdJtB~fr zcbZ!8qbn$Fhrsp5<8#mj5Pt}kYWS3|%bqE!(C;v{p;r*{SuC}(i0Gj4vnmwd^k0RI zd($ChmNb26I(*4)<~Uw=oa?by3m|ot*)D362nnQ|uv|xTi`U(^j>t^HWe=qHXdfWQ zHd;h|EON0&<}dr^6S74}7eS!XKO7(=9{i@$#Nw*7}mtYdvE=}|g1J{Zg_u7`Ql-wJocVhCb$LhBaOkKhIwKY>g+SQPY_ zW$jxmvKL%oYeL=2ila@2IX)rzVL|7PfwA$1ScUnRgIAMscN9G!cdQ5{A&YB2YVJSv zuA>Rs)ua?KS=0{OrKD9^g|q{ThG970@ej`b3d8wv$^RqH|8S?#7NcqO7G>J8JLrun zu#DxQ@-l3S>}iN>iy+y&5#4Uq4j45c#!AT-A=Gnsaj&7W0n!`V!$+#P)hYkUpQ+W5 zQLz46Ek#R{W>Ye#6lGe#`frJ&*WsTejp9|+1*<}PlZ0XLzSgserJ#yrJ)w`lP^dKGvb--~)Pz&1%ft&PM8?^P4FTh_#la*H zK|}h#u?TaA@9}NorALc(?_TUh(z4kxty>GA#D3RiEcG>eBk_i}-5Z2EB-YK?J?(Rj zPk@q}>I~u~C(uO1K9ObZZv*O$3SslAW8`&CAy`+##p5<8W92?RU;$PR7y{50t8wtp zVjB_Dw6AwC_BM`Mo)s(!nXUQ3vSI>#wbe{Ly-G+f(0SN?=k}K6yYq?)6lC1_uw7Ju zW6P|`w94{#itocrCR_b&<7EV-=jclzar^-%$&qfP=f)?&&6v}3p%yh8=DK0QO7H(} z)n+S#fRS)|jE(@2!i5syPvRfoP28h~GS>0^Y;&je&s2Z`v(4YXuw*Z9sj0smW0#Ky zym{ERAswpFrL~gXPyayyVC$9^)-MjMf#$N@Mpaf{VUK;C2X63vQ^N>k9HN21EBWie zm3Fn?zSol`lU=1UvFa&Wc=N34XpIVbH0-~ki4II`vKoSfAj|#Vf4%1S&0lI1>>zf ze_Q%BfGFjH$IJoS^_Tb`X#baCs3^?|oufxi4Qd8->g}q&`^zGvHS|wDB8l`RCb~@+ zs>i??YV-t@H`~i9k)W)xa9<31@IO-C-hYTKfG8afppJxB#jfl(1! z+0i{WbypePyfK}%9!)oG(N2~$oK!6t;Gz`iwk)e}AYOTbN0?7Kr~!3aO{kIb@TQ)K;7C`a@^@-{(=6({zF_zNsSQUtuzu9m5<4e@;qG5 zgnzZ^B=K?yJ3BR4JBAtIrt}Es1ajf)f9B&K9IB^ADBu_1cJ@p>!~?R|DezOw@`iXX zXg^(tjgt!asR0}^wXpR!C$Rc;Zs;;qn$cC7i4n%x&Ei$B1zuIHG8+fPmHp9L@(3Z| z!&K{O0Yd%Mi#Oqk$D})%KJl@^+GU+W*SFXrcF`ksEz47#0K`=qfrPgxFd3X&c!Sl@ z6Xohj5p`>iHtBtr6Zf-#o_2tVT_^@USoe0%ovSk7yt(GKHVb+;(%Bl=Dy)nA@)4E3MY79Kmf z`mePQYKscHjmOH&*a$z_-;AINw|P)%iC9N*>}=L@bSC30^HFPwNNk9&?ir#`h)M1{+JdaE)^NdpV%#v29q zS`WZr&(=v$5{nLdNz|~%!4A^Nn93Z*5V9lZ_EY3>-P0ioK@ChTmvYm3mKkO zn^b5*9FpxnRd!%fs}vKq;-Pt>tOo!H-gudzs0$ z$!`r$3K?>UWDK>?j5iH*&aBl}BJj_pKQFS5H?aw|6lZqHJ);0ua1hV_!wdC3LJVv4 z{^wYzXcu`kr&dS<+c+Fz3F8j>zy~Y+`oXg~&c2Ad<;&na&9t54>Y1stBkV@`s?MO_J{jh(Y+cL6} z4v$q-6GZ_r2XEi%CE3$!=U(Fpc&6oZuM$RVLQHm z)vaxAyE~|%O}l85W%0${vESm$vX65hcOGLHADJBsmDsVrgwYi364bC|07+)B9-Gh| zT=f<#sBfA{{Ne?I^kfJoAmhJPmHNJt@xesc!Mz1lUr`Q3IOOZ#0K#Hz#s>nBrexooF1lQma+z0Eo~uIN7{=7(qe87ZwUPmx>gu>mi)SC z>*Nz=FE;jPj0Tm3F%)&gS`=|~GxSO&o8lg#NMUlr`Vt}Zu!2#q)M#vnm!p~uM>}mi z>TwqHk$~1d)iH5n)8vZD!2(l62a|U=A({`F32gw!uL?HtN(_Y!3{2F9bv4HsPG2f^ z%O6&C!*r7{_cyzBy#4@wbCF46IX za419lJKR)VFl_zBgVT{ddhaPn@FO>?B#)K@ZUHIrc<`4`2gq7e6rh4j`w=uF8M4{E?Zh^=SD zN^M^~=~_7O33|FW(QAf&To5>?S z=h1xo&_Han9QFba((36P>y7z^|1sN`uPgs7hn6S#E-j2U4xvi4X_}YRm z!(;sOE$qLahFxT%74T-VZt99A8AL6!x?NgVY^QhBu4EHH+(Yb>tFLVr&GxETu=J3H zlT=RGFslwLUkocXTVzn=V>P9d0U2xp4tJLekbjaZ@*}k%`Q5q3C}72B~FyKb~6Z$Ufy;=sBE_nAHn~rJ8ygG{2V+K(uB$P>{1&YAD(vo*eoh&bqVJJoOMO|?U5 zj;-I=C-;>DiSLv~QkhQY>+jvAvKCsaJi3{2-@V)hXEsedWhL~31Y9dvTU?3`(bFJG z89*%sesbw#itMx?YyXq$YdtY8iG_Dt*}YUonI;xo(q)1pqPvW<-FJpKFNplDuX7Go z7ya5(-vuH))J0k7-j}`e2&gf;!nE4!g#j}4o^y~R<(ntHtun197hYm^e*F$xg*e}U znXEPgmFA}#nK}gecX}{Cm@}3b?-1w2KMY|TDc3tX7cfIu*g`>9hxsQBgipWV>cF<`3+xkuMb9WBwx$JSzb4b+xOA^w zthR;)GGl1|M)AP-+3|*Z{>aINmx0C@70rm0A$0nU>E9&k%KG0)6f68Ai5iREFcRC5 z>R7-#F^3oQf}~yKpC_D937Ckq!wsnaivOKpyEM(VK$3nSS?qT71<_}0 zVWd6wG%drIe{CO<&C=eH=f~o3m+lf-Zrt+L0Z=3U0vh!@{pT!b==6@GUG*m=89U1|wHikPZqihlH!WvWz zyRh7c`jGAy=60n_m=DwZ{2u@BSe=wKQ|&XeC>cuJvsKxy-U=CMmY?aA|km8 zFv2*IK`;B@-tn5Fyw}6@5lC)(VS0jdudy95Yh+FCa~_2fTQFth(e;ExW{+f>{y!cr zme{9BbY#Iu#(6VIrgWKg zQT5;V0i0kN`{8F?)|G~>-uXb!)M1uEeZU`1_FsC-f{A96oYJC&`n@L4gRF#xa&`MH zQdhOIjLBP44*!83<_ChK#_vbbR5BkVk^fKK3UOU$+ikFGpe29|esM^& zdrSFNcN@o)@FdsXa7XO#SN`3A)|)vKMQryH0;2F3)Ql35r_M_G@MPf<^U<(oo%BcP zXaL-%q)qx|*nX}jw&Q?+&gk@@0m$o@rG}=!doG)5*PH9DYm?c#@3fN2jYmB*R))v@ zdEV=_?6dd%jfsw-Qg~>BBP<9MJkiE5%c7}xNO-j_IuiNLr#R$WZA`XJKUP=ZM!2ug z>rTy>`C$rqSDzPWQ9uFxZKxQ<&(|6>l~PJjr+(7uQm}F#5Z$Be_*L#1Loe&T@awaN z%8vGi{Qo(H#2fue;8dt-;1i{fy+xz1Z|0g~UABRp`YX61 zcYl*3ZTI}3ojcz%(C0C;OYa3yz;uFI>}|xCYcbPgACpTl@F_EilPzG@Sqen(RI1(i zT$p$umnE&FXM@Ry1#~uMJ0Q}*28<^Fzo}o20>k{p(UGHo+n^&Gcjb?F&G$In{$>3L zNlvz48GmsvE<#T?a8gsxw>A=JelmA0SU_00U{lb2yvM%&Z}&w6k^J(uJJZ825FtI$ zx`~`Vy2Ufp9Ux6S)Is_%=(EM8{+dECyJD)MM2??1AXegy!(YN zY^0DRQ@A-F9c{R((6Wr-`&}(EooSD^%-u73r!@=<>o2TlxE&l`X+qMm5YIm)yhAqJW@Pu{AC6uM%|BGEA@eEZ39{af_<={lL-+HnD*x=goG!2 zB|*^<7pdnYdUk<9<9HVz+R`CIIc=U?b}?Q%YNJ*lu(Y%KJPqW@i>*2=o@=)c0;2ev zMPvGfR5gi6ED8ocpM${xp9Kyr-5b#=xj6ZJY1y=5u16IDIZu)O4b6RX=QfbSpeO;n zpA|7HYm%|4zT%%82l`)~{b65pIWYFsgq`p&QAkO}wl zednwf-D?#d81;Izw@F?vtYz4g=_I3q2s-5%ZS0fC<}D>Yk8R%k+{)bR)z%fI$v7lNipAK=V~gI}Klt5g;061l zb)rqER1ylB_sn1HEI@g*#%v&v^ej}NP~G;mQn)*!F=zAyyhjlw@-~7&NoG~xXUNdG z28)-AsQf2AnH&3KW%XhhC!-}z`uy7;UbvWkpVNogeuUA+nXCegi~QoSZY3W6M}&#& z_iK{$WjT%x-oBuU%$s3s?4Q0$W9Fgg-c0*w>QkR3$6Tz|EMA{8+XRW3~26TabTRdS7-(v8i3*^c1WCoXvs}GSIJlv7t zsIRBkTpz2Egr-t*tr!$#v?{8rW~5z*^9VqZp(YDdj}Zoe=McZXoh{jmNbE8iTJ(#k zjWhe?@GpYX&rYg~UsRi@bz*Xs>4d-h~AykLR-MkEiWUYzO=%-coQ!&YDUobBoK zUwoxA0~y1NaG#y&nR#_g+QKrO%V^`>Ma!LWe%B{9VO*J&M2PD&ZZfwyPj3{BlS{!D zf>n}*y^f@-;#%HxAH3Q35t8@*%K&%z0cL>X=qyso19v*lK30bAfIgNdR@(Vxkq@$z zJxrDwb+LW{zX3+h*MV~edQ{PsFm=m0sIPD?W;p1%z06@x(}{5zBT$wSF?1lPC$zT8 zq{VrYNxM0=?RND(HvI;i*4s>a{!51svp6pxsGDA-KMrP%izukvE%A$MyKX-#Uk%|P zI~;o*(z@IxjGSs#%#em|XpZkvyM+hgk5qsz2faOEp6`8O0ENHa7B)F2GfT#ABc^El zhRU${fe4@Qgw!VGtL#mj8CWz-mbn|gbL#YrVPOJj>|euVb3B|j8JZ}dL;sadA4Ks~ z*oMwT>G!Yi5$HYz3yV{sof_y@T;N!v(Im%71juh&kytPvq7stU-J2LyyF1whf||dA zNJBI|Wftw^=u2BhnViTbb~?nKnT1z8n~YTyhiwM%+WMgRiJ7}SH34^?PPCk2k+(yV z(;6>F@YbHbF1`vl;bo`Xmo7?I?|x3h`W43&cGqX1EUJcurAJ}A+P6wqLK$`)hi`Y6 z)<6f5&@SE5>*tZ6v;yrW;%UZ!ZNp}^lHdIgVXZTphgqLu0nDR7DNBA2f6b)JwM=1_ z%)A%7`Udq1+`Gph+<|?vzr^qA0d7cRk)4x`)v5e)8q#9B+J~8fj@L9T(fpF5jGm&O z?;sIJ9rXq6=A(~}z4O6G*Yu#B^*m~4v`#P|T@$xDsy^{Eldg?b!9`n#qc(j5dfTem z%XM1QKT&*IwRG2;VH($|1F~E{EE{g6y@fUSU0V-qo9o;Dht-7m7DAv`d&$Bf3*& zuIF&Ay(b&*r0)>9il?~h_g_xBVqAUGWDKadJTbi!YFu4@6XGGJN?a##ZIq? z`RAtbYNkj%sV&JS$RMwu<6N(KjtcEm!$PrDdfCBN1K0ieysn__8Z5N)i|o=D>diRi zZ=Sw>8RA-)4zRE+x@Q*N+HZb!iEB;qZDBb(x%L0(?mDBITD!DjXd+EOnt&8ViUQK4 z6AbO5AS&Ge(u;;3Iv5ZvG*JN|3K11SdKV%@MF^eHJE8X?HT290SnfBo)~xw4cV^c7 z%Sul6yWhU|dY)&W7KfVxA0axpz8R}u8Ks}&?~D><{x0VLm)rd7Kzd|w3rHz-{FjmI z1@CxhaCL9jJ3@xuSJaN+v{xtfREnvVv4e~Hn7uDda0z|nM?w-5-v8{Zo=>$KwW&D6 z`k(K1Qn%({a}+}-Hi|yxCA&-AFx`HK!WG|X5u#29rL%I z$>T!|W#C1#x;-u|rvZ2_L){51;(uy*|GX{WEg~#$h{7CFj_zSoxn$_-_D;@mOA~5W_#5ynY>ILUQ-p%cZ(=yrm1` z4V$b0{ch=z%$B;QuG{Cl;MdD+rT3+PfLCv7%_YvF)PUGv?kNhAyD8luU@rtlqNfNK znximzcoxkc0&o1!Jli(-!`@@f11_{hUR^u?N{RLb8X&U_Pp2;Dn2tKN>!EqnL|I;qTdIV>=0|8#@D;;@#Q%E9mEgEoQxnVRR5j%~xCigNh`EhmtEw z5h~Zh9yMV-rh-_0e*3>Ak=Gyx1={7FE?Ouq`+FA0Vmqn5WM3)x;FiQesz;qfBG>-Y z!YhqOmWz+_b}Zr z-%L-7iS9T;@=}~;TMfK;5sIS~Vcpg`F8}PGPeJ)Vhg53&fnA6>@}?wE>hawNhPeI} z8-RIc@X*O2Y?GwRVl)L~D0|5R8Ol0w$CnRL)|^Y{rw?j{pir3rc@4;xgGl+Qas-Ur z&%n{5?RlsSg79ui!_x76=qF!UP7yNZ55J#GjM;7SOQoi8BtCP?fmyLm-N4PbMZT%= zDcb!SYF>lMx=2Snid8SVNT{E6?hkxK{8R4HHzD{IW=4rH)I3B#hvv% zL8NP3g(iml?9Yxh+6(6!2`6=& zPxVQ6^cWO@^(SAR6)Qdd;zm$@dn24g9&<%di#Tf-BbMc#sR1yooU4>F#-u( zyP0JE_;bQ2+r7~8h8`G8WYVXx7THUel5$Q``AsFlU()P(cSwiN4dct1J>vjUSClF5 z^uJdv`EmURp+D=fKRW-Qu;fb{E}|fgSN?mA%1&KR-T7U3^Kc)R^l0K&EB6KqR#{mxTlQUepYQnPz|*} zgDRjRKEFx@960-)+`%+wGxTt-^+iBR9&v6Xw*m1h^j{G()AImgHV6BIn5Cro{n00V za!Nx+%2y$z4fhHkHs5NX=khD$PXkJ=v1MP-Ighy=hiol75F|l*15nTmDD1w>8%7bG zb`b>O2G?8L>tMjyMUu06n!|VR`3b@cCldw0^kk-4GT{M($MzLwxvQA&dou@L#~A>u zPZ_7Me@WR6h*aSrKPKIm7rHEM;5!z~p0(-H zAwwIJeFm9^86W(&uR3J0yH+W?X?Lp8X3aFizUbJk$PdHT$5f$~nFgMxTw^!3lwFPM zyPzQ#i<;wkj!ZgmIfbP9Ai}3D;~VyQ%>~tSA4pOPMYkr8x+Z8dc#ft&md}aSTr|(z ztkVv;=zJs~xyKdoO_Z|c$%^KcFDR+6PLI64xP{C|Qk7TwPIE;yb)}~+WYv2;w|Uve zJ57I1x)k%7RE5ClqeJ5Y=ktUVq4KcklD0quebadMmkUpV;QehEw?UEEn_Za+TS5xM zfRy_iK;2s(YY?brPMVN^H2cZ_>}Nteu?bh^+IB3mHGCmz~km!?Trs|B|)GM`^aiLFH4uadYSD#EaE%K%s(J z$x6QbvaM~yR#Ke;1s;Amp&$yMKZHK3uWAGo9{F`+K$Ty6=VS=CpR*lOsBtqYKb^V&jY$4W901| zvJhRj$mrGa@k?FYt?BQX)^3-g#xPAMLf{=%Y(gzf7C&IwybT({UmYU4MgsvEZ_kI`<|gy#hUMllMfE8Q_CldSG#F%3z3%mrz+kJ zsb4z|fwJCmfGMq&bV$>DGWOCEGFYjcXmtFJ!4BZp%`K!aGL)@^A75cz%a>i7F1wwMrj)J0w~f zbP{iqs1de@P%-vWKsL<3NG7Y0*A{WO2kt8xH$4j4(+)Tl;PTvNsVt`Tf&)6TO!Kl+ zYBWKoxN*_5`w|*(osGq!44}gw+?pB}7(7X&zG|nIZ)c}h(!L}=cqJu#`wypYd^5zB zcZPhgVDEluGh*D`(eM4o3v<@|a|Er8=CZv`qYR<*UNW_@oz?nBnqiwS8)^*+Opg`?O4WMLug5_PmhG{E~~Z#X>2^>%K> z_|YFVO^Wf$4Mg#AN%xYS78@E1|9K>Fg0f#9h5wT6I2rzy?Wk@DS9GX%$>(?q4;Wh* z%=mV<$TKdJG&}coGs=gr;Lv^_m+4+hx$LjqjJR+Atl|A!XK)Ap)NdZ&kK|#tv6mDq zFY*V3*`(dD-Q$j8I_1@4w%V^d#j&?bhWp&^H9mxr!8>f^Ttl%v~vzg~*W;Y1ShLuW3 zMFLE~bYIWiT-qk8V5ZM7PwaVg7~b&R+jIO+*Tb+ES$|))4z_zeC0kMDSBcm24GMi{ ze3hPf%oTCF_tOE$V`+A}Go})Squ+%4(PeXLm%eYH9JLS<>xS?fL17_@4ddRKH;%Q_St5H zyi=YMPZa>80W2m`@Yg{HHab?($~U2=aD)99G4N;LrI&n+JAFpE!}Mpa@hc#+*d95L z30?^Wjq_S&163Cef(Y8NI(!_+_bS&y zE;iI>h8sQ#CWYE>Sl0HfZCHygtryG!fh&nv2L!Gn1T8U#la~%8BL8S{OC>`&kk^nwby?pDl~?+!pA`j$-~F=kL*NBb(I zA5<@(mUnerG2)#XB>%+nxVV6Huzo0=mj{k<!hh!59PU zM!|`Fr%01?A|E9txlM*)Ze&rjd^k6TX*Mb;1{Oqgs47+!g-ECJJPnekAftt-qsGqQ zBp4jd2$OM9BBBwh$MhMeFH?D*0C7BeqKXBhtk2+7Z-M0L$heLnC{q6kQ=N7z>U7hq=I$cAR0ctD#V2fIs8&i?*XP{g&kfKV0b*bP--$b+1Pi#b;!?| zZ$Lu9`u4nC`$rQjos)8bbu~{_@*U^M(80UJp-}>t5-+E?%V=$p?{hr>Orw`KDto?4<7mTIJG z_F?hbSev>Jj#VlX!vxE0Q#}A;1K)-mDJt-4uOJq z{R+kld(SJR8;j#w@?>guvbS<31_wHqdnsktKTBTMr9?|a z2^Wli8T*jj!nKenu(JQdyYU;Fy$Z5Ou;Sr-KmY4kPdY@nA$mJPF+qu2a77j0ZKzz; z_tF?6{btb&^@B`*ffbe388GKT-cPX7iieE$Yb$&H`sj3{;JTTOQur|Yp6ETNgc$C&M zLSvh?E(>x+7~2+=56x6|E7O|V+RK_C+~s?s93#<#@1Pgm?-Y?7 zC`B&Hb~QUQl&SP_>HIRGpgyipHU?WtnQsUrEgNU+HjMP!4^7GPe0%;L@8bq-es^Z9 zx5r|7h+7wp+vM^~tRbj7y>5Il;~4hyD*-8ogW0i1ura4E_Dg*b z^hCTPkmg1ESJ+kSfrWE%eSyzv@#^yYGi;jZy71LD+0?=O?;ck7u#Z%$3f`&*#SrY2HlfD{_#x3m z^%n~90lMG^3v7%I#%Tmb&#yH>d>A@ObwD*t)_|T#7HO*l{#J+GG#-i~sDS9Bp4J3M zyK9WfDUXzr`jI#^g$mSVDHCaAu5JPE7!O`cU~Se%@(<>ZTkp>A-))njeU?V@e&jR; z*Dt|`%e%Uic{$*-{B2gdC!_g(a)l;5_kjB8Qt`x$qNmuMpBFt0`Ai&!&P_L7Eev?LCb&Mn9Io zime??{7&*xppgZG9A@cY-A7tX6Y=c7*Im#Cys+E9XfyhPesi8=P0M0STDOt|!emKNp{}*hWL3gIa-v$=8 z!M%Nml>2eh-lAJ^k9bOCVuE9~NGj)FCO$WRkFn%we`BI-#s*All7%TY7L zwz~2a`^ztxJQOHE92n@_E_;I2h>Qg&neESy3#_uHu4=aNx4JoVT^g^pNg!VC&cx&F+L~MMmU6-RCA(^gNmVm^)E(d!ctKsXF!-|O(`N5y*PX2~Q%=e##T^e!j!$@~ zTz=`zkbmsz`X9R^|BDSFoSa_3r8A8^3u`MVca(R7A*iE*CE6Jg)KYxBxcf{Xjygt% zFON&@?28}2N>chP5|`vLLPitOZ&J-iwm^ZP7)TOW`SP`rzM0WMmP%^)6hh-Jh{IKc zZF&G;%tCZ^y;Q_)$M5H-Y+cz7nVRB~b?tef87P>8wi?a5qH)!v)1=(aGOnX)imNl= z`x+0Yor|$}MzLd0PhoCwT4viv&YYl@A8GN_3Hz278zF%NJ(Z8a{hQ>(ShRW~xIaFU zM{(`DZSEG?J+{X^K=X!Ms!IXElP(Xl=Wb-!(k6~&ddLpQDFE*Ui6t5qqy@(fmT?9Z ze3&*=ir`!cPT9S-Wq>a~6P&q~s3Q|u7li+@e7B$}l$$fDZ1~3qcZ5tNgbe6S=3NwC z@(LZ&qv>oFgs#8%MpD|v%2AM*vr7HI;&O;eod4V_Rfx`>+5S7g3zsMTUM^KtA1i8Dv);*qnx=)gJ>&L?=7%1 zQe6Y;w&V5u-2_vwYC<&R?lB51`Db$PN*&D2i7 zD{Ez+bgkvOZzG1PE{bKgP{4|y;{(HvX$Cw@?7LROh8C>sTZWTAlw+?bG|;Z(y!xc# zf!4D>29-bgm}Ghd5p>Q&pTH2S-kT}LIJ2iPLe94}C0+99l|>OSKlA)u9mRYW)B_Hg zwTWNbuVy9-7AX2;)`f-neP#&&waIDJ9g6Y34&To#V+v@n>b=` z)}L5`$;t(zIo-tyMK~VYke2u>RsZFkOlf83h^`Z?)3;{zWW7(!(oW)e&KJ&71V{V( zmL|O<*3hhF*iw*_RVWfQ;)b;Zt^gx73fi`ftrE^=m%$|;o5Oe(Bs9!5WSMR=V|DoW zSMi(4qvyGqeV&XRCz@3R^2eS4Hun>z>Ag_(AhSD7R0v)4V5Vz~Z)c8SI}df~RArg2 z&7DMWn##%eNXRA9p4UaSiv^jz5EipS`S(HKFHF|2qyc(}*9vZTM{MC|Lz_hd6QMt6 z&5C?`>Z`2Jl9;Ka6$(wyIwM**%akVjv1qBDhpwSQ|Gf<^kWcUw@WE5yBybR!<&(Wm zy4bdDIVl%X5mVVs&6rVA3Fv`%R%MCZo#kR@YbGG*jmmGL^iAN;xSPP}A1$V(JsAh51mQ zv%TH3_V6s!t6inpu_e&B%`$h)!{zq2>{ognVfLc!r@)VcBRhElzm3Xw`kGkplQ%rf z6(QN{W;S0|6y0I>tuesAip5N~C+c*?G(%lyhHiy{RbUMli8dQ!8rS$^kB|nLefpMD zLqQ!sk}~pDK<8Ms9{6DZ-S&k4lrBeCM{q}x0$%jCgXy{vjV@bXkKgELO%E~X5TSUr z4`~)dyxK~+k#M5Vujvywn<;)@f{56wiG39H|K$eDARgnfl2h}13i$!NTkMFox-KL~ I%`)WQ0H)`uGynhq diff --git a/docs/articles/index.html b/docs/articles/index.html index d4d7734d..fefc0597 100644 --- a/docs/articles/index.html +++ b/docs/articles/index.html @@ -78,7 +78,7 @@ AMR (for R) - 0.5.0.9021 + 0.5.0.9022 diff --git a/docs/authors.html b/docs/authors.html index 6c9d4a73..0cae75ad 100644 --- a/docs/authors.html +++ b/docs/authors.html @@ -78,7 +78,7 @@ AMR (for R) - 0.5.0.9021 + 0.5.0.9022 diff --git a/docs/index.html b/docs/index.html index 9735202a..131bee7f 100644 --- a/docs/index.html +++ b/docs/index.html @@ -42,7 +42,7 @@ AMR (for R) - 0.5.0.9021 + 0.5.0.9022 diff --git a/docs/news/index.html b/docs/news/index.html index 3c187f88..7bc98225 100644 --- a/docs/news/index.html +++ b/docs/news/index.html @@ -78,7 +78,7 @@ AMR (for R) - 0.5.0.9021 + 0.5.0.9022 @@ -267,7 +267,7 @@ This data is updated annually - check the included version with the new function
  • Exported files from WHONET can be read and used in this package. For functions like first_isolate() and eucast_rules(), all parameters will be filled in automatically.
  • This package now knows all antibiotic abbrevations by EARS-Net (which are also being used by WHONET) - the antibiotics data set now contains a column ears_net.
  • -
  • The function as.mo() now knows all WHONET species abbreviations too, because more than 1,600 microbial abbreviations were added to the microorganisms.codes data set.
  • +
  • The function as.mo() now knows all WHONET species abbreviations too, because almost 2,000 microbial abbreviations were added to the microorganisms.codes data set.
  • @@ -347,14 +347,35 @@ These functions use as.atc()
  • Functions atc_ddd() and atc_groups() have been renamed atc_online_ddd() and atc_online_groups(). The old functions are deprecated and will be removed in a future version.
  • Function guess_mo() is now deprecated in favour of as.mo() and will be removed in future versions
  • Function guess_atc() is now deprecated in favour of as.atc() and will be removed in future versions
  • -
  • Improvements for as.mo():\ +
  • Improvements for as.mo():
      -
    • Incoercible results will now be considered ‘unknown’, MO code UNKNOWN. Properties of these will be translated on foreign systems in all language already previously supported: German, Dutch, French, Italian, Spanish and Portuguese:
    • +
    • Now handles incorrect spelling like i instead of y and f instead of ph:
    - + +
      +
    • Uncertainty of the algorithm is now divided into four levels, 0 to 3, where the default allow_uncertain = TRUE is equal to uncertainty level 2. Run ?as.mo for more info about these levels.
    • +
    +
    # equal:
    +as.mo(..., allow_uncertain = TRUE)
    +as.mo(..., allow_uncertain = 2)
    +
    +# also equal:
    +as.mo(..., allow_uncertain = FALSE)
    +as.mo(..., allow_uncertain = 0)
    +Using as.mo(..., allow_uncertain = 3) could lead to very unreliable results. +
      +
    • Incoercible results will now be considered ‘unknown’, MO code UNKNOWN. On foreign systems, properties of these will be translated to all languages already previously supported: German, Dutch, French, Italian, Spanish and Portuguese:
    • +
    +
    • Fix for vector containing only empty values
    • Finds better results when input is in other languages
    • @@ -400,19 +421,19 @@ These functions use as.atc()
      @@ -486,10 +508,10 @@ These functions use as.atc()
    • Fewer than 3 characters as input for as.mo will return NA
    • Function as.mo (and all mo_* wrappers) now supports genus abbreviations with “species” attached

      -
      as.mo("E. species")        # B_ESCHR
      -mo_fullname("E. spp.")     # "Escherichia species"
      -as.mo("S. spp")            # B_STPHY
      -mo_fullname("S. species")  # "Staphylococcus species"
      +
      as.mo("E. species")        # B_ESCHR
      +mo_fullname("E. spp.")     # "Escherichia species"
      +as.mo("S. spp")            # B_STPHY
      +mo_fullname("S. species")  # "Staphylococcus species"
    • Added parameter combine_IR (TRUE/FALSE) to functions portion_df and count_df, to indicate that all values of I and R must be merged into one, so the output only consists of S vs. IR (susceptible vs. non-susceptible)
    • Fix for portion_*(..., as_percent = TRUE) when minimal number of isolates would not be met
    • @@ -502,15 +524,15 @@ These functions use as.atc()

      They also come with support for German, Dutch, French, Italian, Spanish and Portuguese:

      -
      mo_gramstain("E. coli")
      -# [1] "Gram negative"
      -mo_gramstain("E. coli", language = "de") # German
      -# [1] "Gramnegativ"
      -mo_gramstain("E. coli", language = "es") # Spanish
      -# [1] "Gram negativo"
      -mo_fullname("S. group A", language = "pt") # Portuguese
      -# [1] "Streptococcus grupo A"
      +
      mo_gramstain("E. coli")
      +# [1] "Gram negative"
      +mo_gramstain("E. coli", language = "de") # German
      +# [1] "Gramnegativ"
      +mo_gramstain("E. coli", language = "es") # Spanish
      +# [1] "Gram negativo"
      +mo_fullname("S. group A", language = "pt") # Portuguese
      +# [1] "Streptococcus grupo A"

      Furthermore, former taxonomic names will give a note about the current taxonomic name:

      - +
    • Functions count_R, count_IR, count_I, count_SI and count_S to selectively count resistant or susceptible isolates
    • diff --git a/docs/reference/as.mo.html b/docs/reference/as.mo.html index 30856766..095fbfe4 100644 --- a/docs/reference/as.mo.html +++ b/docs/reference/as.mo.html @@ -47,7 +47,7 @@ - + @@ -80,7 +80,7 @@ AMR (for R) - 0.5.0.9021 + 0.5.0.9022 @@ -237,7 +237,7 @@
      -

      Use this function to determine a valid microorganism ID (mo). Determination is done using intelligent rules and the complete taxonomic kingdoms Archaea, Bacteria, Protozoa, Viruses and most microbial species from the kingdom Fungi (see Source), so the input can be almost anything: a full name (like "Staphylococcus aureus"), an abbreviated name (like "S. aureus"), an abbreviation known in the field (like "MRSA"), or just a genus. You could also select a genus and species column, zie Examples.

      +

      Use this function to determine a valid microorganism ID (mo). Determination is done using intelligent rules and the complete taxonomic kingdoms Bacteria, Chromista, Protozoa, Archaea, Viruses, and most microbial species from the kingdom Fungi (see Source). The input can be almost anything: a full name (like "Staphylococcus aureus"), an abbreviated name (like "S. aureus"), an abbreviation known in the field (like "MRSA"), or just a genus. Please see Examples.

      @@ -271,7 +271,7 @@ allow_uncertain -

      a logical to indicate whether the input should be checked for less possible results, see Details

      +

      a logical (TRUE or FALSE) or a value between 0 and 3 to indicate whether the input should be checked for less possible results, see Details

      reference_df @@ -303,9 +303,9 @@

      Use the mo_property functions to get properties based on the returned code, see Examples.

      Intelligent rules
      This function uses intelligent rules to help getting fast and logical results. It tries to find matches in this order:

        -
      • Taxonomic kingdom: it first searches in Bacteria, then Fungi, then Protozoa

      • -
      • Human pathogenic prevalence: it first searches in more prevalent microorganisms, then less prevalent ones (see section Microbial prevalence of pathogens in humans)

      • Valid MO codes and full names: it first searches in already valid MO code and known genus/species combinations

      • +
      • Human pathogenic prevalence: it first searches in more prevalent microorganisms, then less prevalent ones (see Microbial prevalence of pathogens in humans below)

      • +
      • Taxonomic kingdom: it first searches in Bacteria/Chromista, then Fungi, then Protozoa, then Viruses

      • Breakdown of input values: from here it starts to breakdown input values to find possible matches

      A couple of effects because of these rules:

        @@ -314,14 +314,17 @@ This function uses intelligent rules to help getting fast and logical results. I
      • Something like "stau" or "S aur" will return the ID of Staphylococcus aureus and not Staphylococcus auricularis

      This means that looking up human pathogenic microorganisms takes less time than looking up human non-pathogenic microorganisms.

      Uncertain results
      -When using allow_uncertain = TRUE (which is the default setting), it will use additional rules if all previous rules failed to get valid results. These are:

        -
      • It tries to look for previously accepted (but now invalid) taxonomic names

      • -
      • It strips off values between brackets and the brackets itself, and re-evaluates the input with all previous rules

      • -
      • It strips off words from the end one by one and re-evaluates the input with all previous rules

      • -
      • It strips off words from the start one by one and re-evaluates the input with all previous rules

      • -
      • It tries to look for some manual changes which are not (yet) published to the Catalogue of Life (like Propionibacterium being Cutibacterium)

      • +The algorithm can additionally use three different levels of uncertainty to guess valid results. The default is allow_uncertain = TRUE, which is uqual to uncertainty level 2. Using allow_uncertain = FALSE will skip all of these additional rules:

          +
        • (uncertainty level 1): It tries to look for only matching genera

        • +
        • (uncertainty level 1): It tries to look for previously accepted (but now invalid) taxonomic names

        • +
        • (uncertainty level 1): It tries to look for some manual changes which are not (yet) published to the Catalogue of Life (like Propionibacterium being Cutibacterium)

        • +
        • (uncertainty level 2): It strips off values between brackets and the brackets itself, and re-evaluates the input with all previous rules

        • +
        • (uncertainty level 2): It strips off words from the end one by one and re-evaluates the input with all previous rules

        • +
        • (uncertainty level 3): It strips off words from the start one by one and re-evaluates the input with all previous rules

        • +
        • (uncertainty level 3): It tries any part of the name

        -

        Examples:

          +

          You can also use e.g. as.mo(..., allow_uncertain = 1) to only allow up to level 1 uncertainty.

          +

          Examples:

          • "Streptococcus group B (known as S. agalactiae)". The text between brackets will be removed and a warning will be thrown that the result Streptococcus group B (B_STRPT_GRB) needs review.

          • "S. aureus - please mind: MRSA". The last word will be stripped, after which the function will try to find a match. If it does not, the second last word will be stripped, etc. Again, a warning will be thrown that the result Staphylococcus aureus (B_STPHY_AUR) needs review.

          • "Fluoroquinolone-resistant Neisseria gonorrhoeae". The first word will be stripped, after which the function will try to find a match. A warning will be thrown that the result Neisseria gonorrhoeae (B_NESSR_GON) needs review.

          • @@ -330,7 +333,7 @@ When using allow_uncertain = TRUE (which is the default setting), i

            Use mo_uncertainties() to get a data.frame with all values that were coerced to a valid value, but with uncertainty.

            Use mo_renamed() to get a vector with all values that could be coerced based on an old, previously accepted taxonomic name.

            Microbial prevalence of pathogens in humans
            -The intelligent rules takes into account microbial prevalence of pathogens in humans. It uses three groups and every (sub)species is in the group it matches first. These groups are:

              +The intelligent rules takes into account microbial prevalence of pathogens in humans. It uses three groups and all (sub)species are in only one group. These groups are:

              • 1 (most prevalent): class is Gammaproteobacteria or genus is one of: Enterococcus, Staphylococcus, Streptococcus.

              • 2: phylum is one of: Proteobacteria, Firmicutes, Actinobacteria, Sarcomastigophora or genus is one of: Aspergillus, Bacteroides, Candida, Capnocytophaga, Chryseobacterium, Cryptococcus, Elisabethkingia, Flavobacterium, Fusobacterium, Giardia, Leptotrichia, Mycoplasma, Prevotella, Rhodotorula, Treponema, Trichophyton, Ureaplasma.

              • 3 (least prevalent): all others.

              • @@ -374,6 +377,7 @@ The mo_property functions (like as.mo("S aureus") as.mo("Staphylococcus aureus") as.mo("Staphylococcus aureus (MRSA)") +as.mo("Sthafilokkockus aaureuz") # handles incorrect spelling as.mo("MRSA") # Methicillin Resistant S. aureus as.mo("VISA") # Vancomycin Intermediate S. aureus as.mo("VRSA") # Vancomycin Resistant S. aureus diff --git a/docs/reference/filter_ab_class.html b/docs/reference/filter_ab_class.html index 82e0c76d..e6387dad 100644 --- a/docs/reference/filter_ab_class.html +++ b/docs/reference/filter_ab_class.html @@ -80,7 +80,7 @@ AMR (for R) - 0.5.0.9021 + 0.5.0.9022 diff --git a/docs/reference/index.html b/docs/reference/index.html index 2ed17949..a99f2ee1 100644 --- a/docs/reference/index.html +++ b/docs/reference/index.html @@ -78,7 +78,7 @@ AMR (for R) - 0.5.0.9021 + 0.5.0.9022 diff --git a/docs/reference/like.html b/docs/reference/like.html index 1b0b35c4..18edf3f9 100644 --- a/docs/reference/like.html +++ b/docs/reference/like.html @@ -80,7 +80,7 @@ AMR (for R) - 0.5.0.9021 + 0.5.0.9022 diff --git a/docs/reference/microorganisms.codes.html b/docs/reference/microorganisms.codes.html index 104b3c0c..0b071283 100644 --- a/docs/reference/microorganisms.codes.html +++ b/docs/reference/microorganisms.codes.html @@ -80,7 +80,7 @@ AMR (for R) - 0.5.0.9021 + 0.5.0.9022 @@ -245,7 +245,7 @@

                Format

                -

                A data.frame with 4,731 observations and 2 variables:

                +

                A data.frame with 5,171 observations and 2 variables:

                certe

                Commonly used code of a microorganism

                mo

                ID of the microorganism in the microorganisms data set

                diff --git a/man/as.mo.Rd b/man/as.mo.Rd index a621d410..c6f9167a 100644 --- a/man/as.mo.Rd +++ b/man/as.mo.Rd @@ -31,7 +31,7 @@ mo_renamed() This excludes \emph{Enterococci} at default (who are in group D), use \code{Lancefield = "all"} to also categorise all \emph{Enterococci} as group D.} -\item{allow_uncertain}{a logical to indicate whether the input should be checked for less possible results, see Details} +\item{allow_uncertain}{a logical (\code{TRUE} or \code{FALSE}) or a value between 0 and 3 to indicate whether the input should be checked for less possible results, see Details} \item{reference_df}{a \code{data.frame} to use for extra reference when translating \code{x} to a valid \code{mo}. See \code{\link{set_mo_source}} and \code{\link{get_mo_source}} to automate the usage of your own codes (e.g. used in your analysis or organisation).} } @@ -39,7 +39,7 @@ mo_renamed() Character (vector) with class \code{"mo"}. Unknown values will return \code{NA}. } \description{ -Use this function to determine a valid microorganism ID (\code{mo}). Determination is done using intelligent rules and the complete taxonomic kingdoms Archaea, Bacteria, Protozoa, Viruses and most microbial species from the kingdom Fungi (see Source), so the input can be almost anything: a full name (like \code{"Staphylococcus aureus"}), an abbreviated name (like \code{"S. aureus"}), an abbreviation known in the field (like \code{"MRSA"}), or just a genus. You could also \code{\link{select}} a genus and species column, zie Examples. +Use this function to determine a valid microorganism ID (\code{mo}). Determination is done using intelligent rules and the complete taxonomic kingdoms Bacteria, Chromista, Protozoa, Archaea, Viruses, and most microbial species from the kingdom Fungi (see Source). The input can be almost anything: a full name (like \code{"Staphylococcus aureus"}), an abbreviated name (like \code{"S. aureus"}), an abbreviation known in the field (like \code{"MRSA"}), or just a genus. Please see Examples. } \details{ A microbial ID from this package (class: \code{mo}) typically looks like these examples:\cr @@ -65,9 +65,9 @@ Use the \code{\link{mo_property}} functions to get properties based on the retur \strong{Intelligent rules} \cr This function uses intelligent rules to help getting fast and logical results. It tries to find matches in this order: \itemize{ - \item{Taxonomic kingdom: it first searches in Bacteria, then Fungi, then Protozoa} - \item{Human pathogenic prevalence: it first searches in more prevalent microorganisms, then less prevalent ones (see section \emph{Microbial prevalence of pathogens in humans})} \item{Valid MO codes and full names: it first searches in already valid MO code and known genus/species combinations} + \item{Human pathogenic prevalence: it first searches in more prevalent microorganisms, then less prevalent ones (see \emph{Microbial prevalence of pathogens in humans} below)} + \item{Taxonomic kingdom: it first searches in Bacteria/Chromista, then Fungi, then Protozoa, then Viruses} \item{Breakdown of input values: from here it starts to breakdown input values to find possible matches} } @@ -80,15 +80,19 @@ A couple of effects because of these rules: This means that looking up human pathogenic microorganisms takes less time than looking up human non-pathogenic microorganisms. \strong{Uncertain results} \cr -When using \code{allow_uncertain = TRUE} (which is the default setting), it will use additional rules if all previous rules failed to get valid results. These are: +The algorithm can additionally use three different levels of uncertainty to guess valid results. The default is \code{allow_uncertain = TRUE}, which is uqual to uncertainty level 2. Using \code{allow_uncertain = FALSE} will skip all of these additional rules: \itemize{ - \item{It tries to look for previously accepted (but now invalid) taxonomic names} - \item{It strips off values between brackets and the brackets itself, and re-evaluates the input with all previous rules} - \item{It strips off words from the end one by one and re-evaluates the input with all previous rules} - \item{It strips off words from the start one by one and re-evaluates the input with all previous rules} - \item{It tries to look for some manual changes which are not (yet) published to the Catalogue of Life (like \emph{Propionibacterium} being \emph{Cutibacterium})} + \item{(uncertainty level 1): It tries to look for only matching genera} + \item{(uncertainty level 1): It tries to look for previously accepted (but now invalid) taxonomic names} + \item{(uncertainty level 1): It tries to look for some manual changes which are not (yet) published to the Catalogue of Life (like \emph{Propionibacterium} being \emph{Cutibacterium})} + \item{(uncertainty level 2): It strips off values between brackets and the brackets itself, and re-evaluates the input with all previous rules} + \item{(uncertainty level 2): It strips off words from the end one by one and re-evaluates the input with all previous rules} + \item{(uncertainty level 3): It strips off words from the start one by one and re-evaluates the input with all previous rules} + \item{(uncertainty level 3): It tries any part of the name} } +You can also use e.g. \code{as.mo(..., allow_uncertain = 1)} to only allow up to level 1 uncertainty. + Examples: \itemize{ \item{\code{"Streptococcus group B (known as S. agalactiae)"}. The text between brackets will be removed and a warning will be thrown that the result \emph{Streptococcus group B} (\code{B_STRPT_GRB}) needs review.} @@ -103,7 +107,7 @@ Use \code{mo_uncertainties()} to get a data.frame with all values that were coer Use \code{mo_renamed()} to get a vector with all values that could be coerced based on an old, previously accepted taxonomic name. \strong{Microbial prevalence of pathogens in humans} \cr -The intelligent rules takes into account microbial prevalence of pathogens in humans. It uses three groups and every (sub)species is in the group it matches first. These groups are: +The intelligent rules takes into account microbial prevalence of pathogens in humans. It uses three groups and all (sub)species are in only one group. These groups are: \itemize{ \item{1 (most prevalent): class is Gammaproteobacteria \strong{or} genus is one of: \emph{Enterococcus}, \emph{Staphylococcus}, \emph{Streptococcus}.} \item{2: phylum is one of: Proteobacteria, Firmicutes, Actinobacteria, Sarcomastigophora \strong{or} genus is one of: \emph{Aspergillus}, \emph{Bacteroides}, \emph{Candida}, \emph{Capnocytophaga}, \emph{Chryseobacterium}, \emph{Cryptococcus}, \emph{Elisabethkingia}, \emph{Flavobacterium}, \emph{Fusobacterium}, \emph{Giardia}, \emph{Leptotrichia}, \emph{Mycoplasma}, \emph{Prevotella}, \emph{Rhodotorula}, \emph{Treponema}, \emph{Trichophyton}, \emph{Ureaplasma}.} @@ -146,6 +150,7 @@ as.mo("S. aureus") as.mo("S aureus") as.mo("Staphylococcus aureus") as.mo("Staphylococcus aureus (MRSA)") +as.mo("Sthafilokkockus aaureuz") # handles incorrect spelling as.mo("MRSA") # Methicillin Resistant S. aureus as.mo("VISA") # Vancomycin Intermediate S. aureus as.mo("VRSA") # Vancomycin Resistant S. aureus diff --git a/man/microorganisms.codes.Rd b/man/microorganisms.codes.Rd index 2bb9fe22..46252cac 100644 --- a/man/microorganisms.codes.Rd +++ b/man/microorganisms.codes.Rd @@ -4,7 +4,7 @@ \name{microorganisms.codes} \alias{microorganisms.codes} \title{Translation table for microorganism codes} -\format{A \code{\link{data.frame}} with 4,731 observations and 2 variables: +\format{A \code{\link{data.frame}} with 5,171 observations and 2 variables: \describe{ \item{\code{certe}}{Commonly used code of a microorganism} \item{\code{mo}}{ID of the microorganism in the \code{\link{microorganisms}} data set} diff --git a/tests/testthat/test-mo.R b/tests/testthat/test-mo.R index 79aeb460..c4b535c3 100644 --- a/tests/testthat/test-mo.R +++ b/tests/testthat/test-mo.R @@ -80,10 +80,11 @@ test_that("as.mo works", { "staaur", "S. aureus", "S aureus", + "Sthafilokkockus aureeuzz", "Staphylococcus aureus", "MRSA", "VISA"))), - rep("B_STPHY_AUR", 8)) + rep("B_STPHY_AUR", 9)) expect_identical( as.character( as.mo(c('EHEC', 'EPEC', 'EIEC', 'STEC', 'ATEC'))), @@ -229,7 +230,7 @@ test_that("as.mo works", { c("Microbacterium paraoxidans", "Streptococcus suis (bovis gr)", "Raoultella (here some text) terrigena")))), - c("B_MCRBC", "B_STRPT_SUI", "B_RLTLL_TER")) + c("B_MCRBC_PAR", "B_STRPT_SUI", "B_RLTLL_TER")) print(mo_uncertainties()) # Salmonella (City) are all actually Salmonella enterica spp (City)