From 1227e2c60c141d7ab3c1498d53183fd50d8bc4dc Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 22 Dec 2025 08:48:41 +0000 Subject: [PATCH] Built site for AMR@3.0.1.9007: a5c6aa9 --- 404.html | 2 +- LICENSE-text.html | 2 +- articles/AMR.html | 18 +- articles/AMR.md | 8 +- articles/AMR_for_Python.html | 2 +- articles/AMR_with_tidymodels.html | 305 ++++++++++++++++-- articles/AMR_with_tidymodels.md | 251 +++++++++++++- .../figure-html/unnamed-chunk-14-1.png | Bin 65285 -> 32166 bytes .../figure-html/unnamed-chunk-15-1.png | Bin 140523 -> 71804 bytes .../figure-html/unnamed-chunk-21-1.png | Bin 0 -> 65285 bytes .../figure-html/unnamed-chunk-22-1.png | Bin 0 -> 140523 bytes articles/EUCAST.html | 2 +- articles/PCA.html | 8 +- articles/WHONET.html | 4 +- articles/WISCA.html | 2 +- articles/datasets.html | 4 +- articles/index.html | 2 +- authors.html | 2 +- index.html | 2 +- llms.txt | 2 + news/index.html | 20 +- news/index.md | 25 +- pkgdown.yml | 2 +- reference/AMR-deprecated.html | 2 +- reference/AMR-options.html | 2 +- reference/AMR.html | 2 +- reference/WHOCC.html | 2 +- reference/WHONET.html | 2 +- reference/ab_from_text.html | 2 +- reference/ab_property.html | 2 +- reference/add_custom_antimicrobials.html | 2 +- reference/add_custom_microorganisms.html | 2 +- reference/age.html | 22 +- reference/age.md | 20 +- reference/age_groups.html | 2 +- reference/all_disk.html | 8 + reference/all_disk_predictors.html | 8 + reference/all_mic.html | 8 + reference/all_mic_predictors.html | 8 + reference/all_sir.html | 8 + reference/all_sir_predictors.html | 8 + reference/amr-tidymodels.html | 234 ++++++++++++++ reference/amr-tidymodels.md | 192 +++++++++++ reference/antibiogram.html | 16 +- reference/antibiogram.md | 18 +- reference/antimicrobial_selectors.html | 5 +- reference/antimicrobial_selectors.md | 3 + reference/antimicrobials.html | 2 +- reference/as.ab.html | 2 +- reference/as.av.html | 2 +- reference/as.disk.html | 2 +- reference/as.mic.html | 2 +- reference/as.mo.html | 2 +- reference/as.sir.html | 14 +- reference/as.sir.md | 12 +- reference/atc_online.html | 2 +- reference/av_from_text.html | 2 +- reference/av_property.html | 2 +- reference/availability.html | 2 +- reference/bug_drug_combinations.html | 2 +- reference/clinical_breakpoints.html | 8 +- reference/clinical_breakpoints.md | 2 +- reference/count.html | 2 +- reference/custom_eucast_rules.html | 2 +- reference/custom_mdro_guideline.html | 2 +- reference/dosage.html | 2 +- reference/esbl_isolates.html | 112 +++++++ reference/esbl_isolates.md | 58 ++++ reference/eucast_rules.html | 2 +- reference/example_isolates.html | 2 +- reference/example_isolates_unclean.html | 2 +- reference/export_ncbi_biosample.html | 2 +- reference/first_isolate.html | 2 +- reference/g.test.html | 2 +- reference/get_episode.html | 116 +++---- reference/get_episode.md | 114 +++---- reference/ggplot_pca.html | 2 +- reference/ggplot_sir.html | 2 +- reference/guess_ab_col.html | 2 +- reference/index.html | 9 +- reference/index.md | 2 + reference/intrinsic_resistant.html | 2 +- reference/italicise_taxonomy.html | 2 +- reference/join.html | 2 +- reference/key_antimicrobials.html | 2 +- reference/kurtosis.html | 6 +- reference/kurtosis.md | 4 +- reference/like.html | 4 +- reference/like.md | 2 + reference/mdro.html | 2 +- reference/mean_amr_distance.html | 88 ++--- reference/mean_amr_distance.md | 86 ++--- reference/microorganisms.codes.html | 2 +- reference/microorganisms.groups.html | 2 +- reference/microorganisms.html | 2 +- reference/mo_matching_score.html | 2 +- reference/mo_property.html | 2 +- reference/mo_source.html | 2 +- reference/pca.html | 2 +- reference/plot-1.png | Bin 35350 -> 37129 bytes reference/plot-10.png | Bin 70715 -> 74261 bytes reference/plot-12.png | Bin 86421 -> 90034 bytes reference/plot-13.png | Bin 85572 -> 81952 bytes reference/plot-14.png | Bin 38976 -> 38850 bytes reference/plot-15.png | Bin 55162 -> 55112 bytes reference/plot-16.png | Bin 37343 -> 35083 bytes reference/plot-17.png | Bin 53379 -> 51225 bytes reference/plot-18.png | Bin 51169 -> 49038 bytes reference/plot-19.png | Bin 43411 -> 44054 bytes reference/plot-2.png | Bin 59674 -> 62752 bytes reference/plot-3.png | Bin 58827 -> 61489 bytes reference/plot-4.png | Bin 56679 -> 56174 bytes reference/plot-9.png | Bin 92180 -> 83411 bytes reference/plot.html | 2 +- reference/proportion.html | 2 +- reference/random-1.png | Bin 32918 -> 33633 bytes reference/random-2.png | Bin 48276 -> 49329 bytes reference/random.html | 36 +-- reference/random.md | 34 +- reference/resistance_predict.html | 2 +- reference/skewness.html | 4 +- reference/skewness.md | 2 +- reference/step_mic_log2.html | 8 + reference/step_sir_numeric.html | 8 + reference/top_n_microorganisms.html | 2 +- reference/translate.html | 2 +- search.json | 2 +- sitemap.xml | 2 + 128 files changed, 1616 insertions(+), 440 deletions(-) create mode 100644 articles/AMR_with_tidymodels_files/figure-html/unnamed-chunk-21-1.png create mode 100644 articles/AMR_with_tidymodels_files/figure-html/unnamed-chunk-22-1.png create mode 100644 reference/all_disk.html create mode 100644 reference/all_disk_predictors.html create mode 100644 reference/all_mic.html create mode 100644 reference/all_mic_predictors.html create mode 100644 reference/all_sir.html create mode 100644 reference/all_sir_predictors.html create mode 100644 reference/amr-tidymodels.html create mode 100644 reference/amr-tidymodels.md create mode 100644 reference/esbl_isolates.html create mode 100644 reference/esbl_isolates.md create mode 100644 reference/step_mic_log2.html create mode 100644 reference/step_sir_numeric.html diff --git a/404.html b/404.html index 3f7e7ffa8..2d4812c11 100644 --- a/404.html +++ b/404.html @@ -31,7 +31,7 @@ AMR (for R) - 3.0.1.9004 + 3.0.1.9007
+generated on 22 December 2025.tibble, i.e., using
provides an extension to that function:
autoplot(combined_ab)

To calculate antimicrobial resistance in a more sensible way, also by
correcting for too few results, we use the resistance() and
susceptibility() functions.


This plot provides an intuitive way to assess susceptibility patterns across different groups while incorporating clinical breakpoints.
For a more straightforward and less manual approach, @@ -1357,12 +1357,12 @@ extended by this package to directly plot MIC and disk diffusion values:
autoplot(mic_values)

# by providing `mo` and `ab`, colours will indicate the SIR interpretation:
autoplot(mic_values, mo = "K. pneumoniae", ab = "cipro", guideline = "EUCAST 2024")

Author: Dr. Matthijs Berends, 23rd Feb 2025
diff --git a/articles/AMR.md b/articles/AMR.md index 041b17c84..6a3f227f6 100644 --- a/articles/AMR.md +++ b/articles/AMR.md @@ -3,7 +3,7 @@ **Note:** values on this page will change with every website update since they are based on randomly created values and the page was written in [R Markdown](https://rmarkdown.rstudio.com/). However, the -methodology remains unchanged. This page was generated on 15 December +methodology remains unchanged. This page was generated on 22 December 2025. ## Introduction @@ -52,9 +52,9 @@ structure of your data generally look like this: | date | patient_id | mo | AMX | CIP | |:----------:|:----------:|:----------------:|:---:|:---:| -| 2025-12-15 | abcd | Escherichia coli | S | S | -| 2025-12-15 | abcd | Escherichia coli | S | R | -| 2025-12-15 | efgh | Escherichia coli | R | S | +| 2025-12-22 | abcd | Escherichia coli | S | S | +| 2025-12-22 | abcd | Escherichia coli | S | R | +| 2025-12-22 | efgh | Escherichia coli | R | S | ### Needed R packages diff --git a/articles/AMR_for_Python.html b/articles/AMR_for_Python.html index d19f090a3..a40a28e66 100644 --- a/articles/AMR_for_Python.html +++ b/articles/AMR_for_Python.html @@ -30,7 +30,7 @@ AMR (for R) - 3.0.1.9004 + 3.0.1.9007-@@ -413,7 +413,7 @@ ROC curve looks like this:This page was entirely written by our AMR for R Assistant, a ChatGPT +
This page was almost entirely written by our AMR for R Assistant, a ChatGPT manually-trained model able to answer any question about the
AMRpackage.
predictions %>%
roc_curve(mo, `.pred_Gram-negative`) %>%
autoplot()
-

<mic> columns directly in tidymodels
workflows using AMR-specific recipe steps. This includes a
transformation to log2 scale using
-step_mic_log2(), which prepares MIC values for use in
+step_mic_log2(), which prepares MIC values for use in
classification models.
This approach and idea formed the basis for the publication DOI: 10.3389/fmicb.2025.1582703 to model the presence of -extended-spectrum beta-lactamases (ESBL).
--- +extended-spectrum beta-lactamases (ESBL) based on MIC values. +NOTE: THIS EXAMPLE WILL BE AVAILABLE IN A NEXT VERSION (#TODO)
-The new AMR package version will contain new tidymodels selectors -such as
-step_mic_log2().
Our goal is to:
+tidymodels
+recipe.We use the esbl_isolates dataset that comes with the AMR
+package.
+# Load required libraries
+library(AMR)
+library(tidymodels)
+
+# View the esbl_isolates data set
+esbl_isolates
+#> # A tibble: 500 × 19
+#> esbl genus AMC AMP TZP CXM FOX CTX CAZ GEN TOB TMP SXT
+#> <lgl> <chr> <mic> <mic> <mic> <mic> <mic> <mic> <mic> <mic> <mic> <mic> <mic>
+#> 1 FALSE Esch… 32 32 4 64 64 8.00 8.00 1 1 16.0 20
+#> 2 FALSE Esch… 32 32 4 64 64 4.00 8.00 1 1 16.0 320
+#> 3 FALSE Esch… 4 2 64 8 4 8.00 0.12 16 16 0.5 20
+#> 4 FALSE Kleb… 32 32 16 64 64 8.00 8.00 1 1 0.5 20
+#> 5 FALSE Esch… 32 32 4 4 4 0.25 2.00 1 1 16.0 320
+#> 6 FALSE Citr… 32 32 16 64 64 64.00 32.00 1 1 0.5 20
+#> 7 FALSE Morg… 32 32 4 64 64 16.00 2.00 1 1 0.5 20
+#> 8 FALSE Prot… 16 32 4 1 4 8.00 0.12 1 1 16.0 320
+#> 9 FALSE Ente… 32 32 8 64 64 32.00 4.00 1 1 0.5 20
+#> 10 FALSE Citr… 32 32 32 64 64 8.00 64.00 1 1 16.0 320
+#> # ℹ 490 more rows
+#> # ℹ 6 more variables: NIT <mic>, FOS <mic>, CIP <mic>, IPM <mic>, MEM <mic>,
+#> # COL <mic>
+
+# Prepare a binary outcome and convert to ordered factor
+data <- esbl_isolates %>%
+ mutate(esbl = factor(esbl, levels = c(FALSE, TRUE), ordered = TRUE))Explanation:
+esbl_isolates: Contains MIC test results and ESBL
+status for each isolate.mutate(esbl = ...): Converts the target column to an
+ordered factor for classification.We use our step_mic_log2() function to log2-transform
+MIC values, ensuring that MICs are numeric and properly scaled. All MIC
+predictors can easily and agnostically selected using the new
+all_mic_predictors():
+# Split into training and testing sets
+set.seed(123)
+split <- initial_split(data)
+training_data <- training(split)
+testing_data <- testing(split)
+
+# Define the recipe
+mic_recipe <- recipe(esbl ~ ., data = training_data) %>%
+ remove_role(genus, old_role = "predictor") %>% # Remove non-informative variable
+ step_mic_log2(all_mic_predictors()) #%>% # Log2 transform all MIC predictors
+ # prep()
+
+mic_recipe
+#>
+#> ── Recipe ──────────────────────────────────────────────────────────────────────
+#>
+#> ── Inputs
+#> Number of variables by role
+#> outcome: 1
+#> predictor: 17
+#> undeclared role: 1
+#>
+#> ── Operations
+#> • Log2 transformation of MIC columns: all_mic_predictors()Explanation:
+remove_role(): Removes irrelevant variables like
+genus.step_mic_log2(): Applies
+log2(as.numeric(...)) to all MIC predictors in one go.prep(): Finalises the recipe based on training
+data.We use a simple logistic regression to model ESBL presence, though
+recent models such as xgboost (link
+to parsnip manual) could be much more precise.
+# Define the model
+model <- logistic_reg(mode = "classification") %>%
+ set_engine("glm")
+
+model
+#> Logistic Regression Model Specification (classification)
+#>
+#> Computational engine: glmExplanation:
+logistic_reg(): Specifies a binary classification
+model.set_engine("glm"): Uses the base R GLM engine.
+# Create workflow
+workflow_model <- workflow() %>%
+ add_recipe(mic_recipe) %>%
+ add_model(model)
+
+workflow_model
+#> ══ Workflow ════════════════════════════════════════════════════════════════════
+#> Preprocessor: Recipe
+#> Model: logistic_reg()
+#>
+#> ── Preprocessor ────────────────────────────────────────────────────────────────
+#> 1 Recipe Step
+#>
+#> • step_mic_log2()
+#>
+#> ── Model ───────────────────────────────────────────────────────────────────────
+#> Logistic Regression Model Specification (classification)
+#>
+#> Computational engine: glm
+# Fit the model
+fitted <- fit(workflow_model, training_data)
+
+# Generate predictions
+predictions <- predict(fitted, testing_data) %>%
+ bind_cols(predict(fitted, testing_data, type = "prob")) %>% # add probabilities
+ bind_cols(testing_data)
+
+# Evaluate model performance
+our_metrics <- metric_set(accuracy, recall, precision, sensitivity, specificity, ppv, npv)
+metrics <- our_metrics(predictions, truth = esbl, estimate = .pred_class)
+
+metrics
+#> # A tibble: 7 × 3
+#> .metric .estimator .estimate
+#> <chr> <chr> <dbl>
+#> 1 accuracy binary 0.92
+#> 2 recall binary 0.921
+#> 3 precision binary 0.921
+#> 4 sensitivity binary 0.921
+#> 5 specificity binary 0.919
+#> 6 ppv binary 0.921
+#> 7 npv binary 0.919Explanation:
+fit(): Trains the model on the processed training
+data.predict(): Produces predictions for unseen test
+data.metric_set(): Allows evaluating multiple classification
+metrics. This will make our_metrics to become a function
+that we can use to check the predictions with.It appears we can predict ESBL gene presence with a positive +predictive value (PPV) of 92.1% and a negative predictive value (NPV) of +91.9 using a simplistic logistic regression model.
+We can visualise predictions by comparing predicted and actual ESBL +status.
+
+library(ggplot2)
+
+ggplot(predictions, aes(x = esbl, fill = .pred_class)) +
+ geom_bar(position = "stack") +
+ labs(title = "Predicted vs Actual ESBL Status",
+ x = "Actual ESBL",
+ y = "Count") +
+ theme_minimal()
And plot the certainties too - how certain were the actual +predictions?
+
+predictions %>%
+ mutate(certainty = ifelse(.pred_class == "FALSE",
+ .pred_FALSE,
+ .pred_TRUE),
+ correct = ifelse(esbl == .pred_class, "Right", "Wrong")) %>%
+ ggplot(aes(x = seq_len(nrow(predictions)),
+ y = certainty,
+ colour = correct)) +
+ scale_colour_manual(values = c(Right = "green3", Wrong = "red2"),
+ name = "Correct?") +
+ geom_point() +
+ scale_y_continuous(labels = function(x) paste0(x * 100, "%"),
+ limits = c(0.5, 1)) +
+ theme_minimal()
+### Conclusion
In this example, we showcased how the new AMR-specific
+recipe steps simplify working with <mic> columns in
+tidymodels. The step_mic_log2() transformation
+converts ordered MICs to log2-transformed numerics, improving
+compatibility with classification models.
This pipeline enables realistic, reproducible, and interpretable +modelling of antimicrobial resistance data.
In this third example, we aim to predict antimicrobial resistance
(AMR) trends over time using tidymodels. We will model
@@ -461,8 +698,8 @@ amoxicillin-clavulanic acid AMC, and ciprofloxacin
CIP), based on historical data grouped by year and hospital
ward.
We start by transforming the example_isolates dataset
into a structured time-series format.
+# Load required libraries library(AMR) library(tidymodels) @@ -525,15 +762,15 @@ rates by year and ward.--Defining the Workflow +
+Defining the Workflow
We now define the modelling workflow, which consists of a preprocessing step, a model specification, and the fitting process.
-1. Preprocessing with a Recipe +
1. Preprocessing with a Recipe
-+# Define the recipe resistance_recipe_time <- recipe(res_AMX ~ year + gramstain, data = data_time) %>% step_dummy(gramstain, one_hot = TRUE) %>% # Convert categorical to numerical @@ -566,10 +803,10 @@ variable.-2. Specifying the Model +
2. Specifying the Model
We use a linear regression model to predict resistance trends.
-+# Define the linear regression model lm_model <- linear_reg() %>% set_engine("lm") # Use linear regression @@ -588,10 +825,10 @@ engine.-3. Building the Workflow +
3. Building the Workflow
We combine the preprocessing recipe and model into a workflow.
-+--Training and Evaluating the Model +
+Training and Evaluating the Model
We split the data into training and testing sets, fit the model, and evaluate performance.
-+# Split the data set.seed(123) data_split_time <- initial_split(data_time, prop = 0.8) @@ -662,11 +899,11 @@ sets.--Visualising Predictions +
+Visualising Predictions
We plot resistance trends over time for amoxicillin.
-+-library(ggplot2) # Plot actual vs predicted resistance over time @@ -677,10 +914,10 @@ sets. x = "Year", y = "Resistance Proportion") + theme_minimal()+
Additionally, we can visualise resistance trends in
-ggplot2and directly add linear models there:+-ggplot(data_time, aes(x = year, y = res_AMX, color = gramstain)) + geom_line() + labs(title = "AMX Resistance Trends", @@ -691,7 +928,7 @@ sets. formula = y ~ x, alpha = 0.25) + theme_minimal()+
diff --git a/articles/AMR_with_tidymodels.md b/articles/AMR_with_tidymodels.md index 4db5a2065..747801c2f 100644 --- a/articles/AMR_with_tidymodels.md +++ b/articles/AMR_with_tidymodels.md @@ -1,6 +1,6 @@ # AMR with tidymodels -> This page was entirely written by our [AMR for R +> This page was almost entirely written by our [AMR for R > Assistant](https://chat.amr-for-r.org), a ChatGPT manually-trained > model able to answer any question about the `AMR` package. @@ -351,21 +351,250 @@ and reproducibly. In this second example, we demonstrate how to use `
` columns directly in `tidymodels` workflows using AMR-specific recipe steps. This -includes a transformation to `log2` scale using `step_mic_log2()`, which -prepares MIC values for use in classification models. +includes a transformation to `log2` scale using +[`step_mic_log2()`](https://amr-for-r.org/reference/amr-tidymodels.md), +which prepares MIC values for use in classification models. This approach and idea formed the basis for the publication [DOI: 10.3389/fmicb.2025.1582703](https://doi.org/10.3389/fmicb.2025.1582703) -to model the presence of extended-spectrum beta-lactamases (ESBL). +to model the presence of extended-spectrum beta-lactamases (ESBL) based +on MIC values. -> NOTE: THIS EXAMPLE WILL BE AVAILABLE IN A NEXT VERSION (#TODO) -> -> The new AMR package version will contain new tidymodels selectors such -> as `step_mic_log2()`. +### **Objective** + +Our goal is to: + +1. Use raw MIC values to predict whether a bacterial isolate produces + ESBL. +2. Apply AMR-aware preprocessing in a `tidymodels` recipe. +3. Train a classification model and evaluate its predictive + performance. + +### **Data Preparation** + +We use the `esbl_isolates` dataset that comes with the AMR package. + +``` r +# Load required libraries +library(AMR) +library(tidymodels) + +# View the esbl_isolates data set +esbl_isolates +#> # A tibble: 500 × 19 +#> esbl genus AMC AMP TZP CXM FOX CTX CAZ GEN TOB TMP SXT +#> +#> 1 FALSE Esch… 32 32 4 64 64 8.00 8.00 1 1 16.0 20 +#> 2 FALSE Esch… 32 32 4 64 64 4.00 8.00 1 1 16.0 320 +#> 3 FALSE Esch… 4 2 64 8 4 8.00 0.12 16 16 0.5 20 +#> 4 FALSE Kleb… 32 32 16 64 64 8.00 8.00 1 1 0.5 20 +#> 5 FALSE Esch… 32 32 4 4 4 0.25 2.00 1 1 16.0 320 +#> 6 FALSE Citr… 32 32 16 64 64 64.00 32.00 1 1 0.5 20 +#> 7 FALSE Morg… 32 32 4 64 64 16.00 2.00 1 1 0.5 20 +#> 8 FALSE Prot… 16 32 4 1 4 8.00 0.12 1 1 16.0 320 +#> 9 FALSE Ente… 32 32 8 64 64 32.00 4.00 1 1 0.5 20 +#> 10 FALSE Citr… 32 32 32 64 64 8.00 64.00 1 1 16.0 320 +#> # ℹ 490 more rows +#> # ℹ 6 more variables: NIT , FOS , CIP , IPM , MEM , +#> # COL + +# Prepare a binary outcome and convert to ordered factor +data <- esbl_isolates %>% + mutate(esbl = factor(esbl, levels = c(FALSE, TRUE), ordered = TRUE)) +``` + +**Explanation:** + +- `esbl_isolates`: Contains MIC test results and ESBL status for each + isolate. +- `mutate(esbl = ...)`: Converts the target column to an ordered factor + for classification. + +### **Defining the Workflow** + +#### 1. Preprocessing with a Recipe + +We use our +[`step_mic_log2()`](https://amr-for-r.org/reference/amr-tidymodels.md) +function to log2-transform MIC values, ensuring that MICs are numeric +and properly scaled. All MIC predictors can easily and agnostically +selected using the new +[`all_mic_predictors()`](https://amr-for-r.org/reference/amr-tidymodels.md): + +``` r +# Split into training and testing sets +set.seed(123) +split <- initial_split(data) +training_data <- training(split) +testing_data <- testing(split) + +# Define the recipe +mic_recipe <- recipe(esbl ~ ., data = training_data) %>% + remove_role(genus, old_role = "predictor") %>% # Remove non-informative variable + step_mic_log2(all_mic_predictors()) #%>% # Log2 transform all MIC predictors + # prep() + +mic_recipe +#> +#> ── Recipe ────────────────────────────────────────────────────────────────────── +#> +#> ── Inputs +#> Number of variables by role +#> outcome: 1 +#> predictor: 17 +#> undeclared role: 1 +#> +#> ── Operations +#> • Log2 transformation of MIC columns: all_mic_predictors() +``` + +**Explanation:** + +- `remove_role()`: Removes irrelevant variables like genus. +- [`step_mic_log2()`](https://amr-for-r.org/reference/amr-tidymodels.md): + Applies `log2(as.numeric(...))` to all MIC predictors in one go. +- `prep()`: Finalises the recipe based on training data. + +#### 2. Specifying the Model + +We use a simple logistic regression to model ESBL presence, though +recent models such as xgboost ([link to `parsnip` +manual](https://parsnip.tidymodels.org/reference/details_boost_tree_xgboost.html)) +could be much more precise. + +``` r +# Define the model +model <- logistic_reg(mode = "classification") %>% + set_engine("glm") + +model +#> Logistic Regression Model Specification (classification) +#> +#> Computational engine: glm +``` + +**Explanation:** + +- `logistic_reg()`: Specifies a binary classification model. +- `set_engine("glm")`: Uses the base R GLM engine. + +#### 3. Building the Workflow + +``` r +# Create workflow +workflow_model <- workflow() %>% + add_recipe(mic_recipe) %>% + add_model(model) + +workflow_model +#> ══ Workflow ════════════════════════════════════════════════════════════════════ +#> Preprocessor: Recipe +#> Model: logistic_reg() +#> +#> ── Preprocessor ──────────────────────────────────────────────────────────────── +#> 1 Recipe Step +#> +#> • step_mic_log2() +#> +#> ── Model ─────────────────────────────────────────────────────────────────────── +#> Logistic Regression Model Specification (classification) +#> +#> Computational engine: glm +``` + +### **Training and Evaluating the Model** + +``` r +# Fit the model +fitted <- fit(workflow_model, training_data) + +# Generate predictions +predictions <- predict(fitted, testing_data) %>% + bind_cols(predict(fitted, testing_data, type = "prob")) %>% # add probabilities + bind_cols(testing_data) + +# Evaluate model performance +our_metrics <- metric_set(accuracy, recall, precision, sensitivity, specificity, ppv, npv) +metrics <- our_metrics(predictions, truth = esbl, estimate = .pred_class) + +metrics +#> # A tibble: 7 × 3 +#> .metric .estimator .estimate +#> +#> 1 accuracy binary 0.92 +#> 2 recall binary 0.921 +#> 3 precision binary 0.921 +#> 4 sensitivity binary 0.921 +#> 5 specificity binary 0.919 +#> 6 ppv binary 0.921 +#> 7 npv binary 0.919 +``` + +**Explanation:** + +- `fit()`: Trains the model on the processed training data. +- [`predict()`](https://rdrr.io/r/stats/predict.html): Produces + predictions for unseen test data. +- `metric_set()`: Allows evaluating multiple classification metrics. + This will make `our_metrics` to become a function that we can use to + check the predictions with. + +It appears we can predict ESBL gene presence with a positive predictive +value (PPV) of 92.1% and a negative predictive value (NPV) of 91.9 using +a simplistic logistic regression model. + +### **Visualising Predictions** + +We can visualise predictions by comparing predicted and actual ESBL +status. + +``` r +library(ggplot2) + +ggplot(predictions, aes(x = esbl, fill = .pred_class)) + + geom_bar(position = "stack") + + labs(title = "Predicted vs Actual ESBL Status", + x = "Actual ESBL", + y = "Count") + + theme_minimal() +``` + + + +And plot the certainties too - how certain were the actual predictions? + +``` r +predictions %>% + mutate(certainty = ifelse(.pred_class == "FALSE", + .pred_FALSE, + .pred_TRUE), + correct = ifelse(esbl == .pred_class, "Right", "Wrong")) %>% + ggplot(aes(x = seq_len(nrow(predictions)), + y = certainty, + colour = correct)) + + scale_colour_manual(values = c(Right = "green3", Wrong = "red2"), + name = "Correct?") + + geom_point() + + scale_y_continuous(labels = function(x) paste0(x * 100, "%"), + limits = c(0.5, 1)) + + theme_minimal() +``` + + \### +**Conclusion** + +In this example, we showcased how the new `AMR`-specific recipe steps +simplify working with ` ` columns in `tidymodels`. The +[`step_mic_log2()`](https://amr-for-r.org/reference/amr-tidymodels.md) +transformation converts ordered MICs to log2-transformed numerics, +improving compatibility with classification models. + +This pipeline enables realistic, reproducible, and interpretable +modelling of antimicrobial resistance data. ------------------------------------------------------------------------ -## Example 2: Predicting AMR Over Time +## Example 3: Predicting AMR Over Time In this third example, we aim to predict antimicrobial resistance (AMR) trends over time using `tidymodels`. We will model resistance to three @@ -573,7 +802,7 @@ ggplot(predictions_time, aes(x = year)) + theme_minimal() ``` - + Additionally, we can visualise resistance trends in `ggplot2` and directly add linear models there: @@ -591,7 +820,7 @@ ggplot(data_time, aes(x = year, y = res_AMX, color = gramstain)) + theme_minimal() ``` - + ### **Conclusion** diff --git a/articles/AMR_with_tidymodels_files/figure-html/unnamed-chunk-14-1.png b/articles/AMR_with_tidymodels_files/figure-html/unnamed-chunk-14-1.png index a4c4c0185ab5580381ce98d6f35bbe1b330c23a1..09e769ea739a5347984a30ec30823be2bc27b11c 100644 GIT binary patch literal 32166 zcmeFa2UwM9x+S{RQp-}IC?mO4)KUagBu5oRL_sA ^gnbR}pJoh$FcT2 `Qo}JPw&x>4nZRfxR zZVkQgogYuT9B`i47L=eK{Y3Xju0zVhck;gPWVw0H@w`=xZaUt%`~1oin@?m{91Kiz zb$u>c`D%lW(IWw4(L6oVu#8FRx!l5Dn}V+{RiPqt&dQnrhMJ7qlNI3=uwTLW_Tiot zM;PBId>_g9$*E(MjpPTiKdrpV_=WF}va859_y3@ HIzN;bsQh0W_k*BBpyzcL~ z#7Bcft&IKg@$q9>2g+N_rsyfIQZ%EM^lR+dWoK0$8?2Z5&4vRPJMB)%@vtadm{foK zsU>S*V4%q`P`C4`pVD3K`A=&{->etdocrYq8$0`W*5nZpk>1wtFRa&i-&ET&H&RF& zz^LZlsB3K8mYe7s*vT={N6(CE9m=A0d^SkDn7VV%+2GCFbgm!euztVeLyCT3A6{*i z)oy?2`lnZ-UH1e#b7>0}lGC4Vjm{3H$nyubehN-VNHA#Bz2W7jB)-ogr~la_5lg+m z;wztC{kD3fu|3DB4fouq>9{4=tx}UeaPZ&;o#($EJ#g{)&wG@^IW%;vPH;GUd0 y%9R^;`{C%)3cOlDU>>U_U!0e?!|)z z^d!p@Ha6qpt%HMuU12vm?({~uN>itDY272-V%AsMtV%f9b;jps#tjzdXAU`xeR(-i zt7tI&?X%TX`wjU*>VmkllIg6aiOIk>s~qikE6ib}vDNB{Jw`nhL8-mrPQ`;Mg?e8v z2=nfe_pZ?2HytCh5ZBcG{DF>5rO;rTh*8C(ovJT_yPo%6Gcmav -1ah%a|e0ExhWRb06AAvt@ce0T_x7ly##V0&GKC>7x{m$PqrEaqVub}ui*qIK?riEx%IdgV zTwMIV+xkOW8wZ_EPrW(Xd2_Pa*x+kZ>LKed@0&~#l7wIO= rw`P>q(8NJy0?BMg>vr9%08|qdCu*wcVE1C(f2V%nZvQ~@gala zd!kcqHsh^&)R}H|?vCGv>&JK(1N9uQIgfhkSESHvs-=p4xnoh=Flerkw=mg?pU&?r zT sfn6L!sc3`b`6>{<~Q2yG!AHICJrheeBdQ!fuY|VL2=x4UR}Lm zV3m{HyH(7R=boBGrV9xP6_KIVm+1|)>6{<0u1?X%dy}v7V1gg$C&$O%4YA0HYkf16 z{0lFyC)s34!%m|`+dNgz&N;TcL`=9JpzIuSpD(lNNxdqEvh>UqmW1DG>F+ivzbo_S z-L> %Wwqh zSSx(Z9Vs}kt h|rvE^00cs1_lT9mmC+xltP4) zJ}vZAhHR6W|IBRg&Vwbj%Uj|knVsCBOsl3#?nNiI>2BV%SLxmjnu`dnAUj)ZNfh7S zSX?yl7Te?MTHgBVw^b5}k7InycT`EweVw `T{|@nySnov#*xSMah>lX z%m2}lYZpj#6g?esJD}I}u1ykeSy`D@($sK!?kWHDl-!ae3H=0-3DM#HUQ^|pE~_aN z;p40)Y|8nvuCP2fAvc-oik^ktsB<3KdHV zKknk<@_J$GplC(6by8-EPWFqpT7d%k9VQWU#JjTL?A~yDePgW-6I0W)JDc{}Pfv$Q zm8}2ZkN7j+BT{&cKEIV;r-^SN`GbG(HhdTVtWn=JUwdwZsa?vVeN?Mmx5P?WTHoo- zATNdT+`$@w_eyt}|LAm=Pj4f$%=|Zcrfc70_sb*sQ{I2B- Z%Xe}_ZiydBYELmgw$uzGlp;eST~wo?ULNy7!;tM zc#(zNh5o{T2K(a|6Nsd3CJT|bnC`}@#GEuRFnF;4?n?yo@p7lHsqzV3SuuTgy3_|S zEDnr?rM$B5tXzPhRey9~W{xEi*I>KxMBj%GH8nqS&%BrKd?3$tXNu-3W1X#YMRTiW zK=-PztJiORhaa +tW~IXgANeWSy{I1iiqLtWiw{E*y|kIdptj_a>h%q+SyakiMm zyJajaP8Iqf`3e?NNpy`^oQS!YZEc9n5}T0VNs<5wtsWlJBTI`TRU1#Q#rDrqs P*RNi8)&J0{`>>(1e+?cy{=10k->$9-DG(U z)}6a+fZwqM>e_2kkpL`5u16dw?`$zmsZ7ZVExYVxnvyRpGcty~&RV!IWNGmF_toUV z@eE6O9XGqYNT7EfGS&B#cA2$(D`+w_kdRU(kmVfCk`N;@-O^YPpwBI6bjE#w{zun! zgXyLc>8%DO-d>G*PJ9Suy8_EkV5j8G4d)&*EPE*W?bWJr^J ?Y3@ak>_||xfG}DVv?^vV{Tzlr6jX3;XL aye~)R}m)?`fWr{ueesMCZ&@O(-3queP&7PGUx=S;l zM|4=>Ut+C(vfJ>E#Ze#E#PKdUT=Tq&%BHnkH-DYSk1Dc~kO20nJd- =Y|aB?e-nF5^ZIAz>;_6&^CLu;P99%#mYT{NB6* zfVL2U6}HS5PJJT3zlq@T!z{&Nai;gic1be+l>+(zZL3%N6Qr=7|K-nxi-4=iAD?wQ z7Y6E69o+T1laiCYN1S^lIHm0$59bUf&yPL7^j6Eo+|giPeX4F$_xwkh*$+M~=2<57 z@h_2f#s?$j+Im~eZhTEG=?Qe5Dc8>oj&e4*3fRnUnRlpA+N3VlzBMy6*r4Lkp`nJB zP2O+AuXyrhzF+&zb1UCnteGv@Plkcqwvug;_wCL4Q3Q%2V3e&0P9}8?4Vlf07!of) zh+WUlhBORiNG?uyrM6n+77?fjaMIr4dSgJLtARD7(@N)SqXvcY>-ZkG;m;&S-dfA- zZRtAKI*R8k)?b=!{5>U-L)h%1ySWzizRc*mP3w~rx|x5j3X`}IHpG|WF?2O~K B;xThZ^Kg7Z za+!b+o6!ErHk;~~lP#uQ0 |yE} z@%Oy!t=Jl-wv7 z4 R5xIk~zrU#)O z`eci}$RFE55OAbDXX%T?`t-Hj3w`pr(X^`lMXBa-$`R5@)Kgy<=SD2k+U**31NFJ2 z9Bp$KT;{vDeX#exq) Lhf&n$g#+rr$G&w7EpgIq|nSaSo F_k01Xcl)`!SSvr3Bm5993d&83T5(qrVhWxx2#PK8a9YNmtVQ9u xxxRiC2zD@Clm-b`fqOO;McNb>Co|tufS0g2NSN3Uqyh(nmO}5Tr zS)E5c_Y;j|9adhAt3fc_0L7&R=+ z+X=}z`wQl~1uTEsp_6Kk0ki^iE5=Mk6po _ z?feu_TSiNVb-@58_j%;cc{w@aBr_5We?(Zg`1jT8FOPjG9sN_ldB>80C%5yrqoIxi zaibq27SpxEOIj|KfBXElai(mcC2MKEdZ{AI5}OssEOQ`gFNeFXTHpM0fx>xf9T$52 z3_Z$Qd_NaTTLK0T=od%^hlBt_WX!6|m;Y#GqpGLJrJ?6wNX^gA&Tj8F%^4t|K7kI@ zf5UXC=)QHEFdZ{IF1D?Uz6Hz?C7+cSwIpzlK;a@%lf9!}-GTDUh<<|;t=2ie0mf}s ztq!p)Xg04-==RA^;=F6IAzD1slvhB&lD=gLt4OLa)KF8$X((fcp5olit2^Kt6J~!G zDellPfG)vp+>77bXNH#O`b%3z3YVzc5|*+uQaY--tp}aEsY9(T8v2=ZOSP|E&-woR zL+#Hh_W2On{GP&jpjUpfQ$#=ivFS44*`1b_mR|$}^!IwWc6o`2Yg}K4*qg7Flojff zCt;Rav^A-rw>pBBw6IMv-fFP4#Og+PifQY`loV9lEBh+ju=hjssq>>Hxk)q<2n*+t zfw!esw`knA@OXV|ZExTRZrEZ_ $O0rlRthxFk=D+NnnK{1%U|RCzgy+u7bmuR8 zt7ekpk<`oia}O|y_eIXTR7;Lmtf9{U`4yw?d-*uJ2+z-AnNL?wm~(t%brA^zNPdQX zEcqS3t)v!LW0XAdYuQq?VqmfFZp9x4avvs1tugKC9^wbvVVP0TQ`T@+*SI99#^#Cv zM~T#D=b=+~Nv?4Fe#L~*$a?+hV^jwq@WBd$RyE@=J9X*|vftphACi!wr;$6``FuE8 z$X@RbT>9oN^G*g(W#d4KVa@qIwHsvqS^ z^yk7n&@mea5)2Qv#VAKyy?XVR=^yB1$0sIMjL@vh9(aUXahy!&N(qp;*AyP0k({Dj zp0GZXyy+V_1qRRdt !d3&i?2Enyu)~pX+nmXcoCc0s4!rv_ *C&F npsDl zLvy@Z!q|{{l9oRo%JdLXtINW+eKiMmzF4tpO?vCdORKIimy>e#AWRIgj?WZSBcy*t zQC&{R1NEVXHk4E$3wqY2yJv(|VwB9MMhPxcXHWvPh2a}%KzoK8H*TD ((Et(sYCHd4(iq8m?C@X4C?HW>q}T%&U1oQ zqPs#48=lU*`r*lZ;R*i0@($Of1v5a%W=!7)=hooh;6%_U<#yGN4n@_!%mZ!-8}2IF zrf*hX($Y(CNn`ToM+V-dJyl^L*m8!NnX@;+;3(NQXc}iY X#C2(|olVwQGhhMbu4PPw ziuP-LtWy*QX-Wi|C%$-bH~|}ya06$lW+LxMdDLT|9CSGPt&8>=p0Mn*!AGv$GLgnZ zjJs@PI}%&IkiNm3q{fuAe54jo%NDPFTt1!^NfN2iii(Td*NWj@KRm^&KXW=0l~;G8 z=N4IcIcnYy`J8};gA>h%Pni!kjL8_b O%4@caPmyd}X*TTX#0=l$eFC znEVCK5~*%yz6MflzG8d!>F1q0N$q~|<@HPVwjX-($)yTK?# ?Twxq`Yu9iHnOE3U8t+8OP`&cVngi>Ss^Ml^$^xWOIsF6 z$lG*nKZs9ZHZo>+6iljWXp}51(3Xm>#e}KX7?AxyDE#! LwVBDkv6KcJhhFx|_ zz+49kp}~r&c7T0};g?ZwM~A>3lZhuh-0uT%sO4A%jotx2&@Q!tiI=7>jz`=ux$F0^ z;hx6htjS_KmzEH=UW|gLD}H13<$=7#^-6OoLW+}|P3n5&t$Fi;Gy~r)({CNaGIspy zoy{nP((4kMR@c}NVwr%PcSyOcg-Z(~Ah20SzxXK^BeX?fz9)fjMFD>d0G1A68_!F= z8&pBkr_FUtb)o>cr)`nFn}{bMnC@V7rt4y)w~$dJ%tt2b5R1771sOvHbHk&Jg^NOZ zH$VURa-?9cbF_rprw|Jx6 nNsCq50+gGb0ey;sG@%^)WIW>(j#zAy!)ZbSb1e- gwxHjCAB15Lyt!A#xj~3kta5Ne8>RiT+Ip8kQT_j{I_) znVSntgc$)S?X%n4_t9V4b#o}#aZEiNw=*atNHbkEAUfxdb$}@px60ssqU0OO{~>Yj zAD|B|UqUYB@-~WWbv>vsR8TA|=XG^C5pYi=e^2RS!UhfC)85L$lJ7{r3)r?(<2%a3 z{m>qV%3d76*4?%9325^7^%P3`wMr*RitOoUpBPX5cL|jLuxI!W$)x`Yckx6cb-f#% z^#b)|sv^aW%fQ6K8Q(zF+^q4B5PtuiC;EWMgp4)wFQ03;{JE#zZ28|%m;ap)`TGUx zKDDnaFKFi7w33{tIZni-ci<%qAo+L_P=9*^>rW*4=Fah C|@kSmJ#pGX*LZY43L4b}WmX3)V)$0i0cEGDNCT;Kf7 z3m|=CxNW*vq<|$`$0E!efk1;4K3MwgN%R-g<7L&q*sr717@Vo}60l#_UW}EUu6}xC zoWkedwxy=4#K#A8^hs3Wou>M8T146=v?0-vi`gyTJyq~)X|rs8VR*=Kq7TBT6_R5~ zka0LGkmo4s)*_)solQh{ou4j|@%|7cZ~4XeJMsw6ukDW$i=;X9hHaOyH {VPRn*aW*+EAB2e2n{|8T z LPX$ ^9=g=G{d$XwQ+ zyonOx;~TVUc43M}$OXI&q(~kV^F!46=|@sd_F&nHA>0uGorvSfX(K41cJ90kI@1gD zDm+KK |9b@2zJCVpVsoD^hAlOJfQ;y(5&8p>$ z>}{DbvX *p^+%q!% zXF^g^W$zK$YCP*i@V+A*$Oh9u-& S_H&l3qP^DH{HvF@RfwPOy2!@w-XNGVNql|29aaLWHs)#ryYK-b zpAeS63-!`HB9qJv tAOe_km|(I=#mYnBF_gzGdIe#f4jcm}*1wNtiS>18O@D zvYCa&GH>)`$ei@T#78W*>Cf&r6!XbjDbdMz5DyPXnS48mWu&fW5@7$N+&d&`|A;BE z%k;YKZ{3-FJUm9bN>b7YdM2#(&YjW={mM5?E0-@4|8yl{g0y&M(`8S9`n{K7L6~s} zAq?aPd2TO&Ccd3d>X|nuTb1pLk;4#5f+9a;(e`qFGbbnmB^`%ue _wu3rh4`%k^8^LCKO+9%gz@DBu2JOX7&&ez7u(~xkW2tPS;wQ>7#(Sw%SRy zW~XLYi}+Vi9Ph n1!V1`vGjK0fYFl(21EwrpYVXMKK~IfnAhGJ4{5-M@-bS14!u zzkS|JSxkB;{m9X0ty{zCeiyFDXy4#f%Z8%x cqNu4=N3W zX%Awl${z~k*JazZ=ZweR2 Pr_$2??Q+pF`FJzju01&7m(>wA;zwJc-J@lcLR7*4}t#_ z1ur9RmJ4UWcF^m1rzp@_7kDL4c(96L?_@(srcErOqg~ufH+QKrtjg!uP7Ax~6*xPz z!8v0EEv5t&nYh`~-(QmaF~IOX3%l%Qm!;t%1gjF4DJqzxEb{ `3 zyLEd*e`HBWiDwv~BMo-5$}SCAx_ZV$P{sKR=f`5>;`*O2)J7{B)W@sA%{pEsk=5Mu z{4Eo(FEsu5xgQuM&@Y#EPwn~x1h*B$-lE8(w>ojl{8uA(D+b`xK&-I?R{`q&OX<-b zIV(Q9LyqD$`LLG8GPp!#qnJ^Frld2#+%gpoF->p)$kAZaIIpkI9d*)c|IG+y>FJ+$ zE^;2uioP+@!NNjpMj*b1*3=LBm3I>{e{h0Ip|G64;3{vX`*kHH(tTg_)Jz?WZ{uPc zYsUTSHgnkYRxt!{jl$XbzQz>&*K td z*@0!_G!UY_2~96wo%wCBLu701Si(V+5#>X~)e1Yf;@nEgLu8M$Mf? u=zemK-izS|qA8 z1Hw<@i5^KhSj)*d&wh*;?s&6&9o16Z73~2+HpfydE&5cH#CF53*@+wTB-S5za^&P7 zE=pK+`)i!U&f@@^e(2X%ZeAAz$!))SmV71It>YXixd`n~URDfYrXl-+BeAseCck`g zs-E#dW{%(0@O{M%jV9 ?f5ZDb|U@6 |y7O#3@AS@7l0fywJ=yYF0O^EngbMN_n{yXaeH?B_N0m7Dv zg=ZU g`$qGc+`{0*&5v$l|benDA>M4b_&kw#pBdp%DSnu{wXUV#p8NN}dJ=0;9NER$H zk%1ENJI*Y11X6$!K8=|6zJ%ITm7?1q+&Vk2V~{k15LS+SAa!9j8X^_>OycH%Yf%K6 zLXG&6cvg2?Wn6OJ4%)id2T_Cab&lUru8L6Ab7C5Hsh+(y%$32lg3{tY%c&Pf|2};a zkvX9#J>+q~#y@ GduM z*DF)U{O&< q xUxRoeO z)?i1Hr!qG8BP^F8)ireb)pT2n$#dG(Ij*u+Y_YcB`<@X)YM6AvYh1f}^*uaXp>UBr zRo!n0YBLCC*)>cYkG?DzZYP#|^%R?#?!XwQsbRvmf)5OPcslxFc{d#WuCW~Bq-O*! zQYGJ~8Yz0J~ref)O^&KL692Fvx aJ!!lQ6OUq1qT ztNL)Z^UN4gf5iGCZ;gTJF@h*xKP{YO2X698QW>ra-1=2aWQ`o Ptj>dD&s{a-+$CL$p#BChY0!5qApnGG{Yzm+6_^OS<26a?#e zKr21gIt-Wn!t6SI9O3$T!=@&4v8=5JULVahTE|40mQcJ-k?l2H$E2?5(tnSK7$A95 z9qf436W{-~mg^Dm^p?(*n@tS0-Uw@S0CF4u;6t?yo07u%5CkPkd{N}b9}_fEw)*h; zpB5W_*+m|+$AEk8q8?grgeI9m8LB)xqu?tEkj5%`^P5&941rZ}6Z5XfX;Hi$3UgdG zf{q^#7PBsY!E~pWxT}lebu*6(aSusL0dd@J7hY_C*cmRXsXnpygFfo{5;Qc(MUG8W~H>WRW kcfev{5i4r=Mt4c-WE(33G7h- z@0Z@N2s-l_EXbvEkEsUf-ECSwGJ519IoXJPV~!aTdD*03wPadVmy%fbL-iDxY(vW& zt6=jZo9}@|dybkk^wQe8x`)6-i1 c@EwE#4aCz7{GoG7z}8)PXK(l;5~dIk{725iS}#2wRL$ccQz3xp;AImM9DMlF zn?HC;-#^$Th<=Q=>u)zY48+A8h8ID7q&2|C^s!>nT1Mt>$RtoSr?8+v8hmRtNcC|f z_@wcdKF(iuCFvQ{MGontUOoXPIQ6w)GM73rN|#N>?>^8F4I4ZbhjM+yCzrvbto^O4 z)@+C!$k4daY#68({vGW{%)==IgDy6Gc5uqDycg=&)vIMAoFB%DEh```H)w0IlAg-0 z?nZ|jR*PwQc1XzHzlOBse#{M#FOSs9g%TCf_qL|GF4)T@A$w=IlAg=$C*jlrY*dl` z(pg3rtqLsrx5TFglv0MR8Y+NIr3vPuV75NR2)z&QQ7UNBZAA92V3a5=k3~9eM%6Dw zU)V=Xq`v9>UVX%gP&P?S)5r*~xf41z2q+LKyA1I%O*`K>Tc?T`?@9$z$_JF^3+Bhl z)e5O`s_}_KZ5gJG_h3dLrXI3kQSQX3?pG@i0Vzsbqo0KZLxd4;nZ;@6xmH>gM0Oi` zy~bXJD)GTYw6i7Lw-H(Uw;RJa<<~C|xM1jncuM;+_ci^alK&8-Z5zLoG&m5|Gd1$# zKIi0Nbwi*U-9t0gRoA!pa+}?vsW0Y5qcH?(VpRA2LcB=m(F@bHZ{7{T-VludjW-8! z_{u%e^J5GV#=n~T=BM8(tu0u-`)g~Fjz*$_@C_4ooJ@_Hv`o(<1K}BI-CX-h_#6Uw zSRwyBI}`Lmp|KzG5b2=eDMhoLAWQ^|$Y5Hb2mRnI>!HhXzE{xDITNuo6A`cHitamY zr%gq~B$f>n*_geA@` cBb1YkL$vhr0KNogSQW+A zZ$0pyIG>#dwP_}Yo>SqPO*CVMECD}+HmPXKW&{eRFB2W)talrG=Uv|9ShEP&t;Ape zAf9^lPAe<}%-=Z75 $fa_f@t>HSD6u=3Xd#%bUUVTjj5K2idKDdE7rhLTD5R*B@SriqV&cY%1cDS5IlK zsksklT(l*v0MU^cw1oniF9vE`<_p2j*Kj-UAx|k{X2V^QUQ4)Lor$ Me3(I;*`veTv!8}2S3{DcGzL2*J 0PO-+yBsgE3M9N`{ev^v2INsFAxY%xiw2$K*&yRGH;zl!W6C(KW|E=`F~SwfZx zLS?Nr>Y(C<(Iq`inaxHaXA4e3U*W>Kbw&c#={-dBQQWuc)y R1<>PIC1-1>1bCat^V52<`0uc47NI+sT#&2Ujn|eu@=XG z<9Y$R%|_X 1vIR4cF5`JUqL z%xf^5i%M>5+^Q7ajJB)@t}6bC^mC&x^@;9xeQL@w+fsj7HlbvkAEzupVpPq<9-m@U zVh{&)WeB?}8X8#&+(h9_Dlz8FN$>sw;Vn7CXgpqI(-~i~x9M~~kzv3Gk{L;tW49?8 zOzmPu6&uNUO~tJPL$$x$IQ_~iw-xMm`D8irb&>m!b+>=DVr?S*)n3~x=0DWblNtm- zfFF4 0v1pbU4+;s{qT8=<&NRhlFULLBy)~j5t5YI63=Hq z-b$%q%5Yfc?OIn;b8cM?$&=dr%#3TURj2P3HG-3JNRjcNH7nGlWT&vkS^^n5d*rI; zFJAZk%?l8pLT6l#Vym=rnHm2xcJ?QZ1k&mbH&wN=>+DBjPa^KavhFd*YA0kCPqx2o zKC$;H3s`zzKs1#DnBRRV$+#G&Z2hVUaC#xcgo}7c+po`l <&xx^ewN{FR~cmKyAr?n-2{M{R M zZJ(fZTW82KCM `p2JEmp|QECaq_4tow7g- z#J9ZX&`9k|8pPo8u_TF(v=`~-sJbwsTI4O#N?Gi~9RZ6mF`LZPxJy3-E5{gN6E`Zh zr5_JckM1sM6&E4J31S}_29Ztje-PZ#N|K}RP?BnSF-Y*bCJ^JOo)4pHI0A!lP2|yL z991wzU MX%3&=wo6c3reV?^yt*`3uN!ovwMFY|!utnZF-{^=K??#Cfm6 z7+F_vyBd&QZ^C|L1HK+c|G#iyCdQsvpwxo0b|pBt>AAG`qD3qHwjY^9%884pIXt-& z=1_z_ o~#$Vn) zPz%f26~Fvw;GX{WX!Yv)g^S;bf%hUzEn)Is5PMOED~=XW@Wp~j8kIH8ApRBr>*Lk{ zxjn>2gcf8Chr^C|(V(-h!*RXVwYv3%$D=P?%jZU$R0UR37+Gwf5n@AgO{}cQD1N%t zMS4 {_OL-KbypI21}*cpEwc^R|*DtbnS}+44fu8r=rh_r?7!8G~AbS!NzP zj^F-*)s{TT$kDPA#D3le53_%DW8+r%!^%Rhzgc&}#~<}v@{4@@^36!2X8k ZVo^temvZBO(ld8$_^hxvyv|lZ2s*BlzC*39sP#@^)^!rtKtWg zWofn_&jM{&&>x{RC&UAxtI{w^M$n>SC%2Pp%C5bRc5EI6Qs5zoTZEO+zcve!_DItH zKn_EhsSPYhFP#bnr$Czb$?Y~H7T|KNPZa~FRQgHlBR1V8f05&o@SDBB2_qI``O #|GE7NtsBkq@?rGCGsu|vix#U z{u)PE{|%)U_sYrdY*FJN8v5~| !TzvXSxb zvN6IQ-f(4|H}PgO4wIN}0mO+QAO*sb17>jy 9( zCr!L~K@Lm!A6|s`lxzkJWtm?xHPo6_WU~wony}Jv#Dre6#nr19mnd{s?o0i((e+#m zY~jWh=eUerTak^mM@CV+#x8@Zzn*uOZoJEDWHn(jsJ;Zbk~2{fN>Ub!ZxJteM#(je z)6o|eXB!I}95+xRZ?)W)X&d=PT6J&*B{Ho4j7+a*0|K4xU_(-a0fjv_8O@am4zEdj zJP}p9$8kgtPYLG@9nTV_pu@Yd!V;Vp$I1naQHsU(hz^~`GQnCmkvi#qIB%|SnGNUC zl6*|q@UGuomKRvLla&4-i}*c$-5hMYco`MVmkjFskBwt#wNfZ$m7WbOrB4E2{;h81 zDJ8Q`2-l_Al%-%&RsmuYE|3(}XM&H!S$B{glsHg;u*XN6HYR6qt)lcrihmqoiPi#S z96Dn>E2dojhpu!i@T9FT0n1nqS_TeY4QLD5Nt##P=Rfk^tv|nL`y)lzy=sD+FFHGH z?)554)5Ya2LHXf4U1Y}@!VZ!sNs4>$-wh6JJKQ;ZQ7cQLR>@j6_tund)^Z`VMlbYG zHNqp1BPftL7JaR=L&>Qb %XPm@+`;|LVGvEyquY`;%N zy>xEJ9Ac slMU(^y2}^)BKd-@m26e8KmI1C&O@gJG49yUfl=H^W_WD z`eIot#02AR*(8q8Sjzm@FF~cFkx35I!Aq9;HCSa^4l`;F%FwBhl@p2r`KrwpCMGRU zO-U)wr^l!Q+`N;{uE;^Bv8ng5 % z$|iv^h5OmSQzV-)vmSoBT>MdLyzypk05$(1kbLHT$%ineTT>VpwmkqO0EcSGL@JyI zJf)-|C1a8_dZFB@1kn;iPFfk%ExS?gFz9r35(0t)q&ypdgXD~qXfdtXZ|BShaRbWe zDlMDLXw(aVl44eedcL|^q+rymtaopi?S;RpR1-5u4fv=soSxL!k_8!o9KS%;DC1n6 zahW9>41J@-+u37w**bcIi%FFqYD@59k%bWYikfGXb_B9eOrd`@I`sQC>aBOg)RG9t z>l#Hmx=TsVeC9pIlBzogMjM5q7B||vlQ{&z2ygWv;Gjzj&heD5VD>e^SCO5@Q%X)S zA;e)?-n07NtNmSsF+X5qtBM7oz(9D~<{4_fUr3W7B=- f2%YL!`shw#2cay9 zcEZyS^1>o-v^dk7fhE(A)9J3&_tDJ9?xF c|Mwx zPG1Rh{vLvQ7`RXwn5!!R9jt2=_C|vYAxV!&bT~Gv8w6S<%&KEJhANRICJQE8ax71r zoEcg1Zgyfw^fq9o4IwT-)>&yK(bz)?;{j*=9z{tw4zBrv>go&$6-1GPlr|<_ErFD5 zgW}c*zU}y82JWDw?^2uV`VDC1O4-AGGvwF`_=1z_4T#5?xPAd@wnUKl?zV9f34M @o zD2Lw`a>f^5Md5N6c~DI-_Zo-I?LG78K1RkRt)iAiO-MF{aX1Rf3c_SRv0z-n_CkU? z4HXsiE*=Hw1f-%OjaDJ%0rj+x!`w;1o&j67G8lJC%aiDD5;&TIbTx&T--ef&9KRDX zL=E#gvFx+AH=ds!-4|Gn|7e09CdE9?*)nW bOGrBfUkpZ;qYpL;j{+!Nl|S!XyR*y% z+kQ_9UL1KB#3MGCnD)ZDyKJkE1o|@k2!u4JJCdVb{CI%0;yWKEf^s5LE`E>P8XmVC zN8<4wn&l2d+E?%`7btWNv;27)dPFZ0{wZH_DnQW&&%Zv213)7ieG+~=+w^W;^89Uv zbRCkW(25Wdfr#mMd&kg=Rxp-6fs=oT>`FLYg~QI%-@am+LPl0Qzgku%W!)LnG|Dzj z9RJ4< p~8a3qs!k;nUBAil){(dEwX$1fe8q z;z%Wv%=={mA@Z#zee(p49D4}gN=il{`XL;KG8(Nx2OFbRp&xh*WL_FMb_ PJNU z!@wP+iH68CM8BUvv4`H43Ub;4OdvM5lC1!`yG06T&N6 uLEjfYk>Ep+j1oOy2 ztrWMa#{}e>O34Ww(0O?fr=b{YN%i1_va;QQIxnj3&*O-VZkfd{8B(RTG#0up>EO^W zWXJfjJhMmtZ;lVjpM6J^WgF}34dICtLkDUafJHPc1#u}U)g)d(_9Xg&13In*0X9e- z0wV+jLmhOzBPo#}Y6GT(xKD`Zj2H(iLd66bYB{1mTb?-MDZFDoCa%aQjx*9hP0ofO zXAz>TJcVS6JaYKT`}@vlKRxS9I%rWz>kZD66DIH-5#t3B US|R(Y5ANJ;(nxm zY{jpu?4Cu8pD;xkWn8$TC4%|g$RaE))o5k& #GG5adfZ3=!(5NE16WZU9;8LTsiteknAMOsD(S)86! zPAbjOCXm;A6mb4PZq*<;7^`${$+xx6?lye1M3*}&zKs$oxWIM(r^pq*ZVc=1m3%cI z-VNQLbDSvLq*P}Vi^_bKSUL*6AkLk<_J(Op!S}OU0iFwuh2NHE^Rd#lNDZHAoTlr_ zpFdGcmriX1+=O#sk3t7*rCWW-a`xj{nowR+ZU5^%aY|bv$(`p z0?Khx3pt0zj|ZE!T5B%wfTk}n02T!rp!0H$Gr)rFg|I!cDR-+$r??>4VP`ar(PA@# zm2n;&3chZldk{2$47gVT#8@B-h9iUpBTg1h`=-aSa2(>RCa%sOw~^!?dz%PaVoUSm zetAoBHm0W1MD$Ri6}U9c&JrRR7f3I%fwmP$TIs=oncA%}y2YU@^MoO~j;7VNEXAnH zs|DxEC&@z@iKe=1puCmckyGdBwiCO auBiNqnN`=h-6ipYA7`h__i-mypnC%9holhcc;yNrmO!d>FVET zJO4>Z^PhL|@2YM8lNsr|Ft|ecDj`V*StxEy@d%!u_kB;fr~)cUALoJ0)-}$VuN41b zg`?np)W|^fNhL^hc6{IbcSUzmeh4oK)T!1~x&HkC-Lg?CyVXJXu zJih*qV()(jk^jp )6v8d%PVzSb$gBQ0%Bp`( z?LTg6UoBaVbVSAPAD8iVty Xf#m#?no;KQ-QCVo@zSrspY6u)@(Rah`cH%~~h z#3<*Hiv7`#tnOxJ@uiRJ&RIE_pT0Z2L&@t&!X01L!zWaE#J>L_6o08f^y|-`+}^LL z{=A?ym?#Xs(V-xujE_5f9EOcoKP^`3zKZSv1k<>1!PkDcE$;W IWRJ#?c9VoH)c8e~S^xK-iNNAngo&$w1-H~o$-t_z^)RA*g zd;G(~lBTDpd-ykzC5f-RH7h2Tc=qlE+PVf7A_rRC=Iz^m38{RBQ$z><+@^OwA|j&p z<3~I2M?L&omfu9lTe%{g=k39C>Vl&}?Uz!&gfM0%rUo>m@F<`u;;a_?U$48#yYgxn z?dCVQ(0!kN`}U2k6}Vc?_u+#FAFkLjP%0i & ze*KfIUp=F_3Rml>D9m2}a`Wb`TTjpKxRR`J?%aKzxb$>Y2p ++RR&hTsuOCkaMzulM zf0c1oYx^fk@Y=FJKf9|?DAZ4iu0EewnJKbr1rwoJTBlBZzv9TJ6W>Sfo|%hS5>`!I zrMoGx+>onvC{d?YRcU5P--h7U1Fr-L3v!heFN6`r(Dx}swfdH4m-{!kx-PA$qz3R{ zT!qbBj`V3!t}=CZclSiNGP%F)+Is@GJaurxaWvcdR=Ktaii*Ar;$7)BoABt=_pc {g5xuMo#hc(g6mai@UWvNl6+P^y}*E +hbBJ^R<+MEU>mi~n%7fpq*by?LnDRpVM(b8t2SPR*nJ;iFrYpt?T)z4G9O zsBBM+5aVl_i(1d<-o*d=PaVn6v^K;GN$nilIG9*Jr&ey!(0PnAG}WD4(K+V`uRD(d znvc%Q$;ssxJEFT(2!x7bW1n?)x@jYS^wX#KyBUh0^*?~Me}=fbar;48)PNc#-kj{V zmcDff8Up##ot|_eVp(3=ew!Q>xkfh^A$Ik5-_=b^W;B}()I7cg4m=9BrlNQ6-W#RW zw=}{K#G|lo-8!_Ds3Z*?78InzSjxL+&q>l} B~Bo597&x%s#UwU)PB;z3Ui+Gww{0*1gx%oZJuhn(*BMMi&)Zxb; zZ)nW*=I+X7qR5t$KN_S*j-p|MDL22BTlBi@pMU;2(4Lz$IYLV@Z_Vt-5s9j@va(V2 zSGM0Kdp|Ev65IMJ9(&+JlsgBLdz(cTw2>%iCHr>oF6v55Sf4LKp*a7E&|z(DoiU}T zsAvZ{LBSV?PDUdh)-`K%_r_h?F77m$SX*10Zrguhs3Tt+2jTt(i(Q1!@W#6HMBX!% zUF8<|ZS$vwD-h0opF*WlA>9D@I1DO##xu|-`}gjZUtC;7S4-gLEnA}T0i{N1rPbBS zxN)^JXYPSkKV(OAb1MHt2Zi#@&OgG7N~Lad_QK5}sa!TNu!EmX(HCEAS??X|5X)pS zBGR!)Hr&+d$7aGIAX$v7?6uO2&PI9LpfO9~f~{@(%2lh_Gc2)9L~+E_PKC0{%KS*f zOx!fvD#VuQNVwv3ZeQv{#5yM{>$Y>(t}UB4KZPyi0{XyQqP$dC#JR<7J-DwjVyCPS zg3za1`;Ek*R>}n0E=D~^KJ$Hw(_c=q$KWte-=}bq@b1`gboJ`hUJV%Bs~oJXtiDgt zT9PUWp5m&t*|G02jgS+yAW?bsl95J;Rk%Q<7Q9GH+p>LoEEafLW#5OW46NTI-CT93 zh?WnzWse^_HbKrtg=`<3Y1aG%hg$w} SL6-?Y=gRJ{dmiYg8E={rRoC zzHL5gD4yP`Fcn9~9O$`H3Wr66(%GtEAv(v3hrh`ZSgvLq^6=qig NrROy38a>GP*6}=b#-H=d270PtFS^X*~@S>_QMrB z(c}~3WZ(dCc|cuk+Ag=fXZ$0LrjL}UzO=XylDIW|5H`}4 iy36SaHsw(e$oqCI zNih7P&rcLLPZ5LS4ZHX5 ev zZDoiej7wxD_wKb@%k-Thj7kiJkj!8a$!-^yE-o|WR>);&ka3A*zpuCUZ}>jXcb fl0+H} zCY<&t@5m?654G}_AdfS>4;>nS@Vbc*FqI4LLp;Ok{&SJZH9F^@Lx6ER=^C^VG=h(Y z w z&EK3`D+$}MZ5so%V?JLtWV>*|0{7-{{Go@h1B}33*umw4x7cj_Z6wBv!R}uMwxtAj zQdP~OUj;b3yA!Q@!}V?ZxrX7R2UxK55 LD$hTs{sTAvr+`kAhEjbV zd>#Hx4tKP*_mamM{fdCc2mR0wJ&?CQ4waJO>r#)Hi3F2jbg6AQ)MKQCNX5x13+HLU zR9Bd3!$|en3N(D6PJTk2!XHH!Wqq$RreOnVX=y*QB#paZG{_i_EU@=%O-xKS%V$`y zVDrg%fim=E6?oSvp%N1LrXPx;RkNQ7s*k=l58nXTmaeAWMp>EXfuTtDkjv$qI(14% ztz7* -AH zE3kKRN<`(r2L96qVIFbzkC~b+E1gJ;@Y71%S-BIopciCnKJ7YU$%R`czCBgz=1D7S zYYJ$G$~A{`RZT*7g1d34NfIztNOsPH01mn6-4PLgC~b1rp`r8rEkpKu7g{6KTD+n= zN<&@e)e=2dOhlsep4~bDAcbe)Y65ckf|H50x`aR9%P#K)cnUKm5iXyv*#UL+VtM%h zJBIF6Yb=-*o$mB$QmRFRyS=ZVprAa(BWoqlo2U6lKZ2+yy}R3s)`*&92AaJy@#fZ| z!yMq1AJA!|Ua?q*zywxIbaX|;EJ$p*9#yf9&)Ncvgh3syknxC!bONL*N~ta^C|laP zURRfnyITgapB4>Nl #>LWa@u_Lv2NxhWG`bS4a1m#z7~6Gqbt#*K@=Y`*i8}b3 z2}gVTbYil=R2l5NU+yaO&&+3(`-87B0}az1%=t?Sl#PwOJ7Nrn5LmffRh1E#Q4Ssk zuirV()w|L|to)EnvBK#j%_&^lQq5vqd0T>^Xf7HDy}$vkck$xI_UHmN0S@>&z_eUZ zrtYRq&UAXbrXSc3Ee{WGoRBo_ApxW&JYm(-MK&Y)q@wJN@A~>SY}w+BDq#z#Njd51>aZ!6IhEDd+N6nX z()=;^-n7?Jwm7P&5|JbtO=VY9R6LTwQ~Dg3If! %XK{Vu(Y14_Hoi+_1j-l`$xM zu_k5cQ?LtNac(P_eLD5~@A6=6)Nb_I-X>);piJZP1p>nuKtUU$Nx+f}ByMPpkS??z z>LCZG@>eoKGkjZ(-Z*&1G;SD**z4D=dqQ1~&=dnEthnO -yvikrquA7zc@GtD=qu_$8$;sL6?QXOjg&&=7yF^7mY|&RQN`W*^OpWJo zNY2X3%j-)%NZZ`poHg*m0vOxL%Pakl+1+Pr>vlVs6{pm6*@cGQ)26519vwYW)Oo>X z2J^%20PQg_osi2vbLNb8HWS+Z7EyJ+gn(;tc#NA{D&+KQB(n-@$)SN5UQt0Iog8u8 z@koe8!$4rVm{SK-hiygqeQ!X(op{x)S$FU10g Inlzm1 zL3BG5%8;lq X`Apv_@$4cmeG&!=@g>yuhDm;M9pA zrOzh~0V2$CRD-KN7enO{M2sC~quH_9= ;2c<8wR(`y>*#S^BckjcA z)KnF+%EWf0())K!ktj)UXx<6s2DX>tTBvAn5s`A$g0BC2 k$5=|7VBmiZR&@vH2=0;&;%?G!pHrc23sZ?Ch+L^bL>&c9lfC z({E1J_2#gW6>V97TqY_@StFecTl3EXP)XHkGccq3d#}#(TXp40a%a>P?z6Qd_{Ox5 z{J(2mwM8x-QBumaZBfNm9>_Rt=2XoLZmeS#sDz3Y^)Q%~FFG1j(&pA?qNisUTsfVE zFh%oL6Bu+_C2fJv#%!#t{8PI(S->+FM9hLH?jCkr(Yn}jOfo|3&jHH(mlTpoRg?kK zk~T(Q-dkYVgwvvWh~}v>Es5BDcq02{gvYEivM_qgnZaF z^*TB~BRl#`cn+OCG|E5EdK|}`Lzm1dSW5{^U#6yn;Cg7V*wvJ87B1vHe#}vudR4rK zv%2pC Q=#coP`7*SwF ~wBlSU z{ni{5PfSDzWX4m&5Ukm&v=3k$#jBV=6`_<|mtxsSS`%C>M-(HM_D#{s<)5a(tvunQ z7u0TibY&cpAc%_#-Nn+5a%Zqe;`p*vE1umjud1E?_%R$ FNDKJmGP@V5$O z(uitSi_)|2kgeT%Z1_%bi06)xB3K-EDZZGTN3}dLW-R(OQ}1)nVeIpdebk{LduAYx ziiKaw4WO^1LB4Dc$8i7aztnQ6- a7IA;a z6F}UohK?`)ymaQbWB!K|TK|mo#!rbq5^OX7ayj*7mN$Mlu!xwP`Pcu?n}7Rz;nJ-) Wl4@L5BWEKgN83f;nZNzOss94g=25o* literal 65285 zcmdSB1yoh-);7EWQA9vd5kX1;l~(CSkrq%o1Vp-}a|0G&&?Sv@cc+Miba$w9iFCs^ z7y7*CJ?A`UjQ=0w|NeKpd$3&Fz4uz{jv3dy=DhDW4`sygaY=DeC=|Yg_ z`W9<@FSU}&zg{1VTGX`<+*)wlbhNW; zkL2d%wbozz+Ct)~ec9u st3uYngR(% 2z;S4nRn-1tdFY-K~ zK%u@> 6R5FKabmo*45RW-JbC6rwx4^CwMR?ySv)VGBK(<>{zL})_J*l+#-bf zf%k)ig-b`a+rPg1q3 ?60+R z`jUidxjKHi+9*bePVl639e7-S#iHV4K|w*vkeV`dsM2}M_-g>|?&z{>@^h?HX =y? =T*8Xm6;>R7=n%8$+B6qqxOvkG 1k<20t)Pw)RxAp z1 5fyIc-PrJKKF(<6moGon8~i`Ysd2V|2K`Grd0fHBeDWsc)9A zc*N@6&W;Sv9L>S<(V@i`v-b+Z4eX)KiLwGa_d(Qf=mcH1f1PY!mpRFVehi({^w2hJ z3Zg4puG+h&8N*|n#$h&;KrQBT^Bhj&^47wq=U8e5hW@)73kD$!%*;yTRp^a6Vyyz3 z?m(F(Gz+P7&yxKZdTaFhOzC=;6m8wi)=d;jDDIlO3})e7kz1a%9~T!*qip+BosJH+ zY 7>dkgdG|4Khk91wBBcAA_8Tgd7Tx!2OHoe^r zqTy?3s$V^x4Kk+?V6*!5hUfZ@bQqgaz>cqEc7HlUR!Lk<9x|u$viy27ESeQ6si~=i zEDUn^ `4BdlDU) zar<%fJZR3B<~N0d`39aRdfySV_^7M9hdg}zI3vQm>}%vtkV6jhkrW*t?xe4d$q&NL z=lLoqD9lbrSQI5jK~seaaAMWp*ewmc#;aTT?nzmn%PzD~sNYJuR&NQ-kk8hvwAr0Y zX1H-ftg93C9W11`!39DrP^jb>*Rs{sRT^@9wFun&qs`*#uy(LkS2kA5?3U7QL_2(r ztoremVLpo7@nEArqSku-=cqcUvvN=Ko5Yru2lym+zC>ykn`@A%V+~k9hpu)nSFHKm zVP&O`cAISUFFV{_Xq}shc9!9_|M^~Z5Aho5&{%&8ey0!ZQc_Y2m2RCP#9^GYY4|cQ zw2rB3smal4k&$GH$;l?Q9{Bjo1`B Ey~`Z*lKjrrcPjXrgD!w#ycsj0B>eo#1D z`1S198! K6Q)W+V2k~B_$if^lh`ny+jL!pIR3S*WS7}mYtPl zp63ll=js|8?Kzy;cwd38QTy@CtHK^B!kz@+KsvXokI>T5e5&9*0*04-o-z%#|6CrN zvzad%HV>o$W1|(pXr9Upc=pVJSaiZr|8(rC-xIv&?=OT&Uar1f_5i z;!pb+bha#cR2choGF+>R3dFbeJOswU;n}vb_op~-{Y2)sJ(}OPTbh%dt7@w+Q{8rJ z)PA9bwOygyZYd}xCR>W7QUSW1S0GrpE&u|h#*KA)4#t;_h9uxUSl0V&?cf+&99`Gr zDSMsW26D8g_aZpV?tp^mkvT8sPMg&Do)z5B8QX`)v9}5AE#^$Uq->yY&d4?DPP#sP z1?R;3z2)la&az0E m1Ijie; zbtm`2zKO}m_(0=6d-W-@?UfMOxwO}ycL#EH@M~|q2YV8cEgi*ESmUVWx}%pr0yYN^ zJ_nOqpo#X!(M+Pz0hA!Br eEFs)WO4_Mvrj&C64qssepzqm121 z@#4X0MwUwrH07IvWz~Xj-@Wr5t90g6I|?(1HVO(26;p7t_L;J+bGq`jrz=rPc>d_e zI~K-%+nuS gjqsb1c!VaLcUqUMc(k@4)-?^}Dq^IEx2MZT ;wJJ;^kayE!7y9r6| z54&< givxXcblQ&F= zW5-;Lh>FUTm*K9n(x~C2 hTt>^np!9yP^(4YMp?lc_@YU%Y0MPLuaS?7Orl+Qi#wr|#iY;Qm8(= Z`}bJb(iZ_QsDwny2Kb&ONlXEd*1MoZrSH70@EptD`s5 z7DdWos?um;KVs=wWI7l(KW~hUiLrCwO3rO{f4Io38^Nq_2qw5lO1>?v%BonET-zXG zQ2LO4O7OGB({a*%Gx);1azn`)yl0HL6$Nza6V}-e-QUe4kKgF5PESwIzb4k~03Zwf zyNGk5rF|1DwGnux-HmLw%*DmU%Pw(8xK#z*+pLme7VDb}T1P{XS@`%7T_a| efcf#4cG0J|7P68wZ z!CwoN)%MGpXn;@w2@6@}%yCy`!&hO{B_THOw^ 5orCcA z=H*KqrH`4TtlPNNs$DC0hFh2H7RHYbixD-;U-af2OVK)94OJ_%Nwu=FT5oqdlut}d zT-`f>zunDY3*keOT;tv}(S|PHtz#=+8p72|+WBr$POo^_%ygurv*g>0GxwO^EOf?u zeqY;}4?bJ (_veA5{nk2pr zIyOH?1{qoPTR!A0Wo9k|ILojf)Ux*YhI0b5-W>z$9<%Jh?n3qzjkD6F^J(cVyGogA zM4fzJOU$W>T*BO(oXWnhIFK?`8+BjLchT0?9^hD??W|>715x29_wF15!`kRX&&-^q ztPiqyRc{ky*f1)0>{6z=XN{T9)HyN;WjU3y9uH1(DB7#<*HRvK7&`KLe#@C~=6L^0 z_}OI-ZGd?nvVAY#jvI5yH)tm)Wh)Qqy~<^5Hd 1|ome77=`D*Q6ws9UVcEels?(h!%aNE<3BD&127M@%0A< z0dHtGPtMG6ZkMWmZV6*;or;0b1wVv$E+H^{pRw?1CDU~^6uEa(lVpBXmPR>;T3;J# z$Y*)*7AZk2KA0x;v*bLwRTQAsOI0TQSy%V;t+5QjkwVzv;o|GRez#S7ql5!QNVN7g z@2*^}ms!k(uN+sJr&RG{;|W^@uI%qo3kp_$&9MelElm;nbkJ?65MP9PJAcIO=%6*N zd1B>N&sLAT>}w|Cg^2= !AkJ?S zdwzmPo$c$wh6mqg60T>lMdqVv%jjii={`=xSnOBVSN!^XW_k^@l0VK7qNep`t;4R! ztV)*(rC*m{6py<)2Zk~l07Zh}$iQarp8R$J6M^d4xOexMY0V`vEk{qDp?JyT&@xyC z6wErbFsvJ2L*H%8aVD%i21txc %xddrMO#fry{3uq%f6H~B_jhh`8SxD%k{ukJ1 z=J9JD@{);58O@jU#fzOq|Ef8qmh Pjc9ZvkBA{3v8WFGe!qb0lAU7TXeWJ~$ zjx-)BDP50gSI&N5GK>I>A6MOFo&q8R&+*}B=?n!TV!NPbt%4^btRMgpQDELq;(~Dc zeTi9(&ad9e&WFFeUxbsUmnkJId4G9J#LzO+uVJszGViTq^0>I>Md%UW{JD;g!rIN1 zK)`@)3rGN~B&Jbjb6Wi;un-(EvM~Z0{LY&_SZDcSeFb(KE1rjI^kt~(__WeX5No+u zzSINRF%e*4X6}P <)ClCxAcW9-a?I~!YD*<<=Ejh+-BK;K4K z`)P)6H&ZUf(r# ^6e1+4TEjhwEbZ6SwY@sL%9I#)+cm-G` z?PmV%Z!f3UNLcmRRK^jxXHw0(58Ob2kB2#-6jTzp!j)JMO~#mjMz*c!eB;Ew%<~ zU%saTl((PWk2g4JyELSTb&7y38Jb+}$rLI+9H)U-+Yu-$kP3d# OZ)j69tPO;(% zU$`N|hLr~X-*e=FDZoUgyq~q?{S}(o5WXaiA8r=wmqKu&)vx7-j<>BVW6A98Ld)>& zm8dc0w%g5iT#d7;F?im`|B|!sAXx)kbsOK>gS8!l7<6Ao+5E`?kTg7X=Dvox5EWnl zLsw}f|42tNmzPc7+ iNL}jHeuZ(_9(iRrD~Sr 4_uCYLW)sUu_X`17RU;0C|ge7H&0?HIwm#r&%V zWMh^M as_#P(-t3};+bsoMVW z&TsC54A;k+yj⁣vT2>lUpWt-q{^_)g1=i{0k3v#;W*m4n2(O?d>IOB~BOgSYWQs z%e!-ZgQJ+-u4k}ofg_T&jY}9L55kSsVnEb>TQ3_jsz3~{;nuR=xx;2Y!o{RkAg-CM z?7X?y`J?Wg?MAOM1CWbdowru LJkb1Ooja~gN@y(NK2ChES~>Z`Ikc# zIj^0<-Me>R>gm`<$^>nA&901Mpxi@*P~IoG$p|) 7K(Y%^d``%S?b1k6O24_= ^K!`zaD>0wLqyJ(sa1whU|@G5V#>m#k%OIRekxih|0#JUL*n z0% 72Ykl^HtXL%Jfw^q)pr$n-Kb~ z7grx-YLdVR))(B5xsW|Y+bwXV`7l4R_@f6NIS-reE{ogFyF{m^=H?ARP!Zjnqc-yK z%3XEyTv0a{2s nG;s{zDGeO#I9j+VBX%X#6f(CF6tkpdFhTBfF*1fh@c=p_`Qosy##T>5R zu-@gY-jN<)-~~@bO|&4;;4>vML`>5yz))9o^nQjzfdO8+e52Jz2g`&<)Z7Ehu3P1P zZaxP;h^q~)qE*O~FKF|BCavN{p`LJJ8nVrUOmW1tf4Cj5suS54eoOns&VJ1)O4C(S zgpYRqS(-f9oVk%7bI{^)2-% ;J2kL%;AnokzTs620p=S7=jI|4}VY^c-ZbmZIz|hb4 zq{>%X0TJf}{A}wS(pc46)R)f)GwtT*z!&Z38XrQAHY#}9JM+cZQEB&u?vO#^z-G*w z9DIo`ps<9K#C*s|6xBmmv?%T{HorQ30ionMxwSHUy5Hnc5c2=mFd2Vx$C%d3g0}B| zm32M8A}zYPICx=mS{3NsEXPm_NJ@MSywP7CR2iau8R1fGz#F}biLL6E;bofi-2&sF z1%#WKQWWsYaXb5f&Sj5>Z`g0>BR0((5Z6lJ5Tl*u>DCIredCJ^4<|hUM%sJUv>amh z%9Z*n(>6MsTE_3km-`W)ECa}ipT^KsQdHE#ylO|^+6ipJM%(@O8%2hCyg>;N*@Ph} zqfNgE!d`ZZu?oK{U)X83t+BPb$lLPtnoW g6Y(sQFjETp(mAFKsZQv+Sde zYp@4sWNJWlm49b4(1S)epc5eVhaPUzfm``)(h(dYeB+$sE;<0itjB!Fc}d;&hR5GW z@!FF@!b`st#z_Yl(|RCLy@6P{67U{E8IR2Tl$6E{2#A4-)&VA69}P}>pu{r%wr-=J zpH-nR!e=@s%S0K6s27>44%`7Vd?vMh&W6-&yO#3!?r;I)j9t06M!6kHcGYg$ZOG@< zLd=nA0rZBx#?o*xCuEl{%E_9j7Aq+#D|@=MfdDqRxYl43vvF4sFL5*j{Ww(*?Bn}` zy{(9GF{*R7fRZ<@04}bcE;;gPNNY 5=MqKp#^fo?=7l!>VNGW=tsd* z6K^}NPUhHh6jf0VHc 4>kWsQ6k2R>ON_ z 2M45QT&o3jN3&FNul;bO=2sHg+X-P(*AI!|bF}J-shP5R%@q0@ zT0pA)g2FZI4iD|i;AGC6MqNX*t-oX&p;Ynahv1^hZ*KY|@+H`QnVy*BkEpV;vZ2P7 zmJH=Fm}oHMqH1d4oz-qf30lRixAmHWa+7lA?@30Zf)&ja+dFxJGTXxN0QIj@AR}t7X)sEqj)Yg z=XVhgl(r8M30)C2^_|KUpirOM+Vh_4PF5ef4mqp$tr48+YUb8H-8D}uDNe@<4 zr=g}6j&VCIt%s~xXC9B;VoIV^s0SVsp*J`%KdBMOmzYa!^h9kzzENzzl1QhJiNk<5 zlGolmaDkJTR~@FU8?wC-rc%H)j=3G7Hy}g$H4oUHz6oDJirx<5+>WksYbl5vf2X!x z_Z>7K1why?`1FgH-$x#J@bI^10!-h5mQjLxB*fRAX^j!A)Jc$TT|h#p&4U4;a+G znabtsYtTuDtOf;;$(icKGC&l*ai{_sc@CHYZ{z4Et=uxFr2c|lsPcsRatv__Y;0^K z2!{YCnRCoRc)9whN?`w&Ffi`QAVNGFJ@U5GVFt!P&yotblyG0N6oyA2a8UzNg-+m3 z3Jp82nT=Jb0<{BVoNK~6<}z_*O~*t)kEUm=AxrYnSMX2;(OON%DWXiZLP<*Wx<7Eg zJwT!%nI;IidVpq40YpU4Uie)@ANXd3ScrE1$;|{A;u!R%>ir2v$xQ3fKHDLq I0(s7LdU{rkTgU%NKB7yON^ivc(kGs^J0X8 9v#$t7Qk^?<9vx#Q&Uma$oDHf5QHh{K zCSdocH*+9jMUsXvL-W1qp}-0xK?u44bq;u?I|)Rs{2&$yfXIIVB1iFZ;l-2KOCg04 z$SW2Duja3Up&V=sw%?zkK3zJ|@#if{{hScs(BqfsT@?PGxBq*7>`%IU61DPd`
w4#3&xs-1dR% z+P2PR(TWHx8gjs*LR9CL^--vyTmL`RU;QZ>eT=XaeHgZKBU1CL(zN|w9C zMPjwRmqlWIcn#rrd_#52Z!1@+3%U@{eGA@7oVhr#D$>l3R11Q(;9CK)|D~LeD=jHW zR5P1%tkv)W=ra%z!Qo9Js7#ritBD5(?E!*Rsc(K}qE9(mlqo*t_4+Wp6hZ@GFpywh zO4)_1R(4!gcU+oUTHYf MnBT@yp$$0}NGE)i=>cuqcR z94ybyT>3p@hRslzSU}$ EefI#mrA}mv2!y{H~%jyo%hic+u3H4d?jEb2t76 zOs5x9wU(8#ln3E*$nWN(yz+Y-I8mAI<19yI?5o*Y3_9au@!5KM42kVq!B%6>xL40i z3?oT6 $hB*yx`ehvoGNI?lAS!&nTvT=HE9%od#|q1e@bP4AhTPv(fJ&PUF_J$@?>Zd_=+R z6CF7%M_)a>nn|6j{2!^A>X`hwl7 A;^LfGC8Qjj2lS=#hQ`C7v3^qpVP0DkYs$w%P+& sdQ}=}(u$Y2Z6%c10uQBRQW68E@k9?Hg8`OXK&v|M)|{n>ewZj6QAH zlI2r&iIJ@Ln_BQ3+XpK>L1+?!J`#UPwf*y$A9U +1O`G*xS7wlW>7A)Ci> zW4u3YW(IVAQf>d L+gI`5|0rekFK^xg3Vz8Q-tZ+YVw&mxcT zVnT419~<;iRB_Dmsm;`}4agNi5Nv=)e9pVb8(VKPo*Adfwebv(ojm@Q^!K-t^8=^l z?7D?b5_~8a#2P9t86G>bSi}QB&$xJI7!G!|zCP-pb$MQ3lX%#EB60s$1Jm%W 7o}`TJw8JCVF;1QP?>Ey#2E@IDk(@J z0Wy>d5K27Vr-OkKCetXRLl0@-x>QL#v-&q{*zO-!yn|pIcT?%4cMA#r)dwLj!7W z;ZcuydnH1_&}>%uPbjNN*&2hwx{Om44nia(B#(OMHk@o{qU? zzuUeE?psMIB#*k})s;_f!NI{_Z{cxA$=J^K(2ccX1iXbJ9jMUZvHwZ7oP?67o3i>k zWhD_{Wo;dQ$aJ %<7_Zh#(gF7gzpdi|bwKsrSCUsI8WB(nYFf*q#pdfU9xHy}}2#B`ZM-P7A9OajxCXF(?>~V=v zg-U`{(AA}KD?dNq7HXoU0-*YxT(Pn+bRWW7R?{#jHj@bOA>%%;h}6d;uUK{yb_^Rw z$5O~!(?~Rs+dm$-Q+Ri!%y!{gR{!^BvrrHjM6)zf3Kt{6bHMt+vYX%!r@yW)M6QMu z8x5VHpca%|Xg32PDIHJ%ixE=htER(Epy}(4)V_wzAxyw61o(`dn=0(r>`s!7K;$e! z*z$KXpuDnE8i#?Np5}m4m*560k_do8r^&6oD|l%OJevbL8_*C#sM#um#Siz!nxQlm zZj%o6icNE-n$cSF^3*Zy{TV#xNNR7vg}O*EgGm!Sgs#7Z2RZw?V<_uXxyb8|t(o2L z(zdMkDI5sRwfpo`s=9i5?7RjTewSewHTG)RsHx*??$kWDhRS;`_mBigWxnFKE<-X% z#TNbWL_|q$sy&Wrn7Hjp`24^{fYR*~>Jo{^$NBkr2Tm+;NqCAah3}0qX;eT!{{sGw z0f8SLaJdtsCs4P$j4@|>dg3V)b5Wezf>oXS#AdMa!3j$G6hWz=G&>y )H~~U?vt>(2O#yJy le8x(M4UI%eN%7P)#U{KCd zc=X8MF?6x3OYUHrv)UiZ>5x)YkEWV2=Vg8kyFtA&NLk#|Y;SMp^js`~T<-={XGU 2V#aA*F$c{^vF* z8wRxyuK$p}0cDArkm&D)G9f5EFUVPo0bcx3l h ^ z8T}avDo5`3L&HBX&BQ_Tq3S0nDvBJjw@^Isz(c!n&L$071*>cP6d?El+PxQQIgiEX zcWyr*C?X>L{rmS^#W>;=e`}I2gY!Cmxqtbe#3TRTut`sUzQ&?0J6O=zofHp#@4)#7 zZVQbdaK{i$F #QS59hX%}++(j~*E+Eq?^26g3sjknr410m|9O-H`noVc#Y z!zRVd@#S67 Fr)7ehsaoUwET#a`qd|UkMzS z1%t(GhWpEHJ`dsZ*iRUQuZ_9}J5^d5gYQ0mm2>0OKKY z0LvB4E@H5$y}D|I7D F}88NA Zxl30 mSx Ej*jH1EBG^9zmlP#Ma9F&$)qOcrFsZ`=!U?EfVM-pV3-u`TWvHANZe_zU6nGFt* zBO<@q>Cr^3-Hc}(lm6!Q4yo3MZ1cG}={^Y*zKSp$Kw Jx6*lQ zS4!Eoax03!$gqJRTty}Jh;BBcqNgWk1H``%ISBu8MxDpNU<(MiI@e9D=#*P>pM@xN z{))YH