performance/0000755000176200001440000000000014741740672012567 5ustar liggesusersperformance/tests/0000755000176200001440000000000014412517050013714 5ustar liggesusersperformance/tests/testthat/0000755000176200001440000000000014741740672015571 5ustar liggesusersperformance/tests/testthat/test-binned_residuals.R0000644000176200001440000002036214620351763022201 0ustar liggesuserstest_that("binned_residuals", { data(mtcars) model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") result <- binned_residuals(model, ci_type = "gaussian", residuals = "response") expect_named( result, c("xbar", "ybar", "n", "x.lo", "x.hi", "se", "CI_low", "CI_high", "group") ) expect_equal( result$xbar, c(0.03786, 0.09514, 0.25911, 0.47955, 0.71109, 0.97119), tolerance = 1e-4 ) expect_equal( result$ybar, c(-0.03786, -0.09514, 0.07423, -0.07955, 0.28891, -0.13786), tolerance = 1e-4 ) expect_equal( result$CI_low, c(-0.05686, -0.12331, -0.35077, -0.57683, 0.17916, -0.44147), tolerance = 1e-4 ) expect_identical( capture.output(print(result)), "Warning: Probably bad model fit. Only about 50% of the residuals are inside the error bounds." ) }) test_that("binned_residuals, n_bins", { data(mtcars) model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") result <- binned_residuals(model, ci_type = "gaussian", residuals = "response", n_bins = 10) expect_named( result, c("xbar", "ybar", "n", "x.lo", "x.hi", "se", "CI_low", "CI_high", "group") ) expect_equal( result$xbar, c( 0.02373, 0.06301, 0.08441, 0.17907, 0.29225, 0.44073, 0.54951, 0.69701, 0.9168, 0.99204 ), tolerance = 1e-4 ) expect_equal( result$ybar, c( -0.02373, -0.06301, -0.08441, -0.17907, 0.20775, -0.1074, 0.11715, 0.30299, -0.25014, 0.00796 ), tolerance = 1e-4 ) }) test_that("binned_residuals, terms", { data(mtcars) model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") result <- binned_residuals(model, ci_type = "gaussian", residuals = "response", term = "mpg") expect_named( result, c("xbar", "ybar", "n", "x.lo", "x.hi", "se", "CI_low", "CI_high", "group") ) expect_equal( result$xbar, c(12.62, 15.34, 18.1, 20.9, 22.875, 30.06667), tolerance = 1e-4 ) expect_equal( result$ybar, c(-0.05435, -0.07866, 0.13925, -0.11861, 0.27763, -0.13786), tolerance = 1e-4 ) }) test_that("binned_residuals, deviance residuals, gaussian CI", { data(mtcars) model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") result <- binned_residuals(model, residuals = "deviance", ci_type = "gaussian") expect_named( result, c("xbar", "ybar", "n", "x.lo", "x.hi", "se", "CI_low", "CI_high", "group") ) expect_equal( result$xbar, c(0.03786, 0.09514, 0.25911, 0.47955, 0.71109, 0.97119), tolerance = 1e-4 ) expect_equal( result$ybar, c(-0.26905, -0.44334, 0.03763, -0.19917, 0.81563, -0.23399), tolerance = 1e-4 ) expect_equal( result$ybar, c(-0.26905, -0.44334, 0.03763, -0.19917, 0.81563, -0.23399), tolerance = 1e-4 ) expect_equal( result$CI_low, c(-0.33985, -0.50865, -0.98255, -1.36025, 0.61749, -1.00913), tolerance = 1e-4 ) }) test_that("binned_residuals, default", { data(mtcars) model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") result <- binned_residuals(model) expect_named( result, c("xbar", "ybar", "n", "x.lo", "x.hi", "se", "CI_low", "CI_high", "group") ) expect_equal( result$xbar, c(0.03786, 0.09514, 0.25911, 0.47955, 0.71109, 0.97119), tolerance = 1e-4 ) expect_equal( result$ybar, c(-0.26905, -0.44334, 0.03763, -0.19917, 0.81563, -0.23399), tolerance = 1e-4 ) expect_equal( result$CI_low, c(-0.52997, -0.70426, -0.32935, -0.59948, 0.55472, -0.55251), tolerance = 1e-4 ) }) test_that("binned_residuals, bootstrapped CI", { skip_on_cran() data(mtcars) model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") set.seed(123) result <- binned_residuals(model, ci_type = "boot", iterations = 100) expect_named( result, c("xbar", "ybar", "n", "x.lo", "x.hi", "se", "CI_low", "CI_high", "group") ) expect_equal( result$xbar, c(0.03786, 0.09514, 0.25911, 0.47955, 0.71109, 0.97119), tolerance = 1e-4 ) expect_equal( result$ybar, c(-0.26905, -0.44334, 0.03763, -0.19917, 0.81563, -0.23399), tolerance = 1e-4 ) expect_equal( result$CI_low, c(-0.32623, -0.50543, -0.80879, -1.15154, 0.67569, -0.65748), tolerance = 1e-4 ) }) test_that("binned_residuals, msg for non-bernoulli", { skip_on_cran() tot <- rep(10, 100) suc <- rbinom(100, prob = 0.9, size = tot) dat <- data.frame(tot, suc) dat$prop <- suc / tot dat$x1 <- as.factor(sample.int(5, 100, replace = TRUE)) mod <- glm(prop ~ x1, family = binomial, data = dat, weights = tot ) expect_message(binned_residuals(mod), regex = "Using `ci_type = \"gaussian\"`") expect_silent(binned_residuals(mod, verbose = FALSE)) }) test_that("binned_residuals, empty bins", { eel <- data.frame( cured_bin = c( 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0 ), intervention = c( "No treatment", "No treatment", "No treatment", "No treatment", "Intervention", "No treatment", "Intervention", "Intervention", "No treatment", "No treatment", "Intervention", "No treatment", "No treatment", "Intervention", "No treatment", "No treatment", "Intervention", "Intervention", "Intervention", "Intervention", "No treatment", "Intervention", "Intervention", "No treatment", "Intervention", "Intervention", "No treatment", "No treatment", "Intervention", "Intervention", "No treatment", "No treatment", "Intervention", "Intervention", "Intervention", "No treatment", "No treatment", "Intervention", "No treatment", "Intervention", "No treatment", "Intervention", "Intervention", "Intervention", "No treatment", "No treatment", "No treatment", "Intervention", "Intervention", "No treatment", "Intervention", "Intervention", "Intervention", "No treatment", "No treatment", "Intervention", "Intervention", "No treatment", "Intervention", "Intervention", "No treatment", "No treatment", "No treatment", "Intervention", "Intervention", "No treatment", "No treatment", "No treatment", "No treatment", "No treatment", "Intervention", "No treatment", "Intervention", "Intervention", "Intervention", "No treatment", "Intervention", "Intervention", "No treatment", "Intervention", "No treatment", "No treatment", "Intervention", "Intervention", "Intervention", "Intervention", "No treatment", "Intervention", "Intervention", "No treatment", "Intervention", "No treatment", "Intervention", "Intervention", "Intervention", "Intervention", "No treatment", "No treatment", "No treatment", "Intervention", "No treatment", "No treatment", "Intervention", "No treatment", "No treatment", "No treatment", "No treatment", "No treatment", "Intervention", "Intervention", "No treatment", "No treatment", "Intervention" ), duration = c( 7L, 7L, 6L, 8L, 7L, 6L, 7L, 7L, 8L, 7L, 7L, 7L, 5L, 9L, 6L, 7L, 8L, 7L, 7L, 9L, 7L, 9L, 8L, 7L, 6L, 8L, 7L, 6L, 7L, 6L, 7L, 6L, 5L, 6L, 7L, 7L, 8L, 7L, 5L, 7L, 9L, 10L, 7L, 8L, 5L, 8L, 4L, 7L, 8L, 6L, 6L, 6L, 7L, 7L, 8L, 7L, 7L, 7L, 7L, 8L, 7L, 9L, 7L, 8L, 8L, 7L, 7L, 7L, 8L, 7L, 8L, 7L, 8L, 8L, 9L, 7L, 10L, 5L, 7L, 8L, 9L, 5L, 10L, 8L, 7L, 6L, 5L, 6L, 7L, 7L, 7L, 7L, 7L, 7L, 8L, 5L, 6L, 7L, 6L, 7L, 7L, 9L, 6L, 6L, 7L, 7L, 6L, 7L, 8L, 9L, 4L, 6L, 9L ), stringsAsFactors = FALSE ) m_eel <- glm(cured_bin ~ intervention + duration, data = eel, family = binomial()) out <- binned_residuals(m_eel) expect_equal( out$xbar, c(0.27808, 0.28009, 0.28167, 0.28326, 0.48269, 0.56996, 0.57188, 0.57456), tolerance = 1e-4 ) expect_equal( out$CI_low, c(-0.42552, -0.45162, -0.10819, -0.7339, -0.28086, -0.52599, 0.02795, -0.44023), tolerance = 1e-4 ) }) performance/tests/testthat/test-r2_kullback.R0000644000176200001440000000107714570063447021067 0ustar liggesuserstest_that("r2_kullback", { model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") expect_equal(r2_kullback(model), c(`Kullback-Leibler R2` = 0.3834), tolerance = 1e-3) expect_equal(r2_kullback(model, adjust = FALSE), c(`Kullback-Leibler R2` = 0.4232), tolerance = 1e-3) }) test_that("r2_kullback errors for non-supported", { skip_if_not_installed("pscl") data("bioChemists", package = "pscl") model <- pscl::zeroinfl(art ~ . | 1, data = bioChemists, dist = "negbin") expect_error(r2_kullback(model), regex = "This function only works") }) performance/tests/testthat/test-test_likelihoodratio.R0000644000176200001440000001032214412517050023073 0ustar liggesuserstest_that("test_likelihoodratio - regression models", { m1 <- lm(mpg ~ wt + cyl + gear + disp, data = mtcars) m2 <- lm(mpg ~ wt + cyl + gear, data = mtcars) m3 <- lm(mpg ~ wt + cyl, data = mtcars) # stats::anova() rez <- test_likelihoodratio(m1, m2, m3, estimator = "OLS") ref <- anova(m1, m2, m3, test = "LRT") expect_equal(ref$`Pr(>Chi)`, rez$p, tolerance = 1e-03) rez <- test_likelihoodratio(m3, m2, m1, estimator = "OLS") ref <- anova(m3, m2, m1, test = "LRT") expect_equal(ref$`Pr(>Chi)`, rez$p, tolerance = 1e-03) # lmtest::lrtest() rez <- test_likelihoodratio(m1, m2, m3, estimator = "ML") p <- c(NA, 0.5302030, 0.4747344) # lmtest::lrtest(m1, m2, m3)$`Pr(>Chisq)` expect_equal(p, rez$p, tolerance = 1e-03) rez <- test_likelihoodratio(m3, m2, m1, estimator = "ML") p <- c(NA, 0.4747344, 0.5302030) # lmtest::lrtest(m3, m2, m1)$`Pr(>Chisq)` expect_equal(p, rez$p, tolerance = 1e-03) }) test_that("test_likelihoodratio - model names", { m1 <- lm(mpg ~ wt + cyl + gear + disp, data = mtcars) m2 <- lm(mpg ~ wt + cyl + gear, data = mtcars) m3 <- lm(mpg ~ wt + cyl, data = mtcars) rez <- test_likelihoodratio(m1, m2, m3) expect_equal(rez$Name, c("m1", "m2", "m3")) rez <- test_likelihoodratio(list(m1, m2, m3)) expect_equal(rez$Name, c("Model 1", "Model 2", "Model 3")) models <- list(m1, m2, m3) rez <- test_likelihoodratio(models) expect_equal(rez$Name, c("Model 1", "Model 2", "Model 3")) }) test_that("test_likelihoodratio - reversed order", { m1 <- lm(mpg ~ wt + cyl, data = mtcars) m2 <- lm(mpg ~ wt + cyl + gear, data = mtcars) m3 <- lm(mpg ~ wt + cyl + gear + disp, data = mtcars) rez <- test_likelihoodratio(m1, m2, m3, estimator = "OLS") ref <- anova(m1, m2, m3, test = "LRT") expect_equal(ref$`Pr(>Chi)`, rez$p, tolerance = 1e-03) rez <- test_likelihoodratio(m1, m2, m3, estimator = "ML") p <- c(NA, 0.4747344, 0.5302030) # lmtest::lrtest(m1, m2, m3)$`Pr(>Chisq)` expect_equal(p, rez$p, tolerance = 1e-03) }) skip_on_cran() skip_if_not_installed("lme4") m1 <- suppressMessages(lme4::lmer(Sepal.Length ~ Petal.Width + (1 | Species), data = iris)) m2 <- suppressMessages(lme4::lmer(Sepal.Length ~ Petal.Width + Petal.Length + (1 | Species), data = iris)) m3 <- suppressMessages(lme4::lmer(Sepal.Length ~ Petal.Width * Petal.Length + (1 | Species), data = iris)) test_that("test_likelihoodratio - lme4 ML", { t1 <- test_lrt(m1, m2, m3) t2 <- suppressMessages(anova(m1, m2, m3)) expect_equal(attributes(t1)$estimator, "ml") expect_equal(t1$Chi2, c(NA, 85.26365, 0.84141), tolerance = 1e-3) expect_equal(t1$p, c(NA, 0, 0.35899), tolerance = 1e-3) # close, but not the same expect_equal(t1$p, t2$`Pr(>Chisq)`, tolerance = 1e-1) expect_equal(t1$Chi2, t2$Chisq, tolerance = 1e-1) }) test_that("test_likelihoodratio - lme4 OLS", { t2 <- test_lrt(m1, m2, m3, estimator = "ols") expect_equal(attributes(t2)$estimator, "ols") expect_equal(t2$Chi2, c(NA, 105.73844, 1.04346), tolerance = 1e-3) expect_equal(t2$p, c(NA, 0, 0.30702), tolerance = 1e-3) }) test_that("test_likelihoodratio - lme4 REML", { expect_warning(t3 <- test_lrt(m1, m2, m3, estimator = "REML")) expect_equal(attributes(t3)$estimator, "reml") expect_equal(t3$Chi2, c(NA, 89.32933, 2.85635), tolerance = 1e-3) expect_equal(t3$p, c(NA, 0, 0.09101), tolerance = 1e-3) }) m1 <- glm(am ~ mpg, data = mtcars, family = binomial()) m2 <- glm(am ~ mpg + hp, data = mtcars, family = binomial()) m3 <- glm(am ~ mpg + hp + vs, data = mtcars, family = binomial()) test_that("test_likelihoodratio - glm", { t1 <- anova(m1, m2, m3, test = "LRT") t2 <- test_lrt(m1, m2, m3) expect_equal(t1$`Pr(>Chi)`, t2$p, tolerance = 1e-3) expect_equal(t1$Deviance, t2$Chi2, tolerance = 1e-3) expect_equal(attributes(t2)$estimator, "ml") }) m1 <- lm(Sepal.Length ~ Petal.Width, data = iris) m2 <- lm(Sepal.Length ~ Petal.Width + Species, data = iris) m3 <- lm(Sepal.Length ~ Petal.Width * Species, data = iris) test_that("test_likelihoodratio - lm", { t1 <- anova(m1, m2, m3, test = "LRT") t2 <- test_lrt(m1, m2, m3) expect_equal(t1$`Pr(>Chi)`, t2$p, tolerance = 1e-3) expect_equal(attributes(t2)$estimator, "ols") }) performance/tests/testthat/test-check_outliers.R0000644000176200001440000002615514736731423021703 0ustar liggesuserstest_that("zscore negative threshold", { expect_error( check_outliers(mtcars$mpg, method = "zscore", threshold = -1), "The `threshold` argument" ) }) test_that("lof illegal threshold", { skip_if_not_installed("dbscan") expect_error( check_outliers(mtcars$mpg, method = "lof", threshold = -1), "The `threshold` argument" ) expect_error( check_outliers(mtcars$mpg, method = "lof", threshold = 1.1), "The `threshold` argument" ) }) # 1. We first test that each method consistently flags outliers, # (given a specific threshold) test_that("zscore which", { expect_identical( which(check_outliers(mtcars$mpg, method = "zscore", threshold = 2.2)), 20L ) }) test_that("zscore_robust which", { expect_identical( which(check_outliers(mtcars$mpg, method = "zscore_robust", threshold = 2.2)), as.integer(c(18, 20)) ) }) test_that("iqr which", { expect_identical( which(check_outliers(mtcars$mpg, method = "iqr", threshold = 1.2)), as.integer(c(18, 20)) ) }) test_that("ci which", { expect_identical( which(check_outliers(mtcars$mpg, method = "ci", threshold = 0.95)), 20L ) }) test_that("eti which", { expect_identical( which(check_outliers(mtcars$mpg, method = "eti", threshold = 0.95)), 20L ) }) test_that("hdi which", { expect_identical( which(check_outliers(mtcars$mpg, method = "hdi", threshold = 0.90)), as.integer(c(18, 20)) ) }) test_that("bci which", { expect_identical( which(check_outliers(mtcars$mpg, method = "bci", threshold = 0.95)), as.integer(c(15, 16, 20)) ) }) test_that("mahalanobis which", { expect_identical( which(check_outliers(mtcars, method = "mahalanobis", threshold = 20)), as.integer(c(9, 29)) ) }) test_that("mahalanobis_robust which", { skip_if_not_installed("bigutilsr") expect_identical( which(check_outliers(mtcars, method = "mahalanobis_robust", threshold = 25)), as.integer(c(7, 9, 21, 24, 27, 28, 29, 31)) ) }) test_that("mcd which", { skip_if_not_installed("MASS") # (not clear why method mcd needs a seed) set.seed(42) expect_identical( tail(which(check_outliers(mtcars[1:4], method = "mcd", threshold = 45, verbose = FALSE))), 31L ) expect_warning( { out <- check_outliers(mtcars, method = "mcd") }, regex = "The sample size is too small" ) expect_identical(sum(out), 8L) out <- check_outliers(mtcars, method = "mcd", percentage_central = 0.5, verbose = FALSE) expect_identical(sum(out), 15L) }) ## FIXME: Fails on CRAN/windows test_that("ics which", { # suddenly fails on R Under development (unstable) (2023-09-07 r85102) # gcc-13 (Debian 13.2.0-2) 13.2.0 skip_on_cran() skip_if_not_installed("ICS") skip_if_not_installed("ICSOutlier") expect_identical( which(check_outliers(mtcars, method = "ics", threshold = 0.001)), as.integer(c(9, 29)) ) }) test_that("optics which", { skip_if_not_installed("dbscan") expect_identical( which(check_outliers(mtcars, method = "optics", threshold = 14)), as.integer(c(5, 7, 15, 16, 17, 24, 25, 29, 31)) ) }) test_that("lof which", { skip_if_not_installed("dbscan") expect_identical( which(check_outliers(mtcars, method = "lof", threshold = 0.005)), 31L ) }) # 2. Next, we check the print method test_that("zscore print", { expect_output( print(check_outliers(mtcars, method = "zscore", threshold = 2.2)), "5 outliers detected: cases 9, 16, 19, 20, 31." ) }) # 3. Next, we check some attributes since it looks harder than # expected to test the complex print output itself test_that("attributes threshold", { x <- attributes(check_outliers(mtcars, method = "zscore", threshold = 2.2)) expect_equal( as.numeric(x$threshold), 2.2 ) }) test_that("attributes method", { x <- attributes(check_outliers(mtcars, method = "zscore", threshold = 2.2)) expect_identical( x$method, "zscore" ) }) test_that("attributes variables", { x <- attributes(check_outliers(mtcars, method = "zscore", threshold = 2.2)) expect_identical( x$variables, c("mpg", "cyl", "disp", "hp", "drat", "wt", "qsec", "vs", "am", "gear", "carb") ) }) test_that("attributes data", { x <- attributes(check_outliers(mtcars, method = "zscore", threshold = 2.2)) expect_s3_class(x$data, "data.frame") }) test_that("attributes raw data", { x <- attributes(check_outliers(mtcars, method = "zscore", threshold = 2.2)) expect_s3_class(x$raw_data, "data.frame") }) test_that("attributes univariate data frames", { x <- attributes(check_outliers(mtcars, method = "zscore", threshold = 2.2)) expect_s3_class(x$outlier_var$zscore$mpg, "data.frame") }) test_that("attributes outlier count data frame", { x <- attributes(check_outliers(mtcars, method = "zscore", threshold = 2.2)) expect_s3_class(x$outlier_count$all, "data.frame") }) # 4. Next, we test multiple simultaneous methods test_that("multiple methods which", { data <- rbind(mtcars, 99) expect_identical( which(check_outliers(data, method = c("zscore", "iqr"))), 33L ) }) # We exclude method ics because it is too slow test_that("all methods which", { skip_if_not_installed("bigutilsr") skip_if_not_installed("MASS") skip_if_not_installed("dbscan") skip_if_not_installed("ICS") skip_if_not_installed("ICSOutlier") skip_if_not_installed("loo") expect_identical( which(check_outliers(mtcars, method = c( "zscore", "zscore_robust", "iqr", "ci", "eti", "hdi", "bci", "mahalanobis", "mahalanobis_robust", "mcd", "optics", "lof" ), threshold = list( zscore = 2.2, zscore_robust = 2.2, iqr = 1.2, ci = 0.95, eti = 0.95, hdi = 0.90, bci = 0.95, mahalanobis = 20, mahalanobis_robust = 25, mcd = 25, optics = 14, lof = 0.005 ), verbose = FALSE )), as.integer(c(9, 15, 16, 19, 20, 28, 29, 31)) ) }) # 5. Next, we test adding ID test_that("multiple methods with ID", { skip_if_not_installed("bigutilsr") skip_if_not_installed("MASS") skip_if_not_installed("dbscan") skip_if_not_installed("ICS") skip_if_not_installed("ICSOutlier") skip_if_not_installed("loo") data <- datawizard::rownames_as_column(mtcars, var = "car") x <- attributes(check_outliers(data, method = c( "zscore", "zscore_robust", "iqr", "ci", "eti", "hdi", "bci", "mahalanobis", "mahalanobis_robust", "mcd", "optics", "lof" ), threshold = list( zscore = 2.2, zscore_robust = 2.2, iqr = 1.2, ci = 0.95, eti = 0.95, hdi = 0.90, bci = 0.95, mahalanobis = 20, mahalanobis_robust = 25, mcd = 25, optics = 14, lof = 0.005 ), ID = "car", verbose = FALSE )) expect_identical( x$outlier_var$zscore$mpg$car, "Toyota Corolla" ) skip_if(getRversion() > "4.4.0") expect_identical( x$outlier_count$all$car[1], "Maserati Bora" ) }) # 6. Next, we test models test_that("cook which", { model <- lm(disp ~ mpg + hp, data = mtcars) expect_identical( which(check_outliers(model, method = "cook", threshold = list(cook = 0.85))), 31L ) }) ## FIXME: Cannot use a single threshold, but only for this case # test_that("cook which", { # model <- lm(disp ~ mpg + hp, data = mtcars) # expect_equal( # which(check_outliers(model, method = "cook", threshold = 0.85)), # # Error: The `threshold` argument must be NULL (for default values) or a list containing # threshold values for desired methods (e.g., `list('mahalanobis' = 7)`). # 31 # ) # }) test_that("cook multiple methods which", { skip_if_not_installed("dbscan") model <- lm(disp ~ mpg + hp, data = mtcars) expect_identical( which(check_outliers(model, method = c("cook", "optics", "lof"))), 31L ) }) test_that("pareto which", { skip_if_not_installed("dbscan") skip_if_not_installed("loo") skip_if_not_installed("rstanarm") set.seed(123) model <- rstanarm::stan_glm(mpg ~ qsec + wt, data = mtcars, refresh = 0) invisible(capture.output(model)) expect_identical( which(check_outliers(model, method = "pareto", threshold = list(pareto = 0.5))), 17L ) }) test_that("pareto multiple methods which", { skip_if_not_installed("dbscan") skip_if_not_installed("loo") skip_if_not_installed("rstanarm") set.seed(123) model <- rstanarm::stan_glm(mpg ~ qsec + wt, data = mtcars, refresh = 0) invisible(capture.output(model)) expect_identical( which(check_outliers( model, method = c("pareto", "optics"), threshold = list(pareto = 0.3, optics = 11) )), 20L ) }) test_that("BayesFactor which", { skip_if_not_installed("BayesFactor") set.seed(123) model <- BayesFactor::regressionBF(rating ~ ., data = attitude, progress = FALSE) expect_identical( which(check_outliers(model, threshold = list(mahalanobis = 15))), 18L ) }) # 7. Next, we test grouped output test_that("cook multiple methods which", { iris2 <- datawizard::data_group(iris, "Species") z <- attributes(check_outliers(iris2, method = c("zscore", "iqr"))) expect_named( z$outlier_count, c("setosa", "versicolor", "virginica") ) }) test_that("check_outliers with invald data", { dd <- data.frame(y = as.difftime(0:5, units = "days")) m1 <- lm(y ~ 1, data = dd) expect_error( expect_message( check_outliers(m1), regex = "Date variables are not supported" ), regex = "No numeric variables found" ) }) test_that("check_outliers on numeric data only", { data(mtcars) # all predictors categorical mtcars$wt <- as.factor(mtcars$wt) mtcars$mpg <- as.factor(mtcars$mpg) model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") expect_error(check_outliers(model), regex = "No numeric") }) test_that("check_outliers with DHARMa", { skip_if_not_installed("DHARMa") mt1 <- mtcars[, c(1, 3, 4)] # create some fake outliers and attach outliers to main df mt2 <- rbind(mt1, data.frame( mpg = c(37, 40), disp = c(300, 400), hp = c(110, 120) )) # fit model with outliers model <- lm(disp ~ mpg + hp, data = mt2) set.seed(123) res <- simulate_residuals(model) out <- check_outliers(res) expect_equal( out, structure( list( Coefficient = 0.0294117647058824, Expected = 0.00796812749003984, CI_low = 0.000744364234690261, CI_high = 0.153267669560318, p_value = 0.238146844116552 ), class = c("check_outliers_simres", "list") ), ignore_attr = TRUE, tolerance = 1e-4 ) expect_identical( capture.output(print(out)), c( "# Outliers detection", "", " Proportion of observed outliers: 2.94%", " Proportion of expected outliers: 0.80%, 95% CI [0.07, 15.33]", "" ) ) }) test_that("check_outliers with DHARMa", { data(mtcars) out <- check_outliers(mtcars$mpg, method = "zscore", threshold = 2) expect_equal(which(as.numeric(out) == 1), c(18, 20)) }) performance/tests/testthat/test-r2_tjur.R0000644000176200001440000000044114355271477020262 0ustar liggesuserstest_that("r2_tjur", { model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") expect_equal(r2_tjur(model), c(`Tjur's R2` = 0.477692621360749), tolerance = 1e-3) }) test_that("r2_tjur", { model <- lm(mpg ~ wt + cyl, data = mtcars) expect_error(r2_tjur(model)) }) performance/tests/testthat/test-compare_performance.R0000644000176200001440000000532514715376125022704 0ustar liggesuserstest_that("compare_performance", { data(iris) lm1 <- lm(Sepal.Length ~ Species, data = iris) lm2 <- lm(Sepal.Length ~ Species + Petal.Length, data = iris) lm3 <- lm(Sepal.Length ~ Species * Petal.Length, data = iris) lm4 <- lm(Sepal.Length ~ Species * Petal.Length, data = iris[-1, ]) expect_silent(expect_identical( colnames(compare_performance(lm1, lm2, lm3)), c("Name", "Model", "AIC", "AIC_wt", "AICc", "AICc_wt", "BIC", "BIC_wt", "R2", "R2_adjusted", "RMSE", "Sigma") )) expect_message( expect_identical( colnames(compare_performance(lm1, lm2, lm3, lm4)), c("Name", "Model", "AIC", "AIC_wt", "AICc", "AICc_wt", "BIC", "BIC_wt", "R2", "R2_adjusted", "RMSE", "Sigma") ) ) # table split expect_snapshot(print(compare_performance(lm1, lm2, lm3))) expect_snapshot(print(compare_performance(lm1, lm2, lm3), table_width = Inf)) # vertical layout expect_snapshot(print(compare_performance(lm1, lm2, lm3), layout = "vertical")) expect_snapshot(print(compare_performance(lm1, lm2, lm3, lm4), layout = "vertical", table_width = 50)) expect_silent(expect_identical( colnames(compare_performance(lm1, lm2, lm3, lm4, verbose = FALSE)), c("Name", "Model", "AIC", "AIC_wt", "AICc", "AICc_wt", "BIC", "BIC_wt", "R2", "R2_adjusted", "RMSE", "Sigma") )) out <- compare_performance(lm1, lm2, lm3, lm4, verbose = FALSE) expect_identical(out$Name, c("lm1", "lm2", "lm3", "lm4")) models <- list(Interaction = lm3, NoInteraction = lm2, SingleTerm = lm1) rez <- compare_performance(models) expect_equal(rez$Name, c("Interaction", "NoInteraction", "SingleTerm"), ignore_attr = TRUE) out <- compare_performance(list(lm1, lm2, lm3, lm4), verbose = FALSE) expect_identical( colnames(out), c("Name", "Model", "AIC", "AIC_wt", "AICc", "AICc_wt", "BIC", "BIC_wt", "R2", "R2_adjusted", "RMSE", "Sigma") ) expect_identical(out$Name, c("Model 1", "Model 2", "Model 3", "Model 4")) models <- list(lm1, lm2, lm3, lm4) out <- compare_performance(models, verbose = FALSE) expect_identical( colnames(out), c("Name", "Model", "AIC", "AIC_wt", "AICc", "AICc_wt", "BIC", "BIC_wt", "R2", "R2_adjusted", "RMSE", "Sigma") ) expect_identical(out$Name, c("Model 1", "Model 2", "Model 3", "Model 4")) expect_silent(compare_performance(lm1, lm2, estimator = "REML")) }) test_that("compare_performance, REML fit", { skip_if_not_installed("lme4") m1 <- lme4::lmer(Petal.Length ~ Sepal.Length + (1 | Species), data = iris) m2 <- lme4::lmer(Petal.Length ~ Sepal.Length + Sepal.Width + (1 | Species), data = iris) expect_silent(compare_performance(m1, m2)) expect_message(compare_performance(m1, m2, estimator = "REML")) }) performance/tests/testthat/test-check_heteroskedasticity.R0000644000176200001440000000122414576267034023736 0ustar liggesuserstest_that("check_heteroskedasticity", { data(mtcars) m <- lm(mpg ~ wt + cyl + gear + disp, data = mtcars) out <- check_heteroscedasticity(m) expect_equal(as.vector(out), 0.0423, ignore_attr = TRUE, tolerance = 1e-2) expect_identical( capture.output(print(out)), "Warning: Heteroscedasticity (non-constant error variance) detected (p = 0.042)." ) m <- lm(mpg ~ hp, data = mtcars) out <- check_heteroscedasticity(m) expect_equal(as.vector(out), 0.8271352, ignore_attr = TRUE, tolerance = 1e-2) expect_identical( capture.output(print(out)), "OK: Error variance appears to be homoscedastic (p = 0.827)." ) }) performance/tests/testthat/test-check_singularity.R0000644000176200001440000000210614676732355022405 0ustar liggesuserstest_that("check_singularity, lme4", { skip_on_cran() skip_if_not_installed("lme4") data(sleepstudy, package = "lme4") set.seed(123) sleepstudy$mygrp <- sample.int(5, size = 180, replace = TRUE) sleepstudy$mysubgrp <- NA for (i in 1:5) { filter_group <- sleepstudy$mygrp == i sleepstudy$mysubgrp[filter_group] <- sample.int(30, size = sum(filter_group), replace = TRUE) } model <- suppressMessages(lme4::lmer( Reaction ~ Days + (1 | mygrp / mysubgrp) + (1 | Subject), data = sleepstudy )) expect_true(check_singularity(model)) }) test_that("check_singularity", { skip_on_cran() skip_if_not_installed("glmmTMB") set.seed(101) dd <- expand.grid(x = factor(1:6), f = factor(1:20), rep = 1:5) dd$y <- glmmTMB::simulate_new(~ 1 + (x | f), newdata = dd, newparam = list( beta = 0, theta = rep(0, 21), betadisp = 0 ) )[[1]] expect_warning(expect_warning({ m2 <- glmmTMB::glmmTMB(y ~ 1 + (x | f), data = dd, REML = FALSE) })) expect_true(check_singularity(m2)) }) performance/tests/testthat/test-check_normality.R0000644000176200001440000000557014676732355022061 0ustar liggesuserstest_that("check_normality | afex", { skip_if_not(getRversion() >= "4.0.0") skip_if_not_installed("afex") data(obk.long, package = "afex") obk.long$treatment <- as.character(obk.long$treatment) suppressWarnings(suppressMessages({ aM <- afex::aov_car(value ~ treatment * gender + Error(id / (phase * hour)), data = obk.long ) aW <- afex::aov_car(value ~ Error(id / (phase * hour)), data = obk.long ) aB <- afex::aov_car(value ~ treatment * gender + Error(id), data = obk.long ) })) msg <- capture.output({ pM <- check_normality(aM) }) msg <- capture.output({ pW <- check_normality(aW) }) msg <- capture.output({ pB <- check_normality(aB) }) expect_equal(pM, 0.2054236, ignore_attr = TRUE, tolerance = 0.001) expect_equal(pW, 0.5496325, ignore_attr = TRUE, tolerance = 0.001) expect_equal(pB, 0.734765, ignore_attr = TRUE, tolerance = 0.001) }) test_that("check_normality | glmmTMB", { skip_if_not_installed("glmmTMB") skip_if_not(getRversion() >= "4.0.0") data("Salamanders", package = "glmmTMB") m <- glmmTMB::glmmTMB( count ~ mined + spp + (1 | site), family = poisson, data = Salamanders ) out <- check_normality(m, effects = "random") expect_identical(attributes(out)$re_groups, "site: (Intercept)") expect_equal(as.vector(out), 0.698457693553405, tolerance = 1e-3) expect_message( { out <- check_normality(m, effects = "fixed") }, "for linear models" ) expect_null(out) }) test_that("check_normality | t-test", { data(mtcars) expect_error( check_normality(t.test(mtcars$mpg, mtcars$hp, var.equal = FALSE)), regex = "Discrete or character variables" ) out <- t.test(mtcars$mpg, mtcars$hp, var.equal = TRUE) expect_equal( check_normality(out), structure( 7.15789362314837e-12, type = "residuals", object_name = out, effects = "fixed", class = c( "check_normality", "see_check_normality", "numeric" ) ), tolerance = 1e-3, ignore_attr = TRUE ) }) test_that("check_normality | simulated residuals", { skip_if_not_installed("DHARMa") m <- lm(mpg ~ wt + cyl + gear + disp, data = mtcars) res <- simulate_residuals(m) out <- check_normality(res) expect_equal( as.numeric(out), 0.2969038, tolerance = 1e-3, ignore_attr = TRUE ) expect_identical( capture.output(print(out)), "OK: residuals appear as normally distributed (p = 0.297)." ) m <- lm(mpg ~ wt + cyl + gear + disp, data = mtcars) out <- check_normality(m) expect_equal( as.numeric(out), 0.2303071, tolerance = 1e-3, ignore_attr = TRUE ) expect_identical( capture.output(print(out)), "OK: residuals appear as normally distributed (p = 0.230)." ) }) performance/tests/testthat/test-check_convergence.R0000644000176200001440000000233414676732355022334 0ustar liggesuserstest_that("check_convergence", { skip_if_not_installed("lme4") data(cbpp, package = "lme4") set.seed(1) cbpp$x <- rnorm(nrow(cbpp)) cbpp$x2 <- runif(nrow(cbpp)) model <- suppressWarnings(lme4::glmer( cbind(incidence, size - incidence) ~ period + x + x2 + (1 + x | herd), data = cbpp, family = binomial() )) expect_true(check_convergence(model)) expect_equal( check_convergence(model), structure(TRUE, gradient = 0.000280307452338331), tolerance = 1e-3 ) }) test_that("check_convergence", { skip_if_not_installed("lme4") data(sleepstudy, package = "lme4") model <- lme4::lmer(Reaction ~ Days + (1 + Days | Subject), data = sleepstudy) expect_true(check_convergence(model)) }) test_that("check_convergence, glmmTMB", { skip_if_not_installed("glmmTMB") data(iris) model <- suppressWarnings(glmmTMB::glmmTMB( Sepal.Length ~ poly(Petal.Width, 4) * poly(Petal.Length, 4) + (1 + poly(Petal.Width, 4) | Species), data = iris )) expect_false(check_convergence(model)) model <- suppressWarnings(glmmTMB::glmmTMB( Sepal.Length ~ Petal.Width + (1 | Species), data = iris )) expect_true(check_convergence(model)) }) performance/tests/testthat/test-mclogit.R0000644000176200001440000000263714412517050020322 0ustar liggesusersskip_if_not_installed("mclogit") data(Transport, package = "mclogit") mod_mb <- mclogit::mblogit(factor(gear) ~ mpg + hp, data = mtcars, trace = FALSE) mod_mc <- mclogit::mclogit(resp | suburb ~ distance + cost, data = Transport, trace = FALSE) test_that("r2 Nagelkerke", { expect_equal( r2_nagelkerke(mod_mb), mclogit::getSummary.mblogit(mod_mb)$sumstat["Nagelkerke"], ignore_attr = TRUE, tolerance = 1e-4 ) expect_equal( r2_nagelkerke(mod_mc), mclogit::getSummary.mclogit(mod_mc)$sumstat["Nagelkerke"], ignore_attr = TRUE, tolerance = 1e-4 ) }) test_that("r2 McFadden", { expect_equal( r2_mcfadden(mod_mb), mclogit::getSummary.mblogit(mod_mb)$sumstat["McFadden"], ignore_attr = TRUE, tolerance = 1e-4 ) expect_equal( r2_mcfadden(mod_mc), mclogit::getSummary.mclogit(mod_mc)$sumstat["McFadden"], ignore_attr = TRUE, tolerance = 1e-4 ) }) test_that("r2 CoxSnell", { expect_equal( r2_coxsnell(mod_mb), mclogit::getSummary.mblogit(mod_mb)$sumstat["Cox.Snell"], ignore_attr = TRUE, tolerance = 1e-4 ) expect_equal( r2_coxsnell(mod_mc), mclogit::getSummary.mclogit(mod_mc)$sumstat["Cox.Snell"], ignore_attr = TRUE, tolerance = 1e-4 ) }) test_that("model_performance", { expect_snapshot(model_performance(mod_mb)) expect_snapshot(model_performance(mod_mc)) }) performance/tests/testthat/test-r2_bayes.R0000644000176200001440000000307614645233345020402 0ustar liggesusersskip_on_os("linux") test_that("r2_BayesFactor", { skip_if_not_installed("BayesFactor") set.seed(1) BFM <- BayesFactor::generalTestBF(mpg ~ cyl * gear, data = mtcars, progress = FALSE) r_BF <- r2(BFM[4], ci = 0.89) r_CI <- attr(r_BF, "CI")$R2_Bayes expect_equal(r_BF$R2_Bayes, 0.71, tolerance = 0.05) expect_equal(r_CI$CI_low, 0.62, tolerance = 0.05) expect_equal(r_CI$CI_high, 0.79, tolerance = 0.05) r_post <- r2_posterior(BFM[1]) expect_s3_class(r_post, "data.frame") r_BF <- r2(BFM, average = TRUE) expect_equal(r_BF$R2_Bayes, 0.72, tolerance = 0.05) # with random effects: skip_if_not_installed("BayesFactor", minimum_version = "0.9.12.4.3") mtcars$gear <- factor(mtcars$gear) model <- BayesFactor::lmBF(mpg ~ hp + cyl + gear + gear:wt, mtcars, progress = FALSE, whichRandom = c("gear", "gear:wt")) r_BF <- r2(model, ci = 0.89) r_CI <- attr(r_BF, "CI")$R2_Bayes expect_equal(r_BF$R2_Bayes, 0.36, tolerance = 0.05) expect_equal(r_BF$R2_Bayes_marginal, 0.21, tolerance = 0.05) expect_equal(r_CI$CI_low, 0.27, tolerance = 0.05) expect_equal(r_CI$CI_high, 0.54, tolerance = 0.05) }) test_that("r2_bayes", { skip_on_cran() skip_if_not_installed("curl") skip_if_offline() skip_if_not_installed("httr2") skip_if_not_installed("rstanarm") skip_if_not_installed("rstantools") model <- insight::download_model("stanreg_lmerMod_1") set.seed(123) out <- r2_bayes(model) expect_equal(out$R2_Bayes, 0.642, tolerance = 1e-3) expect_equal(out$R2_Bayes_marginal, 0.58534, tolerance = 1e-3) }) performance/tests/testthat/test-check_zeroinflation.R0000644000176200001440000001035114706655512022710 0ustar liggesuserstest_that("check_zeroinflation", { skip_if_not_installed("glmmTMB") set.seed(123) data(Salamanders, package = "glmmTMB") m <- glm(count ~ spp + mined, family = poisson, data = Salamanders) expect_equal( check_zeroinflation(m), structure( list( predicted.zeros = 298, observed.zeros = 387L, ratio = 0.770025839793282, tolerance = 0.05 ), class = "check_zi" ), tolerance = 1e-3 ) }) test_that("check_zeroinflation, glmmTMB with and without zero-inflation component", { skip_if_not_installed("glmmTMB") skip_if_not_installed("DHARMa") set.seed(123) data(Salamanders, package = "glmmTMB") # no zero-inflation model m <- glmmTMB::glmmTMB(count ~ spp + mined, family = poisson, data = Salamanders) expect_equal( check_zeroinflation(m), structure( list( predicted.zeros = 298, observed.zeros = 387L, ratio = 0.770025839793282, tolerance = 0.05 ), class = "check_zi" ), tolerance = 1e-3 ) # zero-inflation model m <- glmmTMB::glmmTMB( count ~ spp + mined, ziformula = ~ spp + mined, family = poisson, data = Salamanders ) set.seed(123) expect_equal( check_zeroinflation(m), structure( list( predicted.zeros = 387, observed.zeros = 387L, ratio = 1.00093023255814, tolerance = 0.1, p.value = 1 ), class = "check_zi" ), tolerance = 1e-3 ) }) test_that("check_zeroinflation, glmer.nb", { skip_on_cran() skip_if_not_installed("glmmTMB") skip_if_not_installed("lme4") set.seed(101) data(Salamanders, package = "glmmTMB") dd <- expand.grid( f1 = factor(1:3), f2 = LETTERS[1:2], g = 1:9, rep = 1:15, KEEP.OUT.ATTRS = FALSE ) mu <- 5 * (-4 + with(dd, as.integer(f1) + 4 * as.numeric(f2))) dd$y <- rnbinom(nrow(dd), mu = mu, size = 0.5) dat2 <<- dd suppressMessages({ m <- lme4::glmer.nb(y ~ f1 * f2 + (1 | g), data = dat2, verbose = FALSE) }) expect_equal( check_zeroinflation(m), structure( list( predicted.zeros = 153, observed.zeros = 155L, ratio = 0.987329032258065, tolerance = 0.1, p.value = 0.944 ), class = "check_zi" ), tolerance = 1e-3 ) }) test_that("check_zeroinflation, glmmTMB nbinom", { skip_if_not_installed("glmmTMB") skip_if_not_installed("DHARMa") skip_on_cran() data(Salamanders, package = "glmmTMB") m <- glmmTMB::glmmTMB( count ~ spp + mined + (1 | site), family = glmmTMB::nbinom1(), data = Salamanders ) set.seed(1234) expect_equal( check_zeroinflation(m), structure( list( predicted.zeros = 389, observed.zeros = 387L, ratio = 1.00635658914729, tolerance = 0.1, p.value = 0.944 ), class = "check_zi" ), tolerance = 1e-3 ) }) test_that("check_zeroinflation, MASS::negbin", { skip_if_not_installed("MASS") skip_if_not_installed("DHARMa") set.seed(3) mu <- rpois(500, lambda = 3) x <- rnorm(500, mu, mu * 3) x <- ceiling(x) x <- pmax(x, 0) m <- MASS::glm.nb(x ~ mu) expect_equal( check_zeroinflation(m), structure( list( predicted.zeros = 178, observed.zeros = 202L, ratio = 0.879643564356436, tolerance = 0.1, p.value = 0.008 ), class = "check_zi" ), ignore_attr = TRUE, tolerance = 1e-4 ) }) test_that("check_zeroinflation, genpois", { skip_if_not_installed("glmmTMB") skip_if_not_installed("DHARMa") skip_if_not(getRversion() >= "4.0.0") data(Salamanders, package = "glmmTMB") model <- glmmTMB::glmmTMB( count ~ mined + spp + (1 | site), family = glmmTMB::genpois(), data = Salamanders ) expect_equal( check_zeroinflation(model), structure( list( predicted.zeros = 386, observed.zeros = 387L, ratio = 0.997860465116279, tolerance = 0.1, p.value = 1 ), class = "check_zi" ), tolerance = 1e-4, ignore_attr = TRUE ) }) performance/tests/testthat/test-pkg-fixest.R0000644000176200001440000000612114736731423020750 0ustar liggesusersbase_iris <- iris names(base_iris) <- c("y1", "y2", "x1", "x2", "species") test_that("fixest: r2", { skip_if_not_installed("fixest") fixest::setFixest_nthreads(1) res <- fixest::feols(y1 ~ x1 + x2 + x2^2 | species, base_iris) r2_res <- performance::r2(res) expect_equal(r2_res$R2, fixest::fitstat(res, "r2")[[1]], ignore_attr = TRUE) expect_equal(r2_res$R2_adjusted, fixest::fitstat(res, "ar2")[[1]], ignore_attr = TRUE) expect_equal(r2_res$R2_within, fixest::fitstat(res, "wr2")[[1]], ignore_attr = TRUE) expect_equal(r2_res$R2_within_adjusted, fixest::fitstat(res, "war2")[[1]], ignore_attr = TRUE) }) test_that("fixest: overdispersion", { skip_if_not_installed("fixest") fixest::setFixest_nthreads(1) res <- fixest::feols(y1 ~ x1 + x2 + x2^2 | species, base_iris) expect_error( check_overdispersion(res), "can only be used for models from Poisson" ) }) test_that("fixest: outliers", { skip_if_not_installed("fixest") fixest::setFixest_nthreads(1) res <- fixest::feols(y1 ~ x1 + x2 + x2^2 | species, base_iris) outliers_list <- suppressMessages(check_outliers(res)) expect_identical(attr(outliers_list, "outlier_count"), list()) }) test_that("fixest: model_performance", { skip_if_not_installed("fixest") fixest::setFixest_nthreads(1) res <- fixest::feols(y1 ~ x1 + x2 + x2^2 | species, base_iris) perf <- model_performance(res) expect_equal(perf$AIC, 107.743, tolerance = 1e-3) expect_equal(perf$BIC, 125.807, tolerance = 1e-3) expect_equal(perf$R2, 0.837, tolerance = 1e-3) expect_equal(perf$R2_adjusted, 0.832, tolerance = 1e-3) expect_equal(perf$R2_within, 0.573, tolerance = 1e-3) expect_equal(perf$R2_within_adjusted, 0.564, tolerance = 1e-3) expect_equal(perf$RMSE, 0.333, tolerance = 1e-3) expect_equal(perf$Sigma, 0.340, tolerance = 1e-3) }) test_that("fixest_multi: r2", { skip_if_not_installed("fixest") fixest::setFixest_nthreads(1) res <- fixest::feols(c(y1, y2) ~ x1 + csw(x2, x2^2) | species, base_iris) r2_res <- performance::r2(res) expect_equal(unname(r2_res[[1]]$R2), 0.837, tolerance = 1e-3) }) test_that("fixest_multi: overdispersion", { skip_if_not_installed("fixest") fixest::setFixest_nthreads(1) res <- fixest::feols(c(y1, y2) ~ x1 + csw(x2, x2^2) | species, base_iris) expect_error( check_overdispersion(res), "can only be used for models from Poisson" ) }) test_that("fixest_multi: outliers", { skip_if_not_installed("fixest") fixest::setFixest_nthreads(1) res <- fixest::feols(c(y1, y2) ~ x1 + csw(x2, x2^2) | species, base_iris) outliers_list <- suppressMessages(check_outliers(res)[[1]]) expect_identical(attr(outliers_list, "outlier_count"), list()) }) test_that("fixest_multi: model_performance", { skip_if_not_installed("fixest") fixest::setFixest_nthreads(1) res <- fixest::feols(c(y1, y2) ~ x1 + csw(x2, x2^2) | species, base_iris) res2 <- fixest::feols(y1 ~ x1 + x2 + x2^2 | species, base_iris) perf <- model_performance(res) perf2 <- model_performance(res2) expect_identical(perf[[2]], perf2) }) performance/tests/testthat/test-glmmPQL.R0000644000176200001440000000112714546750702020201 0ustar liggesusersskip_if_not_installed("MASS") test_that("r2", { example_dat <- data.frame( prop = c(0.2, 0.2, 0.5, 0.7, 0.1, 1, 1, 1, 0.1), size = c("small", "small", "small", "large", "large", "large", "large", "small", "small"), x = c(0.1, 0.1, 0.8, 0.7, 0.6, 0.5, 0.5, 0.1, 0.1), species = c("sp1", "sp1", "sp2", "sp2", "sp3", "sp3", "sp4", "sp4", "sp4"), stringsAsFactors = FALSE ) mn <- MASS::glmmPQL(prop ~ x + size, random = ~ 1 | species, family = "quasibinomial", data = example_dat ) expect_message(performance_score(mn), regex = "Can't calculate") }) performance/tests/testthat/test-pkg-ivreg.R0000644000176200001440000000047014620351763020560 0ustar liggesuserstest_that("Issue #530 from the `modelsummary` repo", { skip_if_not_installed("ivreg") # for ivreg diagnostics data(mtcars) iv_model <- suppressMessages(ivreg::ivreg(mpg ~ qsec + cyl + drat | disp | wt, data = mtcars)) out <- expect_silent(model_performance(iv_model)) expect_snapshot(out) }) performance/tests/testthat/test-nestedLogit.R0000644000176200001440000000271314620351763021150 0ustar liggesusersskip_on_os(c("mac", "linux")) skip_if_not_installed("nestedLogit") skip_if_not_installed("carData") data("Womenlf", package = "carData") comparisons <- nestedLogit::logits( work = nestedLogit::dichotomy("not.work", working = c("parttime", "fulltime")), full = nestedLogit::dichotomy("parttime", "fulltime") ) mnl <- nestedLogit::nestedLogit( partic ~ hincome + children, dichotomies = comparisons, data = Womenlf ) test_that("r2", { out <- r2(mnl) expect_equal( out, list(R2_Tjur = list( work = c(`Tjur's R2` = 0.137759452521642), full = c(`Tjur's R2` = 0.332536937208286) )), ignore_attr = TRUE, tolerance = 1e-4 ) out <- r2_tjur(mnl) expect_equal( out, list( work = c(`Tjur's R2` = 0.137759452521642), full = c(`Tjur's R2` = 0.332536937208286) ), ignore_attr = TRUE, tolerance = 1e-4 ) out <- r2_coxsnell(mnl) expect_equal( out, list( work = c(`Cox & Snell's R2` = 0.129313084315599), full = c(`Cox & Snell's R2` = 0.308541455410686) ), ignore_attr = TRUE, tolerance = 1e-4 ) out <- r2_nagelkerke(mnl) expect_equal( out, list( work = c(`Nagelkerke's R2` = 0.174313365512442), full = c(`Nagelkerke's R2` = 0.418511411473948) ), ignore_attr = TRUE, tolerance = 1e-4 ) }) test_that("model_performance", { expect_snapshot(model_performance(mnl)) }) performance/tests/testthat/test-r2_mlm.R0000644000176200001440000000054614666017356020070 0ustar liggesuserstest_that("r2_mlm_Rxy", { model <- lm(cbind(qsec, drat) ~ wt + mpg, data = mtcars) expect_equal(r2_mlm(model)[["Symmetric Rxy"]], 0.68330688076502, tolerance = 1e-3) }) test_that("r2_mlm_Pxy", { model <- lm(cbind(qsec, drat) ~ wt + mpg, data = mtcars) expect_equal(r2_mlm(model)[["Asymmetric Pxy"]], 0.407215267524997, tolerance = 1e-3) }) performance/tests/testthat/test-check_itemscale.R0000644000176200001440000000357414574064055022003 0ustar liggesuserstest_that("check_itemscale", { skip_if_not_installed("parameters") set.seed(123) d <- data.frame( a = sample.int(3, 100, replace = TRUE) + 3, b = sample.int(3, 100, replace = TRUE) + 3, c = sample.int(3, 100, replace = TRUE) + 3, d = sample.int(3, 100, replace = TRUE), e = sample.int(3, 100, replace = TRUE), f = sample.int(3, 100, replace = TRUE) ) pca <- parameters::principal_components(d, n = 2) out <- check_itemscale(pca) expect_length(out, 2L) expect_equal( out[[1]]$Mean, vapply(d[out[[1]]$Item], mean, numeric(1)), tolerance = 1e-4, ignore_attr = TRUE ) expect_equal( out[[2]]$Difficulty, item_difficulty(d[out[[2]]$Item])$Difficulty, tolerance = 1e-4, ignore_attr = TRUE ) expect_snapshot(print(out), variant = "windows") comp <- parameters::closest_component(pca) out2 <- check_itemscale(d, comp) expect_equal( out[[1]]$Mean, out2[[1]]$Mean, tolerance = 1e-4, ignore_attr = TRUE ) expect_equal( out[[1]]$Difficulty, out2[[1]]$Difficulty, tolerance = 1e-4, ignore_attr = TRUE ) # factor_index as none-named vector out3 <- check_itemscale(d, factor_index = c(2, 1, 2, 2, 1, 1)) expect_equal( out[[1]]$Mean, out3[[1]]$Mean, tolerance = 1e-4, ignore_attr = TRUE ) expect_equal( out[[1]]$Difficulty, out3[[1]]$Difficulty, tolerance = 1e-4, ignore_attr = TRUE ) expect_error( check_itemscale(d), regex = "If `x` is a data" ) expect_error( check_itemscale(d, factor_index = 1:8), regex = "`factor_index` must be of same" ) expect_error( check_itemscale(d, factor_index = factor(comp)), regex = "`factor_index` must be numeric." ) expect_error( check_itemscale(iris$Species), regex = "`x` must be an object of class" ) }) performance/tests/testthat/test-item_discrimination.R0000644000176200001440000000073114362215436022716 0ustar liggesuserstest_that("item_discrimination", { data(iris) x <- iris[, 1:4] expect_equal( item_discrimination(x), structure(list(Item = c( "Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width" ), Discrimination = c( 0.894040250011166, -0.348657747269071, 0.863271047498634, 0.921040960149154 )), class = c( "item_discrimination", "data.frame" ), row.names = c(NA, -4L)), tolerance = 1e-3 ) }) performance/tests/testthat/test-helpers.R0000644000176200001440000000076714645233345020342 0ustar liggesusersskip_on_cran() skip_if_not_installed("withr") withr::with_options( list(easystats_errors = TRUE), test_that(".safe works with options", { expect_error(performance:::.safe(mean(fd)), regex = "object 'fd' not found") expect_identical(performance:::.safe(mean(fd), 1L), 1L) expect_identical(performance:::.safe(mean(c(1, 2, 3))), 2) }) ) test_that(".safe works", { expect_null(performance:::.safe(mean(fd))) expect_identical(performance:::.safe(mean(c(1, 2, 3))), 2) }) performance/tests/testthat/test-model_performance.lm.R0000644000176200001440000000210514355271477022762 0ustar liggesuserstest_that("model_performance.lm", { model <- lm(mpg ~ wt + cyl, data = mtcars) expect_equal(model_performance(model)$R2, 0.830, tolerance = 0.01) expect_equal( colnames(model_performance(model)), c("AIC", "AICc", "BIC", "R2", "R2_adjusted", "RMSE", "Sigma") ) }) test_that("model_performance.glm", { model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") expect_equal(model_performance(model)$R2_Tjur, 0.478, tolerance = 0.01) expect_equal( colnames(model_performance(model)), c( "AIC", "AICc", "BIC", "R2_Tjur", "RMSE", "Sigma", "Log_loss", "Score_log", "Score_spherical", "PCP" ) ) }) test_that("model_performance.glm-factor", { model <- glm(factor(vs, labels = c("automatic", "manual")) ~ wt + mpg, data = mtcars, family = "binomial") expect_equal(model_performance(model)$R2_Tjur, 0.478, tolerance = 0.01) expect_equal( colnames(model_performance(model)), c( "AIC", "AICc", "BIC", "R2_Tjur", "RMSE", "Sigma", "Log_loss", "Score_log", "Score_spherical", "PCP" ) ) }) performance/tests/testthat/test-item_splithalf.R0000644000176200001440000000056314355271477021704 0ustar liggesuserstest_that("item_split_half", { data(iris) x <- iris[, 1:4] expect_equal( item_split_half(x), list( splithalf = 0.7864936, spearmanbrown = 0.8804886 ), tolerance = 1e-3 ) x <- iris[, 1:2] expect_equal( item_split_half(x), list(splithalf = -0.11757, spearmanbrown = -0.26647), tolerance = 1e-3 ) }) performance/tests/testthat/test-check_residuals.R0000644000176200001440000000557414705407645022034 0ustar liggesuserstest_that("check_residuals and simulate_residuals", { skip_on_cran() skip_if_not_installed("DHARMa") set.seed(123) dat <- DHARMa::createData(sampleSize = 100, overdispersion = 0.5, family = poisson()) m <- glm(observedResponse ~ Environment1, family = poisson(), data = dat) res <- simulate_residuals(m) expect_identical( capture.output(print(res)), c( "Simulated residuals from a model of class `glm` based on 250", " simulations. Use `check_residuals()` to check uniformity of residuals or", " `residuals()` to extract simulated residuals. It is recommended to refer", " to `?DHARMa::simulateResiudals` and `vignette(\"DHARMa\")` for more", " information about different settings in particular situations or for", " particular models." ) ) # check raw residuals expect_equal( head(residuals(res)), c(0.01815, 0.7062, 0.56076, 0.19282, 0.31423, 0.10115), tolerance = 1e-4, ignore_attr = TRUE ) expect_equal( head(residuals(res, quantile_function = stats::qnorm)), c(-2.09365, 0.54232, 0.1529, -0.86756, -0.4839, -1.27504), tolerance = 1e-4, ignore_attr = TRUE ) # compare to DHARMa res_d <- DHARMa::simulateResiduals(m, n = 250, plot = FALSE) expect_equal( head(residuals(res)), head(residuals(res_d)), tolerance = 1e-4, ignore_attr = TRUE ) expect_equal( head(residuals(res, quantile_function = stats::qnorm)), head(residuals(res_d, quantileFunction = stats::qnorm)), tolerance = 1e-4, ignore_attr = TRUE ) # DHARMa args work in residuals.permormance_simres expect_equal( residuals(res, quantileFunction = stats::qnorm, outlierValues = c(-3, 3)), residuals(res_d, quantileFunction = stats::qnorm, outlierValues = c(-3, 3)), tolerance = 1e-4, ignore_attr = TRUE ) # outlier_values works expect_identical(sum(is.infinite(residuals(res, quantile_function = stats::qnorm))), 3L) expect_identical(sum(is.infinite(residuals(res, quantile_function = stats::qnorm, outlier_values = c(-100, 100)))), 0L) # nolint expect_error(residuals(res, quantile_function = stats::qnorm, outlier_values = 1:3), regex = "`outlier_values` must be") # nolint # check_residuals out <- check_residuals(res) expect_equal(out, 0.02574286, ignore_attr = TRUE, tolerance = 1e-4) expect_identical( capture.output(print(out)), "Warning: Non-uniformity of simulated residuals detected (p = 0.026)." ) expect_error(simulate_residuals(m, iterations = 1), "`iterations` must be") skip_if_not_installed("MASS") set.seed(3) mu <- rpois(500, lambda = 3) x <- rnorm(500, mu, mu * 3) x <- ceiling(x) x <- pmax(x, 0) quine.nb1 <- MASS::glm.nb(x ~ mu) set.seed(123) result <- check_residuals(quine.nb1) expect_equal(result, 0.000665414, tolerance = 1e-3, ignore_attr = TRUE) }) performance/tests/testthat/test-coxph.R0000644000176200001440000000171014412517050017774 0ustar liggesusersskip_if_not_installed("survival") lung <- survival::lung lung <- subset(lung, subset = ph.ecog %in% 0:2) lung$sex <- factor(lung$sex, labels = c("male", "female")) lung$ph.ecog <- factor(lung$ph.ecog, labels = c("good", "ok", "limited")) m1 <- survival::coxph(survival::Surv(time, status) ~ sex + age + ph.ecog, data = lung) test_that("r2", { expect_equal(r2_nagelkerke(m1), c(`Nagelkerke's R2` = 0.1203544), tolerance = 1e-3) expect_equal(r2(m1), list(R2 = c(`Nagelkerke's R2` = 0.1203544)), tolerance = 1e-3, ignore_attr = TRUE) }) test_that("model_performance", { perf <- suppressWarnings(model_performance(m1, verbose = FALSE)) expect_equal(perf$AIC, 1457.19458886438, tolerance = 1e-3) expect_equal(perf$BIC, 1469.5695896676, tolerance = 1e-3) expect_equal(perf$R2_Nagelkerke, 0.1203544, tolerance = 1e-3) expect_equal(perf$RMSE, 0.882014942836432, tolerance = 1e-3) }) test_that("r2", { expect_error(r2_xu(m1)) }) performance/tests/testthat/test-checks.R0000644000176200001440000000200114576267034020124 0ustar liggesuserstest_that("check_factorstructure", { skip_if_not_installed("parameters") x <- check_factorstructure(mtcars) expect_equal(x$KMO$MSA, 0.8265536, tolerance = 0.01) expect_equal(x$sphericity$chisq, 408.0116, tolerance = 0.01) }) test_that("check_clusterstructure, ok", { skip_if_not_installed("parameters") set.seed(333) out <- check_clusterstructure(iris[, 1:4]) expect_equal(out$H, 0.1869618, tolerance = 0.01) expect_identical( capture.output(print(out)), c( "# Clustering tendency", "", "The dataset is suitable for clustering (Hopkins' H = 0.19)." ) ) }) test_that("check_clusterstructure, bad", { skip_if_not_installed("parameters") set.seed(13) out <- check_clusterstructure(mtcars[, 10:11]) expect_equal(out$H, 0.5142575, tolerance = 0.01) expect_identical( capture.output(print(out)), c( "# Clustering tendency", "", "The dataset is not suitable for clustering (Hopkins' H = 0.51)." ) ) }) performance/tests/testthat/test-test_performance.R0000644000176200001440000000324714415242745022233 0ustar liggesuserstest_that("test_performance - nested", { skip_if_not_installed("lavaan") skip_if_not_installed("lmtest") # Decreasing m1 <- lm(Sepal.Length ~ Petal.Width * Species, data = iris) m2 <- lm(Sepal.Length ~ Petal.Width + Species, data = iris) m3 <- lm(Sepal.Length ~ Petal.Width, data = iris) rez <- test_performance(m1, m2, m3) expect_equal(rez$Name, c("m1", "m2", "m3"), ignore_attr = TRUE) rez <- test_performance(list(m1, m2, m3)) expect_equal(rez$Name, c("Model 1", "Model 2", "Model 3"), ignore_attr = TRUE) models <- list(m1, m2, m3) rez <- test_performance(models) expect_equal(rez$Name, c("Model 1", "Model 2", "Model 3"), ignore_attr = TRUE) models <- list(Interaction = m1, NoInteraction = m2, SingleTerm = m3) rez <- test_performance(models) expect_equal(rez$Name, c("Interaction", "NoInteraction", "SingleTerm"), ignore_attr = TRUE) # Increasing # TODO: Increasing order must be fixed and double checked, because the empty line should be the bottom one (?) # m1 <- lm(Sepal.Length ~ Petal.Width, data = iris) # m2 <- lm(Sepal.Length ~ Petal.Width + Species, data = iris) # m3 <- lm(Sepal.Length ~ Petal.Width * Species, data = iris) # # rez <- test_performance(m1, m2, m3) }) test_that("test_performance - single model", { m1 <- lm(Sepal.Length ~ 1, data = iris) m2 <- lm(Sepal.Length ~ Petal.Width, data = iris) expect_message(test_performance(m2), regex = "Only one model") expect_silent(test_performance(m2, verbose = FALSE)) out1 <- test_performance(m2, verbose = FALSE) out2 <- test_performance(m1, m2, verbose = FALSE) expect_equal(out1$Omega2, out2$Omega2, tolerance = 1e-3) }) performance/tests/testthat/test-rmse.R0000644000176200001440000000324114642733710017632 0ustar liggesuserstest_that("rmse", { skip_if_not_installed("lme4") data(sleepstudy, package = "lme4") m1.1 <- glm(Reaction ~ Days, data = sleepstudy, family = gaussian()) m1.2 <- glm(Reaction ~ Days, data = sleepstudy, family = gaussian("log")) m1.3 <- glm(Reaction ~ Days, data = sleepstudy, family = gaussian("inverse")) m2.1 <- glm(Reaction ~ Days, data = sleepstudy, family = inverse.gaussian()) m2.2 <- glm(Reaction ~ Days, data = sleepstudy, family = inverse.gaussian("log")) m2.3 <- glm(Reaction ~ Days, data = sleepstudy, family = inverse.gaussian("inverse")) expect_message( cp <- compare_performance(m1.1, m1.2, m1.3, m2.1, m2.2, m2.3), "seem to be identical" ) expect_equal(cp$RMSE, c(47.4489, 47.39881, 47.38701, 47.41375, 47.39979, 47.38705), tolerance = 1e-3) }) test_that("rmse, ci", { data(mtcars) model <- lm(mpg ~ hp + gear, data = mtcars) # analytical out <- performance_rmse(model, ci = 0.95, ci_method = "analytical") expect_equal(out$CI_low, 2.30486, tolerance = 1e-4) expect_equal(out$CI_high, 3.79093, tolerance = 1e-4) # bootstrapped set.seed(123) out <- performance_rmse(model, ci = 0.95, ci_method = "boot") expect_equal(out$CI_low, 1.9494, tolerance = 1e-3) expect_equal(out$CI_high, 3.38406, tolerance = 1e-3) # bootstrapped, mixed models skip_on_cran() skip_if_not_installed("lme4") data(sleepstudy, package = "lme4") m <- lme4::lmer(Reaction ~ Days + (1 | Subject), data = sleepstudy) set.seed(123) out <- performance_rmse(m, ci = 0.95, iterations = 100) expect_equal(out$CI_low, 26.26066, tolerance = 1e-3) expect_equal(out$CI_high, 32.5642, tolerance = 1e-3) }) performance/tests/testthat/test-check_collinearity.R0000644000176200001440000001654414736731423022534 0ustar liggesusers# https://github.com/easystats/performance/pull/547 test_that("check_collinearity, correct order in print", { m <- lm(mpg ~ wt + cyl + gear + disp, data = mtcars) out <- capture.output(print(check_collinearity(m, verbose = FALSE))) expect_identical( out, c( "# Check for Multicollinearity", "", "Low Correlation", "", " Term VIF VIF 95% CI Increased SE Tolerance Tolerance 95% CI", " gear 1.53 [1.19, 2.51] 1.24 0.65 [0.40, 0.84]", "", "Moderate Correlation", "", " Term VIF VIF 95% CI Increased SE Tolerance Tolerance 95% CI", " wt 5.05 [3.21, 8.41] 2.25 0.20 [0.12, 0.31]", " cyl 5.41 [3.42, 9.04] 2.33 0.18 [0.11, 0.29]", " disp 9.97 [6.08, 16.85] 3.16 0.10 [0.06, 0.16]" ) ) }) test_that("check_collinearity, interaction", { m <- lm(mpg ~ wt * cyl, data = mtcars) expect_message(check_collinearity(m), regex = "Model has interaction terms") }) test_that("check_collinearity", { skip_if_not_installed("glmmTMB") skip_if_not(getRversion() >= "4.0.0") data(Salamanders, package = "glmmTMB") m1 <- glmmTMB::glmmTMB(count ~ spp + mined + (1 | site), ziformula = ~spp, Salamanders, family = poisson() ) expect_equal( suppressWarnings(check_collinearity(m1, component = "conditional", verbose = FALSE)$VIF), c(1.00037354840318, 1.00037354840318), tolerance = 1e-3 ) expect_equal( suppressWarnings(check_collinearity(m1, component = "all", verbose = FALSE)$VIF), c(1.00037354840318, 1.00037354840318), tolerance = 1e-3 ) expect_null(check_collinearity(m1, verbose = FALSE, component = "zero_inflated")) }) test_that("check_collinearity", { skip_if_not_installed("glmmTMB") skip_if_not(getRversion() >= "4.0.0") data(Salamanders, package = "glmmTMB") m2 <- glmmTMB::glmmTMB( count ~ spp + mined + cover + (1 | site), ziformula = ~ spp + mined + cover, family = glmmTMB::nbinom2, data = Salamanders ) expect_equal( suppressWarnings(check_collinearity(m2, component = "conditional", verbose = FALSE)$VIF), c(1.09015, 1.2343, 1.17832), tolerance = 1e-3 ) expect_equal( suppressWarnings(check_collinearity(m2, component = "conditional", verbose = FALSE)$VIF_CI_low), c(1.03392, 1.14674, 1.10105), tolerance = 1e-3 ) expect_equal( suppressWarnings(check_collinearity(m2, component = "all", verbose = FALSE)$VIF), c(1.09015, 1.2343, 1.17832, 1.26914, 1, 1.26914), tolerance = 1e-3 ) expect_equal( suppressWarnings(check_collinearity(m2, component = "all", verbose = FALSE)$VIF_CI_low), c(1.03392, 1.14674, 1.10105, 1.17565, 1, 1.17565), tolerance = 1e-3 ) expect_equal( suppressWarnings(check_collinearity(m2, component = "zero_inflated", verbose = FALSE)$VIF), c(1.26914, 1, 1.26914), tolerance = 1e-3 ) expect_equal( suppressWarnings(check_collinearity(m2, component = "zero_inflated", verbose = FALSE)$Tolerance_CI_high), c(0.85059, 1, 0.85059), tolerance = 1e-3 ) suppressWarnings(coll <- check_collinearity(m2, component = "all", verbose = FALSE)) # nolint expect_true(all(coll$Tolerance < coll$Tolerance_CI_high)) expect_true(all(coll$VIF > coll$VIF_CI_low)) expect_identical( attributes(coll)$data$Component, c("conditional", "conditional", "conditional", "zero inflated", "zero inflated", "zero inflated") ) expect_identical( colnames(attributes(coll)$CI), c("VIF_CI_low", "VIF_CI_high", "Tolerance_CI_low", "Tolerance_CI_high", "Component") ) }) test_that("check_collinearity | afex", { skip_if_not_installed("afex", minimum_version = "1.0.0") data(obk.long, package = "afex") obk.long$treatment <- as.character(obk.long$treatment) suppressWarnings(suppressMessages({ aM <- afex::aov_car(value ~ treatment * gender + Error(id / (phase * hour)), data = obk.long ) aW <- afex::aov_car(value ~ Error(id / (phase * hour)), data = obk.long ) aB <- afex::aov_car(value ~ treatment * gender + Error(id), data = obk.long ) })) expect_message(ccoM <- check_collinearity(aM)) # nolint expect_warning(expect_message(ccoW <- check_collinearity(aW))) # nolint expect_message(ccoB <- check_collinearity(aB), regexp = NA) # nolint expect_identical(nrow(ccoM), 15L) expect_identical(nrow(ccoW), 3L) expect_identical(nrow(ccoB), 3L) suppressWarnings(suppressMessages({ aM <- afex::aov_car(value ~ treatment * gender + Error(id / (phase * hour)), include_aov = TRUE, data = obk.long ) aW <- afex::aov_car(value ~ Error(id / (phase * hour)), include_aov = TRUE, data = obk.long ) aB <- afex::aov_car(value ~ treatment * gender + Error(id), include_aov = TRUE, data = obk.long ) })) expect_message(ccoM <- check_collinearity(aM)) # nolint expect_warning(expect_message(ccoW <- check_collinearity(aW))) # nolint expect_message(ccoB <- check_collinearity(aB), regexp = NA) # nolint expect_identical(nrow(ccoM), 15L) expect_identical(nrow(ccoW), 3L) expect_identical(nrow(ccoB), 3L) }) test_that("check_collinearity, ci = NULL", { # 518 data(npk) m <- lm(yield ~ N + P + K, npk) out <- check_collinearity(m, ci = NULL) expect_identical( colnames(out), c( "Term", "VIF", "VIF_CI_low", "VIF_CI_high", "SE_factor", "Tolerance", "Tolerance_CI_low", "Tolerance_CI_high" ) ) expect_snapshot(out) }) test_that("check_collinearity, ci are NA", { skip_if_not_installed("fixest") data(mtcars) i <- fixest::i m_vif <- fixest::feols(mpg ~ disp + hp + wt + i(cyl) | carb, data = mtcars) out <- suppressWarnings(check_collinearity(m_vif)) expect_identical( colnames(out), c( "Term", "VIF", "VIF_CI_low", "VIF_CI_high", "SE_factor", "Tolerance", "Tolerance_CI_low", "Tolerance_CI_high" ) ) }) test_that("check_collinearity, hurdle/zi models w/o zi-formula", { skip_if_not_installed("pscl") data("bioChemists", package = "pscl") m <- pscl::hurdle( art ~ fem + mar, data = bioChemists, dist = "poisson", zero.dist = "binomial", link = "logit" ) out <- check_collinearity(m) expect_named( out, c( "Term", "VIF", "VIF_CI_low", "VIF_CI_high", "SE_factor", "Tolerance", "Tolerance_CI_low", "Tolerance_CI_high", "Component" ) ) expect_equal(out$VIF, c(1.05772, 1.05772, 1.06587, 1.06587), tolerance = 1e-4) expect_snapshot(print(out)) }) test_that("check_collinearity, invalid data", { dd <- data.frame(y = as.difftime(0:5, units = "days")) m1 <- lm(y ~ 1, data = dd) expect_message(check_collinearity(m1), "Could not extract the variance-covariance") }) test_that("check_collinearity, glmmTMB hurdle w/o zi", { skip_if_not_installed("glmmTMB") data(Salamanders, package = "glmmTMB") mod_trunc_error <- glmmTMB::glmmTMB( count ~ spp + mined + (1 | site), data = Salamanders[Salamanders$count > 0, , drop = FALSE], family = glmmTMB::truncated_nbinom2(), ziformula = ~0, dispformula = ~1 ) out <- check_collinearity(mod_trunc_error) expect_equal(out$VIF, c(1.03414, 1.03414), tolerance = 1e-3) }) performance/tests/testthat/test-test_wald.R0000644000176200001440000000251514412517050020645 0ustar liggesusersskip_on_os("linux") test_that("test_wald - lm", { m1 <- lm(Sepal.Length ~ Petal.Width * Species, data = iris) m2 <- lm(Sepal.Length ~ Petal.Width + Species, data = iris) m3 <- lm(Sepal.Length ~ Petal.Width, data = iris) rez <- test_wald(m1, m2, m3) ref <- as.data.frame(anova(m1, m2, m3)) expect_equal(rez$`F`, ref$`F`, tolerance = 1e-4) expect_equal(rez$p, ref$`Pr(>F)`, tolerance = 1e-4) # setting test = "LRT" is not expected, but should at least not fail expect_warning({ rez <- test_wald(m1, m2, test = "LRT") }) expect_identical(rez$Name, c("..1", "..2")) # Reversed m3 <- m1 m1 <- lm(Sepal.Length ~ Petal.Width, data = iris) rez <- test_wald(m1, m2, m3) ref <- as.data.frame(anova(m1, m2, m3)) expect_equal(rez$`F`, ref$`F`, tolerance = 1e-4) expect_equal(rez$p, ref$`Pr(>F)`, tolerance = 1e-4) }) test_that("test_wald - glm", { m1 <- glm(vs ~ disp + hp + drat, data = mtcars, family = "binomial") m2 <- glm(vs ~ disp + hp, data = mtcars, family = "binomial") m3 <- glm(vs ~ disp, data = mtcars, family = "binomial") expect_message({ rez <- test_wald(m1, m2, m3) }) ref <- as.data.frame(anova(m1, m2, m3, test = "LRT")) expect_equal(rez$Chi2, abs(ref$Deviance), tolerance = 1e-4) expect_equal(rez$p, ref$`Pr(>Chi)`, tolerance = 1e-4) }) performance/tests/testthat/test-r2_mcfadden.R0000644000176200001440000000377614736731423021050 0ustar liggesuserstest_that("r2_mcfadden", { skip_if_not_installed("MASS") withr::with_options( list(contrasts = c("contr.treatment", "contr.poly")), { data(housing, package = "MASS") model <- MASS::polr(Sat ~ Infl + Type + Cont, weights = Freq, data = housing) expect_equal( r2_mcfadden(model), structure( list( R2 = c(`McFadden's R2` = 0.0465152150591893), R2_adjusted = c(`adjusted McFadden's R2` = 0.0459671013089695) ), model_type = "Generalized Linear", class = "r2_generic" ), tolerance = 1e-3 ) expect_equal( r2(model), list(R2_Nagelkerke = c(`Nagelkerke's R2` = 0.108408289848161)), tolerance = 1e-3, ignore_attr = TRUE ) } ) }) skip_if_not_installed("withr") withr::with_environment( new.env(), { test_that("r2_mcfadden, glmmTMB-beta-binomial", { skip_if_not_installed("glmmTMB") set.seed(101) dd <- data.frame(x = rnorm(200)) dd$y <- glmmTMB::simulate_new( ~ 1 + x, newdata = dd, newparams = list(beta = c(0, 1), betadisp = -1), weights = rep(10, nrow(dd)), family = glmmTMB::betabinomial() )[[1]] dd$success <- round(runif(nrow(dd), 0, dd$y)) d <<- dd m <- glmmTMB::glmmTMB( y / 10 ~ 1 + x, data = d, weights = rep(10, nrow(d)), family = glmmTMB::betabinomial() ) out1 <- r2(m) out2 <- r2_mcfadden(m) expect_equal(out1$R2, out2$R2, tolerance = 1e-4, ignore_attr = TRUE) expect_equal(out1$R2, 0.06892733, tolerance = 1e-4, ignore_attr = TRUE) m <- glmmTMB::glmmTMB( cbind(y, success) ~ 1 + x, data = d, weights = rep(10, nrow(d)), family = glmmTMB::betabinomial() ) expect_warning(r2(m), regex = "calculate accurate") expect_warning(r2_mcfadden(m), regex = "calculate accurate") }) } ) performance/tests/testthat/test-check_dag.R0000644000176200001440000001046014672543117020560 0ustar liggesusersskip_on_cran() skip_if_not_installed("ggdag") skip_if_not_installed("dagitty") test_that("check_dag", { dag <- check_dag( y ~ x + b, outcome = "y", exposure = "x" ) expect_snapshot(print(dag)) dag <- check_dag( y ~ x + b, outcome = "y", exposure = "x", adjusted = "b" ) expect_snapshot(print(dag)) dag <- check_dag( y ~ x + b + c, x ~ b, outcome = "y", exposure = "x" ) expect_snapshot(print(dag)) dag <- check_dag( y ~ x + b + c, x ~ b, outcome = "y", exposure = "x", adjusted = "c" ) expect_snapshot(print(dag)) dag <- check_dag( y ~ x + b + c + d, x ~ b, x ~ c, outcome = "y", exposure = "x", adjusted = "c" ) expect_snapshot(print(dag)) data(mtcars) m <- lm(mpg ~ wt + gear + disp + cyl, data = mtcars) dag <- check_dag( m, wt ~ disp + cyl, wt ~ am ) expect_snapshot(print(dag)) }) test_that("check_dag, cylic error", { expect_error( check_dag( y ~ x + b + c + d, x ~ c + d, b ~ x, b ~ y, outcome = "y", exposure = "x", adjusted = "c" ), regex = "Model is cyclic" ) }) test_that("check_dag, multiple adjustment sets", { dag <- check_dag( podcast ~ mood + humor + skills_course, alertness ~ mood, mood ~ humor, prepared ~ skills_course, exam ~ alertness + prepared, coords = ggdag::time_ordered_coords(), exposure = "podcast", outcome = "exam" ) expect_snapshot(print(dag)) dag <- check_dag( podcast ~ mood + humor + skills_course, alertness ~ mood, mood ~ humor, prepared ~ skills_course, exam ~ alertness + prepared, adjusted = c("alertness", "prepared"), exposure = "podcast", outcome = "exam", coords = ggdag::time_ordered_coords() ) expect_snapshot(print(dag)) dag <- check_dag( podcast ~ mood + humor + skills_course, alertness ~ mood, mood ~ humor, prepared ~ skills_course, exam ~ alertness + prepared, coords = ggdag::time_ordered_coords(), adjusted = "alertness", exposure = "podcast", outcome = "exam" ) expect_snapshot(print(dag)) }) test_that("check_dag, different adjustements for total and direct", { dag <- check_dag( outcome ~ exposure + x1 + x2, x2 ~ exposure, exposure ~ x1, outcome = "outcome", exposure = "exposure" ) expect_snapshot(print(dag)) dag <- check_dag( outcome ~ exposure + x1 + x2, x2 ~ exposure, exposure ~ x1, adjusted = "x1", outcome = "outcome", exposure = "exposure" ) expect_snapshot(print(dag)) dag <- check_dag( outcome ~ exposure + x1 + x2, x2 ~ exposure, exposure ~ x1, adjusted = "x2", outcome = "outcome", exposure = "exposure" ) expect_snapshot(print(dag)) dag <- check_dag( outcome ~ exposure + x1 + x2, x2 ~ exposure, exposure ~ x1, adjusted = c("x1", "x2"), outcome = "outcome", exposure = "exposure" ) expect_snapshot(print(dag)) }) test_that("check_dag, collider bias", { dag <- check_dag( SMD_ICD11 ~ agegroup + gender_kid + edgroup3 + residence + pss4_kid_sum_2sd + sm_h_total_kid, pss4_kid_sum_2sd ~ gender_kid, sm_h_total_kid ~ gender_kid + agegroup, adjusted = c( "agegroup", "gender_kid", "edgroup3", "residence", "pss4_kid_sum_2sd" ), outcome = "SMD_ICD11", exposure = "agegroup" ) expect_snapshot(print(dag)) dag <- check_dag( SMD_ICD11 ~ agegroup + gender_kid + edgroup3 + residence + pss4_kid_sum_2sd + sm_h_total_kid, pss4_kid_sum_2sd ~ gender_kid, sm_h_total_kid ~ gender_kid + agegroup, adjusted = c( "agegroup", "gender_kid", "edgroup3", "residence", "pss4_kid_sum_2sd", "sm_h_total_kid" ), outcome = "SMD_ICD11", exposure = "agegroup" ) expect_snapshot(print(dag)) }) test_that("check_dag, formula-interface", { dag <- check_dag( y ~ x + b + c, x ~ b, outcome = ~y, exposure = ~x, adjusted = ~ b + c ) expect_identical(attributes(dag)$adjusted, c("b", "c")) dag2 <- check_dag( y ~ x + b + c, x ~ b, adjusted = ~ b + c ) expect_identical(dag, dag2) }) performance/tests/testthat/test-performance_cv.R0000644000176200001440000000074014355271477021666 0ustar liggesusersmodel <- lm(mpg ~ wt + cyl, data = mtcars) set.seed(123) out <- performance_cv(model) test_that("performance_cv", { expect_equal(out$MSE, 5.91153, tolerance = 1e-3) expect_equal(colnames(out), c("MSE", "RMSE", "R2"), tolerance = 1e-3) }) set.seed(123) out <- performance_cv(model, metrics = c("MSE", "R2")) test_that("performance_cv", { expect_equal(out$MSE, 5.91153, tolerance = 1e-3) expect_equal(colnames(out), c("MSE", "R2"), tolerance = 1e-3) }) performance/tests/testthat/test-item_reliability.R0000644000176200001440000000074214561136140022210 0ustar liggesuserstest_that("item_reliability", { data(iris) x <- iris[, 1:4] expect_equal( item_reliability(x), structure( list( term = c( "Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width" ), alpha_if_deleted = c(0.454, 0.877, 0.489, 0.467), item_discrimination = c(0.894, -0.349, 0.863, 0.921) ), class = "data.frame", row.names = c(NA, -4L) ), tolerance = 1e-3 ) }) performance/tests/testthat/test-check_predictions.R0000644000176200001440000001041614676732355022361 0ustar liggesusersskip_on_os("mac") skip_on_cran() test_that("check_predictions", { data(mtcars) model <- lm(mpg ~ disp, data = mtcars) set.seed(99) out <- check_predictions(model) expect_named( out, c( "sim_1", "sim_2", "sim_3", "sim_4", "sim_5", "sim_6", "sim_7", "sim_8", "sim_9", "sim_10", "sim_11", "sim_12", "sim_13", "sim_14", "sim_15", "sim_16", "sim_17", "sim_18", "sim_19", "sim_20", "sim_21", "sim_22", "sim_23", "sim_24", "sim_25", "sim_26", "sim_27", "sim_28", "sim_29", "sim_30", "sim_31", "sim_32", "sim_33", "sim_34", "sim_35", "sim_36", "sim_37", "sim_38", "sim_39", "sim_40", "sim_41", "sim_42", "sim_43", "sim_44", "sim_45", "sim_46", "sim_47", "sim_48", "sim_49", "sim_50", "y" ) ) expect_equal( out$sim_1, c( 23.70112, 24.56502, 25.43419, 20.40954, 13.58266, 20.72532, 11.95366, 25.14559, 22.61286, 18.48403, 20.26737, 21.2291, 20.67149, 10.07628, 0.25886, 10.64176, 10.18407, 20.68235, 28.10115, 27.55045, 28.22301, 18.94021, 16.87727, 14.05421, 13.8378, 28.13797, 26.86451, 23.90539, 10.68719, 28.17587, 21.65853, 26.07681 ), tolerance = 1e-4 ) }) test_that("check_predictions, glmmTMB", { skip_if_not_installed("glmmTMB") data(mtcars) model <- glmmTMB::glmmTMB(vs ~ disp, data = mtcars, family = binomial()) set.seed(99) out <- check_predictions(model) expect_named( out, c( "sim_1", "sim_2", "sim_3", "sim_4", "sim_5", "sim_6", "sim_7", "sim_8", "sim_9", "sim_10", "sim_11", "sim_12", "sim_13", "sim_14", "sim_15", "sim_16", "sim_17", "sim_18", "sim_19", "sim_20", "sim_21", "sim_22", "sim_23", "sim_24", "sim_25", "sim_26", "sim_27", "sim_28", "sim_29", "sim_30", "sim_31", "sim_32", "sim_33", "sim_34", "sim_35", "sim_36", "sim_37", "sim_38", "sim_39", "sim_40", "sim_41", "sim_42", "sim_43", "sim_44", "sim_45", "sim_46", "sim_47", "sim_48", "sim_49", "sim_50", "y" ) ) expect_equal( out$sim_1, c( 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1 ), tolerance = 1e-4 ) expect_true(attributes(out)$model_info$is_bernoulli) model <- glmmTMB::glmmTMB(vs ~ disp + (1 | cyl), data = mtcars, family = binomial()) set.seed(99) out <- check_predictions(model) expect_equal( out$sim_1, c( 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0 ), tolerance = 1e-4 ) expect_true(attributes(out)$model_info$is_bernoulli) }) test_that("check_predictions, glm, binomial", { data(mtcars) set.seed(1) tot <- rep(10, 100) suc <- rbinom(100, prob = 0.9, size = tot) dat <- data.frame(tot, suc) dat$prop <- suc / tot mod1 <- glm(cbind(suc, tot - suc) ~ 1, family = binomial, data = dat ) mod2 <- glm(prop ~ 1, family = binomial, data = dat, weights = tot ) mod3 <- glm(cbind(suc, tot) ~ 1, family = binomial, data = dat ) mod4 <- glm(am ~ 1, family = binomial, data = mtcars ) set.seed(1) out1 <- check_predictions(mod1) set.seed(1) out2 <- check_predictions(mod2) set.seed(1) out3 <- check_predictions(mod3) set.seed(1) out4 <- check_predictions(mod4) expect_equal(head(out1$sim_1), c(1, 0.9, 0.9, 0.8, 1, 0.8), tolerance = 1e-4) expect_false(attributes(out1)$model_info$is_bernoulli) expect_equal(head(out2$sim_1), c(1, 0.9, 0.9, 0.8, 1, 0.8), tolerance = 1e-4) expect_false(attributes(out2)$model_info$is_bernoulli) expect_equal(head(out3$sim_1), c(0.4, 0.42105, 0.47368, 0.61111, 0.4, 0.61111), tolerance = 1e-3) expect_false(attributes(out3)$model_info$is_bernoulli) expect_equal(head(out4$sim_1), c(0, 0, 0, 1, 0, 1), tolerance = 1e-4) expect_true(attributes(out4)$model_info$is_bernoulli) }) test_that("check_predictions, lm, ratio-response", { skip_if_not_installed("lme4") data(cbpp, package = "lme4") model1 <- lm(I(incidence / size) ~ period, data = cbpp) set.seed(123) out <- check_predictions(model1) expect_equal( head(out$y), c(0.14286, 0.25, 0.44444, 0, 0.13636, 0.05556), ignore_attr = TRUE, tolerance = 1e-4 ) }) performance/tests/testthat/test-model_performance-various.R0000644000176200001440000000506614412517050024032 0ustar liggesuserstest_that("model_performance various", { skip_if_not_installed("AER") skip_if_not_installed("ordinal") skip_if_not_installed("betareg") data("Affairs", package = "AER") data("GasolineYield", package = "betareg") data("wine", package = "ordinal") data("CigarettesSW", package = "AER") CigarettesSW$rprice <- with(CigarettesSW, price / cpi) CigarettesSW$rincome <- with(CigarettesSW, income / population / cpi) CigarettesSW$tdiff <- with(CigarettesSW, (taxs - tax) / cpi) m1 <- betareg::betareg(yield ~ batch + temp, data = GasolineYield) m3 <- ordinal::clm(rating ~ temp * contact, data = wine) m4 <- ordinal::clm2(rating ~ temp * contact, data = wine) m5 <- AER::ivreg( log(packs) ~ log(rprice) + log(rincome) | log(rincome) + tdiff + I(tax / cpi), data = CigarettesSW, subset = year == "1995" ) expect_equal(model_performance(m1, verbose = FALSE)$R2, 0.9617312, tolerance = 1e-4) expect_equal(model_performance(m3, verbose = FALSE)$R2_Nagelkerke, 0.4042792, tolerance = 1e-4) expect_equal(model_performance(m4, verbose = FALSE)$R2_Nagelkerke, 0.4042792, tolerance = 1e-4) expect_equal(model_performance(m5, verbose = FALSE)$R2, 0.4294224, tolerance = 1e-4) mp <- model_performance(m5) ms <- summary(m5, diagnostics = TRUE) expect_equal(mp$Sargan, ms$diagnostics["Sargan", 3]) expect_equal(mp$Sargan_p, ms$diagnostics["Sargan", 4]) expect_equal(mp$Wu_Hausman, ms$diagnostics["Wu-Hausman", 3]) expect_equal(mp$Wu_Hausman_p, ms$diagnostics["Wu-Hausman", 4]) expect_equal(mp$weak_instruments, ms$diagnostics["Weak instruments", 3]) expect_equal(mp$weak_instruments_p, ms$diagnostics["Weak instruments", 4]) }) # DirichletReg is currently orphaned # test_that("model_performance (Dirichlet regression)", { # skip_if_not_installed("DirichletReg") # set.seed(123) # data("ArcticLake", package = "DirichletReg") # # ALake <- ArcticLake # ALake$Y <- suppressWarnings(DirichletReg::DR_data(ALake[, 1:3])) # # # fit a quadratic Dirichlet regression models ("common") # res1 <- DirichletReg::DirichReg(Y ~ depth + I(depth^2), ALake) # expect_equal( # model_performance(res1), # structure( # list( # AIC = -199.993722776335, # BIC = -185.021667961168, # R2_Nagelkerke = 0.0405982703444639, # RMSE = 0.922951614921502 # ), # class = c( # "performance_model", # "data.frame" # ), # row.names = 1L, # r2 = list(names = "R2_Nagelkerke") # ), # tolerance = 1e-3 # ) # }) performance/tests/testthat/test-pkg-estimatr.R0000644000176200001440000000075114412517050021266 0ustar liggesuserstest_that("Issue #530 from the `modelsummary` repo", { skip_if_not_installed("estimatr") toy_df <- data.frame( y = c(1, 2, 3), x = c(1, 2, 4), weights = c(0.2, 0.2, 0.6) ) mod <- estimatr::lm_robust(x ~ y, data = toy_df) modw <- estimatr::lm_robust(x ~ y, weights = weights, data = toy_df) expect_equal( as.numeric(r2(mod)$R2), summary(mod)$r.squared ) expect_equal( as.numeric(r2(modw)$R2), summary(modw)$r.squared ) }) performance/tests/testthat/test-model_performance.kmeans.R0000644000176200001440000000203114355271477023626 0ustar liggesuserstest_that("model_performance.kmeans", { set.seed(123) cl <- kmeans(subset(iris, select = Sepal.Length:Petal.Width), 3) expect_equal(model_performance(cl), structure( list( Sum_Squares_Total = 681.370599999999, Sum_Squares_Within = 78.851441426146, Sum_Squares_Between = 602.519158573853, Iterations = 2L ), class = c( "performance_model", "data.frame" ), row.names = c(NA, -1L) ), tolerance = 0.1 ) set.seed(123) mod <- kmeans(subset(iris, select = Sepal.Length:Petal.Width), centers = 3, iter.max = 100, nstart = 10 ) expect_equal( model_performance(mod), structure( list( Sum_Squares_Total = 681.3706, Sum_Squares_Within = 78.851441426146, Sum_Squares_Between = 602.519158573854, Iterations = 2L ), class = c( "performance_model", "data.frame" ), row.names = c(NA, -1L) ), tolerance = 0.1 ) }) performance/tests/testthat/test-r2_ferrari.R0000644000176200001440000000220714642733710020722 0ustar liggesuserstest_that("r2_ferarri", { skip_if_not_installed("betareg") data("GasolineYield", package = "betareg") model <- betareg::betareg(yield ~ batch + temp, data = GasolineYield) out <- r2_ferrari(model) expect_equal(out$R2, summary(model)$pseudo.r.squared, tolerance = 1e-3, ignore_attr = TRUE) }) test_that("r2_ferarri", { skip_if_not_installed("betareg") skip_if_not_installed("glmmTMB") data("GasolineYield", package = "betareg") model <- glmmTMB::glmmTMB( yield ~ batch + temp, data = GasolineYield, family = glmmTMB::beta_family() ) out <- r2_ferrari(model) expect_equal(out$R2, c(`Ferrari's R2` = 0.96173), tolerance = 1e-3, ignore_attr = TRUE) }) test_that("r2_ferarri", { skip_if_not_installed("betareg") skip_if_not_installed("glmmTMB") skip_if_not_installed("lme4") data(sleepstudy, package = "lme4") sleepstudy$y <- datawizard::normalize(sleepstudy$Reaction) m <- glmmTMB::glmmTMB( y ~ Days, data = sleepstudy, family = glmmTMB::ordbeta() ) out <- r2(m) expect_equal(out$R2, c(`Ferrari's R2` = 0.2354701), tolerance = 1e-3, ignore_attr = TRUE) }) performance/tests/testthat/test-check_sphericity.R0000644000176200001440000000134214355271477022214 0ustar liggesuserstest_that("check_sphericity | afex", { skip_if_not_installed("afex") data(obk.long, package = "afex") obk.long$treatment <- as.character(obk.long$treatment) suppressWarnings(suppressMessages({ aM <- afex::aov_car(value ~ treatment * gender + Error(id / (phase * hour)), data = obk.long ) aW <- afex::aov_car(value ~ Error(id / (phase * hour)), data = obk.long ) aB <- afex::aov_car(value ~ treatment * gender + Error(id), data = obk.long ) })) expect_error(check_sphericity(aB)) msg <- capture.output(pM <- check_sphericity(aM)) msg <- capture.output(pW <- check_sphericity(aW)) expect_equal(length(pM), 12L) expect_equal(length(pW), 3L) }) performance/tests/testthat/test-check_heterogeneity_bias.R0000644000176200001440000000421714677205112023674 0ustar liggesuserstest_that("check_heterogeneity_bias", { skip_if_not_installed("datawizard") data(iris) set.seed(123) iris$ID <- sample.int(4, nrow(iris), replace = TRUE) # fake-ID out <- check_heterogeneity_bias(iris, select = c("Sepal.Length", "Petal.Length"), by = "ID") expect_equal(out, c("Sepal.Length", "Petal.Length"), ignore_attr = TRUE) expect_output(print(out), "Possible heterogeneity bias due to following predictors: Sepal\\.Length, Petal\\.Length") out <- check_heterogeneity_bias(iris, select = ~ Sepal.Length + Petal.Length, by = ~ID) expect_equal(out, c("Sepal.Length", "Petal.Length"), ignore_attr = TRUE) expect_output(print(out), "Possible heterogeneity bias due to following predictors: Sepal\\.Length, Petal\\.Length") m <- lm(Sepal.Length ~ Petal.Length + Petal.Width + Species + ID, data = iris) expect_error( check_heterogeneity_bias(m, select = c("Sepal.Length", "Petal.Length"), by = "ID"), regex = "no mixed model" ) skip_if_not_installed("lme4") m <- lme4::lmer(Sepal.Length ~ Petal.Length + Petal.Width + Species + (1 | ID), data = iris) out <- check_heterogeneity_bias(m, select = c("Sepal.Length", "Petal.Length"), by = "ID") expect_equal(out, c("Petal.Length", "Petal.Width", "Species"), ignore_attr = TRUE) expect_output( print(out), "Possible heterogeneity bias due to following predictors: Petal\\.Length, Petal\\.Width, Species" ) out <- check_heterogeneity_bias(m, select = ~ Sepal.Length + Petal.Length, by = ~ID) expect_equal(out, c("Petal.Length", "Petal.Width", "Species"), ignore_attr = TRUE) expect_output( print(out), "Possible heterogeneity bias due to following predictors: Petal\\.Length, Petal\\.Width, Species" ) }) test_that("check_heterogeneity_bias", { skip_if_not_installed("datawizard", minimum_version = "0.12.3") data(efc, package = "datawizard") dat <- na.omit(efc) dat$e42dep <- factor(dat$e42dep) dat$c172code <- factor(dat$c172code) out <- check_heterogeneity_bias( dat, select = "c12hour", by = c("e42dep", "c172code"), nested = TRUE ) expect_equal(out, "c12hour", ignore_attr = TRUE) }) performance/tests/testthat/test-performance_aic.R0000644000176200001440000000267414546750702022015 0ustar liggesuserstest_that("performance_aic works", { skip_if_not_installed("parameters") data(fish, package = "parameters") model_norm <- lm(count ~ factor(persons), fish) model_pois <- glm(count ~ factor(persons), fish, family = poisson()) expect_equal(performance_aic(model_norm), 1930.755, tolerance = 1e-2) expect_equal(performance_aic(model_pois), 2758.236, tolerance = 1e-2) }) test_that("performance_aic for log-model works", { skip_if_not_installed("parameters") data(fish, package = "parameters") model_lnorm <- lm(log1p(count) ~ factor(persons), fish) expect_equal(performance_aic(model_lnorm), 1025.352, tolerance = 1e-2) }) test_that("performance_aic Jacobian", { m1 <- lm(disp ~ hp, data = mtcars) m2 <- lm(sqrt(disp) ~ hp, data = mtcars) expect_equal(performance_aic(m1), 372.8247, tolerance = 1e-2) expect_equal(performance_aic(m2), 367.1239, tolerance = 1e-2) }) test_that("performance_aic lme4 default", { skip_if_not_installed("lme4") m1 <- lme4::lmer(Sepal.Length ~ Petal.Length + (1 | Species), data = iris) expect_equal(performance_aic(m1), AIC(m1), tolerance = 1e-2) expect_equal(performance_aic(m1, estimator = "ML"), 125.0043, tolerance = 1e-2) m2 <- lme4::lmer(Sepal.Length ~ Petal.Length + (1 | Species), data = iris, REML = FALSE) expect_equal(performance_aic(m2, estimator = "REML"), 128.0054, tolerance = 1e-2) expect_message(performance_aic(m2), regex = "was not fitted") }) performance/tests/testthat/test-cronbachs_alpha.R0000644000176200001440000000252714620351763022001 0ustar liggesuserstest_that("cronbachs_alpha, data frame", { skip_if_not_installed("parameters") data(mtcars) x <- mtcars[, c("cyl", "gear", "carb", "hp")] expect_equal(cronbachs_alpha(x), 0.09463206, tolerance = 1e-3) }) test_that("cronbachs_alpha", { expect_message(expect_null(cronbachs_alpha(mtcars[1])), regex = "Too few") }) test_that("cronbachs_alpha, principal_components", { skip_if_not_installed("parameters") pca <- parameters::principal_components(mtcars[, c("cyl", "gear", "carb", "hp")], n = 2) expect_equal(cronbachs_alpha(pca, verbose = FALSE), c(PC1 = 0.1101384), tolerance = 1e-3) expect_message(cronbachs_alpha(pca), regex = "Too few") pca <- parameters::principal_components(mtcars[, c("cyl", "gear", "carb", "hp")], n = 1) expect_equal(cronbachs_alpha(pca, verbose = FALSE), c(PC1 = 0.09463206), tolerance = 1e-3) expect_silent(cronbachs_alpha(pca)) }) test_that("cronbachs_alpha, principal_components", { skip_if_not_installed("parameters") pca <- parameters::principal_components(mtcars, n = 2) expect_equal(cronbachs_alpha(pca), c(PC1 = 0.4396, PC2 = -1.44331), tolerance = 1e-3) }) test_that("cronbachs_alpha, matrix", { skip_if_not_installed("parameters") m <- as.matrix(mtcars[c("cyl", "gear", "carb", "hp")]) expect_equal(cronbachs_alpha(m), 0.09463206, tolerance = 1e-3) }) performance/tests/testthat/test-check_homogeneity.R0000644000176200001440000000273714570063447022364 0ustar liggesuserstest_that("check_homogeneity | afex", { skip_if_not_installed("afex") data(obk.long, package = "afex") obk.long$treatment <- as.character(obk.long$treatment) suppressWarnings(suppressMessages({ aM <- afex::aov_car(value ~ treatment * gender + Error(id / (phase * hour)), data = obk.long ) aW <- afex::aov_car(value ~ Error(id / (phase * hour)), data = obk.long ) aB <- afex::aov_car(value ~ treatment * gender + Error(id), data = obk.long ) })) expect_error(check_homogeneity(aW)) msg <- capture.output(expect_message(check_homogeneity(aB, method = "bartlett"), "Only")) msg <- capture.output({ pM <- check_homogeneity(aM) }) msg <- capture.output({ pB <- check_homogeneity(aB) }) expect_equal(pM, 0.3496516, ignore_attr = TRUE, tolerance = 0.001) expect_equal(pB, 0.3496516, ignore_attr = TRUE, tolerance = 0.001) }) test_that("check_homogeneity | t-test", { data(mtcars) expect_error( check_homogeneity(t.test(mtcars$mpg, mtcars$hp, var.equal = FALSE)), regex = "Test does not assume" ) out <- t.test(mtcars$mpg, mtcars$hp, var.equal = TRUE) expect_equal( check_homogeneity(out), structure( 6.18792236963585e-121, object_name = out, method = "Bartlett Test", class = c( "check_homogeneity", "see_check_homogeneity", "numeric" ) ), tolerance = 1e-3, ignore_attr = TRUE ) }) performance/tests/testthat/test-model_performance.gam.R0000644000176200001440000000142614412517050023103 0ustar liggesuserstest_that("mgcv::gam", { skip_if_not_installed("mgcv") model <- mgcv::gam(mpg ~ s(hp), data = mtcars) # TODO: improve output expect_equal(as.numeric(performance::r2(model)$R2), 0.7348, tolerance = 0.01) }) # test_that("gamm4::gamm4 - no random", { # skip_if_not_installed("gamm4") # model <- gamm4::gamm4(mpg ~ s(hp), data=mtcars) # # r2(model$mer) # r2(model$gam) # }) # # test_that("gamm4::gamm4 - random", { # skip_if_not_installed("gamm4") # model <- gamm4::gamm4(mpg ~ s(hp), random = ~ (1|vs), data=mtcars) # # r2(model$mer) # r2(model$gam) # }) # # test_that("mgcv::gamm", { # skip_if_not_installed("mgcv") # model <- mgcv::gamm(mpg ~ s(hp), random = list(vs = ~1), data=mtcars) # # r2(model$lme) # r2(model$gam) # }) performance/tests/testthat/test-r2_nakagawa.R0000644000176200001440000000737314645233345021055 0ustar liggesusersskip_on_os("mac") skip_if_not_installed("lme4") model <- lme4::lmer(Sepal.Length ~ Petal.Length + (1 | Species), data = iris) test_that("r2_nakagawa", { expect_equal( r2_nakagawa(model), structure( list( R2_conditional = c(`Conditional R2` = 0.969409477972726), R2_marginal = c(`Marginal R2` = 0.65846169440315) ), class = c("r2_nakagawa", "list") ), tolerance = 1e-3 ) }) skip_on_cran() test_that("r2_nakagawa, ci", { set.seed(123) out <- r2_nakagawa(model, ci = 0.95) expect_equal( out$R2_marginal, c(`Marginal R2` = 0.65846, CI_low = 0.33708, CI_high = 0.94718), tolerance = 1e-3, ignore_attr = TRUE ) expect_equal( out$R2_conditional, c(`Conditional R2` = 0.96941, CI_low = 0.94299, CI_high = 0.98426), tolerance = 1e-3, ignore_attr = TRUE ) }) dat <- structure(list( y = structure( c( 1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 2L, 1L, 2L, 2L, 1L, 2L, 1L, 1L, 2L, 2L, 1L, 2L, 2L, 2L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 1L, 2L, 1L, 2L, 2L, 2L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 1L, 2L, 1L, 1L, 1L, 2L, 2L, 1L, 2L, 1L, 2L, 2L, 1L, 1L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 1L ), .Label = c("0", "1"), class = "factor" ), x1 = structure( c( 2L, 1L, 2L, 2L, 2L, 2L, 2L, 1L, 2L, 1L, 1L, 1L, 2L, 1L, 2L, 2L, 2L, 2L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 1L, 2L, 1L, 2L, 1L, 1L, 2L, 2L, 2L, 1L, 2L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 1L, 2L, 1L, 2L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 2L, 1L, 2L, 2L, 2L, 1L, 2L, 2L, 1L, 2L, 2L, 2L, 1L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 2L, 2L, 2L, 2L, 1L, 2L, 2L, 2L, 2L, 2L, 1L, 2L, 2L, 1L, 2L, 2L, 2L, 1L, 2L, 2L, 1L, 1L, 1L, 2L, 2L ), .Label = c("1", "2"), class = "factor" ), a1 = structure( c( 9L, 1L, 1L, 5L, 9L, 7L, 1L, 1L, 9L, 5L, 5L, 5L, 5L, 6L, 4L, 3L, 5L, 9L, 9L, 6L, 1L, 9L, 9L, 9L, 9L, 5L, 2L, 7L, 7L, 7L, 4L, 5L, 7L, 4L, 2L, 9L, 2L, 2L, 9L, 9L, 5L, 5L, 7L, 5L, 9L, 8L, 8L, 8L, 8L, 3L, 9L, 5L, 6L, 6L, 3L, 9L, 6L, 9L, 6L, 3L, 5L, 6L, 6L, 5L, 7L, 4L, 7L, 2L, 5L, 2L, 5L, 5L, 9L, 5L, 9L, 4L, 3L, 5L, 5L, 3L, 9L, 3L, 3L, 3L, 9L, 9L, 3L, 9L, 3L, 3L, 9L, 8L, 3L, 9L, 7L, 9L, 9L, 6L, 2L, 9L, 9L, 4L, 9L, 7L, 5L, 5L, 5L, 5L, 5L, 5L ), .Label = c("1", "2", "3", "4", "5", "6", "7", "8", "9"), class = "factor" ), a2 = structure( c( 6L, 6L, 12L, 12L, 11L, 11L, 11L, 14L, 14L, 14L, 14L, 14L, 13L, 1L, 1L, 13L, 1L, 14L, 14L, 14L, 14L, 14L, 14L, 14L, 14L, 12L, 12L, 12L, 7L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 5L, 5L, 11L, 7L, 8L, 1L, 1L, 12L, 4L, 11L, 11L, 11L, 5L, 5L, 5L, 2L, 13L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 5L, 5L, 7L, 7L, 8L, 8L, 8L, 9L, 9L, 9L, 7L, 7L, 8L, 8L, 9L, 10L, 10L, 10L, 10L, 1L, 10L, 1L, 10L, 13L, 13L, 6L, 11L, 11L, 14L, 2L, 2L, 2L, 2L, 6L, 6L, 6L, 3L, 3L, 3L, 13L, 13L, 13L, 6L, 6L, 6L, 4L ), .Label = c("01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14"), class = "factor" ) ), row.names = c(NA, -110L), class = "data.frame") model <- lme4::glmer(y ~ x1 + (1 | a1) + (1 | a2), family = binomial(link = "logit"), data = dat) test_that("r2_nakagawa, by_group", { out <- r2_nakagawa(model, by_group = TRUE) expect_equal(out$R2, c(0, 0.05771, 0.07863), tolerance = 1e-2) expect_identical(out$Level, c("Level 1", "a1", "a2")) }) test_that("icc, by_group", { out <- icc(model, by_group = TRUE) expect_equal(out$ICC, c(0.3200625, 0.1096797), tolerance = 1e-2) expect_identical(out$Group, c("a2", "a1")) }) performance/tests/testthat/test-item_difficulty.R0000644000176200001440000000245314362215436022047 0ustar liggesuserstest_that("item_difficulty", { data(iris) x <- iris[, 1:4] expect_equal( item_difficulty(x, maximum_value = NA), # old behaviour structure( list( Item = c( "Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width" ), Difficulty = c(0.74, 0.69, 0.54, 0.48), Ideal = c(0.56, 0.61, 0.57, 0.7) ), class = c("item_difficulty", "data.frame"), row.names = c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width") ), tolerance = 1e-3 ) out <- item_difficulty(x) # new behaviour expect_equal(out$Difficulty, c(0.74, 0.39, 0.48, 0.15), tolerance = 1e-3) expect_equal(out$Ideal, c(0.56, 0.56, 0.56, 0.56), tolerance = 1e-3) }) test_that("item_difficulty, maximum value", { x <- data.frame(a = rep(NA, 5), b = 1:5, c = c(1:4, 6)) out1 <- item_difficulty(x) out2 <- item_difficulty(x, maximum_value = 6) expect_equal(out1, out2, tolerance = 1e-3, ignore_attr = TRUE) out <- item_difficulty(x, maximum_value = 10) expect_equal(out$Difficulty, c(NaN, 0.3, 0.32), tolerance = 1e-3, ignore_attr = TRUE) }) test_that("item_difficulty, maximum value", { x <- data.frame(a = rep(NA, 5), b = 1:5, c = c(1:4, 6)) expect_error(item_difficulty(x, maximum_value = "a")) }) performance/tests/testthat/test-r2.R0000644000176200001440000001017414677205112017210 0ustar liggesuserstest_that("r2 lm", { data(iris) model <- lm(Sepal.Length ~ Species + Petal.Length, data = iris) out <- r2(model) expect_equal(out$R2, c(R2 = 0.83672), tolerance = 1e-3) expect_equal(out$R2_adjusted, c(`adjusted R2` = 0.83337), tolerance = 1e-3) }) test_that("r2 lm, ci", { data(iris) model <- lm(Sepal.Length ~ Species + Petal.Length, data = iris) out <- r2(model, ci = 0.95) expect_equal( out$R2, c(R2 = 0.83672, CI_low = 0.77725, CI_high = 0.87665), tolerance = 1e-3 ) expect_equal( out$R2_adjusted, c(`adjusted R2` = 0.83337, CI_low = 0.77282, CI_high = 0.87406), tolerance = 1e-3 ) }) test_that("r2 glm", { data(mtcars) model <- glm(am ~ mpg, data = mtcars) out <- r2(model) expect_equal(out$R2, c(R2 = 0.3598), tolerance = 1e-3) }) test_that("r2 glm, ci", { data(mtcars) model <- glm(am ~ mpg, data = mtcars) out <- r2(model, ci = 0.95) expect_equal( out$R2, c(R2 = 0.3598, CI_low = 0.09758, CI_high = 0.6066), tolerance = 1e-3 ) }) # glmmTMB, non-mixed -------------------------------------------------------- skip_if_not_installed("withr") withr::with_environment( new.env(), test_that("r2 glmmTMB, no ranef", { skip_if_not_installed("glmmTMB", minimum_version = "1.1.10") data(Owls, package = "glmmTMB") # linear --------------------------------------------------------------- m <- glmmTMB::glmmTMB(NegPerChick ~ BroodSize + ArrivalTime, data = Owls) out <- r2(m) expect_equal(out$R2, 0.05597288, tolerance = 1e-3, ignore_attr = TRUE) # validate against lm m2 <- lm(NegPerChick ~ BroodSize + ArrivalTime, data = Owls) out2 <- r2(m2) expect_equal(out$R2, out2$R2, tolerance = 1e-3, ignore_attr = TRUE) # binomial ------------------------------------------------------------- data(mtcars) m <- glmmTMB::glmmTMB(am ~ mpg, data = mtcars, family = binomial()) out <- r2(m) expect_equal(out[[1]], 0.3677326, tolerance = 1e-3, ignore_attr = TRUE) # validate against glm m2 <- glm(am ~ mpg, data = mtcars, family = binomial()) out2 <- r2(m2) expect_equal(out[[1]], out2[[1]], tolerance = 1e-3, ignore_attr = TRUE) # poisson -------------------------------------------------------------- d <<- data.frame( counts = c(18, 17, 15, 20, 10, 20, 25, 13, 12), outcome = gl(3, 1, 9), treatment = gl(3, 3) ) m <- glmmTMB::glmmTMB(counts ~ outcome + treatment, family = poisson(), data = d) out <- r2(m) expect_equal(out[[1]], 0.6571698, tolerance = 1e-3, ignore_attr = TRUE) # validate against glm m2 <- glm(counts ~ outcome + treatment, family = poisson(), data = d) out2 <- r2(m2) expect_equal(out[[1]], out2[[1]], tolerance = 1e-3, ignore_attr = TRUE) # zero-inflated -------------------------------------------------------------- skip_if_not(packageVersion("glmmTMB") > "1.1.10") skip_if_not_installed("pscl") data(bioChemists, package = "pscl") m <- glmmTMB::glmmTMB( art ~ fem + mar + kid5 + ment, ziformula = ~ kid5 + phd, family = poisson(), data = bioChemists ) out <- r2(m) expect_equal(out[[1]], 0.1797549, tolerance = 1e-3, ignore_attr = TRUE) # validate against pscl::zeroinfl m2 <- pscl::zeroinfl( art ~ fem + mar + kid5 + ment | kid5 + phd, data = bioChemists ) out2 <- r2(m2) expect_equal(out[[1]], out2[[1]], tolerance = 1e-3, ignore_attr = TRUE) # Gamma -------------------------------------------------------------- clotting <<- data.frame( u = c(5, 10, 15, 20, 30, 40, 60, 80, 100), lot1 = c(118, 58, 42, 35, 27, 25, 21, 19, 18), lot2 = c(69, 35, 26, 21, 18, 16, 13, 12, 12) ) m <- suppressWarnings(glmmTMB::glmmTMB(lot1 ~ log(u), data = clotting, family = Gamma())) out <- r2(m) expect_equal(out[[1]], 0.996103, tolerance = 1e-3, ignore_attr = TRUE) # validate against glm m2 <- glm(lot1 ~ log(u), data = clotting, family = Gamma()) out2 <- r2(m2) expect_equal(out[[1]], out2[[1]], tolerance = 1e-3, ignore_attr = TRUE) }) ) performance/tests/testthat/test-check_overdispersion.R0000644000176200001440000001165714741713414023105 0ustar liggesuserstest_that("check_overdispersion, glmmTMB-poisson", { skip_if_not_installed("glmmTMB") skip_if_not(getRversion() >= "4.0.0") data(Salamanders, package = "glmmTMB") m1 <- glm(count ~ spp + mined, family = poisson, data = Salamanders) out <- check_overdispersion(m1) expect_equal( out, structure( list( chisq_statistic = 1873.71012423995, dispersion_ratio = 2.94608510100621, residual_df = 636L, p_value = 3.26607509162498e-122 ), class = c("check_overdisp", "see_check_overdisp"), object_name = "m1" ), tolerance = 1e-3 ) expect_identical( capture.output(print(out)), c( "# Overdispersion test", "", " dispersion ratio = 2.946", " Pearson's Chi-Squared = 1873.710", " p-value = < 0.001", "" ) ) expect_message(capture.output(print(out)), "Overdispersion detected") set.seed(123) out <- check_overdispersion(simulate_residuals(m1)) expect_equal( out, structure( list( dispersion_ratio = 3.91516791651235, p_value = 0 ), class = c("check_overdisp", "see_check_overdisp") ), tolerance = 1e-3 ) }) test_that("check_overdispersion, glmmTMB-poisson mixed", { skip_if_not_installed("glmmTMB") skip_if_not(getRversion() >= "4.0.0") data(Salamanders, package = "glmmTMB") m2 <- glmmTMB::glmmTMB( count ~ mined + spp + (1 | site), family = poisson, data = Salamanders ) expect_equal( check_overdispersion(m2), structure( list( chisq_statistic = 1475.87512547128, dispersion_ratio = 2.32421279601777, residual_df = 635L, p_value = 8.41489530177729e-69 ), class = c("check_overdisp", "see_check_overdisp"), object_name = "m2" ), tolerance = 1e-3 ) }) test_that("check_overdispersion, zero-inflated and negbin", { skip_if_not_installed("glmmTMB") skip_if_not_installed("DHARMa") skip_if_not(getRversion() >= "4.0.0") data(Salamanders, package = "glmmTMB") m1 <- glmmTMB::glmmTMB( count ~ spp + mined, ziformula = ~ spp + mined, family = poisson, data = Salamanders ) m2 <- glmmTMB::glmmTMB( count ~ spp + mined, family = poisson, data = Salamanders ) m3 <- glmmTMB::glmmTMB( count ~ spp + mined, family = glmmTMB::nbinom1(), data = Salamanders ) expect_equal( check_overdispersion(m1), structure( list( dispersion_ratio = 1.98057695890769, p_value = 0 ), class = c("check_overdisp", "see_check_overdisp") ), tolerance = 1e-4, ignore_attr = TRUE ) expect_equal( check_overdispersion(m2), structure( list( chisq_statistic = 1873.7105986433, dispersion_ratio = 2.94608584692342, residual_df = 636L, p_value = 3.26556213101505e-122 ), class = c("check_overdisp", "see_check_overdisp"), object_name = "m1" ), tolerance = 1e-4, ignore_attr = TRUE ) expect_equal( check_overdispersion(m1), structure( list( dispersion_ratio = 1.98057695890769, p_value = 0 ), class = c("check_overdisp", "see_check_overdisp") ), tolerance = 1e-4, ignore_attr = TRUE ) }) test_that("check_overdispersion, MASS::negbin", { skip_if_not_installed("MASS") skip_if_not_installed("DHARMa") set.seed(3) mu <- rpois(500, lambda = 3) x <- rnorm(500, mu, mu * 3) x <- ceiling(x) x <- pmax(x, 0) m <- MASS::glm.nb(x ~ mu) out <- check_overdispersion(m) expect_equal( out, structure( list( dispersion_ratio = 0.409521313173506, p_value = 0 ), class = c("check_overdisp", "see_check_overdisp") ), ignore_attr = TRUE, tolerance = 1e-4 ) expect_identical( capture.output(print(out)), c( "# Overdispersion test", "", " dispersion ratio = 0.410", " p-value = < 0.001", "" ) ) expect_message(capture.output(print(out)), "Underdispersion detected") # check that plot works skip_if_not_installed("see", minimum_version = "0.9.1") expect_s3_class(plot(out), "ggplot") }) test_that("check_overdispersion, genpois", { skip_if_not_installed("glmmTMB") skip_if_not_installed("DHARMa") skip_if_not(getRversion() >= "4.0.0") data(Salamanders, package = "glmmTMB") model <- glmmTMB::glmmTMB( count ~ mined + spp + (1 | site), family = glmmTMB::genpois(), data = Salamanders ) expect_equal( check_overdispersion(model), structure( list( dispersion_ratio = 0.971975646955856, p_value = 0.88 ), class = c("check_overdisp", "see_check_overdisp") ), tolerance = 1e-4, ignore_attr = TRUE ) }) performance/tests/testthat/test-check_distribution.R0000644000176200001440000000177014620351763022545 0ustar liggesuserstest_that("check_distribution", { skip_if_not_installed("lme4") skip_if_not_installed("randomForest") data(sleepstudy, package = "lme4") model <<- lme4::lmer(Reaction ~ Days + (Days | Subject), sleepstudy) out <- check_distribution(model) expect_identical( out$Distribution, c( "bernoulli", "beta", "beta-binomial", "binomial", "cauchy", "chi", "exponential", "F", "gamma", "half-cauchy", "inverse-gamma", "lognormal", "neg. binomial (zero-infl.)", "negative binomial", "normal", "pareto", "poisson", "poisson (zero-infl.)", "tweedie", "uniform", "weibull" ) ) expect_equal( out$p_Residuals, c( 0, 0, 0, 0, 0.90625, 0, 0, 0, 0.0625, 0, 0, 0, 0.03125, 0, 0, 0, 0, 0, 0, 0, 0 ), tolerance = 1e-4 ) expect_equal( out$p_Response, c( 0, 0, 0, 0, 0, 0, 0, 0, 0.34375, 0, 0, 0.65625, 0, 0, 0, 0, 0, 0, 0, 0, 0 ), tolerance = 1e-4 ) expect_snapshot(print(out)) }) performance/tests/testthat/_snaps/0000755000176200001440000000000014715376125017053 5ustar liggesusersperformance/tests/testthat/_snaps/model_performance.rma.md0000644000176200001440000000021114412517050023612 0ustar liggesusers# check_outliers.rma Code out Output 2 outliers detected: studies 4 (Hart & Sutherland) and 8 (TPT Madras). performance/tests/testthat/_snaps/pkg-ivreg.md0000644000176200001440000000111014715376125021261 0ustar liggesusers# Issue #530 from the `modelsummary` repo Code out Output # Indices of model performance AIC | BIC | R2 | R2 (adj.) | RMSE | Sigma | Wu & Hausman -------------------------------------------------------------------- 182.692 | 191.486 | 0.655 | 0.604 | 3.484 | 3.793 | 13.869 AIC | p (Wu_Hausman) | Weak instruments | p (weak_instruments) ------------------------------------------------------------------ 182.692 | < .001 | 19.958 | < .001 performance/tests/testthat/_snaps/compare_performance.md0000644000176200001440000000714114715376125023407 0ustar liggesusers# compare_performance Code print(compare_performance(lm1, lm2, lm3)) Output # Comparison of Model Performance Indices Name | Model | AIC (weights) | AICc (weights) | BIC (weights) | R2 --------------------------------------------------------------------- lm1 | lm | 231.5 (<.001) | 231.7 (<.001) | 243.5 (<.001) | 0.619 lm2 | lm | 106.2 (0.566) | 106.6 (0.611) | 121.3 (0.964) | 0.837 lm3 | lm | 106.8 (0.434) | 107.6 (0.389) | 127.8 (0.036) | 0.840 Name | R2 (adj.) | RMSE | Sigma -------------------------------- lm1 | 0.614 | 0.510 | 0.515 lm2 | 0.833 | 0.333 | 0.338 lm3 | 0.835 | 0.330 | 0.336 --- Code print(compare_performance(lm1, lm2, lm3), table_width = Inf) Output # Comparison of Model Performance Indices Name | Model | AIC (weights) | AICc (weights) | BIC (weights) | R2 | R2 (adj.) | RMSE | Sigma ------------------------------------------------------------------------------------------------- lm1 | lm | 231.5 (<.001) | 231.7 (<.001) | 243.5 (<.001) | 0.619 | 0.614 | 0.510 | 0.515 lm2 | lm | 106.2 (0.566) | 106.6 (0.611) | 121.3 (0.964) | 0.837 | 0.833 | 0.333 | 0.338 lm3 | lm | 106.8 (0.434) | 107.6 (0.389) | 127.8 (0.036) | 0.840 | 0.835 | 0.330 | 0.336 --- Code print(compare_performance(lm1, lm2, lm3), layout = "vertical") Output # Comparison of Model Performance Indices Metric | lm1 | lm2 | lm3 -------------------------------------------------------------- Model | lm | lm | lm AIC (weights) | 231.5 (<.001) | 106.2 (0.566) | 106.8 (0.434) AICc (weights) | 231.7 (<.001) | 106.6 (0.611) | 107.6 (0.389) BIC (weights) | 243.5 (<.001) | 121.3 (0.964) | 127.8 (0.036) R2 | 0.619 | 0.837 | 0.840 R2 (adj.) | 0.614 | 0.833 | 0.835 RMSE | 0.510 | 0.333 | 0.330 Sigma | 0.515 | 0.338 | 0.336 --- Code print(compare_performance(lm1, lm2, lm3, lm4), layout = "vertical", table_width = 50) Message When comparing models, please note that probably not all models were fit from same data. Output # Comparison of Model Performance Indices Metric | lm1 | lm2 ---------------------------------------------- Model | lm | lm AIC (weights) | 231.5 (<.001) | 106.2 (0.408) AICc (weights) | 231.7 (<.001) | 106.6 (0.454) BIC (weights) | 243.5 (<.001) | 121.3 (0.933) R2 | 0.619 | 0.837 R2 (adj.) | 0.614 | 0.833 RMSE | 0.510 | 0.333 Sigma | 0.515 | 0.338 Metric | lm3 | lm4 ---------------------------------------------- Model | lm | lm AIC (weights) | 106.8 (0.313) | 107.0 (0.279) AICc (weights) | 107.6 (0.289) | 107.8 (0.257) BIC (weights) | 127.8 (0.035) | 128.0 (0.032) R2 | 0.840 | 0.840 R2 (adj.) | 0.835 | 0.834 RMSE | 0.330 | 0.331 Sigma | 0.336 | 0.337 performance/tests/testthat/_snaps/check_dag.md0000644000176200001440000001742314671770242021273 0ustar liggesusers# check_dag Code print(dag) Output # Check for correct adjustment sets - Outcome: y - Exposure: x Identification of direct and total effects Model is correctly specified. No adjustment needed to estimate the direct and total effect of `x` on `y`. --- Code print(dag) Output # Check for correct adjustment sets - Outcome: y - Exposure: x - Adjustment: b Identification of direct and total effects Model is correctly specified. All minimal sufficient adjustments to estimate the direct and total effect were done. --- Code print(dag) Output # Check for correct adjustment sets - Outcome: y - Exposure: x Identification of direct and total effects Incorrectly adjusted! To estimate the direct and total effect, at least adjust for `b`. Currently, the model does not adjust for any variables. --- Code print(dag) Output # Check for correct adjustment sets - Outcome: y - Exposure: x - Adjustment: c Identification of direct and total effects Incorrectly adjusted! To estimate the direct and total effect, at least adjust for `b` and `c`. Currently, the model only adjusts for `c`. You possibly also need to adjust for `b` to block biasing paths. --- Code print(dag) Output # Check for correct adjustment sets - Outcome: y - Exposure: x - Adjustment: c Identification of direct and total effects Incorrectly adjusted! To estimate the direct and total effect, at least adjust for `b` and `c`. Currently, the model only adjusts for `c`. You possibly also need to adjust for `b` to block biasing paths. --- Code print(dag) Output # Check for correct adjustment sets - Outcome: mpg - Exposure: wt - Adjustments: cyl, disp and gear Identification of direct and total effects Model is correctly specified. All minimal sufficient adjustments to estimate the direct and total effect were done. # check_dag, multiple adjustment sets Code print(dag) Output # Check for correct adjustment sets - Outcome: exam - Exposure: podcast Identification of direct and total effects Incorrectly adjusted! To estimate the direct and total effect, at least adjust for one of the following sets: - alertness, prepared - alertness, skills_course - mood, prepared - mood, skills_course. Currently, the model does not adjust for any variables. --- Code print(dag) Output # Check for correct adjustment sets - Outcome: exam - Exposure: podcast - Adjustments: alertness and prepared Identification of direct and total effects Model is correctly specified. All minimal sufficient adjustments to estimate the direct and total effect were done. --- Code print(dag) Output # Check for correct adjustment sets - Outcome: exam - Exposure: podcast - Adjustment: alertness Identification of direct and total effects Incorrectly adjusted! To estimate the direct and total effect, at least adjust for one of the following sets: - alertness, prepared - alertness, skills_course. Currently, the model only adjusts for `alertness`. You possibly also need to adjust for `prepared` and `skills_course` to block biasing paths. # check_dag, different adjustements for total and direct Code print(dag) Output # Check for correct adjustment sets - Outcome: outcome - Exposure: exposure Identification of direct effects Incorrectly adjusted! To estimate the direct effect, at least adjust for `x1` and `x2`. Currently, the model does not adjust for any variables. Identification of total effects Incorrectly adjusted! To estimate the total effect, at least adjust for `x1`. Currently, the model does not adjust for any variables. --- Code print(dag) Output # Check for correct adjustment sets - Outcome: outcome - Exposure: exposure - Adjustment: x1 Identification of direct effects Incorrectly adjusted! To estimate the direct effect, at least adjust for `x1` and `x2`. Currently, the model only adjusts for `x1`. You possibly also need to adjust for `x2` to block biasing paths. Identification of total effects Model is correctly specified. All minimal sufficient adjustments to estimate the total effect were done. --- Code print(dag) Output # Check for correct adjustment sets - Outcome: outcome - Exposure: exposure - Adjustment: x2 Identification of direct effects Incorrectly adjusted! To estimate the direct effect, at least adjust for `x1` and `x2`. Currently, the model only adjusts for `x2`. You possibly also need to adjust for `x1` to block biasing paths. Identification of total effects Incorrectly adjusted! To estimate the total effect, do not adjust for `x2`. --- Code print(dag) Output # Check for correct adjustment sets - Outcome: outcome - Exposure: exposure - Adjustments: x1 and x2 Identification of direct effects Model is correctly specified. All minimal sufficient adjustments to estimate the direct effect were done. Identification of total effects Incorrectly adjusted! To estimate the total effect, do not adjust for some or all of `x1` and `x2`. # check_dag, collider bias Code print(dag) Output # Check for correct adjustment sets - Outcome: SMD_ICD11 - Exposure: agegroup - Adjustments: edgroup3, gender_kid, pss4_kid_sum_2sd and residence Identification of direct effects Incorrectly adjusted! To estimate the direct effect, at least adjust for `edgroup3`, `gender_kid`, `pss4_kid_sum_2sd`, `residence` and `sm_h_total_kid`. Currently, the model only adjusts for `edgroup3`, `gender_kid`, `pss4_kid_sum_2sd` and `residence`. You possibly also need to adjust for `sm_h_total_kid` to block biasing paths. Identification of total effects Model is correctly specified. All minimal sufficient adjustments to estimate the total effect were done. --- Code print(dag) Output # Check for correct adjustment sets - Outcome: SMD_ICD11 - Exposure: agegroup - Adjustments: edgroup3, gender_kid, pss4_kid_sum_2sd, residence and sm_h_total_kid - Collider: sm_h_total_kid Identification of direct effects Incorrectly adjusted! Your model adjusts for a potential collider. To estimate the direct effect, do not adjust for `sm_h_total_kid` to avoid collider-bias. It is recommended to double-check for the collider-bias on the dagitty-website. Identification of total effects Incorrectly adjusted! Your model adjusts for a potential collider. To estimate the total effect, do not adjust for `sm_h_total_kid` to avoid collider-bias. It is recommended to double-check for the collider-bias on the dagitty-website. performance/tests/testthat/_snaps/check_distribution.md0000644000176200001440000000075014616413233023243 0ustar liggesusers# check_distribution Code print(out) Output # Distribution of Model Family Predicted Distribution of Residuals Distribution Probability cauchy 91% gamma 6% neg. binomial (zero-infl.) 3% Predicted Distribution of Response Distribution Probability lognormal 66% gamma 34% performance/tests/testthat/_snaps/bootstrapped_icc_ci.md0000644000176200001440000000223314430402261023355 0ustar liggesusers# bootstrapped icc ci_methods Code print(out1) Output # Intraclass Correlation Coefficient Adjusted ICC: 0.722 [0.502, 0.794] Unadjusted ICC: 0.521 [0.310, 0.568] --- Code print(out2) Output # Intraclass Correlation Coefficient Adjusted ICC: 0.722 [0.647, 0.886] Unadjusted ICC: 0.521 [0.474, 0.657] --- Code print(out3) Output # Intraclass Correlation Coefficient Adjusted ICC: 0.722 [0.644, 0.783] Unadjusted ICC: 0.521 [0.412, 0.615] # bootstrapped r2_nakagawa ci_methods Code print(out1) Output # R2 for Mixed Models Conditional R2: 0.799 [0.678, 0.852] Marginal R2: 0.279 [0.204, 0.392] --- Code print(out2) Output # R2 for Mixed Models Conditional R2: 0.799 [0.734, 0.918] Marginal R2: 0.279 [0.231, 0.309] --- Code print(out3) Output # R2 for Mixed Models Conditional R2: 0.799 [0.739, 0.846] Marginal R2: 0.279 [0.170, 0.390] performance/tests/testthat/_snaps/nestedLogit.md0000644000176200001440000000055314510751271021651 0ustar liggesusers# model_performance Code model_performance(mnl) Output # Indices of model performance Response | AIC | BIC | RMSE | Sigma | R2 ---------------------------------------------------- work | 325.733 | 336.449 | 0.456 | 1.000 | 0.138 full | 110.495 | 118.541 | 0.398 | 1.000 | 0.333 performance/tests/testthat/_snaps/check_collinearity.md0000644000176200001440000000201014576267034023224 0ustar liggesusers# check_collinearity, ci = NULL Code out Output # Check for Multicollinearity Low Correlation Term VIF Increased SE Tolerance N 1.00 1.00 1.00 P 1.00 1.00 1.00 K 1.00 1.00 1.00 # check_collinearity, hurdle/zi models w/o zi-formula Code print(out) Output # Check for Multicollinearity * conditional component: Low Correlation Term VIF VIF 95% CI Increased SE Tolerance Tolerance 95% CI fem 1.06 [1.02, 1.20] 1.03 0.95 [0.83, 0.98] mar 1.06 [1.02, 1.20] 1.03 0.95 [0.83, 0.98] * zero inflated component: Low Correlation Term VIF VIF 95% CI Increased SE Tolerance Tolerance 95% CI fem 1.07 [1.02, 1.20] 1.03 0.94 [0.83, 0.98] mar 1.07 [1.02, 1.20] 1.03 0.94 [0.83, 0.98] performance/tests/testthat/_snaps/windows/0000755000176200001440000000000014546750702020544 5ustar liggesusersperformance/tests/testthat/_snaps/windows/check_itemscale.md0000644000176200001440000000237014546750702024173 0ustar liggesusers# check_itemscale Code print(out) Output # Description of (Sub-)ScalesComponent 1 Item | Missings | Mean | SD | Skewness | Difficulty | Discrimination | alpha if deleted ----------------------------------------------------------------------------------------- b | 0 | 5.02 | 0.79 | -0.04 | 0.84 | 0.06 | -0.55 e | 0 | 2.12 | 0.81 | -0.22 | 0.35 | -0.09 | -0.03 f | 0 | 2.00 | 0.82 | 0.00 | 0.33 | -0.16 | 0.17 Mean inter-item-correlation = -0.046 Cronbach's alpha = -0.159 Component 2 Item | Missings | Mean | SD | Skewness | Difficulty | Discrimination | alpha if deleted ----------------------------------------------------------------------------------------- a | 0 | 5.02 | 0.83 | -0.04 | 0.84 | 0.21 | -0.18 c | 0 | 4.74 | 0.81 | 0.51 | 0.79 | -0.04 | 0.41 d | 0 | 2.07 | 0.79 | -0.13 | 0.34 | 0.13 | 0.04 Mean inter-item-correlation = 0.067 Cronbach's alpha = 0.178 performance/tests/testthat/_snaps/mclogit.md0000644000176200001440000000110214412517050021011 0ustar liggesusers# model_performance Code model_performance(mod_mb) Output # Indices of model performance AIC | BIC | Nagelkerke's R2 | RMSE | Sigma ------------------------------------------------- 38.823 | 47.618 | 0.836 | 0.298 | 1.016 --- Code model_performance(mod_mc) Output # Indices of model performance AIC | BIC | Nagelkerke's R2 | RMSE | Sigma ------------------------------------------------- 13.228 | 24.424 | 0.998 | 0.009 | 0.068 performance/tests/testthat/test-check_autocorrelation.R0000644000176200001440000000066314576267034023247 0ustar liggesuserstest_that("check_autocorrelation", { data(mtcars) m <- lm(mpg ~ wt + cyl + gear + disp, data = mtcars) set.seed(123) out <- check_autocorrelation(m) expect_equal(as.vector(out), 0.316, ignore_attr = TRUE, tolerance = 1e-2) expect_identical( capture.output(print(out)), "OK: Residuals appear to be independent and not autocorrelated (p = 0.316)." ) expect_warning(plot(out), "There is currently") }) performance/tests/testthat/test-r2_nagelkerke.R0000644000176200001440000000134314574016742021403 0ustar liggesuserstest_that("r2_nagelkerke", { model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") expect_equal(r2_nagelkerke(model), c(`Nagelkerke's R2` = 0.589959301837163), tolerance = 1e-3) expect_equal(r2(model), list(R2_Tjur = c(`Tjur's R2` = 0.477692621360749)), tolerance = 1e-3, ignore_attr = TRUE) }) skip_if_not_installed("withr") test_that("r2_nagelkerke", { skip_if_not_installed("MASS") withr::with_options( list(contrasts = c("contr.treatment", "contr.poly")), { data(housing, package = "MASS") model <- MASS::polr(Sat ~ Infl + Type + Cont, weights = Freq, data = housing) expect_equal(r2_nagelkerke(model), c(`Nagelkerke's R2` = 0.1084083), tolerance = 1e-3) } ) }) performance/tests/testthat/test-backticks.R0000644000176200001440000000122414412517050020611 0ustar liggesuserstest_that("check_collinearity, backticks", { data(iris) iris$`a m` <- iris$Species iris$`Sepal Width` <- iris$Sepal.Width m1 <- lm(`Sepal Width` ~ Petal.Length + `a m` * log(Sepal.Length), data = iris) m2 <- lm(Sepal.Width ~ Petal.Length + Species * log(Sepal.Length), data = iris) expect_message(check_collinearity(m1)) expect_identical( check_collinearity(m1, verbose = FALSE)$Term, c("Petal.Length", "a m", "log(Sepal.Length)", "a m:log(Sepal.Length)") ) expect_identical( check_collinearity(m2, verbose = FALSE)$Term, c("Petal.Length", "Species", "log(Sepal.Length)", "Species:log(Sepal.Length)") ) }) performance/tests/testthat/test-model_performance.rma.R0000644000176200001440000000303514412517050023114 0ustar liggesusersskip_if_not_installed("metafor") skip_if_not_installed("metadat") data(dat.bcg, package = "metadat") dat <- metafor::escalc( measure = "RR", ai = tpos, bi = tneg, ci = cpos, di = cneg, data = dat.bcg ) test_that("model_performance.rma", { model <- metafor::rma(yi, vi, data = dat, method = "REML") mp <- model_performance(model, estimator = "REML") expect_null(mp$R2) expect_equal(mp$AIC, 28.40474, tolerance = 1e-3) expect_equal(mp$I2, 0.9222139, tolerance = 1e-3) expect_identical(colnames(mp), c( "AIC", "BIC", "I2", "H2", "TAU2", "CochransQ", "p_CochransQ", "df_error", "Omnibus", "p_Omnibus" )) }) test_that("check_outliers.rma", { model <- metafor::rma(yi, vi, data = dat, slab = author, method = "REML") out <- check_outliers(model) expect_equal( out, c( FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE ), ignore_attr = TRUE ) expect_identical(attributes(out)$outlier_var, c("Hart & Sutherland", "TPT Madras")) expect_snapshot(out) }) test_that("model_performance.rma", { model <- metafor::rma(yi, vi, mods = cbind(ablat, year), data = dat) mp <- model_performance(model, estimator = "REML") expect_equal(mp$R2, 0.6463217, tolerance = 1e-3) expect_equal(mp$AIC, 24.21375, tolerance = 1e-3) expect_equal(mp$I2, 0.719778, tolerance = 1e-3) expect_identical(colnames(mp), c( "AIC", "BIC", "I2", "H2", "TAU2", "CochransQ", "p_CochransQ", "df_error", "Omnibus", "p_Omnibus", "R2" )) }) performance/tests/testthat/test-performance_auc.R0000644000176200001440000000257614436076277022040 0ustar liggesuserstest_that("performance_auc", { model_auc <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") # message set.seed(3) expect_message({ out <- performance_accuracy(model_auc) }) expect_equal(out$Accuracy, 0.75833, tolerance = 1e-3) expect_equal(out$CI_low, 0.6, tolerance = 1e-3) expect_equal(out$CI_high, 0.9875, tolerance = 1e-3) set.seed(12) expect_message({ out <- performance_accuracy(model_auc) }) expect_equal(out$Accuracy, 0.97222, tolerance = 1e-3) expect_equal(out$CI_low, 0.89722, tolerance = 1e-3) expect_equal(out$CI_high, 1, tolerance = 1e-3) # message set.seed(3) expect_message({ out <- performance_accuracy(model_auc, ci = 0.8) }) expect_equal(out$Accuracy, 0.75833, tolerance = 1e-3) expect_equal(out$CI_low, 0.6, tolerance = 1e-3) expect_equal(out$CI_high, 0.95, tolerance = 1e-3) model_auc <- lm(mpg ~ wt + cyl, data = mtcars) set.seed(123) out <- performance_accuracy(model_auc) expect_equal(out$Accuracy, 0.94303, tolerance = 1e-3) expect_equal(out$CI_low, 0.8804, tolerance = 1e-3) expect_equal(out$CI_high, 0.98231, tolerance = 1e-3) set.seed(123) out <- performance_accuracy(model_auc, ci = 0.8) expect_equal(out$Accuracy, 0.94303, tolerance = 1e-3) expect_equal(out$CI_low, 0.90197, tolerance = 1e-3) expect_equal(out$CI_high, 0.97567, tolerance = 1e-3) }) performance/tests/testthat/test-model_performance.bayesian.R0000644000176200001440000000732314666017356024153 0ustar liggesusersskip_on_cran() skip_if_not_installed("rstanarm") skip_if_not_installed("rstantools") test_that("model_performance.stanreg", { skip_if_not_installed("curl") skip_if_offline() skip_if_not_installed("httr2") set.seed(333) model <- insight::download_model("stanreg_lm_1") skip_if(is.null(model)) perf <- model_performance(model) expect_equal(perf$R2, 0.7398733, tolerance = 1e-3) expect_equal(perf$R2_adjusted, 0.7162912, tolerance = 1e-3) expect_equal(perf$ELPD, -83.49838, tolerance = 1e-3) model <- insight::download_model("stanreg_lm_2") skip_if(is.null(model)) perf <- model_performance(model) expect_equal(perf$R2, 0.8168386, tolerance = 1e-3) expect_equal(perf$R2_adjusted, 0.7979026, tolerance = 1e-3) expect_equal(perf$ELPD, -78.38735, tolerance = 1e-3) model <- insight::download_model("stanreg_lmerMod_1") skip_if(is.null(model)) perf <- model_performance(model) expect_equal(perf$R2, 0.642, tolerance = 1e-3) expect_equal(perf$R2_adjusted, 0.6053454, tolerance = 1e-3) expect_equal(perf$ELPD, -31.55849, tolerance = 1e-3) }) test_that("model_performance.brmsfit", { skip_if_not_installed("curl") skip_if_offline() skip_if_not_installed("httr2") set.seed(333) model <- insight::download_model("brms_1") skip_if(is.null(model)) expect_message({ perf <- model_performance(model) }) expect_equal(perf$R2, 0.8262673, tolerance = 1e-3) expect_equal(perf$R2_adjusted, 0.7982615, tolerance = 1e-3) expect_equal(perf$ELPD, -78.59823, tolerance = 1e-3) expect_identical(colnames(perf), c( "ELPD", "ELPD_SE", "LOOIC", "LOOIC_SE", "WAIC", "R2", "R2_adjusted", "RMSE", "Sigma" )) model <- insight::download_model("brms_mixed_4") skip_if(is.null(model)) expect_message({ perf <- model_performance(model) }) expect_equal(perf$R2, 0.954538, tolerance = 1e-3) expect_equal(perf$R2_adjusted, 0.9529004, tolerance = 1e-3) expect_equal(perf$ELPD, -70.40493, tolerance = 1e-3) expect_named(perf, c( "ELPD", "ELPD_SE", "LOOIC", "LOOIC_SE", "WAIC", "R2", "R2_marginal", "R2_adjusted", "R2_adjusted_marginal", "ICC", "RMSE", "Sigma" )) model <- insight::download_model("brms_ordinal_1") skip_if(is.null(model)) perf <- suppressWarnings(model_performance(model)) expect_equal(perf$R2, 0.8760015, tolerance = 1e-3) expect_equal(perf$ELPD, -11.65433, tolerance = 1e-3) }) test_that("model_performance.BFBayesFactor", { skip_if_not_installed("BayesFactor") mod <- BayesFactor::ttestBF(mtcars$wt, mu = 3) expect_warning({ p <- model_performance(mod) }) expect_null(p) mod <- BayesFactor::ttestBF(mtcars$wt, factor(mtcars$am)) expect_warning({ p <- model_performance(mod) }) expect_null(p) mods <- BayesFactor::contingencyTableBF(matrix(1:4, 2), sampleType = "indepMulti", fixedMargin = "cols") expect_warning({ p <- model_performance(mod) }) expect_null(p) mod <- BayesFactor::correlationBF(mtcars$wt, mtcars$am) expect_warning({ p <- model_performance(mod) }) expect_null(p) mod <- BayesFactor::proportionBF(y = 15, N = 25, p = 0.5) expect_warning({ p <- model_performance(mod) }) expect_null(p) t <- c(-0.15, 2.39, 2.42, 2.43, -0.15, 2.39, 2.42, 2.43) N <- c(100, 150, 97, 99, 99, 97, 100, 150) mod <- BayesFactor::meta.ttestBF(t, N) expect_warning({ p <- model_performance(mod) }) expect_null(p) skip_on_os("linux") mod <- BayesFactor::regressionBF(mpg ~ cyl, mtcars, progress = FALSE) modF <- lm(mpg ~ cyl, mtcars) p <- model_performance(mod) expect_equal(p$R2, unname(r2(modF)[[1]]), tolerance = 0.05) expect_equal(p$Sigma, sigma(modF), tolerance = 0.05) }) performance/tests/testthat/test-icc.R0000644000176200001440000001031114677205112017414 0ustar liggesusersskip_on_os("mac") skip_on_cran() test_that("icc", { m0 <- lm(Sepal.Length ~ Petal.Length, data = iris) expect_warning(expect_null(icc(m0))) }) test_that("icc", { skip_if_not_installed("lme4") m1 <- lme4::lmer(Sepal.Length ~ Petal.Length + (1 | Species), data = iris) expect_equal( icc(m1), data.frame( ICC_adjusted = 0.910433109183341, ICC_conditional = 0.310947768161385, ICC_unadjusted = 0.310947768161385 ), tolerance = 1e-3, ignore_attr = TRUE ) }) # bootstrapped CIs ------------ test_that("icc, CI", { skip_if_not_installed("lme4") data(sleepstudy, package = "lme4") m <- lme4::lmer(Reaction ~ Days + (1 + Days | Subject), data = sleepstudy) set.seed(123) out <- icc(m, ci = 0.95) expect_equal(out$ICC_adjusted, c(0.72166, 0.52239, 0.84024), tolerance = 1e-1) expect_equal(out$ICC_unadjusted, c(0.52057, 0.32429, 0.67123), tolerance = 1e-1) }) test_that("icc", { skip_if_not_installed("curl") skip_if_offline() skip_if_not_installed("httr2") m2 <- insight::download_model("stanreg_lmerMod_1") expect_equal( icc(m2), data.frame( ICC_adjusted = 0.40579, ICC_conditional = 0.21881, ICC_unadjusted = 0.21881 ), tolerance = 1e-2, ignore_attr = TRUE ) }) test_that("icc", { skip_if_not_installed("curl") skip_if_offline() skip_if_not_installed("httr2") m3 <- insight::download_model("brms_mixed_1") set.seed(123) expect_equal( variance_decomposition(m3)$ICC_decomposed, 0.3262006, tolerance = 0.05 ) }) test_that("icc", { skip_if_not_installed("curl") skip_if_offline() skip_if_not_installed("httr2") m3 <- insight::download_model("brms_mixed_1") set.seed(123) expect_equal( icc(m3), data.frame( ICC_adjusted = 0.930217931275196, ICC_conditional = 0.771475122370036, ICC_unadjusted = 0.771475122370036 ), tolerance = 0.05, ignore_attr = TRUE ) }) test_that("icc", { skip_if_not_installed("lme4") data(sleepstudy, package = "lme4") set.seed(12345) sleepstudy$grp <- sample.int(5, size = 180, replace = TRUE) sleepstudy$subgrp <- NA for (i in 1:5) { filter_group <- sleepstudy$grp == i sleepstudy$subgrp[filter_group] <- sample.int(30, size = sum(filter_group), replace = TRUE) } model <- lme4::lmer( Reaction ~ Days + (1 | grp) + (1 | Subject), data = sleepstudy ) expect_equal( icc(model, by_group = TRUE), structure( list( Group = c("Subject", "grp"), ICC = c(0.5896587, 0.0016551) ), class = c("icc_by_group", "data.frame"), row.names = c(NA, -2L) ), tolerance = 0.05 ) }) test_that("icc", { skip_if_not_installed("nlme") skip_if_not_installed("lme4") m <- nlme::lme(Sepal.Length ~ Petal.Length, random = ~ 1 | Species, data = iris) out <- icc(m) expect_equal(out$ICC_adjusted, 0.9104331, tolerance = 0.01) expect_equal(out$ICC_unadjusted, 0.3109478, tolerance = 0.01) }) test_that("icc, glmmTMB 1.1.9+", { skip_if_not_installed("glmmTMB") set.seed(101) dd <- data.frame( z = rnorm(1000), x1 = 1:1000, x2 = runif(1000, 0, 10), re = rep(1:20, each = 50) ) dd <- transform(dd, x3 = as.factor(ifelse( x1 <= 500, "Low", sample(c("Middle", "High"), 1000, replace = TRUE) ))) dd <- transform(dd, x4 = as.factor(ifelse( x1 > 500, "High", sample(c("Absent", "Low"), 1000, replace = TRUE) ))) dd <- transform(dd, z = z + re * 5) expect_message({ mod_TMB <- glmmTMB::glmmTMB( z ~ x1 + x2 + x3 + x4 + (1 | re), data = dd, start = list(theta = 3), control = glmmTMB::glmmTMBControl(rank_check = "adjust") ) }) expect_equal( icc(mod_TMB), data.frame( ICC_adjusted = 0.995480998331767, ICC_conditional = 0.244468078371849, ICC_unadjusted = 0.244468078371849 ), ignore_attr = TRUE, tolerance = 1e-4 ) expect_equal( r2(mod_TMB), list( R2_conditional = c(`Conditional R2` = 0.998890233308478), R2_marginal = c(`Marginal R2` = 0.754422154936629) ), ignore_attr = TRUE, tolerance = 1e-4 ) }) performance/tests/testthat/test-roc.R0000644000176200001440000000136614412517050017445 0ustar liggesusersskip_if_not_installed("ISLR") data(Smarket, package = "ISLR") m1 <- glm(am ~ vs + wt, family = binomial(), data = mtcars) m2 <- glm(Direction ~ Lag1 + Volume, family = binomial(), data = Smarket) roc1 <- performance_roc(m1) roc2 <- performance_roc(m2) auc1 <- bayestestR::area_under_curve(roc1$Specificity, roc1$Sensitivity) auc2 <- bayestestR::area_under_curve(roc2$Specificity, roc2$Sensitivity) test_that("roc", { expect_equal(head(roc1$Sensitivity), c(0, 0.07692, 0.15385, 0.23077, 0.30769, 0.38462), tolerance = 1e-2) expect_equal(head(roc2$Sensitivity), c(0, 0, 0, 0, 0.00154, 0.00154), tolerance = 1e-2) }) test_that("auc", { expect_equal(auc1, 0.964, tolerance = 1e-2) expect_equal(auc2, 0.535, tolerance = 1e-2) }) performance/tests/testthat/test-item_intercor.R0000644000176200001440000000031614355271477021537 0ustar liggesuserstest_that("item_intercor", { data(iris) x <- iris[, 1:4] expect_equal(item_intercor(x), 0.2900708, tolerance = 1e-3) expect_equal(item_intercor(x, "spearman"), 0.3147349, tolerance = 1e-3) }) performance/tests/testthat/test-test_vuong.R0000644000176200001440000000333314412517050021053 0ustar liggesuserstest_that("test_vuong - nested", { skip_if_not_installed("nonnest2") m1 <- lm(Sepal.Length ~ Petal.Width * Species, data = iris) m2 <- lm(Sepal.Length ~ Petal.Width + Species, data = iris) m3 <- lm(Sepal.Length ~ Petal.Width, data = iris) rez <- test_vuong(m1, m2, m3) ref <- nonnest2::vuongtest(m1, m2, nested = TRUE) expect_equal(rez[2L, "Omega2"], ref$omega) expect_equal(rez[2L, "p_Omega2"], ref$p_omega) expect_equal(rez[2L, "LR"], ref$LRTstat) expect_equal(rez[2L, "p_LR"], ref$p_LRT$A) ref <- nonnest2::vuongtest(m2, m3, nested = TRUE) expect_equal(rez[3L, "Omega2"], ref$omega) expect_equal(rez[3L, "p_Omega2"], ref$p_omega) expect_equal(rez[3L, "LR"], ref$LRTstat) expect_equal(rez[3L, "p_LR"], ref$p_LRT$A) }) # test_that("test_vuong - nested (reversed)", { # skip_if_not_installed("nonnest2") # m1 <- lm(mpg ~ wt + cyl, data = mtcars) # m2 <- lm(mpg ~ wt + cyl + gear, data = mtcars) # m3 <- lm(mpg ~ wt + cyl + gear + disp, data = mtcars) # }) test_that("test_vuong - non-nested", { skip_if_not_installed("nonnest2") m1 <- lm(Sepal.Length ~ Petal.Width, data = iris) m2 <- lm(Sepal.Length ~ Petal.Length, data = iris) m3 <- lm(Sepal.Length ~ Species, data = iris) rez <- test_vuong(m1, m2, m3) ref <- nonnest2::vuongtest(m1, m2) expect_equal(rez[2L, "Omega2"], ref$omega) expect_equal(rez[2L, "p_Omega2"], ref$p_omega) expect_equal(rez[2L, "LR"], ref$LRTstat) expect_equal(rez[2L, "p_LR"], ref$p_LRT$B) ref <- nonnest2::vuongtest(m1, m3) expect_equal(rez[3L, "Omega2"], ref$omega) expect_equal(rez[3L, "p_Omega2"], ref$p_omega) expect_equal(rez[3L, "LR"], ref$LRTstat) expect_equal(rez[3L, "p_LR"], ref$p_LRT$A) }) performance/tests/testthat/test-bootstrapped_icc_ci.R0000644000176200001440000000411014430402261022644 0ustar liggesuserstest_that("bootstrapped icc ci_methods", { skip_on_cran() skip_on_os(c("mac", "linux")) skip_if_not_installed("lme4") data(sleepstudy, package = "lme4") m_icc <- lme4::lmer(Reaction ~ Days + (1 + Days | Subject), data = sleepstudy) set.seed(123) out1 <- icc(m_icc, ci = 0.95, iterations = 20) set.seed(123) out2 <- icc(m_icc, ci = 0.95, iterations = 20, ci_method = "boot") set.seed(123) out3 <- icc(m_icc, ci = 0.95, iterations = 20, ci_method = "analytical") expect_equal( out1$ICC_adjusted, c(0.72166, 0.50154, 0.79417), tolerance = 1e-3, ignore_attr = TRUE ) expect_equal( out2$ICC_adjusted, c(0.72166, 0.64683, 0.88631), tolerance = 1e-3, ignore_attr = TRUE ) expect_equal( out3$ICC_adjusted, c(0.72166, 0.64359, 0.78347), tolerance = 1e-3, ignore_attr = TRUE ) expect_snapshot(print(out1)) expect_snapshot(print(out2)) expect_snapshot(print(out3)) }) test_that("bootstrapped r2_nakagawa ci_methods", { skip_on_cran() skip_on_os(c("mac", "linux")) skip_if_not_installed("lme4") data(sleepstudy, package = "lme4") m_icc <- lme4::lmer(Reaction ~ Days + (1 + Days | Subject), data = sleepstudy) set.seed(123) out1 <- r2_nakagawa(m_icc, ci = 0.95, iterations = 20) set.seed(123) out2 <- r2_nakagawa(m_icc, ci = 0.95, iterations = 20, ci_method = "boot") set.seed(123) out3 <- r2_nakagawa(m_icc, ci = 0.95, iterations = 20, ci_method = "analytical") expect_equal( out1$R2_marginal, c(`Marginal R2` = 0.27865, CI_low = 0.20403, CI_high = 0.39177), tolerance = 1e-3, ignore_attr = TRUE ) expect_equal( out2$R2_marginal, c(`Marginal R2` = 0.27865, CI_low = 0.23123, CI_high = 0.30851), tolerance = 1e-3, ignore_attr = TRUE ) expect_equal( out3$R2_marginal, c(`Marginal R2` = 0.27865, CI_low = 0.17018, CI_high = 0.39031), tolerance = 1e-3, ignore_attr = TRUE ) expect_snapshot(print(out1)) expect_snapshot(print(out2)) expect_snapshot(print(out3)) }) performance/tests/testthat/test-check_model.R0000644000176200001440000000760714741713401021126 0ustar liggesusersskip_on_cran() skip_if_not_installed("see", minimum_version = "0.9.1") d <- data.frame( y = c( 101L, 219L, 70L, 67L, 31L, 243L, 41L, 250L, 140L, 210L, 22L, 121L, 282L, 144L, 223L, 297L, 20L, 13L, 148L, 57L, 143L, 109L, 273L, 83L, 28L, 153L, 261L, 209L, 134L, 95L, 17L, 11L ), x = c( 9.43240344971252, 15.2821279871535, 29.1169666338249, 14.0859852649899, 15.6464367574587, 8.86321119888889, 67.9427830082998, 8.60340052656454, 21.9029971533007, 19.8586681899898, 9.68086847417484, 25.0990259928273, 16.1398284119823, 29.3829154122785, 31.5592351678585, 14.0320212214305, 31.3815560884357, 18.3566866719804, 28.3822251897697, 67.9433435559261, 26.6656339570149, 5.83151069454924, 7.93210796912854, 35.9198997836162, 21.6330853399868, 34.484392512508, 35.9444483480784, 28.4517728364097, 27.2868577206239, 8.1803022427107, 46.3029232706936, 41.516915503604 ), offset = c( 481L, 515L, 396L, 451L, 547L, 409L, 375L, 430L, 526L, 456L, 450L, 425L, 406L, 396L, 421L, 417L, 430L, 419L, 436L, 517L, 511L, 435L, 489L, 417L, 372L, 373L, 351L, 367L, 350L, 339L, 169L, 63L ) ) suppressWarnings({ m <- glm(y ~ x + offset(offset), family = poisson, data = d) }) test_that("`check_model()` works if convergence issues", { x <- check_model(m, verbose = FALSE) expect_s3_class(x, "check_model") }) test_that("`check_outliers()` works if convergence issues", { x <- check_outliers(m, verbose = FALSE) expect_s3_class(x, "check_outliers") }) test_that("`check_model()` for invalid models", { dd <- data.frame(y = as.difftime(0:5, units = "days")) m1 <- lm(y ~ 1, data = dd) expect_message(check_model(m1), regex = "Date variables are not") }) test_that("`check_model()` works for quantreg", { skip_if_not_installed("quantreg") data(engel, package = "quantreg") qm <- quantreg::rq(foodexp ~ income, data = engel) x <- check_model(qm, verbose = FALSE) expect_s3_class(x, "check_model") }) test_that("`check_model()` warnings for tweedie", { skip_if_not_installed("glmmTMB") skip_if_not_installed("lme4") data(sleepstudy, package = "lme4") set.seed(123) d <- sleepstudy[sample.int(50), ] m <- suppressWarnings(glmmTMB::glmmTMB(Reaction ~ Days, data = d, family = glmmTMB::tweedie )) expect_message( expect_message( check_model(m, iterations = 2, verbose = TRUE), regex = "Not enough model terms" ) ) }) test_that("`check_model()` warnings for zero-infl", { skip_if_not_installed("pscl") data(bioChemists, package = "pscl") model <- pscl::zeroinfl( art ~ fem + mar + kid5 + ment | kid5 + phd, data = bioChemists ) expect_message(expect_message(check_model(model, verbose = TRUE), regex = "Cannot simulate"), regex = "Homogeneity") }) test_that("`check_model()` no warnings for quasipoisson", { skip_if_not_installed("datawizard") set.seed(250419) # Generate random x values x <- rnorm( n = 500, mean = 5, sd = 2 ) # Generate y values y = 5x + e y <- 5 * x + rnorm( n = 500, mean = 5, sd = 2 ) # Generate z as offset z <- runif(500, min = 0, max = 6719) mock_data <- data.frame(x, y, z) |> # both should be whole numbers since they're counts datawizard::data_modify(y = round(y), z = round(z)) |> datawizard::data_filter(x >= 0, y >= 0) # Run model model1 <- glm(y ~ x + offset(log(z)), family = "quasipoisson", data = mock_data) expect_message(check_model(model1, verbose = TRUE), regex = "Not enough") expect_silent(check_model(model1)) }) test_that("`check_model()` with transformed response when named as function", { data(mtcars) # rename variable, so it equals to a valid R function mtcars$rt <- mtcars$mpg model <- lm(log(rt) ~ disp, data = mtcars) out <- check_predictions(model) expect_s3_class(out, "performance_pp_check") }) performance/tests/testthat/test-r2_zeroinflated.R0000644000176200001440000000353014412517050021746 0ustar liggesuserstest_that("r2_zeroinflated", { skip_if_not_installed("pscl") data(bioChemists, package = "pscl") model <- pscl::zeroinfl( art ~ fem + mar + kid5 + ment | kid5 + phd, data = bioChemists ) expect_equal( r2_zeroinflated(model), structure( list( R2 = c(R2 = 0.179754784762554), R2_adjusted = c(`adjusted R2` = 0.175242984898761) ), model_type = "Zero-Inflated and Hurdle", class = "r2_generic" ), tolerance = 1e-4 ) expect_equal( r2(model), structure( list( R2 = c(R2 = 0.179754784762554), R2_adjusted = c(`adjusted R2` = 0.175242984898761) ), model_type = "Zero-Inflated and Hurdle", class = "r2_generic" ), tolerance = 1e-4 ) expect_equal( r2_zeroinflated(model, method = "correlation"), c(`R2 for ZI-models` = 0.0945232333944027), tolerance = 1e-4 ) }) test_that("r2_zeroinflated", { skip_if_not_installed("pscl") data(bioChemists, package = "pscl") model <- pscl::hurdle( art ~ fem + mar + kid5 + ment | kid5 + phd, data = bioChemists ) expect_equal( r2_zeroinflated(model), structure( list( R2 = c(R2 = 0.0920246818082126), R2_adjusted = c(`adjusted R2` = 0.087030318121789) ), model_type = "Zero-Inflated and Hurdle", class = "r2_generic" ), tolerance = 1e-4 ) expect_equal( r2(model), structure( list( R2 = c(R2 = 0.0920246818082126), R2_adjusted = c(`adjusted R2` = 0.087030318121789) ), model_type = "Zero-Inflated and Hurdle", class = "r2_generic" ), tolerance = 1e-4 ) expect_equal( r2_zeroinflated(model, method = "correlation"), c(`R2 for ZI-models` = 0.08938686), tolerance = 1e-4 ) }) performance/tests/testthat/test-performance_roc.R0000644000176200001440000000356414736731423022043 0ustar liggesusersskip_if_not_installed("bayestestR") test_that("performance_roc", { skip_if_not_installed("lme4") m <- lme4::glmer(vs ~ mpg + (1 | gear), family = "binomial", data = mtcars) roc <- performance_roc(m) expect_equal( roc$Sensitivity, c( 0, 0.07143, 0.14286, 0.21429, 0.28571, 0.35714, 0.42857, 0.5, 0.57143, 0.57143, 0.64286, 0.64286, 0.64286, 0.71429, 0.78571, 0.85714, 0.85714, 0.92857, 0.92857, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ), tolerance = 1e-3 ) }) test_that("performance_roc", { set.seed(123) d <- iris[sample(1:nrow(iris), size = 50), ] d$y <- as.factor(rbinom(nrow(d), size = 1, 0.3)) dat <<- d m <- glm( y ~ Sepal.Length + Sepal.Width, data = dat, family = "binomial" ) roc <- performance_roc(m) expect_equal( roc$Sensitivity, c( 0, 0, 0.07692, 0.07692, 0.07692, 0.15385, 0.23077, 0.23077, 0.23077, 0.23077, 0.23077, 0.30769, 0.30769, 0.30769, 0.30769, 0.30769, 0.38462, 0.38462, 0.38462, 0.46154, 0.46154, 0.53846, 0.53846, 0.53846, 0.53846, 0.61538, 0.61538, 0.61538, 0.61538, 0.61538, 0.69231, 0.76923, 0.76923, 0.76923, 0.84615, 0.92308, 0.92308, 0.92308, 0.92308, 0.92308, 0.92308, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ), tolerance = 1e-3 ) }) test_that("performance_roc, as.numeric", { data(iris) set.seed(123) iris$y <- rbinom(nrow(iris), size = 1, .3) folds <- sample(nrow(iris), size = nrow(iris) / 8, replace = FALSE) test_data <- iris[folds, ] train_data <- iris[-folds, ] model <- glm(y ~ Sepal.Length + Sepal.Width, data = train_data, family = "binomial") roc <- performance_roc(model) out <- as.numeric(roc) expect_equal( out, bayestestR::area_under_curve(roc$Specificity, roc$Sensitivity), tolerance = 1e-4, ignore_attr = TRUE ) }) performance/tests/testthat/test-r2_coxsnell.R0000644000176200001440000000030414355271477021123 0ustar liggesuserstest_that("r2_coxsnell", { model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") expect_equal(r2_coxsnell(model), c(`Cox & Snell's R2` = 0.440140715155838), tolerance = 1e-3) }) performance/tests/testthat/test-model_performance.merMod.R0000644000176200001440000000371514643720175023577 0ustar liggesuserstest_that("model_performance.merMod", { skip_on_cran() skip_if_not_installed("curl") skip_if_offline() skip_if_not_installed("httr2") model <- insight::download_model("lmerMod_1") expect_equal(model_performance(model, estimator = "ML")$AIC, AIC(logLik(model, REML = FALSE)), tolerance = 0.01) expect_equal(model_performance(model, estimator = "REML")$AIC, AIC(model), tolerance = 0.01) model <- insight::download_model("merMod_1") expect_equal(model_performance(model)$AIC, AIC(model), tolerance = 0.01) expect_equal(model_performance(model, estimator = "REML")$AIC, AIC(model), tolerance = 0.01) expect_equal(model_performance(model)$AIC, 23.58593, tolerance = 0.01) model <- insight::download_model("merMod_2") expect_equal(model_performance(model)$AIC, 21.4729, tolerance = 0.01) }) test_that("model_performance.merMod AICc", { skip_on_cran() skip_if_not_installed("lme4") m1 <- lme4::lmer(mpg ~ disp + am + (1 | cyl), data = mtcars) m2 <- lm(mpg ~ hp + vs, data = mtcars) # REML expect_message(expect_equal( compare_performance(m1, m2, metrics = "AICc", estimator = "REML")$AICc, c(177.52804, 182.88598), tolerance = 1e-3 )) expect_equal(model_performance(m1, metrics = "AICc", estimator = "REML")$AICc, 177.52804, tolerance = 1e-3) expect_equal(performance_aicc(m1, estimator = "REML"), 177.52804, tolerance = 1e-3) # default - ML expect_equal( compare_performance(m1, m2, metrics = "AICc")$AICc, c(174.5701, 182.88598), tolerance = 1e-3 ) # default model_performance is REML expect_equal(model_performance(m1, metrics = "AICc")$AICc, 177.52804, tolerance = 1e-3) expect_equal(model_performance(m1, metrics = "AICc", estimator = "ML")$AICc, 174.5701, tolerance = 1e-3) # default performance_aic is REML expect_equal(performance_aicc(m1), 177.52804, tolerance = 1e-3) expect_equal(performance_aicc(m1, estimator = "ML"), 174.5701, tolerance = 1e-3) }) performance/tests/testthat.R0000644000176200001440000000010614412517050015674 0ustar liggesuserslibrary(testthat) library(performance) test_check("performance") performance/MD50000644000176200001440000003621114741740672013102 0ustar liggesusers4c633869d22edf1bad49f860bb31fcee *DESCRIPTION 2a82b21fde954a640e3a9d7cf8ff41a6 *NAMESPACE 2f9a2d722e5221621c8167aa11a52e77 *NEWS.md 4fef8ce0973eaecef14aa3cd65c5acb6 *R/binned_residuals.R e42a79e0aa77061c0993df153f869470 *R/check_autocorrelation.R 5676d70c18143056c870be6a35ce04f7 *R/check_clusterstructure.R 20d222dbbbd8a8576507cc5de65d1033 *R/check_collinearity.R 69b272ffbf8eff95764f249773d23d2b *R/check_concurvity.R 413bdf3b7e07c2f34c8dd7c8d0a43085 *R/check_convergence.R dd02e48e69261af0d3803497858c8b35 *R/check_dag.R f87f18d7c3abc05463e34d0fc26d8105 *R/check_distribution.R b6be0c40173381f1f067bba84ed31769 *R/check_factorstructure.R 91e0bbc500abb64effab78d8d90e7237 *R/check_heterogeneity_bias.R 53cf6adac2213d977593a7df48a3b01a *R/check_heteroscedasticity.R bcd8abdfc607f45513225adf57ae41a6 *R/check_homogeneity.R cf20935ade39863cfa3de71c5a61ab6d *R/check_htest.R 7a506b3aecd96a17957e79d43ddb5edb *R/check_itemscale.R b26c922cae3fa16a8747c111caf4beec *R/check_model.R 90fbeb85dfb1960963a28596822b26a3 *R/check_model_diagnostics.R bba580053bba521d195df5d37a18cb82 *R/check_multimodal.R 7ace76ca05943abc867a08c6a0051bb9 *R/check_normality.R 086a0eb047a15e5c4bc683c9bfa4800e *R/check_outliers.R 097280a7655fe819395ffeb91bf23a9a *R/check_overdispersion.R 5d30329063bd87211915449c9c5e085a *R/check_predictions.R 0dbba27088011f82085f7dde09561e78 *R/check_residuals.R e42e630e0e5f5f40ef4e5afbb4a62ac3 *R/check_singularity.R 8feb5757c51ab709251a2f2c34f6a7c4 *R/check_sphericity.R 3714afa9a6503032e296bdd1098ae1b0 *R/check_symmetry.R f43537dfff5da8f77d8f538978bc9db3 *R/check_zeroinflation.R 7ad023b442bf4a03d6d04d4b62567bf5 *R/compare_performance.R 197533654c539dbca8ab612d6f73e73a *R/cronbachs_alpha.R c8b6d9eccc60eb80fa6c6bf7676b985d *R/display.R 4940ef9e3bf7a1292ed815d1620cf49a *R/format.R fb1164079224e604c0181b17c7dd9178 *R/get_gradients.R 4721a4f43587e9cd3a2e1aba6f06377a *R/helpers.R d1907b01c19a4d9fa4a152d3ad7caf66 *R/icc.R cc6fe86ea48a5f816efdf56fa9fad744 *R/item_difficulty.R a88afe77d19c9d65652984d6876168c9 *R/item_discrimination.R f7fe4c594d25facd0b3dbbc3fcf5671f *R/item_intercor.R 94e50e184d9325b5805a0f3b372ef610 *R/item_reliability.R 9d2f9f180fdb5b5761390ab007ed7e81 *R/item_split_half.R d75df9a97d67629029e78ad66942a2f3 *R/logLik.R 0826850bcbe46d24d1e3f4e0e8480ac0 *R/looic.R 1e51bf7075239ce2150ac3193897f22e *R/model_performance.R 4a8059cf53efad0d7a823399220e3653 *R/model_performance.bayesian.R cf4036e45ad29f58ce139a2e1f15b54f *R/model_performance.bife.R dca2d0e512d6c25f4730bc55791f6e31 *R/model_performance.ivreg.R 99666c4e9faa55054908f6b961271c9e *R/model_performance.kmeans.R ceeb001d78fe4edbf176001560139f64 *R/model_performance.lavaan.R 0cc2d614fa2113abb3e9ed1f1959fb5a *R/model_performance.lm.R d3061ba33fb0fc2fb95d1fc7f9c0e1d5 *R/model_performance.mixed.R 6f9a39a3e147aa2518520ea83d79775b *R/model_performance.rma.R aa0654b17fb015c8c818d4f2a40a40d8 *R/model_performance_default.R 7a213a37a887cab95ccc7e7d88b6847d *R/performance-package.R 355fce3e74ff3f95e658c18f2fc77cf6 *R/performance_accuracy.R d8debf3ab74bb2672920a3621a762f34 *R/performance_aicc.R 71dd28aec40ca58f35f4fc20ca9318a9 *R/performance_cv.R 66d28e27426e63b4c0480d7d68e6087e *R/performance_hosmer.R 9a10706ed6413ee2a9cdee1929b75140 *R/performance_logloss.R 5347ccee650d8458596bc6dd695ff22c *R/performance_mae.R 8d84750f61230cf080d33a432cb18419 *R/performance_mse.R 0def002a510399f048f802d85386e3b1 *R/performance_pcp.R 68b871724e758a7bea018d2863e50c45 *R/performance_rmse.R 351fb527c9a8bf9c2b5ed7e0ab91eb73 *R/performance_roc.R 2c7e55fbc18fbf1278e54f24321689a9 *R/performance_rse.R f2d7eddd161d9db5242fcc7e16d5241d *R/performance_score.R 5a443d448dc89a8864a78d3f045974e3 *R/print-methods.R 54a2ac64749ebe7dbbff9c0f288ddb28 *R/print_md.R 19bbec8f0812f5d025a5ff98240bebfe *R/r2.R 673804a08da040d8215bb7e405304d7f *R/r2_bayes.R 1ff01a0a70b50d0eeec318f411c1152d *R/r2_ci.R 851e1cd75cbd7167a982b2e878aed0de *R/r2_coxsnell.R 328c2bc1fed0f6f9eb8af1510e8f59cc *R/r2_efron.R 8e692a032fee2ca67092dc9aae5e6ca1 *R/r2_ferarri.R 511aedbdad661094162519bbf82bab96 *R/r2_kl.R 3923f5745b351021e9da9f4de459718f *R/r2_loo.R 6cd1afd6a0b21c9035991f6a12b07dee *R/r2_mcfadden.R 5d85009b89659fa3716b45867d954881 *R/r2_mckelvey.R a3e1b0c4ab9ee32152b00d12ea681f93 *R/r2_mlm.R ab209b7350dfdd1690cbc27530881825 *R/r2_nagelkerke.R 7985568ba7f5e4e26ea67a5bafc96145 *R/r2_nakagawa.R c6dfd8f5b20f83a86f407ffe34a0dfeb *R/r2_somers.R f6fdac3aa7f8acc9b759db0c39196592 *R/r2_tjur.R 5434ec23d24ecfef1aaa52f814aa1419 *R/r2_xu.R 32265bf8ef4e9f3286186fbd0f3f4bed *R/r2_zeroinflated.R b93589685d529a5bece7aab9e1c6b625 *R/reexports.R 7ff6356deeadd7e217392afa3a39b0d0 *R/residuals.R 24f546c06bb5c1737377dd9ca86ad218 *R/simulate_residuals.R 1101cb3feb58384028a2734fec7ca7e0 *R/skewness_kurtosis.R ce95df9d8c6c87d36bcf02b9d5db72cf *R/sysdata.rda 44d25795e4184142b1e0e95de187835d *R/test_bf.R 6967d0a9feeffb297bdd44d1436da03f *R/test_likelihoodratio.R 9c54bebc3c4ffad123c4e0cfb843e031 *R/test_performance.R 97a9fb5d46aa05daf6a4c62c830437de *R/test_vuong.R ab5de3d3f899150111b17f6f97c91a07 *R/test_wald.R 413c7ac11bfb91021cd5d12acd6ef960 *README.md 1dda19015f0aa969acee990c150e3ac9 *build/partial.rdb b3f9f88d249c4b33a27a9567252871b1 *inst/CITATION 5796ef4446df7c2ee219eca43db7b56b *inst/WORDLIST b375470f888f6f59afedac666f454679 *man/binned_residuals.Rd 3e94293df7678e054618d18abf9c2442 *man/check_autocorrelation.Rd f9b5078a1a8f88495d20cb9535a525b7 *man/check_clusterstructure.Rd 203fed4ff3a3dd9e90f16369e1b838c2 *man/check_collinearity.Rd 35d938bb14962f9bfe74013f1c9d4875 *man/check_convergence.Rd 296bc7a0b64a2562b13ee1c4bbf4a336 *man/check_dag.Rd 8ce29cd2c92d233264ea67d5ed96e6df *man/check_distribution.Rd 4b6776d5031ee7544f4ae1e9e83b7388 *man/check_factorstructure.Rd 3f666eb7cc05344776f477f1a3b4e832 *man/check_heterogeneity_bias.Rd 73b0521eeee39362b1496b1d34a780ed *man/check_heteroscedasticity.Rd 374792315b879393e4ced18ca2144730 *man/check_homogeneity.Rd 15ac3508ef0e537142dd5b3d62b3bbe3 *man/check_itemscale.Rd 42c4a2f016c78a82cbe2f2b181f20e8a *man/check_model.Rd c7c2d3ab709befe97e7c3dc6890d467d *man/check_multimodal.Rd 7f26d66b106bf937692019a6160610ec *man/check_normality.Rd 18d15d6a3f3f0e2340e89c9fac8767cb *man/check_outliers.Rd ac1fab6c30093fc3f4633b0dc38c7109 *man/check_overdispersion.Rd 0ab7f7dd24f06c2a19aac487c84eb32d *man/check_predictions.Rd 71534ac83a4ca1c59d84ba10306da9c2 *man/check_residuals.Rd 8e0879d7cedc31926a35b7407642604f *man/check_singularity.Rd a5aa676bf803829497c0a306389ca897 *man/check_sphericity.Rd 9ea3fb91182f94bab263a8db44e97524 *man/check_symmetry.Rd d73c46195993e6cf592d59b50eb40c7f *man/check_zeroinflation.Rd 66bc416b58e3e63a19e70d06c8a41072 *man/classify_distribution.Rd 662281249b277e4da829e96c3373189d *man/compare_performance.Rd c639d91d01c9b918678b199f276c8550 *man/cronbachs_alpha.Rd f71bd9e688099b16abad850600ecf0a0 *man/display.performance_model.Rd d0145b99b577e763a3ee5d0863665b76 *man/figures/card.png 3c5fef75dbf3fc529506455b847cfd56 *man/figures/figure_workflow.png 1c7a7648e019e82f9c2e2558193a5dd2 *man/figures/logo.png 899848437d58da611299750568a41d8b *man/figures/pp_check.png e22c02dc326590a298502a318b9d1a85 *man/figures/unnamed-chunk-14-1.png 33eed1a6f21d8f5b18dc641794252afc *man/figures/unnamed-chunk-15-1.png 018a68482c95b3e8246d21daffae18d7 *man/figures/unnamed-chunk-20-1.png 0da25d332ce85011d1964f50874e8e49 *man/figures/unnamed-chunk-21-1.png 89fba128116d33b2e43b45982469566b *man/icc.Rd 10ea4717a2cccfcd3413f68539b55d73 *man/item_difficulty.Rd a3230da10897b22dff92ce4f39d85a98 *man/item_discrimination.Rd 9199c63650610d7712a14bbfce22f1ff *man/item_intercor.Rd 731bb41be7ebe4898c7c47bb31985a42 *man/item_reliability.Rd cd02bfeced4129437acb197389afa68a *man/item_split_half.Rd 8aedd82a320ccce57af5da40579138ea *man/looic.Rd 0f9178c4670e947ecfe620efcf04fe3e *man/model_performance.Rd 0f8154803ea449ec73677f74ac58df52 *man/model_performance.ivreg.Rd 22a996e9543ade69ed83021baf4fc64f *man/model_performance.kmeans.Rd d3291d3f203defa6a38fc7259b3decf8 *man/model_performance.lavaan.Rd 49f94e1de98ad2eae2342d9ce4a7c5ae *man/model_performance.lm.Rd f32689e4a7fd34c98b7670bcf805ccb8 *man/model_performance.merMod.Rd 77328e3bd728fd5821bfe0ebbd281fc9 *man/model_performance.rma.Rd 31c7b671cbaf1cc18587c5f672d726cc *man/model_performance.stanreg.Rd faf80a3f2155207f50e4a49b3c74c7de *man/performance-package.Rd a7cf38d14b1a9530664f7b5c0531f961 *man/performance_accuracy.Rd a1eac6cb0e507a617dc494bcd83e39c7 *man/performance_aicc.Rd c73b998501eeb037dbcb816b4a9fd555 *man/performance_cv.Rd b0606732318c712d8fd3da8d0d115b0c *man/performance_hosmer.Rd 8f76ca962283233b71567559624ba5aa *man/performance_logloss.Rd 027930234f6d6bd10794271bc16b729b *man/performance_mae.Rd e53431892b8f3872c6d062097bcb551d *man/performance_mse.Rd dbf8f55a6a8576573dc6759b5ce6bf92 *man/performance_pcp.Rd b7b542cc67b174f63c5f93e639f61143 *man/performance_rmse.Rd f6870c12fce2dfcdf3bd8f9502d4f5ad *man/performance_roc.Rd c286a0eb42a42e8f6120fa9f2069f67a *man/performance_rse.Rd cd85a42bdc370a4932414581c705b1e4 *man/performance_score.Rd 15c11dd8fd130c0d92f4c7c6943492c4 *man/r2.Rd 6b00245914ec7729415883ea06d068cd *man/r2_bayes.Rd 65f6df5ff076f79eee8f3f7c7ab85a19 *man/r2_coxsnell.Rd c8a9a8e0d67ec7a482a5a8188da92bb3 *man/r2_efron.Rd 7153267871af5b3405782c390db67bd8 *man/r2_ferrari.Rd 773807d314ce59329d77dea451742f74 *man/r2_kullback.Rd 37875fa13f9e369a4b8ccf775ad4747b *man/r2_loo.Rd 34821aa9e67990acb2ae85e3fa31e69a *man/r2_mcfadden.Rd 3007656b0dc3cf2ed5b4375cf45fede7 *man/r2_mckelvey.Rd d23e3693e5d50684df812b94adf3f00b *man/r2_mlm.Rd 844aac6a9207091f02503c6eeb2f705f *man/r2_nagelkerke.Rd 31e0553187d1038df76e4f82f1b71555 *man/r2_nakagawa.Rd be55217b4daf40e292aa8f83e0afe413 *man/r2_somers.Rd 938adfb78f1ebcf16a283b1f552542b6 *man/r2_tjur.Rd d999be4ed1f5c8489dcb6ddfafb3dc73 *man/r2_xu.Rd 197b1f10b81538365808915b9b1bebd2 *man/r2_zeroinflated.Rd ae2fddd61049fa35769ba30880943dad *man/reexports.Rd df69927a308e89345ccf03b5e315c657 *man/simulate_residuals.Rd 7f9c11cad940c3fc6d980ced46576aec *man/test_performance.Rd cb60cbf3577412c0bc6256424ce45d55 *tests/testthat.R c06eed005d9dc7b9cd6cba0bb1530356 *tests/testthat/_snaps/bootstrapped_icc_ci.md e710428ba2136d29454da0bc8e00265b *tests/testthat/_snaps/check_collinearity.md 76f82723837899452feea2214ab39513 *tests/testthat/_snaps/check_dag.md 15e75c08c01e0784d631fd041d093873 *tests/testthat/_snaps/check_distribution.md e6761e5a2ccee055dc8f3886f200ff6c *tests/testthat/_snaps/compare_performance.md 380e85797f95ed441e0a6e5268f5fdf1 *tests/testthat/_snaps/mclogit.md b4ad974eb8a31371747749a7553fb6c9 *tests/testthat/_snaps/model_performance.rma.md 5ea3535b333a95e35e1adbb74e25a966 *tests/testthat/_snaps/nestedLogit.md 46a8f355bb3e94d589f24807fadae608 *tests/testthat/_snaps/pkg-ivreg.md 88afe65ca9747a513100cec8a2a047c8 *tests/testthat/_snaps/windows/check_itemscale.md 09d81b66ba81dd6f52bec56c7533b59a *tests/testthat/test-backticks.R 1a57a8d1ef255bf57b8f1b4c288e6884 *tests/testthat/test-binned_residuals.R afb2dbaa7a0fcc3a643fb4ed37786787 *tests/testthat/test-bootstrapped_icc_ci.R 98345bef78f4faf0150dc41c60c7875f *tests/testthat/test-check_autocorrelation.R e374e46f3ac34887051a09df383a2a18 *tests/testthat/test-check_collinearity.R c58d83e932ca3c0bb158c778513f527b *tests/testthat/test-check_convergence.R d5ed1d726eb0a126b49358c793d2a6be *tests/testthat/test-check_dag.R 2da2ce2c43031dfe937bd5ba3cee9360 *tests/testthat/test-check_distribution.R 069e5c45d5971f4c4eac47b3611968d5 *tests/testthat/test-check_heterogeneity_bias.R 091d51068e4329bc400b60f55822ae9e *tests/testthat/test-check_heteroskedasticity.R 8fb39b5282281f7b56f24a937a23bfa1 *tests/testthat/test-check_homogeneity.R 7246d7a3a67b106bceea74b414eb96cd *tests/testthat/test-check_itemscale.R 0f0192db35b13b75dc3f81fec1746556 *tests/testthat/test-check_model.R 3c4ebcb5735b7f5f064ff076146ced78 *tests/testthat/test-check_normality.R 12e9fe2752519ef7309a1d27422e58c4 *tests/testthat/test-check_outliers.R a15371c4982e4f2397511e4336eccaa6 *tests/testthat/test-check_overdispersion.R 5011119304a75ed31ffc84d8c2b48f4e *tests/testthat/test-check_predictions.R 1392d042b832596182fb02491404b566 *tests/testthat/test-check_residuals.R 622e48fbd558008a6febab40fe7dc254 *tests/testthat/test-check_singularity.R f5a4c9c082cb07dd37b16deeadf095c9 *tests/testthat/test-check_sphericity.R 9d2d806e9d7436b69cfa6b1651b73e8a *tests/testthat/test-check_zeroinflation.R 72ba257b6313ea6c8d2f7d0b87c712d5 *tests/testthat/test-checks.R 0839e83b1e448bdb9edecd808ea93d7c *tests/testthat/test-compare_performance.R d1196e664ed5271a4dbc4b12d7882564 *tests/testthat/test-coxph.R 993ac4058ecf6e30410c783add29add4 *tests/testthat/test-cronbachs_alpha.R a417a8b3f5967e24c8ead8c5854a0c81 *tests/testthat/test-glmmPQL.R 9dbb4fb51cb3c30b4cf30cb75b1c65a9 *tests/testthat/test-helpers.R ac9bc64af3d843046704e725e275bec0 *tests/testthat/test-icc.R 643e75d61d3989bbd3f8a70ba4eb5086 *tests/testthat/test-item_difficulty.R 9eec2c5c8c17f0243a43c1e30fc4f952 *tests/testthat/test-item_discrimination.R a946e64120f2668e03d3b5ef9a1b5c8a *tests/testthat/test-item_intercor.R 005ac9d2bb4e70a2673aa3dd5efe2954 *tests/testthat/test-item_reliability.R a00a601bde42cbbf059ddf8cd1a45400 *tests/testthat/test-item_splithalf.R e5040b6fb32d7b2ff4b662bd6fc7bf55 *tests/testthat/test-mclogit.R 6f7954b701ca5d0eba73be10d909ae66 *tests/testthat/test-model_performance-various.R f699c703cc80ae6377accdf85d38b0a2 *tests/testthat/test-model_performance.bayesian.R 9d0600c522298797d4c23fa43d89346d *tests/testthat/test-model_performance.gam.R e08cd027c79d379966973b2de26e5d05 *tests/testthat/test-model_performance.kmeans.R 8cd14ee14a0c15e7d24ea02e72892117 *tests/testthat/test-model_performance.lm.R 4d0baf5e8505425455ebf2f4bd4f8327 *tests/testthat/test-model_performance.merMod.R 7c29bcd0792c25e316e25a1b8c265d30 *tests/testthat/test-model_performance.rma.R 97e48e862b4d1d9d7fb224f1f6867e24 *tests/testthat/test-nestedLogit.R e90b21aed29b8d998bbc559ccb55416d *tests/testthat/test-performance_aic.R 48d913f8db209bf6b562d6764e38872d *tests/testthat/test-performance_auc.R df68b7c71e73c9dd3740f2f669d51df7 *tests/testthat/test-performance_cv.R 109bddafe314fd848f78583927adbe4c *tests/testthat/test-performance_roc.R e903a4c2b93c8693534f9411453aa0a4 *tests/testthat/test-pkg-estimatr.R 3fa8d3f0bd30831d70569bbd375174ba *tests/testthat/test-pkg-fixest.R d3a319d4223624b44e4c726b07f69ca4 *tests/testthat/test-pkg-ivreg.R 336ae525d2b6ffdaa3b33c6988a1778d *tests/testthat/test-r2.R b659d59d417a248282416b0994547957 *tests/testthat/test-r2_bayes.R 2dddc26ccd2a4728b72a43f2d014af82 *tests/testthat/test-r2_coxsnell.R d7a36818b08d159fc064d3cfe92a3239 *tests/testthat/test-r2_ferrari.R 2b85deb64059ab82587f5a48e02bd525 *tests/testthat/test-r2_kullback.R f48108a50f0a704e63ab341b209c8445 *tests/testthat/test-r2_mcfadden.R 0043f53c50c7145a54a959c952df6cc2 *tests/testthat/test-r2_mlm.R 6a65c383da6becc4c2ac7cf85a447410 *tests/testthat/test-r2_nagelkerke.R fd04c74e31e96ddf22da83fb1c3e7de8 *tests/testthat/test-r2_nakagawa.R 4e32117bfd50a3da8f4285edc418f8a0 *tests/testthat/test-r2_tjur.R cbcf28b07a7cd10712fd0fac1ed3bb85 *tests/testthat/test-r2_zeroinflated.R 47da624e64886fd4e22671b4dcafd284 *tests/testthat/test-rmse.R 43de587053804a18f350baccbfd729e9 *tests/testthat/test-roc.R 6a338f43e5739c7ebef8c33e0195f684 *tests/testthat/test-test_likelihoodratio.R 518b3ecfca4105f46dd0030ee740e38c *tests/testthat/test-test_performance.R e5c0894f8038582b66d9b25ce2678ffc *tests/testthat/test-test_vuong.R 3f140ce84000c0f16a84fb839973b0b3 *tests/testthat/test-test_wald.R performance/R/0000755000176200001440000000000014741727701012766 5ustar liggesusersperformance/R/format.R0000644000176200001440000000154214335664246014406 0ustar liggesusers#' @export format.compare_performance <- function(x, digits = 2, ...) { # if we have ranking, add score and remove incomplete indices in print if ("Performance_Score" %in% colnames(x)) { x$Performance_Score <- insight::format_value(x$Performance_Score, as_percent = TRUE) x <- x[!sapply(x, anyNA)] } # format weighted ICs weighted_ics <- endsWith(colnames(x), "_wt") if (any(weighted_ics)) { x[weighted_ics] <- lapply(x[weighted_ics], insight::format_bf, name = NULL, exact = TRUE) } if ("BF" %in% colnames(x)) { x$BF[is.na(x$BF)] <- 1 # x$BF <- insight::format_bf(x$BF, exact = TRUE) } insight::format_table(x, digits = digits, ...) } #' @export format.performance_model <- function(x, digits = 2, ...) { # format p-values for meta-analysis insight::format_table(x, digits = digits, ...) } performance/R/check_dag.R0000644000176200001440000005313114741714001014771 0ustar liggesusers#' @title Check correct model adjustment for identifying causal effects #' @name check_dag #' #' @description The purpose of `check_dag()` is to build, check and visualize #' your model based on directed acyclic graphs (DAG). The function checks if a #' model is correctly adjusted for identifying specific relationships of #' variables, especially directed (maybe also "causal") effects for given #' exposures on an outcome. In case of incorrect adjustments, the function #' suggests the minimal required variables that should be adjusted for (sometimes #' also called "controlled for"), i.e. variables that *at least* need to be #' included in the model. Depending on the goal of the analysis, it is still #' possible to add more variables to the model than just the minimally required #' adjustment sets. #' #' `check_dag()` is a convenient wrapper around `ggdag::dagify()`, #' `dagitty::adjustmentSets()` and `dagitty::adjustedNodes()` to check correct #' adjustment sets. It returns a **dagitty** object that can be visualized with #' `plot()`. `as.dag()` is a small convenient function to return the #' dagitty-string, which can be used for the online-tool from the #' dagitty-website. #' #' @param ... One or more formulas, which are converted into **dagitty** syntax. #' First element may also be model object. If a model objects is provided, its #' formula is used as first formula, and all independent variables will be used #' for the `adjusted` argument. See 'Details' and 'Examples'. #' @param outcome Name of the dependent variable (outcome), as character string #' or as formula. Must be a valid name from the formulas provided in `...`. If #' not set, the first dependent variable from the formulas is used. #' @param exposure Name of the exposure variable (as character string or #' formula), for which the direct and total causal effect on the `outcome` #' should be checked. Must be a valid name from the formulas provided in `...`. #' If not set, the first independent variable from the formulas is used. #' @param adjusted A character vector or formula with names of variables that #' are adjusted for in the model, e.g. `adjusted = c("x1", "x2")` or #' `adjusted = ~ x1 + x2`. If a model object is provided in `...`, any values in #' `adjusted` will be overwritten by the model's independent variables. #' @param latent A character vector with names of latent variables in the model. #' @param effect Character string, indicating which effect to check. Can be #' `"all"` (default), `"total"`, or `"direct"`. #' @param coords Coordinates of the variables when plotting the DAG. The #' coordinates can be provided in three different ways: #' #' - a list with two elements, `x` and `y`, which both are named vectors of #' numerics. The names correspond to the variable names in the DAG, and the #' values for `x` and `y` indicate the x/y coordinates in the plot. #' - a list with elements that correspond to the variables in the DAG. Each #' element is a numeric vector of length two with x- and y-coordinate. #' - a data frame with three columns: `x`, `y` and `name` (which contains the #' variable names). #' #' See 'Examples'. #' @param x An object of class `check_dag`, as returned by `check_dag()`. #' #' @section Specifying the DAG formulas: #' #' The formulas have following syntax: #' #' - One-directed paths: On the *left-hand-side* is the name of the variables #' where causal effects point to (direction of the arrows, in dagitty-language). #' On the *right-hand-side* are all variables where causal effects are assumed #' to come from. For example, the formula `Y ~ X1 + X2`, paths directed from #' both `X1` and `X2` to `Y` are assumed. #' #' - Bi-directed paths: Use `~~` to indicate bi-directed paths. For example, #' `Y ~~ X` indicates that the path between `Y` and `X` is bi-directed, and #' the arrow points in both directions. Bi-directed paths often indicate #' unmeasured cause, or unmeasured confounding, of the two involved variables. #' #' @section Minimally required adjustments: #' #' The function checks if the model is correctly adjusted for identifying the #' direct and total effects of the exposure on the outcome. If the model is #' correctly specified, no adjustment is needed to estimate the direct effect. #' If the model is not correctly specified, the function suggests the minimally #' required variables that should be adjusted for. The function distinguishes #' between direct and total effects, and checks if the model is correctly #' adjusted for both. If the model is cyclic, the function stops and suggests #' to remove cycles from the model. #' #' Note that it sometimes could be necessary to try out different combinations #' of suggested adjustments, because `check_dag()` can not always detect whether #' _at least_ one of several variables is required, or whether adjustments should #' be done for _all_ listed variables. It can be useful to copy the dagitty-code #' (using `as.dag()`, which prints the dagitty-string into the console) into #' the dagitty-website and play around with different adjustments. #' #' @section Direct and total effects: #' #' The direct effect of an exposure on an outcome is the effect that is not #' mediated by any other variable in the model. The total effect is the sum of #' the direct and indirect effects. The function checks if the model is correctly #' adjusted for identifying the direct and total effects of the exposure on the #' outcome. #' #' @section Why are DAGs important - the Table 2 fallacy: #' #' Correctly thinking about and identifying the relationships between variables #' is important when it comes to reporting coefficients from regression models #' that mutually adjust for "confounders" or include covariates. Different #' coefficients might have different interpretations, depending on their #' relationship to other variables in the model. Sometimes, a regression #' coefficient represents the direct effect of an exposure on an outcome, but #' sometimes it must be interpreted as total effect, due to the involvement #' of mediating effects. This problem is also called "Table 2 fallacy" #' (_Westreich and Greenland 2013_). DAG helps visualizing and thereby focusing #' the relationships of variables in a regression model to detect missing #' adjustments or over-adjustment. #' #' @return An object of class `check_dag`, which can be visualized with `plot()`. #' The returned object also inherits from class `dagitty` and thus can be used #' with all functions from the **ggdag** and **dagitty** packages. #' #' @references #' - Rohrer, J. M. (2018). Thinking clearly about correlations and causation: #' Graphical causal models for observational data. Advances in Methods and #' Practices in Psychological Science, 1(1), 27–42. \doi{10.1177/2515245917745629} #' #' - Westreich, D., & Greenland, S. (2013). The Table 2 Fallacy: Presenting and #' Interpreting Confounder and Modifier Coefficients. American Journal of #' Epidemiology, 177(4), 292–298. \doi{10.1093/aje/kws412} #' #' @examplesIf all(insight::check_if_installed(c("ggdag", "dagitty", "see"), quietly = TRUE)) #' # no adjustment needed #' check_dag( #' y ~ x + b, #' outcome = "y", #' exposure = "x" #' ) #' #' # incorrect adjustment #' dag <- check_dag( #' y ~ x + b + c, #' x ~ b, #' outcome = "y", #' exposure = "x" #' ) #' dag #' plot(dag) #' #' # After adjusting for `b`, the model is correctly specified #' dag <- check_dag( #' y ~ x + b + c, #' x ~ b, #' outcome = "y", #' exposure = "x", #' adjusted = "b" #' ) #' dag #' #' # using formula interface for arguments "outcome", "exposure" and "adjusted" #' check_dag( #' y ~ x + b + c, #' x ~ b, #' outcome = ~y, #' exposure = ~x, #' adjusted = ~ b + c #' ) #' #' # if not provided, "outcome" is taken from first formula, same for "exposure" #' # thus, we can simplify the above expression to #' check_dag( #' y ~ x + b + c, #' x ~ b, #' adjusted = ~ b + c #' ) #' #' # use specific layout for the DAG #' dag <- check_dag( #' score ~ exp + b + c, #' exp ~ b, #' outcome = "score", #' exposure = "exp", #' coords = list( #' # x-coordinates for all nodes #' x = c(score = 5, exp = 4, b = 3, c = 3), #' # y-coordinates for all nodes #' y = c(score = 3, exp = 3, b = 2, c = 4) #' ) #' ) #' plot(dag) #' #' # alternative way of providing the coordinates #' dag <- check_dag( #' score ~ exp + b + c, #' exp ~ b, #' outcome = "score", #' exposure = "exp", #' coords = list( #' # x/y coordinates for each node #' score = c(5, 3), #' exp = c(4, 3), #' b = c(3, 2), #' c = c(3, 4) #' ) #' ) #' plot(dag) #' #' # Objects returned by `check_dag()` can be used with "ggdag" or "dagitty" #' ggdag::ggdag_status(dag) #' #' # Using a model object to extract information about outcome, #' # exposure and adjusted variables #' data(mtcars) #' m <- lm(mpg ~ wt + gear + disp + cyl, data = mtcars) #' dag <- check_dag( #' m, #' wt ~ disp + cyl, #' wt ~ am #' ) #' dag #' plot(dag) #' @export check_dag <- function(..., outcome = NULL, exposure = NULL, adjusted = NULL, latent = NULL, effect = c("all", "total", "direct"), coords = NULL) { insight::check_if_installed( c("ggdag", "dagitty"), reason = "to check correct adjustments for identifying causal effects." ) effect <- match.arg(effect) # retrieve formulas formulas <- list(...) # check if first object is a model object, and convert to formula if (insight::is_regression_model(formulas[[1]])) { vars <- insight::find_variables( formulas[[1]], effects = "fixed", component = "conditional", flatten = FALSE ) formulas[[1]] <- stats::as.formula( paste(vars$response, "~", paste(vars$conditional, collapse = "+")) ) # if we have a model, we *always* overwrite adjusted if (!is.null(adjusted)) { insight::format_alert("The `adjusted` argument will be overwritten by all independent variables from the model.") # nolint } adjusted <- vars$conditional } # if outcome is not set, use first dependent variable if (is.null(outcome)) { outcome <- insight::find_response(formulas[[1]]) } # if exposure is not set, use first independent variable if (is.null(exposure)) { exposure <- insight::find_variables( formulas[[1]], effects = "fixed", component = "conditional", flatten = FALSE )$conditional[1] } # handle formula interface - if "outcome", "exposure" or "adjusted" are # provided as formulas, convert to character here if (inherits(outcome, "formula")) { outcome <- all.vars(outcome) } if (inherits(exposure, "formula")) { exposure <- all.vars(exposure) } if (inherits(adjusted, "formula")) { adjusted <- all.vars(adjusted) } # process coords-argument coords <- .process_coords(coords) # convert to dag dag_args <- c(formulas, list( exposure = exposure, outcome = outcome, latent = latent, coords = coords )) dag <- do.call(ggdag::dagify, dag_args) # add adjustments if (!is.null(adjusted)) { dag <- .adjust_dag(dag, adjusted) } .finalize_dag(dag, effect, outcome, exposure, adjusted) } # helper ---------------------------------------------------------------------- .finalize_dag <- function(dag, effect, outcome, exposure, adjusted) { # check for cyclic DAG cycles <- unlist(dagitty::findCycle(dag)) # stop if cyclic if (!is.null(cycles)) { insight::format_error(paste0( "Model is cyclic. Causal effects can't be determined for cyclic models. Please remove cycles from the model. To do so, check following variables: ", # nolint datawizard::text_concatenate(unique(cycles)) )) } # data for checking effects checks <- lapply(c("direct", "total"), function(x) { adjustment_set <- unlist(dagitty::adjustmentSets(dag, effect = x), use.names = FALSE) adjustment_nodes <- unlist(dagitty::adjustedNodes(dag), use.names = FALSE) minimal_adjustments <- as.list(dagitty::adjustmentSets(dag, effect = x)) collider <- adjustment_nodes[vapply(adjustment_nodes, ggdag::is_collider, logical(1), .dag = dag, downstream = FALSE)] # nolint if (length(collider)) { # if we *have* colliders, remove them from minimal adjustments minimal_adjustments <- lapply(minimal_adjustments, setdiff, y = collider) } else { # if we don't have colliders, set to NULL collider <- NULL } list( # no adjustment needed when # - required and current adjustment sets are NULL # - AND we have no collider in current adjustments adjustment_not_needed = is.null(adjustment_set) && is.null(adjustment_nodes) && is.null(collider), # incorrect adjustment when # - required is NULL and current adjustment not NULL # - OR we have a collider in current adjustments incorrectly_adjusted = (is.null(adjustment_set) && !is.null(adjustment_nodes)) || (!is.null(collider) && collider %in% adjustment_nodes), # nolint current_adjustments = adjustment_nodes, minimal_adjustments = minimal_adjustments, collider = collider ) }) attr(dag, "effect") <- effect attr(dag, "outcome") <- outcome attr(dag, "exposure") <- exposure attr(dag, "adjusted") <- adjusted attr(dag, "adjustment_sets") <- checks[[1]]$current_adjustments attr(dag, "collider") <- checks[[1]]$collider # remove collider from sub-attributes checks[[1]]$collider <- NULL checks[[2]]$collider <- NULL attr(dag, "check_direct") <- insight::compact_list(checks[[1]]) attr(dag, "check_total") <- insight::compact_list(checks[[2]]) class(dag) <- c(c("check_dag", "see_check_dag"), class(dag)) dag } .adjust_dag <- function(dag, adjusted) { for (i in adjusted) { # first option, we just have the variable name dag <- gsub(paste0("\n", i, "\n"), paste0("\n", i, " [adjusted]\n"), dag, fixed = TRUE) # second option, we have the variable name with a [pos] tag when the user # provided coords dag <- gsub(paste0("\n", i, " [pos="), paste0("\n", i, " [adjusted,pos="), dag, fixed = TRUE) } dag } .process_coords <- function(coords) { # check if the coords are not provided as list with x/y elements, but instead # as list x/y coordinates for each element. This means, "coords" is provided as # # coords <- list( # score = c(5, 3), # exp = c(4, 3), # b = c(3, 2), # c = c(3, 4) # ) # # but we want # # coords = list( # x = c(score = 5, exp = 4, b = 3, c = 3), # y = c(score = 3, exp = 3, b = 2, c = 4) # ) # # we have to check that it's not a data frame and that it is a list - # values like `ggdag::time_ordered_coords()` returns a function, not a list if (!is.null(coords) && !is.data.frame(coords) && is.list(coords) && (length(coords) != 2 || !identical(names(coords), c("x", "y")))) { # nolint # transform list into data frame, split x and y coordinates into columns coords <- datawizard::rownames_as_column( stats::setNames(as.data.frame(do.call(rbind, coords)), c("x", "y")), "name" ) # reorder coords <- coords[c("x", "y", "name")] } coords } # methods -------------------------------------------------------------------- #' @rdname check_dag #' @export as.dag <- function(x, ...) { if (!inherits(x, "check_dag")) { insight::format_error("Input is not of class `check_dag.") } cat(as.character(x)) } #' @export print.check_dag <- function(x, ...) { effect <- attributes(x)$effect collider <- attributes(x)$collider # header cat(insight::print_color("# Check for correct adjustment sets", "blue")) # model specification exposure_outcome_text <- paste0( "\n- Outcome: ", attributes(x)$outcome, "\n- Exposure", ifelse(length(attributes(x)$exposure) > 1, "s", ""), ": ", datawizard::text_concatenate(attributes(x)$exposure) ) # add information on adjustments if (!is.null(attributes(x)$adjustment_sets)) { exposure_outcome_text <- paste0( exposure_outcome_text, "\n- Adjustment", ifelse(length(attributes(x)$adjustment_sets) > 1, "s", ""), ": ", datawizard::text_concatenate(attributes(x)$adjustment_sets) ) } # add information on colliders if (!is.null(collider)) { exposure_outcome_text <- paste0( exposure_outcome_text, "\n- Collider", ifelse(length(collider) > 1, "s", ""), ": ", insight::color_text(datawizard::text_concatenate(collider), "cyan") ) } cat(exposure_outcome_text) cat("\n\n") # minimal adjustment sets for direct and total effect identical? # Then print only once if (identical(attributes(x)$check_direct$minimal_adjustments, attributes(x)$check_total$minimal_adjustments)) { .print_dag_results(attributes(x)$check_direct, x, "direct and total", "all", collider) } else { for (i in c("direct", "total")) { if (i == "direct") { out <- attributes(x)$check_direct } else { out <- attributes(x)$check_total } .print_dag_results(out, x, i, effect, collider) } } } .print_dag_results <- function(out, x, i, effect, collider = NULL) { # missing adjustements - minimal_adjustment can be a list of different # options for minimal adjustements, so we check here if any of the minimal # adjustments are currently sufficient sufficient_adjustments <- vapply(out$minimal_adjustments, function(min_adj) { !is.null(out$current_adjustments) && all(min_adj %in% out$current_adjustments) }, logical(1)) # build message with check results for effects ----------------------- if (isTRUE(out$adjustment_not_needed)) { # Scenario 1: no adjustment needed msg <- paste0( insight::color_text("Model is correctly specified.", "green"), "\nNo adjustment needed to estimate the ", i, " effect of ", datawizard::text_concatenate(attributes(x)$exposure, enclose = "`"), " on `", attributes(x)$outcome, "`." ) } else if (!is.null(collider)) { # Scenario 2: adjusted for collider msg <- paste0( insight::color_text("Incorrectly adjusted!", "red"), "\nYour model adjusts for a potential collider. To estimate the ", i, " effect, do ", insight::color_text("not", "italic"), " adjust for ", insight::color_text(datawizard::text_concatenate(collider, enclose = "`"), "cyan"), " to avoid collider-bias. It is recommended to double-check for the collider-bias on the dagitty-website." ) } else if (isTRUE(out$incorrectly_adjusted)) { # Scenario 3: incorrectly adjusted, adjustments where none is allowed msg <- paste0( insight::color_text("Incorrectly adjusted!", "red"), "\nTo estimate the ", i, " effect, do ", insight::color_text("not", "italic"), " adjust for ", ifelse(length(out$current_adjustments) > 1, "some or all of ", ""), insight::color_text(datawizard::text_concatenate(out$current_adjustments, enclose = "`"), "red"), "." ) } else if (any(sufficient_adjustments)) { # Scenario 4: correct adjustment msg <- paste0( insight::color_text("Model is correctly specified.", "green"), "\nAll minimal sufficient adjustments to estimate the ", i, " effect were done." ) } else { # Scenario 5: missing adjustments msg <- paste0( insight::color_text("Incorrectly adjusted!", "red"), "\nTo estimate the ", i, " effect, ", insight::color_text("at least", "italic"), " adjust for " ) # we may have multiple valid adjustment sets - handle this here if (length(out$minimal_adjustments) > 1) { msg <- paste0( msg, "one of the following sets:\n", insight::color_text( paste( "-", unlist(lapply(out$minimal_adjustments, paste, collapse = ", "), use.names = FALSE), collapse = "\n" ), "yellow" ), "." ) current_str <- "\nCurrently" } else { msg <- paste0( msg, insight::color_text(datawizard::text_concatenate( unlist(out$minimal_adjustments, use.names = FALSE), enclose = "`" ), "yellow"), "." ) current_str <- " Currently" } if (is.null(out$current_adjustments)) { msg <- paste0(msg, current_str, ", the model does not adjust for any variables.") } else { msg <- paste0( msg, current_str, ", the model only adjusts for ", datawizard::text_concatenate(out$current_adjustments, enclose = "`"), "." ) # check if we could identify missing variables, and if so, add them to the message missing_vars <- setdiff(unlist(out$minimal_adjustments), out$current_adjustments) if (length(missing_vars) > 0) { msg <- paste0( msg, " You possibly also need to adjust for ", insight::color_text(datawizard::text_concatenate(missing_vars, enclose = "`"), "green"), " to block biasing paths." ) } } } if (effect %in% c("all", i)) { cat(insight::print_color(insight::format_message( paste0("Identification of ", i, " effects\n\n") ), "blue")) cat(msg) cat("\n\n") } } #' @export plot.check_dag <- function(x, ...) { insight::check_if_installed("see", "to plot DAG") NextMethod() } performance/R/skewness_kurtosis.R0000644000176200001440000000166214257537777016741 0ustar liggesusers.skewness <- function(x) { if (is.matrix(x)) { apply(x, 2, .skewness_numeric) } else if (is.vector(x)) { .skewness_numeric(x) } else if (is.data.frame(x)) { sapply(x, .skewness_numeric) } else { .skewness_numeric(as.vector(x)) } } .skewness_numeric <- function(x) { x <- x[!is.na(x)] n <- length(x) (sum((x - mean(x))^3) / n) / (sum((x - mean(x))^2) / n)^(3 / 2) } .kurtosis <- function(x) { if (is.matrix(x)) { apply(x, 2, .kurtosis_numeric) } else if (is.vector(x)) { .kurtosis_numeric(x) } else if (is.data.frame(x)) { sapply(x, .kurtosis_numeric) } else { .kurtosis_numeric(as.vector(x)) } } .kurtosis_numeric <- function(x) { x <- x[!is.na(x)] n <- length(x) n * sum((x - mean(x))^4) / (sum((x - mean(x))^2)^2) } .normalize <- function(x) { as.vector((x - min(x, na.rm = TRUE)) / diff(range(x, na.rm = TRUE), na.rm = TRUE)) } performance/R/cronbachs_alpha.R0000644000176200001440000000571514736731423016230 0ustar liggesusers#' @title Cronbach's Alpha for Items or Scales #' @name cronbachs_alpha #' #' @description Compute various measures of internal consistencies #' for tests or item-scales of questionnaires. #' #' @param x A matrix or a data frame. #' @param ... Currently not used. #' #' @return The Cronbach's Alpha value for `x`. #' #' @details The Cronbach's Alpha value for `x`. A value closer to 1 #' indicates greater internal consistency, where usually following #' rule of thumb is applied to interpret the results: #' \ifelse{html}{\out{α}}{\eqn{\alpha}{alpha}} < 0.5 is unacceptable, #' 0.5 < \ifelse{html}{\out{α}}{\eqn{\alpha}{alpha}} < 0.6 is poor, #' 0.6 < \ifelse{html}{\out{α}}{\eqn{\alpha}{alpha}} < 0.7 is questionable, #' 0.7 < \ifelse{html}{\out{α}}{\eqn{\alpha}{alpha}} < 0.8 is acceptable, #' and everything > 0.8 is good or excellent. #' #' @references Bland, J. M., and Altman, D. G. Statistics notes: Cronbach's #' alpha. BMJ 1997;314:572. 10.1136/bmj.314.7080.572 #' #' @examples #' data(mtcars) #' x <- mtcars[, c("cyl", "gear", "carb", "hp")] #' cronbachs_alpha(x) #' @export cronbachs_alpha <- function(x, ...) { UseMethod("cronbachs_alpha") } #' @export cronbachs_alpha.data.frame <- function(x, verbose = TRUE, ...) { # remove missings .data <- stats::na.omit(x) # we need at least two columns for Cronach's Alpha if (is.null(ncol(.data)) || ncol(.data) < 2) { if (verbose) { insight::format_alert("Too few columns in `x` to compute Cronbach's Alpha.") } return(NULL) } # Compute Cronbach's Alpha dim(.data)[2] / (dim(.data)[2] - 1) * (1 - sum(apply(.data, 2, stats::var)) / stats::var(rowSums(.data))) } #' @export cronbachs_alpha.matrix <- function(x, verbose = TRUE, ...) { cronbachs_alpha(as.data.frame(x), verbose = verbose, ...) } #' @export cronbachs_alpha.parameters_pca <- function(x, verbose = TRUE, ...) { # fetch data used for the PCA pca_data <- attributes(x)$dataset # if NULL, can we get from environment? if (is.null(pca_data)) { pca_data <- attr(x, "data") if (is.null(pca_data)) { if (verbose) { insight::format_alert("Could not find data frame that was used for the PCA.") } return(NULL) } pca_data <- get(pca_data, envir = parent.frame()) } # get assignment of columns to extracted components, based on the max loading factor_assignment <- attributes(x)$closest_component # sort and get unique IDs so we only get data from relevant columns unique_factors <- sort(unique(factor_assignment)) # apply cronbach's alpha for each component, # only for variables with max loading cronb <- sapply(unique_factors, function(i) { cronbachs_alpha( pca_data[, as.vector(x$Variable[factor_assignment == i]), drop = FALSE], verbose = verbose, ... ) }) names(cronb) <- paste0("PC", unique_factors) unlist(cronb) } performance/R/get_gradients.R0000644000176200001440000000423714335664246015741 0ustar liggesusers# Tests # data(iris) # iris$w <- rnorm(nrow(iris), 1, .3) # x <- lm(Sepal.Length ~ Species * Sepal.Width, data=iris) # all(sandwich::estfun(x) == .get_gradients(x)) # x <- lm(Sepal.Length ~ Species * Sepal.Width + Petal.Length * Petal.Width, weights = w, data=iris) # all(sandwich::estfun(x) == .get_gradients(x)) # x <- glm(vs ~ mpg, data=mtcars, weights = wt) # all(sandwich::estfun(x) == .get_gradients(x)) .get_gradients <- function(x, ...) { UseMethod(".get_gradients") } .get_gradients.default <- function(x, ...) { insight::check_if_installed("sandwich") tryCatch( { sandwich::estfun(x, ...) }, error = function(e) { insight::format_error( paste0("Could not compute gradients from a model object of class `", class(x)[1], "`."), "Please try a different test-function, or file an issue at {.url https://github.com/easystats/performance/issues}." ) } ) } .get_gradients.lmerMod <- function(x, ...) { insight::get_residuals(x) * insight::get_weights(x, null_as_ones = TRUE) * insight::get_modelmatrix(x) } .get_gradients.glmerMod <- function(x, ...) { w <- as.vector(insight::get_residuals(x, "working")) * insight::get_weights(x, "working") w * insight::get_modelmatrix(x) / insight::get_auxiliary(x, type = "dispersion") } .get_gradients.glmmTMB <- function(x, ...) { if (insight::model_info(x)$is_linear) { insight::get_residuals(x) * insight::get_weights(x, null_as_ones = TRUE) * insight::get_modelmatrix(x) } else { w <- as.vector(insight::get_residuals(x)) * insight::get_weights(x, null_as_ones = TRUE) w * insight::get_modelmatrix(x) / insight::get_auxiliary(x, type = "dispersion") } } # .get_gradients.lm <- .get_gradients.lmer # # .get_gradients.glm <- function(x, ...) { # w <- as.vector(residuals(x, "working")) * weights(x, "working") # if (substr(x$family$family, 1, 17) %in% c("poisson", "binomial", "Negative Binomial")) { # dispersion <- 1 # } else{ # dispersion <- sum(w^2, na.rm = TRUE)/sum(weights(x, "working"), na.rm = TRUE) # } # rez <- w * insight::get_modelmatrix(x) / dispersion # rez # } # performance/R/r2_mcfadden.R0000644000176200001440000001163114736731423015257 0ustar liggesusers#' @title McFadden's R2 #' @name r2_mcfadden #' #' @description Calculates McFadden's pseudo R2. #' #' @param model Generalized linear or multinomial logit (`mlogit`) model. #' @param ... Currently not used. #' #' @return For most models, a list with McFadden's R2 and adjusted McFadden's #' R2 value. For some models, only McFadden's R2 is available. #' #' @references #' - McFadden, D. (1987). Regression-based specification tests for the #' multinomial logit model. Journal of econometrics, 34(1-2), 63-82. #' - McFadden, D. (1973). Conditional logit analysis of qualitative choice #' behavior. #' #' @examples #' if (require("mlogit")) { #' data("Fishing", package = "mlogit") #' Fish <- mlogit.data(Fishing, varying = c(2:9), shape = "wide", choice = "mode") #' #' model <- mlogit(mode ~ price + catch, data = Fish) #' r2_mcfadden(model) #' } #' @export r2_mcfadden <- function(model, ...) { UseMethod("r2_mcfadden") } # helper ----------------------- .r2_mcfadden <- function(model, l_null) { l_full <- insight::get_loglikelihood(model) k <- length(insight::find_parameters(model)) mcfadden <- 1 - (as.vector(l_full) / as.vector(l_null)) mcfadden_adjusted <- 1 - ((as.vector(l_full) - k) / as.vector(l_null)) out <- list( R2 = c(`McFadden's R2` = mcfadden), R2_adjusted = c(`adjusted McFadden's R2` = mcfadden_adjusted) ) attr(out, "model_type") <- "Generalized Linear" structure(class = "r2_generic", out) } # r2 via loglik and update -------------------------- #' @export r2_mcfadden.glm <- function(model, verbose = TRUE, ...) { info <- list(...)$model_info if (is.null(info)) { info <- suppressWarnings(insight::model_info(model, verbose = FALSE)) } matrix_response <- grepl("cbind", insight::find_response(model), fixed = TRUE) if (info$is_binomial && !info$is_betabinomial && !info$is_bernoulli && class(model)[1] %in% c("glm", "glmmTMB")) { if (verbose) { insight::format_warning("Can't calculate accurate R2 for binomial models that are not Bernoulli models.") } return(NULL) } # currently, beta-binomial models without proportion response are not supported if (info$is_betabinomial && matrix_response) { if (verbose) { insight::format_warning("Can't calculate accurate R2 for beta-binomial models with matrix-response formulation.") } return(NULL) } l_null <- insight::get_loglikelihood(stats::update(model, ~1)) .r2_mcfadden(model, l_null) } #' @export r2_mcfadden.clm <- r2_mcfadden.glm #' @export r2_mcfadden.serp <- r2_mcfadden.glm #' @export r2_mcfadden.cpglm <- r2_mcfadden.glm #' @export r2_mcfadden.glmx <- r2_mcfadden.glm #' @export r2_mcfadden.polr <- r2_mcfadden.glm #' @export r2_mcfadden.bracl <- r2_mcfadden.glm #' @export r2_mcfadden.brmultinom <- r2_mcfadden.glm #' @export r2_mcfadden.censReg <- r2_mcfadden.glm #' @export r2_mcfadden.glmmTMB <- r2_mcfadden.glm #' @export r2_mcfadden.truncreg <- r2_mcfadden.glm #' @export r2_mcfadden.mclogit <- function(model, ...) { insight::check_if_installed("mclogit", reason = "to calculate R2") s <- mclogit::getSummary.mclogit(model) r2_mcfadden <- s$sumstat["McFadden"] names(r2_mcfadden) <- "McFadden's R2" r2_mcfadden } #' @export r2_mcfadden.mblogit <- function(model, ...) { insight::check_if_installed("mclogit", reason = "to calculate R2") s <- mclogit::getSummary.mblogit(model) r2_mcfadden <- s$sumstat["McFadden"] names(r2_mcfadden) <- "McFadden's R2" r2_mcfadden } # mfx models --------------------- #' @export r2_mcfadden.logitmfx <- function(model, ...) { r2_mcfadden(model$fit, ...) } #' @export r2_mcfadden.logitor <- r2_mcfadden.logitmfx #' @export r2_mcfadden.poissonirr <- r2_mcfadden.logitmfx #' @export r2_mcfadden.poissonmfx <- r2_mcfadden.logitmfx #' @export r2_mcfadden.negbinirr <- r2_mcfadden.logitmfx #' @export r2_mcfadden.probitmfx <- r2_mcfadden.logitmfx #' @export r2_mcfadden.negbinmfx <- r2_mcfadden.logitmfx # special models ------------------------------------------- #' @export r2_mcfadden.vglm <- function(model, ...) { if (!(is.null(model@call$summ) && !identical(model@call$summ, 0))) { insight::format_error("Can't get log-likelihood when `summ` is not zero.") } l_null <- insight::get_loglikelihood(stats::update(model, ~1)) .r2_mcfadden(model, l_null) } #' @export r2_mcfadden.clm2 <- function(model, ...) { l_null <- insight::get_loglikelihood(stats::update(model, location = ~1, scale = ~1)) .r2_mcfadden(model, l_null) } #' @export r2_mcfadden.multinom <- function(model, ...) { l_null <- insight::get_loglikelihood(stats::update(model, ~1, trace = FALSE)) .r2_mcfadden(model, l_null) } #' @export r2_mcfadden.mlogit <- function(model, ...) { R2 <- as.vector(summary(model)$mfR2) names(R2) <- "McFadden's R2" R2 } performance/R/model_performance.lavaan.R0000644000176200001440000001622314736731423020037 0ustar liggesusers#' Performance of lavaan SEM / CFA Models #' #' Compute indices of model performance for SEM or CFA models from the #' **lavaan** package. #' #' @param model A **lavaan** model. #' @param metrics Can be `"all"` or a character vector of metrics to be #' computed (some of `"Chi2"`, `"Chi2_df"`, `"p_Chi2"`, `"Baseline"`, #' `"Baseline_df"`, `"p_Baseline"`, `"GFI"`, `"AGFI"`, `"NFI"`, `"NNFI"`, #' `"CFI"`, `"RMSEA"`, `"RMSEA_CI_low"`, `"RMSEA_CI_high"`, `"p_RMSEA"`, #' `"RMR"`, `"SRMR"`, `"RFI"`, `"PNFI"`, `"IFI"`, `"RNI"`, `"Loglikelihood"`, #' `"AIC"`, `"BIC"`, and `"BIC_adjusted"`. #' @param verbose Toggle off warnings. #' @param ... Arguments passed to or from other methods. #' #' @return A data frame (with one row) and one column per "index" (see #' `metrics`). #' #' @details \subsection{Indices of fit}{ #' #' - **Chisq**: The model Chi-squared assesses overall fit and the #' discrepancy between the sample and fitted covariance matrices. Its p-value #' should be > .05 (i.e., the hypothesis of a perfect fit cannot be #' rejected). However, it is quite sensitive to sample size. #' #' - **GFI/AGFI**: The (Adjusted) Goodness of Fit is the proportion #' of variance accounted for by the estimated population covariance. #' Analogous to R2. The GFI and the AGFI should be > .95 and > .90, #' respectively. #' #' - **NFI/NNFI/TLI**: The (Non) Normed Fit Index. An NFI of 0.95, #' indicates the model of interest improves the fit by 95\% relative to the #' null model. The NNFI (also called the Tucker Lewis index; TLI) is #' preferable for smaller samples. They should be > .90 (Byrne, 1994) or > #' .95 (Schumacker and Lomax, 2004). #' #' - **CFI**: The Comparative Fit Index is a revised form of NFI. #' Not very sensitive to sample size (Fan, Thompson, and Wang, 1999). Compares #' the fit of a target model to the fit of an independent, or null, model. It #' should be > .90. #' #' - **RMSEA**: The Root Mean Square Error of Approximation is a #' parsimony-adjusted index. Values closer to 0 represent a good fit. It #' should be < .08 or < .05. The p-value printed with it tests the hypothesis #' that RMSEA is less than or equal to .05 (a cutoff sometimes used for good #' fit), and thus should be not significant. #' #' - **RMR/SRMR**: the (Standardized) Root Mean Square Residual #' represents the square-root of the difference between the residuals of the #' sample covariance matrix and the hypothesized model. As the RMR can be #' sometimes hard to interpret, better to use SRMR. Should be < .08. #' #' - **RFI**: the Relative Fit Index, also known as RHO1, is not #' guaranteed to vary from 0 to 1. However, RFI close to 1 indicates a good #' fit. #' #' - **IFI**: the Incremental Fit Index (IFI) adjusts the Normed Fit #' Index (NFI) for sample size and degrees of freedom (Bollen's, 1989). Over #' 0.90 is a good fit, but the index can exceed 1. #' #' - **PNFI**: the Parsimony-Adjusted Measures Index. There is no #' commonly agreed-upon cutoff value for an acceptable model for this index. #' Should be > 0.50. } #' #' See the documentation for `?lavaan::fitmeasures`. #' #' \subsection{What to report}{ #' Kline (2015) suggests that at a minimum the following indices should be #' reported: The model **chi-square**, the **RMSEA**, the **CFI** #' and the **SRMR**. #' } #' #' @examplesIf require("lavaan") #' # Confirmatory Factor Analysis (CFA) --------- #' data(HolzingerSwineford1939, package = "lavaan") #' structure <- " visual =~ x1 + x2 + x3 #' textual =~ x4 + x5 + x6 #' speed =~ x7 + x8 + x9 " #' model <- lavaan::cfa(structure, data = HolzingerSwineford1939) #' model_performance(model) #' #' @references #' #' - Byrne, B. M. (1994). Structural equation modeling with EQS and #' EQS/Windows. Thousand Oaks, CA: Sage Publications. #' #' - Tucker, L. R., and Lewis, C. (1973). The reliability coefficient for #' maximum likelihood factor analysis. Psychometrika, 38, 1-10. #' #' - Schumacker, R. E., and Lomax, R. G. (2004). A beginner's guide to #' structural equation modeling, Second edition. Mahwah, NJ: Lawrence Erlbaum #' Associates. #' #' - Fan, X., B. Thompson, and L. Wang (1999). Effects of sample size, #' estimation method, and model specification on structural equation modeling #' fit indexes. Structural Equation Modeling, 6, 56-83. #' #' - Kline, R. B. (2015). Principles and practice of structural equation #' modeling. Guilford publications. #' #' @export model_performance.lavaan <- function(model, metrics = "all", verbose = TRUE, ...) { insight::check_if_installed("lavaan") if (isTRUE(verbose)) { measures <- as.data.frame(t(as.data.frame(lavaan::fitmeasures(model, ...)))) } else { measures <- as.data.frame(t(as.data.frame(suppressWarnings(lavaan::fitmeasures(model, ...))))) } row.names(measures) <- NULL out <- data.frame( Chi2 = measures$chisq, Chi2_df = measures$df, p_Chi2 = measures$pvalue, Baseline = measures$baseline.chisq, Baseline_df = measures$baseline.df, p_Baseline = measures$baseline.pvalue, GFI = measures$gfi, AGFI = measures$agfi, NFI = measures$nfi, NNFI = measures$tli, CFI = measures$cfi, RMSEA = measures$rmsea, RMSEA_CI_low = measures$rmsea.ci.lower, RMSEA_CI_high = measures$rmsea.ci.upper, p_RMSEA = measures$rmsea.pvalue, RMR = measures$rmr, SRMR = measures$srmr, RFI = measures$rfi, PNFI = measures$pnfi, IFI = measures$ifi, RNI = measures$rni, Loglikelihood = measures$logl, AIC = measures$aic, BIC = measures$bic, BIC_adjusted = measures$bic2 ) if (all(metrics == "all")) { metrics <- names(out) } out <- out[, metrics] class(out) <- c("performance_lavaan", "performance_model", class(out)) out } #' @export model_performance.blavaan <- function(model, metrics = "all", verbose = TRUE, ...) { insight::check_if_installed(c("lavaan", "blavaan")) if (isTRUE(verbose)) { measures <- as.data.frame(t(as.data.frame(lavaan::fitmeasures(model, ...)))) fitind <- summary(blavaan::blavFitIndices(model)) } else { measures <- as.data.frame(t(as.data.frame(suppressWarnings(lavaan::fitmeasures(model, ...))))) fitind <- suppressWarnings(summary(blavaan::blavFitIndices(model))) } row.names(measures) <- NULL out <- data.frame( BRMSEA = fitind[1, "EAP"], SD_BRMSEA = fitind[1, "SD"], BGammaHat = fitind[2, "EAP"], SD_BGammaHat = fitind[2, "SD"], Adj_BGammaHat = fitind[3, "EAP"], SD_Adj_BGammaHat = fitind[3, "SD"], Loglikelihood = measures$logl, BIC = measures$bic, DIC = measures$dic, p_DIC = measures$p_dic, WAIC = measures$waic, SE_WAIC = measures$se_waic, p_WAIC = measures$p_waic, LOOIC = measures$looic, SE_LOOIC = measures$se_loo, p_LOOIC = measures$p_loo ) if (all(metrics == "all")) { metrics <- names(out) } out <- out[, metrics] class(out) <- c("performance_lavaan", "performance_model", class(out)) out } performance/R/test_likelihoodratio.R0000644000176200001440000001421314736731423017333 0ustar liggesusers#' @rdname test_performance #' @param estimator Applied when comparing regression models using #' `test_likelihoodratio()`. Corresponds to the different estimators for #' the standard deviation of the errors. Defaults to `"OLS"` for linear models, #' `"ML"` for all other models (including mixed models), or `"REML"` for #' linear mixed models when these have the same fixed effects. See 'Details'. #' @export test_likelihoodratio <- function(..., estimator = "ML", verbose = TRUE) { UseMethod("test_likelihoodratio") } # Short name for test_likelihoodratio using the test_* naming convention #' @rdname test_performance #' @export test_lrt <- test_likelihoodratio # default -------------------- #' @export test_likelihoodratio.default <- function(..., estimator = "OLS", verbose = TRUE) { # Attribute class to list my_objects <- insight::ellipsis_info(..., only_models = TRUE) # validation checks (will throw error if non-valid objects) my_objects <- .test_performance_checks(my_objects, verbose = verbose) # different default when mixed model or glm is included if (missing(estimator)) { mixed_models <- sapply(my_objects, insight::is_mixed_model) if (all(mixed_models) && all(sapply(my_objects, .is_lmer_reml)) && isTRUE(attributes(my_objects)$same_fixef)) { estimator <- "REML" } else if (any(mixed_models) || !all(attributes(my_objects)$is_linear)) { estimator <- "ML" } } # ensure proper object names my_objects <- .check_objectnames(my_objects, sapply(match.call(expand.dots = FALSE)[["..."]], as.character)) # If a suitable class is found, run the more specific method on it if (inherits(my_objects, "ListNestedRegressions")) { test_likelihoodratio(my_objects, estimator = estimator) } else if (inherits(my_objects, "ListLavaan")) { test_likelihoodratio_ListLavaan(..., objects = my_objects) # Because lavaanLRT requires the ellipsis } else { insight::format_error( "The models are not nested, which is a prerequisite for `test_likelihoodratio()`.", "See the 'Details' section.", "You may try `test_vuong()` instead." ) } } # methods ------------------------------ #' @export plot.test_likelihoodratio <- function(x, ...) { insight::format_alert( "There is currently no `plot()` method for test-functions.", "Please use `plot(compare_perfomance())` for some visual representations of your model comparisons." ) } #' @export print.test_likelihoodratio <- function(x, digits = 2, ...) { # Footer if ("LogLik" %in% names(x)) { best <- which.max(x$LogLik) footer <- c(sprintf("\nModel '%s' seems to have the best model fit.\n", x$Model[best]), "yellow") } else { footer <- NULL } # value formatting x$p <- insight::format_p(x$p, name = NULL) if (is.null(attributes(x)$estimator)) { estimator_string <- "" } else { estimator_string <- sprintf(" (%s-estimator)", toupper(attributes(x)$estimator)) } cat(insight::export_table( x, digits = digits, caption = c(paste0("# Likelihood-Ratio-Test (LRT) for Model Comparison", estimator_string), "blue"), footer = footer )) invisible(x) } # other classes --------------------------- #' @export test_likelihoodratio.ListNestedRegressions <- function(objects, estimator = "ML", verbose = TRUE, ...) { dfs <- sapply(objects, insight::get_df, type = "model") same_fixef <- attributes(objects)$same_fixef # sort by df if (is.unsorted(dfs) && is.unsorted(rev(dfs))) { objects <- objects[order(dfs)] dfs <- sort(dfs, na.last = TRUE) } dfs_diff <- c(NA, diff(dfs)) REML <- tolower(estimator) == "reml" # default anova(test="LRT") if (tolower(estimator) == "ols") { out <- .test_wald(objects, test = "LRT") out$df <- dfs # Replace residual df with model's df } else { # lmtest::lrtest() lls <- sapply(objects, insight::get_loglikelihood, REML = REML, check_response = TRUE) chi2 <- abs(c(NA, -2 * diff(lls))) p <- stats::pchisq(chi2, abs(dfs_diff), lower.tail = FALSE) out <- data.frame( df = dfs, df_diff = dfs_diff, Chi2 = chi2, p = p, stringsAsFactors = FALSE ) out <- cbind(.test_performance_init(objects), out) } # for REML fits, warn user if (isTRUE(REML) && # only when mixed models are involved, others probably don't have problems with REML fit any(sapply(objects, insight::is_mixed_model)) && # only if not all models have same fixed effects (else, REML is ok) !isTRUE(same_fixef) && isTRUE(verbose)) { insight::format_warning( "The Likelihood-Ratio-Test is probably inaccurate when comparing REML-fit models with different fixed effects." ) } attr(out, "is_nested_increasing") <- attributes(objects)$is_nested_increasing attr(out, "is_nested_decreasing") <- attributes(objects)$is_nested_decreasing attr(out, "estimator") <- tolower(estimator) class(out) <- c("test_likelihoodratio", "see_test_likelihoodratio", "data.frame") out } test_likelihoodratio_ListLavaan <- function(..., objects = NULL) { insight::check_if_installed("lavaan") # Create data frame with info about model name and class names_types <- data.frame( Model = names(objects), Type = sapply(objects, function(x) class(x)[1]), stringsAsFactors = FALSE ) out <- as.data.frame( lavaan::lavTestLRT(..., test = "LRT", model.names = names(objects)), stringsAsFactors = FALSE ) # Rename columns colnames(out)[names(out) == "Df"] <- "df" colnames(out)[names(out) == "Df diff"] <- "df_diff" colnames(out)[names(out) == "Chisq"] <- "Chi2" colnames(out)[startsWith(names(out), "Pr(>")] <- "p" out$Model <- row.names(out) # Bind all data out <- merge(names_types, out[c("Model", "df", "df_diff", "Chi2", "p")], by = "Model") class(out) <- c("test_likelihoodratio", "see_test_likelihoodratio", "data.frame") out } # helper ---------------------- .is_lmer_reml <- function(x) { tryCatch(inherits(x, "lmerMod") && as.logical(x@devcomp$dims[["REML"]]), error = function(e) FALSE ) } performance/R/model_performance.R0000644000176200001440000000431014736731423016570 0ustar liggesusers#' @title Model Performance #' @name model_performance #' #' @description See the documentation for your object's class: #' #' - [Frequentist Regressions][model_performance.lm] #' - [Instrumental Variables Regressions][model_performance.ivreg] #' - [Mixed models][model_performance.merMod] #' - [Bayesian models][model_performance.stanreg] #' - [CFA / SEM lavaan models][model_performance.lavaan] #' - [Meta-analysis models][model_performance.rma] #' #' @seealso [`compare_performance()`][compare_performance] to compare performance of many different models. #' #' @param model Statistical model. #' @param ... Arguments passed to or from other methods, resp. for #' `compare_performance()`, one or multiple model objects (also of #' different classes). #' #' @return A data frame (with one row) and one column per "index" (see `metrics`). #' #' @details `model_performance()` correctly detects transformed response and #' returns the "corrected" AIC and BIC value on the original scale. To get back #' to the original scale, the likelihood of the model is multiplied by the #' Jacobian/derivative of the transformation. #' #' @examples #' model <- lm(mpg ~ wt + cyl, data = mtcars) #' model_performance(model) #' #' model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") #' model_performance(model) #' @export model_performance <- function(model, ...) { UseMethod("model_performance") } #' @rdname model_performance #' @export performance <- model_performance # methods -------------------------------- #' @export print.performance_model <- function(x, digits = 3, layout = "horizontal", ...) { layout <- match.arg(layout, choices = c("horizontal", "vertical")) formatted_table <- format(x = x, digits = digits, format = "text", ...) # switch to vertical layout if (layout == "vertical") { formatted_table <- datawizard::rownames_as_column(as.data.frame(t(formatted_table)), "Metric") colnames(formatted_table)[2] <- "Value" } cat( insight::export_table( x = formatted_table, digits = digits, format = "text", caption = c("# Indices of model performance", "blue"), ... ) ) invisible(x) } performance/R/check_heterogeneity_bias.R0000644000176200001440000001047414736731423020125 0ustar liggesusers#' Check model predictor for heterogeneity bias #' #' `check_heterogeneity_bias()` checks if model predictors or variables may #' cause a heterogeneity bias, i.e. if variables have a within- and/or #' between-effect (_Bell and Jones, 2015_). #' #' @param x A data frame or a mixed model object. #' @param select Character vector (or formula) with names of variables to select #' that should be checked. If `x` is a mixed model object, this argument #' will be ignored. #' @param by Character vector (or formula) with the name of the variable that #' indicates the group- or cluster-ID. For cross-classified or nested designs, #' `by` can also identify two or more variables as group- or cluster-IDs. If #' the data is nested and should be treated as such, set `nested = TRUE`. Else, #' if `by` defines two or more variables and `nested = FALSE`, a cross-classified #' design is assumed. If `x` is a model object, this argument will be ignored. #' #' For nested designs, `by` can be: #' - a character vector with the name of the variable that indicates the #' levels, ordered from *highest* level to *lowest* (e.g. #' `by = c("L4", "L3", "L2")`. #' - a character vector with variable names in the format `by = "L4/L3/L2"`, #' where the levels are separated by `/`. #' #' See also section _De-meaning for cross-classified designs_ and #' _De-meaning for nested designs_ below. #' @param nested Logical, if `TRUE`, the data is treated as nested. If `FALSE`, #' the data is treated as cross-classified. Only applies if `by` contains more #' than one variable. #' #' @seealso #' For further details, read the vignette #' and also #' see documentation for [`datawizard::demean()`]. #' #' @references #' - Bell A, Jones K. 2015. Explaining Fixed Effects: Random Effects #' Modeling of Time-Series Cross-Sectional and Panel Data. Political Science #' Research and Methods, 3(1), 133–153. #' #' @examples #' data(iris) #' iris$ID <- sample(1:4, nrow(iris), replace = TRUE) # fake-ID #' check_heterogeneity_bias(iris, select = c("Sepal.Length", "Petal.Length"), by = "ID") #' @export check_heterogeneity_bias <- function(x, select = NULL, by = NULL, nested = FALSE) { insight::check_if_installed("datawizard", minimum_version = "0.12.0") if (insight::is_model(x)) { by <- insight::find_random(x, split_nested = TRUE, flatten = TRUE) if (is.null(by)) { insight::format_error("Model is no mixed model. Please provide a mixed model, or a data frame and arguments `select` and `by`.") # nolint } my_data <- insight::get_data(x, source = "mf", verbose = FALSE) select <- insight::find_predictors(x, effects = "fixed", component = "conditional", flatten = TRUE) } else { if (inherits(select, "formula")) { select <- all.vars(select) } if (inherits(by, "formula")) { by <- all.vars(by) } my_data <- x } # for nested designs? if (nested) { # separate level-indicators with "/", as supported by datawizard by <- paste(by, collapse = "/") } # create all combinations that should be checked combinations <- expand.grid(select, by[1]) result <- Map(function(predictor, id) { # demean predictor d <- datawizard::demean(my_data, select = predictor, by = id, verbose = FALSE) # get new names within_name <- paste0(predictor, "_within") # check if any within-variable differs from zero. if yes, we have # a within-subject effect if (any(abs(d[[within_name]]) > 1e-5)) { predictor } else { NULL } }, as.character(combinations[[1]]), by) out <- unlist(insight::compact_list(result), use.names = FALSE) if (is.null(out)) { message("No predictor found that could cause heterogeneity bias.") return(invisible(NULL)) } class(out) <- c("check_heterogeneity_bias", class(out)) out } #' @export print.check_heterogeneity_bias <- function(x, ...) { cat("Possible heterogeneity bias due to following predictors: ") insight::print_color(toString(x), "red") cat("\n") invisible(x) } #' @keywords internal .n_unique <- function(x, na.rm = TRUE) { if (is.null(x)) { return(0) } if (isTRUE(na.rm)) x <- x[!is.na(x)] length(unique(x)) } performance/R/check_factorstructure.R0000644000176200001440000001753214736731423017515 0ustar liggesusers#' Check suitability of data for Factor Analysis (FA) with Bartlett's Test of Sphericity and KMO #' #' This checks whether the data is appropriate for Factor Analysis (FA) by #' running the Bartlett's Test of Sphericity and the Kaiser, Meyer, Olkin (KMO) #' Measure of Sampling Adequacy (MSA). See **details** below for more information #' about the interpretation and meaning of each test. #' #' #' @details #' ### Bartlett's Test of Sphericity #' #' Bartlett's (1951) test of sphericity tests whether a matrix (of correlations) #' is significantly different from an identity matrix (filled with 0). It tests #' whether the correlation coefficients are all 0. The test computes the #' probability that the correlation matrix has significant correlations among at #' least some of the variables in a dataset, a prerequisite for factor analysis #' to work. #' #' While it is often suggested to check whether Bartlett’s test of sphericity is #' significant before starting with factor analysis, one needs to remember that #' the test is testing a pretty extreme scenario (that all correlations are non-significant). #' As the sample size increases, this test tends to be always significant, which #' makes it not particularly useful or informative in well-powered studies. #' #' ### Kaiser, Meyer, Olkin (KMO) #' #' *(Measure of Sampling Adequacy (MSA) for Factor Analysis.)* #' #' Kaiser (1970) introduced a Measure of Sampling Adequacy (MSA), later modified #' by Kaiser and Rice (1974). The Kaiser-Meyer-Olkin (KMO) statistic, which can #' vary from 0 to 1, indicates the degree to which each variable in a set is #' predicted without error by the other variables. #' #' A value of 0 indicates that the sum of partial correlations is large relative #' to the sum correlations, indicating factor analysis is likely to be #' inappropriate. A KMO value close to 1 indicates that the sum of partial #' correlations is not large relative to the sum of correlations and so factor #' analysis should yield distinct and reliable factors. It means that patterns #' of correlations are relatively compact, and so factor analysis should yield #' distinct and reliable factors. Values smaller than 0.5 suggest that you should #' either collect more data or rethink which variables to include. #' #' Kaiser (1974) suggested that KMO > .9 were marvelous, in the .80s, #' meritorious, in the .70s, middling, in the .60s, mediocre, in the .50s, #' miserable, and less than .5, unacceptable. Hair et al. (2006) suggest #' accepting a value > 0.5. Values between 0.5 and 0.7 are mediocre, and values #' between 0.7 and 0.8 are good. #' #' Variables with individual KMO values below 0.5 could be considered for #' exclusion them from the analysis (note that you would need to re-compute the #' KMO indices as they are dependent on the whole dataset). #' #' @param x A data frame or a correlation matrix. If the latter is passed, `n` #' must be provided. #' @param n If a correlation matrix was passed, the number of observations must #' be specified. #' @param ... Arguments passed to or from other methods. #' #' #' @examples #' library(performance) #' #' check_factorstructure(mtcars) #' #' # One can also pass a correlation matrix #' r <- cor(mtcars) #' check_factorstructure(r, n = nrow(mtcars)) #' #' @return A list of lists of indices related to sphericity and KMO. #' @seealso [`check_clusterstructure()`]. #' #' @references #' This function is a wrapper around the `KMO` and the `cortest.bartlett()` #' functions in the **psych** package (Revelle, 2016). #' #' - Revelle, W. (2016). How To: Use the psych package for Factor Analysis #' and data reduction. #' #' - Bartlett, M. S. (1951). The effect of standardization on a Chi-square #' approximation in factor analysis. Biometrika, 38(3/4), 337-344. #' - Kaiser, H. F. (1970). A second generation little jiffy. #' Psychometrika, 35(4), 401-415. #' #' - Kaiser, H. F., & Rice, J. (1974). Little jiffy, mark IV. Educational #' and psychological measurement, 34(1), 111-117. #' #' - Kaiser, H. F. (1974). An index of factorial simplicity. #' Psychometrika, 39(1), 31-36. #' #' @export check_factorstructure <- function(x, n = NULL, ...) { # TODO: detect (and remove?) factors kmo <- check_kmo(x, n, ...) sphericity <- check_sphericity_bartlett(x, n, ...) res_text <- paste0("\n - Sphericity: ", attributes(sphericity)$text, "\n - KMO: ", attributes(kmo)$text) if (attributes(kmo)$color == "red" || attributes(sphericity)$color == "red") { color <- "red" } else { color <- "green" } out <- list(KMO = kmo, sphericity = sphericity) attr(out, "text") <- res_text attr(out, "color") <- color attr(out, "title") <- "Is the data suitable for Factor Analysis?" class(out) <- c("easystats_check", class(out)) out } #' @rdname check_factorstructure #' @export check_kmo <- function(x, n = NULL, ...) { out <- .validate_factor_structure(x, n, ...) Q <- solve(out$r) Q <- stats::cov2cor(Q) diag(Q) <- 0 diag(out$r) <- 0 sumQ2 <- sum(Q^2) sumr2 <- sum(out$r^2) MSA <- sumr2 / (sumr2 + sumQ2) MSA_variable <- colSums(out$r^2) / (colSums(out$r^2) + colSums(Q^2)) out <- list(MSA = MSA, MSA_variable = MSA_variable) # TODO: add interpret_kmo in effectsize and use that here for more fine-grained interpretation if (MSA < 0.5) { msg_text <- sprintf( "The Kaiser, Meyer, Olkin (KMO) overall measure of sampling adequacy suggests that factor analysis is likely to be inappropriate (KMO = %.2f).", # nolint MSA ) color <- "red" } else { msg_text <- sprintf( "The Kaiser, Meyer, Olkin (KMO) overall measure of sampling adequacy suggests that data seems appropriate for factor analysis (KMO = %.2f).", # nolint MSA ) color <- "green" } # Individual scores: text_ind <- toString(paste0( names(MSA_variable), " (", insight::format_value(MSA_variable), ifelse(MSA_variable < 0.5, "*", ""), ")" )) msg_text <- paste0(msg_text, " The individual KMO scores are: ", text_ind, ".") attr(out, "text") <- msg_text attr(out, "color") <- color attr(out, "title") <- "KMO Measure of Sampling Adequacy" class(out) <- c("easystats_check", class(out)) out } #' @rdname check_factorstructure #' @export check_sphericity_bartlett <- function(x, n = NULL, ...) { out <- .validate_factor_structure(x, n, ...) p <- dim(out$r)[2] detR <- det(out$r) statistic <- -log(detR) * (out$n - 1 - (2 * p + 5) / 6) dof <- p * (p - 1) / 2 pval <- stats::pchisq(statistic, df = dof, lower.tail = FALSE) out <- list(chisq = statistic, p = pval, dof = dof) if (pval < 0.001) { msg_text <- sprintf( "Bartlett's test of sphericity suggests that there is sufficient significant correlation in the data for factor analysis (Chisq(%i) = %.2f, %s).", # nolint dof, statistic, insight::format_p(pval) ) color <- "green" } else { msg_text <- sprintf( "Bartlett's test of sphericity suggests that there is not enough significant correlation in the data for factor analysis (Chisq(%i) = %.2f, %s).", # nolint dof, statistic, insight::format_p(pval) ) color <- "red" } attr(out, "text") <- msg_text attr(out, "color") <- color attr(out, "title") <- "Test of Sphericity" class(out) <- c("easystats_check", class(out)) out } # Helpers ----------------------------------------------------------------- #' @keywords internal .validate_factor_structure <- function(x, n = NULL, ...) { if (is.null(n)) { r <- stats::cor(x, use = "pairwise.complete.obs", ...) n <- nrow(x) } else { r <- x } if (nrow(r) != ncol(r)) { insight::format_error("The correlation matrix is not square.") } return(list(n = n, r = r)) } performance/R/performance_accuracy.R0000644000176200001440000001757214736731423017300 0ustar liggesusers#' @title Accuracy of predictions from model fit #' @name performance_accuracy #' #' @description This function calculates the predictive accuracy of linear #' or logistic regression models. #' #' @param model A linear or logistic regression model. A mixed-effects model is #' also accepted. #' @param k The number of folds for the k-fold cross-validation. #' @param method Character string, indicating whether cross-validation #' (`method = "cv"`) or bootstrapping (`method = "boot"`) is used to #' compute the accuracy values. #' @param n Number of bootstrap-samples. #' @param verbose Toggle warnings. #' @inheritParams performance_pcp #' #' @return A list with three values: The `Accuracy` of the model #' predictions, i.e. the proportion of accurately predicted values from the #' model, its standard error, `SE`, and the `Method` used to compute #' the accuracy. #' #' @details For linear models, the accuracy is the correlation coefficient #' between the actual and the predicted value of the outcome. For #' logistic regression models, the accuracy corresponds to the #' AUC-value, calculated with the `bayestestR::auc()`-function. #' \cr \cr #' The accuracy is the mean value of multiple correlation resp. #' AUC-values, which are either computed with cross-validation #' or non-parametric bootstrapping (see argument `method`). #' The standard error is the standard deviation of the computed #' correlation resp. AUC-values. #' #' @examples #' model <- lm(mpg ~ wt + cyl, data = mtcars) #' performance_accuracy(model) #' #' model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") #' performance_accuracy(model) #' @export performance_accuracy <- function(model, method = c("cv", "boot"), k = 5, n = 1000, ci = 0.95, verbose = TRUE) { method <- match.arg(method) # get formula from model fit formula <- stats::formula(model) # get name of response resp.name <- insight::find_response(model) # model data, for cross validation model_data <- insight::get_data(model, verbose = FALSE) info <- insight::model_info(model, verbose = verbose) # accuracy for linear models if (info$is_linear) { measure <- "Correlation between observed and predicted" # check if bootstrapping or cross validation is requested if (method == "boot") { # accuracy linear models with bootstrapping bootstr <- replicate(n, sample(nrow(model_data), replace = TRUE), simplify = FALSE) models <- lapply(bootstr, function(.x) { text <- utils::capture.output({ model_upd <- stats::update(model, data = model_data[.x, ]) }) # stats::lm(formula, data = model_data[.x, ]) model_upd }) predictions <- Map(function(.x, .y) { stats::predict(.y, newdata = model_data[.x, ]) }, bootstr, models) response <- lapply(bootstr, function(.x) { as.data.frame(model_data[.x, ])[[resp.name]] }) accuracy <- mapply(function(.x, .y) { stats::cor(.x, .y, use = "pairwise.complete.obs") }, predictions, response) } else { # accuracy linear models with cross validation cv <- .crossv_kfold(model_data, k = k) models <- lapply(cv, function(.x) { text <- utils::capture.output({ model_upd <- stats::update(model, data = model_data[.x$train, ]) }) model_upd # stats::lm(formula, data = model_data[.x$train, ]) }) predictions <- Map(function(.x, .y) { stats::predict(.y, newdata = model_data[.x$test, ]) }, cv, models) response <- lapply(cv, function(.x) { as.data.frame(model_data[.x$test, ])[[resp.name]] }) accuracy <- mapply(function(.x, .y) { stats::cor(.x, .y, use = "pairwise.complete.obs") }, predictions, response) } } else if (info$is_binomial) { measure <- "Area under Curve" # check if bootstrapping or cross validation is requested if (method == "boot") { # accuracy linear models with bootstrapping bootstr <- replicate(n, sample(nrow(model_data), replace = TRUE), simplify = FALSE) models <- lapply(bootstr, function(.x) { text <- utils::capture.output({ model_upd <- stats::update(model, data = model_data[.x, ]) }) # stats::glm(formula, data = model_data[.x, ], family = stats::binomial(link = "logit")) model_upd }) predictions <- Map(function(.x, .y) { stats::predict(.y, newdata = model_data[.x, ], type = "link") }, bootstr, models) response <- lapply(bootstr, function(.x) { .recode_to_zero(as.data.frame(model_data[.x, ])[[resp.name]]) }) accuracy <- mapply(function(.x, .y) { roc <- performance_roc(x = .x, predictions = .y) bayestestR::area_under_curve(roc$Specificity, roc$Sensitivity) }, response, predictions) } else { # accuracy linear models with cross validation cv <- .crossv_kfold(model_data, k = k) models <- lapply(cv, function(.x) { text <- utils::capture.output({ model_upd <- stats::update(model, data = model_data[.x$train, ]) }) model_upd # stats::glm(formula, data = model_data[.x$train, ], family = stats::binomial(link = "logit")) }) predictions <- Map(function(.x, .y) { stats::predict(.y, newdata = model_data[.x$test, ], type = "link") }, cv, models) response <- lapply(cv, function(.x) { .recode_to_zero(as.data.frame(model_data[.x$test, ])[[resp.name]]) }) accuracy <- mapply(function(.x, .y) { roc <- performance_roc(x = .x, predictions = .y) bayestestR::area_under_curve(roc$Specificity, roc$Sensitivity) }, response, predictions) } if (anyNA(accuracy)) { m <- ifelse(method == "cv", "cross-validated", "bootstrapped") if (verbose) { insight::format_alert( paste0("Some of the ", m, " samples were not eligible for calculating AUC.") ) } } } else { if (verbose) { insight::format_warning( paste0("Models of class '", class(model)[1], "' are not supported.") ) } return(NULL) } # return mean value of accuracy structure( class = "performance_accuracy", list( Accuracy = mean(accuracy, na.rm = TRUE), SE = stats::sd(accuracy, na.rm = TRUE), CI = ci, CI_low = as.vector(stats::quantile(accuracy, 1 - ((1 + ci) / 2), na.rm = TRUE)), CI_high = as.vector(stats::quantile(accuracy, (1 + ci) / 2, na.rm = TRUE)), Method = measure ) ) } # methods -------------------------- #' @export as.data.frame.performance_accuracy <- function(x, row.names = NULL, ...) { data.frame( Accuracy = x$Accuracy, SE = x$SE, CI = x$CI, CI_low = x$CI_low, CI_high = x$CI_high, Method = x$Method, stringsAsFactors = FALSE, row.names = row.names, ... ) } #' @export print.performance_accuracy <- function(x, ...) { # headline insight::print_color("# Accuracy of Model Predictions\n\n", "blue") # statistics cat(sprintf( "Accuracy (%i%% CI): %.2f%% [%.2f%%, %.2f%%]\nMethod: %s\n", round(100 * x$CI), 100 * x$Accuracy, 100 * x$CI_low, 100 * x$CI_high, x$Method )) invisible(x) } # utilities ------------------------ .crossv_kfold <- function(model_data, k = 5) { n <- nrow(model_data) folds <- sample(rep(1:k, length.out = n)) idx <- seq_len(n) fold_idx <- split(idx, folds) fold <- function(test) { list(train = setdiff(idx, test), test = test) } lapply(fold_idx, fold) } performance/R/model_performance.mixed.R0000644000176200001440000001321514736731423017701 0ustar liggesusers#' Performance of Mixed Models #' #' Compute indices of model performance for mixed models. #' #' @param metrics Can be `"all"`, `"common"` or a character vector of #' metrics to be computed (some of `c("AIC", "AICc", "BIC", "R2", "ICC", #' "RMSE", "SIGMA", "LOGLOSS", "SCORE")`). `"common"` will compute AIC, #' BIC, R2, ICC and RMSE. #' @param ... Arguments passed to or from other methods. #' @inheritParams r2_nakagawa #' @inheritParams model_performance.lm #' @inheritParams performance_aicc #' #' @return A data frame (with one row) and one column per "index" (see #' `metrics`). #' #' @details #' \subsection{Intraclass Correlation Coefficient (ICC)}{ #' This method returns the *adjusted ICC* only, as this is typically of #' interest when judging the variance attributed to the random effects part of #' the model (see also [icc()]). #' } #' \subsection{REML versus ML estimator}{ #' The default behaviour of `model_performance()` when computing AIC or BIC of #' linear mixed model from package **lme4** is the same as for `AIC()` or #' `BIC()` (i.e. `estimator = "REML"`). However, for model comparison using #' `compare_performance()` sets `estimator = "ML"` by default, because #' *comparing* information criteria based on REML fits is usually not valid #' (unless all models have the same fixed effects). Thus, make sure to set #' the correct estimator-value when looking at fit-indices or comparing model #' fits. #' } #' \subsection{Other performance indices}{ #' Furthermore, see 'Details' in [model_performance.lm()] for more details #' on returned indices. #' } #' #' @examplesIf require("lme4") #' model <- lme4::lmer(Petal.Length ~ Sepal.Length + (1 | Species), data = iris) #' model_performance(model) #' @export model_performance.merMod <- function(model, metrics = "all", estimator = "REML", verbose = TRUE, ...) { if (any(tolower(metrics) == "log_loss")) { metrics[tolower(metrics) == "log_loss"] <- "LOGLOSS" } # all available metrics all_metrics <- c("AIC", "AICc", "BIC", "R2", "ICC", "RMSE", "SIGMA", "LOGLOSS", "SCORE") if (all(metrics == "all")) { metrics <- all_metrics } else if (all(metrics == "common")) { metrics <- c("AIC", "BIC", "R2", "ICC", "RMSE") } metrics <- .check_bad_metrics(metrics, all_metrics, verbose) # check model formula if (verbose) { insight::formula_ok(model) } mi <- insight::model_info(model, verbose = FALSE) out <- list() if ("AIC" %in% toupper(metrics)) { out$AIC <- performance_aic(model, estimator = estimator) } if ("AICC" %in% toupper(metrics)) { out$AICc <- .safe(performance_aicc(model, estimator = estimator)) } if ("BIC" %in% toupper(metrics)) { out$BIC <- .get_BIC(model, estimator = estimator) } if ("R2" %in% toupper(metrics)) { rsq <- suppressWarnings(r2(model)) if (!all(is.na(rsq))) out <- c(out, rsq) } if ("ICC" %in% toupper(metrics)) { icc_mm <- suppressWarnings(icc(model)) if (!all(is.na(icc_mm))) out$ICC <- icc_mm$ICC_adjusted } if ("RMSE" %in% toupper(metrics)) { out$RMSE <- performance_rmse(model, verbose = verbose) } if ("SIGMA" %in% toupper(metrics)) { out$Sigma <- .get_sigma(model, verbose = verbose) } if (("LOGLOSS" %in% toupper(metrics)) && mi$is_binomial) { out$Log_loss <- performance_logloss(model, verbose = verbose) } if (("SCORE" %in% toupper(metrics)) && (mi$is_binomial || mi$is_count)) { .scoring_rules <- performance_score(model, verbose = verbose) if (!is.na(.scoring_rules$logarithmic)) out$Score_log <- .scoring_rules$logarithmic if (!is.na(.scoring_rules$spherical)) out$Score_spherical <- .scoring_rules$spherical } # TODO: What with sigma and deviance? out <- as.data.frame(out) row.names(out) <- NULL class(out) <- c("performance_model", class(out)) out } #' @export model_performance.lme <- model_performance.merMod #' @export model_performance.glmmadmb <- model_performance.merMod #' @export model_performance.rlmerMod <- model_performance.merMod #' @export model_performance.MixMod <- model_performance.merMod #' @export model_performance.mixed <- model_performance.merMod #' @export model_performance.glmmTMB <- model_performance.merMod #' @export model_performance.mixor <- function(model, metrics = "all", verbose = TRUE, ...) { if (any(tolower(metrics) == "log_loss")) { metrics[tolower(metrics) == "log_loss"] <- "LOGLOSS" } if (all(metrics == "all")) { metrics <- c("AIC", "BIC", "LOGLOSS", "SCORE") } mi <- insight::model_info(model) out <- list() if ("AIC" %in% metrics) { out$AIC <- performance_aic(model) } if ("BIC" %in% metrics) { out$BIC <- .get_BIC(model) } if (("LOGLOSS" %in% metrics) && mi$is_binomial && !mi$is_ordinal && !mi$is_multinomial) { out$Log_loss <- performance_logloss(model, verbose = verbose) } if (("SCORE" %in% metrics) && (mi$is_binomial || mi$is_count) && !mi$is_ordinal && !mi$is_multinomial) { .scoring_rules <- performance_score(model, verbose = verbose) if (!is.na(.scoring_rules$logarithmic)) out$Score_log <- .scoring_rules$logarithmic if (!is.na(.scoring_rules$spherical)) out$Score_spherical <- .scoring_rules$spherical } out <- as.data.frame(out) row.names(out) <- NULL class(out) <- c("performance_model", class(out)) out } performance/R/check_collinearity.R0000644000176200001440000005520014741711131016734 0ustar liggesusers#' @title Check for multicollinearity of model terms #' @name check_collinearity #' #' @description #' #' `check_collinearity()` checks regression models for #' multicollinearity by calculating the variance inflation factor (VIF). #' `multicollinearity()` is an alias for `check_collinearity()`. #' `check_concurvity()` is a wrapper around `mgcv::concurvity()`, and can be #' considered as a collinearity check for smooth terms in GAMs. Confidence #' intervals for VIF and tolerance are based on Marcoulides et al. #' (2019, Appendix B). #' #' @param x A model object (that should at least respond to `vcov()`, #' and if possible, also to `model.matrix()` - however, it also should #' work without `model.matrix()`). #' @param component For models with zero-inflation component, multicollinearity #' can be checked for the conditional model (count component, #' `component = "conditional"` or `component = "count"`), #' zero-inflation component (`component = "zero_inflated"` or #' `component = "zi"`) or both components (`component = "all"`). #' Following model-classes are currently supported: `hurdle`, #' `zeroinfl`, `zerocount`, `MixMod` and `glmmTMB`. #' @param ci Confidence Interval (CI) level for VIF and tolerance values. #' @param verbose Toggle off warnings or messages. #' @param ... Currently not used. #' #' @return A data frame with information about name of the model term, the #' variance inflation factor and associated confidence intervals, the factor #' by which the standard error is increased due to possible correlation #' with other terms, and tolerance values (including confidence intervals), #' where `tolerance = 1/vif`. #' #' @seealso [`see::plot.see_check_collinearity()`] for options to customize the plot. #' #' @section Multicollinearity: #' Multicollinearity should not be confused with a raw strong correlation #' between predictors. What matters is the association between one or more #' predictor variables, *conditional on the other variables in the #' model*. In a nutshell, multicollinearity means that once you know the #' effect of one predictor, the value of knowing the other predictor is rather #' low. Thus, one of the predictors doesn't help much in terms of better #' understanding the model or predicting the outcome. As a consequence, if #' multicollinearity is a problem, the model seems to suggest that the #' predictors in question don't seems to be reliably associated with the #' outcome (low estimates, high standard errors), although these predictors #' actually are strongly associated with the outcome, i.e. indeed might have #' strong effect (_McElreath 2020, chapter 6.1_). #' #' Multicollinearity might arise when a third, unobserved variable has a causal #' effect on each of the two predictors that are associated with the outcome. #' In such cases, the actual relationship that matters would be the association #' between the unobserved variable and the outcome. #' #' Remember: "Pairwise correlations are not the problem. It is the conditional #' associations - not correlations - that matter." (_McElreath 2020, p. 169_) #' #' @section Interpretation of the Variance Inflation Factor: #' The variance inflation factor is a measure to analyze the magnitude of #' multicollinearity of model terms. A VIF less than 5 indicates a low #' correlation of that predictor with other predictors. A value between 5 and #' 10 indicates a moderate correlation, while VIF values larger than 10 are a #' sign for high, not tolerable correlation of model predictors (_James et al. #' 2013_). The *Increased SE* column in the output indicates how much larger #' the standard error is due to the association with other predictors #' conditional on the remaining variables in the model. Note that these #' thresholds, although commonly used, are also criticized for being too high. #' _Zuur et al. (2010)_ suggest using lower values, e.g. a VIF of 3 or larger #' may already no longer be considered as "low". #' #' @section Multicollinearity and Interaction Terms: #' If interaction terms are included in a model, high VIF values are expected. #' This portion of multicollinearity among the component terms of an #' interaction is also called "inessential ill-conditioning", which leads to #' inflated VIF values that are typically seen for models with interaction #' terms _(Francoeur 2013)_. Centering interaction terms can resolve this #' issue _(Kim and Jung 2024)_. #' #' @section Multicollinearity and Polynomial Terms: #' Polynomial transformations are considered a single term and thus VIFs are #' not calculated between them. #' #' @section Concurvity for Smooth Terms in Generalized Additive Models: #' `check_concurvity()` is a wrapper around `mgcv::concurvity()`, and can be #' considered as a collinearity check for smooth terms in GAMs."Concurvity #' occurs when some smooth term in a model could be approximated by one or more #' of the other smooth terms in the model." (see `?mgcv::concurvity`). #' `check_concurvity()` returns a column named _VIF_, which is the "worst" #' measure. While `mgcv::concurvity()` range between 0 and 1, the _VIF_ value #' is `1 / (1 - worst)`, to make interpretation comparable to classical VIF #' values, i.e. `1` indicates no problems, while higher values indicate #' increasing lack of identifiability. The _VIF proportion_ column equals the #' "estimate" column from `mgcv::concurvity()`, ranging from 0 (no problem) to #' 1 (total lack of identifiability). #' #' @references #' #' - Francoeur, R. B. (2013). Could Sequential Residual Centering Resolve #' Low Sensitivity in Moderated Regression? Simulations and Cancer Symptom #' Clusters. Open Journal of Statistics, 03(06), 24-44. #' #' - James, G., Witten, D., Hastie, T., and Tibshirani, R. (eds.). (2013). An #' introduction to statistical learning: with applications in R. New York: #' Springer. #' #' - Kim, Y., & Jung, G. (2024). Understanding linear interaction analysis with #' causal graphs. British Journal of Mathematical and Statistical Psychology, #' 00, 1–14. #' #' - Marcoulides, K. M., and Raykov, T. (2019). Evaluation of Variance #' Inflation Factors in Regression Models Using Latent Variable Modeling #' Methods. Educational and Psychological Measurement, 79(5), 874–882. #' #' - McElreath, R. (2020). Statistical rethinking: A Bayesian course with #' examples in R and Stan. 2nd edition. Chapman and Hall/CRC. #' #' - Vanhove, J. (2019). Collinearity isn't a disease that needs curing. #' [webpage](https://janhove.github.io/posts/2019-09-11-collinearity/) #' #' - Zuur AF, Ieno EN, Elphick CS. A protocol for data exploration to avoid #' common statistical problems: Data exploration. Methods in Ecology and #' Evolution (2010) 1:3–14. #' #' @family functions to check model assumptions and and assess model quality #' #' @note The code to compute the confidence intervals for the VIF and tolerance #' values was adapted from the Appendix B from the Marcoulides et al. paper. #' Thus, credits go to these authors the original algorithm. There is also #' a [`plot()`-method](https://easystats.github.io/see/articles/performance.html) #' implemented in the \href{https://easystats.github.io/see/}{\pkg{see}-package}. #' #' @examples #' m <- lm(mpg ~ wt + cyl + gear + disp, data = mtcars) #' check_collinearity(m) #' #' @examplesIf insight::check_if_installed("see", minimum_version = "0.9.1", quietly = TRUE) #' # plot results #' x <- check_collinearity(m) #' plot(x) #' @export check_collinearity <- function(x, ...) { UseMethod("check_collinearity") } #' @rdname check_collinearity #' @export multicollinearity <- check_collinearity # default ------------------------------ #' @rdname check_collinearity #' @export check_collinearity.default <- function(x, ci = 0.95, verbose = TRUE, ...) { .is_model_valid(x) .check_collinearity(x, component = "conditional", ci = ci, verbose = verbose) } # methods ------------------------------------------- #' @export print.check_collinearity <- function(x, ...) { insight::print_color("# Check for Multicollinearity\n", "blue") if ("Component" %in% colnames(x)) { comp <- split(x, x$Component) for (i in seq_along(comp)) { cat(paste0("\n* ", comp[[i]]$Component[1], " component:\n")) .print_collinearity(datawizard::data_remove(comp[[i]], "Component")) } } else { .print_collinearity(x) } invisible(x) } #' @export plot.check_collinearity <- function(x, ...) { insight::check_if_installed("see", "to plot collinearity-check") NextMethod() } .print_collinearity <- function(x) { vifs <- x$VIF low_vif <- which(vifs < 5) mid_vif <- which(vifs >= 5 & vifs < 10) high_vif <- which(vifs >= 10) all_vifs <- insight::compact_list(list(low_vif, mid_vif, high_vif)) # if we have no CIs, remove those columns x <- datawizard::remove_empty_columns(x) # format table for each "ViF" group - this ensures that CIs are properly formatted x <- insight::format_table(x) x <- datawizard::data_rename( x, select = "SE_factor", replacement = "Increased SE", verbose = FALSE ) if (length(low_vif)) { cat("\n") insight::print_color("Low Correlation\n\n", "green") print.data.frame(x[low_vif, ], row.names = FALSE) } if (length(mid_vif)) { cat("\n") insight::print_color("Moderate Correlation\n\n", "yellow") print.data.frame(x[mid_vif, ], row.names = FALSE) } if (length(high_vif)) { cat("\n") insight::print_color("High Correlation\n\n", "red") print.data.frame(x[high_vif, ], row.names = FALSE) } } # other classes ---------------------------------- #' @export check_collinearity.afex_aov <- function(x, verbose = TRUE, ...) { if (length(attr(x, "within")) == 0L) { return(check_collinearity(x$lm, verbose = verbose, ...)) } f <- insight::find_formula(x)[[1]] f <- Reduce(paste, deparse(f)) f <- sub("\\+\\s*Error\\(.*\\)$", "", f) f <- stats::as.formula(f) d <- insight::get_data(x, verbose = FALSE) is_num <- vapply(d, is.numeric, logical(1)) d[is_num] <- sapply(d[is_num], datawizard::center, simplify = TRUE) is_fac <- !is_num contrs <- lapply(is_fac, function(...) stats::contr.sum)[is_fac] if (verbose) { insight::format_alert( "All predictors have been centered (factors with `contr.sum()`, numerics with `scale()`)." ) } check_collinearity(suppressWarnings(stats::lm( formula = f, data = d, contrasts = contrs ))) } #' @export check_collinearity.BFBayesFactor <- function(x, verbose = TRUE, ...) { if (!insight::is_model(x)) { insight::format_error("Collinearity only applicable to regression models.") } f <- insight::find_formula(x)[[1]] d <- insight::get_data(x, verbose = FALSE) check_collinearity(stats::lm(f, d)) } # mfx models ------------------------------- #' @export check_collinearity.logitor <- function(x, ci = 0.95, verbose = TRUE, ...) { .check_collinearity(x$fit, component = "conditional", ci = ci, verbose = verbose) } #' @export check_collinearity.logitmfx <- check_collinearity.logitor #' @export check_collinearity.probitmfx <- check_collinearity.logitor #' @export check_collinearity.poissonirr <- check_collinearity.logitor #' @export check_collinearity.poissonmfx <- check_collinearity.logitor #' @export check_collinearity.negbinirr <- check_collinearity.logitor #' @export check_collinearity.negbinmfx <- check_collinearity.logitor #' @export check_collinearity.betaor <- check_collinearity.logitor #' @export check_collinearity.betamfx <- check_collinearity.logitor # zi-models ------------------------------------- #' @rdname check_collinearity #' @export check_collinearity.glmmTMB <- function(x, component = c("all", "conditional", "count", "zi", "zero_inflated"), ci = 0.95, verbose = TRUE, ...) { component <- match.arg(component) .check_collinearity_zi_model(x, component, ci = ci, verbose = verbose) } #' @export check_collinearity.MixMod <- function(x, component = c("all", "conditional", "count", "zi", "zero_inflated"), ci = 0.95, verbose = TRUE, ...) { component <- match.arg(component) .check_collinearity_zi_model(x, component, ci = ci, verbose = verbose) } #' @export check_collinearity.hurdle <- function(x, component = c("all", "conditional", "count", "zi", "zero_inflated"), ci = 0.95, verbose = verbose, ...) { component <- match.arg(component) .check_collinearity_zi_model(x, component, ci = ci, verbose = verbose) } #' @export check_collinearity.zeroinfl <- function(x, component = c("all", "conditional", "count", "zi", "zero_inflated"), ci = 0.95, verbose = verbose, ...) { component <- match.arg(component) .check_collinearity_zi_model(x, component, ci = ci, verbose = verbose) } #' @export check_collinearity.zerocount <- function(x, component = c("all", "conditional", "count", "zi", "zero_inflated"), ci = 0.95, verbose = verbose, ...) { component <- match.arg(component) .check_collinearity_zi_model(x, component, ci = ci, verbose = verbose) } # utilities --------------------------------- .check_collinearity_zi_model <- function(x, component, ci = 0.95, verbose = TRUE) { if (component == "count") component <- "conditional" if (component == "zi") component <- "zero_inflated" mi <- insight::model_info(x, verbose = FALSE) if (!mi$is_zero_inflated) component <- "conditional" if (component == "all") { cond <- .check_collinearity(x, "conditional", ci = ci, verbose = verbose) zi <- .check_collinearity(x, "zero_inflated", ci = ci, verbose = FALSE) if (is.null(cond) && is.null(zi)) { return(NULL) } if (is.null(cond)) { zi$Component <- "zero inflated" return(zi) } if (is.null(zi)) { cond$Component <- "conditional" return(cond) } # retrieve data for plotting dat_cond <- attr(cond, "data") dat_zi <- attr(zi, "data") ci_cond <- attr(cond, "CI") ci_zi <- attr(zi, "CI") # add component cond$Component <- "conditional" zi$Component <- "zero inflated" dat_cond$Component <- "conditional" dat_zi$Component <- "zero inflated" ci_cond$Component <- "conditional" ci_zi$Component <- "zero inflated" # create final data dat <- rbind(cond, zi) attr(dat, "data") <- rbind(dat_cond, dat_zi) attr(dat, "CI") <- rbind(ci_cond, ci_zi) dat } else { .check_collinearity(x, component, ci = ci, verbose = verbose) } } .check_collinearity <- function(x, component, ci = 0.95, verbose = TRUE) { v <- .safe(insight::get_varcov(x, component = component, verbose = FALSE)) # sanity check if (is.null(v)) { if (isTRUE(verbose)) { insight::format_alert( paste( sprintf("Could not extract the variance-covariance matrix for the %s component of the model.", component), "Please try to run `vcov(model)`, which may help identifying the problem." ) ) } return(NULL) } term_assign <- .term_assignments(x, component, verbose = verbose) # any assignment found? if (is.null(term_assign) || all(is.na(term_assign))) { if (verbose) { insight::format_alert( sprintf("Could not extract model terms for the %s component of the model.", component) ) } return(NULL) } # we have rank-deficiency here. remove NA columns from assignment if (isTRUE(attributes(v)$rank_deficient) && !is.null(attributes(v)$na_columns_index)) { term_assign <- term_assign[-attributes(v)$na_columns_index] if (isTRUE(verbose)) { insight::format_alert( "Model matrix is rank deficient. VIFs may not be sensible." ) } } # check for missing intercept if (insight::has_intercept(x)) { v <- v[-1, -1] term_assign <- term_assign[-1] } else if (isTRUE(verbose)) { insight::format_alert("Model has no intercept. VIFs may not be sensible.") } f <- insight::find_formula(x, verbose = FALSE) # hurdle or zeroinfl model can have no zero-inflation formula, in which case # we have the same formula as for conditional formula part if (inherits(x, c("hurdle", "zeroinfl", "zerocount")) && component == "zero_inflated" && is.null(f[["zero_inflated"]])) { f$zero_inflated <- f$conditional } if (inherits(x, "mixor")) { model_terms <- labels(x$terms) } else { model_terms <- labels(stats::terms(f[[component]])) } if ("instruments" %in% names(f)) { model_terms <- unique(c(model_terms, labels(stats::terms(f[["instruments"]])))) } n.terms <- length(model_terms) if (n.terms < 2) { if (isTRUE(verbose)) { insight::format_alert( sprintf("Not enough model terms in the %s part of the model to check for multicollinearity.", component) ) } return(NULL) } R <- stats::cov2cor(v) detR <- det(R) result <- vector("numeric") na_terms <- vector("numeric") # sanity check - models with offset(?) may contain too many term assignments if (length(term_assign) > ncol(v)) { term_assign <- term_assign[seq_len(ncol(v))] } for (term in 1:n.terms) { subs <- which(term_assign == term) if (length(subs)) { result <- c( result, det(as.matrix(R[subs, subs])) * det(as.matrix(R[-subs, -subs])) / detR ) } else { na_terms <- c(na_terms, term) } } # any terms to remove, due to rank deficiency? if (length(na_terms)) { model_terms <- model_terms[-na_terms] } # check for interactions, VIF might be inflated... if (!is.null(insight::find_interactions(x)) && any(result > 10) && isTRUE(verbose)) { insight::format_alert( "Model has interaction terms. VIFs might be inflated.", "Try to center the variables used for the interaction, or check multicollinearity among predictors of a model without interaction terms." # nolint ) } # CIs, see Appendix B 10.1177/0013164418817803 r <- 1 - (1 / result) n <- insight::n_obs(x) p <- insight::n_parameters(x) # check if CIs are requested if (!is.null(ci) && !is.na(ci) && is.numeric(ci)) { ci_lvl <- (1 + ci) / 2 logis_r <- stats::qlogis(r) # see Raykov & Marcoulides (2011, ch. 7) for details. se <- sqrt((1 - r^2)^2 * (n - p - 1)^2 / ((n^2 - 1) * (n + 3))) se_log <- se / (r * (1 - r)) ci_log_lo <- logis_r - stats::qnorm(ci_lvl) * se_log ci_log_up <- logis_r + stats::qnorm(ci_lvl) * se_log ci_lo <- stats::plogis(ci_log_lo) ci_up <- stats::plogis(ci_log_up) } else { ci_lo <- ci_up <- NA } out <- insight::text_remove_backticks( data.frame( Term = model_terms, VIF = result, VIF_CI_low = 1 / (1 - ci_lo), VIF_CI_high = 1 / (1 - ci_up), SE_factor = sqrt(result), Tolerance = 1 / result, Tolerance_CI_low = 1 - ci_up, Tolerance_CI_high = 1 - ci_lo, stringsAsFactors = FALSE ), column = "Term" ) attr(out, "ci") <- ci attr(out, "data") <- insight::text_remove_backticks( data.frame( Term = model_terms, VIF = result, SE_factor = sqrt(result), stringsAsFactors = FALSE ), column = "Term" ) attr(out, "CI") <- data.frame( VIF_CI_low = 1 / (1 - ci_lo), VIF_CI_high = 1 / (1 - ci_up), Tolerance_CI_low = 1 - ci_up, Tolerance_CI_high = 1 - ci_lo, stringsAsFactors = FALSE ) class(out) <- c("check_collinearity", "see_check_collinearity", "data.frame") out } .term_assignments <- function(x, component, verbose = TRUE) { tryCatch( { if (inherits(x, c("hurdle", "zeroinfl", "zerocount"))) { term_assign <- switch(component, conditional = attr(insight::get_modelmatrix(x, model = "count"), "assign"), zero_inflated = attr(insight::get_modelmatrix(x, model = "zero"), "assign") ) } else if (inherits(x, "glmmTMB")) { term_assign <- switch(component, conditional = attr(insight::get_modelmatrix(x), "assign"), zero_inflated = .zi_term_assignment(x, component, verbose = verbose) ) } else if (inherits(x, "MixMod")) { term_assign <- switch(component, conditional = attr(insight::get_modelmatrix(x, type = "fixed"), "assign"), zero_inflated = attr(insight::get_modelmatrix(x, type = "zi_fixed"), "assign") ) } else { term_assign <- attr(insight::get_modelmatrix(x), "assign") } if (is.null(term_assign)) { term_assign <- .find_term_assignment(x, component, verbose = verbose) } term_assign }, error = function(e) { .find_term_assignment(x, component, verbose = verbose) } ) } .find_term_assignment <- function(x, component, verbose = TRUE) { pred <- insight::find_predictors(x)[[component]] if (is.null(pred)) { return(NULL) } dat <- insight::get_data(x, verbose = FALSE)[, pred, drop = FALSE] parms <- unlist(lapply(seq_along(pred), function(i) { p <- pred[i] if (is.factor(dat[[p]])) { ps <- paste0(p, levels(dat[[p]])) names(ps)[seq_along(ps)] <- i ps } else { names(p) <- i p } })) if (insight::is_gam_model(x)) { model_params <- as.vector(unlist(insight::find_parameters(x)[c(component, "smooth_terms")])) } else { model_params <- insight::find_parameters(x)[[component]] } as.numeric(names(parms)[match( insight::clean_names(model_params), parms )]) } .zi_term_assignment <- function(x, component = "zero_inflated", verbose = TRUE) { tryCatch( { rhs <- insight::find_formula(x)[[component]] d <- insight::get_data(x, verbose = FALSE) attr(insight::get_modelmatrix(rhs, data = d), "assign") }, error = function(e) { NULL } ) } performance/R/model_performance.ivreg.R0000644000176200001440000000456214620351763017711 0ustar liggesusers#' Performance of instrumental variable regression models #' #' @inheritParams model_performance.lm #' @param metrics Can be `"all"`, `"common"` or a character vector of #' metrics to be computed (some of `c("AIC", "AICc", "BIC", "R2", "RMSE", #' "SIGMA", "Sargan", "Wu_Hausman", "weak_instruments")`). `"common"` will #' compute AIC, BIC, R2 and RMSE. #' #' @details `model_performance()` correctly detects transformed response and #' returns the "corrected" AIC and BIC value on the original scale. To get back #' to the original scale, the likelihood of the model is multiplied by the #' Jacobian/derivative of the transformation. #' #' @export model_performance.ivreg <- function(model, metrics = "all", verbose = TRUE, ...) { all_metrics <- c( "AIC", "BIC", "R2", "R2_adj", "RMSE", "SIGMA", "Sargan", "Wu_Hausman", "weak_instruments" ) if (all(metrics == "all")) { metrics <- all_metrics } else if (all(metrics == "common")) { metrics <- c("AIC", "BIC", "R2", "R2_adj", "RMSE") } metrics <- .check_bad_metrics(metrics, all_metrics, verbose) # the lm-method does not accept ivreg-specific metrics out <- model_performance.lm( model, metrics = setdiff(metrics, c("Sargan", "Wu_Hausman", "weak_instruments")), verbose = verbose, ... ) diagnostics <- c("Sargan", "Wu_Hausman", "weak_instruments") if (any(metrics %in% diagnostics)) { s <- summary(model, diagnostics = TRUE) if ("Sargan" %in% metrics) { out$Sargan <- s$diagnostics["Sargan", "statistic"] out$Sargan_p <- s$diagnostics["Sargan", "p-value"] } if ("Wu_Hausman" %in% metrics) { out$Wu_Hausman <- s$diagnostics["Wu-Hausman", "statistic"] out$Wu_Hausman_p <- s$diagnostics["Wu-Hausman", "p-value"] } if ("weak_instruments" %in% metrics) { out$weak_instruments <- s$diagnostics["Weak instruments", "statistic"] out$weak_instruments_p <- s$diagnostics["Weak instruments", "p-value"] } # remove NA columns completed_tests <- intersect( c( "Sargan", "Sargan_p", "Wu_Hausman", "Wu_Hausman_p", "weak_instruments", "weak_instruments_p" ), colnames(out) ) missing <- sapply(out[completed_tests], function(i) all(is.na(i))) if (any(missing)) { out[completed_tests[missing]] <- NULL } } out } performance/R/r2_mckelvey.R0000644000176200001440000000472614335664246015347 0ustar liggesusers#' @title McKelvey & Zavoinas R2 #' @name r2_mckelvey #' #' @description Calculates McKelvey and Zavoinas pseudo R2. #' #' @param model Generalized linear model. #' #' @return The R2 value. #' #' @references #' McKelvey, R., Zavoina, W. (1975), "A Statistical Model for the Analysis of #' Ordinal Level Dependent Variables", Journal of Mathematical Sociology 4, S. #' 103–120. #' #' @details McKelvey and Zavoinas R2 is based on the explained variance, #' where the variance of the predicted response is divided by the sum #' of the variance of the predicted response and residual variance. #' For binomial models, the residual variance is either `pi^2/3` #' for logit-link and 1 for probit-link. For poisson-models, the #' residual variance is based on log-normal approximation, similar to #' the *distribution-specific variance* as described in #' `?insight::get_variance`. #' #' @examples #' ## Dobson (1990) Page 93: Randomized Controlled Trial: #' counts <- c(18, 17, 15, 20, 10, 20, 25, 13, 12) # #' outcome <- gl(3, 1, 9) #' treatment <- gl(3, 3) #' model <- glm(counts ~ outcome + treatment, family = poisson()) #' #' r2_mckelvey(model) #' @export r2_mckelvey <- function(model) { UseMethod("r2_mckelvey") } #' @export r2_mckelvey.default <- function(model) { .r2_mckelvey(model) } .r2_mckelvey <- function(model) { faminfo <- insight::model_info(model) n <- insight::n_obs(model, disaggregate = TRUE) if (faminfo$is_binomial || faminfo$is_ordinal || faminfo$is_multinomial) { dist.variance <- switch(faminfo$link_function, probit = 1, logit = pi^2 / 3, clogloglink = pi^2 / 6, NA ) } else if (faminfo$is_count) { dist.variance <- switch(faminfo$link_function, log = .get_poisson_variance(model), sqrt = 0.25, 0 ) } y.hat <- stats::predict(model, type = "link") # fix for VGAM yhat_columns <- ncol(y.hat) if (!is.null(yhat_columns) && yhat_columns > 1) y.hat <- as.vector(y.hat[, 1]) dist.residual <- sum((y.hat - mean(y.hat))^2) mckelvey <- dist.residual / (n * dist.variance + dist.residual) names(mckelvey) <- "McKelvey's R2" mckelvey } .null_model <- function(model) { stats::update(model, ~1) } .get_poisson_variance <- function(model) { mu <- exp(stats::coef(.null_model(model))) if (is.na(mu)) { return(0) } cvsquared <- stats::family(model)$variance(mu) / mu^2 log1p(cvsquared) } performance/R/performance_mse.R0000644000176200001440000000474214736731423016265 0ustar liggesusers#' @title Mean Square Error of Linear Models #' @name performance_mse #' #' @description Compute mean square error of linear models. #' #' @inheritParams performance_rmse #' @inheritParams model_performance.lm #' #' @details #' The mean square error is the mean of the sum of squared residuals, i.e. it #' measures the average of the squares of the errors. Less technically speaking, #' the mean square error can be considered as the variance of the residuals, #' i.e. the variation in the outcome the model doesn't explain. Lower values #' (closer to zero) indicate better fit. #' #' @return Numeric, the mean square error of `model`. #' #' @examples #' data(mtcars) #' m <- lm(mpg ~ hp + gear, data = mtcars) #' performance_mse(m) #' @export performance_mse <- function(model, ...) { UseMethod("performance_mse") } #' @rdname performance_mse #' @export mse <- performance_mse #' @export performance_mse.default <- function(model, verbose = TRUE, ...) { res <- .safe(insight::get_residuals(model, verbose = verbose, type = "response", ...)) if (is.null(res)) { res <- .safe({ def_res <- insight::get_residuals(model, verbose = FALSE, ...) if (verbose) { insight::format_alert( "Response residuals not available to calculate mean square error. (R)MSE is probably not reliable." ) } def_res }) } if (is.null(res) || all(is.na(res))) { return(NA) } # for multivariate response models... if (is.data.frame(res)) { if (verbose) { insight::format_warning("Multiple response variables detected. Cannot reliably compute (R)MSE.") } return(NA) } mean(res^2, na.rm = TRUE) } # mfx models ------------------------------- #' @export performance_mse.logitor <- function(model, verbose = TRUE, ...) { performance_mse(model$fit, verbose = verbose, ...) } #' @export performance_mse.logitmfx <- performance_mse.logitor #' @export performance_mse.probitmfx <- performance_mse.logitor #' @export performance_mse.poissonirr <- performance_mse.logitor #' @export performance_mse.poissonmfx <- performance_mse.logitor #' @export performance_mse.negbinirr <- performance_mse.logitor #' @export performance_mse.negbinmfx <- performance_mse.logitor #' @export performance_mse.betaor <- performance_mse.logitor #' @export performance_mse.betamfx <- performance_mse.logitor #' @export performance_mse.model_fit <- performance_mse.logitor performance/R/r2_zeroinflated.R0000644000176200001440000000442214527666553016215 0ustar liggesusers#' @title R2 for models with zero-inflation #' @name r2_zeroinflated #' #' @description #' Calculates R2 for models with zero-inflation component, including mixed #' effects models. #' #' @param model A model. #' @param method Indicates the method to calculate R2. See 'Details'. May be #' abbreviated. #' #' @return For the default-method, a list with the R2 and adjusted R2 values. #' For `method = "correlation"`, a named numeric vector with the #' correlation-based R2 value. #' #' @details #' The default-method calculates an R2 value based on the residual variance #' divided by the total variance. For `method = "correlation"`, R2 is a #' correlation-based measure, which is rather crude. It simply computes the #' squared correlation between the model's actual and predicted response. #' #' @examples #' \donttest{ #' if (require("pscl")) { #' data(bioChemists) #' model <- zeroinfl( #' art ~ fem + mar + kid5 + ment | kid5 + phd, #' data = bioChemists #' ) #' #' r2_zeroinflated(model) #' } #' } #' @export r2_zeroinflated <- function(model, method = c("default", "correlation")) { method <- match.arg(method) mi <- insight::model_info(model, verbose = FALSE) if (!mi$is_zero_inflated) { insight::format_warning("Model has no zero-inflation component.") } if (method == "default") { .r2_zi_default(model) } else { .r2_zi_correlation(model) } } .r2_zi_correlation <- function(model) { r2_zi <- stats::cor( insight::get_response(model, verbose = FALSE), stats::predict(model, type = "response") )^2 names(r2_zi) <- "R2 for ZI-models" r2_zi } .r2_zi_default <- function(model) { n <- insight::n_obs(model) k <- length(insight::find_parameters(model)[["conditional"]]) y <- insight::get_response(model, verbose = FALSE) var_fixed <- sum((stats::fitted(model) - mean(y))^2) var_resid <- sum(stats::residuals(model, type = "pearson")^2) r2_zi <- var_fixed / (var_resid + var_fixed) r2_zi_adj <- 1 - (1 - r2_zi) * (n - 1) / (n - k - 1) out <- list(R2 = r2_zi, R2_adjusted = r2_zi_adj) names(out$R2) <- "R2" names(out$R2_adjusted) <- "adjusted R2" attr(out, "model_type") <- "Zero-Inflated and Hurdle" structure(class = "r2_generic", out) } performance/R/icc.R0000644000176200001440000006377514736731423013671 0ustar liggesusers#' @title Intraclass Correlation Coefficient (ICC) #' @name icc #' #' @description #' This function calculates the intraclass-correlation coefficient (ICC) - #' sometimes also called *variance partition coefficient* (VPC) or #' *repeatability* - for mixed effects models. The ICC can be calculated for all #' models supported by [`insight::get_variance()`]. For models fitted with the #' **brms**-package, `icc()` might fail due to the large variety of #' models and families supported by the **brms**-package. In such cases, an #' alternative to the ICC is the `variance_decomposition()`, which is based #' on the posterior predictive distribution (see 'Details'). #' #' @param model A (Bayesian) mixed effects model. #' @param re_formula Formula containing group-level effects to be considered in #' the prediction. If `NULL` (default), include all group-level effects. #' Else, for instance for nested models, name a specific group-level effect #' to calculate the variance decomposition for this group-level. See 'Details' #' and `?brms::posterior_predict`. #' @param ci Confidence resp. credible interval level. For `icc()`, `r2()`, and #' `rmse()`, confidence intervals are based on bootstrapped samples from the #' ICC, R2 or RMSE value. See `iterations`. #' @param by_group Logical, if `TRUE`, `icc()` returns the variance components #' for each random-effects level (if there are multiple levels). See 'Details'. #' @param iterations Number of bootstrap-replicates when computing confidence #' intervals for the ICC, R2, RMSE etc. #' @param ci_method Character string, indicating the bootstrap-method. Should #' be `NULL` (default), in which case `lme4::bootMer()` is used for bootstrapped #' confidence intervals. However, if bootstrapped intervals cannot be calculated #' this way, try `ci_method = "boot"`, which falls back to `boot::boot()`. This #' may successfully return bootstrapped confidence intervals, but bootstrapped #' samples may not be appropriate for the multilevel structure of the model. #' There is also an option `ci_method = "analytical"`, which tries to calculate #' analytical confidence assuming a chi-squared distribution. However, these #' intervals are rather inaccurate and often too narrow. It is recommended to #' calculate bootstrapped confidence intervals for mixed models. #' @param verbose Toggle warnings and messages. #' @param null_model Optional, a null model to compute the random effect variances, #' which is passed to [`insight::get_variance()`]. Usually only required if #' calculation of r-squared or ICC fails when `null_model` is not specified. If #' calculating the null model takes longer and you already have fit the null #' model, you can pass it here, too, to speed up the process. #' @param ... Arguments passed down to `lme4::bootMer()` or `boot::boot()` #' for bootstrapped ICC, R2, RMSE etc.; for `variance_decomposition()`, #' arguments are passed down to `brms::posterior_predict()`. #' #' @inheritParams r2_bayes #' @inheritParams insight::get_variance #' #' @return A list with two values, the adjusted ICC and the unadjusted ICC. For #' `variance_decomposition()`, a list with two values, the decomposed #' ICC as well as the credible intervals for this ICC. #' #' @references #' - Hox, J. J. (2010). Multilevel analysis: techniques and applications #' (2nd ed). New York: Routledge. #' - Nakagawa, S., Johnson, P. C. D., and Schielzeth, H. (2017). The #' coefficient of determination R2 and intra-class correlation coefficient #' from generalized linear mixed-effects models revisited and expanded. #' Journal of The Royal Society Interface, 14(134), 20170213. #' - Rabe-Hesketh, S., and Skrondal, A. (2012). Multilevel and longitudinal #' modeling using Stata (3rd ed). College Station, Tex: Stata Press #' Publication. #' - Raudenbush, S. W., and Bryk, A. S. (2002). Hierarchical linear models: #' applications and data analysis methods (2nd ed). Thousand Oaks: Sage #' Publications. #' #' @inheritSection r2_nakagawa Supported models and model families #' #' @details #' ## Interpretation #' The ICC can be interpreted as "the proportion of the variance explained by #' the grouping structure in the population". The grouping structure entails #' that measurements are organized into groups (e.g., test scores in a school #' can be grouped by classroom if there are multiple classrooms and each #' classroom was administered the same test) and ICC indexes how strongly #' measurements in the same group resemble each other. This index goes from 0, #' if the grouping conveys no information, to 1, if all observations in a group #' are identical (_Gelman and Hill, 2007, p. 258_). In other word, the ICC - #' sometimes conceptualized as the measurement repeatability - "can also be #' interpreted as the expected correlation between two randomly drawn units #' that are in the same group" _(Hox 2010: 15)_, although this definition might #' not apply to mixed models with more complex random effects structures. The #' ICC can help determine whether a mixed model is even necessary: an ICC of #' zero (or very close to zero) means the observations within clusters are no #' more similar than observations from different clusters, and setting it as a #' random factor might not be necessary. #' #' ## Difference with R2 #' The coefficient of determination R2 (that can be computed with [`r2()`]) #' quantifies the proportion of variance explained by a statistical model, but #' its definition in mixed model is complex (hence, different methods to compute #' a proxy exist). ICC is related to R2 because they are both ratios of #' variance components. More precisely, R2 is the proportion of the explained #' variance (of the full model), while the ICC is the proportion of explained #' variance that can be attributed to the random effects. In simple cases, the #' ICC corresponds to the difference between the *conditional R2* and the #' *marginal R2* (see [`r2_nakagawa()`]). #' #' ## Calculation #' The ICC is calculated by dividing the random effect variance, #' \ifelse{html}{\out{σ2i}}{\eqn{\sigma^2_i}}, by #' the total variance, i.e. the sum of the random effect variance and the #' residual variance, \ifelse{html}{\out{σ2ε}}{\eqn{\sigma^2_\epsilon}}. #' #' ## Adjusted and unadjusted ICC #' `icc()` calculates an adjusted and an unadjusted ICC, which both take all #' sources of uncertainty (i.e. of *all random effects*) into account. While #' the *adjusted ICC* only relates to the random effects, the *unadjusted ICC* #' also takes the fixed effects variances into account, more precisely, the #' fixed effects variance is added to the denominator of the formula to #' calculate the ICC (see _Nakagawa et al. 2017_). Typically, the *adjusted* #' ICC is of interest when the analysis of random effects is of interest. #' `icc()` returns a meaningful ICC also for more complex random effects #' structures, like models with random slopes or nested design (more than two #' levels) and is applicable for models with other distributions than Gaussian. #' For more details on the computation of the variances, see #' `?insight::get_variance`. #' #' ## ICC for unconditional and conditional models #' Usually, the ICC is calculated for the null model ("unconditional model"). #' However, according to _Raudenbush and Bryk (2002)_ or #' _Rabe-Hesketh and Skrondal (2012)_ it is also feasible to compute the #' ICC for full models with covariates ("conditional models") and compare how #' much, e.g., a level-2 variable explains the portion of variation in the #' grouping structure (random intercept). #' #' ## ICC for specific group-levels #' The proportion of variance for specific levels related to the overall model #' can be computed by setting `by_group = TRUE`. The reported ICC is #' the variance for each (random effect) group compared to the total #' variance of the model. For mixed models with a simple random intercept, #' this is identical to the classical (adjusted) ICC. #' #' ## Variance decomposition for brms-models #' If `model` is of class `brmsfit`, `icc()` might fail due to the large #' variety of models and families supported by the **brms** package. In such #' cases, `variance_decomposition()` is an alternative ICC measure. The function #' calculates a variance decomposition based on the posterior predictive #' distribution. In this case, first, the draws from the posterior predictive #' distribution *not conditioned* on group-level terms #' (`posterior_predict(..., re_formula = NA)`) are calculated as well as draws #' from this distribution *conditioned* on *all random effects* (by default, #' unless specified else in `re_formula`) are taken. Then, second, the variances #' for each of these draws are calculated. The "ICC" is then the ratio between #' these two variances. This is the recommended way to analyse #' random-effect-variances for non-Gaussian models. It is then possible to #' compare variances across models, also by specifying different group-level #' terms via the `re_formula`-argument. #' #' Sometimes, when the variance of the posterior predictive distribution is #' very large, the variance ratio in the output makes no sense, e.g. because #' it is negative. In such cases, it might help to use `robust = TRUE`. #' #' @examplesIf require("lme4") #' model <- lme4::lmer(Sepal.Length ~ Petal.Length + (1 | Species), data = iris) #' icc(model) #' #' # ICC for specific group-levels #' data(sleepstudy, package = "lme4") #' set.seed(12345) #' sleepstudy$grp <- sample(1:5, size = 180, replace = TRUE) #' sleepstudy$subgrp <- NA #' for (i in 1:5) { #' filter_group <- sleepstudy$grp == i #' sleepstudy$subgrp[filter_group] <- #' sample(1:30, size = sum(filter_group), replace = TRUE) #' } #' model <- lme4::lmer( #' Reaction ~ Days + (1 | grp / subgrp) + (1 | Subject), #' data = sleepstudy #' ) #' icc(model, by_group = TRUE) #' @export icc <- function(model, by_group = FALSE, tolerance = 1e-05, ci = NULL, iterations = 100, ci_method = NULL, null_model = NULL, approximation = "lognormal", model_component = NULL, verbose = TRUE, ...) { # special handling for smicd::semLme() if (inherits(model, "sem") && inherits(model, "lme")) { return(model$icc) } if (insight::is_multivariate(model)) { if (inherits(model, "brmsfit")) { return(variance_decomposition(model)) } else { if (verbose) { insight::format_warning( "Multiple response models not yet supported. You may use `performance::variance_decomposition()`." ) } return(NULL) } } if (!insight::is_mixed_model(model)) { if (verbose) { insight::format_warning("`model` has no random effects.") } return(NULL) } # calculate random effect variances vars <- .compute_random_vars( model, tolerance = tolerance, null_model = null_model, approximation = approximation, model_component = model_component, verbose = verbose ) # return if ICC couldn't be computed if (is.null(vars) || all(is.na(vars))) { return(vars) } # Calculate ICC values by groups if (isTRUE(by_group)) { # with random slopes, icc is inaccurate if (!is.null(insight::find_random_slopes(model)) && verbose) { insight::format_alert( "Model contains random slopes. Cannot compute accurate ICCs by group factors." ) } if (!is.null(ci) && !is.na(ci) && verbose) { insight::format_alert("Confidence intervals are not yet supported for `by_group = TRUE`.") } # icc per group factor with reference to overall model icc_overall <- vars$var.intercept / (vars$var.random + vars$var.residual) out <- data.frame( Group = names(icc_overall), ICC = unname(icc_overall), stringsAsFactors = FALSE ) # iccs between groups # n_grps <- length(vars$var.intercept) # level_combinations <- utils::combn(1:n_grps, m = n_grps - 1, simplify = FALSE) # icc_grp <- sapply( # level_combinations, # function(v) { # vars$var.intercept[v[1]] / (vars$var.intercept[v[1]] + vars$var.intercept[v[2]]) # } # ) # # out2 <- data.frame( # Group1 = group_names[sapply(level_combinations, function(i) i[1])], # Group2 = group_names[sapply(level_combinations, function(i) i[2])], # ICC = unname(icc_grp), # stringsAsFactors = FALSE # ) class(out) <- c("icc_by_group", class(out)) } else { # Calculate ICC values icc_adjusted <- vars$var.random / (vars$var.random + vars$var.residual) icc_unadjusted <- vars$var.random / (vars$var.fixed + vars$var.random + vars$var.residual) out <- data.frame( ICC_adjusted = icc_adjusted, ICC_conditional = icc_unadjusted, ICC_unadjusted = icc_unadjusted ) # check if CIs are requested, and compute bootstrapped CIs if (!is.null(ci) && !is.na(ci)) { # this is experimental! if (identical(ci_method, "analytical")) { result <- .safe(.analytical_icc_ci(model, ci)) if (is.null(result)) { icc_ci_adjusted <- icc_ci_unadjusted <- NA } else { icc_ci_adjusted <- result$ICC_adjusted icc_ci_unadjusted <- result$ICC_unadjusted } } else { result <- .bootstrap_icc(model, iterations, tolerance, ci_method, ...) # CI for adjusted ICC icc_ci_adjusted <- as.vector(result$t[, 1]) icc_ci_adjusted <- icc_ci_adjusted[!is.na(icc_ci_adjusted)] # validation check if (length(icc_ci_adjusted) > 0) { icc_ci_adjusted <- bayestestR::eti(icc_ci_adjusted, ci = ci) } else { icc_ci_adjusted <- NA } # CI for unadjusted ICC icc_ci_unadjusted <- as.vector(result$t[, 2]) icc_ci_unadjusted <- icc_ci_unadjusted[!is.na(icc_ci_unadjusted)] # validation check if (length(icc_ci_unadjusted) > 0) { icc_ci_unadjusted <- bayestestR::eti(icc_ci_unadjusted, ci = ci) } else { icc_ci_unadjusted <- NA } if ((all(is.na(icc_ci_adjusted)) || all(is.na(icc_ci_unadjusted))) && verbose) { insight::format_warning( "Could not compute confidence intervals for ICC. Try `ci_method = \"simple\"." ) } } out_ci <- data.frame( ICC_adjusted = c(CI_low = icc_ci_adjusted$CI_low, CI_high = icc_ci_adjusted$CI_high), ICC_conditional = c(CI_low = icc_ci_unadjusted$CI_low, CI_high = icc_ci_unadjusted$CI_high), ICC_unadjusted = c(CI_low = icc_ci_unadjusted$CI_low, CI_high = icc_ci_unadjusted$CI_high) ) out <- rbind(out, out_ci) attr(out, "ci") <- ci } class(out) <- c("icc", "data.frame") } out } #' @rdname icc #' @export variance_decomposition <- function(model, re_formula = NULL, robust = TRUE, ci = 0.95, ...) { if (!inherits(model, "brmsfit")) { insight::format_error("Only models from package `brms` are supported.") } mi <- insight::model_info(model) # for multivariate response models, we need a more complicated check... if (insight::is_multivariate(model)) { resp <- insight::find_response(model) is.mixed <- unlist(lapply(resp, function(i) mi[[i]]$is_mixed), use.names = FALSE) if (!any(is.mixed)) { insight::format_warning("`model` has no random effects.") return(NULL) } } else if (!insight::is_mixed_model(model)) { insight::format_warning("`model` has no random effects.") return(NULL) } insight::check_if_installed("brms") PPD <- brms::posterior_predict(model, re_formula = re_formula, summary = FALSE, ...) var_total <- apply(PPD, MARGIN = 1, FUN = stats::var) PPD_0 <- brms::posterior_predict(model, re_formula = NA, summary = FALSE, ...) var_rand_intercept <- apply(PPD_0, MARGIN = 1, FUN = stats::var) if (robust) { fun <- get("median", asNamespace("stats")) } else { fun <- get("mean", asNamespace("base")) } var_icc <- var_rand_intercept / var_total var_residual <- var_total - var_rand_intercept ci_icc <- rev(1 - stats::quantile(var_rand_intercept / var_total, probs = c((1 - ci) / 2, (1 + ci) / 2))) result <- structure( class = "icc_decomposed", list( ICC_decomposed = 1 - fun(var_icc), ICC_CI = ci_icc ) ) attr(result, "var_rand_intercept") <- fun(var_rand_intercept) attr(result, "var_residual") <- fun(var_residual) attr(result, "var_total") <- fun(var_total) attr(result, "ci.var_rand_intercept") <- bayestestR::ci(var_rand_intercept, ci = ci) attr(result, "ci.var_residual") <- bayestestR::ci(var_residual, ci = ci) attr(result, "ci.var_total") <- bayestestR::ci(var_total, ci = ci) attr(result, "ci") <- ci attr(result, "re.form") <- re_formula attr(result, "ranef") <- model$ranef$group[1] # remove data attr(attr(result, "ci.var_rand_intercept"), "data") <- NULL attr(attr(result, "ci.var_residual"), "data") <- NULL attr(attr(result, "ci.var_total"), "data") <- NULL result } # methods ------------------------------ #' @export as.data.frame.icc <- function(x, row.names = NULL, optional = FALSE, ...) { data.frame( ICC_adjusted = x$ICC_adjusted, ICC_unadjusted = x$ICC_unadjusted, stringsAsFactors = FALSE, row.names = row.names, optional = optional, ... ) } #' @export print.icc <- function(x, digits = 3, ...) { insight::print_color("# Intraclass Correlation Coefficient\n\n", "blue") out <- c( sprintf(" Adjusted ICC: %.*f", digits, x$ICC_adjusted[1]), sprintf(" Unadjusted ICC: %.*f", digits, x$ICC_unadjusted[1]) ) # add CI if (length(x$ICC_adjusted) == 3) { out[1] <- .add_r2_ci_to_print(out[1], x$ICC_adjusted[2], x$ICC_adjusted[3], digits = digits) } if (length(x$ICC_unadjusted) == 3) { out[2] <- .add_r2_ci_to_print(out[2], x$ICC_unadjusted[2], x$ICC_unadjusted[3], digits = digits) } # separate lines for multiple R2 out <- paste(out, collapse = "\n") cat(out) cat("\n") invisible(x) } #' @export print.icc_by_group <- function(x, digits = 3, ...) { insight::print_color("# ICC by Group\n\n", "blue") cat(insight::export_table(x, digits = digits)) invisible(x) } #' @export print.icc_decomposed <- function(x, digits = 2, ...) { # print model information cat("# Random Effect Variances and ICC\n\n") reform <- attr(x, "re.form", exact = TRUE) if (is.null(reform)) { reform <- "all random effects" } else { reform <- insight::safe_deparse(reform) } cat(sprintf("Conditioned on: %s\n\n", reform)) prob <- attr(x, "ci", exact = TRUE) cat(insight::print_color("## Variance Ratio (comparable to ICC)\n", "blue")) icc.val <- sprintf("%.*f", digits, x$ICC_decomposed) ci.icc.lo <- sprintf("%.*f", digits, x$ICC_CI[1]) ci.icc.hi <- sprintf("%.*f", digits, x$ICC_CI[2]) # ICC cat(sprintf( "Ratio: %s CI %i%%: [%s %s]\n", icc.val, as.integer(round(prob * 100)), ci.icc.lo, ci.icc.hi )) cat(insight::print_color("\n## Variances of Posterior Predicted Distribution\n", "blue")) null.model <- sprintf("%.*f", digits, attr(x, "var_rand_intercept", exact = TRUE)) ci.null <- attr(x, "ci.var_rand_intercept", exact = TRUE) ci.null.lo <- sprintf("%.*f", digits, ci.null$CI_low) ci.null.hi <- sprintf("%.*f", digits, ci.null$CI_high) full.model <- sprintf("%.*f", digits, attr(x, "var_total", exact = TRUE)) ci.full <- attr(x, "ci.var_total", exact = TRUE) ci.full.lo <- sprintf("%.*f", digits, ci.full$CI_low) ci.full.hi <- sprintf("%.*f", digits, ci.full$CI_high) ml <- max(nchar(null.model), nchar(full.model)) ml.ci <- max(nchar(ci.full.lo), nchar(ci.null.lo)) mh.ci <- max(nchar(ci.full.hi), nchar(ci.null.hi)) # Conditioned on fixed effects cat(sprintf( "Conditioned on fixed effects: %*s CI %i%%: [%*s %*s]\n", ml, null.model, as.integer(round(prob * 100)), ml.ci, ci.null.lo, mh.ci, ci.null.hi )) # Conditioned on random effects cat(sprintf( "Conditioned on rand. effects: %*s CI %i%%: [%*s %*s]\n", ml, full.model, as.integer(round(prob * 100)), ml.ci, ci.full.lo, mh.ci, ci.full.hi )) cat(insight::print_color("\n## Difference in Variances\n", "red")) res <- sprintf("%.*f", digits, attr(x, "var_residual", exact = TRUE)) ci.res <- attr(x, "ci.var_residual", exact = TRUE) ci.res.lo <- sprintf("%.*f", digits, ci.res$CI_low) ci.res.hi <- sprintf("%.*f", digits, ci.res$CI_high) # ICC cat(sprintf( "Difference: %s CI %i%%: [%s %s]\n", res, as.integer(round(prob * 100)), ci.res.lo, ci.res.hi )) invisible(x) } # helper ----------------- .compute_random_vars <- function(model, tolerance, components = c("var.fixed", "var.random", "var.residual"), name_fun = "icc()", name_full = "ICC", null_model = NULL, model_component = NULL, approximation = "lognormal", verbose = TRUE) { vars <- tryCatch( insight::get_variance(model, name_fun = name_fun, name_full = name_full, tolerance = tolerance, null_model = null_model, approximation = approximation, model_component = model_component, verbose = verbose ), error = function(e) { if (inherits(e, c("simpleError", "error")) && verbose) { insight::print_color(e$message, "red") cat("\n") } NULL } ) if (is.null(vars) || all(is.na(vars))) { return(NA) } # check if we have successfully computed all variance components... check_elements <- sapply(components, function(.i) !is.null(vars[[.i]])) if (!all(check_elements)) { return(NA) } vars } # bootstrapping ------------------ # bootstrapping using package "boot" .boot_icc_fun <- function(data, indices, model, tolerance) { d <- data[indices, ] # allows boot to select sample fit <- suppressWarnings(suppressMessages(stats::update(model, data = d))) vars <- .compute_random_vars( fit, tolerance, verbose = isTRUE(getOption("easystats_errors", FALSE)) ) if (is.null(vars) || all(is.na(vars))) { return(c(NA, NA)) } c( vars$var.random / (vars$var.random + vars$var.residual), vars$var.random / (vars$var.fixed + vars$var.random + vars$var.residual) ) } # bootstrapping using "lme4::bootMer" .boot_icc_fun_lme4 <- function(model) { vars <- .compute_random_vars( model, tolerance = 1e-10, verbose = isTRUE(getOption("easystats_errors", FALSE)) ) if (is.null(vars) || all(is.na(vars))) { return(c(NA, NA)) } c( vars$var.random / (vars$var.random + vars$var.residual), vars$var.random / (vars$var.fixed + vars$var.random + vars$var.residual) ) } # prepare arguments for "lme4::bootMer" .do_lme4_bootmer <- function(model, .boot_fun, iterations, dots) { insight::check_if_installed(c("lme4", "boot")) my_args <- list( model, .boot_fun, nsim = iterations, type = "parametric", parallel = "no", use.u = FALSE, ncpus = 1 ) # add/overwrite dot-args if (!is.null(dots[["use.u"]])) { my_args$use.u <- dots[["use.u"]] } if (!is.null(dots[["re.form"]])) { my_args$re.form <- dots[["re.form"]] } if (!is.null(dots[["type"]])) { my_args$type <- dots[["type"]] if (my_args$type == "semiparametric") { my_args$use.u <- TRUE } } if (!is.null(dots[["parallel"]])) { my_args$parallel <- dots[["parallel"]] } if (!is.null(dots[["ncpus"]])) { my_args$ncpus <- dots[["ncpus"]] } # bootsrap do.call(lme4::bootMer, args = my_args) } # main function for bootstrapping .bootstrap_icc <- function(model, iterations, tolerance, ci_method = NULL, ...) { if (inherits(model, c("merMod", "lmerMod", "glmmTMB")) && !identical(ci_method, "boot")) { result <- .do_lme4_bootmer( model, .boot_icc_fun_lme4, iterations, dots = list(...) ) } else { insight::check_if_installed("boot") result <- boot::boot( data = insight::get_data(model, verbose = FALSE), statistic = .boot_icc_fun, R = iterations, sim = "ordinary", model = model, tolerance = tolerance ) } result } .analytical_icc_ci <- function(model, ci = 0.95, fun = "icc", ...) { alpha <- 1 - ci n <- insight::n_obs(model) df_int <- if (insight::has_intercept(model)) { 1 } else { 0 } model_rank <- tryCatch( if (is.null(model$rank)) { insight::n_parameters(model) - df_int } else { model$rank - df_int }, error = function(e) insight::n_parameters(model) - df_int ) if (identical(fun, "icc")) { model_icc <- icc(model, ci = NULL, verbose = FALSE, ...) } else { model_icc <- r2_nakagawa(model, ci = NULL, verbose = FALSE, ...) } out <- lapply(model_icc, function(.icc) { ci_low <- stats::uniroot( .pRsq, c(0.00001, 0.99999), R2_obs = as.vector(.icc), p = model_rank, nobs = n, alpha = 1 - alpha / 2 )$root ci_high <- stats::uniroot( .pRsq, c(0.00001, 0.99999), R2_obs = as.vector(.icc), p = model_rank, nobs = n, alpha = alpha / 2 )$root data.frame(CI_low = ci_low, CI_high = ci_high) }) names(out) <- names(model_icc) out } performance/R/helpers.R0000644000176200001440000000416114645233345014554 0ustar liggesusers# small wrapper around this commonly used try-catch .safe <- function(code, on_error = NULL) { if (isTRUE(getOption("easystats_errors", FALSE)) && is.null(on_error)) { code } else { tryCatch(code, error = function(e) on_error) } } .get_BIC <- function(x, estimator = "ML") { # check ML estimator if (missing(estimator) && inherits(x, "lmerMod")) { estimator <- "REML" } REML <- identical(estimator, "REML") if (inherits(x, c("vgam", "vglm"))) { insight::check_if_installed("VGAM") out <- .adjust_ic_jacobian(x, VGAM::BIC(x)) } else if (inherits(x, "bayesx")) { out <- .adjust_ic_jacobian(x, stats::BIC(x)[["BIC"]]) } else { out <- .safe( stats::BIC(insight::get_loglikelihood(x, check_response = TRUE, REML = REML, verbose = FALSE)) ) # when `get_loglikelihood()` does not work, `stats::BIC` sometimes still works (e.g., `fixest`) if (is.null(out)) { out <- .safe(stats::BIC(x)) } } out } .std <- function(x) { if (!is.numeric(x)) { return(x) } # remove missings tmp <- x[!is.na(x)] # standardize tmp <- (tmp - mean(tmp)) / stats::sd(tmp) # and fill in values in original vector x[!is.na(x)] <- tmp x } # recode numeric vector, so lowest value stats with 0 # factors are coerced to numeric .recode_to_zero <- function(x) { # check if factor if (is.factor(x) || is.character(x)) { # try to convert to numeric x <- datawizard::to_numeric(x, dummy_factors = FALSE, preserve_levels = TRUE) } # retrieve lowest category minval <- min(x, na.rm = TRUE) sapply(x, function(y) y - minval) } .get_sigma <- function(model, verbose = TRUE) { s <- insight::get_sigma(model, ci = NULL, verbose = verbose) if (is.null(s)) { NULL } else { as.numeric(s) } } # functions to check if necessary default argument was provided ------------ .is_model_valid <- function(model) { if (missing(model) || is.null(model)) { insight::format_error( "You must provide a model-object. Argument `model` cannot be missing or `NULL`." ) } } performance/R/model_performance.rma.R0000644000176200001440000000736514620351763017360 0ustar liggesusers#' Performance of Meta-Analysis Models #' #' Compute indices of model performance for meta-analysis model from the #' **metafor** package. #' #' @param model A `rma` object as returned by `metafor::rma()`. #' @param metrics Can be `"all"` or a character vector of metrics to be #' computed (some of `c("AIC", "BIC", "I2", "H2", "TAU2", "R2", #' "CochransQ", "QE", "Omnibus", "QM")`). #' @param ... Arguments passed to or from other methods. #' @inheritParams model_performance.lm #' @inheritParams model_performance.merMod #' #' @return A data frame (with one row) and one column per "index" (see #' `metrics`). #' #' @details \subsection{Indices of fit}{ #' #' - **AIC** Akaike's Information Criterion, see `?stats::AIC` #' #' - **BIC** Bayesian Information Criterion, see `?stats::BIC` #' #' - **I2**: For a random effects model, `I2` estimates (in #' percent) how much of the total variability in the effect size estimates #' can be attributed to heterogeneity among the true effects. For a #' mixed-effects model, `I2` estimates how much of the unaccounted #' variability can be attributed to residual heterogeneity. #' #' - **H2**: For a random-effects model, `H2` estimates the #' ratio of the total amount of variability in the effect size estimates to #' the amount of sampling variability. For a mixed-effects model, `H2` #' estimates the ratio of the unaccounted variability in the effect size #' estimates to the amount of sampling variability. #' #' - **TAU2**: The amount of (residual) heterogeneity in the random #' or mixed effects model. #' #' - **CochransQ (QE)**: Test for (residual) Heterogeneity. Without #' moderators in the model, this is simply Cochran's *Q*-test. #' #' - **Omnibus (QM)**: Omnibus test of parameters. #' #' - **R2**: Pseudo-R2-statistic, which indicates the amount of #' heterogeneity accounted for by the moderators included in a fixed-effects #' model. #' #' See the documentation for `?metafor::fitstats`. #' } #' #' @examplesIf require("metafor") && require("metadat") #' data(dat.bcg, package = "metadat") #' dat <- metafor::escalc( #' measure = "RR", #' ai = tpos, #' bi = tneg, #' ci = cpos, #' di = cneg, #' data = dat.bcg #' ) #' model <- metafor::rma(yi, vi, data = dat, method = "REML") #' model_performance(model) #' @export model_performance.rma <- function(model, metrics = "all", estimator = "ML", verbose = TRUE, ...) { if (all(metrics == "all")) { metrics <- c("AIC", "BIC", "I2", "H2", "TAU2", "COCHRANSQ", "OMNIBUS", "R2") } else if (all(metrics == "common")) { metrics <- c("AIC", "BIC", "I2") } out <- list() attrib <- list() s <- summary(model) if ("AIC" %in% toupper(metrics)) { out$AIC <- performance_aic(model, estimator = estimator) } if ("BIC" %in% toupper(metrics)) { out$BIC <- .get_BIC(model) } if ("I2" %in% toupper(metrics)) { out$I2 <- s$I2 / 100 } if ("H2" %in% toupper(metrics)) { out$H2 <- s$H2 } if ("TAU2" %in% toupper(metrics)) { out$TAU2 <- s$tau2 } if (any(c("QE", "COCHRANSQ") %in% toupper(metrics))) { out$CochransQ <- s$QE out$p_CochransQ <- s$QEp out$df_error <- .safe(stats::df.residual(model)) } if (any(c("QM", "OMNIBUS") %in% toupper(metrics))) { out$Omnibus <- s$QM out$p_Omnibus <- s$QMp } if ("R2" %in% toupper(metrics)) { R2 <- r2(model) if (!is.null(R2)) { attrib$r2 <- attributes(R2) out <- c(out, R2) } } out <- as.data.frame(insight::compact_list(out)) row.names(out) <- NULL class(out) <- c("performance_model", class(out)) # Add attributes attributes(out) <- c(attributes(out), attrib) out } performance/R/test_bf.R0000644000176200001440000000524514736731423014545 0ustar liggesusers#' @rdname test_performance #' @export test_bf <- function(...) { UseMethod("test_bf") } #' @rdname test_performance #' @export test_bf.default <- function(..., reference = 1, text_length = NULL) { # Attribute class to list and get names from the global environment my_objects <- insight::ellipsis_info(..., only_models = TRUE) names(my_objects) <- match.call(expand.dots = FALSE)[["..."]] # validation checks (will throw error if non-valid objects) .test_performance_checks(objects = my_objects, multiple = FALSE) if (length(my_objects) == 1 && isTRUE(insight::is_model(my_objects))) { insight::format_error( "`test_bf()` is designed to compare multiple models together. For a single model, you might want to run `bayestestR::bf_parameters()` instead." # nolint ) } # If a suitable class is found, run the more specific method on it if (inherits(my_objects, c("ListNestedRegressions", "ListNonNestedRegressions", "ListLavaan"))) { test_bf(my_objects, reference = reference, text_length = text_length) } else { insight::format_error("The models cannot be compared for some reason :/") } } #' @export test_bf.ListModels <- function(objects, reference = 1, text_length = NULL, ...) { if (.test_bf_areAllBayesian(objects) == "mixed") { insight::format_error("You cannot mix Bayesian and non-Bayesian models in `test_bf()`.") } # Adapt reference but keep original input if (reference == "sequential") { ref <- 1 } else { ref <- reference } rez <- bayestestR::bayesfactor_models(objects, denominator = ref) # check for log-BF if (!is.null(rez$log_BF)) { rez$BF <- exp(rez$log_BF) } row.names(rez) <- NULL # Adjust BFs for sequential testing if (reference == "sequential") { # TODO: Double check that formula and whether it works for increasing and # decreasing order. # For increasing rez$BF <- exp(c(NA, diff(log(rez$BF)))) # For decreasing # ref <- nrow(rez) # rez$BF <- exp(c(-diff(log(rez$BF)), NA)) } else { rez$BF[ref] <- NA } # add log-BF rez$log_BF <- log(rez$BF) # Replace denominator attr(rez, "denominator") <- ref attr(rez, "text_length") <- text_length class(rez) <- c("bayesfactor_models", "see_bayesfactor_models", class(rez)) rez } # Helpers ----------------------------------------------------------------- .test_bf_areAllBayesian <- function(objects) { bayesian_models <- sapply(objects, function(i) isTRUE(insight::model_info(i)$is_bayesian)) if (all(bayesian_models)) { "yes" } else if (any(bayesian_models)) { "mixed" } else { "no" } } performance/R/check_homogeneity.R0000644000176200001440000001377114741711371016602 0ustar liggesusers#' Check model for homogeneity of variances #' #' Check model for homogeneity of variances between groups described #' by independent variables in a model. #' #' @param x A linear model or an ANOVA object. #' @param method Name of the method (underlying test) that should be performed #' to check the homogeneity of variances. May either be `"levene"` for #' Levene's Test for Homogeneity of Variance, `"bartlett"` for the #' Bartlett test (assuming normal distributed samples or groups), #' `"fligner"` for the Fligner-Killeen test (rank-based, non-parametric #' test), or `"auto"`. In the latter case, Bartlett test is used if the #' model response is normal distributed, else Fligner-Killeen test is used. #' @param ... Arguments passed down to `car::leveneTest()`. #' #' @return Invisibly returns the p-value of the test statistics. A p-value < #' 0.05 indicates a significant difference in the variance between the groups. #' #' @note There is also a [`plot()`-method](https://easystats.github.io/see/articles/performance.html) #' implemented in the \href{https://easystats.github.io/see/}{\pkg{see}-package}. #' #' @family functions to check model assumptions and and assess model quality #' #' @examples #' model <<- lm(len ~ supp + dose, data = ToothGrowth) #' check_homogeneity(model) #' #' # plot results #' @examplesIf insight::check_if_installed("see", minimum_version = "0.9.1", quietly = TRUE) #' result <- check_homogeneity(model) #' plot(result) #' @export check_homogeneity <- function(x, method = c("bartlett", "fligner", "levene", "auto"), ...) { UseMethod("check_homogeneity") } # default ------------------------- #' @export check_homogeneity.default <- function(x, method = c("bartlett", "fligner", "levene", "auto"), ...) { method <- match.arg(method) resp <- insight::find_response(x) pred <- insight::find_predictors(x, component = "conditional", flatten = TRUE) # edge case, whitespace in name, so surround with backticks ws_pred <- pred != make.names(pred) if (any(ws_pred)) { pred[ws_pred] <- paste0("`", pred[ws_pred], "`") } if (length(pred) > 1) { pred <- paste0("interaction(", toString(pred), ")", collapse = "") } f <- stats::as.formula(sprintf("%s ~ %s", resp, pred)) if (method == "auto") { check <- tryCatch( { utils::capture.output(p <- check_normality(x)) # nolint p }, error = function(e) { NULL } ) if (is.null(check)) { insight::print_color("'check_homogeneity()' cannot perform check for normality. Please specify the 'method'-argument for the test of equal variances.\n", "red") # nolint return(NULL) } method <- ifelse(check < 0.05, "fligner", "bartlett") } if (method == "fligner") { # nolint r <- stats::fligner.test(f, data = insight::get_data(x, verbose = FALSE)) p.val <- r$p.value } else if (method == "bartlett") { r <- stats::bartlett.test(f, data = insight::get_data(x, verbose = FALSE)) p.val <- r$p.value } else if (method == "levene") { insight::check_if_installed("car") r <- car::leveneTest(x, ...) p.val <- r$`Pr(>F)` } method.string <- switch(method, bartlett = "Bartlett Test", fligner = "Fligner-Killeen Test", levene = "Levene's Test" ) attr(p.val, "data") <- x attr(p.val, "object_name") <- insight::safe_deparse_symbol(substitute(x)) attr(p.val, "method") <- method.string class(p.val) <- unique(c("check_homogeneity", "see_check_homogeneity", class(p.val))) p.val } # methods ----------------------- #' @export print.check_homogeneity <- function(x, ...) { method.string <- attributes(x)$method if (is.na(x)) { insight::format_warning(paste0("Could not perform ", method.string, ".")) invisible(NULL) } else if (x < 0.05) { insight::print_color(sprintf("Warning: Variances differ between groups (%s, p = %.3f).\n", method.string, x), "red") } else { insight::print_color(sprintf("OK: There is not clear evidence for different variances across groups (%s, p = %.3f).\n", method.string, x), "green") # nolint } invisible(x) } #' @export plot.check_homogeneity <- function(x, ...) { insight::check_if_installed("see", "for homogeneity plots") NextMethod() } # other classes ----------------------------- #' @rdname check_homogeneity #' @export check_homogeneity.afex_aov <- function(x, method = "levene", ...) { insight::check_if_installed("car") if (tolower(method) != "levene") { insight::format_alert("Only Levene's test for homogeneity supported for `afex_aov()`.") } if (length(attr(x, "between")) == 0) { insight::format_error("Levene test is only aplicable to ANOVAs with between-subjects factors.") } long_data <- x$data$long # Use this to also get id column dv <- attr(x, "dv") id <- attr(x, "id") between <- names(attr(x, "between")) is_covar <- vapply(attr(x, "between"), is.null, logical(1)) ag_data <- stats::aggregate(long_data[, dv], long_data[, c(between, id)], mean) colnames(ag_data)[length(c(between, id)) + 1] <- dv if (any(is_covar)) { insight::format_alert( "Levene's test is not appropriate with quantitative explanatory variables. Testing assumption of homogeneity among factor groups only." # nolint ) # ## TODO maybe add as option? # warning("Testing assumption of homogeneity on residualzied data among factor groups only.", call. = FALSE) # ag_data[dv] <- stats::residuals(stats::lm(ag_data[,dv] ~ as.matrix(ag_data[between[is_covar]]))) between <- between[!is_covar] } form <- stats::formula(paste0(dv, "~", paste(between, collapse = "*"))) test <- car::leveneTest(form, ag_data, center = mean, ...) p.val <- test[1, "Pr(>F)"] attr(p.val, "object_name") <- insight::safe_deparse_symbol(substitute(x)) attr(p.val, "method") <- "Levene's Test" class(p.val) <- unique(c("check_homogeneity", "see_check_homogeneity", class(p.val))) p.val } performance/R/r2_kl.R0000644000176200001440000000234414570063447014125 0ustar liggesusers#' @title Kullback-Leibler R2 #' @name r2_kullback #' #' @description Calculates the Kullback-Leibler-divergence-based #' R2 for generalized linear models. #' #' @param model A generalized linear model. #' @param adjust Logical, if `TRUE` (the default), the adjusted R2 value is #' returned. #' @param ... Additional arguments. Currently not used. #' #' @return A named vector with the R2 value. #' #' @examples #' model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") #' r2_kullback(model) #' @references #' Cameron, A. C. and Windmeijer, A. G. (1997) An R-squared measure of goodness #' of fit for some common nonlinear regression models. Journal of Econometrics, #' 77: 329-342. #' #' @export r2_kullback <- function(model, ...) { UseMethod("r2_kullback") } #' @rdname r2_kullback #' @export r2_kullback.glm <- function(model, adjust = TRUE, ...) { if (adjust) { adj <- model$df.null / model$df.residual } else { adj <- 1 } klr2 <- 1 - (model$deviance / model$null.deviance) * adj names(klr2) <- "Kullback-Leibler R2" klr2 } #' @export r2_kullback.default <- function(model, ...) { insight::format_error("This function only works for objects of class `glm`.") } performance/R/r2_efron.R0000644000176200001440000000263114335664246014632 0ustar liggesusers#' @title Efron's R2 #' @name r2_efron #' #' @description Calculates Efron's pseudo R2. #' #' @param model Generalized linear model. #' #' @return The R2 value. #' #' @details #' Efron's R2 is calculated by taking the sum of the squared model residuals, #' divided by the total variability in the dependent variable. This R2 equals #' the squared correlation between the predicted values and actual values, #' however, note that model residuals from generalized linear models are not #' generally comparable to those of OLS. #' #' @references #' Efron, B. (1978). Regression and ANOVA with zero-one data: Measures of #' residual variation. Journal of the American Statistical Association, 73, #' 113-121. #' #' @examples #' ## Dobson (1990) Page 93: Randomized Controlled Trial: #' counts <- c(18, 17, 15, 20, 10, 20, 25, 13, 12) # #' outcome <- gl(3, 1, 9) #' treatment <- gl(3, 3) #' model <- glm(counts ~ outcome + treatment, family = poisson()) #' #' r2_efron(model) #' @export r2_efron <- function(model) { UseMethod("r2_efron") } #' @export r2_efron.default <- function(model) { .r2_efron(model) } .r2_efron <- function(model) { y_hat <- stats::predict(model, type = "response") y <- datawizard::to_numeric(insight::get_response(model, verbose = FALSE), dummy_factors = FALSE, preserve_levels = TRUE, lowest = 0) (1 - (sum((y - y_hat)^2)) / (sum((y - mean(y))^2))) } performance/R/check_zeroinflation.R0000644000176200001440000001466414620351763017141 0ustar liggesusers#' @title Check for zero-inflation in count models #' @name check_zeroinflation #' #' @description `check_zeroinflation()` checks whether count models are #' over- or underfitting zeros in the outcome. #' #' @param x Fitted model of class `merMod`, `glmmTMB`, `glm`, or `glm.nb` #' (package **MASS**). #' @param tolerance The tolerance for the ratio of observed and predicted #' zeros to considered as over- or underfitting zeros. A ratio #' between 1 +/- `tolerance` is considered as OK, while a ratio #' beyond or below this threshold would indicate over- or underfitting. #' @param alternative A character string specifying the alternative hypothesis. #' @param ... Arguments passed down to [`simulate_residuals()`]. This only applies #' for models with zero-inflation component, or for models of class `glmmTMB` #' from `nbinom1` or `nbinom2` family. #' #' @return A list with information about the amount of predicted and observed #' zeros in the outcome, as well as the ratio between these two values. #' #' @details If the amount of observed zeros is larger than the amount of #' predicted zeros, the model is underfitting zeros, which indicates a #' zero-inflation in the data. In such cases, it is recommended to use #' negative binomial or zero-inflated models. #' #' In case of negative binomial models, models with zero-inflation component, #' or hurdle models, the results from `check_zeroinflation()` are based on #' [`simulate_residuals()`], i.e. `check_zeroinflation(simulate_residuals(model))` #' is internally called if necessary. #' #' @section Tests based on simulated residuals: #' For certain models, resp. model from certain families, tests are based on #' simulated residuals (see [`simulate_residuals()`]). These are usually more #' accurate for testing such models than the traditionally used Pearson residuals. #' However, when simulating from more complex models, such as mixed models or #' models with zero-inflation, there are several important considerations. #' Arguments specified in `...` are passed to [`simulate_residuals()`], which #' relies on [`DHARMa::simulateResiduals()`] (and therefore, arguments in `...` #' are passed further down to _DHARMa_). The defaults in DHARMa are set on the #' most conservative option that works for all models. However, in many cases, #' the help advises to use different settings in particular situations or for #' particular models. It is recommended to read the 'Details' in #' `?DHARMa::simulateResiduals` closely to understand the implications of the #' simulation process and which arguments should be modified to get the most #' accurate results. #' #' @family functions to check model assumptions and and assess model quality #' #' @examplesIf require("glmmTMB") && require("DHARMa") #' data(Salamanders, package = "glmmTMB") #' m <- glm(count ~ spp + mined, family = poisson, data = Salamanders) #' check_zeroinflation(m) #' #' # for models with zero-inflation component, it's better to carry out #' # the check for zero-inflation using simulated residuals #' m <- glmmTMB::glmmTMB( #' count ~ spp + mined, #' ziformula = ~ mined + spp, #' family = poisson, #' data = Salamanders #' ) #' res <- simulate_residuals(m) #' check_zeroinflation(res) #' @export check_zeroinflation <- function(x, ...) { UseMethod("check_zeroinflation") } #' @rdname check_zeroinflation #' @export check_zeroinflation.default <- function(x, tolerance = 0.05, ...) { # check if we have poisson model_info <- insight::model_info(x) if (!model_info$is_count) { insight::format_error("Model must be from Poisson-family.") } # get actual zero of response obs.zero <- sum(insight::get_response(x, verbose = FALSE) == 0L) if (obs.zero == 0) { insight::print_color("Model has no observed zeros in the response variable.\n", "red") return(NULL) } # model classes not supported in DHARMa not_supported <- c("fixest", "glmx") # for models with zero-inflation component or negative binomial families, # we use simulate_residuals() if (!inherits(x, not_supported) && (model_info$is_zero_inflated || model_info$is_negbin || model_info$family == "genpois")) { # nolint if (missing(tolerance)) { tolerance <- 0.1 } return(check_zeroinflation(simulate_residuals(x, ...), tolerance = tolerance, ...)) } # get predictions of outcome mu <- stats::fitted(x) # get predicted zero-counts pred.zero <- round(sum(stats::dpois(x = 0, lambda = mu))) # proportion structure( class = "check_zi", list( predicted.zeros = pred.zero, observed.zeros = obs.zero, ratio = pred.zero / obs.zero, tolerance = tolerance ) ) } #' @rdname check_zeroinflation #' @export check_zeroinflation.performance_simres <- function(x, tolerance = 0.1, alternative = c("two.sided", "less", "greater"), ...) { alternative <- match.arg(alternative) # compute test results result <- .simres_statistics(x, statistic_fun = function(i) sum(i == 0), alternative = alternative) structure( class = "check_zi", list( predicted.zeros = round(mean(result$simulated)), observed.zeros = result$observed, ratio = mean(result$simulated) / result$observed, tolerance = tolerance, p.value = result$p ) ) } #' @export check_zeroinflation.DHARMa <- check_zeroinflation.performance_simres # methods ------------------ #' @export print.check_zi <- function(x, ...) { insight::print_color("# Check for zero-inflation\n\n", "blue") cat(sprintf(" Observed zeros: %i\n", x$observed.zeros)) cat(sprintf(" Predicted zeros: %i\n", x$predicted.zeros)) cat(sprintf(" Ratio: %.2f\n\n", x$ratio)) lower <- 1 - x$tolerance upper <- 1 + x$tolerance if (is.null(x$p.value)) { p_string <- "" } else { p_string <- paste0(" (", insight::format_p(x$p.value), ")") } if (x$ratio < lower) { message("Model is underfitting zeros (probable zero-inflation)", p_string, ".") } else if (x$ratio > upper) { message("Model is overfitting zeros", p_string, ".") } else { insight::format_alert(paste0( "Model seems ok, ratio of observed and predicted zeros is within the tolerance range", p_string, "." )) } invisible(x) } performance/R/check_singularity.R0000644000176200001440000001673214736731423016631 0ustar liggesusers#' @title Check mixed models for boundary fits #' @name check_singularity #' #' @description Check mixed models for boundary fits. #' #' @param x A mixed model. #' @param tolerance Indicates up to which value the convergence result is #' accepted. The larger `tolerance` is, the stricter the test #' will be. #' @param ... Currently not used. #' #' @return `TRUE` if the model fit is singular. #' #' @details If a model is "singular", this means that some dimensions of the #' variance-covariance matrix have been estimated as exactly zero. This #' often occurs for mixed models with complex random effects structures. #' #' "While singular models are statistically well defined (it is theoretically #' sensible for the true maximum likelihood estimate to correspond to a singular #' fit), there are real concerns that (1) singular fits correspond to overfitted #' models that may have poor power; (2) chances of numerical problems and #' mis-convergence are higher for singular models (e.g. it may be computationally #' difficult to compute profile confidence intervals for such models); (3) #' standard inferential procedures such as Wald statistics and likelihood ratio #' tests may be inappropriate." (_lme4 Reference Manual_) #' #' There is no gold-standard about how to deal with singularity and which #' random-effects specification to choose. Beside using fully Bayesian methods #' (with informative priors), proposals in a frequentist framework are: #' #' - avoid fitting overly complex models, such that the variance-covariance #' matrices can be estimated precisely enough (_Matuschek et al. 2017_) #' - use some form of model selection to choose a model that balances #' predictive accuracy and overfitting/type I error (_Bates et al. 2015_, #' _Matuschek et al. 2017_) #' - "keep it maximal", i.e. fit the most complex model consistent with the #' experimental design, removing only terms required to allow a non-singular #' fit (_Barr et al. 2013_) #' - since version 1.1.9, the **glmmTMB** package allows to use priors in a #' frequentist framework, too. One recommendation is to use a Gamma prior #' (_Chung et al. 2013_). The mean may vary from 1 to very large values #' (like `1e8`), and the shape parameter should be set to a value of 2.5. You #' can then `update()` your model with the specified prior. In **glmmTMB**, #' the code would look like this: #' ``` #' # "model" is an object of class gmmmTMB #' prior <- data.frame( #' prior = "gamma(1, 2.5)", # mean can be 1, but even 1e8 #' class = "ranef" # for random effects #' ) #' model_with_priors <- update(model, priors = prior) #' ``` #' Large values for the mean parameter of the Gamma prior have no large impact #' on the random effects variances in terms of a "bias". Thus, if `1` doesn't #' fix the singular fit, you can safely try larger values. #' #' Note the different meaning between singularity and convergence: singularity #' indicates an issue with the "true" best estimate, i.e. whether the maximum #' likelihood estimation for the variance-covariance matrix of the random #' effects is positive definite or only semi-definite. Convergence is a #' question of whether we can assume that the numerical optimization has #' worked correctly or not. #' #' @family functions to check model assumptions and and assess model quality #' #' @references #' - Bates D, Kliegl R, Vasishth S, Baayen H. Parsimonious Mixed Models. #' arXiv:1506.04967, June 2015. #' #' - Barr DJ, Levy R, Scheepers C, Tily HJ. Random effects structure for #' confirmatory hypothesis testing: Keep it maximal. Journal of Memory and #' Language, 68(3):255-278, April 2013. #' #' - Chung Y, Rabe-Hesketh S, Dorie V, Gelman A, and Liu J. 2013. "A Nondegenerate #' Penalized Likelihood Estimator for Variance Parameters in Multilevel Models." #' Psychometrika 78 (4): 685–709. \doi{10.1007/s11336-013-9328-2} #' #' - Matuschek H, Kliegl R, Vasishth S, Baayen H, Bates D. Balancing type I error #' and power in linear mixed models. Journal of Memory and Language, 94:305-315, 2017. #' #' - lme4 Reference Manual, #' #' @examplesIf require("lme4") && require("glmmTMB") #' data(sleepstudy, package = "lme4") #' set.seed(123) #' sleepstudy$mygrp <- sample(1:5, size = 180, replace = TRUE) #' sleepstudy$mysubgrp <- NA #' for (i in 1:5) { #' filter_group <- sleepstudy$mygrp == i #' sleepstudy$mysubgrp[filter_group] <- #' sample(1:30, size = sum(filter_group), replace = TRUE) #' } #' #' model <- lme4::lmer( #' Reaction ~ Days + (1 | mygrp / mysubgrp) + (1 | Subject), #' data = sleepstudy #' ) #' check_singularity(model) #' #' \dontrun{ #' # Fixing singularity issues using priors in glmmTMB #' # Example taken from `vignette("priors", package = "glmmTMB")` #' dat <- readRDS(system.file( #' "vignette_data", #' "gophertortoise.rds", #' package = "glmmTMB" #' )) #' model <- glmmTMB::glmmTMB( #' shells ~ prev + offset(log(Area)) + factor(year) + (1 | Site), #' family = poisson, #' data = dat #' ) #' # singular fit #' check_singularity(model) #' #' # impose Gamma prior on random effects parameters #' prior <- data.frame( #' prior = "gamma(1, 2.5)", # mean can be 1, but even 1e8 #' class = "ranef" # for random effects #' ) #' model_with_priors <- update(model, priors = prior) #' # no singular fit #' check_singularity(model_with_priors) #' } #' @export check_singularity <- function(x, tolerance = 1e-5, ...) { UseMethod("check_singularity") } #' @export check_singularity.merMod <- function(x, tolerance = 1e-5, ...) { insight::check_if_installed("lme4") theta <- lme4::getME(x, "theta") # diagonal elements are identifiable because they are fitted # with a lower bound of zero ... diag.element <- lme4::getME(x, "lower") == 0 any(abs(theta[diag.element]) < tolerance) } #' @export check_singularity.rlmerMod <- check_singularity.merMod #' @export check_singularity.glmmTMB <- function(x, tolerance = 1e-5, ...) { insight::check_if_installed("lme4") eigen_values <- list() vv <- lme4::VarCorr(x) for (component in c("cond", "zi")) { for (i in seq_along(vv[[component]])) { eigen_values <- c( eigen_values, list(eigen(vv[[component]][[i]], only.values = TRUE)$values) ) } } any(vapply(eigen_values, min, numeric(1), na.rm = TRUE) < tolerance) } #' @export check_singularity.glmmadmb <- check_singularity.glmmTMB #' @export check_singularity.clmm <- function(x, tolerance = 1e-5, ...) { insight::check_if_installed("ordinal") vc <- ordinal::VarCorr(x) any(sapply(vc, function(.x) any(abs(diag(.x)) < tolerance))) } #' @export check_singularity.cpglmm <- function(x, tolerance = 1e-5, ...) { insight::check_if_installed("cplm") vc <- cplm::VarCorr(x) any(sapply(vc, function(.x) any(abs(diag(.x)) < tolerance))) } #' @export check_singularity.MixMod <- function(x, tolerance = 1e-5, ...) { any(sapply(diag(x$D), function(.x) any(abs(.x) < tolerance))) } #' @export check_singularity.lme <- function(x, tolerance = 1e-5, ...) { insight::check_if_installed("nlme") any(abs(stats::na.omit(as.numeric(diag(nlme::getVarCov(x)))) < tolerance)) } #' @export check_singularity.default <- function(x, ...) { FALSE } .collapse_cond <- function(x) { if (is.list(x) && "cond" %in% names(x)) { x[["cond"]] } else { x } } performance/R/item_reliability.R0000644000176200001440000000616314561136140016435 0ustar liggesusers#' @title Reliability Test for Items or Scales #' @name item_reliability #' #' @description Compute various measures of internal consistencies #' for tests or item-scales of questionnaires. #' #' @param x A matrix or a data frame. #' @param standardize Logical, if `TRUE`, the data frame's vectors will be #' standardized. Recommended when the variables have different measures / #' scales. #' @param digits Amount of digits for returned values. #' #' @return A data frame with the corrected item-total correlations (*item #' discrimination*, column `item_discrimination`) and Cronbach's Alpha #' (if item deleted, column `alpha_if_deleted`) for each item #' of the scale, or `NULL` if data frame had too less columns. #' #' @details #' #' This function calculates the item discriminations (corrected item-total #' correlations for each item of `x` with the remaining items) and the #' Cronbach's alpha for each item, if it was deleted from the scale. The #' absolute value of the item discrimination indices should be above 0.2. An #' index between 0.2 and 0.4 is considered as "fair", while an index above 0.4 #' (or below -0.4) is "good". The range of satisfactory values is from 0.4 to #' 0.7. Items with low discrimination indices are often ambiguously worded and #' should be examined. Items with negative indices should be examined to #' determine why a negative value was obtained (e.g. reversed answer categories #' regarding positive and negative poles). #' #' @examples #' data(mtcars) #' x <- mtcars[, c("cyl", "gear", "carb", "hp")] #' item_reliability(x) #' @export item_reliability <- function(x, standardize = FALSE, digits = 3) { # check param if (!is.matrix(x) && !is.data.frame(x)) { insight::format_alert("`x` needs to be a data frame or matrix.") return(NULL) } # remove missings, so correlation works x <- stats::na.omit(x) # remember item (column) names for return value # return value gets column names of initial data frame df.names <- colnames(x) ret.df <- NULL # check for minimum amount of columns can't be less than 3, because the # reliability test checks for Cronbach's alpha if a specific item is deleted. # If data frame has only two columns and one is deleted, Cronbach's alpha # cannot be calculated. if (ncol(x) > 2) { # Check whether items should be scaled. Needed, # when items have different measures / scales if (standardize) x <- .std(x) # calculate cronbach-if-deleted cronbachDeleted <- vapply(seq_len(ncol(x)), function(i) cronbachs_alpha(x[, -i]), numeric(1L)) # calculate corrected total-item correlation totalCorr <- vapply(seq_len(ncol(x)), function(i) { stats::cor(x[, i], rowSums(x[, -i]), use = "pairwise.complete.obs") }, numeric(1L)) ret.df <- data.frame( term = df.names, alpha_if_deleted = round(cronbachDeleted, digits), item_discrimination = round(totalCorr, digits), stringsAsFactors = FALSE ) } else { insight::format_warning("Data frame needs at least three columns for reliability-test.") } ret.df } performance/R/check_itemscale.R0000644000176200001440000001466414736731423016227 0ustar liggesusers#' @title Describe Properties of Item Scales #' @name check_itemscale #' #' @description Compute various measures of internal consistencies #' applied to (sub)scales, which items were extracted using #' `parameters::principal_components()`. #' #' @param x An object of class `parameters_pca`, as returned by #' [`parameters::principal_components()`], or a data frame. #' @param factor_index If `x` is a data frame, `factor_index` must be specified. #' It must be a numeric vector of same length as number of columns in `x`, where #' each element is the index of the factor to which the respective column in `x`. #' #' @return A list of data frames, with related measures of internal #' consistencies of each subscale. #' #' @details #' #' `check_itemscale()` calculates various measures of internal #' consistencies, such as Cronbach's alpha, item difficulty or discrimination #' etc. on subscales which were built from several items. Subscales are #' retrieved from the results of [`parameters::principal_components()`], i.e. #' based on how many components were extracted from the PCA, #' `check_itemscale()` retrieves those variables that belong to a component #' and calculates the above mentioned measures. #' #' @note #' - *Item difficulty* should range between 0.2 and 0.8. Ideal value #' is `p+(1-p)/2` (which mostly is between 0.5 and 0.8). See #' [`item_difficulty()`] for details. #' #' - For *item discrimination*, acceptable values are 0.20 or higher; #' the closer to 1.00 the better. See [`item_reliability()`] for more #' details. #' #' - In case the total *Cronbach's alpha* value is below the acceptable #' cut-off of 0.7 (mostly if an index has few items), the #' *mean inter-item-correlation* is an alternative measure to indicate #' acceptability. Satisfactory range lies between 0.2 and 0.4. See also #' [`item_intercor()`]. #' #' @references #' - Briggs SR, Cheek JM (1986) The role of factor analysis in the development #' and evaluation of personality scales. Journal of Personality, 54(1), #' 106-148. doi: 10.1111/j.1467-6494.1986.tb00391.x #' #' @examplesIf require("parameters") && require("psych") #' # data generation from '?prcomp', slightly modified #' C <- chol(S <- toeplitz(0.9^(0:15))) #' set.seed(17) #' X <- matrix(rnorm(1600), 100, 16) #' Z <- X %*% C #' #' pca <- parameters::principal_components( #' as.data.frame(Z), #' rotation = "varimax", #' n = 3 #' ) #' pca #' check_itemscale(pca) #' #' # as data frame #' check_itemscale( #' as.data.frame(Z), #' factor_index = parameters::closest_component(pca) #' ) #' @export check_itemscale <- function(x, factor_index = NULL) { if (!inherits(x, c("parameters_pca", "data.frame"))) { insight::format_error( "`x` must be an object of class `parameters_pca`, as returned by `parameters::principal_components()`, or a data frame." # nolint ) } # if data frame, we need `factor_index` if (inherits(x, "data.frame") && !inherits(x, "parameters_pca")) { if (is.null(factor_index)) { insight::format_error("If `x` is a data frame, `factor_index` must be specified.") } if (!is.numeric(factor_index)) { insight::format_error("`factor_index` must be numeric.") } if (length(factor_index) != ncol(x)) { insight::format_error( "`factor_index` must be of same length as number of columns in `x`.", "Each element of `factor_index` must be the index of the factor to which the respective column in `x` belongs to." # nolint ) } } # factor_index must be a named vector (column names as names) if (!is.null(factor_index) && is.null(names(factor_index)) && !inherits(x, "parameters_pca")) { factor_index <- stats::setNames(factor_index, colnames(x)) } # assign data and factor index if (inherits(x, "parameters_pca")) { insight::check_if_installed("parameters") dataset <- attributes(x)$dataset subscales <- parameters::closest_component(x) } else { dataset <- x subscales <- factor_index } out <- lapply(sort(unique(subscales)), function(.subscale) { columns <- names(subscales)[subscales == .subscale] items <- dataset[columns] reliability <- item_reliability(items) .item_discr <- reliability$item_discrimination if (is.null(.item_discr)) .item_discr <- NA .item_alpha <- reliability$alpha_if_deleted if (is.null(.item_alpha)) .item_alpha <- NA s_out <- data.frame( Item = columns, Missings = vapply(items, function(i) sum(is.na(i)) / nrow(items), numeric(1)), Mean = vapply(items, mean, numeric(1), na.rm = TRUE), SD = vapply(items, stats::sd, numeric(1), na.rm = TRUE), Skewness = vapply(items, function(i) as.numeric(datawizard::skewness(i)), numeric(1)), Difficulty = item_difficulty(items)$Difficulty, Discrimination = .item_discr, `alpha if deleted` = .item_alpha, stringsAsFactors = FALSE, check.names = FALSE ) attr(s_out, "item_intercorrelation") <- item_intercor(items) attr(s_out, "cronbachs_alpha") <- cronbachs_alpha(items) s_out }) class(out) <- unique(c("check_itemscale", class(out))) out } # methods ------------------------------------- #' @export print.check_itemscale <- function(x, digits = 2, ...) { insight::print_color("# Description of (Sub-)Scales", "blue") cat(insight::export_table( lapply(seq_along(x), function(i) { out <- x[[i]] attr(out, "table_caption") <- c(sprintf("\nComponent %i", i), "red") attr(out, "table_footer") <- c(sprintf( "\nMean inter-item-correlation = %.3f Cronbach's alpha = %.3f", attributes(out)$item_intercorrelation, attributes(out)$cronbachs_alpha ), "yellow") out }), digits = digits, format = "text", missing = "", zap_small = TRUE, ... )) } #' @export print_html.check_itemscale <- function(x, digits = 2, ...) { x <- lapply(seq_along(x), function(i) { out <- x[[i]] attr(out, "table_caption") <- sprintf( "Component %i: Mean inter-item-correlation = %.3f, Cronbach's alpha = %.3f", i, attributes(out)$item_intercorrelation, attributes(out)$cronbachs_alpha ) out }) insight::export_table( x, caption = "Description of (Sub-)Scales", digits = digits, format = "html", missing = "", zap_small = TRUE ) } performance/R/check_model_diagnostics.R0000644000176200001440000003474714736731423017754 0ustar liggesusers# prepare data for VIF plot ---------------------------------- .model_diagnostic_vif <- function(model, verbose = TRUE) { out <- check_collinearity(model, verbose = verbose) dat <- insight::compact_list(out) if (is.null(dat)) { return(NULL) } dat$group <- "low" dat$group[dat$VIF >= 5 & dat$VIF < 10] <- "moderate" dat$group[dat$VIF >= 10] <- "high" dat <- datawizard::data_select( dat, select = c(x = "Term", y = "VIF", facet = "Component", group = "group"), verbose = FALSE ) if (insight::n_unique(dat$facet) <= 1) { dat$facet <- NULL } attr(dat, "CI") <- attributes(out)$CI dat } # prepare data for QQ plot ---------------------------------- .model_diagnostic_qq <- function(model, model_info = NULL, verbose = TRUE) { if (inherits(model, c("lme", "lmerMod", "merMod", "gam"))) { res_ <- stats::residuals(model) } else if (inherits(model, "geeglm")) { res_ <- stats::residuals(model, type = "pearson") } else if (inherits(model, "glmmTMB")) { res_ <- stats::residuals(model, type = "deviance") } else if (inherits(model, "glm")) { res_ <- .safe(abs(stats::rstandard(model, type = "deviance"))) } else { res_ <- .safe(stats::rstudent(model)) if (is.null(res_)) { res_ <- .safe(stats::residuals(model)) } } if (is.null(res_) || all(is.na(res_))) { if (verbose) { if (is.null(model_info$family)) { fam <- "model" } else { fam <- paste0("`", model_info$family, "`") } insight::format_alert( paste( sprintf( "QQ plot could not be created. Cannot extract residuals from objects of class `%s`.", class(model)[1] ), sprintf( "Maybe the model class or the %s family does not support the computation of (deviance) residuals?", fam ) ) ) } return(NULL) } if (inherits(model, c("glm", "glmerMod")) || (inherits(model, "glmmTMB") && isFALSE(model_info$is_linear))) { fitted_ <- stats::qnorm((stats::ppoints(length(res_)) + 1) / 2) } else { fitted_ <- stats::fitted(model) } # validation check, sometimes either residuals or fitted can contain NA, see #488 if (anyNA(res_) || anyNA(fitted_)) { # drop NA and make sure both fitted and residuals match non_na <- !is.na(fitted_) & !is.na(res_) fitted_ <- fitted_[non_na] res_ <- res_[non_na] } res_ <- sort(res_, na.last = NA) fitted_ <- sort(fitted_, na.last = NA) data.frame(x = fitted_, y = res_) } # prepare data for random effects QQ plot ---------------------------------- .model_diagnostic_ranef_qq <- function(model, level = 0.95, model_info = NULL, verbose = TRUE) { # check if we have mixed model if (is.null(model_info) || !model_info$is_mixed) { return(NULL) } insight::check_if_installed("lme4") tryCatch( if (inherits(model, "glmmTMB")) { var_attr <- "condVar" re <- .collapse_cond(lme4::ranef(model, condVar = TRUE)) } else { var_attr <- "postVar" re <- lme4::ranef(model, condVar = TRUE) }, error = function(e) { NULL } ) se <- tryCatch( suppressWarnings(lapply(re, function(.x) { pv <- attr(.x, var_attr, exact = TRUE) cols <- seq_len(dim(pv)[1]) unlist(lapply(cols, function(.y) sqrt(pv[.y, .y, ]))) })), error = function(e) { NULL } ) if (is.null(se)) { if (verbose) { insight::format_alert("Could not compute standard errors from random effects for diagnostic plot.") } return(NULL) } Map(function(.re, .se) { ord <- unlist(lapply(.re, order)) + rep((0:(ncol(.re) - 1)) * nrow(.re), each = nrow(.re)) df.y <- unlist(.re)[ord] df.ci <- stats::qnorm((1 + level) / 2) * .se[ord] data.frame( x = rep(stats::qnorm(stats::ppoints(nrow(.re))), ncol(.re)), y = df.y, conf.low = df.y - df.ci, conf.high = df.y + df.ci, facet = gl(ncol(.re), nrow(.re), labels = names(.re)), stringsAsFactors = FALSE, row.names = NULL ) }, re, se) } # prepare data for normality of residuals plot ---------------------------------- .model_diagnostic_normality <- function(model, verbose = TRUE) { r <- try(as.numeric(stats::residuals(model)), silent = TRUE) if (inherits(r, "try-error")) { insight::format_alert(sprintf( "Non-normality of residuals could not be computed. Cannot extract residuals from objects of class '%s'.", class(model)[1] )) return(NULL) } dat <- as.data.frame(bayestestR::estimate_density(r)) dat$curve <- stats::dnorm(seq(min(dat$x), max(dat$x), length.out = nrow(dat)), mean(r), stats::sd(r)) dat } # prepare data for influential obs plot ---------------------------------- .model_diagnostic_outlier <- function(model, threshold = NULL) { s <- summary(model) if (inherits(model, "lm", which = TRUE) == 1) { cook_levels <- round(stats::qf(0.5, s$fstatistic[2], s$fstatistic[3]), 2) } else if (is.null(threshold)) { cook_levels <- c(0.5, 1) } else { cook_levels <- threshold } n_params <- tryCatch(model$rank, error = function(e) insight::n_parameters(model)) infl <- stats::influence(model, do.coef = FALSE) model_resid <- as.numeric(insight::get_residuals(model)) std_resid <- tryCatch(stats::rstandard(model, infl), error = function(e) model_resid) plot_data <- data.frame( Hat = infl$hat, Cooks_Distance = stats::cooks.distance(model, infl), Fitted = insight::get_predicted(model, ci = NULL), Residuals = model_resid, Std_Residuals = std_resid, stringsAsFactors = FALSE ) plot_data$Index <- seq_len(nrow(plot_data)) plot_data$Influential <- "OK" plot_data$Influential[abs(plot_data$Cooks_Distance) >= max(cook_levels)] <- "Influential" attr(plot_data, "cook_levels") <- cook_levels attr(plot_data, "n_params") <- n_params plot_data } # prepare data for non-constant variance plot ---------------------------------- .model_diagnostic_ncv <- function(model, verbose = TRUE) { ncv <- tryCatch( data.frame( x = as.numeric(stats::fitted(model)), y = as.numeric(stats::residuals(model)) ), error = function(e) { NULL } ) if (is.null(ncv)) { if (verbose) { insight::format_alert(sprintf( "Non-constant error variance could not be computed. Cannot extract residuals from objects of class '%s'.", class(model)[1] )) } return(NULL) } ncv } # prepare data for homogeneity of variance plot ---------------------------------- .model_diagnostic_homogeneity <- function(model, verbose = TRUE) { faminfo <- insight::model_info(model) r <- tryCatch( if (inherits(model, "merMod")) { stats::residuals(model, scaled = TRUE) } else if (inherits(model, "gam")) { stats::residuals(model, type = "scaled.pearson") } else if (inherits(model, c("glmmTMB", "MixMod"))) { residual_sigma <- if (faminfo$is_mixed) { sqrt(insight::get_variance_residual(model)) } else { .sigma_glmmTMB_nonmixed(model, faminfo) } stats::residuals(model) / residual_sigma } else if (inherits(model, "glm")) { ## TODO: check if we can / should use deviance residuals (as for QQ plots) here as well? stats::rstandard(model, type = "pearson") } else { stats::rstandard(model) }, error = function(e) { NULL } ) if (is.null(r)) { if (verbose) { insight::format_alert(sprintf( "Homogeneity of variance could not be computed. Cannot extract residual variance from objects of class '%s'.", class(model)[1] )) } return(NULL) } data.frame( x = stats::fitted(model), y = sqrt(abs(r)) ) } # prepare data for homogeneity of variance plot ---------------------------------- .new_diag_overdispersion <- function(model, ...) { faminfo <- insight::model_info(model) simres <- simulate_residuals(model, ...) predicted <- simres$fittedPredictedResponse d <- data.frame(Predicted = predicted) # residuals based on simulated residuals - but we want normally distributed residuals d$Residuals <- stats::residuals(simres, quantile_function = stats::qnorm, ...) d$Res2 <- d$Residuals^2 d$StdRes <- insight::get_residuals(model, type = "pearson") # data for poisson models if (faminfo$is_poisson && !faminfo$is_zero_inflated) { d$V <- predicted } # data for negative binomial models if (faminfo$is_negbin && !faminfo$is_zero_inflated) { if (inherits(model, "glmmTMB")) { if (faminfo$family == "nbinom1") { # for nbinom1, we can use "sigma()" d$V <- insight::get_sigma(model)^2 * stats::family(model)$variance(predicted) } else { # for nbinom2, "sigma()" has "inverse meaning" (see #654) d$V <- (1 / insight::get_sigma(model)^2) * stats::family(model)$variance(predicted) } } else { ## FIXME: this is not correct for glm.nb models? d$V <- predicted * (1 + predicted / insight::get_sigma(model)) } } # data for zero-inflated poisson models if (faminfo$is_poisson && faminfo$is_zero_inflated) { if (inherits(model, "glmmTMB")) { ptype <- "zprob" } else { ptype <- "zero" } d$Prob <- stats::predict(model, type = ptype) d$V <- predicted * (1 - d$Prob) * (1 + predicted * d$Prob) } # data for zero-inflated negative binomial models if (faminfo$is_negbin && faminfo$is_zero_inflated && !faminfo$is_dispersion) { if (inherits(model, "glmmTMB")) { ptype <- "zprob" } else { ptype <- "zero" } d$Prob <- stats::predict(model, type = ptype) d$Disp <- insight::get_sigma(model) d$V <- predicted * (1 + predicted / d$Disp) * (1 - d$Prob) * (1 + predicted * (1 + predicted / d$Disp) * d$Prob) # nolint } # data for zero-inflated negative binomial models with dispersion if (faminfo$is_negbin && faminfo$is_zero_inflated && faminfo$is_dispersion) { d <- data.frame(Predicted = stats::predict(model, type = "response")) if (inherits(model, "glmmTMB")) { ptype <- "zprob" } else { ptype <- "zero" } d$Prob <- stats::predict(model, type = ptype) d$Disp <- stats::predict(model, type = "disp") d$V <- predicted * (1 + predicted / d$Disp) * (1 - d$Prob) * (1 + predicted * (1 + predicted / d$Disp) * d$Prob) # nolint } d } .model_diagnostic_overdispersion <- function(model, ...) { faminfo <- insight::model_info(model) # data for poisson models if (faminfo$is_poisson && !faminfo$is_zero_inflated) { d <- data.frame(Predicted = stats::predict(model, type = "response")) d$Residuals <- insight::get_response(model) - as.vector(d$Predicted) d$Res2 <- d$Residuals^2 d$V <- d$Predicted d$StdRes <- insight::get_residuals(model, type = "pearson") } # data for negative binomial models if (faminfo$is_negbin && !faminfo$is_zero_inflated) { if (inherits(model, "glmmTMB")) { d <- data.frame(Predicted = stats::predict(model, type = "response")) d$Residuals <- insight::get_residuals(model, type = "pearson") d$Res2 <- d$Residuals^2 d$StdRes <- insight::get_residuals(model, type = "pearson") if (faminfo$family == "nbinom1") { # for nbinom1, we can use "sigma()" d$V <- insight::get_sigma(model)^2 * stats::family(model)$variance(d$Predicted) } else { # for nbinom2, "sigma()" has "inverse meaning" (see #654) d$V <- (1 / insight::get_sigma(model)^2) * stats::family(model)$variance(d$Predicted) } } else { ## FIXME: this is not correct for glm.nb models? d <- data.frame(Predicted = stats::predict(model, type = "response")) d$Residuals <- insight::get_response(model) - as.vector(d$Predicted) d$Res2 <- d$Residuals^2 d$V <- d$Predicted * (1 + d$Predicted / insight::get_sigma(model)) d$StdRes <- insight::get_residuals(model, type = "pearson") } } # data for zero-inflated poisson models if (faminfo$is_poisson && faminfo$is_zero_inflated) { d <- data.frame(Predicted = stats::predict(model, type = "response")) d$Residuals <- insight::get_response(model) - as.vector(d$Predicted) d$Res2 <- d$Residuals^2 if (inherits(model, "glmmTMB")) { ptype <- "zprob" } else { ptype <- "zero" } d$Prob <- stats::predict(model, type = ptype) d$V <- d$Predicted * (1 - d$Prob) * (1 + d$Predicted * d$Prob) d$StdRes <- insight::get_residuals(model, type = "pearson") } # data for zero-inflated negative binomial models if (faminfo$is_negbin && faminfo$is_zero_inflated && !faminfo$is_dispersion) { d <- data.frame(Predicted = stats::predict(model, type = "response")) d$Residuals <- insight::get_response(model) - as.vector(d$Predicted) d$Res2 <- d$Residuals^2 if (inherits(model, "glmmTMB")) { ptype <- "zprob" } else { ptype <- "zero" } d$Prob <- stats::predict(model, type = ptype) d$Disp <- insight::get_sigma(model) d$V <- d$Predicted * (1 + d$Predicted / d$Disp) * (1 - d$Prob) * (1 + d$Predicted * (1 + d$Predicted / d$Disp) * d$Prob) # nolint d$StdRes <- insight::get_residuals(model, type = "pearson") } # data for zero-inflated negative binomial models with dispersion if (faminfo$is_negbin && faminfo$is_zero_inflated && faminfo$is_dispersion) { d <- data.frame(Predicted = stats::predict(model, type = "response")) d$Residuals <- insight::get_response(model) - as.vector(d$Predicted) d$Res2 <- d$Residuals^2 if (inherits(model, "glmmTMB")) { ptype <- "zprob" } else { ptype <- "zero" } d$Prob <- stats::predict(model, type = ptype) d$Disp <- stats::predict(model, type = "disp") d$V <- d$Predicted * (1 + d$Predicted / d$Disp) * (1 - d$Prob) * (1 + d$Predicted * (1 + d$Predicted / d$Disp) * d$Prob) # nolint d$StdRes <- insight::get_residuals(model, type = "pearson") } d } # helpers ---------------------------------- .sigma_glmmTMB_nonmixed <- function(model, faminfo) { if (!is.na(match(faminfo$family, c("binomial", "poisson", "truncated_poisson")))) { return(1) } betad <- model$fit$par["betadisp"] switch(faminfo$family, gaussian = exp(0.5 * betad), Gamma = exp(-0.5 * betad), exp(betad) ) } performance/R/performance_mae.R0000644000176200001440000000307314736731423016237 0ustar liggesusers#' @title Mean Absolute Error of Models #' @name performance_mae #' #' @description Compute mean absolute error of models. #' #' @inheritParams performance_rmse #' @inheritParams model_performance.lm #' #' @return Numeric, the mean absolute error of `model`. #' #' @examples #' data(mtcars) #' m <- lm(mpg ~ hp + gear, data = mtcars) #' performance_mae(m) #' @export performance_mae <- function(model, ...) { UseMethod("performance_mae") } #' @rdname performance_mae #' @export mae <- performance_mae #' @export performance_mae.default <- function(model, verbose = TRUE, ...) { .is_model_valid(model) pred <- .safe(insight::get_predicted(model, ci = NULL, verbose = verbose, ...)) observed <- insight::get_response(model) mean(abs(observed - pred)) } # mfx models ------------------------------- #' @export performance_mae.logitor <- function(model, verbose = TRUE, ...) { performance_mae(model$fit, verbose = verbose, ...) } #' @export performance_mae.logitmfx <- performance_mae.logitor #' @export performance_mae.probitmfx <- performance_mae.logitor #' @export performance_mae.poissonirr <- performance_mae.logitor #' @export performance_mae.poissonmfx <- performance_mae.logitor #' @export performance_mae.negbinirr <- performance_mae.logitor #' @export performance_mae.negbinmfx <- performance_mae.logitor #' @export performance_mae.betaor <- performance_mae.logitor #' @export performance_mae.betamfx <- performance_mae.logitor #' @export performance_mae.model_fit <- performance_mae.logitor performance/R/r2_somers.R0000644000176200001440000000230414504243270015012 0ustar liggesusers#' @title Somers' Dxy rank correlation for binary outcomes #' @name r2_somers #' #' @description Calculates the Somers' Dxy rank correlation for logistic regression models. #' #' @param model A logistic regression model. #' #' @return A named vector with the R2 value. #' #' @examples #' \donttest{ #' if (require("correlation") && require("Hmisc")) { #' model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") #' r2_somers(model) #' } #' } #' #' @references Somers, R. H. (1962). A new asymmetric measure of association for #' ordinal variables. American Sociological Review. 27 (6). #' @export r2_somers <- function(model) { insight::check_if_installed("correlation") info <- insight::model_info(model, verbose = FALSE) if (!info$is_binomial) { insight::format_error("`r2_somers()` only accepts logistic regression models.") } input <- data.frame( y = .recode_to_zero(insight::get_response(model, verbose = FALSE)), pred = stats::predict(model, type = "response"), stringsAsFactors = FALSE ) out <- correlation::cor_test(input, "y", "pred", method = "somers") r2somers <- out$Dxy names(r2somers) <- "Somers' Dxy" r2somers } performance/R/simulate_residuals.R0000644000176200001440000001566014706655512017020 0ustar liggesusers#' @title Simulate randomized quantile residuals from a model #' @name simulate_residuals #' #' @description Returns simulated residuals from a model. This is useful for #' checking the uniformity of residuals, in particular for non-Gaussian models, #' where the residuals are not expected to be normally distributed. #' #' @param x A model object. #' @param iterations Number of simulations to run. #' @param ... Arguments passed on to [`DHARMa::simulateResiduals()`]. #' @param object A `performance_simres` object, as returned by `simulate_residuals()`. #' @param quantile_function A function to apply to the residuals. If `NULL`, the #' residuals are returned as is. If not `NULL`, the residuals are passed to this #' function. This is useful for returning normally distributed residuals, for #' example: `residuals(x, quantile_function = qnorm)`. #' @param outlier_values A vector of length 2, specifying the values to replace #' `-Inf` and `Inf` with, respectively. #' #' @return Simulated residuals, which can be further processed with #' [`check_residuals()`]. The returned object is of class `DHARMa` and #' `performance_simres`. #' #' @seealso [`check_residuals()`], [`check_zeroinflation()`], #' [`check_overdispersion()`] and [`check_predictions()`]. See also #' [`see::plot.see_performance_simres()`] for options to customize the plot. #' #' @details This function is a small wrapper around [`DHARMa::simulateResiduals()`]. #' It basically only sets `plot = FALSE` and adds an additional class attribute #' (`"performance_sim_res"`), which allows using the DHARMa object in own plotting #' functions from the **see** package. See also `vignette("DHARMa")`. There is a #' `plot()` method to visualize the distribution of the residuals. #' #' @section Tests based on simulated residuals: #' For certain models, resp. model from certain families, tests like #' [`check_zeroinflation()`] or [`check_overdispersion()`] are based on #' simulated residuals. These are usually more accurate for such tests than #' the traditionally used Pearson residuals. However, when simulating from more #' complex models, such as mixed models or models with zero-inflation, there are #' several important considerations. `simulate_residuals()` relies on #' [`DHARMa::simulateResiduals()`], and additional arguments specified in `...` #' are passed further down to that function. The defaults in DHARMa are set on #' the most conservative option that works for all models. However, in many #' cases, the help advises to use different settings in particular situations #' or for particular models. It is recommended to read the 'Details' in #' `?DHARMa::simulateResiduals` closely to understand the implications of the #' simulation process and which arguments should be modified to get the most #' accurate results. #' #' @references #' #' - Hartig, F., & Lohse, L. (2022). DHARMa: Residual Diagnostics for Hierarchical #' (Multi-Level / Mixed) Regression Models (Version 0.4.5). Retrieved from #' https://CRAN.R-project.org/package=DHARMa #' #' - Dunn, P. K., & Smyth, G. K. (1996). Randomized Quantile Residuals. Journal #' of Computational and Graphical Statistics, 5(3), 236. \doi{10.2307/1390802} #' #' @examplesIf require("DHARMa") #' m <- lm(mpg ~ wt + cyl + gear + disp, data = mtcars) #' simulate_residuals(m) #' #' # extract residuals #' head(residuals(simulate_residuals(m))) #' #' @export simulate_residuals <- function(x, iterations = 250, ...) { insight::check_if_installed("DHARMa") # TODO (low priority): Note that DHARMa::simulateResiduals(x, ...) does its # own checks for whether or not the model passed to it is supported, do we # want to use this or do our own checks so we can supply our own error # message? if (iterations < 2) { insight::format_error("`iterations` must be at least 2.") } # It's important to preserve this object as is, rather than prematurely # extracting the residuals from it because the object contains important stuff # in it that we'll want to pass onto other functions later, such as passing # the fitted model into check_model(). out <- DHARMa::simulateResiduals(x, n = iterations, plot = FALSE, ...) class(out) <- c("performance_simres", "see_performance_simres", class(out)) out } # methods ------------------------------ #' @export print.performance_simres <- function(x, ...) { # TODO (low priority): We can probably just base this off of the print method # DHARMa uses, but with an easystats style. For now we can just stick with # DHARMa's method. msg <- paste0( "Simulated residuals from a model of class `", class(x$fittedModel)[1], "` based on ", x$nSim, " simulations. Use `check_residuals()` to check", " uniformity of residuals or `residuals()` to extract simulated residuals.", " It is recommended to refer to `?DHARMa::simulateResiudals` and", " `vignette(\"DHARMa\")` for more information about different settings", " in particular situations or for particular models.\n" ) cat(insight::format_message(msg)) } #' @export plot.performance_simres <- function(x, ...) { insight::check_if_installed("see", "for residual plots") NextMethod() } # methods -------------------------- #' @rdname simulate_residuals #' @export residuals.performance_simres <- function(object, quantile_function = NULL, outlier_values = NULL, ...) { # check for DHARMa argument names dots <- list(...) if (!is.null(dots$quantileFunction)) { quantile_function <- dots$quantileFunction } if (!is.null(dots$outlierValues)) { outlier_values <- dots$outlierValues } if (is.null(quantile_function)) { res <- object$scaledResiduals } else { res <- quantile_function(object$scaledResiduals) if (!is.null(outlier_values)) { # check for correct length of outlier_values if (length(outlier_values) != 2) { insight::format_error("`outlier_values` must be a vector of length 2.") } res[res == -Inf] <- outlier_values[1] res[res == Inf] <- outlier_values[2] } } res } # helper functions --------------------- .simres_statistics <- function(x, statistic_fun, alternative = "two.sided") { # summarize the observed and simulated residuals if (is.null(statistic_fun)) { # we pass the values to compute the p-value directly (for "check_outliers()") observed <- x simulated <- statistic_fun } else { # or apply a function to observed and simulated residusls, # to calcualte a summary statistic observed <- statistic_fun(x$observedResponse) simulated <- apply(x$simulatedResponse, 2, statistic_fun) } # p is simply ratio of simulated zeros to observed zeros p <- switch(alternative, greater = mean(simulated >= observed), less = mean(simulated <= observed), min(min(mean(simulated <= observed), mean(simulated >= observed)) * 2, 1) ) list(observed = observed, simulated = simulated, p = p) } performance/R/r2_bayes.R0000644000176200001440000003431714736731423014627 0ustar liggesusers#' @title Bayesian R2 #' @name r2_bayes #' #' @description #' Compute R2 for Bayesian models. For mixed models (including a random part), #' it additionally computes the R2 related to the fixed effects only (marginal #' R2). While `r2_bayes()` returns a single R2 value, `r2_posterior()` returns a #' posterior sample of Bayesian R2 values. #' #' @param model A Bayesian regression model (from **brms**, #' **rstanarm**, **BayesFactor**, etc). #' @param robust Logical, if `TRUE`, the median instead of mean is used to #' calculate the central tendency of the variances. #' @param ci Value or vector of probability of the CI (between 0 and 1) to be #' estimated. #' @param ... Arguments passed to `r2_posterior()`. #' @inheritParams model_performance.lm #' #' @return A list with the Bayesian R2 value. For mixed models, a list with the #' Bayesian R2 value and the marginal Bayesian R2 value. The standard errors and #' credible intervals for the R2 values are saved as attributes. #' #' @details #' `r2_bayes()` returns an "unadjusted" R2 value. See [`r2_loo()`] to calculate a #' LOO-adjusted R2, which comes conceptually closer to an adjusted R2 measure. #' #' For mixed models, the conditional and marginal R2 are returned. The marginal #' R2 considers only the variance of the fixed effects, while the conditional R2 #' takes both the fixed and random effects into account. Technically, since #' `r2_bayes()` relies on [`rstantools::bayes_R2()`], the "marginal" R2 calls #' `bayes_R2(re.form = NA)`, while the "conditional" R2 calls #' `bayes_R2(re.form = NULL)`. The `re.form` argument is passed to #' [`rstantools::posterior_epred()`], which is internally called in `bayes_R2()`. #' #' Note that for "marginal" and "conditional", we refer to the wording suggested #' by _Nakagawa et al. 2017_. Thus, we don't use the term "marginal" in the sense #' that the random effects are integrated out, but are "ignored". #' #' `r2_posterior()` is the actual workhorse for `r2_bayes()` and returns a #' posterior sample of Bayesian R2 values. #' #' @examplesIf require("rstanarm") && require("rstantools") && require("brms") && require("RcppEigen") #' library(performance) #' \donttest{ #' model <- suppressWarnings(rstanarm::stan_glm( #' mpg ~ wt + cyl, #' data = mtcars, #' chains = 1, #' iter = 500, #' refresh = 0, #' show_messages = FALSE #' )) #' r2_bayes(model) #' #' model <- suppressWarnings(rstanarm::stan_lmer( #' Petal.Length ~ Petal.Width + (1 | Species), #' data = iris, #' chains = 1, #' iter = 500, #' refresh = 0 #' )) #' r2_bayes(model) #' } #' #' \donttest{ #' model <- suppressWarnings(brms::brm( #' mpg ~ wt + cyl, #' data = mtcars, #' silent = 2, #' refresh = 0 #' )) #' r2_bayes(model) #' #' model <- suppressWarnings(brms::brm( #' Petal.Length ~ Petal.Width + (1 | Species), #' data = iris, #' silent = 2, #' refresh = 0 #' )) #' r2_bayes(model) #' } #' @references #' - Gelman, A., Goodrich, B., Gabry, J., and Vehtari, A. (2018). R-squared for #' Bayesian regression models. The American Statistician, 1–6. #' \doi{10.1080/00031305.2018.1549100} #' - Nakagawa, S., Johnson, P. C. D., and Schielzeth, H. (2017). The #' coefficient of determination R2 and intra-class correlation coefficient from #' generalized linear mixed-effects models revisited and expanded. Journal of #' The Royal Society Interface, 14(134), 20170213. #' @export r2_bayes <- function(model, robust = TRUE, ci = 0.95, verbose = TRUE, ...) { r2_bayesian <- r2_posterior(model, verbose = verbose, ...) if (is.null(r2_bayesian)) { return(NULL) } if (insight::is_multivariate(model)) { structure( class = "r2_bayes_mv", rapply(r2_bayesian, function(i) { if (robust) { stats::median(i) } else { mean(i) } }), SE = rapply(r2_bayesian, function(i) { if (robust) { stats::mad(i) } else { stats::sd(i) } }), # "Estimates" = rapply(r2_bayesian, bayestestR::point_estimate, centrality = "all", dispersion = TRUE), CI = rapply(r2_bayesian, bayestestR::hdi, ci = ci), ci_method = "HDI", robust = robust ) } else { structure( class = "r2_bayes", lapply(r2_bayesian, function(i) { if (robust) { stats::median(i) } else { mean(i) } }), SE = lapply(r2_bayesian, function(i) { if (robust) { stats::mad(i) } else { stats::sd(i) } }), # Estimates = lapply(r2_bayesian, bayestestR::point_estimate, centrality = "all", dispersion = TRUE), CI = lapply(r2_bayesian, bayestestR::hdi, ci = ci), ci_method = "HDI", robust = robust ) } } #' @export #' @rdname r2_bayes r2_posterior <- function(model, ...) { UseMethod("r2_posterior") } #' @export #' @rdname r2_bayes r2_posterior.brmsfit <- function(model, verbose = TRUE, ...) { insight::check_if_installed("rstantools") algorithm <- insight::find_algorithm(model) if (algorithm$algorithm != "sampling") { insight::format_warning( "`r2()` only available for models fit using the `sampling` algorithm." ) return(NA) } tryCatch( { mi <- insight::model_info(model) if (insight::is_multivariate(model)) { res <- insight::find_response(model) if (mi[[1]]$is_mixed) { br2_mv <- list( R2_Bayes = rstantools::bayes_R2( model, re.form = NULL, re_formula = NULL, summary = FALSE ), R2_Bayes_marginal = rstantools::bayes_R2( model, re.form = NA, re_formula = NA, summary = FALSE ) ) br2 <- lapply(seq_along(res), function(x) { list( R2_Bayes = unname(as.vector(br2_mv$R2_Bayes[, x])), R2_Bayes_marginal = unname(as.vector(br2_mv$R2_Bayes_marginal[, x])) ) }) names(br2) <- res } else { br2_mv <- list(R2_Bayes = rstantools::bayes_R2(model, summary = FALSE)) br2 <- lapply(seq_along(res), function(x) { list(R2_Bayes = unname(as.vector(br2_mv$R2_Bayes[, x]))) }) names(br2) <- res } } else if (mi$is_mixed) { if (inherits(model, "stanreg")) { pred_cond <- rstanarm::posterior_epred( model, re.form = NULL, re_formula = NULL, ) pred_marginal <- rstanarm::posterior_epred( model, re.form = NA, re_formula = NA, ) y <- insight::get_response(model) br2 <- list( R2_Bayes = as.vector(rstantools::bayes_R2(pred_cond, y = y)), R2_Bayes_marginal = as.vector(rstantools::bayes_R2(pred_marginal, y = y)) ) } else { br2 <- list( R2_Bayes = as.vector(rstantools::bayes_R2( model, re.form = NULL, re_formula = NULL, summary = FALSE )), R2_Bayes_marginal = as.vector(rstantools::bayes_R2( model, re.form = NA, re_formula = NA, summary = FALSE )) ) } names(br2$R2_Bayes) <- rep("Conditional R2", length(br2$R2_Bayes)) names(br2$R2_Bayes_marginal) <- rep("Marginal R2", length(br2$R2_Bayes)) } else { br2 <- list(R2_Bayes = as.vector(rstantools::bayes_R2(model, summary = FALSE))) names(br2$R2_Bayes) <- rep("R2", length(br2$R2_Bayes)) } br2 }, error = function(e) { if (inherits(e, c("simpleError", "error"))) { insight::print_color(e$message, "red") cat("\n") } NULL } ) } #' @export #' @rdname r2_bayes r2_posterior.stanreg <- r2_posterior.brmsfit #' @export r2_posterior.stanmvreg <- function(model, verbose = TRUE, ...) { if (isTRUE(verbose)) { insight::format_error("Models of class `stanmvreg` not yet supported.") } NULL } #' @param average Compute model-averaged index? See [bayestestR::weighted_posteriors()]. #' @inheritParams bayestestR::weighted_posteriors #' @inheritParams r2_bayes #' @export #' @rdname r2_bayes r2_posterior.BFBayesFactor <- function(model, average = FALSE, prior_odds = NULL, verbose = TRUE, ...) { mi <- insight::model_info(model, verbose = FALSE) if (!mi$is_linear || mi$is_correlation || mi$is_ttest || mi$is_binomial || mi$is_meta) { if (verbose) { insight::format_warning("Can produce R2 only for linear models.") } return(NULL) } if (average) { return(.r2_posterior_model_average(model, prior_odds = prior_odds, verbose = verbose)) } insight::check_if_installed("rstantools") insight::check_if_installed("BayesFactor") everything_we_need <- .get_bfbf_predictions(model, verbose = verbose) # Compute R2! y <- everything_we_need[["y"]] yy <- everything_we_need[["y_pred"]] r2_bayesian <- data.frame(R2_Bayes = rstantools::bayes_R2(yy, y = y)) if ("y_pred_marginal" %in% names(everything_we_need)) { yy <- everything_we_need[["y_pred_marginal"]] r2_bayesian$R2_Bayes_marginal <- rstantools::bayes_R2(yy, y = y) } r2_bayesian } #' @keywords internal .r2_posterior_model_average <- function(model, prior_odds = NULL, verbose = TRUE) { insight::check_if_installed("BayesFactor") BFMods <- bayestestR::bayesfactor_models(model, verbose = FALSE) if (!is.null(BFMods$log_BF)) { BFMods$BF <- exp(BFMods$log_BF) } has_random <- !is.null(insight::find_predictors(model, effects = "random", flatten = TRUE)) if (any(is.na(BFMods$BF) | is.infinite(BFMods$BF))) { if (verbose) { insight::format_warning( "Can't compute model-averaged index. One or more Bayes factors are NA or infinite." ) } return(NULL) } # extract parameters intercept_only <- which(BFMods$Model == "1") params <- vector(mode = "list", length = nrow(BFMods)) for (m in seq_along(params)) { if (length(intercept_only) && m == intercept_only) { params[[m]] <- data.frame(R2_Bayes = rep(0, 4000)) } else if (m == 1) { # If the model is the "den" model params[[m]] <- suppressMessages(r2_posterior(1 / model[1])) } else { params[[m]] <- suppressMessages(r2_posterior(model[m - 1])) } # when there is no random effect, marginal = conditional if (has_random && is.null(params[[m]]$R2_Bayes_marginal)) { params[[m]]$R2_Bayes_marginal <- params[[m]]$R2_Bayes } } # Compute posterior model probabilities if (is.null(prior_odds)) { prior_odds <- rep(1, nrow(BFMods)) } else { prior_odds <- c(1, prior_odds) } posterior_odds <- prior_odds * BFMods$BF posterior_odds <- posterior_odds[-1] / posterior_odds[1] do.call( bayestestR::weighted_posteriors, c(params, list(missing = 0, prior_odds = posterior_odds)) ) } #' @export as.data.frame.r2_bayes <- function(x, ...) { out <- data.frame( R2 = x$R2_Bayes, SD = attributes(x)$SE$R2_Bayes, CI = attributes(x)$CI$R2_Bayes$CI, CI_low = attributes(x)$CI$R2_Bayes$CI_low, CI_high = attributes(x)$CI$R2_Bayes$CI_high, CI_method = attributes(x)$ci_method, stringsAsFactors = FALSE ) if (!is.null(x$R2_Bayes_marginal)) { out_marginal <- data.frame( R2 = x$R2_Bayes_marginal, SD = attributes(x)$SE$R2_Bayes_marginal, CI = attributes(x)$CI$R2_Bayes_marginal$CI, CI_low = attributes(x)$CI$R2_Bayes_marginal$CI_low, CI_high = attributes(x)$CI$R2_Bayes_marginal$CI_high, CI_method = attributes(x)$ci_method, stringsAsFactors = FALSE ) out$Component <- "conditional" out_marginal$Component <- "marginal" out <- rbind(out, out_marginal) } out$Effectsize <- "Bayesian R-squared" out } # Utils ------------------------------------------------------------------- .get_bfbf_predictions <- function(model, iterations = 4000, verbose = TRUE) { insight::check_if_installed("BayesFactor") # Estimates params <- insight::get_parameters( model, unreduce = FALSE, iterations = iterations, verbose = verbose ) # remove sig and g cols params_theta <- params[, !grepl(pattern = "^sig2$|^g_|^g$", colnames(params))] params_sigma <- sqrt(params[, colnames(params) == "sig2"]) # Model Matrix mm <- insight::get_modelmatrix(model[1]) colnames(mm)[1] <- "mu" # match? if ((length(colnames(params_theta)) != length(colnames(mm))) || !all(colnames(params_theta) == colnames(mm))) { if (utils::packageVersion("BayesFactor") < package_version("0.9.12.4.3")) { insight::format_error("R2 for BayesFactor models with random effects requires BayesFactor v0.9.12.4.3 or higher.") } insight::format_error("Woops, you seem to have stumbled on some weird edge case. Please file an issue at {.url https://github.com/easystats/performance/issues}") # nolint } out <- list( y = insight::get_response(model, verbose = FALSE), y_pred = (as.matrix(params_theta) %*% t(mm)) ) rand <- insight::find_predictors(model[1], effects = "random", flatten = TRUE, verbose = FALSE) if (!is.null(rand)) { idx <- sapply(paste0("\\b", rand, "\\b"), grepl, x = colnames(params_theta)) idx <- apply(idx, 1, any) params_theta[idx] <- 0 out[["y_pred_marginal"]] <- (as.matrix(params_theta) %*% t(mm)) } out[["sigma"]] <- params_sigma out } #' @export residuals.BFBayesFactor <- function(object, ...) { everything_we_need <- .get_bfbf_predictions(object, verbose = FALSE) everything_we_need[["y"]] - colMeans(everything_we_need[["y_pred"]]) } #' @export fitted.BFBayesFactor <- function(object, ...) { colMeans(.get_bfbf_predictions(object, verbose = FALSE)[["y_pred"]]) } performance/R/r2_nagelkerke.R0000644000176200001440000001466314736731423015636 0ustar liggesusers#' @title Nagelkerke's R2 #' @name r2_nagelkerke #' #' @description Calculate Nagelkerke's pseudo-R2. #' #' @param model A generalized linear model, including cumulative links resp. #' multinomial models. #' @param ... Currently not used. #' #' @return A named vector with the R2 value. #' #' @examples #' model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") #' r2_nagelkerke(model) #' @references #' Nagelkerke, N. J. (1991). A note on a general definition of the coefficient #' of determination. Biometrika, 78(3), 691-692. #' #' @export r2_nagelkerke <- function(model, ...) { UseMethod("r2_nagelkerke") } # helper --------------------------- .r2_nagelkerke <- function(model, l_base) { L.full <- insight::get_loglikelihood(model) D.full <- -2 * L.full D.base <- -2 * l_base # Is it still necessary? if (inherits(model, c("vglm", "vgam", "clm2"))) { n <- insight::n_obs(model) } else { n <- attr(L.full, "nobs") if (is.null(n)) n <- insight::n_obs(model, disaggregate = TRUE) } r2_nagelkerke <- as.vector((1 - exp((D.full - D.base) / n)) / (1 - exp(-D.base / n))) names(r2_nagelkerke) <- "Nagelkerke's R2" r2_nagelkerke } # Nagelkerke's R2 based on Cox&Snell's R2 ---------------- #' @export r2_nagelkerke.glm <- function(model, verbose = TRUE, ...) { info <- list(...)$model_info if (is.null(info)) { info <- suppressWarnings(insight::model_info(model, verbose = FALSE)) } if (info$is_binomial && !info$is_bernoulli && class(model)[1] == "glm") { if (verbose) { insight::format_warning("Can't calculate accurate R2 for binomial models that are not Bernoulli models.") } return(NULL) } r2cox <- r2_coxsnell(model) if (is.na(r2cox) || is.null(r2cox)) { return(NULL) } r2_nagelkerke <- r2cox / (1 - exp(-model$null.deviance / insight::n_obs(model, disaggregate = TRUE))) names(r2_nagelkerke) <- "Nagelkerke's R2" r2_nagelkerke } #' @export r2_nagelkerke.BBreg <- r2_nagelkerke.glm #' @export r2_nagelkerke.glmmTMB <- function(model, verbose = TRUE, ...) { info <- list(...)$model_info if (is.null(info)) { info <- suppressWarnings(insight::model_info(model, verbose = FALSE)) } if (info$is_binomial && !info$is_bernoulli) { if (verbose) { insight::format_warning("Can't calculate accurate R2 for binomial models that are not Bernoulli models.") } return(NULL) } dev <- stats::deviance(model) # if no deviance, return NA if (is.null(dev)) { return(NULL) } null_mod <- suppressWarnings(insight::null_model(model)) null_dev <- stats::deviance(null_mod) r2cox <- (1 - exp((dev - null_dev) / insight::n_obs(model, disaggregate = TRUE))) if (is.na(r2cox) || is.null(r2cox)) { return(NULL) } r2_nagelkerke <- r2cox / (1 - exp(-null_dev / insight::n_obs(model, disaggregate = TRUE))) names(r2_nagelkerke) <- "Nagelkerke's R2" r2_nagelkerke } #' @export r2_nagelkerke.nestedLogit <- function(model, ...) { n <- insight::n_obs(model, disaggregate = TRUE) stats::setNames( lapply(names(model$models), function(i) { m <- model$models[[i]] # if no deviance, return NA if (is.null(m$deviance)) { return(NA) } r2_nagelkerke <- (1 - exp((m$deviance - m$null.deviance) / n[[i]])) / (1 - exp(-m$null.deviance / n[[i]])) names(r2_nagelkerke) <- "Nagelkerke's R2" r2_nagelkerke }), names(model$models) ) } #' @export r2_nagelkerke.bife <- function(model, ...) { r2_nagelkerke <- r2_coxsnell(model) / (1 - exp(-model$null_deviance / insight::n_obs(model))) names(r2_nagelkerke) <- "Nagelkerke's R2" r2_nagelkerke } # mfx models --------------------- #' @export r2_nagelkerke.logitmfx <- function(model, ...) { r2_nagelkerke(model$fit, ...) } #' @export r2_nagelkerke.logitor <- r2_nagelkerke.logitmfx #' @export r2_nagelkerke.poissonirr <- r2_nagelkerke.logitmfx #' @export r2_nagelkerke.poissonmfx <- r2_nagelkerke.logitmfx #' @export r2_nagelkerke.probitmfx <- r2_nagelkerke.logitmfx #' @export r2_nagelkerke.negbinirr <- r2_nagelkerke.logitmfx #' @export r2_nagelkerke.negbinmfx <- r2_nagelkerke.logitmfx # Nagelkerke's R2 based on LogLik ---------------- #' @export r2_nagelkerke.multinom <- function(model, ...) { l_base <- insight::get_loglikelihood(stats::update(model, ~1, trace = FALSE)) .r2_nagelkerke(model, l_base) } #' @export r2_nagelkerke.clm2 <- function(model, ...) { l_base <- insight::get_loglikelihood(stats::update(model, location = ~1, scale = ~1)) .r2_nagelkerke(model, l_base) } #' @export r2_nagelkerke.clm <- function(model, ...) { l_base <- insight::get_loglikelihood(stats::update(model, ~1)) # if no loglik, return NA if (length(as.numeric(l_base)) == 0) { return(NULL) } .r2_nagelkerke(model, l_base) } #' @export r2_nagelkerke.polr <- r2_nagelkerke.clm #' @export r2_nagelkerke.serp <- r2_nagelkerke.clm #' @export r2_nagelkerke.cpglm <- r2_nagelkerke.clm #' @export r2_nagelkerke.bracl <- r2_nagelkerke.clm #' @export r2_nagelkerke.glmx <- r2_nagelkerke.clm #' @export r2_nagelkerke.brmultinom <- r2_nagelkerke.clm #' @export r2_nagelkerke.censReg <- r2_nagelkerke.clm #' @export r2_nagelkerke.truncreg <- r2_nagelkerke.clm #' @export r2_nagelkerke.DirichletRegModel <- r2_coxsnell.clm # Nagelkerke's R2 based on LogLik stored in model object ---------------- #' @export r2_nagelkerke.coxph <- function(model, ...) { l_base <- model$loglik[1] .r2_nagelkerke(model, l_base) } #' @export r2_nagelkerke.survreg <- r2_nagelkerke.coxph #' @export r2_nagelkerke.crch <- r2_nagelkerke.coxph #' @export r2_nagelkerke.svycoxph <- function(model, ...) { l_base <- model$ll[1] .r2_nagelkerke(model, l_base) } # other --------------------- #' @export r2_nagelkerke.mclogit <- function(model, ...) { insight::check_if_installed("mclogit", reason = "to calculate R2") s <- mclogit::getSummary.mclogit(model) r2_nagelkerke <- s$sumstat["Nagelkerke"] names(r2_nagelkerke) <- "Nagelkerke's R2" r2_nagelkerke } #' @export r2_nagelkerke.mblogit <- function(model, ...) { insight::check_if_installed("mclogit", reason = "to calculate R2") s <- mclogit::getSummary.mblogit(model) r2_nagelkerke <- s$sumstat["Nagelkerke"] names(r2_nagelkerke) <- "Nagelkerke's R2" r2_nagelkerke } performance/R/logLik.R0000644000176200001440000000304614505025056014325 0ustar liggesusers#' @exportS3Method logLik ivreg logLik.ivreg <- function(object, ...) { res <- insight::get_residuals(object) p <- object$rank w <- object$weights N <- length(res) if (is.null(w)) { w <- rep.int(1, N) } else { excl <- w == 0 if (any(excl)) { res <- res[!excl] N <- length(res) w <- w[!excl] } } N0 <- N val <- 0.5 * (sum(log(w)) - N * (log(2 * pi) + 1 - log(N) + log(sum(w * res^2)))) attr(val, "nall") <- N0 attr(val, "nobs") <- N attr(val, "df") <- p + 1 class(val) <- "logLik" val } #' @exportS3Method logLik iv_robust logLik.iv_robust <- logLik.ivreg #' @exportS3Method logLik plm logLik.plm <- function(object, ...) { res <- object$residuals w <- object$weights N <- length(res) if (is.null(w)) { w <- rep.int(1, N) } else { excl <- w == 0 if (any(excl)) { res <- res[!excl] N <- length(res) w <- w[!excl] } } N0 <- N val <- 0.5 * (sum(log(w)) - N * (log(2 * pi) + 1 - log(N) + log(sum(w * res^2)))) attr(val, "nall") <- N0 attr(val, "nobs") <- N attr(val, "df") <- insight::n_parameters(object) + 1L class(val) <- "logLik" val } #' @exportS3Method logLik cpglm logLik.cpglm <- logLik.plm #' @exportS3Method logLik svycoxph logLik.svycoxph <- function(object, ...) { val <- object$ll[2] attr(val, "nall") <- insight::n_obs(object) attr(val, "nobs") <- insight::n_obs(object) attr(val, "df") <- object$degf.resid class(val) <- "logLik" val } performance/R/print_md.R0000644000176200001440000000746214620351763014733 0ustar liggesusers#' @rdname display.performance_model #' @export print_md.performance_model <- function(x, digits = 2, caption = "Indices of model performance", layout = "horizontal", ...) { layout <- match.arg(layout, choices = c("horizontal", "vertical")) formatted_table <- format( x = x, digits = digits, format = "markdown", ... ) # switch to vertical layout if (layout == "vertical") { formatted_table <- datawizard::rownames_as_column(as.data.frame(t(formatted_table)), "Metric") colnames(formatted_table)[2] <- "Value" } insight::export_table( x = formatted_table, digits = digits, format = "markdown", caption = caption, align = "firstleft", ... ) } #' @rdname display.performance_model #' @export print_md.compare_performance <- function(x, digits = 2, caption = "Comparison of Model Performance Indices", layout = "horizontal", ...) { layout <- match.arg(layout, choices = c("horizontal", "vertical")) .print_md_compare_performance(x, digits = digits, caption = caption, layout = layout, format = "markdown", ...) } #' @export print_html.compare_performance <- function(x, digits = 2, caption = "Comparison of Model Performance Indices", layout = "horizontal", ...) { layout <- match.arg(layout, choices = c("horizontal", "vertical")) .print_md_compare_performance(x, digits = digits, caption = caption, layout = layout, format = "html", ...) } #' @export print_md.check_itemscale <- function(x, digits = 2, ...) { insight::export_table( lapply(seq_along(x), function(i) { out <- x[[i]] attr(out, "caption") <- sprintf("Component %i", i) attr(out, "footer") <- sprintf( "Mean inter-item-correlation = %.3f Cronbach's alpha = %.3f", attributes(out)$item_intercorrelation, attributes(out)$cronbachs_alpha ) out }), digits = digits, format = "markdown", missing = "", align = "firstleft", zap_small = TRUE ) } # helper ------------------------------------ .print_md_compare_performance <- function(x, digits = 2, caption = "Comparison of Model Performance Indices", layout = "horizontal", format = "markdown", ...) { layout <- match.arg(layout, choices = c("horizontal", "vertical")) formatted_table <- format(x = x, digits = digits, format = format, ...) if ("Performance_Score" %in% colnames(x)) { footer <- sprintf( "Model %s (of class %s) performed best with an overall performance score of %s.", formatted_table$Model[1], formatted_table$Type[1], formatted_table$Performance_Score[1] ) } else { footer <- NULL } # switch to vertical layout if (layout == "vertical") { formatted_table <- datawizard::rownames_as_column(as.data.frame(t(formatted_table)), "Metric") formatted_table <- datawizard::row_to_colnames(formatted_table) colnames(formatted_table)[1] <- "Metric" } insight::export_table( x = formatted_table, digits = digits, format = format, caption = caption, footer = footer, align = "firstleft" ) } performance/R/performance_cv.R0000644000176200001440000002042314623661613016101 0ustar liggesusers#' @title Cross-validated model performance #' @name performance_cv #' #' @description This function cross-validates regression models in a #' user-supplied new sample or by using holdout (train-test), k-fold, or #' leave-one-out cross-validation. #' #' @param model A regression model. #' @param data Optional. A data frame containing the same variables as `model` #' that will be used as the cross-validation sample. #' @param method Character string, indicating the cross-validation method to use: #' whether holdout (`"holdout"`, aka train-test), k-fold (`"k_fold"`), or #' leave-one-out (`"loo"`). If `data` is supplied, this argument is ignored. #' @param metrics Can be `"all"`, `"common"` or a character vector of metrics to be #' computed (some of `c("ELPD", "Deviance", "MSE", "RMSE", "R2")`). "common" will #' compute R2 and RMSE. #' @param prop If `method = "holdout"`, what proportion of the sample to hold #' out as the test sample? #' @param k If `method = "k_fold"`, the number of folds to use. #' @param stack Logical. If `method = "k_fold"`, should performance be computed #' by stacking residuals from each holdout fold and calculating each metric on #' the stacked data (`TRUE`, default) or should performance be computed by #' calculating metrics within each holdout fold and averaging performance #' across each fold (`FALSE`)? #' @param verbose Toggle warnings. #' @param ... Not used. #' #' @return A data frame with columns for each metric requested, as well as `k` #' if `method = "holdout"` and the `Method` used for cross-validation. If #' `method = "holdout"` and `stack = TRUE`, the standard error (standard #' deviation across holdout folds) for each metric is also included. #' #' @examples #' model <- lm(mpg ~ wt + cyl, data = mtcars) #' performance_cv(model) #' #' @export performance_cv <- function(model, data = NULL, method = c("holdout", "k_fold", "loo"), metrics = "all", prop = 0.30, k = 5, stack = TRUE, verbose = TRUE, ...) { if (all(metrics == "all")) { metrics <- c("MSE", "RMSE", "R2") } else if (all(metrics == "common")) { metrics <- c("RMSE", "R2") } else { metrics <- toupper(metrics) metrics[metrics == "DEVIANCE"] <- "Deviance" } if (is.null(data)) { method <- match.arg(method, choices = c("holdout", "k_fold", "loo")) } if (!is.null(data) && inherits(model, "BFBayesFactor")) { insight::format_error("Models of class 'BFBayesFactor' not yet supported.") } resp.name <- insight::find_response(model) model_data <- insight::get_data(model, verbose = FALSE) info <- insight::model_info(model, verbose = verbose) if (info$is_linear) { if (!is.null(data)) { method <- "holdout" stack <- TRUE test_resp <- data[, resp.name] test_pred <- insight::get_predicted(model, ci = NULL, data = data) test_resd <- test_resp - test_pred } else if (method == "holdout") { train_i <- sample.int(nrow(model_data), size = round((1 - prop) * nrow(model_data)), replace = FALSE) model_upd <- stats::update(model, data = model_data[train_i, ]) test_resp <- model_data[-train_i, resp.name] test_pred <- insight::get_predicted(model_upd, ci = NULL, data = model_data[-train_i, ]) test_resd <- test_resp - test_pred } else if (method == "loo" && !info$is_bayesian) { model_response <- insight::get_response(model) MSE <- mean(insight::get_residuals(model, weighted = TRUE)^2 / (1 - stats::hatvalues(model))^2) mean(test_resd^2, na.rm = TRUE) RMSE <- sqrt(MSE) R2 <- 1 - MSE / (mean(model_response^2, na.rm = TRUE) - mean(model_response, na.rm = TRUE)^2) out <- data.frame(MSE = MSE, RMSE = RMSE, R2 = R2) } else { # Manual method for LOO, use this for non-linear and Bayesian models if (method == "loo") { if (info$is_bayesian && verbose) { insight::format_alert( "Simple LOO cross-validation can be very slow for MCMC models.", "Try loo::loo() instead." ) } stack <- TRUE k <- nrow(model_data) } if (k > nrow(model_data)) { message(insight::color_text(insight::format_message( "Requested number of folds (k) larger than the sample size.", "'k' set equal to the sample size (leave-one-out [LOO])." ), color = "yellow")) k <- nrow(model_data) } cv_folds <- .crossv_kfold(model_data, k = k) models_upd <- lapply(cv_folds, function(.x) { stats::update(model, data = model_data[.x$train, ]) }) test_pred <- mapply(function(.x, .y) { insight::get_predicted(.y, ci = NULL, data = model_data[.x$test, ]) }, cv_folds, models_upd, SIMPLIFY = FALSE) test_resp <- lapply(cv_folds, function(.x) { as.data.frame(model_data[.x$test, ])[[resp.name]] }) } } else { insight::format_error("Only linear models currently supported.") } if (isTRUE(stack)) { test_resp <- unlist(test_resp) test_pred <- unlist(test_pred) test_resd <- test_resp - test_pred MSE <- mean(test_resd^2, na.rm = TRUE) RMSE <- sqrt(MSE) R2 <- 1 - MSE / mean((test_resp - mean(test_resp, na.rm = TRUE))^2, na.rm = TRUE) out <- data.frame(MSE = MSE, RMSE = RMSE, R2 = R2) } else { test_resd <- mapply(function(.x, .y) { .x - .y }, test_resp, test_pred, SIMPLIFY = FALSE) MSEs <- sapply(test_resd, function(x) mean(x^2, na.rm = TRUE)) RMSEs <- sqrt(MSEs) resp_vars <- sapply(test_resp, function(x) mean((x - mean(x, na.rm = TRUE))^2, na.rm = TRUE)) R2s <- 1 - MSEs / resp_vars out <- data.frame( MSE = mean(MSEs), MSE_SE = stats::sd(MSEs), RMSE = mean(RMSEs), RMSE_SE = stats::sd(RMSEs), R2 = mean(R2s), R2_SE = stats::sd(R2s) ) } out <- out[, colnames(out) %in% c(metrics, paste0(metrics, "_SE"))] attr(out, "method") <- method attr(out, "k") <- if (method == "k_fold") k attr(out, "prop") <- if (method == "holdout") prop missing_metrics <- setdiff(metrics, c("MSE", "RMSE", "R2")) if (length(missing_metrics)) { message(insight::colour_text(insight::format_message( paste0( "Metric", ifelse(length(missing_metrics) > 1, "s '", " '"), paste0(missing_metrics, collapse = "', '"), "' not yet supported." ) ), colour = "red")) } class(out) <- c("performance_cv", "data.frame") return(out) } # TODO: implement performance::log_lik() function for deviance/elpd metrics # - When given a model, it should pass it to insight::get_loglikelihood, stats4::logLik, stats::logLik, or rstantools::log_lik # - When given a model and new data, it should pass to rstantools::log_lik if stan # or compute a df like this: # df <- list(residuals = cv_residuals); class(df) <- class(model) # then pass this df to stats4::logLik or stats::logLik # - for model classes that do not compute their ll inside of logLik, # then compute the ll by running: # logLik(update(model, formula = {{response}} ~ 0, offset = predict(model, newdata), data = newdata)) # methods ---------------------------------- #' @export print.performance_cv <- function(x, digits = 2, ...) { method <- switch(attr(x, "method"), holdout = paste0( insight::format_value(attr(x, "prop"), as_percent = TRUE, digits = 0), " holdout" ), k_fold = paste0(attr(x, "k"), "-fold"), loo = "leave-one-out [LOO]" ) formatted_table <- format( x = x, digits = digits, format = "text", ... ) cat(insight::export_table( x = formatted_table, digits = digits, format = "text", caption = c(paste0( "# Cross-validation performance (", method, " method)" ), "blue"), ... )) invisible(x) } #' @export as.data.frame.performance_cv <- function(x, row.names = NULL, ...) { data.frame( Accuracy = x$Accuracy, SE = x$SE, Method = x$Method, stringsAsFactors = FALSE, row.names = row.names, ... ) } performance/R/check_sphericity.R0000644000176200001440000000502714736731423016435 0ustar liggesusers#' @title Check model for violation of sphericity #' @name check_sphericity #' #' @description Check model for violation of sphericity. For [Bartlett's Test of Sphericity][check_factorstructure] #' (used for correlation matrices and factor analyses), see [check_sphericity_bartlett]. #' #' @param x A model object. #' @param ... Arguments passed to `car::Anova`. #' #' @return Invisibly returns the p-values of the test statistics. A p-value < #' 0.05 indicates a violation of sphericity. #' #' @examplesIf require("car") && require("carData") #' data(Soils, package = "carData") #' soils.mod <- lm( #' cbind(pH, N, Dens, P, Ca, Mg, K, Na, Conduc) ~ Block + Contour * Depth, #' data = Soils #' ) #' #' check_sphericity(Manova(soils.mod)) #' @export check_sphericity <- function(x, ...) { UseMethod("check_sphericity") } # default -------------------------- #' @export check_sphericity.default <- function(x, ...) { insight::format_error(paste0("Test not supported yet for object of class `", class(x)[1], "`.")) } # methods ------------------------------ #' @export plot.check_sphericity <- function(x, ...) { insight::format_warning("There is currently no `plot()` method for `check_sphericity()`.") } #' @export print.check_sphericity <- function(x, ...) { if (any(x < 0.05)) { pp <- x[x < 0.05] pp <- paste0("\n - ", names(pp), " (", insight::format_p(pp), ")", collapse = "") insight::print_color(sprintf("Warning: Sphericity violated for: %s.\n", pp), "red") } else { pp <- insight::format_p(min(x)) pp <- sub("=", ">", pp, fixed = TRUE) insight::print_color(sprintf("OK: Data seems to be spherical (%s).\n", pp), "green") } invisible(x) } # other classes ------------------ #' @export check_sphericity.Anova.mlm <- function(x, ...) { S <- summary(x, multivariate = FALSE, univariate = TRUE) test <- S$sphericity.tests p.val <- test[, 2] # validation check if (is.null(p.val)) { p.val <- 1 } attr(p.val, "data") <- x class(p.val) <- c("check_sphericity", "see_check_sphericity", class(p.val)) p.val } #' @export check_sphericity.afex_aov <- function(x, ...) { if (length(attr(x, "within")) == 0) { insight::format_error("Mauchly Test of Sphericity is only aplicable to ANOVAs with within-subjects factors.") } check_sphericity.Anova.mlm(x, ...) } #' @export check_sphericity.mlm <- function(x, ...) { insight::check_if_installed("car") check_sphericity.Anova.mlm(car::Anova(x, ...)) } performance/R/check_multimodal.R0000644000176200001440000000740014736731423016416 0ustar liggesusers#' Check if a distribution is unimodal or multimodal #' #' For univariate distributions (one-dimensional vectors), this functions #' performs a Ameijeiras-Alonso et al. (2018) excess mass test. For multivariate #' distributions (data frames), it uses mixture modelling. However, it seems that #' it always returns a significant result (suggesting that the distribution is #' multimodal). A better method might be needed here. #' #' #' @param x A numeric vector or a data frame. #' @param ... Arguments passed to or from other methods. #' #' @examplesIf require("multimode") && require("mclust") #' \donttest{ #' # Univariate #' x <- rnorm(1000) #' check_multimodal(x) #' #' x <- c(rnorm(1000), rnorm(1000, 2)) #' check_multimodal(x) #' #' # Multivariate #' m <- data.frame( #' x = rnorm(200), #' y = rbeta(200, 2, 1) #' ) #' plot(m$x, m$y) #' check_multimodal(m) #' #' m <- data.frame( #' x = c(rnorm(100), rnorm(100, 4)), #' y = c(rbeta(100, 2, 1), rbeta(100, 1, 4)) #' ) #' plot(m$x, m$y) #' check_multimodal(m) #' } #' @references #' - Ameijeiras-Alonso, J., Crujeiras, R. M., and Rodríguez-Casal, A. (2019). #' Mode testing, critical bandwidth and excess mass. Test, 28(3), 900-919. #' #' @export check_multimodal <- function(x, ...) { UseMethod("check_multimodal") } #' @export check_multimodal.data.frame <- function(x, ...) { insight::check_if_installed("mclust") mclustBIC <- mclust::mclustBIC # this is needed as it is internally required by the following functions model <- mclust::Mclust(x, verbose = FALSE) model_h0 <- mclust::Mclust(x, G = 1, verbose = FALSE) # Parametric loglik <- stats::logLik(model) loglik0 <- stats::logLik(model_h0) rez <- list(Chisq = as.numeric(loglik - loglik0), df = attributes(loglik)$df - 2) rez$p <- 1 - stats::pchisq(rez$Chisq, df = rez$df) # Text msg <- "The parametric mixture modelling test suggests that " if (rez$p < 0.05) { msg <- paste0( msg, "the multivariate distribution is significantly multimodal (Chi2(", insight::format_value(rez$df, protect_integers = TRUE), ") = ", insight::format_value(rez$Chisq), ", ", insight::format_p(rez$p), ").\n" ) color <- "green" } else { msg <- paste0( msg, "the hypothesis of a multimodal multivariate distribution cannot be rejected (Chi2(", insight::format_value(rez$df, protect_integers = TRUE), ") = ", insight::format_value(rez$Chisq), ", ", insight::format_p(rez$p), ").\n" ) color <- "yellow" } attr(rez, "text") <- insight::format_message(msg) attr(rez, "color") <- color attr(rez, "title") <- "Is the data multimodal?" class(rez) <- c("easystats_check", class(rez)) rez } #' @export check_multimodal.numeric <- function(x, ...) { insight::check_if_installed("multimode") rez <- multimode::modetest(x, mod0 = 1, method = "ACR") rez <- list(p = rez$p.value, excess_mass = rez$statistic) msg <- "The Ameijeiras-Alonso et al. (2018) excess mass test suggests that " if (rez$p < 0.05) { msg <- paste0( msg, "the distribution is significantly multimodal (excess mass = ", insight::format_value(rez$excess_mass), ", ", insight::format_p(rez$p), ").\n" ) color <- "green" } else { msg <- paste0( msg, "the hypothesis of a multimodal distribution cannot be rejected (excess mass = ", insight::format_value(rez$excess_mass), ", ", insight::format_p(rez$p), ").\n" ) color <- "yellow" } attr(rez, "text") <- insight::format_message(msg) attr(rez, "color") <- color attr(rez, "title") <- "Is the variable multimodal?" class(rez) <- c("easystats_check", class(rez)) rez } performance/R/binned_residuals.R0000644000176200001440000002151614741711161016421 0ustar liggesusers#' @title Binned residuals for binomial logistic regression #' @name binned_residuals #' #' @description Check model quality of binomial logistic regression models. #' #' @param model A `glm`-object with *binomial*-family. #' @param term Name of independent variable from `x`. If not `NULL`, #' average residuals for the categories of `term` are plotted; else, #' average residuals for the estimated probabilities of the response are #' plotted. #' @param n_bins Numeric, the number of bins to divide the data. If #' `n_bins = NULL`, the square root of the number of observations is #' taken. #' @param ci Numeric, the confidence level for the error bounds. #' @param ci_type Character, the type of error bounds to calculate. Can be #' `"exact"` (default), `"gaussian"` or `"boot"`. `"exact"` calculates the #' error bounds based on the exact binomial distribution, using [`binom.test()`]. #' `"gaussian"` uses the Gaussian approximation, while `"boot"` uses a simple #' bootstrap method, where confidence intervals are calculated based on the #' quantiles of the bootstrap distribution. #' @param residuals Character, the type of residuals to calculate. Can be #' `"deviance"` (default), `"pearson"` or `"response"`. It is recommended to #' use `"response"` only for those models where other residuals are not #' available. #' @param iterations Integer, the number of iterations to use for the #' bootstrap method. Only used if `ci_type = "boot"`. #' @param show_dots Logical, if `TRUE`, will show data points in the plot. Set #' to `FALSE` for models with many observations, if generating the plot is too #' time-consuming. By default, `show_dots = NULL`. In this case `binned_residuals()` #' tries to guess whether performance will be poor due to a very large model #' and thus automatically shows or hides dots. #' @param verbose Toggle warnings and messages. #' @param ... Currently not used. #' #' @return A data frame representing the data that is mapped in the accompanying #' plot. In case all residuals are inside the error bounds, points are black. #' If some of the residuals are outside the error bounds (indicated by the #' grey-shaded area), blue points indicate residuals that are OK, while red #' points indicate model under- or over-fitting for the relevant range of #' estimated probabilities. #' #' @details Binned residual plots are achieved by "dividing the data into #' categories (bins) based on their fitted values, and then plotting #' the average residual versus the average fitted value for each bin." #' _(Gelman, Hill 2007: 97)_. If the model were true, one would #' expect about 95% of the residuals to fall inside the error bounds. #' #' If `term` is not `NULL`, one can compare the residuals in #' relation to a specific model predictor. This may be helpful to check if a #' term would fit better when transformed, e.g. a rising and falling pattern #' of residuals along the x-axis is a signal to consider taking the logarithm #' of the predictor (cf. Gelman and Hill 2007, pp. 97-98). #' #' @note `binned_residuals()` returns a data frame, however, the `print()` #' method only returns a short summary of the result. The data frame itself #' is used for plotting. The `plot()` method, in turn, creates a ggplot-object. #' #' @references #' Gelman, A., and Hill, J. (2007). Data analysis using regression and #' multilevel/hierarchical models. Cambridge; New York: Cambridge University #' Press. #' #' @examples #' model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") #' result <- binned_residuals(model) #' result #' #' # look at the data frame #' as.data.frame(result) #' #' @examplesIf insight::check_if_installed("see", minimum_version = "0.9.1", quietly = TRUE) #' \donttest{ #' # plot #' plot(result, show_dots = TRUE) #' } #' #' @export binned_residuals <- function(model, term = NULL, n_bins = NULL, show_dots = NULL, ci = 0.95, ci_type = c("exact", "gaussian", "boot"), residuals = c("deviance", "pearson", "response"), iterations = 1000, verbose = TRUE, ...) { ci_type <- match.arg(ci_type) residuals <- match.arg(residuals) # for non-bernoulli models, `"exact"` doesn't work if (isFALSE(insight::model_info(model)$is_bernoulli)) { ci_type <- "gaussian" if (verbose) { insight::format_alert("Using `ci_type = \"gaussian\"` because model is not bernoulli.") } } fitted_values <- stats::fitted(model) mf <- insight::get_data(model, verbose = FALSE) if (is.null(term)) { pred <- fitted_values } else { pred <- mf[[term]] } # set default for show_dots, based on "model size" if (is.null(show_dots)) { n <- .safe(insight::n_obs(model)) show_dots <- is.null(n) || n <= 1e5 } # make sure response is 0/1 (and numeric) y0 <- .recode_to_zero(insight::get_response(model, verbose = FALSE)) # calculate residuals y <- switch(residuals, response = y0 - fitted_values, pearson = .safe((y0 - fitted_values) / sqrt(fitted_values * (1 - fitted_values))), deviance = .safe(stats::residuals(model, type = "deviance")) ) # make sure we really have residuals if (is.null(y)) { insight::format_error("Could not calculate residuals. Try using `residuals = \"response\"`.") } if (is.null(n_bins)) n_bins <- round(sqrt(length(pred))) breaks.index <- floor(length(pred) * (1:(n_bins - 1)) / n_bins) breaks <- unique(c(-Inf, sort(pred)[breaks.index], Inf)) model.binned <- as.numeric(cut(pred, breaks)) d <- suppressWarnings(lapply(1:n_bins, function(.x) { items <- (seq_along(pred))[model.binned == .x] model.range <- range(pred[items], na.rm = TRUE) xbar <- mean(pred[items], na.rm = TRUE) ybar <- mean(y[items], na.rm = TRUE) n <- length(items) sdev <- stats::sd(y[items], na.rm = TRUE) # sanity check - do we have any data in our bin? if (n == 0) { conf_int <- stats::setNames(c(NA, NA), c("CI_low", "CI_high")) } else { conf_int <- switch(ci_type, gaussian = stats::qnorm(c((1 - ci) / 2, (1 + ci) / 2), mean = ybar, sd = sdev / sqrt(n)), exact = { out <- stats::binom.test(sum(y0[items]), n)$conf.int # center CIs around point estimate out <- out - (min(out) - ybar) - (diff(out) / 2) out }, boot = .boot_binned_ci(y[items], ci, iterations) ) names(conf_int) <- c("CI_low", "CI_high") } d0 <- data.frame( xbar = xbar, ybar = ybar, n = n, x.lo = model.range[1], x.hi = model.range[2], se = stats::qnorm((1 + ci) / 2) * sdev / sqrt(n) ) cbind(d0, rbind(conf_int)) })) d <- do.call(rbind, d) d <- d[stats::complete.cases(d), ] gr <- abs(d$ybar) > abs(d$se) d$group <- "yes" d$group[gr] <- "no" resid_ok <- sum(d$group == "yes") / length(d$group) class(d) <- c("binned_residuals", "see_binned_residuals", class(d)) attr(d, "resid_ok") <- resid_ok attr(d, "resp_var") <- insight::find_response(model) attr(d, "term") <- term attr(d, "show_dots") <- show_dots d } # utilities --------------------------- .boot_binned_ci <- function(x, ci = 0.95, iterations = 1000) { x <- x[!is.na(x)] n <- length(x) out <- vector("numeric", iterations) for (i in seq_len(iterations)) { out[i] <- sum(x[sample.int(n, n, replace = TRUE)]) } out <- out / n quant <- stats::quantile(out, c((1 - ci) / 2, (1 + ci) / 2), na.rm = TRUE) c(CI_low = quant[1L], CI_high = quant[2L]) } # methods ----------------------------- #' @export print.binned_residuals <- function(x, ...) { resid_ok <- attributes(x)$resid_ok if (!is.null(resid_ok)) { if (resid_ok < 0.8) { insight::print_color( sprintf( "Warning: Probably bad model fit. Only about %g%% of the residuals are inside the error bounds.\n", round(100 * resid_ok) ), "red" ) } else if (resid_ok < 0.95) { insight::print_color( sprintf( "Warning: About %g%% of the residuals are inside the error bounds (~95%% or higher would be good).\n", round(100 * resid_ok) ), "yellow" ) } else { insight::print_color( sprintf( "Ok: About %g%% of the residuals are inside the error bounds.\n", round(100 * resid_ok) ), "green" ) } } } #' @export plot.binned_residuals <- function(x, ...) { insight::check_if_installed("see", "to plot binned residuals") NextMethod() } performance/R/r2_coxsnell.R0000644000176200001440000001710714736731423015351 0ustar liggesusers#' @title Cox & Snell's R2 #' @name r2_coxsnell #' #' @description #' Calculates the pseudo-R2 value based on the proposal from *Cox & Snell (1989)*. #' #' @param model Model with binary outcome. #' @param ... Currently not used. #' #' @details #' This index was proposed by *Cox and Snell (1989, pp. 208-9)* and, apparently #' independently, by *Magee (1990)*; but had been suggested earlier for binary #' response models by *Maddala (1983)*. However, this index achieves a maximum #' of less than 1 for discrete models (i.e. models whose likelihood is a product #' of probabilities) which have a maximum of 1, instead of densities, which can #' become infinite *(Nagelkerke, 1991)*. #' #' @return A named vector with the R2 value. #' #' @examples #' model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") #' r2_coxsnell(model) #' #' @references #' - Cox, D. R., Snell, E. J. (1989). Analysis of binary data (Vol. 32). #' Monographs on Statistics and Applied Probability. #' - Magee, L. (1990). R 2 measures based on Wald and likelihood ratio joint #' significance tests. The American Statistician, 44(3), 250-253. #' - Maddala, G. S. (1986). Limited-dependent and qualitative variables in #' econometrics (No. 3). Cambridge university press. #' - Nagelkerke, N. J. (1991). A note on a general definition of the coefficient #' of determination. Biometrika, 78(3), 691-692. #' #' @export r2_coxsnell <- function(model, ...) { UseMethod("r2_coxsnell") } # helper --------------------------- .r2_coxsnell <- function(model, l_base) { l_full <- insight::get_loglikelihood(model) G2 <- -2 * (l_base - l_full) # Is it still necessary? if (inherits(model, c("vglm", "vgam", "clm2"))) { n <- suppressWarnings(insight::n_obs(model)) } else { n <- attr(l_full, "nobs") if (is.null(n)) n <- suppressWarnings(insight::n_obs(model, disaggregate = TRUE)) } r2_coxsnell <- as.vector(1 - exp(-G2 / n)) names(r2_coxsnell) <- "Cox & Snell's R2" r2_coxsnell } # r2-coxsnell based on model information --------------------------- #' @export r2_coxsnell.glm <- function(model, verbose = TRUE, ...) { info <- list(...)$model_info if (is.null(info)) { info <- suppressWarnings(insight::model_info(model, verbose = FALSE)) } matrix_response <- grepl("cbind", insight::find_response(model), fixed = TRUE) # Cox & Snell's R2 is not defined for binomial models that are not Bernoulli models if (info$is_binomial && !info$is_betabinomial && !info$is_bernoulli && class(model)[1] %in% c("glm", "glmmTMB")) { if (verbose) { insight::format_alert("Can't calculate accurate R2 for binomial models that are not Bernoulli models.") } return(NULL) } # currently, beta-binomial models without proportion response are not supported if (info$is_betabinomial && matrix_response) { if (verbose) { insight::format_warning("Can't calculate accurate R2 for beta-binomial models with matrix-response formulation.") } return(NULL) } # if no deviance, return NULL if (is.null(model$deviance)) { return(NULL) } r2_coxsnell <- (1 - exp((model$deviance - model$null.deviance) / insight::n_obs(model, disaggregate = TRUE))) names(r2_coxsnell) <- "Cox & Snell's R2" r2_coxsnell } #' @export r2_coxsnell.BBreg <- r2_coxsnell.glm #' @export r2_coxsnell.glmmTMB <- function(model, verbose = TRUE, ...) { info <- list(...)$model_info if (is.null(info)) { info <- suppressWarnings(insight::model_info(model, verbose = FALSE)) } # Cox & Snell's R2 is not defined for binomial models that are not Bernoulli models if (info$is_binomial && !info$is_bernoulli && !info$is_betabinomial) { if (verbose) { insight::format_alert("Can't calculate accurate R2 for binomial models that are not Bernoulli models.") } return(NULL) } dev <- stats::deviance(model) # if no deviance, return NULL if (is.null(dev)) { return(NULL) } null_dev <- stats::deviance(insight::null_model(model)) r2_coxsnell <- (1 - exp((dev - null_dev) / insight::n_obs(model, disaggregate = TRUE))) names(r2_coxsnell) <- "Cox & Snell's R2" r2_coxsnell } #' @export r2_coxsnell.nestedLogit <- function(model, ...) { n <- insight::n_obs(model, disaggregate = TRUE) stats::setNames( lapply(names(model$models), function(i) { m <- model$models[[i]] # if no deviance, return NA if (is.null(m$deviance)) { return(NA) } r2_coxsnell <- (1 - exp((m$deviance - m$null.deviance) / n[[i]])) names(r2_coxsnell) <- "Cox & Snell's R2" r2_coxsnell }), names(model$models) ) } #' @export r2_coxsnell.mclogit <- function(model, ...) { insight::check_if_installed("mclogit", reason = "to calculate R2") s <- mclogit::getSummary.mclogit(model) r2_coxsnell <- s$sumstat["Cox.Snell"] names(r2_coxsnell) <- "Cox & Snell's R2" r2_coxsnell } #' @export r2_coxsnell.mblogit <- function(model, ...) { insight::check_if_installed("mclogit", reason = "to calculate R2") s <- mclogit::getSummary.mblogit(model) r2_coxsnell <- s$sumstat["Cox.Snell"] names(r2_coxsnell) <- "Cox & Snell's R2" r2_coxsnell } #' @export r2_coxsnell.bife <- function(model, ...) { r2_coxsnell <- (1 - exp((model$deviance - model$null_deviance) / insight::n_obs(model))) names(r2_coxsnell) <- "Cox & Snell's R2" r2_coxsnell } # mfx models --------------------- #' @export r2_coxsnell.logitmfx <- function(model, ...) { r2_coxsnell(model$fit, ...) } #' @export r2_coxsnell.logitor <- r2_coxsnell.logitmfx #' @export r2_coxsnell.poissonirr <- r2_coxsnell.logitmfx #' @export r2_coxsnell.poissonmfx <- r2_coxsnell.logitmfx #' @export r2_coxsnell.probit <- r2_coxsnell.logitmfx #' @export r2_coxsnell.negbinirr <- r2_coxsnell.logitmfx #' @export r2_coxsnell.negbinmfx <- r2_coxsnell.logitmfx # r2-coxsnell based on loglik stored in model object --------------------------- #' @export r2_coxsnell.coxph <- function(model, ...) { l_base <- model$loglik[1] .r2_coxsnell(model, l_base) } #' @export r2_coxsnell.survreg <- r2_coxsnell.coxph #' @export r2_coxsnell.svycoxph <- function(model, ...) { l_base <- model$ll[1] .r2_coxsnell(model, l_base) } # r2-coxsnell based on loglik of null-model (update) --------------------------- #' @export r2_coxsnell.multinom <- function(model, ...) { l_base <- insight::get_loglikelihood(stats::update(model, ~1, trace = FALSE)) .r2_coxsnell(model, l_base) } #' @export r2_coxsnell.clm2 <- function(model, ...) { l_base <- insight::get_loglikelihood(stats::update(model, location = ~1, scale = ~1)) .r2_coxsnell(model, l_base) } #' @export r2_coxsnell.bayesx <- function(model, ...) { junk <- utils::capture.output(l_base <- insight::get_loglikelihood(stats::update(model, ~1))) # nolint .r2_coxsnell(model, l_base) } #' @export r2_coxsnell.clm <- function(model, ...) { l_base <- insight::get_loglikelihood(stats::update(model, ~1)) # if no loglik, return NA if (length(as.numeric(l_base)) == 0) { return(NULL) } .r2_coxsnell(model, l_base) } #' @export r2_coxsnell.crch <- r2_coxsnell.clm #' @export r2_coxsnell.serp <- r2_coxsnell.clm #' @export r2_coxsnell.cpglm <- r2_coxsnell.clm #' @export r2_coxsnell.censReg <- r2_coxsnell.clm #' @export r2_coxsnell.truncreg <- r2_coxsnell.clm #' @export r2_coxsnell.polr <- r2_coxsnell.clm #' @export r2_coxsnell.glmx <- r2_coxsnell.clm #' @export r2_coxsnell.DirichletRegModel <- r2_coxsnell.clm performance/R/compare_performance.R0000644000176200001440000003123314736731423017122 0ustar liggesusers#' @title Compare performance of different models #' @name compare_performance #' #' @description `compare_performance()` computes indices of model #' performance for different models at once and hence allows comparison of #' indices across models. #' #' @param ... Multiple model objects (also of different classes). #' @param metrics Can be `"all"`, `"common"` or a character vector of #' metrics to be computed. See related #' [`documentation()`][model_performance] of object's class for #' details. #' @param rank Logical, if `TRUE`, models are ranked according to 'best' #' overall model performance. See 'Details'. #' @inheritParams performance_aic #' #' @return A data frame with one row per model and one column per "index" (see #' `metrics`). #' #' @note There is also a [`plot()`-method](https://easystats.github.io/see/articles/performance.html) implemented in the \href{https://easystats.github.io/see/}{\pkg{see}-package}. #' #' @details \subsection{Model Weights}{ #' When information criteria (IC) are requested in `metrics` (i.e., any of `"all"`, #' `"common"`, `"AIC"`, `"AICc"`, `"BIC"`, `"WAIC"`, or `"LOOIC"`), model #' weights based on these criteria are also computed. For all IC except LOOIC, #' weights are computed as `w = exp(-0.5 * delta_ic) / sum(exp(-0.5 * delta_ic))`, #' where `delta_ic` is the difference between the model's IC value and the #' smallest IC value in the model set (Burnham and Anderson, 2002). #' For LOOIC, weights are computed as "stacking weights" using #' [loo::stacking_weights()]. #' } #' #' \subsection{Ranking Models}{ #' When `rank = TRUE`, a new column `Performance_Score` is returned. #' This score ranges from 0\% to 100\%, higher values indicating better model #' performance. Note that all score value do not necessarily sum up to 100\%. #' Rather, calculation is based on normalizing all indices (i.e. rescaling #' them to a range from 0 to 1), and taking the mean value of all indices for #' each model. This is a rather quick heuristic, but might be helpful as #' exploratory index. #' \cr \cr #' In particular when models are of different types (e.g. mixed models, #' classical linear models, logistic regression, ...), not all indices will be #' computed for each model. In case where an index can't be calculated for a #' specific model type, this model gets an `NA` value. All indices that #' have any `NA`s are excluded from calculating the performance score. #' \cr \cr #' There is a `plot()`-method for `compare_performance()`, #' which creates a "spiderweb" plot, where the different indices are #' normalized and larger values indicate better model performance. #' Hence, points closer to the center indicate worse fit indices #' (see [online-documentation](https://easystats.github.io/see/articles/performance.html) #' for more details). #' } #' #' \subsection{REML versus ML estimator}{ #' By default, `estimator = "ML"`, which means that values from information #' criteria (AIC, AICc, BIC) for specific model classes (like models from *lme4*) #' are based on the ML-estimator, while the default behaviour of `AIC()` for #' such classes is setting `REML = TRUE`. This default is intentional, because #' comparing information criteria based on REML fits is usually not valid #' (it might be useful, though, if all models share the same fixed effects - #' however, this is usually not the case for nested models, which is a #' prerequisite for the LRT). Set `estimator = "REML"` explicitly return the #' same (AIC/...) values as from the defaults in `AIC.merMod()`. #' } #' #' @references #' Burnham, K. P., and Anderson, D. R. (2002). #' _Model selection and multimodel inference: A practical information-theoretic approach_ (2nd ed.). #' Springer-Verlag. \doi{10.1007/b97636} #' #' @examplesIf require("lme4") #' data(iris) #' lm1 <- lm(Sepal.Length ~ Species, data = iris) #' lm2 <- lm(Sepal.Length ~ Species + Petal.Length, data = iris) #' lm3 <- lm(Sepal.Length ~ Species * Petal.Length, data = iris) #' compare_performance(lm1, lm2, lm3) #' compare_performance(lm1, lm2, lm3, rank = TRUE) #' #' m1 <- lm(mpg ~ wt + cyl, data = mtcars) #' m2 <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") #' m3 <- lme4::lmer(Petal.Length ~ Sepal.Length + (1 | Species), data = iris) #' compare_performance(m1, m2, m3) #' @inheritParams model_performance.lm #' @export compare_performance <- function(..., metrics = "all", rank = FALSE, estimator = "ML", verbose = TRUE) { # process input model_objects <- insight::ellipsis_info(..., only_models = TRUE) # ensure proper object names model_objects <- .check_objectnames(model_objects, sapply(match.call(expand.dots = FALSE)[["..."]], as.character)) # drop unsupport models supported_models <- sapply(model_objects, function(i) insight::is_model_supported(i) | inherits(i, "lavaan")) object_names <- names(model_objects) if (!all(supported_models)) { insight::format_alert( "Following objects are not supported:", datawizard::text_concatenate(object_names[!supported_models], enclose = "`") ) model_objects <- model_objects[supported_models] object_names <- object_names[supported_models] } # iterate over all models, i.e. model-performance for each model m <- mapply(function(.x, .y) { dat <- model_performance(.x, metrics = metrics, estimator = estimator, verbose = FALSE) model_name <- gsub("\"", "", insight::safe_deparse(.y), fixed = TRUE) perf_df <- data.frame(Name = model_name, Model = class(.x)[1], dat, stringsAsFactors = FALSE) attributes(perf_df) <- c(attributes(perf_df), attributes(dat)[!names(attributes(dat)) %in% c("names", "row.names", "class")]) perf_df }, model_objects, object_names, SIMPLIFY = FALSE) attri <- lapply(m, function(x) { attri <- attributes(x) attri[!names(attri) %in% c("names", "row.names", "class")] }) dfs <- Reduce(function(x, y) merge(x, y, all = TRUE, sort = FALSE), m) if (any(c("AIC", "AICc", "BIC", "WAIC") %in% names(dfs))) { dfs$AIC_wt <- .ic_weight(dfs[["AIC"]]) dfs$AICc_wt <- .ic_weight(dfs[["AICc"]]) dfs$BIC_wt <- .ic_weight(dfs[["BIC"]]) dfs$WAIC_wt <- .ic_weight(dfs[["WAIC"]]) } if ("LOOIC" %in% names(dfs)) { lpd_point <- do.call(cbind, lapply(attri, function(x) x$loo$pointwise[, "elpd_loo"])) dfs$LOOIC_wt <- as.numeric(loo::stacking_weights(lpd_point)) } # check if all models were fit from same data if (!isTRUE(attributes(model_objects)$same_response) && verbose) { insight::format_alert( "When comparing models, please note that probably not all models were fit from same data." ) } # create "ranking" of models if (isTRUE(rank)) { dfs <- .rank_performance_indices(dfs, verbose) } # Reorder columns if (all(c("BIC", "BF") %in% names(dfs))) { idx1 <- grep("^BIC$", names(dfs)) idx2 <- grep("BF", names(dfs), fixed = TRUE) last_part <- (idx1 + 1):ncol(dfs) dfs <- dfs[, c(1:idx1, idx2, last_part[last_part != idx2])] } if (all(c("AIC", "AIC_wt") %in% names(dfs))) { idx1 <- grep("^AIC$", names(dfs)) idx2 <- grep("AIC_wt", names(dfs), fixed = TRUE) last_part <- (idx1 + 1):ncol(dfs) dfs <- dfs[, c(1:idx1, idx2, last_part[last_part != idx2])] } if (all(c("BIC", "BIC_wt") %in% names(dfs))) { idx1 <- grep("^BIC$", names(dfs)) idx2 <- grep("BIC_wt", names(dfs), fixed = TRUE) last_part <- (idx1 + 1):ncol(dfs) dfs <- dfs[, c(1:idx1, idx2, last_part[last_part != idx2])] } if (all(c("AICc", "AICc_wt") %in% names(dfs))) { idx1 <- grep("^AICc$", names(dfs)) idx2 <- grep("AICc_wt", names(dfs), fixed = TRUE) last_part <- (idx1 + 1):ncol(dfs) dfs <- dfs[, c(1:idx1, idx2, last_part[last_part != idx2])] } if (all(c("WAIC", "WAIC_wt") %in% names(dfs))) { idx1 <- grep("^WAIC$", names(dfs)) idx2 <- grep("WAIC_wt", names(dfs), fixed = TRUE) last_part <- (idx1 + 1):ncol(dfs) dfs <- dfs[, c(1:idx1, idx2, last_part[last_part != idx2])] } if (all(c("LOOIC", "LOOIC_wt") %in% names(dfs))) { idx1 <- grep("^LOOIC$", names(dfs)) idx2 <- grep("LOOIC_wt", names(dfs), fixed = TRUE) last_part <- (idx1 + 1):ncol(dfs) dfs <- dfs[, c(1:idx1, idx2, last_part[last_part != idx2])] } # for REML fits, warn user if (isTRUE(verbose) && # only warn for REML fit identical(estimator, "REML") && # only for IC comparison any(grepl("(AIC|BIC)", names(dfs))) && # only when mixed models are involved, others probably don't have problems with REML fit any(sapply(model_objects, insight::is_mixed_model)) && # only if not all models have same fixed effects (else, REML is ok) !isTRUE(attributes(model_objects)$same_fixef)) { insight::format_alert( "Information criteria (like AIC) are based on REML fits (i.e. `estimator=\"REML\"`).", "Please note that information criteria are probably not directly comparable and that it is not recommended comparing models with different fixed effects in such cases." ) } # dfs[order(sapply(object_names, as.character), dfs$Model), ] class(dfs) <- c("compare_performance", "see_compare_performance", class(dfs)) dfs } # methods ---------------------------- #' @export print.compare_performance <- function(x, digits = 3, layout = "horizontal", ...) { layout <- match.arg(layout, choices = c("horizontal", "vertical")) table_caption <- c("# Comparison of Model Performance Indices", "blue") formatted_table <- format(x = x, digits = digits, format = "text", ...) if ("Performance_Score" %in% colnames(formatted_table)) { footer <- c(sprintf("\nModel `%s` (of class `%s`) performed best with an overall performance score of %s.", formatted_table$Model[1], formatted_table$Type[1], formatted_table$Performance_Score[1]), "yellow") } else { footer <- NULL } # switch to vertical layout if (layout == "vertical") { formatted_table <- datawizard::rownames_as_column(as.data.frame(t(formatted_table)), "Metric") formatted_table <- datawizard::row_to_colnames(formatted_table) colnames(formatted_table)[1] <- "Metric" } cat(insight::export_table(x = formatted_table, digits = digits, format = "text", caption = table_caption, footer = footer, ...)) invisible(x) } #' @export plot.compare_performance <- function(x, ...) { insight::check_if_installed("see", "for model comparison plots") NextMethod() } # utilities ------------------------------ .rank_performance_indices <- function(x, verbose) { # all models comparable? if (length(unique(x$Type)) > 1 && isTRUE(verbose)) { insight::format_alert( "Models are not of same type. Comparison of indices might be not meaningful." ) } # set reference for Bayes factors to 1 if ("BF" %in% colnames(x)) x$BF[is.na(x$BF)] <- 1 # don't include test statistic in ranking x$p_CochransQ <- NULL x$p_Omnibus <- NULL x$p <- NULL x$p_LRT <- NULL # use weights instead of information criteria x$AIC <- NULL x$AICc <- NULL x$BIC <- NULL x$LOOIC <- NULL x$WAIC <- NULL # remove extra columns from LOO criteria x$ELPD <- NULL x$ELPD_SE <- NULL x$LOOIC_SE <- NULL # don't rank with BF when there is also BIC (same information) if ("BF" %in% colnames(x) && "BIC_wt" %in% colnames(x)) { x$BF <- NULL } out <- x # normalize indices, for comparison out[] <- lapply(out, function(i) { if (is.numeric(i)) i <- .normalize_vector(i) i }) # recode some indices, so higher values = better fit for (i in c("RMSE", "Sigma")) { if (i %in% colnames(out)) { out[[i]] <- 1 - out[[i]] } } # any indices with NA? missing_indices <- sapply(out, anyNA) if (any(missing_indices) && isTRUE(verbose)) { insight::format_alert(sprintf( "Following indices with missing values are not used for ranking: %s", toString(colnames(out)[missing_indices]) )) } # create rank-index, only for complete indices numeric_columns <- sapply(out, function(i) is.numeric(i) & !anyNA(i)) rank_index <- rowMeans(out[numeric_columns], na.rm = TRUE) x$Performance_Score <- rank_index x <- x[order(rank_index, decreasing = TRUE), ] rownames(x) <- NULL x } .normalize_vector <- function(x) { if (all(is.na(x)) || all(is.infinite(x))) { return(x) } as.vector((x - min(x, na.rm = TRUE)) / diff(range(x, na.rm = TRUE), na.rm = TRUE)) } .ic_weight <- function(ic) { # ic should be in the deviance metric (-2 * loglik) if (is.null(ic)) { return(NULL) } diffs <- ic - min(ic) f <- exp(-0.5 * diffs) f / sum(f) } performance/R/performance_roc.R0000644000176200001440000001465414736731423016267 0ustar liggesusers#' @title Simple ROC curve #' @name performance_roc #' #' @description #' This function calculates a simple ROC curves of x/y coordinates based on #' response and predictions of a binomial model. #' #' It returns the area under the curve (AUC) as a percentage, which corresponds #' to the probability that a randomly chosen observation of "condition 1" is #' correctly classified by the model as having a higher probability of being #' "condition 1" than a randomly chosen "condition 2" observation. #' #' Applying `as.data.frame()` to the output returns a data frame containing the #' following: #' - `Sensitivity` (that actually corresponds to `1 - Specificity`): It is the #' False Positive Rate. #' - `Sensitivity`: It is the True Positive Rate, which is the proportion of #' correctly classified "condition 1" observations. #' #' @param x A numeric vector, representing the outcome (0/1), or a model with #' binomial outcome. #' @param predictions If `x` is numeric, a numeric vector of same length #' as `x`, representing the actual predicted values. #' @param new_data If `x` is a model, a data frame that is passed to #' `predict()` as `newdata`-argument. If `NULL`, the ROC for #' the full model is calculated. #' @param ... One or more models with binomial outcome. In this case, #' `new_data` is ignored. #' #' @note There is also a [`plot()`-method](https://easystats.github.io/see/articles/performance.html) #' implemented in the \href{https://easystats.github.io/see/}{\pkg{see}-package}. #' #' @return A data frame with three columns, the x/y-coordinate pairs for the ROC #' curve (`Sensitivity` and `Specificity`), and a column with the #' model name. #' #' @examples #' library(bayestestR) #' data(iris) #' #' set.seed(123) #' iris$y <- rbinom(nrow(iris), size = 1, .3) #' folds <- sample(nrow(iris), size = nrow(iris) / 8, replace = FALSE) #' test_data <- iris[folds, ] #' train_data <- iris[-folds, ] #' #' model <- glm(y ~ Sepal.Length + Sepal.Width, data = train_data, family = "binomial") #' as.data.frame(performance_roc(model, new_data = test_data)) #' as.numeric(performance_roc(model)) #' #' roc <- performance_roc(model, new_data = test_data) #' area_under_curve(roc$Specificity, roc$Sensitivity) #' #' if (interactive()) { #' m1 <- glm(y ~ Sepal.Length + Sepal.Width, data = iris, family = "binomial") #' m2 <- glm(y ~ Sepal.Length + Petal.Width, data = iris, family = "binomial") #' m3 <- glm(y ~ Sepal.Length + Species, data = iris, family = "binomial") #' performance_roc(m1, m2, m3) #' #' # if you have `see` package installed, you can also plot comparison of #' # ROC curves for different models #' if (require("see")) plot(performance_roc(m1, m2, m3)) #' } #' @export performance_roc <- function(x, ..., predictions, new_data) { dots <- list(...) object_names <- c( insight::safe_deparse_symbol(substitute(x)), sapply(match.call(expand.dots = FALSE)$`...`, insight::safe_deparse) ) if (insight::is_model(x)) { info <- insight::model_info(x) } else { info <- NULL } if (is.numeric(x) && !missing(predictions) && !is.null(predictions)) { .performance_roc_numeric(x, predictions) } else if (inherits(x, c("logitor", "logitmfx", "probitmfx", "model_fit")) && length(dots) == 0) { if (missing(new_data)) new_data <- NULL .performance_roc_model(x$fit, new_data) } else if (info$is_binomial && length(dots) == 0) { if (missing(new_data)) new_data <- NULL .performance_roc_model(x, new_data) } else if (length(dots) > 0) { .performance_roc_models(list(x, ...), names = object_names) } } # methods ----------------------------- #' @export plot.performance_roc <- function(x, ...) { insight::check_if_installed("see", "to plot ROC-curves") NextMethod() } #' @export print.performance_roc <- function(x, ...) { if (length(unique(x$Model)) == 1) { cat(sprintf("AUC: %.2f%%\n", 100 * bayestestR::area_under_curve(x$Specificity, x$Sensitivity))) } else { insight::print_color("# Area under Curve\n\n", "blue") dat <- split(x, f = x$Model) max_space <- max(nchar(x$Model)) for (i in seq_along(dat)) { cat(sprintf( " %*s: %.2f%%\n", max_space, names(dat)[i], 100 * bayestestR::area_under_curve(dat[[i]]$Specificity, dat[[i]]$Sensitivity) )) } } invisible(x) } #' @export as.double.performance_roc <- function(x, ...) { if (length(unique(x$Model)) == 1) { auc <- bayestestR::area_under_curve(x$Specificity, x$Sensitivity) } else { dat <- split(x, f = x$Model) auc <- numeric(length(dat)) for (i in seq_along(dat)) { auc[i] <- bayestestR::area_under_curve(dat[[i]]$Specificity, dat[[i]]$Sensitivity) } } auc } # utilities --------------------------- .performance_roc_numeric <- function(x, predictions) { if (length(x) != length(predictions)) { insight::format_error("`x` and `predictions` must be of same length.") } x <- .recode_to_zero(x) x <- x[order(predictions, decreasing = TRUE)] res <- data.frame( Sensitivity = c(0, cumsum(x) / sum(x), 1), Specificity = c(0, cumsum(!x) / sum(!x), 1) ) class(res) <- c("performance_roc", "see_performance_roc", "data.frame") res } .performance_roc_model <- function(x, new_data, model_name = "Model 1") { predictions <- stats::predict(x, newdata = new_data, type = "response") if (is.null(new_data)) new_data <- insight::get_data(x, verbose = FALSE) response <- new_data[[insight::find_response(x)]] if ((is.data.frame(response) || is.matrix(response)) && ncol(response) > 1) { insight::format_error( "Can't calculate ROC for models with response-matrix (i.e. response variables with success/trials)." ) } dat <- .performance_roc_numeric(response, predictions) dat$Model <- model_name dat } .performance_roc_models <- function(x, names) { l <- lapply(seq_along(x), function(i) { if (.valid_roc_models(x[[i]])) { .performance_roc_model(x = x[[i]], new_data = NULL, model_name = names[i]) } else { insight::format_warning("Object '", names[i], "' is not valid.") } }) do.call(rbind, l) } # add supported glm models here .valid_roc_models <- function(x) { if (inherits(x, "model_fit")) { x <- x$fit } inherits(x, c("glm", "glmerMod", "logitor", "logitmfx", "probitmfx", "glmmTMB")) } performance/R/test_performance.R0000644000176200001440000004467514736731423016471 0ustar liggesusers#' @title Test if models are different #' #' @description #' Testing whether models are "different" in terms of accuracy or explanatory #' power is a delicate and often complex procedure, with many limitations and #' prerequisites. Moreover, many tests exist, each coming with its own #' interpretation, and set of strengths and weaknesses. #' #' The `test_performance()` function runs the most relevant and appropriate #' tests based on the type of input (for instance, whether the models are #' *nested* or not). However, it still requires the user to understand what the #' tests are and what they do in order to prevent their misinterpretation. See #' the *Details* section for more information regarding the different tests #' and their interpretation. #' #' @param ... Multiple model objects. #' @param reference This only applies when models are non-nested, and determines #' which model should be taken as a reference, against which all the other #' models are tested. #' @param text_length Numeric, length (number of chars) of output lines. #' `test_bf()` describes models by their formulas, which can lead to #' overly long lines in the output. `text_length` fixes the length of #' lines to a specified limit. #' @param verbose Toggle warning and messages. #' #' @return A data frame containing the relevant indices. #' #' @seealso [`compare_performance()`] to compare the performance indices of #' many different models. #' #' @details #' ## Nested vs. Non-nested Models #' Model's "nesting" is an important concept of models comparison. Indeed, many #' tests only make sense when the models are *"nested",* i.e., when their #' predictors are nested. This means that all the *fixed effects* predictors of #' a model are contained within the *fixed effects* predictors of a larger model #' (sometimes referred to as the encompassing model). For instance, #' `model1 (y ~ x1 + x2)` is "nested" within `model2 (y ~ x1 + x2 + x3)`. Usually, #' people have a list of nested models, for instance `m1 (y ~ 1)`, `m2 (y ~ x1)`, #' `m3 (y ~ x1 + x2)`, `m4 (y ~ x1 + x2 + x3)`, and it is conventional #' that they are "ordered" from the smallest to largest, but it is up to the #' user to reverse the order from largest to smallest. The test then shows #' whether a more parsimonious model, or whether adding a predictor, results in #' a significant difference in the model's performance. In this case, models are #' usually compared *sequentially*: m2 is tested against m1, m3 against m2, #' m4 against m3, etc. #' #' Two models are considered as *"non-nested"* if their predictors are #' different. For instance, `model1 (y ~ x1 + x2)` and `model2 (y ~ x3 + x4)`. #' In the case of non-nested models, all models are usually compared #' against the same *reference* model (by default, the first of the list). #' #' Nesting is detected via the `insight::is_nested_models()` function. #' Note that, apart from the nesting, in order for the tests to be valid, #' other requirements have often to be the fulfilled. For instance, outcome #' variables (the response) must be the same. You cannot meaningfully test #' whether apples are significantly different from oranges! #' #' ## Estimator of the standard deviation #' The estimator is relevant when comparing regression models using #' `test_likelihoodratio()`. If `estimator = "OLS"`, then it uses the same #' method as `anova(..., test = "LRT")` implemented in base R, i.e., scaling #' by n-k (the unbiased OLS estimator) and using this estimator under the #' alternative hypothesis. If `estimator = "ML"`, which is for instance used #' by `lrtest(...)` in package **lmtest**, the scaling is done by n (the #' biased ML estimator) and the estimator under the null hypothesis. In #' moderately large samples, the differences should be negligible, but it #' is possible that OLS would perform slightly better in small samples with #' Gaussian errors. For `estimator = "REML"`, the LRT is based on the REML-fit #' log-likelihoods of the models. Note that not all types of estimators are #' available for all model classes. #' #' ## REML versus ML estimator #' When `estimator = "ML"`, which is the default for linear mixed models (unless #' they share the same fixed effects), values from information criteria (AIC, #' AICc) are based on the ML-estimator, while the default behaviour of `AIC()` #' may be different (in particular for linear mixed models from **lme4**, which #' sets `REML = TRUE`). This default in `test_likelihoodratio()` intentional, #' because comparing information criteria based on REML fits requires the same #' fixed effects for all models, which is often not the case. Thus, while #' `anova.merMod()` automatically refits all models to REML when performing a #' LRT, `test_likelihoodratio()` checks if a comparison based on REML fits is #' indeed valid, and if so, uses REML as default (else, ML is the default). #' Set the `estimator` argument explicitely to override the default behaviour. #' #' ## Tests Description #' #' - **Bayes factor for Model Comparison** - `test_bf()`: If all #' models were fit from the same data, the returned `BF` shows the Bayes #' Factor (see `bayestestR::bayesfactor_models()`) for each model against #' the reference model (which depends on whether the models are nested or #' not). Check out #' [this vignette](https://easystats.github.io/bayestestR/articles/bayes_factors.html#bayesfactor_models) #' for more details. #' #' - **Wald's F-Test** - `test_wald()`: The Wald test is a rough #' approximation of the Likelihood Ratio Test. However, it is more applicable #' than the LRT: you can often run a Wald test in situations where no other #' test can be run. Importantly, this test only makes statistical sense if the #' models are nested. #' #' Note: this test is also available in base R #' through the [`anova()`][anova] function. It returns an `F-value` column #' as a statistic and its associated p-value. #' #' - **Likelihood Ratio Test (LRT)** - `test_likelihoodratio()`: #' The LRT tests which model is a better (more likely) explanation of the #' data. Likelihood-Ratio-Test (LRT) gives usually somewhat close results (if #' not equivalent) to the Wald test and, similarly, only makes sense for #' nested models. However, maximum likelihood tests make stronger assumptions #' than method of moments tests like the F-test, and in turn are more #' efficient. Agresti (1990) suggests that you should use the LRT instead of #' the Wald test for small sample sizes (under or about 30) or if the #' parameters are large. #' #' Note: for regression models, this is similar to #' `anova(..., test="LRT")` (on models) or `lmtest::lrtest(...)`, depending #' on the `estimator` argument. For **lavaan** models (SEM, CFA), the function #' calls `lavaan::lavTestLRT()`. #' #' For models with transformed response variables (like `log(x)` or `sqrt(x)`), #' `logLik()` returns a wrong log-likelihood. However, `test_likelihoodratio()` #' calls `insight::get_loglikelihood()` with `check_response=TRUE`, which #' returns a corrected log-likelihood value for models with transformed #' response variables. Furthermore, since the LRT only accepts nested #' models (i.e. models that differ in their fixed effects), the computed #' log-likelihood is always based on the ML estimator, not on the REML fits. #' #' - **Vuong's Test** - `test_vuong()`: Vuong's (1989) test can #' be used both for nested and non-nested models, and actually consists of two #' tests. #' #' - The **Test of Distinguishability** (the `Omega2` column and #' its associated p-value) indicates whether or not the models can possibly be #' distinguished on the basis of the observed data. If its p-value is #' significant, it means the models are distinguishable. #' #' - The **Robust Likelihood Test** (the `LR` column and its #' associated p-value) indicates whether each model fits better than the #' reference model. If the models are nested, then the test works as a robust #' LRT. The code for this function is adapted from the **nonnest2** #' package, and all credit go to their authors. #' #' @examples #' # Nested Models #' # ------------- #' m1 <- lm(Sepal.Length ~ Petal.Width, data = iris) #' m2 <- lm(Sepal.Length ~ Petal.Width + Species, data = iris) #' m3 <- lm(Sepal.Length ~ Petal.Width * Species, data = iris) #' #' test_performance(m1, m2, m3) #' #' test_bf(m1, m2, m3) #' test_wald(m1, m2, m3) # Equivalent to anova(m1, m2, m3) #' #' # Equivalent to lmtest::lrtest(m1, m2, m3) #' test_likelihoodratio(m1, m2, m3, estimator = "ML") #' #' # Equivalent to anova(m1, m2, m3, test='LRT') #' test_likelihoodratio(m1, m2, m3, estimator = "OLS") #' #' if (require("CompQuadForm")) { #' test_vuong(m1, m2, m3) # nonnest2::vuongtest(m1, m2, nested=TRUE) #' #' # Non-nested Models #' # ----------------- #' m1 <- lm(Sepal.Length ~ Petal.Width, data = iris) #' m2 <- lm(Sepal.Length ~ Petal.Length, data = iris) #' m3 <- lm(Sepal.Length ~ Species, data = iris) #' #' test_performance(m1, m2, m3) #' test_bf(m1, m2, m3) #' test_vuong(m1, m2, m3) # nonnest2::vuongtest(m1, m2) #' } #' #' # Tweak the output #' # ---------------- #' test_performance(m1, m2, m3, include_formula = TRUE) #' #' #' # SEM / CFA (lavaan objects) #' # -------------------------- #' # Lavaan Models #' if (require("lavaan")) { #' structure <- " visual =~ x1 + x2 + x3 #' textual =~ x4 + x5 + x6 #' speed =~ x7 + x8 + x9 #' #' visual ~~ textual + speed " #' m1 <- lavaan::cfa(structure, data = HolzingerSwineford1939) #' #' structure <- " visual =~ x1 + x2 + x3 #' textual =~ x4 + x5 + x6 #' speed =~ x7 + x8 + x9 #' #' visual ~~ 0 * textual + speed " #' m2 <- lavaan::cfa(structure, data = HolzingerSwineford1939) #' #' structure <- " visual =~ x1 + x2 + x3 #' textual =~ x4 + x5 + x6 #' speed =~ x7 + x8 + x9 #' #' visual ~~ 0 * textual + 0 * speed " #' m3 <- lavaan::cfa(structure, data = HolzingerSwineford1939) #' #' test_likelihoodratio(m1, m2, m3) #' #' # Different Model Types #' # --------------------- #' if (require("lme4") && require("mgcv")) { #' m1 <- lm(Sepal.Length ~ Petal.Length + Species, data = iris) #' m2 <- lmer(Sepal.Length ~ Petal.Length + (1 | Species), data = iris) #' m3 <- gam(Sepal.Length ~ s(Petal.Length, by = Species) + Species, data = iris) #' #' test_performance(m1, m2, m3) #' } #' } #' #' @references #' #' - Vuong, Q. H. (1989). Likelihood ratio tests for model selection and #' non-nested hypotheses. Econometrica, 57, 307-333. #' #' - Merkle, E. C., You, D., & Preacher, K. (2016). Testing non-nested #' structural equation models. Psychological Methods, 21, 151-163. #' #' @export test_performance <- function(..., reference = 1, verbose = TRUE) { UseMethod("test_performance") } # default -------------------------------- #' @export test_performance.default <- function(..., reference = 1, include_formula = FALSE, verbose = TRUE) { # Attribute class to list and get names from the global environment my_objects <- insight::ellipsis_info(..., only_models = TRUE) # validation checks (will throw error if non-valid objects) my_objects <- .test_performance_checks(my_objects, verbose = verbose) # ensure proper object names my_objects <- .check_objectnames(my_objects, sapply(match.call(expand.dots = FALSE)[["..."]], as.character)) # If a suitable class is found, run the more specific method on it if (inherits(my_objects, c("ListNestedRegressions", "ListNonNestedRegressions", "ListLavaan"))) { test_performance(my_objects, reference = reference, include_formula = include_formula) } else { insight::format_error("The models cannot be compared for some reason :/") } } # methods ------------------------------ #' @export plot.test_performance <- function(x, ...) { insight::format_alert( "There is currently no `plot()` method for test-functions.", "Please use `plot(compare_perfomance())` for some visual representations of your model comparisons." ) } #' @export format.test_performance <- function(x, digits = 2, ...) { # Format cols and names out <- insight::format_table(x, digits = digits, exact = FALSE, ...) if (isTRUE(attributes(x)$is_nested)) { footer <- paste0( "Models were detected as nested (in terms of fixed parameters) and are compared in sequential order.\n" ) } else { footer <- paste0( "Each model is compared to ", x$Name[attributes(x)$reference], ".\n" ) } attr(out, "table_footer") <- footer out } #' @export print.test_performance <- function(x, digits = 2, ...) { out <- insight::export_table(format(x, digits = digits, ...), ...) cat(out) } #' @export print_md.test_performance <- function(x, digits = 2, ...) { insight::export_table(format(x, digits = digits, ...), format = "markdown", ...) } #' @export print_html.test_performance <- function(x, digits = 2, ...) { insight::export_table(format(x, digits = digits, ...), format = "html", ...) } #' @export display.test_performance <- function(object, format = "markdown", digits = 2, ...) { if (format == "markdown") { print_md(x = object, digits = digits, ...) } else { print_html(x = object, digits = digits, ...) } } # other classes ----------------------------------- #' @export test_performance.ListNestedRegressions <- function(objects, reference = 1, include_formula = FALSE, ...) { out <- .test_performance_init(objects, include_formula = include_formula, ...) # BF test tryCatch( { rez <- test_bf(objects, reference = "sequential") if (!is.null(rez)) { rez$Model <- NULL out <- cbind(out, rez) } }, error = function(e) { # Do nothing } ) # Vuong, or LRT tryCatch( { if (isTRUE(insight::check_if_installed("CompQuadForm", quietly = TRUE))) { rez <- test_vuong(objects) } else { rez <- test_lrt(objects) } rez$Model <- NULL out <- merge(out, rez, sort = FALSE) }, error = function(e) { # Do nothing } ) attr(out, "is_nested") <- attributes(objects)$is_nested attr(out, "reference") <- if (attributes(objects)$is_nested_increasing) "increasing" else "decreasing" class(out) <- c("test_performance", class(out)) out } #' @export test_performance.ListNonNestedRegressions <- function(objects, reference = 1, include_formula = FALSE, ...) { out <- .test_performance_init(objects, include_formula = include_formula, ...) # BF test tryCatch( { rez <- test_bf(objects, reference = reference) if (!is.null(rez)) { rez$Model <- NULL out <- cbind(out, rez) } }, error = function(e) { # Do nothing } ) # Vuong, or Wald - we have non-nested models, so no LRT here tryCatch( { if (isTRUE(insight::check_if_installed("CompQuadForm", quietly = TRUE))) { rez <- test_vuong(objects, reference = reference) } else { rez <- test_wald(objects) } rez$Model <- NULL out <- merge(out, rez, sort = FALSE) }, error = function(e) { # Do nothing } ) attr(out, "is_nested") <- attributes(objects)$is_nested attr(out, "reference") <- reference class(out) <- c("test_performance", class(out)) out } # TESTS IMPLEMENTED IN OTHER PACKAGES # # Non-nested # lmtest::coxtest(m2, m3) # lmtest::jtest(m2, m3) # lmtest::encomptest(m2, m3) # nonnest2::icci(m2, m3) # Helpers ----------------------------------------------------------------- .test_performance_init <- function(objects, include_formula = FALSE) { model_names <- insight::model_name(objects, include_formula = include_formula) out <- data.frame( Name = names(objects), Model = model_names, stringsAsFactors = FALSE ) row.names(out) <- NULL out } .test_performance_checks <- function(objects, multiple = TRUE, same_response = TRUE, verbose = TRUE) { # TODO: we could actually generate a baseline model 'y ~ 1' whenever a single model is passed if (multiple && insight::is_model(objects)) { null_model <- .safe(insight::null_model(objects, verbose = FALSE)) if (!is.null(null_model) && insight::is_model(null_model)) { objects <- insight::ellipsis_info(list(null_model, objects)) names(objects) <- c("Null model", "Full model") if (verbose) { insight::format_alert( "Only one model was provided, however, at least two are required for comparison.", "Fitting a null-model as reference now." ) } } else { insight::format_error("At least two models are required to test them.") } } if (same_response && !inherits(objects, "ListLavaan") && isFALSE(attributes(objects)$same_response)) { insight::format_error( "The models' dependent variables don't have the same data, which is a prerequisite to compare them. Probably the proportion of missing data differs between models." # nolint ) } # check formula of all models, but warn only once already_warned <- FALSE for (i in objects) { if (!already_warned) { check_formula <- insight::formula_ok(i) } if (check_formula) { already_warned <- TRUE } } objects } .check_objectnames <- function(objects, dot_names) { # Replace with names from the global environment, if these are not yet properly set object_names <- insight::compact_character(names(objects)) # check if we have any names at all if ((is.null(object_names) || # or if length of names doesn't match number of models length(object_names) != length(objects) || # or if names are "..1", "..2" pattern all(grepl("\\.\\.\\d", object_names))) && # and length of dot-names must match length of objects length(objects) == length(dot_names)) { names(objects) <- dot_names } objects } performance/R/performance_hosmer.R0000644000176200001440000000511014736731423016764 0ustar liggesusers#' @title Hosmer-Lemeshow goodness-of-fit test #' @name performance_hosmer #' #' @description Check model quality of logistic regression models. #' #' @param model A `glm`-object with binomial-family. #' @param n_bins Numeric, the number of bins to divide the data. #' #' @return An object of class `hoslem_test` with following values: #' `chisq`, the Hosmer-Lemeshow chi-squared statistic; `df`, degrees #' of freedom and `p.value` the p-value for the goodness-of-fit test. #' #' @details A well-fitting model shows *no* significant difference between #' the model and the observed data, i.e. the reported p-value should be #' greater than 0.05. #' #' @references #' Hosmer, D. W., and Lemeshow, S. (2000). Applied Logistic Regression. Hoboken, #' NJ, USA: John Wiley and Sons, Inc. \doi{10.1002/0471722146} #' #' @examples #' model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") #' performance_hosmer(model) #' @export performance_hosmer <- function(model, n_bins = 10) { if (inherits(model, "merMod")) { insight::check_if_installed("lme4") } # check for valid object class if (!inherits(model, c("glmerMod", "glm"))) { insight::format_error("`model` must be an object of class `glm` or `glmerMod`.") } # mixed models (lme4) if (inherits(model, "glmerMod")) { y <- lme4::getME(model, "y") yhat <- stats::fitted(model) } else { y <- model$y yhat <- stats::fitted(model) } cutyhat <- cut( yhat, breaks = stats::quantile(yhat, probs = seq(0, 1, 1 / n_bins)), include.lowest = TRUE ) obs <- stats::xtabs(cbind(1 - y, y) ~ cutyhat) expect <- stats::xtabs(cbind(1 - yhat, yhat) ~ cutyhat) chisq <- sum((obs - expect)^2 / expect) p.value <- 1 - stats::pchisq(chisq, n_bins - 2) hoslem <- list( chisq = chisq, df = n_bins - 2, p.value = p.value ) class(hoslem) <- c("performance_hosmer", "list") hoslem } # methods --------------------------------- #' @export print.performance_hosmer <- function(x, ...) { insight::print_color("# Hosmer-Lemeshow Goodness-of-Fit Test\n\n", "blue") v1 <- sprintf("%.3f", x$chisq) v2 <- sprintf("%i ", x$df) v3 <- sprintf("%.3f", x$p.value) space <- max(nchar(c(v1, v2, v3))) cat(sprintf(" Chi-squared: %*s\n", space, v1)) cat(sprintf(" df: %*s\n", space, v2)) cat(sprintf(" p-value: %*s\n\n", space, v3)) if (x$p.value >= 0.05) { message("Summary: model seems to fit well.") } else { message("Summary: model does not fit well.") } invisible(x) } performance/R/check_autocorrelation.R0000644000176200001440000000476714736731423017476 0ustar liggesusers#' @title Check model for independence of residuals. #' @name check_autocorrelation #' #' @description Check model for independence of residuals, i.e. for autocorrelation #' of error terms. #' #' @param x A model object. #' @param nsim Number of simulations for the Durbin-Watson-Test. #' @param ... Currently not used. #' #' @return Invisibly returns the p-value of the test statistics. A p-value < 0.05 #' indicates autocorrelated residuals. #' #' @family functions to check model assumptions and and assess model quality #' #' @details Performs a Durbin-Watson-Test to check for autocorrelated residuals. #' In case of autocorrelation, robust standard errors return more accurate #' results for the estimates, or maybe a mixed model with error term for the #' cluster groups should be used. #' #' @examples #' m <- lm(mpg ~ wt + cyl + gear + disp, data = mtcars) #' check_autocorrelation(m) #' @export check_autocorrelation <- function(x, ...) { UseMethod("check_autocorrelation") } #' @rdname check_autocorrelation #' @export check_autocorrelation.default <- function(x, nsim = 1000, ...) { .is_model_valid(x) .residuals <- stats::residuals(x) n <- length(.residuals) dw <- .durbWats(.residuals) X <- insight::get_modelmatrix(x) mu <- stats::fitted(x) Y <- matrix(sample(.residuals, n * nsim, replace = TRUE), n, nsim) + matrix(mu, n, nsim) E <- stats::residuals(stats::lm(Y ~ X - 1)) DW <- rbind(apply(E, 2, .durbWats)) p <- (sum(dw < DW[1, ])) / nsim p.val <- 2 * (min(p, 1 - p)) class(p.val) <- c("check_autocorrelation", "see_check_autocorrelation", class(p.val)) p.val } # methods ------------------------------ #' @export plot.check_autocorrelation <- function(x, ...) { insight::format_warning("There is currently no `plot()` method for `check_autocorrelation()`.") } #' @export print.check_autocorrelation <- function(x, ...) { if (x < 0.05) { insight::print_color( sprintf( "Warning: Autocorrelated residuals detected (%s).", insight::format_p(x) ), "red" ) } else { insight::print_color( sprintf( "OK: Residuals appear to be independent and not autocorrelated (%s).", insight::format_p(x) ), "green" ) } invisible(x) } # utilities ------------------------------- .durbWats <- function(.residuals) { n <- length(.residuals) den <- sum(.residuals^2) (sum((.residuals[2:n] - .residuals[1:(n - 1)])^2)) / den } performance/R/check_symmetry.R0000644000176200001440000000232714501027040016122 0ustar liggesusers#' Check distribution symmetry #' #' Uses Hotelling and Solomons test of symmetry by testing if the standardized #' nonparametric skew (\eqn{\frac{(Mean - Median)}{SD}}) is different than 0. #' \cr\cr #' This is an underlying assumption of Wilcoxon signed-rank test. #' #' @param x Model or numeric vector #' @param ... Not used. #' #' @examples #' V <- suppressWarnings(wilcox.test(mtcars$mpg)) #' check_symmetry(V) #' #' @export check_symmetry <- function(x, ...) { UseMethod("check_symmetry") } #' @export check_symmetry.numeric <- function(x, ...) { x <- x[!is.na(x)] m <- mean(x) a <- stats::median(x) n <- length(x) s <- stats::sd(x) D <- n * (m - a) / s z <- sqrt(2 * n) * (m - a) / s out <- stats::pnorm(abs(z), lower.tail = FALSE) class(out) <- c("check_symmetry", "numeric") attr(out, "object_name") <- substitute(x) out } #' @export print.check_symmetry <- function(x, ...) { pstring <- insight::format_p(x) if (x < 0.05) { insight::print_color(sprintf("Warning: Non-symmetry detected (%s).\n", pstring), "red") } else { insight::print_color(sprintf("OK: Data appears symmetrical (%s).\n", pstring), "green") } return(invisible(x)) } performance/R/model_performance.bayesian.R0000644000176200001440000002431614736731423020372 0ustar liggesusers#' Performance of Bayesian Models #' #' Compute indices of model performance for (general) linear models. #' #' @param model Object of class `stanreg` or `brmsfit`. #' @param metrics Can be `"all"`, `"common"` or a character vector of #' metrics to be computed (some of `c("LOOIC", "WAIC", "R2", "R2_adj", #' "RMSE", "SIGMA", "LOGLOSS", "SCORE")`). `"common"` will compute LOOIC, #' WAIC, R2 and RMSE. #' @param ... Arguments passed to or from other methods. #' @inheritParams model_performance.lm #' #' @return A data frame (with one row) and one column per "index" (see #' `metrics`). #' #' @details Depending on `model`, the following indices are computed: #' #' - **ELPD**: expected log predictive density. Larger ELPD values #' mean better fit. See [looic()]. #' #' - **LOOIC**: leave-one-out cross-validation (LOO) information #' criterion. Lower LOOIC values mean better fit. See [looic()]. #' #' - **WAIC**: widely applicable information criterion. Lower WAIC #' values mean better fit. See `?loo::waic`. #' #' - **R2**: r-squared value, see [r2_bayes()]. #' #' - **R2_adjusted**: LOO-adjusted r-squared, see [r2_loo()]. #' #' - **RMSE**: root mean squared error, see [performance_rmse()]. #' #' - **SIGMA**: residual standard deviation, see [insight::get_sigma()]. #' #' - **LOGLOSS**: Log-loss, see [performance_logloss()]. #' #' - **SCORE_LOG**: score of logarithmic proper scoring rule, see [performance_score()]. #' #' - **SCORE_SPHERICAL**: score of spherical proper scoring rule, see [performance_score()]. #' #' - **PCP**: percentage of correct predictions, see [performance_pcp()]. #' #' @examplesIf require("rstanarm") && require("rstantools") #' \donttest{ #' model <- suppressWarnings(rstanarm::stan_glm( #' mpg ~ wt + cyl, #' data = mtcars, #' chains = 1, #' iter = 500, #' refresh = 0 #' )) #' model_performance(model) #' #' model <- suppressWarnings(rstanarm::stan_glmer( #' mpg ~ wt + cyl + (1 | gear), #' data = mtcars, #' chains = 1, #' iter = 500, #' refresh = 0 #' )) #' model_performance(model) #' } #' @seealso [r2_bayes] #' @references Gelman, A., Goodrich, B., Gabry, J., and Vehtari, A. (2018). #' R-squared for Bayesian regression models. The American Statistician, The #' American Statistician, 1-6. #' #' @export model_performance.stanreg <- function(model, metrics = "all", verbose = TRUE, ...) { if (any(tolower(metrics) == "log_loss")) { metrics[tolower(metrics) == "log_loss"] <- "LOGLOSS" } all_metrics <- c("LOOIC", "WAIC", "R2", "R2_adjusted", "ICC", "RMSE", "SIGMA", "LOGLOSS", "SCORE") if (all(metrics == "all")) { metrics <- all_metrics } else if (all(metrics == "common")) { metrics <- c("LOOIC", "WAIC", "R2", "RMSE") } metrics <- toupper(.check_bad_metrics(metrics, all_metrics, verbose)) algorithm <- insight::find_algorithm(model) if (algorithm$algorithm != "sampling") { if (verbose) { insight::format_warning( "`model_performance()` only possible for models fit using the \"sampling\" algorithm." ) } return(NULL) } insight::check_if_installed("loo") mi <- insight::model_info(model) out <- list() attri <- list() if (insight::is_multivariate(model)) { out$Response <- insight::find_response(model, combine = FALSE) mi <- mi[[1]] } # LOOIC ------------------ if ("LOOIC" %in% metrics) { loo_res <- suppressWarnings(looic(model, verbose = verbose)) out <- append(out, loo_res) attri$loo <- attributes(loo_res)$loo # save attributes } # WAIC ------------------ if ("WAIC" %in% metrics) { out$WAIC <- suppressWarnings(loo::waic(model)$estimates["waic", "Estimate"]) } # R2 ------------------ attri_r2 <- list() if ("R2" %in% metrics) { r2 <- r2_bayes(model, verbose = verbose) if (!is.null(r2)) { # save attributes attri_r2$SE$R2_Bayes <- attributes(r2)$SE$R2_Bayes attri_r2$CI$R2_Bayes <- attributes(r2)$CI$R2_Bayes attri_r2$CI$R2_Bayes_marginal <- attributes(r2)$CI$R2_Bayes_marginal attri_r2$robust$R2_Bayes <- attributes(r2)$robust # Format to df then to list r2_df <- as.data.frame(t(as.numeric(r2))) names(r2_df) <- gsub("_Bayes", "", names(r2), fixed = TRUE) out <- append(out, as.list(r2_df)) } } # LOO-R2 ------------------ if (("R2_ADJUSTED" %in% metrics || "R2_LOO" %in% metrics) && mi$is_linear) { r2_adj <- .safe(suppressWarnings(r2_loo(model, verbose = verbose))) if (!is.null(r2_adj)) { # save attributes attri_r2$SE$R2_loo <- attributes(r2_adj)$SE$R2_loo attri_r2$CI$R2_loo <- attributes(r2_adj)$CI$R2_loo attri_r2$CI$R2_loo_marginal <- attributes(r2)$CI$R2_loo_marginal attri_r2$robust$R2_loo <- attributes(r2_adj)$robust # Format to df then to list r2_adj_df <- as.data.frame(t(as.numeric(r2_adj))) names(r2_adj_df) <- gsub("_loo", "_adjusted", names(r2_adj), fixed = TRUE) out <- append(out, as.list(r2_adj_df)) } } if (length(attri_r2) > 0L) { attri$r2 <- attri_r2 attri$r2_bayes <- attri_r2 } # ICC ------------------ if ("ICC" %in% metrics) { out$ICC <- .safe(suppressWarnings(icc(model, verbose = verbose)$ICC_adjusted)) } # RMSE ------------------ if ("RMSE" %in% metrics && !mi$is_ordinal && !mi$is_multinomial && !mi$is_categorical) { out$RMSE <- performance_rmse(model, verbose = verbose) } # SIGMA ------------------ if ("SIGMA" %in% metrics) { out$Sigma <- .safe({ s <- .get_sigma(model, verbose = verbose) if (insight::is_empty_object(s)) { s <- NULL } s }) } # LOGLOSS ------------------ if (("LOGLOSS" %in% metrics) && mi$is_binomial) { out$Log_loss <- .safe({ .logloss <- performance_logloss(model, verbose = verbose) if (!is.na(.logloss)) { .logloss } else { NULL } }) } # SCORE ------------------ if (("SCORE" %in% metrics) && (mi$is_binomial || mi$is_count)) { .scoring_rules <- .safe(performance_score(model, verbose = verbose)) if (!is.null(.scoring_rules)) { if (!is.na(.scoring_rules$logarithmic)) out$Score_log <- .scoring_rules$logarithmic if (!is.na(.scoring_rules$spherical)) out$Score_spherical <- .scoring_rules$spherical } } out <- as.data.frame(out) row.names(out) <- NULL out <- out[vapply(out, function(i) !all(is.na(i)), TRUE)] attributes(out) <- c(attributes(out), attri) class(out) <- c("performance_model", class(out)) out } #' @export model_performance.brmsfit <- model_performance.stanreg #' @export model_performance.stanmvreg <- model_performance.stanreg #' @export #' @inheritParams r2_bayes #' @rdname model_performance.stanreg model_performance.BFBayesFactor <- function(model, metrics = "all", verbose = TRUE, average = FALSE, prior_odds = NULL, ...) { all_metrics <- c("R2", "SIGMA") if (all(metrics == "all")) { metrics <- all_metrics } metrics <- toupper(.check_bad_metrics(metrics, all_metrics, verbose)) # check for valid BFBayesFactor object mi <- insight::model_info(model, verbose = FALSE) if (!mi$is_linear || mi$is_correlation || mi$is_ttest || mi$is_binomial || mi$is_meta) { if (isTRUE(verbose)) { insight::format_warning("This type of Bayes factor models is not supported.") } return(NULL) } out <- list() attri <- list() if ("R2" %in% metrics) { r2 <- r2_bayes(model, average = average, prior_odds = prior_odds, verbose = verbose) attri$r2_bayes <- attributes(r2) # save attributes # Format to df then to list r2_df <- as.data.frame(t(as.numeric(r2))) names(r2_df) <- gsub("_Bayes", "", names(r2), fixed = TRUE) out <- append(out, as.list(r2_df)) } if ("SIGMA" %in% toupper(metrics)) { sig <- suppressMessages( .get_sigma_bfbayesfactor( model, average = average, prior_odds = prior_odds, verbose = verbose ) ) out$Sigma <- bayestestR::point_estimate(sig, "median")[[1]] } out <- as.data.frame(out) row.names(out) <- NULL attributes(out) <- c(attributes(out), attri) class(out) <- c("performance_model", class(out)) out } # helper ------------------- .get_sigma_bfbayesfactor <- function(model, average = FALSE, prior_odds = NULL, verbose = TRUE) { if (average) { return(.get_sigma_bfbayesfactor_model_average(model, prior_odds = prior_odds)) } params <- insight::get_parameters(model, verbose = verbose) if (!"sig2" %in% colnames(params)) { insight::format_error("This is not a linear model.") } sqrt(params$sig2) } .get_sigma_bfbayesfactor_model_average <- function(model, prior_odds = NULL) { insight::check_if_installed("BayesFactor") BFMods <- bayestestR::bayesfactor_models(model, verbose = FALSE) if (!is.null(BFMods$log_BF)) { BFMods$BF <- exp(BFMods$log_BF) } # extract parameters intercept_only <- which(BFMods$Model == "1") params <- vector(mode = "list", length = nrow(BFMods)) for (m in seq_along(params)) { if (length(intercept_only) && m == intercept_only) { y <- insight::get_response(model) params[[m]] <- rep(stats::sd(y), 4000) } else if (m == 1) { # If the model is the "den" model params[[m]] <- suppressMessages(.get_sigma_bfbayesfactor(1 / model[1])) } else { params[[m]] <- suppressMessages(.get_sigma_bfbayesfactor(model[m - 1])) } } params <- lapply(params, data.frame) # Compute posterior model probabilities if (!is.null(prior_odds)) { prior_odds <- c(1, prior_odds) } else { prior_odds <- rep(1, nrow(BFMods)) } posterior_odds <- prior_odds * BFMods$BF posterior_odds <- posterior_odds[-1] / posterior_odds[1] do.call( bayestestR::weighted_posteriors, c(params, list(missing = 0, prior_odds = posterior_odds)) )[[1]] } performance/R/r2_nakagawa.R0000644000176200001440000003155214736731423015274 0ustar liggesusers#' @title Nakagawa's R2 for mixed models #' @name r2_nakagawa #' #' @description Compute the _marginal_ and _conditional_ r-squared value for #' mixed effects models with complex random effects structures. #' #' @param model A mixed effects model. #' @param by_group Logical, if `TRUE`, returns the explained variance #' at different levels (if there are multiple levels). This is essentially #' similar to the variance reduction approach by _Hox (2010), pp. 69-78_. #' @param tolerance Tolerance for singularity check of random effects, to decide #' whether to compute random effect variances for the conditional r-squared #' or not. Indicates up to which value the convergence result is accepted. When #' `r2_nakagawa()` returns a warning, stating that random effect variances #' can't be computed (and thus, the conditional r-squared is `NA`), #' decrease the tolerance-level. See also [`check_singularity()`]. #' @inheritParams icc #' #' @return A list with the conditional and marginal R2 values. #' #' @section Supported models and model families: #' The single variance components that are required to calculate the marginal #' and conditional r-squared values are calculated using the [`insight::get_variance()`] #' function. The results are validated against the solutions provided by #' _Nakagawa et al. (2017)_, in particular examples shown in the Supplement 2 #' of the paper. Other model families are validated against results from the #' **MuMIn** package. This means that the r-squared values returned by `r2_nakagawa()` #' should be accurate and reliable for following mixed models or model families: #' #' - Bernoulli (logistic) regression #' - Binomial regression (with other than binary outcomes) #' - Poisson and Quasi-Poisson regression #' - Negative binomial regression (including nbinom1, nbinom2 and nbinom12 families) #' - Gaussian regression (linear models) #' - Gamma regression #' - Tweedie regression #' - Beta regression #' - Ordered beta regression #' #' Following model families are not yet validated, but should work: #' #' - Zero-inflated and hurdle models #' - Beta-binomial regression #' - Compound Poisson regression #' - Generalized Poisson regression #' - Log-normal regression #' - Skew-normal regression #' #' Extracting variance components for models with zero-inflation part is not #' straightforward, because it is not definitely clear how the distribution-specific #' variance should be calculated. Therefore, it is recommended to carefully #' inspect the results, and probably validate against other models, e.g. Bayesian #' models (although results may be only roughly comparable). #' #' Log-normal regressions (e.g. `lognormal()` family in **glmmTMB** or `gaussian("log")`) #' often have a very low fixed effects variance (if they were calculated as #' suggested by _Nakagawa et al. 2017_). This results in very low ICC or #' r-squared values, which may not be meaningful. #' #' @details #' Marginal and conditional r-squared values for mixed models are calculated #' based on _Nakagawa et al. (2017)_. For more details on the computation of #' the variances, see [`insight::get_variance()`]. The random effect variances are #' actually the mean random effect variances, thus the r-squared value is also #' appropriate for mixed models with random slopes or nested random effects #' (see _Johnson, 2014_). #' #' - **Conditional R2**: takes both the fixed and random effects into account. #' - **Marginal R2**: considers only the variance of the fixed effects. #' #' The contribution of random effects can be deduced by subtracting the #' marginal R2 from the conditional R2 or by computing the [`icc()`]. #' #' @references #' - Hox, J. J. (2010). Multilevel analysis: techniques and applications #' (2nd ed). New York: Routledge. #' - Johnson, P. C. D. (2014). Extension of Nakagawa and Schielzeth’s R2 GLMM #' to random slopes models. Methods in Ecology and Evolution, 5(9), 944–946. #' \doi{10.1111/2041-210X.12225} #' - Nakagawa, S., and Schielzeth, H. (2013). A general and simple method for #' obtaining R2 from generalized linear mixed-effects models. Methods in #' Ecology and Evolution, 4(2), 133–142. \doi{10.1111/j.2041-210x.2012.00261.x} #' - Nakagawa, S., Johnson, P. C. D., and Schielzeth, H. (2017). The #' coefficient of determination R2 and intra-class correlation coefficient from #' generalized linear mixed-effects models revisited and expanded. Journal of #' The Royal Society Interface, 14(134), 20170213. #' #' @examplesIf require("lme4") #' model <- lme4::lmer(Sepal.Length ~ Petal.Length + (1 | Species), data = iris) #' r2_nakagawa(model) #' r2_nakagawa(model, by_group = TRUE) #' @export r2_nakagawa <- function(model, by_group = FALSE, tolerance = 1e-8, ci = NULL, iterations = 100, ci_method = NULL, null_model = NULL, approximation = "lognormal", model_component = NULL, verbose = TRUE, ...) { # calculate random effect variances vars <- .compute_random_vars( model, tolerance, components = c("var.fixed", "var.residual"), null_model = null_model, approximation = approximation, name_fun = "r2()", name_full = "r-squared", model_component = model_component, verbose = verbose ) # return if R2 couldn't be computed if (is.null(vars) || all(is.na(vars))) { return(vars) } # compute R2 by group if (isTRUE(by_group)) { # with random slopes, explained variance is inaccurate if (!is.null(insight::find_random_slopes(model)) && verbose) { insight::format_warning("Model contains random slopes. Explained variance by levels is not accurate.") } if (!is.null(ci) && !is.na(ci) && verbose) { insight::format_warning("Confidence intervals are not yet supported for `by_group = TRUE`.") } # null-model if (is.null(null_model)) { null_model <- insight::null_model( model, verbose = isTRUE(getOption("easystats_errors", FALSE)) ) } vars_null <- insight::get_variance( null_model, tolerance = tolerance, verbose = isTRUE(getOption("easystats_errors", FALSE)) ) # names of group levels group_names <- insight::find_random(model, split_nested = TRUE, flatten = TRUE) # compute r2 by level r2_random <- 1 - (vars$var.intercept[group_names] / vars_null$var.intercept[group_names]) r2_fixed <- 1 - (vars$var.residual / vars_null$var.residual) out <- data.frame( Level = c("Level 1", group_names), R2 = c(r2_fixed, r2_random), stringsAsFactors = FALSE ) class(out) <- c("r2_nakagawa_by_group", "data.frame") } else { # Calculate R2 values if (insight::is_empty_object(vars$var.random) || is.na(vars$var.random)) { if (verbose) { # if no random effect variance, return simple R2 insight::print_color("Random effect variances not available. Returned R2 does not account for random effects.\n", "red") # nolint } r2_marginal <- vars$var.fixed / (vars$var.fixed + vars$var.residual) r2_conditional <- NA } else { r2_marginal <- vars$var.fixed / (vars$var.fixed + vars$var.random + vars$var.residual) r2_conditional <- (vars$var.fixed + vars$var.random) / (vars$var.fixed + vars$var.random + vars$var.residual) } names(r2_conditional) <- "Conditional R2" names(r2_marginal) <- "Marginal R2" out <- list(R2_conditional = r2_conditional, R2_marginal = r2_marginal) # check if CIs are requested, and compute bootstrapped CIs if (!is.null(ci) && !is.na(ci)) { # this is experimental! if (identical(ci_method, "analytical")) { result <- .safe(.analytical_icc_ci(model, ci, fun = "r2_nakagawa")) if (is.null(result)) { r2_ci_marginal <- r2_ci_conditional <- NA } else { r2_ci_marginal <- result$R2_marginal r2_ci_conditional <- result$R2_conditional } } else { result <- .bootstrap_r2_nakagawa(model, iterations, tolerance, ci_method, ...) # CI for marginal R2 r2_ci_marginal <- as.vector(result$t[, 1]) r2_ci_marginal <- r2_ci_marginal[!is.na(r2_ci_marginal)] # validation check if (length(r2_ci_marginal) > 0) { r2_ci_marginal <- bayestestR::eti(r2_ci_marginal, ci = ci) } else { r2_ci_marginal <- NA } # CI for unadjusted R2 r2_ci_conditional <- as.vector(result$t[, 2]) r2_ci_conditional <- r2_ci_conditional[!is.na(r2_ci_conditional)] # validation check if (length(r2_ci_conditional) > 0) { r2_ci_conditional <- bayestestR::eti(r2_ci_conditional, ci = ci) } else { r2_ci_conditional <- NA } if ((all(is.na(r2_ci_marginal)) || all(is.na(r2_ci_conditional))) && verbose) { insight::format_warning( "Could not compute confidence intervals for R2. Try `ci_method = \"simple\"." ) } } out$R2_marginal <- c( out$R2_marginal, CI_low = r2_ci_marginal$CI_low, CI_high = r2_ci_marginal$CI_high ) out$R2_conditional <- c( out$R2_conditional, CI_low = r2_ci_conditional$CI_low, CI_high = r2_ci_conditional$CI_high ) attr(out, "ci") <- ci } class(out) <- c("r2_nakagawa", "list") } out } # methods ------ #' @export as.data.frame.r2_nakagawa <- function(x, row.names = NULL, optional = FALSE, ...) { data.frame( R2_conditional = x$R2_conditional, R2_marginal = x$R2_marginal, stringsAsFactors = FALSE, row.names = row.names, optional = optional, ... ) } #' @export print.r2_nakagawa <- function(x, digits = 3, ...) { model_type <- attr(x, "model_type") if (is.null(model_type)) { insight::print_color("# R2 for Mixed Models\n\n", "blue") } else { insight::print_color("# R2 for %s Regression\n\n", "blue") } out <- c( sprintf(" Conditional R2: %.*f", digits, x$R2_conditional[1]), sprintf(" Marginal R2: %.*f", digits, x$R2_marginal[1]) ) # add CI if (length(x$R2_conditional) == 3) { out[1] <- .add_r2_ci_to_print(out[1], x$R2_conditional[2], x$R2_conditional[3], digits = digits) } if (length(x$R2_marginal) == 3) { out[2] <- .add_r2_ci_to_print(out[2], x$R2_marginal[2], x$R2_marginal[3], digits = digits) } # separate lines for multiple R2 out <- paste(out, collapse = "\n") cat(out) cat("\n") invisible(x) } # bootstrapping -------------- # bootstrapping using package "boot" .boot_r2_fun <- function(data, indices, model, tolerance) { d <- data[indices, ] # allows boot to select sample fit <- suppressWarnings(suppressMessages(stats::update(model, data = d))) vars <- .compute_random_vars( fit, tolerance, verbose = isTRUE(getOption("easystats_errors", FALSE)) ) if (is.null(vars) || all(is.na(vars))) { return(c(NA, NA)) } # Calculate R2 values if (insight::is_empty_object(vars$var.random) || is.na(vars$var.random)) { c(vars$var.fixed / (vars$var.fixed + vars$var.residual), NA) } else { c( vars$var.fixed / (vars$var.fixed + vars$var.random + vars$var.residual), (vars$var.fixed + vars$var.random) / (vars$var.fixed + vars$var.random + vars$var.residual) ) } } # bootstrapping using "lme4::bootMer" .boot_r2_fun_lme4 <- function(model) { vars <- .compute_random_vars( model, tolerance = 1e-10, verbose = isTRUE(getOption("easystats_errors", FALSE)) ) if (is.null(vars) || all(is.na(vars))) { return(c(NA, NA)) } # Calculate R2 values if (insight::is_empty_object(vars$var.random) || is.na(vars$var.random)) { c(vars$var.fixed / (vars$var.fixed + vars$var.residual), NA) } else { c( vars$var.fixed / (vars$var.fixed + vars$var.random + vars$var.residual), (vars$var.fixed + vars$var.random) / (vars$var.fixed + vars$var.random + vars$var.residual) ) } } # main bootstrap function .bootstrap_r2_nakagawa <- function(model, iterations, tolerance, ci_method = NULL, ...) { if (inherits(model, c("merMod", "lmerMod", "glmmTMB")) && !identical(ci_method, "boot")) { result <- .do_lme4_bootmer( model, .boot_r2_fun_lme4, iterations, dots = list(...) ) } else { insight::check_if_installed("boot") result <- boot::boot( data = insight::get_data(model, verbose = FALSE), statistic = .boot_r2_fun, R = iterations, sim = "ordinary", model = model, tolerance = tolerance ) } result } performance/R/r2_loo.R0000644000176200001440000001373414736731423014315 0ustar liggesusers#' @title LOO-adjusted R2 #' @name r2_loo #' #' @description Compute LOO-adjusted R2. #' #' @param model A Bayesian regression model (from **brms**, #' **rstanarm**, **BayesFactor**, etc). #' @param robust Logical, if `TRUE`, the median instead of mean is used to #' calculate the central tendency of the variances. #' @param ci Value or vector of probability of the CI (between 0 and 1) to be #' estimated. #' @param ... Arguments passed to `r2_posterior()`. #' @inheritParams model_performance.lm #' #' @return A list with the Bayesian R2 value. For mixed models, a list with the #' Bayesian R2 value and the marginal Bayesian R2 value. The standard errors #' and credible intervals for the R2 values are saved as attributes. #' #' @details `r2_loo()` returns an "adjusted" R2 value computed using a #' leave-one-out-adjusted posterior distribution. This is conceptually similar #' to an adjusted/unbiased R2 estimate in classical regression modeling. See #' [r2_bayes()] for an "unadjusted" R2. #' #' Mixed models are not currently fully supported. #' #' `r2_loo_posterior()` is the actual workhorse for `r2_loo()` and #' returns a posterior sample of LOO-adjusted Bayesian R2 values. #' #' @return A list with the LOO-adjusted R2 value. The standard errors #' and credible intervals for the R2 values are saved as attributes. #' #' @examplesIf require("rstanarm") && require("rstantools") #' model <- suppressWarnings(rstanarm::stan_glm( #' mpg ~ wt + cyl, #' data = mtcars, #' chains = 1, #' iter = 500, #' refresh = 0, #' show_messages = FALSE #' )) #' r2_loo(model) #' @export r2_loo <- function(model, robust = TRUE, ci = 0.95, verbose = TRUE, ...) { loo_r2 <- r2_loo_posterior(model, verbose = verbose, ...) if (is.null(loo_r2)) { return(NULL) } loo_r2 <- structure( class = "r2_loo", lapply(loo_r2, ifelse(robust, stats::median, mean)), SE = lapply(loo_r2, ifelse(robust, stats::mad, stats::sd)), # "Estimates" = lapply(r2_bayesian, bayestestR::point_estimate, centrality = "all", dispersion = TRUE), CI = lapply(loo_r2, bayestestR::hdi, ci = ci), robust = robust ) return(loo_r2) } #' @export #' @rdname r2_loo r2_loo_posterior <- function(model, ...) { UseMethod("r2_loo_posterior") } #' @export #' @rdname r2_loo r2_loo_posterior.brmsfit <- function(model, verbose = TRUE, ...) { insight::check_if_installed("rstantools") algorithm <- insight::find_algorithm(model) if (algorithm$algorithm != "sampling") { insight::format_warning("`r2()` only available for models fit using the \"sampling\" algorithm.") return(NA) } tryCatch( { mi <- insight::model_info(model) if (insight::is_multivariate(model)) { res <- insight::find_response(model) if (mi[[1]]$is_mixed) { br2_mv <- list( R2_loo = rstantools::loo_R2( model, re.form = NULL, re_formula = NULL, summary = FALSE ), R2_loo_marginal = rstantools::loo_R2( model, re.form = NA, re_formula = NA, summary = FALSE ) ) br2 <- lapply(seq_along(res), function(x) { list( R2_loo = unname(as.vector(br2_mv$R2_loo[, x])), R2_loo_marginal = unname(as.vector(br2_mv$R2_loo_marginal[, x])) ) }) names(br2) <- res } else { br2_mv <- list(R2_loo = rstantools::loo_R2(model, summary = FALSE)) br2 <- lapply(seq_along(res), function(x) { list(R2_loo = unname(as.vector(br2_mv$R2_loo[, x]))) }) names(br2) <- res } } else if (mi$is_mixed) { br2 <- list( R2_loo = as.vector(rstantools::loo_R2( model, re.form = NULL, re_formula = NULL, summary = FALSE )), R2_loo_marginal = as.vector(rstantools::loo_R2( model, re.form = NA, re_formula = NA, summary = FALSE )) ) names(br2$R2_loo) <- rep("Conditional R2_adjusted", length(br2$R2_loo)) names(br2$R2_loo_marginal) <- rep("Marginal R2_adjusted", length(br2$R2_loo)) } else { br2 <- list(R2_loo = as.vector(rstantools::loo_R2(model, summary = FALSE))) names(br2$R2_loo) <- rep("R2_adjusted", length(br2$R2_loo)) } br2 }, error = function(e) { if (inherits(e, c("simpleError", "error"))) { insight::print_color(e$message, "red") cat("\n") } NULL } ) } #' @export #' @rdname r2_loo r2_loo_posterior.stanreg <- r2_loo_posterior.brmsfit #' @export r2_loo_posterior.stanmvreg <- function(model, verbose = TRUE, ...) { if (isTRUE(verbose)) { insight::format_warning("Models of class `stanmvreg` not yet supported.") } NULL } #' @export r2_loo_posterior.BFBayesFactor <- function(model, verbose = TRUE, ...) { if (isTRUE(verbose)) { insight::format_warning("Models of class `BFBayesFactor` not yet supported.") } NULL } #' @export as.data.frame.r2_loo <- function(x, ...) { out <- data.frame( R2 = x$R2_loo, SD = attributes(x)$SE$R2_loo, CI = attributes(x)$CI$R2_loo$CI, CI_low = attributes(x)$CI$R2_loo$CI_low, CI_high = attributes(x)$CI$R2_loo$CI_high, stringsAsFactors = FALSE ) if (!is.null(x$R2_loo_marginal)) { out_marginal <- data.frame( R2 = x$R2_loo_marginal, SD = attributes(x)$SE$R2_loo_marginal, CI = attributes(x)$CI$R2_loo_marginal$CI, CI_low = attributes(x)$CI$R2_loo_marginal$CI_low, CI_high = attributes(x)$CI$R2_loo_marginal$CI_high, stringsAsFactors = FALSE ) out$Component <- "conditional" out_marginal$Component <- "marginal" out <- rbind(out, out_marginal) } out } performance/R/performance_rmse.R0000644000176200001440000001236014642733710016437 0ustar liggesusers#' @title Root Mean Squared Error #' @name performance_rmse #' #' @description Compute root mean squared error for (mixed effects) models, #' including Bayesian regression models. #' #' @param model A model. #' @param normalized Logical, use `TRUE` if normalized rmse should be returned. #' @inheritParams icc #' #' @details The RMSE is the square root of the variance of the residuals and indicates #' the absolute fit of the model to the data (difference between observed data #' to model's predicted values). It can be interpreted as the standard #' deviation of the unexplained variance, and is in the same units as the #' response variable. Lower values indicate better model fit. #' #' The normalized RMSE is the proportion of the RMSE related to the #' range of the response variable. Hence, lower values indicate #' less residual variance. #' #' @return Numeric, the root mean squared error. #' #' @examplesIf require("nlme") #' data(Orthodont, package = "nlme") #' m <- nlme::lme(distance ~ age, data = Orthodont) #' #' # RMSE #' performance_rmse(m, normalized = FALSE) #' #' # normalized RMSE #' performance_rmse(m, normalized = TRUE) #' @export performance_rmse <- function(model, normalized = FALSE, ci = NULL, iterations = 100, ci_method = NULL, verbose = TRUE, ...) { tryCatch( { out <- .calculate_rmse(model, normalized, verbose) # check if CIs are requested, and compute CIs if (!is.null(ci) && !is.na(ci)) { # analytical CI? if (identical(ci_method, "analytical")) { out <- .analytical_rmse_ci(out, model, ci) } else { # bootstrapped CI result <- .bootstrap_rmse(model, iterations, normalized, ci_method, ...) # CI for RMSE rmse_ci <- as.vector(result$t[, 1]) rmse_ci <- rmse_ci[!is.na(rmse_ci)] # validation check if (length(rmse_ci) > 0) { rmse_ci <- bayestestR::eti(rmse_ci, ci = ci) out <- cbind(data.frame(RMSE = out), rmse_ci) class(out) <- c("performance_rmse", "data.frame") } else { insight::format_warning("Could not compute confidence intervals for RMSE.") } } } }, error = function(e) { if (inherits(e, c("simpleError", "error")) && verbose) { insight::print_color(e$message, "red") cat("\n") } out <- NA } ) out } #' @rdname performance_rmse #' @export rmse <- performance_rmse # methods --------------------------------------------------------------------- #' @export format.performance_rmse <- function(x, ...) { insight::format_table(x, ...) } #' @export print.performance_rmse <- function(x, ...) { cat(insight::export_table(format(x, ...), ...)) } # helper function to compute RMSE ---------------------------------------------- .calculate_rmse <- function(model, normalized = FALSE, verbose = FALSE, ...) { # compute rmse rmse_val <- sqrt(performance_mse(model, verbose = verbose)) # if normalized, divide by range of response if (normalized) { # get response resp <- datawizard::to_numeric( insight::get_response(model, verbose = FALSE), dummy_factors = FALSE, preserve_levels = TRUE ) # compute rmse, normalized rmse_val <- rmse_val / (max(resp, na.rm = TRUE) - min(resp, na.rm = TRUE)) } rmse_val } # analytical CIs -------------------------------------------------------------- .analytical_rmse_ci <- function(out, model, ci, ...) { s <- insight::get_sigma(model, ci = ci, verbose = FALSE) n <- insight::n_obs(model) conf_ints <- c(attr(s, "CI_low"), attr(s, "CI_high")) * ((n - 1) / n) out <- data.frame( RMSE = out, CI = ci, CI_low = conf_ints[1], CI_high = conf_ints[2] ) class(out) <- c("performance_rmse", "data.frame") out } # bootstrapping CIs ----------------------------------------------------------- .boot_calculate_rmse <- function(data, indices, model, normalized, ...) { d <- data[indices, ] # allows boot to select sample fit <- suppressWarnings(suppressMessages(stats::update(model, data = d))) .calculate_rmse(model = fit, normalized = normalized) } .bootstrap_rmse <- function(model, iterations = 100, normalized = FALSE, ci_method = NULL, ...) { if (inherits(model, c("merMod", "lmerMod", "glmmTMB")) && !identical(ci_method, "boot")) { # cannot pass argument "normalized" to "lme4::bootMer()" if (isTRUE(normalized)) { insight::format_error("Normalized RMSE cannot be used with confidence intervals. Please use `ci_method = \"boot\"`.") # nolint } result <- .do_lme4_bootmer( model, .calculate_rmse, iterations, dots = list(...) ) } else { insight::check_if_installed("boot") result <- boot::boot( data = insight::get_data(model, verbose = FALSE), statistic = .boot_calculate_rmse, R = iterations, sim = "ordinary", model = model, normalized = normalized ) } result } performance/R/item_discrimination.R0000644000176200001440000000531314620351763017142 0ustar liggesusers#' @title Discrimination of Questionnaire Items #' @name item_discrimination #' #' @description Compute various measures of internal consistencies #' for tests or item-scales of questionnaires. #' #' @param x A matrix or a data frame. #' @param standardize Logical, if `TRUE`, the data frame's vectors will be #' standardized. Recommended when the variables have different measures / #' scales. #' #' @return A data frame with the item discrimination (*corrected item-total #' correlations*) for each item of the scale. #' #' @details #' This function calculates the item discriminations (corrected item-total #' correlations for each item of `x` with the remaining items) for each item #' of a scale. The absolute value of the item discrimination indices should be #' above `0.2`. An index between `0.2` and `0.4` is considered as "fair", while a #' satisfactory index ranges from `0.4` to `0.7`. Items with low discrimination #' indices are often ambiguously worded and should be examined. Items with #' negative indices should be examined to determine why a negative value was #' obtained (e.g. reversed answer categories regarding positive and negative #' poles). #' #' @references #' - Kelava A, Moosbrugger H (2020). Deskriptivstatistische Itemanalyse und #' Testwertbestimmung. In: Moosbrugger H, Kelava A, editors. Testtheorie und #' Fragebogenkonstruktion. Berlin, Heidelberg: Springer, 143–158 #' #' @examples #' data(mtcars) #' x <- mtcars[, c("cyl", "gear", "carb", "hp")] #' item_discrimination(x) #' @export item_discrimination <- function(x, standardize = FALSE) { # check param if (!is.matrix(x) && !is.data.frame(x)) { insight::format_alert("`x` needs to be a data frame or matrix.") return(NULL) } # remove missings, so correlation works x <- stats::na.omit(x) # remember item (column) names for return value # return value gets column names of initial data frame df.names <- colnames(x) # Check whether items should be scaled. Needed, # when items have different measures / scales if (standardize) { x <- .std(x) } # calculate corrected total-item correlation id <- vapply(seq_len(ncol(x)), function(i) { stats::cor(x[, i], rowSums(x[, -i]), use = "pairwise.complete.obs") }, numeric(1)) out <- data.frame( Item = df.names, Discrimination = id, stringsAsFactors = FALSE ) class(out) <- c("item_discrimination", "data.frame") out } # methods -------------------------------------- #' @export print.item_discrimination <- function(x, ...) { out <- insight::format_table(x, ...) cat(insight::export_table(out, caption = c("Item Discrimination", "blue"), ...)) invisible(x) } performance/R/check_htest.R0000644000176200001440000001606114736731423015401 0ustar liggesusers#' @export check_normality.htest <- function(x, ...) { model_data <- insight::get_data(x) if (is.null(model_data)) { insight::format_error( "Cannot check assumptions - Unable to retrieve data from `htest` object." ) } method <- x[["method"]] if (grepl("Welch", method, fixed = TRUE) || grepl("F test to compare two variances", method, fixed = TRUE)) { # sanity check if (!is.numeric(model_data[[2]])) { insight::format_error( "Discrete or character variables are not supported for this test. Please use a continuous variable for the second argument." ) } m1 <- stats::lm(model_data[[1]] ~ 1) m2 <- stats::lm(model_data[[2]] ~ 1) out <- check_normality(m1) out[2] <- check_normality(m2)[1] attr(out, "units") <- c("Group1", "Group2") } else if (grepl("Two Sample t-test", method, fixed = TRUE)) { m <- stats::lm( formula = value ~ factor(name), data = datawizard::data_to_long(model_data) ) out <- check_normality(m) } else if (grepl("One Sample t-test", method, fixed = TRUE)) { m <- stats::lm(model_data[[1]] ~ 1) out <- check_normality(m) } else if (grepl("Paired t-test", method, fixed = TRUE)) { if (!is.numeric(model_data[[2]])) { insight::format_error( "Discrete or character variables are not supported for this test. Please use a continuous variable for the second argument." ) } d <- model_data[[1]] - model_data[[2]] m <- stats::lm(d ~ 1) out <- check_normality(m) } else if (grepl("One-way analysis of means (not assuming equal variances)", method, fixed = TRUE)) { model_data <- split(model_data, model_data[[2]]) outs <- lapply(model_data, function(d) { check_normality(stats::lm(d[[1]] ~ 1)) }) out <- unlist(outs) attributes(out) <- attributes(outs[[1]]) attr(out, "units") <- paste0("Group", seq_along(outs)) } else if (grepl("One-way analysis of means", method, fixed = TRUE)) { m <- stats::aov(model_data[[1]] ~ factor(model_data[[2]])) out <- check_normality(m) } else if (grepl("Pearson's product-moment correlation", method, fixed = TRUE)) { out <- .MVN_hz(model_data)[["p value"]] class(out) <- c("check_normality", "see_check_normality", "numeric") attr(out, "type") <- "residuals" } else if (grepl("Pearson's Chi-squared test", method, fixed = TRUE) || grepl("Chi-squared test for given probabilities", method, fixed = TRUE)) { out <- c( "5" = all(x$expected >= 5), "10" = all(x$expected >= 10) ) class(out) <- c("check_normality_binom", "logical") attr(out, "object_name") <- substitute(x) return(out) } else { insight::format_error( "This `htest` is not supported (or this assumption is not required for this test)." ) } attr(out, "object_name") <- substitute(x) attr(out, "data") <- NULL out } #' @export check_homogeneity.htest <- function(x, ...) { model_data <- insight::get_data(x) if (is.null(model_data)) { insight::format_error( "Cannot check assumptions - Unable to retrieve data from `htest` object." ) } method <- x[["method"]] if (grepl("(not assuming equal variances)", method, fixed = TRUE) || grepl("Welch", method, fixed = TRUE)) { insight::format_error("Test does not assume homogeneity. No need to test this assumption.") } if (grepl("Two Sample t-test", method, fixed = TRUE)) { m <- stats::lm( formula = value ~ factor(name), data = datawizard::data_to_long(model_data) ) } else if (grepl("One-way analysis of means", method, fixed = TRUE)) { m <- stats::aov( stats::reformulate(names(model_data)[2], response = names(model_data)[1]), data = model_data ) } else { insight::format_error( "This `htest` is not supported (or this assumption is not required for this test)." ) } out <- check_homogeneity(m, ...) attr(out, "object_name") <- substitute(x) attr(out, "data") <- NULL out } #' @export check_symmetry.htest <- function(x, ...) { model_data <- insight::get_data(x) if (is.null(model_data)) { insight::format_error( "Cannot check assumptions - Unable to retrieve data from `htest` object." ) } method <- x[["method"]] if (grepl("signed rank", method, fixed = TRUE)) { if (ncol(model_data) > 1) { out <- check_symmetry(model_data[[1]] - model_data[[2]]) } else { out <- check_symmetry(model_data[[1]]) } } else { insight::format_error( "This `htest` is not supported (or this assumption is not required for this test)." ) } attr(out, "object_name") <- substitute(x) out } # check_model.htest <- function() { # # } # Print ------------------------------------------------------------------- #' @export print.check_normality_binom <- function(x, ...) { if (x["10"]) { insight::print_color(insight::format_message( "OK: All cells in the expected table have more than 10 observations.\n" ), "green") } else if (x["5"]) { insight::print_color(insight::format_message( "Warning: All cells in the expected table have more than 5 observations, but some have less than 10.\n" ), "yellow") } else { insight::print_color(insight::format_message( "Warning: Some cells in the expected table have less than 5 observations.\n" ), "red") } invisible(x) } # Utils ------------------------------------------------------------------- .MVN_hz <- function(data, cov = TRUE, tol = 1e-25) { # from MVN:::hz dataframe <- as.data.frame(data) dname <- insight::safe_deparse_symbol(data) data <- data[stats::complete.cases(data), ] data <- as.matrix(data) n <- dim(data)[1] p <- dim(data)[2] data.org <- data if (cov) { S <- ((n - 1) / n) * cov(data) } else { S <- cov(data) } dif <- scale(data, scale = FALSE) Dj <- diag(dif %*% solve(S, tol = tol) %*% t(dif)) Y <- data %*% solve(S, tol = tol) %*% t(data) Djk <- -2 * t(Y) + matrix(diag(t(Y))) %*% matrix(rep(1, n), 1, n) + matrix(rep(1, n), n, 1) %*% diag(t(Y)) b <- 1 / (sqrt(2)) * ((2 * p + 1) / 4)^(1 / (p + 4)) * (n^(1 / (p + 4))) if (qr(S)$rank == p) { HZ <- n * (1 / (n^2) * sum(sum(exp(-(b^2) / 2 * Djk))) - 2 * ((1 + (b^2))^(-p / 2)) * (1 / n) * (sum(exp(-((b^2) / (2 * (1 + (b^2)))) * Dj))) + ((1 + (2 * (b^2)))^(-p / 2))) } else { HZ <- n * 4 } wb <- (1 + b^2) * (1 + 3 * b^2) a <- 1 + 2 * b^2 mu <- 1 - a^(-p / 2) * (1 + p * b^2 / a + (p * (p + 2) * (b^4)) / (2 * a^2)) si2 <- 2 * (1 + 4 * b^2)^(-p / 2) + 2 * a^(-p) * (1 + (2 * p * b^4) / a^2 + (3 * p * (p + 2) * b^8) / (4 * a^4)) - 4 * wb^(-p / 2) * (1 + (3 * p * b^4) / (2 * wb) + (p * (p + 2) * b^8) / (2 * wb^2)) pmu <- log(sqrt(mu^4 / (si2 + mu^2))) psi <- sqrt(log((si2 + mu^2) / mu^2)) pValue <- 1 - stats::plnorm(HZ, pmu, psi) MVN <- ifelse(pValue > 0.05, "YES", "NO") cbind.data.frame(Test = "Henze-Zirkler", HZ = HZ, `p value` = pValue, MVN = MVN) } performance/R/check_distribution.R0000644000176200001440000001776114741714030016770 0ustar liggesusers#' Classify the distribution of a model-family using machine learning #' #' @name classify_distribution #' @docType data #' @keywords data #' @details #' The trained model to classify distributions, which is used by the #' `check_distribution()` function. NULL #' Classify the distribution of a model-family using machine learning #' #' Choosing the right distributional family for regression models is essential #' to get more accurate estimates and standard errors. This function may help to #' check a models' distributional family and see if the model-family probably #' should be reconsidered. Since it is difficult to exactly predict the correct #' model family, consider this function as somewhat experimental. #' #' @param model Typically, a model (that should response to `residuals()`). #' May also be a numeric vector. #' #' @note This function is somewhat experimental and might be improved in future #' releases. The final decision on the model-family should also be based on #' theoretical aspects and other information about the data and the model. #' \cr \cr #' There is also a #' [`plot()`-method](https://easystats.github.io/see/articles/performance.html) #' implemented in the #' \href{https://easystats.github.io/see/}{\pkg{see}-package}. #' #' @details #' #' This function uses an internal random forest model to classify the #' distribution from a model-family. Currently, following distributions are #' trained (i.e. results of `check_distribution()` may be one of the #' following): `"bernoulli"`, `"beta"`, `"beta-binomial"`, `"binomial"`, #' `"cauchy"`, `"chi"`, `"exponential"`, `"F"`, `"gamma"`, `"half-cauchy"`, #' `"inverse-gamma"`, `"lognormal"`, `"normal"`, `"negative binomial"`, #' `"negative binomial (zero-inflated)"`, `"pareto"`, `"poisson"`, #' `"poisson (zero-inflated)"`, `"tweedie"`, `"uniform"` and `"weibull"`. #' \cr \cr #' Note the similarity between certain distributions according to shape, skewness, #' etc. Thus, the predicted distribution may not be perfectly representing the #' distributional family of the underlying fitted model, or the response value. #' \cr \cr #' There is a `plot()` method, which shows the probabilities of all predicted #' distributions, however, only if the probability is greater than zero. #' #' @examplesIf all(insight::check_if_installed(c("lme4", "parameters", "randomForest"), quietly = TRUE)) #' data(sleepstudy, package = "lme4") #' model <<- lme4::lmer(Reaction ~ Days + (Days | Subject), sleepstudy) #' check_distribution(model) #' #' @examplesIf all(insight::check_if_installed(c("see", "patchwork", "randomForest"), quietly = TRUE)) #' plot(check_distribution(model)) #' #' @export check_distribution <- function(model) { UseMethod("check_distribution") } # default ----------------------------- #' @export check_distribution.default <- function(model) { .is_model_valid(model) insight::check_if_installed("randomForest") if (inherits(model, "brmsfit")) { x <- stats::residuals(model)[, "Estimate"] } else { x <- stats::residuals(model) } dat <- .extract_features(x, "residuals") dist_residuals <- as.data.frame(t(stats::predict(classify_distribution, dat, type = "prob"))) # Extract features x <- datawizard::to_numeric( insight::get_response(model, verbose = FALSE), dummy_factors = FALSE, preserve_levels = TRUE ) dat <- .extract_features(x, "response") dist_response <- as.data.frame(t(stats::predict(classify_distribution, dat, type = "prob"))) out <- data.frame( Distribution = rownames(dist_response), p_Residuals = dist_residuals[[1]], p_Response = dist_response[[1]], stringsAsFactors = FALSE, row.names = NULL ) class(out) <- unique(c("check_distribution", "see_check_distribution", class(out))) attr(out, "data") <- model attr(out, "object_name") <- insight::safe_deparse_symbol(substitute(model)) out } # methods -------------------------- #' @export print.check_distribution <- function(x, ...) { insight::print_color("# Distribution of Model Family\n\n", "blue") x1 <- x[order(x$p_Residuals, decreasing = TRUE)[1:3], c(1, 2)] x1 <- x1[x1$p_Residuals > 0, ] x1$p_Residuals <- sprintf("%g%%", round(100 * x1$p_Residuals)) colnames(x1) <- c("Distribution", "Probability") insight::print_color("Predicted Distribution of Residuals\n\n", "red") print.data.frame(x1, row.names = FALSE, ...) x2 <- x[order(x$p_Response, decreasing = TRUE)[1:3], c(1, 3)] x2 <- x2[x2$p_Response > 0, ] x2$p_Response <- sprintf("%g%%", round(100 * x2$p_Response)) colnames(x2) <- c("Distribution", "Probability") insight::print_color("\nPredicted Distribution of Response\n\n", "red") print.data.frame(x2, row.names = FALSE, ...) invisible(x) } #' @export print.check_distribution_numeric <- function(x, ...) { insight::print_color("# Predicted Distribution of Vector\n\n", "blue") x1 <- x[order(x$p_Vector, decreasing = TRUE)[1:3], c(1, 2)] x1 <- x1[x1$p_Vector > 0, ] x1$p_Vector <- sprintf("%g%%", round(100 * x1$p_Vector)) colnames(x1) <- c("Distribution", "Probability") print.data.frame(x1, row.names = FALSE, ...) invisible(x) } #' @export plot.check_distribution <- function(x, ...) { insight::check_if_installed("see", "to plot predicted distributions") NextMethod() } #' @export plot.check_distribution_numeric <- function(x, ...) { insight::check_if_installed("see", "to plot predicted distributions") NextMethod() } # other classes ------------------- #' @export check_distribution.numeric <- function(model) { insight::check_if_installed("randomForest") dat <- .extract_features(model) distance <- as.data.frame(t(stats::predict(classify_distribution, dat, type = "prob"))) out <- data.frame( Distribution = rownames(distance), p_Vector = distance[[1]], stringsAsFactors = FALSE, row.names = NULL ) class(out) <- unique(c("check_distribution_numeric", "see_check_distribution_numeric", class(out))) attr(out, "data") <- model out } # utilities ----------------------------- .extract_features <- function(x, type = NULL) { # validation check, remove missings x <- x[!is.na(x)] mode_value <- NULL # find mode for integer, or MAP for distributions if (all(.is_integer(x))) { mode_value <- datawizard::distribution_mode(x) } else { # this might fail, so we wrap in ".safe()" mode_value <- tryCatch( as.numeric(bayestestR::map_estimate(x, bw = "nrd0")), error = function(e) NULL ) if (is.null(mode_value)) { mode_value <- tryCatch( as.numeric(bayestestR::map_estimate(x, bw = "kernel")), error = function(e) NULL ) } } if (is.null(mode_value)) { mean_mode_diff <- mean(x) - datawizard::distribution_mode(x) msg <- "Could not accurately estimate the mode." if (!is.null(type)) { msg <- paste(msg, "Predicted distribution of the", type, "may be less accurate.") } insight::format_alert(msg) } else { mean_mode_diff <- .safe(mean(x) - mode_value) } data.frame( SD = stats::sd(x), MAD = stats::mad(x, constant = 1), Mean_Median_Distance = mean(x) - stats::median(x), Mean_Mode_Distance = mean_mode_diff, SD_MAD_Distance = stats::sd(x) - stats::mad(x, constant = 1), Var_Mean_Distance = stats::var(x) - mean(x), Range_SD = diff(range(x)) / stats::sd(x), Range = diff(range(x)), IQR = stats::IQR(x), Skewness = .skewness(x), Kurtosis = .kurtosis(x), Uniques = length(unique(x)) / length(x), N_Uniques = length(unique(x)), Min = min(x), Max = max(x), Proportion_Positive = sum(x >= 0) / length(x), Proportion_Zero = sum(x == 0) / length(x), Integer = all(.is_integer(x)) ) } .is_integer <- function(x) { tryCatch( ifelse(is.infinite(x), FALSE, x %% 1 == 0), warning = function(w) is.integer(x), error = function(e) FALSE ) } performance/R/performance_score.R0000644000176200001440000001733514736731423016616 0ustar liggesusers#' @title Proper Scoring Rules #' @name performance_score #' #' @description Calculates the logarithmic, quadratic/Brier and spherical score #' from a model with binary or count outcome. #' #' @param model Model with binary or count outcome. #' @param ... Arguments from other functions, usually only used internally. #' @inheritParams model_performance.lm #' #' @return A list with three elements, the logarithmic, quadratic/Brier and spherical score. #' #' @details Proper scoring rules can be used to evaluate the quality of model #' predictions and model fit. `performance_score()` calculates the logarithmic, #' quadratic/Brier and spherical scoring rules. The spherical rule takes values #' in the interval `[0, 1]`, with values closer to 1 indicating a more #' accurate model, and the logarithmic rule in the interval `[-Inf, 0]`, #' with values closer to 0 indicating a more accurate model. #' #' For `stan_lmer()` and `stan_glmer()` models, the predicted values #' are based on `posterior_predict()`, instead of `predict()`. Thus, #' results may differ more than expected from their non-Bayesian counterparts #' in **lme4**. #' #' @references #' Carvalho, A. (2016). An overview of applications of proper scoring rules. #' Decision Analysis 13, 223–242. \doi{10.1287/deca.2016.0337} #' #' @note #' Code is partially based on #' [GLMMadaptive::scoring_rules()](https://drizopoulos.github.io/GLMMadaptive/reference/scoring_rules.html). #' #' @seealso [`performance_logloss()`] #' #' @examplesIf require("glmmTMB") #' ## Dobson (1990) Page 93: Randomized Controlled Trial : #' counts <- c(18, 17, 15, 20, 10, 20, 25, 13, 12) #' outcome <- gl(3, 1, 9) #' treatment <- gl(3, 3) #' model <- glm(counts ~ outcome + treatment, family = poisson()) #' #' performance_score(model) #' \donttest{ #' data(Salamanders, package = "glmmTMB") #' model <- glmmTMB::glmmTMB( #' count ~ spp + mined + (1 | site), #' zi = ~ spp + mined, #' family = nbinom2(), #' data = Salamanders #' ) #' #' performance_score(model) #' } #' @export performance_score <- function(model, verbose = TRUE, ...) { # check special case if (inherits(model, c("logitor", "logitmfx", "probitmfx", "negbinirr", "negbinmfx", "poissonirr", "poissonmfx"))) { model <- model$fit } minfo <- list(...)$model_info if (is.null(minfo)) { minfo <- suppressWarnings(insight::model_info(model, verbose = FALSE)) } if (minfo$is_ordinal || minfo$is_multinomial) { if (verbose) { insight::format_alert("Can't calculate proper scoring rules for ordinal, multinomial or cumulative link models.") } return(list(logarithmic = NA, quadratic = NA, spherical = NA)) } resp <- insight::get_response(model, verbose = verbose) if (!is.null(ncol(resp)) && ncol(resp) > 1) { if (verbose) { insight::format_alert("Can't calculate proper scoring rules for models without integer response values.") } return(list(logarithmic = NA, quadratic = NA, spherical = NA)) } prob_fun <- if (minfo$is_binomial) { function(x, mean, pis, n) stats::dbinom(x, size = n, prob = mean) } else if (minfo$is_poisson && !minfo$is_zero_inflated) { function(x, mean, pis, n) stats::dpois(x, lambda = mean) } else if (minfo$is_negbin && !minfo$is_zero_inflated) { function(x, mean, pis, n) stats::dnbinom(x, mu = mean, size = exp(.dispersion_parameter(model, minfo))) } else if (minfo$is_poisson && minfo$is_zero_inflated && !minfo$is_hurdle) { function(x, mean, pis, n) { ind0 <- x == 0 out <- (1 - pis) * stats::dpois(x, lambda = mean / (1 - pis)) out[ind0] <- pis[ind0] + out[ind0] out } } else if (minfo$is_zero_inflated && minfo$is_negbin && !minfo$is_hurdle) { function(x, mean, pis, n) { ind0 <- x == 0 out <- (1 - pis) * stats::dnbinom(x, mu = mean / (1 - pis), size = exp(.dispersion_parameter(model, minfo))) out[ind0] <- pis[ind0] + out[ind0] out } } else if (minfo$is_hurdle && minfo$is_poisson) { function(x, mean, pis, n) { ind0 <- x == 0 trunc_zero <- stats::dpois(x, lambda = mean) / stats::ppois(0, lambda = mean, lower.tail = FALSE) out <- (1 - pis) * trunc_zero out[ind0] <- pis[ind0] out } } else if (minfo$is_hurdle && minfo$is_negbin) { function(x, mean, pis, n) { ind0 <- x == 0 trunc_zero <- stats::dnbinom(x, mu = mean, size = exp(.dispersion_parameter(model, minfo))) / stats::pnbinom(0, mu = mean, size = exp(.dispersion_parameter(model, minfo)), lower.tail = FALSE) out <- (1 - pis) * trunc_zero out[ind0] <- pis[ind0] out } } pr <- .predict_score_y(model) resp <- if (minfo$is_binomial) { .recode_to_zero(resp) } else { datawizard::to_numeric(resp, dummy_factors = FALSE, preserve_levels = TRUE) } p_y <- .safe(suppressWarnings(prob_fun(resp, mean = pr$pred, pis = pr$pred_zi, sum(resp)))) if (is.null(p_y) || all(is.na(p_y))) { if (verbose) { insight::format_alert("Can't calculate proper scoring rules for this model.") } return(list(logarithmic = NA, quadratic = NA, spherical = NA)) } quadrat_p <- sum(p_y^2) structure( class = "performance_score", list( logarithmic = mean(log(p_y)), quadratic = mean(2 * p_y + quadrat_p), spherical = mean(p_y / sqrt(quadrat_p)) ) ) } # methods ----------------------------------- #' @export as.data.frame.performance_score <- function(x, row.names = NULL, ...) { data.frame( logarithmic = x$logarithmic, quadratic = x$quadratic, spherical = x$spherical, stringsAsFactors = FALSE, row.names = row.names, ... ) } #' @export print.performance_score <- function(x, ...) { # headline insight::print_color("# Proper Scoring Rules\n\n", "blue") results <- format( c( sprintf("%.4f", x$logarithmic), sprintf("%.4f", x$quadratic), sprintf("%.4f", x$spherical) ), justify = "right" ) cat(sprintf("logarithmic: %s\n", results[1])) cat(sprintf(" quadratic: %s\n", results[2])) cat(sprintf(" spherical: %s\n", results[3])) invisible(x) } # utilities --------------------------------- .dispersion_parameter <- function(model, minfo) { if (inherits(model, "MixMod")) { model$phis } else if (inherits(model, "glmmTMB")) { if (minfo$is_zero_inflated) { insight::check_if_installed("glmmTMB") glmmTMB::getME(model, "theta") } else { sum(stats::residuals(model, type = "pearson")^2) / stats::df.residual(model) } } else { .safe(sum(stats::residuals(model, type = "pearson")^2) / stats::df.residual(model), 0) } } .predict_score_y <- function(model) { pred <- NULL pred_zi <- NULL tryCatch( if (inherits(model, "MixMod")) { pred <- stats::predict(model, type = "subject_specific") pred_zi <- if (!is.null(model$gammas)) attr(pred, "zi_probs") } else if (inherits(model, "glmmTMB")) { pred <- stats::predict(model, type = "response") pred_zi <- stats::predict(model, type = "zprob") } else if (inherits(model, c("hurdle", "zeroinfl"))) { pred <- stats::predict(model, type = "response") pred_zi <- stats::predict(model, type = "zero") } else if (inherits(model, c("clm", "clm2", "clmm"))) { pred <- stats::predict(model) } else if (all(inherits(model, c("stanreg", "lmerMod"), which = TRUE)) > 0) { insight::check_if_installed("rstanarm") pred <- colMeans(rstanarm::posterior_predict(model)) } else { pred <- stats::predict(model, type = "response") }, error = function(e) { NULL } ) list(pred = pred, pred_zi = pred_zi) } performance/R/model_performance.lm.R0000644000176200001440000002363614736731423017213 0ustar liggesusers#' Performance of Regression Models #' #' Compute indices of model performance for regression models. #' #' @param model A model. #' @param metrics Can be `"all"`, `"common"` or a character vector of metrics to #' be computed (one or more of `"AIC"`, `"AICc"`, `"BIC"`, `"R2"`, `"R2_adj"`, #' `"RMSE"`, `"SIGMA"`, `"LOGLOSS"`, `"PCP"`, `"SCORE"`). `"common"` will #' compute AIC, BIC, R2 and RMSE. #' @param verbose Toggle off warnings. #' @param ... Arguments passed to or from other methods. #' #' @return #' A data frame (with one row) and one column per "index" (see `metrics`). #' #' @details Depending on `model`, following indices are computed: #' #' - **AIC**: Akaike's Information Criterion, see `?stats::AIC` #' - **AICc**: Second-order (or small sample) AIC with a correction for small sample sizes #' - **BIC**: Bayesian Information Criterion, see `?stats::BIC` #' - **R2**: r-squared value, see [`r2()`] #' - **R2_adj**: adjusted r-squared, see [`r2()`] #' - **RMSE**: root mean squared error, see [`performance_rmse()`] #' - **SIGMA**: residual standard deviation, see [`insight::get_sigma()`] #' - **LOGLOSS**: Log-loss, see [`performance_logloss()`] #' - **SCORE_LOG**: score of logarithmic proper scoring rule, see [`performance_score()`] #' - **SCORE_SPHERICAL**: score of spherical proper scoring rule, see [`performance_score()`] #' - **PCP**: percentage of correct predictions, see [`performance_pcp()`] #' #' @details `model_performance()` correctly detects transformed response and #' returns the "corrected" AIC and BIC value on the original scale. To get back #' to the original scale, the likelihood of the model is multiplied by the #' Jacobian/derivative of the transformation. #' #' @examples #' model <- lm(mpg ~ wt + cyl, data = mtcars) #' model_performance(model) #' #' model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") #' model_performance(model) #' @export model_performance.lm <- function(model, metrics = "all", verbose = TRUE, ...) { if (any(tolower(metrics) == "log_loss")) { metrics[tolower(metrics) == "log_loss"] <- "LOGLOSS" } # all available options... all_metrics <- c("AIC", "AICc", "BIC", "R2", "R2_adj", "RMSE", "SIGMA", "LOGLOSS", "PCP", "SCORE") if (all(metrics == "all")) { metrics <- all_metrics } else if (all(metrics == "common")) { metrics <- c("AIC", "BIC", "R2", "R2_adj", "RMSE") } # check model formula if (verbose) { insight::formula_ok(model) } metrics <- .check_bad_metrics(metrics, all_metrics, verbose) info <- suppressWarnings(insight::model_info(model, verbose = FALSE)) ## TODO remove is.list() once insight 0.8.3 is on CRAN if (is.null(info) || !is.list(info)) { info <- list(family = "unknown") } out <- list() attrib <- list() # AIC ------------- if ("AIC" %in% toupper(metrics)) { out$AIC <- .safe(performance_aic(model, model_info = info)) } # AICc ------------- if ("AICC" %in% toupper(metrics)) { out$AICc <- .safe(performance_aicc(model)) } # BIC ------------- if ("BIC" %in% toupper(metrics)) { out$BIC <- .safe(.get_BIC(model)) } # R2 ------------- if (any(c("R2", "R2_ADJ") %in% toupper(metrics))) { R2 <- .safe(r2(model, verbose = verbose, model_info = info)) if (!is.null(R2)) { attrib$r2 <- attributes(R2) if ("R2" %in% toupper(metrics) && "R2" %in% names(R2)) { out$R2 <- R2$R2 } if ("R2_ADJ" %in% toupper(metrics) && "R2_adjusted" %in% names(R2)) { out$R2_adjusted <- R2$R2_adjusted } if ("R2_ADJ" %in% toupper(metrics) && "R2_adj" %in% names(R2)) { out$R2_adjusted <- R2$R2_adj } if ("R2_within" %in% names(R2)) { out$R2_within <- R2$R2_within } if ("R2_within_adjusted" %in% names(R2)) { out$R2_within_adjusted <- R2$R2_within_adjusted } if (!any(c("R2", "R2_adj", "R2_adjusted", "R2_within", "R2_within_adjusted") %in% names(R2))) { out <- c(out, R2) } } } # RMSE ------------- if ("RMSE" %in% toupper(metrics)) { out$RMSE <- .safe(performance_rmse(model, verbose = verbose)) } # SIGMA ------------- if ("SIGMA" %in% toupper(metrics)) { out$Sigma <- .safe(.get_sigma(model, verbose = verbose)) } # LOGLOSS ------------- if (("LOGLOSS" %in% toupper(metrics)) && isTRUE(info$is_binomial)) { out$Log_loss <- .safe({ .logloss <- performance_logloss(model, verbose = verbose) if (is.na(.logloss)) { NULL } else { .logloss } }) } # SCORE ------------- if (("SCORE" %in% toupper(metrics)) && (isTRUE(info$is_binomial) || isTRUE(info$is_count))) { .scoring_rules <- .safe(performance_score(model, verbose = verbose)) if (!is.null(.scoring_rules)) { if (!is.na(.scoring_rules$logarithmic)) out$Score_log <- .scoring_rules$logarithmic if (!is.na(.scoring_rules$spherical)) out$Score_spherical <- .scoring_rules$spherical } } # PCP ------------- if (("PCP" %in% toupper(metrics)) && isTRUE(info$is_binomial) && isFALSE(info$is_multinomial) && isFALSE(info$is_ordinal)) { out$PCP <- .safe(performance_pcp(model, verbose = verbose)$pcp_model) } out <- as.data.frame(insight::compact_list(out, remove_na = TRUE), check.names = FALSE) # check if model was actually supported... if (nrow(out) == 0 || ncol(out) == 0) { if (isTRUE(verbose)) { insight::format_warning(paste0("Models of class `", class(model)[1], "` are not yet supported.")) } return(NULL) } row.names(out) <- NULL class(out) <- c("performance_model", class(out)) # Add attributes attributes(out) <- c(attributes(out), attrib) out } #' @export model_performance.glm <- model_performance.lm #' @export model_performance.Arima <- model_performance.lm #' @export model_performance.glmx <- model_performance.lm #' @export model_performance.lmrob <- model_performance.lm #' @export model_performance.betareg <- model_performance.lm #' @export model_performance.censReg <- model_performance.lm #' @export model_performance.clm <- model_performance.lm #' @export model_performance.clm2 <- model_performance.lm #' @export model_performance.coxph <- model_performance.lm #' @export model_performance.felm <- model_performance.lm #' @export model_performance.iv_robust <- model_performance.lm #' @export model_performance.lm_robust <- model_performance.lm #' @export model_performance.multinom <- model_performance.lm #' @export model_performance.multinom_weightit <- model_performance.lm #' @export model_performance.ordinal_weightit <- model_performance.lm #' @export model_performance.coxph_weightit <- model_performance.lm #' @export model_performance.glm_weightit <- model_performance.lm #' @export model_performance.plm <- model_performance.lm #' @export model_performance.polr <- model_performance.lm #' @export model_performance.bayesx <- model_performance.lm #' @export model_performance.survreg <- model_performance.lm #' @export model_performance.svyglm <- model_performance.lm #' @export model_performance.truncreg <- model_performance.lm #' @export model_performance.vglm <- model_performance.lm #' @export model_performance.fixest <- model_performance.lm #' @export model_performance.fixest_multi <- function(model, metrics = "all", verbose = TRUE, ...) { lapply(model, model_performance.fixest) } #' @export model_performance.DirichletRegModel <- model_performance.lm #' @export model_performance.flexsurvreg <- model_performance.lm #' @export model_performance.hurdle <- model_performance.lm #' @export model_performance.zeroinfl <- model_performance.lm #' @export model_performance.zerotrunc <- model_performance.lm #' @export model_performance.nestedLogit <- function(model, metrics = "all", verbose = TRUE, ...) { mp <- lapply(model$models, model_performance.lm, metrics = metrics, verbose = verbose, ...) out <- cbind( data.frame(Response = names(mp), stringsAsFactors = FALSE), do.call(rbind, mp) ) # need to handle R2 separately if (any(c("ALL", "R2") %in% toupper(metrics))) { out$R2 <- unlist(r2_tjur(model)) } row.names(out) <- NULL class(out) <- unique(c("performance_model", class(out))) out } # mfx models ------------------------------- #' @export model_performance.logitor <- function(model, ...) { model_performance(model$fit, ...) } #' @export model_performance.logitmfx <- model_performance.logitor #' @export model_performance.probitmfx <- model_performance.logitor #' @export model_performance.poissonirr <- model_performance.logitor #' @export model_performance.poissonmfx <- model_performance.logitor #' @export model_performance.negbinirr <- model_performance.logitor #' @export model_performance.negbinmfx <- model_performance.logitor #' @export model_performance.betaor <- model_performance.logitor #' @export model_performance.betamfx <- model_performance.logitor #' @export model_performance.model_fit <- model_performance.logitor # other models ------------------------------- #' @export model_performance.mlogit <- function(model, metrics = "all", verbose = TRUE, ...) { if (requireNamespace("mlogit", quietly = TRUE)) { model_performance.lm(model = model, metrics = metrics, verbose = verbose, ...) } else { NULL } } #' @export model_performance.margins <- function(model, metrics = "all", verbose = TRUE, ...) { orig_mod_call <- attributes(model)$call model_performance(eval(orig_mod_call), metrics = metrics, verbose = verbose, ...) } #' @export model_performance.sem <- function(model, metrics = "all", verbose = TRUE, ...) { if (inherits(model, "sem") && inherits(model, "lme")) { model_performance.lm(model, metrics = metrics, verbose = verbose, ...) } else { NULL } } performance/R/check_clusterstructure.R0000644000176200001440000001107714736731423017716 0ustar liggesusers#' Check suitability of data for clustering #' #' This checks whether the data is appropriate for clustering using the Hopkins' #' H statistic of given data. If the value of Hopkins statistic is close to 0 #' (below 0.5), then we can reject the null hypothesis and conclude that the #' dataset is significantly clusterable. A value for H lower than 0.25 indicates #' a clustering tendency at the `90%` confidence level. The visual assessment of #' cluster tendency (VAT) approach (Bezdek and Hathaway, 2002) consists in #' investigating the heatmap of the ordered dissimilarity matrix. Following #' this, one can potentially detect the clustering tendency by counting the #' number of square shaped blocks along the diagonal. #' #' @param x A data frame. #' @param standardize Standardize the data frame before clustering (default). #' @param distance Distance method used. Other methods than "euclidean" #' (default) are exploratory in the context of clustering tendency. See #' [stats::dist()] for list of available methods. #' @param ... Arguments passed to or from other methods. #' #' @examples #' \donttest{ #' library(performance) #' check_clusterstructure(iris[, 1:4]) #' plot(check_clusterstructure(iris[, 1:4])) #' } #' @return The H statistic (numeric) #' #' @seealso [`check_kmo()`], [`check_sphericity_bartlett()`] and #' [`check_factorstructure()`]. #' #' @references #' - Lawson, R. G., & Jurs, P. C. (1990). New index for clustering #' tendency and its application to chemical problems. Journal of chemical #' information and computer sciences, 30(1), 36-41. #' #' - Bezdek, J. C., & Hathaway, R. J. (2002, May). VAT: A tool for visual #' assessment of (cluster) tendency. In Proceedings of the 2002 International #' Joint Conference on Neural Networks. IJCNN02 (3), 2225-2230. IEEE. #' @export check_clusterstructure <- function(x, standardize = TRUE, distance = "euclidean", ...) { if (standardize) { x <- as.data.frame(scale(x)) } H <- .clusterstructure_hopkins(x, distance = distance) if (H < 0.5) { res_text <- paste0( "The dataset is suitable for clustering (Hopkins' H = ", insight::format_value(H), ").\n" ) color <- "green" } else { res_text <- paste0( "The dataset is not suitable for clustering (Hopkins' H = ", insight::format_value(H), ").\n" ) color <- "red" } out <- list( H = H, dissimilarity_matrix = .clusterstructure_dm(x, distance = distance, method = "ward.D2") ) attr(out, "text") <- res_text attr(out, "color") <- color attr(out, "title") <- "Clustering tendency" class(out) <- c("see_check_clusterstructure", "check_clusterstructure", "easystats_check", class(out)) out } #' @export plot.check_clusterstructure <- function(x, ...) { # Can be reimplemented with ggplot in see stats::heatmap( x$dissimilarity_matrix, Rowv = NA, Colv = NA, labRow = FALSE, labCol = FALSE, col = grDevices::colorRampPalette(c("#2196F3", "#FAFAFA", "#E91E63"))(100) ) } #' @keywords internal .clusterstructure_dm <- function(x, distance = "euclidean", method = "ward.D2") { d <- stats::dist(x, method = distance) hc <- stats::hclust(d, method = method) as.matrix(d)[hc$order, hc$order] } #' @keywords internal .clusterstructure_hopkins <- function(x, distance = "euclidean") { # This is based on the hopkins() function from the clustertend package if (is.data.frame(x)) { x <- as.matrix(x) } n <- nrow(x) - 1 cc <- apply(x, 2, min) # minimum value per column d <- apply(x, 2, max) p <- matrix(0, ncol = ncol(x), nrow = n) # n vectors of space for (i in seq_len(ncol(x))) { p[, i] <- stats::runif(n, min = cc[i], max = d[i]) } k <- round(stats::runif(n, 1, nrow(x))) qq <- as.matrix(x[k, ]) distp <- rep(0, nrow(x)) distq <- 0 minp <- rep(0, n) minq <- rep(0, n) for (i in 1:n) { distp[1] <- stats::dist(rbind(p[i, ], x[1, ]), method = distance) minqi <- stats::dist(rbind(qq[i, ], x[1, ]), method = distance) for (j in 2:nrow(x)) { distp[j] <- stats::dist(rbind(p[i, ], x[j, ]), method = distance) error <- qq[i, ] - x[j, ] if (sum(abs(error)) != 0) { distq <- stats::dist(rbind(qq[i, ], x[j, ]), method = distance) if (distq < minqi) { minqi <- distq } } } minp[i] <- min(distp) minq[i] <- minqi } sum(minq) / (sum(minp) + sum(minq)) } performance/R/check_model.R0000644000176200001440000006505514736731423015361 0ustar liggesusers#' @title Visual check of model assumptions #' @name check_model #' #' @description #' Visual check of various model assumptions (normality of residuals, normality #' of random effects, linear relationship, homogeneity of variance, #' multicollinearity). #' #' If `check_model()` doesn't work as expected, try setting `verbose = TRUE` to #' get hints about possible problems. #' #' @param x A model object. #' @param size_dot,size_line Size of line and dot-geoms. #' @param base_size,size_title,size_axis_title Base font size for axis and plot titles. #' @param panel Logical, if `TRUE`, plots are arranged as panels; else, #' single plots for each diagnostic are returned. #' @param check Character vector, indicating which checks for should be performed #' and plotted. May be one or more of `"all"`, `"vif"`, `"qq"`, `"normality"`, #' `"linearity"`, `"ncv"`, `"homogeneity"`, `"outliers"`, `"reqq"`, `"pp_check"`, #' `"binned_residuals"` or `"overdispersion"`. Note that not all check apply #' to all type of models (see 'Details'). `"reqq"` is a QQ-plot for random #' effects and only available for mixed models. `"ncv"` is an alias for #' `"linearity"`, and checks for non-constant variance, i.e. for #' heteroscedasticity, as well as the linear relationship. By default, all #' possible checks are performed and plotted. #' @param alpha,alpha_dot The alpha level of the confidence bands and dot-geoms. #' Scalar from 0 to 1. #' @param colors Character vector with color codes (hex-format). Must be of #' length 3. First color is usually used for reference lines, second color #' for dots, and third color for outliers or extreme values. #' @param theme String, indicating the name of the plot-theme. Must be in the #' format `"package::theme_name"` (e.g. `"ggplot2::theme_minimal"`). #' @param detrend Logical. Should Q-Q/P-P plots be detrended? Defaults to #' `TRUE` for linear models or when `residual_type = "normal"`. Defaults to #' `FALSE` for QQ plots based on simulated residuals (i.e. when #' `residual_type = "simulated"`). #' @param residual_type Character, indicating the type of residuals to be used. #' For non-Gaussian models, the default is `"simulated"`, which uses simulated #' residuals. These are based on [`simulate_residuals()`] and thus uses the #' **DHARMa** package to return randomized quantile residuals. For Gaussian #' models, the default is `"normal"`, which uses the default residuals from #' the model. Setting `residual_type = "normal"` for non-Gaussian models will #' use a half-normal Q-Q plot of the absolute value of the standardized deviance #' residuals. #' @param show_dots Logical, if `TRUE`, will show data points in the plot. Set #' to `FALSE` for models with many observations, if generating the plot is too #' time-consuming. By default, `show_dots = NULL`. In this case `check_model()` #' tries to guess whether performance will be poor due to a very large model #' and thus automatically shows or hides dots. #' @param verbose If `FALSE` (default), suppress most warning messages. #' @param ... Arguments passed down to the individual check functions, especially #' to `check_predictions()` and `binned_residuals()`. #' @inheritParams check_predictions #' #' @return The data frame that is used for plotting. #' #' @note This function just prepares the data for plotting. To create the plots, #' **see** needs to be installed. Furthermore, this function suppresses #' all possible warnings. In case you observe suspicious plots, please refer #' to the dedicated functions (like `check_collinearity()`, #' `check_normality()` etc.) to get informative messages and warnings. #' #' @details For Bayesian models from packages **rstanarm** or **brms**, #' models will be "converted" to their frequentist counterpart, using #' [`bayestestR::bayesian_as_frequentist`](https://easystats.github.io/bayestestR/reference/convert_bayesian_as_frequentist.html). #' A more advanced model-check for Bayesian models will be implemented at a #' later stage. #' #' See also the related [vignette](https://easystats.github.io/performance/articles/check_model.html). #' #' @section Posterior Predictive Checks: #' Posterior predictive checks can be used to look for systematic discrepancies #' between real and simulated data. It helps to see whether the type of model #' (distributional family) fits well to the data. See [`check_predictions()`] #' for further details. #' #' @section Linearity Assumption: #' The plot **Linearity** checks the assumption of linear relationship. #' However, the spread of dots also indicate possible heteroscedasticity (i.e. #' non-constant variance, hence, the alias `"ncv"` for this plot), thus it shows #' if residuals have non-linear patterns. This plot helps to see whether #' predictors may have a non-linear relationship with the outcome, in which case #' the reference line may roughly indicate that relationship. A straight and #' horizontal line indicates that the model specification seems to be ok. But #' for instance, if the line would be U-shaped, some of the predictors probably #' should better be modeled as quadratic term. See [`check_heteroscedasticity()`] #' for further details. #' #' **Some caution is needed** when interpreting these plots. Although these #' plots are helpful to check model assumptions, they do not necessarily indicate #' so-called "lack of fit", e.g. missed non-linear relationships or interactions. #' Thus, it is always recommended to also look at #' [effect plots, including partial residuals](https://strengejacke.github.io/ggeffects/articles/introduction_partial_residuals.html). #' #' @section Homogeneity of Variance: #' This plot checks the assumption of equal variance (homoscedasticity). The #' desired pattern would be that dots spread equally above and below a straight, #' horizontal line and show no apparent deviation. #' #' @section Influential Observations: #' This plot is used to identify influential observations. If any points in this #' plot fall outside of Cook’s distance (the dashed lines) then it is considered #' an influential observation. See [`check_outliers()`] for further details. #' #' @section Multicollinearity: #' This plot checks for potential collinearity among predictors. In a nutshell, #' multicollinearity means that once you know the effect of one predictor, the #' value of knowing the other predictor is rather low. Multicollinearity might #' arise when a third, unobserved variable has a causal effect on each of the #' two predictors that are associated with the outcome. In such cases, the actual #' relationship that matters would be the association between the unobserved #' variable and the outcome. See [`check_collinearity()`] for further details. #' #' @section Normality of Residuals: #' This plot is used to determine if the residuals of the regression model are #' normally distributed. Usually, dots should fall along the line. If there is #' some deviation (mostly at the tails), this indicates that the model doesn't #' predict the outcome well for that range that shows larger deviations from #' the line. For generalized linear models and when `residual_type = "normal"`, #' a half-normal Q-Q plot of the absolute value of the standardized deviance #' residuals is shown, however, the interpretation of the plot remains the same. #' See [`check_normality()`] for further details. Usually, for generalized linear #' (mixed) models, a test for uniformity of residuals based on simulated residuals #' is conducted (see next section). #' #' @section Uniformity of Residuals: #' Fore non-Gaussian models, when `residual_type = "simulated"` (the default #' for generalized linear (mixed) models), residuals are not expected to be #' normally distributed. In this case, the created Q-Q plot checks the uniformity #' of residuals. The interpretation of the plot is the same as for the normal #' Q-Q plot. See [`simulate_residuals()`] and [`check_residuals()`] for further #' details. #' #' @section Overdispersion: #' For count models, an *overdispersion plot* is shown. Overdispersion occurs #' when the observed variance is higher than the variance of a theoretical model. #' For Poisson models, variance increases with the mean and, therefore, variance #' usually (roughly) equals the mean value. If the variance is much higher, #' the data are "overdispersed". See [`check_overdispersion()`] for further #' details. #' #' @section Binned Residuals: #' For models from binomial families, a *binned residuals plot* is shown. #' Binned residual plots are achieved by cutting the the data into bins and then #' plotting the average residual versus the average fitted value for each bin. #' If the model were true, one would expect about 95% of the residuals to fall #' inside the error bounds. See [`binned_residuals()`] for further details. #' #' @section Residuals for (Generalized) Linear Models: #' Plots that check the homogeneity of variance use standardized Pearson's #' residuals for generalized linear models, and standardized residuals for #' linear models. The plots for the normality of residuals (with overlayed #' normal curve) and for the linearity assumption use the default residuals #' for `lm` and `glm` (which are deviance residuals for `glm`). The Q-Q plots #' use simulated residuals (see [`simulate_residuals()`]) for non-Gaussian #' models and standardized residuals for linear models. #' #' @section Troubleshooting: #' For models with many observations, or for more complex models in general, #' generating the plot might become very slow. One reason might be that the #' underlying graphic engine becomes slow for plotting many data points. In #' such cases, setting the argument `show_dots = FALSE` might help. Furthermore, #' look at the `check` argument and see if some of the model checks could be #' skipped, which also increases performance. #' #' If `check_model()` doesn't work as expected, try setting `verbose = TRUE` to #' get hints about possible problems. #' #' @family functions to check model assumptions and and assess model quality #' #' @examplesIf require("lme4") #' \donttest{ #' m <- lm(mpg ~ wt + cyl + gear + disp, data = mtcars) #' check_model(m) #' #' data(sleepstudy, package = "lme4") #' m <- lme4::lmer(Reaction ~ Days + (Days | Subject), sleepstudy) #' check_model(m, panel = FALSE) #' } #' @export check_model <- function(x, ...) { UseMethod("check_model") } # default ---------------------------- #' @rdname check_model #' @export check_model.default <- function(x, panel = TRUE, check = "all", detrend = TRUE, bandwidth = "nrd", type = "density", residual_type = NULL, show_dots = NULL, size_dot = 2, size_line = 0.8, size_title = 12, size_axis_title = base_size, base_size = 10, alpha = 0.2, alpha_dot = 0.8, colors = c("#3aaf85", "#1b6ca8", "#cd201f"), theme = "see::theme_lucid", verbose = FALSE, ...) { # check model formula if (verbose) { insight::formula_ok(x) } minfo <- insight::model_info(x, verbose = FALSE) # set default for residual_type if (is.null(residual_type)) { residual_type <- ifelse(minfo$is_linear && !minfo$is_gam, "normal", "simulated") } # catch models/families not supported by DHARMa - we need to add more # exceptions here as they appear, but for now, `check_model()` also # automatically falls back to normal Q-Q plot for all models not supported # by DHARMa if (minfo$family %in% c("quasipoisson", "quasibinomial")) { residual_type <- "normal" } # set default for detrend if (missing(detrend)) { detrend <- residual_type == "normal" } assumptions_data <- tryCatch( if (minfo$is_bayesian) { suppressWarnings(.check_assumptions_stan(x, ...)) } else if (minfo$is_linear) { suppressWarnings(.check_assumptions_linear(x, minfo, check, residual_type, verbose, ...)) } else { suppressWarnings(.check_assumptions_glm(x, minfo, check, residual_type, verbose, ...)) }, error = function(e) { e } ) if (inherits(assumptions_data, c("error", "simpleError"))) { pattern <- "(\n|\\s{2,})" replacement <- " " cleaned_string <- gsub(pattern, replacement, assumptions_data$message) insight::format_error( paste("`check_model()` returned following error:", cleaned_string), paste0("\nIf the error message does not help identifying your problem, another reason why `check_model()` failed might be that models of class `", class(x)[1], "` are not yet supported.") # nolint ) } # did Q-Q plot work with simulated residuals? if (is.null(assumptions_data$QQ) && residual_type == "simulated") { insight::format_alert(paste0( "Cannot simulate residuals for models of class `", class(x)[1], "`. Please try `check_model(..., residual_type = \"normal\")` instead." )) } # try to find sensible default for "type" argument suggest_dots <- (minfo$is_bernoulli || minfo$is_count || minfo$is_ordinal || minfo$is_categorical || minfo$is_multinomial) # nolint if (missing(type) && suggest_dots) { type <- "discrete_interval" } # set default for show_dots, based on "model size" if (is.null(show_dots)) { n <- .safe(insight::n_obs(x)) show_dots <- is.null(n) || n <= 1e5 } attr(assumptions_data, "panel") <- panel attr(assumptions_data, "dot_size") <- size_dot attr(assumptions_data, "line_size") <- size_line attr(assumptions_data, "base_size") <- base_size attr(assumptions_data, "axis_title_size") <- size_axis_title attr(assumptions_data, "title_size") <- size_title attr(assumptions_data, "check") <- check attr(assumptions_data, "alpha") <- alpha attr(assumptions_data, "dot_alpha") <- alpha_dot attr(assumptions_data, "show_dots") <- isTRUE(show_dots) attr(assumptions_data, "detrend") <- detrend attr(assumptions_data, "colors") <- colors attr(assumptions_data, "theme") <- theme attr(assumptions_data, "model_info") <- minfo attr(assumptions_data, "overdisp_type") <- list(...)$plot_type attr(assumptions_data, "bandwidth") <- bandwidth attr(assumptions_data, "type") <- type attr(assumptions_data, "model_class") <- class(x)[1] assumptions_data } # methods ---------------------------------- #' @export print.check_model <- function(x, ...) { insight::check_if_installed("see", "for model diagnostic plots") NextMethod() } #' @export plot.check_model <- function(x, ...) { insight::check_if_installed("see", "for model diagnostic plots") NextMethod() } # other classes --------------------------- ## TODO for now, convert to freq, see https://github.com/easystats/performance/issues/354 ## need to fix this later #' @export check_model.stanreg <- function(x, panel = TRUE, check = "all", detrend = TRUE, bandwidth = "nrd", type = "density", residual_type = NULL, show_dots = NULL, size_dot = 2, size_line = 0.8, size_title = 12, size_axis_title = base_size, base_size = 10, alpha = 0.2, alpha_dot = 0.8, colors = c("#3aaf85", "#1b6ca8", "#cd201f"), theme = "see::theme_lucid", verbose = FALSE, ...) { check_model(bayestestR::bayesian_as_frequentist(x), size_dot = size_dot, size_line = size_line, panel = panel, check = check, alpha = alpha, alpha_dot = alpha_dot, colors = colors, theme = theme, base_size = base_size, size_axis_title = size_axis_title, detrend = detrend, show_dots = show_dots, bandwidth = bandwidth, type = type, residual_type = residual_type, verbose = verbose, ... ) } #' @export check_model.brmsfit <- check_model.stanreg #' @export check_model.model_fit <- function(x, panel = TRUE, check = "all", detrend = TRUE, bandwidth = "nrd", type = "density", residual_type = NULL, show_dots = NULL, size_dot = 2, size_line = 0.8, size_title = 12, size_axis_title = base_size, base_size = 10, alpha = 0.2, alpha_dot = 0.8, colors = c("#3aaf85", "#1b6ca8", "#cd201f"), theme = "see::theme_lucid", verbose = FALSE, ...) { check_model( x$fit, size_dot = size_dot, size_line = size_line, panel = panel, check = check, alpha = alpha, size_axis_title = size_axis_title, alpha_dot = alpha_dot, colors = colors, theme = theme, base_size = base_size, detrend = detrend, show_dots = show_dots, bandwidth = bandwidth, type = type, residual_type = residual_type, verbose = verbose, ... ) } #' @export check_model.performance_simres <- function(x, panel = TRUE, check = "all", detrend = TRUE, bandwidth = "nrd", type = "density", residual_type = NULL, show_dots = NULL, size_dot = 2, size_line = 0.8, size_title = 12, size_axis_title = base_size, base_size = 10, alpha = 0.2, alpha_dot = 0.8, colors = c("#3aaf85", "#1b6ca8", "#cd201f"), theme = "see::theme_lucid", verbose = FALSE, ...) { check_model( x$fittedModel, size_dot = size_dot, size_line = size_line, panel = panel, check = check, alpha = alpha, alpha_dot = alpha_dot, size_axis_title = size_axis_title, colors = colors, theme = theme, base_size = base_size, detrend = detrend, show_dots = show_dots, bandwidth = bandwidth, type = type, residual_type = "simulated", verbose = verbose, ... ) } #' @export check_model.DHARMa <- check_model.performance_simres # compile plots for checks of linear models ------------------------ .check_assumptions_linear <- function(model, model_info, check = "all", residual_type = "normal", verbose = TRUE, ...) { dat <- list() # multicollinearity -------------- if (any(c("all", "vif") %in% check)) { dat$VIF <- .model_diagnostic_vif(model, verbose = verbose) } # Q-Q plot (normality/uniformity of residuals) -------------- if (any(c("all", "qq") %in% check)) { dat$QQ <- switch(residual_type, simulated = .safe(simulate_residuals(model, ...)), .model_diagnostic_qq(model, model_info = model_info, verbose = verbose) ) } # Random Effects Q-Q plot (normality of BLUPs) -------------- if (any(c("all", "reqq") %in% check)) { dat$REQQ <- .model_diagnostic_ranef_qq(model, level = 0.95, model_info = model_info, verbose = verbose) } # normal-curve plot (normality of residuals) -------------- if (any(c("all", "normality") %in% check)) { dat$NORM <- .model_diagnostic_normality(model, verbose = verbose) } # non-constant variance (heteroskedasticity, liniearity) -------------- if (any(c("all", "ncv", "linearity") %in% check)) { dat$NCV <- .model_diagnostic_ncv(model, verbose = verbose) } # homogeneity of variance -------------- if (any(c("all", "homogeneity") %in% check)) { dat$HOMOGENEITY <- .model_diagnostic_homogeneity(model, verbose = verbose) } # outliers -------------- if (any(c("all", "outliers") %in% check)) { dat$OUTLIERS <- .safe(check_outliers(model, method = "cook")) if (is.null(dat$OUTLIERS)) { threshold <- NULL } else { threshold <- attributes(dat$OUTLIERS)$threshold$cook } dat$INFLUENTIAL <- .safe(.model_diagnostic_outlier(model, threshold = threshold)) } # posterior predictive checks -------------- if (any(c("all", "pp_check") %in% check)) { dat$PP_CHECK <- .safe(check_predictions(model, verbose = verbose, ...)) } dat <- insight::compact_list(dat) class(dat) <- c("check_model", "see_check_model") dat } # compile plots for checks of generalized linear models ------------------------ .check_assumptions_glm <- function(model, model_info, check = "all", residual_type = "simulated", verbose = TRUE, ...) { dat <- list() # multicollinearity -------------- if (any(c("all", "vif") %in% check)) { dat$VIF <- .model_diagnostic_vif(model, verbose = verbose) } # Q-Q plot (normality/uniformity of residuals) -------------- if (any(c("all", "qq") %in% check)) { dat$QQ <- switch(residual_type, simulated = .safe(simulate_residuals(model, ...)), .model_diagnostic_qq(model, model_info = model_info, verbose = verbose) ) } # homogeneity of variance -------------- if (any(c("all", "homogeneity") %in% check)) { dat$HOMOGENEITY <- .model_diagnostic_homogeneity(model, verbose = verbose) } # Random Effects Q-Q plot (normality of BLUPs) -------------- if (any(c("all", "reqq") %in% check)) { dat$REQQ <- .model_diagnostic_ranef_qq(model, level = 0.95, model_info = model_info, verbose = verbose) } # outliers -------------- if (any(c("all", "outliers") %in% check)) { dat$OUTLIERS <- .safe(check_outliers(model, method = "cook")) if (is.null(dat$OUTLIERS)) { threshold <- NULL } else { threshold <- attributes(dat$OUTLIERS)$threshold$cook } dat$INFLUENTIAL <- .safe(.model_diagnostic_outlier(model, threshold = threshold)) } # posterior predictive checks -------------- if (any(c("all", "pp_check") %in% check)) { dat$PP_CHECK <- .safe(check_predictions(model, verbose = verbose, ...)) } # binned residuals for bernoulli/binomial -------------- if (isTRUE(model_info$is_binomial) && any(c("all", "binned_residuals") %in% check)) { dat$BINNED_RESID <- .safe(binned_residuals(model, verbose = verbose, ...)) } # misspecified dispersion and zero-inflation -------------- if (isTRUE(model_info$is_count) && any(c("all", "overdispersion") %in% check)) { dat$OVERDISPERSION <- .model_diagnostic_overdispersion(model) } dat <- insight::compact_list(dat) class(dat) <- c("check_model", "see_check_model") dat } # compile plots for checks of Bayesian models ------------------------ .check_assumptions_stan <- function(model, ...) { if (inherits(model, "brmsfit")) { # check if brms can be loaded if (!requireNamespace("brms", quietly = TRUE)) { insight::format_error("Package `brms` needs to be loaded first!") } # check if prior sample are available d2 <- brms::prior_samples(model) if (is.null(d2)) { insight::format_error( "No prior-samples found. Please use option `sample_prior = TRUE` when fitting the model." ) } d1 <- brms::posterior_samples(model) # get samples from posterior and prior d1 <- d1[, grepl(pattern = "(b_|bs_|bsp_|bcs_)(?!(Intercept|zi_Intercept))(.*)", colnames(d1), perl = TRUE)] d2 <- d2[, grepl(pattern = "(b_|bs_|bsp_|bcs_)(?!(Intercept|zi_Intercept))(.*)", colnames(d2), perl = TRUE)] } else if (inherits(model, c("stanreg", "stanfit"))) { # check if rstanarm can be loaded if (!requireNamespace("rstanarm", quietly = TRUE)) { insight::format_error("Package `rstanarm` needs to be loaded first!") } # get samples from posterior and prior prior <- suppressWarnings( stats::update( model, prior_PD = TRUE, refresh = -1, iter = 2000, chains = 2 ) ) d1 <- as.data.frame(model) d2 <- as.data.frame(prior) # remove intercept from output for ridgeline plot. # this would increase the range of the scale too much if (insight::object_has_names(d1, "(Intercept)")) { d1 <- datawizard::data_remove(d1, "(Intercept)") } if (insight::object_has_names(d2, "(Intercept)")) { d2 <- datawizard::data_remove(d2, "(Intercept)") } if (insight::object_has_names(d1, "sigma")) { d1 <- datawizard::data_remove(d1, "sigma") } if (insight::object_has_names(d2, "sigma")) { d2 <- datawizard::data_remove(d2, "sigma") } d1 <- d1[, grepl(pattern = "^(?!(b\\[\\(Intercept\\)|Sigma\\[))(.*)", colnames(d1), perl = TRUE)] d2 <- d2[, grepl(pattern = "^(?!(b\\[\\(Intercept\\)|Sigma\\[))(.*)", colnames(d2), perl = TRUE)] } # grouping variable d1$group <- "Posterior" d2$group <- "Prior" gather.cols <- colnames(d1)[1:(ncol(d1) - 1)] dat <- stats::reshape( rbind(d1, d2), idvar = "id", times = gather.cols, timevar = "y", v.names = "x", varying = gather.cols, direction = "long" ) class(dat) <- c("check_model", "see_check_model", "data.frame") dat } performance/R/performance-package.R0000644000176200001440000000226214346602101016770 0ustar liggesusers#' \code{performance-package} #' #' @title performance: An R Package for Assessment, Comparison and Testing of #' Statistical Models #' #' @description #' #' A crucial aspect when building regression models is to evaluate the #' quality of modelfit. It is important to investigate how well models fit #' to the data and which fit indices to report. Functions to create #' diagnostic plots or to compute fit measures do exist, however, mostly #' spread over different packages. There is no unique and consistent #' approach to assess the model quality for different kind of models. #' #' The primary goal of the **performance** package is to fill this gap and #' to provide utilities for computing **indices of model quality** and #' **goodness of fit**. These include measures like r-squared (R2), root #' mean squared error (RMSE) or intraclass correlation coefficient (ICC), #' but also functions to check (mixed) models for overdispersion, #' zero-inflation, convergence or singularity. #' #' References: Lüdecke et al. (2021) \doi{10.21105/joss.03139} #' #' @docType package #' @name performance-package #' @aliases performance-package #' @keywords internal "_PACKAGE" performance/R/check_concurvity.R0000644000176200001440000000275514736731423016464 0ustar liggesusers#' @rdname check_collinearity #' @export check_concurvity <- function(x, ...) { UseMethod("check_concurvity") } #' @export check_concurvity.gam <- function(x, ...) { insight::check_if_installed("mgcv") conc <- as.data.frame(mgcv::concurvity(x)) # only smooth terms smooth_terms <- colnames(conc)[grepl("s\\((.*)\\)", colnames(conc))] out <- data.frame( Term = c("Parametric", smooth_terms), VIF = as.vector(1 / (1 - as.numeric(conc[1, ]))), VIF_proportion = as.vector(as.numeric(conc[3, ])), stringsAsFactors = FALSE ) class(out) <- c("check_concurvity", "see_check_concurvity", class(out)) out } # methods --------------------------------- #' @export print.check_concurvity <- function(x, ...) { vifs <- x$VIF x$VIF <- sprintf("%.2f", x$VIF) x$VIF_proportion <- sprintf("%.2f", x$VIF_proportion) colnames(x)[3] <- "VIF %" low_corr <- which(vifs < 5) if (length(low_corr)) { cat("\n") insight::print_color("Low Concurvity\n\n", "green") print.data.frame(x[low_corr, ], row.names = FALSE) } mid_corr <- which(vifs >= 5 & vifs < 10) if (length(mid_corr)) { cat("\n") insight::print_color("Moderate Concurvity\n\n", "yellow") print.data.frame(x[mid_corr, ], row.names = FALSE) } high_corr <- which(vifs >= 10) if (length(high_corr)) { cat("\n") insight::print_color("High Concurvity\n\n", "red") print.data.frame(x[high_corr, ], row.names = FALSE) } } performance/R/r2.R0000644000176200001440000005436114736731423013445 0ustar liggesusers#' @title Compute the model's R2 #' @name r2 #' #' @description Calculate the R2, also known as the coefficient of #' determination, value for different model objects. Depending on the model, #' R2, pseudo-R2, or marginal / adjusted R2 values are returned. #' #' @param model A statistical model. #' @param verbose Logical. Should details about R2 and CI methods be given #' (`TRUE`) or not (`FALSE`)? #' @param ci Confidence interval level, as scalar. If `NULL` (default), no #' confidence intervals for R2 are calculated. #' @param multivariate Logical. Should multiple R2 values be reported as #' separated by response (FALSE) or should a single R2 be reported as #' combined across responses computed by [`r2_mlm`] (TRUE). #' @param ... Arguments passed down to the related r2-methods. #' @inheritParams r2_nakagawa #' #' @return Returns a list containing values related to the most appropriate R2 #' for the given model (or `NULL` if no R2 could be extracted). See the #' list below: #' - Logistic models: [Tjur's R2][r2_tjur] #' - General linear models: [Nagelkerke's R2][r2_nagelkerke] #' - Multinomial Logit: [McFadden's R2][r2_mcfadden] #' - Models with zero-inflation: [R2 for zero-inflated models][r2_zeroinflated] #' - Mixed models: [Nakagawa's R2][r2_nakagawa] #' - Bayesian models: [R2 bayes][r2_bayes] #' #' @note #' If there is no `r2()`-method defined for the given model class, `r2()` tries #' to return a "generic" r-quared value, calculated as following: #' `1-sum((y-y_hat)^2)/sum((y-y_bar)^2)` #' #' @seealso #' [`r2_bayes()`], [`r2_coxsnell()`], [`r2_kullback()`], [`r2_loo()`], #' [`r2_mcfadden()`], [`r2_nagelkerke()`], [`r2_nakagawa()`], [`r2_tjur()`], #' [`r2_xu()`], [`r2_zeroinflated()`], and [`r2_mlm()`]. #' #' @examplesIf require("lme4") #' # Pseudo r-quared for GLM #' model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") #' r2(model) #' #' # r-squared including confidence intervals #' model <- lm(mpg ~ wt + hp, data = mtcars) #' r2(model, ci = 0.95) #' #' model <- lme4::lmer(Sepal.Length ~ Petal.Length + (1 | Species), data = iris) #' r2(model) #' @export r2 <- function(model, ...) { UseMethod("r2") } # Default models ----------------------------------------------- #' @rdname r2 #' @export r2.default <- function(model, ci = NULL, verbose = TRUE, ...) { # CI has own function if (!is.null(ci) && !is.na(ci)) { return(.r2_ci(model, ci = ci, verbose = verbose, ...)) } minfo <- list(...)$model_info if (is.null(minfo)) { minfo <- suppressWarnings(insight::model_info(model, verbose = FALSE)) } ## TODO: implement bootstrapped CIs later? # check input # ci <- .check_r2_ci_args(ci, ci_method, "bootstrap", verbose) out <- tryCatch( { if (minfo$is_binomial) { resp <- .recode_to_zero(insight::get_response(model, verbose = FALSE)) } else { resp <- datawizard::to_numeric( insight::get_response(model, verbose = FALSE), dummy_factors = FALSE, preserve_levels = TRUE ) } mean_resp <- mean(resp, na.rm = TRUE) pred <- insight::get_predicted(model, ci = NULL, verbose = FALSE) list(R2 = 1 - sum((resp - pred)^2) / sum((resp - mean_resp)^2)) }, error = function(e) { NULL } ) if (is.null(out) && isTRUE(verbose)) { insight::print_color(sprintf("`r2()` does not support models of class `%s`.\n", class(model)[1]), "red") } if (!is.null(out)) { names(out$R2) <- "R2" class(out) <- c("r2_generic", class(out)) } out } #' @export r2.lm <- function(model, ci = NULL, ...) { if (!is.null(ci) && !is.na(ci)) { return(.r2_ci(model, ci = ci, ...)) } .r2_lm(summary(model)) } #' @export r2.phylolm <- r2.lm # helper ------------- .r2_lm <- function(model_summary, ci = NULL) { out <- list( R2 = model_summary$r.squared, R2_adjusted = model_summary$adj.r.squared ) names(out$R2) <- "R2" names(out$R2_adjusted) <- "adjusted R2" f.stat <- model_summary$fstatistic[1] DoF <- model_summary$fstatistic[2] DoF_residual <- model_summary$fstatistic[3] if (!is.null(f.stat)) { attr(out, "p") <- stats::pf(f.stat, DoF, DoF_residual, lower.tail = FALSE) attr(out, "F") <- f.stat attr(out, "df") <- DoF attr(out, "df_residual") <- DoF_residual } attr(out, "model_type") <- "Linear" structure(class = "r2_generic", out) } #' @export r2.summary.lm <- function(model, ci = NULL, ...) { if (!is.null(ci) && !is.na(ci)) { return(.r2_ci(model, ci = ci, ...)) } .r2_lm(model) } #' @export r2.systemfit <- function(model, ...) { out <- lapply(summary(model)$eq, function(model_summary) { s <- list( R2 = model_summary$r.squared, R2_adjusted = model_summary$adj.r.squared ) names(s$R2) <- "R2" names(s$R2_adjusted) <- "adjusted R2" s }) names(out) <- names(insight::find_formula(model)) out } #' @export r2.lm_robust <- function(model, ...) { out <- list( R2 = tryCatch( model[["r.squared"]], error = function(e) NULL ), R2_adjusted = tryCatch( model[["adj.r.squared"]], error = function(e) NULL ) ) names(out$R2) <- "R2" names(out$R2_adjusted) <- "adjusted R2" attr(out, "model_type") <- "Linear" structure(class = "r2_generic", out) } #' @export r2.ols <- function(model, ...) { out <- list(R2 = model$stats["R2"]) names(out$R2) <- "R2" attr(out, "model_type") <- "Linear" structure(class = "r2_generic", out) } #' @export r2.lrm <- r2.ols #' @export r2.cph <- r2.ols #' @export r2.mhurdle <- function(model, ...) { resp <- insight::get_response(model, verbose = FALSE) mean_resp <- mean(resp, na.rm = TRUE) ftd <- model$fitted.values[, "pos", drop = TRUE] * (1 - model$fitted.values[, "zero", drop = TRUE]) n <- length(resp) K <- insight::n_parameters(model) Ko <- length(model$naive$coefficients) out <- list( R2 = 1 - sum((resp - ftd)^2) / sum((resp - mean_resp)^2), R2_adjusted = 1 - (n - Ko) / (n - K) * sum((resp - ftd)^2) / sum((resp - mean_resp)^2) ) names(out$R2) <- "R2" names(out$R2_adjusted) <- "adjusted R2" attr(out, "model_type") <- "Limited Dependent Variable" structure(class = "r2_generic", out) } #' @export r2.aov <- function(model, ci = NULL, ...) { if (!is.null(ci) && !is.na(ci)) { return(.r2_ci(model, ci = ci, ...)) } model_summary <- stats::summary.lm(model) out <- list( R2 = model_summary$r.squared, R2_adjusted = model_summary$adj.r.squared ) names(out$R2) <- "R2" names(out$R2_adjusted) <- "adjusted R2" attr(out, "model_type") <- "Anova" structure(class = "r2_generic", out) } #' @rdname r2 #' @export r2.mlm <- function(model, multivariate = TRUE, ...) { if (multivariate) { out <- r2_mlm(model) } else { model_summary <- summary(model) out <- lapply(names(model_summary), function(i) { tmp <- list( R2 = model_summary[[i]]$r.squared, R2_adjusted = model_summary[[i]]$adj.r.squared, Response = sub("Response ", "", i, fixed = TRUE) ) names(tmp$R2) <- "R2" names(tmp$R2_adjusted) <- "adjusted R2" names(tmp$Response) <- "Response" tmp }) names(out) <- names(model_summary) } attr(out, "model_type") <- "Multivariate Linear" structure(class = "r2_mlm", out) } #' @export r2.glm <- function(model, ci = NULL, verbose = TRUE, ...) { if (!is.null(ci) && !is.na(ci)) { return(.r2_ci(model, ci = ci, verbose = verbose, ...)) } info <- list(...)$model_info if (is.null(info)) { info <- suppressWarnings(insight::model_info(model, verbose = FALSE)) } if (info$family %in% c("gaussian", "inverse.gaussian")) { out <- r2.default(model, ...) } else if (info$is_logit && info$is_bernoulli) { out <- list(R2_Tjur = r2_tjur(model, model_info = info, ...)) attr(out, "model_type") <- "Logistic" names(out$R2_Tjur) <- "Tjur's R2" class(out) <- c("r2_pseudo", class(out)) } else if (info$is_binomial && !info$is_bernoulli && class(model)[1] == "glm") { if (verbose) { insight::format_warning("Can't calculate accurate R2 for binomial models that are not Bernoulli models.") } out <- NULL } else if (info$is_orderedbeta) { # ordered-beta-regression out <- r2_ferrari(model, correct_bounds = TRUE) } else if (info$is_beta) { # beta-regression out <- r2_ferrari(model) } else { out <- list(R2_Nagelkerke = r2_nagelkerke(model, ...)) names(out$R2_Nagelkerke) <- "Nagelkerke's R2" attr(out, "model_type") <- "Generalized Linear" class(out) <- c("r2_pseudo", class(out)) } out } #' @export r2.glmx <- r2.glm #' @export r2.nestedLogit <- function(model, ci = NULL, verbose = TRUE, ...) { out <- list(R2_Tjur = r2_tjur(model, ...)) attr(out, "model_type") <- "Logistic" class(out) <- c("r2_pseudo", class(out)) out } # mfx models --------------------- #' @export r2.logitmfx <- function(model, ...) { r2(model$fit, ...) } #' @export r2.logitor <- r2.logitmfx #' @export r2.poissonirr <- r2.logitmfx #' @export r2.poissonmfx <- r2.logitmfx #' @export r2.probitmfx <- r2.logitmfx #' @export r2.negbinirr <- r2.logitmfx #' @export r2.negbinmfx <- r2.logitmfx #' @export r2.betamfx <- r2.logitmfx #' @export r2.betaor <- r2.logitmfx #' @export r2.model_fit <- r2.logitmfx # Cox & Snell R2 --------------------- #' @export r2.BBreg <- function(model, ...) { out <- list(R2_CoxSnell = r2_coxsnell(model)) names(out$R2_CoxSnell) <- "Cox & Snell's R2" class(out) <- c("r2_pseudo", class(out)) out } #' @export r2.crch <- r2.BBreg #' @export r2.bayesx <- r2.BBreg # Nagelkerke R2 ---------------------- #' @export r2.censReg <- function(model, ...) { out <- list(R2_Nagelkerke = r2_nagelkerke(model)) names(out$R2_Nagelkerke) <- "Nagelkerke's R2" class(out) <- c("r2_pseudo", class(out)) out } #' @export r2.cpglm <- r2.censReg #' @export r2.serp <- r2.censReg #' @export r2.clm <- r2.censReg #' @export r2.clm2 <- r2.censReg #' @export r2.coxph <- r2.censReg #' @export r2.polr <- r2.censReg #' @export r2.survreg <- r2.censReg #' @export r2.truncreg <- r2.censReg #' @export r2.bracl <- r2.censReg #' @export r2.brmultinom <- r2.censReg #' @export r2.bife <- r2.censReg #' @export r2.mclogit <- function(model, ...) { r2_nagelkerke(model) } #' @export r2.mblogit <- function(model, ...) { r2_nagelkerke(model) } # McFadden ---------------------- #' @export r2.multinom <- function(model, ...) { out <- r2_mcfadden(model) class(out) <- c("r2_pseudo", class(out)) out } #' @export r2.mlogit <- r2.multinom # Zeroinflated R2 ------------------ #' @export r2.hurdle <- function(model, ...) { r2_zeroinflated(model) } #' @export r2.zerotrunc <- r2.hurdle #' @export r2.zeroinfl <- r2.hurdle # Nakagawa R2 ---------------------- #' @rdname r2 #' @export r2.merMod <- function(model, ci = NULL, tolerance = 1e-5, ...) { r2_nakagawa(model, ci = ci, tolerance = tolerance, ...) } #' @export r2.cpglmm <- r2.merMod #' @export r2.glmmadmb <- r2.merMod #' @export r2.lme <- r2.merMod #' @export r2.clmm <- r2.merMod #' @export r2.mixed <- r2.merMod #' @export r2.MixMod <- r2.merMod #' @export r2.rlmerMod <- r2.merMod #' @export r2.glmmTMB <- function(model, ci = NULL, tolerance = 1e-5, verbose = TRUE, ...) { # most models are mixed models if (insight::is_mixed_model(model)) { return(r2_nakagawa(model, ci = ci, tolerance = tolerance, ...)) } else { if (!is.null(ci) && !is.na(ci)) { return(.r2_ci(model, ci = ci, ...)) } # calculate r2 for non-mixed glmmTMB models here ------------------------- info <- insight::model_info(model, verbose = FALSE) matrix_response <- grepl("cbind", insight::find_response(model), fixed = TRUE) if (info$is_linear) { # for linear models, use the manual calculation out <- .safe(.r2_lm_manual(model)) } else if (info$is_logit && info$is_bernoulli) { # logistic regression with binary outcome out <- list(R2_Tjur = r2_tjur(model, model_info = info, ...)) attr(out, "model_type") <- "Logistic" names(out$R2_Tjur) <- "Tjur's R2" class(out) <- c("r2_pseudo", class(out)) } else if (info$is_betabinomial) { # currently, beta-binomial models without proportion response are not supported if (matrix_response) { if (verbose) { insight::format_warning("Can't calculate accurate R2 for beta-binomial models with matrix-response formulation.") } out <- NULL } else { # betabinomial default to mcfadden, see pscl:::pR2Work out <- r2_mcfadden(model) } } else if (info$is_binomial && !info$is_bernoulli) { # currently, non-bernoulli binomial models are not supported if (verbose) { insight::format_warning("Can't calculate accurate R2 for binomial models that are not Bernoulli models.") } out <- NULL } else if ((info$is_poisson && !info$is_zero_inflated) || info$is_exponential) { # Poisson-regression or Gamma uses Nagelkerke's R2 out <- list(R2_Nagelkerke = r2_nagelkerke(model, ...)) names(out$R2_Nagelkerke) <- "Nagelkerke's R2" attr(out, "model_type") <- "Generalized Linear" class(out) <- c("r2_pseudo", class(out)) } else if (info$is_zero_inflated) { # zero-inflated models use the default method out <- r2_zeroinflated(model) } else if (info$is_orderedbeta) { # ordered-beta-regression out <- r2_ferrari(model, correct_bounds = TRUE) } else if (info$is_beta) { # beta-regression out <- r2_ferrari(model) } else { insight::format_error(paste0( "`r2()` does not support models of class `glmmTMB` without random effects and from ", info$family, "-family with ", info$link_function, "-link-function." )) } } out } #' @export r2.wbm <- function(model, tolerance = 1e-5, ...) { out <- r2_nakagawa(model, tolerance = tolerance) if (is.null(out) || is.na(out)) { s <- summary(model) r2_marginal <- s$mod_info_list$pR2_fe r2_conditional <- s$mod_info_list$pR2_total names(r2_conditional) <- "Conditional R2" names(r2_marginal) <- "Marginal R2" out <- list( R2_conditional = r2_conditional, R2_marginal = r2_marginal ) attr(out, "model_type") <- "Fixed Effects" class(out) <- "r2_nakagawa" } out } #' @export r2.sem <- function(model, ...) { r2_conditional <- model$r2c r2_marginal <- model$r2m names(r2_conditional) <- "Conditional R2" names(r2_marginal) <- "Marginal R2" structure( class = "r2_nakagawa", list( R2_conditional = r2_conditional, R2_marginal = r2_marginal ) ) } # Bayes R2 ------------------------ #' @export r2.brmsfit <- function(model, ...) { r2_bayes(model, ...) } #' @export r2.stanreg <- r2.brmsfit #' @export r2.BFBayesFactor <- r2.brmsfit # Other methods ------------------------------ #' @export r2.gam <- function(model, ...) { # gamlss inherits from gam, and summary.gamlss prints results automatically printout <- utils::capture.output(s <- summary(model)) # nolint if (is.null(s$r.sq)) { NextMethod() } else { list(R2 = c(`Adjusted R2` = s$r.sq)) } } #' @export r2.scam <- r2.gam #' @export r2.betareg <- function(model, ...) { out <- list(R2 = c(`Pseudo R2` = model$pseudo.r.squared)) attr(out, "model_type") <- "Beta" class(out) <- c("r2_generic", class(out)) out } #' @export r2.rma <- function(model, ...) { s <- summary(model) if (is.null(s$R2)) { return(NULL) } out <- list(R2 = s$R2 / 100) attr(out, "model_type") <- "Meta-Analysis" structure(class = "r2_generic", out) } #' @export r2.feis <- function(model, ...) { out <- list( R2 = c(R2 = model$r2), R2_adjusted = c(`adjusted R2` = model$adj.r2) ) attr(out, "model_type") <- "Fixed Effects Individual Slope" structure(class = "r2_generic", out) } #' @export r2.fixest <- function(model, ...) { insight::check_if_installed("fixest") r2 <- fixest::r2(model) out_normal <- insight::compact_list(list( R2 = r2["r2"], R2_adjusted = r2["ar2"], R2_within = r2["wr2"], R2_within_adjusted = r2["war2"] ), remove_na = TRUE) out_pseudo <- insight::compact_list(list( R2 = r2["pr2"], R2_adjusted = r2["apr2"], R2_within = r2["wpr2"], R2_within_adjusted = r2["wapr2"] ), remove_na = TRUE) if (length(out_normal)) { out <- out_normal } else { out <- out_pseudo } attr(out, "model_type") <- "Fixed Effects" structure(class = "r2_generic", out) } #' @export r2.fixest_multi <- function(model, ...) { lapply(model, r2.fixest) } #' @export r2.oohbchoice <- function(model, ...) { NULL } #' @export r2.felm <- function(model, ...) { model_summary <- summary(model) out <- list( R2 = c(R2 = model_summary$r2), R2_adjusted = c(`adjusted R2` = model_summary$r2adj) ) attr(out, "model_type") <- "Fixed Effects" structure(class = "r2_generic", out) } #' @export r2.iv_robust <- function(model, ...) { out <- list( R2 = c(R2 = model$r.squared), R2_adjusted = c(`adjusted R2` = model$adj.r.squared) ) attr(out, "model_type") <- "Two-Stage Least Squares Instrumental-Variable" structure(class = "r2_generic", out) } #' @export r2.ivreg <- function(model, ...) { model_summary <- summary(model) out <- list( R2 = c(R2 = model_summary$r.squared), R2_adjusted = c(`adjusted R2` = model_summary$adj.r.squared) ) attr(out, "model_type") <- "Instrumental-Variable" structure(class = "r2_generic", out) } #' @export r2.bigglm <- function(model, ...) { out <- list(R2_CoxSnell = summary(model)$rsq) names(out$R2_CoxSnell) <- "Cox & Snell's R2" class(out) <- c("r2_pseudo", class(out)) out } #' @export r2.biglm <- function(model, ...) { df.int <- as.numeric(insight::has_intercept(model)) n <- suppressWarnings(insight::n_obs(model)) rsq <- summary(model)$rsq adj.rsq <- 1 - (1 - rsq) * ((n - df.int) / model$df.resid) out <- list( R2 = rsq, R2_adjusted = adj.rsq ) names(out$R2) <- "R2" names(out$R2_adjusted) <- "adjusted R2" attr(out, "model_type") <- "Linear" structure(class = "r2_generic", out) } #' @export r2.lmrob <- function(model, ...) { model_summary <- summary(model) out <- list( R2 = c(R2 = model_summary$r.squared), R2_adjusted = c(`adjusted R2` = model_summary$adj.r.squared) ) attr(out, "model_type") <- "Robust Linear" structure(class = "r2_generic", out) } #' @export r2.complmrob <- r2.lmrob #' @export r2.mmclogit <- function(model, ...) { list(R2 = NA) } #' @export r2.Arima <- function(model, ...) { if (requireNamespace("forecast", quietly = TRUE)) { list(R2 = stats::cor(stats::fitted(model), insight::get_data(model, verbose = FALSE))^2) } else { list(R2 = NA) } } #' @export r2.plm <- function(model, ...) { model_summary <- summary(model) out <- list( R2 = c(R2 = model_summary$r.squared[1]), R2_adjusted = c(`adjusted R2` = model_summary$r.squared[2]) ) attr(out, "model_type") <- "Panel Data" structure(class = "r2_generic", out) } #' @export r2.selection <- function(model, ...) { model_summary <- summary(model) if (is.null(model_summary$rSquared)) { return(NULL) } out <- list( R2 = c(R2 = model_summary$rSquared$R2), R2_adjusted = c(`adjusted R2` = model_summary$rSquared$R2adj) ) attr(out, "model_type") <- "Tobit 2" structure(class = "r2_generic", out) } #' @export r2.svyglm <- function(model, ...) { rsq <- (model$null.deviance - model$deviance) / model$null.deviance rsq.adjust <- 1 - ((1 - rsq) * (model$df.null / model$df.residual)) out <- list( R2 = c(R2 = rsq), R2_adjusted = c(`adjusted R2` = rsq.adjust) ) attr(out, "model_type") <- "Survey" structure(class = "r2_generic", out) } #' @export r2.vglm <- function(model, ...) { out <- list(R2_McKelvey = r2_mckelvey(model)) names(out$R2_McKelvey) <- "McKelvey's R2" class(out) <- c("r2_pseudo", class(out)) out } #' @export r2.vgam <- r2.vglm #' @export r2.DirichletRegModel <- function(model, ...) { out <- list(R2_Nagelkerke = r2_nagelkerke(model)) names(out$R2_Nagelkerke) <- "Nagelkerke's R2" class(out) <- c("r2_pseudo", class(out)) out } # helper ------------------- .check_r2_ci_args <- function(ci = NULL, ci_method = "bootstrap", valid_ci_method = NULL, verbose = TRUE) { if (!is.null(ci) && !is.na(ci) && !is.null(valid_ci_method) && !ci_method %in% valid_ci_method) { if (verbose) { insight::format_warning( paste0("Method `", ci_method, "` to compute confidence intervals for R2 not supported.") ) } return(NULL) } ci } .r2_lm_manual <- function(model) { w <- insight::get_weights(model, verbose = FALSE) r <- stats::residuals(model) f <- stats::fitted(model) n <- length(r) rdf <- .safe(stats::df.residual(model)) df_int <- .safe(as.numeric(insight::has_intercept(model))) if (insight::has_intercept(model)) { if (is.null(w)) { mss <- sum((f - mean(f))^2) } else { m <- sum(w * f / sum(w)) mss <- sum(w * (f - m)^2) } } else if (is.null(w)) { mss <- sum(f^2) } else { mss <- sum(w * f^2) } if (is.null(w)) { rss <- sum(r^2) } else { rss <- sum(w * r^2) } r_squared <- mss / (mss + rss) if (is.null(df_int) || is.null(rdf)) { adj_r2 <- NULL } else { adj_r2 <- 1 - (1 - r_squared) * ((n - df_int) / rdf) } out <- list(R2 = r_squared, R2_adjusted = adj_r2) names(out$R2) <- "R2" names(out$R2_adjusted) <- "adjusted R2" attr(out, "model_type") <- "Linear" structure(class = "r2_generic", out) } performance/R/test_vuong.R0000644000176200001440000002051214736731423015306 0ustar liggesusers#' @rdname test_performance #' @export test_vuong <- function(..., verbose = TRUE) { UseMethod("test_vuong") } #' @export test_vuong.default <- function(..., reference = 1, verbose = TRUE) { # Attribute class to list and get names from the global environment my_objects <- insight::ellipsis_info(..., only_models = TRUE) # validation checks (will throw error if non-valid objects) my_objects <- .test_performance_checks(my_objects, verbose = verbose) # ensure proper object names my_objects <- .check_objectnames(my_objects, sapply(match.call(expand.dots = FALSE)[["..."]], as.character)) # If a suitable class is found, run the more specific method on it if (inherits(my_objects, c("ListNestedRegressions", "ListNonNestedRegressions", "ListLavaan"))) { test_vuong(my_objects, reference = reference) } else { insight::format_error("The models cannot be compared for some reason :/") } } # TODO: Add a nice printing method with some interpretation (see nonnest2's output) #' @export test_vuong.ListNestedRegressions <- function(objects, ...) { .test_vuong(objects, nested = TRUE, reference = NULL) } #' @export test_vuong.ListNonNestedRegressions <- function(objects, reference = 1, ...) { .test_vuong(objects, nested = FALSE, reference = reference) } # ------------------------------------------------------------------------- # Utils ------------------------------------------------------------------- # ------------------------------------------------------------------------- # The code below is adapted from nonnest2: https://github.com/cran/nonnest2/blob/master/R/vuongtest.R # All credits go to its author # Testing snippets before each function were added for quick testing, but can be removed later # TODO: Get rid of dependencies. Currently the functions require: # - sandwich::estfun() # - CompQuadForm::imhof() .test_vuong <- function(objects, nested = FALSE, reference = NULL, ...) { out <- data.frame(Omega2 = NA, p_Omega2 = NA, LR = NA, p_LR = NA, stringsAsFactors = FALSE) for (i in 2:length(objects)) { if (is.null(reference)) { ref <- objects[[i - 1]] } else { ref <- objects[[reference]] } rez <- .test_vuong_pairs(ref, objects[[i]], nested = nested, adj = "none") out <- rbind( out, data.frame( Omega2 = rez$Omega2, p_Omega2 = rez$p_Omega2, LR = rez$LRTstat, p_LR = rez$p_LRT, stringsAsFactors = FALSE ) ) } out <- cbind(.test_performance_init(objects), out) attr(out, "is_nested") <- nested attr(out, "reference") <- reference class(out) <- c("test_performance", class(out)) out } # Vuong test for two models ----------------------------------------------- # ------------------------------------------------------------------------- # m1 <- lm(mpg ~ disp, data=mtcars) # m2 <- lm(mpg ~ drat, data=mtcars) # ref <- nonnest2::vuongtest(m1, m2, nested=FALSE) # rez <- .test_vuong(m1, m2, nested=FALSE) # all(ref$omega == rez$Omega2) # ref$p_omega == rez$p_Omega2 # ref$LRTstat == rez$LRTstat # # m1 <- lm(mpg ~ disp, data=mtcars) # m2 <- lm(mpg ~ disp + drat, data=mtcars) # object1 <- m1; object2 <- m2 # ref <- nonnest2::vuongtest(m1, m2, nested=TRUE) # rez <- .test_vuong(m1, m2, nested=TRUE) # all(ref$omega == rez$Omega2) # ref$p_omega == rez$p_Omega2 # ref$LRTstat == rez$LRTstat # # ref <- nonnest2::vuongtest(m2, m1, nested=TRUE) # rez <- .test_vuong(m2, m1, nested=TRUE) # all(ref$omega == rez$Omega2) # ref$p_omega == rez$p_Omega2 # ref$LRTstat == rez$LRTstat .test_vuong_pairs <- function(object1, object2, nested = FALSE, adj = "none") { insight::check_if_installed("CompQuadForm") # If nested==TRUE, find the full model and reverse if necessary if (nested) { dfs <- c(insight::get_df(object1, type = "residual"), insight::get_df(object2), type = "residual") if (order(dfs)[1] == 2) { temp <- object2 object2 <- object1 object1 <- temp } } # Get individual log-likelihoods llA <- attributes(insight::get_loglikelihood(object1))$per_obs llB <- attributes(insight::get_loglikelihood(object2))$per_obs # DISTINGUISABILITY TEST -------- # Eq (4.2) n <- insight::n_obs(object1) omega_hat_2 <- (n - 1) / n * stats::var(llA - llB, na.rm = TRUE) # Get p-value of weighted chi-square dist lamstar <- .test_vuong_lambda(object1, object2) # Note: dr package requires non-negative weights, which does not help when nested==TRUE # tmp <- dr::dr.pvalue(lamstar^2, n * omega_hat_2) # pOmega <- tmp[[4]] p <- suppressWarnings(CompQuadForm::imhof(n * omega_hat_2, lamstar^2)$Qq) # ROBUST LRTEST ----------- # Calculate likelihood ratio; Eq (6.4) lr <- sum(llA - llB, na.rm = TRUE) # Adjustments to likelihood ratio if (adj != "none") { # FIXME lavaan equality constraints; use df instead? nparA <- insight::n_parameters(object1, effects = "fixed") nparB <- insight::n_parameters(object2, effects = "fixed") if (adj == "aic") { lr <- lr - (nparA - nparB) } if (adj == "bic") { lr <- lr - (nparA - nparB) * log(n) / 2 } } # Null distribution and test stat depends on nested if (nested) { teststat <- 2 * lr p_LRTA <- suppressWarnings(CompQuadForm::imhof(teststat, -lamstar)[[1]]) p_LRTB <- NA } else { teststat <- (1 / sqrt(n)) * lr / sqrt(omega_hat_2) ## Two 1-tailed p-values from a normal: p_LRTA <- stats::pnorm(teststat, lower.tail = FALSE) p_LRTB <- stats::pnorm(teststat) } rval <- list( Omega2 = omega_hat_2, p_Omega2 = p, LRTstat = teststat, p_LRT = min(c(p_LRTA, p_LRTB), na.rm = TRUE) ) rval } # Compute lambda (Eq 3.6) ------------------------------------------------- # ------------------------------------------------------------------------- # m1 <- lm(Sepal.Length ~ Petal.Width, data=iris) # m2 <- lm(Sepal.Length ~ Sepal.Width, data=iris) # ref <- nonnest2:::calcLambda(m1, m2, n=150, score1=NULL, score2=NULL, vc1=stats::vcov, vc2=stats::vcov) # rez <- .test_vuong_lambda(m1, m2) # all(ref == rez) .test_vuong_lambda <- function(model1, model2) { # Compute lambda (Eq 3.6) # Get AB AB1 <- .test_vuong_AB(model1) AB2 <- .test_vuong_AB(model2) # Eq (2.7) Bc <- crossprod(AB1$sc, AB2$sc) / AB1$n W <- cbind( rbind( -AB1$B %*% chol2inv(chol(AB1$A)), t(Bc) %*% chol2inv(chol(AB1$A)) ), rbind( -Bc %*% chol2inv(chol(AB2$A)), AB2$B %*% chol2inv(chol(AB2$A)) ) ) lamstar <- eigen(W, only.values = TRUE)$values # Discard imaginary part, as it only occurs for tiny eigenvalues? Re(lamstar) } # Compute AB (Eq 2.1 and 2.2) --------------------------------------------- # ------------------------------------------------------------------------- # m <- lm(Sepal.Length ~ Petal.Width * Species, data=iris) # ref <- nonnest2:::calcAB(m, n=150, scfun = NULL, vc = stats::vcov) # rez <- .test_vuong_AB(m) # all(ref$A == rez$A) # all(ref$B == rez$B) # all(ref$sc == rez$sc) # # structure <- " visual =~ x1 + x2 + x3 # textual =~ x4 + x5 + x6 # speed =~ x7 + x8 + x9 # # visual ~~ textual + speed " # model <- lavaan::sem(structure, data = lavaan::HolzingerSwineford1939) # ref <- nonnest2:::calcAB(model, n=insight::n_obs(model), scfun = NULL, vc = lavaan::vcov) # rez <- .test_vuong_AB(model) # all(ref$A == rez$A) # all(ref$B == rez$B) # all(ref$sc == rez$sc) .test_vuong_AB <- function(model) { # A, B as defined in Vuong Eq (2.1) and (2.2) n <- insight::n_obs(model) # Get A (Eq 2.1) if (inherits(model, "lavaan")) { insight::check_if_installed("lavaan") covmat <- lavaan::vcov(model) # model@vcov$vcov duplicates <- duplicated(colnames(covmat)) covmat <- n * covmat[!duplicates, !duplicates] scaling <- 1 } else { scaling <- insight::get_sigma(model, ci = NULL, verbose = FALSE)^2 if (is.null(scaling) || is.na(scaling)) scaling <- 1 covmat <- n * insight::get_varcov(model, component = "conditional") } A <- chol2inv(chol(covmat)) # Get B (Eq 2.2) sc <- (1 / scaling) * .get_gradients(model) sc.cp <- crossprod(sc) / n B <- matrix(sc.cp, nrow(A), nrow(A)) list(A = A, B = B, sc = sc, n = n) } performance/R/r2_xu.R0000644000176200001440000000206614406575225014154 0ustar liggesusers#' @title Xu' R2 (Omega-squared) #' @name r2_xu #' #' @description Calculates Xu' Omega-squared value, a simple R2 equivalent for #' linear mixed models. #' #' @param model A linear (mixed) model. #' #' @return The R2 value. #' #' @details `r2_xu()` is a crude measure for the explained variance from #' linear (mixed) effects models, which is originally denoted as #' \ifelse{html}{\out{Ω2}}{\eqn{\Omega^2}}. #' #' @references #' Xu, R. (2003). Measuring explained variation in linear mixed effects models. #' Statistics in Medicine, 22(22), 3527–3541. \doi{10.1002/sim.1572} #' #' @examples #' model <- lm(Sepal.Length ~ Petal.Length + Species, data = iris) #' r2_xu(model) #' @export r2_xu <- function(model) { mi <- insight::model_info(model) if (!mi$is_linear) { insight::format_error("Xu's R2 is only applicable for linear models.") } .r2_xu <- 1 - stats::var(stats::residuals(model, verbose = FALSE)) / stats::var(insight::get_response(model, verbose = FALSE)) names(.r2_xu) <- "Xu's R2" .r2_xu } performance/R/model_performance.kmeans.R0000644000176200001440000000134414272453120020037 0ustar liggesusers#' Model summary for k-means clustering #' #' @param model Object of type `kmeans`. #' @inheritParams model_performance.lm #' #' @examples #' # a 2-dimensional example #' x <- rbind( #' matrix(rnorm(100, sd = 0.3), ncol = 2), #' matrix(rnorm(100, mean = 1, sd = 0.3), ncol = 2) #' ) #' colnames(x) <- c("x", "y") #' model <- kmeans(x, 2) #' model_performance(model) #' @export model_performance.kmeans <- function(model, verbose = TRUE, ...) { out <- as.data.frame(model[c("totss", "tot.withinss", "betweenss", "iter")]) colnames(out) <- c("Sum_Squares_Total", "Sum_Squares_Within", "Sum_Squares_Between", "Iterations") row.names(out) <- NULL class(out) <- c("performance_model", class(out)) out } performance/R/display.R0000644000176200001440000000343314620351763014556 0ustar liggesusers#' @title Print tables in different output formats #' @name display.performance_model #' #' @description Prints tables (i.e. data frame) in different output formats. #' `print_md()` is a alias for `display(format = "markdown")`. #' #' @param object,x An object returned by [`model_performance()`] or #' or [`compare_performance()`]. #' or its summary. #' @param format String, indicating the output format. Currently, only #' `"markdown"` is supported. #' @param layout Table layout (can be either `"horizontal"` or `"vertical"`). #' @param digits Number of decimal places. #' @param caption Table caption as string. If `NULL`, no table caption is printed. #' @param ... Currently not used. #' #' @return A character vector. If `format = "markdown"`, the return value #' will be a character vector in markdown-table format. #' #' @details `display()` is useful when the table-output from functions, #' which is usually printed as formatted text-table to console, should #' be formatted for pretty table-rendering in markdown documents, or if #' knitted from rmarkdown to PDF or Word files. See #' [vignette](https://easystats.github.io/parameters/articles/model_parameters_formatting.html) #' for examples. #' #' @examples #' model <- lm(mpg ~ wt + cyl, data = mtcars) #' mp <- model_performance(model) #' display(mp) #' @export display.performance_model <- function(object, format = "markdown", digits = 2, caption = NULL, ...) { if (identical(format, "html")) { print_html(x = object, digits = digits, caption = caption, ...) } else { print_md(x = object, digits = digits, caption = caption, ...) } } #' @export display.compare_performance <- display.performance_model #' @export display.check_itemscale <- display.performance_model performance/R/performance_pcp.R0000644000176200001440000001513014736731423016254 0ustar liggesusers#' @title Percentage of Correct Predictions #' @name performance_pcp #' #' @description Percentage of correct predictions (PCP) for models #' with binary outcome. #' #' @param model Model with binary outcome. #' @param ci The level of the confidence interval. #' @param method Name of the method to calculate the PCP (see 'Details'). #' Default is `"Herron"`. May be abbreviated. #' @inheritParams model_performance.lm #' #' @return A list with several elements: the percentage of correct predictions #' of the full and the null model, their confidence intervals, as well as the #' chi-squared and p-value from the Likelihood-Ratio-Test between the full and #' null model. #' #' @details `method = "Gelman-Hill"` (or `"gelman_hill"`) computes the #' PCP based on the proposal from _Gelman and Hill 2017, 99_, which is #' defined as the proportion of cases for which the deterministic prediction #' is wrong, i.e. the proportion where the predicted probability is above 0.5, #' although y=0 (and vice versa) (see also _Herron 1999, 90_). #' #' `method = "Herron"` (or `"herron"`) computes a modified version #' of the PCP (_Herron 1999, 90-92_), which is the sum of predicted #' probabilities, where y=1, plus the sum of 1 - predicted probabilities, #' where y=0, divided by the number of observations. This approach is said to #' be more accurate. #' #' The PCP ranges from 0 to 1, where values closer to 1 mean that the model #' predicts the outcome better than models with an PCP closer to 0. In general, #' the PCP should be above 0.5 (i.e. 50\%), the closer to one, the better. #' Furthermore, the PCP of the full model should be considerably above #' the null model's PCP. #' #' The likelihood-ratio test indicates whether the model has a significantly #' better fit than the null-model (in such cases, p < 0.05). #' #' #' @references #' - Herron, M. (1999). Postestimation Uncertainty in Limited Dependent #' Variable Models. Political Analysis, 8, 83–98. #' - Gelman, A., and Hill, J. (2007). Data analysis using regression and #' multilevel/hierarchical models. Cambridge; New York: Cambridge University #' Press, 99. #' #' @examples #' data(mtcars) #' m <- glm(formula = vs ~ hp + wt, family = binomial, data = mtcars) #' performance_pcp(m) #' performance_pcp(m, method = "Gelman-Hill") #' @export performance_pcp <- function(model, ci = 0.95, method = "Herron", verbose = TRUE) { # fix special cases if (inherits(model, c("model_fit", "logitor", "logitmfx", "probitmfx"))) { model <- model$fit } method <- match.arg(method, choices = c("Herron", "Gelman-Hill", "herron", "gelman_hill")) mi <- insight::model_info(model, verbose = verbose) if (!mi$is_binomial) { insight::format_error("`performance_pcp()` only works for models with binary outcome.") } resp <- insight::get_response(model, verbose = verbose) if (!is.null(ncol(resp)) && ncol(resp) > 1) { if (verbose) insight::print_color("`performance_pcp()` only works for models with binary response values.\n", "red") return(NULL) } m0 <- suppressWarnings(stats::glm( formula = stats::as.formula(sprintf("%s ~ 1", insight::find_response(model))), family = stats::binomial(link = "logit"), data = insight::get_data(model, verbose = FALSE), weights = stats::weights(model) )) .performance_pcp(model, m0, ci, method = method, verbose = verbose) } # methods ---------------------------------- #' @export print.performance_pcp <- function(x, digits = 2, ...) { insight::print_color("# Percentage of Correct Predictions from Logistic Regression Model\n\n", "blue") cat(sprintf(" Full model: %.2f%% [%.2f%% - %.2f%%]\n", 100 * x$pcp_model, 100 * x$model_ci_low, 100 * x$model_ci_high)) cat(sprintf(" Null model: %.2f%% [%.2f%% - %.2f%%]\n", 100 * x$pcp_m0, 100 * x$null_ci_low, 100 * x$null_ci_high)) insight::print_color("\n# Likelihood-Ratio-Test\n\n", "blue") v1 <- sprintf("%.3f", x$lrt_chisq) v2 <- sprintf("%.3f", x$lrt_df_error) v3 <- sprintf("%.3f", x$lrt_p) space <- max(nchar(c(v1, v2))) cat(sprintf(" Chi-squared: %*s\n", space, v1)) cat(sprintf(" df: %*s\n", space, v2)) cat(sprintf(" p-value: %*s\n\n", space, v3)) invisible(x) } #' @export as.data.frame.performance_pcp <- function(x, row.names = NULL, ...) { data.frame( Model = c("full", "null"), Estimate = c(x$pcp_model, x$pcp_m0), CI_low = c(x$model_ci_low, x$null_ci_low), CI_high = c(x$model_ci_high, x$null_ci_high), Chisq = c(NA, x$lrt_chisq), df_error = c(NA, x$lrt_df_error), p = c(NA, x$lrt_p), stringsAsFactors = FALSE, row.names = row.names, ... ) } # utilities -------------------------------------- .performance_pcp <- function(model, m0, ci, method, verbose = TRUE) { y_full <- .recode_to_zero(insight::get_response(model, verbose = verbose)) y_null <- .recode_to_zero(insight::get_response(m0, verbose = verbose)) n_full <- suppressWarnings(insight::n_obs(model)) n_null <- suppressWarnings(insight::n_obs(m0)) pr_full <- stats::predict(model, type = "response") pr_null <- stats::predict(m0, type = "response") if (tolower(method) == "herron") { pcp_full <- (sum(1 - pr_full[y_full == 0]) + sum(pr_full[y_full == 1])) / n_full pcp_null <- (sum(1 - pr_null[y_null == 0]) + sum(pr_null[y_null == 1])) / n_null } else { pcp_full <- 1 - mean((pr_full > 0.5 & y_full == 0) | (pr_full <= 0.5 & y_full == 1)) pcp_null <- 1 - mean((pr_null > 0.5 & y_null == 0) | (pr_null <= 0.5 & y_null == 1)) } lrt.p <- 1 - stats::pchisq( q = model$null.deviance - model$deviance, df = model$df.null - model$df.residual, lower.tail = TRUE ) lrt.chisq <- 2 * abs(insight::get_loglikelihood(model, verbose = verbose) - insight::get_loglikelihood(m0, verbose = verbose)) structure( class = "performance_pcp", list( pcp_model = pcp_full, model_ci_low = pcp_full - stats::qnorm((1 + ci) / 2) * sqrt(pcp_full * (1 - pcp_full) / n_full), model_ci_high = pcp_full + stats::qnorm((1 + ci) / 2) * sqrt(pcp_full * (1 - pcp_full) / n_full), pcp_m0 = pcp_null, null_ci_low = pcp_null - stats::qnorm((1 + ci) / 2) * sqrt(pcp_null * (1 - pcp_null) / n_null), null_ci_high = pcp_null + stats::qnorm((1 + ci) / 2) * sqrt(pcp_null * (1 - pcp_null) / n_null), lrt_chisq = as.vector(lrt.chisq), lrt_df_error = model$df.null - model$df.residual, lrt_p = lrt.p ) ) } performance/R/looic.R0000644000176200001440000000470414736731423014223 0ustar liggesusers#' @title LOO-related Indices for Bayesian regressions. #' @name looic #' #' @description Compute LOOIC (leave-one-out cross-validation (LOO) information #' criterion) and ELPD (expected log predictive density) for Bayesian #' regressions. For LOOIC and ELPD, smaller and larger values are respectively #' indicative of a better fit. #' #' @param model A Bayesian regression model. #' @inheritParams model_performance.lm #' #' @return A list with four elements, the ELPD, LOOIC and their standard errors. #' #' @examplesIf require("rstanarm") #' \donttest{ #' model <- suppressWarnings(rstanarm::stan_glm( #' mpg ~ wt + cyl, #' data = mtcars, #' chains = 1, #' iter = 500, #' refresh = 0 #' )) #' looic(model) #' } #' @export looic <- function(model, verbose = TRUE) { insight::check_if_installed("loo") algorithm <- insight::find_algorithm(model) if (algorithm$algorithm != "sampling") { if (verbose) { insight::format_warning( "`looic()` only available for models fit using the 'sampling' algorithm." ) } return(NA) } res_loo <- tryCatch( { loo::loo(model) }, error = function(e) { if (inherits(e, c("simpleError", "error"))) { insight::print_color(e$message, "red") cat("\n") } NULL } ) loo_df <- res_loo$estimates if (is.null(loo_df)) { return(NULL) } out <- list( ELPD = loo_df["elpd_loo", "Estimate"], ELPD_SE = loo_df["elpd_loo", "SE"], LOOIC = loo_df["looic", "Estimate"], LOOIC_SE = loo_df["looic", "SE"] ) attr(out, "loo") <- res_loo[c("pointwise", "diagnostics")] # Leave p_loo as I am not sure it is an index of performance structure(class = "looic", out) } # methods -------------------------- #' @export as.data.frame.looic <- function(x, row.names = NULL, ...) { data.frame( ELPD = x$ELPD, ELPD_SE = x$ELPD_SE, LOOIC = x$LOOIC, LOOIC_SE = x$LOOIC_SE, stringsAsFactors = FALSE, row.names = row.names, ... ) } #' @export print.looic <- function(x, digits = 2, ...) { insight::print_color("# LOOIC and ELPD with Standard Error\n\n", "blue") out <- paste0( c( sprintf(" LOOIC: %.*f [%.*f]", digits, x$LOOIC, digits, x$LOOIC_SE), sprintf(" ELPD: %.*f [%.*f]", digits, x$ELPD, digits, x$ELPD_SE) ), collapse = "\n" ) cat(out) cat("\n") invisible(x) } performance/R/sysdata.rda0000644000176200001440000277330014616413200015125 0ustar liggesusersBZh91AY&SY0w( $ w$wmT` @@ $ P(@(P@@ (@(PPAT(((IT(PB)UJ)JXt`P  B/Tp@nutJ]Ԋ;@ (A@hh$PUPP*Ш@4 Ҋ(((nԔJJ$@ԍ`<$ % 4SѦ= OQb4=#4PzQjhmCF~S Ѧ##@ #iO4)FTG5 =@ꁠ6@IMT~AɵO4ީFjG4dML zh hh )$A0$joJh`@!M11FLFbi# R4FMO)MOF=4M=4L56&jmi=ii14 &Db f4Ɓ4z@)QMP@ 4@@ 8C>{ys=>?AGS?#~T}f~/|\fJivsTR7EЬV+W;gg}`WJ]+V]]"Yt]WTb.q=g;8Y=~gG=z~z.]viwvr\ r.wt) ,ztE˞O%~Rߗ``0`ONɓ&L1F#40Z9iF)ED& FQtttteFQVEyxz 1LS1L/_x^ׯ^SS/E^/^^^iEEAAAAAAwwv]ID44% CC ;4iFtttteGFˑrS%2S×.G'%5eYSRŋ8&d2@ɓ$dٟ}{z׭z8|G|_|GAt@FC `(9NS`0F`0`ς%9N_Ӱ``J.Eȸevh~^^S vR** D>OOOON:]OO$OOO]]]]*TTeبT*`Uuu y9+*8ZXVcX,Ef !H_߮ p.]\zY=g_?>_;|?=g=gTJ9,0adAQQNSN .]~_G%^%^APS\.) C ˗ _|Ϻ#ؽؽ~|G|^gg>y=>ľ#>#>#{a=~Y=g$t+׭ZB"շ`ba,wVիh~~Ù:N"O$OOOdd__DAAAAAAAA sa9e19crG#4eEDQTT4444% Cx]xbX^^^ŅGGEEEEDE^eFQtwH"Ղ BPЪ*TT*TU J],GGEXbaNRRR.]NдZ{)xz/Eח+.]Reh-N2i) bƚ bxbŋ#L2dɒ2F@2d2d2.J*jJ"*J*J#.\FQFh44g0tn7#a6Q_%mlB pz`%uuq\6lٳh Z @GÆBAGCB!PdbF,XF(bbbSSS&&!db5,2dɓ!F%52˗.)C\p]մttIDEEDQQQQQ=txAj-1qb d))bZlehVX`X!b,EłbB!xJJB-ENjEկ/^`01;wQP2 Vk(}{ǁ< ___^~W׿___^n+Jҵnܭlf]4: átfՅeeeRU%UUPU%UUPU*b*bx)ZV8nݻv۷n7lٰl6l6l6;7j5j5f͛6l𰚍FVZ­" ۶FWWaљYYXVeaUՕeIRTJT]UUUUUV&%eeeeaXVVbb4iѣAFQ\'T$?= +.*f٢ FKw/+/!9pÎ ؙa#n.H\d0ښV8 >pԳc: ^~!$w;vm1 &aqRB 6"]Fcjjvf]/j;X˃xA/ ~sjCAUS*v@9Nƻ x Y?& ⯄ -V9I<LakcbӷzeLHMQy+IQ/1Ca"+ERh~ ҌPZvY^^ܳdupƩkU(WK$p2TIҩUE=t7"!ucFgG0k7n :z :dRer~Ve$w"g V0aeZ}i.Ġw Bs)l[4] _wOV2,:_ dgoj-3٠pĆ8/v:Mt_cF?5B=hَg:]Xekd6t<#m `A-YUVs 8c?/p*&-סe jL!KѷbsH84Y`묍TY-m=ٺJL:n#.q Y'MnUL ߱&8HC-Y3I2]4ͭ-,YUm؊ /T!՛-ݡcs%*R<ґJzb#<ϐ"A<΁1Z0GO_n~ZJjdGgz!x">)@ !7P-9ޘk "PoJI ͮaHG:TZ7yV5m@.1)똎_bWt}k҇adkm8T3@<@@CydRIt:[Pf{2`L T0 mNn^Φ MxCRɌYY.i&6NisVөuGAs1xs퇍ry8, *vnGE`tsvl@C+V:xL'r>KASU%& HP4ob2ư=)b0@g&\AqaHJrmI#/!lGgbR |ߘ/ie(jEDrfi%-CB0h)X^]/`zxҺ_q;Ov2 =TnKTf>vfl%mKPL+PM{ALDYa(d3]AD3C~Ɩ&A|^h/?zYTTZN踅 W5&wuCCKLYqrڥUǣ9 +fD{qmyd@!SD#=݃.(+9HnC&oZJ֣ɲ"څF9N η|7Z'K>u *GYpʘM, A1x>zKZ /1&oLoX=9cLi|=M7BR kGZO16B_F~n/H`0=6Ek *#G/C=gB(ʪ Ke"uEQ9(z>'Y~"WRNlksM{f`hѮ$xNVǮfr0[>%QՑgWQJ7دy`7q+ }JR5*X \QxxQ+ &15/Nm;GtT43,ϚS  P^KS0wt7Z8*1ޘ7A! *}.F$CҗA#֯Ml;P Y+9_lzLWLvVh[.qC+5\s*Jik?CD&>L,2=9g4-ȫ!9JSpv e 9彚Z%M@[z_ p؍H1OTu.jQ#8lMQ PqG&dHI1 0਌l *!XcpU} "2M,=_3E2"gFԁkwyB"@˃)β6#=>&k{.]D4} Pj⏑%H$ u[PZ~ ՃAw*PǰxT͹*jX0G6B#)CcCE5a9 &գݬŸzXX*2ɆɱBVWwhʣ8PFFb{@+ԍ7 8z+ƒ3rT8Ofhpۆrg1B%JyPq4r$CvIU,~Ί[2+aD{.6 "egHP!Kp< jK$P~ތ`b$HCve6?cjTOqcFҳk^J4)I,L %q_z|^FS{1(VG'a){\lZk )x |!Y?= A$'Qr;`#L{ %AH$J29HH 52#(eB+ZjAs'wpݠY> `|g;.jӟC(b~ZbUAW/"9yU a`>'IBG73rJw{pH$W (etrLI&eUYԘ"dU[y 25G(\iꋀ߮& $:+)g%mTD.XH&~3eԚW 9.D ːmSbaB%,&n!P&t<wHMҞnIkRξ-<َo)`i~.YjtqIp HK)OY@Z膉9 hYXDd$ %")!0܍XFHY]ADإh_FE8ŴbKjOjh,-j.09=˕ %Yĕݑ*"Ꙁ۱A rtvK2+4E&sr'I?Y=pf¢"(/px>v4K}aBEAg|Ni٫]X{KPSZLDۅuylGHFqʊҿ.L}jTQ\旭}zi~W9SkLҲV>FҘ n0)w+֋̫y'DJ ۰,W0K[cX>HP@,) HQJ&_MRwKE(=QrOj'7O¾L#9:b&M"LT&|dF=ش2R렉в2Hk,֭(rtD1 izpVYg$hǁ CKTH֥y {DK|-! Mc68ߪxY&C-}^y^msф8BGwn弔g֣ ~Y`pUa(TZ69} "#U)vE1NؘvUCA\"pls{z;"AP|A|<<׾3C?<{zVk:UR>" u𴛧$MV,Kĺ\(|Lf:az{ܿI4/\ P2E/C<_*{~7T9hƏ Mz1o[MUf(ؾnꀚ;e܏BìL|zT먰j(FDv45j`U U E!S5M| gaEwecrC!~7ȓEWEGv|Pv~8@'LRC6jWr.Q:෢xSv:%|xoH6ɱX6x^d`DXȁuldb! /%Gm|MyQ#8+&@,rYZ2:ϼ~~/)xx" X FC777oE{=6 rQ]>ދDݾHW;;G5d%||1>qiiGi4>O==ju3w8C_uM6fv&lW+ZkNQ5i$$$$5ZQ9\ ֚/ zzz{_1\jz_$WRַ[cQyG)bEtt<|:YFiCC!ŚJj*UwȄ X;wXUt]) KWԬYҬh^4;wF%ޣQEECkkjZV V[uu_Ƕ|c>S~LyGGGjcVĈ{_5ZNSooWn[ԤӚsOkkiiSJiM)ieKWϟ>|666666|'GzGrG9@P|}?LL(hp 5l6 a\\PHHtkuJbzRRRR200`F7;`=<&HH9۰`Jܘ(r\\$"H]:tpn |wcڔj5ܛS׭qL\\]jZ['8o%q4;++++(JinQmM__6<:''cAaw><-Op.Ux DDR,؄DF,k&"![hP mK}gGkg!2xX-(S/rNQ@lʏ-4,\~J׭ĩ4hfSԊ9Dߥz=%{+Hޏd,Pb G/ q#Owҋ|Aڭ2\(oSF!`DUO )EMU`W%+كSaN⭜ lcn,rmңT"+R:OOcT,bU 2.fώ]l+̪G@nwE0f%R $rXcB]<~}+xcL-Q4]€zW AD=$h *.Jz@2U[AfU4s%u)pJw,#p |(`.b"6u< dž.7G-cGnAO (!lyX!\=s㏴{Ot7X^.ZUb IT-H> -:= y DQNy4,/2n.0'*O0؊<|.F%9`=O]Vd|Qs]*PGeC*3L ^#\Ǎ6 \،IJz2 PD0m׽!E7xL&xΌǖ=J@VҬ$4#+$KCk꾓0"y#+2S7bwlUv~n%F|L%l A mTBZ3M( YR)uO,ߕ4fłrrnW`0;yyipv@_X (zn'u2]dPrYk.kEq"kb;x8eHknZB- z>%|֚eC `UH'hnہ^H|r^.i~0iq>6D'ؚe23dz $T呥&o Ixy.f;jDi@"2V lL57VHdxmR^_97X 8Oo0vw:9EQc_Cƴ㶳z 7|F͗"{6 շgv@dM: puǚ8aksu4$~ F>`^F>ؖ H(?|6CWgJ(iNM4K]4JfmSVCw{Ĕat#S*.ͦBXطk$;{|M }#a~0Ҵv N'8DW--v2525wExwײGRu3pKn`aìB!"Yb:7ynOyR% 'b4!z3w`#"42@@fO-Hba20-Lfxg9D Ӳ`lLxB) /[P !ӠEgi^qk-.1oČ!H6@QTN`ʜ Ο?5jp5 /c͈ezξxkqxnz2DLëaa#W*ͭFg #G%Tp4QP‚Tw/a-6Fp̪V fo,T=M G}}2D@_H̜}0(r:t'/uTAW`9uUzQ :vxj޷qO\s%exREir1NNp$rl.7D`zUvXs0,zgs;'灭MoiPƙ~4%'R p͋d~y1hbP;J6 :2 % ŗrbg<͵ J\$I]pq(E2ye:k2Fp#f"Q4F-RƚD?3{HZwP.vm¶:;FhP VsɞLzxӯﯱ,f; NNJK+< 2keG٣4g2,Ĝ7|ޯWO{^׵?~ ?Ny~_s}H]\] :-&NOkdk+% BT=39g3Y|?3|/H)+[[GtָLLkw;W:33]NRjMNJJjkTjs=¢zT=,=gc= IBhm>FG=`$dvE.6 L||zfg٩1q5*h$VIvwo}||'0f7I': w{~))Mzʶ<ÙPTPP|k5))ccnw93;r||pUnplzQӫ++oof30z{7n2}/q9Y[wݞ}vRRSs[vve{y @WWaŜҊۛ͌#űdY}|]]MM iZ1QE14Z(CtspeO3fk|X4`}dAJR oFQit8gwx\] -Z[_LL|CsC}2DYxv7Qw4ƓIhmfΎ14fG5555mmž&G#i4N'23ุo/88j&iktSMqFL? k4'Ձy!Ӭq~?r3ʚ.g*jȸ4|ϙӭְ"Ȳ.../p~3q9\W.v3`qxkS3.8mz>MvccctNW+Mnr?0LO;G220##9G(qfCf33qqhrf f!:qzjk?I'̓D55mr \v3./-]&k_xWp򔿂rȿޤݥW# .׃!5L Wd@㺃o|_V/zݽO*eNơ0!X $t5{5m~#V|ƿ9fx_xQз īVhb%sjFd7|RA06 X&(E+œ]78MQ-Dqj ~l0-N{'c! mS &9;*xT]fT:Yv>rFy`uݚŞcRcwQ/ 5Z>F/؎8=,2*3 ˈ P)p2qLa2rc'(P6;wǰpⓎ@2_}">ְ)PaP=-v 6b{U/Olio# Ŕ@}}To V؀EB(EjoD#X&4Goh_6Lk.C3xP@P1-oq AϏզۅw<L%r lwt7tQ3P+(Pbd R`xPs) 3 uGrBfz"np ^ʌލQh)I,kC}-V#S/'V2.@dT“ulN_Y0{$l,}ꇖEU2p<#Wj۴ey΂1dBx!!-;"oA+trR~#ɻGS޳^oe_iF/nM% eVЮ 6U_mn߫YcvI@zߣ?KØ|?'%=)褤k'%`~I'ju9~G#z*+ӡǏaju= 6Ni:m6/ck<ùu 싋.ʗ0piOq8g%6ZYy o;eNkӷ0h{1GѦe0X^_kXUUUUzaXl>o^_qTR溜>c1f326mSSﻫGG{£'&>S2if2\8FO{{Pwlim9|sܳq:Q"X^׵HQIֹst9|Zkڞ{m {{AAeS 'mH;w3gwww7BB@8{dBFjk?wUߥGeWU}~wλwCu÷|aʳ"xmf(w #h ,&[N"i݁$2tWVŨ*1ٴcΑSenY0XҐ;頇h߃CPEj*R֛KVR^_jPaa􇊤ENRŗn46c{OGVb j#73͒ޭ/Cx"j@z௏9TyĥPJXFz ό˙c m+IRCnTI@ai]hUYt,='Pl#+AvQSQ1\ =?0,%*kzt"/mVY'9 Y\i% *09dxzr+ɞ[*YGy Vᨎ)~g~VP'ϔf XI,^La.TA?`xOѨ \*OQgJTm"dR?k(n8R "sLD0W3׷(%R^.^t8削y.8\B x[&Ьg=og D$ |^j16l= B62.)" :m@B\#Bz9IG6Bn-EhgypjRy'j\U 6Z#( Kyh.@(*E+⭴*eEp I[IcYo!@9dAaFE{t)&%7cçQ[*̧F"fytnK`Lqo Y|T=TjH;I&xù h_yxŏq3g\3gݖ8i7{vF[o赵|w:~*23 ot+9Ξa5Od\\~O'|Y]Vz_W7…yld#//G mf >K`;󷼋y^WitR3x<5u<#Wm_w/[[jzűRSEh?gxp=t٪Z_Gѡ}w|f24Z,|? ÙgFFo7{]/55EE|eDbǰa9YY~X-I|U*B;4}=x<^[-^G|]nv&,~o\ZZ|6NO]=(EH褫\5?N) :[)f[Gk 䰆%K "9OZWNU(Ї/ٮ CB l ֕ P! N#9d{p#1Vy{݆,zB[{**l.vEX5f)6|:jSY8 xM3 w\92y )2I+1m 7Pjdmۧ/mG4,Kp8P{;ޱ*#I?-iRlLКԁzM<<'*B  Ql΢E8V!zIJ( R#B"qR5xEf]W (ΎLd¨%hkRLa1-b&a}4+"8Ob)*$}`18׆w`gv~I% @^؅7Y-ٗ5u`iº=7,Q,2oq1;gdIü̚MVZ H) 4;8vȕd ~>p1@;'<1/q^`M5٩cPF6O~?|}Vv|Oq~m;IIY_?23YkOl54<~ _mVW<#w=+-͠iV,n&:+z'DlCo]w7^dۓɮR/g1uGGGGr/q4g5z̶[-udddgss54W~FmzRRXއz%{w}oO~oؿ}~npbȓ{!Yem,l}\3:}(00FMu!(.+́=~j/ıj-V6lxbf>W&#;8H n6(#X̪.lQD:(U 9{!՝kQQ aðI3Ub@PGSJ9iQQev©I1C]E )lU v(76[^19ZZ0P FTIȸ9pQV  |wXxN}euv̰!sH.0e,7TcP V$a/J,3 3YMV[;R?9]kߚ?Y?5k2in~xs?؟=/˓|]v^AjO?Isūdh<\i{ 23[1ooy9:KK;<ɳk.Ƃ66 ?~_ #?1`>augFD,퉮4aZ}fq|$VMO/5z/0"'^`lsL_6HP VoG)kl``Edէ+l) A[Эkǩ p5`Ijڿ% lX=uulk˜Ƙ6mZއZ43!VF`gB.o6] CUzMMLqyl{|ߒ;HHjMi!!UQ99-U|LOs3>~S+r_> ?c_ɌE3Ihf1 ?K;} Wkn沘?֮* + !ڙ큁[h]{@Z*AU9g˜]͞Y}]%iZsfoo?e/??}~ޟ~o]_/ /Zz՟ ss={?;VIv!/'3}wnSQCFO]cSѸ7ޜ~OWi~~_}G6e'+MJ xvdL?g+ovz6{>}w~gW/~{=k>>wOe4-Z?"OoqQg=u7ϙe_c?I{y}:wWCCmY/}O|xxG?W}{|ΉC @&g?Zfgp8[.Z/>=6ZoO:?;7/Zl/@k/ƞ߿=ww׿H}16`Y]/PUK;R A>h7o=,Q[ ۩pJ1\k'5?\(D Q4%JP%ZF/{D}zxOňzhP{1vA( < FIv bV^ ^}rJ2 ~yIV;Ԛ/ z}]W饤GlCY 3UY]!j;?R(Y{Q$WkJ秹3y07bzޙQ߆<ء3-wv^-%8"Q# &E9q0P1.nZɳh>^4l]Y ?K-)dOf:ɀH 96J )D!f486m'B&' /b*czsE_קu2$AT#3T5K" "G"A pT#&dAa&bP"Q88s:l28\qAJ2ԩD"̈ ̂Dư3KEqB11xGqn̪l@/u^!0gָDE\;ˋP!$08(٨);a)1WE"TS2bNλc)5l9b&bⱘ$[#g\53aɊ" G 0s~a V.O<56{ k1P\VH"qW \.'N\EAEhY5Y 8;`(W\84TS+$(Zfx$ ĨDfk(.D&drK4f.}{|⠱L fvcp\d\r86f. rl!vfkDݗQss\dϤ&jCU1'ndqpsGN9 mc#2!RjcreC\:P޾p&quʋ͇\^TbXN,#8ET̩R!Y/ttY Jzh""'*t&E#)X bZ$,bH"F"G\Ȓ{)Q5ȃq@1Ə'"㙭y(U@=*,ۑ( $#H(ZEMrnҌF!\UEb))ĩ1 +\r 0(cwv&LA-E9. s59W89lnk/$k]\Ԃw+G !m૭kKK$o9>R XzGs/xOf/\ SRl $9wfQLٞ!S>rb({ I"jɄH*8OdrB̨ce勻q!6:#dYdMhFR1d-R1x!&Tl9&ɭsj%qr:M|lԩ?S#xHȫvlȑ}8up"TEd 9塬G1Uy͸<ļqq ()!`$L d&Y)!0TbHE Qmݣ? MJ$Қ&W0_s`1FLAUEDvJlHTRU$Mf/- V&ϔ'Ԉ'o['k;fMsPQ戸3;nMB&Wpa,*1Mpd2 pdX R6N+jLNͱD\3,02\{CdkQ|^9M1$ɏd͇)d%m^Zkv2I=frDjqW+."\rLEdl̈ͽMq_YGrrEDTGd#BX,h"q+&CUu*X0Ґs"Efer1p횋fxZ⢢dԪXIDAQDjxٙ51IpE_⿛QD&V,"yHu۩YX1xv`*6Yr6fُR\qA1ʄsܕ)r S,8㙻{6N%3G);e;!I3Ďo M-MJl DuuECwIPX !UȮvsVe29 y=p0{a,;ɨjŪ*|N/1YlW1bX1r(&#S9$3Ʊa|LݙW:H9Ph(nTقPd<,d͖RqTIe0^\!s9r^Lfj(*EXT}#|WX]DuxRNr8M.= '[=55FH*Hܒ8)&O$Iٖ׏|"lQEQ7Ucp\*CvF>l2E&_d8-.}-17ŏ@uv ^ʵ$`@Ka$[n0FT=b;i _fN9ٯvMcMo&\ 2dAANAFCZ8Y5mBّU0[ jgݜV̲؋n{8~G_'4q쀫XDvd;6KD9qqF/ռ@ hh>IדNe\B1K+d&DUO}ξ_nzMY!uP%RF|̏ռ؅3aG]xpbV">v9ǯ9T쀵X̊YH#np缞õ;KX&TnGxJԂ&"^l5UQ+b̉'ʹm ͐P_vkQ y + Kܻj{rN .eYFW$V&B!E)a$썇z{GSzכ8Զ*+# F9s"brP&*@eE,a/UOP8uŨE_XI>TJU".D< e1]~9fm $ٕ FAXB9r!&(DfF9Ly&6r r%}VaTL~IR=ɑ "bswTmPf;nG) *9fkTxE:wlp3͗`;9h06_L39fjkdE\-kv쉳<]@oiP?E1sQ͕FY$+ȕy#xܢ+ι݋G=ݙ9"WٮF uc`s*:ծZvZDD/nwp:B_$\j7adz'dl3-_'\>^ˑ8M;-GcGTfW,H×2pgSEʇHEUr9lI"2L9Dqs`Z{9IڛZB1*?R0m^'a1&..m9X2DLL&ĝf/#ˊ۷c* $/%\Ycf$ R5$Xe W(8Fw5ELnux19[ϝܽIIIIݕ8KY3㒧,$[{旁$oݙ2<^g.wK/$|x*MOw]p6Z*v*TȱCƈɕ8MlOamňxӏ,]HCg%h s`IGQT:Y94ĉ-Ud qsL+d H{MVKZa=1[Ybsfظy!S3[&&1(kT(v7'mDWSn :_}ĒHlў$o{y7y'˘D"EK֕eJ*La;])')X;]s/q7o`Gh-ݜvH旼͇ߍxY ns|>ƨt džl.ll |J(%EmW')P|˶SH=; 29;Z:y=˖ڮC7Q !⯔g ƕy}fYcE;^J\PHLYA`9{6^`L(d~Iu++HK-cB >{0Qy۝D/[(,/BA0lΚpQ8 |!q AC]Ē_sv4J,yoFiPtkLP$ɪo?VHCW̼d)QkrwmI@TR   h:׶C-#S (Oj(}L=CR:42"cuI-WYƛƭ:k7W$?đ DL qW<?@ NLF2±+,\$cC5T25]HdG2BF8fWɰ\\*BxLjc,bNJk8LDQRl !d1sX98!P\PEE"u G"!.5X+@..Crbcp/'>1DS5"8W TS9vȕ9!EbGc%pr"bH28][ 26 յk!l,ܳ@k*"q3Qݛ+.%sd#n"(.j+6CLmEFm Ji #dB7Ey%d vɆjY+{iב k\#.dّ, z\*;Kr{@j8mD;&q9)JKWRI$C["k6E ԩpI ,"GYYH2*2d-j&oɐE~[Ek D5i6x\Vh5r2ιyipl$s4z-j \#v j qLUHx픭E2!Ďj\>;`uɴ7dEl.݃dS%Vb@;g{3spS.q+D@,9q⦷fLpTznjTaQL5HMr6d|ط*$x555*I'$fQpl`]K̑9q¤GH|6mH(.o!4wǎ㩞y sfDq\l%pkHo7SbxXb1N^#e۶Dؑ ks%,ֹNdT& G#'!l:fJk$1rH#ع4Yf5°QO,-sDEO&I:mQg^XҜLhe,THRʕRc֣93"XrP\ldQVCPvOg>^r6i)̈́u%u QzqJ{cY"ux8&*Ű3\sry6䁾2'jBe_\f:d~ s-!*AiV9+XcR6V+dYAEq~=o4N}mvGXnWXlr;g8OUnBB'\ι\\f\s붅b 1U'ۄv/nޡ\(Mb*+3sAy. 5 d;x7i s")Lm#,x]Ib63jBj^˝\ mF 8#ЭuIesYa'*vY!%O/./YN uU"D'`QjWd6NC*;3$N6M妽^dR+ݮÒq&flQ2)9koxgqMn/a\'Iam4'&drGl݇2.NE:L"aNrTZF[jLN7[!cɐN#(cyrђ2ٶ1HzGDk#lٸav#pdE̳6ysv0식LH#ǫ&T\m3qHV)XE^HD:Բ+Hx}I&]4E68ԌcMM2)``2+'vVv&Ǣe;(:8EOi,I 1;1,DkjZf :{zdzvE\!pLXHc#+:3a,XRa͟o_d\{{ijvA䜥pk!>hd~26dqr>@ AgΒ+xlI4zwri i':q%䨾R!-Ddm$턬^+VZ2a>]\3o(,q35;i&*䵍*ʷav:Cٹ5fv VI+,jw]$"AU'm҈,l,sN߽s&ӉT3 '&Qo2BT%c;7E>:uɟ3 &Gy؉#=uru*5B=rRNʵ1\J/>{9v7<epD!fN8N;;Y^#\S" ِݫ|Zy0<H#JCRY&q.uÜtVWDbAJ&zdîjklj K,{>;/-p\2}N>Jl"; "_E^!!:*O;n\4=qbQj]qǒ.JID\Rr_wj_wH+V9QqM $Lvd}N^ro^H uȉr#wug%kH|Jv1Cl#k V&dYca&2ksy!ȹO$̷Cӑ᫑[Yrj95ݑI6l`KyقvXi0+Ra0 `k\]5_dfSM(Y*D a\ԯ& _s<'#',_ͼTLd8ˮ0.,qOmc^r#yuBZ XD垏q:%݅SVx*weX9ǭ,1*%v"䋍,oB aUڼu* ຝk6 C=s;6XΤE7aXW56@P51b8 %Lrلӳ#q 9*ec38ƱQ^rl5HBIqMeveDH&K0RKYhrf1qH|clj,*@UrF+! 9dZQ@ղ6ƣɅɮvx*Q'˓g9lI.&[!lLGW!*w[Uōdo(UH Hp,Ųk^nu*IZd$7$+Qy!nY*ׯ{QZ[Elꐀ65&=##qiJ5Za !ƑIW#*kMn W*5ESqrLO'o\*ݚUC3Hu jy&ȸO- CMA]K ݙehO%v4Gx$hHV7 ˄6g'p۰^5qZǩN;;q&"mԍAU3,w]YS'{TTO>vNRlҩ\XĂ̖W9`lҖz$GXkf 7,X! "q%qR8**S^J$ɕ9NH6a$v.wr+>D"G;.f^W\͑y [2m#Vw*NlJ1yd󒈸AqW4N*XՑsnjFyCyʵy+~~{I#+#d?-Ȩ<ַulȁ>[g9"] ʝtnٱiZZ׍kX>?㗝d>wK Ăvq8oh>:|FvdASy`hG eΎDI [(+țqAE5v|URN\"5"nÒq,9Y'yQTّV!P2$q"ȨȾA;rS"9QS)&(IvxnȷY( K#-Rz;u{xgw&i=͑6̲q F#.6fYdh'wtڕ(ݰ5!bY61<{s:~m6IQU'n,Nlfti,~sG<.lɑ%ɮUbZ,Ȯ|7&8F,)bQ3dȜb|bR9Y;)7i"{v>IP1N$I E.Ff6`(K6xk8`/hjpqMj6d r2BĒDdr r(ەV\&e9h˺WaO`Miq%9͛9-xҮm5">ȡQmlA!3-|BºB'/6Yc> ;־9/ݮAH^<9 gwfF92"(dQE%OkQéE6Aa^s;aA*ٯ'n,nQݵlH'~>|gw-³W`ؚ=|xhz8ʩ1RX*$lo&|M{.}uM#Hd` &l$@ƻ,%s;#!ݲ bv}spF$QIR#dcv|O:rS(E@ĮHrK _ks9{ϫgXN*{JZȕ"5eN5r}{ݫ|hƫkwŃR,nMCZֿrW2!y-*]d6hKg|rlc!?xBZS%9o7_V 7c=#3RqTָAI$T|EY+,xƥ|NVrIƍw]!'i,Ε_!,fdY9rXū g޽3Y!1*Eі/Mlb2IRס4ehMom샯ebǛ(e͓}{̮lԧZnH,Ú//l:Z'lYB;6ĕE?s\tW\m=5lܯ.n䦰~мwۧp6zϒy2$_6=ӖcebWlw.fm c*}?[jɇJH{MpҾ;ȾummvFJ!%tܲW"ԫ`,s55a2DpIܜLǺN2lo[eZC9 $\lE mJO'^#M<܎hzg*˖8|7.ٮ)n^+8Ms(i78śǕG6 *fE UǛn\,B(d^YE1EeEbFRTf*?;xDM$uFq "[\g'O y865ݙSg ΧvbBHI,;|zi05q=h"4=9Ʀj<8,_$4lKU;T)]dM;-ѱϩniSiz];wζ.SԳu{Z׳; jNy{H y_6F>s9V]ևT P|.]H;$ʌ@y!$u&-sѳda\aZ>I^Sc$&"A! v\*Ve伇rBy>81:B/3Ƣ~cmPE?SU"pԗTI/fq 66m;Rf;+}ԾAoRIr(슞YyלH3ަܤNLb>2@O7%[ ս:\ܩc#EHFG鍒soĬȪH9^{|T~9']e졊Au*$^%]r՞̣?s,M!һĐvNCGSLԌ>p/F΁I( }p0^4SHA=0*l>&DI] E,EH䞔9{|<%}y8UUR>{emXD Ll`aM^#]#]dA(N:hvxhĞ7*uT3Mݦڻp_CV65 ’ó)6GA )e| ]9T)p)@g{@Dyy4gr%QFܻrX/$ u)_쭼2A_°  ‡gN&q]2u c љ ࣎Q3dL)D{JRw>`h\7< ufFH'7VPMԆM܃m &r']4ٙ\ .%U:(ݫ`'Ԩ(M*ؖ֗"hi) m-79e)ECX& IF:-SUltۉUMBP i.2SF6LV pDaRjn7GYSWͤmTNS s(?y!yJa(T&'6.Q!نz!fR`>l# I)cۧI^: +ʱ܁%fxgr qMPgv>9KqqtHrBNS(Q6F.w;Pv?talȥO2^M;H O"s PGA{@q!J qߋUf{e_{4i DEeUF}ksknYiF8t;YSHWsd(_˔hQyTq\ șOcoYXd^zBTGU#yZxlE֖3%18`9h l`-Hl[׃.gCΘqL'LW.ǣ%h>2Eզ:@~ټQ~cv Anau>y@u-G+ }<(lP.3 #F6Kx[0Zu6V@y,TK9+䟕΃*(N.v|v"ˠY𼆠l;مȃUc1A>Bk1 }X Ў4֋  إ*#!4>w 5 eWFF/H`zJXˢ?)Deg_ccnXf!%93!ҴbE7)wƯ)u >x#o}?ș`7Y92H[(1PGE4M,h,R 11ҍR:@-1Z'Sͮ*xE(1bCl֔Rjxg,gB8pQ$'zBl0n֍Tr41$2S Gųޒ NU.wILA?nUCBR>}`.O"OffLfR@ϣ0>30:?~ݞ1#KϦ|qh& OsJk٧ O& > ӛEā@0[t?%_GΡ{SBl,weuL- j>L߬Da?CH`xtm(˯[™* MSH>a fFU-?cgX_fߛu+\lIXaU,QBkqYlSn`_FejAAƹL[Ci9.yOz'v0r^npLJ3*}Ϟ}v3-X!5l&,Jڈ7HF*-0J#.wcEa`v(|:^#QdrOe5t]Ѹf*%NEAt)g/KH\q7^R@ N='ܫ@.k{$=sei@@CoY:I͠:ؚGat,t/ZW&;?co 1iP" ڨlUDGSo,^8]L<OFd/ut5S_/g&^H۹(Y3.5:,|ՉjΠVX)n=X`:tXvD#0z)ϗ>R, F CL a|/LжְWBܚ~i&q&QxFK׸AnkMum([ 4,. =tL_2 cBq%µ-7E/Q: i8M_"!˄OrH-}2 wkQv|6l4)T#̢DV][X^7:w IǩfHΩawNL5^ɧOQ,-IWRPXJbXCYHpaٗé4#h4K(ti[#"CwPm)ݱcznWP}jdTꊅĦZN|\f?h lByXP9]LB|wVOѓS`&{ +9 ;i iXwϦr.+|)l138NF\K5 Xz0V2}=fqBW,KP uqC% jxUv׌\< 5 A@~]R|T/zM'zߗ(6U{$q`㝄*"ܓZ7Eu/i-0f XhhxΠ(Ǵ%Vi7>å"ң ih鑅vUvfsJdo E[:&c>lKݝM6ج:O@> vIyDxezg@s%Ds&gZ"bj7œbYς} )3RSy lϖB Oɻ8g#ΐ+oP'!4 Ah(Ӈ5:huSWU󾏎@~V%e8lѳ{r>落9nYM}d3:{DE Qhw@q|sAjǡ~BA[{AfU*.O-qp!`bǵD,Fk M12pHKld$%:08 .Je ecb~>ձi/b{FQ14~&POa`lPI.,eH¡3 9/۩4Lzl/h^3bamXK#^:Dv n'3h@)߅$.^Tٯ^3~M裊m("$N.ķC\Pz]4Wpu64Nvػ.u ْ2&6okݤE%2P{h!ϝYhgJ gFN؟G.b t`APAؠDB `uGb1؄mE=g~G"s 𱱑EWme 2JRd գQ[a\'5)m##vTmoUh$:A94PRB8mF(Vǰh0cQ`2Z,M)M+P.K)Dyi-Ow4PF qPfE+7Ӝ<۾Msǃ4CwQUj2%>ٔa%|)/E?DvaÔ%;R U&œǗJ)xZM±H}1h{yÃ~$.{rYDgJe2Eӵ>F<\*&괾70yJ2Z0Ԯj[TtıQPiq2 4\*抁)t!{蘬_@'ڟxŻyP y|T!% mX1N59ؗT=| |Wu4-/V^,r{d*er=e_9ζk&b'Aă$G5ٓaו5H}ȃDF_NJߜ@d @Qԅ+oLr}G#O}qcQ 5og/Z(*>VƯqԑ\tV<%􍀦kӪ8y<JhTK!ŜOt sѷ 3e婕ף}Ġv τ).a QOD*] ߢ`DIqr(g&+HD!<$ NeIm k>(3JF@& 'E[:&*mߞ rųCq!.d7}CLj6~PDEDJ? ? %6WUq{sِy ,)TΧL(K~z r 3a4W /+Y@ώ6e XpvxxH5<_ِqV:j|d⩷['A]RꤑiǬ!~bFQr}#9^i3LLˤRz"ZO*\]DՃj ˄'b'\HG%p??rvDFYKeB2dTLtfߑ!ly=_B (|>mQT`<_0 _лQ܃>[] PFxڗ2Hl 56 e 5jXw+7j?/>vdcX !M`auI¥W|}ĺi Fˢj Vbvq)} [PӞ$@wf,SE?]g= 4A ْ/{DbeMqPaYI^6~1Pv?DFsqFyA)H=A'.!4u?Y.`ʲ3=1i N?{=y(fy/u~V|~"bգ;з-^yNmScB`n(iN*s\z }c1:r'dኢ,3f')03#O`óԅbݔ!q ›[!e t>uOwp* MPzaWqڗ}oF u yH^a5!cʧٸ޶+n,. 4*oe(^EG n1U@'^**)]#_g|]ZjD:7 <&H˱!4#c|5P(Oww|uV/~.=H.ї)]6|( <rKS 'A]8ae KcU F ku۔CDyOGHΥZGfAЀmդ,O:^5T> PP([c\ ]q#=ca8_5PxrzJ (JGzZ17RêGj_=9*d_*7NafߢN=}J-Yp_MAbmv50?ಟ)D8Ph4q5IJCZɃa8"^Y}.VKP_#a/ؾ珈x='p9&w5Ψ5_ͫ IqVn)]m*bLA[ՌJBYX!")"2a#`0PP|w$_Lrm0]%nD]2̓SX{/OrH j.AKǏN];K&&0tKRsW;:@4VA!_,;,THûxt܇b SNtղ!jnzbI3f"H̄I#(yN?D= ;D<8 ?n#YTMCr^'sڻ-5yC4ORYg6qC*  y+:^@[{e7SWzPԐ`6 Ͳ4.}'!U(ø2X 寅v<56$~( XRnNo-:O828QjNqfmOg $yf|99* sv`Ekxmh&pnAZ!Yhh:&KXtoV. Op蕕T>6U~w3aX_}oLٔx0&pɾ(r WXF=&3m4+ Gv|ˌ51+Uz֥-3$]fR?lRFLO&שvm55K/5ϐWĿ_jjk~чx1ߪU -U/t6c탵IuFjI`Pa#;”ͨAO/BOn/{<804R 08;P3I[ V6o` 7}ߤ\kx0Ͻxjt)3/14 |J InC$5ؤetke $yAzvܟbN]u`{UUtmǭ]*GgBK#S¬⻠q}5AyN]-/#CrTo݁"|oq| *Xd@BWC` .ff1O飨|<2Fo-HpW^+3 ~[D[xP00 h-Q:*7+h /]Ґ%fqݢ0шecC ݏ[xvc~1 ֭Eh30 ϨEqCMbU`gf\!Be6h-NL@`2zZyP;9 al2BScS !qB6$ ҇ϑ+!g꽷!c<$ꃣ~r:y&R9͈80K5%WBU%aBfjjO=& l91\'-iSO2@j@y.O~DQlNS/C]rD汧ϺtK/!ǐES ~3aZl b(+d *vi۾ 6plUv@M¾5ٜZ(/;zp9LJOI&bԥX*MzK֚gwNDq#O=(d=L E]C/ʷXkhopXt`Z!ڈ=EMqC'akwJ ܧ;jVt :{#5 Dmڧ<}#\ g1#v H_x;frR{Xi0:p\kd(FIayyMѝ,ݲoQp zkZqʉ[@z@aլf,G\=GT@d ]Bʃ'Fʺ̤ (>Ž2R}?pZ ٷSֻXIexS9O@x2>y=@DcmF-!3q9X2zK3yxm:"cV\vWLˡy78htE{ĬN$L^);s@J3 Eh9`OϞ#m|7+0˸Y_Ȑ11Jԅi D%x?Np>Ss& AS'xܭT?-d!faEmA%;'{r|SV7τ}FQ}ItMQ"ωүԗtK>iE'\TٸyG skƻsxoTG{J"%Ԁy\r#rG - PNm  b!e`(;/NeIJ|}ͱ'A*%s|!2?Gk1_-bΡs<И. Ţ.)m](tdJ9-*f$@ ː"ab'@՜yC}z<]^#=Ӥ<Z7?< 'YY8TMcvk65aC ?7';x\J !Iv*Wܞ)z3j2GFP`1[8„ҧÔd|ף:ԨqQ"򶺘EקԮuOXSLj.A5iLF7z| =mH ,#-D>Nt0r9wʓH);{_$iad9% LcwY+2>niGBk=~l:PYfCŌNB܉枊r'Ro1\'~/BF x,l\^4{RJn+wߺ@dbHJyB3Hݗ̋Rb* #+iC\s'.ŵpp(CK8Ss\ 0@E)k$rƘ8v򕨃qH2$ i.P0)#Y0!}l˨8^y -fw싡Q.x^jLq,B`BTh76Gˉc+)LF+Ԃ& ?3Ȭ3"OL@~A`{-aÛndxPȒ-).B^Q! 5\ܐZ !f->b%ዛ(Қ=հ2b1Hz%D% |c?"dP/;/to֫Ld_'(cسc:𿭨 Vq>[]Z!ue`ߤئ|P P%l䍖.X) uv*ct2 #TIqyvDXԝ{8Z--3˸ KvC%/'2Q+ 4ƪUL*P7jkʟY9Hngdò9)P`&0qvkC%tslڐ3- jaxƅ{=@,^3|,DyjQ6A9n[꠪t&J {O@ГX1+_?JU;IB #,{AiL (Je`r8QW))H)WDm(-S ֈX^A{qYK$5=S:zЌv]*v: Go#ͷ)l:6! @g,Z7mitZ-2DL l􇌜hScz#Ð3Ε 9X} }4_c3IV6/27NB]taSڪPiVN{LL{݁jRJ5xoT\*l)?AeF?jܒ@f#rT!_]MR,k}L-H+ETL~^5,h4%$i3HYnj:E~pKWb {_)K-)=(&`HT8I[Iźܨ_  jCUuQ)>vomX}cP?N<`tIT_jL0ncGUvB"Ǻ/\+GTJF!TysA Q fA ? ~1@0G 0 3OwO濏mP‚@:|T1ù^ ;.<]l!asTC')%6n+JeFcb'`mU?<*  9lFlj%L\E;, 4[ti4Aa ⼊b$5/EUL[()!n$\I!;(ā[26@_VwԇA!veUĤBsr ZueѨ&iƂ(b%ɊT,CMmSݓLesʢk L"`O)S6%*b$K=#=g%ӽ[`s*XIXQ$\%txc8hUBBJpwEP/ͱTh=0K,[i* Sj7XCj-@ðL@)P[`fRIrɨ8NLJ8qf$TO &}CŴz?TwMR*:c`q{F5r#ws(4z s,ְPĝ6Sg/B]HWBEvr,'"&&K5Ez71~< 8I dF%PuKqt0ڜ2W,9cS3 b lxaדN%"٩(sSq93:?AZ*KdZȒ^1U]le 79t8HZa#['" ̳[O߃pp8BGڒ Uu᧒h23vKtk!J9(|!$ݗn J6IX1z]QZP~:X;6I&e4 V<3[ ;0Ոk=S PZ0 qMifbDJ/,`)<0Mdg! XÊzwtvI,1 `ƓT+:᝭_lÓA{loq )EUEwO= "GQJtk [\=p#D"J%Ҹ[-/]r$) c%`h_ަgKk໋i._Ȓ`r7YaCYN%,FÃH]22-rúq&*pҝĬ4/XN GWQl6;k$I1NXb܂'o"͎-YN/؛KB7`F&6G#ψ#Πg^ PHHרݠL_2 uQ?LSw =G^|f1[H R|@}-|]|A~U%ڔ9K3g򳓑Ms]Wk7qMA+%de(:!W?a|I|ٱ Go:9k}@ 1^T|reθ,'z\Ąlul*1Ҹq!d4.6xLmVqU&tzt=g]p9$K7yRf'/o\t(RV5mce^,_hPihXaК &!#P'c ZɽÈ[y]h|ܾjZlלpuԌ){^d6+A#4zȎn۔eko(duc)׈L?K|L`鍎C]Wo[ Ao /)e.ls_ ĈlPڋn ᯩ'0P4%D2hȕ d8W@D5Et2\^7-ƠGe!)i"A BC; &t&U:jB@f,;3@c,Χ01xތ700"k>~01rQuSŬnZGuKacǖ~9C';ӅeW1'صAo8 cNpyQcj4[`܉Kg8s .hmTk+#Eaх[tty@Ʀ E݂Fގ|2vdwu &,I`0SZ:av9aC'V44.GHS,4k(Dd$N㓗RR,A9\ލRv bBú5`ĀwRiM죯^v7lE Eޙs"%C.D)"&ć5B~PNL (cfaRF+2<;=1j\RWa`AR# Di-f`E /}1!9_A4L\ WOc &84"BXcNz4 "Ff%*_V E18"bϒH>j iU^Pq2=79X?Q$؀HNJt30wqۥH.k&"g05;I8U(#YT?y4r`qge8rw(o6q,8!4/Dyv. `!n05V^S(cL0ˡdSN#?eT l#MBXF@TZ7ƞRLuO/7hW1PJadKyD;vzM2ݜx,w(ΤU5j E/~GQueN}-BSE1%~zrF*"Sp=/l .`픮ΧL̂F*uiLlcND`b坷gv͡d -ᩑu_W!w*",够]\`w2b_a/{;\?zuǓ.?LZKrsy:@U޳%1z2>(OyO0+`qbdUSq>"Y/3ςزvmL-]=z4vPIrtZӺ5 2nqqradS17g5G#?y_mBN阸8{89KI VKxD] Xװ3]6#0ܗ5G۠˹dnVH&NnM*{ }}GGMrG{jJFz[ RS.Q )]F(Z LRxbA}=F~8۞+$ jݧS##A߿>EraR M|_Ao>￴zV!3N^uOPy6>῟ѣO\w?\`A]U.1,I%0!,#-#FV'2.nHR #kҒ*!fDE%F6df67"-){T(L.Iɒ _P1bf2Uf410Dh +$2Шq#4@e96}b1҄p&i} r >̹g53%k .S1ZSՆ1Zљ*☹6֥(uY,"X̣T(]$虘1 ÛR8̔QehJۂCt,Ƃ3hetvar] GlA~{]kw EG@C$Qi'e~tMyRq8֠ap7v߬]hVaܗFA'^Qp ud}$ KQ}2R5 TK3#Z̩dFQk;k^xJ*x: ~E @#PĄ{UZWpҡ٩YsJVBfŠ ރC:!t(Qq[+qchNow^4aèZӁwwTT9I;C(MZv >vqGiM#∰ZWR4 (|\,/iزJ31am+̝Y pFT g{N)*=y.BB_Or7 ﯞ>d>4 GԐ|Z|Z}z#"~oGǺd#⏊>!=H?T&xPQGGc'WOR|zd'ş}h$AzI?$LGf_?ƙ?hPpX7LMЙAP ! V&VE ! A7)\N!Cx%GcbJ,XRJRXb)J+XT9J,X)JRSىeRRJJ,Xb)R)bŖR|d,X XbŊRc)K,X)J*T,X*TbK,XRK,X-,)K,,X*Tbŋ*TRK*Tbŋ,RJ,XRŊR)JRb)JRbK,XcBHD"I2I$1S 9gAI z̑ Hs30 2$"D.dbSHY LB"2.fIJX)K,X,XR,XRŊ,XRRŊR)JRJ)J*J*Tct)e,R,R,RYRRr,RJU)JR,XbJYeYJXbŋRYe)R,R,R*TR)e,RYe*Xbŋ*R?*Te,TJTb)b)b)e,R,|r$$F2HHfIBI!XI 2WI!$Ʉ1!ra0$ H)$ F/ÎFdD&/Q^I!"̑eu C Ye{L&S)RJژLWXeָ,Xٖee)R)}KLY)K=ltz,W Rŏt.abRK:deX*TbJazazazaJYgY2X̹2^zez* ::{*JR,,eUU^YgK+גz/XWY+d)K,yJRXRy+YW/X^zt]2R2RK=u=Ve/XX,˙s#,e/X1L/L#,e)J/ fYbŖ_k/YTb1J_^,Xt)bǪX$IHEL댋,,XRT,Rb)JYe,Ye,RYRYe,RT)e)eYJYe)R)e,R>bR,JŊ,X,X)K,)K)K,ʕ)J)K,RŊRŊRb,Xb,)JR)K,͛6lֶlM4ٳf4M4ٳf4ֶlٳZM42Hd2 CY&͍MMkZߔcf͚6lll٦6iƚlllljji6llilli͚֧ٳf4M5kf͛5ֵ=ޛiiflٻ6ilٻfilllllٱ6i͚6llllk[6lllٻfU)UJRUU)bŖRYe*XJRYeJ,Wc@$2"I 1$`IfI f1Vc$I,Đ\ÍdHd $LDEc&I+3"HYJXXb)K,Xb)K,,ʪ,R*T*T,X)K,*X,X>JYe,Xc,,)J,)JRb,,,*T,,K)JRŊ*R,,Tbŋ)UbUYeYT,,*إeR\DI&L.DDdDL$b$YbH2$I%Ȁ̄VAP$DԈ3$fDoI!p&^,UXy/XDQ?AADPPEDPEAADPPPQPPQzףרz=h;hvv;<)G=zQzG=AA=Gv;vh;hc۷cvv;h;A;Gc;Gc۷n݃vv۷c%dBG#d ɑIDf!30"3!&b3"Ib!b"3"!a#$Os$HfH>"*(DP(x|/߿~((((  ~?G?~~?A??A SׂAA `R A `@@)||>#||>|>>||D~?G?EH)?~xD"#x>>|#QEPQEQQDQEQPEG^G!>|>*<'@ @@@@  $@@ϟO><$(PBHGpd0~W?~~s}g3*(}*R#|=zNCN~NNNt|nӧ^Xxg)D?|Q/:'7_}J*#>zH|!Gyszo>~v\?}O5_O5"O/hqxh I$J3$$dȒ2dH` 1$@a d!$3 d̘L C}ߗGXW]ם6M5cZ!0ü{mQbm7;|E*GEEc$7dZXNkE7Uّ;:8I:08yʗd=T'(ӼΤAkyb\yɏ!zĆI2s}ӯ\twUvQW9smjN5ǐ3;O\|^&(m!N8<)fm6ۯ6ŎGɯ!FaY! !%cℓ+,RI !lfov q &u#Y2$ĪAq!+QkH'$lbԯ+L\Z`PX+IF$e,m~ӖZd>D5Ի>~7; ?LQpKLvkrTH!B&s[*/MhڹF E3]N!5a8=E',CdtI C\V'spM]4q)dW7r46嚗v$h'gd-䊞KCd"=X*oUhuSpR${?p3םn5,z<9ɨ(؎5Pr9'y9EsmxrHy"݋$aS&B8"q7 NbIG2 #!OlA1 ~' D$"HHNA $l0T ]H6FB8kQ+#3?иgDr0qMCS:_`ࢢ+D$rE+G2'9IԍDA zÿ/ ɲSpV0P*d16]b!Hk5jZ.eW"gӇ\V28(<ʮ]j(T5 &@ۻH4rX"댋*-HĎ'_ z֤G#!B5lQUEY$B&KlB),ksߨYĘ_&xĜE56/ ."L眔 )ԉET8Y3<16)"3D"-,&z>s#cS/$ud'%CFs_,9"93g\ًAJ,+g#dH,6LPUSϻUXΡǍZ5^450\,@W1L쀽I$p7!nw~^pժAAW:&dBMEZ1P#ɕ3SY!iv2nژ":B2H<S'|ŀWBA< O!5B s28.r8.\̎ UqW$Hʑ"D8(G? rB8.*╎F&cA$r1Ȫ@p\P$)\F9 QE . % 3l $)\6m.bG\$ &2b(k GA+ApPd &`GApQSd &f. b๖RHER9yn[UUTQETE$pP9pS fa#p\"*(qpDQE &q"DLH@ ? Il D""D .  `fff`%wwww;vy 5- 4]WR_())YUEً$k$/Û$#FF×iȐdeW$zTظ/pab376@5?nEDӲ%IPj, 爾vzCjlۚnI4YLF))IOfFk|Hq{xvMp4& 掎,{3~~{~< C-&Rc4mI&/!ǙY*CI~*8>"퀯!]6h!<톚6F̗dv)isda55^]C2~_]\^p.*acMwK/y D#msXl!6ּ8;{vgX:B x3'"Y?z)Uqkr<}>6hƈÑ$vA2ko,Qc,Z\dr/6 Ԯbxu8!2%)7|Qu rlȚEm#bVQpc\ 9$-qTy}ý\\FI0PS?&e Dy*u։bMcf#l8ϩT~+UTUl!a> q8CJ513Y "uגUQ̈́xN1\@gS2")ɖHƫjo<9s298eDU-H1x!RE*Hk4ZjTG"Ų͓]"Y+bຆArH-ʢa\& & 3l&,V H9m(̉jO;dA"2 0QE1W "eA̋3dęTb$G(Ǒ$>WfI2G21\=H $q\{>rs9\S1s 0YaE J홚+d&ŎY28. H " F5S?߆sT^Uu{gR1H=3>sf$ua$qLD p#ffkP af`` QGDq !. c8)ࡑF9 QE"@*s2VHcdsqWHb"O$p WqqQrfrݡ$ p\5s#F&0qp\$H3QE^B,qT\r .GL ***"*#. \pۖֆȮ*-2d"G\d &uB8((bཐ$*SVB*স##DW!@Ȋ("g$H B8(".F8G#8.Tg;_LPn ?*f]aonuG4|HI$m˳J@r,4'$x]Yq<A_J%ex~;_>(G]EF"LVm[hfKkPP$VM>~Vb'S*xY&~"ھ49'g,眶Y ؉R1rZ]+^$̪OZ߉Sh(kOyCq3ަDuY*u|wdY,76F 9h ϥ&M,=mOle:fNPEs͆5ŷ]v:BYSc3!mXAy~2leg!2<GE9"8e]L+ȨY1pF9fW#SǤȞYsSPkd=y6RfY3)V{#x9U>Hb)LɩȚ ls[yJ+3U㼆1N'$BdK wMi^9!ȄLbLq0o<\;"\Ҟ6C 3by?:C8B/Dl s5]&dECQACG+U %zk8EQG,&/dl?+|W# Gp[G"#0\*M"O+a jD~Ruג'R9\UA96 zL5 lg*5C!&Ii{*DȊjJ@dqHHDQ@JNukZqsV$\32f(F8 )TEs1Aja H$B1Q?d7wsM֑"G жvdY2' c&!d&aH)$\0U\# l2H`F b) `I bczdc*A,*LP*W"Dm*s1Cemd"DSd dI.(((&)lr=*. .fC8D*D,## EWsRYRّ1p$ ?hJ#&( $'T9$LWQE T)I"b*1p8YdLSXLJ)I$G$q=f$qEEGC"b,Qr9T?pS?o>}؇T,WR?q3 0<ClQW9-"qrk9as-寤$Q]PSdg6gb,|swK̉Pzp͹dt}'o;8'"&y&sS(SlT,͒&6g7#d: fʬqoUY^DbݻpH#rd l;e<B٬+vx')l!\QT=j^Rd_y#ka1ݻ+溘xl,E!!oME9yCDud]q@QrFgԴUu\$=PZ8Fc ~~߯EOť7m!,YtӲU2!هUg3Ggu3ɻ& ,6v,}by[U̢Hyq]9\9NP5d KUJfQb~u%Qq^){vǩ[;+R$c$b*{wo$orHdrncfk_%OX9iz$$cjmx夰qB!<luf]xmy)/3ke׎!IƪQqR6ݞsbEksG ٘ ayOyEF?͕[$:Ow)e,$[HmH*(} oHJx7Pywk'W׽O3b<{ [sI.a*Bffwc'bTk9>'.T*T6| .V<*#\ٞ&:"$R$s r2v˒*% 6j/y~&AAR(~Z뙕0O5+Ec6Z F0r~9_9I\jwmRXKdUU1Ȑ$(ɋtC &L^HI8Ljc$=Nx͐io',HMc\Q'7G8ّ.G2hkQK.꥕1<,¡ mgSC66ße q$EOjdP8(\#yU# +HIHԩ8sjm ,db,9aHjm"D b1s8FʘT Wb(9Wfa&xlS1>R؉bBd4 [,kW0|a1G>[cT9nÒ5jh%=p쓷GDf7`@\ώGQbvF98#gĭ5m¹PZkuQ5A[IVLa5xÉ'ealB8c٭q'g7BU8r"bfcAkCG!ّmֵl\5RMJ!+_SXu Q$v\Ü6LK&<dUxqq$Ȋ< Ȃ"ͳGAA!S#/2+BW5\kn`z(eT\!qH+?)3]$'º.jɁ3q o'bS^9x+݅WLMظ GcZʕ݊I+D %$Nwn+ƹ"r$rR H>kX$!Fgܯq5"AⱊI$\3 @Q̈́qRHeecEG$&HBNZښ% ")~?agq[8j"W;HjKmsUFL~JB,y*?Ӱ̞yBlv宥W !?IԲ>L&$hǼiɊW,}c&xayiΤ]{%#asvG p[j \VL_%ļ99$JDK#L[{vl25ζ8(&F"_[Esw-%ZEc Z |GE$ْLk"G٪]KgYybu{#q&/L~˄pgKLH&[Zٝ%;q:7nSoa}DjL{ZN&WyԈL6LB7bC[u'&ّ=@nI8V*eq®#AgeEp@<#PQXp}zfdLH.ABL3 HmXX`s`GpW?6|cfim#aK:fh(.Q 1rj;1EԮWevX MJ}ʨdD3ٕov 2 HW1nʊ68ϹW6L6HG9;Iֈm.G!XG勞͡8h**9PM(,bX]D|DP18NSgDqq8¢ݥl-z8κ9*W0'$O.l*s$l5+l2 !$"9Z$GZAB6z*.C!FS?'O'ۂRH$ p\"ฤs1pP, b\UgҤHf(9D1pP\3\b*##ԃ\ vep\5F0Hหpěebۮ3Q D")XY,X-q^1X AV!+iKiZI0epS*D"dpR9XH. d#m\9N;a[Jmr1##DTs$+ܶ1~$ LQEs f1k!ԉF$"lHT,!&q ࣬V11 1*!pL'M.Hɷ8ciKi\U$ BHvDd*9HWÍCd &%FȌf.cc*8VXsvpOO?oQMr"NdIHZ:7ks-`u?r@80AI kH' jaˈ7qU9dvY^i?Q&ySc]@SRP_)͈eTor+ζOkrAc$*& `QG<*K~&>!lr),">Lu\w G[IBLAl)Ǫ.9Z lDRh; aҝ8qUyEwI-SR J>o!*vACvb UxF@xhX|䳰SJ;!s8#Ro)UN:LBf$QJYi2Ul'̈WSȸ|`*TR5 O}/|)_Ї,E$c2,,I;Acy H 緮kr͒TsPԬBXq vf-l#d^l:Xj Ox˚g9ԍ}MuiISP E $H8"<ݭHdX19wKf,AC}2A0ECH\Lx1%+aDߐdj WP\Cs@PGq5Xֹ hEI dE3[]"qz\9'P כ1G[0"~.'c'XL")MCC53Q f'*.D#dL<\+i ₘu-{F"p*qqb,TrH/2لk5gQAr}Ž=VӨg"2I$r7 AAW*(̂櫄ka8n+fL !y b:L"}6Gq:#^ux.^=H= h$ im500lIfd@0']3!1\A1A#2BFd 㙙l#"bl .#\LWqv¶d'',+l!9FNU)m(BRڪY$d,Hr )!$r1p\"(A8.* v$#ঠ6`2+\sdRHW28. ccbE I5#&BH/$HuFE H &p|-*Mf1`$: fímmKmm4emHE V1XĢV +epPIF&Gٮv2;-pȦI9/7wtQW?"G p\0ق*:TBBfuB.*$, OiY1G6@Ca 02VVҸ(rN%y[g?i?oΟ?g?a?gO|,Cu`[ G#OÈr%#R>&kD*o&nwwO<LqT k٘DCR23 -`lZ#!3vb̝ybdSQqY6Ɛʑ-r.gfQ\bGy>ӷ#ο8srO%u!13,2x>Iǩ׉Ϧlg92$q6E#SX"^+C}cXqN;XmqEƺʵ3vQR;ekǎ2K"dDpH{=C\vg6<^X&8Բ{-U>ME1" '@t BTdlܤrۊ?ot~|O *zWӏlQ]N#%^]p%H*".)R~PZ&oglQ6x1#J=ۻDYru ^rfD9X͚ꨞȋ/" 8j8Y-̛/V'' )3HϜʨ`iD(ʮFiÌu wݐZ"_l6je+V"INA#y^#k2ɹ%ݖ57D^= [7`sb|޵QybaF53#= Y5pG $1TﰯB@V4PBEI$V f" udz:H鐑$HuԄx`q7ajNۘ$1C0ffaV'![S '}]ݺU&u#ATܕ{H3̀Y.*al#"{sX/hoF x$ p\r$Cd5ș^b@dTLS2#Iw!3 9"inĎEr"KmjDbFb(r$ E^±:$εȄC,ۖڸ..euB+c!Ǟkxe|kll+*F$=D(XEʂ9ĉpS" T* fÒd90\-O$WV q#1,>Ld(,H8+L\,VHH,pPr̐b. m[a+XV9L1A0n[~w/$=s/<ZeMdv9|Mv"vl.Ynj=;ҽyfֵ\,mio; PUw$L+nZAUٚف-VYOd\:3?>OCbeGdm2Y{I .I\Q~%w%g'ɜN8E^ͰSv 69K0X!d'|?|)s}9c C" U?)}Y]Y&VHD.w#39d$ "+˺6OϷS3IxٛJRن .W'_| s~3C\\\C)7~+|c埽0$ WԎY#5¦"*5=:H!W\XO cq|@mmAp]}ui$Y,`ԃ!!,]bɕ@MLi!F@-/m=qU\JbF&JR2È9LU]-T5 k`j;6H>@fAFvI]3 ` "F8{ ٶ6D?g}~3e,BGg6G:50C+]9M'^+5¹\=KX0䤳.*^EȊ B\1J«Ԃ81&#\ kS5mW;ΦɆع2"xƳ**]B!3 "b栻N]v^9Xk*W"dPJƯY}G+a8 #XlsݐSs5b9$c;'fZks,S 9X'dE\geS aȘ1/QCR'{8!JW\Ȅ6nY&s3vgәH ׮gߒmkX)d""!R/yf. V[#SdJy9,m2&;BX CPKKHF53ZQ㚼p '"!KL0Cpχ=$Ȿ{miZ z̒k1>P\$$$eM;#H2IApDMk\s]REdUȕv{HSmM{ve$^'8W+yh.{giĊ9QW./9NY%,Y?;>*mB/|X.6}'~4xL3T_9~>!^=iPa@Ek2qvd#Z'>r$D-AFCT\DRD\py*Xᨼes!\,(`l䊹+ƹd8BcUhu.dj8ɐ9u[&+RX.lH\O5$kg5kSlyC}~ۏT 5?}_|YǢO7l%hzc.K$dMd6vT5ʢqavr# L_oثprcR>]Jp .l $s=ϩXLG,e_!TjdQ@~H5$Kio(hvk QOfqTE[QJ9{C4MGyo<?Ɇ%LrCYOf1 d6$}Dy|9j[6 КNEQY?o/8>xmdfk~#K1RW^iҞr+k25׼7?<A,Fx[`D'ZI yZ#csY' l>ߓ+Q)ω35_\;UK6#Kr[͓kuUQ6>̯"*&XY\5S"͵G{NZI\9b2ub *<䋚(G8\EE2{~hAp{$X)b$NI멎ldÚԉcZq;d"{&⾥CK&\HWHsWvWerT$h)pTs`yc*Vo7 "Bm.56O\95I٣m(xy2 8B1MJ.2d9$b rH-+ģ-%r1!$RH7!ɒ3$81IEY[ia 2HK+lY"PUE\8^[)J0|7-Wȳem33~ m\{򋼨i,NeT*jH9ЦlȔcP <AY3fY#1dj"Řq2MIFYp=֚9*c\5B̉Qz0skIN늸ؾsDrɂ₦̂,bfO~4۴ԺR/ fwx:5:l=zz%K)Sd+l1&ާxqd:"rs eXIdRCxxKǛy2 ۨA5")dB&^7+X@ܝ3vA8YG+jJ?Ok6VזLQf;~Ew6W#fMXrfQqr"?߭ړwVYu8۶9/>v׮DaJ.ISͻ8Iu#'[:B OF߫v̬V'@eH?pՖl$FCvd7ZÃ3L:{ g"CNxfdm*B+#PU?P|M#" لߪ9Rبo!lȑ:*9T,2lbjxp8E wvUK&b㓌TNb4˼~6y"&IA$***kA~yB#$ɭFDDR8DLju2'ܘ$g/dll"<=adL?S*WG¹X.,nb*_(a iq\2f%HS\Z"K $^s49ε̨jث!{ |2HȅUInjA#d %匐+' TԂۍ!~{;s\ʄHSǻ3^Jb尉i@SAq+U5Fb(lK8Ȼ/j҇~f̙MϴDc".28琴G ,{=ES(x$AK2Y')fh%$RGc2f",뻿:iDՅ!!6Tq &D󰭰5qؤu[Ѷ`LmimF3Z+q#`I=c0F f!!8bD֌ysMwh#jA}{ 1Y+V7lܨ)^$c[f0!qw9%qb+#U\U-bvb;}'vxGlpvoyȇĢGJ;˪mݟ/=wFI [In!u^+SrTNII<ދ-7=9c[0QerIR#!  nҗ1]vn6! Hw+3?_-<η89"K[ɲ"|O˾fgNJo׮ڻ7D';4LdxY'Qg lpݴ. S?ɞ&wR` +i2rS~!AEO>g9~__Sgw&.xr#NR9kE2gJ !=K"ڎ:w#N1$a>R^2C?|ۂM]P H&tqMrvcaǯ^FвdB GSR!N?MSfN!I " G6#Աٞ!(uQ Dq5֦Q',$'NHHs}MgfS5=6MsTr$W1 NP.yv 2AHXA#{YlݘؼLAUyeg&kl݄\$͑\i!TQ+٘inCaai?9jQ56Ȟ%c!hYg!v@y"gS9[ zXg#!,\S8x2 gvjlXִ] ]9i#F{Oq{aa{_?VV3~JN_pDdll &fAq$HǎD I2؊T )),pPwa;2F \zزE+$qqZX$b8@P_\[iO&ʭjGî &_ZB'$nIWx5&$ϛi-3 Hfo)HIy*GY"Ѭ As]ܶܽW1ɉ@-n 2MAAq+mq3yu4x* VFLs'y mq=9H ْ@`)bE$b/?~~>|jmJP}W" b x4|rTG\yJyO&YZRs2&{2 Ya>RMO>>7^>>'';dseƆ?sM#!hDZE*]]g}g?yh;X.FXNO>oIsҕRnq^H9W/{7I{ݏυ8Ww;7o̮gTSw!牮V$?{"F$H")Djju8#9.ɩDXTGQi{,fuStZfN(j^Bi啎HƍL\d|QuR&.DD_S6&D\_?$.A$a S9\va$8l1La"q gP1]YWuxUk_n|AMyb0S2ubGW2='/UW\ɜKHI3P-jd@C5UB5%"]Gevh_wy.r !E1T8D"dMJGuüum

LPGҨd2H} ?WA=sW2 lݘLT va03S;& vCxdW ZU3P:PE#bsbs~3Da+-G䱶! (&gJk㙑 ̆]|w.78`F9ֺ$H`dr&7 *S3 Ƕ- ♀I?3 T29z> jM)IO_9 [+8\Eۘ")_얋gԆhL5}=VrZAǒ[=.q&5+51!E– CPKr8UMKfrb6HU$T囤 Z%Jg%9#dH#%-Lu !}Ia6(qF;Op-Ǘ"'!nq>p)__/}?9D'$ٮ_ZLRzzm4:\O Dlh[ʕ#؜7հMr&ٺCjTnrEOK&!ap\PWY*/9NJߪwy q**׉db׋MV2Z+w tkNkݍX9HGg_or5Hv*DY%Su9Ǯs:6Jf͖Tr8] adH2~>>8/#6Yj)7ǜx"قL.Y\PTssWω.fG!*M㼊qTYx+N12\ȼggR/%.ym7p\* dTTuĮ4W`D#s*əb \\dfb. e*r[bKl9N߃Av}ι'_y5s#!rQܘQHaS FI&G2"VvW sA3\p#A[ +Y{Iys;`IB,T2&ELʰ{\>'*%Bl0v" gPH#\-AN'ǝТ x «!<as84rg["V)l/hj ; aEADHsyncZc$ܖHQBu2ً"K W#&T&ɼɑ,K0EcY9G^&c$+^%C\$K^ͰdY&".c/<漄e1 r<8*h/"F1Zx\?Ĺ6V<ǩz/II_@4}P$i2$GXn@GA3Mva``@T(\3: !L)fa.f. 7%h02ŒBl-]mNp崿,K`:͛^y19k,dV*nY# n5SA] Y5$֣Z ;]eSddƓi| N1eebYdē b"D#h'kPO^ffdt]nmk7y^$UjrԬ$;m+33yI~ rR"$I:ei٣m*^[|آcLv y[ͥ#=8)l)&ӉQE0aq8#n9>gDzi-䭲8[R5gf6Qj+$FLMN[wc}m + $d8hVO$a )cr R dֵ#,U]H,$DU<$)Z1wsl$,mRikzWzu@Dcǎ 1H dKbO&uz^H:睇,8""BE5?x]w,[n1٪]ıMay=gHk 8+S5_r&kg,Z l8r8q8s2Ͷ̪㳖.fdQPK2#g"jjk-r,]#ǐlԎI+͂)qYªgpqxr+#B1 !*(ئ2װW>wd{hrLv%6Ldl,pQTUL*Fdmb.q+\8dq a^0dB!/(VԸ$ݘɑLS0r6C#H(q"T͑r  j\vGP.LqA`Ŀ_lv:S+q̮o qs531<ڭjk5Mw`]!kM\^T3!ʭ^`T\U XQpQE6J9$6lU¸ddWdV0}4M@G =W=ٕ $'N6 crVhM;W~[h8:  dr .^Gc}M[{޻i_P; 0eeCX!eFKKË,.C [͗$T FT.G"abԥ%6 Ƙ}XlD"%T@2z뫛;vۆJ `*өDJL@(fa{;:zz$t} (P88dJ!wv0DpA66l(LEå*AA˗R-[o"n+Pb %H"1c  Rۮwj]"$V ,+;I*I%$ )f0c ؘ!RJI s;& C(2 ʕ +*" {-*t{# i D(u!2J+'K0` 2f/덫]릛ݖJJ%JRIB\ 8&yNHqZ]4禕EJJI* feLq/3'<<^6sHFQ0d%LD ?cg9ヷ=u߾_h(\$!`y0$S8 OR{wk+}uxpt8oʅGW ' H@>  wakֱ['W 9P]a@9Q!HHw[b ҋ\ۣlΐcG FpNAdd$ɒ!lbֵD(u+}yٞU !CApHA3̘d0+V9dN"ȮrV RRHIwqwhm;ܭ N"ȪS H:$B^Wn,uxޣ3p0FAQ9Cəf0c9F9닾ڸEutaPÒI>qN;+@خjȲ-S LdYHwVsڻjHN*dS*D aU`#8[i{6 v`% !J!û1rNc;]kIxlLUYD&!I&Ov;mm`{" D!Da''nݎǁwݳwmjuܶȨx REBa ^-1ӊb ; Gdpɓ 0¹PR`wuȲ& a:RH̬ZŋS6z(]^ :$\+YJe)AH~oC̦;Weۓק^GzmlzŌiHr`tdH%l`{.Z##}˕22)EBBNBC!#$_c ܽbr8#W„P !J&}9&GwN,juks%fL0 ( p&W}W]ݻ/WZskYJa@\!'R!DO " tɮ_PY(P !J&BfH!ٍk¬"0HaA!J_7&IwfkGgo7:2iW6 `'RN:l^iN+}c&Ma`.CC'ޑvTGqwb1~;cSb;(pC# -h]3b>86-p)D'R# ` ܭzt쟍!ei E̩ Nɔ1urRkXq9ڻ=Ja-U$!iLI%w쾋_s|5]xwwqto]_w׎9<( Rt:'_B!t;0iFuշmx92(D.%Jd ^bWr[^EB6"dH0T%pt8D;|cX}ɴD]y#aT;HHUHaJ2c9Y&I$fT3^TWE&RDʅ$y؝ԜDxQrz:޵ h.A ?؈";7:;88ҵF!(pe!(!I$;&1ޝu;%/}ҔE!(`u$3LWvL;:PpĄT9'^.^Uc5YEP,HHJ'D-&mzZ8:%$$2Ԅ967[f[u``dJ$.BɁ?" X1c-iTbٵi;Ȥ5EԩEBQ$10" X1c%k1~me1\CTYBQ@@b`38w&烍䵬ץ9:hJ%!!b$"11ks~󦓤QB`,BIS& vA٘. SBE!(G${ܽdLkR o7c}{늦 E!(b~ͮokMv]̒Iqɏ3Wa5rzӰB2#)* rLN͌`o2N1Zi*zӰJ2#pAI~N˷o;i?54xB_?~_{{zK:=ߧW[׍J$6 ) R:$ 9nmoi/w; fN;ݸok*HIU>av9o{a~ШzBcxsOJCCzZti~?^@z=Azk^҇6-kZ9ۃzӻC Šd2Y&L2{SCjs^¸kC-z,L(!I|twSIZZsP I`ʓ+]&Wc:|78t}&c ,.M1~8ڷ@\HdPu PCcdܻSyDDL rwNrd&jQ}x5DĢTBBQ!3DB3:9]y#}ptUt2( Q \wwvalXG(Q·/Zh֍ZBA(r N; b)AQb:z-Q!b "BSI@̀ ` k^%3q]k{1* (D2$&GvL1,|kqw-uƮ 2,@IQ,`ՕMצRKap^zsMFU 0X%HJ$$N,\ȥ9n[L\ܬstF%Tx<6k8v4:"H:0te*.`0c VSvKW,s֜ʑJ$X0)Ab"A ΢ 8RzJE(\@J!BTfeL18J_zWvdJQt f wvaI<cgyeKEd.HwJk畎-έxB ,) ۴ ŭgnݍVh(ed`%UM(PI b!UBiB+-kRfH/h(a U&RaIwq kܴoo%l *`$?9ʒd""s^Zm|.tJQ9{J:wtb,!P/΅z>)[#*˥F CG;Br.զr=kDv•UL,J32LBl9回ojW} i(7) )N0&Z+G,VԽuA2&1!B$?3{ug9JѹNy7~:ֵm#NBa1e(rI$&~ߺYkZָovֻkL#ta\c.193L{[{S}PV4! 9U "s93+*GǵkskVrƄ"@aBgdLl$3 N8:2^ȡ HRI)+w|fb#+]9 ӜȤu*TJiNCw28=k-yf-m}3N(H((?u*f;33vKSl^psFSJ0qHA ,f_?<^+jd\CP],RADCb.ZԧD[\0`5RW ?Miq a\:#Zvz'jsN-V t@XLJ!I0+/$V E+ HA'$ûb&"[zkZQ 0r 2u!aaJc^2H8:% WN0)Sr;1 lU23R]p”JdHH@+Rg23c/sZݬVy'j|qwgu(ȀXR`T 0c '\ztvt ESPrQaaIiSqa]]j%NNBBߛ~C9˰wv-w1;X:q7?A(]tWP1('21Zg&ld`#~o~ &2!L.\M8Rc~vkWy $X(R!Bӻ `8ڻo!ÄBvbr/g'kRs~ێ8rQ҄Q02bQ*8Jw0Xͫ9L*Sspq#ȠHHbū6^z҇F'y^)[cWEXp`(aC\kZeW(tbzgꕻ.CEJ *($$ӻ1`.Uy #2$UR\ t)ӻc.W#rA`* .diS0GBN7)ьscZ]F$CIRBQ*AI4 겳&hJ ͹'\׮qv8TPJrDI$@CbUsLw8㍴)"`"E$Τ$brkENS1ԋXDPu#c҄wBe"tJR2Qdə/5҄mMTB!LAbSfI0;:Q7]s[bQplRa Q($D fW.u˺4ij;.  ' (%D#8.^/|ƵZj{k7]q2,"J.H:uaH\kZֱii]_zԬֵ9)g%E]uVb,حi}Ɗ"` ܔ:u! O|̨PDCrUjT8:[D-!XLA8]^ ГZ\"Q 達V PHJ .{SK[MgH:YIU #,0/r`ZQS{Yޥ4n`2.Ȑ,L,,X\/{%{޴Ms{E]E(NX .׵ZVp>S֍Ya@I$M8̙3^79d6mEa#,) $A28 W(MX▍BS: Rd2;bJ= 9ŧ΋"ʴuV JHvd1 .{Zxێ҈pU )D R(,\ܼza6ޭD8l*0AlcrҔMXG]sc]$00$RB`Q`rĽ)N[q~KcY+"l )$ 1rZIͭśiQBr &XPLC˖@=7jWu]%&\A0BϒIRfLi.^Ft]B(V:pD0BkZI,Z DrRNA e,VL1FTe/6-:nLB:V)L^b)EJ1M64i+)dģe  Pr{+H*Ncmv0mpB]' (DFRH6,VMr,boޛ\"t0L%PJvfX1{SZ6vBE( TJ` т.WJUJbkwBE tJ$BI?f0`u{"qf^3dNʐ$0`09*Rcܲ=yc\կPXVĒAزňjÎ^pEH!TA?{&+װ°X9X IK00abjS:|u~npa( $èf&룡ί͸MpA ̤r%O˺^/rgq)⪺B2-Ռ"QI)&a^,Z,1N'c[ӥ֎[*@0{ՠ(Z ^ Qu'F 3 c ֣A];-[pJ(rHBu Hc `!R8*j^MH pl,+rT1.u0G]BuMfv} $[2wIQAZԧDb'h.逕pHJdĦ$2fIH|zi'h.逕pJQ%4C8<ÿQjuLDpl#a`(u Q*W~w9̒I8=sM-0:6E\']*W"L0׽ Vc; (p`0PJTL ^w-Zձ1 "e*,.9 РfeL!DA\7c *@:,!`*IRS2D8/Sv8|(82` $T8:d&kXs7="*Y00T *Hqqb0qLoX- a0A ) Fo}5'BU AԎ` W) 6΄@B6TBBă)$8[]5rsnp2FAQqӡ33$Dc [sz'T%DRe B3*Bfe1&CqϠK鯨}S#QQSP}]a'3ˮ]a]٣GjvnC?B+#G;ý?b]x:/0H4 1⇌95 y y+^Yvyk;kߗx0b6j2hOK˻3r:r G2]|b=es*;lp[ܧ_U| \ H6PZw;+#YgtJOwsNū5kT/UQ8>/\ض f)V#?)8[)R^\,ͪ.Շ"w W <$˗z[uD멮Zzjfs){29HSXM/gǬ-/c<7C^yhY+[{:B!gME =KQ)U%+վէE*$6hƤy#1YUg1kWa^JlZNxS'xzO,AnטM5PdMJj*Z؜ <ζ$hM/_N깼[ΜDy Fm7&wEս:R}Ez?Qr9):ԏoz`YL-jէ,zt u*To>*Oߍ. ս^+5ѝϪ^n+->zttBlt&QNg-Wd[VAꗔW@hGx.}Qnlkh?(!AUAG>r P形hD~2aZi=a=(yﭫJRߓSƸ sӋP>Ⱆk'V.:ܽhƝTԪ_&P]S 1/@ϏQ{(]+}WȯV[ũd7U鲗MO>ݜ5y5V&)\9uj? A۪櫝NsSpgu㪯x<].y~ٻN>zk~bM1ל}Ͽ{ݣ WS}Fk}a[zȔךNjwߌML+/qSK[x>>sOʿ_{zwUZ 9]nWmOW_Q}шX0t«B(M|Zmw}_5 wwh9z)kvky5Ptw[sVy1yE;SMy(yן͕IFWo>vg>^哽] O~u^~$,L >fm-___=z׺c YתW:zȚW&x>OZx{^M9Q@n% 1ooTkW}?_P\RF/Zյ{y{4(  M|#~=H]x 4ՓOgtsn~sL˥ w7~|Of>r:+7={Yv,in/o*ru}9U1\əKfxko$~\cIf%x՗㧊؋#%\ӻ|V1Q뜙79U 0+SS\^$9a'h 4 M BQQz;^a6];)R(wwbOLp,3hHTQGiTgh PGy(肞2fڡqVPH8䕨l@pO{UZJE?uoK6\l1%w$3~&pT5S^3,'}e6d%YW7F{؆VAn']IXecԍũӘ AEgF08(q5ԐfQQD\sm(3QV^s4Gs-)v Da\r;L/lx*ޢ\iJύ'  i@}h ԉzrzɽDq]bFVj3[{J'PG|vd38[eZU=vC<ҠM|BfDIEM\rl ㈆m4h 5"CFW3L[{gw|RvdvvǑߧaYmצ n:gzVy[y7&|r B˩=XЂ  ԋqjJp(IM]OdJIyӚhnOYr;twcIr;jeꤿUVp1SqWUFVm^A ӥcʢ Xzw%)Jhyԡ7zta9KF֝eu*rXPnMd`}ԼjHe4E➥xvKR[r~ }9gWy/v;iyl~2疑)y"bh.|uXy?:57>ܿU\ϛW:21?ډ|q"\hQ_x_\A/ |~i^5f#kǕZ^seCyܽD{3\ڸ&Ttk߿g1{lc}ׯ|}q; U+_cbY+0T뺝rrwmNy~Ogx8Pp^|rz眥➳N/^ =/Ssnz^a]waN[uvhϾWz=ݎ9|67N_E&xhٿ^%k>-`RH^Eg'^$~n}R|ꮐ* +Gܯ>_ }s-zk7ף>ߝfM p5 DIҪSCoj9%]LoH>+}y'TEt4>.hm 4 K%dn?B?B6ۭۛr*p U *Cxy%Kxxo ުP;]~A;;;]cصE**V⨪*.J+v˲T н B`L BPrZY* 4a Cb,CF"1* $DP K&v>9O:C⮂2L|s1TC'ϞO'y<>|||ϜN'f͛6l٤lٳp0000 /_0*իVa0L.˲.˲..nnnnK(qr[{{[[[[[^3p8g ՚,;;;;;;;;5f l՘YfYfvug,ggpvw\oߛߛ[_E[\\ppQUvvvu EQTQTVjUjT*P[uP*EQ\%rTUҺWWWAtEwwvڻQEz^&L0L&&L&(ɑE~~_Q`,DQEaaxxxxhFXfbf`# DDE0ч|AEXxxxxxq!M&IZN'ٵ 8'q5MU*N8N'MST5M&Q5f͛6li6lMDiPM Db U КBhM&fyܴr9g-.Z\r-rYXr|_,9a\9g,~~r30LL1LS a0&ɓz^^WzzUYDLFq_pg`_~_1LS a0;:/W;;`, 0 0 /~L`"*Ia0L& dɓ&L/L/Kz˲.Y^ΘL&L)&LYʠT 0000/__ ~/W"#0!D,00<<<<3 Xk a3 ÉD10 0Xk 03 a<<50<<0 <<0 5F"Ċ,LLE111"1 LLLLC "1 E3 a53 "1b,CDQ)q11 CIjf!D)t(|y>:1ю8c>>:Xcutc8cXb☦*X)Tb(bOJ|<'z'Ϟzy<<'x螉<'<'zNBq8:p q8q8)pN ȜӧN'>y<)N'U===xO >|zC'|zz'xO =O<'|z>xTF*1qqqqLSb\\UC*U,sU2L$2C$2C%99EZHFP@eFB2 2\e#(2, (222BC)e,(2++(2(*PE>O>>>>}:()H2(YK(2*tN*ՠ*A@TAPT    AP@("TP( @*P  @(P( P( **1f,Ř 1 Y BP ** PAAAPT(P@PEPTP@(APTA(U(UEQF$%UUQEQDQ(PPTD讈"ѪU("(* @P(P* P APT(P@(PT P@P @T@PTP(Bf#1`fbYP(APTP @(APAPTBP ]@dBUUUe@ePK)eFRYK)eee,eK)eeePeFRYFQRYYFR2Qe )*StO>>_G>}}>_AC}>}G_K}/}E_IK}/}C}}>ڀP @(  PPJ%TRTR E"R %DBDQ!a!PT$$* ! !Q !!E!!!!D(Yk-ee,2,2̳,2,2-bUPT! !PQ !P ,Yk//-e,*HBBBU T*!R!R %J*T%HRT$R HE"*JBQ *%Q(*(B(Q !D(HHBT! !D$$(BBBPBQ 0T$$((E!!PHHHHBE PBT*BBQ $*UUTBQTUQEUTUEIR B*AH)*JD*"Q((J4hJ%J)QJFDQ(FQ !D(J%D4hJ(4LTT RT%J%IRT*TIRT"IRTE*TJ*AH)E"HHR) HYDAQ"$RTR AH)*K9Ȋ( "%DQAQ(DDQDDDDDDDQAQAQ"!DADAD("DDDQDDD"QE"DH"J%"J$J %Q"$DDDDQ(rQ(AD"DHQEQEDDDDD(UUU cv]cvvvvv;PQ !DID(DDDJ%D(QAIRThEQTUF4hѣEQFEQTQEUEQTBQ(h !D((*(4h(UQQEEQEQJ*PaBa!! P BPBHHBT! PB(E !(BJB!"(RBB!!BB(Q !PT*! Br(J(*F"EQTQEJ%QEFDBBBPD*BT0*vuEQTJ%QDTUEEDQTUD(J%D HQAED"""DH"QEQ(DDJ%D(cv]ivvv]ivvv;uwy'O'yOɿ|<}y[ zXV4o+J1Y["5QWNON^)O>w.xu^.zub<z# ?]J>|k}635d|XV:/C\|;] a:ubczO- =M\xWM6gsVt2rW(xJ5^}n_u~fŴM/Ez]v?{zy>ξjvTw5%9.ip!s^4ǧeV]nbdq@{Tmsr5WJ{n5um>5\>]JNE u^xڽcʭELzrO-trVŌȯTۺ]Znw[xWe_~G5$zChUl(m9]jbr}}|?ϥIߥ]zE2mFt e۴j_ױզo/,jS:ݨ9H53mc5H8OMH"W [Po0:uqܞVEwW^):͕%v~u8ךFם\lAT;}DuG"Ducq!|'4|w_[ rϊۃ;\?^uWžU=[Ώhj]NPs'uprT{vܿYxex.(:{vU[hs:o_;AJڷ.-Vw,f2dfT^D5;k3l%û{TFHvSw2ڼk߷Яw=o﮼|ҾN*Gмmo^:ΧAw*M@nx[|ωjrS^^ADWE?Uf7Wt|O}}[?μL 6WWFxύՃ5)"8x܋}R@(+l9>{\|NO$y<_)e"A m2{WQUG1jogG G+ĄR7 Ƭ(P[tӧ,1MDe1[`Cl nMP]^Uߣ|725z˷:ׯȚh{U!3]"b(0; cߔ_Қ,YDZY**7ZiRe#G 4L&\)c'g=.R{(q[ªF))Q4U_PkږwMzQp?klb(y^f_Z"*TEܓ-{i"iPk owƙٔhy9/]hͻGH8&@UKtYx) j<3+u RC\6 CPP[% ,i8Dbu j˛Pɺj^RpݒS=_MK>߯|#d߿5mBeNOss0.OQ,&k\% n{yӯXgKǹk^y]WMrx3"k:u[y7产1ǹfS۝/-|N jK{~ k-W/]>7J D>~9y6YJJ]#uu9l{)ϵJwRgy]Mx꘮B\ƃK)bC <;gz\* G|>z<2]bYK++(2_#### 22<' ?1̿223'*իd*&Icϟ5=OON}9OyloK/K>C """,K|}v]. 蹹ך`l S#aţF[++"Ȳ,$Y#$,,+.Y6Kd ` `zZխ^WOT2a0, ] cr+TT1,ljKĪU5vı'NKb,IөR86Fl1V*R6 ` akƸK^_q1quƸkK ` X,\[X,Kzpk"#'Ϟ<,,il6""y<Chz'elH#e6Fț7al&lm38'N,+)im&MiaVVJm6Mi[#dl[ &&a6qMSTieeTdY9YYYYYYYEӧmY+%ee:t9N[n7pn79n[%IO'n[u7Fu7Fu>|=o nѝnnX)V{td{{o7xHo2Lw&I7}[哓JJ !8 D*fY3CBCqW8g 8a¡\^/ 5P \U8 C¡VoooonkkjZP8(qx^/^) HK[[Ujmx"\^.r3).))*K8ZTk|>jU\^.vtVDDE8J%ooSrUrqcq1q2q#qUjB8^/g ,;;;308|38++3 p0Cqq8fCCq8%(qq8CPqq8@#;:д- Bд--308\. (8<AP\N'8q8N'DZZZZp8\.8\..8\. %tWD8Άд--- BZ(a- EhA. \3BC hggQl[EZZQ(ִh۫ugn[\\+qqmmV[Vűmmfl[űll[Ų `3K... Ե-mx̵̫W3Kunrܷ-UVԵ-mmKRԵ3C4-պY778뎸\l[[f[[űl[űlb--ض3LV- ՚V[+` kkbZ+KL0E- B331f+KL[TZ1f+{rܷ-rܷ)n1\e\eH)ȮEssrUʹW77%r\n7QTW\enսD\\\gűl[ŵ+zE#q7UʥK9g+ Wj.J^zK(­[_a0L1LS0&zT/|T**^*B/||/////// /J9!I9'$䜕||Bzz^^U*L0L& @~~_ߗɓŝ~~~_~_E`@圳˩S 00 3 05s`sTj檅Csw;sw:lib!UbbbbaXK a, 0%#`X+0L0LR9G)DD`Enaryi1aa0L&&U*ߔX& `rWx^x^^^^^^#Sx^yyx^^^^+xx^^^^+x^^x^^x^+^#r9\S.j.7q՚K4:98Vj|՚>>Y>).B 9B.B,뻻 WawwP*z^* ~TQ9k圳r_/k˩S0# ,#XJP*jL㞹랹?3{PSn=)-":ljnfI(eI62+5=.~|RꞺw áAB9^?9uK멯'=(UAWnjOGk:.!TTCM>ρNS~}n ^jGz]8s徽_<Ԯ+~;:y";% +Qy!/8eLn4vurʕ.g3jr7}w}]w^WK-n;@?=uѕO֟VIwYVКʮrf&oϪ9ߞw8r/yn㗩y뫺W^r +q ӹN,^Xd~t_/|Jk7}/>!4#b3̺.x7לƎg!:9Hy[D9>rZ`,9g-㨎Ux+2닒,'<=']Y}Fo+L^IVn'QG~;U~G}|xu=v+ᵕj1ZrO2U<pR#dTrkUٕhn J:Kii<<ݓ i^8cww5KKm[<6_p}ט9״ZemDlckgvU˒C*[gD6&&bNڧ4TzWSs(҇z(|z4OP*:mQ׵ۚQ >~C׏G^*z)f>½/uoϞg"}.'n0_G|wlT!mt@ӆh_Vl͒V_J]zػ:ZKgXΕRl(5EFm;U2^N9uȈXzڻb_v3=4Y.coqǯrwۮӱ4 2$z19NC0uJӤZrqg9=H'jj*2[^F^bd-ᒌ1Kj!t7wߵw=|:nsg<瞥/"kgY<}bY z߿;t_-f"6|}D gtgQs}z<=z<_=5fáU&{nؚ]/~;/ {{uu~ck|uF}o7ee~j1NWr?'?O3v˶|>?Ӳ,e/C<|;>><++}o3_o;o1OYuJl~߫:]bά: ^WgLlt |׵9óLN?/彽Nǹ;,lw뛛;O,⿊;N˲.O0al.; ;9džk,"t˲m{,,?_{n۶;K,K~olwF]؆!jZ}7#dae~x^dYXۛso>zZԩUU\n65asZ[GZZ5Uj둮F]\+Qz>}WG]jYڭT0FW5e֬՚Vjsazޯz9q\66>}Wn֚mb\XXX\ϟ>}bX%bXbX%ccVVjV^.-`X.Yk5a=c?𾾾k|e|kV__z,5_JIl[-el6E afn fv]k]6f6z'DmӚmSjmvSjmy͎ǣz&ٛ3fTSjmvm{3flv3ff͛mclmclP6clfv]*6 lm-6 ͎c{ǰ{Ǯz8J{'?fYk5a^%{'ccWiR->=R6ۛsnm}I-''''=;;rnOhYks2ٻYclBB{G{A{^vvܛclev]lg6flg6fg͙g=vvk2VJ2K%d#$*n;Ym2̳//r+/,-߷~߷ٹMɹw>׵VڛSjmvPچڛSjmvSjmvX=llg}Sv+bqv&1LSqqqLS^cSkڛS==1qw;nCrnMɹ7;7&SwݛwTnX8c9owzoVowzoM7ޛxc{ٻ1spn 77YO'}Mi>}}qEu[żUjtnѸbt}N8m͹8[-5xk_N'vM[ChEeedY+"Ȳ $m N' alkԊD=OuO'uXk5e"ZՋ6X-lFlhqvMҕ-W=b ^*^DZ{QTX)8)6;lCc:t&͛7k;!=] bXXOaa6mXV66%b!4g,:val6 .rkvv]ky4m4hhsw+r+r+r;hhkyٻ7;rnMsjM7hG??OW;Ĉsp8YٖeYB\.8%"ZZZZZZc,emmcqqpttuG=e\T\%"uuuutt]]]EҺWWWEuuH㔊GpI\¸WiihZ- BдE-Vд-------E--- BZ+AZ д-- BpLSJ. pN pLsiRvv|?}w}oc)V[MNM:{ChXXXXj~zgb>>O-:}og^^y|?z+8>z4f?jFMGJ_|L#Фm yU5nݯ^7~s55߰)0l1v*BTv^(JGIRxoמ_u׭=CG%7%ҕ|_|sܪm/sܸ{}dnS}E},\ __oMPjWjGjM"EVUV&kuŽsv,Sݎ|ɬdCcAV Nyy5bjNۡ;-wƖ(~kH?Q0IE ߻z`תׯ9@^HTzۻiCV0Nbt٧r^<^<^=%}OB>}/UOԔ}>XscVL6Fj?Ӆp}ܬ>/C[/+}N?E~_/|_?'^]zz&./ydy:w"Q/-O =?OzyeQvw70kkvEggv[$&uY9>>47>I6nav_3t7MXGduEM>y]3WW7?naW_G5֏Gzϴ}C f}mQ|瞷ޝwu3isz޷o7Ozw}ύU[})RR=o}˫s}s-iƿ}gi4NwCk511>z}#DhG>hw߻J(7#drQo>e^NNz J6V_?yd_/5Ƹ{=[םyyך^gl6lh4@h4`qݯkڝooveggYun_u k]dիFy~5Fjdfꞩ)wqvݧivivcoov;NNð;ð111;|XiR;Ka=c.n{2R7;;;;;o^D^x>x5_ѣ?gu?gy~n[~~cqcZkNJ4ms;-KR|qq{;.;HNvLR}jqqt&qq}vdS?w?q2f>{zx>|wn^^}M7Ktn< nT7<3<3<2y?x^{*M.GZ-RZ=4a4Fvvh֏GV Š)R~K> <+22qJ'~wwzG]e7Dޏ螇~_x<ɘڍFPx^t*cc`yFXgyagaiifWz^1jMI]gy瞼yVyvy^Wx6Mim6KҜcx'[[[[x't:M)iM){t4M&{O4M&E#{O'}ww}w =ޝ{w[z~vivE{{Oq]/g_YY^gP<1R=c]/]Vɩ&9XsMzҲ=aF>cw=ſ?]yW2ӏUkz~.yڟ8/|x{*wtJLꙇ|'R}}]|}~U;ڼ=ZkTUxv˱Q7kխCxǺ{׫{|l6+ygYffl{K.{=z޿wlٿt?OمbUt?ޣ<4M}_{{Bo7;zur\[}Obݗeg4)⛍;^߷7Mm6dZ>yop|?Owq/K~NOxؖ%ZKd_[ky>ɝ}ݷ_EkOZs7~iaaF{{{o/S}/'}O}o>Io;w;:γ:~<,?a<'<'~.Y_yy~gz|;~-n["/^s&o1}~{ccםy5&xyzM^]Z=k͛+>}oo[c߭h4 ^]sccaag4@h AjZϳj|W?O'&\>3ӳx 9bK||> E"Û͊-A(auo[֝i[[vYpx9&Icaa ccccE }}su*\vay?<}./Cg>l6ԩrM6]flϳ>vkz:v=cz zw]vuw]quw]uu~v3<NOz 9|tkkkmV;=3{ 8|>˲.˲=K2öNӴ,/K?n۶;b;ðS1NӴ;N8kg8kN'N&]q8~կOlBF| wq{553mʤ8Gz{sKrx8}}>׏<ԬW}e}}s}y%/#ߟ7o_IƌGG~ut+y^M>:&No9-oszt oǯC>Sp˙Y'o<̡9t*a>}|>/|xLJ=D1ݣ8"5Oyպtp(ILϟS7Ǐ k]"TvɃ#I)d KjCCoFk:}7|q~.O'5:w3RjO+OS?R~,/=o?33336; Wy_ˡC>}moUv:}mu}^S?K:m7ui1NO} æ鹼jZGNtkߛ?'MnynIiigfZZZ?t/K}wq9?z?G 2gW4>q8&q8ƣQ~?}蚍Ggl~oͰrWC} S>ߛ߭߻{_aZv{?#?~z^=?Μ˰;î: .?K/[z]*ҮDZ󱱱Gnj5W~tSk핗M>} Q6ߣPuGTly~xO{.Hi>Mٻ:mmh- Cϲ{%dzcvM6;3f>y#Ю"?*KIn{a{/ݕ/~_辷vgngxΞ>^.S{ߣe|o=vm}}}ҟڔ蛬jj$mϣ_G={kׯt`92:B]MG,?׿|*L#ǐ۲j_qxj>'}w#k>'mzwԩB|lo#>?sjO{_x8=WU}wkaa}_Wi{jOsw{g3##w}DZy>YYwxx>OS>gɜ>m6}oݷm=OS5'&&se{?uߍ~ѭ6KWUfٿ;]uw}_W{zԩuu>~Y:\gkuz޷Pa~N] /n6!bbjZW|_xx}o[?3M'lM~}t7GswO/Tm^鷻koĪnlm?龯VWhfUkUڬ߿޺no2}|g_ÿtn|^gk=zg~NB~ZʖuWv~mvg/?9߽}{]w]kkzOf-~Gq,j{?n?_[/q~DZ{.OyKkg[ >!T>'lmm|}?O>xwGzoؼ=|j:겋_ YnRRZW_3~Pӯ?~3~_3>?UY^vҫRj}v}M^Q>?{\7o7h(P{_~?> M]x?p8uNfe=k:EQm6h;OLg޶NO4y~~_k}<6o7_ o퇌FyzUgy$bW_^_Vݤ~ײ:m*Z]FIUq-Յec1ȁU+YXnsqǷRwj5f-_/ț7~/h;~3;|&La<ϱ:Y_u_>f2>ğoȃhjҾ;_5.kwgg>wի>Fkk_ƚh|/7?1տ4}+ROjHjOFxv3:Xϸ̒DQz>ew}u'3>'OW#Vmdy-|^r9|h?ǤF]7IcHs|'?_c6w~mnȔrDV5>oI"zBOK^%=r |h# E$SZąτn?99F>#c:{N-r>~{ӤQ,c֯Nk$R%B^<>~mSjTqe7FeG*^u,Z򉭿WIN_^[.q1pOϘ/~u:߇R2`bJBx=wOvHE)a>'[e x5t!?q|{Ƭi[jG@jb]UŔU2w UT]w>zG Sv&NIR jGl-P3N~{kh]{7sνi'G^NvHۮ6!Wpm[-d4[~''2lDC +T0O1kԎ[W|TX┪n*꣧SɺXvrQm2 5)^5Kn{Vcݧ㐝HwL@]\EY˚#*V|̾64akޭDRw5N[ods.F {ަF fkT_ڰv};mcC(*kQt SEs6Ѽԙ5>EfyuOͺb" 9CTy,6X&mɗ;OmQF5Fi[3 -`R80IUXlZ<A풧&`""*éR_gֽ%MYqJiRQ=g9Py3!_F2z醦׭-=Zo +RquQgg&ADN춧W^Jsr-QՈ ϞVk6WN>y(<MSKm=Jk|@_ hI>{' +u"6uP 5_+InCtFwO<Ol]P3;wU\oY/|[_v Y&Бɜre*&e֨AUTw9)bEcAβw~Itd+be'7%ݓDOmbh%][YziA Q}z}w7hgjuݼ[uE- T7խ"{~xOֽ1s֤߱C#|c^)|j-KeQh{>7}}Tꦑ/]96Bp_gDrRJ;{Ӱ5;z٣eeN-|>[/}qǺn7[/|h*SWO-eSfBbd]+nj TQ5ЧņWoWܹ[(mN3g7[Ǯ<5fmWUeʫ[(');tS>Vz7\ݨs|žUɹ hne\vdS:\>=o]k}yǯѥõ%~^3?k}HG`ۇEEB~-ڷ{ ʒ*vfU-UmsPux.ywJ9޹{]Վ}jqvׂrES:Ʒfηb߿W i7؜k6 Z=tn(Tm@QPpbkY&LsLV+ZMQeSVjbn'LIX]Uʅ/g|Mr[QèRδyf UI}lo;n]Ki5UCdCV9k-̻^_QZx䳱f:G K^%n=Sfnk*uRd8T\8CU}kYIҺR\٩MfJ7t6T TR G_U9MV'm0lJ*fj鬷LReR 0eҔ Aۛ!]jui$wUc)k2_[uuZxeSu&tn×{ dbw 85),ABAI칲Up/WлmF3_T$!"HB hmZ1&E{jשODkr&`E\s&٬BLB喝)' Mt!hOz۩{ZVP P5Sil{7ϬuA[5^v1a1>_,Pw/\EpC[Vl Tsyb&w6,[OuW]t#\&Ml\Ah_9%=ojxxP7gbtqy}MZ!DuSy⳾ڪi^Mgl&buMkn#;DB"nGrr㢐hу ]3WcQ'7ȶ$ҲtՖrhP>Rj:qa_/[$yRE%\>OT>r0q>!s5+W:vr\ˮHP j޶3GSӿop g{^󕕔ߍs|[RḼn^gB,B` ]TNiڴa:i9=+7cQ"GgwqwۻYX{:γo)DN(emw:[0Sk2/7!~ ]}WeQOgl}d[֗^ր6HLq_ ۻqz9ɭɭ7n/V1zW msUbaMKOZPl*nEXPy3()q:}?h^v oBӐE@u\3!B9jn\8γUEW"vf_WnJSy|[˗WϗSMbt"~]XU^`};UPik*=*/MihkfIu#)Î.v'&J0^ *+J3lQ~׵ y)eTnf[9ގegj-nNPS:Tc{yڶsE3B 3^9;_tE^ jxpֲn[)Fk*1665}9Y8}]VLZ(Ӟ(M0QdKPG8ȣwCZ:5r7}M-}د`qTy+P԰U֢_l[;wLAbV51r*Qh8TځQ5mRk!䂓S p׮sݵ(|ceO=MJ2KQQ>OXT$/U*=2.!"(38NlۤH[{YǶPYإaX}e{1[qW0G6nv'`N;9-̋DT|wmַiZZM^+XfUqiu,bHB7k3IbHO)?foon3xH>DBGꞿ-Ӕ$*1 V-Jb(XP<ױ.o# 2ݴؤoցzoϬ:_;^ߏG?/]\K^jT5B@%қڍn)(4%gnzX-i~%[%FGI}Ӑ RrR'>sOD-=Ԟ{sMR9O/ڳK+ "j`Q@cEt:\r6ڜ#uMϻR`RA,^:,Yf>CМ͞ԢIr-ډƿ=ߗ7&ʥcN:U0TCWmSUvFECnT%{QfskuFn/̦<^Pע;)A UW6QobLMQ鋋#|n5(6k1sv<>ʯZ_/e]9T - z&õtQV:!GZiV"y$%m&i|GPpy!-+)PvDV_^8i#fm5B[|RCǐem wJWvkqGg,0rҿQ _S;*k^^-51:ۏ9J#7,@IXr T<(4-5ukN: y X~mCkAP¼]ӌJ›N&Vu-Qu%"/3}Sy;&=̫RfS[o.ĘCl=zxφ=Cu)ȰEjr&ݺ9}O9E=Ne1j{%}XӸH(o+׽ݞ[˓#ݶ8&|]j݅*gAs A> r \'jZZUb0FJB((&4麙~_TH$c:~'ʻU|^Rw .~ԲӨmcл^,{:N\@?,_?/K_j񽙾:n>7%ὪD>߽]{msr`|);7ƚ^vvU9hb~cWlx`߈,=x]ZNJn~=뺥5:˕׮TAUh׬84gMU{nOի3eo{~e [M9ϙf*6)HBӸ񪯁;cuc1M}~w[-q "z޶RfO{:ۅ;KIik^}_/۪_xܹܟQ~BTxKǎt]r)3֗z]5а[{m=>+(7b$kص]P,@>E77Cs|鮚UHh3_f\0RRmS׃w~jzz;ۓs;Q{/HuEq!d_'/[]ATg'kJ8u[/RzUo Ean}ןMaŮx AFR-.͋k﮸ ~4eyYj뿧Q_7Mu}7u"]꺫VnRwώۤiR[4XR%m${]̼{ߏf ɋQoQ+u:b=y=So5q QVBOQUQ^5Q'{oe}tz۳g-B)Zڣ+U ϟР_GlF7_Q|[omѤ >)QQ4oKv5FޅmNNLVjJ/LB2#b꺊 pE:BJ?^ku綽~krr}MB6r9J\].+9IwV\TnG\{NFìD3 ݿsrNXkf*oSLViv/~tcuJS>=Tg.Ng*e&ׁY@z}:m(9WRuΕI=Mo5%,{Qm߿;]WuTEl[uY%z0D_]5<u:7αz}}׍W;pJO?T<> pfq]y6Ҷo}?]s+{nY i)U| ubzЋ6*56ki *8nu)Ҕ{e*x* bJ/S?Wd***iE')ژmOQGsL*Gj:MLML?xJDdfOGd%fyEh`!x#I"ɒI(Oޓ"~迖_H"O0(?S+4F,֧/"TČ"fZ>gO$bOD&?IN$~a#qD"A88+M8#H=ăIRHpDt@TG4zGcYi#-$PB(!"B3$# BB=?~~I_$ۡBFP]4HM#oP${EsqNx;_I4Ӛ II"H <Ir'{݆_')!BE B0B+hB-A BbG'gi1:é 9'(PP#B2P@J@ЉRG9$WTTO+zE HDHDHE@E@FjHBBFd$o!Y mOʦݵ>̔2pYCTjpԓJO?"~vh?"wp&Qh[FѴmM'*5FѱlZ-Ql&ڛ&ɴmlSji4l&Ѵj5M&ѴjZɲmFjɲmMj5Sjl&ɲh[&ɵ6ɲl&Im[VImFɲj5lFѨl&ѴmMm&ɪjl&ڛSjl&ɲl&ڛ ɲmFUi4FѲlFѡhhl[&ɪjmFɲmFյmFQi4M&Imj5FѪj&ɤmFQmSjhZM&8$劆2EdfU*02Y2@NLeX',+ 1+Rr)3 HS2)fVCRrc0ʪS,R0Y,*)ŒʀɁ9 *rrNIl&ImFѲl&ɲl amFImFѴmFQjFѤj[FѨj5FѴj5Sjl6 amVաmFѰhhj5&ɰi4VժjM&QmM&Ѵl6VQjFѡm[ ɲhhjamFImFѰi4FѨj5M&QlFѰhhj5 Ѵj5M&Ѵl6FɲmFUi4Fѵm[ amFɲl6M&Ѵl6&ɴm IjImZj5lK).Y*2XNJ3fIK'B̑+'±XID1Y\XfUb)VeT.1K f"fXbDU ,9e 2,ĥ,1YfUIE X2a3 \̪LVeJVC.eRL¢e\Kb3$FUΙe,RLSTJFUuarrrQ:pìG'Y\faqte82Gnj㩁ccΆ:uqQααCc c#X1ã#FGUért,'Lrue9:d:ruerues:artb:1\:YW.]:b8trd]2\]2]2X\X\̘\̘\]X.WGGp.brrr2r2p'que\e\e\LS)ՃL,bpæ''VS)KYYaaS#G..L..\]L.G..c,Uq!љp3*æ+X+X+)c)ìS'YNuY.uY..VKLN.Sa⸮xSaS)Ք%æKYNfe8:dptf.0:W'S*ue9]eNYNYNubsFKFKF.WS1c#KKXc#Xc# XG]YN]YN.VS.:d2.ъ3 X.fX\:̰tp**rtdt %Ւ)æS 0Θeu1tՕrʸddufX8ufX9:29:29uˬ.]X]X....pdte9te8:2Ntʿ.W(Tᒕ L!lZFImVal&aj5FѴjZM&ai4FѴhhj5FUjVաl&amFIj&ɨhhm[Vյm[VQj5 ij5FѲhhj[-Qj5Z[Vմm imZZ[Vհm[VQmFѴlZVհl6-յm[Val6VѴi4Fѡj[&ɪmFյj5 ѴhhhhjZFQmVաm[VѴl6VQmFehhm[VQrrUr1 ɘ&K!p8CCa6VKKjڴM jڶCCh6 -- hlal5hi6h6ajMjj6jڴ46U6--CCIj6QڶjjajIj46[-jjZaj5446Ul jڴ46MjjZUm5ZVaڶQl5CCh5Vh446al6 VIj45ZKKjڶMCCQlN#9+ UU*,ArfKAF*f&*d& aLRSdQNc1S)̦1H))qfeR\a`s1,\%G!6 VUl jj6h6ajZUj6Maڶjl46 al5ZQ6jڶaj6 hlZhl45 Uj6Ul[-KKjڵVij6 d6Um5FCCeڶ FUl6MCCCCaڶFjڶMhl VKKaj5Fjl6-hڶVCCCCCam[VյmMCamZ-ѤmZ\*p_$!Y##"I0,*I+K23!`fVef%2ff3(d2U`s,Q!23*LʬJŜșS QfTJ0 b,C0N1$YRŗV1Y0,8Y̢ˌĪes,ʖaY!Έ̩3!Xtf2qQT̕( .+r.=+L'LL0qє xu⸮ONN8z29]bquNruNNqd*qノq:˔.ep+NWXrxru8Y]29:drt+W.rQdpbr#WLW*\W#G.N]2C䜏#Kp85C5$kAjCZ R4 h&H@-TR.`QH%H%`a;N`NdRJHR]`V DW$B@$z뎡XL:@Z*-`O2#*#*@HW0JrH[FIS5ԩDdR"2)Z^MֺC!,̛9u%euT r S$((IP ~&dPəjeHTʐ@%I טsʑ/^a+ , Pz!Ufb3$$R bQAbŀaDXQXTX!Gd !FZHQAfdu 2L/g _7p2.2, Ĵ3iY*H#*F0U J' *$1+ ^GXeZufQdDIYB 3D2J3 e`VJQU,"$P3*rfLʐ2&B\ )HHQjLQQjL\&W!ZR,Jf`W5Bo#9X0ƊbT+\5_{zՈje>y %v֙n33ZmUhVVr3%JΫگ>M0cבfGZl%v6 VvUr[`LB_~~^5~ǒDE;u2u7;Km˓$5-CɔOv-E֩Ԩ_o}+_+5RwY֊YC3:!-Lioמ)TR?xDž86|eqkI]wyweÿ镣~ ]7 1jŃK睎 x"SNo'QNczMs'>,~}{9_o~⊩G*Uw#UEL"yl&³UgU׵nEk Sm)$5_V>%ok2j&fb /X|?ev*xu9̊bs![Ҳ)$D'첾۔"Z`PĀh+jky8)T i~𿭗zy/,㬽Yu`TUJB2EڰY*`  d L2V[I ̅f-YZ *+RB@&HB&@E&BIRT*X)䕒H 0Z@,"-H3Kh̒@3!+ S"VȰE`#RTD(3҅fX,[I+V֬"j,Pi2?8sPRNcʂ%ưX,kX,uFJ"GI0$X(d-Qb()S4dlMfN.qfqqrpiE]@uvACPݰPP3 $*L‰0¹aXV.kV,Uy̞gfNs'|6<2VS9%"mHfŬ3%صI5hAm UTVEPEJI=3me Q]hWZ,sEMM*IQ BQऋऊb"֨DU@k' v'$%SSsAd;FRNed(袢 ecDC2UEPkdʊPڢ"eTʑ%TĆ£¬GDq(HXʕ"0j4 U@QcɺǬɭAr\X.KLͬ2 f%EQ3*( (E"X/^4feb2݄hC*C , dQC?'u3E'369[d֒ &dm vYRs%Iא(J=*WYDfm".Em" 7&|g3*eg3eE+ -ssϴ5u؟Inbynҧ>oޣ `V"QBb+@*W@uHkc2zɬ#1Akm'iڙ*];S"$,.*b4JK["ݾ0rJ{s $i*VUEQJbɑLb0ζuD֑}BEڙG+ R:*wffs3wvfdC[ j65n"fm@EGPL"ȥjfj)ZIeE&IeENI8$&.jJҋ]r,5Xd椁椆 L*TJNeD $&#+YXTa3aUfrVE%d^CQ͕TfQY^2:ŬC2 aQdG5̕KoM.V U͍.VəV 6uSk-bD9' h&alE$U'+IIAN2 k.bSd0**T;dCI L dFd**eC9 ebEAJE@m2o+ 2o+^k"1rk"2 *!UVXF"F$[*>&ms vuZH.VaXdJQeHD" {2@Ԭ*06aUT)!RԤcR2T3!X d "3%b0̣S.<2/W^>OZ}gg}}-IUOү>{EYΛ< Vv*2}2wS?;Ι<[hUA[er:~o_>>谟ZmoVj'^xI~5s{ "qJqK5Kzams]Y;׃fqT~8&A D:'|qL9֣b[jiBs$.@.QPܨ1B- ^oϯmh_$G H h]aPjw9quzTi Sظj2LOAX7}I1_Կ~mj!3~ǩ^FĊ?U!,Q1b_M_;;s. Qz C lJ&§M~?e^') ]6E.h~Rөo/.)u?wVvIs榨@{~4 P[{xU=a_4ؐ$SNu}ETlZB>7'Ar}';VVO2W0b5lR7PG\xowМb@V"-Tar>&(F."Շ9ojaFN"şRkg*_ |kk*r~Go.vL:4f I: F A_xB|[' o&ϊ5Uв 7l5TnKUy8N~&dD7_#_Kϧ|>Qw+>edhȭU Y;"?EpnTmF-9q$m'Ờqw}'>4[Ș-ޙnܪc:,&R9r&X_4bɆU';pFoo=G;Y5md|̣kq_%neE.=r|L˾hfGG"?jلH" bS`iFҶ*Jh47~kJTZFNIxfOQdᬭcͳSm&LGRmڳY?W,poZuSRub(u+JVN|f_VVc ~iױ11ݸb/p^Mh4=n5isv%#Yr2r)bnh㋙&aaU%$TEu57*,=VV# (oos;c9Y >$?xpJK$RI: A|] s!K/ :c@ P$Hy$ Xɓ3~˙*̜`VP$C0 3(d2' %AE l I fI!IR PTI!5@* g23$ 9ma̬C<G-$$}mXH{\h:BJjs !ݪÒ !>$ާ2,$INa99rfLsyb0F*L($+%d5ULG"US 0\¥XEIsrJF\ܒbRXQv0c ݔIݔIɐ^IX,PPZXV2<œ'!c**H,QTAb5'j G$ڭd'1Aa$ddګR]ĩWmJXjL5,2VjAZg$լ X,V*l L@ EeJes'ks+9Nb"<*w4DT̆JZVKJR,E`#+#*LB:I)P" R)mFEAQ9yY(s=?˧ǽZJmH²H\*A,*E"hdy'+%WɒpVWg&`橺r PmvjPmv{z<`SrC >?ega'0< a_3*ͨL T3DK *fMB( >Z14Ziy v mW0=|8P\p9iNvQ0RʼEŋ&y+{[y+*'(.c 8SlhFd] rVo>;!G.:8wvhk Cq|23YݑyI7Ik!+b XTB" b-3\bk µ (ߦ XYs#?Y? $@C9؇?gStM}a;"3cYX(~gb1OQ.2LϦ}!XAQȈ]fMO8)%v Q~;z|j%X44dF;%D^'繱+5h#^g6~4~M%<ƹq}NEEoR`EDfe~^vg"z7JNO]LaȡMd}T YDΝ93j~|MdhَV%fBKd4Aؓbh}o{/}|>a>ş^ttz1DU9V1"CUXa(F_d:΋'r&Es>{ {@ԨNIYFj(,2.@.QE%☊PN)J",Ԣ,WԫRMW. @LDLD{aMG5\ r=aX,D`]b"b" !b@8.J88,Aljy749">"ors9|=2*Ɇ2*J'հF MlBLDDE^DENH*Ebf0Zf0ZeLzh>>g%}9ͲϦ+l566uA^PucuV[.ۜ1'=ɕN{ {0Yx sRdMbԬ3Y0O[kd*A&E=aEXaQQyjqN rzU5lPU:u@;GXGY_3 =s9P^yMy_' m]nAuk-ӑ\Feu\Fd [#+5l+Mw gX,S>pQ2vpg(A)b$IDTIERATQRATTM!S^с]o=]޼^9yTsG3s3 X 6JX6#]ټY;6nvÙF`LDjbX#ZP>!UzPU{QŸ́QY( d :aX naXVE¥dX]G[5mTu5heg1KZ=y UfMf'uY:u\8 .P5䬕͜Ԭ[fqyuoҺ9_%Awl.e6r|\#C͵ 8kT Дn5ŽEZXޠ>KꁐUPUx$ji$) r5X$Ef`gZ,*{<ǩTk+G%vz*>>Ojت)`x+ r›؞ lNbj3'8͌sb=UgVT]a0 aagڲǩ׳jʋ {_9k69}+ r&JTb %JA`]^uV*8b"}~n[J/^ݢn JO0g۟ngaϴh?~7Ӷg6Yr*~~Z_޿'>triTQWzx'_/_-xK-/ρ~*?-gu~߷ץ=-] }GK_-K!g(B?ֿn8-| gfHTmFãjF!/_Ȅvoxaf0>}(|GWʏ`߶ϭ0S?_8Vb'tYU&)REgww{AN=ǒy'&qCɟW3!39Ƞ{(^}1kY׻g^u[I$LI2 Äa!/;PV0X.vJ5ݜsS2p׵8jd-EYF.k#8IV"%XN"MaUXsN+&hd [{u^v[{r$&ʳ !Iؕ 뛱* alY!E 5pQ{F1Q0LU:%Ìap%Xub "2V?5ϵX}.&IuUda^^DbԨ-Q%V\(\Z'1W*Y^aX f5  Nؘb/mHX"g{ B\Rk`e*6,=U&B7%LAbRrVsIZQQ|3T_5 ϼR(aHmTXL+jĻ)feO%I̩^j1"m58(',9rͥ$nHkT3f?[XV;aV d""l YacE-l, h kȪvR"((D"m0T`UE5i[@̂YO&ҋ&m1k`!Ů4cO"|g[ T 1dD92?^"'Yɨy'tGo:sP}nAq)x`ݏLJq-3+)/Zuu%BN~W[K4W[K9Ph[yZ.g<Ǭں_+gjmy8C7P߭1 ޡsQ>YۻC"Mgn MiLnhxƧkVqz=8q_!w]wOZ4t&maM㊍@S>\s󴟄DYr% G\ -uʬ 5ek O' 浃Ԝ3>|ޜ£"w Rj\U!\"*( Ҭkdql1W;F. Ѯ; @HdόmBVd ?a@bd2|A[DcMA[Dcl|IUd䝪'uaaX-/RӘs K&ONœ'R5j~jVs8JL(0iRzO07X ʓ*GSڭE+ϙOcvYs+1dUNy''<ۺ~Pu9hH,M"CZl+9U(_lesP{b7͟PZ!ϨUcedV>χ (kLe JYL88C֩:J=em9Qe L2,ڂF[2Qn AAޡit x^:U>W~{>GE|f~s>>ϩs?BumoPE2J;0ȳԻ]gQ$G:)}5uܐN;ҡW"xr6ӷn۱yן==MdI3U|~Hi녟dpbC+|#z |%z:>c'Iɵ՚<ؐGRUeD'f jw9s2iw92 9l3 &\\%J59 %!"",h'y`zRݚh^炏 <m'Wφ^x'䈨Z3+-1jBw$4S& p55\\:Ux=RtO[Y@PtѨaE {>%CXY\}Qr,{LujE] FgM4@`iEL)ƢEj,a +p[LͬrIY:\,ѡA?|I>hOb༩S~?c2u!X2f"Aߚg3ڞfI$oS!uaIu2G^fB;S7 X6jf!%)=@&,6)I ԭe| B%O[Y+~3>uBBWWO$'?>Y_>! ^(eAAB5*k* $jfYPk)edGQT\Phk-PB5BalfL0Xހ9d̋2VL/RwymyU9ocèN5{ P8(RjE>|dr(}*wvEUjvg5SksAOz.`j.oi s&rCYLnC5flv~q!ffeTfffUA[aNvY3ȍo@]?(bM'3/ Q$Ԋ,zEHCHRݸzG~1ߋF|O]Ϝf{֌2a'!XrC6yȵ{o<, 5("5zsd%TAB9knMyS9&(5 1Gl\%I$QJªgfRCսLK jAuS2tF{w*yuO4QL޳wP^k3SPyS媃欞jE5d̘|UG`mN:pw*-pzqEN@U/B*FЭJiW35u3>O}}z'}=h}gyxjn 4jjrD0u4QVM]}Nu8*E'\,^K9fo>'ؙ%/̗a^馤m,b,N?~n{Jb[aM2zm% 5"pݳwvnb+c6DuKTc4m\F!z>w9}w>~ߴ>Yn}_nG1dU&Ad@G)vϥ'\Y"E3{y89ޛ_NJaSw+|_мg | T ?g)YoKGNB@܈_y~%R,l\ϊɘrA3V^Pkխv*i!KO׮_w67U/U|6(2|%wdWnXi~"6AО^xEl:2 y[!a.kJ&'n4Da:+y*5u5"$STVuQ֓%H9ˑ"g/5 E\D5 uÃA?ZGD[>jع5y(IM;"bDy:Y6lQYu@*JO>h)>99}f*=!9@x᫬UB%9UEF"cNj'y)v2Thݲw{v5˻t (S'15mUfd3*|yPRebuʅJZvo=\}29y%^Rk2DUY*,($[f d9IG>}O?9{Uy}OG=îzs=SX HIBEBO7PP s O lIT!S|HI<'$5 '2|a$y'0I%I&I+@y!B$yI +ڮk G"+NQ*B ;+RrBJ  @{Ri_1$Ȉen#hbȉ5Ù!e]f-a$!$(`mI :ޭA3 ENf|cY 0QN`$a#ϽZ?;a Maf3.4P!;r X4Xߛd;V qk2HHN!9!!89JH-mW+Q+]fO TXrow}&|a'Φh* UNb#JI{OL:RKx.R-ӓz"q|@Z߉y,gco8R+PpDSlQ^0b"~3"*zrdTUNLjf-"V%˃, fSEOJF \؄%1,G:\g 0aϋ *+UT~onyZK37I{"'"!qp&~c~o|DR2 IaD7l*})׶\ 7<Nzy2533FsPu9X+? S_]$;Hi2ǮK>օ&3J-EznqO5bӭ5T'v wUju?ef4+}g>>ϻ>_.WY-[bSPfA=2 ZEfoy뮞uƑ"..j۝樣<>VLxYoFg'>4,VM njl}O%Z| 0cF*UDG쏯l+ ۻx*Yxݦ}ϯk_Z^>_ϮH٣;z_>>>=w2qB&kh5kR؃ߦzw:_zr-e~9N KwTSbѕߦZV`񇭭1 uGt(yÙh% AQE5NxB_r3յ4HPRKN?_ S}9Ä 2E΢䊱3C.EPZȥh2d;U0QH*s-bj1X"*]8nSWZRt` _lEE!AM*! 7cRT]p"dAsQT8H  m;"5P5*)ćU5: 2*<ڹvuY9vC"*E+YRbg,OS2HCW\s!_:>VT>zA "`>ϯh[JwsXT:ϚUgRxd;I )둠a 9!ͧ\QqͥdJZJLr|y1kRiQb֔g5 cBrfsX ~? Vz/_^~OkȗOKPPLgm5ƿr5&Ծ~`h_k>[3dx3;1)'^j 'VLWiWj3PAɅ3PA&;`rd'l'**ȡ^KȡXЪ0+%S SU턨zvNuڙNy s(E2dP2 eȳr TDE-NbG \`Sye19{˨V&C7 4{Sy3Sҕz>upEcXD!SҚj*y')U;T EYƭs[~R9݃\1;7,x-:x=d(gb*0sh|^*Eu 9RC$kv F]EBQE5tE5ͩO:y=+.r(ڱMdsꍘR}ղk]Kbe4iǮUhj5m?Z圜TOz999{u<(5ڙ$MR7rI$:dSƢ(K.6T˨kUE/$UwU`(4u0ne*WozԀ n ]%bqK]SqȎxnsrM8ث=VĶ*Vg|+\QuZ1V(z.{%X=E5+3DZ39!%#P\g[zL]gn]m9+.9+9E3n23kLDCh8IYqhpŨHV>Z)ȸ!XTQ4QG.,)םwO" 𬫅J_aB(m6 .|RW*m\x¦rru!cF&Bƚf:fD֕cPJlLʛe0gzo_3z5>s|ξo1]h:27cgI\$/whdNA &J݌1~4V/RG.kE)3~""*+!R"d/-EJ3" _Xqٳݮ=\Oq_Qf9)M֤lT!-YYW1d^L梍,Pmi쾜0X|t3U)eRO3 E!~`wYs|ĮՂΌx3^$v815zʨw߾ni)* -rkY\ǕƿK?/kx%|Kϯ`+w/@a!UqEh N9G!SഢES]}9XN'qߚWcM;v+YT!pSݺ\V-X]j0jj7Vi5F_,K%.kKKo_WjT=rE8L5Ϲ ;,u~<O[XOPŤ5 Z5?~~yi '@~]E>O4W]Ϲi,4+{׃i46 1p__.z@XIkQGP_+4Ԍ, k| *\D)2N{ZozȘfy Tw-EO_>4vRβ6~Nδ<:V֞箷2Yqs7h@Q}(/;dg1}.8Q=WHQ &dFԱ@EkL#0X+%Z.w`S2mQkk&LﳵѴδ,I֬+PF+5k9iQ&..k6iTQWly@a @L=ٔ*JQ>{=.buȰz3SRLAѶDv@v-ErsJʐ!;Ԝ"\_|~z Wga|U\TW!b/JGO;t 5#螆CYV5yy6ƓvlToz2_3W++9O5ڒ״F;ss+/[ )5LbgL,W׺g|ELooz(q:fJ;cx^fjdEĮI(6'2QZ,+9 mG'C: Cj/R@U8 >Rqs-Ndo/wT}zj-K팬;\ /ledTwW "wT†J>h汞hdփ܄+\Аi9 W)s@M-eM*jGM<3rfs59;|V=5ghR45!h! E:5T%dOE[Ssq=kuMѮmh6gzVu 8L5#w \fڎvSh^Y;_{Wf?=BTn #Y^_"dk+y4Cs2% Tk ոyႪa[D͝mqsfQEKmn룱cRVNsۙ3==ے[SĹGMphI{*}Vr|yۇ+PykYD;kY3B+؊n;)[jn m9p}n ju7Պ`jo7!MqI5,睶:Oi^T9WoWΩpa9w.L㇆m/NIϝn=y9km9G'3k݄p92!U]RԺp~& 7r xUUr`Q{uUb:Pnݩ׫bKv6?m =XhUyC"UɑyzÉspXYeryj-D(2-D.eEspMFWMmwXXYY  B*e ko<-b!uH h]7:ˤX޸ߺC+g^>*j wdȩevX<js'PTgT^g&EzdfLPBm&ܯD̕P$,XVQuddذA D `ucPrj#Pׁdh+8iukh+8isʘ^R Z>\>^bN&lTٽ͛JxS`.0"\PT%3njUs;l*ޥWUoREѴc=rfK,Xո(/Q[VQS+1eD$z}=='Dn&@,$ 8Pܓ@+*PMMOX+u"Oqرm]*跭0$79v=!o=DolYfZ5`Zm?PʅsTZzwF%&)㑪m8R1\@VZp1F2 XT;)) QR5*K焪$^sÒ9V^SZ CĖC1  VXޒ˜k,TzKw6XMV=[]nuFq yssnRl6^nRlИV|k=N;ylݷhf[[F뵆a\uBf뱲ȿ;;v=b{9gm3~>)On4]7*asbTs=Hcs)FJ buI}|j <|er}r `r{uVUבV,ۮأ\v}4O]K|1ׇ2>ᄈ>zϯ1\,wFījĩ]dzRI^Oq<,Ot/nHEV@T|yr2MЄz kݍC?Ra6*I$\s>h],{V,dpݘTȞjŶ __EӼ$G㚍GOkss}|ϴO}`#R ninjfp\[cDQ?77AHJޛe3~Yo̦|eu%DaV7\֘~N-ةh<{_֗4Z^?=/xm.:=KiRWqb޼ i}W̵lIc7x#cdѥ4 ~l_ܖ.Z>_ϾWzo'/9¾kc/n|U??{KY?s3ps{N' 9 D6VEL%7j dQmvɓf;Ɣj$Q շuqh$=ۭa9![ͬ">G<ズg S)MaGՙ* '#B({~Sb?N9Bpt]l3'Iu*T5Sf u&igiW#Ei:sȉ[Z0^jb#6iCteAdPd KnfVZeAMpN{JFl54]JH#dsJdbh hm?"w"ttH]P 臓)fL[% @6`sJ#ZSح x߫غO!jhj| ~?l<3x߱taSr?Y_Țar>E!$+*)5⡆M ˍ2w ˍJL'y`g^?7,ax˯Z=O2<~'$O$بض%ik[6êP8'u3M}3ݒLI$ѕ%YZ@R1ejH@ #j%HJZ^Kd뻏%[a7RƬ7L ZY煊.bv.تNb劥rd=H,XAH(>O: Au&a,> myS$\}$].D<}WոZPWnifV\7T]cfj]:ow omi`)u%7PiF(-HͷX2m3v䆏*}G%h\E5 5FȌj af i9&ēNIeRۏgUuVE#⿍dlwn\ofrf{y9AZÐsZk^y (/C'S(/\*;p%;wyyqQ`s7c/>=HH.$GǕ@[!*+)%#e;l]툻 $hy 9nIݪp}\vuTv;$zzㄜYg'1kgᗪe1Y|՞ep/9<\Q "$|X\0+$r:.Ƹ^W{0i1cΈkgqc]ԬkĚX2Bu;O]FC&E2Ϛ/lJؕfsw撝;w*KG5[:$L֡^Q*mNQxӜ_]G9V -/1,6Ur]$hiޡ*FlYYξXŪgx R2چ٫FcӾD5v*k˨د3=k˪Vy׬YS7zsbR64.|;jo99˚[+,m MA5Jo(XQeMD lw澒/ֿIZ]iξg|>w{2ry}^>0\%ҵ}4+dԟWAHi3LbSпCONz~z偨N 4N ]^uiBaQ ÏW=_CRU="5R}-~~˿~z<{i1ϩ r^fe 4}\Wk\^ 5 z(` 1 ]~ZȞHZkϏ^9ο0;~k[}*Z>8gZ ֗cBA$FUŲ~X?*|v礍=P6k4@\%0BìX*s W+R d"%EiCҨ,iIYw纂{az 9`Տ=8_w{I66뢜:漒'ɫV(V)sEG;SFy1PXCT&YP_qw3=N̨HYBJRH[k.j(~^e+AqAWI2BG:~˅ŧP qB>oЊ=i99`BrTTER6qqniSїKbUQU!O>t'Oefe[s~HVH,'S=0 4j(tCa( X@2&kbpadM$JkrG5 $P =<{i W2z/ +>_C$VIW. `VYMOgBPPMS~[JBC=VHHRV@,V@_"!;Ny8=ּgZɒg{ZgާǶ|yjcy o]7s+vk:L*֤LlYٝOkY:Χ9M"B˒54 ȐLE Ypv8T7^:[ m&*8Zʸ%yUI:pfa) O!oÐ r(G \Ekt<$Q]u=k+XfEyCuOvk[V;5X/+OýѤ-><(CSlR; S|EeU:URiV4FV]iV;BN: n+r[8+ʪݑgZR6"m5iHI$7tā:I.3uAKK+{NdjK?yy/x#ksoe175y"_&W_XWRW+2C&ϲdQe&Ny;QW/X,C\^}y+*:LUe:0v0 _ u{\^P"Nn2= 4LRYז0p Q3̼rn0ADwQ;G*ʏ&8rsZ7p0xNN#CUyv Zsme]8Dk%QwsAef h lMɼ߾)|뇩y\=MnV|vަg{mj̛=yd2oS!W&DyB2#ϭfxw3Q#ݹ2/Ű̞櫭=\d绕KP~r^ fP˪$eWP3r곩%wȡJۺڔoc3y>YJ70ύfMh4VzGYqo,ʕ^nZ/if[gÔ{rFҾp=̍oُPb "NHZOR}sY*gϵc'%!zrE dNQYZzͩ!r- !pkI\=:uR}3:EI N>nNCws\hz&h;N}r"s^DUʹdTkȅ9N\nyO.m^!nUmQ!ڴ"5t){hkR2*FC";veO"W75Zis͎%sgf9|Fvk<u5Ԇ:V* Fyʂ W%\X}3s(>gŲs,俹*~k]ؾJO&VTwP^L+eE]p_2^,y+e]z`/z{=xڻ+=x^,j{;l)gno}_z99]ιoS*NBSwNNqh w6p\EM@I j@Tl ƭjQUQNqҺ"WIy-ꨧ;dѴuTSH'  2ތvk  3F;gSϓ&jy\|眔?nqjj5;m b 3oJ*,£ 3TYR4` /+=~}_<0,eC<;n|z(9 /rUw?Îzڎ)]'x{q'߿?~ߟ}>Ϡc"EOdwa?-1`jMl{s{Jk#gH?Wwn}U)(h&iy$i-W~sPÄ%ҍ X~xkzQgk8~Kt&!㞖ѥǤFw?ɯ*z>'6O9X[{fC9Y94k*k`*yP{sm6PDQAZ  k3ekqTjjff(-OUgz89#PcߺVjhp{ -Y-SQE|箝vI2*}Y<+3SȠѡYO[S e5+>ܥ~8PDݷl#O }$_$PGOy> z9OhYERګ!Gg8K3%cvoY pwVxYQ7dnd ewɫO^u9uXnrSL oIBkg MaFMnǛˆhiyj j]ZYW֬T@Չ ]c}5I\|9>UEhd[T.YKT#ƨՊlK]=/"sy$UOܝf|bŖwʐ4d B5PpS@ˍjn,Xy|(xDqgEOT O;DE*wNw%-bs$X*R[h69-9=fu:;;&r)onLSZ/]^8|"Pu}r u[TJ X* n9D;>Ȣ%gg>MxǙ=w|y:ǮL!#P(x(KYU"1ph݅6#㕻ݞZҖiٻֳnAFhsF0X:z4QNOVu*q:;EF(w\tÂn^Ij}[ԣTjNW"nj*kb>' AưY4+4+Ea+Gv' QBzQZ0QU1|? QEN/8bfu}3sv]U;^3b#z\yr@GnmͺTsYv6-9]n qmQV[SCj$%!QxdL㨼rl_˦(1|Sɺ׾m/YʵƗyTDpv GXDUqs^*-櫧B YyIP)e%v֨uR2{NMG;NuɫҜc6iKZōͶןqͶBH0㼲EY&&ưb+nmV)uWR{lz ylj7i 媝Ĝ-%AfDilKtKvm˕vѫKl *;`o6h"0Y2 &RGUTL󚊜giZ?k&nwh&d9SwYzRj:  6Nc'}2|^k(ÙZķm`#4$ABZkTMDoV5Re9;T:nqRۋ~At9?EE{{B]VݵD+.XݵD%)?fDg]|k*TD}}%ucgk?6|x>g{dhE76OW{΍B;t0+PtӰ4[ۛPm`$o t9^J^ozrZ.[U ̒fP.&ػ51}rkd2c@G$ɎYSJ$)L0iR̐hӵ*hvyE9VITFi_}cퟌ~'}̳lE)wL ^)>>>冧\،i\9uz!>>yR"(~鷱duضvFQ]ۮ '9DhXa}aH/."~3ku|nq9ԶߗM$3d6Li'{4Ą mXxMw"\RzՂBp|3s/+> >3:_ OZGuG8kJ}➶3U8GMa>5>56YZ 2wYr9+ v6\OؿKϣQL?YG`bCSRW%_,>aCԕ?PG s"ŇMH Iq˜98fJu :œ>}zdeNL9X_VzfB_OK*EDQLDS#6?=>7W8gfՕURLm'K .mYg;QOa6&=Oڣ%j*z+W.?]!Sddq\>RU "截e^CB!8Hq*~7I5\&]&zT|8 AG9c}r{6;]dN7P2gG8]B{ډlkRmgٴT-#27x&8ȗxn]DqPF#mGctDx$1݅Y&!]d_ח_>WnA ͽILPb]F+4 X%ƐUn+(j V5Y+(j/VonЖA%f5h`p2+ECK?#xD5{h(o*%Pf0bv5-T!cS@"J'O. .Y6u (X5Hz :+-/J<Wɣ]\T.XW(\, #K-;A!1#EۀHw;sf]{N.o|`T9U4;uQUTFyd=Dg}O 4'&s7/w!"51$Q5ѽ@46f [laDN뎾OwDo'ؙl{3j7].(j9em&L!YHBy%iao)1B/ى[hFJ7-4ٲ#[xkr#ߪde(jxFQ֪20DRvG{Xŗykbbˍ/YnHj3Y%U Z7)v^EܧKySotYS(cVguP㛍UfQ if,UV+ EF*ʭU[iB^e C;299݇Ec2;A?8("o0gDY(&Kh].v]mk)]lҹGuV0hvsUkVΧUm|\i3 K QB%(e*"7Ce:ϛǿ-Jݗvԫ,eo-uRaB@T/E 8[T+.PqB<T X,K1,"hk˩t`UwS;C=㼭eMa/j[ NBFNBq9kmUq9Fj,i;eTM1N f )&ų _6X ]V mّURuTMx,WTT陋ނJN\t.ğ.\SnI9k^-z5V6$_[Cokpp:fV]^۱lc|y6Nv\-'WT4nDɗTiR"dinA=f/wr3x^(^1zgЙwin3{kLLz"Lf.ވ=*R0<@C*Aow,[ctʕlnAPBܷF̟*66Hّ*6@q -UqEhVi4n93!Ģ|aGk<Jy<%gwO*}5ʨu졿; \]r DԍkSԶj!)m#V:2 ت>9* j*4oM.cy>Yu&5f]j5l/6n;'kVwٯQ50LufqɭufjۺqyhRؼ*4K :RCDN)_NA1|bS;e/.Vk·߁=#_/dk?7v?fnɿ^Oƨ3U*"TȽ2,ګ[I ]9鴞&1`sgҾdTAb1O_~퀱FkpƭĶD`ŠY;jћĚ<3UA3^eO0|7T풍XIQMîՖ7Q>9 x\aD2{s ^%0QQ'?Mص_.2|UMYS%C!| MQ1^4gp[:(^[cQOmrx*7^EbZls冱SLI5?Nm.ݱ£6n ran .rU51<gRrE}q_}Ϟv}P}}Ycߒi#&rWZu7TiiCzcw7V?}}zVHdmпJiJ&TC(1nrZaB=6)4tkG̲ҙq YOW5߹㈾HHzW8|wc`"qʭKc&mns^iYʟeSUp\",SʾisvN(j\7yϻWO|#ns ,OwpS??/^Z}/b~Z>.7 \#e2 Ls`]5>ͧb*fjMw5+ VV_i8)4L[79Jyۜ8J\84]_^?9i-4{m}4NއYn]QmnvbݻxzJ {wcARQguI6IbքJ/blw!E/bQzߵvWr/H$UcTP "LRGzˆ/(|'Z U`kRFڎRuI]i.-R x|l AnF@mZV((kGn9oB-@/S%So;vQXV(a* 2L(⚄ĒMs]zފTNj9~GNLsr&qI l-`=&."IaONK5U;f}{ue+K;) i8"y.aYEXuΨB_iEUΥ^`֪UJm֨{gdR|ήvyaj2qlIa!S#V\ZkX#Zřju-k2i(T( enӠE5\>-\%|b93N"ԲzӘ<8uޜ8.wePYO2I&&*5X;\"cG1Md.SIcD{GlN*rz!|Rw'kW8j}ǭ5,g{s\R;GT`X2n%0m{NffK{ /JʳERaEgUuؤ*eU/˛ɄUEEV `ԬvTyXKT2Jmzv(}$VYc#ZʴqfV,&JԕZɜNHaYͿ0K9Q`fR9#k,m9^Qق"AԪ|D/3֚dʛKR⒨ն;ۮ(a/%ԋ=F^4qs:+ㅣJю{l4^7 PR,yqyA>%_ 5+nq$YτeoupT`SSauݐu7_+qO>DqvASe HmJW7\"$|U&.+5F"OA|rfTɑjIyM}04x戇,wrSS(W*ݶoQyg|%rӚ7=FN<*G PدW_ ~/7^!0 KZ~FSzdnf߲Qsْ6t:UXS%lm4\[/Z3E'7xs4!lwh ] Me`{}&'G[ۭ1,EƲiQ#B3gj"Ucs?ae*@hG8*Ĩj{O3NuOZ+3[2Ѭ$z̩\::q4L;ʒlxBR R̊0Fk:DiYoSahY8l䏑r:ÞD(k+"8Sݗ$|7* SӦ"ڕK,MVՐt*jmY}G4 hAgM9B -\\Fް5e:4śUiԤdT*8T JLNjnFeJuV5M,VD 'nil\2M[̦wZ"VĻt{d]dAzӳrXD$ Lp3$H#WUUEG5̰Zaڵ,X}3 $5x\N(-/5DleoMJLˉʘEwkkVH@@l (t,$jH Q7vB sɜ=- (CșKJ0Nv}a|Kkg;krC EOU#XPi.P&e 45Mj3bi23y˺Bu]{[u#hn) lY)M%a R欤hI &>|UxQ|UڴujܓwM[,=nwXsAvxNjomjNjo_09s%EasS{v;znXԺf>|:JߘFu0+{?H٬Uմ CX[@|j4GuB h.Qt2$-o3^^{m ښzzgM[=s.k<:ÝMY6 y|u<,YWՋ- ,dqЧn=z_K3m,^lRu>Xz5/lW=]OF+3jdb'm8mh5Kn6ij4uٲlٲ8WQD䱦8⬊'%45,S.[آ61nFyOqѢbܨȜ4Ġ6A'+bP@cdTXk b ykuTwaSar*>󰩮/(URz}W{ <TG `Ҷ24ٙ bcoT 'BzQ#WmcffkEh֋Ut).Ǯ[[ǭRaK%\Ztyswpnice4\˸7J3d3N(C9y8'Ņ()$Ǥe(S԰ofqV⛽F8p)ɲx6[{Y6OT';پzuΤNsw3&O.*fV2R#86yzۙJE1ipFwjĹ>SSUw~ӟ0벾e_'>aϞ52dMcuȫnշdn2ڳIѷlcȲlcι 7l]qh#??:ts}>< [Ys/4ufTB*@J⒧5?3z4\\{sME*=}6ybSYFc,϶}j}GG}O{2ϏH>]G5B[5(P{9.8rE%Fhsm~٥~y^e/_ /Ҫzmq4/}}}kυ4i{Vӿ◵zvɩ|V_~}~v} ډW_sCo}vV J&u2%M;S//8(qʉV=P%s!Z (fuyJjsXeGӒ~&5 ß]G S&b(|:},♭%ۛ5$Bq|bc?8S\4j UR%#aW'O#wo_ L0̊`1KXºW hTV|pnwB{[s."6uŒtP ǘ3OW;zv(A>݊'~c)m`cI21֊j +wwQLJyw*<# x@GcـR9N{a&f;miD{mΧ kTnuLVQFtKjqi]ݲbՐwlzg]2vgT2EqrӲЧSAVBNBAx(F:ʘ8(F:.UTϽ7sjgo2]l(-P{vQGM ʎQEhZ&vz]nZݺ WmKmXTUPL%VvNUkąp=2qz\9`$2ƛ$UEw4"^wNԷ;yޡݚWk޲S\RS $^%)ZFT;`@骍`ozܗSCfܗSC2D7E2N oulʤ Q%V <]?[kmW}eao]>kM묬i+S4IV޲yreڷQRiqʥwxdM\xl)BʎV6"QοH+{_#.`m@Dv[OsW)D+UDj!VWC[" H ՚r M 57XB˧Gć8NIr9#TiiI4vcW̺NƃTǶyuMʊodєBq`h˭:vp:˭=o<{br=Q=`6ջ#& b{_NM]{S=TӓnQ1B̼(֘o7Zwk{hX-Ѧ+F`jݚbkVLMl\[5 Mm sy[5 Dž&ЀH;Z.A ]Xٛk{vٛjuj@05H/Z$Lg 11~әgs^wW~˨;y]goںwc\d{zBcPSAսD{z0 |y}EWL?5޷%-{K/ ~V=7MǴ~sAO98s^1Oaܩه^x_~/./kp_~*<ϡT)K4x0Aw_kƿ*,Z5Q} |3K?bu/;[ gygܓ_9UĨJOH3j|f|(b5q{[l+Yp/vsYzd:u?:5 C\nb30{e)9:N~K7cu58玿@"d\rOpu5?[qQϘ*VXW M('?J?E_(}j~4a 0?.a,3g 4\#U?TaؑUOB/ 0@\wj\ds.[\^xwcjjqӄ*mMVt/pvt&&FF;{<#s.N3fT3A2,l nzޢǾWpں=fSRL a &6 $LmT u,awPUA15U,V64U;(jSV.{˺Tjoubͽ*5Fm:r3V+rr h-ܺysfFˡj擦M:iʚNM4:-ene,uF+PcoW2PJTUj"gÞr>{,=w]D8T,w)1ϒ/i|IH! ně9tI[F]E ` ʊ &A38[KjX|*RgY땞[s>"wT›L ̚]mm<~.SBu׷*Okc,0}/\*4ㅽ+7.6,7ZZYzN?NQN맯jgyRz6wJ;c}RhSLJ7 Bf^0 jWIWN1FTS M-2PybP?8;͋}SFݱovrvr醉iLͽp6ޣqYCc3,,D˨kWR)TQdWRk+cj+Khw"Ɯot5[in,p1{EXL's5\骝EڝuU\umuN7 n+t[^m\sXq=\LsA -„ ,6eG|&cj#Q'kr^*zk{E+{=5cc4٬FT bsq胮uFfX&6dә Mq4o+Bk$r`Y)CR 3*P<ۻfņ8iya֩T+lRL Fd4#2!T&qL4:q}DgpDT\7ҳ' fNN"[\':%I'wN r2 ޅlvM uhbYl{O{6~Uzݞ0ۭmH2L]Ad$1̕I\I:Ȋ|DSYM8Si6j7 MAnymf~7O~7_~/{'~5ד~7^o}1il9fߒq/<jj)DrtVv1 9i"ֱciP3PQmo'go6oy#܎u.xj,Ȱ" vfONO<*߻De,>u<<5 40sUb(ʕ#q/}}wۏγB+l!J'R~I̩ĜkA*ɲ9m*gnNcMm~uzjXhPTAr(wXGV_#Dw`ÑY(&+~^4ztv&@D=;Bevq愪P]{e\ȓh;[2sw A1D}shJb'4)GF5ޜe\tP֨TA.O{ 5>+ED;f_;?'i~/й4j5@sU>:+9p;CZtAbS^05Q5Ẹ"hrTbbY;gg"j?.Ϣ:m~~kYߏ&oat(Yc{e>5TllMb{61&~d>p' :K T%h*|>3]g#4kznS&gCkFwieb2  姾@QmPМz/HKUHkBؤ{FThEx(I|c&Uq񶓴LI^kXy6_rOZ>*dYcFX?]^Ub+3 YmU6(E䬭VJ텰#(.<3 kld"+ 3G9E !~!P*[y&`L+lSv:o,Q0xε(5Eoʋ=^Y[r\ȬʹܞY>§9>PoXCj %f^1LҌw3#L*Jb['|P+ x,!#Y{Њ$2V(( u!']pEjP`UlR_kh m)9AsX9K 1a֕Mc5lY*=L̽k "lEɮX?'2ar\bԟMظCI4\^\:Q5aQqX~bX("xvUJ`(.I?C33jQT0T(bNFL$qWv=PA=죩amF$8< *\|&bʌEjen8֢ d/G5hRpBqMCJB2,`BnЭF?}LMb`NA/"s5 9N 9 'D{.)'%mO&EsQ'[BvzU*yɔUeSSKɚ-[{rҲEYDb.fqvI, H92ZsΑi}gQ3[T*8!Zşk6)5z,u5ǍZ9I8ӷt HZ~E5(TنTJ֠-b*G&wYD짍#(g)OJ>E+ԯ`}Y߆~Z~+w*}C~?q_S~iv !aI%ܗqhsv j~7vg'qjf]|^NToq)su<=yS{hT{irxЉV8عs{VS-@rʌ9EEVGﮪ8]:7wfɎo[rP"Ę!q8GT2ڻwbASIߜ:7$)VXDTYt"G$[OOgyBό<咞Dq>rg.dS[**LݪTUUh@!)Kj4URwwwowK&gǖWO("0^JKuMSW켩WUUoڽ4-TaiRR^ 0l3`*+ս.EvQ_e>z'W>C~<Ͽ3BgoH ?X[.E3f:ǭ !͵Е}͝8m 4Jb=TOSQwfo0 83ͳEUOOWH$g۵_*R;R'5@28 D(v6UyWƝ_uh*9ctNV.hʝd\-p|oĪA)bvJC򜙪sY 0y2iDo.׮9R #㴢o7N qYu>9|{ԶBT_ۤZgƽlTSk,YZ>g%wqٳ7?3~?>3ϚRI&~Q%~o.goOgJ%JڈqsnLVi#y CJlPt\z0XcԔmmDŽ'l]Шއ%J6^Bȅm2˫AD:MPh^ F$lXEth-SEY4(m~u"i u_Ek@)+TQ77QPXҾomo#y\@Hy^EO`k?&fޯT?_ :ǧy>uJFXƪq%eQUbC9<TT_Y|[ΥzN8M:sIiTWVK/Ym;*)ORKf5|EWfy*%!tk*zz*C}_Ϫ]X ?sUS+} OOnO¾XJǬ'ZVj\8ZFgِQb6 UJN_~~Xg4ܢ=ňА☊(|TE\{U@M=fW]W$9%`" ʊktz6eܠk9)S? F}2"vqEum<دoкQ?Bv󦵆LՔ^s[J{Yhb2!U6 i¤4-U1BC EY캭I"dm &($pǥطmA^W"13. H.swr>'WB_Q<j!ߍRʅEeKRzy'ۮZd4{wsPP':Eb<52pRBr+͝l'%W\5XGb$WU-kklPF)93WHmqFaQԛXu#L!TG =>` >?<~x¿<~__k_c HlL:2L9d51~E~+C.b0NbN5\jGRVdY_4?O?~<~{?7u! ޠOL<6$L/`qn!sTTL?QNޠk_zt$hpwt]n=*cs||/k^(^M!鋦!)_޴k?'_o{TǭFKXkvozbo߹Zbu߬[;˸EO}y{46$hTGYCIu/|QGoy*`,ݕ ȣ:$8C"OZٚ|eejZ0@iX,ZT} ~ḳ.Nv(J*$(1j&qJC=]Ri*NU"jɦܮkwlT3@u/%N8,*598ؙ.JAiTԻzav1nA8 7"Qqp]s;݇ +ݕ`|ދ=KPu(dO۱9(5C9+IDg^ ºOO?j~}Uܟ> ڞr%vt뫷gnN;{}_xyyg;Կ0ZIZWג p&'|; ; 7F1r2H$c%Ji7 *\uג]zWMgsیK֍'Ŧi]\U⿷{O㨧ՙeYGO ?L?H~uzjK?B9~Ge,ee`ɓ\?oq j%s0w\%QAE4^V2QFdw\9?',?2looLOrdv5s\}EhDE)Q~jC0qAI?)ͳUR4fMC CYO\= {;t Z[m6JNWLbQ+|xbf.eOwi'baG}tHd_$+;QhϿ2&GS''S @¶d=@ݰϿ~=7>G_#|'~,~|z?r+T53&fe"}JoZ[y2km~ vkԚF/b[*}Ft;쿕!ng: i+TE9wXiycz1=1??s*)). *kT\؆=.(V =$LrYxGv`ݺ*!P+Zm놻1 a›OPAgæL3=C:^e<#"zSmP)4lʌ8A-pLJU(ܚu\TəK"l+PJ1ŋ9\ ۣl]ܑګ+<^s- ԇ4V{Z" /cMOgrN%H*Q4Bb­X#3ʇpE;\|QrAZ;D9]Ցؐt)Qmұ`)XO w !Q5*:eJRԙ0̞ѕqQ8bßr놢E Qzq{WࡋdUWJ`#t* I0JM~9>V`#'>zjACW/Syיv;]uvuv:va2O>'o uS%J$4M VƮj<@ aF j$N+vNKĥ>+|+|+/t0c\y^ccnQ$4<ӎH$)U!a~??}*=*>|O|>'|{ { \$I*M{CL`Q'KҭEv{^А- IkKJQe_á_j{Wk)0 22bŋ&VLY>w f0ɆXcߟ s]u]wJ{a^rxQ:a4v}SLdɕ YY0q>>%%0a!]\ܨdH"|'_{uwgGcN@>>mܧ 'z{'f|(O:<u^e>ӵu2]>uӳGkWWNξ;Ӯuӷnvvuݻsq<燥(IOR|YcpF3f(+W_Ot|. B;]]]]]:v;::];vgg]۷:燞O<=-JI$M?Hj[]d39=Xy{W֯=}Sr_%ӳӮ:?}~11beN/;w~;]_ߏ[׏k_ - >I>Uve18Nӫӳn]]kcX}祧y (U=x_Z_zZQi=C~YLNS)uv$,ɑ&fVF11Ïr˜rqcW/_.]:tNtޝw=ތ1r%)RdǭyW?"j3++Y{|Q>(/mGv.KvVSuuvvuGn]:tNvNoOOO^>Y]9sީ{V|fZ _kI~/T~aeL1dɓ,XɉFS/=o~w|^|)ykֽu7].If3!yCO:> e\e\]]@WgggnݝNi}y<1WקG]ttt]sz}uxY$IkI)!`q>`pdWNݝ]:u;;:]Y3d3c.N\RO=-nR?";esUc?Rb2h}{OEu`r.o۳gS|2c}>_@|yom%JHVɎVJU@B @>- I>=Ku`r.onNήggiӧWNu2̱ˇ\og篯ppq%l9";㌐4̬X;z2*vܟd_d>\,Bw];:]]N];]c,=^~.Ǻde;cX2b㓕׼e㓓b,1s߿wxsןy5^כֵ{4?$OL?>˨+]tvgWNήzӱߟ3WnۮK dy+^<=^ R*Nfx^猻VO $ _Z_KIM-|-%O]N{;Nݤ]:v;;z>J;vNg=||O':;)M4Ӄ*LW>Ώ4xK>y̜{⽇)vvgNnkno'Y13&L`ɜ9^O^~|ﮗ].|5\V[^tZޏJ:ʻ v].cq1c&LX2,|>>:Ɍ2̘e@O律;*QDVZx|:y3j{(ܯ8yWaep;0LŃXb+)ý}>>}>㣎 miǛMʕ)w$HUՏȑAUzdv]q9ۮvvv|ӽ9qˋ66O=^~>~w];{;ۧNs\9q/z>}.`Ix/kKδC*d8e\NUYX1b1dd&_9vwwgN|O}>4h^㕍%9"1]/O?pʱ'L'%p;ca,b̌N,1˜9p,xuP@JJ#ϟ>dž~zI}iyKKi*ZKW_ rO_.tc3a\ˇ]g/ogîGG (TT9]^뮺Ɲvr;[,YQүڽ\W!tttwWGgknۮg{:W]x~GoF88ڮvuqY"Tߎҟz022JX,IAW½/jaqYN;uӳ볫޻ug]uۮm R/ 8M\q%DUξ5_߇*SOʽ4U/ue0.;uv۷Gku_aA@ btutu$HK}$>f7\QW@H+⾃u^`۫NΝ::::~~1f2aǿWS`nTA$hha^$H}7ZQW@O~ Y/Wu8X:v]t۫>t뮺N޺ۮ|fg8ˎs}g~^mb9gwSǏВ֖ZU:~`{/I1\,2eL`X|u]wz]t۷_;}>&9m6j&KD[dmޮgygO2x0Wi/TKl2f, dǾYcefN\qק}^Ww޺4]զ>K h=}j8G%T{).'ڽ+*||||{e1V1eNttdԩRRQ }W:g_'>O|_+|>?nzӧW]u۽y\>>>}瞗.T2B\^H+VWѫ26g<(QA|WiWgnΎݝήnΝ;{wgn:ugn9r~ξ$MzjZ_kI}IMG(Wr+>9,tN2ed&Y2F0ŗ]ɖbXc&zzzKzׄkffo33>"__&L39O4xO8yj'11;|>O|>O/|fLP"@DDzfes^בi >ZK)vIv=ɉȾ_'W|>+>|||K}}IH$> z<2#i5?SWꎣ'TõuʲzWK),1&eXgϏ/>_>>>>^WzU|X'> >F^ᄇ Z%KKkLWaV#vbe:rqÇ+ώ\9x緿g~^~=zz^e{ߣiG>%~ɄʾKҽ)qY.ea0ŕ+VLXz.r㋎{2Y-y@0a^W-elmǛ9'''k ~t^ʽbՄ\%aVd++& 0,||||O|e8^׭zx_kx[ǎ|WKH_=1rd1:tӵӫkN||Uy^W+< PԉH#[ǎ|WKHGz_+ID^Tb?4]21Nntt۴tuuvu̱c,a˜OOqKCuKm*L:SCJL+Z egStǒu>uݱc'.Ü\sq.89q~7J%J-䇫hY! ԂH 'dqOR%YӮΝ{vŌ8r㓇r{׿}q8|~OKpnRJ3m-Of':5=u|!(}G=Ku۳]]tۮt뽻up{{zǏ Ǎx׿Wk㿏>м 읇^v]W1XRX\),XɆ1`ɓ0˽]t{v.\>>n[2d%ӒZi,kW>T?ieYFU꬧v^;N՘VX1ee`,;uޝuN:uwcr~ʕ*Q.KCNIia'Db (2ʿA.v=ӥڲpÇ+...w]:ӷn{1Kyy燝u-&cikdvDfG^ty+j_q8_eG# 0 1eaLXg?:nӮt۷nzzzz====zw]Ntb@0 q}MD4e@ IVJH}#vVS]Gp bXɆL/tNuwg=zz=zz= 0spqNu%4VʒyUfXǒ>5x#O]yyC=+jdwg]ݝuuuӧN9rqˇ|||yノ2T $r_`+km9][)"F,(A,zd=Knλ;vvtӼ.N9p\q~}ϷqJ$$_% ӕղ+hKIz2_rtpb|WnW]ݝ]ϟ/|>r|Uo<_/ʯy^W׾W%'xxxyꧬrʲӴ,Xɕ Xdg]]u'.|yԴ-GFcl%H]$d |mI1cU5`VFOp)~IS/԰d;Nӷ]v;uvv];:n;wO?uֺ׮ſKNj)<ν~ҿ_!QtV&abCY2Ŗ a+}|:zu۳TjX:J%)JQ*Rh2 }?-G]um˂+D ?Z/Gՙ{$^y={GKYN\qrqrs|12ca9ϟa˝}_; 2\r@keHXFN!Њ'Pt=Q]'}Gv,Lb#,0bV:u޻ޝ=:vWn{=μo㘽řڻןsk?}j?%{.Xce`ɑYczzvtWnb(C<<<0u:>?%vPCD~>Nz̽Y^r|!q^ڸOEt0œ+&LY1e1&V q1&q8s:z_kjNeewВ -/a/;,V LNœ+&Lɋ)21bÜ98{{׵_Kֽzׯ^w뚓Y]$>$^/0ӈX2e,L,X1bɖVYvXcp |x$<<:@2 *D㏷ZJ_{WKuX_ eŋ,Y0#. r'> #<=0c$㏷ZJ\v>,J&?vUv] fV2b+21b&eϼuC,2Ɇ1~0q/}sZKk\7+﮼}c^}kfjWҿ)}U{'ߝXddŋ dbņLs2c,Xe<\@ }>2dhj\2Z ܩNjTKPHJ4eY8$V%I8+XL˿:u۵ӧWWKgggGniNngn|fcsr㲤#CM@M!jzdMdjX?3̟Y:bLG{r亘ea,,dɑNïuӽu۷z۷Ü㜹Wޗ{׺Tƾ4m&IitJuvIj⺘pˉÓ+޺뫽vnN}[M&@H2=uusju2ca2,1\緿~ޟo[zߥ]xk}sw]s—uy~.I'*柪bAq^Ӓunkߌa X X<(=)IIzSlz=gu<)w_)xikKK_:ֲ~KYW2X+qY]۽:v:;:]]&afLf3,+'8zcN %)RHrDޏSƯ2Q$b??zQN!Oj^ev2̘aL X0نXe @oL`1 pq87(J!hvKFJ4d *D/pP'{r+&bɋ+2edgl1Y3.9sp{zzzW=z^|^ׯ^羲w/@֞CڲXzW}#vt fVLˎ\qÎK}Ky@=]]\ ʑێr#F4d@$1Z(%1_rq0wNݎ;]c˗r\9q98s3c39qx뮺-ec%rTR]]\{$ɏFoO8ڽe=S2&L0edddɃ~.ˎ8er߷wӿ}`KqD&dI3 u2B+Ŀz9N迀;WL/Ebbp'..qrxx<0`1Wו>0a^1$HN-ܧǮ{g^c%ᗝx {++zdp㓋+rqr\NW8{I1& `]}y^^O5xqqy~:>7C9UWʲ]vYL~uݝή];;p.=s<&zy108>:N:::::$j;u#ƭ ulX'꺯U{G){.)tLXa&22?]{{||@ b`:>111{n.I%VxxxyOͅwOXy^jWʽ˪{>a2dņLa߷zvY,%Z@ |} Nm66*TrI2MZ])߽{SK_?^_:4e_u\pO1LɃ#,2{_n]:e3s}e޻z﮺닜[zŖ|ptiY=Q#*⿚~h0=`z ,V']ttޝ]]헿~w<<1'%86W-$ \h[#VFZ@.#^԰>ʲ, 00V,Y<<'x z[p L  ǕDž~we{>t1z?z2.#/PX V&Xe Y1ed̝{EzOG^Lj+&:SM>u;&<UԖ>__(ʿ>C/殆K0LFr2ŋ,bɕ;zV&1Lu:9_}Z#뛮vLy2K;t4yUm_|!WaLKdb bYYݝX@ P(<1y燓'ξ pq_pSkrGG0aȬ '@?*9OE\LVS#\\88\p|un,e&޽Kd O<O:1pr]|@IL+[Z=wy,zuGO|w۽uӣݺzj[<냅{ ʒ$q.P}qzŞ~|>(*%~K$j2u}*L/Le˓˕Óqprq_];]n9`룎;)rԷ% ;Ǥ9r=Xa_ ?2yU}_tLY.˳,a L2cX`ɋ޺s9ˎs{?bBk/+֒?AeᅒbtGn]c.\''|w./kޗ7﫪'C>SO:=ly#r;_3&V Y0+ Y1egXɓ  P=- NRdI69w͓3ƒ3_I-{I*ֵ{}Ӕ3&V Y2baLYY񌱌002qc8Z/^||-[^|;ffə<.5yWžyUW8)v>cY`̲eb+ ~32b@K NDr:9]ʪbZkH-/$(U]K Ұ eeeb Xdc,1㞯O}[VV_|U2'ؾKKC=GUvYNN]vuvvtttn۷]v볳L tu88㉶%D)Jcc%4ԁ\N~~Fby'|*G^_euqˇ.9898qr\;۽vZ%ԱK%Z%D`GS:q]tZk[.宾$ @~ʿ2QA척.k9\8prr˓aL21&;CSGG]u8dR*KɒV;[&K5#=t|(W=L/R侥{NUc+&dɖ2əaL"K}Ptu]u6+<<~7=Th=i|Q!̲^W8YVG{ӳ;;]NӬ9rrq˓8;xy 1:mR0ӭ;!+]XU+|8!!YLTWS걓&3 YX1ea99\8|߯y<< ]uW8m%Id2Վ4x*֫+ЊC%Cⰱ=Sr)ڳ0&,11bŃ++c2cbœ1׫`0cq-H+rS\%Jl#F*c2)<^𗺞{i/䲘2ɋ LYX2'f1b( %@Lc 01*ur^Ҿ/dqXX&LY2bb&&Xuce2f29~^= z^־WKb~-]Fs^Oe=U!ԸLYdɓ+&VLL2beYa2, @LcI G`%J%( D sڿ>@ ~Cd001Ҹ)]:;utvwc,r.>o88A*T$LI8J%=%Xc~0VJd?!{?H/ee2\rœ,Y3) 1ebα˜r}N8888888A*TI$$yd)RIcIj<~o\~ߵ2ʽ_=~ܰ\,.Xd 2ŕ2λ޻uۮj\KD1<<<<<O0c$H"DsǓjK#7&L#!ĴDt ~avjWU 1eL0,X1&]NvWgW~k޽^f{Ye*}G|Ki;! ~Qt==eFLYY1dœ&38oWz`pqD@.8M4HdI+ZiWVW<4e-y bi I5}U/dd2;Y1ddɅ,Xu &!>((%ם=Mw޵-/zQ$KOp/>_jbbwtӮwgNw~uvݺu]fcסu췙y灉$ՏEeuul ? GLUzFK2_Pr`Ç.s\998\:t]t,K%ZPA1:Ny yy L txW++`Q \dH%+A!d}% /j,NNrr㋃#~3&88s'Nglb P( P&Jj[wqH$6RcJrV=̙= GR|W=J.K꘮K)vvw]]NӫfLqqq.8p.O|3,eƻy^U׌Yk|:;~Iq\_r>e2 2,LLgr9\8p}>κ룉 2d*T6zT$HqҴ*G|0zyCȞ5{(>Dzbr11YNaVYbŕ]\9>Oqq DLmm6R$H㣕Ħv~0ErIԏҾGNK2L+ de&e,Luc3,ce9ׯ^wy涽{ޗ>7o)pO_ZiRuOr?2e*WvY]&FYX2a,1bec,edXe1uפ4uƜZVƔV<,ɞyy/8zU/*;.KYc2bņ,a2g8.\8.˞oooowʓ\lnEuly5n'# Z@Z~t>UbNU.\s.pz?i9r'.8p㼻.{{{{O'-1c7*MpK}ձm]~j}U~pSdaÇ'Npr8=n\q˗9qO=uq>l*T$2d"Dx||}чPppqT\\^\7Wuk24%`}WpXŃ&Xd X1`Ǿ?}z'Nvvv<<ɀ0cpqmɹ$dϰ%8=X rI4 W{,W++Ó.G^}:ӳ1߻ׯCmo&]O>TH<`$PHzYW_ʽX VW'''''.W#.q.pǧ_jK-燘[&8\c4s^[نa6xg>!}j/j˩r89e8& LP ]uT& -燘ׯyjVWoύVx*^2fV,Ye,2d#;t2Ɇ^ ^x% `2pmXӮ3z}~{1yC ~'>K9YNW'+.\\N\N];ޮٌa l^ nlh|44&nIm^h_pWڿT}+}Sӑ9q9pfa2,20N&ԕ%xiIuIuJCQ)R6r%;*KOw}^<22pR{SүHʽjq]W+&e1`,12 2YeP ㉵%Ihy..IyK=tw}kO/h5i!~=UꟕzFU{],dFLX2VV Ō2& 'qM5 p}ɒ%^νVfW3'^TxUW>yd2YOW`+&,1+# ee`Xe,a1a.^}_O>>9|./֠KK_:_^Ր>}ULV f,2+ `ɋ,2g]ݺۮݻ:}>cih+5!3V Q5]ڳk@ii}%5({ԺW#d+×.N.G'29{=s߿~{{=uReHy#^WW45XǓ~'T?_K & 8 Y1eaX2bɆ;ss={gxC<<<)o T2Ǥ+8\L/s Ç+W)']۽vۮΝ:,9{{_gk}to_KQ G U.&deL1`Ɍ0ecw۽wӳA/v.#¯*=>^(dw bX`L3۽wӳ]gOOOWk}myOe:kдеi/>ҽ{(X&aYdNw{=s.c0O$I 2 $Vnɮi2Q%'X{O=azCW0S`3,a21eLXr{{緿cxxx?xO' $$Y__^y[Uתu3I{5ZZ}CW쾩^w Lc tg.r.._㋜3T]U/@tQGuzT{'i Lc ,\.\\8 c$%4:vHr]\@czQƏ|(EڟHjt|a<y'<6lm66 }~ww}x-Zk\W+}W.Kz)0w,YXdɌeba{={G]qpq]nL2XICn8KN1#ǖڬ%(4 KH%+P0I=vCaË..G'#ÓN럎+IjZ (tu-qi&DLϯkm}K^s|Z_Z_KIM$KWb9LX`,Ydɖ=f32ɓ,2bɆq~0`10 -%J%I$48ӌ%00zQȼ뗾.SOYb bŃ+,2Ǭ~fY1e"@<0 Wn RR$IRXXln]|`DhXx"@ЎQ~2\,,3 Xa&V,2fe?90eYe=߷OC&K燘@NJi4Ԛ+_mhӨ=##\Wj^9\8r99\NWc3,Ƀ <Ƀ0`p<SM1O_^~dfO4|(GQ+˃)'88qqprrr3c2&8㋇>o=zzq88ナ7)Ged5>'3`UetddF+^9,۫];]];];aaqϿP1J;+$ɭ!{3<3O*QG)z/re_Jt䰰ueF,3&V&Lݺ]\KDK%xb`01ߕK$^>RLKKI(_:%102bYbɌX12g]vNNWoC!1ܖvCGsQ+Vd̞DyU|%L/q^)reb d,ɕv]ۧn}mJR;))J ǬV;ZmkiլCѐF +R@X=d;+dɓ +V۽vZZ,%Y.\r`Sq6Jd$^oYrU=i{4i|CՐr2ɓ+2`œ,YgX98׷n:룠I-4!쇱^=jU}U LX0ɓVLXec 88q>Աo1aKM}Gr<]u1")1c!Dt ~Iʾ{VKGp Y0 ]޻vg]un߿~~=z\}~ߵ^^¾Wk2W/KIhҺھv:YNنbɆ 0œ,2ewv]u۳κZ)ry<1믎I$=$`0|+ev}C%{4ִִ֒zWCWں]O e,aLX2g޺v޻t鞾G׿}/w{5 iv/)0 V&U˗9rÇ'+ӽ۽v޻t鞾qツqHCHz]nqތ?S~v'!, OAe.NNW.8rps~3pˇ `c0<:p|qJ$yץVVY*Cde2CWW/\.Wku۳ӮΎcp8qsfzz`2 yumʔI8KjT_2>=W=* { uv;];vӽw&q\}'|ulc8룫޷'k:~ϥUCJ6i/:A_G#UtL\N.W+'.\8w8˓ߧnu|q]N&k]ll*wO/d𧚽W==Q:]V&r㓗ΝVc&e.q{.9ogn8~_JuևI 45)vDwdK@>VzW_e_U{ʰr˓˕Ë㋗ΝVc&e˗8=w->>:mmZht CCRieVWFkzFQ?tb=_0>}S*d& Xc 0z3,c YP(@`& 0`:ッ6u|z^u]sK~_+Z_:IV vʸ\Sv'N..N\NNN>ufX1e ==z== :㍴xz=dW:R\*Ldz <yʯM_ |%{NUËG.W'+'];u]D,a,<뮎!j6Fx6K|d:=G_|UUav_#|ӫNgkӳ{;޺vdKRjZԸy ]ttm es%Iv޼gd7O^d>U+G+L1a,3e`@ D bP ʒ$$I&K=kϵ닋ϟ21}o^t}ޣWaj;WCtvNSYXa aVXb}NXfeYeiqsqy9sּ^TIb<ޟώ^ 'Ə^R@vCv;L)&20c&,`ŋu,&Y009TCI&K%;(qLQ7-Lj }:e]W꾋zitw&20c&,`ŕe2e Ѡ|}xy11O2TJ)d#߿?_G!UUڽS/Q]eܙd0F`9;9q'?<.3,1Y럏o<G2Y"8q 4MF#Fщb~q_W8aܙdF`̦Nc11 2YwA P1%/C2ɋVLV;̙}?-XtttttN?-8d2I.=$ah#I b ? Wd>e:N'.W'+WY̙?1O}GA?*LI$ܒI_(?t~p?zOP ,.)9\rq˕Ã.Nqˇ9><0`0|cG]u$k[ϕt4$ִVF#%=*8^鑉LeeeaX9rsN\8qˇ'.{߫ק0|cG]u$2FnL-YY&X93/*Jxy#/x{Ձ{,L%Ãˋ.99}|tuGFz::CN8J9"m$Ʈ)@!>`e>t,82w8prr\88rXs|}=G]y8뮏 8*PҵH<<#ܸL qܰ=NŖ,,LY1g132e}g+ϵ9ykk|g]/bzb /Dʿz '_b S '#ˋ×.'+f?2}M KuZ$]"C]]c2{W_yW^U{VCbqÇ\Ó^\y#'1'& crmn+~ip%hI/kZSZK#1YWԽ{.F c 0,f22}>y<뮎ダ%Gc$GqKǜ䗯>z:>ya}ˊNGW2bɌXa&F,20e,dc9}SYgԢVz827[%c$> |a|{/J}S)dUA"(W|LJ$E4D::@) Vfv;u֢ڭ]XY-CYwu6Ks]mwsunlWϢR !g{'].6uG jْۻwaNٶ/wfXѬrut|2Ylڄ*ͭw{Pskenݨu(z:od]n}Oo٧=۽ y۴t[P6yEGk{v9np㯷޲݀{޷ޯwU14 yorzz믾y6:]iw{>ƀ_>}M>{{=LW ;4nަl =[پ{w_}_y^*tun-wuu.+W5mkz} ( @ta 4`( (4B@@>ztEhP( Tv>th`x{ރG@Ԕ wۧhP^ӻs6Νn=nչMڷfiZu8;ٮ^ۺugjڷx%٦]wNlλuFjƬԺܶ"ݎbUnZ`4$4˪խc7g_;^fb&]u͚J{kv;W*8j4eݕncilEnTֳٛe֎nu|Bjҽ[-U0v%w40۸NZtswV[fuu͝Uv:uƶjJioW:Ӫ- Yۧun12uRumn·]Vvmvvѯo[pl:J9͝uIt-zٽ2ئkbj)듦7vtsV[k=kY:w5ݻvksַ[m֦,lf'gp*٭u[jvU'{yZ*ٮfw`,K޻[v͉MiVOssmݕ֚%^U5nӎymhWAWku[ӺQI3r8H-mYkԧlݍttkͺ[e]sCyM:nԑkuM[]}o^U)4;;vvvn]K]]zŻ}2yٻnrlN͹֎K]H\ڦ)UѨݛWrM+wgwn;nn㺺5ӶclZӻ۱+{^H 'wui6=]ZVms[[l.Y9;B]n]m{G[{똡]S'Uncqu3t뵳NU[^;۫Wjnҡsj.cfZfUC 3ҷuWmnnݛ.w {mݚ|vBZ5E[s;NVv^JugsTYnNmmLe2v\wf{M;mʷ+mۑܜ؛9Wn䶧k]TjJ3vntֶmٛ;7;u^^3gZuky}wmՖ^aC{6s]ۚnøulѻ j^ke۝WsV9H:K׶]ͳZ:YͶ޹6˦띬4ݚ\h՛-˂vwk[y^n:\Msn=(T(P ׮z{{=6+{K;۷}zt{ soku)}WϷ]W:_nض>:}7{\ݝYw[Tg}xy{}}}g׫zof{}_|z{{^+[uNm}ϾWk}m[[};y'm{Lu}:ϲm>zwv[q|y}vO_W7_z/z v>}m}sW}yzxn^{h{m_}j}o^M{OzsX^mμ۽}Ycݞco{o]mzϼjٯpo}m}t_oѾ}wLhb]z[t=z:i{}OCnsnn{OjײiT{ڮ}5N{Yk_\Ny}>w9>\nz}[ywW*Ͻo{绫 ݓ{z/f}ڇV+Pbޚ^ڱ}tz=赃PWݾvau}Wp}VJҎTynǶ{<ݹ9m_Ot垧׭7mj'پfW}=پݮswZ;}waao.mޭvyY^.J}^M=9}vk[}ymm[u]ݹιS 0FML&abhbhdfL#Abh`"@`LM12iL0@ hMThL``M214dFCA#Ɉi 4h ha10`!& dɠѣM4ш2iU<40&LM LɄ`M  iD b߹[E&-:@TcPNA$ZҚe(X?FNHmot xFqk[#0` Kqp$@2mS Py!AElƽHE ؗ1du~|1Sm"S 4 x.x{ 9S@/i\-C3cґ +ɔ*qXDhFƪZTV6L+&rX$01O/*+~DZ[(5FxBdUE>0&^POMͦdZU0+hW$Iz[57" S .hV &D *+F3]SkYXh" F`6FDs"eǬ^-:<1gQ҂DF͆EF`Ta N(GcBH^v`29: Y:At`3ky\JҏLK ]{B|+ 2 NZ"\:OjVQ%M `Bh{GVbYsG MP(!acxB y4`t$. "l@TnmS`) 'I #%@ A1(f[JI"h0oݯKwA2(B j6ƥΰ=2;ZtG\H"0F5/9(P /_Fjg!VXD/ @EHtés,6$OT辒Uն\=aΦR l<ۋ.zG:`8 0@1B&7) gǎYY!SX&cQM gMANT&  WR.zs_Z[QeF(pP9O؈'ljL= Vυ Ta0%o#g0 ?+QjdԳ*FF3\BZ#c ?0ZV.򩽎 胤q]\g=L-=#ǽI7D1wJuupq^XWfr;2xHV̦A/)"qKͱ@PA f#u"hP F-QN%T(E$$&`]baY4AQ(C ʗ3rc1m6lHgBtzyQ~8A!Y#4su`+"k& 6 3f ]_P3dU{R/92^tC͌Edpa Py7j%qAU.3,VhRAõ@BU(D5fABj*vטʎE&*fCJ,rAPQʁkB(1 tz͊Ǧx$ y^AÖbA  x+fhY7MzfJ̢oyFQ12}n#Йb& g$W>@!g a ^3l2_`bRfZ(?_n̍LFVV0nZed>YĻgxM!EML$d]F (l'25E#(R  #b$MS0Li& V'"UO"LQ" LԳ۶LWYzX΋d7e )O^V#6YRI1 My*c^{HUӝIlg sVj,#1udP E9AN P/!nfn3.Kf{IB, H+G#^}r# DI]AVUR:ƲQi0Ș,1lκӎ@;ǬU~XK4X5QceH(]WB)ukPC UǬ//H.W =WC U8&^㮖++ix[u+uk z4.+#\X2Ɍ!d+LÐʮ0z!T W^; q t5JI! `V8Hz Z/u ǰ,`]P/k@5ִ+^8K+Ix׌Pδ DŽZ~Ʃ%UU\B!☪ z$(0b!N zƼq@*u\q]ccQQA$^A,1U(k ~kha(~Ak:k  ZxUcHyJ1Z*ՁbxָF޿|CzxchdpB8CG#4Uv/Xq/ *$F0ťH * ,* u)UU kT(((Ʃ%+pq^uƫPD(R)c$- BIqQPUc@*k0ABA 5Z8jqZ(R!ⴣ\b8UUc -,!I%LJ1HP:ACA*TbbUA)Sղ:9c_63&ɾc{5caϣt}"lw;=/ vPqTw+fO=V/}U &.t'hsim;VWJt'PEDՍ[l6GDfگDMίaԢtrAU03~4~%Et^wj WwIKwO{c ^i]w1y9Z5Z\79^iѺGKN,Ey~0 `ԩ6*$w*q*MYWbBb(䥤 MPړ# j׌WO,ߙíANOljk>-zlyJ:/NG_&5T Vi+fqTr̕LDNgrqrAEnjuXз\:#"1~? 3VMWIg\VCt}<_!Zjc+݉xP {FW=.2b6VGNYB嬒ob)W[6y:<;Tl1_6M\S\`_.8ET7,ϣį?5`ŚEvo:7^=3{+n D&+@82V#ճ"$2_kjXh=kxVOHҌPʚ^i6*NJv>\ V{' EC&dڟBskJ5nLv_`*T߿4 _)374%ܼeD>ߕk0]3NR$qƑ]5òQ WG9Q!hAcdmR^g_'GP5L1rU`CnlG‚#׾ћ;MkR },mfi+(NU,ajh7n]h+7fjB`Z{$΃+y :uC+Lr c+?j/ {$^L~Z lӲ$5}\_Ok˷04qoرCэ}8Ze09t_%s&?X2vZG awR e`Ca͚*4x(~ȬIgP%h0? {U:gQt*Ц{7-W$7ic*+SSnukgM7,Z-"ʿRotd6~h FK@L$l)>ڬSq$ВTR'p>D\Y^Y ]>45j`PRI͒ΌwEܭJ<=Ko?7L_ӷUpsg-g"J8oIf'/ӟ|VRhN$qcs9؃A^YZl0{pnղdWɥ+isZ"KٜSR]O]E/dW@](f+[Cxi_`x ʓC(ߤ%1+ekJtRA56+U32功5_[T8,9uKejb#/J] #uo\f5N]wqXr x]iDr^!borj7r7&q?pr1o9C7_K?O)(inĒ%jh)Jͣ=}DC6<ݭ$ಐR0PS:KȶT&˜7D۬*ˈ|-T>geǵ#GJV!zx"m R>RO^|k6iܬ;Lt,uaYT4Wf 伪p2UC[꺮d sلݒx9!Cel=Tϑ^ya̺'qR{E7nh=bճ{c47^~{<94k!_q7 ivn43)I]'uRuZFidТC`Bƭ~Xw4Mְ/(0"D-g5[ãļ~qgMgRQ#RЖhfQэZ>F#Yr8HdX~uY3f ͵?it1ts~?g&{~]f:Vf8 x8uѡKɯ밥m=giOOXFx9㵨Ķ;ȳ "eb?O6U#m@}:'WwM4LjnFz"lxه^L`Z䤽Z =04nW"vuʒH_rU=Ve" =8/;Ot7d|Ul}'-/b$SB~|i~?1Eˬ5mA=,C<JhEܧY)JwGrIy.홊ktҝ/u塴'M*x'uɜ.4fjPlv6h*wtX݋Ȱ+:Z9Ֆ)ݿkJ7A֭X|Mӊ`>M>QSvS"x5JeCaEiIDbRP|\& ^I(3+&uW%I2;8g{# |'.e0bt,}i족F5a'}^Pc lܩ^K Tcv%T4az~ؕX&&vSC KRZ=~%bxTmR|//;bG0~{]pp8-hli zL=s1fr5QfkMww{].Dn$u᲍NBʑ 1O(&\@P\T_,@w)N0+#[Rʼn3+/|_ 8\uݒxbw$4ʊf>%z;ɨ-BdQ_z#IP="[0E\s2L_=`GdS51i^^CEﲙ1X-:#>0l%K+Bxs(H0`PלTfDͺ~ dd/#a2,XJ9,zK`R=%gtPG_Ga}YpZ%bfdt^s9I;B&8pEy%ǧi%]:̦s67W.@3t҃>vbxl{LRy&9D$15s 6U;)#%9b#Dud3yɊ(q8D4֥e>s?k( 1Q'HAmNB!ͳrW%M]zL3)s<]|-c@F/Ɨ& QW.`߃Iv,ίi_KH,{r\3,bet`$F1`1b(ƇaD~Ȏvy,ҳO}bC${KDAofhi/+?,oіV}TξϰލItOn|ET "[S\ArA?~{aNAiyS(/Q`#0FoF| JIOWܙԑ3l(WuAlxX ;9WFg:ջݢmoꓠK#J =7r0ۣB>yu k T~ٔV<X4_)vo1zׯ-nkOYG)]hH*ʵwN:iD6cEuq,g2Z=sN9Q0ճ? Ȗsm5&yXGͽNmY{u-/8G5 ^!Q/~<kپ3ʆYbcQ"sWRtjYhd+a+ܨg"?/p3SSo w qyQ-4h}"lEy>%T [E2O?h-Yr.ĺ},) ۖWg,V`@@ imm|;sG5i° ZYkӵmL78y+'i 8 >2BKԁdoy <5՗&ơ/0F8yf=Pe$Cr%Zª&l(=ȕ('AR jF,//WvQlGC"qi`%+!5sr>!RGSq-Jus;@68&[|d%|b“cOh"T}gT8'/S^@oa?NI?);K~K{z=ti|di%kΦ2Lds癭 ۃ8x76z:YV˃\^ZWy蜎Umopp. RϾI4U)&} =՗\vħ=TչɮF D1R}LV `,˻Tg7*M<@vD3LA /p8?+F u/n~D.D;޺*2/zw$ n}ʳ&7ي"#wTډ4MYX-#D w,6tZDU6VM]7΂*i}$9W3Ԓo0$Z8eSPA}רc>8HFŬԙ*͓evs}}NJYAXBT-/58Qqf~= J&jWK;y[b:8gE_ U _%G𜴢̫u/(PAIT{χԭӥ ݱkteac2]%:9a{z|kg DZ[[廼a94&?ո39&YXiUd#\JlKӜ{MBLx_GV")]|ñY8*]-Wq?&6<|5]gu>êq/4? N+'ٹv.GwM}1Wov>њQ. m[lKw\)6*,~J U?r.} 2Nw2t&-c|[JBbv6V{9]Lah{=eV(AlӽɾȀzSS4O(| i,ž8YZ41ծVK NS35}Wt}VsA+-^nMcUd_eNM+ŗʑ+gꍑRRy[{#u>b=WS&港vgd:v!̚O'VST8MnQI` 3=37ʤyah, uc!coQ*ivwKR}I-NXѿ*u84_۱ rK7xvETFT]猈۪is% :N"N3&elݛ欗wK7Ifo7,q-y)j%䮾Fo1.ӆƾϥJ?rGVZٴ*}>o+s$M_󭫔8QN(T'gpÿKee]0[kW˰BXZXeg ,sj+JVWT7 z ӫs9 oA!<|RQe;26u ~xF-CSJj:)C5V,Tн"΀Welep.ӆ?i7&R0!{z٫zS҆4/B*yT4"q{,}.F5ѭOqaW;eJ_qB,:m2>V-wƓ+3_udޯ!Њ»ʸ{1tk[p֜ M8lKj[+O&zǚʸ[*t^j.WŸ.d/Q,fal06py@j3+M'͊G (u P |%%8L+ݷžtcSF,2F}~%)U*¥mkgrCeFlwɪٿIh%&Spg1hDC@_?T#YL ӡmdvrg]*L_m.[CehT>;}&wسge ilK{95Ju<Ӕ[ r5-t'@EkblT\vVw=&5*_} vy$- gXy$1*==q: X+ç$6FfGgv]%fɶI-.1;P R=ݞ+=R) q=YcYIPs֍'Iek:D8wD|:kG4K,j(z _6כo`\N%Z(Qr.cL{ِk_ha,Jߺ ?_ AVM>;d(!m-Ա:-^|zޑz]E6qƨQ,޷bx='7CJTt&%7{:p'LwIL /#c!h[>̰-*-HQaŜco}eAo [SMUtmnE&v퐜!_ nGb~nuK'<㺛I|'NepiTeL!2T<Yh><.>[5ºdC+[RϷb]d#m 02Z0VcjcNSb3`yc|bƴҖ\m墳7W]-QtTɚ/iBgRz馆>I:;⍳Ò9Z˾#tԞ5+<:W'ǸdɠB'!0{.}>nBm܆apNh򦖿6.mQvo:ڥqXƻqmm̦Ȅ"pKNϢ $gH2}N#eҶQ4,ת]-UoWC%&|OkEϐcA_j]6R s9W{dJ=#hQW>yEZ9_ 6/9X=Dd)n䯦\4+mYɴ:]x{XDkV=4*ړGj:o+M35Zck>XHrm2-x&"Rvr߃za0W! C)ċ__:U/&Fy,wQ_v"m:럩U]>cs|L` ~au =|bT`ҿq2Ǜonψk^,֞ @e_2,MddS,tcѥ ֛awЋ-L &7ⰆGgEn'iG>vH "pjby:=B?bEwZLAʏaU=KiSyuܑCnk,KI{s܍e+37m;hGYg>^L4a 5IBOX%J-M~nO9r,!04K~3U;F:osCG .y{G"ߝ ag)gge9>uK/cI}w89 ?g _$l@N= זy3@vOX`=̦0X 鴴v#)DXT=\ȍ+Ft&vcR2.RĄp+#ɑv4**VH:r"& 6JmǓƻf0)08]:V-䑒G|l{.SY|݋_|O7H̗Oj<(L<-ZV)Aʬn(xuzy5 :k1d/;f\}3u5[4%j}IiףokNT8-GbY0nj )l?7oMl +bƿ,E#1/ rmu>s& m G.:>IMG~jF4mR\VkKWZ`caB,Yj[v_L^\s$"}M[s)eeX_^?ac [~0PT qj]/akLL 8_A=7ޭЩjV.t`'@]) ](MݠX% ]G$0(YB+P7!97z@7Xf +{UaAEzxVJkxG"/vk\0Nsq={#i 7&aZ) E~'" 8x!A5z[Wg>!QN|3AC쓇1m+QgJ ܄PױZC4_a>YG6IZ+ލjR00}Bbo.< 0v"Qq&C8o鑀 <+҈0BrxLV2lCRC%e x@{$8#\2c~S.0W-kȥ:SA:p?`2s*m]+u9JUϯ'*:Vpl#FT)u/PsP!75$*HTJ2j;UָܘJ*ve`+բ^FZ-ej QV0$4E8 |iXbdŀD nZB*B1S"M[6|c@muj 09%W;RHwY3VE| {Ƴ0UfԠhـq\̮ܴdADN_p +f_NYCei^/vmX;!a, 1> SE0ܫ~j "w4,&L3l2cI$O1HeFPph%pHVD F)(>&y=9A{fl{ ƊQ+,#$4EQȪ`8dNbr,X( x uR"ZX_x`~H +&b< nX"yX^rJw[>" JQ)j0öI6'#X:~p@>7(1"Ń&dFD=CgHMr  MJ(R2clB ٙS4ƒq`He^\qPMF$QQܩŤ5&|t^W,Onf Xʉ0S$d8צFO8U$!"p?enR1O6j69Dn,j HD3+s;iʟ )atuPp&ZD%`Hyr\?>:(?dP1(k-5ڨ1Μn*FD0$37I-:Gr*2 ,"S3cȵ 2wǮg8Ɏm7>8=lw@t;/Hk()kg HNz𜴔Cj4?6AEU  6` sǑ2-9Iښp+vNA ZELW%YXյAT1:zFr84_"|n M'/ '_:ӬXv1%d-qՃFf.] PH W ZtOZ|[IL}kq ]j ._?C(["B]99Ybl6-;v!!F?P偹 FTgޚй.;۝[MCҨS瑟z{ xg Id7/D8GWI: #HGy|g4.T6 fֱMU ƌ'Z?7=KI8ͥZ/mȅ#,&lmI4hy#'\uF DUUc=9asmZZ`XFVrAs*U??vyBsڭ)EԲF%zL׳?o#h(")ʹYEg9FM90@4WΛd}*٤G'q|zL֢6 +(s+ظs H. '\cz̯i3ݧz) ?dd|9@◮>X;21yQ"iRrTɺbjf.װwNim],CѲYq׋5go%T!(/Jq?-Pӌ{ _%?rMùzˎxY])}F:mm{vjY# cemVy5p;v|&{?B[]?ӖkQ2A"=?`)yܞew`B"UbzYnxHY.!p"Bq9sOڽ'&ʯ\&yJK[2SȣC |yF.LUg巎Or'1 [biw\);~y|c~oQNja #r]s,Xk7g]²ym_שXq Sb"ӳc$ T<78w>2޼M 'MK]_C39ّ,hRT, /`a~W?en<]"cH$=Gm)ɖQQɫRӶG!eI*TmO":)+@.-M g%>g" V^=ё鱹d-:wU̘x' |Qį[ DڛZ_u)h55cwX9Hœle寖?\VwdW-m.7J,{Њ&N5s~u$%[ӷH7pg[Xu3Ыr낊fY!&s;td]xKM' mlwѨb.N/, Lзui̺]QnjҨZ(,h9R,0g8N% Rw%Uw3;࠲.ss<$'~B}}a?K/%>U>9* jH I\eڗdb(ؚxw d#+<Җ$(Lx% ,_ɜc1ûc_yY\Χ%D(eD-ah{0 M6^~{e8g4nk)D9-j^yʷiE>2,!P wz\^=lNX_)Ң2L/ܽemf6ަN:tѵ fl:,LSѤ.˛D'F;>Z-O}ztk[mV3Ȼb&]n ַY9jE2;u5Hn8",,|IVUCQMEH|1,&/קӨkRR>;eûpvRIGTm sRAC,ɹeг@N^z2HZbIΌkta_6uR8=x'00:*oj<4\,Sxq,qSǮZ7*%4Α1Y9gGnˍMmNe:1+c;c} VQ+7$bSd{[Y ٯ)I&ȫ8ՖG,Q8e2={yp^荈/ؽ3~F-1B=]c^u8n_LV{vI7L_y1I,BT.2bg;-&ͭe^c/MO @So >{m,<,\ASJDGLu]qep(2~'敫-b6|ckC[z-&V[v^ K;pl"}ƥI< G8|b+ N+lF#cGPXLaPWY:h~[-'Yx΢ЇgjޯQejA_35#iG_uV r~ёoub+̿"rEq:rEkX́з/w9tjw!yֈpkQ MSi.BZq0xO&pn n.i\e R/IfD v#/K=U\ M4x+mjh i1ZM-Vw::M6-xz=Q`{{%( PTu+) 0֥eX.Rbl}k_GhD=&O>Ai̗*ݥ75ʰNxMp'WE*ʲ/dq PfP~QJ2R"myz'V\6"R~醲֡ʵ`&7lnTLL@o(`&Ȭww L`v|X^ ˒1V{ّu@TvN}a[rE7 ԣ߲ww$X˯# ;Pql5vB妃wXKhJeO[T^nhI\9\Bj\T %E~3ᯪdR}>YA֫m3ba_`FƒۛW=' WUj}0+jwnhF$L:}^B4A~c+:˜Tj8,]b7 84EU8^F9s m-MRT(C,+TVqx󔬯!Z#yFa6j|D!]վ1/m!Z?c*6US|dVg5Ձoe@޷׬ʴ$%c$&֟dFe\C6+ܮf LQ\#~}{_&X7L_]Sx{@/ E|{fa'Qp hss%隣f'Q,/^Eɽ[Ma'vm괹Iibݛw~L#o_ƊvOeY"N1cCH_\ti)zpɽ5]Z(ҠA)k8vա~o"=m<~l'* $SkXR9TiR●o]cǐ/0A$A PC0,bb ` ,A5QD c Э UGZ7 h'%!`#%LQ:@@MYo,R~]~bi0f E,^+FǦ,Wq }8n)G>/̞0Eֳ rLMtG;|"L*X("Owye 0` :#]Hhu&NČ֜ ogU|=)BôNJ8, _=c,ATk+l9]:8護qsޥ ncHYbltj#`VKp'B Q"}e\:jKj; y37Yw{LIUic2PxFXQg)v@30 NWZO@e5cQ0-1qpMs%{-07_dQv!&rA(?hWgY iGFqBa(CJA}h#6sQg1=+QW vBz-H3$:Cn#ىE1t1hz i7"%!6@HlWF0l^E!#Xb lόOO/p.^6oVMf[`fGOJ$hE^se'!#Â_9q b"ÎhaʼnHxJA]y,I1^/(r!d0/3dD> -FBd",= 3Tp3_˽ )lgU⬲bu>91nS'TG \.̾r]1:]#-B34XdZTnLkFg'i叹FC ިY}8M)f ΚaYuB%ZAl/j?]ju륕 M]?k&sztK=oۅ0c3 ١VgP_lm֘ĝ(Q&Ob*6'ݚHם/c0$mZFV݃?zfOs2S/e7U/J/[ 嶡thcݰ|Oq+{/׏٫~%L[0LG\[ Zhv&)Gn5 D 'ݨSNkey̼Ou\l/a)WbU`gǁ?~B:Nkf1/ ncB[jaRV~ovGQkWe[eu-G>8*x6T;ຒg\G)[F DIk3%]^LE(:vfزlz8w ҕc}Sw;~!}59LzP+[|hu=yqei77};ʹJ*eq~Ope R5>g*CwwJxܬH *$^; lNQ[s:Z[,ښD߀w'reTl1U1fmivKFECx#{9z]cg47ǚaFhM>eWsCw4XdhPulB)X>3<^nA#O|_=b+^=|ݡ&rFa^MV0e z*9F*#+*N3[K$qyR"<ja_Y~WA^<(tijzt:5ʭůMeWjMW|sr03`THW٩}\$JF|3jcزU?COSOcNG2dvB.QWp &P(u?NLK/RUL~aS=vӖ~ Cy#g9ތ))E04T7r2jM_"Z^% F$AbX6NBٺX>KU.>|CclèS &BEx+C8*:#ZB=G Ƨ7ssΫpfqDq )$+lpKEe=aMRUB"Ć,xSIZs%f7Jd"~ fev5sYTY=ʹy5)PuafFF|Y2MXoy32c~_q4Gb`Ӊ ̽ͦD66CxeRY9T3,;e3aӸ kI>?DUC7Aהm[fպ5Y},!p*Me70O^鑔,4R^ ^6oH1Ȝw@X9? eX Ŷcl$!CS zOvZ?UC}<)yfEV$> g"1$°[li^WvR>“~_U|MސEqؽ݃錊 Ln$9J.li{JL)tO;6Lj(GrwN5E4}worbY[c f ڍ%BjeV3 l{\<|>{n ǣ7:oԥ ->>V`Je)v~G})9Hg93z<ӦꬫƔLSV.A_Z᳤ٌc0/|9(D A37l+C[KդFBW눖 ɔkWVQ8G* ki) m[&S c"4F-ȗu$&)p^x|9:}4)Ƣ+ʿQjN" q.Ωrb㨙50<{G&μYt#JE4/^nwLi畘Ppqow'E\eG-ERv{qP hFd(,>VFO_:aXc #Y+.=X^'3Ŗ|rG>І^cFeQ'W@fdaQTpެvHa7_a6H}=Ϣ '0m&Jr4|mbZ_韒G❚&C Aj|~aK`g,dĠC {i*h&4_d1:p;9訏1>?EfR]D#$rɝeGJا(DacjګG*6a?c^@ om:{avQ=UFA'C2d@Ru y/CjY7LNʧ[T[-} l\O:;H+ i7G]suì[t'QRP”ĩ!FoIZUD+Wwx .ҏFm?zr>UHjn[luN"=A*jz!3Rhd!QZK-TU- ,WSE TW~]:pOU0PnuZKlf|uc|O /,m?AH;L ]h[|Sara&*o-#9tosg'N%ϡM/(&퇄MI_9HI%F/FhNUJ'Q}U| lc"j/17 hAfMIߵj#eKD3u+&v.ȗ0=;,Y͉SLr0D,e6q?~C6j2(JT/02W҆2z)on_qU]%zZx-ǨKGouڨakUcbu[Q,zRN}\Wf$\\/BF#~[3ڿkg<*L9͙W\Sy )<5g]V-Wg1Y]A_dH\Rs_US#D9Eng,#ѳyeyrgi 8(u1 U^w: %?6ozUiHF.d+e5 ~@W EC :D݂ GxPgFGGf=R3_w1 iiv<0qcI k-1V3ż 3`̺5vcjnEPtxfYal:+d3(кEE5wHH{b}h[VE=j5TV[! ۤ<'cu=mB<="#l9Qsi@^ XmpQ'.dž)],sl%Nj>NM5xWSi9 F×{@&//e kf'I\Us$;N Ś5dEՒR|?s}D7KepZzGh<@"6r/iYRH<xkĆM%+j,xU:xyeLz ^gcB̹QTi\%jT04#wsy$Cd!vI5?6ѺVC+KUm4w=#: +dU2uf3-kUQc{~]O*Ioyg3ڙ"X`j|es; 0Ȧa'gm.s=4Ǘ:M#{С]"SYº4pM#MҼ!az[$]*Ӌ&eRݎ̂1;}]Yy]w='$vޫ\묰 9?=7~0hF+N{u ģwD c9oPˆ`ͮ cVTwe~qdcY%W=kFҕ.c"+M̍MRGjqg_M .78.!<kKpY$W0+33M^v;LzM϶ի仩8cZRM$|W ղ+%^QLm shKiW"'9zx؍s33iOlc(A֫Bo+t/w@7S(ʹlHH Aza∟3dyF!NhG7̅ qM>0mzՒl>EFup$*Y j44K 6c?tSn!_@mc[YAxGRI*fq4:#Fru3zZ;--'p"r KSAJʻVR/9@Cx$z)[ilj<xokh<$"g7 b3C$Б*8*;TUSȾ.Wbv J}\(~GerVpޭҡ1M;p-C3 ڪ<9ڞ&N+畼@5;ڗw[a/_gߧ P[=&㞞#=p诠NZ˪|+)דU kvPUoa}3=/)&wĻ 3}ǵĵkwtz.e7+>6GqQr>hKvKQRuF~F 7Ui$-' &bt"2qoWCGSKz5TEOSg(^|MD]?-Wpd RQ\؝N")G@^3myg X߀L>X^Kf"Biا&m,柝GF˰^d8fd5M,"/DTFf Jܤ(;T'+a#)Uw h)VYcm:G~'bbP(Tڝ4]o yKQtn!r:-qFЄXSW 9mnχ S̿48Nii3Ic\3jjSIUwg?w@}/ {Pv84xxqkb7nw(JA=#.|rK^5eto Z^7-=١-i^=ÿD aJ&CmJd׮mTEHRg8b&ǔdFSljHR m\;H /TbWYqkrx ;%-fg=ngQ2T{fEiM]SQOѲACꂒxXq@VR`ټQ۩kl1kV?-/Q*|jPb>P}¦<1{~0^%5ar› EvÒ=u (O4m!MRh'Nq6n;}lx(r[ɔbRC.we!$5gekڨXOtDXԘ{lɞu^)`xÌ,'N5H>rQ].ҙ&d[k]ڻYK΁oکf٢1,_-=N0 z(?P @ 9"R@ܣH P)e€x"$7eS|qE3@aB$avj+FDux0+]UGAkQ( DA*%Bοڸ\ QB⫊)OqǥKlkKŐX$R ?P$Yz10-q#&. k.:=cX`1+c$ƈ"(P $I$I$I$A""~0m5r,V5׏X%Av #ƺ!^*:PQukT:KR^58%VCQ(bc<\jV#~-<@1 ˆCGKª` D]XzclK`׮8zBCJY Xƨ!Ƹ,8ip8(%HTUW @q @~!z\UW^tK5B*pƺE `T/U cI/!C C$:5¯K]/u D Fz(TǬ`$,|Zk c%ǐ#\WHc!zx`"  ~@- rqX舁D(w0: ,P!K +@@0&V ph1 ##'`W ZҮR8ǥ׌0oZC`k|  @zqVxÖ C%(UQt+ z .*Œ$] !B?tUW1$¼`uU6#o|6/W BF:PakƼkֈBx$A=cZC  cb0?hy/\,uϚkIxԅj5/\q1XX^[jq  hD :!~ƴ$K cutP1U!xUkCkXZ5:V (HPA Ki *I$ [ Ɔt kJ1J,c1UUb֩j5C(HBAhRI 8c-*C+JC\ %CX )!])e**( C]hRA%q5CX'B/(0q_e,6s:̽m%0um?= Tw[c9i[CUQ:^:uӒ?YĘjGWߡ0xUl}n f!>~6,_D!D>'=CH V~S: .#=M Un,:HiNlP[NޮwQ/7B{S7g~6 >qk#ZUOMhE_?Hoxָ=4*Zw+Uo-uo7aƩ 2'kVQ0:ɢF܍HcviAoqvg;G }TL^$kT3o4֎@~ǚ 87qhV*Ɋ훉^}%^1NE[WYBM>#>DС2a|]Hcn䫍o7?Zʘ^.KK[PGbCp-%ؾZ>.VXtH͘0a59ʽ#:QHe5_ WO ^h<(^x3ʹy<%O0o\[}-= ]!}_֜:G[kĿA⑪uj菮Ulx*2UOMGX8G"qrdv<Ӧ 7՝)0`iO֞O)9WghR.CA"tG^](zQB3ׇj<R`{:6}W-8mFIM\NFxQ-ӱ5waMƢQ͵_GO̷Dg|ﲚ\_-wҲ3 !2ݻs;UiTDD&МŇ:4Osv~K{>+| ]AAS()!Rd; z,lGưk#h1D0d ͸tηՅSIA^KGT3+iy3r]@x %bAT-$HK"6IAWk +e"Hy0|{4tt4gaJLw|zdVN>(Il4()"=@CBtpB$(PlY /S7 c%JB"Ku^?5 7P7R7 Dc$w+eX?;?X6 )ѿ_v&\b*Q40{4C"[]ˬX p]V4a"QPR.T4. T%\ ,fp? @ Gn,5: Xý{mOl^((m1hJh#e<"?OӫB U72R&XI}KDAiPKŚDTꟙm qsS¯ ldWhP$T3 :P)Q@*Ht(4H7q@7dzHDADrH%G*2DpSQ(,( gI D8C!DD(1;d7DxA)($`Q  ڔ8BDdn!XD$D x#@.@Hb hID\@HzT2tkZx%Hៜ`+bu]2ϱXؐ5_5UThRAOm l@870vUrw%t:suJڑumeMDm۾_粯|Fos?c)yc+cs9xU;lCB; F!#< wft{c6Ib4H8(ZzZز&xX"ψ<⑌1SR@ny34S-\Kp0w cЛzmٞA;ȑP],.C8~@ % x7y#< Q5b[t0LI*)sP8:.J@hGѢ$R,.@,pt\A哙N.7s.#;5Qf#TՒ u 2c7"stin{|12AVăBf2#n 8xKpT%פ]R (ޜv;zylu_f(+D (#–˓ R&q+ @3OBIIa8f6ry6UG "{orT-hCr䋕\~hIQg 0D2F8:i+k qpCF{t:%nE_0U^+cu-MjPz`LZ*Fg@СGHq;y吴x9h͞Mi$:؄ VPrele@kx%L=־SJKvnlK"cwKҷnj $S U};֧TGY>'y.]Z^xԚlejL@8Y@8 Ib U[1LQ:l4zeWxTNyF:~yI ^*5X$'$YKI){!8/c[c.s/&aBʂ; )"_+n}w>,^Ye9ґ0y<(a1iݫ1aY5{xGBPPP@!TIUBLQ $1cHRIJ"XB R @T)(-TqcL羜SxܟdQvIݍz27Jv~~3Wr zn},|چTP@F- cH^[޵+6S8 \ߤu,"`>^`;րLqxwlҞ!Ik&N *%EN+\Ci8老Ѕ6&BAhpZGۢU69\l"Q(EV Nv7jnT<d{MQ͘odEA:c5Dc7Yj~#uݗe5Rh: *b]?>9d"@xȬ6vrl(qD2&E.͔ :$!PB(LYJeB  @Y"@K!@88AS#)eTBPJ1DrȄnJ E\@KDA!$E@-eA"f@D *LA(FHJHэ DQDP b RP a@$ B O9@8he %I%PD( b3 v@LA " I@$W )@@܄DtRyB)G(.P"_dJNpjH&=;.`J"sQ0d"THH@nx'|IzxIQLyTOi8F&&*pE5b{=خxI/=_Pkfo7 2"RReEoxnSp%5{,ŋܭBfFI^c H#%G#& .#;Oa3w cӨM -^љw&GHV]aP $9~sdMAW`#WE9DaEi܀zw / B\ v74ae6N6Oc(^qZJ'Uy!Կj-'iuydIS_eI !%Ie)JWwk1o!ʕ|xn+S[W/ؕ@:Ĕ)_ujUɟsA&Ej?O&2"Ud樤*dr"3Er-9-*vs'o釔4AL{iVpF7}P rBo?{!EaD,IdrIVKen ›'%QF<зN%aD*\-NހR.Нv; 87q8)Xr_qnYCEN/)s}LR^,*|Bއ?4ؘ,¢(N n L_8gF5q02;Q GSc l|$rL5" p QISn~n^wDnqa}B/h" +]((w%QDA+ b  DKqjB"lWk #d1q(Qe?fcD3 ,6 3ȾԦ1>)q˼Iߺ@)4k [xo+Vn$#j˂}4{p?g͚=p߁lE(.y._o BT̉YP %Fmɐ#MxZ+>A+o\t`zoݗSuHr=#@RJЗvٍmc LAua. hP`;`p|.BU@ǰ>\>N|HЬx028rLioYvy`Ah!kWgC<}Z3~Odxzjk!1}TFa*ШimcC*T0b UP2*RK KGaUPK (҅CZ7}il=nb9HRJ,qcR$Z$-!Ut*ctMF\6UD$"hx#Fը4P:NG(aUQ|*Y0:wksx gʔ7U]PŠI(bU8B# @WJ"X 1 %T`RJ)I Iii B )RIt*5}!xIRQa`kcJIP RqTC(BTTc T(ҬPHgiQY ˦6e'݄!u Gy@"b aP.L4cv DNJ Scp 1"""u:""ۯꁈ>w|o{c! DLh4|Du|"ܻ|-FEB"} H VPHj""Tun?Hմ@=Df98+Yѕc~vm>S'8 r@wtoYyo@B\Qa*A3<@@aMVX^oѤ8'yMh9 62|٬ZFL--oQ,w "gZ¿\r2L^LAlCi>\ _B#FqgSx.nUlc:F:1w WuŐ%B+<#>ծGLض `B{tHf]V(g2BxqZ4!?H({ڞ ^D?u-o^K6Uv2|@ d&*8z<6$!&oo pk =p4l##Æq̗ܥgKj}J3i((VuxOBM]%P4IL_cLI?,ho97^e|b&LqVpFT X !L[pSɮo\Mir,&=䳞DMWxFkTGԐZp>lM8R10nq=[V 3+&zZmA`[l+cԢQ߸uYũjeM6I͓i8+DQ̨5sl4MIQWB#bT2NVa87[,o[fpssgz:Mq]2zWMYPtC4u^vsGVDLǎ|ryP'sHL7?8LS{m+dAc4L NaU`V]7YA"]fOTwKᒟ ho@:BJ䧬}rM seYI:Y)1[[Z[X:t ^VDi{I :SN}uQ0[xy7:SFPRFE7W DGiCz{W¤̻; B,@VO[UܩbE?'9k G x~R mkyW(16V?i ؊1;zWc¼jqhy:>yߓ5uM3SCE7pl8ұ'Z'=ԅY6/8$rֆwO%礊C֩X7y~Y7NʌGmI 1,@}67D:{cc~~;bzU 0`J,sVl%DirAјw|] 3饜=rQQChc, PTT UkU0'lWI!JPX1J)VJ!,!HDU JH*XT XXC4ZB!(^(R¥Ja J-*I$ҧR'("04#x>:[7ڱ7WEP2 \5"3Zo7+f tO 7hLEJ @ vDrU^H1B*w5~2mvDlFr2c"ӮQehm!l#'?],:yK"ն!E))^*=8(d@DvB @,P!DD (V(WDg@@Bb*rJ" єD"M9D  @% P":@> ,EU>B-EjJ!Тje" NР@lP Ap! iDEPl(*UB"LJ t D1(A(@ҁ @QCADpDY'aD@QPI@PT| bND'DD@D@bdP"KHQ}HDBDH"$ԄI(8'x3DŔRyH@r&J$$"L"" " "x (b@DiJQ @ D R(" DJD PDA@<H(A}!$ 9D D@2LP^J&h%Ąʐ9d @6" QD  D:B"ϔ!B3%! ܐrDDPi@DHrYԠ t b8Rqy#5@€\D.7q<5A^Bي$̌ iDIlb.F}<ʹ%AVs'V (vǏ&+y;ǧ3&p>(gu+@Ŏ_ܫ>.Va @\&5o@L$̓Y^XHLe`FR*/$ztbPfY͏p$ WS Cut  ]cSbAI/ќӴ19G8:51hmDŽ 5K-T_rB- ;"le5RP}LP\y=Be[S'2&,"nbD 5NsoSMgŋ/LQ&y6O̫ŜD; 7,۲'l(P}`8 Xz Z `h}Ğ _ 4I\8OmNI@T&ա+Ze/,1{$wp4d6hᬯ)Kwxmp8ᚋv]LtfsOwӵ'@Ъyv*'4Bz9g0je FW-J (Y DN1 %9!B$XIIQQa51 D-P 9@55#b@g_яCar<GEte1w/,AK2Z@ €dvsVŌ11vљyA,Tq`O׏z<+GTNH4ÑaEǥo=xZX#per~>Aç.I6A\oʴ%g/cߔSِ``mvM:UH~m^3dakUr/o*` W;Kɭwk|B4+9/]*%" w4(;?BMrѣd GY3C٫޽?FYxpXT\jEW~}Wxٔ0J^@w ]Tv;'vap;VֽMhn؝FJus׵ Eɀn *J'V㠇[V 0g,-3.@D`8%7E}xF<85:~Tw7[gVf؇809JzitLs?nНi!AGa2216mݞ_6\cY|kmTI!e 7X,6`5Tsc}zd*R.J Dr[a{893͢9QIYUH iʣ6JA^Kmk mB Db}PP=7]z(NRs!HHA!:@(e2gq ^OfP-$ $n CeJ:vR HJa2*2I$W;EGs\b!)`_l*>L:I*>l6Qox IL5e9KOy2[κGy٠QQ6.2'M}Nk#נYVh~543w.96`!Yxovwﶧw6D{{y^y=N1oj,PH򠘟Itl}PaApZDW-;뾫+Nk:F9jGOCẌg<68}c Ln*̯|61MNȖ!+_ٮl?qOPhADa]:ww⮧aMFN jS|M:$U(|-WJ|~N+E<)ͭ[`tvexVN#1z'Y_T&+$ۅ*|bmb40 BAɌ,j޾<$<;<Ф;7 )A( cO&#<Ibu&x[QeA|Bg/'9Ē<Np؂NE20f}ww(6æk"K.S^i+hHIJ$i-'@ypT뙸d1+0#^CޟK vа mP$5-y}vߎ5/ͷX(Y#YPLWcMpR[梌e.0<(wm\Pf Z6kQ'HG8N` gI4gGÊ\x<ռ,|sE[f7\LkQׁ9F]$ctDJ>QU?Lrp.#Ug:ۮK S< ţFczW@0RA$B+ ) !I񐠔i5C\*ޡC( U740_(ŐgK-e$UN]R(뒤-IGVcZ5`R;ԓ28hRLЄs#S*0b$;/Kh7:D@as~b/ld_}gQCAA^*b$U!H%+8K%*TU$0RQU'RQ R(b+Kj*^1@!0$B 7,1]&JMer;(OaGf<P[vn=0kPo=u̇݊qkG$: g؎咧3,vϯ?7U#{kT/w(˵EQ0as1H* s@*D̙ FrA>eȏƀx~%"b?z攗˩+ Ŏ>@{?`$j ${Hmh JDF-"+ g 到V6R=r>I:2ǣn@kW1x{'׊vnWZ[}dDmPM%Jf|nÞH*N !C9plNmG W Fү"iSiHX@5q 7>Oi5yS/|t^dIQ6'qgxpSeN5#z1? R]5lI8zo8T'uLh"Yox;u7XywI;z#(Yk a_Zƹ3[3N[Q-eո*Wxɺs!MrI8 O<[ IA |p+H|9/}M$HKTmAߩgwL~N;ߪM3O^/5g![- 3}~(s  $ >}+;<$ H:Zko;VyreT4is! 6_Av<J ;w1ϣLhF>'*8\ rXں*X2])&iWˆZUD!ڠ HÁB07&a⼵Itq AZnO2QcUU[R^eClY1@Mk g6vV՜z lTV. CrIfS!\47vͿCW#mU0Wkm \v\ǐ ߰gbXp4Ƣ=/&]f)?>Yֵ\lDA],b(( )S8x'|m >O1D @ PfZ)V|="*2*|V"{Hiy'wj(q׎@XB~U ʧ2S %ٕy$od<$ĵCPS *ݦl6ĘqRY]iSɀʢ>5. y.+z+a%̷'745wG- .rz^UDC"Ŧ N/cﵷ"J梃;щqL_ykNgZM+ZdN?Zϖ !<&>fuTGw^?ZnÁƟ{`YA֜Wa\Mgq;!~h,r{߯o@p R}=sGvE˶AOAp ~`.TLc?R85Ń;#M*_qf@,RߠhNSV\- V4#H3Qf-Gv/O#g1/`dL $$@Y(D xnOثpl@l_WRv{w}&`6gjѕ[ljִ1UV 30i7CLy3*s6UH]oM~^}*Z A{$fmEl"V'W1Bp.ݑu`I>/jR /Rj@G,XRpZݹZZ|+1ͽ]yo RQ'WWQldG︥r:h-oӺ?cMBJ`TKF#ITF_۳N c|jw/#@$D$*UH(P  CT),P d! H$5BZ#J5Uj#%,QZB1 BXP)@HE DI ui&b<[?ě[$3Uv9I ,KZ$ao9lj)xETiNJw~APwxΫ8?kjNSPwrlݹ)7]h-DL]Rρ5=FMT5p^,ɍyV꫞n_4 fɮQztDznc$z @v x, Eb*࣪;L*Hi*hDq1ZI~dt Թץof"-t(!Hz g*FD؂=y JWkLl]% iS}nes/L1> x^U<e~lډ_FOb)jhyW黝Ȏoo ŏ]p>^ %MyÊ#{s#d:iC [c UeOinkg8$L+| S+>u:s8s]2s{EU3ez3N`[p;m162Ι;@ eqbBpfj=N*A{:VP|EDnJ=' 7^ yt0bLoRu ƫΊ"1eiq OŹV'y&+YNDYh n;nClgX? fW.s>:B 7614ᲀyunB:_%@xΟlX!pK4Qr"{8nP=4w9ב.V-R 7䄒 i*atbEU$X#"w*4nEXDwHS=V_&/ #m\Gy'j<82 尶d@ `rJ. QI īަFK ۺ!|p~!=#%K Ӏ+y@fbEU >OA5_gt(gAR_(A DX4$hӇLioI}G3„p%RuӘ.xڣwΦ(=E# "8H9h6_vgYHaVmtib"A|zڱ@- )ΤPf1h}Ĝ0&7ۈZfDmj^#Ֆ.fZ, %(vjA,#i-Q dm* eb2n#Jyϯ꣞QT_ghim ~nwn;x)c wIÁ$ hL4,LN:fۦ36b$‹6at_>\)O;J,(PA=V ucl(JB""! URL@P(ܩqUPQHa )* BKT0 X@dQkUhⰂ⢔PUUBUII$ (U@E($ xV* Q "A(@B*G aҥ X ,*BPI"?(|Ef`;^1%[YAj Յ [=rj' !A7擥€Vr:+f&"g!nXˑg6tj59Oe~ ͹JdQٷ @io^ O S~n#ថAY*NLp1/P$̌WF8w#qjQk Y9}qUe<_ ":"q#d&qꌼ \ͻxiwNHk_à>?44>T'"{$ÿ(RDOP, Ԅ !H D/`RPsJ(O"bJuD|H.D"A.(6Q3&Ԡb]"PM +2 @2)P7;Ju@$c[Mz !C\=$G 'WCkgTFw~jH-W4ȗ ot^`^hgtw32kzrGyCd mG^{s>u}844qyz? ^qd2@};"ZApO|VЊϠT"y^+ K;1oLa;M6G_^0 ~Guk%7TvuB MY.xN#%QbDƮ)+bk݂R^I3YQG)(CAx50)ןWv -,ФrXʍ >t!D:E(GN9p`pK-yrN(W&1pyjD\&fƄPx҃ v(yJ rz  } /Xu>>By&mG(SC}y6)g2&X/Q8U:B3WK!&=$^# 5QFz5;BhEs!puF8M :pʇ=Dgzt "XHk?ܥ&5O ~ TvذP)Ad۟tTe9I}.nJ.rFdI sj|@xQd3j(qݒ7ul^6%LX:) 3ךPs-cCihxsaGx?Ԋx.q;oړmUDCP8 AF1"IRR䩳2>~)Uy:s1* 8Wr֏,yPН祑 R$߉D*?uSH;A576WfU.{`8!)F{śZLkנ'kQ= h"M*ck$%8py4 ,jX%$]Mr 8Y/'(rraL{C `T|8xEdžھ'GsJBtί䎎i492G|"[~,zB_LDR4b`)Ѫ KaxKͱ)EGL%@))h*AjK@g h DGTGHA1(qHDHQ֚A@ ӔC;ZՈH*(NWJTHB8[![oT 6s(8eLIST@ʝX@(R% ~.43! ! A5!9G-TD v""8֔AeP@0E+$[zY{.)--< Y~,/1Mp=?ߌź^^7ך@%L[g: 7t/2'_t.ydVl 4#Vn?p6s%0QpN~hbiBGYX͆.I#iVo8$$H@cWx*<-?e6 iVwhf;O`t )oRof>~yқ6Fdl}y$ .J1Zlc9!4$oPZKkaB"]!_@c/G-XI-7{i3\9B2{sxK[,*ε sp0b^V|X :oΖ8n 폳\>]llj-r~.B œ4:EdYV(FK+#~ mdT.pXln1K572xHr+TSv\CvZrIE%m{ahc XBGS3OʿO}Qt$t:xZhEB(ƂfdI',HM̃^7q@! d/ 1xK'ks 2;m }=S8-0S̎0`=0!J (<0Qa$b4PaJ٫PW7[LX$-KPY' `9 )_a;>dVIpcMn㍯c_WӈSTyErU"eٯe ;_n>+ ;w!1 -vg@w !F{2w;g[xpJp3'S3I0 MxαGgb!G@ow.('Vjci8Ѝ:d(F|9syO!6X .c](Vf.y ,YF- ve<" -r~$p`8] 3`HHl-wG>FdR"| &BA5*XGU` A T0$8|1}kWM`7$D1`$A* "5! ݹ6~\7H!"kNk=Ү+Q9H5,cI J*U$ŏ $Rp* 0RP (` KB!i! +VCKA{ }ZHQ8qۺ9C?ughOG01j D4?*Qg%UxsH@eȸmlC=@&;XG@ǁC).y~Kq[HN S6P B"#ȮZٔ@:Lv'xU.ko38@nXb;ԜJ–',kjUEn|{HF):1Vi2!j}bs}\9Ҩk̯Op<`-(avWf \B2q'B&KT$/@27@u16 uXFQe\$)fc0*l= ڭu8NvyAa%B)Rjxx 7rq|q܈>9" a3e^{uzeUC wP a_s=~uk ~ߧi'Q;BG[xb _mvZl p[LP"kȪݍS~Ux!tr<5S["KB_,+o?>%C 1jY6$Z;;茰HE˂GEHk"yu}>Z?+É0M`+ƓwzIRCƖ_'c*[@&OR)b\KnU-:{ !uoMqמGv}"/jW&㣨+ ]de%{3lΡ1<9wr9ގ3^{V;̫By<@):&Bg'?߰-1j2 ߴk1*._!v`1?o 8I ƙx%cI-[Zs8)mZ >a7v+6щyoGҾ(쭥ۃ=g`*;%~}#)e EߕM'&R:N]҂Es@K>93񩠙.CD:al|t?G۳+&o[o󃷳=|ɧdӱ|j-JW9 r?rF0;A 65VK*7:D7}4$o[6 CYooP||}o6 [W0RPCм@|d%;Lp~iBˈ;h3">뺰 չ)qdhj( oVUf5=IjoAbDgC?BՀYo=xD6SHP}Fi+^?a[!x?;do* A 52@[ƹT<&<͌לfY`%JH$0ˆ YrD~ib ˠsmlۙVx^Y7OAS;r:NEZ~9_91eyQ(.Wj4b$J@8C $F8Y53ˊN1ȇGdfC0`Ḑ>+oqm3&E85Иg/J_>'R<@$=  B5gH*-VBR   I% ,qCi ^C*%G B#7UzT*E|%}.Mfw4[vb.%;EG9,qFiO|r..z`q[P+^xۃip 2Vq[?s"pY #Xw쓽uͻJ`_%u|9 >#, 4 n"#4Fe>ZWX fPC?C5A"rkh-6^b @48y"ɦz\fZ>sQO(;N80|4*y3 e(>PI!Z;fj[_9h=]zk.;K -~Rmy+î)MR-'.PxL(n'Ѐ,͔`$dA"PD@"mJAT )(8Bf&0DYD/ O 2@DˆQ Q)^2 (@p(D7DQ؀| 0-!B1@lˆQ+$Ҁ!B @ByAd(>dPP E Rk6TBg@D4@b A +&AF((%  $ 9̄Bא-p#@4BSe0& IڐQPAR @f(d(5ѐn YPt|6(XA(AG("0%@&!n8D"FD@(%B @Q"dH@mrZB(@l &h$  :b(Qs (@LP"'N@BA(球FP(D2"@DLYa BlB b3QRxJ u@Oqz(b}Zͫ/Kyqw<Қ+xT-e#O,OUʟѽV6:CVHVquLfQcEFQGMIw9LMcYj(! ƣU||eYylsƈ=я3_eJPIDŽts'؃͠z8`9GhS1rfHLPI/>"o&;k"nV0S!fz>.\Kue2h{KË-OǪ؋ET 0]FHwĮ3viDMI~715Y-?~|'\b&~pC?PkTV x^ṫ|+ѻع8>"O|H3rx \Az}E ]vv;JB'q$+NK=hlj}VswX[MW,"s}vnux\y7n1ifIJ`+!q띰~߸K qYߖn>8!Po ۻ}|G4u0Hu2+:FZ?Hrlobv:WI~"+.:UP:EOa$lHλ%9/Γc:}1 b3cA¸{Ԓ#G,[Wyro[ty#&=ANwFٵF,Jr(D% A DrKJ@HK @="%4@j@51^6ZQl %uI^z0HBdg\n"p&eUC6ypJgE&poTGHqI _2͓íj# VQ;TB_0]b*U58x 2h *(H^i?U^8}|}/J_n^5ː癟a$ Xـ BhP-v,rR}WeDGH:Mv[F2o[ NCʹʇ.!;گ!*0*5}<ۛi^f=XU̯6/~8o;W(pmȜ Hb U b@E(R\Ƞ ( E\b"~g Ю_/##W#@X1VF҄Pi`\hF* RB0B4ڙPhfa=XN/Aw˜@"YbňDuhT$ $(4BJRQ¤-,cI(  .CZxJ1+x~QA$0 $uA<  4 /A jU5ZCHa$"(mCIi{ gZzbC`xC&#A5 _pD+S3²r0(l.%xdtPꚕukO?t̅{]9N!VH*D4 !ϾӮc!V2A받|CDP ytc{ G&hQEH603),~27DDc‚C_g ^ē8,#Ύf孆!\R `8Og /5/ JsS4,M4Ek}Kl`5[g-IA 1=DcJ,BY0Lfnݹe(\BIHNH`V$js/vKЄ}rh^6f .TFnH D7> c%cW;k#Vj@Y'\j|ߘ|^jmŶЋ4zEgno9T]^EgBӻՓ>7H nG ޭ"CV*d%z~ƭIר,ۚP7RE0 uwW kM*e͍ɽ3b?7јwtf0L.L];*]PzK"$~8\7C9b'| So'iH*WӞ8x& ,#ɤi(ȅC?'R:yop=n*?*(AĊ g+.2ǿTz4ry1NFgY%a` w%{ $߰c&ݚ 71|?d\O%"xzbv䆺5a~V @ڵ|@ǑTRSCϚb +>k8;o\fbYk$(mWnA GN,wޖv<}os/Jo5LjEr߱/ϩ涐A)>ˈ^!W[W"<[Np,83:mN*m'T ݖl#3Γ.n? /%BB)ԍkޞP70?N hg%$U(H9` CR$*P!$PBFK*ARUQI* J@V`(V `puiJ5T 'w [eww 'O59ƙaKC%%[bJjc61GM8JA zRJPBU H$Da%b 0*1Uí* 0a%a *\qjU)zi- X]\q cp =ZO4${LIOQt5>UG#GUABA(B |э2aw\_o9v~ $Vsp3A o5nOҖqu$pڱs9|pP( "XH@(A(TJ8 (J BQUY1b RHWXJt ZUBkC~獧ZKFs7pOP"K}k'1;=u2>tќSy7$㻎z?L|WhFP(bq-Jbh1be!}>C9`֩EdUUpB\*phx?=)t;ϴdrrZw1^(/9!D;c.sOGӼ{L'BT>CRC>(ߜmҘƝBW*S+q~'pFo.`Nk#R98AàI"hŞ ?Q8xXwPW34j͖Oe渚T, ƝrC~?r-I2klQ; ?uLB[-!fe|NX_giJף/PX\Q@ĐuLj6cOjQTy6`@rU3 @f 4j#6˼Aqx:F4.CM|+Nw͗!ܦ͸ƞudKa?g63nì0)vV"EfoƯRO8Ҩ%hňt;LIzƅZ(v>?9O?Zo%ToP~G  1U*d T$,)]ࣔ:\üfhX\"HC#NRaFKY!Eq/%t:k&\_bRG t:aT )@A*K%JPHR` 1@cUQ ]Gɂo;UT_tP'73`g6ɐޘ$jC(m % bQ9zh9t{VKkb:"9ݱ%zdcWK@@?_IPmj֬3G=:lՎ}\A _\8-PV+ZEeן_*T 9}xg!C'± uC@;j+1D,,W]s,%e,ʪK Sh)A¸ _'9-4 G2uIߛBR :t~_z [ Catyu3m:mCG_w H}?` ٕgѝK[W886#hb@}A^cӰ:;ˁ+5~L8O3ϯ=P@i q;ac1 /iA-`tL^!B9gaF]<D'a|N0mbjX~1Ÿ'`Xoy CKm># P*\;;2 1r cw/?&&9᪯J\[zz%ΖᶶHA.HnF6[Ll<0i!>4Ʒ~Ze8YۻDYc!$Oȓr5z6p2;%a'j*%,fhm*P `.~nAXfRܼOcU l0Yn6=LeAs(,{x8F2Ot;ڌBA kHEKi֙:҃uNZTx9`?!\%dgX6|8 ~3a =*`#16se$iBȘXvr߱ڭ~3q2)C Z~An"[O8O9N#5y9GB("/6;FHInNNzz&YN7>ɐWfY/Ҧ0-k7yWޑUnZHa6.9elu/v~TDI 8QZkLk3J++xX]cDr%@u݁Ln3ې% K4=k+Lz+ ߖaA_|*;宣"{.y_WJ +ݪ`ILN7A!v˦QU;s xA1Ґ7y~~?a &&X|AclBO6qvC.RoqYtPI?КRaw↥9Uqk*R?S?o{D.:(}QVBtf覂_|r=.g"cµд/5:zݣ访6 B|\+r{.+&=lbpBeҩA\Qd:G%Ȣ??3cx9gs˒Ax]M˛~svahTA9Qp ?#t7#HWgs-݋ [sw?Zm_ZYr lϓU$\6E\c]f?a_fsA2~7j(LkY9G|ʗe#Yː!8>YVɦۉ}F. 4 ~u$o[ɻv)z7-@8yYw(3\uo>Q00Y:ɆU2`]`k&aC%AlV:p$YgTPɅΎ Ak#OI{%Q'ƎrVh}aW@%f;:x5eJBQ,2 mI0*6uTX)Z%4:?YTeguϩAQ/O7/ }?=s%[})w?/n2fV᢬F(|zT7AAd K󃋥Ml;}lYݓ8G߿fგDY9eu yqu#Ϥ4|4˟U4TArn3RM5~&ohy~olZ||c*P5K?"A\ sgwbBE=ƣPf Cun> ґ3ZqK5V[d`?w(wYMDNluV/ !S9laﻄ:BFaW= %[|>\F@,%&MLvˬ鞉tCR2NDnB_D8SL⠒K{IcNm!6c6բYx=1rKo@=Ə?glB}u<]l}) r`T+Ak[c4{806 WMHa L⥼½J{{‘}3]ˀ"G]U㠰yZGW~BڹZg~\%Sg #5&@gX"f^`΍-uEgܤ0JsN0 c*:? ) 4&F2g7Ta /ϧ;Z~EDnmvw'%H/+~FgA\ ?4}ߣ"T] n|l@N.URp5bó+o/#xD/Se:eֱP5BQnx1TPE!4K F:p)BPpJRPJQ걈(=w o3oz.몗1ۗ|ҒLp˜hjKvxxa2(LR&c! jfakT `b(PJ(22'eHi@\\_NNwClbT)(|JP0q*F??Kdh&!!#\UCExVEl`PٮGc` R2?+R*@5XQDCRA,*A T„XB AR( P8A !#KJV!$ -K0IQ]PH-WJ0KCT\ W *1t¥T$XPTPI(B)R-c0 a%ha ZT%UBH-T5]l^NFߙY{[FKHI::`[W3_d'y'yfM+&?_F$ is Rb#`50f)"6BaM*9 ("}BT$6g9{Z`:TT >ސ?)(`M%yP`G_ )ӓ<0G,DؠzP  1a '3.`N+*R8ј2T7d\]F|A((RGp`P;XG 0W**"H)78c=H"NHjMDJGHaqU޾>tm[\!-i:Z 6\i?zqn>5;wQo䍢SBw_!aeGGd3K3r ͽ8̎>,+>,o+`ḴxvG/b28pFAw.&^xpKaRl v!^0&t7#!AeG6.q^ʊE9Ig}YcP{ZWx2ym^m*1T+ˬI%qmo tDnva6(;a~G1yChnHiI1n֘/-8=(Rl Cs s9V}6cr)~˝MOWt[GB?OU͙qLRrtjrk<{ MR1v?avЉ%&aOii,/ko6sF}|zmf'L$$<1 ҥ=s-g^9H[b# fF'LL2˖>~:*sR|lAHR !SZBWHB r[p;B(tQ|96$<'D^!~&(}DƀMӟbIhr4ơ4U6|1;D[g}]):=Sc;犓 z,ts-0Q{x?R*B-oehױf\4sR!23&]"44cc[E j D|OM5EHhEDm|-G6i\/:21/S"FZ:A\#AN!G@Ԫǿ=43+  70E a $DM RϖFnowF 銮WJԞhU(rԄ1RE U$+UH*ҁH  _l][u- 2 >wNF#l0Z8dy4P+]kxn| @('E%':i-c5z 7y X>z](@c*P0E(**5BH "(K H)F6H (z* T* &6u `kg_L3+; \ÿt۟<'US*@mRR7rLWQ JT ՙp3`e'Jª0((kcRcSp" r8=%a=C7x>~NLfER2Nyʻ;Ҋ  r#?Yt})\ z3qw|4w% o]%~9ȗPS-NȆTOEBv ;Q +&wTi^6O=]@QAQ C׮α $h ]0F/'Z̸TsT0RQSS!>ĦǜR}4ZQ7_ms2,mg/R?hUu/u}NS'CE~tH`X핚C!-X1Laq[̫FLG%q:#.݁{CIx l2%yjgԦ+85̓}1<[*i&>dwyj"ϛ ?(e(Y9FLs2E`wm:lll+MFÂPjBWS_r/8U ..sn$sxQR$߰~j88ޓG(Ɖ8qP-WOգ4 )Ͼr{ %R4G2^Ke`1}wܿ޽ S{.oC7u?F aDR,Vsȱew sIhP}֖c82G` :{TA/泯X#ӊ%u ʒml(zI_0!A8 Gr|3u":1un N ]$}sSF?騧 5Gua?L:"2 ǥOݼ: ܼl創2!1;4G7^5fS>'Rα#{Y6趏 x ܢ-kbVȯ'ufppnVf^^\(33-oXɑ>r{dZy,K4FiV%#S4wbubib(ht#H<~Bxb(ﶛ|U?bJ]wDfF ,.# T~TU! 8cTcqg_ߖ"jcK8Heѵb!}JD?kfryikS~ɛ}1'9뤟.;[T[cZUW32,^f|JlZcU^*h<+3*`@aiIsO l]Ώ܊Yj;Ͱ7$"W/5Gqp}wzŢ);ϥ[QA/lź'ic 3YQR37w:Ψ>e-*z&Fl*3 q*o|BmGDRm!֙'j* cY_WpJj-S6BRlo+.L({pr erPcع62S9@ӛDr[ \E0) `#nNg^;>LI9\ ֎԰vvɥD\!;,{w#퍭*~x:LyudG>n9O~0h rTvU'IuoY՞ev+y|[2Q0u !L!VѮ0(8NM 5(K$!@ҁ)cADA(JB;eMN!-kH̐99I!>$" qDN @DL@ (<@*%Ԣ% (i,D_ 5"iA2}҄lB"<(P "H@BlJyf q'AUQS(ac a P[*9"dM@ !;I" @*@TOAi!('e4% BTREJ@d (yQ @@MAT!F|"lDD"xH@gP|@H&0(lB0( H2 P`H@;ꀝ"g-KqA'%P !@ܠ(Q*EJ'E#!@$P TD JUqi؞8b{oCgg&,W`e݅ű%*>xX>9tuZ _jͲK0s0fSƑ[HĬI-wmn> 3XYni/7~Œ):Du'hFRWbY; \ Tdz\Zx+xM tx?p#Rӄxwu[E]*hDRIU1тI4P3<V{b{ 64H&RRY~-ฃ+ QR#vvFUP"rg`OѦܔ](6WPczalFMneNLpA*L-_ 58k z𤍣sQV#;5,*6rF I"Kwu[ܾ}V:*F!Q8-`}w:K(Mō5M˼QˣS;]K8wz@b8t3̩4b Ȩ [û5yTiTMW4ٽʱyȟ]E2ު3Rzy͎0A(`kn)" NPv?Y8oQz;B7Gg9YdvEl< J~~;Ph_Fwn9^drQ?6ve D Ke-`yS&Q" JD @A(1eeHr*5$ܠN DJHD"٦@H]jfs2^L9>m9q{_}ou@ڛ0L7gFR`3fͅɍkP$Nϑ281ՓSƳSsȓ`^. [gWޏ{n|y4;|w[OlF˭e\s/HjS\IAz,K k,aD d/nrHOJt+J(#% a`jq3}yc24!d~Ÿ9`󂫙@Ƃa(.ouvGZu?i īܕ`YITUA@Zrr4H#f !0 J+ P8CRQ* (AVFQUBK((  *_eM~FI]h(!FBlє4w5zK$$>!U R$Fư)PC1o aP)Ya]3RQ%{3է g#wG<җ\ RF(U($R$ RTYXdn8$$Kb(1 0 ZB IRTB*@PA(U )UV@$P0$H ]V0V GCE>X xTI*A$ U@~B1%P0.uT*I U(*P( U|@RH1Tk 0/d^ԬU`KLoZiD-d$Yƕ *(ϒwU\S#nK5VP4rpbZ"?=+5ȥIgUh[(dNY\Js|;+y5+2#KYܛX)?Nr~%eڸ٠_!.gS>B@Gڂec\F8$E8`>6vWŗz]ocMSUPXM/.si1чrGwBce?gQ`t;@af'UeSIu8^qcl(,<&ʲD Y!(睇`N7ʑf 6=n_o4g[zH>o#گ~^,M4x&xFOQԯȧEcҙntuP5hf[;v+?2m86HoXM.}|fE.;D# Z-rE*R \PVʶr'ܽFL4 &tVSvTT Ͼj0{hu n۶sE .:,V̓RMĆLQwBӧ-gFoGn6*E :~e0jStV"⩚.l39b"ե: f۞Ԇ]lWQ2† 3;/ 1})Y6!< Bςp_;Qj dMGKqxhՖhuEݫoy^}2FF2}/|rYVu(^.l{AouPۆd2hfصt UHwA/.ϬWHv#kpO W3NzRÇ|1o0dj*:5UJ-.>ɂDcʶ2`JzӶ#C$k >QFw+`LrrXMkQ;|)Z1\m+VN3TW$n{wBT-*/'SMS oZ8'2H^r>A s1vS.I`\y r5b"gDgoSEʙ9}&D#^tMd6HH>K9ل#D3ؚ_ *(g6ҝ K Td[iOexz/ YDD^lNj)618v)۞fЍXPTz q*+(~ tEMSczt2"_ȃo/_U'~R#\Bn>+ ޼j9$G[vaUay=@ߝ5_eEΨc~}Ȼk`Q40g1.g.te"rPI;{X,DO_ O'L4>ݬ\uc:!6a보%O0_!ݩ'гa(851 %u.a> F_Fc󣃯9jlޣPޱ}; t `$0ވ>yA=K E0mVs* =GڤrĜTlFu}I|7evK -ERGl\shuZIi0Ok+3Y־^P'Y{D:rNERzD~- `b컚x N< .S:Kc?u= ,-Q/spnMy[=Ќ[ZƎt)o_X(܊v~uAzZi\I~5=~0ZC~z9剙dފN}Dg$-kk[:~G+rӚ}Iƅ L@Oo޻h z= ~Q!~ 'yFijtn吲H@:o`/%QgL^O^nѡy;g8cEn5MmvI^Ȼ"?Sc| BhQ9A 6fO͇Z8َ79pvK4J |sXjF<4 lϘ2 Ḿְ=GsG~1ܖnˤĊ}(e(Л|0;fqcW=M$+0!Mֹu~yf|VMe"Β_&M(U 77),14Z;~z{gӰV-zdR?9^v(-dswK5]1[%re

ɋ=tpe;8g{ζf,F+YnfQ]hXiI|KOR{*2T qKQٿIe+oz O4rvKi}uqgMlꗏRHOqD:(8gˍ7E[T*w`E\S_m`f&|fakΦP.&zJ\FɧU>wq)49_ tޛK]ۼB@$\X|ZK瓫6v 9ngM!K~rE˿.p)c5‘#}DC@HKX l%)ao*ؑ = O$( ?Wyi]j{͚Ak6DeYi6ۙ9>mQ,1 ۘg6ҽ¹>*DDbä8mp3D]XA3e4$>@}!g}ctZ^"yq 0|nnt#qjF/d{n ax}@ 6&s+0o}ǬJCNPIpq*9 2^Փl~n2n+PF-rʲc͉*fï~:ndn=ݳy)]/'' $ Ι^FmUmZCLX,g8E@vAG7pɰы[915Ʌpa6^)a~Ic}Fnj'Z8#1'KۮI]l$>f-+W^bGK4*G7fwV3 Sfq 5)m]]E_,2yf=rY03˥oiN! 3H]/4v/ dO[Z!C*\U6pbbvӫ)0ؙ >Y2-FoXDr`a02~)K-ԐqDr7qQ.y[8 rvzys-SpNh>Xyy{>͂m1p@b 6PoXDh-y^4XUFdF"ӻ_5xڕNN@x[UϾL ѿ/Vݙ !pg67GBlW=qfK@p~(O(ϭxx#*Rpxwo 3֟Ľ;529}V5ŃPrtlA=loYx4ڿZ/tJݩ  ^83e1JLcHFg@Y VD`eH^5s+tY=rџ=zapՐ8V|6`@9FpJ"Z Fw xK4T kr@|Zv!mݼQ4>)>V>Q=:k/(EM#yEX?:H Dަ3ef0Y!iɱ z6^0J|'.ʢ\b l5ͫD=HVHuH}Hm \q% LtЗ3ms A̎C5y2U0hS$V&;ѫm̄͗S/%^^̾B?M1-[:Q o*hv5+h珩T!_ 3?Gg;%>q|@BZ4.\2DyC'/-D`O_}_}Ge(V#ՕR |wX iP&y▔Ycn(MFnߛ;A=J..\zrƂâ;raڬSd| =~M˻ٿMR%ka*vYy`TIQщ}o :lPy|9F e~L%-6!atľo{Z&$WhkE/CYy)\{`#rAs~X-ykpu9Y}߉QД ]tH>KvN@27tL1>7nŠb`wVn̛#Q26Sǿ9~"R6,b7qԏb}ueP+Iy5! ʹ>{#v? Uq|\E1oq,{>ˉ?vkUH۫ ^sl1Bݢ_UYcTPuP4z?lzc依FW޴S? =s0;W1*t I-/ 5}X)ڝ x_ -6m,>p?EV3YX݌`S}{Gu y lP1M3\箙iHBҠӉo٨:Y[ ͧWmӒHٮ-FzO >k8 qi`ȥSLf@y*Ҝ axXiltt{x uq_Ր vA:J^MZ5{6P@;g2Z:?K _sA}n1ʣ2|E:"IZ)-KL'vgk98TF0u{m!5vQlNڲdrsUóedd$+jˮS%Y,!\nud!宒O"!b}؀ zNs_ Y8NG'+/Z7"+ˌ1Θi<#@h̞x[i@ ob'6G &Q>XufJɅsR+洕>ݕ@MP{a]Iole QԀ l03GW3ӸtdpsNg_bӣ1PEř&%Fȵ"(mxA@_}t VPA:8- v}h6 Nznwt/68|eF UuquLwp7ͻ;^LdPB\|/G^ZM^;ӮjAވ ?[9Xr[.K\tFmfeF>rHZ߬O9#M { |>*l-Wj3)/5XnҺ=PY -oTӾ*6ڬ-{bؗ _riMmG_P#hncESx ƍ5afsreuDwvy(`8)(׭].y2{7 QMQf?FJHR%;h+4/R3aB $&?˃f a (4A8vJ<(hR.E;`v>p[ g\PkNDrja"1h Θ&.D%ti0)Rl&l(_)JJq]N@AX!HKÚTľ_9t>γv/S`cns,j`#BvC(ܘR!I*Jzxo˞<#bHxG1[s${ۡ JΦȊ,wflֈT|Պ'4|Q3!f_1F27#0;3 J9j?U J 6"tmEѿ҂4n^HZ_Aa2s}u拟)c/RiQLw1.NL%!;[WELR&>6Ik'ECxYIrqŀeStt$rwls#T_o\`T%<_ s]oQpAl_C9bּA(P20 /dRn{lFJ5q4 .*{c|z$꽷^BL!%UZ쵝!yaC%5%21+Y?ځ)bvsZĤڥl'zY|3dUgS EҔv0xR0~/R$P63iK&'¯Ch%ўE߈> Jǽ(x]a4߯wt@~6QP&eݲ%Ӓ)hlN482n?JVw ?؛k]"`&nq:?V#]e?^;-Yg@Oz+ƚ93N8:)\r`N;/lrm×z~؞ d_0e,6D0b&|-Q9~A#e7rqyDצ>{k~kFhF^qc\a.J S9n UB9P1!AC՛ӝbl£e~BT7_|RЃAUxu YIʊ-0)k7FLH)9v%`צl>3g_#<=[1]Ge7&&eK!74:^BiڪxS~%@-bΚEn?%AV 5ioe5QE|ET0 w^pq'(\_FQu6Bjs4۲e`OGE-A Ds>C Ldg8Fu|K[D4Do/mˈ8Z;ڰk܍mN橁0Сfi>#R'S.DhBO#e WZaIDh9o] >qaN&4a%0rD`"&ypmFp gi.G}ꥫ~I,򥠾~n/Œ+ QUh%o'q!v5fρOaʃy9/i G^7wOT:7i8@&i#Jj* 73D`炳S^Dg!ι[عSC9}C7i0%5IDe!e샳LY^=@x1ڧ:Lwà.: q]<{GCSg3!$p}?N)Ac Ohyۃ_;j46 TQA, ^2n;Gm{XjNg 8e=4r1FO',@ҧG2TȂ"]y.D.tGh*K0=B#k.Gb}u[J&>(яVxr#Q1_Hn6S!$D 1S"Px._i A1/_3]CPT3$9!cSYuk^%U<Ư\h*O9.)=D@X*t*q:j`G(oiÊy!0<#1Ȁ4=z&y|Ha)5:d! bsxդm)uY[ҩD=u>РF21#}MyN?>D^4/!)Q7ۋ+F]`Luhue_Ff޼uAd\lEv,XlM-t1|llY5BN=?ezt"-qt5"C+1jԨ*T6h t6HTy0<>]-?:ZHDN"=s:u r ~_HP=J+F>ƒjj/PO@qςAlhm*maI.<tGפls|^RQRxLS< (gc~)#7sqD~QHOS8(?>`á5t8sxA]9Y_\q^zWU)KB x{ VeK>Qx 2Tx-X "%zk 37GbwA j.T"?D?wlf*7Ǵe5`ΆO8<&8KlE2ppdKp'xR\(> THb?r 9p=#zc.8kZ=H BLNc2YqJ m/ cRWB-9\tgI€힌 N.8@^pahp9xWuغF ZXЯD?wP'ݝk=.*bm>"Ԋ.B{+lb]QRjFH(-oo5Opc{xwhnߵj WO**ljL=L0;m@ח-{&+Zp?[J53^)Chh^zب:Xr}N>&f6ZAN 0ITUޏ?D/ݼAIYo@r4܂\z0 Wgr[}?Y!9dIY*[E!vl[Mj_; IFf#MȠ>Ϩ͑"-7zYǸe'ܼn zLvP 2ߑ0(9FG4(2 )w;(P&@ND(!LhNY~Q~(R@ɐ-Ap(RB% Qy b"F tK(MI@t A: mBD۝1A|($5B\ &ly1"L0ĐB @8D$Ȑ PRD@W $9"4P< F HA(a@ Q@0 ?/Br*kfT]\bVLDmg0aq^rK0|Ѷ]V4W}3?jIg6Foa熀#a,,7] z/IHSb#([d)?omu&gh6Q+ O^U'xsBl͆aMR_0hhշ0~ٱr& l,Y{O,[?&q U* _8㢨&\7׺`a<0tnUd029F`g[ ؕng}OF2^ta@9f‡B8l4p{X0|[~wTms@1-7Xe0ts20WBNK0I2SCBQnGC=k@VE%R M~% cXo{oxh0Lb@ ~$&6YȤ&~H]?8Y调(1x~Fk,+O>㣠q-D␂A(J ii?EDE5@KO(&TÐy9>&6aQ[m[`X7.@P0lqi{Ted[߂p#'(@ s_d͓jզUr¬$myeK^J%ivuxۤx=z%/`a*\t(ީ:'#G }%|dk2+d]gfWO^'=@>ܙVɵ;_@~ 0Dvau?$ 5Xi&Axuy |bE%-qUvQBzg6a}rZ4crHGf{di#|~ct`9^j1$2_{G%9z-/p/Pp)48sܶӍfU ׏T~ɕыv S05 Gr*Bdq xpQC{b8•,[Od@v-drɴ ל i;]ur$${RR3C-M*IJAl$?)Q֞ݠ`ˇA7\H(!]u8\^^8.7q^+=SUJ[۬s˂۫9C(ಖԗ{ me9W9tl3)n$v\둹 H3)j0M辱Sp82LSۂ1 zxA`HXH%&В~jU0ݭ~؟W]jhG4%x{X`Sc*cdv0`몮Q]zƠ'È(#ou~?.3 WZ80x؇fBvɜ:9+ώE ]xpd xx2!h3C󯼲}?٣vz2_:\}^ .Ͱmqx]+fȑ0/F10ذU "l8s֡oE `<0 bb>q%ǸʖE7AsU@5H@4d p//vtl]Ĥъ3 enr=u|P~킥Y6J84Zq#c}OA z5BPꀆj8`yL7eY]bШ>A9i⋧j1SWB;#xg.bJ&`V&lhȁ]e,rۮxNܝ tUahWg-Q-DTs5bN@j+P{UαOn_h->seKO/+mS, \_lI%HXb2ῨH.3 uZ2aWzGw:`4 N]*hí@%3[jpۖ0霏_`Wk1:m(<ȯ1S1%:JRәp:wxM9]Z͍mYW?V|nL rla8;gOj7O\i #D[r 5Z@-ƍX-/>HE-^,cVOy-7!1mfcbp_*ހhߦX/Vu,u٨z,3H c8ܓWd7tf[=,{Yȼy̩HH6{!zQǽL v@Mʚ" ֝>S}#m`08'A3HCza7(q`+$dtnviZ>m}}ߜ\?ްXeb<1kbh<t(HlyLiwZX'w7G<އ&ȣ7]ɖ\/ery55}e7jam5CrQӓs8g¾uf^jM:#I<9M)qؙ;,\RafY\?|ˏl@^iݼ)+"bQ뇭*9Wpb81:˧+yW(L2.r ]0҆*tg5w!H"؍<,k/9iG޸V cQIr9 ̽b[M_ff=ko㸗=hs gMY{hsHVQ,av!{ K{4}q'-;u;(5SA?tHH7$KS,V4∁ fpwϵ!"D40?:e*`0`oF͞r& ulF'ym6#,;~.:5g~fOT!qdTV6!zƶ <0-C{?sLWJ7MM-؇Fs,&K'i72M_Rw q!xsw3J)x_E])/.K^&P? Zmo}p6XieLREd_YXph9XY.1&+^Dn P**dQMygbA-ͣ^]ͨP<*Lª}'Jw5nK}x%Lάԍ5oEhش7k}+crxr9PE_>cq dGfzyqTVo 0Ěkv!ab:eHՄ~)<TVT3xPY&t7-r>,qM{[4OMlO5\p$!mwKG;}H~_OZ,1i}O N:6LOVe6uGZX;mOt>\ Gx'쫴@ߔK 782x=؛X"2ui =YG~^yEXP^/O@}ipw: -)?@^gL}zIH3%6,չ PzS3c0`ϔIөNI6g3me?R{<90:KʤR3h Rl gZ`|,E/Zc7ݯ Lfo;?4Brƅّ6h??z.N{E BZ]:";/S3=Yl>~ ٯǴq;jzs6urzdYWñhػ^5V= cY{|dC%$Ql\/5ޡq_FÚ3 k>~%2bÚΌã؉JMCMYs<6z :Ξz:?T~]P#K872\FxC4n"]ܱ0Ǽ.VK-y.&c)a#u/D@Oa ;Q3`Q"4Ļt+ià+7+wHLe^Dm} ~/f. jd/ `ZLHTĮVi5QH W,|ׅc9QVQ);wm4\ܸ-DW;`V^Lk tE_kǵ#}v\<e{pGT%NXԑ4xC1>y]jEe^B<}DG9 e-*{C]X ,ANL(r7oq81rq݉Wu/矣ᱥ|/ᒥQ寈{.U*zFzMC~/Cb=aqTcuS44v\/jsX*1|IʶK?L9_ou:~+q熔Dv  dǿ{-DvEu{ڎK?X2R.#1L4}P}{*OEkPwP Ƥn= ?_ıX,wÿ#ީsxMSssWXAtA]j+!Oo- vG04LL2,/]j~=1"HZsj{ҞyAr(<@LLE\;`'9usHmDa*0-tC:(}Pʆ ZR7K#H @Am*Rك/z0 swWy):,"z oߨu|(/pŃwhE05eHp "}y+El@1u%֍o :H2ah "իJ)HE~ĘTfeq5581YpSAT!TIzXެFQջh}͟~|EȁSVg'_Z1W1xv5^=|w)/]*{IuJW%wV=v?єXkY4c&枇(PB t^1aVv!gv ߔڣT& nq:?s r)J>"=hY wj>7f ƟKCuRR VLtb(ܦHNCa,ͿO _Ib.Y!/YR]M#є+WԝkvWYZA2(*{`;`5z 1effΡ%߸lh d'ǂ̀`JidqQupqti!يzd'0vužo(otrIsI γ:{ڽgShq^^~DK3HuwYfA;Z[Tψ8.> <Vcg~9pcc"8"icPE\}sw/kX\'&E4"="Z,Tֻ*)f t@۔,pr.<ZȘzTVqhJdLn%$kls~pށVN?'{>Xs@/nN5Wr=H#YqLDgtu>X7أ|<ȭ 7s7ןȸ%m֨}ہwAEew5Y~ Dg]F$ ;m}Q};/%`<UX9Wfm .xHq]Rx @e-!.F+,૦3.pkq=b+:.к2c] q|!9Tc,DѤH9Hi}}bwO$IãaϱK*)Μ;yQ8YPb9}EhҌ@Q>xy4/ۭtKo;>G$?FXl5b5m=rձ`,ag_`d^}ҳ)Ra?0IM+Ѐ ƌ] Cqv.UQ -bb4&㉨,dYG@ k.?oo]ph;"JTWSz[iS~}dZgq+b9Dn?8%הI؄#Xy*f§q+,YԈ 5 H's7B^K z{yO>Hq1`4FJ"u~^d<&z)#H}tg;^ =?L9ApT i| ~qv?g #u$32[DKtBPQ~8#$aFI ?cQ&)şΗz̆N6j,_.d+9V8x{,q;1P`/#,eTTaMCMRٿEQ}X.SIV_4kw]U,OOLՆF5wIYp\,mwCJ~w;%ߨ3 H6S7QaR:zו,:YZqH:wthb 3rwQʆQ2t|-@/x05>'h'\}Ne Կ] ?1}f@,5i7^؋딢`&`L_RZpI d u!֗{ϴ0ڸ 0,C:!yPLMU1Y7V9%)sZX?+\~_/%I-x;!!vdisΟTw*\T =PB 6-p[_AaYhkd 0R"s|ݻ92=x¿)"Hݸ85nq2KQF" 4v4etٜDEko]4pGfݪ?`{ z(u"'خ4")w8'okč! 2y: CG_¸rz[qm:3F1: Y /CpbYR9wf́{D7'Q ԫ+ ʸz;f&ʥ

~1pW F2 fƐJLO61j ^}6uy!9}]5nf?ynmxLs&[49V ?US" ᳶ6Ϯȧ#~^N]Rdk ѥ-L!&a(FЯ\=ru7ИC1WYp&HBsRʛ6s]y3v?f_c~}T_>-ZJR1"4`٤prB)*@;J{wO 뛩QndYʏ_+Q*n>WVEC}t PmLvx iwDW(]=IP>Ⱦǽ:a[O2L[eFN⤧Ctu6iDž'b!<@dEbV &yAqըmVc´!W*Pb vW_V{.{?m4 K;N7b@ˊIG-pV_?~K@$B:Z編Oϴ=# QQㄝIsCyV=uɕe ne"D||~נ.`"|4Īi|[!VYsd_\)~5g9A/lϕzC]auZ;E@LZ@ cz1L*43y \ksHe ?+5ٞxC0k֢w{[_аdAb+f+ q>4'(AuD1s0'~Qث=W<_ۂ(ҚWх ۢj졸T$Å H{ iE ,~j zl':BObr_m +/4/<̦bPWt[>م5*NpkT] $m"f/J<^W>+Q03_u{M*($봩nRx.mpDP|єz0 mh: W3|óh, Z=k9𨣩-Ϙҹs2PGRbhڴ鎚ƯhؿRg?aUGI'ca1ut Iil k[yrMk7b4ld^|s *-xՉ(p1P'˘V-' FSkqa!6΍c7?%̟|\+PmVg &=[QlxLc"݃_ ; *H0b\#S'♀di0tۍ9,dQMxU688L$2em_XU? k3N\Uvre}ȰY b=S46PjߟJ:u}haܿ37Y&d "d`mTA먑G q3 mce yh =B#CpP0ZA*8elJ LZX AYDS!䀔  v/)ΔOae zByȄlX6(#˘4 (x%@҈;%(D&EqD>r8h őzE-7td J i,@BPǪ"O$& aKi@4 $$A#9!@R|PVH鲄rnB A#k(uRcA)(|!.@dP%)!x2@  ;8-eS@B Aj q#3DsxꄯؔPKE䐛4\ 9Յ=G{VDq|R/<{D4$xf c0 - o30l?WrL=Ls_z ںwNC^ЋD\8`6)ntfmM(MA{ėp&l"3>U>9o,O\oڰRPmݩkj|Lf]m^X70ĆQ[sΟh;=No\ Flpr$ 95 ;k]篛#-KM@5n܀".ado4 3G x1S3,@[Td.GE b*+3 yvveK1z=<TB1k-R&CHhgg?qH!ZXD|+m xbySXJ Xׄ*y5 (P+wpat-(:f8NB\2^ <0U:uR;d3y pm#7_zSGeoWR0@#j{ep,xRg3c_:z}w,邪 JH1ZSmX* ÈQOs&*1<=1~¦<\zȌ99qb WxoLտamNe׋wՁvdaHApi ' ߐ-3d#4Q R)NI0zYF-\^OKy=?{z?`dH; T0|TҔm//@I,W}aOTE$16C$ j󝹸v :Ͱθ17LhBxzDf", Ee(L(\+UBu{щ)>>n# l8gوHװ/ .a[S*lY=PSg^9LR_h7!znF4e@r0YƏXb]%{dP Ս2Y /dHeP1ꘘ 0,)5k6$2.Qs>w^]dժ8f}u#D;@F&+a˷?ZjdxcFz,IǼ^=|ķQJjc[,&sY>Y8fcN-?T>ciK0&0TMn+V1Y;r2-37 /#k-󓊻9bDufFjX6hnhXm 4uwò=B U=">*k$=l]G c DZ3شE0 OnhDZCJ*XM(ޟͪ*}ˠȕ~pXaH2_ƚyx@:ȱU;qVe2gIO{Kd*w6K|Olmcfoa1/r"퉯3.GCKO rY>8n8[CƒnB7p_Cy=W.F'.CmNOjO".<&Wԫ&9xc[?"'W3yTW-|o8.@7LgTGL_Jk8bӢ2p>d<#װ;|Y/?L7SK /MV%`)UƳ7So!_9;hSHb\ҥz}lBxcwu1|SmU-r̈z,81TE0R WխjM t<)K: I;*NzuɒEkځ e5[c6d>֥tHG2oKX UixS}0XVX}Kz>rr=R'$l2RAY"@N<0rS~ܖ èp6l]+<')\D/`,GuH6#G>Q۹un`7(?\r8oRIջQVߢxNa qdf$4t ~Áf5±'wFb7#*]+t !5t:og\P?Lqi2~_ a!!7WlG QԟoDBP])4:eSWs )1Ei846xL_9PsoZ<>!!$4ջڸ_+D`Rd3/lc pڞu>y%v`EA=2>l|iii.c&aTx`0Ven*t/.H ,v7}Mig~(+Bp%-o5$b9CeuO}q7TBvu.7 pyXH>"xȕBm=@x\W ",DքϹE:nQ uzQ#{Xf/AMvTlw&,08u y ks<0Sb _ˬG*d`Ҫ<3/Ġ(o>| F`V3V!P]k0O[>?bJHYWGliy&}:ݗ2͢;i JW #e#?; ,?c=pwB6 Vk0+D~o*r{TPZiLJ;=~B ? fv飰zj#UٌY;ohӇC?tc_?{ksc]󐖊ϧKK0[>mid]:E@wQhϙOKMÈmUЭm9>k|!9O>M>yI:١*>:DK΢Ȧ9}1c,sxf^]f+A_?鐶uzeeSTr"CWp1nxڥͻyxЏ3d, nJ/4;fbL+*pY3"Jx5ݰk n5%iI^i-Bu_H;GRIgb㰰.x$dT\lrL{BGzC׾,j4C2NorB J:77ƯW15>G].yѩQfXRMvOXnC\aC{OAIq1oQ/ 5>>„~Ih*[TX klzlpDz =Bxy o)3PXῤR5ر-%!Dj'go;= H&eԸ{úmy!3ǹv[๼g ̎`@D107Ke=ؽN;OUG.@ {bH@~>`s&st!oHtsB4+19[|{yïen![uQTNk rU'p}k(NJwfbrfR2owN%=[cr;컴Q+BO#rZyԓg/h1^#qFkJ${7@+Y\a'Vlur@6SE@p_ zbLSM&6pqƬypCwĊs4ڇޭ$ Hp ,hd:&(3'ߟC/+4JZMPPVfdFUwy{jS zR#^98AgX^aJZwqA WZD(Uw,:["ĬT0S0-1=ϷHwB"s9Oj[lA[NJ|Zj>IiSݼON.fk;]xHrnXmfLŰk rzz_=Ip]}dg`CY( 'y%[!mA)s?vәXbQS/=_gnގo.!{D1cC&G7! I(桀he?9;6^ne[kDsK8iԛ je5D߾mjIS&/\ 0mH@-m֐e\M34d.-QiOζn_;9ӼxT+ Ofߵsg e_ʾ(GxI~N)g:svkN; <DRO (p@Õ$!Blzk> ߗ> eYD:ZGiUZ:N sQ, Q P%ARCr{c c:zޛ Cѭ2s@9ꏼZdߔ K2y?H=/…lVP8IVKeif|ԕ-jT~7x8lVgy[ Mlg2YQ㛽t5L{v# ^lBﲏdV4n?u-WM 9r df)D돋0bᕝAK3;/Bq,f|a{r~Zɐ1r*2_/fѠfs23ƥTnklv,2NB_)7*W#f>NZl} hEuo$`_t}NJw=տ=1S9wG=9ɲ4`r-yw 2mV2(5t9 jȯ8?*aTZʡwV9!z瀍SVWGŎCI+<ƽQ-rɧ8w%b=4ת^l)v5zT4gptP[|Y{?ix#p@t6 ܖVߝ@!a^ɎeY\;hنIΟqW4;;ߪNavЭw**P#v"̊bz5S|jCKA.bǏke~pAY@hPmOFᱹXo|?*ekF:Zg`elCUIf.H]#jI7N>3脩U_`wζvyHGq&XW^P|BT]h}I Ϸ}C31LRb׿yUYކe@hg$l.6H+~pd<5$<%*ǥ0r5aj#)=P&z7qe4I,%_/V(_W Of</``FK^ވ¿#:NH L#X>e7V .x{G+8 %<䒯TFs/{w%qv>^m4ЫA^RaWk`pЂ6RIyE!)b@UY4SXkssr:Vx>CnGQE~֩mghxLp,d+LdR14[Ў!Ngv~^o ]= zvms^\NU_y^k@d\6[sop=`F2tA3W&'o?R} Vh|F/4 "2h!0{( $khvUahb /t6j(A^8z&DbcTΊ {7EnP "# 0;.s (n3D6e"ʼnF 4as@?gFDAK^615Tm]| %f}m8z4\+m)U!9'4χN6gU$%qhh ^]ȗ\rpNolh\Xj&Q`s IxmvxU>X.EZ! ?>H赎zf*O9<-kx 9$jx1 L&%'rf|M4.UL/pVgIZ݂')k'JSpn>=wP\ 9KHZG1= 3.8;NNQ")%Fϱn,4܅KJI~F#t^vjFT ^96G?5>?#i3.KwP}rhj0TB<P k&::?y@dbOoJ܉Bg= 's=Dx=}8(QgRGB@xx(.PDR60ChU-㵍dܥ ]P s5fӲUܮ[΅uRuO{RWV!@S12{ myKJfy4 FjZ|5͒cz|_QkU-Oi6R~HkkT;Fcg]eמ/7CPq';"vɝ` ,:%|>C`q漉^% p_2յmVC^o-pMLЁ.neZM) B8x7%/ Qf~N^aѳd7;mo2N[_UNVl>gmnޥ?NʰBvP.^u$w1J.rbx:cHιW\4 %礫m3 CTN~sl'eZ ҹϘmJGRݣع!$aj] [(i0ƄF;#_H@&h,LǭLM ߿gBd`L )i[<[ oHWpd4H43;ts[FQ>@='Z/}ќ""Ȃ}A:+~DG *%SdPUW,R]JO4#>QS* C\N~*vxcVQZw?kB{) DVAؿ k;A2=[Q  Q. V<F)Cq@C7_Ƨ++9/e;3pU/_ el^$~z$m!<#L&JZڼ;*u@õ /r@][y:4ۛ$ 1BB<$A4gVn-Tψ%#h/C4:%i(uG=Do^ /ÍT }nOZ /5jlaȄQ_FFEks>Q|Օ*`z5L %F ,Y(9PMߩu((ѡ!X6Wwe1>rx"`#~l0Spuߋl m~bl9Um; ʈ*{i~Bt:~|je_;⇔hY^t8ύ0T }2ڻdrbvң# NX]*eh|ކ@r!fB3u_< q] 2h XۋJ)_W;mcآ,Z;w-Hr]+oyp9 9 iDHC34Mql ZԖv"ՙZ572$X!?7ӅߐGo?n}m5ePVp(}dO "b֘yF{)}iKF4jj\!Nah:@a[l1F/Y,20?|ogM֚>|WAt4"ƁpqS:wk#ꁦ0fE1GrO/n DHlh^E0R?DGf)lCze^`uyS |n);kc GP*4&cirX$M-HaLXس>e~]OzT,K n}@W? FM,|d0\gbcN{[HPӑ"O0nǕJ0"܂C]S"9dWpmB  8W^EƩF4)u`W1L #U s&չ”Q KZ(7#ׂ# S?~{;ŋ.ܯYv6y(%f7Ugד$mdC =Bgck1TjP?(egf3޳sf= -;<"z4 >Ymf#O=.=5P𨛄^Zg;z|n۹@Ls}TJ!,jrwa86Y]#fAeX3s=0ǰ]nnJ & 0ºu'g47. ;4Gw3.P2 (K=3.pa{Ln4,Vbc4 >.7cvQI7mF~ͭ?F Ă@8s>v>zwгߛVlSJ=;$эEg2"&7JH(Mg tʠ~9-M4)ܻb| >(cF+P9C0 \lwbgޛl +b@ז$9|z5o<,x/BRHEll?IEYK[lPOkJuW)l[ OJ نwg/ 'S;??^W<_TɽBǮjw*tke휙ƽxseGFY ﯏g\B/JQwMQjҀDmՂ64GhPW-9|uR&ꁨta/6 ¡W8vNw-W>l?wtFv5Oe|2#:)O5-+'Dwzzy_2WR7T6?1#1c$~vqWx%s6 rCpN+p~ b`3ѐ?=2/:OknnI9IvfQV{ua_*~~/NH_۷i*:op[Ξ? <±DsNã][]S#`^RCx'}2ZYZ#?$: +LW$[鲿3V5Vř4{=뤐X^" ՞dڙ?'ϳCg^ y҅V4I unvfTnDǽ'9{X= w#$(fmoOV3jLg]:GD+Fܡ0ln ^{Y8 57;#,6/Yo2KG&&!,evoVV.k[%CHmUb$$xw_@!);D *XtI|cVL $Xp̊$,nR'Oyd[a_~Mi͟6oC~.6$*sƤe N;"HA(,A_(Zān%GZ>n1’ŀEޤC; yoo¦wCSUqe`H bF>m/!a*y-i PzΕRʩi?ڿu:jk69̵D =Zm5gAd 5ˣGߊ26r-EuFEZDcORq811/0!ڽeH#H)-kc-G*diKWv1 nuF(p dz [#|0Oj/}D\/阜y^y >9 D(şWmw#i[*jyt3~=2'IlrmYp͌6,Q|s} yucI=풃}ن03i%/Ա ecE8\V"^{z`5|¢!ԙlUv  VHYcS֨J h.n7j{ 5=:bJwU%6(OчK~f)R+bfoWu FkŒC̑[{pn/bWՒ&7 s?څ$n -ƽjr˾㊌Ƈo@o "gt RD? z Rp;^bQǾ޴x_4/Hxq7TM8FusET2߯*2\9]c^BzcT_uR8>S>o8^5^3wbb3pO "dUP'1ojdyG]ϒ{ؤzݜWfksK"2(>Tgw~(׻ |ᜥ 罵l?PoNY?8F[JbS1\bxcMп9ʧF\U9}rMVVV8%?akݫ+GQNTEaVCiNK FF,wuO*94 IOJCej_ YMgM:%Ouze+K df`JH1~CTP6G2q(3inrwS^3S40?;ܓ&&9|\~?ye:MoV57\L,؀@M/Z5ϩ*mc+3znN$h=ؓq5G!;`TB~t-f=G;ku `ǝ SDR/.GysPԸZEӘ߂u9\ Mw,RjhRUFˑ{7d$":sE:~mA]z/{txX~]ޣ[5X̽zú& *&hKt%otKwAp<;]uGӼ}aѓ`Jobͭ!أ|&4. ߓ"O|͏LG6eAJ%(x[JS ήWH=&^v*gߠq>E1ìW4j]=f{o[74/Li3H\B%70F3O3"1uLHۤpmf:xNҮs +kFShZ%qG }ߺ~8E2^L\k&uNdgN!u}Pv>o1u<%ml _7!d]El0TS"t9-"NiW/B Z$2]zs0U\ '&It7p>i~_0t9G*f]$1dtg1u*|QU[f[yEn5ۡU5ݙㅺ[$ 㜿`jоJ)JruݻKavȪX2YU{}ӓ4jtt&M(Hͼ34cٶ9Nt \XZ>z9$qB1IӞ4Bvv VY@a_ǟ!P"̺bswώF-G* ˡo#r8&'Aݔiȫ¢+ ]5ek狁hP{cMeZx&F niY֎[+vb #' 0`rE֐ى}^g`#~>r}}2G艄|" |gL` Hk*J%1 5L;8$!Zxj3L9RfNmII~!-g=މПv @? >΢y8m2B=~-^ fV?9ɓ/ʧʐ:>4?>E ۹x|ߘcC>6pE%jy~q"Mk3j6c8_H[GșOM\3Ώ;'AR<}9Wơg42/|£c_9 K3es'Xܸ/}$hk|:S(z]>a2[Xu3CNnwN>EFc6Ƙ۶xcDN?totE!+ ]OLf!j5mZu'dku3#eVj0s'Qǚ9D~Rݦ_!Sd%VR9RK=/EUghU9tQ|lj 6FJm۷Q?A {,Ӎ\HlvAfv-IqDnyĮ~|$6a%aОTΊ m9[#?9.G(: ^q7.(To7V!za_M{ Ckbo\r m-ivv%w*?~8V_MQN}*W'J9kws|G  [ >lzsEFS0ii\!ڍ3)NX6PMoo.e)k9̳>޼VׯRJmWʨ d'wO;y>Q/O0,C97$|~y<}%\?. X*7~>ン&8>Gu9:' zA ]T}p:%^mwΙdn/6OםqD!L,Ox~v`aRJD1 hV0oӣ0}lubRCo6-$GZ!#r1o!Ѐ1߉04l 'с|zjGB6gBҋ&lաtT<)Mx"/V?߭m哶(,&)'xŧn6fV>r$,%"~iPMÕm;##טA7v"Mg.,I RԱNd=|CϮ!qeIۃY~kȱaQޑ⠦DH3^|h*ľ=x}5O=ʥtjG$)< CM7|tƒs?Z4maNpzɸBnvy]|OSqf-VCcoOsSg Wwb)-a?_xם9ţ2y7ͤ5 0roe~++i 'p`FgaUS1?('m\6?*$ ot<qj~viʥKBk]LcTth X 7!7`@j5Fy/7)L^tB6ebP뉗ҰqÂ8E =ɓwtlWF7E:^X#y~`de Jx{ԯ4V#UyA`V~;oNC^t?~t)g'P$d|ɓP*z|3ݢ \Eo^\ bXie9F? bBxua7XAk38Fܟ~+sya7Si=v{'右#.n6h}Y]^styG.iLG^C.$‡96O1W WMQRΈ{l, p:N~b骱 FtQl@ڗK TՂ|T{\O0׵Q[Gco~ Q>v*{D5_|n#`uhTe τ!9,,$ig7`U,r<%{zm9كqD _ 9('I,Ż𓵳bsKQ"mD6}+^H']K\iQa߰oiThXdL;o&CSbۨd1mHc񀵨cZ d#߽^9 ȱcT)\ nIAK0ƘJ6h5uxlS h--#f =BVb*މUGG?6&i^a 9 H%RPud"3ŌhTnf\y;Xk,Ap$ *͋PWrC} Rv6 I{uSꊽbh\rn #m` \~2NV(YLx0 hٛ} 0u|`/VlǷJDXc-,3hkCCnϓxG.piG޸uVj8$$pD֏! ?J+γ !c['Kpx!qtLT_b֡sPK;R38t53Mډ;sR̃5Y}9‚FduPIޙ7uRJ|xd;.S--=6g7Shˢ3RxPoud.Y&o[KPAC!Ʌ{oq,?"k|KkqQL4F~oJAsm!3=?{`zrn<"2o7mQ`ACs!ejv+^.u?FEݒNC*@'Dc!K,ju$1BSD|}!4VOhZz\ʁ,p)aJ:/Y HJ~TQv,!xh2_G֑߸ RJjb,-9 .f#9X!`đdo-ˑ  =*R>%NV7 #g^qd:  xolOܯѝjYfϖLFZ| ٩xˌ?%WI>ڛZN_eʜ<{?) 2hb<8;$ėw~ ^:="FߙRKtbϲ6N[|W?Sp ;}lMMm…V.:ߌ0:b ǵTi<_* g zʝs/Mr);-r YiJ= T\6ʜU{5xW5&Vxҭ sQXB@Ikh F&TpF׃MW39 `lBX[!"ɪ t8VJ ?sJ:w'eβ LeG!yOk஭mDj9u`4T'88Tk Tp<60g;qct]'nt8ulg}V?J-7C)oyUa"ʼnw)1Ȼx@+^ D{{j-2DPRH=6qW5DR֥>R"rMޭԈf=yV9xl*^xo^)iVcL@o.F9۽WeѻzLC- m/ҲL.#!ji.Ů>R-D"3?O#GꞫ/cJ+.0w/l|P~ Vg ͠O :I"my*ѮXa>W"nTO#KD0`?v7ne".cGGәA)zuQur^aUfe~{MFSQ[rbԾg#Q3ŜaN=,r31ѝ-h,ER>xyf|5 sc>Htmy;3m߮<$ܻO) HZ!bH͆`;oKvcVGn-]ԙv?H>Q1lxG`ֹЁ"5Ŷvk1f$}{3-'s2~P8xZ25hFq E-"[JymT=!2 w`l[G[K7f`Bޢ*D.5M쌾ֱOfIj^m^M[)Ef&FHo@Ѧt=J&2l1}BVDOf@ sD+GzyLʜt|icon!G"#EˑeyHfhWT̙eW:]-cG!|3&6jB"}W DWgjƛTѣ0Z[|qX%` N GKՋ̰-Еr 0[]Elhw?̰PӦpQ9+TwW./BC5M:S0?1Yr+ޖtgY3ޭ#-WL s_TG>6 #JbNe( ؛3'ǩ/͚K5H(GNK[jJzW8b+>}m1ߵ! gA^=>r.IGW0PO$ {gDr>BN["3:rC3> H)gC@oG]PM971 ޴z @W?7mOSRM2HknPF?}_'Vp ss&%-W:.9u_U.[s{` u햯se-N: PViK#'`4;{μ #E׋@7PT BR*kOP9^7~_Psќ%w0V\ (נ_чP!q;MԵ<{t/m(IFlE8z%:^;yZ5&Ҕ[Pn|WW\Mgsg>v[I)➻OS_ov'Z%|2Kׄ(Urx._ӽz+ŹpMG0p}5[mCv{=Ύôǜ_g1L;DUO6?[M:΂?Ef*"Ci$'u7&I`'=c@ĩ?Qg0RP JUO'`0mtd&0IݐO*oR;u:Ta~l,*"(J&cp83 Q㳄 `dO([NbnFi+^g?0N6ȷGM_oDZo>Ψ?(Ib4#(i+y~ҹlnWdO(썥AMщ|,DYΟ$?QdPF(N༧ b_ G&?ѸE/wuAjmfXvZŶ4T*᭞يֿK-߭g;0mugW_칿͙C6N%XrQ?\Lu [NR0h&r{/NŦeެJ)9qlObbْse)$FZ\HVߏO7C%*HWaRqXv$ A(ߒ> ~k[a4 dϐB45x:e*ܳ}ޯb62kugOCX?y\K=RogԻ̣Sd;wYQ`tᘲ@`$K1qCٞJ|o#Rq2l|  lKoMEL63 ha1] Zeyȓ2Ie"d.ȟPBenFAnoM :* ޘ%0_̍AdMKt(b4c_@ב4#P  AI!9E?AX0}{wS% OIMeKK鬐(SuAZ(ѕtDl0R☈PRP]p ,Ddј@,b(E "gE6@WvHS @AvJj010} #16d 嬉uF|m_ԤֈKnҴ!+d$9 O ,0&D$#@)Pp j3gTfy fVPRH.):<:|r@o2l^gg9@ b\-q7nj-F2~r}Op[)CV vA>qXpID5` ws#]zPܤm}=+Zg2u_=&#E=ӧwrbz9-iqL5j#{>q UUDj'Tj8Cd\;0քX者y;{2YZ/2{=4[}e(ö|5)fm.6T$ iuQSBw2t :Zf+}jܦ8'oӦ{ڒU4_ 8u\yg߶42qJ 2 n49w2gYHYтMFM@4" D';/,ȦgRXa-v.{&-+u33fZFH1.74m_i˯1 ߸Ztv0miy(0 Zu: _c3 ҸC毸[(Wِ*^W*S4Օm&:+KGYGǍSwLGv"McWQta!Ud@؃RK/YS<$ÜRn?3G'(s̻ &4&bT=4SDTIUyb[9.vzFpfEq}fLߍ.*wwytd*4pL#xXU$'@+Kú8@b mztnJl̻DQgCtz A'sDl31tA94'PX!LB3iVD:}7lִB5 /| _/nQ:hK @t{/E":NP"2l DHiy,Vfjw ]82;]͠٫.yR zSb5y %*R{o Z04fVkrr8m[ł?Ӈ4KDilϏ]Fna L%5%c5& - vjfn"ҕy22eN6J"x+;s  naR_sL m|%m93.oKs1~Fxy8o1@L.)&>ʊǏ;`>swlYMOǼsY< W0Gfׯ6nTWDVр=  @>U26BnI(g&{ MCd_^ ?n4|YNJJ8 gKGφ:!R7Rb's;' `l,?(*mP3QҤ<(^j95{mZB䐶wHfSlj!&pNj5'촠ckqZе @vxZ/ueK]U҇!5ϒ( #{э7HCTV Ww}~gKYSs:"GFN bYvJZa,2 BT%A~]Q_J}T9FCT:}ޖpָ]>__/AFF oxA5_'~eٻ^Xs}ʽeΟygA.z03k&Pk?z.nKEnTǰR:c:,&/V[| mA3./oKaNj ܪw2cX_2ZC)EF | =߂j> )fVQ/0oSQdīva,D kðr>?rIEO+-B=|~6GGoߐ~oM ^֖ڂ&R{N1.< <3z=/w~5Ы*9ew#?Ln9-~iEzF\랝7ɧjf VI 'Kkr|N9 pN_Tƻak,:=TA'<= .{/Lm(V;'۽Ӊy?ѽ$_ZѼZ'G]d-hBH_T w',nJQRʆh w53_5 aZ[\U7fd2Æ2ĀY< 6@&ǗZmђ,Л>TI"egK̗s F{^>obɡSї΂nFh׭8Qz!`5$cvWF,]~ܲ răHh<@HFz?snKEo$$=bbTVK޶׃[R-#]DjQQ9W"\z0GT+nLtzpm>_3z+dpg u<9yTS:LYu{^N>a G.?(4AX|KwLim+%D0^;Fѭd"n^6ʶr X,q@dRF."ZIG q%6ߩ.' W5R\]6] h]#3bS7t8D *ξIĝRͧkzM"S!O:$ݜO9J5aOŽ| ޱ VPHה#yP@=ϟu6L #ab{$; l8f(,+p-9!*?IQ+莳wG}폇e۳Qnw{T+`7\&7oprm=&ѹ!Y+"'|ʹs?Ɲw?d/KsڤӾ߄[VݤAdhd"jWnՉqJ;:oW}و)!D͘n0~zSkH(G$c1zӘ2D̾cd[=Qw 9$V3Nv27ɷkY3һ}9BJ:z̞1r`Z%[ Ey|w/ j5B캯0 }H((m#kMrt"()y6]Ƶ\&oӠpJ$,΂IWFXp34m&j@if?@?+BRjy(]e.䓔0]\_*~fNjgִ9r/7+Gxh1Br{|1.!>@c2zݠ3 ?D8/_$~GL lM$# F t` cc1_m\1*Į!uUTJ]Q,reyP\<)Evl@99)ebig}o Q(Z"/?; C%]C^ǕV[Mp(%i;f5ą?-j/kr/ EhC2a=JEcoKO'Y Zͷ'Y']~_r=q"Bkc ٳpD>Yiy #^Jt]ʦ|Ob(TtǬk K\JWՌyFw!|D/\M+7]?+4N^/m?swL| Zp"|r@K<+]dȾ?6=/~ f}99 0esuJFoo\zӞNlGG; &N5l-?/zY)T;,ݍq+ؤO#9g^d؜xEnpJ߲jH AI-\O¬:xOE*Ί5'(W;EV^(txNWu׸`4c3G߅@ y`gP촄;NHպ@fbmp)5z!vABQs󤥲>ҘPuim9 p(ߩo&)Ǧ! TNL'w>r6D7vN=SS܁ɯ)+$RӲF[IVk4bbNG>Mm5ET.Lu;]?+N&An%}i5U>u|Ga!=ELjˊP`!{XkHT^W}&,?%fqĶ"",>~ha3ub}ELW&.v27rIcgFʋȍ:Zrd2C,(Gufۗ>Gn\KtCh\~x~Ơ8-q*YJOH l+EHAa۵aN0AOzpD@ Ĩ>^ڛSOUMz0R({DN!-_ ʗyO ,xy X/.K'k6h{p:OC7¾\ȫJ@ 8pT'?ztYnRh 1n)ڝM!"c0A(2nA%R$ڼ+w"_7K=kq_פЛǷl}ݎmȃ#08AJg+s|-Ws:6uߠ^A͟{+2Qbv=P.i&邅hrP\1V#i%ة8ܷcЏ6nu,I#To kj٘m.On5jE"ہ/jiָK@ =sd@1?;GiWI;c ǟ(rN^- `dc/LŻ:" t@16UW¥2w;&3 FCxXĕĚ:j_c}iYq]Nh`J?Q5S Q'T9P3Er {0/J'? yʧo0zfqY[YrN hETr683 %WYI ogx:&\}1L4g.)6Ҳ=]ЯLu/_F3Lq/<;iES"w| %{4BiNl5 dKd$2F42uK YLjXLm5虲.p:ݙӣvx2C>~2OM&o+Z6td1.Bk~/S+(pƗM_-e]_} AЅ!-#գuoV3n5W{LiY:`f{/\T#òe7f~|2,bPR (AvX#?$DTM:L>ĬeSݿo^t}R[#O!,pF>L }?Ta%cL1Y 9dy(Zq!WUZP,h."rztWmyj[}h}}yD*>"m8{%>σEQe\ӣ O3ȭ=A0L~{Q_Ӱ8y_ۅHsWtyh׈JyǬ0]iLqr~Lt:+ex ڢL?%[ A*Uؘ6_%ї7Г|ə.}}1LJoG Mv>b7f+O3:~܀~8i1yٝ/, Fn]}LB~  ?Iq{ɶ\2M?:KNv\92#P~Uyf=:3Ɣo꽗-PRͳ0gxkDEaG7hv`kۿsc/]{Nbf(VGb?ۄt?eqq`>P?ތY D5eӋ@0wabBIfYK3y-uS$$wWd߻ z0b@lXhO"u張"䘸Isx8p1{8Di웝t polq~Z|e6FXMܘC,N?%RcbW!] B°Jᵊ-ZC^o6 aЩؙӶcg_AB%=QT[ݽ2?^ (YWRc??bC6i A߫.3ŦL6@4bpvLgz\5^t]0w3Fgn8+~$O)Ozeg|{Spe{8]F{LY5՚YJ Zndkljd:Xb3tS9}dh׊"o~hG)cf#۹UAU}o׎^ySEH vzrMe!z-\j8=w9k<=\&j] Blu&8FX1>Me)L%ƱO>*%#Uפ8 _Ul8=-3]]8NZYJ=[aZphEhJeJzdVdDPnU Iy4 ؕXҙZDߑDwk$8$A]R~{Aa* :cnoӅggBZFՆȽH $@s/ 7,<XǝƒʫCՏ~{Xg6:<=ɮO_ P^у)vlAYrqS'fb% 0ha)aorY4Q<Ktʐw 0(X$Tj,٢fǑK?04_+7H]B ѓ6{!=7`HckA#u}IUX[wwy-gsµ%]}y̮Q[3=QzJiQm/-w1Q>~Q= mDS;fpbz FX(P V(Oe~R}yc 8]&,!Fbgɖ=4xhAZo ;~)])1 iҸ+gՌLok^cf"iƜ%4(YLV9eohڂ&~8;X.JM7)w{?lIx6N͝9T%~ɯ5AӃ%EE/jwd18 Ѡ{m;1\heh<%S|_4cK~[˲*gBǸU?/G#-G~n <9wk`iq% 0lׄ 3< \:2@)VMV^lWS4仦y" *4!<2d% NJoʒ҃:>l\\T @uG<;ЮT(>o04|m[f`]D]7;r`X=c` *NU%@,|Y&RMds䢄Z`S"#?!Oc\ݩ> lp'wG1B{PSULƉoҞ#_|9E j'T:KyϐAؿ+[ 16muYnXU>R4B#S~uLGٔn:Z79y0a;>Aʞ߂`Α$>n.\䱉J:uj?;@A:ZV7q9]}& w˥'zu_J(G&$,.SDHpcw.>J=K7ÖF5G[=_#;d_y7JӑwT_?hɐx$]8l5dëυlWwq_ktKN\A}|ɪWZa`c5[d==u.#u8FT5:(Kρ2[ݸ Θ5is2e-<Z=ASv^zL;5b(ntn9^/0ccK&9,#+Ѳm]yhMa aW!\?sOQҠ[N\#2<^ M!YbޛY}3^xF-jcQ&Oe+RL&B;'\Oٔ/ICrkqє'ί)_](ʔ@\"Kt/"~=j]U1) ?oPch_; T&pp|9돭,A‡#֖vueX22:#MrMYbHpOxjNNrv$PF0B\|rѢی0rG{AuFG`=:A}Q ~p)Y7A;VAh*US|PCiKS`aAvuc3sASpPҬ@U=c+uO5ꊳWJHO6Bb ^-T,ڮXrZ1"֍頴onθ;; M؉#tDdE֮;J;shu@>_H JIt6Gk9>#KMg/ ;¨_x"G%'_YN$a熙ݝ'T,7jYm$q!"Q"Xf .5PbO` Lg#lhđ'+wku(OD h;_͈zǃ>P(?3#P|@чp0C/7EyG; 9ۗ``u6XuZ\g0ŶqgMQ;le3|h PɱX}P2)eJ 8_Gg*_:.wE{vb GxRoИxL H5q$qm_mu?[Hlf)Ŷ0c-ިx[2iak}'fW]ʯ18.)0NI):xOŅkW&EYD<l-ӷ2h]M?z܄*x^,'寸ӰM2eq2jM q5RPdAL)aBVt6<*Daִ3n!I`}?1:Z-*Ww R_F&A_) ۓaA?Z,Xpm"}DА r{xRXo @&oqWn}T( ܻJox2S&|ȻG(vdY#];IC=>D48мJ.O /tz0C3equ7q+%sŇ S1Kqí{?yf] ڊgM0qvD+%5K6]oj2wl'lRR-?vd@ ţ{;}`0xϫ{_0BB$>瑻de^i4@Hԇ˪N8ʖ6,d.H4?.`-[;C vyW/y*z){48~sݽL 1u;I~Pҥh`+wr1](3u}\\@w\_H;<&eD nW_=;#04Q``V8nSO1m]s7]@(MPu3MuTSt*k\ۤu^W&j0;tFD#!nNA3Tg.xsN%7 m{8, lVlZScf,!0-??pdqAM*I6Q7xjWX[3FM;~D=oU4໺,Kus=ꌃpF9=, ztmo0\5;cQ3;ondeOϕ+l-漓pX9n-8>*1_G3<,3>[N"l7wḯ6M\2=_?xQl3nKvBYpj"d1/W[NzG4+he3ȧm~USfL ,ZcNA@[NJdχ BR3饫?Κ ExTJz2Q]p<sdÙЌʹuQ㦟naPSCi;h3+ }.JWE)@@43\>>Y:XPu89JhyH n<ʧ`Cz}ZB,NrsלдTTZhpP +_Ӝc]MY2_䣐r3|l8`yi) N)zhHv=$<5.XGĚ@&=ϵ9PH<c:\m!a"]tFeAd})^~ zeGVKir@){ίMI3}  |kh:y 2š_Y;9;n[$x*^冓uM88ɄdsD ;EJK|Hb3/Q~lf/_fկɔ}C"bMLx#4=FE6}0Ӻnv~/{l( rg`vC[ƪdxnL0xCdE[jIn-wρl5}7Gihfb,69q?xhGT}X`.\%DJ,-/#NOfF$}6iMf4W6ũ?ROG[5Vܙe,ISm,Rs)IW(Ԃ%HgO}vĂיҊU۔$gۜ5S>w{|'6%}0فWigEmlH^|ys y>WUQϹ.jc3dgP5jAIW~w),h:qfy _X<ַvo!ḋzJgо*:8g@}Jov[gܽPi"8Ne2I8)z>|2\\:q[*^'QM 2SX#7mtwT {'Ʋ V=/V$ٳ_Em֎Ug/jIHĽ*J2mWhY$P*}ʰmg VO-BsH5|K9ogOf^FX?*S/un)2mhN"r$ظ90Ym Z¬B>b5]$<׎6%=?T뻇3=Ǩ.rMFRQ-aȜw?s--Ӯu-.Η&3c`~Emha%rh 6y 缙tCO22==^9Iko_R~-Q83RsLRLUYM͎/ .͆hURU}kKr%B}@+ J7L)F]doluO=? rOy| 38g=U'9EͯI ~vg$Kv8*W(et#4a%t 91͠q,㣯_MK_&@Ux 1a)C|긑)̙9u$P_ M9; ʳ(H*-Xw`,fq(„zH@BTȍC$%#̴kچ5l 23!]{S%q[J6C\4ڙ1`O%ScĬUǬFU73]mGo$}cuco/}npfQǟ%\ܝŇE#zRRv{R?krcN`W!qW4Ëe> x0|tn>= V[ @%qQ8߯􅺨E&ԟmUXV^:x}OM:p{7xV7^|Q_YiQ=ruw犯ů-.E*Y㴫kz:5$5P ^d vZ? [E܂|=Ys4V_$ޜO2ZH^n7&2w$H=;fZiw2@U7)hp(v.U5z|lUV\W(C.Y&¶]G{N\71<7XD mg _4UBts{-eшFP;gɡoï71JeԄdA-rwdչ]ɕȁiUt=nǨ}A kֵK):y!~;M \z#c*&0IqbG%US;;>"XES_)dtUN4}mh(;ʇ •  vΖr ;4wL+t=?4- $3[URꥷy$4$pɡN$P]yn>92ad7{#nĒ~c&1οm;K; vwVRƄzRTdh1l &q\e)lj3kHb|.낚?XejDJbr ])=Mvv(5_8oPშjxm+b1h OS̛ώz{1@~<*l9,尌WkzQqSOqӹﶹ'wis-b~C53H(Ѷux/)5dC+`՝Ls` xvhE] az毤=NP ^u+8a7/8OM20m"2C.}rbUk<,R_ݣvi/K^iǣ&{X_=xd|4{ْ݇Pڵ Mvu$ܐ]ԶLSĢg$ǣ^1d.J9v%$H8qu> CHwE7GbisIoJwfk"$4MΜa(^ !m~,`f;uMiՑ%velCO I1o.[S][5Z4~XxI? /.&Lrµ/=͒b Nf4Uy1%VJoO]Ba1#&jrgK@N(bdkjr0 KNt2}.$-I>eֈ:d0_D _;RM sH?+1qpVo+BV+#[ \X2orp2UzZR6 w$A"7x\\\?XƞCzըPE\)UADzqΐgq\6+e;0c ߸'Hh_vPCjOcNݎkPz_ƻv/D; RK<lPR0j5(%YDA^?$G*P1 z{J^BJ DИyE>M̒Hƽ=Nv{K%lb!M?o%m q?G78b0Cc6jJq5CЎ$!^Ly@.Wyr%ٸ~žJ]d*@)2ÍR~5;Rhj`a:H>Qܓ*1Cs+2; Dud&:ɉh R̕ uq}Ct7&,NA)s;FfAQh+2EM:m>1J }je:#2q͐qô}IL[IuLXN1wYlB39[B~0cǚ21&QCi u=Np!~ʹA aƖ-OO"jA(S,p tFA$P!oxkmD;2p +lbvʘ@iW9ϸ7mj- V ZɈ@pm5N?ݙTY?{Hִ[e`|03JdEK%/fLUs qʃCŹKx闋M/qv}U/N`q_M RJ9&j)+smoq+cA!c$$~vQ] с/>0ɱ"v+(4䅮MrҸ q;n))C*'+ٌcZe:2ge[QbLяqy._$ P8|'X Fրcc@NHE%Sm;Ѧ}$ "QǖvhP4}tv&x?}@ }cW9hb[b=;@qWg{=7/z?yO -y=8~ B,(AFĔxS?pt[e1E9^:,w74A9xL~D3R;FdJ ;lG= W퇒.f-K.=6uERw0 `ƄBHl{L wr$]GJC#%!8I*7c2-3-* 8NhF* C^t:|2⟗qtz@BTƀ8@h>ʺٟiՊL ,%;$¯eX&1mjx[}< NLzfndz(~H0фPѴ1מ~c mVIHݴ#XoCS6cT}ٿMh41:Q(Y'qߜz1BqȽZi%ta sjȓ?\ ,ܳ^ɬrРlfS1AY!ki-}-F?k0Ñh&rvpJ s)HD'@hG ao2szA#JOgۆwlv9Ξʀ:vv&DA9K:bM W2rCC=5'!8z"//poN##Xmy=4ijp@y3yȁbO6sxawޜ9-kQs;\XJ2r=Ɏ}]? '+獊PS=t Rg ,&7bԆZ*iBA88>bVne_r70 RH`[yބ$lKEM=#Oq_.6-."5i2x?rSXvO\ݰ0sfkkRҧ2C{6NGaTaZi89i<X7S Z'J'*IVT~ex `0 - ycº'.F >[`'uسxB $ U:T|_56ˡp[ Fx?Ia_EHK( |%OVzNPzCϋ gi"n*M{BsNqBKC; 8$2yzaZֿ'/{Dώy7ɜxd ,F zi 7 G79[Ll\~sr%0{ oЌRL<+б^S7e_Xם o{`Na QySzͮb"_!'4-wͲ( A:ZHpEH'W)jyFؾХCi4VU Xp]`n E-*cjtg75mN FΙdXP{MiԘ͘ N=_2?VSAOY &^np]*Ս5q0eB">HSHMLΉY pq6s]m ppUJQIIu1(Yݯ$IK(J%ژ홎[vT~Kӣ 05m)/[!%inl3 [BKEDچZAMZ B['rpBXRHIΣGs"<6DJ2'& Yl|xȱc>>TԨÛg0.a3,gGsG;ܯEU1ɊtY KP= |4mIoG㊩Ӓ0 4\-W:g*CKȰ ǥ/jCdP +`o@jSDT'fk8Ѡ *sMpmiګs~7ɴ5 +)la\joqS|)ns; 9>NFߢd6^ 1%?=<{GoʹXeτ[h+]RNt1Zjmƨ ] iy7B4; b@uAj/2Fɲaҹx*ǁ䢜?+] "ۤ!ǜRHA#DԠOp1Gj"]x;)>Ҟm_ 0GufжŽe%3%N)3W-hp!Wfd=)^؇nҤK<.X_{t49αՊk{v3rB{3 oS1 <&S '6P`ZbCp" ~md欒;[D"-kfXaiMv ĉ2b nЄdxdO+ du lzS\Q}+3Av.& q?5vP1m̌ -8NSǹ賶_F:Q0! =²aGkem~BDnTUz/N/#_ NmXE#E Dl'4Stt1u,43EeƋڊ_Rqݖɸ#k5%L'U @=Ek {(ը%肻k^Dpj\Mѭ; _E/h=hDQI6ÿCaK&"9aړ[ͫ-`4gHKغW9)BgcHyD]vڽ@}ȴB8Y_EQ#8wIhOHsR_sSG{$pBz>AE by ]ȀaVrO$J밄- X t0 wQ-3'FAh*ޭ[d Tl3CQ) RX;>7E>`E^c u(IgR{+& Q1/^}\( 0_?I#Ѧjq&2Җ^bڧa8bdw? 60dmh6{ j(}nw'U}Dzb?2UHݿH\ЊLG$pH7)xq@s-_g;qILo͵$G! U;G~bˏӄ > N_5Ӥ7-S'ŎZNNw JZZ[i;Q8*~F_q8ӵӬxX t,H A!/(PȑD6a"ӕCcfum̑OiN@PQFqh|yv}l"*Pw v"5ema;sem; .zիh$Jr/fwmȂ~b&APL]@$!3cE+6ǩsY.4lw}D\ (vbM% uT_ϡPW03TѼ[in5\QCE+gMjSX2uu&./ ɑA`b@H5h6} jnGV<ՠ“̈X0_|zȘ?ztLeɸzF/몃6ӷ1h{]( 0!< q%C݅!:Knt9ќ Ы+XN6A\eWVA|/ދ8( 3ޯ g,9!x> {z|QBBdÕyk1*جn%jȀƲ  S3-)Z{ީ ?X'>XhpĶw94KWQv:23z"8/~lj_SSc2R@*nvBxjщxmxP0h1N5c3i ,PS'AМz>foj dDMokmTk*iU V>*Gap;(yM܅_ }/N):/bS?p{Kѧ} R*.)I}K3\5`udm l $,*=Iq4dG(ō Mx܊kP^pZx`rkrgȽ08OL95_ 3:U~ʋFoAx±iS } 4-BRX'Nv9-=jp/:s.%W=% $׷l@hRH`N ##,Ow%- 62 ނnNhVSc\ޯ[/kj{L(' `։ZΥ3?7$b>5?|w({o(vx.Q~ᥔ_߳K&l*k ؛@O)s ]hay5FLh=G5֞8 @jq{-'M-]"y_*zSAP`ڎmIEӈfsns LkQ, :gン誏`<ȥ_/~M59 o1L4Cyі,ፚ.wV)vƃ?pCJmM^CnX:l~bETPD.R*_7-JkcUJ8kGݭkܭ֐C>T@WlVsGaeHr60Q@扔!rΈ GG܄@Xƌ g `)g{qinŘ]\x=>M7mڢ_Ah`?$r65PN~շ0pB "O"m=gIԮQH=W '9P`W  Uqfԥ<go+t֌jE"PS2SxѪ>\/*''q#f2c-ܿĭ9ݾU=j2Q;1:\ ]l}Qo_Aw ՙe ʼn)fr@RvnfJv槂ضT"]4.N%!3v? DŽ> nr]R#=qS0O+TؘJVz15be_&$Dj4\=;է#E N(vѭQ\>*K`k+3`k j="!͟#m# _h1>Hncd75ҷC%cxgOD=i+ɄHvhˎ_F;HHGKY *s}-Ad4,+JLJ[(F!;e[QcmgLϗ\k`Ld08?Ҷ2R#H.:Lܗn VSf[ A%>3ba=Je]؇MmGE 5~?VCR:,fhfaFڈE^)lRΎP?WH3,[&3=\xaL!`6%Jī$u{(;L(ᢹMw96z1 @ (Tm%_ɣ>bY+:rd|F{"'&g> ik65wnVD.eV{#JUԬ࣍SЌB@+ -sr&`m/>FO-lV249FjV.w(DcrPZ'TW[b(W.\͢A&GǒkH% x܁wI.nuȯB`l)J4:̄(`@פgqSW ]&%T+RyO{oQ@E`&ǀ8, ?\jDه^be"`n!/; /l]3C`-]H nzEr9{k=3m `i=~GC.pS:0H!,*,TQ pw5^=LRy+X+7'œmV|C#S%m jꠌTozA>xzSqTn"AێKQq:2YWI#_5Ybr+IM S8-).˜Qѿ#OSzKI'YX6OS>)t 52JCY]>hޟ|a4е/;f ,UX4W@q«{?8` JM9^S(AVԸH uDwNt^jURIR~#Z0<IFR[]);poPc J,|י 6"$~(ߎ`7(cSO(TR;4;Ew/*z8\8V5rˁWeq&钦PbJsn5a D:" A1 4v_8X.T00QgqSr=h>*=3g2lީ]N"%e;ZOˤHb YB܈ @b]xb iz~f pM +6hjy|5a[A[GB,5e?D(+Bp z/C~d=kS #^ vJBwM3r&69 S[,8rf9>*뢃3D#\D,BE  ]G]?]oa^",}h e m刎$+0.:Zg-&,Q$Yأ`V\Bi ;@ n/-'%@& 8n w}JBk`1=qEdՀ$ˡ ~[?y, m3OZ'1z=FP1S\濋6lqG n XY2,qbP8K|mCr,wj3bw'M|=eY=HHhZyq8\\`.<4G5K[Z{ a7`5/ҔM~?g>:TTLޘ ʳ4HO t$ syi8,%ɝ¢F05g@6toQ7Dэc9$Tꍠ4" q4Yԋ#YUrF xzaNZ>yW#f]Cmaϩk^6BX Jk1 `g +;=[R1rAW& W>dP5[k"G#B!HcBTO5-Gqn&-Vw<ˉht,fK_A.M3/0Q^͝,s| :SsP>ٳ=V@ø+DXsB91fcǘ՜9`϶ސD$CҲzA{Nk֍|F5k.ԁX?%:ȁi!iԗs|<6!D& ,@ B[6Mhwf18#10dHupE!7mi2Hzf!F_r"FȖk@biz?JOE0 14$Ve_oYaai)-(D&\;iRGuV+=fWwhvزR3FO0#,T_aL@ǣ 0asRHEcqX&3{`tƻ[JboXk ,Y P57ٿd =uA'lO!r4v^uܵ4t3rY}lL7V;ϵ佭W  Ar;8 )"*Cm{0W_z}hȂcg<ķgZQ d L.fzm=(Pf OKaguMݒUDu!hZ)k06_[ݺ߄ O1Mmڽ 1t^JifCִ1ރv a*p̕ U_Iw:u4`jTGU]MWkWm:>j |Tuۦho@*vk#|Ff#m`dL=qd(jԏjt =DxܚR t/ J NI2_?{ᗾ8J` f0q:f%C h Mrʟ{dll۬ sH̓DD"q|*:P5fu).7b$W'3"H)C2Q=gk@ۭbhK{6SYUܵ#Ks倰Eh |6F4xU^c{7.xcd}jZk[ ?Ύؠ 0zЭGZh#yQN;ɘL F=rI^.iZ:KG)kt13 D)鉕]UvtzU?ZH|re8t;b:q5 72|^jWAT \ C&:\ShHy?# jɎd ΣsQQiz#4('VYn?&#ɦ;@~p l-[5dɄCҀC-SI~+Vr#x_aTD^C!LΕ`I*u{ "sa d܎+W]V7)$+`Hĺ=$nXv!7KJF ޫ۝3VW:8΅j~wߚg!\Kd<Վy{.KHnHrɆpf y7 wt7Nzr--(c2=|rP!H7`L`-In`}S'!լG@ Э9'C!D`,_T`Vek"croxaX(VXFyiblS;B^1atqD+lK8AKRΣ#ŗLګ#Ah|N/G.MzuYށ• fR(&g'=s7R* P W XW4 -1Wk yaXc Trj2z_#H1;jǁ1<[#lϭa#=|a'U':r=8LRjEqHrDx7u)&nL/$]7E^.C"%zWtv=*gd+@MCō,-n */X*d@En^$nE.DO>d죩- .G/!5Qi۬2_AF3ba5#K r'EAMa:ȋvFra}5τoIxN`V~PLOv8A ?o,LLbPE++M# sXM {GA nj mo׫>H~[zwLS՞$(Sx4?aRO"o( ,]}e.#e^]9_' s)- K+K)b0} X{&>qdUV׼ Or}QˈYl+9ڼ0a^;E?NB`H:}#'Fa< bǣ䰢&e "YYRcs9*"M)GA.̂vXxq!|AN!FjCNQVwP-nNbQ\xp`N$0? 2+_I=r [|xse!L2H!߸Guŭ{ .m+o#툹 ~}b2MuL.Yk:ȁ0iwbʝs.B U<Ƈ}1<3A:9c() Z>f'%jM`¿>-ߵH]/#?vck.x`oͬ9bh'jLCr_/CE27?}&{+g%ō#(1-eˠrqpL=؆S[.Eyg!)*ar`Р@̔oUl_Z9A@Y޷_?G 70-ȝ[cwB+g$NJ+"3 "`ajUn2Ͷ4O~y/IEd* ⨲h94-xi:䊑1%׭T("'/A[5f InBltt8Aia_ )fs:p6喞q;-D@m@] @ILV=4-݂gآ+J?\WƗMUQgs QD @+kYFU?C,-z[–kŁ,KFdb&v3𕔵 NIX'mZFųEA; &1 bpKٲB l-Jԋ?|Y][>[ݴQnEKOj?0`` Rj-k,F{+_Pkn"ZBq4\>{cfܶ뭕lgxʾp3 hw8iK%'nur3+s^NС|b8Djb=titoȎ ]6C&AhH@ >pjrN6foW̰z(n^@TD;2+\uTuM)3C?h&f-"-PhA$ ~8c&zRj2oh{ t*5N{"讌 >X'Д|O/t.8l{€GL2iHh ݦ}#d*p`[T-'UZ(r@P۟{~5b'<{4HW> ]rf07[uM*VX!1ݶek4'UxF%Uc񷴕X!1%Ei9G.}a0{NL߼߉;3s3a,Ѿ$ N#I;Ͼ_IMꃶ ;;J}3d<4X PpWacCEI]ۺ6#6E[(\OdҎ(YڱHǶ@nؼ[W=F%?YƛqpNcȿ *>@2ft;$i  =\\GI<MWa=zbCU^[BX_ɶẒ{o ͞m+1)`=+bF/1vČ־7\ }A`Hb-$QgcEX蠔W䀐ExOx =^+# yFNO`^Lv(A=p;B vLGr]h804a%NkESzӺzqܒxnN;ĉurun(Ą +RUI .gO<(ԓȓwnʍ񙹊-.oO& Lc9Hv]!\=b#fh(H?\uEB r ǾAd^.'oOYmѥ#óL "u{-Ψ X _^q$L2"8 ّ+-S13 H@  Va sZ'NsbIT~}3@%($_BJz4AN6 M,2҅y =Rs6$BEImxϴ=!"a@z HToBp7G9/2HGܿyCF)T  wp8S~9?781QOhK= ?DΦPgtuY1EC@L>t$Ȩ^Wd(Zޑ<[޾$v ,e԰b#GeQKzX 1Ӭߦ:1 갹/jАFr1)XCn}Z;9Wl)g0q9>a m&J0ViڂƎiri! ;И/V"|hԢnYdϏ+i.e{k-hf#N4B›Q4l .=蓯4^2.6ތDACE}A7PyK11 N4ʭJ}NA]#W/v嫦߬4.nNBĻK\}lFQ}RP$#I&Y}r\rJJxTAaiv'U ײyO 2cEǺ,{ PňY0ٶ% k{LDoE;9}9#=45 ~ E\Rl[v1Y-6&ޯ]~[w<]bt._nBL ;]jtG NԱ1+nDb4hf])h]~3̠Dغ2b}`qr<wTDoŎI?ǚu}d!%e"/[^mM[D8p?XxBX8)Z)v~(?1?Ҫ狥;^qmMU;BZ#A%PZKc:?L,k{Dcg:k} #U} Jm5:9ޣ23 &V= AȜ6qbk`hC{P']_KVd=?y*z"#K+w$VZ⋊-moX=0ώpL!\m^$ 7,MS.@b~)|* ѭ-Ww Åť×:++Gr #fBՄE;{fwB_ט0I]eA"uY׎>ʭe,Qʲ8/ `5}RcdTXFX2x\+@i%<!b\Z j!kfA0u|,jYXJPaX}?Gb]Ӊ- zj|YĊ|)s.h[up}ZʚP+-`*J='j D@C kA M;J_;fZgk-爼R82]M5γ SXj _Rbq[2aΉpBdypp)aͳܦF[DL=C섁8‰>CB eP@P('~n hȕ] A[T9@B/DAF6ėU>X=В?wu( iQO8`A+F%Қ yNC'e;H,¯u;5'&?#ȯd ]pz|$vEC!bv1_15{lR-ZSh]$7iކƠO&כҤr!̥XZ9)h~8o8PAݲh6!p-=̻ӄRЄխ7w6 A.xgVE|49"먈̌OCVڌv!̚TWݨ.,Eٟ9rV>PMV@J _lPY= AgƵŠ5aO`z_4YbfJyDj- f%0䉐 'B>Y'r; oI52tQm +̼PY&W;abF`"dK\:'mFh0 &\4W!>;ւf L8ҹ< mZ([Z0ƳRbe -yi)*f戬íK8/y-]AGǧ"il~VҠa5BӦx")Qk/R|rBnF}̵`a NKyïp{8 +J6%4WNFA< ^HS#RO}D E2f Pž=z#slr &E;YX X:\k&y7Q'20]r'W9jl1 N7XqÉp/TrY$b]RΣz+ 9)7!sBuo&πPw}A 1 :C$4*ykp X@ RRuZgkj&Cȍ9ٯ`C$(U~|hfs6 6',NtV4IL&:R6dΝah+*V8ѱ [ȒaxHTX +Ɗl, 8 Pd T~o<EU ppN{]$ 1;Ea$m23lܱ S%İ0P8q1kMY%|a+YXPAԉ7}Pȧ1@Y,f`eQ;,DrhNJ u.Jz-='N\]T(4l3$7i4ߜڒQoC6Hfm%fΰI&\ ys7*OOBf5Z ؃hP1 )*( boyp^ܧ|AݺS\n1 |~PuKb8(x$ǹLAX^ڱ`mi,E0tF]k/LkFbk,T:i÷RI:g`ձj ؋ r]x%  Bݨriێ+;>qxm.Td]1wZp&K +[-D5`wP|&_pb:V2\P?qdaC!P@= @X{aŖDDIJ C.U TJ6);*I+i4OyfUUb@q,t¯Y8B<"-5=$T[wŔ8)g#:3 Si\@EZ (zpG;\̪ǯԙ,2g㭢d4϶& j~ 59wFUM.&x(Ź@TE jKYzl=9RQּ:/p/vm}VE=-~5,(Vtsj1o_t$&@ ]Vmgp SУFC (%cs^G[AQmIڠn\/(,#+ӧ`-KcP  k\A-d QǿJV [s̽Ӭu]݆6lZA_;-,W=OM&!xȬGpV†H4>G㬺 Z5,r`bYN0|_Q|cm|5XGX}S`1NqA4taĝ^:0VڟI9#3g!j&?H|pA !;Ci`d܉z κ)kME|Sa*IlxI;6S&*kx]/PӇGnF•`Hc\rzt̒#A@4 [z335V`SW/6A>n{"\h~ÎRrC D>pj堹rAJ_ojY݃ae8G iKVw4q]UW+K`B/τ{?Wufx5m$h!]s[l(\0K +ZZG:Ȏx2wfIYj!s.$7NnLnё*tz{K IQ/dm巤8N_(cΦ zW7 |GisrƩя +\L:>o;lPmYgOC(-W.`_Is)3ԝePv [wG,\RepU?nY WN^׷]b X\#/lHXNCθO 6=UWJ\ I|gNubUVzND`ƚe&zbqk vNy#݅Y:E0I!I`VR~m:GFXX^#ͅ0ǚ0PʂgyzÑ~:l`l76648xTF썍WÆ-odD-BjB?\e6᪟dδ$ܒ 2Q .P;[c\hc<*\D>Ts:ξ>=NgƮpp}80upՊ?']7Ǭ;0u;´~l?%kv$ $:JTy`Rt *~]|It4tF I ɝRSНjvxcv?Z鶑#,ȍ^'yψ$hyȩɷDGS m_4#:)ɗ-MŨ.vA4y`t=O̔(  nqߠ'諒JC dAFC LA58k*h٧2AJ k.g Q>,@v9 =xu#(B:rJȥN=kfM IvHAagwi٦|Wu.vzlȁ#36``/l6ǓB&z6! 5fN5t~)}4GG+2 KpS#Q]*j C1T*# VE;^"[Ne`5{\Nɟ*Qż[&j_"Y>88$gݻЎ= ]W;򳠇4IV-J^|Sq yS c#L]qip/hk9Ϗ"vRє w%YQ3 <iŻm ;^:I>0 _2-QڨG~]\4Q3cvAsfeJA.y{ 6Bm;G悀!S2;& b_z1^D*Fhsf\v+~|~- Ѭ}OU~>q+81ڬ @v'@2!k5!mZOC\?gK+rXe*5|vIarB BG;BX[vIӏS;7)c-)t^z0jafܫRI}<ʒeì)n΂$ (JUGP#_(0`~щ.;pH^?8'Bjx=nJ㟫m_0DP-t tej6dՉqlnf" +m ԭx:íyFCșؾO Ca3JVYa}ޮ,]R%=x#<<-p#(?нpeV0ڋt GJW?;uIkS+:3H9`ȕpn߿e%7):jsQA\v5W|2gZ:&r" L#`bnhwP ٛb󚆜Vi( SI%jaGJm&ِyB{"X6NTܙ~:f_yA;sPgX*p{@HYe-kC+|4avOܢɚ "ί-yEᵖE`E¯WWXpeϼ=n=}$d}K 1G3ޛ9GӶcUwЗ/e/KCub-%J TMTU +AwX/QٞVp?pOjXZ ,Hɐ<J&J3~*_G_8&{GϪ 5pn@2g<'q 8QY,@pFlĸs2mUZK dVהx΁ˆ'p]<K ms;4i Qu&TcrIƝR%Lt^mP %)†kM*"G};ǔXi9c}DBR h{P]mO>x,zgc_4 -E$5 YS_!x,+RNza<ְpoV-E!(qF>٨M+S;7Mimsj1<`n4R*Z,&>;Ɠ"t-(t& 2MFЉyRu?覄)Jwʚ;{]xl9m#x!h\i_Qz?{k~n fӼaVˮ>WؠzѓaHB=]M]Byn ?tS%>$e 5Cm3+p 9:,S'}d,ޏ fdk ܍vQWJ% =WVM{>lpI+aq?\4ݹM#DXtѪƲ(5Ѕ[ibxq@` >Ǔ|@nWe^o{2 ]~І{ ˇҫx?RwW|ݒ+m~:ꓬx{w5mJ2I Ϳ<,u.9"nKF3SlA~3},Fr;I+4FՄ1?aLpPғ&%σM\XI[-Li{{; v_e eE>e`H n0EY8tm"HToV:]aԤsT[=#X?q?P]!A6Rш9@B3Eu6fݜ|<WeW3pѝQv'9K| ;HlV!>sC%d#1&&ꕛOf+'' |`K1a,;r rD†A3ɶ } E9 :7B4J N|C^0/I^Hmk]i<@h6!\9+CTHY%Ҏ|"tqtq/ͽ)xHzTYqeg=qhy._ \9TW,.~>08,2UmnXǵ Je%)0kc}S@(CЖ9^fx::6jWLŗ9G <(Լ0G.mf Q7 q[L\;n Um/[5O?~F"}?Zպ1Xǐg]Ap=UDUK55t턔k7@SMӋ/5]g9 ,Z0L^{Y9`ߘ-jeo  sgetٜs @s|^˪?HD=Q]kPn.{J1L:jؒ__>QMw;1J^e_!cpl'5atW q\Ra {Md;(&$h}a.цc+(}P VF}>FfǙnރ)ZE3=+'WT+y^CY:d)`;8;X~mr4-k#tIJspg,lx!wx+\: ޯp=*2U}ըZ_b1i*OAѣ,0R9wEÝ4j&66蹢Gm4-?8cj歫 ϼ?g;'s2C6u|ƲޥlqIɋejsXм! n }gk1^iz\&>ssA*ZL"UY[!4x-L ;ӳB۾#cΙTAX\4ڮb'2 Yn&*xXVoٌ:-`Aw)ѯ+Z* ^.Rҥm ˤ8PH[Rh&i#*Wљ+,_K A+irY7S=%u~bncru+g = c $(J~evS"o?Rw^-uej.j)X/.F]zD" )(mh錐{גYՁs+`1 q.xfBv!tC wujrtzP1 ΋%-ZF~CԌ1aHp:W}6y! }z⸖y#$`1q8[*hV$lR)X&]-1hA\"z`8N%TQ .0q لl z 04%WP*:&L!"X;x#^00Q6C!Pᝠ;9GPs @wLJmc+uTf+Ir4OH'Z>㌊/ЏeAp $RkIv=UӤ#߬#.J qc„gZV'c3&&v*Wr5Z%# VF φ4\ʥcjq Ŕ[&TԜw8X mt}Pq =\0clTnOY-R?sl%3 ֥c-XнEGv QtU's`K3;bdҗ Ɗ}n ^hPk-28^QyJ.o"vD[>̋و4p_8)\ƪ0+"n@Vs.ӻ>qZÝʉn[;V2Ml:NԀGVHd8~JLarV(k|z9']lLSX)["UR뎄4g ˏR$1)ʯ0 ֗Qv:P>3e>BomxK6?LcJJP3c&W@q;sSiZ u^C=bE4d ܤnN|>؛l!'Q~\wѴh1![E0]y=bSNgRڄwp-NnА6J,J+jOT"Qh kNsls]A!T풕;0;?ƃ^Z3Xoc)_4~\lUʼnjFbhnֽ:K'=F9*{IcWscgfjV9>@ D 7 : ĕJȒl929~iی`&#K/^bAM?U#+IG"}e=~Q rusGEkTE q8 n7t['Ky(*0Vxp>qAWYcD*y&':,lZF8ƀ}y 9{Y{n+=ms\ܩx8a_^1}q7O&)P|"!87~+,QODʭ*px&`\Qʔ99=MĆƏTEmq3mIC,| W-2~޴>B "{~%azvlKhѣI3~ 7G.A ʑ p>PSm5q2^aY#Ai\|h0:J.S6,z=& Ԗ$B)NȔ"3Թ\hړ䁈yI>gzah( [R X2 LEvi I OVطC徹aYOr)h Ibg/J47NŢ 9Q е\^V#[b@+WnbR`Cr|6-d:I*-GV%?9SwCѢA(]m#bO< ! ֠)"td68jTiQV4"g.liG +@` o j =z@tHji-* 5 1_:XG괻Q뜟{W\b GIBB9ġA[TN}},͡J酜Զ_z7K :ڈ~IqRN*SWt^9;đ@C=~-Ū#":Zo[HF UA fs9`s?w&MM];NqVbDH@ƹlfKaWgMڷoy ,&̆xcFQf *d]lv@k<1uC^My~>wSl+z]Ҹ 4dfnIfΆRYADH euJk?µkҠ@} Rbֲܹk:[$ekW,}˔!P̣4Fߕ5KCC2`"OБh( ]3C4z8ᢘ3,i^3P(쥤mS<< ZUε j3 +p.\D%u`'+#vu<}%mS)6DbMTq㟴Zeu&1TRcY {[lPpjs:nCZBUd0X vb35&E:rXTߜ0v 6~92.Yn0 -(Yjnj p#%S&Yh&/CD )ZK"w>\/-\uf&,&ϝ z X7PLr~jdƾwfeD<"@SЬ͢DˉojQz)gҳmͶ|O{<΁z򱀒6Wi5%7˺n.8L+pJ46c>wʝN)QIEmf^KgF~{WgémEYIzNfZآ%Wab:YWP!XǼhO5REE>[L'9]*N Ȫr=n#C57 o+42CL[q[Ɍ4ϴ`%$>O‹e|Ū;=#Єs3j>cOkRC/~6^kņ$yc' Iy5~.j*׏1;1ἾlxZ/[iӭ8besSa]auc NH5E)ʞIΐAt G .1 {E gsm 69+%8^%u[aq}M͑$* XW#i,1X~֤iuZ~4j1X jB2XYTzxDd ng3Q^OӖqPsף&wV}O&d 1m0# !#-³Kžqbg۲ԡL!f fւkm,vK3CöQzHVj.H=Z{U6ZB l Beˤq\R-fNZ2M"݄kt=>iO֦D@"ߝcqy'FŘ9+梟ޡG<Ll@UdM # F%Ǥl_.9)}q R ~qf.hK_WDĹlF et<62Y EUDP>RZ2MO@ U}‰Q5 vyTeD뽟fDE!fK` A&o=5>las?s{ܑqk=}p# @BUQV*&]pmfCAN2U ,-vL'C(Y@j1kn:2ڥ㯉5trԙ|rgӎzs/m7#l y C2`*I#ZiPeEj-} z]-z?E} _]lp{zW4 O;l{aOwm4߃(m$A_Ћ Ktsl E^0-Vم  C$|gث; iO5~-K|A9W&PЦ@x mM6ro c8Vv@h1rG{S!)&`P4py]KOXEv$@͋a0>+NID d?!1 #@cD*1ts=N!2Eێ௃" Ȋw_m44 D %0 <سu%[k}q*Xw wfMă vY4kg(G ՖZSiJk2X\gV7A;vxE؆RUl-B4ϐWaW߼@0$|V9Hjv,5#A 1`V_z$590J3'Hu-aR fl``X՞'W!0qŽ.:aHX星dծ<0Lp"rZDN5fb[Es+ØϞ.:)Jn6׏d}ڸcHq}7,$Ca+D6{015#_ mBMj=l)`1%p А9|Q%"r(A_c۔!a#-, . &U`q@z߯ IH'Ma4J@~m 9!}3C1^3I=1C\^)3קbl`I  N[ Cό||2Fk4yZ#JBFˮhT;R`t3G{}kdf7U*7e1͞r3U.TJa| {|7]+o2>=ZrljXc% ߦ_t7ƌT-wn(}v0% 0E|~`fw?^{%ܺ] LbzѤʑ::5`o?,qRCE cT2[̿g8x_Q$oJ^rzI߸gd®?RHpx`V?F+\rUU˽9#js3 C?ax4Bs0J%QެylNj2?jo_|Ռ-'b1qJ(Vck|fw3| v\ZY <7MK9cJ C wqX)aCՍ )(}? {71UV TM266өEdX=f#xo|іq)$" /e; x~?2)=@]?uk-ؼ&\+e"ӏ'zB&)d\h jwRy]n'1@cvz H:x`:x1xD/ C&9ix**`¬^ExZld)b#<ݑ7;i' `T o=\_ޚI 96L~Kҫ-nh C>uka1us V%k9b昙(x_a`-);K{,{^WyZlLK^d 3hCnHF]E& gco^@ ,dzgɱR8Bwmn)>+.NI&B]P]g?sO$L]P5  0 b f:}!B3#"¹!^<i=6SP@eD w+`{#+)#*PE &0<`t1 ,ey[9366]_'z O<Ґ`jb@ b˻}Y1Z.Ͻ}UQ\с7$V*2rTkmzI&5}GvbQi_z1,v'_E/"|mb=L] Z*MO*(0 C -(о 聆8" C k+xhLh E k cVycoŌoQ[4vDc |;eVʄO,&pƙHܶ_@83HN)LwѵXYS~6䝂)$üZ9}w>]@X움ZFah"Gl -<- М6L]A-'7;9+Л X1jS8%aXZkfkC;XTc~b85p#X@ 2A@ ցLWĆqRYVO'YW 0OZyN({af< W/Ɖ eR˷åuǦ `I7ۓnW}yog j 3: xW/165bfXs{b~ηmUcYfS[Z-؎?iQyhpc2]SBQ5sUyv66h20A k~Šf:^V{ 6 *$oLhgt;Ȍenޟ#~05 [y[( F` m5&'El^9Ÿ@mg<9 4qP"\Z+YԸE|SLI4n^:MV^@j㼬C] $\h? ޙ: ۚ/yE4=ޝ $v5YO H6\w`ꇄ5b޺A,sR'wlbfdUXBQ÷h0U>\=x'qr意8GhkIS'9";Hq ļR3u槂4ɥ\4|ÓU,*Hv܍UQ\03ogZӨK?g@YggŬi?( k+D}N֯KXa`d7YͣXɮ~,Lb?ͻP={-Xp5I( A19^]1ߌYA mSÜJ9uܗѕiP c[H9>2~(=(1|%s ۉ%XjiͮYU9/9B:xhB؈'-'˨ݞ[EЭ, 0X_I-[,)|xqM=]lqW+!QJI՗ˍ ZU_Ng@$v\l{>iqzr8r`즀 ,)nhz^zY|2Ob|'4 @od>01OϘKA @v=n9;5 2 ޛU^YlAgc%KT^`qEzTCak!yDjɶY9)q|Y,,i_6RG%+ܒǙ^J(b25?yV:`QN o<>'G ݄Tb-f2MՀ jݍ~ށyAȲWMTğE@c,顬-,0ŰD]ӖעgQH2O]/ƾIT)-i`-2۝#Gn]& 4d B70BqBVMzC#%O5RĿ9|<wQ]ZP}Ym@e[BM? ˔3ϛH I.|R0P; mdƖgw'Sf\)QƆzq? {[bb\ o37HOXg߂ ͝ 3 \.k>g,G:.6^||4n5~|`P`v{>qbP-8l5w3Aպu0󃣥5=֪_uQU-htsx-uw; njpȣ~13Doj|B܀i ll J Z%QUK>Z-&j˄4!cj¹E:~V/  _kG+C BMz=1tAzjфaVᕍb9v*@PTy+;n{ ;ڝu\ ;\\jâWocopA*+NufYi6@tI{F9$pf'8q;`]{s+vZ9< MLܸu.^-k}bK1DK@ I`ɡ0؁o<˪5Ԫ,f}3_LmZ\\ ;&XdW>yʪ1jl_NC"[k'Ɛue0FMczj7yB`p3c`|gJ a$_M^×l²ut센7Y=k?DȊڗGKhrZ x .w ˤ_̊[ؗt!qec.0 р-r_w (Vu(=0OsOK gsًԋ J]Gel Q{:Uh^МrED!?%K܋ ۳J*/$<O Exe+T[2oFPKPQmue'y@a CR8Mf7+Vvt--F׭k L+?(3Nz)eB{83f` r!EP8Sx1bM~gլ۫Lyƛհ2Ktc`0=ꬋ hLc+ Єl.2ޞra@YB L4V s9i0m75! G+c<&MS$!2.j ,p&7uC9q ł}%3@7fQ=nj+eEۘů&8(4A pJEa!l\Xxл Ύ`A0]u``yK2kPh$2a#T,< u)K m:{YzԖinFؘ,3bt yD*ȵ*C]|QЊ|N`Nt` A]aTN7I>U  Dbxo/uak /\?_@g|Y#Bp:h'^rw0M"N 7J\-ĉ`1T>Fo*B^<`_sFC.1`3zXZR/Hzݎ*fns(W8$<0<"d"!;yYA^0s\l7>&F3_kFaaB4܈||êPX(<%5Z>~u{=cEKD9ӎn' nh_XA_WA7 ?jZz%# W' ,).h5jF*{H 3Jc/"{kSf^~.D@gʳ%ΎSq7HqD1)(z3-oBnܛ u$|mm=Ce#ZPebYu9# -SxܵxȘ2ה8ůEm2! khåXj=lIUgbb25f ʨhĺJ1X.E -o.Y;ۨA}0vjd 0E|z;֌fGr/sv!L|-A2g {Ke5!BB4:QL͒XDI_͢q(+G9=(_p| 1WK+DXpX3k a f7BΝ&D72VxaϊĐ@l/s3["*F+S:Ep-L_B3\5lnl {fG*`ޓq[azAuv>THR NI^&a' 3eEzdi> Ojb Ҹ=dL8 Iqwbz)U$l{ZWVG6V.~<{r P͏T[86Anص 5ԼP2_.KL}1&^MSSK^18!wpp1F>/W#3-+d KnUԘ͝ G7ğqjBoyR']4&,.=o@'DCu@$t8AWr!Kd!O:C\:Z̩s& @qFH0b> 8goU-QAC.zF[l5i=Dw!8-} NdGb0{@% ( {܊`hԤe)UL.Jm7u"q=R!5MYdtkoKWM뿅Y)>G|+6M'c /IҼy,f]wB ~I_5&߉3oILK؇ :G F1٣oSCl;j+1AZIm_7hZ0뒠,"0o>b4+F$!#9egw6xQ8j/;$pkZH>b=ubw1;3ů2`!l;f;y kg]xS4"YC_f4CbSI d#mH!ADv- LI@%yoF*V)"/xELk}&!=ūZ]w[(ER2d7[&=MIW.9, A/1*vrUuN] }"څ (n8ڏgoizIz`}hIܴjۖKzZuS MS/afR8wZx.8&6ݰʍω}=5Ifa`W8TʕU35.Q~EFa)UJxv޴w\RHtrPt#[Z08 <$w}ތ,bEsU0L'8f$Ad,$5|FlW-a$3YH< 7IxPv2{dz(Єc'Ǣ";A^WΧoEA,|?@ۈl;)kzF ΰ ̠ @wOy./Jw>S1hLdCa'?,?`vw1n'|%yyiiV@ZCp 0Rs.P0I8-B jq99Xڣ .vI} SU L-=s&?H `@oCiQx'`az Yd)ֿǚ^e<՚(4^.|.1%̋Up#.l4 {OmRId6RJS@7*uRPR=AV֟>uT!~mf5JHrWQ;kg$3S.C*/_o~;bE^zrMmaod(!1Y8d)36gqh?~͢H}_(Z6j3G~ )QR{M]l'؏`Bo|~( ~}&,J&( =H۸Í|ؾOݲv[ۼ_4,[.gA2iOhUră0,\g=.-\gNF f0v^Mgn\rऀ耝^\P_xCxش;9Jh౷zr߷i|l)C(WG FPt`[rFPOS=qk[)\'@o ך00bþ4EF²oęr$&3NULni >(MB4`I(+^s_<*V+.do)_W"jʭlfb|Vrj\`^+ovcY.}Vھ:./R_?^ 7=." FRt^yWmn8-fpPy{{,PѨhT ~ŝ/"֫+Eh{Y<'1a@nF0&x#B lĿ~/1+w"|6V lr%`TRPep6;%ۿ1Yi[3vSc)k}V֋] m?]=ݱ@P3(m#n KI9DH#T`ݠ Xj(1R鴠8b%):&gԕ)dM%jtP&{LWq׃9^0,Hr56}0̏;~zt ;^01ZJ>iNH|B~N1cUG Eu*Gm1Z/f6LߧB mvK~6*:b"׼=ߺ@]elAٰAn -2k|ux"0 <ۊkai}|ya9/=ᄾ[jT6ܶ]3D+T^p6.m.bzz#Rg;U9q ڼU4*0_3Nϱev'ki jl7zGŌ]ſ?U*a VFU~/al޴N^KII0 $ǮhJ$yhIrX%2ɩbRh`( [/ک/LXppV:0qkAWrMt A } (PCxJ#0%*, y0˙c@@XYyg+b7wHCP᳭X meI$K|6nyu %ys<4?x ;uu/i LF b]4BxKYIQoEzafãХl_vL ܶSiC 8t/X3jc z4LxR&`CA:~J 3GdLG* V+zIn4K.prevd@5DNӗ]%n˿=7Ǭ#/%G^-TR8l Gt8"0!e)93vLY)W¨R9Xq%@慟nr>F m ǽut&L3׷}_8\+K" +J1߯a^Ҫx6#I5UV,P9ėuGYmv,kFT5Nrp~ +{mC mӥA)}ڝ]EycZkI,8\sXp۠M*XwFrk^mi kflo.#eV%HqW A9g=p[ݘN|QK~ezJ|9C]5o@$6!j=@^D@0(*`L_bu?VطKM̷6v-*E AR2 vB Ǭe!氤d1WHY'ӥr\;MݮV[SM^0N\ugrx{Srb~]j p_??,z>碬\LCbjqXxs%9אHg dE)m»XiAaΒM`E!da!'432h0$dmն '8m{irYb9eNjsNPUSH@B}C5fFX{oznQ2Ж&=rË7n@ng!m vЏ/C;۩|&B0~j‚ \ErE=™j+ b/ިxB*Lm#kK_B)`O┊4F,|^w0eeL(ʧ)V>Dۚ^zX1 S7DLA >l: \akX b9 $G~[Lw4vݡ^RLf2Y GN+T6(A_b]ow/xBwr,0cWlq zMs Ji즤OV5͇`1G)wYȓҟ(54_,J"&<ӈ z GcQ/^H!?#|(.x+Kkr.<i`J˱xZ:_O}D@l&HAq IgB$ /=H_듼ts}\QprşPḁf(C&rչ=b!z"HPpJ z]guwR+gpr,!/$_/f{7[OY XKn@.Kym !w-Y0fwxg/#ش)OlxZ1A ~>?[W,S6aKee~wB@+g()u6Q.!T 22#/W.FZ}|{Vh?\L=L*-ܬ)aD*̔= Z~ LcrЄGw 7сntв^1kHvoc'<J;b&85AgCv JVT(LKZ 2"? G7|D4XhʝEJ d׭#UBQGGL% A'܆ e{$)ۢ\֙#Vro3ypzNG ^&jC^N P{t(Z_l,s{V_s}b<};5ĝ@qYg|\=& {6(xOh?_n50 *ӆҏqĻ?fkv҈x)X?dbI|gQv[) $dh ΅s{(/=lַ_ $܍b+,[G9DK'}/<4EMqc.ʧSRN?1x IRe}~ .'82ttHvr vGЕZ"z[ޫ<dD PlǼǓ:G Ɉm`5}c-⍙cc=YK"r“F:f^5DLXʪ#ҍ#Pd2PHG 1SeT3!x/{p>#X#ԦNEr/,gR1y϶їz:Q^(1cn*)~P 9Te26;J3wps$( T$woL~th.זLJ*4 Z^ `-wJ;8s%}B&-#Dum$C8wFUZI Cpa;Loz`>EfއW#-~yrq{3vTďh4m>NA|~_HMV6R6L(8`Ӣܔd ywK@YVCk~-K)z*Ѐ $^caSX ٷ!P ,-6$킞4oM`-\Ze/PH*j;׼,Y.HɓBϙMXqv>Kj,5g#սuԼ<@`MnZ^TA@+B~I!Lwβ EifRs$`5A{+Laɶ!+?e{i3Ip+[Jf!qJFi/"0^#1RO<{1.tT$Lx}v!}#UbE`> y;K%pVS0딅ˁb҈nƷw鉼T}?8ghekYtIȞ-Sw)Lem9 DXI5Wa7dU?um6X=e)N]g=mq4`Z[GL̇㈏[#CgY$+ѓ]?SLcOtj"k;㹬E]mŒJ0n[W(YZu ,zиu75H'@&N7\+Tq]ҚGC!唯#4y+ J4O+hN= K4H]TfXam&9=]~@yRG9hg FlkU):N: -Up#6ƍ`Ȁ/ᎮG 񂯋=b \2*Bnc@I cЧxe8E1:SUϗôf]I]ALzeb҈qr% $Aa0zK dʞYy P$*t =lς>Zd6r-rcmB:~@xOWVg"#] cL]nQžCeT-[dGL>P]8 #ISa.J:;-ekOcu\M% ,}ɣ i:.Yϸ\`Ǒƭ36cArh+kpc ]9LT*TȐ-K%osGe8Ng?[q]"|8 ~V_Π|i{TIk=DL^@dX=!w:zL:cԱK8ѫ/ vØ`gk ^p Ų\t6q/OS{"H#C|O6j3qY3 @K!`T&B$ _;ySQqK%Ͼ q~t{֠7BA{f-|R/~sYKqe Qpk ^ɾ@Se03v4.a5Oyu0g*P A8>s`U55 VRKN1T28uF0b {] .@ު`),F*Bao'd}GE ^%qAMZUZOmZJ-U gOapҮDWbeI܁CH[4}/S!BpyO5,A,+ ]N;a+C<{/Q~D'ܟTCBTُo: } .xCHaᚄܦ`O&C( L%3"R:|/6="_$isl!sm ̺GSO6ApӦk3%W"p}*vl LTX0ڮ$头k*`1~R.xÈi\Y87)MnZH p@h1?<(4j-׊2 ;% 'u}Z ["W zsͣ= x׍Yů2 b{$Iūf7?5Τ^RϵyFTbҦO#!n&6LHao$o)g;c|̤^w I0K> ēVI4RF9>(nPi mSפɑ;0.odEn/uPc)Yڛ PMe>S ip Ϻd6&~#N$CAZ+ɭԳI~w3YC &Mt.QE!22̌?Ц^}p:&,c=n-@Ρ,@ z8g{SPfFlRD[V|OWj-SG jȸY{絎oݻM۠ "o(ƺX#4-oEh1a })iבm=L@t-X8Cy^չetg(Loa q*Q1jur}ů#*-u'2 HpfVΦ>oPѥ8[&j^J #˛L -BYw@%w|!WP 3+sT)`򬬐MЈZ^K!8% lu<BW3X z M#>'h&l|xMpn@CyG%X`X'0 Dr^֘G)/>D]eQU7!:E>R=F{(ދw#/>cgn-zԨD؛ߙn1.醋A|zNwg.tChLJK ;v|!%wq哽{ײvb2/OKͲbdn0 M"G2 :l}_%Y"٭"ih5E#5m&6sMrj˫g T@fcv7YifX~+"hd!tBeՑ$BY2ϱȍ)WE1k r얭A4Q_qӥ\¨ YFs|jzS*ku`(_Nd19;0Fm1DķWC&lnִ6\E }K`'7imC$;0%uXM+- g6]ˋ>A3ͳ nwm>d@j%&'+G-Ljk~pSֱhǨ@Z@4 8'9G[_Y8.- o^ؽ>- "N v9t"#yGfA+nndLav3%̭fBMJzh0>0c;圖±|om_з(h0]+-l8;!` +Z׺| .Q I@潄"<_RE)6h[tJ1˼ \L\",kJL(["8hםp^dݑDAӁԝ;ַskRQM\d^7M'=;_^t%G OLdlLU0 zꙖ@+ԩkEJvD-҆ զE ^a\v 0Apд].6_ -* -0G:$6X( űոUt6?Dmfd)s!I@76D =S)QS`~ !_ܑh7q=h?OڥadXE U ghrBP4}>8PQtaQwͲ1n0'ͰҠ Y2]zD>4$q~5M ?Q7Zj2!͟vSR7+FH833F:ِm$T1}^7Nyͦȼ<u[c mH+|79Crjs&n 8g]& 7쩴zy9_D`&sl2\ߵbVuD׶*-q۳\ (6ū1{F; rKJX YK }3DMbshg//d$.Pio벹 Mv_J4 E>-pDV0cU_#8wmc>R]CF؁渠l2$ xH'Z\ C[@+]Vs{l~ްxcp0W.sN#A欛pµ_6j(Hl7@YNrWxnXm88/,G} l^z"?g$=[_j2*3CcYi} l}_Kaw2./aݏκ3tPLl5Q[}M2`.`ګ;v_<-"3߆3؆iUMb9ti g_rykutBSf,{xHt6{Dq8߉M<\Q<>ƿo{b8+;r>HJkJA'<hCT즰.vMTpecB鑺0,O)}*q1?l'>R [C͖xWؐ(Pj6egpY=EP?Xx%93 XyN%!:|7Q]rGt܂>dbjbvfPM яbحGƦ &b][W^u='XMH9oN_8>ࢽV)i[Kd28{"^l!z﯁EF6__Z$e%ӿELAfB9 H$K $%=MRqCTn5o]%(h'xVEy+G%ʰ4aG vd}pI,ɀΜ7>rgRZj+yKWg]vTFEx3gq4ʕwvg=#VBW^WQ'a?%:$Csޞhu>>``CbIcWh&80R>)wYM/Kn2*L~QDDnzpKNE*QNW=/r\g. :DvֶgЩce.NNo>ꂴq\E{ݲXBaFS%Hsi{Ѩ63%~ ps $;Mh yX9W4.mt3y2Xٗ~$ D!+솢i?̊MdT=xn3$6+xdfy(aެHBv5 K 7M9@̳Iq܋5Ժrb%= "y ttFԖ{qt@5u]L'W$ľ'C4%G l֦~h ߳;1v]7O훟1KA?1 P"MAΓyjKVVO5M6;)O{N&Bր8ћ [8T -zjC|qWkDE&bDaxhDV´k;kmF ;š"t# 1_[xO0ŧ"Mxp'`YSBbҟiA3v1ևQ(՗ІU"px(xIASta9ـ10yׁlR27Ybm` HEUHq7q]C(%'NM{TVthO" oPR-z]n#I8P$@@}~g,4f.\aʩڼ?5(PT. zHzw uU:.85j>E)o Rյ=.tY7A "%2i.LH8 Zgiu+>E<ށ,9A Ѧ HèݲfacouPŦϪH_5٧)M1ޠ <~LBC҈ںV'n}J>9,:` \dxKxK)t@ iRiw~L`>`:wdr&+3e-XBt#RӫtI%ߌ=wPLh& g"ϬJKXOaѐ1>37̷a+4b7ITyZ^vhLǺ ɱ?P 84vNq&NT7zia U9b.HF)woyCk@E0w+:IrS=uԚH'* e'#3UyK c]ROR2J;ťĊqop_* G ])b܈H)՘GA *[!u{(0OcPl$;}Mdv!SH | uM.ԋ^_A-\n@B3^TW=8}׃; Ai*27"Ĩ5IhR)ch^WIɼEK՚u*i|Ϳ_ 99K׵+6I0i` z2zEwoWš:2 >~|YPfA5k*zG)uFRkZ7Xn/ͧ緣7ίXMje>wϬ}>93Hf ?6=|ĎʖnM߰:i4z" ST[:B `![޵|3LM.#Jy ʬE=ާҹPs S!\B "&Ilp.)2 /!оoCu?8GpABk-}p} cx^ Y!eS s$53\s* 4Co:EE_#mNW59QIQ~.p]jM9pZlx>RG Jeڭ :0İ)d" 7m:iʍO%Xڮ1;]M\r=Q4O}.VgQ':L8$}g=,ᕷU;m ю B]!j!_6^,Fz?i*pN퐒;oPI:eJn IfV3H+V~AO:Ê< 0:[@RgNqeSjL Nutq'w8RkH[ae#J_+N3!4Fg.4zm6yǮaN9`l}$˿ |9'cO]0{yĊ=V2%1ri3e[c}?' |)~1[0mrLxԾ0)1EW C1]~$wM!>@wOȞzcGbޱqOpOj &&6~gIקv;G5m(ن Ci YcIs9\ŦTh^-䤢#^7U/n^{R]+)[)P4y(@w4ݣ,$u[H-.ÛɣYT1D Y|eW&t3fs >&l+iD`QNU.:.匬ےFyͳbOo?2w4PUܯ0&ӛXXiO:3mթ5[0 x~8b.=$X"'!au ΌV 3ǩ%mCOBG Mߗi)ey+6=f񸡸e@(E+tXԭnfQ*ށv(]\gd㢽g9 |l07lt 5%`V" N6\s@:z;xsYroo3MJ6}d!uLMq<Ǵna>9$0ř|hЃ)2"-/ | TVO82rgZE -p)&,G22lEGauUv`*]xC5&Ub@`xXg3gg^O=.%ji(~8[>Y)pyί9wk/l۶ +3 3st9:pctXinJP%XPm"P >ԟElbiZL_YKabͽo/Ff7xqfytN/MW I޸efRbsD [eUYF̴FrčOt7j ~#H[Jdg Ou9ћ1S:4.c[ꧺ.hjrYF>rXX3zfQsNÃXfID7* AO1JYD{A"}k]>gG7 xᜠ#,_mτ_slk6ܧ|K`r]|//- |vVmMKP1nLݩML<ɐ|;m˾*&'Ĵl7@y:bm' |NY(4ғ^o>Ƀ5VJ>` M\]fmQP{HsZ'I :/ZYX%8_%2vB9iu5}>j]UqnLuQS^tՁѵQ4>j H]$&oJի9v!^xZ!/vXx+=xOE$F46ӹԾkz һ2ܖJ7FCxl^S@}JEs~A0rݜ{YEz 0(ZًPnR18Z1$JL1F*3>jK_ۨeLh]leA/Ʈv0j(]peT:cZzGJͰo 9bGOoԀ$FJcsձڽYl*ecWVo])}CYg+)SΤDp5D{,| /.P!Js_8FNW`eNFhXQ*SZtXWk)Jc`"B:&qv';0ؖy@ hOINߜ>#nRbѝ0FGpԬojyU,9\Pk8(rǜcf~\GSì "оT{orV,#sR}9*-ѱܑ>_ʒZPu؜?"P*9v4{&4Un6К^0I`-Qk{ &QM#َٮT=Q>X>'<&8*H"!<>V _J繶Z.&eRSpm<4e|EA8{#hl<{OY=g:=gkhYL'qR -22#F*:@= Mvj AKVhC*v𗭿X|/Ô Ȯj*l#.:EޕB.yfHv, i,]j6-]ʟ1_>m2q_"KD&Z]xx;^sj0=1Vv}tZĴKu(-=[HoI|C ~.Ratje)m+s0g`tCJ4@CX%>$ c|TzAf%Z0 *^mu,Ι>Zc4/ *}$Zt:n%F[$H2*|uMEskՆ]aWΙ4KV93S?UO--7>(LI_TcS \636xo~Zf8xK/KH'.c{O\&ak#qn'5X0F.]{7ҐKZAe$$<K}@!|pi?J}S9eHtqq);t|Sl?#ugq(̃ =!f?ٽep_uSCIy^:>M'Fb/?R#>}q Ax2Ò8YQ%D27CcBsu呗~35Q*T諭PcV![qœy^l,VQ㑾 S[\.M:p^K',"bIEU"]?M2;l뉱0ũ^1;  [dq*NbKZZd4<8H|V;Es7C؃9#Āaݠ(XtlSApↃ$2G`XPS !@~$(-0Ycs󇯵0~c1+;9d1) gQ{C}fdu!h#/}QĆY3cOu\. ,&Ax&?TN^hV. P͞HE]E*,JN]/9u0 -5+ד&O錱{pÅc:\i Hc[Tnk'oקuYO>NѽT<3iExEJٵ,v-[n/$ bM5,Ïp'RF ق xa{Y2yFT}`N/SF9 X ;sbpژ@C&w)[Bشɶ%ٛҙao~k !/t f$$* l]0F%V@pKoLTX.+tPWdr6Yk6>,UT8n!M&W:bNH:z6 @W!{Ĝ h;n% "]'=Tn6I1ӝ z/qQx $sG2~5%!&cG::CS.cQӆ~^ ?]}"Q~؀o<@'% q|.VQ6zLs~J-4?ۿlg.S%^y)Rʃi@Zus:P$hGZT NjSYPB.W% IxsW&Xqe|^!m})QX޶:W0B QfԼlWHֶCs ޴˨ &mfRZ>q|9F%"Ff?*93P"@'&+ʅRȔ0iѱq^jH{5PJre+EÔg8PK`cG icHr8 S`+ 1'[nK?:e< LڏQLx*zñxHIcg2ٸ_@#38i#9(:CQQb'/ՠ13e:y~\# S gPK0FsĿddB 5tD)<DŽVsP'~?%u >Gx.(Aea{'nu0aev,w/Y㠝3bYuVzuo`j@yWљH>kȍӺL?3Wy3)`jwiʹ6>+W^|16OyrzG?}cKfeql^34(&Z]O?t7G_I sqd/WWXy7Cs$O%Ma`:dfz/ȏz Ad'KMXXshdR#/alqj_g%3iב.Ks"u~^؆{~"P#k >C)پvN,#0B*3uJq} ͠XV8E^F6ѣ0Dִxd;Bt]԰}x`@_lgLz&> 3k YxA&po[dI4׹RF{__s[ SsbNBy֒%ڇe.7&sY:jEd*-Y޹JjiR&S6NlM5FQ?*ޞTܣ 4X5|/Ɯ \(&=3;ÿ3JrS_shtS^Mƹo$Vl.i^XV]rSJyb#G$ب8-#J"gݤݟ{\<=Ng3Fo[x B#߮}dz:>;S._ ܫCiqB3[nc6f8K(]4렧fOOtZq6_ j^kk]꼱%gNRsӦ33aű4k4^ڡza< ::Ha+>S,*^]V;Vnmxe}^z co)=IL>1#'h㛸t)9.9ݛyo/~=lZAQ6oC%%X<ƌPfpX>euˠJ&,| ]Z7 + W__YHEǓljV9/L)ײr{3GoW݂!0е3{ۣuNva}WbͷDիgqMa-m#nu|mKp^͞ Qe6.>=X8?h{s @ rV!z 7LF;dC#oZ{l!f|q~0WnרcbۨbSW^2ffd/K֠M h|nXNNN"wm8"EFyS/-0%}~N;52׳&p݁BBhS)>2`$ohZѨHKJ<&ǡX/&=e]֢6.RYk/G=5Z[\S]+GR|[UE`#?#s咟Css<+^d{^YYc 8a#&ny~Ƞ8XY8 6O_ 3\Ӗ!QyZ.epNh\RQC?s;- s&2L8^ E >^;0Q& _eLW F yUmJ#I_u-h$0A[CJ,{3zyYͥ/F֕q4fb5X!}Qtf\Q-Rba/+3,S)M#&H[O5:r&wRx~u )Xw*OˮZ!ṷ{*CyÉ:T_fp#4o8F2^ÔtQsUyM] ps3h dJլR\kYa١c7 @mǥG8nĿ2g( JE6iDc~*csB̼dS:b.شȻE` IΓe t\w)NX(8I΍O7KMNw(Z=DHJ(㩠ZpLqzB=>Z =s3ntps+4E~rgޝ5~I7FO/ݓ( Q~ 0dˁ e80lI7Nt:n{MP!8H/~wS7)ez_]-sS;XV"!ʭ3 ”O:P~_6w <<}(49mQ㘍qf˻o9z;L\{n`/HP}AƧM~&^ОW^E#ź#T]ޠ\ːtp32i6V77.:R Љ EfE8yYzY֭#W6Cf.67sdL6arVPMO3ܹw{4%c7sbWw-ud8Z}bP<[CI&]\YUvhԲ"tz_w OE-е~iU9~QD6iJUjD݆ 낂ԸP,p6cDY~vЮkM JF{s;{|\0Rڂ˟m'c%f"(LQG/x\=[iufyF%Hٺ{yS,@zd~^1QKf;[YTW~:@。Ož{;58Ok<{&'l􊝓[mX>Atl@3rM?]I!>br֠uE}8CL[Pbs_?cAi}S WR'{[i**[Y_Y-տ'azu$ˬ(wU=FlͼuH3#PkL)b4o=^t9&Ҫj,aш8\Yjd_v]{@U$ZTYXVK|t|71G:cwt[ۑgSlʇbJqct+MVvʺ"jiʹkcrLewO_*z0X=e3gErJdپ@ԽEcO&aǹ8ǝ+>% qZ~þJJu|tZ\y3g;S .{=[{E:d+|TϽ 孂R!M'zd\"~buK{/2dr3 \Z@aB@fNNss-2|nﮑҿjJ;Jpю,gy q46V;uZ4}<"w26 ~]ޥM5:-w 1!=譝4nn}@@:CU9劺=3 .v I^^sHe=h*d\et(%8j*7,6BV—آ k43Mik&a>O>aen#Vέ^>"B#<=”pՒ1w&yҼpC u@*05}W uY!1sn<싇 hb+1է`G{O\K >hgUY+g(a[Vд7uU-eq>4VPi1x[ni$8-|#+yXBQK gx1[sO#x7i^g߿UEl}`;ErBTePUg| |I~}ekG9<+OPΨWYƷIt (I:rCCik _FLhgtJCJR'T?7, 8i=[~46kTIzKc|ҮASj|nfM/S-q2%T#5e^ƺ*S6kI >|ɼl>vu# ?T9h_W+pETie,>^npfuRV]rJ[vkvFɸ`B=#̿V"?C|T8pjg;\/p5/. ߸JYE:Ua(!3ە> msrЪTT(k$qٿR"Β N0"W$oN OOEG:ئb[8mA=<*^`Z3懼1vUi,)ZoDs?lҷȱ)O1y8j6 A3.i4 M(uV>옹d,(%7&=6Nx^D&Pʏro~|.')7 -s{ {+*c3rV9Nd+YaWj9*u캍ެw}'WpB@mq@oK3]C? fyG Ik_J j^ a_nz^==haG|'Րeyw^n4zkz詳ypƺy+t~QLH,JlTHŕ~c6:LTtab7elOs򗭚e9{X5NF9-X%Z&:&Q$jܲsR䆈p?GAՌnோe>mVW"pzt9 dg=lmҎIJ=H.YΊ쓷H9ʘ=wej8*(`~ey`+ഥy-;xMZsd|c<ϓJ.Hͨ(|779GˆoJNEU۱gߌo6Bm!7+n5W_>]qhlV]_],utT΀ɣ5* O'.v@jS^w=w8F+ iDpI42/f).RWFt4#VyF9 irF%8_w2bHgE?( aAL|>"xFQecwxtM(Le:^Lby$#1^EU22L1jr>+zf[ !?w╹TrR\yc`4eWPDmlZP_H'p/}vsʤ^A>!% O dԏ;{M& ơ[ >:#ҏέh_SL(QOjr%.vH* oJ@6s"G]1u{яbTi*{ {'nt~}k9s`\OYCq(v#[M\`:wTKKA s$AvdJ=2S~V/ܧvhL2B*Ʀ $íi} w|֞&4LLYB[P&ICCo)osn4n^ݟ+hw޿_lE^/F7L;c9 ?-i1%%o]v)+D>A?I!d@4tO}vA~泬ggŸˣr ?JDa`yw:ln0(Ud0L{A)T(oώ5;!st_WVmq(i|h[ǴjGW^q>it[p"UKGXku߁;>lkcߎU-ӌcf徚̢&3W2'__^kꟆػG1dg=G:ǩZT~Vwהe{]LGੜm}n[ 3<+Dۀ(7<.2֡H|VIӟnVtCQ׺ ^b+QDR n j0θf~S`hblZӾ$\]J~Q€)|AQ['X<Yp`]߻Ft_B'aj%Z HOZ߂ೆ|A~9wMZXt10(©P+ic{1$Eo9ݚ}D LTfVelA{FI_[\zvLacb:ArN,V{e\ja'N7G0Bwښ :1J˧_FR`md ຈ2 pg;U\ܭ}|땮>_(֟up4-ӄəuy5Y" - L}4qx9]^va. JvQm}}Oſ5^M$7Ac/ ?tGuMAEے G`o3|}GXxh"v Q 9NE,9Zj/b57/ <}EPCv`VVjcܡTxL~ rd{,e|)l-:\\ܞ ߚlw8(iy<:mVjgN}ـn̶5$3 KCZ?|msV@ ":b7w4Ax/JbGX۔,pgv** ㄝ}4R\( 4{#_J3byH0 qûWרdA31AX@kq(Fbڮ* E)袗)c?Bٚt#ӝ4&^>b +U dknrkao4ӱcA͏BؼԴ{QM /W5WV@SL wԋ6>k=x:xh "ۓ}g)tAlKSϒK3v]Z7-8w敡uFڛ3J3MH(M]9t<Nkl\ܲz2]Nf:wC(ctuh7*\T#歩v姊vtK>%5#J>.6iY5z8(9jqm= kku=#lbdO 's C&O˛~txH:za+@(ռ"<:hLBpQ,7/es`7ocZjU0e,D5MWo<~y4;+=V9q7-_H۷9*dа: )8Byfx׆խ; ^^2 Z>]_ۈ4|>:|vt~ hƧrYb[ҴU7;_vsT9~ÚKM[+LL'Dhqo<]~w{ /} :jycy** w‰c'g{ΚEB`x!A-ycbwf ]/6.n`/r:1Í=#y_ԳXHy]jPhqK& CYϾJg~dp7ol9թmM!dq=a' 0%Ї>kdv]Yӟz[u'!Od3 Ρk 兵tGHc73Pzޢ ثM)~R>![;>&J n9L11J'"5G we/QK-nw $(`Ҥ` 2ym%m)#Wb|zgIBq ֓YINUCdG6"4k$)c'QY[&vƋӫ#zal{Dߓ?.oWU:{ɧG"rG3{+RZT-5.?t.r-{9;͇E%c-m'v|s>W]]])_A;1 S)6@4aԝ"_C g g;G5 I g$[kIJH9yΣ=@#n'Pߥń|G]9Jrl+w17np)u\ t42宇SFq\6]AcM!r]b69l^5Z VTb2*WNUW:9[vPmC{̳fk^#qI?N9? _- Ď].IЕcs9 ggg^!-+;F 7‚[\)8\{s?\ D62Au#ΎQq'LП~z@,Z"a5Ud4"]|D{_#UWUf!}ݠN:z}eBAk x ]XF7.qA5ϊ5ǽq4pBcP`xa Xm iF|vѰ!l Z# //5g% %c!^o|@y4!l.Qe)"1,R &j &90mU+ L=vM]xvk[؅|#8xW!(i–F헵y _ %8!(*:)Ti@|W{ī:!?[U%AL|s I#ƒ0)_7*e=g]Q=W6"=O]y@H'-{^Nfs;5k5c> $=#'F%/⑾scsK*q64L> ul'c!b㜆sX,ڭހC'û+d<F'Q,PNGm_>7`< Z>(%^UfUT껑SF~gZ,8U4e/ M\pLb] Z9Ĕש XKg6Spߓ& Z= N$Z2êF$&B,#wS!hbd+6tN%3ј:ߖP;Ih,PVn*{Kn܌?;F*2Å4犒GUC&m9bi,nG%)PMۚ/QlmtiuݹTݿExJXWݛvUqy;˜-3g[/Sӈ'/9gF>Ɔ)߻uA~/ˬm]&i̹$s' 1Z*Pk;|c\epNr'mѕKq{B>G#^6G5`nc^m6~\š~%)]NBZ'=?Vڟ'ٛsG+A332k^a2h> 0{I^5Kγw7{T{=fI ( %B>Åé7{S5WGnjUhŭu#14+ЂKk\kC8&`#0T19mz)pG^%{R.ğ+x`E߽c<7, 0ѹ7}xᒡ/ϙ"[rzÙB=<5\̍oŠ[&;ELMbfAF&'MO #u*m_Ԑ> (L ɯ;zFhAh@tl$$s$Da=>qһLrN`ë2߱C!MR82](ޓ>G>AKx&8@o\Kܕ_ &閧X9F H뀕Rv?aUd{-BՀg8}kLcՓꉼݏ+~CJ*=E]L1#`Q'[9c&fs5DNP:N  VOx5͡U7CBnP;Bmf$lLq 1#4B'W-?<{`VH_ڠ~pO^q9o}aD2[Bޅq%U57u5~id˭[7ܾi\P3(B: o3pj ,當3;D}?d -I<|fto.72*mSvl <9V:21eY> q8ܗOMhܟ]vaC"t"TQէQcQF~0)!|ZW)oe/Kyt,;~vUԹ gY&_dis ~?6;_Ú^oe0yYjj X{yͩKv:?ag@fWkLt !꼽84&&HEujBkq_]şuC؛l"#Ƨ=XuoZ:v(΀XoV.a^)@OM%cdޮN*(vLG뱊~U>6a/+Aq\V 6C^/j@׾IM Nu~G_hEG}+-f(*=-?龢5U]*]y%IX=&ԷJ*R16QyoRD6{TcA@ U>5Rmun=nvaw?sQR>Q`͐FBx %B.RX}}34TSG|s_sSk" MD9Z5U?U]4 ?܇0c'_ ;2>yvt+=̯lyH pӣ`m#٫krAΩ̺e= b^@8mgo5@uV/Hގ-_SM=u|iW#IF]p6O[q"k4mVT"6F N8fp:\pc,\?1K࣯tV]|a]+ }Cw]pi+2p7 ٌuj")":e?PzV}6Nȫ/M8(›'qlH4XV:@X<·yV=*ƒv#( hm;Tva37/hSx ſwlYP>m?cbꃭ =2]4.To4O*^~7gȸFs]/ضյQ -``Btr.睪XT2~wa9cWUWMWnKQłqM11x=.R5Xvs"@|к#zO>JIאnhXAQ1ekЎrݤe|gqX:׮,%#dFO?˙hiz[ζ~?}iV''XywΓI $`,"ȠGo"~O~O[.)دXweO&`|ϜGVyaZ<27m A EA j*8\\$#M;'D1~7t#=EiEv Ưzk~Fu]Vg- Nz1]ɤ.;l; $CnҠRS_2 ixi_˫Vi<3Pk){Q_ x@z#n{QqL1o{6HI4DyˆJhiɧ&y+a2|S h`i =\]=jzhٛjl1 GN@ l k[MDQ`k%L5@>o VS 6 \jp0z^7m=UΐxK( h46fqYɯV!odf#P*޹Poɩv*|ϸ3yi]s\rIøڪf+_P`_nliRYx ፭v 2_kxن~vS푇{^i8}y]F>su+Qw͇\= F9L KEMba2ScO8 3@oq& .m23a,z72 R}I߉U,OEm6(B{1u+z[iG`abʧD^ݸBFZWcm' A`fWorq D7=^r#1Ho'AEBSKaYMKg[)[

D.rH4 BY:Я9WC%+(6%#P%Xu?/Tͯ2] m?][Oó8#ReC3dymEO]__%C{mxqs5eO4Z=a3PUkn^-aBYZC.ѷlrPU?t_n{W v g<.ڸ)س#/l៤ycɵȣ\,33{Zdp@gdODou66,+w_9w i tۀ68xR͑!۽afUSvN4st°Sׂߩ˵{MU<Cnaۨ!tYР8Oxys' Җ櫈W τрq\W5'9%;W(X9>|?Vo4CփV?ChQf+Gֿ*ГvGK X%k*_?iN ӥ?㈸~RT "KU%W9RY;e oZ49,1H!|oE*ۚ:]5$*n2?΅/La|ͮ *>ˉ1E;fso}/6ѣUbϦmKW굦F AW^Xk cFMQ& "@Fc2^v.n[{B7ξ&T0"q,i,Z*TY!~30cT?\΅ 掑,Sb:6k]7نeq*'8ΏMvtCIV 3R dWA  X vd1}eI,/x, v&,Ķɔ1ؐDZz@jIPգ)-lˊI#ړYj\&iuBT~˾)Ockt{5(ăxo3s^r,Bɕ G*TbqǹU swĤp3+aM($~0~L㹣eaVС9=^Cɮi*ѱJ4*v>Mޗ1*ڗ)Ӏ zRKi%;i!  \|G1 Cg:@+7Hl9=1fhb zU|FXxJOo*?kGe&ma(CF~4̛Ꮢ޶\qb\=WdF<? | I\_\HjG]D &(ma, .Our$,>@sX7$=TU_k#ohmyun2.k묟5ժۚ7Vbǃ|3>tUL@ѻ5T ش]h35loCR?޶ʧ5iC{L;nhi(K/xm ks3.O2,&d nNxfnN6ۣ7^M>x]$Q`¹k@<%|-ݍsv:Ξa,9!\/QRf:}<$ +xNn  Ύ1{sۓs/rO&cvp3,p֪>VR 鴻tR|}sdB.KY!Vc;1A݁k{N iɾtz,M.)  !LWh졩(weI5gĈ%O6ēYOڋz;g [BOQX#$/#sܱ Hrg+|RRJ=)g/x0@0fJ4p^,7 s249i;sd5dVsEy>8['5%n6h0fX[I`~{1g_S\xjs`Dg0E{| >ۺMג7:@n[} 1n!bٿ; d&(jn(lf"c>\~^d[b^7=S;g=ZF`@'n$ L|yȇ܀2l=GO in[b=yфeu]3B II;|SU)뒣\d2.Ơ4,)ccp\(oW-5hIpp&l9{çIspٷ7kbW>bȸuN%/Hf.ZftVDc27CKd؇Wөc6gIvkƂQX*xh)ݕִH~Ȑϯc/T {DBNa_(>X\F[ RËxazz9_"2<~ɛ: SVuNj -* c#COfPsѦ. P:x83\*CB }^l{ȻI!u]S=knMr4vDg꿫òV<r'iזk,^YOtaрV?6^i~a.ݕ#9mDj`Y PpqMqc3_:\`HāZdeo u{um|ǹ?ϼifUܛk1: 1i)2Q 5Iy.-|_11uY3L:V<yt)?VVl.jevcw^=B{O-%Au9߬Y6r y?^#efca};!Fp%ოXŐ L/Jf5R y׷GC64032^3V!{84lb{D5~ċffM_Pil&С1w1ʓwͦ'G. ';Sb}scM>0q ^'HS^{V->ش£ȀXn:Mn6näkn|y `df:*)vCrN>d=0qT 5:y7gGV:[gT z9M 9Q[^%3axU771`3GI0LĞlSlFL}`~Ћm*&ˠ-OdcάsO&|S ߄d*!+x뺏gRg<;} E 2iL,WQ oSq]R.mr=͇#:`?P~zKX FiVYކZ/ /3 uSkdgDi{Z';Zraf\Kl=YȜ CCr7|202vut{{d|1WOaoO|5;y Řk>fW~O@gg2Ӯczs+M!WaoOƏ+ֆƨ佒NBb_O?x1!儋XJ˾nN`Sܞ&l Zڄ d쟮yS dlsne.HzyjMiL-By\ >?'T3p2wካZR>bG rj-& \.Ct|)o]akAI''r'ZQ,.]M>,< ^DX8'#TUwÇg ^nhCne8.ǂXdVNer'3dP;r<_=L47#^do[o8O! Ӹ)8^C 5򮋶5gŦ{@o/iu胵' ۂR pVK/-zgyLυZ=lRWgwclIy82WF58 sU <)HpMMQ$iƾ1 NTiΌj>!GRq<Šٶi_|><7?UG$"t{fWhI.U%"Ժ!u[J CxTzsWt > ٳ\YYgeet#)5\dxG%&g髲O݃vߘr2jƽ/@5PD]TRV'٠0I gQ.ypߎ>99JCX&BIB#xL+/I(WW+.m۟R` {_SY8U-jHrOQ&.R0 =b}/6n| }$Q,)L10%)fSw{1)n""- 9yu0M{ۑveA*YQbdA U:blMEFW>0' d (ST Rd? ?m%W/:t8ٝ}#\|ۑ# \~:6,.z%U͊(ia]?J2yR~ MZΎtKu=iI;\l]ܒ䅜k DX2\_ƈT;B8tRI9#o)c'Wzwrut9;t2<r =QI.X5șp2R-G!~>ʱA dӭd٣l>O ɽ_6竚[O6$.hV:4XȽ%A +0u< Ϩq[zDo? T ̗`ѧF :V)5gUU})O%[vԤmf}]}V9??A}+uuЃ"PRxp2v+}D^+-֖1z릑%]* P~uQRzpfێg:+޽ĈVt| Z*p+;KFm7eX?gwˍL^(ypov>p:xWIO'=gƃӛk7n' *$8%-='>DbjOv|&ژIR¦H9`Sxa "C;噧d~y:|; ѿzmQݹxZ䬎#{7`UvJ䱺SNW. iʗ43g",0BwFV^8غwi[ kj^9%b•gOR:pG/:„tE$=DխϬadTċ{|0[9*c?Kc_/\yP~>D@[]8Bccws_M+W$ @K3B}}r[ʇ0[p &% ;I°xLek/TkFR\YdܼQVtY[*AK͇J_EG!J\ DO6)RK[aj"QHϭ~{ylh9Ky {{;qD0!+L̃nwZ1戮t,] M= ΙIwdu~]:mkWq+(t(E{wbQ4έwʼ[4c0 ZԘ,NiqK\+ͳu4  —wWqyJ5#r9 ?S.ȖhA9XiUl!{sVt my!DQf3S7 Xy|o`KbPDK2$''?4U6ekȴ?qfzðf6iЫBZ=V`N|=W2|ѝk!9BrZYU4#$Wa+"w{g5܏ mymq >v v({;9S#W#(0+cbU:}2wQ|Y6g ڊvAmGpmX l0NUoiaioSIOc5>aeMlla[2|j`qވ"vuM_1An{~U(eqe,z Rrtx.3NɎfS |Cy*Yğ5<~CABpe5M;>S>lK"E?M{,m4aI(L|JCGq[>h_HA/˫{THSЭ˧@yT;lu8^DğS!Wjs)Μ my |b_j}/0eQ+kn8xk"6Q,A[mhz2^9M8mE߯xAH:ZaDZ|d`I2y9/Lwƺ\p1 '[@nC(o\VMBdi),ܭWWw;re|<dKl}}cCZ3Niؙ5C82h/#ZĿ]igpbw^1^rԇ,MNW"&z')^#`g_G. SX߼1^9ӭnF%y?EJw~n؊Ut%rӅ}B4YZN]oS ^KȾ0o*3,G`:/FB |8Dg;LgCW DʂNa\[CWl.s{3,I~j]guy GĽ8wU.tɲLå˻˽3z-IwzsCaP*G5[[K{+U#4#/0syK%<,J4ln' nlxWy66 gyV٣\ g $JDS/.V[I[b-{.νɵU9|1.`X'..!z9L{C"18ֽWm;7 Cߦ3 j@"ͷpQ5YwRXϋE>㫙E=(*yFgӊ: +?X) [vl@@^KH7|`*N7jHRGJ`)P&ԜI6+_;Z`0iPO"ep^αez㺨};O !Lwd"*km 7+g Kf%rlvI iibc檌>ۖ_xsRkEؤ3йG} )j{ۮg@14N[f8sWv?D6zk6^*cxZh|s{} vQ=="CZ_ag1}7臏tpߩɋXs4۴haFq"3Vl|3<9M1"sk!Lo`'Mv{^먶)ehh{}d\z;*ؒVv(\؜,MHWXm WV|ŷR꜎3aZ[bG.?7lu.Q^O-۬]Q+m|rDLP Epl9-8~2 UF 6@ztx!,іO<^tJ:O',͇ =Cѽ lM|RY,p-'u +hN *zw]ԱpǮzew؁XC4N3G /gs=Fe&LVHC<p:1n'`fRh&JݛMͻ;PL&2-2#3<+eǗ"7yEYvB_ ̜I2>k$Խ^> ;{Gc\t/kkƊ>ofysɲ`PsQ0.y8}l"^d,8/3J> XBv83BfD͓גj세vufګg4!Wq6Nqz~X׋'B^y:Wȿ'1ߦ49K/ayv@*2u&<5l+O3ݰQ솓wMf o̷w-.$Sy[fS;a;ѥüRtaL/F)f=GLp`})]?$ ľJ)04NgqM¹ =Y0KC `˔Uמfmu1X$ e.oavXWQ=/BTN o>?_\U^21֠f_Ka%K[ĚFO0s}hװX|LZ>1ӽ ߘNf!${^-Z--5uX{E Mo?ԇ'ZЄv2֝_&GWDS|W.2iVUņK7Z 7;ZXtj\ qx!X|XUh=ww"(5#v,y/ⓢm9,sn;UX`lv^wGS)CVlpd[&6.ќٿ6_<3X 5x=Γ9%⥓XUWȲ;v@$)ַh?m;ΎɅGpT@+Swt(4ZlyNؔAcC5/>ur~S&1 @R:B'"cC>MA鮩)dΜ'^mZFʌlBy{tOPdvk? $L@\R8"JzY0m=t]hET"A*$_OռG@ar'%9@"jެ9,K6> dhj1~ έ 7e;_nNuGÏJ9$/Fa])}~/ 3\LT%0)JWZ-N]o.[i|mZ -Tnԋ6X*/],`L:SH:ȘVsQV mE1򬏊丿w̞u8Z S1tUJF0Uj(@)բvpQk(#eD'S׶cqr]Z7Jjlco+1k8W/ 3}KFWҸR~ l,ѶV&^Fkw@c4l*- :~E'햁A앬L{vw cr:GDjU:Y@zE=c цG{9YMcc (߾ʴ>Fjz^|Yv>aZoGҰ1}9iW3],0?{# N%MZ3q㔐iUlGE?)lzH]lش;U2̔23նfÈY##M;QW+QB|ѐF.C\('2?Pѐ __1A(X~x.EwXyRWۿV)͜{<-._W;5N:oeV`,lf}^̔/5ƜAPp#6Y0["~.U+FgocE-f\qYuζG^?='k Ng{C [^M! dOÓɆoӹ`lFN'ʷЂ#Q 8f?} ׮V98`u_ MW~#ΗAEIќJsr-d@8tzq"v.}>Lt>RsbOXfnwٞfu &[j8SK!w m }Ԉ[PH!lP-`9VD%}o)K$oUMCn:4;UJ07RڶM@̥>,4"@؃^vfCI~@6M`r`֙Է}fiw&(< eǃj$+CR?o  vw"ix /IwN%,nx1J:@ˉRZt_D9'8=w#'·Ȍ6ӊf0hwaqYY |*ѝ0As,ݜ)+a>CF*RN`?U (؏QFΪd-q&f?үF+"Ħݥ"9C=dže|Г[{'/.\;fqC~M4F/qʡjEy3;A]C?@eԎ-Ak>S oǥ;xQ(-cI b8ɂV'͡NIŶ3=L#_7нD; `ݙka[hLx0teyL[?yK'G/u*_\b $񄽁 GݶtO6"+#=VI2c4e(g嵣K{D_ d#WsGf_r *<j73OѴ `^-9O5 3n } j"@k;}Dmq2>&qlh {rx k% Z,9M:"'z<{|RO>]EܥGhQ3ԣ/m٥~PU6;v8S!zEQX uJ *='ؿ\ xv+^{M|Ms Ԯ9u8l!t`d%H)Q/W)g?cV]( s,4URwK5pRx{_&t}j/Z؁*7U1y'+5"yPCkh;!,|S$AuE>;!#N"1y}ҷ-kzsWʙ3 O[ʡL-)mbo;^Y 3r=1/럹VD_,LN$=μT)┧eZdDhm\,ܼPǨ`,-0!B\wWUhl8zG:"Mj2϶}͢!avϥbzUa J{f!7J-gxeGɣB/ˁ_ ^ˬ@-4܌d۸PclWw=ׁƾ0%2,:tzd۽7:.]kqpCbCM亱zBœB.\igTLJ|g2^SxM|&> Ѡ7yu.;~2ĭ jDr{oa[ ܗo)qa|hUGFQ:EGD h [f1O' >jrx /-D ¦=XЌc (ƺ^jmuEs#;RXMreF4,>΋,KՇz$RĪ(뇵=b~9 z4ÿQltS٤ޕ7||m^My4'?K5QBY|Gq",._ W`~&ID_JZ4`,) vyv-|ӱ\0 )VzopmOy9 Kubz :0e@b&Ctݚzy<G ScFCn} R̭:ldz:_1 $"w+H$a>n*\` Rfh뤖}u]Kx_'CC7LAecVt&=:Ow#5IɄL2(wJqŢ2jYGR÷$AkKKu'EX>ٞ @BKa|u;;?3Hn6CL=/k9fV+0oh$QFoGZzZ֊0idt|nK\\ 7ւ S4]¼قFMZ+Iyջ-}eUjãWao踥rNv^G x ݿ.m 2t Urd7Zʏo,fVb󷫓-rRW8CZg~,k΢^yHy:V{}BΛ-J2fRƢ+ؠ m!A3>D07i]l!s)H[tFS&(.y-Xu2K+#x[?@` #Ǯφ DQ/Jj}I= KoW}Fk~o,nȸ')e>gne k$IQO3ͨHEVJ؆"ZUXCjO/$4ZNT# s=Kg젒0eBsDɐnwk#ւJ&l@aS=:zdL OKi˜~gMO_<먴jyr&޷Ր6=CzoQw-Pb1;}}C@X.nkr :8 /{=?Q'ҤrEy7> z]Lu']!yzxI|/*ظZ4B{<׈_FaKZi8_j*]ꮃ7ұ$Zz58qp7Ġ͖yWڼQRr~q7=I~hS꒾KNW K+~$ Fx\'bűpͲmJ !bœ_Kq' b hԿW lܫXO"Sn^0& ^J`z̶g!3LŇ:-oi2sqs4p;m ѝ[ޓ6E%:L%J`wrt)^a'dRD>-hRP|')j 'ljꟜ)I6SÉyP4. G=>mX439s~C`=_=wo5S_yhgr'p(lY ڧ"1oX-{qi}iDK@bY`U ^1ޱvq8=Rw95֠|L+ u$ —)۸ {<_Ѧٗ}-u9* ψ=7*CH(|Mo}@ߡ24ZX^Zq[~W=i.JӮfYV{hBIeMJIEϟilIwrHE]s+p6]+ |nװ|G۝͍,D}~6R{hO?] FɎM@{w*\ezNS7`{O2d_m3;x3?Z> \+ի+zI3t}`rD2ᚢOP9VLfr>+OfvGzOFkS^/.cL.][( ܢy#|өVb f2x=Y@8FeT8xD_A`QywBа2ό4-W _)N{I&er_:T EMw=ۭ:IoB=l;ч mʹCE蠿t긘wE͍z>>ۻ0>a4XQ)x[IT[Oaս.m߫zT $JUn#9*CŠ lUl3m٠ci8.ݝD7ah|Mѣf;ٛXXL PBl S^dt8leBR[dbshE HMOyAMlFyog%x='|soi [iL7~ RUg"x`>W)V>eL}mFy6[Q˕O,/UioPukXIܷ:oW 'Hɠ-EE[Zpْ[>6HԽvΦ↺l6Z9!\Id2;ꋂ\ܚ^;3 ' 3N9uݞ,jS爉ψ\Sx3qY]>`Se[qlc7I^:dA,8CbSpXNOZ ktSl&S:{&JDIM4qzYzs3[+qbs"8*QW#wr *`+tCj gEC؅52yl\g4/4*:SU{K֨!̏x﵂ZJ.=Z2i!rTcX[ϝys+-ѯ!'32^c}NLN VoU (](PTbd8EiN sEn% ǗhºjN&K8w FS,*^0fSA_ ?Xo[Ygg*W;H)sMo)`ل^j-(= */RŝZlfO͹W?!136yA7@0\=,MB]-0.Ώ X'FIr+-h%)]rʏRj P>,m[0PCX2(.}Rltxt2r~ܯفPExAR]Hۈچ~޴-L*y]otԧO咏K?Rxy64C,cg dQ@c89a)egrlI`x?$!' C:R̒seV ]x?-g^l`âNֽ؅QGRvi]P[|D,܍|NyiKӔAu?N0 *|u>i ZkwÖQ*.9 d_-o _[%fW_5=I, DAEDޱosڋIJ<ݤl/.pu7Ͳ+q6>7 ˸eg1G`6IRWWNnju(=P*Of6`c_;ke|^˟ֽ\GKS}Aڬ5Ix=Dl:oNRՋsiP04ulȽZACӒ͙WKl.E}ܜz1ٜb k?yK|t}}Q=38e?hbZc诎)YwX(kLJO'rњ p/*^m >{KT$huӞ=)>~o[mfղ8bb8O/5 #L{j.g-7PSxP:rԆQiAnbu9Κ>b^oX@"s`T.1V樿5; b>; q5>w=P&~{WEwJJ~qMpjN"*lrMc[V>dnG;PEw~oގ%JYǍL[n/.vܼ@3?&,pVqTXNqu[΁k?m/+O[+ZCJsrVo_D)2~-*Y3A9LTڬlOmdF{18ٻoqrX^xhuK\S>NRϲ+U,t7$N qX'}JUv; ;r87mJNDL!ߧ~~{?wiؖpQw0̚s%6={nc?t+O/E{g12NG+ 8=];>ڕr S߮S6:GYW ۙ5*t"L'!we]Znxl^-EK1iJQ'Cӫs>>Sw82zdu'os>U"eE#Rݶ0BƃJ%@x1+`1UI0" *n}C5 T#'iz-"gs"ci~m_?6ȳ\r#{ _\F ڹ(9 ]T'ton[sDR[]GT;8ҹLޟ?'`R%JUQ:f wu#|zM(nGXʎV5sHtoǨnZy8 14ؖ;_ueӿ̶0O2QCr˭5LvJQ8oҳ•p?Xؿ@:im yp$U;-#&欝r@)MfJ%2=Tom O{DQcm뻣ЀAXH0IIIKe=.d勤osB_k6*973=2^G.YKdQm^OjVRy=W'Gv1 <6p|*Ig? i=tŀ}]%WqUPFr@ZvVryQ1P9 j9VGq>\^C"$cy $cpKW/2x PGÜ`ۯ5޸ $%o8lGB˲Yt.op'Wb8g8tUreE(C-\$AϠe.LblyjrUKg;B8j [Go-?ootN;\x؝k嶺J\ͨ)졭壘&jDHς`.ۖӴ:5IoV^$_oCB ܿQZg)xʼg5/l^uP,i'^idk/ k8k½{}H.ߐkOZ  F2̎{'}yF 2dɦ7g}6Ee"\xo9hŦ+!*(vAmd{YRI\ͼS\So2 wu8(J=]8XkT3 #JH~2{lʾbI0fEܻtglq?G@ke&X0Uqhw͵ǪPOȰ7e7lX-zqՙ,-`"= rU fAuLDz.S5v4C2£i q(kC62tcޥY=o߃TdU{Y`1q/JKV "|6Oo̰JӒZƗrUS=NiQ龿O|" %Hzl\/ju#zyKRbZ=.jd޼COM_<caAsyKS)?h>G_G9"+R9ae):[`^HS M~?,ubj 7:TB ѦLo S;)k 7wbz JG[ ? '&ݬ$>?v8+t)9#}@5N>|ٯ*d0aQSkc(_Z +"7Z'3i:2Y:K)S 3/Ʌ?DžW]ibʾ5):opa͂fG~!ߛf7pa>dG~SSܴ%A6Zkk0m@šcV7P)o4)H:`0Wx^;7c'DfQߧZ1T;Ȳ~7E&ns̵|s2PMUUPwf8T\FQW=֗vD,MVLӦSqg[ wʬ *{{+ |.2f|mYLͩ(zQ=!B1()UvZFwlF\W `yҴ gw^+dπ="ծb'; q.l onb d,Q}G`Yp@S0E6'HCk_,iI3xllbs/=0;^Vӧ"!*\+&crjW&/]ioa75Vݛ9󴦪Q%࡚eStfW  ueT0>p~rXp2 7 ڒٝimm9E)eUkpY9agY/ 2^F*6ʲ5!'nlP͍Hd`kVKh8hyq;TMcsZMNg .sg!vTݴ+R#~G'_Iޡĸ!qG1Ѥ583E$J>lF¬gn:b㈛&rT`C#s({~v6ĵaZzI,!3˨ؔ1M4+ vnL7r*itxo3s}^P4 Q 6jE% ^^ܵ!-}*A,u .oPu>]#\ͨOc쩝Ȗ8,ݳ}ڝOj9`ԝ28u7)9,jPPch-JsW],wXT['ypѯUa_&Yuo";"Әsx|ɘ@]N3r"Y\,[Z37|Ldt]@Tx–~N,yֆȲ`v/r=g>9(2M(zٓ2y=]ﵙiʹ7bJ^pK_wcl:0֊4_E&4h:"9+H#bpɆhAx9R AKEYӽa(l}OȀ/5j`FWqYz>U'dW܇"^>IatU{>BS{3O Li1ƬbV̹J.&tT.iv#4JZ -[r$m^YlNb:)l0~$vM[%ANke:H} |'/t-$vLb:fJ4GϰdK9.Cw8kKI%}U$GMA pCwƬ(v> p4.q&)$#'pd𹓊i4% *!ɬ?(7J>ř4n8S!B!5ZΗqdZJ]JX,7`~*F*޷Tb9N\x07 l94ǝb>EYhN#{F7?2_I(Ηmz/$S2i0$Z| ']_8a3_eE+SZ\L,*$W5[6*hNq|rV{Rs~:q}[T|PĒ3lyTldeXP@carVäYqVo>eL.Do]H凅d6)<릻uQR|1pKs7~'4FEy*&,;^U)AϼOQlT/$]w  s3yx ji|oCkO3E-`qFr1VߤcW$.񎖋;1cAr/t(Th.)Sm/'eKrVсϒ uSw&bhl@Ū wY8c iS/}M|aZz~C.H)pe:up?ZL{ MtNש>>>rOE߾Cm2_~$MMk:(+?] '{+boeF9;p9)Ͳa~3b6WSzhk܊MW1$_p,Mں~?R/tQgtѵtvD NaE ~껋Oq;ց4r60h ލ Ufs=0Ԙ?d/5Ё, Pn* 6c^^E/ItLt˅һ.[3*yL9<=bgR= o{c\e8<1HX@؅<M~$ Vf@Lj .J:GAvZz7Z=p_7}?m ,mHn֨8FM9/-$߾Vj߂^DCưQtc)x`t6^96u?K*n S_&?`]f6ѽ0 *WJfnԽNsfY)}9Z3[q MbGQXߥXa%V?&Ϟn8BbUسD\F}?:- ˿`4ڀԓ9]T ?_֌Om,G;6;G ϗ"=y R7*- A@" cVa35K~N)VQTP%6L3?'Y3)5X4` dʍea2Qn_VD[US] M?ſmIԞ]͟ 穡(zJjRA8˭Uvog/ 3єVO@P!~=PD)q6f!,ONM:X^6:9ᚸD1^V?K,gyk4%r% "gs3-ʑ@F'ԘYg1r0:\FMRW+!`禩bQ[NEPw:>1L*eႳHUc'2mf6)~ n(+ Eb|_tLYt%8`0Һ8J|EVpɚːDomBl]:Dt=-?] ڹ)!Qðh~TSͷ>5eUr-J}MF\ V^.%UʣM=5 GՁ'm] _MO7?bU6>~G1sq/sٸ˂zYY i|g'$9:O"?חKHb!KY-4˜YىՆ?;;!~@8 iiL S),9ԧ 2wۋP< p=o:+JVF_:TR\jÞN&s7%Eb>},z / bӡ5+dI>u=ro*Vr,~@cYyZK-ϑofԸTB j a#A'׃Ekp|6@(LOgm_m{Il@ջش8!uaUTθޓ :GekjbwD3k/Fǐ8S1Rx%*nWhlU3tv=3"'k#y#F "~ޭ$WVD/|sj8{b}zٖ,Ȟ`j4?H/X]6oA(k4=ZWϓB)$*KFx_@m [҂c7޳὾u/|UaɪTKc{R^|MaRKI nþ1̄מx?P1V"G0~ [0 iP߿9oPžqJ0*w pb~)Qmz %3!awWMp8VsecS.B:ܢجM̬u˞'{w7{RSZV"?ߑQܔ&u53L/2C󃲍}Vu5q %+,]sOa|j.G}*V0Clg7:%kd#4[KDf&p[<̖Ƨ;xӿﺎMVb27_dSM7dҌGFÀ?gT[5nم!WJ{*rF͓+sjրN‹v %w&$Cɟ/d.~=\7VL<*Vu\ݬ;N`mWCu18>ӆ8a/j9w:LWZW.`q leF=ϿIRDi(r\  f47Y#ZE) *r3ㅚ5cI_$j7< ;=ahM0cji7%2|=^tW`R>fkPhcV9&vfQ2Y~\@C&K,c~y-<el9FDf}r?\>-J7lV;̲S}[d񖠜(ZA`jq W3 K;e):Ξqa_ H%M4R3;V5C'* Q)e?/<[ /Y8.J D7$nԛ^w܈}rV6`xt/SC!}8\(=@ R^9m;چ_|@zorj=Kbn_5{rThdki8qc935yԷh˲f5OJ~[TgUWأEBvAx"ؿ{"r8]I#e.ฆqf Wi{F(494z1ZuH6N- 4{DH&qWģo{KQ#c'S UBڦP0v!0@Uo,U2g,`R%L,]us:ugJWFP1' ӮC8 (mv5[O1)G$&k@Mr$wll B, PQ@ٰGCawY~Qr"W0aYǖ-'˵K'Nyʓ4fe]T4r>i95B~I{+l$Snt_t0M^ > sH6 墔Lc3f[ߕduZBE`ĭ,6nیNqGImle,0h~Rq5U~`ǽ]h) ݼ\׻g6@fRYlˢ ν` 2G? ^ ^oLrb$j&f"&CP|zc[!EqE>C]]r= q$LЩ"t{Ek|(O称ft|se|1H'Ǹ4cWg@}JJWghJ1BJ%wE`)#iu#GVrعƎ\[&WCm/O#w.ۮ"R_e{8NuD v@,*S';w󃏘~Y 186OO^uũ- pja"z7TƬT(d?0RkI-֨M^gEqg!>c\(>s_wV34IL[vIAOdb rپp&"FqRW*Վ> DkޫjorJ]Ji&7[y7J3+|㵎>M/*G FKK@eK@߃i]c\u"a?a!02PK׺O2a`0[6]D?lٓhW]J$'cHswKb ϭ~dpb:)յSf Y3>lYO=u>=,桷4c3.6b۫f@oF@aHU{F7Tޭc55U s&JŗD),rw$:TTvf1n?@~''*؟BD9k^ܢKx?͓+ܳKeN5Am>.GwpEӖTC/_xUV?+9;=dVXGO_aByԣBg8ѲgVJ|S yZmVm gQp8|?= Uh6.kD{5\&])gSPq2EnʮѢ)K*5& ɭKN: ơ0{LRt,15 aK;[ BƢo =IxĥK%" 2xmZ| ]'1=lqk;}^nJ[#4 ]3Uyd,(Mv~kmf;9 r&?su ]0DYJ.84M : Y3X|Y?Wmr,=[Usi̤ n)I%~lW~nSp3t;o8Wu$htfȭk;npS:iԿ>(9oP*vIGE-#[lkm Ր_JIem9i/4wѡ(Y?Ve! 7?C-G~\ s7e[fW+5lx綂LCt_z¿4{ +gl~qnVLImwMz>ٷeԆaVvIoh)SjKRӕӠY<ߋlEp߄g=]+dYU_ }Im% }P@f#^:K*TL|.Z@18hjFq):KFakU %O_3?Pr Bʶ &]|o#S0pk!yv iQS"լ2-p*JHpѱGe ge a,3!R~Ng Yپ0{ ׏@ao!,sx?ۆ'j^5[hVZ^C.Eyu "'Rm42P(xk>Tz]]r2?VܬqS,*Gi$>d lN5t5\Fd1lgܕ'ǼܨLXHd7zLҒĥ'K&i ٩ƞ P@0E)׉Lr)̸v֖"@v f)!S  dJvKM<}dHHJ\90\ncܣ`ն8ǔZR8 WC&:o"y(2D=)ȗtCT_JvY674gh:4X1MGeܛs~Ikyzd42;Ce=V#%+ 3Uh=3vS̭g \MsEQl}<?GtG[PD]I:aҋlɡԨ2`4ɽ:^ Qv a6DbPT;e|_Wc  'G@k~Ψ7ڎXDCB2kDDYKl_5+!tgo~쒌Ǵ0rj,b>q鄥Ms3jQDzd=@&,VFىlٹs0rٟ )~&KoqfGS93-|΍qw.#%4Ƈ u?PS 5MΣӂZ6OD:];Sٰ0so59iA^ĀJ^*yH?7ָ^Z, nǨ=9]d>L",7i%ĸ)DhʉGa ڱ.|ƌbxKeE׍U6Rx(=m6"15Փ#6ꕃ-Vq]J ҷEQ6yY75)8H ۾j*eGH˙sz8@M,8o,>y.ε_:{s`>CXjKW g1'.B]rQk}G*t-g,G#xSE1}m`aN9/6gIKtX8gk;kDs?/jxTqaY!oIQk,Tґ5crimoT?SA%w:!K\I7|> vO6f9iHܔ䩴X&$m|ם0ӞyӺ@̂5X !6d}*+$8G؄.7~5WPyQ.a*|:w> p1'cx$>~C?RvϪz)6KX XY8Ɵ#*Wrقm;bY9%nLMKi' ڣQܖٻbXl1}5FMG:q. T%x='.0xC;ݵ;k IZ }?iwdpuye3V Y1 О'>#UZeDyB}n;H)Oׇ1q]*p7wUDg2꒘%\b 7Xhz-F)?eISu+/1 4].v=w$hp'VW= 89zVho-:Y !G5FJ7Y -4%|=(VU-?_Ղήri`y_D9S:4>F%5'pm_+pq "/[>(Akz\javxβ[H2'x%Қ։X}aNm(=15cht݆>Z 4ȃXl:][O[_O:$֝8A{ V Hrv?iBN%b1C%SbA VӍZcR=$E;U.\{^љʷ8~? ~~ NJk+擢TG.UJ<(/D4p mS9`F-7k/pA<݌طǒ++P>9Ὸh!q3Y1ˢ!+]i:.^a]v6;nP[0nj&hyu,\ǓXCnWb}EmEKM~mLZejDǣ/WŽ٩mc8p* mk25c&`ln}?}36U_߂k:͵,hJs0y-ʒvOOr\i8]'memy.? "ZOIz =GuHUW\c ]gb3ϪF?%]/q%vJ I\)}lPuFS7cM\yGφluAjmO˳c#Y9W_̓:cE=O[YnkgXwOX :E6m#")* D5֟:5؂"e.bwuw6RN?i;"kf;\ MAJYIaPíd=Q86:Vy&%zWwt}&ޛjzQ%~fN˫=a5jgJ攕e33XJ Zx8/@)&6բZ*B&\rW|);Ћs]%˯eA|ԩ%LNQ>ClهjŌø΅ߩY,.C}P>.f'7P `,y2WdY'Bxg -,Y ic߲cux3@B7#29+{wǻ+͋ )rY0nt'U!~нnjOj FM1a`a6ڽzU"h[qeU= UGSXٖ֤HcN7Ϫy[nxKۥF@{TnZ&~<;ʑSta.WhqEdջ E[g91uѯ#+4V:ٕťMbcw=qAƑXP5$< ]?bS$Ά.0=v'%^ygf-?Hʚ0q7Є-1ɏNJqN0{HkRT?0YNv_dg;j L__-(EV/oß9O16t4.DXRHnOKno&{U2y_I|Z-2=o-&Yv)Z}8WSotӓz`J2ܭ% u uhQ66ֵ"8!Q^'[-+x;ńуc^q<~zKLr%c}ҳCLKV#0h)5JK7٨k^!S(&XeRg&y:l}j.Δ @ 3TGVֻY\^*Db}mWU9vg5=|cHMVLZsNZ_!GHtfv5 f!=3<9iutMv9OG^O`6VE;f1m|X *,nz.(K\?s'@EtݛOpW_6YRQ$NUR;c.{-c^aHsx>f} or3aiqeuAb m׫ ))?Hb04qCA-3@. .R8}iy)I`Q^e=N''%OoK2*fF+Χ"-X|fE4-ԇqʴݜ.Q׸7]TO9Zy2yB'rS$^b,yp_0׶}|(?VۜL [Rh-4(7VLo{Z9eh'sPB>ە5ꔿ"q`tRP{%br>ιh>gJh6bGoB6O\%};| (ؓX ǧ~-czx '<ZRr8CIa+ȭ WӬZoFsVݏٿ wM-x`QQ0>Y@#/6hVuIsO3i/`G+%gz=_Ngvc BfGԗn i߶գ7 }^S OgZ2ާ ޞUw>h>ۿ*˅ie^ OL)Y)'ix^I~ io4܄uM%oM>}W2ѽg!WWͬ˯ZrS>iN!0=o4=QT ej9> P&rzP7+ЈΔ׽r?o5k-q CJ epˏbû~vc̷_*sD8r32~c>W+T6LOk@{KJOD+gފŦ|+QHM;!SZ7wsZeS0䥨к%uMCpK$m> x,;=mH:DTS\s1t"=Hp}*[ %;ViUJefyVӟ#>|?#XQjNt}^foVcL@p66Bn=snaNϕ1;nȩ1,,"c<%ckX ͉zc>ZTS~= 4[t7^&}"pp1FT1%L\%gNg?eF<ٌOB;eܘ5rfG܇wh5*j & #JIa(:$;\ހ0ppt.v@=,q,:?jO t۱SsL9+Yy''5˽Nsk+w6weuK){f?X9 6gX;Nk6⒨boٽ΢0gK/qRU5k&db<#qU.<`蛧;i!аP˶W}: ibʽ?>5m+ǫ_~I1m!;6kL&%UCOƓmlʲ#WI^udUl7cYk[gȨ__hoEҙf%t. ƆQl{: (^q3br^"bxY2CˁL,NS?-fl=qS<Ϸ19򐹷PT+~y.nQBjɛs5Ni_`3e_{w:hkr kRtp =Ro̳ѿ|nz3FR>3# aMdQט)ij2sW`rsv ?i}CVT]9G wڻsLveH<si}}tYd43du\(^7{BOg&[?/f~.r)]Q0eE,>c~w5%9^C:葌 dXUkm_A@Jh tO51-p#i:tOمBQ|ھ_B;ѡ.}aT, x}Ňn* s_R dBM)=by p~|Xcv6k[,Y^gN[zEG׵ipۏu[9|{ ސVi7e~\bXz4(*kwz`TTȟQx\g~Wwh;-0 g_o‘:$#ubJ5!%L_=O]IL dQgX8zeA\26І`WJ2N X3{n>l6?zS/uߙATU-5UJ|z-Nh~ʯ鹄r5ú lvǃf+bACu1a+b*0AS0xF;l;mÝ|L >WISmE%2k!LJbz4sϏ~]\Cʼnp;GZ}*j'o<챈Ǯ|*Ջ2N {u6Y-Q%v 8կϿ NS*"tZƓ#ZsĤf{xp"ca1dzsC^qWE2`dʜE=^mzjEt(AGdy 2T;bZp ZIs$>~SM` 7>o+C+Pk~&B@$w>؈IH)brvZtnu`z?s6*<*yoTe^Et1)|t $Ro9lzS/RWRw3SܺGFF߬߱<.t% ,ܤ㷉ǹ%7be;d[d*-;Wݣ̩D]z>Nm(K2Y>3"6u| #Y c\+nf/GCyϠhzu*6H<"ІӿPIב ws1qw,ԪugdJr}l'ʪq0 T[j̎NX'i_Ee6F== eF +gn` P[p1~u'[([6wk6gm=^=f4r mܐp*b/3w-\lwXOl_ѕզϚ`e@jp1W Ete ?aكf*[%7ȒB'#^LG iv,{b+Y|E{3*Uu~ єr>MJkB!\o5ݎ r' fQ3WP2Hf/%X` S;X?aH8⾝x5>Ej: \gi"; zy13;]3mMrq}9ãh/QujcFnJ4PH.biġ.H/oON/IQE8,^Ti{Xn^7 xiWR42"Wɲ ??yڕ*uй- l xU^~&lj@ 0n0~huyxNlZZUT *zldw:Q7 U'd K?nwvq6M&KR r,-pR+RU"C# O!mN]*G:L3"\ď$o|)0%튤=`4KCݣa^ 5ׂ ;?Ɇā "IUm.zͣ&П*`3뼬OJsyXucdC|FCbo:tG{ԋTk4Ǐ2Ѱs{zQ=eMGƓS=PD?3|Vk!}SID'E~ z_ɘE"mZʙ[u,~m9F T^Sc#0K*ϥ";O`N{YeU;"7 $X_m.* =9rCxY.;G.gyb5h'L[uHm@puAoRƊM<)@&a*|}j4pk15^zUg׻)מxswSu?S(NWiBESm0챆qJ:/']HQhWHwAQ֑; F= [~ gmn]ɕP?Gܦjy]lǫ"$Q a_:g~~]E4^}C1ɸ*Ok[̮I|&UI>| u QvcfaMϴh1hG76ZZ4{b*ս{fT/ ݅]Qv;/UbVTi}yﳼb>o 6u*4Ĵ<ϸȺQ,6Vwx_Bq`'-!3ӏvGRa96%AG*1z`aVZuZ]0#ΞU縍5e*{;D\Y?ҵK@hy sX(+e=/_dLmwoυd bKZk8Ea+Yn߸%^2i|DD*ݨ.dw_~|aj1H_$.@&P8^7:Ͳ&݌Ⱦ_oichdy!u5>$Oy |Qv+a*vPyn{U}*!3\u0yӓ_oN T؝5آI\Z7;Nw*}5KMz&Gd&v,pyR2|:[H|̓ru+z/ Jk_e2|N6Ur__YĦ8R#AL6?2=^p8ta )C53[ )JZ~s[l' B̠x@*~d?訋=b@A"Pu#8nϦl~܅j9ntT8)lh،ʺedOaly9vetߪ| YE'đ RwՓC$e7 yrq:;{> Mvnw.\\hz4W$&\U9?'.P},e3;1y|BL3|z*ZrjC8^[0{87ʼnXl,#JPt61>(qC+/cvǾG~e֭1@p䉨`brj @ ,aG '-x^'2#<6ѾfTK6_E߳hP}=.v: Ji+8/r:QYpUp+A wPKB ap\<;JVE6O<)W]GJc{.-HųeS6V`Ey!ͷ@qQYWH, /4GA}˶=˷U3̣yeS [r#t1n^*ws²f䓅F^zSt7- 'ma5fdat=[M&Zk˹+mT sY3Jire2\ʱ]\Q8ľGXLh7-nwkz7G( l왙9ޔlIrNLD;_I=Pg1hF_!ccƉT:tLd&!%I@>2;o.$PZL=P2z~k"8eh,&.:7MJKVck %GE7ul~r@pЁ yRo5'֞9$9%5Gȭq>>m̼T3sIV!хQu%JN+EnCG1omP_mqEr~| 0EA (7^PWNFP= 3UC sY<:]İa\Ec_ۜl p)pl U7^z '%?2֪ЁC/^7\{3`b!oUѼ8VoZu}鑇*2f}Cɵ2ĵe_f:w=b~2y*s]`C)?\/N3% *pr S70A%" 3rN%Lvϋh>ɿ>̓Z`в. 3ʢ),ݏ{ЎL9>)|X}6n`y+uVܽ 0sZ{?ľUI>{0Ɗ";[!eM^fv_Gl}Qܞ׹iݠNR6˶NnmN+# 2F,Aq5_cKvm.6 OoXy2ү7uqϿONuO6Hǜ;zaJ؜0<9z$0 ݨ]9>.ַR# dӍž$)h5Nj;NޙÐA=՚q_ 欿݊5Zxr%>{;74mT-q~kIW]u86P0*܀]la/cd.y!z4=vj,JTM$=TqtY))u06\]I1b] :S~qr֐ PQv5iJW"ЁO|VA{ qRK6U8i h˾j{· J [2Ծs+G= " 0Wg?Dh̿Ɇ TJ) ZQY,g? *EۊD篞CmWiSBPiLa[ph i`aDko9oU yVL)YhIV~\Vd{cX.9zGHioo3FXλ b:'Ne>W9D`_RB摥\x(d}e kc .jPB!$L ?cg/Ӻp0dC [8!::8DͰ| b/U?pꐽ‡j`P]Cf}m,G?1ҟMC@bTy }$P a/ %˰DlMcD#LZ1%w$a $MOl1%4 S37.ޝ;B%4-j} $rT~ g^moʗ̋#E-G񗈓?g.艪 ]Pa&c/V٫8:j_xUڶA Fǵ<6f¯5oabk9!h(} /;Op:z>e,69JX %qO"cwqX9S. EA5:KAVvlܼnq@~^F?7&T_uc*Pzb+&M,Ps`Zzx)a~ʟ9.Ps֥Ⱦ,z_quTi}2Z MUylPYתRlt>EmJ> b\I7#5O : ;TH:|.؂}_zCA;Z f&1],lDy)V7>EyJK|S/O 5M=p@q ozFY*>Tl5Ժu{f-&Q-7%5LoѵY5o {G񨓝p&AѬ<)tqx-Z;e0\%_Zz<ԏ4s2d{Gbbxm#BXw v6*˔GY0p9j\wtnV,W^2jvDuwKMH#{Wheh= +xJvbKime{Udy)V3?$AI>aӣ띙yx EŮ=ubLLr8A˨N<{Ewk:IO[PfQ^`%v 4yVYSD!9T9"ۭ.a 6b.o/,%Ϻ$7 (i4TDR|iAg7˓Vyg~scIz?񵣪6c^~V|AA1#'G+ΔG@;YxlRq<:|s ;R]c!4X՛Th:ْ2[yB/~dh5<6~Q|*6qO/8(CW8j'ޯlŵai|%&Sz3og|9Ôw' vl 0d֯+a΃d}G=5C'D!~A|3EJDʘi~o]@Y2(ptЀH#gǼ8'>u>cw[r/]3r.clChTn#qip߼?D_  7FfYCjrF~I˟REcW$drJ_[#r#ޝwRm܅祇a`Ө6O ޿iu0p byB{oQmu{|`Fn=Tll1:=-YnTc!)n oHm4䵒u-R154^hsӗiJY]_{" ,{Uq/he_kFaUT"#vff%Lfz-Of09R1|yJ@03sK,$<(2]cbҿoq% f`)Ѭ' J"x6oO<6Gz)3|}q8]_7;R| R8a@ DZ#3ךaˉ ݢ_X^-Fl^ ){ [/jy 1#sHKJxh@y4rL}*cP %%|хm܁Rv[Z" ~=nQ)e>j"`p%(CԱm屑݈LQwN/7%m;)`|!u>"ͫ%CؿG3އ;X0׼u\6c=hWg8xG7- Ů{KF|U/%Z^6s[rBCдtYiJ7t˛'*31-.n :׭jX.dqB84li{0wE;b;qD+DZvlu!>{™5Wg8>myߜ_jctF,?@K6e%M%Qy/= F }Y3ki饸WܧɺrM\[k~\  vc ގ;UVkWbue D, Bfl 8x$&D^~ . 6, -YaDN> 0t/]6st:?t 4~gGE$.1o X)~fǕKZ]ͼ)x[9v4ƙ^6g2`i{B3ZcȚD@cJVܬ,[v˗DZ,C`qɘ!9p.P|bUۧs}(?N\nՂ;XD(̟Ӕl.eN+Y^kNiQDʿ$Ĺ⃱z,83{XF]!޸Tmi/|:;Dc6`wZR(wl*F䚁ƃkd@`T`жPRK 9ݸ=P 32<xfbBȖG8\m{3#)V/`,|m{9M;^}7nϤe}i;FLݴ!$0uh6aZٿCNhf$,'0ORpKv:^sO4Ҵ/C7VuK-i@?!3m6 dw2 ?nb|P_+4D󱚹mes Ìt F8V lHIP?8I؁lhQ/))G>Ze%2jà;۹2| {< l`9 zAx^ 1U3YeLVkA!ZcWmMBD-anY -baڀ7vdMF\Z= `o\`mFxW( ';a/q}Q.)=.4CnYƶr f# z43EK, !Ÿ4ZP/_J.3`KaQ3 Ðˠ`7P\?zKfi+hR_SQcP̿ a&1v[e4V! j>+3; -]hqyy:&`lc2iۉ n !5w ̊Ȋh娘l,YqsĄ\0el\t]Sa(qd/ dc-T{\Â?ۢE-Ձ8M;Q)yV(*w@& 5^z#:cG9D9ӂ|0,e¦&"a zJ[5\mُfzd0+I_X |qȣcs@wRvna2CpјlxzQV]\ 2@L.)%!aqOg#`kh#0 bH{S® Q(a3:~8hm؆hq/[$s|E9c]#%c5\ePh4:Y|y;~[hMzcg2mzJ2|F]xWT i8gexJ^;G#[ UJK7i_@M<7Waҹf11@ U$7I|tgT Ȯp yns hB_]Q3vp1x"Z@ ?I|tV6&Pr٬%r2fCJ.V<r{C v$~A:3\V=PȻsCc$)mv(VR+qpDbZ/xL>1X, ,C24l@] \M {AyɜK/RsP7Mո ٟ(B9t#R$<'cA3,): nwy%9[CbԖ2dLŠK孰 lQXi걇싮d9hnY[>}<_Ucm~R:zqJ/_t@2-WSb1r~Wy1K%xo#w.(dEӠ 17NRDu'\ U<[O3r d:sP? bn^RSU?M/e9y.l8`ӌ۾BN Ce=ȫnR^o)J67&=Ωqm>tr6AH1̼\BZhQsx*tee+;*U~ed8%ʴ՟g/N< *}'|D۳cdզvh$":ydΠ#)I.jF8`^Fige%_t#x7*yEj|AZ~BY@w8_:O\[!H?ڑZ 3'Rҩ;?ɮgis4VGsE=/Ϋ(nO&PӣPűÝ`9+$B׏*YQ8&y!ߠc, ݄iS[T>LbsJRd)eݘ qTz0\]Ҭz9k3gW ;)K-F _zKf]GѮ!b?hI?M7`VҸ^-ߟKfFdy~77orrs>M$(i%:3oNL“M5CoDzu%ZxΖ]\ ؆jKV}XgU_:Λ-cs2i:dYǦ0ZS9\Aq}%tw@zbf^_qDjL@O!k  n7# 頔5?+6&w]|v.P'Q83:?P`ma֠JoKvL_:4SZJlZ;z%ȄH j2 ֩E]|ML A+ /{ 8S9_[1nE370[ oq]Dx>3G)cɘwر뽴7g\k wbC +`h0cr"WxC`WGLPҋ hTИ+s=>q,(A y|6oL\ UGf\K`SsGFRQ^yD,&Z2~pn@kW~32)Fvl"V~St-g*uzx!e3/oKF*D$ *\i|y}WnkoGrqfx)'[=k(|[3EϔA1$ʗAjJ]rHh? |CeEe>VN%}kώ~rTle#ڤ=E&=jxpeiSͶ`e"~2lޱ.M%%_Y9ӷZ0ޅ<4[u@鹨}z׊6Ƽ&ZN;l߆<>S(#Lx jlg-dСlO=Nbq]<ozW} ^`e,@c;?s#n~NA|uۇ̓2@QQ ]mA͗l&)u'_eT_@|.3쯆=\B}}J.ʴF%9iQΊuYS/hFk/[0uNi"|?9 K31C0?ӊ_[IN߄:\x*oT+YLvwXrmzkrty~/=nXX3bu:7=t^_"ƥ΍*8FDVLLMKvNLv8& (=2 ƮHϞ2^tu-`7[//Y 5c,V--,h;ﶎM]WyG\e[tK$ ٚ oM5VAxQ??lThd25SF^’Ƿ萝Y ;1 qвA.p?"s bLR{2F) pzbGDcؐzX zO^SNa g3/X<&52 ▋lƻZ's'L,Yvb9>Ƙ e(]=΂a\cMtg.N >5 ~mrgW%mm2/t!`z:3Uªkv|׿ݑ-t.-|) 8ϐeVeS &7KM*1| os ݩnY LP2g?76)󸽎}s[0@l$#&˹!Z1 ڣe2kQ yqu/ڦRk- ɞ}^3;@י>~Qu8/)xkm,?VQtDJ>9 ,gtp.תԬ\P"g&P`םd)<,F5oc˻T ;;G4ٶ"z)iFRy@|eYVz|XyW}F}Dz*ak _6=s H:oFmGfYV;PjW|žr^ۂ;^}9y)3ͧ S q̢6F;[aU+rLV%GoFX.!zp:GFHՓ8}G^F4¡*Qw⅟n]'+3CâEFX4yT@WTR^\6r4%$B̹fDSMtjjq(BĕQ>:[-秉 t{5A/?֤Za< PȽ2~ǡPPK8! XwQ:8(Se DiVb ͍^ `{y\1C}"[Uس/L7$S߶EX|K q1+1A<XVB9pSәR'GfOfL vOb9 C #i\ɉ.:d C}cJņL煃w2wHpkRsG-JV7qM\TvBU~ܒӏ+ >4͟X!nu}%OoJtih(Gs =QOt̟&WwadsHk Cr+N:K9*-/fKrar_.ֱyBFʷ5Đp |񞂖/OWǜWSː+ڸ+M'6x.N5Jv#0NBHY}}r=eMОǨx)+/`?&Y,^i)EpQSO&;9N{8AmuJ,dv ΍ &_Yi[a y-ߧKf5%}7<[S&kFZނTji7zs.JFe2:%M|b;6]^YV0GS\*4NwQ{ʽBV (}x ž<ӗ"iwJ*?^֧kM'RKq(w߿C3{a MN Vc,b?M'}LY8 _foSr9x]0PT˟x ^~]^_G&ßjyuisG –DnArMC%fBsRGe͙F󤷝3cY$wEʆ1ݖǀJ2p|x''T4z8W,Q%sj:Loˍ35!vWu@ U*NkG3ta$<X;.:"7tw'kaDyM,Ei2; =qqXζB'38u'li0fmn~HСgp45~>wilc&{7䧦W1bm]L㋣}xP冧?6JV~0nij,$n@sA)1dVƧgNcC|.Sky}\Gغ{APhMȃV*tg:i#&V7 H|.>q!9cE5 ]ޛĬvs^eRa\HMK@UXsJ['p_jPh"o&aT< q Yj#U8VFBab0Z/%L+:yHLٿU8 J)@aּcqbʭjƬ6^M:u=dMi SV惓gB".U]߷BV,2ٜ7ΕH/IseiAȌ: q\|&€ 1MVXGJ rwf%9.: pB6lR]Z|s~W%3!tFa* b(Am<C cG:>&TmvWݠvoR삃#n:UL =dVvV/*YAy b5aYU =_0*{"MM{TWr49=Ez+{ɫ*N˵ в2ԣ,B~Vg!WD7}*NӉ<< WJMО~:ut|{q,V)oh Kkȣw[WH24qp( ='.p},Үa!{ 5l->2똠O\Lۻ]@sn*]'B9?-iRFnڸ$2D+a,{ʀQ뙮K{GUOs~R.`$ozO'! ط>WqV9ogar(kZ6~o ]#0~}:%O\k]2cm,Coϰ w:q-g#c#q'Zi0!hǗ|_{yNՇC.clOJqmkLYoYxe)b\n`rp}5夬:+R+{7 @#fk.!1*snW9&^͂I }ƨ^)(3trfQm6S n \ ӍFäc]+a:0(b9)2fn j6-fz2XPdryv5|DN UlbU_%2[Q]/=a@%:Ur572BV\^EQO*e%iƌ,PuH>p/ծo<)Fäm  Q"O!2bw sо21})06`Mx2!٢ז_U-L~.npRhoyG<btU;ԯ?nE*׌Ʃv;!&-efe /ŧ 1~jƸ"^Tdq?k[Rmo붭^; 9qP*ʓ*~2n t)ҩۏ'v8=f˶ɇH߸)::d?Ƀ a7ԃ3ӻ.ݸJN~b.x`| L{= 3 Sͅ(XL^U]Tw_=t-:ۯ)S<)?\5mVb5򿟻f~8$44=zN7TʉAU ߃T8ϙ҈$ AfX2BdV^QT;7r']{xwzvdwd@lk|a tך`c͇{P(Ѯ/b9p:2uջFO|IonN̒^J KʐAtm*ySs ٥;ۏ0Sނ[=lT&W}<b&;aULTWFR[J XLG_I>$;U\.{~=D卿-JbGh &Ow$,yU7̰}u$E;?203;ı ߭Evzle^IJĂ l7pn1Bf-T7Dnjuo:bqn mr؛G=t5>\_>t0NPuMU A4$5\u[KՁq>y<;./Egz_L{ObslخuLC/](./ލ|x ^I2Ks*;_g̓/㓙0_8XO[GƆs/3!_J7A#ߑ9¾SA3ѹn>A&[2L[|X6'NwMX}V}6yUa]<& wöQ̈́^'uBiquFS,BxuްTž4Yl [q% 7v0 K%6K-r%R\|Mt w- Ϧ>NlfX޵hwF#[w}hE0K#z!"N H:HKG3jb} aԉir0"P5*`Qa`Ȯ/m=}eI1s.bӠSl[swaG@.X,eA~|nAtWNe?WPp($cV2=`fa;NEhPNTE*e,@nNfmU Ҭ' z xZaj~g>Yܷ% fQ v?9Ppmjk-,]vC+_ONPi“ xЪy؃')F"O.=dG%0)>7~_Y^#z]OYd⍯w*;G!Tid܆HCJNЮ{ֲ_;b} 9 .ԐW}z438UDޛnn>@.ւkViv=n'|w#tvI'PZ)Ly?^,1F<:L^zxs5K!4ݪ5^h)HD A Af76y8ϖg+xvGCLʗk#_+*(:P#6gfs+=?w*c4XSN|)=rW}J+ٽ,?aK@A((vW_LOVNck {6[/}lԘEU <(K2)l&o3|%{]V B{sw6GN R0gC9IgOB$'Ȣ+rʠ0p/80BCLXSUet+Lp$/Y[eo\g7 t}4:G}3GFV}FT h"?p) { '94AjVrJU׋4uaz pd9"]|[u@d֠XOάiQ{ԏAz`L2ӝGunA }F{2[m[3=,n#[.j(wC_6I+7J_1)ZF$RΩWln2/B&θd7P;xvelcs|bY'g £.7‰>[*Jͮ$Q!0S$4@0];bx:{M}AMvhHkKX7 ^p#yo gUۥz,t5:N޽kDDe}7m3ąh35i3i(goHg2z{JxIl+ƉP/~j6;% ^_BNp~Lef@K܎hb{:<[ZOz)Eq8 vEDgvM6#Ä9I/Dr2/(l;X]7X{;[;C)AۖjUGnK_0MJ}f ٨_3W+^< { ,)3kRȋ aH~`Lu>$qfS@UE-]YZhZ4ʮ4jI=w!B<:jSӥ3:{]=NܢZZ[gu }|{ȷ/QTG>kza4Vi1Ўvʗ!pVq-N;k'wL(;i3bIui[6Xz:TTRw`J6@%:AfRX/})8crM $! /q=_=Hߵoe> -pk~ Sa}l:[+BHV(&Hҋ';<Ř#ְS~QuWI3Q"kmLe OB T9=(a YV5!6xk^Ï1Vj5,&% Ϥ d:;^:MYkY3P_#9m0 LlSa.,Oɯcƪ y nJ eG(POs`|&BJOԣD[Rg&1Ns޸k V^׶ccˮ_( 'pfY^mE-t2mSI: +y?s$룈C!]hJp^r}i{^bEW'Ga\+i4tuW2j&oԘ?paYB|QzoB -ưTŦώVC!Sf1[${cAY'|̓OOq"YC'rc9.Bo**7^ݽ0dx `I{Fѥ؇or,Фo#l',ګzt~"ƾ (JbnԔIH~'Źb[F2SN x%#vJ0V|iq,bqj1G&eH;N A~`TI?n d?؁}cbiECCuMN ml(|W4js޻μI%m=< 66B˦SKn\1oNtw|l>in(U=(.ȯ*H:u\`͝A+2Jn< ϩ ?~LCr?JiZG7r[ JDE`cyqRpNݷNJ{MK1E, EoJax!>BŠѧlCb o5n+ ߂z[Խ6ढN>AyO/&{p_ML53]-e4Fvp9mPb;>Q*> 2b%~WZa%l68t\$5:ވFٸXQA4h&v}lds{)yvˁu[CwXjB~Iþ{]ܷG i&ks%{ݪ؛N/Mha{'ʏioHtc5+4<1_un؇_;_uNqjew0|pi3G2-jy'8WB _yݷ^TZϤ0YIaM(! :6Qݳ*鵱)L4s>OlK'س#OF!I7G!,&?YEL]V!M>fݘLLm8a@i882 Μ0<{.1~.q]H (Sܤ[?QzT: `QpmS^醣j?FWM_hǒi,Dx4ǭ.oY%7hڷcv=(?_i^7ql#9D8;Ι-ѷ-B>EtJ =@Z\- Uv# i8w3f 2*É-/KeLa7o Jogcaxpp8̫Xm]]ƄD Y^!cIΠD -mx,"Y\ U);@jGq_> گۏ#=aL!Qv eR 2` 0 !aH%kJQѰڶѕ{2 e`%Եg ٘f[^|f%T.DO@i^-r{Wh?µc-N,y~_ӕ#hj,.L~)IL*ˮWbq'G$|G 2K+ MGdp;mw? 1ܼI(Qջ_#3ekNd5 &0P|'~ָ f:Ho93xL|tvZL܏NqU-58TXE >ɼ.BB|dM̈tF];wЦ5Y(fofZwlU"_7k0`"+ }S+ǤܲTu_r6PȬZޚYh@/5MSb'jq=ҙҬN'Ֆ;#'*e=b|f=~ٮ[^cZ!Iag^> :?U#MB*~$k1i# ;O:Q@9{>24=eHo6$X/zCև Gr)38 \V8oq^A Lr0EYw)D[W*/9Щ=-%'z#OHrItng>EOAԼl= Pjs (E"sS :X?QBPD/ `^ZJ9n}Y*2M 0gp4zֹgNrRdmc'^1yEc/gfG+E (Az}QL@]a r-.U$ !CW9ZIqyXb_]F=\.myO5)VG!V= H+eH$|`q ˼B֚ݹ Zw;1.^V]n> Nsfx\,x77]ȚǟN.wښ/CZ %kJnO<+hhm;:jg5jMR( C &9hf]fWbBg(oaWn?vN~鏷[U|#0ϔNkWRbY+^NZZ7syPo8/|w-Sf34?1i<ȸΗr,3dF~Xi|ŵX]w Aot 4lIm b5ƫ C.;xB3 ~b(t"8&+x8z͗S9$U8$# "MRvI ~3*;~Cns)$q[:8̊pղ0fHTyhTp7#ִ%20k*h=Da8!"CHBE8‰LxOL`0LDpDT Vdz|H~O֜ TRX{F\ {賘݂ [\oSHcPM6%')m.K y,$ŃbKVw'-0XS}7K~8MZcFMeU 7! go^A4+W%)`W"[RAE_@38)T@6f=0{;J3SPIME˹fp+8v<.^"ہzuYKTgMn]*):"~tG>?^(@rs"XT̵JjT\i9[0u~Xw٧/#*s rW2SP&1uoIzae,6';z4mu4F܃٭{.nitӐ?+C/bƉ޻LaǂU<Abzh6*t=qŗl%e>2SjoFr Fq&X4@ξ}2ҭ.]fJpă{(+~Ýrc`;#.3K_gbdSEjhQ`|UgOHEȿТ ~YMq '}Ϳ"p~_/pVc f2류LЙhvqvh9Z!vtB AṂ\sRNײZn\7M?i3qDr)$@,_$6%&gfKAA3߈pݳG>Y}{5N8` i} [oXB-ǚ焺U%>&LG׬^9Z\)Eş: NAnh6lmjZ#/Ov\2䦫:k .q2 p4ܷg¼Hdx5&Y _F|o,Fe7< wpV0uuFi`x'g ӡG0 'q]JܼW2\Xs:0n$0TDY1vqJ{ĥLy 鄩YkHxf.}g`tyZKBo;IZ+J.NhV/U9^7$f\Ϳ;%.1۟did|ťӅJ}[0o%gMȧ;i|LNʮ$簳1֍9BK8@ʀT-quH8&꺠`o/x 8;pH%v=Kc̔qQ,QgK2Z /QKO)SGH.bdBéWD l8NH9=PuщWɖOYqwkG0Do'؊A0/ƛ*fXb򵳙k es< _ ӞhIveocgۨۯs7ۉ;fG"rUa$<8.捳A\I@eR l !78r8Q`I),Ü` ;GE꟟Ɵ+ 0<|nMrQ`4 }ߏ4*]bUQz}#z+ZQA⮺b[A .!ydWKL.< FgaQ5'6c.̣E|kAP,{APPݓYF##?&͍I)Mj c#z%"TnT~A؝o*viަ4e14}.)2:Ȏt`?c j:kzq~/b*K|Q?S9ZaθhY?K&l=}VU""ɵSӀҭ8XLį=P-Cs)/}S D)TRhG;dt9mAA\Q"-DŽ;Ȳr3C`&169d;C"DʭxRsIzo 6WӲA~4#Q`dmF2;FZ<ُ J}q)x^dUBϿX"`ٛV;C$2ӞbP0亄./% &E6%/O0L ނ%I0&Un֎(Zh`!-vd= Dp}3xه]x~`%c^TVԞk/\LClw %c G3O?8GO6jUyR01E*-*ńcDzv􁇤BN m&ÍV9.$ȏ|zE8j76OX׮)&>&0{ [`0v,/".Ԙx ͖^-DeD۠[q%@S0s;F\Ɔ|a$h<٘L//Wz?,BHwۿ5>P/8d;zi_ZhRKw=R+(lmG(:4g: Ҋ?D p:uPjזiG8f sz w-_T NX]&'^q:J?V3Dr6^ jr,CbjvJ뷱7?vM|}H"K1~)x _*1Y&^߲+gYƙ/IO!c#D)"5"jo(Pfs`^ENp-JocilƵfs2ev_{z-FI G |t߉h(Jutfl=?4&Q]ݽf}gd@cӬ$sDjmϨ/V9.vHQh*nirg8e[(=hn/" u,%`o_qzBI&1ʥ6K6l>V`B]ⴃ,g; Pu2{$ "!O=֍6Ey^Yqt0j~Vtk G \#gn5t{'8Hӳ/7^ZKJZ`fICh4L5ھ4c.D"W^x=ng'Z{\T6Ee˂~j]sz-z~{e#A~/R2LYІToS7KqΨl/rθΔ/l[jXns_&1E}%ޥy>&Лd3P{U_S?7°GD|_y[5ъnk3'%f-j"t HuW fڍWD"C&[S{^^}61Lih jnPQZM&p.#k~pֆke_׊þ4؄.: 7 е6.R@{W"k\L`pwupA90<瑄K_=K/,{lNOTB{&u%kb L笅t}$B돞ڲ)p:F:gcD)چŜܪhGdwZeMʠ~!ʘ2kZ%`Lj68KMUvuIPd&hmk| pb@h:Ͻ!>G+;7'x0xT~'C@M'H!ulEv( ^:3s^`]F"W,ύ{|_RIQ@~xfViĭ3]PEv2`sT[=ruT 5^f4OY 5*[[,ջ_ }_" Ly^R\CлJbe7\>oJr|f!&xEY~ya GAs3XKc;}́yە1u@OwxF<ɃO(γ?s*EPHk$Gu:ȷSJ-ӓ+9Ikܞoqu~"u~4Z.C@wƏrzZ4+H=w(%3f[ <`݃TwO1Ns8VF 6$<|h'y7F"w׻,!A[s44v'!]P_cCp~. OCf5_FL"_mP/9sG:5+'Jw3 <&P3iJ 'CTqݼƉJ>JbGםejF|q!˪t:~Ga(gO6Jxo>G qw0IO|7nku4vp ;g?atby0x`Ǡ+A|URrTԡ '/O=/ql8ŝ.qef~a`v, 3r@.@`>iϹV3D4a m=prMޔLFC ,Cd|Tz vo*O FWnr55Yi {O'X 0õrr>DG95n;0c p p8%nOQeC _%,DQ #J4bOx~݅W*=An+;nȅԡK[pfZ/g`6s2|2P씻I_p{e)Kי20 ':z׫ljE\tM釧Ō挠Q '09 \nE [Bv))ySxS 2!&̴ 3CEшr)AmnZ`IMTdP֌{HI Ύ]~M {=andcnWP+nQQֺGЮy/'Wډ.p sɒu[4Y:#;tuA xJS6%aU¿2w; Шd/dI%'쉆u& mq@;$"#+Zѭ\iI%0q7q,cAf+f0l~J:gɄH%X綈 Qꬋdȝkq9À>/+*+]25 Gc̊T,[6yY'I)!SuL!掦դ?NpC0DMʖh EKyKLC5G"JQb]U#EpbT9+̳OLˈ6dd^1EꜮl:^##u;<z+hlq:?B_S]8L]ߋnw-Ɲ*1M V#c%_Q&t*O FDCXLyp}j"0IASrogqq>]oEIkDpJhDr-wvUK42T!gL(ʹv$ڣΥEh4l!h|2WuyZ\acb/xs``D#$Ci$%f|sn)9^b)cwvw]zo1qC<̪1!qssH~ӯP >o-V>yZ%jG|7J9RomTz#{/sfxR5&&s-Gӕ~ƭ,=:Gyq_ގV`&ϙ=!0pӪ]$9G׿a,2&Mޛi[^7n.}ߊ]YvJB>OnT\j@@i3S}sqIst$.m۫Cw [[,F&7U"KVxFC/'ʾܓ8lF)(tt Yng,CeY4ST!3 I"@Xl˅F( [AZ ׆Xg,!!PiSuy$]wq h`+r*TLLn?.mO.9?V之{:P;:n 3VEt\RcC,벷vcD@FP ^ިE@Tq"Iz=+©Kz tHGo;Nukz#Y5Vwd* XtJú/Nb.pYu)h7Az@JU1׫$M!JZ>HY 8~Ü9rwj +\Oyۈ@O,_Te%u|j ϑ(Xń$ D`i` ~7aFsL':R0?.8zo=ci. #+>b^h]|=EB,x#YS`i^O%vI~"v vհj\5+l݀gAVBK W*wEwsvA6yǺryLa |C!Z#PL?!P*%& pc!g܁N ={ v(gcojc1@< 3GSE;(?nsٟeDpm>+BM;2& 'g/j@VG) ftmz> nDѥE;gfw+OĻ'؎2wIt-ԥZ/z+d8mOw(T[ Ɂ5 ߸O0]-Wo< xL4_͚{`_Oh=sD) +0 Oq:hf.x9| ?w]93Es @\nt\iHLu'\%濥{]0k2+֥Ff Ic=/Y);b fit k qkǵK(5-_8rrY(R\>RR7?[X9nIŬ7 q+ttB!Z{|ѾLӦiD+Vw(取6ԬڀhvmS Z^$u;h~( qfQbirۄ˪S+Ҥ0ӯHv6nkwwt lZm#[,2XOʗ KN1$v,~%0i^o=ﭣ#j(ѱ3&0qYXͅ9EOi؅~Pz1bkf 0;_naԇTtNovb^c,Hl;ڠop>=E88LPؼY#A_ N.c>h {} й`Ώ@R[=zrF1o׌7|wIŪ`st/~LΏ .[_ zŸ2:1iOzÌg%+nAʵOjbUPj)E,;PsKN=U;t,Eӥ^6tL+1sb.;RA0u@ts"27NVNpY0ǪӘP_ӭCA.3bF(~S46 ty7y9 *~4S36W:u%,`U](l`C7Vh̖؁d̃8 8nH_m\D 8lCc$?-^UV˦ 9~)աnVoJfZ.\eڔѯbY?@\aI~;Gq~d'.gbi?mBWke8GaXxcpjM@YN1 .@(Ş+Oczk|gru51Bo78XV|IXv[3?ABç^M\O:~E揤AI:E5,f yU02l۠(آ_> vP \I&5 Se7:cgTfu/J#O\}] 0~nڣ6G+D4<1|jca ɤ(G Zѯw(9|)7+;tD*5a_O*I1ԆrU=ŷas6|UU W4QA]3a="GK"Hz:Jug}Yq!O1k_1o3$? gÞF2ϰ\:oΑ޶r7Ҋ | =8HD[%$iı# /sq2d9N40|\95xʧ2Cq><(C(袢g>oi+ C __}T abx@yy SV\|]L2.-M > @2|yP=u;̉o5fnj.CͿC?tb*#JGFM7!ih%[j%{!Da!D3KcĈ]xyu_Gh"A0TDE!`YBZB$.EoV5aU \2%\OYtZKPJqGZZgљO0u^eRZ\9o*4IwV;̙8uIc'Η4́vde{ 8+~;MH~4pA ` :scq Ko`GdFsg^8\$Ym._cն錷ٜm/y\iw6rFu_qgG]_n?'BYGq4QeT⎉p߷kf{:1z@w24(?W3y,#5Y)ph?P9d_?$\BYM 5^׾?yg@=+ DDߏ!b6ד_X' ϑ|OiT\=*z;H?<_66_%~]2Uuƕvx[\[M\uw02N:Eq_sFw nAv=aodjx.ږ9=5VcXogN-z>p[F3NgeoX\bltKƇgC%L+P,cLm#72͍ GUPDM'kt@c‡Ǒ~+L׌#u]Q`gl2hኮc׭gWd14 6?=2N:h\Q!C,;`&4+}n,ts#6 %랻{]Ũ8=?mz5;N{;}Vk@EjK*;uЦ-Z'$ uY@73mČoI*/ eڻv~]t F*iV7aLy/Wd³._yn,j*~U~~,(!dX>O#ī3P{P_<ؗU>?Q<grۿE%qkύ7Ьr jӝg[w2aNewIIyjeEd1 ?(.M&z9Nv6BH@9߳[-w#ưo7 Eɔzu.h[{|YUF,F`6y?"@%@jK*ؔ8*վ\IZI࿆4eeY,Y};O'w.ͼ7C 0F NcJBb̂8C㏴(:lp_k?iR;rؿD= 1ߺ0hjZO#[; ($Hg因bV tbQ#rKĶla@ghč8. .21ic_Sgj;F/64ly&B/yЈ8XjdYFv!X4XIsݵ>=C-T 9?-rѧk4x/q}tok;֗hs`[Z$6{&كcK=]Wl[! :PpN>A0aNg< c/QM NJ_ ~!gͤuPe8I;(>)^}xd굀K/P@χv bbdY\2QCyfv઴ ބY9M1> KƇz{؂#+ g_T* $?7v;lYaMvNY]΅~OhR_(?oovIp'I[7OՙoeTXwbP;[t+`<69e8Tʑ-_TvoR8}V$\8]lC؉h ]׹:tM˱S[2JU'wͣ;LvsS|O:7VK$nĘrQT/PYݖKգ=Q 6ZאW,Qg6]0E ;7c̫޽|ɾo5A=wK_LsKkٶL0z.G.#Jc\ƕBƓs[)m4'b~TfPB:B-:<~_EKˇFح05up%[`N-ǒf>8Zwp" ˛#`DJzU>ZYThvv=/f+4W CAw~QOw0Gw닎VPX.Y1e41P[ye9@`]ZBvl}6^)]4\`6N&vfJ$iz϶O}Gxh}t>&Iw~0KV'z]=)Ͻ~ޚ{p%G&R\gaO[,Lgnaf wXN:=^c=]"At.R6SO,KU;uP+욜4VV@ˡl>B{I1j޽5=+_߱霘+%urӦغ_ehSuGA醡4V=+t͎'Lӯ0I~Y.Zk!B9v8̣ .Nt_ ծHkA<$OФdV_L Hڎa_bV8b3,x3Sar~G[[wL$XsR1C"k+MRBS1$*z1l͓\C,1KD WtyPBU薄Y u-:_+|? Ue8X3BIZPgmm#A'_@ϻ_}쉩H(wjӅB}u .vqOZC.t7iy9 cېAiEHjk__s]$66ipaT5鵵u oCy'rmKZU?rgF -+ey^6 bū12Xڐ߅rOo șcZm"j٦jh`HΞ2b  9ik\;=>q\$2-]/kdUBBpMe#]^$LvgN//.L0NdcoY4v?YW4T^#w}6bYVf?dĢpQ_@(S_1z%/gبYPЏjtK0rI3\12Pb} /nhnngrfJEҠ꿡) [x{ YʋտjRVE@|yG0ߏP4 x8bPNp G^lils[_4'2-l6"am)mWʍ0FAmr܏](/ @s4n ]Aq(+"И^X*SF:_ن+X;6BD +GkWk?}R‹D+y@9_xdVx2ztnQu̻dDRϭĺSVȓ*m#Q@a:{(-XJekd2.co3ӁAŭѠar'isQKyп1#w5槰_7\B_ZoeH(q鬻XL*h5մL}p2'(B_Vhq[}CyITWIntgɗOݞtPzQ[ywyt5[NhE$x:]U4 i3[*"Z,Ç2JxҢn0A9Ԝ-O9)oZLiEL`1f`'ձ'ȃ.yXwyL~nj\sK NtHSơJHPMa?e (svIrɆUI 㲃Nty%oS?Z4=8O7ز5Tbxw~|ܿ{6`c{+q(^S} 5-pA]TsyH +ҡWzp.3Dc-ꤒ(e1 8wz<ķdTFߴ|2(}nzq hal6/,Iozu;a:W \뾸(c1f,/RՕJ>YyC > :/t.#⇙L1xKww?Z!mP2\uVKAQ,v8n΢Iì 2 dx>A]IO&YtX+S{3q~ߔR0QdlAnu4Z֧+MzyDG,k_>]^~-Ŀ:k5U*6VU7{ک+Q 𔇸KMg*=l8S5`G_ >xpqz@buIĩ:i7-M֐ob5AW趾~ q0ӟޯp0&h#$J-[ Y&aT5B/j1Q{RǬ[:rȤy%|;<UJsS};Z,~p(Z)+ulW.|bGiA 9[۔ڞ<{>g3?9Jn;/mWT֡Bgc07 ?..c^װyK߾_pEf )Dӯ5? [*3\ۛZb e׏#q n+ lتd_.%dthSq2o|Ja}.(fU3b{%>ޓ5*0mU3&< S}x&`yҳEEG}t]u|,*ܗe+wN/;YqQޒRڌCbO''E5ڞOQCo 7Knq'ڕ}Ik|!5W?en"#>Vsf[o'UjcjɣK)NI{(d{QTj}:^o#hBj vFqϬ4QA*0%>f(<ILAFް 6%򰮋ʏR};/jagx< Ϥ]mӬ)^'\ ͤ+s6k R_o7RF9vQr@҉ӤB7Wvt.zJ >l]@~̲ѭ#͸j{Rԑq#>]p?:$S׹ϕ.f߫0"~ňocHW0nHKΆ?Y7=j+wwv.A[o *~S7(bSt/ۖUg3x-ӰPM^uh0*մj K f#r-#Y$S b>{Cug~u\s\qOqq ZF>45204T=] ?,6 \*yvoCsFVAPkd]-9WK*=pD˘& _>o2Ɯ5qƿV8] & |B}Ii"?&IbJ4;rx5?i2H )y1't.R{Tkgڒ瘱uxnvUܱ]M}'~RM)T:GZ |<U!?]͍Ͻ \۳B"?YVawE,*;_lm;בmIf5ŴMYs/R\Dɶ6^;2S+6\=v[poV%M7>֣+oFᤗ4+)l]͟lGF{O_в3JV``uY5M7(pOZ1Z`#2!͏]ͩG%Ǒʟ e> t<%aAhps(G!S󊉪&^4o, Sy3q GZ:O}dFD^oog}u7H 'V>\ހyWvuY|[@31c&_)( <^GdZҤcCcA}7Ps͞)2&.{Wgr<7|CM]a:#w7sV*mʺN8dvY>l1YW7f2('wq?ӆgL0ʺ8ņ}'N^ Y`upK`ݏ%KSQxU iychů M^֊SOYY(b?xʉ ~ŬMwf>$ES{Mnj76yo~umsL99]c)o)O!(ƾ;]0:R.Zv|8k=vOzh`!~1ghx=#[@"zgLɄ>QKGbٔdy_ Ky 6Ci~ёSntc/?Z;6q $aQL"͔hx:p;:2[x}a+:VbvA'\LJqʝ٥/J.|owO,~c%ưrKk>br;ApWe1W+},_BY0Xw}3)f[ 2 Ƿ]I?3%_rK܊ 43@pD^-gK2P_ǛQi/%w5=WyDojux t=S┛8TL;@)sm(2L%t9LU-4bMSn;ZB]|BWn=D,?6;}12386z9$u T gɮG`߃iy&Z6gxb 8k:TT yA5ŏ:.K,_zAU;|BV~~GC_k^ɰb#8:ƜV|sHn`>њ;If;erbTTX#]vW Ս rSTmzhxPlTnG*r*D|- ȅ\'MUʏ5e>QIѼP4!6iHJ{I9n2Bi/q~V.]$ %Wu, 9:upF\ʬKX^y6W8Ɖ_g tg*. >A,H ma8cMapmt(ؙQv R+<.*8܋ԢrUȋXl9b<:Y!y\zIS[h$P<ٿ9)N?}{7_S@rrVI[E޹Ƕm>`2XjBQ-7 -R'eߥB{MEvۓq@ T$w'¨-`HF ㎷a+8m~꨹;EN %̕{'ND)/g BoŷY;@NǕ7X<,E@]ДU"V3²[_ |iU{c+Bb?P/zr=m; ihk\T.}*L(A9~JeM 핓l6A\<2o^(a #Cmjܦ B]su|A@Y?Rm ZH Dl1r=9 DgloQ֮3 $ft@FcR0&*ҷgzm{ru߹8 %Npo958m5v˟N33Kb_o.o{j2η^{ Cy"{j!<Ȧ]-׸|o(U~@W!ܼR ݯ<ѵMzf. ϋe~ }ι$iIl+.캟iP&NN #'?];D\&TQw~#?0]GòZxEW]ؘs3]v+C4y:e\kDYiv3 _eJb10 LR0NὭ˳LB& ƹ;v~wLR&y]2cҗ1ac;Td1z=/KXN/[rCW>1[I2U ߝF?J4&9PC`;˺7Qt։'%]1d _B[>UcQh u˦T9NW0 _bﹷ@%S!m4c$s J>cBoo7Ue&s'H>_aa#NGG~P u%Kt9=-'djWeNϫyεRfL4KPm1Ncqezț/Yu1Qȕs[;|5 E :&QGrҪKmїC(7mh>n6ă6jfREƞ]Ia$/z6G;1@9CFj,9b[[ \Q~s!˵2ҕ?Ѷ}N12]|pTƛ8uR,;(WXIPlRJ 9)ɨ~>WCSֻu,=BHQHf[ gs7Q]iSP]S%3k`0{ qhSm_5QSޟRCߙ|p:Kנg5z%L|rV뮦Z&bЅn ^W/=.Q'M2'GZ~a^US_; 7!\" ez }`GGΖy%r'?jkeU6wن&6+_sܲ^mu*/GGeUU`^0tэ'Z{5 HWkM)!iIj>Z}6-Ds6 W)U,Ux:yHj@Nx-qD("ߧ6cg"ֿl_F/23c$CsjIfx-c?r9U94&T+cTf`(ȎafŔj+g!8 d=4 LhMcb<"cjd7yxS1 E\ |"ˇ7a?WكbJpc u' Ƞi!{mg{wi z#v AfYr}hYn/թU\·hc'aeoW%<9[օO36k gK_i :eMQdySb` 1ZyJ:^Lzjx#,s '' }8Pb0r%h"c.J_ Ri[d#_>Y$4@_pG̓Ւwbg70*+jJ'"@pKqUP&=Qy`՗~Bz-v(8i3*9&.G6臎ݧ+gs<=;w)gh3ſ1J%rjvy.ݷ]0Z_V2FF8{>Hfg/'4ڴYSi-i`AB_y ;pkƄģ=/|ko5>:_R,s|\`kg[QXg¶wC^ ޠ48 ?J-]˩["œd4v6N6WS[B֊d8ҵ[_G!H yʢ$}#]wbp$}HmRZ3r =MJKE,iT^( Aբ":S_=$_O&k+(yT#W: _d&anRN} X,ynrӸ`=yDz0fV0\3xMW&~ί#|,K 3bCk;^& h9S_uzb>(`??RRAͱ4~}Qxf=ľ';Q>d A㗟#Bp]8˷V*6ԑ]N\[Kt_FֲߍSNoI+f>I2jC>${`^*+~WY~W΀F[}|QCi%\J=hI;p慹|Q_ũ~5ƺ`G|o<Ŏ%k bnUz-qÀQ؛Pŀ~AmCmJ[FAz0*T3_V p{+ڂפW8AL׷tͪƀ6zl47݇xVHl>;OX>: ȏ h\1~AFM>ɛetlg[$kt;A&i=&q',ݛ }&Yw71bJ `zFey@*X*Ę'ݖ]Ԯؿ6I(7K$%ั#<:%a@t,Y7h-#0m[0m!{|&A!jmBvL+ڮ47\NEB߲n2?.BaA/HGI_NutX{[x兛~{_0W/p."IV!ǧECz2w>rsݖ r f5`a"o|f:Ŧsq2J::Ug۠42 S$T_Q gܓB#R>x=ŲOX[O:bu:~AB|Vw ǝ'5QN2*=JXo*K7hIJָ Y@72އ?x.(W ߞG0͎-wHڌcg !q7wdPiePk_Aʱ !(Z0 %~0žb7Eh妆%2^YX7uձ׾EvS)*JxNw"MG&'/6~@Xq{QT&!js=̑_eєޔ!֋A j'qZm!V!pKW޻ڥW{Oxn% 1mnnO:FQE8M8jF49 X_jӔ,"c'3/9OxP)rf+h3yߙ֠l0DuE DU˯Gj1DS ԝBbpuȂDi(0_|VzMi& Q^"> cF5]Yz*ub  Akh6r= @fh vX|D (/}qM)i$=$PDr>]s|A,v/pѦIIk-"Ú &mip붒PNg.oϼe|adE,a:J%[6>(xFR%~Y-%\;rw:#a?Qnkl I};:yT11Ʌk 4폳bnb'C&I=xwhHAMn1_Ypc ?Ai^Ll% ] OܿwƽT"[df鷠>gg0d-kFx2T,.f:YvΑ%#ΛcVF}9H $ÅgI~Sքi։D 9E,1D<]6T& b2VL y5ES.!h:VrWMk5>M*v" xxio Lh)$+O=2T$?ˍa~WTMKc,XH$9\QZ_fȉV_h4{k\'.on{ ہ,Hp\\XF([| *xg=KCq߼ysAtFFcBv>zGtIPuVrc,?EBJ4bϦ1n](yǍU[7ۑ-!c?3#[J>S!YA:8got  ɾwc%W_0fjliHLg(rr|ޡ\,>gظdB޲Z$}xÀ`dݴ*6 v R R^]FOrE=%4^뉟LfٟR5JLcqψ7&_Ѓ%`jQ7!Ve3)deחl[l?*o{-StPi~ݝirH*O|kd9j ʟrG ^:E7u7f@g9T9IWו}J{{C\GCV?ϝ*3fn;"wвrx+<Vm&(KX箎bKXGkD 7QT; }!p/Fig!mڄijZ&zK)Yl ׉$EM9auZV6zoq w-)>H(PxO1܏zX6nH.SƄ5\O;f_߫~Wqgl1]O0Ty:{_!K/48[/'KoE"`WqO !ggj|Ի&XRѵ+돧|,ŗD1mEm-:.ĥS]gE9'׍9}qcҀ-|6_fFߡI`Aj͑GII>[7B%=2HR tDR:mݤ'0=R3UM$nZvJ`ǯ{vKח/ N tKT/.Uiۯ5U// hrҤ. q1N7B?Fp!u0@Qk~]AH5%72TsjJ)}G" /{@&`qzv}^}}:v9LzI݋Jq[/&Iao63%KpD STzqdY#ǒƺ{_=їeg&sV!;F@-h'K&+VsTļKx3V-b0֥tZtXh08q@`9a># {R#}\e9TrؓuX1L%ª]|eEg04 E(r-mЙ>H3R2>ksY Ri6 \Ӿ>l$Ҷkw-'4)00j̛5g KX~NHt=`:SQ>>?mcSFY΢"E3%o:쌊m;*ő6ai/]ē&>9/#ΐ;f0M\ dgp0?^-Qb3nP|1Z h+l\by8˫l<|A@$sɫqP3c\/ҥb'"zD#z9Waߒ~ QW;Ką^~xءX*]_S %& CQOCu+ENhY[܂H/o_>O168U ÝmsUf%҇p|Zn>"kc{]y"2He59؟Fd9ɄUJG8hR@P}/f-rK#27t5)ώm '58QVJ> @&BUK+CȾ~TPjyEyLGzcGN !QH2o}Ilad} OēqL!^_ّ<éTjM+Av)}(7OWRۨ:Gw-a;ֻͧͻi8FV%pFzXj? Η1zRӡH,ݰ騷1:1L'U`^g2kY'z?xO٦(Ǹhdmrcp;˘9,{bJ3N>/ sL$QN(ub>OuCjy_dSt$ +#g%jkP/ {|F7*E̱SNB(kүpS MĿ@gx)Õ19"AhCՍ1y-=3ta*0 ᧣U5\\;SY7 8Sur/'a׾{,Œ[t# ȉ܅[[G Tŷ YqK,g]57.q5{1!O`Hovơϳ*dE|@櫾;ݕu}b, Bɮˣ zra^6VEj˫_pQ?uANǒ7^60 LŁ;CLpT5ӳq ϝ6íPgjF* E@=@nw.YKUsK<Jeu% vǧxiV5s6c!v @4MqzԨJx$Q/Lq#|STϲ[a qRZO-Vc9sR':!C-/HwxGVM#Џ'˜< D/5\{|ar,³U"aE#qgt@|<%G5WׄZƹ][84=Ldž̔ QC~< VoqtzB\s Hم[K/BMZ$o*aI߄֪wƎX7R̄*J2cpFozdGP_';vHずzR}3>Mc9'@>Ċ^I;ŲoUCF,0L|<{l &,,ƥL_ȆbX,k䑑ؕ,OfBː/`b)dqv$25d5?y:F24Kfa 鷘b%F^yku/5T_VKxkz+b-%f#:ئhc}_vZ|Q׊9y DXgIiC9Pn}!SeGDd`9V%y:@e72Vd1nכP}a* p 0z=TA c+/}jd= ꃰXV5nx: C]˸ X2iȺhGj.F!tn=SXڮoHMiM3[ r O'8[C&6ADX<›W2YO36"TVs'ԣ`!b0qn2<86sl|'܌L脚K4a5˜=b{yCiS(Ԩ9j٩Ko")2zh/2 4kb,Fg9v ~GtˮQUϨ'OSRvp8?ojX}') Z(2=J 5KK -R~a. )BvgEa${'>7& Oż()Cgm7J.Nsh3`}{V>&*Ic4GД?x<,RuK,T/ڍ߈7nA9T?T6ߍ)!bbXC;R;jjtD1A~]8IUDخj탿=%Y"љp?*iz'x;dJ)_6sgo!\X`ZW :O,wjTBȜhn`]AUâ40,cNJP>EF"(1vӻ4&}R0xŪ E{(ab =@~X87%m  *^#`Dٍu@[uE+AZ.ԢP-7!|L' $'ӈ@(\5_ T/-EQ% u1GP;(G-hBu}Ā&Z"2cT5_g:R "J<`6{ya"-/|`PNG}y..?8--'5Їp]dʻzpsbbMGM3Mx! m81z .hH{xjIC)_H?/೛,D:IN+2ʜR5!n[晍Bup^L蓹f/kI)sK֭Ee + ?&Ff/eR(ox16fVbv}gpdq_mK_WXxF\cĎ]#W\1K s2G^Eѧ ^hmƏŲ,hN5SBEnkzBZ:H}@TuOS`M[cz7hxs=hcK-ޚGa6apiX]y⥤:+5UD[T .2o@De39+{bs?.1sb昗F (#| ֏ye[e/#>PםbWI33׸C2hmЦ//2Gt➑ansr]1Λ]G TAprCuN 8nG$`fsc[~ w& DObo;u!7Ɩh{&Llʾ)t=>΄S`7gKkdEaeJT)Ɖ\L>~֌ցM[`KnJZG%ݴ,W1o'lv3,Ũ/=sۺ;k8P0ęxC8:Ie6u ?jA`'ՐLMdKI_TY M:}dx7vLk1T=w'"zS7XK/I:X7hPN0&uЩP.@@kP \k9c]ܷ%rnbLn?Ȼ-Y253(a^ĂDɴ֒fE.00q#,S%#@(~tЪ֧!' K^c+to7x6X=/:ci~}m5Q~YAzz^,zo&?5cABZ3J&[411o o6~){<1HkY]Z 6Vm3pșU/I|-#26Ky:mJ>R Ԟ}͔tOK\M ʞ<2WKG.@20U%He~t}tĬ7:j7]ʉX=.}ub[."D6E˯ q=\C`<bY@zqߴr0)JvVx#%q&HZ| Ȫ3Q{sx0{=2pcKl/DEٶg7â9CFf!ěNl$1$ -*u$D VG}>ΞSZ U Bf:W86pvYPlCFf;R1šiDh!M0KҹGtWCl8@ ,={ 1vinJM5CjV:%%xyd"bz6z-¼rnroo uGW Ocd}1qSܟ@RZyJ{]h''=.9P5 a̴3l[yŒ]܌vNy n>qz* {L ZIMS.bs K~_q]%□hї0(ies /uDDݓg,j{m8H7EA:z 1Y.k=F̸iAvjZHleAZ]{E=K m#'⺦="bF7]+VEk]tWFwf}OXakCp#貣+:>DESu߆PvmNN8 %?V9S$+4Jt޸neC&]Z9n39 z i(!J&>$4c}TXT86nJd_KzZcjqD 6ҝӵ|t괋ɆҵıgQvRť:$mK@8x];Y&YiѕVdIBT4~OEޢWڕ\ɷi{屵2U;Ml>85g$Ϲom)(6>\^ @&ansnՀ H׫dy ec Cq잵.) r n=;ȯy?+,͖yOك /ƾ}tF~ ` 9%Y7O2HO*2֫ZuRn$嫋gn|i/n]ϊ͸SA-'"EL_gNfm'\*pmtlw"7%bis8p%@D2V A,e gU̟ǦV=5^n?@EU}yy{0n]8~&k'QS)e([/{*D%  GƵg%W/{Z Ө h 8˼qdH6詶^XZ f7߁> 讦Rwz.?v; a -᠓{yU,##CpAHR82k]EIԖsߏy\xl;Wh r7qicZPQxs ޾COilؔ~g-w>\ yE=MIh0V"d/GgY5>$&!!ǧ'ؒ]*7Ԡڐޔ3%~`C_ˏjUMCULAZɉU"HI42{qpa,r1QaLp`T4n+4!]p: \}cu.yF|ڡEχ̦ rѯ^pઝ&j:m[&zsvo>s5};B%:>^ ˮ :W̠#b=:@ojޢZVQuK0Oq#U*`Ǿ),uuu6P6Dv5J~ρ`~/:M.91a#CF/]l JECO"oi!4*( DBaDEC YNbؤ9;r`[12P~cRrs \QuMNћ'Z]n{9\BLjPC<6T!oZWA1e ( r]G- 0֡10#'Onȯn fd.G- &T}P8L/.L o+W>VL&^'{o@V6=L4Ok\ B'?\3oXx|JLޗ 9A=^S`#Lj.b i&s ͛_Giօ"dZ䕖_jz r-IW{g/a׾cwjWС3 5OWXcF٥ v%`;>mH`xQ47dߔxOV2-Iw-廭;MyӇ f\M^I_Bg2NenvEOPpiJ[(WC (('w4Gm F:wܻUx][>L~u?k?t,:"^ܗ݂2:8FtQ,Xqw鉽Sϖ _TȋOnG8㘶|l(GlxVwqU1mE ͙ƨ)'ٵ0߫j,w&~۱pv,៲.(T0vp~3l֞ǻ+ f&E}-2uPV㎀FQjzTivvVlt-jaTsv1hw؞xdӌҰ7)ܐeuݚ0b"S97ـxdb4$j}NUܰ`Bʑ]>4|B1eaVJ,U_ nRot>81{ 58\h"NX Ճ@n)V_,ZTXCZcTu v@r'_f=@u8Ǟ7U,W xr}s^Iw\<:uίK5LBV8`䱓>#2lrܩ@utPR4RA 7'_Kc|^1F&Un+gS{cb}q,I3qQg&t!k E{Oڃ7&ЇԢNrqb6WЮaDÐ%2׻HI0lwbH5? ?Bgj,|0:$M*f/9)&gm[\^ ܺ~_D{m܊.(5Wӆ /-#F*`Fd,m8ɍۮQϮ iLvC_݈<.t/BFctdZ@u}n9O~Εn¸R)G+1Gxb|<EڅD\`nBKO!}e,;KTY24>dXTRɷt~ҳl @Uga9mL(x]7:{`>K* cth}}:@)$܈%贖kׅ{ʲ{t.,'FߟgIn7U:)-^׿(4ov ϡ4&oo;rIƍ8ce|^V2?Ca9MtL "㐼]BK_뉵R((o.?m_g&[钻k/ 3{ϬR:U~ۭcMvlHw&%yˎ>bӧE<  >SZm5%J@4o6iZỦ70T)e ۓ7J :v[SUByqajJ7hjە~;-dNwFaAz~qe#g]m TVg4H%t “Y v4 Zp| 6 gJH+ّP0YOʡĭ#ܛ@L,/ɞX:6uxϹsqSozkڱ{]oVk^PQyS6R/)eY_^kmDd?q ~`jaOa>R3 fH]k܌oi̟}% T”3RTOjx`3_VrZۖl•VF_uXܩTǾmz<_zw) 5wSRƧՈ'2Z0wAx pu;?h.SR*|\)(elLw d>2HC\4xS%epJ+/?XY|# FM g'$_ F[$/Pr1kޫhikr/ (t`:ȿ:umݟN X )NW ؁FݟCWq`{R',!wq >򟨶l3[`^+g:cz k NL*-3:^7bvG?)DV.w;]O3lK[knOíZtmYyvKY|,-Ex;[I ͡*ބ:MRQ TO¶ʲ}ct2Ŋ\^pȯY1,fxnF*D;Y1XJ#JՔܦ'j3 Gч0Is_.W1N7dD~f/n(d9շjh-1^-]bk~3(ahEUNeZGS#$ !_ 5USaOw@)`y08^341Q7PVf>a2xzok ?%bMh)"- ]Ǒ'Ц/9TsPLE WO::Xbs#Tx7@1ցJa>Vś?khL Z2qvr;LѲ9;ؐF#"eF^2$vgyG=۶Bk3Dn!q-+(M;R7B*5; rFlŬjW}@I+?/FXnv,PwKWH:m02И%Dpv]X g&/%^2eƒ5ׇ_o]@\-,؍%eϟyA-e~t/z 9_˸N!Ϳ0}u66_-n+j`B;9#闶Fx`}kULxңq<ʢrG;5OR֔G/>a1oŰ׿)fSӊMoV{ֶRw2< xge#`z㤹ח*)?UuMEq:Чn{ 6?C=L E\fMkW V_kYv+<('Zp_4c {Id #ʬ'2IVhWfq]xJd"$3Y眫d㶩:ؙ ;t,R}L̇<N[ wQ:`FpNl/>N:DԘs+*8Dm:f/(6)jM`thxg>Z""B|R<3 )`Fc"lX{ l/rQSWFovg4`1LmsM=bi9 #ܶYev{ _-?+&4)bvbv>ߏԺcSY -U8ǣ3gOD&gUֺcSrG!;Z5Ǵ;RkYɇ6gȪ*uUw& rܺ-~F)Q'DTC=`~ фlI{Vģh*ɹIPa!&9zv^B:]1ۉ _ڿQjobrOYgy>Th6?E& #6nI31B(F,z%&fC|OCԎ~\'r\0X}XÏ &Zc;ù^g8zl69)HO[K {CP63|f x}^ >%?;]7m~knQBMYّ =UE9}>j1{}s->w-&Ny#w4vDI.;D jB*U#3 =sB+e9:e>ձ'&u[.Զ~y?Ce˱׬#D!$Gׯe*%]̾BrDT ۆ L7ܮU-q=}Ve5~3'g #R9NE|1hZCqRC @>J{WŚվf+8j;~.Bݲt; Nhw)ʆVPIQ,\%&i͂x}D[t3K2w酥Z'eŵk# /i2-ttor-7_ 3~@K˴ӡM8F"n8e>KUY)Mi4]WYҍL@A:V&/ZhEwD 11A;P4sekdu~`lSYD̲6\Yb0.{AOCxz׹w0smV5ď%'| {`ET~9<2;QD] K@"?*y d [Y'ΐ$Z>^,TI /]ͥxV7=?mJ;;- Jǜ {ݤ.SP[ph|+rL?@l/^\d4#^y; 攑{tw k<=;em]"U[4$qWzV$(1SFԒߟꐣwp[+aJ ;oŴ@]i-G^҈ SZf.t K"Aso<%kNp6E]ס:_n>]*rT<:^G jNoy5QGӱE=b2"3ȉ$3f[g'5mHB zRI/lwK2r|ŠۨR6؛NmEWp! FWx<@!(|N`tsC -4u<ʚҢ#oR}?1^9rETX2jWB%R15\棲K {#Js%JyRͬYFcm;n3^Uz Js[J_N qTFL \<K-D|phJ3GQ6Eվ-u9Xo]տ;& k11m0I愯AwY $դ-Y4v%߻TJQ.\%euF(~71oAQw#E운odyi}O9y}&QhJ86Gjq~%:J*:Azjii /8boU,~x_?)GF;^TGI(YT`R7u=?ʹvpKR՛"\-.?os;_^`R5#mhu1uz& H?m/N"s>Bln0竳,iS͗:)eԻY|ڔM9#M%A(Iۡj)3n2|WG% 2q{JZ䫔&*u5̙6b~?+> l5Qqw0^o'UݦjeNǒ3ȀՄ[XIiHtSZ%q2+o]2.Lox6jƏhcD̕jGX FnC4+%t}W Z?5Qm1;_~qjsE-N>rmռh &UQ9mkDz/(s-s TBGV~cmY&&Nziε\=ddžYGݞwG^ QcX1pqUY)-qXqm({[E üG $vβ?4Ԫ]Bu{֣WíSD`;=}3'=+>ףf2ۺF<\LĽr'/8^laGZޝ(#KCF=1=`Z[~tx.͜/n_'@wuv1^iKGB,r+8h-s:N@Ơĸ@K-corZ$}zLThA0 Dc_%\hbdkpmX] +lVg=*г>0"^ďVSx[-#}ъJ q@w,Y% wG7܉T\b?8RNd{>.ESI]#,*kqk|WAd7s)n <؟υ cmʴnQ>\4mYO-^5m#_[u2w]i>[78N=!fm ?8w>"PmiA1sEڡsghta86+QW,)Cv1tR9aOqCWѐh-srdm&Ũ$h!|`d'#)oWoA?WY>cr3 *;V+oZ{!~DA^SJk(ɑTޏwIn3<=&Ey# {Z M fehMDշxjypu2 zٺ$Ð5)ˀ++0[SW*٣Dp>$"gJQw*uOVdѧ=j&3 y;hCj"! ~rJ)@[w?AGoVbQ,f5=~bX:՝hYmig[<$K}OcbPB.֖h2#Ppd/-azž'#6PDŽ*e\':o;i_f1C SFԽ?y=N4sόkIdFD.qy"11G2 n'Ώ|e Er.v5Bq~S17cr1LV&&wǶ O3H9Q0f'&YyG8v&OB >Pp1z.fHr7IumZu +ɸW ې$jboAq.̊>BR ų;2%vlCn>A+~w /7p:ҝ>5yhP{zIvIhD_'pD%H4q) &ؼoV㗞]l|Z?a5X0o]J1 9<,%7Fx݊cBDWOl" +F"p15GQ_z&@qdS|fiPLpu " PO8pji)J{"űTQ,f5" t"|g VAw@aZh5}ꡟi`ˬZc".}oi01Rs*l).>ПcƐ%)X݊N~.W>gΚ3ÏӃt,L7YyP: * dW8R( +㳝KJRX? Eeγqj=& Sxz~ƶ*1C<ۓ.Ttl >[~Q7ɒ3lPG!< q;/*1OF 3nO=2ҠUz7rdN,+^*W$~g6k\+,X QZé Ű^ki#`{%_>M'2 h܆dl3,fцחoi#-z9R?l.|U ^4~w%uj4WUP*.[#ڱ -GBr<oa~JWge޿[ZUF&7lˠ4{はl#z2~ݍ#T Bw@PϠeDt X{pKYm+7/C9BN->Bʋy,w1sݶ_S~ljIq =SN^!1Cg6rR -M}ZQoAi^z~Kq/d>x}Gk>:`.tPc(.aYINδbϕd\d\GKA6P͗1xXX8w?-¿L遄\{zl@J ;g *vɥ,p볝"=R| _%4ħ#]t|289$ ^H?N$Hw=;~ "jY Ր{EZ1Ιd^̺zp閆.mq\GM[.ii{szɪZLrP0軼Sr@} PP[/Gܲ4B('*PŮ _s/$`-Ŀ6[2D>iE*8ra1um 忨Ԑ#vW75M=z6d.8 K$9W)ݥ&<g6rn훸j%rukpc^j|W I,h*o|0~L+lJ qN,x}ܲa%YG՝2@[͊#.Y`*gEs#kwxC I+ģsOD#Ad&_Ň$SBu{w>6?a1"+ ?鴴^,RcȐ?P6KA TM7G\|W:HC@6n"u"83e~.; kM,etqO |2`hBdJ h~9!G%a̼߬oyKKΧ\aRy*L wuKčLfёiG䤥!-h=ime}Bx(Ę;߭Ph)6ct0-a^H*f1_<)&&R rq #︐M ;Glvv1ӓ#@X| ޓrB2uW>&4I6DW=lzӃMcGOs(i}Zˌ͎ #{OW܅a~/T6KgҹZ h]'=H}ܜ.;b)Th+V GV̍T=mGb9¡ޡ}B4rwŅV?CD+0+"IӶ;WSuog7& >LJFDŽ$dS~Rq [REu&߿yײr<6d̈́IwmT1QfoNW\z.7"j=NeQ14EBjz)8!qR9iи8*to{Ψ% Rk*,k$8 Ė>+;Y+a+%R-KW;W=iaoWT;m g ݍkMm  N'sJ~UƲD,?Rf]ҷ]n-2 4<8+./o$9N[2ѡcNF:WIv;T+!`\yxiӉ߻?&b\ :q~7@ jj /~Fv7=:N,DuPwTLd9"5dv_p@rsW,wOQ>HœJԓ֋iꖤo(Pz3Y~7)8z {7=H˔u2ĕl~f gn=<3W{կggj;ngɪ\g܈40qoWwJl}ŭ-3>[>E.YGU^$;#};\ j],sSnǭ58oqBq,]AM@~{;2S=~Dy!L] x,wy X-;%yx15yM'|uiI3$yZ "*E sR~ x9]vgSQhy݅{[(􏚚pyaZmh\S*P1 } _l C)#p۱%4CQ.0J] lN~T8ݰ`ͷG<t]͊w?G̓˾Ү,cUL A/n~e䡉 ρ!xjk 0АLrjb B|3R `A,YZ>kfs.@n2d/>E:MBDqECm(A^Coa_-Un@KDcۯp b*eǕ⥂ز"OVf=d>9Cʥ|1{T3oMܱ oNg)ue=yճS ʍhPUVί qSCdMVhkǏf$>"A,OnyXƾ0+& >3d[-1@q<(#VUo.o^a!Ku !J30ʨng_ c^<]$^tLR0}:wMhꊣ.Ҕg]?)6&ME2e +^mfƘ,g+4D!E.ЄpC 5cse*v4\VXFEX?<=m ){NJ_Xt1OX 35C]R؅э2Tnܓۜ %0Hg<uezuN6[ڷ3 #:IJ\ @$Xi.<:GC삚V+Ki:mBp䔈 88),%c$ SPݕv턒1Ũs C\;;IH㈴\&G6:) M-WvLGzmvM ; pf dXl2Lv!kF꿪ͭM?, O_JcoUIfᓸ\rĭ4RաK5ȉ??}fFyH-| rNGDnXE(]TڜKo_~7Pw3_+?A"vBtÅ\+6BHBo@vI_;Q9V瘔mg}3˨,LI6 ٟ`{Rq{o@e;nr= Rd!dRz5oS#D|t}\9e$rF]hY<lM?D$&̜$&"' ;xV{-wCAQi`,Mz2%}+30V`1o;.<^.fC/4Pf:4mR˚U}WśK?e_Gn]'FOOă7ބ 9IqE\:pA1yv2~X.k,+Ҟq  ]!t7Pr7~x6Hj]Ֆu b3W?x͸}AHK{c6w F=}6e6Q D|[5 ɶծ0S'H#}aZP ;pY[\~Ī!"աv LӾZ[UڌM9|(YsL"/N.a6`T#Vz;4uӯ=ӿZI;wo8Ll67u #lp4em*YI<(zcaF('m]L%*ZJH1mF4ƆK\vsbqmDʑ@֗FXɴV?;^RjVƜڭ  jG&gDFM%{w[ j|hIjXD#pb{7+]}'N7.x9Wies f^y'S-i}_a[7-|no>0e/vk*Z͙/jciQdcFwO.YM2\F*<}p:n,e@QnƫgjۖUĎI=nln;Ȥi9ݏ=N(ac`+ 's3J ;rgoHX˷-+k:Av*:$BAB%_`goV %dϹAr6W 9w:S//+a{Z WiSDGw تL_6N@p%6uK]3_%v%T4:60}u}IPAUm'ܛVf73jKp,îA4K,\tc)㇒7߮X3Mz$*awLY.s*j~jBXdz-gvͭ2K *ȦA$KS^ba&j1ѯ|ZWJmaN":㍩ P*)we"3tXSK.V.kg#A j[0Hgs`ԟfONur'?9D<.3xhմǬ ^)~Mm8~ܖ- #"+ Av]]5@7e304fQ w=^Ԏ!#OL 9鱜@S#иksKkw+aο[\,7aYiW~MEu_.)@6 `z=*}287"!g}lAjP?Fˈ *D#ޠ 7@J?OQũ?5J;3 Q&Kc4<>wB(h/2/s~W9 `.*gj1Zl?K ~塺E郫fY ǕkhL0@31MuzP (0@BYpBrҁ\\#+ZyyfZGb/Ok=P\x-žCyY!@g0䋂5%]0* (t";#Sz~\0*H,ϯ\f2!SE~ g81So&emubm[S [k XabB./g\AnaNW5""l<{g$h>x̅+mtSFDzc6%X+30;Mi:}:ۣ)n:b:hR/]VÁi+{> _)^'-YoVm|ANALLwG2^7RÒ c!}QY2?\Ń1LO;7V7 ijS.ӓzW& B&+͛[-}#d~=F~h`H+QŰ}cm6-.T񌖅ĵI)4i 7Rqo?ܧчH:Te;Gj<څ8q=D;Aeٞh [~m=Lr7g=;M@#kH;h`wz$ÃL'aN#;"9{cz$. *v@ s3(Capۖ6H SN8尅r3?Ex~7 8F|JBWalanmPJAD~y4k栦?q.VIpՇ i]e] % [yU؉&dRoOTzle.n'wwiԛ@™gh`!3W|c3`XNi/P'21 j}X"6LA )I.8%/8;gc<[WU{JwιK^HÁ!C1,*PT} `yk<GSuh Peƒ}#,wtY/:7y$b}zco̿_tx2'TfTzqXR`Vٍ缪.~ID[B7>~P'M/ɩ-" ؛fS"CJMp#]lf"&ꍀñU4^fJjR#dw)^[ⵢ+[o{gJ@|,NQ0S:2')uא{7`8,?P &ڂw 6>R70XHzaѴn{\9&!{I^`+a3 &ہ6n0K1樦vSwOMxR{L&:_a~U^/awg,a7s6}q*Y.ܸq/?3SЕd^š0 9qհ0J]{Hqj?*2^aj x|NIE`$8[Nj i*VMG>0Tx9uAKB)h?I`gKS,lie {N;MI}l $8E; A:|D'`\64JZfVu,nW2@[뇨Y~·.y% mCv]/07JD  gf:j⇎K1$\yDx) 4g ?7N;"ҟ:[uW"U%LdzLĦyߟ8RxBA 1OA+OfeN WOyԢV$ġUN([/WCaU: =ؽGYIu= ЭXFt?~4w|C K F'Bn;YH)z%- X|cD{腃qD=:T,-~է̙"r?Zq)iA5tZجX#ͺJͱxqwe?X-SJ-?owjmiƭ j2/@-p~҅h3|!djoIp܎CZ^; H'岳9>z@{.?M?!hpBUW8srCK- T\0p7EzV@H¼V&@)L(7zDId{}_?@cK,C.FƊoX9V 'lKfSo'jn/*v2N^ aErBqL`ˮ-t Ȳz|(Z&Ed:؇c/*jw%oC]RDgN̰U/,~ p0 N6  Z>{!Ҍ@&4p&"vsm[}vN#w1)uX[1ݯ?ccU%ޖπsmno _,5lK :K7?rAHT rVt"J:qہ"feL(̍(8t6x6p*=C򅝎a*}ۛa:̯{)6[9pP*$FW@F!*J^3밋4DW8YXk>gjxgSsdayE?~%Qw%)~L푮}M3v6кE'"egΣEc,yu ϭ~Fۣ__'u%K.FA~|$opCv:. m\<ꗵkyZgA *GfjUfD n>H4!n ǖ美Ȼ,A_(&,HnCl/ZX^uJ1&9yZ 3Ӄva ߧn.6NPrnrQ5 *ffERMd=9#NcG&yg2d7G,A d<(tgи߁|U0/" || UՂ =c3^%}'RQbBk߼+Y5ufsC d{E=12QzABmqZ%۷gjdmEx;׵ )&[L bRxxP(Ӵ79Uc>AIq:Q ܼqw/հHʈla֬CBFG|R`D.n4uA,ye}&l_7v=0|gJm*GфHY86<㰄MWwa=cD277y];_!T3 h`;oȮT# Cy1C@֦71$%WnZ6hޯ3dqN7*[8!]f9ֶ `d 87m}&>Z{Auۇ&U}. oq$;Ϭ%m5?ծ7=xnt"g2*org'j^Pq҈4eMޅ!ڍVeo⃤  /7zuzv3GD *6˟u?ZbK|3¹[Ob!i7r-z5[;[)FEhzYT F6]SO?:j"aB;d aHRsyK޼v^&֧܏naNyo ֶi.4 n.{cRa=AbD9X/VoWbNQ%K'rzVʪAN?ěz]EN9i+_ۇ+R!{?V\2ZgӲW{@l$vbgn̙jew6jXexy/%k'f̞"V?. A~vKX-œM0_PR`s;HL}-#MU7?T֞еHCʌtCI'c)m]sK~~|P$oS8_{#gXϱ";_4:] KSZzTΏkOVv _QJLx7Z [+X.n %)VayD\M|E4`jrذ" RKy8- j7oR)0g۷<S5yK<AJ__y+̙os4ML?LC&#b)+JaVJ$ަR"J [{ʎYo!E_N^i%Z7h7~Q\ 0ZLc&C8ܯ7=;΃4E#W@oHD&b-37Ib%Z0][c;[~AQq5EcURoard3_-i~- ~Mas L)oHZ8]W3j+KN I\|vt;a?W,hP^R-U~MEv;Cguzv:Ur%uJъL1kf1eF/# ׃ը|}]6}$B<b2Ne6vG`Qĺ_by:T`o]6 ::Ry{#:$b74P~XT!.[S}zx`Rri[" 5)GЎvmt]#@]]yd06qV^Uɦȼns@Ei19Z@S#!-]͂_LAp=&.#Y㣮NNm&1N &_ G#sr߁I;'ayy,\~bǩSѻyxGd6-50mq1K: 4fA8*+k jU-4P>3 ,*t~jH^9G1?\o )dcG诒 Dy\*_GS@6 .F` a%;I9DΘonXja— >Tjso^F.@nW#&g' \>8?M{0h:M:Ppr),C~?1(%]:p`6IKܡK+R,6_t% X;Ea>d}:?D鶨2*QG3No"o}Nap&Y+ӽug"5~ɇZk^ɴ#$wuZ*wɯtЮBTaC*됺z:|f<ǁuPfƸ@POnrLY>} #7YtZ]>tΕ ,u`ѥAzUJ;\v՘oۧT٤$2vK~Q?x<i>cDtR/XOP- 0Q3y2bT7A7[úTn.XוA4C q> i_P׋1"T=c+cwVGb&c;/H=eJz)Y6Or`lVV-Y4O͕Sd({, ߆WC;aJ/9ʲ{YIF!ґOOEQ+e<)f rxjd:ژr$ՖSEv@e[΁Da8`d [-:?[E MrzhjmI xޙiJY){%bRy>XR4ϰusv{s_3Mf=jQ0#( ~6 CV5v~kH5o;GWUfc!Fͬ"+nf|6 ͕N~VnCH= N$)}vndṟpNjO:| zj٩gUC=5E)Bf)Y΄@GZaز*| C`}s'763|)y|4\oawi2hݟ(]+= cL5K+)9˭cdIO_ԍePߔ{!h?G$>B>u*߲S'8Sa%)V%M[7arGz2]G}ſj)>NmdqcoE%n3}a& l D(5bؠ;\}i#Α&eSA>܉<[Σ#.x;xzo6\!TNnoעF7^ ۸o q(V7!G8lG?pgBdOBwhsxNאO-Cރц谬S灋[ j*zYYzh2g,UҸC*ML̄%0ib=FO[Tt躗aү.^y'dLa69%4q#I znGc$Qt^UMBbuO|bI*,D۩$w%y?ydz.RGy 鬉򅚢7BbRS_L!{Ԓ$WyT5iߖ"q`@ T_5K3wCLڐ&֍h ሦ1"~8ӨϲJڧG {Bm{tIr0x=F $yĠ/->+.޲ I$>2[vdL섿rư4L"q=D#v7D޽E١ALjWXklZny W9W"u`#PagtM#3A@Q"*ڲ"jr@cP*Z׿B c t>2g~ fLWf| "2?"BOx|o~T#+NHm+ H+1FWr&N+7)h.b:egYuz ^- ~b$CF'GH!b@80Џf-@hwٷIXg㷡+zX=f˴}|9/ |zI"| GA(}UOq2-h}z|P^@vj$4e5M#\c-S1~Tb@)Ԥ1~"I H*[Uk}pɀ$cvmikf`\()-m3!=}}a:Z=,W$ol2AH{)J*AygKR"(_F)wG5>z4G1R<#cఄBXAhÍ; v4G7r_*%fp!&a%_5*[d-葱P:]ow}yIE{& s)[z!["YnA'gimxs7s>RY,U?r&y ,)Nm:|$ ʠڜ/ghRwMJ൏/, scit2ެ+;\,D:h/^*U u-o ZnrI]i~nc)?:ЇJ hhG467v # G-=,̞JjHlr|4*)F*8Pxq啚)Tea'hozFR避?zSn@+~~+1f̫ǹ'ax+L޶ zp{&`-l5jix]m^ ƞ2`+Dp˵t<T $ߊ^n-fjh-~ -yE', ѯ[ʒ L߹(_ #o{64Cc"\-chq2:e10"IHCzhG2$ұAkꚝomFxYtKH!,yqa\C--X#? R$.ub!'8fͫiBWtלL$:q??FqJo~15WNzΟ& }&C xD'AL^zO.9>@nHy.b, >"_Ct]/.kfwbWo\cQp]Z44BS/h~w'\_~Vn`EEsvВ]eaY @1﫞U+']&}·$5tm,$y"-GW/ ߑW]]IJ9As_}*?Y (U}R5 ojס1]w7-3b3>hy ̑,gTXq%jvmňu_#nze)YQϚ]5x1H7&=POvbfF,PuV7d~X5sLPwT@GE lMn=jث(99B~[A 'V6+mݤt GT .J 8 ȩ@@3nފ{#G c)c8I~h#xAgg{L!w_ZFy/XDŽų{3W3K_{*F0֩wsWW޳rK'LΞEVro^R ZPGI\lՕNb6? ՝}IC<ҬYqMt9JԽ1nWpYk:S厬|aկǮ~粍3H6P3xOsh?ihkzޫyu3L lps7grk&]=4}KdXlH&wӁ}MK!-~v\WHhosYsk 'zFǫEē1Q3Sݩy)¹aY,i_ HƄFec6 kDլTn|at{D5W6WB;>c't4y|*|ۍqsF,0+sү.1{o&g@uKݚ:ki{? QBNw$B*2ʌmxuzHU'__Ix<_B@%?T}y l-Ait赭g2-mbbPp?9,ybS٢ "6{1Ϙ 2UROm@1,n>Wn(_Z9>-Ν07vv a c9HK dT~IC ?q+n$AkQJ;>ކ`|I_\,/I 1myJ(p j* 8 8vTGL`M0c. R\ZId>5!(P0}`yM_,a_. {bNoXl cl0d%-_IcX[mE>o~΃jlqXX8->C|6̵p1'܍ qa ^q|u=y-g [( :8X:Q{q?U5Pl{Nˀm >2+_1i!9r7Kek m@xoI?xϺpIa(as26~퐆=Ԉ`j+ea~䦎ì F^> +3,hўv@7!tĺ&^"p^1aǕ:M4eSZ98[ m/`r5'[l|f1EC<^Ł$l C|f@]=tR7P7䓄R=W(\C>rӊ%{#Z fDOǺ}پ65F VX oFf;Ū`4fFO&DS˾.c@dv. x὾Hgd)'INclâEbs:ɋnX>< [{{XB-~*i*݉AuCua (h:;Zڬ1@g>Ы'ؔw }ˋB=rNBB |gnLLPmwR4@g؊J \1$ O5Ȍ#`b$S+=-Aه?t&-C 0R ݑx?+bGEQGu3 Wdt_Q`g! C?>>,y-H ȏƏ^ָwrDiգDÉ}AbWf5gV)z *}@ѵx㵶M:7lPteDYĹbF> +C%EZ|PC,ҨJ9i\#T]o{+w,'/ &*R.Xϫ] ;.*UP9@㔃̳:>ڳ:F_'Ed$t+2/0w1O@5 !niLVJ/(@ȕ>\&g*5rO+r} ɂА Q̀nCFbA"RǷbP{*L &zr[ve;&Kv2Κo]E;ӻi~8;Nwl"+jbi*h!^l9stk y^hd1krS=nކӼ_2jEJ&jSIl׉"!mҏ:X_JN2A(W)cbdg~9|D(U4O, ?KgcD%g_~sݭAhW9Eh's.n|Cze3^@}x77E PNZN`,5=  d7cv'x,e_nh&%v%(B(ۇ,_8Mmx5Q% "& A/F~:X"" &}] r?[ T6ު7_%$ZD«4;GsV`zE̩9Ÿ'c;ؓz)S#b;Bš=q>4qz'"&/k{RniYSvoz _x\!QlQ9$A%Sۡ$H=nTzzZ'R_E«4'~mm7_}Lӏ9?}GP,oJ1BN|qX= 8@])`Iiʖ[ o>_HDGT4=7Y& <>Hp}G@4)^/Ff_.Z /1z>km/_\Mv:kU6lݧa{/#ptм[$;/X\<4:Uoĭ`Rhq0C|bs<+~(?XTշTF1MjZLK1:tq=2T99)"P=}hᘼB9l(L㵕T~dn6WJiBh;>&0yXSgL!z eP';$/6NwRb6m+/ )h(t璓FXpbFn;dFq%&_te;Hx$N,o?ރ _˜mAB὘ίs,'BĦXR,~T HS#IBо - sqsFPr<+SX 0DlW!2pG93>S5tw ˑZE[g[6qyћu: \VQG),?uspjr9~% ?szm6η),/s}woݟ x+[Ի4l%b`ȫޟ}Α`#td`IS[%s~+DYc{?ؙ$>0P=X&3z䷽CY*ۦM &~52ژQ4BƊQ{pQ.w ƐaQ*F+%3%Ƀ9JNSB]A U\{N\/#^΢xﺎM˃8ܭ^x5ֶbCgu/ =-GN >`C`#᳷-ayL$q;%H 8ľyn~9 S1ju"ȺDlkwz߼FAE˂Vv#tlf̸(L7'Ds-"ZV,9yd_9@v*7\wh4{ ҒD2ɋL) )H` QX|6RNAbDW߲^Au?YNh(jI*&{qpfH+uu(}a\Γg LH[7DR"_+됈Cڦ*/<)ek)ـw8L ѽVwy }^$) XAއ@X@ 0 P_ڽ Etގr@a9`jgNo ih0hE(FaヲzEn$1lsEW2A)^y>ŷ]^u :i?z}k|ߊu%7-nP0.PbZƢ.-YJKRc܏5pPw-ޙ"uܘW$3 8>|j"hP؍X>,J⼃(|gx$0@bhj|<^YqWnP I#u/O ׉@=ť, dvp>Ok @c7ju_xh9(D6|I,È; [ii*s/=Vq6Cx (EFFь c ;fJX^{KKcY;eݾa}6^ϑ^xj0A:_KI| sٺەU jpI2r7U8ڕ$^mTZ۳h~1A B,txC<0F0<m yK:sQ4Nw<''czS9Yo QS3 u=af\dFq`*g@S.Gbͬ۳ 3l~8^BV[ i?`ծZBrƮ75u_[@פC!u7=O W_ڼt 놛|?kF$m ="/3GMRYX7Q%tODF7wPژjHnnMA>7"\klMpa#n&<39$zLqB ifL0 51'rߋ0' y*Wl XW+tQ.]\;87{"^ wOopOU/&8a6Icb;JoLly`S{7g_8yup9Gߖ'̠`+i2E~ٮ\X5MkgT?YݸʶV>Oҷǻ%H!mY_0FUV{464jCyJ6I)d+5E|{6AsìHsi-zڪ>>Z/XAq w>\ guDv .?H\M$'X@'p>c4vW7'Ir.=*iև rl(S3\b X iJ˂ ϐ }OA[/~i/^\`]rN(M! D ,C{qüa\ٝC & 9rAlT 8$d<|p Sª0\[wۛ?9{^AS+- 5҄/s04usLdb\# /hsXj H:K=sMguQ?(2>bd|WJ_(EU.qYRJ3 ?bJ0}px Cs0Fa h#r{뮠=TmaH)tˤEТȯ%ލ`#=6+' 9&=v^RrGpM:M~0ETz_ORcD3\< g2dq*|U\KR&Xn\{G= `VO |>>6IRݢ7 8S =mMR<%V$H\6pۿB_-~_7wS֎d/cs["gjg1ӯCyT(B/J/ ) `ArnXUkh>IHBfp X8#CQP.!uv^;b|%P$&'dPPRX& SP\]<="_q(r-K AB5"N rL222/GTKbOaolanN0^ 1T:USjaF90[H}|<>Ix^d8m,Aƹ L$;P۞ Kj>yBbKL(սqW! I\ A oM"f|S3H! ĨUU ;aƋ(wԹDU~JHxh39Ӏ8e^c.2<؂T *-uq\}̨O+y2H m Z%#\3Y<2|5d8 ~]z7B ߒ4m(% `>#ӝQ! @M~Twҫ㫾P"NcpΊeG,a`LW8J},e n>+FU gb濉M$'01V+`Q3NYgL1!͗aM6(EI{Nodwn'Jwݲ: þ]'w+W=﵀rK@v#b`*\m SFm–ʝ ;u*HhqG_DOB(jShgt\"qnf?:^r+T{cb,eqb#:>n0vnF&QJhp*;\fű|T:Г A%8I==bcWH ][#Ԋ˥ 5 ft% %l,Q/nCan@c#YOJfiYB~8W IscbOjpgD :}cFs" lyѻ(+0׮T1N.t4W{O#i<&V5Zr"(\I+1`Pj5";X;WY)+F)eT AE~ qlcT聦g%K)nn80'=0R4W}p.QQ)&u^@.%eM&zN2P!Y M( = VO8wkd=ȫ/&&>dnS恑Зs|5oHHbhIt@.e]åpA[th.e{zYZ 7?Z~PD\s:Q.#˻J[7$MQM}U!'Nt/q+1)t arH8 ˒"J=n,?eT O<{z~~tԭRE[xSvx~ b_$J{0м/FjwX C#VzZM@hjT~3e XB5 ub(H%Pib|<v~mxk>_9%$&ճ2Z,XnP^w78Z Н_vE P=XEڙsZV0 ;nD;\8b(z16RZ̴(wuw}p6<[zd߮|*v[o:ts o4˧P2Io3YqT܉U[t峷REZ-#P5煷;nQo0-QݠI͌0B֒2D]K4is ~H$ϏZ.=LYкd8>4䶾KnY~&Ш=jN#9GOL6PA6TRs׺;x-~I||6,͵ҞY*b^6p;zA4ѿ͹_6)qF=$J^r3vng}QOioRqIQWK AKWc]{+xO멷]IS$WJ/yZ!R:c$02=/IƝ=sLBp̊4޸E^d-l:Cyj_g0a3`R6?*FVOeqc`N91GMmG Os6["s6 ?P5\,(T^cD,zWr *kf GAΧQ#I2(CB9ǖl}̖-tUG~s[ayҨW٪s"v&G=t<Kۤ72x؛4(9/4)/´QiwD)xe祐jeփgdo$]26O;" ;k~?Y98 @n+p~Je%ƓxLNwVO>j{ {|9f&r8[ADQSc"+YQ*SZT |d<&0Y-9~`e゛57𲩧pàd,Ѥ [?DeJgM $Xyc뀘qE7W֭JD r#ԝv4vHlŐj|z@K¶{3 y ԖDRqoy#&<(&4:s=[C h*UՒw|wHsYЊ(^~CխqSOZjEE_j5 :[Fw=o-?r` QYcT* nAcKnZ/=d&=³;-.7&לn?Gs#́\Ad ڄ`EF͟Wivu{2%?|8ð5**7sDsPou~ه8K!^oR RB˽Ac( /vBW_f\v58[oB`Ԉcfd¹voN1rqԮXdދ=⺳y_n%*i9˕*yoaorSK?WO&Ƹ3^JyzqP:f}k'γF0-T=ȝ.G RڧAMx{%bNUIOqvma;W]5ZM~z* ̦[ZYU^e_w8+E qrVܨsT!ԓU x\̧;whP6 4{D*ȑ,"<3;Ɓ2^~*z}%j(]M#'g&5Ôaj"wJ|z>J{ʕ2tk:bLυȠz.%F0Ѕo)Ǣ!$<4>3D"#eZfϚKOm{90'ac#}.@ƕլ}GܼG8Qj{gT eWqWY^ 'aߣʦqdp;BbJl2UDbvy.;:DpVtI%Zs; '*ǔW):m6n? nrs빴q;O6JeAq>ѧX٢V-C&:_D{Fxuxg87]t'>VZV=}W&eG¥\PV$njݡoV>=r%J.֬k[P8 X5 5\i}OymO4? N dV'X9%e~WkCjpcL#D !E^ڔig"yVQ!A}jvn-*#2J`W]weoƣ(RߐsKF^ a֔ENRG1|3vqZuzm֣,Ik' 7/ʈ2m& c@C?}~F RBE,_4lwL>)adȅ s&~K*U4Ȱ+\[+&s: tFLJse|_ewC9Ē=4i g3tmJjL1 6eki

tv gEO ][4U'AGwVELA;m/+m˨?zQ&}~Kf~b?u7ynV={ [lj_m>6 q y>4{VY$2A(?I&QVAϹs1꫗sLo,gFK6 _Wp@ܤKTiol:.ߍg_ 6Pi0k06UJbb^ m 8xQBjz5C^ sT3\3̴/ Awέ5QH2. Z~HeV""=9XHj5ZҔx K՘rDax h"!֟cI:ԁsO' /Ie8N`Bt (& ]5.[#XfR{xvd26-C Q7V$vy_B tX<~ꦈDSne8 ,ե %}tNG_ 9D` XQk4il? n`@;q ߻LG{m#C`y*5\'oK_WErȳȨwm{M]ؿlZCϢ%`M񹬐T'VB-3p)۱BL꘽} f&-U7y& ʷԜ_B&fWեbFC:xJ/<31װYMt$*j@GuML* @I8sM{4oY%<6uM /<+|UQpNv]c,$^_5`'3z]Ĝ}4"M&|R<8;Ld|ND$B_Dre طCT}nCݖAe^}=Ո([MkWn ԝs B.%7SX)goA*Ϧ>̃`?AFn-$ a^ f V~c-x%=|7Ӓw hZ*gre.iS/;~ pc_G**ءNstJ=sq=mbxs1% G"9k'x/ PerNQ 1sG ۡ ]z#A(g7Bel[x (E¢'Rx~gb[I3 . ?SI޸_kSі< '|YA=}sS5+kw[r8]<ٹNgL@\B+q:1d$L~gFmMȩy/N^{ hQf]=p 9݁DylufBx'8[zܩ4RU\-ӌвB8Qr^zUSN/va{fW@79G(M%):?O<߮u7 Ajgᰌ2Ù+._ecٕѾ{_;^SppV2֦9N}w0_tg#PbTpǗ|0:W(1}'P>KS>\>ǘQDAw{/Ea'RbGj|wQ8ӽ #Ads.4uG}csӲ!S?y \;8uZXF މʒ қq] cr(Hpa(VՒ}Qu'bcp zhv5t9C9@xKNbgh4a:*g}H.mAņDD<'u-qM 2{][ I1 cI:legn@EvZ̓CNd?wM d6aqt3׊4>W6_I.l˗J v ̷} ŅU c&Q"apA !2WT ~uv@1raz@q:Tᙞ9bb妮6)[h~P1SGطx`.cL"N [_8i!wzh-H%-v5  I#jof%_0d v}z<Hf4fٲd7?*e|j&mK@Su'@n@j`tAsH8a՛D,Xr22%$|4dX!Bn >߸Mpv LY3;=ӅF'!GZYhk5.|%bVt҇ɀ.mfř(S_P5\Q@b*`P{GBCj N9IňHD"GHCaLvHUP8m m) ҭvIK=.Hɾ~ɵYm Q2m୪*))d'ߔ7k>bC6'DTu+2뺬?'V.v>Wм-|CXMpӾF^zkzA73+ޱP8|]g6 N;s$wY[a⳧wC|ԄΆHZ!#ggLMu; ~3!t]`}Dž"nŭiuزYakk_wIfu\הd+Jm7rm_/LB1@ܪ.ůMֶ;F&7VjgƬm|5KGIa;9TnΑ_V7:J C4xFE>XyXoJ'L HfL=1w'|5Ӫ_ƄF 4~@ߺ$-1%SҠ, h%̤)3 rMuOv2`qi {J_j)`[Zۙ%""iToɠ9N"F}Ni>L-v@d!pӶ2OdI~6D!qt:}RT f,%ý<#.Zr3g"K3 -= ~-՞'TT6En"7EdarKIoEc~;Y3 V+RHs V@B mF{A듍eSJbXÓU! {k]'4&$7rx]RNG{x ljźNnae@9y(7^H{U1,CW9 hpsSP\qd<8 O|ޚCPp[8kbuRE2"wWT KHB`~z[OX %Gr*lƃ-Z~: zip BI OQ`{u0F?;˂ATl+ .NziDgGq0SIno~EczFOfS)-q=kxgw%Rd[mSqVR;6*ew|8:ʼn,_GjY^Ț&}U^`]}ff<\5u}L㰞TA9k,Dj<^x >!@51y-Ђ7}"Ov_+9&<'nh (OG[Ffϼ!^c-# u{gծfXK !]mT*!\iD<~dnx'I8(E /cn4aK *-\}8шfH"| Ƕ,`8b[Q&?8V6IID?S!gzN,u7PjFx~1#zt8)!d5a<`(G=㻐\=բ$;ϟ6̎my&tqL9 COu} Z3}0e=(noo|z~)ri%w ^=.Jas-EyyI_yKi?/Xۡj>h|N5⪮hWDNqn[OυoeW<kpMn+m ;֢s--O!yT3K|,l?wӯ* 7e sm,Tە?`Rzo䲖Ht 1ۙvJ\Gw$2 .H ́8DW^GVTR,Ɯ9fR,Q'^aa4@WO 9HprVPюـA,xH";e_YLܤMBNk=vy{aĂ` ;B􊰪\osTW&RKR7g~Tz 8\pG+XSMD'޷9g:Fս@܎W+o0Kk^xUdlR߷Ɲxnp28Aaj/5D׎o?ľO$8NFqmyz*X"+lQVR 6OHl= mKR !g_m*B,0L^ZVDTm7;^I.u,b]\PcC|ScTj tH$~|"KyGKhvPPFRA!+@'&`"\AGpvqޙKJRF)%>^9p[!\9c8V[5:<)W'"~>;#xQRƑ 7+!fvcUٜ2 J5b~XcVxAE_)iUWx3A~7Ճfe%|{Fw/@F.'}>O'Rg5=Gz=?W]v@wHoDB+ޭ,r/Bi#_ηay1Daʳ+)5KaK[z7zeB'`3JuX}V!:M>?v5U߸'ܸ]ϑ0aEӏ2\C Gג##x4 }UԑŮ.C!j3EM7w(̚U<R{*CGU˥[s~\]. ͜_FM% fM=8}m&"5FeѴA! jíDa+ֵ9F!:A7㺷ı50E1F*M 7Aw^[utrފ2Fح@9"=#Vl1_u4 IX{e9@! Vzi ~k&1a~M8N*W#`]/= P03&u{sa_qC`H{#x/3cV?&j' Xa?#5"E7"o,B0#\vOm^)/AҩTXw_$^EsXZz4ֽXA4_2 &o;56L2*+*hQiRz<}9Vɿk>&/aP ^>xvK=$λDRVlĊXv Ƀ}ɑP4uUt;YpV+^dSBrО»E&??XW'Ӌ&倉zr ˄U06/$ƼR e”' ͅGΑJT_oF(N(fsG 㧶*0@ \΅߻BPRTCz6†GOJ<L[opfPzJ 6dc]Z|#7zZȢN{ʆsnqKx* ^.SI>`i);9vp MYHGҽW$/|tV^`i%ۤ#,Xd lHo sFU'^8264$ytTjQI獅$DJ 8#P#!n.#+J/ra 87Y7$M~5ykۚhR.i @Ky  TwA ZmK`d& ϠRaF ==$ [yJ… Mڳ!#ytt>$쓳&.!QKTM/Į[cM/YYq MX&?'R\ wnWK/w`\XC1;I6g#hn2 mz*R}ݺIwi>`63^䭖:B>~b9bB]olXTmj~Qut#To ~όf6UA(1foMTuH}- /)O`Tp.1R0ұx5Gƅ_;Zq.cn Ӱ\%(=IPe9"5c&`3MP`@zCqgE5ckF^ e2䦴P GصKMa-nآ/)Ҥào# RDW1BQ3&Ib7U"?"I桋-# 7ny>mճ U7# h׿`XH0I)pb;? -5|06JR-eˋiJs仕.gD5f{⨗j@^.TAr׳c\`f֬%΃ A-Ct83=ƞځqY{v`Hze_v=BYj7E@a6QHHҲX/fm\h[{Y<v &:ά,I+6NWzr+-tFw.|G*J|TqO֡[7.q 'kT闟|)WyŏO5 ;gF#Wő@g]ViU?wrHe#56/=*!<|S² A8Q`6%Om6ֳa&:pFI bc_|Qj{= /jknH& פ0$#-$rÔŁeKV} }1`FL31XK nDI PMXx_P@NeRok= 8 c (@ȅ!}(nI Rv[qpT};Pk*(t:0&T&VKPׅ&~kNRʠ%i:egx&'|cI%sK9{ȃ{hՓ~­ꝣuaD$ k\=b;~aؘۇď=*&l['gRxv0=搾ڜe 'JkoYx)zΡyǚzyfgN~CP T=f]V1GJ#~!3E̍`P8a f sZXbsiADˠ(HD.rHO!n.&s~1 =}X%l1hv+ ylmzќߛZ\1hGN>V KIJ0z% `3 "/8~ !_z-!#g)C\\Er [mK~<J b;c2CDI4ۊvRX^r <Ո%O.QL}u*eJ{\ay*A;QGOY،U #&[9J.P$"ƴËe% ӌ8jY[ڑ5j"XIR;#EbWI-뺻Z08#2Zz|?9댧XBjm0]tu;ytmOH ` ~6(2Ax|ٗGN{Ѯ0d9ܤ$d/K1NeJ$83^!)d>=7wqQjy {GY#=-Mqpu֟~3p0 %y~0W v~sbQ@Nr97)%ї;i  (E ~Ad:;asr3[U)4Rܒj[w Abj: ltQ)A&wssK/s!Qb+U?ctx: X6Q_DhJH`fbJl` Un-1e6Q::gG)mѦw}މQt Uҹ:{D $j`LHDZ*ëb>&tA pP 18:,kTAT JOPr].B|Q0(\s k/pKsj9xʟ7xed0z5pƯ/ );\5X:!1}H؈exbVZ JلNryה!a D6h,T5ֻ`@0hiD*k3/U+,[ Al|=|1[ zp)$MB:fCGdV~^&Dd黤#fZ,)%?PAp& L '[9q,mgv`7ؙ{K+n.W(;fxactvdp*o北GV,TX4e) <~VAU?W}1 6_3 Ht~xrQŠʺ5ygRZ13/*n Ά WZȡA?r9pt*\9V5;O;v66mlݕ+С?WE 3n2jLtAhT{L@cw]sdK ~|vVanIG+?Bl`Pd# pq#8,U?txN0t.U Zlns7S +ڮ΍@f Қ0҂c|:ƸhG cS_h< P0jGFh GzH7ٲV"oBA[-VnA hMw1V*ݳV5!|T]<:\lmHs̑\@/7)Ü#(%e%+329خ$F6ۡ2g%MH~TOKQ`1p0\`E ޥ"9@PQĿܯ27hawaQ:HK s KH1lv2IikwC? gs~FeH/k#A7>/s^zZ'Bѿ+X1_Eoͯ]FYș3O%(G<>I7 f7JfԮ rw ylB꒘X>< g;?)wm>O')ՠ|Ћ#4_ڂ DzRu Ѵ/hz\Pnp\: 5 Pm6K/c5bu$|ct$;9+`VCy:vX)nԭ(Ov.Aބ]7X8V *at~ $kiBgE& } tC-Ը*/ř ],:²&߅^.,nptv:j |'BnRsqE"HRs mysN'*ڼ':Ψ!yT@ ֦?Rjff{9m´Wс{AWƅoߣ]t{LVA@%HiN l40V54ؙ! K\шgUbxҎǘzO) ˙gr˹-k>ymF_Mreh)-E|;Wrڸ=m"i=78oUSf92tE%Gix<Ӿv 0~xz _k%%Ɔczg=<طoؤi ̽[硁KCgtt+:Y7\.WE z32uu̬emMQv钇?j8v?ާ"pRQ՛ճeUF̟?GA-zw(1_Ka7۸;/a_Q W Ă/]@4}cxǍqsNӫIs͸6X;ĭ_;6Xitc­bƗlj#u:"O?oclsKxL7K==s"c|9sMOqxf\Be䶰cR " o&o}ޥY2d|V?|׹=H6;{+Oup~/ݸ&_XwW!y&-+ DE<5bo|n:/dh}*g7?__:ѓg=p"iG",7=\rnWG&,rnMqŒ#JphVu$]rN]@wR^J`H7Xu8{ l0S@Ϋ<5 RԁF@85/vgmoB?6|aUM!?,zma?TDƹ2_$\ejƑ?x%g@cuNU62μxFygwJ}}y2>_p@`t^4=,JĻ -d#[ T( A e-ouA5´%%9jL o"佤8g0d WJ=%u)c&x֛J[ P^ bkUbsEaafm^*Y2;(# LQ{Uѫ-Fﹳf~#~唎yKsg#RdjsΓ2jtFt|obe_ek]qW=89 j Kƚ\-vQW2fkVS;巅p?u~s`0wvY[ GaJ̥EĚW#OUbA05ႣpiJ<NMEњ.3t2"t^:FwoLeӦ ӇI.8CQsTap#j;.th;dK~BSRv/TٯԮuTh'ԒcI~K'I Tc g YuC+_O7E]:o>hdG$u)?@+P > g5AV4OUl@0Vô0~K&|o\hm"gtQcvE_!ԳwS&09%-S q@:P5 Z3$Gdk g=:}ӵyi.4 OBGuTX:qt̳JT*!Gy\%+?@ 8@|BlFNYG,|ս;D ATf6^'k$^Qc\ǯ314_ocE4Qk䈗v#7}ZDOwuQNhC@s'a o gU$2[I][* !\=9  ϾI3p*ubUwur*`%clLٱb2R?DNbfXdD+zrY6U5'!\@qȘ;~_l\4Sbq/Y GN'H|_쮓cys~jΞ"d(pؤS0&-x<DuRmoмD:) EWhm617I  B,N8x"տ* 1#,ԝP ||BʳAlXoYZ,v{jV/Py9-nb_yX?rVRS s]8EnÔmVi\f& qPM b%f@'p){@5İehKB @lAWԹ J8c81ԧBR"Di( m(Rh?1,Q} ՐnԢ癍 pO1 A p\ z¢:9”E*=JQ3|_y3YV%==m)EgSY3/, D0&4-\*[ZkL~L@OH 0ǽXIK**]u++pȮFS'0u5^*=FH(UOՂu]`:xpD{dzlѭhF Tz bw6<=Z f7Qm 3A)mP.B^63q}?i-BvK9B!y!ANɍaxf=Uņfݦ|Js9%QFxgJ6~h,;-}O8k6!C>_H!(MP S|9%AYa&'mWdzrQʌg0_7| [HW=$XHY@HuہpJ_BWN*iL xb5\FzT_]_%IƑdS ~ɣ]3.(xJ.!(骰7 t3WsB)ea?~ZלK`;:ި"Iz?x #Sd|7)d8N!FHpbqk+nUf} oa)-7h'JeWP4)i^*̿C&Ј{2v'vuL|NNxo:!r,`R3%x"H#G>6Bp@pjGnv1[~\2W0+#To587%x@A _ |z=w[yɢlԗ(˶HɁ5ZE޾WeSu%ѤCG2s1xO\0e;H'59ۗ F]6w > *?r4[Y}Pq.,v?]R?^^ s# Ǣ4dy;+{T#weUZ=hإ8d Ù86Ϧʨ 3m29pK{KF .]q2 b8bO+9: E+3&f TE {Sqƀ3fEX˿M-HG@>suO-/.3D)zV\N2C@)Yo|jʵs$ym?bQ<4 WV0@Hp "Gr˥ΑjSo<㝁&SV5A9%nyI&YL-mjx8˾!|~䧪u^axZ<=_s'{P+ߏVR8kCJi]Ŗ|=_\jMyE:8ܶ4QKhI5`Rf>C莁ZFTYh~N1>#;1;>TDMzFڥn .OmOEDG)HV|G}?.+7K#7kW#J9癘C3)u[>[s( 9dJqVϧ?[])=0:<p& 0}u̍_|֠U3a|/ۤ&uIh^Nνá;;vVqىIaK]Gy);Dq={/֞ͷi Ӟ + .t>Qٱ8cL)m*y9+^G VEe8x6x:ǣ/8:{a"|Rhk)"$ͬkCҫPzU$`elhu=#)D>)>[j,vax1ߏ/ (JbM!B @mqym}|7m;2tm^,i 5)f^LI0b&Nh]LE!߬<{2[q2 =^,!U9Acu0 ۍP4G(N8;"pm4fR^LIw>׹rg]BgD{O9E~G{gZN-nR/I&IJ< q N۽4S`*F~)5g7Y ((_d1jsiCa7~BʱeRW݋cqׂ ;"$?-itǫPJnDK)V!T)㭙'cGǚ-lh 5MElFCxI!T2U]gx˱e/+m~ 1X@4Dؽ6A P};wjƁe~}l: s]IvqLx Zg^ *kP| ƨ ˹ )Yb'}812P~D~"nX+̆+Q܋>ZW Č[ X`aZ;~te첍 qZtX :MYC`Bg|TL!g28P n~El$r>O_[©Sgn\A?'CT(^˚UP>iBoO! rӎ2' /:{vgsoaJ?8P)-7'1YFX4 K - Nb2|}q xGLSӳQ!Coϭ$)c(\R/mlOǪuv&svdzfG6*bՖs m 69$%W2 ϻP$TO4ݡss]&zϸ5Ƥ{-Пx]w$5_ZP#)2ڐ*ۣ-$0 *" 4/$jӬt ~8r2H_ph;WlƍɒV q$Lq)k~L?䓭M"3z8HX8}WYso)Pjzw<>0ʠ "xTT_| jK;tjw/& = W9;Tcz}SGSn$L> @$ 1ҋ6gGDXRSX3{dBEU)+cKo}"\H:CK6 ojb:"F>mq96>ەR;(k%7><\{:FՔx.$OveY؄s<;e'nM4"TOnu𫡐-D[QDRJ!%`P'QhF0pc,UTH13v1et9HsAy+Tދ09x6U{]HCJh%`q[ u*K`tcL>Hrb}6ĥmbDžj%=J#U"9J{~pܗAǮM|$f^Ɂ[e.|Ss, 9Ip::˲ ԍy+Ks3x_t3OP +N;yL] DȯwhU9N%)|(qWoص=n֛%/m!w '"X]FG# Ǭ_/&ِ`[0 [|}4<,@Əf >)4Ni# Sꄼ^T:)4~0X*@#x}rwmzO9W-hGWxh %I~% q d9Kt*X;&ʆT"K9G1ng~L.RJ#AaU6B}CO#Z=6K XG~0_͡ǵ4'iάafg8F(,p27?W5gyK !iRSs*d3RY̜Oϯwezok4tsxlzHoF|Yš9o{?}mK+RESuRSf`CB= g_OFbzIh,!.wU;u4F Jdu,ޗ| uA^ɗ+U;|U ٞ;Д/Zkd^jh #Ep]<=Z Yl\7| H+˦£c|1wcex$,oU=# (qI?vD 1^Ƨ2 n69](V:5gخMS5V a&a,ePr r^TtenCXkÔ J)I?L`er`ʙJ*Z.jc-e_aKt2T@v9Ą\7Px59UnO@sQ|1C3} ypL T5mkDc{;+\o+On&Fgy)_͢ዖ.<%.\Thn-SHe^ m)8fثU0bq(ϥ/\p* q{A߼%xv&2 vIt}r HD՜`&NZ#g?X{edsN $+Z1Dtwn\Ws'v@E@~ bGD:C|Dپ˦rn*JY-v_X?WY$Oِo4iLBNHO~eF4itZxeJ&d+ߣ!@ع7&TKlI(#FxC0p>Ig3 BPBg<K;FmzH0mp4Re }4A<>6Ե-R\KsX.1姐tk9\BT? "#b5܁_tBγ+ro%6ˉ1 k1L*J36L:kx͇Ę\k%Zy<;ڛcGE\8& gzbD`h7GskyTDAyZN`JF;qQKF WY7b:A=\Ǚ[|ץW$>]˧ wA1Tvh ;ћvU章&D>*QCZ/)CDw.=+Ҙ=fǑp#i!1E5գL>#OdG"]C݄]1藅r/`ѭ*}ϼP]JD ~ߒeƥSbA]}v.\$$=]`V{#k6lhXG/bv7N$+7k (E6&E.LZY$a1IɉI2Kss+(L#$: h%b9Z` mrHU!CL4 ܟMnݪi0Dr  [sNtأֺ, BD~jN tT4Y*ܸzZ*3ZhHz<~- 6nO.`w.Ɏ%+*!~];gwTm$uMxj<۹6Ybw8߾0`;a6WNrJ&MVCh5{%{c!=v5jP~ K9t735q^34t}M3~O pN.dXψ~Ch d-zҗB$AaHZ<`ΪG2;BZ_ ꗾI|Yǁ{ `RVcCr /`}0ˊ_CJD`/ e.Ϛ>Iҡ_w@7I 2Kʕ&3(1fϛ.bLPCJKZzPs[en bu'ȭ끌@0-5bjä>ҷbks#.ԺkEs9Erc]U(S2qY䲎Uk72?fϹ q[5Dmp+lZ-O'>kbH ͺTB"8>QӒQzڈ 6aei|ANRӇb- ?vw!O5xY@˽,JLMG~G#m&iNOF ȇTۢ樣aڢJT7~A_H)uC%oxQٴ?$Zܺa g1ዜI<0 z[VF4zm'?uNY:}ݕ;T=Yv.宮ަC~ÌEsAttw?M9M}'b\:U\զmB!<ŇM|r&)&1=u1S/i|c*ߞ3yoXLnQ* QtPG+6fex'QMi ¾VnXDvtܘA>僁C?=¾!jb^mUL'$y- 5o.Yo7}Օ1U_wҺC+tm&S# } 7W*{$Ks3y_s+*G(aB[y9h>PB&Puvm]p<< \՜?beq۵q#\ ~_Y: gC\^EwlwOPbJd:AL&?Gp/7ٕ`GnboGOsFѽ|AH/?蓪1i*Ei20Z3RoB_8ϙP]}̚Nd2#IAë3=r1p@<Vc?ⱴ;v_}P7*kGJ1/;LejqP$S3 p?5N3^#h  f鑩6N:IE6, 1V4fΈѤ*PaqbA0Ö !զ,"O EД>^^GoX0n0o1aI7Ƕ-#^BՅ%6E>Y16ofK'zN*'ܣ)h<<шcd`*Ѱj(o#)bItCAXM^tJ40=})iZמ%`pqʞd3ɉ Xd盎=~|;B9Ox,ɺ> O%.(\rr(L{S 샑ij]j{F9%K¤Kne Up_aeN>W_ѢtBeyF $#z咵Zxȥ=p\iMs*p|ƭ[#R?7^K߽H(bM+S٤=PP볗/-in yƜ;Cy$h{b s΃(k ]Ik ?}Zz}6d㑚6*1? CPOdQQhHg& 0s)5̛|/` # 0طg,@T!ќ[)ŒE%bU.xrc֝e+(׌qb= 9r1vʃɲ"9kM\ieSZc\ᬦ)]" Ѥ ౐>CnC.;9 :"HTAY" %(щtNQ` ^ (o'QEP}W699S-=t7RsooaGLѼ4>/RkYG2\EG+a.Cx2Ϭn ZҮQ'bU' $HX3eL|e%zThZ!h6+ tV< rറm |`Q}-/MK4QB`RuΛX ˋQNژ^{m]bJpU<*"9攏twIcav])W,PYk{v&"AQQ)q"W}0L$xd+(  -|]_eQ 7g 3PpAi$?Hm ythr;ݕ0i{썖52]mHDۈĦH&iƲw$׼/7[)Oኔ;}{G^Z:资y8>IZt`pr# }#JEdcg_bûቭX}<փoXFMzczןź£ )tPl!-FqXDŽ$U\wr  ^|F qeizaܼDҐK߽perK$e4H_ sP"o/ɫ/-^/9ϓU:Us=ߑٌ\n<l)5m/ v0K2}rMSRUh*3o#YQ{4㚙 -C/uuX_GB&zGb}79Ō-Lf SȄF\OЛK}*oʻK!vHer ޕF,;ea2"h}%}ɷ!{A8q<[#Z//_o{Œ]L Z,\r.~,fJk[PDGϚ|/_z }͋NqM~=$5G=o^OAvGUq(f| Rz'mMMUIk?|2_G{8b)UP$h$=ܖ監ka.cLolÿh(Yf>A#:CMZm46XC[F#;G7fW%QoTkezW|O v Ril/' v)N%u?g8?깩}^|jt@dc>Wþ+Ӄ΃Nŵc]jxWml|TcO$.ル8/T:.ҽ J0dϢnF ۸&b΃С2fp eqrA+FqZA,Ԗ%k[bQ;=!O8P9Kwx 02ىS*b7tI~"4W?F覬/.e3J}nHS:+}RZO}sȀc C^zs9"Mmt*T1ިZDWSP/fXۆxUP}sr~wh+'S ?|u0_mpr?3?NSo]TC̸gE楛()Z  Wڍf5%TC?|D poz.Os6h4+'ˏRkSD=lZxenۺxwXnK|C\篑 c]Yc-Z5lM}n5F -~qnmSKܒ8~ⲚK.P H6g*a 7Pԏ"{wuY3독B& FQҊLϥm-}HBrtx2lZ |f3O12.p|iiyԛԽs-Q!2pV: >èIQJ2.ҰdI_)gJu`t؟[aA"BJ21cPʇ,wQhaN:Bc> ԁU6k@`Bjp5e6ߚ m}< 1T\k5|KgJz ICdI]C{x{F7f- /Y*nZ<$_f,n|/Ȩ+Lǭtu%<4H`O21% & 5Vz gdsEVu5(:yvEx y!97ބQ=<j^=}u=۶? SbATgLŁC)=zf҄'+̸Cx[e_FD:z#Y³WT wP oL7W:O'fi4HUX)`G蔏YVM RYS7@3 CfBԷSdY\lr<fC4^;=N +1S'/nZ8gʦmKsxUgvozC<(CCP-vy&EmؤOY{/yjf02oA nİzoz]rt٧Z1ɨlV U{[ME #^Z9V#!_-σI||=rE!~-Xm;! D6* ŽfrGި# >mtŮ@)a@67[k|)K0@rN8fЮ<:؍Q*ߵC!٫0_م߁B];3z*lsq5x{%)?C_>$HJb*;Ouaȁ,Q=l#.KMaN;st/x 0A&[%ypR  qw4:x?CJZ0ݜKv!RXʎ&pWTт/@w&Q'ːcBV8<0CZ|j \ћ]If H E^=(3`Ư8tqWmmLa[쳀fǃa#?32D27|@#TX] lSp\WUzCf u9/bոtm}3:q O7yZ$4 %&ɮp (ݻr{-4;lit\c0Fb0> ھtdo?FB~&ÏL֩gEaY!gKlN99%uM&pEh41T4JO5ٓ-&$So!hiH픜PYcΨ7 (;k~~(Z (oFs_ h7{ē/#3}g]~\z )䉴{mVߧQϻpF&tY5sf (y 'ɁȬD'8QPz4d9 r:s==ee$udKe>9-mPq+#:T0n V|'PhEQwm&JLE 4ʟB#{HP*ƚ56Iw]} hZЖ800~j_.8#`xAvQi]Rv=yT氒yUM͒:MGo>[۱Dnhe0H yf&* ]s}ȫl6kE!ljRmǾ ,d 3Тb3{n[V93Va+8(HϢϖOC\)7 Uon}A鞨 p|D?"v''=eYB-!M _3ɡR~ nE@/,htvϯ5ut j̼nQvO0QO7?x<05/0'j3D^UК!Q:ݳ ?DӔ6x|ց~攼wWfngDA.7u)P-\#_M{#u)P=gc!';pMBLxjEg;CbC1؍DŽ`vfx"͠Z7ni4$K.w5_c{ dg+Dvl\ݨk% t>6ԉ?.N;+h;7 3ZAeeHʵ{>}Z+wUG -6yFzgUb}tN]"X Yv>/d$X.xl3C H'HLlM\؝e}p][)6K.4OC߸`nWq$()85wyٍj+Ts$F1q> )T%9(1}Cq^<:'yMve׃XaN \ Q`:=^I,u. &ٮR($]> cA̪Wury6x~R^OZyQ?k z\%ّD}<#"Cz%A:/P! Q'c,[#uxS_t0[Bʪݟ8V={q01FjH-'"̥'Bni('%?ӃYMbslnS cVPAx hnzq*xMAHI@OZzZEaq{F)Ne*zo=nHV/Q Wb2R>4NE\ XgPH^$sha5j5 }XKX(mE8n&o+s^,yTM?Au =n~%3W,ZCg p%}؍2n@y%1KQ+ܩjG>2竪'vC %FsǣVvS#3!HynD\;cH,}xV>*=QZv~;5UȱeFIP]rL0/+%[U]3eweLJ5/79O}Ϊ12W"\FA=cY|,3^2C+摻bJ~ v:؍C܎W$$GH :3,Qo6ZLD| f,G0-v>@F6v/|U[͐=vٿіcao6w#<$4 nuU֑ (HQG Tf<Ȇ׺,-=ijO:;X?}T X1] L~B%bqVGb4l2,86HG 5 aAG*O4Xx•4ISRPh&RWgCt-O |SSNk]8/TIjpi72{l>JG3U<NmirD#6x Ku=lSt)}hfݕmXh9O4x3 iwFFD2]Zh5CeJ}].ոt,<}NeX;y3qm헡'qN;aP* >?oNmK^UYx?t3&45;u#noҁlGZ 㕸x^ #Z`y9! h^Sqf>12$VhoC^]~i ڈ7Lz,.SȔCStیClvjp@Í fVDdAaJе=\xL-]U $EX@9|t'ր|KcB3b*$XI16a+u3^z={q$]յ!Ϳ?w}j@Bsn/pP{e#v)ߘ,9U+*u,opjv2H%ۄ>$F Z7qy8 Ev{0ltw_!9Rw]d+6Vk,c6.Ixh5eeHo#:U2b{aD\oޜSTuZiڋx]=UG`NDmjŲ,#?( 7-@7+v&èrU=nt-!$!pm; TEJ+DB*9ȫ^z;sПť;lC@UwXVV=Wa#y;!ֽPd#?G$4Tw3Q̓1yJNc1 "hقgb&ّҽŶ=N8Sg޹8ٵ0k C4ebWlN1oY~?H@ FfoNv@7:Kl(fupA \cedTw#)qE^SBo_CNJ͂bC9uG,7X<0@DQe><KRxA5̛ҵ(KS׊#$%z67rEL38TɖL[3TuVﭘ@K1 .!d@&gcgC"GTog.1n7yv-xT9ᶛPKe^$"ld抇c.[A&512$pP}{nna&{j꥗?&[g Z^=ZUSAM㌋\`CWdeYNE i)=nx,s+М(TLF / XT :khsX_ПݍH(Ƶb[`F#5q‹jpQ$L23g^K諘C؁-* >*78z28GU4x:h buq8e9p%I3"J-F 1V~NSU!\{,=ȅ$y ͭ:EXDznS\<]ƫ 5>g!ąKXY?(V=o]FϽd ͩW&Mχo/2&@ש[+x^d/41ex d''`uǧp3pNdFq|a ZidW4m?!zFBrf##F{)H\%${FXJQ$n?_~{=$Ip:r:|FTח0w.E9ԁR0"og}.GNRTa+0 HE>Dw'1iF\J"w%_.⎽OtkA|qq/B}^m/62uJu"dzE# Yٗi2ra#c?Ěڠ@Pb 3&͆-wD=ӝ_)w>f=~se";9+wGOJ˃6 YANZ'mEğrU6Zu2P vJԯ/sM;.1ukNuf 9UO@JUq8NJIfNxgIGܩYns-(u.ؤ#t>wK bmi3 /v`֎/x7t4GXmwY߱%ivDZtj)u ߗ,LN$?j{hߣc,lf148 й64#_GXه `8l^O,8ߝ^S?TDpy.IqQ/C4pcLocbUm|aPxP:̪c.gXB{.^G[YH"=xhC 쒶.=Jfn,9-^y7L;' hrΥ-SVROPe[y]hyKK2BKG>%f~~K\b}ʴw+z4 el?c (|>pUxe@w|eݛ=oO"2n@Ϭ*kH[z斺"ևO3cٚD TaߩvFu9 8L*ؖa_Z~R$x~eԧ5^wrutݴ[Ã٤NhSMhqN2LlQphDƗ.|A)ԏ8b -n4T]Yhvtw+gfKj$ae+[39_]=ſݱ OHK6(igښ}lMҗ{FUo 48 ̎. Z 4Qm3<0Qie#KFlރS"Qr?5Mǿ]6qӲ>$xZc^h[I+FMȜkbs.6R8y"iy7n%m!s F+;G&H~:yv?*Q7 $4%g;[to^ rjAP=TbY _ɛpQhptGðQXq]q/R&MWoRPrpz߃#رRNjŀ4K&hA9ƞ|̤/Q8>򥠍!M$P;){_v̻sbS~gJ׌N&eT8_1E+lKQ;Al54ѐ;$Q+`bTSӆ8(A*rtGs֌=/ܱxJ[r tY_/F  ބ8~^FoMCM?g4|\F44Qe>^700iOc ,FDH{zB?CdOhB6k ־3`b4qsJ!x zg G/8h|~4^ goHiY$K@  *ׄ/+-#5x?쬫\V' ma? 4Kߖ@0THq1>|gmZᖖHH{X)8hȃ1bE2%[1yŚ u),T R~q6gڻֆFitI$1Bp@ \EEh9x 瞯MkW䨽jc*~2QxԌmZYLG B훁+9o;NrKpm*=fNaTX2h%Qtm^__O͇eT£/Qܙ|a|i?t*h1׿pa'"AnZ1DOt imٸZyC*XOO R-)\LEEJr[MoX& "e,4 A*Ǒ]~oflz`ſj5+h~es^o!Px{G~#F;RhLl\Fr"!GťM*&PpBd÷ؙ<QPmq<#&ఞfݫi1-[U#f/ \-AxFc4N큛K}Jڏ"6*HaK譝րkz^ z>xamDoo(k?$3DW|,' 8GBrʥԤW{DdŁ2{ݜM\h(:J;wz{v9YA<ʄ6>4m(;AʶT5vZ64 D@W_5׸h0r vrcpE;b7[;ws9#^LFD/BL7ovz^Iwf"!ŲlY|Z > )y{s)[^ ϷĈeg^o73>mo)ʱohY\&œX! f5s@@>\mi83ȑ.˵ ŝ~Ճsy/|ApN\k0.֣2hIC;i| {h))0?os/g x/ nG@gr%w+f\%c5ڵS  )X z8b3'vOX2zWOb*E%~Eh#;D'5p.cAKlz4u+aHp!Vh!h&9I̵̳BJBis/%<3{fWhH?C=m-ihzm*~ ۋq#Drҫy'uN=M$Q v_0eoJIy,e DyȆBB6fǓ*y(r "58H{Wc| Xk?$vl8fg]'dlIϪ6,Ms;C\U[WYV:`_<:]JVU'LXoR9ICFUt3sQ#ڦ8EJ;DnuEӑ>Fpg*=S_Yϊl`&vkg*sLsv&z2؆'8آ>uhM>02 Ut{:GfL/*AA[e"m|mʩo:d E[1W|0_^W`7S[D4 eƵdd*9E3r#r^=:O+/ >vtx݋t_O wS/%BuIs i cqv}-,6"9o [#-J563>pfYA?v% ڶ _E:=ťo itKV~@|f ?B(2S{bj-5(UpI`n|ooJ1ى;M-iѭ K-?ǠXG;̶F6_rI}f95ôpʈ便,fMFAAa˝sw*Uz^ұ_;#e(x|Xq6`Hu="Y)<"o+ a#0گB)7 1`K{ۇbU=U )3/PJF?cSg.J!rpwvߪ\#!ғk uo ޝVcWq`:q ~w~A$6FiO?谾LSxI"_ݑ-a`2{@Up#h)Chx >,DF^Dn$ )!uWXNlM DQ=s$A6sDsJGhM 3z`F' )[p4=K0Z``[(?bɦ%3/K?r;Y1%G3iae4x~Kxo3ES*6):xUa':?>T)BgsQ| < ,BlY*V3əi/~(7bS¶"<6\,:*rvgH*V꿕tcdˉqJ} wLmpKx/2b lT{C57S7tV9Sݹ[Wy ʴ~vO+|DStMSN$<7Z(ahmӱ1ېKaV_2JD 󰋡o'mAq12!g;6Hu4>8zmc~oo9).1eo}ƇbT6B߰ l:t> N ao]NJ(#~7H?铙en?C/(x%uZfgLCtFaq˺+QQa$kkG0 fZ묐Ayuuνwܟ⤟٭DNH/6qƤbZKh}{hQJk}0O稙IګngF"l"M]!LʖU(9?k Ɓ$ffOvXFGftT (\(c5~dF@}UuF#xMM)qS*?- ?VWcm|np-E Fw@o~QF2Iq:d6U^D0Td1H 0jVǾwU0>J;r Y Ycr/}WLge&<87߀>hNG-!Ҏ9IYRVPgΡt4tՑ7jm~E&eoupk#ș?Ѥ=O\{ƙ`R*Qf( ^d7duQ:7d@ܴh }/I2feppNehf} QVϫc9yx9> x{5RfD)Mу3{0@#UԵA .opV.Sy Єc#vHs`p})wU|sLU(wC$0e HmvrKP"-{׊V!Ke}Uq$1b>_7+epyZp6p+ ,IhdgxdW۶5Em[pc í\iz*4Cg5 e- A*嵩>ƽ(S}xjIuxkܖmi<7t|_ZS4_΢^hbuy&vZ's9d4X |z_R2REk~ʾDn]/kEow~Ha^F[F}yNq(:NmPR{r8hXE\TCXNC7\#u)@U>ͦ`42 X,[NHDmI~*AKM.)vn$#gO2Ja<>bwlÜ A9\B'cy֩,{5$a:#lxH%Hp\Cv(gHo*O ] >7'-N4EZ%Azwv|ڈQ`6q 9[`H!`~#T (iOn5xB{Oxca=j(u8H#6?B2.']¾+.gtp9["DE?V8>" iG\hpΊ? /'O>4 b6o72lVEx{s+0xgkogJ7-SXX7V,/#zxw"fc UQpă* Kk}}Eu>uTV3Ne ʧr(<7M~W3]){EW9;1?ZsY0Tģ+39Tm cC/`'hHΝ5w~)V5g57Mv`D7[wꗌ WfDUehMS׺r3:z 5kpq/=Ewb~8^(h$bҹKgXE:"{&.Mf%mNPo#dA0C˽>"`yeDz?/@x";RBHI[?T`Wy]H$dA^$mf)U f2l2=k 6/8Cbk7 Rd㿾y rf /aܩː91Ԗ( L߉`H =;y®\Db5 9 t-/|ȣ68Ep0O[y(bdb/1mf^=-n.I%Ra=c  J0^TvP}(Bpr9ޅ݅⑍"@h)ǖS:.]$~u&/Tڿ P#FއL4HzB7U3rE!.@7< 'HI*wF/ ZmEql˾57-EvAKƿx}z!lR(>HpO˴M]h{Vҭo9ȾjW0py4>eC".M?8ގcv5AhM_3|!k!nk\ګ510IS_$i럹axiFz,c=߾3ڴJg,i2k+2//Y &lɘF l31`2iYT]=)^R75:  U&X 0_6w 0sl(!ɒ,IXG!$K ɤU@Ns%e9W8_;Q6ow`aȬVP/ĸ~ܶo5~x%}v.%p,k`P ^PWTC edWO`',joxEw cdrwҰ޹#{nB~ϭ8cz-"f泱9\N |N(;nU/AL '+̼DcQ+ zJC8**N"ࡱlj|lYWwXDiZ2ԝa!kE [( #,e`o W#bzFFznpNm2Q˿:lP4P}c@+Ϥ&ǚ4>gšL`~car(ɦN5c ik! +[CLOMx n1b_!|  ~8yt=Sg#ے3 $҉*6cN"!r\$R[d!2lbx-r4n@-X%L%֐'@~>]cܽwQaw51bOɠ,P|%ݘuH\V=)wy,Tq8,{Ա% _[dd4n~1^(~ Hg=\Bddf,)#6B{ele@@^P.ҾEyx]1o.2KRXC VmZeKك ~!NoT[؜-1$Q:(Sų Q) a,Mb?U-@uREd™uw,<{;& М/Bt^9,*]p> Fr`:?<ɨۤAB?({[#s 2O])A4iC8w"P:o >\ J5;1Wgf8$رS n@$>+R->!K5:=.qpHtB:gNw\-պ Q[_1uu@ NC-IDMV^6>YV:˷ `㢦2!7 L^n0c63NU{-0Xf*Q.3fј4Im UMAO;^ǩ eG݂|4u?6yMfJS:s^˱Jn̏<3F^3))+g_EEBDԚ7uFy LNYofy /9oW֎DSqdu,}uxė2jXof4+m{DM9+"_Ret0 k%2 Vd(Yj)jkVx](19- zJqYr3ZRqdHV"IiHhF/DSX ?Zgޔ*nә#ْ16K A5mB#5h ਿO=LhQBU|$:Y# c^ތXeGS >fJ3P)7)= a1=X]#)" 2A怆7Z߿8:B!1z_FK:##qƔo|PD2SKWX{zyVI` !?S:oWo?txFFJjK|-̦}69m4A}46g+7oDLVe l(ІCNH=hVT:SpXhdO{5!ck=\4q1˻a-; >,T](a)3W7S%y%<_-ߐ^fyt^ß0)I3[ zjM#]]b~1-P͖9tɃj7'v.*>Lu k^5ψ }h)ydzjn͌ߤ٫ŭk,YeƢeGjKOѡBYS8 ~ɗ3~J/옧kI( m|~NAB6t@,Nwcu"n(,:%AT4  r\ō$~V4ԃT'Y)aß`(3 G3GSbp"p~d%-2gwplA?;1ZZ5r:@ B#XcLӢ~K&e<&Q<X&O)E/C%+ekN54 ӆ*h{*;EW u,pV2hJ2{\{h>^^4"Ywe B0Sר= ZPҙz)!ï e(U_oZ1SQL&~aͺqE:l Ȏ gO+/ *.mvUtGTq.Y(^nBzZ(5ƘIwj]$<3;1"( C.RaA}+ }i'pAb{/QQ(42|>fFjr<գ[`"D;1LdWRǭ~d(쉍//0jGUqOE Pjߏqtnai%GPV^}r$Ȁ  U?%fFRlqQN貰r">\#[T'ASƪJWjl3WİA! .䰾qio}RJbb'LPqy_*Hm߃Nsv.}xelViJ9\zN'8hC'N^i|3?Jش9 R=q E~uҟZ_ DA9Dbb}qFrxa n.*#J"H%{>plj5E.!킷R/ֶҞ DM]nq" hQ_o_Ls#`3Q[,Y;}Ovvhhbb$9} R ~3+ѨeA֭\&zQ8Ģcjyع?h.Y@}^)N ځd/s GA膚IɦdJz_LLE dws- rġ JRBb20K Tz>0 *z$!;堬dG靷$rGi ~#Ё;TgA C۶-ԎAaTGjPF` DK>1{8p::Q׈a2U`鐍N0}6"Sz -Se#8T ni R!?dRAxuq +?N`(INAI 7?R3O̴I4xSC:FA!εnJ4G R*&^,ʿ+zmFD,\y͞y$aBƘWK>St69Mbx?G}u}IDFτ F}֚2=WiRhݗM!( l4G#,f*/on-{:uZ3z\S{Y5hFU%pkxjb8fЫx_@hl y>uyblc@en/-2y'nw >Ijfb2hLjn:7F@Zzw4RӞ g[*\y!N=w LDv k!<}l`~P8i3/„8~{e, ɏ '1ۈ/v7HoH2Fپ^Q^;x~)~ܸ2zN HZt ;(xQ3ꦠczvrmNtj"BUo~ L58:׫ rvabI [CAKlOӲq*PMi*6L4(v=c:.$NJV€' A6HW|53\yBBF|ڊg3qU,.3FUԙ3;D4cٵKSY7oYA;?Keײ;"3\?C3h [пhCPGNCt= ):L=k4`c Ay"qj}ң/R=|?ߧyV. ~r._=p-3OqJ=a[:Gg(7ƃ'4xhŽO˿@EuUnh+vt#`87(mmOjaAvWVUNܸ?{rHVʮ>jhZ-)xMܧ߼9TWgE9|( e oX>G[9-KEG+ Xׁ:+M,_Yڊ9lY1O}V>X=౿-nQExN:0)mH|`g%xCDlmlH'ZDwgŜnI 3m/>M~+ dxLq:i4<X`uu><Cצ=#]3YB .` et8_h9YT):o=Ŀ2)c4J TR^P[=)3!r$ᨤɚd~]!y3^[ $Rm 45K/@B=о!"F鄺r#]q;k&UMm@K(3j׻E%N0OG0ÈAޢ؎Z ' ;V(U Ck|m~Ȥ"Ip/D)[br}yE=-bHVW1 d!{~q"SCk|3{zd9qr56\&}|Vbv\VJN)D+sO"^y=|h97F–d6b u.qvzb\.|xF^<@@E/ #w0.a~ ; N܏"sK8Hgjф0'EW/MkyeM(T^?KP)x{NYX~h'@J.YIVWIko+>yV^q4z_ TׅO ] 9S7W:ަFgIr8g9L\DX q=vٮ>, <_Ż`L_ъ"Y12m*o+[um/=3[nItV{Jҙq F Yȡ ~l#33;_ {.:,dW."AR0- (#Bw_ii .AY2l`gj=:<'WP\eXA(O\HV*(сL rc9b u<؁81C67)ȳ{5+4wmŖPzEnr(! XoXfW[9=BZ!AnTZ[+L(`0k i-B3 㩍S+2j X^rƄxb5zri B.(!PI ɶMz}Y{l$Ƕ*Ы`,fG1x2~. OoXžx/9p ÖznsG%vjn Ǧ9e`^6{Z0w[;^=@>2.+f#pdbh L8p{P L z`oYraf# ]F*,T9I= 籢UC[ j(gk?5hɭQܭ'a9)=)o>{q5YAHD=MSDпa&5} Ku]@(@^p%YR4Bc(Ő2ub!͎sss ナUyΑ2V;a u}qR8}S`QSA>F}:*&;}P=<~/V1;fDoN_MԚF| bҿõ"*h23,/?t@kpq]Ԧ{$S&(nI7LwYb",g-i>Z^Zͨ@+7jL+[4bwHsL'iT`&!|TC=AVS>5gkɔtzQԀ83Duoaj9 6?sN;M@eb јƨiXT{5iӣxh?|D;޾@p%tH&oKe!k7o C]-Z1B xPV.\qq aw-ތsES+)Ļl(.~ 9]ȸT1wz|s @L|]I 3Vͺg"W'UA()< !9 J.&xVzȃLog"~3Kb9DB陸|-ByX~Svv+f7UmkVJ,5T;o wˎ+$|S^JbZaa:*d!lߤ&9gL&ksc"}EmXt(`~2MH~#8Nu"H`Qx,?!AԖe ѽ=?(3Fhzujx#5+P02ŷIa1+%fjhE 2cݜcGhhDCCO_'rYN0¼&ǎ6n߮~|H`K 3r`86"],U; #nݲt5SyQ{cO7U_@ s¹Jg_gh8'`;ߦ{w8nTVΆ0V_l+iN8$1CJ-L An9);,e/3U1KSpMzu˻`ѠAe__ε qBz#}O2]ai뵫RO)=z$԰tFȢU S_I/MQo)xvd0C<[柱9=Mzӣu$!&%*^Yb('x+U_/R6-0`G ?ĺ*֮>Лբ%yE )A#rJZrS|AQƆ7s}CwT.d?|ƚ1,W w6B"K:@s(&x0yơ۠[K+[G!4uF|8*1et^KO h>gn{n8ȄV7{9pwRWt\H"8СSŽO ՟̂]$Ly$ eeM=i=ab(.W K]WZ6]vٵy̼xG91Z!sIu#o%{x-*% үµ A,! ]yhEasgӾcBUҁQ]@CQd?. Fyh\2{<қC+ /R^z8&~Sw=HX0wqtΐ*0nXFAᦏ_* 2b bRt&]g'ۥEnLF0ۖIGpO.sҒOY$Oơ^C90좭Rt}% J?:Tazqhr{ot"׻ y&/-ͻh)h?xkٰvי3Fo{Xk΍YG2X-l$GubEvkRJ#~%XMC}-]uLUTZG;܁$wb*CD^D  t> aENĎA6@tG"Y _f8t $lvx̴Olқ\%F$H qEY4 &wүef+!>'j&0 cvscX,imF >rewi}fFNJLGut%bto=ӵ+ohq_+%`_Sz;z\1#',EQ쵷CR"#< c6q[%9S3QXd3O|+nRaR+τacfx,d/ B :\o$*]-wGӎb|N:ie+хc2*,Xc|>LzC^Nܠ %ĥ5;4`fO"Ex GJ梡7B,;b~E6$/t?wkX:$%v&E=Gz<Ą&:#+ɵşQ~̢5ԦZ ?=d4,,> p :. ;H]:^=9H0(cߦFƷn`(]Ǫ|H%Eό_8&%HF@ h݀ر!A,|V] )_¹2TC;nQ/ *!{E@Is섞=~HzH|,5[}$%ՐzA l0,ylUT*z,MVs(i*^,:mqGt;Đ*I]aq0n^\(ZSޯNiEsò:JX\vB*'.i=Pr Dg<4Glfa An|%r39O$%;tW-W՟`~Jy`_(ˠ)s{"[Vω/3y ݗQE4Hp zmuDOF?b=ݔrUujԯ/hyNYF68 I]I+[*osK_WFOi;A?ȵkƯDY'GvID\z; 9#KKbϏbB˴-ooҦʧ Ay^0},BfVy&M&7'@h,tcuyP(7*8+de*ˑv]y#Yƽej!m` =O@\=c'3h =9ڱLşhL,kmslO\Fm=6\eovTmOWf*dW-B_ D% X!'5-4=%~]BYgXf G@`,,0mD kۻ_${o|I|]϶u|pS<с|j׍;x&xfPtySZ{g2؛0o1L`"m藼Cb1qYlPwlyc9LUd%v{2CQ?(uUzi}|{Dyز8@hYj7ƻpJ|6ʭ4mc 7:_^{G{)I ww9aB›v-x).7=}R`X.y'*чp@JǸ;[' aU狣(+KrSO!L6Aڴˡ1VH{э~Fq!.V_`?礓9tU/XqC$ L:t"ɼۂ|*ؕNkj,bsU3-o ~. (ᕘ EA!%\-_jNkKC"SfVјv[xQU) 9PVJM)F9$~x!~UpZO_Fv_:1ƵnhDDW)6INJzLmB&I|!w6G_WGqeC\xe})qG'hE '5ߎ;*θ3mӐ` rFWmb>W+q/2 XWMc=d8L9~ ]jHHM%gz6ۧҶΔxO5zޒ35sߜBhaV[BdN͉7`sTѬ&`!Ouyz D^+]JwIdt˞;)꿷}u_44Lq&&@iI"뚤 ֢X]ʵ Džwm-d7_ιo|Kc?g]ww6/~v>gS蘻ItT(q;ǿEOf@EX3fD$ύ{KgH!`(}!9>?NƊӦ.ɋ5 y0j&|>St r;∝ 5Ҧ-<̇/\W-7:,ugP7U*c#E_MphrW0pȌ>|Grİ$9 Ȥ¥ )P.2nlk(sW@yŬ,xiY3LFNi2l| 3{ƦYз=^R BL}xcJأzM?|/2<|3Ls!(ö'n\p@ `4=_i͟vigqtzN8oם<DH tf5-(*9RhZvm9RR]WBBl+e~D; MO-fا[&x- `FwN/jm^L 1l~*sB#XWi,?=w.`2uǸן5R,q 3Ti(X+:&ŭ՞z]GTvEkՖC5>/xԋyP.6]MZ{@ ?LobƱ.$\33*aH ݚr0'XMިjYxs2t4sȅЖ2گ|v(^!=&?)8Woe'$WOGDf^0#w{(XKžj{(17at2iLpHʅB.{C&ge߸˸/ 1ϳifoˡ2٪mv<+F ZV1Y7E6^$85;ӅOASYQ`x9yceZ77/&0B!2 a/~R]suI2~"q<;cQwVS &#?@vR@czYF%r?R|f{qebfuoD8NVW>WyTFiOUĽ_c_ާtM3v{gcE Kv ٕ}1e滚hz #!%|N_D[꯱?0u8㮛n%}|fw*e_ΩK[/=&+"uXp\bB`v;junu!+pK>U<%wDsծtz5#({u0?IrR? {h9UG0Oܴ2g"xxHN_\DrUet݋kqB13ǒ] .bƐ;HAp[?(*x{g|jB&;{xܳ8om@?=C+{g]g])4.Ņߏ?ԧ3C}]g@YLb6.XҪ4}s"x/%%NJa\;LU&6{"\tcy@uFq}'Uu~_ T;;׫W-Œ|W'=XGo6*9 JA"jIi}$b费3I|57\?<ɘ9YgưA/!?P; } :0asÿDb3?^VtFŝY"9`W pmXjS]$ Wn>TXy}_βY#2/HCˁHqE<e}6`M6zPrP} 㺻 6{QlKSxhɬlCb5A=Yl#2{ ~#_wipM*,S 6s VWi_k&N7};9|7?e2 {XhY{A <@\D|ڲ=KG~`:l6&h] b˖թJ![&Ͱ3]$i؇N>`s'N1Y1 jS KW W`@\P죭ÿo{"1e K U'zO}#E! ߉a òʊB9Bc)IְJՖyc8wMwj`]{"rI#܏[xllƢϊ3;YL9@f0_tHaIwZh\؋MLn,%⯷RvՀG*e^Ca{i2!G{b+$W31%r(im~i#)6 ~ui6mсYΟaƼ (`em*r1f[{Z;~AVG1AP]>NY3яL<g"&Zi ; &2A#hT4[&  u4#2.dE6yuܻ"㉏ O}4[VVuNx/. 2d}W-*쁼cYHsC0}yI1WRU{ljwYA>:]Ka@ }x)dO{hqh52v-@yC+2ϸތQ㤘_9Bc,I7o6 |\;w^P+37Zt*yskkۆΡI8IwqwAnjjRx@RJGށNcRp% C;+Q½Skͭ-iDybZ9:sLXhn4Z)tH0@Qv n0=B}7WC,R40DFf7pοvNp,nJ`Xg"n7K4Uzkku/>3l L 3,ͼlp F!L"zPV2#`;c.o숍rc1)gGJ$jHFpTf 9QW }FUob_g qwÓN<$B;f!~dۅ3jx_OG iJ"զ ˂Oyaԅ#0}`nI`n#X8x0)S?!PE]Đd(71mEwj:z- c/wVhfoٗj^ w8"Lh4kF`*U)0%`/ 3˵6n2Hk1ӐJ1-yW r jufB(@oFԫoH?pǤ ,k[ #%GYPLi5no*F!{P5DJѮfȥߙ%GI"mȨqt ˦g*e9J[Gk!G$X '7D* :x[h4έW3XfL,x6gޱj(~&WsB.[=Tz@u2FKL)Tbد35޽€ϙ _FWԬ?OՏl<b(oؒn,H32v9EA!^8gǾ(Lr9eP>fqB&E"y~o˟N+RȜ,˙1k RXCP]ߝ=3 {Sˏoolksi 3-1ɪ^;cu:f|TMx.d֕~ S5/xwؾy;ʘJu:\ӭft'SfjvKtrS&v} G>Ҽ-;vj tיXі2# vkNzY,#R9iYU t!;3cMƨ_.!VYbD|r)b_lZs"s Q?&3|┭I뺌QY-WGq4 ãwN]|5M7C\Dd?y~])#z/gߩ곮U].`"١n'#:_3^G>М7ی9ڐ}pWxdE0|-^kѠX )&ۛMDbQ铹)P/J<,A$?8-2^ďPXH:sKa<ÀHޤ9A;Tg Jn&z 5-L. sxǜs۬dn:+Ѿ[TXMgO-xI A9XvcUSG8K[47Lo?;fzq9 :ύmͮʆ1`4tizVr:%?@|S!/hg9v^FZ]ke%jf]1_ ]>I cJmqR- ƭ{8)n0^aH$>0NG$?*С4R=IQA ilTZMQC6iʩȽYۛp@M,dbmpQ+twgx(s8c\<2M'S4+?{[eQojC8Ȭy]FtTT픊*x<j8 ]Z*Zχ rda2XOw^JND:bzn3&GѼ3@pu?^RUr7Q&400CCht`ܲKÞ_1]C+O6bq ױcgSFڏUE.o(q: GgQj[̼O۽,l=c5?^c ث{A[Պ(gl'p-󦠘X֦s03*$feAQ;kj>6J rq&?8Q!8N]_%>&Wr5/1R@?KB2vˆM6튻( n)W_ዘSSq$p kv]:Ft8(/MyQW-V{i|,B|iQ\Lf5#_? J􂃢X'G0&va6;pUHQB96q;gcy#ZٴWiA}yӨkNmrz|NAݲ4bՏƚo&3,L*@g޹z)iqfCh3i"edyx?TG$ ,G^Φ%s]^|[ˇ?FĞ(t,IF9 t&VPyeK.%?MSr`o}^9'ݔGUVTt̨IQo^U( R/~lqc˗Ryu$D)bk:{j p0@{ОX:)4k񪚡K&[?kK\ˎo>/lpGSfR4|]'afGd@=S2dislshHU-jRUZa9܂$*e5]\W2ۅA6(NqR*z7wrvhpSWedY d?teb?"Mi(3ۺ{U !slc}e;|{욦+.aƕK5o]6k)冀38cP,: Ԓ9416$(n܁~w8@A`YG5N.:d#(x˟_-'[mUNd k #,"-.4V73oġ :ݍ]aT8>K9/`!TL2q:?n׎l-/H=R- ū#1LD1/30B߁hxT"K҉VxqLTW{խ-־fs=FpK9EӅk%ysDX/'"ϗmRy_#7y-H$Qh71 4jXLxhIvK/dH9TX0W|h퉹:]S۸[)yt3gE̝Q5tRʙ$uX^Π(MxbxnM$=1We e/2pl7)*PJ7;#cDZCO Sa1_9[ LOL{Yc3-Kף9U cND0Ob9Eõ pϬؠņNh\oA2QMnaMOB7I Qݲݝ1U1@jAWCFPP{8A<"0ST =ac=ȻrE!%zk^%۰SY-]=QL @܅yz";:ػlԮpY`zh"+ &IXTލ来pY D=essk-*o&NѮ{ Cg~@e8l=Fq{V5oiiȰsWR/,Wob_㮈RWB\ҰuV kIő|DrR8/Ƶ4WGd&iw~GwKՅXe.,R.rs;%nF) [ɧxvrpXۻYdvj~v']o.i|%;̾qp=M3J&u;3H ;q_+VGSdRIU `#rx<Е}&YkO`8WD6,̲sasufK[>mc+%@x# h 4y3= DTpaz8VWtmwF )jY}`}a=ysz,nMlЩRSO^MC}{14ܭMwmqvfBK˝K6`7'2価ת7OĮi8j1@&E;'"TqXrj +#[,̃{m(fLCl:{23[oSq,ܵnic1NTmIF,'}W~ysOU(<#ʁAK=yٔXuguSg8;Ixתiߧdq̿N{4EGW+9:NC~^(>Bi%l1Lt0|:h"qߕfV(0ytcNzkQ6pS`/lN$7DdVMvEͅ?Ʈ]I·rC0y70=x'QwHtݪ!}NOI !h{(L6A@|@PwHaR{:R4: ^m/ms{l Me#H) 3'.jxU8@ܖe?mӗ0äm['jA3x+|Om(vUnLTj />sľVӂ |ѩ'ګ7L;0Vh2ʺ>7¥OMBT=Jjz:%gs6̞om]1!|ޯUha'j%1YN\. ɴ;W )$^Wk8 L${E('5gV;x1ET5L܏EDBLnsy͈/MxE 5)Q$Fqpgi"Vڜç3zם_w.tG8^"沽6'n) apׅg.ė;-笌;+lG#9+*nhL~>rN}cD/ˣK,l[FnR )|3˭ԢJGies+8|!Fvf2'"y`|=,^1kthliSa[S\"oK_8A 'ߛK)Lkww!AJ_J#?,Q[ק?8%#L'{pZ=FvIe#ԉta /G:9Dl6,R f+@K &^RaA=tlΏB~x]iV^vo8?(]TٽWuש6;rx?qU]QvU(|?kﱎFuX"5Q K >kl<7ۀ]#]+4b J6mX $;5M)W :x@tWuj3Jk',=V<$hkdPQk3Zth /neX\5~L1TPmhkZx 9da'Ŷ˦X˵F^?i`𱬾}y,n]cɆyZTuI2Kl= 9L>eCW!CD4.9nSGdL`G]v?A9!}M_0THxzSoE6,ր}6Ǒ^ ܢaQNhþ%~ICZXXzR-y._0Q& jsg/ff|GQ1XN.ˆ1pk aPc9| ?ЃGVaiӨutybm< U7}u}썝lesͨNwe:dϓ4n1F#X һ ojI,}8ٿ0FۍCL'ss vnJ5D6>E+5) ?YRfo}AI6j S`3qb %zl5)LF.nD cx^%`˸ƟUS9jc tq|b싩Ј.1ǕQϘC%9o뜺#39|Q.PbU[Sdؽ)=q.A<n{@r-זg݁۞}U'n.W* >"'vNȁIe^*"@ mq'9WpO̎t/$rIT=,]Y,f6`ÿ# uX\b3 RD_wMlH!ZƏ|}Hn"MTN 1Ai%[9KC;2 gΎْe~xed/1N:按ykLC'fORm`r=72joSme5pF*1ikqv@weq{Npj} +%5^ǴuW$tpAXB#"]wsE~Xsi\n}i"mx)-Mmc2 Z+:rm ͋tg^~ x@IkQZlL%\diO*bBs;};rd1:ѿÖc gٴ6']ѹ6)˅>wm#(ٿ޺wʑc?uGa߁"4Ꮍ@h䑝[s.Mbug{Ζݐ5p5e0]/ LVbg?He-vlmwMFΠ0K:o'(Ȥ%DjS٠S'| i[D5,㜄=퀴zjGc47BSfL ;uP+ "|b$lp~8v0mk fM$513~I9q}X3Ύ;=-Dq7ʔ|ufߌg/ӓQ!ӹ39hmqz|<ϰXe_M#Zلt|>m)1an$gAB2_0%ٚb/;G/`+8 @\ tEEoqkM,@ƚU^ \d6}?q6 nyx{&;]=6_Zb)r&:́Oud= |&8I9CyAfy⺴Q1/E,v@4 BL:&W FϪ8srtL (?vrzDލ_댙2Nf uQjfm9lФ]K^(O]@⯍lQT>Qd},є{ù>RnY7F/jfuhSiޫ)~/ 8lNW03~xw)LǦzͬdv͚ M/]5za1O&->E>IvcהKr+u$1v|p&H]y~Hᗂ|ϣ^;Gm(L\4Ft"xpNkՖkQ: ?ٚt9ϿfĴ\j٫EPZV ԌqIg Hˑ6xˢwL8P{fQʰRNel*ޮSۜ(`m᥽rʂ8O@B {23),`;=CH+cS tI =Я ޴ Wa9ad K+t6tM~R Ed=QW@y+<Q;Az|_PNV(Fcچ%hvvx04 NtnMy,zٸaFaD'&l2LzxOR)+^NiK8r9Ww$YM#At~? ݏSF\Lxhqewr^y 1~* )FvƚpWh@?DRn+gө giR<2\&UrkfX߶Z}F @3LyɗQ@20M#!oT,FuP->rhB 2@ S. jl3Xmlm.<{sg6UDrK6 Zf=wz2[ͦ(~[\1i@RNE˻fdhv#J(.^ :QE.&xf OkQǹp0;8lRo;tZ70A駹+.zƍj< {Y`fFͷW3L PsV 9:M x.2-}y?T)TPeζa`1)!: Gi0OW)')-^( \Zk>9_:yUB}1{0:#՞մ"Wyh41. W4[ٳps7؈vX<'ű/R*iƎJ}0ݽüIQȀ,4S*ўnPX:/|&u3eK{!z [Dčtcy#W);k0E]E{f[I0Nкצ:rq2ClF'f~LÌ9]n>N;adK|xD} W &Z/El!z y|C< g5g#mM"7Dt<>97QDL/JZH|S}+K'ړK 20h)Ps3>dJ71} P`>v-@7\~Ё{l5R]56오;Tq%g[TZOjzƜ_ H8rOܾ.Kܼ^Kz爺8=eZ)X#bZ:SguK|Y ,δjaE˔ l4wkX1SH! g`F+ey3hc.L\,|fEd:Aa(EX-?iX6'.j"#9k:f{*l%[SڕNϑ^qn<O30FYͰNмDwo/ȒRI_3oTU!ɃU zx 2![DֹT?"遂 o (+T||0},%rt$zP;g?y/HT rߓ*-͸)8T8ꈣyVIr^*4(zcaa~WB}-&晆O˼lU]xR{uwf8_}EG,#Xʱtx߅V sG!n=MO߃ c CApHͲ2s Y ;,5?*Si!CeZasu! I_.J[nyīH)1sJ{}&@4L6?٤.bч u+@)&Qo'vI$?;.7>0MB$ :M] %u 'f؈1O P4ڔkvFBUSSlJakN$;èDGd8׼?Mևn i5.rm” s / Y 6iJh.4 ȕU݇'ݍBtIG*1)wjlw^eE-Z~y-Yyf,2}RJnﶿoM(@WCv8Ṟ> kI%0m {Iȅ jF9)r*n{ٳc{ZJ \Hwf}uz=F]j2[s?u;F1i&GW{reɸd\xZd@)kG7thIlTIП\bx{VzޓѮN3&JeC7u,jhӷFf:p.% veL K B݊Y ,-$JzD6Ƃa&fˤƢ|q)_t:dG!\^fx'h!1\X;]N_fHda FLT 8aVv >W&2WI`6R w?v4O6h#r:P2V:N -\t! 81 Q0yz6#́w|B1~t? NectЌ5T6fӍm_1A̼ں]P& o.jsR Ȍ!N.oxw.ixzhj| `/BG]ѝ֎6*17W}y J/saMŌ^xͨՓ퍜b҈ДG^# \^9iwJm0t$4/+Vq2(>ZT[l@WxI׵W)od+b{?!Sz-ּ' "n9??>#C:ztٴw7"?as8e J EL*"G%õnvχ}/M e_ nMa_ -d>P_m3zDf l53Uۅ0Ɵ?Qj\׌o-HoXc8 Q7\[,$B ͧ+LUV/K_B-E!?û`":^v>JZS_|/َTŧV}Wɋ3OF]:k:}V9ejkp+VџBhx~7r Fn4jw>[;oh-0ߦ-T1n5ՈF kU_of1 Hߙ.d~ԇ;1I6{!䔆=cTpb`u YkrZK@ZoU-}hGpG (֓ΎH~wgdщtazxfz=k\㛬G}$ yuo%Z DS3{t(4;V)nzgF,ߤߚ#yy#?e2)f˺@?0+џٸZ9~VرN„FO xk'2[.O^|ߤ=8+Ujd" =~,!їi#.ڌ#}I0˟H_8 i8=fokC6 v'4n^Q2$̄5 ?m)*/}B=B jk ֖+Z{n+G#ʷx ڱQu}:- yKkήS ѶgwC80L&5"/95V<^tf aow&U Dq l?0ot/pzp>dwTMxr4hzRv6ߟvC;*&9ak]%DwU?u1,"g2r#5G,Q>~s8=S| d ,7I"(7JU Yyc・N.)Btd)ٛ0 L+?}ƣ2}5pUHz*¼/-#C&`\KXG|^f!;VQ(ya"= /`o W:\Oh`ȋNNzVwyXƃ~qFόP+AHMUQܰJVK%pIcx%s*QV& 2Fu /cǜ1@'g:o)Vm$9{Y*m}ce\|Su_3 kSYwK׭ X 2ؐ4nUxpU8~!G]m<gmGmȔn~y(TlHvPN9D "hJStQ|M"{_ X,BKٗR ɿ׸Uc `d/lrK, 0ƶEҹ/F?v# xB)|OY_XFnuݱ'8EGV8}\dL2W2O+)>9Z!XߟǺK L3fڮjPIis}:36< &A #6P6U}tw0yXa8ȑΣW)LH[w O 햴} 2퓃Ǎ;ӣ8KQӲI19Y6͌"Ov(%FiZ֚PQeXUJr}>6;ɀz Qg=zt4 XH rP/Z ZA̎bcRc/+ 3b6Ѝ^~aуQÔ_Γ &Q}n<)85Ԡ"EE2Xs T,}o}dz!ܶ7I7u=FuQ]XGb:.q-\P]洎t&?"Ȃ $k{=..GSV[>٨hjedYCCVyG>|&uo#qU Qrga&EiԂMM(]ǶWDk#WRyb k8E nVm|kZ@ލz ]NcpyW AR[d?}jy#t _nmTΰMp/3ycBw!6b80cu&oirjScx /_v<f ʁ+D@byB.WUM>k^0}L6L@FS4!VQ=ZdCT?A(eP800;~fj|{jHe ǩ+qFI:SWSxp[Q" Ղ@`/ۑ#{^sР|2-:cI}6 KϵoGc8 Z4VnJ*KH֙4J4@q,pc{7g(r|.аDQK? S$'ϭ-)͹A9qe(9@Afj; .'ү\r}nh==;~zݞweWVH;N+Qerll^͂Cn,GɡG◭:pFQ"õշzh- e%1ch2ޫә1#.Zfײ)_LJ$"\kOM˚ȢƲy՞WMvL6Mpߟނ~f$F ߴWvN˖%6@* 22,x .zt})1 OtyAg]l0b1eB%;hjéz1+u32kc O3激x Pq#Q|vB~:kʌT+5]Ze:%sHxa3W1^ ̑u^LʑqkDt;!D{wfDܕ嗆&{rG: ԟecI'S$JZP&8g4e(Hy^<"Unlh֓Іlݔd A&HjJޱ&nܙ<,j! bkBaxeS`Y<3y x%DllEeX;jɌgHPCda'*r`e#Β5 ̩3bqcz6 A=p9rt}Al E5(v ͢?o2.<xV|vt:^Ţ @x7:*0UClDq?1#Zxu巵2imqdl@V 2F5@ .u*+lM*qܪG8#{Qۍ|a Tb]!jxظ>bFLԵf +( se7EYb6?*L}{iB98vLpݘzߔӦ{~p3̈ &Ȇ.3Ki{tf:IƯb: ݚqnUwH9V88E (|y*وs/@M(7~ts9oIt-m޴2[YQ6fa=-*;h C;=b [Do;p7 *_DecwuF@&wXORW}V!Ј 1-t`<ޣx\UtOS*ie/␿j71=)lntj4Ͽݹ5:$-Ӧ]iIC% R 󁘜ճv]sg^ [^pKHR|LL%U3c2c䲮q[$~4T[.&Tk!_9NQIcƄpY`b޻#ݢ['J *nUv0iZ7wcKܠ`"f3PrG^L"62io1vMKM*߸q? ~phYj5uJi' Ã0a{mQEy/7?>>޹j!խ.{npDKw,YDD Uo،$t7*' |xUwk e.y(l rQdX@LN2*WfъW}ƈz m1Py~&ͯ﬊!94|^N7#pRtEBjRP6 8Qy>+ko?PQ9$ݭe7FO[t]dV>gG\xl<'tUT`C@III:$#.0Ӯb6k#Z5{T7$'^r-: ]KfE- Ƹ3Y {xO<] U׀6TQQb#y@0n: kY;䆄ꖨ˧g8߁:@>KkZ؈89uAWT`%œ0JF%/:b? (k}W. yԝBx``Ȭ7'epIkqK!W B!Sp2dnW3%xq2K,}K/Coz?C q eXe5CˢWw]dHL#oJE9){vĒ"p_{+cAv=Eo@ aލ@O^@^I`W|>hVubDdg}oiEdn6 @K'EChі½fm:mQ,W]s &Z3+)EQ#P(_달 88+̦7S/ bȃjj<)V^{1%),Qlc0?t9}!&%BG -XIOGm?g{nd*ǼvUʦ#oy^r- w6̶ kn_a =*zٔJKW_22~KP<#eJzH~Yex)$knfj&곡<3\Σ=&!LG@ q8_ƵXaqel `q&xܥ- kA ]9cK߃dgR#F\TjNj,N.RSֻh~˹ht5aԺţ}嘌YPP9x`!܍˓5`feA ʡˍh/qoƠF9ИfAۂ ||8@O@\ tR`̐TXr7i#I)CFLr5}`8gNP wDZ/.Hp0IJ Z.S}x퐯9 w6|ac'ٙi)tM 6B.$]W9QوZ[ZzO-5jrS<_ܥesO͒Q=)!OֿLlע0#Zg܆BѴu:pѩ>/'N\]~ͥt|OMfLS3!: Я@_# UD%Yq >%ZHIs^(az NȈ|>/+6 4m@g CqjD"=OitAv.U-يTV/f֞/,c38f0ZTΊrڂ}½K# H~ynDC]k/zY'%)݁?z,ۤk7"<(;-zL!}1!bH3s~uT$MҐÜUyj(=6/'Ju7 Z>*QmkhoF%!GAL* 'lJ7`Nc~?3"]`ad^1_<8)+ YIˢ&W#9:qGioGQM큎YB(*yL?'D@d[{ӝwah\%]ߧ D*f 5j2SƒJYlbGaϑ 4Tk_-VDBx#rE!%@,loiK};_)C a^Hh>c Ţ.F9>BdH'9M67wPgCC1fquE$I7Lc=YGyqcQ㍅d<ޜC0!98X*x6e((y߃P-Hi^i (:c.\"qW ;!6#ā qU`+b*M+0qnLёԔ65g,ٵVM1ug?ZMT~%V\->fd+F4rI/L+x֮[OQ$B.սMP$ R',0G*.ntqy kᆖC͵sRߧg"޳Bj3EtBҰWĸQ%-D˚Y9ǚnFc9-h<Swa>~R^QBj̓)&ݬJEG賬ϕ4m[c† igtq'z.8|pǷ:qmx]\؃zײ"\_g-ygh-N(*hO|hs5z5/%s=`{29f\xR@;toD;+eNMbHG6[=yc*_97B(x?ķy8y7ݘH^D ]L<5M,)3m"|ӺNܲW.KK4@9 Ȭ]{sK  cҌ2Oy~h5&hxƙFJD)l>M V_4Ɖo#U,@cleH@Ɩp>쎇AEc΅ROa]cI%h~-eJjW ?tT&q Ij^bYwbU>6tw,#mkPP=jNea:s5\B̓7IJ~/{$m%x<! *2k#f g0]k6cI\X|}ם,F8G7vgؐZZ,.==V~^=g@PpθՌe pnrdPtPLur@qSY0ArLM PO3~,U4[ Ď%uIGsUV]Oй=8RprN;Mz>l\_2EC(aϼb7Q)C!:WerںЕ:/ ^%눡 SAoNJ?[,],CЇ'E80aBy F03QƒV#QD`:u}E7`4]hXz:> u%X`,Zw~#$%p̳ @( PyLng8wC 14q0Hpw< {v,fcyOd' \> `Z"Ł%MM5Ww]N@ћwo&9' $re|"ϖ(6U̹O;7gZ '4Q1{Fm lD"<Yȣi.H `!y~ i_:n%/x(I2;1=o2ގgZ&tNǷ_K3ouGYm/r #~7{iL&}uj:F~T4`É<븸a-6σe!U)zX/INZ4*_*ė% S8)ZBJ'=oLOWW*m|y&({xV@~ؒQ$bPUB4D YHН7m:&8p[NYmdI)9|W聹SSY>L5dm/"zJvffuꏽRFw4Sfq=ƷJ)\$ƛ{܆]aXW&YXWyQt_%ڳFppeV/P+g cAnm_ C]Ee6`>Sdxvp3j]=G.o3cgl]ư{cU}#͗OgEyJDhR*% PW0V L j߾QH&y+[{J C`hL bqY<| fě)e!0>#=*E?T)ZF&䨐A4Nؠ2:#yV* LtePxJ\PPxvh4 VT'rڿ#Tf/)xV )z}SgtxB/ZD`xĬ1f圮|:Yゎ m}6FX.BfSp 3y VTuuƦwƞ7KY7">HIky;ѿr*&sg-F@n;+UZ=oQeSsnXB%4Ϲ >6:34a d_1R^u; Ta g[ۮ쳦qk쏱8JN-Җ.~/za#'VN9<Ǿ%KT^.BUqs`"A‰i?De0mݩrYz OrkOrFoڽOw=8ه*VX;L{ڋlsv4_ʕF^F)(*]*ژzt~ߐ"uژߡσi{D@Dd?0ndT>gAB_+@ d>MY'YD&;[ UNiT`֜(/x.iir/}kIys\yk?hWPT}h5ZE8 39jD`sl|lqފt}i3X:ĂT-K&:k;3Kt=NYO0~ʜ*7 L`(.xv!:>gdQ'!⠅t S~N g[E&BWfvֽy*@ڸcns4u^D̑p1b\Ԝ.jzX!_Sho(m߰Us"C O=h͟92;Fi$od}A?B0so O?h09d vɌ B prǩBEpvs aU*|MTkiJ9QlX+j?~mkX3gՈYwܑ|)rE~TC^X,%)*0c- 6vPTV@:(7}̾7#z?'pNÌ|)$BGtP"Xk_l֚}sDbNl+<7FxfyI:sL.٦s#MX2Foƨ O0ֹ9vG$1kphf;4$e+4mVSzfW { F Լ`A 9 nҟ@8}hpŵ +n}O B{ ڇPxOpqeǓغQuxrɟ!L{ Z&Bc/?QTnkot2Al+*HJQU:,$BԳ0v@1Sb'f3۷OGEiHԴsMg&R4myvQڐ;u[Qʪ66Avt Lf^oo\$NO%KR\Q.T6{ujuctm2 }Pwjdi|&VlK[ѹʙ> PNmT nU:%КueOmM%7&^lp&oQad2ݯһ]evݪLĚVxNmC/(]?cyAa^wtjkkM鑒"T00~DPCujsCh}qu Qoy-*30^FBm;~>[>\>KO5r.ws$hm~[К]Mp(Smr}TǴD)tPD^=cBɯbU7'n `NNj5C%WXd8-恙?xsv=*.u#iZ(e`r[G%X9un)k_0˻1q39x%JfdFgwvT۝ ;mt[3n͚s6W J+M4ٕ}h,Rh/C5g\~ֵdGޅV,;11eر/3<t60 WS0Ro(2xߏ nX9֣BtWQ-F.&ҙD0q~-t'HGXL\f nK.s7 K}h5Jh̛Wz+Vw9)N5Ć|jW9śR Fa_$:R@wۙ).<<c[o$jG=V !k g$;9ʙjw&:9e#isr~9=@;2a9ޣ@Ӓ CK,X8+] l(l~ѫˏZqnyOZs]yp&:ԲSH ɖx(S)浽3/bg76xS,W۾hP:f팑z&f F9=JqHC9?lyĉ4qO-Gx\-*6gGV٩8"r»E9%O򿐹6=QZD /RyLΩO~~>.N]{>?elJ7P0׶3Τ!UiFf~j=`}SV1HeW&Cwc05*йASď0q7(#u 0A(. QɌT_ԀBUcSCÅwUw.SuӖʸ3Z%>^ŽT_9i/EŮyܟ"GPWpk:l~PYۣg٫a1 gqض{ 9I#DeAۋ9˳yD+N Ign@p]G7\ As9;i#jk+p8Z՚xTn_xޠ\$JFF8^ zϕ_RB ەᣴx^/|͆d&V;Wȼgau<P_? ,@V8֟꺥:j*݁yk|:w[%b/I٣oO9sq0qakP)ua9 L(mSo|q%.O?>@ 7%g0\@6S4G"/Ή4kjn˅yvbWvTNѳM{~&"6uY6huJZ'֥Lja%D~M,hdV8iv-VOT͇o_#цQgip?M=<3]8~M "H+w߲:J#Ahj;#}G@^O/ӣ3{2NxNH Rcd"U6fsycc+:1o%TGrl3Gwew55ȯ@ /dlĊ#S77bXF ӂ4ZX ! (S4?yf?v+$od*LR6x\1LOs/ޑ㻚9jUY e09=iKдc)4.@Jq5/iX\xbv̾FOFIԴ%H~Ƚ*G%])pE9 d1YۈE%e,ffƯN[ Xܖbf\ݖtLyU<^E.' fվ{4EVf2|?g]mB4.%z$݄_o1ygՇp|L \'%jWov\kJ%ApY[WxE巬N`lqzR :anD0N,>/̫$zb81Ai6wISkFrx|u?w_&KAJ8eMt"%nשM8)9r'44XR|d+f+8).J4fSKQ"p0kcUypQ0tѣ-K~4 0@2%n!Zmccbrƹ 6TԀo8oX_"N.QK1vi"5ZP|]-dJ#Mcm> :w xqa_Dǣڔxq3!CgW< V9xnvc"1/3`@1 xG ;ّМH]X;ql+dtOʯԷee߶ԛ榌LbFW7 & 5WEJKԻx =_xXM/YSSW۹ c@Ż 3#c!FY՜J?.aT7Io+J!zjx߭V!IΣ֏V?qX59`1xgr:v]J]Ī܏қ|k̢lա&⋝E;TH޲+4\$֛dsz)Uɋd3T*ݭ.\ņD1| xOt{" ѭm~eQ)zJ+u0aφb&+؅7̍r)Xwj Gl{^qsFN}EME G8b\ wy*FmxZF'ab5,WE/PGkFruaF"&dX9jXnuz^WF*CNKAmc@佯2GV^v;GchxDuvi'6d׳EȘɥ$%}&9ソK0  l-.*3ef!` PB%ގ&FVo!>L@jX> #vu] ]˹*ՉIi/:'<.מY x)@qW(B` NT7 J@dp>lw ?J“ rƨaX^:4@W~uGqER )z@k]WyLuo$}0 SB7chL47]EL&KFnq$ˬ ~8L{^{LM)đUlyJrI+K,2]۹̃>2#Z~Q~Ts #J22 eZ![uǖ:XR2AXh$[ƽgiU\ҖĪs1֍"OGT<~[&fvu6}KL*,[$[c7V!pBTpLLюq+/K}I2wj"aKT12(̞QMwmifN5ݨlD3,d)d~QVmvb*3r߮b:<NJ>Q͵,:2p/n OOj6/D'F^rq6Cq.9pa{*}-536F_Y¦8K.'~6^sԾ4S{\hNڌZdt[G`rVƈl0Nx(QLľSmxdpί̸W/-`z]ֲ̬mQ/ԵMN :Ǵu\`tB^Sl_lb'TW@Eefѐk]Dk4裌 \[T gձk.;ݴno=wۨjkG-R0sс\n<>sGnC.^ xS;b+.T4\ٯ,3Q1(Ɨi?r\G#XQdlxыb+NP3jI^3#:5ADǺh}D; j+~%00?tw(xi{CD<; %z{goٍw t|/ʅ!TvaT>Tt<~(:4߀U8/'al6@DA44Lsx`oCz kX}qG%:&;ZȎM^uEDEqK4h% B.Ră:. j1+j w>ӭ8˙,PWmu +k]]^~j]O]C)dh N墪oeTw#= ZHrTn%8!StLaoOeԵc{>"MD3^VkoE^T%TkEI<(yЂCF/q @FW;t#CIFRWIjҕ0u9L+ ҬH}ʏe EA8^:;C j' _iBMZ\`8/ $ZFwcP"%'By1j".\(S|Xxmc cU/3 L>T5~K-Ȋ}—1W_YYTRC|pxJ {+Ƀ9kY/ :7ljy[ " *BJ)+" ѣaʱ{,DPM8GV<';LgfO0F@^C:@?X Bq΢'ޗt$*m "6*{GdEepf~_wX+Obv;- & П@W*l82"YC@;~B*EL)dgKy/~~rZw\x/hlҌ.z$yX" awtmKIvx_3ꂐˠ^ҌDٖWOȷhH%2X}(BDHe:PoO8Z잤?Y-4.%Wz?MG-{elW>!4.%6h |U/=ebR@ "(G .Pv7]N5D% &9Tog"ž_ct. vP!y9Z>GI7l]]vT[06TlU`XP|Kx7=7'-e ϣ #{#5x0YG臟 ),*A A^/ѓ`Bہdm70yx:Asc_VRE\oLd#.J֣"aA>V'{:q"8Z1;Nl|ZrxUسqWv; qζdDvr19eo/p6#*B5$ϯa" fn" "X+J1;=?qaG7PPwREBԮk]7^_{ċttN#ĊIJML]M]NQj\*Zh{;[x vÐ>߳J@a(i`C(߯K tF^.LNF8vj#7q42^qɺk A,sQ:#9YvLH|Ӿ; ZvF͠JS?H<;%F5Hn?2ݢl:*zM49|/5rkTf5D(?6)yOn @}nBlBvQC~ώSe}\V EwZlc;W4zy.\WOխ-`ӫ0 >Ù3ō56t˫ʿoL#jt&|(zet/釛)uf82VA!'i=?!ntm!FBO^p3>tCHJ0!7ңI̕| }j4>2&,4H2N" /#nwdlJdrX)KZܫP~7bEUWfSrQk썈|0rZVH pPs[=㛉>yC"3̷'B{$kO$y,O,!Fc#*,J>DH+)Q< Zy8ZZܱmHSNB_}RnhALSוh}, F0D±dV/B1kሩdƄw,w:턠~售_t@@[mH ݅  _ Qi5NATpoh=zJHB`WEw7m[0T)_w1B k,_h4XqZ q-F2gAw δD >Nkbh =9cyf"˵8Ϭy!~wc҄v@XԣnSz/s6ќ;JGêŏY5RX.D{Qjfdyw;)(eubQl?@k >qic>#uvLVRsm?6tnزSs`[@50밬mDiXiג E`qYD("C4R:nF|W㱗wcRR or/5I)[V(> WkgP^Ҁ'EI`&&M<@ Kp**iz@Sq7kg ޑݭ{V%eȿjڅ2A #4/p1DS2F4*&rfT 24TG2bSGoȣhAGIx/Jڇ@UFDDyUshC]|C R!LQ&6I ?U;; aɥ.9ڳM4tdO$@X!PfDSx>'m4Ecuk".B~Hw8$L::5bnTǛsYk !༧Qbu~G'Q AbFgVxhgwNZɺ_&˪Q/?RE˩0\֗tEm9!Abt8G6XFbUZ$]~7fݥܟ;1Qn&"~; K o d{G@<sIdjow!)>=}BOodT* Eñ W>1Ha+yqx ;h{xEk,Sb#O[䍬8uBG<2Dмi"D@XOe> Z0l~,I)7dhs킴xk P5Pˌ.>e/xB+{a} R}acd(C|Dh㐷hvŘH/Ǽ K@=0kգ.wċ'k'^L|Hv4/vg?gGwwչOk϶?*J* L+ V9K.!0I oB5bKWćbI).VOֲxS. fy!u0RēVPE.0'.7<:N1nƋ!ءnyz?Tk߯f ҹĦǛvsrJ!|7wh|׮bٯNVHrR% ^ o3'm^IwoSPoJ4Bzk2 ` xsy j/?Cu5k/wbOP3 #nc; (hZb QoL>W+RձovVZbk"j*2òpNͥ ⪧3ZC ߏ=(H?[32}%]'-6msfzOϬuE]ZJO&6qA 4c" RE1\1T"+t*)aGCpg>\^ w5c^9Emk\_f߰:-A)|OHy2s ybiѮ̽>qkh{l׸eM#{ bDsi>oۯ:8a \FkR8"wštx"5Z=޸~y *+'Dh2m =0 Fn{M!%YoF7Dm} kD" ekJn"!V/ V8{&mXUYLfSgF6nw~6z]YHPޙVRmD1zמ,:A_*_+5ra1C< F9(݃e] ߦ2 rh{_|pvQ d]Z7',Dq0p@bK<:O 2~ZpIeGUo 2"\Z<~@ d`Z.g=-{C79Lx|΃bX+{DAFph\-K"٪Bu .xZ#> =̖3 ,$4w!l7gffɴkބNT߲. @#Ւ6=AUz4Jl!;}awnco(*{6_;l@^wqNSl".^]1A(V:)N 4zOS 0L,83mezے ~pl3fȫqw#[;ÆLJ{P*tkGjt ttȠl}Yv-u2ڱ6E%97{o̲lh,K j[˥aeMqB(w|UNb8E(xLjug639ÏK% vaB~Ig0=~hݡUl\]ĥ&&,ƃ C5JCck;!n4 =\=s#}V:֚|o 3`)Lu0wZ= Jf7yHUFl@v}lk5>ȌD4^z|aـ7Z?OϯAkwܫz $4RYD1| ZZStFKG8ur @ *@h.'upD#ݓaa 2x2o*wU2n1+fR }XL[e"f0$&BЩ4J5ڡP [H8B+65Ae-7&dT'|wΕ^y*(}02!_9,ȕI8t9ɮs%} M.,("$tnp0 ԡTGN^۴yGwba{8nL&?yr/deLu8 ]ȗoZ_bzͬ]["V$.aBt,LF u;BtKzgI=ȀVYIܜ>Qfd =fֆƋ.G3a"DqK"{x,If=&I4jTvEL$^cc$T#13?{5~G7yU:7nL>7}iEq娟2R ⯭x}'K# z3-\+ɕ^èUIa"T>\ˑ"U:˸zcc.nQ5> ߰& Z{(j:xPR1g\A8${c6\YPJmnC-w  6)xuí|q&Ⱥ{ ^HswQ bV/$RW; ~~Vc72 \(ZZr_"x7.("}xC Ngk";@X{qaAA^2ƅ%L9o&z*&(71x;5n5[ӰVzM.Zml]XМ!Ɓ"(:8XX >h>iѲjaFp<і2یbS !eu;I₯cn~Iv  LtwP>e%旎2i5RL4aO|vL;·PuW1XǦHJb.HtrPXfZDl9L3w{ !S+7l8H_w8sj L[0e ?=tAT%m+aB:}E畑 [=6  6߈ c傜oͼHB~e0"Tkp7MwC.5<>xz M_PcR?=d;d^ ^(S ZxzC5h/Q8;уJ6.$B &ǖt[ż2<0 (8U|n6TloPz0XYH6R{<ED ˷ӕ/PNO VޚSOѶsX^uƕĎȮYn/Q~kQyrH(k/v)tEX%OL!G?%VI+v5No[:2YR[Uޫ_NvS? =. EM*u rbōث+1.p3u>,$PMck ~8AV/4c%9Iv jVs-`s.~u}ӑp/FFj@S4op`8A|<+Hc.BVȒ"3֖.OLt{{k5h=-3j5/y=%$1fz5D-mP|ڡI;+谼0vܶa`2E ]kLNzO꿡66sF7t *@tX.濮>Zm!ysp^Q$dܝaP`$~7pHi,)Vm$K~RJwHF̮pTQ\R-ٔ>3^ %[ >z˱@CJFR8‡,wg/TDa !+?ߩ^/Ya D1 Ɔ cSʇʪërH|uXTm vAmTIV.į"4g=(վOm5yc: j*ocO!JWdՏAcsa6e@sߊy`TyՋ& ;6coD(xwFhAgR,NXE "u(ng[SE[×@=UUy""ۡ+D'pNC{!1$j9"c3:!tv\0LD'ÝZ!&9/_ʁM0:4%x!W.fIGV䱄/iqFr07c-yd"ѯ$w52+zkz<9O$oۅ昘\o )ۄ6` vV<@Wxpk#G.(l f|L !b 3'@tc>p ȽO,>_:HyGÁ՛3 Lihk5hP#[Zq^]znN$sj|( -)ʨI;l!Yȅ8߸Uqqa)oŪ,fsŃ$Eg) ,|g Hߥ *w3ay"*nobOW~x:!K1^E`%$H?o*`^AԞ#/rWp%6lc#T|D Y<8< {./z/!Z|´RBv$Jjfudбvrk4mIe ko8U:#MJ^ni@v*R0sh *l|16-D3$ff4nGx|}R.!(.uoȼt#u9ϲ;-}qV̟.u eA^_&6ɜyEηJo++1Ś W ybDzep r8g]6]cb oE?WtOh> zp#,Tu ZkPE..@ @"U4Z2މڹreu{\BFڈ?C+]1Z5_d@gi輇rؐ*|\$!-XlT, \~n.H|RA>PdMsG!W.l1YqP_rs@GK{Q"}xsX}{]#_/"޾*LOxVL𣸋Z ARl0k]pu5* v?_h= 3*z/7{^IN~UWbLb9ؽX'h}P+PnS8R%gxiC^ny^QM2NO[2yUDGO:0Lv_hNRBensFAH۝ ckƠ,4G4I@lD*u E4͟u`UAv4>Nqb7[= YFSO `~p25t+ b7ٵ5?rQq^,_߇=*͎?޿YYbV)5 )&F'K3)أ~p,pJ|SӹHԓ̿H鷩j 0Jl1" o@Ʊ\$(xHDȐ4B3 (ADٿ%g7D[˂YW{W.9σ|~P 5bYtB!>R7͜6(H=XdŒ+ͽMwyeeKoPov $7lGƲgߩ~Z"(^/f~BPpL )+&7RUIJ l)$yШOr]5[dē-:PPaEcU\@i't_̣Nm$o6G8~7y9o̤,4O3;2~ІE댣eW18 r=6hr,1+g{\ky7BQL.+[>BMs7?z:vknqh#4onYS5c*Dd%hzxQߏB?1[Ӟ72+Jo (4f~3&n^arCƻm4|x$o3v,&\k,+C\#J@;ߧ{v 7q/f蛒>6SC,4J'!_"C?}O_/@gkG\Jero<==}4J`,uMkp!l/|ENuu3|2 ޑl`طMOnE;`m^nE_Aky0eMAx3mQ'G|tЈ~0N\ (!ictimfܨ?#2   {P{%@?LȮK8w`B??*H]ύ' $/ gWI'4cq]?B^kMC Y/P?AM&ĎR~5|H Y)Z w#uqDLDi%No8,m 3  8P/5lYȻsvk? >EgV2T{ēo#Iьɚ_Nk󱼵pv%  XTvcxP>pbo#a̅M[Da3CgG(1﯎="o?u$L;h={U)EsFB o5xOoPQ`CK $8zFX"ϼ/0|l3gotR޵v v[,m+̅DƎC/ @#g{) 3# ~O1$6Nx靑skS@wOV2yvUyѸvtԬ, Te>q])He0n$s@  i"vqq2__bSΰ@o<؀C21${ z+1^# q8Q*4O=,Fp}±`Up[ۙtC_!d! D F C8'"Ȇ{K.go/eL:Ҷ+%!Qī0҇*8ݶ^fI{`=s;hPCGtkh8 .$=ߍjMd[0B[$qm!~-m_f. }x /:9Y$g,eOQ_W"X pv>%o/Gm|_Ts |_1E%ێAݻ+䘦gI9+z;u}bh\?O_K|bWh.<["m_s m.`}c!#h0UlPEq/ +Z  ϪwH͘:= zcAAClc&ŭQP] &&K_Lx" _zE:Q"W҉<24qZAHtRea_>("l x"I7wH0ĐOrq+P wFA68O{Yc,@0 !]SVF<~3gnS|fo,0`^[=9Q47*Xo}FjѬ. !a=JV}Q*G$I H:6 {/-o<@lSq穴H3 f"# #s55s8k >.0jEYCs.`?~`: ޫ"=J͸X)7=IYG B&8#iײi͝ç~!{qke?/y!Bt,6 lr2W"Y ZE&4"u 4@v&żʳ__?cD>Zd3.Hc 3t)0t]~8[%42E |捼%Ҷq`s6L 8 F5Gs"tOOU G#*9\8Sw`숴p, 7 1."|Mx['GP\h_q k|]$pK=_/5v !ְi6yy&bƆCO euO|"m{8ƛm I[(SbޣK#̔Gj=tK@aeS_&38| _I3X3ID߹'b-9m6MҰ &JeTBa#F©'DJ"uܮDظ7. mS;QhyL͏d=#a 0lґȴ-nx83]B@f(performance/R/performance_aicc.R0000644000176200001440000002027414736731423016376 0ustar liggesusers#' @title Compute the AIC or second-order AIC #' @name performance_aicc #' #' @description #' #' Compute the AIC or the second-order Akaike's information criterion (AICc). #' `performance_aic()` is a small wrapper that returns the AIC, however, for #' models with a transformed response variable, `performance_aic()` returns the #' corrected AIC value (see 'Examples'). It is a generic function that also #' works for some models that don't have a AIC method (like Tweedie models). #' `performance_aicc()` returns the second-order (or "small sample") AIC that #' incorporates a correction for small sample sizes. #' #' @param x A model object. #' @param estimator Only for linear models. Corresponds to the different #' estimators for the standard deviation of the errors. If `estimator = "ML"` #' (default, except for `performance_aic()` when the model object is of class #' `lmerMod`), the scaling is done by `n` (the biased ML estimator), which is #' then equivalent to using `AIC(logLik())`. Setting it to `"REML"` will give #' the same results as `AIC(logLik(..., REML = TRUE))`. #' @param verbose Toggle warnings. #' @param ... Currently not used. #' #' @return Numeric, the AIC or AICc value. #' #' @details `performance_aic()` correctly detects transformed response and, #' unlike `stats::AIC()`, returns the "corrected" AIC value on the original #' scale. To get back to the original scale, the likelihood of the model is #' multiplied by the Jacobian/derivative of the transformation. #' #' In case it is not possible to return the corrected AIC value, a warning #' is given that the corrected log-likelihood value could not be computed. #' #' @references #' - Akaike, H. (1973) Information theory as an extension of the maximum #' likelihood principle. In: Second International Symposium on Information #' Theory, pp. 267-281. Petrov, B.N., Csaki, F., Eds, Akademiai Kiado, Budapest. #' #' - Hurvich, C. M., Tsai, C.-L. (1991) Bias of the corrected AIC criterion #' for underfitted regression and time series models. Biometrika 78, 499–509. #' #' @examples #' m <- lm(mpg ~ wt + cyl + gear + disp, data = mtcars) #' AIC(m) #' performance_aicc(m) #' #' # correct AIC for models with transformed response variable #' data("mtcars") #' mtcars$mpg <- floor(mtcars$mpg) #' model <- lm(log(mpg) ~ factor(cyl), mtcars) #' #' # wrong AIC, not corrected for log-transformation #' AIC(model) #' #' # performance_aic() correctly detects transformed response and #' # returns corrected AIC #' performance_aic(model) #' #' \dontrun{ #' # there are a few exceptions where the corrected log-likelihood values #' # cannot be returned. The following exampe gives a warning. #' model <- lm(1 / mpg ~ factor(cyl), mtcars) #' performance_aic(model) #' } #' @export performance_aicc <- function(x, ...) { UseMethod("performance_aicc") } #' @rdname performance_aicc #' @export performance_aic <- function(x, ...) { UseMethod("performance_aic") } # default ------------------------------------------------- #' @rdname performance_aicc #' @export performance_aic.default <- function(x, estimator = "ML", verbose = TRUE, ...) { .is_model_valid(x) info <- list(...)$model_info if (is.null(info)) { info <- suppressWarnings(insight::model_info(x, verbose = FALSE)) } # check ML estimator REML <- identical(estimator, "REML") if (isTRUE(list(...)$REML)) REML <- TRUE # special handling for tweedie if (info$family == "Tweedie") { insight::check_if_installed("tweedie") aic <- suppressMessages(tweedie::AICtweedie(x)) } else { # all other models... aic <- .safe( stats::AIC(insight::get_loglikelihood(x, check_response = TRUE, REML = REML, verbose = verbose)) ) # when `get_loglikelihood()` does not work, `stats::AIC` sometimes still works (e.g., `fixest`) if (is.null(aic)) { aic <- .safe(stats::AIC(x)) } } aic } # mixed models ------------------------------------ #' @rdname performance_aicc #' @export performance_aic.lmerMod <- function(x, estimator = "REML", verbose = TRUE, ...) { REML <- identical(estimator, "REML") if (isFALSE(list(...)$REML)) REML <- FALSE if (isFALSE(as.logical(x@devcomp$dims[["REML"]])) && isTRUE(REML) && verbose) { insight::format_alert("Model was not fitted with REML, however, `estimator = \"REML\"`. Set `estimator = \"ML\"` to obtain identical results as from `AIC()`.") # nolint } .safe( stats::AIC(insight::get_loglikelihood(x, check_response = TRUE, REML = REML, verbose = verbose)) ) } # VGAM models ------------------------------------ #' @export performance_aic.vgam <- function(x, ...) { insight::check_if_installed("VGAM") VGAM::AIC(x) } #' @export performance_aic.vglm <- performance_aic.vgam # Survey models -------------------------------------- #' @export performance_aic.svyglm <- function(x, ...) { aic <- .safe(stats::AIC(x)[["AIC"]]) .adjust_ic_jacobian(x, aic) } #' @export performance_aic.svycoxph <- performance_aic.svyglm # mfx models -------------------------------------- #' @export performance_aic.logitor <- function(x, ...) { performance_aic(x$fit, ...) } # styler: off #' @export performance_aic.logitmfx <- performance_aic.logitor #' @export performance_aic.probitmfx <- performance_aic.logitor #' @export performance_aic.negbinirr <- performance_aic.logitor #' @export performance_aic.negbinmfx <- performance_aic.logitor #' @export performance_aic.betaor <- performance_aic.logitor #' @export performance_aic.betamfx <- performance_aic.logitor #' @export performance_aic.poissonirr <- performance_aic.logitor #' @export performance_aic.poissonmfx <- performance_aic.logitor #' @export # styler: on # Other models -------------------------------------- #' @export performance_aic.bayesx <- function(x, ...) { out <- stats::AIC(x)[["AIC"]] .adjust_ic_jacobian(x, out) } # methods ------------------------------------------ #' @export AIC.bife <- function(object, ..., k = 2) { -2 * as.numeric(insight::get_loglikelihood(object)) + k * insight::get_df(object, type = "model") } # AICc ------------------------------------------ #' @export performance_aicc.default <- function(x, estimator = "ML", ...) { .is_model_valid(x) # check ML estimator REML <- identical(estimator, "REML") if (isTRUE(list(...)$REML)) REML <- TRUE n <- suppressWarnings(insight::n_obs(x)) ll <- insight::get_loglikelihood(x, check_response = TRUE, REML = REML, verbose = TRUE) k <- attr(ll, "df") -2 * as.vector(ll) + 2 * k * (n / (n - k - 1)) } #' @export performance_aicc.lmerMod <- function(x, estimator = "REML", ...) { REML <- identical(estimator, "REML") if (isFALSE(list(...)$REML)) REML <- FALSE n <- suppressWarnings(insight::n_obs(x)) ll <- insight::get_loglikelihood(x, check_response = TRUE, REML = REML, verbose = TRUE) k <- attr(ll, "df") -2 * as.vector(ll) + 2 * k * (n / (n - k - 1)) } #' @export performance_aicc.bife <- function(x, ...) { n <- suppressWarnings(insight::n_obs(x)) ll <- insight::get_loglikelihood(x, check_response = TRUE) nparam <- length(insight::find_parameters(x, effects = "fixed", flatten = TRUE)) k <- n - nparam -2 * as.vector(ll) + 2 * k * (n / (n - k - 1)) } #' @export performance_aicc.Arima <- performance_aicc.bife #' @export performance_aicc.vglm <- function(x, ...) { insight::check_if_installed("VGAM") VGAM::AICc(x) } #' @export performance_aicc.rma <- function(x, ...) { stats::AIC(x, correct = TRUE) } # jacobian / derivate for log models and other transformations ---------------- # this function adjusts any IC for models with transformed response variables .adjust_ic_jacobian <- function(model, ic) { response_transform <- insight::find_transformation(model) if (!is.null(ic) && !is.null(response_transform) && !identical(response_transform, "identity")) { adjustment <- .safe(insight::get_loglikelihood_adjustment( model, insight::get_weights(model, remove_na = TRUE) )) if (!is.null(adjustment)) { ic <- ic - 2 * adjustment } } ic } performance/R/model_performance_default.R0000644000176200001440000000250614736731423020301 0ustar liggesusers#' @export model_performance.default <- function(model, metrics = "all", verbose = TRUE, ...) { .is_model_valid(model) if (any(tolower(metrics) == "log_loss")) { metrics[tolower(metrics) == "log_loss"] <- "LOGLOSS" } # all available options... all_metrics <- c("AIC", "BIC", "R2", "R2_adj", "RMSE", "SIGMA", "LOGLOSS", "PCP", "SCORE") if (all(metrics == "all")) { metrics <- all_metrics } else if (all(metrics == "common")) { metrics <- c("AIC", "BIC", "R2", "R2_adj", "RMSE") } metrics <- .check_bad_metrics(metrics, all_metrics, verbose) if (!insight::is_model(model) || !insight::is_model_supported(model)) { if (isTRUE(verbose)) { insight::format_warning(paste0("Objects of class `", class(model)[1], "` are not supported model objects.")) } return(NULL) } model_performance.lm(model = model, metrics = metrics, verbose = verbose, ...) } .check_bad_metrics <- function(metrics, all_metrics, verbose = TRUE) { bad_metrics <- which(!metrics %in% all_metrics) if (length(bad_metrics)) { if (verbose) { insight::format_warning(paste0( "Following elements are no valid metric: ", datawizard::text_concatenate(metrics[bad_metrics], enclose = "`") )) } metrics <- metrics[-bad_metrics] } metrics } performance/R/model_performance.bife.R0000644000176200001440000000247514620351763017503 0ustar liggesusers#' @export model_performance.bife <- function(model, metrics = "all", verbose = TRUE, ...) { all_metrics <- c("AIC", "R2", "LOGLOSS", "PCP") if (any(tolower(metrics) == "log_loss")) { metrics[tolower(metrics) == "log_loss"] <- "LOGLOSS" } if (all(metrics == "all")) { metrics <- all_metrics } else if (all(metrics == "common")) { metrics <- c("AIC", "R2") } metrics <- .check_bad_metrics(metrics, all_metrics, verbose) info <- insight::model_info(model) out <- list() attrib <- list() if ("AIC" %in% toupper(metrics)) { out$AIC <- performance_aic(model) } if ("R2" %in% toupper(metrics)) { R2 <- r2(model) attrib$r2 <- attributes(R2) out <- c(out, R2) } if (("LOGLOSS" %in% toupper(metrics)) && info$is_binomial) { .logloss <- performance_logloss(model, verbose = verbose) if (!is.na(.logloss)) out$Log_loss <- .logloss } if (("PCP" %in% toupper(metrics)) && info$is_binomial && !info$is_multinomial && !info$is_ordinal) { out$PCP <- performance_pcp(model, verbose = verbose)$pcp_model } # TODO: What with sigma and deviance? out <- as.data.frame(out) row.names(out) <- NULL class(out) <- c("performance_model", class(out)) # Add attributes attributes(out) <- c(attributes(out), attrib) out } performance/R/r2_ferarri.R0000644000176200001440000000521514642733710015146 0ustar liggesusers#' @title Ferrari's and Cribari-Neto's R2 #' @name r2_ferrari #' #' @description Calculates Ferrari's and Cribari-Neto's pseudo R2 (for #' beta-regression models). #' #' @param model Generalized linear, in particular beta-regression model. #' @param correct_bounds Logical, whether to correct the bounds of the response #' variable to avoid 0 and 1. If `TRUE`, the response variable is normalized #' and "compressed", i.e. zeros and ones are excluded. #' @param ... Currently not used. #' #' @return A list with the pseudo R2 value. #' #' @references #' - Ferrari, S., and Cribari-Neto, F. (2004). Beta Regression for Modelling Rates #' and Proportions. Journal of Applied Statistics, 31(7), 799–815. #' \doi{10.1080/0266476042000214501} #' #' @examplesIf require("betareg") #' data("GasolineYield", package = "betareg") #' model <- betareg::betareg(yield ~ batch + temp, data = GasolineYield) #' r2_ferrari(model) #' @export r2_ferrari <- function(model, ...) { UseMethod("r2_ferrari") } #' @rdname r2_ferrari #' @export r2_ferrari.default <- function(model, correct_bounds = FALSE, ...) { # on the reponse scale, beta regression link doesn't workd predictions <- stats::predict(model, type = "response") eta <- insight::link_function(model)(predictions) y <- insight::get_response(model) # for ordered beta, fix 0 and 1 to specific bounds if (correct_bounds) { y <- datawizard::normalize(y, include_bounds = FALSE) } ferrari <- stats::cor(eta, insight::link_function(model)(y))^2 out <- list(R2 = c(`Ferrari's R2` = ferrari)) attr(out, "model_type") <- "Generalized Linear" structure(class = "r2_generic", out) } # helper ----------------------------- # .r2_ferrari <- function(model, x) { # if (inherits(model, "glmmTMB")) { # insight::check_if_installed("lme4") # # coefficients, but remove phi parameter # x <- .collapse_cond(lme4::fixef(model)) # x <- x[names(x) != "(phi)"] # } else { # # coefficients, but remove phi parameter # x <- stats::coef(model) # x <- x[names(x) != "(phi)"] # } # # model matrix, check dimensions / length # mm <- insight::get_modelmatrix(model) # if (length(x) != ncol(mm)) { # insight::format_warning("Model matrix and coefficients do not match.") # return(NULL) # } # # linear predictor for the mean # eta <- as.vector(x %*% t(mm)) # y <- insight::get_response(model) # ferrari <- stats::cor(eta, insight::link_function(model)(y))^2 # out <- list(R2 = c(`Ferrari's R2` = ferrari)) # attr(out, "model_type") <- "Generalized Linear" # structure(class = "r2_generic", out) # } performance/R/check_normality.R0000644000176200001440000002163614741711405016266 0ustar liggesusers#' @title Check model for (non-)normality of residuals. #' @name check_normality #' #' @description Check model for (non-)normality of residuals. #' #' @param x A model object. #' @param effects Should normality for residuals (`"fixed"`) or random #' effects (`"random"`) be tested? Only applies to mixed-effects models. #' May be abbreviated. #' @param ... Currently not used. #' #' @return The p-value of the test statistics. A p-value < 0.05 indicates a #' significant deviation from normal distribution. #' #' @note For mixed-effects models, studentized residuals, and *not* #' standardized residuals, are used for the test. There is also a #' [`plot()`-method](https://easystats.github.io/see/articles/performance.html) #' implemented in the [**see**-package](https://easystats.github.io/see/). #' #' @seealso [`see::plot.see_check_normality()`] for options to customize the plot. #' #' @details `check_normality()` calls `stats::shapiro.test` and checks the #' standardized residuals (or studentized residuals for mixed models) for #' normal distribution. Note that this formal test almost always yields #' significant results for the distribution of residuals and visual inspection #' (e.g. Q-Q plots) are preferable. For generalized linear models, no formal #' statistical test is carried out. Rather, there's only a `plot()` method for #' GLMs. This plot shows a half-normal Q-Q plot of the absolute value of the #' standardized deviance residuals is shown (in line with changes in #' `plot.lm()` for R 4.3+). #' #' @examplesIf insight::check_if_installed("see", minimum_version = "0.9.1", quietly = TRUE) #' m <<- lm(mpg ~ wt + cyl + gear + disp, data = mtcars) #' check_normality(m) #' #' # plot results #' x <- check_normality(m) #' plot(x) #' #' \donttest{ #' # QQ-plot #' plot(check_normality(m), type = "qq") #' #' # PP-plot #' plot(check_normality(m), type = "pp") #' } #' @export check_normality <- function(x, ...) { UseMethod("check_normality") } # default ------------------------- #' @export check_normality.default <- function(x, ...) { .is_model_valid(x) if (!insight::model_info(x)$is_linear) { insight::format_alert( "Checking normality of residuals is only appropriate for linear models. It is recommended to use `simulate_residuals()` and `check_residuals()` to check generalized linear (mixed) models for uniformity of residuals." # nolint ) return(NULL) } # check for normality of residuals p.val <- .check_normality(stats::rstandard(x), x) attr(p.val, "data") <- x attr(p.val, "object_name") <- insight::safe_deparse_symbol(substitute(x)) attr(p.val, "effects") <- "fixed" class(p.val) <- unique(c("check_normality", "see_check_normality", class(p.val))) p.val } # glm --------------- #' @export check_normality.glm <- function(x, ...) { out <- 1 attr(out, "data") <- x attr(out, "object_name") <- insight::safe_deparse_symbol(substitute(x)) attr(out, "effects") <- "fixed" attr(out, "model_info") <- insight::model_info(x) class(out) <- unique(c("check_normality", "see_check_normality", class(out))) insight::format_alert( "There's no formal statistical test for normality for generalized linear model.", "Instead, please use `simulate_residuals()` and `check_residuals()` to check for uniformity of residuals." ) invisible(out) } # simulated residuals ---------- #' @export check_normality.performance_simres <- function(x, ...) { # check for normality of residuals res <- stats::residuals(x, quantile_function = stats::qnorm) p.val <- .check_normality(res[!is.infinite(res) & !is.na(res)], x) attr(p.val, "data") <- x attr(p.val, "object_name") <- insight::safe_deparse_symbol(substitute(x)) attr(p.val, "effects") <- "fixed" class(p.val) <- unique(c("check_normality", "see_check_normality", class(p.val))) p.val } # numeric ------------------- #' @export check_normality.numeric <- function(x, ...) { # check for normality of residuals p.val <- .check_normality(x, NULL, type = "raw") attr(p.val, "data") <- x attr(p.val, "object_name") <- insight::safe_deparse(substitute(x)) attr(p.val, "effects") <- "fixed" class(p.val) <- unique(c("check_normality", "see_check_normality", "check_normality_numeric", class(p.val))) p.val } # methods ---------------------- #' @importFrom stats residuals #' @export residuals.check_normality_numeric <- function(object, ...) { attr(object, "data") } #' @importFrom stats rstudent #' @export rstudent.check_normality_numeric <- function(model, ...) { attr(model, "data") } #' @export plot.check_normality <- function(x, ...) { insight::check_if_installed("see", "for residual plots") NextMethod() } #' @export print.check_normality <- function(x, ...) { pstring <- insight::format_p(x) type <- attributes(x)$type if (identical(attributes(x)$effects, "random")) { re_groups <- attributes(x)$re_groups for (i in seq_along(x)) { if (x[i] < 0.05) { insight::print_color( sprintf("Warning: Non-normality for random effects '%s' detected (%s).\n", re_groups[i], pstring[i]), "red" ) } else { insight::print_color( sprintf("OK: Random effects '%s' appear as normally distributed (%s).\n", re_groups[i], pstring[i]), "green" ) } } } else { if (length(x) > 1 && "units" %in% names(attributes(x))) type <- attributes(x)$units for (i in seq_along(x)) { if (x[i] < 0.05) { insight::print_color(sprintf("Warning: Non-normality of %s detected (%s).\n", type[i], pstring[i]), "red") } else { insight::print_color(sprintf("OK: %s appear as normally distributed (%s).\n", type[i], pstring[i]), "green") } } } invisible(x) } # other classes -------------------- # mixed models --------------------- #' @rdname check_normality #' @export check_normality.merMod <- function(x, effects = c("fixed", "random"), ...) { # args effects <- match.arg(effects) info <- insight::model_info(x) # valid model? if (!info$is_linear && effects == "fixed") { insight::format_alert( "Checking normality of residuals is only appropriate for linear models. It is recommended to use `simulate_residuals()` and `check_residuals()` to check generalized linear (mixed) models for uniformity of residuals." # nolint ) return(NULL) } if (effects == "random") { insight::check_if_installed("lme4") re <- tryCatch( { if (inherits(x, "glmmTMB")) { var_attr <- "condVar" .collapse_cond(lme4::ranef(x, condVar = TRUE)) } else { var_attr <- "postVar" lme4::ranef(x, condVar = TRUE) } }, error = function(e) { NULL } ) p.val <- re_groups <- NULL if (!is.null(re)) { for (i in names(re)) { for (j in colnames(re[[i]])) { re_groups <- c(re_groups, paste0(i, ": ", j)) p.val <- c(p.val, .check_normality(re[[i]][[j]], x, "random effects")) } } attr(p.val, "re_qq") <- .model_diagnostic_ranef_qq(x, level = 0.95, model_info = info) attr(p.val, "type") <- "random effects" attr(p.val, "re_groups") <- re_groups } } else if (inherits(x, "glmmTMB")) { p.val <- .check_normality(stats::residuals(x, type = "deviance"), x) } else { # check for normality of residuals p.val <- .check_normality(stats::rstudent(x), x) } attr(p.val, "data") <- x attr(p.val, "object_name") <- insight::safe_deparse_symbol(substitute(x)) attr(p.val, "effects") <- effects class(p.val) <- unique(c("check_normality", "see_check_normality", class(p.val))) p.val } #' @export check_normality.glmmTMB <- check_normality.merMod #' @export check_normality.lmerModLmerTest <- check_normality.merMod #' @export check_normality.afex_aov <- function(x, ...) { r <- suppressMessages(stats::residuals(x, append = FALSE)) p.val <- .check_normality(r, x) attr(p.val, "data") <- x attr(p.val, "object_name") <- insight::safe_deparse_symbol(substitute(x)) class(p.val) <- unique(c("check_normality", "see_check_normality", class(p.val))) invisible(p.val) } #' @export check_normality.BFBayesFactor <- check_normality.afex_aov # helper --------------------- .check_normality <- function(x, model, type = "residuals") { ts_result <- .safe({ if (length(x) >= 5000) { suppressWarnings(stats::ks.test(x, y = "pnorm", alternative = "two.sided")) } else { stats::shapiro.test(x) } }) if (is.null(ts_result)) { insight::print_color( sprintf("`check_normality()` does not support models of class `%s`.\n", class(model)[1]), "red" ) return(NULL) } out <- ts_result$p.value attr(out, "type") <- type out } performance/R/check_heteroscedasticity.R0000644000176200001440000000756614741711350020154 0ustar liggesusers#' @title Check model for (non-)constant error variance #' @name check_heteroscedasticity #' #' @description Significance testing for linear regression models assumes that #' the model errors (or residuals) have constant variance. If this assumption #' is violated the p-values from the model are no longer reliable. #' #' @param x A model object. #' @param ... Currently not used. #' #' @return The p-value of the test statistics. A p-value < 0.05 indicates a #' non-constant variance (heteroskedasticity). #' #' @note There is also a [`plot()`-method](https://easystats.github.io/see/articles/performance.html) #' implemented in the \href{https://easystats.github.io/see/}{\pkg{see}-package}. #' #' @details This test of the hypothesis of (non-)constant error is also called #' *Breusch-Pagan test* (\cite{1979}). #' #' @references Breusch, T. S., and Pagan, A. R. (1979) A simple test for heteroscedasticity #' and random coefficient variation. Econometrica 47, 1287-1294. #' #' @family functions to check model assumptions and and assess model quality #' #' @examples #' m <<- lm(mpg ~ wt + cyl + gear + disp, data = mtcars) #' check_heteroscedasticity(m) #' #' # plot results #' @examplesIf insight::check_if_installed("see", minimum_version = "0.9.1", quietly = TRUE) #' x <- check_heteroscedasticity(m) #' plot(x) #' @export check_heteroscedasticity <- function(x, ...) { UseMethod("check_heteroscedasticity") } #' @name check_heteroscedasticity #' @aliases check_heteroscedasticity #' @export check_heteroskedasticity <- check_heteroscedasticity # default --------------------- #' @export check_heteroscedasticity.default <- function(x, ...) { .is_model_valid(x) # only for linear models info <- insight::model_info(x) if (!info$is_linear) { msg <- "This Breusch-Pagan Test currently only works Gaussian models." if (info$is_count) { paste0(msg, " You may check your model for overdispersion or zero-inflation instead (see 'check_overdispersion()' and 'check_zeroinflation()').") } insight::format_alert(msg) return(NULL) } r <- insight::get_residuals(x, type = "pearson") S.sq <- insight::get_df(x, type = "residual") * .sigma(x)^2 / sum(!is.na(r)) .U <- (r^2) / S.sq mod <- stats::lm(.U ~ stats::fitted(x)) SS <- stats::anova(mod)$`Sum Sq` RegSS <- sum(SS) - SS[length(SS)] Chisq <- RegSS / 2 p.val <- stats::pchisq(Chisq, df = 1, lower.tail = FALSE) attr(p.val, "data") <- x attr(p.val, "object_name") <- insight::safe_deparse_symbol(substitute(x)) class(p.val) <- unique(c("check_heteroscedasticity", "see_check_heteroscedasticity", class(p.val))) p.val } # methods ----------------------- #' @export print.check_heteroscedasticity <- function(x, ...) { if (x < 0.05) { insight::print_color( sprintf( "Warning: Heteroscedasticity (non-constant error variance) detected (%s).\n", insight::format_p(x) ), "red" ) } else { insight::print_color( sprintf( "OK: Error variance appears to be homoscedastic (%s).\n", insight::format_p(x) ), "green" ) } invisible(x) } #' @export plot.check_heteroscedasticity <- function(x, ...) { insight::check_if_installed("see", "for residual plots") NextMethod() } # utilities ----------------------- .sigma <- function(x) { UseMethod(".sigma") } .sigma.default <- function(x) { s <- tryCatch( { estimates <- insight::get_parameters(x)$Estimate sqrt(insight::get_deviance(x) / (insight::n_obs(x) - sum(!is.na(estimates)))) }, error = function(e) { NULL } ) if (insight::is_empty_object(s)) { s <- insight::get_variance_residual(x, verbose = FALSE) } s } .sigma.BFBayesFactor <- function(x) { mean(.get_bfbf_predictions(x)[["sigma"]]) } performance/R/performance_rse.R0000644000176200001440000000126014257537777016300 0ustar liggesusers#' @title Residual Standard Error for Linear Models #' @name performance_rse #' #' @description Compute residual standard error of linear models. #' #' @inheritParams performance_rmse #' #' @details The residual standard error is the square root of the residual #' sum of squares divided by the residual degrees of freedom. #' #' @return Numeric, the residual standard error of `model`. #' #' @examples #' data(mtcars) #' m <- lm(mpg ~ hp + gear, data = mtcars) #' performance_rse(m) #' @export performance_rse <- function(model) { # Residual standard error sqrt(sum(insight::get_residuals(model)^2, na.rm = TRUE) / insight::get_df(model, type = "residual")) } performance/R/item_difficulty.R0000644000176200001440000000700214736731423016270 0ustar liggesusers#' @title Difficulty of Questionnaire Items #' @name item_difficulty #' #' @description Compute various measures of internal consistencies #' for tests or item-scales of questionnaires. #' #' @param x Depending on the function, `x` may be a `matrix` as #' returned by the `cor()`-function, or a data frame #' with items (e.g. from a test or questionnaire). #' @param maximum_value Numeric value, indicating the maximum value of an item. #' If `NULL` (default), the maximum is taken from the maximum value of all #' columns in `x` (assuming that the maximum value at least appears once in #' the data). If `NA`, each item's maximum value is taken as maximum. If the #' required maximum value is not present in the data, specify the theoreritcal #' maximum using `maximum_value`. #' @return A data frame with three columns: The name(s) of the item(s), the item #' difficulties for each item, and the ideal item difficulty. #' #' @details _Item difficutly_ of an item is defined as the quotient of the sum #' actually achieved for this item of all and the maximum achievable score. #' This function calculates the item difficulty, which should range between #' 0.2 and 0.8. Lower values are a signal for more difficult items, while #' higher values close to one are a sign for easier items. The ideal value #' for item difficulty is `p + (1 - p) / 2`, where `p = 1 / max(x)`. In most #' cases, the ideal item difficulty lies between 0.5 and 0.8. #' #' @references #' - Bortz, J., and Döring, N. (2006). Quantitative Methoden der Datenerhebung. #' In J. Bortz and N. Döring, Forschungsmethoden und Evaluation. Springer: #' Berlin, Heidelberg: 137–293 #' - Kelava A, Moosbrugger H (2020). Deskriptivstatistische Itemanalyse und #' Testwertbestimmung. In: Moosbrugger H, Kelava A, editors. Testtheorie und #' Fragebogenkonstruktion. Berlin, Heidelberg: Springer, 143–158 #' #' @examples #' data(mtcars) #' x <- mtcars[, c("cyl", "gear", "carb", "hp")] #' item_difficulty(x) #' @export item_difficulty <- function(x, maximum_value = NULL) { # find general maximum of scale if (is.null(maximum_value)) { maximum_value <- suppressWarnings(max(vapply(x, max, numeric(1L), na.rm = TRUE))) } else if (!is.na(maximum_value) && !is.numeric(maximum_value)) { insight::format_error("`maximum_value` must be a numeric value, indicating the maximum value of an item.") } d <- vapply(x, function(.x) { # general maximum value, or per-item maximum value? if (is.na(maximum_value)) { max_val <- max(.x, na.rm = TRUE) } else { max_val <- maximum_value } .x <- .x[!is.na(.x)] round(sum(.x) / (max_val * length(.x)), 2) }, numeric(1)) # ideal item item_difficulty fun.diff.ideal <- function(.x) { # general maximum value, or per-item maximum value? if (is.na(maximum_value)) { max_val <- max(.x, na.rm = TRUE) } else { max_val <- maximum_value } p <- 1 / max_val round(p + (1 - p) / 2, 2) } di <- vapply(x, fun.diff.ideal, numeric(1)) structure( class = c("item_difficulty", "data.frame"), data.frame( Item = colnames(x), Difficulty = d, Ideal = di, stringsAsFactors = FALSE ) ) } # methods -------------------------------------- #' @export print.item_difficulty <- function(x, ...) { out <- insight::format_table(x, ...) cat(insight::export_table(out, caption = c("Item Difficulty", "blue"), ...)) invisible(x) } performance/R/item_split_half.R0000644000176200001440000000330114257537777016267 0ustar liggesusers#' @title Split-Half Reliability #' @name item_split_half #' #' @description Compute various measures of internal consistencies #' for tests or item-scales of questionnaires. #' #' @param x A matrix or a data frame. #' @param digits Amount of digits for returned values. #' #' @return A list with two elements: the split-half reliability `splithalf` #' and the Spearman-Brown corrected split-half reliability #' `spearmanbrown`. #' #' @details This function calculates the split-half reliability for items in #' `x`, including the Spearman-Brown adjustment. Splitting is done by #' selecting odd versus even columns in `x`. A value closer to 1 #' indicates greater internal consistency. #' #' @references #' - Spearman C. 1910. Correlation calculated from faulty data. British #' Journal of Psychology (3): 271-295. \doi{10.1111/j.2044-8295.1910.tb00206.x} #' #' - Brown W. 1910. Some experimental results in the correlation of mental #' abilities. British Journal of Psychology (3): 296-322. \doi{10.1111/j.2044-8295.1910.tb00207.x} #' #' @examples #' data(mtcars) #' x <- mtcars[, c("cyl", "gear", "carb", "hp")] #' item_split_half(x) #' @export item_split_half <- function(x, digits = 3) { # Calculating total score for even items score_e <- rowMeans(x[, c(TRUE, FALSE), drop = FALSE], na.rm = TRUE) # Calculating total score for odd items score_o <- rowMeans(x[, c(FALSE, TRUE), drop = FALSE], na.rm = TRUE) # Correlating scores from even and odd items shr <- stats::cor(score_e, score_o, use = "complete.obs") # Adjusting with the Spearman-Brown prophecy formula sb.shr <- (2 * shr) / (1 + shr) list(splithalf = shr, spearmanbrown = sb.shr) } performance/R/r2_mlm.R0000644000176200001440000000622014666017356014305 0ustar liggesusers#' @title Multivariate R2 #' @name r2_mlm #' #' @description #' Calculates two multivariate R2 values for multivariate linear regression. #' #' @param model Multivariate linear regression model. #' @param ... Currently not used. #' #' @details #' The two indexes returned summarize model fit for the set of predictors #' given the system of responses. As compared to the default #' [r2][performance::r2] index for multivariate linear models, the indexes #' returned by this function provide a single fit value collapsed across #' all responses. #' #' The two returned indexes were proposed by *Van den Burg and Lewis (1988)* #' as an extension of the metrics proposed by *Cramer and Nicewander (1979)*. #' Of the numerous indexes proposed across these two papers, only two metrics, #' the \eqn{R_{xy}} and \eqn{P_{xy}}, are recommended for use #' by *Azen and Budescu (2006)*. #' #' For a multivariate linear regression with \eqn{p} predictors and #' \eqn{q} responses where \eqn{p > q}, the \eqn{R_{xy}} index is #' computed as: #' #' \deqn{R_{xy} = 1 - \prod_{i=1}^p (1 - \rho_i^2)} #' #' Where \eqn{\rho} is a canonical variate from a #' [canonical correlation][cancor] between the predictors and responses. #' This metric is symmetric and its value does not change when the roles of #' the variables as predictors or responses are swapped. #' #' The \eqn{P_{xy}} is computed as: #' #' \deqn{P_{xy} = \frac{q - trace(\bf{S}_{\bf{YY}}^{-1}\bf{S}_{\bf{YY|X}})}{q}} #' #' Where \eqn{\bf{S}_{\bf{YY}}} is the matrix of response covariances and #' \eqn{\bf{S}_{\bf{YY|X}}} is the matrix of residual covariances given #' the predictors. This metric is asymmetric and can change #' depending on which variables are considered predictors versus responses. #' #' @return A named vector with the R2 values. #' #' @examples #' model <- lm(cbind(qsec, drat) ~ wt + mpg + cyl, data = mtcars) #' r2_mlm(model) #' #' model_swap <- lm(cbind(wt, mpg, cyl) ~ qsec + drat, data = mtcars) #' r2_mlm(model_swap) #' #' @references #' - Azen, R., & Budescu, D. V. (2006). Comparing predictors in #' multivariate regression models: An extension of dominance analysis. #' Journal of Educational and Behavioral Statistics, 31(2), 157-180. #' - Cramer, E. M., & Nicewander, W. A. (1979). Some symmetric, #' invariant measures of multivariate association. Psychometrika, 44, 43-54. #' - Van den Burg, W., & Lewis, C. (1988). Some properties of two #' measures of multivariate association. Psychometrika, 53, 109-122. #' #' @author Joseph Luchman #' #' @export r2_mlm <- function(model, ...) { UseMethod("r2_mlm") } # methods --------------------------- #' @export r2_mlm.mlm <- function(model, verbose = TRUE, ...) { rho2_vec <- 1 - stats::cancor( insight::get_predictors(model), insight::get_response(model) )$cor^2 R_xy <- 1 - Reduce(`*`, rho2_vec, 1) resid_cov <- stats::cov(residuals(model)) resp_cov <- stats::cov(insight::get_response(model)) qq <- ncol(insight::get_response(model)) V_xy <- qq - sum(diag(solve(resp_cov) %*% resid_cov)) P_xy <- V_xy / qq c("Symmetric Rxy" = R_xy, "Asymmetric Pxy" = P_xy) } performance/R/item_intercor.R0000644000176200001440000000404114500061526015740 0ustar liggesusers#' @title Mean Inter-Item-Correlation #' @name item_intercor #' #' @description Compute various measures of internal consistencies #' for tests or item-scales of questionnaires. #' #' @param x A matrix as returned by the `cor()`-function, #' or a data frame with items (e.g. from a test or questionnaire). #' @param method Correlation computation method. May be one of #' `"pearson"` (default), `"spearman"` or `"kendall"`. #' You may use initial letter only. #' #' @return The mean inter-item-correlation value for `x`. #' #' @details This function calculates a mean inter-item-correlation, i.e. a #' correlation matrix of `x` will be computed (unless `x` is already a matrix #' as returned by the `cor()` function) and the mean of the sum of all items' #' correlation values is returned. Requires either a data frame or a computed #' `cor()` object. #' #' "Ideally, the average inter-item correlation for a set of items should be #' between 0.20 and 0.40, suggesting that while the items are reasonably #' homogeneous, they do contain sufficiently unique variance so as to not be #' isomorphic with each other. When values are lower than 0.20, then the items #' may not be representative of the same content domain. If values are higher #' than 0.40, the items may be only capturing a small bandwidth of the #' construct." _(Piedmont 2014)_ #' #' @references #' Piedmont RL. 2014. Inter-item Correlations. In: Michalos AC (eds) #' Encyclopedia of Quality of Life and Well-Being Research. Dordrecht: Springer, #' 3303-3304. \doi{10.1007/978-94-007-0753-5_1493} #' #' @examples #' data(mtcars) #' x <- mtcars[, c("cyl", "gear", "carb", "hp")] #' item_intercor(x) #' @export item_intercor <- function(x, method = c("pearson", "spearman", "kendall")) { # Check parameter method <- match.arg(method) # Mean-interitem-corelation if (inherits(x, "matrix")) { corr <- x } else { x <- stats::na.omit(x) corr <- stats::cor(x, method = method) } mean(corr[lower.tri(corr)]) } performance/R/check_predictions.R0000644000176200001440000004652714741714041016600 0ustar liggesusers#' @title Posterior predictive checks #' @name check_predictions #' #' @description Posterior predictive checks mean "simulating replicated data #' under the fitted model and then comparing these to the observed data" #' (_Gelman and Hill, 2007, p. 158_). Posterior predictive checks #' can be used to "look for systematic discrepancies between real and #' simulated data" (_Gelman et al. 2014, p. 169_). #' #' **performance** provides posterior predictive check methods for a variety #' of frequentist models (e.g., `lm`, `merMod`, `glmmTMB`, ...). For Bayesian #' models, the model is passed to [`bayesplot::pp_check()`]. #' #' If `check_predictions()` doesn't work as expected, try setting #' `verbose = TRUE` to get hints about possible problems. #' #' @param object A statistical model. #' @param iterations The number of draws to simulate/bootstrap. #' @param check_range Logical, if `TRUE`, includes a plot with the minimum #' value of the original response against the minimum values of the replicated #' responses, and the same for the maximum value. This plot helps judging whether #' the variation in the original data is captured by the model or not #' (_Gelman et al. 2020, pp.163_). The minimum and maximum values of `y` should #' be inside the range of the related minimum and maximum values of `yrep`. #' @param re_formula Formula containing group-level effects (random effects) to #' be considered in the simulated data. If `NULL` (default), condition #' on all random effects. If `NA` or `~0`, condition on no random #' effects. See `simulate()` in **lme4**. #' @param bandwidth A character string indicating the smoothing bandwidth to #' be used. Unlike `stats::density()`, which used `"nrd0"` as default, the #' default used here is `"nrd"` (which seems to give more plausible results #' for non-Gaussian models). When problems with plotting occur, try to change #' to a different value. #' @param type Plot type for the posterior predictive checks plot. Can be `"density"`, #' `"discrete_dots"`, `"discrete_interval"` or `"discrete_both"` (the `discrete_*` #' options are appropriate for models with discrete - binary, integer or ordinal #' etc. - outcomes). #' @param verbose Toggle warnings. #' @param ... Passed down to `simulate()`. #' #' @return A data frame of simulated responses and the original response vector. #' #' @seealso [`simulate_residuals()`] and [`check_residuals()`]. See also #' [`see::print.see_performance_pp_check()`] for options to customize the plot. #' #' @details An example how posterior predictive checks can also be used for model #' comparison is Figure 6 from _Gabry et al. 2019, Figure 6_. #' #' \if{html}{\cr \figure{pp_check.png}{options: width="90\%" alt="Posterior Predictive Check"} \cr} #' The model shown in the right panel (b) can simulate new data that are more #' similar to the observed outcome than the model in the left panel (a). Thus, #' model (b) is likely to be preferred over model (a). #' #' @note Every model object that has a `simulate()`-method should work with #' `check_predictions()`. On R 3.6.0 and higher, if **bayesplot** (or a #' package that imports **bayesplot** such as **rstanarm** or **brms**) #' is loaded, `pp_check()` is also available as an alias for `check_predictions()`. #' #' If `check_predictions()` doesn't work as expected, try setting `verbose = TRUE` #' to get hints about possible problems. #' #' @family functions to check model assumptions and and assess model quality #' #' @references #' - Gabry, J., Simpson, D., Vehtari, A., Betancourt, M., and Gelman, A. (2019). #' Visualization in Bayesian workflow. Journal of the Royal Statistical Society: #' Series A (Statistics in Society), 182(2), 389–402. https://doi.org/10.1111/rssa.12378 #' #' - Gelman, A., and Hill, J. (2007). Data analysis using regression and #' multilevel/hierarchical models. Cambridge; New York: Cambridge University Press. #' #' - Gelman, A., Carlin, J. B., Stern, H. S., Dunson, D. B., Vehtari, A., and #' Rubin, D. B. (2014). Bayesian data analysis. (Third edition). CRC Press. #' #' - Gelman, A., Hill, J., and Vehtari, A. (2020). Regression and Other Stories. #' Cambridge University Press. #' #' @examplesIf insight::check_if_installed("see", minimum_version = "0.9.1", quietly = TRUE) #' # linear model #' model <- lm(mpg ~ disp, data = mtcars) #' check_predictions(model) #' #' # discrete/integer outcome #' set.seed(99) #' d <- iris #' d$skewed <- rpois(150, 1) #' model <- glm( #' skewed ~ Species + Petal.Length + Petal.Width, #' family = poisson(), #' data = d #' ) #' check_predictions(model, type = "discrete_both") #' #' @export check_predictions <- function(object, ...) { UseMethod("check_predictions") } #' @rdname check_predictions #' @export check_predictions.default <- function(object, iterations = 50, check_range = FALSE, re_formula = NULL, bandwidth = "nrd", type = "density", verbose = TRUE, ...) { .is_model_valid(object) # check_predictions() can't handle exotic formula notation if (verbose) { insight::formula_ok( object, action = "error", prefix_msg = "Posterior predictive checks failed due to an incompatible model formula." # nolint ) } # retrieve model information minfo <- insight::model_info(object, verbose = FALSE) # try to find sensible default for "type" argument suggest_dots <- (minfo$is_bernoulli || minfo$is_count || minfo$is_ordinal || minfo$is_categorical || minfo$is_multinomial) # nolint if (missing(type) && suggest_dots) { type <- "discrete_interval" } # args type <- match.arg(type, choices = c("density", "discrete_dots", "discrete_interval", "discrete_both")) pp_check.lm( object, iterations = iterations, check_range = check_range, re_formula = re_formula, bandwidth = bandwidth, type = type, verbose = verbose, model_info = minfo, ... ) } #' @export check_predictions.stanreg <- function(object, iterations = 50, check_range = FALSE, re_formula = NULL, bandwidth = "nrd", type = "density", verbose = TRUE, ...) { # retrieve model information minfo <- insight::model_info(object, verbose = FALSE) # try to find sensible default for "type" argument suggest_dots <- (minfo$is_bernoulli || minfo$is_count || minfo$is_ordinal || minfo$is_categorical || minfo$is_multinomial) # nolint if (missing(type) && suggest_dots) { type <- "discrete_interval" } # args type <- match.arg(type, choices = c("density", "discrete_dots", "discrete_interval", "discrete_both")) # convert to type-argument for pp_check pp_type <- switch(type, density = "dens", "bars" ) insight::check_if_installed( "bayesplot", "to create posterior prediction plots for Stan models" ) # for plotting resp_string <- insight::find_terms(object)$response if (inherits(object, "brmsfit")) { out <- as.data.frame(bayesplot::pp_check(object, type = pp_type, ndraws = iterations, ...)$data) } else { out <- as.data.frame(bayesplot::pp_check(object, type = pp_type, nreps = iterations, ...)$data) } # bring data into shape, like we have for other models with `check_predictions()` if (pp_type == "dens") { d_filter <- out[!out$is_y, ] d_filter <- datawizard::data_to_wide( d_filter, id_cols = "y_id", values_from = "value", names_from = "rep_id" ) d_filter$y_id <- NULL colnames(d_filter) <- paste0("sim_", colnames(d_filter)) d_filter$y <- out$value[out$is_y] out <- d_filter } else { colnames(out) <- c("x", "y", "CI_low", "Mean", "CI_high") # to long, for plotting out <- datawizard::data_to_long( out, select = c("y", "Mean"), names_to = "Group", values_to = "Count" ) } attr(out, "is_stan") <- TRUE attr(out, "check_range") <- check_range attr(out, "response_name") <- resp_string attr(out, "bandwidth") <- bandwidth attr(out, "model_info") <- minfo attr(out, "type") <- type class(out) <- c("performance_pp_check", "see_performance_pp_check", class(out)) out } #' @export check_predictions.brmsfit <- check_predictions.stanreg #' @export check_predictions.BFBayesFactor <- function(object, iterations = 50, check_range = FALSE, re_formula = NULL, bandwidth = "nrd", verbose = TRUE, ...) { everything_we_need <- .get_bfbf_predictions(object, iterations = iterations) y <- everything_we_need[["y"]] sig <- everything_we_need[["sigma"]] if (isTRUE(is.na(re_formula))) { yy <- everything_we_need[["y_pred_marginal"]] } else { if (!is.null(re_formula)) { insight::format_warning("`re_formula` can only be `NULL` or `NA`.") } yy <- everything_we_need[["y_pred"]] } yrep <- apply(yy, 2, function(mu) stats::rnorm(length(mu), mu, sig)) yrep <- t(yrep) out <- as.data.frame(yrep) colnames(out) <- paste0("sim_", seq_len(ncol(out))) out$y <- y attr(out, "bandwidth") <- bandwidth attr(out, "check_range") <- check_range class(out) <- c("performance_pp_check", "see_performance_pp_check", class(out)) out } pp_check.BFBayesFactor <- check_predictions.BFBayesFactor #' @export check_predictions.lme <- function(object, ...) { insight::format_error("`check_predictions()` does currently not work for models of class `lme`.") } # pp-check functions ------------------------------------- pp_check.lm <- function(object, iterations = 50, check_range = FALSE, re_formula = NULL, bandwidth = "nrd", type = "density", verbose = TRUE, model_info = NULL, ...) { # if we have a matrix-response, continue here... if (grepl("^cbind\\((.*)\\)", insight::find_response(object, combine = TRUE))) { return(pp_check.glm(object, iterations, check_range, re_formula, bandwidth, type, verbose, model_info, ...)) } # else, proceed as usual out <- .safe(stats::simulate(object, nsim = iterations, re.form = re_formula, ...)) # validation check, for mixed models, where re.form = NULL (default) might fail out <- .check_re_formula(out, object, iterations, re_formula, verbose, ...) # save information about model if (is.null(model_info)) { minfo <- insight::model_info(object) } else { minfo <- model_info } # glmmTMB returns column matrix for bernoulli if (inherits(object, "glmmTMB") && minfo$is_binomial && !is.null(out)) { out <- as.data.frame(lapply(out, function(i) { if (is.matrix(i)) { i[, 1] } else { i } })) } if (is.null(out)) { insight::format_error(sprintf( "Could not simulate responses. Maybe there is no `simulate()` for objects of class `%s`?", class(object)[1] )) } # get response data, and response term, to check for transformations response <- insight::get_response(object) resp_string <- insight::find_terms(object)$response pattern <- "^(scale|exp|expm1|log|log1p|log10|log2|sqrt)" # check for transformed response, and backtransform simulations if (!is.null(resp_string) && length(resp_string) == 1 && grepl(paste0(pattern, "\\("), resp_string)) { out <- .backtransform_sims(out, resp_string) } # sanity check - do we have a ratio or similar? if (is.data.frame(response)) { # get response data, evaluate formula response <- eval(str2lang(insight::find_response(object)), envir = insight::get_response(object) ) } out$y <- response attr(out, "check_range") <- check_range attr(out, "response_name") <- resp_string attr(out, "bandwidth") <- bandwidth attr(out, "model_info") <- minfo attr(out, "type") <- type class(out) <- c("performance_pp_check", "see_performance_pp_check", class(out)) out } pp_check.glm <- function(object, iterations = 50, check_range = FALSE, re_formula = NULL, bandwidth = "nrd", type = "density", verbose = TRUE, model_info = NULL, ...) { # if we have no matrix-response, continue here... if (!grepl("^cbind\\((.*)\\)", insight::find_response(object, combine = TRUE))) { return(pp_check.lm(object, iterations, check_range, re_formula, bandwidth, type, verbose, model_info, ...)) } # else, process matrix response. for matrix response models, we compute # the ratio of successes and failures, because the plot cannot handle # matrix columns with separate success/failures in simulations. out <- tryCatch( { matrix_sim <- stats::simulate(object, nsim = iterations, re.form = re_formula, ...) as.data.frame(sapply(matrix_sim, function(i) i[, 1] / rowSums(i, na.rm = TRUE), simplify = TRUE)) }, error = function(e) { NULL } ) # validation check, for mixed models, where re.form = NULL (default) might fail out <- .check_re_formula(out, object, iterations, re_formula, verbose, ...) if (is.null(out)) { insight::format_error(sprintf( "Could not simulate responses. Maybe there is no `simulate()` for objects of class `%s`?", class(object)[1] )) } # get response data, and response term response <- eval(str2lang(insight::find_response(object)), envir = insight::get_response(object) ) resp_string <- insight::find_terms(object)$response out$y <- response[, 1] / rowSums(response, na.rm = TRUE) # safe information about model if (is.null(model_info)) { minfo <- insight::model_info(object) } else { minfo <- model_info } attr(out, "check_range") <- check_range attr(out, "response_name") <- resp_string attr(out, "bandwidth") <- bandwidth attr(out, "model_info") <- minfo attr(out, "type") <- type class(out) <- c("performance_pp_check", "see_performance_pp_check", class(out)) out } # styler: off pp_check.glmmTMB <- pp_check.glm.nb <- pp_check.lme <- pp_check.merMod <- pp_check.MixMod <- pp_check.mle2 <- pp_check.negbin <- pp_check.polr <- pp_check.rma <- pp_check.vlm <- pp_check.wbm <- pp_check.lm # styler: on #' @rawNamespace #' S3method(bayesplot::pp_check, lm) #' S3method(bayesplot::pp_check, glm) #' S3method(bayesplot::pp_check, glmmTMB) #' S3method(bayesplot::pp_check, glm.nb) #' S3method(bayesplot::pp_check, merMod) #' S3method(bayesplot::pp_check, MixMod) #' S3method(bayesplot::pp_check, mle2) #' S3method(bayesplot::pp_check, negbin) #' S3method(bayesplot::pp_check, polr) #' S3method(bayesplot::pp_check, rma) #' S3method(bayesplot::pp_check, vlm) #' S3method(bayesplot::pp_check, wbm) #' S3method(bayesplot::pp_check, BFBayesFactor) # methods ----------------------- #' @export print.performance_pp_check <- function(x, verbose = TRUE, ...) { original <- x$y replicated <- x[which(names(x) != "y")] if (isTRUE(verbose)) { if (is.numeric(original)) { if (min(replicated) > min(original)) { insight::print_color( insight::format_message( "Warning: Minimum value of original data is not included in the replicated data.", "Model may not capture the variation of the data." ), "red" ) } if (max(replicated) < max(original)) { insight::print_color( insight::format_message( "Warning: Maximum value of original data is not included in the replicated data.", "Model may not capture the variation of the data." ), "red" ) } } else { missing_levs <- setdiff(original, unlist(replicated)) if (length(missing_levs)) { insight::print_color( insight::format_message( paste0( "Warning: Level", ifelse(length(missing_levs) == 1, " ", "s "), paste0("'", missing_levs, "'", collapse = ", "), " from original data is not included in the replicated data." ), "Model may not capture the variation of the data." ), "red" ) } } } if (requireNamespace("see", quietly = TRUE)) { NextMethod() } invisible(x) } #' @export plot.performance_pp_check <- function(x, ...) { insight::check_if_installed("see", "to plot posterior predictive checks") NextMethod() } # helper -------------------- .backtransform_sims <- function(sims, resp_string) { if (grepl("log(log(", resp_string, fixed = TRUE)) { sims[] <- lapply(sims, function(i) exp(exp(i))) } else if (grepl("log(", resp_string, fixed = TRUE)) { # exceptions: log(x+1) or log(1+x) # 1. try: log(x + number) plus_minus <- .safe(eval(parse(text = gsub("log\\(([^,\\+)]*)(.*)\\)", "\\2", resp_string)))) # 2. try: log(number + x) if (is.null(plus_minus)) { plus_minus <- .safe(eval(parse(text = gsub("log\\(([^,\\+)]*)(.*)\\)", "\\1", resp_string)))) } if (is.null(plus_minus) || !is.numeric(plus_minus)) { sims[] <- lapply(sims, exp) } else { sims[] <- lapply(sims, function(i) exp(i) - plus_minus) } } else if (grepl("log1p(", resp_string, fixed = TRUE)) { sims[] <- lapply(sims, expm1) } else if (grepl("log10(", resp_string, fixed = TRUE)) { sims[] <- lapply(sims, function(i) 10^i) } else if (grepl("log2(", resp_string, fixed = TRUE)) { sims[] <- lapply(sims, function(i) 2^i) } else if (grepl("sqrt(", resp_string, fixed = TRUE)) { sims[] <- lapply(sims, function(i) i^2) } else if (grepl("exp(", resp_string, fixed = TRUE)) { sims[] <- lapply(sims, log) } else if (grepl("expm1(", resp_string, fixed = TRUE)) { sims[] <- lapply(sims, log1p) } sims } .check_re_formula <- function(out, object, iterations, re_formula, verbose, ...) { # validation check, for mixed models, where re.form = NULL (default) might fail if (is.null(out) && insight::is_mixed_model(object) && !isTRUE(is.na(re_formula))) { if (verbose) { insight::format_alert( paste0( "Failed to compute posterior predictive checks with `re_formula=", deparse(re_formula), "`." ), "Trying again with `re_formula=NA` now." ) } out <- .safe(stats::simulate(object, nsim = iterations, re.form = NA, ...)) } out } performance/R/check_outliers.R0000644000176200001440000020376514741714051016123 0ustar liggesusers#' @title Outliers detection (check for influential observations) #' @name check_outliers #' #' @description Checks for and locates influential observations (i.e., #' "outliers") via several distance and/or clustering methods. If several #' methods are selected, the returned "Outlier" vector will be a composite #' outlier score, made of the average of the binary (0 or 1) results of each #' method. It represents the probability of each observation of being #' classified as an outlier by at least one method. The decision rule used by #' default is to classify as outliers observations which composite outlier #' score is superior or equal to 0.5 (i.e., that were classified as outliers #' by at least half of the methods). See the **Details** section below #' for a description of the methods. #' #' @param x A model, a data.frame, a `performance_simres` [`simulate_residuals()`] #' or a `DHARMa` object. #' @param method The outlier detection method(s). Can be `"all"` or some of #' `"cook"`, `"pareto"`, `"zscore"`, `"zscore_robust"`, `"iqr"`, `"ci"`, `"eti"`, #' `"hdi"`, `"bci"`, `"mahalanobis"`, `"mahalanobis_robust"`, `"mcd"`, `"ics"`, #' `"optics"` or `"lof"`. #' @param threshold A list containing the threshold values for each method (e.g. #' `list('mahalanobis' = 7, 'cook' = 1)`), above which an observation is #' considered as outlier. If `NULL`, default values will be used (see #' 'Details'). If a numeric value is given, it will be used as the threshold #' for any of the method run. #' @param ID Optional, to report an ID column along with the row number. #' @param type Type of method to test for outliers. Can be one of `"default"`, #' `"binomial"` or `"bootstrap"`. Only applies when `x` is an object returned #' by `simulate_residuals()` or of class `DHARMa`. See 'Details' in #' `?DHARMa::testOutliers` for a detailed description of the types. #' @param verbose Toggle warnings. #' @param ... When `method = "ics"`, further arguments in `...` are passed #' down to [ICSOutlier::ics.outlier()]. When `method = "mahalanobis"`, #' they are passed down to [stats::mahalanobis()]. `percentage_central` can #' be specified when `method = "mcd"`. For objects of class `performance_simres` #' or `DHARMa`, further arguments are passed down to `DHARMa::testOutliers()`. #' #' @inheritParams check_zeroinflation #' @inheritParams simulate_residuals #' #' @return A logical vector of the detected outliers with a nice printing #' method: a check (message) on whether outliers were detected or not. The #' information on the distance measure and whether or not an observation is #' considered as outlier can be recovered with the [as.data.frame] #' function. Note that the function will (silently) return a vector of `FALSE` #' for non-supported data types such as character strings. #' #' @family functions to check model assumptions and and assess model quality #' #' @seealso [`see::plot.see_check_outliers()`] for options to customize the plot. #' #' @note There is also a #' [`plot()`-method](https://easystats.github.io/see/articles/performance.html) #' implemented in the #' \href{https://easystats.github.io/see/}{\pkg{see}-package}. **Please #' note** that the range of the distance-values along the y-axis is re-scaled #' to range from 0 to 1. #' #' @details Outliers can be defined as particularly influential observations. #' Most methods rely on the computation of some distance metric, and the #' observations greater than a certain threshold are considered outliers. #' Importantly, outliers detection methods are meant to provide information to #' consider for the researcher, rather than to be an automatized procedure #' which mindless application is a substitute for thinking. #' #' An **example sentence** for reporting the usage of the composite method #' could be: #' #' *"Based on a composite outlier score (see the 'check_outliers' function #' in the 'performance' R package; Lüdecke et al., 2021) obtained via the joint #' application of multiple outliers detection algorithms (Z-scores, Iglewicz, #' 1993; Interquartile range (IQR); Mahalanobis distance, Cabana, 2019; Robust #' Mahalanobis distance, Gnanadesikan and Kettenring, 1972; Minimum Covariance #' Determinant, Leys et al., 2018; Invariant Coordinate Selection, Archimbaud et #' al., 2018; OPTICS, Ankerst et al., 1999; Isolation Forest, Liu et al. 2008; #' and Local Outlier Factor, Breunig et al., 2000), we excluded n participants #' that were classified as outliers by at least half of the methods used."* #' #' @section Model-specific methods: #' #' - **Cook's Distance**: #' Among outlier detection methods, Cook's distance and leverage are less #' common than the basic Mahalanobis distance, but still used. Cook's distance #' estimates the variations in regression coefficients after removing each #' observation, one by one (Cook, 1977). Since Cook's distance is in the metric #' of an F distribution with p and n-p degrees of freedom, the median point of #' the quantile distribution can be used as a cut-off (Bollen, 1985). A common #' approximation or heuristic is to use 4 divided by the numbers of #' observations, which usually corresponds to a lower threshold (i.e., more #' outliers are detected). This only works for frequentist models. For Bayesian #' models, see `pareto`. #' #' - **Pareto**: #' The reliability and approximate convergence of Bayesian models can be #' assessed using the estimates for the shape parameter k of the generalized #' Pareto distribution. If the estimated tail shape parameter k exceeds 0.5, the #' user should be warned, although in practice the authors of the **loo** #' package observed good performance for values of k up to 0.7 (the default #' threshold used by `performance`). #' #' @section Univariate methods: #' #' - **Z-scores** `("zscore", "zscore_robust")`: #' The Z-score, or standard score, is a way of describing a data point as #' deviance from a central value, in terms of standard deviations from the mean #' (`"zscore"`) or, as it is here the case (`"zscore_robust"`) by #' default (Iglewicz, 1993), in terms of Median Absolute Deviation (MAD) from #' the median (which are robust measures of dispersion and centrality). The #' default threshold to classify outliers is 1.959 (`threshold = list("zscore" = 1.959)`), #' corresponding to the 2.5% (`qnorm(0.975)`) most extreme observations #' (assuming the data is normally distributed). Importantly, the Z-score #' method is univariate: it is computed column by column. If a data frame is #' passed, the Z-score is calculated for each variable separately, and the #' maximum (absolute) Z-score is kept for each observations. Thus, all #' observations that are extreme on at least one variable might be detected #' as outliers. Thus, this method is not suited for high dimensional data #' (with many columns), returning too liberal results (detecting many outliers). #' #' - **IQR** `("iqr")`: #' Using the IQR (interquartile range) is a robust method developed by John #' Tukey, which often appears in box-and-whisker plots (e.g., in #' [ggplot2::geom_boxplot]). The interquartile range is the range between the first #' and the third quartiles. Tukey considered as outliers any data point that #' fell outside of either 1.5 times (the default threshold is 1.7) the IQR below #' the first or above the third quartile. Similar to the Z-score method, this is #' a univariate method for outliers detection, returning outliers detected for #' at least one column, and might thus not be suited to high dimensional data. #' The distance score for the IQR is the absolute deviation from the median of #' the upper and lower IQR thresholds. Then, this value is divided by the IQR #' threshold, to “standardize” it and facilitate interpretation. #' #' - **CI** `("ci", "eti", "hdi", "bci")`: #' Another univariate method is to compute, for each variable, some sort of #' "confidence" interval and consider as outliers values lying beyond the edges #' of that interval. By default, `"ci"` computes the Equal-Tailed Interval #' (`"eti"`), but other types of intervals are available, such as Highest #' Density Interval (`"hdi"`) or the Bias Corrected and Accelerated #' Interval (`"bci"`). The default threshold is `0.95`, considering #' as outliers all observations that are outside the 95% CI on any of the #' variable. See [bayestestR::ci()] for more details #' about the intervals. The distance score for the CI methods is the absolute #' deviation from the median of the upper and lower CI thresholds. Then, this #' value is divided by the difference between the upper and lower CI bounds #' divided by two, to “standardize” it and facilitate interpretation. #' #' @section Multivariate methods: #' #' - **Mahalanobis Distance**: #' Mahalanobis distance (Mahalanobis, 1930) is often used for multivariate #' outliers detection as this distance takes into account the shape of the #' observations. The default `threshold` is often arbitrarily set to some #' deviation (in terms of SD or MAD) from the mean (or median) of the #' Mahalanobis distance. However, as the Mahalanobis distance can be #' approximated by a Chi squared distribution (Rousseeuw and Van Zomeren, 1990), #' we can use the alpha quantile of the chi-square distribution with k degrees #' of freedom (k being the number of columns). By default, the alpha threshold #' is set to 0.025 (corresponding to the 2.5\% most extreme observations; #' Cabana, 2019). This criterion is a natural extension of the median plus or #' minus a coefficient times the MAD method (Leys et al., 2013). #' #' - **Robust Mahalanobis Distance**: #' A robust version of Mahalanobis distance using an Orthogonalized #' Gnanadesikan-Kettenring pairwise estimator (Gnanadesikan and Kettenring, #' 1972). Requires the **bigutilsr** package. See the [bigutilsr::dist_ogk()] #' function. #' #' - **Minimum Covariance Determinant (MCD)**: #' Another robust version of Mahalanobis. Leys et al. (2018) argue that #' Mahalanobis Distance is not a robust way to determine outliers, as it uses #' the means and covariances of all the data - including the outliers - to #' determine individual difference scores. Minimum Covariance Determinant #' calculates the mean and covariance matrix based on the most central subset of #' the data (by default, 66\%), before computing the Mahalanobis Distance. This #' is deemed to be a more robust method of identifying and removing outliers #' than regular Mahalanobis distance. #' This method has a `percentage_central` argument that allows specifying #' the breakdown point (0.75, the default, is recommended by Leys et al. 2018, #' but a commonly used alternative is 0.50). #' #' - **Invariant Coordinate Selection (ICS)**: #' The outlier are detected using ICS, which by default uses an alpha threshold #' of 0.025 (corresponding to the 2.5\% most extreme observations) as a cut-off #' value for outliers classification. Refer to the help-file of #' [ICSOutlier::ics.outlier()] to get more details about this procedure. #' Note that `method = "ics"` requires both **ICS** and **ICSOutlier** #' to be installed, and that it takes some time to compute the results. You #' can speed up computation time using parallel computing. Set the number of #' cores to use with `options(mc.cores = 4)` (for example). #' #' - **OPTICS**: #' The Ordering Points To Identify the Clustering Structure (OPTICS) algorithm #' (Ankerst et al., 1999) is using similar concepts to DBSCAN (an unsupervised #' clustering technique that can be used for outliers detection). The threshold #' argument is passed as `minPts`, which corresponds to the minimum size #' of a cluster. By default, this size is set at 2 times the number of columns #' (Sander et al., 1998). Compared to the other techniques, that will always #' detect several outliers (as these are usually defined as a percentage of #' extreme values), this algorithm functions in a different manner and won't #' always detect outliers. Note that `method = "optics"` requires the #' **dbscan** package to be installed, and that it takes some time to compute #' the results. Additionally, the `optics_xi` (default to 0.05) is passed to #' the [dbscan::extractXi()] function to further refine the cluster selection. #' #' - **Local Outlier Factor**: #' Based on a K nearest neighbors algorithm, LOF compares the local density of #' a point to the local densities of its neighbors instead of computing a #' distance from the center (Breunig et al., 2000). Points that have a #' substantially lower density than their neighbors are considered outliers. A #' LOF score of approximately 1 indicates that density around the point is #' comparable to its neighbors. Scores significantly larger than 1 indicate #' outliers. The default threshold of 0.025 will classify as outliers the #' observations located at `qnorm(1-0.025) * SD)` of the log-transformed #' LOF distance. Requires the **dbscan** package. #' #' @section Methods for simulated residuals: #' #' The approach for detecting outliers based on simulated residuals differs #' from the traditional methods and may not be detecting outliers as expected. #' Literally, this approach compares observed to simulated values. However, we #' do not know the deviation of the observed data to the model expectation, and #' thus, the term "outlier" should be taken with a grain of salt. It refers to #' "simulation outliers". Basically, the comparison tests whether on observed #' data point is outside the simulated range. It is strongly recommended to read #' the related documentations in the **DHARMa** package, e.g. `?DHARMa::testOutliers`. #' #' @section Threshold specification: #' #' Default thresholds are currently specified as follows: #' #' ``` #' list( #' zscore = stats::qnorm(p = 1 - 0.001 / 2), #' zscore_robust = stats::qnorm(p = 1 - 0.001 / 2), #' iqr = 1.7, #' ci = 1 - 0.001, #' eti = 1 - 0.001, #' hdi = 1 - 0.001, #' bci = 1 - 0.001, #' cook = stats::qf(0.5, ncol(x), nrow(x) - ncol(x)), #' pareto = 0.7, #' mahalanobis = stats::qchisq(p = 1 - 0.001, df = ncol(x)), #' mahalanobis_robust = stats::qchisq(p = 1 - 0.001, df = ncol(x)), #' mcd = stats::qchisq(p = 1 - 0.001, df = ncol(x)), #' ics = 0.001, #' optics = 2 * ncol(x), #' optics_xi = 0.05, #' lof = 0.001 #' ) #' ``` #' #' @section Meta-analysis models: #' For meta-analysis models (e.g. objects of class `rma` from the *metafor* #' package or `metagen` from package *meta*), studies are defined as outliers #' when their confidence interval lies outside the confidence interval of the #' pooled effect. #' #' @references #' - Archimbaud, A., Nordhausen, K., and Ruiz-Gazen, A. (2018). ICS for #' multivariate outlier detection with application to quality control. #' *Computational Statistics and Data Analysis*, *128*, 184-199. #' \doi{10.1016/j.csda.2018.06.011} #' #' - Gnanadesikan, R., and Kettenring, J. R. (1972). Robust estimates, residuals, #' and outlier detection with multiresponse data. *Biometrics*, 81-124. #' #' - Bollen, K. A., and Jackman, R. W. (1985). Regression diagnostics: An #' expository treatment of outliers and influential cases. *Sociological Methods #' and Research*, *13*(4), 510-542. #' #' - Cabana, E., Lillo, R. E., and Laniado, H. (2019). Multivariate outlier #' detection based on a robust Mahalanobis distance with shrinkage estimators. #' arXiv preprint arXiv:1904.02596. #' #' - Cook, R. D. (1977). Detection of influential observation in linear #' regression. *Technometrics*, *19*(1), 15-18. #' #' - Iglewicz, B., and Hoaglin, D. C. (1993). How to detect and handle outliers #' (Vol. 16). Asq Press. #' #' - Leys, C., Klein, O., Dominicy, Y., and Ley, C. (2018). Detecting #' multivariate outliers: Use a robust variant of Mahalanobis distance. *Journal #' of Experimental Social Psychology*, 74, 150-156. #' #' - Liu, F. T., Ting, K. M., and Zhou, Z. H. (2008, December). Isolation forest. #' In 2008 Eighth IEEE International Conference on Data Mining (pp. 413-422). #' IEEE. #' #' - Lüdecke, D., Ben-Shachar, M. S., Patil, I., Waggoner, P., and Makowski, D. #' (2021). performance: An R package for assessment, comparison and testing of #' statistical models. *Journal of Open Source Software*, *6*(60), 3139. #' \doi{10.21105/joss.03139} #' #' - Thériault, R., Ben-Shachar, M. S., Patil, I., Lüdecke, D., Wiernik, B. M., #' and Makowski, D. (2023). Check your outliers! An introduction to identifying #' statistical outliers in R with easystats. *Behavior Research Methods*, 1-11. #' \doi{10.3758/s13428-024-02356-w} #' #' - Rousseeuw, P. J., and Van Zomeren, B. C. (1990). Unmasking multivariate #' outliers and leverage points. *Journal of the American Statistical #' association*, *85*(411), 633-639. #' #' @examples #' data <- mtcars # Size nrow(data) = 32 #' #' # For single variables ------------------------------------------------------ #' outliers_list <- check_outliers(data$mpg) # Find outliers #' outliers_list # Show the row index of the outliers #' as.numeric(outliers_list) # The object is a binary vector... #' filtered_data <- data[!outliers_list, ] # And can be used to filter a data frame #' nrow(filtered_data) # New size, 28 (4 outliers removed) #' #' # Find all observations beyond +/- 2 SD #' check_outliers(data$mpg, method = "zscore", threshold = 2) #' #' # For dataframes ------------------------------------------------------ #' check_outliers(data) # It works the same way on data frames #' #' # You can also use multiple methods at once #' outliers_list <- check_outliers(data, method = c( #' "mahalanobis", #' "iqr", #' "zscore" #' )) #' outliers_list #' #' # Using `as.data.frame()`, we can access more details! #' outliers_info <- as.data.frame(outliers_list) #' head(outliers_info) #' outliers_info$Outlier # Including the probability of being an outlier #' #' # And we can be more stringent in our outliers removal process #' filtered_data <- data[outliers_info$Outlier < 0.1, ] #' #' # We can run the function stratified by groups using `{datawizard}` package: #' group_iris <- datawizard::data_group(iris, "Species") #' check_outliers(group_iris) #' # nolint start #' @examplesIf all(insight::check_if_installed(c("bigutilsr", "MASS", "ICSOutlier", "ICS", "dbscan", "loo", "see"), quietly = TRUE)) #' # nolint end #' \donttest{ #' # You can also run all the methods #' check_outliers(data, method = "all", verbose = FALSE) #' #' # For statistical models --------------------------------------------- #' # select only mpg and disp (continuous) #' mt1 <- mtcars[, c(1, 3, 4)] #' # create some fake outliers and attach outliers to main df #' mt2 <- rbind(mt1, data.frame( #' mpg = c(37, 40), disp = c(300, 400), #' hp = c(110, 120) #' )) #' # fit model with outliers #' model <- lm(disp ~ mpg + hp, data = mt2) #' #' outliers_list <- check_outliers(model) #' plot(outliers_list) #' #' insight::get_data(model)[outliers_list, ] # Show outliers data #' } #' @export check_outliers <- function(x, ...) { UseMethod("check_outliers") } #' @export check_outliers.character <- function(x, ...) { rep(0, length(x)) } # default --------------------- #' @rdname check_outliers #' @export check_outliers.default <- function(x, method = c("cook", "pareto"), threshold = NULL, ID = NULL, verbose = TRUE, ...) { # Check args if (all(method == "all")) { method <- c( "zscore_robust", "iqr", "ci", "cook", "pareto", "mahalanobis", "mahalanobis_robust", "mcd", "ics", "optics", "lof" ) } method <- match.arg( method, c( "zscore", "zscore_robust", "iqr", "ci", "hdi", "eti", "bci", "cook", "pareto", "mahalanobis", "mahalanobis_robust", "mcd", "ics", "optics", "lof" ), several.ok = TRUE ) # Get model information m_info <- insight::model_info(x) # Get data my_data <- insight::get_data(x, verbose = FALSE) # sanity check for date, POSIXt and difftime variables if (any(vapply(my_data, inherits, FUN.VALUE = logical(1), what = c("Date", "POSIXt", "difftime"))) && verbose) { insight::format_alert( paste( "Date variables are not supported for outliers detection. These will be ignored.", "Make sure any date variables are converted to numeric or factor {.b before} fitting the model." ) ) } # Remove non-numerics, but in case of binomial, only check predictors if (m_info$is_binomial) { model_predictors <- unique(insight::find_predictors(x, flatten = TRUE)) } else { model_predictors <- colnames(my_data) } my_data <- datawizard::data_select( my_data[model_predictors], select = is.numeric, verbose = FALSE ) # check if any data left if (is.null(my_data) || ncol(my_data) == 0) { insight::format_error("No numeric variables found. No data to check for outliers.") } # Thresholds if (is.null(threshold)) { thresholds <- .check_outliers_thresholds(my_data) } else if (is.list(threshold)) { thresholds <- .check_outliers_thresholds(my_data) thresholds[names(threshold)] <- threshold[names(threshold)] } else { insight::format_error( paste( "The `threshold` argument must be NULL (for default values) or a list containing", "threshold values for desired methods (e.g., `list('mahalanobis' = 7)`)." ) ) } if (!missing(ID) && verbose) { insight::format_warning(paste0("ID argument not supported for model objects of class `", class(x)[1], "`.")) } # Others if (all(method %in% c("cook", "pareto"))) { my_df <- data.frame(Row = seq_len(nrow(as.data.frame(my_data)))) outlier_count <- list() outlier_var <- list() } else { out <- check_outliers(my_data, method, threshold) outlier_var <- attributes(out)$outlier_var outlier_count <- attributes(out)$outlier_count my_df <- attributes(out)$data my_df <- my_df[names(my_df) != "Outlier"] } # Cook if ("cook" %in% method && !m_info$is_bayesian && !inherits(x, "bife")) { data_cook <- .check_outliers_cook( x, threshold = thresholds$cook )$data_cook my_df <- datawizard::data_merge(list(my_df, data_cook), join = "full", by = "Row" ) count.table <- datawizard::data_filter( data_cook, "Outlier_Cook > 0.5" ) count.table <- datawizard::data_remove( count.table, "Cook", regex = TRUE, as_data_frame = TRUE ) if (nrow(count.table) >= 1) { count.table$n_Cook <- "(Multivariate)" } outlier_count$cook <- count.table if (all(method %in% c("cook", "pareto"))) { outlier_count$all <- count.table } else { outlier_count$all <- datawizard::data_merge( list(outlier_count$all, count.table), join = "full", by = "Row" ) } } else { method <- method[method != "cook"] } # Pareto if ("pareto" %in% method && m_info$is_bayesian) { data_pareto <- .check_outliers_pareto( x, threshold = thresholds$pareto )$data_pareto my_df <- datawizard::data_merge(list(my_df, data_pareto), join = "full", by = "Row" ) count.table <- datawizard::data_filter( data_pareto, "Outlier_Pareto > 0.5" ) count.table <- datawizard::data_remove( count.table, "Pareto", regex = TRUE, as_data_frame = TRUE ) if (nrow(count.table) >= 1) { count.table$n_Pareto <- "(Multivariate)" } outlier_count$pareto <- count.table if (all(method %in% c("cook", "pareto"))) { outlier_count$all <- count.table } else { outlier_count$all <- datawizard::data_merge( list(outlier_count$all, count.table), join = "full", by = "Row" ) } } else { method <- method[method != "pareto"] } outlier_count$all <- datawizard::convert_na_to(outlier_count$all, replace_num = 0, replace_char = "0", replace_fac = 0 ) num.df <- outlier_count$all[!names(outlier_count$all) %in% c("Row", ID)] if (isTRUE(nrow(num.df) > 0)) { num.df <- datawizard::recode_values( num.df, recode = list(`2` = "(Multivariate)") ) num.df <- as.data.frame(lapply(num.df, as.numeric)) outlier_count$all$max <- apply(num.df, 1, max) outlier_count$all <- datawizard::data_filter( outlier_count$all, max >= 2 ) outlier_count$all <- datawizard::data_remove( outlier_count$all, "max" ) } row.names(outlier_count$all) <- NULL thresholds <- thresholds[names(thresholds) %in% method] # Composite outlier score my_df$Outlier <- rowMeans(my_df[grepl("Outlier_", names(my_df), fixed = TRUE)]) my_df <- my_df[c(names(my_df)[names(my_df) != "Outlier"], "Outlier")] # Out outlier <- my_df$Outlier > 0.5 # Attributes class(outlier) <- c("check_outliers", "see_check_outliers", class(outlier)) attr(outlier, "data") <- my_df attr(outlier, "threshold") <- thresholds attr(outlier, "method") <- method attr(outlier, "text_size") <- 3 attr(outlier, "influential_obs") <- .safe(.model_diagnostic_outlier(x, threshold = unlist(thresholds))) # nolint attr(outlier, "variables") <- "(Whole model)" attr(outlier, "raw_data") <- my_data attr(outlier, "outlier_var") <- outlier_var attr(outlier, "outlier_count") <- outlier_count outlier } # Methods ----------------------------------------------------------------- #' @export as.data.frame.check_outliers <- function(x, ...) { attributes(x)$data } #' @export as.double.check_outliers <- function(x, ...) { attributes(x)$data$Outlier } #' @export print.check_outliers <- function(x, ...) { outliers <- which(x) method <- attr(x, "method") round_to_last_digit <- function(x, n = 3) { max(abs(round(x, n)), abs(signif(x, 1))) * sign(x) } thresholds <- lapply(attr(x, "threshold"), round_to_last_digit, 3) method.thresholds <- data.frame( method = method, thresholds = unlist(thresholds) ) method.thresholds <- paste0(method.thresholds$method, " (", method.thresholds$thresholds, ")", collapse = ", " ) method.univariate <- c( "zscore", "zscore_robust", "iqr", "ci", "eti", "hdi", "bci" ) vars <- toString(attr(x, "variables")) vars.outliers <- attr(x, "outlier_var") var.plural <- ifelse(length(attr(x, "variables")) > 1, "variables", "variable" ) method.plural <- ifelse(length(thresholds) > 1, "methods and thresholds", "method and threshold" ) long_dash <- paste0("\n", strrep("-", 77), "\n") if (length(outliers) > 1) { outlier.plural <- "outliers" case.plural <- "cases" } else { outlier.plural <- "outlier" case.plural <- "case" } if (length(outliers) >= 1) { outlier.count <- attr(x, "outlier_count") o <- toString(outliers) insight::print_color(insight::format_message( sprintf( "%i %s detected: %s %s.", length(outliers), outlier.plural, case.plural, o ), sprintf( "- Based on the following %s: %s.", method.plural, method.thresholds ), sprintf("- For %s: %s.\n", var.plural, vars), indent = "" ), color = "yellow") if (length(method) > 1) { insight::print_color( c( "\nNote: Outliers were classified as such by", "at least half of the selected methods. \n" ), "yellow" ) } if ((isTRUE(nrow(outlier.count$all) > 0) || isTRUE(attributes(x)$grouped)) && (length(method) > 1 || all(method %in% method.univariate))) { cat(long_dash, insight::format_message( "\nThe following observations were considered outliers for two or more", "variables by at least one of the selected methods:\n\n" )) ifelse(isTRUE(attributes(x)$grouped), print(lapply(outlier.count, function(x) x$all)), print(outlier.count$all) ) } if (length(method) == 1 && all(method %in% method.univariate)) { cat(long_dash, "Outliers per variable (", method, "): \n\n", sep = "" ) ifelse(isTRUE(attributes(x)$grouped), print(vars.outliers), print(vars.outliers[[1]]) ) } } else { insight::print_color( sprintf("OK: No outliers detected. - Based on the following %s: %s. - For %s: %s\n\n", method.plural, method.thresholds, var.plural, vars), "green" ) } invisible(x) } #' @export print.check_outliers_metafor <- function(x, ...) { outliers <- which(x) round_to_last_digit <- function(x, n = 3) { max(abs(round(x, n)), abs(signif(x, 1))) * sign(x) } thresholds <- lapply(attr(x, "threshold"), round_to_last_digit, 3) studies <- attr(x, "outlier_var") if (length(outliers) > 1) { outlier.plural <- "outliers" case.plural <- "studies" } else { outlier.plural <- "outlier" case.plural <- "study" } if (length(outliers) >= 1) { if (all(as.character(studies) == as.character(outliers))) { o <- datawizard::text_concatenate(outliers) } else { o <- datawizard::text_concatenate(paste0(outliers, " (", studies, ")")) } insight::print_color(insight::format_message( sprintf("%i %s detected: %s %s.\n", length(outliers), outlier.plural, case.plural, o) ), "yellow") } else { insight::print_color("OK: No outliers detected.\n", "green") } invisible(x) } #' @export print.check_outliers_metagen <- function(x, ...) { outliers_fixed <- which(x$fixed) outliers_random <- which(x$random) studies <- attr(x, "studies") if (length(outliers_fixed) > 1) { outlier.plural <- "outliers" case.plural <- "studies" } else { outlier.plural <- "outlier" case.plural <- "study" } if (length(outliers_fixed) >= 1) { if (all(as.character(studies[outliers_fixed]) == as.character(outliers_fixed))) { o <- datawizard::text_concatenate(outliers_fixed) } else { o <- datawizard::text_concatenate(paste0(outliers_fixed, " (", studies[outliers_fixed], ")")) } insight::print_color(insight::format_message( sprintf("- %i %s in fixed effects detected: %s %s.\n", length(outliers_fixed), outlier.plural, case.plural, o) ), "yellow") } if (length(outliers_random) > 1) { outlier.plural <- "outliers" case.plural <- "cases" } else { outlier.plural <- "outlier" case.plural <- "case" } if (length(outliers_random) >= 1) { if (all(as.character(studies[outliers_random]) == as.character(outliers_random))) { o <- datawizard::text_concatenate(outliers_random) } else { o <- datawizard::text_concatenate(paste0(outliers_random, " (", studies[outliers_random], ")")) } if (length(outliers_fixed) >= 1) { cat("\n") } insight::print_color(insight::format_message( sprintf("- %i %s in random effects detected: %s %s.\n", length(outliers_random), outlier.plural, case.plural, o) ), "yellow") } if (!length(outliers_random) && !length(outliers_fixed)) { insight::print_color("OK: No outliers detected.\n", "green") } invisible(x) } #' @export plot.check_outliers <- function(x, ...) { insight::check_if_installed("see", "to plot outliers") NextMethod() } #' @export print.check_outliers_simres <- function(x, digits = 2, ...) { result <- paste0( insight::format_value(100 * x$Expected, digits = digits, ...), "%, ", insight::format_ci(100 * x$CI_low, 100 * x$CI_high, digits = digits, ...) ) insight::print_color("# Outliers detection\n\n", "blue") cat(sprintf(" Proportion of observed outliers: %.*f%%\n", digits, 100 * x$Coefficient)) cat(sprintf(" Proportion of expected outliers: %s\n\n", result)) p_string <- paste0(" (", insight::format_p(x$p_value), ")") if (x$p_value < 0.05) { message("Outliers were detected", p_string, ".") } else { message("No outliers were detected", p_string, ".") } invisible(x) } # other classes ------------------------- #' @rdname check_outliers #' @export check_outliers.numeric <- function(x, method = "zscore_robust", threshold = NULL, ...) { x <- as.data.frame(x) names(x) <- datawizard::text_remove(sys.call()[2], "()") check_outliers(x, method = method, threshold = threshold, ... ) } #' @rdname check_outliers #' @export check_outliers.data.frame <- function(x, method = "mahalanobis", threshold = NULL, ID = NULL, ...) { # Preserve ID column if desired ID.names <- switch(!is.null(ID), x[ID] ) # Remove non-numerics my_data <- x x <- x[, vapply(x, is.numeric, logical(1)), drop = FALSE] # Check args if (all(method == "all")) { method <- c( "zscore_robust", "iqr", "ci", "cook", "pareto", "mahalanobis", "mahalanobis_robust", "mcd", "ics", "optics", "lof" ) } method <- match.arg(method, c( "zscore", "zscore_robust", "iqr", "ci", "hdi", "eti", "bci", "cook", "pareto", "mahalanobis", "mahalanobis_robust", "mcd", "ics", "optics", "lof" ), several.ok = TRUE) # Thresholds if (is.null(threshold)) { thresholds <- .check_outliers_thresholds(x) } else if (is.list(threshold)) { thresholds <- .check_outliers_thresholds(x) thresholds[names(threshold)] <- threshold[names(threshold)] } else if (is.numeric(threshold)) { thresholds <- .check_outliers_thresholds(x) thresholds <- lapply(thresholds, function(x) threshold) # need to fix this manually - "optics" automatically includes method # "optics_xi", which is allowed to range between 0 and 1 - since values # for "optics" can be > 1, it might overwrite "optics_xi" with an invalid # value... if (thresholds$optics_xi > 1) { thresholds$optics_xi <- 0.05 } } else { insight::format_error( paste( "The `threshold` argument must be NULL (for default values) or a list containing", "threshold values for desired methods (e.g., `list('mahalanobis' = 7)`)." ) ) } # Keep only relevant threshold valid <- method if ("optics" %in% valid) { valid <- c(valid, "optics_xi") method <- c(method, "optics_xi") } thresholds <- thresholds[names(thresholds) %in% valid] out.meta <- .check_outliers.data.frame_method(x, method, thresholds, ID, ID.names, ...) out <- out.meta$out outlier_count <- out.meta$outlier_count outlier_var <- out.meta$outlier_var # Combine outlier data my_df <- out[vapply(out, is.data.frame, logical(1))] if (length(my_df) > 1 && !is.null(ID)) { my_df <- datawizard::data_merge(my_df, by = c("Row", ID)) } else if (length(my_df) > 1) { my_df <- datawizard::data_merge(my_df, by = "Row") } else { my_df <- my_df[[1]] } # Composite outlier score my_df$Outlier <- rowMeans(my_df[grepl("Outlier_", names(my_df), fixed = TRUE)]) # Out outlier <- my_df$Outlier > 0.5 # Combine outlier frequency table if (length(outlier_count) > 1 && !is.null(ID)) { outlier_count$all <- datawizard::data_merge(outlier_count, join = "full", by = c("Row", ID) ) } else if (length(outlier_count) > 1) { outlier_count$all <- datawizard::data_merge(outlier_count, join = "full", by = "Row" ) } else if (length(outlier_count) == 1) { outlier_count$all <- outlier_count[[1]] } else { outlier_count$all <- data.frame() } outlier_count$all <- datawizard::convert_na_to(outlier_count$all, replace_num = 0, replace_char = "0", replace_fac = 0 ) outlier_count <- lapply(outlier_count, function(x) { num.df <- x[!names(x) %in% c("Row", ID)] if (isTRUE(nrow(num.df) >= 1)) { num.df <- datawizard::recode_values( num.df, recode = list(`2` = "(Multivariate)") ) num.df <- as.data.frame(lapply(num.df, as.numeric)) x$max <- apply(num.df, 1, max) x <- datawizard::data_filter(x, max >= 2) x <- datawizard::data_remove(x, "max") } }) row.names(outlier_count$all) <- NULL # Attributes class(outlier) <- c("check_outliers", "see_check_outliers", class(outlier)) attr(outlier, "data") <- my_df attr(outlier, "threshold") <- thresholds attr(outlier, "method") <- method attr(outlier, "text_size") <- 3 attr(outlier, "variables") <- names(x) attr(outlier, "raw_data") <- my_data attr(outlier, "outlier_var") <- outlier_var attr(outlier, "outlier_count") <- outlier_count outlier } .check_outliers.data.frame_method <- function(x, method, thresholds, ID, ID.names, ...) { # Clean up per-variable list of outliers process_outlier_list <- function(outlier.list, Outlier_method) { outlier.list <- lapply(outlier.list, "[[", 1) outlier.list <- lapply(outlier.list, function(x) { x[x[[Outlier_method]] >= 0.5, ] }) outlier.list <- outlier.list[vapply(outlier.list, nrow, numeric(1)) > 0] outlier.list <- lapply(outlier.list, datawizard::data_remove, Outlier_method, as_data_frame = TRUE ) outlier.list } # Count table of repeated outliers (for several variables) count_outlier_table <- function(outlier.list) { count.table <- do.call(rbind, outlier.list) name.method <- grep("Distance_", names(count.table), value = TRUE, fixed = TRUE) name.method <- paste0("n_", gsub("Distance_", "", name.method, fixed = TRUE)) if (isTRUE(nrow(count.table) > 0)) { count.values <- rle(sort(count.table$Row)) count.table <- data.frame(Row = count.values$values) if (!is.null(ID)) { count.table[ID] <- ID.names[count.table$Row, ] } count.table <- cbind(count.table, val = count.values$lengths) names(count.table)[names(count.table) == "val"] <- name.method count.table <- count.table[order(-count.table[[name.method]]), ] } count.table } # Preparation out <- list() outlier_var <- list() outlier_count <- list() # Z-score if ("zscore" %in% method) { out <- c(out, .check_outliers_zscore( x, threshold = thresholds$zscore, robust = FALSE, method = "max", ID.names = ID.names )) # Outliers per variable zscore.var <- lapply( x, .check_outliers_zscore, threshold = thresholds$zscore, robust = FALSE, method = "max", ID.names = ID.names ) outlier_var$zscore <- process_outlier_list(zscore.var, "Outlier_Zscore") outlier_count$zscore <- count_outlier_table(outlier_var$zscore) } if ("zscore_robust" %in% method) { out <- c(out, .check_outliers_zscore( x, threshold = thresholds$zscore_robust, robust = TRUE, method = "max", ID.names = ID.names )) # Outliers per variable zscore_robust.var <- lapply(x, .check_outliers_zscore, threshold = thresholds$zscore_robust, robust = TRUE, method = "max", ID.names = ID.names ) outlier_var$zscore_robust <- process_outlier_list( zscore_robust.var, "Outlier_Zscore_robust" ) outlier_count$zscore_robust <- count_outlier_table( outlier_var$zscore_robust ) } # IQR if ("iqr" %in% method) { out <- c(out, .check_outliers_iqr( x, threshold = thresholds$iqr, method = "tukey", ID.names = ID.names )) # Outliers per variable iqr.var <- lapply(x, function(x) { y <- as.data.frame(x) .check_outliers_iqr( y, threshold = thresholds$iqr, method = "tukey", ID.names = ID.names ) }) outlier_var$iqr <- process_outlier_list(iqr.var, "Outlier_IQR") outlier_count$iqr <- count_outlier_table(outlier_var$iqr) } # CI if (any(c("ci", "hdi", "eti", "bci") %in% method)) { for (i in method[method %in% c("ci", "hdi", "eti", "bci")]) { out <- c(out, .check_outliers_ci( x, threshold = thresholds[i], method = i, ID.names = ID.names )) # Outliers per variable loop.var <- lapply(x, function(x) { y <- as.data.frame(x) .check_outliers_ci( y, threshold = thresholds[i], method = i, ID.names = ID.names ) }) outlier_var[[i]] <- process_outlier_list( loop.var, paste0("Outlier_", i) ) outlier_count[[i]] <- count_outlier_table(outlier_var[[i]]) } } # Mahalanobis if ("mahalanobis" %in% method) { out <- c(out, .check_outliers_mahalanobis( x, threshold = thresholds$mahalanobis, ID.names = ID.names, ... )) count.table <- datawizard::data_filter( out$data_mahalanobis, "Outlier_Mahalanobis > 0.5" ) count.table <- datawizard::data_remove( count.table, "Mahalanobis", regex = TRUE, as_data_frame = TRUE ) if (nrow(count.table) >= 1) { count.table$n_Mahalanobis <- "(Multivariate)" } outlier_count$mahalanobis <- count.table } # Robust Mahalanobis if ("mahalanobis_robust" %in% method) { out <- c(out, .check_outliers_mahalanobis_robust( x, threshold = thresholds$mahalanobis_robust, ID.names = ID.names )) count.table <- datawizard::data_filter( out$data_mahalanobis_robust, "Outlier_Mahalanobis_robust > 0.5" ) count.table <- datawizard::data_remove( count.table, "Mahalanobis", regex = TRUE, as_data_frame = TRUE ) if (nrow(count.table) >= 1) { count.table$n_Mahalanobis_robust <- "(Multivariate)" } outlier_count$mahalanobis_robust <- count.table } # MCD if ("mcd" %in% method) { out <- c(out, .check_outliers_mcd( x, threshold = thresholds$mcd, ID.names = ID.names, ... )) count.table <- datawizard::data_filter( out$data_mcd, "Outlier_MCD > 0.5" ) count.table <- datawizard::data_remove( count.table, "MCD", regex = TRUE, as_data_frame = TRUE ) if (nrow(count.table) >= 1) { count.table$n_MCD <- "(Multivariate)" } outlier_count$mcd <- count.table } # ICS if ("ics" %in% method) { out <- c(out, .check_outliers_ics( x, threshold = thresholds$ics, ID.names = ID.names )) # make sure we have valid results if (!is.null(out)) { count.table <- datawizard::data_filter( out$data_ics, "Outlier_ICS > 0.5" ) count.table <- datawizard::data_remove( count.table, "ICS", regex = TRUE, as_data_frame = TRUE ) if (nrow(count.table) >= 1) { count.table$n_ICS <- "(Multivariate)" } outlier_count$ics <- count.table } } # OPTICS if ("optics" %in% method) { out <- c(out, .check_outliers_optics( x, threshold = thresholds$optics, ID.names = ID.names, xi = thresholds$optics_xi )) count.table <- datawizard::data_filter( out$data_optics, "Outlier_OPTICS > 0.5" ) count.table <- datawizard::data_remove( count.table, "OPTICS", regex = TRUE, as_data_frame = TRUE ) if (nrow(count.table) >= 1) { count.table$n_OPTICS <- "(Multivariate)" } outlier_count$optics <- count.table } # Isolation Forest # if ("iforest" %in% method) { # out <- c(out, .check_outliers_iforest(x, threshold = thresholds$iforest)) # } # Local Outlier Factor if ("lof" %in% method) { out <- c(out, .check_outliers_lof( x, threshold = thresholds$lof, ID.names = ID.names )) count.table <- datawizard::data_filter( out$data_lof, "Outlier_LOF > 0.5" ) count.table <- datawizard::data_remove( count.table, "LOF", regex = TRUE, as_data_frame = TRUE ) if (nrow(count.table) >= 1) { count.table$n_LOF <- "(Multivariate)" } outlier_count$lof <- count.table } out.meta <- list(out = out, outlier_var = outlier_var, outlier_count = outlier_count) out.meta } #' @export check_outliers.grouped_df <- function(x, method = "mahalanobis", threshold = NULL, ID = NULL, ...) { info <- attributes(x) # poorman < 0.8.0? if ("indices" %in% names(info)) { grps <- lapply(attr(x, "indices", exact = TRUE), function(x) x + 1) } else { grps <- attr(x, "groups", exact = TRUE)[[".rows"]] } # Initialize elements my_data <- data.frame() out <- NULL thresholds <- list() outlier_var <- list() outlier_count <- list() # Loop through groups for (i in seq_along(grps)) { rows <- grps[[i]] outliers_subset <- check_outliers( as.data.frame(x[rows, ]), method = method, threshold = threshold, ID = ID, ... ) my_data <- rbind(my_data, as.data.frame(outliers_subset)) out <- c(out, outliers_subset) thresholds[[paste0("group_", i)]] <- attributes(outliers_subset)$threshold outlier_var[[i]] <- lapply( attributes(outliers_subset)$outlier_var, lapply, function(y) { y$Row <- rows[which(seq_along(rows) %in% y$Row)] y } ) outlier_count[[i]] <- lapply( attributes(outliers_subset)$outlier_count, function(y) { y$Row <- rows[which(seq_along(rows) %in% y$Row)] y } ) } # Add compatibility between dplyr and poorman info$groups$.rows <- lapply(info$groups$.rows, as.numeric) outlier_var <- stats::setNames(outlier_var, info$groups[[1]]) outlier_count <- stats::setNames(outlier_count, info$groups[[1]]) groups <- lapply(seq_along(info$groups$.rows), function(x) { info$groups$.rows[[x]] <- rep( info$groups[[1]][x], length(info$groups$.rows[[x]]) ) info$groups$.rows[[x]] <- as.data.frame(info$groups$.rows[[x]]) }) my_data[names(info$groups)[1]] <- do.call(rbind, groups) my_data <- datawizard::data_relocate( my_data, select = names(info$groups)[1], after = "Row" ) my_data$Row <- seq_len(nrow(my_data)) class(out) <- c("check_outliers", "see_check_outliers", class(out)) attr(out, "data") <- my_data attr(out, "method") <- method attr(out, "threshold") <- thresholds[[1]] attr(out, "text_size") <- 3 attr(out, "variables") <- names(x[, vapply(x, is.numeric, logical(1)), drop = FALSE]) attr(out, "raw_data") <- x attr(out, "outlier_var") <- outlier_var attr(out, "outlier_count") <- outlier_count attr(out, "grouped") <- TRUE out } #' @export check_outliers.BFBayesFactor <- function(x, ID = NULL, ...) { if (!insight::is_model(x)) { insight::format_error("Collinearity only applicable to regression models.") } if (!missing(ID)) { insight::format_warning(paste0("ID argument not supported for objects of class `", class(x)[1], "`.")) } d <- insight::get_predictors(x) d[[insight::find_response(x)]] <- insight::get_response(x) check_outliers(d, ID = ID, ...) } #' @export check_outliers.gls <- function(x, method = "pareto", threshold = NULL, ID = NULL, ...) { if (!missing(ID)) { insight::format_warning( paste0("ID argument not supported for objects of class `", class(x)[1], "`.") ) } valid_methods <- c("zscore_robust", "iqr", "ci", "pareto", "optics") if (all(method == "all")) { method <- valid_methods } if (!all(method %in% valid_methods)) { method <- "pareto" } check_outliers.default(x, method = method, threshold = threshold, ...) } #' @export check_outliers.lme <- check_outliers.gls #' @export check_outliers.fixest <- check_outliers.gls #' @export check_outliers.fixest_multi <- function(x, method = "pareto", threshold = NULL, ID = NULL, ...) { lapply(x, check_outliers.fixest) } #' @export check_outliers.geeglm <- check_outliers.gls #' @export check_outliers.rma <- function(x, ...) { ## TODO Check whether we can enable CI argument # but we need to find out at which CI-level the overall effect interval was estimated ci <- 0.95 thresholds <- c(x$ci.lb, x$ci.ub) lower_bounds <- as.numeric(x$yi - stats::qnorm((1 + ci) / 2) * sqrt(x$vi)) upper_bounds <- as.numeric(x$yi + stats::qnorm((1 + ci) / 2) * sqrt(x$vi)) # which study's CI-range is not covered by/does not overlap with overall CI? outlier <- upper_bounds < thresholds[1] | lower_bounds > thresholds[2] d <- data.frame( Row = seq_along(x$yi), Outlier = as.numeric(outlier) ) # Attributes class(outlier) <- c("check_outliers_metafor", class(outlier)) attr(outlier, "data") <- d attr(outlier, "threshold") <- thresholds attr(outlier, "text_size") <- 3 attr(outlier, "outlier_var") <- x$slab[outlier] attr(outlier, "outlier_count") <- sum(outlier) outlier } #' @export check_outliers.rma.uni <- check_outliers.rma #' @export check_outliers.metagen <- function(x, ...) { ci <- 0.95 thresholds_fixed <- c(x$lower.fixed, x$upper.fixed) thresholds_random <- c(x$lower.random, x$upper.random) lower_bounds <- as.numeric(x$TE - stats::qnorm((1 + ci) / 2) * x$seTE) upper_bounds <- as.numeric(x$TE + stats::qnorm((1 + ci) / 2) * x$seTE) # which study's CI-range is not covered by/does not overlap with overall CI? outlier <- list( fixed = upper_bounds < thresholds_fixed[1] | lower_bounds > thresholds_fixed[2], random = upper_bounds < thresholds_random[1] | lower_bounds > thresholds_random[2] ) d <- data.frame( Row = seq_along(x$TE), Outlier_fixed = as.numeric(outlier$fixed), Outlier_random = as.numeric(outlier$random) ) # Attributes class(outlier) <- c("check_outliers_metagen", class(outlier)) attr(outlier, "data") <- d attr(outlier, "text_size") <- 3 attr(outlier, "studies") <- x$studlab attr(outlier, "outlier_count") <- sum(c(outlier$fixed, outlier$random)) outlier } #' @export check_outliers.meta <- check_outliers.metagen #' @export check_outliers.metabin <- check_outliers.metagen #' @rdname check_outliers #' @export check_outliers.performance_simres <- function(x, type = "default", iterations = 100, alternative = "two.sided", ...) { type <- match.arg(type, c("default", "binomial", "bootstrap")) alternative <- match.arg(alternative, c("two.sided", "greater", "less")) insight::check_if_installed("DHARMa") result <- DHARMa::testOutliers(x, type = type, nBoot = iterations, alternative = alternative, plot = FALSE, ...) outlier <- list( Coefficient = as.vector(result$estimate), Expected = as.numeric(gsub("(.*)\\(expected: (\\d.*)\\)", "\\2", names(result$estimate))), CI_low = result$conf.int[1], CI_high = result$conf.int[2], p_value = result$p.value ) class(outlier) <- c("check_outliers_simres", class(outlier)) outlier } #' @export check_outliers.DHARMa <- check_outliers.performance_simres # Thresholds -------------------------------------------------------------- .check_outliers_thresholds <- function(x) { suppressWarnings(.check_outliers_thresholds_nowarn(x)) } .check_outliers_thresholds_nowarn <- function(x) { list( zscore = stats::qnorm(p = 1 - 0.001 / 2), zscore_robust = stats::qnorm(p = 1 - 0.001 / 2), iqr = 1.7, ci = 1 - 0.001, hdi = 1 - 0.001, eti = 1 - 0.001, bci = 1 - 0.001, cook = stats::qf(0.5, ncol(x), nrow(x) - ncol(x)), pareto = 0.7, mahalanobis = stats::qchisq(p = 1 - 0.001, df = ncol(x)), mahalanobis_robust = stats::qchisq(p = 1 - 0.001, df = ncol(x)), mcd = stats::qchisq(p = 1 - 0.001, df = ncol(x)), ics = 0.001, optics = 2 * ncol(x), optics_xi = 0.05, lof = 0.001 ) } # utilities -------------------- .check_outliers_zscore <- function(x, threshold = stats::qnorm(p = 1 - 0.001 / 2), robust = TRUE, method = "max", ID.names = NULL) { if (threshold < 1) { insight::format_error( "The `threshold` argument must be one or greater for method `zscore`." ) } x <- as.data.frame(x) # Standardize if (robust) { d <- abs(as.data.frame(lapply( x, function(x) (x - stats::median(x, na.rm = TRUE)) / stats::mad(x, na.rm = TRUE) ))) } else { d <- abs(as.data.frame(lapply( x, function(x) (x - mean(x, na.rm = TRUE)) / stats::sd(x, na.rm = TRUE) ))) } out <- data.frame(Row = seq_len(nrow(as.data.frame(d)))) if (!is.null(ID.names)) { out <- cbind(out, ID.names) } out$Distance_Zscore <- apply(d, 1, function(x) { ifelse(all(is.na(x)), NA, max(x, na.rm = TRUE)) }) # Filter out$Outlier_Zscore <- as.numeric(out$Distance_Zscore > threshold) output <- list( data_zscore = out, threshold_zscore = threshold ) if (isTRUE(robust)) { names(output) <- paste0(names(output), "_robust") output$data_zscore_robust <- datawizard::data_addsuffix( output$data_zscore_robust, "_robust", select = "Zscore$", regex = TRUE ) } output } .check_outliers_iqr <- function(x, threshold = 1.7, method = "tukey", ID.names = NULL) { d <- data.frame(Row = seq_len(nrow(as.data.frame(x)))) Distance_IQR <- d for (col in seq_len(ncol(as.data.frame(x)))) { v <- x[, col] if (method == "tukey") { iqr <- stats::quantile(v, 0.75, na.rm = TRUE) - stats::quantile(v, 0.25, na.rm = TRUE) } else { iqr <- stats::IQR(v, na.rm = TRUE) } lower <- stats::quantile(v, 0.25, na.rm = TRUE) - (iqr * threshold) upper <- stats::quantile(v, 0.75, na.rm = TRUE) + (iqr * threshold) m.int <- stats::median(c(lower, upper), na.rm = TRUE) d2 <- abs(v - m.int) Distance_IQR[names(as.data.frame(x))[col]] <- d2 / (iqr * threshold) d[names(as.data.frame(x))[col]] <- ifelse(v > upper, 1, ifelse(v < lower, 1, 0)) # nolint } out <- data.frame(Row = d$Row) d$Row <- NULL Distance_IQR$Row <- NULL if (!is.null(ID.names)) { out <- cbind(out, ID.names) } # out$Distance_IQR <- Distance_IQR out$Distance_IQR <- vapply(as.data.frame(t(Distance_IQR)), function(x) { ifelse(all(is.na(x)), NA_real_, max(x, na.rm = TRUE)) }, numeric(1)) out$Outlier_IQR <- vapply(as.data.frame(t(d)), function(x) { ifelse(all(is.na(x)), NA_real_, max(x, na.rm = TRUE)) }, numeric(1)) list( data_iqr = out, threshold_iqr = threshold ) } .check_outliers_ci <- function(x, threshold = 1 - 0.001, method = "ci", ID.names = NULL) { # Run through columns d <- data.frame(Row = seq_len(nrow(x))) Distance_CI <- d for (col in names(x)) { v <- x[, col] ci <- bayestestR::ci(v, ci = threshold, method = method) d[col] <- ifelse(x[[col]] > ci$CI_high | x[[col]] < ci$CI_low, 1, 0) # nolint m.int <- stats::median(c(ci$CI_low, ci$CI_high), na.rm = TRUE) d2 <- abs(v - m.int) ci.range <- (ci$CI_high - ci$CI_low) / 2 Distance_CI[col] <- d2 / ci.range } out.0 <- data.frame(Row = d$Row) d$Row <- NULL Distance_CI$Row <- NULL if (!is.null(ID.names)) { out.0 <- cbind(out.0, ID.names) } # Take the max out <- as.data.frame(apply(Distance_CI, 1, max, na.rm = TRUE)) names(out) <- paste0("Distance_", method) # Filter out[paste0("Outlier_", method)] <- vapply( as.data.frame(t(d)), function(x) ifelse(all(is.na(x)), NA_real_, max(x, na.rm = TRUE)), numeric(1) ) out <- cbind(out.0, out) output <- list( data_ = out, threshold_ = threshold ) names(output) <- paste0(names(output), method) output } .check_outliers_cook <- function(x, threshold = NULL, ID.names = NULL) { # Compute d <- unname(stats::cooks.distance(x)) out <- data.frame(Row = seq_along(d)) out$Distance_Cook <- d # Filter out$Outlier_Cook <- as.numeric(out$Distance_Cook > threshold) list( data_cook = out, threshold_cook = threshold ) } .check_outliers_pareto <- function(x, threshold = 0.7) { insight::check_if_installed("loo") # Compute d <- suppressWarnings(loo::pareto_k_values(loo::loo(x))) out <- data.frame(Row = seq_along(d)) out$Distance_Pareto <- d # Filter out$Outlier_Pareto <- as.numeric(out$Distance_Pareto > threshold) list( data_pareto = out, threshold_pareto = threshold ) } .check_outliers_mahalanobis <- function(x, threshold = stats::qchisq( p = 1 - 0.001, df = ncol(x) ), ID.names = NULL, ...) { if (anyNA(x) || any(with(x, x == Inf))) { insight::format_error("Missing or infinite values are not allowed.") } out <- data.frame(Row = seq_len(nrow(x))) if (!is.null(ID.names)) { out <- cbind(out, ID.names) } # Compute out$Distance_Mahalanobis <- stats::mahalanobis(x, center = colMeans(x), cov = stats::cov(x), ...) # Filter out$Outlier_Mahalanobis <- as.numeric(out$Distance_Mahalanobis > threshold) list( data_mahalanobis = out, threshold_mahalanobis = threshold ) } # Bigutils not yet fully available on CRAN .check_outliers_mahalanobis_robust <- function(x, threshold = stats::qchisq( p = 1 - 0.001, df = ncol(x) ), ID.names = NULL) { out <- data.frame(Row = seq_len(nrow(x))) if (!is.null(ID.names)) { out <- cbind(out, ID.names) } insight::check_if_installed("bigutilsr") # Compute U <- svd(scale(x))$u out$Distance_Mahalanobis_robust <- bigutilsr::dist_ogk(U) # Filter out$Outlier_Mahalanobis_robust <- as.numeric( out$Distance_Mahalanobis_robust > threshold ) list( data_mahalanobis_robust = out, threshold_mahalanobis_robust = threshold ) } .check_outliers_mcd <- function(x, threshold = stats::qchisq(p = 1 - 0.001, df = ncol(x)), percentage_central = 0.75, ID.names = NULL, verbose = TRUE, ...) { out <- data.frame(Row = seq_len(nrow(x))) if (!is.null(ID.names)) { out <- cbind(out, ID.names) } # check whether N to p ratio is not too large, else MCD flags too many outliers # See #672: This does seem to be a function of the N/p (N = sample size; p = # number of parameters) ratio. When it is larger than 10, the % of outliers # flagged is okay (in well behaved data). This makes sense: the MCD looks at # the cov matrix of subsamples of the data - with high dimensional data, small # samples sizes will give highly variable cov matrices, as so the "smallest" # one will probably miss-represent the data. if ((nrow(x) / ncol(x)) <= 10 && isTRUE(verbose)) { insight::format_warning( "The sample size is too small in your data, relative to the number of variables, for MCD to be reliable.", "You may try to increase the `percentage_central` argument (must be between 0 and 1), or choose another method." ) } insight::check_if_installed("MASS") # Compute mcd <- MASS::cov.mcd(x, quantile.used = percentage_central * nrow(x)) out$Distance_MCD <- stats::mahalanobis(x, center = mcd$center, cov = mcd$cov) # Filter out$Outlier_MCD <- as.numeric(out$Distance_MCD > threshold) list( data_mcd = out, threshold_mcd = threshold ) } .check_outliers_ics <- function(x, threshold = 0.001, ID.names = NULL, ...) { out <- data.frame(Row = seq_len(nrow(x))) if (!is.null(ID.names)) { out <- cbind(out, ID.names) } insight::check_if_installed("ICS") insight::check_if_installed("ICSOutlier") # Get n cores n_cores <- if (requireNamespace("parallel", quietly = TRUE)) { getOption("mc.cores", 1L) } else { NULL } # tell user about n-cores option if (is.null(n_cores)) { insight::format_alert( "Package `parallel` is not installed. `check_outliers()` will run on a single core.", "Install package `parallel` and set, for example, `options(mc.cores = 4)` to run on multiple cores." ) } else if (n_cores == 1) { insight::format_alert( "Package `parallel` is installed, but `check_outliers()` will run on a single core.", "To use multiple cores, set `options(mc.cores = 4)` (for example)." ) } # Run algorithm # Try outliers <- tryCatch( { ics <- ICS::ics2(x) ICSOutlier::ics.outlier( object = ics, ncores = n_cores, level.dist = threshold, ... ) }, error = function(e) { NULL } ) if (is.null(outliers)) { if (ncol(x) == 1) { insight::print_color("At least two numeric predictors are required to detect outliers.\n", "red") } else { insight::print_color(sprintf("`check_outliers()` does not support models of class `%s`.\n", class(x)[1]), "red") } return(NULL) } # Get results cutoff <- .safe(outliers@ics.dist.cutoff) # validation check if (is.null(cutoff)) { insight::print_color("Could not detect cut-off for outliers.\n", "red") return(NULL) } out$Distance_ICS <- outliers@ics.distances out$Outlier_ICS <- as.numeric(out$Distance_ICS > cutoff) # Out list( data_ics = out, threshold_ics = threshold ) } .check_outliers_optics <- function(x, threshold = NULL, ID.names = NULL, xi = 0.05) { out <- data.frame(Row = seq_len(nrow(x))) if (!is.null(ID.names)) { out <- cbind(out, ID.names) } insight::check_if_installed("dbscan") # Compute rez <- dbscan::optics(x, minPts = threshold) rez <- dbscan::extractXi(rez, xi = xi) # TODO: find automatic way of setting xi out$Distance_OPTICS <- rez$coredist # Filter if (is.null(rez$cluster)) { out$Outlier_OPTICS <- 0 } else { out$Outlier_OPTICS <- as.numeric(rez$cluster == 0) } list( data_optics = out, threshold_optics = threshold ) } # .check_outliers_iforest <- function(x, threshold = 0.025) { # out <- data.frame(Row = seq_len(nrow(x))) # # # Install packages # insight::check_if_installed("solitude") # # # Compute # if (utils::packageVersion("solitude") < "0.2.0") { # iforest <- solitude::isolationForest(x) # out$Distance_iforest <- stats::predict(iforest, x, type = "anomaly_score") # } else if (utils::packageVersion("solitude") == "0.2.0") { # stop(paste("Must update package `solitude` (above version 0.2.0).", # "Please run `install.packages('solitude')`."), call. = FALSE) # } else { # iforest <- solitude::isolationForest$new(sample_size = nrow(x)) # suppressMessages(iforest$fit(x)) # out$Distance_iforest <- iforest$scores$anomaly_score # } # # # # Threshold # cutoff <- stats::median(out$Distance_iforest) + stats::qnorm(1 - threshold) * stats::mad(out$Distance_iforest) # # Filter # out$Outlier_iforest <- as.numeric(out$Distance_iforest >= cutoff) # # out$Row <- NULL # list( # "data_iforest" = out, # "threshold_iforest" = threshold # ) # } .check_outliers_lof <- function(x, threshold = 0.001, ID.names = NULL) { if (threshold < 0 || threshold > 1) { insight::format_error( "The `threshold` argument must be between 0 and 1 for method `lof`." ) } out <- data.frame(Row = seq_len(nrow(x))) if (!is.null(ID.names)) { out <- cbind(out, ID.names) } insight::check_if_installed("dbscan") # Compute out$Distance_LOF <- log(dbscan::lof(x, minPts = ncol(x))) # Threshold cutoff <- stats::qnorm(1 - threshold) * stats::sd(out$Distance_LOF) # Filter out$Outlier_LOF <- as.numeric(out$Distance_LOF > cutoff) list( data_lof = out, threshold_lof = threshold ) } # Non-supported model classes --------------------------------------- #' @export check_outliers.glmmTMB <- function(x, ...) { insight::format_alert(paste0("`check_outliers()` does not yet support models of class `", class(x)[1], "`.")) NULL } #' @export check_outliers.lmrob <- check_outliers.glmmTMB #' @export check_outliers.glmrob <- check_outliers.glmmTMB #' @export check_outliers.rq <- check_outliers.glmmTMB #' @export check_outliers.rqs <- check_outliers.glmmTMB #' @export check_outliers.rqss <- check_outliers.glmmTMB performance/R/print-methods.R0000644000176200001440000001223714736731423015713 0ustar liggesusers#' @export print.r2_generic <- function(x, digits = 3, ...) { model_type <- attr(x, "model_type") if (!is.null(model_type)) { insight::print_color(sprintf("# R2 for %s Regression\n", model_type), "blue") } if (all(c("R2_adjusted", "R2_within_adjusted") %in% names(x))) { # print regular R2 out <- c( sprintf(" R2: %.*f", digits, x$R2[1]), sprintf(" adj. R2: %.*f", digits, x$R2_adjusted[1]), sprintf(" within R2: %.*f", digits, x$R2_within[1]), sprintf(" adj. within R2: %.*f", digits, x$R2_within_adjusted[1]) ) } else if ("R2_adjusted" %in% names(x)) { out <- c( sprintf(" R2: %.*f", digits, x$R2[1]), sprintf(" adj. R2: %.*f", digits, x$R2_adjusted[1]) ) } else { out <- sprintf(" %s: %.*f", names(x$R2[1]), digits, x$R2[1]) } # add CI? if (length(x$R2) == 3) { out[1] <- .add_r2_ci_to_print(out[1], x$R2[2], x$R2[3], digits = digits) } if (!is.null(x$R2_adjusted) && length(x$R2_adjusted) == 3 && length(out) > 1) { out[2] <- .add_r2_ci_to_print(out[2], x$R2_adjusted[2], x$R2_adjusted[3], digits = digits) } if (!is.null(x$R2_within) && length(x$R2_within) == 3 && length(out) > 2) { out[3] <- .add_r2_ci_to_print(out[3], x$R2_within[2], x$R2_within[3], digits = digits) } if (!is.null(x$R2_within_adjusted) && length(x$R2_within_adjusted) == 3 && length(out) > 3) { out[4] <- .add_r2_ci_to_print(out[4], x$R2_within_adjusted[2], x$R2_within_adjusted[3], digits = digits) } # separate lines for multiple R2 out <- paste0(out, collapse = "\n") cat(out) cat("\n") invisible(x) } .add_r2_ci_to_print <- function(out, ci_low, ci_high, digits) { paste0( out, sprintf(" %s", insight::format_ci(ci_low, ci_high, digits = digits, ci = NULL)) ) } #' @export print.r2_pseudo <- function(x, digits = 3, ...) { model_type <- attr(x, "model_type") if (!is.null(model_type)) { insight::print_color(sprintf("# R2 for %s Regression\n", model_type), "blue") } cat(sprintf(" %s: %.*f\n", names(x[[1]]), digits, x[[1]])) invisible(x) } #' @export print.r2_mlm <- function(x, digits = 3, ...) { model_type <- attr(x, "model_type") is_multivar_r2 <- all(names(x) == c("Symmetric Rxy", "Asymmetric Pxy")) if (!is.null(model_type) && !is_multivar_r2) { insight::print_color( sprintf("# R2 for %s Regression\n\n", model_type), "blue" ) } else if (!is.null(model_type) && is_multivar_r2) { insight::print_color( sprintf("# Multivariate R2 for %s Regression\n", model_type), "blue" ) } else { insight::print_color("# R2\n\n", "blue") } if (is_multivar_r2) { cat(sprintf(" Symmetric Rxy: %.*f", digits, x[["Symmetric Rxy"]])) cat("\n") cat(sprintf("Asymmetric Pxy: %.*f", digits, x[["Asymmetric Pxy"]])) cat("\n\n") } else { for (i in names(x)) { insight::print_color(sprintf("## %s\n", i), "cyan") out <- paste( c( sprintf(" R2: %.*f", digits, x[[i]]$R2), sprintf(" adj. R2: %.*f", digits, x[[i]]$R2_adjusted) ), collapse = "\n" ) cat(out) cat("\n\n") } } invisible(x) } #' @export print.r2_bayes <- function(x, digits = 3, ...) { insight::print_color("# Bayesian R2 with Compatibility Interval\n\n", "blue") r2_ci <- insight::format_ci( attributes(x)$CI$R2_Bayes$CI_low, attributes(x)$CI$R2_Bayes$CI_high, ci = attributes(x)$CI$R2_Bayes$CI, digits = digits ) out <- sprintf(" Conditional R2: %.*f (%s)", digits, x$R2_Bayes, r2_ci) if ("R2_Bayes_marginal" %in% names(x)) { r2_marginal_ci <- insight::format_ci( attributes(x)$CI$R2_Bayes_marginal$CI_low, attributes(x)$CI$R2_Bayes_marginal$CI_high, ci = attributes(x)$CI$R2_Bayes_marginal$CI, digits = digits ) out <- paste(c( out, sprintf(" Marginal R2: %.*f (%s)", digits, x$R2_Bayes_marginal, r2_marginal_ci) ), collapse = "\n") } cat(out) cat("\n") invisible(x) } #' @export print.r2_loo <- function(x, digits = 3, ...) { insight::print_color("# LOO-adjusted R2 with Compatibility Interval\n\n", "blue") r2_ci <- insight::format_ci( attributes(x)$CI$R2_loo$CI_low, attributes(x)$CI$R2_loo$CI_high, ci = attributes(x)$CI$R2_loo$CI, digits = digits ) out <- sprintf(" Conditional R2: %.*f (%s)", digits, x$R2_loo, r2_ci) if ("R2_loo_marginal" %in% names(x)) { r2_marginal_ci <- insight::format_ci( attributes(x)$CI$R2_loo_marginal$CI_low, attributes(x)$CI$R2_loo_marginal$CI_high, ci = attributes(x)$CI$R2_loo_marginal$CI, digits = digits ) out <- paste(c( out, sprintf(" Marginal R2: %.*f (%s)", digits, x$R2_loo_marginal, r2_marginal_ci) ), collapse = "\n") } cat(out) cat("\n") invisible(x) } #' @export print.r2_nakagawa_by_group <- function(x, digits = 3, ...) { insight::print_color("# Explained Variance by Level\n\n", "blue") cat(insight::export_table(x, digits = digits)) cat("\n") invisible(x) } performance/R/residuals.R0000644000176200001440000000035314272453120015073 0ustar liggesusers#' @exportS3Method residuals iv_robust residuals.iv_robust <- function(object, ...) { datawizard::to_numeric(insight::get_response(object, verbose = FALSE), dummy_factors = FALSE, preserve_levels = TRUE) - object$fitted.values } performance/R/reexports.R0000644000176200001440000000031014620351763015133 0ustar liggesusers#' @importFrom insight display #' @export insight::display #' @importFrom insight print_md #' @export insight::print_md #' @importFrom insight print_html #' @export insight::print_html performance/R/r2_tjur.R0000644000176200001440000000504014510751271014470 0ustar liggesusers#' @title Tjur's R2 - coefficient of determination (D) #' @name r2_tjur #' #' @description This method calculates the Coefficient of Discrimination `D` #' (also known as Tjur's R2; \cite{Tjur, 2009}) for generalized linear (mixed) models #' for binary outcomes. It is an alternative to other pseudo-R2 values like #' Nagelkerke's R2 or Cox-Snell R2. The Coefficient of Discrimination `D` #' can be read like any other (pseudo-)R2 value. #' #' @param model Binomial Model. #' @param ... Arguments from other functions, usually only used internally. #' #' @return A named vector with the R2 value. #' #' @examples #' model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") #' r2_tjur(model) #' #' @references #' Tjur, T. (2009). Coefficients of determination in logistic regression #' models - A new proposal: The coefficient of discrimination. The American #' Statistician, 63(4), 366-372. #' #' @export r2_tjur <- function(model, ...) { UseMethod("r2_tjur") } #' @export r2_tjur.default <- function(model, ...) { info <- list(...)$model_info if (is.null(info)) { info <- suppressWarnings(insight::model_info(model, verbose = FALSE)) } # check for valid object class if (!info$is_binomial) { insight::format_error("`model` must be binomial.") } y <- .recode_to_zero(insight::get_response(model, verbose = FALSE)) pred <- stats::predict(model, type = "response", re.form = NULL) # delete pred for cases with missing residuals if (anyNA(stats::residuals(model))) { pred <- pred[!is.na(stats::residuals(model))] } categories <- unique(y) m1 <- mean(pred[which(y == categories[1])], na.rm = TRUE) m2 <- mean(pred[which(y == categories[2])], na.rm = TRUE) tjur_d <- abs(m2 - m1) names(tjur_d) <- "Tjur's R2" tjur_d } #' @export r2_tjur.nestedLogit <- function(model, ...) { resp <- insight::get_response(model, dichotomies = TRUE, verbose = FALSE) stats::setNames( lapply(names(model$models), function(i) { y <- resp[[i]] m <- model$models[[i]] pred <- stats::predict(m, type = "response") # delete pred for cases with missing residuals if (anyNA(stats::residuals(m))) { pred <- pred[!is.na(stats::residuals(m))] } categories <- unique(y) m1 <- mean(pred[which(y == categories[1])], na.rm = TRUE) m2 <- mean(pred[which(y == categories[2])], na.rm = TRUE) tjur_d <- abs(m2 - m1) names(tjur_d) <- "Tjur's R2" tjur_d }), names(model$models) ) } performance/R/check_overdispersion.R0000644000176200001440000002532414736731423017327 0ustar liggesusers#' @title Check overdispersion (and underdispersion) of GL(M)M's #' @name check_overdispersion #' #' @description `check_overdispersion()` checks generalized linear (mixed) #' models for overdispersion (and underdispersion). #' #' @param x Fitted model of class `merMod`, `glmmTMB`, `glm`, or `glm.nb` #' (package **MASS**), or an object returned by `simulate_residuals()`. #' #' @inheritParams check_zeroinflation #' #' @return A list with results from the overdispersion test, like chi-squared #' statistics, p-value or dispersion ratio. #' #' @details Overdispersion occurs when the observed variance is higher than the #' variance of a theoretical model. For Poisson models, variance increases #' with the mean and, therefore, variance usually (roughly) equals the mean #' value. If the variance is much higher, the data are "overdispersed". A less #' common case is underdispersion, where the variance is much lower than the #' mean. #' #' @section Interpretation of the Dispersion Ratio: #' If the dispersion ratio is close to one, a Poisson model fits well to the #' data. Dispersion ratios larger than one indicate overdispersion, thus a #' negative binomial model or similar might fit better to the data. Dispersion #' ratios much smaller than one indicate underdispersion. A p-value < .05 #' indicates either overdispersion or underdispersion (the first being more common). #' #' @section Overdispersion in Poisson Models: #' For Poisson models, the overdispersion test is based on the code from #' _Gelman and Hill (2007), page 115_. #' #' @section Overdispersion in Negative Binomial or Zero-Inflated Models: #' For negative binomial (mixed) models or models with zero-inflation component, #' the overdispersion test is based simulated residuals (see [`simulate_residuals()`]). #' #' @section Overdispersion in Mixed Models: #' For `merMod`- and `glmmTMB`-objects, `check_overdispersion()` #' is based on the code in the #' [GLMM FAQ](http://bbolker.github.io/mixedmodels-misc/glmmFAQ.html), #' section *How can I deal with overdispersion in GLMMs?*. Note that this #' function only returns an *approximate* estimate of an overdispersion #' parameter. Using this approach would be inaccurate for zero-inflated or #' negative binomial mixed models (fitted with `glmmTMB`), thus, in such cases, #' the overdispersion test is based on [`simulate_residuals()`] (which is identical #' to `check_overdispersion(simulate_residuals(model))`). #' #' @inheritSection check_zeroinflation Tests based on simulated residuals #' #' @section How to fix Overdispersion: #' Overdispersion can be fixed by either modeling the dispersion parameter, or #' by choosing a different distributional family (like Quasi-Poisson, or #' negative binomial, see _Gelman and Hill (2007), pages 115-116_). #' #' @family functions to check model assumptions and and assess model quality #' #' @references #' - Bolker B et al. (2017): #' [GLMM FAQ.](http://bbolker.github.io/mixedmodels-misc/glmmFAQ.html) #' #' - Gelman, A., and Hill, J. (2007). Data analysis using regression and #' multilevel/hierarchical models. Cambridge; New York: Cambridge University #' Press. #' #' @examplesIf getRversion() >= "4.0.0" && require("glmmTMB") #' data(Salamanders, package = "glmmTMB") #' m <- glm(count ~ spp + mined, family = poisson, data = Salamanders) #' check_overdispersion(m) #' @export check_overdispersion <- function(x, ...) { UseMethod("check_overdispersion") } # default ----------------------- #' @export check_overdispersion.default <- function(x, ...) { .is_model_valid(x) insight::format_error( paste0("`check_overdisperion()` not yet implemented for models of class `", class(x)[1], "`.") ) } # Methods ----------------------------- #' @export plot.check_overdisp <- function(x, ...) { insight::check_if_installed(c("see", "graphics"), "for overdispersion plots") obj_name <- attr(x, "object_name", exact = TRUE) model <- NULL if (!is.null(obj_name)) { model <- .safe(get(obj_name, envir = parent.frame())) if (is.null(model)) { # second try, global env model <- .safe(get(obj_name, envir = globalenv())) } } if (!is.null(model)) { x <- .model_diagnostic_overdispersion(model) class(x) <- c("see_check_overdisp", "data.frame") attr(x, "colors") <- list(...)$colors attr(x, "line_size") <- list(...)$size_line attr(x, "overdisp_type") <- list(...)$plot_type graphics::plot(x, ...) } } #' @export print.check_overdisp <- function(x, digits = 3, ...) { orig_x <- x x$dispersion_ratio <- sprintf("%.*f", digits, x$dispersion_ratio) if (!is.null(x$chisq_statistic)) { x$chisq_statistic <- sprintf("%.*f", digits, x$chisq_statistic) } x$p_value <- pval <- round(x$p_value, digits = digits) if (x$p_value < 0.001) x$p_value <- "< 0.001" maxlen <- max( nchar(x$dispersion_ratio), nchar(x$chisq_statistic), nchar(x$p_value) ) insight::print_color("# Overdispersion test\n\n", "blue") if (is.null(x$chisq_statistic)) { cat(sprintf(" dispersion ratio = %s\n", format(x$dispersion_ratio, justify = "right", width = maxlen))) cat(sprintf(" p-value = %s\n\n", format(x$p_value, justify = "right", width = maxlen))) } else { cat(sprintf(" dispersion ratio = %s\n", format(x$dispersion_ratio, justify = "right", width = maxlen))) cat(sprintf(" Pearson's Chi-Squared = %s\n", format(x$chisq_statistic, justify = "right", width = maxlen))) cat(sprintf(" p-value = %s\n\n", format(x$p_value, justify = "right", width = maxlen))) } if (pval > 0.05) { message("No overdispersion detected.") } else if (x$dispersion_ratio > 1) { message("Overdispersion detected.") } else { message("Underdispersion detected.") } invisible(orig_x) } # Overdispersion for classical models ----------------------------- #' @export check_overdispersion.glm <- function(x, verbose = TRUE, ...) { # model info info <- insight::model_info(x) obj_name <- insight::safe_deparse_symbol(substitute(x)) # for certain distributions, simulated residuals are more accurate use_simulated <- info$is_bernoulli || info$is_binomial || (!info$is_count && !info$is_binomial) || info$is_negbin # model classes not supported in DHARMa not_supported <- c("fixest", "glmx") if (use_simulated && !inherits(x, not_supported)) { return(check_overdispersion(simulate_residuals(x, ...), object_name = obj_name, ...)) } # check if we have poisson - need this for models not supported by DHARMa if (!info$is_count && !info$is_binomial) { insight::format_error( "Overdispersion checks can only be used for models from Poisson families or binomial families with trials > 1." ) } # check for Bernoulli if (info$is_bernoulli) { insight::format_error("Overdispersion checks cannot be used for Bernoulli models.") } yhat <- stats::fitted(x) n <- stats::nobs(x) k <- length(insight::find_parameters(x, effects = "fixed", flatten = TRUE)) zi <- (insight::get_response(x, verbose = FALSE) - yhat) / sqrt(yhat) chisq <- sum(zi^2) ratio <- chisq / (n - k) p.value <- stats::pchisq(chisq, df = n - k, lower.tail = FALSE) out <- list( chisq_statistic = chisq, dispersion_ratio = ratio, residual_df = n - k, p_value = p.value ) class(out) <- c("check_overdisp", "see_check_overdisp") attr(out, "object_name") <- obj_name out } #' @export check_overdispersion.fixest <- check_overdispersion.glm #' @export check_overdispersion.fixest_multi <- function(x, verbose = TRUE, ...) { lapply(x, check_overdispersion.fixest) } #' @export check_overdispersion.glmx <- check_overdispersion.glm # mfx models ------------------------------ #' @export check_overdispersion.poissonmfx <- function(x, ...) { check_overdispersion(x$fit, ...) } #' @export check_overdispersion.poissonirr <- check_overdispersion.poissonmfx #' @export check_overdispersion.negbinirr <- check_overdispersion.poissonmfx #' @export check_overdispersion.negbinmfx <- check_overdispersion.poissonmfx #' @export check_overdispersion.model_fit <- check_overdispersion.poissonmfx # Overdispersion for mixed models --------------------------- #' @export check_overdispersion.merMod <- function(x, ...) { # for certain distributions, simulated residuals are more accurate info <- insight::model_info(x) obj_name <- insight::safe_deparse_symbol(substitute(x)) # for certain distributions, simulated residuals are more accurate use_simulated <- info$family == "genpois" || info$is_zero_inflated || info$is_bernoulli || info$is_binomial || (!info$is_count && !info$is_binomial) || info$is_negbin # nolint if (use_simulated) { return(check_overdispersion(simulate_residuals(x, ...), object_name = obj_name, ...)) } rdf <- stats::df.residual(x) rp <- insight::get_residuals(x, type = "pearson") # check if pearson residuals are available if (insight::is_empty_object(rp)) { return(check_overdispersion(simulate_residuals(x, ...), object_name = obj_name, ...)) } Pearson.chisq <- sum(rp^2) prat <- Pearson.chisq / rdf pval <- stats::pchisq(Pearson.chisq, df = rdf, lower.tail = FALSE) out <- list( chisq_statistic = Pearson.chisq, dispersion_ratio = prat, residual_df = rdf, p_value = pval ) class(out) <- c("check_overdisp", "see_check_overdisp") attr(out, "object_name") <- obj_name out } #' @export check_overdispersion.negbin <- check_overdispersion.merMod #' @export check_overdispersion.glmmTMB <- check_overdispersion.merMod # simulated residuals ----------------------------- #' @rdname check_overdispersion #' @export check_overdispersion.performance_simres <- function(x, alternative = c("two.sided", "less", "greater"), ...) { alternative <- match.arg(alternative) # check for special arguments - we may pass "object_name" from other methods dots <- list(...) if (is.null(dots$object_name)) { obj_name <- insight::safe_deparse_symbol(substitute(x)) } else { obj_name <- dots$object_name } # statistics function variance <- stats::sd(x$simulatedResponse)^2 dispersion <- function(i) stats::var(i - x$fittedPredictedResponse) / variance # compute test results result <- .simres_statistics(x, statistic_fun = dispersion, alternative = alternative) out <- list( dispersion_ratio = result$observed / mean(result$simulated), p_value = result$p ) class(out) <- c("check_overdisp", "see_check_overdisp") attr(out, "object_name") <- obj_name out } #' @export check_overdispersion.DHARMa <- check_overdispersion.performance_simres performance/R/performance_logloss.R0000644000176200001440000000411014736731423017150 0ustar liggesusers#' @title Log Loss #' @name performance_logloss #' #' @description Compute the log loss for models with binary outcome. #' #' @param model Model with binary outcome. #' @param ... Currently not used. #' @inheritParams model_performance.lm #' #' @return Numeric, the log loss of `model`. #' #' @details #' Logistic regression models predict the probability of an outcome of being a #' "success" or "failure" (or 1 and 0 etc.). `performance_logloss()` evaluates #' how good or bad the predicted probabilities are. High values indicate bad #' predictions, while low values indicate good predictions. The lower the #' log-loss, the better the model predicts the outcome. #' #' @seealso [`performance_score()`] #' #' @examples #' data(mtcars) #' m <- glm(formula = vs ~ hp + wt, family = binomial, data = mtcars) #' performance_logloss(m) #' @export performance_logloss <- function(model, verbose = TRUE, ...) { UseMethod("performance_logloss") } #' @export performance_logloss.default <- function(model, verbose = TRUE, ...) { .is_model_valid(model) resp <- .recode_to_zero(insight::get_response(model, verbose = verbose)) ll <- suppressWarnings(mean(log(1 - abs(resp - stats::fitted(model))) * -1)) if (is.na(ll)) { if (verbose) insight::print_color("Can't calculate log-loss.\n", "red") return(NA) } ll } #' @export performance_logloss.brmsfit <- function(model, verbose = TRUE, ...) { yhat <- stats::fitted(object = model, summary = TRUE, ...)[, "Estimate"] resp <- .recode_to_zero(insight::get_response(model, verbose = verbose)) ll <- suppressWarnings(mean(log(1 - abs(resp - yhat)) * -1)) if (is.na(ll)) { if (verbose) insight::print_color("Can't calculate log-loss.\n", "red") return(NA) } ll } # mfx models ------------------------------- #' @export performance_logloss.logitor <- function(model, ...) { performance_logloss(model$fit, ...) } #' @export performance_logloss.logitmfx <- performance_logloss.logitor #' @export performance_logloss.probitmfx <- performance_logloss.logitor performance/R/r2_ci.R0000644000176200001440000000375614335664246014125 0ustar liggesusers.r2_ci <- function(model, ci = 0.95, verbose = TRUE, ...) { alpha <- 1 - ci n <- insight::n_obs(model) df_int <- if (insight::has_intercept(model)) { 1 } else { 0 } model_rank <- tryCatch( model$rank - df_int, error = function(e) insight::n_parameters(model) - df_int ) model_r2 <- r2(model, ci = NULL, verbose = verbose, ...) out <- lapply(model_r2, function(rsq) { ci_low <- stats::uniroot( .pRsq, c(0.00001, 0.99999), R2_obs = as.vector(rsq), p = model_rank, nobs = n, alpha = 1 - alpha / 2 )$root ci_high <- stats::uniroot( .pRsq, c(0.00001, 0.99999), R2_obs = as.vector(rsq), p = model_rank, nobs = n, alpha = alpha / 2 )$root c(rsq, CI_low = ci_low, CI_high = ci_high) }) names(out) <- names(model_r2) attr(out, "ci") <- ci class(out) <- class(model_r2) out } .dRsq <- function(K1, R2_pop, R2_obs, p, nobs) { NCP <- R2_pop / (1 - R2_pop) F1_obs <- ((nobs - p - 1) / p) * (R2_obs / (1 - R2_obs)) exp(log( suppressWarnings(stats::pf( q = F1_obs, df1 = p, df2 = (nobs - p - 1), ncp = NCP * K1, lower.tail = FALSE )) ) + stats::dchisq(x = K1, df = (nobs - 1), log = TRUE)) } .pRsq <- function(R2_pop, R2_obs, p, nobs, alpha = 1) { a1 <- 1 - alpha # This approach avoids undersampling the area of the chi-squared # distribution that actually has any density integrals <- mapply( function(i, j, ...) { dots <- list(...) stats::integrate(.dRsq, i, j, R2_pop = dots$R2_pop, R2_obs = dots$R2_obs, p = dots$p, nobs = dots$nobs ) }, seq(0, 2, by = 0.25) * nobs, c(seq(0.25, 2, by = 0.25), Inf) * nobs, MoreArgs = list( R2_pop = R2_pop, R2_obs = R2_obs, p = p, nobs = nobs ), SIMPLIFY = TRUE ) sum(unlist(integrals["value", ])) - a1 } performance/R/test_wald.R0000644000176200001440000000566614736731423015114 0ustar liggesusers#' @rdname test_performance #' @export test_wald <- function(..., verbose = TRUE) { UseMethod("test_wald") } #' @export test_wald.default <- function(..., verbose = TRUE) { # Attribute class to list and get names from the global environment my_objects <- insight::ellipsis_info(..., only_models = TRUE) # validation checks (will throw error if non-valid objects) my_objects <- .test_performance_checks(my_objects, verbose = verbose) # ensure proper object names my_objects <- .check_objectnames(my_objects, sapply(match.call(expand.dots = FALSE)[["..."]], as.character)) # If a suitable class is found, run the more specific method on it if (inherits(my_objects, c("ListNestedRegressions", "ListNonNestedRegressions", "ListLavaan"))) { test_wald(my_objects) } else { insight::format_error("The models cannot be compared for some reason :/") } } #' @export test_wald.ListNestedRegressions <- function(objects, verbose = TRUE, ...) { # for binomial models, only chisq-test if (all(attributes(objects)$is_binomial)) { if (verbose) { insight::format_alert( "Using Wald's F-Test is inappropriate for models with `binomial` family.", "Running Likelihood Ratio Test (LRT) now." ) } return(test_likelihoodratio(objects)) } out <- .test_wald(objects, test = "F") attr(out, "is_nested") <- TRUE class(out) <- c("test_performance", class(out)) out } #' @export test_wald.ListNonNestedRegressions <- function(objects, verbose = TRUE, ...) { insight::format_error("Wald tests cannot be run on non-nested models. Try `test_vuong()`.") } # Helpers -------------------------- .test_wald <- function(objects, test = "F") { # Compute stuff dfs <- sapply(objects, insight::get_df, type = "residual") # sort by df if (is.unsorted(dfs) && is.unsorted(rev(dfs))) { objects <- objects[order(dfs)] dfs <- sort(dfs, na.last = TRUE) } dfs_diff <- c(NA, diff(sapply(objects, insight::get_df, type = "model"))) dev <- as.numeric(lapply(objects, insight::get_deviance)) dev_diff <- c(NA, -diff(dev)) out <- data.frame( df = dfs, df_diff = round(dfs_diff), stringsAsFactors = FALSE ) # Find reference-model related stuff refmodel <- order(dfs)[1] my_scale <- dev[refmodel] / dfs[refmodel] # test = "F" if (test == "F") { f_value <- (dev_diff / dfs_diff) / my_scale f_value[!is.na(f_value) & f_value < 0] <- NA # rather than p = 0 out[["F"]] <- f_value p <- stats::pf(f_value, abs(dfs_diff), dfs[refmodel], lower.tail = FALSE) # test = "LRT" } else { chi2 <- dev_diff / my_scale * sign(dfs_diff) chi2[!is.na(chi2) & chi2 < 0] <- NA # rather than p = 0 out$Chi2 <- chi2 p <- stats::pchisq(chi2, abs(dfs_diff), lower.tail = FALSE) } out$p <- p row.names(out) <- NULL out <- cbind(.test_performance_init(objects), out) out } performance/R/check_residuals.R0000644000176200001440000000654514600524676016253 0ustar liggesusers#' Check uniformity of simulated residuals #' #' `check_residuals()` checks generalized linear (mixed) models for uniformity #' of randomized quantile residuals, which can be used to identify typical model #' misspecification problems, such as over/underdispersion, zero-inflation, and #' residual spatial and temporal autocorrelation. #' #' @param x An object returned by [`simulate_residuals()`] or #' [`DHARMa::simulateResiduals()`]. #' @param alternative A character string specifying the alternative hypothesis. #' See [`stats::ks.test()`] for details. #' @param ... Passed down to [`stats::ks.test()`]. #' #' @details Uniformity of residuals is checked using a Kolmogorov-Smirnov test. #' There is a `plot()` method to visualize the distribution of the residuals. #' The test for uniformity basically tests to which extent the observed values #' deviate from the model expectations (i.e. simulated values). In this sense, #' the `check_residuals()` function has similar goals like [`check_predictions()`]. #' #' @inheritSection simulate_residuals Tests based on simulated residuals #' #' @seealso [`simulate_residuals()`], [`check_zeroinflation()`], #' [`check_overdispersion()`] and [`check_predictions()`]. See also #' [`see::plot.see_performance_simres()`] for options to customize the plot. #' #' @return The p-value of the test statistics. #' #' @examplesIf require("DHARMa") #' dat <- DHARMa::createData(sampleSize = 100, overdispersion = 0.5, family = poisson()) #' m <- glm(observedResponse ~ Environment1, family = poisson(), data = dat) #' res <- simulate_residuals(m) #' check_residuals(res) #' #' @export check_residuals <- function(x, ...) { UseMethod("check_residuals") } #' @rdname check_residuals #' @export check_residuals.default <- function(x, alternative = c("two.sided", "less", "greater"), ...) { if (insight::is_model(x)) { check_residuals(simulate_residuals(x, ...), alternative = alternative) } else { insight::format_error("`check_residuals()` only works with objects supported by `simulate_residuals()` or `DHARMa::simulateResiduals()`.") # nolint } } #' @export check_residuals.performance_simres <- function(x, alternative = c("two.sided", "less", "greater"), ...) { alternative <- match.arg(alternative) ts_test <- suppressWarnings( stats::ks.test( stats::residuals(x), "punif", alternative = alternative, ... ) ) p.val <- ts_test$p.value attr(p.val, "data") <- x attr(p.val, "object_name") <- insight::safe_deparse_symbol(substitute(x)) class(p.val) <- unique(c("check_residuals", "see_check_residuals", class(p.val))) p.val } #' @export check_residuals.DHARMa <- check_residuals.performance_simres # methods ------------------------------ #' @export print.check_residuals <- function(x, ...) { pstring <- insight::format_p(x) if (x < 0.05) { insight::print_color( sprintf( "Warning: Non-uniformity of simulated residuals detected (%s).\n", pstring ), "red" ) } else { insight::print_color( sprintf( "OK: Simulated residuals appear as uniformly distributed (%s).\n", pstring ), "green" ) } invisible(x) } #' @export plot.check_residuals <- function(x, ...) { insight::check_if_installed("see", "for residual plots") NextMethod() } performance/R/check_convergence.R0000644000176200001440000001033514706655512016547 0ustar liggesusers#' @title Convergence test for mixed effects models #' @name check_convergence #' #' @description `check_convergence()` provides an alternative convergence #' test for `merMod`-objects. #' #' @param x A `merMod` or `glmmTMB`-object. #' @param tolerance Indicates up to which value the convergence result is #' accepted. The smaller `tolerance` is, the stricter the test will be. #' @param ... Currently not used. #' #' @return `TRUE` if convergence is fine and `FALSE` if convergence #' is suspicious. Additionally, the convergence value is returned as attribute. #' #' @section Convergence and log-likelihood: #' Convergence problems typically arise when the model hasn't converged #' to a solution where the log-likelihood has a true maximum. This may result #' in unreliable and overly complex (or non-estimable) estimates and standard #' errors. #' #' @section Inspect model convergence: #' **lme4** performs a convergence-check (see `?lme4::convergence`), #' however, as as discussed [here](https://github.com/lme4/lme4/issues/120) #' and suggested by one of the lme4-authors in #' [this comment](https://github.com/lme4/lme4/issues/120#issuecomment-39920269), #' this check can be too strict. `check_convergence()` thus provides an #' alternative convergence test for `merMod`-objects. #' #' @section Resolving convergence issues: #' Convergence issues are not easy to diagnose. The help page on #' `?lme4::convergence` provides most of the current advice about #' how to resolve convergence issues. Another clue might be large parameter #' values, e.g. estimates (on the scale of the linear predictor) larger than #' 10 in (non-identity link) generalized linear model *might* indicate #' [complete separation](https://stats.oarc.ucla.edu/other/mult-pkg/faq/general/faqwhat-is-complete-or-quasi-complete-separation-in-logisticprobit-regression-and-how-do-we-deal-with-them/). #' Complete separation can be addressed by regularization, e.g. penalized #' regression or Bayesian regression with appropriate priors on the fixed effects. #' #' @section Convergence versus Singularity: #' Note the different meaning between singularity and convergence: singularity #' indicates an issue with the "true" best estimate, i.e. whether the maximum #' likelihood estimation for the variance-covariance matrix of the random effects #' is positive definite or only semi-definite. Convergence is a question of #' whether we can assume that the numerical optimization has worked correctly #' or not. #' #' @family functions to check model assumptions and and assess model quality #' #' @examplesIf require("lme4") && require("glmmTMB") #' data(cbpp, package = "lme4") #' set.seed(1) #' cbpp$x <- rnorm(nrow(cbpp)) #' cbpp$x2 <- runif(nrow(cbpp)) #' #' model <- lme4::glmer( #' cbind(incidence, size - incidence) ~ period + x + x2 + (1 + x | herd), #' data = cbpp, #' family = binomial() #' ) #' #' check_convergence(model) #' #' \donttest{ #' model <- suppressWarnings(glmmTMB::glmmTMB( #' Sepal.Length ~ poly(Petal.Width, 4) * poly(Petal.Length, 4) + #' (1 + poly(Petal.Width, 4) | Species), #' data = iris #' )) #' check_convergence(model) #' } #' @export check_convergence <- function(x, tolerance = 0.001, ...) { UseMethod("check_convergence") } #' @export check_convergence.default <- function(x, tolerance = 0.001, ...) { .is_model_valid(x) message(sprintf("`check_convergence()` does not work for models of class '%s'.", class(x)[1])) } #' @export check_convergence.merMod <- function(x, tolerance = 0.001, ...) { insight::check_if_installed("Matrix") relgrad <- with(x@optinfo$derivs, Matrix::solve(Hessian, gradient)) # copy logical value, TRUE if convergence is OK retval <- max(abs(relgrad)) < tolerance # copy convergence value attr(retval, "gradient") <- max(abs(relgrad)) # return result retval } #' @export check_convergence.glmmTMB <- function(x, tolerance = 0.001, ...) { # https://github.com/glmmTMB/glmmTMB/issues/275 # https://stackoverflow.com/q/79110546/2094622 isTRUE(all.equal(x$fit$convergence, 0, tolerance = tolerance)) && isTRUE(x$sdr$pdHess) } #' @export check_convergence._glm <- function(x, ...) { isTRUE(x$fit$converged) } performance/NAMESPACE0000644000176200001440000004761014741714104014005 0ustar liggesusers# Generated by roxygen2: do not edit by hand S3method(bayesplot::pp_check, lm) S3method(bayesplot::pp_check, glm) S3method(bayesplot::pp_check, glmmTMB) S3method(bayesplot::pp_check, glm.nb) S3method(bayesplot::pp_check, merMod) S3method(bayesplot::pp_check, MixMod) S3method(bayesplot::pp_check, mle2) S3method(bayesplot::pp_check, negbin) S3method(bayesplot::pp_check, polr) S3method(bayesplot::pp_check, rma) S3method(bayesplot::pp_check, vlm) S3method(bayesplot::pp_check, wbm) S3method(bayesplot::pp_check, BFBayesFactor) S3method(AIC,bife) S3method(as.data.frame,check_outliers) S3method(as.data.frame,icc) S3method(as.data.frame,looic) S3method(as.data.frame,performance_accuracy) S3method(as.data.frame,performance_cv) S3method(as.data.frame,performance_pcp) S3method(as.data.frame,performance_score) S3method(as.data.frame,r2_bayes) S3method(as.data.frame,r2_loo) S3method(as.data.frame,r2_nakagawa) S3method(as.double,check_outliers) S3method(as.double,performance_roc) S3method(check_autocorrelation,default) S3method(check_collinearity,BFBayesFactor) S3method(check_collinearity,MixMod) S3method(check_collinearity,afex_aov) S3method(check_collinearity,betamfx) S3method(check_collinearity,betaor) S3method(check_collinearity,default) S3method(check_collinearity,glmmTMB) S3method(check_collinearity,hurdle) S3method(check_collinearity,logitmfx) S3method(check_collinearity,logitor) S3method(check_collinearity,negbinirr) S3method(check_collinearity,negbinmfx) S3method(check_collinearity,poissonirr) S3method(check_collinearity,poissonmfx) S3method(check_collinearity,probitmfx) S3method(check_collinearity,zerocount) S3method(check_collinearity,zeroinfl) S3method(check_concurvity,gam) S3method(check_convergence,"_glm") S3method(check_convergence,default) S3method(check_convergence,glmmTMB) S3method(check_convergence,merMod) S3method(check_distribution,default) S3method(check_distribution,numeric) S3method(check_heteroscedasticity,default) S3method(check_homogeneity,afex_aov) S3method(check_homogeneity,default) S3method(check_homogeneity,htest) S3method(check_model,DHARMa) S3method(check_model,brmsfit) S3method(check_model,default) S3method(check_model,model_fit) S3method(check_model,performance_simres) S3method(check_model,stanreg) S3method(check_multimodal,data.frame) S3method(check_multimodal,numeric) S3method(check_normality,BFBayesFactor) S3method(check_normality,afex_aov) S3method(check_normality,default) S3method(check_normality,glm) S3method(check_normality,glmmTMB) S3method(check_normality,htest) S3method(check_normality,lmerModLmerTest) S3method(check_normality,merMod) S3method(check_normality,numeric) S3method(check_normality,performance_simres) S3method(check_outliers,BFBayesFactor) S3method(check_outliers,DHARMa) S3method(check_outliers,character) S3method(check_outliers,data.frame) S3method(check_outliers,default) S3method(check_outliers,fixest) S3method(check_outliers,fixest_multi) S3method(check_outliers,geeglm) S3method(check_outliers,glmmTMB) S3method(check_outliers,glmrob) S3method(check_outliers,gls) S3method(check_outliers,grouped_df) S3method(check_outliers,lme) S3method(check_outliers,lmrob) S3method(check_outliers,meta) S3method(check_outliers,metabin) S3method(check_outliers,metagen) S3method(check_outliers,numeric) S3method(check_outliers,performance_simres) S3method(check_outliers,rma) S3method(check_outliers,rma.uni) S3method(check_outliers,rq) S3method(check_outliers,rqs) S3method(check_outliers,rqss) S3method(check_overdispersion,DHARMa) S3method(check_overdispersion,default) S3method(check_overdispersion,fixest) S3method(check_overdispersion,fixest_multi) S3method(check_overdispersion,glm) S3method(check_overdispersion,glmmTMB) S3method(check_overdispersion,glmx) S3method(check_overdispersion,merMod) S3method(check_overdispersion,model_fit) S3method(check_overdispersion,negbin) S3method(check_overdispersion,negbinirr) S3method(check_overdispersion,negbinmfx) S3method(check_overdispersion,performance_simres) S3method(check_overdispersion,poissonirr) S3method(check_overdispersion,poissonmfx) S3method(check_predictions,BFBayesFactor) S3method(check_predictions,brmsfit) S3method(check_predictions,default) S3method(check_predictions,lme) S3method(check_predictions,stanreg) S3method(check_residuals,DHARMa) S3method(check_residuals,default) S3method(check_residuals,performance_simres) S3method(check_singularity,MixMod) S3method(check_singularity,clmm) S3method(check_singularity,cpglmm) S3method(check_singularity,default) S3method(check_singularity,glmmTMB) S3method(check_singularity,glmmadmb) S3method(check_singularity,lme) S3method(check_singularity,merMod) S3method(check_singularity,rlmerMod) S3method(check_sphericity,Anova.mlm) S3method(check_sphericity,afex_aov) S3method(check_sphericity,default) S3method(check_sphericity,mlm) S3method(check_symmetry,htest) S3method(check_symmetry,numeric) S3method(check_zeroinflation,DHARMa) S3method(check_zeroinflation,default) S3method(check_zeroinflation,performance_simres) S3method(cronbachs_alpha,data.frame) S3method(cronbachs_alpha,matrix) S3method(cronbachs_alpha,parameters_pca) S3method(display,check_itemscale) S3method(display,compare_performance) S3method(display,performance_model) S3method(display,test_performance) S3method(fitted,BFBayesFactor) S3method(format,compare_performance) S3method(format,performance_model) S3method(format,performance_rmse) S3method(format,test_performance) S3method(logLik,cpglm) S3method(logLik,iv_robust) S3method(logLik,ivreg) S3method(logLik,plm) S3method(logLik,svycoxph) S3method(model_performance,Arima) S3method(model_performance,BFBayesFactor) S3method(model_performance,DirichletRegModel) S3method(model_performance,MixMod) S3method(model_performance,bayesx) S3method(model_performance,betamfx) S3method(model_performance,betaor) S3method(model_performance,betareg) S3method(model_performance,bife) S3method(model_performance,blavaan) S3method(model_performance,brmsfit) S3method(model_performance,censReg) S3method(model_performance,clm) S3method(model_performance,clm2) S3method(model_performance,coxph) S3method(model_performance,coxph_weightit) S3method(model_performance,default) S3method(model_performance,felm) S3method(model_performance,fixest) S3method(model_performance,fixest_multi) S3method(model_performance,flexsurvreg) S3method(model_performance,glm) S3method(model_performance,glm_weightit) S3method(model_performance,glmmTMB) S3method(model_performance,glmmadmb) S3method(model_performance,glmx) S3method(model_performance,hurdle) S3method(model_performance,iv_robust) S3method(model_performance,ivreg) S3method(model_performance,kmeans) S3method(model_performance,lavaan) S3method(model_performance,lm) S3method(model_performance,lm_robust) S3method(model_performance,lme) S3method(model_performance,lmrob) S3method(model_performance,logitmfx) S3method(model_performance,logitor) S3method(model_performance,margins) S3method(model_performance,merMod) S3method(model_performance,mixed) S3method(model_performance,mixor) S3method(model_performance,mlogit) S3method(model_performance,model_fit) S3method(model_performance,multinom) S3method(model_performance,multinom_weightit) S3method(model_performance,negbinirr) S3method(model_performance,negbinmfx) S3method(model_performance,nestedLogit) S3method(model_performance,ordinal_weightit) S3method(model_performance,plm) S3method(model_performance,poissonirr) S3method(model_performance,poissonmfx) S3method(model_performance,polr) S3method(model_performance,probitmfx) S3method(model_performance,rlmerMod) S3method(model_performance,rma) S3method(model_performance,sem) S3method(model_performance,stanmvreg) S3method(model_performance,stanreg) S3method(model_performance,survreg) S3method(model_performance,svyglm) S3method(model_performance,truncreg) S3method(model_performance,vglm) S3method(model_performance,zeroinfl) S3method(model_performance,zerotrunc) S3method(performance_aic,bayesx) S3method(performance_aic,betamfx) S3method(performance_aic,betaor) S3method(performance_aic,default) S3method(performance_aic,lmerMod) S3method(performance_aic,logitmfx) S3method(performance_aic,logitor) S3method(performance_aic,negbinirr) S3method(performance_aic,negbinmfx) S3method(performance_aic,poissonirr) S3method(performance_aic,poissonmfx) S3method(performance_aic,probitmfx) S3method(performance_aic,svycoxph) S3method(performance_aic,svyglm) S3method(performance_aic,vgam) S3method(performance_aic,vglm) S3method(performance_aicc,Arima) S3method(performance_aicc,bife) S3method(performance_aicc,default) S3method(performance_aicc,lmerMod) S3method(performance_aicc,rma) S3method(performance_aicc,vglm) S3method(performance_logloss,brmsfit) S3method(performance_logloss,default) S3method(performance_logloss,logitmfx) S3method(performance_logloss,logitor) S3method(performance_logloss,probitmfx) S3method(performance_mae,betamfx) S3method(performance_mae,betaor) S3method(performance_mae,default) S3method(performance_mae,logitmfx) S3method(performance_mae,logitor) S3method(performance_mae,model_fit) S3method(performance_mae,negbinirr) S3method(performance_mae,negbinmfx) S3method(performance_mae,poissonirr) S3method(performance_mae,poissonmfx) S3method(performance_mae,probitmfx) S3method(performance_mse,betamfx) S3method(performance_mse,betaor) S3method(performance_mse,default) S3method(performance_mse,logitmfx) S3method(performance_mse,logitor) S3method(performance_mse,model_fit) S3method(performance_mse,negbinirr) S3method(performance_mse,negbinmfx) S3method(performance_mse,poissonirr) S3method(performance_mse,poissonmfx) S3method(performance_mse,probitmfx) S3method(plot,binned_residuals) S3method(plot,check_autocorrelation) S3method(plot,check_clusterstructure) S3method(plot,check_collinearity) S3method(plot,check_dag) S3method(plot,check_distribution) S3method(plot,check_distribution_numeric) S3method(plot,check_heteroscedasticity) S3method(plot,check_homogeneity) S3method(plot,check_model) S3method(plot,check_normality) S3method(plot,check_outliers) S3method(plot,check_overdisp) S3method(plot,check_residuals) S3method(plot,check_sphericity) S3method(plot,compare_performance) S3method(plot,performance_pp_check) S3method(plot,performance_roc) S3method(plot,performance_simres) S3method(plot,test_likelihoodratio) S3method(plot,test_performance) S3method(print,binned_residuals) S3method(print,check_autocorrelation) S3method(print,check_collinearity) S3method(print,check_concurvity) S3method(print,check_dag) S3method(print,check_distribution) S3method(print,check_distribution_numeric) S3method(print,check_heterogeneity_bias) S3method(print,check_heteroscedasticity) S3method(print,check_homogeneity) S3method(print,check_itemscale) S3method(print,check_model) S3method(print,check_normality) S3method(print,check_normality_binom) S3method(print,check_outliers) S3method(print,check_outliers_metafor) S3method(print,check_outliers_metagen) S3method(print,check_outliers_simres) S3method(print,check_overdisp) S3method(print,check_residuals) S3method(print,check_sphericity) S3method(print,check_symmetry) S3method(print,check_zi) S3method(print,compare_performance) S3method(print,icc) S3method(print,icc_by_group) S3method(print,icc_decomposed) S3method(print,item_difficulty) S3method(print,item_discrimination) S3method(print,looic) S3method(print,performance_accuracy) S3method(print,performance_cv) S3method(print,performance_hosmer) S3method(print,performance_model) S3method(print,performance_pcp) S3method(print,performance_pp_check) S3method(print,performance_rmse) S3method(print,performance_roc) S3method(print,performance_score) S3method(print,performance_simres) S3method(print,r2_bayes) S3method(print,r2_generic) S3method(print,r2_loo) S3method(print,r2_mlm) S3method(print,r2_nakagawa) S3method(print,r2_nakagawa_by_group) S3method(print,r2_pseudo) S3method(print,test_likelihoodratio) S3method(print,test_performance) S3method(print_html,check_itemscale) S3method(print_html,compare_performance) S3method(print_html,test_performance) S3method(print_md,check_itemscale) S3method(print_md,compare_performance) S3method(print_md,performance_model) S3method(print_md,test_performance) S3method(r2,Arima) S3method(r2,BBreg) S3method(r2,BFBayesFactor) S3method(r2,DirichletRegModel) S3method(r2,MixMod) S3method(r2,aov) S3method(r2,bayesx) S3method(r2,betamfx) S3method(r2,betaor) S3method(r2,betareg) S3method(r2,bife) S3method(r2,bigglm) S3method(r2,biglm) S3method(r2,bracl) S3method(r2,brmsfit) S3method(r2,brmultinom) S3method(r2,censReg) S3method(r2,clm) S3method(r2,clm2) S3method(r2,clmm) S3method(r2,complmrob) S3method(r2,coxph) S3method(r2,cpglm) S3method(r2,cpglmm) S3method(r2,cph) S3method(r2,crch) S3method(r2,default) S3method(r2,feis) S3method(r2,felm) S3method(r2,fixest) S3method(r2,fixest_multi) S3method(r2,gam) S3method(r2,glm) S3method(r2,glmmTMB) S3method(r2,glmmadmb) S3method(r2,glmx) S3method(r2,hurdle) S3method(r2,iv_robust) S3method(r2,ivreg) S3method(r2,lm) S3method(r2,lm_robust) S3method(r2,lme) S3method(r2,lmrob) S3method(r2,logitmfx) S3method(r2,logitor) S3method(r2,lrm) S3method(r2,mblogit) S3method(r2,mclogit) S3method(r2,merMod) S3method(r2,mhurdle) S3method(r2,mixed) S3method(r2,mlm) S3method(r2,mlogit) S3method(r2,mmclogit) S3method(r2,model_fit) S3method(r2,multinom) S3method(r2,negbinirr) S3method(r2,negbinmfx) S3method(r2,nestedLogit) S3method(r2,ols) S3method(r2,oohbchoice) S3method(r2,phylolm) S3method(r2,plm) S3method(r2,poissonirr) S3method(r2,poissonmfx) S3method(r2,polr) S3method(r2,probitmfx) S3method(r2,rlmerMod) S3method(r2,rma) S3method(r2,scam) S3method(r2,selection) S3method(r2,sem) S3method(r2,serp) S3method(r2,stanreg) S3method(r2,summary.lm) S3method(r2,survreg) S3method(r2,svyglm) S3method(r2,systemfit) S3method(r2,truncreg) S3method(r2,vgam) S3method(r2,vglm) S3method(r2,wbm) S3method(r2,zeroinfl) S3method(r2,zerotrunc) S3method(r2_coxsnell,BBreg) S3method(r2_coxsnell,DirichletRegModel) S3method(r2_coxsnell,bayesx) S3method(r2_coxsnell,bife) S3method(r2_coxsnell,censReg) S3method(r2_coxsnell,clm) S3method(r2_coxsnell,clm2) S3method(r2_coxsnell,coxph) S3method(r2_coxsnell,cpglm) S3method(r2_coxsnell,crch) S3method(r2_coxsnell,glm) S3method(r2_coxsnell,glmmTMB) S3method(r2_coxsnell,glmx) S3method(r2_coxsnell,logitmfx) S3method(r2_coxsnell,logitor) S3method(r2_coxsnell,mblogit) S3method(r2_coxsnell,mclogit) S3method(r2_coxsnell,multinom) S3method(r2_coxsnell,negbinirr) S3method(r2_coxsnell,negbinmfx) S3method(r2_coxsnell,nestedLogit) S3method(r2_coxsnell,poissonirr) S3method(r2_coxsnell,poissonmfx) S3method(r2_coxsnell,polr) S3method(r2_coxsnell,probit) S3method(r2_coxsnell,serp) S3method(r2_coxsnell,survreg) S3method(r2_coxsnell,svycoxph) S3method(r2_coxsnell,truncreg) S3method(r2_efron,default) S3method(r2_ferrari,default) S3method(r2_kullback,default) S3method(r2_kullback,glm) S3method(r2_loo_posterior,BFBayesFactor) S3method(r2_loo_posterior,brmsfit) S3method(r2_loo_posterior,stanmvreg) S3method(r2_loo_posterior,stanreg) S3method(r2_mcfadden,bracl) S3method(r2_mcfadden,brmultinom) S3method(r2_mcfadden,censReg) S3method(r2_mcfadden,clm) S3method(r2_mcfadden,clm2) S3method(r2_mcfadden,cpglm) S3method(r2_mcfadden,glm) S3method(r2_mcfadden,glmmTMB) S3method(r2_mcfadden,glmx) S3method(r2_mcfadden,logitmfx) S3method(r2_mcfadden,logitor) S3method(r2_mcfadden,mblogit) S3method(r2_mcfadden,mclogit) S3method(r2_mcfadden,mlogit) S3method(r2_mcfadden,multinom) S3method(r2_mcfadden,negbinirr) S3method(r2_mcfadden,negbinmfx) S3method(r2_mcfadden,poissonirr) S3method(r2_mcfadden,poissonmfx) S3method(r2_mcfadden,polr) S3method(r2_mcfadden,probitmfx) S3method(r2_mcfadden,serp) S3method(r2_mcfadden,truncreg) S3method(r2_mcfadden,vglm) S3method(r2_mckelvey,default) S3method(r2_mlm,mlm) S3method(r2_nagelkerke,BBreg) S3method(r2_nagelkerke,DirichletRegModel) S3method(r2_nagelkerke,bife) S3method(r2_nagelkerke,bracl) S3method(r2_nagelkerke,brmultinom) S3method(r2_nagelkerke,censReg) S3method(r2_nagelkerke,clm) S3method(r2_nagelkerke,clm2) S3method(r2_nagelkerke,coxph) S3method(r2_nagelkerke,cpglm) S3method(r2_nagelkerke,crch) S3method(r2_nagelkerke,glm) S3method(r2_nagelkerke,glmmTMB) S3method(r2_nagelkerke,glmx) S3method(r2_nagelkerke,logitmfx) S3method(r2_nagelkerke,logitor) S3method(r2_nagelkerke,mblogit) S3method(r2_nagelkerke,mclogit) S3method(r2_nagelkerke,multinom) S3method(r2_nagelkerke,negbinirr) S3method(r2_nagelkerke,negbinmfx) S3method(r2_nagelkerke,nestedLogit) S3method(r2_nagelkerke,poissonirr) S3method(r2_nagelkerke,poissonmfx) S3method(r2_nagelkerke,polr) S3method(r2_nagelkerke,probitmfx) S3method(r2_nagelkerke,serp) S3method(r2_nagelkerke,survreg) S3method(r2_nagelkerke,svycoxph) S3method(r2_nagelkerke,truncreg) S3method(r2_posterior,BFBayesFactor) S3method(r2_posterior,brmsfit) S3method(r2_posterior,stanmvreg) S3method(r2_posterior,stanreg) S3method(r2_tjur,default) S3method(r2_tjur,nestedLogit) S3method(residuals,BFBayesFactor) S3method(residuals,check_normality_numeric) S3method(residuals,iv_robust) S3method(residuals,performance_simres) S3method(rstudent,check_normality_numeric) S3method(test_bf,ListModels) S3method(test_bf,default) S3method(test_likelihoodratio,ListNestedRegressions) S3method(test_likelihoodratio,default) S3method(test_performance,ListNestedRegressions) S3method(test_performance,ListNonNestedRegressions) S3method(test_performance,default) S3method(test_vuong,ListNestedRegressions) S3method(test_vuong,ListNonNestedRegressions) S3method(test_vuong,default) S3method(test_wald,ListNestedRegressions) S3method(test_wald,ListNonNestedRegressions) S3method(test_wald,default) export(as.dag) export(binned_residuals) export(check_autocorrelation) export(check_clusterstructure) export(check_collinearity) export(check_concurvity) export(check_convergence) export(check_dag) export(check_distribution) export(check_factorstructure) export(check_heterogeneity_bias) export(check_heteroscedasticity) export(check_heteroskedasticity) export(check_homogeneity) export(check_itemscale) export(check_kmo) export(check_model) export(check_multimodal) export(check_normality) export(check_outliers) export(check_overdispersion) export(check_predictions) export(check_residuals) export(check_singularity) export(check_sphericity) export(check_sphericity_bartlett) export(check_symmetry) export(check_zeroinflation) export(compare_performance) export(cronbachs_alpha) export(display) export(icc) export(item_difficulty) export(item_discrimination) export(item_intercor) export(item_reliability) export(item_split_half) export(looic) export(mae) export(model_performance) export(mse) export(multicollinearity) export(performance) export(performance_accuracy) export(performance_aic) export(performance_aicc) export(performance_cv) export(performance_hosmer) export(performance_logloss) export(performance_mae) export(performance_mse) export(performance_pcp) export(performance_rmse) export(performance_roc) export(performance_rse) export(performance_score) export(print_html) export(print_md) export(r2) export(r2_bayes) export(r2_coxsnell) export(r2_efron) export(r2_ferrari) export(r2_kullback) export(r2_loo) export(r2_loo_posterior) export(r2_mcfadden) export(r2_mckelvey) export(r2_mlm) export(r2_nagelkerke) export(r2_nakagawa) export(r2_posterior) export(r2_somers) export(r2_tjur) export(r2_xu) export(r2_zeroinflated) export(rmse) export(simulate_residuals) export(test_bf) export(test_likelihoodratio) export(test_lrt) export(test_performance) export(test_vuong) export(test_wald) export(variance_decomposition) importFrom(insight,display) importFrom(insight,print_html) importFrom(insight,print_md) importFrom(stats,residuals) importFrom(stats,rstudent) performance/NEWS.md0000644000176200001440000007765314741710712013677 0ustar liggesusers# performance 0.13.0 ## Breaking changes * `check_outliers()` with `method = "optics"` now returns a further refined cluster selection, by passing the `optics_xi` argument to `dbscan::extractXi()`. * Deprecated arguments and alias-function-names have been removed. * Argument names in `check_model()` that refer to plot-aesthetics (like `dot_size`) are now harmonized across *easystats* packages, meaning that these have been renamed. They now follow the pattern `aesthetic_type`, e.g. `size_dot` (instead of `dot_size`). ## Changes * Increased accuracy for `check_convergence()` for *glmmTMB* models. * `r2()` and `r2_mcfadden()` now support beta-binomial (non-mixed) models from package *glmmTMB*. * An `as.numeric()` resp. `as.double()` method for objects of class `performance_roc` was added. * Improved documentation for `performance_roc()`. ## Bug fixes * `check_outliers()` did not warn that no numeric variables were found when only the response variable was numeric, but all relevant predictors were not. * `check_collinearity()` did not work for glmmTMB models when zero-inflation component was set to `~0`. # performance 0.12.4 ## Changes * `check_dag()` now also checks for colliders, and suggests removing it in the printed output. * Minor revisions to the printed output of `check_dag()`. ## Bug fixes * Fixed failing tests that broke due to changes in latest *glmmTMB* update. # performance 0.12.3 ## New functions * `check_dag()`, to check DAGs for correct adjustment sets. ## Changes * `check_heterogeneity_bias()` gets a `nested` argument. Furthermore, `by` can specify more than one variable, meaning that nested or cross-classified model designs can also be tested for heterogeneity bias. # performance 0.12.2 Patch release, to ensure that _performance_ runs with older version of _datawizard_ on Mac OSX with R (old-release). # performance 0.12.1 ## General * `icc()` and `r2_nakagawa()` get a `null_model` argument. This can be useful when computing R2 or ICC for mixed models, where the internal computation of the null model fails, or when you already have fit the null model and want to save time. * `icc()` and `r2_nakagawa()` get a `approximation` argument indicating the approximation method for the distribution-specific (residual) variance. See Nakagawa et al. 2017 for details. * `icc()` and `r2_nakagawa()` get a `model_component` argument indicating the component for zero-inflation or hurdle models. * `performance_rmse()` (resp. `rmse()`) can now compute analytical and bootstrapped confidence intervals. The function gains following new arguments: `ci`, `ci_method` and `iterations`. * New function `r2_ferrari()` to compute Ferrari & Cribari-Neto's R2 for generalized linear models, in particular beta-regression. * Improved documentation of some functions. ## Bug fixes * Fixed issue in `check_model()` when model contained a transformed response variable that was named like a valid R function name (e.g., `lm(log(lapply) ~ x)`, when data contained a variable named `lapply`). * Fixed issue in `check_predictions()` for linear models when response was transformed as ratio (e.g. `lm(succes/trials ~ x)`). * Fixed issue in `r2_bayes()` for mixed models from *rstanarm*. # performance 0.12.0 ## Breaking * Aliases `posterior_predictive_check()` and `check_posterior_predictions()` for `check_predictions()` are deprecated. * Arguments named `group` or `group_by` will be deprecated in a future release. Please use `by` instead. This affects `check_heterogeneity_bias()` in *performance*. ## General * Improved documentation and new vignettes added. * `check_model()` gets a `base_size` argument, to set the base font size for plots. * `check_predictions()` for `stanreg` and `brmsfit` models now returns plots in the usual style as for other models and no longer returns plots from `bayesplot::pp_check()`. * Updated the trained model that is used to prediction distributions in `check_distribution()`. ## Bug fixes * `check_model()` now falls back on normal Q-Q plots when a model is not supported by the DHARMa package and simulated residuals cannot be calculated. # performance 0.11.0 ## New supported models * Rudimentary support for models of class `serp` from package *serp*. ## New functions * `simulate_residuals()` and `check_residuals()`, to simulate and check residuals from generalized linear (mixed) models. Simulating residuals is based on the DHARMa package, and objects returned by `simulate_residuals()` inherit from the `DHARMa` class, and thus can be used with any functions from the *DHARMa* package. However, there are also implementations in the *performance* package, such as `check_overdispersion()`, `check_zeroinflation()`, `check_outliers()` or `check_model()`. * Plots for `check_model()` have been improved. The Q-Q plots are now based on simulated residuals from the DHARMa package for non-Gaussian models, thus providing more accurate and informative plots. The half-normal QQ plot for generalized linear models can still be obtained by setting the new argument `residual_type = "normal"`. * Following functions now support simulated residuals (from `simulate_residuals()`) resp. objects returned from `DHARMa::simulateResiduals()`: - `check_overdispersion()` - `check_zeroinflation()` - `check_outliers()` - `check_model()` ## General * Improved error messages for `check_model()` when QQ-plots cannot be created. * `check_distribution()` is more stable for possibly sparse data. ## Bug fixes * Fixed issue in `check_normality()` for t-tests. * Fixed issue in `check_itemscale()` for data frame inputs, when `factor_index` was not a named vector. # performance 0.10.9 ## Changes * `r2()` for models of class `glmmTMB` without random effects now returns the correct r-squared value for non-mixed models. * `check_itemscale()` now also accepts data frames as input. In this case, `factor_index` must be specified, which must be a numeric vector of same length as number of columns in `x`, where each element is the index of the factor to which the respective column in `x`. * `check_itemscale()` gets a `print_html()` method. * Clarification in the documentation of the `estimator` argument for `performance_aic()`. * Improved plots for overdispersion-checks for negative-binomial models from package *glmmTMB* (affects `check_overdispersion()` and `check_model()`). * Improved detection rates for singularity in `check_singularity()` for models from package *glmmTMB*. * For model of class `glmmTMB`, deviance residuals are now used in the `check_model()` plot. * Improved (better to understand) error messages for `check_model()`, `check_collinearity()` and `check_outliers()` for models with non-numeric response variables. * `r2_kullback()` now gives an informative error for non-supported models. ## Bug fixes * Fixed issue in `binned_residuals()` for models with binary outcome, where in rare occasions empty bins could occur. * `performance_score()` should no longer fail for models where scoring rules can't be calculated. Instead, an informative message is returned. * `check_outliers()` now properly accept the `percentage_central` argument when using the `"mcd"` method. * Fixed edge cases in `check_collinearity()` and `check_outliers()` for models with response variables of classes `Date`, `POSIXct`, `POSIXlt` or `difftime`. * Fixed issue with `check_model()` for models of package *quantreg*. # performance 0.10.8 ## Changes * Changed behaviour of `check_predictions()` for models from binomial family, to get comparable plots for different ways of outcome specification. Now, if the outcome is a proportion, or defined as matrix of trials and successes, the produced plots are the same (because the models should be the same, too). ## Bug fixes * Fixed CRAN check errors. * Fixed issue with `binned_residuals()` for models with binomial family, where the outcome was a proportion. # performance 0.10.7 ## Breaking changes * `binned_residuals()` gains a few new arguments to control the residuals used for the test, as well as different options to calculate confidence intervals (namely, `ci_type`, `residuals`, `ci` and `iterations`). The default values to compute binned residuals have changed. Default residuals are now "deviance" residuals (and no longer "response" residuals). Default confidence intervals are now "exact" intervals (and no longer based on Gaussian approximation). Use `ci_type = "gaussian"` and `residuals = "response"` to get the old defaults. ## Changes to functions * `binned_residuals()` - like `check_model()` - gains a `show_dots` argument to show or hide data points that lie inside error bounds. This is particular useful for models with many observations, where generating the plot would be very slow. # performance 0.10.6 ## General * Support for `nestedLogit` models. ## Changes to functions * `check_outliers()` for method `"ics"` now detects number of available cores for parallel computing via the `"mc.cores"` option. This is more robust than the previous method, which used `parallel::detectCores()`. Now you should set the number of cores via `options(mc.cores = 4)`. ## Bug fixes * Fixed issues is `check_model()` for models that used data sets with variables of class `"haven_labelled"`. # performance 0.10.5 ## Changes to functions * More informative message for `test_*()` functions that "nesting" only refers to fixed effects parameters and currently ignores random effects when detecting nested models. * `check_outliers()` for `"ICS"` method is now more stable and less likely to fail. * `check_convergence()` now works for *parsnip* `_glm` models. ## Bug fixes * `check_collinearity()` did not work for hurdle- or zero-inflated models of package *pscl* when model had no explicitly defined formula for the zero-inflation model. # performance 0.10.4 ## Changes to functions * `icc()` and `r2_nakagawa()` gain a `ci_method` argument, to either calculate confidence intervals using `boot::boot()` (instead of `lmer::bootMer()`) when `ci_method = "boot"` or analytical confidence intervals (`ci_method = "analytical"`). Use `ci_method = "boot"` when the default method fails to compute confidence intervals and use `ci_method = "analytical"` if bootstrapped intervals cannot be calculated at all. Note that the default computation method is preferred. * `check_predictions()` accepts a `bandwidth` argument (smoothing bandwidth), which is passed down to the `plot()` methods density-estimation. * `check_predictions()` gains a `type` argument, which is passed down to the `plot()` method to change plot-type (density or discrete dots/intervals). By default, `type` is set to `"default"` for models without discrete outcomes, and else `type = "discrete_interval"`. * `performance_accuracy()` now includes confidence intervals, and reports those by default (the standard error is no longer reported, but still included). ## Bug fixes * Fixed issue in `check_collinearity()` for _fixest_ models that used `i()` to create interactions in formulas. # performance 0.10.3 ## New functions * `item_discrimination()`, to calculate the discrimination of a scale's items. ## Support for new models * `model_performance()`, `check_overdispersion()`, `check_outliers()` and `r2()` now work with objects of class `fixest_multi` (@etiennebacher, #554). * `model_performance()` can now return the "Weak instruments" statistic and p-value for models of class `ivreg` with `metrics = "weak_instruments"` (@etiennebacher, #560). * Support for `mclogit` models. ## Changes to functions * `test_*()` functions now automatically fit a null-model when only one model objects was provided for testing multiple models. * Warnings in `model_performance()` for unsupported objects of class `BFBayesFactor` can now be suppressed with `verbose = FALSE`. * `check_predictions()` no longer fails with issues when `re_formula = NULL` for mixed models, but instead gives a warning and tries to compute posterior predictive checks with `re_formuka = NA`. * `check_outliers()` now also works for meta-analysis models from packages *metafor* and *meta*. * `plot()` for `performance::check_model()` no longer produces a normal QQ plot for GLMs. Instead, it now shows a half-normal QQ plot of the absolute value of the standardized deviance residuals. ## Bug fixes * Fixed issue in `print()` method for `check_collinearity()`, which could mix up the correct order of parameters. # performance 0.10.2 ## General * Revised usage of `insight::get_data()` to meet forthcoming changes in the _insight_ package. ## Changes to functions * `check_collinearity()` now accepts `NULL` for the `ci` argument. ## Bug fixes * Fixed issue in `item_difficulty()` with detecting the maximum values of an item set. Furthermore, `item_difficulty()` gets a `maximum_value` argument in case no item contains the maximum value due to missings. # performance 0.10.1 ## General * Minor improvements to the documentation. ## Changes to functions * `icc()` and `r2_nakagawa()` get `ci` and `iterations` arguments, to compute confidence intervals for the ICC resp. R2, based on bootstrapped sampling. * `r2()` gets `ci`, to compute (analytical) confidence intervals for the R2. * The model underlying `check_distribution()` was now also trained to detect cauchy, half-cauchy and inverse-gamma distributions. * `model_performance()` now allows to include the ICC for Bayesian models. ## Bug fixes * `verbose` didn't work for `r2_bayes()` with `BFBayesFactor` objects. * Fixed issues in `check_model()` for models with convergence issues that lead to `NA` values in residuals. * Fixed bug in `check_outliers` whereby passing multiple elements to the threshold list generated an error (#496). * `test_wald()` now warns the user about inappropriate F test and calls `test_likelihoodratio()` for binomial models. * Fixed edge case for usage of `parellel::detectCores()` in `check_outliers()`. # performance 0.10.0 ## Breaking Change * The minimum needed R version has been bumped to `3.6`. * The alias `performance_lrt()` was removed. Use `test_lrt()` resp. `test_likelihoodratio()`. ## New functions * Following functions were moved from package *parameters* to *performance*: `check_sphericity_bartlett()`, `check_kmo()`, `check_factorstructure()` and `check_clusterstructure()`. ## Changes to functions * `check_normality()`, `check_homogeneity()` and `check_symmetry()` now works for `htest` objects. * Print method for `check_outliers()` changed significantly: now states the methods, thresholds, and variables used, reports outliers per variable (for univariate methods) as well as any observation flagged for several variables/methods. Includes a new optional ID argument to add along the row number in the output (@rempsyc #443). * `check_outliers()` now uses more conventional outlier thresholds. The `IQR` and confidence interval methods now gain improved distance scores that are continuous instead of discrete. ## Bug Fixes * Fixed wrong *z*-score values when using a vector instead of a data frame in `check_outliers()` (#476). * Fixed `cronbachs_alpha()` for objects from `parameters::principal_component()`. # performance 0.9.2 ## General * `print()` methods for `model_performance()` and `compare_performance()` get a `layout` argument, which can be `"horizontal"` (default) or `"vertical"`, to switch the layout of the printed table. * Improved speed performance for `check_model()` and some other `performance_*()` functions. * Improved support for models of class `geeglm`. ## Changes to functions * `check_model()` gains a `show_dots` argument, to show or hide data points. This is particular useful for models with many observations, where generating the plot would be very slow. ## Bug Fixes * Fixes wrong column names in `model_performance()` output for `kmeans` objects (#453) # performance 0.9.1 ## Breaking * The formerly "conditional" ICC in `icc()` is now named "unadjusted" ICC. ## New functions * `performance_cv()` for cross-validated model performance. ## Support for new models * Added support for models from package *estimator*. ## Changes to functions * `check_overdispersion()` gets a `plot()` method. * `check_outliers()` now also works for models of classes `gls` and `lme`. As a consequence, `check_model()` will no longer fail for these models. * `check_collinearity()` now includes the confidence intervals for the VIFs and tolerance values. * `model_performance()` now also includes within-subject R2 measures, where applicable. * Improved handling of random effects in `check_normality()` (i.e. when argument `effects = "random"`). ## Bug fixes * `check_predictions()` did not work for GLMs with matrix-response. * `check_predictions()` did not work for logistic regression models (i.e. models with binary response) from package *glmmTMB* * `item_split_half()` did not work when the input data frame or matrix only contained two columns. * Fixed wrong computation of `BIC` in `model_performance()` when models had transformed response values. * Fixed issues in `check_model()` for GLMs with matrix-response. # performance 0.9.0 ## New functions * `check_concurvity()`, which returns GAM concurvity measures (comparable to collinearity checks). ## Changes to functions ### Check functions * `check_predictions()`, `check_collinearity()` and `check_outliers()` now support (mixed) regression models from `BayesFactor`. * `check_zeroinflation()` now also works for `lme4::glmer.nb()` models. * `check_collinearity()` better supports GAM models. ### Test functions * `test_performance()` now calls `test_lrt()` or `test_wald()` instead of `test_vuong()` when package *CompQuadForm* is missing. * `test_performance()` and `test_lrt()` now compute the corrected log-likelihood when models with transformed response variables (such as log- or sqrt-transformations) are passed to the functions. ### Model performance functions * `performance_aic()` now corrects the AIC value for models with transformed response variables. This also means that comparing models using `compare_performance()` allows comparisons of AIC values for models with and without transformed response variables. * Also, `model_performance()` now corrects both AIC and BIC values for models with transformed response variables. ### Plotting and printing * The `print()` method for `binned_residuals()` now prints a short summary of the results (and no longer generates a plot). A `plot()` method was added to generate plots. * The `plot()` output for `check_model()` was revised: - For binomial models, the constant variance plot was omitted, and a binned residuals plot included. - The density-plot that showed normality of residuals was replaced by the posterior predictive check plot. ## Bug fixes * `model_performance()` for models from *lme4* did not report AICc when requested. * `r2_nakagawa()` messed up order of group levels when `by_group` was `TRUE`. # performance 0.8.0 ## Breaking Changes * The `ci`-level in `r2()` for Bayesian models now defaults to `0.95`, to be in line with the latest changes in the *bayestestR* package. * S3-method dispatch for `pp_check()` was revised, to avoid problems with the _bayesplot_ package, where the generic is located. ## General * Minor revisions to wording for messages from some of the check-functions. * `posterior_predictive_check()` and `check_predictions()` were added as aliases for `pp_check()`. ## New functions * `check_multimodal()` and `check_heterogeneity_bias()`. These functions will be removed from the _parameters_ packages in the future. ## Changes to functions * `r2()` for linear models can now compute confidence intervals, via the `ci` argument. ## Bug fixes * Fixed issues in `check_model()` for Bayesian models. * Fixed issue in `pp_check()` for models with transformed response variables, so now predictions and observed response values are on the same (transformed) scale. # performance 0.7.3 ## Changes to functions * `check_outliers()` has new `ci` (or `hdi`, `eti`) method to filter based on Confidence/Credible intervals. * `compare_performance()` now also accepts a list of model objects. * `performance_roc()` now also works for binomial models from other classes than *glm*. * Several functions, like `icc()` or `r2_nakagawa()`, now have an `as.data.frame()` method. * `check_collinearity()` now correctly handles objects from forthcoming *afex* update. # performance 0.7.2 ## New functions * `performance_mae()` to calculate the mean absolute error. ## Bug fixes * Fixed issue with `"data length differs from size of matrix"` warnings in examples in forthcoming R 4.2. * Fixed issue in `check_normality()` for models with sample size larger than 5.000 observations. * Fixed issue in `check_model()` for *glmmTMB* models. * Fixed issue in `check_collinearity()` for *glmmTMB* models with zero-inflation, where the zero-inflated model was an intercept-only model. # performance 0.7.1 ## New supported models * Add support for `model_fit` (*tidymodels*). * `model_performance` supports *kmeans* models. ## General * Give more informative warning when `r2_bayes()` for *BFBayesFactor* objects can't be calculated. * Several `check_*()` functions now return informative messages for invalid model types as input. * `r2()` supports `mhurdle` (*mhurdle*) models. * Added `print()` methods for more classes of `r2()`. * The `performance_roc()` and `performance_accuracy()` functions unfortunately had spelling mistakes in the output columns: *Sensitivity* was called *Sensivity* and *Specificity* was called *Specifity*. We think these are understandable mistakes :-) ## Changes to functions ### `check_model()` * `check_model()` gains more arguments, to customize plot appearance. * Added option to detrend QQ/PP plots in `check_model()`. ### `model_performance()` * The `metrics` argument from `model_performance()` and `compare_performance()` gains a `"AICc"` option, to also compute the 2nd order AIC. * `"R2_adj"` is now an explicit option in the `metrics` argument from `model_performance()` and `compare_performance()`. ### Other functions * The default-method for `r2()` now tries to compute an r-squared for all models that have no specific `r2()`-method yet, by using following formula: `1-sum((y-y_hat)^2)/sum((y-y_bar)^2))` * The column name `Parameter` in `check_collinearity()` is now more appropriately named `Term`. ## Bug fixes * `test_likelihoodratio()` now correctly sorts models with identical fixed effects part, but different other model parts (like zero-inflation). * Fixed incorrect computation of models from inverse-Gaussian families, or Gaussian families fitted with `glm()`. * Fixed issue in `performance_roc()` for models where outcome was not 0/1 coded. * Fixed issue in `performance_accuracy()` for logistic regression models when `method = "boot"`. * `cronbachs_alpha()` did not work for `matrix`-objects, as stated in the docs. It now does. # performance 0.7.0 ## General * Roll-back R dependency to R >= 3.4. ## Breaking Changes * `compare_performance()` doesn't return the models' Bayes Factors, now returned by `test_performance()` and `test_bf()`. ## New functions to test or compare models * `test_vuong()`, to compare models using Vuong's (1989) Test. * `test_bf()`, to compare models using Bayes factors. * `test_likelihoodratio()` as an alias for `performance_lrt()`. * `test_wald()`, as a rough approximation for the LRT. * `test_performance()`, to run the most relevant and appropriate tests based on the input. ## Changes to functions ### `performance_lrt()` * `performance_lrt()` get an alias `test_likelihoodratio()`. * Does not return AIC/BIC now (as they are not related to LRT *per se* and can be easily obtained with other functions). * Now contains a column with the difference in degrees of freedom between models. * Fixed column names for consistency. ### `model_performance()` * Added more diagnostics to models of class `ivreg`. ### Other functions * Revised computation of `performance_mse()`, to ensure that it's always based on response residuals. * `performance_aic()` is now more robust. ## Bug fixes * Fixed issue in `icc()` and `variance_decomposition()` for multivariate response models, where not all model parts contained random effects. * Fixed issue in `compare_performance()` with duplicated rows. * `check_collinearity()` no longer breaks for models with rank deficient model matrix, but gives a warning instead. * Fixed issue in `check_homogeneity()` for `method = "auto"`, which wrongly tested the response variable, not the residuals. * Fixed issue in `check_homogeneity()` for edge cases where predictor had non-syntactic names. # performance 0.6.1 ## General * `check_collinearity()` gains a `verbose` argument, to toggle warnings and messages. ## Bug fixes * Fixed examples, now using suggested packages only conditionally. # performance 0.6.0 ## General * `model_performance()` now supports `margins`, `gamlss`, `stanmvreg` and `semLme`. ## New functions * `r2_somers()`, to compute Somers' Dxy rank-correlation as R2-measure for logistic regression models. * `display()`, to print output from package-functions into different formats. `print_md()` is an alias for `display(format = "markdown")`. ## Changes to functions ### `model_performance()` * `model_performance()` is now more robust and doesn't fail if an index could not be computed. Instead, it returns all indices that were possible to calculate. * `model_performance()` gains a default-method that catches all model objects not previously supported. If model object is also not supported by the default-method, a warning is given. * `model_performance()` for metafor-models now includes the degrees of freedom for Cochran's Q. ### Other functions * `performance_mse()` and `performance_rmse()` now always try to return the (R)MSE on the response scale. * `performance_accuracy()` now accepts all types of linear or logistic regression models, even if these are not of class `lm` or `glm`. * `performance_roc()` now accepts all types of logistic regression models, even if these are not of class `glm`. * `r2()` for mixed models and `r2_nakagawa()` gain a `tolerance`-argument, to set the tolerance level for singularity checks when computing random effect variances for the conditional r-squared. ## Bug fixes * Fixed issue in `icc()` introduced in the last update that make `lme`-models fail. * Fixed issue in `performance_roc()` for models with factors as response. # performance 0.5.1 ## Breaking changes * Column names for `model_performance()` and `compare_performance()` were changed to be in line with the _easystats_ naming convention: `LOGLOSS` is now `Log_loss`, `SCORE_LOG` is `Score_log` and `SCORE_SPHERICAL` is now `Score_spherical`. ## New functions * `r2_posterior()` for Bayesian models to obtain posterior distributions of R-squared. ## Changes to functions * `r2_bayes()` works with Bayesian models from `BayesFactor` ( #143 ). * `model_performance()` works with Bayesian models from `BayesFactor` ( #150 ). * `model_performance()` now also includes the residual standard deviation. * Improved formatting for Bayes factors in `compare_performance()`. * `compare_performance()` with `rank = TRUE` doesn't use the `BF` values when `BIC` are present, to prevent "double-dipping" of the BIC values (#144). * The `method` argument in `check_homogeneity()` gains a `"levene"` option, to use Levene's Test for homogeneity. ## Bug fixes * Fix bug in `compare_performance()` when `...` arguments were function calls to regression objects, instead of direct function calls. # performance 0.5.0 ## General * `r2()` and `icc()` support `semLME` models (package *smicd*). * `check_heteroscedasticity()` should now also work with zero-inflated mixed models from *glmmTMB* and *GLMMadpative*. * `check_outliers()` now returns a logical vector. Original numerical vector is still accessible via `as.numeric()`. ## New functions * `pp_check()` to compute posterior predictive checks for frequentist models. ## Bug fixes * Fixed issue with incorrect labeling of groups from `icc()` when `by_group = TRUE`. * Fixed issue in `check_heteroscedasticity()` for mixed models where sigma could not be calculated in a straightforward way. * Fixed issues in `check_zeroinflation()` for `MASS::glm.nb()`. * Fixed CRAN check issues. # performance 0.4.8 ## General * Removed suggested packages that have been removed from CRAN. ## Changes to functions * `icc()` now also computes a "classical" ICC for `brmsfit` models. The former way of calculating an "ICC" for `brmsfit` models is now available as new function called `variance_decomposition()`. ## Bug fixes * Fix issue with new version of *bigutilsr* for `check_outliers()`. * Fix issue with model order in `performance_lrt()`. # performance 0.4.7 ## General * Support for models from package *mfx*. ## Changes to functions * `model_performance.rma()` now includes results from heterogeneity test for meta-analysis objects. * `check_normality()` now also works for mixed models (with the limitation that studentized residuals are used). * `check_normality()` gets an `effects`-argument for mixed models, to check random effects for normality. ## Bug fixes * Fixed issue in `performance_accuracy()` for binomial models when response variable had non-numeric factor levels. * Fixed issues in `performance_roc()`, which printed 1 - AUC instead of AUC. # performance 0.4.6 ## General * Minor revisions to `model_performance()` to meet changes in *mlogit* package. * Support for `bayesx` models. ## Changes to functions * `icc()` gains a `by_group` argument, to compute ICCs per different group factors in mixed models with multiple levels or cross-classified design. * `r2_nakagawa()` gains a `by_group` argument, to compute explained variance at different levels (following the variance-reduction approach by Hox 2010). * `performance_lrt()` now works on *lavaan* objects. ## Bug fixes * Fix issues in some functions for models with logical dependent variable. * Fix bug in `check_itemscale()`, which caused multiple computations of skewness statistics. * Fix issues in `r2()` for *gam* models. # performance 0.4.5 ## General * `model_performance()` and `r2()` now support *rma*-objects from package *metafor*, *mlm* and *bife* models. ## Changes to functions * `compare_performance()` gets a `bayesfactor` argument, to include or exclude the Bayes factor for model comparisons in the output. * Added `r2.aov()`. ## Bug fixes * Fixed issue in `performance_aic()` for models from package *survey*, which returned three different AIC values. Now only the AIC value is returned. * Fixed issue in `check_collinearity()` for *glmmTMB* models when zero-inflated formula only had one predictor. * Fixed issue in `check_model()` for *lme* models. * Fixed issue in `check_distribution()` for *brmsfit* models. * Fixed issue in `check_heteroscedasticity()` for *aov* objects. * Fixed issues for *lmrob* and *glmrob* objects. performance/inst/0000755000176200001440000000000014666017356013546 5ustar liggesusersperformance/inst/CITATION0000644000176200001440000000122614257537777014716 0ustar liggesusersbibentry( "Article", title = "{performance}: An {R} Package for Assessment, Comparison and Testing of Statistical Models", author = c(person("Daniel", "Lüdecke"), person("Mattan S.", "Ben-Shachar"), person("Indrajeet", "Patil"), person("Philip", "Waggoner"), person("Dominique", "Makowski")), year = 2021, journal = "Journal of Open Source Software", volume = 6, number = 60, pages = 3139, doi = "10.21105/joss.03139", textVersion = "Lüdecke et al., (2021). performance: An R Package for Assessment, Comparison and Testing of Statistical Models. Journal of Open Source Software, 6(60), 3139. https://doi.org/10.21105/joss.03139" )performance/inst/WORDLIST0000644000176200001440000000640014666017356014740 0ustar liggesusersACM AGFI AICc Agresti Akademiai Alonso Ameijeiras Ankerst Archimbaud Arel Asq Azen BCI BFBayesFactor BMJ Baayen BayesFactor Benthem Betancourt Bezdek Biometrics Biometrika Bolker Bollen Bollen's Bortz Breunig Breusch BRM Bryk Budescu Bundock Burnham Byrne CFA CFI CRC Carvalho Casal Chisq CochransQ CompQuadForm Concurvity Confounder Cramer Cribari Cronbach's Crujeiras Csaki DAGs DBSCAN DOI Datenerhebung De Delacre Deskriptivstatistische DHARMa Distinguishability Dom Dominicy Dordrecht Dorie Dunson Durbin Dxy Döring ELPD EQS Econometrica Efron Efron's Elphick Erlbaum Fligner Forschungsmethoden Fragebogenkonstruktion Francoeur GFI GL GLMM GLMMadaptive GLMMadpative GLMMs Gabry Gazen Gelman Gnanadesikan Guilford Hartig HDI HJ Hastie Herron Hesketh Hoaglin Hoboken Holger Hosmer Hotelling Hox Hurvich IC ICCs ICS ICSOutlier IFI IJCNN Ieno Iglewicz Intra Intraclass Itemanalyse JB JM Jackman Jurs KJ KMO Kelava Kettenring Kiado Killeen Kliegl Kristensen Kullback LOF LOGLOSS LOOIC Lakens Laniado Leibler Lemeshow Levene's Ley Leys Lillo Liu Lohse Lomax MADs MSA Maddala Magee Magnusson Mahwah Marcoulides Mattan Matuschek McElreath McKelvey Merkle Methoden Michalos Moosbrugger Mora Multicollinearity MuMIn NFI NNFI Nagelkerke Nagelkerke's Nakagawa Nakagawa's Neto Neto's Nondegenerate Nordhausen Normed Nicewander ORCID OSF OSX Olkin PNFI Pek Petrov Postestimation Pre Psychol Psychometrika QE RFI RL RMR RMSEA Rabe Raudenbush Raykov Revelle Rodríguez Rohrer Rousseeuw Routledge SEM SRMR Scheepers Schielzeth Schielzeth’s Schumacker Sensivity Shachar Shinichi Skrondal Smyth Solomons Somers Specifity Sphericity Springer Stata Subscales TLI Technometrics Testtheorie Testwertbestimmung Tibshirani Tily Tjur Tjur's Tsai Tweedie VIF VIFs VPC Vanhove Vasishth Vehtari Verlag Visualisation Vuong Vuong's WAIC Weisberg Westreich Windmeijer Winsorization Witten Xu YL Zavoina Zavoinas Zhou Zomeren Zuur acyclic afex al analyse aov arXiv autocorrelated bartlett bayesplot bayestestR behaviour bife bigutilsr bmj bmwiernik brms brmsfit cauchy clusterable confounder confounders concurvity dagitty datawizard dbscan der detrend difficutly discriminations doi easystats et equidispersion explicitely favour fixest fpsyg gam geoms ggdag ggplot gjo glm glmmTMB glmrob grey heteroskedasticity homoscedasticity homoskedasticity https intra intraclass joss kmeans lavaan lm lme lmrob lmtest mattansb metafor mfx mhurdle mis misspecification misspecified mlm mlogit modelfit modelling models’ multicollinearity multimodel multiresponse multivariable nbinom nd nonnest overfitted patilindrajeets poisson preprint priori pscl quantreg quared quartile quartiles rOpenSci recoding reimplement rempsyc reproducibility rescaling rma rmarkdown rmse rsif rssa rstanarm se serp smicd sphericity strengejacke suboptimal subscale subscales theoreritcal tidymodels unadjusted und underfitted underfitting underdispersion visualisation winsorization winsorize winsorized xy youtube performance/README.md0000644000176200001440000004300114647434117014043 0ustar liggesusers # performance [![DOI](https://joss.theoj.org/papers/10.21105/joss.03139/status.svg)](https://doi.org/10.21105/joss.03139) [![downloads](http://cranlogs.r-pkg.org/badges/performance)](https://cran.r-project.org/package=performance) [![total](https://cranlogs.r-pkg.org/badges/grand-total/performance)](https://cranlogs.r-pkg.org/) ***Test if your model is a good model!*** A crucial aspect when building regression models is to evaluate the quality of modelfit. It is important to investigate how well models fit to the data and which fit indices to report. Functions to create diagnostic plots or to compute fit measures do exist, however, mostly spread over different packages. There is no unique and consistent approach to assess the model quality for different kind of models. The primary goal of the **performance** package is to fill this gap and to provide utilities for computing **indices of model quality** and **goodness of fit**. These include measures like r-squared (R2), root mean squared error (RMSE) or intraclass correlation coefficient (ICC) , but also functions to check (mixed) models for overdispersion, zero-inflation, convergence or singularity. ## Installation [![CRAN](http://www.r-pkg.org/badges/version/performance)](https://cran.r-project.org/package=performance) [![performance status badge](https://easystats.r-universe.dev/badges/performance)](https://easystats.r-universe.dev) [![R check](https://github.com/easystats/performance/workflows/R-CMD-check/badge.svg?branch=main)](https://github.com/easystats/performance/actions) The *performance* package is available on CRAN, while its latest development version is available on R-universe (from *rOpenSci*). | Type | Source | Command | |-------------|------------|-------------------------------------------------------------------------------| | Release | CRAN | `install.packages("performance")` | | Development | R-universe | `install.packages("performance", repos = "https://easystats.r-universe.dev")` | Once you have downloaded the package, you can then load it using: ``` r library("performance") ``` > **Tip** > > Instead of `library(performance)`, use `library(easystats)`. This will > make all features of the easystats-ecosystem available. > > To stay updated, use `easystats::install_latest()`. ## Citation To cite performance in publications use: ``` r citation("performance") #> To cite package 'performance' in publications use: #> #> Lüdecke et al., (2021). performance: An R Package for Assessment, Comparison and #> Testing of Statistical Models. Journal of Open Source Software, 6(60), 3139. #> https://doi.org/10.21105/joss.03139 #> #> A BibTeX entry for LaTeX users is #> #> @Article{, #> title = {{performance}: An {R} Package for Assessment, Comparison and Testing of Statistical Models}, #> author = {Daniel Lüdecke and Mattan S. Ben-Shachar and Indrajeet Patil and Philip Waggoner and Dominique Makowski}, #> year = {2021}, #> journal = {Journal of Open Source Software}, #> volume = {6}, #> number = {60}, #> pages = {3139}, #> doi = {10.21105/joss.03139}, #> } ``` ## Documentation There is a nice introduction into the package on [youtube](https://www.youtube.com/watch?v=EPIxQ5i5oxs). ## The *performance* workflow ### Assessing model quality #### R-squared **performance** has a generic `r2()` function, which computes the r-squared for many different models, including mixed effects and Bayesian regression models. `r2()` returns a list containing values related to the “most appropriate” r-squared for the given model. ``` r model <- lm(mpg ~ wt + cyl, data = mtcars) r2(model) #> # R2 for Linear Regression #> R2: 0.830 #> adj. R2: 0.819 model <- glm(am ~ wt + cyl, data = mtcars, family = binomial) r2(model) #> # R2 for Logistic Regression #> Tjur's R2: 0.705 library(MASS) data(housing) model <- polr(Sat ~ Infl + Type + Cont, weights = Freq, data = housing) r2(model) #> Nagelkerke's R2: 0.108 ``` The different R-squared measures can also be accessed directly via functions like `r2_bayes()`, `r2_coxsnell()` or `r2_nagelkerke()` (see a full list of functions [here](https://easystats.github.io/performance/reference/index.html#section-r-functions)). For mixed models, the *conditional* and *marginal* R-squared are returned. The *marginal R-squared* considers only the variance of the fixed effects and indicates how much of the model’s variance is explained by the fixed effects part only. The *conditional R-squared* takes both the fixed and random effects into account and indicates how much of the model’s variance is explained by the “complete” model. For frequentist mixed models, `r2()` (resp. `r2_nakagawa()`) computes the *mean* random effect variances, thus `r2()` is also appropriate for mixed models with more complex random effects structures, like random slopes or nested random effects (Johnson 2014; Nakagawa, Johnson, and Schielzeth 2017). ``` r set.seed(123) library(rstanarm) model <- stan_glmer( Petal.Length ~ Petal.Width + (1 | Species), data = iris, cores = 4 ) r2(model) #> # Bayesian R2 with Compatibility Interval #> #> Conditional R2: 0.954 (95% CI [0.951, 0.957]) #> Marginal R2: 0.414 (95% CI [0.204, 0.644]) library(lme4) model <- lmer(Reaction ~ Days + (1 + Days | Subject), data = sleepstudy) r2(model) #> # R2 for Mixed Models #> #> Conditional R2: 0.799 #> Marginal R2: 0.279 ``` #### Intraclass Correlation Coefficient (ICC) Similar to R-squared, the ICC provides information on the explained variance and can be interpreted as “the proportion of the variance explained by the grouping structure in the population” (Hox 2010). `icc()` calculates the ICC for various mixed model objects, including `stanreg` models. ``` r library(lme4) model <- lmer(Reaction ~ Days + (1 + Days | Subject), data = sleepstudy) icc(model) #> # Intraclass Correlation Coefficient #> #> Adjusted ICC: 0.722 #> Unadjusted ICC: 0.521 ``` …and models of class `brmsfit`. ``` r library(brms) set.seed(123) model <- brm(mpg ~ wt + (1 | cyl) + (1 + wt | gear), data = mtcars) ``` ``` r icc(model) #> # Intraclass Correlation Coefficient #> #> Adjusted ICC: 0.941 #> Unadjusted ICC: 0.779 ``` ### Model diagnostics #### Check for overdispersion Overdispersion occurs when the observed variance in the data is higher than the expected variance from the model assumption (for Poisson, variance roughly equals the mean of an outcome). `check_overdispersion()` checks if a count model (including mixed models) is overdispersed or not. ``` r library(glmmTMB) data(Salamanders) model <- glm(count ~ spp + mined, family = poisson, data = Salamanders) check_overdispersion(model) #> # Overdispersion test #> #> dispersion ratio = 2.946 #> Pearson's Chi-Squared = 1873.710 #> p-value = < 0.001 ``` Overdispersion can be fixed by either modelling the dispersion parameter (not possible with all packages), or by choosing a different distributional family (like Quasi-Poisson, or negative binomial, see (Gelman and Hill 2007)). #### Check for zero-inflation Zero-inflation (in (Quasi-)Poisson models) is indicated when the amount of observed zeros is larger than the amount of predicted zeros, so the model is *underfitting* zeros. In such cases, it is recommended to use negative binomial or zero-inflated models. Use `check_zeroinflation()` to check if zero-inflation is present in the fitted model. ``` r model <- glm(count ~ spp + mined, family = poisson, data = Salamanders) check_zeroinflation(model) #> # Check for zero-inflation #> #> Observed zeros: 387 #> Predicted zeros: 298 #> Ratio: 0.77 ``` #### Check for singular model fits A “singular” model fit means that some dimensions of the variance-covariance matrix have been estimated as exactly zero. This often occurs for mixed models with overly complex random effects structures. `check_singularity()` checks mixed models (of class `lme`, `merMod`, `glmmTMB` or `MixMod`) for singularity, and returns `TRUE` if the model fit is singular. ``` r library(lme4) data(sleepstudy) # prepare data set.seed(123) sleepstudy$mygrp <- sample(1:5, size = 180, replace = TRUE) sleepstudy$mysubgrp <- NA for (i in 1:5) { filter_group <- sleepstudy$mygrp == i sleepstudy$mysubgrp[filter_group] <- sample(1:30, size = sum(filter_group), replace = TRUE) } # fit strange model model <- lmer( Reaction ~ Days + (1 | mygrp / mysubgrp) + (1 | Subject), data = sleepstudy ) check_singularity(model) #> [1] TRUE ``` Remedies to cure issues with singular fits can be found [here](https://easystats.github.io/performance/reference/check_singularity.html). #### Check for heteroskedasticity Linear models assume constant error variance (homoskedasticity). The `check_heteroscedasticity()` functions assess if this assumption has been violated: ``` r data(cars) model <- lm(dist ~ speed, data = cars) check_heteroscedasticity(model) #> Warning: Heteroscedasticity (non-constant error variance) detected (p = 0.031). ``` #### Comprehensive visualization of model checks **performance** provides many functions to check model assumptions, like `check_collinearity()`, `check_normality()` or `check_heteroscedasticity()`. To get a comprehensive check, use `check_model()`. ``` r # defining a model model <- lm(mpg ~ wt + am + gear + vs * cyl, data = mtcars) # checking model assumptions check_model(model) ``` ### Model performance summaries `model_performance()` computes indices of model performance for regression models. Depending on the model object, typical indices might be r-squared, AIC, BIC, RMSE, ICC or LOOIC. #### Linear model ``` r m1 <- lm(mpg ~ wt + cyl, data = mtcars) model_performance(m1) #> # Indices of model performance #> #> AIC | AICc | BIC | R2 | R2 (adj.) | RMSE | Sigma #> --------------------------------------------------------------- #> 156.010 | 157.492 | 161.873 | 0.830 | 0.819 | 2.444 | 2.568 ``` #### Logistic regression ``` r m2 <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") model_performance(m2) #> # Indices of model performance #> #> AIC | AICc | BIC | Tjur's R2 | RMSE | Sigma | Log_loss | Score_log | Score_spherical | PCP #> ----------------------------------------------------------------------------------------------------- #> 31.298 | 32.155 | 35.695 | 0.478 | 0.359 | 1.000 | 0.395 | -14.903 | 0.095 | 0.743 ``` #### Linear mixed model ``` r library(lme4) m3 <- lmer(Reaction ~ Days + (1 + Days | Subject), data = sleepstudy) model_performance(m3) #> # Indices of model performance #> #> AIC | AICc | BIC | R2 (cond.) | R2 (marg.) | ICC | RMSE | Sigma #> ---------------------------------------------------------------------------------- #> 1755.628 | 1756.114 | 1774.786 | 0.799 | 0.279 | 0.722 | 23.438 | 25.592 ``` ### Models comparison The `compare_performance()` function can be used to compare the performance and quality of several models (including models of different types). ``` r counts <- c(18, 17, 15, 20, 10, 20, 25, 13, 12) outcome <- gl(3, 1, 9) treatment <- gl(3, 3) m4 <- glm(counts ~ outcome + treatment, family = poisson()) compare_performance(m1, m2, m3, m4, verbose = FALSE) #> # Comparison of Model Performance Indices #> #> Name | Model | AIC (weights) | AICc (weights) | BIC (weights) | RMSE | Sigma | Score_log | Score_spherical | R2 | R2 (adj.) | Tjur's R2 | Log_loss | PCP | R2 (cond.) | R2 (marg.) | ICC | Nagelkerke's R2 #> ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ #> m1 | lm | 156.0 (<.001) | 157.5 (<.001) | 161.9 (<.001) | 2.444 | 2.568 | | | 0.830 | 0.819 | | | | | | | #> m2 | glm | 31.3 (>.999) | 32.2 (>.999) | 35.7 (>.999) | 0.359 | 1.000 | -14.903 | 0.095 | | | 0.478 | 0.395 | 0.743 | | | | #> m3 | lmerMod | 1764.0 (<.001) | 1764.5 (<.001) | 1783.1 (<.001) | 23.438 | 25.592 | | | | | | | | 0.799 | 0.279 | 0.722 | #> m4 | glm | 56.8 (<.001) | 76.8 (<.001) | 57.7 (<.001) | 3.043 | 1.000 | -2.598 | 0.324 | | | | | | | | | 0.657 ``` #### General index of model performance One can also easily compute and a [**composite index**](https://easystats.github.io/performance/reference/compare_performance.html#details) of model performance and sort the models from the best one to the worse. ``` r compare_performance(m1, m2, m3, m4, rank = TRUE, verbose = FALSE) #> # Comparison of Model Performance Indices #> #> Name | Model | RMSE | Sigma | AIC weights | AICc weights | BIC weights | Performance-Score #> ----------------------------------------------------------------------------------------------- #> m2 | glm | 0.359 | 1.000 | 1.000 | 1.000 | 1.000 | 100.00% #> m4 | glm | 3.043 | 1.000 | 2.96e-06 | 2.06e-10 | 1.63e-05 | 37.67% #> m1 | lm | 2.444 | 2.568 | 8.30e-28 | 6.07e-28 | 3.99e-28 | 36.92% #> m3 | lmerMod | 23.438 | 25.592 | 0.00e+00 | 0.00e+00 | 0.00e+00 | 0.00% ``` #### Visualisation of indices of models’ performance Finally, we provide convenient visualisation (the `see` package must be installed). ``` r plot(compare_performance(m1, m2, m4, rank = TRUE, verbose = FALSE)) ``` ### Testing models `test_performance()` (and `test_bf`, its Bayesian sister) carries out the most relevant and appropriate tests based on the input (for instance, whether the models are nested or not). ``` r set.seed(123) data(iris) lm1 <- lm(Sepal.Length ~ Species, data = iris) lm2 <- lm(Sepal.Length ~ Species + Petal.Length, data = iris) lm3 <- lm(Sepal.Length ~ Species * Sepal.Width, data = iris) lm4 <- lm(Sepal.Length ~ Species * Sepal.Width + Petal.Length + Petal.Width, data = iris) test_performance(lm1, lm2, lm3, lm4) #> Name | Model | BF | Omega2 | p (Omega2) | LR | p (LR) #> ------------------------------------------------------------ #> lm1 | lm | | | | | #> lm2 | lm | > 1000 | 0.69 | < .001 | -6.25 | < .001 #> lm3 | lm | > 1000 | 0.36 | < .001 | -3.44 | < .001 #> lm4 | lm | > 1000 | 0.73 | < .001 | -7.77 | < .001 #> Each model is compared to lm1. test_bf(lm1, lm2, lm3, lm4) #> Bayes Factors for Model Comparison #> #> Model BF #> [lm2] Species + Petal.Length 3.45e+26 #> [lm3] Species * Sepal.Width 4.69e+07 #> [lm4] Species * Sepal.Width + Petal.Length + Petal.Width 7.58e+29 #> #> * Against Denominator: [lm1] Species #> * Bayes Factor Type: BIC approximation ``` ### Plotting Functions Plotting functions are available through the [**see** package](https://easystats.github.io/see/articles/performance.html). # Code of Conduct Please note that the performance project is released with a [Contributor Code of Conduct](https://easystats.github.io/performance/CODE_OF_CONDUCT.html). By contributing to this project, you agree to abide by its terms. # Contributing We are happy to receive bug reports, suggestions, questions, and (most of all) contributions to fix problems and add features. Please follow contributing guidelines mentioned here: ## References

performance/build/0000755000176200001440000000000014741727701013664 5ustar liggesusersperformance/build/partial.rdb0000644000176200001440000000007514741727701016013 0ustar liggesusersb```b`aab`b1g``d`aҬy@D?M7performance/man/0000755000176200001440000000000014736731423013340 5ustar liggesusersperformance/man/r2_somers.Rd0000644000176200001440000000133614504243270015534 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/r2_somers.R \name{r2_somers} \alias{r2_somers} \title{Somers' Dxy rank correlation for binary outcomes} \usage{ r2_somers(model) } \arguments{ \item{model}{A logistic regression model.} } \value{ A named vector with the R2 value. } \description{ Calculates the Somers' Dxy rank correlation for logistic regression models. } \examples{ \donttest{ if (require("correlation") && require("Hmisc")) { model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") r2_somers(model) } } } \references{ Somers, R. H. (1962). A new asymmetric measure of association for ordinal variables. American Sociological Review. 27 (6). } performance/man/r2_mlm.Rd0000644000176200001440000000510214666017356015021 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/r2_mlm.R \name{r2_mlm} \alias{r2_mlm} \title{Multivariate R2} \usage{ r2_mlm(model, ...) } \arguments{ \item{model}{Multivariate linear regression model.} \item{...}{Currently not used.} } \value{ A named vector with the R2 values. } \description{ Calculates two multivariate R2 values for multivariate linear regression. } \details{ The two indexes returned summarize model fit for the set of predictors given the system of responses. As compared to the default \link[=r2]{r2} index for multivariate linear models, the indexes returned by this function provide a single fit value collapsed across all responses. The two returned indexes were proposed by \emph{Van den Burg and Lewis (1988)} as an extension of the metrics proposed by \emph{Cramer and Nicewander (1979)}. Of the numerous indexes proposed across these two papers, only two metrics, the \eqn{R_{xy}} and \eqn{P_{xy}}, are recommended for use by \emph{Azen and Budescu (2006)}. For a multivariate linear regression with \eqn{p} predictors and \eqn{q} responses where \eqn{p > q}, the \eqn{R_{xy}} index is computed as: \deqn{R_{xy} = 1 - \prod_{i=1}^p (1 - \rho_i^2)} Where \eqn{\rho} is a canonical variate from a \link[=cancor]{canonical correlation} between the predictors and responses. This metric is symmetric and its value does not change when the roles of the variables as predictors or responses are swapped. The \eqn{P_{xy}} is computed as: \deqn{P_{xy} = \frac{q - trace(\bf{S}_{\bf{YY}}^{-1}\bf{S}_{\bf{YY|X}})}{q}} Where \eqn{\bf{S}_{\bf{YY}}} is the matrix of response covariances and \eqn{\bf{S}_{\bf{YY|X}}} is the matrix of residual covariances given the predictors. This metric is asymmetric and can change depending on which variables are considered predictors versus responses. } \examples{ model <- lm(cbind(qsec, drat) ~ wt + mpg + cyl, data = mtcars) r2_mlm(model) model_swap <- lm(cbind(wt, mpg, cyl) ~ qsec + drat, data = mtcars) r2_mlm(model_swap) } \references{ \itemize{ \item Azen, R., & Budescu, D. V. (2006). Comparing predictors in multivariate regression models: An extension of dominance analysis. Journal of Educational and Behavioral Statistics, 31(2), 157-180. \item Cramer, E. M., & Nicewander, W. A. (1979). Some symmetric, invariant measures of multivariate association. Psychometrika, 44, 43-54. \item Van den Burg, W., & Lewis, C. (1988). Some properties of two measures of multivariate association. Psychometrika, 53, 109-122. } } \author{ Joseph Luchman } performance/man/check_predictions.Rd0000644000176200001440000001325414741713425017312 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check_predictions.R \name{check_predictions} \alias{check_predictions} \alias{check_predictions.default} \title{Posterior predictive checks} \usage{ check_predictions(object, ...) \method{check_predictions}{default}( object, iterations = 50, check_range = FALSE, re_formula = NULL, bandwidth = "nrd", type = "density", verbose = TRUE, ... ) } \arguments{ \item{object}{A statistical model.} \item{...}{Passed down to \code{simulate()}.} \item{iterations}{The number of draws to simulate/bootstrap.} \item{check_range}{Logical, if \code{TRUE}, includes a plot with the minimum value of the original response against the minimum values of the replicated responses, and the same for the maximum value. This plot helps judging whether the variation in the original data is captured by the model or not (\emph{Gelman et al. 2020, pp.163}). The minimum and maximum values of \code{y} should be inside the range of the related minimum and maximum values of \code{yrep}.} \item{re_formula}{Formula containing group-level effects (random effects) to be considered in the simulated data. If \code{NULL} (default), condition on all random effects. If \code{NA} or \code{~0}, condition on no random effects. See \code{simulate()} in \strong{lme4}.} \item{bandwidth}{A character string indicating the smoothing bandwidth to be used. Unlike \code{stats::density()}, which used \code{"nrd0"} as default, the default used here is \code{"nrd"} (which seems to give more plausible results for non-Gaussian models). When problems with plotting occur, try to change to a different value.} \item{type}{Plot type for the posterior predictive checks plot. Can be \code{"density"}, \code{"discrete_dots"}, \code{"discrete_interval"} or \code{"discrete_both"} (the \verb{discrete_*} options are appropriate for models with discrete - binary, integer or ordinal etc. - outcomes).} \item{verbose}{Toggle warnings.} } \value{ A data frame of simulated responses and the original response vector. } \description{ Posterior predictive checks mean "simulating replicated data under the fitted model and then comparing these to the observed data" (\emph{Gelman and Hill, 2007, p. 158}). Posterior predictive checks can be used to "look for systematic discrepancies between real and simulated data" (\emph{Gelman et al. 2014, p. 169}). \strong{performance} provides posterior predictive check methods for a variety of frequentist models (e.g., \code{lm}, \code{merMod}, \code{glmmTMB}, ...). For Bayesian models, the model is passed to \code{\link[bayesplot:pp_check]{bayesplot::pp_check()}}. If \code{check_predictions()} doesn't work as expected, try setting \code{verbose = TRUE} to get hints about possible problems. } \details{ An example how posterior predictive checks can also be used for model comparison is Figure 6 from \emph{Gabry et al. 2019, Figure 6}. \if{html}{\cr \figure{pp_check.png}{options: width="90\%" alt="Posterior Predictive Check"} \cr} The model shown in the right panel (b) can simulate new data that are more similar to the observed outcome than the model in the left panel (a). Thus, model (b) is likely to be preferred over model (a). } \note{ Every model object that has a \code{simulate()}-method should work with \code{check_predictions()}. On R 3.6.0 and higher, if \strong{bayesplot} (or a package that imports \strong{bayesplot} such as \strong{rstanarm} or \strong{brms}) is loaded, \code{pp_check()} is also available as an alias for \code{check_predictions()}. If \code{check_predictions()} doesn't work as expected, try setting \code{verbose = TRUE} to get hints about possible problems. } \examples{ \dontshow{if (insight::check_if_installed("see", minimum_version = "0.9.1", quietly = TRUE)) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} # linear model model <- lm(mpg ~ disp, data = mtcars) check_predictions(model) # discrete/integer outcome set.seed(99) d <- iris d$skewed <- rpois(150, 1) model <- glm( skewed ~ Species + Petal.Length + Petal.Width, family = poisson(), data = d ) check_predictions(model, type = "discrete_both") \dontshow{\}) # examplesIf} } \references{ \itemize{ \item Gabry, J., Simpson, D., Vehtari, A., Betancourt, M., and Gelman, A. (2019). Visualization in Bayesian workflow. Journal of the Royal Statistical Society: Series A (Statistics in Society), 182(2), 389–402. https://doi.org/10.1111/rssa.12378 \item Gelman, A., and Hill, J. (2007). Data analysis using regression and multilevel/hierarchical models. Cambridge; New York: Cambridge University Press. \item Gelman, A., Carlin, J. B., Stern, H. S., Dunson, D. B., Vehtari, A., and Rubin, D. B. (2014). Bayesian data analysis. (Third edition). CRC Press. \item Gelman, A., Hill, J., and Vehtari, A. (2020). Regression and Other Stories. Cambridge University Press. } } \seealso{ \code{\link[=simulate_residuals]{simulate_residuals()}} and \code{\link[=check_residuals]{check_residuals()}}. See also \code{\link[see:print.see_performance_pp_check]{see::print.see_performance_pp_check()}} for options to customize the plot. Other functions to check model assumptions and and assess model quality: \code{\link{check_autocorrelation}()}, \code{\link{check_collinearity}()}, \code{\link{check_convergence}()}, \code{\link{check_heteroscedasticity}()}, \code{\link{check_homogeneity}()}, \code{\link{check_model}()}, \code{\link{check_outliers}()}, \code{\link{check_overdispersion}()}, \code{\link{check_singularity}()}, \code{\link{check_zeroinflation}()} } \concept{functions to check model assumptions and and assess model quality} performance/man/check_heterogeneity_bias.Rd0000644000176200001440000000473514706655512020647 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check_heterogeneity_bias.R \name{check_heterogeneity_bias} \alias{check_heterogeneity_bias} \title{Check model predictor for heterogeneity bias} \usage{ check_heterogeneity_bias(x, select = NULL, by = NULL, nested = FALSE) } \arguments{ \item{x}{A data frame or a mixed model object.} \item{select}{Character vector (or formula) with names of variables to select that should be checked. If \code{x} is a mixed model object, this argument will be ignored.} \item{by}{Character vector (or formula) with the name of the variable that indicates the group- or cluster-ID. For cross-classified or nested designs, \code{by} can also identify two or more variables as group- or cluster-IDs. If the data is nested and should be treated as such, set \code{nested = TRUE}. Else, if \code{by} defines two or more variables and \code{nested = FALSE}, a cross-classified design is assumed. If \code{x} is a model object, this argument will be ignored. For nested designs, \code{by} can be: \itemize{ \item a character vector with the name of the variable that indicates the levels, ordered from \emph{highest} level to \emph{lowest} (e.g. \code{by = c("L4", "L3", "L2")}. \item a character vector with variable names in the format \code{by = "L4/L3/L2"}, where the levels are separated by \code{/}. } See also section \emph{De-meaning for cross-classified designs} and \emph{De-meaning for nested designs} below.} \item{nested}{Logical, if \code{TRUE}, the data is treated as nested. If \code{FALSE}, the data is treated as cross-classified. Only applies if \code{by} contains more than one variable.} } \description{ \code{check_heterogeneity_bias()} checks if model predictors or variables may cause a heterogeneity bias, i.e. if variables have a within- and/or between-effect (\emph{Bell and Jones, 2015}). } \examples{ data(iris) iris$ID <- sample(1:4, nrow(iris), replace = TRUE) # fake-ID check_heterogeneity_bias(iris, select = c("Sepal.Length", "Petal.Length"), by = "ID") } \references{ \itemize{ \item Bell A, Jones K. 2015. Explaining Fixed Effects: Random Effects Modeling of Time-Series Cross-Sectional and Panel Data. Political Science Research and Methods, 3(1), 133–153. } } \seealso{ For further details, read the vignette \url{https://easystats.github.io/parameters/articles/demean.html} and also see documentation for \code{\link[datawizard:demean]{datawizard::demean()}}. } performance/man/performance_mse.Rd0000644000176200001440000000211514642733710016770 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/performance_mse.R \name{performance_mse} \alias{performance_mse} \alias{mse} \title{Mean Square Error of Linear Models} \usage{ performance_mse(model, ...) mse(model, ...) } \arguments{ \item{model}{A model.} \item{...}{Arguments passed down to \code{lme4::bootMer()} or \code{boot::boot()} for bootstrapped ICC, R2, RMSE etc.; for \code{variance_decomposition()}, arguments are passed down to \code{brms::posterior_predict()}.} } \value{ Numeric, the mean square error of \code{model}. } \description{ Compute mean square error of linear models. } \details{ The mean square error is the mean of the sum of squared residuals, i.e. it measures the average of the squares of the errors. Less technically speaking, the mean square error can be considered as the variance of the residuals, i.e. the variation in the outcome the model doesn't explain. Lower values (closer to zero) indicate better fit. } \examples{ data(mtcars) m <- lm(mpg ~ hp + gear, data = mtcars) performance_mse(m) } performance/man/r2_zeroinflated.Rd0000644000176200001440000000225414257537777016741 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/r2_zeroinflated.R \name{r2_zeroinflated} \alias{r2_zeroinflated} \title{R2 for models with zero-inflation} \usage{ r2_zeroinflated(model, method = c("default", "correlation")) } \arguments{ \item{model}{A model.} \item{method}{Indicates the method to calculate R2. See 'Details'. May be abbreviated.} } \value{ For the default-method, a list with the R2 and adjusted R2 values. For \code{method = "correlation"}, a named numeric vector with the correlation-based R2 value. } \description{ Calculates R2 for models with zero-inflation component, including mixed effects models. } \details{ The default-method calculates an R2 value based on the residual variance divided by the total variance. For \code{method = "correlation"}, R2 is a correlation-based measure, which is rather crude. It simply computes the squared correlation between the model's actual and predicted response. } \examples{ \donttest{ if (require("pscl")) { data(bioChemists) model <- zeroinfl( art ~ fem + mar + kid5 + ment | kid5 + phd, data = bioChemists ) r2_zeroinflated(model) } } } performance/man/model_performance.merMod.Rd0000644000176200001440000000520714546750702020536 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/model_performance.mixed.R \name{model_performance.merMod} \alias{model_performance.merMod} \title{Performance of Mixed Models} \usage{ \method{model_performance}{merMod}( model, metrics = "all", estimator = "REML", verbose = TRUE, ... ) } \arguments{ \item{model}{A mixed effects model.} \item{metrics}{Can be \code{"all"}, \code{"common"} or a character vector of metrics to be computed (some of \code{c("AIC", "AICc", "BIC", "R2", "ICC", "RMSE", "SIGMA", "LOGLOSS", "SCORE")}). \code{"common"} will compute AIC, BIC, R2, ICC and RMSE.} \item{estimator}{Only for linear models. Corresponds to the different estimators for the standard deviation of the errors. If \code{estimator = "ML"} (default, except for \code{performance_aic()} when the model object is of class \code{lmerMod}), the scaling is done by \code{n} (the biased ML estimator), which is then equivalent to using \code{AIC(logLik())}. Setting it to \code{"REML"} will give the same results as \code{AIC(logLik(..., REML = TRUE))}.} \item{verbose}{Toggle warnings and messages.} \item{...}{Arguments passed to or from other methods.} } \value{ A data frame (with one row) and one column per "index" (see \code{metrics}). } \description{ Compute indices of model performance for mixed models. } \details{ \subsection{Intraclass Correlation Coefficient (ICC)}{ This method returns the \emph{adjusted ICC} only, as this is typically of interest when judging the variance attributed to the random effects part of the model (see also \code{\link[=icc]{icc()}}). } \subsection{REML versus ML estimator}{ The default behaviour of \code{model_performance()} when computing AIC or BIC of linear mixed model from package \strong{lme4} is the same as for \code{AIC()} or \code{BIC()} (i.e. \code{estimator = "REML"}). However, for model comparison using \code{compare_performance()} sets \code{estimator = "ML"} by default, because \emph{comparing} information criteria based on REML fits is usually not valid (unless all models have the same fixed effects). Thus, make sure to set the correct estimator-value when looking at fit-indices or comparing model fits. } \subsection{Other performance indices}{ Furthermore, see 'Details' in \code{\link[=model_performance.lm]{model_performance.lm()}} for more details on returned indices. } } \examples{ \dontshow{if (require("lme4")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} model <- lme4::lmer(Petal.Length ~ Sepal.Length + (1 | Species), data = iris) model_performance(model) \dontshow{\}) # examplesIf} } performance/man/simulate_residuals.Rd0000644000176200001440000001020714600524676017525 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/simulate_residuals.R \name{simulate_residuals} \alias{simulate_residuals} \alias{residuals.performance_simres} \title{Simulate randomized quantile residuals from a model} \usage{ simulate_residuals(x, iterations = 250, ...) \method{residuals}{performance_simres}(object, quantile_function = NULL, outlier_values = NULL, ...) } \arguments{ \item{x}{A model object.} \item{iterations}{Number of simulations to run.} \item{...}{Arguments passed on to \code{\link[DHARMa:simulateResiduals]{DHARMa::simulateResiduals()}}.} \item{object}{A \code{performance_simres} object, as returned by \code{simulate_residuals()}.} \item{quantile_function}{A function to apply to the residuals. If \code{NULL}, the residuals are returned as is. If not \code{NULL}, the residuals are passed to this function. This is useful for returning normally distributed residuals, for example: \code{residuals(x, quantile_function = qnorm)}.} \item{outlier_values}{A vector of length 2, specifying the values to replace \code{-Inf} and \code{Inf} with, respectively.} } \value{ Simulated residuals, which can be further processed with \code{\link[=check_residuals]{check_residuals()}}. The returned object is of class \code{DHARMa} and \code{performance_simres}. } \description{ Returns simulated residuals from a model. This is useful for checking the uniformity of residuals, in particular for non-Gaussian models, where the residuals are not expected to be normally distributed. } \details{ This function is a small wrapper around \code{\link[DHARMa:simulateResiduals]{DHARMa::simulateResiduals()}}. It basically only sets \code{plot = FALSE} and adds an additional class attribute (\code{"performance_sim_res"}), which allows using the DHARMa object in own plotting functions from the \strong{see} package. See also \code{vignette("DHARMa")}. There is a \code{plot()} method to visualize the distribution of the residuals. } \section{Tests based on simulated residuals}{ For certain models, resp. model from certain families, tests like \code{\link[=check_zeroinflation]{check_zeroinflation()}} or \code{\link[=check_overdispersion]{check_overdispersion()}} are based on simulated residuals. These are usually more accurate for such tests than the traditionally used Pearson residuals. However, when simulating from more complex models, such as mixed models or models with zero-inflation, there are several important considerations. \code{simulate_residuals()} relies on \code{\link[DHARMa:simulateResiduals]{DHARMa::simulateResiduals()}}, and additional arguments specified in \code{...} are passed further down to that function. The defaults in DHARMa are set on the most conservative option that works for all models. However, in many cases, the help advises to use different settings in particular situations or for particular models. It is recommended to read the 'Details' in \code{?DHARMa::simulateResiduals} closely to understand the implications of the simulation process and which arguments should be modified to get the most accurate results. } \examples{ \dontshow{if (require("DHARMa")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} m <- lm(mpg ~ wt + cyl + gear + disp, data = mtcars) simulate_residuals(m) # extract residuals head(residuals(simulate_residuals(m))) \dontshow{\}) # examplesIf} } \references{ \itemize{ \item Hartig, F., & Lohse, L. (2022). DHARMa: Residual Diagnostics for Hierarchical (Multi-Level / Mixed) Regression Models (Version 0.4.5). Retrieved from https://CRAN.R-project.org/package=DHARMa \item Dunn, P. K., & Smyth, G. K. (1996). Randomized Quantile Residuals. Journal of Computational and Graphical Statistics, 5(3), 236. \doi{10.2307/1390802} } } \seealso{ \code{\link[=check_residuals]{check_residuals()}}, \code{\link[=check_zeroinflation]{check_zeroinflation()}}, \code{\link[=check_overdispersion]{check_overdispersion()}} and \code{\link[=check_predictions]{check_predictions()}}. See also \code{\link[see:plot.see_performance_simres]{see::plot.see_performance_simres()}} for options to customize the plot. } performance/man/r2_tjur.Rd0000644000176200001440000000201714335664246015221 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/r2_tjur.R \name{r2_tjur} \alias{r2_tjur} \title{Tjur's R2 - coefficient of determination (D)} \usage{ r2_tjur(model, ...) } \arguments{ \item{model}{Binomial Model.} \item{...}{Arguments from other functions, usually only used internally.} } \value{ A named vector with the R2 value. } \description{ This method calculates the Coefficient of Discrimination \code{D} (also known as Tjur's R2; \cite{Tjur, 2009}) for generalized linear (mixed) models for binary outcomes. It is an alternative to other pseudo-R2 values like Nagelkerke's R2 or Cox-Snell R2. The Coefficient of Discrimination \code{D} can be read like any other (pseudo-)R2 value. } \examples{ model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") r2_tjur(model) } \references{ Tjur, T. (2009). Coefficients of determination in logistic regression models - A new proposal: The coefficient of discrimination. The American Statistician, 63(4), 366-372. } performance/man/cronbachs_alpha.Rd0000644000176200001440000000234614561136140016732 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/cronbachs_alpha.R \name{cronbachs_alpha} \alias{cronbachs_alpha} \title{Cronbach's Alpha for Items or Scales} \usage{ cronbachs_alpha(x, ...) } \arguments{ \item{x}{A matrix or a data frame.} \item{...}{Currently not used.} } \value{ The Cronbach's Alpha value for \code{x}. } \description{ Compute various measures of internal consistencies for tests or item-scales of questionnaires. } \details{ The Cronbach's Alpha value for \code{x}. A value closer to 1 indicates greater internal consistency, where usually following rule of thumb is applied to interpret the results: \ifelse{html}{\out{α}}{\eqn{\alpha}{alpha}} < 0.5 is unacceptable, 0.5 < \ifelse{html}{\out{α}}{\eqn{\alpha}{alpha}} < 0.6 is poor, 0.6 < \ifelse{html}{\out{α}}{\eqn{\alpha}{alpha}} < 0.7 is questionable, 0.7 < \ifelse{html}{\out{α}}{\eqn{\alpha}{alpha}} < 0.8 is acceptable, and everything > 0.8 is good or excellent. } \examples{ data(mtcars) x <- mtcars[, c("cyl", "gear", "carb", "hp")] cronbachs_alpha(x) } \references{ Bland, J. M., and Altman, D. G. Statistics notes: Cronbach's alpha. BMJ 1997;314:572. 10.1136/bmj.314.7080.572 } performance/man/performance_roc.Rd0000644000176200001440000000553214736731423017000 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/performance_roc.R \name{performance_roc} \alias{performance_roc} \title{Simple ROC curve} \usage{ performance_roc(x, ..., predictions, new_data) } \arguments{ \item{x}{A numeric vector, representing the outcome (0/1), or a model with binomial outcome.} \item{...}{One or more models with binomial outcome. In this case, \code{new_data} is ignored.} \item{predictions}{If \code{x} is numeric, a numeric vector of same length as \code{x}, representing the actual predicted values.} \item{new_data}{If \code{x} is a model, a data frame that is passed to \code{predict()} as \code{newdata}-argument. If \code{NULL}, the ROC for the full model is calculated.} } \value{ A data frame with three columns, the x/y-coordinate pairs for the ROC curve (\code{Sensitivity} and \code{Specificity}), and a column with the model name. } \description{ This function calculates a simple ROC curves of x/y coordinates based on response and predictions of a binomial model. It returns the area under the curve (AUC) as a percentage, which corresponds to the probability that a randomly chosen observation of "condition 1" is correctly classified by the model as having a higher probability of being "condition 1" than a randomly chosen "condition 2" observation. Applying \code{as.data.frame()} to the output returns a data frame containing the following: \itemize{ \item \code{Sensitivity} (that actually corresponds to \code{1 - Specificity}): It is the False Positive Rate. \item \code{Sensitivity}: It is the True Positive Rate, which is the proportion of correctly classified "condition 1" observations. } } \note{ There is also a \href{https://easystats.github.io/see/articles/performance.html}{\code{plot()}-method} implemented in the \href{https://easystats.github.io/see/}{\pkg{see}-package}. } \examples{ library(bayestestR) data(iris) set.seed(123) iris$y <- rbinom(nrow(iris), size = 1, .3) folds <- sample(nrow(iris), size = nrow(iris) / 8, replace = FALSE) test_data <- iris[folds, ] train_data <- iris[-folds, ] model <- glm(y ~ Sepal.Length + Sepal.Width, data = train_data, family = "binomial") as.data.frame(performance_roc(model, new_data = test_data)) as.numeric(performance_roc(model)) roc <- performance_roc(model, new_data = test_data) area_under_curve(roc$Specificity, roc$Sensitivity) if (interactive()) { m1 <- glm(y ~ Sepal.Length + Sepal.Width, data = iris, family = "binomial") m2 <- glm(y ~ Sepal.Length + Petal.Width, data = iris, family = "binomial") m3 <- glm(y ~ Sepal.Length + Species, data = iris, family = "binomial") performance_roc(m1, m2, m3) # if you have `see` package installed, you can also plot comparison of # ROC curves for different models if (require("see")) plot(performance_roc(m1, m2, m3)) } } performance/man/r2_mckelvey.Rd0000644000176200001440000000240314335664246016053 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/r2_mckelvey.R \name{r2_mckelvey} \alias{r2_mckelvey} \title{McKelvey & Zavoinas R2} \usage{ r2_mckelvey(model) } \arguments{ \item{model}{Generalized linear model.} } \value{ The R2 value. } \description{ Calculates McKelvey and Zavoinas pseudo R2. } \details{ McKelvey and Zavoinas R2 is based on the explained variance, where the variance of the predicted response is divided by the sum of the variance of the predicted response and residual variance. For binomial models, the residual variance is either \code{pi^2/3} for logit-link and 1 for probit-link. For poisson-models, the residual variance is based on log-normal approximation, similar to the \emph{distribution-specific variance} as described in \code{?insight::get_variance}. } \examples{ ## Dobson (1990) Page 93: Randomized Controlled Trial: counts <- c(18, 17, 15, 20, 10, 20, 25, 13, 12) # outcome <- gl(3, 1, 9) treatment <- gl(3, 3) model <- glm(counts ~ outcome + treatment, family = poisson()) r2_mckelvey(model) } \references{ McKelvey, R., Zavoina, W. (1975), "A Statistical Model for the Analysis of Ordinal Level Dependent Variables", Journal of Mathematical Sociology 4, S. 103–120. } performance/man/r2_kullback.Rd0000644000176200001440000000163214570063447016024 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/r2_kl.R \name{r2_kullback} \alias{r2_kullback} \alias{r2_kullback.glm} \title{Kullback-Leibler R2} \usage{ r2_kullback(model, ...) \method{r2_kullback}{glm}(model, adjust = TRUE, ...) } \arguments{ \item{model}{A generalized linear model.} \item{...}{Additional arguments. Currently not used.} \item{adjust}{Logical, if \code{TRUE} (the default), the adjusted R2 value is returned.} } \value{ A named vector with the R2 value. } \description{ Calculates the Kullback-Leibler-divergence-based R2 for generalized linear models. } \examples{ model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") r2_kullback(model) } \references{ Cameron, A. C. and Windmeijer, A. G. (1997) An R-squared measure of goodness of fit for some common nonlinear regression models. Journal of Econometrics, 77: 329-342. } performance/man/model_performance.rma.Rd0000644000176200001440000000617514620351763020074 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/model_performance.rma.R \name{model_performance.rma} \alias{model_performance.rma} \title{Performance of Meta-Analysis Models} \usage{ \method{model_performance}{rma}( model, metrics = "all", estimator = "ML", verbose = TRUE, ... ) } \arguments{ \item{model}{A \code{rma} object as returned by \code{metafor::rma()}.} \item{metrics}{Can be \code{"all"} or a character vector of metrics to be computed (some of \code{c("AIC", "BIC", "I2", "H2", "TAU2", "R2", "CochransQ", "QE", "Omnibus", "QM")}).} \item{estimator}{Only for linear models. Corresponds to the different estimators for the standard deviation of the errors. If \code{estimator = "ML"} (default, except for \code{performance_aic()} when the model object is of class \code{lmerMod}), the scaling is done by \code{n} (the biased ML estimator), which is then equivalent to using \code{AIC(logLik())}. Setting it to \code{"REML"} will give the same results as \code{AIC(logLik(..., REML = TRUE))}.} \item{verbose}{Toggle off warnings.} \item{...}{Arguments passed to or from other methods.} } \value{ A data frame (with one row) and one column per "index" (see \code{metrics}). } \description{ Compute indices of model performance for meta-analysis model from the \strong{metafor} package. } \details{ \subsection{Indices of fit}{ \itemize{ \item \strong{AIC} Akaike's Information Criterion, see \code{?stats::AIC} \item \strong{BIC} Bayesian Information Criterion, see \code{?stats::BIC} \item \strong{I2}: For a random effects model, \code{I2} estimates (in percent) how much of the total variability in the effect size estimates can be attributed to heterogeneity among the true effects. For a mixed-effects model, \code{I2} estimates how much of the unaccounted variability can be attributed to residual heterogeneity. \item \strong{H2}: For a random-effects model, \code{H2} estimates the ratio of the total amount of variability in the effect size estimates to the amount of sampling variability. For a mixed-effects model, \code{H2} estimates the ratio of the unaccounted variability in the effect size estimates to the amount of sampling variability. \item \strong{TAU2}: The amount of (residual) heterogeneity in the random or mixed effects model. \item \strong{CochransQ (QE)}: Test for (residual) Heterogeneity. Without moderators in the model, this is simply Cochran's \emph{Q}-test. \item \strong{Omnibus (QM)}: Omnibus test of parameters. \item \strong{R2}: Pseudo-R2-statistic, which indicates the amount of heterogeneity accounted for by the moderators included in a fixed-effects model. } See the documentation for \code{?metafor::fitstats}. } } \examples{ \dontshow{if (require("metafor") && require("metadat")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} data(dat.bcg, package = "metadat") dat <- metafor::escalc( measure = "RR", ai = tpos, bi = tneg, ci = cpos, di = cneg, data = dat.bcg ) model <- metafor::rma(yi, vi, data = dat, method = "REML") model_performance(model) \dontshow{\}) # examplesIf} } performance/man/binned_residuals.Rd0000644000176200001440000001036414741711171017137 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/binned_residuals.R \name{binned_residuals} \alias{binned_residuals} \title{Binned residuals for binomial logistic regression} \usage{ binned_residuals( model, term = NULL, n_bins = NULL, show_dots = NULL, ci = 0.95, ci_type = c("exact", "gaussian", "boot"), residuals = c("deviance", "pearson", "response"), iterations = 1000, verbose = TRUE, ... ) } \arguments{ \item{model}{A \code{glm}-object with \emph{binomial}-family.} \item{term}{Name of independent variable from \code{x}. If not \code{NULL}, average residuals for the categories of \code{term} are plotted; else, average residuals for the estimated probabilities of the response are plotted.} \item{n_bins}{Numeric, the number of bins to divide the data. If \code{n_bins = NULL}, the square root of the number of observations is taken.} \item{show_dots}{Logical, if \code{TRUE}, will show data points in the plot. Set to \code{FALSE} for models with many observations, if generating the plot is too time-consuming. By default, \code{show_dots = NULL}. In this case \code{binned_residuals()} tries to guess whether performance will be poor due to a very large model and thus automatically shows or hides dots.} \item{ci}{Numeric, the confidence level for the error bounds.} \item{ci_type}{Character, the type of error bounds to calculate. Can be \code{"exact"} (default), \code{"gaussian"} or \code{"boot"}. \code{"exact"} calculates the error bounds based on the exact binomial distribution, using \code{\link[=binom.test]{binom.test()}}. \code{"gaussian"} uses the Gaussian approximation, while \code{"boot"} uses a simple bootstrap method, where confidence intervals are calculated based on the quantiles of the bootstrap distribution.} \item{residuals}{Character, the type of residuals to calculate. Can be \code{"deviance"} (default), \code{"pearson"} or \code{"response"}. It is recommended to use \code{"response"} only for those models where other residuals are not available.} \item{iterations}{Integer, the number of iterations to use for the bootstrap method. Only used if \code{ci_type = "boot"}.} \item{verbose}{Toggle warnings and messages.} \item{...}{Currently not used.} } \value{ A data frame representing the data that is mapped in the accompanying plot. In case all residuals are inside the error bounds, points are black. If some of the residuals are outside the error bounds (indicated by the grey-shaded area), blue points indicate residuals that are OK, while red points indicate model under- or over-fitting for the relevant range of estimated probabilities. } \description{ Check model quality of binomial logistic regression models. } \details{ Binned residual plots are achieved by "dividing the data into categories (bins) based on their fitted values, and then plotting the average residual versus the average fitted value for each bin." \emph{(Gelman, Hill 2007: 97)}. If the model were true, one would expect about 95\% of the residuals to fall inside the error bounds. If \code{term} is not \code{NULL}, one can compare the residuals in relation to a specific model predictor. This may be helpful to check if a term would fit better when transformed, e.g. a rising and falling pattern of residuals along the x-axis is a signal to consider taking the logarithm of the predictor (cf. Gelman and Hill 2007, pp. 97-98). } \note{ \code{binned_residuals()} returns a data frame, however, the \code{print()} method only returns a short summary of the result. The data frame itself is used for plotting. The \code{plot()} method, in turn, creates a ggplot-object. } \examples{ model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") result <- binned_residuals(model) result # look at the data frame as.data.frame(result) \dontshow{if (insight::check_if_installed("see", minimum_version = "0.9.1", quietly = TRUE)) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} \donttest{ # plot plot(result, show_dots = TRUE) } \dontshow{\}) # examplesIf} } \references{ Gelman, A., and Hill, J. (2007). Data analysis using regression and multilevel/hierarchical models. Cambridge; New York: Cambridge University Press. } performance/man/r2_nakagawa.Rd0000644000176200001440000001740314675461510016010 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/r2_nakagawa.R \name{r2_nakagawa} \alias{r2_nakagawa} \title{Nakagawa's R2 for mixed models} \usage{ r2_nakagawa( model, by_group = FALSE, tolerance = 1e-08, ci = NULL, iterations = 100, ci_method = NULL, null_model = NULL, approximation = "lognormal", model_component = NULL, verbose = TRUE, ... ) } \arguments{ \item{model}{A mixed effects model.} \item{by_group}{Logical, if \code{TRUE}, returns the explained variance at different levels (if there are multiple levels). This is essentially similar to the variance reduction approach by \emph{Hox (2010), pp. 69-78}.} \item{tolerance}{Tolerance for singularity check of random effects, to decide whether to compute random effect variances for the conditional r-squared or not. Indicates up to which value the convergence result is accepted. When \code{r2_nakagawa()} returns a warning, stating that random effect variances can't be computed (and thus, the conditional r-squared is \code{NA}), decrease the tolerance-level. See also \code{\link[=check_singularity]{check_singularity()}}.} \item{ci}{Confidence resp. credible interval level. For \code{icc()}, \code{r2()}, and \code{rmse()}, confidence intervals are based on bootstrapped samples from the ICC, R2 or RMSE value. See \code{iterations}.} \item{iterations}{Number of bootstrap-replicates when computing confidence intervals for the ICC, R2, RMSE etc.} \item{ci_method}{Character string, indicating the bootstrap-method. Should be \code{NULL} (default), in which case \code{lme4::bootMer()} is used for bootstrapped confidence intervals. However, if bootstrapped intervals cannot be calculated this way, try \code{ci_method = "boot"}, which falls back to \code{boot::boot()}. This may successfully return bootstrapped confidence intervals, but bootstrapped samples may not be appropriate for the multilevel structure of the model. There is also an option \code{ci_method = "analytical"}, which tries to calculate analytical confidence assuming a chi-squared distribution. However, these intervals are rather inaccurate and often too narrow. It is recommended to calculate bootstrapped confidence intervals for mixed models.} \item{null_model}{Optional, a null model to compute the random effect variances, which is passed to \code{\link[insight:get_variance]{insight::get_variance()}}. Usually only required if calculation of r-squared or ICC fails when \code{null_model} is not specified. If calculating the null model takes longer and you already have fit the null model, you can pass it here, too, to speed up the process.} \item{approximation}{Character string, indicating the approximation method for the distribution-specific (observation level, or residual) variance. Only applies to non-Gaussian models. Can be \code{"lognormal"} (default), \code{"delta"} or \code{"trigamma"}. For binomial models, the default is the \emph{theoretical} distribution specific variance, however, it can also be \code{"observation_level"}. See \emph{Nakagawa et al. 2017}, in particular supplement 2, for details.} \item{model_component}{For models that can have a zero-inflation component, specify for which component variances should be returned. If \code{NULL} or \code{"full"} (the default), both the conditional and the zero-inflation component are taken into account. If \code{"conditional"}, only the conditional component is considered.} \item{verbose}{Toggle warnings and messages.} \item{...}{Arguments passed down to \code{lme4::bootMer()} or \code{boot::boot()} for bootstrapped ICC, R2, RMSE etc.; for \code{variance_decomposition()}, arguments are passed down to \code{brms::posterior_predict()}.} } \value{ A list with the conditional and marginal R2 values. } \description{ Compute the \emph{marginal} and \emph{conditional} r-squared value for mixed effects models with complex random effects structures. } \details{ Marginal and conditional r-squared values for mixed models are calculated based on \emph{Nakagawa et al. (2017)}. For more details on the computation of the variances, see \code{\link[insight:get_variance]{insight::get_variance()}}. The random effect variances are actually the mean random effect variances, thus the r-squared value is also appropriate for mixed models with random slopes or nested random effects (see \emph{Johnson, 2014}). \itemize{ \item \strong{Conditional R2}: takes both the fixed and random effects into account. \item \strong{Marginal R2}: considers only the variance of the fixed effects. } The contribution of random effects can be deduced by subtracting the marginal R2 from the conditional R2 or by computing the \code{\link[=icc]{icc()}}. } \section{Supported models and model families}{ The single variance components that are required to calculate the marginal and conditional r-squared values are calculated using the \code{\link[insight:get_variance]{insight::get_variance()}} function. The results are validated against the solutions provided by \emph{Nakagawa et al. (2017)}, in particular examples shown in the Supplement 2 of the paper. Other model families are validated against results from the \strong{MuMIn} package. This means that the r-squared values returned by \code{r2_nakagawa()} should be accurate and reliable for following mixed models or model families: \itemize{ \item Bernoulli (logistic) regression \item Binomial regression (with other than binary outcomes) \item Poisson and Quasi-Poisson regression \item Negative binomial regression (including nbinom1, nbinom2 and nbinom12 families) \item Gaussian regression (linear models) \item Gamma regression \item Tweedie regression \item Beta regression \item Ordered beta regression } Following model families are not yet validated, but should work: \itemize{ \item Zero-inflated and hurdle models \item Beta-binomial regression \item Compound Poisson regression \item Generalized Poisson regression \item Log-normal regression \item Skew-normal regression } Extracting variance components for models with zero-inflation part is not straightforward, because it is not definitely clear how the distribution-specific variance should be calculated. Therefore, it is recommended to carefully inspect the results, and probably validate against other models, e.g. Bayesian models (although results may be only roughly comparable). Log-normal regressions (e.g. \code{lognormal()} family in \strong{glmmTMB} or \code{gaussian("log")}) often have a very low fixed effects variance (if they were calculated as suggested by \emph{Nakagawa et al. 2017}). This results in very low ICC or r-squared values, which may not be meaningful. } \examples{ \dontshow{if (require("lme4")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} model <- lme4::lmer(Sepal.Length ~ Petal.Length + (1 | Species), data = iris) r2_nakagawa(model) r2_nakagawa(model, by_group = TRUE) \dontshow{\}) # examplesIf} } \references{ \itemize{ \item Hox, J. J. (2010). Multilevel analysis: techniques and applications (2nd ed). New York: Routledge. \item Johnson, P. C. D. (2014). Extension of Nakagawa and Schielzeth’s R2 GLMM to random slopes models. Methods in Ecology and Evolution, 5(9), 944–946. \doi{10.1111/2041-210X.12225} \item Nakagawa, S., and Schielzeth, H. (2013). A general and simple method for obtaining R2 from generalized linear mixed-effects models. Methods in Ecology and Evolution, 4(2), 133–142. \doi{10.1111/j.2041-210x.2012.00261.x} \item Nakagawa, S., Johnson, P. C. D., and Schielzeth, H. (2017). The coefficient of determination R2 and intra-class correlation coefficient from generalized linear mixed-effects models revisited and expanded. Journal of The Royal Society Interface, 14(134), 20170213. } } performance/man/model_performance.ivreg.Rd0000644000176200001440000000207614406575225020430 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/model_performance.ivreg.R \name{model_performance.ivreg} \alias{model_performance.ivreg} \title{Performance of instrumental variable regression models} \usage{ \method{model_performance}{ivreg}(model, metrics = "all", verbose = TRUE, ...) } \arguments{ \item{model}{A model.} \item{metrics}{Can be \code{"all"}, \code{"common"} or a character vector of metrics to be computed (some of \code{c("AIC", "AICc", "BIC", "R2", "RMSE", "SIGMA", "Sargan", "Wu_Hausman", "weak_instruments")}). \code{"common"} will compute AIC, BIC, R2 and RMSE.} \item{verbose}{Toggle off warnings.} \item{...}{Arguments passed to or from other methods.} } \description{ Performance of instrumental variable regression models } \details{ \code{model_performance()} correctly detects transformed response and returns the "corrected" AIC and BIC value on the original scale. To get back to the original scale, the likelihood of the model is multiplied by the Jacobian/derivative of the transformation. } performance/man/performance_mae.Rd0000644000176200001440000000133714642733710016753 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/performance_mae.R \name{performance_mae} \alias{performance_mae} \alias{mae} \title{Mean Absolute Error of Models} \usage{ performance_mae(model, ...) mae(model, ...) } \arguments{ \item{model}{A model.} \item{...}{Arguments passed down to \code{lme4::bootMer()} or \code{boot::boot()} for bootstrapped ICC, R2, RMSE etc.; for \code{variance_decomposition()}, arguments are passed down to \code{brms::posterior_predict()}.} } \value{ Numeric, the mean absolute error of \code{model}. } \description{ Compute mean absolute error of models. } \examples{ data(mtcars) m <- lm(mpg ~ hp + gear, data = mtcars) performance_mae(m) } performance/man/check_factorstructure.Rd0000644000176200001440000001060014620351763020215 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check_factorstructure.R \name{check_factorstructure} \alias{check_factorstructure} \alias{check_kmo} \alias{check_sphericity_bartlett} \title{Check suitability of data for Factor Analysis (FA) with Bartlett's Test of Sphericity and KMO} \usage{ check_factorstructure(x, n = NULL, ...) check_kmo(x, n = NULL, ...) check_sphericity_bartlett(x, n = NULL, ...) } \arguments{ \item{x}{A data frame or a correlation matrix. If the latter is passed, \code{n} must be provided.} \item{n}{If a correlation matrix was passed, the number of observations must be specified.} \item{...}{Arguments passed to or from other methods.} } \value{ A list of lists of indices related to sphericity and KMO. } \description{ This checks whether the data is appropriate for Factor Analysis (FA) by running the Bartlett's Test of Sphericity and the Kaiser, Meyer, Olkin (KMO) Measure of Sampling Adequacy (MSA). See \strong{details} below for more information about the interpretation and meaning of each test. } \details{ \subsection{Bartlett's Test of Sphericity}{ Bartlett's (1951) test of sphericity tests whether a matrix (of correlations) is significantly different from an identity matrix (filled with 0). It tests whether the correlation coefficients are all 0. The test computes the probability that the correlation matrix has significant correlations among at least some of the variables in a dataset, a prerequisite for factor analysis to work. While it is often suggested to check whether Bartlett’s test of sphericity is significant before starting with factor analysis, one needs to remember that the test is testing a pretty extreme scenario (that all correlations are non-significant). As the sample size increases, this test tends to be always significant, which makes it not particularly useful or informative in well-powered studies. } \subsection{Kaiser, Meyer, Olkin (KMO)}{ \emph{(Measure of Sampling Adequacy (MSA) for Factor Analysis.)} Kaiser (1970) introduced a Measure of Sampling Adequacy (MSA), later modified by Kaiser and Rice (1974). The Kaiser-Meyer-Olkin (KMO) statistic, which can vary from 0 to 1, indicates the degree to which each variable in a set is predicted without error by the other variables. A value of 0 indicates that the sum of partial correlations is large relative to the sum correlations, indicating factor analysis is likely to be inappropriate. A KMO value close to 1 indicates that the sum of partial correlations is not large relative to the sum of correlations and so factor analysis should yield distinct and reliable factors. It means that patterns of correlations are relatively compact, and so factor analysis should yield distinct and reliable factors. Values smaller than 0.5 suggest that you should either collect more data or rethink which variables to include. Kaiser (1974) suggested that KMO > .9 were marvelous, in the .80s, meritorious, in the .70s, middling, in the .60s, mediocre, in the .50s, miserable, and less than .5, unacceptable. Hair et al. (2006) suggest accepting a value > 0.5. Values between 0.5 and 0.7 are mediocre, and values between 0.7 and 0.8 are good. Variables with individual KMO values below 0.5 could be considered for exclusion them from the analysis (note that you would need to re-compute the KMO indices as they are dependent on the whole dataset). } } \examples{ library(performance) check_factorstructure(mtcars) # One can also pass a correlation matrix r <- cor(mtcars) check_factorstructure(r, n = nrow(mtcars)) } \references{ This function is a wrapper around the \code{KMO} and the \code{cortest.bartlett()} functions in the \strong{psych} package (Revelle, 2016). \itemize{ \item Revelle, W. (2016). How To: Use the psych package for Factor Analysis and data reduction. \item Bartlett, M. S. (1951). The effect of standardization on a Chi-square approximation in factor analysis. Biometrika, 38(3/4), 337-344. \item Kaiser, H. F. (1970). A second generation little jiffy. Psychometrika, 35(4), 401-415. \item Kaiser, H. F., & Rice, J. (1974). Little jiffy, mark IV. Educational and psychological measurement, 34(1), 111-117. \item Kaiser, H. F. (1974). An index of factorial simplicity. Psychometrika, 39(1), 31-36. } } \seealso{ \code{\link[=check_clusterstructure]{check_clusterstructure()}}. } performance/man/check_zeroinflation.Rd0000644000176200001440000001052114600514307017634 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check_zeroinflation.R \name{check_zeroinflation} \alias{check_zeroinflation} \alias{check_zeroinflation.default} \alias{check_zeroinflation.performance_simres} \title{Check for zero-inflation in count models} \usage{ check_zeroinflation(x, ...) \method{check_zeroinflation}{default}(x, tolerance = 0.05, ...) \method{check_zeroinflation}{performance_simres}( x, tolerance = 0.1, alternative = c("two.sided", "less", "greater"), ... ) } \arguments{ \item{x}{Fitted model of class \code{merMod}, \code{glmmTMB}, \code{glm}, or \code{glm.nb} (package \strong{MASS}).} \item{...}{Arguments passed down to \code{\link[=simulate_residuals]{simulate_residuals()}}. This only applies for models with zero-inflation component, or for models of class \code{glmmTMB} from \code{nbinom1} or \code{nbinom2} family.} \item{tolerance}{The tolerance for the ratio of observed and predicted zeros to considered as over- or underfitting zeros. A ratio between 1 +/- \code{tolerance} is considered as OK, while a ratio beyond or below this threshold would indicate over- or underfitting.} \item{alternative}{A character string specifying the alternative hypothesis.} } \value{ A list with information about the amount of predicted and observed zeros in the outcome, as well as the ratio between these two values. } \description{ \code{check_zeroinflation()} checks whether count models are over- or underfitting zeros in the outcome. } \details{ If the amount of observed zeros is larger than the amount of predicted zeros, the model is underfitting zeros, which indicates a zero-inflation in the data. In such cases, it is recommended to use negative binomial or zero-inflated models. In case of negative binomial models, models with zero-inflation component, or hurdle models, the results from \code{check_zeroinflation()} are based on \code{\link[=simulate_residuals]{simulate_residuals()}}, i.e. \code{check_zeroinflation(simulate_residuals(model))} is internally called if necessary. } \section{Tests based on simulated residuals}{ For certain models, resp. model from certain families, tests are based on simulated residuals (see \code{\link[=simulate_residuals]{simulate_residuals()}}). These are usually more accurate for testing such models than the traditionally used Pearson residuals. However, when simulating from more complex models, such as mixed models or models with zero-inflation, there are several important considerations. Arguments specified in \code{...} are passed to \code{\link[=simulate_residuals]{simulate_residuals()}}, which relies on \code{\link[DHARMa:simulateResiduals]{DHARMa::simulateResiduals()}} (and therefore, arguments in \code{...} are passed further down to \emph{DHARMa}). The defaults in DHARMa are set on the most conservative option that works for all models. However, in many cases, the help advises to use different settings in particular situations or for particular models. It is recommended to read the 'Details' in \code{?DHARMa::simulateResiduals} closely to understand the implications of the simulation process and which arguments should be modified to get the most accurate results. } \examples{ \dontshow{if (require("glmmTMB") && require("DHARMa")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} data(Salamanders, package = "glmmTMB") m <- glm(count ~ spp + mined, family = poisson, data = Salamanders) check_zeroinflation(m) # for models with zero-inflation component, it's better to carry out # the check for zero-inflation using simulated residuals m <- glmmTMB::glmmTMB( count ~ spp + mined, ziformula = ~ mined + spp, family = poisson, data = Salamanders ) res <- simulate_residuals(m) check_zeroinflation(res) \dontshow{\}) # examplesIf} } \seealso{ Other functions to check model assumptions and and assess model quality: \code{\link{check_autocorrelation}()}, \code{\link{check_collinearity}()}, \code{\link{check_convergence}()}, \code{\link{check_heteroscedasticity}()}, \code{\link{check_homogeneity}()}, \code{\link{check_model}()}, \code{\link{check_outliers}()}, \code{\link{check_overdispersion}()}, \code{\link{check_predictions}()}, \code{\link{check_singularity}()} } \concept{functions to check model assumptions and and assess model quality} performance/man/check_collinearity.Rd0000644000176200001440000002077214741711171017464 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check_collinearity.R, R/check_concurvity.R \name{check_collinearity} \alias{check_collinearity} \alias{multicollinearity} \alias{check_collinearity.default} \alias{check_collinearity.glmmTMB} \alias{check_concurvity} \title{Check for multicollinearity of model terms} \usage{ check_collinearity(x, ...) multicollinearity(x, ...) \method{check_collinearity}{default}(x, ci = 0.95, verbose = TRUE, ...) \method{check_collinearity}{glmmTMB}( x, component = c("all", "conditional", "count", "zi", "zero_inflated"), ci = 0.95, verbose = TRUE, ... ) check_concurvity(x, ...) } \arguments{ \item{x}{A model object (that should at least respond to \code{vcov()}, and if possible, also to \code{model.matrix()} - however, it also should work without \code{model.matrix()}).} \item{...}{Currently not used.} \item{ci}{Confidence Interval (CI) level for VIF and tolerance values.} \item{verbose}{Toggle off warnings or messages.} \item{component}{For models with zero-inflation component, multicollinearity can be checked for the conditional model (count component, \code{component = "conditional"} or \code{component = "count"}), zero-inflation component (\code{component = "zero_inflated"} or \code{component = "zi"}) or both components (\code{component = "all"}). Following model-classes are currently supported: \code{hurdle}, \code{zeroinfl}, \code{zerocount}, \code{MixMod} and \code{glmmTMB}.} } \value{ A data frame with information about name of the model term, the variance inflation factor and associated confidence intervals, the factor by which the standard error is increased due to possible correlation with other terms, and tolerance values (including confidence intervals), where \code{tolerance = 1/vif}. } \description{ \code{check_collinearity()} checks regression models for multicollinearity by calculating the variance inflation factor (VIF). \code{multicollinearity()} is an alias for \code{check_collinearity()}. \code{check_concurvity()} is a wrapper around \code{mgcv::concurvity()}, and can be considered as a collinearity check for smooth terms in GAMs. Confidence intervals for VIF and tolerance are based on Marcoulides et al. (2019, Appendix B). } \note{ The code to compute the confidence intervals for the VIF and tolerance values was adapted from the Appendix B from the Marcoulides et al. paper. Thus, credits go to these authors the original algorithm. There is also a \href{https://easystats.github.io/see/articles/performance.html}{\code{plot()}-method} implemented in the \href{https://easystats.github.io/see/}{\pkg{see}-package}. } \section{Multicollinearity}{ Multicollinearity should not be confused with a raw strong correlation between predictors. What matters is the association between one or more predictor variables, \emph{conditional on the other variables in the model}. In a nutshell, multicollinearity means that once you know the effect of one predictor, the value of knowing the other predictor is rather low. Thus, one of the predictors doesn't help much in terms of better understanding the model or predicting the outcome. As a consequence, if multicollinearity is a problem, the model seems to suggest that the predictors in question don't seems to be reliably associated with the outcome (low estimates, high standard errors), although these predictors actually are strongly associated with the outcome, i.e. indeed might have strong effect (\emph{McElreath 2020, chapter 6.1}). Multicollinearity might arise when a third, unobserved variable has a causal effect on each of the two predictors that are associated with the outcome. In such cases, the actual relationship that matters would be the association between the unobserved variable and the outcome. Remember: "Pairwise correlations are not the problem. It is the conditional associations - not correlations - that matter." (\emph{McElreath 2020, p. 169}) } \section{Interpretation of the Variance Inflation Factor}{ The variance inflation factor is a measure to analyze the magnitude of multicollinearity of model terms. A VIF less than 5 indicates a low correlation of that predictor with other predictors. A value between 5 and 10 indicates a moderate correlation, while VIF values larger than 10 are a sign for high, not tolerable correlation of model predictors (\emph{James et al. 2013}). The \emph{Increased SE} column in the output indicates how much larger the standard error is due to the association with other predictors conditional on the remaining variables in the model. Note that these thresholds, although commonly used, are also criticized for being too high. \emph{Zuur et al. (2010)} suggest using lower values, e.g. a VIF of 3 or larger may already no longer be considered as "low". } \section{Multicollinearity and Interaction Terms}{ If interaction terms are included in a model, high VIF values are expected. This portion of multicollinearity among the component terms of an interaction is also called "inessential ill-conditioning", which leads to inflated VIF values that are typically seen for models with interaction terms \emph{(Francoeur 2013)}. Centering interaction terms can resolve this issue \emph{(Kim and Jung 2024)}. } \section{Multicollinearity and Polynomial Terms}{ Polynomial transformations are considered a single term and thus VIFs are not calculated between them. } \section{Concurvity for Smooth Terms in Generalized Additive Models}{ \code{check_concurvity()} is a wrapper around \code{mgcv::concurvity()}, and can be considered as a collinearity check for smooth terms in GAMs."Concurvity occurs when some smooth term in a model could be approximated by one or more of the other smooth terms in the model." (see \code{?mgcv::concurvity}). \code{check_concurvity()} returns a column named \emph{VIF}, which is the "worst" measure. While \code{mgcv::concurvity()} range between 0 and 1, the \emph{VIF} value is \code{1 / (1 - worst)}, to make interpretation comparable to classical VIF values, i.e. \code{1} indicates no problems, while higher values indicate increasing lack of identifiability. The \emph{VIF proportion} column equals the "estimate" column from \code{mgcv::concurvity()}, ranging from 0 (no problem) to 1 (total lack of identifiability). } \examples{ m <- lm(mpg ~ wt + cyl + gear + disp, data = mtcars) check_collinearity(m) \dontshow{if (insight::check_if_installed("see", minimum_version = "0.9.1", quietly = TRUE)) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} # plot results x <- check_collinearity(m) plot(x) \dontshow{\}) # examplesIf} } \references{ \itemize{ \item Francoeur, R. B. (2013). Could Sequential Residual Centering Resolve Low Sensitivity in Moderated Regression? Simulations and Cancer Symptom Clusters. Open Journal of Statistics, 03(06), 24-44. \item James, G., Witten, D., Hastie, T., and Tibshirani, R. (eds.). (2013). An introduction to statistical learning: with applications in R. New York: Springer. \item Kim, Y., & Jung, G. (2024). Understanding linear interaction analysis with causal graphs. British Journal of Mathematical and Statistical Psychology, 00, 1–14. \item Marcoulides, K. M., and Raykov, T. (2019). Evaluation of Variance Inflation Factors in Regression Models Using Latent Variable Modeling Methods. Educational and Psychological Measurement, 79(5), 874–882. \item McElreath, R. (2020). Statistical rethinking: A Bayesian course with examples in R and Stan. 2nd edition. Chapman and Hall/CRC. \item Vanhove, J. (2019). Collinearity isn't a disease that needs curing. \href{https://janhove.github.io/posts/2019-09-11-collinearity/}{webpage} \item Zuur AF, Ieno EN, Elphick CS. A protocol for data exploration to avoid common statistical problems: Data exploration. Methods in Ecology and Evolution (2010) 1:3–14. } } \seealso{ \code{\link[see:plot.see_check_collinearity]{see::plot.see_check_collinearity()}} for options to customize the plot. Other functions to check model assumptions and and assess model quality: \code{\link{check_autocorrelation}()}, \code{\link{check_convergence}()}, \code{\link{check_heteroscedasticity}()}, \code{\link{check_homogeneity}()}, \code{\link{check_model}()}, \code{\link{check_outliers}()}, \code{\link{check_overdispersion}()}, \code{\link{check_predictions}()}, \code{\link{check_singularity}()}, \code{\link{check_zeroinflation}()} } \concept{functions to check model assumptions and and assess model quality} performance/man/performance_cv.Rd0000644000176200001440000000420214257537777016634 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/performance_cv.R \name{performance_cv} \alias{performance_cv} \title{Cross-validated model performance} \usage{ performance_cv( model, data = NULL, method = c("holdout", "k_fold", "loo"), metrics = "all", prop = 0.3, k = 5, stack = TRUE, verbose = TRUE, ... ) } \arguments{ \item{model}{A regression model.} \item{data}{Optional. A data frame containing the same variables as \code{model} that will be used as the cross-validation sample.} \item{method}{Character string, indicating the cross-validation method to use: whether holdout (\code{"holdout"}, aka train-test), k-fold (\code{"k_fold"}), or leave-one-out (\code{"loo"}). If \code{data} is supplied, this argument is ignored.} \item{metrics}{Can be \code{"all"}, \code{"common"} or a character vector of metrics to be computed (some of \code{c("ELPD", "Deviance", "MSE", "RMSE", "R2")}). "common" will compute R2 and RMSE.} \item{prop}{If \code{method = "holdout"}, what proportion of the sample to hold out as the test sample?} \item{k}{If \code{method = "k_fold"}, the number of folds to use.} \item{stack}{Logical. If \code{method = "k_fold"}, should performance be computed by stacking residuals from each holdout fold and calculating each metric on the stacked data (\code{TRUE}, default) or should performance be computed by calculating metrics within each holdout fold and averaging performance across each fold (\code{FALSE})?} \item{verbose}{Toggle warnings.} \item{...}{Not used.} } \value{ A data frame with columns for each metric requested, as well as \code{k} if \code{method = "holdout"} and the \code{Method} used for cross-validation. If \code{method = "holdout"} and \code{stack = TRUE}, the standard error (standard deviation across holdout folds) for each metric is also included. } \description{ This function cross-validates regression models in a user-supplied new sample or by using holdout (train-test), k-fold, or leave-one-out cross-validation. } \examples{ model <- lm(mpg ~ wt + cyl, data = mtcars) performance_cv(model) } performance/man/item_difficulty.Rd0000644000176200001440000000421314361743111016776 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/item_difficulty.R \name{item_difficulty} \alias{item_difficulty} \title{Difficulty of Questionnaire Items} \usage{ item_difficulty(x, maximum_value = NULL) } \arguments{ \item{x}{Depending on the function, \code{x} may be a \code{matrix} as returned by the \code{cor()}-function, or a data frame with items (e.g. from a test or questionnaire).} \item{maximum_value}{Numeric value, indicating the maximum value of an item. If \code{NULL} (default), the maximum is taken from the maximum value of all columns in \code{x} (assuming that the maximum value at least appears once in the data). If \code{NA}, each item's maximum value is taken as maximum. If the required maximum value is not present in the data, specify the theoreritcal maximum using \code{maximum_value}.} } \value{ A data frame with three columns: The name(s) of the item(s), the item difficulties for each item, and the ideal item difficulty. } \description{ Compute various measures of internal consistencies for tests or item-scales of questionnaires. } \details{ \emph{Item difficutly} of an item is defined as the quotient of the sum actually achieved for this item of all and the maximum achievable score. This function calculates the item difficulty, which should range between 0.2 and 0.8. Lower values are a signal for more difficult items, while higher values close to one are a sign for easier items. The ideal value for item difficulty is \code{p + (1 - p) / 2}, where \code{p = 1 / max(x)}. In most cases, the ideal item difficulty lies between 0.5 and 0.8. } \examples{ data(mtcars) x <- mtcars[, c("cyl", "gear", "carb", "hp")] item_difficulty(x) } \references{ \itemize{ \item Bortz, J., and Döring, N. (2006). Quantitative Methoden der Datenerhebung. In J. Bortz and N. Döring, Forschungsmethoden und Evaluation. Springer: Berlin, Heidelberg: 137–293 \item Kelava A, Moosbrugger H (2020). Deskriptivstatistische Itemanalyse und Testwertbestimmung. In: Moosbrugger H, Kelava A, editors. Testtheorie und Fragebogenkonstruktion. Berlin, Heidelberg: Springer, 143–158 } } performance/man/r2_nagelkerke.Rd0000644000176200001440000000127014257537777016360 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/r2_nagelkerke.R \name{r2_nagelkerke} \alias{r2_nagelkerke} \title{Nagelkerke's R2} \usage{ r2_nagelkerke(model, ...) } \arguments{ \item{model}{A generalized linear model, including cumulative links resp. multinomial models.} \item{...}{Currently not used.} } \value{ A named vector with the R2 value. } \description{ Calculate Nagelkerke's pseudo-R2. } \examples{ model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") r2_nagelkerke(model) } \references{ Nagelkerke, N. J. (1991). A note on a general definition of the coefficient of determination. Biometrika, 78(3), 691-692. } performance/man/model_performance.lm.Rd0000644000176200001440000000473714666017356017736 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/model_performance.lm.R \name{model_performance.lm} \alias{model_performance.lm} \title{Performance of Regression Models} \usage{ \method{model_performance}{lm}(model, metrics = "all", verbose = TRUE, ...) } \arguments{ \item{model}{A model.} \item{metrics}{Can be \code{"all"}, \code{"common"} or a character vector of metrics to be computed (one or more of \code{"AIC"}, \code{"AICc"}, \code{"BIC"}, \code{"R2"}, \code{"R2_adj"}, \code{"RMSE"}, \code{"SIGMA"}, \code{"LOGLOSS"}, \code{"PCP"}, \code{"SCORE"}). \code{"common"} will compute AIC, BIC, R2 and RMSE.} \item{verbose}{Toggle off warnings.} \item{...}{Arguments passed to or from other methods.} } \value{ A data frame (with one row) and one column per "index" (see \code{metrics}). } \description{ Compute indices of model performance for regression models. } \details{ Depending on \code{model}, following indices are computed: \itemize{ \item \strong{AIC}: Akaike's Information Criterion, see \code{?stats::AIC} \item \strong{AICc}: Second-order (or small sample) AIC with a correction for small sample sizes \item \strong{BIC}: Bayesian Information Criterion, see \code{?stats::BIC} \item \strong{R2}: r-squared value, see \code{\link[=r2]{r2()}} \item \strong{R2_adj}: adjusted r-squared, see \code{\link[=r2]{r2()}} \item \strong{RMSE}: root mean squared error, see \code{\link[=performance_rmse]{performance_rmse()}} \item \strong{SIGMA}: residual standard deviation, see \code{\link[insight:get_sigma]{insight::get_sigma()}} \item \strong{LOGLOSS}: Log-loss, see \code{\link[=performance_logloss]{performance_logloss()}} \item \strong{SCORE_LOG}: score of logarithmic proper scoring rule, see \code{\link[=performance_score]{performance_score()}} \item \strong{SCORE_SPHERICAL}: score of spherical proper scoring rule, see \code{\link[=performance_score]{performance_score()}} \item \strong{PCP}: percentage of correct predictions, see \code{\link[=performance_pcp]{performance_pcp()}} } \code{model_performance()} correctly detects transformed response and returns the "corrected" AIC and BIC value on the original scale. To get back to the original scale, the likelihood of the model is multiplied by the Jacobian/derivative of the transformation. } \examples{ model <- lm(mpg ~ wt + cyl, data = mtcars) model_performance(model) model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") model_performance(model) } performance/man/check_itemscale.Rd0000644000176200001440000000573714561136140016735 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check_itemscale.R \name{check_itemscale} \alias{check_itemscale} \title{Describe Properties of Item Scales} \usage{ check_itemscale(x, factor_index = NULL) } \arguments{ \item{x}{An object of class \code{parameters_pca}, as returned by \code{\link[parameters:principal_components]{parameters::principal_components()}}, or a data frame.} \item{factor_index}{If \code{x} is a data frame, \code{factor_index} must be specified. It must be a numeric vector of same length as number of columns in \code{x}, where each element is the index of the factor to which the respective column in \code{x}.} } \value{ A list of data frames, with related measures of internal consistencies of each subscale. } \description{ Compute various measures of internal consistencies applied to (sub)scales, which items were extracted using \code{parameters::principal_components()}. } \details{ \code{check_itemscale()} calculates various measures of internal consistencies, such as Cronbach's alpha, item difficulty or discrimination etc. on subscales which were built from several items. Subscales are retrieved from the results of \code{\link[parameters:principal_components]{parameters::principal_components()}}, i.e. based on how many components were extracted from the PCA, \code{check_itemscale()} retrieves those variables that belong to a component and calculates the above mentioned measures. } \note{ \itemize{ \item \emph{Item difficulty} should range between 0.2 and 0.8. Ideal value is \code{p+(1-p)/2} (which mostly is between 0.5 and 0.8). See \code{\link[=item_difficulty]{item_difficulty()}} for details. \item For \emph{item discrimination}, acceptable values are 0.20 or higher; the closer to 1.00 the better. See \code{\link[=item_reliability]{item_reliability()}} for more details. \item In case the total \emph{Cronbach's alpha} value is below the acceptable cut-off of 0.7 (mostly if an index has few items), the \emph{mean inter-item-correlation} is an alternative measure to indicate acceptability. Satisfactory range lies between 0.2 and 0.4. See also \code{\link[=item_intercor]{item_intercor()}}. } } \examples{ \dontshow{if (require("parameters") && require("psych")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} # data generation from '?prcomp', slightly modified C <- chol(S <- toeplitz(0.9^(0:15))) set.seed(17) X <- matrix(rnorm(1600), 100, 16) Z <- X \%*\% C pca <- parameters::principal_components( as.data.frame(Z), rotation = "varimax", n = 3 ) pca check_itemscale(pca) # as data frame check_itemscale( as.data.frame(Z), factor_index = parameters::closest_component(pca) ) \dontshow{\}) # examplesIf} } \references{ \itemize{ \item Briggs SR, Cheek JM (1986) The role of factor analysis in the development and evaluation of personality scales. Journal of Personality, 54(1), 106-148. doi: 10.1111/j.1467-6494.1986.tb00391.x } } performance/man/r2_mcfadden.Rd0000644000176200001440000000177414335664246016007 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/r2_mcfadden.R \name{r2_mcfadden} \alias{r2_mcfadden} \title{McFadden's R2} \usage{ r2_mcfadden(model, ...) } \arguments{ \item{model}{Generalized linear or multinomial logit (\code{mlogit}) model.} \item{...}{Currently not used.} } \value{ For most models, a list with McFadden's R2 and adjusted McFadden's R2 value. For some models, only McFadden's R2 is available. } \description{ Calculates McFadden's pseudo R2. } \examples{ if (require("mlogit")) { data("Fishing", package = "mlogit") Fish <- mlogit.data(Fishing, varying = c(2:9), shape = "wide", choice = "mode") model <- mlogit(mode ~ price + catch, data = Fish) r2_mcfadden(model) } } \references{ \itemize{ \item McFadden, D. (1987). Regression-based specification tests for the multinomial logit model. Journal of econometrics, 34(1-2), 63-82. \item McFadden, D. (1973). Conditional logit analysis of qualitative choice behavior. } } performance/man/check_sphericity.Rd0000644000176200001440000000200414501027040017122 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check_sphericity.R \name{check_sphericity} \alias{check_sphericity} \title{Check model for violation of sphericity} \usage{ check_sphericity(x, ...) } \arguments{ \item{x}{A model object.} \item{...}{Arguments passed to \code{car::Anova}.} } \value{ Invisibly returns the p-values of the test statistics. A p-value < 0.05 indicates a violation of sphericity. } \description{ Check model for violation of sphericity. For \link[=check_factorstructure]{Bartlett's Test of Sphericity} (used for correlation matrices and factor analyses), see \link{check_sphericity_bartlett}. } \examples{ \dontshow{if (require("car") && require("carData")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} data(Soils, package = "carData") soils.mod <- lm( cbind(pH, N, Dens, P, Ca, Mg, K, Na, Conduc) ~ Block + Contour * Depth, data = Soils ) check_sphericity(Manova(soils.mod)) \dontshow{\}) # examplesIf} } performance/man/check_symmetry.Rd0000644000176200001440000000115414501027040016635 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check_symmetry.R \name{check_symmetry} \alias{check_symmetry} \title{Check distribution symmetry} \usage{ check_symmetry(x, ...) } \arguments{ \item{x}{Model or numeric vector} \item{...}{Not used.} } \description{ Uses Hotelling and Solomons test of symmetry by testing if the standardized nonparametric skew (\eqn{\frac{(Mean - Median)}{SD}}) is different than 0. \cr\cr This is an underlying assumption of Wilcoxon signed-rank test. } \examples{ V <- suppressWarnings(wilcox.test(mtcars$mpg)) check_symmetry(V) } performance/man/r2_bayes.Rd0000644000176200001440000001060214645233345015333 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/r2_bayes.R \name{r2_bayes} \alias{r2_bayes} \alias{r2_posterior} \alias{r2_posterior.brmsfit} \alias{r2_posterior.stanreg} \alias{r2_posterior.BFBayesFactor} \title{Bayesian R2} \usage{ r2_bayes(model, robust = TRUE, ci = 0.95, verbose = TRUE, ...) r2_posterior(model, ...) \method{r2_posterior}{brmsfit}(model, verbose = TRUE, ...) \method{r2_posterior}{stanreg}(model, verbose = TRUE, ...) \method{r2_posterior}{BFBayesFactor}(model, average = FALSE, prior_odds = NULL, verbose = TRUE, ...) } \arguments{ \item{model}{A Bayesian regression model (from \strong{brms}, \strong{rstanarm}, \strong{BayesFactor}, etc).} \item{robust}{Logical, if \code{TRUE}, the median instead of mean is used to calculate the central tendency of the variances.} \item{ci}{Value or vector of probability of the CI (between 0 and 1) to be estimated.} \item{verbose}{Toggle off warnings.} \item{...}{Arguments passed to \code{r2_posterior()}.} \item{average}{Compute model-averaged index? See \code{\link[bayestestR:weighted_posteriors]{bayestestR::weighted_posteriors()}}.} \item{prior_odds}{Optional vector of prior odds for the models compared to the first model (or the denominator, for \code{BFBayesFactor} objects). For \code{data.frame}s, this will be used as the basis of weighting.} } \value{ A list with the Bayesian R2 value. For mixed models, a list with the Bayesian R2 value and the marginal Bayesian R2 value. The standard errors and credible intervals for the R2 values are saved as attributes. } \description{ Compute R2 for Bayesian models. For mixed models (including a random part), it additionally computes the R2 related to the fixed effects only (marginal R2). While \code{r2_bayes()} returns a single R2 value, \code{r2_posterior()} returns a posterior sample of Bayesian R2 values. } \details{ \code{r2_bayes()} returns an "unadjusted" R2 value. See \code{\link[=r2_loo]{r2_loo()}} to calculate a LOO-adjusted R2, which comes conceptually closer to an adjusted R2 measure. For mixed models, the conditional and marginal R2 are returned. The marginal R2 considers only the variance of the fixed effects, while the conditional R2 takes both the fixed and random effects into account. Technically, since \code{r2_bayes()} relies on \code{\link[rstantools:bayes_R2]{rstantools::bayes_R2()}}, the "marginal" R2 calls \code{bayes_R2(re.form = NA)}, while the "conditional" R2 calls \code{bayes_R2(re.form = NULL)}. The \code{re.form} argument is passed to \code{\link[rstantools:posterior_epred]{rstantools::posterior_epred()}}, which is internally called in \code{bayes_R2()}. Note that for "marginal" and "conditional", we refer to the wording suggested by \emph{Nakagawa et al. 2017}. Thus, we don't use the term "marginal" in the sense that the random effects are integrated out, but are "ignored". \code{r2_posterior()} is the actual workhorse for \code{r2_bayes()} and returns a posterior sample of Bayesian R2 values. } \examples{ \dontshow{if (require("rstanarm") && require("rstantools") && require("brms") && require("RcppEigen")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} library(performance) \donttest{ model <- suppressWarnings(rstanarm::stan_glm( mpg ~ wt + cyl, data = mtcars, chains = 1, iter = 500, refresh = 0, show_messages = FALSE )) r2_bayes(model) model <- suppressWarnings(rstanarm::stan_lmer( Petal.Length ~ Petal.Width + (1 | Species), data = iris, chains = 1, iter = 500, refresh = 0 )) r2_bayes(model) } \donttest{ model <- suppressWarnings(brms::brm( mpg ~ wt + cyl, data = mtcars, silent = 2, refresh = 0 )) r2_bayes(model) model <- suppressWarnings(brms::brm( Petal.Length ~ Petal.Width + (1 | Species), data = iris, silent = 2, refresh = 0 )) r2_bayes(model) } \dontshow{\}) # examplesIf} } \references{ \itemize{ \item Gelman, A., Goodrich, B., Gabry, J., and Vehtari, A. (2018). R-squared for Bayesian regression models. The American Statistician, 1–6. \doi{10.1080/00031305.2018.1549100} \item Nakagawa, S., Johnson, P. C. D., and Schielzeth, H. (2017). The coefficient of determination R2 and intra-class correlation coefficient from generalized linear mixed-effects models revisited and expanded. Journal of The Royal Society Interface, 14(134), 20170213. } } performance/man/item_split_half.Rd0000644000176200001440000000245514257537777017016 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/item_split_half.R \name{item_split_half} \alias{item_split_half} \title{Split-Half Reliability} \usage{ item_split_half(x, digits = 3) } \arguments{ \item{x}{A matrix or a data frame.} \item{digits}{Amount of digits for returned values.} } \value{ A list with two elements: the split-half reliability \code{splithalf} and the Spearman-Brown corrected split-half reliability \code{spearmanbrown}. } \description{ Compute various measures of internal consistencies for tests or item-scales of questionnaires. } \details{ This function calculates the split-half reliability for items in \code{x}, including the Spearman-Brown adjustment. Splitting is done by selecting odd versus even columns in \code{x}. A value closer to 1 indicates greater internal consistency. } \examples{ data(mtcars) x <- mtcars[, c("cyl", "gear", "carb", "hp")] item_split_half(x) } \references{ \itemize{ \item Spearman C. 1910. Correlation calculated from faulty data. British Journal of Psychology (3): 271-295. \doi{10.1111/j.2044-8295.1910.tb00206.x} \item Brown W. 1910. Some experimental results in the correlation of mental abilities. British Journal of Psychology (3): 296-322. \doi{10.1111/j.2044-8295.1910.tb00207.x} } } performance/man/performance_aicc.Rd0000644000176200001440000000616414706655512017117 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/performance_aicc.R \name{performance_aicc} \alias{performance_aicc} \alias{performance_aic} \alias{performance_aic.default} \alias{performance_aic.lmerMod} \title{Compute the AIC or second-order AIC} \usage{ performance_aicc(x, ...) performance_aic(x, ...) \method{performance_aic}{default}(x, estimator = "ML", verbose = TRUE, ...) \method{performance_aic}{lmerMod}(x, estimator = "REML", verbose = TRUE, ...) } \arguments{ \item{x}{A model object.} \item{...}{Currently not used.} \item{estimator}{Only for linear models. Corresponds to the different estimators for the standard deviation of the errors. If \code{estimator = "ML"} (default, except for \code{performance_aic()} when the model object is of class \code{lmerMod}), the scaling is done by \code{n} (the biased ML estimator), which is then equivalent to using \code{AIC(logLik())}. Setting it to \code{"REML"} will give the same results as \code{AIC(logLik(..., REML = TRUE))}.} \item{verbose}{Toggle warnings.} } \value{ Numeric, the AIC or AICc value. } \description{ Compute the AIC or the second-order Akaike's information criterion (AICc). \code{performance_aic()} is a small wrapper that returns the AIC, however, for models with a transformed response variable, \code{performance_aic()} returns the corrected AIC value (see 'Examples'). It is a generic function that also works for some models that don't have a AIC method (like Tweedie models). \code{performance_aicc()} returns the second-order (or "small sample") AIC that incorporates a correction for small sample sizes. } \details{ \code{performance_aic()} correctly detects transformed response and, unlike \code{stats::AIC()}, returns the "corrected" AIC value on the original scale. To get back to the original scale, the likelihood of the model is multiplied by the Jacobian/derivative of the transformation. In case it is not possible to return the corrected AIC value, a warning is given that the corrected log-likelihood value could not be computed. } \examples{ m <- lm(mpg ~ wt + cyl + gear + disp, data = mtcars) AIC(m) performance_aicc(m) # correct AIC for models with transformed response variable data("mtcars") mtcars$mpg <- floor(mtcars$mpg) model <- lm(log(mpg) ~ factor(cyl), mtcars) # wrong AIC, not corrected for log-transformation AIC(model) # performance_aic() correctly detects transformed response and # returns corrected AIC performance_aic(model) \dontrun{ # there are a few exceptions where the corrected log-likelihood values # cannot be returned. The following exampe gives a warning. model <- lm(1 / mpg ~ factor(cyl), mtcars) performance_aic(model) } } \references{ \itemize{ \item Akaike, H. (1973) Information theory as an extension of the maximum likelihood principle. In: Second International Symposium on Information Theory, pp. 267-281. Petrov, B.N., Csaki, F., Eds, Akademiai Kiado, Budapest. \item Hurvich, C. M., Tsai, C.-L. (1991) Bias of the corrected AIC criterion for underfitted regression and time series models. Biometrika 78, 499–509. } } performance/man/model_performance.kmeans.Rd0000644000176200001440000000134514257537777020606 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/model_performance.kmeans.R \name{model_performance.kmeans} \alias{model_performance.kmeans} \title{Model summary for k-means clustering} \usage{ \method{model_performance}{kmeans}(model, verbose = TRUE, ...) } \arguments{ \item{model}{Object of type \code{kmeans}.} \item{verbose}{Toggle off warnings.} \item{...}{Arguments passed to or from other methods.} } \description{ Model summary for k-means clustering } \examples{ # a 2-dimensional example x <- rbind( matrix(rnorm(100, sd = 0.3), ncol = 2), matrix(rnorm(100, mean = 1, sd = 0.3), ncol = 2) ) colnames(x) <- c("x", "y") model <- kmeans(x, 2) model_performance(model) } performance/man/check_dag.Rd0000644000176200001440000002234014741714104015511 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check_dag.R \name{check_dag} \alias{check_dag} \alias{as.dag} \title{Check correct model adjustment for identifying causal effects} \usage{ check_dag( ..., outcome = NULL, exposure = NULL, adjusted = NULL, latent = NULL, effect = c("all", "total", "direct"), coords = NULL ) as.dag(x, ...) } \arguments{ \item{...}{One or more formulas, which are converted into \strong{dagitty} syntax. First element may also be model object. If a model objects is provided, its formula is used as first formula, and all independent variables will be used for the \code{adjusted} argument. See 'Details' and 'Examples'.} \item{outcome}{Name of the dependent variable (outcome), as character string or as formula. Must be a valid name from the formulas provided in \code{...}. If not set, the first dependent variable from the formulas is used.} \item{exposure}{Name of the exposure variable (as character string or formula), for which the direct and total causal effect on the \code{outcome} should be checked. Must be a valid name from the formulas provided in \code{...}. If not set, the first independent variable from the formulas is used.} \item{adjusted}{A character vector or formula with names of variables that are adjusted for in the model, e.g. \code{adjusted = c("x1", "x2")} or \code{adjusted = ~ x1 + x2}. If a model object is provided in \code{...}, any values in \code{adjusted} will be overwritten by the model's independent variables.} \item{latent}{A character vector with names of latent variables in the model.} \item{effect}{Character string, indicating which effect to check. Can be \code{"all"} (default), \code{"total"}, or \code{"direct"}.} \item{coords}{Coordinates of the variables when plotting the DAG. The coordinates can be provided in three different ways: \itemize{ \item a list with two elements, \code{x} and \code{y}, which both are named vectors of numerics. The names correspond to the variable names in the DAG, and the values for \code{x} and \code{y} indicate the x/y coordinates in the plot. \item a list with elements that correspond to the variables in the DAG. Each element is a numeric vector of length two with x- and y-coordinate. \item a data frame with three columns: \code{x}, \code{y} and \code{name} (which contains the variable names). } See 'Examples'.} \item{x}{An object of class \code{check_dag}, as returned by \code{check_dag()}.} } \value{ An object of class \code{check_dag}, which can be visualized with \code{plot()}. The returned object also inherits from class \code{dagitty} and thus can be used with all functions from the \strong{ggdag} and \strong{dagitty} packages. } \description{ The purpose of \code{check_dag()} is to build, check and visualize your model based on directed acyclic graphs (DAG). The function checks if a model is correctly adjusted for identifying specific relationships of variables, especially directed (maybe also "causal") effects for given exposures on an outcome. In case of incorrect adjustments, the function suggests the minimal required variables that should be adjusted for (sometimes also called "controlled for"), i.e. variables that \emph{at least} need to be included in the model. Depending on the goal of the analysis, it is still possible to add more variables to the model than just the minimally required adjustment sets. \code{check_dag()} is a convenient wrapper around \code{ggdag::dagify()}, \code{dagitty::adjustmentSets()} and \code{dagitty::adjustedNodes()} to check correct adjustment sets. It returns a \strong{dagitty} object that can be visualized with \code{plot()}. \code{as.dag()} is a small convenient function to return the dagitty-string, which can be used for the online-tool from the dagitty-website. } \section{Specifying the DAG formulas}{ The formulas have following syntax: \itemize{ \item One-directed paths: On the \emph{left-hand-side} is the name of the variables where causal effects point to (direction of the arrows, in dagitty-language). On the \emph{right-hand-side} are all variables where causal effects are assumed to come from. For example, the formula \code{Y ~ X1 + X2}, paths directed from both \code{X1} and \code{X2} to \code{Y} are assumed. \item Bi-directed paths: Use \verb{~~} to indicate bi-directed paths. For example, \code{Y ~~ X} indicates that the path between \code{Y} and \code{X} is bi-directed, and the arrow points in both directions. Bi-directed paths often indicate unmeasured cause, or unmeasured confounding, of the two involved variables. } } \section{Minimally required adjustments}{ The function checks if the model is correctly adjusted for identifying the direct and total effects of the exposure on the outcome. If the model is correctly specified, no adjustment is needed to estimate the direct effect. If the model is not correctly specified, the function suggests the minimally required variables that should be adjusted for. The function distinguishes between direct and total effects, and checks if the model is correctly adjusted for both. If the model is cyclic, the function stops and suggests to remove cycles from the model. Note that it sometimes could be necessary to try out different combinations of suggested adjustments, because \code{check_dag()} can not always detect whether \emph{at least} one of several variables is required, or whether adjustments should be done for \emph{all} listed variables. It can be useful to copy the dagitty-code (using \code{as.dag()}, which prints the dagitty-string into the console) into the dagitty-website and play around with different adjustments. } \section{Direct and total effects}{ The direct effect of an exposure on an outcome is the effect that is not mediated by any other variable in the model. The total effect is the sum of the direct and indirect effects. The function checks if the model is correctly adjusted for identifying the direct and total effects of the exposure on the outcome. } \section{Why are DAGs important - the Table 2 fallacy}{ Correctly thinking about and identifying the relationships between variables is important when it comes to reporting coefficients from regression models that mutually adjust for "confounders" or include covariates. Different coefficients might have different interpretations, depending on their relationship to other variables in the model. Sometimes, a regression coefficient represents the direct effect of an exposure on an outcome, but sometimes it must be interpreted as total effect, due to the involvement of mediating effects. This problem is also called "Table 2 fallacy" (\emph{Westreich and Greenland 2013}). DAG helps visualizing and thereby focusing the relationships of variables in a regression model to detect missing adjustments or over-adjustment. } \examples{ \dontshow{if (all(insight::check_if_installed(c("ggdag", "dagitty", "see"), quietly = TRUE))) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} # no adjustment needed check_dag( y ~ x + b, outcome = "y", exposure = "x" ) # incorrect adjustment dag <- check_dag( y ~ x + b + c, x ~ b, outcome = "y", exposure = "x" ) dag plot(dag) # After adjusting for `b`, the model is correctly specified dag <- check_dag( y ~ x + b + c, x ~ b, outcome = "y", exposure = "x", adjusted = "b" ) dag # using formula interface for arguments "outcome", "exposure" and "adjusted" check_dag( y ~ x + b + c, x ~ b, outcome = ~y, exposure = ~x, adjusted = ~ b + c ) # if not provided, "outcome" is taken from first formula, same for "exposure" # thus, we can simplify the above expression to check_dag( y ~ x + b + c, x ~ b, adjusted = ~ b + c ) # use specific layout for the DAG dag <- check_dag( score ~ exp + b + c, exp ~ b, outcome = "score", exposure = "exp", coords = list( # x-coordinates for all nodes x = c(score = 5, exp = 4, b = 3, c = 3), # y-coordinates for all nodes y = c(score = 3, exp = 3, b = 2, c = 4) ) ) plot(dag) # alternative way of providing the coordinates dag <- check_dag( score ~ exp + b + c, exp ~ b, outcome = "score", exposure = "exp", coords = list( # x/y coordinates for each node score = c(5, 3), exp = c(4, 3), b = c(3, 2), c = c(3, 4) ) ) plot(dag) # Objects returned by `check_dag()` can be used with "ggdag" or "dagitty" ggdag::ggdag_status(dag) # Using a model object to extract information about outcome, # exposure and adjusted variables data(mtcars) m <- lm(mpg ~ wt + gear + disp + cyl, data = mtcars) dag <- check_dag( m, wt ~ disp + cyl, wt ~ am ) dag plot(dag) \dontshow{\}) # examplesIf} } \references{ \itemize{ \item Rohrer, J. M. (2018). Thinking clearly about correlations and causation: Graphical causal models for observational data. Advances in Methods and Practices in Psychological Science, 1(1), 27–42. \doi{10.1177/2515245917745629} \item Westreich, D., & Greenland, S. (2013). The Table 2 Fallacy: Presenting and Interpreting Confounder and Modifier Coefficients. American Journal of Epidemiology, 177(4), 292–298. \doi{10.1093/aje/kws412} } } performance/man/check_normality.Rd0000644000176200001440000000442114741713304016775 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check_normality.R \name{check_normality} \alias{check_normality} \alias{check_normality.merMod} \title{Check model for (non-)normality of residuals.} \usage{ check_normality(x, ...) \method{check_normality}{merMod}(x, effects = c("fixed", "random"), ...) } \arguments{ \item{x}{A model object.} \item{...}{Currently not used.} \item{effects}{Should normality for residuals (\code{"fixed"}) or random effects (\code{"random"}) be tested? Only applies to mixed-effects models. May be abbreviated.} } \value{ The p-value of the test statistics. A p-value < 0.05 indicates a significant deviation from normal distribution. } \description{ Check model for (non-)normality of residuals. } \details{ \code{check_normality()} calls \code{stats::shapiro.test} and checks the standardized residuals (or studentized residuals for mixed models) for normal distribution. Note that this formal test almost always yields significant results for the distribution of residuals and visual inspection (e.g. Q-Q plots) are preferable. For generalized linear models, no formal statistical test is carried out. Rather, there's only a \code{plot()} method for GLMs. This plot shows a half-normal Q-Q plot of the absolute value of the standardized deviance residuals is shown (in line with changes in \code{plot.lm()} for R 4.3+). } \note{ For mixed-effects models, studentized residuals, and \emph{not} standardized residuals, are used for the test. There is also a \href{https://easystats.github.io/see/articles/performance.html}{\code{plot()}-method} implemented in the \href{https://easystats.github.io/see/}{\strong{see}-package}. } \examples{ \dontshow{if (insight::check_if_installed("see", minimum_version = "0.9.1", quietly = TRUE)) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} m <<- lm(mpg ~ wt + cyl + gear + disp, data = mtcars) check_normality(m) # plot results x <- check_normality(m) plot(x) \donttest{ # QQ-plot plot(check_normality(m), type = "qq") # PP-plot plot(check_normality(m), type = "pp") } \dontshow{\}) # examplesIf} } \seealso{ \code{\link[see:plot.see_check_normality]{see::plot.see_check_normality()}} for options to customize the plot. } performance/man/compare_performance.Rd0000644000176200001440000001213714546750702017642 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/compare_performance.R \name{compare_performance} \alias{compare_performance} \title{Compare performance of different models} \usage{ compare_performance( ..., metrics = "all", rank = FALSE, estimator = "ML", verbose = TRUE ) } \arguments{ \item{...}{Multiple model objects (also of different classes).} \item{metrics}{Can be \code{"all"}, \code{"common"} or a character vector of metrics to be computed. See related \code{\link[=model_performance]{documentation()}} of object's class for details.} \item{rank}{Logical, if \code{TRUE}, models are ranked according to 'best' overall model performance. See 'Details'.} \item{estimator}{Only for linear models. Corresponds to the different estimators for the standard deviation of the errors. If \code{estimator = "ML"} (default, except for \code{performance_aic()} when the model object is of class \code{lmerMod}), the scaling is done by \code{n} (the biased ML estimator), which is then equivalent to using \code{AIC(logLik())}. Setting it to \code{"REML"} will give the same results as \code{AIC(logLik(..., REML = TRUE))}.} \item{verbose}{Toggle warnings.} } \value{ A data frame with one row per model and one column per "index" (see \code{metrics}). } \description{ \code{compare_performance()} computes indices of model performance for different models at once and hence allows comparison of indices across models. } \details{ \subsection{Model Weights}{ When information criteria (IC) are requested in \code{metrics} (i.e., any of \code{"all"}, \code{"common"}, \code{"AIC"}, \code{"AICc"}, \code{"BIC"}, \code{"WAIC"}, or \code{"LOOIC"}), model weights based on these criteria are also computed. For all IC except LOOIC, weights are computed as \code{w = exp(-0.5 * delta_ic) / sum(exp(-0.5 * delta_ic))}, where \code{delta_ic} is the difference between the model's IC value and the smallest IC value in the model set (Burnham and Anderson, 2002). For LOOIC, weights are computed as "stacking weights" using \code{\link[loo:loo_model_weights]{loo::stacking_weights()}}. } \subsection{Ranking Models}{ When \code{rank = TRUE}, a new column \code{Performance_Score} is returned. This score ranges from 0\\% to 100\\%, higher values indicating better model performance. Note that all score value do not necessarily sum up to 100\\%. Rather, calculation is based on normalizing all indices (i.e. rescaling them to a range from 0 to 1), and taking the mean value of all indices for each model. This is a rather quick heuristic, but might be helpful as exploratory index. \cr \cr In particular when models are of different types (e.g. mixed models, classical linear models, logistic regression, ...), not all indices will be computed for each model. In case where an index can't be calculated for a specific model type, this model gets an \code{NA} value. All indices that have any \code{NA}s are excluded from calculating the performance score. \cr \cr There is a \code{plot()}-method for \code{compare_performance()}, which creates a "spiderweb" plot, where the different indices are normalized and larger values indicate better model performance. Hence, points closer to the center indicate worse fit indices (see \href{https://easystats.github.io/see/articles/performance.html}{online-documentation} for more details). } \subsection{REML versus ML estimator}{ By default, \code{estimator = "ML"}, which means that values from information criteria (AIC, AICc, BIC) for specific model classes (like models from \emph{lme4}) are based on the ML-estimator, while the default behaviour of \code{AIC()} for such classes is setting \code{REML = TRUE}. This default is intentional, because comparing information criteria based on REML fits is usually not valid (it might be useful, though, if all models share the same fixed effects - however, this is usually not the case for nested models, which is a prerequisite for the LRT). Set \code{estimator = "REML"} explicitly return the same (AIC/...) values as from the defaults in \code{AIC.merMod()}. } } \note{ There is also a \href{https://easystats.github.io/see/articles/performance.html}{\code{plot()}-method} implemented in the \href{https://easystats.github.io/see/}{\pkg{see}-package}. } \examples{ \dontshow{if (require("lme4")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} data(iris) lm1 <- lm(Sepal.Length ~ Species, data = iris) lm2 <- lm(Sepal.Length ~ Species + Petal.Length, data = iris) lm3 <- lm(Sepal.Length ~ Species * Petal.Length, data = iris) compare_performance(lm1, lm2, lm3) compare_performance(lm1, lm2, lm3, rank = TRUE) m1 <- lm(mpg ~ wt + cyl, data = mtcars) m2 <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") m3 <- lme4::lmer(Petal.Length ~ Sepal.Length + (1 | Species), data = iris) compare_performance(m1, m2, m3) \dontshow{\}) # examplesIf} } \references{ Burnham, K. P., and Anderson, D. R. (2002). \emph{Model selection and multimodel inference: A practical information-theoretic approach} (2nd ed.). Springer-Verlag. \doi{10.1007/b97636} } performance/man/check_multimodal.Rd0000644000176200001440000000272414504243270017127 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check_multimodal.R \name{check_multimodal} \alias{check_multimodal} \title{Check if a distribution is unimodal or multimodal} \usage{ check_multimodal(x, ...) } \arguments{ \item{x}{A numeric vector or a data frame.} \item{...}{Arguments passed to or from other methods.} } \description{ For univariate distributions (one-dimensional vectors), this functions performs a Ameijeiras-Alonso et al. (2018) excess mass test. For multivariate distributions (data frames), it uses mixture modelling. However, it seems that it always returns a significant result (suggesting that the distribution is multimodal). A better method might be needed here. } \examples{ \dontshow{if (require("multimode") && require("mclust")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} \donttest{ # Univariate x <- rnorm(1000) check_multimodal(x) x <- c(rnorm(1000), rnorm(1000, 2)) check_multimodal(x) # Multivariate m <- data.frame( x = rnorm(200), y = rbeta(200, 2, 1) ) plot(m$x, m$y) check_multimodal(m) m <- data.frame( x = c(rnorm(100), rnorm(100, 4)), y = c(rbeta(100, 2, 1), rbeta(100, 1, 4)) ) plot(m$x, m$y) check_multimodal(m) } \dontshow{\}) # examplesIf} } \references{ \itemize{ \item Ameijeiras-Alonso, J., Crujeiras, R. M., and Rodríguez-Casal, A. (2019). Mode testing, critical bandwidth and excess mass. Test, 28(3), 900-919. } } performance/man/performance_pcp.Rd0000644000176200001440000000471614335664246017005 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/performance_pcp.R \name{performance_pcp} \alias{performance_pcp} \title{Percentage of Correct Predictions} \usage{ performance_pcp(model, ci = 0.95, method = "Herron", verbose = TRUE) } \arguments{ \item{model}{Model with binary outcome.} \item{ci}{The level of the confidence interval.} \item{method}{Name of the method to calculate the PCP (see 'Details'). Default is \code{"Herron"}. May be abbreviated.} \item{verbose}{Toggle off warnings.} } \value{ A list with several elements: the percentage of correct predictions of the full and the null model, their confidence intervals, as well as the chi-squared and p-value from the Likelihood-Ratio-Test between the full and null model. } \description{ Percentage of correct predictions (PCP) for models with binary outcome. } \details{ \code{method = "Gelman-Hill"} (or \code{"gelman_hill"}) computes the PCP based on the proposal from \emph{Gelman and Hill 2017, 99}, which is defined as the proportion of cases for which the deterministic prediction is wrong, i.e. the proportion where the predicted probability is above 0.5, although y=0 (and vice versa) (see also \emph{Herron 1999, 90}). \code{method = "Herron"} (or \code{"herron"}) computes a modified version of the PCP (\emph{Herron 1999, 90-92}), which is the sum of predicted probabilities, where y=1, plus the sum of 1 - predicted probabilities, where y=0, divided by the number of observations. This approach is said to be more accurate. The PCP ranges from 0 to 1, where values closer to 1 mean that the model predicts the outcome better than models with an PCP closer to 0. In general, the PCP should be above 0.5 (i.e. 50\\%), the closer to one, the better. Furthermore, the PCP of the full model should be considerably above the null model's PCP. The likelihood-ratio test indicates whether the model has a significantly better fit than the null-model (in such cases, p < 0.05). } \examples{ data(mtcars) m <- glm(formula = vs ~ hp + wt, family = binomial, data = mtcars) performance_pcp(m) performance_pcp(m, method = "Gelman-Hill") } \references{ \itemize{ \item Herron, M. (1999). Postestimation Uncertainty in Limited Dependent Variable Models. Political Analysis, 8, 83–98. \item Gelman, A., and Hill, J. (2007). Data analysis using regression and multilevel/hierarchical models. Cambridge; New York: Cambridge University Press, 99. } } performance/man/model_performance.stanreg.Rd0000644000176200001440000000673614570063447020766 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/model_performance.bayesian.R \name{model_performance.stanreg} \alias{model_performance.stanreg} \alias{model_performance.BFBayesFactor} \title{Performance of Bayesian Models} \usage{ \method{model_performance}{stanreg}(model, metrics = "all", verbose = TRUE, ...) \method{model_performance}{BFBayesFactor}( model, metrics = "all", verbose = TRUE, average = FALSE, prior_odds = NULL, ... ) } \arguments{ \item{model}{Object of class \code{stanreg} or \code{brmsfit}.} \item{metrics}{Can be \code{"all"}, \code{"common"} or a character vector of metrics to be computed (some of \code{c("LOOIC", "WAIC", "R2", "R2_adj", "RMSE", "SIGMA", "LOGLOSS", "SCORE")}). \code{"common"} will compute LOOIC, WAIC, R2 and RMSE.} \item{verbose}{Toggle off warnings.} \item{...}{Arguments passed to or from other methods.} \item{average}{Compute model-averaged index? See \code{\link[bayestestR:weighted_posteriors]{bayestestR::weighted_posteriors()}}.} \item{prior_odds}{Optional vector of prior odds for the models compared to the first model (or the denominator, for \code{BFBayesFactor} objects). For \code{data.frame}s, this will be used as the basis of weighting.} } \value{ A data frame (with one row) and one column per "index" (see \code{metrics}). } \description{ Compute indices of model performance for (general) linear models. } \details{ Depending on \code{model}, the following indices are computed: \itemize{ \item \strong{ELPD}: expected log predictive density. Larger ELPD values mean better fit. See \code{\link[=looic]{looic()}}. \item \strong{LOOIC}: leave-one-out cross-validation (LOO) information criterion. Lower LOOIC values mean better fit. See \code{\link[=looic]{looic()}}. \item \strong{WAIC}: widely applicable information criterion. Lower WAIC values mean better fit. See \code{?loo::waic}. \item \strong{R2}: r-squared value, see \code{\link[=r2_bayes]{r2_bayes()}}. \item \strong{R2_adjusted}: LOO-adjusted r-squared, see \code{\link[=r2_loo]{r2_loo()}}. \item \strong{RMSE}: root mean squared error, see \code{\link[=performance_rmse]{performance_rmse()}}. \item \strong{SIGMA}: residual standard deviation, see \code{\link[insight:get_sigma]{insight::get_sigma()}}. \item \strong{LOGLOSS}: Log-loss, see \code{\link[=performance_logloss]{performance_logloss()}}. \item \strong{SCORE_LOG}: score of logarithmic proper scoring rule, see \code{\link[=performance_score]{performance_score()}}. \item \strong{SCORE_SPHERICAL}: score of spherical proper scoring rule, see \code{\link[=performance_score]{performance_score()}}. \item \strong{PCP}: percentage of correct predictions, see \code{\link[=performance_pcp]{performance_pcp()}}. } } \examples{ \dontshow{if (require("rstanarm") && require("rstantools")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} \donttest{ model <- suppressWarnings(rstanarm::stan_glm( mpg ~ wt + cyl, data = mtcars, chains = 1, iter = 500, refresh = 0 )) model_performance(model) model <- suppressWarnings(rstanarm::stan_glmer( mpg ~ wt + cyl + (1 | gear), data = mtcars, chains = 1, iter = 500, refresh = 0 )) model_performance(model) } \dontshow{\}) # examplesIf} } \references{ Gelman, A., Goodrich, B., Gabry, J., and Vehtari, A. (2018). R-squared for Bayesian regression models. The American Statistician, The American Statistician, 1-6. } \seealso{ \link{r2_bayes} } performance/man/check_clusterstructure.Rd0000644000176200001440000000421514620351763020425 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check_clusterstructure.R \name{check_clusterstructure} \alias{check_clusterstructure} \title{Check suitability of data for clustering} \usage{ check_clusterstructure(x, standardize = TRUE, distance = "euclidean", ...) } \arguments{ \item{x}{A data frame.} \item{standardize}{Standardize the data frame before clustering (default).} \item{distance}{Distance method used. Other methods than "euclidean" (default) are exploratory in the context of clustering tendency. See \code{\link[stats:dist]{stats::dist()}} for list of available methods.} \item{...}{Arguments passed to or from other methods.} } \value{ The H statistic (numeric) } \description{ This checks whether the data is appropriate for clustering using the Hopkins' H statistic of given data. If the value of Hopkins statistic is close to 0 (below 0.5), then we can reject the null hypothesis and conclude that the dataset is significantly clusterable. A value for H lower than 0.25 indicates a clustering tendency at the \verb{90\%} confidence level. The visual assessment of cluster tendency (VAT) approach (Bezdek and Hathaway, 2002) consists in investigating the heatmap of the ordered dissimilarity matrix. Following this, one can potentially detect the clustering tendency by counting the number of square shaped blocks along the diagonal. } \examples{ \donttest{ library(performance) check_clusterstructure(iris[, 1:4]) plot(check_clusterstructure(iris[, 1:4])) } } \references{ \itemize{ \item Lawson, R. G., & Jurs, P. C. (1990). New index for clustering tendency and its application to chemical problems. Journal of chemical information and computer sciences, 30(1), 36-41. \item Bezdek, J. C., & Hathaway, R. J. (2002, May). VAT: A tool for visual assessment of (cluster) tendency. In Proceedings of the 2002 International Joint Conference on Neural Networks. IJCNN02 (3), 2225-2230. IEEE. } } \seealso{ \code{\link[=check_kmo]{check_kmo()}}, \code{\link[=check_sphericity_bartlett]{check_sphericity_bartlett()}} and \code{\link[=check_factorstructure]{check_factorstructure()}}. } performance/man/check_overdispersion.Rd0000644000176200001440000001316214600514307020030 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check_overdispersion.R \name{check_overdispersion} \alias{check_overdispersion} \alias{check_overdispersion.performance_simres} \title{Check overdispersion (and underdispersion) of GL(M)M's} \usage{ check_overdispersion(x, ...) \method{check_overdispersion}{performance_simres}(x, alternative = c("two.sided", "less", "greater"), ...) } \arguments{ \item{x}{Fitted model of class \code{merMod}, \code{glmmTMB}, \code{glm}, or \code{glm.nb} (package \strong{MASS}), or an object returned by \code{simulate_residuals()}.} \item{...}{Arguments passed down to \code{\link[=simulate_residuals]{simulate_residuals()}}. This only applies for models with zero-inflation component, or for models of class \code{glmmTMB} from \code{nbinom1} or \code{nbinom2} family.} \item{alternative}{A character string specifying the alternative hypothesis.} } \value{ A list with results from the overdispersion test, like chi-squared statistics, p-value or dispersion ratio. } \description{ \code{check_overdispersion()} checks generalized linear (mixed) models for overdispersion (and underdispersion). } \details{ Overdispersion occurs when the observed variance is higher than the variance of a theoretical model. For Poisson models, variance increases with the mean and, therefore, variance usually (roughly) equals the mean value. If the variance is much higher, the data are "overdispersed". A less common case is underdispersion, where the variance is much lower than the mean. } \section{Interpretation of the Dispersion Ratio}{ If the dispersion ratio is close to one, a Poisson model fits well to the data. Dispersion ratios larger than one indicate overdispersion, thus a negative binomial model or similar might fit better to the data. Dispersion ratios much smaller than one indicate underdispersion. A p-value < .05 indicates either overdispersion or underdispersion (the first being more common). } \section{Overdispersion in Poisson Models}{ For Poisson models, the overdispersion test is based on the code from \emph{Gelman and Hill (2007), page 115}. } \section{Overdispersion in Negative Binomial or Zero-Inflated Models}{ For negative binomial (mixed) models or models with zero-inflation component, the overdispersion test is based simulated residuals (see \code{\link[=simulate_residuals]{simulate_residuals()}}). } \section{Overdispersion in Mixed Models}{ For \code{merMod}- and \code{glmmTMB}-objects, \code{check_overdispersion()} is based on the code in the \href{http://bbolker.github.io/mixedmodels-misc/glmmFAQ.html}{GLMM FAQ}, section \emph{How can I deal with overdispersion in GLMMs?}. Note that this function only returns an \emph{approximate} estimate of an overdispersion parameter. Using this approach would be inaccurate for zero-inflated or negative binomial mixed models (fitted with \code{glmmTMB}), thus, in such cases, the overdispersion test is based on \code{\link[=simulate_residuals]{simulate_residuals()}} (which is identical to \code{check_overdispersion(simulate_residuals(model))}). } \section{How to fix Overdispersion}{ Overdispersion can be fixed by either modeling the dispersion parameter, or by choosing a different distributional family (like Quasi-Poisson, or negative binomial, see \emph{Gelman and Hill (2007), pages 115-116}). } \section{Tests based on simulated residuals}{ For certain models, resp. model from certain families, tests are based on simulated residuals (see \code{\link[=simulate_residuals]{simulate_residuals()}}). These are usually more accurate for testing such models than the traditionally used Pearson residuals. However, when simulating from more complex models, such as mixed models or models with zero-inflation, there are several important considerations. Arguments specified in \code{...} are passed to \code{\link[=simulate_residuals]{simulate_residuals()}}, which relies on \code{\link[DHARMa:simulateResiduals]{DHARMa::simulateResiduals()}} (and therefore, arguments in \code{...} are passed further down to \emph{DHARMa}). The defaults in DHARMa are set on the most conservative option that works for all models. However, in many cases, the help advises to use different settings in particular situations or for particular models. It is recommended to read the 'Details' in \code{?DHARMa::simulateResiduals} closely to understand the implications of the simulation process and which arguments should be modified to get the most accurate results. } \examples{ \dontshow{if (getRversion() >= "4.0.0" && require("glmmTMB")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} data(Salamanders, package = "glmmTMB") m <- glm(count ~ spp + mined, family = poisson, data = Salamanders) check_overdispersion(m) \dontshow{\}) # examplesIf} } \references{ \itemize{ \item Bolker B et al. (2017): \href{http://bbolker.github.io/mixedmodels-misc/glmmFAQ.html}{GLMM FAQ.} \item Gelman, A., and Hill, J. (2007). Data analysis using regression and multilevel/hierarchical models. Cambridge; New York: Cambridge University Press. } } \seealso{ Other functions to check model assumptions and and assess model quality: \code{\link{check_autocorrelation}()}, \code{\link{check_collinearity}()}, \code{\link{check_convergence}()}, \code{\link{check_heteroscedasticity}()}, \code{\link{check_homogeneity}()}, \code{\link{check_model}()}, \code{\link{check_outliers}()}, \code{\link{check_predictions}()}, \code{\link{check_singularity}()}, \code{\link{check_zeroinflation}()} } \concept{functions to check model assumptions and and assess model quality} performance/man/check_convergence.Rd0000644000176200001440000000751114504243270017255 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check_convergence.R \name{check_convergence} \alias{check_convergence} \title{Convergence test for mixed effects models} \usage{ check_convergence(x, tolerance = 0.001, ...) } \arguments{ \item{x}{A \code{merMod} or \code{glmmTMB}-object.} \item{tolerance}{Indicates up to which value the convergence result is accepted. The smaller \code{tolerance} is, the stricter the test will be.} \item{...}{Currently not used.} } \value{ \code{TRUE} if convergence is fine and \code{FALSE} if convergence is suspicious. Additionally, the convergence value is returned as attribute. } \description{ \code{check_convergence()} provides an alternative convergence test for \code{merMod}-objects. } \section{Convergence and log-likelihood}{ Convergence problems typically arise when the model hasn't converged to a solution where the log-likelihood has a true maximum. This may result in unreliable and overly complex (or non-estimable) estimates and standard errors. } \section{Inspect model convergence}{ \strong{lme4} performs a convergence-check (see \code{?lme4::convergence}), however, as as discussed \href{https://github.com/lme4/lme4/issues/120}{here} and suggested by one of the lme4-authors in \href{https://github.com/lme4/lme4/issues/120#issuecomment-39920269}{this comment}, this check can be too strict. \code{check_convergence()} thus provides an alternative convergence test for \code{merMod}-objects. } \section{Resolving convergence issues}{ Convergence issues are not easy to diagnose. The help page on \code{?lme4::convergence} provides most of the current advice about how to resolve convergence issues. Another clue might be large parameter values, e.g. estimates (on the scale of the linear predictor) larger than 10 in (non-identity link) generalized linear model \emph{might} indicate \href{https://stats.oarc.ucla.edu/other/mult-pkg/faq/general/faqwhat-is-complete-or-quasi-complete-separation-in-logisticprobit-regression-and-how-do-we-deal-with-them/}{complete separation}. Complete separation can be addressed by regularization, e.g. penalized regression or Bayesian regression with appropriate priors on the fixed effects. } \section{Convergence versus Singularity}{ Note the different meaning between singularity and convergence: singularity indicates an issue with the "true" best estimate, i.e. whether the maximum likelihood estimation for the variance-covariance matrix of the random effects is positive definite or only semi-definite. Convergence is a question of whether we can assume that the numerical optimization has worked correctly or not. } \examples{ \dontshow{if (require("lme4") && require("glmmTMB")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} data(cbpp, package = "lme4") set.seed(1) cbpp$x <- rnorm(nrow(cbpp)) cbpp$x2 <- runif(nrow(cbpp)) model <- lme4::glmer( cbind(incidence, size - incidence) ~ period + x + x2 + (1 + x | herd), data = cbpp, family = binomial() ) check_convergence(model) \donttest{ model <- suppressWarnings(glmmTMB::glmmTMB( Sepal.Length ~ poly(Petal.Width, 4) * poly(Petal.Length, 4) + (1 + poly(Petal.Width, 4) | Species), data = iris )) check_convergence(model) } \dontshow{\}) # examplesIf} } \seealso{ Other functions to check model assumptions and and assess model quality: \code{\link{check_autocorrelation}()}, \code{\link{check_collinearity}()}, \code{\link{check_heteroscedasticity}()}, \code{\link{check_homogeneity}()}, \code{\link{check_model}()}, \code{\link{check_outliers}()}, \code{\link{check_overdispersion}()}, \code{\link{check_predictions}()}, \code{\link{check_singularity}()}, \code{\link{check_zeroinflation}()} } \concept{functions to check model assumptions and and assess model quality} performance/man/performance_hosmer.Rd0000644000176200001440000000214414257537777017524 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/performance_hosmer.R \name{performance_hosmer} \alias{performance_hosmer} \title{Hosmer-Lemeshow goodness-of-fit test} \usage{ performance_hosmer(model, n_bins = 10) } \arguments{ \item{model}{A \code{glm}-object with binomial-family.} \item{n_bins}{Numeric, the number of bins to divide the data.} } \value{ An object of class \code{hoslem_test} with following values: \code{chisq}, the Hosmer-Lemeshow chi-squared statistic; \code{df}, degrees of freedom and \code{p.value} the p-value for the goodness-of-fit test. } \description{ Check model quality of logistic regression models. } \details{ A well-fitting model shows \emph{no} significant difference between the model and the observed data, i.e. the reported p-value should be greater than 0.05. } \examples{ model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") performance_hosmer(model) } \references{ Hosmer, D. W., and Lemeshow, S. (2000). Applied Logistic Regression. Hoboken, NJ, USA: John Wiley and Sons, Inc. \doi{10.1002/0471722146} } performance/man/check_singularity.Rd0000644000176200001440000001400214666017356017337 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check_singularity.R \name{check_singularity} \alias{check_singularity} \title{Check mixed models for boundary fits} \usage{ check_singularity(x, tolerance = 1e-05, ...) } \arguments{ \item{x}{A mixed model.} \item{tolerance}{Indicates up to which value the convergence result is accepted. The larger \code{tolerance} is, the stricter the test will be.} \item{...}{Currently not used.} } \value{ \code{TRUE} if the model fit is singular. } \description{ Check mixed models for boundary fits. } \details{ If a model is "singular", this means that some dimensions of the variance-covariance matrix have been estimated as exactly zero. This often occurs for mixed models with complex random effects structures. "While singular models are statistically well defined (it is theoretically sensible for the true maximum likelihood estimate to correspond to a singular fit), there are real concerns that (1) singular fits correspond to overfitted models that may have poor power; (2) chances of numerical problems and mis-convergence are higher for singular models (e.g. it may be computationally difficult to compute profile confidence intervals for such models); (3) standard inferential procedures such as Wald statistics and likelihood ratio tests may be inappropriate." (\emph{lme4 Reference Manual}) There is no gold-standard about how to deal with singularity and which random-effects specification to choose. Beside using fully Bayesian methods (with informative priors), proposals in a frequentist framework are: \itemize{ \item avoid fitting overly complex models, such that the variance-covariance matrices can be estimated precisely enough (\emph{Matuschek et al. 2017}) \item use some form of model selection to choose a model that balances predictive accuracy and overfitting/type I error (\emph{Bates et al. 2015}, \emph{Matuschek et al. 2017}) \item "keep it maximal", i.e. fit the most complex model consistent with the experimental design, removing only terms required to allow a non-singular fit (\emph{Barr et al. 2013}) \item since version 1.1.9, the \strong{glmmTMB} package allows to use priors in a frequentist framework, too. One recommendation is to use a Gamma prior (\emph{Chung et al. 2013}). The mean may vary from 1 to very large values (like \code{1e8}), and the shape parameter should be set to a value of 2.5. You can then \code{update()} your model with the specified prior. In \strong{glmmTMB}, the code would look like this: \if{html}{\out{
}}\preformatted{# "model" is an object of class gmmmTMB prior <- data.frame( prior = "gamma(1, 2.5)", # mean can be 1, but even 1e8 class = "ranef" # for random effects ) model_with_priors <- update(model, priors = prior) }\if{html}{\out{
}} Large values for the mean parameter of the Gamma prior have no large impact on the random effects variances in terms of a "bias". Thus, if \code{1} doesn't fix the singular fit, you can safely try larger values. } Note the different meaning between singularity and convergence: singularity indicates an issue with the "true" best estimate, i.e. whether the maximum likelihood estimation for the variance-covariance matrix of the random effects is positive definite or only semi-definite. Convergence is a question of whether we can assume that the numerical optimization has worked correctly or not. } \examples{ \dontshow{if (require("lme4") && require("glmmTMB")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} data(sleepstudy, package = "lme4") set.seed(123) sleepstudy$mygrp <- sample(1:5, size = 180, replace = TRUE) sleepstudy$mysubgrp <- NA for (i in 1:5) { filter_group <- sleepstudy$mygrp == i sleepstudy$mysubgrp[filter_group] <- sample(1:30, size = sum(filter_group), replace = TRUE) } model <- lme4::lmer( Reaction ~ Days + (1 | mygrp / mysubgrp) + (1 | Subject), data = sleepstudy ) check_singularity(model) \dontrun{ # Fixing singularity issues using priors in glmmTMB # Example taken from `vignette("priors", package = "glmmTMB")` dat <- readRDS(system.file( "vignette_data", "gophertortoise.rds", package = "glmmTMB" )) model <- glmmTMB::glmmTMB( shells ~ prev + offset(log(Area)) + factor(year) + (1 | Site), family = poisson, data = dat ) # singular fit check_singularity(model) # impose Gamma prior on random effects parameters prior <- data.frame( prior = "gamma(1, 2.5)", # mean can be 1, but even 1e8 class = "ranef" # for random effects ) model_with_priors <- update(model, priors = prior) # no singular fit check_singularity(model_with_priors) } \dontshow{\}) # examplesIf} } \references{ \itemize{ \item Bates D, Kliegl R, Vasishth S, Baayen H. Parsimonious Mixed Models. arXiv:1506.04967, June 2015. \item Barr DJ, Levy R, Scheepers C, Tily HJ. Random effects structure for confirmatory hypothesis testing: Keep it maximal. Journal of Memory and Language, 68(3):255-278, April 2013. \item Chung Y, Rabe-Hesketh S, Dorie V, Gelman A, and Liu J. 2013. "A Nondegenerate Penalized Likelihood Estimator for Variance Parameters in Multilevel Models." Psychometrika 78 (4): 685–709. \doi{10.1007/s11336-013-9328-2} \item Matuschek H, Kliegl R, Vasishth S, Baayen H, Bates D. Balancing type I error and power in linear mixed models. Journal of Memory and Language, 94:305-315, 2017. \item lme4 Reference Manual, \url{https://cran.r-project.org/package=lme4} } } \seealso{ Other functions to check model assumptions and and assess model quality: \code{\link{check_autocorrelation}()}, \code{\link{check_collinearity}()}, \code{\link{check_convergence}()}, \code{\link{check_heteroscedasticity}()}, \code{\link{check_homogeneity}()}, \code{\link{check_model}()}, \code{\link{check_outliers}()}, \code{\link{check_overdispersion}()}, \code{\link{check_predictions}()}, \code{\link{check_zeroinflation}()} } \concept{functions to check model assumptions and and assess model quality} performance/man/reexports.Rd0000644000176200001440000000103214620351763015653 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/reexports.R \docType{import} \name{reexports} \alias{reexports} \alias{display} \alias{print_md} \alias{print_html} \title{Objects exported from other packages} \keyword{internal} \description{ These objects are imported from other packages. Follow the links below to see their documentation. \describe{ \item{insight}{\code{\link[insight]{display}}, \code{\link[insight:display]{print_html}}, \code{\link[insight:display]{print_md}}} }} performance/man/r2_ferrari.Rd0000644000176200001440000000241314642733710015661 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/r2_ferarri.R \name{r2_ferrari} \alias{r2_ferrari} \alias{r2_ferrari.default} \title{Ferrari's and Cribari-Neto's R2} \usage{ r2_ferrari(model, ...) \method{r2_ferrari}{default}(model, correct_bounds = FALSE, ...) } \arguments{ \item{model}{Generalized linear, in particular beta-regression model.} \item{...}{Currently not used.} \item{correct_bounds}{Logical, whether to correct the bounds of the response variable to avoid 0 and 1. If \code{TRUE}, the response variable is normalized and "compressed", i.e. zeros and ones are excluded.} } \value{ A list with the pseudo R2 value. } \description{ Calculates Ferrari's and Cribari-Neto's pseudo R2 (for beta-regression models). } \examples{ \dontshow{if (require("betareg")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} data("GasolineYield", package = "betareg") model <- betareg::betareg(yield ~ batch + temp, data = GasolineYield) r2_ferrari(model) \dontshow{\}) # examplesIf} } \references{ \itemize{ \item Ferrari, S., and Cribari-Neto, F. (2004). Beta Regression for Modelling Rates and Proportions. Journal of Applied Statistics, 31(7), 799–815. \doi{10.1080/0266476042000214501} } } performance/man/check_model.Rd0000644000176200001440000003035514723555505016073 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check_model.R \name{check_model} \alias{check_model} \alias{check_model.default} \title{Visual check of model assumptions} \usage{ check_model(x, ...) \method{check_model}{default}( x, panel = TRUE, check = "all", detrend = TRUE, bandwidth = "nrd", type = "density", residual_type = NULL, show_dots = NULL, size_dot = 2, size_line = 0.8, size_title = 12, size_axis_title = base_size, base_size = 10, alpha = 0.2, alpha_dot = 0.8, colors = c("#3aaf85", "#1b6ca8", "#cd201f"), theme = "see::theme_lucid", verbose = FALSE, ... ) } \arguments{ \item{x}{A model object.} \item{...}{Arguments passed down to the individual check functions, especially to \code{check_predictions()} and \code{binned_residuals()}.} \item{panel}{Logical, if \code{TRUE}, plots are arranged as panels; else, single plots for each diagnostic are returned.} \item{check}{Character vector, indicating which checks for should be performed and plotted. May be one or more of \code{"all"}, \code{"vif"}, \code{"qq"}, \code{"normality"}, \code{"linearity"}, \code{"ncv"}, \code{"homogeneity"}, \code{"outliers"}, \code{"reqq"}, \code{"pp_check"}, \code{"binned_residuals"} or \code{"overdispersion"}. Note that not all check apply to all type of models (see 'Details'). \code{"reqq"} is a QQ-plot for random effects and only available for mixed models. \code{"ncv"} is an alias for \code{"linearity"}, and checks for non-constant variance, i.e. for heteroscedasticity, as well as the linear relationship. By default, all possible checks are performed and plotted.} \item{detrend}{Logical. Should Q-Q/P-P plots be detrended? Defaults to \code{TRUE} for linear models or when \code{residual_type = "normal"}. Defaults to \code{FALSE} for QQ plots based on simulated residuals (i.e. when \code{residual_type = "simulated"}).} \item{bandwidth}{A character string indicating the smoothing bandwidth to be used. Unlike \code{stats::density()}, which used \code{"nrd0"} as default, the default used here is \code{"nrd"} (which seems to give more plausible results for non-Gaussian models). When problems with plotting occur, try to change to a different value.} \item{type}{Plot type for the posterior predictive checks plot. Can be \code{"density"}, \code{"discrete_dots"}, \code{"discrete_interval"} or \code{"discrete_both"} (the \verb{discrete_*} options are appropriate for models with discrete - binary, integer or ordinal etc. - outcomes).} \item{residual_type}{Character, indicating the type of residuals to be used. For non-Gaussian models, the default is \code{"simulated"}, which uses simulated residuals. These are based on \code{\link[=simulate_residuals]{simulate_residuals()}} and thus uses the \strong{DHARMa} package to return randomized quantile residuals. For Gaussian models, the default is \code{"normal"}, which uses the default residuals from the model. Setting \code{residual_type = "normal"} for non-Gaussian models will use a half-normal Q-Q plot of the absolute value of the standardized deviance residuals.} \item{show_dots}{Logical, if \code{TRUE}, will show data points in the plot. Set to \code{FALSE} for models with many observations, if generating the plot is too time-consuming. By default, \code{show_dots = NULL}. In this case \code{check_model()} tries to guess whether performance will be poor due to a very large model and thus automatically shows or hides dots.} \item{size_dot, size_line}{Size of line and dot-geoms.} \item{base_size, size_title, size_axis_title}{Base font size for axis and plot titles.} \item{alpha, alpha_dot}{The alpha level of the confidence bands and dot-geoms. Scalar from 0 to 1.} \item{colors}{Character vector with color codes (hex-format). Must be of length 3. First color is usually used for reference lines, second color for dots, and third color for outliers or extreme values.} \item{theme}{String, indicating the name of the plot-theme. Must be in the format \code{"package::theme_name"} (e.g. \code{"ggplot2::theme_minimal"}).} \item{verbose}{If \code{FALSE} (default), suppress most warning messages.} } \value{ The data frame that is used for plotting. } \description{ Visual check of various model assumptions (normality of residuals, normality of random effects, linear relationship, homogeneity of variance, multicollinearity). If \code{check_model()} doesn't work as expected, try setting \code{verbose = TRUE} to get hints about possible problems. } \details{ For Bayesian models from packages \strong{rstanarm} or \strong{brms}, models will be "converted" to their frequentist counterpart, using \href{https://easystats.github.io/bayestestR/reference/convert_bayesian_as_frequentist.html}{\code{bayestestR::bayesian_as_frequentist}}. A more advanced model-check for Bayesian models will be implemented at a later stage. See also the related \href{https://easystats.github.io/performance/articles/check_model.html}{vignette}. } \note{ This function just prepares the data for plotting. To create the plots, \strong{see} needs to be installed. Furthermore, this function suppresses all possible warnings. In case you observe suspicious plots, please refer to the dedicated functions (like \code{check_collinearity()}, \code{check_normality()} etc.) to get informative messages and warnings. } \section{Posterior Predictive Checks}{ Posterior predictive checks can be used to look for systematic discrepancies between real and simulated data. It helps to see whether the type of model (distributional family) fits well to the data. See \code{\link[=check_predictions]{check_predictions()}} for further details. } \section{Linearity Assumption}{ The plot \strong{Linearity} checks the assumption of linear relationship. However, the spread of dots also indicate possible heteroscedasticity (i.e. non-constant variance, hence, the alias \code{"ncv"} for this plot), thus it shows if residuals have non-linear patterns. This plot helps to see whether predictors may have a non-linear relationship with the outcome, in which case the reference line may roughly indicate that relationship. A straight and horizontal line indicates that the model specification seems to be ok. But for instance, if the line would be U-shaped, some of the predictors probably should better be modeled as quadratic term. See \code{\link[=check_heteroscedasticity]{check_heteroscedasticity()}} for further details. \strong{Some caution is needed} when interpreting these plots. Although these plots are helpful to check model assumptions, they do not necessarily indicate so-called "lack of fit", e.g. missed non-linear relationships or interactions. Thus, it is always recommended to also look at \href{https://strengejacke.github.io/ggeffects/articles/introduction_partial_residuals.html}{effect plots, including partial residuals}. } \section{Homogeneity of Variance}{ This plot checks the assumption of equal variance (homoscedasticity). The desired pattern would be that dots spread equally above and below a straight, horizontal line and show no apparent deviation. } \section{Influential Observations}{ This plot is used to identify influential observations. If any points in this plot fall outside of Cook’s distance (the dashed lines) then it is considered an influential observation. See \code{\link[=check_outliers]{check_outliers()}} for further details. } \section{Multicollinearity}{ This plot checks for potential collinearity among predictors. In a nutshell, multicollinearity means that once you know the effect of one predictor, the value of knowing the other predictor is rather low. Multicollinearity might arise when a third, unobserved variable has a causal effect on each of the two predictors that are associated with the outcome. In such cases, the actual relationship that matters would be the association between the unobserved variable and the outcome. See \code{\link[=check_collinearity]{check_collinearity()}} for further details. } \section{Normality of Residuals}{ This plot is used to determine if the residuals of the regression model are normally distributed. Usually, dots should fall along the line. If there is some deviation (mostly at the tails), this indicates that the model doesn't predict the outcome well for that range that shows larger deviations from the line. For generalized linear models and when \code{residual_type = "normal"}, a half-normal Q-Q plot of the absolute value of the standardized deviance residuals is shown, however, the interpretation of the plot remains the same. See \code{\link[=check_normality]{check_normality()}} for further details. Usually, for generalized linear (mixed) models, a test for uniformity of residuals based on simulated residuals is conducted (see next section). } \section{Uniformity of Residuals}{ Fore non-Gaussian models, when \code{residual_type = "simulated"} (the default for generalized linear (mixed) models), residuals are not expected to be normally distributed. In this case, the created Q-Q plot checks the uniformity of residuals. The interpretation of the plot is the same as for the normal Q-Q plot. See \code{\link[=simulate_residuals]{simulate_residuals()}} and \code{\link[=check_residuals]{check_residuals()}} for further details. } \section{Overdispersion}{ For count models, an \emph{overdispersion plot} is shown. Overdispersion occurs when the observed variance is higher than the variance of a theoretical model. For Poisson models, variance increases with the mean and, therefore, variance usually (roughly) equals the mean value. If the variance is much higher, the data are "overdispersed". See \code{\link[=check_overdispersion]{check_overdispersion()}} for further details. } \section{Binned Residuals}{ For models from binomial families, a \emph{binned residuals plot} is shown. Binned residual plots are achieved by cutting the the data into bins and then plotting the average residual versus the average fitted value for each bin. If the model were true, one would expect about 95\% of the residuals to fall inside the error bounds. See \code{\link[=binned_residuals]{binned_residuals()}} for further details. } \section{Residuals for (Generalized) Linear Models}{ Plots that check the homogeneity of variance use standardized Pearson's residuals for generalized linear models, and standardized residuals for linear models. The plots for the normality of residuals (with overlayed normal curve) and for the linearity assumption use the default residuals for \code{lm} and \code{glm} (which are deviance residuals for \code{glm}). The Q-Q plots use simulated residuals (see \code{\link[=simulate_residuals]{simulate_residuals()}}) for non-Gaussian models and standardized residuals for linear models. } \section{Troubleshooting}{ For models with many observations, or for more complex models in general, generating the plot might become very slow. One reason might be that the underlying graphic engine becomes slow for plotting many data points. In such cases, setting the argument \code{show_dots = FALSE} might help. Furthermore, look at the \code{check} argument and see if some of the model checks could be skipped, which also increases performance. If \code{check_model()} doesn't work as expected, try setting \code{verbose = TRUE} to get hints about possible problems. } \examples{ \dontshow{if (require("lme4")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} \donttest{ m <- lm(mpg ~ wt + cyl + gear + disp, data = mtcars) check_model(m) data(sleepstudy, package = "lme4") m <- lme4::lmer(Reaction ~ Days + (Days | Subject), sleepstudy) check_model(m, panel = FALSE) } \dontshow{\}) # examplesIf} } \seealso{ Other functions to check model assumptions and and assess model quality: \code{\link{check_autocorrelation}()}, \code{\link{check_collinearity}()}, \code{\link{check_convergence}()}, \code{\link{check_heteroscedasticity}()}, \code{\link{check_homogeneity}()}, \code{\link{check_outliers}()}, \code{\link{check_overdispersion}()}, \code{\link{check_predictions}()}, \code{\link{check_singularity}()}, \code{\link{check_zeroinflation}()} } \concept{functions to check model assumptions and and assess model quality} performance/man/looic.Rd0000644000176200001440000000171014520417117014723 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/looic.R \name{looic} \alias{looic} \title{LOO-related Indices for Bayesian regressions.} \usage{ looic(model, verbose = TRUE) } \arguments{ \item{model}{A Bayesian regression model.} \item{verbose}{Toggle off warnings.} } \value{ A list with four elements, the ELPD, LOOIC and their standard errors. } \description{ Compute LOOIC (leave-one-out cross-validation (LOO) information criterion) and ELPD (expected log predictive density) for Bayesian regressions. For LOOIC and ELPD, smaller and larger values are respectively indicative of a better fit. } \examples{ \dontshow{if (require("rstanarm")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} \donttest{ model <- suppressWarnings(rstanarm::stan_glm( mpg ~ wt + cyl, data = mtcars, chains = 1, iter = 500, refresh = 0 )) looic(model) } \dontshow{\}) # examplesIf} } performance/man/icc.Rd0000644000176200001440000003310614675461510014367 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/icc.R \name{icc} \alias{icc} \alias{variance_decomposition} \title{Intraclass Correlation Coefficient (ICC)} \usage{ icc( model, by_group = FALSE, tolerance = 1e-05, ci = NULL, iterations = 100, ci_method = NULL, null_model = NULL, approximation = "lognormal", model_component = NULL, verbose = TRUE, ... ) variance_decomposition(model, re_formula = NULL, robust = TRUE, ci = 0.95, ...) } \arguments{ \item{model}{A (Bayesian) mixed effects model.} \item{by_group}{Logical, if \code{TRUE}, \code{icc()} returns the variance components for each random-effects level (if there are multiple levels). See 'Details'.} \item{tolerance}{Tolerance for singularity check of random effects, to decide whether to compute random effect variances or not. Indicates up to which value the convergence result is accepted. The larger tolerance is, the stricter the test will be. See \code{\link[performance:check_singularity]{performance::check_singularity()}}.} \item{ci}{Confidence resp. credible interval level. For \code{icc()}, \code{r2()}, and \code{rmse()}, confidence intervals are based on bootstrapped samples from the ICC, R2 or RMSE value. See \code{iterations}.} \item{iterations}{Number of bootstrap-replicates when computing confidence intervals for the ICC, R2, RMSE etc.} \item{ci_method}{Character string, indicating the bootstrap-method. Should be \code{NULL} (default), in which case \code{lme4::bootMer()} is used for bootstrapped confidence intervals. However, if bootstrapped intervals cannot be calculated this way, try \code{ci_method = "boot"}, which falls back to \code{boot::boot()}. This may successfully return bootstrapped confidence intervals, but bootstrapped samples may not be appropriate for the multilevel structure of the model. There is also an option \code{ci_method = "analytical"}, which tries to calculate analytical confidence assuming a chi-squared distribution. However, these intervals are rather inaccurate and often too narrow. It is recommended to calculate bootstrapped confidence intervals for mixed models.} \item{null_model}{Optional, a null model to compute the random effect variances, which is passed to \code{\link[insight:get_variance]{insight::get_variance()}}. Usually only required if calculation of r-squared or ICC fails when \code{null_model} is not specified. If calculating the null model takes longer and you already have fit the null model, you can pass it here, too, to speed up the process.} \item{approximation}{Character string, indicating the approximation method for the distribution-specific (observation level, or residual) variance. Only applies to non-Gaussian models. Can be \code{"lognormal"} (default), \code{"delta"} or \code{"trigamma"}. For binomial models, the default is the \emph{theoretical} distribution specific variance, however, it can also be \code{"observation_level"}. See \emph{Nakagawa et al. 2017}, in particular supplement 2, for details.} \item{model_component}{For models that can have a zero-inflation component, specify for which component variances should be returned. If \code{NULL} or \code{"full"} (the default), both the conditional and the zero-inflation component are taken into account. If \code{"conditional"}, only the conditional component is considered.} \item{verbose}{Toggle warnings and messages.} \item{...}{Arguments passed down to \code{lme4::bootMer()} or \code{boot::boot()} for bootstrapped ICC, R2, RMSE etc.; for \code{variance_decomposition()}, arguments are passed down to \code{brms::posterior_predict()}.} \item{re_formula}{Formula containing group-level effects to be considered in the prediction. If \code{NULL} (default), include all group-level effects. Else, for instance for nested models, name a specific group-level effect to calculate the variance decomposition for this group-level. See 'Details' and \code{?brms::posterior_predict}.} \item{robust}{Logical, if \code{TRUE}, the median instead of mean is used to calculate the central tendency of the variances.} } \value{ A list with two values, the adjusted ICC and the unadjusted ICC. For \code{variance_decomposition()}, a list with two values, the decomposed ICC as well as the credible intervals for this ICC. } \description{ This function calculates the intraclass-correlation coefficient (ICC) - sometimes also called \emph{variance partition coefficient} (VPC) or \emph{repeatability} - for mixed effects models. The ICC can be calculated for all models supported by \code{\link[insight:get_variance]{insight::get_variance()}}. For models fitted with the \strong{brms}-package, \code{icc()} might fail due to the large variety of models and families supported by the \strong{brms}-package. In such cases, an alternative to the ICC is the \code{variance_decomposition()}, which is based on the posterior predictive distribution (see 'Details'). } \details{ \subsection{Interpretation}{ The ICC can be interpreted as "the proportion of the variance explained by the grouping structure in the population". The grouping structure entails that measurements are organized into groups (e.g., test scores in a school can be grouped by classroom if there are multiple classrooms and each classroom was administered the same test) and ICC indexes how strongly measurements in the same group resemble each other. This index goes from 0, if the grouping conveys no information, to 1, if all observations in a group are identical (\emph{Gelman and Hill, 2007, p. 258}). In other word, the ICC - sometimes conceptualized as the measurement repeatability - "can also be interpreted as the expected correlation between two randomly drawn units that are in the same group" \emph{(Hox 2010: 15)}, although this definition might not apply to mixed models with more complex random effects structures. The ICC can help determine whether a mixed model is even necessary: an ICC of zero (or very close to zero) means the observations within clusters are no more similar than observations from different clusters, and setting it as a random factor might not be necessary. } \subsection{Difference with R2}{ The coefficient of determination R2 (that can be computed with \code{\link[=r2]{r2()}}) quantifies the proportion of variance explained by a statistical model, but its definition in mixed model is complex (hence, different methods to compute a proxy exist). ICC is related to R2 because they are both ratios of variance components. More precisely, R2 is the proportion of the explained variance (of the full model), while the ICC is the proportion of explained variance that can be attributed to the random effects. In simple cases, the ICC corresponds to the difference between the \emph{conditional R2} and the \emph{marginal R2} (see \code{\link[=r2_nakagawa]{r2_nakagawa()}}). } \subsection{Calculation}{ The ICC is calculated by dividing the random effect variance, \ifelse{html}{\out{σ2i}}{\eqn{\sigma^2_i}}, by the total variance, i.e. the sum of the random effect variance and the residual variance, \ifelse{html}{\out{σ2ε}}{\eqn{\sigma^2_\epsilon}}. } \subsection{Adjusted and unadjusted ICC}{ \code{icc()} calculates an adjusted and an unadjusted ICC, which both take all sources of uncertainty (i.e. of \emph{all random effects}) into account. While the \emph{adjusted ICC} only relates to the random effects, the \emph{unadjusted ICC} also takes the fixed effects variances into account, more precisely, the fixed effects variance is added to the denominator of the formula to calculate the ICC (see \emph{Nakagawa et al. 2017}). Typically, the \emph{adjusted} ICC is of interest when the analysis of random effects is of interest. \code{icc()} returns a meaningful ICC also for more complex random effects structures, like models with random slopes or nested design (more than two levels) and is applicable for models with other distributions than Gaussian. For more details on the computation of the variances, see \code{?insight::get_variance}. } \subsection{ICC for unconditional and conditional models}{ Usually, the ICC is calculated for the null model ("unconditional model"). However, according to \emph{Raudenbush and Bryk (2002)} or \emph{Rabe-Hesketh and Skrondal (2012)} it is also feasible to compute the ICC for full models with covariates ("conditional models") and compare how much, e.g., a level-2 variable explains the portion of variation in the grouping structure (random intercept). } \subsection{ICC for specific group-levels}{ The proportion of variance for specific levels related to the overall model can be computed by setting \code{by_group = TRUE}. The reported ICC is the variance for each (random effect) group compared to the total variance of the model. For mixed models with a simple random intercept, this is identical to the classical (adjusted) ICC. } \subsection{Variance decomposition for brms-models}{ If \code{model} is of class \code{brmsfit}, \code{icc()} might fail due to the large variety of models and families supported by the \strong{brms} package. In such cases, \code{variance_decomposition()} is an alternative ICC measure. The function calculates a variance decomposition based on the posterior predictive distribution. In this case, first, the draws from the posterior predictive distribution \emph{not conditioned} on group-level terms (\code{posterior_predict(..., re_formula = NA)}) are calculated as well as draws from this distribution \emph{conditioned} on \emph{all random effects} (by default, unless specified else in \code{re_formula}) are taken. Then, second, the variances for each of these draws are calculated. The "ICC" is then the ratio between these two variances. This is the recommended way to analyse random-effect-variances for non-Gaussian models. It is then possible to compare variances across models, also by specifying different group-level terms via the \code{re_formula}-argument. Sometimes, when the variance of the posterior predictive distribution is very large, the variance ratio in the output makes no sense, e.g. because it is negative. In such cases, it might help to use \code{robust = TRUE}. } } \section{Supported models and model families}{ The single variance components that are required to calculate the marginal and conditional r-squared values are calculated using the \code{\link[insight:get_variance]{insight::get_variance()}} function. The results are validated against the solutions provided by \emph{Nakagawa et al. (2017)}, in particular examples shown in the Supplement 2 of the paper. Other model families are validated against results from the \strong{MuMIn} package. This means that the r-squared values returned by \code{r2_nakagawa()} should be accurate and reliable for following mixed models or model families: \itemize{ \item Bernoulli (logistic) regression \item Binomial regression (with other than binary outcomes) \item Poisson and Quasi-Poisson regression \item Negative binomial regression (including nbinom1, nbinom2 and nbinom12 families) \item Gaussian regression (linear models) \item Gamma regression \item Tweedie regression \item Beta regression \item Ordered beta regression } Following model families are not yet validated, but should work: \itemize{ \item Zero-inflated and hurdle models \item Beta-binomial regression \item Compound Poisson regression \item Generalized Poisson regression \item Log-normal regression \item Skew-normal regression } Extracting variance components for models with zero-inflation part is not straightforward, because it is not definitely clear how the distribution-specific variance should be calculated. Therefore, it is recommended to carefully inspect the results, and probably validate against other models, e.g. Bayesian models (although results may be only roughly comparable). Log-normal regressions (e.g. \code{lognormal()} family in \strong{glmmTMB} or \code{gaussian("log")}) often have a very low fixed effects variance (if they were calculated as suggested by \emph{Nakagawa et al. 2017}). This results in very low ICC or r-squared values, which may not be meaningful. } \examples{ \dontshow{if (require("lme4")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} model <- lme4::lmer(Sepal.Length ~ Petal.Length + (1 | Species), data = iris) icc(model) # ICC for specific group-levels data(sleepstudy, package = "lme4") set.seed(12345) sleepstudy$grp <- sample(1:5, size = 180, replace = TRUE) sleepstudy$subgrp <- NA for (i in 1:5) { filter_group <- sleepstudy$grp == i sleepstudy$subgrp[filter_group] <- sample(1:30, size = sum(filter_group), replace = TRUE) } model <- lme4::lmer( Reaction ~ Days + (1 | grp / subgrp) + (1 | Subject), data = sleepstudy ) icc(model, by_group = TRUE) \dontshow{\}) # examplesIf} } \references{ \itemize{ \item Hox, J. J. (2010). Multilevel analysis: techniques and applications (2nd ed). New York: Routledge. \item Nakagawa, S., Johnson, P. C. D., and Schielzeth, H. (2017). The coefficient of determination R2 and intra-class correlation coefficient from generalized linear mixed-effects models revisited and expanded. Journal of The Royal Society Interface, 14(134), 20170213. \item Rabe-Hesketh, S., and Skrondal, A. (2012). Multilevel and longitudinal modeling using Stata (3rd ed). College Station, Tex: Stata Press Publication. \item Raudenbush, S. W., and Bryk, A. S. (2002). Hierarchical linear models: applications and data analysis methods (2nd ed). Thousand Oaks: Sage Publications. } } performance/man/model_performance.Rd0000644000176200001440000000310214257537777017322 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/model_performance.R \name{model_performance} \alias{model_performance} \alias{performance} \title{Model Performance} \usage{ model_performance(model, ...) performance(model, ...) } \arguments{ \item{model}{Statistical model.} \item{...}{Arguments passed to or from other methods, resp. for \code{compare_performance()}, one or multiple model objects (also of different classes).} } \value{ A data frame (with one row) and one column per "index" (see \code{metrics}). } \description{ See the documentation for your object's class: \itemize{ \item \link[=model_performance.lm]{Frequentist Regressions} \item \link[=model_performance.ivreg]{Instrumental Variables Regressions} \item \link[=model_performance.merMod]{Mixed models} \item \link[=model_performance.stanreg]{Bayesian models} \item \link[=model_performance.lavaan]{CFA / SEM lavaan models} \item \link[=model_performance.rma]{Meta-analysis models} } } \details{ \code{model_performance()} correctly detects transformed response and returns the "corrected" AIC and BIC value on the original scale. To get back to the original scale, the likelihood of the model is multiplied by the Jacobian/derivative of the transformation. } \examples{ model <- lm(mpg ~ wt + cyl, data = mtcars) model_performance(model) model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") model_performance(model) } \seealso{ \code{\link[=compare_performance]{compare_performance()}} to compare performance of many different models. } performance/man/classify_distribution.Rd0000644000176200001440000000073414260574712020245 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check_distribution.R \docType{data} \name{classify_distribution} \alias{classify_distribution} \title{Classify the distribution of a model-family using machine learning} \description{ Classify the distribution of a model-family using machine learning } \details{ The trained model to classify distributions, which is used by the \code{check_distribution()} function. } \keyword{data} performance/man/r2_loo.Rd0000644000176200001440000000415514501027040015007 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/r2_loo.R \name{r2_loo} \alias{r2_loo} \alias{r2_loo_posterior} \alias{r2_loo_posterior.brmsfit} \alias{r2_loo_posterior.stanreg} \title{LOO-adjusted R2} \usage{ r2_loo(model, robust = TRUE, ci = 0.95, verbose = TRUE, ...) r2_loo_posterior(model, ...) \method{r2_loo_posterior}{brmsfit}(model, verbose = TRUE, ...) \method{r2_loo_posterior}{stanreg}(model, verbose = TRUE, ...) } \arguments{ \item{model}{A Bayesian regression model (from \strong{brms}, \strong{rstanarm}, \strong{BayesFactor}, etc).} \item{robust}{Logical, if \code{TRUE}, the median instead of mean is used to calculate the central tendency of the variances.} \item{ci}{Value or vector of probability of the CI (between 0 and 1) to be estimated.} \item{verbose}{Toggle off warnings.} \item{...}{Arguments passed to \code{r2_posterior()}.} } \value{ A list with the Bayesian R2 value. For mixed models, a list with the Bayesian R2 value and the marginal Bayesian R2 value. The standard errors and credible intervals for the R2 values are saved as attributes. A list with the LOO-adjusted R2 value. The standard errors and credible intervals for the R2 values are saved as attributes. } \description{ Compute LOO-adjusted R2. } \details{ \code{r2_loo()} returns an "adjusted" R2 value computed using a leave-one-out-adjusted posterior distribution. This is conceptually similar to an adjusted/unbiased R2 estimate in classical regression modeling. See \code{\link[=r2_bayes]{r2_bayes()}} for an "unadjusted" R2. Mixed models are not currently fully supported. \code{r2_loo_posterior()} is the actual workhorse for \code{r2_loo()} and returns a posterior sample of LOO-adjusted Bayesian R2 values. } \examples{ \dontshow{if (require("rstanarm") && require("rstantools")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} model <- suppressWarnings(rstanarm::stan_glm( mpg ~ wt + cyl, data = mtcars, chains = 1, iter = 500, refresh = 0, show_messages = FALSE )) r2_loo(model) \dontshow{\}) # examplesIf} } performance/man/r2_coxsnell.Rd0000644000176200001440000000303414666017356016065 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/r2_coxsnell.R \name{r2_coxsnell} \alias{r2_coxsnell} \title{Cox & Snell's R2} \usage{ r2_coxsnell(model, ...) } \arguments{ \item{model}{Model with binary outcome.} \item{...}{Currently not used.} } \value{ A named vector with the R2 value. } \description{ Calculates the pseudo-R2 value based on the proposal from \emph{Cox & Snell (1989)}. } \details{ This index was proposed by \emph{Cox and Snell (1989, pp. 208-9)} and, apparently independently, by \emph{Magee (1990)}; but had been suggested earlier for binary response models by \emph{Maddala (1983)}. However, this index achieves a maximum of less than 1 for discrete models (i.e. models whose likelihood is a product of probabilities) which have a maximum of 1, instead of densities, which can become infinite \emph{(Nagelkerke, 1991)}. } \examples{ model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") r2_coxsnell(model) } \references{ \itemize{ \item Cox, D. R., Snell, E. J. (1989). Analysis of binary data (Vol. 32). Monographs on Statistics and Applied Probability. \item Magee, L. (1990). R 2 measures based on Wald and likelihood ratio joint significance tests. The American Statistician, 44(3), 250-253. \item Maddala, G. S. (1986). Limited-dependent and qualitative variables in econometrics (No. 3). Cambridge university press. \item Nagelkerke, N. J. (1991). A note on a general definition of the coefficient of determination. Biometrika, 78(3), 691-692. } } performance/man/item_reliability.Rd0000644000176200001440000000333614561136140017152 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/item_reliability.R \name{item_reliability} \alias{item_reliability} \title{Reliability Test for Items or Scales} \usage{ item_reliability(x, standardize = FALSE, digits = 3) } \arguments{ \item{x}{A matrix or a data frame.} \item{standardize}{Logical, if \code{TRUE}, the data frame's vectors will be standardized. Recommended when the variables have different measures / scales.} \item{digits}{Amount of digits for returned values.} } \value{ A data frame with the corrected item-total correlations (\emph{item discrimination}, column \code{item_discrimination}) and Cronbach's Alpha (if item deleted, column \code{alpha_if_deleted}) for each item of the scale, or \code{NULL} if data frame had too less columns. } \description{ Compute various measures of internal consistencies for tests or item-scales of questionnaires. } \details{ This function calculates the item discriminations (corrected item-total correlations for each item of \code{x} with the remaining items) and the Cronbach's alpha for each item, if it was deleted from the scale. The absolute value of the item discrimination indices should be above 0.2. An index between 0.2 and 0.4 is considered as "fair", while an index above 0.4 (or below -0.4) is "good". The range of satisfactory values is from 0.4 to 0.7. Items with low discrimination indices are often ambiguously worded and should be examined. Items with negative indices should be examined to determine why a negative value was obtained (e.g. reversed answer categories regarding positive and negative poles). } \examples{ data(mtcars) x <- mtcars[, c("cyl", "gear", "carb", "hp")] item_reliability(x) } performance/man/r2_xu.Rd0000644000176200001440000000146614257537777014713 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/r2_xu.R \name{r2_xu} \alias{r2_xu} \title{Xu' R2 (Omega-squared)} \usage{ r2_xu(model) } \arguments{ \item{model}{A linear (mixed) model.} } \value{ The R2 value. } \description{ Calculates Xu' Omega-squared value, a simple R2 equivalent for linear mixed models. } \details{ \code{r2_xu()} is a crude measure for the explained variance from linear (mixed) effects models, which is originally denoted as \ifelse{html}{\out{Ω2}}{\eqn{\Omega^2}}. } \examples{ model <- lm(Sepal.Length ~ Petal.Length + Species, data = iris) r2_xu(model) } \references{ Xu, R. (2003). Measuring explained variation in linear mixed effects models. Statistics in Medicine, 22(22), 3527–3541. \doi{10.1002/sim.1572} } performance/man/check_distribution.Rd0000644000176200001440000000552314741714104017501 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check_distribution.R \name{check_distribution} \alias{check_distribution} \title{Classify the distribution of a model-family using machine learning} \usage{ check_distribution(model) } \arguments{ \item{model}{Typically, a model (that should response to \code{residuals()}). May also be a numeric vector.} } \description{ Choosing the right distributional family for regression models is essential to get more accurate estimates and standard errors. This function may help to check a models' distributional family and see if the model-family probably should be reconsidered. Since it is difficult to exactly predict the correct model family, consider this function as somewhat experimental. } \details{ This function uses an internal random forest model to classify the distribution from a model-family. Currently, following distributions are trained (i.e. results of \code{check_distribution()} may be one of the following): \code{"bernoulli"}, \code{"beta"}, \code{"beta-binomial"}, \code{"binomial"}, \code{"cauchy"}, \code{"chi"}, \code{"exponential"}, \code{"F"}, \code{"gamma"}, \code{"half-cauchy"}, \code{"inverse-gamma"}, \code{"lognormal"}, \code{"normal"}, \code{"negative binomial"}, \code{"negative binomial (zero-inflated)"}, \code{"pareto"}, \code{"poisson"}, \code{"poisson (zero-inflated)"}, \code{"tweedie"}, \code{"uniform"} and \code{"weibull"}. \cr \cr Note the similarity between certain distributions according to shape, skewness, etc. Thus, the predicted distribution may not be perfectly representing the distributional family of the underlying fitted model, or the response value. \cr \cr There is a \code{plot()} method, which shows the probabilities of all predicted distributions, however, only if the probability is greater than zero. } \note{ This function is somewhat experimental and might be improved in future releases. The final decision on the model-family should also be based on theoretical aspects and other information about the data and the model. \cr \cr There is also a \href{https://easystats.github.io/see/articles/performance.html}{\code{plot()}-method} implemented in the \href{https://easystats.github.io/see/}{\pkg{see}-package}. } \examples{ \dontshow{if (all(insight::check_if_installed(c("lme4", "parameters", "randomForest"), quietly = TRUE))) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} data(sleepstudy, package = "lme4") model <<- lme4::lmer(Reaction ~ Days + (Days | Subject), sleepstudy) check_distribution(model) \dontshow{\}) # examplesIf} \dontshow{if (all(insight::check_if_installed(c("see", "patchwork", "randomForest"), quietly = TRUE))) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} plot(check_distribution(model)) \dontshow{\}) # examplesIf} } performance/man/check_residuals.Rd0000644000176200001440000000656214600524676016770 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check_residuals.R \name{check_residuals} \alias{check_residuals} \alias{check_residuals.default} \title{Check uniformity of simulated residuals} \usage{ check_residuals(x, ...) \method{check_residuals}{default}(x, alternative = c("two.sided", "less", "greater"), ...) } \arguments{ \item{x}{An object returned by \code{\link[=simulate_residuals]{simulate_residuals()}} or \code{\link[DHARMa:simulateResiduals]{DHARMa::simulateResiduals()}}.} \item{...}{Passed down to \code{\link[stats:ks.test]{stats::ks.test()}}.} \item{alternative}{A character string specifying the alternative hypothesis. See \code{\link[stats:ks.test]{stats::ks.test()}} for details.} } \value{ The p-value of the test statistics. } \description{ \code{check_residuals()} checks generalized linear (mixed) models for uniformity of randomized quantile residuals, which can be used to identify typical model misspecification problems, such as over/underdispersion, zero-inflation, and residual spatial and temporal autocorrelation. } \details{ Uniformity of residuals is checked using a Kolmogorov-Smirnov test. There is a \code{plot()} method to visualize the distribution of the residuals. The test for uniformity basically tests to which extent the observed values deviate from the model expectations (i.e. simulated values). In this sense, the \code{check_residuals()} function has similar goals like \code{\link[=check_predictions]{check_predictions()}}. } \section{Tests based on simulated residuals}{ For certain models, resp. model from certain families, tests like \code{\link[=check_zeroinflation]{check_zeroinflation()}} or \code{\link[=check_overdispersion]{check_overdispersion()}} are based on simulated residuals. These are usually more accurate for such tests than the traditionally used Pearson residuals. However, when simulating from more complex models, such as mixed models or models with zero-inflation, there are several important considerations. \code{simulate_residuals()} relies on \code{\link[DHARMa:simulateResiduals]{DHARMa::simulateResiduals()}}, and additional arguments specified in \code{...} are passed further down to that function. The defaults in DHARMa are set on the most conservative option that works for all models. However, in many cases, the help advises to use different settings in particular situations or for particular models. It is recommended to read the 'Details' in \code{?DHARMa::simulateResiduals} closely to understand the implications of the simulation process and which arguments should be modified to get the most accurate results. } \examples{ \dontshow{if (require("DHARMa")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} dat <- DHARMa::createData(sampleSize = 100, overdispersion = 0.5, family = poisson()) m <- glm(observedResponse ~ Environment1, family = poisson(), data = dat) res <- simulate_residuals(m) check_residuals(res) \dontshow{\}) # examplesIf} } \seealso{ \code{\link[=simulate_residuals]{simulate_residuals()}}, \code{\link[=check_zeroinflation]{check_zeroinflation()}}, \code{\link[=check_overdispersion]{check_overdispersion()}} and \code{\link[=check_predictions]{check_predictions()}}. See also \code{\link[see:plot.see_performance_simres]{see::plot.see_performance_simres()}} for options to customize the plot. } performance/man/check_outliers.Rd0000644000176200001440000005033214741714104016626 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check_outliers.R \name{check_outliers} \alias{check_outliers} \alias{check_outliers.default} \alias{check_outliers.numeric} \alias{check_outliers.data.frame} \alias{check_outliers.performance_simres} \title{Outliers detection (check for influential observations)} \usage{ check_outliers(x, ...) \method{check_outliers}{default}( x, method = c("cook", "pareto"), threshold = NULL, ID = NULL, verbose = TRUE, ... ) \method{check_outliers}{numeric}(x, method = "zscore_robust", threshold = NULL, ...) \method{check_outliers}{data.frame}(x, method = "mahalanobis", threshold = NULL, ID = NULL, ...) \method{check_outliers}{performance_simres}( x, type = "default", iterations = 100, alternative = "two.sided", ... ) } \arguments{ \item{x}{A model, a data.frame, a \code{performance_simres} \code{\link[=simulate_residuals]{simulate_residuals()}} or a \code{DHARMa} object.} \item{...}{When \code{method = "ics"}, further arguments in \code{...} are passed down to \code{\link[ICSOutlier:ics.outlier]{ICSOutlier::ics.outlier()}}. When \code{method = "mahalanobis"}, they are passed down to \code{\link[stats:mahalanobis]{stats::mahalanobis()}}. \code{percentage_central} can be specified when \code{method = "mcd"}. For objects of class \code{performance_simres} or \code{DHARMa}, further arguments are passed down to \code{DHARMa::testOutliers()}.} \item{method}{The outlier detection method(s). Can be \code{"all"} or some of \code{"cook"}, \code{"pareto"}, \code{"zscore"}, \code{"zscore_robust"}, \code{"iqr"}, \code{"ci"}, \code{"eti"}, \code{"hdi"}, \code{"bci"}, \code{"mahalanobis"}, \code{"mahalanobis_robust"}, \code{"mcd"}, \code{"ics"}, \code{"optics"} or \code{"lof"}.} \item{threshold}{A list containing the threshold values for each method (e.g. \code{list('mahalanobis' = 7, 'cook' = 1)}), above which an observation is considered as outlier. If \code{NULL}, default values will be used (see 'Details'). If a numeric value is given, it will be used as the threshold for any of the method run.} \item{ID}{Optional, to report an ID column along with the row number.} \item{verbose}{Toggle warnings.} \item{type}{Type of method to test for outliers. Can be one of \code{"default"}, \code{"binomial"} or \code{"bootstrap"}. Only applies when \code{x} is an object returned by \code{simulate_residuals()} or of class \code{DHARMa}. See 'Details' in \code{?DHARMa::testOutliers} for a detailed description of the types.} \item{iterations}{Number of simulations to run.} \item{alternative}{A character string specifying the alternative hypothesis.} } \value{ A logical vector of the detected outliers with a nice printing method: a check (message) on whether outliers were detected or not. The information on the distance measure and whether or not an observation is considered as outlier can be recovered with the \link{as.data.frame} function. Note that the function will (silently) return a vector of \code{FALSE} for non-supported data types such as character strings. } \description{ Checks for and locates influential observations (i.e., "outliers") via several distance and/or clustering methods. If several methods are selected, the returned "Outlier" vector will be a composite outlier score, made of the average of the binary (0 or 1) results of each method. It represents the probability of each observation of being classified as an outlier by at least one method. The decision rule used by default is to classify as outliers observations which composite outlier score is superior or equal to 0.5 (i.e., that were classified as outliers by at least half of the methods). See the \strong{Details} section below for a description of the methods. } \details{ Outliers can be defined as particularly influential observations. Most methods rely on the computation of some distance metric, and the observations greater than a certain threshold are considered outliers. Importantly, outliers detection methods are meant to provide information to consider for the researcher, rather than to be an automatized procedure which mindless application is a substitute for thinking. An \strong{example sentence} for reporting the usage of the composite method could be: \emph{"Based on a composite outlier score (see the 'check_outliers' function in the 'performance' R package; Lüdecke et al., 2021) obtained via the joint application of multiple outliers detection algorithms (Z-scores, Iglewicz, 1993; Interquartile range (IQR); Mahalanobis distance, Cabana, 2019; Robust Mahalanobis distance, Gnanadesikan and Kettenring, 1972; Minimum Covariance Determinant, Leys et al., 2018; Invariant Coordinate Selection, Archimbaud et al., 2018; OPTICS, Ankerst et al., 1999; Isolation Forest, Liu et al. 2008; and Local Outlier Factor, Breunig et al., 2000), we excluded n participants that were classified as outliers by at least half of the methods used."} } \note{ There is also a \href{https://easystats.github.io/see/articles/performance.html}{\code{plot()}-method} implemented in the \href{https://easystats.github.io/see/}{\pkg{see}-package}. \strong{Please note} that the range of the distance-values along the y-axis is re-scaled to range from 0 to 1. } \section{Model-specific methods}{ \itemize{ \item \strong{Cook's Distance}: Among outlier detection methods, Cook's distance and leverage are less common than the basic Mahalanobis distance, but still used. Cook's distance estimates the variations in regression coefficients after removing each observation, one by one (Cook, 1977). Since Cook's distance is in the metric of an F distribution with p and n-p degrees of freedom, the median point of the quantile distribution can be used as a cut-off (Bollen, 1985). A common approximation or heuristic is to use 4 divided by the numbers of observations, which usually corresponds to a lower threshold (i.e., more outliers are detected). This only works for frequentist models. For Bayesian models, see \code{pareto}. \item \strong{Pareto}: The reliability and approximate convergence of Bayesian models can be assessed using the estimates for the shape parameter k of the generalized Pareto distribution. If the estimated tail shape parameter k exceeds 0.5, the user should be warned, although in practice the authors of the \strong{loo} package observed good performance for values of k up to 0.7 (the default threshold used by \code{performance}). } } \section{Univariate methods}{ \itemize{ \item \strong{Z-scores} \verb{("zscore", "zscore_robust")}: The Z-score, or standard score, is a way of describing a data point as deviance from a central value, in terms of standard deviations from the mean (\code{"zscore"}) or, as it is here the case (\code{"zscore_robust"}) by default (Iglewicz, 1993), in terms of Median Absolute Deviation (MAD) from the median (which are robust measures of dispersion and centrality). The default threshold to classify outliers is 1.959 (\code{threshold = list("zscore" = 1.959)}), corresponding to the 2.5\% (\code{qnorm(0.975)}) most extreme observations (assuming the data is normally distributed). Importantly, the Z-score method is univariate: it is computed column by column. If a data frame is passed, the Z-score is calculated for each variable separately, and the maximum (absolute) Z-score is kept for each observations. Thus, all observations that are extreme on at least one variable might be detected as outliers. Thus, this method is not suited for high dimensional data (with many columns), returning too liberal results (detecting many outliers). \item \strong{IQR} \code{("iqr")}: Using the IQR (interquartile range) is a robust method developed by John Tukey, which often appears in box-and-whisker plots (e.g., in \link[ggplot2:geom_boxplot]{ggplot2::geom_boxplot}). The interquartile range is the range between the first and the third quartiles. Tukey considered as outliers any data point that fell outside of either 1.5 times (the default threshold is 1.7) the IQR below the first or above the third quartile. Similar to the Z-score method, this is a univariate method for outliers detection, returning outliers detected for at least one column, and might thus not be suited to high dimensional data. The distance score for the IQR is the absolute deviation from the median of the upper and lower IQR thresholds. Then, this value is divided by the IQR threshold, to “standardize” it and facilitate interpretation. \item \strong{CI} \verb{("ci", "eti", "hdi", "bci")}: Another univariate method is to compute, for each variable, some sort of "confidence" interval and consider as outliers values lying beyond the edges of that interval. By default, \code{"ci"} computes the Equal-Tailed Interval (\code{"eti"}), but other types of intervals are available, such as Highest Density Interval (\code{"hdi"}) or the Bias Corrected and Accelerated Interval (\code{"bci"}). The default threshold is \code{0.95}, considering as outliers all observations that are outside the 95\% CI on any of the variable. See \code{\link[bayestestR:ci]{bayestestR::ci()}} for more details about the intervals. The distance score for the CI methods is the absolute deviation from the median of the upper and lower CI thresholds. Then, this value is divided by the difference between the upper and lower CI bounds divided by two, to “standardize” it and facilitate interpretation. } } \section{Multivariate methods}{ \itemize{ \item \strong{Mahalanobis Distance}: Mahalanobis distance (Mahalanobis, 1930) is often used for multivariate outliers detection as this distance takes into account the shape of the observations. The default \code{threshold} is often arbitrarily set to some deviation (in terms of SD or MAD) from the mean (or median) of the Mahalanobis distance. However, as the Mahalanobis distance can be approximated by a Chi squared distribution (Rousseeuw and Van Zomeren, 1990), we can use the alpha quantile of the chi-square distribution with k degrees of freedom (k being the number of columns). By default, the alpha threshold is set to 0.025 (corresponding to the 2.5\\% most extreme observations; Cabana, 2019). This criterion is a natural extension of the median plus or minus a coefficient times the MAD method (Leys et al., 2013). \item \strong{Robust Mahalanobis Distance}: A robust version of Mahalanobis distance using an Orthogonalized Gnanadesikan-Kettenring pairwise estimator (Gnanadesikan and Kettenring, 1972). Requires the \strong{bigutilsr} package. See the \code{\link[bigutilsr:covrob_ogk]{bigutilsr::dist_ogk()}} function. \item \strong{Minimum Covariance Determinant (MCD)}: Another robust version of Mahalanobis. Leys et al. (2018) argue that Mahalanobis Distance is not a robust way to determine outliers, as it uses the means and covariances of all the data - including the outliers - to determine individual difference scores. Minimum Covariance Determinant calculates the mean and covariance matrix based on the most central subset of the data (by default, 66\\%), before computing the Mahalanobis Distance. This is deemed to be a more robust method of identifying and removing outliers than regular Mahalanobis distance. This method has a \code{percentage_central} argument that allows specifying the breakdown point (0.75, the default, is recommended by Leys et al. 2018, but a commonly used alternative is 0.50). \item \strong{Invariant Coordinate Selection (ICS)}: The outlier are detected using ICS, which by default uses an alpha threshold of 0.025 (corresponding to the 2.5\\% most extreme observations) as a cut-off value for outliers classification. Refer to the help-file of \code{\link[ICSOutlier:ics.outlier]{ICSOutlier::ics.outlier()}} to get more details about this procedure. Note that \code{method = "ics"} requires both \strong{ICS} and \strong{ICSOutlier} to be installed, and that it takes some time to compute the results. You can speed up computation time using parallel computing. Set the number of cores to use with \code{options(mc.cores = 4)} (for example). \item \strong{OPTICS}: The Ordering Points To Identify the Clustering Structure (OPTICS) algorithm (Ankerst et al., 1999) is using similar concepts to DBSCAN (an unsupervised clustering technique that can be used for outliers detection). The threshold argument is passed as \code{minPts}, which corresponds to the minimum size of a cluster. By default, this size is set at 2 times the number of columns (Sander et al., 1998). Compared to the other techniques, that will always detect several outliers (as these are usually defined as a percentage of extreme values), this algorithm functions in a different manner and won't always detect outliers. Note that \code{method = "optics"} requires the \strong{dbscan} package to be installed, and that it takes some time to compute the results. Additionally, the \code{optics_xi} (default to 0.05) is passed to the \code{\link[dbscan:optics]{dbscan::extractXi()}} function to further refine the cluster selection. \item \strong{Local Outlier Factor}: Based on a K nearest neighbors algorithm, LOF compares the local density of a point to the local densities of its neighbors instead of computing a distance from the center (Breunig et al., 2000). Points that have a substantially lower density than their neighbors are considered outliers. A LOF score of approximately 1 indicates that density around the point is comparable to its neighbors. Scores significantly larger than 1 indicate outliers. The default threshold of 0.025 will classify as outliers the observations located at \verb{qnorm(1-0.025) * SD)} of the log-transformed LOF distance. Requires the \strong{dbscan} package. } } \section{Methods for simulated residuals}{ The approach for detecting outliers based on simulated residuals differs from the traditional methods and may not be detecting outliers as expected. Literally, this approach compares observed to simulated values. However, we do not know the deviation of the observed data to the model expectation, and thus, the term "outlier" should be taken with a grain of salt. It refers to "simulation outliers". Basically, the comparison tests whether on observed data point is outside the simulated range. It is strongly recommended to read the related documentations in the \strong{DHARMa} package, e.g. \code{?DHARMa::testOutliers}. } \section{Threshold specification}{ Default thresholds are currently specified as follows: \if{html}{\out{
}}\preformatted{list( zscore = stats::qnorm(p = 1 - 0.001 / 2), zscore_robust = stats::qnorm(p = 1 - 0.001 / 2), iqr = 1.7, ci = 1 - 0.001, eti = 1 - 0.001, hdi = 1 - 0.001, bci = 1 - 0.001, cook = stats::qf(0.5, ncol(x), nrow(x) - ncol(x)), pareto = 0.7, mahalanobis = stats::qchisq(p = 1 - 0.001, df = ncol(x)), mahalanobis_robust = stats::qchisq(p = 1 - 0.001, df = ncol(x)), mcd = stats::qchisq(p = 1 - 0.001, df = ncol(x)), ics = 0.001, optics = 2 * ncol(x), optics_xi = 0.05, lof = 0.001 ) }\if{html}{\out{
}} } \section{Meta-analysis models}{ For meta-analysis models (e.g. objects of class \code{rma} from the \emph{metafor} package or \code{metagen} from package \emph{meta}), studies are defined as outliers when their confidence interval lies outside the confidence interval of the pooled effect. } \examples{ data <- mtcars # Size nrow(data) = 32 # For single variables ------------------------------------------------------ outliers_list <- check_outliers(data$mpg) # Find outliers outliers_list # Show the row index of the outliers as.numeric(outliers_list) # The object is a binary vector... filtered_data <- data[!outliers_list, ] # And can be used to filter a data frame nrow(filtered_data) # New size, 28 (4 outliers removed) # Find all observations beyond +/- 2 SD check_outliers(data$mpg, method = "zscore", threshold = 2) # For dataframes ------------------------------------------------------ check_outliers(data) # It works the same way on data frames # You can also use multiple methods at once outliers_list <- check_outliers(data, method = c( "mahalanobis", "iqr", "zscore" )) outliers_list # Using `as.data.frame()`, we can access more details! outliers_info <- as.data.frame(outliers_list) head(outliers_info) outliers_info$Outlier # Including the probability of being an outlier # And we can be more stringent in our outliers removal process filtered_data <- data[outliers_info$Outlier < 0.1, ] # We can run the function stratified by groups using `{datawizard}` package: group_iris <- datawizard::data_group(iris, "Species") check_outliers(group_iris) # nolint start \dontshow{if (all(insight::check_if_installed(c("bigutilsr", "MASS", "ICSOutlier", "ICS", "dbscan", "loo", "see"), quietly = TRUE))) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} # nolint end \donttest{ # You can also run all the methods check_outliers(data, method = "all", verbose = FALSE) # For statistical models --------------------------------------------- # select only mpg and disp (continuous) mt1 <- mtcars[, c(1, 3, 4)] # create some fake outliers and attach outliers to main df mt2 <- rbind(mt1, data.frame( mpg = c(37, 40), disp = c(300, 400), hp = c(110, 120) )) # fit model with outliers model <- lm(disp ~ mpg + hp, data = mt2) outliers_list <- check_outliers(model) plot(outliers_list) insight::get_data(model)[outliers_list, ] # Show outliers data } \dontshow{\}) # examplesIf} } \references{ \itemize{ \item Archimbaud, A., Nordhausen, K., and Ruiz-Gazen, A. (2018). ICS for multivariate outlier detection with application to quality control. \emph{Computational Statistics and Data Analysis}, \emph{128}, 184-199. \doi{10.1016/j.csda.2018.06.011} \item Gnanadesikan, R., and Kettenring, J. R. (1972). Robust estimates, residuals, and outlier detection with multiresponse data. \emph{Biometrics}, 81-124. \item Bollen, K. A., and Jackman, R. W. (1985). Regression diagnostics: An expository treatment of outliers and influential cases. \emph{Sociological Methods and Research}, \emph{13}(4), 510-542. \item Cabana, E., Lillo, R. E., and Laniado, H. (2019). Multivariate outlier detection based on a robust Mahalanobis distance with shrinkage estimators. arXiv preprint arXiv:1904.02596. \item Cook, R. D. (1977). Detection of influential observation in linear regression. \emph{Technometrics}, \emph{19}(1), 15-18. \item Iglewicz, B., and Hoaglin, D. C. (1993). How to detect and handle outliers (Vol. 16). Asq Press. \item Leys, C., Klein, O., Dominicy, Y., and Ley, C. (2018). Detecting multivariate outliers: Use a robust variant of Mahalanobis distance. \emph{Journal of Experimental Social Psychology}, 74, 150-156. \item Liu, F. T., Ting, K. M., and Zhou, Z. H. (2008, December). Isolation forest. In 2008 Eighth IEEE International Conference on Data Mining (pp. 413-422). IEEE. \item Lüdecke, D., Ben-Shachar, M. S., Patil, I., Waggoner, P., and Makowski, D. (2021). performance: An R package for assessment, comparison and testing of statistical models. \emph{Journal of Open Source Software}, \emph{6}(60), 3139. \doi{10.21105/joss.03139} \item Thériault, R., Ben-Shachar, M. S., Patil, I., Lüdecke, D., Wiernik, B. M., and Makowski, D. (2023). Check your outliers! An introduction to identifying statistical outliers in R with easystats. \emph{Behavior Research Methods}, 1-11. \doi{10.3758/s13428-024-02356-w} \item Rousseeuw, P. J., and Van Zomeren, B. C. (1990). Unmasking multivariate outliers and leverage points. \emph{Journal of the American Statistical association}, \emph{85}(411), 633-639. } } \seealso{ \code{\link[see:plot.see_check_outliers]{see::plot.see_check_outliers()}} for options to customize the plot. Other functions to check model assumptions and and assess model quality: \code{\link{check_autocorrelation}()}, \code{\link{check_collinearity}()}, \code{\link{check_convergence}()}, \code{\link{check_heteroscedasticity}()}, \code{\link{check_homogeneity}()}, \code{\link{check_model}()}, \code{\link{check_overdispersion}()}, \code{\link{check_predictions}()}, \code{\link{check_singularity}()}, \code{\link{check_zeroinflation}()} } \concept{functions to check model assumptions and and assess model quality} performance/man/figures/0000755000176200001440000000000014644214241014774 5ustar liggesusersperformance/man/figures/card.png0000644000176200001440000012052114257537777016442 0ustar liggesusersPNG  IHDR2gttEXtSoftwareAdobe ImageReadyqe<IDATx՝0[v3`&fـr2JD eHUl[Qh,CV axA2<أ6#vk LPO=9v]]=?Z&&=z`'?߻<96@8&@# F( P0@`@# F( P0@`@# F( P0@`@# FX?;u/ 9OꜤS VV꥟=uo?C @B:oz;"pkwW `0@D­]3fLƢs޺_]}]u:Ќ0~o74L4W_ >ƥM@C]sz"NI='!*`4@qr ;`@Qwݹd^!T˯*Rw@;Ek \4h`܋z7}swu]O|{Q !ޢS~ޖU_  c[oO4\@8Bk\ջ|eU8 tv5W}_dٟ5Y!> -Q׺O~ -QQג@_f4@ sO>iگ*!bJӟeTH tߧ~TH t-180@s/2Y?x:fżef?G)Vf@cBPH t }!/  Yte  f?k* !sO>g(d:2d @ t-1YT@_ t#,7( P0@`@!(-vԟN9ܓT;9[xԅ'|g7?}K,qwp |E՟+]TϮΑ:/swgDuoЎk'aeܽgSIh]?_|~jvrz͙mc~Ʒ\}Ƣk,J:2h0 FFwtȚa]黛9gBp7_ֻbʑQ+gn)T%7ΣQ#{F[~홫m;~9kou9'tdqsm>8HRo:ѶO4Ujj]@eh6c<{K ߠ^NwL^+-ǢU_C_ʥzIkθ ~nw9 u̥ӝ"\鷟=E47V]7-\=Ѡ7mRJon}o{_4im.=|ҵ>|O&~f.Fw/y`c C}~}_: fJn-c#Vc|އ5w=^,\RzBcc뮛= WH6~w{?-D !zn9)gΒΥߙ;g0}_nkgӓiKn٫|VmӴiMiu{P0W~)rǵ.\D{{[|"z;Ϯc 0qe}7{X5c#}"_Mu,A׭ Tyq몗{p놂8(,ҿ4Mu*co~ju)Nɴa>n9o]>xGi|'hxm ,[>R |YUOuoӵItN>^u JSyp.>w91ŮѵŴ ~sf)ԏ]E lI%6-j f:5tJtHWU,tZ3u|NB}U_]`Yyއc[K\XnZꞦ{[s>`X}ݧ'+mia|7.r 4R{uGQ?,Ӵ=T~PPEH`Bݳ^:jlSki Ytk~Tu-aMa,ʍ{q߿vhy }{\}!ϯUMJh9>RNAcFLr.CRkK㺜BVO՚a&( ]ScqŅwTnt\t={V]ץL5>UX҂@s)u}ZWj>?il jJ Y !-cB<{+)бֹ+p $/$ua ^>e3e 9KZM"ҧ{jG@bͱbvniѺFteM#q·E|>H]3ƕ RRۯs(W98CFQҀCaR;otj:w76 k|¿ֽ^L_]}\w*ێ^9s[@t~.8\iUk/AbM6797rvĹA@e֥ u[/j޶Μ2{(V5@vx Ĝ>CwhkF}E]Ԕ>6뷪RzY{;..SREYa7h|_na{tk:9}u2sXLōI6-)遘,W{qI)y\ZES!-;kjb.k' <𤳄tQ[j<|j;~u~4\z?/=y^b5IoluնqQi s5ͲI5µCh\EZ@Ôf%k LJ?&?9""Nw}cQJ3lkO_g?Fߩ[WW?l9w]jlD`]EuNG" OE:Hccr5өZoOtL޴pX?Ww_q9'X|1¿`Goב=?]gjżeյr`TzXcەE'LҰJ|DmaXj VxSŊy} }iM|3KZReOn៮z[Q;16oXT}V=\UޮFlY^z &H>4Ul~@>\}O[X}0MOn|:W40ɽd*h7:ݡ?] >O]Ӯs:V>CcGn. .Z>tY}A{-8hC UU"TT?7-. B${b]8]8)$&\40QU߿sBsj)]s1p7vW^g8zMm_߽q[)ucQMM4>KWmir:'%v~6Ť^j]CeV*A]kGuSguOK[ΡISˁnꛮ u;V>C:]"O%nsIOQT[<&_{~?hi, v C7DSt םu0CIsMV[k)X]oq|łյjS+{uo[+籨>9dԗHeiQi.Z`~wu UmM?Qi꺉1 Y(yk]Z?]-鉴 SJqhγɞ>BL0oRj!Tƒǵ*7X`ljA4sQf^w{yJWUMs ]oz7|2jQӀ,1}8XR@?7P*^- a:v^sOjz_*tkY״UeZ^릱㡿' IjtMy |Nہuz/X&~nvw֕Ӎsk߭JK'Җ3݌xRC?4iA&\_*@=uϾ|\=Oy jwRGus!w[fjb-߫2HNy ԝ!OO)+d~j1Fg𹎣:;mX/scv"M!S5k]9T,4iwo[7U^#Qߩ^)=(]qL(^}ϖד*uCcP&=1ΘS; tM˪!q_*kY7%V*B` OS*3>BRv˝f}}P]58 Z_T']w?٧@*Ek.\Xk0aX1їs.ɪ ZVݍESYoXG(7L1äzX`5M-) F/nx3jMs8ρEC22`KhwAk tu~$}ϾL>tU{a]uɺȍCbMݧWؓڽU2P.b}@+屨:oQ8b|_x-+Rlp}tJSn'L=\2>/偒G}UT'y+1¿z_$1? C|5v-G 7, )O}O}ͻ?*@~"҃ǢV귤zg7{GxT\]sWOʭu|RYvJS6L9$cЬh؃5؟Sw}Z՟*AۡKoJA[K8$>]1 NB7 rX]?TG؅_zC.`@uf5xHuPi^c맕e.O. MT` .VIJW+>6$R%k! >sG:Mlq08ՍRD_kUk@2M'ƪS% xюe@=퉵B.T<}&VҠB'n!OV[nEjSٸn'p2)TN̪_XT~vl5ݣY^VU]Z"a-:>izaS)|Rj{roԅEZBUBeנ=^ߏu?ОeXtb\^>ڞXᮏ5s scKwy TCVBuo|~ f5mUA9z_W) vY+/>*&ש!U0cYRT(z;gM^S̾yZj@[!ֵjk'f5s%>}Y])}Rdܰퟂ Ī/DoVSSXJ)foF<к$bQW%LqaPs :o-Ta`)9JUɺBAn΁T(VcƢV<  Q<{[|r<_]N0߉4:'{bqw\+ [=%'ltb w 5 *,({yz-s]k[C+aNWin&X<^}Arh*'l㻝Y+Ki:6)i$kAo;:Yn.7slv:el:zB'R ԎYCF*:.:<2qtE\wzbӟ2:_/Xv8 leѱءF5d݁ڵk9P;ӵd4+S!X}w5G~oo,wUR.xX3`@{;Йj]QeZ4ktNd^:ֻjS?JOsDן+t~b0"/bx3 7,>Ug]"7 qv'Ϭirܓ+=sUql)ZW_<Et![ԒŚrkS.7_OuV~mܗnu9k8 .SJ)'6 PӁncN6fz>x}W`Ʋbj^u-(~pz7{F}q$n LEf`vu-H `:bޤR7J5{,rU |xucf@^'؇~os G9okiS\Cus au96 k}/deޤVU/LnPe?mq@bXG :.ᰶBMKlNUZa9cUv;A )לquoݹD ffZ3~.u@¹`=$C6M3ijcu;@tpI)Lᇪ콟asGpϾفy`]ndo\*cE`R?ķ )A!2E1@xs6Y/g꟡NƳ0F%ʏ,=yIZfW*-Nнw5?Wߚi{Kg`9bnZ&z[{,K ęYD%Ao, Y4V@]NT;Sh挫M¿ ~1N@rclt !X -`6-v:6@wXOUutm󺼑Z,>wJGuH2vu`[攖j>?Hf#:@xt]d5зjt 4X>%}(ߵgNUKv}) ĤvKAerw >k)NqL۟~ ;]>2j~ &EЊy ,%u, )tv.Z?ZOP~?rFŖsPk'gRyIpucX,';,sg=K׵uI V5@s홫8KFäӑ+ؖ[,it:hKWvVbJӟ7sh''$,<1(ilOh{*jt`@] /o7 r]Gl]쀸6M|J(#{cIШ^2Y< ^ ׵uBXv0N_Ѳ b  JXy 0*ٵg^mPYTn#t]ƺΛaRO3(kθ)ۭ.Ya0Wj9#U׺ȿu|;]uË>ˉ`vT<6O;9戆0~ ᫪rz՜@DzmVxv׵uOq,:ղ0 8cimƢv޺#`5 ,[5~JtóXD9;RmEս>>7/"%Zzs-[-Ii` ҩ\Wgs KoZx"($ 5> "]hXIUX,+t izvї9F<7cN 6oߴsYm0S_Uν;eZZ~FX)k$IVFWZU'?f3M)׵θc%LdhHP} Y?DeEEX؀,4 ?o}sqy8)vZiw5hP60SUtqי=Jc (",lPZ?mز@'wS{ ӰR ԯg/r>7Rew16@0F1 `B2է#>5z'/: @9C@Oٵ>k5ZN[Ҧt)LE|E icQXuUF`btX"oGn4kx5r:>:ixNӟ @&j#U=AzSH}(69܍9"#E W"tU2%N'rS{X >;w:lSU~{yY!e_jCuڕg_K_c%e,:Di&߫ MJU%gpj!z tgr >׳Q'*vgU\kJǐ\>ּUC69@)ʏcL[ |27![}޺lܵg:x(1eS端3'72 N:g>l}s 7wiuPn(t-0[={QUyۂy!7-\]+]z鳯kš>^EX5upz2pOGANvwx*|\>:lԛ]wV6&jt K'VUƾ+3m(|U= 5޺X8_]Uyf,tpnj ]{wF%1j N^]ޡ߿snss߳ D{5ȉ:4d P/]z:IGJp)hh|pgP_vŵœMC~dsІonXu8M羂}1fY1ВQ!?l! RAcQwhpXU|cQ}0C;>ƣ@` nj8SŷmuvDI ^]`e6SoNB?t 3W%y=uA=3a j`CA`̇}a~UHH1mu]/A.ϥz鸻hNmF;`,j0 >C6GjH/5갪֟)=QYk?Y|] J\wz]1mBJIA8OmfɄкE{c0oy}e>bR‡A]{UMLgcїɣbW.۟oMmZ墨n G9:Y\zqu M0Lײk}>qSIu1Z!ho?o=j3VԱ^:GcQ+]/̔.7%5u_pիun{p"DpIAV;ܓO@PS8@7)۴?{wwudw;?@V̻?Ppwoב=G N[55XUz a@G{m]pڒu>xЎ3pձ #@YnQB|9ksS?L!FnZwU`[ASy#@&i` BD! Sژj9%OLoO^ =sU^V[w@>:" 5Yz; @DJ1Uh]} ЏIŭ+8l #3v-_* S ۣ;?Sd0GBA)Ҁ-^_ꚦ+ûI[0韜{'OͯA3 qOU5mЮ=ޖq XϧA SZ ˩ `({3}^_^\zVyբ¼^=לX|4X쎭S]H5q t; 5@@?/iۑ_ @ nS;  vX;7ybB<`i{@Uta 5 λ*Ԛm/W/ 5}@m1) Oְ)ijBI2~@wnA M~ŷ{@M#Vs~"07m1ف0TMr`>x69ws@ ah?ܗ)H[4=XU@YcpOpb`[n q}W-)ZJ2;n[Hu s@[ʻz/|~N=`6&!]`%snrޓO>{Gz?|wUW/^ܻ+{_}o?0)kv ,P鿓zu`}gaKuhOm䄝' Z[.a  >Tܴb1ٳq?\M=[vmo}߯B]QTUJ϶~gD @$`\W/+ZWPS4 ew6-Aω{KrmƶX F[dIo)Jq$׻ֳŅwUmh6@|T&2ͦ (|ɽZn >M[hRU΃務P @֭Zj4IyUu-[z˗/~< ʓqP0 `SA\5g~9S|o1\/Y:gqߥOuŞ۶mRXPUժ5.Z1RUv Б0)Ui=x*PTm9@ЛzL38$BZM~hm?y l߾q,ܽ{w Bn(OZ S׉ZjVܜ@9Gf]h<̫UjG_knB@XzLJS}4Gn`W 7)~v¦ >^knذ0e 5W!w?z ]_?C:Ν,H(|՟T"Szo:z*+]S0ޠ>vMk)ػZ,dX5T* C{NNvFՁ:z:Paqa ce />tjAU~0/ XpL+-;j錃hq:.ƒhg!+Q Gז cVb-%@u 8 Z[/04ݴջ$3)Fz' 6MvUR!HyBM9;MU[\u??~T_r*#=K[0ӽzVx߯즅%Ǥ~7ni|U')DJnءD 0eff&رǯTYw-UeŎٺ; $GՁWH6~w`v蚀Sw[WUd|Κ"?Tf?'|۴i5 "\1*T e 1VUƿ[UJi]Eڵk@MU0UՁTi ^7xɽ^vN> 都aWEPJbU2 ~zߣ5φ p eI=Qo*|衇qP PSU f!@PZ/O;ϵջ~[Uд5?J U5)4~#_Yɦ'kϼM0 M;ZNCԆhe( o[UՁ>PP;h7]j]kL.1|=RYa韜_U-ϝ}h^U_\?jZNYPC GMt LMIn{'7oZJSPMz65kxj?#՟NV?6N. 1MokR0]L1T``YUP׫sU.S7WkYOUSߝw9_ >V 輎-d.[M4K~ޠP9ʼFrZNU O_=2o_ -Omsӯ^^Vu*S(8n ^orW`{T Fz˪ L38Uc]? 5עzJӁn۶-hJHBBlMrWԦ}תE 6[0H  d"tj縟IBUoz or~*4}o7rES|wp b2#1QTԧۮ7]Z!i!Xu}f4Uz_VMֱ$^RiӔ_DuM4LS\B)4T%jt4@R̝2w}v]; @!|G=F#ݦ*tSjiC?KLTD|l1aDMSp~x ~?f0h |ł(nh#q7"TjC'鿎iP  6 *4q>Ǹ4mc4]9Mi_}@{5=MӌCT2,OU*afM  4@bΨ0·aU/&XT16ѭ8LTSچPxhma<[U6@¿\5OX`'~LDJ! MyhCG!eW ?<*?L%Vuv)i+_J 5$ *lhZqqߦ Q;VĔ򮏜jͿ,1H $Ddͽ^qZOJi*UW p/=:)|=sXprUWM==LW :ǬwQߧÌZlM;cNN,l 6m4U刦jӚl1סROE fff6l0Ru6Q8ȰiĖXܦiMך¿11H Rg}Cp5m>+s[ @ ϼjQU12h*5]7 ԲOTʭA1ס5(u ֟Q^Aa|W%(GNUݴ{v*៻H д}9n>O/=w/_Qտl( Z0|]hzٸI Jo^[i93Dܖ0 _ˮHC)_U7RaWUFji)T`0%8O|6hPsQ!ƍAgN/B!,cZ:'?Zr964MHA?UG7 |@K?wVAg Q R5]+h>jMjTٟ_N8Tν%tUURi#c4ǵg^ݍ6():? MGR禮-= d 0im8O~C0SUDU\*%>4Tt N)Ss<߻]iZ5g*5sSoOέPl*Gu S @^ AAaB?UNMZ7T8A#!`80M{mZu4U*ll҂;0}>ޗ,Y2rS{!v9 \MmJT1 xGBSsJm"L7VTh@:(6FF-`H|iϝ7R֙Tş?k֜7x6\WԦ9r'L& `L!K4W(,ȭ)H=X\oe&7|ΚhX 3mPͰnʱ@}vbϝSXgj}:FP;N~N'6Ԧ ǿW1  Q^:PتS-5HTڬZU3|Qʣa™Arh@jM6UѰ3לquri41R.]g4 +CjiX)a 0LA~_UTl)u5qHO s_w4W_}gb"ϙXl߾g*p?a24WFm߱1 L@߫w~R\_$MŖk4Wh6sRM!kMBSB.5QVֱCʐ_M5O P'k/'Mhs E'F_ a6oӱki@?K| EQ j?gBy^[naIF{W^yeUbe5_RaGNJwLE#hcU1M[ܚ K簍D^S}/?A*-BU~;J5UJKDSe=pJWm UIuc&L`%U}Q-v_5:(x,>7gPiOjX_s9b7Zd7._~?M}׺9a/7@ Afג /ocWߎҔ(ljWڳ]Na]*5uT!!G}uD~ZJUT%T`Sիv*ׯ_^`e-{OC ^7S@D GB@TK3DRkʃI`ZBM8i ƍ; CNu4 X9[1Ү#{8Ka}O=P ?T缹(\z/|f A&} ‡vv`2&ҡ!^Lѹ1OZ ش1+os|iH Qi/r_ `UMɟߜM_}z 'x&MaUxZRk[rpŊC׵t.vY?zusowoO0Eo {om S8) $g8PQ =bzGz_|qc_jݴI(T3:!UtUçi_3ȣi=Iwnڴg)]y\Z\ڀ\K,>ZvVh 'pq<݃G3Ztz~4nF}O᮪Ɲ|@!*J mpWa /`ZScP@66$7wZ}sX/w޺sW璂0˩츭*ͯ]o; Q 6Wj:Tia̡44۲Som&96 #=K[ATѢ@Nzք1-S/a W6@?U0iQPyσWȢW[ ^Q)R׬ukθ`k ($o<uo }Um =m>ٝp]'=l{Q{kŜ؏T$~QD L @ 0@zOO]4C!C[N B*t\ [O-NUi@_I(n={wYש+_9NeSG~/nx. b4Wy D.n?u av!V2F7ZT>hګTUvP߳a:bq^3f?:z}TjeJ' C"OĮ i.? 㘴h\փ_;6UDHe0WΪ݈ 6x`cI TSxY(QPdMFTȠW}z-?1jTs*̜ޱM^4>l{~ָys$!DQ _ZPpGq5^_kc-p2b?B? cn1Hkк5m:w}6qN8(W¦9Ӄ`AT*v4WמygPBXe!D1RzVOuCIڠ QwE*?5͔xMUuSϧW CTn lM汿5 Pg$y]UbjW}y[󻾧1@e:C)Sc7I:^sx#äBL ң.rb![Z#!>mJx*@K *~qlWoGSJLzgߧ;@=-N\zVVOU>Hܝ8wӆѴi cri\T(!s4c"~~<yy;5\M>%l/LJDi*֓Ѵw~yw S<@k?톨sEA4 JOp_b݃o*IPԔ<+?]9sCє7vr}:*-4pq;u[P|U*\|衇R;쩃&B`cJe)Sgr9G?-MS଄cs(T;K4kYS%*Uh]_l(+?M:P-Z1YSXWo˖- ݦJ܄"eF&>@U҇JTX9hu !A`ݠ@UOzO`/P6@G7QoZ`7S|U7j:ۥ?wZU*Hܶm[*k iKjCOU/woj%%U*ѴDI( Rƭ,ӹTZj?yBUeWn[<89U֥{aC]7W_`…9/{1+ꪫ_}off|r}JӗJՆ@SU)Z0"DHQäXU*%>ҖP!yȾa l/]=^ PJ*C(!|}^Ʃ@ Y?,xӣ P0Xpt>-I_ڜ?U޽ U7r `A5F"Sz &5TUѐdõ^ Y۶VjczYy߶OOȠw?:@Qwc=UGv4$0Z~۪zcPi9PM {4hTy4QC@AA7f=ΥrO'>v:UUFyᇓx. ԟ Y]Lu j6DSWryU6rȝuj/EtViCOV>Uh(YN$=? {E۴Ǥs{JRWN0?]4mY)Q/*t ν? 닍粮K(yצM:[O$?v;jSI)Dҽ:] $t`}/ϧB$ N wM)A.ZX_fF*=S]T@$OwWk#Mg]I~s*F[qvuRHJ (.=W HWs? @+z]~̍f4&/\xwmbފ{nSU448FU/n>1k8R!< 9 Fb|b7.MacIi) nT8sp"oDAM=, D94OoXbg4H똄zD]_郁{7ngۇ{xX:C|ݦTE74!F mb=0RBTEorJAt.*aaHӞGU=Ra}NOƨFk% P%;y.U) 57@Gvp:L֮]ۉϩsÆ *B7T=Nӱ_0iA]O6=2W|%倳 Y!L $@GԹS,'Uv 7+vZG-im3cw%{+鸗|G7?4FW:Bm$@QM>HqW` Yp ¿UVi߶qvAEKlD ^UF :b9+C.w 蔿w!DQ!n8f UJ!)0+eS}@Ӆ r*a6Z_USxq={9 YS qR!IS7mV h?^ǃMU_Z~s'Ҧ }\(1AmuepZU8<dN!.WOtZH^ZiS HRZg됄}L.n d}V9P?Æ* &(?O@8كGv~j/wRh6[B.;6} sp<lPJt[֍EnX tߔ#U`U{=?K Falu~{kЇ>4o^Z'Ӷ 9Uٺ1Qmu[hblAZ|:seX jL昤㒮C$6cF:18[v_r\=Om[i2yi_>{)MMە v 2( K0-.χ~C[&ca>8ykݺꢡJXž#ZMTogc1ߋng.?%>,? _>V)LL%LUBwU{^{3̻?_y/҉.g/%(P:Y=] M5bgW *\{OuKu~S|OB[U?roBH}PHDT_ՠT*TWX$KW}M_?V3]Mu~Xd-]w;?T!ځs<8ʿEϭ=ە ;X.UZazR;*(+U4}m j߹u&J ۳(i[~aGc*¶+-<`ׯ#߽kAg5!z{:4 $+9bP Ӧ]HGȐ ֕ʯ"}V%|HeV"],zs$ yؗs;cjWn]^r hŢ+9RD*tu:~j}TUIcTuQ}_!]=uS.$.*Һ L'xc^_2zunWR^} /XDK\Wo&]Q.$h髲&馃&إ.:TmY] G:h¸ cC1U:^67czOŅ=u"V5BmwxCUUpBUaKe]m/ [!kg;[{=k|nCS}C#%rƫ俗K['N@9;bn~_Aä"y8aU0o$ L8Q~$Jʪ Cl7QW`Ul)YɺG;]"SuW}y+7 6k+C$hW\,hos}UkNl@Nvw'pmnuןZ=XAr3]~! u;nuW.(zz|9BVUEgD?L]DYu>L(/ukOЇt`HuR},ߟco.سuyl?ulr}L*XG ^\=%O*onӃ6`r׿Pv!AS{EU==Κ16yMUS: ۪M*]}n\]*k4<㫇j]Z*od;IRe$9|H/w­&[i d^~GZ;@ :L[*Z"`ǀyz}ugy-v ߵ\_X3`>YZ.}z/o p;xtYGuXPe?`T؜_`?Utv8U!UW}+m@BK v۳}K~n$_[) lve0ӅT Kߘ[sK.=I5NUP/u~#G-밯6<%Wdf>sfHu1 Ԑ*Ou*>dbʝ_볚}sl\z CZ XjM A{*-ڟ%諢+%Qq4 4+1܅ b`PP+9HʤxY'Z\Ur3ЗTK+}u-^8]h aCZs:IoMd:~R;uu??iO C :I]xھL[ suǜz~Ҫ$ ᣦy.]kےDjU`lK\uLR4(C9N|>IU%𥳐mP~!3_ urM}e{h(]ݽS>oȓc!l 1[r=; Wk>5ՑoQd$k28s|~{wA)rlZNrP=ս >I 3.JE {両!~eɃjBӼֹ7H-Z? W2 J?Bee6ULZT=TbtK c]_BS f!^[XS!Ot8odd?,Хz()yR!nSr"0@h|L&OMuU+J)y/!r]}a/KHKOLvpPlNҦ`ILC^]WSr+%0SV_CJ(V҅!UNupݪc|*ׁIBXMMÓ?z6_9 ]C J Nxu\*q P dj-91Zwr9큇ZWFT/H;dIւ:M 0-@/_/D"`.kJIJV`mTLA){SX}.q҂~,@ $LעV:QXڗzG3P +@j`u>pE }*%@9.ǎ, ҿ?W'KpQ/Bqkq>-|Ν?a?eA^&10c )R;*ao}CoRq׺: ›}9˞znva ֹr+} K@)RTZ)LT9`j]N wۣwoG49WU\ ^r% yة| ~ui U{'ZUh}EWzA T d`a'%i]j]δHӡo0S qMUh}O~,X* tPBk\\EveZoVI w›+s0ĺBzkJ=)!,=KZ[][ަ;S+pk_z50U@hY}S>pX:II|+ o~a6/_g`ГMOD ٯ?2LXwu&/R ʤz%JQ?AIjOj6TR*c!0P}r" %L;pN'/.ٻ/<~QEzuo`ТW o *`8x}''N~l"G_{ʃ /~iBj%T N{bcﳏ_%\½SI0aBU~>B'ul?:;s{A|RT&,`Qj8f:IB+j?wGt]f &kߓRwݝsE¾EGOJ|{r" a[>#Kز( @hI9eB߷껬ү*\%Յv%.xZV| UCBpI@aBn<@h @`'/wVע .l:(mgЂu' +^}7~e0?eЃ̿щ5{L @h&d~cWS\h 纶am0 @hS+ 3c])0 ZaKpY1~%\xQ[;#Jvg`ziq–NWL 0la~CuJ *4#a>g"Ф Z¿,:Za O% 3_t -df]%퉗W;  5 ^Ny@aC"Z`X&O/P)m9 6I[)/;e/𮒶>!2䢮R˚4i! ?Q??`&%g Wk!BCt>wyp둵8s L}L52K4i ,]{:-BCM&NP { 4)Wֹp@ 5*S 2)Wֱ h<?XiC`L R$r?` EءLf^4n|ڑY{<F5F?ՓT7=! a>|EءZ|oZ{CjjVǮA55o 6iM?> g2$kuuwF@54moic^rؕ{o{#[9q0Э,o {NXoܴ{U{Põk4U7 0N@ኃW6h*aU.{LqB ijm2MMsa`PS6Lk=0qޢ 8|숅 BM0mog`xP&@~*aֵ&΃ &B50-qM xe諾 BTļQGa{m`wm 篾遆V3M8 @`Z@*V$Sk ?C &H ;k1UjiZU}?o~EBCT$;sQ?0Mny}`?vUcdU{& |K7ls[LϢɿ@9TҤ/wr뗯Ir*r aCV\xN >iɾ~ l(5 ?;p,ze -d榭uC  "0-@¶u S{({6ؐ&@ml'{O.>sbS]u@ퟹs *I-H+՟:ϧG_{jvzL K_)ݟЂ>vdvW;='>~u/l{A $'ܷs~oXȢ!ۇt'(ݪIϿg$^yCyxR`P0?tB𼄄W e -''9O Pi(*z qao‡;U{U%|W6 O?%=,K|}_e`|/ACN8xju} MoN @E`S0aLJh`` l| Eηz˅:Շ}KT>yߥ0 mޱ2 NTNvӄ*w%Ի呣{ՀZqk}֨T>-B|(a0TE27B¿j0P-R4VU*K _Gl,IfR̮¿j_ϺfRoW_ e@`c*e6f?u@`c WߴF*UUWe[I;twm/OyJ,yom3Kϐ` `mUoZ[1`V_VgPZ O'ﻴ/~NqߙV߄:R$뇟k5I [Kqu M}Kld{?`S@vPA V?'&@+T9Խ'@@kEo^z_ hDF0^tv?*@5*?u`vwMǮm̞yΓ #Z ̇qխ^s{{B&߼ܾcЃB*l0Lh6`^mˠeUӄ^|' Lh.(âO66¿yՠU]Zf~)A L؉]TkQ!`𯒀  {A` L00n@`'ڮ֢B6]`۠O`Z'0^@`g a]A!c T;hsa٦m]"6UP#v0JH.(ۤ _ .j;_UH}uZesD%{[tb,;=<>I(vwޮ$l+o}%{{.e;Eдnʺ6?PlaUB*=R혀G>{=۾0N@`TNOBLm {[~m I+^FyR*6h^cf %P8UeY^³0*V®m I`s00OܽU Ei aE`sKt?P'N = -@۵KZWKP8zᾓ{g¼>Y_ {]qJ{ |[g=QP$xoRŹ?hKWPֱIL(s<62\U9L`3 6JJۢ}emܻ:[$DN%D; -ޛnU-coON%ۦg&\UTY֕L^;!::mL. .=Vujng01X ЋyMv=*h`NHzmy'6 Ћjouge(P+ǥFҪlcT$4ZWaA %kZ=wʪpnҎ]ŲM|L+0 zi[oדiM*۔;ghAp@wz/<}~`S=Ɛ1hz?UN| 3(MKZׁ\BǮw-]XZ!*@(vr)uwmG{dvǶ ʶl"kU(|Т} 8v@uݴ<۞ F'YL(e~#W &; idMkd}nyЖ:.$ S5l~ 2NZnk™|M%g疅f;gP2k$)aZ&UO ڜ lER I&/*<v'7X(^[CiZ/]\uxs>,C@ϳ]LmTZm$}UZ}ݤy~۷3=UȚZL&ILNB'ߦUkiG[5ঁe5]66h`B9[@`p[u, Jz]ڴskÿSM)$lI J0Hu۶mU82MN/__on*asڂW=*LY`2"U|=~vߑ"N}Me?Nu۽l Ig|}+ܞ?0DC#ݶmgO$ nx߿OxֹKA`uyRXlG@Uu\ /U v6խPLɾyPSȬ\&@ 0aKb)U[m_)mPwjC 0P+*ۧCFCto \`;@Ts`K@(MUg 6'4|%La!,vLX!(F۟_wA ?ї-B^㦽/< @(M'釞kEe;~lGe}NUM[`BX6<%zOn{􎍃2a8mp27~{N]ڰ^z!cvd2?uk=U+ 3_{['|\40Rs.p6Kp*~뒀4kTvV6_|Ϟ] ߛ_|tN%{jBZكp*)Iȗz jˆ8E0W^|s Es+m۲a5b>pT~y2 F$! okr_8h([h]WǼ_@U⌽ -t/*@`LzWxWjvav~!7=?㣺/>fgf/x1AϮ_-0*΃a=& P3ߙُl\׽ڧ _ߛ/(uy0-@q>1qnwGf5_Nz1 3ߌvavt糓goxA'sɄPc < P {U/2{ (R7C уT`Ne`ו>1WY`T[}gjo-D잽ٱcXQI p TJxJ@gbSdM-Ugl;hCsg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|U\ @IDATx\U0BE$$) ((HUN "ʥ+U*W0^"*pBN(*% C 7g3ɼys^}o)e%) @ @ @ @ @ @`] @ @ @ @ @ @ @ @ @ @ @ 1 A @ @ @ @ @ @ @ @ @ @ P @ @ @ @ @ @ @ @ @ @ @(B F @ @ @ @ @ @w @ @ @ @ @B@{!A# @ @ @ @ @ @@{ @ @ @ @ @ ! à @ @ @ @ @ =@ @ @ @ @ @^a @ @ @ @ @ @ @ @ @ @ @Bp/0h @ @ @ @ @pw @ @ @ @ @ @@!b4 @ @ @ @ @ @ @ @ @ @ @ 1 A @ @ @ @ @ @ @ @ @ @ P @ @ @ @ @ @ @4xWӣ>f͚^|Ŵ+UW]53& 2! 0sIw_z'?FƍƎF5# @ @ @ @k]Jh 򑏤>:j SI~+xӤI*[_Oϰ{!QGN<Ćۚ:uj:#")S?okzeϋ3fH'N5sI}{su>ӧW.N;Z{cɝ.?啞\@ @ @ @`P] @`P.ҴzSN9Ν;7׿Nkƀdu48C n^{F[E]o @ @ @T@f @R 2uQiҤI^fСiرiiJ>h1cFz뎉@O<1 6,}{߫ۮ%pF,LZwuS~3<\śjF]vY:}O .`@ @ @ @ @}݋3"@h(0gΜ[?uX`{?]&'O9L @ @ @Ui7 @sL?}[J+bg~G<0]y啹~i[!W?>|ӌ9l}e*?Zܾ &\|}pkV-J󾭆[g  @ @ @ p#QAnt)u0#'eK=}a\þYgU+r5jTt~t%TweN;- ܾ *狅5X#M>=Wg,y?? @ @ @^`h؃ @`~xӾJR;wzqȔ|W/;O>2D`ٹ3&>+;SZ`*yRL&mrnV[mʺ @ @ @ 0 pGX @+p''x"曧;.WӕZ*}߭;, @`j'1b/;ȑ#Ӗ[n[L<9曕'NXY@ @ @ @ALo}$@'(zdo; &Gyr{7]{im5/ 2$=:p|0OfJsI+B?~|Ї>z^믿n4sٛb5HzZdEvK\##CK,VYeϪ©Js=D"6&2OI+;i%,mFi.ꫯ3fT~lԨQ+2>~gwQsϥ^:E6M7ݴ_[0m[{za]vY:=O .rGܷrK/ D~8=gV%}Gg59{6lXZveJ+6x{t֞"Է0cݬm< x=x;3ޟq_=Ҫﰾ8 @ @ @@`' @`>[K?s?[ou'?IiE-m?4eʔR5Rd\Zhrnb-VyKӦMk{Qʂ}+?YpK.&tz,Ƚt) 1 Y\_b)UΎ,p|)6fʗyKYرc^#:=RےMH(pW\tk(eA,`K~ӟX}򗿔 ûK+R9>;nVB磌*mfuOK뭷^O,k(7pC)HROR^ FoxT=g^rz{,o:w0J/r=p6oOG]M)z补lLg|^OM,﮻u~ߕ=v⋗♑Mީ;_?׾/}K]m^xa:38 sa Ǻ7x__qO}S>7Wl@wh;~ @ @ @l4 p} @8" ?KW&:˜^BBlw#gYJ~s:uj)˸Z{s]]{v*_Eȑ#:>>_\9Bm#p/eY뛺F=_ʲ%7:}uP뮻gbr>;6G`{Ne~8E)Ơ-?ӥcl9\\koe/r!=z}29ꨣzGoj :.bPՆR_#z7ϙU_rLIEp@uOcC^{4iR)݊.wX @ @ @ _ @`>袋zb)~zR~ӟ,-]y=9,&i,mʂӌ3ztl}zb-ҝwޙlMw#LӦM?nܸ{5X# 60^])&|󟯴c%LYݴVX!eӔ)S4f̘2˔q38|_}wߝڴ6TWw eܧ/'NLX]~27,}Zn2 )':O~2-څ??Ҝ,q?&L0ܧo1G7ʹkVυ6jRܧ%V[-e_g\]⹵B ,3xR<cEL֎{oԨQj@Am;,@|#iN~{I1]vY@_~=_wYO|"e_⋧8 }(?8K믿^?1f{<9r-n89B>&aٗ+lP7Elg]~WWUVY%mvՕVwzU:g @ @ @@ @`>Ȃ#ssܠ{)1"צhcZʂ;m5\S>Kvz\^wL\oС,rݱYd鳟l:< , zݱQU77*;kc\++ mxlD[ʂ뮵>4ܿe1lI) 8إ,k};6 6mGe_wLc\\d,F`Ԏ˿se9Z ,N8OB+!Cҳ>[ۼzXdoo ke+M:ں{ϑ*W_}uZqo]wueFrcl-Yܱo*fعm$ʶڅVA[<& N:ڦU1S ~u]}ko5 `;6Pϖu}r}61&w̗.$C< *~.r}އOóIfu~&.uJM)ŽZ}-RٳgUﰺN @ @ @ P  @O>d]F]Wʊ=gΜ%,ˌő 92RZc#{xdiɂ׾{#Ctdl̍J^nog#n;4G➔#8"wyilxXdg޹sNʂsu+rJjZqSd]^>2$Wn)EꞖȒ,=E_"xdY/==]y\]6xtQGUW-rW]uUjnwtYg3++R/Zo>O[ 7:[%37c{_j͏UǗzZ@qOqwVY#|uIdU@=Z='ݳ%/(ėH:+{.+˭Z  @ @ @^ @@4 p_feRM3[yVKen]OCG@]W%|nGy~m>_ctNFfKA|\`ꪫRD8~W{}"1q'"htBBE0n`.o)&t=eʔպ=P_b* >_Yg6;mMS;agWO#GlZ[j]}^XBǺY[o5kLjTofi喫?@wkI @ @ @ &0` @~h5XO>d;wn2Kvd%F3gVxG+]-4\&Lt,m ٳgW}ꩧ*=]~8=HӧOOLu}-,LZr%zG..4>묳?qDFf p=hDb+E0alNaҹ[E]T*U ^xaZJ'Ṋ71گ3eܸqMRe=O:餦12tەh0z. X7;O?tn܃4Xi}7]TE @ @ @p 7$D_F/B^ɳ5no㒑I:_l%} n `#1;Jm_G}W^y}ڴi/Ϛ5nBBq]9ӌ3wQ#|HcƌIm]c=?Ą"ǽ?rR~NO'O\rTbǖ[nYYBgk^O;n<>#;Nէ=z.z{2(cߑE98 _vl]xEk`Vd0_{*-Rx6Um{}W/zSZ=- p,]ivSwl{Ύ/B@=Z=ZƤ/w`wk~ @ @ @S@`6 @|u])f=˕ /9{gxwʔ]sMŜ9sr5嚹 Jok#xr9 &O>9kVO3LrK7 Æ a=:fJO<&M_`8 }_'(}TgZ<#Ҏ;袋rr&N[JǠ?7rn[ouO_v}\۱fKS]kYwX8 @ @ @]jj @ ;"D)S=ܳϿ|t#s6JoyQ]g̙iM7oGL^)-r Osצ߿.80vUVY%[/?->}z'J~x'ݯ~{)OXdE*}uW(* L*w=}ٕɓ'xƆQ}9Z=-䎾u;&tW3w{Gc}ƭsd7x,B~s @ @ @h- @|3Iws-5+d [o;N庍0{'2zyzy֬Y=nܹsSm/_we]?jRw_}պĉcǦJ|wݯ4mڴO:5uYClsW(* L*-"Ef^x\/'Kl/iƌ# /٧[=ϒW^yBŗHXcQO4;2h]zk_ @ @ @%0t. @p Ә1crX9s:蠃ru+R:4O ];uS?SuAƍS<sþ~ߧw޹ؿQy!=Q^??rAɵ%ܫZԛ >TK.Vgoʉ'VfcK/D{jvSxFpouW-@Ǻ'݈~Ťz[W˿/S}y睹[޾úr @ @ @@QEEiv @@d ,_:ӧOODV=أ8"7宻J:իr4l%~VWPA .`|nsdD/JyRdȾ袋nRܛ1?pn=ۻs$^]&O\E]|ŕMzZ+Yr75knzl&}+WJL6w}_o搶ߧc,G>ܮ?x={v^z)xi]wM1!0pgWn aY @ @ @ P`M#@F;_\]OW^y啴;T6;g} /ܱZ馛Vc!2FPqO˷C"Rt7;V ~'Bz4lذܱݭ\s5uD`)SVX!-`m=v79 z6,-첕 H{7?ϩ:syd=\h>s?4ˏ~}__fV;k]?CvVuoqnטp[wmȌvUk}תwXs @ @ @T@{AF @-YO8ᄺN=H8IEflvAu~cPS1urȺ:~y~oA?fˎ;XZ^FOߞnᆺC]6`3 /r[.-B:q¤$&. K/4WWz brs-ַJR[:\WVj9OYE<k߅offm:;D}&n}m-g\NTv9&Pl]eɹi5֨ޥ˭/GjU38>A,L Ϻf qQGM{랋ݵݶzn|_SOO>9Wʹ瞛k6եvrX+Vêk @ @ @@qT 0@YJK/t |a}NKY`c9&MDZ[[~X`\ݑGYwygZwܑ;6j>\?;ߟ6hAvZa*˵SIw%#nkGP~,Θ1Ž{~~xnc}!E&lƌӱ~܄qVAr*Z9͚ǿ;K%|뭷sW^yeDUW]5dU>Z'@ @ @ P$ċ2m!@[/vmi뭷.gaHKG׿ &"?$Yܝw9tIէl~(wG䶟s9=#m`_|1M6ygE~d`Dhd馛g>rPhdӟN<KL*`3|%2)G{L^#F(o~{/~/"+뮫4'YO:?>7._#G矯 1y"Vq zx6.~m2dH]VAd>Sxv.pϘT% "naر)m]1)tAGL`zC\7k'ĵ㽲k6uvߩcݬw㞈g[9?y#w_:2/"{K.d Z @ @ @( M @@fmҽ[w}뭷6vR`ly`Gf4^]x}\?LMoQ{d1_qcM ϫ U=&OW??R"DfK~_/| iΜ9fϞ]RfaҤI)Z=Ͷl-,&&pUOML:鮭Z봳6 @ @ @d3 < @`^?Ӳ.&-0^r%iy?r#GywLwuWlcYeUʙ7d{)Sf<ӟ'84:yd}'Lw}w9+V[m;<2?Z +97miʖ>b7'N߱Z=X|嗧[^zcmz{$xbaC zEoW_ƌ!V]uVw| @ @ @Z$ E.C(RK-"{nd=si#FmT" qo{yo}ahy#~}-GfKL<馛A,HîFƾc 6ܯrEM\sM'2wUm]yB_Ə_D>4so~3-ҝvgJ]vY:SS+O^DW;ο˗3;f~t 'VZÖXbt'r窍ZE @ @ @RJ!Z @x饗c=Vy˿_{YrW_}+\`gy&=s)"H-~6`6= ;PΆQci#0OƍKZz_^د7#c3A;Tc2ѣY; 똧~:= 1'H/x9=kof=>U?>fҕok}o;3=CgKǗCbrT<~G@ .X%> @ @ @`> @ @h@ul둑<2O `dﯟs& Vg. ^V~w: @ @ 0ש  @?{w6&,CIgtw aw1C@6f R.]28W @ԓ@T^kJ:[ed߁Z_.D%y|pF @ @Ԏ{ #!@ @ PZ?d\>Y%E`9OV.=VvN'BI݊QiyoEd=G.&2ܶ'@ @ @p @ @@ B۹A[SSSnHV/G]*@)^>$NW{/M{ @ @ @]pK{۶ @ @9W}kk+E&[T[/W]X/ ({ uh G5x @ @ @ @@MGhH/U.OG7B_)P*|*@]r @ @N@:' @ @ԄΙ{#~-Bú񼭭Mx&/'X~-(; pI @ @p/3x @ @z8::JQy=/{ppp# {KKˍ|7%PQ=&A{, @ @ @( ~m&@ @)Ϯ666Rܯ544dOiySSu#P7ikkL=źhwy޽[oX#@ @ @. ^{ @ @Ԕ@a׏lݽ1F2{3D~jٚ|11: @ @Ԍ{ !@ @Gξvm[ZZ~ G=mmm*=6J 777ܮsBKwwOB, @ @pS @ @%O|p(@TvϫˮZ[[ G> @ @ @" io+ @ @@M DPtuK1]]]ǡK P {L=U~SROOOk @ @ @ky @ @@M lnnhWi-_Ek Կ@\JU! dk @ @ @VkeO @ @@M DRR~޻wASiMNE˶rߥx|ٷ: @ @ pe+z @ @zȥ {ܯ_i" z24ӓ^Lnkggt =C L @ @Wp @ @R `?hݽҶ j Jv%;::PLع4 @ @ @%/% @ @888HY3BkkkW {F%~B{@5Ԣ@Գwvwwg1/\ @ @K  @ @J`{{;-..,~?ٻRCCC]yU,">007R#@ @ @p @ @Ԕ@أ:{#~ٰfccc*U&.Uhommm5\~vu-ݢeZ[[[|^h @ @ @Zj#@ @9,]&R=#!wwY & DR=Ǖ1.︺{\C#@ @ @+XG @ Psǡ^^.lyQA 1xtxxx!{L*jhhu&@ @ @p}l  @ @iaa! ^h{ZZZR/z  @ _ 'wvv;Y'Z#@ @ @ @ @5'u\=“GGGcT@@Q!Bz: @rowLH6{nwk @ @ p7~ @ @q02iYFƭ"/חY`xbi;^MKMMMy @ @ P`3b @ @@M Dd_Eݨaĸ^ @@ t miOJǖ8F#@ @ @p}d @ @X__Oinn.]4tq:M5E!ֲ)Ain~zA㎫\DO_ @ @Z_ @ @lܬz["H,w\V GtR:<<ڲpu: @ @ @p5> @ PXUk_^^z;Z[[ @pJvvݝ"㸥 @ @ @ >0 @ @@ eq|Օq{zzCqRu1600ޤj!@ @ @ߌw%@ @R`}}=+ >x@۪t"@_%W!GZݫinq\5Y4} @ @ p׈ @ @Eɂ)VZ[[pFj]`{{xUpڎwUF' @ @ @ PH4??Uk_^^jPVOE۪t"@ZX[[ˎQݽ+twwg4 @ @q @ @8::JKKKYV5zmۛzN @ql\\\ )W` ` @ @\Yz' @ @@M gvuueR[{ՠ @STtJUo{/{{{]ݤ*5 @ @ PY@ @ @B dٴY6fwUVU mmmΪ^ @ @p?kb  @ @i~~>־\6466Z{__ʳUDwI`uu5 Gu6;;Fu@ @ @ @@[I @9"~xxX*nojj5: @,l"Bմ,>88bbF @ @+XK @I,`dwwwcWWq5ٶ^ pV`?1xnn.퐳$&EE^WM1 @ @! {@ @(NMU5 k @ loog"쾵U՛D񹳳D @ @" ~W$@ @ )pxxUPrUؘ\__ UD.MF{Tyuwwg777W} @ @ Pu{m @ PT433^UaED\@LP[ZZ*/,,s?$###ill,utt_ @ @ԫ{YE @R`}}=}-ZM+=x r Գ@TrGv մ4 @ @5m/ @ Psd_\\̂环8}n @΂sssikkADds@ @ @zph @ @B DE,J!ݿ? g\FW G=nqNP4::bF @ @zpk @ @#aEM#@K JΫܢ{Tuw @ @' ?  @ @7*¹Es@[(---e nLooov088\\. @ @({v @ @8<??cui`6q @ @ @EKH @Դ@cÇ@jhh8 @JvZWWWvx^w  @ @ P5  @(~Bf7!Y,f @*q1==✤RkiiIcccitt4Vj @ @n]@w @ @E:T~"Li @s҄8Gb]Ts+twwWj @ @nM@}0 @ P4455z"6Z|fll,uttTj @ @nT@Fy9 @ P4ڣQ*F=Ba @|4ĽZc"@ @ @|< @ @|/..fs_apn @"DՕ~3Ջ@DZ'O @ @ Pp/I'@ @jR GR85*F@** P4(ȫ0х[8xǧ֫ {'N,达^mmll,=~82DَV @ @ pg̮ @ @XnNY# XԈ@OVU?YmJZjdSmuoޏ#^ P|Z5FnT`~~> onn|azQ6lG+ @ @{6 @K B߿O_~Mv-"QrH`omm1n^ŀvT>0U/zʼnӁR:Ow\=W܏,J?b?jԆ@# oooTLp{ݛ @ @p}k @ @@"4;;|vvvʎ=N?Nccc)P#ADz{`J瓏KJ;rѐmom~~drQ_9{f^Y~pg @ @p?kb  @ J<#rM5r2Y+*4Fո#^)^ ^}㷽t//-Tq[[ۯ#pgoU{ @ @* W䱒 @I411g}NZ>|=zZ D9 'RմKJn*|w1&S'I/A499Y<O>M)5 @ @W@~-#@ @5+ˎ1cccYlG+Z q㛪 GezTcTz鎕—&hloow-I'+ ^1۷oijj*eJ_w+sOڮ[m)~&&dR=LoԺnv.933bJ666UtwrB @ @({q @ @B ,..?^ fAi888Ȫ _g۞s’''q\TccOL4 Ĥ/_ٲWre @ @({Qq @ @DӧOiaa`{4'?'[yG GV#@bn ǕKb*+{UU'\͊sW^} @ @ @vkw @(@&''[_TOQ]#p$'Wb`lNVe;+z1"K~cc#;J{755U5&Գ@?jA&f*]  @ @q& @ QTk}qzIR1:OȲ atk\#aR5%YޕUKqY4wQ 333ibb"Dixx؄\!  @ @Ԟ{#"@ @@OB1 dU;::@ D.*7 RGhͪ^~jK`kk߇Jkmm=}߉PvQ-@Ls{١DŽ/_fv @ @p` @ @XQvrr2a4882u%UcO٣Z1 fP^X5S ~CNWyoHL~9yu Y >|^qhzY @ @) ^Ũ @ @@ D^u~\MϞ=Kq @ @}F@ @jV UG1666Ǐgx(@),U Uά:{Bh%-N&JVswT=&D^#Pd;JQ}?wSȈ| @ @~I @ @0[[[Y=BZSToU Bn)&s}ooBأ"{Ki KL)2sY=[[[kaӌ?11fffʾ;z*;d @ @7* ~ޜ @K MNNfr_#400P3Z'8J W7[qd>dd$=})E!'OG YVYuRzzhOMMMy3qIDq}-~5(fggϟSٳ4:: @ @/ ~ޑ @Ԭ@>~ rhh(x"Ev@ lnnWE[OOOL} |"*-.w%rXAop9)oK &MLLCq\޽{eXA @ @/U @ @Pׯijjl#gBmֵ@&ި\---z PY 1V~\ }\EF#P+ղCNϟ?weBV @ @ͼ @J`~~>});dO>.,cu llldu#tSwttdè+UN 1/*DŽ\bUTtsi˗܏jjjGFFr[H @ @ o'@ @DE;䎹%~: 殷u R\uӟRj  @{Lޮ1*1*&\inR &aD5浸@歶 @ @pކ @ @@VWWpLV#!bM,HTG466f."D^JvOU<1*&`9LK9ϟt q?44B @ @wQ@.uL @8<}sɓS\ /*S|U=Y*  @@!kaa! UL"^EUus;l)u$@ @#:ڙ6 @)zc1[QGUkZ?݄:<<(^nkkknFtF*UVVVrUrY,$@ @c:޹6 @j_ B>|([A{ll,x"EPe"m|"^Mho``8w: PTdš]]J߻H&U3 @ @pQ^oN @Ǐ*y=ׯST\V ~= ŕ*E8/Bz @]ctIqL8:::]u lll?3}^M?Ye @ @" ^/{v @ @@a_>v @ @@   @#ppp>UuKKKzUPFGGG)&OD.k`jhh8 @X^^Ύ ztwwg8kll<N fܷOʞy\ښB @ @Ep/3n @(@SjVׯSru,$'R{}J ===  @ 17q cq㱱4::bBF"LLe @ @߁O @-U|~;Ц4>>FFFr[HNv5;-S"\gE*+  @\v f]]] T%޿vwwsgW477箷 @ @@܋ @ %ϴ;#箷@@\ *#oO"<,L:ԸWVVq@5{{{Ǐeڲ/y;} @ @Ԭ{#@ @ D)ȟ?NtϳP@i{^uiqh @7.=77{.xr1;oǕ}4y^'&8&8V @ @@- ^1& @(v믿RʝYUŨ8O t~= V,$a9]8vOOOJ9;O%(vvv:;;;zzzN. @ @@!  @ 0;;>~rɓ7sy,}=gEq( @ @" io+ @Ԥ@"Tᒼմ)Xv,pttU[Jǝ߃Empp0 ,Ԯrt_XX8wQyÇ)&Hu;lmmeWZ]]uOo޼I----$@ @ PkG @ %޽{r=66?r[H ?~H_|IN"~,7(@cR[\J[ښ?~FGGK(9THtkooOo߾MݧWyN @ @kn @E *pioo̐#UۣZF|B,%[6#&⻥ @!vōjkkKO>]=(w @ @nA@}$ @G( (ONN:*n|2555宷n lll/_QEgϞ$ @* DRt޽b?+@_k1ñ @ @ rrH @EKgnÆƊ9 \OʪlJ @"9߈+D]#PXXXɻ2U\M(LQ @ @ %@ @ZX[[K޽K;;;gښ޾}+,tF.joool{ pJC]1f`` ;ym $_':tŕ޼yJC @ @p-yK @5+ÇttttfLR51brr2~_JBQ=*Gv pY}qq e#Q[#߿~ɓW+Wi @ @~y @ PӧOYX9occci||\#-=\ʂd*`.,込\-3w^z]ptt;U˵,.UNr @\)Bv;+dGe1Ǐ$O>;1aT#@ @ pYy @Ԭ@pƲZcr)9XNSirr2;ɂy-&|R<:^ 600Us @ @_Fk @ @fvvvVWWό1^JgYPQ}tbb"̔,U5 @[[[d+o`OSV,//g{]){ꪻA @ @7/ ~> @~Jz]*xm0VQai?wghjhhc! @糪[xQL(}qvs0u0&`yWJׯS\)I#@ @ phK @5+۷ӧ7oޤ֗@k>~)mHzD = @J499bRa^/_Ly-3rWMzazIum @ @&oR{ @ @ Dinn.}*LS_ rD* ^J=== PbOL)Z >|&>I= @ @pEA @"޽{|~SSSV=B5Z} D&4?NkYА2 @K,,,dAW766Ǐgxշ@\M)G9_ gd, @ @8- ~Zs @(@&3L{V*e7ttt4={LȲBV @&WUL_~ͭUܣ W.«JgZZZ:33ҙ @ @?w_ @(f[)*k+˵ @ lmme~@t7,Q],MLLdNoPN @ @@& @ @X]]*Ǐ,~"(}bKHjhh% @,,,dA9ړ'OR766>g6&o޼I1AY#@ @ pZ@ @ P?1F3-Ǵ^vFGGӳgRKKK>V @ܼ@ONNfA{{{V}ppnM *{.[&@ @M/FE @fff҇N-MY~- YgA}eۣcӓbCk @#U?}bj600;::ukkkٕt{Qv&W_:-9 @ @ }o  @ P/_nOWy^GGG)&6LLL-Jϟ?OdN @ܺ@TD=E٭)eJs|He7bll,={ĆBV @)A穩Z\i||<Z} ?UY޽{WyN @ pN @(zV}ww̐#vAT@lm@˗/Swww>V @_ &~)-,,ݘܰl+'۷lߟyLlU @ @Թ{`G @,--wޥ3C~yzW`qq1>MfjiiI߇Mj(n6r @<1yWt7sL|{{A # _~FFF, @ @~w2 @F`nn._g Q= rC &0D={ @~Tky- mmmy-+r;ӧ)n @ @pV @ @f"-*3}6 ^yAVVV ۹[p޽ݝB @%|DŽW^箷xcN8lY,aYeYlYuM  B p/ 4@S(%PB8C p4)[ۖ%_,wfvfVJK\;;i>>t'U:B@@@@}}9;@@@ a4* czzٳX|o> gѧٲeˬ8l5@@R\ӚԩS +Z :+8sZUU    0uOk˙!   +;رcc̴:5kV` OǚB):<[bedd$q  &pY۽{9r$5gΜi| umf'O F~CC@     >u%g  $ vĉb В[@[ZZӧ[yyشiG@@ TsN;sLz}L*|$BunllqC:F4 @@@@` pzה3B@@V@Cͫ _ooo󭺺 J@&;ê-lԑAU۳8b@@I8}r >z2U%:˪rkkkD1rrrX    ܓq   @Y}})oϷJ*yap ڢR{YYCv  #8|ܹsOu?{j Zr 8pԯQG@@@HbI|8t@@@ YT[Ϟ=8EYyyy`9 K@3U]U4B@@Q 8uuu!;;GZr C9Mg5BTQQ    I*@=I/  $@{{566ZXE +))IS8c;vvځAOYpӉʙ1Y  0& .ءCl޽iSZj:5a K.:!@@@@ T{( @@@C >Pʕ+п$8sڵpkN%ż,C@@`\zzzB|> ]vF) td0   $^-   4wƌVSSc ВW@ӡ'1|[lz@@(Up߿轈!--Z\\|8p]WWgYYYu,Hsٞ={LZzz&;wnj!  0!j Bs̙3V, v۶m5Tuu5n:r    @0!  J@FSuoS]vi)pI'$V%QgPˍPr^_@j?ٻwFR,L|]ㆆ lvvsI    @ pOK"  @ 9U9s昪Λ7rssb3gyo:ߚad~;x`ٲeˬ8t= @@LԩSQTTdܯ$B"{ȑfffZmm턏"L+4h"+--5xEC@@@ZFl   [@'6l`&֪+WUNmTCPdM7d~#=8UCN>=/TmcXs~!  gϞ]vѣGCQ#M{~~~z&urҗT딫J yX;v]Ueee|%2?܉={<`=</X.{;to<    f   0vٿɓ'aSS ox}4HΝ;#=qDdz'T~˖- VRR|i?m4*\@U[ZZl߾}iS8CA]c_y@@DPYoWվx6UwW]}\RDK<!$#@IDAT~ӽrcc\fΜiwZkuVgT ZV#i7n;>C9?gyƿy@@@@    X>OӨ_z[|͟?ߩe K8pÑ9r>ˋ,O U_]AJ9p6۳giTVVVf/F¶e  (*ߵN'Ͼٴi7B>`t}t?aSgy9ܷmu_kXUnܙ'|2n[sܐve]f7"{-OM@@@@. p@@ƍjm#i m~;w6n߲eiuosL':g455YcccHagdd*CEZZG@@g-ZtT(l߽{/ߖ(_*%UW]YqTy_!w HC#%|=Z6ԌK_LU>@@@@ U@@@`\ُ*D;Qܹ3j~jgΜp#4en%3fh6ܐHGyXn[`?v饗NcGC@@@0/9   H[N_r w/+VX^^SZZx_#_WEU~Mtvvw]o~cn'f'O|@^:'Nӟ]doy[ދ/v?Cg'@qq򕯴뮻Ι~رq|/_1  T=Dyy͝;HXy4*p/\л8 <@[?я:!wu>{*` ܽ~͜9ӻhD7p=3 Pc_@@@@̦] /\@@@`to| ~ov{ӛΎ   _6 \뮻|UUU$O^;>} pl޼ӿկ:{rĜ9sLz5?:|uu}_%K8 ^WU/l[w( Q.KG'}9 [U+++/@@HFՉ@?y9GS'lj>9w]|nFw6Qr׵u[GGsΫc=F[ZZ/}id>33 %{4FG!   I`:   ꪫ|wèpQL g>v]]]qp{`rˠv=ɓN ]4ܮ({*S;L}C穂y59m۶-4ܮ 8jkk /  S@unTSS:”FRG;eň|xZ׼&?tގzřٳg;G)ᗿe֮];'^B    )(@=/:  'pZaaad +ͩ 0w[V+\s5v*?N;t|ԧ* k5US0൯}}tG?}C9U[G>hYp;qc~F=¼n+--5UmSO=U(ZOO󻨎V2U!  @P`ܹn: ԽƍMzi/Gy$㒒{ ^ׄ_G>''r {5yf@@@@O`=!  'mw}]wu歖~QoG\r%Η󭺺f̈BwuWB??~z'л}}}ާEMU?9TPZi6ww+**뿬,nѢEWҩ}/?o߾=*`SyEg͚5ξon1Wۋ0'>l;w t`! S |Z  *Nlm}ŋo[vL\Wi1suy߹Ȋ?{!`^ӽtmY@@@@Q ɮ@@@ 5*/]4@;7|.T^պ=nwoovש❎{a.s)p {+,Y䯐z?+L6$Z[[)xy'خNXBU>\z5)y9)@@xh+WƼۿt?{l<^>%F^ywF|yyy5u:ӧG]̎9;u!   G 5+   0TnJKK=_7O~.r{m{9]_"*p X_}T\۝:u*6 sz)tqׇU_UȮJwA֟C.Z(j>lF!6Pj_SSӟ4jM߭={VAASݘ   0:9ݻ'"괻l2FOR3z .O~B'^uUj[bرYPW"ls^6t 5:B(콟; @@@@ >^@@@_}ΏiwU kéA`ML8pݻ<߿?5y{]fǼxb+++@@@ (N;g۹s;Ҫ:xOO)|+I&1Z6Tܵ}pWGk!wuN,    (@}1   0U1}cQC}7adQ0Z!2 uVhc 򗿴{Ƕl8TYo۷o)ʕ+l@@:fgg;!쁁}ƍ湹Q xVlذD-SO=t~Z6T]ZUݦk@@@@`   ^CϏ\4@@@@? P@@@`hO~0֏Kg>3=-Xzy޽{#ÝXdIԦ&WUU̝Q]UE*pCaǩՎ?n7pCpz<+V8GU9ssh_&:(~;p@k˝`F,D@@)!Xwm|^DG5upFwvׅ=;؏c{gꤽcǎS{FB>Xݟy8ÞPǝ* q饗??ļj_G@@@r%9@@P,{ͭXի~OsrmCBK.u7z萻Da~^ zPƫw1FSSuvv^Na ]'e,@@@ syyy͙3̭QiZtg͚H?Q~}9#E-dٳvWرcǜԱ[Ȱн!FgٳNԻvrZ;BUw{zz'ua    I#=~}6  LXpB_oٲŝ: #m/z*nU}yW'X Us[AA)pp1ߴiShݭO@@;w[Apg{hZRm^ym9muV4ݻz~y(ܮz͛UM}͚5Q~7 yᇣx+^aϥ!   .@=8@@~_Ɍyw]iUmP]ëNF8!g}tn+Ml,!M̑#Glͦ*ʐ W1  ( k׮ oQqo7W_}^kzW8Y333#bM+/~Mlayw`!   )#@=e.5'  -ַռUW;we_olo7y57naӐ#maUrW-Z䝍9O*̟9s&Bn׮]cǎp{%%%NEðn#  L@ZZ\Җ.]zپ})M#=#Q~;S^^nuuuQPm$vwL^YYT{Mjy{K/@@@ܧ@@@ n , {} y+dq֭M>ݩ"XQQa!  @b :S7nTY&jıK.$v$K6?իm8۽tqq/|)@6u_)?TSxu{/| C=    @H3D@@@8|u*ڞqSp.VSScN}*">k {[UUxE#V[o>8S~/Mf:{'GƪBj*'a(&Ks?Svw;f/i~{hxSUu*+Q]]=v@@F$g֭s>IlӦMN𢢢w*lFW_5?5t(Wb _qU`;utpႽo/~vqg-w{hg͚ܿ;w]__v{ f@@@@ SG@@ ׿u l +6UM?m%%%ξF[} /u\n۲e'#* FVz&`!woE:F=kru]}ʝ_l*T|'rv߹ꪫ"Ýp^.t;ݻC{Sn K_r~䂂Zu\vwO}ʩ     `   c;w=Cv 7*]{ƫJ~{;|>TTTE/lΜ9Q͸!wݿh|;0wG=*}n]xN[lYi=Xd:Q&Tu^a]Tʬpy@@L@#P-_ܩڭQM^njO]y6Rx._N:whjcm\J/x3X>;::BGҶG?]s5aOe    K^4'  C)O :zvŋ5yo5* ئMl<!/--ͩڮ4@@:Ŧº8uTԉuuuƍza%aۮjav=Iv޻wodw_>2? u׿M-Vӽ]MM t܎#   (0x KE @@g}0uggsI'0o<[`󥶾Ϧ[cַ"z)+((̏dbC#9DѣN z&ypL   06۷'VpkoyyyV[[k    0|÷bK@@@ c7tk׮k֙nWt 裏\ OJ--]ԩe   0u?t IUTTļ*3Kp{d7:kT.U!    Orsb+@@@ Z[[… Mu}rrrlpNꡇ5aL-==VZeفݻ7fESt*3޽;4iz  @aaay֬Yokk/2$Z]/T@@@@1 p3!;@@@&W@_ڵ9EEz{{#?Ddկ{"cpڄܣ:\ffY4= @@RW ++˹73gNݶnj9+["dޗN<     LX5@@@ Qzzzl͑}N;#*<@5\c˖-";q℩s'h=~ݻh ](|////;8{SmQTmfΜ_<  :666B!Q6UZ"۽@jjS~    a-   N]ڽMAoݺ6m|v-ǻr7u 盂iiiM@@@ TJiuT7u&|k}vӈk6}t[jUn4    S7G@@P%pUn:~֮]kv=o ִj]v`y]*unW}?UVVƥcG@@8p۷/p([SScyyyuSeA2]sٖ-[L#y[zzYf͚]4    GI@@@ T Na'ND*K򜜜rU~g---v!S(@닊l…/^>r?ym۶)-Zd#  :UUUe Knw5צMn4@@@@ K@@@PAℛO{{{566סJJJY 0u)M F^LxHllɒ%#   )-@=/?'  "e[n57UW5d7B>ڮeddXmmeggW1 0 *+ HXx27OU_^RC@m۶zzz'oզl#   )+@=e/='  "g7o6U9sتU"{.S%~9kll"YYYVWWg @/`Bl2ܪf2;I fr< zihh8m(TM#y:C:%@@@@[  $ߛ6m 9ik׮5UA -C:~UM\\1h  O [U#Qe{2|i{u!Lw=Y™#@j 9V韛R!.]zHmަ^k֬a//     Ss   {˖-д 'z8arWRUBJ*bS"AvoevUdC]SP?e&G[ݝV >DX дw^kii :kFKĖ*v^tO.WG@@@HUz9o@@HhQǩ֪ULUbK{OOS=,YRRb˖-#p7Q9'T@[lnBZj #*gӵW{w+s)Ͼ@ Q:dw n2ZݵV]!w{m999zjSg<    Ss   { jEEE }c=d wvvZCC5,Ybeeec @B (`:x+@b jsp{+wƭm1SRرcoree'yj?ymݺq Aʫ4   Tڜ+  $@kkڵ+pNѣGmǎ ̟??pX$:twwXT] #vqrbO߱ٳgۜ9sQq4X(  0'N۷v]xg2[]{ܦQ***G@@@RB{J\fN@@Eöm8\USp:Z[ZZLMajS= 08vzTlٽT+O$ߗʻwӧO뙩3Enn|ף橚; &I-}sNz2GBĺ\tFo    S"s    n޼904y~~֦d*B.`CPk 4@ Ο?ؽ hMu7>s h􀾾:fGS U=--m@ {:R}Νk+W4u؝F=\Z#iD7SGBb@@@@)-@}J_^N@@E@I7mmW6R%B];vرc!33J,@T@uoԑg,MvwPXTyHoһ7?q}.S]aw;OCE@U۷owjjjLwֿSF@]^@@@@` pWC@@PRUnWSe۵kך*ߦz̐OCC8q"prrrT!аH@aި@X\sU(NA߉@J@ގKST߂>w0QP'Fkoo-W]vQkjj ^ p/ Ν;g[lqFȫ4   LeSrn    [iΨcU8j͚5OrWe}]\~~ix*&9hmӿI 3^G{< oEx^,m6mzh5yK@vK=K!wX1ލpEuNz6uBP=Gxz0   S[Ծ  $@ss>|8pVPPX &2䮊P󭲲d!-OXAv=w#ddߒt:tˣ4y2l߾}]oMMX9Gs ;^iuB`Đ @@@H.u8Z@@BVRR2t|Oe"B r*ۢEܿy@`B^?۝ǰjWߚ7AaDΝ[ &[@͛_5y#&̫k#@OOOJiJC (dEoԩS{oHuwu0a 0!!F*..qĺUիWF .BYY-Yd'@@@HbI|8t@@HN.ۺuk [aa\p0/kw\'k o~~HEʊcnI3MMM&WoSGZS(    0O+   @ (i&4,ڵk9+7!XvUO]j,i 0nVAXuIS( lFFHζ 0t^ѣP낂GiiiC= N>6yD#Z͛7onhT:ds߄5kpEa@@@)q9 @@Ht}eXUYW_Fgeey3=BUau֭W^MP`ׂ@`hg)Gj 2PbG qԩEܿ۩} Ou慠V]]mőyL3F_uR3gu)    0'CD@@Pю?uN\sss33:ф{zzp:`x M{{jUǚ4{1g'ԮJt"N78q)r$M Az!c{Bsp_$> +_oӽ:h3ʇWi@@@Hf|8v@@H ={XKKKX(I=V]gϞ= Eُ9tpR5ԑH|SLmrWuwuQt$M ϟ?m@ 0;_\h$Bjjjx>;G@@@ >QҼ  @kkڵ+pK,r] V}V+o~;wGEOssz D@A#) uQ@UvozsL=E#i @@(J7nRLiib޽N8_<    Tܓrq   ]C;w.plʕ6msöGm̸ !M_v   h/v4 dI\T ou?}t`9 @@@@d ,WD@@صkF̙3f̘ (䞝a   >2fAbԁ^5z9sU… L#   I#@=i.   p;|pPsFFF`9 /p   `ׄYMMMC}WW۷oD@@@Cx(@@@ࢀܹ3`Q^^n,?w./+   XwO i+V#    @ pO+!  @RnhhGoAAF-cfbnߺu1 x*   @Scuww1 s MMMc    Lܓjq   u|NiӦE-g&Nr|k^@@p]]__o=TrwI&Q#͙3'5Ϟ=k;;Gm     `3x8@@@ Z[[رcQǭP{uuG-g&#@IDAT# 0Ց[ĊD@#p:aGveѴ閗g3{ii>p& @__[GG={LeeͲVoӦSKg*V!wer:#&hZVX<rJ۸q9s& g,c@@@Hd|u86@@Hx}I{q.[f_ B&VN_Mpqn;V:`a$sȑ#I}ؑ_ lΛ7 O'F2BY,+^tT}jf{m.[`6s)© ݼ"s;!իW[vvvjcNk4*Y877]4    pL   0ߪm Dx1= 밦]߿YTZZ_<$9v܇j _Yaa!!͡XSR@ o?~ wuu<_}&>x𠵴8L\@ )p{ssXM~]OvCN=ꬹxbsmkx]=k,w    @B pOA!  @2ر6}I\YY]h[Z___Ty9B6Ӧ[VVVn{3$ MՆ1Iv@$fw~4GX#ӧя* @ yb)+b(:8pb:Wޫ;\q]PVVf'OtFp_Hl͚5y    .GAO@@@P={D_]tQ*q[b~|` m۶-r6zG8SiGХ— a0Ç;A^pF6RP elS (,mzAɧ鳙) ;ý*Hg7n4=zޗuLC@@@U{^ @@V@l8>Un/..,gAn ӾY@ oWAKUl`MJUjWp`RC{{<ߒzl.0T]32~ުosoE}/c 0BYX    .0#C@@J@1)N=gϞn_|Gzzֆ zI9#PvUkWkn16"h6FbSYY3ǝX#h;w +4t4H GryyyVSSc۷o*[nUVp$cVK. Bk.={6Ѝї#   @|F/>@@MMMmٲeS WTT8ՙGsGs8wtt8!IU͙3 Q*L9mڴ6g= (ONDzoV=>}VндLxݳwB%ԩSN}ՌbM:k= n:HG4@@@@ Ɖt58@@HhXggg1Kj R**$x!u4PPj, geevJ---,@ ^7nt4,ܮ yL:;w.^DT%.`IU{߹s=3٪LCW= 7hMy+V:[ss:/   Lȼ@@RT@v(qWȵN<x.\X>Gs8Xjƌh"[~9''g=" K 33Ӗ.]j^z[FFFidڳ>,{zzbn ?x#H:s֭[Mawʕ+B U@@@@a vl  pojj *J0mbav+rW>wvv04Uhokk!w_XXhӧSaH06@&P@yἷ… ~T ^Q0nw5B u)eg:¸8vٳg:ڵ+jg{9s@@@@D Wc@@@Зv̙cԗ U&F}v D*h'*H@ǏwGУyyyCn +{|kkd]G|QU4D#߿+mn%5k֘hc6ڬ[   *@YI@@@ kT l'N%KlѢE J{KK1 0iٸqo}p +x@) ٶ|rKqZ5>?N(^i 0z Gwe7_YYif͊zر#~    (@}y)@@H.rUUeff&$۷ώ=8ŋ[YYY`y<r*DLﳛ6mrFkX~3z?y,GH\}g9+{vY'a;|%rb Lv=yM˛Wa4At@@@)0#V   ),*3'8ػܐm۬/U]4j93 .֮gΙ3JJJiӦ I-peQQemmmN:}޽ _*,>I hD Gy>~әeҥ5    0}X  )( Jަ/w,Y]t:;;mΝWPB'r u^s* 8q www<- `{NNNX 0y[?lsܹ:uxAܹs X-^5bFY`w1quP"u.F[n͜9ӻi@@@@`O5/  "===Q`ʕ+ DoFU@UMJ &>8ylWxfJA& @ dff*8]T'TsG]2UtWН $j=BVG猌 FOsXQQa]I#f455Y]]$@@@/f)   G+NK\m۶Z6}ʺ!wmN˿yRQ@AuVw*C2Pk:XRb9 z̥{.+..s7oԃHp{˗/PmѢEQ˘ @JX"Vu&ctZ4:Fvvv0G 0j ϛ7/kk۷;'O<s;V 0)Ϙ1jkk{={ݔ8 hT ^) = @@@@q >Π@@S`׮] ޖaUUUNE9r#{ps̉ϋ^ "Hzg7c^Rٳg܎  &vZ;wnMDI@ 1r>'#3C4-`љ@@@@9Jr@@@hkk#GDIWeaihii -]TE.!DB_N:e `UZNNUWW[]]ڌ H ++鐺zjKZggmٲTߩ5sX@ $sݵgF݇w_|@@UMaٳǻi@@@@ @@@ TQMD?dW/KJJ4iN{\*tN>nذ ppH@ bJۦMQGcn M`*]sPQQF>l3?UHjvСAGko<    0cE@@L@l744磎\.\tww;4{/((e˖'r߶m[:O~ƒs.pSE#_;3k,+++34" @P՚*5STTd-29i$T @ E;m޽y󼋙y^޶c6}ާ!   {[jG7:#::u*f,G ab֨jo]N\}C Lp]'WXagώ۝ Q+w]곾8˘F@@@[x?@@Hx'Oڞ={YQQ1hX0* ֚BSr W1AuDٵkSJX﹪k*^\\L0$!Lܹsm͚5NXV#65}Fh%6mMX@Lp {Du0>P]!wkkks:3   d?   "\i꛷ق @sss`Hyz~vvv^urvK}ryձ }rݶeݙFXdl{'P("$>oںul1;U 8 g4 DHp뮀:BGZߧ:N3+Ǽ<糿vI%}?     0n|8n@@A@O:uYYYN%j!3qطo=z4o˧BS*9ϑ#GlÆ vГVͲ2[~-\4OC@ tWV>l2Sx6^@@^@!hSUE9!_>8p B Oܧ՜J[n]v*57 p aB,CH&TKKKY›qFӽ Hpk*+Vpg#Ǐ{F晈3埑dw'w}־uHL86%<ÄI1`b0f0ؘĀ6B fI2I03vZo-K%j,JGԩs>GV~e@@@HD(@@Hy lU-kkk50ޞ'OrO a8P۷B %%%rMk >! I:hMnݺ%tX_{{{6 d{={Ǚmm@A:`ww7In@@@@ [g@@2q`i$loog I3. ɶ# ֌,..F<} uvvʛ&)//  d@QQ\~]<CUܹcUu4.BpSYgsv%L wQÇz;6b@@@839  V_XXp7-\@ ݓO:QD}oK ;XMъccchu7 @^zI%ҿ䜞۷o?A푯4δpڬDDy:::Ѝ s   #}Ixx,   {;K@CnwW6[[ȠC099)333~:W@FGGpiyڵk?Zx@Ammmr-x2;ikoo/6t"tv:={byN+011!%A@@@<=$t   @& {Z魡!N3% ZawVBׯ_퍐{\ϣbꫯb'֐JWWMoЉ @ fWWWΝ;255%Zݝ@"GW˓7nHAAc,b:؝<Jcc 5P     xy<  ښu:sFKؘh4T^^eBY{/777_ԊZ]]oz^#ч 555K/IKKK+59==-oߖ >Z}moo[ ZU?x277'c    uοds   ZM+[gg F@[\'N=rO }pp ###o|"Ry[  hUnݺ%UUU7ߗ!݈Љ?O':}߳RzHmbb@7     pfg&   LMnhhwq??*EwS777Y>5NBe ꫲqs tuuYv @@ v"G|kܹ#i"@=, :-yw}ooxjW>   U `{@@@ 4PdۛV\b> lnnZ+ݻ6poˡ{dgg'[^_-YDw]r$hf)oIN:k>*wƆZ]ϯNڨ؞Gt j%Av v: -wttnOC4${{{ϣQ:]gqws?jvnׅ   Gyx   ӧOJa>v h0)--g`Alo~IJ~#A`QIA[7( X~]IP8L3!{נ=JL;888GZ]w?:HH@tmkk\zU4DOwY0@< vF|]}oؑ HEE QZP7pP_u;{@@@@ F1B  V/ .'PT{h~\~]nZ|8[hϟc>DM'xwpPZ_aOכ Mag.[;D@:tp~DAgҊ2M7ϔ=nOw0j:֭[C( ^ayM/@@@l WsD@@ K44b0UO[*j%1&wwwO7nigА{_C>x#fC&< kySAު$ӟT7qz]Z.y kEĥSx}}i  |T!ϙnaO kn~WN%Ig ܞˣEukfUs=yMV7{377'MMM{"   Y!'Yq9I@@2_ӧVe0LVIܲw?~ء&G? gXy"3>$7/K~Só? ·PX^мY4aW$Q'OȈTDoi  p:՚=Ei;wX^ֺWۓ{ lO:ZCdllL]ҽ-03ٛ 6cW>   D M   Z ^%Lš";-N rccê@>tFYUUfm:ҟg|$'J EX9< Ȼb);4XM X5VY+]~@8@aa[HUBtWVVCsSxo8Pg}+//:G? п4448f+t^x^@@@ Yq9I@@2[`mmᩞVNae/ @jՐҒKlpׁ:HTe.=r<ΆTVV&%^@g+E׭466& #   d  #iw*LVI̲ڇV5T1Η^PD0cow-4WW8|ym:  ϟ"@͵~O:!4xT+Jݞy/皶XH4pjZQ|ppPnݺ[%޽ثAႆ   D M   ޞB"U$ ]ooZ1_'cW~ ΧdCj> 8ޑdR#ת'xG8i'z=ʊ+;E@<555R^^.cccmqqQGxM2 R~__nJ599)GGG13hiݙ Sϑ(yq=࠼KlZb N ܼy׵r7@@@2Jdd@@znnq999Ve0B-U7>K@~t+++j[[[\v٪:@=uV6gw,U>|h 8 q8iO_;տh"a    Kg8t  ӧOW_To*Zx ޽{ ȕ+W<.gsrpS];2M!rx @ _}[8U h^wgOϟT}z"LP3+c$|h$ ^y--LR\@qHnt`E#>p{G$gs{+_As:^̚)͗}xkkkr]ǹ7RXXg@@@P*}  i%011 WTTP+IWQ+ yCsQe{?l2EɭII-|&x:XGgFX^XT4 JmYriy+8oU7ۘJA/&`™I@@B T}.**rwqtI?g@Cr_{0"&~]&AiGm$ 蠑i_isMؽ]jkkr>S5%!r$o yV?-<yG^=,_@2g;JIh>?%< _wυ @^  k>|hUs<2y.> 'Ojw}ϻc~W 5YYnܸJnuڵkr=r:Y@@@@ ןG@@ mϽ=j%q|9H w|y__=;:@ 6Χdm"+QwtG_^i}wEݖ /mUm}?i8-]~|/Y#tt?? Ȼ*[y{Hyݞ$]PVyj|kY^%#C'    @@@MYm?PhKE5;J*Þf<,ڑP'+2%rxX2.oQe [`0٩X!Y9~IR=y χk⑩PoUT'<ߣ)u?Yy%/6agy| ˩y}!qOO{ JCC WNq6x&^j<ۤ?_I_h    p@@RZ T}(**rwёW]j8Ó!Po_)ul2.Mn ϑV[]Y\aTQ"S1v19EI coxT?ț; yS>hu-/g(4 [O }()M Zu Lp aDŽM656ISs?Wn4^1Vyބq޺y G ȇf =4fˀCOjxTPy^i g7\n/S766^~MnOeUV0tv VI̝jkCԛ   p{@@RV`}}]rrr%V@C2C{  C{# ^#.@VE"mB_ZQull8]]RZV3lmI9#3|8`Ox>)Y hf+IZyVVCy <3_3p>:+kߋr2z`_nOb B000 oߖ%t0iPS};~lvI   @ pKω#  ZÇloo"S%XڮwPgh/cBwmEF-VX5_bw?6BѰb\ evfVffg"> F\O'!SRb%Iy-_]; ywx oMz׬.I9pv)@r厀5'z^Pz ݙ PXX(7nܐIu^2>>.:~p{p3+w̌X%N //Ozzz9kWUU!   @ pkϙ#  Z!mb+//&M'`A9::r[?oiiqbʇG=_mm1r hHU#)5yvxEV@~G u'냑'u_qgVx~qi; 疗WWwV?O kpx\ǬJgIX.++l̪2˜>#}psshtK/ϑ%EgBM_t͛7C]"   @ p‹)#  :ܜ0upFa5?{ Uq?=JߖƟE=`_@_L_mdITHl*s^rSȻ UA8@=& OܵgOgˡJF{(9<¼s:oXϟji(Wgnc^^{5RIig ~vt~d&BM_|Q tuuښNuy~~^}A@@@ ]כE@@ VFs7J Zbt 5MhG STvܓ'Ũ'"e5{m G%sl??:{ݨT]&~@ teYV?-<Rd©5Xke 2M!|'y& Ӈ*grx؜&ʊhE*թ8ydJ۷oAd||\}܉_#sLuP,,    5Rs  N8ri$ Znll̳+VVV#~gehDv_ #bmK=*h|4)K7z;FаEVgyg%mY'}y" Л[Ox޵7}KZ\}_599SSS!]ǀVp$k:4T!w:YWTTHmm4^WW'_Lׁ   '@=9g  @ .Má=*յV741Ͽ"oS1x-YM Ndxx ׬/n@ I ϛuy+ǟTwT7L8LkMug}TO7;Y2iP>e<ܞ54_CCCCJEEE`=@AS'e[GT>[QBL{67dddD<+~gH[ߦkON wwmy{Pބ5N˟TY|]X!? WnCۙn݆'!Px]]]r3+W7"    d̾  i! kE.{+++EK@T~ga<<,%{c`s+x&;?f}}owOeMhڽe@ 坄' o&ouM`7< A{[4.C _^Iӛ )yNB^엑11b7oޔF9:-P^^.2>>؇׿_8Y8z)t~ϘA[@@@l}}9;@@R^ T}.*sCCC)uw!kmm}ژe>    @ pk˙!  M:7-q299aOOylҿbpZ˯ȓ~H%Yr?<<)!!, Y466E@#3Aܚjx -ջ&Xz75oM.'uNǂ/׽Un|P):.lE@;wCmiiIjkkE#$Z=_߫UVV&I    4  /0>>@XXãZÇg )ݓ'_ROrr1!9y{\4r5@'Vߊji@8L-}'\ܞ}=T#Og*--.k`GFF\͌t9ucgZ^g@@@2K{f]O@@Њ[?voaah.ZB ؛Vmwq? >a} dVk۩3ummM4rtt(-)kfYG o*TyVU2ofV Ix<’irGsire U+t @@4|6N3l,uZٝ   @  (UC_wеV%F@?쬷gJuJ"o<]{^%wm&ܗDgԮ^*D¡@NHfxhwO'gwaxkCUy߼_pT'<}>AD@gxҗ$O> { -MٴhW_}ձGWәh    Y!   k{ӊ\W\wq?D0<<,zko֔>g@Ak~eS%вO;3+3Ӟo MxVҁ \T[]~mbUAg>S}^Nn Ji-`ytķ<==-Y,d@W]Џ‡>BM/J|C,)Oאny3W d;ڥ^>>6K#u•M p|P֭ Û |hY@d{kq$}+ XeyyY›kֺpwhkk޻ߔBM R\|4-   d̸  i#099)J\ZQgwnNNe[v_/Q5r&?b-~tt$ZUB xQaTF! Y* \*Soll8eߙ 랷At? 絪UA8,f̝;TTp>k:K_y}ikkkƾ))ett4<66&7o q@@@2GdC\K@@}Ji=༼fkt{ 4R8c:~kı^CsT\6Vp{*^9 @.Z@߫iHm]aE|> VWI~stK7-_.%_V˗^?F܇3x,l>~DN+Gz,} D֮WVVb ["   @pOKŁ"  ZYpV%F`ffF677;+***9:Y@%S\$mɭpXdW+S=便gǭ UUU200G@f[= }wlmzl|I?vT|#77n@ `Uq>/@qYh    Y3zr6  ꪧbrqq4661ہiGyW4BC @A[/@[;ڞ!UFUF^*===DG@Pi{Gz_S><;g n7ǐgmGmOՈ <"5bqqQ!dl@@@.Se  dVmSxkX?|S!Y5eoJt=ggj!u?x_ioinN^<2t  NrYZZr>N HwoO# p<pa Dz699)Z1   #@=s%g  @ ΊVԲj?̌lnn:TTT$>E)l*9R3±}WVVdhhHF©&q  p+WSZ1>>.3}NS>.= @@@@M@@@ VY-~`0(>&wqj]R:?~^ <'3 > )((@@ > ۫Wzv+ޓ32vs>W8q4(4tvvzv3<<|ax<:^mmtP@@@H?w8b@@R^@+eMLLxS+ki-ZQQQ;X@ Qͯ|D1n?Y='#侷gU<ߕ+WS9ѳ!  ymnj@ lxƎ)|1(</"@F]E@_{rryk=ٳGD9,V#   @wq#  *033#{{{ Eeqɹvvv" Ъ$<@ni%̵&-&=侹)wݕ@)aφt  $DY:::3X0CPǰh:gљh JyycG[[[c@@@C _<8J@@dn~llsp=U@}#Unjjg)Uқ?i֧?'q,3Ӟ˗yЁ \@Qq\q=X^'ZKT=Y ۻ 䖖H_Ҙs㟑Bsss25  Nt,l  pq2p}SYY@ 'pF, p?R g<yhO xgk= %%VPwe>@@Hgܫ=Ǵ(&Y D p.KZtC [TTʊ9X@@@@ ׆#C@@ -V²VъYtH^t=F > *GBidW>kU^;5><<g@C}ri  %;^vM"dhhHFGG='U_ ׯT>ws׳Dx_Byو@@@H )q8@@Sɓ'M755ٻ4C9::r#96K_r_]]8G#C  >JUUUpٹ/% ދe8mv6{xx555~ّ@@@t WcD@@ E&&&vɢTpm{]XlyoT699)O>uw   )&@$.  @heMj0A+dݕH"M_3h/P@ƴ㣍MYxɑo5I@?H8! i*!w}#\~}@fD62j;$Ո  g](`aaAXt&<{;88   0  .ܭ9t:##h `K? e_c:Y|muւA M奥D@H_<+iZ шX -S"m AOUikk %P8Y@@@@{\$@@T*bRZZjvdz,;::}, Zs/}222env۰@@ }?~,=ˋ!nX(Ϡ}6h laMMM;DX@@@@ 5@@HyH۵"->>>>ىNWCA@rJw?-9%1+.w:ՠrw iSK؉rim q~tw hnnh=/g    H_Ig  )766},] ׵*ng3@r {W_}}Ⳓdm/ˍ7xB:@@8-^_ 7o܌8;T*.S=_`u6ޱ Q{ccc;;8X@@@@ %@@Hm "g_4Vn8x)$Po?1Q20/%%G=&=6B@Cy1䮳}>qh;v)4؀!   2SRp   'Od}}qUUUTowoabbBScZ@ \}߿N#ojF{_+r@@n+}}}RZGC kn^F݆ HtvttTf+ "Vq#@@@@9ܟ*@@p hݨ9Ɔ,--9۴ LFg?&m1+YrSp@H[X3ͬ>ސGdqq1oc.O $DV***ڊ{ޱ,^{_|N@@@ %@@Ӫ_eȳj1h6ZHC Srˤw?-⢘Ni?);rSp@H;C'!!w=P81Up?6@ Y]]]]!ߗ3th#±G@@@@ >@@)YRCr:xЊm42M`Vv~{$ˉ»+S3 ) y<'Eš,//cK!cd J}}co3X*"9f1{#   #|:ő   @ VpJz])=zy`Jm@ udppPb:'2A@R^ p{w@)3bp~e {fv]ϱ U$,    p/'G@@ 4z{EEE| V\qannh6$cUn Lx߻%9;[$p*).q”^~T6! \@Vr/·###^~_~,wH@cc9u`Xדxhik/ s@@@.]_@@z{rV\k4AC St#nNNs/a}#:Vrwp @L"ܵNhoܣ "rம.Syو D>mKVܝ@@@&@=i@@`Z][쭰P2 LPDCfoܐR)W>b_}#Yx2;!X \@ UrC]֭:44$Zy͗] *LYsss>&ޞ,..mGl   I Vv  @fP=Q+i5wӊlZ@&lmm9Nn(?=w9#`@ NNé pgۘ*pwpl.#Uq{_X@@@ #HOde$@@Hf핕,loo;X+8X@ &&&duus ===R^^ҷ#p,U=$t @ Y)Y.Mݝ]ږ͍MY__~[>]:3>VACREz`HwIm]X@hPR+D+C0V` W(h݆<>`V$5Cgܜ\Vsr|z?T*˗ϳnu9OKC+pY񖖕JwwhҁnUݳv<{D:/M@S-..:~?_ RRRriǕOUU۵{]]{UǏ   @ pO+q#  DUAFJl42A`ee EnrnegdMhmY7-_ؔQ 1jh VIحg]Tcih>DGڧ k >0i ]c j/--IY01p@vu<ܼyBf&}Ϫ!P*4@@@γ"  P,d;;;M?.tЁ1ÞSЁ1RP8#͟9z0υ{$ѱ8@gNnvJ졀x*aipE_5^T\$E [}!@v J=UeaYHUL>~` m*v1̢!w >X&:=~A1OjUǷUܯ^Jʜ   @ pO+"  d̙۫1 j5`:P@ ёuv3*eY~7pD燤rwp@V hP~8dC2NV_yx WTdB/LCHp{Hzik;7cOg ~7sп`4"Uqݕe+~=@@@W _}  i%zV_@+k4]@+jݪk;1m{dA/{gyޠ,Hݧ^#!ꚁ}1# ٿ.58g p~iͺ;^>dӋr+x$zzzk /O%C1Ft67wTN.4bu|[l)4ʾO# j]Uu[OlCqy*yѼ\hSt+W,:PgP 7Z~g9%#   Pd  dVo0Iuugp]]]|@Q#{hh ڏ]Ìn?o^y|~YF9:/9 NzB:HK}4lnlky2>˗|A;zߺ5ڢv]5PMD?Vj&0uz?Qt?2MJ RRZ"fYie:\odr=thOoܻ{z zu30)Z{4!_@GG=Ԧ}%m: -..D0w@@@pC @@@"UookkɈ睛kjj39uAOOxґWU)m}Kpw/Cc/E<rЁ@J mh?eyСp5d)~(yؗ&WyMC`$o ewT͏st@楥Vؽܚ{&^繳THp{O$˽vÇ`1EkA3@@ hYÇ&&& O@g0u/:p*Q   #@==  @ lʚToO*A,L7.A@?_^^,>x:Lc{#- YMCB)#^jU S{Kw{5xTERhB`X~*G EjWxZYgwW̭V8 }i4 )b ݵoGƠ<ߎ5Y?$Mc«F-2/Ý: 776E+EEb/o~kA rpPw < s ۣ-// 학J&w @ yniTTTXB]펩uC*;XH9aJ`?8~]?@h!7+W0@Ҏ}@@@,@=@@tJZRJTf~徆[PP A) tx䉌zNA?O֠y} o+/rS +3պKJKZscq Az K?NM:By: bTVY(`-50o+++/`HC dB=t-kKx`w 3?+"l%&&&A8Tb_>rjj*%   q p   UoBiX^^}Gk0}J ࠸JҫUWI_o$h*pFk'E_"nJ=" [@kOj,&08TCvC&[_ߕaw 﫱VVWW/e)).*+4F/\ !Ni00%B-!+Y ff6eE>gmX!< @@@l WF@@D@+PVO@CUwwwSq֣BGDCxDъ^O|XfџT\Hck=!,t"J'UׇXv':DҲҤң[Vw@)@L-53;#=5Uu^L Y昪===r}9ʉp߁i?{w~vWKnInL0@83 Il 61x;a N2 CnuZJKMV[Rުn?Z#~]〰@{LI_)΀ih%@@@@4? ,"  oƍ*>e!Y4? hPGD E3jp{04V_r?羬oxo`ev_RJ _:ex&fPzSSS']jN*Yp-Y[ZZLߛ%fA$5# @@@8g  _){{oo/xi5J3f Lj*k\ h^,}_֊we~F>!릓uO(X@$\emm-ԾkڞjE72f=4@>T$1 GN+܌e76ğ@ {p{zQgWH6~w$èG WPHd Ԡ3>sI% tЀ51o 5! @@@8g  [@/--N&W>}jfJ{g<<\m=с0e'7Yvx=)&򻭛N r?`݋hc HYi7ꤸ8 ΚklHXy--Y=zIP׬*K6@IDATe;Z@bL]~䉼 $30[LA^;d'   dVz7@@|#]3SiUJ^UT)Q@okvkikk R _(m r?>݋k0c *+⃵chDu$\|-{rZѬO曛3! ~(5*I}{, ~\~]~yb}u'fqojjOHtokk+^ ?@@@Ȭ@o2{<  9pޮ~ 㔽]yj4 ~/Z\̕XRϯB? 7Km3Vn`ُ`ݕ;gN_I)^]kY…!PC3A!H8)..-ePHT 9(p]EXuֆ_7:@:YFٍϥ;]+]2Mx@Qe@@@2'@{,  @%S?`<TɊkzӓvvvӧnk濺:[*JZ狟 NS?/e׮H^8Tr?kkkuW=An Aoh-lmnr`\vvYxctƲ$Rx50X4{FX XܵwoGR   nd}@@@74RYYiIorr޾ijqkjjLu eXq}.; fi|wO5,]5L5qlA:euuUݻ'wʊmkkko޺$) 3'^.#F*;urYZZ"4,% =)W';3>Nږ 9(.I8zxtFgLWkс(jD` ψ 8媯!XL   pwoEK@@|'4=k;%}===G  {)Eݔ厛6A`uuUܾ#?ay*{‹/HW+>܂5𣀾'ooonƳC%= thI vi^zܣGo50t }=>>.;JANYܧy]9ųWu    @@ XkG7hp- vZrp|<*Y;::L##$NťS#   @\0`s@@(@ɾbt>itN{{{ϴ/@4K m\=!:ţ%YwKԒ~tؘ<|PvvwA4еU^uKTPT"36+KHX:ZmԔlnnZYGsNYs9}ƀ?\9   uܽ~  g8>>#uB f5Aa){{OOCȮ-LG ng(,|KrF'$ ޾LLLȝwN͠FGFʕ+RYUY8%dDB4Vg}hnnNglm%}|!@p{f.S(e$둓 ҳ#9nۀhJL:ΪFA@@@ lQ   #4]}GoVPfkCW ^p4}.%=9Qݍ:âq    p@@_ hY 3XP]m-tF7N5@!7 -3vwwMj ~l75* i)imvN6jklDQ;;rolL>}*T*ʕ+2zSR#PU@ёQNEȝwl9;_е(>=MD.]$XǏU,#9⮁Bwe9Q~3-R@@@@ }7  xV@c2R){{ooG s qܮ7)J[~J$y#Ö߽gqH;'/:88ɧrwl' V VQy444xt@uM\zU]&555g,mw-)E-3"֓bKښmia {ԝfPt#'@@@W  @ ֛f%Qrڲe,do?'ʒnMŹ_FKm4$Gk-W rOm:ܾ}[Am}}}r illdG%*@ u222y޾sGfldGZFja F+zxd:u= ࠭mT  ,_/C;(so   Z\_  @eooϴ7fښAԀG;Pq}TR]]-PXr ]8E7>D]76 ׮JUe:<=3#lTN`{k[% Nen݊u##lsMrtffgm< a1_8ͬ4N"   Eܳ͡@@kf~}jF2k!{Uu/ svoo% lB:V/H戫~c:5"IcAk:PѣGNUnݺ%mmm sB@u޼uSB]!ǿu:Ng;z8gbsvuǞ9VljjfSXVxF C, .fpEg`T     =-@@֖?ciiig3ֱ|Ύ-Yuut7N@L288fjJEHq7eSI< ؐ;'Z02:2*.]u5Ok(7\777N,"E97<dp{ }g,kkkIg1c\hwi,dq7j[:â EXF@@@ m؂  ۵Ý:ȬVֽ"&&&lNO:{~R]ujDJfwhjr*8r8vedtTkm۩@]"X!r)/+f~I| ԣMeQ7xO>H^֐ r ]g#{zCgXd]q;    5*    &YZZ2FŽޞ-{foש)xQ@ yk, U,_@mst_9Z[wީAN*ڎgm_X\pܑf,y󦴵1 PH r [߄ܾ}['%=Nlj?W?_677,bdTVVwOiXfc4ng@@@^ g  >XXXe"{{)swsss烃T.nmL3sh,Y Ag3?N3Mؽ174fm׌eeeT *Z\t)ͽpxx5XZFj&{쉝3 ^^^6Vg;}{#NыE@@@<%@.A@@ϛ;e25`&A8`0Hv+^8>> [wE3S'K?+7:_w6Y#ܓɸݓc2;7 DD6FG нslnl:nu=Lp0cH$b\ hwvkkkrOiEQgf    @rܓ۰@@ h}sxZvڃuX2k@m rե=nQE~3RX`![&kD{2`w~ 222" v*@;44lz]:rJK@ .7nܐ:Gy{'6h>PIp7/wg\tI} v Eg3 OfP 3Q)    ,@   xV`ooOtJhc,pd5ZؐsM[[- ~؎E hԉ a4sfpNkZ:~}:h}UdrO&Fݹ{W677ߨ4,uvtQ4Բ @yy\zUgߓ{c27;W{rbsѣڤ[A/_=LG"[=R@T[Lx:#Ž&TЙEgf-@@@p مZ@@<+`:ll=1=t1ʩӢ[EۻU,HGm~8=+?-wpp > s(Y^V.#F1y"&z7ߐjAwvfvFim{Һ=,:3}c(xM@h8}bβ]iEN    0'  xR@oxTƢSEoee􀺺:aDX֖͙DR!J:]^_rFu6;NZ[[RS[' @*22:*ݡn'۱Yܽ#]Hv\dpO\t6fsh(xI@?{hx:3Žμ30hn2   ,@{!_}@@w:Nm,@WHyьB|^8eu% Iuu z)np7hW ?N ܗiiI\rE4ض @瑮PJ"hi}ͳgyPAp?.bE{lZ ;R|m]eSw&dO ᘾ@@@(\ s  >wc)YY h`KYYmzxvȅ̌-[eetww;3@Ywz,3{ﲛKx) w255,5k{CCélDȜ@Uu\q]:;w:0/]/7+] ~^\4772:{ r %*љEgc0Q$31~gM`2   *kp  xH ۦnmmMi.{+N7`;::ȂɫUڒYfFjRJiTtoOmljZB rۗ{cD[fjhfT  @vtno_\zMJl9cwdks˶ JR̠vg39cY]]ec\})@;zXd}}X2   pi  Onnk;%=zs= 8>> BTWW@KSSӲJ4v[ )}mmMݕݽ]["(#aȾ@m]^Z#,..ڶv]% b/b/_FBEt}ΐGqH喖[#l@@@@p/ " W@,6hڸe- ޠ-//7 ^,TVVS!b䊫_/~UT=]gfÇrl VSQ@ KիnV׿듓A:υv^ج/Jܵ}355ec\ 8eAN*岟^?~e>O Zuw   ?w1  @ h\foGZv7Z"y wcA)*#E/~V\us&ǮڦjAGnbj;@Lo_o3= _X.r_;P&b;aKlecssЊEr+3Yr%ѭ32   opw @@5{vz3̳Hf⢩7ۚ5Ԁ,:=p( IF&/G]M(߂wwvn;2w~O( GKEy;;rz[cUq|Ta֘:c˶GL:/hqM`,3Q X N#-@@@?wwY9#@@|%YیEo(XN!N)f&%R BYʬ@{\4 ;hsUT%]I8ruU\~J6*@ c^[' Iw۱33#ZnI_bP?XLO6#- Og3M*ƾzeݞ~    .@;@@<.4E&O![__ hkk#p8W$\3Kuumwv#ԇ꠫?Տ~U[7D`;@ .]˗/KQ_kـ@|"ϻB]2<<|uuUΈv]3w(b i46@fp|rpp 3"efwԈ@SS롱0[Qe@@@BN`?8@@ XonA|ARKh fd 춶aEUIq]}Wen)}ksK޹kYVZ&#F}E  zqTU?eޘhW ^G$LIggk3ss hlcN߽0ypAƢyd7   P@@73"= (.IgpNI(2/:55b, hpΌg,3Q XgkswXFK@@@K   @ 8ML{zy~~Hȑf`f+**^@Ziѝ];xkU{7'&&D:C^*M#䉀gvfzfF&N:Ndl(g2YrH 8}b|Кݚ :/NN"   p_*D@@ NY% fbck@cccA?'})穱twwYY@;&\)Yx3 g3z Io_o,P +vv5-.-CY;] ~9IqʃGS:𣿿߶ uzfי(\܍emmM"e@@@ R4  666l7ޞޕutt(ia%W;SƢ0۰|Xʇ]?Ϻj붑Wu Ǐs[etdI6*@7KuUdWWWrcm *%0wܵsZWWg,,,XA W]]]C[ PapOϢ    P3G@Ғo---:* X @4ӧnhFFoJg(禬}e?:H)p2X)##d @ kl4ؽ Lp{=N'P:={ϒ}zz:k=r}:C6 plmY3cqNиe@@@ Ap9G@@ @kПfm4݉e۲i:` X\\ͼh,;nܸ(+=1M)>?E31X. t쇥|貫?_4 5mpQ} /:J|=zd{  oa1+) Y#B  ~'D@@@ pϳ  _@+4XorlMT lmm57d LMMٲo32;#UJQMw\ME> < A`-  nU֢ﳦM[])؟G֓?[gs];9dYܭ/ y:se,Nh~k   }}9;@@ Xo^MfInYMoooez45`,hfE}~f`$(RXsW/O"O&]>@IDATMQfӧ.h`455ٶQ i552:2*eefǏm m 0 l10PFpxhe=E?XF ',::YN:擃 So6   @ C@fN/75N]E;;Z],/.XO^~%W'v-o}Iw\OQ&23;c;tiI\zMlۨ@@@2(##R5_YYq۬X ۝T ev5/8}H$чЙ_w4ـN}ooO=V   yvA9@@ hƟ uN4K6\ hFENsG WR-3Od]?j{p䮙=z$KTWh, ʶ @(//k#D3ZƆ<_N n?(7ܣiX g Zr(**AXsu&3vN.//   @^ D@ua9h~g^:eoNqBifm7ձ s#˿(僗\O}Ut%]>|R]]϶[^QnWh V KSSmΎܿNp +%);e͋ۖ)[O ӳVai=j KVUUIeyvwFK@@@-@G@# fjnn7̧A WĂ(5K6\ h&Eͨh,zӟ",c{Y)r|c]dl9 Dv͚k-իRZZj: Af;ߋer`Np)}|YjlGQ@6s5Qδg,}۱Ylnn4/    ܄@@8M9Ғ^4ա%folr%M`͸HA4~GOkƶhT|F]kpĄێCCC زP )}'===]x;6L=4TlƢA+++*ȺLzdqw ${?Z"  s-9@@ X5/ffrlkksZ"pN{{{E)YZTۏ7d-Wm*YHr% N{@3 hPe;;2vw,>˺LFFIyl'J xO pzg|HA W]Ψg,:KHe͂_]]mjFc)   t9W@@ t577iSR f6fWZZjb hP4aY ?X{PjbnJcY|4=Sӂllok޾^[= \" nT r zD;0H$"sss*ȪfqVWW?L2ٲmXF@@@ ɷ+  R]OiJb_\:4UsGGG!pjSSSaQoSp+ϗ_]s?Yj{F .3V @ۥ!ۍ\Rģpupk@,\ `#g_nr?;A~@@@~=  @74x}}}өkjj9C sr?ͬ)+P\S-_UUzG>%;ڞ_b砰Lϲk @4ݚ:s J KR|4u를\L>N`Z    'Ʌ4@@+'ۦLMLWu*g6h>33c;LOO  T ^grw>\|{`jUtsٳgISwvy,k(@\ kNE_&&9=pI0 DcYXX  Xd9К06fmm=   dF8@@,`>;< z֛)zH@o[s2 ztŏ owM;xwU{4 ӧ)Sc<rwJ;@L hpĩڒ~Ro,qt>ՙuB):VȦ@SSoE;}>XNm+H_@@@+`V{   5@[!M{? ܫGA tݝp<ozWgqWm4gjPna@ ɂ۝^677AURxbss'S'mYE>Sȅ wc *JCCi+@@@ ABʜ#  gvvvdג]/a2\ h@ޞdo7qrN@ ݿ)jOdsUT&:(KA+nݒJ"S@ ɂJ2gc+}Q wuu.͙XA htЬiS X#YL+@@@|.@/ G@S柿b{oޮGb{rQ?==mk@v (/~F*]BvjIY\ZmW]%&D @N n&IW9X!=2gjy8hl=Y:dq]U*(h{N:}.PyK9w,#   /˕<@@|)` ڗNk0կFԐ@.ޞ =fŕ }^.{`z]{K+ܮ*ܞ())!b* @v'z-ՓhB %Ujɲ?S3#PTT$ֿͦHTNJ~]Ƣ}6@@@p+@[)!  aM7:i#+&!zpp`JeoBY*4o{Cio[.{{'M?Ņφ< nOl =!O@l ܞSOotw$VO~g v()Ny# uvv2fk;)/7 .Hk‚ :t^ꧯQ+++yqn    ~@@@y֛VxxiJfkV0ߟ$'͠g niiJߜ@ۏ$5u:yHjy>oY__ܞ1A ~"\Y}ϵ5K(/(N D,;:t2Nr"XS4ng@@@| ="  ;ͶdU]]-`w璋۲UIyyy.1 \W=?_Bʶ:hcjjN IQ츧Oa @&ܞ8~_%VO~..-f@II/]O;77GW!D֖mVCv7*bK:+XA@@@ Nog    ۍ(>tՓyG~KU@]ӹldo7ruJQ^/I{-?m+W nO< ?@2-D/giyЁJ3U{laghHXɢw^dqw^VVV   P w><)  ۵N7~&fӀb 'kV T J?Y0~=r03gkߗΔa,JWۍeܭ"#W 퉾K}}}b:Yg!Rdq3^) pƢYܭōYFtu=.~߯Fg+cϨ2   @> WsB@5諨|AA- *Ȋ>ޞjB~\9^[COI.ʕ+ SSVr?M i \Dpv@JUe?:ᣇox45`slU~ _TaSZ;>OFgYqšAgp@@@U|  g46gIeȊI@Z7IM` = @ [mTݯuuȽqYzOFQyY?mM\&  \Tp{JU0S#V+`pn=?gps!Kn3^?w^6C@@@"  p6559ŝS+w{ +8g,MMMRUei2-eՏIY_Cm-k ylnn300 UՙyNn@E'QVVإƲޏ5aٟS; :::L6Mu  C-//YI.PWWq:Cq   ]w_A  ;' eb @q7Z!p>wduJ޷^+!`⾷'Z@ wc~Gf2   ~ W# J@3mllAleeeEѨZ[[M BlHs T\Ч>צ-hL.IM@E?LXY@ @gzדeq_XXqp,;p8,w@K@@@|$@.]E@[ޜY^,--v٫4;l 8eoBCToiy{OmX-H8ۓt!? rVv@ٕX=9|NKN6;TуtvvڲΒևbd>&= N,ӿ/|iӅ~!W.]jfݝ]S=+H=~FG;1wuufsx(UdTfpG24uHw{    ׇ! 䑀f 1i#+&kEg"b% :Hekkt$}DŠJK@UV>Q˿v6rτ"@Ck3F IEuHE?Q|, Dc:0YM"dC6pheeEt% g,N|   "@{\I@@>ZoJP߷ݬӌ_@6fffl#{  GH']bA\ n9w>r"@|.^K "S)(q~xϓsSwXT]@kki::롩+''ˉ   _p땣  ި+eNuﻓRNSZg;@eo@><G$ǫk֗x?}& ES ъL(W3'p=2G<~cDl.yCCΎD"S+   ]h_A  mѬhbe7E3}c\P4CoƓDŠGѣGHr䪷[m)Ix_O FIͭu!p~x菓qK ,nkk3+Mu p,G$:`Z;Ev   p  >pt3ʧwvB hkk!{Uu/ ÇEE%Z[-O剪S/_ͩm2 L?@{~ nO(vvvJsssb5Sg횘 l65b{%)=ȯw=P(dQN?@5yw@ꏟS[[kvOD_@@@ na@@ d`0xGʿ].--NJȚm"aD3fo.055%:hof }ɗc n9|l!P% ?'%XaL9Ǐ N ৛ >8=Jk(--k}}0MoӺH{ c_EXF@@~@@zcnssO  'n" W@3?[3(566skv=tKKK{ ]@X:5SZ;qAAZB)KbOW÷dpv_.F+/ `eP4fan2G/k~ad+E/UI4X?wK   0c @@ꪩO@@LutPiCeeTUUXA"4uzc ^Ь箾eOHiݬ[d7iX!=X| nOh577K[k[bޙUIi-I6IuX 2  ")*#3&ԁB ݛi5m4{r{N=.}{{ՅfÑ0$Gn=TIhۘnF@.P[EN,PŞq @ @6ܳ^@ #`zOa !K S'(D=q: ]veEEEb ̒"%s& t]} &KNY<"`@)'0EMRQ\;66M+|!P|ºj3zr[GGk=c$ߛM܅AEK! @ @ *@ ![{ 9zcN>9 D5&RM@'ըN8N\RHlYͯDQ,W%R=T)@j 亸]"+z"ѣGe_=}b,w=Tw".؍QטPcH{.N,N @ ]@ SL9s):脜99c 1@{{*S@2H@dvӚڌvgVsxc]+dbx+9qS!$@>J,/K. #mrH0%x.=k{.Ұ=c$n*I p05i! @ @lh1m @@0'TWYYE=LSu"sttQ98N^ u)O PO[nqGjhWZ*Nyi,᧟Ϋy= @bI&^ϛF>uڰW$((*]˦UXNVEkt|dS=[UUh9H$@ @"ܳbT@ "- u p,:SX&;B*'!7l7ip4;w!C8WRR"+VwH4yţ 맾&;"d<@#0ƦFעH]cB9|f/-pW^:^;ZeJQu"cPcH{NwÄ $@ @@ pz@ %T`7sɞLoSJA@CsIG vT+WwsgKӏob_dOʛLܓM L@>ە/_gy޻gSBR L/YX<ٞAwb @:w׸Z:ڒmu!>|،" @ @:ܳ`@ l!5=45Y$r@ 1k 9͛'Ӧ QJ%GJssŋDJLQ"֯߸:J[%jdCDcMMbwq{.]lY8e^ӌ1giӋ.՝09f3bڒMsa8"C[!@ @a·I @ $0'***BMO1'9}C$L@aw A#0f ˷m&*z>4Jtdz;G\r:De" @;sLY`3 ޽[\Dd@Ν2ҔW;V"Y|LyC o i^cDf|{sܬ|1? @  =."] @Qs4̜lr$0'/DQaHqTB‰A hsYc̿Rʗ:c6/^+o*2!rOUʄ voN .jG1];:d.P0ݏ},s LcͺcWwڝ.͢<"UUUs9pL0w$@ @lJ @ "m9ٔuJCV^ @:=#T(JEIVBH'F X";oz1{'#DiNu,' =fٲeR4ȑICgl, lĄ%3ow|A?O`َJDa x9zMF/T@ @@ p5 @9BDRѡ/Gnl2e7srӞ1I@c:,++m@ d׮]Z/^,FL#Mw*NqdWEgg*c]Oa.D)K@@ܞK$EŎJ=*8)"`Dz|lt >ƺng?!/ZxlG-)  @C{z8S  @@Pvww:$gkm̙y@* z iΝ;]Xh1sEcm+%1D~y |!=WZF/YUqKK H.?'g|bѝ0@EEk51t+3 p646B @"GPp@ ؘs2ɑH BT/Sm @ =ĩo2222Hpο RvzG' =7 %5{ZqS P3watommk.Gǃ{~ ܕyJP$< ck ~?b 4#z B @2O{- @ix!7=JHkΞ1RE"KSSM&˖-ˊ]AY>~tLGwKLg|U9y@R@@s@ Rdv:GoR4Vp鮾xEe缒=ȩV -K\ٷw;qdEx^h% uQN<G;S^-((!nإ=c@ @@ pUM @YG$2'Cij9)إ >88 RϟLΊ$W#~G!'_$9"$8@ H`54Zǃ ΔC7~uEDXRu'M5na @ d rh' @@` Yە 8gN"9 LLL5kV3 nngPϬ{1eY8d{WXk_zLXA0DA H5&X 2msꦭM+(^5]'FGcɇ :QP71tn:7<O&ǒ݄l*OM &3gtTcJ<9x*++# @ @ `,4 @A"`NGAjkP2f z{C; t鑮.GŲ`G\*^q_yi1214,m}TW gϊ?"-o~GZZBfN>猎 P Yqh}lt,"Zt)*9vSaL=Ӌ~oh")c[gqie1b#nϮk?{lѝ)uuuՙ֏wK;=i:fca签d8O7~ow0100 N1@ @@ +D @M@EJan:yE'ʠ @>P1kssˋ/V] Y1r'cZKO_³%N="3̥T480(C?ۧMz>6Tw{8&5]eRVZ&e?kx,? n뼨ilڼka՜9s':L!00cܘטÇǀ LӅG|3a@ @@ pU  @YKM/ ~[WTT$ .{FNѝ#Vq "dxpO.A t쨵QhwwwNl}Ùc i @ 1r6P @9)ؗޮg p͍@6GT@)/_}ݜ?" + {K GyHN*H/+-2)-) U[ɢ ڧ\T:22"cc!{X>4<x?v/> eQ2 ?w̙3#X njk͛'aSQM.&gAai  x資.睰ܹsA>=TUUIWWW$E.1@ @@  ri @2H@BL/HXΩ|X/'0!\ !g(C[Аw8_,Ő3U?IR` kb܃r%chpHt[vK ~*.+qqIIHlbj24sl߀9d>H^OMf͜WTzRCq{jfTnZ$۶ms4c};vTp`/0=sńg⫔@"YLںX1lS8 xÎ9s漘#@ @@ pEI @AޮFڍe\x8ԻTDÎSKKKe| ,WdxN|湘]rkߔyә{:ih_SbъrK=CfT U4 :_uu;]oѾ/DoE2ma١:!<ۓ2h%{z/ﵰ}sʧs.  ]hY==]yD͊X@ @ @ .zM5R*~ J(S}ͮ܋/iӦ!bZi4y;ء#1Jɺ52mbMgD=y]ÖE2yDଙ&&eBh Sͅ|Oܚ!!zǒKq{ry4HULe,^8A<$f!yAw,)ɣtKy&lz!p^l @ @kC @L@=pn^[96C pH%<֥ʆO*UvSzoǬ߃WL3c☰t]iR8+XǼ|Iɠa*dRA~Y+^TRUU%#PRR"uuu]EGCᨅ Ⱦ}BC^g͚%USmg/lX(]D`/#P;:3!kYM}~^C6}CMü eGGG$QCtuY<#P8 @ `'pA d~ {+"(sQۣ3#uBiS/ 0U*&q"Q*{K/dl~iЧi#G%A8*fjokQdVWDPQQYi2P E*0jrHhA,o*D*nWou&p  wf…gϞH/Tz/"qX41{8jˇf,/u:uvdbmޭ&$^c}rf@ @@ k0<}'{~_ g]+s xx%ySf筨p/Y_u@ @ pkH @2@Rx=~!LfkR2z)B?G7g'b0-5g_J[pL_N}Mw&DS'`n*(s5ܹserIQTpe@II/X OX/k׬yuzU17?Y6o:6Ff'q{pM:Z ,\Jfԋ;^ϔwq]5dOcUYY3 @ @&@ 0'T]PPvg&")--d; 50/nuMX ,'Ma4mi~b)3b;>~-_"%Vbqoy~;TH@fk[k  0QuuȬYDEX|״Itт^#GL`/]SϛW'uuQq[=;w8u0$|g]|W`zD@ru'"7C*D7ǜ" D(3;'}ұ3#8 @ p.oXh @Hرc)qll|&$l{"e ʢE^G75 ELBֿ ݽēN +++'m B}$ojkkhz;Y ;P`}'E D3iIѐ昒>S"֎dMgK  @ ^˛ @r$Qt5i]`Q@PRꅬGN@ t𰣒:D" }]=Sߣr膛|D&DngyVv)CC +W˼y>)KE?s̑k5kCe`r޽SOK{{{ {ĩ 8@p[k#@ 1=D ɽ244IDB'q8:E2s4I@ @YK [  @@?ňc6ivŐ _zzzDEp2I@=8v_ietmwʱ#1tZpz̼oy~;ԫuۑ#Gd~{復Fϛ/e}>| nبٳ'$Ua's5=[\zڭ^? 6_?_]M \M( m'ę(--"}k)s<.ӱ߫`W:;tC=jާwuTUUظq\}ծN:$җϖ+Bi7,MMMp:ԩRwY~ s@ @>U@ wڱoYx"2@T8A M'7.SϽD,1ORl\3o&2Ƚ_4.k,0h-;=#ò{ni=*/3g$(9yY)/A^ܛeFnG|L/ K@;a=X?JcOKʟ?Uc'!DOEUlYo[9s<կ~Yof;Ў;"]n) ~u @@2 0L@ 39h=e7'u@'KbH''vkOy_'ȱ^_3),rpU[pgsѼY6mU>w\9azYd lIj446 '"^/[exh+K!nKI"GؑHIe gzRA<`[t^cF/T?UxL  @2K{V mv@ )ֆzMhȈ ;j6'! 0z2w;SO='ER3}2gt|!oN@&ZZrY䮋=t7^ٜ9sdeٲeRǷ0m|QQjMp̳ʁrBL=oo:n?9DZ7w;}2Q }EQOb x!֎~` O'}? @ &= @H32ɡ47+ձ( З'gzo=.s;4@;[;?+o2Ƚ_ۼYteee.At%m\L[T_Lz,{~mWW 9Zv)Y"覻n™վ9r˿JʛL&rW17m$}Ǝa5rJ)(G _TtҐj!ٶm[߰쫒 fBܞAY^u%Үw%nkmsp(C>6>Ov$"!%k *ssarrgM-Zh<~q} @ $=; @Ӄ9)fZsL'U|A s)9sU d<*tC+չ`=u+(tz؝ԼtB @"=@@ kR֜ v2:srfPk)؜OYyo>W˼B'ȱޣg*S6,;w;v{dp 'ȼy 'xCL[~5>>Z|K#n7,Dϟ8U;xp8b -2v5";S A qUUU׸9v&>ÜqjG9"/^,w\$ @ ]g @$55)&A fL9ӠÇ2k,WH *GDr|R':{t|3"nyf3 ?iӤ; H_ ·ꬅD{bv{==ߏ 'YMsN?"p"E\2ܵLdԕ+ex˙;VJ_Gv8묳 ~a?ݑw]$ "8hkk.g֡;477c=&wΩ֡k[lv-T4$*C#n[O<<䓲m6  @ 8G9s @S"`NQ)Uc'̴{^i9m!hTsHCE@?]c7Xv;/k2} oGƭ2W̛ aVkڙn~{tF#ó~766JmmWmϓ ʪUB{ȰDowM7bGz&3A= {qfho|+1U6wxUܮ<}V"cұ9s-"_{{{%( 5N===R]]e`` ϖ7p}/$h=nr);y_oO}*ʿ;婧r-W._| o]WF]뮻Bum߾ݕEWJw˫_jWz"{|RaCm9"O9 @ ; 8](dgh5 @Bk렯,- ɢJLf:0$v Y'2E#Jf΅$*ʥǷIaut=[_y3),rTbl=*4]Emׯ:lR[ٳLJXxQPʳ>_zKuTՋ Lɿ滘z5Eɯ~ו;nE9  ΍:7)Ҕ1kGy$sp}EwqZ1gO~"~G? ySӸ~X.2bxۿo}C!MS_~~f~9SCb}/q}*袋{1J=2W׽uru׉c2;vqn-((@ < =.2] @:\6'ɠג{%̼*Ͻ^ӣLv vLQE&EA@V{HK7Jÿ~C,%J:+o&3QC-Z矓!-Y$A;] $"Ǖ+WJ"WU0;wfD0uIH"kkj%̌y}z3FND'`ϙcQTȈ ;wO2::,GxG8Z@jdQ퉘>s9r׺iD+O!@򋀏}  @ݶW=͜ q,! f"%PAU3cqM1+뗶>, \ͨ?"[HzrW_ -MTыzQL0˖.ҴJ ,՛={D*uuuI>Q!|Yy0`P|FQO^cԼ ;HqvX=j8Gq$/j4Hc9_n1d'(:%O@z{ְbp|Ob~%D-nݺ{Ckkkȫ~;ӟ)Rw?,ꩼֹ0:|^xYg!o|NeC?/~a/&m&?7g> k׮+Vڰi&y'{U,uOuiYv\pzj >tڭ|ߏڠ_ע ^G @@~{~\gz @ 0E^b.ɠ)VSO0s DvVUU%* j=gSh}* @͝3kt\Y3WVTڢ"Vk8vl޴S^`yollq{'JH/_M 6?Y 3_2ˆۓA2(-+uT 6l<9 [+ޝ'I`َ<===.  &qtE}48/1xo LKNfs=k1ܧM'L`4]pH3q]h?,]MǠ^ࣝgOSO24^|gDk|R꺸6l`s 'l!a|8MYd5WwKJvC @ pkL!@H@^}}}R̉3G"s2E"` UhhS@oo{ܹs9N{_k% ;j7ә%rvxns;˗KӢ&c J@w8nqR4~&;|pe;vr["㤤ԕFA@qszqWAUWWW2ϝ2,!\,Ã{,Bt}nr$nDSx~S2O5A ^T{4Sa{+_)裏}^|O~uqzF.3bկ oy[d޼yhr$Ss `rTv2[;Kկ?8!@PYxh2 @@z 9)fNEM-Ca떍-ԿMӋNxyd`hoow5PX TZ2n X.eVשw곖w7ҒRYv̙3[2A fX=;~x=s?'Sꆊ۷o*q )"PSSZޑڲKӬw\,~MWtM-WgTLfeU͝ګ|p'|2~gG޽{;±V;ΑMEvgy%ݯi^?N=̾p ~khhN,ns5OҗT.,f9 @OΧd@!@ $PB,kk1ϰQjsIIŁ`:;7ȮϕIe?[9r2J\\Xuwz[~nNg԰A,_y>a~_,ZH*gTnZzt_d]b riC1٭CtL`zaL cc1M@eOxnv"fjtбPSǦ&ڒd$r4P/wCsGyDwZq}E^&xN>o<8J,\БjzpwN;iLA|3Y:V:I\cu]'*9SxEBU  @YKY{h8 @@; &ށt5(wefM kɦLy&VՑ@FVVHӏoihՏm5y"ʊ W{TXsfOq>6cQ$=WĵkJI5fDg@{h2s!i0e 3g:Nw8} Lẕd֗+ed r{ 홿..8w/G!RBdbi_m:>iٽ_䚊]TرCԋi%ru.Q0r@yE;~K$T˖矏* FܞkwDC`ggtp*=9ub {gϞ8Uq  sH7lr9:@ VX!˖-TOWX _EvSg-,׾_TTw5>MFqW0 "IE~o}K^t"Ջ>1DD@ !-E@ @ !9P9|MO$cwׄ)Hcs*zk\(3^/txkv퓶>" LyxFY@2E[l>Kc7V`=:m۶m3ܞdR7zjٹs`n7URRZjO ݾ}#NEŲfqD@ 9YmC׋z>g+^cc1O[O  {K1N]ȭع2}Pz zo>rF}EU<]j ]b?1]4h O>dG tQիq=#-Xw=KO?Xϴr-/~ y'6'r5ׄ֍7`Yx( @@V@UB פOCsr1mmCޮ-MdOhi68x𠄷x3ԃ{⯁O}$W4yk/464$0#nw!!"@\ioowSD%jexp(je.zZAb(t<]d7P{:H73TΨ\x:Óf&"P[\7fy'PkPm繱chhv7|kA ƠYEΕeuc9a:T6`G? eÆ x$!΃zK/utę͛7:xnpxwd;է?iٴi# .p +_)ZLJ?aGdHM ` @E{~]oz @ 'sRǜ􉳸nLgʜ7L/|XY']v@v0Y_]ɴCQyx8I쨊L3t.4̅M^*6\r >34ELX-k+VXA`*&M΅I(X9s#@(!M?Mv~&)YwՁ>ly~ G/X>@d۷o*{~rj뻢@:1{:PN>dy^(mmm,>.\KݧZȨr|ߘ_r \sMh씫:OUWW'G 뼌i}^7@ __כB A>>k' [9`=dO0iٺ{-ٔ)N@̉KޮX(]T~_I;f6z<ۺe  **).qũO.,D@A`2q.x2tߠ܇-OJ⮋3Kh>ZA_PcTߕnEx!0zFKN\:kkL4L_ 6$3/yK{%K%niFi8.sj*~YOOOKܮnݫ\{^'p֐'z/q&w#*O/\4}Rop`Գf4 @y@{\d@ IJϽ [xp&g2 ;Bd,@WWI쎨p~r_镶?"‡ رC\[t;~T2͈݅DL&n/.*ukʪl3*)a}w_keٲeQT!>9yD=c q=@IDAT;|…SO=U~_{fN:b絮o9EԻ#<"*v% .@z!yf60 @@(&t @qЭ9U mE$"__4FcHc9D:U)\ӗD ]Jdt-x" &SO9Id>sGGo9S-_yәIٷ8׭ߓ-ޚd DYs]^m8bիW 2 N>{I' c2+=)re].ޭ g{QϬ۷ow\#I@N;֬Y#^ {y/ʕ+ }@[[[{Eߵi̙!OꍍI[Q?|s޽{C+^ QzL--ȑ#RTT$ 8t߿_z}wj]`84IǕ@ l^Z@ 0Dyӕvݖ<,n׶,VKhՓ" AVX![nuP;z޽;GI &* u1iwwwމ@ |L=׻Ѕ=t)#La?u.p7߁DN&oذ!+,,uօ"}oyߘ*|0@ LF`d C @ 9^dNdPi^" 3a$Jv2=g%.K *iVVQC[g_ySKZ N5|7o=*tWVTTz+xa.kW߲?OY\1~;elbl,V}P1`7A 9W=kʞǦ xA!@ s)m @s2ǜ D#ׄbKS)~IkRd̒f"/*++43[wO W{{ze׮]6Ϟ=[]Da|BI q{-~~}8` @ w@EvScy&.8IJcxpOzAA 1)<F3Ǭi&Ѽ-N!@ _!@ Ǭ둑Gd#HS`#RQ'e/߆jjjaIͧK͕չi#2>8+3 ɶdbbQzf_l3#@n!"nkhl9s愃ݻwKOOO$@WDʦ=Y/֢A $`IcVɬ+r\ @@v@׏C Аdsr̕!#̉/x 'I>3)"]Q pϟ7WG&g_yI=+nٲEtaJKdʕ2m?Dvz3dەz(^tK o.YזON`̙RXx:thr0g̫'$Epݨ"w $`IeRLN9& @ fRS7B @ &q&{ہ47L'M/JEȃ\4 D@ Af +,|%4 O+ )^}s}MF&Gw%#]Tj*)..Dq"sH=FXBJKJQO]"wsa#n̚5Q4`hȐkchXL2LJѣ'zorfHٹxs'@ @O{_Cz@ リ*d=cKK%\C ;Νkr gVKӏo2_=t7dO;Lm(FF\R|q@n!/-ns+** -8ѿ-  Jss=cd9s\EcRM*BZ~׻=cKkLk/rs5.3E,իM @ dsh) @@ ^%%%=7L>X#`J"b0csWH-_׵qi2 }--,Y"UUx"C@ U0ҲRY|Lgg=cd@uu'wy= s`}&21B ,LBkLkj2d 4 @ @@Ac @B1'yΠYPN)=4ݑufzt;?}&_閶?*CǛidw'`TUO{ww ʫ(ň;:(  . :"b縢83("kCC/MwSU]{UV嗷0#Ň̌Sܸʌ8ycZz衢Ӗ-[& A~(Gn/[.Ye+l@̗/^*~ttT\`kgwKg9sM!q͞X,`:`vJ }  D@tU@@oDƍ27q,%`:u,A`ppPfgg]~2e#V+.<[zOx:O>y⼏xJ[M"勇~Xf23Ӻeƍ}n^ G] իeѢEs><uThI5{mTuB-I^o+6h U=p};n3Tjg,gW{ @+kB@@W;_֟@@]vvc6+ƝѪۂz{{#Z[g3C |t.Ewg==eWKS=Lo__̓^ X= Ib%n7%vS}2_Hijjr=wg`` 0Rol|)Ja+{OUIMo|kSp),veR}3ً   @0J  1ݼq} t剗 tCwwYY[5$碃XO@+>ṱsdfoK2Oټysѕ+Vŋ wEɯQ nϷG8f?.ccmVhop#n?Wd3V0YgdV)Daʶ] NQ. (uC@@)@{:V# )EټpO:aK!*j@kJT箒sOw_&Jt`˖-d\z{zd}An.y!|;WX!K.o4_5_dafY ! -+iܛZZ+Jg'p7k/ ڔ_=$}*G@@-@{#  otttHs3oKQM:MRJw(iG&nn5eIX]SWv1Oiu={ u. |pOrwqRp{mƍٕߜ9>1.۷mwc0Lp"yod ?Im:ݔV]('kS_2[^{^[r&   @DoH   7o͝5h/!fuCoYEfE =ޘfğؔ 2_Jۺ՞:׾)m>Go~xґE#ND1ݴ|QiO{ZQv 쐱ѱ@ , v'~Lzp}F/-Bi0k]kX)J   @popP<  @Nj]mmmbXK@9%{zzʞ|( +%ih]H6| -|şaʺo˖-b ŋeɒ%]:9(|szz{d5f͛7ܜk?%п({D1VٌqHPQwww~l PՐeO^Kzq    =RAe@@-`lEqc]DŨ[@9L; ~ 4w #_b9bٕ{A{ u.&pj:A `Qn7c5wP:s_hp94hWnOsEcf-[ /^,K,)yN(y-%|zz{d5K~7o.zJ ,_ٌ}%ibsيiHPWlרlJ琮#E ƫ   ! 4  Cvvs' :ݔhy|M(!36 ~ eI{ ;_ri[LFw ˷˚ 5yu#Lfo}l … U~ҍ`7Z+?';K{S4l(#TcUL{Ԙ7(   @0J  1,~ܺN X .Nez|X*Bt]{W6 Д [KۚUR(538ZYY!=:}Ԛ$1=WK,ѱ1ٽ{k)$zwSoCy7/.mFY!    @{ h  LK톳a8@y=27ZYS@#,Xg䅀,zkd{eW]Qyh}*dHhoo׻.ٿvv-p!   ࿀+vJ  DM@nDލfaGT`4Z`tt ^Dd#5ۿP&/8Cz.dg*KЧK1GWL ﻯ(`[盲z;7Nn/otRٶuLMҞ={dmEޞ//UёQ1OHewĴ=" џgB3sD:(07bӤuvM}r~/*?T<"  kOnG@@6M͜rOY6/䵜%gaՃr+022j\sstwwfv7t/ ?Q~G*73#V[`}RW+`` WŰg8==-7jo:'ђpji& Vޮ6yaĴ   <@@H njnD ^ @OQ&aV͎RAS3ۙ2 l0A. 0&7ⷾA]Jm-;udsI[A==EM33p~_ {Y;fwμ63s]۹/-ƺQ3s@-ٮmEN[ ϟ@@@   @Nvv3 H#0ᗀ-Wy>3 r.& drrUĊ+}~@}x^vJ~c}5U{kVN2v~ J k~f~,g>gCEΧmU!=)lJOR@@@ *G'  @Cl7i􍯆V0bk/"A1-fR 8QtvYU?vM i](mǾo~W?>c߅@pg*WB3{KKk߮@=_3al& '*K6yu׮jJCZ˴@@JQJ@@L@23#*7go:9g8(/02Rg%-GNnyK/7|J1^'.X&pKC{캬 ^5Yܾl0S2<<\H ~ tuw]L6lꗖ{#0-3}J_ W|#  I =)=I;@@7M2O5s^ 6I1tvv ~ 2f @۝v??Uz}zFN{d-&GrqU:<^reQ]vc~ ==={*mx pY܃V܃NwڕnUl@@@ppכ@@"*oj1{{^W9@yஃʟQ* *D jt!-*w^ف]$;3%y.Xa+yJ) .t#XJוĸsXZ*?-蝈vGy N6X-N\ܗV_{S_K@@@ GrA@IozżyW/I!@U(Lsuk9@{3r'SB1{Y&S^2 A6k nԼ>5ljTsg2cNq/3g3tgw%خ[)vW:\l    @{  }}v+&A}J.R96'0::Z9E$Q```[ssXµ϶ќ (Y/WHeEOߓ߇Or%`:z{z)-- N`짿]w!dZ۵+}=083]    *7! DU@вjî2v/$<[-!,h[{___ŒJxcnɒ%n\.~4yd?yJDDZמ3yĊ]/ݻ׵ 866W ͧr^~Ki]]JKV]za$c٩i3ev}I[!=~=Jp{}lr1Op.{qn7#O2k2;AwG{ 6-j6}gĠA_1]JfoZ^;r<#r ' _B*r?+=o~yXZj K.d=ǫ=  @WcW}*  @"\l7qӼneIf#^^0[&ȁFFF\Y P@6djnD2於MoT̎2%9 AYۃ+eѢE s@oO+ɩDe$muuj7,3bG1][]q}(^0].bٷotw#{|guVuf3͛ VCariͧ[妛npI@@ ߾  > nnT\+]Nijjt\|M5}#'> .[6G똣5.?IBʴ)D%hQ0?R-K.ɧާ} G38c>A˂(<@@Hn  ̲idT2_3гkYK S˙_GGsu|07Ru{__ֶj%S=wGeO= 1LD{:Y/^*xddD\@Nɘ%UN%󾊠ZߙSާqpmeeb <r9wݢca;/3{erA7on-Iͣ-  @A+  iݜInJ ] \=7c1 ~ 0_SI̠5;嵞۝<zvjZvz>9X2M^$q}dɒ™Ž>/TߣOLNsh屬'x591a *Mn^b*xJ? o[oa$jӦMw֓b&z;Yh:+  @pORo@@l7g 2NI vteՀHp:݌/}>ͧi! M~oe߾֬V\2;dϖ^q(p¢*ݳ9DV.SlOɩ5FZy4⍪^ʵ}!RBc}㋱U>E۷oO?].-0O {"o'nK^߼ 3@H@))Jڀ  @}3Pdte?Tп We7RxW]]]O&%:x)V"!O΢C\YvǓ3~XYS3sş%]lmr69V|IG; ~K/]O*96>& XAF} gXqZi|,q?%N͋S]mm&=5451^x~//###>a&0Tvmry^/L|3嬳ΒfYWo}[O"SS8'fowbgkg!;[7o78X 0#E@s4V[scSw%lc *)}|N_NT\b; ٳG:O6g?+<|p2_B47O`x뭷ٴi<¡! _~|9u1_WYq~zyӟ%Esͺd8 HuUE@F@ߜ7o)5߾z21,w-¶fwp@FȪO|Yd }]ǒ'޹hܾy_[Ϫ?{R,_/<%!xbWcc-l P@WgWQSpOʸR_̗@gE_ # e_ªGh `;!>h*g!K7|s9b[~%?f^+^ݛ֭xN o/d+Q0W̖8)? _V(d@+v1nUG@@9ox"5I̬VfV҈X峞hZJN6%AWG]OʏX.T{,}[e{e߮XTfUi8{L#7I\«{dJ6Fy ];]3Kz 6R#QT<.|O\T5?3lhqe٬/ @4N;4ٻwon-rI'__/wk0|ojo^|3e͚5?Y~_ɍ7Xh[nroy["pwοF+$(;dl~w}rG8 VvG@K@(7o*' h+&3K ~e~i,y 1060K5]$S?$w߫P=?O^&K?z~ѱxttcIiN1>d /X` >/浉?hnn*d71Y8Te62?K2#ɽ΅#  n7y''|rիW.z~<@]]V^K__ۿ[JQ~Pg3iӞ׮`^hhnsnq E X9u  "odq42)aG07I N f|٭XS@qg%jͦګeɢi6}CF+Qn;7{D5 PFm3)exhع:tvu=-Ǖ M-0{Xݨ? ڮEUI[u}lnJKկ~+Y;g/BWp>q~YÑ]w_>/D|ժUkOwqGd!  ^@@%`)cyFM?Tk`NtUg[`nnN!:FUkܷ7<Ĺ{6Nq8U"@…gebYy䑮/zыYzks|iC)ڶm[a=+裏(tA}݅uV@@ x"M  IJݼ)C:hŰ{ ;;AYn= CL5Ae"o;ϩwʪ/SŬ23d~ -+K/]xդ&inrs%Hwgf.[O1F payVWM/wPبK#b˛Qg{=8ն$^ IhyI^/خuE]45n_Kj@:(ioo/|rg<mƂ GFFva{M($jݻ]5ذakύ(oܸQ5o@IDATfI>L'{i@^  @X%M9  ĊF#Hvz|u&xA/fpQ`QCÞ=_:E& }]%fn9WVqE#CrTƥr+V[fZ](avyܗj7H ~M푶6*?44$,%`ĤUD4y]2VςK NfA^3pYHA xUڵk]۶ {=[d nW@F+Ah@@ q27kx ^q`ӊw5 Ba^<\zzrF-k>{tu'ײyJDng)jζd`@iuc/tUয়2JU tu?`r=W6.yk=ҟë %%M@/V=^APnwS̞nkq9ՒwN! q =D@@ݔ7+<cNhMs5SMWD;+ղm&Ą͋-rm)JZ{*z蚯O)mTy#!B{,ΗˠE~y5:W SSEⲣK{@,> ڮ߄SJI_=l\* `\_b&Iڢu퍢n )@{ڔ  9M,Dx*4==*Yrd*l*IZV@^U `+e>/ǭx*P{S(&tݞfoIGW Y*]tt,`Gpop$xevwĤ^jpoB%!_mm*|%c|Uއ4Z{O~-%ȼkOK >Nr  how]KG@@ ۅϸ=~3 kneawdś>4, s@܀HpAF<B?pdvhS(%UE*#Ƚ@QX)C}p"+萶6W\l P@gi!(7y4rU7gAgD5Ƅ&*18@.]jАk;8K,Izi Dt4D@ 2+}t2zz ীpԗtəǷɮ+ٹ9O飒۝&}Fv^?[aUё/@Kefzƹ֊2{E$> >E6)ˌl6B oM_8wћ@ \Нwe˖ $@{@d  Yu)o ?cˤd|HuzF>Vu~,022J۝Zs%yġ]%oMKځ;&={XqOMO=W2ZK+! ^fpfpkk3K~rlg+xoVzω @pi|w.yu@@ Nǩ+  z&HJJPLJ{iGzl_AKK@Ӷ&''EJE:eõWKˢʉs)&Oih wfݬ\tDDir'Јޞ'N%`Ug=7A3v54iSkK3 ܸП{՘E@-SoW_6|r Ihc68%s @**  )C{iegR$Zڋ# %I~=l S@u`(V_#9M꩑ι@xSF%2qb5Np{aעѱضGOJ^KԨoKUOaz|vlGBN> ee|JgrOqy2;SF$kvgNp瓷njبk }93YΛZ*iF߳HVzlkjq}Jrl@?>|yiݲ}B۝  1 =G@@7eMJIF.ʴ dmZl7PO?=L lXk5fBe{. _W8qHvnS0=cG[,^fow= A;{<},A6R茙LѾX2{&TR&.* خeٮyU( Jilb Pi\N]wjf@@Y# B@ߔECB2E|J :!% 43=LS866j}gowVt?!Ur}[%7\T\s$9ȝv['s_OOafکI>6U΂ecj{) خeٮy\dMQQR'uB~'NcIjSi Pv:MF@/o6S^ tfI[F>Z쇀lVuy4wwɆk2z҆͞~XT$^=i2L\gpo(^3}őUlײl׼RDR \D ,^X8B ߅ \q>{$i i =ͽO@@r~7m /VV iJEvvv keW>+᮳>$>={I r'ٳX*~M$=B+[ZZ>ff2!M-3枀~nIۇW#JJZ\R{;! P_8;vW/4NV@@ TbQu@@* 2Mt\[㕦l[ p7͹e,tL}h{} Ѯ2 ^ +?|x.н’8 Y{eAf:{뛽ɑrr7ǜdm۫V>S+À6n6ٚy&ɉɈךI5>?kWawԖ8+ug7㋧1ŹWQw۵,5hԶ^X5OAgN>d1Y."1]֭[Wu})5y|+_)1tM׾d'x(?-LtRyK_Z)C@b'mz5 #  M@ߔ7m咎Tʴt}Э4EB_Y-Wz?Mi{{{3) _JO<:㼢mO'hwʯ'4yԕSܻ{ EDcѥ,19E{cz" lLg9><VeGT+kYDějVST)xby^W8+'m<}'?IYrtttYA@ @{z6  ,o65gi"^ 4Q=nFz8H\{'{jo'/SZ=}Pn++6A nS=YܓǍlQkAW#VMM+-l$Qw1%`e:) @L&(7oIͫ.;w?_7T@@N   2Mp%/gmeZW156襹ڄfg݁H@r,dqN.D<npҲp~Dnh6)ȝvgϥw=TCޞHf{LLg9Wʪ4Oѿ)-\˪΋ x˗˫_BE~֓✝o}T  D In  1Aܴ)݁ʤīG 0[z=ª>G@)ڥgp5O˟5=cϗ֏Df_y6,0{ qr'c^r6ׯɩtzZL<ܛZZ*Ĵm ώѬ=c:/R#@4K p߻wo4*S-y/~1O)gA@%@{  4XvӦULxE{b]V/'=] NMπٲ^BYqٞ%;6.OFF=7їStt&r;npMLN$a|21 pom7ld 9z/IblʤīG@ W󕙘M6Eb>+m?|)gA@%@{  ,onڄ\LElwŪbXuW*[=/ŮT!^>{=z,xel";hٻwر#Z6{M{>яʢÉ  @ώWݩ-  u 26u i^ 7Hpvw_O%bǁdd[N7Q,EwyVSO:SxsmUWAp_ͧ-w+`rk#!P@[k[ 3ҒeJD}vP2K_]LJJ{q'׽N$,~˿KB@@O{b"  @R Mvi+s>^*&ز={<?2*-I;}^bYˮKz^ώu7~_s3 7zgsOb O Y$=bBi+S$^![K4ә4@@ tC'@@@( 26Qo#뢭L]jd$lV7t:IKe[&ᖊ=Qe׮}—b&AgowV2 w۝0Op.5yuhj*Nm{V*z{Z[,|1$N}& < *ͦLJJ{q~'߽@@b/eB  P!ciSOI:W[ᕤn\[[OzɌpc733㪀u0ګ/%c7\?yDcvg[A3o۾Mv 8״Np{Ml=lƵ5 X"mj?[ZʖV6K c/M@_blV&%^8   Y  @  M6+*k+S^P.SV<3BNeA:]ώ4ͫSӞ*_zJ[*Qgow% w۝Ҭ{hms>;;+sss^N% el mfMIZ Kz|ulFi^[^J^~@@@vkL@@ nnļU/(H 0 0|$#@&83qKoVd-d[c˻2gݏ    ^g" \v3v& +hS[a cF2Y<</?A̍gؘDnǹYr(y,* r'=*z؞2qQ'~QoB]+ա z|ul/C 0 j+s&H   Pq&  @l7cl7mbLߪ6e@_0|a$mc[DZ~{/Ԗ6ˮ>TU۟qigowNpSjZۊNc ޷ރUo#7/6lKn, ױ%y`ly_wѻ)@@@j v;D@f&Z}텕L-J-(H ᖖ Aq*8ou|Z:S3~v ^SZK{{3 r'= =:^(XW6=Xr\;KxsalVxdQ*L[3]GJ@@@<֞g"  +MX5*j/NYzl3R6j.c+ XtuG6| Ҝey3W/~U1w?^1.j j r'=j侗RN%b5ul5VnmfrR&_ulBF 0Sj+s&H   PugΙ  DYv3v&mn 0][dyXcl%r[O)<Y/7L۝ ?2>><$۶o^zO]hf˲wqv3{O_^px+[pB6F*Wlǖg pv&flC u?9C\ ͌oWHziik4E@@H  DM$6ټjɇszl{خU@-VMs 0Oʆo}A6Ƌ={~as 珤mv' w۝b"`g{-%oA@ ul5y pdtsP@vulHD5 0i+s&Hdn)lj!=僀# h.u  $]v3v&^ۧ*GJJBU@-]jrSؿyڿZ6+{p-(}0Gd%[s`@v <* ^*qlMױ nĆ~؊&p 0\e7IbY2"  $@Od  ?M,k/qNc4z8mc˔kW8i,חxe֦H2):tLnb8&?\1PhmDZ#Rg^" _`hܳf_&flFY[i+3ޛMJ@@@N   ݌ݴiLW*z}1sѯ[ƼvEPKjsssqz(u4gi?p^0p˦M&* jko"܋HQDx$(RVωbO3dX֩hle9A1nc{i+sI   7q#  ݌ݴ}C}j'X)1bP%_L/tӝOKKK,3LZɆo^-=ݮ6r/ݏZsD^.*r-(2!ȽlQ2Y".2BE0O-OL󉴕y&%   @pB/P@@nn4r,T{aNi[1T:[ A#(` FVګ/TfKnu||({O:h_wT n萖f9 r{gGs\kYDK5b&_ރŢI-0{E$豤ǚEU[;\[3]GJ@@@pݎ3@@b.`cifV}텕oψ!-p Sqss%Txm¿y,;ݞLgf >xya; +^$=/zfg_leu5I'2{6nkDjcbJCB`ly'VL~@@@vQԞ7g"  iMH7"i/Bħ(IT{[[[MqyRc+n|LgXIyA=mVrg-`W\undk-݃#IyŠ UQ[V0V ۾RfW91oپI&  @MY  M.7*mő:@H~=[3XC-pUڮ)7M'Q}t¿yd•Wk nc䞗gzm9/s~R85ze6 aeزc Z@㶿<$Z9-!Ҙ~떟K׼ҭSzM؃   S  @Dl7 V!3!R1 RA o h["uG [O|r\O]*3vxJD~G{^ ^:vm'}e{l-ɽ LƟœ_q[KPsX_pMG@@@ GrA@H7hJw$|m8R-HA2WgU6t CZmhwz|ÃxnhXv~MNzJD~G{^^X5\~Sv,JS[ܷ%#ފdUOv񺕬mdkBVziy"  #@{0  +}4+u' =L{]Lz>ҁ ԄR(b^Ӗ=򋻶wyaOȥA{JDAH{^^23YL^#y~)*3!$Nu+f3pwѻ)@@@j v;D@f&Z}EL-bo-}M}F.)6W\\`gٽ8eO&C_Htwܞo5Ay ~zvFy94Toomq b&I%eT=>a 0j+s&H   Pq&  @l7cl7mbLߪ6e@_f9ВIN#u׶IcmryLx {2ΏJ䞗g%iWt\@ ٹmȲqI=gg۸ 'dfNv6uCl_BVHB@@@!A  ZMk/5 e2b|ɉ,:ȝb.333f]/pO},zsW9y?̎i"p$|s rK;];c}y)=ew0{Xh{nV}('Yz|1J2)*@@@pϒ@@b&`cifV]eM-8zl.qʝtp n7A,zvgV*?>9]%d s%4@#%=/R36fp/elۛ[Z$*[[+$aH>%-gG# *=IWi/   '@  3M5+m3fl~ r*ЩTxm<ۇHZ ?Qx42=foQc/zls//D!Ml%:jkc2)*;[nwU0"5r: FVT@.Py: ~@@ Y}̸_l7mvxz.v@U,"M@/[H[@nNOgHvέ{-{[55˭oc'DxL[e,}ZLk[IWi/ v?O_Z&hzɒ%qFٰay04&sϗ{WV^-?яB+7|s+wvVK.Q9/Z Pv:MF@/`n8onO5+=&j=c/I M}؂CXʟxeio|!ȫ^]{/\:;Dlܞo:Ay ~. y~'[5}^- geFJz|1>-meb d+o.y'| ;{A&=;|p)笳 ߼ys!{奿_N;[oUn&y+^*S7@H@s H@@()onڔ<9ei>^)5,a0[V A@M6cK/^fo7gwJ9ҕ X_sܙ=Ef(;K|-*43(l|%;pO~χBު,TRa GP &4e*x<%_R^ZmFwqMo}{þۺu\s5}r'wR3z,֭oާ?iJjSi DtD@F@ݴ 媭L _?Fz|9:SxV<-.3+6{}dWRv'e{ϕ٩˝DZ(G{^Sߑ&ikk_f/IklX(c"+6Q$6@ 5}Lfff m^jwy/}IzW*Їd4e]V]pl6+\rL qg}O9';93Θo|%Ŵ@.@{{! *onZeLQFz|1"a1؊QŠ]]]ZӼq#lHݙpgI u*>?˞ !=n919h΂zmץr3'Vvּ9/_{ؼΐ$U>\p222Rh_z~ +{^Z9y8?c[BZX&&ܟW X;3;7erA'nv"@@{1 D@H9oڤOtIWi/T'Ǘ.7R#_@-^۰V@ww+sSׯH8{^pohpqCUrss#w";?!G@Vֹr1Ұ ɛntɆ]tu꟭g w8 A#ZnZY;瞣e˖QEE1Wf2q𿣏>:W[oUJf̘AZQ[S?.]ӆ hĈ@nZ     ⱺZtyYH(tP? 1nhᆦ > v^ՊS݂WKXo2pomWh}vΛFIܮ"wDj|'3kԠ^E=*#ӻW`8g;3@-~$ [G_GZ;V9 8E`xbٳgSmm-]tEqF5=AO< 4opPnn:ŖoFYRāmzV2 d\cM/P\ERnp4 5 ܵN+vƧߨ=~8a$չ!E i˴ ȏv=?@R?ْ{uUD 9ߟ<^n! 4n 3͈wܝq~F|gt{{+8*:+\d`9!nB3gR]]tWDHF[mxvYYYtg-З_~Rkl"bq5cϗ,\Pwu}хOU\afg}-ZK;c 6mqd͚5db6;u m }~'j~^5ja @qlk;N N:ɓ鮻 6%(7ngت (zDG4"p vR%ze($P dffJw$EVR٘K“>w2vm-_ENC9Q*(=?@R?ْ{uU[# {D$@]8Q#=s(2YXpvA ;S@=#{ܘ9^H  bl]ۆ)S8ϙ3G'n^u++ofw]+-36:Y/K2(h/ەkyI'g4hi>cA@@@ c5- 7``e$bL< u஥7Qܹ3b=ߨ=~0_}x3i v MEq"w>v6Dt(///" ]g.Ei=R8!~.qAݲ/ pož]WA ~11a:(l\ ^{h-&=˗/S|ӏc%ɓ<ƍՋFs~[Ö8 5i:ύ9rH'@e    ZE,qƵOBD^Ih nuA7D1,`P|քk }ݙxy+3ޮ5^]>hhLv D |B'NȞci ۓp}/\p,cdu}_VE9,Dk]4)A 'N$ѰXouQ{キ., h9hby,+teL:.21i۶m:t., ֭[Kl9E[4?%u7վ^@@@l PQ$weą.W5xoq_];7Qο],9zz5uq~ EUYe](O>z7 Z ;mgJv'{p@侇}ߡP~~3'@{Gi麰x. Yv]|3ZV J)ȊshRX*5e,%6/jjjRN2J3PS__KaDzj]aƱ#Fu8"Ku;    ` !  ed7%`g"/2-N+:/\1G@fɪ]/2W"RֲrAsA|'?1Vngmdu譺A/Ƚ%2b\G@_:oOtm{ 5̀*{g?Xq* 5#R"+^ZB@ nh]V@ E{gwiORdq}GV k#\DJqq?KJJN#˵{<6    VJ( @@@@sd2u̦&)Xb,l`SE \ 6Nb)=]ovΝazA~#£Tt֩޵m;mj v|w:ѱ7 V+$Ql3ND"DA)e #8ˆ.\?M cI\8d[^Ȋ ^n5/cި6w\) ;i۹Qt-Fh<ѠAtX3bX8"KA@@@J[Iexl2Wx㹎`̪MUXVZQIn ^zz"KFKk&H͔gEZwsVPE   F ،B: qreFѝ}`ѷf+-Jd-@;M@Ent[~+EUޮT}K DlxEПu8CzF=v,6],{^^{鿮&T'?c近NnD&3@ϴPp fee_1jH ⼟l+%@ȊpH)J-{_p;x>nteE,WWʎ;taYTe]8VLXxxBa>}l@@@' p@    #VxӽK^d􈿇E>!mC _6quS/D;V翼Kmޮ4"_*}n d+Q1?s֮S@ܮ}̘1{F466Fl(Ua$.| `݉A=Nu8%gJd%y@l}jwO>Y#WWWו+ׯڈ[ @@@@ qaFxc('YqXE;>%*/h&%@ɉ{Up>~Mg}k G})"M;DZ $ع#4Pw hoЕy". d[[,]@qK6e8_'YqgC΁@l߾=l\߿z'?g 6l0č7Nl_Dk p(qaFxN`W^6NbE2)xe#/ah|Eaa,pIۧOp"P7*Ey 2BE'W[M-H[;'Wӵ#';']@::̌n,iq,H nF-E(ٳl+EDt" @@ L^x!iÆ EѵC !+W^!Q̭\~?_˒8pVn"z@@@@\K@\Ȓ-޸7LdՃÃD>$tMDL*}HH׫ݻwv!Pwѣ5Uq[۵ tՔڨ濽@G]5bKŋC7xSh+ t323]NS2`=:~⻠,o P_ ds]~~xP|M; s8o>J+ 5O9|̓O>y}YCBh_QQ6ypNPF    & .do\'yUh-_>t'_,<36UHْj~ٱ@z: yO66*~+jt<~N _n {xߒWǷ.7w-nH>9u]]q AtY>PB1Ro1 C_-]T0[;wnvj=?я֬YCO;hjgy~i5,z^|Ezh߆mFjHx@@@@FflE  Y &a|Cd6hx@"e}'C`_zYm`0 !ȧ~pzfK}𞛨(eTTli d} -|nڕeljUt@]}FD [9Zt~#)NOs~QwEF;p  pă>1zhztqF;|EI3Ln8 _ҤIb5{Μ9t]͌s-_J&4`rss#jkiixD@"ڱcZlhh Hz/^a&zlI=e=^ ׶n֏Sۮ>l}aa!ac2v񅴽rBKJeB*KIWp `3rs(zms0w^[&:ٻa0B@6%2RV*a։sk>6nܨUul>1A6.ر8;s1~zz'8v˖-#'syyyBoIr~tZ;ϭ~~&   b=\64 @@@@! .di*Yq&D >tt!^,еp `5٦Zq{9!a{{ !GSH&}qhsy9Ui22'^.,*JNhmf}QgQ<]v]s5qO1b=4uT]I_Zx UB?@@@`ݏ>" +.ޘ*&';= {LU 6 U[ZlnnY7`kx+۵vwчR`0ʾU[D([G'A}rI^JY' #S E`q ,B+(( @,V&̌L1!2 v{hΦ+WV檫L ğsE@@@@& o;OTNOt?mAwB-5=8@>}tw-c; ߽Zo?dAIL΍Imwhu#w74Җs/]NMx#V:hAş~u}Kc'ES}x񻱱QRu8l mΝ ÛSuZw?Xog,}a݂;(vw@$%*D'  _DϝzW pO1GO?!XTCO9fM7D/Hm㏧G}4<~op ٷo_:3bejjj] ܏8[SW^yE5D\X   N0w6ӭC}     x@--9Xlmfl\'[<4$tN%n?neeeQ4QSfkf跢h]x\AKsK%C\w,}aq;ǎKY^UY<)P3=w8ookom*.[ ݱ\0^y{[L@G\#w1:+\p9,^XiXr+ o{n@fmөc7һ!oٟ٤R][&DZ7FX׻wom ` ֖N ܧ@ZOm"]GB6F| _Fws@^8]ak ,'yP|\(p箊}P+ܳ'M#__DMU }Cb⭗jO)7lW~ݝv6qHba|ܵ4oi_~WR@K^ΛxL --fG#en@!pgSz7v,pVwc=V{YYYu%%5 ̌L*((0I@<т{vV 9KuQxܻܵE,i Al JN&J8?*C  TtӼy󨵵~ak#tI'ѫJׯ_[lM6f̘AÇ'8sNڲe _uʸKhѺ8ϟ4k(//]BA@@/Zf- AN3Πw}VZ_k6s=t駇|y&x~:7</_N^?訣z~     0blQ5|Rha']E7@WX+)v8ݢ"nݺtijqP1ȥP][jԳW㦵* _Y%v?wt?Mj=???2[rGqvٯ__ % bGqCENH'H;vQpipds wnW)M/s@}z6|r|"ł , ,iFYYY4ȉ'҃>H^x6{v|"⽖    HSNԊ:@@@@@EdE59MȈ"  Z+a ٤  TGY+7T50WIOv; ̑hĒ]T3jxy62#?Ŋ l} }ΚNؾ/--_y){YYY"wv!Q9,6eիee2! HNδ4^@^7#% {- @@BJ(@}!5)A@z;# _6 vuu! F@FW42xsA]uԳy+B     '"4@@@@ ⢩DT[:Ҁ?Q>&J`kZbcio5zvޭJߨ&:c=ve@2Jш^D o--̢Nlc-]2:{;PB=_r+ 8E䞟D˩R #'!4h0XJUW^Nv.@g|;uCW]\|7te(ﯬ,ϴ= dPG      ZfM;::(  I@\ ptx$+Ę' ~Y|Dq# 6V{@*ӊ H۹m6bnq\d-velzdfАS`qU|>te da>b; /:v_Wu{YYd N"wv%%O'Ш;}QV6zzRYI-L-3'wJoHWC&pۢD[~ۈ?      =1CA@@@l [rlֳEg }ywnxccgڏz ōs!+ռ òjlKܦ}JMH۵}):4P~ΐ_S[~. Yl?kۖڧ~:-g+;,+D}VoH8h G@A"w#.㛜"!"*~&dQ C(.(A@@@@@@q;lT\qc&JԨWjs2{Fٺ&444xsXuŶR]]..YWc'JDn+}ʙ+7/d)H]nHcCnhG(=B      !{rV-jA}ddKN@vEπ+ zb w!V())(*"V%Zo]E4oQ'+Q?{֟vZph b3L#/ ۵}]K#:7O 46O#`=iC*{瓽&ds|l{oN(@@@@d4c0=/b4#2---@D{0$Á䀢"]l7W-0F^+| oG de)ц>'oHzqsb"}}˞ Cؚu 2PXMֶV]o,w-{2ՎvLY{^3D      =q(@@@@jNf=L{=@222td_A|R777@ "EY,4 ȬWTT]mYo׋j.>hS1l6:Nq* ~Oj/vo F:ⴑbg'8l#V~AU&lc!pcw>SLٜW@@@@@@#\U @@@@M2`]!!d^ZF/yNĂ@|,p iDCbM:;=63\oՅﴛ8۽.nW+k(l5%:g.jbW8SMߗ(j;tN[o]a3d͸iEGlZAwn?DڑG4tIψ~J5) {0WVTFXo4h &}Yt=/!pe!p+ 8gsZp Wt6@,9pzb 7@?S2(QT' .n9G?xD(pYQ(pߵkWxS2hc4R@>}" lɽz!y4OnM`*ZE5Qh{ӕ+RnWaFc+i{?8kaA侇F[kl۳!ID+$nni֕^_ )`Ă{k슾 kZ'{'^9-3eBZJQFA@@@@@ pw    Z4,F/b ۻwp&JARM R"ccsUk : ]a~mw.0c[W-^W_O׭ ?giAǍ,m:a+r]|1 kܮ[L~7hbVed rJyEye-4vnH~ :as wBkFBms# ^x!q];wҦ7ϐ)g =EA@@@@<3CM^ɡ+;;f.HOO[k&kw>@{ -t8S޴S{+oNSlJCeϴz_6҂߫rܒۛUoUeQӉ$]s#~)#;/VS]L:YYԿ] `Ɔƈ0f`,; g-ٻ2ND6N}GWl>}[i|3݇.XB%▸nZ % B@4DQ" `ֱw> VEVD;_V'ĭ} ngayK'ϘvnGtwױ.^|*f:-WKOE.n./J߲\9oCKɉ"*FDJhhl;7'Ҍu<H.B2@| LA('4jKm^OerBxii      ܝ"z@@@@\O@X{alp-Cxl [@AA@ȷ+d58pΉc˖D7A&$R.MuBO=vd䈗b;ʏ5Rb*wA|~7QmH6ր$߂{+ -w}& 'v)u洔k) T+HܓlF¦'I2^Eä4(j`mmm:[& ZďJK#-1,RgzRkD^+OzwuUBCh0Y{qٽϸ>RIΛ7GZ̀455Eot-c{菴cIN`* >=ٜ}-Vɲ=      e$ уut R8(##CGt8HL ZK dɡ4Άdeeuu,~80TL{UZ`dx|1=?XZ_7N44jiWCTPsKn{E"(wP:KwZ[[#6R[>l ̰xE+      >(@@@@"e[6(8DǢ]$D ,[Ae!0dbѮUWW[εoM%}nk"w0Ya݋vE~wV%fA8n=wY~B*ϻϿ͂SŴEl9ucX:# V;vʎK@`h#udx[%s{!nr=D 2 {R      >(@@@@D.dhhk(x5;;[OŞHYl$ NdJK#|MED4商_bvۿ\G.7Y-lwc u\b;7~KOW^,rgq]z ܼ\+"w&Qx_Ԕ}d, 3>-N|4^R@$qJˊ̑1ރğsSk%.\/ ̖BcQ$ ܹlWo5h щ yS[r/.6'Arz,l*z{U B/?~?ᘁfOO55-<(ڄ+2*u Ƚu\^رcm߾]L2+KXLXug&u?Xp'Xptw<~p `qnO˲^~I@@@@@Ow!z    `!q-Ab bpD^a#Y!{Xy- "SZk 4p1U@9M5FIVҁ`K}!o.ƬϜ>@iѓxEܾKWѿ>O]K0=(Ux>WPۧ+iQ>Eq1D,&޴qS0 6XN7p)`w-إ?aqc]@Jl ^x!2Gۮ$yA80+nrL< ;YYY>uw)r ---!ѣ@F,,fj-lA&AXejxi&k8Oo}C 㦋 vSHߠh!Kŷr*.=nn4"OhQ'ҠGS6(Dܫ*MG>W8A`gN]5 oҀ1pĬuw@uA,/sz=('X_pJ 'fT     '3? -WEӕD l89zҵOY.%Bl 0tPJ$n׶n⇖nv5k#h[QõqR SM]fazsy9UUZc.~mmTYo#o1|]U\J+9WA~H3pRT5dvw@kjC)H@9Q m~ dFM      NIڨ @@@@d6"wS*>=GȪD@wEdCM --FnذʩYv7ۿ,?;Ͷ^خ(kȽ $v7Bsj~;^u;LeKb/7l@`P7%%tPpd#ޏ?ÑF[UI=y~+GnF9Ɍ5$] Zg|H5z@ȷ@IDATlK#dK x;q\* d"|K ;;%b1[[ `@߾}w޺l3 E4G#xF -ܪxqTfc]BsA@@@@@^V,+iZlGV&>MN/pϏhc^ AAF{w:ٻGf@SS%"$H@@@@@@$Q'7,p`;[Z(O =$%!t n\L]]]7KC6H?]t6mzVWЊk,&qW;Ta+#d6b1!C\,l_҈WK1Ý뿡i'SoLNjnƩo&p@Scuv7ɞjO2 N]4)7/cvN[hkkՇ{L#"{D$IA@@@I@s+a=XEp > WG@\==@޽#eψ `#>}Pz13[ꫯlda.%+Sb{HkC.q):w^7UAL ؉;nKVKw/dQ : 2*D<f (" ǀK %PUUEoV zN\`>(@@@@dw^hm6sѣN`St>F\; , }\۷oWkٹs'?G@1tV([[[iÆ 4j(YvXoO Dΐb'L]=iBUNuM3\wJ\Yh܊B=pQQccś˿;Douvء+5jH< 599b`.q{7[Yf,es^' Yf׸<@F~;Zƿk\s Y_i|s=굫Ng[nx!B{ۚ XpOAGA@@@b-ވbZWY`,.DS zk5^NtM# `1c"[n%ޞ,qt#!,yb2' 1K<<6c,/}V,aEE"J1ڲ0oڼysDy%Dt-ަkoK9.T D ެ,Z׆8Q/x33Wes9=9chu]G֭#>͊'3<s]_~9edd8Qm+Ob"> ^ls"GwآdMry<=[-.DTBSxqݾ(RβK<Gl=䖖FJٺ{+h75ň+Ƿڝ q"l~RH!ؗx W/g>q:s1<թ*8Wc%ݵdhh@K}FI!P__Q/"#FNaϝB"wif sS|yfsz'~q #cիj>M48 _Ґ!C;뮻`k @AE@@@@#uyt R< .Dwtt8f%ѧLq!Ŝp `E^z銮 ())!u,[v-q6:^S.8-n__. YlR䬣k%? ەϬqch[#Fک鸞CV6ʁNbW_.AMÇw}HϠܼ\mTjCρ\0Kh!:.: `LnTJ/I%&+@VZE>h,In&KH.6spCsMM5k@@C@@@@D@P$[qS{QFmD8G:ڽ{s~_ŋO? 8b p~4rp^{ˈT    `m"A@@@Owsc([$CO@"jRÁ){キNxE|q;=vv~g*a_bc)7A !QgT~Iv++*6ѣ)+[Q%""@!lQtE)*pO3D8Adp|◂ lNJ6wԻ" Ź#$JOUTT$Z~a5fNA?{j.\ @4q    "N8H>:b: `(p fAz0D@n9D3&\۪&-nı}} |3N O`R?NAq?(sѱE\۵m;U||k~K7+#RޱORȄ(p&&x.:HcI3ٜKqn4vn\=wy^~p$o? l TSdavaڵkUkKBHCn[Sd{ŅBbbpbDKU0G@ m3%СCɰc'Dmvi- ۟(zc JKi?^'NHv%dx57ҖKG[o8E-7D`۷/G#E`WH->S5@Ha=b &3ڪ87 466ݻ ӊ3 mFz{H=O=ZG㱊Iwqz<٘!6'T⛢p5 @@@@\B'3*Rf;ԈU` #TXF}]X#,<o޼YaP$7uAG-F)nz'ݿtuZ [kgO?~$RV=rṴmLXnzU([G|?"r/++#h,h~VX8uy#Fh`ަu,pOYgĂ{qGҐ B4 ϕlأCt8شiis!~ijj [L_d q~'O=԰_SeeeO>|8ztiʛnI]'p [}ҊynL̨cN?xIu3/zxEOVPywRς|y=R Z"wv%%j4 +j =nєs^b۶G4o߾q, ݾ%s,J!+$i]^^U7@;Pw~9ch4d˗Ӄ>Lhj;dzʢ3<3ly$n_kjٚ[oE UV-ZK;c 6m>aQ5khɒ%lxcwީKoU-%vMMMv0:>A@@@ngn$:O,ʼn dJ<>Ax5;;[gO&n"]cэ>㣟g1/ `'ۧ ˥~9^?~|*vGv<{wN!Uκ߉TT1dh#Y<ƨȝ-}SeFAlHF׬80b=$j35VQeW:rwdsQ2 േ NرSN9Emnqq1رc /TrӑGI|s=D?nݺp~Ny>*5ja @q8ԩ&OLwuW؈Oҧq)'3f?8ESq1-sh^ dNuh?I Udؘ֥yv}hљZ<-\#- t_K^PyFrEO?_y$Gd_@#.Ŧ-UL?_ΒKY!:^UYI6l륥' и]4_Yp΀=1%yQο=z`2I@M"9)1^ 2p'ckVN2%,tƱΜ9:qW_XzrSO=&a+8P+pw1)vj_er%-ڋvtItgk,'{<4hi&|0kd;bT    Uډ;₏XL1 G=G]z-_x?M7Ӫ7Y(d}pL9!-%"nW*񦄅4C&Q s'Qo9TVzѕT{ǽ5x"w٦AV@dm~\`,wg@$qNE|N">fc]{@^^͞=;f'L~A-"5~kԘ /zڕyN8>`1aDqF#9owgq4hi'{|͛~@i    9,b/}<1,[3hљMX"E60`@D^DZotQ1-Hq"~SW}w0l?qx?RNvmmk#7TM6u"\e*+"wV-A jkk#§d/uBq]hyw6x|dFdsU9S7F6ocY0u |F,is⺈,kFoFKώz]FW6l.+0bĈX}-"Ku|+@nE    ["lǷFDz'̴4්hŝQVՁr@@Ks7N:x: `/[,[o9#Bn4򖖖&qk#]JaWA/8 l"wMdGȷNXi3Ҹ][ө$l~v\nN.K.& Z9(vKރ+ Ĺ=+CY"3~w#> Xo101;MUUqjguM4I ;EFņ]RRb8F-gxejbDڴKGy     q"s 1cAoJP=7q!ǽfRvhŽ+d:c\#giզq3OYo5Յ,_.jz\vqE~Mm-KJE kȽ $v7::k)a*{뉭_GsTUY2A Z[ZIC=`~_klletnxc+ݬDf\/:N t;sp 3رc .H*gNʃ?od%ٖ8+YX҆PB)kiŸRH I˖(-K;mm7ky&sl,cif}ssfP[un.K&QfzFJdiiZG6d@H{4C"  Gf wsۖ:5`|Prp Ќ Rhll^haÆt#eoG0{{8=>sN!tCkjʞ lϟCP__*7g(c?~ 7e[]򕛥= O 5cbf vJ_hq[e$*066شɱ,_$Q<ɑctX@=(G/ qȩyZ5FFeKgxyG#̻M<7&կ~E擝XZZ품9‚f^:J"Nyc{cu  ]ܳ@@<.PG-xS2V=Fox zX%9t쒒P׀t {0}öGFYu(S e,fp{quYzGGF"U\bTSUO l}T>,{?ʉc WqቧˤK7IzAyqC ^صk#U;9i .'](^Ç#IuMתlXNO@S3u!_ic7c @ X)ƏMo9`;ޱcvv;l۶vh3ms>N@!PjP @@)Af'3xś5^W;ΜKf?f{.xGə-wjLMrE_QO=-Wo _~5k`m+G/"k{,ICHZƟ\9:!C}ׯأ[h'LMM9j ===}vvkc? -혷lnԘx3}:'q4UjuK"3fjNtSogZ@@ SSQd&@@ hp{EEXX=XWAfnT 4}||<(}w@4X'FGG#]ÏɓwX;U fn2946%C_sPᴮ g_e|V?[dcl]2L1++r7o~/M7}R A~)33{nY\r"ݛCM!O>d,drΏzZ?;[@Jٟ=F{ 8%qmm%3R-!=U>'w3q;w  K@;nܸ1&uwU,#笵[*28pQh <mU-kg-u  @pO(C@9}f}6|o5z *))qbPv*epJƊh'T4449|(h& R)p{KS^8jpԒ˷ +Nj_{Yҳm(,+[?+G^x  ;%ZcYؽOZ)ٲ)ݲѣGe߾}fiokM%&~ I,bwGa-=zS)HZG/\_2o~]n6ioo̯u 6?_uTȌ-o:#;Nd>':1s>@%Eo՗   qaB0rf3?zW@o[3hM? ShnnvESH@_JZkmU(-4uG/r߯9 rR nĭ7\!SZjd%_7={wvv: kFCh&w=.l >|d= JX;:h!6=i6fNs~x̼ R@ Af ~Wf;Gjm\X>00iFKKKd @@ gBs  Z LC7eflKi9d hV130-x"Xhnox9qlϻSG9].>Ӟaݏ_])?8q/HlPqs{"=k)Go\'sTo5kPm&mmm*6nhwS hKǹ?9Ē ,sH<:`f`&??R;vW."lv]w7ȼ9q}ɭj.qtԶli xJwO]*  E;C3/;u24S3SHguX 039}CA =+O{n%Ʀ_wӻJn/[6/|R&7~A;91q,}ӱ?<ӢYR\T,l?EU0'enaCh @ tjtQs]w;,D I}{SI277e_HΝ;#&jn뮻N]B?O}{|pt윃?Ugfg@H@4>;G@@7:f= 15+++ Ghf N9xhpьF͢ PH-,avQ0{ )Y -] tׄ}'B٫ {6tO-}Hs m_I/oӶ'_7 f߳g,,:;dVVTʶ~'Hw%SSS]m˙A ]#ÎCx܃ÓNrM}^ֽݾ%wTF)0??xt.qUi韆ɅG3<3n3^޽{_jdGyD[ ~##ӹ4a p>;G[@@E  0=~-SKkwO.D(hF U ӠG'T*>yL{_羵Y/}K7ER(d= R,07;'k¶g /]ǩ{bѱfGxH='{S)<eipfI3Bq4R@vi[# L]믿^**bF޼y|ߐ#}m^"@~^ @^F" U|(f>Zsm 1ckWL55d-"Rq8NA 7/~v=ޱoX/rK_"Wy:T4c@)ۤgH_%7ly`~A~9OK`i)#*K޽[z{{ɘ٘e֭tV d>CCC}ql nonYcl:y3R힓y/oL3rR0J@3o~ ׼Fu]T-C|_Nhz`M’kEdb /'  n{t#  3TZ<ZA;vȑ#G"K5ɹgT ɡCl{ɶ؛EVb Kem3@N;/=!?{Wz2^|]v0e > ݲe466f_zynKe%-}N7&Oʾ}dqiѱvvCCcZ(4558LƍX*(=GyY3z޿/K{cG<6hϧpP̦[ԇ^wm#4PO?+XΝ;Ñ]}nd ~Vկ~e=YD?QHЈ&nVZ<ߞ   2:QK@@, e123e;iRVs)*6Ľp pˀJwo^+?'}-m:9wE0cr9ݎv=}}saCu$/IaMuU=&/L~hm@e;]JSOKyp֓L^-OȨ-]֚C1{_׀v3;ɹ}w{ 6@ yO*C&{tK"r饗Fڧc!XۇiB$kɵ?AW]u &@@ gRs! V!̷KS̒4M9(PSS#EEEn`&֢٢梏`ݖiL޾Pk? lٹ\ۭ(--N;M:::#cccO"$LXj{)ݾղ42xrߎq[h~Z]ЌtqTVUOBS1G##͋ҁv)(ZMg}'Ӡ3  <=Ts?(uGW_WO3=r7'6§<#Suuu\oyDmm\~,ڀ > ݇*# d^@Ql'&q{0),6lرcʾc;3$(@,!teo?ic|![+gSOfр" rwd 6e>J7uJϏ-/0GQ}27ܾLNNkɬ ===, R r7GhmmB EE㊂`GeKdU kr'NӎUTT8@SS\tE{ߋL=P?3w-n}~uF ϵb|WJyyy5  O E5@@/`>q{Zzz p *N@ E@&4 j||\2qzΑC?goύ=f:묳\3]} Tð. +ʥJˇQ#ʓx7~|00~ΝrGO;]2=nUG@ p7Ӈ*# dG|أ3zs\yׯFZ\\}HA $A@ N'T*sXז}xx8N&Xr h}kyBۯ,9\SCЪ׿޲ek}-PJCJ-s"Ƭ">R7vЃLτ:Xθ[|7o,:FK8}׮]Ck QHV`xhضnmk-c&-={n١Qb:03(JtO笅{V @ W*ꄯY_KWWy: M7$W^y?~48h.f}ɥ1cdpb5S?=mMHO":z9^T"ʗm,n>=[nŵ ځ׽uNyYq/}Iַfދi?:Gmm|H8  O 4z@@C@yhf.%ji阂@w=ftJ8Q4}``6r`00%xE!`xU{om elTPYI}`-o>ql4>>. }:>I|2ޏJ`a1a\_~-Rz/,.T6m$ދ%N&w/^ihhQ{'<, $= {Yܾ0j'=,:V,E h7g嶶6GÚ=yaC@IDATMo_td:M\QUUz^򒗄m8 v!T;_}ՌƗה&  U   @mR :J$zCTܭEgG-..}m}i{W鳝R|C"b,\4Zg4uV.v`Y)}Aaq__n,׀xL{%Rv6}ûdiMf`_jYm2y6ع1>FXA.BTavfYX+*sukBb pvEwVSSms#&=~'{wLI=( @ \z饢)uuuW2MsnSO=U㎜k B@ G@@2,oNw5 7}HA 0i}(RFS]+Om׬Oӫ =zTo.ݹ']%PRn(yR3VYQQak5F3O?t)++iLpgʶmD;0::*>ٳ'4v,=9p@(-]_{ jK^/KI絍 r^}fdtV1}477ۖ1@Q"鰝~& 7??o;yɶySG[ /@@@ +C@@<+@{!i+d rСCe,|n^F9쳥1:uqy駟&Ǧggge޽^E[kZf?z+N/<n r~ݴ3;.N`}6"4x@:){Jǹ|L3ݼQw@@@ =)-B@HDphr3kTCm3H5 {V`Æ XYSSckԔ9rĶ y E0=\ٴiSOc=&CCCL`gK4 W;0ؘh~'=+egIe+G'dkwF+rU|fBG3HKKu $](tۇk0)J͍]@?giBk1qZ1   @p  p{c> ]2Pa3y3P N'z#ke\l7-{ooo N7RpM9鑲;go[ٳgYݣJyw^o~װHvПd˃ߔ^\?)yLrzhk=t1 k@@@Ȝ@q3W΄  /LZi Lp<<<@ |lk;a)dS@3kQenlMMMEaYwCG:wd -[g~M^/### uJ(-- ej/F*^p  ,-%XvEJlJx?/mrߵkW賴n}-m(/0=5m|-./+o|[XP$H"1sgV"G`)o&RjgM-PTS-]`O㯣c.E@Ȥ@t B@@8Tևif(4#Ut{بnn3^9N _45][Y5jnu8t+((~ gu+P8#k;v,~aGPJKGGG(@W_ʆ7\!姝,o|,Զni~U|e/ A~Rg_;7JN,p ,`dAv$=[v{KM7} =`]U]!  @ ĿKMa  ^@Y'''E3ST3qjFõ &H7Hfƞ \\\ jN5zh e֌'g1 L;}?Ѐ`J4}bb"Ԯۣ]+kMZ;%hd*}nw @(ݽX6mVdamaoR! ptk[zjv-[Hwww(xzddD v w vנwݣjZkv,~"Az"^\\sNM ;d7;qcʺg}vRT]8ZN2R f$gG }W˥[6z=wI^![6;7k;=YObf #e456gvNe%=A#Y=:z1ꇚ+@@@{ Q?@@O hbYY-lܸѓJi`^BW p?l"ڮy\Gkd~FYKx笽R}^NY&4=ӹDNkD?9VK筟NO~Nn.~YصGZoE;;\BܽxUܼv ZZ[l˘I@"0Ȭy(??͠N@a0s tO~.JZnYJOښ~ܐ l'n:RAtJw ,'1)5tN8v!j%yi۽ڴ#   {N:1@@ n wkq{d]ϴ8 lAA 8-D!e16 S'@p{l92~XWU)]_YVj es_NjllL{6ԟ=`6>SݛE %dp_ί tkE:aޓˣn @@@(@ uB@mvv֑eʗ KccAJ^j6m ٩L!v9pm3 =u \h~ۥ;_uue?]x)?2x ]~YZ^U^%dp`|)=ȑ#\1WRR"c,Wcj   Sw K@@X"Ҫ;mذB}x>99i[ ԩ816n(m;&dϴd0rB%"=#egT{WNȱLjllL{ggddtvb]]]edP(~r+SO:g#v%pg@@@, %xN  {555RPP`k63]7:|,D )d[@Gزe rx)p@v7W$e%8j A:4|sGGՊ3+ȣctr`4 4ntz^9zoG@@@J4@@ RUUe;C%̄7L7P! 'NLHsDP\&; =@ @aYlg>,Qs[1V{fA###2=3c;YeEؖ1YD27C50{_^dQQTTTߑ-@@@ T@@fF$}L !z|6HhaH^`ӦM֢pEL')@p{`lZ|R>=W'˰ {92c#W #G绑G.DVC;OLLZu+Jl3mG`-   .7@@LR!ƿnCL>|8l@ "},(xADUٳgh%yۓ7c.PqsFeM`zFFyXYqrOuo>{ysSTUGKO 8j,uEVssJo͢ҶR(ZY3-{ځZduL#   eܽ|u  4+YIzE*++FaEm[ )0ccc)<B`m---RUevӠy7yxi2(nj!׼. 2|[ıIrOАLMM\\T,;7ږ1%2򠣡~n2;TU9&`&=uuu97[2ԟ#"   zSo@@Xp)65==-f֩;5r͒m-nfgL kt֭RXh5Lo"oW"/OH6~3RPn%K?2Yxxfm=A7o,}}u d)_^~E\Q3iQ#t wqn-Vi~4;KR@@@'`2Q#@@|'`fF|f35*nhhp,Ivd\a>m nYޱ6m @j/{Rҝ\&A2uiMto^fGf27uGHA`D#cǎjV__/NA ]|Dv(z[?^I   :@@@ f/ϧ9qG6.2ĥE#wfq %VGݻ(zg.g p~Om{,d]G7S6C¼ ee[Lv g?rq.) h[i JlEmdޣd@@@  D@@'̠VƚQjÆ em )(//wWG0ƥtU lݺhrrRV}\ޑ\ o [_#]w}I|M/ZGَ /ih}O߁G56,[Fv;kQ[-m0@ 4gC{4sfi   @ p4W,B@Ț>!mfBӚ^A(dBH"n2Q΁@4}@83ZBp,d\@[>x](н:1?rI헩 rONzaaAةS** E dp_ zB_֢ߕot LOO;^潢t7=v    Wz7   I]We)jkk 0m e-fB:Ȗ@}}Nv-'NnqfnjȨ@y/~WJ;;(ŪȉP&_vͲ =ZhҒA* dpw@,*a:[~1555{l A@@@{Q=@@ ܮY(4Hζl"̤K@_ff85dh$sܖ4  n}[_rArm ю2een>}35A񑇇E;<[KQ0C-[ȈmEt,TJd˽vO IgM_Sdvvv ޤm%3   @w\$  ?H&v\Bؑ 2 % @ ̢۶msƍ[4W3'3 @aEtv|=6e苦_.z, D(Kkr?3=# 6o,%%%,@AQ5GɺiR%0??/333Ùl+t۽L    }p"  JKKVqmQg^sfT(VEXfLhi99E IJLfٻwh6|+WoMkO;vI/eRebcܝQw߾}`ᦦ&O;Β kE_###fiG s+ B{?v稣/P@@@~z@@f$ͦdfBtTbG>.K$Ohc ^kkkmU$ rϧ^ y3ʱ2|⹿/eooIWWm3((*Y@V nϑ֢5u 0vB0GT7}_    gJQw@@O j b,255q|Ќ&)xQ`֭RdaiCt ݋J6_nȑnk)+S.A\}o]lm,ޝXʭ 1rhhv=l[ XZZ3 ҿzqzy'E@@@{P+@@p{d>ˁf f䕖sP(nЀa2f@III(`άO__# R( '󟔂Ғ@f~_*Yܳ/ҽqk87n(U,@ ͊Vvtv*nfihh01"`foMI"@@@<-@/C@f֠Ck2E@*+GbqZEC ph(#ت3vޝ[m@.-~S[jҁCkd%_7 w}ݿ,/۳{Hkkr6׈((Z{`{ lլmmme NOaa֦9sl{!   @^ ח# [v n;6`&"`fqz&H>L7:4}tt4I`ӦMe~~>hg] U  ` y<|T檘䑷^'G>Pg| r3:lٲE4`#uWFGx{umk٥EL#6`g3vfjF_   >΀.UD@̇vm]zkntt ld-CCC( ۶msЍӋON'*v G:WmoH_M^&9qhk| r~(`u\΍ѝ;YE#6dAvOȺgE;5[ vV @@@,@uG@fp73N<߈,UP3N ebiA-Ͷ/,,&ŒQޜ`EpҲrP KʊZ8/ǟLjtnAss#455f!P/VDip4g-RYYi]4ipt     @{.\Eڀ  Y wk<33u= Y&''eqq B mmml؃i>+G`mu jسgͭYܛ,sjȊW'[~])ٔFd䷿~8ܗe׮]r=wU0@حY:9v #99~/dou43H[;YqhiWVV&u@59    }Ul  @f>?Z~mii͇w%Bk3-333gBpzzz7gΝx~+Q_H@͡ 2C..?|@a ,xh.k`޽{eaqv}emѼl1mhNq˲SC=T])dJ@,--Nv/ȶ3!yQża]4   ~ oW" NAډ]׋X vV 3!ٰBwSy , LBp_Dt "M_+e:7+^) %T]]N_ l>9~-k-ܮ%)(0>C$`dw;Un9(v>Z6}Mn̈́@@@{Q=@@ m-|l]3b>؜BLA SUUU,: fr eOBڃ!hoo &@i~ۥ;_uueW^xI{٥2b>|XG6mgcCxZڭn366 No 3H[G1#[    }r&  ̇ċa޴ӎIA dqϤ6Jvڼy㐚S\nաn -0^, q]]v^:S}VTTÅ2f@KK477;w^v"qXDJ6˖)W\YʊȧdJ00ůAYyݲ͚e]Ĵr9vlWG>/6b qF.'.-@@@n`@@t ;c͡unHjkkmGNA k m ,pOҒj*Bp.A [>%7|P ? _#%_:6[wٳG%uVGtq $=pŸZ[[E)dR/VZZ*UUUoev̧    Kդ-  0Yv bL;X=N':,))vttTHApI'9^Úv׮]4Dp_I&+e&E͍IUmq>U2㇓/)OIv4H%L@b>88h*(( p I mjjvJ28hg z#    $7\@@ňKn@+f6uȩ@@?m-=ڨA 4o|d gP@sϒT Vew `\6GFFD3_G**+\ `OWߵR?oiۀ v?Ln!;&z/ZY3   pU  ai'v)խڶP f,k͠FA^xfѠ=Bp{9/@qSluI7M_"'OzT ǏKooYs)9((nFi<]dv@5Btdy7^"Ekw    {ׄ! 䨀f6QimqjefᬧS{@ jiimnm14K[ fqL3-@ W lg,f/daǮK^ r_{J 5N;6`dp,+Ԕ=kѠ؊ F 0~Z(cZ@@@|(@ҵWB@IDAT/UF@->J|sa>ԋ@`mmmn~&@DE%v%ځ(SLIs'^![n)ޘTeWԽ'_7R`ݻcZKyYyhD1*96mֺpKt)w ptrz|QeiiVUl   9t1i   4lX ѧ5\yymq<3dBD4Y ´4 o۶mRVf|;vpMACc"z'E_w]/0:7BʊٳGffmѺtIu񽀎;@G"0=TWWޣ i^~71;fN~9{vKPO@@@b Ku  XPteka53 %N5{L ;Nѱ @Q0pk9ٹsgZߛn @ [_#]4^x+_WADzס4A:[JYc#_1ݭAe|wq;[;Y@*49 Ry\:iWYY贜K-   -@{~_Z  s` 3S 477;6q,c s5==Ss|R*en}-?ӢQ.Z!4+n^/RXS}C5}T_vfd+L5lqp =ElU---utm iעv"{=L?#I3F@@@ R@@ hPXɺg43n-p4s0[C̈n / "===*i={8P&$H@\z~])ݾ5fpj9~Iʍ3Jkkk*Ʊ,@p7^nAnÎ]Ƽ/ف (`&)Qxz_!vT@@@ qX  @᝙ORR}\9D0`|| @z&tɺNcr_&_6NWWXRSS#[nT5E w#pkM[XXZSȴʊN@n#:vм7ugV    S}z6  tj[#V6`&"-Xd&H;uuu9l׎ [G,}]';bp HRO'[O>#=W+N& I훊SZeEl۶LXPP.~C=]G$0G7n!o=[ :t Çjgۖ1   @ kW  F  Ӿ6+񴓀hХ޺i%PWWxtZI8MvЀ>}%&=W#k(nm|]^Yr &杲20 r={8GO @>|³82>>n~v,nۈ$`&%n#G>h:Rhr.ba@@@ pūJ@@|!60]:}g>~X[wk?G@ 3}vrpq`c Y’'󟔂Ғ9󓇥W}I헊>?7/OzZ4pZJK'Kqqu1y&P@~1Kgg'#(gD@LLLΥ;k#:߭̄fҌ;@@@ G@@-PQQ!eeeFn96,X@ 277'ccc)< B 8x)Hyy\k.-' /]*[&U?JjTl w ܹs,//۪^4F@AѺ4^?wǬE?466Z1@ոX|v"^&} @@@r]\´@@f@{^vUGA* A ,}}}$+|Uwy_eLޓ9Y ,$a $x  !3bĠՑ9+muuW򶻼7KpYQ]ԩ7"nEf~efhVn g5vKKKH0[3 'N 2m  @ NuKOIO_ 2%Yޫf:Hp{Q)(425b%sg=І9 ){8A- M˓ S+gvEA@@@ pO{C@ӔL>w $&c$ hkk5Ib/8{/(䞝mE===Yp}# 'M|OF?󎌌?!S+$S@?+KKKMupNW쭹@@@ ==G@@ ]VVf: @h W4XP:YmQ@bJGGƢAW\ic5 i"/?O?!oKV󌗲oϼBnYܶKˑVkkz]VRRb'FB dྙrL:hp~@A Ua}}tx8wƢÌmXF@@@ ̿  H:հHgwfiJl,#hͰfZ3Z$Sp'Dg,8vhPcр^h۰ l_~L$Ӊݐ\]Oj(=Wzd}Tڤ^lfz;A@1 dYim/oll/bayyٖ%[NA N8%%He|l>:~)   dtos  pjiJb_D ;?Y0? :Cbeqg }@GJg"cڵk{Z|(ziWͶduo{,Yh~n^^ K~F@,ܽfp[CjRYl555ٮRGykkkN 2O; vi   @0pF@@P@Lg+&k8>>nj Рߊ a5W=;;;Z r5  V95U'dA6gf=oZ{ʦ%x߾}v 4܍,p= N3qsDLLL^%PiOwU^^ˉ!   KX2#  kF&@wRZZjj<99i v15`$Jm^ۣ\:Xɓ ^g@ wS,Y?.=*=Wn"ӑYBT x rJ?@VX7ݯp/":kT  ]+&mƢu@@@Lp/  lW`SHVWW*M XA  nv =///Z֭[244 @ ?/InKnU}}}uKt A;p[x:!ˬq7أ333R\\Lْ4 pwhvwHK@@@+@{p;z  N+n,靍l bkf+5 j&0;4=C}?;qhhQ̣v#WI)tUۻe}:UCpPǤTk X2ggWB)~[לf5 8}A:8h   @ Fw&  4˳5;[zibBTgggeyy91d`_ ᠘a{ثhO5Fkw̻ X@Ri⧤o|. 51aixhXn޼i_Nvt떢"m;U侓N&fҁdqqtr? 3fFq'bO-    (@{&3  Yk'_:g "w ]466QȈNjl2hsrr"A:KhޞV@4u}4'e_`S]yY|Y~lmmɍ7dphжI^ntwwKA}[c P2MTLIU f!{{RC@_h8}7ceS| F!  dus  ,NLXB  J mhh0uAn߾mcd $*=zu㢯277'.\%M#@/<)y]j3}W˵?E֒/ǺI~.:A2lT%3 Ƣ9 "4adXg]/1*Ά AG7   ^@@=fqS=!nw,Wkkk2==v O)5lN@ۣH8x19p@j\xQ/@kmo~I~N2H'ϞY]޶(ܮA{Qr G'ZO t l0IgG(Z@333nTUU>bXA}S@@@T3@@|-CؘY h0۽߼ySlT HdGA399rD:v  'P>{ow)ȾȀcݒeq(#dvIVuB}}$ NߵXܘ"NNk   @& I6   1waaAMu,wޕuS+B@.--5zyyYMu HdGE677KggcFB :{ @ }rJO'}gP*98<.) Dl.%<@2~F;qxz>>>nj/eee:Vb l_KL ba@@@ o&Jr  챀S&N{|شڝ5c:11VW;44$NA  n7Wuu?~\Ցe}rJ8n,9cP {t|Rpc"ӟx"arv[96]g }^iW}j @@@ =}K@@ JJJtVec%l -(,,Abj ()LN}>X\pAV@4ȩ֯A*{ۙ2_oۺl r/..m108(#̾csI CD~Y[[3R.?8}Bp{j=UUUvBk@@@P4S9%@@f ___N`߾}RSScj( 1\466J^^Z'75`Sp{4ɓRQQ r@ }J-Y/Iaf|ߕ\nl׷iѣG ]r,7<ӌ~n5QSζdZ^^.z}Oq'$=>)   d@@|-?jYufv sAڥa2- *0T4 PK?G/2XC@@\3@@ cz\?VWW{tQP(i[zuL$)뀮ÇK{{mpܸqCn߾m n@` hjȤl+'.4&=Pݜ?{r"gQF zAn7jcǎٞfddDz{{ ۱ ,& :sT5U| yeto'3Y`7r=NM{+kr$v)pҁ^X8e@@@ =  AiblA8TQ 5XɎma9:ևAY]]SNAnf=v8nmmɍ7ڵkh 7:+͝;wu[g:ym'?3k2w{YrKM+NPx^umD"`ޮ:t_~8 u   $H[@@R@3v999iԀכ4hX)E@3[:ۀS_L?'.Q ek,ϟyM#D`ee%20u*zsxI_Ծm~CpM̺/~%1Ѭ{YrKM++<@Í p lՙllT ,,,̌𕕕RXXhcegkԠ@@@/@} @@5fw#8]` $l\ӗ?n'NH^^:.]$'mP 4@$  XuSoIZӲz//ގHWfyhgYZZ!yn*YA Nߡ466W:ܜsXjkkmWog@@@L =u@@ բ?pf 4;5(tj2==mcT hyYfqlb sp{KJJӎLCܹsG\"M "{ v5L5{X<)'yv޴2=pّ#G6K蠥sLt#$Y@3^pA3+mjnoze-K/[.{3T'X4]'$4[w,~֝ @@@    ^)S'{̼EEERYYi:q \XX0ձ@4uֆY(2)xxI̦'2(Ě ո@^@u5]ܭ%''G;&---e@@@"@{P)  jkkMkkk)4شNMlZ43իW֭[ֶ̓#xРK.9ՀǏKTIBUN"㟐WQ6gw r߭rtaξ0|M[ÇKNN R)?~?@:w!   2SFρ@@؝@^^TVV6֬:Vv,YF:P`2v {$PZZjˌNLcrIwl4::*/^%۩Dp/]rEn߾-:XZ8 gΜIfѠiKVz?^?_dEjxM]N+&6r=|]2<<,+++MM XA N':Ž:Z;2;%   &@{.  @zX3<eqrI: ͌njE5ZZZlӖONNߺJ,@p{|` immG:f\\\spЁΝsl}]8,A}K|6d~A;OjL{,ge.H///f5sS },LF333NQ@@@p مZ@@|-ܳ-ӥk ś:j&=.qbrMV4^'۝2Hܜ` rt5F{ԩ3iX'zI)tʪ2Ihf"[>s;vlLyN_.~}ZZZ,A9ցMzWx>;{B l3S߾}[.\ z}Tjjjٳr}WW ;OJ^Wm3?jn߾-/^w#" LrUѬֲo>innӧOeP^=O:U)8{z;oc"]{#sJot.Yv*::655!2n,:@mme:pLwxYF@@@߷` @@@ K^^N Y]1Gmmmk‚ X tC=d8>.\y~Y3ZF~^sΉ9鞹7VZxQ'uaû5][rg=r( i30)$`'qǬ{KcE3g    4wNB@@5ʊ~؁=A㮩+P ;;;uڅ!^(>_'wf2An&+<[Rp?l/Mnc cZI,`M:%¹1    (@#   O]'''w")N}AS/Yo@ 4#GDƢ]&&&U,Hv;tTN>-Xt3/5hT{fրg}vY,3W8p/]Oy?T|FZ}2im7v}ctܹsT^ aT fTWWK~~~*cʊ>XA@@@o@@#PUU 0httԸʲK p  N5OA:Ckk{nݲnkDEnO:P"T=B35?afpB&I:MDݝx4tlN;I㺬%MSWTL?dʅ˞6&=*YgpmllwPg}}}|I*@gt@kV   qp  E@ jjjL]XXe 4(Vtx돏r t&YᬙW6 ϽIp =˓N9uꔔ9nϹ;wDJIőJȞ\pA_.kkkG+,,cǎIww9@K~Zھemk_bicdL^2hmoB$5.2GlwIgrY]]^}577XAoKKKQE@Xv!ۭtF(NA@@@o{5  @IDATp֢)lai#‡mmm4e~~^2۰ۓǥKnULgggP쥀(^rEzzzdqqqz ҎD1+;ۤ"/18ް.2I(ƀ~TIN:M3+OMMقZu#GfOnG Nu:t(HLN     ` nB   @+%'kv*ӑD(Y@4ôh;_Jr nOw23&={VZ[[%;;:˗իP@,9ܹs1go@[ V|衇"3eeeu72bKsMģ_}Y~1Ѭ^ A^}VvCoܸa,D2n {G:@ee׃1k~O@@@@   i&h;#27H\U`銉F>ftl;%'-θ`f@iʃ ~oIZӲV_>"K=Oic==./~ua&Au^PfBn:}bjȈ@1̑J@@@ 8w3   _4ԽIY]]5ձ_DA+cZ b bYE_4\ۓ띪iwzv~shL  U@i5 ؂OˋVJ^S⨧=n޽'#x<9Oic==Y9γwz/Y:K^/DM%777浬ftƢ*@@@@h  @P4Ch@P X-uw$Y@HwvvڲI$G8(ɓ'ԱkT ty󦬬80 3DĚ @=*ݶnM Z_Ro; BN2_-g rF@ʽ)[TA.044dk~>ĄmΪ)W86   @p=H@@p̱,k#<}:ś@ee6S+Q@uZIB*nOk`v8qBDޝfzg}V! :ݾ};2`̌)-2^R#/?O?!o6j!C? v뎱:2AqAq|Ʈqh$Ƣ-*]hR eVVh;@@@v/@@@ iNSO|1liiH(A)F__.C<%1'5{=p={VZ[[qΙ`Ν;'W^eUh@ƍ_FFFb-z nVUUf5i1Vo%''Կ9[9SVv-@pvC 6l|G߽{W.\ ===2;;keȬ:xi =477SR+P3SR&ݛcAhrg}Vekk+f[n@ w\pAzzzl_gA1D̔`T<iƗ$o ϽRuuìqLIq7)}]xX^^ @5nUZZ*GA@@@ۊ7d  Z!{0YwwiaMMicAsttT ~Рm ^~v"w;SNɱcǤ,fWVVƍ_4cR @pt֔Yt(VAiGgFZ߿cmG Hw: ޏ]2Ih}նbrE2 0;;kKxsTUUOdoP   p5"    Ѡ9cyc.Ee``@677U,#["q@m1z_rq9yTVV,?svb(Ew`s\HB@3`+c\I.X7 xd @@@b Kz@@HL4PX4f%<=Ż@SS h/ AhmmRSwzcBp# Y:;;ٳR[[cЌ"{vGk-:uJE)-P ;OJ^W gp~2vAvl|sjp_ ,?wܱif/[#*lY܍%'''rnc@@@L`bk@@@ccwCCC:* 䆧znnnSf}<^zU4,@p D9yhvH ٩}'nC`4[訜;wNdkcM̙3bo c2Z_aÏ~@=2Ax'ݵVCρ.0>>.V:C5/ ohh%BK   A =F@@f7m+1 euu56܀4@ѣ5͛7]_v_  ,}s#A;z}GnDoݺe @ ;::y{Iaa "Px\N/eɿ݌ D t¢mF'mkiiQ_@w?Ƣ3XF@@@= }  Alm,CpO."MMM cMmj >Ќhg-OP ~߂ ^;v-'O T-oy~곲rΫk{e? ÷`vv6'pV} ~p:;Ż~&\^^6m3ě]ɴ+    JŷsC#@@@mmG7S)GakV|-H@UU֢h5"Bp;? {n_rE&&&Dv) [@Oy]g\lEEE--Pcϓ'=9lȫ~E?i;wҹJyqY?Iz,M@MlzHٝАmCk2 [*@@@@`W@@55ƍ`H I:55 fvk ڕš7i?WD-~iZߍhY"7oޔ7Ũtg,hbك=`@@@=p]   orrr"Y%Z^^{Xv)A&hñcĚivqqQ4' v&l_|Ydmm-=8\]tiPk"۷vKHč|#_zO{Xy' YoAv!g}g_EwI )8$]`ii)rm`ܲLt@@@#@{b\+  )ENRMcѩ58@ "ܭ?uvNp{ܓQY]\yt钌`4}bbB\ j jA#dk=>.O?%E?|O0v rϪWhsQ V} zf,yyy3Qv'Yld+@@@ 0L߭@@H# `+--ݮcfq?iEA Hmnn~Su06ݐf+Y5}3yV5tdݶ"zp֭HJh Gu^:[ jǺGH!}B32'?Ogdeee w`aafG: 65 ҲLEVU*w 66!;wz# Eb4>>nj M'    ) =@@?:t},~^4ɘ]ifF@_#1ۍE3ܞ:uJtL:^vF}?\AtJ^Z\27am_ >}$qǖ39\z~W\T$hf^ij Ik3c2=cGFFly   [w@@|+g?Ѣmi=D,w=fN&/Q7mmm h+W"AGpB hP1=MP=$rl&Ji{^F 0vQƠv {Xڥտ*k7Ȩ 惿'|qL r.ׯ_յUINvttv[v׀P8Htࡵw\YUܭuKnnXF@@@Tv  @P41]iA9_SvVWW#?k DΟ?/2ZVVVD3=z4m%n޻GYO/`X3GuoZ#A~IǛ0_9F;4v7jI@~gWd-o<k2++.K+YLk^F,o`C:nˋ[?6v$Ht>p:(Q %:ۜeڢ!Z@@@H@o{|  )РHh7ǥErrrU ,}200 |Olz hOWWe`En=H-`H>o Ӣ`w" A h>vvȫUUUmӰ%㟒?/\z #{*leJ䤌_\lg}ۂ DAZqMٝ6zS+    ^@@566F21G;^K8ȝ]@<ɄZ43>QM@P[[[͛kEqqq$@tCVnНEW}!mmmhPͤTO3 L4=9;h277 hנvEd7EW8%}7l}-7I2+)3z G~mtr__[nλNjjj.#۰@t‚} Cg#y< @@@{=  i&?k/cˑH7P 4஁GA CL,ruϏ냰Lp{%g ԠtӢښiM4H{)**2An$Ffqq12gEMhpWQH7?歲rm޽'#:wJ/Wv7׮]3J'_ZZ*-6B mlڶd h^Zn^:tX2   $P s <8F@@ hJ 6U5U)4Jo߾<00 u, 4֬5ncWN>-J!=( WWWGѠw ^vS4Q_hh{,k%:̮nj i`{aanwvJ A_oOf)S<{Aj>I wf {Q^nttt8 ;RHm@Xmmmd`1zb,zˠK   $Vw@@!|?Gfw?ڈ1txxؔ_tnhhq~@Ү.9鱭W^nA3~/"VZ5}CP@# , zuޣB "4+`~~t&~YAw.I'>,gH5mYoڵR?f䮃:rȑ4hڄ {$S}as}Vcw5 { @@@*@{By9  Ь̮ѢYWFN@Aׯoo^)ѣu, 4ҮK.hVw}wvv:=o: h 5'jkڹ9o 팳Jh@C59d60yާ]!ٽ޷NmIIv@.s:IQU얁lOXv]^r?~itrIήUXlJh =:Kk uzzڴqEEET    $T s =<;G@@hfqcK()).//o@+at[ hhGG\v}fL~Y!/@@"aD4@kVof@i%80m+_NmⲭءK4=߶T욭]m) @HO/Cvnluk~AF_fH;,YYy䮳h 􇋇IeeX5'a6YF`/4]1}655X(`5   {.@@H `vcf; 2ӬeeepI? ;|\rt۷oˉ'Lu 4*YXX  ~*ޠ/4^o94CD@ ?q*NA: ΄x fe߭NC4.!؝@Nm~/dw>,w_y㟐s, b﷝7j[+ mcú$M```@zXt@=Fozc$4;@@@+۹v!  @PcdpplYGt:յi0Sz}_%,j}ЌwTqSDp{ 94 ֠wd zwТMT4]T%+8^7? |r޾N~:uv fgeu d_~w9dOBgX=*uwmwLG ύZgC[7o޴uE?'І9v@*HB1]?| ̆}]@@@/۹#"  @4Ш\fff{p޽H #Qv'Y/^hXn"a%I}0}khMM:'"P][[9!ifwcwnh 3f?oc0nkhsu)O2? HQɮa&c?,H^[jNvNZ+{NYe,m{/0:ZZZZx_xX탃- HXA@@@ DQ$!    fzoߖǏXq/P\\֮EoooV ~ҥHhD4cqoooC('Cc l ms*<Ѡw}Su9i@kvϸPPPLHs~M Ϟ7K\~ /|$R3䮯zͩc^8J5scNr,sqӍЙ \7@@@@`psRv  @Q\e~=Mzk?⮁)GFFVJJJ7d h`dwww$]E===rIѠD˾ CꟛNAmcpxm4xn \7Fx܎@f>iǯHk&W홠c)lO𣯖W+#͢\`Q6 v'{WVVMA:]GTe%+< (:d g,M>`-:hxuԨ^O:tX2   $Y$s8@@ ?j0˗MRO>mcŽfU7n6Ϝ9&V*~ESi'bfL~s&Av+N@d 䵵H7$Cop5{? +.J/"l=ɠ w4-,A_;;;.YI͛7M`e4My zl .P>+*=Q]>"K䮟I5쬭9Tde #d ; `Z2nEqYֶa@@@/@{9  ժ*S5oհf$@T #GBg-zmx[C@   GǞ'O?%gOiiykfVF^+2OGB'+;5jZs'dEf{?0ۺSSU]]mcś,:YMM@@@"@{BX)  #4u3QWNX4mXF h=S3 ZL$ ApUu@@`9_ro; g1*[ ACN:+;^iشְ hA4x{{Nuy    ==@@@U1ձM@>~qh6w $PWwAlyav @ l1(Āad(р"M0AHf )0}7Փ'{^tT\N~Vjijj2I;uLLLT   ^v­'ZR23Zy _9ZҒ,,.ґǚMcp+B[,ؘ5:}FɱW1Ɔloo;*,,MA@@@ =>@@@ f"^tQZZXK;h| &P__/aov @@ ]OKFm;9ݲ_xښucII5bP4.vV#zoE"v]o5@@@@ Ho!  @BdeeI]sw nw,󲿿㖰;/ýWVV; f&Nc ۽TC@"/Wھ9?CY?Cn71;7'!^je ]n58=hQq\ 8==Ic;7 hM@@@fo  VA]5 ķ Ζ&)^Ð QS{=i@ 7  yyߐ@ߐA{\?>>n?/7O:;;웒Bs܍CŽ4=j^UU{ɼ ϑ cG@@@ .pB@@? n w{}o GNA 4"yeӎUnR@y|Ǥ7IRre[S޾{KvVtvuDb:k(DR`{{[VVVdZZZū/$GGG7     @@ IffpQLxÌ('@jjD022"[[[$   EHfksX?[\=V ɹ+CzFzv{Ӱ!Cd3vu npW3~:cFs,    <N@@6{ ۬ؔ JMMc#:KNA .3>~XdxxXz<  *&m_~׎SY_R>'Mgdqa?>>!{"{kȞr]CڗtJzڭ#D,8ѯū/5Ա3    `?=;F@@:tsnsXuQ=zddd[]]8j%MA rP#Chfweftנw{D0 H _/KՏep,}J{qɵA3280('ǎM[uuKNn>3in>0 ,5::Wq߮ۋvihhW1   q$@{   tfGTKkkqa)$f wo/>==Mpi@@ NG~H?V\V__ni r_\Z4u\ZX6}%׽` $0AM;=v    @| V!  RPPh"wbʚmnnQ $===n*dnI@@ o/}N=Oj_z7Ie1JEcl3֌T3pcccIDp7%dž޲Q    ėu>h   hii1:55ed[6V ,DN3䞚SyP@@G NZ?i) Qٔ7~W~SrSuzTZZ޶#ts!\Y.;ILLL]{d,Lŵ333oUMMMvv   1Ø잝   _ =Ѭc Yoì@ Ņg+u8]D@xXԜli՟ ۃ Y㒺b>>:D(gnK0i999qUEEcfBߩVWWo.Վ:f@@@@ psB@@GY ƦOAlmmʊwЇ}9| ###76}ttTo\7@@NWZw$"F.H}B2ܜ,.,1Er}]cuQtAwinn6Fs/<   <h  ˓JG.---9 _ 55Uۍ'''E\SH$`p{(c&&&DX@@ }si$^u(RsTr?Gr9c݇ rO !}wǹb&tFjdo%=4I|@@@B@@Z+̌3L}O\qqс@۽2w_C \ܮ}}}m4M?s<)  )qGj`ҹR"){u$= 3}'.G&s,_PP 555:f&ۉHw:k!   @p0G@@ 4qj)hiitWe޾,p[p{aa䞓ctvvVz*@@C %#Cj'dgը|%%蓒6 [M[XCX49Hn))ՃruulD    V"  lٕ5Нr?balllLt8s ~-===//8TH311g@_2jTg$/cr2GA qc仺:euA@+!{ @   Opɉ  ij@efzgC~ͰL@uuh&k{988y{F wLoo^uD:|\q0 ĥ@No?a/D ɯK޿c^.]/Cg/YYYlbzxxxXf@@@B@@|!j/rttdb:<0:9we7=ty^dttLW"L  %.srKcQ|Rln_X,S.Ao+}4fowVcd<2.pqq!}c/J3$L#   }qh$  @IDAT/vٮP`ѱ3! Y׃7ʂXfLOO^ehhHsAA@ɯ>*o@y9a52chT$}kQr%e2P7czS^^cn rrrXFrrql@@@x"  0;;qp+++cnځ!KA <ˠ.M͊HA@xX<66&KKKFCr囤duT%EIb rOIOϵdp7Ro86̕gqnnj^'ם3    a  O@z <55心kjߚ]RWHO` a@@0}uuyQQ<~Xr;Z 27U\vf+"'֢Q rȸ){3:WފQCBCqwd7"$Y>^233CZ@@@@ pAk@@@EE9Ck)^C8[@ n6QܵGuuuuwwW޽{'<]  @...dxxX֌}HOOh]-y/>%՟1Ml,SEg)H#ZE#=F*,zb/I]]; ctw    S _ y@@b(A=2HwW!\{"P n~+(d_޾}+  `!NRVV&]]]q棩<ߒRj7ΧOJd~g- oliÛ \ޓx&.zOČh{ill r    ?_y@@H@;Z#J@VV4_c.###]2#+hۏC?./GGGG@elmm[֑:;;=ۃ 7_/_< V/?)ܟ ۃcg!W`llLa/555RXXhbE7W1   > g'"  벸.( CIG3<@,ۃ9zU5؝  S.UUUjjiߓ{37Χ\g}sR,) r%{2k=t5wg {A^h7ow@@@@ pA[@@H )//w`8꘹ca g766QB lvhmm ^XAWuL  DF@;{N Y[[qb,hH̔O}R~%%3Y+)GݾSWfW`d~&o Ys^Jee}6˺    I   $frpW3e<22"KA YE5;{b}^@@Р7oވu#츗n{KZ>iѬe) r/_w{JAȁ32s~eYcxxCG4HWvQPP@@@@z@@Z@fihv?2N@}}96:f@<QFs+daa!(  w?@qa>땶/}7nѱ¯J~Vfgd!dp=s, OOOdgg{8,&>Nn{{۱B)++s1    ݟV#  &IMuzzA⨡LyÛ^:щJSp{Z}_MƌluyE@Y`~~3;*uuu7o wJѿM)ևѿŸS{hn+$g]0@ Icᖖ @@@3ğ@@@@  w^"0ijnQz*@<Dz{{%###Xu*ta@]-jffXX;6k{/c;TI'~L$5/7-d)Y;=% rvV{X8tD fDF@;NGƗ    Y   $@CC`"[[[ ~; rPORPa&<΂y^wvv͛7F`L  \ hwdmm.8)}}},EHfksXI[ߐ?euxAen A)$8kjucc nѣo5@@@@ pSB@@H.SX7 33!*V@{rƂT$jVG3    8'ιH@@febbBȘVv"#p{bdH9ɓ'O$Xuzxx(o޼:&@@Dk u #ridHɖ_9x?o[r25X/%#0,f7㐵cvDF@GY4S>@@@S<  q-6j)G3 âBHkVn V]_j!&@@L8RcIJW99rU&e2}wB\^3RS`llL@uO`qqQ4Kmmi@@@H0r8  E@eiiIvvvULSM4Ki{x $zp{SRR^E[pt $ vs "2|?/}NrExߗ| ,N){VŒuY[[sơ=c!f^_u8E   Nwߝ2  @bdffʣG h,w]E34RN Y_]]-===[5PG? oi@@Oz599)}jYoc ieR lr뺁3S+ό #NN{wL;h|    $}~9:@@Zx(1oaa!z~;d nӧO " 8>>nlDk    $9B@@Z ??_A}y3Agg9ZЖu$_;7e-l޽  mbF5=JNo#M=yDW@?;F^k^N|PRR".+#   pϹ  $@SSh3{@[DN@Tڌ jV4cA*Zvj_f$~fmhhB;69c!f@@@@ pO   O*~]KM@UUL3zt#-~nc]K/.  Q<[ZZU_@ai_Ԃ{n{a1TN;S"'Kx}OsvvvvĖ@@@@ pSD@@H2?{ч*# nd:~R3>;榼zJCK! 18887oWlYkjj۾YھY4G gtˏˮ~`/Q\;+%rj`nn9A@@@W?!  , cCCӥhJbW˓OJAAfpzfE5V@jpKVVuw=h!.k[B@&(rttʯNi`n__444 PLoiJ>j<2_(t1TWK^[ZZ-k#   k}}h<  )PXX(!'&&u_ ''Gڌ QOnГ'Os 3>Ox@@@?  -fdI,}ptŞAÞ!2L)))$?<./G@nؐW^yvDMKKCtǟ,+˒2iL{db+:RА1ڒT[[MJ}ĄqE| @@@R<4  1w^YsTf#_S#@pß+4sc$ m~4cddD4 &SSSֵC^^<}Tt$,JRRS%==]zzzA/*7]G[333"Jf""emyX@@@H*ܓts  S^4^~lдfJ22WvDXcs[fvwuyL^y@Hn#y,..zBTWW˓'O&υAa,,,ʊ kD&cA*ّ%:yjiiq1   -@{r@@_hеS.F/2̇/+ƊX O l>2Q4`Mkt   `v۳W[iiiVV0 =1֖ggnZZZ$ѣG)    @P   RUUhٙ֔ TTTHccql =>KU3)//V]j qJ @[B{ddD xQ;cg=ZzCCh}ǖLG    vL#  @\ p<`/\A"8dd \ =::T$nba:BuYV5WD_)  kYYYDvtAQƵӈjy{˳u&Jdw.[y@@@     wwnH>`\džOOO@,1؎4C'O$''ئ~dffFS @K@߼y#]]ǢQ u< :LOOPa/eee@@@@:ܯ@@Z@3lUTPYYil|hhH40;cg=h }}}R[[ۣ#yՙs*@@AWGCzz6Z;={L =ߧ2rszz*FGkDjmFGZXXpb)    Mߤ{   Dƌ`q{>lXGG3LkI  66'8?^ѣGV{y  O@߼y##KFFtuuIggh4ſǹϙfn)?D^@;xeׄ::@@@I_ln=@@kRpQGGG=E 2s'}tc/փkrLOimԪ[$%%hf`9991ާ@O@;NNNJ# UUUɋ/,I ;Et%ozoA{<*   $ u:9@@OjC`'LX3A2==' nOڡ t/((X__zO% ćޣzJ<-(Udm$u%Awt#tt뮱g}`qqq@ک@ݽ::d@@@    kͶiԔTDF qomnnNuy '---ffwމ@A@QWtA9>>6ؔ =vww9-aJGrf:QG@@@kp7@@@/eeeRSShn ap39556  B --ApFj`jЭhP(aN&X-^QQ!/^}*ܮA333|C@ )ziiI^z%{,Ϟ=:== quD3xddd8ꙉރLMMloo7~30@@@p a@@+5hDU"7((e{{[&&&UL(@p{PI~4W' y+N?@[kscG\&ST$A9͚A|yyxggTDF@k=@@@HTgA%Dž  I#P__/Ŏ=== rDO@;hhK.@p{V,@II<\jjjiii1>p211!%@P`wwW޾}ku=>>6P;zϥx Be{uRP6TΊvt2O@;靬v@@@@.Eu@@@=X]\\$3gP3www{Y[[9>Y+nO3+خsLJ244$FKD@ NyyyySinnI}r]O4]{qq Xeݛlooɂ   W_Z+   ha~zzjS9R+s{SSSt0D!/h deef *[[[k̴^P @ 5҉v*̮AܮA"%@::`UU5^*++E(    @$p"@@@hhh"G5])|٢5[ۓ?qˋ/Ƭ˗/evvVϯ]7@HD@ KKK‚8Ǭ9?n)"-@z?UfDW@;9vYu     >z  Ѐcs#;::$??q 3 vx322 +))lY}+++~@]@Ӵשz]+ݢ)@ץfff<~XtdJtԧyc]]]׎e,L    "    >+ɜI<gV 4@j LHY~h\>yyykNA@Q@3{3h6xYYY7>}j\W!@SU777ک]95ȝ=7$j@@@@{ ~/>VF@@? TTTHUUɚxhhH= @Z < ͓ܞ gٟX\\li'낂#~W 66f$@h ̌|R rq~(,H 3)..ܴv C 62d@@@ 4@Ժlmmfl|V>υx>;-A zN5ftCD@ Tgzz lSv萧O^!+}, w n Y;UG^3""zAn@@@@ GSm#  oh>`?==5ꩈfhEg6=@II]_222Y9]?׫~kkkz*"/jyyTWWG~l@@@A x @@H*}p)W}||,cccVvJ&&Gڡ1Nϋv6aYޣ֘6Lp{H,T YZZ <<;;4X[[zё( \'ppp 󲾾~cTE vn# w$lcQhtwvOF@σLVVǦ@@@ n`@@[@35fg e2蟇1h@cO54;t<,ІxЬ8USScel@jӑ4꬀wDHJ=+]n*^K^7M$ w lAeeګ{N|,T    @ p2@@@XԚ-^4_ 466Z5(^4A?t?gi`C 4kݣ#4FҸT"DM@ںqzmv>Cvbvޥx+]iau$b @@@@ B}   dcc 6z3.(Q~mii284XC3=?D!!٧RSSE[5~4`q4Sh"_QQ @b ubwwʲ/ 䮟uwr=B9;;FWb^( q.p~~.ܮ2ҼԑʴaУ^233ɓ'O뫽lMMi@@@@Apvv  ~hnnwɉ ؝q/vj0Uh稏 d[\/Xt/^HeeX讙5;@:77g}OMM^W_W4Sfsk@Ax wkpsmϺfpN`ttԸk{B@@@n B@@RRRKCy;b&]Y4U%4` e{.Y޳G(^E;,--Yk1@@@;#MOO[Ff{+**ٳg-F( UAi4kfsg쀚P f%=NO6B&k Ԡ5m8&`@8uǚ];戞 6>11an hgaY;9v-gO    '@@@ l /_ l{zz$%%%Xk4럞1Ǟ4f P J!ߵ5XGذ`o)YL#w7[I;&VUUIii)wgM& Y\\4[WW':2%F&}/b   (@{P,  *UA~eF:J4C{{Κ. rL#?"ѿGYBgu׀Kͽvy@ 7[^c-J{sa33ƒ}bS]/3vf]?oP   ĉ@e@f   ЌtF5 ZyyQOEt&''e~~+I Lcd}̔>! +(+% Z$55 @ =iO=:B U333}>*<{5zhgׯ±Zw     dpC@@@ >0 u2<<,ϟ?*<;ӧ)%Nٳgg@@@W.@@~Z}5k0Tj~ۻ5=c   @b h{JFLG.RQQf@@@[Ըm C@@|$PPP Fdyy٨"a=u@@@@hX:Aؽ(f n7T@@@@x =C@@TUUI}}^͞cS]Ly䉤\GA@@f ˋ؃CXQJKKɱ,3    pY   GIII@zЬ)ʒ4n}c@@@ Ye``@NOOmɑ.IIӷ@@@O}qh$  E@k:p'''VŅ_%ay0   *Іs3::*{{{ݦIoo;A@@@"@_D@@d}ewwWULGY>(#  W*15c^3S@@@@ 3G@@@ rssݍ\YYw5QA?y.(M"  E UfOAD)ذ{z葔G@@@|%@NE@@? Iss䉉 4ꩈ@0=I _읗Gnl @@@8(oG"=0ehhQee444T    ~H|[i/   '"hrzz<!*۷%O*%Sv$y޶/bM]fojj48T @Hkl_~YHBRXX(EEE`X8>>?{gN8eYŲ$ˎДa H%@ze=a-[Ò(;h&@$-[dIekɲ%ٲ?;3Wdɺ=GμܙXw._ oH^^,x[VD}FO;ydx33ljuӾTI;'0[~~mݺs/4   ħn5  đرΜ9qԹR+䞖 _qeg?x} lͦ4@RoĄ9Ξ=߬R+))q`:VD }Qb$=~{|'azrPYYEJ X{:_k{I{{{}׻vrx'y}ܽ{"|O]m6n    *r   *pAKG{TTn߭ϩLާiU=ݲe)(@CK <쾘z )..v~TRuU_@W@B~DvKΧ2Xz x_+rj F\t'@@@@D (W@@@PxiΝ㬯w[@ǂnw`vAw6"aQӡSSSڳL wSSSVF''NqSt1-333jWPbX"I:kZkkr->A޶av3   ĵ|<  ěÇMýMUUxK *xmN]4@`|UhIMNN.mnW @[,Z@-+$(ئAvnv j!ԾXAG ߨNm***L!Dݫ<cਪ*knn^7a/    @ p   @rH*xWZ^^^D?3 ,W}!۷o;zUl͖cX)bvW牉 SŶPཤ ,A`zz:fWܹsK؋9߭z:BKz#6B(033cv2MꦦE[Dݫxi>?={6bGܸe˖E]0   İ8  $ܜܹWOrH_Zp{xw^w6B$L eq'4*/eff;OX" ){ /Dw( ,U@4 2а]r_o# tA۶m0    %@=.''  "*y+{*tJTJT}WUNUMVEd]US!! 8) SSSK: ;Q (R(W@_._qoo GHOۺuG3   $D   ĕĄرvW'sv;v>iiiaz< Xmg:Awm\'p< KiVKdDP\>O>mΦ`^T]JJJT)ݡt_lWlڵn@@@@ PA@@x{{ƍn:_w\p ɻwﶹ9yUżM69A ,v׫*/߹<'~4~&0fW]ҩj0nvÀ%Q@k.v---VQQL}Xjkk!i@@@@ !'e@@@ СCW\aA |@Di-['V^B\o   q#@=n.  $z[2c=~۵ktת*kjj"tI!74h91{]~}yU`]у@i @2 پ}|c В=>::j{]5kX{{;>:@@@@ Y'˕<@@@ TiOjjj 1/v[aN;uz-//w*@M@A3gD5l"*+ԗGy_@KkNrss {AASXv]c 0x)ܮXjӱ4;۱clݾS+..^GC   $$؜*  ėd]]]зXEE;-b+Pɓ'ݮkaamڴɨ "ap쮠{x(ZӪ}ABA2`|Ae&n=(.mVi`:yyyV ssssN51߱͛7;| c#BTG H \@@@X5F#  P@Aƒz\yYYwkkݥuڳg?~ *Bx4@V+M!wo@~5BAAXvCa^ $ߟxT]"o%~i{'_˜ۺuk_cf@@@X)+%~@@@ePԝ;w {_-B{#G]Wڬ4 oxWݝv_ŞZȮ4@ (0p{@0=Uy2m!)۱cDw*# @@@@;@@@ oUx8ZU ?^f%~;x`xWhɪCL , 7L{KOO^WPOWh +#p12rkiixH!w}'Q;An^B@@@@ G@@xH?'bL{OOO`ȤҚMi W@dm ^3XwSQ!~Ri+s]+ p1A\mVWW,:-䞨1"   @| pQ#  @ *{+q[nuM"]SNݻ}JˋT ? /6m.w PʾۓCbM@z{{mttwh7|#QB(sN yf0b3    F   g8?'dEU;;;̙3nWU׫JC@@"{qꙙ=F~~oYv{]4ĉKޞ|'F    ܗ]   [ɓk.V-((-[bKp믁v1+ 5; @@O@Oij oڴ)n;y:5.}XEEy@@@@? p磀  ĩӪm K2MK- v!+777[eee @@@ \NX$/SVVf7nفx O    Sܟ` @@;mmmt,dz)୼u1fYq3  'pa <:Ox k)خ; @@@@`~@@yUwǞv#yǝ gx[II30!==ݻy@@H2 ݷo_`p fVR{ߣ'E@@@ G@@VƩ Ԛwp{Ԕrk[F  ${챓'ON8##6mde!xyZ2|N8G@@@o}8z@@@ $XO?c/w#>B]]]v ߊ [QQo   iz<'ܞbc1~1g ;SSSG@@@"@=    @ L+Xm---VQQ^y 5볡!)))n:2:@@@ 1T]Rkkk4ۮ]Lx᭠l5 Ga@@@X    /sssNŸ^VVB} ۷/pCU_~)NC@@v !iqMM\D^XOLLΝ;mvv6rrrl֭'t@@@@'@}q^  ļ?MA͛7Rpe5(A*5YZ[[t^D@@ fhÇQq6lODwf}rrҞ|IPrz!   ,^@@yq]dÛeǣ1gϞǏ;!s9YQQak׮~ٟWggMOO)//:::@@V@5UOޖnzJRgίF];v07Ulu7=Kz2S=\i@@@@ 6,A@@ |'x"r~~~z{ӞTuSB-bm签>;csss#`ǎ馛o~sD_ЌoGqUJ]w%/u:No~h}/}iۯĆɓ'}̴M6ߛс  +*7q5+_JZiVAUUUV]] 7448!󠝎٭ZTWWg_BAAGFF{b5mꪫn&*#   Q  @@@ 񽽽0` ַFὫBZw@*}ZtW\a&;w_;Cu]v3www~n{ի^ex;ĻoСCf)pBL?+,Xwz/bBgm7n [x6<<(SRRAA"TI  (A>=U Hpp){O ^ʮ'i`Ą'O~v~?iz @@@@ R 9K?D0  \k^QۑCCC n>ڇ?ak~[~o|۴ihݦ?+~#{Gu[=//^W8׭[geee6>>nP_!y=V~m۶mZ?hk׮ ꎙSU%0)V% _4  Ė=^EApE {PSuGn]{vÃ*V2{'O:/~W׽ً^"{ֳeӏ+X?cM4-oys7!   A;@@@`Tum֭Ӄ>hgL_ww[в5###<`v[ *ͅӧOڑ#G»/:p?lVT}wGL #1ggۈy;iW_}6`bC;vt^u?|[}}}Df4iO{|_dv'A};@@@H$8GN@@I?կ~ռUĿ,x~Pev] 5k?]Xccch:ڄ(??^؝w9o]*׾^|U£T+BBU)|'Lh   {OG|'Vg0{=gUU}M돌8kOӈM'>p{Ċk__(HŸCL    .@=??  BxyyoZjn%PgBU㚚B"xn!,h U~S8c}wI{衇Y^=e+//,1;v̷@@X=*ଁw 9997)zzz O3 +uooғG]lFg#VӠu7D@@@@ 'E@@@ ?h;w.+_e<@|Luu9w*VUUmqȑкnZ3᭬GӢ =~nnTI?~@@VR`hh456ol+yI+,鞷&j])Zy@G}C^o/fO]}աMΟ?osOh @@@@ '@@@ &T/%%%t,p i ny_߄S^! kЪZ>33_3L۸q_:Xɼ(v!{'mzzڻy@@ 7S=Jwh---2x >J5 [NU{x{[jzR[m؞Y}}Rwv    @B 'p2   @ W=ж}v'ЬTkhh I2 E۵*NLL8+|^׺[ЫuY)R̶nj.=Yvm!  uY{hȴf2:O@ëk`xvv ڵ+t/] ui7tSh~)]wG?2|_ʾ@@@H$D:;@@8JU4_L{_B?áJnT)njjʺ"z,{^#oW^ypvvֹv677[N  ,*h{~oͧG{={58^Rk_ 755ne@@@w>   * |_}{Gǒ/[ή&<@hzzֳBǎQ_+^Wܹs|'?I{M!k Cs-&''Ӈ  ({!U߿4x۶mP0u=M]\sw5@@@@I }n@@@!paԧ><<|3=.Ѧon=x޽<<^9o|c{mǻ}׽ΦC9rľ/;? p(|??OvS`9ڡCxɻRŚ%oKn2n׀fCX@@kǏfff|瑚j6l0 J-]ࡇ XUu/8n=便nW k`|MWWZCCC<3    '<;  ĥ??2>})؇?aKKK._lQSQ#PkmmzWWWmuUnwZT=yn|/~hxsk:栠wF[~m+)ʐ u8q"H欧WfD 3  $T}pp0uf\[򖅯5u_|dށnѣQ-[ޣ]lĎA@@@ pЁ  ,^W7 x}]ruk:U}QgGwK^L+X?_:4r6}vu>!]z׼nt4@)q=[ĄѠ   ,N@U58X߫ZUUVwlt$ -rhr{{VRR>4    2 ֖]!  P`\_uv=oN:B a?uwuPEݻw;Cq"++TUtzJ|mvv~ӟڟ??m˲RRRL[FTwR gǎFp@@P{,0ܮt{{577{oޘZ){nF{m333o̮5XpO_KC@@@4*_[#  @kkԩS600Vc]?_ _B;Cxnv.BwWZuuoh wvvڦM]k>m,U6;yqNp$ Y W(c۶m΀q›ƍ-###|1   &077gD<<<daa0;;NEf={0Oٳz衈Nu}t/6t3#!   qe   djA=88hs}k_3"N0Bν4B?{G} 7Pyo]vYGGEC֭sr,T?}_&{_uk:rA" 9 Ǐ;().._4  ^`rrҺ u~zӀ_ h`B_r{;i?Wm/{rtOmA ݧ8 @@@@VF uev^@@@\Pi'?iGՖuQ 47_:](|ojjj|sN;wo|xhwK_^x홎.PYYi Vuh`^H/Agzdž@AAAāEk:4۷QZZCtg'hO>m?^   $dp   pxD BU؅ .x;vwGnǡ?϶BwVUU9+**Bۨwwwrۼcb~NNmݺ u ,B>C@@ fffB<ʜKMcRxe}Kپ}{h3wPgnn= -_mfiiiM;;;{?veHk_C|3CL\>U ꪫH*===Tзc:@@XEUj?p4*tXzѶmLOŏܜ]rOݣ}p[[3lEoo#G?j?O".6344do#qÆ vW_lS#   I!@=).3'  (mЇ"MղΈ<9ϱЦB +q)M^EB?Ȉ)T0|v-ٳgCݯ{Li#̖-[>tmx ;sLr:@@݇hpAMOR=///h1}1*gx;8B=LOjii 7|s侁>Kwq}_z/~ {`'Npg><    @ ="?   pOnF{C??믿>Է USp6nM_~ݻwvc'$x[n뮻TOdz~S}9& o]N17: Y ; U]U۽I'd@C@@ 4WOTJetłߺ,{dYY>Xk׮-_l>Oۭjr6w=k^{ _Tr=ν#< ss A@@@X{_|N@@bC}{[x6Uvkp}P݉B|3KzU%/}Kë G_HrQ(_W[nnϬ* *AC@@ =VoPxu?>ʻ_/M^JJJW^yYfnXWWg7o~30]~Qg?&&&S_i    O >5   jDxעV*r]4}{ӛ޴_r/*$^ҕXYFSBoSxSNy1  @L LMMٓO>5^]]PLU;2kmm%@@@Hs-9@@@ @@8uprr2̲lÆ VZZР^@jj>:@@@@ ЗC@@KٳNӾζ-#~TSU]f'@ @@ UzrUUU*iiiQaA ;wcmi&.b@@@@ '@@@xPe޽vQߡ+̢J%%%etķԔSs||22bA 8-@@ Nfffl߾}666xXWWg+ ]]]׮]k7n@@@@K ~Ʉ@@@`FGG >{MMMT$w*tرQjjjBt" -}}}vUnUm \Ng| >|عAg!   $=   gSGo+))6KOO.b>=ϝ;x6 ;}tdddXSS.3z6=òG@@@HbI|9u@@@ TQռ>;cEEo!0;;kCE=B'W  (̬Gz +ܮ;-1N8Tn׀eo[f$&/     Tp3   öo>Sjjjx%{*:k:Uv! \>;x ~_בZ ttܷЉ    G*Q@@@K'Oڞ={Jqy.5AU}nn.pP]]muuu  #d UUU9ҢB \[---nݺ8?K@@@@`%.F@@XQ)4z[^^mڴɨIi'p{}}UVVZjjjX  4}w2}7֊BhrWW8qw6nEEEet     .@=\i@@@PBUPȽл>;uT3`ʢ@@ [X|[fMUO pI:f<@@@@ @@@ .\`a߱ƍܷ8zz<455YAAApF  eT]߽5 6u` i_c@.055Tl?zhԝdddX]]O* 4AO:w$|@@@@Ƕ   q!088tVպkkkї044dG=r[~eggG]  @" HnH.\<q?Cg h޽{MߥҚM    *@R@@@ .T;0n:۰a;-n?pA-  0/ ɨά |ZF    K 5A@@KӧOݻٳ/,,v-#*eddX}}:%))я $6==L悂 q4BUY񶴴4kkkR"@@@@$   &p9'>11;l۴iёN~kㄼ֬Ym@@Xw+++sVN{e     p߇    (p*---v)H>@@@@ \@@@ .T{޽0Z{{镖333N Lah0|%@wagP|t9'Ouj @@@@ @@@ &&&lݦ@)lE'Ԕ ѣGyZZUUU9ą@XIY'~С{:O-*((pxMR'N8v 6ZYYw    ae   &p*+TrÆ TIq7 Ҡ*FC@]@d=u6_lkll$W v'߿>//xU    +%@}d/   @ (ܡ* xhR ^s*OOOGHIIr%U  pgϞuB E]zz[eei@-=+M=H!$焳G@@@VCj   1-p) yTWW9ppG@2<8oTMYYtg6   055  (r]]O$rQѣV!ZZZN@@@XM{#  ĬA6nhAK2YvfΝKJJ{qq@&p#GD[OKKs9,L wiqaa^EC@@@@`<   έ ަ2;8 z@C4@@`!zҐǎwu T]UU&''4@"MO!    WSF@@ @Q $;Ae A:wshDL^^)++#L 'NpWm{tCCS'QH@@@@1r!8 @@@.S`$UWW"TҡOXtWELXUUi -077<-СCQɮ@aa+]^~Ӏ oSL#    (@= DŽ    #AM4 ZLNEVUufN]i  Xz2Аܹs\IIl/**w=&̌DLj--- Lޏg   ąL$   @ ޽{CT0yÆ V^^[F :[*l륤n7   "kA%OKdUl JǭΞ=[E%ҁ    @ p   ğ$ (P***04 bClxxTuA η@@ Ek $y*P4%%A0@}~-///p9    ĚX"   @\ (Tr;x`+F$PpUpU5W\5k{AAA.F@rBȣN 9!HZVVVGЀ =Qɓ"֭fcm     1*@=F/     q{JMMMVYY]<>UqW5wUx z 󵬬P]O!)Q)g*N@@@@8 'D@@OO+oXCCUWWi,TرcNb9r…@@`6<<H@V_`srrLvK#wءCO';;xN    &@=Ѯ(  m$Zpk ,l3?N&BWGmlǀd?]岑riy D> D5?# On rZ @@@Jo޼Z=:ͥׯ_@#@ @ 0 @J!xgffҫWRToC@Uv(Q@2Z9~>}f'ƕ4 @ @$ Mm_  @ @GGG鯿JQűZˋ/r2- ' @@Z־KZ>Xv^ @"ǏF*xZ{Tk L NOMz˗/]y @ @. G'@ @ DUݫ,侰Pme.JUX{GGG>.$@ ]k橶wWSқ7oa՗24==]u @ @# @X">Wk333Yfxxj܉nkJak }+W*ңGRT nM6wޥo߾jzY  @ @O@ݑ@ @:@ `wgս ͋/rBw!'aDݍQ4l "ppp}ODP{\&Bq8Ox EÈ8;/_|ť WB)d @ @[s, @ PZ Gʨ^g!j-#P˰nc{vv6 Ge @@'''i{{;mmmt||GFF.C ?OG-7oR+ıի%4 @ @/ ~S[$@ @kkkYUʨNYEDU@"|WvJʹE8-Ew hWvk椢e}ll {Dqǻwҷojnuu5={,c @ @' {~M @J-;~Dpɓ'j I2^* SSS^w qU^@{8'5tnn.gf/~GȽZ~:@5 @ @W@F @J)T+311zT^-v{TwíXV=" Dx=G}kk+ GȽ<WE ~/y e0$@ @ f;I @np{#^Eٳ400Pe +p||Uv7#~5'~Aa#*ggguzW_8;;ۅګ;YZ\8|>j.^JΣ @ @t{gΫ"@ @- 3b,,侼u5 /Պwvv.Ý85055fff*"O\~E[nLTio|E=>5e8)N˗/bՖ @ @ pw l @ @QÇYUZJ/^HB,/@Ts޾ V*W6g~S%FO"@ qZ^=kvKʼn;gZGW#Pfx?{.܍} @ @ @n  @ @@7o^*\F%k@'f, nI WF:[i>|[Q" wyJEZ^J=r @ @I@  @(EZ__O?~LբeTtWe8>>V ]{T| Њ@\i%GEzըm?W?"$SZ[[[iee% @ @ @+ @ @R DUϟa@IDAT?/_ӓӧOnU" ;@ (okeҙ499[ٌ WU?w*JКm9W\P{|6 B 3O5Nϓ @ @?W%@ @8::J߿O߿QٳgY=bj:Y`2t8ǯݜ(Ҋ(@q"[|δh<4*ÇYk8˗)N6 @ @({Ĉ @ @@)"x۴]sŋi~~f+t@VuŃF{hhZ=©L#@3NNN坋z\"qHN4kK&'{.{Oz\ XN @ @@ 0 @ @,"`a"&\VxǭTajUoVzITe1 f'DRdUnt Q:q@7 BV̮. @ @ $ ^0 @ PV쮯?F[eGFFju@G ] Gȵ-cccׂ{;tm@s'}E  q_:[ ~soϵ;W0XYYINd @ @ oN @V {?N_|IU#ӧ)*QkY 3B^zWݹ8nWw` q%DfxoO>8qV[XXHϟ?OCCCXN @ @@A :1E @,pxx>|^s7l#55O * F5v<>>~ttm"HwGv|o C6:E k`qe/_fNwA @ @ܻm/ @GJ޽{Uŋi~~V t@k{jUa^}bb"{,X]W&###)kh{jՇEׯ_o.b9 @ @%p/D& @(?jPONNf]< >E6‚~yL===x `)8rUC73x:{f%еq2WTlܬiWϟ?Oj*YA @ @\/%@ @JkkkӧO)*jsssYEn М@"6tKFkZ kzq^:$ I"y4(ߏ?W+JZ]]uH @ @({Yf8  @ @@D6B_|XrzY=N ¼y=w"tdqj<ٯޟK|~Q=OLLd'|AM2+4$'oX=Um @ @p9G @ @B|}ب9G}iiIܚJVhM a>[GJy}rP׈pk{LPK$_ Ҳ@kqM }_MOO/_fZ},'@ @ @C{@ @J-PTһwvlj@qvKy5FZo#XyQ^=N¸V~^]q>gku@߂Vdr @ @:H@&Ӯ @ @2 #Ydn{p E=B-ѧ>ѯ'ED%Vnlj= E ͚ٞ_{& @ @:N@ @ @ Dvmm-}1 Kړŋn> pͫ_σ7^j=7o%J%NϟS{{{4\c!еqu^ ~}Izvtb  @ @Y@g߾ @ @ DpӧO˗/5OQ3>EQ#@|8eiS+ _qBHyDj|Y(@|'2ֻǏ  @ @) ޝn  @ @@)"Qshr +AǛ BwY؜կG5hv P kswE4>>^Q @ @) ^ @hHRoߦ#VVV5 PJttttYQ%X{x\jq"RjX'&av')=v gs\'nVɂ=r @ @L@& @ @2 #{. ڏGGGku”7RӫՐzp>?T q˳gϲF#@ @ @@. K'@ @J!#0Ǻ@cgj/ž$ϙFW5՛ Gu ^}/O<~F @ @7EM @B */_Z̤Ozݬ#@hR`oo/}9}3㤙*;uZI @ @@w w{ @ Pz׬bhT&''ln @"PTҧOfݞQ=*MTV @ @   @ @@G\\\dC~}˂sssn_+  @WV}kk߅UEj{To @ @ Ш{R @ @{T{TFFFjzq: @@ 﫟?fo}5<}47e] @p5͉ @ @ 𯀀 @ @].pvv{T2LTn @ #>^wL}}}iyy9=y$ k% @ @- nQ#@ @J/p~~}dtJ @C dk677a`` Gn_+  @ @ pWw%k @ @@...FS߯?cccY}nn.k% @>`_PZYYI)k @ @xH @ @@)",^Tydd$Ǐ޺}$@[v @ @- ~^ @(@T@TB}IZXXHg'@/pvv]yqO @ @ PG@U @ @ZQ=d{zz\ZZZJuZIhV`ww7}5}-EȽ^LO>MYG @ @pP~/N @]`oo/}9}]ɂJ PG ־⤻Ll @ @xp @ @:A0 GՋU⢪u$@ 4S=WW71 @ @ - ^18 @ @l˗/)'''_U[t @]-l㴲FGG @ @ PNrΛQ @ @8??O?~Hi{{Ѫ~+ @U0n*+;K @ @@g w| @ @Y۷op~ EjKKKibb(a @ @-d @ @@7n'&fMG}%@ @ =3 @( C!@ Z{I @ @J! ^i2H @ @SZU[:~ @K۷o)B5o @ @Np? @ @@iTu/8+Z{]+  @ @ pM@? @ @/ρ @vE @ @ @ܻm/ @ P*ׯ_cIKKKiaa! _ @ @ @>s{L @P@UN! @@W Umg  @ @C;ĵi @ @]裡讪]&h\j틋irrғ @ @]$ EmW  @ @Pս @@yTk/\) @ @p/ߜ1 @ @?Tusssidd?۳.p||~}*UM?NW @ @uXE @(@Ucdz{&x  @NP{۷zzN @ @ 𯀀 @ @:J gfOOOڷEU6 @@' ʹvvv5b҉ @ @ 7Ĥ @ @Tu{vF:U BQ=BJTa*  @ @ а{T: @ @/Uݿ~ޡ˰xӑU2Ծ0499t$@ @ @sҋ @ QYڨTk _'&&: @@g ĉ^ywv`` =z(ϧsu$@ @ @ܛқ @ БJ%ÆqhhZ]a:  @"Ȟ#hP\jjoN? @ @oz: @ @vww/ eprrRa9  @][.`P{g @ @ И{cNz @ @R nlld!faw<<|v @ @# ^0 @ @@i. 2Paކ#HWCGGG D}~~>hy: @ @ @ ߯W#@ @t@ݣrn*JaGeAÙat$@@w D}{{aPxӑ @ @N@2 @ @/QawvvoN?t@jȾWNNNPXӑ @ @! ^y0  @ @@ ]ݣnZ=tyV=B훛P{糫D]#@ @ @ w @ P˰_wOOOHmrrRut$@@JnPro_GFF}~ @ @ PpO @ @:M Q7*6v>55uxpc5(~ں 558)><] @ @({&p  @ @*pzzzv dapxT.EB U:-Z\vjoEs @ @ P^Ν @ @:V y82[EdK II)Gs{ppkZA @ @- k @ @!Ю#5h\,moo_tō+ @ @ @5k @ @(a|+m||Z཯x:VĝXJ<'탃ls @ @ @@SMqL @ V:Ν{x  В@\booZ=WNQ]#@ @ @- ~^ @ @Tpں zWYm@ NTdJ%&"Ȟ @ @xhO @ P*+mooӶ?*'e6B@9Ue`{,kGMiff& gϘv @ @S@E @ UY^+Օ{~?::*UGT+D\JDGTd?;>>?" @ @ @" yv @ @Bmٗ Bmw"azׂfq2L[tm @ @[@Ž @ @@W DUJk< |ZTfPe>B+}Wg#ގ6440{, @ @ @@wL @ @ D6Q]AkAGtVLh>WnVfբ {r600Ю @ @({!Š @ @UjXޮj vJ/B[NFN0\  @ @ @fܛӟ @ @= D U*^vzzDжZ=_ztm=T+ybIDn @ @  @ @@I"{v|||{!<^N_ 4#pvv؏D=P]$ru|~Z=JU$  @ @ @  $@ @ Pf GZz#>44T5w_C:] ֯z~rrro {A#@ @ @poKo @ @*{{{UoG8>q5E]_ G~!jW.MN#@ @ @~_@ m @ @@i"@ݯ |TWDzS9薁8٢[~\ާ0] 9^ @ @U@[g~ @ @h@Z䤁}< N] FWE(Iu 2ǁ @ @ @Z  @ @t@ޯ>0|ޢ{wwn}*1y@=E<^>N#@ @ @- ^1: @ @Q\#Ш@P-/4 @ @ @?'@ @ Pjo[򇆆0{~!}5 @ @ @s;wn @ @H?;; F D輿?e[oo Ζ  @ @ @R j  @ @V[yͲ='Rh @ @ @vC6 @ @h_+ _^Q]#@ @ @ڗwc 6bo E Pj@ @5 |~{+{Ƶ?_W^?XO=Jo M_ l?|VoܴQp \` 'vUk76wj"xeupͽϺ~MMW FX5d˯/"B.wYlho,j_)ٺ[n#Ehz~<5X;'ˊ^g6O\ 4R M,\^Whj9_{m%[(' G( _dG|fDdӮo;eh=qM38lEu#E>Zxuf4B M.\̞Mb]:Hճxq<F{7TG1Vdyz見&Yj(zb]@|#(oVCk eZUC3.Be#ENBkE;t9P " zPCwUf3J?֞pfzw -(@cq58w՛6<[1t[ Y5|<ʳxo/PʣXF5`AC6]sb^k 0n;8QU3P#ʚPLᙷ Ë}5޶~{] A+ʼnA J~_M2~Gd F8' YCzj@KXC7t!j=mlATYZc UatA^ڻ8pB{7iZ 3uh;,(h*;_ƪ3huq W*loV{]?o \qU.> k+/d l\78}H5ݯ[Pj*.Fj_9҄҃bRu e:Bߔ]_xM>$5=Y"o5f?*m7׹%RCYk{(V: wxaUg@ @5 Pj@ @5 Pj@ @5 Pj@ @5 Pj@ @5 Pj@ @5 Pj@ @5 Pj@ @5 Pj>{jbo"P0\uCap3@ 3 jH0 ?!U+@ )+LP5$Fo5D*av@ ɐX4 jH40ͭA LyۀOL o&~L&& ! im-pjļP0m@ 1lMh !8o>j,v@lvH1pfE0k 5f[` 5abxϜŷd,!n 95xe11]P?e]P/%vx@ ~&{ގ`>|=B.g a6@ x`a@ <a@ x pa@ x AiFA@>!С@j`7XPUL 0jj 7L c%-܎$X50SBS@F10l +Â4Pm51s1 e5%FNa7A`UwWWNp>۫uo:_'ߥ-ay  \[ψy̽Z驷5||dr}Bo5lk{Zp>_jux 5$@pPv/lO;cUB(j 6:GϏa&_vWe!=? 5no湯;3Z:aZ Cv7/'ot1Ԑ PAߞ԰SރWm{/U!¾:-NW͓ϾwvЛ$@PǶ7,P ?\Bt& 1rn< j Gޜ>Myb,F )'  C<+35d7 @QjőHd2SC~Ξ*ŒG5?jHorz9g)i; ;;}XPx`twCحlp3ՒgzD$ X_>?850{$eep qj`I.)fGnHƬƎ1;pC*@ $0+p( bG^ o Piu,zE@[ jbcKKp4 Y8<ƾ53PJ pÀZ pԀ]TRM~D.Y%E|,+3STpCt.fhnPJ pä:XK-5\> PC2Ц955`eɖ54X u . j]3Dt.M5hw@{_ A A训37 *pbO/# K7l5<= 0( j0z& jA=5o !ǺRjURpFW= 7LAdB #فhr!uu/%> zVdj`taCliXQ 5wQ xod\B jpR30 SbZJ pC@ .SG7B{MSܐ2Wdjp))xeEI5 t58u13X 1ۭN7$ Ԡ95ߨ7jA$ ܠ5bjp6Èݐ elzAzp?+IJՠ+%)`8ܐr7h|n?EOՠXɉ!p甪nH% jvC^1b>iE7$ɂftCb:\r5 h5%MG  AYFԠ?5``jpN/zRHE7bՠʦhAIAPWJX{ƾM'PK4o~nHAoQ3aY:-$jhEVo(]3H011䛬+jbj`]@ lA{(Rk.Bՠ7 jfS%-ޗB_Zpcj`&fd 6^gjajКO ]7LZ B nЙ D50% jhEtk>쎪@I TG34Cs@ nJ L%AkհۋS)ՠ Y8i=qpÌPW{(TXf27<X=~FO885|'٪t )45T s4^iT<ũAgL6# Y NY68#yM NAG <N,M :󰫡>737c%E,K -Λ4[wL@ڐ2sVkgQk܎?}ڧV|ͦ}35 m˼>GØCGbh#:iE!$3V QC-B.re7O*f9l# WȲ FLՠPQ0l5&U%H7ŠARŰ@A]O& 5N(bV{a] 2g5(0hsk'f| 6dj0J_Q(X6'iC0fz 5i=zOCgM7[z&҆d\gh?ic'Z{c5i 0W5(S(O `9ӊBbjpv'|l ҆)T5h\*"Hp1bƒ$i! 3UCzx[tG0l\gh#'f\N\coA P5pcy{鸡#(ejQOx1{*bM9rPQiȘT n3qkMk{|_܀!Mf% K (T H0S533ZzV5mǛH5 mH5` }lM21uwxH$sTCz cn迁"Itw5g9@?~K(dj0i'8j*M솈0 T))% ldK 5~Ābjps`~F~*+ < B+Ftfd 2G5RK cw<& )mK>7t_H٩=xц"T_J"=ftz):Ta E,P FTrM~T175xO=LAk쾇K=% Z! :csCT$\F4hXX5hnDE Sw k&hڠ2.7t_H XB?AUϚ}f=% >fu`E>jpdYjp'Fi8#Rz%$ farC*ĘܦH iÕx8(jS`J0ި+R륐`Fb i1+5xjvehiûV~0({Η%Nt߸rzS2ܦH#i`ZhV 6p~#V3߲xo= l7x붫߹nj P\̧ߣl8X]GWNeiC ~=a`4I6m8X𑲢88x|wVf|mY۫+ĄB ߐw2mK0z!/+͏j8?xnpLPgɳ 58>-fpQ3 wx&C:ؠ(Z῜ͅp">{wvrzuG`U/lĢ`ԂQϣHKU?X6犂#S>np@s"1(&r5* K&r6^Oxi@sLcP^YtPCV5Dd惇ۍaح&&%1zRTw,E=:C Մ_/OlL(znom-c2nyVr5dq'xk/\tƔhҫ'FZYލ/WX jpABEXU+(POTՆd٘P@ $)F,P-Z! 58  Ekw5d/Nknx åUP-Pf5p?E 'X IDAT60^ڀ?,C 'h U9Sy/ 5'A҄ݡ:ICs)m[ڬ?c15\O,=քe"eп{iǠi Mbh0xTCy(8ԠԐ.j`^7+D @qkU;5p P%Pä뉱dH1$ hmAT5 [HmH -3jH.mK&K/ɴf Nj%钔5 {K7\* (9Y?L ʤ!r5$4DV05j![H)'dOLJ i`І z13A.n{zQjhX=b.c _9IHD OluCSwI5\۝7$P6" S#OÅ祆q^?h5ںyZDL5h#ύh' 5y[/}kG"i=55 5GpBT0TC֫Wߛ+CPp$EZIfrjpIᇷ2v5;_<[}]7sQ054$VO0| 2հu'^꠫r j'oI`χq?e߳Èot\Dſj(jR #^jhHN 3A bB[cjHjڅ $jx(B Ù`T=15 +Oa83wwKv]g}A Pv5j8W5PjB-vX k`YODU $6 R!Zڰ05P f 6% SRP,Crjrй?3k`cj0'(11fԠ6LO !3_HjS挭zY4e kxkdp=!2NYf\A TC~% K =jh6hY!P@VOLQ \ÌpIj̐-9R2@ )z r` 5TqzbBjh2BZjЇ5 a=4$wK]Ot%йj`:xS*BA~4Ԑ0]#I5h,\aP:tz 5X5?A.1Hǡ :²5/j2RSq;~L SOj<$K\FuÈ\~ƧB. 0@2QWE-2;vh޳t5ڱw o0_?hAfrI!(POZ)^54 c;Ta(!=zM v^YzaXc3? LzX` П5}h@$rd!$PW5X>|~ gwÇ*ȩrH^ Dp#1zBFn oM-䠹tE5aj;8Pc4aTc-IP kfk'fJ%j`I)cA Ǹ9UXlG쫡F z eVj1'.n~Q=8i5 u}t\{5빐juaN8pɥc3kN#+mj չKBrthi84SAa_ bnj~Yl[ <4S|gj.PCӇ3Սk;pRsRjLו7|juݛD"q? KvZSHI͐G/{:ue055nJ#Tj{!od7ņBFbNSLˏ~կuԀgOW;RFOP٦x}(`-HafMGVå O}M*̏>ug 38315d>xv(p@4N!B>M#^IUB?q! WNoC:|9?<_=<Kr<nt3\͐~wt!9pƽϞxVk޶>;W$5_@:y&,w WC5YP՞w$ᒃNڟ ?1.ZZCUdIܸwtvw=Zu; 2-5:8ȿ%-~'!zs|/pCnfR BYO=@! (->sˉz8==s#[ꉡLW뗾B)d(%bd)Nlb6`m1:cp}3TYY·Zc [ PJ0%5T<ngxs5䛊!E'g(֗\g,zlry"SZn0]`)XpfpZ,ڿ->[{| ]*k"*E3)/m 6r``BXlA֝V޳&وU5Zw^}8 ц2)ſA`6x[QOZbfh%8`q~ 3n77Ʉ` Kr` @KwLJA}Se&L`\ՠtCn}vPVZ4Ø}&`< 8Z ;  7!-q,3\ 5qN``j zL~b! EFۛ5cjpvG[6fPICPfc?ҕߊ Ukx+yfPb:gj?1i6d&jcjP(fм/SL|Ag4yon+U f@YkF ~#Khk<' ubBAݛt fldb6C3s5p|$_w[x H2o5|$P۔ bPotj`ejѐC0 g- N3UVmn01(4gj`P5.qmUdW6pQyHŀ!I $Y4c)jq̈"_mf@ϥ!̀!QCh7D,*qN zf5:;>8B91V3h}"0'OtCt\ _,F F.qhF3ő8`_,H ޾RsC,!1A|5xuC8MNb@99rb!c訷=GnPTĐPNfIjX"\PNDgQj{|]bD,L ^Rps3۫uo:Rwٮ, !UFBp{URÇW?8jHI{J5쯎ߙ2L԰+a"8cB ۛ/EAtB;m_>(.԰Sb>xŻۡ~t6.WB7O/ardwn웳7h'fW\Qn{'@@ $V7j-7V rPÕyk>9\)P8:[ 6ͽdgcOdyIK@ pTHr59_ΞɃ4~q:AQKg({ŕ'O7?~8 5Q2g$bdo_&޸-@ @arTHno>غMՐQn3ϓXj;՝U=V{(ʫ"[dR8Ϝ(*yC:E{}7Tw^(kUQI|~{Pjgbo (PPj@ @5 Pj@ @5 Pj@ @5 Pj@ @5 Pj@ @5 Pj@ @5 Pj@ @5 Pj@ @5 Pj@ @5 Pj@ @5 Pj@ @5 Pj@ @5 Pj2 oIENDB`performance/man/figures/logo.png0000644000176200001440000004222714257537777016477 0ustar liggesusersPNG  IHDR4~sRGBgAMA a pHYsodD,IDATx^`U׆lKOH{OR(Y`QbCŎQQAzQAPB wH $lϹ33I`Svʝ{mb#UC-hmr7ypV,~ޟaewd!{u;r]=#@7،% ZaDѻ FWyP#@`^8jȫ\BV1Fm0ʃ4K{V|a8%UీN؆EP|IkM ֯!b"@[BY3yK EK7^hΈ/o@x(T"{.E}L* #U$0о"z[.YZMXNl{@`E 1NH5J,d~s1*]r{r[ pE](B3ޤēm6c]ƹ]B5@#L°շ`Am td׿.Egq偕==OZ*kk4־˫nn+1$ZG$;&[2.n/oTx߆\ {_O U\i1gʫnynn7u`h/lD㢶hqI 53})QQ[l[[^;nR$P! aXMR@*9u9Z%hYj֧;cwb--+XPR=͹ZEj:HYtoZQ| F TBtux s877RrǽU`kǧ'@ {w^PJpdC R% KѲqI6c{b6c:?1gwS+i.߈~A/Bg\-uJtyU` t AJh}E%VoӽrC-?ѫ5r-@aHSoz |Z3 Z^a^VzЄyk8i r)3=HN:݄`+Z ~{cIO b]U#}`0sl 9j\r#v 0 {z0d8RM#bsaӪ{z-1`V{Qn3[`ҖAf,O}=U9ѕ"T̞!9XJZ۳jlMc+$C{f!+H33wȫ4e`/&`n"r A3-y 퉰KJYzQmm1:Q^]&)ӏf̠\Dgi3:ʫ BlL0Mg {H^U(Oh+&{ 4~[ 9_"KVd`(tXVB.1?ÿWԓچyMm^!%16?XeZzw݀ {A7)wtLI]Bӿkj+anyz[ ΂*' IY)Kml'D'ɫo7U1_[ >衝e$oEoÍkßFXQ #HhU4P T~`z# qk.KbI'J $:oN5;.|^6ve ^R䥹KtDp=f^:u#yKSC31H)ѝs? H#!4Wv?@!M ܊ŋݖ58tyh"ك:X[*&=Gu3Yw$W:cx2mi>n2X`,:<6Xp;~l3#E~FV^aJkJR}۱;w"x%t$]76#=$V)m>G/wE8Vl?QS^]┊ca hls(ĪM8)^uMaZPX(NjgBH<,񆞣'M%F |O==Ge׌܃[=H fD.h3"ݾ\B4П9"~!oaJDt^۰MV Gk{3R@+ѬAzhFo3F4*.aqK^kIc?U`<My"I02yn&$B?gi0y2,[wB1yUGIx=Uu6&Ӊ?7)V!l&3 X`W#{gZSX!Iҏ *4>ntƲ+vEPcCb IJh?.°IXh++U&su,{f2BUn.\mcԡ!^hviH7fsP%X@:hP+sM۴MRw&e FӺ*=xMꂡ{Nq)m)09BJdec3:}cnmqER5 (fP޶;FW r_-?HEY3 F2-*S 4#/wE,xe k@kVPƊ+~6= mǃKG䎠X85)Ul6rlF АeɆ{*o-7V #*gn_p*@Y?a?V<޲X0,hSj=~`͊@Xp .;ߵpDls ߌ+>|݂;3LVR̩b[ĺy( 6{KlWũNGF o?Lt=A݃c5n. W=˵#8 ^rÏ[ zPԿ7t,^x%dl5 gX2jNr WXL'ߌiv8kJ"Yiq)\\$-]^=|^}zg1olއS8Mw=͜A^E|\][;ݓgWyX>ok+J87ݏeƢokS*~5ar͇"_޴H4'9>F + @o]h5Z\7`W~sdڲ n|h \WpwX_i{ h G-7ߟ~88~ěa፥ }jCGs p ̽[Sw[S0B[=e7f'އQ^t~8 D|y]( kSUC፳bYn Z>Z/ >)Wrܿ8_cb$܉$LÛgf bZgP?x#h:akg>ONvXM`B{Ŀ!b=.2ObOj~|OV]*tD5bXwm \!W5鸸FU,FQwwƛG1t&f6x]lKNɫ|؟q@OEb`<h]d61A%!R̻Z/-F@WnZIy ._;Z k0ѻkWW j֤sKk:=_m^ߋQp!&U#ofb1_u؇)) ߏ,VȀS$U,ޘv4-ɦHȹL拺:8塒6BOOM? ƢajZPJs;l^tb9r@ `Qi|p=i0ܰ#bF4a $3Yԉi8}AH ]F(w|)5Etx\7bIHb#ٍ?"Ks0$:tU۝mZsΎ M8q\֤\A\ȾD@sts&&x,!R%af]1}'5G|e|O(Ysx}$_\A*f!^ȎV焅עRvYXX,L݋'{,k?o ~A}?^+?VYXO%c^<( =[󿔉H\w}[N5&+m_ݧR2Xsm0,[͇m'@_c"7-t++ո 9C 2큺Ħ#OK;Q$n.6R2Ç+f6KȹdV_GN1iT1t?Ĝi{ V[ _}c6VloZd;F$|_l/ RO UGS IT Ù fxϠJ}ųdX\o\ʈN{= P!>SN*yP )|S䦩y3ǔ M:'@s.ЃegTJR$;4ۙyս~{9OV0>N&Yi;U "ƞ|,z2Z|Kf9Я]~,{:1mL.3tA7>D޹qMGX %.uL7@:_\kj7ɿaFuI?*f) ОlI C¯ Ee{FSaq[yӘ&p;/;vÖ8W9OpJ޽=ИXcWr%^b[œ#Np>11S M>ƺ Y8tp 0;A,O/;'j #)P*LGѱ[*z+ U\PnP']V>A>Q an-Ru#|s1>7LyEG\.r3y3=b}x-A_Cp4#U.ޙG:3tԎj$r SDBɫ_]-Z*\}8q8 S:'o++3Lq(lm8Gm;Wc8otVuk3G~W>Gg'zXR%pa8w5h,/q[(#Dɞ('xE[pŴݱjzda9ſ7tOSDpd9nI!G+id݁͒)K(==K6~J i݂#|?\m(/<)hf`cv/TI5I:+Z҆'eu Շ:t 'K=U8-).DkV`@EQܺ(%4Zև'D\<}_./+ }%q#a;kIDhϰHm: )2H wWo{Qdյuؖ"EЏ՘(6>'G X^j. (xkft\5QRGԳUh[28+ R12} ~kpGVч]`K|h`_B[RԠJ'kwohU|e-&l*~*¨9>;\G|Xd 6qs~-_3ۧ ⒀+g^&,]Og5}G$vRKh qs\bMgbt!h\O Ŧ6>i`]w ~7 W4AM?.Dβ|;bom!y!FDKy܂Rǧ0SbM;O T3T&g7RVx`BБ^=P}+H9ǹ_}ҀF}:a}I;,v-蛗T<22BU%aO==*tFӲUXtO:"a|[ j'Jd3\֌Md~l0݅~!=*ߕ⪃ 8(t n _/_ L`QŽo-8*vDpsJAqO3.YqcH́7t=k*Ώ)|n!v@?n&?D;gu+ُ;@(׎*q[}5*M(\9 -9\۝f߿p`!|5K{uQ h6Yu|} C,,:-Ub9()}#DtSc+߭ᣈ׋X 6 :Ap{aj'Em^N:c󵔆(t^!뿈v)|CuCU9Cd( s3As>S/՞CNJĂp~Aqqq_!¯_5zOtTXzެ5SpY7 *h2fzi\4mr}L(Y'q0ȓNWۣ?Z&3s{B燇^#W-ԩSѦM,[ O=]+ewRU*yl6GXr%$ j*4*t.BQXrՋ톈:VTPU賵HMMu\g2Lg[^|6oތ~& K,ÇQR%|y Kx5!ӥKL8ժUdz>gϊfMZ/}! ;.ι<?233 wU+Q-,do/o`Ge˖j`ܹR˯VAm<|}}1}t$$$bp]w{!uu|]:g_]r Eu 0mD4+-" . [;0r>P¾Īy K/AcϞUEXc"EnNN"##ER ԩθv1Q<< ;v,ۇW_ޜvZ!~e;\-"@+D_v~y)/_ m?݀s痤N(}v w}b9?4lPD۶mCݺuk.Q >\C"ݚ!og8p%x(y1}{=IBBٖ[4:#@'PG% ooo|"dzHߟ|28e{VZAgmQ|#p ZpP ?iSihEa_8pԿ:yI6i$?~\vQ8||'رcĐ~NU7x"]&_..\ݻwk|JV"/dΝ6l>s揤5c<t?+2:uc9rŲTO 0|f͚cǎ"apQAOQ1#:8 LGyD^[dRh!%6Q`811Ǐ?b1B\`jBiiiXƱ5)GJc8TW@2D~+i$g wS ?ӦMٳE~~~ӧu&GV7'n47Ø?rX"yw %Pu B!;&1%ˮ4Qꍘ+Q`?쭷Bxxh*Qx }./y>w=퓓7t56 o |Oa`5ZzľrWƘ1cA𻪣Km  /gùo’-Yj5&4@۬G%CELr/zvE׉rG!6m/?:z:Acե))m۶ŹsD qf7[2Os8HWgw P$Aw ŷcK bAŽHڢxw_#DDN0y Z[:/՘W޷o_ZJ^c`gztO%!q:_ډeg%+D6_ԗ,4xRz\zLiFcʅHo>Ut♯Y֩lEcv*>&T^Z/1?hJ1Ubq~d#!{u6[ rf{<)Y^O_`_!1`<,L>е|\%FH({8kNߒ / ]^qN- vwN݃Cͥ:i[B06"J';ƕ?SBp ><$UN=ry:%]ɸӉf.u$,9 gCC1GN"tF~PjiȾ S4mՆxܩ)a^=Á\(䢕, -p?^NiYBj)7xh=i3}S!+!|`vNbai&4~uI~,K0?uk sf-cʟI0؄ -cGZoYעB0yGCKcR(֒\&A+'C5wzW8m-Rl2&_SY6֣bB]HOg<",J%#muW CRuhori[|_ Nش=l?;H`D?Df&#c[U"uE+ *O\S5#\&+&ojԿ&+Nn&7GWyq~BI; F{0u2i!jNl@ƻm.(q3q#AĔBz8Ǖ|IcA 54h74^M^q~Lޠ";WVGث*A5]Wݿ^CUT[ 6#U++g&uęKyTQr'5eV%oVcse87(&# 8v^3l&ի_ 3vݳD,2lX !Oͱ}oOk Y]T>~r_ϮBM{g{=xWs\ĶzUo[OyMA^h7RvP$]j|yM):A{DFo-bt}lGbq4";# 6=U˧f֋qan1HF!OZNx9=qE_֖枮U $ϵ\Y$*"4l.tkۯ rUkS&o! !O@`t;/ jf[t3*Y5x %TK?b.Suj7%4W^+LSD ~zm>8 Xn&s~5AWKyd.MsZd槾5q6";< L-:R[p7 A2gI,'o*](YOÉ7ťaI/w! ۴x)WM5in–'iSNO Mwj֨))<>HZv.>W8yPWnW tX҇|@jWBk<6$S-h36&2AJ|n_p9YHڐ>bJE| ,v%>>ă?coNKe; &wBcg29Y8>~}(l7.|-qiА"g)ȉb&ǝ-߅_Nbϸ Í\d?cU>_zN~z2*|}'a^Zq z+tn7mpc)ŝ $Ⱦ<z{Q>%˂n+RHmLst#M"-ҁ;3y) k>BCBqHXW^{Eԃq%pZ3 % 1lD3 .n' wie_Qޕ;l wJ۷"rڄ0gP~J K6r. .]X@XSKh߂[sS*9j}::>ԧ@^(ߘJg+؁-ivFMفk)()vٍ6[mلz?΋~[MySl4_3+K$W v%qDZ?s\6{/)Bw]WV]đǍ&ƏÜ$ pd31Fa8jn؀4b-neaH҇kS2MqtU.Wmfvr[|E57jc4cKO2@iQC(܃QŰ'oMѝ0?aq_CxQ] X } M+{qS"Rs~)cN|DdKȩ\\s]"6w |XB_vZ1_7œ^|!Xmk/1gqI`v SO )huS)n a6y#B"+Ս]Bah[/$Sqe_ ByOpdՑRs,|Ȗb׽sޕ9(oud?)ȤQQBx?JsI]r[=nn 4OUl0|vPRFiJt<=va(:fLJJ(0񿟖&_߃)h~G n[~E!ԧ:ݫG%FEB|BӜU~uq6K"7g_‚sE1XG۶R?@R,ǥ_O^̻Y\UP_9weORK^/Q2=Oh_V 㗷x( &ѯ}k)T_3zJX&CC<Raqg`YKS SrK9WT*> |NVElpc+5 ~L^+-t :hyYO,/dk(XrʧPp*@B̹sP9ݥWn?:-Wbpnq콊Ź'i=FA\Xa Ϋ Y[ 븼/xX$ &n%.ryZAAgDaػQʢh$BoB  "vWCߚ"v .6I\0`bʨ1|kC-y P2Co6v!X!Nrqb^qgG),Å&8'xJw!1\VC{y~xKCI&DlG' @UtΣT3#a'D{}#K-0[BajAQma %Y#Uhvz U`vxn[7{[}1}NbeBkqndJ :}zŽ:H%2L++1(\F`-L4{͸8U G?䥲E%kPWIC E~!\ߩfK!WRI}.X%!֨A_bǑ0oXVRD m/fMU] $o_=)9eWƵ-Rv`Ix n٪"fd$bYw$#ZD"zD_+}+TIrjARu.CbJB<$ޤ )UAEM(R LJҳj~ʜu>S^ό TQB 67ꉞCATތ48NQP76 ߗ~hdP3;غ"%Ê>&N[:7Caun {| ԉ W4:vH'&%Z༷N `X`Ue޻N;<0#w[" qoF)yj FSۙN-L0Fcoye)`4(茨q'o3PG¨"Ρ2+F,@v ~sƦA?#vq8BqsrxR:L :t k nYݶ_DWPpɾ6lӏ܊Pl^qLQ|_P|N#1N-`~a^]/|N#Y -|ë&iC6ϥ"mcMnH;%Zx͍S&^-F s0V Jx="&3:Bۊ>^vJ n|F {џX+r&uj-X:Hۗ$8d~Lَ, ?A\sS[ _KZ6WR4-(:wɯۈR~r̓ ELs;tv _+/)*5\ϿmD6.5]F?ʫq+L!+0w(HqWÛwޏnsR%ןACa!n/!pZ}ILrGޜbN3֝Ұ¿^ b︍B|<&v kG}}:9T)~é=+ BSz"tQ$X }?w*b4o=S#@LI@w~Ѕ=/eZnC)15BKmyzxx7=1~GߺĐɫݢXC'GN21&=&?/ x-zUU{WC1yoLXrN!s7u;ÿ~(mt:k|.V PpNo13 -*Sw_?Qf㙑C1ex4b2jewidhrw@I+^1Xԁjró~?]I s 1]WJ骺,_#=B &r!lZ&^}0)(V.v)YL3y:,oʞZdFb蟔a(މF?Eǻ-+ǂuXĶ^ ҋ{ @iV])_KaM7ܺVKS=|2E+Iz$NkKlR1W] HCȍu%D9Z% Z"+LPc\=ݜ̭6Ǣz)=6Rv'M%:&1b' ̮-!gpXF+&%;X̢?\G+',=+aq|⥋IĿ.IuT/<;&TiJ|0E~<-X(; \$X梵ݵD'V˞y6O?WN>hUjLxe?@` t[W"C?b같)]^턡o+J5aѯ${Bx]|pj]Bs{S5WD+f\6Z Eݖa#@JxUNΈD0Wg%Lkayyrtg}9l!s;)"$oLk߻TzXCM17¶h7WQ,ۋ_aH>un@K*sWG f ~BlWfC`#iL^7m%op=)0iaDuSJ421_[ i}/ZvfG1zaXNW;`!F"{SH\wKѭq?6ǠUw Ӌ=oZ{HX=T8|љ9͞~aȑnșB`:h)sZ`oemŢ&T=g$DEt'6'W{X:*EcE_J)gåw!1|S&,AZxs}\mQ,##{+iGfbY rӃ0ʭ*eڌEDTu,ߟ߂cJV֞atXc^Bv3}IyU?oH/t=94QC | ^q9CJ謨~8 )î ұfuàk2I1۰%v t8l5MķFFX64,rt{V*j} ;tk ŭD3}axLSʨ,E+2^,DW,?2.9_""sYpmT*w6XʹSLT.(O ^galRe@fOPR6o\1^0u ..4~FKوy0,CߝmM W_Lˊ+~x| ^ Y)trGMXm)YpQ$K[_wANU8 Y OD-uD~`N7rKN >~?X5p~>,:[mÑ:{3 = ϐW{n)ډLTSm c0c뛰hKMl}t.eޗ# Uy FO6;9 /2'}Eo!3:/[ўґ `z3F hgVha Cn_Vj]-)uUV} F6Ya#ʫok<,6,FVlEutuW-Xv>MBlǐM'QC><T`+ϣF%ti,ֶ6 }U cqZPl&ѼƖnRV,mIsh`bUpX݉}qG;9 1?gh  #1 =T?Psg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|U\ @IDATx5iJPQPԳS(]v**,gٽ.{(aA, ?a2;;;3;OgM2'ɔ7$2) @ @ @ @H)Q @ @ @ @E: @ @ @ @#AC @ @ @ @>@ @ @ @@`А&A @ @ @ @0h@ @ @ @ :4I @ @ @   @ @ @  k @ @ @ @ @ @ @ @#AC @ @ @ @>@ @ @ @@`А&A @ @ @ @0h@ @ @ @ :4I @ @ @   @ @ @  k @ @ @ @ @ @ @ @#AC @ @ @ @@ @ @ P VXK5sL5o<բE վ}{ծ];ղeKUVj&u 4Ԙފ .0*(8*pyQF9KtMNOz vm$ @ P lv*8fum9R<]tz׌,$ܬY3#  tPp ˒%KUW]^5w\=\5tPc"/r5rH';8#.vm7rJ'7X=CN=Jl5d 4-H ,Pcǎ5j$*2U/2vVRse=dȐʨ,RB @@E݆۠I&?eC!OFI#>䓼u=qoKCbpAs=ƌcu衇J ;&* @}@zKPϞ=X]ϟ?z*FM @ @RCTiMqꩧ4f6tɊ ;v47n8qE0W4hG P`PZB uYjmUqsH@ @ 0A/PO>dցVZ};ơG[nY EԮ][{Yy䑬R"f̘|M#_I=p LK'P @ @q@Uٷ~;+#4=%W(Y Whl7 @ @DT/!@˖-(w҃;/v" vm.B *(BT@)$`B  @ @ Xlݶm[#UPz~ibŊxR_&L~kh/t1Z}ɒ%N￷]tt]vL?W_};'vYDKR䖿ufDR$NV7|Qģ>db݋/~g!C᠁j&]?{R#kiӬ7`[z|uM/Un·j8m@Ex'u]iРAmt9䐜evaN:9gN_={fC!]2F W^y9~ 7Sn]r&Md"s⋌G.ӱcǜuYvq̳>/2w} }uVDdA2W\qEfѢEN4J#_m atMC`F=P0Kfڷoo i!@ @ xAwuj! ד&@!ӠA<7n9蠃2cǎ W?p˹gzLmԐ2cۣ2'pBFetN3h#qrq 12~zf5G: °aYǩSyA+qr饗}[Btno UBhm1ʓ… q}1e6l]r_ /d+{.袢Z|1@QPQdB('  `<`{{mF 2zjƫpP{|pF/= VF|a1˗.K](%̙Svɨ2|͛E&m]$B~1zuG}b tUWeԩ.裏XtI9CNզ3Cgk{Fwm2*wwdYƷ/&_}_9G|MF>iчtM~|㒸L$  H =v}nV1& \SO=hzZ|$ejvS[!7}t;(/L}6{챇;*ʕKrlweWpG?cE>mlc Pk]>"P'(L@/}]'Tz K9 77NJo'xq[nF7:C^XnP0Emfփ^Qe ^Q)Ńzw6N^'Nh륯, 0(%pvw* qW_XkM6U_~^kp}-;Zke{-#ٿSo[ɋ' yfΜx #YCD @  >\->`Xwu-^r]m־_/M>8d,N'+NɯjҙW:ljAN>0aTn+8aI 8P?L=L*$j׮]QYj˺+Y%q=~g}`讻jjrLX_}^{p弦;B }sA TҖzZGҋιՂ싨9)m+YZQ,d'3g.2mQy~S2w_VzYrTؐ!C-w 7YRԫJd.h"fYh?oem˛kECV[#M60o׮]F;c @ P%[N'O?EMy$7~wOz9GW^y%Ӳeˬ<*d}5 WA:W8ʲϕ&TO0f+sYgߴvd\1HFtGVm'2zJHR$jjЙIj*q"ykNN0d5q#<4vlKz$4aVۋ{ƌ9_2˖-:'kzD@X+ P*Ѡ+,\Ys5B$;#yw?Јw'׫&dV${l9^œOC/kx!{r N<\d2){y_veYr2?+) @ Pe ˨ 5QzLݳޏy;Iɤx +;BРA!xr^;iIr_!#ܼy|u.R| IꔤڼtfR?o|.G5iA%9Nl0hJ8I0No`krڛWXmz٤H ӼtQt_u:x]to!DMp  ls)X,xyd vkmذave o6#.W@O뮻I"^x}]^z_a8z$DtY]wu>G%m+>v#n"9@ @@>Sk;w|W\;/˭m'p|犔# B+=6RYD矫^{C)ۖrM7T(q:KiAWk!$@%DD^83r(+,Tz y"@7\bvbXWFPzE%!ԠAI ,YMA٧d?Os'in;koBq @ %ًĘN:aƎd>;3%NIsҥKYiL'Ir1b!|rqO b`瑤N.tf~+.:$I\\+PG ^qE͙3Hi_\#1z[CM{PPNt6mBJoc䙖k#@!d0z8yNYq1jԨxՊ-*:$Il`Cd,^Çm8RLjj[la]/u=^ kqC QoEw{喙u:rMw@ 4D, f_\k׮J d =._ qӧOWb)u28ʊ.>fBdIDV{JN< @ ={>"K> |vm͚7lYg9R뭷jժ#kg$8vQDd\-Z|ԨC8y>IvV]8ӦJrU^wzwdYCn'uծխ[WK.u|? =O`? 8 `']@B^d78 ƏeQv)y@-(p ,UMc5 |MkY-[Z|'l޽{5!. @ PA ^0ckݺ;X1$J*ӠnqꔜJ%Ӡc]+=Ӕ/~ic;_]͜9n6U^=k '"^?18ӠoV5=!  PrJj,uO> СC/)HVxwATИAܗ48մiSx#x9#L @ $[>Q%GVttOyBC\ N:`sQ˗/Fg)e sDƗTĮw5j?pCÇa be~2NܮX2O ={Mj jF;S@ڤIzш_V_~Zd>kċޫׯo |YJTA 6Tv!?o2>r ;Ks @ @ ڢlv2YROU$=zUIK׮]:+W4 TJNq 4蠒'qRn!͟?rŊƇNyLJ*N>flOgϞF˖˖-3 ~g5duZhBi5T Pc`PcV;v&?1}Q{M7ZiAGp[^ =Z1HvW^y:"s\Z qYABs;YZNRGil7~)% @ MO>Fdq.:c$ 4$d [v @ @&E]dLq̘1tiΝQOxܓꪫ J=ܣMoR:EW-:$I$켫4+*ˊgul'ovlO[7k:[!X0n 6PUAxگy:  I !0tP%R<@ԫWl;]vrc"a-P'x%uSl P| p%zZ\wp/3İD;Kdj7f͚eYnd -X@I<(ʋ!+Zx9 +k! @ HkwH9 т+;V}G;k+4F) $Et)Z{"TVjm,onwDթ/3_$S2J0U*q`7 \L0?Nz7aծI[ r?6w}u/ﱢϗ|`'LxWf]dKMfu_&@!z&3/Yl `JcGFZm]o |r|~.xцYt7-GO_+)2m۶I4!+SOe O2wi'# g\´3eӊ\#@ @d뮻FBOyܹs Ws:8W\.]2z`9O^|,˴ZÆ O E2G/^Xϲι馛r>NI*4D>tPL{s=V}B*sʕ%Vz٤W0WC'~vob`?J^P@([NF@8 td5K~yϽ[~9M#3gδV0&}ݕ~VT3AZ~T^xa^q&N}p}Dt;  @ TKÕ,ɞޟ~EsӞ>I.nA~gѵk׬Rf!N qOkQ8Hs:h ckZD"]/[W²0Ў /J~xi<0h!j!ЧO5yduw=zֺ뮫nFk!CLkW^ym&y ^{{=kΝ;[&Y|VܕW^EyNW_}H\ٺDt; >? @ @ IlY);v[tÆ G`͠&E&~i5a%Ľ{V:uR 4P͛7ǔ}e#F:(xƍgEĭS+3ɸ֯uPI$PdoR˭vlnG-d+諯ZU=܇zE!kmقB*uޏE ,2 #?^ީTˏ?e[gaN),qO[YqGJ:jV{EȘ1c{y󔬦ܭ[7' SBv ]Nj$ jdSi@ ib;&F#?Spk'@ @ !_庝|ѽ{ww*$ *Aj8>ǮШ> z-ØAVwׯ_lH@ @@>|zǬU/e-Bmvje{ WAUSC@@M#ACMkq wa{g$"@ @@#ТE 5rHލ7VWsydnH[ը@&B@@B2=!@ $QFg}9K'p@ @l=z%Ks=g :TM2Hr!aITu+ t4@!,[L\OL^{uQm۶v@ @ XwuUVxÈ{ψD'q5ר .8Թsg5x`#@e@U #P+]SH @~Ft֭&Md29 6T&LP믿_A @ kG1xU첋:#TNTŋ_|NƷkwyG D|@B*5!@ ';]}9\y3@ @E] l) N[1fҠC\@J" %d@ ̟?_lru'[M<vmv!@ @ Gr-jҥzOIr 7w >S r?|׿ )رcL.bu!8 7eswaÆ91Bu  'ze8jنrDž'Ǹi?r]\CMFu/@{5b˩=1 7 ;m={mr2)75]1Yi$<((GY |J&[pb gy[nYǧ~vuWh"<6dx"!%XYxqVe˖iϟ ,]`33b;w\oVlVyg5ن?P|jԨQbH"Ǹi?[1YHt$* o@O@{5b6GM{J3H 7]h6VSq҂^LtcԴxpgS45N`ɒ%֊S+W,+ N.馛:D< @ t/7o:U^f"@&@bÉ @@Q*B@`6"! P"t%s:+4á$pI';>ɨYfiӦɓ'Ho[_wʲDpSNU}Stյ^o?k+.lذs @ jv/Kս5"N4@CF4B@ Hq ؒs 4HmJ=/5qD{G~GN\RR!CiߤIǏQp c)JY (/EOMieCHtihdT]Xˆ XtiФծ]PRd2dXd`$REE;YJGi%2\|__~:'csժUGz!k z/ e˖)[ e㚚qSi׿R^G_W\%@ ~6㾊n#\ DNZB)4i|GCTHܲqMMA~܄=FXb-'* A^{m%6MV ~[?Wƍ!\5Jխ[WmSNQzSL_}n6U^=%[<rCkРlԖ[nvqGu!5X97GmG>c?(mܸZUngn  MߪC:~j]wu)G2 L:Ur-꣏>RSLQg϶Fmwnvi'%b\k}Q0vX%cO rZhf%8oaԋ/&Md,XZje z-'|'I'd+'"_V=sK.Q۷w¥x͛nV5bMdk׮#PzjҤI)E>Wu]>P~3gu>"O}{;0/}[ƌcy[T"7xcugK D!]~4_}*t?}gw9dM7{~T8jTc81&!TtfC{?7s3ճyU?y8t6/@a_G'X"QeK?& -YFpcUrqh%V]u j@}=pJYQ mE_-u 1&\ϲ@w0ύbmDs<[^ۏnO}! t2&}mېHE"OvImuAt> 0y_*u 1&c:M ʗ~aB߾}_kg6`_t6iW_ʷI$;(e|MߺS%nLއ܏@IDAT?WL)}c;vED>Od\sMEO? sSN9_Ϣrqw]꾖qWJy`g 0k*Fi~8~mU_apc2,Lۑ@P6{,~.m׳yUtm~)ξbCaHǖizGn)cFz|huS8ki7~DI*t&8d560h0 $}m"\>8^{Y kΘ͚5ˌ7.' +ͽLL}ଳ2{IpI8e{m9 8e{hLn{2{9#[laMzӹÓ&M2&)=PL,ĂLi% ن&x!wW;+}Zƀ^wyFny?N wZƍ_=+WP_?;1 ϯ3fK R0c81z H@%@yqWmoճM}'̥݆Ih"h"Y3<.m&ː{1cl#ajB/ƽ-q%_\ )qAZxIr_;>}t).9/;<19c]FVq!AK_~zuA G߽{wlyk2-0nA\gΜ.駟:uճgϬti"X{Q>"+.Ym۶!JEx%:˅ya:@D{ Q4n_BAuXF)[k6J}Œ8d J/L=K8㼯(Π!g8Nk Vy6L6me⼯0Ǡ7D[մ/IjtE_pZk-~)me2vXz뭧N8G)Di$)l"IʤWQP~\N$֓J؝8ntAA  ND~yTUt7eTmtF%Rpm.Q]S>nm76q{L˪Tψ+ o]m?zyuM7nM?/EY~ȗnK/)^ظ䧷)pG'-ˆnXPe pTn]CvWѳg6wHE12FqNTm6^_|˜W^y$O==z['5L{7omcokd,F9nW_)z:-;> ;LZyaax{-zAgU0 M+F}2ξ[%,'OzbM伸dꚚqS׿ Bv@[{O>Yqyykd^U_[!D ) H gX=KyQWP] f*:QoTm6^6mHat6,kF&WatI&t`А G(jofT$޻ZBsϵ[ b"/ޗ炙H~Q4-ߛ4VZ 2ֽꆜxCvYdKLLTm6^ /`m5q]w”X]s5 vZld 9~aYe¼y~X0/$ޗ8WH@$OY}gU_K{N\FoGuMM_gR<tAVBv>{6l B$1&A@@U%$!{TԴtc ݆?\I\eWR~%I({#Y;0^@4a70&-K L/ #ofiԨ.&4bd✨ ԩNo+KI&9͚5ZFg~itqN暡WKK03(Lpk^:r;4GÜ 2dK_ꤓNҲIJi7곓﫥 ;ԛo +=䓁VJET}թlHORc2X$ (t Yϓ~6꾊nÿO ;An#Ӥ-ȵѦn݆rGuMMUIχa"mn#8+VhΊUF`РAjvjv+ٛ}wvW_}u-Z(Ԭ)]4e ۽}xLCə4id1cƨW_}UUƍ˚6m'Fv}Dz}(ݮu`Gȶ>Q6mkA]!ef|7o^U]dO[s]ǀ[bؓ/Ϳ;# ʾǛm޽ mj/GeOcH~\vep:jȑySM,Wq n#b)z;J}6ʍnnm&] 0y0y UH%ʎn#WO4vͳ γdE虒c'}]kn[8pU.]|kҵkW#~2,0H,v5(-[$@ \V*\;xխ[2l%|9.b[F˰LL̠V5XbEeϯ(ܺkd8 I95ppܹzq_{*a O?0f5ev]vQk^4l…Fn83"cTi7Q5Y׿K/ԉ/dۣ0DW BO%< (aVl~Jj#*0 GP%T6rD3ޫo,5ώ.n#Jjmh!7(e2="}Y_]C5X&SI[4d˖iӦe˖Nӧ;Bَ`M7U:3S*Euy|/7xCm'ĺ= Ě:ujb_̷m8_n_ p1<nm\[O o_ݦIľn#@ޅnFv.6`T5=Ƃnc54X-Mnlr!k ^uYF}e+;ӈzg-3g:Bo fܛwdeKLl_2|G*hd_~i- =l0e#W, xx=#T[oj֬Z`A*j}1CIE:uFbҥKdc9i(Cw뻃FD\Kp26 R?~饗!oO=TAWȊ󾬤i 2F{?NƊۘ9ywXw>Ɓ*{MT/*9s_:Z%N#+I\XW,ַRd@mDgW9 󟦾nFQn0J~TmAts)-*uLitg`Kr`_~y\|.C1J,-gO<&Md-O+(Iy39&Yl(-[>9,__s5N8G)1bsxM6QIJeT(aOZxã>>%&J' >_V9C,e+ Yv6#{G~zjLϚ5P@k8iE[o r,^Vi2eJd˗;N?to{2lyo䫥 N^Vq"yJ\w$dw?&z}JN|Kۺe;dRѠcRd$1 " xUEgW9 n m86dE$.(KI^@(-np.ŧ@a :+uLM6AC)-z 2y)J|:8Ǟ|I%_Ds1cle!w~ciŖ12ٲ? c{G}gNQ\r믝4IWTN{l^tEJĈ^sk׮d%'1id^=SK:;A˿+Yvb#3fO>9+SO=UWo.'\|ŹGj*{|PJ)b-1`տlvFr}_CB?'\]p+OBB2{<:ϯ( 1fpo#[W~%e_, Õ<&@ .6q˕ºRmќnlOt&o݆Hv8wEIBFnvAus(l~Ap%Z'AC2)njРA?zg8 4jH]FX_o]]&gDF$-ee/KU&zެӖ-[?|5tPX׮]9S,J$H -[*XL61ϭ&͛ne#… U޽mĹ=2i֧O%lw]>h;hWbvbl_V[)ٯ,*EFYBvyIϞ=ճ>kG9cǎdp9cUGꫬ`NoαnAծ1g-Tuqr{7,/ -%du 9(A kmDQȖ@2FuI^lK)$q^&qYU\(2l#5T'~^Jct Wt? (]bM>۰[|i;6>nBGeu\"AߋVK̗$ F nßQ1\cҿ qh>'#3Zr|b8?yai%~8+3ڸ!3xVPgHF:BN)^OLkC#Gr5퓳<{HM K+/m۶ ɦ]w5TN̿{F3[&/_.uzX^zC+cCR D8Np{˷zy Kj.7׿(x=܋\_vF$oh,$ݻwwҥ/ߝa=qqa[r_}w?3ha?q mCu.0c81zBz@AXM)b%d)-;??*Qm0iנF&] wi0Ef.S$k6V,ncBE|k둀@M&'ʬ! ds6~I;Z"]KJ9&YzQ&[|}UH&M|ɓB7;RY됤? d)SX6d+(rS6 v%{r6:Pz6?e;l'w?09YP2?Ck @O}s= 9^W]uz饗m|G)曭-h:uꔕc ;lnݑ1dpz嗕~PƓ{.r5uT5p@\wʗjLNȹ==oڪ-H-k48/y̳YÕ>&l{ `@aRmD䒆nlAt&;$6l~ ^[J#q_jt6LvB񧾽X]i[8Ē")3ge {v$\tiŮwee/IX?~/zY{#(iYbD|yi+f?XiӦٳg[ mڴQnZgu 0ao,+%ѣ&UV)e8pB PlMΉ0yI+EǼZ@a,53`VElf%]+ly=l9_rfn铛lcRݢE>-)`5PZ-{$B$㦀EW0e>X0&=(/4={IVeen#dwmnp._ܱq˞莠(M]K$X$ *@ @ @ @rw@ @ @ @H# *@ @ @ @0hC @ @ @H4 2A @ @ @j8 jx @ @ @ 4!L @ @ @ N> @ @ @ @ 0hHc  @ @ @ @w@ @ @ @H# *@ @ @ @0hC @ @ @H4 2A @ @ @j8 jx @ @ @ 4!L @ @ @ N> @ @ @ @ 0hHc  @ @ @ @w@ @ @ @H# *@ @ @ @0hC @ @ @H4 2A @ @ @j8 jx @ @ @ 4!L @ @ @ N> @ @ @ @ 0hHc  @ @ @ @w@ @ @ @H# *@ @ @ @S #rJ8RשSGe2ZjeQ>6}~%{GF~G}Вm J.tRid-FOPrɤ󶏔J%>h)QPR@JmpMJ^[i?J&RMJrMc[lδI;6m9&ŒrLp|$gD`ڴij̙N;wV:tpnϼyҥK^[ZNOy Eo֬Y묳/7,YϟѨQ#պuk'}Dj͛ AL@fƌkF{O:'?ۭ<+0R?}tØ]vnݺ)1VX,XiٲS~w-Z&M_0$v7Z}*qŋ*cW+x{=%s窅 ƍ+yѣr-<鼺N:;)iNծ͂n&IgϞ܊VZ&ijjy;_wuU0 xMowsQr\eO`ѢEFm*؟xm֬|;hڴid/ n=%nAC܄ @ TUVG}T-[̒=YWU|IKAVLoy^;C^}UNv9(I&^ 8P>? @  eO @ @ ĸOL4YA=쳖ACe{LOjs @b&AC̀ @ T~Z,[@|MØN:jvRlnLp6h#'~UC@ @!y@ @N`ĉ_ YtN:$#.oΝѡC_端R+WtwprUjW^AB2M 0P\^xcoo N-HlB1Uӄ.K-{3ݹ;;}g4{9ߣsV,OpYgyvѣG=,   DW)'@@@@[4e]&^xzGzN< W@'|)SȬ#9%\u22   4LmD@@@@ n3ϔK.DʢNtzpM9qaO[rssij>Beehp;[}}dه   A"K    ]GիW_,19AdddDv%:DCCTUUGK(//:⃹Iw&%%Iaa4777`a@@ l    -֬Y#}9𠺺Zn*='ݻEYb_^= a(C 6wEJJg@@@( %hN   I ba߾}w)m&믿^,Y2.4D<嬬, uWV:::ѣ~v7*tsO 1Xޮ#>1$bl}h^kkk*ę:iiiObBĜ3ZWWyQN3ygggkIoo2:NkD@C85) @@@@okhhȓL/-^X***$--=N?ax@nv9s ]4{jEiN hЋ6/[/ $6>L'6ظOvV{ߞa_x2\%: dʡOg'4(@@@@  RM7$](6m$}}}}zmƍrwyJk@5@a\ "  DC =DƜ@@@@ .tsZt|_̠V\)w}!_xs1^>sW VCrPlF@@", x@@@@_~]Vt趶64SUW]%=_]֭[YN1a“ia^\gW`1}GlXItd#Kj*X X+{?.'PFk=w Ѣ]D9uBľI_7Ŕfu@@@@l/?TWW{S0R FQ粖   @D!   kuqMtKRreʲer*)ɏܝױn;G ˽W__/-roa<,yD: 4zgg@@H\!ykOl }?8,EyH>:k9 ᳤$@@@ .,;jdt|F]'?{n|f\⥒=tgu:W{IIt>@9iii @@@੷/_#]'Fws7^\-{̅rgIUwuL9VN C@@@]Kŏ_g`qxdT|տoqgl,000 +uĆ ~ lO']]],f,  -08<"3Xhsܠ&>8Œ)h   л#~ m;o6)C#~CFMY__.>`@NPUU)O&jkk=-:tk9sYA@@ѯ˛nJ:zD; !87B@@%Qpq CCCpaGijjj<'͕|Ϻ.,[k}Ϟ=^޽k ^   8"[><p p t 4@@wOwˮ =$L=!@RR,ZsN uVd oDG]0ڵkE̙3E&ky'm瞞yw<͛'ӦM󬳀  )066&^~DHch+9W%!z    ,GBjȨCGt2F NhhhQ4PA,}GzyY7/s9NٸqZF>/6yF@@sU L#<H @@@@j bZg @ Q{4?==kݳõper5\gΫ7oW^yżYJIKKfYF~mil{GGv馛$##&:2Ã>(l={|ɞu@@@ q><rw4\F"@@C":mF@@T3"QF,""puɱcu$zH***ZrssV=*^uЩ&VXͼ*7x???|rwʜ9sJ>9rk>Qϡ:-Yg@@[  Gg@ rNW''?'r!  8@`tt,Z~ , @t[oUx ٽĜ:UDU$''˺uK/pw~3#4ht?SPP`:  $X.\$R7АHM[@@@8(ϒFi(όs%JJJAv'|3Z:NqWGphToɦMdΝ=.NqE(ed  $@zC)] 30   U٥hkH[2$9x(++/̞=;c,Y"q54:E^^ʼy$` XmjkksO3(:W젠8@@#u!ԤB-&'!ẜ#  +pީozaSf}<"@xrrrdܹGxJ.EAB@@8eveJkW?}k?#@@@ª"Y}+3fJeINs    ğNqÅ'ݰlt젏OcToժU(;o!ǎ&ioo\ rqwP@@@X ˾cm518GXVs#   M.;sN?P SϔT hF- <ԙ-[րQy䷿zթ[dϞ=SO5\#W    M҂,~J[~5zL~vãv΅   Hv&'g7|\I4kV)KO7Π"Q_עk0\cZ  DS`k~Z<Լ3G @@@&&g_$)~~eeͩ3&ar)^~e F}RSSϗ˴iӤF+El"rg{  D[@Gjkԅ}G[嵝Dh엤$,Y6}QahW!   CRS9.@IDATKʕ+qOA+#R!z'WY~dPVrw2k@]w%)߉*7oʒ|+`c5\R,X ?w=iiiFV@@@,Q, !   )=o2)g MbS\GsAGgϼ<;\ Wv$7nto>`2       $<00sgӀ~snaѢEu_ VjϮ7xó       0BC ZQ;00 MMM3͘1óͅ}А+V,OpYgQSS#GXaz@@hꗷv6iu-$䦍)dba<ɍ    0 SE5G]]y`O>S]jt#`N۷o' 2   /nӔt:=ȈZ)ːΛ/_SQ]@@@@; `1F70)'>lTArssij>Bee;[}}dه  68!}-il]gwˡϐf7    ~ S24}Ӯ]V_4p=AyyyX+#DQ\\wIIIRXX(ch𛎌  JOzww^zqD!_ߔu~LF@@@@ fn$[s= 0{ncQVX!ׯl϶P4`aAwta42RRR<#  P0Ѥ]A fxF@@@iꗱAN)#C| `9h#۷O;e m&믿^,Y2e2h@9(e>\ź+C+=9i^sy˱#`} D7:j200 Hu${Fk뼆7F-} }v!P6:Pl?q:>k?S%9Yk J@?+SOO 7GKNf/V@@@*pMx}A0Ȉ꼊1H2oY$Y~bK GZ l:T-@ |}')I   B`uؿ?l~ ]v6tTN)@@UirM7IAAu{:M6I__{PqF;Bsz!0" ֻ,YE@@ >r Bf@@@|  c$5BbiA,*Tg§ n[[//ʹ4بwusZt|Qۍ+W… wfM;.7)7{$=5%289ΘD91^:N=l 5|Z^8@@!0r%lRCB@@@ Xg;|);~hdwԇT ッkWH hY;˽*\_kN:o ӓ]bq',   @ %eȊ7j0y$i A@@@O<®ΥGl_:zB9~Ƞp8148&uZP9~]RRYgԟCȃ  6R^t>B`Cdtq    KGw0h 栏f:p/@@CMC.Q/xTNc**̕T---^KOVV__|f͚,;@@@iW[.)Ɂe7P=o [*wΊ  ċ@3;{>܎ia)27+<儥2Qn(777˽+244$͓nPUU%vaW[[+3f̘>3guV@@@ϛ&]}_.͕}qdUSȈ_vdB@@@._v;\)*B<87դl ~*OU)b>4>|Q}+`-[u؞={'Zٽ{.8XA@@Q/%$gzrJYaSULye`tuE@@l(tFs:(#\:!e*Q !,))I-Z0j֭~x˺vɲo̙AFz<6sOO;:Ĵi<,   Ns.o_BV4]2%99}7,* 囟Y*9a6yJk{[@@@S ?;Ϝg+Nxg |欹!S$fm A<Nݝ:*='@ r>}guᣏ>w}׳H;<ϺuappPZZZ<5³n^8sD렩S6n(_%%%Ŝͽ>âF⋍E@@@)ɲY6cllٿl5H}xx8't@@@.˕9,/}V..:5M^q\FhQߝ~|rO/|g>~+%--kyN'n5kx?ϽFtdDzo>gϖO>ٳ  ďF&`t}؋   _ "g o;֟zĝ_X)ELwiveFhY_wur19~f:2C=EZrssV=* d:Ċ+֢T?;9sHUU|'rѻDr-*   @ X% F@@E͔G_-'FIlnY D%N񣯮msd 3R\ږQK0B:?##Cnq444ȶmW_x3$''_.g \;SqAyפ+!??]O~@@@DЀot|vڊ   ^4XHNN], ciErWΗ2 ɲfiW!!N*l[%%%]v0FkVUi Z/--o}[i&ٹstww+:==]."C2H   @ ̐=O@@@;sk= v٩rҀv׍W58P&:OF$HKl~v|4إ'|cɒ%ؠSPIaa̛7O ={w}>6& XݙL466N/QVV.   3n™F@@@; (yؤUo^}tNJ D|dPLj#su?"z"? }@@@F@@@ $g/_WRs\SwJWZ嵏*@@S{z#  N@NU !  8F`vygI{֮~IIN,WY()Ɏi EQ"   ~0:HdA@@Y 3=U.  @ؽ   chpLWQQ@@@p $   `!    }hoP3@@@ ;T@@@ #j   p@'QE@@@p .*   `Gjbxx؎UN    cR[s*   Mn&A5ptttUNIJJ+/"#066UpWW$'sϘJWFGG-]"zSOO}b5𶷷`UODbq/hѯmbqhhȫsׁM:>I~~~ؿ. @@@D~OTڍ E@aɟhG*zy9}<`6H3Z_ֿ1-kY)JXhX; É"  Y@ aSP    4$dh@@@p pa$)@@@` o@@@HȌt͵lêE1Om:Wvv6xDkHpT.{G'NQI1z'1 UiАgWVV)vù5>]5?ihF#+5.a͑ 9X?IL'|2yF@@@ @`oa+Ɏ    0 @@@_N}     G    0I     @xh'!  $`:AM3@@@@ 5jN   Oڂ   Nu B@@pM8#   8Y ɕ   B`hhHFFFbqjΉ   @1_& m=70,Ey2@ @h5gB@@Fg   @z?_+/lD:]ִH`|J.@%@@ @@@PȎ  $3Q˷erVJv?6<#0    L79@@@D~& f0ۼ^20f     `@@H@^+#^Gk:Ļ ô@@@ 4@@@n ]/}pDk XB h^M   `R(   7]ʎ#!gC:'7i    @D!  8^ett,v!9x !z   DTR8   xc]!AGy @ h^    `s@@@rQ@ <9F@@@)   @sr򂜌BFr]ں%;3Mf˙ +(;U\q$@@Cu&MA@@ d@@@ ^fܔBW0C~vx#B '<(+>%KeAUl @`ttTz{{%7775G@@MD   X\Rddt,薬:2c}`mKoѦIOkozUvũrye!iiig=q@ƂS@@) >Y؈   `qMp9&%%Ur-i%kS3q,;=dl9ikk! ۴5*BPCT9   Q !jԜ@@p$:mD03g͕9cwEM?wv|x"!^{vL`xxX4  !tя@@@q^|U)-^~j@*[dgMsPב~ΠMFFFEF =퍊288sq@@@"_4,#  +dV5RVW#מ1K~pْ⌟oVW&Fijh7],z3u"'g"hc:;;z±G@@8!@@ @@@XPY(?򥋗q$' r|؈ aABM=^GokkFWm/0b,`L=pz@@V&8@@@LO?Y8-zo`X s3dNEd9{@GBwC#4XG]"o!"Щ'233%-ymAy  8Qk@@@ui70b bC4tB)'NX@Dz""  @Th 3'A@@p@q^fXj[r^ؘ: {&lA :D@B@@g 0݄"  DG@ɨ( d\ k---% ɰ0 tww!@@@9   8{IeH'H故T[[[ex8.  fР'~Y/?@ @zuq$IQq;(r]< @@@ NMB q1l|e{ɾAp5AGuΥLB@Hk](u-=C~7 KgKfzbL :E}ooVd@bOs3詓$3yXzG'e/:y<@@@ Y_JGؖ;|VWu3dzw}ag>6" ħޤ[U+^5ϟ&5%{"%ɨ Av: AqS Եt"˖!-iDR36],9&@@@ JL7%hNѯj<6)wJ9wi_ǐ @@ >>Yl<kvHi)|akr9Ȉ;A /@@CvϺFg׈ RFҐ %˘$:lL}i퍫}g#  DN/rS2 :w0${,˗YyI  #P);>vMIh1=SKtuu3@rpqL&00<"״LE&ܯ; y)'=    # :zdF`Ҁ~̡  ':*CeInB3訏fR!% 0Nhc &K:DzҰ ~ cmlndŰ ǥGz5WBY2D}ZFRa@p9::Sq@ ϹFu}w 6w#2s4kq  AGf W/=!pz'?ItQ=XJk8" K^Y+#>~$(p6\{"y5/@+ jxgo}'{{O= !+R  tJ f q( twwKccϳUo$Ѹ8)=:Bð.ʈ9a|ࠍѾLJ}t&zMUw5O#:D}H~y<~S4?slȈgGG{+!`k-ZXHY!$#"kF!-r⁕lQ^p]~prwH X# !=G4E-RfsvZ_GnE8NHAˌDX_/Y!G{ z:U`+C=#  m `5yno1gH@EْwӓF$%{[wdD7વt } 8@!`G6!q/ );cM6h /➪䢋.uE555gijjF:*//iӦٳeɒ%eǎ!a:菙WZpW4]֝>I1  F@H^3Mcm\eqZLxQ[82󅺬ruș\ /_t״#ɣͫϔPb}],(jn׌9i#҇]? HH}IJN4^z@_CIs!X#䢓lgt~%s2Xߍw,}oܸQz{{ݕ6FyfyǝBl_p_^***<&[x'wTMg}˖-KKϖ'^qϿ4v', ru@@?֛K^"{3UYAQ\?p89(rYKgP  0N5t /4@GJVڹs?3`h0[֟0Dv @@b)Q1D,;ǹ 7W/]ʣ#',P?}{.Smٲ=VNGVկ~垂b̙رcc_$9P&[5LǞ[?LBE @@ uh𛊌/𿿰R׶Κ&9+{3Ӥu934Fu~kD_(7΂`@@/ "~ULDI`iܹrUWɏ~#, F 8>}h~c[ heSSg׌3<,.P%:9< ~v@@@aw~R 옓; uB$o钙ɰ&"py ՏѦk|͹ dFY^q  ீ30ZG̐*]v\x&O떗KGGL9:Q)";;}n}:9 ؆  ~ч6k@)>h~q.SO')) ]wt ;?k!ImN/]C@`t8(483ϔK.DʢB:k_|###|bnB3;؈  Р#AiV6J B r:mR\\P2*ɕ~cޣ啜$׸%7I  @3ޱAB tDիW_,1$߾}^={׺bh͕"]vPR4(BGp#H   `?.y}mP#hW|X@#˺$/!c>҂,[/>:&n=$;kZdHr1̈́3 DT"KXf#.~Ky֬Y^Ɗ9Zn*=477YϻwXB֯_³@@,h~ׁ^5@oIOO !#v8jGЈ4JfHi~k\FdS_Q@]7ޛHR+^ pqջ=uT{z'Zضm߿_zY$SY4NB2eֵI0ւcƙ'}>1$blI ##Ů{faۖY-5kB=J_zu_&Rd9Z_'':o'̽2Щ'JJJ逾 d0 k?tMRPP`垎bӦMalbƍ;ংqZl@@@lm^ɂ/ u˴1t"[i  @b}Ci+CɃ>5pWNN.]*_}3h+Ww-ٞ^𬳀  S ͹[($:2`I0!9N0 p48E@@ :׹kIBرC6l̰h"< _~]Vt64S^XX(W]u፤1gG#/XZп%NNoϡ}8+K׉I4>;HiDU@()) < @@ޣ(ey'~`|+~gddHeeߪU_c@&󷈀KUUcjjjk[E#CmYYYT.F:cǼOO@ss,:u.}bhY]>ɉMe8[@V7~Ob=Q  v%CzÀ  f׳|֞IffQR|[8mC_+FW |"(P76@@^p!!b@Xn, dxW]|xY24ht !   ZGa0y& 펎 q,DL@#4J͈S0  @E.IgҌЋ>|^#ʨ [^^^uzDXA@w( }<%GK{A (RIOOxB@@ C&B{i#Nx1O#&_^=ܨ5:Tn4慍Z8  hЂ/CIA;u@ :VII4@@@ t8L.WҚhkk{Wtu#i7,K,16#ꔍ:+u   ` bpp'y hy#QsP\\7G" ă3C/҆x+PկJuuuMנ 4i޼yrm] ~S@@`ĠIY;uC @Ox$@@__Z| MMM7ȳ-P#g>,~Ҡ߫S^=;|" R@olˊR),ɖuV@zF$@@^ѠS'O4f ZPRR,ZS^ݺug}7!w00jSG| 0O6"l?P:fr2qKMj  ^WI7]/,]TN=Tg6$j]WW's`^7v <~ p9Ɋ~˽r~|rپ}{r5׈3'Cx+7˕W^)iii^XA@@ZG֠~|KB ^hX5[  @0:ZE5~!ŗ޽{Ը4%%e\@quɱc".zH***ZrssV=|^jbŊM,#  `;}Av]C$@@C ); h:D8c   e4L&>b+SD:eddȭ*O<޽s:c0tuɥ^  v20zDBHR&6qiZQ@@"//@B{ Gb:5ڵK|Ih ֓'|\qYG@@ z#1wc?Z4DK CU/0g ;S# D]@/@ 82:x~/}Idч)(tTB7o$@@$`>qT5@Th 3'A va@IDATFPIB@@ D$@*#su?XGTpXm>q ]%%/; @&SIJ$UDyڝpC4@@  @DG}iNFMNNY@@p A $x7\ve3Y`gNAa:  Xwkh7_TnbIm@ ! .2#Q"K8_```w#-@@R@pud1 ׿vOa?lܸQ~~E5e˖Ivvvi#=̝;דW_Fp8NܥgWϓœqש%.֞j# ē3SoF-:9ѣGkYgnJiiֳ  V@MMMgmWQ1 @@zWNAAB@@ Vz wyu=s0z3h3gz[ <=,   =SFj>U  ]"~!!W\!{ݻw}Wl͜.RgYE0m  1БtlFa'pj$@@C Q:>l%##$%%%2|Yj{ZW_}ս8; 4րK=uj9S ~i  `wFg{ٿ~t{F"|饗DPpzz婧?¨NMq{e@@b#/^#Ŧ&!P SCyJӑZ`NBZZ|sEy6766T[[)*77W*++E}萞0~"1V" лk}ZgYYYoۯo>SD~G^ Jt 7Hyyyi@@'381 k4ql.miAXA{K!>)'Ę<'1F,IEQv-l}|e{ν{kN9s{fgΜ9߯Ywq'4hjA3gZ[hp+',|Ұ`$@$@$@$h/T.yUoPl2;wnÆ 3ۇw0      8jɳ37  #6,4h Tk *AVUUiE!CֹBhCl$@$@$@$@$@&CHUL"+V-[Ȟ={ȑ#(&LnMrssf  d6ms=HHHHHGߌuuuy$̙H(hpU'҄r,**J5Q >ZgвUy}8$ iPי$   OuO|"[nc#G?.W `|V x "o/\G<===VD 999bN0j1P jQ9aa|gIHHHM9ԙ, 8F ))InFNbl     mt0 2uS 4=j5//l !..NBCIiiTTTf_" Xp     p@[[8Gg|      $(p@$(h :Y-4f; ?tHuuYjӧwܡ0JP=a&SdddP`IHHH#$,1 \ҚI p PO?5dffѣ\+ (//7+G1mZٹs;vL.]*Ǐe!谥C^\}wvv sYMԀikk + A7(qVsG]]]=RkT[(vihc鯙=Oz3{r.BBB\jY2`A$@$@$@$@$CC%bQHIwusc[nqIGٹscZ: 7fp.v'V`/|{ߓCjI/,^&(w :e'1116-5~b]L0滵  ,|dhx|tUUU] / @pe/@&u%Gjhh,o@?RTT׮]u1XjW^yEq %fXm    # 12k@Xj+!)S!    p|#ՙ"]A$Css455I||>%''jzs-@pm/U9/:!Yظ8up"33X i!::ZӵMj%''ӝ\6zNDg 9 D[Aˏ8sـyFFW/ip@c4m_C1P[ЖtMo3OZ~˗/7Y}$@$@$@$@$@GQK𿒳$@ @A+(9 tAȰ~zM&sO͘ƌ\ /H5:G$@$@$@Gd#;K4     "oDkڐ(hpc_} wK,94pjhhPgӥAO\t):h^<9 z[yM^_cy|L*7<ђ?=Q +cP>쳪XhW"ǏvM 4 bI@O=p?a): @@[DHHHHHHH<1PJ$@OFP-_L̐$_%77%<)0; |F!>|)h0 'pA@$@$@$@$@J7n kXn    lk*g ǂ x Gn?CyiWRSSd (#:uJckJ<]dqPڍ*F @Cs|Y7   F$qT'X,i43pbB‘#Gdj+ m@llϬpYiii.Gk7%@xh!%%EBCCMz@EE9ӝ.E&t1kӛxvaA Hf__@;R?`Z-YsOO1.\G-+22'hx2ޔeTT=ӣAO|MA#\ 3|ߖxmqȮ]Լ`grW?OW_9@AWSSʼnIHHH Մ~p>|kYF^u9s% h!!!bw@`N$&޿&&'{%|;ڸD \K,]&}yz56]Xx G/^wݻWva*GDD|_uS 2m~'Md4`' 9deeX߿_>snϟo 8Cjn̖j3    "7Y0U; V!f     +t)KB$ (hV}dgg ـ:fVc~;1&ځ)SȴiL *o]pLK>SnYd 8C0UQn9C @ x--[f&wUޣGvURLHHHH&0.;+LP`#r,..VGs /[GҺ뮻O>rss>09>l&OUpZ`45L @ |'V!Ǥ?n/F*Y妛nRS!B$@$@$@$@~N.f  k(hF N>\g =RXXh ᅥB;- jK.%DԎE&HHHH6u#l`      K[lmS`Y鞷]oȱ20^Jˎҙ3gZ1ZEcpWtRu#+WHHHHHE G{txH/h.(h/. I$@$@$Ο?/lQuf*=-_OͯJEKi?W(o Ǐ |r⇕+WN/ MWI >GyD'V No|zjYPr[>cr' h`9/ 8KW76_òviih8g<  "7lRSVlaH m%;;۔)+,]T-[&r嗛KJJ8:"W^y'$$D(h0 u3 p@q]W~_ڵkMZY[rI'}7,Xl6;HHHHH @@X WZէf03ۗ%e͚5F2̟^zɴ G@7@FTַAVkwtȓoIqHHH ``з1`c"L{l#o6MҢ⭝}^&p뭷s='X p?jyJ\\'?+GHHHH kO$~mդVБ#G~'~im{n߽~k4iɓns|0ppH j@ "Gn{Q{zN)mII$@$@~L&E1'Pj%Gy<'0~xy!a]!;;O?|ߐcǚ3fϝKK}qhkk۲$@$@$@E`HB l ';{Mg 6m2f_?VWWW˱cfY  AU5/֞I6N "rlS5>>$<HH@0 +m^G\&1a61b`NoCIBB:Ҥ4x@CC   p&ò: 4tJe{T5ȹ6WY?[G嶑 "!2ȴ)a<"4\YdpTdF'JD%C g!|:uʄ9pm6S<̛7l[LfVSР/ C47LLLv8/#x@uxTySFXP<HH|@wZ=-;O$,r&<K"afRvvv \zuY?   7wa [sJSUD֝:Ukm@@:Ƥؤl)!M{ pa-9sF]zuspLKKJ5~]sg2 @P Ь]n ^̈́9rYhyH@ww*ь]BHHJBI #qAv 7ȳ>ֲP~׿u}ʕ}pBiXx - m*5%W6 C`chYڠrwm9s>!`xfAA@‚YA $?4,HƩm}/ۑGQD dz&DDVay])ޚ\S@$c䭒rgl5mZlwnݫ."nu1Z#G?.WFc< & X@g({ <8MSԥA]!1프( 3Cl#%`F7fvc ;걜$ ̛Ɓ&NEb?1CWx4&v5G]ͪ0o pBD=*>P2|-[ׇ!  g oW'8[@</ m NU 1KɾDgDumV WɆ#8ꔢE|d,8fuA3EoљSy xT@cѡK koמ%pmAsx&2 >4j3?5gExǹmLIN/p,Yĉ45g'X!>>m?QL   L kL KhC:9Pp!Cyc yJ^`qUKykwf|\vPZ닭log7?/+J ZuKAd| EAGUYucK{=Q)u-)Q22;IF$"2H@!9?<Ce$04PG+ mqPF#>bBUUUW5$@{m?g!j0 =$P(+6*;\0ew͔ 8;T*=}%e$͗Cʌ3  @6Aj9H˾qϱ$'Q96˹:]+$k+RITh<,*++Mb`3I"!Pmm@؏_x8btHHHGbww3FݝmNNq!a0w:lE;tnDF?"g_a[qU&k g[k\1Wɸ\u< $@F&1Xt@*k?K{mVbOGK\;lA,>az9 @l?n@_hLH&$#beؠ !zjmsHhbVA$@$@@֖h2flxZLX8d4t$F8Q@!RޤKNpN6Uw&Wf\#c ].hxȫ,׮]9   kv3o2\# ;&( ç1" `QuQ~fM6pƞ\:4 3h nO-]MeE\,lWGؿfǍg  (l0Ί1IHH0 AJH49T nv8tĄyCȰfqߨr[ yxn5Cܣ$4$k\a  p Ȇ 5@S ?8\-b ->' 8G)%ږ555"o`#XO@'U}}@`!!~'M]Zڮk\cDvJB,h~FmYY`"Żk1dw4Y' 6bD $@$@$@nn_@IDATA}հ}=]ɭVv\Ir2N ѪaS{PcUN H"ͪ ? amjYt87p۱j9^(5 '0LhWۉJL!62b$*"T;:"[)fUHrUz|` >ol\Zz].#Z Qq34fH:Uj`kJE]:~n@0-9F( L$`@WW*V/uL{ԋ됸\H*)ai}EԤdI5.9iq2XF0'taUrpBR1FFFX.d   <IyϱEzSxC B9t#;O %2Np{LՒڲcPذ|^uB~TQxG$002ۛɮJQ 5'HGm7?aX{Rբt)`=tUW}] c4 4@܊^   uϱ ao6#bޑsK&#,4l7H@ĀLX[X&N S+%KHZZZּB~ Dn,Z#ujӦMrYzdKdԩL}g δ)qfbh b y 8@w rR|?Zc"1*e1 #4qE77KWSbPy%fk{ %5}RZ$DȘ!)2w|\5e( U`!\(08OB pDGGn(BA3-1<))ISW3<O ]1s}3yv J7wێ;HҪʼ 9rl`No'1oXo*h/9W\nݙ0 Z`V.ݖ1&  !w,޷ #pV9Z641 @vJ)PE:W"qCp>*݊<,7ضސ#/ie$ZM巵R^"O}|) $k00P U;QI~M&ɄhR]r^G&o6_2um),< $j* vMO>L̀/\F)骸ȑ#cS֭ 3giwm-?K*0ws% Fu]O|Nyhtpm%WH|x ˜L 5*NFY3Y|dT&ux|l,LIuI' 8w Hf)͛7(hFH4 i>("u hWw*c״5c-?yy!1V?BzfBt#akl0mv#h&pfW?GN4UڬrftKDO|6,'+ |믿.teQ/S<׾5̜9SF%I${mqgZ{4o3Qm  c.e :pCbSɄ\0$e,%yOXh췐G&ߘX^홁i5k֨gΜ0 s#dx)A=8.EЮXr!LY8usquGLUICw ߽V)7B; ':Qd{Q>( Q:Ȟ)ㆦʬY24=ey2 T5DuV7lXckGG1"1OI6 P"/d_/bx0lٲEyioox`AAo73 4{lW^Qw={TQ>δ<01 W, $@$@$@`V쟊c3e2뾣P˂;gn BCBadNhewMqTgvS{K7?G𚠡Tyg~,; g˾SUO-ET(Z5%*[O;%n)r:xw,t<%S|PowJ^_W(->Do-謯nhSF(Ȕ;//5˜OA8常8?4*䯫nEb-}A<||mDd- h'Aum{ì#ëIZxp1bJb;@uVS6PPP`ڶ2k,=ٳۛ6m*hpg}M;,WڄHHH:&'YO{mh?P=1yj!'6VҢS]ط$\56Vtёl2FmE$@AF N'vŝ01/I0 1fh;L~\:VMK)hFЃ{v>?om 9[,ߺy:m ҄1`f?#ϼK:?oyڵi w-mm$@$@@[bpVypl*2\yt"Rf3Dմ/gߏ%hbfVpLa͚5fw۰aɓ/ N>~a9A-@aYbi@ w}$@$@6d&wT}o-,sf1c4;6]"bY$Fww`h8mjK%+-WIu;-ЬwxԩLN7Ȧ`BI}hpAҡ>씱CS%%>v0 YxwcxdipHl2`:.g̘!]w <أ=u)?JMM5m[0YyyyLOf4LQ|R  p vdp='Uu'j9G(9_ 6%~aTXk@՗2cǺ 0~ټ$#|)Slb&hU W\q4t-7h@x  ':rE:NeΓs Z=- hqU,'GC3Q\h}Qiufmʧ7M: fo0ʶFyVUx5B1]H<P ={\{A@)))ˀ>9wmp}4>~~eYh  P{њtŭ 63퍦461[3zɉM6z 0dyj]ӻdefbGtXDؼj4ZOFK1M:$hغzSNNWx@MޒnMu[_  b$&*~$'bf ?ݢYp@穭c QJ #}Y2h=Y:)Ee R< f~"dHX5qM KuE[2 $@$@Fn:+Vc.#*gHҧ@*yUxIvů$7Ufa̙M#L4y }]ҥK^P;V\)?LrHH7!DL2 Ιj;ud_ ANq{t=RQk\WP`sZHqz0*^q919Kg$?| @` ;N֪6j6/~aO>@^8?^}UywԶ-2'W"ګ'ʈ>H6ă&m;vFb\s_|܃n #z@>ma{,8GM+Upu5o}@?^ I}}x9g%Y?fdWW^yt7=>"v<8|D'Ix<-I CCA]E2 ~yUwE:=ѵvyUv3Ax饗djhg?S F ,'p @ct A*ԫ ): " *Բ^"a1~Lx̵Nqe]p5tYb0}h=xx|\?dK[G:~N,k eզXtuI}<~5,f0/Ku1Ne)P/%w;\<|}hWb85& $Q\s՟XmX̐//Q\Lx|5f*$fР)nP|Y + ;{ߖ'OĪ돦 J`T?v|~\+<{c (UQ廷M{{H|9bZR1YSwR\ьv'foBXkTݜt܌ \s-ÉsV}+~FB]iT.vB3TL-k1are# FKLM{}LY^yr7]|;D=b v`0Fr&&-'͛3mcc`%0X SrnbIH|]~hWwbÉOV 3IdLJk Ix?P]]-]uJ`opU8 Mps:yeq4G*[)FSkCv)ʐ4[evd}w .wo>SfϞmZwveڴBZOڵKg ,@X޳|Åܙ~ѧe,kLrU%|w韥~oX}XN}LWv?5@ҿ7cbbgwKܹOJ\z gcccO kKUK{=T.?I#M ۹sMANNCN:޴ڪ)m,[& -Bk@Ѭ1xfą]p]&&Xl@'ag8varlzye2G0$-V_,k0nكƸCdZMAh\|9A*K+D39/In=T՚ȀpIQlýdqIAZ}jYH5c|^VW} yEXa.j+i'Vl5Eғ.6 #DqGgEvi~d4a„\nn={VM n0|:-m_?ŝiQQQ .g1eͅ6xw>6<Qi4@g 0c g4+, $G^hb6<ui2O?xc<@rQ~hiS~q\'IU0b)Pp '\UNC$@$x,ȁWCը^~{=9Pn(j>wD$p zΜ9&AC]]<_ǫǚf Kʕ+`v @` Y _AZ'~= hA)AƢ/}pD:v,Kwq &0EhZ|\VR{ANM17ٚC;).[5ηg:-ز׷_Lzq$㧥δ2 xc&n/ߵ_ -IqHH@#@  ]?: =>]*#a!eC1 9Р~GG?#a}L2$h@Q.Y޻w;!_ 7p$&,79[>йk)hו00וiRZ K] ]tXSBg`@_:  8$K0H0Q\,B=UMe|0++5NnlLLp[f)h9 mMg-Ͼ4OpT^ݙڑrtyX#gjeˑsş8 BëNo(*7ņ3X|P,+KjE{ߨeX!*VϾx}桃BwΫMr>4Rb\+777a9pZ45r뭷:UO?T^uӹ2j(6W4  l@,U1 ɝic]os xWkba|u  Vx3㢅6{N)V.I'##9qϟ/>7K<#5,X@֭[gOQ߉μ_$$1"FBJ) Mth ZLF@Int +RKfʂ rIշKoHDEJJ|WD aO B v˶#erI31 /ɒgKZkf)xp*)ilE ,d7L~t_fYٲxڮn4lbZ\.hp,|C?4UgU{_v W^-8W0! @?СCԓ+--5dIwJ~~~ݙv̸|= X4~X/.F$@NuI)ݽ=fyx(s yJ\*#0 @5=zTEi)hΟ{Oc5>Y k,̙(#2<[F$44ё3qaD2teDGg&`~ z2mx)Y O@sɫ rUc;{$"\`H~& `{ hRyLT~P6(D5: nt\RNdΜ92b9qZKo_~Yu9o<_Rղc5BSC-6I&G}d:Æ sbMδ2 1<߰ز_ ׶5)|E'*Xg?Cδo''*$\%d_b(># #UA8~xy΄M6 L4Z4H^^|'r1ӌ$4328hlɎ۞'PZ'{kKԌW+XFguqZ3!s$"K iH褁Au .hRY$y4`p l.3m_^b+,rEj?^k7;gи4q9}J8(wzt$d/Y,Y1'$@A+->> wy`immU&$${ xɮX?^.(nH:r4 (=:bيLMr?p4~po CY[ڻltq KEųf@` K]NK'ŝ@CtDd&4o@VV*@w#}³J]؁O= 9 8=FsΕj"x+rZuၴ_|EZmϯ;w@Da3BM?mI'  5vɋ`s9 wϒH~c p=48R5+1c#0. x|)9f^]QuɋBqKO?J6 :|3UPE' 7`p"`퀁R0q` @&+.%:::tc\3=9.g㙉N6yӉkO˚6Υo_(a!q2T4$EJ}Hΐ0v|ټn80rHyWՁ~a%|wq|[>ptcV ٺuj vڥ#>3M׿UN!3Pfvt˳kFqTqukɛ-w^^`0Dhַ[nO?TP/,,;cmԨQrUW]%tե,{G?\T݋KNNӧ͞կ~n1ܙ݌yH`bZ&m'MFH,a1X'%/oO*[`ec1Hlm7VN. 'P4BsO[q,w)V6TV$Ep\=AR",rH SXo_Y7r, Zb  \6.[oh Yy1Y0󸿙ReU㕓Iy[_Z-M-)sw.5BFǪ. "_җb.P[[H355URRR$==]]7$8A…\IXTT.IB#  gHD`Jp9QW.孶;UMT(/mEezpj ~.Cǂ+Yz7@Z|ӈ3_Fd=BADuG2LnlH:z*yԹxVuwbY}LvJTkܝ]?Q~.n0*&xy`3<ݔ]ZZ/?&*~|U7"WWZl&ɉ-='?0,k@HXk,M{'p8Lyx&d;mBp5񻃫W進'mvH3IaI1pre#EPlzeN!//s!XXto]]f^etHȠ;u $66@7  ns}(KE$/ yKU&riCY {G̕fJ=@$Y^5yꩧTi&w%tI_蜜. *n(k\k:[şFqI1/#3ͬH\O@P 6`7;QP&M@stL1S ,7Z5#B7ϴ7\('"BYd SVmk4!N ^:RbB,d@{U 3w-E+gXB!D Q#,YkxLRxjˈp3a7˦Ćя7̣=;{{ ǽ;)ttӈJ(&o۩i #g0&`L@C`ddkۨ(ߗbHqzF,E +[EK`W.ÿksИ}ya)tKJNpȕ`L)=bJJJoJ3Z[[i׮]cQhheLD&iWC7SQgU-eRDG.fKɣpdP> ]~MdL?1/ee7+!*Dnp!h`$ eJ=b oB%F`L '082JۏVѶcU408b0T!j9wR*e2& n` 1N&L1]faKҚ\s&&G)[kӦM鱗2:t$hx'l)eN! Vjö%SXpGUG8),A6@྾0&pEgC__dm++ov51`tg P<,qbNl4 :C{]n~y?/`L a85*8UJikVNyij+"e["fx'`v!+2ZIKEX(/Uͪİx )lY9`%vm 32kmêS}ͥR\RM.)1&/t`L 0C^rl1|]JYIQ:'ӍM"!h,f6F3&`.|B@apt8l)7 Z+Y47vɼ 0p{A]zAÙ3grsǍsZ|v5 wHKch%̰8Z' b6L 0&k-`,62Z5v@L Dsg`=WU͡yYy8 0&`TPiMd0yi9 al J8 0%xxkG';jM"XM?qEp>4I>e:eee,hpok`'yix0$n(ꬳlgzZ$wyqi7,ϡ_x ( f@&foa&F:nX;饒ݘG)D&`dó!**`:zhǎj*)5U,L 0&`]}4Ll\\6o0o!I &I{xn(-rCiW:LkR a!2 2@&`L@]Xm@6q8h bu]/mL\ǧ >QR3CĬeѣٳ|M:y$~8Apw%HX 颋.?`L  37R9Z-aYl3&o_t-T u-pP|3.Ub&&ܓ N8A?uO% h}\)V%E!T4_,!DYՆcML DH<^Lu?H~LyhΤx P\0ND)s:mvN^OthC(!N0EϏG}nݪZ[;7˃>8N̠9H#HK/T;י`L D*\r,A!/K s`L@lmu~s=b@1vߒ&z#n/$n7z(Pa7otkma6[[$o>MCc#V=zvi.b_-Oȕԍ3 V"80&d biaUMN7A~$Z9͆x"wg-ʄA6"wͅCy6@3CA{ |b㮝teG$*D&D3 !AëJǏW*JҒ%Kd&p)A6H sZ hlD???K s`L &o pRFma~W W"N 3w$AÏc*((^0;JoTJ4&0MvI; 07!008BZhAn543+eʻx: :IeqD^Y`8dT\ۆwN]Ki1Px{8p (!88XO^ٵk*-Ν3 [vHrsY)3%`LDIn79guǒ:'ńy8KW;22F'Z)_Lha 0\x']Ro^XX sp8{ۛ›e{iKĠHk)FXp[A5k誫8Ϲ*&$.N]':˄ՆtF*{QrQg-!PLn)ҒC8 07&D5,hD*襒0Yy8 "76l_g\CkeZ[D+Vٖ7/_.鑟Ă/`C` j'kͮtdX y, 5s39H9M:S/ԴՔN׬B@'Drc :hy LBr:ZmBFbyWA'2$AG|[tO\k&I_t#vѮSKz+=&^ @i$f͎Hq>L xC%65EGR|[t $pd4B000 bni90& u͚^nz?:X-/5&<  ؉= od~{=jT>m7z6lp0~Zr5/m4ffP}ZsTa 0u ѡn/)1VKcL 0!z.*WO.!h$#T^~nK֭g0ꫯrO^{MޤbA0&N׶1]H.e~ Pek 8x'`#5&ޮO[+NHu%NQljL x =:ή]z~>9`DI; E&5 tgJeShpMq3Eә ̟HTfzBj0o- 0&,!pT){!3҂Iy8 XK+g}V:y;}K/ԬWVVү~+ 9lf`LR-WYRV{πK.ev 7p7 !(ۣĠH܍brb>NdLs.h4&$Id-bUO6ҎBj47|pÅ!nF&|0D5 ք+%k1L 0W',~b5s"y8 BW^y0 a֭R4Tf\\X{ܲe m޼ f]wK&`yu5: 5`@ྉ`#CggN3#6&Sr`L{-R&22bWosKgPlkh-ߤw^,N'khLB[3o!G7NBUdqX`L H]g5y%vcvnM 88x3=g?7??N8#f@믿u`L 0s D18|TV゘  R<=v!j0&Cs6PZ(5ƈ3O%` –^n W]]=.+S# >>^ZB&jhh9V\ɝH&Bԅ7@iOc⋋9j1Z5$в)4+:|\L ؗ̉^Ko,UڵX0%6י`LC{iƍ:y 0&%#-n0oxH %F>a`Z;ek `?)y x-a5>I`*K۪tgL }QI=:\ :7ߤ>a~;5kL 3(/:]KBpJ7(3PuajI7sc3GǠ9U?, aM?яk_TXXH_BHHH01R+whNަ9'b=#@0k0.[7̏͢`?V[˕cD/":yNTPmK7uQpFSXHpS 0&<@Ig=:R UiL.`rÆ R4999\꿀5IL 0&"pI*ϗ.^0Ѫcm904R.I`COHɾkwK= 0N=سgKj?5[̠9Hc=FvjCww7=3kgu&ܘC̍(MRo:- 6tV 914ad!2&l<܈, `L{tH#g{ _6{~R+ݻ\{&pIzN8lrP忳r E +R|PP$l`k θ |NO#+(\yZ;Gώ?h,W"|;r`L{ 8E[oiYƦ΀xO~B=T&0w&|."y/@7̏˒cmj1^OvJ񥒯hbX7ɔhS|0`L 0&k$R[(e4&`L x tӺI~SN}Í+Ь,ױNT>,6rcU"KpK]_%ip"`Aႆ]ui^^ͤ+--jjjl. `L}-ż,)=uNWў[^RLop-uϊɐ\U|. 0&`D`ޙ-/ݮ^3tuuQuuԿ> r-}Βқ);;s2&pf-DK;op‚)9&T1N ?_DZ:(8")#>^axx`! u. x;jeXKeEH c5^`z rC`I↹éQWŋf?9&`_ID'Q?ʗgL 0&ܛ@UO+=}ߊH f';v+Vz.,3\s5Aӧs/[gM&P@p-K5%,n/TR}>!lz2IAB`>A)J.}}}q*. xՄG4F’ *YY_(IL x(LHuSPP@ GN:sN>#`L4`B^^Kƍ}v?96%%&O&! ;%a pQq 6Wb07pK0nEZ<`L 0"a1:^XisimJbNd 4ST|ɢ"$iСCO##Zb_\Dx 0S#ۙ 9Gh_s)iQSLM%RD)IBpzCvxɂ8`L 0&\rzbͦEp"p j:6l@6m"LnINYu]4|z嗩Pc*++l>^aL 0&HEUTPj)ϹM˧Xua Y ́ x  jTkO- uy;}3Ȣs%[*}Fc5期&,[L>~$;Xbbb miiJyMCfffe]暤VL Ȁ(upK%Ↄ-=*o 0&C |uڦ-o-&?_ʱ` VnI A`@5c ~Ng*6k)]Xh𜖟X͆1bYK? A~ؘ YOK?XJHH~Hkjj2A?ҏۃ7 0'"%N17ͧ .%"ĶR , h8e. 0&OhD' >ؠ0cYx?p(>H|>Eb`oK諐-5&aldfDs3Oba ,c98>\oOn#NU)r7uGL Mψ1dϡ~<݋A,E6[n2A"?ܿ=>;O<0:L+\M(\(&J'zM4?:V 8 {DO U牢atcbrx\}v}m `pG|Qqy ػN{o۫iɡ7|^yz-kn6Ic3&d0ixVс2:ZIBuFz"BvxpKq5ŴTQSzsL 0&gO|H ,u6}+cbNd$lOw| .RN |.&~a]A7N9jTPAA>QNw$3&`LmmUƒsc&]S)D&h"5@KIIs `L 8@H:*k (64X,`A2(^l&<}Cr-ʢYy8ErB3b7W32XvNo"̓fဗXi`!.7vI8O0@EEEyfڴi-]nwح\0P&=❹kMpPXp8QK >-0l)"K94'\dL 0&ީW̞!XjUD&?['**Jj;Tp!OX3_HG>t*32]}3~&5TA \odž/ 5n/#1:Dv Wwzd,pps֚kc1#z.>8`(}b槼Yuچ{LL\3I,Lп&DYHH$dpֻD9J\^6,OX}Oג#[n\ڐk {v :Kඣ6nh*UT1'H7N\HÃt [+CP+4 tїRDYaVu*. 0&R{_+>JXzx3ҡv(++sjx25ǩ%+^A7 !..u 9)osXwkfNJV7;HXg75|m} +wk a&2񬾐F}t9>qg޾o x###%x.ǞiiZؔ]FɊy) 3/o Ȁ焒x\p`pM{Hާ7i\):ڻ `gPc2r5.)hPa\ƶmt PFNNdN:E4sǎH˖-ScŕF{ &L"1WxC¡ *1:Z*z 3oML)I',Ip`L 0&J:)fK@ :3s"p kb EJ:;x 0&aa4U jN>;ق0xfg٭\`P Ⱃ:Db}xRhQ|bNt̶>Oe ?<9/4ص壏> ;C3;vcѢE4ydz뭷47'|"ͩFp. s"IK{xVa!n!Y8}D(訑?P?͈N14+:E=|`L 0& hG}@Cc#5JQjv p12i$*//jk_~4Țbs=9gl `L 0GISPyA?:<.inv3簔0a05m!Óܩ5mۆH]I³]}'ڢM|R?N PܸkEm0vA]K.L^n(F=*YJu |pA2i, l8"DEQZaplX*e# wpK! >YL 0&}ϤrS`!77Wmheɒ%{)m[+ֶLz& ~'k Q~{FP׮jGp}&|^EӔD G-8ʜ cL 0&; gzu}}EL]ijkشi;r[n%/~azg _L 0&N ߏ0^Rh1rY  cxkDz뭷t,%XfN111}L 0&N ,HXLrz=<x"0dk |l~ zC¿mQl4w `3иsk朳C\\fIe`h^Eb1& ?VW~i ^/=`3D6%(W 0 R,)Ρ>!nX8ϯa%qsa0!6=RSi9r32&p" 5ldakK1/'2W%8~;_?Ӯ],*& G?.Ȣ83`L 0w&02:FbiQuwҐ0@ 4kRf{Hº-ꢆ4Y8u@ Z8L j?NX4ր|SPx'}E?a&((BC(?">{Gޯ= jKgҠ _>պqq׀-xpm< {\R?mYl*t5}pL5,6f(}j,6v.SǶq[R;gli:D_~4ѠzQ<ː7==MFwج/ 0&J`zdu?_TO* '{p|?uxUšOf\cmS%x0\! nN{K_98: il y5s3 c,jܻljTaU* ֕8ৈ.mw\[o $D}JTz"Lg,}4|cfȰ%eƌo}Nca2'4lwl%0+б>b$nܹS19_5{dUGok1{n|(OR.n PQO=-:Fo|:MqtAK AєO9!-bByAc=Fr,oSnntѢE:_Pc^yӟϚz֮]k͡:`Vbss>K7`Yۇ1϶tM7Z |tqtu\)s}s.PjPH5y_駟g*Ç~HMGW^m4 \p=sf7^x&.aŊ6ZYSxN7c~_I:;wKNjNq9BzPe) wf`jllD'$g?m۶-\s%\r-EHǮYr _.G>wޡ%KțFGdBcҤIҵvQ,X@XG5E!99J`L Xexs):  J j[Eq'()ij5@\Y Əpѳcl4F'A\:fF\CۺH"bw ίV K/D^z)-[̨u+XUsʻV7: nl\0o@;&T7wӇ3 ~bZO~}Y>c%wWn,Y(YU:wGx FJUu[ 0D-Ԯr SovWvs:`C{tNJJ r`Lr=#]5t :@m9*vC:+CB{02rClj)0&|%/Q_ݻWpwӆ l,gL 0& ߘ`*uS %{>Q.uܬWq&XT݆zl1wN]Ka 5p$t]>Qw[Vv1a/ܰ\YFu5ˆJQW*e CB]]kcQt>ZzJMM5tljJCWr:`L 0o'0EǻkxEH yyVk(b2/":G*aL6&̡1| ;} r\IۼdL 0&*Sv~k TZES",?>~5ujQg6R]LaӦMF}Ü'ޅ@IDAT<,^Md7M<,~88&&FtQER|ШM?nj\KSO=T=ܣﴴ4ҷbiX ~bWcwC_ (p)4'p _J HQ,CČp3fct1}6F3+$7+$G:+ T?;Q@`4 lV\ʵ5k*LgΜѴn#BliHJJr77-ToB@\e~?(%f>KvK,_4uҕ@S"(%$SZ f}Q<߃-I1f a\w'xB}\pesn?AԦ]ͳ>zl򭈲 Jv]ϟo󯤻˧1q!(5V^,XH7NZ^ BɝwIׯjzvvwK sWx߲Z ޣn=vqs-g0+ /l=uY]]y.XSbL 0&`uc,hw3G =0n1Do OѶJMF_3脪.zowŧ~}~i:;⹢?挺x9 WXÏ @DVJ,p!4A:&yuVMujkk5 1 ,ďG~\uǠt@\?%L\.pBJOO7  G4ŢВ@VMF*U)CllA;t[322뮳Վ_vjeZC RݍT^Kb )hn(27S|P$M47&`?ḽ=APѡ?p{A̍7jo:u=++]%[% XB9F5L+fXt=3J׋멟&%yx~͞u@>- 9kD'jsΜ9*QW x='.rWTqǕ*em>YXKѓ+eisUF}NR!U !B\dG-,)B3U)tL 0&klha<y_8&x?S0֛BP?3Cm9g蛵82Q%tL Ȍro "mmmfO`dΤ8U0~ܪe$DP\Dٽ*z{914tq.ʳ>+us[aV!Nʤ?/P0U-mKi3uvάvx 0'KS#SJk:*ꨣS"V4ӘM7t➦KS"Xfˁ :zaȮlծw%NAbB478LCb W< giwTw ʃ6em\Hi*U+1/"aazxINw 'nQQK =7 0&ܛ@{m3Lab_x`EK_j(*`5U{"[ž)XBLVq**[X҂!fg:|;-D Viߩߺd=cmt~wf}'#E]È9P`?S@( w,U9;J_Ԟl:s͈N?=o3&`%eL4~2xe6}S< g`N Gk֬m۶iξe4hh `L 0FF O5 ߷E41~8&Z:~u &;%cySѵ2ms*KJnxȢ jXՁS!:<6.ϡ}Ul*ES(ok[Wip׹999ܘ-92$O>1' sҡ_}{nw(L&4W-pt{"}(5.fdQpSn3G6,"c2HVNuS1bWUt7iV >r)GbJd%A^~) :zcҀ~`*K%943:]1$EMv6z~Q덤 ,ݺ*\)j-֛^sjaai(6 xkz3k֕;d^ܑ<@ twyGM>:3&D\v/A&v.(BCQVjYc,Fe('?mQl&d'(qt",4L! ޝu0t<\A 0_Fї*ͮLD|븒7蔑h $v;wF 煯c|]P3rCnnm- ċ9fb}5efffW͍cB K9 Sj^.Ȣ nrx\´<"L# P:4tڽ 张FBA“(;"AXuH$ %/ )[ROCc#6ChjT -",uݰNQ`r]N?8_L²vh@ρO|$6d.RfR/M5vx?'{Ieѯg}%86sg^z fwG}D| ]pJiiiNgzo[vYIFq<8o BXvAa 5y7g@qr̙*G FO aMhlc=082|oQ# :h[W:UK)%&szpg1ĉ&'),2WLTTThJɐ߯ɇ+Vl˗/PYY閂tȳD`jVDil)[ӳlJujwwKB̠322FۏUfYj0$iQR+9' ஢J}ٺm>Q>4)<^DfyH&Ks T4ӻhgcAGk̋(MȀ‡އʬ:vl,ߴ@:X}|TYK{->Gp~ViM9+hut~ѷ"m`/4ڿLXA+ȏ J8ҷ62e:uԪFln `L 8XN6eF[{qLvĀ%,)sp 3xeЯ.|?8sPB3b|4<"v5Lhb4fS9[HHdis‚)I4sR<avmZOϿbL XN⳥( e0 DtZ9sD94wfhF%ӴT.!Qr2/ŽZz:bxMq/\:M_4H/:`;hRoQiR#w ՆNQpg j覧 >ӇɫhN햩,gfnB`dlXd%T&Ϡf\n&Lt gp#`L ؓ@PN[`2[>Qbp]n&i%6)o&0;gՌɲO?WF\KӸvƅ\`pK111% {S5ۥŠ;"mqo222 eG$ zz9mdvJ@bcc5n'vIWVT[X[+ֶ}|Im3X¢,TJ\ZIœʤDibɊ9K6|7.]$3S$qDu[q0g;R. ڀũ3a%GZ[N O f23eAӤx۔ i{}mfr~}_4?6nL 7y g`B?!Sa}\kZxb 3&`L \$`Ųv_ aIx!5  渦V\L1dY˯D͉VkL]eGS/ [oif$lk-̀>5%g1qp, T,!h"mf.5}Ƈ~(U(ao42W^jUKUrИun˗f gFh| `&JD 1؋08:Leb೤S ,a}6J烘arD$pX;GlXG\'>Gh6c29$>n&,2Ԙa>W/N)Yx Y*8ZAGUESlw2?L]C`LM-/4ә`L 0&ܔ&X)kVj1  pOSӔ-(ѝgӟ?,0\r/RyYW'NӧY .㩧Ҥ${E\c3{_Q= 0+ KCp?JiAr-o 0![yb^MKrh^DB]9xtUGMT;x=ŒѺ<,uh%3gr/([,Bt?6A.v6цtǾF ^ j}TIKMet&q}Yk7 0&>|~y m9RIC3ίI.̥t!p0>g)m4M׮Ja>42bɼ(B18,,L^t5SwrZ\?0YXE K3G˚x[z~\X>{&Xz<[kpAC||Bax\gӧ)++K >aϟ/o[~:Y~~~t 7?YPP@_%q ̙3TUUf*W C&^)FF98( 3rh]eEig#u7@.eVl/b,E.nޖGl=o• fNM!,{8u-4ȏ:zt;,7VdoQg=*{%Y-Ƚa:HBBI0 cwEU,Y%\zݪ-3]ޙwE(\lD1ya_mM:_*Al>22>t brϛ~8j‹DgM%j_+{Fƹl#0RGĵA֊Tvhl[>&Bb;FdJ~\%C7d覴8-DRq[q&?7/xaoQPTo-p;8*IS%Ή9oU 2W+}/4Bi/_䢳Ws%S'_ >a_к,9INǏ+ |XjxQ_^s̑;TN~@?%RgBu< z-BJGy"L-[jz'⸱Q7`0@ PJoT@Dpx [qmy+ԱC K"^.?,1r~LV=DFKw*e^D0Y,[*gFTI#+jaf4dƈ7mԞƫ[0o>]?ɼW]d]F`F`"gzXGR&TޒBDbK$O\&XE  1a B/=/': ewHRָP (ykyQhM7t;F{{;θNu_^ \xp}$\ 1?u.oGinECwfbEV$ԂWۂjrƧgE.lG5\cAA^x<SJp|)+NRݎCz D8}XMDXrQ(0֖b>[1aj 樓`#J #&W!&|u] 7}Or"<^XyWK❘(I-/K!Ee>Ad 2Gd íI1;,z p0)65)Ԕ◔ d\wKbOc%y8#»л1q$?a]H}%vV (JК6# Y_G c/?z5GgF`FMQȩz:m`D` lNEnPi1AmXˤ}Obq:mw0}ggA 'K 9`+H ߹ UY[S3v\KR4ZTc3 r(uv\'ՆC?HY͞O8y-8pb] hJ@ĄTR`bgXs-!E[oݷo %mJӗ,Yri֭/A50;v%‚? 0MMM % C IIIxW m16P w`&0v@謼LDPYZQ'&TC[+Dd"W\=3BGGh<O5_e&2 Dd Hr2H%1V6.&cf7(_pC.w*OTBQ ؆:iEd,dkVY.Tl\\\?wQ ${}VUWX!=` A?Fj DzXx%$&zR7x%y#`N 枿9)œMF Fm_sORn C%)MoY/d2 /!Ui/Vˎb |\~Xt5 " q孕xT6wXqA~a Ga@RGcDx+e1V)bT:%OEB]r-HUnjE_-BFZM k _gF`UzBP+n$FIh6 R4-U\/sAoDMZ4oPs(5=f EҜXa/H`nxxX"s_ -uvU(_z/op೙R) > #4P~z8p'N@QQ&++ 7t4[) >{lu]R]ĉf$\]p۲tv]PyF-Rz4sJ:pe^%yCݓDU 1Bopu4\5^fj9M.o16X\ӎ$-LjH!B\Y>a=0#0GBiy1*T[}.nwHu󄧋;<]D[q]ڊcʫ8"HXH2O>wan3r^$ڊ#ܘtL׆odH8m zEshۊHRX4,RrAf`,2cp #`iHy Y<4cYA;_WZrD{Щ9.y#ޝ FgE(尙 '4%En:crFd\vWv}˅2òUGdW'C`ddL}spsR{EHR/@2ڇzY)FK ˢ2#&t#!X}T@p$QSqs\vHCV?_;=èңBOąDrd|RqX֍#!JdƙF`Em8Z-~a!Qޓ2D\%B܉n=CB5nH"!zȚopI~RRLJT: U=mM-AR޹BEB!Yl$ 6:&=rj2\iPQɑ]:/{эؓBpN1wdFH `J4M\ruwC闫c#= IPtvv:vG;%Buu5jjjD?OHII2\|;FR֔F":R #*sZ+_8RT/_;d!EIq\LjáRk!}') ">x1BHX)yR^:;HDc/]\qetܒ44fPڗ݃r~=_<9%½KAxC4Q0,TgL1`s>ڄlN|w[d3o@gcF` -Bj $Fe-se0A^+m4q6sm@[҈mlQ!ў0&Z%<$H EȈGF%JAnh"9PjJ4 Ac}JDO!9a#9"\3ozƨfcAfQe @j&@dBdMDRfp&k`onCc24G'giHE۔\Ǥ==ܤ-7 udE[{֦ӂԐ 7WwX9)Rmiľm+A<5֪ yP )Rh %u4+j& 2 wM^kD|J9BU'(גtp+m E%!S0=$AoE^LA^~UE-Ngo{u\c~q挋Y1#X1.:\*Ž:Y!eHGj@xMPS?Sق t͊Dpx [\㺹qcWw% c72rVe]U- sxAJ@? B!>%8VkQ+o`bnrN7bF Z[[&{'|{]cQO%[r~Wv{ꆓ4'͈Lw}mͳSf%5e3NhΏ?$y$[R'N;P`{Fo`-6 e"ӵX13ިP+3T#bF*$w~D*I@9ȋfW}!v5BJX^WgĹ m,\b*&H-y.߸F<-ְ4+$Bpȉ Xbea~YK'ޮ$2݊[1#0 $s .KK4q-9ۥ^ _*NC.Lg|<0U8PRn9Ar >_洖nl*"{KN*x UB-nQH]S@!+؜  9">+MH Ui@D__/hccWl2A k1O~bffj`&l+v)Vl#02y_&w] mk,X_V0#0j1uejZݽ0%(V$."|*i꒓ydEa aV:B9$JGضo1Kwԝ犐Dn $+EAfq۲ Ć 6|YC7:P؃B>HBvjfDB6Rj[+o''YJ 䯚n?msNZ![Iŕxh Dbs^(HSǘOO?4hn$BJݎ;^z /%>fFQNk2e$;YRׁ8y` (LȠ!&Lv`[}i|H IU'+łp 񴍉/ŹP(&)M!q4"%Ty:*#DȠގ _H\ܓDUYçG,bY61,X6Fg_Uҽ}r슘ix$cϞ8#0#, Ia4XkF-(q}Cln P{ΊýȦ5ΐ. ͽ ?+94wBH焒=Vƞ")yrŜd,HT^1; Ƃ^ *[=Qp̘$Cb${)wB,wwQa =-iR|?|Dp!RJ$#ySvX RP&08Swp'~nhW%"E'/SCq^C> r:=y"((V 7܀o111(//=ܣGygwYmΝ8wRRأM oFUGPcrР A<1iH og攔BƟ Sb+ɨ 9UK[}_t\H"LF$bg&٘%ldL{Շp\oic8\eEz`22gMQѠDڬ$+im=_$3'O19\efq݌#0 0 yIA"1L!bx̉J̰$!z[K 5͆{+R>6HRm PZ)k[+Z.!I@SH ƶ"'c~z* bs"Pԅ׿>nng5@d 2=ZQP$(2αiF[8zUyQC켠RFV,rW"MӉD b2n*!MNBÑ#GpS _rrr0k,I [~=~(y0#`t er#;$?)T[Dn1ӟC@$%$/'DpHpo @w=H$AIv' !>a. s @ %/ǒ{^Y5}mx))w6Ops+.ԍbMڜdGR><hncIn߿q>!ׁbl1#0vh@ z)acuzH<<Ðh@2-ZТy+TКOoFhPCDn #u7IJ3L* )j.p8Mt,$}y̡ѷ4g<©\#7 *bD6DsdDf@J b-Ҿzy'҂@c& @~ + ÞK(H úYC}CBB@ܜ!;E&hi1MAp yްaJ 20HWBccRî]-Ix(`Fps3y=,"RN J$; p,rjkr/!BBTA%'>iK1A⼹'#Wgcm z(NI 1ixhv6\Tǘ0,GZᩩk1+Y'jmV+iĒ+4w/JqtYT&r Yng[И1<=yyZc޽*+*|0Ej|k,uDEB.;4QZ Ndmzhs!ӕ[G~JE_KPm|1zr[J=}QNKFΏP*65&aQ/?{iihG"AΟ(}KIof`V.TtuaC[ qHul#@a\p!幄c#@sk_(TNh )4(lڵXh-1~>>[,j,; HAx2k &G+םv^ ' \ S 'Hng#P,aRcċ6PP ;ACC _oƂ d+'?UV(R EOc-s.!Ia[}>ktg6j?rR!UHJ̀*9 iz\SzFHXzJϢäoX`09>9'5ܑLh0EU#\D$Ю8d-}N^~y>zGS|B Aq6]{ꗦ9E* "41#>3L"4$F *;jg-$urš%˃BR{(E@IDAT,*A"#`bP/kVP(}Vӄ'/KA_]|~;gG@r .e.1CcQRc {DrT7x]u%3UGڪP?+ֆkk$/\~J )Æi+-@X7jD6S,A1#0FJO^fܰg] WWNúY4:.g#7^Sh@+IALng"\fkdN<H 3_"32/OhAsCc+6:appP\2)s u0#`yL¶UFOV\ t;x&(QZP:wۜz-NŒD!7ɟ w,LGVp^-*+SOy&? ^m-\qW"ܘ4PWkkkÆ ƛOJ#=DfP$RCNNG }7ySIo꥗^RNBU[BQaDGG+Uꄆ{4(׈f:m)i,y 0PJ N'.&!03%_(EQpӓÌ*kυ1T'H@J/Ιߘ"TQH˅@ܢφps5}|*Ų61A ::0݊da.)f ^`}:!,LdBCAAJi; ؒ[͗,ƆaAf g/߾ƛ٫zjV"gu~F甮dm=p}Tcun8ra[d?v 0L䅩@^Vk\`VDORG['e~&mT[-U('&ϗRCDn&b?D~,s5½  "JL ;ヨy:hGyϻ-]/ߙTf$cחꀈ/@$qE>HaҤI(+0L׮]k4KkbΘ1cw{DeAyrI-=tYʫƃk!._23v@bDu.E8?y;27,JEV/Cü4lҊδfH"7D} \G"D$"bKI0>/C;@~}Ԟ[gwOL3i0OxM-ϲ>: pdf/5A7z~OΆ<8mR`HOO?ִ3|)>n êr5F`ٴ80ׁcg S4VP~Qss<ܔ#ɶJ,zRlz## *#1cuhW]TjAO`&{˵^ "@ u).|p(\7^IKX@8k^Ahhooǟg4uQSN1{Emţ^V[D(?}Ǯ bc@_Ouy&˛Q#;]Bq4S9.=<}'essxV>q3׈#`\; BrfYa.5)WJj#Gnf;뱾d7ګ5gr630ݖϊrZ ӤCThpDH-sx9sdus޼yP***P]]xYe͑ׯd"=mfhnnlߔwT8Z/*zR)v@K]letDS,̰9w/@K96'%kfi;#)ٚ NOnhR%Fj* 'fƤp|U{u71gr)޷a(T=bIVBAe j"tWoaB M?ȡC9 @T("E2ᠸ|x|m۶>,䆋hii/;w;T9FzB6AѯQi<a6F1|/G^dӋ6t H#1 _u3 7e5T oğkfο߶mû{)┬mPX%\8L,&,Dg"Ä=TէΠh)9([nnU UW]Ц:IB&4#d/U@XoDbXH@e8'uqrQxG2W!şeZ▼lh1mlp,I*/򇄄Ⱦ̐9Y@ lv0}wY 5bcc%ʼnHVژ*@j $i?  ώr?=gnksNIrAn\xYvJm ]nS^tcfb̫Cf+.+$pF^+O4^$"qnˇN`B0KG?jػw+Ac=իW+]F;/XK/*z\'l#L$Y l=#@}םj #CaPĖGnɓ'"-)[0 Xg@{R9!wtl }CbAk[ф8>?QgC5qOC BG!}hhT2x@o޼y"]yǺvHUYEEEEH׎;&<;z ղj! sڢpOi<,$ KS&?4l%[k3GY#ڷ2Pac|~G̲Jgn'M\-iAm*umux,qoԀ()ZDq?[kUsZA;} , ~bTaI ̤@wR0ow$brlPepE[NwiC֪wBSz'0FE8WJYiE ԁ.3!E"3=nu< LwlkHj6KW~cR# sڄ!Y_|4`ܲe$}HPEO7>>[-v@ߠx7YGL1#0 BC:U' mSRMVLEr|CrO8~Pl0lI=8*ZP 7f&BaE9%Cu8V҄s*1;5b4zѤy>Xz!.qvF .kiBI2Pfc*5\@TT4iM~Bya&Jx J_LL6 ggrI,HHUSmd0JwHY@~]?],z&*71/l‘V _OĆyiXd]CHuN 4bsMjUԔ[!*yFrexkYUy13 B<0b Dd=T6F0Ѡ0"03%N0Խ@oąkD MGmh$'㦚%"oK^f< v 6؃/+IX0(' 3B,eh5EC'o=~]딶ݫ #.DG<ԈtF }d۱cJ3P!")(ŧ~ 349HaNYr"ZjljG@ 칊9!+؀fC6MhFx㩤U~7GP4et媝X>ׄs6e>j ;qw,NT}F@9OesAa4#@e>ky@?cT,:۸Mϊ*==6V0DqLl#L4?#ziۚduYL*G &Ic EWkРlYYY%UL</Ҹ*D]]&fE6ݎ "J|| C sIJ4@wЄ%$M1W,` |[E)&TQ{Poh"go e-x0n!|߽[cG?,Ș,(ںѪ4sHNY9yOXjvӓ0g00h-im R8 W,#`d%b_#xjR!9/#0ANܰ('܈I,eLx_NnsC "`21cR8gN^QSrfv.h{ x)oɗ#-Na|in,-jBmNdULȳ:4`ydE³a`2mK)R㐙 fyR7A ʄrA]aI/B //o1}tȌ!& ڦNUc:꫱j*BώL#p믗{% "CʤFa2I%ͱ Cͥ zH Ƶq<2=IJR0z~0S\ 2d݊F?}\  &*8+4-?NZfKMm0Ð 侶  !Dt |vy_N0Q .K+['3!cjz#/Ww<2u5H=Mz 1({!קLA$BCCrG(Ip⚮1[A(z-Il!8+Έ A!}HAc8/#X3oB:Kv~Ψn4v*}E8`_^;zž\_N(mYbv"\E#""BN5G}PBz~!U!WR,0 tww[lBڣ|YР|LCicҶ+gǜd. ZIZ>9<_u֍'|?Tmmmк_]UY.TN;hGaDfPT\3uNh={UT>22R%}}S+ܯV5*)2Ld""lAckVl?{P׆g^7Uv;uQ[MXeݟ.=l>Htv ɓ$P-W c)VTdQB6yߪ"N>-G_z%ëw |?.1 +[Aqn_"Z9!= PW7ڿjN7;_؛{l?QSexxtDFPRمB-jz+Nv׊>S^c 1>锫?̠@x]ZZH-) }uuBAYYY*H ei!,*"ٗ k(%&&*vͺSp{n 1g`H]wy|<]*zD|sxf5`2: ˧Ǚ3'$;@a}^|>yt iw(#p{OS'/W9LfpO}b ?JXF~򓟨W kBHhcG}u_?K|;țRC[*gɓCxfc"6q*@sPYYX@D{3f4PXAAA%c*h9 \FeE y}[ QADɤ\JCww7***oRpg x42[x?Zdg@pu"@`)|%U4]%Hg&"3, ]cw `s` 4Q|Vq:I1i]jݗ 6HA2PvUU3244$P?0nVоˆ?Ieoꫯ1OH' <5Yzz:}YjF`/addԨ.2! qaBC7)vN cJ\0Ri7J~ BShBV><%_Y͵yg~t&}RQRtq iX=3CARѶlmý8^0eRSIrsuLPX`C`JbmĈs 9"T#@DGGK@o>\yҾlܸQtZ9ݻwcŊ:'z{wC-&uEvMD(PXXXv)oAsF% q,_\=%>UjժUq^~"J燧HW9#䃟2ol:VJ Bu5`.}[M{(y"I`m? D'-Жnχy#* 2>:9)*Р ;OZQx4c5\]l{fK3RrBe nfV+**wnv2]9s&^{5IOс=F2ւLfP[F`07DyQ1ɣ|ddi4la\Q[Z`~ɤ7&PkfӖ!p/al('>={^Ǜ;PҩS~r.|YyLY q>!x$c%_[&3mӓ1 67P6B ۵k>sš;v8tP̴4뙨/uWW>j& \;C2sWWߡZT(+#PDADj.Çdzcҥΰsc\yJ]%U-3> m9uy:"5DžSč̠5QX ]vQ?oI;N4K+L*υ ׊bhlDk. YZTkc-|  9vs36Un)ۼy@I?),ǎq;VQu1#0}!_br()2N;A؎ q6@!XI㎎]7 {恛rpm,lgGip;UUhdpW5H ϊT:oM>sR$f$J&WXUWN_@z77-NC(> C;sύ_&֮]+{hdd6mU6Mmm <&id@whLaoLq III2eN]]ȩ8Or)Ǩٳg4г{Wq7)96l"(۵^kBrG3W#SyQw oYqR"<"X}cm'!TzUן ksw1ݼ(8SzlSB1c+h|9= E8Z۾xrםi;~_)Ag! *u]*ǚhIDh/@jǠ$#0s"l.fbPtsаy9uz3 -t'B[潋ybٚiJtrKMk kgʸ頉O8WM_+7?AAz`4½ 騐oDZ2$N޲ro1Sq%9>r|I$] +ZtAN]+3 *ÙEI*Ν:K{K,AHH% ҂GJyf<}h_G|Ɂ$99DUU  |csZBhzhRSS#1CrɸJsRe(98-Og|g @ aFFP* *'F ƥ BaP p|uS|YPի[q3OξށU1v:1)ND|@Ƞw.Ef]rhmB)ɜl4cӦM'4 .կy`F37y>f0L1\8B`*)zsjh Ah%VNxQ"V9lɲS#L"4xRVb-umP+rp>8dA+ ;kh|IHIBGDx؊}WաŘ4)KVmG8Oa. Ӑ#T.a>p`= @EYGl=^Y)1xֹ;V >|^z%<#hmB!/?KABCC!y5R1TQ5ig[oIYZZ*%~&ahE&shR`KC[( A媫;#Fl8xNbz|, /"H"AO9wSpBg{7Jj䢿PxZϾ92BN /O1ti֗EڛmqU SNd|NiRi R3 ^^^͠l===ㇷr }Qy`F0!^xCjA~NTY@ywIS};W̎U/o[1dO. Q!hh>jkҧ3$>Mƽ_>3>^fM\E?{&GqmNڜVڕvsBaI.6`1\u6`,1( $vVaAڜ뷹MI;3o=OLwWUWwsJmG1bBoQ p HeECO :Q:O%SeYIN43Ø,6DFɽW͑eԻ{xe eE$S?˺iI+!@ XR__ng9%<]b=#/ڵK,cey睧n(g4o D {Q-Bb/: \r%nS{u1 '+2Nʫ压JQDc#Os?y=Y] ;Z˽SV vbPBL|򙲣^>Y%k0")}ډi K7o00I>C9PʭuSi|8Ȍ|>k)h &o|r;c$@$@!H G6'*"05dW:mi,lTyR\^C[W,i 0L?EZ?oFaYYshw)r'IƝZ(Nt{ n%t*f0+D+0*U1L)/aԴȎC֥ R4Ԣte7ʲx. ȳ>+O>/8{/8Jg,BssfV)l,Po[{}yNOɓ' 6]AԀ ѣ榸حz& .W>=K̠jW{}*N~CHq)āJq帇w*_p\1f&;3] %ڻ!-)Fb"}>]c2:,-Aeo2nthMj. !g `${Vσ'u!aʕ3B> 8dŨQ&VtZp_pżQ'NWj*֡^GXi0Y5\),=͎HHT rdj L/J{|r#')cN` 20{-+HԣB"il_UFeMr9v pZ<)WV..jGlNں3蹅4LeNO#beFB$(i Er` @(((P0555ԤZ* + iff=eIHA<.vټNL0$+m/ \L8 o.'zZn9p̡Vk'&*GZ=68Jz<.9\%Oί^4EbŌ8[*7˶'bOCJB">IS*K2bߝfUo(b aSC+~9Gܹ'qQ.ɀKEetdY$_1&K!66֘dB6Uѣ   &P!5M`4OiR<:JUsy6='?ydPŴ .@XQ" s)aU H TP`? p^dTÆԾc, }[3׃O qj0 1ʪWKr(ɔ1<1){{e{Q ֖#K쬬;*L7prlR낢(;I*쬒,t)b#圜I[B6T֨m5xLoISdt:0D1Mx%w1pEyk˒C=$|jnŋ3SO #@IDATIW^- F6C$@$0ʏ;Sؕtf,{<_i*;N]OLpL),45d}*<3r@2222!HٴJN]/٩2W+q` CxñN$)t?4тHt lpALmL@qN|]*(ϲrb+]2]Y ޤ}QR Yjii din jT}"34[vJbmVL`!+%NF"C $EɼbuQ<ת:UC"r8ҡX>uEw:;ߒ"$7.E 6iUH{LⓁA:^% hbu $@$`r=^nە\b\h=$Df]-YS)?ҥrILqyHn!XӢX8-$%%Itth>:x2VIW*cv&C}uwEɍK'* %Aưmug|JG?N9'̍bcpNphA.hYY_५\Azjqu9=e (X9٠LcR|-DnZ`elg' 6nE7 "DID=p,l> mݽԪUWek G{maxr>>:\3WԵ=)oҘw.Pl,,͚hyx{;zTCt+j ʿ /~!`9 zW_ LlOwksZ{b"`ez |Nb_A(H.LXr>ĪO^zԐ:{YvD*iH X<{9:c2 XC`oeϖ{k6Jo?,I(u{\K@}Ygi}  NihoV耸==+]|gtbM}k]V0}|w# NR%p՝1&Af)n!eUz'HD\ xUv:ᬎzw.CV| 7$xE~'81VPs'؟=lcWHIQ6o%:Eemmmmî<Δ F~^OMMޛ`[0c>QGGtw[OfeeQaCn:i@$@$zĂ/^$qI?{ޖE,[Ku4_.֢~gxJH{rla.Q]9' d{ lXV)=G>ľS<UjӼt3J&&U_hA%` Є& ^DEĀ!t *G;ȃHHwN0>>w2'p@>:!&ok::rC?~=##Q2' EYI^״ stPtҜɒ(xE:/xk>"jX)eI^I0`y7{ߖ!QX?#ds %էG^d%f@Dp7,{QY81GOs4(h0MSf!`",G91Ixd[ @,iBXs;s/c/Ҽ$rоF $@$@!45C{ud%FUU銬#\M($@$@L$7Y%ݎWNq_mEu6:oSoܷyN$ @[D-%K_HNN*n$`[+dKs}C6`vwPР' V;(DŽek`9 &mH=qW KmްyЪ%O$ {t8_befqOL۶!Gsm\i=l\MkLھDݖm3}"rYg%-O?t$/+r}5y1  cK{T@!ΞQ`K"λQ~MPiN &+{ @]O<3Ž\ =迤ӛ';mP0x]նHqA~PYY)^xCؖ'lZ??nEwyGw\F47 ffW,ß?ѣGL1&C6Q_ TÔ;V-C}2֗&rdlQvv=GX/ !?ON}6W]&Oǣdxϱ\q7Cɓ'aC8 s,/FC4p!`9a1@__ m6>XD{뮻dgG*))2vX\y YSdۡr_wn؈(y@q'lwzVPP3es'7y?+Gafj==-9gM̊9!70(UNbZ0.cU9rB\KO039pm|[՘Q)fIH `r7%%k,acI{{W~G/n&7oq\,Jzz:-$@$`Swn g>"Q&:kLat( ŋeLb{)omxZnD.+Kx2k':O/-OLx|kCb?))I]Pe%I@S{")ql%]<(z%X08 a]K V@XK&vAOzIFEۛ¢yr͒ 2 }%wvωGI{ƍI||>}> / uW͖>/Պ2+0{N2R0O,lREЀbl8yP\2c G]^\sb Ɠxo\ *' n!U>n])hTfIBxi*`iT;'r@4Xv IkvPuCl;k>J )2k|'% )AiCr}\cdbaZpU! &LR0y9   CN dCy=$Mm;0$qQR fe͹lCWt W&VD o"OeKܩ#XR^\x'099OVtt:hBt( d|B uo=iA2sA7ls'LHFD ƀ%.+ lIKKvWYs ]H>yKGٮlC]c3I,#+FEIrYߥ-@lR|&Qb ΐ(2 ӣ3;;eHH@NZ\xI\+KG6,M`f۪O:mebF ?x^ۡXoq"ICnDp5@N :2\J,֟|.h82d< 4D :5{/LCܠ OŁO?CZ;{?]-j[/IBL<93HH41-9,Be|IHHF@V?Ɵ-ţ-=.Z9YE.14ߏmpŋ%/>i`;~ejj*ְLJА"<.r E!@ 4' &01 %Xqj7S0= g{q;zt,sm쐧>L% @1C $@$@$@$@ $L~ H[W呝Im}2b$+(LH̖c8:0h\%yze qbos7Iɸ$0zzzL /˲zj"@3uTOW<  /͕9c嗻ߔC']^xԐu|W[.+%W͗ё1.1kEъ&9LmW&DRUR(;uAS\iH$;l'H$0$Sj<-20yXG*rAqF ⓀD \p5b3p_Bk…+ 3Сw`PvG[zet|'.;i x̟U>LL$@$@zRdFÇ瞓;vVկ7ҟ~?3⵴ȺumΜ9PFvFD   Be",T^8At,lwȕccfIL8xҀl[JrTzf/-,Bo,I@].886!CQ54ءTg֕%pbi!/-A~69X0ybKgʵEM 6;O @)d0{b ͒H >S-o~vXڻlV6;(V:or񒝚` V;~')hÅHH|K !!A1#<"}Uq[[[mw}~kڞ߼y|__Wg{$@$@$@"7%ҋWߒ]MJ9+;N^"׍[(M.,t] #wcoZc]';x;e< $B |9~5 Qr7\Mx`Za?9 *< seo'+e^[+1d+B<# b328s@]lEMUݡ6_flR^\MlpL):\\KUvηuWۉC$@$@$Xe P1Q444=#g\ݙرc3hWWW˷-ɵ$  < I9 nWm].cr넳嬬RiC5",NY9\С'!IӘ5"\Ma{N2'f9l'HW-B-Pj-5o +"M9 HA cĪK3h%Y9˥ - ?IHH(9Qk`9\oRUUe7n[[8FuufPbԩ)UV 3h^{1뮻C$  0Ht,/X#'uDO<5R w(y;mE|n4>_2gWπ= ҩHx)+L޳ZZ-':I.|0`vZ0֓u"  |Ñ@ RV`J˰a6hV4m\: + rw<nX`eJ&:|ބ3M~LK$@$@{& s=weܹ2sLUY~lڴ\II̙3G??XBHHHx J7:3[.n,kJorQt"1ǖ|:d"L4.RDs{YlBYP gMΕ掕sCͪmJXnЬ8h.,znywCc[|FΞ?$/Y7{(O1 sɪ/xC&yC=$EEEVmw^}UC?3XF7!m60~m7iIHH/NiveDltRſ63'Kdqw.ySi"aHN[ǷGurIL WD6+.Y='ص(>\jqh<.txUI}4hH{CuC13HW`X۫a$Azs] *+Vs$/=A78 ? r,rg2h emb$7 -3&sBB`pa\Iw RQ2(*Bz{(R:}0Z>P *q5{ڤ_BQvaKv_)t966&  p@b`x62x-,Xƃ~Cr饗Zۙ2eK:9x𠽨;{[ZܰNzvl?tR;O#ʢyY˵cJL}Wu6[!?Ժ^^f?֨e64ye5o-fcw "Z9'B0z:9q (hp'IXB0@$0Zu]bSB.EСl<@ЧT"_{N$G2RvJ,kyIHHcxLII0`Asr`QB`wԩ~;vչj} /tȯ_" =EQXJhrY׳n+07]7;?)/$CN,v,))G|D\c>.U&s溂2&EN5Hu^ècHMcKG*OKKS,'AH`d x1ܪ0-1YiIr3$ QCNZܲtDEQ>wF$@IbT VAOz[Z3g͎*<%  xgvv73&{=K;'.-Ef]u5Wɱ%'tlg~l(-[="4VLs'NjH3Zu!%Yͫ[d'2@@$Xi>)@ϭ1@X ;{rirGbd3␲ i\  B9BF"0y@$` Sҽ.HInDdRNZ<%rU>Y%kCFIba|"|%I +z.'3   xׄeXc 3Tаs3=s39:Y  'x'%=wA./s+G7 7H`,N 3>ONLH,]flezJ8}lW}MYGkK6GߞtF'H{_xr0@$@[7@ʰ2K@i~dK]s9-2$&2EEggtuuɩ# xD+d fJ1 zwyV5Daa1g;`-wHH"? [?kph蔔W5̒Xwarr^yvdRqRh\7n ` g͕`ni@3jUX?] [^' c\ ϐ F 唔>,HΛQ('}osl w;-h†L <"D$@$@IKKe ?,+X=L&sεwc벂WxHHݽDwכU3 eIFtDl{7'|(C[02TRQu36&Bn_>Uu;#'zt0mĨ0ϩHt{aF&:b64Q$`pkY<*V_cHw\dROWZ9SNЧw'̀+ gxHH0wO+, }B(8rݙK?#h b߾}Vy7j;$@$΁ شw|mZq !1.'||R $Lw//-3#;tdli8,N]!E .Ә-%'D˳kʥi 3 &Kfrx#}2#9Vwv&H{JӢ2~/KmO I71: :qP)FEC+̇F,cN;6 'ɩ0_#c)ԘI 8c C&!pL%L& P'%`B%Yf&߻f,0.O gI`& G琁HF,5`p#Y^HH 0bbbL* <OvEEE1d*\p_~ &b{6NUO{n$FO}zPr~b\NzTIVD #pND/yKv4,]co<ryldDsƒO& S1Ҥ).&k:b"g1%!;֤P6O͗%Sua$ =C@v ` + j`  @@G"==]uAwc k %&&>cH&!G}TVZ%/i8<<\;<X'h{/K)..vH%^ikksp?{{/͙15`þ;xGl̃+!Bh288(pUk/#ӊ]5Kt**ZWDŊa~i'MpW,7kGu X#"OXު)LOYc[dkae2&^iK{mb{ ,Zoʀ6.ߝpD)zΟ߶ 2c`.cYg}rhu ض }}p~g&ngl x_mX7gNgJ 4 VA\{.O$@$[3's3/LzruɺuѣRSS}ϖ,]LMMU+WkVlYE $Y oA rrNcIp`+(J*I0,0B XhrL\>7_.'mh_#%)>rؽm' RK,6KtC9zp^sfEM8y{f`hP~ymisE(V.~ 7@ų@Owۛ(A w{VNq?S>;&X4>  &iXtc`4.KE$)uxey1 1 j1KR@|pxu &O,cƌ袋"v 0m?D]2Zx^Mq&4 J??9_)G@^lRyvub3jO 5dG[>fFqHuv|R3;h|91 i)~B1U $@$@$ Gvl|-`uK`[OO2hqc#C9477[oCWt~[^s2&0=H~+OX֞,?}>ÑeWG|e$.½dLZ#?s)+:Q)H#[mas=a|M-  6-WB!iQ\7y{7u :|LxcX ݲC`om~ ,c'd߱&ijȈpH^L◖&|I7SBxFJZFDh/m) R6.I|C 99Y]ܘ @ `P֑F"aP{:[>:('h (CȈ  fi0V_Mvr 48~d?2Xxʢ}H{u;{KbeZjN@hN/*V \8 1YWJVB(r\#fioWMOhoo?Cݒ4* 9|wLf_ƈ}&OA3:u\^o?3>KnpI:|0D  <C݂D' /䀩;<񿣕r /bM8@;g\0Az3J$@$@@1YC &H_qD9agMɹ=ek:&\V0KnD0[G偭/J@ӌrIHw'NR4l-IWnK9 81 @Q>[Fo_'[^4U R&C`K/\!p9@H4S,#Mf")2SYV   ܇ 1pR6{@؀g đ̫䵪{GA͍eRrh<&F-/qE(s;:Gb%)f!&iRU 3G{.7X$@$@!J``pHxcbK4CC/o>p2#w |A;D&1Y i'ꛞvp@(hgIHB&d2\PJ~B0}O.ΖKԕqMW|oӳkoOs] 5]/Hk,,(B-$%%yj]81׫w{~YWy0>Рc '-4]G SefΤpxa/Z pB`ӟ'* @7j땦PC߁AqY,F 97o{5kp (+ I$#@g~`Uqa56hkkN>(T\<:Fy:y&qoS!baB'~Lh;/!ѡ3DWri-“#E?Vzq=kъ#,%cetIN0ĨXe\X[KRw? 9r}\Ɍm/ZHkil{Yv48w^Jn" \-u"?qqd|x!S,1@[$e^HH@%084$m=&kwVFM6.CΝ^l>76J㢤ϫ0jg֫JH r)))0ÊTwr!p4 꿎jCJ+ZcJ  QY//׶VD }t #w]!E@HnV?6>PWo+b,\\qBO=G.]PE86В2RPPW6{:jGߐSڤv6Gv.]w$Eŧl0&BD o-r @(j&nit CʂwW ƲbdsUnJt3kȟ+ޗז3N ɫ;ec1ƤefZSvD@}a@IDAT q8 #c15R,ZОmZVLK 4ԙXp 0'OT˽}hW`[#Okeۡ_8{? u~ Ī)=m LpFFn $`T0o Fm!HH7.Vo:iXeHOOA&@A2;  kj[e!NVm%pթ gQNXtcgѤ\ q?Yp&X]L8b〤ymED)=K p $@$@$`F-RY\jb[ k= {,ĹF<2:(h2Ա̫侩JbAoD}vLY*Ywec#姳,q5ƾ1X["0yٲ$@$@ ye*.% X׷aHi;;!-,JȜÊwL3:s 4NLLT-6P`v 7%b֦_7  JuÙ- 4hbpZ^r.`|3q#/~,xviJe’2关%LY)TPu||䱊5i*g;&G;\ƏRE!eI[yuy1F& $@$`45a4, 9NHfky _,R<2mu-;.\@rC:%$m%q[[tww[ LHH9G5M4_߯n6QK#B^0XU# =^@dR?455 YF 4zXQ'rb.兊Z]M?4(:EV)Β+]iiHq1'V&L_)yk$O,N V k4f$@$@xO)O'xw 8yl.SBFR*f(+Ό=FThoo:d@dY| z__po01%e pNbʊ uM k':X=''t[X'׷%| '&Ŋ@oBYq'ɜ 30 |N/2+-KMR\(jyyg6%9_ϛ*ji-`Ovskjv \M qdzjA2ffI(h0haUk&[n=ĩ>>a%;;{/⋪9qO>}:l=4$$b"n f1xNB uvvzꞥ&aBc* |޹2CNlBY__I&eE{]] 9pׅew;!+AC~hNM0J.aH#XjHޕC)?,X?oŪ;awqdID@PN>[&/ VS'/DὖB^3 NA]'~yG_,Yħ5K'HH)qRI4 0`n%M2TDG 2%}m0. 襃[cbJ&`mΜ9VWXtaa;$sd*9Q>/*(]i+)n T f ~Z[[^ܱIa_W%` aJ|!T+&*?8=/TT4Uذ(kdSCOj-2@.qg2 ԘpW 02juRg3`0sϕO)>@]*?O)R\P\Lw2 ϖmOz\M7GY`. ?d1V ( % T[OC"1f$j'c p1YrDD?ؙ-W.,,VX~7~0W\DžїH[U;gFL,Ls+M #CĀIZ  Y/SǦˋ)cWۖyfI! S'͙X9)+nzUu6_U8bC&檟s$.q@5VR+:DcM1*\2\?A~S@$@F'@AZ+Y~iu%VŋW\kৼD,XXvzJK}̓: 'l\ynL˗-J\t59_姉`!h w|b;1j&9h`E܂*Ld12}X)!)lg.,,Ew=.,`Em@_lcǎ˗T-$Fqty3.gMɓ/.+"A芕 $@ h16-KۏyT(>A#2,\V̔o߮X? mWk|VHݐ?ƧK"r(SD!+a=xgTZVz9nt|{2>?.=*an , .4428 kơ9 5ɓ'e˖-p|R]]=7 e  ғb%‡FMŻ2IJXaO aK7&1N1Gcbb5r0BaB>`K ٳg[U.,jjj-;XZx5EgQm߾]χzY#(O'/r@vV;,rB\D斚gr "E!l X!L @_ W *;Vmt5NdD\,PFGcrŊkǶ+G7{,l K G ޭޥ1E(s!g $@$`4JefqL12cF˵ʗ ˻5;4&uJə$c'Pw3HDĿ Xh)bǛ/&^\iI@X(la\sREDE q;F*Zk2XEHNҤ\)KQ\)I̒H_dRy@L@$@f$@A[͢7oX3fվ;.JիW VX{Ι3Gj @(t|3/X(of$_Z} 09i$x$&NHq]R㈋dmf%!;#^k][` maCh]|]>aႂ4\WK|E Xw{)`oyHc+hF`uA0~ H&y`yӦ `8\㗜%C&䫛?Z?W`$@$_4_s߱c tN8a5Х &WVV&Np?aiM?˽+~e:\OOڗ_=Go[}et.Fƾ0I`\xȸ탒ar xwB"1c0nm6ƥ6r%d]WC^(99YOҐsȇ~ed' @LR-kdlm%fHg9ێ& &8 O=ՋҥKUD Dn%QK 2tժU}f7maqHHH dh 0 3o/LpȼmȒ/^,iiiبH\Ag|p+kctT,)Vl^P'EKahH?тHLOf^ee/2 ]vj aʔ)r뭷:pu;w}W/_n @VÒ ͩ1 s5KK>! \r;>+`.^*HKK%=R;auqt"5+( a0_; Sc@X0 );h0`֠O@,Z9#:zh:w'`Vw@싂,hx%@f4Qܹ7$c>y13Q矫118ƌIDM@hvhhz_hۿJSꜪs}8Uuzԩ_1amoA|Z<'^FId{&]-"/cǎ| s"K@ fH&).xuXcxTy[_óo镝ƿsmWN&i@)&φ  w=<X~9r$\5H@{64[N^z饐ṵr~"sĮ7z.\(k׮a7sT> zqIhԓ8<eϮ&2αVHc=Ao Fۘ%귂GccхY^ 8?41Q[߫.J{ Lp^:'׹YpjmIF)zi4xKLn"Mz Лz)nzgqYވsail43mX3Ai ʁnhp+:<7# h ȠO} k`zw̘1V@COh @@z㷪JC_@xM)D*|r+ !mC4| ?:-Kόz[6@O "@`  ^j!/YtIpzk H=Z =XSi@@ Y)ACPh0+)[/:&$*A $Hnsh$VMv/ۼk'cίG}Bn;!<D ga~@ Q4x,}-zK=crYz{3fX=]|i4l4c-ՅcCț  =TTTH[[ @]똽$@HM}Fk̐KRO@{NTC^c5Ý4Ċv (**3H +QI~C"׿u3fnAL=Dh^'Ox v 4"  5455IwwwtvTzCC/9 @RW@(*//'!u>an>l綊Fnhs[ G z*S^ vx$Q>d@gg̠csI{8`geeȠ :q4>Qh"C/ka$@@F{d^Oib  \̠|zbJv C~^_vWymbJKK#$X?/NV`o}[F$0cqԩ^z{{eP9kxbsW@@>]#s>BWӀ[A $@H]==3[*uۘ{yTW\ܶW@<7 pϾߞo.<''G>O~vuuI}}9kDVWW[ٳe֭h95Zرc{b=iꫭy&@@߃UUU`y5~lt%Hb$@qF9vhwŘ*4kpy}KmLۚ͜PiN@'=%!*@@C@Zv޽!CMhjkkQ h&;x2fO?-ڣØ1c ǏGQuy1  B@/P LP"P3 V+/ իWɓ';z-`HvzFRVq'7>e (F_oڋ%2iT<Sr251mF[@:9[@on?ȑ#)ɧ w8uT Mbɒ%rM7xE@H@k MMM1?Qq:i uD "vڐ`at5Ȕ)SdĈC}xuȑ#媫:ER:g~D ȏ^*pg'JQRA GG/"@ 4u &} Pv%/58˪cN>]nf# x'75TPұI M A $@Ν;g iߟ+W4e0|K瞳^}Uc^ *9~a#8-F@)h,F@1Ĕ7@P4hٳ(rN.?f%8yd&Z @@I RYo .ĞY livC$@kAoo`7h"c\UV[[[e۶mFP}=7:ƛVOz+5-Cg1#1Zs#]=an3NnrJX?@  $ާ 'MdKjPt@@ ezPMf Ar!'[#@xi&kԩS&.\h OaqFO|uƍQ/ b=:FMؕY^@{c^b)#eR_o o-OK 6\0Q3I@{,H @:АL@@R^@oŽLjw }%Ң$x(3o޼r_`rQ;vlD~k/̂VOLx&7rP~ xFJF$%=={YBeEy'NW_*GZS{.JIa^"y}89 eH@/82{I^  (O(E}>Ѯsrrq+4".VB >|8dY̕'{ںu' 'NaȫnǴ7G{"!@z h=q9WgB_o !k\AqB4O{g !$N  𯪪}r) z㢢BfHd8t萕tCEjjjBO<fa1{}0WjȉӬ\o2#H:=H[S_Pzh@@@BǗmkk_ZRS4% @ v/ZFh.$ic ,;{I<"}yyЮ]r)c8% =z+ȑ#,v9dy3*}sH ؤ:DzQd~y(3 #  `@/E j.Eg޴z< @@gg8V&`nf@CCCqIAfeٗE3"{Oݻ7l[l}]w%3f~ٯ`OGt==3i5i>7=Iᦆ?\pWK@?sxfVkLp~Nv_ pm#`ӑ 8Fl$ZA6'm"4  ).'Ԡ7'~h|zâ~6Fpv(}:ޞf3~ӧO|4oMiӦIuu>u ~Bmnn'|RʸqBvz1x;dVΝ;]Ĕ'SaMYu `HEAA Λ,-mWc#G`6c hRdOwW$R[C= v@@@ &{`yl@*F  8o;e\4Nk3M2EVX1`O=: /`]4UVɃ>hÙyfxMvxV A f`\22"/ǻHz ΏO@@X@oC}ĈƓovEÍr­&#k~:/ۻ k89s|0A?|{3]fn'N7xÜ5^Vϐ1@^^DۛH;aHj= TпDA`ȉhGj  kI>٤݈듷ϋa)4xB5 1ו @!77ܸMgwn//]T/^,yCC1D 2eVq~mYd5zZ`B\>YYYwj|})5 ho~|NmrY=%$sz~:9[Jgb5?'z,q.c`Ўꖬwi5YʭaoL&sm`@@ '$zʼQ5A/Eg^\ ^0_3 x{ܳF|Wr-SMM/ҍ.\(k׮X-..6b=ި=zoֆ,W'͎< Eb"2:u*44mfqر`+mw@V>;{؏ m s;$R@ic.MJKKŋcxbCwMtgA Kf;w1tYO@Z^I?EO@wϊMW &@@R@ \@=A5( ,M> HJ ~33fР֡'Nj#UH K/X)!F  wlqM \STTR2@  B@@Ћ-$@ 8/755EUH}"L4ȑ#͢'OSVlBfTb}cTEg3, ޽2Y;c o    x%ctorGWUUE:ewJ. 2s$A)"H@ t(Q q;' XH1RA    0@uuk5al3~xs!U>uuu!;{lb=C ̀:7!a!D)G#ீ,3@>t)@@@@T=zڵ˨?~\Ǝ Ygĉ!Μ={V{1imm .ɓ8p AgbEC.[@ cLgggy((({Sy#"@ R@@@@`!ٳ'd~ݻw6Ҹɤ :q/ ---R[[klΧROL'm ीJegg{%y!!BK 4$yR|@@@@ qƉiÆ F`9?k[[[ڛˆ#X&KSZ7o懚xWD{0ŋI5( Đ5>IMB [ۏ?+fۻȾ P,ot(}%!d 4-D@/K"   > |s ,V~O:SWW?}5Ӎ7hN{zaښOh/ [ni4aԨQ2Ď;޳W_m'YO~v'w5 :$ONyixb(+\?MnbB)<ѠO|lv=@^^hp @ MX   ^+6m:T=X"bSO- &ӭyĉ'Gy덾9sܹsny'dٲe{u{zzd͚5[o˭:hWgH!q%732H"]`ͦOz&3XklY1;HqC frYOk  h'CME( MA@@@,%w}'?co;wzH&N(GÇˑ#GD0p}yr19}hz駍^ƌc\?~=zT:;;CCM̛7/d}&HO Ht-WW/O :˧7ʣ+.G  ވe#E`пK}(@@@@G@|A* 8p@6l ! TĬԩSeY~߿?$A//]Tn6M/kL@ݓ@`>N4?c qraw@_p$@܆w@@@@|; /G}$7o_vK԰k.y饗6nf/kPJiii:V:'SQO~<,j՛zўR0i(H5EA@@@- wuۆc:%nD0aycƌ3DA : Aɓ% u=y3l@jGϹkɟ6Ul 03 "0̠5$@ڇw@@@@ wҧ'MdGYRx-8t -E{5}\A+t$%5AZ #KO@@@@@ iWyHB N5jCzz{i]ƂLB EEE2lذD} I/9雐      h+J)y5ŋu>dpO{bB+@ !-J#    X}ZoH\E̐¼lAb jfsbq/+=cSgp#@@=E@@@@:>}qqqX L.u] 1h/2MgH0~N8CB\ȭX@@@@bС&1*`(WNCMHfʒ|݋D{[&ve!3Dcu5@K2 -6D \4$W{QZ@@@@B@iԤh* Fq߸N/HNV͛g]O6\22|-OKJJ1{ERD 4@@@@@ sx#Ko-׷o>8,{ )Eeq\5s,2 =fRO 77WY:;;S3jB{h3oMO&ij;/9RSY$V%,F" !"&VB@@@@Hj"%IF̾'Οdk g:|wh0MAJ/hhjj/ +]/^+;*iw7w@/6^\ @h@#P@@@@RE@FLP(˖}HJCo -8JKKEH=)/|fE\7@/y    @ h~>bTDA{lvPM1XP՞6 f0W߶[xE%@@C     %%%[xJ.JJ_jB{+#utu^F?ʏ_@NԷQl )@@Ð<    4j$c@ ֐`CΘ{zoi[6B)@@CK@{hߝ(,,u @B$@@CZ     D%%%>DT0rssJwRjh/E~5a*V癓^U! ``@@@@6+@IDAT". @ :aÆ[CtnA\[۲,E;X rݏ4?mlE C!@SSW@@@@H@Nכq$@tRr 0(Cdefȕk\A^:\F{+D6Fh @@@@HmZ[H  N ̍qw5JE)ɵ$. Ru(  `p    D,8@ dggKUU[C@Q,!=_~^7{,6*Y H fW    $9{2ׁ#A0{kr WWLn7!͙2BQm @8"&J     dK6 | Ghkk8JXTT$FAN2T~ni0hQ23䎫.7Nw5TŠ; @<@$ \]]݀8| Yƌ/^smˠF+l,~LzzzB$!˘O7d^|BH|qQ{{;|o8ۨC|spsHtNvkbݐ̘A CB^'\k>ku/{H@XxەSھa$^R+>!Gꚥ|fgJMe̟Z-_?Q *@ En =3Vl]s^p޴4|7l8K<im9 ^8?Gr. ^ӻD|ΟUrJAбy!C@ U! }:D2\k{%;蓩 )+_     )O o"GA{?ؗ=+ A $Tr3@@@@K@o%%Li@B " 21*(( ;NrB`ȉX9hMRJΝnm5P}Rmv`See%]WA|nkkF:^0#c?Q)R0mN>mF%eDB{[!??B m;;y؇)//il [Kղ2k Dz>M%@ &N? ΔD@7כB E=D/b9 @qg `]l#{j]zL'F9Uے d/΋U6}"ɏup~^ yM^97^u=Ds{ν9pN(!]"-FXkkh>)>z@" $zw5X    i)=q'-J#@:/jO(  )T@@@@XtHX6e@ sCОth= 4@@@@@BHM@n»o3"77}F Zׄd    @j rC, @ho ࢽE$@`v    B@ /** DY( @fo Wz(܋5@DАe    @h7z3 zsJ" *r L7A" !R)C@@@@ rn|x#S=H+ P^w4X-#[B5h &r@?^ٳg@@@@%@7ہj x&m 6 IVVV7X  7@@@@@  F;P @ @aa1@3=@)@Y0ۅR!   @[[ET3g0wDR[ŋ!&!" iCC]Ƈ$~&|N !{<||gg9ioo}rhGKK/U ٝA ٹsY ]90cv0 B\b43    @B`{t,tRpڃS-~Nl[IZED'0 z6cQj{4A{fB{+]3t;O9񿝜D CN@@@@@H@vv1E^^^5Hҩ~Y_@ P$@@@@@@ VPZZjؐUZb͍xVDW!'g    i,PPP :@!+++=6d̄Π\233n 8}tww[;(++30pƐ6)))M ;.LzC_?%B9ldY!9E%:?&imm "'.LګBO@?#Y1UTTƫyF   qVesS">6AQ@okwߑ$]OoƐ#7łpc,8"D#ϔM8od&smAzӰY%mP:y4< hP|^lo8y&4@@|߯;ޣD5g˜#䏮 UT:v  '(ԭ" ==?_D٬h9% @"hH6B@@@lZ~V9ѯ|v5OAbkNN3c3@h]"  H{e[߅a p?%9 BOg~[^ qLqT/?m|fpm^@@Lcn ql__ ||B|nh,a<43 @X j1/^ >68'Ʊ-λ"{@8 G\F@@` l;Pq0Yg7z)+5'ū_#<o,?) o_wPzA~GE~SS}$7/$+n!9\FL { z+.. nhiiN!ZB˩$@H*P@@@ @wO">\3^+eW@8.:Y w?E$@T 33SʤJtH$ (,,4 !(B9@47$@@Hub.掘O+=&hױO@RO/~+G#ܡSM?yG @VVTTT4@ J:Xh ~ï_@ hH֥n   ` hn^c'Kzv7ƿI۳! @p EjO7 ! ^JKKeĈRRR"U6֠ 1B{ ! צ@@wa-w}1='ڝa17- @׷8kk]_b7!_@{F(((JNgd6A a/JH>Iρ#  @ 0 ]װu`gY׻dt^q G`Î=Śzz{v @: h/ [Í :pܠ:ą-a$@J*RC@@Hw!]ޠNSs-^kt @|uI,!@s1 <0zzzzxO{4A4(B_ @ j\ 5F@@F4f#[W CMރMF}@<` dhp< @ 0D=5G@@ ^2u}]R:DdPUU}}>/@L@p\Xvl fCW!D)@@C`  )GWwU]周g{P*LT @*4TA\.@@@ EhH   023c^iw?͔80T&VQo]7;v 3&Tp]2@@@HqiT@@)_o#cG玗>3.XӨBYىnv f%zhy    J  $@A^KFE\ۯx8jܺpra&IEd@ &*͌= A{7$:  $ZD?@@U$_]yӥ 7kвT_ݹ@I{s7_.ڻDI>2uLy @ |Heq^ԥ^V __zy۱   F`wnre[@@@ ٙ//}@9rNεt.d|3eLW)Æ p--3#Cy2kp;sЍ]:RtvLCr )o N@׊w}Ǿ WRʋ4    ъ>  @^N\92"K5?>%;-εJGWqcJjhR0E I$0yT<__&z͑zu2cD@@" !$VA@@]@{q݌@S~J91q7džfMkgKG3 ѧjL!  @hH8C@@@@ SV#!  A !B@@@ Eu]葊<SU,YI]'   %~[m.)ϖQRZWq/ @hH 6B@@ ^xw7cg[C*Z%.?vQ3    lNu> YI{e$Y >\/?XԷ~qg1iۏȺGWo\y@@@?tvuˏ^*vDWɈA @m;J  ز}{`{{{/?#j}1   `q`;ur><:L#$ v@@| fwu}Xol=,/@x@@H;xh*)vtuD"$ IH@@)):D,ƶl6   @J |T{V}x4k!p<&<6B,@@C!  @pN5ow}ݨ1oφ   @ >WUzŋ`c@` 4   $9麤p    :WUѡ'mp#K`A@@$8םtml  .\A  !8mAI@@@ [ϻ. =CO@@@tK ۻҝ#)%@@CJ5'A@@D UVfd· @@@dK 󲓝#ha0  D*0(U]oTE   N兒1u8Ws]2@L(@@I`j]0} A   @g\ 7KfMt1 4xNJ   Keʘ!_?)@@H5[;GiDѡH #z%5A@@ | &Ēn[4Y 59A@@Tz9! s릥* BV +oiE@@@Oo2N]>q{f5@@@ }2 gge^$%9Qm  ~ӳ۷o*pB!7ncǎə3gQ\f͚%W\qTf6B@@ Yn^0Ir3/ {V3Gwͣ԰R  (PQ'kϾ#N4%(/3.Wv]V@H>f?Tٳg{+6l_]C*N={/,˖-E   .GW+o:>``Ô2ɕkR!  J_'  )%PSY$󥣫[>:tVۍ}hr.7jp*  q̐[M6iO 2,433Y=@ @h@#8C:%]6$!++K2e1Bjkke޽[E^n9R*k  @~N̟Z.ե   @;GBH?΀~XJJJ".iAAAsd͚5*rJ#\A ϗK.D{9x֫j,Φ'ӊW@@@@@@@h*ak?~WQQ3Ʈk{ fXh 6LVZe,nmmm۶A F@@@ tttƍE8s466^(//YfW\!:G{ܳgQ:.A R0a̘1#*۷KZpIJ)    %`<60nܸx"li&k=aԩ@za⇾B   S@ds_]C N:e˲l2う<7z"@.RY|TWG6?/G,i46   A ?xrرdB_?cpႵyYCM,Xz[8z5   K_ fpKV^m|ϋ>H~@ o>(o@o,Ӟb fɈ@@@ CCɇ'ŋJ~4>|*N\Y{r[_ui@@@С&w3eee5\c 7C; {\E֭[g pUWYN>tww[YUTTu]'F*ihh'O!14ȯ~+czi @@@ !`<icUK[l}]w%3fz5 n*KﻙI]aùqp#`lRi{ y Nӫ$0f]pxr.[[gH{@36ƞ1x=CK|%ڣ= =;RL I$-X h5Ǝɦ=4I{_4`ԨQЀ~/9szmy@@@H al'ONu >0m46Nu .Amnn'|RF|  z+C3 ---!A CS)2}K Qۿ>LM?>C#"VvoHY: uttg哤MMMIo8|pH`=9ؓ&@@{Cdz7m'N275@@@ q4$:c:+O2EVX!"Uxz!@dz|] hp(Xd¹>Oi b@@@|8t萵ע,kJLo|*W&t {ѣXK%7#\W@@@h?dC=͜9SWrszr饗#<"b}7ސ%KEjvhniNF| mD   E@8v옕wEE5nBʬ#486Þ&L`ur]v_j/`khP=F@@@!@@C0(ҥKeŢ]744L; ~^ڪo*9Ą3 1sssYb ЧCJzCumDz 8 '`${@^ w]FlY)uzDo` 8Wq഑~~dVNhI8' V{4z* "!o(g?ӽ566! lnnNxՐL7w]h]z.PۃLiCe0JωV|,T=ڐc~h?0цDVo =1uTǚͺ h1kٜEV B@@@j4۟3L$2A8{g83Nbc̤!3PN5yB ۓO>)weܸqX\m$i@&)X`,}Kc)}Us$X$8maDN15 I0,oϹt4xhZԧ;4蘒d ;m? `x>9y}:a?jȭ[tO5#/gH/ y Nӫ$=gP8 ߀s!pg(8%q^,Ш{~+OCDwk,`FOXtX'Xm49V{l`H`[Kc}r(ۿsD^Pܿ2믗ӧXl{oY SL+VL: /`sUVɃ>7\:Y6@@@dhՋpBIi7L4}xw9OQ8-{bS@F1 ]@ vHY-Hm~ϥvR Dkbp>=m P{YedSO=Ы,z뭃nnRW9ss=qh/:t#1g f^)lȞ.]*/6o.CGeoi@ymCDo @@@ 蹟cɓts:aѲk.c`OΏ;6ly {8q}K}'F\gH   3!=FzMn:y饗B`+WFԏַi.\(k׮Vo-^$mxH   .4u(`^8tѽa$4IummU"kA g6T47ݳgOD w671^h03B'   @ 0ݬRn%7rҞ"5a!YΝ;Wn߮k̘1V@@@ /6$/@@@<hBAOx֭F}r׆-+"ڋ;EiܸqA6l뮻nq&u:kZ{1b54y   .ASSS}6tss3ģ;Q /)~/zk\P'OXYS  6HmmmH0CIIQRk}&@@@@ 8!/QvW 39s_{DS0fRYYi2h0CI{{1?BwI.$@@@ Аx{ԓn j7!CuiCKE~Xn馰ƺ|G-Zd1P>%KoodԨQ2@@@qfQƿMb`Ĉּ^A3鵐o}[=@ƚ &SN6a56ol5+Cnh$@@@]K욽F* N>m.E]ԋڣCiLhzqaƐ~%ug   o)zLsΕ~i.^䩧?Z6P曺~}}9+\Cio.?Ϭ􁉿t}k&mf iCkj/C=cOjnb\kчJH    !@@@U[ya 3gΔ+V<<Yh0d„ FODŽ裏ZK5H>o&h3hޗ^zJįp ~_֭[:tIJedΜ925׬Y#oV}k2o޼e   $N +qbO    A nO~"Fv)=L8QF-6zh3iOw9u޽! Ch,t~yr1K}S{|駍 ƌc yq9ztvvlCMB    pN@@@@4pA`!N8aH{*8pYB@(--uӼgcjyٽ{;3F߄d馛싙F@@A%    *c^xA>#immW,2n0iWɓ^e5d>FPî]䥗^zkpn-ӧOo>   v/%~@@@@ h 0uuuK >ܸe unkk3N>m AQ\\,eee2ydIz@@@/hB<@@@@@@@@S Os#3@@@@@@@@<@$ @@@@@@@Vo= @@@@@@@< D@@@@@@@@o͎HS不GnYdIL;萍7ʱc̙3(EEER^^.f͒+B cʛۥ9*.\PrrrbږCVc'ܹsRRR"#G#FȄ dƌ1PLlld q,J?JGӧ]]]RVVf.̘(&66Bs2{5N5~3_r<+U9x*H .%" F04xr-ӑylذA^uioot3l2YhѠ&g{TRZZӶl@"e͚5^*˗/ "bb$gHi8%ŏH@_~eٱcǐkp]we6 ME6 &HdZd> n8vp/>+fLx8 Il. Ǔ7';@^g})N&d@\_x:|2uTs6_WF0Å \_{':;;88dn?C3ks-zˋy{6D X?wޑ?~|m8%b$gcQP9"w''O z\rIuE1qp{Nfϱ)k 1U2ү^>x~SXx~N8_Lz)30Dz&m_x~k׮5zg03ʒkFLbt=?ݻ׺ [273CHeRgnruɨQJLz|ШVMtqY:'89EO5xԋcQPӟTz Zx3@[hЩ4okLsG‚gűȮt 8,Yb UO=oO>>kMs,(@ !8'sc' gEo7$\ WOqk22I ^~3ԠSx_qKU3ΐO>Yϟ/˗/LZ[b;Zj|y0@z&:hVXBeyI^X DI Eh˩Fv*={&Mk73f̰ׯ]C=!ŀY7n47o^@q #s6㙾˒(v}γi&{8݀6 bhѢE*܇HPbA_C"KRZ=+Z f͚p/ea" 8bw&΋@WORLlA_'zxO \>oQg !oʧңGiܸq7zOÆ 3ަׯ/ڟ&2c yi`P DaDy 9" qР7|u,M<yEG X ɸ-3^ =3} Yyr~kٲL0Aׇi=C=X9~k_~m!n5}.L! ܋ ]@9r,ZȦg}d뭷ǭE#3q8e^Z#;cފG +'S^0\'VθX|EXhVK3i?$oׯϨ/lS אmͮJ9mK_夓Nۧ]1c\A=;: C.Fp dr Y+p/$V,hXl=uT2esf kF0 x&:rVXdυIˉV DsJ= /iWL6J* hpq0 Ȇ 4i?ڵWd'VMt+VСC+0i$JA`ҤI 3yu<>CN "5dȒ3ڵ#N8Av횔{QRf - \`>_q?)X":Ѭr?)# DOvP /ity.nݺt0 o~OzygQ˲fs@)Vp(KpJ a^C"Kϸ ,]5R ^KD"%u";cu(=;@6׉.YY * s>BVD Bη5o;65DB nL:t3rݺu뮻N]̝;׬lwna(0}t6lh{VҖJ;0k}5dq/$@ڵVzi~n6ꫯeժUtk{%':nّp7{+@WO _f |l!ˉ=/zZh`Җ.Ktjժ[@>}%KȲen&կ__81bK޽q~+O=+av' >R&A r Y^dIW.,9r漙3gʠAZ^@"'u"#;cmAry~Rb:r?)`R~<4v@lרQ#`o^K͛7'֛սKj+{6rJ{$0vXy'9潭c>dIw\!"hYW_}[VV&L`܋\ IH. nCI ,ube%g81>~I>iTBZh0D fZlZR+IDI@zW̦wE;4 0! */ ~ ԩSG;8W6}8"#DR8F#$wV̳Z+'1?brNǜ뤼bO+"P, _),1@95k&K,1PŊcz֬Y#+W޺uk{(omڴ`: Ff2@h0۠Adv3ϔ2>˕@! "å&]irzѷimqFת܋\ IH. n@X ׉u8O, >*P 4D#Y hɓ4giժUL>ݵL6m\ Pv5uÆ Ҷm[K3>t2b"Юeg0Csϕ-[KC9RDEd Y ,]Tn6:u$xnE͛^`H pGt|g ]&Њ$IHn(zNGsήOd#?k .Fb"]h i1c^:NfΜi/o֭[gbXvl[[rfc>Tl%M~^Tbhذ{>h$A֝,L܋ #MhOYpz~NpNSv%xRg !s=6l#zG}d8kM~ZJ {޴iS{"oNj-&LS XD(^|E?7 fKA\:Q^ų<"Ю];{5 &u>3||M[=kw{Wq'u2# 1\o@PWO/;@ ʏ=/P 4"w}hD=lڴɞ7z#GEF Vm Tp6kwYo3@ |2qD;[fg-uԱgPyX7 A_C܋p nM`4v'ؓW.{ǝ܋ #MhOY`~~lpNS%xRg<{@xw.W_}e9~Kjj Æ ӧӶv[e]qt"zhҾ~a9c{C@!}Kp̘1.;LT"-5ʕ{bbŊҧO%%0¸ á$7'4?6Vy9Ct;#GvM?c]9gr/rj0@4Yn:<3g͞Ipǖ:~N9JBbO@4[ j z=n`ƌ裏ʚ5kE+U$mڴ-ZȬY~s5תo_~R^={@y!:{IxKPhnٲԮ][̙#heΤ]M~I #PT?yGn/ K@ k{Q ,BZ >8>_͚5eܹ2{lYzsڵ5;½+8 )ױ%g) Z;c)8|*գ :~RgO+ n1R#V}G!mVvi'{<݀'hdݔ)Sdʕ׳tRp[\pҸqtf>(5Trei߾ʉV,X?4+gΜi^Kzs~!H߾}I|"Pի隸0º!ưl2?>h~Zdh VQr~^S%Et@y&rulIYVXgF<-+'8J(øNz= ;g#y^hs=̀ `X~5~ӵ38CׯoOg Gkݺv◴k;Yg%"LCy%Ot܇FL k{Qd'%bk ~Isw;Ova 6Y|"@yɬs[|@y/J̈q|E]y<ΫR;ʰ'vx\@=o9r .JmҤhzq@ 4,X[bԩS wvE>dI@n܋rsch h Z~xye뭷Fҕ7q/* #Px—9(n3w~Rd|Fe!@@@@. kd@ # xgaÆ|Ŋ}oӦ8LHrʌrY7LD@@@(:l'/u  @V4d _VZRNog Æ $@@@@ Q:D  @q Y\y$7        3bV.       Qˉ(yD@-[&/V4h@7o.+Ɇ d޼y`f͚IKPs!… eŊ͛vRn]z뭥RJ[. '5\h̙3G*T`Z6nXիWB    _ )U 'UEE|@~1"ǎ @uٹ{Dôo&4GWZeM6?M& hBN=Ԭ_qQtM;03a &~1B~qgܹx≲>8'm~` -l\Z3 _.m۶F]7n>heܹb\sl6x ϧ5komf7/mڴ]Gmx3  Y UEZߐ:|R?n"s: -]Y8>ǎ Prڵkڴi=:wMF9Odz]ږȑ#'}KtG}d~&M-0][cu48#Y4ig-vZr; */exZa%5,<+(o9Ǐ7~i3XEWʓs7M_eƌ*{!c iرfʕ+L|+"s%F3@@H#"\I )uO$ 't˅\"\@_ˋG 9 hպ'ʹے_VNj*c=&wyh%=z6Ӎxիok p 3x9sL \-zx)ϧoFnVI ^x<ϝF@@(.)hȮ̩HEEr @h!^"\Yfbu [Vjժ:uH+;.4h 'tNf7 ښ?,_5^{ѢEf <ٕ=3?>kSVtݻ˾+۷7зC>s3f9;O>/ڛOfk֬iOK6j=5wޮq-X@:W.bۛMV>{9YpM~|ugb@@@ 7䲎)gJ~]Qx^@ 4Ĺ9v@ &vP~}{&Ν;Wy$_ >мXIfeOn6Yj9[rx§ve fT\|rQGmٲyڵ`9Gn;3X_~1n:Ѯ!,T׀ g;v 6&o0ön+C Zj]n㏗/\f͚e/M#׷{"|?Vn&P=Mڶmkiɀ̷oFA@'   D \q>gJ"O䧾: 0]? @\sh$Y~aW]vo9egyG3ϴ4BoҖ&^{5.,ezԫWnµrF9t~F ,o++!V[me4hO[7]=}>iSΤ]xkԨ!?O'kWLZWb@@(u~Br]Q$dO _S# 7n[nٮRKѮ-hEI&M6rGK/d.f:tovi&{K￿tg;o<#~zsU.5jtS+VRFq:^{I]ӒfVtK}@Cv{LeeeQamYd=4wZh!4r1@@L:iO;2=t;Qd>IbcE@{=z!M6uMK5r1Ǹf駮qkDhpN:)0N=TyShVڼy=ʏ7w'hvrwʅ^(I7-x6lؐn|V;gq89^y衇䪫2[k[H   #3%OdrgZEE&,q !.%q" ٳ]{l߾k<݈cZiʕ-8N\A>#JTv@D&U&տ/첋wS)ǫT0Χ:\z-0`hE B   @ϔOP?EI}n:LEY @q(e@. 4)O5jiB}G:SڵeƌIi~gn1gqv PbEiذaZ hkEӭIyҥ*… jSf֭͒['G~vQޤ~6m4E`.&8>hy\2hA$ZڽvѪU_@@@ A:RQP?͞AMavWKbC   ,7j(但?S/_5\eDߨp4,[̵uTkZ&MРz24?3zpiZdL< ъ п?#MraO-[+R`n:?~7h  lnEv}wѲ&!  Q"sQP?ő-9%k(, >@8 @@ zD iӦYV[h2iO?_>`o@C޽uR h ?|G*RyaO݄h?w,^8)ܹsW_54o߾rK|N @@@aYǿȑ#[n1Hꇾ}SOɥ^*J,k|"  F gJ'(rn:  W^!ks (мysk׮-Æ sMeDLޮ;,XѰtV[{7JCNqo |tرcZжm[~?[СC|eI!] |rZjrAVnb„ 2|I䬳Β~ž   @x~'wE߅B @ N4ĩ9V@BzEjV4RF iܸq^sаaC.\(7o3oJ :u]xYf1c%\bvOaq+ժUK׿Z/ۮy[.Hv}wIR3e\;}+;;͋wu>[i柎ofp'|"|NӢEZ{   㙒-[,|Qq.m߅ PG y\rkM5mԵM XxkZdoۧ[/qګXnaĉrJ{ ѣ]K mua=L̠+< 4D2IZ^A.mF=X4hUKyW$ԦM]jKzn@@@C gJ'[΅QGA*@-t9ł!@b%QΔGly>wK/G!M40a1µȓO>)uuMLbO7{iv`OL2϶$J;cǎ4\x2n8{]o߾=7!βP>(aheAժUevΝPNLǀq)IL6MA5l6ݞ6@@@RȶA=]'gJ2"s: -M EX0 @]6gq'[)?{̵n&m۶uM;$,睰tRy׼wdgk2R^=,.BI3ghP7mذ;)qCҙ>v X]>WӔ?̘1#UyTԩ#rf@@@%m}:A?Sj(|CuaKQhI@-4l`@X ԨQurE\Ӝ#._fM ^vZnV駟\=X׸5ҲeK4h3Z$Sku% rB^\>; Ж%%'~.͚5K* \`<е믿.}ksd޼yrW$t}\;]twv% 8g:S7g޽sa@@@7覲]'gJ"r"s: -I E- ! +ƍ~. `8SO].+k;wvm^eʕ<Yf=g$Yg%[m=MnfyGd̙hZbm]k@ ufnӦMN6{eȐ!j*t mA:A]ʓ;0׹O mB["sꩧhx>suuy|   ȥ!u~á~ZaQq.QGIB+Po ?"  wI&Ʌ^ڮvs׮2*Fu&]ϖ_~w0]8vyݰ(|饗… }Tv?{{!w}ws|ԩ~/X]̞=۹ԯ__:u$=]^JM7ݔmH7ar'o lҬY3x]N:4XJ;~[f1o{\4Q$n6y\۰F N-[<`-jv5N;ށϧW_}Օ|iҤ]f8]l:$!  &Pu7NϔZO~BM"s: -} B  X@O?@ϙ3ǥrV_WBK ֆGwm9/A;3趶~{֭[[?̠A?]-;+8&kLhYx\zv5@EyԖ?p׮ƍU7rW(%-[o0jo]ﴠϧ:J盯˗1hp7A'-%8   ^ \ R 1eBOhQGƹD&  s@X iFޤ-̚5 6~X(;vSTjRZڦߧL-\~ҼysE}k}m!]Fõ[\g4 `ȑfS<6m*}#FE]dA-5XIpRaMzru]g$[WN;VZK9=IЮQjժ)󢭭s1o^R.L@@@\rYG3 Up'taQq.QG>Cx D<˝F@ A`޼yh"3^Vj׮5!S[LЦ.Mwm_kѢMĔ)S./ ݇>2       @i PQ!       i"]|d@@@@@@@ 4˕B@@@@@@@ 4D<       )@@Ci+G       @hty@@@@@@@JS,W @@@@@@@H #        Y        !G@@@@@@@(MJ\9*@@@@@@@"-@@C#       P4frT       DZHG@@@@@@@4h(r@@@@@@@ .>2       @i PQ!       i"]|d@@@@@@@ 4˕B@@@@@@@ 4D<       )@@Ci+G       @hty@@@@@@@JS,W @@@@@@@H #        Y        !G@@@@@@@(MJ\9*@@@@@@@"-@@C#       P4frT       DZHG@@@@@@@4h(r@@@@@@@ .>2       @i PQ!       i"]|d@@@@@@@ 4˕B@@@@@@@ 4D<       )@@Ci+G       @hty@@@@@@@JS,W @@@@@@@H #        Y       ܓXb̚5K~7Ytl6KͥB %w   D[`2yd;w,^X5j$-[-ZHƍψv >},\P,X ˖-f͚ɶnkխ[7  405$}y7/B=W^]n;{ꫯvwbد_?,uQr5ށlWcڛ_">=@ Pv[6 @@ +u]ʄqi2?ONcѢEٺꪫ䮻l}7PٽX% \:QFѣeժUI˨AҵkW9CJ*%]6݌.HƏo/vwa3@E @hZ ̜9S,O?Bk׮{'SNnlXQ _.]~,?uT8q} \nco?K.@@@,F糮o|c޽{W_}2{첋9?gdfID*UOK.D)ƪU&,< :4!\ɫW," /@0Cː#  @i | ]c2Djժ0 ๺|eeergmGrg~6h aUV[oeRfƍf}7|#׿reWF͎@ZoYB.ڔ_0>|͢J:_j~۵Noڴ~: QF0-@w;@@@ $LիW7,fpD{g-ww3hk$>Cz]p s9?|'eo5]+ @P*%Y1zh3 ۛE d/}٤f͚K/dF}{$z9餓|[xfQXcǎQ&y|P  DH`ʕnҸqc4F-O޴͛M[TYwVO>39ꨣm&z)LI+4  @) T, /tR9Ds&}H6Z_|x7]v$sܹ2b4F@@@@| ^ڵ͛A֮]+'xlڴu8s=u0wߕ>ښd~nذA'm- @@ N .p}ɜ9s\޽p iَԯ__nt$@@@@ (KUV jWl h7:.]#;T, ay率Ç3=p iÍ7(Z/k:ɓ'˼y̺-Zn&o}tb 6myngQ뛢Z^W3Rz Z2 PjƏ$7n3ٳg^5xZjtAeFe|Aٟ>e+μ׮]h lĉo{wwmKn6MAqtƃb(3 \ybŊeFPC'[fURw?:uqA9h);묳ʶfMeCCF4rtY~7z_~evmO)?+ݵص]#@5C涍J2#5㏷UZlֳ>&X@@Z^p=СCSn'g^op>oϗ:ܻwoWy?\ۻ]J7bڻsk6),jOgw&9yt^sz-j[k¾>䓤Zc5պ~M6V=~eFIjnԨQe~uCq:w\v]wiJ)k0 /.ˣ>;ֵ??O B_Tn;ku~)k/LC(=)C∊E` Q_LrIkY߾}|CH|3:(W%ǵ>4郈r:qݺuM6"ˌ.F\wnoX(92ƴ۷0Za(es<}>e .6ЪB&M2skf͚eo3] kAŹV-^ؚ^hO&|;`A@@@G 0y*3y)ٰ>g:S6,܇5l4۟/š3ˬ<Ngwk9gXu=?yN6|&Cz5]\t~ Z/xlO/[zu}xg̟? HdӍ.5|MRq ZN;ISK4ӗluU+%ziG>)kŻo@J[偄@ /bvgBʕEMFĶooժbT]PhrQLz rg^z%92]\M?0utAF &|,]4gϖO4s zsRFF0ilٲoֈbDqg65OV]    Pa=C. 9ޛR(BMx=16c|"F i9:M6e ѣ-f.d {キL:5:F+ b%~me hsFp+Yㅺ32Zu[2ekZ#$CV-:BKm׊e' @|%8>6i9aˆvmA> y~zhrMv*F1s-1ys-?r_}4jԨЇ2`j4'Ffm>=ZG)7t)3xh_dt+!Ff:u2Sc+y.^\D<>裤A+E D4t" 0E.FubD k=?kF[7_R,!Y4p[oy=7kuZfHVh2Ϟf Fk)xsuklY\+2  ,3XϙV[ς;찃zlS͢z3w/n"]'?kۻr4k|!rޒъ/.Ӓ x0QDG_dy\uAFvPC8N(s̱߸q-^8p7Pk0-X1Z 5i2Zpsi _SUWQ!úVe@ &Ɨy~͌KwI'}?n+u4~/3ؒnN3kܸx5m,MӇŬrѮ<̤]-̜9H8T)vn%M6%tkMJO<m3]\]50Kgx,Ө*?~|ѪD6MAmfSv N#_}qoxK:n<ĺ7ʌ". @@@ _rzN Wݟ)KWkyvn_u`ud}/Z.䒄}{v9aQ?VXỞ [t7.˹}뮻.3znQqI ,Oъ،7Ct--zf"+¬ ڰ=. @<*_ H]@Mz'> _޵kFy1\ӝ#ڂFt{#^{͹hdo6y 2ݺukeZjfkwڄX4x`9_#tQm&Kꃶ֠]M8F_A#SEr 6G}l)Bǭ4fMi.Fhz,o8/mga*-iv7oiӒ$@@@ JA=F Ӽ*OQ-bHes|F̊n"m'V_~´|N(o@=-'`/]Y7Zt/yСb jԨ!kG7o*k0-}KpL띴糒j TUKm׊T&iOXl޼y t[o%ހlwug >35B#ǵUZfR76y~ Zv̙],u]'DIz۵?lmT[j5yvlCƎ+^Z| ̴~KQ5Og2 s.ǧlTˬX&Rf;O[d8xu\_RL3tW:3gE N8C3T޽j*eWr fS}F)ywEPי۱uU,A_Ƶb|"Sx{GMyŋBʵnݺmεF=>chQkI6?ko޴~z$sO?uM 5j䚖ɈvuMm{{;;>{lE t8ǽ_؝ 5-FhP392e{z ʄN8 @@@> z|[JeV 2~]z߾~Xls{ %a!co4]ǛuKoiԨQ;fWe/kPM^{:g}5Ю]2XQ^:køVO@x TasA xR2ApѦky@KڴFW;#g͚n6dQf̈́{-({ךg*UdÆ :SLS>/?˸qiloY}Ef2Mܟ|I{х Y۞v7qK}d:0    ybF1<ǡ̂9ղe˄MuCP9&'A!61VP}r!MuQ9y]5?ַֻ_keH1\oy_GoyfVAr]Kt׆q'  !A4,Y$'ك߾s h]Ò3!$֭[^4CtI6ֻa0qD駟̠m0Ywldz^v]~mʴiMi_@r:piA@@ 3o=<s,캉l=7 i%Ă MР3n֭xKVԖ>Vkyf`zynX\K.DniW^-Ϣ?[9s©jg2Xꥃ6k%se@J[.'J| vtݛB 8:%۝rVZ>蠎Tƿ\qf@4h 53f̠A?Mo6K/ڵkzg@@@PϼQ9lYxg>K U7ǰ_@|ǹ;GLȵn{ӧOOȃNn=?3E[Mm{L>`'HJ\jG}ؒu;ngϞfk$#p]Kty$9= #bTa6ïMM9|v+ /`xɒ6mM+~kfלs~׭[azͭCvm'wٴ5=٧ա*Æ ?0bM϶6Dž4*y[]x8S؏{ #  d'Pr Y7o!maÆ~WZ(Ǒ2]kW^ݬqML2| V 8lew=Inܓ5ᬳΒ??US]X\뀴 g3f̛79I.W^qMnR3Ir]L,xH^:ky #S.'Ynv9`LP>9䓭IfouMw.7x踕4h` ڟeľkg30k,\S MBN(_ocn_&m@\ԩjw!:O?]Ƶo: Li+ƍft7`@@(֧d&meoݵw}7 oVF6ln͵_/ iF/b^ܓѮ]@hAco0Þ{)H]&P^bEB*yz=Zaq4my]v]v^@@@ h=G6i [a?;]*åZ7/#9e PoҖ#3M4hϢE\J3]bh?¿;2qĄ5ۊ\."{^ԯA[n>{nOtf(ʯT/kqz0 S܏){x:mڴ7fI=܄/8oS^ޠLе8go78:|]wɪU\Ԗ>#t _}#:rGvc%뭷Qy7a8]   +mۼx4s_>T&ESmљۀ|wy饗1ݻkZo`Bey~?&w9^?k`äI3Ҁg*kP둜S_}Xu^Lt7Qj[΀\-[`@ 4ĵC8n2QΤW\qsR]LT 'd3\_-3u9}u?]5- шɓ'UW_}5?5Y U暞j_Mׯ]BPFk_7@,H+   \{&9Ks|BJ`B)MhYg*%=^Rk,FEmOs7~s4a:dO\RKy3ڶ.u2I]L:5#Q:aZ'~ևsMdDӧht~y{Um!(ѳgObdwœ|='l8 (wDJTFkW~۵=&ƯTf   @~gjcǎx3P /[^7qW'tI]p ~YO;e̘15j$7xkZ})B5BLMmYUVRn]95B_4uu[Τ-zJ<3)V@ȑ#]5%]*uz̥\/ֵa> @i P[G㎄|uQ9C"]MVu7aK>eFw-8vѦM]]ǯ͙35-ՈѾ {eWf矋M6]?5ktmrݺuLFsOyES[7v7]v@@@ +Q[/\lYF7y7s| b|*,]wNꫯ&,]tQt[4"ؙJT7 &8W5$z\ lDJgnFO)S8'oY>t}K\t}jKZoŔ g{9?ٰ^~eqor) o]X   >ծ]۵CmPӓ%}&izVXs_P7Gp/]Θ1#as.ڲoo۷z;9q㎓QF%]/4Miw-[]O[Op&}AF.M朜0uں3oRNxP/8]ÅBúV  V|#-@ΝEٳh+ ΤiP5\#:u[</}rJs\z饮y<p 'v!?x/]T&N(ǏÇ xgE6H[iL4mԌl  dhuj.ړFz{Z&u[}VZ\\[f{1y7]6,l.gD[:M+AK}o?֧omMr}z[pd@@@ 4u5 2ާ͵6l۶֗hڥj>mVfR " s_&P7u+r"? x?u4=L:I&ɷ~gNBēt ͟v/vaZ iv'pءїonFuϻZ^۵k'jvCZ_uZŋln~nݺ?c!9ѻw& =RZIv0@  fϞ]f|9,3.)eW:FKڿtQfprF}wyy[rmx(H>}=Ó.7cڵ~iE]t2alވwm;btCkYˌ}W^6A3OÅw7_WײFe=/ӁlN+̫5z=μwwnL JH^ o=#+ko=#~Zkf|ΩtPtK29CipZ9\`2Dt/8Ǖ&vYeu].kyx|"ԏ;g Z+Zk?kRvɭk?mI95;utQi?"uvq믻m$ͶMoh$oYGAS-D8n3 =34[[287QD?,4~ FpEb\p!  TH@|饗سgOyܖ'iI>q$=iM:.Mpo˷v z79ѧv]XhKgyfewjGqczn&bD[JtcǎEc0ݩ$MxT⸲]Vxy@G 3:6O>Fi&2xw_~F KL0AZRG+Ms1Ŗ6'h vqGm&s-(SmOI'T4|۶m_tBv-`hW^ymPnᡇ ~W^.ǎkF=   @Ǹq/BV\?sfۨLؾoTpZqI{^޵g?s+ =t.^;7|S Pt1y_ӡA}yMf=`xoRǕͲ˛~}r+AO@j_6FQ$Y~BHn) ooF뭷4kZVƌ#ÇNfΜ)giTbh/    P~֗;F-zmzMثW/VV1ؼbqq]]hpo"Ҿk{1-fmレM4./h:f̘ᶌ:lj'a2i$r7|#SLSAڵkƪֽTXH*q\.+lz_JԔ %@ڞ+7&^l{p/       TB.'*:@  {YJ@@@@@@ P!@B8iS~B(|A@@@@@Ȍ]NdfS@o)ᄏϪEW$^{m{+%f@@@@@@!cQ@ k/e˖Zp<#2p@2<ꨣ+1      EZhV!M @CA/-Z1cƄ*2h[ѣGlPZX @@@@@@5 KG|r/+2C^f      dE%H ٳsycҮ&>iڔ"1@@@@@@ };G>#9I]tQhY}z_r%ra}dr' _~|wF#rJ۷[gϞ2fiժUyV'|RM3;Nڴi 8{lի̝;W8yCR鲦1yo:tw2R:4mJURU/cW^s=߶_z110 Y+R +5^J*V֋MkI&ҲeKCҽ{wJtn$ kaxLgL{cp_&^&~SM1Q/XfDo6dc_Kҗ(VS~n[+KGj%6a;g/D B{5ɓ'˧~ǿ`<Ȓ%KBqyXxq(>,hѢ̙Sg~]>ip ~ ^{mE+3g!ӧO/Z+D+4tI2>Ӈ=()| Uɗ.3g K.mX5Afb&1BN?ty7eV żX>pl͛7/T̟??͝L Lda{f;&5/vLKVBTW_}}Jo=;夓Nm&i1] `*H/'5L^eH̓}-.6ǔ_6'N}zrS,ʟkֈ@JblkrzP렭zxiER+3JgҠa:,)wBic^f͚%'xmr)5׋y~\rZվI? lذwQZ$5`lHU/@y\zGZhH@SeHVҚ:6]Z?JUW]v2c 9.".LIp ^%5K: M6kZ`]we~}0~xіAk>Sdu֑zr67E Pgxd$i#$2-@LoWnzXէORajR@j:^ҷoߊ3ZO>Z8]zް 7mvȐ!>y'QeM/ɶ&,i plY؞h^y*kQl&FY&Ewn%oN;M iݺ7'ǴubV@M bQy PQuBCn:Ok׮rtV@`_zxtkʭФIT+4[/GWj# ^zRɈ[ 2Y T浘ڶm+s[b}mAoF_Écʬ2T;{9A(Siu&T#$xouh Π8 w 7EkkVhfmR_A$:tp5j[@@@{キz衡<|A@@.*4T"eX`5i_Mm?\.g#8m=@_xM;/ZbElmL_Gψh_SnSOuniW57n -[::T|衇_9RF>ԩlvrGˠAEE ~׷_{5#OSov<`:Ss7NwGyD}MvCpg/~ i<"dΜ9nÇ#FȌ3dUVM7T>`QΝ;3EyT7U&OVfh֬暲;6I]O믿nI{=ꫯ}ؾԼ3_0[B(VA탃~3t|Λӹ?><6J.쒛8qb޴2c<.ŏ?{GsNM⊜S1h|r- '6jSs=ꪫ:.lZDrHΩԔs*zߝ9bQZ?Zn]0NO?1L-TNmfx|D?e]񫯾j.򛗝i VP`Btr*|ǧS9`tcI>,{۞y}cmxG8Kgc+cXNۡmTfvy~̜Iic %8nm쇥[2OzL9k;: i๸w:7 7P8L;N qL Aq&q}GxZА1m!i9蹤]x&L3 Q_[e4i?^9sEJw Ɲ5fPG[OEϮd%"O4ɓnUbZIpӾ~Ը.ۥRn6wKoP:L>MoRFqyq,]ǥiTB@Tf@@+485[sg}vFw4i缉s%Рw[Oܧ>X/v#U+x8oƙA^ʻ'Z#.}:MR2BAƯq7s*m6oڝ7k۶mnj^:[jt=rNkiI:i$O^8-24N7<ȜӲFx5pA@׮]-[{s_~yi $>.?sZHo;j%^|&'6z;Xs,sZ/879fi4]=XN<+6pÜqCq7(sM>ZJVwݮZ+n\ve&os߸8\ǒIcn;ƱXJ>[i ކ2'LBLC}͋+G}l]cql?u:Oi,34yi&yp*K-Q~UDytHQQ6GK'loP<7MIecGoXLLTJ FFRi]g-4~0N?ܖ-4ۉ+>󾛴Ͻ;Oƍ羁 Ni<7;vJ>l!w9}(45ӷז(=VNB˛ O+78]#oulz(iJ1j5lϞ=Jj4}.o7kkN7  {_n(N wѠtIcJVk:zP|2MINo *b7֡ib$P+LN~5 kYpsƵ4ݜ7Z3>i=wk ߘ Z^+yq駶ԠNn -OӲ*N[ ,!Ͻ;_Lěyz }CN/_\[w2:NG~0t}V$,ѤNJ5uLX,%enoۛ^{M?./010 c=m{c~XU!RI,, ?ܻԡP8mSڈs'IҪ=Ֆ[3&Ǵ߆RAeAwii!,Ӹ/yx娗JThuYhgV2CӔqI*K)vUI_pHQU6GK'x~i7?/&7)ll`l6`GTh~;^;y7hРЍVhVw瞼[D߆0^xӴB - ]w](n}oЇWS\.^86>+C8ذѓ o7tb>JZ9!T[7?mmzy6LoRF涎Ee?-@uBw1gc+4DFp]z nVh(^ס6dPq``o~PÆ f;.H;b6wK6橧S0y>L.6\uU$}hpJizr-z-u=ctjW޸^h7ZmиG(;Nm1ɯwdA'?Ӫ6_}UE.PbjZɳ>nO1/O cƌ UnEXדF27bqV((6D[]cfp壸ܶwccX|l !~ib`d{l;6Rέt41pǤŒ԰:hh=_s93J_,O6)mĩ)XSAB}"v7)vLkzl6:LA[et8be}͗+GߘrWhyiOxl?yeOm'ZIy/6˯,}~6R i7?04MIes:m&ATh(r#w߀ԚM8u]TI}ߤy[߀v~mdЇڵkJ7zRoΧ:@4} R]ԩS|k F뮻-3& R|͛w Non/6:ٳCi> oD+f<5-In$,s\MC7 O0aB聛v o&h`*{7:y,jMiZv<L/gii/M L˜lOc~Xʹ&԰V[m7pVR98;n+Р-hedFeߙbǴoäUMiy_㕣~\ 61M /G6ϟ~V̰qiMd{_66)f%4v.`;6J OQ6cVnbO!9Af@,MBqގ.m۶^&OwNj=߈8Mp盝wn&\y{3[o=o3gN~qF4/4dssQq޸D٩MwN`e*Ӝ8p΍cבoӵMu9~%?oGwO5? q.b"ğ֭uQ*N0 ew&߆3! eA9Ґ},?y6oɕ,4<*4Ufo9jƞ[WVLҾ~Triv6,w>MUJJ^4cRez),@)Th(EeJ?)N-!uZÈ#BQ%yom"чN"dƌ4}dݻ\^(4IE9=00yqN }דgr׋R@hMZ#1WhKnvы蠕f~ͿTGMKW8tYm'z368DB0p&6xt3rLuJKBi3݇t=zn$eF]U I:TԱر4 _c$A4J&y/%L^%[aN[}mĉ,}+9/6GlSڈӦqןVfV Ҷ|׷zl%/L ^>M?PNCZe4..$׍IKGI G8ʗRYf>h{_m칥U~e$ǫ$86<$iKIӛ6},VLOjIxJBCr,WӧOHJz2ˤmCN+(D+)LP 64FKb=<=8ӷm/3mk=ʯ,D$.<$iKIӛ6},VLOjIxJ(&{6헾PM"(|cEB5&.]6zX~O֭[VӪUw'*ڽH ͛7ꫯv7Ȅ$ui+oh۷V&.PdFa…nj+iGiPAok% &ȅ^h2hڇҥKMK5LMR#0oiG풬X:uJGBi3}CCo21m۶޲eR'+ e$#_p,P]de4{)aqk?LrnU2z> vL×sqNi#r.JL)%O]& eA`$&a*}Y,I ?*S4v~eF?Z-l#des`t{^|KGӓiqq,Lo-#`*Pړ- @}Mh༸1cƸ1<-MmjYPr ڬlpGUg)]-LbL≖I<& 8,jmFrrT˞$}j`K07eo/ʱ`kly$O0mo~.o=r7wCޠ}-맍sJq!@ߙXY( B"-:5ftyӺdKo5~}Y2׏r 3,oPy+5|0*ӃdThKܙ}S(7¦=/Zcڴi N{/IQIG̠#w}}"G[mܹ *fEN(}X}Qw7$4+4 As5׸Ją׮Z8 9dW b*joeY2IQs[py; *`Rcv^yURP/t9Q/[|?ܟWlDV԰KfէYGkjsw9"ӷG) (XAGV*xqԚG} kI-чIH4kleSOW_}%~ɕ[ } R).88$ْcdžchYAt\!V[-o~T_|e_' d8rPH;_hx:MpGr6.߸a~5ϲq&R c$[iY/M^06jrH{0=A,X௦M+.0b2iz ;| %- YH-GM&K/y ^K;kbHr dXu~ǟ}mpO˒I׏>,j4ֽ1;v>+Tvc±v]mRVkTh-J~ h-P}s ~Zދ-r+vo{>:u觾ag9$Ǣ7"?5j7DO &M`oϷ~;49OhF/LG)nh s)n ؘmUj)"Gv>CkaMǵy-mksm)#_\Zg:X]v:lv|xS f4?X^龪w>3yo,Y.su[ ʳ>ղ[nwъE Vm)d?eu~XGA+ciR,{.c4/iY/M^p6jz_Jѕ+W3+TX2^P[ݼysK|}psutM t sԷ{1&^z%y%`gnA`gu?#Ǐ}ڎ&ZDoDC=$Frԇ&5Y꠵o:y>ҁnsߨ W4}S|w]|B# G .Pм޽{h^}QÃ>OV~ zH+1z~4zOElqlEQxjx 0_ҁ7FOm'Noo( {W55Ϫb,/DZ`$a,ʱ_&[:vq? n7h9;Tcf981ed%8;cR* hYHC娶XlЗ?O^,XY,ȴ:l?JU+ǾmlRcȒI׏jgl}Lom,oXT%[RThKsy}7yr]$}Р(jn8Fa_hIo{キjwޑˏV߈HÛo;}p y4p>lMoEߘ.4W^yoS7IvQ?s=W:vMN3pU+*[}xZ_ZS`r{G03  >ӼI-4R8裏 .}饗ʗ_~ V(q͍BeO[5ъT .:uN:)u\`'=?~܈p!-^c!4.li9+q:vq? n`ߦu_We}98B d]~gLA[eAퟅ4$IDQ0dȐI2e~y'QkBMSgq^%?ZIy\#K&i_?ͲIgl;g%~[b%ؒBCmo_rG@oDÿop7Ҵ-0pa'j_#qFߩD>X7fBĉ'ǎ -~;oҥ믿^6 _{ݮW_6M>K }K]{@:w,￿V.?%3?nwntlLr: [lEb$?hР[6d׌wh%`m#ZtD [&7xcFN۷o_y'IVffmB %hW2I+CᄏA/.HZ>, 8W_}uouӛZF2W+l ϝv)Ԓ^j7h?Ka?-8r뭷ʎ;Po3;Lͳq|[>8Bp}i]/sVuT~&=&4+8Pv\q6TJrVYdd! Iҫam?qg-:ApkdM~e`㕾,4:l?KWei7d,mo$|V7ȶsVu,VLϊ-qV9K^؏Gt~yh 47k(l0qMG 6۹ }rN农Eysp s~rN:}ه:džkD)zءn9fqhi]"o᝷ sӜrkɝviuY'y.i):JqZd9…|87r #<2[es% GlSTt03)losSkxe?-o2 `E*4hAv/xN9V`{gؕcYW:tJO0mq}鼡 ބrT躢ΛhzjKnBĩsZp:_7GO^{m?~o=>wm N.HJrNk(9 ?}^:}:s%頕H8|j`r(L0uLb#4,6͟_}84Gӵy4 M\hQ$Ev<i&cdheo˗/9-VOV3$洮EY cLizl<L/c7Ĵ]$7Iǎs+s51=&~><iyqNi#δ}~]AemΘmHRf,H3 &/ccxJ *oٲ{-6}9|c*4hl\czy3y(ϟqgH<ɳ)ǾVm<.WUiog׏bzo/>yF>s.g7?/M&&Ie{{q,]{iJ lw΄7 vm6⼽/ۯMk wyEMJ!~zҥK`B=zPY>-м,|Ѯ#Яz b]vm.X //46s]h"{\k>|#W_}6ߞ/]a8iC JcW/׸%iݺh_`-_7\܌o&J#.|MӦ WSOBl?s{%LԮonnJb16Ԯ {@cp_( IY.9T檣6/Hĕ)Z>\ɕW^-:-ԈvgێT q[vRyp5\J>D`X*ѴM2Lg$´j8&N&}AӢ-A E/ zo~|@Uh\I P#NUtOw2jԨ@@@@G.'g[9-7m^$j}(3A X*3T£Rjk0~eΝ;lG@H.-FڲU    P]ThEjSЮ/_~7… Ƭ}k3ް{z|"Pݺu`_wuWU(e6mA@:Yt;K./p@d|ԡv4rH?nt @Ǝ+=|GnWUI'XY@@@HE 0        )@ij       "@T@@@@@@@BCą       P!F"A@@@@@@@4А&q!       @*ThHH@@@@@@@@ M*4I\        Ra$@@@@@@@HS ij       "@T@@@@@@@BCą       4O%")Y`̙rwʕ+8N?tСC,Y"Æ oV4ιsJvcǎ[H޽m۶e@@@@@@@*!@J:< SLS|rdDx套^ŋYpL>]ƌ#O? 4H @@@@@@@(@ n0qF't+4~XM&|pG@@@@@@@Th_Иտ ͛7K^k׮ne/BF7ߔ5XCva#       dM "K.ur%}Μ93˷nZN>d27Q+5l#<"{9wz-|"       )JM$̚5QV\q '*33}I .>       YBC>|f͚ɦn8Z!C6xGYg?̰aqF@@@@@@@ȚʸE͛vr}^j9vXYl~m g?gO8Q&OOc~_q{MH=ȿ@p1[P,~S[ߔnWK/=7۱$YXbE?djZ1ԗ@}}y\A\ն@tw\ToZt??yeW_?k}Ȑ!h"7l 0@}&M -Su/F%ݻwN*y\xCNҤI4$2e,__h֒VZA N hũ-[e~ް&tMZh}X&oƽ9MVĚ73^ uxǀ)0g3f;[lŋ{8t߿hWEoh߾kg[}S'K@]rZ_}\G˪Zg ݥK#N:=zHӦPty/ܵQGU_ )ӂSjoO6͏@@@@@@@$WK}oܹxq}OெA+<~R d\ _F6E `:hk :tpk2Th0#       @*ZAm?`ߥKׯ㎲[g)~. r-O> M 0mC+@̚5F?HjtD@@@@@@Ȋ@E*4h%GyD{PIQfΜ)CuVYen  L{N?{?+O1@IDATO3aƍ7xÏrnB #вeע-ZYXH_̙HfϞ]wy&Í`ia=Uy'ϥ ߔnWKjvtzu[:RC{ޭ[!YA@@Gz}KO[Qxdڴie^ vUڶmk]f2o<;w%[q䡇C=T q)4Mx{H| -b4/Z!ZAX$ |@@@@@@@l X_W_-ǏCdwvzwMO0AF-|7cƌz,X sPJlٲТI?4}(r        P!+{^"oꫯ.]wUj zrk g'p7~:ϳ12rHݨՉ:ʸFDVp(|_VZ[7}.ǒʇN6REh+7Mct~a7.7ץou˓o@@@w+4hk \sL<ٷ[lak!vgs=',YMp)vCa9s}.ji I+4DkZo%X E[\נ@tҥD+C`R#w;X QvSUx |7lI)giҤI Z4oeIʩ&J DKZ]@@@@ zpĈrXeUD[O8#cǎrlfկ^BeڴirYg?ƫ-AhE4hb7A+tD       @%R0w\7/\tIҩSJOڴiƠys+|ߗʏWzq#&LM~뭷4{wygi׮54͛3?L+3h_#       (jM6l#gyի$YL+6xrʽ+>XXk7jԨѾۡezĠk%ٳgV @@@@@@@Ȣ@/{wIkK,UȚkWhЊ EӦMfC`?ܺ3       @Rкu,`ZlU[HEB+:v(͚5޼yMԭ[70Ĕ)S{2F[3_P#       PQO+^;(d:tk"guVJ[m+2cƌ1B|A@@@@@@Ȑ@~ 2X_=zHN|~[-[і F` k׮wF@@@@@@@Ȓ5%塇+V?ʽ+ {7'       Hˉs=W&LgtȐ!Ҷm[;#.2|p1cQdҥrJVh wqGhz馛aA@@@@@@@ kWhe֬Y~>W\3@#[oU,YF駟o[ٳtM&M$|AǎOL/!Ą       +4{om@8åM6FWiŅ .@N:ugvb_aUWN;MV[m,#       )LUh|8 FΝ;vOѣe… lR h        dD 32Qdh k̠F]~h73f^K.k #̲    P/̙3tIO@@Ȓ5RHVb?@@@@K.> `3$@@@<M˳ւ        P܊     Sf$%$@@l P,"    @ ~\"ė?"  @vАmAJ@@@@@虓d˫>vC]PjK0 @@Yy5'g[`oI&NdSp4YbʅɲV '`Y\Zli N+WҢE ;#v>gv"P+޴V'X8er9?VJ\ 4oYfaL] 4 P!=7֏_~*:M.|yp9Jsa|F@@Zh I6@@@@E7?z!Ty_>x'  Ԑjhc@@@@jM@[ݺO a&  Tob@@@@JwU0Wx\-`f"  @u PE@@@@6i*W0X:j7 ~\"6DV\7 3@@@P]ۋ"    P]ڬ&;`3s0@@G ճH)    u-:Tѯ L@@涓9gYti,_<ᅲ\.fsΦA     U$pVdwdSbS\+EELD@@L XpG;taÆ, "    @vZ4k.W| ~c:s|G]OD@@D*@@@@@]\=}</>Db&  BC7C@@@@o g0YrF@@@PM["    />dvёe+WE%˖Fg@@@yi eɒ%iGK|    XhѢKV\鯫cǎ8#hbj#nm`*'Ο!׎|J.wxp2   PWhh $@@@@Za 7+V3Sdrd=ʍ>7}~5R6w ڨ_0@@@ D )B@@@@GoYV~)W b%(  TZ @@@@%ФIeUGe9y0@@%@lmR    %tj^.ሂK]HyYlipD@@lP!ہT     @#9i= 2~4ߏH.+   Py*4T~@@@@HI]o^07';>y`f"  @{GME](<@@@@@64i"W0X{F?wzLi^֒n7 3@@@Wh׿%ƍhPQ~V    @Eڴh%r 2űiܺtmZ<&"  @6r"ہT     @w??F5ix tNesd.릸FB@@ͧC@@@@* 횽 y宽ΐ.r   YHˉ6L:tż&@@@@36A}?UjrՙE@@zRpV)G@@@@`eH5֯!@@jY.'jy7@@@@MQ@@*BCn4       @ Pַ0C@@@@@@@ RаhѢ*d         %i'׿tIӧ4o*N2!       @RmrJyw?ذ>~'ݺuXI    aKȑ#%36m*=z3   P+4={l2d׻wobCe˖`#    +VȬYBiYdI;_@@@#`BC0 ~_er+7l #       @ӴN8۷4k,6 Or4ԶeBZYJ_ rPuӦ7|Z_%- 5w\4iRr޾}mUhc6;3dĈ /%Z2_xr뭷Je޽{`G@@@+dѢEYyZT,]4SiI6, C-˫$ D+,UUz[:x9Vxs~}0zN@۵kMY*4xYh޼߼yD[l.)Ǝ?Ak- 8P:wa@@@@@@@jSbm#jr!]w%<qҩSXSʝw醿 75b       @m|d={O?]N99rK2l0U͸hebvI-80    T͒feh֬Yj*Sil@&.݌hٲCDѲ!KeUlt…iF6{<o79*}ۑ`d{кu:9Y n[yFWm-ovI駟zAٳg˃>m6nņw|eo:iMi{PYޝg;N=Yο(QQEQ@:x;n&&kܙgy&!+    @A-\>:m U ͐},O^C)QbϷ~VYcYt*VMNX X9 L |ms@5@d>S?/n"ͻޢ쇪__|:tڠ;f\_nҾ}{ ֆ @@@@@9eK_SrɷIlh i1sN@@3      )rxq͙͟?'+@@'ظ<1lڴI 3!'?<.pE@@@@Pl#!twtj_} ]$@@@nаo>Yx,YDjM``7NMVkv     E|²ӵ2(jxj]F%ڎ   P]E4?~\.]j2޽zjt"ӧO .@    4@fK_E^xqɷIϘZ۱@@ZL@éS믿6֯_/:Dm%44T&Olfc۷omͨ@iiyeee##"ZV=@:  Mee/[IЪR;R-} :uYAYସTy; w[ۺVc猬z @@j@Cyy^Z>so7=\?.)-[ '7ƚUV9?YX M<+@E噛n:ּ|n|Mwޜ?׍\9E](/w+uw4ar&~oqy{m u%#%/fch[Δi]F-fb'     P@ZxsfjV%UE~~T)G@@M 4k@NN,]ưszL SNzӠe sڒ>iQ1} 0 f {֫ QyR7;n0Xm J. n[ -H 9" jL rg77HBXTmى  @[p{@CQQ,_ưn:588X&L`fc4hשպv&~6-;ld3)(%!!!6+$P׍ P#GjmlU,嬜 2;S̑[!} @ t 1j؟ l9$-zJ6FߩζD@@ =W1pyIddd[sg      aL \l>^w8sQWnC|X!  04ԕA&OlfcЀ      1">^NjN+ܖ;    qΞ(ݢ:C+^²uj|{t\13exR:۲@@_p{޲QFɟg7o̞=[f/Ɔ     N#P!Nj /^mK@@|U ĠA jƸ@@@@@F t MGF&z;ێ  [-ުPV^I@@@@@"Csgˌ>j\gEg  mA _?:    mC _v~U640X F  @-n hk;#\s}{ԹX-[&ڵ˺vxxL8f@@@@@Tysگ$_u꭮p]@@Z[__]^{53[Cvv%K5ؗaÆɃ>(:tf@@@@@XP<:vWVx\@@& T O-˗/wxzP   @ 4[@v] j9>*,, 6}m]3+IQQʥW 뮓        f h 1&&FnF9s|;Çm|$Reڴir(m@@@@@@@@x$6֐K/+Wʗ_~)ׯ'Nؚ4U&F-cƌCfu        @h@I?~h޽{eݺufp[sUx=zA gu9-Ր@@@@@@@h^ hp֭rWZ***ɓ'+ѢA @@@@@@@mPq@@Ġ @@@@@@@h[;h[7E@@@@@@@U*&:    W QrI9  n @@@@h G sg=#?/Ok ]  mP63d@@@@h~ʆc{6~&%em# 8Z[B@@@@@XF;˺@yeټD/*cU    G@@@@<$p8_nAW;\#?%W5@@O Im    xQKAiq=f'MN)v" 4 -@@@@@ p0?[qqJr ,ˌ    \@@@@@ Eʠ\\1ŝK_}'\>  Cw(r@@@@@tnA^:QWKTp=._~('N| @@h@`SX@@@@|I 00PVDD  '.3Gk\VyUc|gOseY]`K@@5A@@@I`8pTTTXС $.725\c}Z\.iб4F@@&4l)(($&     ^,s.K{$47Kl<)/lA@@g4:tH*++~СCmV@@@@@Z]K_Hܩ q= @@I @:6@@@@@Z@p@\wDYp2$ ~nǰhؖ1z  j<ЩS'N<)۷oYA@@@@hyF{O.}Pw*~ϹPBjM=  . x>^=\-Ya @@@@@)1)VG68yֳV@@|CΚaC̙#PYY) ,իWѣ%%%ERSS%--M$0aݴҢ)@@@@@+0hUVXsp@@@@@! 6׎   x%o͛7;Z        @`"63h@@@@@@@Z -w       IL93ϴIl        x%!0+uMV     FཝHlHOIJj8:  @d H4A@@@huV"III6+ rNnDNHX m9'   t    krAau֍6h9 ך ڣS'>\.> n>t  4Xq    к6n(ȑ#%88Qr МU.Q\^*\i.RϖgMa{TkG  @hQ iFk$.c޳h1HOL@@@@ RPPШN 8Fq4paNYaѥGt0^t,-xg'  Zon7\ySd„ 2c ILLt    mN@3346a1`hUon_r#߾#lD5Z0H!  wА#>,]Azeɒ%rĉt<@@@@ p0LƈmLHal8>qPߦʖ/dJA2;6@@x5aݺuF=Z}w̞=[f͚p      =o塆ܖ #bKv{ȩ]B\$v7Ƨ-~ :@@Wk 4j fի$''KRR(AffKii̜9sϖC:Է ͛%++\t:KbYbMl˓^#<<@@@@hV^s  'v~0}c7dZe]R kKz H{@@yOTqĈrmI=~`ꫯ'|"f۪*yG7hSu^ ;~lڴtK Xv0c 3Z:**++믿>ZB3df 5jTgc   }N: Ad1uĵ}Wʛۗ7j: ɿ~Lu"{Hb(@@(@oV`f&_"_ fc7|O?Q4XOS Ծ?h"]unϟ?_t)ӅB-@@@چ@II6ڴ4* tv/s.SޘKm7<+N_Urmȶg2B@ZW248hwȑ#L)?.eee\} >(((^zꗞ_ИtJi;^`+sAm;jرx{W56DJm^yd̙/7yyyZo?"[06 8s%`Bٳq֭#A @@@|G@3Xc_GFfgtN z__ҩSfEћ49nI}W ׀2W@raYQvdZ4@9`ݕhms{6wQ^h/64~_\\ltMhHOOw"66ֳ5\-88?Bme߾}.2..ڮk%99YQhF]DZ@@@Z)8=z~3reNG1o<랍ެ}7j@|M Z\ 9䂤~6Tƃ oseuƢ"k1+Ƕ}߿f_D ,pQmz36m5$xCSDGGNvҪd@@@|B@34ؗ~wQc0>|700fa6+ @[(sqDV8@@" :Zs6TeGҥKct"o-Vnj#IIIֶh˰fgC l)$u?MS6^@@@iӦɓ%''GN3Q=}K/7|ӂX|\xֶWtͺ2UzOMlSthT@/p)p>L+kkkiggh`9b[#u &&ܲtZqtsϖ{z^:fB)ۙՀiKn]wwJ@_/-~|77Ѯ5ngəZ@Fcuyi3ZH'qvT4gΤA.Рө'z3cd  @K((-/lIKT]! @ x%A ?cٳg5ʢ"yEtM9Gˣ>*Ւh`IO=*848(tn:y:   -<  mk",]y2qN|U_9U_Z7l"o^x A篛 NcgH8dcaQRO<(b;yF Ei~ʺP1OZ"ubLMluW;gk >pqa Rt]~_4XA@@@w@ۃ 퓢"4f>}M^@Q`ps )gyƴcSΒ`WOC;@@ {S4T r?~|Cm1m dX ZEB?7m 5HV@A@@@п{-֭3VYYif8qb裏'O Ќ'NF_Mfg5o7N>K5 xS+ =<`gϖ1c4W_]t>H-~8ߤ x`DajPCjjՃ`ѧ,rrr̺'NX\YooL_@A@@@8pР#@ rЩ+W\q>U,X _~}\|S(l $*3Ϟ`.GO%7 r5FpòC߸>0O+J ˔ܤp0  44uX:$OvN51tP:6@<##N2# n(;r3ԁJa XcZϽI`@@9Z}@/X(,,aۓҾ}{-۷oRѩ"+zرcV3Pq2rV;+ ۶m8@@@!"Gu-˖-h%22R&N(3g}JHH~}Lѥ^xL2!xX 9"V~\s9Tp,>Av8p\c-*r  4t >gpm ̔mi>e%!!~}UV-++Υ&5V:ud[ux8kډZ&MTg SNH3Xt@:1   !7țoif6Ԍ\4#]w%}i?cYhxO@13aɁWsZ}=oL;AA@ZtpriܚPw>))]kytJ[@?޽{KbbѮzS>Dv̧!jرc壏>2wk7xCz v|̝;!ϯ֎ @@@Z> S@.]N\twՂUTTW_Rзo_Ez2)4Sь@!й}yydAtݕ.Ҕ6  aѣuSzxl㉝a֥4Ks='[ll+O^|E[zWY*64}uɜ9sĮ7);wtb>qaU   @+xt854?4gyF\jۚKndԨQrp43 ] @Wc[^ ._޽>yxM9K#.>@@An`=#CV>wjV=z v7|]v8p\RtN]D)3t^O2l0>|}U@^Ԁ P^X7\|T    ZyUN`_4… ,:DϞ=e׮]A w6EqP@h-ݣ;L1C[eC~4 L7a@Z@4$''K/$ǿs.{5g͚U~OJ|||{@w-7T6l` A mcK\n 7oh:ts1+,t̨(ZV@@@h7BzxGSN*uPOh9#[o[|WrwNIi;T}hh :-ŬLSvYWF%n C  -A]5}aMESJZZ 8жS@p7="5O߿\~4h0ǽkNl޼Y ,?O̅x@@@hk֬F3jP>4\VXP5h +]vr 7~;f޽f믚I?w 6@ DCͥ gV6e@ڜ@49ZjJVA YYY4;v4S[ʼn~yԀ3fWש-tcǎN/ zjysF@@h'O}Yc9sf ᄈʸqmcǎ5N=~>̶ fYޱ)2cCO3@hW|A9}QHElA P@@@h AԖСCb~ĈUWFR3"Z  4M`{aٞajd'P#a]B#vF@J@7j+zBдux@@@@wSۃ]]'wt(  PGvVks ?[ty澮Qf rMbET; @h[GxAXdq|.m۶͜!""BF-SN!Cx\ @@@Z@UUCWlD8Tk֬q>|öFvvUSER@@iNf.l#7%*$s@|K z_7xR=x^ӊ-=>xbs5ktM5C   @JJ4Nh_JKKeÆ URtڨX:+  pb|@L]ޱ*_} k}vyGݴo:   @BBIYY9tڵ ׭['zVۚMcЈ @U`RUuug;Vz:tvu.@hs=W-ASgz-9[v9)    v%--y~ yW2tP wmhF߶M ,V@hݍ:Jvf-XLzrʪRTv&@ZW=* ,p0`<O8;oL6M̙c%8^hܹӡ @@@mӧ[ܶmLD˔)S7-":m˜+ oe2wr9SeDR/iԘyfؖsH^ۺL~KEug' L91w\'$l/K]Ntt׿aÆo[TO?-?Լ"   hЁk(((0GtRѥ/ƍsصde˖-RYYiө)f̘am 02* Hl.7UVȖd]>+]6eƝSQP@@ AƱ^:Nq=TBjPʄ Do\,\lyfFddd=G@@@|A 44T>33Cyy{0li&:ݘ9s$&&V@& :t3<)56gkCSʐM9c@ l> Nfɡ GbE4ۈʌa{k49Tp\CK ?>P@i.*..\׳fjt0$?Ϭ۷o@@@h&MF Z-hرcܹC?C=  <~˭/05˺,#%研7 WLD0eT[)?/^l5q.~^C/2׷u iEʌ˵g3+?N R x- ,%*8L~?*+~ޡc:E5<F=ט!.4Rw2㓿Yd4=GJBXu<+ PBCC%99Y9bnS'8891F      n̠;]^*5EJIq@D1( xW[_c=u>bY]JrDu+iLea+ `1ɢ#(/3( ຀Mrڴiɲ'ȢEtˀk@@@@\ѩHlKvwC]-;ա-ErɄw+Yo2o*ٞsJ_hfaȐNGS%Upu5u߁־pc N12ʚݶU^@Egh~M:U^y0rJy衇oW(((yr-l     ઀/9ҺoiQ   PӱNf.Yk o|'o,!%2CC d<ˡ=S_eF`]5q!;ƹSdU.s &x5k̝;52i$7n$&&<9vdgg˖-[>"x]+eȐ!ul    @$==ݫXtW@@e 46yT%C~s 7ki>$̶Wڬ?NmQauN7aCJ ^#1:]@^Jm+R>) Wk7pرC[.[Lt f)$lU5vEnQ   STJJJZg5 2I;l+9%+3""?L+$pCchkw1Sęl E(vTai"0 Z?4 f:tO:N@@@@@@]Urנ2@ha_y*``kS[ r`!rZoJ3hnLg J@A!=,_\z)9~xݽuڛ*wu3i      @ Y}'Y).-AsٖsHilw~qy:΅@ruꇐǏE5J@צ!%FKEyfc߽'L eW8@^z7OҠA 6m+Ww}'GC"лwo:u5M󌀳"   @s476ǹ9'  nH\UUU?ܰADwyUe//s@|E@l%ИޕhYe}Ψ~\󒛍&RC-ouӍ`j @\]0~ 4\~/,,'NHEE$%%1g   o zCt@h~5*\.>ZWj6°>Kz$ɒ"ٚsPf=FAN.4#.p]4eB       A쀄.b~й՘bK1]A:v[FZ>)ֶ'V**+hOI}@K rrڵ']Pӹ} T@7    $++Krss\j2vTivŒ/;v쐕+WJII  5Q 2Rw‡PӀ\sYZIt}RLF% )]6%-*o1%J}!4LkkV=uK3"NfYtj n4f @@@j?\~m9tP ك  ಀ-C5,,;m`dwHN-RNid1k&cz ln>`[ƬTIBq%¢Kӡ &Հn4& @@@Ȑ;Srrrn^@@]'ܾ! +s=u\Juh$y_[۬ PԾ2wU; h(228l8:Uc3%E<&l/y@:`yE3lgV ù  P=mh/ OM42'F@@@tʈ|Yz9m2B@@@̩$4˂'NQAA:c5 ;9adLc$t1ɵ5,7fMzM+/o^jUIYA 9B@@@ ٿ,AAA{9v*RXX(RTTT؛nI. @@S?ĸS'("tt -0V5/ |/3~Z+om_ad_1[&2.,Yr`Yʖ/NkTC;ĚfNrڰ x% 9B@@@>sF;w{W9'hpBnn~wȑ#uÇ믿W_}UN +V̙36  mQ`xROYqcr01D=bNAP/of9o]']vp$E^;]D]MׂwGTgB S.9B$좓0}:q)g[+@Mj h`xZYnϧO$:tOgJc yd Ω) ?Q+ h@@@(PQQ!6IIbR }B˪URSS'/]vɿ/@-?\2\Da#C4{FAkQJ+˭ Ye/TOk XI52EI\@$2Ր}bS~ ѯg7,ʃ:t?a=ȅJxlu2dHAG~Y hcCN   @hȔpW9 4po3D@@@74}9~ú}@N9QW v`Q @(<2xcډ]#" @3 6 57lb7 PT    o tA%///HIIo>)++o\gffZmm*XA@{^b1%NAQ+aOvu䖞5e%5)Қr YyxDJq8UC#ϯS #   szsΑۇ~(W_}Wk׮]RY~1ª:uJo۔$k@@ ٢j)?ɓ3A~ ~1% *tّ!C%Y x0X v>m@hFG_.   3 h8qvmOsFȾ}OUUU&?_~Ղ^u)**RSSuV@@ڦ@$l>..N&L`?8p@|A,999{ɼy,P!`@@Xc]$t֢8rv(5Tk\ؒs@tٔ)5Nca,FÏY{tGI֞ @1^ hFCc*A@@@;b˾PQQ!| 4 hcZ+A7nh.dXӧKTTmW@@,dLй}siM{?2[2L 4ASe%ݙR4uYײ[u8m݁->e8!80âD[-[nMQ&u.q*C!M"CAg x x -A`rzq\P@mnY@gMHQ_& foMmEB-t 3Bk0 FQs+زCRhEu)%,C#A0IA03A           >DlGWGU| Z%*[҇z`V nZ&-ȡK' Z!b Έx4 Yvۡ>YuUE6N?, B +jA4c &@@@e]!1:^pj};=tN7&<~{9.oh#P&D#XۛȠvGh@@p/ WW(**"*0a1@PPbQnzd)gRBTذt]MnRo;lm)  @qKsq"M@C傆z}pZ~e{RPvPo3o@g\*d#xVtPp߸)pWb;ﶧzrssHq͛7;>3   ^A@/N? J3dX3!]2q8C HۦŠpn\Р۩'|BUUUJk rc$o] kl'/G.umˮ3 8KVYS_C٧TdhC   H %.~ްw=qΓ7/)" ϝ԰E, lk*n(JkV:]c-#ǷCB.CdAE +/+UE K RzveAР@@@@@@@@[y{lt|{3SiWmϴkxfEG>bmvr߾qC) ءg_ZOcwP^ЇJ8AO @bH|/t o8,?{q@@@@@@@HKKVxIË?;\עB{ݫNjeK1>gCj&U?%\kʁfWV3Gio~}!=Css31D!4El2b&067dnֹoV& 5֕Jm@ (J X!{zXwe嘽F-cu6Orr;AU@~C!?u<&Oԫpq^; 3; g><ݛ[=iΝfumm-m޼|I t(   _^ې hD*3 @^=IL6FTS:p&v4Y~tQ7U7Jz۳D`!p9qVD~P_bHǍM̦8vO::"JII!X=Hkq;%]# $"i,(СG.i"  +@/Wp *E Q x!}ؿaW~|c5CP8PQ2 }WI+'/"ٱf-Pclvclma|lma?~h ,8!Sf/$uɲ z;ȂH{E h LHYi+ 8yf =ޮ~ [&?޾PNFf++&3!hQ7 ~J;$LQ  솃U} ;фtzbu}#; zg+p?on[4i@eThTbtQX(NPw [ kBf1@@N@rb9]Xwo3$t S---TVVF_}}ѡ4IYYY1"  ?QIfoiv3iA@ Zۗ_Mi10|"PVצO (Cr WD NFVOW }Gt3Ăʕ+;s  )faEMmNkz-:i$vDXgPX  "iYTRK5&WUo=p/ /;t:VWWgQ3Ae:]K-PB=8;ٳgӲe˜->Nh4ƍK͟?}|d>t?!*i̤H I *@msp7 ihzeO1tXLTRG%͵T*슢DKqgpJ}qEI4 һbX~[ǰ [nT9.yAEAM@O> l#plw5.#X,#?8H! j1b[n0RzB/'I&S𠞻c2$% ,mj56KE?T5Q% 5T;ZBXdA2; !!,j.vA+        %)55;e;-fɺ[sDD Qt_8:!XhP=Mzabx#!          ^O`x_Pm(C0i( G0i[h    0D%-uCxz^rAK*p) gw9N>uě:Ľ1$A@@@$pόh٘3D`lEUm ݭxy)# t513%%%7n'E  rit ff+ ?!@cS7`PEKЁunU$#+ 8OxG(//ϣؼyGG  J7]0: 9rb JPAEw)1:fO3%i@@@/ u m& JEpVJl~ ~1@%?YRMGHQOPrbtI[1naB GoSbU{Xz4*)@@@zDI#  #c         #܉[s['U7IH)~$]OwvѦ+>^ZO?&z4.@  h7      L ==f.r'ᔜL>::jkk***Ͷ Jy55L  " :Ҥ?1V[xs; !`   `E+8&O$vmVgZ@>B+F:YDA4.5c}udUR^i=l2"6BbB顔ն8]@@@FFu(A@@@@@@o [;ۧdӭ5c=+i2ԯN`Au>s{Σ@~w~+uq% (. p/ZWHp_ ΗqI4eCA@@@@@@@EE)SX **222D*^Uw`E Flb(NOOWx'Z!6oJL n<qP龿nT ҹci|Fuhq=^#\GpX5&/aK]/ʹyeShVN2ԴߓI>yng×n@ ĽPmn A@@`v1\'-->]1+M&?!X@/ ] :ISMiþ")NX\xחҪΥs$lBtYch?/;;%O\V׷l2d~UV8.[:աvvW_!>UpJ^$8H'&r(.( "fckL`i5'PLxaoW5Yx+~4np2uv.Y<e<A@@@ + AzLBR7mDk׮+V j4_5Jٴ4Q>%֮gF{SUJՍFbwZ&_y *z]}ۓ+X,0B 1oR}&,=8|5'[kpB{ 4;'& A D<WVsQPP]|^9Ol6˪õ^K:|xw6tB3bhVPxx8շtQFo+]Nq?!'TԵRYm|H3]('T3%IN:Tk-BQZ@@@@`0FP__OJDe0,YdeQ@@@@@@@̟?ƍGRŸ'Zz5sϥ>„.]vIyʬ>zh袋p }#ho~S2Ά E<[W1.QsD-H݄\0#KdA@@@@ xT-lر>ڶm0]ߕټysq@@@@@@@$Uޕ˕3H[XQOIIIn*\UU駟~ C#ppYS4w66e J1:4+ B%N$57_    # Б#GF k@@@@@@@`J￟z'CuuiSOQJMx:j =>&]1\~NEoHCzzJΥ3G .BLaD~B{_;JyD@@@@@ moK .H ;;֬YCW^yeZpx @|Wϡx e%ML׵еZ;ٝĪ[Vs[SEB5 @@@@@׍cڸq#߿O:ƌCd0MF"VN{/kÇusC-?2226| ^D )@sݴ7OⳲKQk!f(m6 (#!O_AB>O'4Y(,#vu     0,< ;VA7-8K 33n&iceeeTWWGd6)>>())I;[?x0zshqm;RNBQ`r:G KuOf~3 hTPdh !D@@@@G ǏWUG},Y!       "V&LPG#l‰[{Hkݻ kZi-TpT]%hm Gm#@@@@:T B}yHŌQbAI/2!WPNm&26+[\ݬ$OJT∀p!1 wCC3@@@@@@@I(//O)EWV9RnnU+6oP+iW\<'^5k|T% CUCTJZ85C^dO^<3'Y#    N\F˂^rAAZE         00RQQAV@@vYn`2 3k9J)q{VaarԜ )Jwn4t:ZtuÆ d2cD@@@@@@@@@S:::h޽~ecq&W@^'ѪΥ%͙y6c˟R[YJ=>&͂c[n40+$;-` @@@@@@@`BBB(44j^2C9m #oEfK43艛Sww͖i4|r451㻻^6S#emn }$>^I&4     ;wsUVI+d4iʕ 6@@@@@@@|/8`y  g{Jh^+{OTј\]btx&s_%J)<] :GZ%Wk6U]:w-9J9:zi:\XkdM-!#,}⋩}Y2ʹzji唚J))) eP@@@@@@@@@l |[nY o/UַQaev;1B?=)HoV}Q}K;}@X +!BEgybS ^G v\eq ?|>EFF`,jAc=t'tz=U#DcSY. -Ql:PLejɎ<~LpQRbwݴnG 'O4{--Da%́zf2v{ijaai `k=z< 立 Ḣ %Pd#Eu_ǒg{utƨxjcixbF#/v {{:U!ak ɫ6W'!Zϊ =wˤ/  #aݑYlh6Hb&!r :xC Fc2ziƍd4<{tSzzrHp?d;SyR &Sz|;Yl/hYf?{ Za7s&rJjo!k3DSF驔Gכк}_&ҝO4ߏlm sib };{+aeS):{4vL}R%}tWRJJ6PKo?'^}---TQQ! )>C+h޼y,_O<}WxԿDLoX,Ke˖O! F/ϵ+fPw]TݚQNzԀvz᣽)v!:jZ8&sl;qbe|@E}-D&stao8ϫ(R,R99yonw(fc㻻)MX'\  'fb!P(⭩Z$CK ݠEXki_~5-b5]u?O%Z驧+V… kJ2M^R^^.?P~_"׿J}'hxhsܹsT 2 ɊFx[lOHMD&6KE BCGLܱx,mBf,Eh܇Y\e!دsD bC  ӍxA6W̠߅ji}֐jS5:sҪ[8̃  0Y̒SU=Y 5^Wi.&k!hk.%x +1C\\-YRSb,0`슂-5jT۰a!((-ZDْ vsqQڵkRn.ϟ!      L>C'؊'|b{,b˓e_~ӟZb)С*n ͡A]]ŔIKg \pub~갦fAbEyb<:VRT碳hqBpf_X䊖'`xZb6k\Ew`2BbW;b+~V_jA@ 8PC)Llm TZˉ﫮`۷u﴿W_,"e+..@%=&&bccmڴi4uT)u8ثa_N!!K%`6m"衇(88nX0eFwyTDs̑^ʼ[ʏ@~y/vr؃/`논@@,vdא?3f[z뮻@J{/8U i4|ΖB]VZ8vfƏ/AI1*QXd[;h籊>UO>q|J+>+a rTs|m&לW36P L#VxB46C,p+mbSMUR/[Kd!4޽? 5뮻N8J/P*  p1UUUg7onu>n3:˛o)%޽{%Q:       vܩt,J`mؼyUҙgt-o~)F0a9 n ֡ͅ+Z]0l-Q0^`F1`^we`y]hfC:iіLÐwv3*<V/PO'pj:m 8}GwQ֫V 1MN3Yno$a1Qac54VX""&sc .-G%EXw] z\+#^x>~.xƗ_~I?iq'MT]y rXpz)9Iw4 a۶mJ>69Ћ7PII6~V@@@@@@@ 466ɓ'!\v aJ>{V Bv8n, !"pMً3ϕֶ Aݖ)jzO?%G {1z7)*yUeFJZĐn7ڔfDD$&E"lQk3fS A@@@@@@kuD8sN09bCg7rxHc t۲)'QlD(uΞJ ztGHyb$v4ngۄ{YD"Hg_ۼ(`Iq)Bt#4*OJl,ֺSLlUssx]hW$ =z YʈW|, Ihf0ȲSUc(+%?RG [n\N#8̝;WI/H> _ꫯ[شv%cƌQJq~QSRR;bbbH6)sS*C@@@@@@|bi5 w^4G&8h$~ /Ƕyf6xX"66NJ3gΤbueAرcE4ߧ 6n4k_&[6sZsljh 5JbycAb"Xp9@O#2*8,^o շXѡjE;psN4yڼL<78LliBA5H56 k =/E 7d¨D% ^Y{́-LOhd="hX~_s= lq'ロL{ݺu^%hP8[MO= |*@Ȃ$]p       -xO@MeVVUbGX|:Yfɇ}_|U#7V |7矓Oɮ>9B~!]q4o#+.坫,^;c"&<&B>.GV<"Â-34(TF%F%3sصmGssm'hji2!$b肙c3վ{.o ?o2I򄀡էIQI4& b;-` @n4ݻ+R9v6&ovzOƍs*w_ `pNfWئJ_12 QVZ6y $ `gp#+<+p /_G3wpDg*TPP ߧK* _n+a믿d~+ >Yv$h`͚55+V A-ؤCW͑j7YĤcOJ?ݾ.*2-^0#nX,V;8|YYN L׌]D"KyE W*NeY40oF/K>0HVkh<4A@-Z\#X Y_Z?\$qBrpRzX bq(#*A|6WWEvs^ 0|Uw]`"hJKK}Jа>.r2V/V jESPT^JThVQ}W3/Lh8 NE#!,V3ؔ@!SL_h@p\N`O^W7;WHl#؂  CENHʄJ|1h-="^XZHdʒ.87:d3 oߤ́:qAy%\aTCP(//OZ)^Q}yѤIf+h(-Jͯ6ʆ( 39W_oBBB{VKk뮻*t4y睒ANdQÜ9s(''z-I5&۾Ka l2Ү.iLbPr"JwAMGQor@H{ӣ>:$\#1b{k ~uěioc<ydxQ8E`_?7@A@DtBXZ`Ci񂯺F cY 1)x]E/ްn4Eu`PWp]C-wb7r8q"-_\>쳗}'3L:CyA@@@@@O?eol{}}($$Tnn.8p*zJA>Կo6+1z(͓&N|M)oݻW5!$tL HԶ7K3 >H"!pBHExD}GxZ߲>s>lRkeЊ)T{MD@`[:kդ%Bv!Y_\Hu+_ ,&ek Sh b/ Ģ"_lMA}W%b(%}I>9/Z&L@wq'Ru1a+ph8K<x#%KPLL2'mf GJ{/X*öm۔n~_;w䞢Dʶyfsn'/GR`-Ҧe,H$C4%PAl^ AΎ[-k@%mmA,t Zvˬ!Czha< K[pB~c%{-.8!\*3"/>]xcȑ#C48q,7W|pN 6h+XYAm~Ƥgz\>\csW%dZHML]}&-)yg]w2HNc{*LONiaN ɰ޺}}&LaiԴ~?֊3ϔ:~weGRtt4M2~QFF!ʂ2̚5n|=;v.(9I4X^Db@٠K` R,lkܚBY(D)᱔+1RSD73hݎ(2.R-0{\ !VHlM t%W _*pϤ A:USZ{xd!æM$, r UРvl@@@@@@@B/\ڴv=;;~… %rޞz2s xؒ:ٳ5=JW]NxM,zU9s& hay KA`@ZLiĶR@B=;['S E8gs{Fʭ奈 E(<(…'D缵,.^\#\PY^(n.J[R Ņ+%˘1cҿ% V^MWʑK5[2*hu!>>^S҈]n+˅@zaIa im'X~s$äLB2#mAmt:O1yq+uɼD)[-C D@, [lh8="D~Y@)$5F]D (ho_&YYAJ>`2[?{^=Y)[В~sn_+9mWф (y0^#+W멹ǤɆ z?^x UW]eu ^"6(\ytI쒂_@J53'$$؃nKvr='`GMM#/bgEҙ Nar()JA  KXoeTT-D 5*,0x*œ&a7%5!pݪOizʃ<"h`v= kN^{-]tEhTOرjvee)p{9%E ,ޘB؃vHuy, nb+e<{@/]Yx""Γi”j. -Wq{ptgrk M7Oڞ! G̤4=q Jk[h<}(DY(ph҉A;I'+N }5[@ɫ/6{CtA{d+66J׋s E ,Xhً8[\g .HgU}UώQ3NK玥R8Z\G}UJͭݚGGӏϰj>,82-:aюWʡU.cp. On:WFd{ɓz*++%CG}exx8=䓒IDBGؽ? 222ݻt:tTyjeYPP`fVV1@@@@@@@ svy xcr J4n8> `0YyeWiV1CCCm۶McCjwTle◢rw/ZpSj+ow1dYiߔ3O]]3E0az%~3꿈ͼM8a7:44S[:fb&:&aҙ73}u}-U5R.m&js:(ƮN鼆M%8KLFRNX"e%X/oC yyy߶zXȥ~3-;euX$!}fUkfSbts1ܟ C 'N$vslhhɡb:X[DkGߋ?_ o(ANQI8͙a~5bK5s% /şY{yJc۴iӬ@; zKJJh:n5iҤI|Sߑ#G4wN3ieee =>벳) xJltRO6UJks*Gє-S^l#,wP/u5a_|MMEwHJsBz]WGI&& = 9qNN<}y*9JoJնA.H#+EypG給Ak{L2d;?\>_1A yz@?Hx(_W.yx Ԗ|X/D7=ܣ0ӝ?J1#J@`      ~D ǭ[}n eAÉ'?)y晒{yB(m_賵Hg/.Q~y8\~6 H)LT8ObҞ'j͂:;>y{LoEC ,")u^WuP"a/=T fnVL m]Ay; x>O7tS7uPu,L!:jMfaeUMŒZxmSOuIۗ (@wP@]J `j(Q T=zT|p,9_VM֋l/ =rTXX犿QF yr⊊ ۮ;} X0tJ8\ѳ5UM;?-CUimdHw %vJ[}8]YO߁lN9uȟ K d [рMM[rn>OEMګm릗v/!2PnGha%aP %m:['=oY26'{/ }Nhsʕt5 !dZ} +Ҁ E7В%Kھ}R=+@@@@@@O|oիWK=f٥޽{ŋ#H:dSAo$9) /P { ljdQ=`U6mV6#n ڵ]) @@M ^}iMKΠQVuwjDI[&ۼ"di 0Q7IJ96#xY`C]ھZ  <[֤-,eo)1ZÖ#Ut1d85&5 /cpD]j` um k5ИnMrXxIXTj@ "(Vu=_m4/ FW9z.n֪=Fx PBzyr؟L57t01,bx6 z6?DU`KpǞ೵ u౩s%\b7 aϖ={曭UeO"6Sľ@@@@@@@_ǟgvO~_// wUV?n{'m]L WVe ʡ$徱?J1~sZ_lW2l_C'{'-bS tâqlf|Q@6tF]yIp{ae;|j'35%؋8 }@cO(V7u{S>Ǎh!TCiot},9Z┙hH%[q>7NOz0*H}'`}ޅ.`hw}2 141:GJǁ3YkpϓX9o9NUl\+g{] OsG!m,\萎Cr{40ʊH1 4&"B z}7Mf,CWq% ^KcS^^t}W_}gZ%yQg`'獏d.rΙBeDT뒤K/%xs%yD (4Y9~ iKhS8%+Ֆåμ, 3gJXٻ8k U{ ƀӛ44BIx䅒jH gB3ƽWMһgJ+iWZVw sg̝VΙsrJwͼ Y+$BntT ))), \pk&v f?ڍ!"VA#UxYvS@)/:$jۮsJޱ-$83U`4L0^B_Vi]ނ[xR2B H$'e~$[O,I3LxPkyxQnEĴެ[qm%Jd5kY.@^u) K ؞Mz" 29)>(n$ )+ YQtfRJN"$`A Z8A>]:{ e=6ިSa l~.׃6Ճ ]srr\zQQQoc޽m; F,XM \(@ P(@)X]o~-{J;$#<=gj+әtv*m$)2 ^w^J`p*Uz|7gѮNc ӬQF kʵp@=ſ_:]Q9V8^;虦$aj0Dv>J<_r [d-ؓQ2H,y$; Ս?w,&q Ip5yjh,LA *>]캄F3+jQ < Oқ'B]$ArT݀y*[uu Wm/7I?g xy-d.zYz{)L j9)gFsK~,y޾8 Sq ?cõ 8>ksU#wFNM4mU^]nlZ{MH2Y48nL,tRdχ /Ia +_(@ P\% ctJ,^Geƞy ֒aZʼ:Dc;/mS\UuZÃ|sΌb8,+9?wO 2 {"Smm5j"g#A 2P(@ P@vv6dsL/f̘ R4ֹ~]e[=A2|OUOJ9@ٙ/tYu܎ӶrSuӁl產IX287v'}u|dB8V\? AwgE)#figߒ~G~ tHמq3cstv4F 1.*cUx5Tꦹ-7e,n/}J]co'~t$c*~]FoF3>>߼9PT` 2!:ngGŅ"#S딠*mzghhl B^dRrtYޛ|KB?ul({OaW 4{(-=V,OZ nH AZ7V# ñTknej^eUd]>zU 0-pA~&Z/ A\`x?zո^3dUjhċ(2uٹ0պ7 wu=jUƫ\j,_j֯oI+CP(@ P(@ e&3||Q) $$$`ZLIII]^JFFtXa@ u!zqQ5 7jzrcnga :&2Q{:6? A^HGO6p; ^54fM_o)*$\;] G: fh2գ64ayh&~h/($ؾ_B)|ucK/Q*HPliʚ#m3VW3yzOi Yg8YVJ4/s]϶!idښzHoI :>#T6MF ᭲Y@bu@љ[2-T7IUoJ TmAa&cdm=&$:ԡtoky P(@ PzA@n[0n-[__厓&Mnt''+`ٙvƥNoYفOlo{\2n`䘐Z^žN܂޵ןMr~I/ ߩrVuUؔ}X,O僄 G@S. zr>hm҆-}T4aѠ<015Xi&uI_Z[7lF]P1M hj fhP! #;dRFǫZɄa)l6 'q6Nzۀ!Π:D::^]`ldf^^jXhdK0wzej@{-#7eU`0/H6*A&UV!d"yXDU H|UB*D-Yu-] `@}uPcg뿭>dLޛ,#`n}U|z{Żm+Ǹ0 83.Xfwл<:(@ P(@ P(vtL2Ggc8+H8*Ɉ41|x{OwI ݼ%KKKCLL܈9zK` hL:*2dI_ nh r` rGʮCe9oAԙPU_=IXd^^W ɨPV_ՍZ_֕y_uz?5,Jp$ඡ*¤v<T__`; u kQ>]+SS5v쬴9b\T ???,ʶmS(@ P(@G<|pf(7>liyy9^u,[ ^^oH&W_})-Zp+y:˦W6h7܏. ޿*)W}y% cS`Pc#mGsP,'G%k !7$A,3͖yë^)eΔ3sf*xaCvO&DŽgWNýWLEqE64˟{oː!j C{_e$=^< tzdl<[Ȱ1qjw#7¾S/s5IX$G .M>hu:P7ղZhEW!yl,* o/xP#>*@I&OP#g,}.R!OhR2MZVe24s6\8$j r!sjUQW˲F>I֖JШ\Xp$G#9$ )*Аhm.AZr;3Gۧ`'}cчDƊн?UDAsf׿^?S]a P(@ P(Еdh6l222o/^g/qZOuCCnsŦM]۵/eoV'z  GY?tP;Vo9aXq <65m^*hZ^yt k:Yh)jޓvg{ݝvrS{q#I5DNUt`5&dy!E/$j _G R‚[Ȕ岪:h7eY/u4ڻ"I?տ?\|9m@VQq ÒYi6fylFk8X l*`QuKPd!F 2$D,IV *ә0ī 20$p*u \ܺ[Ėq)".pz@ SP(@ P(@C@ =%#8 f00\T٫NsFdeei7o= (@ P(@ P@ꫯի_~%ʰb ;\Daa!y[JoZ _/K04ǎӦ$-~#44&.S GkfhCOROk[>쪋S:\G52rJQUۈ? O r|I1++Z0u6T`G~p4aC_.IhCG gjUXi0R>bdw}H CGW"n AC'aU`CU[ L>*hҳn)`C@bT37T C3Pl\>W!V ?v6iy:2cհX2vf[}cѣZ̙3[wZr%dKO79(@ P(@ P` H6o?q[n7ߌEA,@9[D&z~GEEo{57xd9s AӃt0 GKJQ/+}Yh4fZ *峇#dd8O\w`,LM25D“Rt3QRs]h;̊+Gqe?NƏ.ArB[NbH(O|djl#C84yעѷF phBTᡪj.P#Ob!Zf 3{; e sTC e=9XO$Bzz֫ S҃d[^^/*e P(@ P_eό »ᆱM36o$b. K.ծEa&!!2d0 ^j^ MDxJ*k6S7&TT׷.Xw[9CZ!LOCօ!*$Lzɩ,t@9TAko5 Kn&i>U%觺^ AQ u!2~-Qv &"Z3U&Ry%nS&/O-H*x^c ?n@;Fdy2+ TJ5W69ht~) !ZU'VM]g RЂT Fc@w|e)91eyz(+fh$ݵ,HKK\:(@ P(@ P\@śow@ 2DCDDj%A& PcOv֋!ၸ`vM$3CG 0>^7>ߨ,@~fgMq4YE GZ\ML窮mp]5:=iݶ9*Kh7ynsr}YIwv}v@ܺh<~~4uǟF:$TG{$['͓ dr2KzPӌw\4y5^1[M^? jvqM>0"!> B} S*+ѠR{i  ," 2K hчl1 gv/Ow^^-m/ HP~mnI&{i\T򳗯92TX S+93=J v U|ϔ0}Y.ReTV?,kO.H^Ap 裏"''+чV|aێ6455iTfff^IB P(@ P?m۶?|wpiZxymRRƌk|HŠ @/ n@n -kf %6&- ᛽g[hӗ;OߟKT0Ŗù8_ , 3F nJݧ7pcQ)O,AD_GMQcŷUֆO|+wɔaoESP5RgUA [ ųI n BhzBݣ 1Xp Lhl2AM2IK /uѤ5A^n^TA  A ~3?&,@ $0h}{{}Z f^da;>o* Uז)ٺhFjV[mFժ@P>ULM-V7k5 u5wѫs6 ό@Y!SO˼eA*!'!j(}.AQIP Hv,K/ h%\;wz@c?>|ADPYE?,Y(@ P(@ PӧOLz҂$AB P7F Pn~KJ SO?N 0X!j[LjꨜPǓ`Gʑ_8ЎmWF0< K&i Lc3SŸϱח @}a ߲p.5 ##0 8tϼۏi]~gQKOL%`18wb>v{2 pHҟu[nGMݫ^n; 3F)ʻ:ьQ]50յD@RrXnljjFie6DHlu5A\`69r&T7ԣNդU]CԩRTV#5 3^ԈHaV?rG?z(WK ܗ% fe=!x{z[]L-{`'|dR$GТU}'?ˀ'Gl;`z-|`1N8ѫ;}٘={6!!!x|T(@ P(@ QF K5dXh$;^*[`gz>H@e%f !|p&]֫kQmtyB'5pK>ؔn\sT`^F%E@9q#h g.hP1_X딶,OW}?cBp<[m }TPhu [.A 2E  ,-lXl9n؜_.A-(~2TT[ko"B:1}4Aʎ f|8\{Hc[_6ꖕ63xb`cTonQs>T* \/?:It T2d5NH,i{GƽWLֱ(Й@dhJƗ^z ?o3glצW(>N P(@ PѾx7س P}, W~qo?Fuڲ|$^|?4,r뒙춙d2omϵ\mW]ƫCqE]є1v퍆ڝ-Wid8=Xvp;HƉU7-A7B<>3ƾƾ ^ % ON -یl_Z&<Gju2̄qm|!\`͝4-HFppX ]R1_^ɢ[C*E*7exWŲMF@ڗ ?S2l RoV~$FuyyԚȞ}<(P:Հ(@ P(@ Pp1dggl6#55iii2eVKKK3/܇CF +UOk Vw!.'l3yd84\uHl:C;;#0*)vSH&{#7"-ReZHIe jlۤ3dlW 2 ?msss{l0h0H{ 6e; P}аb ֶC2c;P(@ P( /O>A}{ծSкk|r?~{eeeމ@(ϵʚ)] Q`-f[,Wn[7@\3w$_8n^<˲cj<).otUMMerZ=s G[ow]] ǥjF(@I@Crrrw}(@ P(@ P999xpN z _5~iu>W:=.7R+p\  8R6چFGw|$e⛽,3QUۈ`_LNjazs˰ /Wa&7 9c٭O J@2U,?o;iMg۫vH P@4ܗ(@ P(@% Y.}kCHӻmEmxmWsp3J{S\>oO36ѡVYҽK  *0K QË'gfo-|<-C\D^t/ʪ]h5}WMCrLHm\A Pp hԓ| .BgX(@ P(@ kf3#F@HHN:L^ڵ WֆPYY?Xnj믿v,{ ϬEnF _r]kwہ0l :$R"!LJG(=sC6<O> (бi)71ѬRT5hCL1-(@' E@CssDqq15J;$}dcc֮8t6l؀:4: P(@ P@?׆? `ӟ'N _|1uEEE~FŠ+0|pP-p='9|MXyw;|$D9LP} f:9Qg>9wϵf PZO$>Ӿ8}~!x(@ P(@ $Y'O / O}%aΜ9s;W]u,$5 P#R֛3,[0Ve(nwա s%`Ʒ:W}z%A[0K1$ fxV@\(@ PHU$G P(@ P@ a@IDAT}⦛n'SLARR4p;?),Ybu P LŪ/t` eg:\M;ts#X2rPWoFt?2`QqX: ^_{PkٕӺ { wMZ۰@_B|ot\(@ P I@Ú5kƳY|||ooo=:\jjDee%Q]]b̗/_. :V(@ P(@ PUUUV S&L`48qncǎ#<8ಂA\D$qEm+<,\1A֊#@& U,􀆬J7_ef!:<nMMͨGʜUIm I)-+& `Y`c(@ P xf_J6?Otz0IUm/H@Crrȑ#xq(@ P(@-`m~;w`%ِO@8kL6/`0n=e/G޷G+v&$t]c?[3,w +(@ P S(@ P(0x 6x.WJ PM~|$l:/wzӭ'p,#yxorVWΆtu1tKVm:[Ǟ1sOgFF PA `Y$u_G2rX-AK`ĉѾmr(@ P(@%7.WK P <<ܒl`09-Oo+(@ Pˇ rѪn9DgCNNƾB P(@ Pt#Sk‚|oŻ"."!zZ;zhb}Ùzs P(@, 111 Ciiƺm۶)$$$ǏGCCS rssqlc+(@ P(@ P(62̄LE8YH ¨p$ ͟͡l3Q(@ gh?D'Ol{2-+b}}=va,[Vd'N:+(@ P(@ P(*A0r8,.J+ P(@py@\Ĝ9sk)))~#dgflPqY ~xP]]m욘hY(@ P(@ P(@ P(@ P I@… ohIvKbŊ8p>22s|I͖-[PWWACW"""lm: P(@ P(@ Pp@ kwT6 <Ӣqdy{9p$6(@ P@4Ąm@VթaGQ[߈ u۾c(@ 4 6^%(@ P(@ P(@%IâH&yWxPʀ_.?>݋Vj"pͼQ4HY(@ P<]}B(@ P(@ PSEq-7/==/{GFćv=]/~Za(@iGM=A}Y4559<(@ P(@ P(@ Ix]K2 <|Ynq;a'LN>څ3Rn몆N㏫)%/n7R(=fԔ#YjRLWk ?r\?znNЏrz@Czz:~®;C '?-#qm::깰XE3y͍V]/(.J ~}c BGqT{%ְA=mX"RKf!&,/gJ]愡Q)Hxl<²vFmWJRڮ>e0ɵNalJs PVˀ-A-u m =9 Ԁjy睚cdd$nv,Yd0)@ P(@ P(@ [Y0}D,dpf j~{]xh/ea#;joNtA wd@#`lK PPOl7֜ڃydl 85!??0,**B]q{F P hUj*< !<;vkTVb̝#[{j/W=ms'ovyY}'7}T߸(@ , Cॾ7275}aSbnˆ(@hjnB^UX!e.C6dV%@_˺ >a~u)zEG[?նa<3Xd bccxgO})@ P(@ P(@ Ph/Sٶ7X텋f (@ PՂ -xA+dШ:*֕ Au o?$!da|+!)) 8~zj$Ej2Uc=h7|(@ P(@ P(@+؝^ܒ.'N蒉 (@ PIA(Oe# p&ӂZWV_3eG%w{GwPCD|PX/O "T C} S7x#}Ѷі-,t޲ (@ P(@ P(@ 8O 4<j3C]/@Z7,\]&F|Nh;f҆8x JKKQ[[;`x!(@ P(@ L.gZ(@ P` ȓHզvm PpoH57j .d`? ?am)dX ٬-u]طoVh"(@ P(@ PN>]vyb P(@ PM !8饹.b'@4횇LI]/*S_(@ P(@ P(@ Pz_2 4bv?z'!',!ORzHYuw4;G P(@ P(@zٳmT/>>>9(@ P@hh2#2B ZT -uĠU63s4$@ÑZ"x&A|sXf}pbĈEJJ;(@ P(@ VH\wcc#ﱬVr(@ Pn$PZWePe\в.R4Yvm vpu`JoUBbpK'6 DOˠ(@ P(@ P` z뭐(@ P; 4,fWP uU uNn^U)UF~2"<G \h X3-x< I@Z[(@ P(@ P(@ PFCT24zZpAoK?4B[nPRmQ***lv?]؈(@ P(@ Podkjj,Znv [SMMMV0;jnU}cۤgLm{w䶟ep e\5d+Ѽiv)չG곫:t> h?lقw}6mB? ~(@ P(@ P\( TUU֍:cW! 7#6E}z֓FVTA%NV䉔 )9:&OތNՎٓ z -o=y =J/~Dxw-o?QсN?@9MۯfPPm,A"W>>>efD>鳪2fo8g.qVCP.ŋǮB2?ٞCqDžc͇rydЋïaeuЅܷ0z8 z E@*P!%-szQ)nqcٳ^RPu֟I4!.0-sz\@L{Ɩ[W,?mo Uڢq X(@ P(@ PdffZ}*iii}qAsNI(K 7.ܩb5!c[40e ڶFw2:*~_z2.W`θ;,KC˟նX?Gp`OǎF`ʅO:/(@ P(@ P(@ Pe":2Ԅ)!]ѲMF yUV ѡP9؀*k+ ]B Nڎ'2qD]-D P(@ P@HHH@cc]}vOn600桡1P󑛛Mm1o05i9|||ڽu܇\充 b՚5kp7ۛ(@ P(@ PpX`ƍx嗍~`*xG|rKˊ /?nٌu PzYhV ~wYNM4 PjTp™` Xl\d0puUjEwיXueh0 `3 - o:y >)FK 7tӠAR(@ P(<7|8y睇K/Xv"Ceg?C=*Zb{ P) Ҫaƒ|s?PP]n]:BqmU,HĈpYUzr܎MV@LMȮgZ@_PGq=(O$!>>{/dlK)?u[5b7)@ P(@ P@@ؽ{zrzڴi۷ooce` wSs΅zILLԫS@/ Vz̐Urc9QxV[Cxr{Z&K.V:2!Z E?ѮmoI/קWe_ ѽ`nD:,(DC1MY0Ks<蓀!]x1ԍXj>S,Yqqq2d6990_5^(@ P(@ P@nn㭖힟ߝp~* >ln_Jf(@a&cdTh'`=&0wy.i^fVeK''۞N;W< 5rxY9 j6/K c v۹OO^}U:uJ.deeiurK.}׷_5(@ P(@ 8JԸ=fihh0P(|sp듟冠^{!.dA.,5+gw)pwx# k7 YJo|UJQmgSoG/Ȋ)Й@4lݺ{_F P(@ Pjo>$$$Xstɓhy:T=?S/E}cP?aXyk@ A2M,*8& @ݛ: <:s1!*9U%ؤ^ٷjus ~B?m`1ôL yj;^ $aWqX^fj0^)V(`@4=(@ P(@ P ȰedUa\p`ǖ>ȪURR2(@ Ppģol17V,ƈpc+VY 2 2BVEQKXl?שUS3 GCOK"d&5z:ӫpx?o{_ VL£sB01:⾯^Es Ø0s;|sz?֝n}p{sqה-Ejh,&=k_L+}kI=)0$ 2P(@ P(@x{{cF&ȯ nvڵx뭷}1bc Pz. |eV~8aXƔ +n+`njB~u R(ւ$hA ^PA2Bi]U}?Y^ 4xp&p!͆L κf? M my[[-O$k~ g%63>DaGFܓ+GBt@?+@}v3(@ P(@ Pv,]>gdŋJcc#>cȾnC S ƑLs?]>ea X TXy.N! y5(6W#Ws+K=?H^}-+XgZ"SAo?֚32HtT.U۟!렖A#^ h)P\5^q`}x-s'vQ;*_oŖ(@ P(@ 9stwfj*Hܹs.0I=YWXX[jm.%%]t:.P(3'W߻ ?v6<==zv`Mn )8  Bhwo{2%87=r=QeZR4.E0tVUƴ45T>4>؆L\.6,4zbldӍH4H.ZaR ](@ P(@ P,'x?QT[^^z)mDdd$bbb Tȶ|H"m|Iu(@ tCpf1~oc2+ w-9G\vl5$ "ú$DT.;OAʚd|j# Rguخ -RBb:kjlK2s[P] xvق (@ P(@ P iaaa6{* ~ڵ 9993j2dcq%(@ Px h47i;O:G+7w홺wVE1@G| ; LHIkvPNWQg^jzsfo P~fhߊ-)@ P(@ PpcÇ7wyÀ.A8\s5X|9N*ގ)@ PxgQl:zr| ]]Ǟbw{6A6uZ;v"& i*6.{EF%&59ٻ8?uZ]V-7 c 0`C B桅B}M1.r ޭnɒެsI:ɧ;egfgwg>wHXfxhOqjg"T.UP+C u@ya   t2Ho~#3gΔ~A֬Y#;wln(I&E]$iii5@@`Cgp4veFI $Z[cH였@-*`"Ͳ@e&OI])uت,A2qC^Ϸ%&JYf)3쯨! Bhhه    妛n'%%%RZZ*';2 J`ONI/u^, 9%ZT66H¢\ہΖju  d Ђ$K0+;sA]!$hmct tn뵒BKLeZՓ?~"oMzmӱõ h !r?ٖooݙfO?p9   tU5kCfffrssȑ#2q6Kc@8]`3מ^5qC_[, fYL ZdЂc۪А A~-REY%#OgZ0``Ml ע F&m h֮̔<]ydբ\l5Vi`P]+\R3NҾ3(oǑ   t6'|R,n &yQɤgѢEqF`@@+U\4rH["BʹPhY2I4 Kpũ:Gdp_bEif^jj-"Vχ1H)FHVEGYKϷ'SgjJk>Qİ>z 8'@@sNB@@@ wyrիڃ(y衇zM. x@%aѡY V, \1XQNF"01m|G-4T[fpt~Δf':WZQ/Xg_[} +?3=8+6M^yp;R\S.9k]G0g'ϻAf[ J!^|j?8z2s}5epR'h   )0o<:ףG$B@(j[p3f9%i8.#pNB/`o5̚O,&T\"W/Aڝ,kwv,v.=j) u1)" @@@@S ٳS# @ml%9# ;*4@( ^Wb2Bm9`oy$HH@fJoOװ8mo!4(D6Un|-/#Ǵx -a!@hh#@@@@@@%fbbj2 DO4M;q.-3"$k7\N ȌM&Ah]PP =L&袋K/mwojjj$++KrrrH$""BbbbdȐ!2b o9@@@$(ǎHѕX@@}]5zQ5etSkqr@I=f˔7ϗjꃔ$u˗ŋsYSYY)*hb׮]_UW]%Ǐf   @PS6448PQQ!,ZHEV)::ZӶ  [X fow5;[Ϋ*AMaOB@hгÇZ>@+l9@@@ZCɇ~([l<կ~%7tS]zO5á}RYcԨQ裏j3ڷ 8Pg;*Q\PbR$$QS 4xIOeժUg|%KeҤIү_?ILL&v-ׯׯtRIJJ &ud@@@ jb CwO8a(/ڒ6lKyIMMM@8M`p͸08>KZ =T  IJP|G}O=URR" .{*~`TA cƌkw455i+>((ڔ-   ^-P\\,sΕϖ=*OLO vl@@3E'dCP_{T:=23B[;5@^! 4t೼sNy7EIb#3f̐g}ֶ={Ao>tq&;V > JOwu6   Xԍm O>Po_/ U;$qC0m{G{n5Jjŋ˯kf仸@@@kϿu* yr dp@V9 rpw@  *@8c hPSE;/ԗ¼[$&Rjo߾g Б'Pkn3ʴi /v_ȑ#c[X`6n(4؊G@@6e˖I]]-EZ ",,LsuvM2~u]q˗/'ALHH6d ORa%A1.?Ռ 74B@uk&VԮj=ajJIU?aQwYxkR}SS`g?3CsDDDH\\^n)"*ºvh~~~Kه   l\TZ fPRjb(5,8XWS@\ >9u%\MU.F:}Z???<@@@7 ?vݩV4ئH2dmU QHZ[@\'P^W-?YԌ  ˾R܄WP'KrdP|Ou3! G<pAy%//MWwG&5deesQ@@ T׈=aC-aoi4YuDRA4t,D@ hPJ<)**JRSSe׮]>mذA~iywy`5`Z[3Զʫi3mO@@@O @|۔d[l6_RR"ن#G4[*D@y@.Ձ ,S+f,BeXbEwe87 Ic *6A-0sLꪫ$%%E:$gvp]w 74LtR9pq]>;Sc_#功&"L " ؿnqEAuw׍A/L'NBn*־j=۔S)[3ȟ'Mxm4lݺ4ÇV\Zڂ (]% :"u QIdT20.]#9' H@úu kY+"w@2f1b6# dwyGX]nk`ڀ۫H;*/hp `smO97 gMy{\wfԕxxg=qULb{͛ {t~ m5Ãm-G@6 r44 *ܠX4N%}PKg`/ +ԼIb܌/0 vt^7-{jQWD@z:ƻޛAmp Ϫ=֥'>,*l+Wgʹ%ADڵzӧL@.p/- 24!Cva@@k = 5KCJJ=z]Uә44+;]QA& S+ uӒZg ?oNy ^,6lɤQ믿^"## u 곉o.VG@ T5ʚ=,{%5.9XΊMt  [nhP34G~GWdT ٳmj۷ Xn a+wy}5e@: VYCF1O B#S}Цl {/-u*pArj`&IB~a䮻ݻ   ]T@`.J°@n wGRontY_ώMӂ& T! )рRRR䩧 6ȷ~+999-eee&6 @Tt9嗿5 }9ܹsO?m۶9\CEqEi(|ٍ#   +s T_:kO%f%%1ݼU@@@^+5j5UUUi *A2$''ա+y]20k,\2ǎN=@Ps@@@:}@?,jGgL@3H(ɭ,9S M-&Sz 0ޟE9@ z< bP    rssu  W ۱}S.=0ڬ  ^, r!>|x!   gϞ,AhZـAq 31$s[;9@:W4dggw}=n9۹s<#(8seڴi2rf۳@@@U:)**҇ xYiȩ8sg[YT CJD6T" ]I MMMkuӣGyGm@O ?np}@@+<А/ .4s9r˘1c ӧzo!_~믿3gjz%@@@@Gldݺuh")..6ܹS/5Jj    4_|wѣGTjM^xA^~e"   >)`6ETbM{ݻw[n7lؠ͌9k,4hP\C-KӝyԌĉ^GQvD7dMR^^n-_ >Pf63Q *++ u}.&sAJm>_=z;Y|A;/谵kjOI.J;mۤB"##kA@@@|MPlQ7>\:묳D}-;A}qki7ٳCԇBoIf>~uz ~+s%O (ȭ}&X|6ڎ~GxG腻}.ing>p=FJJJQΞ= ֓|z@;t萨%,H    ԯ_?Qt~ŧ~*ԇϗwpZ{*@(`j2ˏ߹d_E6seL\8\Ƅ xk{pbo Q-7IJJ2pȑ`/     irw; fPƌ#%,,L?L-e2 @Wl/r6]OݽXfP*wsW6B@^34ld&qǏoG@@@eʔ)$Dk3-DGGˌ3>-VX!^z^vu&$$D[m3T6UKt|GJjkk0CCC2#pH>ٷFIjM Ddזg;OePM[lRq]Wk **5F(ZPK)00ak]O0D~DNN\s{@C||퓑#GZhlll^Q@@@@-[&Gu *`AͲ`T@JJo)?n8YdXgx>U_wDnݺuĩuΠ *٬U};F Rׅ7N;l>t{]+de.FMrYÝjK#~G4߫v3%`|/}{ x X%|{~ؾ.|[Gh={q@Tl߾};^+    ,~ٲeSWQw48u]#uGMZZРv'233Zv͢Bqe2jQd@#u>Q d8x¸,OkZ^[TH\hwv}# *p*M͵3>sT-l?3ypp[     &$C|C Й͋dg'~D̠dnLæ  @p JMkj§zJ~v?Z?_~M$8!0hEw }w]    )IMKB:2߲w7[N-#Ӗq#33F˔m9  .ȻiӦ[oOݷrJyW8\DEE|/ovp @@@@7t} uuug0mY6رc`I"gڲjwC¤eZPI%!!!>" _# 2{ly>F˵#OO  @ꀆAH/@@@@ӂv! ,gkZsrei38琉xlR"b~c%"7v>! A6`@@@ ҂2j H}gg}r7>,?&EF[h,;6X,3͐@@ ]yd    SҧO4B\s$40{I@@#5 + &=ю#dʔS.YD|"    ,4_e63L3R>1Os a7@@N UW]%_}Hvv_npE@@@@@k Tȫ['{VܦAOΔߌLĦ8#  ВGRRR~Zۛo7xҭ[>@@@@@ 455ɗɋ#euUm:sfLe6dl6Gc@@H@شiӤ^yillw}W/^,_~$''K=GDD30 3)     .xug;[I]*f??Z @@ x$ߖGOrss;vLxGfee98     U*k͋䓽l*sL_f'xٮ@@ x/˶mۺC@@@@@:wGBkʝx%a1gi j !  4c`\@@@@@@imeDz-1gǡ    б hPKF̛7C бbi<4S MfHYBr?oo=/?n<^3\@@@pG,Y">m"AAAo>}FFHeeKuuϚ3g\qcbizD4x"wYLc %M +gڵuZf{*ҐiQ   t4|7^zܹseذa*8Dkww˸qcrrrd;HmmV%_ކ        t^4L&ٺu.fcxg$))ISÇAիWҴ .@~ѣGe޽ꫯʽޫy^ .!AP|o:g Ѥwe5 _P?KH/P/fɣcc:ʾ}*׍u]/.&?'pPL\6BX&]l   np{@C~~Û1ci j#5km3SOmݦ>_ڲ{F 00ӫW+ _5g;*#k{^7y&ؔۘt4!g@@@@S;>syyaǘ1c eko߾֬q֝jYfiE5{g@@@@@@@:*++ TɆnjʶӧɡ[vy@@@@@@@nhX,k:JQQQҽ{w}}&z޽cǎ}Є}{     l9vHVn@@<& 5斒Plgih)AMJJR-SPPWy2    8+(?***=vI`_i`-E-(    6L-[]/kFOJFF^W__/?;Vf֢$''y2-0s] `S΂t{@@@./>ںuaqqqk ptqRXTooAF'c8O%    tR;wA _|QT}zZNKKd@@@@@ox}w fP}mB鹣/  H@Ô)S$%%E]a֬Y2o<ٹs^'M9YviA/̟?_o/4d@@@@@Kj,1[r$O%Zt@@5(s&y0Lj*>| 8Pn:}y Uyffn7d.2޽my@@@@@U2w۲$~oG].WgՃh  @ qĉrFjS 'O6ԩ`P3gim@@@@@<%N3w. z.  W x,A)\yꫯJffbРvOnɷJϨV@@_ Wyƍ  >#0s]k:p|s#807?/s߶rBY7JDp7j   `'򀆪*1Le%""B/}N\pN    .`2ʢC?ڳΓ?V@@_py@ý+]322w*ʶm u,deet @@@@p(h6VΗlq߶Aʽ#VG@@\µ؅    tSzOeoouLs1g   9@@@@@):S<Y>Mn|Qh  F4Hn歕ml@@@@@ *wS y\?pRg}D@@\+:{64@@@@@UžC?7.>4Jef@@Zpy@C˗c/    +,٬w2..NϓAVƁHQ^޼ȶZ,0j  My@3<鰾Vn=:`#{@@cҫW/1Lzw `/0gi5;mkezQM)#  @%'=,]T]rNN    xBaSe/Ow x&  @ ϗիWkHd̙]A!   ,`C-=W{զ&Tæ^äLJm 'y x@K?,,$pt͑;郞kQ5'k9ϧ:mf0+**$99Zd    C곢BrcW δ(PYY)Z{=g;1Oժ$P&VuumyP3{߮>xp;F[3DRR;>D[ 2jY}"       ew#.!n(         ]nhٳa 'NȮ]K        G>5B||\xᅲd}}}z     oHrrW V-j2>%&&JPP^&MXkGFFi;5555҃g<iAA455P2$(***}QQQ$R}A\\^&6 Gy }G|A4h'7Û}'@@@@@@@9Р矗7xCT0l ڵksϕTIKKt-50m'#       Е)࢑ϟ?_rss 0@vޭ eg|3>'@@@@@@@@ x$aժUm6ύ+#       W {u        >3h@@@@@@@[#KNnz       H@C`G.Qh.        VD@@@@@@@7 0U     ʪU ;vddd(t>&|  @Z/^O'CG@@@8,G}}c@`]>% zC@@@YAEGJII444z2@IDAThGPClllho0w-+W::uéC@@@@Ȯ(V yN6f.  S *o>H; F@@@@j.}K fP,{E 83B@@S h͕{G?~7@@@@@^9xp&<'4O掺B )   {+jɈyuH0À<1$    ^$E"gG=x*?4   yаd9|i }322$ @*++\}̜9s+k[@@@@Aom/iqbRdٓZlN@@Gè{%sΕaÆO'h[ƍ;]NN,_\ydee_o8/@@@@-]sk>jq![%40vD@@ } $[nGfcxgdz0کִzjkVۦi *gϞZ޽{W_5    #pZXԙt7Kr836@@D RSSƌ#FXf=oIMMzJBCC>LlG@@@@ꏤ>42@kk2    M D=Gi۰@@W ~~~2l0]DPUUm3zQ}!O?eی:zUrrʙ%Kh3X(]tq?QnF=zu]tZPG@@@@$h6ޗʆf-Br,QG@@@s =A1M0A*--;S:kfРA7/{0CAZZ]v[RR" .ǧܸ{dƌ2x`Q3a3FfϞ-f߸}W-v     ^(ŲH={$>Ըm@@N# SLCͮt7oܹSI&#Ghm֮]+uuuZ / /4f>9sH~mf񚯵R6md-ٻ) D:" V`#(%+1I4%1hX6) (*XQQRMfg==}m/     jԨa>hsQG{>1x{ɧ桏^KEC8tki  I@FPmnuo۶mB5kV@N 淿۷9S̨Q dԩVh= Hx7g}~Gut%1eʔ    @lVmZg810< h#  @ $A>={4]vY f͚i;0L=;v|hQ ӼyMFt!]ܹ?jXhO    qnۍknf*U͍=0;WpF   @,AD'x{ 4ݵ^kTBTfMs5טz% Ʃ 7N4c n@@@@b+捯&ݾ?tl׮tF"  @&*|oԨQy q… R '됭nMdɒd3@@@@X|+snˀV{Wi1@@b#+ѺukdSN1۰a={]k;l6+2RJnݺo'g@@@@ zvԑfp@B@@iQرTE13kӦM~ OvM@Zʯc@@@@x Οf rêTcs D@@z ׯ7k|&wdW|˖-&<,0Az|' +s@718o8J#yS5(@Λ=kv)/:y@ yl~Ƽٻ=7 @@ C  ^zWk1ctbT* C{hZjFK hQ [F@CFG'9AB SΛLŘ^7)ppF4j̃s}͍ӟ6n6ݚo~v   @ d=`fڴiޟC8͠ALf bw+PH57oޜjRoVnRo?37/ޝgK-t=7{ pޔέwOv(0{jl͵New@@@+b 裏SO=ըq@*rʁT=DBB@@@@ תonsml+  d(̙Fj2jmhݺu@ D8!l[VZ?=M4!B˗/7۶LCM2 PjҲeˌ֠A|_MlҥK͎;7ldLG,Y$52`-PReB@@@@p޼ہXck׮5Fڴi6qFv>2 hO_z$k+(m+/fS0C(PSfZsZySGlJ?m;vrat!   Yݻ\Ҍ;ּ+>9sqO>c1m۶gfR9M~`xyg<       !3z'x Ǐ7W7n4/תU+/ARԮ]۟ Ԭlˈf͚5ԠSЁ       3*b{w_s饗g}x㍦G ]poz3cƌ@բq^V}M\jߝN;}әi@@@@@@@pr!jO6afؠ&)͛Wbr5kڴ8p0`!ޘƍ+Vxfܾ}iԱ) cڵu-n:@@@@@@@@\r:uÇ#FN;-Pŋߛ+4SN5۶ms')f͚yf_:>h5AB@@@Q@GTåM6mq@@@*LBkhHWX oy3f3ee˖,zT0jl4hWC`i߾;vs5͛7u̙3'0=    Q[o^oA@@(X4ݬ\ҥn:3qDI>NGy;C={UjǞ{tf'&Mdzmvy焻~x֭MÆ N@@@@@@@r)&'Rt͚5ͱkn㏛ 3g̘azs 'o=բ baǚ5kc=tj8ꨣ@@@@@@@@ n hpԜСCͨQ̰aI'd4hNu+c*1+ࡠÇ͛7vW53l޼y-[6mt        7X59 RJ]v%\bfϞm^u3zhqT*U!Cx5X}WW\qiժi֬/̗_~ionf;<@@@@@@@(54va̙c&OlLRt C MӦM ىI&?<Pvms:uӁ       @1|f„ ^ Ê+YT~}s{q̚5ˬ[6TZq_jJg       q}@… رc͸q̲e =z&PG(`OvoժU^3˗/7j^AqƆ@B=       P ho@O?4|˖-͠AL~LݺuN[ #Ġ?       ,כI&yA 3g4jb"Q^9#ڶmh2#       @ 4a֭fW_5SN5[lIxzA }1 j !       @a $?4ƍ3'N4k֬I*2h"鴌D@@@@@@@/kNB K,IN;Ν;Anݺ*U*l3n#@@@@@@@@b5R`Ŋf^m KGM6jb0`_~@@@@@@@ S  6l0'Ojc1cپ}{RU?ܫ6*UJ:=#@@@@@@@@p%tjcw}kjժU!    @ M6E[l1 ~S.:/u.ؤsZj"ͺu=\ٺuOGq]رY]d6xt&uw"1߸q=PnRq Y&_}"?4l0YhHV#c9ΡpnRf鎣G@M,[s~ \ v pCzZ!0mڴxlHm"Hd*yK47Qc΁pޔF-zvڙuFd($PzuӬY3ʕ+i-,@@@-~f^M6-+!JRLh@@@(B5k+ Ex   @Yhڵ:tԩQ;2P5=zLR;^"   @veC!R1#   ;l77CS6(ot:А G@@"h߾SN5   "@@C)@@@@@@@"ة]E@@@@@@@< !O       @1 PLG}E@@@@@@@ Ohȓf"       PL4f_@@@@@@@@        tW@@@@@@@D<9Pl&       $@@C1m@@@@@@@< !O       @1 PLG}E@@@@@@@ Ohȓf"       PL4f_@@@@@@@@        tW@@@@@@@DJl'    @ƍ͔)SW_}ezjSfMn<r!f]w7'@矛szף˗+WڵkF -[m -ۉ@^ ZN*۽I.BSnD3J!k;̂ o f{/hѢܹ\r)xf]@ S=?l'x~:@(~(ۗ;DE4~w{ҤIf̘1fÆ ?uUZ՜tIk׮1vdgoX %ߊ+ѣ̙3S"O67N9- @j8] m[o5 |k5׷|"@t-Xxy'g}tؠ|6m$GVT; @rpRIuyڵa;9c@ P> .4Сy{gz<^0J9%K۶m3f26m2p@IK5..Qg&\ .?]c:-Q?L6ԨQ+LL r-H+w}70Y^kA` = P*\ fϞmNTiuN:f=L5yQɉ<4   P T)7|w=D&L`wJ*7{キWJ>~wޱ^{ͫ{ve;ʺ̏@> &%yuV^zwަI&^UV%Kx!U7`+e 20|::X .ׂT@k*EB˵`f˻/h֬܌ L<9P{èQ͛P/<>xl:   @b_~`
(&|T?lVM :Lj {ר.]xׯ_g+!!@fq͛7#F#g<d&kj{ 3 쐚8K/dƎS`W]uU`ZzP@@@@P+etp}v՜~ {eve|O? TM ?O N~^|1cO/kA-Vm,~m˵@akbҮp0ŝvs1瘥K4=C@@@ܦdT1*{Lw#.Qg>Y N?U+O>("YTW;͢E^@ 8] m|߻T\ٴi&C r-PQn݄ .*Msq{A D    H`޼yFUԡCۙs?ܔ50.@&վIM41n7e&NAt-HdwyM_4M6|"@r-P5k==sC9( !AYزeٴiSaÆ@6^aR~}WjU{}뚧kYn s.5l񛘍2@/;v;jrpSYwvD7"SwevٰaÔ3cZjԨa{2=I @\Z׈G}Ԭ_ޛu#H49@q̜9Ծ}{?Y.BsgRPJ>(ʕ+ٳͲeUVyӅvF7,m۶5zQRvvl:S!en[֡)zmݼ \=n;>04uT+VxI5kڵkgz\G@QӦM3uV/A1jժUc7nlꫯɓɺufZlQ~z4i5k\QXz{0rH?c_tMItN}믿V^0Qu͚5l^/^l^u}c]O>^E.5_*Mx_7ng}5FKh}^vwO%t{M8c!+M7?z8;餓T&xݛ6buϪSU gR Zwny ,*<=R z@D*Y˫f ӪGTҋo=ЖNtv.pzkbhǹzi|w{`}}fpW^=W?붥h7Iwu_QUmVwu:IӾ{ P1tOѣGfFۭA#Ֆ)n f:׿̝;7+ꚧ:n0Q@Wb 0(rxi-P;%|I/O繛umnˀt;(P,Ǎq>SɖLrQ|,MN7hSMv6e1@Vgydqَd8 U)M >Ѝ? Z?߳dx@ qZlR6pj=?+qƭagP :58 } @@U.Z){JשSǫRUl+ A'6RfcOԡ -G:t0* `/*=vTMwVU{+նؤ}A|VJV{6)2裏6͛7~2_)n%}>\|~fܪuӹQ`; 6]*A͎FGQO=TZ@T ]kT͕S*5o?hƮyO<]wv+#]Mܟ6AO:pz;-٬ak)9 ]ǎ:(Y (s?4cƌ߲gvU|Fq71 &Tp4(Qc 0PU^z7j"5&U Jnv< =)rWcOH} G Zlm1:VzڣH @ XRJ*&I P>q ʯsu;|ޗ׏w.M@A'(wg7v0uEz{ ]JСP6dU^0_"жQza&Uܧ2U;̠Lm@tڷoJWMtYtmIDF)EU)&YR6)ӡM6rY6Ժg Y Qz`r9U[)0J3guVEW5ϾQU|Nmy)qhJ5~l354Z5c }8lҤ߯7PAPvB&v; 1OoӘ|;n9C^71,R @k۶H57**P@e;2 ^MROJzi`vTnRoiFx _XF]A;[ ڎd8 U .ׁ~%jg8(-(@\zFqSӪzBB˵@n{aÆMvu}-z'f~U. |䄃A'_*0^2o?Wt2;`w-3Z:E~dvT*&h,UR65k+E29;h)?(smf C21C|?)Zg#Fq 7ŗ,V@ Zގ^xfPgazs-x]v_0p|: P:e>^{cҴi ݒԁNJ)S2YR5nRi8N) th7 0ywUٖ8\jq_Щuke.DsV>jV@Cd&ɍ2d$I(4*sO oY$^M(C l2w5q* %׿6_ܩ)zM,3[ aSTW{Ϝ(mnBAZc:D-ڽsQ&Inr᩺@~6݀L+% ->!-8^ |IyM~+[G X .ׂpm>\8kJ^+Z"oсBefEԟ^_$ZA!&AR6cR%&)n܄.q\ΎmXz]U zaƌfp PP09NyfG jCUےϪCD\բڤ ELc?@]>̻֭N.PǍ^:t&nƋ&I'.*մ!Zk)?ݦ4erǘ !b~ieo:&jBɽ^E/ߢRA`2*{=OfڴiU*@. -ԮuESn´"5f,X>5]v4DB( K{#- //]|@TvZ(D|)g5z0>56HK .}G7éBCjZ#kjY'M'vնlk`^lWKWH 32 Ep򊚊lK%y9}WTWe:omH TfV:k4A tcQPVT@CE\T bfjl¬YQ3)~A:uJXC THMML6͟P0?~D^IARB;n&&?ޅ0V-ZгgO>c[H+)A 6`ONn@j 8'3|w{O{Ҿ$vdL@OAKtGi=R_{ dE .SQMW_O;ROnӞz^ O +z>Lv-> PN&^ wL٣ Pwmۤk VKX]x㍤ӇG&8!,롿5vDUGTq/ p˲^M.~YJ>1 $HɦMg|yR#l@Jy I ]?w\7Nj}>}<t]/vlͣ&cX@!7~#pRЁ}0WԶm݀4e܀;\j&|"PzvRQ3v&ɝ,qَLi(<} >}'lN6 #k,=1cF;8iҤ<1 PdqkVLRo  ?ZЅ@FQ뮻(vfER*CYf^1lܸ_ܸq|@\ -_ T2(laZnӭ(VԨ仪K'/^SjfD?MᶽV2F/mpq\[M|5H nP֟ڽ'߷zW-@!.>4(i…F~ .] ׋~7AL2_eE*٤+WL{Tӆ8 o׼H+QKNpYj&7K nPժZfΜi̙Ϯ!yC@O[obC#Wl hM sYյC纽_}l&i6rDPܤ )=SSzVZ +.Q`fT ?=q`/<.̐F gq&wpt T2}?K9;Xq Z :mޭ*)ھcPi'˴;_~PG*Wl̟?_Jw2 : &ap=%7ZOMz)]z?: o:[ջtW'<ɠ ™vDj:sV炛U >DM5/J)_2 q; :{REe.GZy=[[NgbB9n&&>ƅ6F4C33J hPmB6RT#bp=n47э@oތ;a]S hp)5sY>@ܾ6m̈F.Ȅ.Į"Pq2I*1~xK.$f:@Zà ΤI5n2$G`Sl`/}  b^VBh^UI*N7s?OWDR>վZRGf6k,\6yDGtU:æӧßUn~mj-ZȄF}>ny'#׼(lnFtmUf{K|jڇ~|^^ĄSn$˝ XglL4{mKKoٲ[jEkӦ]$ PD vr,sj{Jto[onڄGHss OO܂ fK f(@ܮq4b(\ T[ K 5UұcDpгee[2RvY|Li۶m\;<"6Tpn **V݀N:WA9 kPĉDzA*&}moOUѫOA@IDAT-[敘U5Juk^Rμ^/iLFػvrÆ w5 Q$[ tԴ0JE U;qob] y9T̴iӌmRIy{W=uT Sn%fa@8{(%!nIHUc=/E%w+Di:*jRoS )fRg*~ /oyT˵|#@*8\ T+Nͪ>SI 6#P2=.49Q,G̪@&MSB~=zY㏇,ERbz77~U6PdI*jQ"KW>tC*lFnVۧON:ռ+uzc3fHzG}4={"Ix Gն+QjsQM6ںOTړO>`/mDIn qi|xŊƪYE%~T ot]P[Ū}pp%ؒn`f:MSaeO^z=C-_f:+Pjfn-[LZŋ?;w}r?tvJ /뀞MM6 8u=M8õ b,koT[?(f;餓5,kaohyh '`=)(@@CЃ>P2ls hPGyd P 4[ChJS@/㤗kJ?iN>dӭ[2ƌx@D@AnΪTtW5gJ+Rc)/4*Vj is'xs-\J+Z~ۤ&1nvm!R$J&F0]'l@[[:UdǻMXapP>製)魰䏀jv2dY+0 Rz_|w_mݵwjI%@> {p-.jVT& bõ؏@r-/=o轨S fwjJ1^z~zѽ{w˧#@@A' j[u#apזJVP%|eٗw3O*.@r!^usU)hA?jz69C6'SS*)V}tP3nT]+veR}&J=4jyмz?ey L.D\Lݣ[vV6 hH'~F%͸sTQA1]TkL2,{j&$P(ǍЁ-^+7,\-|1h\8AIʔL j~kذal}K#@=6Uח{M] ^#T\##P 陇 lH .m%\b7 szQGKE5a?i@)ަ^dm_pRz ׷oߌ_РT)={4twWj XdWS3z*7)'YRze=3^Q/v5J*XAHsk^2sAV6?xV֪$.O~u&PHǍIJ 0݀=w&QR- rI7AƩmp--\C`8W@ )JI*1uuoLtLS#3=,_ꏄյ ӽWA'@|r-v 0]pd6(GTL+~׮]Uëa`+[qJ\yQ* PUjj~I y>UܢE 3j>V NǍܞ 7z6l? $<@@@@ (Gm2U#QU60Vfe8g+M" ْ|9 RQ(3M$ժU˫!Lie*V+XFײl^ϊW|WSjGh߾}Z˩{ UH  𛘙S#    k zX? @V&L`n-K*w!+e!Ps4 PP35'O67oN հlm' "    bp@ [nډ~W͸qwk@G 4k_-[?l6m w{fȑ`5ХK@h~]    @> D>-H!p=KzA Mj7#pѝL>kvBWS\sШQ#SNaj*`: 2偄 \>E@@@@ hȇ6"i ԫW̟?߬['t]v X51tPs-x ZjxגnHJL JIH@G~ @@@@| !_ۍDn%*#|SN%1 77W^y8q:unHV~t:F"(ot!    vun@e̙3W_}eon7nluf4h6>ȬX¬\Ҭ^k2DMOtqv8~9ZltV@@@@hva(       P`U#       4D0@@@@@@@r)@@C.Y7       D @@@@@@@@ȥ g        )@@C$ @@@@@@@@ 4Ru#       @ , D@@@@@@@\ АK}֍       4D0@@@@@@@r)@@C.Y7       D @@@@@@@@ȥ g        )@@C$ @@@@@@@@ 4Ru#       @ , D@@@@@@@\ АK}֍       U"2@@@@@@,Z̞=[{m/iƍfҤI֭[t%_6Db)@@C,      owy뭷n߾K~:@ ֭[W_m>3SJ#iСf۶m.~.;Wnƌcf̘mưaLvrIk#    E`ҥO?/^Mc;0(Aif=(L۷o/1M.\|ŦRJ&tMf͹֍ y}x@@@@@@0.\hFLڵ͙g;&2 mx衇r?h@ 4(       @ f&':,SVQ#GO>$o Gr)P%+gݹ8syְ)dOɩdoay%O2MG&z&e[@kÒv@@(lz̙3 ;.wxw7'pQ0ömۼ`TB\^X6*\*"     XUV!CUqijժy駟>_wFr&@@CY1      >k6oAAnf ˓O>@  )@@@@@@<3ѣGA`w#fɒ%fҤI~? h'S      {U}{oڴR%*bd_ڵk͛Mswa/_n֬Yc;}vSfMoYM41+WNg1Iٺue~م F%#+;ն+w޶ԟ:N/6+V0[l1kԨQev<ԫWϬ\[ȑ#M>}J8CN bа     $PQoa>W^t{g s5wq?DArKԗ_~iݺpG6AV@%\⯦{g?Y~?'N4Vi25~}q;ǛS߬^w˺]v_~Ftgڴi7}(λ{>ڜ|^뮻I~ӟ^z:l]) D0ؤ&:t`{3Tã>j^u/]@Je WDyp5{ATg @ А@@@@@(F'x<fƍ w_TŽ:vhlРA镡hѢ@kt9}@e+&UVg`֬YӴllڴ(bpu(C}„ 8L< 6+_bdhO1tMYfJ& !Q{5/ڵkn ÈNdt|W$jn5Ko76lv(hwƎk*SNwrVЌ hJTK ͂@,gw@@@@@Gp 7xɂ??&M䣎:*0۫O5>$ھÇfpv3h9~5fT̙3J7x<#jժv9p@2eZF XޫfRyCx}~i_nٶmQ3jM[ou^7k6j@5,32ItGTR- ^ziF MZ ׶m[;{)GͧLREzg]:?mYfP6Vc9kBDV5@6>D~i;oy}ى={ѣG{yKuV^d @P0A@@@@(tŋ{ջyG_^=ӫqAZ b'?k//(b޼y00fj0g_J+ݦ<4oסN>dӷo_sZ@$; j{1]L-Zxrr)^_|?x4hPd- rWf̘@[6+1]x25Vږ0 gOֿ{' *xEM;v0_-O` (c @9 P,@@@@@l;6:4l00,YI'=u@UQ36m߾L0F~N8kիQ?+jk׮NvQ 7x"):ߗ64qy2K 8; Iܙ+[i UMiηvJZ9&wxUf5kXj !$H}uO>?c@@@@@@ZڶmOգڵk)#W5+Dps<&V+r:{I;̜r)M6I d_)s~5m6;>hի5h ПIOӞI&i}e'a, %PA@@@@@@¥k֬i.\ުeFFz^˗/?o<-Z(>UG8REpxw\Ye}RjBދlb]Gؠ~i׸`Z>ۛ3o޼ۛq+ٳp(P@}]Zre`p zZDMKqEE5QΓ[ͤd; 2,Yk^,>ٸp0ŪUBSЋ  !,B?     1P&zyp:lĈ#Aƍ3w^`p@Gvb >̙cFi&Mdvؑj+8M 6t{VR.Sm[fիʕ+-x5]%jhH8@ Zh"@9 ,]̝;[6ˤ:rܬ _{?coovm` @"Չd7߁YTxǔ=B@ 3˾.!]i{YfvIŋj"QaUd&zkE$>wtu]IZj`Yׯӳy攓;m߾=0IT 'Pn!eLbf C6wy3կLǎ~: k裏&!FcNw;.&Wj7|QovA G6F7n2TqP$aTscku2?\xf֭N3g}vu3|QIoԭ[רtLGaj׮p~;+O]guӧO6R 7/30}˻/_נl$[Fܮqɶq  P:Jzw}[3Wĸ3{-Р hΠ\CI6{d0ZjeZnm{oOsޛl&Ųe˒N5rQ.ay=g窫2 zl\XfM`@ %M@RE.\П4ѳEǯ .0h84ޞ={hS93Ͱaoa&LeLC w^P{?nR |V'RT2׮]M'4p-C=? wCӧOJ\vef $M6sc] /?Yi+jQtX!^25t8^2G@*UsUMS\)zenVqFo)'N4^zQƳoӮj?p[3WPbCR x'͋/EF9;ƅ{tln"АNpT‰Rq3  ɴW ? r@ /fým?M޽f?T3CiSJ&q /=tƊ_O?e5|N 2QeIwq_ `e\д_lz *k\y7G@@.q;)h­LDƆwyvƺjժ%ܤ\C J0Bܤf7TBΝS3hsc8A-Bs6]on5*[n7ٟjqWn@ Zh"@tͫKV+sRGY&!@~ <楗^ύV:/RʒFhnE5 .<ꫯ6GuT`*ej)rBa5# P%0tw3̙3KdG-/\ɓ^{ɚjS}y&2dQ$5Meɭ@h{|~t'?~Aq5=?k6Wwqi>ЍD D C@ کS'$k(!M=fmC]UmS5cǎҥKx2@rkuo5jtԩQOS5%@zI ׯW7Wy'mb߁GOs+M6~ww5g\ہ# Plp6mO=9M a:~m/(۝F﹒ҴmU-fU@_5j mބڇ 7RJF54&MTbҭ[v駛pҟx^3"*TnwzZrt& R>i&tzt^ZbL 0@O8@t9/JFz654}֭[}V!^`=W:־#Fu܇)1N:aL7]M)@$Q?Iuo)SW?O`Ν/>̯X@p 2@ ڜoi]^3(U7Lgy&Mt#StoSg>gϞF%~T"%1 P:BVk/^l.2:HAjSZlgF HPqCz羔yg#s;j]\T-~;5D/t|qa@H5j.(J5lٟ'0>ɒv9Σ>O᪵.}Hgt\r #UR+ߴiSIxNZǹ1T17>0s8{w=~azf͚إnݺAɉh"PjGM7Őx 7{wgClRѲe˲X9zPw6G@P FiFڵkd[N=f{_^ei[ݿd5N+Uחyfjx48iJ3K6}y$[g_o*?#Uz . A3f^ 7r>`9sxj~? ƿ_jժUƖ׵ݑ޿\T;0jElk/w7 ;qu @2xwM&A7nܸD z.y|OOwy{Qf6[Ϲ& l&5PvLJׯoԔKܚ4\MڇtOgrf5jwgxp} K/5i֬YIJNǽ^nv팎S|棏>'N#jC5fo.މXvX@b 2 ݈kE~F5_Z e?#^S팢wߤh6lͫLI\PJw`+t#jS}Ӥ T Mv~k62%,X-Y]wi>ecTu… PFl|^v)oJzt̘1X]lԨU 6yjz9z^ {edz-I.BI(H6ժb3ZG@zbןUB=UQ/l^~eYv{スv'ySuY˗//6uy䑑ĺ륑^,n3z ԢE sꩧ ,4{l,xֶpKTZ՜s9SN)u[_,SpPJw )iGEرcJԨT u]m %JRLIטT~(x駟%{3!&Mx[XkY:)[κdz wMVjXMu,eCw_mD@<`ҥ^tzVtYV+=c(}ou&I6\sMT# hpǥ܄;O݆Dڶ:t-[݉/݀mw}v8zwyM7yRA 6=ɓ?;<ӼwzaS8zkUK޹)k&go4.h˗v"@l|_@ҷ~ݘTnԮJ#<^\U^!A/%L%4^'{_[]?04`2FX^u量nn(/O5̖)У/B׉d)w=y]M{P MQD@^ QTbرXZ" R /Ԝs&{&f2s1F*@S-(8zF:NsA/"@:B 6irxJVݻy'61's l)qMcUXW9d γ>IOpB4=#fFzavrn( Xc\Qq+@@UBv dbLK뀾aeN"r3&uZN}Ն1 h3C2{.*3 )) oNY$pN8\ZX?}/q5G:E^p7=zJɅK(΋s@NroaW4ZfKvjvjCbja\%1vZLKvJ!0aB\4iI BW,]2-?Q'KR~jr+ OkmGZ+\;% ji"B?q 4/h5JϞ%\bV%jWi:iذ-XZ,q%W}_NPDZ\B>2He㤩a̘1IMz,q-uѮKCdSヴWA$E6lj"&1PJ#?퀐W1H'[ZUr }aOdS%0g[*$NīgϞHN,28&8P|<7MrQ.c'Z͕⨣aAy:=@>DcS:Jpqxwf͚m)s5I%%f.}<ֻ>j {+'y睡oY9v y.sigJ]Kϝ1[;$ a+5 iLЯNd\$yEN/.u=GϴF}ϐ8/^lռ@?߹[Cv`~霾w&o'Ҵo1rpM 龉J!SHA6#etҦ8}׼@  & E6%t>l?jqO?-^HA0`6Ynis>:N/RIw-¤B488Nvu2ApÇ'*#K$2OOn5Ң:\냺xd[ݽXS^9=-i׫vw:N4ZP8liҤ}^KT]o%hXSykqKAHiBqGO4 ׎Nna Jc{D[hCZt hzM,bloF ܚR$q=ԩxG I'2[}&$sԦM;rђ}(wyX- qHjT8BK'|?QW_m Krp[ێ1hpu=FBơ#.gB]L w:, w^*n+ \G~]snbxk• @@r֡VZF\'&o`!v;] »k׮gC雨(n͍F݈@ Pi-N} B@;ݶ4˓[ώ^,ӂvb9N @^8ipISr.d6ȴPޅ 4Nەz^کv( 펗 v-X!٭- CӢ^>B*n jO-> Gu-:*ݺu 8y$nad\ %vw 3$4;^ConX/9e9c4G= Һ8l PPy@NBS*39NZR1o½{Z$\fp;G Z9(iƳl\+k9i_!E "7k ;H259/V'p?iI6F+A;T&s11ȝ>ѹ>2'-K#G68p/>d:t-XwM7y4$zNtRs1եc\3 @ nv#Π_ΝkC蓮?ҹvJ2< PyטxE+߶mf,$Ƞ6 eS'iptNXA&!>/&\ܚlq^O2XU+ƹQKtDTw m L4m%(X.Bϩy&:ׇ:h@IDAT .6(N%kD $"^/{.$J#QFy4cO JI!8rc%x͏ۤ@ !a q-ZDwk9PN8N.\\G͘1#槏ԲYfyT_*ran-ԡ{x~EK/Ȏ??g}-=x`#5pĐN]xᅞ|HP^V?ˠ/7Dm4h(o 6\/9|5ns?FjϺq]W>4"$3(oϑwGո(o'XaٸBIWVw[)ni9//DFy †537c㘏 [ZpIAúB]\A<$>:f\kˤ @H@: jc_T}F[nŃCݛ<%v!Mw6} b4UԼPwYg0 Ƀ2!W/߭.O|iPjҥA;'k >Pׯ_D8n6̶9jlxWm[]{R~衇; dZ-@I_|rȐ! +V0)mw:sCArPK:N `>AGcJ*Fܿvaِ4aR񨟞YYpB>d%9a;C=q&3I2ս6OWL wkW^yţ‰/KQU4v,Wn @ȔŵyK.1@I;0z0~tRφ4 k˒?n営~uyma K-EμG~ҙ3,:Rf@ @C!(s"O?y꫗0YwsI:*%ЩS''L81v˯X''$ћnr)N5'q/Ƞt0}X_~82 x`Z tE 4w;m/?Ti =}}gywX|%ZqtB a:㌓F ~!',QhAB]M/ ~MAʓmBIW^X__@!]zr/0~"Žn*_LqA=2HB]L wiӦ^zɌ;6&뎣yzرDN;Ə((#?ŻAF7OXc\"@*o^}F 9Js~{a9,{mtQa;ŋO>9Ŏ+6|w* T~$K&Ro.GA vv 45;h!YH4iR v ranBy9RNa?>T/4/bb/ 8} )[~$ggobγ84or?\%HٙZvTŴ52пOA*A IK; d2W/Lm?ǟtaNUGG!T0N{-w;G;"'1;Ume^o~кHpnN &rX&m zNwUV%(R+W(; @#8tkףiINNpƍӔGBe |%>wRAL׿arS;>}LS^=[՟Rڥvj߈_(V:#Р?8=KZl= -')A2OS&t$1c$ICXӦM&K?Ș4q1Jd@JLA;.Θ" m9  H.vbҜK6*@vAKHqvZ~c*$<>X\PřM388͙36G!5n8h [5:}wqG^)- %_o"Yb?+?d//KHX&-8SUPle𓄣&ȳN#EغE [?wB{\Z$,'2ܴikqFNe\L?PT0˦ K-vI͸T9Rm߭^ZU|i ;%+r#ϱdwGsƂT-(T[_|a-[*'LE!oVDB ^ҿ`}KAS1Kϱ:ranFnrw.C"㸑#Gz}8qǼ?,׹$*\{=.պG\Rw@ @@i@4ډR kaѤ2^СCli phqĈm5C f ;@… =ϟ.M6h1q_> w 6|Ͷ lWZ5fLh½@|iIfqk鐽8\eX-}Ӹ3|p2q̘1f޼yIÝtI㊄k?8A[OpPyT&'/dGO91y:a(իM߾}=Ag:[緃6ϓ,%K[o5.XZ[9,_f "s,nq-;Nc̶{W8sLsgo&d 60_|' 7`Yu"lW\aKرc:3SO=1C/M,z:묄 qI)'BP>Ḩq3:V;lu<餓LFbK@g\^rvw"l#'; @9&cѣ4_Iw5_=:&bJ$1Hxի3UrU @ !DM!> j0;5-&.X^w #F Ksw5ww3Qĉ=R5M Bv^&1Mf%ԜkU%ݹZ6\&=JHwdBqAo-Dّ=W3fpZj  򑐙[C=d/ jr]Z>CʣWK%ѢE '}/(9瞳'J|eÉHXꫯ6l ڶnk$#mDZxv%A ?Vy3w\# :S/x㍍T5:.[MUN><2n 9+ @ @hg)}@xb%rKׇmz'd.C>MmqcpGE_7 0Ǐ󫯾2%rR38#QpR?7#G`%id*@>-`oԃ{"8'vjzxU]ͳmkqo-կm`yي+LΝcY;v;&~V/u2A݅Z`hӦMRt%&܎Æ UK(|S%8&I_ 9|vo,ai6\8 A@Z˶s2%^ͬ?qDwyHX*?CK:,@nyzn2_s!=Ӻ$?0Vui@8ƠRi) @ @ KnHaxQGk9vSN9l PPw3!hf͚?6g/5k֤1j(ԍCiIJ($ @ @(8 B2 tͬzvev~L j-" :uJ /@'XƉDT*om_M7ݔRa̘1o#<2v]*'AR @  c͝ Pj+s9 ֮]kᮼTIKMe]f6xcw0 F`=7c=4o<>0;w6{yWG}d'0=z0_IгgOOz?GƠ @ @'@CsGT,SO=մjʮN,XbY8:u(8|NG@E!X]X(,Rۆnhkj֬+Us=ggs7Gy̙3'ZjC.]b~vTj-Fy!@ @@~ А_T^\{f׷w><}׮]\~ ZC"X]@ay4h`k:餓L5]Bwy9묳J1jQn@ @ '[r 6lczmI^bYxzJtf2묳iݺN6۬1Pg@  (( RKM^LmNzoZdmUu5[nw}MÆ K3ypp@ @*@*U4 |К{=^ P&:uP$j,~2 5 &0v7k @ @J&'J(& @ @ @ @ PIM]!@ @ @ @%Bi( @ @ @ @$4TRkSW@ @ @ @@@DbB @ @ @*  @ @ @ P"h( @ @ @ J"@C%6u @ @ @ jU+RL@ @ @ @**& @ @ @ @ PJEY!@ @ @ @B ih @ @ @ @(%4RkQV@ @ @ @@@BjB @ @ @J Z @ @ @ P!h @ @ @ R"@C)e @ @ @ T*& @ @ @ @ PJEY!@ @ @ @B ih @ @ @ @(%4RkQV@ @ @ @@@BjB @ @ @J Z @ @ @ P!h @ @ @ R"@C)e @ @ @ T*& @ @ @ @ PJEY!@ @ @ @B ih @ @ @ @(%4RkQV@ @ @ @@@BjB @ @ @J Z @ @ @ P!֭zRM@1~|gfѢEfٲeN:aÆf뭷6u5ժU @ s`@ @!-͞=tSzÇ5jx38py'=IǏH]t̚5+VN:k5\cƌk]w$V^mnf裏>፮jsm% rJs!4Fmdjժej֬in;6mژuY'iJ (34w\ӥKڧzlJ3U@'[yy+;wH|͙3)EB>?Y=$8M @õs]f8qb\=cn8 .L|_ZɱBo>v?3gH#@_Gyٳg$qÑGi&M?mٲeg?Ӿ!馛3O2%''JE/}F;]p1cy;lt\lYtqEC;wN:$mFx @ O ,fMykvfǏ @*2%\3g믿vm%\ ^n 0C:vظuf d6x㸰\{~; ?h,X`k3m4>xc5ӧOh(\@ ȼ5FcΚ?RC @ hj˔x `N8{xM(~T \xᅱթS'vI~̝;דl` BA7Yfh21n_2Cu… #,XoQFiӦfw3]zW_}e/_n5kfEf6G}-ӦMVk׮5k׶*ʘ. L|)"o׮y'=E7o:ԚY[hYtmb-076{WƘ+W ]8?e2L[z9gTws1r!a==FE(\AB2"r5oU5\F 1oMݨYS ZsVq8Ǽ5h% @ X8&0em,U?svmW/<=暸czӒ5gym㋁k1bD 66A!uanufVX4X ˤ%azꩤqci[u-LQMj4[pZ^P& :?Ufi0Fbn:a}ljcR^k |衇!b,aq2y:ujڸ2{a}85/?(kաW^̟(/Cmvc̘1+RTǹ(b DS[:gUM>rn|csaΚYUD:1oͬ  p Fk |嗱:Be*!˓CڋmEX&"nfdPByc5="YBL4Xo7֎8㌔W]uL_XL׮];`Ri^~e#nk j2n;-6_|;9sy:\(?$vX;^RhTˤ3ˤm}*>h,4(3j(sGxu!7xc,~Ntܡj j85ktNEFKgҶ`.uEw vQ[;NB-~n1F'>[ԝ5PA͍ƊTNcAGo0)Ӷm[=ϖcwe{g]7`\i<-Z-Noi".Ƣ wQ?wX N{7.>zKPc=4)3n8#!^z胒F#\ADb@rBykJm%V_}\Zka4a\y>cqeR ٳg\Zk18F|:՝Yr-(kK_̙㉓rz뭫] +tW8|%dSԄVcA*'SM$M1`Kw&MϴotIq4]g07DoTYhmIӆ eDTǹBD  ^{A步0gU_[񙷊B=?[ sVq\z&:1oU @(Ix @C/[vm,ud)V!"?TB N]U-[+݉wL&`툎#ǡ'KbK@c 6+&mʉYZ+&wxcH) !pXv0zH# aH oT٩?ϫqhڵ GKJe.2PxIzim  !m:E ^V,s ?{Wx~5kTY]\/ݻwkLXrQqsε8mnDv c $ ƾsQh0 @FiΪRG}.8c2o͜]>R2gMM9kj>B<1oMjC k4(yh -Z'^kwfHe_s'O?O>fM6I']`޽E-ql3f`cil0iPcal-qa,3&#\A@BykpQQ~ N5[Nx2gMGrQ瘷9 @ h/_rXhIܲu'vɜ| ;?}f,PkӦM_"M74NsҥK*AѣGۻ^$[K[oq~Q&7StZ~Ȑ!46ɥJe eb|'iI$ wv+ݏ?hO@NL>Dϩ?qv5j(N7ЮjoFmd. 1\A!ۅ{AAyk0QQ~ F4X[gorF9+) @Ȍ q#UHR)n'٪""Iٚ:-{"$"qo}7nxovq2;_I:g.… +M7Ҹ7Ϧ[oYxf ˎgΊ>J9my睶ŋۦCZn~'n-L:u<~A.ڵk͟"D߽fw<˶) |]°sʴ>8>FiZ?tQ8@@0oM 2sV>Jsi.ykX+'ّ9HEicޚ]%5 @ <*1!9-XF4'xc~aN-Zd*ۛ4i&X\Ю毾*_SHzZREIHH!m"W &իNI̙cd/0f2|ܯ$2xX;[kőGsMwqv(YGgU s1r)aÆ'x£EdᨣHɯEFb^o_Ν tټ }\byG+"T?O;6tϵkz85l0lH/8~Ơ0 <`ޚnYUbϥP歹inYfwr\y@  A(''sOs{ଳβwNe*Р-?#[ 3[5k&*ZN~'[ĉ̙3m-Jrz"g͛iqO?m/";Q|^y>ql/糭G&e8'MϞ=͋/7|ӴoS6i[ qkh94^zo5wui׮;8鹄>lsiH(I@.[:uܥQB PX[U\beޚ{̑9+sְ+ְI|@DXbϚ{a srdoP'vɈ}믿ċbOap1j($T&2Ű;~mڴv(Ln֬Yd%y6 G_f'qV81&)}ރ8źk bϥK]֜r)fԩ&"{ڵc\ ơ޽{? 7[FomRi4hmGv6ʨ[ne\:8!-2uaMU.Y2Yr @[KK}.DpgʜݫYT9 \@!4+0nkf̙4Z/$nm!ܮ~ˊ:6mܹ 3F}@IDAT 2Nʕ+㘥Eyl2Sn]Æ 3ne˖9}>R=p{g…P+2D%72nֶ) GiO0aa70'N4Q`م4Ie#Qa 4$W\!A"vA*r92\,\^Ym01oM„A  A('/+n~_j?مe&M |>ydEjkݺbajFkԨOu1{`*/ESO=S_~پ֎ĨK.\3)7M4K|W 2#/i_<~A.$4%M }Yzu$?sϥX(7;̙3s$/ ?Τ|~/8~@@`݆.BcZh⹻sYUDJacޚy%% @ 1@@*`֢^X݉'ki/Jet:#G7a!O~}hN 5k֘#FxK=XT;m66d d/N W=~A.ysGVZZddСoiԨYْSN9c9>`n'M+?Θ1#{'\p; ƌ6zǹ(@@(c[ٸQ~˔xr9kMNo)9qy9B P42HJ@pPf-j}7μvNݮj6mDZ.Џ7hªگ6_ vgp֮]k|M77!ttA/^z%,W Hݰ÷~Jygo߾8?Gqǯ}F?.–[nW~wΏ;8#n#K`ر~~3jbŊi@iEyb?HǓp@@9`֍\ĘzUڷzUsV?֠=x  HYСꪫ2C/~rӦM3wqGonqki}{{mK\f0`P޽=~΅4BN83w\wܹƺ.]o>Hi.'rh|^{eƏ(8#\u;Q21JZT$lEyb?ʕx r%5z-Lh1oJVÜ5'ǘrF9歙WRA  ᙑ" z+z){q]Fa/^l/b̅9|O2M~iSze?{.O6SN5n9][{xmnɒ%˂js~oZtItN'sL|r3qD3h Dɍ7Sy<%Z?^FZgvasycqQB{ghҤI gdB;/瞸=ˮ_HDM+TgY\f.5kqp; NtըN?ywm6:i̚5NT\ǹ(t<  ;k(eBy+jozu*Q瘷﫤 @ C^9k!Z@-rSZYWZ0龇e7.mNy%;o֬Y }<}Ei>hO?ׯ'c k$ =魅JZss>4hPe IVZU?| K O\M:u{G&j⋞8֎y8p(;ϫBGC˴FqixI'~_uow߾_~Iz'|j׏K14'@,N;Uc2R>uY'tn馪mƓnɊf[ IǗT-5U@Iw?8<$' @L0onZ sVu(υ}N6t2oM>@1gbZ~s֨s[I@ ;قfcYsNosac=s1[]o'·H5qaСF:taӖkk:a,rժUqzs3뎠gv{d/>NYҜ(;3Cm-?q⋄NDyw%x>Jk@+mK -28~hJ.vԆD{\r%iD-3j(S^D 6mj{]wM3\TA"A*hv’bOR0g A|qΪzGycg l ]?4]t- 5Չ_|Ŷ*kƢh!کn=zt̟%}LT͛7϶[ `*38è>%7kmJB$ _*z-E:g&<>>&xbvgзw\uUs|f%X ~wm3fc쳏m@ZnOvV[;z,Z|`ƌc>pAk-`2ȇ@+\F&z-[^z6U7Ց,2_~ꪫ>J#.6q{Iyq. %T!@eNyk8sai1o5o55Y>=_nsV** @N=mwR:v\}Υ}?̥^j>S N3OoQFF/gExӷoߘQX&6b<eż{1-У 494i$N'.YX2̂ 쟴Y&_l_N( 6[@cel֦CFk.5ӧO7b1Ink NI([W \AI@1\К2oeIо.s򙳪Kacޚ$ & UYÆ ]vƲ-{GO' @ %Eї~1|o4K,1/6 0s#8};ꫯ̹kf+Fm  @ @ @ @GZ ]kךO<ѬZ*֭k}YSFXѣG_~̘1H dbذaf-p8B @ @ @ Pa 74W]uYw/ 0O>L6# ]" 8@ @ @ @@H/Q xFv:z긻Hۂgƍ{W^SN. @ @ @ @(MEhmۚ>L2̚5ԪU˴j6IѰaÄT 2ot+adh>CjժjtI19s޽{mަzuMAE`ҥfᄈц  5j @ @ @%Pt)~|x&+zT (z%J~yr F<泭 YRW>uHWn(eKGq0!!PyAw^{YhQ(K,;vYz۷p =a\ܹsK3u]vi׮+laLG?\xf̘1VZE$=m?D.L޸Lt;_5WYɓ':ȨN;;~ABeY7F"y1RƯ o͚5qehG @(b[8S&nҺX"5M:AY%|JyDAatD9BօKnj4G` B8,EР+20C͚5͎;%>s-0-vtV_9ck/82 /kժU ! ɑh @xQjޟR `@ x_.B!@AjpܺkN8ӹsg[=w /Ӿ}{裏?<ځѼy'!pM74fR}%.ѯ*.Έ#n{=#ab>}}XǏeWF ӯ_?sǚ7{fID 0&Ga( @ ü5~ޟR `@ x_.B!@"0a#Nx<`6mx=v6Yp7ڦ67tsɱ@ヤZ5bHwޱMhqSN59r+Ȝ[K\r%  9Jvmc=J> Kr[~Ĉ@ @ sEhxW=%׿JI,J\tiLSرcmm,9u[9S29r ( ~QAXr'1 \@ ԯ_ߜuYe]G*@7lO",1C @Ȝ@̓f?0ร:ec>!Aa HMN<70`YbǏ @ _Փ@p @@8["6 @ @  .аh"vX]ڷo;dv38}ժU3OLʼCiƻ||>Qi}/Ö!K֞} =Z߮Qb lsSN'n}'Ǩ=﹨yDR*;XנA`;/FZ 6dӫW/s9dӷou/y̙3?`իgvyg^{Ν;'B;>S_}O+;7{?~;wmE~{ӲeK}<3>0'N4ӧOJԩc$LԽ{wzzٶf&M2 y]p]vd'oy饗bMÆ cי,[@+}B/#ᝮ]=fq$6={>lOQ<صs1_7f͊c:crK>>ڜzvQ>F^_|߿ @k駟SN' l=Yo'lԎA~ϛ7h"U&LsOӥKӤI;;/6I:33ּ1]|_2ooO?Ԉ… onve?]ϙ3vm:صN ُt(Rp t[/v/\&Os=b<СCAjҦMsEf#$lb7'?Cfܸq?6};͚R>R|2a RjX}ڟ:_G%} y1O+c.ƂDҼCeyGl-&!M_Ҽys;޽{sD/W]|>ӅnL{7 <sUn'|nO>Ƒ}__}> ~̓O>ib5jd;ŋw3۟6G۟B{gGU6~flz/$4D Dk4"UHNʶlgfݝ{̝wٽSΜ9=sN9scU6p/~s7?}䓟|~S{P{Wy'E]df9|q}}`t ZG o<sL մ7P'7ô쉟7x=ψg}]{s^yh2dlٲ>{뭷Rvgw~/J< 2̏z4>V\+\'~sʳS7oN~n[{TlHw6Hӟw힝q+,gNm\sM4MIv?M(?v} C4.Ra<y2y ǟn(+kT4J TwU >@־k{u 0RTl<蕺+(n^@'ukb-r9z= K/3}cnnjTm{5dv\'T*cLuŋS;c:g6emYkiM*\|GN?p.Ա4=?1vttL)SAcرcs9TH4Ӽ$2/ًdL=،0#uj;+}q3}T@vSdvyggɓ':;;.=m8`ror YLh77nt3f3@V}LA$7E\(Ge…P>^Tk֚%mN0rz׿i\}X}]_yuհj^pnu4=MVs$vw k9} V pdtTαs{ŋkZ姵 iܾ\xV46l}Fkj+I QL}177~X^+@2 Pl[Ts='+=VKx.z}|赻:I[kfmB1^d[QQ\u #~RODq,Huyefhz*t׌^Su>!8t,Cq8&wm9][xe^k^}U93=IPg-S;ߊ=-jkv8S%s$~<9@ ]uÜ9-)h 9ôYȦT'EM .sj^ꬳJYQ-4zLy0_ZG>b! 6lHiv}ƽ~mB[d #- {?JW椁 Pq\-z.'^ls'pÇ[xAM[s#u]<ԴR_Ӆ CM\ Zh^ ciaӺ{ ^UDj~5M;m]G;i9>-5y)EuRޚ^KiEm7auTqi{r9kޣr]5QK.OͿa㈪s=o|jSO?:skՒL~)mD[ucV{~zL)_yz祯RwlӕE 7=˽曽KWƘ0o}(fw;7u;B>psgjLAߦ°o 7|=MGS/R=h9sMt9㉿[M[#剫iQ‰(NLSN|=7(?ҋ+v4S^;ۥaxuEy$mv`ZHGa]ɄbS?rћo̙)wZ4v;;.Hgܮ rO=c+S>)gmB,]JXGvL.oZ]Thp+cr:_'fۨZZZubySSNq3d rs=WXn_RfY@5oqsZbAϟz~e~kEvd4^ Z1Zog =H{WڨA·-qPàzmΰiaW<\GQ tLui5tA!NkLA:amKJi~<^.|ͷ4)n;úez>n{]M6):=tS:d")wOpThз !hv_,B|jT-S0M{hAso AO/HM=HYGG֍KRi~r<[ӎXLa+s=K?'cV_Mm:]l<5-ucu=/eϧ˂3M+0~_9$}<90Z|F}ijG'hfL8w#"8#!`dT^r֙}gӉS@4ك9}bZq55L[,_UM/Xhֶ'n;$ sy]LxobZi4 MM~?F.x5x#qnWNjT'G;[=j e4ӽx'Livl:~wqELMg<Ӏ.7bg 'm h x% @n B]ɋG'?GC`*z\}՞b)kl Oy~_r2I? Ins-C~y@L+VV>żt b] 8t,(tAf0I.ϰqs=3f}*g6/zGL2/;8t8uмd1-yI5,1/a:@vy[%֘g/Cߟbj=uD+1Ebӄh8=)=Ap{TL=yfgcSLlx_;찃h%;֦ݿ}5J7Lk bjNJi~<[mzꩲ{͸@3 C9$Cٳg{rs+UViYIN5_#/Z/y'Ea͚5[3߾HmqnWwcB=mmm,kY=QMK4hOp1]d׌_=?ìYo/*>g8iaG]+iG~@ 'ukz.H^8l"==/| b79EUڎhVEѢ,kl Oy~_r3I? )A1o:ŦSR3׀V_lu?Q'Hy;(㨾I)30gAv0I.ϰqs=G?*2S_AMiq=vX١NLk=X':^^hAmԴ"tZʹZt/ZA}B~O~]ӷ7M(yCчئMwØI&sѳ ##{Μ9̿ qёMwYWO?3MkAN2EN:$1}K= 9R_1Y,ie\#/'e4AF݊II>Jgz'uόz  __ _$3oM>=p h,]z|jCǪi~g~6_= 4KߖqzHѓ~wk/D  D@E֠*\мh|#D:n6O3f$Ind2H^d؜>'GOu~Qr.m滓M\ֱ I~s1,W7Ow:Ie֟{~ub8ci3{.\ǂ߿id/=L4_:^gO.Ӄ#׿u5h麚.ġj:I;e`@ZA:묳䨣뮻N-Z6MvaY-G  555LqI0X~KCakUm) ~ʹ`b.@i&O 'I9qFotv-8ĉC) 6x z e{<(_&௤&hzI~4P)s"tk q=4/oܹD:n6k$5e3zm AtXm.\JO0OǍŸփW_}?;4I,yjA6qu$Iv/p'v;//{9{UWɗe{rb?._Ǫ\kK =ԝ^͛)Z>hxN: 'uk6[빡Cffa<''rF W$}mC˥=/':$麣S,H!0I*l M~7=B6Ho=/Ӱ2 2={Aڝ|GG}{dzzRZ+Ao I3JW ֢Emeڵ:jSLJK@r?ЪU$4;L4=,-5 G}_pXO2N/ zRCL۩Ú5kܣ}pSOH8Yb'{!첋;]1ꫯOHEݏ; A+\/\~J9Uʥ˶!nE)sl7[sK?B^߸?I_}R}4':$ß}qiS\[ҹMX(v)1mB{Ad¶|rkV`pWZXp>L[YZoÄۭ&o V\iGśZ>׷;ê`C.( 6@fc}z;5p/ tm#5O;4yon'fz!VӋ*wz' &U6ͧycgq&k%/|2.oY"I.P *-S~m(;c$\]!.JR+Q@zj3)salK6tu82?vo[㸏$_I>uĹ-i'I=zL0ZhKAvaN;ɧ>)׿./hkxWD8dNRSq8yIggbq߃;wFq7nzF[ ?ɉ't3(wv3L*4$\L y72V8v$- Vx衇 h"v֫f373ŝgF #qoW!(Xam#3W+Ofe֬Yvi; hMu_ՍV|; @_A[JÞWlsv뮻-Yʡtz~v~A>uĹ&DXǂ]w.uz-yE QQ|VfIp$+2YyIbb: ?c 9Cw5=g>##Fpݿ݌'S ,ϕ>Փ}{m dL}COv_x_O~2r^[PЙ ?O. $HЃ;hM\B6υ(;_e6l/Z5N8u]g%Kd߳m$<#be]3*gEE~_Zw&s4`2=秾]sw`裏~wM@īH l#5m"Q^%ɷɢo!!qt\mkksf3lD}a^A?ܧ!xQKh_ۚa tq':ŢGg<@ggq{iY~w:IeAQ:kr AK.6A'Pqv}7?n']vLd ^sαjh͟ELn?Vsjԍo? ^zAஈp++{xCᵞK/{4V_J>؊{Fd1umvFA+4G{}[N=^sկ~n*e^ƵYCwxꩧܣi?t}țz3ΐs:kw@.fU)=?|Ek4AeV Z _cWkbW1yGp zN#psI9o^q[kwx7pn&L?D}a^rk̋\G$ߟX뎯}kz,{,/\.]Q!8tLrζAmǏ3iv&\M=l: qرcZNA_p<蠃ьBDmoo/1(#Z%\Ov:eܸq֧6G%j^M+|;q8@ϙ-xh<;h>otA[k^bhx4!6'ʥ 6_]]7 g;ͯƏ쪪z:ꏶv?{讘⎗yDu;hmvݧ^{/[w_:3 8{o'xB*qW2iڢ.&>MJHvEGe}'yc7Z{WڷgyY0V1='?ךz{q-o`i/~4JuR-Y ( B\'\RΟ蹤{֚ӟמQ_mXnܧ[w,9'<$:MPwE_oU\---rW_vmwƃDGNڵb}TA/h˅= {Vv{:}7?k.2_(`<0NȱA$V`}I7?sjhhHDSaڷ6RHDOva)kRMMM$qFHe4̙"C+yPg?2S ,H)},e.nOxjAOqq}Ӧ?tMŜI?ڵ)s!2f~/O3~EM?]8icb4Q~OM%2{2 rɧ!Wl$xq@'uk(t?= 7|s#ȶiB{?Oz>5kutǧ&M䙧LV}'k?]iPàf1_h\W9\+}4?)'>&#]^L::1[2/RxBвj?;޸tN=kܨ5lC6.ı4 vUz>B=[ہ~w=>SH=Xos=^Gۑ>70/XzR˵,rJ>ӹq3,im9@P9X7>Nc׆wuư!C:dPW)z !MGP7q=մiA9CRuuutr { i޳aUن͞^=\YY 6l_>4/&WS~BWh}^[qS QЋ4W+.~2NO>>SV`p_b'g6\]9~1cx׽aФ a _ze; @׭A~U49M3S7Gn!iz?W ћnI7ŵ4aP {Cކ>ܧs=_>rG\OB t{tݡK@׌zhMYGl\B,{TvA?wqslqDQ岽QUh1{~:^kQk#?Ξ&}13=þ0Yv k|5{ݦ0m>zOXۜo!n7e┻-k]68{$Y㽝_3 g;A]civr#|,퍪BI;d xmo>biskkY4fV@wasD ,[LC&1MXy&~łnyp+-1)Ȕ)S< \MmDYzj*ٸqxebnYid\8q?M켘)1ŜLH}}ndҎk|r1,t]"F 3Q:;;;EiBwȼ/b;@+=No|ɂiDvegYxi*tTLy~w:2xs24=|gJ+qgے)$5=I`5xl?ˆ+@p=I @ЊaZ'ۛZA+5AOdb@@@@@W,X@_ӟǼy䢋. AZpNTfp4@@@@@@|А # PMOWW뮓~[n#~       @wRa͢j١LFaZ8!5*TH@#뮻: , ȑ#K>lgRee| _p@@@@@@2!D˟ql2gҜ9sDts=W,YEBM@(uİŋM;vUIaiӦImm^Znyםx:p53@@@@@@ [h'3,  >\~{・D]]g?3Ce]&~     d+PG@V;OHm~2hР~@@@@@F  "Cu'D@xOnp%ȃ>(|ZJ֮]+G5kwq6ěY֎     %-0(eBIo!       E'@EWdd@@@@@@@BC1[       @ L.gy #       W;Z+R-[f쬳Β8 tMV:<1"4Y@@@@@@@BúudV766 r*3hb7nBCު$       @|%Ė-[<7o3       %P¢E       @Ez&?|pg3d]wu@@@@@@@@"rZ@@@@@@@@ WHȔիWK[[5{ʔ)2jԨLQ       P ЙMF@@@@@@@,r" ,"       @a* RWW'֭Fc0@@@@@@@A TJ^z%^#,Z(dHZD+ءL*++Q>3۟ !6{ch^{ch^{ch^;_{ogWJ= Xoԁ}9RWcʱ8͝kg87P #Zf̘aY$ze'z %~ѣQ>D@ٹ_L~' %j*OGu#%}CEE5wQb["؎_|!y&0#       0bаtRZ[ee4@@@@@@@@`` z󛛛eݺujwuW*38        #{xA@@@hmmT*6nv8#!.㖖)++{;Ł\vuuyr/BK@jgg'X\EhV:::(G7H q}!H6lgРA) &]]rR?-t-W-y*V+4/.we[@@@@ KZhf;e)f@@@(KUUUٰaѣGebrmS*$Lo[Ι7ydghii-[82d7g8jjjȑ#E %P]]yENK`ʕ O4)h"=A+*ɴV0a3@a n޴iso믿sC        8XZhP#OnU^ 3gδ-]T~x1   @!}MM/@1-1pK 7շ'  @+4|wq2ydgc=AyaV[m%?eذa{G֯_0   hllz7H   j%@ jW+76{HH  @ ^>x푹sڃa/g*>Y… Y|"   @OODsssb  45WfmZ;d]u='  @ BCSDrԩif̘ᙾ|rϸ{䨣m?,@@@LKjkk=u0 UUrm4@   -P vmsԨQ2zhg &N(g϶&oڴI&G@@@ _6󠤦FR@h5ޗ].@@Wܕ-SW:JC_4ɓ +VD@@@ tFeI@ 5]MRi@@x ^A[^pjg].'taÆ9R`@@@ DS%)@p 5Is[{RÚv?A@@(NWh4i3zWaV[mL3I  @@@0kZioϭ/0BZ @OOJ6Ԇ[qPt   'P  v͑32g'^GGθ{@ߌYr3iԩ0   +&555  @uCtvټ54I @@0Рu8[Mus9~zg=;V/˴.\(---v4>}3   466ʷ#|2  nӵh*l"Z  P\Th8Ceڴi}N."yǏ>_j祗^J/[ou┕Q`@@@ WPE+k@^MRCA(dI@V"ӧ^QQ!_WK/up{Nv}waO9y駝_]O[nHvG-Gv3   @V zJ@@!i75֘,& zH@@ |M_@+4lذs! md˖-!C8;M6yގ3f9!|Ohkkk=ǒ#Grhur}bb"} @aKű)]*M?D@\%   MܕrC4 %&t7a  @rbz:m4ijjJEtP9hMD9h5+Q"#  -Jy*-f@(dT$ojiG9E@@,.Ҝ2ҥKvmMȢE+m   0Z[[W?vQ FBC楩SF $y@@EDyylr˭*sεW^*47q@@@%l[eymE}9˗re@@@H---۶޹Ѯ& ?UYl#> E/АЊ턞[@@%PEyf{O@@@-T*sMN=8eY@bIIcBvۉbݫ7 @IThشih@@@씚8?n`&d\g9@N5٭ lii/:S2 @IThx=4a8#   !*:<ކ @E#Ym0N@@%PdŋwYpv3   Pڧucc$fC6.' 몛M@(Wh.6o>AF@@'uM~ioOS`3f̐9sG@@( 7>ȧ ;?ر'  uVHzNC@%K;O|ͬm.Y}SO=C@@("ٲeK"p雛ˤ33cq'0 %+P,Zeʸ%[l  PlThRVBk#+9A@@Q@n&{qd漲6sȼga@E1M؎m-$>@@b(qݡ\?pꪫdРAKB    _R+3ʞs'䍳vSN@Hv5ѕl:+N@@JX 𬬬S!"sL0E    twwK}}tvvHĮWZoqw&Si::A(2bnf5@@ FX*4?ιSma_n@@@ dPWW'===!MrF %w>" 39X@bhj(l7v.Ĵ\T&  @I R$1(@@@ZZZ<<0O(LYQ^|os\Ʌ'#' @(fbAGȪbf'  @IV   E) l" EWQ;ȑ{N /q>D~Gj/' %-%=UaQ غ(靈C@-K ZG@@  L{ >dUZv1a09lYrǶC`@h,&(n2| JD@@@:;;Nzz 8gH;I{gn.!eB&LPB@Gt5b(.G +o@@$bР7y&N7N;${キg_rR_z _e}Uz3mi8@@@@9#cG AD[E  hl( m22   BV^;ȻFo}KvygKeڴi[o%>yqljVj   ]@ߌ|5+6 L1VyGty$TzMzzz"ID@@ ͭ]!2TjKdB@W \qA,Y"g}vIq:WVVI'3   T՛;!+>ҋT0xkUwע=>2W|&h $  P=)i*œ{LPk  PHH+4|}M2:qD9e뭷qرceV|ey^M?d˗;K M   d7WVeg@@[{|!PeGUٽ)γ'ؓԮ%ꤳzY@P T sA9l  PteQXo^}{ߓkzvmw|ߔۮ G)~}Ve<{xȐ!V% 4A@@@o^, -YhпU} :::  %$J%ҶJ  0p"y#K/Q?UA[e'TUU_,_җz%}LOk:@@@$fs<溜7ZonnZS'u  @Wwut{ JrF  F 5;r%Hyy{r^s / mmm3@@HP[2R)ٲe{ %/P*MՔCW|" 'zzK.]JꪫD+[?^{mtO>k:@@@$t]}ޛl]]4FZ[[' @ujZn  Bu;NƎW͛7MH;   @kʿ iKuutuNea;@R#cI)HV d)zN***NpfL~a'}Wf̘k uu$rb@@(!yoMih yzM@@[G:ђ,V'J`@(yrڤ?Mn2aW׿z9餓W^!I@IDAToI|Æ $^+W;cHi&QFɓeҤI2{lq +V  I<*M=,mZ.&0@Jsk'  @";L>=C=䤣{o7Aۻ'ݰAg꫽(֭sor'ʔ)Si   #呗? `y/Vb"/ZF@JBCkGtlPI $M .'M@ ,:H*++ {ֳqFx,YD⊴mҥKG?<3f3 @@^Nq#eefyjOy  FT+4h" Im9F{X+/z_KKTT+UUTlْJ@Xp&qd2uT ?zBoJs=V̜93^@@H 9n-Hok6~U[_93@@-cZ0hm.YUUYdž! IBÄ <ew%zz'N/=}prː!C)fon)~ik^h`,   8{,`<}#vV-4 SC+3n ͭ`j@@ FP2Ǫ6GZ_?CXlXIJ[Z8餓<f`r 'ȼyɛ6m8   0p=]G/(V+pڂc JK֎.V(  BPfZCף]3cx=>=n8wX&72  #PQ^&ZSƏȸa/\uƁV3RSS#  K״RP6J@(~Pmaeƍ2yȤ_t///bР-4A[_^olBC5   0py߻kjdV6o5Tv9^v1-3h 8ppR@MThsCK7I iUIyA@JZ *uM7-\P?|g<쁿/R__${AСCbоi5ZC?~|3ۦbTUUY4]  1N/]kt:LC@:ǜOzh2  BG-rKڊ|P>O˜9sBߪIgfGs9aww3@SSV[m"G@@m "0PmB+\  @jS4h 袋<(83hooV}H59jA{:{l8#   @&2C& # @ RA+3 m TDB@"BSNP]~\pyP6gÆ o[,YIo0oPi+0k,(   @ZmM[f[K  @V@ t;1PD@nn&_w6wޑ38C.B9 ȭ*wqtttx=cL#O>TWW;:evm&2!;5-;/7ss T:[F(Yoxtk&e`ߎn?֜]ZAkkknN⾝< #*#]=2,x+ Q! @@@`DRAN=TyweѢEe}}\|Ų[ˉ'(￿7Ιn@ظqoj ow;?x^3RVIgkkZg ME$V(죡0JD?BaV^]ѷPmыP^XZx)%*V WTQQߒ3gF~ ( E.0ZgТji*#  @DVAKk_,]#b ꫭiSNNƌ##G*kk׊?Ԑ)L6M~3E)˖-nv!";CIn/   hKVj!  a ݦ"ebchh"}@@l"Р ovmi7hr}裏*LzR !狼? Z)D   ~Rm# @<OO ֖N*45" Bzj _җ+R֬Y7vSqwZŖ믿.7|2üy䬳Βrj[y_@@U(uI;VI{*dx '[@P!E͵~7.O9cV Zg}SVcO~sow1Srcqws*?;sU[O~S{r3 2_$|^xAqSǃ=C;0?CeK%SO=%w pgKeeedyfywǎ+;3@z 6x4i 6,}d%?"NZG xc¨QYOUXSL d@nhh:`Ĉ2~xgp6mVl„  pE3*m!CKzkDmlyS՛ }[oM<cZ?%ad#Y/1̚5+us ћ- i8iB hw65_2fZi{ksF]G^E>)skFr{)zA 轙+bD|,孷޲DCs}7'Nh͝;W9kZLCO&"O?ٸ=S,X%?4f:?u,Yqe;k¼ {طC'uޝUzO:B@51 ΟTfTa^e?uE?⋢ 9@tҡwwڷ~SPN/UkU;|9tWs Рۊmbh@ 1:C5=K46*>Xi@N +2JݮrZ~-#{iU.W]uUE]L`@@N Ǔ)@ȡP)H;#V+F@RАZeNjx^'===c򶷽ml    P 'lZ_zmai$)': sj?2"{-~_dnsf%PIwuprTdwcRXZimg q2ղqFTU9nj1Z8d*Yto~8);nF93xG@@ 222r g.0{lq*Mɢ455"I*- ťՇpJ ԶuJC`hxDsRRM6|s' )+.Ǐ577*fU\Sp(V#dNcrЩOHKK6@@@rtT fH}:r5h9 K_ ],h;Q2{>@_oZg&&3|ӟ&@@@BtT#:% @(@Р`b9?  ޗ^zI{9N馛fa@@r?@+ w@8j*.P8omQI@@J "GIMgggZC)Vl6=v!  @ :D(**SO@jiQ@@ 47wڕ6ՄI2/#v; ٢q<  `T v UB@#$K  @h"8`&y@@@ hbTp8\I  PN@RaT@@ 4LG5<   Pf>O^13c8Y@Jbd I @@ А[Oӥ}}@@@2b I$ӎ  @,P$V:sM" -@@CEw?G@@+0*z:  @FgH " @@ 4@@@lѨx<FeDcRmGB@n"WQѠZ'eXC@f.7R   att4da ]dN?nE 3`St Nua   0Sf*H~@@@ H$AGg ΡÉ@}#F٫l:i5#! PnPܚ4ñA   p [@@@ H :"@*V⅁任pZbqE6Y`IvV@(uH4&hԛ $@@ X&appP>,###cc1֭˽%"  @E òuwzdZtΪ VK)mtT:SΒGCK(hp:?v%T*it'= @&@8*lUg#  94J[n_lM6    0N`mxU{Gb F|e9YŕYѠmTǃ#tNQ31Fg.cyk|wLw(@(F"41A@Zh zQﳟܹ3J@@('_)|Nj{~R>~\|zkjhTt$:^r< D1}M?|hess#[;G޴'M,4LlV@@@>`ȇ  y8?,p&2h3cJ   JWWXuTu֍mc@@(Г5A_ȐL/H -+dsյQF"ASvڹ+ITdB@Ra^ ӕ5   <Ç*w0  [`݇FrT ft(G2gV][D` 蕍ʏ7K8nnxVW\q|hZq E$ @% 0BEh#@@ ~e޽i{ӛޔ    PL~'oh+m`V5ht5Ƌ @% 0B7Fh ! N 6[asNZCI   /B X,mzN:rdDz=}=O6=KyO3]@(UP$fLurRmGSN@@r'P9s~hh(m@@@j'<2L4Ąkb{v  {GLuUD Ò6e@RЩH Dcq Gc⬶O0G  L+P|}N}ɺu릭(   FS!~ ['H=DH `^O

@@(V%ǟ{-1"C62$kU $ds GZW풵m+ITdB@hȼWu4:W8@@`R4hMy%}CV   @!ZP֝⼹,Y`(ȯ^yYqsV䲎3CK׊V?D L 6;vfg-܁P4+N@@ *Mgg|3|+ +pKM OXsB@@H$"R_^P~'v託,u>2d/oh9r5riHUURȆ @y `xo򶙨uf1 @@sE hЪ^yDQ{J:::=񪯯Ϻen7CfF@@*X@zhmnaZy"qc|:?;y~wϒ[O_/^d 2" P)ΐ]OnjHL\{v9@@4s=rDe4pÉ~;Od6mڔmG@@ ЩFFF&^+NYnų%zg̕iL}\2ٻwvo};ieiӂF$# @ 0@]f4dF@@`@Q{9پ}  L@G%t丩UkūxX{\Mo\ϖvx<1#N@p|a5'71UpuMV.[V^.mM  ,E*ڮZ4T^2! (J@ӳ  V`tt41ij]rۖ$^X\FQq;jŪYN:B @@`Esw̼攀  d(KH(0Z C=یֱ)=C1 Ջէ] UUUfx@@dI@BTd.e!  E h6@@@r(Ke廻^3]s_&e@&i`b鷪 ;q  0 S@@JV@GcX9؉ww?!{{MWoiˎղvl6@& arCiwMw@@ a v!  @ D C0,ʗycFH L&[ȍK/1H&@`ʉ,J08V@@4@#   XO@z^b㏆eKյQ#SsW;em ؊ˤQ+hTGME&@L I<δ]iz @VR $Uoo8p`uСҒxs9rg3h  @8Nʠ7I8ӽ;G{P\veCK׊n?aMM@ȓ# VA4(Ϭ r# ,`A?~ ٳg˥^*)s$   @ hPȈ/34 C=یV1LgFYt\}RUUeQ@*ITRsV !!/ "P􀆁ַ%6lȊ\w.,  rXuJ isɒ&yN9}^C"A YCP yk+4"^4{2Ȉ `;yA T@Q^x?֬>OOr7 7`!  ޺Ox|Z:_nEmeYGc1^`|o5kg4K2,kd>ӈdD@ p,%V^q~#(  `^h H"Sjb 씎K5zw^9rSӝw)VիWnf@@JH fL!q_ /8:N1/Mȿ=3O9 оza5'h`U6YݺX>rim6U@@ ?h\=if̏  @կ&M /PnVYlYS;&?GX(a/~Q>il Sr!NAZ@RF#I-tMVg4P(IY'??ke8f|Kg%Rg͖\=h44]g`Zu%5!u9_*xX\P{kw0Lr/bay~G~rp G͵5-/\( 5"׋PvAO,R햖~ZCC]@ 0@n:CB48Y;@44l޼Yo>fmE򖷌mjaΜ9rmu]'gѣc=&ξ 7}fXdYfU/n^ H#߄&gd x$e$K?~?w?_HAS3^#fsד>p8wu]AQ+4E}/J8(i-e|q^s߷ulY?N.V@"?czb=48Y*ŪSg@@E }GO|"`Ԍ:-ſfl@@(7U60]0C27'wKC1"ÃG^s.@jȵ. fa5) @r, `q5ʢ8Cʢi I#43?Xsuc.\Rn&wȺ~Kf[#  @oD4A_fF5xaߐ\y~{ZP~ }ÇL7(8tdD@ïO[Y )5  PX4:l2]6h/ hB>L@i3:*ij:uhzqZnj5s{5Pjddd,4Bn<BnՍ;7~.fŝ;–~l~gI FiHB2888Vpuu%=HӤϳM}ai=9[ex:AMMMڈr3-{eHӭl쐛^*KL1]Fٮt)n$@ Dq7nRpdC@ 4^p83f , 3mƕ^%M-0"mj2{5p$5A/59mFכv^;$g+ɛz57REr7}S\糝*d4bi;Y@jdrpbd7s>cRjw=!GCimt^eխK9lK Bsc5k~b2"Q f\⣢A"vsYB@JQ TJ;wnʚEp&===?  X[ 9) DòKzZ<#eZS]!7.Tlr, XTr1$v`JD@\ :BjիWnzY  htt5 fHF47:5'ՉW)?ڻYBqcX iNֵ떮=7gdA@<B*eS4 h(!  P04 cܹs {M{k֬YD   NɠSEaՂ Yni$<;HHڿUzmp5k}1Z @O)'rߧޔ@@2 Рvڵ+!cW_-nIz衴:YA@@ DQS%kR+$)No:Od8~J6NwܲrYݺtdD@ DcqD֯hՐ 0 &{iu}kc.lذa,ۢEDG !  @x"3$k'~בY+ =GoXn|`3:k`r>@ { `  @vE믗G}41ԬV'&4A-ַ>   ^`tt41͜N/˙ϒ't$ǎ2=]U?oaDǁ~דrLWͳǍ:f  # 4X (@(C\}co|c<w[̙#6۩H ֭[GB@@@x`0ŲG._x*۪˛r>( ˖=r2jj)k箐_*MN:9@@Аn`K  PE hPFO宻Jv{bvq8ח`BD]]|K_5iz@@JQtDɾgPm'l,l?#C/h߾BVkʤ=f0䓍;H01Y:Y׾JrZ;LA&@(@h}~[4H   ,|_nMv}Ji#G$^S/ȢEa@@-78|Wuś%g֮cIsS4aV9ol1f䋄[塞mpZX5r͢5rU2x@P*WhlFȿ1g@@(Z@R7M-S;dܕrK6U@@He5%h@JZ %-J@@(#QzEI dcNq3⬓u亥kj ! W`8ɡ3fGV@H*i4   h qa{zᏆ䡞m`V k-@t   N@ʿ@0K WUUd@(4| 6MӨ3+9("@@LP(^"v?GCrgSc{M,_^.tdD@90Lj94_p@@9O~R3֌ŋ˽; vl߾=m[.W6mڔ( @@рR~70$avaٿ\r%  T@<'P(nr]ONӅl[V}'! MuB! %'P/˲gϞ7,k׮CWr{LgT&@@(eYƂJ=V{l4./v?%'LUVU%o81"üSe @ȅ@-TX @@tР#)tww'FFFfWe\L3ha}}}4X@@JU@z@ʝ@0-{e03Up!kVGW\":Se @ȕ@(x̴r  0@QVvGx< ǎKs6 @@@[!#xaѝg$37tpYkm) @0)t&f-K4jm%@(ohM6N[g@@rÉ@}'V {ʃ=D0]r5 f Ƀ `NWr0ZN~@l4萶_җѣ&^=鱓C:tH_3gd؎  @k:@ʭ@o`HܽQ=tmزKyg.  @L}oI"F@c@@y@CUU[N>e{AWN5ё(@@ h ozxz{æ=G,#!#  P(H  S RiqՉH Ӧ0Ʉ zN#4{@tcC~G$fLiٍ2c: d,N~w|mnvٷo_b 7 k֬ȴrVZ[[f@@JL $t Rn*ɒf!!; @ noo/^93  Б4!="*jWnʦNe@@̸i2BC&  xa<1zdqVf@ %a…mdWΣ~zy]nM=  @D <ÆT/ȝ]oTɶ*yru2n2Ȅ X] `Lu@*#4ʹ_H{AOFdigT#@(@Qr8^$y9ˡWi Ta#2:]&L ȳ{=O@kCֶ,DfMA&@@Tn="1q9x =R>DroF OCQ9dF@`&4DyIOOO)@@r! Ġ 2\ƣ;GH 6U`--]+NSe @(5@8ZjU. lh ө&b񙟾o'MuNqr;i暔 `F(8 a2iʕ+39y衇d%Wo*i@IDAT  2|aLP6!l1̈́TWkO[#vLA@JVu:ZFS:&%/0p8.NgnSO4 @(M4|_۷MlӦMy+{<eǎ8=D@@0Lta34< GdfierQre@(e@G YCF?K-t$@&Ɲi|x|!oCB;@(J@C[l_I  %  H*nWy:9y2Ȉ 7ЭՋLa( ƥ& =SO0HY)@ 2@*!ǏՕvڼNבv2V@@L aLeO8#wv=%|c۳YUUɛg/6FdX'fec@+O1fzl&qLaLcRt'w7ѶiQi gs!cjH4fLV,%fgj9\-1O ч@(.LJ21סh5hюZoO_ɔryϯ@j̽myֵ( '2o>ݦ {S={p b۳)ҲǾr]w^OMK,rnf@@":2wWy`,"{<-!jyk Kd+wC @GÑyR :tQ-br W(\ӯ=sQTŕy!N$`,i0>Ua_c"SRQ4… %A E h[;ǍZm6O~7m$_җni rW_.'N(PS@@B4Ao&lf ecNq3⏚te亥k]Yȍ @(+ӖneJWk;*S1Ű?"G3-@J( SUh}: gx=ny _W+dk\ z׻dΜ9%So* Tjt6OͬǏdÑPVf6D3j](W6~7  oa$Z}b) D)'F4@J.! 7xc≸gyFy@RN:"E]$|;EHB@^֩%&VJ6}İM=J6M+.ږ.  @% h0C1B>q|@]qc ~ݲrʩ5-7CCC,,RԤ܅BM=o%,qIu>yBd5'G gx<9P$ C/t[VMzD7OZz9+S>sH~ 0sVIۼ@?"WےZLUglFr/3DKV<+}Y9M' jO۔M9L}ȓ{}mF>m˶\^@Gȕ{ק G$4\:dQ,w1+>0LN~"k\ )g?Z>^.nD?j~ߎrfRrwwwI4$EYndOOs #-EoT>ۅqֳh@ΤQVLR?snS+7:i; y7ʋ}/` g]ܸP7|ivԊqlC&drݪ /3+QܳzgBr# B@C8 R) 9Ч| (P :$OB;v&# R@GV*@\dRH4(<=@ŵKҼXsؙ5wA@}7\\ J gYa%h`A1Ҡ1}MǬ:c9@ (` ?  c dйuR#yh<~U om^"j]%U֝${r  AH'Id#ʠ7M3񅥹ޕ2)@"GMk[kkk:+9`uXR:DmsnuxJ&2WIЧSw\/RtlߟV~:$g+z[_p8ڞl' $F2,T?oNS.iI͖Ј<|e]\:Εmg.uNbOZ; ;)@M+L> 8!!/dLX(% !X@3%?IZ*m Yf2,Mo^nhh̓2˺Izsct >c9_PԀ:rzzFo&lА*eǓР:,ɝtߓ͢1wHߖL+Az)g3+wv=%;.sEcܼrjo dԟ%'5dП# $]ߏlk3M%3U$? @.tJuDqqT3Ju{Z5iFa>΍T@4qzrٰaWJ`YxqtD@0+ 2ٲ*-_zDܹ{ *&UEdalr,  IL0vTBWaN3# PE hg>#;vȊUR'p4atO}  . :"P*%byܳrܘbLrvrȲKevM"ȃ  `R)'L0Q쩆',f#t (4c}".irWXC@( d= xlp8 O*uo_&[u!-]+jהc'  @ix|4SbNt{dh N(@7nmƼeai   d| wnQ3u/vl8C|mDGcQ,<[^tT   nb憅(AoNoL5Z糢E*Mѳ@%tJGG\~rUWIkkk8%  Ut2@{?z#^>9k 5rLAF@@ ‘FIyٗv .AL7U\@ %??%3=18+  P=sdd@wOzJ4,+̖ #  @!*Qj]Et&Qn<>sSch3  9(ʷ"۝&P  ":"N-B n<҉#a"CmR%^d2\& 9 K Pe<>6-^]]XwNB@*4X'?L{7h,nA4X[ PE h( 9  ` A !"lgxh$o9dezSe  hB2XA |Y @}z:71 @0lnthq(i'J *@@@@@dUio4([ uoo0Zc\t]j E 'ɀrr" A@PD|)'HL&0 NNt)Nn;#89 PǥO&،_9eP&F涸 u:΃ P!Eh8ps=Od|aZ/b?Si&444THL@@t2d{䮮O34rӊurVq{XE&: σp8,M755b @`騔j4p?li "]D@(j@?/gE/RIhTxy _\tEf)KH `#jJ@JE( $??Pի#ȴA v풻K?סF̟'RWW7@@H2bL-Y U{xRmtʺUrݒRpMxhc}ƌOM<=v[<%$m^UUU4@ 0݄U{fz $R>D@xu&#L( :M+2Vs-!sضN?Z?y9qDp}{>@@ h ȈD"2엾G6!lHܓ[γEka W 7~)k7l<-t.yhHgH5*=Ot=uRQ PI4fo)\}Z"1 ,5[T7q2ɇ PE hذaØ^ґ2 fh,y/Y>O%.GyDnŵcYF@2h `0Ƞ7GIS 塞mȡ>pzMqtW;$h\<4=_vzf8 $RX@P@r I(qR2:CMK@CRw@ wޱzk׎gpYg%DV+/\p  @ϗxteq>kFyYT3K&9eN[ȷݙU0C߿+-%oYٖĻE4pJ'a"D5@ȱ@$h,R)P Emx|,Vt? (x@CZsxp%H2A ?x  iʬ  H2 ůk7" ^>_(ye\QzuOe'yT".kL12 E N @8tGJ+VRbP@02aگTY[Pr2 (oǓVsaa=E($@@k2c)±l#KpxcSw%_'zG4?iULkY\l4$ daY8bkB@G]H  6D)dA@rh(~dR}_Z ɖ4$5xG@ZZZ;44$㷥J,v2Z!\  /~1@G"xt{x3qD,X-ûfKkܸIVfn,k ^ٴ_3羑s귝> eА рB"9  3%; e$@@Ciwf(rwiD`_ZM$۪ m* (x@CggvI l߾]/^l[[f@@=% ab1 (}^tV+RUy 9dhGc#VZuN'gP .u⊽uxH840]{fzJɯSFhB2AGd !  0D*- jp92itZGM3  :M~mLq L(P+_rʖ-[z+\{WSS#W[g@@05nAFd\/D^2'9bsƤvވvx6M;^/M?ۗd9rəRDhE2]r  SH2 @N I$uӝQ6hȟK ؼXA ngNy@D(^wuc|:B7ͱl4=3XF@@L h cǎ1*gﱔ`3v,/ϕXp򧰖5ΕKbȼ6irf?|Mu9x5Ѐﺺ|mmm2k֬: S@R!UthVX`DH6\ ! 0S4s9r׎|ߖm, y -ܒIVA@@4M daqe}O<'땃 D5SIjn*y>"~S2{mƈ;'ݟ鎕2= nnnsJkk444tG@bSggiciT~jYM$5#za;oĐ?p:} n?4-_ذaԲek_$@@ $;IE剃U WGk5G7 om[!^6Sz_5|/tȟ_xڤ#{&?t&elt: >>ff  ?u  'UөF0z)P$&acgzJ]@9h?.{1 s;Lޜ9s=qqohh(g bH=^򗿜o|#u  9R sPZy1 ƣ;ݛZ#>۪l6˧:eY?MG?$#}-{06+2FпYA :" @ȧ@`)y^έ@$O3:P7P IcmǬ#d/`٫h_oooI^}L@@,4Ȑ[#;C&1rYJiKF3d\<\3iD S *:qE@2>{҉f; ˈGHH45Nxl6[\Rm:A{ۙ\+wo蒃}^%:|ȠI *:MJfɉ'*> ?XC՗kd.TYHLXY4ZG c Y L5",sp8  t$Z".@TT:AmjwʊΦIYtK`@FQ[XƎ8g'')N0vl#e+hGj:wq|}P񋭯H$ !40aF9bRqrԄysj(ZcZ s7u: 3$127Is\r;Vf"ՑA :", `zKwcGy3}"2]@GXYPR, - P(N  @ dŬ7\^҃q_FM/מ':j;2fH=o_<$Km&68zLdd6y%(nfrypA̦uI:RtZ߹T$>6 1@@r@aR  (3 !; @6\Fc@@ЛĊ I+`d!_a4(hM^{FP)es[o}ۅc]q|j0Xc,pYN q՚rfݲpɲ\vy٭r鳥Ƒ\ՉjkkEI  @ 0BC "0Zu OQ6[ěN@f(+x/ЭiL462p)@JX@~U@㩋<2 9%oZ.IW  ȣ/2ƹ$4$Q\:1?b.!%j4j1=? 20u&+2Fkϗ~Oe`8(hXf9b(Υ9  pߧFh(^ :^3{$! `F  'eϞ=cuYx{cpmӶreӦM,@@뼔oL-lXĸg{?pP=Wy<&q1;ͨ!9봖P01ި@rg=㺮sߏ(3fA$ ]H)QV[͖Ď__9.)/y/qDXIQ -YPDP$ щL/P 1-]`}Vд *KqZfa``{WFzC^^DdM#   L `w1&bZp /Dgxtx 7ɰ"zHH }D]А>h   H"d +yT#SBs؆uW6.0#AXz>;Ӧ &9W`8KP ʔG4P+Q=xm_fsSV֗3A<.#0C"15 @zw8z!D |=JI@2U(hH3̾ @lM,HHHH $G"*B1kI T__nm­feO88t6m 0bЮd6暺9 CQn>Jucxܼddw#VXᘥbJx ZD dt:/ʔ$@$@$@$,t鞼'' -4DdaR98{Ⱦ Ă@ 2J=Ƴ$@$@$@$@p\7 '=?Mְ ڻlqgsZB^f ;BO 7;?DP+$ Yj >kʐC^aв@R3SZX 3;߉BS$(m>;BҼ@ѨEBPa$!777LJ$@$@$@C@lwv=SeKO#yD$@$']#  HNS2GwS HDj=Sp.߅ *4APBQ!\ӗ[}uչ8;P -Cү_de/"bO  @6;4D@^pEBҏ@1 CA?IHB!A_\s 6oPӐ d$á 3i5+K r%BVW!!,ejw%-p@s(}93p˦@?$HHHH tVKC GK?&kr>Gx(+[Y @Hȝc=]viKaa!tMG="    HH o]PUH 5F)ƚye(*p00:#!ώap}U"fBŰٲfd(7?BlZ0\|[ᱷO\'᝗63|A "dO6 Ӑ ,?; 5@AC)ǿ|XƄɄX# 7 Mo9Nuttg:x<+$@$@$@$V&dp?jL)^>@_M]UYS7΅>722]+AB%(ט#N+fлP:_˧+P?ɒde+!C>Ju|q 1ç9_WQ9,I _o܀+WW0.b!E "HHHH`(h>T(jWjR1raĴ$@$@K 6wb;;;֭3 d<2A~N LY :ikqܠG[y<rkg=CրE00c!i(^ҋ գj{ -e$(E ""]9ٸdyդu~AyihUyjMFvG;5bixN7R"+kzFȔHHHH`YH(Z) #0٤DDQh$@$@$ FFF|e4f.;6pGj"E,f^g]-M(zr-Lf*ȵk[!b|FGVAT!&BSgL'?Q/˱jHy>#8{hw0겏wxi/r ͛eF`i+gYgLoDAFb |n}Jc4`e|2-݃VKa~.fk!84!';+!AƁL2T}掇 )4'wb&bů&Ex&  C@ >HZm6[̾K6[ &IHHH %1$7aF]2H! 7hЬI?؂u觡%f :l*XNӄ #⬃HHH&'`w/>y)ܛ*lؐ*e;02+܄*#HHH`0_"fנ?c/\G{zznw12X@`2p=s xD#3j)-a__x8kXFEEEQB{!&Mm Do}xxx\x ABeEbAN%9eIV3NM[aŊ9WⓓSvwR\;MMxU"ʼ"RլFzNx8'·tS{@ ~%o$~>^|pWHH2Md⡁롄DPxg v܉he @o f-U,3\s2߿y%w`ב386AC,cQWw''OFh~a%^p ֔G\3F@t:VS DBb KZ$e3Orpp+~FVYG2 M[E6XT? K-n *OLYЩg\/WMSst0ՒB]>(,yFϙ(Pih/Bϙ))Js @$Dα   5xX,a2籮`Vb ;`Nd0?x:6>֧ .WB_4+L.^DȐxcj   ??DR3At[M4-=!%Rp$iPن21gi벝 `l,u|M5qEpHH`2 @"^Ry6łExoN}Xʘd{gh564Yr`צʅRR}h! !$z&b ),HHHbAbXpMd)b6sNϠҧ^m_!<ԭ-:/Ոz51C]aTi9XXVf[xxk? 2IH $DpEHHH cAJ! v B0a쥸m&)w A<3HHHHRr6NvE-'M8e͝xo ѢPbw102ܣ-7^X\^eX^QZi"c r"M_Vw  $D xi$@$@$@$JN&bZmUTbǡBAHheZ=}Qل'O},Yb3 q՜B Ak04o / @w$:!6E^bDž#ql2 1wj&qL=`w1mXUXS9kgG]ޓ.?v\=~2g Y d* 2,$@$@$@p8GqɞKqm1_{Z2<ݺb T qkz\WY*-$"f(,,n,HHHH !,Ȅ ilW*#S8<| &/ Ue8.![>VªFZ,BeA$4vne&;a0 d4\.tttԩSغukBvHHH D̐VT{o^}22/7^>~ rќn- b3A 4    $@ y^*Ă@P DАVI( ӵ>^:HYgasmY]ـܬV4C.a' q IHR@B Ǐkl޼yZyvr^z%i$@$@$@G@\fi3KJJ2B]uZО xQj  H5cccKazZQe%a38xz&brņ\q*N{Id (Tw5n:Ѭ}p^^&bGhey$@$@$@${>e>jH"DUe[\Uc,lC)fJ4!<c9͙/--Eqqx!Y_#6e5VBS%G :.Ta).*Cu$.-B2-mwY> H= 4D|^̟?{IHHH<"4ͰZg&,),b20V!}vV1_yĪYY,(֖3Wi3h.с%v q^vΎὮ򷻟VF\]V$J@;GeHHHyAvOԥ @ .k\(MS3k^l“'>L9+nL>@'DNN$@$@$@$@YM7*Į3pp$b!/[s0_k0F )nG6e1:hP.Wiwʓá6TKS)V6;Vi~ [jyY4N%Lk$@$@F #{p׿5i2]un̙ޛ\'   nBKgA0bu AUI>V5ؔfLഩ/u?,>2ښՐ7 $q3Ma8aGr X\\EujAf t!7'u$\,W]Qǔ=-ZzNDŋS&m)pM|n,,ٛ~ | |pHH`@ v۶m8Qkmmm%Z&&fϞX @l0L n&5m`˿raay;9zOQ%{v9w/؊  D A<3HHHHH@Y^fӢO`TةD oCwCuXVҀshR]4J2r焥rK (E[yZu\N޳݌yW[pM0@D(;.uJ%"*+Tav LA⋱i&ڵk8?Ajb$@$@$@N@=,ݙ1PzfA^m7Y }G~'؁es4 C  !/mv } |hQYܵl38ڰ0vB Y1;<Ўû^kpMXR^3"CHHA*w?p22s?яaɼ$@$@$$,G bf|#xCD 3o#Q7eְ1Y p-]Pv~f8 41 HHHHH  D&r|W1-e$/(X]yV 8ISSv>;,֖{/ -CxZp?rO6kޭ-+*G.ƕ* Fnv_Pp':gp @?e:gSm:ha%,E,h\ ]G NҙnURܶdOɏql3"4Q<<|u\۰w.DODTاW^'`Qp>! 141 Ċxb N'g&5)fۅa )kA:?nmXkkV#{&N zc LJ3'2N'^؍c#! N{Xh/gg.q '1E|Ő5o("nk6m9RCz#BZwIϟأ-U// ̚R^D'2}.N "h 'HHHB" QE[B$Tp '8z27)a=t +ƭX[0+o "bO Ln_B=wKߤ}XXT:%xPRkK ;AW|;܀owsJV7pmgȲw/[kaƌ!cf   &AC]]]#gIHH% 2XV)W ˁ~(Vmn Wŗlł"N'(ܽ!??♁F$@$@$@$@"S;4>4ubutP=CMfJlF +d]9}/KyTX[m&lW^9>Nz' i4FK|ub*H 9]c%7'8 @:Ha !-IHH mI \6%d0&Bc5rV.(90LBFń$@$@$@$@᝞}J&kg3#7f_s&K$-<yFܹRܱ|}}tn?12kV,~^ƟWׯAzw sOq  Ă@e@I蝝xGoj3Faa!.R~I$@$@$vfY7H@)Qe[]m)XGdHanFܾh) 8.1$@$@$@$@Q#`u׺^F$-H ;zc{ 1溭jzF*>r]HpBDHa~Bm1c1d7U^ܷqUܳ*%lX}G  %x/HH .hعs'qJt5r.Jc;5ia%t:]'   H[Ros -qϵTͮo0s.ĺ!\@D),/ƩfZsdx#lz \u .[1.4opV;$@$y&h?kS_ <1|J\g5\}$@$@$@IN@ S,NiS?^uR+}gDo@3(xEyIA8)VCAAABHHHHH ,6E aQ&>9V";bIY&8g$eȐA1 d$ G '4<#طo_H'E]0lEH0 @\h#dK)ZIhưov ؃) :5SJġs @d CCַpI g.õ0"ɞjWbdoejOQl^-ȁ7&UBbݬ̜-+ 5kF:6m$OWWɝ& d'_NAD :HHHHIÕO{2:)Y4!C(ABNbG`iy-/u 9­žjA s/Ae~iY3.Uy!N;;L$@SHgCxZ؈>?c;444hV^ ---ھz wRd @BKPͦ 3mr17v6+!tZ'O`an[.02TV]nwoX,56A@0HX zc`5    D Q}[ll\|ŐAhyi"  @d>;22Ҫ*mφwIWWW9|gqqd O{^aA$@$@$2Afӄ ♁@h/j݃7NY߳gϮlo*/l8 @ ojՄ ~cX}J4mށ#4겹R,,ApA 4    HE(h;;{wT-.݆B>y_U_5:y48 *^܃U? +%G !/ε:  d%wACuu AQX LUݻ']pH^ 5k:WHHHK@0fؔWbtkJ\cn5ь_+!C%pXvce#RB9 $έP"!&h$@$@$@$@$Mpb> N{:-sG۰1|حB8]c3Po/*^=-~@vv'sը.4-F$@$@q4̜9SstAjnnFCC=G}XvO_~{X$ @XD`X CZ`o؅A9p)[KQ3L z-|HH2@?FGG'/3<< UR֊NJSv^nrBt\| [1_d^5|H$7dꊵd1fMYǤdSYvQ~Ce ]XU1/>xzNGA8  'FJG[K m`¿rWW-"/[xc(((ai$@$@$ /J_z0JT<[rInN/{YTJ qлfw/ʳK5)P'؜0{.g*{Ι;p΍mepaB!>> ݓ9R9{GNYX7yII$.iB.k9);3F^u$;SD O6/I.h>p :t?]{o~m\szkk+e0;]L^"رZh4+V\P.   xc!pOͿ܏a{^HHPkkV5fxU yyy|25&$   H5"hHes 鞝htՍ%Z|"/ tZ:?Ɯ|ZJ3544C.~ Vq6{ΘU}Q0# #0A?<^,YEElsW_ų>dyvOTݐGo6?h/!^)qa?ylܸ; IHH "l6ӵdZMxubu<$@$2 ,{?MMMؿR~5kySq3< ]=7,9 y] "hMM`iy7ȻUeuRV,*SClSTC$@$@)JL͘n*..v<Wxv+眡4M yC,xov>3,E ҢG&Ycr.eOHhze9"'n"AiY9rH{hppP+"&?A`>)z[Zl^Bhs*'bw5\2mwP[Lz]](*޺M&rěH=x[ܣʽ*-r(byC;Atw۶m())BFEo./ΝO~;IAn:.466jȑ#9曚cB$@$@So@2$ JLE pY UrS'p4gF6V.ڐy-V '/p HH2\@i3bu^ΡwZHo?=C44d5LcΪe qۼQgxPMNNCY:T/Y5یw o`k*>[Xiӣn 6J{bMYY3|i7i R㬼I3xwgaաLښ5k#`׮]ػw^fF,_r jjj&#hk;600~+2 k_&fQ`<3o߮$' GVBf&"8wX\}؅A9"9:lZ/ۈR!22-< YfD}HHHHLn<ٳY w̻ 懜 :\(,O1%`sNA~6w ~:FP5VDOz 'ڱl%fg&\ˆ<tH2@B YBDtM*tT[n ;z_7n=[<]0D4  ' a%f3Jd{i+G{?F\\F2w=򕨁2=a%g$@$@$@$@$~̶]'Cc.v 'C`w͜lf2Q<{Oꍕ4ϓJV'? y8jnþ| .+_0m*Q tV  "閄g>I֤#{oaѢEۓ\tEZx O\;vP0(# % D`ZG1Cqv}oǛBY9Yr\W ׬Av݉ܧPZZydHd;X7 $-2ul#/9r Eafy0<4+V#h6K+ȉa Ԫ2Ԏ1Nᫍa:`T8 h$@$@$t=mG5nݺax hkkCmmmHyHH = HX q= ;O Eq&>_^ w{z^ -!"j L؝ʓىIT^>lA^uKqYlu'p>g6Z/Uw㥎xm'$Ą33xw7j/V..B򊒊I؎T'L$@$05 ףN/wObm} @N$@D@ "dp8{O6<ڼ;"nҪ:ոD\F&ewLb @(,Ine ցPY]ڈ;_2}QypzK1QidpQ'm# 8AZ{wFѧ;i|Fa(5oO<9{aV^ Ɯ9srB$@$䥰!op<یߜxmkQ36V.Pr[Pm(>I̘1C B4NHHHHH<Lva,D 9}ޕ0<5^4ċ*쇈bx{/: *<:$.徇GCצ^˓_cK$@D ꂆ??644׿{hjj͍;vD%=a#²땗%%%;C1! 4Y\}O€^OS谭j)8oJȤL"l,N#    9<4tYj+yW0 b    STshaƯ->XS܈,\߱ʩXl؝n5~pVy˛ Xj@N˶Ze% x8jnZmÿ{q򢒟' (I$}M$@A ^HtO?L4".~)OU @@ˆx[OOgz?o^QU?끁gZlHX 2MEiTjm;NFܫ} XJieQ H( o{>VCFK:;;'{M'NNky9s&`Z">Z s @ b>SnE:-$GA̺kR$TZ Xy3r}Q;μmx ?E5QhElq[s)Ή `J$@)@ ꂆx h_Mi  `<@u,0uSIc-5wty O2ow8"Qs=͖ީNqtan\Z*^ہaIh+1AwMtn%"@ށD?YGT%TtxHH $hxq-3C !CSBNAC`{U_iE%~'^|>mz ݤȚ5yk٘OqNO' !a=IŕKpLfGzݑ{: OX {??v.ĽtMM {,JdkX֙e6M amL,..Faaal*KR\Vw|Nf>KKK}3mcaƫaqG&)p帩n rtD\y;|ڶəeSQ {OmEt>rbGR0hק'8ix")++4gv/"!meegQ&044sXTT;>Ug\qr=FW̙qhO=O$@${ mq/⣁c!w7mŵk8?Lv[gƄt*+0?^%<}ܱ[bڬn;賸dh5nk@AGIH L{O4x8̢U|+'0"* ޼e0cZJk;#tuu̢6l_+W/U_cd᝞q ۭyb ccyOK6yuDܸub,)H3Ii! xzW+>Ѝݸ6||}@<{,²Clr ??P}O$@$@$@$@$BښQێrpA3QG'_"z&Fӳac.< ]F^Dxxg}$@$<&hȑʿȋ_|Q[k7 lݺu)j\ _X壣/LΝ p HA%n=-tn~o3~s]#{n\;_b"6hO| 5b}#6(.ޠs{N%h1 4     `Nrq:<6҆>!)b= n@0L%0->N7\Ԙ"w)sOP@IST5TMĂ*$ sAJO~{/jD֭}݇ļZ>-Z !2C _EuCCC,h7&<ٺ%jJu\]ԯGAN_TD9\cK CQjԇ]K/XT]|^~$!%D \4     #`A ˦BL}'BpX94?t_H dX"~ύ(/3N&+de ciq=~y|;L.]pj~GǗArkc'LyxHґ@ ###ַo3õkkEccadɓ'Ԥ-gΜ㡇¬Yz]]Nضmrs;*+i\! 4' 074#aċ`{^κiꚂ2\W׮<|'IGDM1؈r/[ wD9&ﳼqHHHHH F,h89څ=ʂ`aX_ mEh!L'+M8* X!X?vi)S7&x1?Z_C$@$p@ ybxmo I| h7ߌ!7#;G"jGl n@h*/ם'$DȠG!HHHHH`zL"Zf^<~D3pŜuѪ$@-y9"ۖ^z_E<׶/ԋ-G밮bqQ<"a'(h"PE$@)B &ݻw_A`46lΆҗ+w?>].۷!K/{z!tvvj]k߷"Eqq!n I@1HH C ݇x.~*G~v ) _e>8!%RCQŨ0u?̎ OI6ucX,ɟԻðr1Svv6D@!u6L] $-QM?oYVBL\I{=Ģa\Ƣh)„{}Ϟ~/>4v'O߈C,Lt$l5F$@$9.h1|ؼyp7{6yWBA_-:I҅x`X,7,]~ 9x O|m6 zn_f'K#-864iK p P-7; f*µb6'L A,)=$    H1 N2]^6+wQ" cϪi ]h[{&un;OT4esațAE#'S lA 71GzciSs^")ioUK ,ڂ%?(d9f9Eb: Y!ohsjg/'f !ĠǏ D\!    H*\v܃9 A$ƺ-Lͦ={m$?Óٗ3#wο "h?=柇SȤpWc>V`^xOz[=}Gew܌_@\޳鍄 $ ҥ(*b"\^QEE)!$@H!mٝ'>o9;3|1Rų  11H@ yƇ! rAJywZ㟻ߓdK%g8\NiP3 e)Րh:aS+KjI1  X<4&V?NjS/*Ĺ\0byr <ǮudtA}yqأ0A$#!&bg ~_98|B4qІ;q& d GIH1,m7W?,ٷ7+o KF̊Izq=YL ICJf20oRUDR: %%%(** F @ c BuCU5 kzx|MM>oBb$Q徕ƃvI Aq@<2߅_ox|2Nn8,V֨i'jTО|+wIH / =mqP$@$@N@1HH ˥nT>a↓xm2.!dGNՄ KSbˌ)ۛ[SjG\%VP7ĺR|vxxb!"HHHHH w؜muwc amp@/N]fH`0N%x2DBH3+?הl! 7?@9V8i)3A0  tr0$@$ĵxc!ǛtUYᳲq޾m4fFuQv?8})LB4vlTYsfz=fg}     $ԄM]p'{o8K$|2aYO#dp>Z:n"&,Ƹ:ܽϵ |ڽ?/0~l; HC$@yKOr`$@${D "3vNCxy[# ݀5U4     Eךk=} {dž c :ꦕק'07F<q/\xzCy&0b"~ N;]     &j#_uQGQoTdzuoljI$k>j<8b h^1l򩁼gLoڢ ܥ<|nqcb楠!&& @^_---]AHH %A Oj^Rjtmo׼1h'B0&d̴Oҋ௯mŎa/|{)Kbr}oڀ}Ψ{aU{1מ~(*-̙ Ϝ_yz U `@qq1BN$@$@$@$@$@  nN[M=Ov,bj];KDHLSАàzAKIgTe3{V=o-UlSπQ@frF1 ?C.h?d @~&b!xf^ĈxhyPj:L L_z!ŤB#Cee%JKS{ V7 L n{)5XY/bk s| HHO{ @xRdOSWO7^mۄWZ7Hi-o7Կ~g7kXI>P;s~ږR>fIeWYR4|CSx&^#hF$@$@$@$@$@K?X7ocܪ:\}ș*4̸yx/!5ΐh:|q2Msp[k%Rno@{vD̘B$@@ |=@$@$2 +Tn%?-8ЮUXݱ5mO(yci̘+{ALO?< 5b'? *7^Jj]yyUiA2fXA1HHHHH%⛯އqqÌ0ttܼ@K*<'݂^^s54\ Vn@ z.J fճ WJ# _sˑ @ H ÁNM L-H{{muwQ\zl&}J0PЃB/wc^\6X̮ G{B+>oS!!J̞PTȈ{ho$.ftXv/T+AEhb3d@4{VŠhvCFzI+s &m7n|hwG^z|q= U&!# hԸ+5r2n{9~q9Zݝ1o? 5BRIH 85HH# n7\.+1Zz4wC=Hi«i[ r톰(֫I9kaA؆]V&wT[Zסc+eڡ k,M1B Yxxȇ>iCrsEO "d#/}     H+>-'xa4|yg`%wϔjXxCtEEjx *-s-IJ%zsbee @?> 5 -EU',^Z+>܏NU<]fP7&`k=`VRj%W6㇭881q[ش7?ם9vu +a] v1YAAAzb60UhԔ""QDȠ%b` j""4+S3H=;;[e2:%szR+_NYRC\p$t\)D5AؚRtc'&sHHHHH yvaF< 3$% DUҟob(2 /[;qc%n^f   4yb/IH e"Zlhiij<3\ &D@b){|G~U@ܐ.@CQ9>I2W$M?4ؙo:.;5ǔGoH:JI E ;88;M$krVJa~Ըﵷkue  'C HIG@ UI7: H۱y_:^5TSǔfiUh TL&KfT/?RA}yQ5 ң=d+y3) jBHՎV˗LR㭝1Eqp1MU|q1v7^vD<2-E'L GHHHHHEOV=_n[;]+H0ʂæ V\dW^<7LU5zIHHHHH 6OWΨRzc4Ʃ`@Aˍ}fP=qRАP=dɨ7WCد<6\=甬?;A$@$<$@$@D@ !Ch%0u%mv7Om>W>uSujU9B8vTiFV{cPʕ`U@WXpP}a!TD K"u SP!YiбXl6X=WCUiXF$@$@$@$@$@${U{?[mwے1;g.2QRp?hEआPcݛ'/`?8|#jv! G`x%N$@$0Dp8сVްڱbӊJs)fC8LpUP E*K&d(3p/S^ Â>jDږm&?^`JH $]’)+;w8㸙8~֨2j:^1/4b"dO EEEg     /Xy0f)v!w?P&33;Zv0cm?>};fgC/މ_p%h3/IH  1)}ܐɏa5n^ށM8ύ'vUa%ܰwW׿r]A!ʌf{w; &V`ZÁX5;79xڲ7O} -p\uJT 2& @vˆWqvFnV^>3eQD^r0Tdd5ZDQf!I,'Z=<6 ~xSR;|;|ܰOQ?ÇlHH i4\{غuk2}H{W^y%u>>Vk#sG [[uq;i! F\F^/%!-`s7l}n*$B"  7ņInXГ}ez) *<P:(qIq۳[Ԫk6VFWqz4f}KyE]Oň/4 2fiugNŋ7VYp1X< N{w,)3ZhB\.rei,?\YF\rMO@~FN$y;L/^< oTTTŌ$@#@@=SO-k⎶D+8^h$+\4r,,~T+g/Jܲ:O?Y(V\3Ԥbf  H!49!L2IMVyD8]S% ~u \vN}xks[x~ؔΉk_)LNJ<)aB3Q7XoVM]ϯ&|sdܳb'l Ff)K&(,\C&azx #QEX<KgBMN[gT}6lovC9T N/FaAAԲJt_ fbB>3,Y(\:͵1dkn\fϔ|nˋ~Keo<5 7 ˔ .ߋqA[* קV6Di糳`x0k D0m $!'hAvNrڟabF%jC_⦘2HH m.hH[X  8YM1t|+Rй 3PhPMT,(^PnKTWw(^koVq:>r1:;b{@:.iP g!G7Cəu N㛯݇ mV2r&fh&512o5!C\\ۙ, ??erm PF̍WFymo 47б,d7Ѝ5 d=- IϮw{jlg!+ 8G@<Ƿ9F_|vܶj̯3/IH@~Ϻ =?@$0! F#B]^͐O 'qʢ#2ǃ?N R.9ar2Er.ohb4 9&    8hd֯Cc3(6!N L$0je;åw}9gD_nne 0#CCq%n_`ٴ6 _}qb12HH`h $3{hIH + M:;; %"n)fӅmέϡSyeHE`PB:s9&i `1,#PQlwϙrK~!vU4Jr+Ct     #pw+fMZD B&zI#{ Bܮ #K^ }ag}ޠ[W;CϙP6!,vH<2dc| /z mwJkec5V5:nP n7wI w.=ȝ `+>i!ۯog`T&g'nXp&Υ 4 fttt@Wa-%/UIz͆M67&!)h; @xb˛D UN~V}ľ쌯-/.; ~ڊwaNt:(,(@eWCsa6y'    H+ۍ[ry=n?%ya! 7s3T 9DVP5dxᣦϧ_W Jk0[9GW @ 맮LxGgϞ̍- " "0k0!Ae{[p׿63Co*闷Lv0iDҠ7`F2+Sa":|Jsd!H02HH 2HHHHHH  laŽl &KB1{ }qf.o@[T%n8ak <4'9uJ(<M԰qeQ{M[q7'\cѠy@$@$^&hطo= 1.1Zvذۊck ¦TVC9 &۷Uj%d@v6/,(D2T(!NmG3]an8k&̦a֭7gIHHHHF`שqw>PV#-V¸݆/t KeZ  >v"j7tӐMwHF6-8X6vb,,ĥ~2@ 1N݊vOw!4U L.%j\bRI-`bQϞFm***PSSBWIHHHHrHHppq$f6nzgk}NNn28z-} r"0 w,MZ8`ibP§F\:w  !$0pg Ub ܹ3n41zh |i nҤI2 it:{˄6j}٨ ; $ a$ Cgg'$i! Qw8ȨGMI_{{ay:ѭK(68vLydq8brDe Oؖ?ɻ(GwWBKLa$@$@$@$@$@#=Uƥ3?(2vAga&#}2ّM}$ _)2%AyS<6״h]V\m՘_7i@: ^|ňL01|hi"N8 k_<2{ʕ+hn%aժUK{pH`d/>"uA -3v8pUQouL'ihMZQWNr[<:+)Gc^Մ|yh:n[;:]+Dـ1,R$ yp9     n][o(i!&N8?|;2+g4.o@[$zV/Jt.oY/ ^t³0RWvuC~?]% $@$@G l{{-)c`'5kDƎN·| .kJb`|A  2TUUi/N$@$@$@$@yF <83)W>J"<8E@<[T8N_KcQr{?pGA$@YF -r2kQLҧnjjBrBK.vÃ>J; @ "XZhiiHH 9NϮk'Iu l@Ӌn wŕ>ym.GRuI‚BT1u2PqHN@ ՚!Y3Q     ${q[Qx ."j@+ #\^ 6KpCC:lAdܯDp"y+ɚG2 Q"FA+-{ 4w:y M W…r呡hQ~TLW툐F$@$@$@$@$@F㛯݇ mm0Vƭ(,pp38A:^hQbW qhA@zФz<\On{n_ِzȋ0HF{h(,lRVF2&mݺwFmm-&NEsH`x v K1$Z^}"%Z\]eo{py# zBΠ<1k%*M r{=utF"cٕp]/hM''yEuX%HgD㊫Qf0@f(1C%=4H -A!CHHHHH w`wwk!}pqKZk;n@LH4NODd%.1ΓS'ΏOn^%  BFl $D,3ͽ4 0H"fXV8N|9,g#:_,8Mİѡ> 8?OPb}&b[\g; #@2ԠF @xq y;,:GyKcPrH@"hu?BU8^Kg:4軈D  $@$@ |6ɖP{/9}̘1vs"7 dD Fe@IDAT ѡ (`yֺc>ץhtZ!a&o`:Ňv Ä啡f";~(̝XHּ#BB>D$@$@$@$@$߱7N%ez%`1YKbeK9M&>%[-l<Ĉ1D A)((:3q9u׼tڿ9n^f  N ?SO=w&M=.׭[׻!w{w$@CC@BEAD"`O RBBKP<4̳@APŐzaoE `||ȇ>J₉G] MpaSBO6Xr!oO-F$@$@$@$@$0?y7='X-']3&6HM&"k #i?B8Y$1P.y"~qy{Wſ;ڙHH D`Xrs1x׵>jkկ0zPYfiJw܁ٳg8"߃>M;6w {`"^Hi#ŤGI6 ;A )ѣ%czC}Q9g+ %Xf']!\4=Q-H+BRCNFvHHHHH |~o|#nR%f2A'c܎2 zTYR#Mq foIcIpI QUT|ރDe2AHH Oߏk|Ļ%\#<_0sLxuu5N8^î]pM7.Ӽ<Ȋ˗/\XX zqp*ȶ1ĭF ܨBj BW9KfA% xFi+.M`20ҌdNj:d2l6kaHHHHHF_[lFC< S^\1k}ݳhuvۇ-荙$@$@a4Ȫү{Dի`^A|A}%9n:,KV "_H Q;aεXۭ W38mTKjpM䇄 :]a81     5v[x6m5%WRj밹 OYCB&aJFJO!6j ?\ek#Vi‡ytIH AIy&n3&b_5,YZhbYzWG ; !^ B>~oh Պw۶k֬5f(LuNxZ, 6^bT2.[-L\d&fC,E /VM[zk;f/7ʖ4 (4I$D> d!_L~f.ŸO|^|Զ;&җw{U(1/10H!0lϹ瞋ӧk͛7k]/h?Ig}V%%%hFőwAգJ(LXZu)_x}TᒾZKY̼L$ L`X ~֬Y{m6Z Gp>'NĊ+em5d  S!@ @ &T`WTxq^]-xm8fF=>dTs}≝H[н^k3ǻNmYL*Ԑ3,T(=uܵԷ?_^#1+^$(L*{Qb!Fohλ!c8o7L4?x'~!jժtT:r("\#.W?l#>r[[{=,;l,.C8B+ۉ}s',BNO_9 cII oGIHHHHbR!}W|n2n[rJW- V[=k4lN/Ԣ|.G䢠|ˣ&'Kezܿ\W>㿀"!f^& @>6Aömp뭷b̗c0n2<#A fnh;VPRBU.>gĊ*Pz|53q PDI> ż$@$@$@$@$@#@êLik;࿎a/m < Syz]rϫ4h#=pӮÍZb{*zc'WĐ>q& _[na?{@$"PHDޕvu7ފwZa V!$FzwU8obR q |jݏ+.~ ~VA&pʳ"H|+{&y} =,OyPL<uWpyqmz4;e Gݻ4L=! :N_#aԂcfc7u;ۭ[aH<}錨T b egpLa}%%;F$@$@$@$@$@$M[玞!/sN;2|ޱevo{p8y"a'I wŤ5/݅ߜp%7L$@$O2.hp:hooeX]] ǸA$@@@ mm;hFZ R[v`9nc,@J E#C EdGLP/]ii)(dc-     Co`ɽMz+q̘dž{}~1Cˋ21hBcH4?ǟrRZ5!׿z/~rX6i@$@D ゆ]vE;c)f  vN:$,[,~! 8& H޺ߦB/OZNsб<^D[f0k%dK4kha.c"dF$@$@$@$@$@$ݿm\;J-S9' {ad費sZ ^&Qudxhf;sv9O;8x_n~!:YKyH @ .+~x>wbx衇 .,"SIR%`M:qGlx-cᵚ>+/  ʍlp z]rt H!Cqq&d(o8IHHHHH _[;v6ƭ,#7_@ĸ22 $N{U8N'>eӓ; ʍfkqCZײWpָyHr~8:|_駟g=]6EOY$!&p ,_3j+=]/X=H](ԋ! uX2j&.t,Q3&WP RB YxX@$@$@$@$@$@QSڟa~ug`ݜry"ߊ(1"g}glk}s吠AؚFvU̶1qojąweR3/IH dC^Nwq~ᬽh7 \y1wɦH8q(\q j"63@]LBMXw-1A Q F $d 3      \M'f(P77->W3LƊ@0 2\@F6? >jQۏ_sJܓ격Ow&{ Hrxh:s ~<n<3Xt)WUUUJ.'M3' ZG?w}zɓ'O9眃ǹC$$ g/]^':}΄nJX7Gzn-*Y|ek=}=qt}E$@$@$@$@$@$6{=_,3űa9eEZ͙`'H @`LMv" ǃ'Th^W:t[q'!u+}1N0ýds$@$~&hxشiAۇ|P6VZuP击p3zqأcI$`a\'VBO 3CNG{3O,9҆Ys޾FQQ&dU @jdm'ڸ2ne*\yuٿM=FPq ۟ӎB _ ܁i0]b)J# %0l3:馛e˖7X-iڡn Xc-jTbv ڒċI09| ΟGM 0ZX !w:s @ x~`6>wt &͛ ں\ rx=AN 9ua qg]HC\ګ?~,ᔯ⛯݇N#f{͎N|g(,BH$E`q7bΝY f8;&+:(z꩐4 ! TmێGw]3[wꕨ @c R* Q;O: ;0@r#cn     <lj_[cJ(>x'UKA,MEޥH#!QEVMd9[ǜ ={?M8;.I_qͱM #0,˗*fUUUU#:((wٱ4 zi6;11pٸhґhTH 0L bF$@$@$@$@$@$pV\OլU =Q툆i Wؐ;d6?&D N̜hkd2>\&.{kj|{coـk_n[r*L12H@ `O=T\|Xt)***"FN8HvgM߲O: +FJL-̾暲XgI3Pn@e0#WxެNCqqA^lr-_2\eDƒ'[rqxD>C&{7LK?7\N$;twgz[s k;wmdْ-o;' Vٴa^m)tB{ (lze0 ea$@ dO;voٲ-UXòƑ{'{eI9#@bn\&P_~4ZZ=zL= 8vd~47gXGΓ0Jhc@+>ix?m_,C;f5WT>2ޡ(d4477D0<(((}7- { 4[ d%M~|.uYa7>3KzMMgR˱Hgwr#ْj!'E2\'w _[hooϋ`mj]slk52;'x6Am j`@!ZdFqP|]k?Ͽ˦˅ 񀆁)onj΁O|Բ;k}pgOљeqY2xA2Ȭ d](@ P(@ Q7/{BDJO'Dc干|J =KIIZ?'2/xYfRH;[xHKkIxfR5uIku-D)=ezB%(0rpIY>'v }(;5rpfg{فDY%WHaRDcv#; Y.Em?;, :޺- Xmi9quǹ9ȝ?#FxND|T[[3f X555{|ĉ;wnb<12!.K---Neddx+brq6 youy&'''轔_|ѰU}:K[P㤈_ &QǠD\xWw+|~lGU%Jn~~>?\ u;-- қ-< Y߿ٹRl}˾Ig% @dG4 H<";ؚ|xޝ PA 6ܺr16~>Oc=l@ &aUT@;n W:Ogjy_'.Fӆ>ƅ@_N; |G8hݻ7ohɹX hh؉1(`Co0TQ: TAW8`%yն^hS] P(@ Pq/hn/?{{UG |=r>CX+SчP# v2.Jf~,v7~N+~>}3\ ͖A|A:ʑD(@1pW׫^ƠPEF>n|&;'rïkq2x!;;yyy(@ P(@ P |˞@FM8=jcTXwفݒd,F竿9b̸~+;pGa[K`B =s>}:>w}_: HOOZCi=N^}pah9r $N!QVb-V7 jRV .c yLJ( _322QbW{uW8djV9|Yp(IRT?lB-e-;ɦ"?UF9e3-(55WePVeQ"޿p͸ӧQs._܆=GNL}@ ㏇z?8(lXִ _J"=?S@-LN@fb l(@ P(YMϟˏ½'\4uJd'nl7A H!/Su@fg.X(; ҫ$#ϟy~yl|zx06WW.(R4t8(x|ݼ7hIY%r.-\qp'##Zv|(@ P*aܽUt]~spˬsFv[J\6 P 2׭͌}7 36r3vXf??pׯAo,nql_]@2JD DJ[|ZRD c]PMkEDZ$O NF P(@ DV%N:.tV!YϖXce~w:Y|na,7GsUC͓AS\Wb9y[N%L#sHQ=dƆg|s..;n>\8X}@(.كgygy&?xh4ay5 ;z75bQ'x.<9A t;q (@ P!`_G'a6d*eNQ#W=_ K4> /o,w0^>q-W6w P{ lZ( %ώ> eyQY}hqݩ7(@ D%_ի=?7ވ F"V6^PP:]e< Q(@ P!e Ckuȣlh7P, 8ф_;[Nplv1;',@?n@,'eP5-e@(6@-ϼgɑ7Wnō˞'_](@a CR0{A P܊wC[|%52=?S@T]&_u:,"ף(@ P@6q@cd`[w7pՄN# P1ZXo]^vbt:[2S1pOE\F DW[ѩmؒl3iؓA}5ؘc"pb[k0U>GDPÄ~xp"oP#>~s P@xz-V7zBct8xN5IIpDxEYRB2%_q|(k(@ P1*`v(. IN{18%(b957(9 &EDo71F6+ t _]9>"qbQػ<2N!X2>{M#_? /2`)R^ #Gd쉜4رc&M^pM P fk*V 2lazf9+"; AI^IOOO`6}wR P(@ P ,Fݓ!ԃLctq6RS.Ծbɶ˻zVpˬsq޺$Kq) Ę@ɎS(ة׵ Q 2ه65Ba+M_6~=W<9‚A)@@_q)O?=˗/g@CoP 1.|ѰWZ!V'h.9fc 1Z-z'XfQ(@ P'jg ]N'aHΠPʆg,k_ dj-M}'\Su2argB*BP>d!`u1 b>^&\"[F7^M}ޅHaIhoT|P  r^z+m64_uv?1pF ĠiDz-xhڃtu*(ӉvG{Pcq%Ȑ#R(@ Pae!3yވP{ h4zaWLLO=Iye ۋO]\-l-22K\ c@d@C~6\Ÿ Ҍ\ܺ| -Jbv']T]\?w@TdGy< d0ƻヒ5kCii)P^^bC&kEĭRA/_nE gЉK' Jdff"555|(@ P@@VQs@33 5L ̆7'ԈTϡw*sJ)7Po -g7 L/k܇>|Tg P -R`y_F]cΝao3du~yAQNapvHyzL驂2 tdddd0[N`G P(@0 ȫ˫bQ9MQ+aGfFpܔ?7կreSp(3MI@uy|Q9\rG:А.5S%.ڝhA]V1[2SVne_Fe g݌߬x}nCfi !(@ U * V–-[:WbH`oTŪAzbV .c z. qE̞#O P(@ (CՍF/ףdZoƂlm?qotnu.lH=?8(`AHq 4rr2{~ VmJÊ_|4n#\9"yQ:h'2 9iAxiTj+2BUr#n7X?d6fZ\H `@C_ ަp]XٰWA51I*,(GCYznPcp h4O CJ {S(@ P ^R0iĸlD: 4Ya 5Zk0h߾ޡ(@0 0SHp7L;YW׮U66/Ef*3'ε(XQ hxK{K88;u[MANӱb6rS3+ M@R!33YGuhZM P(@ 8]nl3V8f+v?bFy>sL/[[jD]bG )cdf&-4$nSf gWLGiF.~~߿m؃>||=*E (@_Q hPY_\F A ޯ݈j7@5D¹3LȠ $=?@ P(@ + dPZɆt tz_rdN8<+{|Ql(@`d/Y79/+OPNԵ-Z5y8db0:@0 A4w3v:, g+!plR2)ɪJCtIIIC_kP(@ P0t M(յՈ+"\-jK?q)^y@pܱmB֠R-}ě(cf[q uYx_Dje͟=g+&/ٗ )@`@C{9mki7^ YŸr) To{S^q©̱)@ P(.ZSjb^ɬZ:Éx?& w~wd?¢'H:-ػ#([@4 O@+2?8jO|1"hT~yX;L-|[p-ڗ (@z@Ckk+x |3\ﭷqma>(0Ӂ[E=:FibrS3uv VdeYm(@ P(@YdvXiqъl]LY|q <}T1̠huM-9F P,;PiٷW?G k1Bp켁xd(@ J ?N:xf>DIF.;vȓ*+&J j <dvm޼yOc}Xx1>\OʚFw}7^~eϕG(@N!U-V7F'dʹ8`kFyN f(@ P(@hW4b+ЦF류cи}lK=e'] G~Fz­"(J(g;>'}ƺS16HVQW[۰W.}[pe@ DUe˖^Ry p8czuz+.rr-toooLJ~EZ(p˱Uxz-k z%ҠHKK^|d(@ P(mVƖdG{1v~ֽ#$//21T|i-sbbߢ9I3̓ќ7M PY4l 2`g ՙ cG˅@ DҥKI?8,ş~u{セ]x -tY67 fP'%)xp׌ gZFnn.cR(@ PG X2wˉV};`3*g3nb0w~KZ~y(*wPm']ϺeLE<}; ;P1# N֭e&.C1ap Ϫ}0f̘-xZlǵ* ,# Od@rr,1F P(@ P@ 3S8ϩ܆[W%&! 78WO=% XNy-Γ@ oLdYfr'P+ntɶϱP?x%ĺl@ DE :mېm)@ P qL.f។WξLWܺV--DbMZ\Hx@̦з۷gАov~_033scp Ēxz-ky?KF첡!H=?!Q(@ P@O,W,&|e3pQ 2A9a(@ [,24E^ WS[k > uQ9B`@x@ [?tرc {}; . 8E)/E&׫ P'%㤢IrFf ҃EZ@ ,eP N>)-b jW* ( * /-#1RhRRR< 6 P(@ P"niӐ(Y\n7ܴ/lr!(;ј{7+KE#\ve8묳PPP0I6Y={ח7d) .bQ`ow;Y +qH_)C@V{2h4eL(@ P(FYkU(h7_޾nx?-;5>J-+ t+-b P@eu8DZ$Rou]_,h>;g+Q ګ~#{طo_/b>QTEEE썍ۿt{p'(K[FZ|Vŕ0%,1bdPIFF(@ P(@DhWgi*y8vK@rHדD)g_=(@ P fQv V=YkLv~b1;wKl.a+شY}q!(Z[oŮ]q\8t爅())wމKx7ݐ%?F)sN}Kiު̭}|[<%FySʾ!(m4Oy Z }\۔{w^p{'|b݁m% @dG%|nWo܎=ҏ:cWmO_oؘ`贉ؘY2/^>_8X/X)6 P@4L"Ak)G`T,9fܽ5[{ZE(>o.!999xO>`'%}1+ĥ^ y-2͑"K ~C/SM&]Xٺ6mԶҒ8)o,\ hoojx]I>e"t`Kbo}|nlRI8os{j$%`7-<q @tGa \s{#F`@ٸFָh_~up_ܑ*w13;@%v Td a(@ DCd] s64-& ]vܷ |X!+[SPv@(cF P hM!p/S \O<uRU>F" P@ QhAe#~_y655ah⹴y dǭ;}~"OQj0'VoHQ~<%%HNNLy P(@ Ph'c1ao[=nbߚ='O\0uI(7HV &Ǣ(@ 01a 1kN5lhwnߵ'^\فbB)S@^}r^SFCq7lzt91=(ʮ@0g.01DVfSkgMl,o?(yܷts;|m`>g=s;|Gh-=P)}8 aq S;g -]Oqs d a(@ D[S)E{ܾ|m&:?䦥xa>z^.,A׋(-E4D L@(QQzok][MЃ*HeݖσFT{2$喖L^o^:y߀sݏ#wdV1e ZoI^^d X,H&k [x v{YYYTF{ {@>Cˁ(RvKL4Xdo^GČgdµ(@ P؝#?GJ|6sqt(;0R.(Aq(AqX/ES;: 287E^ۍ/wuPmj}|(7'MEsQgCt_AWi{n(@ PMYoZ HWp靆˵-!+N9igZ;l5)@ P!c(Tw?憚_>kܶgZy^\NH \$XVoͶΠMJӰbA"# m6 P(@ P@sEίwv)Q7N;,.N` ‹)@ P`H&ɀ!EsIF.?&<$k*swλg᷿t=%dC[(%EPo*4:;Z(15E1_M.㫗a7nZfmѷCjA9n wc(Ut 2\w_xJȧz {1!qzKưm j?Kt9@dc8d RCԜwYc\ֽfy F\B P(@ P PeNqe4YM@635CB P\*4jWSF+cbN)nb v;{bsS5%(eG[͐υ4YDk]%ef0~/"!3P6bZ`oXUFwP2J +)"S ddff&KDМ(@ P_M|y;"G'R甆jnn񥲿·S\+zQ&)Nhd0ҎK )~)7H &\2<\@ZF3M25gOƄe0CВ[%"g-Q(@ P% Jk(JiMOVk+0hl@)ZOF Pe':HG=wBۅ~o,߷׍=]ȦlAȔd"Cl !@q'򀆲2\B9 WM9"[tZl[(@  taeb `J\- 9h=N/UK %PsG)@ P(@ 8DZ]َ԰NyJ<(fh1"51a(Kvy1}(@ PJe' 4#eǕLī԰~jM{b\Ry2N+d}18)j ԍ[@gae{ʠY&O;3Y9ҽр7bUn܇ Ÿr-d ``H`s(@ P4hlzv3T|eNSkp8\0r-,79mn0ۺ<x,Qf?˚x >%.}yrl6 A&g@ڻ\JQEg D0E&%J\Ym@>TФ$Ckފ hرc'+Cuuu ;2+_ʠO6 Z7D fC^+r}@)))iԊ}S.gF P(@ P  ?yb/T=oށ 9p466:R,ڇ "+ 3wt l(@ ȓ&~&SQT9!4aᬲc01]4 ,{&g?᠆1%<XNeBv MdkAl;Sc$z2EMfe;PQzmxL1e.OF '8h0nJHY4dV#oQ(@ P2,dfCl/>Y 2,^/+rdVI&y2TVV.Ll6 K|j֣5:W>π>%m.|,d& O LS(@ PB, ]`%b[/\utXa2 ~2>\TҸULsoA|W09 qbDzFz\~o#-w[1QOy\M&'xv{_WV+ebcbsMmLjJJwtt0pIie/Œk>2);Mxv)N̙goj1PQG2rv<|~4SZ6ےǶ6y"\rȷơΘ]vG4WU_wu˘!϶޾\a] t7JtXX1O&eSd?Z,3(pR(@ Pi &~/O <YފjCϗeܮRU#={H_nj=GW _;q۔s0x 68O%NfR92V ȯi^a`AĞw?yx)tM$×2^߆`>G/uՍulϴP3 G^=p/۶b .-: 5sy~~FC(/aMLNN{`4(Glz}_ $dee|M8ѓaԨQaxrx5yolҮ,…sq\x$b[@y"X&#gO P(@ $hq 'ڱ6Y7 41 B6 SΌ Dp4x2BP0C϶yc|z^ME^}y'N3J ||kIo t -&t#H~6klw([4޽ۓa߾}Gp?12 ūVKgE"aZ~Nl ׍lf)@ P(@W> hV` TQQq[|q.3QbQ"N<ʓ*'4-TKW[n~j؄O~dF0f vn^7X .#|( Eˍ2QB4 2+Ò%KCMU#t>#3bBN.|\6s"HbK@~p|"fF553[Ҿqߵy;Ys&VkR!wl*~ZIM$Yo G'm(1aj{2NŌxrwr x;8h-oU~+ T94ϻ5[&RD$;jO#^ҍ%=SQ&'b {Žދ2'AOVy$r6yT)8tVFAZ233!_3X 7(@ P(@! hedBjfesњFԷkq&8#<64ݫ_ASk}ݹlŌs>28z\yY^4r=mr<Yp(2#y GSVy eQO X_Fƀ1nu{}|me @ww73u01/_҆5YƝ#EōQ M\PDPӕS5MoKeln; *d-~=HV;GuK_gWiGV珜sg@29 20D%RPnA؜YGՄep{(@ POl|Fv]]]^/`NW'P!) Ŏ@C33։,?f ~o۩57/cq^qPvdٮ#ƕPuܨVQ>Ma='2سgk_~ #: !S1C-V2UXA̐ G@Fgee )UcXm4v|35cL!.]0S*- P(@ P@@?jmo⩸KLO :w(@ P1"Wr4fR!ǩY W?tEx~Rl3݌ۍwkWa}.\7]o*Ɣd}GE;5-Za9+2KXx1d=mYƌ3pS`珜518 ~kԵ^KZsJt 6 P(@ Pip&7MA33즔*8 S<(@ P`F 4 2AmSg7̔t\S3;M_YZpwKpF,yX7QbBi~m޶ pUFȋbٔ/}y2޽WT W\q2(@d7aujmO ˑe`0kOZŠ(@ P(yEڋ> &?&"JLqfT̊,'B P#av$O'.@?fg8] h ;M~Zl0ƵcĬ thBF{L|oA U UbC  wߠ%&$Gee%qU箻  `jI1fٛyS(@ P@&'nM.$M]& 3&+Y(@ P" O.iTKq&kIH,'#G ^ V?Mve?1t,<:u`A 2KV6Dz?ci{2E(!3vŎ@| naO Ȭ Y]io}-A^*3o4FeiC P(@ P~d Z}3ܙ3p CCCC?]2(@ ĉl q7%&faK~_]{˛ {q1'bnՍF+aj/H2]F{+=4O@fe%rrrfw溠7\(@ P [Z֗xG3kxh+< GX' X*H P,;tmV`K_G'"r2Xn oS(@ PD~^q $<wM7AnKtx5 G.VU9Rd_ ԉR~,rF%s$Ҍ]f<]u뫨|/]h9#vd#b\`@C|GB&"j+-]0Wt]JdeeAfhW^ jx7B17 K P(@ P N+$L O}Bf99:_~<ɪ~/[Dhj$C{A PhAl^4 vF^~m,ި^Yn݉HJԶ'w? &7{fq)@ |]øf_C5tbLiAeV^@(]zш=}(@ P( d=%Lid1ݧck:TRByLF PH7e'sEZMx:J_?No|(W}S0;bdGy_`ް:D0C=33r(0 XxdVL{̡ |j;qjjO P(@ P wK C b53Ew=RdC^o_vP@33m(pf(ن,u²7%˒qf< /[Mm{:GoLnOC =_ФCp[ //{yp( mOfNC~~~ăL| TC,mQ9" pV?@ P(@ P@Ì,% )Hۧ^ǟP0CXvG"6+fގͣYS@fGr  x|ߘ'__L\\129Z)j; 3g[9\oGa-y;v@ss3`0y &3@"/;Vذa3D]]]Ǐ_xu-^An/YdD?H%;AKP,ĥ &ԣGCu(@ P(@ $f>Z)C+S8=gHu{: Ҳ$K0aXQYY7tڢmn(mɁl͊q71@4m'/ z˂~pJL: cJVvP!338?{w/GU&~ᆵKBBa',FA¨GDAQ+8#8~|yuX@a% -!!Mrs}SMw.ݷOuN>﩮[9c㖛Gޒ_22M={ȏc+s1DdMJseΰx`qvy0g ^_l\ɲph?QzbS%dVY^Kdr@@@ yZV3ow4Ea7w\Jh>7P#n- ,YB@ $Blѱ1dKqܳr;']-[ߖ?l X*eˎrNYUv\3Y=ou_'eY^ǘL}ӈ]Jw} %%%rKUUI{{ƍ(t]P̞͓UBϼbAYX VRR>)ox.  W}egp+9e }'jay"y \kV'wCQ]*uߢë-k3W_,YNVQԗf d/jP݌YQdsڵk/,-- ʚ5kn)6md;7,I༓+W=Cp9?A_R   F[t0ZP>c0#%&ZiWߐ X7)0QX݄Qy%3 8%3(%܊sWFZ>zL^nNZ97buCqVf_?ּ(׽.KdUVWwA?$5]26Ɖ.-3j2{~_* 7v@IDAT5nw3dMMM}v8+g5wg͛t6ma`4ծH   xyke7[N0CEV|ī'\X0WSoЦ[D@b!Nkqn.[q3'_-7.^/݂MvCP+gl{Rk@0Hhpuz ݻwo6lxm?>|l #0GN)U;}YV:øj|  +/<&-!g4˓!W=_e!ɄEᑱH1.4U /-=ӍlEzHON^.uhwp p_SDlWSvg~症h!5M|]MJ[k~M@C(jL3uKi~<0Ƞ)˒~z,_>b@@@y&TK&8k)9JaFTG{'?U044Dcr@h.c ^k֗i빺vC] 9\<4*8yGw-┭[K@!5geeIEEtvvJii锭3x8g:? h|blY\V^?~LcUI[>G8kd;9@@@hG(/4i5=N fg歓yNgsY73P @jb>  /9g%Zu+#5gyV\9sRysrwt7.9CZr\wR@f͇Sj }C:JJb@R7ox 3gN5 #9'-5`l,,3!   @@Ȁ)Ct7fm'F4|_vۿv I5޽;`ҹs3t4ȦH23?8yRenE@@@ >CL6y+?:V&=quէKz9{y<Vm:?6L ;@ h S4DjbZ=s+O'AOm 9ȹgx@sǟw(_:#rŢ5qo=zIs[[|:$% x_`ddDx9s3@iiiR\\,քG@@pV@[a԰Cb=S"W.O>Ks4M kPCiO:NϑYu&ZgpĖ"_o`Xe oa@$ɐO9Wγ>Y^j~'ŵ ȿm}D۹In8"tIM y&ZcЖbb*=矗_)*++ežq'։EG̎ W8yVLO"C^^כU_4J[MF}v񀿵C.k:r(Q wWGrF@%Q 8N:RAozs@I[>DW:sWWW[OGT9`'Fɋo&mCaⴒŲayR]A']v,YⶮZg=+FpP]K o10gRifܰrQJCFy0?{e95k*C}[=2\I4! .7x.r/Fl0-f)GNNdee[ylmt|;ݶݰ}78ߦKb[c/5vuMl۱fm Y ['?7i; gUsϗEž73X;?2ezṙR]@ NV@CUIn7~:'IW)7y}9,9kɒήGFFǬRFW`j Eei  +5`.E@C|'pgRoe's[w$.yɷ6,))7,HΝb;0,V =ÆV%L .v!sO@0Ò%K믏 i@Y51eddD{{{@=HfY`j]jޯ6-ޤ%%fͫ;::ϗu݆R4RU^OeeeǤឞ0X)**2) cvqq1-9TޤK/!9#)CCC]z>` jz[:VYYg 4-Z)oQEޖ?YZ"7-K.uZ!4j5߬Τ4wq|Y+ C#sXwX7{?;;VMJέX&OyE*c07B6?G/metcNWn6m$UUV~8ƍG #]n ӱJz+ \2MHЖ4$ 7!6ænomogjV/{57n}3ޥ=Ft32\?n}[kԦw X{%xOTQyMڗe3bfy2UfV}؅ARn.tqˏ%&BFK? $@J2 BP&eo+#O'o jyA.w*;޵-9"/0Bt޽o2dgg0f5ݧ ,VX!x)¯>q)@@0B`ptX67 >auairɬ5'e98Pצn56q+9hfLscr['5!)d7<"  &>W]RMzF >-#V*(HGFz ;6we# R)jᨼ(1MU-z3sh+PY .(eK;rj{S5KL9S 0P׾NBްa}پϒq@~t>y`.yqW{r)UrŦ-h74Uʌ  nh얧~j7YMWT92+A/:&Kj蓒,Q7t!ղ@B@l"am|"2(4 #A}[~{9yd]k uJ?o5Z3+N{{g?Gv]w,]Y2hTޭ}E^Zf,ZMeGY.򓥺$y5!''y?vw   )GZG^'i՛ d8+L)M@o9VOB.zMzk3=N-" zޢҢ̄/t j|LgV扡@ev|yzY?k<^E: x1c+ !,`t@'?I9??7l6io= A ,f͊t_[f%VW=sKE2% m'#&{)+  K΃EW}ʸv-qp"C22y[iHOj׷~x. g $@պ Vv%VoEr@UN/O[eņл{5YYv\YlEwڟ4) @#-4Hv&FHKwt`Y|TV*^5oE>W9b\h-TUhDDCz5Y;'|2`/'IMMK/t)";:"^ znI    KfˉųegI3[Q [=ǺoI>{@ʋr$#VB e@֡P1  a 4Jn6XXvLŒMhIϗD+A@@^`MRU$^;p\bҰhf9sWZ{ݕar VG\dGFF0*[hU Cv ;]kIljVXRi5\)țV,7vۿWw-L ӀhJ /n ]ÜyrQYh+3tl)((n   S IcGTN=1S蓢GB@4w Hnn&[+y&ڒҳYgV|Zv_VuM:rӲS\?=- D@K+.Y}ͺe{r94pײi2h@ @@@h엒,LP崻֮P'g:@tIanFf"ںD"!0'%UV`jzٺmJ[[#ٯyvOW w֞YkJeqOUdWJ1#34   G#-tN]Ԇ0I8fZ@XkPƬsDMVF]+eZNK2W~M> o3.f>wGdN_$˦H7.ե򳯞/?C^xv<̝/_ص v0Cj*GV4_"   0K3 ڥ%ir&'[@pD`xtj%iP EL5vXl8Qb|kv~V-=lm}~V -E`u@qDGXYv],Ͻ~Pvof~ YX/ENgűH~~hw$@@@\W r2œiX }}  A%=k*s1&ckkKZ~ tȦA7kxz]ýtVUU"'gϕeys(-/]Q6\QMdr"%E_,߄w `((( *<   $crwvK8lu5OO@@ ~z$nEB3h<@T,H{|rz{ nxf8mg_93de974KϞ2qF4tuuÇ~uvv}-~7,X03' x<)**j   h"ۉlֵ`@@uLnx>ږ.!0@ZGVoV^h|ncgC`o?ֿ(K䴒ŒL1 ---rw7>va_@޽{,_\kJjjj,8 ddd lqV   V+SzW3]M8@@)˔4N&FǎNIRj9X6%ovX7V6䨼ձ~YN.oNZi>S{ZS3v _uy'r O^Li@NN̈́a";   $ȨnMt5a@C4GW *)waGZz(9D`L9krj ˗|Hww466fVo Λ?&E0)   QWӴvѵ;2=?~]>l7[}v+N!]Yg hhooL3p]w-]2mTh2* ,@@@ jv3A0Cl@{)=w)˴H8ēPKg4u[-?*R|@y)Fɾ#ళF  :G\Jyf}gSHE~3ٸqc@\} ऀ fHOOwr5,@@@$ j[QӎNKѦ 'dY& ZQ,)-ȒojpdkW{ wT;t'%Ug>5\F@I|uu]'?} ٺu\s5rE٭,hÞ={w ~]M];; ddd @@@Wp/uģI[d'4I  G%;3Mrnҭh%=.&3@ q hR~ӟ{O?+too<#7pז~@I\6qe#   `.ʱp60{Ocn ! ^[FZYQhX6Z1 z'0J n ]LTTTo[f`mᦛnID*Q题@@@\('Ӌ!6mVwBV 1Zr p@\OKK믿^~gWiir-rwٳÞGA33ƴ   $6^m LN,JOS !ج@@b.[oUm&<Ç;7u;NN8ꪫ$'''`FpB 33n!Ր'/(#D@@@F$(/(Ι/ЗVk t1>s   KhZ~/o4A>}ʲ7'@^^苄    hPAgπTKANF׎I]k}];B@@@rsseɒ%`HII[ewJ   @uMCfKZC^3 V} $@@@ hH f hK EEEbf+@@@Ѐ&R))ultJkWD,fF@@&@@j:.i̐X   $6wˑnLɷ2=!vpxnXѐfc"@@@ hH*@h7',y@@@@[@:c֐&iITKMV+ cc]W @B@@! l {X#a*ź cŃhMSoo ǥIS4 /[O q͉c}cBz u$g6vITG8 ޏqmCP 8.YREaY,@@H4x㍲w޸=q]\/YX 9U>=rcppP/pO7^6u^̚+8XGoof8r93۶/qz7 MO xs*ydp0`ْq8=o &Xrzv̅    D=A/[nȰP7yD@@@@@@dz@C2QVw Hvv A@@@@@@@ !A+b]48.[[f'Kڜjaah No\'^1yMgk噜eW筻;%,Qm:'`m,tIF;^t;ݶ@C}=?VU@?dzz:8wz|H p^S#   @lpӗzl0kӋћQq4ŢAN'@ΨM~ SQgbT޿kL`zhc qM_ ho`YZwuu1\ΗI\ev{{o(@@@@F wusss$t-**ĪVJ       *uX.'lyH@@@@@@@ hHNj*@B@@@@@@pq 7k&G6HiiTWW%##=4.yqqCB@@@@@@p Gg}V~iyehhhRlYf|#>{i29EmA[h !  $@OO[р% >גx:I5/Kr]t_U:t_!ȱ 9TZ`3_@qHT*8?on9NFGe =???]a׮]sΐt"=oܸ~\Ro̙3C [ //OEB@@HNN o/JHGנuj cs&7M@/wuu-^" h 0 .MhB-D ԛ$w hƺR-;0 z65ar-HpDv8uVk?]6Y6U,EB@@HD e&b(   4Ri'm۶??̠UUU2c _9ps=KoY~A@@@H&R𦬬,IKox֣.Qotb0Va!'hȤGg!Y&zk/kz.ICccnwrC=zԿ9HFKfWq'_52{lg ̛7nknI[[[|3w    ŢA 㥆|negZ %%%ܴ1΂7ObYYYd.u˥@#]z]?AoVZZZQg(.sJKKE$pݯzǫ.ikkeXGG|} ?q sʭ`       W  $`mmOnEXp|k_,w3       y@C]]]իƧ3rg0#        4TΞ=;b3f)8h9        4dDF-&;;7       O  bK[oZccS]]f@@@@@@@'fbŊ>~X=͛}i +W3       y@Oj˖-_7;0 .'Udz@@@@@@@K@Ú5k+I<rwHggPo.dxx؞|/~1Y@@@@@@@ HW޾q?R^^>W|       qK@Ûoкxccc 3@@@@@@@H\-%C@@@@@@@ ĥ#"!        %o//|       t9        `\!@@@@@@@ m@@@@@@@ *!C        fAwwPD:餓"@@@@@@@@ q hzJy hFz       q[@þ}nݻwǩ@@@@@@@LK@v)q-ȡCLu!_ K{{$S ZySWW xGy]djj*ۨÁހmY[: 9#?p픔x<|fѣG}d#oyԝNu_w^ c2]z^z^sWi7wȈ@ipoQs8WQw\بD[D}:=r8v:C߇կ~%w}1̔rΎ@{wl>@ssڵk `N@@@#N9)**22od_&(!0E@@@'31?O4SO盕1r   %p'jˏ$@@@Hp:K>cLG=!!  $@嚗QQ@@@8q! ]~da Þ@@@@B@@@yz999        q h(((=6P@IDATݻ7        1h~3.b-[|        *]UW]%:(o[UU% .A@@@@@@@y@Css5?>c@@@@@@@[ 5ojj X@0C #       $@,X0        3fgff3       Eo9r$IЖ-[$''G̙>00˛>NBD Hx饗|Y[h,Y7>ހ3k,W``WY [ɒbpMIQ L7_XcIy 0 ӎQ̒P&86fK@'_c-L,ޤ/zJ2'Ȼi;wnMWAmgxxؗO?7<ի}_l`D& yDHsAinn rXj.L7_0Ot1)/SÔM&9i!ND̸t9OHTk=++K***D.--uEjjh:&{0E@re'--M. D"!`5U މ%>F`<[8vk9ﺺ:mÛuL['fS ɶ-P t1)/ք9e&)#]Gx㍾ЦifΜ9,|@\4gʕя~TVTMmkY(I֠{Pfc*9 47NջpZ, WGVf͒W_}Uz)qڻ;wzO 6>`5i7_Hڊ t1)/ó(1_+ERm:4Κ5!0?pR/^<<|@f<띮\)&`8 <5Jj#w}wul۶M#geҥSN?WL%+Ծٔ±%#`1ǤDG 'bSw\S~cnUίO?;"ր@xcZgE&!D.|rB׀ yWW'Qcc {jҿN?-{wmoތ8 GB@epTk ^7H f p^mV}8#G؅ ʵ^+|QN:$$8;ͪUnn653<#_|w9T fS IZ;&sLK Y 8} Q0s)n =}MZ[[cWZքA;v{' aɒ%rGAE$+ 1]LlNQm?eff2 GΫU_z饲n::B{{h0TAEEEO~Rx_n׿Fy&վٔ„|@&sLK̎8rs Y L pl};# /kJhM6ܿ^HӧBM7nGy$ f$x2PܶC!kpΎuX 8WbG1~Z5ks=gwuHww燺8`ĥ'+v&&;"0cR^"1e^1㟓5ɲ `occ추4腄cJ7r„6 yӼy.CWWH/~Q>OHqq #0m{ozc+ @pVX!$--.?I0NlIF].АO %%E@p^fGVsQ=vϚ5РӮ'4|:)< 8qer^1Bߢ/ĢXGr t1)/ɹ5Pjr gVDb!Xӧ~:s̑o}[rꩧnL48W*D7͛^xAj$#`^{ &Sׯ_8B@ ///Sh@7鉪| :v։O;JFܸo~L:昔Y.p1tjyI 2Rc4::*ooO~Y|y-[xw}B4ag{_1)ں̠7î*;xc@DVJKK}~Iӗ3+"DQ(b&٢u<+l㡸S u”HL4L:昔ir2Qp1_72h86ƮcB>+'?I /O;4K~饗4sL[믷˧>~wzޢl{,EBձ7wb8}X"''',655L;u b 6^ E-)f W:tI % #`1_lNd&86Nœ- M6k^WZ5n,XAtg~V~_4>曽_Hn20CQQ|_pt̏tmOg̃@4wޱ'G;nl߿?`y3 j =տ4P\f!g; WLτ L_xM/0@4L:昔h,1_&`occl+whz?UUUo0۷]^{W_ q"000`3477֯O}$' ;e˖l׮]ܹ3+8AqbW@@}i:pwmi7s: B"$&Ihͦ)\\L:昔V +Ojx9%G-~cY :c 8  p^֐"K,eU {Lu&oZnwpWLD}iZaIb`U$1_lhsB~'~ -63Qoa߿ড'Z>#;d֭gddȗ%} @:,Jﷻ}7044$-M]tww@p^d" To+i4s1_}O+{ bB-5WcN7ywLp㟩[ӿPrlJ8ܢ_rpIuuk@om7Y:Avvop)@ ГO>JdD[4.UH 8䥗^o?۷oؼk%33ӷmᮻ Im OM W;ƥ/_\VX!z422"wq\y啢QyX֯_/yG'?wT40W0 7{tz uJ!1'ߛWɼx;& 㟉[yӿP2slJ8mH:::Rm۶m3gJcj_]xr»l Cw}7 ]תp!!\4G&HKK}s_B)5xoy扞{#hg[[\-2k,˓#GÇE7O駟QDÜWD.0ql~J] `1Ǥb v @EIӪ°fyڷɩ䣏>*xIo,x6kyGu~UUU3@,& @\=馛Zҧ8{͛7 ںW 63@ 18Nzv)E%=.96m{/ '>hg",`ͦ >r5)/.V"ӎ\UGL plt} y kt]nF׀ ҥKE =rI'$OST}8;@`2ַ%=[sT^h [ΫcA <#ˠ-HI_f\s5OZ|?ں6ﭭ7#'/L S hF755v/Q^^n a*9G@ jvA/"??rc9&9׽TT.!I-Jk\C.벴XY)$Z$Rb%*KJ&\=ߙ3sΜ9{}8s9ϙ3g|?GK~si[f徇ؾ;ocxIӦM3Ke_p?ҥ^jN?t̝;\xᅩ~ '`c@@@@@@@*L`RmoǎW\ z)=dN<Xf͚}ڴ @@@@@@@@(Y@N>d3bӢE?A# y(vڦ~c       $P&'HyM׮]C۸8q2e7oEl喦uk1 4/~@@@@@@@@ hnƍ7miڴjri@@@@@@@@*2M<@@@@@@@(P`gv@@@@@@@@ߛ˗"       @y llڴ|wN:YW{<>3?3OݺuMVL׮] b@@@@@@@(S{-Zd&L`̙dY8L3^37p3N׶m[ӿS^1@@@@@@@*G ʰ0d3m4ȗ_~L2x~J5kٳLÆ 3@@@@@@@*O`6y͚5K/M f24,Y 4(R0˖-3z27nt       ,Ko\vefҥ4֭ wq=7nlLEVV[meϟoƏo-W6sA#       @ lJ3G,f͚c1ڵ3[6jWW_ެY33|pzGz6̌3h        T@ћPSwViӦ~z@@@@@@@@PfMsl/:~i͛v3,SϓO>^{v3@@@@@@@,4|qƙo3={;w{챞L=jbI@@@@@@@*B`TڵSmժO?4.ȴo>OG(W^ V #Rv~|%$Q (Xt„  [J{9ռys1c6߼-٫(w#kD@//ԃ~X]%)c+neO %Ajzk1N϶{o9c/Y$pY|4h~30Uic]hST>zhu]5,_y^s^A )yqƙ=z$Jփ@ B9V>\veygl(xc\y09`0_4|`[4d't2~V@(~ޡE\:B@@, ]ׯO~ݻ3}րz4(ZpJtkUtV#(&(AǕmvi'%HKYmK+ 6,Mv=~ P)JءCӬYJdΝknt-Q ߊk 7nt_~I6m8 L*ٳ70\pQ=3(#KA@!fMF0j*O?{FS}He{vmQt# d-AU*jtTPIv6lh9ӠA,LWfMsI'9)<҃@mDtc[nSNF7AEO<5kR馛R !B BIGFʘI?Wy;S;vl+0M_p;u>dvHv6HooE9|f{%ѝqut*d_膮`)]t}եK'nz̤I駟 /עE {tAFY T4*HWC)ۥr_UW]erwr @b hp?.:(7w@l4iyJsk%TmT#x>oVwadJrӎ-ML6Ӣ w UI`Ns9*},>K i:un=N;vt*:U Gnr-wWJucrS3fLZ0nFNR,ecokk}ܽޛ͝ng˒@@yp^3f0W_}Qnyg\=WU ׇUu@([unk֓XJuךN;-cGnKf(!~jr@`[)_ecP]&L`ҍ@PAMTʨpꩧѣG5g5}tJW@>g%쳏9rdMEԭ[yN,{|=э  @9 o I4"@@ @4DHL@v5beg \{dj3gK7+&X|DxmWdë@ƍ `{,[?k, ZK Q3v 0͛7O-S=y2ɷkiٝ_޴iQ;(fժUfݺuFvF)vuW6UTzj4k(Eʕ++Kޕa۔VS$5JI8;hv:uyV~s0#K.uR׫W9bl@]*~*;lvi'E4ϊ+/:/)L%cm-t93Ke^3/AE{Qe˖RJ9ZR1uۿ+/:ׯuj3]1aÔ Ei\s5ykkWP:M8~..W_5o׿W3￿9"W^ڶmGyY4E۪'%UWEJI+ok׮W=8.,-FUj:Լ ϣJlhKuү6mt4t!I\uZh}QfnU=c#+?glOksv0't9SҚLR?l~i'@|7guVNuV)r?~|;VCa {6J}3pi_?K:˞{iRoEtٿ~7H(#0~z Ǎ7ʝ9TA9At}5֡R)>%ۭf+=geoF1J-̉'h籔Zy@G\8w|t W^y,\0m]* '༧Ma@V(@@gh3(5jZHP>?VD=fطyG@ ig}e!x̚5̝;HݪRWXQw}7p.q+T>|&lZ]bI/U+y  8z)J$-+ d^|Eo96h> S6k(#;<ӽ{B饕M Jv)S8Q8xVGxUҨX~?(^ "1 O͚i^7ocNgjS1L5>ehb ʊ^Ν=Xk{'ݰȲv2f̘Q-@S:/Sbó  P@jMڽq^ iq])U?A0"}*! @׉l+A yC9S 믿̞=;{/R0q>q%x8OWE 4v*sUϲ`OvbKyi>zhg[t{\Xw^vW$`nUó?UQ{'&[E~U\tE&Se=ݭ,g믛 fQAϥ|FwRșJ)LS.9ϦfI)>BQ;~kCY.QMAoXbjݥ8uRYv ˆbOK~je)uI[;Ns]\ףڞ3g /00~n@leXO="[@CBژrcГMp˾ ># QcГmjgM}}W3Ҡ/GV煖]v%Ռґ+c[5jJWauqGU ?)կ4J1mTz[t3fplӞk?O'gA=|S6J֭뭷 sSF+S9SzݲeKgVEr O5ݠlQK^ڮ{d05=ej7EMO >(qƙ_F)UO>i/:g},j^ǜ2slQB~s Wwn%B+^5[UǼ 9r>]`>`QRk٫Y;y/űـ2+~:ГZ=57b \Q1nQ嫚a V{!Ǵljj-wV*5o~y Qe3`H>ehE߇:ɒ-VQ:}6,2 " <}Jq\Aw0mל%w>:nf ]nz)/v^p'x= V{!Ǵ* nFNztAN& 9}Ous.36DƙWXݙ>ܚ5k`ԣ !Cx \SGX= 3Վgz fp'Г:EFA~60eL._~ݛSnLE 5kFܿ#gֱs`O,C)SEyURNJ۝~ѓvQf%(HLzYowG1 6ؙڵk\ \sw{E ":.*# @zCd{wu54}[s=7ZH+/J?߁Oߖrطm@b,bT?j('k`kNEH(]T95EJIE3]>y$:IDAT(p;:+dNESO+#4N{;:@z^r%aCje1tOi<6UN8s(!}w}nIp ePJDAq;ҚiذD;M{6m,jBE7OSc?hm Tj7QH@AmR!S:FUI}ϙu2-/۸Blv+0v{CߕHw #y{fРATRu?\6}u*^#-7:+<:O+ԪU{27iB5&:|pl0=  P2gg'wctNM֨Q#tI\ ip=TX6om@b PLMUzTzg5O=EJW_}yɱ+mw(RQ*tcnR~-rTo?XJ4yvĹ*[7EaOө[N/6DA-Q*&pH)3U ({<)P妛nr*(2zDل3fx&ԓQE] hPъ+"UpEAۢB3=yT0RC6/ePi -KMW+ Kyk*hpӒ:.&DN@ ?IBۨ c1l^ewq4`㏑–YKy;cOS.Q~sY;moCX(wKu-SvQs ވZN=T)*wz]K%L? T(;fwĵ$zGdvþuw@)@@C15YVE RSNq^9sR2d*{NiҜ)`@OOWٖxQ2+h r;wgj8jzB/[d9v}')R:U9&nQxeП|C+c9&E5k4odɒH Q_D 4RtX%Lκ/nCT~'Zx 'GFY5têԥc:}Q'5Ҡ[+W4QWT K}2owʆ_}UjVƆԈ;使/+RKs1eZ@˖-sW֭sӵ**Ӈfb@(;=,uz)3iE)I\ i;J}=TUT ޷Ѝ @1h(&˪2;찃ܹ҇R {7'Lu/jWo4|/{nteKx뭷QQpW J(]A_&*.\w1JCm6=aS[ >g}f ߷nfBF(+ɼyRcUsJOޏQ؏ROgWj[ToQ?i"EA[W_}DnXy {5w5W1e|G]qfR)eJ9Mcrw4o̠yt̔{)w:/EjMRt-sx.i@@ >+(;٦MTjSݢeo~93;oBZW1wE}/uzm@( PdU^@mu':X?2Pe 7`}iy+{ѫ&ytyZ? Fm+?MP^ZoJR:2LOm?MO'r}Bݮxv)E/(/l9QB: Ƥ%݅4(A>}̐!C>7|4}oyZX Jsu\$€BwB<;H]۷bv烮j+]QycQw\Qy"U`P @@H\@nLe͚5fرfdA51h FqI] i}JO?/ &! P 2*p^J/޿`*{1 "t &Szai(/ma? QD,UpRv+҃AQajzs5#GL-RYjz" Dʩ\*j{Z?=.[w Q;h|~6۰{ ?vGo6Xaeo~եKC7,Q+Q?iJ}+ow>F hg}b/#۾x} $Ͽ尿`5~/Ԓ@@ 9e)ꪫÇV_~0VҶzm ݥܷvЍ @1rkgYT*DO۽u+냂&.BK/e fP% :Ԩ¹zOۓO O^+JdI]51˥+9F>iGeiyA%:-R q-KYu%QСy衇 ?eQ?иW\埶B(YߦV!7I<d˳JV\V5f|9+ϟ;6>r>; TgAA {4vz*+ڷa7@(T  :G =M?k׮u*Zm֜wyNЁ =s;>[oռi(TyЬY3.5|j` :Tn"0J)g$XcU;25DmzB]%cD竄6]Hw9|bhwџ- l6w^6l0oČ3̊+;g;3l0I|`>7}G)McS*?E.|t;Ìk{;nEY[~裏<ӵkcoSx\%ο~ljF¬2OUsC' Q/vP[n 80Jq- *PUطrF" P 1ke 詾?*$A jժUjyͪU ?qDOzݤIӫW/-lO#=zn[Hw=FF<ٮyrJ!S+F #FH-z{5={L O4=?_9 /r?QiӦy&U68ر,Y7Dիl s⯨r'h{ww71cnt{\o(GيS5ǣ[]4u,qDaj*Gf͚qUؒ]D @rЃM׽{w&iݢx sǻK}- JzTǪmځ@$@Ed1#)BKP`A:u ]2egpQU3O=֭ *U@Ihݨg_Q4M{%d0Vw}=Q*~;x3ӠAOFM6啒Tr?};ɓ'oֳN'DQsDv뮻ot.Awܭ@\o{G7۠7(KF y䑞] KǏ ѹGo ٸqQ]ԄLR_{o֭ +l]0+ dK/4m*/TFװRnBθ?-}F  P 1w y̚5+-u=>J=)=t iOܭ[7'ZڳO?hvZ)dSn{=9s?S_|ݝpp=~ןD=in71miAۦoFФ <OU쩄cTj^h„ )B UwG5~y<Q&뮻3ZOVE ?CO 8 ֋uAݥ0<N:W p#|NI'd R;2$%οA g:ivD0o's-E7 %p 'mz7TY]CIn af: @!4Ǽ)йsg'}('MPP]2=^)!j:ujڤ>Mr!ryN[)^q;xc='*徂k-[z&3fLn0vXO }*R,p{*C ]tQA#zm㏛I&E^?K35oE0?yjv./Tn8فQ|Ld\˘q=JYRt7x= xStݜuYffܸq橧JW۷ s{87_m([tݨk!C/3t  PSF χԵ3<f}-uPǪrٷ1M7  X,b9AOEi=|pi]{wvo{mIuCaeRsJd?(~mWܩ_11k׮u* *+nۤݧ~zZQ3wDUxғvџcUJ92׹g5: ;)N[{EEZ?u~O [*z7̺zUժ0X%pB3j˘~+ӥK[r'FU>+8.Vܲ;u},~&i;'do[D(8ۛ]A0GLӺuk^{%qO@첋6l%?\q_ ir=\3   آ,"8 ;zwu*lEX]vQelb.K. PzrL)le΍ 0.UQ[jK.j?^yUf 2=P)^q;z1?! (ۣ$]Gn$N5TJ9d־WPzinƴTƆB*0۴iZ2)l"蜬s]=P7՝oEjt(Ho߾FaE:'SO5=}ayw {tUW5dO˘{ꕶuyN?K0v9蠃0_~k |d&c*nMXnk.hOz@>Š4|ggpЃ Z@}Zh1/}-PRǪrٷ; /Ye,nnnذ!pRZlMkZCf+(8aÆ;Dnūn^|׿B7c9g6?=m?#ΓsUgzB5h4qSأv_z%rJg- T0`s3M41jZC۩~?En_tqE^B_yw®]:nyUoh֬S zW1G4*Cc?2e C>(˞^z[nq|u朣sEwn>hOF}WPYpaj-PnP"h$^zaڵkg6mWXaMfFan}7QjoxhQVerqJdwlFqsػɢ`]oNiԭ[>kR:X4_X=}RU<ݰM#< f3gNj':ĺnw}UtF=9ꨣLPS|q_ ir=\3   ,~ovnUf)Lpvr(TYXQ_Urͼ?:s/V{{$r+j4'YO>Ĺ.yNn~.ɻS{ƪ+B/7*Jr,S2%5NMOL:(|.e뭷vvW@lz;ҨQ#jժaO-4mꆏΑU|b(2(- Sz霥i*EYTrZF䪀 8U5@5~aۨ UU!no_WH l2$)@/x;Ncsr$'&ؠLmV iٲ=ӝıTοq~7<;'K\ ޝTAaT9]۪@AAMO})  + <迣4MBZ~\%q'(}㌂ @16/X&}ԯ[a _bO<Բԡ5o)i_yn)Red%y`[6=cDǪDSٞ.I뭤c?Nw:vIQ>rHwި'|si];qٝF4MoE5NKzѸqc*֮]̠@}?>`a=VdPQ?CNA#h1+ESM|RqN;41k.xx=QNy,Y̠2hae8 TOec7ѣG}-PǪrٷ7@S<ᘭ("\i!JQv=.rQn+~z/^Y*i@)҂2s'V nf(@CV&E(S[;[w8eW^ye:wzvرNvwxJ!SUy*e ѾTs饗:O;UfcX檼ֹOOhSjq)sQVb_ǷҠfTTOΝ;goE0P\UF5Ԯ]ehy P`n}UM1ۘ+whؠ ('n_{fҤINU]hժUj lQe4hPjݑıTοq7[PÆ s{igr;cD0pz<a  P}YJaaҶPǪrٷc~@|.BWv(]^zVEms4 .|gFS~ +5Ǡj\L-{=ɬ6蕝BTVH$8 1,y$`j"FHT.^c>qSM"輬cU/5T2eɧ[: Gcfr mGo"(یR!XhmBhѢŦM˜Xشis^Oz=놦^Ax)4=qi4aqKUw#l_2g'uͨ'@l˳<@W k!mS\%q'(}| H@@(=N 68O2e"    @J   PI f1cӌE%m7ۊ    hT        U!       hD         Ij.@@@@@@@$@@C$&&B@@@@@@@$hHRu!       @$"11       $)@@Cڬ @@@@@@@" @@@@@@@@ If]        IHLL       I А6B@@@@@@@H4Dbb"@@@@@@@HR$Y       D !!       @4$ͺ@@@@@@@@  @@@@@@@ !Imօ       hD         Ij.@@@@@@@$@@C$&&B@@@@@@@$hHRu!       @$"11       $)@@Cڬ @@@@@@@" @@@@@@@@ If]        IHLL       I ӛQEIENDB`performance/man/figures/pp_check.png0000644000176200001440000005274514257537777017321 0ustar liggesusersPNG  IHDRAsRGBgAMA a pHYsodUzIDATx^`՝V]$nـmt! =$K%\rRR/B %qܫ,mwl߼"l㪶3of%}{,˕0 =1i$m1$=ttttH[ F#;`0 & Q0qg0";`!L a`0Ew(B3 Fĝ`0& Q0qg0";`!L a`0ΑØ`0qg0qP8H0}0qg0g<3٤R*fc Qi( d ^H$O4"L&LR)i(|2l45 D&yNPh:gq>`~<~#n6rQ,bqFT*r:L&tn3 ̰,hT‘Aٿ- }nڴu[ۤ sP9?g>O|6p:@OrFS)FƂPoo߽{OË-[z=|LT=_YO;Vk_5L/۹swȗfJvɶ8YE镌9/˗S.6p p--<41 X,i$v!$vh5S6=UVUȷhw HtSԗʤrW%;L iHTz R8i(R)z N Q$4y=zWE9t_R)iӺziqp{ҋ8ce/?x58A >2V` )H !hP3$YD"̢}s\:nw8/gLϚl6qL:}KE"iS*ΝjY(,T i(b;()\dVZ!F@WVC׭@OfL?nk .pIEǰX,c'qJͲgBxN|4aѶ5jb88w:۶mc fk둟|$5I/*d6wvuľ4߇ kG : 4Bݭkj!"N+rQbCC~S# KUUUf.:AE"QG¡qS =3AHk!&@Ѝ㽽ftd5jfÍO:xk8t& a#Lς`0aKW\0.vJRbP$9s\[#y}G@m DAP&Hs"o8*;aq  q|xTs)吏|z>B(|JB|T!-Rd,2C;A3i2 5Yؗ=ӳ`ʊx"x?sܹh4Kī;~0[4 86p,f39;ں:ԇ=0;D2#݄[Q@!c";;WL&ӲŠ4UݦR)j5/RD<ӻm;?r$/Z8naْ\ Bq+`ϡPsikm#6$P*cCd3di0޵sK/gQkn&vlYk|2^)b0zCG{'7^0q?9?_@_r䦛oJ;K)7d`0tuu\b0 3X03JGG>קnK͛ i\Zat Y6ПP(pPR10q? xr׭̙iHE؅^SN82Sx$gD}3Z!k&yg>O3W^u<;4]R`0Y2.WY޸S}wӍhgn LO={׭[wWg}5kt|$EKE"BJHg2FcF#|9%,:;;Vle+NBI()-MF J jRAao@ EG:DL܏G?.sOͦ|I%lQ+v!|;|RBB*RP8CI#- Ƅ/ϙ;;ĵZ :䐶7h;SQMf3B}3gx6߄Ⱦ֛R0xHbEYeaB?c\4yp@cb|g;(U*ZX̴ 0M~v ^YY2qcwS;JA ]vEB p(zߨUjLV]]$ff!pTb Ƅ"ֱ "`:Rr pBϛʊh$<?A1v0qAEy<dvCQIs;|n4J3< c8? p=bbL&N%`LmG555TJdt;= /;l+޹+ca.޳{7pHE@F %+t*d4ǤVmv[ ,=10q#@pJ}X+Jk~$B|STT}Zp=nw<.T*OZH:3 5"дRVCϤ=j^^tPcabzd]""i3_ d=ɑaGK%#C N aؑ|Ndb N.sIq6c" CPum ݅#g]VB%ah HQY'1'gLR|ZqěG{.22011C\:KK."rN (tēdGJRl뱄}O6@2tgۡrDb1:]+݃)APVtx;BL%S&Ġ ,dr}Vh<ѐbw`0ƐfP;!;[U5cϑqqKΝc)D&б[ES`v1 ێTa&%$S(wԔx<-?f0q'‘M'rZ\AnCEh{4Jۣ& FA!$fN8qN'wtQ8G*jupju2b\@^1F&8'{<̈m2whS&\.1GӮbAb]"c|Sj榧U ?0UN$Rh y&-a4L9NSL&󲋃8AVIO N^hDov͉+(J "^V8 ?r-f3FMgJM&!@ͪyx2ɌbCs¸s@՚F݆4OɥRQ{I4ŗh0a^#H3YdJJNdgfٵ!Fh5NJw\ؐ{"cIH8BI?HҋQ12`2j5jn<'vч{ E{YK\quIrΨ55~4%.'N;d<|!# iJb$EFGq}` `^ a̟+틈Ks'?m:|?+G;BEE9̿CrR@CND "Fg }B:q9v͊P"8cTa^?T(g|oVhqJ@ 4uó:p*S]] ]v$TJ%OopR*HcAZpQ?gl6XwD{rXN%&C;;3l&=l;yzOJUu*L___y)!`(-IrAcd]] 6 [g///h4vUW(1=}×!FYD8ZqVm2áh|+K[kr1'Lx^WE9z=OTډ<Hdw>rME82SFEhYj=o*% Íl2Au~Uj3d2y f-n@-PHg_ȡѨkjj pp0XuU&wuu2iuϞWР|2<"~QBߐ J":6F"3n.GЈ*c쀫@ӱK$3k,wPGI/f`2]s,Gi>4AHcQcRv]u=OLNUPj4y*T[*:A'+ś ~ivs0ƊX,F]e.BMS$$33JLjqz|HDb/2 L9@3rpWWTt w$J40~y2d3bX<w:γTWUH qsOӜ J2FI-746l6(GQ1CٵgޙPWWV{Ɂ``H܁e Njk8χRzMH(1ŽZ `S)(o. 'ҪT4dȑd}``?a`iǾR}GJȲEDo@&63Y|m.+pIT< U1LjqGX&΄$6t/v{}QH?l.KF.Q>h4e:F S&I1E&ƉӻL#ϤNaW#m2dT*Yyxkщݏtmwg0Fd^jr~t)MӦ¸b1,D8ȰF+O6]!4+v͈-FCYRѸg>i䱪:`8P;4dsgd)6IxR;u0H4H3yŽj>u4H$3Zt& MwG2cƌxS?jǫDaIĝ1@^ɄnW*q^l2N1='5y83l3F+ҺZl#¢X6GD L&;ƦÇ!hD2dBa0F{oo/ j+cqG3g "u%M|y#G/T @T2H:aJ:>tE*ygN6E3 cIg2]]FN's}=ئ A@E3Ia-///++n2`Ͱåvhhl;qb#ʍFBNpOXw1c4H$!Jez=1f9Z@1RLRqO$*35ij2 jxHRUYi6::O:٩^˻'-<ϳpgH$5 tZ-N/ъƧx62I= %9(4YawGN;gh$* CTi=Y3] \kh5:Ύw 'R_F=ni_油*㜙>J&MMNA *t_qIګ=nw6h BkXI H`KNF3JRP .^GRvqzwldyېrN 3d3wάʪGyrt96*">H2:8Ng:Q;e&WhdI+dw&=TUWb,~D rtMR7ik8'%HW^e0F >=RWNcqh4K/^6үN D"I޾~lYP j}T?|Ѣp׭9p45ΠpL0F}!ZcZ R`\Z}|x1&g;f͚%!±2bGӭ6۾={#'WY5]c Z 7?mp$3M&xjh4u@)0]8O;8&w@D#`^tc&C]U+#B YI0 a"}Qxnp`@%cSG{iSsKf/Ѫ(IgHwfΟI'l RN;8PW_qNt3AB?j!?b\p:s|mGP h9&>ݖf@&(;AOǸQb'|MZyyd2I͙H>?L&漇P.bZ>XkL"`}fΟI'=pr|*?Y,Cs˗]t͵nڰaӦ7"%YI?0Zqq${Ѝr*78J^"[::Yx<:`kg#M3}M!Rdz zۭ־7=|I *m(H.!ົtzbV(a҉^{ݵHdu\щb082scr;ıLV!ɣT8f<; @MS~ӟڵ-TT Xh.qq8GhFc}}}.WNU  = W]>k춶ݻvL&9wE㙾K#1cfOBw</}70,t!3D{ޕbM7 ˩4G'B =_]U]sǎ?'bѠг?[&wu3L6S"]BTi4jpάYo-/yw;S\eyK [ț8[!=? iЏP|Jp8\{ tT*O$I2WTƙ1pUPObӶ0vG%w~ۢEs==}(Q>4@|G*S{pPTlVDs6Ϛ=q{2f:g];wZ6݆maJMZ-'CƍSN+ȣU1?dMW`9Hzӑ\?A#5yovF,& g~6L"q8BsS'BLy̜5{ú t&H@@lw'M3H72 Vqx|Dt:iKAjN6h[[OO/\Ґxq3ΌI$]MMZQT(e)殏}q?̳c\qW[Kh q×8n1 LL.3*yI3wgp$Gšΐ)Cc{ww7£Dtw͸ΚtRf͚ظ5}dyIJI3YLs!LF"nE>uM ztAшRgdw㺻{MNaͦ @):~@ {>GL2C$@gjqfD"` XUSmZ ;DUu==[Dsbuy8΀"}}SM> ^XmƦS׾J6ŭHӊNCgxME8 ܔ)8vPVVZWWL&8C5ΜI![߁.VVUЇ1:n>JolFPJJxX A780JK fA745x^PD2l2Y= BܓI_:4ONo5x2~aMǪ3Topp`48vtbc2zR({vc(DcwJqR& z<*nN5 N͢ŋ2ف* NR¼f,Y L@j-PR^?00L&i*ɅC$(~qWXiRWYԩS8H0* ڎx&¼ٔgB( hUU8]a骫 p$%SaS5'X;'2NB;nGgbL.q 嗮\qQϏ]N"X)*8-$N8nhSS[3A8C˴9CZL&G1֭(~qǽS!WerĘ rϽ@ l}i2JqliHg 0a NxIAo8|"d2$l‘3Do߯jIZ5>-e~|v4_1%q28@_dJ RYUUqKoyCߜ"w\@(]r`2 ̶h5 \2y-;)#ӂ:2N$K@ l^7A=&9 EˡZ,'̑Jy\ܑ .a2R @=o<;L(ӣ.!0'ˑ8P8 0bvuvf͇ Ag!xqbGѶ#Zft9X0gټıŒFBN(MB"d8x"N;T*մMRiaYkkj`R\rOt{pg#!|---ee.DH ͺ<2H^ERԶ`# GAښIgzz{Gu5AzUWDtZ@SMFcO ]փQk GdwwwyE9GLRx⎿S57IWPhun*D'`q@UUebvj[QQNƬJbwTD2 PLrH܃nlBdn[|+/c]DcUi-8 N`xSԌU~S~mٚJfDE!JI)Nqm{KORoX&LxK.F֮]4R"}!-D 5x|>Y3˒ 3}jFbw$}W_WwNј`#0KQOK/l-$ɒŦϜn,dNd={.=kfee9ڻ%MMwy{ww_̧'{pPTASVv[$C trJWa / T~Ax,>00t: misawb޳Y2tN5MOa=L6;<@}"{tR z}T*Lf޼yG/MGa41thqHw]/@Vzk !6dnWg7nCōJ*+uVWUƦ{ΠVˮXUQYg6y{\u\h,*^GuNUGTZ>$']__B\h{mQ$I:sVCϛ;OPrW^٭as"]l޼ )q#Yq4M޹kV ,+ɤ3cknbnX(JE]8hhl;Jӑe.TVU(])qx>Jrb&i%>YV #cSM^)a#t:!Ι580RK,.ܙFcXeμ Ypaww;?+b ^!U>qL%hݵG͚=kɀhPk4l{MOf%xBH{{]|9Auf36kdAׯ}@ (-,V ^cq@ aܜcjkkdBPTbr;-IrԪ#֗.[ӣv+ltTVTVVVH&%Nt:c>yFQ/\gdqg-)A8? ׷o9sM_ǁ5LHñq̼X_x%bSG#QsѲI9aV|DBN{dJcVݹcW,gHzѓ*P8BnE..u6pɆZr8l S!xn ̫޹cw(.p~m\~EKF]rA,M QYUpk4u*+> Uq0wlVmڰ~p&seO8x8oze lՁԋ@iSVtlrc0v^ R.[N -h+TqyI| Y̫d&qhK+ߓj>|% \J||b%6_$E3 bԩ0h0\ejuMuUUuèB0=(Hq0Sٜtj5*rÆ񒋗O!yZv:e9ͅ 8ѻ>ѱ{>\F ER"yqt1UЇ͋~Ѷv|bD(g OPp$!NKZ-!ߑe˖Μ5C9l(^< {ZUYQn[Q ǎ;P+!MFA]L{"DBZjUrGۇ_7.}&eNݱupĽ9s֡C-`e:hު ,ds0A֛x⩌8@Az=d|[i278S5G҄HrTTnܴeŊ,=|>N=?;Խlk~tQDȝܻ{Y})@}۬ ̟6mzWWА"J !_ՃwtZH`7͘( t(r?s-|3,Al6r?lnn޾colL'2 AΦ7o.u~mBUeV Dߑ'(WܡC>޳T*;;"?}u%Sc6V\F.:uxS~S~<3 x({,捛xkjm?7J,Z}+k(' ( *PL:>3Rf#oO̝;kb1}waQ}4=?{0R,Ot&O$PATj;ؿɒK]8S:OFç>nHk_zCgdID }<;Ң,b(81 6Yӣ>a219NNWŋׯ[ܷaæ@0H%Ƅ"Bqe|@_O[v8 8WP/n}cTjk|/mmC>_wO_ '$HxC$ ێmή}ϥ'0BQ^V^Zw/$?/"'0&xBP=^緼EPreeȠ-OܻpB{ݳ]O?-D D84d22 j:Jm۶W\q]wT*񥌳$>\6'ƇJ>kRQr]~N{7n+6r@_[<ē($K${޽ukk x5 ԦqJcT$I{vj2\$ZhžO>?Ңqyh Vh5rWVvrůK6|u8>"c$tZdmG [ZkkU,>]}+xQڙHp\InM`g/\/|b$9ACn޺t&ݼxm\^*3|bIɡ!_ J .W5ӌFc??_ʗb G<\5Vɇ 'rb̧O~!Cc,gL&Q؈Ec^[֨ozڲRg}mܵyw}t[{3{"32Cz! \$L E^t K3y͛6_w[nI&m JV 5Ic[&S6ϼ /Yv;h 1c6dʨ`(4;>ܼ=jFNcSh߶m0 O B  iO#DuRN1k_[/\r׿U1Dsy{#zIRu_{K.뮏TxOϐ ,)>@0WֶYu{xѷM V0~ %DrM[C+.tIN0Z"h81/ ^oY zpKH$azE͋xfI:iR)!Ic[o5Jb֜ٷ~E-*8NeNr+*ammW]}wj`}?EcޡDpNsy;SU '+""^#(YT ߡPP] *hZAqhu]LGH4 GRnd-ǵfs-AD/[jΜYȴêD %m/8F[ܡ}HҨrѮR AFJEq_ +.j Gxw;..>od%vxTK"=Ν;#0Mmm6:l6Zč#/$@))!q! p(ZmtZZ*rZo,=8p^y7xa~c^4%9!MH:=|ޞ܃-VZ,&n9WyyeeE kx*6aqqEoC7 Nj7fjH[ܧTL<_1"?kK.%a _t+\` }^7ِ6b6QD٬d14w:x0Dz-}i!M h$tBENNVe yRAT`g ^&gw8+XI,dLMe< 9pOOK&\E vaJl^GWTwaWVcwz BQil4[x0:Pp}|hl@_ET¡-n`IsiƸk;7q26y|wqlTHJ`2ZtqM-u]{<#ȩH ߡ]t%Λmg-m[ZAXmں 敻XOp9HTqN"dQ9ÇٹoKdzO|ndǟPHEB;**mv8Τ3bl/1e56 TT D>$֏r?a&VQ_? ΧiCY@CN\l%75~2RNq v cCb,^\bSA)q㶷xG&F5IWX;%]IsS(ZVR*;_6I&y_ q{ r ˖/s,@( F*10`0Ew(B3 Fĝ`0& QHeV_wWKDr'8xS^d2Il1a6#s2 FeKoI;'`0qiXP>x Bht:[ 91^\Uؐ}߾b C---H/n^TVVHu]V $|_h5ӧMvΞfO9;bI;ߜ%O<ԝwގ2l9d ~Zp_xEiضݣGۥ"H^d/K[俥"kӦץ"W H;Eď~:wiam QH2Q(`k`l.֙;`0 ,`0Ew(B3 Fĝ`0?Pb]]reZcl6{{p+*ʋiy\Ӟ>ZKV<А_PTWU-#&٩I&D*+-uGSD"==RYU<<}q000|]]m\/v{P!Yvig)K'#77Jrt9tW-P6עJ ؘ>cZqoGܹ}Ǯ/Zz)F8TϏ<ĺuuuE_{C]]xUXxae}p-[\ԣOsC۱cw̙u;E0n;1wޜ~_//y˖Q(.pie.Y<[/} _>ұ1a>%,-hT:Vؾj}/|+ؾ}G> 6AixW̝ɺw8GZH>ӈ7TtG|1h%* 﫴ұg}~3?JP)ұ1wM6sEpT 𳋗4k4jZ4;.i s̗ P(-_wLJo1st8#14SX<-/oƩS,نu5/8wٻgߕW]Qy(&_x???=9^#{ЭjGjYy*hV_wQ|k^xqJe1MG{:N'>h _GyLNfFare%R\`؋k^ͯ~;{׭.F^.W1<ɓ3go}w?D:6& o+&iT*$>_=oB:V?V]~YSSTT@ƿ|{N$k֜f1ӈϛX,nbx/:wnZLwW;|o=|d[[~c T.W\pfNl2IQ/.hHCF e}**ʥi?ڱq&Ԃwm8H  T+W@gΚ%N[&tΛ?7tͅ⚗PW.WYѴ` YgΛ? n_svM:\d{VTUVV2mTyRm Cl}{ЊB˺6|ڢΘ9}R :=}B{Z,uuX7@.\ >v+*8J L&ZRQI~bʸ_}em2t E7J?vwBӻJ>oL&Lfce+n"Pр_Znl{w;>wg)N?_wp\_M!>w|73,͋@,𦐵I;Xue$j555Ǜ==P˯|x<𹰁MS.xYq\Ԃ?2b400q{!\qPlqVVUUJ>6/`!o q"L a`0Ew(B3 Fĝ`0&cK&|?|k9{>`OH\e0NF._`?g _K3o},o;f c*dں7zv!2MQdbы?^oSg҂8%\w~٣^*`Lǐs/Z$]/3m~籁vn~mOl1#6p:z*Mz?b #oE9cAn{t`ˁse%%|x:ϿC~ߛzY[z nliFQvRxw~o}o;JT ;} SؑM\&v~}_F4rUpo1`P@}eS_sus5ZC;LJno/ɒKgƝmIbp,Jf'L8E&S'\)d] ӈ}쐩N.H׭ ?}Ջsʒ\&˕SޤejMf`%vWi$:}{Zcdsw|s)d[>s]ti`ءP-n!Noz_lӪZ_|⨟ ͵2` "[:HT\'ɻ+y YF8whٵv&K#w,[I*gcP,) f2 Vo?{>BY s3Ǔ}g>+`FJ%ibTr!z`iAz<`ȱDVdWFoV0Zv^7:і_ELŊL/}ь0NWyy^Rc,sscrD(M4iR0qg3h zR*Y[fAEbo%yz{ZE%޸|u* !B!$i_i{T7qKSw 19fΛEXfyf1j/gnAkPJB!B`;V? I3QR#FAGѓ|fs_h8+t2oRﯼosJ)B!BHTy{UYOJ kQ3cy{nnSثyZC;"uLolo?9rJ)B!BHb6|t(o`od'9{/p`]Zl;rz5^Хg:bNs^*ywz(!B!al]?kQ *F{=oEi#k9$VQ>iu_Bʥބ},ob( cݺu'O?!Bv3vlݱE'y򝗝QPDoomtnW<5xD' 13Wf_*لU}6Rlr뭷zA2&2dH^Et!JriY7k ޻؉GdA()B\kT {~ TRoBiֽJ&"s=K9Can/\Q(/e+ǷqBH׏1:wp2@Hְyw~Y_k,oy7fJ]/nK+ZTt׺'Á> TfzcXY6KRuщ lɁeѡM9r$,c %u[o]nG_#$O $ٶn늡sf7~|'رcy-1 S8SR j3"ui:$O&IDRXZ<:,sH2lذ45 jxகI$/l)UIE[jaoQ)Yy@||]}hR^ZjK]} yUS7|V"م2%0:u:,N,D RW! (۬YyqvC>U0Ղ:叜 ?BdKXBwVDE`\@HVuX2X0 46HRՉrlIa,E `F?RH'ұAaq_SKe2nIVl^2dcf{-MMq5{.}0-gMu%z}6V-Ro̽G/M6V>R$pQF1trĭ8UrpÍAҥ,rA]:wĹ;~$" O%E?*$' ²B`!'@ :jfRqJt ΢34y.$8|[oIDPٚ1@IjA6LP3"{:Fi 4Ɓ0TcDHXK(PʈG;T'BnfJ]JRdISJx Canbk 7doҒۿ>&c?eX & *'*l Py] p#2|$)=ڹd8U(] F1i :Dk [[AG5,'ƃ d[ x@H:@_ *WNAc"H"/Ac)t$w1:A2\jY-8?5.+|V]..jKN{WpYW0`'2 o+S\[ )PRB pۤoM'?4XwykT)EC¥$TCPp|W-Zc:rBNpRV׸I\}iJ2 }D _p ˍlgu(Ǘ ΫΨc8@8Ab>S-+Q@It.T2c(5l0qCU4Z{Rc)r{v0|xl9M іZ@㊨: >ߨh O@e2nIU0ܱloL1o5Eifs-UJfs5/g?]荁>t;*aq|lю:R$ȸj;"`|׿I)77VSN.i=׀v[ IGJw%uhb%@ֳp4{B6)}QڷBYFDmi6׾8!Ḷ{]`˪w@#u@9D,irжUNrp!+9.t<(kZ J R _X=}YM` %A =/y[BauÝmK,~-*kSثm{[{eDIzcgyZ|nj]SRdqUr'p&n w;{ +B|C Q޷Jqsa$B}tݪXזj÷ƀkȢ갊H\[-JS>-lU5l^Ɠ+OUSm:8 QDGyT !{.TQH w, t"\)ڡI^5 '!e'Z|\yo"-݊- 6.h^cJ kQEޘz^*ɍעVű ӻ|p~qgu*ƺ55ͥZKJ)]d\JpgB!7l ʪkY1ݥA-uߊBR*n4$K½߹sgǪv2t`$ΨgAUH\kF862}kFa=W_.FXVa2)o[rȷPVu JACaq>h(d Dwj'qϕNܧcR!c4}`];wm$W ?u E2\jw}u3{̛䷣h?W5ߵIEi& ^+k|o ntYqל_k0U(Hv }{hupEpBAuwoA7<׸ 0ʳj[QHYJ\RN'wB>rh=7 v=5,%W[6+]$5рv'sV߹.rɆ-R6}dݺu+<ݦLŷz{M#6+{͇qG8 ]P4E=WdYD aR֥Z;>6&n-٠H)rwyseYÏb+xc,YU}‹ˍ{6׵M.n:[ s5[`Q}Q KXc5 qm.QdkLߒ7 5 3Bol7Β btNoK뢚/ܵ.dASu TE%WNRd+.0tCD)`{r7JhXGUU&2 5S,~l#6΄ -17,kz=4J7~64eCr \)OR Z^:5qa[ dvRt7Za*\BAʌ>XI¯Nji&M"⵫"W-)ay#_ae+gt7qZE0{0{{DTYy\ T?uNcJ xoɯ_Qod23")\[!  ̺K,ӧzT;Juߊ*,[L`MeѾYBi X6: ,k>ʚ=j-rIp"5,4@X`( oqh]zKp2p;)ArUws?+ EQc[!(tXɺ(j2ly--ojФk;lJ-{7O]5tk6&5/t^˞K-7Ǭz7ۛXtĄU,ؾaPJ]Kbsj2]`zZRʵŷlV7cZBQ) T,.T H5/\PWm|Ɩ[QA~tZ2urtnL\qմ,4@u Cj۾ DiKAl!]6NLA "Z Z!|u}Xꦉ+"WВ8!*D2ʥ}AjA"2\k;w}Ғ>Mw^Fyc:٫yifsY.5+sBMt^Y OTrW\(pBd9$b}+!nƪ@J7r5vÁAD8VkVJ+!MB,"ܞeNּ/d}@9m J4%E/Z^|^M|晋ۛ9QTVLceHp5oR ;-0p)+_ z(UJ`Ev~տ/yMwm>gҵ(xAׁ]tGQӽwq]f4vsբ" F̠u`ȶn >Pº+Wk]pnH)MnƪFJ^Ȱ }BNPQtE,իz GD )14˅lȺ RVLo2cV/Ȱ\q' *|ROv1iݽ⮅+ b E-PѓGz~C1(ֳgZ໼2 2~K?w?lL/UI)@]Z+vk1[=W䍁|JqjQJl&A6ȶ%Te+aKJX!wVG{41#fʤqSH1Yް "+Ae/{Y|-`.@CZDRdxEѾt|4 đ)=(tI#>~ E5a Q :`F 7~aÆ(}\wh"ߒf] 'hN7Ã_?v_lʕ7Mgti23D\q+ T Mso'E)E!Ot=}@F[p:āʬAoHj"Bf aJ-ɓM^.c'OA Ѥhx A(TЛ*1]{NXhDfEj_dxm0d˄NBKSh?j' BЊ b-0꒸%ȼu.eУJs*' ݰFRjIBm#z3DW iݒTd$[ReKq?J)Sjwχz"J /)/޲tɖeϬ|E~nn*Z^6/}߲ԔZR$'} 5L1G*` " :,p edrmֿ0q` & #U,J^R@Va(`/DA-YV] E)`ˢPPAe9U/j?Z{`lˠGSTŽ#"*߀&Kn+T R%UH)U~'[WY~e&3:_^[cw7~u[kƨ*+㚗uksmR*e(\Q#I,!\JꂷŒR4ަWe/k=g]?v: }u\^v{?(^ńsξv? {}* .b0!P#/{bˎؽ`sL[_a5<[_[^;۾CWBm">_q\th8;vxu8#N 1؂!*0Ky5' 7/ٺsز\74ndi7Dپs??#YG/^m6e7/ X⿏:0{㼾%WI'(|\x1ħ.hl 2*ܴ}2fv}ZN)EH0|pkp֭t5 2+{*ڞ[ȗHnA)T-Ri-~厝;F97_Q'W_8/K%[A)u-dߌˌMi><ں߬agkw/ԯgC-oev W|q5f`jV=:yݧ;w휷y>jCKRsl(A7l4ksnxTkmT_8;wUٍMcipȯыK.nGd?(& ƚQf:hj?w̃XпpC)g|WTy3oV֍R B9k u@.[SG{Q$研~xKz|=R~i%Mm~_靺]Ͷosv wlbhz'HHf]}<5tƴv-_R?o ,~<`6aLͽ9ƭ~̩yz@MY?PA ==[*iy$P/ uD~5'w”f8)"ۼ%B8Jںs๷ W`jJ@ h,UK mNK_rO1o߰iǖ~٨BJ)Br2Ǘ_~9L P'>x#Fp%zBPE85`3%j춠WY oIU+`_n۷=Je~lZG=y-^7|q 8*;mjVDm)xB%uչ !OYjhM/X7ּ\|;ACOE੦}xf4dJ]44Ɯ6 yC\)uδJ!/TF9(+6o ԓ+_RsJpJJM66+uΝ H'ϪʗXT;޳86ɷT!i%|~v~ӧzakH:il7s7/=֪Po]|y$Exgm3y'>>jZ?JRJB!H{H)uδϯzApvjgu_||+[JcӐ.R_ĥso@2IRN] ()n,m:RXS&).+Y 8۩8u]|ٸcJ=;ݺwRJu)pMעBJvm/EĚra"Fem^x⿜5!B!N*8;6c#[ j5sԶ~ߟM u++]~d๷Ksu|:YW 9+gRRw/~Rj񞒅~; 6MúmJ9boJʊE Vw]h<Ycp !B BTsVv m^?/y[_‹k߳Ɍ Քы_qxW*#R BV~zMj TPwܱn۷ѥԙzByu;*ӦAe.I)E!BH"??{vpgLm/oUKHڴ}h9P&HARRR /,?JA55]O΅ܵs<3+M{eLy՜ΘC1^KgvЬ)V$JϒR$)^X[7RJm'JXz}>keO;w\}#!elۗVaI] s1\bx\̹y?B1_߻_Ŵw7,*ٿvmɡh!!B!9@*PDa--z@@n-vM:F9 6+ V|>%~]v#WR%%*a P<{ k'_+Դ"z1s+Խq)85NzE((Ýv>cI\>&3:#+_iIEBJahPG(Ɍ s>~wg\Jjy4Ϳ%B!$ RJs3+_y}{XKQAMg?_]kF=j ҧ䊘Ҙ+ov˂?u-BHλ=B& ,şΎ}#˞B(*/ܴE])B!Br)Uq6F3.8wz:[芣'-P쵟PȆ/0zfO#THϛ~J)7^,B%d>9l)K}4ryg9?iJ4?mjbi/prefN~SU]x@x GJCd;B!K)FSu-w/ݯǿ{?w-9$D:*YpP_4XP}r~O9J)B!Br_)ue圔8iBOOxKi_kp5s*wǺҝmCHCbEgϯ|k}^5]*G)E!BHnJF/ylo搔9wz'|^=֌V`63{%Pŷ"Lbmo2'CfA~Txy[Ͽ¢QZM;7-B!d=X2_,Щ.,t۵X,Ύ];W9uH ?}̮]K,iӦMV6mz饗~{C!{D:aܛn`U|7Goz#~ߵq]ٿ9o[?T5: N(!B \)eQ30RU~4Ό /.晕|k/Ky}{(r-c#|ђ+vگ_?|ٲeg]oVti 5sN/)Xv뮻I&sΥ\߾!Yo>&t: PJB!JEzkumf̛wjKhѢcǎ?~*X΅|]ؾo//9#M~p zR!"T_}o0c7o^VkUVi]VXQp:RB!,!L碋 x3f}_q :w/u׮7s1<ٳgϟ;x~ի wRHϸ9}qAM0A-07z#aRB!d (Z+8[a׮~d۶xwWog/y;X:㎻n馽駟vݾ/!,5?bu>w}}Žn>݃FG0J)B!B]pZa_<˰k7|Ӳeˎ;xp@vƌvڸ}SYVkz}foSVV+yGuԊ+[ q-c;o"a޼yu3=>G!BHVRy~^ſvz]]6lЯ_c=2d>3rHk#˞.0-;~ܣo۶m?Î;>v8> V\l9ܵS裏7[_>wz'+N/|N"O?ݻ߂f6}yPJB!䨔 yv_nݺٮ];C};wh2?jWҷf]:R9EEESLټy]΃_=޸s>& 8!%/huq|I(="_%B!d;+ZwT0`$v 2do{m.SݮOyZ~حsmy/׺F;hckvw%_,ۈgʌtPPm 4zcg4ӱ+?߇vmͻCAԹ:Gy:GrRNcCڵksS/۲.[O)<`CZq `eF9訳h}p^G7ߡ+~?6Nxի#nUֳK/}kyMlb~:p-{}O8NMJ@&rgt;弟]rއ^}xcCmycQs)<"^CZnA)E!BHnPR8fIs>Sj7JBy-C81уOj߻}Yf:˓]v]:.x/OG=ٳoOm~8칿>/83[}F?ٶ/;o!:-t> )ibU_J)B!BrR* J׮$6i-+G_v~XYzG{vܡskזV?sfG p)ZURB! DJn-&viVG|1]aotIr!L|kE^yeD8Vk],5`?gys{q ӆ5vgsrgÎ=}!B!Aj=%-ޱ:GϞ<ʹa ˏmG~nhׁ{k {o:vmٲe~||^͘:y.o{ʿ'UY|b =Sz׫YJG1ا޾>1GYRB!_J8gA{ԃ/󃎊p⧇t:v]䰾}6nxɒ%U8k;?Sِ.?&O;Bz۠<~H~M1aGC 8:,מ7QJB!R]AŽN=qP:?,OIyZm{i#xm(Ivsk׷= ܸaIO:Z;u?{ Ͼ':.:̏ :!&k!ՠ0ç(!B |f =ojP9x)\ }cG{zݳl Pkԥe]sk׶m8?7n<帓sfT9"s_ʋcU<~Džǿu9Cc卿^AMIQJB!H>mf>oZ{ٻs~M9?d5]ެxm?w@kNӇJ-vܩ3kׂ !ڶm*|ux#N{YA6,l @f O/ݾOw|gi=!u\4ثNIPNSkc{A: FػU^)#j+QJB!n;)>ϝ͎  Q,岁lY?G)E!BHn+ڔnZ#ׂCZvFlti5|6K_cǏϫX]"^羔'73:?ϟ{s^J+h~r_gpmtּlousy]{k3td;3ўkuay15U1ÔRB!ARm~ 5<FTomvQnirjS>_6S-gxDӡ;[?oHķB]KΣnL8DrںRB!%PJaû}xc  oiR:-'wu^>-f0{wymi?G}j;sl{טvk|dPJB!IyNٵ jo?>y-kS>W5+x =W0 |ō:vzn;=i =ٜ;(!B BT>quc:.dV*_:T㔔.tMgH=?!¿zh9IV R_/ǻy7eK)E!BHn"Λݯg=muv} 쁘ǀ0PSJJ:ȧK+g_;uûSJB!R#RpPSeuگT?ÍlA>O9ғjY=sS{YG)E!B0 Tu\4ZC&7Ah?5jvK dk^yHL!B!$DRo-T*]~NK/:\jڧ޾{G=jڦ^=kpg?g|;J)B!BH(}T1W+JǾNR։7um:|glqE>n8J)B!BH":,pC͠bN }d@~^mUKR{o?ZO|BVwϛշ}QJB!B2L$)5qOi\[Et?뱖JTjpZݣ.:a:F'v1 !B!$$R}=Cv˛e[bl`P:Uq!B!$$Rgk*u4/ 2}V6D0!B!$$R'I >EYZL*IS](!B!UD)U{^U~H MM!gRJB!Bp)tPj597.oVߖv))pS;p B!BH.:hڇrrWwω &ZT)=lG)E!B0 Tif/s:p8ROw>Z *^{/un>8J)B!BHI >G֟J+*Z8MN8țNM:J)B!BHIĜ?xtKkO"w7}PS:g>7h`;-ڍ"B!dR zi^3i4yS%aT _aހv}Ln}!B!$XRRmaY}rϠ^=sn7_Dž!c.Sx6UF~{iv(HG喔j6SA)E!BHVcIzeII'iv3u_`Xo>SVUןQ: ki CRYYF <_RB!d5RJMޙǻ=/rVmn?_iu6G-9罜wԥȘ!!R{sL@ 8Dxwk-n.C]DW>CxW;uOw~?s|Tc/yykQpjQJB!%*~tӧa~ە0@Dn8~O鬣ϭ8u*s_lk[OYglfm*hޭ6^pqqnt spuK^nrcPtϱ]>8MѢۭ#fK3 RF~znffjӹZ_ycU.]WRB!,՛0ۛ$禔.Fbe_5ռ%Ti?y/yo:{pÙ|Ag=mW7|_Wg{w܋9O=4۳n^BU[?{o74W_-J)B!B- 7.hz:Kˊ1Sx1viUӒ+y%sTQoc=ek7٩bR(Zɋ\%={^ѝ'_K}bo[3Q ~;}PJB!]WΟZ+ޗf=t]]7~j& .&vK/.:oDtXgN`ŇwѯZv Η߻}Y}|;Q*]^Mum]{osKQPP҆}cDPJB!aǗ-ueޤ|{1Kz=W ashzJt->zX[ӢV=֡ӲAGt?fc kaAjd=£fk[`jq˺7^J K"zuU-ܱiPJB!Kl[òϞi7tn4><`\z~IڻnVwo?םA1 $Lu꽍zE=k5s)aހ^i){lW]ReI u?{m+SM/)ͺ~#C)E!BHqƺy=xcKq {c?XǛ#)wqEHM>g(jTZg%|NaDž8q][}ڽ{XbE-aJ-wNy3>\r])A)E!BH}U,({W񝡎ڕU{7?;.qEH RjCi=G!BTEUMw_fz -jfݱˇٶ]B)E!BH⍋)Y; w7SzO~!9 i6:^j2@nfZfc.뱖}wC>׶{Zuz-OV|soLo7uQ PJB!Rv9m?/&Ac@VW+N<|mnF )EK\Mb._lωQm z5ߵuAc^}-(k74(!Bܱ'(91UEx7\˺70s]d7fZ ob&~dW&RB!/n. մ9Sc9>߸-K{Xb\Y=/!d:|N)$>_[ti+J)B!Bv#6|h`LoL7$O{_邏^*/PUk] yY{o_W{ O8}.aUA)E!Bn7*mQ7c޻-cz7.Ԧrm z7׭eI/ycgxY,bk%O^;b.UB)E!BȎW=gg{f8FAeѓ?=n˺[j\ݛzɋ~ Q]ӽbuo_Mʡ"B!d囗^7+ѥwc=ޥvi9r_jUzy- ?gyf1jɕE/ܨPMPJB!gk\8{' U7_?vN̯$\5oZ;~wsdWo'V(!B!1־윏K3}^zI/\ -Kz4׵M`wZ>׽uޘ|Նg{g2ܹSg"B!hߺy?ۛ4gި~d^W[%Zh2Wx6Q((?{ 1n/:!B!mXteagyܷ1#mcazkQw:o7:w_?♛JeRB!ܼϊqERM@5MxA6Q_BLw2W|_*BG51unJ)B!B?;X'yf:^3W?r]ݛ6 Ttk^kT7fZT7 *:z.ܾ6:!B!$m_9u&3Hhg:>zkW4YеE T-ghK߷1ߑttpn7`Ko(a},RB!ͳ[0pLot7}>o=?_|uQ/t߈e޸BoS7LF/롔"B!DVi,oCpqG|]@A5"nUCr_D ]&nWsRB!$عm-.>fb7i@*ƼvSW|Z}}eXIޤ'}];wsJ^zi޼:nre*((;PJB!QزewS~}dl};LV 2}2d>jݶ/:blot=2n9q() 'gp\R 6;PJB!Q}.9euWDy yDT-7.M=GzQF-dtT53vXk} g:ZɉaA)E!DaĈ)_gS*#m؇rԩs<~ګj[?9>+ƕxJnt |R5Nb8JNH)D]8 !&}sW),albtCx6l ;L?T5;YE* 'Riš"Bлwo}H,u7T׋=YnàVaqիܑdqXfּ ^7C?D7ƘΆ¬UFcz#C*?HI!WÇG :,t!_(! Ȃ]lxbFe$WCR{[e}!85|NR6LAA3h $ ͪtlkΥV'A)U͘Z4l%}ڱc >"GhahرAeSNRBHq:C|}ǖ-[` z?!a1bDD&R@':=+}F@* Jdź>h:E&~ B%D)0a?1ORBH@8p'g۷ERPPn{(֭;vX}CQ&| לȸ cqkŷBLLA)U9R78Xal ۢ~AQx 1q7 gt E)E!T;Ç78pYBŊJ/ h/A \#Y[UdJĚñ^qlON^^V Vn(ԠAqsV!RXFuWo@8\G-ֈ% 0<`%>ƩtА{`ȏ{Rā ӚmT);Pg2N !t{3rHti#\^}XϸO ЯpJVj!Huzp\j6kD ?l)k qtXJ)B!ڱfp|Du@XR }R;8uqQ]N7Y 1%mʓRKmA2 Tub=@D\g"°q7:tt[G!ߣk4Rм3A&NJ)B!ڱlX ZʚQ ?Xc5hn=3`RBHbIeS6fCz*,a`c0\\c퍁cI i`X`eaHT*MJAˑ'% TauK|gqieІBRڰ^sVϗs|bI 9P0KETk.Vd9FX % RB^?JѾq\_"!Y`.CHRY6eV~gBȔ 㫣RIJI85[u@5AT?t]Z)BZ1ʏy7,Y(!jzaÆ: O"ט(dLiX* тv!uG4o HòȈ cCE#RyPJUOb&1.hv 5M(`rr RA3[kl!3ԔRBH526ɥM,&?-c rzpl $tpJc# Wh jСA/,oà- tF(k91!YgqLhb vl73V:be +)k ɪaë@)E!T#}֝ M%`d3_>e~@%o66(xRt pjРA^^qJ 7r1 )c+179 )k#!RX}*oXj-}dEq w \85f A:6 ǷIf,㻞]$t%NB@u)Uq3t ,H)E!T#SѲ2 pB0dc00wp};@:8(ef(@)UPJUVv皀],K1.H,(Ξp$N;F,Ao,RBFMڷ"*.k[׆仾" ( T~ԭ[Zk`ﮃ)0N)(JjY8:"?}:FP z#A  BH~䮽VPJB!Յ%~Vܾ` 2ud4 XCpR+zrEa@ehgӔR5Jj ]b?:Сr[΋sz 3`Y0`A C AJYEsOKB4$\u"Q@ :8- !R@6 sw+!0cp, $ֈH,"$5x`|K֦"!B!$ !B!$ !B!$ !B!$ !B!$ !B!$ !B!$ !B!$ !B!$ !B!$ !B!$ !B!$ !B!$ !B!$n!~رaML6l8GB֯YK ߄8k<W9.|=wt=1*訛vf~C5Ejk3 ߵouue q" u0uJ: :TSuѤY]jҥԳ+GrQ+^dJC^0mE[#cԿ]jB +Rts:LufM6n-:DQW΢oiեjgCT-TBv:o^M4W|s!|t7ܵT8P?Bw~^[߉M(ܰ/ !"PSwQJ}3G=hcy t@EM#)i*??xr aXj*aSR &yg *RcdN7xhϑM4gWо1qNI"TT'toTiGe3qcҍsUANE?qK!cU[/!:fCoE LWoo}" H1\i$Ryw*z c]UZuz`׻y0ߩ}+җo8f) 邤;թp_R瘯'#9Z»* -WB2Kᦥ0TGA "JLmA6oPc4R'B2ҁ}5HF%*>Zq]Ȭ$_:"j`w,زBĄ{m*/jM9„"1_J[UѬv:%"DIY OTt\ps\ 'zSυD^"Qfk%g+ИQ '\HR˕{]YvoH!{ t"hD]s|qݧ/yw˅HsTZR0V%R:9XȰDՎH<|i"$NHaFl ϫ7Gdd 3ܢ)fz1_@E9$bBD:*cpJQ.u.燄ON4AʎWC)S"\*ʅUd%H!d7 EտQJ/g,< D3]L )REPk\87q­R`b¦fr0. ~P:ظA EfcZNj T)`t0U}S֞tًr.Ԫ-HDj/kU&}ˑP2Qh &%Е@ dKgV|PzڗBrؾy z8ARʼOјė+SV zfhưĀrA/U[ҡXx˜HU a~#FY}/D1D9*USIHBe-m4i8vpu6RR"(h3[$!`n\F`+$cLL7)$Rqr^[M:dL=)|;3܆_)dϚx.KU&["C ͠2M{\}ˑ)'P]ER7/ @pE;Nj BJl!(0 ϒ:eDJ!6p'1cBaj8wu KQ@c@Xq Np9%< Ep:Yj*⹬ydKdHU󦘜-) 5P &Zt)& \@8AfKf՝!&iMVne1(?1)GGj!3ʈCP-ߺXABK%`{$["EjHkQ}HYJQڷIBJF#M% LM_lYn|h{9| '7,)\+񷞾+Xrbg̓^Qq卬^y"91dO>6 'r.v%RV{)9Ac Y\EV؊cqV  jn7L?{ Tr,/](XcҒsWYQZY'|3c3qu8-䓱Y^fIPd)|5%o`1d d ^1\F Il^ xz{ dSVYecګIBJ{Hb֕٪}01H)\Z^7Ah`B-eFe*d~YRKX3lR2ʔF;) qSdKRdfl4(Yd0*fdjPP'}gϞB}AiD !$0v +32&7u/{ϚWAL} rz ʹ _d#Cd,Feot)?̹-H P9dX74IȜCjߊ7\#:^LRLX^q`*毉PJ6&1\#а2W0RJ

Nڬf(íVYp&N{C8wjHbY?K洛l@ʵ,RRJ"N ^?@Sb ױgkVTqH9 ^˘ ɷ4d)e"H+ߘU>!RJI0"ڵk'#!c"'UVrr*oK= ;!QpɤH8i'["r%Q4٨6!#L-l ԚHGJ% #$q#Q`I]&X7zN'g]a"&|`Ac@9*Ċ]CVS ppL<ʘ Rɖ\{It(aS-piP]&RQ [cRFqrlH3{)0))ۏir5暙U*MZabV2-2"&R2KZ֕t01trd}8S3'2$-HBqee]!o >|ZBfVvT dMJBOP }M}+R^"fEļ0f*?h *N Ye$ʔ IH)z\3+OJ RRr6"Rr0U1(}hfL:YpeZш/K԰QR ~.i ^%^l>^0.SAU4U =ʖR)g/M;uAmBrUHdUbK)c1þ^9+5sfMr>2U H\H$oP&T\#|^1 5esIK=ʏR"Krj jJ.S`2RǪ+"'r`H)s|kRIBJK`IU(e̹/^ s_oIsa=b 89.od<(I8;3+2dB@&8K!_*nm%e~ʪH!{(`ߋ2QL!ُ(0!`)5R<)%YYH >cm'gd]y#װɷ܋k4+2dsaJADBL`$ .Q6֓&d h3v𓏴>_$d/ HAJnkIg5Lr~Iܕ7rzGfC*IdS&:Wt)*xZgf|(rS~TJ6{Q$hB!94ܓ$&ʓRr낄r RJnݒz*["Ɖ]rCR D 㵗U}8 LR uJVkZDR&򯊒$RyRJ_ Rꇊe iVԧI-T?u@EVnfY: IdKRM:y)T2I3;H!ՂL[SM"'M9{ R ș ߹/OhM7Ter_^W>A= 8czȹ@JDj/'@mI[K(Zʨt7{DMdUJ2>8wLTL Ҥ1җRr_2P,ERdR9TK_"*&|ܵL3CKPٔ?uGU86pHPWCUܼ^$OyR*)R/rB{9R&zpݘ.ad ބCHS80Oʙc*㌌!e)`V%|u$5)%T=@Պ*@oW9: \f93eWͶR,3YձsERɖHZ )׹LO%|#+S$4|]+I+N3ah*i;ޘǼ}yMLߤou&3\r& Uj6R5GY{gsƱdKdHrcLX{ʹ#"f֊³f".%Lj;ؚ"9*~R |`sH&ft)䁾5ΖlI)_g)"iW;IY))d@ +9e\P*pM*[R$r/U rRr9b(iȓ{W 7/RR ZŖ=aBڷiGRn$^ ۞rAkמqZ%Y"f/SR*E!YQ-Y2+En1e)V͛"7TWN錠#kåNfq"CeY=uU= 2.|K$Ir!']sڊ0 I,3:ʲ.j}[*C:*>N|^+2渉fLs w RA.r p^x/kC8M9Xq2t\DgLd(AGǑ>l QiAeB*Q%HrY6%bphA.${f]r+ !$ceRuBK!MLߩLi*ЙFgP @?5?!*tpEy@\ D!8_*cWR%rIޣSDRF6rdI{3f0R BnIg%&|eɂ<a*ЛſU/NjRSR$Gy7ME̹|'/5a` zɾZO(HrF|׾UHT)SF]YvzEE1poj)Ԉ\y[kC)Erz }E3UPJ_0Jvl;:Ȫvnl9R"!$"0GC"dJMe RbVUc*0X"$ٲ_Y( 62sVl-۸Rh#XR0Vm6AY*%ke^Yfy%$6缾I''!B!J)B!BIJ)B!BIJ)B!BIJ)B!BIJ)B!BIJ)B!BIJ)B!BIJ)B!BIJ)B!BIJ)B!BIJ)B!BIJ)B!BIJ)B!BIJ)B!BIJ)B!BIJ)B!BIJ)B!BIJ)B!zB!,sDͅd=t!BH  $l.$G!Bmt!`s!@=@!hE zB!,F.@H\Hc@B!d1pB"B2{:B!$ц@6#B!Y6\:  Bb"Dͅd=t!BH  $l.$G!Bmt!`s!@=@!hE zB!,F.@H\Hc@B!d1pB"B2{:B!$ц@6#B!Y6\:  Bb"Dͅd=t!BH  $l.$G!Bmt!`s!@=@!hE zB!,F.@H\Hc@B!d1pB"B2{:B!$ц@6#B!Y6\:  Bb"Dͅd=t!BH  $l.$G!Bmt!`s!@=@!hE zB!,F.@H\Hc@B!d1pB"B2{:B!$ц@6#B!Y6\:  Bb"Dͅd=t!BH  $l.$G!Bmt!`s!@=@!hE zB!,F.@H\Hc@B!d1pB"B2{:B!$ц@6#B!Y6\:  Bb"Dͅd=t!BH  $l.$G!Bmt!`s!@=@!hE zB!,F.@H\Hc@B!d1pB"B2{:BIĺ`!$"Dͅd=t!T ֯6й}7kF \|oԒˋo?89"Dͅd=t!T9QvA RJ+n0!)  $l.$G!jaºm9d7m5EI5E26\:  eNO M97EG"Y)RǮ6\:  *d]\o~eزԕ QM "$Y"Dͅd=t!T!ǮQ6ܲ!ڗdK+j|훈Ūm*6\:  $I~X_U# #Vl*X}+bTs[6~xl[vk/Y7r5Ldm B6C=dRM8#2cNs!5 ҬEYȏ1_F JCf/'Q)$lH! Jτ$ 2Eo{c.SYÏop"TĶGH8pB"B2{:h4\ʘr;O>DjH6{)׃BV~B)lCf/mH/U"CiBo2І@6#$"5ε('( [09}w|2٧|~(^ڦ*>:Eߕo:v9F7Bֹ`,NglMV %[X?(E $=QȈultJH!M7( P0mt!`s!@=@H(Sm|R*eJ[6NjTHx–/V۾n+1JT9XJ-l*X/s.3,*FCMpD40˱_BqEV %[)KH6{)=lC LȤIU|C d*hd@3) ڗTц@6#"_̀Q̾p!˜-2*]TF,2jP䌄*DzG0Fg$[ytRԲl=,RhH mHI%GVEnNC DFG.@H\Hc@\zܗF{oL恽1gxitD1ge45r2Ҿ#N{#mtjKaT[{10moJVe/zHNHRhH mHI"Spa:mϬ Q0yFjڋTц@6#SOCEy.5dۘit*`|9+V ʁ S4aʑ6z0eΝ7H!PR*^m!_ )%K : tڞ 8,"$U"Dͅd=t!">Z̉o'bӀSO+OJ!A0Fa> "Rr]V|tRԲB=H"JH6{HdRe R)tCréM1)^6\:  $i}Coh2/QTT\YÏԔ|_E.GQB,==` .^e/zDR5$lґR6˄Lh A:mO)DIBRF.@H\Hc@z>iJeVJIsܜK\Zpګ$AnqRZRID)L $^ )2CJPtTyW*=FB.@H\Hc@V8/"T^քC$V?Ȅs{τjrRra$,Z(RU~W?ߍ\)5T5w<öAnD&hP4e@nr*!5 !NJF-j|_NABR O!drK!ɔ^BT E$}ALwFdц@6#$|kICDV欌`D݀e[N }@9Ivlh;URE K ѥH!drK!ɔ^"@ 0g2&56BRF.@H\Hc@krr [Z$]iYoIV[{|c@a3)[dr=(R6$lRn{ ن$Sv{MvCrۓՎbjhͱɾE/pB"B2{:hU|0=}հ[6Hq{0葈D8V)`|-mSX,;q.}D 1"cf9i@IMPHA8\OutH ѳ~=${x^mOSXxCȧ-gِR*R -g%$q =qABц@6#2wX$@Fݥ}yfZ3|%$="Dͅd=t! %@*8НFsY/5w8!$e"Dͅd=t! %@*kkC=2MZHH hE zBr$!`DwK)E* )^?TD×h6\:  $"QS!ɴ^(RhE zBrJ)J)R@ЀH%  $l.$G!DD֜GJB.@H\Hc@B!d1pB"B2{:B!$ц@6#B!Y6\:  Bb"Dͅd=t!BH  $l.$G!Bmt!`s!@=@!hE zB!,F.@H\Hc@B!d1pB"B2{:B!$ц@6#B!Y6\:  Bb"Dͅd=t!BH  $l.$G#GJmxt'ц@6#dɓ'k 0rH d"Dͅd=t!BH  $l.$G!Bmt!`s!I3A= B!T(hE`B(H[6!`B!j"aÆ`B(H%28DL!RM`pIpJB!YBR6 H8R$z))B!d I0"PJPSRB*"0" ")HgA{>6mڤ!$;hpJ$RN‡:4%I]#o9-:CTCjd~)m۶=zċSF,M4 /Tޮ(6̥7kn֬Y:F]MrYgIb[5CLBSR$ R$u>2M ~)%bP ,vm*$5Yr@M:UF} 5k$a8%E@)E"Nۑd7Gٔ 4f4زe˱ F2_Jr-n +K1~*U+WB`䮜0WE3e}ʾtR4u)տ^xAᓖ`P…SR$"R$-BpJT%\fToФI ?~ef.{GEJEc|AU6F.~be%cUGTY*) YO}} f%$!SR$"R$]`GPF$!jb2#I wl U-jf6${ՠ;&d Z͔WJyݧfVʷ}t/$"ѡ"PSR1沙P2&0CԼ2Pc+33ݜ?剪uF%Tn2K85äVEjUb*;T4iPBv[|mNIPJ E?q҂$D!e]qސ S=0剪ssvċ[vP$eGuw0MB6iB> NI"z))R2?Pj 7̕R24rAfF.rlP>5hV3j$$X6 HRPJ̀|$D"e#Ȗq2%qVJZUPv1oHɲXh)jV4̓: 0>n)),R$3:"Ղ4) #|T +edes\8|:uR?T*r2M{ O1M"vm*R=(BB06 HPJRX? XKwYX-LuJEDET< E.va+|%4ye7 foZ!8%ERRd8!UK,c+x 4۾!뮻N]ve%%%)m_/j8{#\*5FCT•ڵkpUd4$) NI"B!"B!"B!"B!"B!"B!"B!"$+af-!BHB)EH~욂:cV}2B!T>&}V@)kE(MѾYnh\AS-7CMK( QS2!u0OӾYi[vY-7Cl) QuF WSʌ)kQ SSRR5RR a iG5E!ykоYlwKk<ҴӾBӑf tJ$DMIk)J)JEnIM륎B!Bac"íB,^x2!dLw~ TM"礔88H#Y &)J)JEJ/B'U -gǖR!;vСC[Bv;? R&!M;8!2.pլjsZ3vRJQJ(*UJYsrV:]!Zq j鳖۠=ITMRtdVP`հ8W2RR5 ٱYJYw/X;b-1* V:'J+s4S[kZ@)j|ieRJQ:!㑵S:N &lK)( Θh@L((%?G@0:%ܘơ*P!:yՂ\Jz:47In2--,Bn%i /RJ)*UޞpKM8uUQpHpŭs"Ie`Y88;}pT ˆ-!͘eCJa8A6#08XQ*ͷ-JYJȉHye=.5JJXƅH)\= MVΫԲ",l'RRCrǗvĊpݨN@j]JAրoV}eOyCs>:-,Bn:c묇}RJb .\q?)LG lK)w؈ !RJRo!aCsd8y)K)id$jAu()k2ʑ%DJI~b=V^$#@6}D* )n*㯂AJ)0G~PCy-O8iS aʗ)JAfߵo"dptn2!!Nvn+"pOf|-lߛp [m˒uFz `3d|kwjV V8J~T$eHYJɪ}05GJ-Xv?*䅽gXUh%FA ZueSF 2wz:lJ)tZE+"%~'5Xj٥ ϲ!2?TkC+ҿ^y.S Lh ;Հw"wu\bfM ν-Z_;Ue;HJYF4A2}X8UKT6TD+>bbQ^zRaHǮ<ҵB12o" )mT4r"ܖ}e[)K`fii_Eڷt-2lgș’RFprD0C!x¹ ԔYDx=#e!υ7.M ԌI N\UM<裞}˗/^"wU&$ 7; Ab-rҌƽu=TN(oKcY]+m[|P-)H ㉓5)ʒX,KE0dL ˌ 7_/IjRJ"37%6 mnQC: $RJYH3ۦP5cdےR`2pUYt]ȌM@3.J)k$jI1zúaVxJzY&x%u m @[X(j׮SOirfΜYn][nѾɐA)oj*$B^sαoΝ\裏֏I ~p@EjͣIxq-^kzn`;+?,};2$t@9n E϶+`Ksb}!Oar+e'LLT2f}e'R(".oҿ^Ԥ|$4<:&)84 k)eI]م| \(i9kƅtmI)l W'(ch)%;!jOyԹ|gҔȓR*e&&kP0C84k @+xdhjbFTqqQL8ʰrBHADRK䢔 />) 2g"ʵF"k>s( @ǝHDRm%bwUѢ}㤓mu,H,Һ0RDځFJ)K&Z,Zcf˛4EjRJ*sGԖuxQC4| d5emך<⬆N> ]PKi˺.]kB1ÐRp"b<4lZ%xma'  t@yCĩF)DN?{R+S2#-QX/oTHkZ2|jw[C·\$ҾYŢ8O'ۖ\RI%Rګua_)eG ( `q[֕e˛4EjRJA 7UzS.j:;ll:(ΚH'۲@ecuu4I_Jn[ yQ\SH"XR*e!RuIIVk! ma`ԋ+c 2k?*2d 8pߏ/Ha*{?pO$TRK(ؚfĆJ)CSX*d"ZBȗ,YB)UXzRґR uWM'!wd2"M)eUfHѬH@i^/s!gLL͖C)e-JaBqЕb];Ed14X|_7LT2|a^!߆n璵53lVjfDQ/L4-0-$ U-Rg0Fu"JR*c&'j"2}-:/-Zuf3/EP$xCwVU7Ȥn H)!)}dtm-r\+ǂ0 JFJYf[\cr e~ O? ҎJ?ꢆHtBqun0E:ٖ}@ikW}R/aHyȾr)Ok=X e!4_iXqۉ{%h +^ԣzc)J[Y* ?`;y'D U৒RF _ݜ?XJRH=sKB􃺸 SWjH:Qըj@~.t=_I25+;&Mt[6ȅpLR e4pAO0JV֕JsV*e~ s"+" AbZI'ۮ%mDdS })e Cq}-0'C b4,oE.qL3Țh +^w%{\]Yr)`nRiJ[bWRD}=s+޲3|r+}FGwkф-!H)i3$uRE:Z #tyKI+)emAe۠z&}IzY&!}S$Wj!RJEg1)%{ I'ۮHPnY/3,*FO_hBeٖqJ4,oEr̍E[Xʤ{On˕R24WPQF}=sY|oqRqrEMEnUifBRQqsW8t<;٥ dەRR\oBi43/ HcLX RLrҼ^I)>(MzI{9G RZ9}45/3ӑR3 Uŷm_)G&}#YWfl9&3/gͼօhւi9:J(y 2Q9WJ$6‰< \VRQ02fH01PWJPR*}Ukf> k8nWNvrݪP>TW~ZT#5`6BHaDR@dpH?M`!+)r{pPA HȢVp:$5)AF6]ԌAjBu[f=HGJ#(9\vECٖ}@ `SLi}$+ʌM2'd%Y*k 0hn9b~"H:9 VhP_8H@\.q6-,ؚ2N  U3Q&K.n:p>خ];zquEtDu)Z$*Jj~3N9n=0`FV{oGi_5pEw g]r$2F%[yHA{%),=2AqPo"e5meg;OEkG5a$! #N P| }s#YDv!+hU5R˶ot6AOȃLS&);: jFPJ!AaDc*DμaXԾI"k* R/FH؊~ZXRLh}/R,VF,:)WTQ)ndlWB$EUԽ 5T`'{~P+-Iy8(oA&l[w-_Vai#KRZ\P KU4!TFЇ R^8)Ra9:!j6 tƕ] Q i"%8ׅ""[ 4@&AYWʜz2֏]"iQȀŔ9 S^R"L?$.Ǡj R/>U8ÇW |)\uU*h| b_K.1AU);)!#X2hNIi" hifk* ~)[vDyhݛSj_AnAԲ"U(2ejgDJm5;:X8okC1aPʠ^\ߔzHYe 5MJ)mX5l>6yXظH ج 3R9ߦO!fEAhipG ^arFFP.abRu (OYo8P .4TՅq?C:7D(16+nJ's.0^n};"+9 ^L#AP!d7@wܛu%60(pǔpI RdmY# Rp@Fm7d:L PJ(@ +R e01aDQrw\Nj"$i Bu@MG[XwWm5vzBLm X } ]3| N4T`qِR\7rUgJC} .#R 1 jxɉǝ8wdqaEk(6, VQQWnC_!*<  #dH UlRze= |uE ݞi@BrJ)BE:,ʩ>ɫh =!$+RqwF1H~XY15c,J +<ɺ$6 *_օȾ&j0"nOVe~ ̘4_N(v/~ܥ2RH,5AzUNGªyh =!Q[Uvf$z QSs9(v/(G!Bh5maBvt'"ryXH5$hfPJ^PJe'PS&$YkQ@[X TT@ڱeԼRdQj"nOHE/;Y:$aY{Fͻ R@[X !$""nO! !$7!d7@w{Bn(!B!$i(!B!$i(!B!$irUJM4kݴiM!B!UHIm۶vmw^:g]ԩSoGYW.okO!ꄏ 1䘔Zti^^^: @ZKEr! :T{V*#F!p8$HȔH-UloٲcݻM!$)YuK%rk<%Bj |>&9GnH)5epnWu 㔌 ҥK:k.d>QF*2.,$x ^xfp1Y~mݦbhVS7| RV9:B! l&2k'|SF}=߯S#F?묳 *g84iR^^*F!Yd;0W0QXEE"a*!q08T]J"ϤBt:Duc|ςn:AoJ07 7sep'jP a)L &*pŠnnOTFID &:tPiL"9*@j[5`!T3a5`>&5R*;^ӭnGC7A?(8%j;VI3fNKkƓ$ylәs"dlQ?FFV?Hx1 q40f-V~Vj$nʨ6 յ1!ȉo`BR#G}] qet ro-n6#W#FKJ\;JQX$$@#GmРڰTZ4T")&VOmuj+o77(w-3GbU]{qZAY\Ud|%jZff[ 'ӘrZwd[৺ӟ~RI]?j8)deYA7WDwW !Y Z/3ʛoZ|O/ץE]vz#<T=-)%j A֯__,; ߚf|N?0tX$Ml( yA Q B*Rņ8%niލ‡Τ*B& olj0K_*_ CрўUK8eXPŒH,X'ŤnѦRGՆ5!Bz0n,*5YcWU:$(qjcF>XcKP WǺqKF[] q 3UR5&,+B}E) ʍJ0͞_G ! z(:ڹy:&M4]@=QV U৺f&J-1=H~Ɵ4&nTYXW%lGbfrT*7(wq|[ڊJjQ lCBl*I#-J/if?h\R4*lF)ep%u(LkJx?2 YN5$3&Y_ !Y?ڰ摒j-5JӌQ&<OdLRvy"%5L\(W_V5yR8ADDu7r+C_60]͌:d=ђj$X"[TF!n|'(a.( 1NWXsKH+>Cpw8֫,n2T7IGJPRRTESQE6CǷ.f w9g>  q"V# Œ|lV6!1ɪ9RIdT=a*TWuY . sosBV(%oDMGPn膺R*ar;#PA w}1wCLyUL_r(hKa]7$~[WAX>oy*|K)_L]a <a` ''fK2}TWșw8J5+]LF_Y^ڕT F/xڤ˴"ݛir00 RK;vk \FJ/Xk`>q9-A*5N:or0ZTjx1(.=H \FJ@eRPTF*J@e]M^R?~\[[> ӯlmmDGOKZ$/XAr~mmMsrRDg4/;ʧ׮]HqF8mu@V)/⧁ nrp?p9RL3g:O?L73qcyr9Xq9ծT*u* ^Gw1`d&9A3eiWu:E煿(dtŕL\Dlg:DW6|3ϧME蜹l)tQ?-J8 Bۮ!hy^ia@yfXDrGN d^^Q3c}4CYsx\NUsț>]Nyj0tUAW}Һ;wHӜP+,N!/pDGW "Kt4V]nhX֫8WI׫`DiAyd@K Ru#O;-# zT^DSE3T5׏>u*ՄZadNyZ "`{T]nDhAD)[Q5*ieBΪ -m4 \㩨 fVt Hj${霋)& 5pJܩxvyY,ȯr厜>keK1+8n4ߊh==ɹUq9rGIo:\įW^ETtM xZP*N#mL1V8JFf8(L!l|\ U]WvV-]%v+& zu<GL|]<Y>,ȯr厜^< Qf`F.O7No6Rۓ@`P42lEӏ ǏoG.^+Ϭ{f,yFdVrhpB{8#)3\Ly9ΟshSD,f\()GZMUkkkR~xN߶+^0_FFTq ̘͔HrΟM+d^PcHe/B\n _|sν|xdz?AvV-sM3s@kX0sNy)Xf4|*HZBb9`nH`Լ("3Q83Jy`T<}tii)~}¸.HCo.Cd))ɓ'[Ex1(R%Kf[qx1s(R)8vvv.{Lq9C*ӧ߿otoJ#T&IO;lwօ dE_nPåp~ec;`aaAWdwwPׯk!Ο?oc;7+ R)@_wrTG{kwTj{{իL~666lN>ݏw{ǏRÇO8cpBܸqWdM=џ ^Qe΁=~ٱYXXh x4G'[$Dq9荎RrBm]=j۠5O^ԓ{9{~3c /Fi}`t)Ҟk#54˪JM:IF6umT4R:8ѣGp$$o5XAC8&x1:&3~^rp{t&j0#˳gϤymnnci$^#4{=&;zICw6L+hׯmYlR! vc6hdS H6xqdsɻu.-occ̙3zƕi.^]qNs+3+my߿S>~؊7oD3|rfO6dA4/B2˗/mJn`ڵk+++K22}1Vx/Hi)vs\__"h]ֺy 4L3odYe$xJJTU6uWMe`an]$s J 3ݼy>Vαzlv%4ZBY슯f$ob-̋2UUR/3} ū2ӯuAʛϋk>?uWJwܑ7]UDǒYM_f2 G#S̬͢ylV"fEު̽ [u;t-K"MWpyM6; a+$9p9XOeΕ ݰUCIgFق՜7Kai0Um.jaU(_f~QuVRgW|ee%efUf*zU?sT^D3uUZkuuu0yDaXA {{{6rdϟ?/a>"m<\gӣ~>2٘2*ڰUHwM޲I)j]*%t D-,mpehˎ:Ug%"M$/Wʧ:Ƨ Ej*s/hV]/ei{Ӊirxe!\"G#wrl#ޥKxq5&.'Йpr9؋O -,yœkc*v6֧je2?UuV.zI^^ZƧ8NyCUKgI*?~۞:ueswQV܇$ݲ2`,eSD'JQf&\VyݹhV]/ei{ӉL۷'Tq!82lelٕf7șDt5;t_5Ur/4^LkyyYW~)@ JL$mRp*NF d~ꬸ)'4\nR5ͥ-LQ+&(!3;gh3\Ob[D_'k'Ywӏ\5VYr;!]V@<\Z7 Q6w %}ݻV"o3r]z/4^R\.6TqY.xkf*U JJn^=LLd>#3L&ӤǹL/Ȣoa&ɃZvBoy:^jӟ4L_fdV^ vC2hˋ@WHKzJ6rXDtTC֎PJefB[Xf-^zBt94#ǂ2.e&dF'i0Ȝ͛7kkkgΜDUbooO%V.9U vȜCך++ʕ+V(cL~5kB!.p9Xq9x&H?9)zhBl4jj+@Gq90Y70λt˕+W2?iyS6w hrHRmt/FoHcchkkeswQ޽-..Z=.D*L ϭQ6w ` o\.sSNY1^,cM@p9$R)@YScswiSR)@)f-M_!2+hIR)@)&[cM/eT PeC.]+hڣGlCW\2 u5޾z*Ss}6_neM8Vд-[oԽTǏkkkf׮];s挝K'N|W|X_IDŽNzFXfmoܸK3yǡwZYl4綀gZ0\zc`0h6zd5?''ɕV%z˳gd>1\N]$gHHB9Fi2{xLSW]/_%Tl`0pႏZ+T֭[itˏIqV0 &`.bq9XV_`OS)M* xj xf"d4g=]tLtgYîi%&>ieD޺Mfڪt j`Ҧz[c0i`p9vRpN6eiQ#dxiF1,:eIT\y- [Fgn*MbLYP4嗆2+isEOҢv],I?yr=jA\FТTJHkfE%Iâ0f#hJWC?qf|eFV^LJE1HdZd.N?[Г'OEKe8V0OKree@i\?D9r0z]wQqiēhY^9@ ke㩯L^\4@-S"{"#s?#9K.Y2+)zI΃\?WC?1KH8E?D{(KrTJE"}8LF+@i KT L70 q @ɑ{QdDz-ñ ٱe +Ip98oQW&3HZOKa.!MJ;2hQTcG>^2 *HEv O:㲳ae`p`lCKKKVTgCkF\"\F?1 G2ȋ"iK1yWG0Dt6,(i j)km Ξ=+772+ [#ʀ*d' ҉ҳpIe:?#sHqǫFNjS.6Rɍ4!12ICLDcy_pL̜Cf9 B%*_Um(7 &#]+rpq$L`CKS)x1 VVV ~͛7kkkёU!ӨHcJ#h .ZVFr."E/^H^,:Hp(J(9wQ-,,Xdb+b iAGV&Rf\o*%_˗׮]"9,/)MH._k~.j#4CeB%2^a߶?iͺiD|= RGtHROɰ8V0ׯ_ Rh39s98:p92שXˡ,//1\pURy4/9F#KhIe _|Axۓubq9YS/!et%]َq @{ O(Ͳ8V0OK>t^,"diˋ:͛r {[[cٳg h1.s9E* ?<^ tݔ߄.l1LCr0F"yWtӧ?Ѕ-Ʊ8޽2(T y) ]b+eއr0 Dx15ijLM–XĤC -.$R)@ ]ؒ+އ@q9JlllXn14+$ &&}ꪕT PdoB$ &"pC~%9V01 ,R"П?necKr`laCPիWy?LZ`LM–X$CBR?~\[[kd}'OO~rܹrƍm0MC1^Q0#Ч؛-̱IJe}.ѱTj04GI޲!ʊ$N_%ɲN8cY&Hi͟={5>9)d oB0 &)}:q͒>R*GlyD٨ӧO%$?~%lŋVHMyE-̱IbNp9ΤRQH3H1MC&57 [c19\zfvƍ%̋1)PYdAzJhdLjgΜ sxbt[G`2V8阰 ]n^UѢu$]c:&dyy&̖X]rŖ7tu+*ʼY@ (c?EQRFt= +ʌM#ҨD&gM4@UOBLv< &,}`02.7ub.suWJh$ܹ#ǏC(3(d,,"/6wUf |2 /+ݻw`VP&QŻM-ϱ ݵ M'urrp4K9E?*N$ƓHA2Y$EQƧF:+BŢ|߿vLB<PҩS4;;;V6a< &LN'4}\Yq9׺TJHԔaKdXɏ Q^X?I=(Իw"12Ҋ'̖X>}9T={k7\r0@SpURIINVz|ّQjz`nW{)+<[cw%[t~ m6%Uq9``ژJ۷oO"%/H$/5 iv$JDR,9qAA҅lLlW]Yi6\TGhRS /_;n*/o t>:NhПHBV#5ݻV6yH &ȡ%+JrpgM`yyYrb9׸=g mi ȼ̓(/<4S)li%峺v2F3ޓ'OllLS[spp`@ Hz܃tu* z{FIAMɬ}]+J B]7 :{CV6-` Z1۱ "${{{V<-` hiiɖ=ě'۱ "$IsBز+Sq-S`c@ ]m.W^!D;$)e;V0E߷e% v({Ǐkkk}yTKJ}"قC3y -۱)J_ ץP[o :\4O*R@od~QJ2 +"[cӵhR-dǶc@ ]j.~ɓ' @mC*FK(%lL_BNvl;VЙBZR@oRXtu)4nLkٱXPB7O>۷6 A*FK(%lL_B#ȣ̎m :\48qŋ6 mB*C{(%lL_BM\n9;+Jh{sS~*͚[T ̬(%L]uYݩCq9v(]ӧqVVVǏKiӳzXeJ~/hjXԵj[ z\{VТ"ӃÇb5p`Zumڳ5Mĝ;w$$677 D*CY}QJX +VmKg@ k.nu7G*@X%+VݯCq9tyV"_R)oB{~n -.XPBF2_R)/V fagg*1ץ˳6۷oT @$cЪ_Bq9s(a~AxNPuǎd h.T 註wA;ti+5cvu @ّXPuJ5 jKBZ:f3\fGc@ 4E*tѻwuvwwx֬BihkktƎ%\PE=#vHe+kc-2]cc@ 4E*tх r劕ɱܴ: -..Zر ":paaء+nc-ݻo=1XPuJ;\[cpy͛7 @1XPuJ~guuXA;lllXZM31XPuJdУGZD9g` h.T ϟ۱:;+ncqYݻw @wXPuJݒ>7 5flg.ر ":0ٍ +n cg5s?n:Ž^ h.T 75rӧrCm.eXPuJ[XYX+hwZNy#XPuJ]qpp`GimbsM:=Cױ "CwQ~LWcc@ 4E*tEcse3yu(悺HNݵCi~L߿oZώ[ h.T ׯ!:$UѱIVu(悺HNXZZCth}}ǪXAX=+nv:V@sA]R@=yĎO͇UѱVJ͛7 @AXPuJj`0VZ:VJVˡ%+nv:V@sA]R@˽{naaϡGYq+Y-+h% zVKɓ'V u(悺HذsH2+ɯٳgCVu(悺H vpou2v1ώX h.T h>{fu%ac@ 4E*YG߈`uu:nW h.T h{X8@رXPuJek-fuuA~h%;V+J.R)Ο?oӧݬ$NV!Ixfv:V@sA]R@;1tEV] MUذbcc@ 4E*SX+h .Xr'Ov:V@sA]R@ Iʔ/PVc Z/;;;V e(u(悺HCYXqY+ӧO[.\`eZƎR h.T hҎtAX`QXPuJmn=cfv 2@;!XPuJmwVo :"}"oEZQ h.T h];νXAGdV 5t(悺HVI__;V@XPuJyK7CtGoovp:V@sA]R@{_tJE~h;8+J.R)%$e͋tJeh;2+J.R)%zsKJ 8V5ܘZΎL h.T h[RV5tƆÍ)=t(悺H6HoI]+[ piiaS@{aXPuJ3yK… VAtmnL-aǤc@ 4E*\nI [ :S@1XPuJտ[RVñnZv@:V@sA]Rlp1%\P0C%%lM+,nLdGc@ 4E*Е+Ws~KJؚ8VYy7dM`ht(悺HYɎ:G++2[ lssVƹ;+J.R)`VΟ?oGwcwi[wY1Cѱ "fbkk9Vq>t\Ev:V@sA5r~ٳVvduu> 9~ܒJtDH[K/qX B5TMqӱfXAe~í/]:n E*kx?Ьw:uOǚcjkཋ@'ЍAHPY+:\r`Zq/Z9V &;+0Itc R)|<p[1 "3L4T (yEnиφي9VOi!@эASH0Wt4ncc0ousGgo-D7 ˜F^ZЬE;zVϱ~ɼ+01tcR)r]t0'{[= %oO` Ơ>R)rfH?{б|1T d^Z,9N:e_"5twdJ̴ZXXg)HPK|VGQf 1?` Ơ&R)]ZЬ'Oȁ;l=+z:7o޴bC7uJrI>%677mt^~`<ܦ0tcPp-h\ޥKlU+G٪:N"F7c#B #}ֱ^|ʕ+V `2`lRhӧ4 Ѿlm+9 эxHЌ-  ֏vc}w+R,ЍxHMY__N3WoǶuv`d^Rk+0tc0R)h>; s27[m @k%)@*-my{V۱N 4B*- .Xܰ5w`nd>ɗUH-\b]fԩS󈭼c$3>}4 VuyT`X<{sR@;J=yĺym+3y_yMR)E#;|6cݻ {MR)SNY9}~E*X\^E*3#ɒL5v^~m%̥WP,..D#&<+ɺ3^9Ϻ`H`$:uڲm 昤Lߩ@prX]]qw޵)m ‚mgοY --ʕ+6ܳ-X{m? S */Z]])@*U(ל7 '/N0<.mxLdJ.\qgϞ%ئqCyidS6`89l8V'/9 0`$S(A6cp R%~&Ltg3YUGmXl*IM0`R#+@LXeS6iL7_uE;yH+@v"`EUIDATp#_89af~k?6 }݅f9JN mtM|+@ljyyyooϦ}tQ~|sE^.9O٠azLZrom(W= 4dɓ%&kӡm/ PR]GiL6䗗y4Dg6 m"&H Ҥ)RH_F[/ m:OdU^< +L&CG+WX5!٭-Vs$_R|1،=$^.޿ZqmLlT,R$flCHz(6`e RuXYG<|yyٺSNfJl9V$Y:}mGlRL ToC،}u3"+fe(xrT,PegRe^ǰdzgO& lRt,aw2I Il8̵t[WWWٳʶc(pd$Rr}`l~ſyK ]>_|awK%=O+%yWxI4e~T^veۉV޽h,7oe}cXꔺ~:/RɦHFwcA㰻eD F>k'Rc"䇃Kw[\(f mVV>[[[O􉥥 cX*;{m,'oT E^r&WU_{+pZqr9KoƻцTJvw_]V՗'oaT;TF|}_沣Yk'ѝ%@ѣ$J\tuvtcymP<]<^*5ޢېJ9zp]iZkc+jTy}ңYs׍{U-?&#֎^Aj''6 #Lgt MdJ RI /.s(o\?B&E6iٿ^GML?kc'72t K%ae/ӼXk>,]Ӷ-.K!{S3Ź5oy4^f>iqMz}-$/:d2^*i%jQ\eFdˇUAjk- IԩSC˶cWQzP/X^lC|!E- q; }SY %Xkf*e%L-*m.cl"K+g2Ϟ,ɚN?=Ɏ\} ,TSyx5oyKC&~NB\Tْ(*<:da# dj''d|ȐAV,ZiQT%, %$`F> %a(^wj++[/#Ai(yt5Z], = aY Q괓1jTm#oidnz˖lWCBM8a Qޕ+W ^0͓u5vXXXtR'O Z2HȒ0+=H?Rt}J eyװd#t}W/Pp+qg:\*׼tڟ%e钰eDF^\"RWFw62YCuz&"+UН!o?:ZF*a&2D}S A#R2A'3?YMqقՎ_r沚7iA7W٪}cNt>sDj"@!:1Fi·Af*%$$鉶CD+HC LFK` }fu|dp)IܰC^la ;%=Q },) >s\qA"M/.O'[V^kC[I |6Nx5߼ETJikYRd32SF߱؊d#J {7% ߄?eV ISt|tX$' LGZ 2{ؒ7 dTHH.g.)MPj( FKZ$ )i߯Wǂ@ۧ Uk'joJ]&f)Y gT(-Ry2IeVh9:Ld(.W:vG> Hwmm\ АϟL _tissmB)QGx$xJP"}L;i! DQWO$X$B9g9 &u%GY>Mk?HUO;$g:kwg | >e}Hv"ƫy-t\e֖Ave4h 9>v,O|V6vtHSFh&y2vTJE#e\֣FҿQWB.'D+8Ie5(= ߚe}>#jut -8>3$Sr#>\1j^y+ y1Y)x_KEQS4%ZِTONͶ'r;d; ّDh}}}uuEg)_Sbر4JJϟCF>}SEPbT)^'$2H8&DleD4Fu|=Ӝ}RiqlaUgG<>eNx5ټT(ci^F<] |xH92dۨbc|'/!'0MSLMJgJ\;~ʐv|bv = n|ai'x5ӼK{Dgc 6v(J FjJocǕ?v X7l_,NX良0ᗘnzG]agJSmv Ţ^s3'w­Tt@uI0Fk6> _t?}N $—-dݭ`,~wP[wZel۾(c+{nccîKlFSC:KC|NJבQ_`/](#s^^ ygʜN5ٟYq=Ppֈ//Nj^y$K#Ef[/"}]쾏ZlUl M'q\6!kI7KU~nqwD֪T25YFJ# ;SUь:y( Rfc&oAJl(ZVRy@zuI0Fk6o%" RO9.}N=+{ FiaJNW~noٱ`0yݻw߆j =`^~-%e'gաT*Lxa :2l散?qK<6s(2A !e~GkUӽ i'x5ӼI9H?MH֐^z~nZܩmo L0F^vQ[Hwǿ`T6 &i(/{{+_>\*%6_OT_U > j*}%CNtY=ʔ^Rt3hWw$_tY L bԚkQͫN1j^y ?T*kN-]O7ut2 3' LJzU{āD2v2}$%cBV6 ' ljUsg䪢eTTvƫy-tr}hhgXgQ i2EsHVlE]S"SM2H:m2]rItַ6ҾW-vD@^#Sg"Tнoː^~JMllu#Hvƨy-U@ʢCT}B3' d1{W&я(l< =6lO6J_3zÇ> QD(gaJk>VAK Q7OB%TMT͵{֟{B{Sj^y WJs "CT}-FN ? ~}eT2:7utDwe?ZAumGxکsI&AODMYOה](;R>"xEFa}oP^kcnN5߼Eؘ:/Y*,=+fN xR/]$}4 EΕ$tOx6x4 ٟBˋ#}7TdMh9җJoȠ5:Y= hW,>&}Z=+ӽ #OvƫҼE}ٿM:#Ѿ D] ioN;d0؊%v*%rp]=Y %_ Cz!:c<)d{`qc-VxN5oyGOߡQ|Qf ͜@oeti'rZA>bXXe*5%hkxHz/(#dўT*oMZZ3rUt/CSj^y]oοDuFN =?9q|!m'^Tc}As4c3TJH,ص_.BK Mzyde<|Ch!Z:F$Yo:Z 7beDQw^ku_Ȍ*uf kBahLAn'^t~lO_O6b_SPBi4|'2D0nY3ɢ?__gg5Z g*Nƫy#[6ut0 { K*k댜 )ꠃ=lk'QG૝&kU[ґ$6vHFoJcO,hJVI"2^Rr<42+ˬ҃ؤG$l9[tI% ǀl_Zgeӣ!G絟1T/lg_i:_JT13e6`.dw˦gA Iҹ$?({m95Ul,O6x, ٟ2LKl"uunGYx2$Tْ''p^ά^J*td4hl ]$rJ k-gXJgv2^͛j޲%3 99mQvcc r$ƅʐy ' NJX$x@Nߟ NNmG*.⌼$f[7tOR)t^ɸ>v7NNmG*>FQ?wυ OR)tT~?W&' ƭ:#Rý_30TMIkoG~fc{SuǭIQH~8[Zeo/y&?"$Bw}})^ H{IO_u~'+h+CɊ.NND*l8A*9OϦ )NNH*upɠt["IioG&H%'Üɱ㪟JI}t@h42A*9`J@L ɱjhO :?9V@kprOcc''@XX :?9V@kprO<9moo_zÇ7S,r$@ǵ>l1K漹idy왜k׮9sF{ĉ_}֖M B/'zW'`0ߞ///߻w6ۓ@6Q+:> 0srҰ2/Rˋ/llBV:^*Jpu/_D[$F$i1K襝?\-W~ƍO>۷0;%S޾}{d0$Fh=$IcV/txx駟*F5!@+ڍ> 0W:rҘ5p 9eiAMVpI' ƠnڌĔɅ =ᛝrctmEC]:9 gVVVn^q R:t>hlʼh$DgNN]y{6ְCEch $:vrXp~4[<' mwBc@k'нSyG)z9'/hOMv3{WGa+ڄ> 0wr{5MogDۜ* Ru@I<#V }`u4_ <a1k:&?22<g@''^st?]BN?%ʫWlT͛7kkk\(({: yBh9NNL783o?JTwŗ/_&㷷]&E[nJ?&OY0O-ovF yfcc?G0,lkk&(X07 :ֹsh˟+589Z' h NNֱɱZu,rh˟+589Z' h NNֱɱZu,rh˟+589Z' h~^)?9Vt }vrg}V3f=|CΝڲ)={&wBbkΜ9'NꫯYK O^NN~$x߼yӓ'O^pFi;:Ļ{~{{{4~=~xXIyПӷ~+1%nܸ'}=>HN腨$A/]|:@oHlXI9ѓS1K̹~yi,Kɔo9̛+Z> 0?prҘyf<2Ö.+-PѢ3 ʳɱs''#͆ ["c|` ?9V}`tEN͆4yf{{{0Ȳiw=c@['PNN򙕕sW_$jjq$E_*^®c@;' :sr &Ǒ8 ˗mpp(.< +Z> ձ*qΝ'O2<7n a c? ֠Oc'' ?ƭ#m" LQ#l@#,;V};9@yijgV!Py 6O̹[}CNH > wzmBs<9M׸o#ueOX2Iy)K4Z +++^Q7oެq2iY0O-)a+Sǽk׮I EN$_x˗!mω'nݺ< `'ZSL,N-//k r͛?fqD糵e1+ }89Z:zcc''@XX :?9V@kprOcc''@XX :?9V@kprOcc''@XXϓիW?|`:' OXNN?~\[[jƬgϞə{}}NHdvڙ3g/N8W_mmm|G O^NN~>hi;O>=y{^~mcǽ= F?~lcY?v莳#?'oV"B#1KHؒ ^^*,:K @/_5Y7 #Vt}`Nl7nO޾}k)i,Kɔo,̡+Z> 0?prҘE:4D3̼&TRɱs''Y [z.|O-F7>9~rm6(l/\`sK' O̡.U3+++z[Hz&6 T^:ʞ99=j@yxnGpH/W01V}c'' UΝ;'OdBMœ [0eG+Z> 4 M&u$1a ̢c@k'нS4M޸q#y,'mBs;9/%lMUinWR0~g@'\'ON.,̧h$<''e`0XYYyꕍJyfmm-S0,r'I~D9_x˗!k׮Iщ'nݺs 4ģ-(GX0O- :֭sh˟+589Z' h NNֱɱZu,rh˟+589fluuupO G`߿o Si03B*å%KJ#afT 0{nLqK R+c[Rg*}>+yc[R$@-g}V3f}'Osܹ-߿vZL++P!IU*%c0ԏYB}DbӧOe˗mXFr5t8qbssS'1IyПTJcG#1K<{LٙqÇ^x~.\?7n|'o߾ߘ> 0'zJ5ĦE'}tQpc[R$C*1-7n :QBSܒB''JS)Y[?~/G^jɚ0'2oLqK G7N`9FŬ)3` G G+FJoLqK GC]JM5+++M4L":hݻ7Iݘچ> љTJԃ4|hoaN":hK)I?Ppc[Rh$T "ܹs2_hS^Padp &Q++NIt, r~F=}8\)7ctDc6O{&wZh<*&Ӕn2?O̹Rz[.H؊b^y*ऑnBW`>I>I9׽TJܾ}{_ Lӧ,}`u2(fS% P}Hb2/}|䱎5qI##y@I#H2R)P|e#f鋷ӯ}?,R*Ȕ7`$-=t)G y=7a)F*oe/7aJ)=F*W$K }v&*4}sE ?~򟟟6Zp_e鞒LK) 翵R)B*!?{κep_ʤF ;zT @Jum_Ek$t/l(]zO@J蕚GNJ#a(LP ۨQ{`raS-',erՓm%;0hLJסAHUoЅ*J;7e͒nCS[4S2h;M2Cf_S2m Qi~7OG$@-g}V3f}'OIܹs[[[6qϞ=+??˜ӧ'N\|9ÇZL60gj&*ÖєaMw )ВTJjҙW>W2m Yz^f+JWV/_ߚ lIEXMRA*c9ssX\Z];Z@^R~#5H@Q΍7$ּx''p?W^eAd^lҾtU}Y27Vi//CL)jҡ.cKR>W ˒^TIEȖ 3_$C,4`Zte0}'v6   clһ_R/H΅OA 5s> 0Jii$fgϞ]SɌѾKHRy~Z?C޾|0W|U66fmW?K:.s_GO5?,E;W)|o֐\-d8YȑL@~)HnVOFJ$Sw/ƐGW!`BI}r$? Kccwl^CR E!N 0?Jihx.34ynL䅭 H~iJP*E#dL(.7HW:ezR 篷Vӗq7U|Bc$+E2H:I l쐿%V/ROuT#Lvq#:XFdQv¿g"Sn"<[KUa&_m?$\|*18X!ﶵ^IcȒz4d><W'p LT]! ,NG}T?D(>W|J -$`a̾ dAjB}R1"R5$5IZ({Vp7& 6ݨ$ Q*ݰ3v;ì*N[[@7NH.p22r{{["oaZ DҐH'P5@b`XvvsV E U.-6E\%R2>LnG.JU^TJ>9ؤR{Ɨ3v;AOw#$R*oYYYhEƏ #{ҘKɼHUy r25~ JNO2}ppۼNjX*p }tnk[mJdT?e~jREwR~SHi6Pun?$?V" }̕ΤRr?x@RSz}-+L:>i5TiUÖ,sK'а= R)Qνwkc+~T\iT1})J= WzJɤWCG|*TO:<ìZ> }@u? Ν;&tУ! 8|\D\dpɿ`dTQ_ wR PGoSL'/.CJnlS)K~ TJM%"Sv.M4|WR\[> }cTtFp'3rAJD ["obCɐZے W#^. W=ަZ* Uم_Rs2>H[#bw῕4U~J/+Gغ> }{YL ј qǩPɰ .D| ?!w>ȣ΢9^uCwKNjX7K=Ý^zClMQ5WOwdՔ*IZp'j+%;WwTO@N/6v ?GI% 3AVA6N ˷s-,lޠOcսTJ(R4KV2OfI/AǻaK'zhBo;tFSdzH7Ԧ E2HN"#2.Tê|=oEycSh*%KҒt2;2=Fknpv.$ȊlLxBIt 0J۷oOڏH^kBQ̋&:__GE;w.Zʰ=kԧTa%#S)@yU74S)h~q NR)r|ɴ^*%$Z43csKb~ʯ{k0{> 0:JM4leny2U||ݩ왿 -2?AVO/Ved H~w׿NoְTJY/*)s,#u(3ܪ~\&}J lrVz>a/|}cDCw?ӭ9?21U2^)^./UΕ&S'%?> rR4iȌ8B/d1?~c>}?@IbS Hl$V@&hV>UŊowTRuSLtˤ'kpoNNT>zsm(> rRw=3o+)ʌ}aQFnllH`sE?^7g0L%6`+Opg^`> rR+RIBWdv?HuAUgI0!~]hZ =7[ﳖ$ϒJar|{VGHuHZ8s$}۷w*+++[[[VPH4*]It'AR)=/!Ԓ׳>|8ࠝ:7)g˗/6{=d6u떮ӧO#W>^6QyI9ѓT} N|#}\䔲]c{\RKJ@ߥin54ݕ^]B9 AR)YS>]-=W_ 95Ow˜ݻ77,mjߒ֭[6G9ZJ[x]D+O4f? KwϋLu߼y#3gd2TR $yG_x1K#%$MW*uԶ.x֖,[˜Xwn$qܹM$*o}字63"y4Au}`t; zl+,y\y_~{|Sy=! Jׯuf)2&6 |R*SFiaۨ姌ȢCݯBs=T$6oϲ!32_֮|$5][[}:^% FA4 YW_}%u.s z}JsKT8Mj ָ,17W]I.O=gv;9D=ʜ9s&&j&٩JL4E*&Jvyk{z+DZ/܌yJ,4/M!,ܭ;* }3H qJO%/i+nA-JZÑvO:U1y\1]D3T2sCl$L[;soU(SAZkQR)$TP%ܹ#W32 zgvŴ ݚ;Apߥ9vwZ$:JiD%zw?]s$Ž7GEο8@E}ВWE) +5[[O/zQMR#WRU*6E1#^#yVk'-FJ/a!ƴ&ΜŽ7߿ۋQ*1md_Xz IE5dMs]kRP/tȭW=Ϝn0RY7{#kw κˑG2Po|&Y0JŹGi ~5RtʏLl=.}-IOK۷-{E`ߡO{i/ꋧ[1#:rT]ORUwp(|2EMgc_mߕK,52/ϭYD.T&:gY59_lmmxhzCB&?2G2V#3xq>IO.){=׹ΥX^^.~ noo/A;wNz3R*?e#pkL4KT2C(NtђFkKlrtIX&PHWӭ10 R4)/{"n>m%R) @̼B*@>H,?$ Iy_*\ I*D/T(xaƼ[RT *#H2R)T *#H2R)T *#H2R)T *#H2R)T *#H2R)T *#H2R)T *#H2R)T *#H2R)T *#H2R)T *#H2R)T *#H2R)T *#H2R)T *#H2R)T *#H2R)T *#H2R)>ԿIENDB`performance/man/figures/unnamed-chunk-14-1.png0000644000176200001440000045436414644214241020637 0ustar liggesusersPNG  IHDRg# pHYs&? IDATxmlg?ccP> 0e4W!]9fؤ{ެHQ f4j ^bF#IN$xg[Yӣ=1N;ÎS~GH8/U_uuWU.?P~uW_׵ѣG ،e*Pe*Pe*Pe*Pe*Pe*Pe*Pe*Pe*Pe*Pe*$[~[F/roGʺ YsXU;ٷW͞]"fPUf6R2Bӯ3R/Vc=ztEej)0(v`ddd㔦̵pv#(F+e?ug5R[svO8=("#Wϟ:c_9+"r8 `@Ou?o7Ղs~~ADzώ?O2T.ws/됫[ ,8zo- ǃy ZOf;ynTbm(U2Se_=;00BgԨŝć1 z#-&pe\ly%jďPL9zk4(!L 5/"Q㡸uF„ wDX@{~gv'ny6Ktc=z`vNcCNzm%wk[]&?LK/ZI6s7w=" .9K:oًMo|Wޕ#'KLF\@O( Dfs5Pf4[ IWё:_5;k^V326Kt#cCp>ņ2n4ت9Bx?to"GG萗_!(\#qˣsGu,NMFԪQ"I(`WS&2!FR֬Λ{ڜO䅵P2j߮d/a 렔chdρ/ 7JqElpc }vl>lfRsG H#qD%DL̑Fm?QGKvH8#n>:_!gs.sE<%KGD} h^ɾEzώ\-*W>z6vfA}p6+"7)@gFrQ7S9G!z], <}.j fJ?a,*Q&o^qo<`ctt˗ϝ;y/\@: 뢔LhիWϟ:?w?8v>w4 N?e˖3﬛QF9e@Y:_z׫ +G*R;hX*eFmp/`3=)8pOpaa 2d2;ѣgmR _K05pl_v)yRe>RO4|D,˿pPA3o_;p 4?0r_%ZvfH̜LEIedX' e 2Dmt-Gy,πqe`]WܧL*sTf&<} ?'{ވef$jd$;29J޲S/2 2ݗ^8޷:js'}%.<:s` N{9 <&|b{,ΡdKۉ=+ah*s`p %x*Ȍr3s'd2U~ED ԆW?0ac/\χLuӡ91K;: ;tّDy 3֔kޞHm*l?9X4&yD5=s=9$Z9?ޮ粰4@r9W7W𯘅| =ƵuQ~hdWtG^.|z]6IOp/)C+'Q.v`KI❆#Ÿ-JodRe˖sQg-t ϝ[9+JXf{9Umm`bNmfl@ENv .6&Onw2N'[)rU+6r^r^uNq)g";e|f[IϚL*e/\8}зs?}`ivy;pnPj( ׎_p>/i07E8J}iUF?8&Ա=z?mFX`=;72rWdt@E|PD3<ꞒC8=("{krmtu}! mRS,aq/'$n'v-$zsIUc|X yjt~ WIY2z>svV~y76-?ļGmr >%rRRE?I*zjNN̫b# b? sr?$y{6@nFHّ~^G""JځEz{lwu}Y!gvVdɷ=MڣcQӌs2ȁ'=oŸbh3"6%?!=3_KIX¿f_/QVHq( {j}-ދ  V8mְ|kE7@ 9"bd䬻[~iNb{BD7$'' D]a?UF?ޅH>l'߳_̧<1bDo_Z|sM\qɿJ%x٫[k)'[_r>\Mp JmFINNDS" "k݂[.uRK+dd"':u.E/URŽ{Em|0{+4.iJ,u+3s&QYOs&jSIg_tș)3LpEz_+?x f2_/ =;00002=8Z{Yew@\83Mq/4ojrc~0pqey:Ju9(v7/H@![+5jQPRLF+Qٳ3_zPn֬gC֓^S.ľ&u5$~Ų4c {R?vWeƘM_ E""^r9 "UNlIX <64k@'%Q3rr~m==(gb-<W-~tN;vy_}ŭ{YeO"/O$Sy?l_Z?\trPcjg6sT]Z+5jQP&:?>wrl94|.tۑ\8ޗ]$-qAFӯe[bx\O]'h9y_!АKWVEFG>"V%xe?d;Ğҝؒ-x.Ϟ1E5 ѓ?9%~~!b&\emOFv9rt(e^Žȋ(T[kḀ\OGq,S t'RvQ+5j^Y٩ 1 ̧`WŹڝ8Ga3m7J&:A1I q_s3I 1$jR1Sb_%Ab'R3VBɕ]Gn0K1YfĿS8SLP?=?Nޔ2U'zNܐmCXREWqf&>wrL.")NgdI?MH=ٗTJ,dFWӐ:2p6{)z[9vjF2[)+\.l-u*g#'Y)mVyt|S/6P,x/ !\Ė䌕oE5 ?9ى ,V-syv`D?Yx"ZV%P!Ol8"/OS>lT/=Kmɟ."En'|LM»+5jѣGnC;pzlaWq*G B cT2@(P2@(P2@(P2@(P2}>99999YWݻw޽[VT/^*݊J/,&$|ZMZ³Y4B B B B B B mn699i^qeӟM~&?|3^&J R*z޽+/^eӿFtoQo *ے#ZfPT^Rig:*+qﯙbBU'""1qLD36.ƔP-Bg:'t9 $R]*eTc؝T؈eTRqC2h\%Zc#R"P1k\)͐Ø2BԨ136 B'k/o!} @$ /cSvL3vϷǭ79G2]T%BmLT-Lw[ˬq/Pnbw8+\C(`]/Q^.( ZMRIbrL~z="29|݋C+|,  D&lMt6JJ[h@5BΎBχ49sS^I }>< `}d>#nˆD(`6ɻ n@LR"~S*Lг9K:֕1^m۶Le$2 dz9}5TkCA ÐH~;J$7P\)J&D׽{nAp5c3am۶I-)dzI(`x9E0AC}ղ1i4 9q̉{{My1{4eWhLL꧃m7IR8/Tku_"Pu2cF)` 叼~ŏF(4 VBf$AξTkÒs &51)9g&5(SD&~Rœ(=ɇt̙3?>jPHj󜱀'Gn]2:Q)\4(y VHDKplglj~lj1fGɫi#rd ]|O^}DvK\C?P&ӽʻ:&/{LPTsQeKqq̯z*tM1WӋK2Լ݈eJXnsCCL`'zKg.Iofcj޽+ C(,I%Yxw&ܔsg:>[̝m skX6DzN.}ۡ(ڟ͎O>핡Tk9Uy KXzMw^}gɷw\ƶE'n1 .QJ2uZs⍞1 '՞?|z`# P2yWB{$)9-e$wȘƩ驘]GGB+эWBC i1("qw )3D}M IDAT|&Hf8F{6w5F1&z&ݬm0acf'(DPBw /1blz!tJw5ޣ7 V4q7[j ʛ&2f(%hOhLޝU2dk-C2_M/&)W\t5E"ʡ. 2 X%?o|=fy/j@bFvۖW'6f_P2_S<@x›Ȼ_sEhkYyt .YдJlT(RT"J|[ƛȦ@ N^JX,P!. $2 A[/vQ^;oL.G/FJ2B(`ά}Xb?G{FhRcC26Я&8XS<.E2"Pe2&|&*Xڈ;UX83MQek|mljA^J(F$2 %7 iGiL LomZxV*>=^Xa2dL2o7v;nh(/dǽu5 DмCboZI&2Q3t$;9:1i]Bk7hF7h3\K`[GVs7Ñ';5P@~IdFܛ]ԟ#\Ln!7 WЮLOe.Z{BwQt8R\.C Pe$/qdT`x#솎hv0HHU:]I‘5P,䵱. "O_ա&NMTil9C;6kg豬%)"Xa2DHt%h=,yqW Mm) 7(ȾvW]TZe(j̶J7Qrt7h2q)Hеt$wR]lůˑob? wzo[QmL96 wI#X&5&r/vi$))[)tM_M/Fvb & 2fY*e&?WR""y|O{u59GJit\|+$2)"enҚsljRN$dR-`C'{%{jš|$Z2 7 lL%Q쫃؝n[KOLgS*FV/>m=F6kNL2g#]ML~z="29|݋C+|ltvd2^}E>~DzP&e2AniLw[N}Ut5jp+5 $*jmjzZ޷.K\Fʖ˘-gp2D:_d+"s;ERCGiIJJЫo2sC"2Pn[& ؤvh"c&D,MmןS 5@h8^KƦYLL&WL&]9lNILbS$k aHgΜ9C 6Y4DKLԈ01GڏnfI CWٍ_x;5#B*Ad^6A%R{GH*%vɉTfO.}P""r*/wa7ѨnϤzLgSZTkV`zݴ5Μݞ{EĆD-T*UŨvTj^DnqMՋLM{STHe@z6K{V d{;PHD:;;;:;׶VfKg޽U35t}Q3:lz _{f(h"3=""=ټ^w#+wGT*l?ݙ]Ҷ3ٝݞ:FkȿMݹ%/6?}EC"&Av,E(:)zP(MR)S.+WR⫯< .^ICxUOO?6mZ 븴-SayuG==FC&uLdk455nWDzIDGjYDGAkc]GSl)"ˏ5H[kc[kfO\>/.Hgg6r^SըԿ[__Ʀ旳]^dg5-jwjφ)|#@ &%2)Riw4ܗr;Rzovhן{қh"69_?oDD'-tg\2?7L#0/?P5ttvRcSdрU9F|7IWcn{v7r[>ݢ?͈F:-vsh͸;'y3ٮKZ2dt_JMLJ軙azƬ}-FLmQ*zO0,&vg/ֲGm/nNp'fL'Tw[㵛Gezߊ`n)[VGCb0Pc6|LS^Vf+ 箚YI2v>DF0V!fWwjKRֳ\9yuDu.jg:t֬@4>6s}lh"hLхvb/l8$q[/Cjme,/9%:K;^zwaMd,qǔ 2΢)Tw?c-ޝ[ߜmowBh+.٠-L5 owTTMʈH{'z?xω3g[K9FO"@JR&EC#ڃdJ"rئLH/.<"t pw@OϯmkGq*n>·߆HIUIye2XP%P cbn&2V L=!`Q,íuc3ߤEd"gw^zIo_;7oq2Q<:cmHAz0H({-߳zoz5Ù;ָfYK6anc<lo_kGB9^< 8DZ N;ݜZ=tJ%n_! /4/Q__֎K6p:}lzkkM9l 3[kTx+vsҶ&Nu#Q'[]ώZwԊ=tMv7o=wیRH$jbICݻx_x=D?kj0YAϦüm[ 2*3f੬%lmx6kJl/ZЬ-]7J6 dcS~vgz~YD;uDFiK64ڝh~ǂ V.W"J/ȑg:wi+х.ڀ86پCwZ@9l}z 2b_齡R$;TڂG)8*:{}lF M/j1\BGխ *8|ޣɋ mLvʖlkݠ+ZO-vb.HVz5AQۧX@8#ꯨBZ&z(A(lny @ ;ɍWI[lcMEw2oț:Xfrcm7^FLg=f;RL{~gO<D.jil,5S&#t_6H4CwdM.̞ }1hJՁuǦDEuMLnN`<I{ў.7ќhOۘT-Ҵ%j)կ>@P*2@KXa8g$;[0h̝y_~tGvړ{n L ݜtvs݂H{GTwwnIkQw虏=]^sJU2L[rD%Xgt_jW<:㒖7q[IǦHc6%u-ɪQ6B7 A!Ӑ!e&Rw疬rkF? 6[,׿~K~ $Seں&y.K`PX+$jVizKCf5 @DC}TqdD_>WoLu_KFl {&$*z|czoscGK~m#C)eSp$*Y`T-PB`Lh"7,-L|ٝGgnmfԶOTm'9լmfu`CÔy76s*nn*(5@Dkw6X͋-3rS _M/2z88Tf'K`YLF-xx۠3S1NeZ "p-~uK:DFǎ[XyI_4mE")<^Klk^W)7h& n-S n26DLm%GǵE$a;<05 /=9bu@.} 11_CK6:}|A.ܼF=Ow4h/ #$ۙ(GKgtc36U΢}ovQ- t6u5jnM%ɘ5Q .ry鱕6F#%Uړ++~IT{% 2@(,?Ul,^Kd|+2MaVZl(xe2n8]l"'w'w$ Uڌk7'[, $­vztX}TfP鍷gb-?%˒B`BS T'"xD6Nvn33 k X69BF'2C4\G{>BDtp{m9]^Q^_$ 2^Kn&c}$8՞h! [#wrs͞t|ۖq'~h 7~ɼMaq&w3w/ ,/'7m74ȾvKdVѩC3키%2o>6s}lF~s6b3s`Ym{wgwt靯mypp y?7bNOzu{P)T uLp U&K/=Ⱦk7'-impwZ&;+Vvy3 tnT6ҭR_B%ۯ*tܖw[ODvsR~[8+Sԣ@!Ϭm Xi^3|}y;vj[$'Kn.T];7iȾH4jюN^፹k7ݜPPp!*ɘt;pwM/j@dr(n(&Mi*=^\@ejLFظ_ܽs`"inOE`W:L;Vt4{3is7>bF異l-3ݡjUf>ݹ Slu7vz]x{;ў{f4Rn}f=1]Ѩ+zc$[\u+rj!|2>X&hٽM}ܚL>63=|gz^Dw1>7tGӍ]}17 0DF7%bp4!H{3iZO4ITh:U,sǤw6MnCW$ߤ)ܪ C Ue2B A]Π99,g`D~6=ѤU373ӸDz،u5E˺8,%5^ :ѽn1>{5ZtW^TU,cTGS]:-pǂIx,P%j7P؊hxvo%Jփh^Ʌsc|Dz|nQDwtDy@-l9ݢCh9Ft,l`mDzIdѤhƄN k^~drWܹ$DO7QJH!#ڭbEY4*?c1؃H6(-rl $|+WuY6#L/ JzAWsVyiz~y ﲊVA㖥X#ل~t:-$ SBO& 6~ E]V΅VXD6Sn܏;_Z۠;Ց}%e[{m;uVlwS(-B`;~4sK;uvkBN/=~O(0/=;يvs҆Շk?ӥў=]nt]i'}Ԇz:90* A^zTz]MV܎ur{el݉Rkcy@~-I.Oс~/r!rwc\e*Ku-m{wm{hܠcĈHkce;wܸ7'"Of" Khz*_Ⱦv hԼf 6hOeʞ [Zt-o76r'iDcS=ٜJ/U*Fqh;NeX,XG W&&t_%vv'r`|lf̾l$1ߍ݇Bd> ^VtGK(t}lz~ŕ"rDZ!cDdk7'u&lwkNt6}<<5qKc.,ي ]I4:эSeۼBsK=nQ˵G5!mbk8L~M/eUy r'Kr IDAT燊_|9`sNes?'&ciTR o|=x+":DZioo߮v_r׺IbEnm%vfvhGo'n$ /.˟ݙY~vGj׭mq،X)Piٍ_z=Bs)oݓ[W|U < a?,U[:"ъc:R{S&2Ow45ܡ]w0F7Ⱥ,i/$݋V-bU0`ܤ!E0 K:,pl- f"G[6jal_Z?Vޢ1Sh&eTrti\{^3=iwLp|d\6MO%` vqrŨ/01.":f%"2^=L/5Xƺ-VJ3DGS#zC`c͟m=Ca+d}v,8F)tCHlLM:oωG_j-{_qm$;twz~YWhm9']%$WۏNL*~LD 1DMlq ]˩jb$[jnh~ƽ9}Br{ iN?k+-:mVm-]ySɢ۸8Q6ϲk3MtsOjB/'Y[Hkc]pnl˸O;ek7'iƒQ K\>%:%vSq@ m8MkS)l0nقcBu}<<~~NbAVLfm޹C;uN+'|hݚ hR! ',kܮF*rך_[Xyz“Ω9M;VI`VOޝ?|=?kFc'Gv ޸H{Yx[ q PZ2}Cwow6hʸ |}Yr5h_3=[wi0HWsю6Zk=nBt4Xٸʼntזtؔ7R?c\F۬I>6ԞDnً;%=Z&!]ܢXw,Gv\o=hKtkR!KX"Nkc$a)4ɻ5PvQ DƛGr']rk:Ug=_IVoLGڭ:OIl?)떷(+Bymyw%K=Ux݋l_[enaEch3DOn]XB†nkk{> ђd'@QeV}t+޵U׶w eT ԰wIe*0L .S"sBߛ]ش,hۼb$;t[ bZ~AO^ mfemva渫X Q)򚡓Xђ-g>XƢ7tBGJT f0/1x_GC;.Nqh?}5u%_~ƺm[_zI9y-lDbS84--ݠsTz['>zBfwqh/=b9N5&2ws~Ŋn\s]ݬMI[kmcw֙z'._ltdTw[ȸ'Sw;Se'(Fu.I  +j|oR^QCɄ ]l;ܿ4dqif~F/ƛw[Xi޹Ⱦh`W}ɍ$hq p㕙4ϒY"wwEff LM\ƢQo +{H/Ct96YcS\H:^/wF|9𽶝IT^KtbP *e &yk}~7=ڭ;˷'+?X͆Յw8<65Ldelm&|<6T]Dwz=]^?=6X)Ml[^!>I^Kxw-:tDziw˭;ܹ%aIv4_m6@wAYZ{ G ۸Wmu(0J>v/Ncn3'TM7Th"#$탯'1>~6w|}痯M/?L/=[0B) !?npovQ#{Ri-H/zz;^q]ڋǢ/r1vtEDl_e0H>Zev5ےz-( ohdskW,UDrO%2.<_N-ޟ*<`C#GHD96 q׽J:Zw|ٝ;ݭ:΁}pOn'*Ypwhubmim;ݢ9$3m#=w7p5Uim51?kM oKc3vhͰH_z_-pKl%/eߊqܶI )1Qb:1@eTq?-yuzDy玥%nJ:LKv;t8:MU$7ܱțH2z+"nNm#l_ȆPŸ-IGYֱe wzc3wnKGIsk+!:c͸}f}맃tc:1i2;6;uЭTZs`ud:=Jyy/yǛp#2&'?Cy臯gҙC{;_|7w'16BJl"j>K"wweoOoNͲ,̯g;W{NxZ^jzaW}Ozl+"_o[m֕Ԙhk|?o{|Go}Lo*?3G4}z|}y΄<i~L;{^*}_v95 [EW:wmr|qkSVvt]^Ƿ|t'vi7>]='1숬 k93.kHVn_O7"m7r۶zD]w VV5<wsÕTjC^=s'nT[RI B(TX k0J;V='uZ;?^MDfܝ[o[w<^O]xd 7b>j"#eٽM?l=7iN];rϏmJ߻˩7qO.ٺsi={< Ykݚ]u__h6S_ ^{, ô{Bǻ_o|mKmfŖ?{$ZZ=]7lr]<+/h09|郋C~LR l 2TO Fn+wޕ*>[]jiEdҁ'[䆿]vu5P2--u_z۶F횔N?^mEm͍;wl gwCKjvyۋm<]fx\Dvݵak׎{v7t5365v׮o}C]=iịޯw%N b|9-N~]22xd55ovۿnw=$''KAΦ)u?9v rni]SڶGgI. "---^TT=*=֪*T`_D:_t{+xԻWRC>hLga4r(M\Bj*~vimӹY~(":kwmoKv[m:ܫ'K7箏\9ytEc݉?w# = [ܱTܹc{ 0|F/)4Nhy-geSe{aYȸ'w]GO-ֶk7'(jƗV%\@Vω3g]ڟ=ԙgʼnTJ:8AdrrG PE/47zclj޳!t_VE#3|pz~n.߼sfkN-ؽ/VD37zæUrp#7Y#r\wnIg˶nMytI6GۄS3[Gup"׿~뉟\фH Dq\1wykc3ݝ]j R dQ#k1PJ#r ^vC/,-K~sssNk9 ì%071 f/+++J=̽{qkTȝ8=Y]&2o|]D>D#hҐbnaeaivhf/nHgwў=]^ZX.6V\\Ir#FZR_m^j;IukzkVEu1n;r<Ⱦv;.S5)˸s{h㳒lܶB⠯/}94WR"~=Zv^J ]hs6IjwP՜@ P-B_oǛZs nύ-҃oKZfb[nktVaz+p+Y&Kr5^WɋNG-"M% cg:j*t~[Tf޳ !&XFY>5 8{rml;"2㳋SjvZ 0ȡW^H$6fr.^I|ɳy wZoǎEnfggw]ͬ6X䩬%>eePWZ9M*e/SxcXKL`Wq-҃o?dkM*-f5J䖍h!Nsd_{w[Xwjc0xI KZe fw._Z!o* ,YNuSҽh鍻{RO{6ܓ޷e5JvCnMeAjܨ좎=宥^K7(`sMdތ[9ƉJ=Ͽ拝")1;;[&#*-pGl>s_FDDݚ[l۶;g |WwEQ7[.iႍ>smHn0\pnvrcHö vg"-ݬD .E2Ok{|>Q @×{PJ:zDat|Tjԍ1 Հwc Pyn5[&D.lDn۝={3H`\]=km l Q kGpp]oLJV/ceFn#No&qb \%0ǎڝ`mHXFzc3 <''twbX 52( feTB‚1D=%?j%hǥ-o:7+A,jq̻9u]E+8D|u>]Sb*|wnIkLl\a 2 7ݲ% MA|kVF mt '́zfeN( E&$*t̙3?g& JC(TRh%c~ʗ/o|B &܎K7wH/=X\yX[a,Y$x1F']>658Mha?INKhF0;BywLbmsEI*|bKZ Vx$q@ᒍ,#պm>fNLQ,{}r3e$t2""=?8$"C߻4L;9|齋C?iV̾TЎKt4gAr٬@9f2T/"{uֆظ0Xߥ82n4It-wJ&ɭt7?8;Qp*Bs[wDdw?e(՝[*8۔{QQk7'ubZrs={{wy ;ݔnYA[$u3Wvff"Kg.9xPPjC~*dOU@YI~q،_k~4[ڋa6& T eA$_|JOeܨݠ-WMFMTvU4F45D]^ׇw;x'MvjeJ0a!A=A!ҧ"wVwbYsyR])$4Plӿ9k;WGD$ yZV{a t1=eH3:ͥL$eGx*59OQN2v# Ͱ j R$B M l&C2cgK<UBQ{gb&rd<Ɲt=wfT9nXs;<5BB$ҢnEj*0s;Fe`?8=]aruw߿C4e.8\&Q,cD$ɏ.O0ڱI6i>Z"fA!2#&&"BeP3;,m2 KbMH'T[N x@!Dܽ읻\UC%$dvϺLr!ۻwV #Tm>@3HN}HՉ؛g]A*Xf63g>JODR=6*GDA(f9@M{Gtɵ7g tJ؍L1r!Y˒(U=Oz-{OsGԼb55NQw6ok}}LZ |/~_TęivU!Qӈ)@D{ԮOE C'h2$Pm414-FA@dH/ ByȿU]k%VQLו\ȺDu9z-P?ҹA5@ ܨ2? ^sَY`"-̇YȟY֮kJ$!Qi5Y-ȽơLDyk&8Ivy]^""29Q^?+BQ#ij$.z'a>P qsOpʨ@QR-Z{vo$P=H{&A;&S8YЌ'(j'"x =M 0e@VigPʤy(Zy5n7msZyX53<Ԛ\ZZcwz8sPEay^=Sc;Bmx]$1Q_a_ClyHv{8):46u4;͊.MW Ӱ|A, [)F2&C"B5Q^`"]ޕcŠ |1d(2ύf@vhCᏪh,VQf!xHV'`iU=v$#ݏx6Y"(UՈpNe,Aٚ{8yFLQcKݞ[Tsyq1~7,hS [fAj&CR$B0j~jxm5#E"45F򹝁V׮Y_Sd"3¢KQD\ Z`U?S-3iHZ8, g$Rur4M1_3fBږm[$];ݻws!OgOdp"#,9F-T3 (yG SFJM64!bLSb*r5CD]^~$^]i$1a6ّ*TV5M2+w hF, 3Vnk{3̖ͤV.2yx|;w3heiPƬr3 #i5k [qOkP b AS+l2$ TM ,g/r h2egEr݋i5ۈE5S32_6!p'Rҗe:&πP4ˠ>k` UqHQ8zFc"z-b`N! uv֣ ؍jBY҅6s FִBaEa$N@Udj&CR$%EmU}޺+/?`=vK_RePvGG֎=֘D٩Vg4]Ȇn9]O1|_L׭yL/jQCEZȱUJRDeC⻯}󷯫}O.2e*S%'"I\lxD];Ӊt↬Ŵz1F f$ɾ)ETJ ⊌J )2$NA("]U{j!LYv+*(\;{SN1O&%m2!Pd4q+yDތɮET-9vnO6l,Y\-DP[67vS䡏CQ-:j$ˁ\ѨᅏF%76gNPg 1,#EL lnOO')U'W`GE.OXDRa^`"cZ/M_Q*uOjPhUER%٘"c55}.4 ګ =,@ 6m) '6z"$${eSS9X|R(4hAl\(B W a ϥz ZeQ ,hP+MdA׃n.ei7&cy+2Q#=v3jbFz1LDɅlu]^Wr!RR`y̎f':"3>EVFWc!sWi/v Zb,h.CʓExem9EԀws"z2X:F? 7\*iFk'cj{&96+AضHNP:yie,j jN!elXd,w#N3El 2A;s-y"m2KB*P 6Sdԑi'(l5i)| n5j/)^IX6c(5Xs䡏!@aaˌe+gwC9]&M.d_ɵs fOs#P$," l%dM+J]Nros*Um}`(""BIP{YYcHRK j'"I# Du9\ųFޢdԢ-v&DIN<9W'R_S<3;(C t=xBQO 9Κn ݈I*^2KNH/ᢢչBiSQ/`WόT0 5I9զM <];,m2/?@'lS.+$X㼖}ڙ=͍T̚3WQ8Z-R* i2ƝtD"/'Ԍe;sZR_ۙ"-Ddbg!&Żo_*}:ŋwvI,Z 䛱>Uʵ@lĢZʄRba.hF:m[PbҞi[Q%adH2P ,m2KZajdY2OLp^ᓩnm2ZvPcAR"q쪓,al/-\F;z3-2aXip͑%C0נh"$/\N̞.XUWʩ]^WwUt's5؍= CA 6d_fR{ GK}[pj/5jp^CNB$!vSD DȠ!Q4F) 됇Ui@e+AmD fj⒨I ߽7z*=# &cgPעMaiyG\9\ƌQrrFԠv˗PW)#`:,$cSdԻ賙pK*,>m, gSNQ]3,J ±Cm71C.s) 3p{!<̳xx`t /W5S YȂ 03v嚔PnjN騭 S />拏6>Ss(#Bhɑ3v#>KFH/hT` 6Z;cb{m ǬʩSCCCCCC{3Bb;S!Fk*B25OAVֺ"C"B >v6T)_`qng==njdSXS6IN(R`4LO'TUxAfQkXҒ}֜ ^9/|T'![nnX]s7C-\ܤk<#P9ب3x X,LVzEC,3[zU@DA(2%6 X݈E]H/-fyrXw=k#Npm2ȣl2D&?/#'qIH~iɚ /lQe"Ṕ@CKll,4V…Kf Ws)6|OqzGV)eR$T+S!Ӄ}|'x@'D/*#TfVZoO~Uv޻TD`.\*&÷}neߥmc7b{nFvp͘`avmr lF-dud wK*0.fj˽ tPas(M@ފ_F-䡏!|"f]i[f^h<ɈuOSCߣr͗X啸_ʘ h߃;/ID}D OVnrK˻EidgL|~?OETt"9II]*EFek(2$ M0d&"I]˾K/?yX&n;3P@AS< Xrwokhi;aM7zWͻOZNhF2ݣ/ׂ`~Iƞ=ܥ|n'he)CD3EM`2R}4pr+&.VY2B3zqAص)ybz1GÉbSmzl% Uզf DQe8yf\ "% ;Ñô" X)EF,25lZ}C6LgsڄKK5, A0m b j 55ʳz-܇;s#f>< v4Q= +$[)- ] Qglç\T۴el2$ \KƲVUC޺uffa؂]ҌDxcޢ>GtzhFAJL5g*̺t 2hz{%UoDwK&D'ɺ ͩ`=\6$2nF{(s;1>Ҿd~H*DgjN2r6o A<2 ^JOD t)2}Dص.2KDD=Ck{Եs?^ɓO6ÜKbgs;}^Gz2Gs;'"IU$X!CUɘ<*Wdhe8{cc!mg;Gs>k@xY_ëm7y%r35$Hy #^p4Gg ^Vg tthSF:UάHPtvֲ"cm{3kf(L$o]mKj{;w"euzl]xFD9n? ?3oǽ5q1$7u|NTG@}77']=Э`/論,^9+WN{TLX]ޱ$fƨ7һG_ϥ~_%DOe :.x0ę ZgbW?Qۡ}앫'l/: &+WDٮXFe#m2D4I~ǖc݌BilS]^Wr!yv!jް1H߹ٵajTa-_u\j)A ,hoYwPK_wxG27wuZI;s#_ Q) ^Q2F0}:YQ}D*AWН% *zQ2L2e:ijj W:݁ۏߜ52;wz]D"$ᮎvY}ˈY\2{PWhhkqADPr $\c?w L Ct픫ʹev'Vok{+<£T#M7.;nW/Zhul FPMu+s{ D;8wo_D;]׻5{V /X ݿDDcGvǎ=͍^xxiiD$xCDwRnMEɅ,ovAX$)#s;=MSF'Ђzzn"J\cho'\>J7C]d+C/3fOKP/luA*"r7_|ܲzjԹW 1}Gid$$UQf%6,5/dpt+N^#rЂ饯< u#@aQj61u9hf$l˖@D~Wr[߲Ӑ]+Q]Z߾ny\HQcz{-%"JS&ʰR4n[8Fvc'"t~p$Gxq 䳇"ՠ_(d" R([OM[?6qF(:U iW`7%S[] B+-'m 1Q@u(`=ί>Dh!յ:TiN_W.5ijV+v{] yl7EF,XJ'(2ZQF1nV(w-E4+2H K,y-܈~L^#5(ڌ݈{ Cbk;2㩌JܳI~ 1E}S^95 |ѳ PVHT_D6C9ՙZ 5!Tu=J-/SUPtQ;~|_df1:~rcYLQaڐ8b {"\.;wQ+ϭ-QgbYK%4C[l inŪmc7b,BD~HՄ}$ot܀Y=͍8ڄu^#۟^:B hu`]pZ_ƛ/>^L 2e&GG'^O)2m[^''b#:1IGb%,JQ ܈9+#6tžK_9w}+1 LDV:`lY] v׺Ȩ/8"&ˊ6ɯjkڜ{!?t׻/ԣ~x7H- j ]_qf6֤  Q#SCUGl""OSCr!TA]l^OtD[)-P]b8#lbI3.rL5}o%PF]fU+>{iPЛGQ6ԒrT[l7$Yyil#"TPnu97%)"ՙDx֝_=="$bz.n|HF6xCOw7z x]%S#> bCQH]ORPvìQ2TM_Q;,D3*fLM1w((3uaܼu{g^5R'Oޝd_b#Xb0gTE_J0ڣCVob O KwG'Y1I4)AH\ʄ F J؛27g q"".c>DkIWP2Ì\=׹*6#]My .BiAqD#[JPh$dA2O^}vad?T'Q–'{MVp<&W+JTP~ڥƆ:#:eӡ*2-ӉtGS=YHݓw㍚]f+lc(C6'L&Jzf3^Qs`p lA廪ҡvxxޮchѠY$1"橔.\f];zg]f׎,Bź`F$PI41\Ȫɤ˨bLb\Ȣ/Frafpj쩡[WVDO'x+;liZ)\1L&72=W j7mzX^j͌-.j{+[ˁa95GG%#L(ioB̚Ny-Wf&"ɠϭIU쀸߉Hoռ7bˁ6OTfojkpT`A( }'NC#CgG+=mD 㧿+2v2|w&nZhް7,-KZ|n'Ġ]Ѭd3EvBFeG;V*Cg`\U@uF(/L=`ԹWN V|GB͢V'+.q9P&5Reʵp \s%n`3,RP:&黴Z+ǿ߽;H K9T ϥPaA0]6.rDSC.\t=jvBdVǤ,R$TJOA` lNoNBmbg/$uLP D%eV o<|h84|es=v]8j9>cOs#<2/<^OeF0~OHs%sm&@0bE)Q&p% .ѼI-XE˘C6tOSLr2򺠰Ol%)3S4S eajjtrb{!|9*̋W>vAʏDɘ)(3u"? {#D45 P{h!v:Z=s٘kq9H{ɡd(gҁBX#fs%^|ݣ/r;w3D ? M!c_ 1j&n~O#>0@s|>5ryκV G_ ] hh K*P,OS^z {aPO{sdW"a#}}euFXoe. BQ(;J)c{ZƬ&vdY?yTfYƩ]2dPsikJGtU?,C&DHuW)QO+L|.ȅBfh~ S`bFBQ'Ђ=QHs@Q3q/^PAX6-wq" IE FCѻ/uDt+<1x9MwbRJ4MFKMf)ԷS6`@0dԥVh TEm&SfJ|iI8Zs2p63}z-H;h$Ap ϥZ]=.-f#E^Dg;unTX lUl"i۴yU_vW#;e:<O=7 +Թ3!G+ 7g %@%Q19(Yv9,>k䢳~Yozwh5\D5Cd*B)Jih[!Qჰx;:P>QYZu!"}QC|/?'㩘^.S~5_ 5 ^(p[##!" #"uk$Z+[   IDAT gJ"_ưɰ: dr_^1"%j'fmn2n(ܠܚk>B~Vނ5P~ʠˀkeVysa)FHmdhCjOSD$/e'ǝ;S屛> 4H3i>A'"Ӥ#f:ʩ | ;85zȭ'ޑ,bA(.OeLP BQC0jL ʹlBQm2Dv24l28)oQ38b*>ݭ2Y$sWKowy6OD' =,. Hrp|x*ú B .~ՕƟ &3^w8sf; C)Sf3Ȕ@ @kiRn zV>H"$3|*r=^#9(S pHԔGB-] Zd7eol >3b2 +D4v#{ 3TFmr O2Q0L4Q#Z*5\IfDJd8DDf?Lg`Q($aMA SÈ˕_F jEC1*:p&- 6˦KQ]&"OS8`Q}3ʰÑyPNtIJw6 .!%6?ODI^45D4OLLbvTf{S.OBij`]\DOڸ JPlnO^·((_i/J!hAfH..ʌ^!?PZ b Nr9kMƮds)RD'MF($}/vBR5ZxjwņMٶ0v#%}o EA?%D`J4 Vdվ&,*ltSt{n<[P{ZewWR(jh}3x*ӽǃp_U7 :mrkS `$~r6otHhs`}|,fmϺI* lE_ P߮@p:QUm2 f .Eȋf̭9hF=];:hq{Oscwe˅Nр_ l5T*gߣɡ@n-˗DMQ(4222E&zU?&A0,+mQd N#OC#;'_W^KVUms}CQs;G]7H/-f>7y]C sw r͊,Jy7” ,~mm{vLs{/K׌*G #2DꨑB }2%A 6b}\me"90 JNv#u2FE S؝G^8WΞ@b ՈUu U](2YF_Dv&haLO$w` ʚ,[ Ն&wp`eVf )vPzͪ%)y|ySin x]Bg}<@ C9 BPˈ}F˛AgO Rhdx*O8(_i*Dbc6!%YQ}n'wS%dn0^Myڔ,BueЦc><Xqf A=6 xCQC-C9〄&Ʌl*Oe.1{ckK cjjtr:;Wn F(>#AQd6IE@Puh[ʓ,|n6<ϣYhymA!"OSJ9vr~*l2Ʌ,:TEռ ϪR1)Yԍ{6O=5c7bYa 5.>e 81D0:%`o'e)Z BaL~044nA~gQc'*8ڥ2SJy!&inĖp[>e=ѣs<"45x*apSLS"]<κYlި=9¹#| F@bv5 ck\\%b~@*Lk]9e{nQBFJ#LQ(QKlA%^gdH$Tf\g[KGFFOU(֟0/RN9kcM<K'ˆcTY;9c X{mFLe,h]Yx'"OSC$aaG5 wOs#|z-r_2FQ[*L^9+Wz'OSX6vPC]ID'SӔN=wb8L818IS$Ba%lAjVjnpunjOS^Uνc%}Z-b Ib]NbeT]FYHDg6L+>BX wy]:ͺDu$8wy]nA"Jpj2OJg%Ǿ6"];̞G%,4' E*+H/W;54<<2222$"8t+PhHMevZ]YëP<`~tj:h<<Oe0T"@IlٸG jdA=˻G_UC;n~O`Os#/BP2WC|(r( ɅlOH'HC!F(SS+$2ZYV"j;4SDWƊ{5()- @RQf쩡O>Tb' YFE&xlT2j2] lj_;CD]\%d\&Sl^)}M&<5i@>~dq)DKA a"Dp ns}n$A ٴèut"ErI0Sg_y(n{ԩSwuGW[},-H! # BSsQ7F*8}~ij`@r)o@$;P[FiWd@(#4}nN1VJ)\pїx-o2k>={ }#˅vĠG_ Q< ܰ}n5Ҟx2KAD<[! |vM1z~c`8DD'O> 9w"|iiGmv(})Ǝ""z衇;mΧVIRd7}Q^j]/VWSw)>ShUͧsyW=gr)(3Q>#}DPxHD|_lϭ`YDUdp̫nKDM@ /m`@OS n&MƼQl25&uEug&A3vw5'фRÇY𹝨lJ.d Yp=r Ѱe&D ÿ3 }GN~~j3EggMJ_{;Ѭ?Jam7`9X<}Iwg|Z]*#yd\:u d72b6ߙp:g2LGGG!;[а4_`i xVu9z}tym2XRVfżT&lLٰĮRI毖.CD3ngf.2Z|nBZ]~OH.ijE i"v֣x*vFc},#l|t BͰNy҅ImȔ2GPiS Q#5:Ƞ5V:r(P|tyحfQH +~OLD | b6[}|. <7φ׬wQng}r!}afŬ&pH0tN.C"&D3,n$[K (3QMf*|6; )0|UH;JtxYU޼ͪBue(wr lD)5/_xtSas#+.F$ 5؅jOe'E8XO&hu (2.⑈2[5ٱ's tr.{R(j@ZinNk"&0*:OAj&R3F<@Kx.u_sذL;3*LRXt,Sc6 X`^bm@uZ~7_|Xa\[Qd@I2ex|$ ^$enUPPRl)i47+Sr!,&}j8?a-]d㑡ZthL!LM ݷ~}Y|\(Wĺ *MDG'ЂDOSx8't\&\DDȠA {-yՌƞ8"?|F#yxtH(_Z |u3=XWƞ|bzG :[w^$+Y[rzQ.lU֛J#J)dk~q^f$Ȕ2SSyrOpb@jo#7`R]'f_ O(2==͍-m2}oH/A!"\jOscH&ݝTTEdK.ƶœ2Cy;Rؤ_* .i4Z"$M  6(?G~بcjl E6r(a3O\|9H35S.] ':ijt̴=|]91=Ck+;JJҔjne'ω4SH5b)(35z6WvM i߾}nݢP(~cP:I AW4hr ^Em _=g&) # Ȏ!<)=6u>$6Ʋ1 1˘0ba8húDϚI.F4q:()E0e2{M'`{^Eeu$Ҍ N844nYauUEJQQf{#DdQg^95o0bߎXY{h9XIuw/swu4;[ݎw_&Dt޽{R&DDiTϳݻ}uosR,4N'ΝN^K7W "rݻwo~~֦XlU{wbV;{[eb,6,ѧ{Ǫ뙈e~6ʣk^$x2֏AӉ߽KD|.mJӉYD4w/{nՙ2 v2K_6w/ۺZw5`gl՟ֶ٪muXAs.sw/zƽ+%u5w,Փ޻OVGushiH`-J~N"{K#ɅlvYjz"z`gzt,GWPviwMD~Ϯ]WO>=liidۉ}b@<_m56@*gvDNuN$BO#"WNQ5fE┬%>" A(` nT&Et P.浉_I.Q*LD8vhvJI,3\OE u]?hIenݐ1HHv@c24w=c7ng^\BvcC]r1ߙ,#A3b4uzg" n/kҭayG(ȼe8W<2BqɣμxmZdԘh4Z;ifcf:y V E)_jD]PYᅵu @#DD֫.P5;rԹu~O#f{]mP[TvZNL. +Yqs@=nq,2Lbq&V?53y%@/AOJ~>zFzi"ćЖgbt7(\]TbwάZ='c;qgac=3M.7`` X $;i}b' B"ݔ%6IX].^tI#WnwuALRM1}?[?‚j-}0~<'"{uGk`a9` xz 팵U%!.iĦmdfq}'(Yd˩dBm&c{t&_֏p&F䰌u~f޻3VFǍgL%|XP Mj>*!2Dd%M?JMA.aͅ 5= /38?X2>>oi0= S63<Ө;3liwWkc޶"Ӆ)5]4| }[e,L_xl2q&2h49,&GcV&x.2;MX0}'Og ?]ΰ:~]Z  %k.n-3/P+x4"f(vy=cDgbD4 F>>K:rRGā KMF$0{sн5E\!"Mz 2tE ^%C-UTA*(a1ڝeŮ>_!"z'/2LlAa9fgv|9Vd2~Qt9fe!rrLRhCD]BcQ^1m;Dl2b& KL]v,i4$aZB+x޸%6 -fsrHrR5FY;La]R\G_d>y' fEuƳiy$iv!}+ E.JxzMF "BF kuyK7KUE .g-] 3=fE2ؑ.ӳɭ˸uL0.dЄIH(6 ;hf1FEw(.#Xj/fWɺL(2zן?YO?\3_g.p/t9ՙ&/՝(`/1nqoۮE?Ofs[1n`A. &Ӝ(LSNj_&Ddm1r0m-fډ.y*g&q3-e,K5 F#u{d|v1g%2Ҹ̥ 52 WBڜ9փ%4}bxSU8wuj昳cdX'$3?WV0GyH+ꌛoo[`if"#r9(d6?bn¥Al2Ͱ'GU"Խ~K§i{ v˸=LALҌHA8-M 芄֩lv ]'ᲁ,ɡ=u摩[x#X#VRD4ֿD㏾0=j;(\ʹ;X=Xa]zϫ&e:JVG1xHALq/:Kr8HAP1cd&ô]u2;}/7n]&nJ0$<2"YL&٥,`krXvZnwT\X3mE>Jý`wELuuIܟ"2-//cf0<9ʚLGkB#X%ǀC=i3Bht0i]a\@$5†Vipʨѐ'M;r1mE uM1(5n1t+cHPd.dp"&5.%HBlإÆފS-_.>gxeVdA+w9ǿ&ubqZ{=?"CDxbQBky1u+=o s)cL1;*6 t 7r8Z MO'Ĥq[[^ S;TƈjE"eDadeRu.e {+Ժjj9et#}C}&/3 #1.#T!k@v2L_Qw(*e?evZT+G-wIIDɸS-ADSQ!dbQ%01m2 9%T/ Eh%:{D! tYFCr8 ÐiR5m_ֈfcc.0 0/: 4Czc2C@Q VMgXۊpdL9N4ƶm2ϥKb*6{6Ιi&.afmDJ4$ĸaQmU1<DtLDЯH6E &#gBө[_\4YɈl`QĈ"Nh&wĶ;(ɡTE/y2h \j Kr49NLDb EX)mcѠ iSe]rrKeymѣ}Xa+uC c&ki_EXazFmrw g?kaV [hHðɈm1;YܰKɠ_/$$"Cla5f2t署Zq{ UW$Ԟ&Mj4b؊NrcGHdPiYF Ob왗_~:9a9}/ͰX,0J#EF.pW0랠_;إjB}Z(&x0Եɜ\4YdR6m=KM%Z<i #Vm)b8ܙkGph ]Fc!zCD6 eTT-DT6+̈́MFJBm7˸aL/pggK'` ) RX9"C,0}@LM#X hy6]n(S&gO,S٤Z&)؋PamΊ s Q#صY͹0ͥ6D/.nP$L.ȅ/̘&Vr8bإw>f95˰.0 Ӌ4fzN`9F+3gs Y.0g~þfvǭ<7,s0;!^Bɸ6xZҦPMi!mBq珺9~N<>*AH!0eampM(3'"Y(2tX'&RTYk-_LS99r ٥,6NMޜ;uazou=eP=Q4_ہRdРyd;eMƝ[X( Dnhrtr\:ͩc ]ܟMFd1L;Fe{  bI "Kr`fBNjs)#8H 5+"c/[zgOL0 ӻtB>I01uL-FNؑMƳ+DHA˩Pud0Tw&w˙dwƍFK[3UT<B!N^MdD/"#YN'"ÁCrY,/g٥Hp艈RoY/0Ldr#XOࡑ^}4z/ o`x<( B(.d6k+-˘& aQ/-gH( 㺂Md܊̶fh.Ӗxe,e%\ihq4P"2㺒Ԥpzf^C4$ọK0 ##E'cL7:1yx{> -Rь KBfM˩إT HMXr;4 Qw Nch#\0 7_u[AJ0ml2m(20<7OeFֆ>R7Jf)ceR(V)D U$tr(9,qSFB[ 7VꎰG ox^-v]= wglS;n|_HB0b9Z,Qr)h"9|d$CDf<dž"ἆ.sTW|uayVhQ5V6,ydJ( 'yH g. l6R\js9ar+2u[/ 6fn"M"x8 sPH.9&jrp.L2譖6(<S)R@O&ռHNe>"NwaC ]0a;e;H{3M14麾 \E!Žr(ʛ'1 Ʉ:.沖:şc<3s=3~xy?cXZ޸i\WEq{D I4n㺲$ݶ'N "Me ٨[WƇ޹YBDa ZNeL̄A*0Ʉ659LDSdw6'2J#T0́N0LzWܸzƍ^#;Rom2_qW.LoGNT$yVwMJۆ] B:|q!mѸDw TSdEM9hƶl+܉aeGҌn- ܙqh(_PDŽ_tR[ZhÄBÆ]prR6BmXay [a-awerj<"<,R2WƲL [_|h̳ϜW47odn\,F{PdM%ޞOYqGiPKU9@nk"F!cbj&}q vTla=Ҋen7-7]az A??7./}a/3er<*O]x̍^[j7F{”Ƨ.<|huo/e,(2b}&1Nj!aQ!(8k+w.Qw<L&PbugGa4Osqᵋ ТB>oEO&T5JT j,BڜNj+-1ၻ։Pdإ>0=gvwbON̖r=ߤ3MUV+6XiV sS OxjN(\ZZv:9R 6Ʉ*647kۍī^wx6H s y @шNL&%j-V[rΈʰVWW[YC 2V-q-y@&Y7|1aϯ]*{7Ʉ2݅l(i(xױ,'xhb"KCw[Xڧ4ɕ[(Rr3$ֽDZ.Kŀ>u'D?oey]ڃL&dk/*wWM;"îDkf)Bw߾"wvi]);(w"6q.YIDv?5FX5nq ;C7vͱcz5i]oT>opi_e>2BI4gm!E#k/oS+&Ǣ%|Lݚd]_1T =2I-BDx!.$6Kc:2#Ou-y [Yaم4ܛZDȗ^49X(o ʛSMj|H"*7DdlڧF*h0<8c~qL0L?z e|{Qfk:l!uOi~-e qIu{XQL=DDS "(nWmGe9'""e-gPr dj٥БEߐCGue*9%'MuX-Iu]8(`;hCS#<λ߼z\83!ʙcKP6@bZ=VСjFTSNާ e>RKQm&p,R"r2/ޮq]n{ (cx<1 !2(.muk:z`ӽa-l&2 s .hU(Dp_=`'99|}=@'l]ũѐ% w̮϶?}%< c?r8ؑV̊aO'5PFl"2+-h ?.bj3l,0L{> )0L*m%3~i%RZl<0cC=Rhܳ)28BYKS Zh76]0{g ]r?䷞?e9H( _)hP~ kT,2uu63[f|{Qd9rr mV3>sa;"T&Mf-_D%ܑ6 e5rP$&H 7i2ϩZ\ݵ㩫ȰMawyQyew\\xH9.}HiP#xu.Uj<\voBLą2¿ui |%?%v[^x-Ef̳/~ТMF<ǰɬ脽/d%0nEưKkpUsoHAM늴m[3 ?}wy$*‡o9HY/EfLfJrZ1l"]ʎ""ͥ6Fc@P(&!'W1 aAE;eό\E'+[FLk[c/~{-mm2̸C^C%9QD5 nb[NVڪA@UTԕo65<Ĉ)sji2dP^1J,"4>J#[pa–?;i7"s(CGyƫW37.zõxg\ZW.p ,o5j2W_}MYiL\0D$1\jCW|1k9@02cr8>kCú"s5]jFoM3Liq8~N$Њaۥ*dqE +eYX9X@!?wubzG~#~\=>1`PDhT g-GWBZMFY "Ѕjer@Q#Ef[ 06vwfG̥?#"0X}xH,c+ k t/Bɧt60 9es-Fgvӝߥ/1]D?b?ʗD?l"Lrz9kN5i2VK,|}[?fa&h0͗7_0>So^D#nxػAE 1A=Cn0 !`wqcن^'Ef6 ez\+f>.8S h,"J/N2'0L[P@K39e4i)c.SI 勨fh9kd]/CDY1 e.n4+wGDaa t'M(ЂuEH7Dߥ|8o_/g-@ tv+a?cwIZEfh3@+KD&|` Oh\Wh9kA1 eM늄Y:.)R-l@r%6O4rCqk%KYH-Dcu{v).Skbap+.U'GU"z akUuO6zZtvt("uW!'A 6 e5R1M~sݩl||tJ==µj䰌"vnem'0}C{XcCnȸ>Jḁ6Dq]A Z1赔P#TAy"fNEf SXX t3}2;2/&59W$)xL+5M?/rh,߬ء&|bf?wǿ6SM"b ?^Ef?h>+&3ڀbإXfŰ4ٰK2D"`ִ tԺ[^] 0]H2tƵBX49,*(~X$.c9VZh_ tr rݴ1a]z)+1MC(t61+2u{4bإɄgs&cR43vIW$T-!GFDH6PVKugqsu/Ae,CDЋ!$ԈS$̥ Mqz\sŅ.. .|0 ӈ}Ps(tRUKB!"4F8 iST'2659Æ#}EX4H[*2Xanf3(Scʘ&Ne̸mAӥ?ЃLbHmθwxsޝ3 :xGEXa:B[~I2%EFU!dD\Jj4bDd%8ؚe'v˸0ACG-uE#Gȩl*Rp9kAs5?ҌCv#leq+MNeYY#zĴ^Nr ]50|ue9k  -g1M3Ԗ"htN91Uڝ"6!]["5 =()-Cr8mf1Fp\ʰKm3]>s3"nd2x:2rg.Lmz+o< [ݵg)qy}z.a:H_oϧdـ9ʔ\t\ .A*2go(Rӧ q_x0=ANV,2XdrTÁ.2DBX}/e:$u_yB!LW_2vLc[?/CK?<ͥ 0QJfGf]f"9OД&3!TbZNe.e&ّPz tE 9~hTa:Nz5Ct&!(^f2Wm7po7<۟ 5'Lzc dtמO]â N< dR |.]LVP/bVβdlutKY(O&FQ2uGΊ % -F <9, 0XpBՊar 9hQC/+jpSgg6WDtI2hS|EW37>= 'hŎA˗RoWjU`"CDBڄ"P餆*XiՏsB/"q4ya3 ӣDnRʄGY0L?#3HѿE%2D4LK餆~LRX_"BA\ʘNjkOz^x^xR'250[j5K#g}f 0 ǖVdv0{g"#v K(M(2pr*,+ &E S#5O%S!"f2>/@xN0Į ""Y,]ưKБr* 5H(P,W*u9Aq iƏ//spl)2#g}-*2W^yW{_M&axJIӇ^[DR&1$nԛBrc/n5RBJϧ.<{&sFWoxh0 38-eb9f` K<)2DWdȕΫFCZKm*,2#pT?cy.\Xvj.3'D4P c!2 5 .P@ 6e4vjʳ9ak䗡3ՙ`7_.SgFFĂ3=Ͱa^☙NfL(M~!m+&Js ]HK[$)(:gdB.54olDc8":7Hۣpb؊7ᑙ_kc9$SMy.ڰ[t,áYŧ.|{a^̰3ȰS IEj61EK(GDev)k9+rl;3s6^3>|_4," ;ѿNYF`K LcVF"&٥T 4n|`Ӎ$2.0 0ur1 2̎+ iEvHȌdBS. ffBZꎹ"7fh x9Z'F<L&T(θ ]&HD$S-xt?{x:0 0LНGwXaڃ_!| AY!"m.o<+BZrZ1lj6^:\Y9՚6쒮Hc 5;T] "6=C+2\0L2@20e@ѭ LrpAS`,*Rp`HSل.˼={LMt޻ uaψ؇RU,0-x(D0RS.!A(2um2"=฿a]Z7A>b tTP)~]#fd.CDeJ6D}n49.PtoEۀa9[rX]/#7Z]ưKN"R ,3Dd9!٥,ty"㺲? 11 0@ۥ.VbZEUŸKo\_"IDN"235d)d,#6L[[tyvD0 - :22"b HBw.c2Rp8pةl"z؉2O"N.Cl-da=cemo.!WP_(/H[PdhDD3:\fH#G%avJ2)j^G\V ZeTš[TeFDl60 0Žb]â "#hn š >ntRC/+6"3٥_A&FL(\{"Vdi$噓qqᾺ".T&]jŞYk\WPĤ+Y,o%˩-&ÿ^[aA&=@aQHLh۰K+- ¬Y1 edR-n&GU]Sl~q5`0i47`EaVhޕH2  iRJMB!"&"R#Ru2Y phrXÏsѧuaaE!&vUd}K+9"LoPdPVdf LI)2/}Tb)cMF+2 ôB'%v+d\496KDa2Dd)Fbr*i(t"ZaYf:0 0 0{E>nE&^1lT+&D430JDgkLK|v)6X:Æ26RdfN)2V,a*Ĉ"NDw/0vifB.CDS 5Bo]Nueaa2LCZTdP$SZ_tr(9,/Mad2xdp@I | EF"#JVdm4ˈǢHlZ\1MKUt/J.3s2.wiaa2L&j!"otRtb4I?}w dEr*ȈRV(2o~udž¥ĈŠ 0-f"B̓%Pp2rBإ !\&FGLjD>Yaa @oh5;G:Q*yVGY"G"U闾?=BO?*Qu q*әD?|JD{,ʛӣG"_=~OKNH/VgYrwc1ic_p4+7?b??|OolmlzllqCǕOܹs,&aC'~\رhΝD$vh0j,؅0ݽT‡n??_KeDC 3Jh]/O?=z$ED;պ#|?z$#A{7`a` 97 yǭID}spsfADd~)>|_h}/FS9{S/S# 'S'GmxYGO Gh`ԗ]dz0Loֵe?xk#a\NB-c[X4/Tb৥)8?ڟVS8phth b_D*Ƣ?(]0 0 NM9"|Ǝr/l gs^1O+wjBgdžN$4܃K돆ɧRTrN%"wi4gr8 Y@J%:DD3z(>?Jёlu-_ 1=l[ZF_Ƈ^skܽg'8}:&"nӻ!\]],+ǦX9pm:t/KcRCf3zTΥ Tڥ Á?tRTȾn큧 쑶\F+_"JۈZHbh,2Ph,"ByL-6Hr80$7-_\.ztj/Ӗ~L/0 0 Xajɾ3"CD9ˑ#@B|1l$n%9T EtR3BA?6%-3'@6. 6{QVda2j=2TNBA(bΟJ<]ȰKB!"E K7,3ww1q]i`؁cLcڃYsτqgԒ{<9ӑ ,,0x.|saX5si:mZm,|wމh$nCB;͹X7Gծ]W폵U{ճzȽYJ &[e j9jgz+kw|U'yg_=z٭>UJjF$5IWkZ}J-%qݮǨViA](AWT4%Q<_] qqn?rUUDT*w]Df)֩e2LaRT_Z/T5폣/YQqW-P]Q&QҧIR[Ѭj’6[͜]mzf+vw?W _1t21C_=ޝ*Z]˔n*/ݤeT8F6}vfՇQWm~ʓ'ṅ}_TezP ژb/%>"WYc7Q5inaIe|C>kzD&<2nқEd^~ܝ (?mzIo#2 \/:I12Q_]HUq)OwVnۢDʓ[6E^TuezЕz]bȏ~oY6T8Fjʫɷ_=|R1X$:Wd["6Gd*T=`qY%Qk~W2T 6߿/"v.r\4* ..` Ǹ3}_OkguXPɿDb_GkQ~[_|tӊ<{GֿU-Tt揻F ?nC=^|E+++"euo8Y08z6ߨLAĬGN"2;K{f˳6=;ч5Sb8&%ZDFGS]Q"5s KI#2CST2WzMld_FLzLiqÕM*7ODރE-`Gy寮rqYDS \tlb8BL=e k;ݪ+wgp$?_/͊8[;jl;F N?Z[6֭Fڅ 0%,38).޲QGd.*2kwa/r8rݝ(WW*r$N1;L2ȂW!1cDkC -ZiԸ'y٭_я'[Oܪň!"Q^?1Fd(ָL 5U1$MgV oˈ}펝[|/)]r=.vkMV>mLp?}W)9~YU?eDރGbhvT2jS*4s[S#_/,=^ygܺ/_|Nni{wVWWolޟV"2A]f_N1qLn˨)TwU>\va{Ɵyu_-vSUQ&"I2p2ַ?SA]drTm.?ߟXRU[GvX~go5$"j%pϾz4 # "25ˌ:Zݘ\Ɣ8IVĽF Zޱꊲ;ȗODlwOD*\sY#,.?Qy<{t] x8KNR IDAT<zzDf+*K|m[":;s eSe_~+{|j1}^2="뇿IџPU}+z53~y(;0!(S8fACT{l髟{3e?8jH[UQ7vVcDFeP(l""4Ō˸H(;;wv%_ǑgyFE[n2篮P]~6/"*.#"w?BU^>UE_?ͯo#4`FPp|Yػ8;Ҏ\Xz7v7|#"zǻzDl{ZW*[SȘ~!PlC3Nߍ-*S2̜2}Y|vf5:iei *R^I3b,qf7nJ'~7 (SP􈌊dNuQTDFDNJ%h剈lݲIDT]q`Ԓqk2BD49%id|4p6 eҧmq??Y],._hV};?R=XT[X;NDDߧ9ﻟ|.x'.g(xe pAEf5jI؊zel[l*/ݴ{Gɘd BAD\r$Z_k\}Do_qT _ -cwgջ*Õ;,.X'΢R5U59/o㮑//"(@e ’qȨ2/Ts K\|W{Qc,.;ȈsDp 81uQQKƸ¦1}5CprwL q]\~rk*J=kFuT}DlG3+Dߩ?Oے {AF1fQ5 ӽl~JD;{Lj)=qB_1 YY a&8k¨l2Կ_,~+/\lh*T,.F3=Zyu˦{U_cvyѺ̨P*1sC3D6AZk͊wG?-,<)-O=\vgm[MEd@dDȘ$Œ X2VSu/_Qw hFu;+Uƙ+׌LjPG{_kƘlLM}4+_8[9.GBŀL$ӦD^\ϣTDʴpL10˒̱Ф*iSj(W,}=hFkFlTW]QټhvhiO ]f~}+3YYS@:aCPp|W*#"W奪w_6:@ֶZ嗪R (ꗀ!ѿxm3S̈PFD^Ǿ֗TC몏fRJWW*h剈T`Ә&JuEY';;t {^@He g_=;;b1)>F-v³6h_,'ٸ)3"2i\3*.]u'fUo{E߈W]fQÔTm#YzhfZ =cTm߯TPELOTr*{GJʨR6n-wt:E"2=Ǝ31deƘWD$"gwMk]TmCQ+YⲈ$MEp}&UJA"(S8j+W.=VTZXz\QYu2W]`oFD_݄cl;Xb`0%Ŕ Xu &1̐m]Wv5I _Xzw,/T^I݀$>4#"NRd6@fHe tͪżyMi}x%^kl峯V=hkbNaѲ!׌G[Ṱ[6mݲʓ?ZQ}6ElaZ2H] [gL-j. Quk2;/<0>~񃉢'nJoY8.ޟb/{KB}_EeϢgDK-^(Θ2^&(۬F@1SR*Lለ4=Z_%"щ'nJoՖߕ ?6vX.Fb1P}gDĘ6ዊ3ڨ2zFe8ݣ(? DGD|bqo=q(ra82~'z!vfU{wV_S+"}{f |Y0uQaU=ԢGd,.[/5?2IþIվp؉rvYŰWUq [N;,3g3u1NgPAWm TUD"ȜsZm9nJ^k}οcȓ=.K} K@SǘJӃG" K-YXʃӦ6vC,]Y)\$"U_D"vk]+-gW,@2;Ο2O TG_u*?ý{>+ G?Ep`^eMm5c(EA^VBR gSYHlAOonl3g'/_OO~m?Qv< zxE 2>>>pQj~WE1LվpdBZ-:04&#BSuD% K*Kpk/ W_ /x >䱕O=Ԡn-)zx x x 6y] /^=Zo}kxDDD| _?X_C6D׮#܊j9\+ڟ.)nlN [:q 4b)nN%̼-ɧϜ99.:?"U޺~,j^pS ⶍ.%2+:"n_>o ڜ.)n$ٜv;hY23b).O%-IzʠE'_8ypDDPaDxd}Īĵq_Ѷ뫪DD+\lpD]ڹ~e`8s(q[,$ Ϧ\$G`:|0ņ$)xa`8"w՗!HdNtC øP[k("Um|"2 @^Wz "-BlD""_NR0\J>yƒ$Ak_á'ٰ/Kj_WzKZ\ @:xzf?Pl-dgSb~hM\B`93OxВd S'N::/e TWUD"Ȝ!sDpD9"m$?걽DvܰyK0J>*-I2(LUU?jDz'8@y+6S*(/2.m;?@XH#kqrYKщ`, .ϩlCD(d?l*vv>k0xq`\3SX S3_xВ,Y]]Pܤ G-I s1']ޛwzp %ܫJBt6'-_C`<|0F$>sLʅ?Ën{\8(""C;1MSl_@!3[}ة_ łb!q:sEk{h f$=e<@NAAAAAAAlMcn>}Q[~&X𖴶6-k}% 3؈}X?zL:+>Piz{J"=e }du; towL~Sݍ5Nֶ:Sݯb6ʐSFDDB=GBotJΚ^Š`x/mJvR<}7> ñmln-Ip"onvܢ 2z'֐pLqٵáήg]ƍwv]a9EZsܘi =M`yUHƭFC"W_"2bmd@CD¡=eP(|Rwč z:~Rkcu7nʹꏑB[!FX_s?l\PڡkMkWL}I/5,B=j)[5o52|>wT5D2%?mzwٞtw@ |:1,"oך35f O3,ouܭi>,"1u#,o?exRxM^i? dHMcwf``8)-fߊE?^z8tm7/{U(+) ݭ/^m@*1,Ч3xo:lyWDϾW2mfS w鷾4ܛH|s#yu761333ݓO? qq VP_DWj{e- =e!T '/ (R* <}OD;Qq{4@/mU8 M2?vqzX!>V7͍[3bɌ{ZٽQni3F4v^햙[WFo9ᵬ3@NH4hHbmT%m 5Jݵ~Q#ָj0ԴլcWoo3dTKW{[[kjn5o.XޫW/7[@J@"1Ҙ vD{P9sg|<r5J,#oO`ב#GɤcεCe1,q8A-}3cQ{A2$?`ב#GܛfI` ~-]LXݚS7:áN#Pg0t+ݧ? Yh IDATz!׸r&ujlJC2ː@bu[=S̿2ȫ.nM0ond3]ڻiPԴjc#4v^:_kͧ ޶Z%xUM?n>O_n*e(CEc-CiO_bJl`]JVWW.䠙`Wg8XrcR\@ eFfmy}==0$ANHKlpv!=e =2 @=e<@Pe<@Pe<@Pe<@Pe<@Pe<@Pe<@Pe<@Pe<@Pe<@Pet͌uuuu1/:rHWz>Stn,X0*c&uܹӵ13;c􄌯'޲|ӧTSUfƂW޻iXcܳIB=GBVڄkPrQ1 YֈZ=_Oz"4&W<}I;,p|Ou׶Ӆe@Pwّ7vl,&+j^y6EenPáO~pĴC=?:M˨M4n4z\#!s1Ddl4d,-/d7b9fk$ݬ۵@ KvݣWL,&(K8cK~\^NIMjQ a w^Lt5~8/{ 2@JM'Q{"Rp~TkcعΞPXkwؕ`(XlO\Ws6M\wt(߁e&1&|`ZGWю9V#v*5W_zchOVBKTFɘ25Ab Z| `LWulͲB_  I*]ZrK؏͡Phtq'Qk[{U}[ڍj{Oˑ6LۏIe}HMcO-O \bJtײV1Geb2#k5ks4^.}w9%od؏Um pYWp?beDṔh;/"~ob,3ӟHHußNO U~'b2Za\ltزXO cMa{9rYMDBZa-&cK3+yp9_00E]q/H67:15͸C)]d{f^;VߍݗN6!{B"~= qIb C[k1[Nx(2<ĵ*j1&ħ3VJX빜H .{2@Jv֞kj{vح+7SB5Hj,b2Oī{ZٽQnYf`2cݍӌɨNDT~GWu^_h().{䐧.gj^y/?{[K e uQMMckwwoիڛEu}f[3cWoo[%b˻kk%QQuqjowwwkkccccMMVh 4FT?m@En2]xƞY+}SSQjl\ovu2:r9p RTzݯrRť:ҩJ9eF ͈̌zBuYQ? ΍~ܛ6h 4- vIӴzٸin9Ԗ~\qK9qr]TT潳1=ة]Klu.*QV:1fzc,Y;; z:C7#CT+ַ{B ;ݧ?ٛbS؍rچ%PVm<$_mMe|;Dc,`Xu^NaI7N7#LDR =r=etԴv^t_{o>}R%"#"t9!EcUO=eӗfQ $rMkk?VlIViKq@jZOiOsVS`5i퍿Z2^,..5rdziۤ\H)=Quyd&;6zx x2 x x x x x x x x #Ac%%%%MS΋L6\SS BL 654ZrbK&R@YwsrCېBPﱵZ*))ij:;dܬ zcM%u4;:Vrrtt:"{h ;O'GE$ƞLsqCgަ}ZѾ-u%MNJ/2yՑo7`zOD$18j.N2a+FZ@V!z̶Aʡc%uKIUGhɺ"T2Ȑ7'j=+uLRd<QToSK{hϞ×GF&;DDZ(*e}h~3ITfWFE$pUbQs-(re⓽fz3dݛ=fXX_1lq.ecCSLNw$pSM%ע'N㢃pSG'"2z.Y*$Qt26n~MzNc<7LYj+r{A 7D\ꆕŖ}kami+qeOׯaqTs aUES"hiMV{)n. MO:/}HǠ͋V=oxf̥q/%ߨm-t:9p~R{z^Ժ%*" 7UݥJe^߱"㢃vŴ8n3gp{~^6W oېmhm,4Z vttLxOhlvHYVmm(S-NGmf7M-c@vy5>TR[=i%v/Òk[4܎mXKV79mԡ[ $ߦMT}TUL}jвw7^u}jիxrҡe~)8жqs/!'(ŖFqt jYn43l2ZS $Um+*R=w#6s+mu.A7־%1 mXǸߗӒHO>{Sf2Q71NjA$bLqk!ٳTꉳou<Iz/XtP&- Q)eRz|cXV67H\~RU@$R{-eJ%N.r$\|T7sK}{i=?h3Ԧ2vf:%yʙ6QQǭLS`STUL&uX챎f3ZZZZNi$۴m?2y5+o؃7OY ×l+)),{h zYdb+VنU l+PE>2͸Lb28;HZT&4CJN󃃃nm 5(T52|]7vl${_Y]]<ChgKVUTΤ^fd]2*2$J馗3s Q1l-*ީD.4###/_u=蝝m[kXIIII1%(KPbWw+ceFOPŦzvҶQ`7)AdϞ]]GFVWWcsXk 7]L&㵗6su6WA홉!FqIkM]k)է ئ3麟Lώ8l  uyشJ6c%Kuirbǖ Cرgk~8q$(oTv"loo^ȘW #٨}[0q~pX6_64uL\ި)ى=Iev2pC)F]7vWWƯ@^ڿc7/Fւql+Et]_v>7.,ց@;'wԪj)I\2Bp]],+Y]] yaXIKH`N3t/p-9"'Nt97s2ql-o札yeJ%'&@aɔ""cbcD$/@!ɞISڳm:|#UBFOSe<@Pe<@Pe<@P +qtlh*mN kҶ&rToSIIɱ!c%%%M膔"S~_B]ua *5gv/ݔ+9YαItlh*կ4!){}>3u 0rٸ^r )3::RTZF'옯}oL fT2oe9Wl؅Q`떱Lɟ3*"M^>B×WWWG>ytսuy.cӤ<2|C暌Nq^ Y)gO_ޙL}7X952!"}3dP&SCk;L6ɺa V<6$zZ'Z[X9б&6=%AaQa6XqK4ڰTjm-T9 : թަ"גlxy˳fČ!6]asP& EJo6^H*/P^~\)Ӫzɛo,Si9 9egO+e% ?g 1(|v8qQ 84@" Ť-,3r9mN3 Y})5t.c̛:_0hrrZ ?How6c~׸awFY]֞A%H"2z.6whfԪBDdm9CLm,7R/ft(SSSCCCCǎkjRc糐~eToSKH>w]$(g]f@Hi Ɲ*u "O~mdś[y&/9WDYi|f ;~<2!}-uoi5_魵S1{_^H+}'[JJR34}u߷ᦙӡյMgfJs-3;tHǠY&-ԩ##'4n3J2醵7i*7dipUY(LY}kKN&/VzkgŔl^2=/NNk̝"͇i,$KcXɾQ@GG󃃃fl5tfcdc0NV2gOפq^WʕH74^4լ~,N ˌZXfDz^zkgE}+u/#{Izg˗GFVW'wvU!"S2jz6&Q;mϴwDž㘎}>n8C﫱8#/_:|={ܕ4IҒmՙMbg'G-ez2uj %YNsƍ{}GaNoGI[Y3}eKj@1bP'+6 ؐ45ToZϊ!'mcjH:gb/Igj\CdjN_ ժWPJࡏUm_זCddjk05u͈l+785t1oI8XG%ب3\qKEL|%J eN3ѾҸqs`+tq+v Qon噾&yf(wK6ɭc hŤk9ͰtŤWmCXEDW[WaVmRU}C>:D"(3qmx0Zd|x`|\O2rͫV|")W䱢ʤa.1Dk}h4*iEK1JlNe!l 2[Ϝi{rpdN s+u)Dц)T'DʬSdΔ;865 2&gΜ90|mx-eP(ZNuAA[?l -^XBXTfPt"xa 0b1f։DD[6D#ƍhQuaBCmSI}G|>_á'LaW<~_e(Nb,Sn޼yMK@*2U9hu lo=^oyղɖ@>izym (d⨈ HnԏSzk2eCP0c`[N&)FK!F2 bP&@Ոc W} G`:*e@)TǠIG[xV }P!KѾb?ȭ4B/ӊbr3R#(8\"#3B#Eͥ݇shlP&3qjp<7R~#D:] [#hK`>ӣ -ۻv P Y gZR,BxZ$Xٮ+t:1$2?(=%ֳ N$ E WsRڏ~Ȇc,K/Ρ=u6#qR ?o1 [0]W?h#{T0az藯}壥+Ƕwu%wԯnC(Äu"Zƍ+cƻ ^[WDx[?hKDn_[_FG8|^}(x)WCRf2o "܃+h52*?LS4?1:*2{v"=q:mցߝN}xc?I7"Zklw?Fe<~*Tz`.\37/]w)xw' Rf׮]ccc+RSssU_SS[(TC"@j0x*i/u+= JjOE/~w~?ڗ"A +YѾ47#c=2TÔ<OOw `E(stR&УLֺO;_[W>fɫߝvzX05V @**z gnHnugK"Y㥴XK]~P 2Y;od=*olz{~H]n~T;CuJMMMMMM!^^vCD~l}e][ϾvQ[kk?cGLjj=&}P2pQ'tU0JJڠXVo#W^ro4]+}p9C}qved()"#C2#d=꛻s?oۯ_cۊ쪛wCh۳nL3eRg"9ɜH+m w]<0x9%@"5RSss"ƇP;hPG?{ODC٤D-_! 5I&gD\!:h.krrRDb\jޟu/=ڼߜ{'FEDk\rKu@#wٹԛq\B B 6˝/X:cGT6y{إ?|c=JR֭MLX45E3)iL&5;#"&Gz`ë~|H'ڟNd |5 WFDMdzą͏sz@ S( ^;Ծ-,:kVdRCIv>4@%eZ%9;ݜ%2"R"KED.(h';w1V_q?SF})=td/ k6IM0J; NVD vӹ7XwүE.kQ[E)p3;h#lS&srG)vz@D3\D:MPίuD@:::űyv.Yu_pEuLPS&6+BH$RcۄhW6%1ݶ|Zsե=~~Bu_nwt{Zߥi\,`+BPGA4@)h,b'L`[㽬2F{KzUf[n׉HMۿXWãR OI]ԕ<]KN#k&h 6>9CS:C 6| "?/V`s{kH߻?xl|GOmt`z&\Z`?˶}|GUc1gʤR)ݖ9}S{m6 (cxT|[M~~ފu/?b] D:Zrid^DD׽x> o!/>ynt .8B탤 v$x=L <]Zÿ 2bqj1G%jc6-{v|}nG6='{^JgsoZM/޸O1S2U"P[1E,en/%]Q&86g"S0P?(x7r3%+/~0RzoH㽃;J؂Edu(ѺROJv%93+B*3ivܡ0ޗ:{n|iD>IјPfn6)"-m"j^/LΉzD}˩hIԑtEV&8FG? gh.orrRDbrhMO`WO#fjbl]}9,MI[HڶD$";P8 JdC4C 6Z~78'8PԔg_:rR/A4Up1U(K 6dgn.i7NCQ&3+LyաߜVd?i` ?'1θdlF~"#"hxovD$'YAcyR[+li EFCv]hu@1cy1ɢ7Dq J9eBѓgkm=f %"t!qUp qkO\m -pmB keD䣛Kѻ䐥i\âK@%|eD%=9i܎& )4nhlU[u2jR/! g2o/dbLnl6Lt8҇"2 qև2TԏC!{ĩhK%;OOOED$غ=Hg>zd? PU1F3[wG.C v:::ߝ;C`%EӉ0n^ sta`u(35p/^jȑ1>dG"v858^N'ۻvVz☪O4L`+Y45G"ƙx2)DK]e'F IDAT2OEuOw% Z3HLlToɐԨD3.D"hE1zjdjfV2hOO=}3dԎ6ёDZ$*DLj"-ܞM[D$ޞO'f:;q)ւ FP.UUVsl߶XWPO^JTplҺiE%. @Vȸ)S@MjT(dOhjN I "USu֭nh5k88TR 3}ES^ͿoRy~Yw666u"R 6dS,R΅2~+2i`A!IW*;yj:uqS#Chs}Ӹ]+""7<nQןZkxeRg %E$uo;uLڗ_JR~x5M)3LC!vVw%28FHd[a&YzY{'svɈ5񛥙x<)"HdL<^m#zJ`w6qou{T"4p3dt̋`<[@M7~ٝn.}(rlաLۖIC$m|tu.qj$p!Z{v|}lMdhnRH$O5G֯UJ9X]+-,,84-r6/n'l#"ȑC=&Ͼ?ip=s lLD -B)䖙d I`\l4#Q$2:Z'4 3+Ԉl#_%) @>&XʤRSss e/L&{%2F3-&''E$9= @>&X̍%rd'\"jɐ`Rߩ(0<(H@iV2M͑HD%0I`9hP0a؁47N%(`gȅ;ƫ*$"oTmjbE0F*ݬef"Ҷ|E7D$Լ^$s Jf,،lZU (Mwx|tsw{`os\uw͸H.`kkW;g 4J`Oeɒh2bSK E*)ϛ4EY45E3)iL&5;#"aV.F4sJ%22؂lTDWpɇbL6 ``<\S!CPP29t`א!ɤF"m|D3p\~` Z hrP LdyR(zl_<)"־mgp!aLܾ v0վ6%3>ΩSiʵ`g'ވ'""ly&3k)Ҝ=?!P "K0LXncSX 6D3N"D6R;3qjp<|=N$w䏳TxÉ7(fvN/"ej1"JQ;312=іdGM2ek /NZ "`جͮ@@STa侊1KdU3kʟ{ޘ3`O'ƕZF[ܲgi7S7*9Qy/ Ʒj4*1U=c^} /^nY1$fY[Nw[W<*?L_5[6%1 izP1[;הG%ӓhS {ut/heBCPhh_\D 3'5ޠ.qp$V f"b5I&gD^HK~*YHKf`b-*;/8U,S2FWwfxЎa-^gBC撈lX[]>;C1v~o~L1*/mD0(P٧Cvi}nF/._)+_mx5Ux;ƴE4+1a"=M&)7f!.P-L*TXHeu %՞{Wׯ_)D0*OM+1L[[FG\'3{;}5ѯ jX4+|x+(Ol*3>8m HfztpܩLPsYz rScs"_G9ZPK+bUG7 O{_xᝦ^cњ_?`<٪f)J`P#& E{ڢ=2^D:cuN};s PP-؁x:1& n<(8IM%*r[/e/}KEI /0Hi9~. Yd4FfM3Ӗ\TqV2$yT,ƈZs*DF\4e[-іN[>P*~=.__a5@rVTc43=rhb2N:TVFp՜[@4S5OIdR{.Ҳ тbb uNP+elQp"TJ@惤r.KbGOO_lۻٰCSS[@f*T"㷩d=DetkW=` (y*e*g\9Cַ/Ѕ :(1R-IBeRZ"t"o'}[zDRCZ\tEYYU+$Y=L[L?2U,V2JfrT;Ͷq /~eR/&EvqL[Jߜi}PRry }KRa6L ]; ^/f2ZQ[fE eE( j~keR|KϷ?]r7ѣ_\q0ȑڴx:e\qlg"cZXX0Wx)OL2O&lȖ!Auܒ67Ei7=VD^wn{Edn}D^py{j_S{RcQuvhW}xIet;=pجrؑ#[*ޙM_qiIN<պG|;\scr7DFD~__.1L[1 c`u67~hFd6.hsPO&(gYL1K}?0k7{~Syh6Vʄ܃j8{ Ղj}X,hEǞIduX ~786/"G(:e Kl'dPKp  k I 4.f?1v{j,ߟ_d1i纺7jpLqLY2?=s؋7F^E^s7#"7xGD>V^zZeV2sIYl]BE9B|)LNuQ|=<܉8̱G"o?wt3?`d^Duj.QS}TА\iݽ *stLB|jar! Km=cd2ƈH8rP #qW [u|}{Z4=HdbLVGGCL&"<cϜ2hhH*჌c{ebg.U4Πe2nDY$vjjnNB!ѧ1˳Q;e2oi n|y0y YʤFFf33""3g5Sd&F"Һ;p"=>2X,xZZ.YH}R#Sb3MKw-10hjD"+I G"Er#d P%Lyfh(!‘-VŔЂ~@K{{zp<8MѲH&[(lpz3P2sѮ=X&Y}@\]Oٓ8vX BԬYӾ:<'"2{o()#{u455ьdZ7_M*s;}!iRfJ#A D3Fd1t~hT 5?pסO+XW8>4?~2J.<``՜26mzinosvkC1K!(ND*`jLp$D"ӣtZ9ϯj{Ynݪd'ZG/nv)Q\4J-}?]mi7~Kw<6B >-Ϛ5k>Ӫ̺G~Y(a666u""27O0"R IDAT P yֳǵ vvv$Uzߕef} 67";xZ$%1ZR:1<ͼ9-PI5D3ڱ5jGJU<YL %E]zr_"._LbږP˧S=m6ˤ2bbƹftV(˜ȸ +0:EF^Rz682"hhH*;`2)fM{sgvs氈ߜ`yZ" +Zy 7=;:߬ \6c/N^xRfTX|l;\wk*@ @"RSSSSZ#TʱRSo$-:vцhK@D2ӣe2WR`Ami*DbEoO;:2\xV`{'F&:QaKdD],37ϟoHP\"QPcQ6h3-mO Ãdzw8!AZ֥Z{Z Kp{w0+?eB崢˭\.#2=LJ=nK\ .̜̈xSLA`+ڎ`*aE(I̦$QvBMN+7Z#yaxB7 .i<:Oܞ5xl:mVϗPeL5ոX&<34Wɛ? alRMGGCq>x^DD׽xk e>Nb֘x9$ɬc&;ʎ& Z:-Ѣ?7.o-"]{v97LdDhhljjND _1Ñm{c,YBٖe[PW4.Ǹe$Њ*33""~~12??oݺv .}`yd߁ȑ=`ucۙͷ}NjG~fM/K "blRD7}z3j^/^2_]''A̚ ~fD!*{`KK2gQ5"q;L=ڙJbO{K#RןZPێr?B,]} Vdo\Kiu1T,5&̦$dvBsKdpWO#"ǎ [u/=3cM\k?zK""6Ńm7/᯲;[U;TPp(&W/x1%1|%֘x9$ɬc&;ʎ&.vl~W߾ҕRvc ;wߺQWMe !]YL>]+(ID6huCɡOvm=3./bt4qώUZt=', 家.g7n\'xO_k6eڏ޺"CA]"rcʥ70TẌ́Pf׮]څ OJfn&ܸD"v(RfPH8rv25+dP:p.D*-u_{vu""wm;ƭoD6dY׸ٖNxx@L~Kg t(QʾHj/ ƦDMÑm{cQf\dK"@޼0w}H*HKw'RbK ͨD6Њbr2Ȭ21"gݾKWC+~[ >WzS}i:-os_(`TI yN &ql%] Y 'T^\5Zgڇw$>^JlN+puՋogw(RM*h&_U0[cNadPu.ܳur>ፍ[oۏ? ]ͯ|gN%(f{zIdmGZݸqۯ^ -_Y'۟mSk?}"B_YW:v2cccv"Pb͈]LveL1 9K-=o^9?J0b]ً_n7:F3ض"&) ڗsќ&eXADpIjScYPG?{OD9=X:4M`3NPDTr"=@AeibbU3J jR0B BzO#3Ì鰌+gk:s覒qp$Hd 8B`O{OY VH=a5P%܂PqbİYBu<R9LBtEUf4{W |P4L՜ MI<ŔK4~btfrJPWApgGutt8=`?"rwkqbz RKY }ݖ[c/| FRU|c2nbPݭ{q=ǸZ<':!5 ,e ZR:1<-N$dne1O20 42>[B:-+kc2#ĦL_ynmriabT -!20;`O7L'7鍶HK7b@Kn958N\tR,a"Fsz3ODxB`SkP$^pz \P C L(&&]XX(8VJs3XQ 2J]8azwtZH0Ƞ{[xE 87Cixz!-[%H =~GG"q`B'R,|a jŹ*A.hiM'҉wG[8LA( {`k0)7>ਖͣ#D:m_1!ʠzaU(-у- 5@-eP%NPs(&W/C"xD['%LOOheVN' [ۻOW='fڪebP Kbg&N MD$<5Q0.Cv$2KALfbd<-"{#3ӣÉĦ%\Hu1ܳqV}fޯ\MDf(-AtjP&P4{v1`%IGl={*x>&'V6Ni-߳[q sqD/x.!;}I@K!(ND jL_IEGOHY|WyW[nUwò֬YS 2ޔ,˺t NroyÇH7*оv|( looE5/҉D"7LFk֬qz0 q (LiYYO:;=;jS!v.h!{Ɨ-j5+_!)ZHC!Em[7`Ldc)2D{{+Z:v˩tjӫk+p\ P?'=D8PFk&2¬R`Skp|<{o޳8%=e8T՗4^vk0ܳ8%8Ő"<^r˦G{{{{G_ܷ{P:x-TQ`uHd@eng'ャ$3=:8^:9i*"SIfzpBDZ# eg SF$۞O'ycyN'$[%5=Hۻ-gWb~+eD$y{{-k=ؽ5Q[UuϪ| 3Km={ܸ5@q>@Kg3Z%E$=R6ݳp> pv$6ӎCeY _B]rqLUF326#!W#2Ǡr;;=*UŜ2:te2e{G&FD$2F2je2399999(|ǘ85@h_gp, .Q)w$2 *6& p|hY xKřʴ̾>1Ҏ^:njp# BLbJ#j/p78PƏ8pT8ڗxLb $:::m={Yc'e|m@\,sD3Pg;=}h_yiV_p2RGGCŨqb=J.2Bg;=оZQLn_jd̥%2/>pA(d1݄ҷw_8gWa7ŎYsZD1K\Bsn^3 z=!&Z\r9mBQPCϴbhRnlR5I{TIGTU*oX*zSF Ct_l!#IC `KbL"Ddii hc$5##/ IDATJ0$e ښ|08t\ IE#CF0P)#Z@ X @")/@Pb#F@˿E H@ݗ|@R$e|@R$e|@R2%vk\Hl>DN_!DbɥTۧN OF>z "KKK~P27/32"R-?3V7 -K}v|1h)S{spRأz;i~zre{eHҗ3`\-L}Vi\2e=qy41z:?X59,_JSK)h,7&#kIL܋ṳ677;jZ}1#ΌA%,#"jf.F'r[oO#rZxQ†odQ29(lhi?ǒ0-eQ_yۑ]cĒ4zjyi<`;cKK޼x~R=j {ZNT!Wd -eӟ y /~!Xzpt iA&G~>0-eQv ##=z4#sZ,|ha#geNNL`4S-E-2""3_Db^엥y&3.ջ!?m 鴰_yM'O /cӴ跔'O"#G]&XfdZ̤<}4V{"2&-ef,Z I.y$h351S$6rjzn4ˋIV;}}ƌjH,881Cή s wun.FF~{FS_H}677.M$޼x?տ[U~/v)aC]y:>3vZxnvV揯k?iޥ!`sWrbC9g391]ݲGƇ}m*+{F3"wZv`j曃=՟N Փ7M])Z{/Db~z'N0+91IUߝsIwuͫ4FDs0׍&>h|\/#)ڛ‹'Ub? 3jCmEEwvHcUD" CHd~)e"21ZHSN0+91CFmN'b"RX?81]ݲGƇ}m*~:F;BG6GOn=N̤$2>8}}RFb>KN&vĽMڕb<}ŒXImnnv3J 'SOɉ90=2>kWi>/zs#0a1r_q3͐6nihiT#܉jQ{W ‹vj7HswNPjߕaU;-TEb֟tn#Û}mvpyT#OS3R8_ε7R&&-Xۑ}*׮4.k~XgVm ]ɉB7/ D-5qbeuUA[=<\!Ƈ>Σ@ 0@UiT2a$v%'f(E"sAu~)~F7\t嘀IxL4@h92ͤ67S-L=y*/Tjs!fccxK>XJN{dND+4A0$Փ'/.#Gw GR&k2T1cRoB= 'f(ٕή朘n#ݾ*=V ;"Yg C6777 />a1H'"'fXܕaaZiwuuϫ4Fdbf? 02b|u[|YHQH{^85К>L|ƞi~Yc `"CNP+91tO5g'ห[pp12 ;WG\=>h! n]__]q?+04HX'Vb+]0j[gsWrb9g :u!'lԭ~ҵΏ7\ wup|&wGy$h)PsO>EGbLGHcO+'fݕa~I${t;'ห[pmp12 ;wGH{$WW΁ h)2> )2> )2> )2> )2> )2> )2> )2Rb+BԲW\֛v0w`;Jۍ:ꌿz֩b$eA_v}T Y5Iݮ zY2[?R2sOUqT:k3)hq2n'zwLROJTėQ_9@KT~U\*Z)55PeylRU^DDDQ㭑FJ4QgKJu;ַ~GoP iQˏR_zr۵ wW k;Dq=j"Q{QDJI.?K"rT:k|lּR׿w@eh)`t̨F4Mͮ7wrײLf K@޾o{S*"ʃomRov熴nhj/`|u !""R&SQ{Qq7Tkыo7قd3ryoVC%2c5Pxbh*wx-I+"~G,[YUmtr@x4UdE%>^5a&,g5"UJkYU+)-{oH;*V6 _=o6nED/k(mxQQ&;TUYz;!FtꎈvqYRCgi#h<$m*jE?[V6HJ}5a]o4k}mHU@*wxxްtg3V5߬{Gfnk rhR;S&ES"]^YnrʴA^h)=g_rL-|sKMڣJ^X&yXJ"0oRbB~7D≤ϮEDQ/ݿ=vn={+$H(Rk%%"ыooؤL۷ koRROS2iNc90JDLG}UXf9`kC݌Ի^ieռ_l݃A~ݡh*w Ѡ?Epb|Pk%*%}B≤ve/>SCꫂUzoHE*WYzv[4D(˜;ul; ~/5[fl~%$/fZL=>N_J26zr 7ZmeUh4_{zn17gS:5F` c6h۵|v˽sdN 0-'ӹLR&RQ.Tn7S(Lnif ?PDLð\U>~rMEX,C [%eJl?,'+i("fd&:'o'OD۶>]lu}}wfՖT ky) Z@ Uc4 JO ESQ:k|LFp1e Vc[|iYYR}RxzU` RQ`5NVIٞsDY)=Ɣ-e|@R$e|@R$e|@R$e|@R$e|@R$e|@R$e|@R$e|@R$e|@R$e|@R$e|@R$e|@R'eΏsfgWs}x֭[fs^ &r<6}"K ʟ8wH,깾,o?qxpˤynu^XyXX5eΏWgoMr-'ǫӋ́䴫4 @y9NoE+;GggugG;+ )-ww,+vqJ(89ݞHbH%{DvJBD`2a?QRxuz("+Gg^/ܽ5]Xl'!2^ 5~O݅VDD 0pw lv3ZWX}CbfgW-Jbg,U4ǫ=o/yn--j|j6D/el4VA ǹզ4yr'=G=C=l|mVE|bXka4l?f=q1&YNmmR/V; [z{A"$VڊXiZrv-sVB6 PmZǍ׸yj3 1[љ!J j 1[j;|j9٣-clT7عvm_Fŭ%9}efW_mI{{wsw]=]XJtǾ[e{c#ۭe4F&8;7=mzK00Db=]s~~[ݴ6oBHCm^8;IHq\IU-42Vm]:̘m@J-k]`,i8v2 Xm~qvXVAK}y:6 N|Ft0md#3iҭ}2\gSb;t=o1Lc\6oFO,PӘHӰoFILGYJsIg8&Y(0l6Z˸iAڃ!s.|-w-Mm|F-rcNT?;dzñy4ѳWQ}(vps&%9???>>>VWgg:<#!'ze4U,.8hz1^Lb׿}p|JqcqzZ]6`ӝvCARƸɔ~n7Cmk0΍76wǖ4̐f!sw廳Hqoql(^ \Xu~lC;;YiY[|clݗleeꃿ59sY?m#rZݻw/_|:#M9Ԕ}[AiN_?՞D{wa}wz(n!o2*ov  'cU !ϏW^7Tfoj1+\h+QbK3r2h!^<8~2CֿnfJ1V~v  G.{-Nή6 ~~~[^4R7[o8:k,k64@ܔdziQݶ7c=TY_ jofP!'/s&!a;kVZ59]H۴[5F9\&nյgkbZҿo/xXyga&u[bIbH~emm׵4͐jVAY{|VQlU^'vC;ɂr,d3sN>6]0εx6%]w}vv4H"stve{K-V+뒘eEq vlnNcTgR֥֭e|iQ<N|_Wͭel|r+6X9:;YG[9:{ ώnY_O;6dže@ǫ;8@0/[spApHع>>aEdeL_ h@7|0. ggG;+ ↛ m7~!n`A{}{W; - IX{w.|w""ō߄B`qCp2fà{Ϯέz皖xugyv~fgmk(ҙ}:?έޔc+Z=>o)ynFQD|׫So6˦Wwd.'c|IHqd41Ai^i)duWEN[{"RܘnFu˺d϶|1lVrw(u]׌&29 ̻w?\6jCףK 0B^Z]" +UGG6J IDAT]>=^u) kW']/BٛzyIj@,]K8IU'in&u5/ެؤ8]>`@BԺq?Z1іo3DseY@+++4mkuնwX*/}+ur^}]E\Uc+Gm٫f{snUm|N9wEUdF5c =sF4_ Օkn}ϡ%G^3]O/ ~z^zܿB^rd]ۇIHffN._=4t]Fx")c|.rdݸEI~:tXi'mRg'eڋws'֗H5H/(MSEtlnȰf^g,QH%)2tGgozݝ4Wz]BZǕuJ z8m|jl`;)c{^ܗc]]O.)@Hʘd)FJIm|/)I׸[mF7ؾ}J8\:rʚw w_R챫_z0z?¯egI.ųL[t [OMbzz5-mޏ<1`g?(y2Mh:;wmtU367fRzQZ{:=t )c'N+R26B8b>쵔q6;ub]2m??>>>έݍ~t_4rF{&ҧn?Ax2Gɜ w빮uݳVW*2-CE!vr\u-[>PA6:T]Z4::ߔ' 02EƤ8#u+ZӧQj6p69vy6ub]vCY;'s?R,x6)X(~8+"r[jc_,%6{;~_$6U9O觴\qmWLK4}hwmf2Ëv˳#jQ?aŽކHb.>V5õyiwpO G CVF u:WIffw?nZv2[V qeS ׇawe e `Bw^>;;YYIgjqoj#eyq+o]ۀOÿ~ _RFF:Ѳ{ h|}qڦlO+sv˗ w] MeXmi7aƯd^_ΪSJۡ8c6S3ZZai}ixuqO$+7{wawC#jﺧfovo]NE@8Pw~#52FݍVWv$6Yigsr~{f0bY[7?DDxǫ}~"Wś@Ҋ~r0v2abTb2GynvqOZV> X7ں2ۆ˿T=oȸs]/Ǟ|j>٦Wlv٨"@){l<,*0h:}U؝:XYmi;6ցMj.=aP=?d]T͖^{]$-cJlsplՉK71?$'-f,+)swY5?rt(JI$Vn^B_e,l)Mn.xL5:owl뀤?Gn^XC{Q:"/*ٞy\YY)XPn_mmf]w\U~u*^ܖc #B?:B NաtUT׽Ύ>r~|m^.BYkl7غu}}wZK8 4=[ .[UQ(f7#18_-BYC9Lmꬺl;?} ^1nQ_D9"`qP[ʜL`[9i':gOlsa_* Zʠ_t8Lۀ tV=j+N>]w8s_mW|ﮫC/ЂP)0|} `\III.ӟ$".UD~wArs/NTK ]wE?.H7~|~ĽZ&"~%vA.Z H@4.52b$h")aB$e|n'"Rcq -e 42> )Х -h0")2FI/NTfF IehJI;92@~0GTSXXWYQ.3-e"8]; [}Du9EuŨ@Sڣ~dZ 3T.%2s.ddNAI S32BR¥3BFi:"##L FFX1:ZQR djjZDbɥ̄w-e¤vZx|j|pc]32BK9}_-}931!"R;-엫BZ7eRȈLji>""oh,G-ec&xu^,rrR5YQt @>"K~C(OBQ¾ a/^~a _c?s t_ڛH,9Lq(#dڛO"G@E^aM |.qZCBH1HS]GIi$d"GOĈed @,EbR3m F/#)"FF `|jFFHtU;}Z=)WED$%bօb/`S-E>a%xጌVo\Wc6mw,T>/@>HIǛj#g32BRƒܴ 9? _42*c}r=b"o~P{E"7&f~vRu+\h)H -JJD&ecdd|AR\JqJa}-o(˻h #Ɣ0S^˪)5I.g-UZ8AF_$e:U TIff2TQRԳeED{ jߑtuH2CLEE$:uGD+ @HctW*" aF:&Ph)irJˊHB&'LMV6\"#4@kZ~a^T [yMDypٗ!B:&h)`"zI*>(Ϙdd2t0a $H-eFBLRJb:@p 2*Y"@>}.l!)`WEDDI&tϔj>}p @RQ= <F$e$ddG:&} wL@Q_^wZL} D|~mrqb8bA.fdT^/ij_d0MR0dcFL2JpQ`8&d0TcFRP2R[UPK80@T:w!3 j=(ʝ;w_\\hZV͋<[+7`TyJTJ[YUEI.[TJ^욪$34S)o/.y.`Hnj$eJl^˙g="h4JSJp*ɥ*%Z/iWws)3 3Vz{Y*WA_w c}Du9E9Bu9EƺϊKzFFY<F[ټ׶<xth]5v1n*W(˻T}h4.+"CX4Zx NKq"8]; [}Du9E9Bu9m?Ԙ]uW$wtS'YU-qD.f))ST.e%@x))S^˪vNf hrJÔ(S ~cT2lyBU5Q;""5Mn'v7#UJYUDi pt ')M7U kM8ײŃ4ah۵fTQ4M [Y~Ɣ'HTpf_jV)l5x'_ZVDol>N4,'t"$3-芙EpZ4;3Dhh<"RTh`̖20 ah=0l޼,] @3`'Z~pyޭL뿊O"? Jtu%hb~TE"p\ fRFLRͪZ~a^Qw4&_bh=0 W٬*a:j }1NT}~@+1p'Ixpwj{+jfdcDDIf5J ɩd2)z/i]יppRDb1)ŠOMʈH4Υ"JE$]Ȉir5O~9wË1E:rRl e:+_NOzO&&DDo/BQ¾ a/^~M\w>~w&pm ykxRR*/^^L-SQJz` 4/Ӧtͫ))3'dt %IJi{+I&b6*˻9Fޫ.^\\./uu@@ϥ^ M |.tmħOD> mdAMʔײypC}쎙?uk7/47BI&*!fRRxH2KKMoė5}_I^eDD._e(˙SmLNN2.ҏ~# ̤ե&"fOSwD4JXx.GL^ޑq b`&e)"3)39hi8U*"LMR.0n*J+WWWryYtae 5-U])(Ӑ Xi{f& -i l hh*\Ϫ ja} d1S%@XA`Xs夢4^Q%=LA\^$3""a&)"]\Y'T 쁭s0d4JS4 C<dt&fUJDda"HT [y m]@AO$EUH Oʔ/J2y}*Օ/op1hn*g 5ϸv} yRT!}@`DSݩ-cxzwb-i"$1D 6ϓ2*,řZ45/T0%! 1}oTNVJ./2N| 1Cf׫y{m[^ZN- ] H=d.H)c^[cf,LxM Rs^HHĄ?ysK2bSƋz&tRX_k\*Z~UE!+`K?7, ْɛLjc$5MݧKMSMFhH4$լ}_I10V%~zXRR*^\ݹ ʣl_\V$x")h<,-\i511WIO.Luxb IQ+j^Yja?x^T3YUI.?vXi\5hHc1k?~m=#,gvwww3ˊh풝UDZ,UD\\V1 @鏈|vÇ=*#&~8y^",R"x*Z/-+"j$"㤈_{P J4;<<,'Ix 08ǍU%.y1FnJzjnV&P' IDATfʔW b#F['eR:(SWNFR)?xW i`я~q ; IJ^vb7}3YAUEDypmfRH4J^ ST8xVɘqB!`"'`@}h۵fTQEDD3e)EDRʪZ2c :X˪$3L R*45EI>~D2/$hHA61eԳ1clJi{=ۈtSIETMͮI>`Jټ*$c Y D4o}4̗ \RmIK?8pÛLE>ݼi-؞8Rz%sHX޼x~y|k\Hl> LJ^炜jZ)(>} j|G@`y})z|k,gO-399i1߁>S@{936){j'U[o^r7UogR UV}sVٜ`Zi-x8LV4y#SeԘ@o&Jey)_~6jo.-o98H̄r=2^??~x*O荆VgB<)SWT^ˢLS6`z3RrU$L^Ke^,rBVQa4#2d;|Qd@Ix7];vAe/7훣w.8X; 2j:̯H2aS|ry!r\^Ȑ;ӧ)}uiݶg'nGDGwa,1G.G.G.GX](ޭR)l꘶@I.?^J2m##(b2MKflxw0`d*6z%>V"oG""д?v|/?ejEV(rΝ 4MSY5$3[Ah/9Ɍϓ2eK0gVRì*ťLY)b /,?"ZJԘM`P]P]}u@tkk./ЖIGI}'em7$լj{h<;l4{&ј<sSky-UOZB@0$V)ED..+""DRD+gTJR)cݔ_Xw L[MD[I޾o!ϓ2z#.0-lU Rc(zo lZӃx2/y'eQ6z7/ŗ5{Pz _-pZç12' F^vZx~BNMv.勵\~6J3HN-͗TM/GZZiO%[Hʈ>7A#MSR ^{IY7O~97CJ0 ɥL&!^Ʃ'sV̥fRC-WŮ \ $7i̘$)SlO@09w4u4ly~hi~0@IR U.{'Y*Jiv/$e&ɤ݅lD05Y%yޠ}.*oƔKI,ʐY UDDQw\\ԛ+JRB45vK=R1"T<*Wrq5UKZ*n.R46?nU00xV^eY[#hٲ"}_4}-@x4"ioDDbF4Wܙ#iW"U~a$)M=[ʫܴٻ=ߺP9ci9UIBыZP S~xjhȢLC`P/1 OԐГE-!:$TTp{1,@[wS,$;'-~8ٖ'G7\fg6 R7/h @D3Я(Y1L|l9n^3Ћvxym`_߭ڞL,2ς^hfIw,'MLM-[oR'PF1L3he)[s{Bz|Q仵OͦH6g+ۚxC?+2YfZ=Jͼy}+e816b[>!EZ k-#ksۙ4-("܎Bz'2%2>n`9"jiN4nd;EʸBxڢ 7㻵} g $h"[N.׮KCs}h' y(LDį @ycS/Ě%h5g|dwD<ƒƔw$2jt)ﻟ-B9Dr_coK4Z”تȤd (fT.X=55R<)Mp,X]G6̥֔Psj5 Ï^Vqj^OX0|2MI1NtqW`Ƴi|VQw z;?.CDݗeۅb3ry|{[c.%tQ)5cuܝI/1 7)iwғ ~`HrFnYg1A^J UAzuxalUUwNNM&&e.'Dž]f%)'̓(oU|pwe TwOg(:fa "eÌE1Ns#x=*5J0iz.C"^ Hll5Mߥm5)_O1*Zvn#A0kR.C"in5&Cޤ̅VbC}_)1ː@Jָƛg<XgA@3Tw& m" er1wN*6iHd. ̡1V$ tpc3IO6oLU<0igr @o:w_;dwbn гMI(y<)L``Nju~! ҁ2g " ^AnP;7]-"{>["y]\۷ջ/eS$.tISD$j)+g&l ׿ Kc[k!l͕^EPά፧nm-9 5>/no;2R!# 9 @ݠ wf o,ua&@^Tf%ȜDn&/)"?v-"L&/-l!l/#I`1gj)c̥iF,CJ#]nC)͙"ʶl8-e[""+D͗NC%sSGvSS0>FRĂ8sSIl2[>m%EZˊA.KтbzsGZ?>Kގ~қy:L$B\5_z۴nk@DZkeSKfNP ӌ cEcwKD:[2oSσ4C ~~,!C\"eڕ#"zbhn-Wۻ/K79[5Jo2Ŏa~qۮ__grd2XtXK:0Fûo?.3EʴNx^%sͼ̉Q1^"ZvƎ+"zƌc_:|m=7wuK$u3{9yvR$/; nvVu}gJ3`k=6޽w<y(UEFӗ^GD8`W6^VZk߭-GDԷ\rX,ݨRzdHIUc;:-QX7 f陘gN4%p%s+9>A/ݘ2z`". e|g&k"Y]ק= %^YJC%ɖnr$jrDKD &u6i^22OWҌۙC"v3`~K- 30[vVWE<*05,RƯ]9Z1̊qP>窖ӦLqݸ*?70O6X ~jI YXh^II3:B/h^߽3#SJoieQ=ODT=JGj+13j!R-P-lGDDT]}<=u+99116HE3+E1*7 +`N1V0 2#2f2s#DM y8ArS,iLt˃ym9v0v gkgbh̤Bh8BQ‰} Ùp&Lw2L{Kʂ`byycz4lO~42A_*3ZpnR7EN+5Vuv~lBAkQV-DZ ?MYH7ID>ռ/1!¾W}ݕ}ȭx, vi.+#eyps ʄL~fV.j+*"}{noowjNo@iclw)mORͬ-GDF212,`ᄂc;VD-.߇3h3(ajF-_9yg~X?'?3?`-05گ]''΃kj$ƔQe| ~|`cyQ4"~j>4Av_#YD\v^5pVmOt]o8Nw3em.Ngڋ$.)*DҳkL8g6LE1zjdXvڲ i3$PF1Lsمb331nze;?\I V)˲QYK~X=t0x }r)sql˱EDTUL٘7y(%J$;3e_Q bZy^Ȩvv6 KHjR!Pfi f$A2$2hqe]ݳ$5Iy(ӭ-'ّ'3%v$1)!;2#IC|N9޸ɱ;deHd1`Ha(-RSbG J 0X㊘f}))#Ivx /X"sAB d4H4>ޖ/C@berr&i/Z~y{3i>_q7%RX^6?B\J6}6/(4 >qa"LOz)7g_+h<DZeX`$>=4"ٜi(⻮0 $HaL2~!L?J0h̓ʸ Q}MQD|tnٞgs-z@'? /fXՋ6zHL_EZpsbz2Ȭ7R`& GQDD?DDlft? 53_rDD_V(Eьe^lDfҒ ㉚/&t>qF\gq7ws<UEEs0!LvNFnA)Ɖ.2DlRLxH/U -˫g&F"`l+P&aB2 '/{hkk>6y(8/2X*63eaGDvmd.D|HM>F})u+F]8.#4Bc`-[oZ,@'"&\i][r-742(؞'"?o$8lϱ *"uΟ2X.ej{}^ۯ<)㻵snNWtfZɶʈ^C|N]rUl1"?@`Rj-.  K̈  RDʸ╜溳WE3L0E}eʺ@3+սӽCɩ" b͔&J/hU)ﻭlowSDwk}e_o/VӘzG zc$2$%D2Яf^^tU*eoneYVuLnղmI(eɷU(fV4S|߭_9Uѫ_+Wс U03֤z KdZ9=X1k#~'3jR x^ uyFs Kd$՝^1 e!3H8ؖc*QR%"ҼlO|$;ma_?ټDFD2@bl%2]}̧8VAJ7:E izsGQ !}KeBخHcqJlh֪Wa¡e^2ߧX`8y+Թxqywfbl2JUϟwNjrDKfrNrE(ngW=o]S+\>m~륽GH_R~ӟr 2q}^FϯۓZŤxsg2{z0D\@9V`hv刨\\g# ;%ifIw,dz Ƕ*"uǬKIsv~}Qc^J`>ޣ2b쟖jV=oZlS{G[8Uo޼jw߉wC^h]H"64`_ՕI.vA$4̛˃yə۶Hf]X΃P}I,2==\@LrrDDr<*8O֣vv=0^ w}(Hl(#)"~@uH蹿wz#tb Ͷ2$Y D+ɡ̳%2"upxai)Xaqqvf`q ,CCڡV%dM#!<֪m=pYv*#6;lcNYkQb!XĆ2nh9K޻7o]{DD!Hh(DFU%'$e2vݾr\2Lf [6{ł;l)ObX; B\/}(}3[$3 dǯ O+▏-GFS$Q'A[tk y LsE>X&2 eZMODMD쎈5["ftrOa$dxkxW׿y4vIe&2$2>8"I;0/*b v?mgUi4}@يMӼXhB" 1[DZꊻ!2AR;vvvvV{ZdҨe??j\qHFPxWXd1@ eyp}Rp$rODkpQ1)H5, Ҏ,+cʈ˫XՃSSݶp|/$xpԾmׯ/5H2ͼ7 vUUyt礒faH2lyz4)@[?ڹ̞3v@͈y3cטּ9Bc ʈ^C|͹{hq7D˯]9'(I;)1" eF鉈^2 ? d1F erAlY5H8H$; kr̔`DqܸLƴJvɩj:#I%r۹R^,ߞoo=0 bD!ɡ @\rrDDs<˱GnsU#5C(0j;'dKg%#C(0J1L36!XW2@Bz#'lZl>H4SC iL\~^ғ͙3erE&=ބ! PϛDy0QU E~K9d 1QlJ|`fC$گ O+▏-GFST" PFQ4"dnHZMODMD쎈5["ftrOAgjD86֏n@mgUi4}@يMX [[[$2eF9LH9 F 0΃ ʄ/G @(0˫"UuED1Nt. h3ceQeIWoyWEU_d2X q `Trf_HE3+E1*7"̹Ő&R`~$2X ` *eےmMy`||~SS#l1exnL +""Uh c`*<mUl-DeIN$N" @ȭڞ?5n%ӽ's""hfITc|q7&2~ߐ17h; 15e'";پL}p)ٝ Gx$^P UEFӗpDp@vNN SD.+\?|&]v^_~#$@/):&y0c& xG6ΘףR@"d2`i؞](6''se5KeyzzO`4}uկ~%in  @ҿB(Хxmz/nrDDD͟l B 30+Fu["iCًoOrb?2 QF̛ڂ , 0q `} DlTcA D2T"1R ĀJl4@\ec6 v28$2$ f!$ 6 9e)HdKX1RkDL2Xg$2""$c׿uMXX#6עb as-͵4n~M@J!@Q)'q7av[[k!lciA  Ee&HdB(u@"HB en$2b%q ը@*ҎPC"X2Hz @ RDN} )@X?T HdkJTt:v;5s:g$2uE @ztk׽DFDY1F- `Q)__E2{r_aEV׵/όݸ5zR -drn/5rGn2$2G @Zggҭ/21O+ HηH&f3_Eo]v]?B/|H{%%?+@%4Uo"{:T|gq7աR :w/n"{7F?jU,+t$ݯ {].2X;/{77VyLfO[6jcu>^f6_tvnџ;ҿ:<62`Njv<..{"nׯ/j16jcuk|W(ǻNm`ԿT ~__E2{r_nmtkz~]իyĮTzwc޾}pͫ?6WJH(g"k2"Rfo&He2q7fctE2Gz4vGv[eV?NWJtuvv\l_o$VE$+ҹUoKֿ߳c1w3z7290tovv]}xƮRiKYvt^:8 {}c^{KkbAwwݮM>c.C;s{WC Kg#[ήqvf,b/s=y9}za&_s?++@ Dk_pWojޮusoIuSv>xlo6{m_unvnׯ/>w]%;okN8p:/͕l?"n}Hj5&l7_}pX|?mFddd_k,m_*e "m[$s.7(*C|^9zpwK:wa^iPpK֡w{];.0q/8mh_gEmD_?>GQtSo K77thx,+@(`S%p:žE+]HУirsQk|x'noCp_<CAUsx(Og|> NS *; z+@(`d2̗oț7Nj5zެݢӎ78 {g^1G֮̐NۯDyR.!ܰI:OdSPF&?F[a:ڴ]  $fĿ2(vS(HSW0v|$mɈ{y7۶dݶvC1nץUon KiK-vj.-V*<ߤSq@&M~=~l`m_EWcwhcmy[۬ >tHݩ'^N1V<[?R}xvvv?+6dW8lOҹxvvֿ!E:OuXo`:NkLF~{YD(d#s&WVI&M 9hLVs/n닾k1Woݘ7̀]^>g QTlU?o7To\BFIDATWۋBO #m zEܿT@$/s/>M<^֛` u; ֽI=~f~Bxw~сi6qXgw7c캾[)7+@%`:wN]D {XslH &2RkX=n`9bl$QAgewDsoY.^P9)a[rR߱~⣙R^WU<DZ-p||\,OW3onnnQ\^}]rE(] ݾewy$2{ifI8Jw}C()2X&1^ *}[H1t S>Hьl'u駗zK 8 n{pvv}hAbtSтх7)E /E3L0E֧{ИU "Z-i><4CUϭ'";ف=2<˫=v"bbc@`?h8g[[DTU{b6j^σۼ;hw^+D Q!"]8Gl4}єWw )fGbji_cjwWˬ52 .lY4yi]r4$^_xc?M!s& 8Oy,r-{uUw$  |l92~, 8m˙| #"d٬lok;ܦwh U-w2\fj#O~G4Yʍ)~>5ך=^Kd^JTu$65R3 W9;PEHN ^cS vok\LWOp]wє}~?DŽ<`!ȲO&$b_ 8}sb[ n֏L;8ww7ߝ{SwYs]\g> Za-@Ĝ^}V.ZLٯG{[MgSϨ=cu–:WYn.m)i>\s9\f\ts,D_ՒA"ۿsWnx|||̊~ǚRf^sbSpg.8v0h7Noˬ5/Qدi<-֑ld8 *#cC>v]ם|)}&vbT.X=Ƕ1{)f|{A3KzrF?~ǺRbtg렣zt90b)|͚yY^2J0oYXTTeZLRl^|h6878,?0|䨘߁yYz;Jrpx~%LozTUº>HT_fVF޵Կgwn)RP t_ @ eb@(BĀP 21  @ eb@(BĀP wgoK0~hͻx[_ԝ?16X1*eb@(BĀP 21  _0hqٍx/#h[>XZqٟy/ V<.Oz[+W[E^K}6[+{Y_ԝ?GeQZCβG_S`FSskEK4ӟyձv5Dˈ9mk8{._+,ڢ8 4=9UOz0eg`i |Kt2XI˺2n|nei7[MOD_ J)qr.&/2"t1Kձ}V`9۞,"9&/29M[pl0Z2_D(ea.׮O] 4 C-WŹzaωI'/2Rӽ'GViٱ$łe{ 4ͼ̫Á: _8,ьϽ0B,<ˊs-GU(H#N ,fa$nD?Pnx ^8"[.^êan5Ym\!dN4yz8)cpZ<ϱ Tlcpme̛^cv;DsL)R;"߉u87<.4c*-c[ vTL޿h֪WUpDKH;B jt\nܲ=>W ej7L=fحUlU6"9sl˹QFR^&3܉.c}|n9IJ0NsZx%-DZ7}9 =AiC{/,XNQ~X=ynPtǒ(g lgU*ǛcOve1GԸ['nxҼE#*0q5(k DTtfD+ eg5sZMc /] f#訴 g֌LfNWUdܪFƽY߼9ooE>LfFӗES{3_+ByKa1S?3#F$pne,sd$2\''VPx&R4|zn9تDvL䉌Hw?L&؉m[:osq)ԫ2ԤQƍJ= lEh uEEѱ)Gdf|{'3YGA=~`df!(I݇n7aLf}tN'.ͳ=bwE~VkU%/$2!lFL&@[އ\afߦ׋8tv?W>rkc#W]zJ^E"slѝ?IDà240r[rg\7noK$//]7 !KsL X+U??$!l4Y.&O,|AxjKcLT:3E<Fn(ol}bt4ۗ3%Ud6uZe=N~9 ]$2a34ϛ5y>u6ާNoTӔ/Ѹ:nґNK tp{ @'eB:ɑ^MY|M.3|W^Kuz[lud%> \L؏5L#fW\Kuz+Si0s 12p9tdrPڵRʎ2؀g_:ṅ W@@ 2-@( @ 2-@( @ 2-@( @ 2-P(-iIENDB`performance/man/test_performance.Rd0000644000176200001440000002726114475564246017206 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/test_bf.R, R/test_likelihoodratio.R, % R/test_performance.R, R/test_vuong.R, R/test_wald.R \name{test_bf} \alias{test_bf} \alias{test_bf.default} \alias{test_likelihoodratio} \alias{test_lrt} \alias{test_performance} \alias{test_vuong} \alias{test_wald} \title{Test if models are different} \usage{ test_bf(...) \method{test_bf}{default}(..., reference = 1, text_length = NULL) test_likelihoodratio(..., estimator = "ML", verbose = TRUE) test_lrt(..., estimator = "ML", verbose = TRUE) test_performance(..., reference = 1, verbose = TRUE) test_vuong(..., verbose = TRUE) test_wald(..., verbose = TRUE) } \arguments{ \item{...}{Multiple model objects.} \item{reference}{This only applies when models are non-nested, and determines which model should be taken as a reference, against which all the other models are tested.} \item{text_length}{Numeric, length (number of chars) of output lines. \code{test_bf()} describes models by their formulas, which can lead to overly long lines in the output. \code{text_length} fixes the length of lines to a specified limit.} \item{estimator}{Applied when comparing regression models using \code{test_likelihoodratio()}. Corresponds to the different estimators for the standard deviation of the errors. Defaults to \code{"OLS"} for linear models, \code{"ML"} for all other models (including mixed models), or \code{"REML"} for linear mixed models when these have the same fixed effects. See 'Details'.} \item{verbose}{Toggle warning and messages.} } \value{ A data frame containing the relevant indices. } \description{ Testing whether models are "different" in terms of accuracy or explanatory power is a delicate and often complex procedure, with many limitations and prerequisites. Moreover, many tests exist, each coming with its own interpretation, and set of strengths and weaknesses. The \code{test_performance()} function runs the most relevant and appropriate tests based on the type of input (for instance, whether the models are \emph{nested} or not). However, it still requires the user to understand what the tests are and what they do in order to prevent their misinterpretation. See the \emph{Details} section for more information regarding the different tests and their interpretation. } \details{ \subsection{Nested vs. Non-nested Models}{ Model's "nesting" is an important concept of models comparison. Indeed, many tests only make sense when the models are \emph{"nested",} i.e., when their predictors are nested. This means that all the \emph{fixed effects} predictors of a model are contained within the \emph{fixed effects} predictors of a larger model (sometimes referred to as the encompassing model). For instance, \code{model1 (y ~ x1 + x2)} is "nested" within \code{model2 (y ~ x1 + x2 + x3)}. Usually, people have a list of nested models, for instance \code{m1 (y ~ 1)}, \code{m2 (y ~ x1)}, \code{m3 (y ~ x1 + x2)}, \code{m4 (y ~ x1 + x2 + x3)}, and it is conventional that they are "ordered" from the smallest to largest, but it is up to the user to reverse the order from largest to smallest. The test then shows whether a more parsimonious model, or whether adding a predictor, results in a significant difference in the model's performance. In this case, models are usually compared \emph{sequentially}: m2 is tested against m1, m3 against m2, m4 against m3, etc. Two models are considered as \emph{"non-nested"} if their predictors are different. For instance, \code{model1 (y ~ x1 + x2)} and \code{model2 (y ~ x3 + x4)}. In the case of non-nested models, all models are usually compared against the same \emph{reference} model (by default, the first of the list). Nesting is detected via the \code{insight::is_nested_models()} function. Note that, apart from the nesting, in order for the tests to be valid, other requirements have often to be the fulfilled. For instance, outcome variables (the response) must be the same. You cannot meaningfully test whether apples are significantly different from oranges! } \subsection{Estimator of the standard deviation}{ The estimator is relevant when comparing regression models using \code{test_likelihoodratio()}. If \code{estimator = "OLS"}, then it uses the same method as \code{anova(..., test = "LRT")} implemented in base R, i.e., scaling by n-k (the unbiased OLS estimator) and using this estimator under the alternative hypothesis. If \code{estimator = "ML"}, which is for instance used by \code{lrtest(...)} in package \strong{lmtest}, the scaling is done by n (the biased ML estimator) and the estimator under the null hypothesis. In moderately large samples, the differences should be negligible, but it is possible that OLS would perform slightly better in small samples with Gaussian errors. For \code{estimator = "REML"}, the LRT is based on the REML-fit log-likelihoods of the models. Note that not all types of estimators are available for all model classes. } \subsection{REML versus ML estimator}{ When \code{estimator = "ML"}, which is the default for linear mixed models (unless they share the same fixed effects), values from information criteria (AIC, AICc) are based on the ML-estimator, while the default behaviour of \code{AIC()} may be different (in particular for linear mixed models from \strong{lme4}, which sets \code{REML = TRUE}). This default in \code{test_likelihoodratio()} intentional, because comparing information criteria based on REML fits requires the same fixed effects for all models, which is often not the case. Thus, while \code{anova.merMod()} automatically refits all models to REML when performing a LRT, \code{test_likelihoodratio()} checks if a comparison based on REML fits is indeed valid, and if so, uses REML as default (else, ML is the default). Set the \code{estimator} argument explicitely to override the default behaviour. } \subsection{Tests Description}{ \itemize{ \item \strong{Bayes factor for Model Comparison} - \code{test_bf()}: If all models were fit from the same data, the returned \code{BF} shows the Bayes Factor (see \code{bayestestR::bayesfactor_models()}) for each model against the reference model (which depends on whether the models are nested or not). Check out \href{https://easystats.github.io/bayestestR/articles/bayes_factors.html#bayesfactor_models}{this vignette} for more details. \item \strong{Wald's F-Test} - \code{test_wald()}: The Wald test is a rough approximation of the Likelihood Ratio Test. However, it is more applicable than the LRT: you can often run a Wald test in situations where no other test can be run. Importantly, this test only makes statistical sense if the models are nested. Note: this test is also available in base R through the \code{\link[=anova]{anova()}} function. It returns an \code{F-value} column as a statistic and its associated p-value. \item \strong{Likelihood Ratio Test (LRT)} - \code{test_likelihoodratio()}: The LRT tests which model is a better (more likely) explanation of the data. Likelihood-Ratio-Test (LRT) gives usually somewhat close results (if not equivalent) to the Wald test and, similarly, only makes sense for nested models. However, maximum likelihood tests make stronger assumptions than method of moments tests like the F-test, and in turn are more efficient. Agresti (1990) suggests that you should use the LRT instead of the Wald test for small sample sizes (under or about 30) or if the parameters are large. Note: for regression models, this is similar to \code{anova(..., test="LRT")} (on models) or \code{lmtest::lrtest(...)}, depending on the \code{estimator} argument. For \strong{lavaan} models (SEM, CFA), the function calls \code{lavaan::lavTestLRT()}. For models with transformed response variables (like \code{log(x)} or \code{sqrt(x)}), \code{logLik()} returns a wrong log-likelihood. However, \code{test_likelihoodratio()} calls \code{insight::get_loglikelihood()} with \code{check_response=TRUE}, which returns a corrected log-likelihood value for models with transformed response variables. Furthermore, since the LRT only accepts nested models (i.e. models that differ in their fixed effects), the computed log-likelihood is always based on the ML estimator, not on the REML fits. \item \strong{Vuong's Test} - \code{test_vuong()}: Vuong's (1989) test can be used both for nested and non-nested models, and actually consists of two tests. \itemize{ \item The \strong{Test of Distinguishability} (the \code{Omega2} column and its associated p-value) indicates whether or not the models can possibly be distinguished on the basis of the observed data. If its p-value is significant, it means the models are distinguishable. \item The \strong{Robust Likelihood Test} (the \code{LR} column and its associated p-value) indicates whether each model fits better than the reference model. If the models are nested, then the test works as a robust LRT. The code for this function is adapted from the \strong{nonnest2} package, and all credit go to their authors. } } } } \examples{ # Nested Models # ------------- m1 <- lm(Sepal.Length ~ Petal.Width, data = iris) m2 <- lm(Sepal.Length ~ Petal.Width + Species, data = iris) m3 <- lm(Sepal.Length ~ Petal.Width * Species, data = iris) test_performance(m1, m2, m3) test_bf(m1, m2, m3) test_wald(m1, m2, m3) # Equivalent to anova(m1, m2, m3) # Equivalent to lmtest::lrtest(m1, m2, m3) test_likelihoodratio(m1, m2, m3, estimator = "ML") # Equivalent to anova(m1, m2, m3, test='LRT') test_likelihoodratio(m1, m2, m3, estimator = "OLS") if (require("CompQuadForm")) { test_vuong(m1, m2, m3) # nonnest2::vuongtest(m1, m2, nested=TRUE) # Non-nested Models # ----------------- m1 <- lm(Sepal.Length ~ Petal.Width, data = iris) m2 <- lm(Sepal.Length ~ Petal.Length, data = iris) m3 <- lm(Sepal.Length ~ Species, data = iris) test_performance(m1, m2, m3) test_bf(m1, m2, m3) test_vuong(m1, m2, m3) # nonnest2::vuongtest(m1, m2) } # Tweak the output # ---------------- test_performance(m1, m2, m3, include_formula = TRUE) # SEM / CFA (lavaan objects) # -------------------------- # Lavaan Models if (require("lavaan")) { structure <- " visual =~ x1 + x2 + x3 textual =~ x4 + x5 + x6 speed =~ x7 + x8 + x9 visual ~~ textual + speed " m1 <- lavaan::cfa(structure, data = HolzingerSwineford1939) structure <- " visual =~ x1 + x2 + x3 textual =~ x4 + x5 + x6 speed =~ x7 + x8 + x9 visual ~~ 0 * textual + speed " m2 <- lavaan::cfa(structure, data = HolzingerSwineford1939) structure <- " visual =~ x1 + x2 + x3 textual =~ x4 + x5 + x6 speed =~ x7 + x8 + x9 visual ~~ 0 * textual + 0 * speed " m3 <- lavaan::cfa(structure, data = HolzingerSwineford1939) test_likelihoodratio(m1, m2, m3) # Different Model Types # --------------------- if (require("lme4") && require("mgcv")) { m1 <- lm(Sepal.Length ~ Petal.Length + Species, data = iris) m2 <- lmer(Sepal.Length ~ Petal.Length + (1 | Species), data = iris) m3 <- gam(Sepal.Length ~ s(Petal.Length, by = Species) + Species, data = iris) test_performance(m1, m2, m3) } } } \references{ \itemize{ \item Vuong, Q. H. (1989). Likelihood ratio tests for model selection and non-nested hypotheses. Econometrica, 57, 307-333. \item Merkle, E. C., You, D., & Preacher, K. (2016). Testing non-nested structural equation models. Psychological Methods, 21, 151-163. } } \seealso{ \code{\link[=compare_performance]{compare_performance()}} to compare the performance indices of many different models. } performance/man/performance_score.Rd0000644000176200001440000000445014504243270017315 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/performance_score.R \name{performance_score} \alias{performance_score} \title{Proper Scoring Rules} \usage{ performance_score(model, verbose = TRUE, ...) } \arguments{ \item{model}{Model with binary or count outcome.} \item{verbose}{Toggle off warnings.} \item{...}{Arguments from other functions, usually only used internally.} } \value{ A list with three elements, the logarithmic, quadratic/Brier and spherical score. } \description{ Calculates the logarithmic, quadratic/Brier and spherical score from a model with binary or count outcome. } \details{ Proper scoring rules can be used to evaluate the quality of model predictions and model fit. \code{performance_score()} calculates the logarithmic, quadratic/Brier and spherical scoring rules. The spherical rule takes values in the interval \verb{[0, 1]}, with values closer to 1 indicating a more accurate model, and the logarithmic rule in the interval \verb{[-Inf, 0]}, with values closer to 0 indicating a more accurate model. For \code{stan_lmer()} and \code{stan_glmer()} models, the predicted values are based on \code{posterior_predict()}, instead of \code{predict()}. Thus, results may differ more than expected from their non-Bayesian counterparts in \strong{lme4}. } \note{ Code is partially based on \href{https://drizopoulos.github.io/GLMMadaptive/reference/scoring_rules.html}{GLMMadaptive::scoring_rules()}. } \examples{ \dontshow{if (require("glmmTMB")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} ## Dobson (1990) Page 93: Randomized Controlled Trial : counts <- c(18, 17, 15, 20, 10, 20, 25, 13, 12) outcome <- gl(3, 1, 9) treatment <- gl(3, 3) model <- glm(counts ~ outcome + treatment, family = poisson()) performance_score(model) \donttest{ data(Salamanders, package = "glmmTMB") model <- glmmTMB::glmmTMB( count ~ spp + mined + (1 | site), zi = ~ spp + mined, family = nbinom2(), data = Salamanders ) performance_score(model) } \dontshow{\}) # examplesIf} } \references{ Carvalho, A. (2016). An overview of applications of proper scoring rules. Decision Analysis 13, 223–242. \doi{10.1287/deca.2016.0337} } \seealso{ \code{\link[=performance_logloss]{performance_logloss()}} } performance/man/model_performance.lavaan.Rd0000644000176200001440000001154514501027040020536 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/model_performance.lavaan.R \name{model_performance.lavaan} \alias{model_performance.lavaan} \title{Performance of lavaan SEM / CFA Models} \usage{ \method{model_performance}{lavaan}(model, metrics = "all", verbose = TRUE, ...) } \arguments{ \item{model}{A \strong{lavaan} model.} \item{metrics}{Can be \code{"all"} or a character vector of metrics to be computed (some of \code{"Chi2"}, \code{"Chi2_df"}, \code{"p_Chi2"}, \code{"Baseline"}, \code{"Baseline_df"}, \code{"p_Baseline"}, \code{"GFI"}, \code{"AGFI"}, \code{"NFI"}, \code{"NNFI"}, \code{"CFI"}, \code{"RMSEA"}, \code{"RMSEA_CI_low"}, \code{"RMSEA_CI_high"}, \code{"p_RMSEA"}, \code{"RMR"}, \code{"SRMR"}, \code{"RFI"}, \code{"PNFI"}, \code{"IFI"}, \code{"RNI"}, \code{"Loglikelihood"}, \code{"AIC"}, \code{"BIC"}, and \code{"BIC_adjusted"}.} \item{verbose}{Toggle off warnings.} \item{...}{Arguments passed to or from other methods.} } \value{ A data frame (with one row) and one column per "index" (see \code{metrics}). } \description{ Compute indices of model performance for SEM or CFA models from the \strong{lavaan} package. } \details{ \subsection{Indices of fit}{ \itemize{ \item \strong{Chisq}: The model Chi-squared assesses overall fit and the discrepancy between the sample and fitted covariance matrices. Its p-value should be > .05 (i.e., the hypothesis of a perfect fit cannot be rejected). However, it is quite sensitive to sample size. \item \strong{GFI/AGFI}: The (Adjusted) Goodness of Fit is the proportion of variance accounted for by the estimated population covariance. Analogous to R2. The GFI and the AGFI should be > .95 and > .90, respectively. \item \strong{NFI/NNFI/TLI}: The (Non) Normed Fit Index. An NFI of 0.95, indicates the model of interest improves the fit by 95\\% relative to the null model. The NNFI (also called the Tucker Lewis index; TLI) is preferable for smaller samples. They should be > .90 (Byrne, 1994) or > .95 (Schumacker and Lomax, 2004). \item \strong{CFI}: The Comparative Fit Index is a revised form of NFI. Not very sensitive to sample size (Fan, Thompson, and Wang, 1999). Compares the fit of a target model to the fit of an independent, or null, model. It should be > .90. \item \strong{RMSEA}: The Root Mean Square Error of Approximation is a parsimony-adjusted index. Values closer to 0 represent a good fit. It should be < .08 or < .05. The p-value printed with it tests the hypothesis that RMSEA is less than or equal to .05 (a cutoff sometimes used for good fit), and thus should be not significant. \item \strong{RMR/SRMR}: the (Standardized) Root Mean Square Residual represents the square-root of the difference between the residuals of the sample covariance matrix and the hypothesized model. As the RMR can be sometimes hard to interpret, better to use SRMR. Should be < .08. \item \strong{RFI}: the Relative Fit Index, also known as RHO1, is not guaranteed to vary from 0 to 1. However, RFI close to 1 indicates a good fit. \item \strong{IFI}: the Incremental Fit Index (IFI) adjusts the Normed Fit Index (NFI) for sample size and degrees of freedom (Bollen's, 1989). Over 0.90 is a good fit, but the index can exceed 1. \item \strong{PNFI}: the Parsimony-Adjusted Measures Index. There is no commonly agreed-upon cutoff value for an acceptable model for this index. Should be > 0.50. } } See the documentation for \code{?lavaan::fitmeasures}. \subsection{What to report}{ Kline (2015) suggests that at a minimum the following indices should be reported: The model \strong{chi-square}, the \strong{RMSEA}, the \strong{CFI} and the \strong{SRMR}. } } \examples{ \dontshow{if (require("lavaan")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} # Confirmatory Factor Analysis (CFA) --------- data(HolzingerSwineford1939, package = "lavaan") structure <- " visual =~ x1 + x2 + x3 textual =~ x4 + x5 + x6 speed =~ x7 + x8 + x9 " model <- lavaan::cfa(structure, data = HolzingerSwineford1939) model_performance(model) \dontshow{\}) # examplesIf} } \references{ \itemize{ \item Byrne, B. M. (1994). Structural equation modeling with EQS and EQS/Windows. Thousand Oaks, CA: Sage Publications. \item Tucker, L. R., and Lewis, C. (1973). The reliability coefficient for maximum likelihood factor analysis. Psychometrika, 38, 1-10. \item Schumacker, R. E., and Lomax, R. G. (2004). A beginner's guide to structural equation modeling, Second edition. Mahwah, NJ: Lawrence Erlbaum Associates. \item Fan, X., B. Thompson, and L. Wang (1999). Effects of sample size, estimation method, and model specification on structural equation modeling fit indexes. Structural Equation Modeling, 6, 56-83. \item Kline, R. B. (2015). Principles and practice of structural equation modeling. Guilford publications. } } performance/man/performance_rmse.Rd0000644000176200001440000000572514642733710017164 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/performance_rmse.R \name{performance_rmse} \alias{performance_rmse} \alias{rmse} \title{Root Mean Squared Error} \usage{ performance_rmse( model, normalized = FALSE, ci = NULL, iterations = 100, ci_method = NULL, verbose = TRUE, ... ) rmse( model, normalized = FALSE, ci = NULL, iterations = 100, ci_method = NULL, verbose = TRUE, ... ) } \arguments{ \item{model}{A model.} \item{normalized}{Logical, use \code{TRUE} if normalized rmse should be returned.} \item{ci}{Confidence resp. credible interval level. For \code{icc()}, \code{r2()}, and \code{rmse()}, confidence intervals are based on bootstrapped samples from the ICC, R2 or RMSE value. See \code{iterations}.} \item{iterations}{Number of bootstrap-replicates when computing confidence intervals for the ICC, R2, RMSE etc.} \item{ci_method}{Character string, indicating the bootstrap-method. Should be \code{NULL} (default), in which case \code{lme4::bootMer()} is used for bootstrapped confidence intervals. However, if bootstrapped intervals cannot be calculated this way, try \code{ci_method = "boot"}, which falls back to \code{boot::boot()}. This may successfully return bootstrapped confidence intervals, but bootstrapped samples may not be appropriate for the multilevel structure of the model. There is also an option \code{ci_method = "analytical"}, which tries to calculate analytical confidence assuming a chi-squared distribution. However, these intervals are rather inaccurate and often too narrow. It is recommended to calculate bootstrapped confidence intervals for mixed models.} \item{verbose}{Toggle warnings and messages.} \item{...}{Arguments passed down to \code{lme4::bootMer()} or \code{boot::boot()} for bootstrapped ICC, R2, RMSE etc.; for \code{variance_decomposition()}, arguments are passed down to \code{brms::posterior_predict()}.} } \value{ Numeric, the root mean squared error. } \description{ Compute root mean squared error for (mixed effects) models, including Bayesian regression models. } \details{ The RMSE is the square root of the variance of the residuals and indicates the absolute fit of the model to the data (difference between observed data to model's predicted values). It can be interpreted as the standard deviation of the unexplained variance, and is in the same units as the response variable. Lower values indicate better model fit. The normalized RMSE is the proportion of the RMSE related to the range of the response variable. Hence, lower values indicate less residual variance. } \examples{ \dontshow{if (require("nlme")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} data(Orthodont, package = "nlme") m <- nlme::lme(distance ~ age, data = Orthodont) # RMSE performance_rmse(m, normalized = FALSE) # normalized RMSE performance_rmse(m, normalized = TRUE) \dontshow{\}) # examplesIf} } performance/man/check_homogeneity.Rd0000644000176200001440000000454214741713304017312 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check_homogeneity.R \name{check_homogeneity} \alias{check_homogeneity} \alias{check_homogeneity.afex_aov} \title{Check model for homogeneity of variances} \usage{ check_homogeneity(x, method = c("bartlett", "fligner", "levene", "auto"), ...) \method{check_homogeneity}{afex_aov}(x, method = "levene", ...) } \arguments{ \item{x}{A linear model or an ANOVA object.} \item{method}{Name of the method (underlying test) that should be performed to check the homogeneity of variances. May either be \code{"levene"} for Levene's Test for Homogeneity of Variance, \code{"bartlett"} for the Bartlett test (assuming normal distributed samples or groups), \code{"fligner"} for the Fligner-Killeen test (rank-based, non-parametric test), or \code{"auto"}. In the latter case, Bartlett test is used if the model response is normal distributed, else Fligner-Killeen test is used.} \item{...}{Arguments passed down to \code{car::leveneTest()}.} } \value{ Invisibly returns the p-value of the test statistics. A p-value < 0.05 indicates a significant difference in the variance between the groups. } \description{ Check model for homogeneity of variances between groups described by independent variables in a model. } \note{ There is also a \href{https://easystats.github.io/see/articles/performance.html}{\code{plot()}-method} implemented in the \href{https://easystats.github.io/see/}{\pkg{see}-package}. } \examples{ model <<- lm(len ~ supp + dose, data = ToothGrowth) check_homogeneity(model) # plot results \dontshow{if (insight::check_if_installed("see", minimum_version = "0.9.1", quietly = TRUE)) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} result <- check_homogeneity(model) plot(result) \dontshow{\}) # examplesIf} } \seealso{ Other functions to check model assumptions and and assess model quality: \code{\link{check_autocorrelation}()}, \code{\link{check_collinearity}()}, \code{\link{check_convergence}()}, \code{\link{check_heteroscedasticity}()}, \code{\link{check_model}()}, \code{\link{check_outliers}()}, \code{\link{check_overdispersion}()}, \code{\link{check_predictions}()}, \code{\link{check_singularity}()}, \code{\link{check_zeroinflation}()} } \concept{functions to check model assumptions and and assess model quality} performance/man/item_intercor.Rd0000644000176200001440000000352114500061526016460 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/item_intercor.R \name{item_intercor} \alias{item_intercor} \title{Mean Inter-Item-Correlation} \usage{ item_intercor(x, method = c("pearson", "spearman", "kendall")) } \arguments{ \item{x}{A matrix as returned by the \code{cor()}-function, or a data frame with items (e.g. from a test or questionnaire).} \item{method}{Correlation computation method. May be one of \code{"pearson"} (default), \code{"spearman"} or \code{"kendall"}. You may use initial letter only.} } \value{ The mean inter-item-correlation value for \code{x}. } \description{ Compute various measures of internal consistencies for tests or item-scales of questionnaires. } \details{ This function calculates a mean inter-item-correlation, i.e. a correlation matrix of \code{x} will be computed (unless \code{x} is already a matrix as returned by the \code{cor()} function) and the mean of the sum of all items' correlation values is returned. Requires either a data frame or a computed \code{cor()} object. "Ideally, the average inter-item correlation for a set of items should be between 0.20 and 0.40, suggesting that while the items are reasonably homogeneous, they do contain sufficiently unique variance so as to not be isomorphic with each other. When values are lower than 0.20, then the items may not be representative of the same content domain. If values are higher than 0.40, the items may be only capturing a small bandwidth of the construct." \emph{(Piedmont 2014)} } \examples{ data(mtcars) x <- mtcars[, c("cyl", "gear", "carb", "hp")] item_intercor(x) } \references{ Piedmont RL. 2014. Inter-item Correlations. In: Michalos AC (eds) Encyclopedia of Quality of Life and Well-Being Research. Dordrecht: Springer, 3303-3304. \doi{10.1007/978-94-007-0753-5_1493} } performance/man/performance_logloss.Rd0000644000176200001440000000204314257537777017707 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/performance_logloss.R \name{performance_logloss} \alias{performance_logloss} \title{Log Loss} \usage{ performance_logloss(model, verbose = TRUE, ...) } \arguments{ \item{model}{Model with binary outcome.} \item{verbose}{Toggle off warnings.} \item{...}{Currently not used.} } \value{ Numeric, the log loss of \code{model}. } \description{ Compute the log loss for models with binary outcome. } \details{ Logistic regression models predict the probability of an outcome of being a "success" or "failure" (or 1 and 0 etc.). \code{performance_logloss()} evaluates how good or bad the predicted probabilities are. High values indicate bad predictions, while low values indicate good predictions. The lower the log-loss, the better the model predicts the outcome. } \examples{ data(mtcars) m <- glm(formula = vs ~ hp + wt, family = binomial, data = mtcars) performance_logloss(m) } \seealso{ \code{\link[=performance_score]{performance_score()}} } performance/man/check_heteroscedasticity.Rd0000644000176200001440000000411714741713304020660 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check_heteroscedasticity.R \name{check_heteroscedasticity} \alias{check_heteroscedasticity} \alias{check_heteroskedasticity} \title{Check model for (non-)constant error variance} \usage{ check_heteroscedasticity(x, ...) check_heteroskedasticity(x, ...) } \arguments{ \item{x}{A model object.} \item{...}{Currently not used.} } \value{ The p-value of the test statistics. A p-value < 0.05 indicates a non-constant variance (heteroskedasticity). } \description{ Significance testing for linear regression models assumes that the model errors (or residuals) have constant variance. If this assumption is violated the p-values from the model are no longer reliable. } \details{ This test of the hypothesis of (non-)constant error is also called \emph{Breusch-Pagan test} (\cite{1979}). } \note{ There is also a \href{https://easystats.github.io/see/articles/performance.html}{\code{plot()}-method} implemented in the \href{https://easystats.github.io/see/}{\pkg{see}-package}. } \examples{ m <<- lm(mpg ~ wt + cyl + gear + disp, data = mtcars) check_heteroscedasticity(m) # plot results \dontshow{if (insight::check_if_installed("see", minimum_version = "0.9.1", quietly = TRUE)) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} x <- check_heteroscedasticity(m) plot(x) \dontshow{\}) # examplesIf} } \references{ Breusch, T. S., and Pagan, A. R. (1979) A simple test for heteroscedasticity and random coefficient variation. Econometrica 47, 1287-1294. } \seealso{ Other functions to check model assumptions and and assess model quality: \code{\link{check_autocorrelation}()}, \code{\link{check_collinearity}()}, \code{\link{check_convergence}()}, \code{\link{check_homogeneity}()}, \code{\link{check_model}()}, \code{\link{check_outliers}()}, \code{\link{check_overdispersion}()}, \code{\link{check_predictions}()}, \code{\link{check_singularity}()}, \code{\link{check_zeroinflation}()} } \concept{functions to check model assumptions and and assess model quality} performance/man/performance-package.Rd0000644000176200001440000000540014705662376017526 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/performance-package.R \docType{package} \name{performance-package} \alias{performance-package} \title{performance: An R Package for Assessment, Comparison and Testing of Statistical Models} \description{ A crucial aspect when building regression models is to evaluate the quality of modelfit. It is important to investigate how well models fit to the data and which fit indices to report. Functions to create diagnostic plots or to compute fit measures do exist, however, mostly spread over different packages. There is no unique and consistent approach to assess the model quality for different kind of models. The primary goal of the \strong{performance} package is to fill this gap and to provide utilities for computing \strong{indices of model quality} and \strong{goodness of fit}. These include measures like r-squared (R2), root mean squared error (RMSE) or intraclass correlation coefficient (ICC), but also functions to check (mixed) models for overdispersion, zero-inflation, convergence or singularity. References: Lüdecke et al. (2021) \doi{10.21105/joss.03139} } \details{ \code{performance-package} } \seealso{ Useful links: \itemize{ \item \url{https://easystats.github.io/performance/} \item Report bugs at \url{https://github.com/easystats/performance/issues} } } \author{ \strong{Maintainer}: Daniel Lüdecke \email{d.luedecke@uke.de} (\href{https://orcid.org/0000-0002-8895-3206}{ORCID}) Authors: \itemize{ \item Dominique Makowski \email{dom.makowski@gmail.com} (\href{https://orcid.org/0000-0001-5375-9967}{ORCID}) [contributor] \item Mattan S. Ben-Shachar \email{matanshm@post.bgu.ac.il} (\href{https://orcid.org/0000-0002-4287-4801}{ORCID}) [contributor] \item Indrajeet Patil \email{patilindrajeet.science@gmail.com} (\href{https://orcid.org/0000-0003-1995-6531}{ORCID}) [contributor] \item Philip Waggoner \email{philip.waggoner@gmail.com} (\href{https://orcid.org/0000-0002-7825-7573}{ORCID}) [contributor] \item Brenton M. Wiernik \email{brenton@wiernik.org} (\href{https://orcid.org/0000-0001-9560-6336}{ORCID}) [contributor] \item Rémi Thériault \email{remi.theriault@mail.mcgill.ca} (\href{https://orcid.org/0000-0003-4315-6788}{ORCID}) [contributor] } Other contributors: \itemize{ \item Vincent Arel-Bundock \email{vincent.arel-bundock@umontreal.ca} (\href{https://orcid.org/0000-0003-2042-7063}{ORCID}) [contributor] \item Martin Jullum [reviewer] \item gjo11 [reviewer] \item Etienne Bacher \email{etienne.bacher@protonmail.com} (\href{https://orcid.org/0000-0002-9271-5075}{ORCID}) [contributor] \item Joseph Luchman (\href{https://orcid.org/0000-0002-8886-9717}{ORCID}) [contributor] } } \keyword{internal} performance/man/performance_accuracy.Rd0000644000176200001440000000357614436076277020023 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/performance_accuracy.R \name{performance_accuracy} \alias{performance_accuracy} \title{Accuracy of predictions from model fit} \usage{ performance_accuracy( model, method = c("cv", "boot"), k = 5, n = 1000, ci = 0.95, verbose = TRUE ) } \arguments{ \item{model}{A linear or logistic regression model. A mixed-effects model is also accepted.} \item{method}{Character string, indicating whether cross-validation (\code{method = "cv"}) or bootstrapping (\code{method = "boot"}) is used to compute the accuracy values.} \item{k}{The number of folds for the k-fold cross-validation.} \item{n}{Number of bootstrap-samples.} \item{ci}{The level of the confidence interval.} \item{verbose}{Toggle warnings.} } \value{ A list with three values: The \code{Accuracy} of the model predictions, i.e. the proportion of accurately predicted values from the model, its standard error, \code{SE}, and the \code{Method} used to compute the accuracy. } \description{ This function calculates the predictive accuracy of linear or logistic regression models. } \details{ For linear models, the accuracy is the correlation coefficient between the actual and the predicted value of the outcome. For logistic regression models, the accuracy corresponds to the AUC-value, calculated with the \code{bayestestR::auc()}-function. \cr \cr The accuracy is the mean value of multiple correlation resp. AUC-values, which are either computed with cross-validation or non-parametric bootstrapping (see argument \code{method}). The standard error is the standard deviation of the computed correlation resp. AUC-values. } \examples{ model <- lm(mpg ~ wt + cyl, data = mtcars) performance_accuracy(model) model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") performance_accuracy(model) } performance/man/check_autocorrelation.Rd0000644000176200001440000000312414413275473020176 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check_autocorrelation.R \name{check_autocorrelation} \alias{check_autocorrelation} \alias{check_autocorrelation.default} \title{Check model for independence of residuals.} \usage{ check_autocorrelation(x, ...) \method{check_autocorrelation}{default}(x, nsim = 1000, ...) } \arguments{ \item{x}{A model object.} \item{...}{Currently not used.} \item{nsim}{Number of simulations for the Durbin-Watson-Test.} } \value{ Invisibly returns the p-value of the test statistics. A p-value < 0.05 indicates autocorrelated residuals. } \description{ Check model for independence of residuals, i.e. for autocorrelation of error terms. } \details{ Performs a Durbin-Watson-Test to check for autocorrelated residuals. In case of autocorrelation, robust standard errors return more accurate results for the estimates, or maybe a mixed model with error term for the cluster groups should be used. } \examples{ m <- lm(mpg ~ wt + cyl + gear + disp, data = mtcars) check_autocorrelation(m) } \seealso{ Other functions to check model assumptions and and assess model quality: \code{\link{check_collinearity}()}, \code{\link{check_convergence}()}, \code{\link{check_heteroscedasticity}()}, \code{\link{check_homogeneity}()}, \code{\link{check_model}()}, \code{\link{check_outliers}()}, \code{\link{check_overdispersion}()}, \code{\link{check_predictions}()}, \code{\link{check_singularity}()}, \code{\link{check_zeroinflation}()} } \concept{functions to check model assumptions and and assess model quality} performance/man/display.performance_model.Rd0000644000176200001440000000376414335664246020771 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/display.R, R/print_md.R \name{display.performance_model} \alias{display.performance_model} \alias{print_md.performance_model} \alias{print_md.compare_performance} \title{Print tables in different output formats} \usage{ \method{display}{performance_model}(object, format = "markdown", digits = 2, caption = NULL, ...) \method{print_md}{performance_model}( x, digits = 2, caption = "Indices of model performance", layout = "horizontal", ... ) \method{print_md}{compare_performance}( x, digits = 2, caption = "Comparison of Model Performance Indices", layout = "horizontal", ... ) } \arguments{ \item{object, x}{An object returned by \code{\link[=model_performance]{model_performance()}} or or \code{\link[=compare_performance]{compare_performance()}}. or its summary.} \item{format}{String, indicating the output format. Currently, only \code{"markdown"} is supported.} \item{digits}{Number of decimal places.} \item{caption}{Table caption as string. If \code{NULL}, no table caption is printed.} \item{...}{Currently not used.} \item{layout}{Table layout (can be either \code{"horizontal"} or \code{"vertical"}).} } \value{ A character vector. If \code{format = "markdown"}, the return value will be a character vector in markdown-table format. } \description{ Prints tables (i.e. data frame) in different output formats. \code{print_md()} is a alias for \code{display(format = "markdown")}. } \details{ \code{display()} is useful when the table-output from functions, which is usually printed as formatted text-table to console, should be formatted for pretty table-rendering in markdown documents, or if knitted from rmarkdown to PDF or Word files. See \href{https://easystats.github.io/parameters/articles/model_parameters_formatting.html}{vignette} for examples. } \examples{ model <- lm(mpg ~ wt + cyl, data = mtcars) mp <- model_performance(model) display(mp) } performance/man/performance_rse.Rd0000644000176200001440000000117614257537777017024 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/performance_rse.R \name{performance_rse} \alias{performance_rse} \title{Residual Standard Error for Linear Models} \usage{ performance_rse(model) } \arguments{ \item{model}{A model.} } \value{ Numeric, the residual standard error of \code{model}. } \description{ Compute residual standard error of linear models. } \details{ The residual standard error is the square root of the residual sum of squares divided by the residual degrees of freedom. } \examples{ data(mtcars) m <- lm(mpg ~ hp + gear, data = mtcars) performance_rse(m) } performance/man/r2_efron.Rd0000644000176200001440000000207614335664246015353 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/r2_efron.R \name{r2_efron} \alias{r2_efron} \title{Efron's R2} \usage{ r2_efron(model) } \arguments{ \item{model}{Generalized linear model.} } \value{ The R2 value. } \description{ Calculates Efron's pseudo R2. } \details{ Efron's R2 is calculated by taking the sum of the squared model residuals, divided by the total variability in the dependent variable. This R2 equals the squared correlation between the predicted values and actual values, however, note that model residuals from generalized linear models are not generally comparable to those of OLS. } \examples{ ## Dobson (1990) Page 93: Randomized Controlled Trial: counts <- c(18, 17, 15, 20, 10, 20, 25, 13, 12) # outcome <- gl(3, 1, 9) treatment <- gl(3, 3) model <- glm(counts ~ outcome + treatment, family = poisson()) r2_efron(model) } \references{ Efron, B. (1978). Regression and ANOVA with zero-one data: Measures of residual variation. Journal of the American Statistical Association, 73, 113-121. } performance/man/r2.Rd0000644000176200001440000000641014666017356014157 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/r2.R \name{r2} \alias{r2} \alias{r2.default} \alias{r2.mlm} \alias{r2.merMod} \title{Compute the model's R2} \usage{ r2(model, ...) \method{r2}{default}(model, ci = NULL, verbose = TRUE, ...) \method{r2}{mlm}(model, multivariate = TRUE, ...) \method{r2}{merMod}(model, ci = NULL, tolerance = 1e-05, ...) } \arguments{ \item{model}{A statistical model.} \item{...}{Arguments passed down to the related r2-methods.} \item{ci}{Confidence interval level, as scalar. If \code{NULL} (default), no confidence intervals for R2 are calculated.} \item{verbose}{Logical. Should details about R2 and CI methods be given (\code{TRUE}) or not (\code{FALSE})?} \item{multivariate}{Logical. Should multiple R2 values be reported as separated by response (FALSE) or should a single R2 be reported as combined across responses computed by \code{\link{r2_mlm}} (TRUE).} \item{tolerance}{Tolerance for singularity check of random effects, to decide whether to compute random effect variances for the conditional r-squared or not. Indicates up to which value the convergence result is accepted. When \code{r2_nakagawa()} returns a warning, stating that random effect variances can't be computed (and thus, the conditional r-squared is \code{NA}), decrease the tolerance-level. See also \code{\link[=check_singularity]{check_singularity()}}.} } \value{ Returns a list containing values related to the most appropriate R2 for the given model (or \code{NULL} if no R2 could be extracted). See the list below: \itemize{ \item Logistic models: \link[=r2_tjur]{Tjur's R2} \item General linear models: \link[=r2_nagelkerke]{Nagelkerke's R2} \item Multinomial Logit: \link[=r2_mcfadden]{McFadden's R2} \item Models with zero-inflation: \link[=r2_zeroinflated]{R2 for zero-inflated models} \item Mixed models: \link[=r2_nakagawa]{Nakagawa's R2} \item Bayesian models: \link[=r2_bayes]{R2 bayes} } } \description{ Calculate the R2, also known as the coefficient of determination, value for different model objects. Depending on the model, R2, pseudo-R2, or marginal / adjusted R2 values are returned. } \note{ If there is no \code{r2()}-method defined for the given model class, \code{r2()} tries to return a "generic" r-quared value, calculated as following: \code{1-sum((y-y_hat)^2)/sum((y-y_bar)^2)} } \examples{ \dontshow{if (require("lme4")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} # Pseudo r-quared for GLM model <- glm(vs ~ wt + mpg, data = mtcars, family = "binomial") r2(model) # r-squared including confidence intervals model <- lm(mpg ~ wt + hp, data = mtcars) r2(model, ci = 0.95) model <- lme4::lmer(Sepal.Length ~ Petal.Length + (1 | Species), data = iris) r2(model) \dontshow{\}) # examplesIf} } \seealso{ \code{\link[=r2_bayes]{r2_bayes()}}, \code{\link[=r2_coxsnell]{r2_coxsnell()}}, \code{\link[=r2_kullback]{r2_kullback()}}, \code{\link[=r2_loo]{r2_loo()}}, \code{\link[=r2_mcfadden]{r2_mcfadden()}}, \code{\link[=r2_nagelkerke]{r2_nagelkerke()}}, \code{\link[=r2_nakagawa]{r2_nakagawa()}}, \code{\link[=r2_tjur]{r2_tjur()}}, \code{\link[=r2_xu]{r2_xu()}}, \code{\link[=r2_zeroinflated]{r2_zeroinflated()}}, and \code{\link[=r2_mlm]{r2_mlm()}}. } performance/man/item_discrimination.Rd0000644000176200001440000000330114620351763017653 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/item_discrimination.R \name{item_discrimination} \alias{item_discrimination} \title{Discrimination of Questionnaire Items} \usage{ item_discrimination(x, standardize = FALSE) } \arguments{ \item{x}{A matrix or a data frame.} \item{standardize}{Logical, if \code{TRUE}, the data frame's vectors will be standardized. Recommended when the variables have different measures / scales.} } \value{ A data frame with the item discrimination (\emph{corrected item-total correlations}) for each item of the scale. } \description{ Compute various measures of internal consistencies for tests or item-scales of questionnaires. } \details{ This function calculates the item discriminations (corrected item-total correlations for each item of \code{x} with the remaining items) for each item of a scale. The absolute value of the item discrimination indices should be above \code{0.2}. An index between \code{0.2} and \code{0.4} is considered as "fair", while a satisfactory index ranges from \code{0.4} to \code{0.7}. Items with low discrimination indices are often ambiguously worded and should be examined. Items with negative indices should be examined to determine why a negative value was obtained (e.g. reversed answer categories regarding positive and negative poles). } \examples{ data(mtcars) x <- mtcars[, c("cyl", "gear", "carb", "hp")] item_discrimination(x) } \references{ \itemize{ \item Kelava A, Moosbrugger H (2020). Deskriptivstatistische Itemanalyse und Testwertbestimmung. In: Moosbrugger H, Kelava A, editors. Testtheorie und Fragebogenkonstruktion. Berlin, Heidelberg: Springer, 143–158 } } performance/DESCRIPTION0000644000176200001440000001202714741740672014277 0ustar liggesusersType: Package Package: performance Title: Assessment of Regression Models Performance Version: 0.13.0 Authors@R: c(person(given = "Daniel", family = "Lüdecke", role = c("aut", "cre"), email = "d.luedecke@uke.de", comment = c(ORCID = "0000-0002-8895-3206")), person(given = "Dominique", family = "Makowski", role = c("aut", "ctb"), email = "dom.makowski@gmail.com", comment = c(ORCID = "0000-0001-5375-9967")), person(given = "Mattan S.", family = "Ben-Shachar", role = c("aut", "ctb"), email = "matanshm@post.bgu.ac.il", comment = c(ORCID = "0000-0002-4287-4801")), person(given = "Indrajeet", family = "Patil", role = c("aut", "ctb"), email = "patilindrajeet.science@gmail.com", comment = c(ORCID = "0000-0003-1995-6531")), person(given = "Philip", family = "Waggoner", role = c("aut", "ctb"), email = "philip.waggoner@gmail.com", comment = c(ORCID = "0000-0002-7825-7573")), person(given = "Brenton M.", family = "Wiernik", role = c("aut", "ctb"), email = "brenton@wiernik.org", comment = c(ORCID = "0000-0001-9560-6336")), person(given = "Rémi", family = "Thériault", role = c("aut", "ctb"), email = "remi.theriault@mail.mcgill.ca", comment = c(ORCID = "0000-0003-4315-6788")), person(given = "Vincent", family = "Arel-Bundock", email = "vincent.arel-bundock@umontreal.ca", role = "ctb", comment = c(ORCID = "0000-0003-2042-7063")), person(given = "Martin", family = "Jullum", role = "rev"), person(given = "gjo11", role = "rev"), person(given = "Etienne", family = "Bacher", , email = "etienne.bacher@protonmail.com", role = "ctb", comment = c(ORCID = "0000-0002-9271-5075")), person(given = "Joseph", family = "Luchman", role = "ctb", comment = c(ORCID = "0000-0002-8886-9717"))) Maintainer: Daniel Lüdecke Description: Utilities for computing measures to assess model quality, which are not directly provided by R's 'base' or 'stats' packages. These include e.g. measures like r-squared, intraclass correlation coefficient (Nakagawa, Johnson & Schielzeth (2017) ), root mean squared error or functions to check models for overdispersion, singularity or zero-inflation and more. Functions apply to a large variety of regression models, including generalized linear models, mixed effects models and Bayesian models. References: Lüdecke et al. (2021) . License: GPL-3 URL: https://easystats.github.io/performance/ BugReports: https://github.com/easystats/performance/issues Depends: R (>= 3.6) Imports: bayestestR (>= 0.15.0), insight (>= 1.0.0), datawizard (>= 0.13.0), stats, utils Suggests: AER, afex, BayesFactor, bayesplot, betareg, bigutilsr, blavaan, boot, brms, car, carData, CompQuadForm, correlation, cplm, dagitty, dbscan, DHARMa (>= 0.4.7), estimatr, fixest, flextable, forecast, ftExtra, gamm4, ggdag, glmmTMB (>= 1.1.10), graphics, Hmisc, httr2, ICS, ICSOutlier, ISLR, ivreg, lavaan, lme4, lmtest, loo, MASS, Matrix, mclogit, mclust, metadat, metafor, mgcv, mlogit, multimode, nestedLogit, nlme, nonnest2, ordinal, parallel, parameters (>= 0.22.0), patchwork, pscl, psych, quantreg, qqplotr (>= 0.0.6), randomForest, RcppEigen, rempsyc, rmarkdown, rstanarm, rstantools, sandwich, see (>= 0.9.0), survey, survival, testthat (>= 3.2.1), tweedie, VGAM, withr (>= 3.0.0) Encoding: UTF-8 Language: en-US RoxygenNote: 7.3.2 Config/testthat/edition: 3 Config/testthat/parallel: true Config/Needs/website: rstudio/bslib, r-lib/pkgdown, easystats/easystatstemplate Config/rcmdcheck/ignore-inconsequential-notes: true NeedsCompilation: no Packaged: 2025-01-15 12:53:23 UTC; mail Author: Daniel Lüdecke [aut, cre] (), Dominique Makowski [aut, ctb] (), Mattan S. Ben-Shachar [aut, ctb] (), Indrajeet Patil [aut, ctb] (), Philip Waggoner [aut, ctb] (), Brenton M. Wiernik [aut, ctb] (), Rémi Thériault [aut, ctb] (), Vincent Arel-Bundock [ctb] (), Martin Jullum [rev], gjo11 [rev], Etienne Bacher [ctb] (), Joseph Luchman [ctb] () Repository: CRAN Date/Publication: 2025-01-15 14:10:02 UTC