From 53464ff1c8b0d15a37988a89a50f86663cc967fa Mon Sep 17 00:00:00 2001 From: "Matthijs S. Berends" Date: Fri, 23 Mar 2018 14:46:02 +0100 Subject: [PATCH] - For functions `first_isolate`, `EUCAST_rules` the antibiotic column names are case-insensitive - Functions `first_isolate`, `EUCAST_rules` and `rsi_predict` supports tidyverse-like evaluation of parameters (no need to quote columns them anymore) - Functions `clipboard_import` and `clipboard_export` as helper functions to quickly copy and paste from/to software like Excel and SPSS - Renamed dataset `bactlist` to `microorganisms` --- DESCRIPTION | 6 +- NAMESPACE | 19 +- NEWS | 17 +- R/EUCAST.R | 420 ++++++++++-------- R/atc.R | 25 +- R/clipboard.R | 84 ++++ R/data.R | 61 ++- R/first_isolates.R | 50 ++- R/join.R | 48 +- R/misc.R | 6 +- R/rsi_analysis.R | 124 +++--- data/bactlist.rda | Bin 39290 -> 0 bytes data/bactlist.umcg.rda | Bin 6458 -> 0 bytes data/microorganisms.rda | Bin 0 -> 39251 bytes data/microorganisms.umcg.rda | Bin 0 -> 6450 bytes man/EUCAST.Rd | 8 +- man/abname.Rd | 6 +- man/antibiotics.Rd | 2 +- man/clipboard.Rd | 50 +++ man/first_isolate.Rd | 14 +- man/guess_bactid.Rd | 2 +- man/join.Rd | 36 +- man/key_antibiotics.Rd | 4 +- man/{bactlist.Rd => microorganisms.Rd} | 10 +- ...actlist.umcg.Rd => microorganisms.umcg.Rd} | 12 +- man/mo_property.Rd | 6 +- man/rsi_df.Rd | 8 +- man/rsi_predict.Rd | 2 +- man/septic_patients.Rd | 46 +- 29 files changed, 693 insertions(+), 373 deletions(-) create mode 100644 R/clipboard.R delete mode 100644 data/bactlist.rda delete mode 100644 data/bactlist.umcg.rda create mode 100644 data/microorganisms.rda create mode 100644 data/microorganisms.umcg.rda create mode 100644 man/clipboard.Rd rename man/{bactlist.Rd => microorganisms.Rd} (86%) rename man/{bactlist.umcg.Rd => microorganisms.umcg.Rd} (56%) diff --git a/DESCRIPTION b/DESCRIPTION index d82324d9..ac9a1b5c 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: AMR Version: 0.1.2 -Date: 2018-03-19 +Date: 2018-03-23 Title: Antimicrobial Resistance Analysis Authors@R: c( person( @@ -25,8 +25,8 @@ Description: Functions to simplify the analysis of Antimicrobial Resistance (AMR on antibiograms according to Leclercq (2013) . Depends: R (>= 3.0) -Imports: dplyr (>= 0.7.0), reshape2 (>= 1.4.0), xml2, rvest -URL: https://github.com/msberends/AMR +Imports: dplyr (>= 0.7.0), knitr, reshape2 (>= 1.4.0), xml2, rvest +URL: https://cran.r-project.org/package=AMR BugReports: https://github.com/msberends/AMR/issues License: GPL-2 | file LICENSE Encoding: UTF-8 diff --git a/NAMESPACE b/NAMESPACE index 1654c1e5..45026ecc 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -13,25 +13,27 @@ S3method(summary,mic) S3method(summary,rsi) export(EUCAST_rules) export(abname) -export(anti_join_bactlist) +export(anti_join_microorganisms) export(as.mic) export(as.rsi) export(atc_property) +export(clipboard_export) +export(clipboard_import) export(first_isolate) -export(full_join_bactlist) +export(full_join_microorganisms) export(guess_bactid) -export(inner_join_bactlist) +export(inner_join_microorganisms) export(interpretive_reading) export(is.mic) export(is.rsi) export(key_antibiotics) -export(left_join_bactlist) +export(left_join_microorganisms) export(mo_property) -export(right_join_bactlist) +export(right_join_microorganisms) export(rsi) export(rsi_df) export(rsi_predict) -export(semi_join_bactlist) +export(semi_join_microorganisms) exportMethods(as.double.mic) exportMethods(as.integer.mic) exportMethods(as.numeric.mic) @@ -48,6 +50,7 @@ importFrom(dplyr,all_vars) importFrom(dplyr,any_vars) importFrom(dplyr,arrange) importFrom(dplyr,arrange_at) +importFrom(dplyr,as_tibble) importFrom(dplyr,between) importFrom(dplyr,filter) importFrom(dplyr,filter_at) @@ -73,5 +76,9 @@ importFrom(graphics,text) importFrom(reshape2,dcast) importFrom(rvest,html_nodes) importFrom(rvest,html_table) +importFrom(utils,object.size) importFrom(utils,packageDescription) +importFrom(utils,read.delim) +importFrom(utils,write.table) +importFrom(utils,writeClipboard) importFrom(xml2,read_html) diff --git a/NEWS b/NEWS index 1c223d99..a9135081 100644 --- a/NEWS +++ b/NEWS @@ -1,11 +1,14 @@ ## 0.1.2 -- Added new function `guess_bactid` to determine the ID of a microorganism based on genus/species -- Renamed `ablist` to `antibiotics` -- Added support for character vector in join functions -- Altered `%like%` to make it case insensitive -- Added new algorithm to determine weighted isolates, can now be `points` or `keyantibiotics, see `?first_isolate` -- Function `first_isolate` supports tidyverse-like evaluation of parameters (no need to quote them anymore) -- Functions `as.rsi` and `as.mic` now add the package name and version as attribute +- NEW: Function `guess_bactid` to determine the ID of a microorganism based on genus/species +- NEW: Functions `clipboard_import` and `clipboard_export` as helper functions to quickly copy and paste from/to software like Excel and SPSS +- NEW: New algorithm to determine weighted isolates, can now be `"points"` or `"keyantibiotics"`, see `?first_isolate` +- EDIT: Renamed dataset `ablist` to `antibiotics` +- EDIT: Renamed dataset `bactlist` to `microorganisms` +- EDIT: Added support for character vector in join functions +- EDIT: Altered `%like%` to make it case insensitive +- EDIT: Functions `first_isolate`, `EUCAST_rules` and `rsi_predict` supports tidyverse-like evaluation of parameters (no need to quote columns them anymore) +- EDIT: For functions `first_isolate`, `EUCAST_rules` the antibiotic column names are case-insensitive +- EDIT: Functions `as.rsi` and `as.mic` now add the package name and version as attribute ## 0.1.1 - `EUCAST_rules` applies for amoxicillin even if ampicillin is missing diff --git a/R/EUCAST.R b/R/EUCAST.R index 54f525f9..ef70190a 100644 --- a/R/EUCAST.R +++ b/R/EUCAST.R @@ -20,7 +20,7 @@ #' #' Apply expert rules (like intrinsic resistance), as defined by the European Committee on Antimicrobial Susceptibility Testing (EUCAST, \url{http://eucast.org}), see \emph{Source}. #' @param tbl table with antibiotic columns, like e.g. \code{amox} and \code{amcl} -#' @param col_bactcode column name of the bacteria ID in \code{tbl} - values of this column should be present in \code{bactlist$bactid}, see \code{\link{bactlist}} +#' @param col_bactid column name of the bacteria ID in \code{tbl} - values of this column should be present in \code{microorganisms$bactid}, see \code{\link{microorganisms}} #' @param info print progress #' @param amcl,amik,amox,ampi,azit,aztr,cefa,cfra,cfep,cfot,cfox,cfta,cftr,cfur,chlo,cipr,clar,clin,clox,coli,czol,dapt,doxy,erta,eryt,fosf,fusi,gent,imip,kana,levo,linc,line,mero,mino,moxi,nali,neom,neti,nitr,novo,norf,oflo,peni,pita,poly,qida,rifa,roxi,siso,teic,tetr,tica,tige,tobr,trim,trsu,vanc column names of antibiotics. Use \code{NA} to skip a column, like \code{tica = NA}. Non-existing column will be skipped. #' @param ... parameters that are passed on to \code{EUCAST_rules} @@ -33,8 +33,8 @@ #' Leclercq et al. \strong{EUCAST expert rules in antimicrobial susceptibility testing.} \emph{Clin Microbiol Infect.} 2013;19(2):141-60. \cr #' \url{https://doi.org/10.1111/j.1469-0691.2011.03703.x} \cr #' \cr -#' EUCAST Expert Rules Version 3.1: \cr -#' \url{http://www.eucast.org/expert_rules_and_intrinsic_resistance} +#' EUCAST Expert Rules Version 3.1 (Intrinsic Resistance and Exceptional Phenotypes Tables): \cr +#' \url{http://www.eucast.org/fileadmin/src/media/PDFs/EUCAST_files/Expert_Rules/Expert_rules_intrinsic_exceptional_V3.1.pdf} #' @examples #' a <- data.frame(bactid = c("STAAUR", # Staphylococcus aureus #' "ENCFAE", # Enterococcus faecalis @@ -52,7 +52,7 @@ #' b <- EUCAST_rules(a) #' b EUCAST_rules <- function(tbl, - col_bactcode = 'bactid', + col_bactid = 'bactid', info = TRUE, amcl = 'amcl', amik = 'amik', @@ -112,95 +112,168 @@ EUCAST_rules <- function(tbl, trim = 'trim', trsu = 'trsu', vanc = 'vanc') { + + EUCAST_VERSION <- "3.1" - if (!col_bactcode %in% colnames(tbl)) { - stop('Column ', col_bactcode, ' not found.') + # support using columns as objects; the tidyverse way + amcl <- quasiquotate(deparse(substitute(amcl)), amcl) + amik <- quasiquotate(deparse(substitute(amik)), amik) + amox <- quasiquotate(deparse(substitute(amox)), amox) + ampi <- quasiquotate(deparse(substitute(ampi)), ampi) + azit <- quasiquotate(deparse(substitute(azit)), azit) + aztr <- quasiquotate(deparse(substitute(aztr)), aztr) + cefa <- quasiquotate(deparse(substitute(cefa)), cefa) + cfra <- quasiquotate(deparse(substitute(cfra)), cfra) + cfep <- quasiquotate(deparse(substitute(cfep)), cfep) + cfot <- quasiquotate(deparse(substitute(cfot)), cfot) + cfox <- quasiquotate(deparse(substitute(cfox)), cfox) + cfta <- quasiquotate(deparse(substitute(cfta)), cfta) + cftr <- quasiquotate(deparse(substitute(cftr)), cftr) + cfur <- quasiquotate(deparse(substitute(cfur)), cfur) + chlo <- quasiquotate(deparse(substitute(chlo)), chlo) + cipr <- quasiquotate(deparse(substitute(cipr)), cipr) + clar <- quasiquotate(deparse(substitute(clar)), clar) + clin <- quasiquotate(deparse(substitute(clin)), clin) + clox <- quasiquotate(deparse(substitute(clox)), clox) + coli <- quasiquotate(deparse(substitute(coli)), coli) + czol <- quasiquotate(deparse(substitute(czol)), czol) + dapt <- quasiquotate(deparse(substitute(dapt)), dapt) + doxy <- quasiquotate(deparse(substitute(doxy)), doxy) + erta <- quasiquotate(deparse(substitute(erta)), erta) + eryt <- quasiquotate(deparse(substitute(eryt)), eryt) + fosf <- quasiquotate(deparse(substitute(fosf)), fosf) + fusi <- quasiquotate(deparse(substitute(fusi)), fusi) + gent <- quasiquotate(deparse(substitute(gent)), gent) + imip <- quasiquotate(deparse(substitute(imip)), imip) + kana <- quasiquotate(deparse(substitute(kana)), kana) + levo <- quasiquotate(deparse(substitute(levo)), levo) + linc <- quasiquotate(deparse(substitute(linc)), linc) + line <- quasiquotate(deparse(substitute(line)), line) + mero <- quasiquotate(deparse(substitute(mero)), mero) + mino <- quasiquotate(deparse(substitute(mino)), mino) + moxi <- quasiquotate(deparse(substitute(moxi)), moxi) + nali <- quasiquotate(deparse(substitute(nali)), nali) + neom <- quasiquotate(deparse(substitute(neom)), neom) + neti <- quasiquotate(deparse(substitute(neti)), neti) + nitr <- quasiquotate(deparse(substitute(nitr)), nitr) + novo <- quasiquotate(deparse(substitute(novo)), novo) + norf <- quasiquotate(deparse(substitute(norf)), norf) + oflo <- quasiquotate(deparse(substitute(oflo)), oflo) + peni <- quasiquotate(deparse(substitute(peni)), peni) + pita <- quasiquotate(deparse(substitute(pita)), pita) + poly <- quasiquotate(deparse(substitute(poly)), poly) + qida <- quasiquotate(deparse(substitute(qida)), qida) + rifa <- quasiquotate(deparse(substitute(rifa)), rifa) + roxi <- quasiquotate(deparse(substitute(roxi)), roxi) + siso <- quasiquotate(deparse(substitute(siso)), siso) + teic <- quasiquotate(deparse(substitute(teic)), teic) + tetr <- quasiquotate(deparse(substitute(tetr)), tetr) + tica <- quasiquotate(deparse(substitute(tica)), tica) + tige <- quasiquotate(deparse(substitute(tige)), tige) + tobr <- quasiquotate(deparse(substitute(tobr)), tobr) + trim <- quasiquotate(deparse(substitute(trim)), trim) + trsu <- quasiquotate(deparse(substitute(trsu)), trsu) + vanc <- quasiquotate(deparse(substitute(vanc)), vanc) + + if (!col_bactid %in% colnames(tbl)) { + stop('Column ', col_bactid, ' not found.') } - # kolommen controleren - col.list <- c(amcl, amik, amox, ampi, azit, aztr, cefa, cfra, cfep, - cfot, cfox, cfta, cftr, cfur, cipr, clar, clin, clox, coli, czol, - dapt, doxy, erta, eryt, fusi, gent, imip, kana, levo, linc, line, - mero, mino, moxi, nali, neom, neti, nitr, novo, norf, oflo, peni, - pita, poly, qida, rifa, roxi, siso, teic, tetr, tica, tige, tobr, - trim, trsu, vanc) + # check columns + col.list <- c(amcl, amik, amox, ampi, azit, aztr, cefa, cfra, cfep, cfot, + cfox, cfta, cftr, cfur, chlo, cipr, clar, clin, clox, coli, + czol, dapt, doxy, erta, eryt, fosf, fusi, gent, imip, kana, + levo, linc, line, mero, mino, moxi, nali, neom, neti, nitr, + novo, norf, oflo, peni, pita, poly, qida, rifa, roxi, siso, + teic, tetr, tica, tige, tobr, trim, trsu, vanc) col.list <- col.list[!is.na(col.list)] + col.list.bak <- col.list + # are they available as upper case then? + for (i in 1:length(col.list)) { + if (toupper(col.list[i]) %in% colnames(tbl)) { + col.list[i] <- toupper(col.list[i]) + } else if (tolower(col.list[i]) %in% colnames(tbl)) { + col.list[i] <- tolower(col.list[i]) + } else if (!col.list[i] %in% colnames(tbl)) { + col.list[i] <- NA + } + } if (!all(col.list %in% colnames(tbl))) { if (info == TRUE) { cat('\n') } if (info == TRUE) { - warning('These columns do not exist and will be ignored:\n', - col.list[!(col.list %in% colnames(tbl))] %>% toString(), + warning('These columns do not exist and will be ignored: ', + col.list.bak[!(col.list %in% colnames(tbl))] %>% toString(), immediate. = TRUE, call. = FALSE) } - if (!amcl %in% colnames(tbl)) { amcl <- NA } - if (!amik %in% colnames(tbl)) { amik <- NA } - if (!amox %in% colnames(tbl)) { amox <- NA } - if (!ampi %in% colnames(tbl)) { ampi <- NA } - if (!azit %in% colnames(tbl)) { azit <- NA } - if (!aztr %in% colnames(tbl)) { aztr <- NA } - if (!cefa %in% colnames(tbl)) { cefa <- NA } - if (!cfra %in% colnames(tbl)) { cfra <- NA } - if (!cfep %in% colnames(tbl)) { cfep <- NA } - if (!cfot %in% colnames(tbl)) { cfot <- NA } - if (!cfox %in% colnames(tbl)) { cfox <- NA } - if (!cfta %in% colnames(tbl)) { cfta <- NA } - if (!cftr %in% colnames(tbl)) { cftr <- NA } - if (!cfur %in% colnames(tbl)) { cfur <- NA } - if (!chlo %in% colnames(tbl)) { chlo <- NA } - if (!cipr %in% colnames(tbl)) { cipr <- NA } - if (!clar %in% colnames(tbl)) { clar <- NA } - if (!clin %in% colnames(tbl)) { clin <- NA } - if (!clox %in% colnames(tbl)) { clox <- NA } - if (!coli %in% colnames(tbl)) { coli <- NA } - if (!czol %in% colnames(tbl)) { czol <- NA } - if (!dapt %in% colnames(tbl)) { dapt <- NA } - if (!doxy %in% colnames(tbl)) { doxy <- NA } - if (!erta %in% colnames(tbl)) { erta <- NA } - if (!eryt %in% colnames(tbl)) { eryt <- NA } - if (!fosf %in% colnames(tbl)) { fosf <- NA } - if (!fusi %in% colnames(tbl)) { fusi <- NA } - if (!gent %in% colnames(tbl)) { gent <- NA } - if (!imip %in% colnames(tbl)) { imip <- NA } - if (!kana %in% colnames(tbl)) { kana <- NA } - if (!levo %in% colnames(tbl)) { levo <- NA } - if (!linc %in% colnames(tbl)) { linc <- NA } - if (!line %in% colnames(tbl)) { line <- NA } - if (!mero %in% colnames(tbl)) { mero <- NA } - if (!mino %in% colnames(tbl)) { mino <- NA } - if (!moxi %in% colnames(tbl)) { moxi <- NA } - if (!nali %in% colnames(tbl)) { nali <- NA } - if (!neom %in% colnames(tbl)) { neom <- NA } - if (!neti %in% colnames(tbl)) { neti <- NA } - if (!nitr %in% colnames(tbl)) { nitr <- NA } - if (!novo %in% colnames(tbl)) { novo <- NA } - if (!norf %in% colnames(tbl)) { norf <- NA } - if (!oflo %in% colnames(tbl)) { oflo <- NA } - if (!peni %in% colnames(tbl)) { peni <- NA } - if (!pita %in% colnames(tbl)) { pita <- NA } - if (!poly %in% colnames(tbl)) { poly <- NA } - if (!qida %in% colnames(tbl)) { qida <- NA } - if (!rifa %in% colnames(tbl)) { rifa <- NA } - if (!roxi %in% colnames(tbl)) { roxi <- NA } - if (!siso %in% colnames(tbl)) { siso <- NA } - if (!teic %in% colnames(tbl)) { teic <- NA } - if (!tetr %in% colnames(tbl)) { tetr <- NA } - if (!tica %in% colnames(tbl)) { tica <- NA } - if (!tige %in% colnames(tbl)) { tige <- NA } - if (!tobr %in% colnames(tbl)) { tobr <- NA } - if (!trim %in% colnames(tbl)) { trim <- NA } - if (!trsu %in% colnames(tbl)) { trsu <- NA } - if (!vanc %in% colnames(tbl)) { vanc <- NA } } + amcl <- col.list[1] + amik <- col.list[2] + amox <- col.list[3] + ampi <- col.list[4] + azit <- col.list[5] + aztr <- col.list[6] + cefa <- col.list[7] + cfra <- col.list[8] + cfep <- col.list[9] + cfot <- col.list[10] + cfox <- col.list[11] + cfta <- col.list[12] + cftr <- col.list[13] + cfur <- col.list[14] + chlo <- col.list[15] + cipr <- col.list[16] + clar <- col.list[17] + clin <- col.list[18] + clox <- col.list[19] + coli <- col.list[20] + czol <- col.list[21] + dapt <- col.list[22] + doxy <- col.list[23] + erta <- col.list[24] + eryt <- col.list[25] + fosf <- col.list[26] + fusi <- col.list[27] + gent <- col.list[28] + imip <- col.list[29] + kana <- col.list[30] + levo <- col.list[31] + linc <- col.list[32] + line <- col.list[33] + mero <- col.list[34] + mino <- col.list[35] + moxi <- col.list[36] + nali <- col.list[37] + neom <- col.list[38] + neti <- col.list[39] + nitr <- col.list[40] + novo <- col.list[41] + norf <- col.list[42] + oflo <- col.list[43] + peni <- col.list[44] + pita <- col.list[45] + poly <- col.list[46] + qida <- col.list[47] + rifa <- col.list[48] + roxi <- col.list[49] + siso <- col.list[50] + teic <- col.list[51] + tetr <- col.list[52] + tica <- col.list[53] + tige <- col.list[54] + tobr <- col.list[55] + trim <- col.list[56] + trsu <- col.list[57] + vanc <- col.list[58] + total <- 0 total_rows <- integer(0) - # functie voor uitvoeren + # helper function for editing the table edit_rsi <- function(to, rows, cols) { - #voortgang$tick()$print() cols <- cols[!is.na(cols)] if (length(rows) > 0 & length(cols) > 0) { tbl[rows, cols] <<- to @@ -209,97 +282,99 @@ EUCAST_rules <- function(tbl, } } - # bactlist aan vastknopen (bestaande kolommen krijgen extra suffix) - joinby <- colnames(AMR::bactlist)[1] - names(joinby) <- col_bactcode - tbl <- tbl %>% left_join(y = AMR::bactlist, by = joinby, suffix = c("_tempbactlist", "")) + # join to microorganisms table + joinby <- colnames(AMR::microorganisms)[1] + names(joinby) <- col_bactid + tbl <- tbl %>% left_join(y = AMR::microorganisms, by = joinby, suffix = c("_tempmicroorganisms", "")) - # antibioticagroepen - aminoglycosiden <- c(tobr, gent, kana, neom, neti, siso) - tetracyclines <- c(doxy, mino, tetr) # sinds EUCAST v3.1 is tige(cycline) apart - polymyxines <- c(poly, coli) - macroliden <- c(eryt, azit, roxi, clar) # sinds EUCAST v3.1 is clinda apart - glycopeptiden <- c(vanc, teic) - streptogramines <- qida # eigenlijk pristinamycine en quinupristine/dalfopristine - cefalosporines <- c(cfep, cfot, cfox, cfra, cfta, cftr, cfur, czol) + # antibiotic classes + aminoglycosides <- c(tobr, gent, kana, neom, neti, siso) + tetracyclines <- c(doxy, mino, tetr) # since EUCAST v3.1 tige(cycline) is set apart + polymyxins <- c(poly, coli) + macrolides <- c(eryt, azit, roxi, clar) # since EUCAST v3.1 clinda is set apart + glycopeptides <- c(vanc, teic) + streptogramins <- qida # should officially also be pristinamycin and quinupristin/dalfopristin + cephalosporins <- c(cfep, cfot, cfox, cfra, cfta, cftr, cfur, czol) carbapenems <- c(erta, imip, mero) - aminopenicillines <- c(ampi, amox) - ureidopenicillines <- pita # eigenlijk ook azlo en mezlo - fluorochinolonen <- c(oflo, cipr, norf, levo, moxi) + aminopenicillins <- c(ampi, amox) + ureidopenicillins <- pita # should officially also be azlo and mezlo + fluoroquinolones <- c(oflo, cipr, norf, levo, moxi) if (info == TRUE) { - cat('\nApplying rules to', + cat( + paste0( + '\nApplying rules to ', tbl[!is.na(tbl$genus),] %>% nrow() %>% format(big.mark = ","), - 'rows according to "EUCAST Expert Rules Version 3.1"\n\n') + ' rows according to "EUCAST Expert Rules Version ', EUCAST_VERSION, '"\n') + ) } # Table 1: Intrinsic resistance in Enterobacteriaceae ---- if (info == TRUE) { cat('...Table 1: Intrinsic resistance in Enterobacteriaceae\n') } - #voortgang <- progress_estimated(17) - # Intrisiek R voor groep + # Intrisiek R for this group edit_rsi(to = 'R', rows = which(tbl$family == 'Enterobacteriaceae'), - cols = c(peni, glycopeptiden, fusi, macroliden, linc, streptogramines, rifa, dapt, line)) + cols = c(peni, glycopeptides, fusi, macrolides, linc, streptogramins, rifa, dapt, line)) # Citrobacter edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Citrobacter (koseri|amalonaticus|sedlakii|farmeri|rodentium)'), - cols = c(aminopenicillines, tica)) + cols = c(aminopenicillins, tica)) edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Citrobacter (freundii|braakii|murliniae|werkmanii|youngae)'), - cols = c(aminopenicillines, amcl, czol, cfox)) + cols = c(aminopenicillins, amcl, czol, cfox)) # Enterobacter edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Enterobacter cloacae'), - cols = c(aminopenicillines, amcl, czol, cfox)) + cols = c(aminopenicillins, amcl, czol, cfox)) edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Enterobacter aerogenes'), - cols = c(aminopenicillines, amcl, czol, cfox)) + cols = c(aminopenicillins, amcl, czol, cfox)) # Escherichia edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Escherichia hermanni'), - cols = c(aminopenicillines, tica)) + cols = c(aminopenicillins, tica)) # Hafnia edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Hafnia alvei'), - cols = c(aminopenicillines, amcl, czol, cfox)) + cols = c(aminopenicillins, amcl, czol, cfox)) # Klebsiella edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Klebsiella'), - cols = c(aminopenicillines, tica)) + cols = c(aminopenicillins, tica)) # Morganella / Proteus edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Morganella morganii'), - cols = c(aminopenicillines, amcl, czol, tetracyclines, polymyxines, nitr)) + cols = c(aminopenicillins, amcl, czol, tetracyclines, polymyxins, nitr)) edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Proteus mirabilis'), - cols = c(tetracyclines, tige, polymyxines, nitr)) + cols = c(tetracyclines, tige, polymyxins, nitr)) edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Proteus penneri'), - cols = c(aminopenicillines, czol, cfur, tetracyclines, tige, polymyxines, nitr)) + cols = c(aminopenicillins, czol, cfur, tetracyclines, tige, polymyxins, nitr)) edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Proteus vulgaris'), - cols = c(aminopenicillines, czol, cfur, tetracyclines, tige, polymyxines, nitr)) + cols = c(aminopenicillins, czol, cfur, tetracyclines, tige, polymyxins, nitr)) # Providencia edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Providencia rettgeri'), - cols = c(aminopenicillines, amcl, czol, cfur, tetracyclines, tige, polymyxines, nitr)) + cols = c(aminopenicillins, amcl, czol, cfur, tetracyclines, tige, polymyxins, nitr)) edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Providencia stuartii'), - cols = c(aminopenicillines, amcl, czol, cfur, tetracyclines, tige, polymyxines, nitr)) + cols = c(aminopenicillins, amcl, czol, cfur, tetracyclines, tige, polymyxins, nitr)) # Raoultella edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Raoultella'), - cols = c(aminopenicillines, tica)) + cols = c(aminopenicillins, tica)) # Serratia edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Serratia marcescens'), - cols = c(aminopenicillines, amcl, czol, cfox, cfur, tetracyclines[tetracyclines != 'mino'], polymyxines, nitr)) + cols = c(aminopenicillins, amcl, czol, cfox, cfur, tetracyclines[tetracyclines != 'mino'], polymyxins, nitr)) # Yersinia edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Yersinia enterocolitica'), - cols = c(aminopenicillines, amcl, tica, czol, cfox)) + cols = c(aminopenicillins, amcl, tica, czol, cfox)) edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Yersinia pseudotuberculosis'), cols = c(poly, coli)) @@ -309,8 +384,7 @@ EUCAST_rules <- function(tbl, if (info == TRUE) { cat('...Table 2: Intrinsic resistance in non-fermentative Gram-negative bacteria\n') } - #voortgang <- progress_estimated(8) - # Intrisiek R voor groep + # Intrisiek R for this group edit_rsi(to = 'R', rows = which(tbl$genus %in% c('Achromobacter', 'Acinetobacter', @@ -322,54 +396,53 @@ EUCAST_rules <- function(tbl, 'Ochrobactrum', 'Pseudomonas', 'Stenotrophomonas')), - cols = c(peni, cfox, cfur, glycopeptiden, fusi, macroliden, linc, streptogramines, rifa, dapt, line)) + cols = c(peni, cfox, cfur, glycopeptides, fusi, macrolides, linc, streptogramins, rifa, dapt, line)) # Acinetobacter edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Acinetobacter (baumannii|pittii|nosocomialis|calcoaceticus)'), - cols = c(aminopenicillines, amcl, czol, cfot, cftr, aztr, erta, trim, fosf, tetracyclines[tetracyclines != 'mino'])) + cols = c(aminopenicillins, amcl, czol, cfot, cftr, aztr, erta, trim, fosf, tetracyclines[tetracyclines != 'mino'])) # Achromobacter edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Achromobacter (xylosoxydans|xylosoxidans)'), - cols = c(aminopenicillines, czol, cfot, cftr, erta)) + cols = c(aminopenicillins, czol, cfot, cftr, erta)) # Burkholderia edit_rsi(to = 'R', # onder 'Burkholderia cepacia complex' vallen deze species allemaal: PMID 16217180. rows = which(tbl$fullname %like% '^Burkholderia (cepacia|multivorans|cenocepacia|stabilis|vietnamiensis|dolosa|ambifaria|anthina|pyrrocinia|ubonensis)'), - cols = c(aminopenicillines, amcl, tica, pita, czol, cfot, cftr, aztr, erta, cipr, chlo, aminoglycosiden, trim, fosf, polymyxines)) + cols = c(aminopenicillins, amcl, tica, pita, czol, cfot, cftr, aztr, erta, cipr, chlo, aminoglycosides, trim, fosf, polymyxins)) # Elizabethkingia edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Elizabethkingia meningoseptic(a|um)'), - cols = c(aminopenicillines, amcl, tica, czol, cfot, cftr, cfta, cfep, aztr, erta, imip, mero, polymyxines)) + cols = c(aminopenicillins, amcl, tica, czol, cfot, cftr, cfta, cfep, aztr, erta, imip, mero, polymyxins)) # Ochrobactrum edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Ochrobactrum anthropi'), - cols = c(aminopenicillines, amcl, tica, pita, czol, cfot, cftr, cfta, cfep, aztr, erta)) + cols = c(aminopenicillins, amcl, tica, pita, czol, cfot, cftr, cfta, cfep, aztr, erta)) # Pseudomonas edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Pseudomonas aeruginosa'), - cols = c(aminopenicillines, amcl, czol, cfot, cftr, erta, chlo, kana, neom, trim, trsu, tetracyclines, tige)) + cols = c(aminopenicillins, amcl, czol, cfot, cftr, erta, chlo, kana, neom, trim, trsu, tetracyclines, tige)) # Stenotrophomonas edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Stenotrophomonas maltophilia'), - cols = c(aminopenicillines, amcl, tica, pita, czol, cfot, cftr, cfta, aztr, erta, imip, mero, aminoglycosiden, trim, fosf, tetr)) + cols = c(aminopenicillins, amcl, tica, pita, czol, cfot, cftr, cfta, aztr, erta, imip, mero, aminoglycosides, trim, fosf, tetr)) # Table 3: Intrinsic resistance in other Gram-negative bacteria ---- if (info == TRUE) { cat('...Table 3: Intrinsic resistance in other Gram-negative bacteria\n') } - #voortgang <- progress_estimated(7) - # Intrisiek R voor groep + # Intrisiek R for this group edit_rsi(to = 'R', rows = which(tbl$genus %in% c('Haemophilus', 'Moraxella', 'Neisseria', 'Campylobacter')), - cols = c(glycopeptiden, linc, dapt, line)) + cols = c(glycopeptides, linc, dapt, line)) # Haemophilus edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Haemophilus influenzae'), - cols = c(fusi, streptogramines)) + cols = c(fusi, streptogramins)) # Moraxella edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Moraxella catarrhalis'), @@ -381,21 +454,20 @@ EUCAST_rules <- function(tbl, # Campylobacter edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Campylobacter fetus'), - cols = c(fusi, streptogramines, trim, nali)) + cols = c(fusi, streptogramins, trim, nali)) edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Campylobacter (jejuni|coli)'), - cols = c(fusi, streptogramines, trim)) + cols = c(fusi, streptogramins, trim)) # Table 4: Intrinsic resistance in Gram-positive bacteria ---- if (info == TRUE) { cat('...Table 4: Intrinsic resistance in Gram-positive bacteria\n') } - #voortgang <- progress_estimated(14) - # Intrisiek R voor groep + # Intrisiek R for this group edit_rsi(to = 'R', rows = which(tbl$gramstain %like% 'Positi(e|)(v|f)'), - cols = c(aztr, polymyxines, nali)) + cols = c(aztr, polymyxins, nali)) # Staphylococcus edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Staphylococcus saprophyticus'), @@ -412,17 +484,17 @@ EUCAST_rules <- function(tbl, # Streptococcus edit_rsi(to = 'R', rows = which(tbl$genus == 'Streptococcus'), - cols = c(fusi, cfta, aminoglycosiden)) + cols = c(fusi, cfta, aminoglycosides)) # Enterococcus edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Enterococcus faecalis'), - cols = c(fusi, cfta, cefalosporines[cefalosporines != cfta], aminoglycosiden, macroliden, clin, qida, trim, trsu)) + cols = c(fusi, cfta, cephalosporins[cephalosporins != cfta], aminoglycosides, macrolides, clin, qida, trim, trsu)) edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Enterococcus (gallinarum|casseliflavus)'), - cols = c(fusi, cfta, cefalosporines[cefalosporines != cfta], aminoglycosiden, macroliden, clin, qida, vanc, trim, trsu)) + cols = c(fusi, cfta, cephalosporins[cephalosporins != cfta], aminoglycosides, macrolides, clin, qida, vanc, trim, trsu)) edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Enterococcus faecium'), - cols = c(fusi, cfta, cefalosporines[cefalosporines != cfta], aminoglycosiden, macroliden, trim, trsu)) + cols = c(fusi, cfta, cephalosporins[cephalosporins != cfta], aminoglycosides, macrolides, trim, trsu)) # Corynebacterium edit_rsi(to = 'R', rows = which(tbl$genus == 'Corynebacterium'), @@ -430,7 +502,7 @@ EUCAST_rules <- function(tbl, # Listeria edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Listeria monocytogenes'), - cols = c(cfta, cefalosporines[cefalosporines != cfta])) + cols = c(cfta, cephalosporins[cephalosporins != cfta])) # overig edit_rsi(to = 'R', rows = which(tbl$genus %in% c('Leuconostoc', 'Pediococcus')), @@ -446,34 +518,32 @@ EUCAST_rules <- function(tbl, if (info == TRUE) { cat('...Table 8: Interpretive rules for B-lactam agents and Gram-positive cocci\n') } - #voortgang <- progress_estimated(2) - # regel 8.3 + # rule 8.3 if (!is.na(peni)) { edit_rsi(to = 'S', rows = which(tbl$fullname %like% '^Streptococcus (pyogenes|agalactiae|dysgalactiae|groep A|groep B|groep C|groep G)' & tbl[, peni] == 'S'), - cols = c(aminopenicillines, cefalosporines, carbapenems)) + cols = c(aminopenicillins, cephalosporins, carbapenems)) } - # regel 8.6 + # rule 8.6 if (!is.na(ampi)) { edit_rsi(to = 'R', rows = which(tbl$genus == 'Enterococcus' & tbl[, ampi] == 'R'), - cols = c(ureidopenicillines, carbapenems)) + cols = c(ureidopenicillins, carbapenems)) } if (!is.na(amox)) { edit_rsi(to = 'R', rows = which(tbl$genus == 'Enterococcus' & tbl[, amox] == 'R'), - cols = c(ureidopenicillines, carbapenems)) + cols = c(ureidopenicillins, carbapenems)) } # Table 9: Interpretive rules for B-lactam agents and Gram-negative rods ---- if (info == TRUE) { cat('...Table 9: Interpretive rules for B-lactam agents and Gram-negative rods\n') } - #voortgang <- progress_estimated(1) - # regel 9.3 + # rule 9.3 if (!is.na(tica) & !is.na(pita)) { edit_rsi(to = 'R', rows = which(tbl$family == 'Enterobacteriaceae' @@ -486,10 +556,9 @@ EUCAST_rules <- function(tbl, if (info == TRUE) { cat('...Table 10: Interpretive rules for B-lactam agents and other Gram-negative bacteria\n') } - #voortgang <- progress_estimated(1) - # regel 10.2 + # rule 10.2 if (!is.na(ampi)) { - # hiervoor moeten we eerst weten of ze B-lactamase-positief zijn + # you should know first if the are B-lactamase positive, so do not run for now # edit_rsi(to = 'R', # rows = which(tbl$fullname %like% '^Haemophilus influenza' # & tbl[, ampi] == 'R'), @@ -500,7 +569,7 @@ EUCAST_rules <- function(tbl, if (info == TRUE) { cat('...Table 11: Interpretive rules for macrolides, lincosamides, and streptogramins\n') } - # regel 11.1 + # rule 11.1 if (!is.na(eryt)) { if (!is.na(azit)) { tbl[, azit] <- tbl[, eryt] @@ -514,22 +583,21 @@ EUCAST_rules <- function(tbl, if (info == TRUE) { cat('...Table 12: Interpretive rules for aminoglycosides\n') } - #voortgang <- progress_estimated(4) - # regel 12.2 + # rule 12.2 if (!is.na(tobr)) { edit_rsi(to = 'R', rows = which(tbl$genus == 'Staphylococcus' & tbl[, tobr] == 'R'), cols = c(kana, amik)) } - # regel 12.3 + # rule 12.3 if (!is.na(gent)) { edit_rsi(to = 'R', rows = which(tbl$genus == 'Staphylococcus' & tbl[, gent] == 'R'), - cols = aminoglycosiden) + cols = aminoglycosides) } - # regel 12.8 + # rule 12.8 if (!is.na(gent) & !is.na(tobr)) { edit_rsi(to = 'R', rows = which(tbl$family == 'Enterobacteriaceae' @@ -537,7 +605,7 @@ EUCAST_rules <- function(tbl, & tbl[, tobr] == 'S'), cols = gent) } - # regel 12.9 + # rule 12.9 if (!is.na(gent) & !is.na(tobr)) { edit_rsi(to = 'R', rows = which(tbl$family == 'Enterobacteriaceae' @@ -551,42 +619,40 @@ EUCAST_rules <- function(tbl, if (info == TRUE) { cat('...Table 13: Interpretive rules for quinolones\n') } - #voortgang <- progress_estimated(4) - # regel 13.2 + # rule 13.2 if (!is.na(moxi)) { edit_rsi(to = 'R', rows = which(tbl$genus == 'Staphylococcus' & tbl[, moxi] == 'R'), - cols = fluorochinolonen) + cols = fluoroquinolones) } - # regel 13.4 + # rule 13.4 if (!is.na(moxi)) { edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Streptococcus pneumoniae' & tbl[, moxi] == 'R'), - cols = fluorochinolonen) + cols = fluoroquinolones) } - # regel 13.5 + # rule 13.5 if (!is.na(cipr)) { edit_rsi(to = 'R', rows = which(tbl$family == 'Enterobacteriaceae' & tbl[, cipr] == 'R'), - cols = fluorochinolonen) + cols = fluoroquinolones) } - # regel 13.8 + # rule 13.8 if (!is.na(cipr)) { edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Neisseria gonorrhoeae' & tbl[, cipr] == 'R'), - cols = fluorochinolonen) + cols = fluoroquinolones) } # Other ---- if (info == TRUE) { - cat('...Other\n') + cat('...Non-EUCAST: trim = R where trsu = R and ampi = R where amcl = R\n') } - #voortgang <- progress_estimated(2) if (!is.na(amcl)) { edit_rsi(to = 'R', rows = which(tbl[, amcl] == 'R'), @@ -601,17 +667,17 @@ EUCAST_rules <- function(tbl, tbl[, amox] <- tbl %>% pull(ampi) } - # Toegevoegde kolommen weer verwijderen - bactlist.ncol <- ncol(AMR::bactlist) - 2 + # Remove added columns again + microorganisms.ncol <- ncol(AMR::microorganisms) - 2 tbl.ncol <- ncol(tbl) - tbl <- tbl %>% select(-c((tbl.ncol - bactlist.ncol):tbl.ncol)) - # en eventueel toegevoegde suffix aan bestaande kolommen weer verwijderen - colnames(tbl) <- gsub("_tempbactlist", "", colnames(tbl)) + tbl <- tbl %>% select(-c((tbl.ncol - microorganisms.ncol):tbl.ncol)) + # and remove added suffices + colnames(tbl) <- gsub("_tempmicroorganisms", "", colnames(tbl)) if (info == TRUE) { - cat('\nDone.\nEUCAST Expert rules applied to', + cat('Done.\n\nEUCAST Expert rules applied to', total_rows %>% unique() %>% length() %>% format(big.mark = ","), - 'different rows, to a total of', + 'different rows (isolates); edited a total of', total %>% format(big.mark = ","), 'test results.\n\n') } @@ -626,14 +692,14 @@ interpretive_reading <- function(...) { #' Poperties of a microorganism #' -#' @param bactcode ID of a microorganisme, like \code{"STAAUR} and \code{"ESCCOL} +#' @param bactid ID of a microorganisme, like \code{"STAAUR} and \code{"ESCCOL} #' @param property One of the values \code{bactid}, \code{bactsys}, \code{family}, \code{genus}, \code{species}, \code{subspecies}, \code{fullname}, \code{type}, \code{gramstain}, \code{aerobic} #' @export #' @importFrom dplyr %>% filter select -#' @seealso \code{\link{bactlist}} -mo_property <- function(bactcode, property = 'fullname') { +#' @seealso \code{\link{microorganisms}} +mo_property <- function(bactid, property = 'fullname') { - mocode <- as.character(bactcode) + mocode <- as.character(bactid) for (i in 1:length(mocode)) { bug <- mocode[i] @@ -641,8 +707,8 @@ mo_property <- function(bactcode, property = 'fullname') { if (!is.na(bug)) { result = tryCatch({ mocode[i] <- - AMR::bactlist %>% - filter(bactid == bactcode) %>% + AMR::microorganisms %>% + filter(bactid == bactid) %>% select(property) %>% unlist() %>% as.character() diff --git a/R/atc.R b/R/atc.R index b03032db..bcc4bff8 100644 --- a/R/atc.R +++ b/R/atc.R @@ -129,7 +129,7 @@ atc_property <- function(atc_code, #' #' Convert antibiotic codes (from a laboratory information system like MOLIS or GLIMS) to a (trivial) antibiotic name or ATC code, or vice versa. This uses the data from \code{\link{antibiotics}}. #' @param abcode a code or name, like \code{"AMOX"}, \code{"AMCL"} or \code{"J01CA04"} -#' @param from,to type to transform from and to. See \code{\link{antibiotics}} for its column names. +#' @param from,to type to transform from and to. See \code{\link{antibiotics}} for its column names. WIth \code{from = "guess"} the from will be guessed from \code{"atc"}, \code{"molis"} and \code{"umcg"}. #' @param textbetween text to put between multiple returned texts #' @param tolower return output as lower case with function \code{\link{tolower}}. #' @keywords ab antibiotics @@ -154,9 +154,22 @@ atc_property <- function(atc_code, #' #' abname("J01CR02", from = "atc", to = "umcg") #' # "AMCL" -abname <- function(abcode, from = 'umcg', to = 'official', textbetween = ' + ', tolower = FALSE) { +abname <- function(abcode, from = c("guess", "atc", "molis", "umcg"), to = 'official', textbetween = ' + ', tolower = FALSE) { antibiotics <- AMR::antibiotics + + from <- from[1] + if (from == "guess") { + for (i in 1:3) { + if (abcode[1] %in% (antibiotics %>% pull(i))) { + from <- colnames(antibiotics)[i] + } + } + if (from == "guess") { + from <- "umcg" + } + } + colnames(antibiotics) <- colnames(antibiotics) %>% tolower() from <- from %>% tolower() to <- to %>% tolower() @@ -172,8 +185,8 @@ abname <- function(abcode, from = 'umcg', to = 'official', textbetween = ' + ', for (i in 1:length(abcode)) { drug <- abcode[i] if (!grepl('+', drug, fixed = TRUE) & !grepl(' en ', drug, fixed = TRUE)) { - # bestaat maar uit 1 middel - if (any(antibiotics[, from] == drug)) { + # only 1 drug + if (drug %in% (antibiotics %>% pull(from))) { abcode[i] <- antibiotics %>% filter(.[, from] == drug) %>% @@ -181,12 +194,12 @@ abname <- function(abcode, from = 'umcg', to = 'official', textbetween = ' + ', slice(1) %>% as.character() } else { - # niet gevonden + # not found warning('Code "', drug, '" not found in antibiotics list.', call. = FALSE) abcode[i] <- NA } } else { - # meerdere middelen + # more than 1 drug if (grepl('+', drug, fixed = TRUE)) { drug.group <- strsplit(drug, '+', fixed = TRUE) %>% diff --git a/R/clipboard.R b/R/clipboard.R new file mode 100644 index 00000000..1f6072cc --- /dev/null +++ b/R/clipboard.R @@ -0,0 +1,84 @@ +#' Import/export from clipboard +#' +#' These are helper functions around \code{\link{read.table}} and \code{\link{write.table}} to import from and export to clipboard. The data will be read and written as tab-separated by default, which makes it possible to copy and paste from other software like Excel and SPSS without further transformation. +#' @rdname clipboard +#' @name clipboard +#' @inheritParams utils::read.table +#' @inheritParams utils::write.table +#' @param startrow \emph{n}th row to start importing from. For \code{clipboard_import}, when \code{header = TRUE} the import will start on row \code{startrow} \emph{below} the header. +#' @param as_vector a logical value indicating whether data consisting of only one column should be imported as vector using \code{\link[dplyr]{pull}}. This will strip off the header. +#' @keywords clipboard clipboard_import clipboard_export import export +#' @importFrom dplyr %>% pull as_tibble +#' @importFrom utils read.delim write.table object.size writeClipboard +#' @details For \code{clipboard_export}, the reserved clipboard size for exporting will be set automatically to 125\% of the object size of \code{x}. This way, it is possible to export data with thousands of rows as the only limit will be your systems RAM. +#' @export +#' @return data.frame +clipboard_import <- function(sep = '\t', + header = TRUE, + dec = ".", + na = c("", "NA", "NULL"), + startrow = 1, + as_vector = TRUE) { + + import_tbl <- read.delim(file = 'clipboard', + sep = sep, + header = header, + strip.white = TRUE, + dec = dec, + na.strings = na, + fileEncoding = 'UTF-8', + encoding = 'UTF-8', + stringsAsFactors = FALSE) + + # use tibble, so column types will be translated correctly + import_tbl <- as_tibble(import_tbl) + + if (startrow > 1) { + # would else lose column headers + import_tbl <- import_tbl[startrow:nrow(import_tbl),] + } + + colnames(import_tbl) <- gsub('[.]+', '_', colnames(import_tbl)) + + if (NCOL(import_tbl) == 1 & as_vector == TRUE) { + import_tbl %>% pull(1) + } else { + import_tbl + } +} + +#' @rdname clipboard +#' @importFrom dplyr %>% pull as_tibble +#' @export +clipboard_export <- function(x, + sep = '\t', + dec = ".", + na = "", + header = TRUE) { + + x <- deparse(substitute(x)) + size <- x %>% + get() %>% + object.size() %>% + formatC(format = 'd') %>% + as.integer() + + x <- get(x) + + if (size > 25 * 1024 * 1024) { + # above 25 MB use a hacker function + writeClipboard(knitr::kable(x)) + } else { + # set size of clipboard to 125% of the object size of x + write.table(x = x, + file = paste0("clipboard-", size * 1.25), + sep = sep, + na = na, + row.names = FALSE, + col.names = header, + dec = dec, + quote = FALSE) + } + cat("Successfully exported to clipboard:", NROW(x), "obs. of", NCOL(x), "variables.\n") + +} diff --git a/R/data.R b/R/data.R index 435f86f2..a8494f3a 100644 --- a/R/data.R +++ b/R/data.R @@ -39,7 +39,7 @@ #' \item{\code{useful_grampositive}}{\code{FALSE} if not useful according to EUCAST, \code{NA} otherwise (see Source)} #' } #' @source - World Health Organization: \url{https://www.whocc.no/atc_ddd_index/} \cr - EUCAST - Expert rules intrinsic exceptional V3.1 \cr - MOLIS (LIS of Certe): \url{https://www.certe.nl} \cr - GLIMS (LIS of UMCG): \url{https://www.umcg.nl} -#' @seealso \code{\link{bactlist}} +#' @seealso \code{\link{microorganisms}} # last two columns created with: # antibiotics %>% # mutate(useful_gramnegative = @@ -63,7 +63,7 @@ #' Dataset with ~2500 microorganisms #' -#' A dataset containing all microorganisms of MOLIS. MO codes of the UMCG can be looked up using \code{\link{bactlist.umcg}}. +#' A dataset containing 2500 microorganisms. MO codes of the UMCG can be looked up using \code{\link{microorganisms.umcg}}. #' @format A data.frame with 2507 observations and 12 variables: #' \describe{ #' \item{\code{bactid}}{ID of microorganism} @@ -80,24 +80,24 @@ #' \item{\code{gramstain_nl}}{Gram of microorganism in Dutch, like \code{"Negatieve staven"}} #' } #' @source MOLIS (LIS of Certe) - \url{https://www.certe.nl} -#' @seealso \code{\link{guess_bactid}} \code{\link{antibiotics}} \code{\link{bactlist.umcg}} -"bactlist" +#' @seealso \code{\link{guess_bactid}} \code{\link{antibiotics}} \code{\link{microorganisms.umcg}} +"microorganisms" #' Translation table for UMCG with ~1100 microorganisms #' -#' A dataset containing all bacteria codes of UMCG MMB. These codes can be joined to data with an ID from \code{\link{bactlist}$bactid} (using \code{\link{left_join_bactlist}}). GLIMS codes can also be translated to valid \code{bactid}'s with \code{\link{guess_bactid}}. +#' A dataset containing all bacteria codes of UMCG MMB. These codes can be joined to data with an ID from \code{\link{microorganisms}$bactid} (using \code{\link{left_join_microorganisms}}). GLIMS codes can also be translated to valid \code{bactid}'s with \code{\link{guess_bactid}}. #' @format A data.frame with 1090 observations and 2 variables: #' \describe{ #' \item{\code{mocode}}{Code of microorganism according to UMCG MMB} -#' \item{\code{bactid}}{Code of microorganism in \code{\link{bactlist}}} +#' \item{\code{bactid}}{Code of microorganism in \code{\link{microorganisms}}} #' } #' @source MOLIS (LIS of Certe) - \url{https://www.certe.nl} \cr \cr GLIMS (LIS of UMCG) - \url{https://www.umcg.nl} -#' @seealso \code{\link{guess_bactid}} \code{\link{bactlist}} -"bactlist.umcg" +#' @seealso \code{\link{guess_bactid}} \code{\link{microorganisms}} +"microorganisms.umcg" #' Dataset with 2000 blood culture isolates of septic patients #' -#' An anonymised dataset containing 2000 microbial blood culture isolates with their antibiogram of septic patients found in 5 different hospitals in the Netherlands, between 2001 and 2017. This data.frame can be used to practice AMR analysis e.g. with \code{\link{rsi}} or \code{\link{rsi_predict}}, or it can be used to practice other statistics. +#' An anonymised dataset containing 2000 microbial blood culture isolates with their antibiogram of septic patients found in 5 different hospitals in the Netherlands, between 2001 and 2017. This data.frame can be used to practice AMR analysis. For examples, press F1. #' @format A data.frame with 2000 observations and 47 variables: #' \describe{ #' \item{\code{date}}{date of receipt at the laboratory} @@ -108,8 +108,47 @@ #' \item{\code{age}}{age of the patient} #' \item{\code{sex}}{sex of the patient} #' \item{\code{patient_id}}{ID of the patient, first 10 characters of an SHA hash containing irretrievable information} -#' \item{\code{bactid}}{ID of microorganism, see \code{\link{bactlist}}} -#' \item{\code{peni:mupi}}{38 different antibiotics with class \code{rsi} (see \code{\link{as.rsi}}), these column names occur in \code{\link{antibiotics}} and can be translated with \code{\link{abname}}} +#' \item{\code{bactid}}{ID of microorganism, see \code{\link{microorganisms}}} +#' \item{\code{peni:mupi}}{38 different antibiotics with class \code{rsi} (see \code{\link{as.rsi}}); these column names occur in \code{\link{antibiotics}} and can be translated with \code{\link{abname}}} #' } #' @source MOLIS (LIS of Certe) - \url{https://www.certe.nl} +#' @examples +#' # ----------- # +#' # PREPARATION # +#' # ----------- # +#' +#' # Save this example dataset to an object, so we can edit it: +#' my_data <- septic_patients +#' +#' # load the dplyr package to make data science A LOT easier +#' library(dplyr) +#' +#' # Add first isolates to our dataset: +#' my_data <- my_data %>% +#' mutate(first_isolates = first_isolate(my_data, date, patient_id, bactid)) +#' +#' # -------- # +#' # ANALYSIS # +#' # -------- # +#' +#' # 1. Get the amoxicillin resistance percentages +#' # of E. coli, divided by hospital: +#' +#' my_data %>% +#' filter(bactid == "ESCCOL", +#' first_isolates == TRUE) %>% +#' group_by(hospital_id) %>% +#' summarise(n = n(), +#' amoxicillin_resistance = rsi(amox)) +#' +#' +#' # 2. Get the amoxicillin/clavulanic acid resistance +#' # percentages of E. coli, trend over the years: +#' +#' my_data %>% +#' filter(bactid == guess_bactid("E. coli"), +#' first_isolates == TRUE) %>% +#' group_by(year = format(date, "%Y")) %>% +#' summarise(n = n(), +#' amoxclav_resistance = rsi(amcl, minimum = 20)) "septic_patients" diff --git a/R/first_isolates.R b/R/first_isolates.R index 67799511..a32cff0b 100644 --- a/R/first_isolates.R +++ b/R/first_isolates.R @@ -22,8 +22,7 @@ #' @param tbl a \code{data.frame} containing isolates. #' @param col_date column name of the result date (or date that is was received on the lab), supports tidyverse-like quotation #' @param col_patient_id column name of the unique IDs of the patients, supports tidyverse-like quotation -#' @param col_genus column name of the genus of the microorganisms, supports tidyverse-like quotation -#' @param col_species column name of the species of the microorganisms, supports tidyverse-like quotation +#' @param col_bactid column name of the unique IDs of the microorganisms (should occur in the \code{\link{microorganisms}} dataset), supports tidyverse-like quotation #' @param col_testcode column name of the test codes. Use \code{col_testcode = NA} to \strong{not} exclude certain test codes (like test codes for screening). In that case \code{testcodes_exclude} will be ignored. Supports tidyverse-like quotation. #' @param col_specimen column name of the specimen type or group, supports tidyverse-like quotation #' @param col_icu column name of the logicals (\code{TRUE}/\code{FALSE}) whether a ward or department is an Intensive Care Unit (ICU), supports tidyverse-like quotation @@ -37,6 +36,8 @@ #' @param ignore_I logical to determine whether antibiotic interpretations with \code{"I"} will be ignored when \code{type = "keyantibiotics"}, see Details #' @param points_threshold points until the comparison of key antibiotics will lead to inclusion of an isolate when \code{type = "points"}, see Details #' @param info print progress +#' @param col_genus (deprecated, use \code{col_bactid} instead) column name of the genus of the microorganisms, supports tidyverse-like quotation +#' @param col_species (deprecated, use \code{col_bactid} instead) column name of the species of the microorganisms, supports tidyverse-like quotation #' @details \strong{WHY THIS IS SO IMPORTANT} \cr #' To conduct an analysis of antimicrobial resistance, you should only include the first isolate of every patient per episode \href{https://www.ncbi.nlm.nih.gov/pubmed/17304462}{[1]}. If you would not do this, you could easily get an overestimate or underestimate of the resistance of an antibiotic. Imagine that a patient was admitted with an MRSA and that it was found in 5 different blood cultures the following week. The resistance percentage of oxacillin of all \emph{S. aureus} isolates would be overestimated, because you included this MRSA more than once. It would be \href{https://en.wikipedia.org/wiki/Selection_bias}{selection bias}. #' @@ -56,7 +57,7 @@ #' #' library(dplyr) #' my_patients$first_isolate <- my_patients %>% -#' left_join_bactlist() %>% +#' left_join_microorganisms() %>% #' first_isolate(col_date = date, #' col_patient_id = patient_id, #' col_genus = genus, @@ -104,8 +105,7 @@ first_isolate <- function(tbl, col_date, col_patient_id, - col_genus, - col_species, + col_bactid = NA, col_testcode = NA, col_specimen = NA, col_icu = NA, @@ -118,11 +118,14 @@ first_isolate <- function(tbl, type = "keyantibiotics", ignore_I = TRUE, points_threshold = 2, - info = TRUE) { + info = TRUE, + col_genus = NA, + col_species = NA) { # support tidyverse-like quotation col_date <- quasiquotate(deparse(substitute(col_date)), col_date) col_patient_id <- quasiquotate(deparse(substitute(col_patient_id)), col_patient_id) + col_bactid <- quasiquotate(deparse(substitute(col_bactid)), col_bactid) col_genus <- quasiquotate(deparse(substitute(col_genus)), col_genus) col_species <- quasiquotate(deparse(substitute(col_species)), col_species) col_testcode <- quasiquotate(deparse(substitute(col_testcode)), col_testcode) @@ -145,12 +148,19 @@ first_isolate <- function(tbl, check_columns_existance(col_date) check_columns_existance(col_patient_id) + check_columns_existance(col_bactid) check_columns_existance(col_genus) check_columns_existance(col_species) check_columns_existance(col_testcode) check_columns_existance(col_icu) check_columns_existance(col_keyantibiotics) + if (!is.na(col_bactid)) { + tbl <- tbl %>% left_join_microorganisms() + col_genus <- "genus" + col_species <- "species" + } + if (is.na(col_testcode)) { testcodes_exclude <- NA } @@ -395,7 +405,7 @@ first_isolate <- function(tbl, #' Key antibiotics based on bacteria ID #' #' @param tbl table with antibiotics coloms, like \code{amox} and \code{amcl}. -#' @param col_bactcode column of bacteria IDs in \code{tbl}; these should occur in \code{bactlist$bactid}, see \code{\link{bactlist}} +#' @param col_bactid column of bacteria IDs in \code{tbl}; these should occur in \code{microorganisms$bactid}, see \code{\link{microorganisms}} #' @param info print warnings #' @param amcl,amox,cfot,cfta,cftr,cfur,cipr,clar,clin,clox,doxy,gent,line,mero,peni,pita,rifa,teic,trsu,vanc column names of antibiotics, case-insensitive #' @export @@ -408,7 +418,7 @@ first_isolate <- function(tbl, #' tbl$keyab <- key_antibiotics(tbl) #' } key_antibiotics <- function(tbl, - col_bactcode = 'bactid', + col_bactid = 'bactid', info = TRUE, amcl = 'amcl', amox = 'amox', @@ -443,6 +453,8 @@ key_antibiotics <- function(tbl, col.list[i] <- toupper(col.list[i]) } else if (tolower(col.list[i]) %in% colnames(tbl)) { col.list[i] <- tolower(col.list[i]) + } else if (!col.list[i] %in% colnames(tbl)) { + col.list[i] <- NA } } if (!all(col.list %in% colnames(tbl))) { @@ -473,8 +485,8 @@ key_antibiotics <- function(tbl, trsu <- col.list[18] vanc <- col.list[19] - # join bactlist - tbl <- tbl %>% left_join_bactlist(col_bactcode) + # join microorganisms + tbl <- tbl %>% left_join_microorganisms(col_bactid) tbl$key_ab <- NA_character_ @@ -595,7 +607,7 @@ key_antibiotics_equal <- function(x, result[i] <- all(x2 == y2) } else { - stop('`', type, '` is not a valid value for type, must be `points` or `keyantibiotics`. See ?first_isolate.') + stop('`', type, '` is not a valid value for type, must be "points" or "keyantibiotics". See ?first_isolate.') } } } @@ -612,7 +624,7 @@ key_antibiotics_equal <- function(x, #' @export #' @importFrom dplyr %>% filter slice pull #' @return Character (vector). -#' @seealso \code{\link{bactlist}} for the dataframe that is being used to determine ID's. +#' @seealso \code{\link{microorganisms}} for the dataframe that is being used to determine ID's. #' @examples #' # These examples all return "STAAUR", the ID of S. aureus: #' guess_bactid("stau") @@ -662,24 +674,24 @@ guess_bactid <- function(x) { } # let's try the ID's first - found <- AMR::bactlist %>% filter(bactid == x.bak[i]) + found <- AMR::microorganisms %>% filter(bactid == x.bak[i]) if (nrow(found) == 0) { # now try exact match - found <- AMR::bactlist %>% filter(fullname == x[i]) + found <- AMR::microorganisms %>% filter(fullname == x[i]) } if (nrow(found) == 0) { # try any match - found <- AMR::bactlist %>% filter(fullname %like% x[i]) + found <- AMR::microorganisms %>% filter(fullname %like% x[i]) } if (nrow(found) == 0) { # try only genus, with 'species' attached - found <- AMR::bactlist %>% filter(fullname %like% x_species[i]) + found <- AMR::microorganisms %>% filter(fullname %like% x_species[i]) } if (nrow(found) == 0) { # search for GLIMS code - if (toupper(x.bak[i]) %in% toupper(AMR::bactlist.umcg$mocode)) { - found <- AMR::bactlist.umcg %>% filter(toupper(mocode) == toupper(x.bak[i])) + if (toupper(x.bak[i]) %in% toupper(AMR::microorganisms.umcg$mocode)) { + found <- AMR::microorganisms.umcg %>% filter(toupper(mocode) == toupper(x.bak[i])) } } if (nrow(found) == 0) { @@ -689,7 +701,7 @@ guess_bactid <- function(x) { x[i] <- paste0(x.bak[i] %>% substr(1, x_length / 2) %>% trimws(), '.* ', x.bak[i] %>% substr((x_length / 2) + 1, x_length) %>% trimws()) - found <- AMR::bactlist %>% filter(fullname %like% paste0('^', x[i])) + found <- AMR::microorganisms %>% filter(fullname %like% paste0('^', x[i])) } if (nrow(found) != 0) { diff --git a/R/join.R b/R/join.R index e4c26b1a..dc474eb3 100644 --- a/R/join.R +++ b/R/join.R @@ -1,20 +1,20 @@ -#' Join a table with \code{bactlist} +#' Join a table with \code{microorganisms} #' -#' Join the list of microorganisms \code{\link{bactlist}} easily to an existing table. +#' Join the dataset \code{\link{microorganisms}} easily to an existing table or character vector. #' @rdname join #' @name join #' @aliases join inner_join #' @param x existing table to join, also supports character vectors -#' @param by a variable to join by - could be a column name of \code{x} with values that exist in \code{bactlist$bactid} (like \code{by = "bacteria_id"}), or another column in \code{\link{bactlist}} (but then it should be named, like \code{by = c("my_genus_species" = "fullname")}) +#' @param by a variable to join by - could be a column name of \code{x} with values that exist in \code{microorganisms$bactid} (like \code{by = "bacteria_id"}), or another column in \code{\link{microorganisms}} (but then it should be named, like \code{by = c("my_genus_species" = "fullname")}) #' @param suffix if there are non-joined duplicate variables in \code{x} and \code{y}, these suffixes will be added to the output to disambiguate them. Should be a character vector of length 2. #' @param ... other parameters to pass on to \code{dplyr::\link[dplyr]{join}}. #' @details As opposed to the \code{\link[dplyr]{join}} functions of \code{dplyr}, characters vectors are supported and at default existing columns will get a suffix \code{"2"} and the newly joined columns will not get a suffix. See \code{\link[dplyr]{join}} for more information. #' @export #' @examples -#' left_join_bactlist("STAAUR") +#' left_join_microorganisms("STAAUR") #' #' library(dplyr) -#' septic_patients %>% left_join_bactlist() +#' septic_patients %>% left_join_microorganisms() #' #' df <- data.frame(date = seq(from = as.Date("2018-01-01"), #' to = as.Date("2018-01-07"), @@ -23,20 +23,20 @@ #' "ESCCOL", "ESCCOL", "ESCCOL"), #' stringsAsFactors = FALSE) #' colnames(df) -#' df2 <- left_join_bactlist(df, "bacteria_id") +#' df2 <- left_join_microorganisms(df, "bacteria_id") #' colnames(df2) -inner_join_bactlist <- function(x, by = 'bactid', suffix = c("2", ""), ...) { +inner_join_microorganisms <- function(x, by = 'bactid', suffix = c("2", ""), ...) { if (any(class(x) %in% c('character', 'factor'))) { x <- data.frame(bactid = x, stringsAsFactors = FALSE) } # no name set to `by` parameter if (is.null(names(by))) { - joinby <- colnames(AMR::bactlist)[1] + joinby <- colnames(AMR::microorganisms)[1] names(joinby) <- by } else { joinby <- by } - join <- dplyr::inner_join(x = x, y = AMR::bactlist, by = joinby, suffix = c("2", ""), ...) + join <- dplyr::inner_join(x = x, y = AMR::microorganisms, by = joinby, suffix = c("2", ""), ...) if (nrow(join) > nrow(x)) { warning('the newly joined tbl contains ', nrow(join) - nrow(x), ' rows more that its original') } @@ -45,18 +45,18 @@ inner_join_bactlist <- function(x, by = 'bactid', suffix = c("2", ""), ...) { #' @rdname join #' @export -left_join_bactlist <- function(x, by = 'bactid', suffix = c("2", ""), ...) { +left_join_microorganisms <- function(x, by = 'bactid', suffix = c("2", ""), ...) { if (any(class(x) %in% c('character', 'factor'))) { x <- data.frame(bactid = x, stringsAsFactors = FALSE) } # no name set to `by` parameter if (is.null(names(by))) { - joinby <- colnames(AMR::bactlist)[1] + joinby <- colnames(AMR::microorganisms)[1] names(joinby) <- by } else { joinby <- by } - join <- dplyr::left_join(x = x, y = AMR::bactlist, by = joinby, suffix = c("2", ""), ...) + join <- dplyr::left_join(x = x, y = AMR::microorganisms, by = joinby, suffix = c("2", ""), ...) if (nrow(join) > nrow(x)) { warning('the newly joined tbl contains ', nrow(join) - nrow(x), ' rows more that its original') } @@ -65,18 +65,18 @@ left_join_bactlist <- function(x, by = 'bactid', suffix = c("2", ""), ...) { #' @rdname join #' @export -right_join_bactlist <- function(x, by = 'bactid', suffix = c("2", ""), ...) { +right_join_microorganisms <- function(x, by = 'bactid', suffix = c("2", ""), ...) { if (any(class(x) %in% c('character', 'factor'))) { x <- data.frame(bactid = x, stringsAsFactors = FALSE) } # no name set to `by` parameter if (is.null(names(by))) { - joinby <- colnames(AMR::bactlist)[1] + joinby <- colnames(AMR::microorganisms)[1] names(joinby) <- by } else { joinby <- by } - join <- dplyr::right_join(x = x, y = AMR::bactlist, by = joinby, suffix = c("2", ""), ...) + join <- dplyr::right_join(x = x, y = AMR::microorganisms, by = joinby, suffix = c("2", ""), ...) if (nrow(join) > nrow(x)) { warning('the newly joined tbl contains ', nrow(join) - nrow(x), ' rows more that its original') } @@ -85,48 +85,48 @@ right_join_bactlist <- function(x, by = 'bactid', suffix = c("2", ""), ...) { #' @rdname join #' @export -full_join_bactlist <- function(x, by = 'bactid', suffix = c("2", ""), ...) { +full_join_microorganisms <- function(x, by = 'bactid', suffix = c("2", ""), ...) { if (any(class(x) %in% c('character', 'factor'))) { x <- data.frame(bactid = x, stringsAsFactors = FALSE) } # no name set to `by` parameter if (is.null(names(by))) { - joinby <- colnames(AMR::bactlist)[1] + joinby <- colnames(AMR::microorganisms)[1] names(joinby) <- by } else { joinby <- by } - dplyr::full_join(x = x, y = AMR::bactlist, by = joinby, suffix = c("2", ""), ...) + dplyr::full_join(x = x, y = AMR::microorganisms, by = joinby, suffix = c("2", ""), ...) } #' @rdname join #' @export -semi_join_bactlist <- function(x, by = 'bactid', ...) { +semi_join_microorganisms <- function(x, by = 'bactid', ...) { if (any(class(x) %in% c('character', 'factor'))) { x <- data.frame(bactid = x, stringsAsFactors = FALSE) } # no name set to `by` parameter if (is.null(names(by))) { - joinby <- colnames(AMR::bactlist)[1] + joinby <- colnames(AMR::microorganisms)[1] names(joinby) <- by } else { joinby <- by } - dplyr::semi_join(x = x, y = AMR::bactlist, by = joinby, ...) + dplyr::semi_join(x = x, y = AMR::microorganisms, by = joinby, ...) } #' @rdname join #' @export -anti_join_bactlist <- function(x, by = 'bactid', ...) { +anti_join_microorganisms <- function(x, by = 'bactid', ...) { if (any(class(x) %in% c('character', 'factor'))) { x <- data.frame(bactid = x, stringsAsFactors = FALSE) } # no name set to `by` parameter if (is.null(names(by))) { - joinby <- colnames(AMR::bactlist)[1] + joinby <- colnames(AMR::microorganisms)[1] names(joinby) <- by } else { joinby <- by } - dplyr::anti_join(x = x, y = AMR::bactlist, by = joinby, ...) + dplyr::anti_join(x = x, y = AMR::microorganisms, by = joinby, ...) } diff --git a/R/misc.R b/R/misc.R index 8d14b600..f3839a42 100644 --- a/R/misc.R +++ b/R/misc.R @@ -40,9 +40,9 @@ quasiquotate <- function(deparsed, parsed) { } # apply if needed if (any(!deparsed %like% '[[$:()]' - & !deparsed %in% c('""', "''", "", # empty text - ".", ".data", # dplyr references - "TRUE", "FALSE", # logicals + & !deparsed %in% c('""', "''", "", # empty text + ".", ".data", # dplyr references + "TRUE", "FALSE", # logicals "NA", "NaN", "NULL", # empty values ls(.GlobalEnv)))) { deparsed diff --git a/R/rsi_analysis.R b/R/rsi_analysis.R index e9a2edf5..55edab3b 100644 --- a/R/rsi_analysis.R +++ b/R/rsi_analysis.R @@ -20,7 +20,7 @@ #' #' \strong{NOTE: use \code{\link{rsi}} in dplyr functions like \code{\link[dplyr]{summarise}}.} \cr Calculate the percentage of S, SI, I, IR or R of a \code{data.frame} containing isolates. #' @param tbl \code{data.frame} containing columns with antibiotic interpretations. -#' @param antibiotics character vector with 1, 2 or 3 antibiotics that occur as column names in \code{tbl}, like \code{antibiotics = c("amox", "amcl")} +#' @param ab character vector with 1, 2 or 3 antibiotics that occur as column names in \code{tbl}, like \code{ab = c("amox", "amcl")} #' @param interpretation antimicrobial interpretation of which the portion must be calculated. Valid values are \code{"S"}, \code{"SI"}, \code{"I"}, \code{"IR"} or \code{"R"}. #' @param minimum minimal amount of available isolates. Any number lower than \code{minimum} will return \code{NA} with a warning (when \code{warning = TRUE}). #' @param percent return output as percent (text), will else (at default) be a double @@ -43,27 +43,27 @@ #' my_table %>% #' filter(first_isolate == TRUE, #' genus == "Helicobacter") %>% -#' rsi_df(antibiotics = c("amox", "metr")) +#' rsi_df(ab = c("amox", "metr")) #' } rsi_df <- function(tbl, - antibiotics, + ab, interpretation = 'IR', minimum = 30, percent = FALSE, info = TRUE, warning = TRUE) { + + # in case tbl$interpretation already exists: + interpretations_to_check <- paste(interpretation, collapse = "") - # we willen niet dat tbl$interpretation toevallig ook bestaat, dus: - te_testen_uitslag_ab <- interpretation - - # validatie: - if (min(grepl('^[a-z]{3,4}$', antibiotics)) == 0 & - min(grepl('^rsi[1-2]$', antibiotics)) == 0) { - for (i in 1:length(antibiotics)) { - antibiotics[i] <- paste0('rsi', i) + # validate: + if (min(grepl('^[a-z]{3,4}$', ab)) == 0 & + min(grepl('^rsi[1-2]$', ab)) == 0) { + for (i in 1:length(ab)) { + ab[i] <- paste0('rsi', i) } } - if (!grepl('^(S|SI|IS|I|IR|RI|R){1}$', te_testen_uitslag_ab)) { + if (!grepl('^(S|SI|IS|I|IR|RI|R){1}$', interpretations_to_check)) { stop('Invalid `interpretation`; must be "S", "SI", "I", "IR", or "R".') } if ('is_ic' %in% colnames(tbl)) { @@ -72,59 +72,59 @@ rsi_df <- function(tbl, } } - # transformeren wanneer gezocht wordt op verschillende uitslagen - if (te_testen_uitslag_ab %in% c('SI', 'IS')) { - for (i in 1:length(antibiotics)) { - lijst <- tbl[, antibiotics[i]] + # transform when checking for different results + if (interpretations_to_check %in% c('SI', 'IS')) { + for (i in 1:length(ab)) { + lijst <- tbl[, ab[i]] if ('I' %in% lijst) { - tbl[which(tbl[antibiotics[i]] == 'I'), ][antibiotics[i]] <- 'S' + tbl[which(tbl[ab[i]] == 'I'), ][ab[i]] <- 'S' } } - te_testen_uitslag_ab <- 'S' + interpretations_to_check <- 'S' } - if (te_testen_uitslag_ab %in% c('RI', 'IR')) { - for (i in 1:length(antibiotics)) { - lijst <- tbl[, antibiotics[i]] + if (interpretations_to_check %in% c('RI', 'IR')) { + for (i in 1:length(ab)) { + lijst <- tbl[, ab[i]] if ('I' %in% lijst) { - tbl[which(tbl[antibiotics[i]] == 'I'), ][antibiotics[i]] <- 'R' + tbl[which(tbl[ab[i]] == 'I'), ][ab[i]] <- 'R' } } - te_testen_uitslag_ab <- 'R' + interpretations_to_check <- 'R' } - - # breuk samenstellen - if (length(antibiotics) == 1) { + + # get fraction + if (length(ab) == 1) { numerator <- tbl %>% - filter(pull(., antibiotics[1]) == te_testen_uitslag_ab) %>% + filter(pull(., ab[1]) == interpretations_to_check) %>% nrow() - + denominator <- tbl %>% - filter(pull(., antibiotics[1]) %in% c("S", "I", "R")) %>% + filter(pull(., ab[1]) %in% c("S", "I", "R")) %>% nrow() - } else if (length(antibiotics) == 2) { + } else if (length(ab) == 2) { numerator <- tbl %>% - filter_at(vars(antibiotics[1], antibiotics[2]), - any_vars(. == te_testen_uitslag_ab)) %>% - filter_at(vars(antibiotics[1], antibiotics[2]), + filter_at(vars(ab[1], ab[2]), + any_vars(. == interpretations_to_check)) %>% + filter_at(vars(ab[1], ab[2]), all_vars(. %in% c("S", "R", "I"))) %>% nrow() denominator <- tbl %>% - filter_at(vars(antibiotics[1], antibiotics[2]), + filter_at(vars(ab[1], ab[2]), all_vars(. %in% c("S", "R", "I"))) %>% nrow() - } else if (length(antibiotics) == 3) { + } else if (length(ab) == 3) { numerator <- tbl %>% - filter_at(vars(antibiotics[1], antibiotics[2], antibiotics[3]), - any_vars(. == te_testen_uitslag_ab)) %>% - filter_at(vars(antibiotics[1], antibiotics[2], antibiotics[3]), + filter_at(vars(ab[1], ab[2], ab[3]), + any_vars(. == interpretations_to_check)) %>% + filter_at(vars(ab[1], ab[2], ab[3]), all_vars(. %in% c("S", "R", "I"))) %>% nrow() denominator <- tbl %>% - filter_at(vars(antibiotics[1], antibiotics[2], antibiotics[3]), + filter_at(vars(ab[1], ab[2], ab[3]), all_vars(. %in% c("S", "R", "I"))) %>% nrow() @@ -132,7 +132,7 @@ rsi_df <- function(tbl, stop('Maximum of 3 drugs allowed.') } - # tekstdeel opbouwen + # build text part if (info == TRUE) { cat('n =', denominator) info.txt1 <- percent(denominator / nrow(tbl)) @@ -140,23 +140,22 @@ rsi_df <- function(tbl, info.txt1 <- 'none' } info.txt2 <- gsub(',', ' and', - antibiotics %>% - abname(to = 'trivial', - tolower = TRUE) %>% + ab %>% + abname(tolower = TRUE) %>% toString(), fixed = TRUE) info.txt2 <- gsub('rsi1 and rsi2', 'these two drugs', info.txt2, fixed = TRUE) info.txt2 <- gsub('rsi1', 'this drug', info.txt2, fixed = TRUE) cat(paste0(' (of ', nrow(tbl), ' in total; ', info.txt1, ' tested on ', info.txt2, ')\n')) } - # rekenen en opmaken + # calculate and format y <- numerator / denominator if (percent == TRUE) { y <- percent(y) } if (denominator < minimum) { if (warning == TRUE) { - warning(paste0('TOO FEW ISOLATES OF ', toString(antibiotics), ' (n = ', denominator, ', n < ', minimum, '); NO RESULT.')) + warning(paste0('TOO FEW ISOLATES OF ', toString(ab), ' (n = ', denominator, ', n < ', minimum, '); NO RESULT.')) } y <- NA } @@ -192,26 +191,31 @@ rsi_df <- function(tbl, #' rsi(as.rsi(isolates$amcl), interpretation = "S") #' } rsi <- function(ab1, ab2 = NA, interpretation = 'IR', minimum = 30, percent = FALSE, info = FALSE, warning = FALSE) { - function_text <- as.character(match.call()) - # param 1 = functienaam - # param 2 = ab1 - # param 3 = ab2 - ab1.naam <- function_text[2] - if (!grepl('^[a-z]{3,4}$', ab1.naam)) { - ab1.naam <- 'rsi1' + ab1.name <- deparse(substitute(ab1)) + if (ab1.name %like% '.[$].') { + ab1.name <- unlist(strsplit(ab1.name, "$", fixed = TRUE)) + ab1.name <- ab1.name[length(ab1.name)] } - ab2.naam <- function_text[3] - if (!grepl('^[a-z]{3,4}$', ab2.naam)) { - ab2.naam <- 'rsi2' + if (!ab1.name %like% '^[a-z]{3,4}$') { + ab1.name <- 'rsi1' } + ab2.name <- deparse(substitute(ab2)) + if (ab2.name %like% '.[$].') { + ab2.name <- unlist(strsplit(ab2.name, "$", fixed = TRUE)) + ab2.name <- ab2.name[length(ab2.name)] + } + if (!ab2.name %like% '^[a-z]{3,4}$') { + ab2.name <- 'rsi2' + } + + interpretation <- paste(interpretation, collapse = "") tbl <- tibble(rsi1 = ab1, rsi2 = ab2) - - colnames(tbl) <- c(ab1.naam, ab2.naam) + colnames(tbl) <- c(ab1.name, ab2.name) if (length(ab2) == 1) { return(rsi_df(tbl = tbl, - antibiotics = ab1.naam, + ab = ab1.name, interpretation = interpretation, minimum = minimum, percent = percent, @@ -225,7 +229,7 @@ rsi <- function(ab1, ab2 = NA, interpretation = 'IR', minimum = 30, percent = FA warning('`interpretation` is not set to S, albeit analysing a combination therapy.') } return(rsi_df(tbl = tbl, - antibiotics = c(ab1.naam, ab2.naam), + ab = c(ab1.name, ab2.name), interpretation = interpretation, minimum = minimum, percent = percent, @@ -270,7 +274,7 @@ rsi <- function(ab1, ab2 = NA, interpretation = 'IR', minimum = 30, percent = FA #' library(dplyr) #' septic_patients %>% #' # get bacteria properties like genus and species -#' left_join_bactlist("bactid") %>% +#' left_join_microorganisms("bactid") %>% #' # calculate first isolates #' mutate(first_isolate = #' first_isolate(., diff --git a/data/bactlist.rda b/data/bactlist.rda deleted file mode 100644 index 743672e9f412b97af161f31432bc6412319ab1f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 39290 zcmV)BK*PU6T4*^jL0KkKS@iK2^a2w6|K$Jw|NsC0|KLCW|M0*6|L{lv00;mG0RiCR ze)<3(O~4HR0000FKu{hFru2=0i#2D>#A)nKp9|r z05>)i0HJMw8fl@R*jm-0Rkg4sC1y2I6|4rZ(Th#CcVrgrKI|WTz6L{3+dyD@c1PLI zPYETaQs<9vcy=`+iW}$*k9ge7p2s;GQIIwO0{7fG>>_>R-uqqO z200%wF>~$jO)1|-&zxs>+!!-wrB^x8cW^1SuJ95wowZq3&b`2(dQtBt+UFg&5v|_Y zR^IOhm$P=<1KfL106oWu&Ax?I*jvdWr0I zdFMSxHMK3fsLJTB+DBSlzyjrV@ILpw_U?Qg$8WfL`uA8UCR%r{`3Vn^uetNO`g7Us z?`OI1b0yE*H$#DYw6kd-uit2H+?sDP-X08pT-)|5aJ9{cKHYwh0mJFU)#Qx%8U-EFJuJ$MIt^}tK8*V5BcmBWmKg0WD2ao&U(c$Xh^#635`+v2{E{N-2@54wg^1b6rxkS%P>8zlE zXN)@&MpnaGTPaq9x=~TT*VN3>zOSCyLw)C#GFrkAj$RCDIbi0NdSK+#VC512v9pdl zgp}`$BDg{Ho3yZT@^@J#()vKr6sO*8ex3RoZ(W)#6iGpF{^$>+LwN9bO2Srw1FMV* z8R@)w)yH#&Ze`Z|sQIHGjE(r}D@>7NL^KKEiiFHVu` zIh>AuM5Tjxdmrpx5{Vzozm}rhpw!jIfP|h9AfT3ND&T9?z13dNU=hPsKDTEYE+4g zL?Z{#ksJt=7TA(AL~bM^2}NN7sG=;l#nua01XKmOStqjKV(SN?La<6o=}p{H5s{G* z5HvB^fs({uEtgkra=_ey0I8Y4=44cejm^x+7D6CYLU|Sf;bU^hnNkm}9tRQzA;d+* zWK59~2SLe_a-u0nO-#&zftdoti54*~T*7M#rgh3sa^%RiYLmp+z_eB_Wmm-pYhsSJ zb21N!QLGa)VnvKKgK|!0VmUlX8Yi)&Euzj1GUf!wCQSC8!&7rJfsX+eKY585;YG>^ zgQ3nGi#pl!NpgX}!yzoW|9F$c;1-a#WGqWVGns+J$iRUh%*fElu~J55OOrDsVrF$2 zmn2+(T#1m0or93?7aW0!nB+}{=RyVxEfeR~b)K`{cn;!aJ?Dnjay{W43=2(fERx;z zOSSMKKNZf8*HPKk4w=KWH7Hn-QB(g zqj5GknU@L>D=Y_sh2Uj?wtI+?AgL0j1-nFXGpq^`)%X#>M8rZ$5H(q4XmwT0mF)2& zy2>^t6EFzOM(ndk7kQGZyh*Md9tRJkGbv&PR(xIfET9n6NE*n%a)KscL7>Yw=FnPL z*-){GLC21fG>Eyrf;bWhkuWeY*ud&t<6@^yGU3VMOw2Gh94c}oT-t?+7JjHF#r4lC7Tr=vZ@+LoL=--7C3a87P{w>2gM<1hi#m zdI*@C1(^ygqj3bxo+|@0B8H`HN|})|!cl^HVrpn;L!b$LY+R+mci#gtVRJJHB?l^E zK!zYCjZ8{l3m3VGFu93@mJhmHIhc)Z=F3Bq(vO*pVL;4-s5*kS585nJJ3O8v{3TL% zT~RV!lFkm2LPUh=a{GuKrzVRox1SLhtg__}Y0J8Ip`px%f-MI9-Ypq~(N{9)OU*j@ z((SVkk!PUJ3=05aKyz=S~KLcviAeabojVBs2?! ziIGIkM+b?%<^z@>P;3h#1-%akZw?9$60g_}|PE+n{pdv|Gkm3)=qD$udV_BLdh7Mn)#2%?yf|lOR}giKyXHMrA@Ii4p`L zMM$@cFe*fYTt+U>&E!n%C}cwtVo;iM6tjFnWlMz2N}3rK z*hCe=<;#W3mnvLWE+mH@Le>v*1_Z30SORetS!|P#Sm^F4nV6I=UDT%}r0r>tCRCZB zLo%ex7>|gd$`meY_!THcqSsS49)dGjmMCMHB1@)gST?rEW)^Q#0m+yV5vb+{r3(`@ zGchwNVt9_z6B37MT#XBzMg}Az*NUVJ)NZ_9B#y~hDmle&YAcY(g`XoSoN1we`AKaD zF)n6x$!_O;OQL*tDs>StCSXX8NK$x`b))Q;E={aLYk;#cd`N*?^d6Z|N6C+c`NYv2_2hG;FbqJWjWyBlArZcQt z&*s(~E>7>wT;x1NOn0VhoGKy3sEw4Bc$^HPB<+xeaXZk&xsg*6CT2wr1_ca^j7u0` zM99(bl6uhcY6)$hd6KVcf+%(DlrElYj8fdp)X3D4QsyNJk%*QYOlApFi4d-4B#erZ zbdf}*QpC;kLRXT?%w4XYaG371ij)yDCT2vq2+>a^oC>NJ#DJ5>S|1}DJ&jI zLFPc2GE!Y`Y^jAHJ|+c8nuwr`Cd!X8L`_F1Y~{o|)UmmtVay8ynv)GgOpzl)nZTS( zO-CROP{L20AW&6&GL9t&GBh%(QHha2K~srhrlxjSJ5|V=n3)$LMpu6s<0xiuIh>3O z8i?G`fdi4bQ({e_xrtzr>+yrn5||J&QpxOcDYA|=A)^a}=yWPb$jph%!a_5f{aJ%* zz_OF=2B@lP!dXDMcwiAh%O4k{fr`z*@ z*!1S`;DL@QwDo%Zzg&JFZ%rvm!Vs-%TGEu-?8euWp7+1q?B}>r76puYg+S^x%{CB;+My$BkZE9oToMWGlOmgqfEG-G^OX**v)OCl4%Drg#p!cTpC?^rz znh7_FoIS~iMb7*hc`X~*_3M)8>~wbV!}3NN)8={jH2b$>{1^Omk^EuhbbBE5gee?f zIbS(({1auQ4a>dq`RR$TS#)ng=VbR*ikeyR28S=T;3rmOHk>k%)gL zX@jEHHkA=8VuQBA(HlkmRZK!wf-qo2(CHDfBX=dE6{4?F0(($1uZ)P_8z(gCHmuCd zNe#78Vv3-xN$2+LIE_b2n*Bx=S`_v?4e`+j;ui;4R>KAqg{bsG`H4IMdl(4(p^)RkC@8pTq+8ECOkWg@UuFZIT# zzn}k7_qm>S*P#6AT04lWLoqSd$-5oKJIRt7gEbkxR3CCQnqB_Z27nq@Muv(6(27t3 zX#~(Hc_@!TN!udO8UZL3ri9P~NE!+h9SXVy(1ws`R+Q)$pc;Bmp+KcZkZBTxDG<^q zX%3WKAQW^W>XS$s0MagiC`8gJr&y6trRp+B?zSe zB_Nav9!eviq=^=Qpb~*vXi5NS0)mAGg<1un3PGV-Q$V@_rj#g9DN&>vM4<{qDHJIU zD7ru>p%$qr0)QzNfG9+yQktMvg!g0$UY2G^W@a~=G!bh49xmfkIe7gZzV10g!}B0;i9vkbtG`Fqx=e}I%vqxg<_(les zFnRkRl33^2?T%g()wcNfnE-XuufXl!)63I(eLpYN_`Li&`FDMj!t#M~Oot{2im50H zLL+R^5m6;2RRKdyLwWj%&GVfXlaG@gxns&YY7EWf@n68P>*J1o40|xOrwiY` zJo5(bb{YK+-q!tm5cScw=V^X3AC~G1#b@P3XPcGbiNi0JTB}Wd*C+Uqiqjce2TGHK za|w3RwN}3wckX`PbD8;DT)bkJ{$Pigzxi-VU2n4b?#Y*7qQdQh5h+#O-79M3w3GT= z;I$`EKm3~|%! zCK?WdRK*8+G7purs~Zt>Ds;yZL8`h`<-o){`M~JA%eqvyt{~}^@-dijb=4-gEBt-R z#l%j{wf_{`w(YxaZcM`y4J{m+TRStLmV$PoNtAH2A;G}l=8Y;*lKdZD+g!Iw)cMaI zx4cfx2c#QnDJTkNh|uX1Z7YKag)%^!NryEP;E@_cDFeap0B=YgKmc@_WtNzQBY;R( zPF`=Dr<=t35J|fH3VN2jS)2*V<#EdC&eY6#g&dovWsX2mzf>UcKrWzWj(t zx(|~Wj8_jyx*Nqix(E{lj=o#<_4U^6fZ&i|zfAAdyzKj9_V*)8*uV$L z3J$akEm9#Wam)Ls9k=UJ;X}?4;L=y+lG$uGY^utRDVUh#zM#thK(7# z0qx8IDVU)AT(S$~VUMJo9+?c^mNv-b1xRf~nw0cyfNck^3=T##kr_f>HBG$?P23j; zchALw9e!Oj$*BsqNl1S1^YQ*@2NA-l^rS@SfG8|j=-j%0k5oFky1XB3c&w48uFyc1 zt~mS@I{}@#rXN13Z`gQy%p=w)^?bl-;JZi`K)-A91jR;>G!;ijLUB{Bx}uVrDCl!E z6-_BaYz~@gw3HUYXhqVLga;lbq~5UoJ$1$tY{=|D&q=KLF6zx3Rn!N8NG z&l5tn(2@Krg{On^4{l-vDyb>4B-IE&h~N2aiv!og@?PJEI&tF}HOi!WK{gw2J)bz- ziU(*~&wf!xW_;%gEOb^CRO^O_NuVm!1B_(@UNT8(Y?0c;k&1z8qEaGIA{3y0{GjMS zO#&f88X8xnLC^_Ev;#_;VNazWydZQdUcfq0T4+I`MuZf}$qod3--56>`aoi!N(!S$ z;-uE7q^62OW`e1uC}|pLsz#9ll(rWHM-?ycz|TvE-NAoQ&&7npPdydFI`#J|At^UqNVPfR5#w$M>YRaDVUGbrn97?Gf&kSVE=+m0T~ zd&JGqo_s*kr?R)*s8ps`pgjcT(9)EKH|X?DD;_fehZQLkQ52C46ckfSMJqvF7>Yrp zLX=2=Xr(LU=^6I<@CoAJbSWTl;>#MGtJ}Hb8zI0THDa$2G%pGTpydv#qCv>upFZEq zlm%Mj)N4po?IBQcL?w1QuNBp&ADj!)od8eE-#%Zi^T_zAM@|oTkt0%Gl#KrT9YInL z)3f-K6=%ti?a^XNF~?)KWeufiTDOl3&Jn`5aLY!|F=NjG9Y3-Hg*1UpC{TbDDRzJ= z{XY5UjDXs_x5Q_~0g5HZgidt=)PQk8C9sfC37|zNRQmb%@`>BQ1ojXU*%kOg0KOkT zFQ6Wdh0xLtkz9Z%2PMMEK+B)M;@hu}Eqq-5P91dacINPQKQT`xkTg9jp;jcN+P#uV z1bO!hF%6;PtfXDonO20Df+T0TYrE^Z`F;Ez5ffT@r6E~gYip#TUZl)psE9{VBwDiS zljv-<6Nk$d5t7Pq6n?+HdPZ~Va}H6=tdk)#3}){0&rD;SdLX9+~C;^~iv1mF2j<>kOB!g|a1dB-;u|y=%ih{6B z8rY3=?u4ic&G~sgdCb0Z`%UA|&30Nn2yq)^VP25JwFoeQQnR!LUs%zVf z2&(oLh&=Y8_l&k&EeF#Wkqy)H-Bd-kkdQW+#A?6ec&O$#ih(%YId^pIWJxtZ?Rg5~ z*3#|Bv>h~;GBL--YNm;(Y?4z{Y*G?EQGOMxR-v@1(r-}h(`)g3zh`-s`!lJWwfQ-H z)>TnoVgVwkqNJp(*lkLB{LwYuu8eFjYxgXGo`JC-*mhS$w+0B}oE6 z)f^~Y(juV09C)H?3Fcl`Xsq+_L8XJFD^({W7{)LmxbaTOg}&VVn$Iv~Be9j=r%IDb zE10o*Kz!RmOL2!3MXq*nSy>+EacU&xUrE{-gLom}Ho}1X&S?cA7r*SRpDBHCC){hxEx3LdfJe>YDWK z?Br=k=)F#^Q%fk8L_Jecrxhq>Ya2dA`2P)HHayRdFiioQ=;?Roml<;u1ncf6)OV31Ed)e$7B9?Lqud3Hjko zw!jbLkWc81AMU|acZ6Nx9x^(BAKZ`+&mytP!Z@IBVjEOP{Ol2n4Qfb_^}w&?g#Ktl zX+S=EBv)tz=?XoPk0=oy*hBu%r)2C(hbRQpEBfEth>y=H`Q%^t^287Bm(HZrf_hSs zAVAw7q5=+vK)MA$B18V01S9iV01=Wj#E^jd=ey!4qKo88$K?5T*2Gq9V!=R~bGsNs zoo~!a_@xuUZ-U!fREnjR#v?lqcEB1TTewrL4lq%=PCIc>?kS>*D5{96r1PvcEoP_k zh#!OXR=)2fv4{=g$6Cn9rYuB6MHER6ySO;abcTA366*$gt*4DN=MkyT!^4i9i!rYl zre!Kpr7BX=ltG8x>9!!zjj?`$4vyA|Ib_jIXZ{a$w$26>1(IV@qvQ!FW7d3;P6BKX zROwudoVsY>E{rX$v`#8xj5*>u@_b^B`p)*%sG^A0@Q%LHLIB-rUkSB57b_Q3$+rb+ zt>V-{b)1;!Qk^Fl?g_jXbIh|+o7(iuPSHC)cswUH zPra+E)m2o*ji#!Pn~u+sx(M7&T=!m=w->y^LIccqSqt6lh=`&&uXUz`<6~n)Ls2B@ z3EV#ccb|OXs;lLz&0*iMx6$uCs;hf~*6FX&APL&atRj1*^d9B001%t#4TD4V*oi** zam@6?iq&Ym+%y3-3Z|t~-6xaw&$wd2 zg9Rd#dFf1FMD35Ns;a84sJm<>T15D=dKq!k%5k)|*dZ3I_mW8h)?=+|(y$Stbi7Hj2Uc<{v)lgGmbQ#IF=3GO3w}cogW}|l<99l{@eeG3M zUyErAto_JS}fB zp4z?Cwr%F}7{xj}^2zW~L~kfO#-C*9;va+<6o{75aQ3O2*4CSG)$U%jU(^y?d9`E*g8kog+#Y!|*`$nuIhHAN9r$@qsw+up^_I(kh!N!1e6T6iv8 za=os!=P>iRO)62h5{V!lXEM^-^g5Y-_FQ3Dc6xf+b(=Wfh)#wEws z8Mc^0*>>96TPO$>VoNty4zJjBi(A zsGWt?Hi}fOvW1+SX;amk!1cKFcb-B?+XZfSCDQ{6h5ldeh= zB0C0r{1QR|hTE7=r4@grC<0IB0DsgDV2K+3a5L?O2lJaEC-Q+R8egcz75x3f2bKDu z;rNN0`FD828$5q+>7Tt)^yB?K`+&v?fw2U^=(Rsj-AR-&pXn@`|EwrRJ=te~He&uX z(&CKlc;m_r#QazFLz2t=6xO=_`0v8TN(u_9++knyeE+L{f6imJH@=dKOAgy`@5VpP zu{q9job&%et!qkizin)-Yhl~V*?5{AM)+Zd6o*!YY(epbC2m-E`cb`ed`$13E?n!$ zaJyCxBKM8&dhb~|wawt}@{C~&Fv7TDIL>c5&o6cHF~c>EFD#xhg(!!SDQDhO?412g z&3nOs^Nhp73^O%`G|7@)(jPsPICX(

4@}a;BF#fAs5pp-L<~;CMF%1|Q5F89zG!W89ZAiLhO!(&Bsh$S4G0d|&N=Nk zcJgiS)t3u)*{xW;F~|lV-VRNB&mQUhBI)&UqTE3iNqC zwyLg=96pN5s>2>wHCBq%?!oM>-Wg>h&b-j}EHFn3m8YxOm!r|hM+Hj_^| z9%GO!a43l95+p*^XEq|-Ikz#{;0p+m3mJH1)uL{WtTO53(WAq(Lk7AxX%n9nJ8G@W zF)N$Bdp1XAPYgOVM#0I$5;u7;-8?H(t~Tk;R%G;X?sa9kzYLJzd)p^sI73Y^!o++$ z5QKzJUL6fv>gV5%w|kX|rB3lz7*99GYOJjj)5+}Nqt#VYqNXA4dNNN(d>$P$Txq~r8ID};m z5F!u|j~K=?55{>9UoMDfBPz>2LbCnY1RWM3Y^B-KNA+K8!Gpv~pRI?&YT1PBJ-6nKEI}I*5f%vOwku#e)uX-E2DoR%dlp%DWaP z!Qs~}mN2h<`aR5OqzE{i&5VttYR4hV7Is2uMBq^1BCJ=bn|mV{9Bv0#}O@S8UTOF@_ zP4;^#a#o5I=UE~I2Z9qTxb4=AZ5DvAYL;OcWs5+;SU19ZnR+zQY2LZlt$JarXJ?}$ zhXb&X?oLHZR7C`Ge9Xv&3cSu5w#AxFMt662cXo1w;BzKXiPaRu4TNYQkE{qz_0|4;pu0Ehg4zTesZJ5Nl{{y*8E zvu4%=^cVi@$Na7T8QI|NJ|qrfH0KLa@rhD9!~5BpuEn4Z!C{$$A+MwdzHH6@wq`D6 zmIgf$ul&E=)s4)C^_iDu5An~lE!QkMx~Kj#ulU$_ciEo(Q6YzD57Vk8KR*4)TfEi4 zHYV4Z(5c^TEJc_bLV5l~L^a!44%Kop=EhvIp{P6RXxi#)uZSUuISkCurj$_ZgHNrc zb8{Ge&G)hE^Y;TG`u|HmP~HBKjQzGj2>nM!)c&sU!IxdbxM2tT&*_j1s$K|xxb#8@ z^kK+f?z5p-gkczdxmxzB{aKFYPJTkz#Hsaj@Axw?ay>vZ1BYF6B6%_2E*FQZhTg5) zNR1k|a^aUuFws>fHzdQC37X=675FqcH&u1595!-woJP)y=yze!hGgmdo4Arp*z#*3 zyH_UJVYKMVx}G?4bv^Em?5lT1=kv=)N4=MR=ls?jodZ{^lbWizy;`tkPn}-r51M!* z3h1NN>+a*v)x$HZcZ!@Qnokem^qXt2;&0}0UJ_CdiILFKOo}QH1cph7CM0M`vo#K5 zoaXxG_^oQxC{0MMNl4YCU>6;ou3Ak7iCy` zLYY{ME&+$a*1h7$%i{AeYzce}NP(p#rRP&KEHx-<)v*z!TVYe+!%G=Hs`!Vu9xP@R zq)W1;^K3`r26v7Yh`O0cO{F7)3}sxh(8r85`bLVUJ>J&Ev1v$g7w@L{ot{qfdDPgG z`TRqZJk|1hB;G*<#9&l%avVen6ee5VUjoHQ7e8zX7r=3!7pnpypknOMt(vN<4y!Rn zYme0YTD6~|_HM$fmJGwldu4=3J@n!3j*K*{5XLBUGQ=Xrcfxcc>q0ZJ9T`W#4-F8@ zqv_^abNBlw&?=NNi#91RzAUo}Bigl9_#WsUkmM%d_H%nM?qQb9BDy?Ic4f*dKCzVH zPtK`S%_b!~IC?k3tD?P(y~k&hW{)PN=#jHlb0iyknRDjTM+~)eYUcEMOskmmSjVR~ zT)2OWUnYz@xQKc9W~2?_zgZ(bZgKyD8m_HEV`u zTRo)YrCq)58aIt8*E5VcX_k^Qp|XxoCpUrNs<6XDa}sptBw^sK-CMf8JZy06VQ{Lp zOxeR69UYpr3Ob? zxQ_dBa0RVDj-E z_hx*alOYr+JC2ylOkB=sY%z(X$1xnLRSkxG^TnVX4GaiMO@Mrx@$?@7n1{R1?fLn? z2%>)&9>TNy&xu9`JDHh}crc*0ZD>ncQqW%E$Ap%q`8>?#(KG|i1xw;^VO zNFYS$0qJkmGSvH^c75bour7^Fn`XOniGi_3)Z2)C-8h*t$mUBdL8Xk+!<)dG!MiA6 z%_8(WFT}na1{leif*;|I8x5PREe^Tm#p#_`!gX@Age`tUM8K6aV5}<4GdCt?Vi;vC zKM3GwKhyQva_UTA7QMMraHVynrYNdTQsT@RI-$n8M)To3B{CD{!1`qyMYG(2n?}bI z4lY^h-?uYUCj8Hjv*wS?LGBjM? z4Iv~9zD?*o{*S5Y^GG5N-NEP&t1;`M`FtPR-QL^*v=|05Ef1+LmaRh3sHyC`aUY*Q zTw&-(sr@efv78^%-QR(YOUQ2#CUOQYSn?PXFcTsCg>T(5BAHij%tS;)qule6Gv=@M zyS6IJJRh;)>oX+eXwm0mcQ(v;hG(LM41#P?u(1|wUFcdOD^?L>0)YaC0y7bzkv5(T z*u*gqX9962idoE&LyPITV{s7*rgFS-%N%#kGRl(CnVTz4Ia*=7!`Cv&@N+t_!=v{rv6XguydF%nRe9+! zt)C`|96bJSMvGgjaHLFGR!&F5;n4WJw(sycz0IF5cJ)|R?4+tpvgy-Ss;aLql@NxE z0SsrsLGT@)1{g;+>dP4f7!8htbsM#VX*gCS$pRuHthv8YA*2;3u@FZDG9PJUEbK?u z>RASk5N3&oz39=Fjx$w>n5ug8aq!oM&lPtxXtD@KmT3b7Guzs*vZ~vygdpF4-@tTb z*15OeHC`KTdbVt?Ta8|_s|-FzG&L$ni8B)Aqw%LehVDM>@KGZXg2H3-YbM;-oSDQ= zNw%1I<(Cb)I5-@Y4i-&pHa;h&DtWk0Of#ichK*~DomGt*b<0+Ll5QzgyXTkBDTi%Y zZ0yS6hfEHPzHN;(s>7{bqgTnhFOt4q&yUOBoR1q7kcT9S3lR=DSFmxU7NN|6*;4W( zZs_ja##=UZa%-!FRZ|Q*?&h*atP+_)79pZ(5;3{nfore|0z#ny&P9m`typ^cx|}(- z5!SdkYnBy>mCFifrU*j~mv>&U_^mY4(Of?7x_~%8p(weBRrtcnA{EJH2Pd=%vy&(} zK^Q=|H&_@jMvjX*EZ}_v3=vu*2EDWEXW_!cD1#)cE za)w-*i9nbqj>kLSZ0(x(xp^=>A*{tO2g=WN;G$>Y0BlWAinX0@{$_0D_D z$MS`PIX6=*#|qYw{JVU~z0>hw{Fz~2s=oK){cX_1l!iFR+5^{+U(@i*;Wb~VlZ^*=*vI3)zQt(!*&ReabMzK&5@a4vsnn&6Ei|$5rhbr zW`@JFH_?+fd7I1G-$VFjLLMgZ9-nakq3jf?9h+Z z6ZUfHd*k>1+vn~VtnYaIZRJjSTyf7qdbZsWJ;4tdXLKZCfCOU>th zOEo<5^+Lyuh3XG$QfFUSgMc9m^Bm?O9HdBu9i#Ik&0AyScpDWlnCbvp8y#+PCzx z3>IODhb+AE%Nr{ZP3SI4Wl1v}2)jh6iire;amOG(MkJ8SB}%NixZ$wbcE%aQE!JbO z$RYwrW)Y}(Dk+dh$U*tWaS9!kmdrL*tTWZack*wwZ3Y*5m2odzScI7fWF|<&MTz1p zHPkW?@joKwrOKEX8JXt9${QSw$cM?9o4xY&cKtm6un+3~3-Ax%{(n#3lj3?n8{*8& z@%GO;{{SC9)ql)CXUplPPl?`dp2yTJGf&k0PS(Tp??{o+wYHg!4wsA!!GMtR#BaD_ z#&vd|-4D;im&fDrgnt+J`Pv6O ziMP=EqjT{yDN_>T2#GMv$kdsfnX)blqyjpd7Bkkx%u8HFo)%%4dl17+FtWsCFYfA( z>N^ZPI5{gB93nt~rl>@~uC=tXs{DE|!C*e?1kR;!(J=TnXw#Q>#~65FRSMa&B=tyF zCi4=jbGp1YVTtckNmEA5b50tnPHmd9%Pfk^38z(Mm$|Fc!%}xd(cbXKmo||NnN}F? zoKDKhqg5T6K@jk&M}i=#pUC$bJ}Vg6!LVWf(04U7#4j%;dJb2B2W8Zb;I(1W|Al1U_zPDnx|TAT{^luHZ@7(!;rcTVV;mzs^gPT#}>O(Iy$M+6B>u*z=Hrg1RC2CA+5yvoIOX!xTSCb25NcDHf#vOL`|8iBYa!Y@a{VV zk>T?^Qqw@u`2|4bx^}Bbb(MblMCReVp@K)P9lz3W|~*% zIB5$%l}EFGV`5EDsQ0|5lB&5$YGF~r8G0~bRj0A5+Dzv;Xv@`FD{l9s z+)Wi795B^dE1}JqhejrdYO2A7Ql90OmP6}0LXU&kpi@eF7@%;NWJ038f@Jzn7Sb@s zPK7EMK)U4=cwoZJy;Zx1R|jKS97vloDnPSyDqKco2G~VhagdIh z7=kQilQ7-P19uF^-RJiD{}=q_=TSZXf4*L~hvw(t1bv^b8Dp9J!LC17`Lw61RFJ`qSMMcB#xPpJ4TKT|BZOFkzhIiT1>R zK{PL)0^^wpjwd1n8<3<^T-Y1ROYj#!sW&FZ#-;{FCdLMiJ3UzJqju~j6zkSwb;`*x#Xsrp3*SPq45v0n;{Q@^j}ViTYKFmZh>!HpX2WxN>U4S1uEh z$ekJL=4hI%l4M9omMeo*uG3hh~4JIp7*nUo5Fk? zJbTLcFROMLd-BREi$3m4ODvTuKH8k%%s$x;tjdRY?mhv>h`5lQu-y8NLnZ@%#M@9lsI1P3ocR zAK&slgh)TQX7>AizQ}ze?)Uw;n;L-J0g6ZDKKe${hH`_+3+Yf`+zNA+ufe8Npunk^ z`O-VRV<(b6wPpy$qt21e(6pxWMXb?*)H2VD*qb?{wcvCau%F^|gg8#sGdh3+HkA*X zVIu%w6EFtEl=gA$_jahqN%ow1Y=uw$;Pc>@Tf8k*2b7+-hh!~lGs;-?|CxXJDW%Y0 z;exoac^sY{PNYNz@`Pgp&!Tu?O^yw9^bA>-tPCw12QfI;|Z+ z%0v+v!choxp=`7xMlw-iHkrr?Q=kxF!3y`eI$+>J??Kt+fCdxcUP0UMDC|yeO4XbjvntCrx&LzX02mwb=uDn__aYC zV1gnx3`9W~VGzVZxJ$>p4JM#~l1Tf-t71!?I# zg%8A-Ve)n1C}xe<_q;AyUq9uaL|%K9=^Yq6A_&BCD*IM>o|2>lRC8OGYs}Epse_d= zCRCx6$QTVko!hX!ZWN2>Hfa=8Yv)Rh( z@X^DEN3oXe6*ggm&D*qeYUIOb4b_CnY_4xcTRo=@-sTuIZ1*thU0|GU^QV*1+0o(b z>CQPutI>w8Z5e39{s!hP5fcX;$P^jKlr=dUiXvjayFcFxh!Gn=l3>)&u&hnV79}!G z&`dz;IKbk~h*DbGJS$#8)OtIxbykNBSd-xImRNhUJ}sSN2Fls!!`|JqM?-d1y=vyd zGL8=fgtgVOCTbzu`IxW>)J$|XCUuTX-4PkE!KPr-Wj#1M93*N(VF=hatVcH_NxfP< zTP-?em2tLpbz$uHJsPm46|$Hyhse{S7FpQK5Lrgxh5{^L8njmq8nsQ^u&kIhaMa+f z39_@pJLRO)Q&y}^5?1e%$9VXXR@-LJ}vD(FMxjMH}<;Y z!nORuJ=RI}*(55AC{NREN9VRAkC?z5r~`5rYjQT0AWew(%dkNGh+L8Sq+R4<1BF8o z5(OffK*ax*QV~AmF)PG|xP<&m;f#ZbJ%M6>ha-vNK!^{OIQT|5wNw!bM3O3^j7(Hm zAfSD}74hVD2(QmK@|-_BJ?L{axv{bqubhwAHrj8X$AQR_N~)4s5gZ9>U{RrA*{V$V zOtIV}xZrz=l|5!|->KIvU0c2>-Z0U}t9GzEK0Y4z4_2K~hNQ{2^-%@}I! zVQg*j>AS`!h{c1$)t`%#Sj~;ip9J_iJzBduwoY0(M3}KBlft^Nu3I=&YVvB>!vzZr zEYGyD;isX8o){{WL^@U9r%Yc?$;6u?qB10EBBYKcK|={Uj$Z7;odjz#Q!^;RsEZRP z1|&9SMf5>oGg6G@Vq!QZX2gj+$jJ=U9h8B|LA8l>dc~cz1d+Qg@{OT zVdU<^gNTl_G%_)%Qv$+hrirl#49(0;)hSVKY;tmP>fUa%l3KQDWwI@a>EV2yTRJ>A z;xuBhE7@L+HgLJKY<{%m+51J~3M@%vf6vh^O$E|-|Q8-z=h zBHjG}>c+LhuDS#qB(g$DNjwA`q=b{oVYCJ%+haX?VHcMfOSkTUS|$ns%WkeS4-nJK zCeNvcX6VgMd1X=PLo2eOAnh{%KS030D9kf4afWK&r)=4f2p%@RD8P8T?QSx9QAaJ~ zMN=EObEu`eTdF6w&>-#sGChn4_o19fUlZm*qaRu*y=&y2yK`;{6>cFahxqt@!=`0% z9s0Af>9L1^_JvH8g1*{vd;uU!I&_?GR6r6K`QI|j|LhTGuUD3tg>)`#CUcL%CZWoj1WKEI>87=2*U|> zBIz17ScGXr3xNb^$ZDZ~Pp|6!uTbV)@B_b(TY&_45r{)!p5&N$*|6`kv4}bl#&E;38fj#%(2eS@ z@3W*=Y_p)yNhFf&;exlr5A593QOulrnH=K{Q3l1;IU6TVjkb;6jJQ=lgAN-sGOtG` zMz7}8u}Z4g*|DQVZmb1OSWL{!P33|k z5XK>hV;II*orFo48WlQpZ+d2Q#t!66f`g7Z28v<32@xX}o{1)rq%|UO z2NBlMIFjn(TaP`ZX?|c|C!?27CQR2KttSL<$9av=1P1S`gvXv$t=eeW^dzk{p z3!(-PV+IUE1ptI0aDy;_kMI-++CzSO;n11$EcCQfOCgd~Jl=;4w0kg&9o#bEUUl$S zqC2SLd8ETJ{VnumtHTkN8*=7*9AGhwd&k8nam5id;}&6wL=c8;Yzz;n!-a^41R#fA z9dN^gAxJ|J2x$+HkBPam2{A6IS9PWvSEQ(ZN|h`{)MNEfJj%Exc}RxS9eHR%9EeCc z4$iW0u;V)>krNUHGT>0O7>(VLxzt$ZL_|!81CtyLhs?~;xGn;aov_@hn>JNvljQla zHqup|zKYSqM>gD-W*fcFCWiJaavX1Oqeat37+}h>HAE3)$Uza##`OFT#P0lyiQjU!~onw(WIq)!4;E7LrR+TL{nUR<6!Y9JQU>IE*}+^l1!O*{g*KfaM4f ziZPE1S-u3u+_7;N3y2uFjs`{+EJ(olf@X;VqnH$lBbb{)W-3hMlx4ortZJztoW>K` zy0B`e4cI!k;F>IG)kdmycVP|oBlWCiCl1bU4op9ywQ}KxSeR!7e*SQy2`(iV6)ah2 zyw%aWl&SG~vYwBFEm|=8IA!LY>#Wh{*~8ODip!HMoRR42*_K@?&U9dD;k!pRjJX{c zVObiMbK}$IL+$6UM3ytNvv9(`f<83(qP{+5xkeaVp`bJfL7`i6h8TA14CgMTNb9OJOmUUC zEOg5A$2`>ITom<7DmBRCEaduNksTUMrBX0#8XS=pyH8|@HJdnC#KuaLy3z3^N;pPhGnOkS+0n(eYG|!BC!^(Aw)i&9eH$FrTCJ3l zEt*8+t9%uuM2%^li#{FZ;majjXR^;m-nVV0kzAzvyjy6u3E+f|5=c!7sJRE4;QXJ9 zqJ_C(5*TSdd#vWh2@-|X-4@Suh&p(ueol?EYjIR`QpjYYql*pD!R$7 zMK?uK3c8gumTZYhb9`MDX|&OvG{-y@UpBVQ43u3Nwn}Rhj5kIYMNQ(=EmVrM@KbHL zt@lE{`MwM0{WeH-C*t`%+lI@7|DQayRcf_1TJcb-L*$WJHF8O*X;~vY)S6DB`Z&LH z+SF`Xxa)2Tk7lcLwbB+Ua%aIJxiyyuR(vIvq@^c!kz(OCGs3{`?Gth46EZNv%%z^P zzP38PR{c@cV=|psLq|}-C2VdU>^h$BaGx0i5{Z&fpB|iCW{{?uXcrKeC8cR87@07W zGK_=Q;{zWe9SUyY&Q2N)Fj% z#EJA(94IPeR;>o1GN+6@zK@Te)Xc+oG+=xf03Y1F{{=)%eljGWOX>2!u{qL}dl7m( z*KezFJ=13&TH8psn-@z~&C3mo*>eS!wY_<^0+84B0m>|ptOyk4%M)jZb$M^Hn zS9(0+?)ClE;aSRo$d@krVMBJ6N&qlTnV2!PkKg}mQ^BFs>anBn?`5U7;hj{N-bXLw zdCH-rJ2~w4thL7)xbWK;qZ3_ijqt8NkD! z{o*n9e+kvBP&caY=g6?SGVW;n*u32ut=B?{!%MMMGhEMHbgDVa9 zj33L6Y-2gDOE`DNl_w^w5Mg8v!U8Q3*_#wWQ7Voj=?}tRXt@J&Pl*}nfuPhyhR)8f z9GJ$;`M7kfJf4k}t8A>SJes#J3X1u zjc4xmJhoY7ki)Y_OBP|?mDp1eNvu@GiH$HCt>L>ZYBHW{h-)@O{EQM&Hwc z41F6tS;EIyXoPF6W=))9LSvYQ1Cl^+!i>dVgiVXWUqjiWQ+EWoSWJpzq5uUq3 z6ZabeSEH{+lSTKKM1&boP$+zu^?6&vJ?+rcY$7?Ujv^*Vlt#p)LBv2t*8L5KSPalZ z0f~Ml;Z%OGt1S!gp$KJ(PIx=NUt4GrH0JK_k)`gm<+TaQYIB?l2sA}Z;S#bl&4Vy0 zTf4o&#rzUTh^`|bsou;g2$}r?_gG2an)SAres zy1%d(gc~Goe!1%Vo}Bv!$L{ym<`MHBH^S4P`ORr*51}O{SAp`Jj>D|27>-6CdzTQ) zM4L+$rjsw^_Iuyi@X*lh>VV8kx9#5WKiXFBypI*-EFK8Kh`Hj+%qah(pnXJmTf^(G zm$Rts><pLxLpC6C_B0=WD~Rosk$i1qPYwZHXkRh+7h9j5K`yaG7ZEpVqCF-Qlht z9@&e-UDj}FRa0j^afXl7op8$t-C;1ij!a3@N0do|(tB%GH{LA5`$RxHCLF0C@G#zP zzQK1dU#&^Io6FpIy$5}~E_B$5;YTuKk?{D(cjzQlxgSplgUZ3(=l+iS1ASN|Ko8yj zU+q4bC-Z$eAKm-@IPjPHH=94F>U~c3{llN~p1A0)@zqt&@pXUnzxww7!nuBw5miUQ zT!0(}Lq#-7Z_Sv~c6D8K8FSHhrb*nj&fBj2FD6F1fD6a*WgQEFut%Cy)-bYNUofwSF#IYiz=61(kOHkXD1f z6TBIin_njgO$-CGCYooPEfvVh@r%Xn2>-S?%!*|}Qje}iI20`%Mup@KGkA1&D_k&&uhOS==0Y%Ip|Bi5utAU_;o}_ z=dyWXtIe2+q9ng79LBq5pCifX1}3mYZ_~Hx+s#Nr*Fm>%cOWZ6*FfUMQ3*VDwGW#C zD%R*ZcXx=00&&w4wwt!vq|;1wO0`|P1l98J$3n+QMG`S8#B&>a2PVmx=TOgGu*`vx z)JtoVY3YsKr^iXN*DhPNBIjtW6GVP&9!D${MHa`)sy#L@#f#lbrK}d%@RN?*cU^4g zptc13L5q@$&8u3f;-^%QM7ql6qpj4et+cx2$a>Pgub*li?Xu5KEvK#y+{~x7qdLOJ znk$&Zn;9K!2BHUT<7haBAok>(dB-eb>vqdpCY35e)b);#l1i%{5XBoCV^k*D*0_+1 zPTgcJNZV%#vsGPL=E@?-vDOo79p@VE+>LAMV!LX-efBhrF&jFcLLP6q)u+zsl?;BGF@_f6b99#eK5 z2i5eeW0U^B&xTK8lXb)-B zKZIY)&v85j;BXEru&{uyAr)1T07#$}Re%*_R3IcMDN?PLsftw=EUVbqAE> z&XL;aZU*Xxhi)fky4)TDln5E!iV3I?XcCo9G9+PavPt8Cu4AuFnYJQ0%HT$p4t7Ku zX@ViGi8rzhsDnvma=;kaRQn-O1EaqgQP1Pe!hSum%NLNXk{qn21{q~I;+slgAuM4g z1|b+cUCiXA@>fCZw^{O2r>P{oMX!Xt?hv*xDd3u#t_haQu2{X=zJtPlz+sfxv-=Nw z*{S=|N!b#Fs*+0TW&ZSex})6oZl8~F);h*N!)6h(r{$70k~yS?jU8AKuD^pv{Qp1a zYSBJ#RQEa_8*!Nl)Q+j5azCRQ9i2>`8x2)H#QL5S=zR(QXm?+cVIffRNBb9uk?SZn zCiDCT^7u7Q`4u-X2N{Ph5DzK1cyV&X!0tS)hxj|EQ45*Z! z!6*%3hS1`Yk@6eLYvWh5_HO65x1U@vzDX|53Uu_^yH$!MYeix+4b<}syicp!V_iv` zkxoAE4uJnB@ct9fAAmoE{KTQ%S{`TzBtH^m;PXmsb9sZSrFC^m4RU3!I z2Fx(U2o|Ncg zd@K$bt!1hET>Q?13FQGn_9M5OGQ%G-gBClDt=|~OVP1kD!n`963i6cZ|6i?bui#nN zDK^C4S8KLfoF>@@7nze8on+ZJn9$!&$U87j~vB=^g<8e&m8Ou3VHTgdW=TDNG z9GzSz<>zIl4rh1&cl?rk4^!oTRpfFwQ{Zc^r}d8nbv@o3a~wQ1nV&J~52#MVwB~w< z=rH}3JDB8*PNIBK_$2qEhv`q7Vfj(-bAFbIhsU?dS#Q(qmcJ~4Y>v;F9g=96C_j4; z!4xEgIv*wyVcGOy^&V;OeN#ykGX*`J)$qO1UZLDScwzcP*gsFv;p9=dAp409S0Tjd z(p-ngPB(Zw!7~Gi$S5&q3T~7YY>*KhG(gi2$6sihNr&AFB~w2;-*-o=+%oY5co=hY z7(RTqe}5&z`iUHRysMhb=MrU?j$g!k8;(wja%iNGwQ5NZ;lKJ6{)_jWCMWlvPdxly zsV8M=r?1fFl1O}%d8!f|kt5unH>ue^X|&t3Qwft~r^Y|Fp#}cn-Tlue+LA}i`xBYa zb##&->U}=EYnt<0biUrVnDw#JSG?ohOIPOL74j$#(r7b@gQ40qWRsgzhqku%V*6o> zafUj(?6_c(2;r)oM9CsZeJ7;;X`vCZp`cVCcAK9dh|#4U8HwEl0cRJMvru%(@)nlS z=&ZkiFPrJqr392$Rs0_&eL(w!6g4KnHU}bX6XFy+)bOujOX$C>4>;ULsAPMdi6oLG zd!H7g$e*!HCw{!shwN&b5CR7vv7-e*`v0->3xfw)=MnKcaPNw6cY%nh-fIdu4*}eC ze#gJ4=cM_K8+y3F{-$C(93cL{2@(nzNf{uh2qdDah@pvsA}As#DrzL5USPm5tpZRZ zu!bOtri7{~h>0Q?nwW_yiKxV`kfti2h*}y-ErG2R#YDtQ6;)H1R6IKvnkXp>(gJB~ zG7bQs6r_{_g%=?eCCmI@7wPY@&mIzc?J>?&P1!-(4aH526xm?b+DfRFHd9HZGC@g8 zPQYYpC)%_$QS6VB^xNEX64A%HgGZOLb?GJ{Jf4)IVoW7yph8I@F5g5(`{YL|4M5cM z#^(~y!C(|23NPnY8M=m`(~tQRo#Vd=pQG>wXL}C*JreV_X2!Voa>j@Gry~gO5ry@( z^HiRVSsEwDjb7N{!ELgsqhhTSpRMIIvS0}gVtHxmPen}k2h$HL~hBn44%tT-=gLSGa3)F z>H|T@h{RfIHU#Wp@IY_3_g*EQr=o`r%^lwp;)$#qhL@xjL}YL#Txy&7P?7_z=WJIG z_$6a=b7S7Grt#!q`*NldZP47>1MJJr9+8rUr&iFe$G~tmJ4`qToKXet)^ALCSUb8E zn#bzXX&M7GoY9;~oN(k4Zc+}`gJ?&nis5@ylL5r^k~Sn*eG>}dy9Qqo!Q^UsU6b1wNe{q~`9F6x%t0N<%8p__^qt$h z;EugL9FwF%>-pxGFH9?vRjZ@zZvadz&^*7?MPyp(8<&*P7S6kMF&i$53o{cR3Wxt+sG> zedi;-)>?8$es=J!85nC4VV8Mrtr-g0qD>mKcjN2TG)D=@@iv~v80PGs!#{({cS~(s zD}+LJl0eoZLxU0(NVN!yQ7woG6&sXhH=92KmRnO}tR1`hMJ}fRH3iT}!|;j0F~-l1 zp99sDKjf3g>YrBqhhJmoqE6jXC$@a=y6t^UpG4P9@48uUsU-Um!9Ffe0gF+%f(~Q8 z;wr~Pky|B@4EAB*RVNjt)Bs7t1 zg*rIp%Z__n!Pifv>&EFl>AM1c>4!ed*N1+MwVM*62a5F!<4UHdlE;w)cyZU5RPtDm z`=%-=85$`$ZZQ^ zBnT*6X1Q)R!Bjok*mrZYTsk*cR4k4!;<9NjaS9dN_D+ z^OkIUv4gwko+3vLUqgL&PH99v|XyvlP@|N#7WDQR6Xm)vea)Fh;CB^Q6LX?rPzKgwYKSi$R7DXdPZu zx&wekEHy|01uMDhc6-nGVRFfz26&v(0VoE7ic*q4$ex`{T*5QGQ!PG@@((6 zCv5#b%;h2QMq5t?-s5Eu+Z3AoC>{bRu6ru-2=XVzi}@Q4?n8rged>of1NztGRcrUB zuBxf{%1(BqSCUTiyf1X{+m?XfBp~(WfCKrU7N`c11f)R^kZ4wE8bGM2ppiNeGy*gV ziQB#pSw~xEbgE}eGnN682}`IDbg$g1=>!w+VMdBPo#t15jGdj>3Ab(>;qBWORzfC5 zLC!VO#Ni`YfvUtt>8`E!$AZjZYN(+20;;>OQA9ZXL6uZK9fcG}!(mlXpyr6Y9Jc1S zP3IevP2rSZNVK6SI+96{nq5PO1A*nL!Uu#eLKRUBN+^caNE%V4X<-0%`!AV|b}2ShwR2T&}_@}KC9 znzet`C#p}hk?=@7jzi7sIVkeXBpv))=w&?ENdH9O_olDi@#vi2pkSfaU^WLpMy3Wp z*_7)`$Xq5l(EdC+mFw=IdPNaMxBO{9!K zJe1R(8gUG5gHel!q5!fSOfn2wVPT;dUN3hsdHG|lN;%7iNUvohX(20%BTZ2)c2C6#N z(G*lAsO=uw%vIEN#4i=zMa(v>6qfb8&D092qNQS7gh4kh=-N~yl?fgOwn-#=<<6|m zrgi5l+IT~yx6A4nVm-aHOE&G=i0`MKj{SF9F4it6yNGq^33iV*Lri=?(H1`=cg%YS zUis(f_wn)tc2y{m8&)mEyEZ=*^lJQFUqT-zXD8`S?|BDDC#pYx&nfLBkY_)o;3xZ2 z<_7KGSF!pze~{}v*2b(4C%Ao2$aW1%QlBK03j}&Z`W|)DhfiO}yTdWa$VyCth$BO! zqJW~Jrky(5Ei|E$xlk41=-*q5yoEBY6p50dLrBtzPL$B2pm8cR0iYD24FN(FAxMQ3 zqG%l@3Q#2pKxqvE0YZ%^Gz!p_qLWBcfl7r2g)~wH0BIJLX&MBEDpH~;A{_>eA)=9| zPK_YaAxb9L28&^9L86yzgwQRpX-x~D&?O+%P_&BZDFLJnB2ZEqQB5fl4Fb{!-`@vc zdmzwLN>F>VO${h%3u^(*DTFL2BM>x_tK7S6Vn*9!wF!)LYZ-g+|ABk`pDC#+P3EOJz})i? zNn%~6Fuo7NXu*p*PEiVaK+U4}RVw$p-H}9{**m3pJt1nv)vrh>LzX z{rCJY@vz;xIXq64Z{n2^txbb6M}WC{j_x~~ngS}rHy}C;Gf?lfS!&yAZ|uApGo`H7 zZYvNtD@W%WJ<>@dvC!yAgD01k$Y_Rk zm*BjE$oX<%6p2QH$UvU^_8K!)`ttTr->%mtHe0kL)7-p5RO z1cM+^5aa^1f(;@fdTQAFlMS99vyDG}3 zB|k}AA{8}5goiWrrEt;vNhtp$l|0(Jwq-muD5w09KZ<%AJe(wk?=hDQj|n3#ZW})j zm$-9}X_$wy0+A_NLoUe&QAa7Eq|yOG6-YV-paV(=ou~Ei@FC$Ud+&%N$oU}90q-(2 zRRa0x;p_v<=?V@hCXedR07Bs#WDQ-=C2Zkn=eXrI_<@{?EL zmJ^}X;q|*bCXKOf9T{fXY1Q?h_a;Z6BgwB=sFaedEr^~+W24Eo(QJ8!=Mf0Qc4*`?A&9`q4UD3U;E#E8)1V1tA|0+@9+d#^+VIVqD#@(IB1(jXEL6hi0|9|A1y zKb&(>k=>=9g;iPGj3ATVKKJ5j@SIpu*3v38e#g85ZBh?5 zF=`MBfd-m{*^@S^(H6rD*~eu?Ma5=69&K^E4eBGSW@H|TX$~9zzV@D>1D?16i#vb+ zlgUM7u?|CI2yIOaN>T-PXf~>(UN&5hJnuONSChiXGBHE3L6KenZJ{Vh?3woHXsUW| zT@4eNQ`>S5-(MZHPsP+>(KTww@?qtBnj}ag%X0Y|CwE8DgRs_P+rBP1oEAwGw#Zr} zOEm>jZb=j!{g@7*mKlJdYN<#Hj~!r{oAH)_?I*5c++^B5jv@Xzn1`nx&&F#jr|2NhHfhJ}8;d9z;2yyPC8Xg1C7Fg^_0+W&&JXC8OEn%iY|U|}$d zVc8}Pb=7y6OlIK0L$Y1<06b51f=Z*jjs!-;a~X3QjP3g<_$V@HHPTQFj{(X%jKP@G zFpbvX*fjXZz5({00)bcs8%hPG3amXfA@Bu0DN44I*jQ4^7Rw42$wJCu7Jf>rb3{Z( zg;l`UY1(=KkCO-0?d5WY&n6)t@U9f^H=3Vo>~2lZUB7GJjfc}7%EhYrTi)8i^SWPW zA@{imz&1t`kr0R(oaLxSDQ*nlIBrOwb9opt6Vp1r;<+_Xt6#eLG)H{k#xTj*{`QO- zBD8&iz3Xk!9yaPec+Jryc*i1T{&}Yy2oVSJ6vx;dr$HG*QLr|}O>Lrz3a}W58Q~QE zA>Wm0W-+s3ME>%j45UaaW(}DntR*t`J2HHD!L;7mpDjL@DA7;#a!Xc~DwA_YiPh02 z7)o>%RB=jmXpm@bUe+s;a(g^i@fJwMBc@>ou8xauL@TB<=(U zHe}qEfly{qB7Ka%-F8-q92Fq+_#cwLEI(dxb03*YCvp(cJ4az_a~D5T4;s_*{mlDY zysmq1`W(K2IqFsaOQYc#(;5$T*Tm?tJbbd%pwk(kzu! z06kR`MXDmyC52mBC!0ud(+OEL5K%Op!)&-lEtQ-M(PUtG5(A>Dq6Z7WVe~2>M*X<*xLqL3!yx4<&7ND} zU`@o%ABOjhWB{8Y<3;$)ii@AGJu*azCnsKKEfLN~Oi3q*oqFy~_u)6mt~ktGp=RY` z62zO3fyihHu#Pu&Y?up|Qgx?Ds*8nL(cF|#@Tdavk}dkj)-L7q&XBvRqSv+KglUGB zo^ha&L@8%=2cm-_HWD<)%zt&wd@DdAaE?S+>N^>JQ0&TV9^Z z3sdBs9x8dyXY!Ksw$i-^P7Ge_-ArYsz3gdwdrxWa<=WmCgrjs$*uGb++dSU)wXn@n zc*V&Sdd88ABPONcC%fT#Vyk@Vl;eg|tRn3BMa=Cccghw}Mq(HXvmsEpQlgN4;Q;bF z4J!Ers;IS8P*o)r1S_$erM;KM*F@NZn_C@s0u_{9Ix9PMk1sMQDs|Qc_qt`t(&V$3 zP4>IDakX3(3WPdAN{B;%V%3v4wz~4SblG3-8yh%IjZKoKb;iKKhDTMlD8|)|ilY{) ziZ|!54)H_t^|R%6)YC-~5m9ZqZ@IQ^WK|kX(5aBBs(i=Y?BXA`3BUrXTBcyCmMKt{ zKcH(GS=ua{f<_Olhnli!Jfk^ogL*ltz3T$1D#}VIAgy~&W#=o}@oTjPwo<+Y;36EP{UDOcSf3VDb#PusXaxLHg(`gbGG+AAz)X zhJ2ijDu}fT?yZ-&)c*h~ktryOn!gVJjp**5VEO11XP`a`{6%`rZ5WbBXvA8Ax<}Gv zEJRBrsE11sVzH}&5?F%BFvk99#6*>95ZU={=DM2dwFwG3X(Nne-1xbk0;WVwk0PQxD-KN=V9#J3)wUyM1p^)0 zR3g}sG7}_eCV=^X8Wqs+K1WBWOHLrMPmopGRa2mao*130&gmJ9D`kce>0vGv5urWo%wIKw)9auz=+5)slQBH6W_=P*}n`D9b-SFAjVi)1KY+ z#<8SH=~*0)<>k)toRi-%Cy%^yc2|?->UpK<$$fJ<4|Zl|csVzwTfv<1{BF$dUi>9K zUb@Y$rz5Xqsap~mR)x|S`6X@QZ@WUbc5^U)d+n80-tF96s;Gf!>usJp71t+hGaO%_RBcZ=7%`uwRxmI}$;jp=OP7*_g@5wVZG=9wK zf3aAWsrilfj-(`!rrd{jB1pi@Kn7!A7&q6>IimIq90bB5A|eP#?LF0h7<~;*SETP4 ztxP>10Pv4OOeevQ!rrcdyi01t6)`nbQS+D!=nsSBCLrt~^_lM34=s0Q*|Ho8@yuE% zs-rBHi@;YVUiY)#ad$}3IY(bfS(s-t7|#UgpMkG>x3iIjfcs7ckeb!9My6QWt=S#a z`Wu@%zkh$s@;Q2Wa1amy__dtD-ia8xp2OlMcvRsK+XhxA9c1dXtWSSUZ z=#t{v*!mcH#|+p}^A!R-lw)(5hVx8B7OxDcn!U{vnW9n^5_5W|3DNFJIT84t^OAT> z%noko(C(}pokwxRLqZ(LR}Wv8+Y~wMU*~%~x^i=MtR<3LyY#ND-g%BUlhd;; znvLV{Epprb9}R|dZ8}YjCeBdC#9j0XS9kH*^xCeEFQ8slPNA08_0YDg>)M&wVmjz< z+E)D-NV?rRs?Sp2s}E)7*Jq6Ep87S2tX|K#>uw}G@Wd0O?B5u zHRdr?r3pdn`-j=yJ`sT^o_&s&6)5s+YBuoRy-^>f@BJIUow}#8I}U6$kVz!w(Olam zSTtm+>R@a}vNEGH3J)_u+9{xg?kat<_XtbUyOmDx=Zq73eB?+UW7Kw-Mr7Zx4!3k! zbLwM@;dp2WG|ScDSRZi8U!IDhf`l|0Dr$=1zT^5?oa#mJMId9V6 z5$FJXlpO&1Aatm7w2qN!PK~16`=Q<4TulSl zK2bPU7`Bg*sqxL0b$#jPsXwpHY1KYE{!Z{Azk7XkcWAeN>TJTFlZ$*e4jPjzCKryQ7{K6c8V&%5Q;}W~^=3TI zQgD+ZD(8ufYeEr81w~068mK6su9V5EENUWPiP7|O;mqi8xHe_I$pJ3qn-l^_wBpsn5w3SqKJ>NM-=g>a^+OGN zmXmaROc*($GN~cSt6IA8F<8btC2}-JEg(ZJRI)y4hFM`zQM=E-GuC2!QC~d6hZrB%)dK@&LnFDX zHjJm|H7?e=BU^4MLeb7iTUDZ^7$>e;cNA}%(N$ckKF>bI_K0FW;6X28^*hEb;XfUB zmV1?zTeIhlE>6s_%AIdTVgr~6kTnQGYUTqrz63$jw}^d`ZCpMNk3{}VU+ew(=0rb;m=d#Xsjm8r^$%UFCt>Rtls+L2yWYwuUi+s^MguZYDkxM6VONg(&@?^nt17#$^^$??Z~;GXq8kzIz| zib|8*M2}<)*5f2 zv}QLNXF51&)g2MVg4pv}qJ3qyGc&MHZKQwb(64)1p!`^mAou;-_flTA$ARx1|s zH&gL789KErTB~eQp^*k*n8Ml!(LrRUH#gN-lejzRyA@Ov%GmO9d^Gr7S;iAvY;(^= zcyRClW~_Je0Oj#j{#A!ffBQ#)l#O3ljc-uGj6ZzH2XcK|~#h?IDHq_9}hC`VNkS8EQu;v67R3UiVsm3m?C~2T*1>mdF0DK-iKR+;A zACJ8F;|A~RPm}yQdf_pQN%L&|wIW)H+~n?=aC|!I4~{V2%YUT&!b*Lb@-{XQ!=Z*3 zoZ8x<&_3 zw$a4xBGEIL>7tnM!K8k1pJS&3?Kt7faG>TX?KT|>?THy=8mLl227%;DkWfx*Sh8S&y5XK(y%8E%H6ch)*!UQA8 zsJJAlV8@4nh=BqX@Q66J+SaNVHI1tlj6+dTh%gwyaD6!7A$vz7*CvXp-6ML&7_j!l zrWmVkZic%G zB*mCvKREk*_A>H*u?}iXz|loDRL6PCuLq9Wl-xpi6SRT2>~{w0+)*%BefQ&AX4F+u zX}Vl>CpJzIyLhhY;<|212?Y`aB6UDLTv(@+2((SQT+w;czmCG1xhZaZLjRxh1Z=2Zl`ObQL z?xJU}I`7r^>GpKpQ$o(%EtSCgqr`bNF;#5B`vZ_4gdGOK=J0}~!7@4wG){<*_>y6S zh#II8em=fOQ-qPGpW5K_ISQCWaa+>db|jcJl|le$K(?h9J6Kss^;b@8NvQOO8_jme z#MCy!HlZ7!X@GHBqM?kYQ>0TZD9OfCjc*;^k0k5ldD@bzeQi}&79f3tNtW88NzD>OPgBfg(G%2slhM0Yty3~dBhdFUp7+!D`_~vi z_7*I10%6F28y)jDxI{baBY5zFiZMiCMc^uXb8ks%L?kiZv=0UKNrs<64;RSb8UwY4 zDn@3hnMXnHFh4hrWBrazVg>5Bx_IrRbf}tEtmh^xTWfgVd?^=bGch_FoyURNKH>j3 z;iXj#h{K`h4c8WzCYK5hLF8yXCvr%q*2;fZuIaK*L*UsQ_`+OZnJ z&@tLL+MR=g2cP0OuoW2V3!jv%1N*?bKG5*{IrX@c`!5LdBapmIjkMq_P5%Zm@#LYB zR4&OeQ;cXm%o6ztL1r~saSS64Cvbica5+>{a1#jqX9=>2mt&LY`Fr`Kcyf~ju_7(C zE5`UpH4u%^&BCy=%P^U3dzyLA9u>q%{CQc(mqobgL7=x-Ru~IXzXwu@yt1iaU zL>8f2Y+8%8F|{?!OqVQz5PN_g!}te@#7|irQ+_sQVa-cdnHhwrb7Qo{TZ}rnJ>#Cd z*ynJSjAJ;Qn~rHFsg#}FSsNrYMLDB)W1ChH#DuO*8alpA=G-vzP2CQU1m-y!b!zUd zI>OjtKPc#(x@hXD2yAIpRaPBR6?PeYUXC*D@U|pkhY2LyluGfaoo%H65X4Q!4R$Kh zQiU%1p*l?>9Yi|yEXXnjvH{$BZr5Q4Rpf-Sa1&s7h+%9WHfSu-j82+hPZzZ!ELk(U z5=oz-F}6Mp(Z27^7%d{vj3IV!8{iESBh4~>q>;nw-`;+ld)$>>Q`zx*kM{?&{83+g zPDAuQk2LW6&$QZm%B$G=ZPOUW9|R|us``6=oXy$9!lCM%KIDhUel6Q1ba4JbvSHnU zhOfi%Ou3&#^(sxI3P<)8ORu*5tMcW2CH?qGKw_dIS0MSxIQVWQrtaogK5|4)$vq$0 z``C7UJ{K6jTO72{B4}nfqI4gHD;HFyX+<>5#)QJ8LLiL4$rGA?QTVhT=Er3|N@$|0 zPneJ=^iN5%x!Nr$ZpiB4=Fv7j?Uil&jkUJhaSaw)wb(QweM;B?{}=%0+02kg;8+w4 zDyqJ@--J~D$1PHwf~v%+fTkIZy^oxV3Hjn1tNzJ14{E7~Z1kna^!^KkzqRaI4$ zNhFd^5UW%qc+`pTaS`wa&)dlAvAxv}i&r^;FMzC(~n>L99LR@e_H z0fm(+m?SD)T>zlVUuS#7LM7gl5ZaT9eVM%y}pKk4-&p*P49TdPwN2 z(O&YPh@gdfk9p6BLO&pN6NmYonz~497A;zm(x{(nFNy|-yIe1u;i|10vTc+>uWGn~ z?IWNLuUzHx-+S*o_Vx+5_&z#xZvQ0qi1XH~2;C|l5~2Oe2%cKZXL=Gd7UI0zQlm9}w*8X7*O#e9pD*Kg-y0LLA`%~wSo5R?X>tK6L3AsT5q5@PI zg$hQIB0_@M0+vEO+x;&H^~b*Z?!`4GnCh>BPbrDn-Xb;5$y4_asWwND*Ixtn4;k8n^A`P3{B6c+b6v_VGXv!w=c46}-Gv7vBok;Xd38fpm!t+iZL#jNIjmT54@yUoX1$X%6T5isZh4W24sM&Z#X;85L?UwVET^AB{4Tk+P(O za4HfW={7KDdo5~Y_mWl`Jee6cVLiL^H3Ym{$gnnWakn|B%GOKnl$oCRZW9un^Uu8O_q6v6Am4cn_}9o5ez&A6jwoI2NyNg zq1tt5h0zF=p(Pn;7~_Sa3`v%SWQXJT`_F(oJ3b4g$_QZT0rW|O0YK_iT!9@(`45C7 zLI;wRg$gttNC!f+v?p!R(gguSN}K`wC-%YWjiMaK8n_{ZDO@KyR~T1 z3?F1Aax{C~J1FFPFnoOd3S~7tEEX)58JL%Su<9pZ#693>j74~WB$K`n`P3&=Dy2z0 zHeh9eSQ7_k85I*nh+@)&XsMjrR|{464H#z&S`09fDU_7{U48c6>ih58eJ{m6VfnL@ z=%{_9nx<2#NZ)SI1ko>d!yu zY$9UG7_h}!A@qEmx_Vt?htO)|IC4s0!l_Gb=KjLPgqjdZk z=hVM;3}Z}Z7eck+*!|o5$>JI)D)<6qps;-GIkc&5jiE}XsccSS^z|<$5;Dr5fnK}g z?Bl%>_h883OEnv!x;Gd)qYZADQ+aoety)n!jGWuAj4S?STEH;{KWp2n{3 zPPNw(L0fEFH60OkKyXY+qZf*rNUa&c`F>c_s!F3yv_UNmHp8f^Sd&E-)NQq(T_%8w z!_x`#u?}*QQ1+)9y{;(Dsi4u8`r09bpzVq{=M*8t9G`cDVt6=}Ow^LNB{Z7yC?XhR zyB2h)j~3ZYsZ3KLU8$x*(%7I@q<}UBffu%cwE!@InG9`-G1$l~7%&q*Zpu;>>&u1gy ziVP_meJY&-G@?+yaDYT8(hAU;M4)I8p``~%X#mn14JZ@{282pcDWC#`XcCa53J`Px zX$=dZ8WBr^yx0RR!oEsShmyJhsuw~4QYM0d29&lzp-KZvJ@df9N}+p~Btd+yIBeoJ z>AP-(vTKP_fEODYBu$@4HVrSz+0l)xW_T}=>VX~b)yc;}8aixJ>z=jTVy0$CSWz2c zqGH>w>>Y6wYo+2bcE-KtL%$k_h2FKiS+fnytv$oLd3eqj}Zmltit+X|^ zW{c!`J>j_6>rUGRG(ntqarRt(Tce4H>{cl{bsTlNn%HIzt1YuuqisuVr>7PR z$C?;jxROLiI6BN}Wki^wWMfcCw#k;;Y|N=`2J526($5!0@kH%D>X zG%Z7Fw^->*Xkyhdis@W!O-z#O1*UA&syL-}u@bHwuH5mpOhjVUQ6(BW8tFG0I*DxZ z<~?BW(;H|mjcOTnl)F|ozLxVqVmxVbX53OSa?=fNv^FqXR^i$iDT`9Iifg-$3s$J^ z>TSEM^@F2P5mAkz(ba855M(6b*yA1AqqgES@whnMtQ^!S;ZrI|Q9)6$hz+uD3!TBx zbzLE9195h_9GgPLMAQr;v!-B*)~%sj z&9*M3+azZgw$epUSnXqLXAu>|>MqvSf+8ncdTp4V>i`u*c5xXtHq=d^?`AA*nu;ll z&8fR??v61kAbkiQfdlP(%mgwrMfUk~AF^3D+aq&>)T89vfy+K>Q+U+_#P$b&F$2Q{ zBI~pS&EdiDS0Fh6#l`7ye(!~|mY<&bk9(n9CxfQnfY|jCzSh#Q5Ri5bnI{hL%*f+7 zhX>f`^$i2X4ML1ONh4bqWmcMCa(zzYii=Iv?Y+IyL(3mWu^84y}x#&xg^@E zs=$LP$|9<&zN?Y#arOyDILyq<%)~@Qlk}fzN|d6ONf4xU9aF*6mX81&VRh9ayc~Cf zI_vO|csv~^u@(kLB8RHg4ioJ>H;U6F{IQH%g@vn&j!Ck*Ckm>n56F59S)Y&M5ggMc z%x_lUTLdae6fij-erulasloSH2Yeh3@Qi`qh%jmpId2`?0F z!!=Z?LFt?a5)+IGX(u+0QBS8+mfbJ$Km01H%Cah%Xw@W93IsloVg2C4g9Z--xT0cW zQ4~ofL`ibX>SR9`w@t-KB#}5jIfK&qy#G#nHO8(an^1z($4=PBKJB|UBSxoHK|OZS zl&R6OVsnzqCWhrbx7g7-KWp$b6OqBOj&|TfC#2?9gjaDrcy6eHzVRFt48`hvJ~_~* z$yrvn>gmbXGdRmb;F=)oBdwBHaDC(PkCC&_<;CJ#!D|Omle8N~r)f3Ur!YO|(jKjz z&u6&NU8i?GudBZoRVd8U6%;`cRK&E=R8>qXNKp_pfk;&pQ%y9|5WYyF=~9GfT0o%! zfhi~`N)-)S(%SFwD}S?^w~ibz@q>Aw`Di{tzI@z$ePH4rX(>^KAT%Sk^PRg&xU zH#Kr_$?)6goSW6I#t`V_aMj6ks}hxp#8tzw{9;7>dTLJsoF@)Sm;jTZ+HXIX)KNe}Kf^>Q%D6SqFJ?$S( zH*TKbk7-4!{BFX4{X;&PTs_lmiKaM@3oDAy@_W*oO;UY1da^ZhMTGNapbgG+h~QN+ikTF zP{~fl7gMNRF~h_;k1$@q<{ZaMAi~n9v{69B5dl$DQB_MoG^GJRQnU$FA|Xfx2(?Q> zp-7a76rj*3w5m`8OH`DN6oAsDC`8jqO+rv513^hkR3%bSG>b}5g#$vZ2vUJUAxZ&7 zB_%Y3P*FrcMAH)!Nf1Oq3Z+VwRIs`yHjRw7MsF=~b1_fhV~gHp+V>q=7I`N%>6p*M z^Y!?vQ*1mqWwzZ$?h5Y-8!AoHyE!b*6D4PAQ!CZ(XB|vxmv!9scDk<#*wIqrOM>Rl z4#RV^TW)wuFK%~nx05@ zQq`n%GLFeUzCBU9X2|G@q8t`S46I2sayoL<(duBt?s>9xP20TFK@tE$l|mK*s77iE zi7gdjRxLqOoQ*W^ax`*ONYxmr`w|F@ais>J!(1jYQM?XK7un$NeUidK$-;PQ`8=UD zP53ozq&G|%R;;E>!ePTM&z|!vOfAPl{1uOn=+E-G9bt3F7zXdLhz1%6t0AnanV>lB z2#(QJ6GgU#O;S_n=^#g)!n_$2-=O$`2<%ZEtd5JulR)z7EGy_9kL5u{c0n>QkVQ=- zkW@ht==wFtdo$T-*&mlaMEaT-bbe2_(73_u{+IvY!vd0iM@G!O2eH{+AAy8v6Yy-K z11TCmD!=O=HU-v&7w&% zNteId+f!0W(Xr00Zk}$ejEzvJ!Zec$C0Az#hjZ{{$?*O@U8<$dahSDRIcvX@13Ake z=~$?97>ILBlNpNUZipnPF7L89IxJ}+KWc1){T)up*X5Qa#u)CNPT}f%liRt>?%_RC z2|8)ME-;d2+o{pZWOOEnH&8SoQ2Z;Y>+*7Zr8)P08u{?%aK5x!Us3-8Na1~G&uYmX z9C5vr>TZ1X>7H|fw{yqI%%{|+e2M9Ku0BtXVXPNq+oo;N!?Ga@0a9d$&kDtmRL1wH z*APXN(>2~bCeUuW@^s;Bh_*C>+L>wBrgz(eafP&BOJyr|V}(Hg6qN%-QL6>1peQAb zzMDk_w^X^l7SDR&wozkCxkqyjuiFXhrnq-KO%vT>ZIu8O)F1Vhw}*F_;hh(ql5En1>Z8eGPAaA z-W}aVi7Mve(nra5&O~5pz7<@cKSdsWI#v<-M)86N#fb1S^J1)R0OlqIzK#9uJ3I*=qWn=;{F#P;L*lT7nmS`kdb&K6txqT#C$+4gd zRm0QW%v?(wyw6(_N?#`yX&y<$?~{3Z)>0(M#99H8iWsxqDm~3hyjyG z+X4g&5;TWxl3UV7NikJXQA8YtPa)yLBD&f<>Yh_@9bv}|GdVh?*_UY(d*G-682~ zaGneNAca(e<)^Z^Y^bPw-eV>qk%yEd9Vqb)k1aYQ#_^0uD8D0}bvGhd>nAveN8oCH zFhYD!*nb2iqZ5Q5+4KJ|D`-9qNDd3HH3-HUCyMh&+hwg?QDvPCZ$Q}jHG_|vS{Y0 z`VGSb=sNdud>oQYB-w-bl4Ni&Xu$NGx{7Gr!~V(p|j(y;T<$n?ogYs$LrxZLS&k>6(|2Ue>p-zClVy{(MtOc24b5*9#M@?MoFLsr-*=nfhA4pK*RuK7@7uv3^h;GQyQ3us0^9_0000001_eu zXcI(}${I+?kYP0SG#;jCPeKg=w!3Wh5C9lr5C~s;XY0fN@BGRS*u($_`v33MI}AcV zg`*ot01vP6e~0+}e>3xbKgvhrw8o4MY11_~HTqaqqq#7eXXO|Wd#C|eOGI~+??;|Q?j z8Wy(-cu>yprIc!bhD(_DjM|tq61Mi4;d#0OE6DSLBaIJTT5691fnLT#8#=-AR+0r3 z*xFz@WV%sw36)Agu@&V5RL_G<5z)!73zG*&tnZlS&k^2`w#ZJD5u!OL#44ptS!C8N zw&G)XVu+7N2XY8QWU~>g8(Vlg7D!&pOPhJTL2-qvp6;7;=}i=+rdm0rJk7iiw}KD( zEuTDbeP?$JkD@d3c%6f^pu&wwO(7u!QvKgo)%QooGX!5a=M(rl5+U4_?hD8&h4DM~ z=vgN5q&laPL<{lZnD`}NWXOCK2fZqsDCilMmy%S~mx&Vt!Y|Nf%F7Uzk+rR5o%gD+ zBC>sCrF5N;pK|27Dv;PSzL9ErFdCBP19os}LynPpDdu_b&_YOM1vCtZIct3rovh@; zc*qCSa_bxy0R*k`IH$wS3N7sK!Mbw#P8^?Q=7Ho zXTzy@TaYOY8{Ol^U^I5Ekn%A@@kr#qaT6#E;}A3;zXBk1*RH{+bvDRZ6`LPvpC z;qYi&2dErWdG6_MLmUm#st=>#%B0C_LoIeK$@OHTltm!&v>hT<`F)R=nP%U|zi#f> z`1bdt?wohp`?(34RJnwM+<$jj?P|kWQjPup%xmd-^UvhruNl92Ua-?A`nfh_#x9AK z>=`09D)@smXUxe-EA=Co|bkdDPyUO*!5IZl;pGCUMqcTE!3;1H5ykeZ4TIuHxZO1 zJjv@k>X+!}xZy^kbiwphA<-#O%*eSU*<>Kn<>;Ej>jW%^TJDI=6S=$wOK#$-iNen2 zbGkNCY;&>)6X8Zh{dy4jS$h{_bNnvc#@NnZbF5kHM@A0jo(nkjEI{zPTfR=`n&HUV z4`s7ub&p5h_nm`uwm4iEu^51toG~dYTM_PEB(y?ExjsqAh<>6*io;(xJo7GHL(yRH zn`rA6>JVF~ChbjK@~SPa^@`bSf)b1JS@flXAWrvICxLmUDjB$YOcZp64IfpCU?niT8Z83{$ba8Ce=|57&#_0>4byt+K zA7_VZ@nzb_9qg*^>9PMQPS1~F~453=vQ)ju$u3n*Pl~iNGe!W;@`rP&7x31 zUKF8RBsafD8nH%__p`(lYqZ;WwK?9jq{nopTIY=H?Vs)Z-)_(L2_O)@^dtfSq?k6t z>|#O$Bi(?I2`}aRp(*$KI{hJY$DgG>T*<&(jV_beOs|STnBHShR75qI z(Sc2EB0sw$r@*84{14uSf&`uz6{f}O>5C`YgGi4wiZ__IXgnk_G_~IoC8j-Suj$s| zzY(E&Z5LHn<7MM>Sv0=df76$s{YebjUy1-wUTU_l4k_b^qyUK|eg@G&9LsVv53V3n zH<_85W^|xaMl>$gHZpB;43&lDQ3sLBHcMhmT zIfS=h4C!y3D?+p0;*t2|Dj%*}5!V;Z){{Gpy;Yh)e$xn1Z zUj*L}s?Z;{Ij0#fn$}v___hgk&G2IPM#P7Yfs60FyAoruE;aWIaehFm;y9Ur z!$AmvQbBUZ$qut5Z#bQ?tA}Ay0^S?R!;lcAkP!gJ3xqbkwH~&SufEp+L6vB-14Ffi zTa%~~5+np*moV6dlp*A^Xi?} z1xcMX<~hFS72rjZ3L-%}ClzCE+Qnx^ZAw(^&GVMaG}_U;ozStrna4-Dmg+pui&VVe z=xj|hm{A?+S5@zv?x6a)n1EAG7nT_m1_7o><{*ltK$5Yb^Y5n{#O|`eopI2&w|Mcj z4{tNJfz668hPh|UH^N~2Z)Id@TTD@R)&Ffe?)oo9P6LO-LB9390Q$0^u@sxz+Z4sD zkRjV+?e_dV1>hs?3j9V(Zvl8nf!o#rV60p^f;zb7(3c~dH2XZfW$Z{jf#&LGQ=y*NhQHHJ{hCv66 zpvvleabaEgq-e@EL_{>iL*f@+!NzP)k6U7vqdle?R~hjWBd)#a8Hly%?5IP^SgZli zG0$VScE-~hElldm^}DnQi-vL;4v^rMfRG6QsFzwPZDtg)A;nTJkXF;-=r;LNdJBq% z{9d%5qE^hS_j=o@D$Fv_SaKsDM;`3R+Pn}m+pda+o<4*i3+9y~;4{iW62C-4o?VREjCgGKdigd$=jt@IVS)N=LTsr3f7IFs8tCz&@f2%i22h=rda*9 zvB|#&tgy(#2I}g|jo*T^mBvuYtOy|wd_qhDf^Qc|a@9B~BHh}t^JFxqNChlHV@Ytp z;ZeMw8&PwG1lSOo)1=JUmwe#@lf$SAg&-k7LBR+bD#VJ;7ny?V(I{rl(7lL~ExGEk z!jp^AaRlv9AKuO*EL)GB02nGfy=pT4+kA570hRW$k3RZem&Sd{(q4Q4V`ZE$3@Jkj zVe33c*LBdsx+|`uawwQ-W_@C{`o|lV31OfPKGKssCG0E!4mgb0bCG+2FOFPYfdoGU z7UJ+Ny{~V=Cr4Gm@l5k!ShO#&i+32U>e5p?n=0eW50f1hPYf%?2n5bBGKIzE#b_P_ zN7TzwY+gl7{fZpR`1=-zQ#PiSx1msG8AZ$2tbLp@j2J2nuGjiy*|HDYY4aCmteK{3 zlMRuGMp~vR_u8maQWF}BM(q;Y5!%uVcF zj8>FJfsslHGi^&1?YS?{QM=$jS`aJi;ytXrrPuHZ*zZZ>}h0tT@5& z>Q6-YVaBnTis5{dL7&aV zRUT{kX^;nf`@bz_O4Jp8c(pG%!9wIz8E(*t>OT!j9y@v4)i+`%-jpt7Jr!MhDB>?P zVMA!c2Dn#l-IS4QRaN?n2>OdKdq-;I+~-jJ_!t|;sECM>s)AvdXQ@68{>4GFnr<(~ zstgDZmzC#%08B$iAqBJ%kc?IbitHv+d~}62-Fq5ArJy-pcnIG)u8flEyheN4l%Tl; zfvKI`%p#~Z?7}~34%!xdQhRr-4H?VG3^tkF{7+$-)98oG@Sgp>bRVfGqm15 zx(B;PF;LA(C~LPJ&zeX+!`W|8X*OsM4D5bJzAF;hvQckc!E1dIW17kA;>F}O!lkv6 zj_-zJ=U;5+vIaxMRkwp@>&M0I#qXg5Zxd2%L|W6MY3F&kToKOJs>tmR_{gzr8*nXs zrxvGtpNi>%j0ZFfPvr?i(H+ExqGeSa8lVTo*a~Lk+=Mr;7&RwRr2fX73t{i#X48Xc z_BPzD_&!7yse`4! zW5A#j8G;FC7LrB)Il^kwRW-<2!XS$G$7B;ThBFn3~wAz!r@*62j7{j;iBr3_LM6bf@4^Fjh~GT zc;cS@9N|OB(5TqBh~O6$b-TU|iNaoQJ`uAhEKQ&prn4+i=XUJQC0+u}hpYV2?R7O2 zxu@?Z_u=ij;vn^B#QNI1??F}0UW!!aqJVYBlRDi7IB5jSK3~HXRxZ>+(4qRhWXdvG z@c}5^)=)esY`F~gnR5;nJA>-{UfkgJV(E(fz?3j~meJFs1sN4je!Dh+~P~42_ZTJ!6 zyXN`^xBb%C_D73E;Dkqhw)$lG+$*bwX>tuXC(=g5DpNh5%1Y3+IY-0#QSIcC?P8d1300x+;L)=~qjSFH##jf++dXPGJB zs^5E{(zci)@{K31wY(5g7cNV9z-vHAqe4J+G!w-QD2GT%RhFjriUr~V?1^Y?2oy*I zH)=yW6nUHr0)$q}!q5nqhp4ktv2DoM8a2_c6QqfxbggGcG8b_WYgbZ8D2tgf62gYy zfe9pm3K(ob3E5M`GR^B-I5QAZ@S)0TLKu&S$~UwpCBi{M=ZLP2rXOO98zBlP^wl$6 zOh93~G!`2s)v3cUHkiDG3rc{wFnRk_TxLb^$LgSQk-yxD14fp z7H2}kl2CNsPSmsjFttmZa)ThX;do$VYAemwp(>gft=biql4^ms5X07?BTUxKgEtp( zL;s#DOLJx!0}sm!Wh62IEj6yDj#VcWSFJ&wCLqJw95I=QR46!19}{xll8WZo?>dtN zxs(jEEoM>$tTcnLg&Br8vD)29*@swJP*bC0r35ZRTKDque=F*jRAF zRn;Vny-qjU+6CA>wl7*#nQ)A{8P+7RZ6HP&S66ZZO2_~qiG9jYxHdZliG3RD#xESE zI*nFL84?sNEHy8OD?b$AD?=*4%t*LWJI`wjts{4rb5bO{ovz-GKE=7)b$PunT_mRc zPdJSqNS#!V#^tfY^q zMQJ?isIHbtRQJZ-G>bb~Wd0!5BH=j9_(-~&-@?$hw9;8upgLV*cgK6fc5NhlUxroK z01rEbTMLnn%nJ(^S|!{HVIEZLc{#V44CMrKtyxx0jii*EAW4}e7K&yYp;nABWmW~N z&LMkR5PrCdK5e00{;laQ9l)}eYVf^aPgTB+38d?-ti$J_id{4=P8LS!i@^^~^~E5p zUBYd#6m6d-lJzjg1{#Dmn-dr@uw$>rnbMm+9W55N^P^fAi8pVPOvb9y#kV@w;!fNbEP_`O8b@wyN)jT1KrKW}mA3jxVM|2Q0-a$l5b=4!%tHWmD}lHKt>Tw7RkcgdlWP{l6iVZtBHKYa(+KBgv=WmFE zgdHJ4Ct)1j-rD>zB-)o+C)&PjFJP|8;qjxVSA_VV*C}2Qg&trX7{8WhZ-=j|5}sZY zGQH^<)bvdKW!)(&XxDvfTPG~jma55C?As!Qs$ zubwA3_F3H36gV_(gf_sa+8a@zAOIV^anE2iHf?t54x?t8)ik=qCUSbWy`niEG-_P? zyaQL(tloz2FnBX(wv&ynt=*xb*?0${&Q(oPYp^{Iy={*=Y<8!sjCQ^5_Z+#w>3cUf z07mry4SOD8?u6UZfocGKxIWGEw(4c}R=Ia>tG>sh*SFhg9@XoK%hh!B zqbt$g)f3wW03C;E;rFjS&Acu(%|nU0@ajo6}^-&w#9 zDHNjU3`C%M05wVnzC+=++rIOxx@b3Xz2Wzb>uq0I?`RJC_V?;rX{0Ffu9vkM!YJ{jdr6pg>RLg*5~H5TW?**MI`G03VKD z>VyyDgdQb!l@3ti1m1tLLog_9BDAP)8K3mVAQ$k${0*8cv ze#9bgKlYH~1l|y#4MmJ79rBMU6!DZ#%P1!BjVdACBi}0VBJ+_pg#T6NDr!wnWGVY{ zpR`D7O`!u9OKEceQUObuKW=hJc|a%j$mUM{vHSVMnbC4P&s*)&n^Yn7t`1j_j01sZd6+t+V1VVuU ziBuMmP$^KMM4*8CV$#QX{bC=_|LwLxR0Hoq#0THf2Hm<5RP-v3=JkJ8xgK`}kaLi- zBuGf{Blckkh=bmlh9a4nfNxT6?^^!G@}5)6ulu|dx0luF_SQek+b{1c@BeT9pZLGS z`=bYs`=HU`>*4hOY@7SPxymkx>tF7}NG|fd<4d_j&r9j7pn+$MI}=7$!&+M@R)e}x zQNP#L%+bEDp4mfv=k4nk%1M6TpVv1$v*WkVEY)$GNByVGjBGJ)k5G!?2hwiR!Nkp0JGEDtm%HFE{rt-xro& zmxIIf?)QzNkhCWG#?AY@3fLWiip;BIPEiHt-e2hfom2$UAsk~2hZ zBq9k#VFIY4EVsqh3s?kH1-e-$vfyIt2cbf+N=oTX+)@#dkr5CyG1!5U#9u9!S8j5^ z+<^e8nZV{`REUku%*Yl(AXGwm76Rd8a>$ud53L>t5(Xi}MZ{!GkrD?%$&zxSDM(FB z%z=TK0>p_HF)m!fYYL`y%1?6S$hK;e#Mr>JRxV{%#Rh9)j<$0$4~bE%6Ek8(j5ULD zPG({`JV_cSv7{}c&J8l=1ji;!_MXF2b2EXD0Tw@bi5THU$_Im?&K!$6+4D(qfxyEd zEV=)9lf>W_khf$kOG7i6fyBtbfgsGt(8#e;MrBKrGbCbWbs3i=T!37Okcpjxkna~9 zfr*&pO@`+}1`90{=hk(ev)*_P;$=POhSqXD;T;SMO>Zoc-Stbg@FG7I&X3no+0_o2 z!?ZOhSdmdwp(2kG1P*-(9F|KO9Y<~1l2{v)5dua=#-`=jwp*DFPXYwV5;7t?RmiN% zw)+s>=t!vC!sVay2-dO$-hqIGj!dL~$Zi%#ovUHaMA=3J@zS2ZDv* zWq`JOh>;+v5~c;aL~%2$3K7-#5x_*mLP`)dS!HN-Rm_#_@gus*HYO7=2+T(8vqu+s zlB&E(t{ol+52Q0GVg*)wUHB}Z5YtE+$iQ-fCSXCJ%QxoGT3Fdov57&)j*&EoxxRup z5($woFfiD_>Rsbvr%p2A$>L1RFgF}3awJ^Zg^3n^s3*p=0dDvbLLTqH-PTWnSv^aS zg4n5B5gg?8SSFIKp8)7sbCE+W)>YjrxnUV7nzQM0My3R`WoLQ_n41Ne3M`{>1k9c* z12ZCqrEN-?kut(jf_h?VXlO&A34Lr_rNMXK12SQAGYKUJDq=u}ASI1VN?;2Yxrs2j ziG-F9x?4Gzjc(@4LzB{vnT%mT%!8;pg0>IZEK)l>o+JDvQg>ZZGF_6+4w6Ddgz0kp z2py*;i!QgH5g4qpXM#bVJ?z4H*qLfu!##nD8zHZMq@Jk9_N5YR1p%SVX?6@%yaxn^2p&q zYWaxhNHHQ@+?M797KXeO3nU@La?Q@14F>S7WTN85=B`L+7Yh?2iJXoP6Mf7FEI^?1 zjEWu-CMPn6WX`+LS-5gWs8@R~C5VzaB266i6(5P2fm3j)VnhoI5+Mr;?{bC9mM&P4 z0>j*kMm81RaA%Sk5s&RK*d>L;X@J0CS}_0Srj!ULKYwxhUUg4%i^rbI$R#< zLGDz*fM8g;fvHj=E@EszEaD(kMDFXD>kfFA#&oaa_2P z9C-^^J;)dmvUy+$#93vsPC;X%xTa=eP`P(foRX8Zra+leW`zvOlPqFBB8MnYxvSt* zp%#l>OxSt|&1P7kj%0~0nXO>j+aZ`)y-WutU_?fvm>QHUOwi24%&CduJ4{SU9i?(K zE_E0fkc(a_kTX%b@pzIuC1j}Q6}hOcLmn1h6Cj#v>e2_nb#$|o%Jq>@!YA@ zM8uhaA~_*R;z`zzvRt_~u?emM%*F9I2%zQ$gbd1%CUPznIGULV*r`&)&Lx5+glIs- zMNEu{6EY@H%*eSiCj!KT7!Wy*L`K9-jz%w|=-HPJ?aofDIV;&+)yeiacyd*GwQ&Gps-pgoM zS!V5;u@k81a5d&po`g(|PZ=XqL@XaSTH(|pV+EHGZxWc!v2Q<{Sa7*Jzcq7^@ewiJ znXYiChZdqXQdQz`GKiD5LKVdCLlWjiOh}oT6gU_ZGBPnNVSy7PN5V<#L&>NmwtePG zy{ZVI*RoK$d9E=_b2C#TQbkLclqyCdSaC6!B~BzlxtNkNDoN5s5|v96H_ZuNODi#U zx_QE5y3Q(4M97($65u06JeF`Os9zESPZd~nOBboBGQ^~?c_jy#0%XZab-A*p6oB}c z6((vTf-svZJjoF?9HFz95bsjP=7onaEDmZ+H4!pIjSgo5aWORK*>udvB;*%IMjxWE)Sv5sUssYCo>5M&TsW*4XXmmPqZ4MsjCTPQzCX{ z$=sO}aT21PhY==MS`@R;=@g|Dr2L05DkCDsL{6g{FB9@fbl`l~tIprSG<~n`U=Wwp z$D(Gc7?1ZeF1tg)33yFmt@#F6;LyL-E}@b>t8vXrfHnTmbCI1P_ZZw?3;;+s!buiN#< z;r8^>l&m2N*0rrEO|Hysc}eek{vOVIdFYgSrPcQNd-mVGru*-lci(%rM`MLDo)}>) zFrT)CDN0hDxz@F>IZL0)5RNH)z7*>1@$~s}_xLzRuwO6t|9&&t`(?*kUrpn_amQSt zi{ook9}MFh{CZ=TetBVNPg-9}{U)QVJU&(HN5u!dH<>{=j^xluyiDQlOhPVq;F+Uh zcMh$@IZ8t5NtQ3DR7TIyzmiw;J0IJBrjkEMc&?8~JfR9l7s^-4Tz=%)X*nvT5NE=R z4`cGwod-Ee|j!48mhG~PM);5(9D`JDT!qFQ= z{S{0?R)R2KM9}FGvLkmTqZOjBM*@BzGq0?O-&-e`^fbMm&m@N0sIf&*R;2O$%MK$^ z(x$(iP;|StZ-n2DdkBwEMR%UaXGPb)J5PNj7$}^{Qk5ksB#U&^7llEbb6sNeEX{F zSoCiDda&9d+Ju27>-{)EgTuppcZQbrzTEfAofc^9U4IC`(`FApWD-jp`#rJC!g{vf z9}^%Bx^?&+yZUd1rC+iq2t z-ec0;L3XVC=&b(s<#;hTW%A2aX|L#VfAEY}n9A5XRGcH2OSYA&wfRfGWBNJHXYaPT zc*QULu@5nS^x%}b-%IJcCS8V$3$_SErB`=!t*esKPv>)r)@y3EI#jBU?kdDDri`Xf z!GXqq5F2Py?fqEnA(GL7-bW_5)h4(r{JqM>#BG~v{z3`r06I-F%S=L%xJXw{Jf9~o9=$tdhGd zVcJFy!Q$@g>oL(hbNp9|evjattEPqs0i91ieX1G0+=xiJ4~8)qt{zi#Hx%yZAVHy& znh+wLv^|14`ES?P*ITv&fRZfYEP)7U(VM^?+`tlt4b4N)d#JoSJz2eJ$Y1{z3JFsEc_lY}Z=gMoMZVCX?_^0HJ$q$=4ZA^Ste z<^50&BZX7xNQuz^P+pkm+`4~{R64r4ydP|MtdXX!&_I^1IQ$el0iC+06ZxgTF!1-7 zN32om`GC{Gc91NAen;X2#YT`c6-P%xaZ|3kqLP{@=yNm`O({cc4w`DTlorBhMbean z2OcJ*-mv{LcNc~0#1`WCWURGBlE5no)5$x+{6e~ zQd43{st|z@zwNRt4?lm$d%i4m<;pQN#YpyoXl;3E@{Nd~bqiVT$|%gwl;K5=io&X$ zaM1}g1zLbO#!xlmB$k%R9jr+hs20T%krIIrr33X6gP{R52!#k}XtUX zBS?WtRu=?E6))|;&r65#S6+Dibk>|+wXT`Sct~k9Cutmg9HIC~Ju6Cu<{bd<2airM zFX+5{^VC9<(+Ns#v=mZRRWwsf$~xNyBxoq43Tk9^%LlgF@iDR!&yX5a_E!2@g-T_5 z1JF)g4Jk-teZGmMW5!@G;-w;LB9bAZf{JNqrD!Xo5lA$MQi%`^6s2!Ck)5sg0C$MllDT%Qhwz9^h(i4Im` zwWABx)2k8N0_IaN1n+IF?;Bc;)hNv1HpwDJq`ava{)8PtQV-X&^rkA$hC{bSi73Y{ z9lB7|tt(d109D(zwWdI9R;+G}=|EzM zap4o4K(!zoP)Teg6ar!dQiV=i@x2p_XhAlF1lmP+Apl()^yCAW%q}6M97wJp3IW8p zEJ_A0e{bQgzC35)&*a~(U5?yu2V?FO@@WG@(z+F5N?ohcNg$6t!Db<}Jav?dyAvwV zlMqCOUK>*X3wplT7=$7=YZ*gS*KM^bs8^{o80sPs)JYbsx}^FWEkxn*iwMbOI0`>s z-#sHa^*M(q=2l6NnT9iVGn5pg9y|TK(k(Y9l3@vi_g9?YBt;#K6RISqIGD3Msfk0Q zrD8|pUl}wpRS8QCNK;HeQ13B(ejKLp$(!ThT_E}J9CyBVDn&y|q3pZcdz=6iheGLT zN*0x+5Tyz<(v+YEfr`bT=ngvG;||*uR>GcC`29H+Pp5;vhEJ3xx_3fU1!nwspDgBI zIs47y&)~Z)9z=B*bU=4Us$O3GWTx&TWSBx>Cd|B|;?*_n#spP*7Kl80q4$ioTrCIB z7?BOr`7Wv=+ekUgN;H;REc-8px3>|{wbK<#*iacgOIi~6+ospw@%wwsuiKqW<*&n+-DOo3^&k=|iYiLKFQk{U zxYEUmDj2+5>XFdIsZOu1oOe3LXj6}W@7>OJIv5beVkD4(A>`wzA(F3!QCbIV1|cB1 zSMLqHC`x=dAmerR>)eu}FjYxgXGo`JC-yggNqoA*B}oE6)f^~Y(juV04m?pc1oJN| zv{rfeAkx9o6{?ewjAIxO+<2#C!ryLw-Dj9G5!lM_%cV)B70g(?pgv8ZCAh}f6d5AKX9dlo3pj`DFC zW7W@>ieZvs^bur6A=+sBm0*OZNYz@gx*yLZNed&8xlJs_eKvg- z;#`fkw^}h`;?lojB8bT6$^BRQSLx5c@9(|N>iwPI!`))`R}=D$75n5)b&n1ze}B?y z>#m_kBW=-!bDUw zX39~uLqtLqs=Z@ZD2-#bejm0NwIq4hICXnj6*Lx@sQXoIx4*{XM>)HHVmIz}iioQ= z;rc`qe{sCgCyG zBLuODRwEM?T5B?>X(Se@=6T!Iw1rt3luLGl^-RM7EE9^kGTDm}GU7rUaw_|6+HRV( z?d0;@N8kI>blP1yp@N|$+>+eo$fzw&bMyZH+ndCdHPRxeyG%>;72lKdcP>EARIiu? z+6;~%M>sK6cKKp>5<*0Oqy&g1LKRi|Y5_kaADRI_dKA{M0sImP{PD;5u&O@7FR+iy zk3bLeqyzghD;%sNiU#%}wM2i?!5FaCq=^4y3jSD6&j@Nz51zz|>H#`Jk7T372#;(b z|5#J9bV`R137A*#|85ZTXvU*+QnAKfpNNtp!oB_cq9r9>SF0*DTVK)R72M2GzB z5Rc7B0U0AqNP+-Sbjf~So)=?wK6CDsi0TTdEk&LdY{@bQm#v351%5uS-6NRlXsLF4ZI6$nWc z59A?}OphD7O%&<>;d$oUJ_MQySB}Pu;03^B;rQa50%#to(zr1=x@6p3m@Qs$Ia3^A z&k@&?;}mz!cebrUiX~nV*W!V(kQn*XKp_SeqniEqveNu z>|!TDo_H0_*AbJrUX>7Jfl~)9TBlKrox7;17bzDO*nKCNPrWWyRaIU_Ddkl@Sl4+i z!Ztfjee2zOc)jzE+))s4BgE zL$s}~qw-83pJVq$zP~6w&zXhuVSp1sDWX&IJK_JK`#GeMf{{u*^rkP8cE`T15Alw5S2E# zRZMv=iEQ`)%sS_wGt`|s`Xlzu_;1;?z5*<_c35xtnLC2A&|4OeMvu8XlH zO0;Xx^40dJI|a~ZCf{*!4e@UXFjmbav6Bq&rM~p4s=t_c%a;1xwtK=}@)%z9d%FtP z8Mn2jg&Sh7knn(Kz2YT_Jo|WiNhwnCB$RzVd@SC2KN@}LuG{70IO85ieVIN56h`uc z%xU&cjw8MZK&K*9E+1(#dZsq<>Gzl0f>g`XA#3v2kWb@V?|Bqx`+DZNeB@H<;P{ii zm>;i4lgcU4swj%4PpmpF-u5nW)6!|f##HJ>kD|+uEA47L=Z~ApZju|>a;M?*zY>>W zlt#Pm=jG&eWE8OtQV@j@F(j*zsLn2S?8oSZ`(Ck{j3HfZwMCtfMKWV#lJ4cGHBdt- z8*GTowF_ZxC(p99qKS`G|JZ_Wj_WB=IKF^O{ ztx`gg=WGwr-O8iKw>4gtkKzw==ZD4A9)A$s)8$V3`0;U3Ut8Zjig$W(EZxey_B5@Q z7qTswvTY~idNa}V+l$?Cy%P7elzs){N6YT^dsmSigEs!PL<}0(!9Ju_|GH2FpPT{y z5OxtGztjf&@WKA0#6GQAv1p+-Y|yGAKU$t_o`l;f3v@E z7{M?$AecQCr|J8tGKMq#C6izEg$T#HEbs=*U(Zc0D9*=@JfQ4P#eY;eEWfIn*I(Zq z_*lt7K~-CfEB=3<^538N40gu%(otz)+io5B$NDxWInHyQf7Gj5(wy(xTPs@FcJlUK zCWleJ7-5AW)uCGud|^pjmL2|-Z(QFKJLk)nI`UjD)q{w=<9pt_)=q76cssnK7()y& zt{6@;o6d8~-F!@N&0~wpCyZfAA>>L~_mul5KT~sF@L)XSFz|y6&187(Erzq3_6`Z- z{rdiM&Ho7^4o*cmknGGb8Xc$dJMad`VcVbeeP#CX7Ci2K#282Jmzoll5Js;rUMaoR85kNCb$9?tA+6>udRVo88^Y-A&Ei%H2)oWtorg9`50| z)!de@?k26b?O$XoIrR4R>)>)Z(g8#Sd8HjRzR~Aw{s*1SG_!R@nbRbt)KVamp8mKq zaa0hHB*rHJoM`vuftM5eNm^0lmi)PLh7E>5I!nlm)C9sp6FbJ?a~BBL3^0XcU5_~9 zxUf(V$!a71o~c4#+E-(NEev32zCJIi;oxqDtJL)_Crt{IomBL5$hXg*Jipe#)8IOW z5OfdlE?)P&Y6(!Q!3^~)Syrz`DDE@PQkwkppMfGOf^f+5oZT8Kt5z9dg>+!*sm;?3nkuwxhaxlw5fKQ1iP%V> zJ8(hayb7JAFhY*PlBO(Jr1GaOHdrlp^n|t+T!rtz0J~fWa9i!F;lnO~9 zFO|P|-9K=S<6*>PI~jsF;M$u-h!t{F%qAL?9GL;bhx%XP2v8(`QwC^?4hX1hG_wf! z#z_Crv|u2Rz@;p z)h9P5%?%i+z^bZklPz1b8gg`fUTi*Xk^i+vMUl{9%COA(IwM2LwyCnatYO`C+Gb_0 zTYE4ga;%Y>@?_naHfxr2f7IGb-FIi%&m&b~UXLf*)m72sht*kCSYyius?l1#@OvwF zhFM7SuQWZ23=zVmY3lZ6==5?C!BWG0Sa8D3G=oKhVaOIZ6hw205+Q1{n-Ojt+nDU| z3)4o2CSDmeXq%&}47zzVXz=Y2!LE(kMCZj$+N*O6O6Kog&5_xY!w!uRuySz3jowT* zPYTrQjktGp30o*%}iM%*<_rz z=Z2GRHk&J+9!$C@vvw0j9*#^R;j@LCf7Hvb!S2HjCij~S8w|RnzJi1qLGrDsO}5)^ zQW4{hn8pnWokpXXFf(&GGLNYpH|2LQW+;acjG@8>gb2Gc0s#IPCZh0tGEJStCzZ#gkc5Y^eIM!Zy*#WiS90XO0^)qi|V&jd#>l}wri4Yu_O-u-qB^C_s5a_t_ zEE=VlMp>B z)>kRE+ilZ0Y(CRYQN1Icfcc2{5J>1i-<8g0MMmOt95Oirph*8qe?RkoALkeK|CEva z%zv->RQ~!4`+u|gssRu9|9!vL|2t1i&;9@K&{?x<0(uMoW@G+V|BUSLcApXlF`9FQ zsd&Vx9pU}#%-3Sj2Vk(w!I0O|1K&1g|5Gy;GRp%Vh}ZsK?drznLwd~1vj_O+*_P{; z9bHrZ8Q1)5JUi^qeyEVcv)h<^I&(z?{*m68n-f5)p{ohfn z_8g78j!V3hgW|<=W;SVD87)g=HZ^!^KZGM7t_qHpG4)XL#Xgi>Z{9+EO?$##PHL z40yv|q-d&h-R*2!7L<PFA;dtDLS?<> z@GMk;bN1j!z5|T-y;u>Y%dRBNY}Hj*byuS?+fE+H z=)+3E3}S~vEJ7@2d?!LKv?Dta(Ug0T@Mwo3#@CgnKYy}~0;xkNvtpAA;>$3iJ*!n; zf$oF!9_u|`&TnQN%re=8S4WA?%(+Ep)-s$a`PC|!q{OFZ4@UTPbXT#Lx!L5|qsggy zBy823$p+r+x$|kGhFY*BT-@EDBH(T&AA6X&9^YBQ%D(uoFy63}<} zkvNeoW@ucgb5^ZfoH{%@I2tvcYMd#;wLJz}a$Q40y16hLu&fmup<1gcyDUsTPhT+o z<&>t)hpN7bPKJjkhb|&+ZqBV*#%yWray}aNWss zCo^{H(bu!Iom~%u6S~fhs^cx$PV8Z;87dlmbzO)Mx9vJCWEO;M<rVWGK+I&+dR@K)}v-Cr&?ICe0&Ra+)(;f@ZD&19d=^Ra|-Sqw#p-p5yWCL4D; z9Tk;f7*fnIam3NHQ+8htQQzV7%gyB7E9Uf9yfUN7e7vM;%XN7hzHgI5&DmIU{|EnO zj}A_b?(#>*Sp%fiyJu5(xlFKX)uZ1=469`}-S6Pw^=f%_lMKBu*;?v5svTQ3W*XvR zSEJ<9n^T35nUNP9bZA^bsE8UGnpbODan|ihl9M^oUUb^p@!c_>I`hPdhaPz7>(EZe zRcB^Vp~%}ti6do6zE=@~So&uT4HbjS#B(wssk>w%g$Hrd8HtOT%`Jv8G??Zil}e$o z&z^X+1A(D|2}!UIlYU-<;4={SdHugXH{K|p#s{#h|1;uIfsW>8W8ON)>|P&NcwR7+ z^!mz?AsKwsEoeno=Q|38q)jtpRjtTbpwb8tIskfG^-Q%t2pyk^7HkWnQ)bz&+~Qzt zQMESWABRpROtLwW%MfW}G_dCICa`YG7&Az{4$JW`hXIB%W?+Z-V}`?K>kC7!d2xDY zRxq7htsx6vkkK$DO&BW*vkcA2nV5zdOAowoGoR`D?KyQOFbiJXsW?))($f@GCn<4e z44qKpT_bt$o)Vb}^I&~4jiTA^K+U6LiH8>~^>5qE)XBdyohb)VZ1UE?mfo zQf8;kpeANyTx2)fR@jm8_%%F!gbCZX#uO~Ob;Nqi&T9Yh(1dEuOm>ZfK5-4$Ll{3woZ}f}?B+0ofpW{h5t|fL@HaTmo z=Q=dh#&LrTFz3E!!!IX>j6N?@Mp_e$c8RLmOZ(^Nd;K3%)8>#w9lL|jA68@6Me_JR zwY$Bz186V|WLh6mUoBdNqft}YcH%!iez?QXk5l?x`(rpir@Oxc8kdmXB245AT(RUZ zCSWE*`3m2s zb1a`1Gph_bKapLGtFzVM@@1l{&q;-B`Lsyk=k$6sTHRBHB4Wz2ay~yEhsou)e~HcR z+4J|_s|wwel}VOeI%?HbRpsI`%Vq+w!@3>LPVHK=jP0b+qYSChI`~hM(sDfY!N!f6 zm7>0GZ%>m{)ZrQ{D&1IR?9qmfO7!$-%N4sUHdY@8qefad%~mF2sq4|l$6gyeQE)7> z$RQe8qzn+xUaJc#t-9Dk1HHeVKwv<{7b!>~8WW&!CQL=B1da@ZIOkaAhNVdnCSqK) zel+M1-N)UY3M67MSWJFwnWu5u#2tp+rx!MX0;KFzDg}gx3nsQ3A0yKhJlrQH8Pcmm zMzzMys>Y2v<*Po)Hx#Pf^vmg#!?vupc4ctGrUyn}M#h>|Vb-rvtLEL8&0jtzS6?_l z9yTi>4oMUiA{=n9VB<(FLzx4zrQ}GVftf{mr<<1M0tGg^c+?uIcu=VwIICE?xt#EMHEGrTU3`0dQLKtkjy7PyM7S*0& zfjPGA&IZ$I4c=@65-cXl4B(3sBo0u^lU#u#8`>p^9ky#x%9RKmy{=C}F*w9woVqjZ z>uj1kJ2j4sJC$BePF6Sxu54VnIWvD5i;0d2eogK7d!WatbK~ni-oL?F50A}$gufcc8S6i^ra~YL4fu+iHVgzmWizYMX2eBct)wSz|8Ti4vnkxZ@-c z8{B%&L5U&;Bnp%wcY4oDGH%twbirA}3g2lwo4YjKte$Rej$@>%w5sMQ(NM~zRu*EF zf-O++3lkIAVqB^I0f^x*0>OAc=(Z02FBEVyM|7;-pj_R?$NyfO+G-|^}j6B$R zWvh3F?&j`0et_qk_JjC4i3Ggfcl5JU&o5Lgc-UT`_O&K;^@unE5Wg|bViC$jh(X#v zGED%Bi^10L|10{NIAr{+7=JhA{G@#aB`hCv@;>Gq-f1AhsXeQIOEAG^7?>>sXb>^7u@v5d%*@jh;+QU|Ha^|rx%DgH0#&HTB!XcwHMhu>gjvw1O zsM-OGi7Mh=y<#W#u5CV-{)^f(4Wd}`z(9Uz{~Lw z1Wb^8hjP+BgOV#dpC>*>SUrn~-xF`4_(tdCW>Tgl#t{->nUSe8IWuHj6-WeiHY{hY zik41BwV26tYmPB0s@+$69T%{(#osy=)(nr`gt2Z zO5vhm@odqjF7K8w@WQGUvt~)^kgiSUC06Hkcy7ZJ;HHwMjhN<~HB_A2HD#7r6_yiD zs>?5SuTKq0-4jQ9!ya7PL^fquW4duWD=Ljtc5KSB=90OqD<(WUF*k7*^$xJ2+ugHE9yR>~>-mgV?@i=rn<7^mBvgGK(Xr!v-!GV@p%;?Jv z+ncZ+GZ%IGSoTkk05skN$&!sUgH7f;KlciL(YJeXO{gnCfN3 zyd6)J=xwq%GG{JL9Z3kdSg9lkiCVP5-G;j!-wwT}CL6)?=yN{5f6wnD4>9I62-_p( zQXU3sdCfL#2*N~7nX4mwThZ|DKJg@e|M0k_rh%jI6$B-IhoZVQ8pc?Q6efLT9NE2lV0U zc6z(IJG(IH#~-1Elk&x5IFmA&&KQpD#|ayjE?m%Q5*%>IaoN2>42lmDV>r%0*x1@Z zkZLN1rLlH$?V2q{YO*FK9Ca|g4->r7^Bwr)WJ!+3V_MOrjM?#g9#hFx zT%@%ysNr&>C1(`Vewl)) zh&B-V3>bu8));+tQb<`3s6~k1b>_GxijIyLYONK}=FG#R6GSytU@-_0;nQQPKFg{Y zuZz9Q3ziV{AA}E=`PvpKcrLG-abKLn|TItF9P$V8YD3RlA2* z2V={3vqzk+8FHTo4r=b*Jk`b+N+YI*Ad4Af%r|oY-NP~XdHue>$^SWd)K7oo@0YFN z`MLK3KF`+-vCRH}*B`6=+FuddM?OO{9JJs@nx7Hn#~45E9vQ@s^DuyN3Z_rb>@YTr z&pYUGjidh_I~$$ z1E)_%a``#xJ!{eGBuxN~W25!c5v7OjhLa5qgc18}8T}c`g60NrvKuLejI;L(f+tF} z?V`>WBSbmxi2?!<^nl`O6Z%pyS%L#9+QW!OVFw~+IReH(Gvr7+E+3Lq-8@FLFr(Uxgu5@WJLD~dPMCvq42oNF7jrtgBY+TsH`wIgwF)wiV z9Xc+D?vaRSXp8f5`R`ApYT-+wJ!IA@q;C-}d5cY6EZvDIbvg z=^I8F$`2$jr9p#mDb8BI2ANWW0;XfEPDUWzx$NZ=rC}>Tv)u0PY$P2A_I9sF@f>^llg1-KNJlW_}d_? zK+Iz-LH%Q`G{Xow{<90MAMFtit4C0BkpxC?ltLXSTP+CDjFec7rg8#Q=mZ!rLlrv0 z5C$O-r%0wkAGATkFv86k#8}HA(P3bUg;?1HF(2J79uQs}FolS+G7yJCBpG8F2NHZ= zy7S5Qa>kqiz6e`>B8n!Wni7@}K!*1p4}(l4SiAg-l_>&^NH@&-5x^4&7EC)<3z1T) zN}{Y<&J~k1M0Y`>MhqHbsE;Z8^1V73Eg8Zm>8*+C^=-1PuQ#K~*(7x;$>{NAxJNrx zYPlcQtz0-ZaIbZqtiP$26nd)i&Q_TzMporDR*CR>`biu%d>r15wwt(W?yo0yiQP`Z z`m8&>96kJMoIjW1$h?&~({>Z^%7S795ffmGN+5T zv%TW+yiZ4K!0tUKjDdel1IS3gtvx4@q4^UD8arHr4or7%;c_sD+WFzKBP@o&6(l@} zAdE*MueE2H=_)`)M>V;2yv+?tm^o7-Wl9-Lfq>PtR4wVl7`o2WKZOP)88zll46vNl zit<0Ws^bk9PuG|0jSbqc9ax?=dpTWR8aQz1_A=d~rpz#TyLOI^T$pU(y0DoomCfkO zXSCtF-G&Vt9EUMRECW`C$Tc@IFf=%rU5haxU^yb~8EC}+7o)7vTNq;uw@fr{@_W4( zMT-9H|9mbWL~Q~|gHt}ju{R`Gl*u^6h<5&lECMwX9Sw<{W0N;TMr<%? zm^9f>P7cQj8j#pRHVx|*9*tVhR*zQ8PMKv~ZJk|Mdp+KbSW$@41`J{FY0(QT>}7~7 zqi{n4v|u%8t{gRLo3~+EFlync!B!QbCq(2fuLBGnSyYZ6aq>K$aquy!j$M|pit5A7 zOqJ-bc3mvF<=ekKCepV$5V{<*T4mh1YnaWM77RehjR_Pa(G;u8b*yF0(ZlM}8$ONG z(c#09qq2&kto_x|?DBVM^ZDiE=J`4}Jl&l7szo7~bcA|a>G&Qt^?484z~7g!_(o6d zPX|?ps$|b)Wj+6N{cqv>PvmodL#{k4U(6%k$v)d8g;9k7e(gy7_K73rFawH!HX(Iv zMx}@oM14}|Abwa}Nd4&-X&8X`sA3{Oq*F*3pV?G|Pq@rV@gc4uKC<{@AmR^TSfABM z;&_lE1LCJ21Y?U;K@g-#B%*C#lR*L)=Z==SV{GF=57nLiGm-UV`jF;lV@8m(eB^(S z)~5OlJDd_sB$7!bkrBX_rUe=n9h#)igv%YmJB|mqsZ-WwW$Q74BNB&D*|6kF@F+=u zGCH(5oIP4~MjEHd>ghg8*-v(?wrImwYYSsu=#t5=g&z{Us`7+IfLW5Z7)4;~B^N+KO9?+0fV)+Z8diipUO zsEU#}nFS0a?m2t24s;Q$$xO_n2BIuXoEVVVnHSLogw0A*ISe{9oS3mVZ+2KnVPX;-Sb00J;e~1CyTh}u4jmkpX=aZ$a*})&P7Yib zpz#i8GoN9}0S(q9Xs}UUz$l@b%Gb%v2AfUs38?zt~&J0{k%*P{* zFD+i!Zpo-n+m#1v79d%|*N(DVIz3hub!^A8(Z6>Q)Y#|Qj#m>%p@Fz)Bh(&N^ZeNG zLI z?A-hOI}VWb4l&v`+!h>;_}sc)V(e}aE>w$m^dBy~ant8r0uB;cAta=p0uE9zGd8U4 zpfN7n8SB#sytv9;zk~|WFi;L#b#a(@hMrkAeM~bqMrw1*Dvv@LU6lz3X_-c0nTw1w zR{c9>%z!}gwE#juy}$8B1I6EKag)-DId2*&nBB{rMJ?LhQ9Zta2XG0I>|jT|4B|rg zpE3;?{u{5rz`%Mbb2Eu?Xzb)H#DiGP@bfE(8&yA*zM_ zet)z3Jj0oHzz+TV?gSCwBM^z!SMyjg$6@Nbx9rCclNO%F2&ND=GGtxanMrh19 za5O=5W_uE0unNa3V&=-X)B=*xvu`j~Lpp_O_$IyHX=t%_Av#?6fyD|KKhYQkn_Vs9(> zFv}|HJUKj=b75Il9`1fk(yNLy2 zbZ>fQbjA+LJ%fW7$yTVZyu!=6--MN6@jgYLSTeqIN3&k8irwVdhYwu2p9jT*EISCm zwH_M{AK9x|>8o+%L8W3Lv3A(j{)VCk=B9gL?+u(Qz)dwoR*%c&B3zw?G0Gf`NQDy!pfFa6 zZbVUtfiT7Q_9uE^g2A6c`#H{IxIv#zB0SYzgJ@w5L!ts zNo*rOsam@^IC9o^Y~nETYtf`In3*D_34rAY5Q;I63t7Gd#@w-S7Ym4vYV~$>e-fEDb93YY2mv^HjKF)7-3l&gx9Y9fdh>&z=R?>V#MS~ZG>kt zHXA)iycm%pFkzrH2tlD+a)uao>kQ{ErAX_#p9pFZeyfw>eE-d6FrnA?x zX14dsNIi9i-L-mW9Bovy>9#qNyz|>RUrce8xGZ$a^T#~Y<6IQ=ODZ+U<1FO*V38df zO{G#WY#JPq7Q0Vmh&7uySj5Ikl)BOJB}zK4Cws3aGgUn&AAOi=u_OVGC%?y-X8MaDm6pS}U7)4Fu)GbtswD41HxUKg>zWKfj=KVHEbtmHaJ==!Mga6f@ zTB@~Ln=N>#RUz_7teUwb)U>RTo@z}eQGFa=x$SB;EnIcC1xK@0x!UOq6*)8DkzAU~ zgR4Fg%TiL4yU4L{n;GF?cXo;N9)_OA79FVRB_I96wJyHzr7HU^@#^jMZYR2IR@AjC@#y|&-OH0QxAKx8#E}QwG>*P|>i$^%hbcz9joVVP zU{4ZyIUh*PU8y-v3oQR^=wixL&5RgkIC0{DGyTBWeq&FAVss4;VU+SF!AyCV&KNUt zBh{(D;@NB=nY1rxvoJxJ4w=V??v3j|@<;dc(pP#s;_mhR)!|vnfykFG`(Ze^zpoz5_0Raw51=;&R!WJLc zjO=y&Sy+s%FwwFO&Y@*Tz<^$*P>+>lN+XsDRJI}{BBC6qjv%&?uxEh~>{VgQmx_`S z6mC*zHLm8EZ`^FFKMWK4;+^zEcpntF9E(^?J|VxxswW-FS)WxICo9lU3*u3k0MwBb@E8l{;v z4FV&(UIiJ;l_u3FT*0?ZVgjk;uNTC;n!0%NV;k=w=P4%(B6WGJ3mX_53zH%_fQvEl z@O;l7(Yzi(*)*BFk@9)Hu|Eb*dD*=0Og@n$VEBO4ad$msq&=SV(>zMM)P=JYZbwNH z)7H$*O_V3?au`ENN*Q3UYEs3by^(w11zrf94UH$5&9!sGOe4Y=QCPDYN8gOHW?+^T zl-G;=O4MVt1;of@8x@0hH&GF;c`PnB8&~lQKCL3!Xn1^B3!v3k)Y;8oJ494CPHk9 zjzI|he~EGOBz&SR2zn4-V;Q3zA^V?TkArXLz=l4Jo^0U}+C;=7U28II;~Enj#4sF^ z1BM*8((<7@6x8_^iS)hxY!@*GCjFchh!Bw40E8g(VHhf^sa;ul-)uFT=+U%jY`}0u z%t^Vhm@?+KI zZw&XhLs77Z=B_x1nIcge5|#`^5w*WFVb%jQ5Wr$zdvK~hU{pwC)UwI=RwFLC1Z9rp0K(_$xu9LbJH z!{Z&_ppjPOeLNlyD+hPe`(J4X@F1`O`~TPd2k{I1pT&Uxr||8gXvgyBd_T?k|310? zV^{RNWZ-%2g>|3&@vr5_^KY;DT(#E83Z28tARGllMKnrp#>{EEI0kMo9C>Y;g!zy%?0F_!)Cb(4#4*gFzR;#ZiM8@@nu-C{D%DSEd@lv(i??sN zfArt2EmGjQ$JZkq3Kou|Lh=W4q#a)@UQXJ~fgFii+ESFcyzr$S_!${WIVe=l4;ezQ zgq2LNeJ4EUd$co|D9WZ0juJDY$?1mr63XsTJnCl(VMQyEgbPLKW^(W3y3dWC|1669 zzPv-mZsulIdb{xtCyzYb=Z>xSxi<4Q$KO!)-m6=^;nt@lNl!bRUOVd1^zri7XF7f( z?KDq0I#ZU8m7Y1(^w!PejV_! z2a(GKQAM%wbw|-d_+k2&x_g!eqr=8Ejhxp=pwMynLLI`7sb*DhuS)QOE3TZ#>d`$l z7P4eM@YhRwVSUJza>m)z3zn)RcG#-j4wbO3dKQS+e8D*j)%8eyk`Vm|B;(FGV;5Vt zTG2GAQWmGIbcB*sSn!4@*xMSRHqN!ggj#m%A!aUe=A?IiS^woh&IvFtyj{}XzQ&BWk9gE2vkL+k6PGu!@w)Nm>j4zsqN70_*- zLCF8X%!+WNbPa%GVRu4hc=$sdycL^uw?n*MoHw;(#FC`UfsA{RI18ug1IzZ<^ zR`16kP?=OAxuDjfB$1kvgY4=G<5>h(0lq;vN zcJtl7JYQgbJ;*&F@Tt+F*hbxsli~wQBTC|3 z4^U}G(e_S&J%siVPLdIY4*>Ibg?ZO`=H7R@ml3N_4uv%Vi9|61Zy=hTyuqhW#ic=^ zN&qPl=|MV1N({m#=HhLz8&!;MY%ZVfo49wJS$esjXV$HbPx~KE89ja315Re(1lKp2Bzwxwvv&3kVAEBC4_= z2^0dVumY@#ganqB#VXluNXPJQ$`9{}6Jdi{D}hrdquKLBCeDwO{?AQ*mi=?Uw!<&S zj^4`I%h+UlNDXV%XjAAp1a3b!W;*RP`Y|U%k0=!(2*o#fMIL)A(V+=>6Ka4;+oPWe z7^w1s*0f_&Z9Uc(l(-L@W4|tl4!{j@lDX`l@i>{vI=UMHvZ0aJBeOki-Nh&nG2Mj( z%m_3IN~b9iFjFe`@CMmV&byhUMB^oZBTEN6A`LXb5Z1(-*#^`>qcQcsF|euhAyEUP zzPVA)*UiNp;$&W)3%_JDtk69Bdu{qv@y|FV>SYBISg{Y^L0nN*}8rm z$5`ta{_U7X%Ab}<)=1`(8Z>oaM!Nm&AN2hHovTFpJyYG#@Y{^YPNa2B6OsF|q1n{Q z;jq`0kHYW4?jpguao$@MfU=A}5Tp%7(aPZ>g ziGkdCTMzJePNEk!JU)h3K#*gOpdKT{T=oS|nA`&b2TS%WK{fUc`QeZCr`$++^#&t! z8uGW5yAH=6rDYaTB?pVjP(DMRD)lW_P|`aF=LDcNh8shQN=L|VDX-~XJAZ%Cp1pYb zVTJNZc5qXtrq$Z4Q7c+25tweLm|fz1UfUY#Ox%ib_jq&%_P;0OJdc6+pO}<8t3%BI z<1v=YIeylxZMG>IGwIJ)Y#BO7UX0k*c%rf>#8!cHRRP=sV*}AQ@Rz2SnSM|Cz zbx(_|p9jlsN90YA{Mv3x8>?cW2qBpt$RtCvRN*&-9YHsy+zX6`H$WsFINNVFWyU^b zMlN?7U%oMx!o37Rg?L7NOU7pF_xe`a{L4D!CfJ+m?RLvkgxes(^D<*IteYnD8ale2 zcQE2>v}+$$IUGb>ZYdj(kVDV7{uB7h`-B=Do{ozC4+@enb34EMKjf3*dY?P`uOpGd zpA%hmKbUw1F%DWYv%5L09pA`v4_L+~MUH|lG8@jx-d7PKbra-|y(hsOKT3TY56X{& zoAk6eJ)OSRYu)f@`P2fG?LHt*(R4Tn58A{qMF}BJhs}hTc70fVhne*r_exOA6!v#l z#P>yd$6)=ThwX`=_VL$oBXU9b5*)5WiPNOH50IR0@Ogq}2iARo!izXlbfBwbfQad$ z2AF|U$~da^y*TAN-L`T-wfOiLJAs_V4DMx zHVN?x9%^`3u_g3h+6SFIlY_DD^hqR8e`3Yv*1SC}viD?pS8>>-FEsi7*0Vj@U}CZ-}vqG~ZKq$!H1A{K^{ zi(qR-F;OuR#Z^@16%P)^CW;C|w1Apg%!7a^1t}!}p+(S&lI!(8*XV7do*m@+tg+5i zO_@Q|8w#2*DdNG~X)2;v*-a*t$ps}XI{}fXpK8$2N3uRk({FLiOGh5+4IW;}*QA() z@_JHYP}L->tgag5ku#la~bf&Dt1t7^5c8GJ7pYev6nO%xFH#s0{}qBNg%FofEN##R0zG(|DG8o{AhhGtcJW| zP|W7kE2GkGY<8G85ji3Y-JESEM(M|QLbF)?T5TghW|NvTi8GEIf=$a{_c?pW^^sfN zAX*hvPOP$KWW!))`!2Jz91_eJ zam%jy)Fd6Fk?sz7;@Iy*7uD)%hEZG~C}0c*1Oak>O}w85XRvutODpPtp(4@{v_M)5 zWI{<~swoC_wG};(oi$~E11rsV~p`(JM3J&QB29F&#X(zj8$)gfT zlvE^WGCK2G_v8C-W^vRT9o^1FGV5)e9iMT?@3oekk>8!XD@H~d#F%B?TWdx_wrG<^ ztsVILb{z@8^A7iS%s9tGw0{nMgTd|^qL|=FPSQvk#E5WWLa7#^5ov}=h6IX@$}=0y zpMgs)sj=1$-Tfk$Q-B(a@mlHk#Ne3YXUk8C>dGJTN#pfTvwp*`vGmZry@HRPd~Z#? zfFIFtbL_@^ zJMwEd(JCN#uTaM-RWm#+dI%dvOxnPysbWKlVxobOqLe8?B7&6!nyIL-5i>JtRH)bm zcS>P7+#T#tp)d=PAa(GhSjYE=Wkn@V4qaB1-OVRAFK&G=2kh3vyPcAA0*4YnNDfPN zpxKu!8W|8EGeM#1!Sjv|zbJS~Ih^TwICyaLmTY|SgS+XTB1a8hQ+;<%X+%w4K~G(O zKjOkkXnYzV^ExV@r69Z>GyD9gfD+Ymt zm>iW4CnU>s@8{-@5+p?EgLGV}Nb*n($0!-T0}Su(HhYELE{cunOePRTRTqf;u_5Gl zqYt;VfsPUIBi-dXuJ@-B9%oJ`f@R^0N-oApySm<~gOVLZG}%h|wGi7Bn);|70w}I~ zD)I?ZiZx>X2E)6M;N2f`q0T`4%kWie@lRbVj+hkZW<_{O+IEHRo%O~*+(<;}#sNCO zxVDLGLM@0xYGM_dMvy8hXe3UAO#qDoqJ941`(+;UeiEs^%x|UxNF^^ogQb3wtE3Q5 zroxRBc{<%yKQ516>?prxc8d15RTD)NG&CKecutK}HHaFlL~feu-+Xv1#uloI4{#Ow zzM_b6_y$!__&W+HkA}jkqnsV_(>OW$4-S*`kEP!k?bbW=?VYoWYM7n9gM)K((VD>n zye~o(Q4Go|8e3!yDAKgBj8$PLf&A650L)U;|w99NMR2q93HLT1vGqL z8T!sFw1m5m<~!d5zhnayPbAZntw7gPXOW-4cp<1GYNc zs&PbW2xI~rwj43EHN{Z|@zH3Lsp$r)I@Zw?R3)hG9<`XOsOyMc72ZY6Hmwwv^}Nm0 z3aX-|VqAnlH!kSfR3w!N9s^q>l0ETrt23#cc;$MY2z0jjeM1aKuUVy=cI`xW)6XY< zd#x917ZhE@I`V|OM~#rv9}qM|&jXswK^9&4&h-UVH&s+5Dk&~4!rV)7bn9%i(uO5*P!-|lwsse33T0X; z6H0{*BT6MYQ$mh`#Hi2)fKr4s1qe`uA{0`IpmdZeK$Il`q%;Tx3N)b5D?(O^O(9AJ zDij(N(MS{lq*_&^Xc8EyN{FP0bQ&~XkpVm2`m1CBgeY|Vf`FNl#4u!x=s zCFu~&BNNf??+%ZN`+WW0h<#qKwO)uvqsi*>SJ?cI2-K}oqj%c=M8NY`%xyQZX`)6A z3Xadc!?U||^Fzb(ztuK5$q%R3?UrV{)T!Ii7L{Ti3^1FNGOr-WB4lxh#0?~>_b%HQ zk+#__LSr2o#$Nlr^2>&hno3i7sZMY=Jj4=Mmubu|gYeogV$PG4LY|N_XuZ`+z3%s9 zQ73jz>0S>=TCsI&(h4~nmMA$eK-4f9o6FhoU!wb_3KSTzqhN%)hD1iSHVnxg0_EyE zxbALf2&)X-fc1#Hj_u-Ts)v`Ea2hkJGa0cMK;W$(oNV`!Nga-dLQEMvytYn&_#HvQ zqwi!8CKXCiX+k9u75at&2~W0nR}bEzIuVQTUV!u;CMFR^Fjxvv2i1Hs&T(I8#X`@W=Qok3biiA!})~G!#3A8_F;wgwiS)AFnleJHkI+FDi|a^fPkyK ztCIkqYirVpvH_gh)cbl|z*#oX8y8*e>~zPVNHPTx4j>hz5NQz;)mLzAE2E*LRaNfl z>`&hIeFvm`%fozejN>OUMPDMn2K}x6IT|}MnHdv9+&ML9bT>vy+0CfRks^7;QpfMM zDi*}Ds<4lmdm>E8gzjq+PKHQDddgY5D$1uNKS^976*WVIhco!nxM=-^lz*B^o^4&* zGM*ZgQ~pSw)}DsXCkY|D%w@wP!br=TgLCNi`a_(1jA0LK1tL;5W(pOu}kbYJ;_7FKEyyu zK}VCHFl<;_5Tx=?4#IT#vU%g@IMzInXmlD=$PEe_0MXKDLX;Zv0P+<&T`8eT0)%vi zk)oPHn$l=Af#+_NbOlufEf7JI*lx*<65v7+5O~mjXeRo)RP{*=G))!|^Y6#J#?gZs z)^yfGO&em|Ix@|&)2r=4?wKBd zk0!lhqEbq*wjy~Qj*lkWMX}}^oJ1qZgc4}zc621sFxjvad>y`VZal{80%U z)>m748~LjtWQrwifCrNb0>4)@F6y{)Q8IYvEt6IXb!kWsP=JtlBB%kQ3MP(51RN0h zRKe8K-Fd)MiA+tg_|fY8JZKuI-mk>jj*TWT$L3+=mEEPDg;S)_gh&Vw+Mf(y-9$%W z$8_#8NKP*dWC^}de~SE)TdAi~e1O;xb&@8gs3ZB*UTAdbE*Sk4N7_jbc>ZIK?LQ+S z;+3eR`H8afK&)H)F#ZCwN{9>7-r5pT&`E0 z+&>Iz<#roXM^?r$2b{Eq`+vgs99uq+PBBy4csqQz(?t9oVTVN3t0T#W zmF{SfAdfA}-S&we`xZ-eGBvRU;K#?re6-luqPBeN*%}y>Ytd;);9`M(OJvBkw!4Ya~^YIbz<4AjACC5IHKKbTTXV^W@EY zZu5ZkXCbU@c?Z5Ux?l2EtmDr2b6ae#%nT+GOgkeuN>VQK35?trD0WM}pa+TWut`*R zk-&)9j$d*R;~!9X{%=!` z1PFuo%46sUY0yScl%VE?d1^%z6@Y~3yBv}Ende$rjBMDEKeVVrDH00VgJwx92~53? z%%3hWZ8x^3&rhw&G*kWVNovxiQf_F`I=Upo2~L6{1Chy5j2xK%0x1jQ)8hHFpKbWZ zXALLaOhXmBl%5o|i;Q7NFrNoE(rq+!#=?2HVMw-HYROudN4iwPGGUaJOp%9DwN_}q zP5;u{ZMNIwU&$nrU+hs{^}5YwU>t;X#mPH?0nM2=C85D3i4*ZM|83b?Byd!N)8c;> zepr5gYm@d0T74l7C&>GYy)y66$KtMkSNnbGlT}(W?s!I^o)|%+^ma2us^g%^S2$FN zo=?jyS`9I|`mf(Ay^+rUWbGUhMKo$M%4I)nbL)AeI zx*{MijbRo=We8Jj;KUbpW1qi;WlKxvN+|SEjNE zqP)(|fzLv8Q?3N>_u?b>L$Ux*Y1lUI#yEkY#x!mWCoK%^+ zrj8u5n2z=an#)>a2|Z-33+J67cU48NYsU!F4J|z5K_ZA!&gu_EDHr1}o4VXm?t8YS z&|te+i#{~Ti__nCXkIrwrRO%-ncYG7m*U#;_E1`%3DMzG&U$|mUUu47py|Pj*?TFB zwAZzbFJ7mq?Rdpbgm9E@iQ5;-^_yp#-uAW`s!tfXB9B;LgMx z+Su#35Uir<(OKK9d3ljZQ?9Ttz0)pEmnEFKZ?)aKjjG_NR3Xv|R7P8kR;-!Dwbzxq zrpo_l*xAB#YHV_L`lvYw=Z=-AQYm7EQx>XE`s& zRC0QSOodfbe@cc}8;G2J~}P zd)5V1Rg{!aL0a~l%g$G|;@4^oZb^2NNlBA(iNTTP)Um*GI}MlE9Dx&Y`Y?sI#I-w1 zAfL0-1nTIRJcBEa1|`h{+`!Zz42e-3-O*$@qrwi8K{UBeQrUZrPwoP#62zh^YWwr< zSQ(ALdSD6MzzoLh8wpL_5=kUFB#5XhqV40Qg1w&JW0OGi^TR zr^(Fl6*3}hc@+`iSaNuAgTCND3iBgu6bybGs72u-YK&OLw-k8;VsOT%hYp!%ON`S+ zp77I*IBpkQoB}GW=sOIZ4g+xD<~jj5Itzj+7>c&fx2|)YYrkX1yB%%`y_wFr#n$ax zQ~OLOhDp&OAj~8=EQltKXsQ5mHtywE<*-rLvbU^at)6VRY_AEt(xthQxPOo|YT3hP z{WFYXTf%j*i;UoOcXfStl#y&mrE_#yYVn|)A<<3Rzrj5lw`huUPNhx#NT#> zZtUh@{@3G`R^IL0pH@ieWwHln#XePZQ+B9z?Cz?w>OUd%fxVwnOTrhJTc{Q%a3IM^ z)w2kju#d!$+|fM|vyyoRoothwCWQk+X;LPN0Ek*BLc2C}cTES;H*z^OCgiB=EwV(l z6-!8(jC(w0|CTNpZl_nHEuEY&m}r})B#8%MpE+e)cx>6s;GfW%oC^}V1eofer-LNj zLM}?OAjo(^6-oCRaA;heqrj+eaz1A+;iL33tMCzqh(42jeA|fD!j?>>)@CVS;*58A|MQUN__=kjg5@9|pefITq4biBg3YeOz zDEZ6+`G=?DCLrt~_89l+4@P^jtZ5C(@x~U4DyYSYXuJYBnLS6D>alVZ(DP2uLm6;q zE-{`7(LVED^>1e*3jz4f29TQ7vPPy@+O63g)cTv7I=^p!+kV^jOE5jKFYupn*iZ=O zc<_55KB&bUj;RBWlET?FoYsRtnndxHphKW8g9Z;kwkozhrXM838YE9tkXNLMTDdUR z%Vkw9UKvw0dzvRRM5HPt=Jie!qunIrN8o%8N#QdvIlH4ny0CI}9n%pEp~+HAK3<>3 zkmaKRj7f!(s2E^_$&-G47Rtfg|%m1shyT1u7>TUZ^?vi*U7jWn zf*S{mN#N=!7al1%dv^1gnS~6jmlht6#?_N^(0RK))SVludAiMQrw2yOHXmOf8_bc- zQV;V^hsH>Qgw=^8gWSXXNU7le6VTlJ`04~R61MU!Nl&IAEFwx}#AdGZ{mc<-F1 zMF}^@CUUiyaVv;GIYx3}rCeNXw;EIpp`=X6Y)!WBar7?vpC^D1ny7$>>9X4=&Co=> zumvbpG<;7=bO}jC6vG2YT3SkO$xiFbsif;;Vr#CtL9a22r6@`dU&MV5_jpJW6X)Rf zSdt$msT%O!y(+)k@ctKnJ9STFb{yDiAd*SVqPezAka)tcTf&P0LsJx6JTW=;D5>vv)#VYw%Q&0LrWCQ36`8bQc$m!T9w zgfbZ_YKq@&hwkGX>P7HIDL1aVA63Z16E&uU<9|EwHa3z;4TH;HE70*VHg{r4Bt33i zoioMmo3(zeIx=llR-k57jAkMS0({IWmq^PH?9x({qXuRWHo@vBZjrrjhf6>#Lx9cz zC=@yn0KA+9ClCxUr*wgl>BK!c#dg6@o#D|D6hinT&;a=;Isx)P=}_ru9U|!gq(io( zLV!9GN;Dv6+&CSf5u|}hMG9JSYAuhjckgcP1J^!LI93?8kD00R&6ah2$>ym)o6Tv} zK3nDP=J{!5pH!cf=R8j*B>q?Q zAvLBkl%)wd6fS37Jz&`l@)5wl1Ci7^5U?b_Leyf)r7+kO2c2xgX^{<6vN8G zFsYf@HS;%iNAjX`bBJiy^JKKf8BgL@S4I%sDedX{@9|rH4Us#h?#TU?*wo3P zl!uwK2hB3ov*>l_k7bKsvd7OqB$-di>uhp2L0s4+Jr3~dkHZ_MG11&mlPzz&QGgDH!zKsLt%Lng#JI9ugks~DV|SlY%at-oBEt!P3iAgHM$qg4eI71Ek& z)@mYPiR0(rq4hnzZKn(;p5I%R@98kaARN|&sFK>C4N!|BkW@j`dKe6mqXtnhGMNd3 z21>$Am|!Ui%PFVgH8p6BD*i(WmRby=M6HsLXpseV)Ybm}e`<3{B>o9L(ZTjV1ot;o zJ3>WiDyZsv{&J0vpnWHC_1;gF7Qf1PdoN|G<9^1e=8Q4oty^$%mRrpker@?9N6Kb> zF1LaD&sQ|&?^dT&n+%T6#_z4GZAw?%8N z0O~&wJyU|cofDTGb-KAf$--sb`&=-}X~qe0gd!>?VNxTaVgiJq5u%kuXanGBBRtog^+Uo$1OJCT~P5K!kQO(`)XqXhNK zPU4O8dMc}xN7du%Us#4C>?xbreU9;qcu&J!<(}%wt=aU(mnUXMK_7GC?1Marz^)Q% z@Odh}U!4)BU!Z?9o8?FiyTrS}e>&ZhWAWn9Z9{XQ4EXkr?&%MPE-nl_l1cj$0}Q9K zZkb`^pB{RjGQ={pg?+=KHP}-}$yXQD*+Ij|FuJ+j(;sW2XL%wIvtNR~mfm-H)qF-N zg~JPn5=jTcUxL1GfWYZ2_D_~O-vsz6>@bXm+=@z*+(eIK@m=NAb@LZhS(0YNMQPCM z9Ff*Juy2tAK^m>i7_v#7CdkB_O{Ck=wM}}ySZxxH0diT6Un1w)b!_q zOr(SKfPPYl#Ek%?S`vx{Dbkt*(t)-$ROo0-L8tWxI&up` zc?r%cNqkcYCN2)|em*yoV|8KAPbVgtnYgT0E#_{g;A%2;YFM>a*rlmih>o>7^YE`1 zH@)3H81lT@;|3p9)T*GSB4M#(qfpw&>;De!whH^yi_O33jVhX;iITf2XJ1{q9Z9M+WYl4~{f>0Snro z?Ffx3p^V=X7G>ns=f5|;I2mdwT$6{Xl*&jfu!r-5Ays981_L~ReFKI~ZRJ-S2gP9{ z7{()#1CCAML_tjxC)B9YX5C-RZzM$b>)y@}2I^zKz`p}Uf-EQt8vp@_k}^>hQ6TbB z=m*FI(s>}1=o5H%d5;b^YZx@pGy?Ed=>R?t9v^gE6S-=+)b12MgLR*#92{qNX6z<= zkjyeeCv%g!Wx?_5s6JT3doBIv<`Pr!YslExLk?^(zP4QHZA^&5Rc1(mgE0>n$L0}$ zh*aVqNO%W~s-l2n1XVKI6{|fqjJI|*f&Au&zz+f(*XjN9yX(zotr9{_LElT}4}E&~ z)%CR-v&Ko{Lka}&@GUJ>E=D_9H+6Z5jmba9+RCMfcQLJ&thAT>%4^Gms!hZ5m2 zBqaba7&k62< z62me*OBl|5O6)if!ra{8p{ha zg;~+rUM=gK=8-=|*|JxXaAajL_t*2?M4b_-gXL-GaVr&saCGVwz--rXoHF zM*%e0gB(B!gAw_siZ6tIl*T;85XL`ZI--(CiV6eZFo6j2DlQ2s?m|3xArRmbySyS8 zYMGTzLSmK~AvsY}5P*mb8_Y5)PSMEq$)c*aNZzrAEIqL(M2hA`dyT~q?s7K}ob=U; zhAwlQVVG1*uz}5zKE7IcG=qF=uDRD=`25)+`G@f3{t_b=NsBPTesTEx_A+=MSO|1d zW(JBWs-`>6I_~n;Wi}9<$<%?c=%TYQ)9mTGriHgW zWY!0eeS^q&YGSI>3+)a7{6OSrdd;b9m?lR-hKbP;{{l=fkpoo%Ps7*9>Tr@Y)A}49 zXCYGvPo#XoTh0~W?CJyqkqxwBxk%`A%K5ACI;;cfK+aZd0oDL(B0>rBAZq}8-bnH8 z965&`S7W|otv^23y(gYC@ja#CR{K(_xMBy`G@kjio_0?j++7)~=bTl%IcE{Yyo+gC zK}l8GVo*ac_7CDc9*)YNVVTQsVcpZXo!|p^40u8VbrCzpVA=}xaxmodGEE^EYW{B@ zTjsCHcS+3>L{C%9WziGVeACgpR;^PqNh8qrWNv3~!T?rKukFh17p5s*9eDw zWN&{|R*y)zMc^uXb8ks%L?kiZv=0l>SPjn-9#5d$G6!o6RE*72G>Mb!VEo=WkMMG9 z5HD55)5mQir9{%0Ndco3tVUxJqN>m~=xHGn(%_)r z^kn!u#EN~ar}FylnN6&ULa zo)M%6@C8$dT;WaQ1fPUtLFFhsAYLX$+He*o|28u5%(i)z_+MiKmH39^ZoW0UIn{5hm}a+3tHA}zHm#`s9&#xoNSn^;MK(t}Js z@}BamEpTWG)y$D)ELK=zbee09uEg!PqG*=wO&HNvm0VPn93jVw6L|5?E8{a!b~@j4 z*aHvJS7(lm?uyDlev`ZyW8P45bL`Gty?e*4jw%JnSP_HkhQ6~?N+wO95GbuD%yrhU zpNH)5#qou5-bb8oK26O^V4PTjBM_gD>G|E=-S7zLh)!;b<%Pmzl0v#U9N1|&)wp_n zN)-Bvo&W)k4Tudr2{LgS9UUD65X2o(Rf>_Ff=TX%MP9Zx?&KCiYUPo8vB!2hY?@tY zAqVgPe&hPX@_dQ;s_7cCN&>(sG` zF#}kDb{?BG*g@5JLRmfp@E?&3UI*)U1-Q&lG{BxOYD8U(;}KNj)^0v0*!tho{BhRr z)2(Mb1bRdr8i$?ku&J)ho+`=W9mq4jyEhvfT@$ZtL+ zRqlP8^~N!W$qDExzR!QtnY%ccR6Uc2+>rVY!MkLRjvv??CLP!qYV`aQE@Rw2K?}Nr zAFeIOp1U89XU97B>}Mz&Ntv0xSl@i-d~R+frtaogK9WRF;+~J^{iiZJdM9gwzqMBx7M#l{e3d{V_Ij8cUgF)`t?5E956je#|5(NFz(roT_i%MIv zI=Fb69mC|@ioQVKYO2B-CW<>iGzxu+*xAg^R<|?|0pA!P=fNbNn)2q&nDxeWrt=_O zwKB}n8KZYhN~3K^(_=|3F>dY72e678sP-JrNtfbzIir;1vcG#q?~BbRDI}fbWN?m0 zgJ;UMN$jA&!I>0pIfhVCw5}hzf-4zI*^d# zT*Vp_G#W+5JmG=h%h_Z^$>?Osd}3{Z*pBeZq>Oz(iNjsQFFONwppP=TrR^*2&gO zf&OpyED3wo%wBhk^n4K{_(>u`yGL~V$Ci7vPKn0_*n0}X=I_YV8Kg7@kTCA%V1jT= zn_fQ_Uz5f!+En=G*l0PU*p7`|&5vhIK61Y6zz$#w>maIMUa$`k0}CouFi2Fu#FMf4 z0elP}Ui*WgcLefN5h7qR5t}WwYEMS5G31}^9*uch-3Q_@dWh(&(O&YPh@gdfkB2R} ztNf0LaQ{QIS4jDyF1@E#Z_50WY#EyKIL%-)m+5Y>zuxu?|uiK z-oZB?7t2nK-{zjt9(vVb8>K_!R6nI*6U$ysgXNgAYzDaJh-Z0>Omk%7AaNXu@B(fe zpZZnLo<8+qv;Iu7ugI)j)r*N|<4>kOj}Kx`wSYX`1IQpiXn>UlVM39pim`js6HP^uXW5#@Y>XTE!80BU$W(#Gu zhvWM&@p&S;0UEdD1Tbx{6tu=0ppPk0i;{=6{r()kH<_FMf0bm>A2ks1x zHsT}3sAL!oO+B%Oqk0^RK#3^DNyw=TfbRza2FH}d^DKkzWRh+Ply_8$oT=@$J~GB` za>cDRHm|pr`jH~K@dSxdgWl0F&R3ts**ukCb zwW*WfNmyv|WMtih_V3Kp67g>*R*2l@KB&Qw(V)qc&|xywT8kjcwNj*Dh7?RBp<-7> zR$g50;q_HjRtANHZVj$ujPr| zyQ@}>-mJGs{*avHh)kPvt8mASUAyCETrOaEr;!<45>D*mYk8zB? zMRa)xwT~ttW61c}`u6#|j!sVN&hbi==SSaT2}PvMRb2u-Bji31kq912QWPlAc_1AM z($Jl^M@SR}4YEc<=RPyD)YQb>w%f6n5hAL|I7+IiQc_Y(s8tvuq;gbXWrmEIM>g*q zNZ$;zm@!zQmC&M-TG_UCKQ``F;2snL6jbnB0uw}4u;(NX0o3X%=ttEy2Fg)IM6|N4 zinh*!2M>p&ks>DNND0-j{-c*_X5!3WB|!G&(9A&A_%Sggl&Kh5RZgdfxDACRbt*tb z6vaqTwr0}XVI@HtxeBAq>S&Yu(j81T!wnO%aC7LbYZlfkQ+IZ)8X<%6LRTY4!NanS zN3#dZ&(Nk*Q1nO=OG7gf?W`R{>==i<43iNg+#;m!gg%uC)e5OnPYswEU{(ad*@i_# z(P9|1pyR@J%8V$VwFAUxQ@})baEzp<_I3DMd#mohj{0AceFO7nC)H5=WSWjguvF#0 zY64`JyW++Yb6}M`=#v%Ul<~SkLdMlw8CZgZAYu8#mHGNNirn<79C_eJ5~d_E6apUO z+IIEyTQVO}tB~QzDT4~7Ew`Kc5NOrpVnm6nFI0XskHj0LP8*|i``PEzAK1ZOwD?)^ zqx7%tlk?vR$|x)L1B-+Ifu2+4z3;nHr&Oe6m`vMjdt8*+iBw`OoT>^Y}{mC zA#L5JiH?d&Hp!c|qNt%b?bk}`vZt6b&q0%{^ytx-$ZgE_iFVv(bBBZ$sB4xwBIai>(3MxAJaS{iMKP^`nmiZrEDA>BMk2>ALVkD3#%yM-Y9M~yz# zA?>4Z!`1hp3?AXAQyZa93?aDtz7rF{#HwdP>w(8FZz6&q;^%u8d!$FjT^mGVG843J z$WdINOr5|t1;NYhxHf z#=>Fa80)fL4c*55TT_9NNE7l8Vx8E2nK{oQ7NDTglH0wqzVvp0%;8kp&AiOg1p!REyBJ^ zP=}Jb0jd{508%D`fd-VeL7_?mNRG}}-iS^t9Z-l#yWD-r=5oC!FIqt$ktZUzd zbf%h0TVqbyp=orwrhuj;q-ZpTs)`K-G-ypKIux3Rc}3)VU5Z*HYdJOGt}3;d7CBAC3<}JiMcN#-La4d(`yL zsLvKw$%m0NEH4@9OlHf?ah@G7RoY}~N}D-jp({0p7j7hx5zY>?8d*^$D8`Ax)g6|q z?DUlbYjX2NF(Ssf>ILRhWuC%kr#z*TV^=7$8%t}Q(NJQP#wT>+Xwj3caIu@TN;rwt z$dcjO*6dQeh>*&t@T8eJbH$6D30?8eKDc}_jkgQAnGCwm7#vnGyye@VOhF3fis=cd)?S&F09`1t1-5l~q)l~zI66(u~NNd|UMFmk8 zj@q8!h0eh|ycrbgxFlXDIC*+{3h50F6uW3RjP0Wa)VcyDb_XvBT%e&K_ff<-Fg7i$ zj!n3^Q8We-+1;KIS(bux+iY4bvL(?CPYADOG{rU0h`4%D(@cUQJu}(nxgObo1yME7 zmlRZ^%!c}T7^{^OUPsit>f0tE?&E;n2P7OxoiIZcixPdFyp!{;EWfQDPE+jE>tV}d~`D*8m*HPb=9AgROD+C8n>_-fhK}>Zp_gqFX zfa+B$2ao3WeU%-_CaS8e1Q@FnMO9UO>x10k_K8LuGcz+YF%c0X_e0|r7$6{(L?B}j zF&jX_(KG<#3$CdZ;N!d**I$H#!QkmXCXkix-THZOI8VlSZxyCV`C}Nj3j~DI?5z>x zt`${OAA#gCW`19IL~~4+G2Uu&2)H3KNTGqq{BvCQg-#E;z&qgJcZlr_W6T%U3*bHm z2glIN&})n)cEab-z8#4xF__S6O&;ENyy-e!F-54RvX(_^YVL%FM1eBY;VY{|(W*#z z>7%!nq~31kNb;Od7tn`Vk#w*IJ02rydQDrwgQv`Eg+p-1Fy1bIso3^1Lw)^1b|h9MY!YhjtAiO>A0yRk|zh}FnV7%pXtwLxYfjyY7knO z>Dw5`s7Rn#w6(adFMi(HDy}gv!^Fq%;PN&ifBOWQ?gcv1N9HUeFmO?CKr)y1)L60 z>7s%tf@r28h3p5Q?hcV`di%r#vNN^^O)~XLGc?6T5JXimEi_dXQwq`)L=7NP6-5-& zO*Dirk|?@Vp&AyDC_tb}N(vH%LpE}@d;Ch<_?%dc)_l-nq=QpIs2=NwIKl|5RxOex zNT6s(ZRb0R$Jy7KNN#H6;gjRH)j2n-U5p{o$lv6^N^cWBTGm{5on+0-Prf zN|*qXq1tahv+(ZT2ym4ZI}T8EQ|Zg|zIS}?2rrx&DM{&TjN-d?sk;%6fbc&VX{4%3 zs#K*X zGT23{cEP3dT0mlksDn z(OwRyCr6@Eis9gi%!%7t6dRBu7%>#xuMl88qnk;nWS!mD7Yt^(v`y8ajb%TA?bE zfuveegeV#nXhM_<5eiTWDJdzWB7%w{0w$Q4nu?`WDO9Oas+Jc-=FzbYD2u#mQ%C1x zi`r${_8nRlc$1p+%xA~Tr_yb4j2zpt+is(G1$Tsvl_u%koDXR13BE*SeLnNvJs8qk z*7NA3aiwA|79x|XOcYh{djY`qF(o=1z&JQW-l`~&U=?PHs;XK3{aCPO;tnzuyr~d2I8u6(BlgU zzHx$8T)-KEp5r~iwaYR#!tvP;f$$7-N2~NYHkw;oDs_E{!K0LkkG-}5hA{)H4(T3J zrLirwgJhHI>AD-5o=A35)uePXj>$gWJyE-6$moiq92Q3mtVuL-I&##}>R`m~d9rm) z+q~06MF?9Yg-J!WqD?_jAwWcgNkRlY6xO?}jU1H{P7%ZW8k!^9ebaPKX2{_`78_ST zJZBi^=9Ur;P7}jd&E*NIZ^5f&A-Z77wPiA96Al@6eK(n6VQw%F&_nflVfieMu({)m z19#ZO0}TXKkk(a9++#iApC_#zZ4;)u@n(WP&#w>IVky5d@d6RpqB~g~7mX%?<>`Bnbo(dPYQnC4dQ6ECVYKBxJyEvmLPw=RataBx>GO2ZH& zR6nUSPHqtP9NHw4B$<3Yy|pzYof{nL*6HTz$jH?Sj3Y@fvQ>6)Xm>vLT%RB7^6gbF zbBx8R*~?x0m>JGl7`Kyy;EfN3mdADG?~2X0b^Je~y>VQgBq!`mkbkSG**g64#JIy9 z)5+XDPjvR~b33?CRKiZ0Z;Om1nYQY5EisG%q7s z7MIk2nIv$&v}dZx9UO7JlS`UTcq&-_X_zvQ8}I;>8OQ z2v`b}Bu02vEP|#ty+*i#Exf%kuU_s>MYl7r1t^r7K&WzSv#xo)2LNJJUrS{xc4LJ> z02Gx2MNz8-sh}t&jJ}&i1-DeWz6)oyaN8)crQD;rhga(f=cc%KJk1m9*`>ovT5b4v z$*b1h_nxxi>#29vcbhkClW%vpvyt=0@ZQOeB@w3|8!Z*qaZGcmc^)3z=JTF>`rlqS zytS{z-me+rb9`lGS1%Q~n~l&lLhlZ$kZ2FTYhVw44djI_EhF|EGoyGQsWh(FvoPEX47ep{nXXI!%=r^MLPTDn+PMomGCD%Ef z!=ANfOpkHAK7@M(Q{a9PBaLv*ES(RW4&%SWrZJCTyABW3W?=CG3kK!~xqba_u6$odiOk&8KZPRTdww6#hgTl3IxHZxuZvA9B?~?Dv zb>ZXZo?l58@@!}V)o}9na~BfE?=#NCl9$QFnn#jxJLKM8^^}RO_4R%^TDhrPC6|+e zO*L@i$+oRjLhBy#JHuno9w!X$?H4Jg$g0{jI?p|5*4lt{aw3qTNGF28L{L;QMAHw% z8X&5apqlxzOtnQ?hRp4{se`#dEYNDG;=)WwOqq&|9tH=nMj0JCl%Oh*G&w&ycx9qZ z8xJEd-OEP0OLb&+n!Nfl%bBs?pLaS!V@nn>>2&yBn|+7z!4SBKi!yG)8B#P^JJqpj zFvc+T@6U~!KX!jZf;^Q~rkEqsjO1@Nt76Kw+KP%G;8gSu`@~mUCzVsg+m3Ki#~td> zNp@x0MBex+5ek=PI7^trybXzwjoR>aBXbjkVNFll>Dk>jGn8q9$IuqjpG=QQGQ1{ z>TX2j`L^3bY(KT+5)K-tE@R0bQ2mI5*dMZDV(X1p+YVLI>T)P^G=ACs%llw4Q54iuMfzAe1O3<)Vj@BOx>PO*ks+Ev5YU1l|5&?{ LDZ+$?P&!fou|bY8 literal 0 HcmV?d00001 diff --git a/data/microorganisms.umcg.rda b/data/microorganisms.umcg.rda new file mode 100644 index 0000000000000000000000000000000000000000..8b67e19b31a1568d557247f8f24e104dc9e14e01 GIT binary patch literal 6450 zcmV-28O`QGT4*^jL0KkKS)vVt-vBA!|H%KcNB{r)$KXQE6`|cyVY+`Th>>@Qvv`8gsJJM0BP!I3=nNVXaXtv35lW_O-6}L zlmG)D0}ucMO#uYcNu<(K$Up!90000Qo+1JhK$;>z0000001Y%v6v^tEGzNx&qZ8CL zG%*3AY7GG*ASQwkO(e)@00Y#}Hl~9h5F72j?{NSDh9Llj^)K0pkNf`ggXm%a0C(x% zX@U?U0D&!$WTF570`C_+S9k^s*TUY5OW~6FUSBM~ve)$}oX7P%IsT8BV1p3R2KWW# zPOD7LizJoWOuG5-#GsgLNH(c)Rac_7KwU3de)}!lG8G)~KQpf5ru=>=QJrqa7fWN~ zDYkj?(K^yP?Zi}Gw^6!+8ZM>dI=ymeCw_4?1?vb1u`||4j#WGNrZbhHkZnXpxLMNV z(*zsmz~Sgr?0dko4`hhuh@Gf1ta~YPIyf`R?77M78pH0I@8c>fg%OoXdRPY@&1 z^Y7qp^K0t9HR}zC`Fcovj7UaWq0so&&X79>Wwq#)H+6)`f#nzX8M3m-CFX5=-D!?) z%m}WY^sTm@2vfxRF3Q9>4DqyE9?S-;`f|wWH52n+svRMcwv9Qe^uR01AFmcJcY3`YFdF4?RDPujJ%M5VnrZdt)uglRePz2#I zgpBKzke;yWg$qOWu6wgVm7CC=7_N7xqT|CQR%Nhdn6`Nhf_7rc-ENp>ShIq7TqiEi z6FRbuD}oYeAgd1hA;g7T)FH}&v^xHaW~$2zCmxk@*KrIfb-CUd#`S7ei)&?6B(^CG zy-f=t=^>g+oy8%b#^&jTBkcBZfXSTOmfeR^`pQ#?DznaP=>s1hv-SZ>v|-Wh@t$1S z>sZqnS35M}CM!X6C6V_(l+EWlB?+?9cK81=pYLn+&*tHtF#X|tQ%s-hN}2V5Ux0J{n)%)scAg`k6LsMR-^?<6jVYjUW~Bf-VSi;;-3qG0ck*U5)A z4ljctEzzyYJM5J>JEj6Sf%eh(TuttpYL`p`X+|s=c`chO ztav_myzCpLvBKcRh{OcD;fYCF*pE1}NXRJzljK+cU#KHR>7NvM=4?Dgt|;j@Xz@1Y z5L>7w?M+?ssx7X%#cZ}g3rsWAq2Q>kQ!%Em)xCzU-0Ad2daavMi#VOlubFJOA^ZqY}@8}XhA%65E0s*9$G<~*&01(g! z5FX3~fJuFyWC@MV9b7<2;Hw(n>s@l>Vs(#8_jZS3cGZ5BdnB|#G=zSklOLr^qHE#Q zdY@eUC(54%+mObov%3hW92t$m@|}uS2xFnO-qIN*7HWL93Qj6G7c)kJNQjLXZ=+e@ z>$9R^EVEhjg$9G`lOhcXnkg_X#1prkvVsu%Y&gKlILfCYmoyESlqFrDw84l2(I7|~ zz}M(I`PBEI_#s>vTlUX!5*tHftM;&6Iw-_Mg#)kM=S~ng89%$@EivKJf!TrR(7jvn z0pq*}W#EIeM!Z3@FnIJ_fr9!g+;Ts6T5>vHeNFQiX}%j5V^sKrG`DLYR75qb@d340 z6E^qOZ9dN*%i2Br91>1?sMb^U^wOW75jc-3MH|#x!Vc*SO)a>@$!U)~tNFUzIOZ~5 zo5j^t`Q3Nm+DzYk{VrZd=OigyW~HTe$+f6R z->*|N%-n6PHC;qj6L9^a6_Yg7c!*3lJH;8Zqbf4#5mX``R?m(C zB9{57S{0uh3P?d#OAP8|BfiXPo5*Ax-xLC65atQWBiT$w-Zd>Vj?2WAXRlDQPWQjL zN!B4tZ^x12Pey##Av@w_m@X5&BW7=k%`QR*!o>y!Yj$C0>HK=y%TQ27VB^L}7SW%O zcZ&)3fw$)(vk=8N9~rP?8LJMQDG71KfL;RwufQRE_m^T!brR!WFvl0@1y>Qo%mx|= zJBcI~zW#<@Fj_tdjc>;ypm0Ff!D{pkbA;=Qw?!D=SL zS0N+U&x?v8=bt_BermAEanD)LbX^f&4Iy6WN66yW1x+zj8pKOL>rM-;rh4;V7ILi) zyY-&2%1K})4K6H0b{fz@CUCIVBZqh$jMj2Ul7ywn(c*=UJf|IxV@=e0p7yDE!Psm~ zGpJD>GgmbC*0-V_u4W(<(}mrJMFD_mk~%~YRHzZ0N&~MNBe|vFQUHdrp$oqyyD0I} zT3}_u!$6lz_0{m0KKxl(8Lg%$ymr6FoxEQw%&Ew7`Dhx{Q-D4cs3?SsSEdPirBFjx z2h(_N+aY@jeJG!GFk`)kMz9{Mi4QLYDZySSdDP#?^QgzA>aBtfS1G;3ia3dM-Cxo`9&>!=lb%L9d@El2d^IH?LQs_r;a5m47(xsI6htOCC{RaL z24w{@;t@qqn{5+FYt|xHEYFu#4K$ToyrO5Yx(!1TqLa=?0f+ z@6CmG(9i{thdu|2 z)^)?y=X_sC|2MK&dv)^nSQ#S&%7y@t4T;Q_u8+x+c(>4f5G_BUV;1taQ4BB_#933) zLc|!oijSlWLPQ=54n$+!&$Bc(uLKPA?bxVizqtqk`lU#?47bQLeX6Cob&A1Kfd)@T z8?_rn893PMZj+k?2R!kNbh~#K&$AtjPRs=8s12|%QARv0s*Q#|8^~>DauW0?(CfBN zEG#>C?XJ}vJ;XTc)DTE5F6VBtMs3C*3S}5!BP|XC ztQSnx4GZ0C1iS-cODL6C0t;_0^m{FBWOL)!8`cMnIMfkPu0f0}!d)|(4zOngrVz^T z6%FrOBBml(LWehD6rVg`T1C%Cr@vftj3Gt9v|kY!m>rd)Y8=eX2|2wlU6Na|-9}0* zA}<7IIg>VJ0r4C)h9}xmm# z+UtlM48V^x@cHJpQcVsSP7n~pd-aLV2ZC=GNp#gYDI($8vGXz-QFtkO4q%Kv>nUmX%KYC6_Zvv-L|Ypy(-ARV1dPb` z#}VtTbTF=p=a}4zCK_3v7_EI{jmredFb_W2oad>!5Cx90zTSD4l!w(NIwllH$;5bV0S5BpNCw?GpjZAbAOY7qmy(J|8(l z=s)I|*?K(KIZZF<)(=!6;RML`3j+}b6t|W^mBb9KKr)|IX|I)iKNvnXpD4RFWX&~Q z7;KC}G}SRrs?|c8keJk3IB1rU;n@B$@3^|{aK~n>Uo#u!xIY~{tPZW-M z3<~h1v%BfEe?v7`b%^o*B751-hkg9XM-4WLv9Jp>$tK$3$H>uE0U*Z26svQ#%!=IK z7QxJC7J#{Rvx|0vCk}ICUsv142dLVU33SS2V9chXED%|cLh9ua@GLPcw^slXkH=Wf zV$^_Do!eEY?#MBoZ;?!IZ4M2_y~zNsjEmPo_&NkMyLPZ=H$%|W)W)G?eKC{3BQ&cf|eU2D#jpEGtH^H}MSz%gl+t#;1Vt~y~5mJp) z?l6Y)sS9O%&7GY&PGapo2C>S$+h_&I3Fkf=13Fxc)!%#Kn0SJ#f}GO3qN!o0bgN6M z;KMsGeX_*!OcWsKbvgzi5Fop`yP)LZZ4V1JW3kbTZ;~X3GDV0ME~7V<6J}UVqJ*lW z{S_5*uH$u_Z|?-PYwU(62NI6EgQqMN^*EZOn75RH~X?<=BB^(N<`7opH^z z%oyiLCe)_9yW_E+k7-2aAW1rm31w%y2GxcM7}C}uyTe~x-Y0N|jn!u}kaC3{7T+H- zff9q~*{EX=3ksss6JQd2+si#T?$3NVk}}Nuw{NO>&h@OjaYVN$r3pd-1QG!XkSB9R zRDmmv$QIvQZzpY{xt#5GJ@b6y0|>H2Q;P*$7;AzxvHrhPte?b@CNXIm^S?Na7L=DM z`}dXwYsbUx)?}?gSLwy6dCm$KBB0B5gikT@RgiOOOL8sfPH;Gbv^ELEEow;3MyTItiO+WPb5Sv*Bv{&!lmwZLY>Liyx| zon~xEEC4dCBI&$rz`O*p-NB_9oIuX!>Q?luOLoyoy!dstHc6hXH_Mhsn`>>B*FsR^ za8dDZO0I~=5r{SbL11^Uced{GMnSx$rMQC5Z%wDZ_i|nV-#Nm`=HKy=VYaY?T=vMA znc;k6%m*0~tRT;9TuutmxSSX<5IQMfE-t`RHzwpEy?DW?I*ljpX~4D~{h6JlI{Fqe z4?Cv=37gRwfB+x?&A7uR`>px!ostQaQoyOY?(ZiU$HQEJofsi#J}z`LU<4Z6m2e|M zS#1;wFhbnHwA5DBMxziBVXQ;~;~Bixs0<`XO-bynmPiQET2nrCjZfU-Ex*Y)&!{gBEoMctC zGNi2O=ML?xQsv)N+!oxr#Y=PL8k@3+P7#OmRck^rDvEWi@JSojp}D+=W6Z&LVV;9sywikDIpS)!hU2Cs`0or$F(?7GcFBvAY2 z%kRS4=Y>+-Qw`$pTfjNyiBdC$TtE$DvYl>&95jMupAXTBs~2h^Xi)s#vSk@8_JEXb z>nI))Bv>Lo8!Z(}_Cx6UzIt4FBAk&+bplYq>RU%=ND4AoTgXel6|)#smUn326wlC8 zL@v(INJIodp`!Uc0Z#RGD}C`&Sr5avq#&e`9=erBN^iX?+hE!%C^}^TH(t2F76;`9 z5MbHt*$Br2u65?l9h!Z$hGg3I+J~>rq9Q$-7hAH&f;xpo6N1f@7@@ftrhkYowHJyZ zX!!&}^aazaNFxQV@#O&Vk~lad8$cnp;C5y*3j*iS{H0piuL%4iK)E(4T=nKI73=Ut%?F&<**wLhXl0~+31n! zA6pk2#M`qmT;d7gAl;#~p`9{XQq;5)s21#1Vxt>Lv}uSa`>_QY5~EP)(jaLEi|9SU zmY&Ai=JQ%}Xuhig*KdA0s%ps)EDnth+b}d~M&oPv zZ@s7nCanc$L5I&dvIs(_PD^*dZ9qt)LO^z!3F3xmhe%0PmZug_1(E{9CQ;hRF+dGw zFKC!5YIraTBOEuu=n*2K0urmay8R7mIF~@$zH&5n__7hz zOw!bxxPGx5@oa_IJ@+qKRGDy%IvUy}v24JMGOn)dGSq<0X5D6XE=6G!#pg=;@tU^V zK5e6p7%41gSKMcv(bXnUJWo#nOiZApc&8QgwU#446jCI_;@EE|uVUpd%SMr|Ewr1z zcjt(w_^c)mYO>xj#}NJUzT&4E5pY&0dvBWsEA-hl-kTpE@+0meZO? zZzZiYzTtGTm`{E>c&KM=tlLm)5agU2%KKbLQ*4waBRz3U8+{9LF;V z5=cPgk?PW3a|~c%s6%P7F@qZhI{Wji(|5^vS)Db?Tv=FYn`JQhmR7xJ=RYc;G}Dzb zBv}NmBs7lQEJ|YlkPTt==H8h!zbnc2zNqdC0~ZXV*r_@8csVsgjQ42Fc;A(k`5(t0 zHgGxwT64@(ZLLLV86YABpQz?>2n>*jopxk{)OFKOjp#\% - left_join_bactlist() \%>\% + left_join_microorganisms() \%>\% first_isolate(col_date = date, col_patient_id = patient_id, col_genus = genus, diff --git a/man/guess_bactid.Rd b/man/guess_bactid.Rd index df6c8c02..32bbbb27 100644 --- a/man/guess_bactid.Rd +++ b/man/guess_bactid.Rd @@ -27,5 +27,5 @@ guess_bactid("MRSA") # Methicillin-resistant S. aureus guess_bactid("VISA") # Vancomycin Intermediate S. aureus } \seealso{ -\code{\link{bactlist}} for the dataframe that is being used to determine ID's. +\code{\link{microorganisms}} for the dataframe that is being used to determine ID's. } diff --git a/man/join.Rd b/man/join.Rd index 16266435..09254631 100644 --- a/man/join.Rd +++ b/man/join.Rd @@ -2,47 +2,47 @@ % Please edit documentation in R/join.R \name{join} \alias{join} -\alias{inner_join_bactlist} +\alias{inner_join_microorganisms} \alias{inner_join} -\alias{left_join_bactlist} -\alias{right_join_bactlist} -\alias{full_join_bactlist} -\alias{semi_join_bactlist} -\alias{anti_join_bactlist} -\title{Join a table with \code{bactlist}} +\alias{left_join_microorganisms} +\alias{right_join_microorganisms} +\alias{full_join_microorganisms} +\alias{semi_join_microorganisms} +\alias{anti_join_microorganisms} +\title{Join a table with \code{microorganisms}} \usage{ -inner_join_bactlist(x, by = "bactid", suffix = c("2", ""), ...) +inner_join_microorganisms(x, by = "bactid", suffix = c("2", ""), ...) -left_join_bactlist(x, by = "bactid", suffix = c("2", ""), ...) +left_join_microorganisms(x, by = "bactid", suffix = c("2", ""), ...) -right_join_bactlist(x, by = "bactid", suffix = c("2", ""), ...) +right_join_microorganisms(x, by = "bactid", suffix = c("2", ""), ...) -full_join_bactlist(x, by = "bactid", suffix = c("2", ""), ...) +full_join_microorganisms(x, by = "bactid", suffix = c("2", ""), ...) -semi_join_bactlist(x, by = "bactid", ...) +semi_join_microorganisms(x, by = "bactid", ...) -anti_join_bactlist(x, by = "bactid", ...) +anti_join_microorganisms(x, by = "bactid", ...) } \arguments{ \item{x}{existing table to join, also supports character vectors} -\item{by}{a variable to join by - could be a column name of \code{x} with values that exist in \code{bactlist$bactid} (like \code{by = "bacteria_id"}), or another column in \code{\link{bactlist}} (but then it should be named, like \code{by = c("my_genus_species" = "fullname")})} +\item{by}{a variable to join by - could be a column name of \code{x} with values that exist in \code{microorganisms$bactid} (like \code{by = "bacteria_id"}), or another column in \code{\link{microorganisms}} (but then it should be named, like \code{by = c("my_genus_species" = "fullname")})} \item{suffix}{if there are non-joined duplicate variables in \code{x} and \code{y}, these suffixes will be added to the output to disambiguate them. Should be a character vector of length 2.} \item{...}{other parameters to pass on to \code{dplyr::\link[dplyr]{join}}.} } \description{ -Join the list of microorganisms \code{\link{bactlist}} easily to an existing table. +Join the dataset \code{\link{microorganisms}} easily to an existing table or character vector. } \details{ As opposed to the \code{\link[dplyr]{join}} functions of \code{dplyr}, characters vectors are supported and at default existing columns will get a suffix \code{"2"} and the newly joined columns will not get a suffix. See \code{\link[dplyr]{join}} for more information. } \examples{ -left_join_bactlist("STAAUR") +left_join_microorganisms("STAAUR") library(dplyr) -septic_patients \%>\% left_join_bactlist() +septic_patients \%>\% left_join_microorganisms() df <- data.frame(date = seq(from = as.Date("2018-01-01"), to = as.Date("2018-01-07"), @@ -51,6 +51,6 @@ df <- data.frame(date = seq(from = as.Date("2018-01-01"), "ESCCOL", "ESCCOL", "ESCCOL"), stringsAsFactors = FALSE) colnames(df) -df2 <- left_join_bactlist(df, "bacteria_id") +df2 <- left_join_microorganisms(df, "bacteria_id") colnames(df2) } diff --git a/man/key_antibiotics.Rd b/man/key_antibiotics.Rd index 9d66c0f9..12932662 100644 --- a/man/key_antibiotics.Rd +++ b/man/key_antibiotics.Rd @@ -4,7 +4,7 @@ \alias{key_antibiotics} \title{Key antibiotics based on bacteria ID} \usage{ -key_antibiotics(tbl, col_bactcode = "bactid", info = TRUE, amcl = "amcl", +key_antibiotics(tbl, col_bactid = "bactid", info = TRUE, amcl = "amcl", amox = "amox", cfot = "cfot", cfta = "cfta", cftr = "cftr", cfur = "cfur", cipr = "cipr", clar = "clar", clin = "clin", clox = "clox", doxy = "doxy", gent = "gent", line = "line", @@ -14,7 +14,7 @@ key_antibiotics(tbl, col_bactcode = "bactid", info = TRUE, amcl = "amcl", \arguments{ \item{tbl}{table with antibiotics coloms, like \code{amox} and \code{amcl}.} -\item{col_bactcode}{column of bacteria IDs in \code{tbl}; these should occur in \code{bactlist$bactid}, see \code{\link{bactlist}}} +\item{col_bactid}{column of bacteria IDs in \code{tbl}; these should occur in \code{microorganisms$bactid}, see \code{\link{microorganisms}}} \item{info}{print warnings} diff --git a/man/bactlist.Rd b/man/microorganisms.Rd similarity index 86% rename from man/bactlist.Rd rename to man/microorganisms.Rd index 8c4abafa..deac25ac 100644 --- a/man/bactlist.Rd +++ b/man/microorganisms.Rd @@ -1,8 +1,8 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/data.R \docType{data} -\name{bactlist} -\alias{bactlist} +\name{microorganisms} +\alias{microorganisms} \title{Dataset with ~2500 microorganisms} \format{A data.frame with 2507 observations and 12 variables: \describe{ @@ -23,12 +23,12 @@ MOLIS (LIS of Certe) - \url{https://www.certe.nl} } \usage{ -bactlist +microorganisms } \description{ -A dataset containing all microorganisms of MOLIS. MO codes of the UMCG can be looked up using \code{\link{bactlist.umcg}}. +A dataset containing 2500 microorganisms. MO codes of the UMCG can be looked up using \code{\link{microorganisms.umcg}}. } \seealso{ -\code{\link{guess_bactid}} \code{\link{antibiotics}} \code{\link{bactlist.umcg}} +\code{\link{guess_bactid}} \code{\link{antibiotics}} \code{\link{microorganisms.umcg}} } \keyword{datasets} diff --git a/man/bactlist.umcg.Rd b/man/microorganisms.umcg.Rd similarity index 56% rename from man/bactlist.umcg.Rd rename to man/microorganisms.umcg.Rd index bc14b777..18c98600 100644 --- a/man/bactlist.umcg.Rd +++ b/man/microorganisms.umcg.Rd @@ -1,24 +1,24 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/data.R \docType{data} -\name{bactlist.umcg} -\alias{bactlist.umcg} +\name{microorganisms.umcg} +\alias{microorganisms.umcg} \title{Translation table for UMCG with ~1100 microorganisms} \format{A data.frame with 1090 observations and 2 variables: \describe{ \item{\code{mocode}}{Code of microorganism according to UMCG MMB} - \item{\code{bactid}}{Code of microorganism in \code{\link{bactlist}}} + \item{\code{bactid}}{Code of microorganism in \code{\link{microorganisms}}} }} \source{ MOLIS (LIS of Certe) - \url{https://www.certe.nl} \cr \cr GLIMS (LIS of UMCG) - \url{https://www.umcg.nl} } \usage{ -bactlist.umcg +microorganisms.umcg } \description{ -A dataset containing all bacteria codes of UMCG MMB. These codes can be joined to data with an ID from \code{\link{bactlist}$bactid} (using \code{\link{left_join_bactlist}}). GLIMS codes can also be translated to valid \code{bactid}'s with \code{\link{guess_bactid}}. +A dataset containing all bacteria codes of UMCG MMB. These codes can be joined to data with an ID from \code{\link{microorganisms}$bactid} (using \code{\link{left_join_microorganisms}}). GLIMS codes can also be translated to valid \code{bactid}'s with \code{\link{guess_bactid}}. } \seealso{ -\code{\link{guess_bactid}} \code{\link{bactlist}} +\code{\link{guess_bactid}} \code{\link{microorganisms}} } \keyword{datasets} diff --git a/man/mo_property.Rd b/man/mo_property.Rd index 16d9a422..3f7e9e49 100644 --- a/man/mo_property.Rd +++ b/man/mo_property.Rd @@ -4,10 +4,10 @@ \alias{mo_property} \title{Poperties of a microorganism} \usage{ -mo_property(bactcode, property = "fullname") +mo_property(bactid, property = "fullname") } \arguments{ -\item{bactcode}{ID of a microorganisme, like \code{"STAAUR} and \code{"ESCCOL}} +\item{bactid}{ID of a microorganisme, like \code{"STAAUR} and \code{"ESCCOL}} \item{property}{One of the values \code{bactid}, \code{bactsys}, \code{family}, \code{genus}, \code{species}, \code{subspecies}, \code{fullname}, \code{type}, \code{gramstain}, \code{aerobic}} } @@ -15,5 +15,5 @@ mo_property(bactcode, property = "fullname") Poperties of a microorganism } \seealso{ -\code{\link{bactlist}} +\code{\link{microorganisms}} } diff --git a/man/rsi_df.Rd b/man/rsi_df.Rd index 05edbe8b..3f553f4c 100644 --- a/man/rsi_df.Rd +++ b/man/rsi_df.Rd @@ -4,13 +4,13 @@ \alias{rsi_df} \title{Resistance of isolates in data.frame} \usage{ -rsi_df(tbl, antibiotics, interpretation = "IR", minimum = 30, - percent = FALSE, info = TRUE, warning = TRUE) +rsi_df(tbl, ab, interpretation = "IR", minimum = 30, percent = FALSE, + info = TRUE, warning = TRUE) } \arguments{ \item{tbl}{\code{data.frame} containing columns with antibiotic interpretations.} -\item{antibiotics}{character vector with 1, 2 or 3 antibiotics that occur as column names in \code{tbl}, like \code{antibiotics = c("amox", "amcl")}} +\item{ab}{character vector with 1, 2 or 3 antibiotics that occur as column names in \code{tbl}, like \code{ab = c("amox", "amcl")}} \item{interpretation}{antimicrobial interpretation of which the portion must be calculated. Valid values are \code{"S"}, \code{"SI"}, \code{"I"}, \code{"IR"} or \code{"R"}.} @@ -42,7 +42,7 @@ library(dplyr) my_table \%>\% filter(first_isolate == TRUE, genus == "Helicobacter") \%>\% - rsi_df(antibiotics = c("amox", "metr")) + rsi_df(ab = c("amox", "metr")) } } \seealso{ diff --git a/man/rsi_predict.Rd b/man/rsi_predict.Rd index 42b0e670..5caa6c67 100644 --- a/man/rsi_predict.Rd +++ b/man/rsi_predict.Rd @@ -53,7 +53,7 @@ tbl \%>\% library(dplyr) septic_patients \%>\% # get bacteria properties like genus and species - left_join_bactlist("bactid") \%>\% + left_join_microorganisms("bactid") \%>\% # calculate first isolates mutate(first_isolate = first_isolate(., diff --git a/man/septic_patients.Rd b/man/septic_patients.Rd index 510e6aeb..8b5176d0 100644 --- a/man/septic_patients.Rd +++ b/man/septic_patients.Rd @@ -14,8 +14,8 @@ \item{\code{age}}{age of the patient} \item{\code{sex}}{sex of the patient} \item{\code{patient_id}}{ID of the patient, first 10 characters of an SHA hash containing irretrievable information} - \item{\code{bactid}}{ID of microorganism, see \code{\link{bactlist}}} - \item{\code{peni:mupi}}{38 different antibiotics with class \code{rsi} (see \code{\link{as.rsi}}), these column names occur in \code{\link{antibiotics}} and can be translated with \code{\link{abname}}} + \item{\code{bactid}}{ID of microorganism, see \code{\link{microorganisms}}} + \item{\code{peni:mupi}}{38 different antibiotics with class \code{rsi} (see \code{\link{as.rsi}}); these column names occur in \code{\link{antibiotics}} and can be translated with \code{\link{abname}}} }} \source{ MOLIS (LIS of Certe) - \url{https://www.certe.nl} @@ -24,6 +24,46 @@ MOLIS (LIS of Certe) - \url{https://www.certe.nl} septic_patients } \description{ -An anonymised dataset containing 2000 microbial blood culture isolates with their antibiogram of septic patients found in 5 different hospitals in the Netherlands, between 2001 and 2017. This data.frame can be used to practice AMR analysis e.g. with \code{\link{rsi}} or \code{\link{rsi_predict}}, or it can be used to practice other statistics. +An anonymised dataset containing 2000 microbial blood culture isolates with their antibiogram of septic patients found in 5 different hospitals in the Netherlands, between 2001 and 2017. This data.frame can be used to practice AMR analysis. For examples, press F1. +} +\examples{ +# ----------- # +# PREPARATION # +# ----------- # + +# Save this example dataset to an object, so we can edit it: +my_data <- septic_patients + +# load the dplyr package to make data science A LOT easier +library(dplyr) + +# Add first isolates to our dataset: +my_data <- my_data \%>\% + mutate(first_isolates = first_isolate(my_data, date, patient_id, bactid)) + +# -------- # +# ANALYSIS # +# -------- # + +# 1. Get the amoxicillin resistance percentages +# of E. coli, divided by hospital: + +my_data \%>\% + filter(bactid == "ESCCOL", + first_isolates == TRUE) \%>\% + group_by(hospital_id) \%>\% + summarise(n = n(), + amoxicillin_resistance = rsi(amox)) + + +# 2. Get the amoxicillin/clavulanic acid resistance +# percentages of E. coli, trend over the years: + +my_data \%>\% + filter(bactid == guess_bactid("E. coli"), + first_isolates == TRUE) \%>\% + group_by(year = format(date, "\%Y")) \%>\% + summarise(n = n(), + amoxclav_resistance = rsi(amcl, minimum = 20)) } \keyword{datasets}