ecodist/0000755000175100001440000000000013131602130011710 5ustar hornikusersecodist/inst/0000755000175100001440000000000013131506235012676 5ustar hornikusersecodist/inst/CITATION0000644000175100001440000000110013034761246014032 0ustar hornikuserscitHeader("To cite package ecodist in publications use:") citEntry(entry="Article", title = "The ecodist package for dissimilarity-based analysis of ecological data", author = personList(as.person("Sarah C. Goslee"), as.person("Dean L. Urban")), journal = "Journal of Statistical Software", year = 2007, volume = 22, issue = 7, pages = "1-19", textVersion = paste("Goslee, S.C. and Urban, D.L. 2007.", "The ecodist package for dissimilarity-based analysis of ecological data.", "Journal of Statistical Software 22(7):1-19.") ) ecodist/inst/doc/0000755000175100001440000000000013131506235013443 5ustar hornikusersecodist/inst/doc/dissimilarity.html0000644000175100001440000002652313131506235017227 0ustar hornikusers Dissimilarity Cheat Sheet

Dissimilarity Cheat Sheet

Sarah Goslee

2017-07-12

Things to do with dissimilarity matrices

(ecodist functions are marked in bold)

(untested ideas marked with ?)

Description Notation Name R function
Relationship between two matrices D1 ~ D2 Mantel test mantel(D1 ~ D2)
Relationship between two matrices given more D1 ~ D2 | D3 … Dn Partial Mantel test mantel(D1 ~ D2 + D3 + …)
Spatial structure in one matrix D1 x S Mantel correlogram mgram(D1, S)
Spatial structure in one matrix given more D1 | D2 … Dn x S Partial Mantel correlogram ?mgram(residuals(lm(D1 ~ D2 + …)), space)
Spatial structuce in one matrix D1 x S Multivariate correlogram pmgram(D1, S)
Spatial structure in one matrix given more D1 | D2 … Dn x S Partial multivariate correlogram pmgram(D1, S, D2)
Spatial structure in the relationship between two matrices D1 ~ D2 x S Mantel cross-correlogram pmgram(cbind(lower(D1), lower(D2)), S)
Spatial structure in the relationship between two matrices given more D1 ~ D2 | D3 … Dn x S Partial Mantel cross-correlogram pmgram(cbind(lower(D1), lower(D2)), S, D3)
Ordination of one matrix (N)MDS nmds(y) or pco(y)
Ordination of one matrix given more (Partial (N)MDS ?nmds(residuals(lm(y ~ z1 + …)))
Grouping of items based on one matrix Cluster analysis hclust(y)
Grouping of items based on one matrix given more Partial cluster analysis ?hclust(residuals(lm(y ~ z1 + …)))
Grouping of items given space Spatially-constrained cluster analysis NA
Multiple regression D1 ~ D2 | D3 … Dn Multiple regression on distance matrices MRM(D1 ~ D2 + D3 + …)

Ways to calculate dissimilarity matrices

Description Result R function
From a site by sample matrix Symmetric matrix with zero diagonals dist(x) or bcdist(x) or distance(x)

Things to do with cross-dissimilarity matrices

Description Notation Name R function
Relationship between two cross-dissimilarity matrices D12 ~ D34 Cross-Mantel test xmantel(D12 ~ D34)
Relationship between two cross-dissimilarity matrices given more D12 ~ D34 | D56 … Dn Partial cross-Mantel test xmantel(D12 ~ D34 + D56 + …)
Spatial structure in one cross-dissimilarity matrix D12 x S Cross-Mantel correlogram xmgram(D12, spaceX)
Spatial structure in one cross-dissimilarity matrix given more D12 | D34 … Dn x S Partial cross-Mantel correlogram ?xmgram(residuals(lm(D12 ~ D34 + …)), spaceX)

Ways to calculate cross-dissimilarity matrices

Source Result R function
From 2 site by sample matrixes for the same sites and samples (e.g. different years) nonsymmetric matrix with nonzero diagonals xdistance(x, y)
ecodist/inst/doc/dissimilarity.Rmd0000644000175100001440000000621613131456337017011 0ustar hornikusers--- title: "Dissimilarity Cheat Sheet" author: "Sarah Goslee" date: "2017-07-12" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Dissimilarity Cheat Sheet} %\VignetteEngine{knitr::rmarkdown} --- **Things to do with dissimilarity matrices** _(ecodist functions are marked in **bold**)_ _(untested ideas marked with ?)_ Description | Notation | Name | R function ------------|----------|------|----------- Relationship between two matrices | D1 ~ D2 | Mantel test | **mantel**(D1 ~ D2) Relationship between two matrices given more | D1 ~ D2 | D3 ... Dn | Partial Mantel test | **mantel**(D1 ~ D2 + D3 + ...) ||| Spatial structure in one matrix | D1 x S | Mantel correlogram | **mgram**(D1, S) Spatial structure in one matrix given more | D1 | D2 ... Dn x S | Partial Mantel correlogram | **?mgram**(residuals(lm(D1 ~ D2 + ...)), space) Spatial structuce in one matrix | D1 x S | Multivariate correlogram | **pmgram**(D1, S) Spatial structure in one matrix given more | D1 | D2 ... Dn x S | Partial multivariate correlogram | **pmgram**(D1, S, D2) ||| Spatial structure in the relationship between two matrices | D1 ~ D2 x S | Mantel cross-correlogram | **pmgram**(cbind(lower(D1), lower(D2)), S) Spatial structure in the relationship between two matrices given more | D1 ~ D2 | D3 ... Dn x S | Partial Mantel cross-correlogram | **pmgram**(cbind(lower(D1), lower(D2)), S, D3) ||| Ordination of one matrix | | (N)MDS | **nmds**(y) or **pco**(y) Ordination of one matrix given more | | (Partial (N)MDS | **?nmds**(residuals(lm(y ~ z1 + ...))) ||| Grouping of items based on one matrix | | Cluster analysis | hclust(y) Grouping of items based on one matrix given more | | Partial cluster analysis | ?hclust(residuals(lm(y ~ z1 + ...))) Grouping of items given space | | Spatially-constrained cluster analysis | NA ||| Multiple regression | D1 ~ D2 | D3 ... Dn | Multiple regression on distance matrices | **MRM**(D1 ~ D2 + D3 + ...) **Ways to calculate dissimilarity matrices** Description | Result | R function ------------|--------|----------- From a site by sample matrix | Symmetric matrix with zero diagonals | dist(x) or **bcdist**(x) or **distance**(x) ----------------------------- **Things to do with cross-dissimilarity matrices** Description | Notation | Name | R function ------------|----------|------|----------- Relationship between two cross-dissimilarity matrices | D12 ~ D34 | Cross-Mantel test | **xmantel**(D12 ~ D34) Relationship between two cross-dissimilarity matrices given more | D12 ~ D34 | D56 ... Dn | Partial cross-Mantel test | **xmantel**(D12 ~ D34 + D56 + ...) ||| Spatial structure in one cross-dissimilarity matrix | D12 x S | Cross-Mantel correlogram | **xmgram**(D12, spaceX) Spatial structure in one cross-dissimilarity matrix given more | D12 | D34 ... Dn x S | Partial cross-Mantel correlogram | **?xmgram**(residuals(lm(D12 ~ D34 + ...)), spaceX) **Ways to calculate cross-dissimilarity matrices** Source | Result | R function -------|--------|----------- From 2 site by sample matrixes for the same sites and samples (e.g. different years) | nonsymmetric matrix with nonzero diagonals | **xdistance**(x, y) ecodist/tests/0000755000175100001440000000000013127510434013064 5ustar hornikusersecodist/tests/testthat.R0000644000175100001440000000005013122530634015041 0ustar hornikuserslibrary(testthat) test_check("ecodist") ecodist/tests/testthat/0000755000175100001440000000000013131602130014712 5ustar hornikusersecodist/tests/testthat/test-crosstab.R0000644000175100001440000001151413122536371017651 0ustar hornikuserscontext("crosstab") test_that("different sizes and shapes of data", { expect_equal( crosstab(rep(letters[1:3], 4), rep(1:4, each=3)), structure(list(X1 = c(1, 1, 1), X2 = c(1, 1, 1), X3 = c(1, 1, 1), X4 = c(1, 1, 1)), .Names = c("X1", "X2", "X3", "X4"), row.names = c("a", "b", "c"), class = "data.frame") ) expect_equal( crosstab(rep(letters[1:3], 4), rep(1:4, each=3), allrows=letters[1:5]), structure(list(X1 = c(1, 1, 1, 0, 0), X2 = c(1, 1, 1, 0, 0), X3 = c(1, 1, 1, 0, 0), X4 = c(1, 1, 1, 0, 0)), .Names = c("X1", "X2", "X3", "X4"), row.names = c("a", "b", "c", "d", "e"), class = "data.frame") ) expect_equal( crosstab(rep(letters[1:3], 4), rep(1:4, each=3), allrows=letters[1:5], allcols=1:5), structure(list(X1 = c(1, 1, 1, 0, 0), X2 = c(1, 1, 1, 0, 0), X3 = c(1, 1, 1, 0, 0), X4 = c(1, 1, 1, 0, 0), X5 = c(0, 0, 0, 0, 0)), .Names = c("X1", "X2", "X3", "X4", "X5"), row.names = c("a", "b", "c", "d", "e"), class = "data.frame") ) expect_equal( crosstab(rep(letters[1], 12), rep(1:4, each=3), allrows=letters[1:5], allcols=1:5), structure(list(X1 = c(3, 0, 0, 0, 0), X2 = c(3, 0, 0, 0, 0), X3 = c(3, 0, 0, 0, 0), X4 = c(3, 0, 0, 0, 0), X5 = c(0, 0, 0, 0, 0)), .Names = c("X1", "X2", "X3", "X4", "X5"), row.names = c("a", "b", "c", "d", "e"), class = "data.frame") ) expect_equal( crosstab(rep(letters[1], 12), rep(1:4, each=3), allcols=1:5), structure(list(X1 = 3, X2 = 3, X3 = 3, X4 = 3, X5 = 0), .Names = c("X1", "X2", "X3", "X4", "X5"), row.names = "a", class = "data.frame") ) expect_equal( crosstab(rep(letters[1:3], 4), rep(1, each=12), allrows=letters[1:5], allcols=1:5), structure(list(X1 = c(4, 4, 4, 0, 0), X2 = c(0, 0, 0, 0, 0), X3 = c(0, 0, 0, 0, 0), X4 = c(0, 0, 0, 0, 0), X5 = c(0, 0, 0, 0, 0)), .Names = c("X1", "X2", "X3", "X4", "X5"), row.names = c("a", "b", "c", "d", "e"), class = "data.frame") ) expect_equal( crosstab(rep(letters[1:3], 4), rep(1, each=12), allrows=letters[1:5]), structure(list(X1 = c(4, 4, 4, 0, 0)), .Names = "X1", row.names = c("a", "b", "c", "d", "e"), class = "data.frame") ) expect_equal( crosstab(rep(1, each=12), rep(letters[1:3], 4), allcols=letters[1:5]), structure(list(a = 4, b = 4, c = 4, d = 0, e = 0), .Names = c("a", "b", "c", "d", "e"), row.names = "1", class = "data.frame") ) expect_equal( crosstab(rep(letters[1:3], 4), rep(1, each=12), allcols=1:5), structure(list(X1 = c(4, 4, 4), X2 = c(0, 0, 0), X3 = c(0, 0, 0), X4 = c(0, 0, 0), X5 = c(0, 0, 0)), .Names = c("X1", "X2", "X3", "X4", "X5"), row.names = c("a", "b", "c"), class = "data.frame") ) }) test_that("data interface", { x <- data.frame(a = rep(letters[1:3], 4), b = rep(1:4, each=3), c = seq_len(12)) expect_equal( crosstab(a, b, data=x), structure(list(X1 = c(1, 1, 1), X2 = c(1, 1, 1), X3 = c(1, 1, 1), X4 = c(1, 1, 1)), .Names = c("X1", "X2", "X3", "X4"), row.names = c("a", "b", "c"), class = "data.frame") ) }) test_that("function options", { x <- data.frame(a = rep(letters[1:3], 8), b = rep(1:4, each=6), c = rep(1:12, times=2)) expect_equal( crosstab(a, b, c, data=x, type="sum"), structure(list(X1 = c(5, 7, 9), X2 = c(17, 19, 21), X3 = c(5, 7, 9), X4 = c(17, 19, 21)), .Names = c("X1", "X2", "X3", "X4"), row.names = c("a", "b", "c"), class = "data.frame") ) expect_equal( crosstab(a, b, c, data=x, type="min"), structure(list(X1 = c(1, 2, 3), X2 = c(7, 8, 9), X3 = c(1, 2, 3), X4 = c(7, 8, 9)), .Names = c("X1", "X2", "X3", "X4"), row.names = c("a", "b", "c"), class = "data.frame") ) expect_equal( crosstab(a, b, c, data=x, type="max"), structure(list(X1 = c(4, 5, 6), X2 = c(10, 11, 12), X3 = c(4, 5, 6), X4 = c(10, 11, 12)), .Names = c("X1", "X2", "X3", "X4"), row.names = c("a", "b", "c"), class = "data.frame") ) expect_equal( crosstab(a, b, c, data=x, type="mean"), structure(list(X1 = c(2.5, 3.5, 4.5), X2 = c(8.5, 9.5, 10.5), X3 = c(2.5, 3.5, 4.5), X4 = c(8.5, 9.5, 10.5)), .Names = c("X1", "X2", "X3", "X4"), row.names = c("a", "b", "c"), class = "data.frame") ) expect_equal( crosstab(a, b, c, data=x, type="count"), structure(list(X1 = c(2, 2, 2), X2 = c(2, 2, 2), X3 = c(2, 2, 2), X4 = c(2, 2, 2)), .Names = c("X1", "X2", "X3", "X4"), row.names = c("a", "b", "c"), class = "data.frame") ) }) ecodist/tests/testthat/test-mantel.R0000644000175100001440000000041413130732366017307 0ustar hornikuserscontext("mantel") test_that("mantel r is the correlation", { set.seed(888) x <- runif(110) y <- runif(110) x <- dist(x) y <- dist(y) expect_equal(as.vector(mantel(y ~ x, nperm=0, nboot=0))[1], cor(x, y)) }) ecodist/tests/testthat/test-MRM.R0000644000175100001440000000043213130724024016452 0ustar hornikuserscontext("MRM") test_that("MRM coefficients match lm", { set.seed(888) y <- runif(11175) x1 <- runif(11175) x2 <- runif(11175) expect_equal(as.vector(MRM(y ~ x1 + x2, nperm=0)$coef[,1]), as.vector(coefficients(lm(y ~ x1 + x2)))) }) ecodist/tests/testthat/test-distance.R0000644000175100001440000000146413130725007017621 0ustar hornikuserscontext("distance") test_that("Euclidean distance is correct", { set.seed(888) x <- matrix(runif(50), ncol=5) d.ecodist <- distance(x, "euclidean") d.base <- dist(x) expect_equal(attributes(d.ecodist), attributes(d.base)[names(attributes(d.base)) != "call"]) expect_equal(as.vector(d.ecodist), as.vector(d.base)) }) test_that("Bray-Curtis distance is correct", { set.seed(888) x <- matrix(runif(50), ncol=5) expect_equal(distance(x, "bray"), bcdist(x)) }) test_that("Mahalanobis icov is correct", { set.seed(888) x <- matrix(runif(50), ncol=5) x.md <- full(distance(x, "mahal")) sub.md <- full(distance(x[1:5, ], "mahal", icov=cov(x))) expect_equal(x.md[1:5, 1:5], sub.md) }) ecodist/tests/testthat/test-mgroup.R0000644000175100001440000000137113130730236017335 0ustar hornikuserscontext("mgroup") test_that("Mantel r is correct", { set.seed(888) x <- runif(110) groups.char <- sample(letters[1:5], size=length(x), replace=TRUE) x.d <- dist(x) groups.factor <- factor(groups.char) groups.numeric <- as.numeric(groups.factor) groups.d <- dist(groups.numeric) groups.d[groups.d > 0] <- 1 expect_equal(as.vector(mantel(x.d ~ groups.d, nperm=0, nboot=0))[1], mgroup(x.d, groups.char, nperm=0)[1, 2]) expect_equal(as.vector(mantel(x.d ~ groups.d, nperm=0, nboot=0))[1], mgroup(x.d, groups.factor, nperm=0)[1, 2]) expect_equal(as.vector(mantel(x.d ~ groups.d, nperm=0, nboot=0))[1], mgroup(x.d, groups.numeric, nperm=0)[1, 2]) }) ecodist/src/0000755000175100001440000000000013131506235012510 5ustar hornikusersecodist/src/Makevars0000644000175100001440000000004013131506235014176 0ustar hornikusersPKG_LIBS=$(BLAS_LIBS) $(FLIBS) ecodist/src/ecodist.c0000644000175100001440000004524313131506235014316 0ustar hornikusers#include #include #include /* for dgemm */ #define RANDIN GetRNGstate() #define RANDOUT PutRNGstate() #define UNIF unif_rand() void bootstrap(double *x, double *y, int *n, int *xlen, int *nboot, double *pboot, double *bootcor, int *rarray, int *rmat, double *xdif, double *ydif) { int i, j, k, l; double r; double nsamp; double xmean, ymean; double xsum; double xxsum, yysum; /* Set random seed using Splus function */ RANDIN; for(i = 0; i < *nboot; i++) { /* Set up rarray. */ for(j = 0; j < *n; j++) { r = UNIF; if(r > *pboot) rarray[j] = 0; else rarray[j] = 1; } /* Turn rarray into a lower-triangular sampling matrix. */ /* 1 means include, 0 means omit. */ l = 0; for(j = 1; j < *n; j++) { for(k = 0; k < j; k++) { if(rarray[j] == 0 || rarray[k] == 0) rmat[l] = 0; else rmat[l] = 1; l++; } } nsamp = 0; for(j = 0; j < *xlen; j++) { nsamp += rmat[j]; } /* Calculate means for x and y. */ xmean = 0; ymean = 0; for(j = 0; j < *xlen; j++) { if(rmat[j] == 1) { xmean += x[j]; ymean += y[j]; } } xmean = xmean/nsamp; ymean = ymean/nsamp; /* Calculate deviations for x and y. */ for(j = 0; j < *xlen; j++) { if(rmat[j] == 1) { xdif[j] = x[j] - xmean; ydif[j] = y[j] - ymean; } else { xdif[j] = 0; ydif[j] = 0; } } xsum = 0; xxsum = 0; yysum = 0; for(j = 0; j < *xlen; j++) { if(rmat[j] == 1) { xsum += (xdif[j] * ydif[j]); xxsum += (xdif[j] * xdif[j]); yysum += (ydif[j] * ydif[j]); } } bootcor[i] = (xsum) / sqrt(xxsum * yysum); } /* Reset random seed using an Splus function. */ RANDOUT; } void permute(double *x, double *y, int *n, int *xlen, int *nperm, double *zstats, double *tmat, int *rarray) { int i, k, l, m; double cumsum; int temp; /* Set random seed using Splus function */ RANDIN; /* Calculate first z-statistic (unpermuted data). */ cumsum = 0; for(k = 0; k < *xlen; k++) { cumsum += x[k] * y[k]; } zstats[0] = cumsum / *xlen; /* Start permutation routine */ for(i = 1; i < *nperm; i++) { /* Set up rarray. */ for(k = 0; k < *n; k++) { rarray[k] = k; } /* Convert x to a full matrix. */ m = 0; for(k = 1; k < *n; k++) { for(l = 0; l < k; l++) { tmat[k * *n + l] = x[m]; tmat[l * *n + k] = x[m]; m++; } } /* Randomize rarray using an Splus function. */ for(k = 0; k < (*n - 1); k++) { l = *n - k - 1; m = (int)((float)l * UNIF); if(m > l) m = l; temp = rarray[l]; rarray[l] = rarray[m]; rarray[m] = temp; } /* Reorder x and take lower triangle. */ m = 0; for(k = 1; k < *n; k++) { for(l = 0; l < k; l++) { x[m] = tmat[rarray[k] * *n + rarray[l]]; m++; } } /* Calculate new sum of products. */ cumsum = 0; for(k = 0; k < *xlen; k++) { cumsum += x[k] * y[k]; } zstats[i] = cumsum / *xlen; } /* Reset random seed using an Splus function. */ RANDOUT; } void permpart(double *hmat, double *bmat, double *omat, double *y, double *xcor, double *ycor, int *n, int *ncol, int *xlen, int *nperm, double *zstats, double *tmat, int *rarray) { int i, k, l, m; double cumsum; double bsum; double w1, w2; int temp; /* Set random seed using Splus function */ RANDIN; /* Calculate first z-statistic (unpermuted data). */ cumsum = 0; for(k = 0; k < *xlen; k++) { cumsum += xcor[k] * ycor[k]; } zstats[0] = cumsum / *xlen; /* Start permutation routine */ for(i = 1; i < *nperm; i++) { /* Set up rarray. */ for(k = 0; k < *n; k++) { rarray[k] = k; } /* Convert y to a full matrix. */ m = 0; for(k = 1; k < *n; k++) { for(l = 0; l < k; l++) { tmat[k * *n + l] = y[m]; tmat[l * *n + k] = y[m]; m++; } } /* Randomize rarray using an Splus function. */ for(k = 0; k < (*n - 1); k++) { l = *n - k - 1; m = (int)((float)l * UNIF); if(m > l) m = l; temp = rarray[l]; rarray[l] = rarray[m]; rarray[m] = temp; } /* Reorder y and take lower triangle. */ m = 0; for(k = 1; k < *n; k++) { for(l = 0; l < k; l++) { y[m] = tmat[rarray[k] * *n + rarray[l]]; m++; } } /* Calculate residuals for y */ /* Calculate bmat */ for(k = 0; k < *ncol; k++) { bmat[k] = 0; } for(k = 0; k < *ncol; k++) { for(l = 0; l < *xlen; l++) { bmat[k] = bmat[k] + hmat[l * *ncol + k] * y[l]; } } /* Calculate ycor (residuals) */ for(k = 0; k < *xlen; k++) { ycor[k] = 0; } for(k = 0; k < *xlen; k++) { bsum = 0; for(l = 0; l < *ncol; l++) { bsum = bsum + bmat[l] * omat[l * *xlen + k]; } ycor[k] = y[k] - bsum; } /* Standardize residuals so z = r */ w1 = 0; w2 = 0; for(k = 0; k < *xlen; k++) { w1 = w1 + ycor[k]; w2 = w2 + ycor[k] * ycor[k]; } w1 = w1 / *xlen; w2 = sqrt(w2 / *xlen - w1 * w1); for(k = 0; k < *xlen; k++) { ycor[k] = (ycor[k] - w1) / w2; } /* Calculate new sum of products. */ cumsum = 0; for(k = 0; k < *xlen; k++) { cumsum += xcor[k] * ycor[k]; } zstats[i] = cumsum / *xlen; } /* Reset random seed using an Splus function. */ RANDOUT; } void bcdistc(double *x, int *pnrow, int *pncol, double *dist) { int i, j, k, l; int nrow, ncol; double sumi, sumj; double minsum; l = 0; nrow = *pnrow; ncol = *pncol; for(i = 0; i < (nrow - 1); i++) { for(j = (i + 1); j < (nrow); j++) { minsum = 0; sumi = 0; sumj = 0; for(k = 0; k < ncol; k++) { if(x[i * ncol + k] < x[j * ncol + k]) minsum += x[i * ncol + k]; else minsum += x[j * ncol + k]; sumi += x[i * ncol + k]; sumj += x[j * ncol + k]; } if((sumi + sumj) == 0) dist[l] = 0; else dist[l] = (1 - (2 * minsum) / (sumi + sumj)); l++; } } } void newpermone(double *x, int *dclass, int *n, int *xlen, int *nperm, double *zstats, double *tmat, int *rarray) { int i, k, l, m; double cumsum; int temp; /* Set random seed using Splus function */ RANDIN; /* Calculate first z-statistic (unpermuted data). */ cumsum = 0; for(k = 0; k < *xlen; k++) { if(dclass[k] == 0) { cumsum += x[k]; } } zstats[0] = cumsum; /* Start permutation routine */ for(i = 1; i < *nperm; i++) { /* Set up rarray. */ for(k = 0; k < *n; k++) { rarray[k] = k; } /* Convert x to a full matrix. */ m = 0; for(k = 1; k < *n; k++) { for(l = 0; l < k; l++) { tmat[k * *n + l] = x[m]; tmat[l * *n + k] = x[m]; m++; } } /* Randomize rarray using an Splus function. */ for(k = 0; k < (*n - 1); k++) { l = *n - k - 1; m = (int)((float)l * UNIF); if(m > l) m = l; temp = rarray[l]; rarray[l] = rarray[m]; rarray[m] = temp; } /* Reorder x. */ m = 0; for(k = 1; k < *n; k++) { for(l = 0; l < k; l++) { x[m] = tmat[rarray[k] * *n + rarray[l]]; m++; } } /* Calculate new sum of products. */ cumsum = 0; for(k = 0; k < *xlen; k++) { if(dclass[k] == 0) { cumsum += x[k]; } } zstats[i] = cumsum; } /* Reset random seed using an Splus function. */ RANDOUT; } void newpermtwo(double *x, double *y, int *n, int *xlen, int *nperm, double *zstats, double *tmat, int *rarray) { int i, k, l, m; double cumsum; int temp; float naval = -9999; /* Set random seed using Splus function */ RANDIN; /* Calculate first z-statistic (unpermuted data). */ cumsum = 0; for(k = 0; k < *xlen; k++) { if(x[k] != naval) { cumsum += x[k] * y[k]; } } zstats[0] = cumsum; /* Start permutation routine */ for(i = 1; i < *nperm; i++) { /* Set up rarray. */ for(k = 0; k < *n; k++) { rarray[k] = k; } /* Convert x to a full matrix. */ m = 0; for(k = 1; k < *n; k++) { for(l = 0; l < k; l++) { tmat[k * *n + l] = x[m]; tmat[l * *n + k] = x[m]; m++; } } /* Randomize rarray using an Splus function. */ for(k = 0; k < (*n - 1); k++) { l = *n - k - 1; m = (int)((float)l * UNIF); if(m > l) m = l; temp = rarray[l]; rarray[l] = rarray[m]; rarray[m] = temp; } /* Reorder x. */ m = 0; for(k = 1; k < *n; k++) { for(l = 0; l < k; l++) { x[m] = tmat[rarray[k] * *n + rarray[l]]; m++; } } /* Calculate new sum of products. */ cumsum = 0; for(k = 0; k < *xlen; k++) { if(x[k] != naval) { cumsum += x[k] * y[k]; } } zstats[i] = cumsum; } /* Reset random seed using an Splus function. */ RANDOUT; } void psum(double *x, int *pnrow, int *pncol, double *dist) { int row1, row2, col1; int nrow, ncol; int l; double thisval, thatval; l = 0; nrow = *pnrow; ncol = *pncol; for(col1 = 0; col1 < ncol; col1++) { for(row1 = 0; row1 < nrow; row1++) { thatval = x[row1 * ncol + col1]; for(row2 = 0; row2 < nrow; row2++) { thisval = x[row2 * ncol + col1]; dist[l] = thisval + thatval; l++; } } } } void pdiff(double *x, int *pnrow, int *pncol, double *dist) { int row1, row2, col1; int nrow, ncol; int l; double thisval, thatval; l = 0; nrow = *pnrow; ncol = *pncol; for(col1 = 0; col1 < ncol; col1++) { for(row1 = 0; row1 < nrow; row1++) { thatval = x[row1 * ncol + col1]; for(row2 = 0; row2 < nrow; row2++) { thisval = x[row2 * ncol + col1]; dist[l] = thisval - thatval; l++; } } } } void jpres(double *x, int *pnrow, int *pncol, double *dist) { int row1, row2, col1; int nrow, ncol; int l; double thisval, thatval; l = 0; nrow = *pnrow; ncol = *pncol; for(col1 = 0; col1 < ncol; col1++) { for(row1 = 0; row1 < nrow; row1++) { thatval = x[row1 * ncol + col1]; for(row2 = 0; row2 < nrow; row2++) { thisval = x[row2 * ncol + col1]; if((thisval > 0) & (thatval > 0)) { dist[l] = 1; } else { dist[l] = 0; } l++; } } } } void jabs(double *x, int *pnrow, int *pncol, double *dist) { int row1, row2, col1; int nrow, ncol; int l; double thisval, thatval; l = 0; nrow = *pnrow; ncol = *pncol; for(col1 = 0; col1 < ncol; col1++) { for(row1 = 0; row1 < nrow; row1++) { thatval = x[row1 * ncol + col1]; for(row2 = 0; row2 < nrow; row2++) { thisval = x[row2 * ncol + col1]; if((thisval == 0) & (thatval == 0)) { dist[l] = 1; } else { dist[l] = 0; } l++; } } } } void jfirst(double *x, int *pnrow, int *pncol, double *dist) { int row1, row2, col1; int nrow, ncol; int l; double thisval, thatval; l = 0; nrow = *pnrow; ncol = *pncol; for(col1 = 0; col1 < ncol; col1++) { for(row1 = 0; row1 < nrow; row1++) { thatval = x[row1 * ncol + col1]; for(row2 = 0; row2 < nrow; row2++) { thisval = x[row2 * ncol + col1]; if((thisval > 0) & (thatval == 0)) { dist[l] = 1; } else { dist[l] = 0; } l++; } } } } void jsec(double *x, int *pnrow, int *pncol, double *dist) { int row1, row2, col1; int nrow, ncol; int l; double thisval, thatval; l = 0; nrow = *pnrow; ncol = *pncol; for(col1 = 0; col1 < ncol; col1++) { for(row1 = 0; row1 < nrow; row1++) { thatval = x[row1 * ncol + col1]; for(row2 = 0; row2 < nrow; row2++) { thisval = x[row2 * ncol + col1]; if((thisval == 0) & (thatval > 0)) { dist[l] = 1; } else { dist[l] = 0; } l++; } } } } void mrmperm(double *x, double *y, int *p, int *nd, int *n, int *nperm, double *r2all, double *ball, double *fall, double *tmat, int *rarray, double *XX, double *XY, double *YY, double *b) { int i, k, l; int m; int temp; double SSE=0.0, SSTO=0.0, SSR=0.0; double r2=0, f=0; double btemp=0.0; int bcount = 0; char *transt = "T", *transn = "N"; double one = 1.0, zero = 0.0; int onei = 1; /* Set random seed using Splus function */ RANDIN; /* Start permutation routine */ for(i = 0; i < *nperm; i++) { /* first do the unpermuted values */ /* F77_CALL(dgemm)(transa, transb, &ncx, &ncy, &nrx, &one, x, &nrx, y, &nry, &zero, z, &ncx); */ /* take crossproduct t(X) %*% Y - WORKS */ F77_CALL(dgemm)(transt, transn, p, &onei, nd, &one, x, nd, y, nd, &zero, XY, p); /* take crossproduct t(Y) %*% (Y) - WORKS */ F77_CALL(dgemm)(transt, transn, &onei, &onei, nd, &one, y, nd, y, nd, &zero, YY, &onei); /* calculate regression coefficients XX %*% XY - WORKS */ F77_CALL(dgemm)(transn, transn, p, &onei, p, &one, XX, p, XY, p, &zero, b, p); /* calculate regression components - WORKS */ F77_CALL(dgemm)(transt, transn, &onei, &onei, p, &one, b, p, XY, p, &zero, &btemp, &onei); /* SSE - WORKS */ SSE = YY[0] - btemp; /* SSTO - WORKS */ SSTO = 0; for(k = 0; k < *nd; k++) { SSTO = SSTO + y[k]; } SSTO = YY[0] - (SSTO * SSTO) / *nd; SSR = SSTO - SSE; /* calculate R2 - WORKS */ r2 = 1 - SSE / SSTO; /* calculate F* - WORKS */ f = (SSR / (*p - 1)) / (SSE / (*nd - *p)); r2all[i] = r2; fall[i] = f; /* calculate pseudo-t for regression coefficients - WORKS*/ /* b / sqrt(1 - R2) */ for(k=0; k<*p; k++) { ball[bcount] = b[k] / sqrt(1 - r2); bcount++; } /* permute Y */ /* Set up rarray. */ for(k = 0; k < *n; k++) { rarray[k] = k; } /* Convert y to a full matrix. */ m = 0; for(k = 1; k < *n; k++) { for(l = 0; l < k; l++) { tmat[k * *n + l] = y[m]; tmat[l * *n + k] = y[m]; m++; } } /* Randomize rarray using an Splus function. */ for(k = 0; k < (*n - 1); k++) { l = *n - k - 1; m = (int)((float)l * UNIF); if(m > l) m = l; temp = rarray[l]; rarray[l] = rarray[m]; rarray[m] = temp; } /* Reorder y. */ m = 0; for(k = 1; k < *n; k++) { for(l = 0; l < k; l++) { y[m] = tmat[rarray[k] * *n + rarray[l]]; m++; } } } /* Reset random seed using an Splus function. */ RANDOUT; } void xpermute(double *x, double *y, int *nrow, int *ncol, int *xlen, int *nperm, double *zstats, double *newx, int *rarray, int *carray) { int i, k, l, m; double cumsum; int temp; int newk, newl; /* Set random seed using Splus function */ RANDIN; /* Calculate first z-statistic (unpermuted data). */ cumsum = 0; for(k = 0; k < *xlen; k++) { cumsum += x[k] * y[k]; } zstats[0] = cumsum; /* Start permutation routine */ for(i = 1; i < *nperm; i++) { cumsum = 0; /* Set up rarray. */ for(k = 0; k < *nrow; k++) { rarray[k] = k; } /* Set up carray. */ for(k = 0; k < *ncol; k++) { carray[k] = k; } /* Randomize rarray using an Splus function. */ for(k = 0; k < (*nrow - 1); k++) { l = *nrow - k - 1; m = (long)((float)l * UNIF); if(m > l) m = l; temp = rarray[l]; rarray[l] = rarray[m]; rarray[m] = temp; } /* Randomize carray using an Splus function. */ for(k = 0; k < (*ncol - 1); k++) { l = *ncol - k - 1; m = (long)((float)l * UNIF); if(m > l) m = l; temp = carray[l]; carray[l] = carray[m]; carray[m] = temp; } /* Reorder x. */ /* loop thru the rows * swapping each value with its replacement */ for(k = 0; k < *nrow; k++) { } for(l = 0; l < *nrow; l++) { newl = rarray[l]; if(newl != l) { for(k = 0; k < *ncol; k++) { newx[k*(*nrow) + l] = x[k*(*nrow) + newl]; } } } /* now x has the original info and newx has swapped rows */ /* go thru x and set x identical to newx before swapping columns */ for(k = 0; k < *ncol; k++) { for(l = 0; l < *nrow; l++) { x[k*(*nrow) + l] = newx[k*(*nrow) + l]; } } /* loop thru the columns * swapping each value with its replacement */ for(k = 0; k < *ncol; k++) { } for(k = 0; k < *ncol; k++) { newk = carray[k]; if(newk != k) { for(l = 0; l < *nrow; l++) { newx[k*(*nrow) + l] = x[newk*(*nrow) + l]; } } } /* Calculate new sum of products. */ cumsum = 0; for(k = 0; k < *xlen; k++) { cumsum += x[k] * y[k]; } zstats[i] = cumsum; } /* Reset random seed using an Splus function. */ RANDOUT; } void xpermpart(double *hmat, double *y, double *xcor, double *ycor, int *nrow, int *ncol, int *xlen, int *nperm, double *zstats, double *newy, int *rarray, int *carray) { int i, k, l, m; double cumsum; int temp; int newk, newl; /* Set random seed using Splus function */ RANDIN; /* Calculate residuals for y */ for(k = 0; k < *xlen; k++) { ycor[k] = 0; } for(k = 0; k < *xlen; k++) { for(l = 0; l < *xlen; l++) { ycor[k] = ycor[k] + hmat[k * *xlen + l] * y[l]; } } /* Calculate first z-statistic (unpermuted data). */ cumsum = 0; for(k = 0; k < *xlen; k++) { cumsum += xcor[k] * ycor[k]; } zstats[0] = cumsum; /* Start permutation routine */ for(i = 1; i < *nperm; i++) { /* Set up rarray. */ for(k = 0; k < *nrow; k++) { rarray[k] = k; } /* Set up carray. */ for(k = 0; k < *ncol; k++) { carray[k] = k; } /* Randomize rarray using an Splus function. */ for(k = 0; k < (*nrow - 1); k++) { l = *nrow - k - 1; m = (long)((float)l * UNIF); if(m > l) m = l; temp = rarray[l]; rarray[l] = rarray[m]; rarray[m] = temp; } /* Randomize carray using an Splus function. */ for(k = 0; k < (*ncol - 1); k++) { l = *ncol - k - 1; m = (long)((float)l * UNIF); if(m > l) m = l; temp = carray[l]; carray[l] = carray[m]; carray[m] = temp; } /* Reorder y. */ /* loop thru the rows * swapping each value with its replacement */ for(k = 0; k < *nrow; k++) { } for(l = 0; l < *nrow; l++) { newl = rarray[l]; if(newl != l) { for(k = 0; k < *ncol; k++) { newy[k*(*nrow) + l] = y[k*(*nrow) + newl]; } } } /* now y has the original info and newy has swapped rows */ /* go thru y and set y identical to newy before swapping columns */ for(k = 0; k < *ncol; k++) { for(l = 0; l < *nrow; l++) { y[k*(*nrow) + l] = newy[k*(*nrow) + l]; } } /* loop thru the columns * swapping each value with its replacement */ for(k = 0; k < *ncol; k++) { } for(k = 0; k < *ncol; k++) { newk = carray[k]; if(newk != k) { for(l = 0; l < *nrow; l++) { newy[k*(*nrow) + l] = y[newk*(*nrow) + l]; } } } /* Calculate residuals for y */ for(k = 0; k < *xlen; k++) { ycor[k] = 0; } for(k = 0; k < *xlen; k++) { for(l = 0; l < *xlen; l++) { ycor[k] = ycor[k] + hmat[k * *xlen + l] * y[l]; } } /* Calculate new sum of products. */ cumsum = 0; for(k = 0; k < *xlen; k++) { cumsum += xcor[k] * ycor[k]; } zstats[i] = cumsum; } /* Reset random seed using an Splus function. */ RANDOUT; } ecodist/src/init.c0000644000175100001440000000422413131506235013621 0ustar hornikusers#include // for NULL #include /* .C calls */ extern void bcdistc(void *, void *, void *, void *); extern void bootstrap(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *); extern void jabs(void *, void *, void *, void *); extern void jfirst(void *, void *, void *, void *); extern void jpres(void *, void *, void *, void *); extern void jsec(void *, void *, void *, void *); extern void mrmperm(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *); extern void newpermone(void *, void *, void *, void *, void *, void *, void *, void *); extern void newpermtwo(void *, void *, void *, void *, void *, void *, void *, void *); extern void pdiff(void *, void *, void *, void *); extern void permpart(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *); extern void permute(void *, void *, void *, void *, void *, void *, void *, void *); extern void psum(void *, void *, void *, void *); extern void xpermute(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *); extern void xpermpart(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *); static const R_CMethodDef CEntries[] = { {"bcdistc", (DL_FUNC) &bcdistc, 4}, {"bootstrap", (DL_FUNC) &bootstrap, 11}, {"jabs", (DL_FUNC) &jabs, 4}, {"jfirst", (DL_FUNC) &jfirst, 4}, {"jpres", (DL_FUNC) &jpres, 4}, {"jsec", (DL_FUNC) &jsec, 4}, {"mrmperm", (DL_FUNC) &mrmperm, 15}, {"newpermone", (DL_FUNC) &newpermone, 8}, {"newpermtwo", (DL_FUNC) &newpermtwo, 8}, {"pdiff", (DL_FUNC) &pdiff, 4}, {"permpart", (DL_FUNC) &permpart, 13}, {"permute", (DL_FUNC) &permute, 8}, {"psum", (DL_FUNC) &psum, 4}, {"xpermute", (DL_FUNC) &xpermute, 10}, {"xpermpart", (DL_FUNC) &xpermpart, 12}, {NULL, NULL, 0} }; void R_init_ecodist(DllInfo *dll) { R_registerRoutines(dll, CEntries, NULL, NULL, NULL); R_useDynamicSymbols(dll, FALSE); } ecodist/NAMESPACE0000644000175100001440000000076313131451365013151 0ustar hornikusers## Functions export(bcdist, distance, fixdmat) export(mantel, mgroup, mgram, pmgram, MRM) export(cor2m, corgen, crosstab, full, lower) export(pco, nmds, nmds.min, min.nmds, vf, addord) export(plot.vf, plot.mgram, plot.nmds, residuals.mgram) export(xdistance, xmantel, xmgram) ## import for S3 import(stats, graphics) ## S3 methods S3method(min, nmds) S3method(plot, nmds) S3method(plot, vf) S3method(plot, mgram) S3method(residuals, mgram) ## Compiled code useDynLib(ecodist, .registration = TRUE) ecodist/data/0000755000175100001440000000000013130732142012627 5ustar hornikusersecodist/data/z.no.rda0000644000175100001440000000110313131506235014201 0ustar hornikusers r0b```b`f@& `d`aqj 4P! ٿuT:GǁW&*:|=n B_ jW:oPZ"~A?[z z=B7@(חh< f8c~k;{JgrڮEWbMiȵWod~'o DU]f^F笰E$_GrԼߑr*7?tzߙeG HqBAּb C 9P&[^zQ~iLx s ,/׃ Jՠ;t[saRKҊ ,$AڙCu0M(83?Ps{Uecodist/data/graze.rda0000644000175100001440000000476313131506235014444 0ustar hornikusersZ}lT?Mc!p\߻;l&~6H" @RеԪԒ?Z5T*m%RAiUhH4MJ)BU#G$MPMBKz~>YY̛ٝînlx<=3dz0k#O,owBC/U^Mwo]?<},)~?wCwxln? >xQ׫MϾ{_Vz(ߛ;~3{T6 S`ݭ{|}#}gn?vz O>G _lK[_uw_B[No> ~zlㅏ"~';H~90~yJ:?|f|%ܕ/+^lW/&ڟTEe=r"~w>z95b`ARگhl?$|a(֣ZM`s`DZݰr[_j24♡V{#ױB*Cj.FwbIg5}cK6os']eZumτ_v>*6 vko% ]Mw;RZZE;3)]u~b]W20 ~M"dOFK[cZ&\vQF3^~Ac)Y%:u6xz?򑬓@Oq?YǙs֍'|%wuy&[ޯ;v~_/DZe󫊥/0.qf_>G1.nִ]@wXG=rw{U.`oabЇ~*/"zCu9 Os);NP~Sre}f`l(I^Binv0yz0^Gم*o9pS뉌?掞wL_ F˪~X*M|0Oҟ׃oO+zc<̋s'@&>1>t_|Ir鉗* ?W; N6]pSMz!7SW<'~ 澂s.^8ckC }lHLOM#%KW?ye\QWpUS1/3zgGzuxqf&yź$7F1rQ\2q'b\3v ǵ[ q/IKÐ| (ӍWGb6s4@^:(_V:֬[ =ahêzWAkc~OZk|N0Ϛz7y{M%_uw%76|d=yg<=o?G`c>1/s^?'y~D4KM2xN8h;&fo5tLef}r瓿_sB'<5k!yBOg}>'w7w.wO{ߧ ?{ k \6NkN}CA.}))?.,uU7\>ǸM_y@罄2'}/%q¸XSil9CO۫azn|o{X@,h+|{0~5o'kwbC}OE"; ~1u8~˼?[ɟ D?=?3OE&?Ρ]?yX20gMw]wJ|{={]]={?v9#Ñ& Hf5Vo;:!SJHS+|op3 n{Ns,lkkwl{G'ښ[FݶXmm3yG$[#d[Ψ5n-(*k[Cђ[k_!n=;s*}0a}pJ[3K2[.tK RUn %AzPЃ!Mx yB^WzxP!=(AA zEV'_ʆuX{#4ÒHJIC8` ~90ecodist/data/iris.vf.rda0000644000175100001440000000042613131506235014704 0ustar hornikusers r0b```b`f@& `d`aEzei |@d=.~اx:Uel?"+S-ՠ*\nI|O7 Y}޳}mUᅤݿं;k|/}\<\ PQp%Pu`uyԂ=Լ 7D,<3.Z "Qj*!acA,e9hdMI,.d;?Rϴgecodist/data/iris.vfrot.rda0000644000175100001440000000043213131506235015426 0ustar hornikusers r0b```b`f@& `d`a\EzeiE% |@F?(b.ͳ}ö+w_O}ccm,1?VEg ֶ}n%w=ٽVe[ N*c> Ǖph.dNR`O E PI^bnj1- U'V N-HIK/ɀqC3SB<% be2F0FRPHb0A4 >]W̬ecodist/data/iris.fit.rda0000644000175100001440000000535413131506235015060 0ustar hornikusersWi8[ܕn2]E+zשh2"T( Mdj-L*?MSrxppn~CyZk?~kۘ:;A%htIL:U(a}w_T/ M; %D~J)$iF5r|IRW^NҥfJ̘ Uʛ򃑿WEűV׫I"qS~'oi/5Pt' nDk֋EOPi3MDJIJy>;=n&'NoĴx1C?Iu_9\*让4EęA(tJDRw9<}5bճI xeZK!)m!- (DC#+eIWm/HO/Aq~BX5욽InS6p?uxe!$J0kDž޳# q9W.kx}#^~􏆕@'llnPY)8gIbC>/{ƽWW tQDkJg@zT,2w5mĂh셜j0۠[#櫪Ώ@/hO76UL:o jy+a㨴34AOW(]7Y;ߧ-xG4y})Z =s+Ns]攌T͟kŁ=cwBWkƹ1B)|M=?k~d9C&x$/f:ߊ!s0!nw{mQ60Z$3ce{/0&Npd(dЩsf]9Nq JjJ%h˔Ő?qQjU?r!пA_RAoy:s\DJn ^ :CU\R8--* r| DYOXI |u2t;lk PQAў&Ǽ԰oXΠZ鹳5{Ɵ\)YПҺ C XܨIa@׉]kH:8Z$Ũdzq6껜$a究Pi{tV:58%'j0h5;' ڴ/UGad:>T=jY1mqr. @K-~u |knu r7LT|r%wL` ܡQj%;B+e_g<2qD!'F5Ͱ,¸k EdC|(A A'v_rnK{F|ˋE3BRrv< 8s4V|փ&g4:k˜{v,lK@n<1kծWǮ^ḼbcVVÜ5xZ>=Ǥ~/)ߎs$6vobjAn^}nR6> SZ~ȩ(h^%u,RtlJ6V[XM ]¦GEv&g8Bfi~!doRydB\>UjWtZ1a{T { WUc2d'9̯"?P̙^1 Q :/1 G`,),~4; ?Ncql損?#3 /6&*nUkq((fJ6/]YXO8p -[aG4inb`c￶>_#C>PP8޽ 07vѾ),ql}Kլjehqy-˛We$~U[]}1hm2\ȵ-yYzzaeiof2#/U~$WPFi<씮Z\q 6ę m _rz% Z-ʑg(^ S?h6hN[!G'tA2q,de{?, 5Oc`!2vYQGhf}`˭ 0BN6myQ*Wki&6Xq&_߶}Vtk* M)D⽑IS1'Jyz>,1nR~e9oI?} 9%Qv7wH%{3I4!s/~z'cf f$Ƥ93S.0#l әUZ_?\[yؗO|Cb}miߘ͖>[_=v>^W5`̍ecodist/data/iris.nmds.rda0000644000175100001440000070472713131506235015251 0ustar hornikusersym}:]oyGCJ3 C1_8м%x2o|?ꞥR8H!qor~M;v!_ egAI^-FƵ>3.Z L,4g\o.9)ߔ~`pϙs>'`RK AG& (9mטּF1L7.UX0.^Wu)},h :[vNtWR} zy[oMo+<;c{Цyw }|G@'k[pضpu…<8'::ԭ&p]G?x2 0&kb U'_#3".l󻺥&1< Ĺ`¹~"=|js: {=BL& 6zѮ9PN7<0F柏_ lZn]m5yV1[^3}9Q&e >4N\?E>Ჾkx18"kp,/ځqf8HRlS4f^٩c2S͊ I@ ؗ5A2/;zΦ/[EQz,0ab8cr6W0 ݼz4'0nG.O?#fW};y#ݭ1z'0 W/i..VQæ^E/,11Nh|MQoQ|p"i+U_X1ڠ)ep#+`|c"xB[#\nDɾw+z cZaqIF0+$2O7/{cڴ `Z];BT$hovXs-܄ƦϘUWxl.HoS $PSܽJNCQ[Ara|%d/:=5b)Ұv9.-pp[ԊS~JԔuc>WI׿ dʀIpKx`zYGkSK. Ȝr8J*/>}V6tZ; oY%(TzgC"0—{n`.߬KP}fd)Tj1#*? KFp^ޝi/\%q^@ g̓D@u蘞:{_?eh?FixX-q# PTy#n$"NLֆ;n>ݗdv¶v6{1Cr FfL&?z0Ֆhq^f^D6}SDpEy?ߋc#ۮ7*!\ci- (|G|J,ApYgͻ!| œo)3"LĜP;aw T#qp:QV-fVj`7"4| RkbTʅtKLFLCD=BHr=3Lj"g¶i6o) 'Fc|N&m"x)c{]1}`4țМnX)I6RC/hO|GTmM[kpjie#rz=Jpb:E+i`pC-ah4Pv[?0Wet/ Me LT}&P~apظɩiݎ%zksAPo5~T}aoAGjʶ`oZaX{TnpJ{k jiCA_g ~S;;}$|,뿵*DNʫ%Pkӓ7VTj (_EGSh {3)( =rllK<Snk3],`ȃ9>m=p(Xz1qIbZ1W=`eZ, ,NY[d /lH`Lɝ  >`LG$~zh3P^V2zO}1&uk`Meb>XJns>N䣢 Nxy?/Up fϢ,h^y ]pt LU{eᱞ/wb,42>{\`5'8XW|IC} oFYԀid'/ec99r;M~RQ"ڊ>3:5E1:'4*"\3W]~D D|_s2A۟sW[I ќ\B_/# Wo+"?0C#(c[}pY@D֏[E]D2fjt[ C?`'"CsƢ"<+\wF>FaNFw/"ўQӋo8bc2&KwUz6":lνDj"9΄'#Bek^:{yľ04=b K[oX ߡ/ۃ)Id)̾CV`$Oj;*,}#-YAE.x0)0N9NϰVFkVAI\!$h蛰%McqZ{EPnm ܦ)ɠ{NS]z f?T3mX}os77MB`u/.`j9\k_fv~j΀: ѻ|X) y#s d wɉ?A=H|裆'Rґ"PTp#(r0sTt2{tfWcF>xf;7t^7 I;%|!=ǞXoV]80hVoySR `KW5l8FQ'uy|X*ۭ?2:Y(0X\(hVV+CS:Ms6u;!u39E_>3Gr!D0Sc7e/ 2O28޷Ls~ K-MnaKW{S Lǧhڢhmu!,%v&`tv/dY6~$>&7]Ư:HFc ֺ|G%*vG+jbxfs`xo30<;loY 5FɋkP4V DJ>ň5_JNb${ZUDr3 |'zm3њED,ϨB$yA"F+HĈw-Y֒Wh q(MbNb놬l "h1 Lj7L`H{;)kbicg(.+[8|t3Uv?Ҍ-"loy##zi:tm AEf*(U1Mx:F3HE||QK8WuDtܥb1-)(e"0_i>c?!!ỽWb)+CR[gC1Bv+ V5za'8LR_-!+)̞^6m|ߗ~߼E?⌘X9Le`={Ζjsdh e-Ys-Q(@϶ 㮫F~ 'P)hkܟy$hOy:or ojݥ'bjTK$PH}E({w6QOFw-X ԽC_tnYWnyUͿ@w0_l8}1 km^슸"h5ځPxЛ|)dt o{=8$*W=a%5y1qOni])¥E̠ fv;.p(oQ'<4=[V^(-=O-\S@ R#G2i7 ɶK'8a5#\:aKs'F mʹ.F6d&S7sE;> ۙZ'2}lj'ræ<%?>MR?h/ʾN&>"FX\Z֜sv҆Cʼ:QBͳs&I|2ksu^ZnV64IU.]&cC>D([&p\pD ձܩ#&2 hw[8$RplK{?DQQ'Aqi11QMDbcrRGlq#O-!RCͽ{1F:?Tt#|Ȏ(umxaT.og ~[DkQ hT_z]헧1rˮ/)ǵ# 1^"N<}5 j_ 1BWw)D}r+?}MB%=DLxQ >!BD\]~9O""˓t]BX>?(Q/ՆqFyKX8Fk[v"'Ğu/(aܪ}FRٝYFqc{]pU Tz0ve#T6r5WtXl&F}]{_,\l. {0A @鴯18 G O,'i?_΀O?w+S@_i]0c1 (hKVV%I nk|CCE.LnUAP.bzo{êBb@uƛY_auDqefoC&˜%c3<p0lXsj=IR N4dzpjvHlx\;ZCJiy/g-AIShX:pu#e>$Reo;\|RM qitɠvimpԔ݋W Sj"`.#EE`#n}#\0p(Su weÑD|ppEL^ X?"]\pXBF/%30&jPDlKۚ/"㛱T Gnяk1z3p8IƨvHݰU1Bۚ .I'uB`Ӎ' _Įyp^C2\ *i9ζX`[Nf8ZnYY 3ӳoZkIWد;pj<άVh 'w7ȍ.[rk9}=)[ c?Aͼw;Vo{Pa8"w""c7S~D2zf+H]nݯوdK"j7XD,/!҉2‘{o,{7qQ o$V7!iOW/{g/"kҮp Er|qÆ\-|cf( ?(GTa*!-HIDqi(&n]Fw+D:tt}j>^B%qís "" \=8&D~R?^:GCjA{cuAD/erpLʗAyUU{hϨb Xzpx5#p_{:bD4cN-+@ #N9w&Jmc`] փ9O2؂ De!X|7ZE6p|/+A*8M#Yd]#vt~c H7naTj;2J3Xy|WZFQQi[EaLAt"V?Dh5hDn r1ٯWG&>ꡚ/\Y&Ł9=]yiH%a5à)pd|0\=O.ewXuHʮgVpƥ 0"_eSt0r'/ L)PϽ S/YlA6;]l,& N [#*{9!*kׄY,FYP`B p)$NDg0BUA<|^F7[J7DŽ)j:D|}h"/pλY?NDqo$1fY17e:̟HBbμBoDx K Y0U[F+7SF``2ef0%64xQ[݈mǒ({;.Ib$F߃<i Ņf]F;>/}(Ɂ E(6v^c][ߗeËղw`[խo` wHN;#Q F'6T/&[mlb[Q79kOGfTG惎Y+pkk@ | {;5E pnFr!86g1 ^U Ij܏VvX3lN?~7(zcrK78l>"Wv+Ie&rq#`aܺyF>\t=(NԎ9mS4g Zʮ!ЄƼn<e'YN` %; q.  ,$pvO-z.ച͠4܌iJApʹhv=Q,]a_E]Tr}0wp.N{vg[;&4c:pi gq2h|jq>jt *'(nj=je7aM毛h{?V8$ )kwo8sϓE?lp>mchKr9i=d 887:5 m,&g8]9 SnԑΝf+(v? g5 ; |"Oʺ G_ecK 7rHȧ:<:f7`A=[0„ C=Jc0#Kň/;N$G'?̭bq7NQb#˱s;s8ٞ z}1KJu`"R$;aO0i?xtR$#q5ye _Vl[.Kv9^t{ on~QDWt;DIei6H:NHäwy!vFp. ED-<ok|ݗ^ՇH" =2Y7f5xE^>%}"]Z>%j  Z÷B5jF' a]G&bZ6̌<@^?p#^5'O"2{`oPFlgH7g@~oWϡ,Y8l:յw=ǺEm6 %*GF3XpJ _8rp/Uӄ mė"ڊεbPnqX?e[Nò]a{f ֛?A bv͎ݔ1֭rR]oأ^O [zu|hAU[ %TYt$qlJ |2%,u AGYؤ8j j2M؁/FJTߠrvVw4l|R=%*EYnko3{~wC00j=&hNfD &w%#qu/GJjjX AB!8p pN$CLNo,DM!Ehi;#_<3,AWiwl1F ~E[~f N *tq0.M7Ol}H'͔8/{)\>&nr?M~Pv1IdvٷQp*˓CA nX> [+)dqzΘR8Mj0 ?Mhtճ ww&pXBQ 9"{Sl^ Fg=_w2F<;F0u[5"~GQO{LD{}{}QF({?GF,%ވ\R41a;Xi"fKDV8]u"q/8~150FPyDB. HRv"o&:҇(EMT R1ft`BswS汋;"| "K\w.DNYW#b񱎆IDY#xdvA#8Dv)0Uci('Mˁ?02|!+0_dxBSջ.0`k;q0/;`yE˚zFplm=0awF&> 0F*@?I&/;@qg&ϗm"R/du"0>:-su#oVH^ˈ,lzݏCa;ej1DT6J4!EV"HF{3v6! j/RaD2LT8Oz[sfVF1!^Q_HWY;܇孈zP/=uQt^|V%026<]Oua2"f #d Uk$@(S.-P7s59vڞ%:g 3p.yԀ{V5Ap(8*׶I~78 k_ ~%1 }C|_O>%]ߢe-W L`u~ D>qϥAn<^i~\d0(8# #>)m=9ֻX݀h Mʶaَ6p\@%S z gaf {"2Z*J[X|g Xfe ,ZbZNzK[ ^o@gǐT1W= KxmC<*#dvӜ18"KWJv̴TELkSDb7nAm 'S.K61PĉSPC5u+vK:vGh}Mgou>TvՆ[uZR+`}`m!("qL6א !2G1~!?&ϝ:^qaB`?0]3>+o8я] cky5Y\"ͧԿ[FC:8|Kˆ=V>ci*+' FSG"ZQ._Y9'c"vƞ3{<~zmS#Z?lF.O#yhuZu`iΊ8I|ԧ1pv,9hk4 UL@{Ζb˥Wje:micԤ Ҳñt%Z`GحOp|6ӂI2T\u[ΰ7\ ^ b&LC2AbN ݕakr?]_-P%zY۰yOq.bc?rbϋJނ8`dk.wvYȰP=/ENZ:/b0n z߮ -Wq>pH  F4+2IDuOD5]s@8/j|±"cxyQ\ =$#Ԯ[>=+D**ܠnxh~#]'v3v +_VpLAL'`a~.?M!{p^Iy7ʫ:>BTApWfσ+WġnJ3\ ~NOh3]+F{a2[/=# 02k7W1|X#R%1rj';KˎQTf GM?*E˸h=O.k>^M,Bh9AnQNW0҂jƾs#o5y {>#Dice\K$sQD\2F;h|G5"zfg8Lx1r2bV¹c]_6dh^%p[s$~()\ֺ3!2z"Y$0*J/DѤEMD8Rrt5I Vш:2J`D$D1CSL$Ye~MWR ]lz 2=æ YEEؤK̻.[-m>ś"۾j I}J2lh5_a)i@*gAW zX( _W >ZM^ϮB~4WU.KTW0e=n-`=#nB$|!1<'1+b`7g]<֑ 3^l85ZS6$H(>+@OLKX5Z;#g~KW"UK`[#X˺JiVp5zf3*Ƚ]߂ÊE>%B2_  y X6J 4O;ÙRҀ("8M0kwScx .O ӞqBԀKp˄x洱.v}&' ,wmkַ>:a?+w_ZL&S@RڄVv *s=sRg=!5r3,Tg'`}CѠ;\uP/Ё7J|a9CbaʻFzL怱cu0:{w 0u0><2wsCŴ5 表P8Iv#X:Ux0ox(Vnܾg4`DhQݜ7`Lwʧ YbK hћQ]QHq AJwFpy߆wZE+wqolg+Vڠob-uͲ=1{q~NR,Fb⶝=n(Wmkޡ(s  ؘ}aGR1: #A퐳189bfB1&s>fHCg^ngWhF>pQd/s_ÈGdl߲}1j]jO2Fz\bT+ۻncANQ?5F|7e;cWQ^zʎYct}&>r~F$.}|1s(*j1Md3t梫$F]'ī7ép%}+ƨhU3Ǟ}z;d gO σHHy8ʘ7 Rfy1ðX/ R]Lwg^T): N'}Ot]&uJ|ﵢ= 'V#p9Q F*Wl?WIޮH\b"eBoڪpI"Rc؏Uȶ'#}hpt0pK$"Fyr+m,u6Ο>և|tǾbJƷ#1j:MFpKGduK{{ d e}Dĭݥ70 ÿ1ZQ $cYiL0Ijѧ+aK L|³}1g[^I˰""$6Lj enbm۠84If;}޲ 's=Oҁt)pJ Õ{ܫХƍhv`peL޿ia&)! v;Kp8x\Y8 ΕeO{I{G>:õ`;CxνQ{ȓqmgspu܁Gpkw"zpH:"\o_1\|$@.G| νQlpi?i 7o $lϼ7g'Έכ,\y"6v[cwvs/WhåFop_}dtm[ w2\hVo\ yZvxT ֥w}u3ਸΧ^a$fv E"="ѵQXL(Vv6D\D{'쌈5_wKN"ldovDuӔmd v >r -cTQ#i {TH 5eB~|g lrXDNZwQ󸾈""Dl|8$(/b65G`g\C`dΘb>rv6{?QZLκcўK%_,\Gcozaшqrmԭ_ynE4b31k'è0 Mby &1ǜna,'>#հ1 }23ռU_Vؖ4/r\B؏?@4>t2t2ͤ2lȱ8wS9Q!m7"ak|g+%>]P+. f?`3!V0vA#0V? o /mS^ۛҡAo[;O<ba_'o?wj/(?I[^^GX@U08A9 3%ͫnk\J3W('?',v g zjesႰ7(۳0gt[ɂEC m_=ct-0K~sY7 TTWܸıRǙC,ǴYPCi:fq1ĝϹo4 =V ާh4_И(:51YpbB^5"z Δc]7~ 2LU%Fv _sÉsxHc "?ھ߾2(hm]ݘkv)bGlxو hX÷F!⅞6G8ˇQy`h;! xhXvgX0|9U^DZv6Dd5lV342$q1v ua;M><'D10*`Evo%pTs#H![U}V~7W42*Z6}m3A%Mӷgr[pWekD [bɠol5 >\=%:.dڈ( Źl` {8О`gͯE`|34r)6q'mp)YQg4ۢ;/>wO +.aGL8^瘸ꜝ^F8[y:KNQmWb:+џxoloџeUR {f=0j||LIIv9JNT-#XkPaDP Jv}3ݘN4$W/CK'135pq/'eL( răr$C<ޭf2= gr̓R޹ԬsΚEOl kpuX r1ԨxSݠ@cҦe&oUgL[l0ndk7L FvP7z9Lm21r' ޅ׶:e\;yF|;#] siyyIv aԭTمH|}'"80R);4qy!7:h&vJhYlkhF3B$@&`oi&VIxPOnDq3F|۷UOUhNEP1B|#Supd; k<9Uk?ooLFF3hv||$Ĉ-rU7zT\wQ|-L|0_E3uI""Y~ptNkIʶeOV|ծ|C@TLo8p\>tL֔MtR).(x&?XX^$C0OdM}8/ JMlپ(?l_e1_=0•N;*oFi^9FO#+HYIFZG-1=OWF&ۛt\4F7{{.y`; >^!j#<54z: Ѯ= 0J9!]ڝ@5F\~qtOY1tucQ.?cd6#&Ma[k-nkᏣg1lL+!YEfEogp !F>m|>5i*X/,`y]裲Qʮ̼b0!JovT9{7NϽ-'QWK0rsf ;8$rH~.t,K톅jl_ =sSzC 8ckexi0Thij~`)skp^-, ?.UրSԡ q^38n{/ [a,Gx8in!jT^ oaõup>$p8ޖlu9DZ8U?l&8RhSys䲩%dQF. p w-=8k{(yVr80%[}f-2o3`m5}t|,ۻAz? &h\`$[:BĶ Q$\O#!dA1=U~gK%ZǔJ`ig@u_6DMzwz{Wz]ֈ\$L3r}pQ0/o]o|7ZV֭+qOԔB4~0WxkKFD{݃~:2H Β6JC %\ޕ B /sM;?o1k ڢ29QzH#ڶ+{jwpi3mjt2x:j l ..%uLY F# 7vM1|Fbᦆfқ: ;oEVHfpF9ufgXnEi>Ȱd)&^1sn#OeA)H va;!3Ng~iɨ羘 e>M?m"B8P.?8e Ly FY&5`,Ѯ:~tۧ'/»7Xi5*zw*< 7+{.D ޕP@?o`lLEX--Vm3<`_ ^ѧxjP0@d ~;& e? [w= ._^gZ57?LX֣{fwd*)uݽ|"ޕ=\\~g<z=KCq7pmQ/E^uڨ3DZ8꘭(u:lQmy j88T ZʇcQTe8k-?\kwo sҔgqcqs*5鉬r~g?lctE =yVuL'j/4  ރLSquhr/Ɨ fZ! pkLn>l4kAy?$J|bսaK|K>5/=Xnډ<{Agpk0Xo?s~"3–_"fᴤ*Ϥ!IQ] ^S_ԉ/~+ʤ_p؂( ?{lmX zcK`ot0Eu)gځyԝ0бL\y><ȼI=?Ž6]bLES8j\Juծ.ⱑۈq8F#W\\P@igv#0h:x+%ñk wMA=X38rjw7:e+S0D_ fNYhs|x8\_ad~ oͱy9'xe, ,3/|@S2h,q>iph;V*90Wf =(~ >18x ։{ )>O¶}RysTވ ̼Suz<Հpv^5,߂lQra?T0t`JpFH] 0okjI`l^On!9azm)K +#3aV9w3Vky #V$7;3SH{tPN>?nvJ9lk{XJOr%Ůw^\W̺Opw"x ;5\' {w4ķ}wDq]*Of%EbgASb^LnO}2JP ,NH,fg@pX_kXspp0@]"g;,gÁTݑ7)ѠXF%rc>]Wcu=0S%#2Y*l=MD8LN8J~rX1Dѥ`<(Wt]Ve+`pGf$Z04 A“_\eX{Ymw,T^s3g`~ݱ7s@ 0B7v}ZxޣO=mF&ϏnK!ji* ;Dj.depx g}MyaJ[AUjl9ߺ,ti${6ao.!`:ϱNr4`c=@;?xlʒgfF|%jZu&׹yrAE c8ƫ 2a;\2lz J@稊5 T ,v h?mvj`8?4FqXfd'2bSy00>]-,\%HrƂbAkIV X .>Qwvj[r=28] -tsZj`j<x`ӦTt<}R+96< %$Nʀ+`@2yA`}ĩt~ a D+{m:yxsGeH~^~dmeiCw#jETZ紫ڈBÁۿo{9]BW3+#=L,H{\ziRʫQY8!yr-#ż>K!t~0aÈtG"DJg# .sđ_clvwX1DG- ڌ-{!Z+e.~+.5EkbBk0"M:>yHqՈbנHG}Bao) D?%yE0&sCڧ>F(}8ie4D䬏j#ZǾ1&-; R 3m{WO!ru1"~"-b@dEUu'`r ΍&聹O6q(x#.=`L+E־Nwo{XSqJ_!̿^p= twv|E/A 0 #yO^Ge~Ɓat sf땵Am{qӻKNA0 Zz/U^4SCY<+0[W 0gˀQn;{XnyJl6_u w]z jY1ˎ$ou.4m/lu^'qjbc1LUu`̞^3ˠ]#Y}mz;kfY}t9 sU)a\dFJD+F{=Cli:!T]fsp ,t~B<0\q}s5aXۨP1 eao>D|]m/AҠ0bURyHZ?F7>`%1UmyUg".P mjyۭa UNPrg90j n,+ pgG~$cg|wʹ(|#~7o`xmw5_70dViRxbэտM\ˣN<{䙈Fd"fr^p:WL`$@_ڻ`1V\4Ͻl ־Lpc-:G`)Nʃ-Uo 'Z<3COKQᒸKy=\H_g/8_ J5ZN=.f/e_Ͻv_*@-* F/?š?祊_]' pW5 ' p)2A_.:9[iLНcЗw;Eo;h1 y/׀l90if jIV_w\S^u\%݅TҚ]OtƍrSe`z*HM"v} `>(ct(W:B;q0,^5xZ8P?%災6\{ۋ@ɢe@o-͓6C&I&? cu +SJ QCx怚MpwƮ20R{=,q-/ D4A_gtj@&Uq%Gh4Zj%S"H}p 9? sMA+;_`)4ޭ>>|lu LX%{e0~l,I}`tY?Vs"=`,SMtql<i 5< O963S7c | 5f?h<98 \y􏔘}fU`㌹A0de}.c|w;nq ݬI-K s[*Pf9UGs{54AJ.3G/Ͷ̸&k?{U&~оE`঎y:nn=C[?X([nP4I% nO"fkUWE9|AXD}s1" 0u8#|JHn-_өlX,ɝQ#T.^3ڣ֙gx`dghdBLǨ&qp' 1"Yփ cNKv6MCtb)ؾéj^xEZ+ow<G=fdm OLyY\p]KaxÛ~a6oFcxcvX[sFpymH W1ܮ NS`2#) l>,;!v#D $`?vax/1i{ j穯fYa4Wϻ|| ~Irm*]4ӹs^ ]ظ eb961냐(i+ #>: [:4vCDPz1 g?OP>4 gIt.71jyD1NWgSZ7:9[,) 5]ERX,\KS +Y.Y hῚkʃ[M秢v =O!`~%խ89YP"pMڷX{6Ϛo<X3A'0\/b^>kXzHڟbfQp9_Y=fi|$0`͙n)SW`!8mPxYÿb̴e~% ;OU]'Ӄ5Ok`fig`~,2is70<$1d V8m9»}Z9g)Xm(}|u/>5/Rj\tfj’ Ke%G|9=U"؊;PB:R r4bgԹ5`fߓZqr$ʂh] L.0>ɶ+Q["8 /ax֢Kwx\sa[WX;zi:ؘOzRpxW8>Tt1\H$‰_5X2a޽q`.GWy/vwX8 z2g}uBR&VD,u_N~2M]M}pxTGe6`Qa g.4=FW>>v<`M!v827ʇ,5p21';l)&&ÅAvრݠ(.yBd9q"(j1o¡xHYO8HE[$ee<5IZ}{S2 "Ϳ}Uaك`>lqr8n1TDku,Kޅ;c?aoaLE¿MsKbWEo*#j!BƗ~"Mы v#ʈn _ ܮpv0+^ Uؼ-VAIVp=?g#\koO=39jh&nrqٔ!A؀GFf_pBBᘌ\azv4\fH x8?}q;}~|;' L".g.B~\|d*N܎ey ^0rCQ+802$A[q^eUpQCC3-kwvWj1\%S"ޞG z_pDfԛLu=TND.Ǽ2*O!fAH+9 Sr3 p5\ڣ "U\ Cp+o*QL Q Ӑ-\q<ұ/ Fd8RxxQ \jk riE "ר 3k3 |]ZF7*iB޳c$<?> ԋpZAʦ1 W25 7v[D8 BWdHlUT]1"v_. tp=-zpw}+Yb7O.~ yDg$"<0#O[0|ISYmjpkOwfyw;}XRs );\7VIDx'~erRW ZTu0X~6#}pWn?2ztn%s|?cI5 \5g^BRgAXBC*gػ-mҥ~{X|lc$s+& @cְ[0]+'s2(x37&7MngT>9P]=9PX+CV୤1苊| vLl1*[m/6r˝AꁃOܺ:W n߯Zxt8d@{AŲK*nla?뢰kj;ILYfBA+AqPy 蓶J-&ByFK}DcfqxFS 0ܣW-ұ`)OPތ ,q k]'sIa`Aן$,K}aNlf`}HWh WI N% `U~1"GO3WmqJ1`AI3>Ҁs]`m) X{ DKWCN0NA V,.U~]yTAJJ{_/\?XK IE݌G0k1 VG&fCr-d֚OX hh3`.A#X* N L>&ZL1 3U,rO 0`YZ04uߟ`>=n ׃[VӃ[9!.e4Cv^^u \| EC$ ດKpYu)m_XF՟pɋ6 HqJ\F9y4^>s ?L۹p .ݰF8}!+ /(g,7_^hANDD߉ 6Or ]Ή;peOp=zBĽpg\RT4j v?}#'7k'5Dz}m ־@pUHpԞم"En>hinѭ.ѿdFvcVDp&+$í߹uoG)|ơ=fpmԂC"e঻ZNI6vm?2t,nKofēk9Fc J⯎ŀI. T=?նB;nمzM0>[vvM̚9~2SX_WvoAQ[}0k-P]5E1؟SY-ٕR(EcTJ$)%YR^P$Y-Yc}pry>_>SƏUX}G -t.H"m 3^*/Kђ [-ix ONs3|;v~8q̣ͤUhs}FEst%2NzʷD'yu`}uhF)OPaA6~ӕCZD\K _C]>n5U\ qakihiGCq (PaknYQ-6ao_eu)(r:], Zj'a/z~09DFL]T/1JN . sEޅZe,҉h, h"ּfct-锟݆_ܣFx\L|G댱U9hiNu}[:bzW$w"h&=Jlz}aDߢijU}o1~anˆ[-V1uwlrYwFf6\tx)F.U6~x>ƃK\nCkWF1"uwoAf<63̊b=E0V FZ E Ѿ~FK+;YY-a$Y uz#)?Qlՙ74q~柉f&raIv`QOČh# ^u}6c@ cґ~g,٘_6 14Es'-⁤P|vs&!$Ffv4j57/u63϶.(F#B&3ZZ7rw :ebr?Ѣ"$FD"?WzZJv蛂Nί_Bə&3U1kj g@O ^4@g 4CwÅ J T6}5FO޶n}=詭{} 'df!K}`zM::.@;Txݠ@C؈غ3h 9 < 351ՠg/fgモiT "a]?u.BCy:To?3E #64j*z8xlR?܂3O:AI/stO=# 0[ȥy96>=Z.^`h;r@/{0Bh2~c2Z-+ܢAs6͡׎/AA^CDž4- \owfJM3hnM4I KA0Qbx^Du K +zPp;hG޻lk*ңBU'uɊ`x:dT6#[=,(n/bo+ݐ|Qz!tµ4nlCiy7\EAm^EU}_miT>`s!f?K #!arЋu^X=]Sd`xJq:dZ,1n;豍 MO.㑂#0/Vڿ}woSok ּ4d.X8{g3F-~)(=bol#{!ɹ>9U Fx{ΗhU=`Tѥ <V;;V-2`mJ+FJ0pPʦGL6=:0B{Rʏ1b]p|L2G1⩖1Ŗu$"&q F.SuW>roHct3mXF^HĨ:\-1&%{1E |X F#t2Ibq~ߞ` 9EcZF1ʊ^LF>}? #Ϯ+Q1фs%3BʊJWQ6 4k:888v sO<4?%Sk4O)ڃ)i]&^: ˓D;Xa q5MJOtpPm+t lO%BrqMOd+ 螪@i5j`'QPyN #u'EaH0E!yrD^XR4:}s*Pۯ~ ZP드v\Ԗ1 O-*ai<[Qb/Fc;&&S)7?(<(Y73(W,˽0*-V6F"cץ̡@Delkˍ̂e;W%ڏh=HP`N?'3@~WONU{#y81'01U<H 'Kjw4 ଚh6|gnj snO.*œipg=ގĉM)'B`/{\Ixpl+B8IQ\N#yf阆SW^俜lO5`\(q; VĔa@0̺׎f <]Gfh=w]G4t*DXX`D ϽԮ+b,v0:PsDCh͞OEJeq?֢4dsvm#3>JLZ)I$#V4{qJ^DhMdkDvkh#xɬw G:izkw17;}N@*b ЬZR;Tvz_߁9~o2%:pԕz,m,Dcwm, ,h1`3cx$ (GU? A͕2>Dcz'/@V뺍;mP2jmsoҘQ0t:+v,Š2Y0X '饐1>|rrﰛfUB,0Kf/8]Rj0H;p& W&7OGU8j~hr߆FLʕ06'_+lZ!`?ł #Gon%Nd=2pAj?N2 r` h/"b8}8tGN&x7N>!8Մ:N<9yg\|;{^%I `W κ%Ga{*YXW0=+kaC*VZQx,& f:f8<6ȍ 'pT6^%ٿ!|qRg8;XРV=CvgݭDVtO[8Y\wwDӶt"8ᝓ2i۽# 4]:- 偆h-{ER4:/Sֽ[@}BӯkAa 뻣б;V[uW{Tl2Є'1A{U /4FlS4IKFFBr#J%N7AŃFȮ($颡{J@dƬ_~B+oQtWz̲.?<BYMv87Rl]| -߇/ZhCI\:X)Ot0凾KgJsBTZ w3Gu }6L/;"cV'-IJŠEZ\2z+Xoxb,+Z PfX8q&1K`[R2~8"h!_ Qϸ +|] M={)9V8 1}F&BX&KdЊrU"\%~^+VryZͩ-GKK˟u%:)'`ns{(&"9c9FR_M#`>׌} D8h1(-^ kДݷ{+D5Խ@ DsW&:oJkFD&q0}Jȑ 1D0jfjc2 \=Vaqbm3YAk -hI~ E*O6E:yMМ;0wv y\G Q Y'v<b.v+ЬnEZr$*#~4]VH?o8#X*ZRR14B6oҮTf7\AKVnͽ{ w،9H8*Z( ѦhߋѬK_;Dl,dќGtwJǞ4<-@-CU7P&9}^F&@w'50"ksg zsOJKg"Tj˕)t%6ԒuX <#3 FY%Z|hų#5aWE|Z8~aa 0ۥ*j7:2xꡟ+mK+ ٣+#v #%Ӡ^ZIh8jyxrӳ2歶A۶SjzW:7>7|2 tYe^NƗW`>޼3K= OU`8n8O}4 꼊,NZSk0yտ Jb5s@Sl)vO0<$]U]0'x`%L *Kan{Ƭ0_$T'ʧ>G~eE0rq'o KH0}"^DLcPq:2Jk{ϿQ:ՁtE~| ~ZW_`d=45> Fn>HЇBb 9=r@'TU}z;`"Ǯ@#c ԓ'aX?(K7X` `2FݹЈ1*Q5*1;0W i#UIQ wcKD0g&^ Ǩ 'EaԽRchy&?#_}S`F5:PԷ}sbTqiz+QL~. czLOcze4H[`1}1FsE^t#ę0j;,n<~f0 bjFT?W[IEԑ➐}abhk](>a)/x#* ^ԨVU%seEP^bfۊbg[`nyX~J^tc+%D^T^lO 2ĝ 5m4I ~8tw(hr\/: _ZG``x12M!.mP7w䜘 os`L̀>x@?MpE/DP\ɎS?g,(Gq'Yj`nGoj?N.qONQNqՐl ڔe7NT6od`uH2x E'zޯv*>zF̼mcNt&m'gz'h7N3'0ڨ.^ i,^b()ؐ ޕ7zNT9S$35+o&T|á sg.Bg5hBŝ036 TuB5yӨ;u#g.sbx/ (Ġfڨ{"̪/-߭ӿg ihoa\SpgB;">sN : ! PzSu67(v+1vTT)y3+G4鞻%vb+[QtJl*2ykKuf|y i܁W?qN#hZ;uR'l?=ds\3P%6 EmcN0dZlT=BӒ^vDzu1P)'z$ɾ@g~2*:ׇ Y/2=wT>"?Uv֨mAH+ζ7FM]jA}r L@^TCYQw9f'3 70{#42_~Y$h GO︴zDu*CE4V.T pt7DMF3_AU"T9'c6nU~(2OǚV C_g)}t{ލoʨ]hc[jPhE$+zp0> د|8?VYF`1ehPTy{&6!Llî@vγ~o"niT Mn;1o.n)jBLaxTJ]TPq捔M/zes,D)9Mg*  $*[J`ʒI `4w|#/4VF@KWܠoGQU!/0NHo Ag&n Y6eV=C J*")8c}F[Ic5+Դ[T 강;z0$yRfS0S(L_pȾ Cc0S?,<V, thgП2[@WUl)iw<$i9[=׎W$ B߾ctqg,j6q]0.G0QWEZ_C=0zoObĪilƖ1PWt1j(Fh;֙Q]4_rz-Q.rkdY#_ԏH2Ȏ2B!/݃iiA$~c`4eS12i:(p 2Eg `$W_cBg+0b-fclcy#,ۆO-ǛqWamKc$DQg#; (rdiwȝ].Fc4 cUbrkFaa׫7g|8z"47;-oƘiA7b3gbnEv43n=1 7w6bwDGnu5g铲F0N}C֛V Z#ߛX aJ=U*xk6T= {OmYhu~fuh[r;nO$ZۢIdlh/Y;nwy|TTAƖ,|{A3gm]B '25h*#y Sڕ/f`$$ 4 CӁ)֧a NX`iLRGgPgi˼}>V.;#)0c vƋp$-fY+wn{c}^CcC(U5߹E|I gEB}5^zbnx?6[|њ^VCC3d7 f%~8NN49-kzi8lm9;~8H: Npm9gG7,} KStuO8niQIYʨS6ڵHM-e9l2~/,*`bqՁE 8YeONmc8pୗ8XN-_ ۥSŎ0Ǣn充_Q]8'XwĕZ570]hfNdNLIۊ# kqjXSN^ɉ6fq"?Ds#WVvﺡ;"6`26tpvZ;yy xUu5_iKQO="0Λap-OΉ^Ck~vGj)kZ+pDk.gEv꣍.l=Uy3o ^w{׋V~/M2e,ZgZhַ:`2EoW0Qc6[z\Ox4FaK;c*Z}C/Ϭ2w4}P@#??dʊԽNYa~Ӯ1'޸>)UL yَ=6yYWFЪG1b]n:xzQ10˹rUhرULVGFAot ^dz | 60t)v?;vjOVXuS%cl9IN| ,hv 99|ΔK*o4h9Ӊ`{4K `zW̆X]L_t_|7zYG@[l⌆*~j:es VA%-X~In y:KiC*0T30 S m~,*vqvg~@tTnGay2xjx8k%EKB.b+ݘ9 tO2 ѲYdۛkg4Z6uy'R]N*`a҃v5֔~ad uo]!i?^QX"{c5}һu^֖FyFR:s9x-ZcTch խc澜?^闎HEvr"Ik`59~bV^eɊ7x?Z~XV~v*rɮ:K )Z3J{f4m7`oI!ًhnuA #Rc/2,Dv[:aAQied>=Wzsn. KȓPv}$ͱBxTEؠޠ[\;nCqP;?x0ٴ/C5ɓ%T XPJccޕ5C-[H` y>e>;yàʂ t?)^CI@?R9-އSア'\(|XreЦT>hD7_[$6B[M> fʧ c4̌?<=× =y}7 Qa;O<} ~(Ӻ0ҋ]uҐ-le9Cȓ_-h:fL FhZauஆS6 p"1=#,] t2gƭ'66P]'Y7{%8o V˿=/=au7+66J$. /U80[ܨM}b~*)NJ۹Oa歇mͪC8MGISLuBw| ͅu\j0VBC}0:)rB5H7{Gs> }C՘JjNM. t:vG#p/+x䅟}IX}z %m'y rn[]\NĽ05"A辦xZ 6C粎̱4j!L_Ga7ߴ7)B+[0ĵ %@3/DWZC݀9$\,ԅd7~Qn=[ 2Vk4?ˬ*E'|.jjb ŘDy%vKZmCy/lrRտ7W},}"~Mt7Wڨ{v[*ܗBڡmJ^6ot,&ߡ%s6x7%e|&ՃP~7?&^ޟC7Cq9!+sGՑj\q( s"m+Y_F{aIrkDs; _946Jo1 mߍoمjn0#OXn;GorIiI-N}Ӊ%?0v1Ѱ{O kJbUVUXiaK̤7a.r3Fud#{',]a}3n(pk`Uo0Ǜtlh,'[̇ehY<+nK[^,Vw70_~[ Km՗WgT]+,~}s3, oZG%a.fݽŖxIaxYyX*kтщ44eǂch~nb>̳M䎶2֢ܛ|0KI~d\ˀo$'@O͍{W.%,:%hy5>IЏz%pP!H}~~kK֫(p!?hhp>NFm%PZ95:ٷG#BQ'cwhplz2&c;/!mEDwޱB"jxJđδJ ))o,wrE}\yztt ^%I6kpuc?HVcMv^F/3XၤM96J?LNjZ)0bP(c1MOfWϔ`)}м#GXYU#s^hq-9R5#GDbmSRJ4ܐ &4۾ח[9QUqc(|vҝ6>6~VF%ijnp` 闥?gFֻN9qsX;{w ڵo=fLh6ZBFdMパ`om/;q_( fpFiZk\UGK24#o-k?q pLqeCNE_=-g+kc ZeK2BNJ&тg_(C¯=NAp[pol.NVI?|puɎUc8YuoPFɚ ,csdFp苛ݣTd͂t5%aՂѮo5]Ὂo) kc-k:Wqut}D>4 V ;z{quqYT2aG–}Ro^K1U$Ͷᔐ7š?[Z`#KੳZ8g2a研 H[$$vNM81ûDrvOb-k ޹zqo6N9y|ыh|"KNY@Ehѫ0 Q$[iGZ<䗏Gm|Q8)nH/ۀFcj~BHScNڒ VJd_QDȧ,e4F7* XRԕS'Do[8QcġWljx>$|fv4 ]|. digCBUtlqT5t0[t:B쨏tmjMA5E-1W~N _51 G_F@/ϪۇQO+m#S eyNGCvĿPBf[GZ-0RcǛ)qO:4܃fw~DF Rhf/:Z*&N@k2K~eymhAtGm$Z{)H5V|jB6HZkK&T>rzFLi@|ޏhEca8ShuΧtGC%vPK^@{N|xxǦ۾EpCkG}v:#Y?B$m7pCbux -_1,Yƣy1%vۼ2:򠍓JNqAp奻1.TU{vI;y Z5U)՜5[ߞMocPkK&c5nk 萴 F p?[30kaWSI%1jc9J:FQtco/0*vc)xK!7Ff9],кHEIc ^BAȕىUk#8r؍a*FKF(bd#G1@i]vJ12CׯG.<lY8"#492 #>ę Yb{YWac 60꫄҄qirJ)Fř[{c^?bjWbEc?1 I#PFk+tf1~!1p^)oÈagx*1 ̳-ݰp[^{V2 fഅ%ZA{;Z@ZmZaM>3D#]ɷ*=SMحf)_#uk.03WOf}'P3@RޅoOJc|* ^+37(0rV> jY)1f?ߘޅgqUsMȜA &hwQʪ(AT-gB}bayvg< =Wkx,!wPȾ/(m 5(g&1.9W 雫,kEˠGzMVMhHzϦAzfelN-ԣƸcύ':llGшhU+w]ʋ)|hd9)ȆW'bKK=PﵫT.:x7u =[(R>1~uvMn_D)C9>Ç{*Q{pCD3Z`sM{ڷͼ4/+.(ĻZl'.@acXCLv1 /e'o6K~!#]c0}~Z,TUl,||ĹlcGQwv룲p4M NN#DIC^K0*;%Km E̫-z9ʹxǮ#wJ%5PVU~Ew+g@m-Z@PKu73m,[LBoR蛠NKvEuVo lh2f6P/e<aVA$g}iAryhUv nqAN_Ŕy_Fc^[υ!(Ou.?n5xVo2 ]+.k&Uv#_6 ɿBlm}0OgtK[:6;0;M| Evt!ڑgq8V=x@<)+B|rlIv>?*7uvrUPZnT=iIُ7@|\&8{{2t/ly!Gfr`+ȯgwemנ\.|HtG1#o@'= ?y3~O0Tw<0 6B+)ف9rf1P7\mvWq^7iƏcSi_)n{h[ؾlnhiIʍޘ |j[osoNi1*7mar =U]҇ n4|ͅ)k#(b[eWo,Ln&N,>σ=g1wPRj6j{U\1[fpsЬ=-hL5ţULR \_{yѯ|1S A#WAA3LZ*z`B~G.)Gx#a.2mLؾ&Q[bS b0s͵@ &o4Re?觅ܫjOmE\QOj5euϗL]Y5MԼ&U3Gō {|Z7x*~cgǿ+aOt1X9J@ C~HBɖAh>ί 569f֜$3(hu71i=mؖ_ѢD0*ň.WTV.1(-XGM:|^Yw6$?F<:^4$;b/H)|?aAhGj `{{0jpr9Fڷ+*Z%_fvylWHD"1"b OGNj3<_`$ YkvU -虾 ehpfbhᵃs7`ahíFhFtTB'S  }!T{tx=RD#ͻ|2GKMp4]*՘5=Hfcxl6YBKp?$x:֢ެZ:[Ւ(zOQW9몵VsVs+6gNͅj3IMe/pKw(9'QrL _-VvD3?:bkO?z M;&N697+2Whq' h1 494cLsusN76<(>47{};J(vBR׹3 YxT1 #fj0}X}`RfVv$6W0&Vh`6K*Υ_ 53b;Q/NXh L>dRܙPFSq@uj ʟ=>U3;PUY{4/0U L$C^zM!{P 4=ԇ>1頑++(_1; 4UA=`B֤0|>oFߑ \ FdѴ䎇c"]8t 67[go= 㢋[.:4>勏Z행wQYRŠ?Sq?uu.ZN}`SbSctx`u235aL@܆$*;zP7'EvbѲX*Fz4c&jFk;or8˕r/|F *8UO 0f==6rV=b'X_a%Ѳs8>TUۊ_t U`Gs3}OG:9'9l`qGg6cq)hSu J=b0w]:85˶Rxƾ(%4N]w>9Kg`9tbW2N$(v s1_7,4gw/9L5}xzhQ>Hᔱ٬*F޿8r nZ:5hLP_8\3aSuc;p nm8"n/m<3e8crS>NM8Ia5u7R>/X 8to|QTvS>NX- *vԿK8.?SK~\3J^7ũz]9O ϶L[HqpJeu1AwI᥋Q }N)O'{Ĭfq785ًr!91g>8tdsA"xdexcBp~sԔsY֜Ϫ XqE8'Aca+9VlvΰFu JP@ d UP=S'\#eiX"R%W_56{&ID4TEƐk}EteA+}>\vB+r'nZ Oc,?ׅbS-Grã8ׇƚ'nq=J%0ҙK0j ۈHDZ`KDaDg'DaWvWc.mX~t F4܂z_n_Fk9/v7bLKȋ'q.ZYBBlx!lm~]_Ѻko:b᯵.PHC ΠjhJLjVOY|@kxAB?\45:Jw%`q *Q==}*nf~Z(;~~2$Q_k]CO$Ugg?p-tXս#RN{`:X}HT:;BuR򻚠>V_&ǡ|ZFo*ѣIRm w힝W43:JAU~25Sʎ籑4DOws{,[B=|Ft$w#شB+hHin ;F#98X4xg->"oUy+|=jӽ8s8j%=!]44؆%CVo@? } :$Q}ˡeNbwhKQLI{}°O6 MdžLOKAܑjjÙ)s}zn ,wV0R[E@zq>"#k^jԝ'cbԻw~$4P4Bx?4v8^|F{YP5罓}WH\`~+2M.6pW8j Ԟq܀OR6hĝlj~x< } cQKFИPs:. b6y[wo=җK6C@ -u$]J^J0lŇ8GhR%~aO twx\n3Y>[2Ф#J?|j{/oOfmV.Xrݨv7_DH!엎"#_\SD~FaT6U5,Fڶ'羊rM1/YbGS*;0^R1&&TR}S[t ぢ=0&kֳRǨNg_(d1N+EjT'=F|e 9R2!) #394ygã@rX/6JpMshXC-L:"*]Sh/'VK*4 S"Cj>&?UMx%Á0aY#b>svfI'ˡ(퇈4_mdeA0n|ce"-:l`rFXǬTPOK(]#*r6̌ܜ&`'@| $H̕ 0pLx >܅Jʽ/!8,'d8M&L7Cchp>'̀ß MҔ/"7b ?[@m;8U׮/B0{lGҍL2+FlD%Ų8d/xc4r{jQtWe)hyL LѿG aEa;΁hx[q/!hZ97S][&q:)b2Zn]=BSWö 'bf?3YU~üX3L'U;-l~C%3dzC_Nd#M$z/[T%mCn'\Vıeh*heYʜam&/4Pۻ6IQ̝`͂-*wF1;Pp9U8e@GQp^p?{3#^|]zRď;dO0)ݠWU %S TGI4\!vj﹐{'ߴL6B&FG#vJ msQ"}lW{HbhqjT!qUyq7R-xܽ AVOg+? # `̱ʯ[C+=60o,s9_NazM44hH{<] QnC6P-Iɝx5 ]0 hc_]/򧁷añ:w2Fi8vEiM͔l.w)8tqKe쀻w"nY];ʋfW+VJ0`mnJٙLaD$=] |'r$n""ܚKԿ r4=݀R-\k`V@n'B7O$0j5;hm0YHUʭnl'jY`c2#XR6 }N|]ʑ0ΠyqNwƀv̀ls.4xWL ߴdx엂U2*e$+/'r_q!>wfv܃)%ƭ/"uz\}tחt7lam*sevZ*\9,Bqׁ\4:#ye!}B=3o~2jVh6nzDHYhfr<lqh|JeX>j,M~r}hC%)ۤXt5\<|[Ma6 ߜ` Cݒ=M=47OǽvcqC]7| F YxQ2jhi:ߨfwfɳJ"lDԱbltBAÏ3,_.}|W_=rQqe7<@/DN}.aYj4F5jtܫ1|vqР`ԁ \\xo_31l-U7-k0F s/̩FnQ9a \YzcR)a+sX- #ޯj Ek11߿FF1BaKɭ6}5+?H6d;FB2WXf\h^24bU0rD)%rNp$`3li{9NytKF|q |10=k.HEW5~ovOv41qXpcG Ej[ eF9pq-Y~ƱC.qI8NDeÙB8ްo,'(Kģ\@;8<k: dzzT9X~#Uʯҋ3_p򧟦&`rL 5?%W1[tqK?qOfҜU¬)Y{8hT͜') {Q,gV2ۇdoЇ#7bJB]ᢎo'r 9r?5!Fsa*GDٚdZRNI OS8Eo Nrd{26 ΟwyXX A֚f.毶xSBۀxpyiT ^o}`Fce*]-É1g)^l2M]5U ɿLJy`;Κ8QeN]q)V kROl%,;=W 9"D`y$Tgk%vއhb-;h3&{t`n9^ب74&Ve)i40b_< ^9gh]9 K4ׯC!70E3,kPI_e1. 0o~'> d?3駘ח}w`A/ ,RaھQ,m թٟ9*y[-+h%eG hNʽ=NC#{5__+ے̶SGe=aƕ%oݧN{d׮uJuL*m֘Up4U|}/1>uF2?I18hN{jyfz U7$F}cQf9tOLl݁^Wq4+p-qJh^}[|O[%⠩@$as<9œuҋʪFm;SnȮ@^½k.+/ӂh>>аu- :t#wb]) , A]_!O@8$f>0䵈&>/ZA_8NTȡOZ<'aaL>"v=-|h?^xmjL\k&ɟxy43$ F r<0a`v hC槼爖<~?>:wq 52@bQnp>>n@?O\4\Ǽa#8XƓG/Y NԑV.4ڸ=Bs=Ao3Т oƞtTC|-WL4wL%כwןQInRfc%4>v{8)$J3NQ]1>|>n:E)]/~|IXD?3et[qR.O!j;Ϡ89X-N:q^R' v)kzN8Shzؠ.eӤ P}z"≓tV ˽eQ8[ZNXMCpFۼypI9{tCI8956=6.pUKVq±w8k32Ϙ'V~ᔔS8Q-~8 d֊I{o_[NZ8Cdm|PCzV^ea*ԋD?jT8RT/,C}G_ßY1ߍw٤h&3mhuV +Eݐ-<{_(Z_OjRP{-h7Mn>]-u<~e 9_`ϊGA5'_D3_ɽ=i:mnkTPDH3IF#oGc!MΈwTЈ% _#ޗ"vhYRkW%gU_up)Tg2fZ}l˼?QԳ?Pg{h{y2DҗC톞scvP24to[SjXll79<>]B? ΪoQ#!HW u%=乸ΛtyRF*Zt0 !.>h@sj9F>S_uQUhZ Fj=#\ȇ;p-KDˍh%w;6Zt`>hEXA-y,Iڏ;hQaLoEc#=h=$Z8(4F3m?}k;ZQdAN_2B6>4 ^ M4'=c#Fh])ZTҽ#? *5ZXopQqJ96_D?YOhEK$͝Ա8$oEcTj쿙aq}[^`4P)*9T͸n6ʽ?D4EcQeչ`Ee1Yr|alk 4{ݲ@s7]Gū;:#z*ySh:tR7ڤ&?:TQ)[w\QOrLgOj8g`N"UׁFL4_ R`J(xldWCY$qbw;mۥI'`Я&q1vlF{WT,? ^}\J= `X>luϗa? 55<4P;s1t6G3a v8M{_E @!˵ 2Ji&YJ?(t\a\>PDٮ9Ba:crBkI_qBsFF*>!:)VX E {2s{M.&=m pB3뛚ޙTE*dq6R 2zsc4K.8\3ztn{7[nzi<ۢG1J-S*׃@.[-/N|fuLaL=N\6i(u!cQA;";_mS =}9b ۷^c|"clVuJ%<;<2txX*S=/WA]zpL2n'g]#HY8V-+gi-^b_B澰J,gi9҇_hB?VMM8߀Z$ZѧtṵCqb%fXh =^y0-T K_+ t_+pl%Oxm0U5˟۴>ZX4z1vj Ld\^Vk>1}`j9ed\?B}HcKmDN& "<"țY t{{f=:# ݿ8={ *l]=Z})t^L$`O%6|e'6Klla{Svճ-Rf9熭Ani0{=Aw\!ȳ9_6je=ѽ:aYl32b0YSZa9;ʧfr`@~)Trj[dM/k+  ,OB~ͩ|mω-rjc歛]anmY }]܆0TݹR #m3:o>pGL/$')lt;as-J9%? 3,g788yY*)w.[`Oݿ EZu#q|/8" mdtaB* as f[.ܐ ?m p삩 TEjyEOMBö-#{Ψ66zc>I1 S0g5P !~. ]^ŝ0BJKRh{DnY]yNci& J5Pƈð@YP+X.NdJB0 J9_a^ϰXUʆUѷl)Y~lI+#)t#s_Kca>[XU/Lf?i^VE3LІipWf ?nsɣdlҡ0^ͯDaec%e:.oY\B}`s2U!}Bv?}US'7SH`0kI-JHOdzr&O'm#Vm3̟? ȫ?=Z k:lsï av[yMG߭0Þa:wdӝ:|[]Kz,SY7~].Iay+8StOb6ɐufWq,থFN$SӸUM*fUֿ|7ᅙ NT5},EfV)$O V,0}\Ұ8)C6}eaC_y qcW7^cCزh^5If0)IVή32'+vB/nQ v X^ޥsvC8٣sMoۊyTL"|{#h\P}UW=dwWOlX]yVj X8(ZG=^4ü?蚪aѧ So7{psL_d粫O|O4@ˤÂ)ĨzƤWX4A2ڹ:5Żz? w.b+; n֪U?a l.0WMƽ*tҍ0l;j/MէHAWbYkaa X(eunq{<kyȦZ=wu} gDvE}| 5>h:Tnй$-60?=۳FVL/Z{ `esdQI'܉W&Iݫ{s/(;!7f 2i)m(t0q,:vrp+3 @[X\=PU'd{&H;#۷ k)@jIJtڄBqPBOLQ#E]9y]ba֞q?T^%^_|w>0|si?Lх>IYKPbU.d ]j?\`mG_RL%`Pـ ]Wmb[>wC O1߽!B84~ hlwzm"k+r:=Xb,DZȂޱ| P6u}{~0?뇕2آb 4ɿWVh0b$W+z3y"\=60z(NPx+OvV*Թ(ݱgS~% v~88ܿ V.#yFlora3>ɍ^[Ob7$|]E+)M\HEwJXptKf `yMYsZqP}tqLf<4֟[! tMq=gh#\S]fcQ.n.nMYeXŚ,<>|?-;Xhpj1%i7NK>filZOԜ?]a]djN9N.z#m+%y8z1`,V9tFư>sl̉?r^#CNalDZ֚+N[VCpcfz䌥AZ\soqDvщac;TeێmcOj4oI#)~c;ݝHط~ΡX>9hr{^Frt:X'GnZaXD8l0/zc{%{t8}ڶnxSJ 8flk/뽑^;SP&_"V w~dJxrFFLĖ`m}=. =H]Oq{`O'Z>I~s'r6q躹PP "ߞAꜷ-Ӻai+0zCG PN8cG>=P>YWإ7md蜖ZE0Tr ѝ[ G\qgaLT7`œ.B>#?U \>|po=3ŷ^ WSwFұ__߿‹V0Z L?zVCR8gh=|0 5'/VARlk;9W~+^OǾNԼt$VqnikVqɯ߾܃sCC8Aiw7aφmTAɆc{#?c}QS.=7a{HO[ 6 [͟S~`@ κD0[ %H|Kک#yV0Adl!h#qq&ԡ ni1}``>6A%\-pmU&mI]h)AwEeEN}vTԚ`pyoQ1m3 ;l7>Qlˌc&|ŪK3a7V!hfNl>G?Gy4#墂OZ# s07=)%`'&n}4]Oett!LiGǚTN| gmtd ,C'M;:!' GL>a dos3CmR\(8v% ]?/M>~> Dگ5@ؖF7Ч0Is ǵo1y&ﻆ02sk`W @ZL#VWW K-D6pa w`۸R7g#HK0Frэ|z!y\BX%v=r p 7|ՁlMU3z8v%\WscHB껞8uP z{U!u jT)7/%e ).;Kr\[\6Tа_Π0jWcv#rKg7٪%k}c cP), GMIz'M'@ndo?[Q:+%65宰d>͘M*JBy~݂Bkx)L |pPLo.߯Gyq$4BH)L*SB~ mIq:HE!%(ߠ$ڙ+y;~tj90M8wg8#l7,Vzoئ# *(4ZoB:㵻:PhsZSh=z7SP߻`&Tdn,~VHqy>v+Zp>tof$hl?\g* }XۃR'< :y&T7'p=A_`×妈\#h+)y$BĭjZm$υR r\]^)C7E %fm '\cuO=g A3!#ݖKݯq]5}~Ixz_rjdxOdU ҂'FY"HNӶ&a{I|22c݅nĿ@ݕp%gyJqzyI_ 4~975vN= 59x2v Oᐄd=Tp_2d~h{W@ꕡWoepwwx_˪M V0 5g0U^<{99K݅mJƵϲ*`APjeg t &HzR3լX?~z;(~(}f 3tu^m{l5sc|FvK2oG<'`[ge7Nq7f~.мx} Xn|^ȱ<?UEm`QnK錹_hD|4ki[i\f~Gʞ Gta5!M]`W=8=c<}%wb9zԎŁ |zd&!yeh `:cKOB0𯓱\ w~@tS)iTx0O2)`G1&|cY3CH2k; $D'5mw9GͿ6=Ƭ=BGyЃEbl3SltNX .!쁤*leIedO?E9Ӡ S5!4%KH*|3PʋmoMqLAPOyt9f1N> ݻ?V`/)yƩ3N@qw|u4>T av:Pn`놟m.6ގ>(g}ek]Hr蝗B+r% 3-gN`&#e7e&i)Ɵ.II _Zqg1'Ӎ]䙘^OsP{Q l#5ױmhf h|P(XuDP⑾SkJ}1+?q{ʨx{C$>AooǾYbвێc8թ8JU0ѦrAMQ+oq`z_4{v$g m{5cw|*}Չtq mB66Bk15GZt(3=Y(/_5ڠqA;W ڵ7FmX6bۢKs`XˈL)-!?0w}ζV/Thۿ݀ܦ{f ;QX?mU1ş+&CKKq}yuf.0'~cv&ޯ^z塕 ]{a>@M>{. P DfE,009!F.i[ٙAr??% < L#0]-οHNyBXzs (Qo:aVR}afKvL> Tlf/M}ٳ@?t.w6Tm|0`Y`Xΐqd%TXT~T)6Ϛ0o`} $B}aB8/fjv5v<J̘kuRLGTr^k{ebqCwӡ6@]nxk0:d=w9tKE63sϭ.πw?6`*댇T!'#Zّx$#ΞvHuǚ7w9Ee<opF ~NSK8zJ;mtel[/ AmߠL7L\:Xĕ΄[r8n"plc Vr#ϱuZm#1rngWJ@yCdc<ľli쎹s;´A&zW,owR7 o_"qM8`,}0^RwnuA"^kamXU,|֗LH{~wB7^Uj OUZ &w%PgL!Z-/;#8J. IbU<ϯ"Tn)vN\9X}Ѳm eae)6$I@SQ`/,WJoD^7YjCMnYܝDVL8`zqAErK>5{"n!/C_}]E&(HLzW$Q%:IBQx$TLDJC|YҞZX=G$CG=0a?+YMЮ =@mfPDS#{ֺ[ZSvK| ]"260(%?;m5{ js7n^Ij3ӼJd-|NKمB]Q&:[%@v!zg$T򅵙*AuN0tζ ҝ׾NB58yWI?y[:͍Pe Ok m ]oPQɾ-pwRK58uecELO yԹ >J ȁ*2r  :}\vw61%n3`4"&vbɍNڠT#F&Sl[ (Т/}2Z$m<_]u$nw  9qmZK Ac0{S|dg-vbՇKa6cChKT ʒ#?w\|#>X@ Ps߁LSxu%LLq8prǵĜyfeU?oJ(:}zEƁo{,:W6ets e~Hi~}XES eqCzn(Ч}m$Z%t/*2{3Z,zQ[:*\+ A:lJЩwL&DDFy|Gme&gA }8} |ZC\~peyf=bAH:J (tNKb^g RϷ' Fm%WRF5"HX~?SX< :/N%%=ks\mwAwg wV&.7$Hڝ!Hv? h0,T ]. })vMyE QNeIeZk9;tTR3nC8Ity#oS:$ZeA*kO&Ջ-̐ē[?a;'Lga !!g^U S;DqBsO(=ӁSdq y0h/YLOu~$Mddm{"eq]b}YnhToՅؾG`>#@miffl5%Ͻ0YŸ>ѦB %i٥@imq3_8x*L'eq̬ؒpyF+`*nH7ga=䶆Q݇Kô 'Yi^ߵ6gl?Qe>Z .geaI7*>˫FzsY2TOG~J[nfUV]d:VK)d)oq%!B>!Y^ +-"_QHk$o"M.u&@DOn sbm(,0bWKY^?д{)3Tjw~ 6L,Z)2S(lB*G`,п(tNC7\EXJz}7B{9H5) S^5.ְ*,adBK&.-ӵO&(ZMd9: sZaZk1?Z|I|yE )7XZ^1)` UQ_ǛW2(tE#7a*7_` '4a0;A7 0Bb.7%4/o;s;LiYŕL>kcߎHI&(`j9^T+vA8vlK,BߧxgX0YP &Q|xy;f!ersw"Ljc2۸;602Tx'#ikNcԄNҋ[7ؖ`ob[omu< +Bro3t&ޛ0&t6f: ~peT >}H? ig\9 p@olm };zcCOL#rʼn>J)+t ^ ЋA]0 {_}VM*g`UrWH|YQ|&,^m9L ! z[• pi ;԰}[84w- bgt1ނ9O$\X`462*jڈ n{>K>dƕBlҳp51iҍؑk"dF`ξ\ 8Cm6<8eJ{?g56nFegҌ12aHa.7jً Ukh.g }ڄõ_ qB u~@M؜yb;kˇ&+Wl7cw|ê_?0~v>ʣe]K/FcmI_u K^gv#3ߋLC^}j'6τAɌT. ʫooQuD`ٙ< SOz vT]W=CcO=G5`g [s9:` xK~9I48hK6V ¶^c 5cWO8Jb2l.(˻ fw6heYǙet8O7TS?*Lȅ-WW"|7f +\`~mRg,ᤍRKi\<$zr.{%\3D3J8[4NBWg ׳(8#6O"U 5vZܦTb\H}ٚNН7]pPZ> ~K}q(:}g4bo­k6027@\3\y9GYf( >ᎆ&! )onweʲmh))2In&𙻠l-?z,;3lIO*eCG0J/eKk. }WPAsK@6T}|,2{W%ZiӵN}. ty@M & @C\%l.4&p5cw]Bp{ h+S; OWBC G_7(t(wttBZ9'5k3U0IS *8̞BaR4S&/DѫX*`_,țz -2y 20yU7K>!( b%s`0C{qu(IlXHҩ>z*ʾWc 9ᰐJ0a*Mmլqk4sͦ'`~:̨z_C܅5DE=vX>>v/9>@7M8u[Сc= [{bbf'iQFNcAK$L 9տ2bցYXr5H([E HҾWƋ5J6a"RJ̩z +n=7f7݊E_xNKQHn)C[ZKKH$V 'E|;cSVoq:~&m! p=e2Ŏ]cqɔC>Io>f-Rex2Hcª</[>_;m ީcY 'c#@g7Tm,MȜn?Ƿ_= ~ :$s"ب95p?|q78[bmϸ 1dq%GfN\Sję'.;BpJK"q|eKFp2WpH g<͂j#eێdpw3P>ӺqhE&'++GLq~[8;%L7(gq\EQ{vHӍw` Cs'hy`w.~g>[B] [7ȢsrV:t4ھ.z{s g('qBW3yۧ,qP4셓w*Rc1h> %U]v8}g"j5R]IލSI$jztXHZ_PhxǤ)4L.luӗ8k1A+Xݑt= ršx۾10rx9.Xj2y(/Bc~'L}I07ٚvtt]xSjFys`ď{0t䘤%loU,_;U_c-a}Ha}-s} MLʥH^y u\ 3,>7\9 ,ϐu:f{? oΎj k =SĒYsB[A.,WʨmIa);QV"R=*aLvSTwb\s7 +Yzp &0|-fc%"3 go da?CW=*fܖ[U \QN(}2*vyʜ8V5o6 M0 fk_M!~?]i !${hR{}jkkcWvMe|WJ6TIƨݢ;3~&7dl}iZ=t( 67qpQux.Wkэzz‡ ie2/ Cjp2Az ΦWWfDU$rq0~U^bdoV7^9y8)2gl8wyF7Xm&7Lyk{#{#`¾A:s.p1׽ qzZs,%\+K^,Ae|A0۟0 3wOr`;8 zGӂ W=4U[/8#&᱇F5'pi3.lcu?+pM fZ\αj=7jp`|n8!*omto*=3}Mp?Caxo>M&#[ >'Zg7+iz9]/S!bAP|?Ŀ _{zڅK|.` Ibݽfu3 ׇ)kJ#ݎtNwiX+ѷ) u=&D5'Oi37>"tQ$reC vW )꽺쭶e ~2q; ڟ7hNTi6ο*,]NV gwNVd A O,/έT$q} '^"kl}ΟrQb%HL*s{ʓ$lT6`0#'fidY::k?] a~|þ(ãLjv۷`wC- O2Toca^Z^]RЀYUvaZXXjg w92`zS/)+b}8 _\?uLQP3|ʶ J^z aQo 0:aHXam;3(?po7ʿ lm;`6qr6xHm鄁M6u7`qgޯ0&3>EˋCw!_`{v朒@S,S w*>?ky>?TSG[zחn @=.#_}Cqo)=ک !зN! FºhTV [VUɰ\>4!(;dQhW`G4oNϟʺ+)4۵ ^#ӿ0uQP) V>X ]V,ֻ/nR(h-mhmB[LT˳wRy/' s=YQHj>bfwc`:^1@γDaJa+IG~yuҭ[F t S›l|ްSa"k4#]jQ0DqҺL}XF!i*UU3t5\=CCU>5As3]ʿSð<*Es9'fj0S{d34ߌZjz~˙k6CW1LsxxCܛ%쁮ygN8÷+/auϫ_a NLvKCE>ڙ{WA^9ObGBXX)ibbESu@16_jϸG'vl7[.Iy`5pB,PM`.';\ g5 ػ(9,c˦l̩Tdri=hoB;Հ53xI rFMILȲF9Ԃ&~cY€wJL,"!q<k9ucy)&, jx\KWwL[]kb~U~,l`jA!F'\1ʑ=W侊CvsѯZgqٚat@v\f-ߛi ;>b'ϛ_hΔ"Ve=<ٵ`ˉ6ՋKq1Rc\ͫOm"0#l|{#6p|}ʚsly1{[5NK;TVntG8ҹ*qyfڃ%Nd.洂>Z{|ip ZAɄlt+ɈR񃥿7^YñRqjRXZ2pOO݉m8p{,CyG и]Iddž-yp&U@! 1zM}ɋNg⸙_$v6-'mw6`"$yh0n[|o5 }?HƢj ]۰}ǹ^l)жPU9Xhpf vgc|Fe}>=޿++Ss;ɡ"UOσ˞Pe3ٳ= 5#z+B԰Kbu6On Srgs,`o),?öOgNFHaq/ M*cB:gF}뮣Xrglg UǪ4}0xHbni;"sOL(h:3~=~Wz¿+BN|Ov2K07nkB!RM y,q`eM<{3;_bQՠ@l2ihG5]vƊ [PHj /T}ݢqzo֭ߡ{iӟӞu 4UՐD7XD/֤=FMP7bRrI=3 懔A|iԏq Ŏ]NP*/pl0]/8âOMj-CܕBrK YvC_dy b59: #_>R<5Nܱ25lgKb*N~;$>pIm3LO~ ʹacR4 4 lClfk`g+?9@+v~IZ܊۠2Rʉj=|s\qKuGpGEW6e~гqƋډ{YYCw6zm/ *#MߙZ5o2Z7ۤ%]OjgXwb{rQSyNNwaֳW6 o!jf9WLDl3ۢ{s?냬)]Km!݇]s-pgpk)ƾdMu6.7 y21s;Eda@n)zJwfƇ5G@ RH7Wݭ=ORMiiWcm"ueF/ _SowB{?>~]5[Kd!ߧ~M-fj^:ht֪`׃Ju~ߖ쿈Civd&ݷNyLpc>ƇN8[@~cKorDh7Vm>s 2j3۱JRtn!e6'QuH~1fw? 3"a;,5{wPuK'8Ek }J(DŽ+y CNցza4.2\Uu?Xm2F纥Sf po4Ezϱ&;cʅ}oۜDrޑXtȰL{[; mJ7 a !JÇ,+"ٱ̇eQ1ݹ]6޻}s u֐J{W: }V-5gpVTnH\j6^Dy|44}]Ί1R[Gva爊SIv#g"Rfr%qhcDqJPƮk'1E`1 4N`z?|; ^?+oQqr Y|Zu=ɺgGNn`uF~lb}P2ҭiO ORX,H [5NN@t{*N1* sϿ6<S6B%(.k.:Fz}+ȟoGط[l6rߒ j=,/_n.hB{ ܱ7AɘKW)Vxj.'߲ dq,IT5Cß@g tﻹ*Ӽ }ؔ?Šϛd|?jzT%*:ڟD@HeVK CSat "*kXA3Y4S* Er3աQyF3̴ y#anKmd!eXF0, !9' 5r=Ҧ} -l"q] 4=FVhp[& f$ \mljWI>t'FdcfO)*VYvdە)%;:SoxteElY~ə+ roj ](CKak09*z=r~Ϊht ZH6t;nPVi;ҎSp荩cn[-Al0m.]^@ $[pY~{6gErZqKVy4 wPkuK2q8wr]U^Z] 7tW)rl<PR;7V;~It>gCwӤ5sn? U*W8WS_R s=@!/9NRh/q:>>4.P=BHȹfl}eE{a*kҷ)$CE *EXz8^D}ZŃSϊQ6wm)i0 LEOa(̚!h(]')d5Ns.Tyfv0Rh%e)N4)? 6PTw SHjBaCe:,6\0XSh`a^/f̕ړyBST4CmǢCo|OG? 9渑% |D~X^kPDc~<8]/?N٬Ks_U3kEO+Tk}V :atb[7V0T.z'FûH Pߔ*HlPb-z7-`W|^ŰR ^kCȨy]4D M!£YSCQYmbd>L:זAarQ[Ū0@*9=ɤUqFG]IUBg\06շw_ʩ=HJnr<UrnK HLb*j&sZ:CR[0$)5"ٶAS'KTuh=P`ZO {ubY][E=_܋=u$Sakw􊥽1棸-v9^he;ֺ+ylٵ*0@_icEJ%bt(-MϘߡϛEc Tjk+B> 6O[^/@vٳ4couފfh{Y|G<? Yr~5ҭ̎e`Omɉ[Md1;qk܅PC_k= g|_vZ6璱t5, hF N*_zqZVi ʍz^BXTa4:~6pxdB* E:iPs -+,"wvf͌8aY*߿ ֑?wB3Imv~?޶8Uhyl`%Xq.:7VeObB8ťl|}ՑaeN6U^AUIM'*<64Pv8)Ub58u*uv~L8>l_X7\4 ,~7ձGd""؉W/<6$ľA*HW8NShm>)(Ҹ%ݮf"~ qgbΘV?) ƸM%q*[1Rt{zǔ}OG|V{>u/$/$awqxe?+dȨ%uVyb7AD68c{}@paHZS-TC/\KѤd sڰ90_8oT(gog : klC6(_-|`$KǻЊڻ_WIY͋}S8wSunU}Wŭ*جrnU,Uw h)ylYHҺ`f3AT]C\NxX&X܄raɊ[|0xx峝;,͊k_葟,C.L]0gTTBsICV] yg dF6ׯKg`Z-ݰz4",LFTt%ad`bXXc^-swTe-sl $iLw_WvAmrqRKNݓT|m۠^'==Ux:[5 iIko]L NE$ml2u;v\cӈ*}@D.@#4s)HxrY4dP5g="X}%ț<+W8 !U2o& ݋jQH[0bFXS{;JO=K]{yE 6FFv?lD} gve }t86_*1 6!8 ~禟A3'h|3iJ>@o$Ns bKCn.Zo:I/frBKW_5? ={\r%ḫw뱇Q9גq2jh";84Yҹc㩋 Q8A8'O˹0BGDQNH}*ld1jdQqx.ҝt܎qT8o[83]O#_a3ֱ~1ӽnc7bK7m[FRh:F҉AR );Tqc~WD&}-X딌w~Z[ ;Ѽ~#[7v Qh%ImZR<vܻxB ⤐lϥZr4T~ RQK3y}*Xi)v)偕O]%2OXW8oJ!LjRHoMj]`uS &Q l?C:ޥ5]0Y}E!Sn5ah->x=RhxknxShOcé3K`]փX̃`uK Tz +G/'(SfC(4^q2;8P ;%_Ry5j;_CۘbM]%uGu=.}zƫUb%T%mǏ`KBsCA.NA{JcYd  Zo&ڍ-OnÑ| X+To+[U_XW͗ŰwP̄%}ʒ]}&?~k>~]z{mcl)t|Zb/8ku(|܅m{=ӖĀQwGC[bs?sBY=Fm!s,$1Upe%lsf}G^ErFB{ l嶾zSǃ%ZʳVvmO+u ^$^spYNqi_Y\˛2{XrO O nn%E5iEcCy*mJqMy}ƻ Wdq1e*/o˞%h뛇q٬\Sf\xI-rWvWY{ r;ڹm6p9aB l+aiJxgV{*#H[ :>f\c,.o H.*me 9u&`*q5A7)}%jm.\`'-'ww¥Aqܞ uY }^\bcDj`gB2AsUPH248fk'tz6 >4"zhEN. -3y @T^:m/fΆB;}ՓC1P@ l6ﶃA/ngGJhOٝ/7aX9՝ Yi) QZFa2%\f^}UڠZ탦NeԺ}9p{ ^(h/堟F`m^Q^e͐j6YKYtJFW6;lX7rNƶpurtkv6R4.=ij{'%C=*Aq/heeGgj6C VVf!ψ]1[y.0=,=rLsEUo `db[0: 3'ͪ)ilmm KWFa5WJL,].~sN0/ǂ|àu{Lx-aAVQaTT5/ΞбJ0.IQ[PX:k6 sߑPhY.%Wr&AX<<.։RaG>14y#Ǚ`z]V~X]6G ٓ?`Eծ<0+8m ?\Mҧ|q}:Xm+%`n0$Fj#0l>3sNl~eӗS`3ؿ?aGQa%{Ps'ڟ' 3]ȃ0s?vY*Z5*UUnZ׼p>15ݞ>S\NNlhoD:As[9,NoQ︴yɮ6.I[ƕhQ=Wn%O~Y{3831ۋi8jn~7nye?rj9K'N/oW\LR8{ =rT*'PpuV_/~17t;pW9[J/2"FVϰⲎ8oy#$^ǥp+1E2qe7A1Ǣliwc$rW7}~Qїc$įK%pi/y^Au'Y87u.<t#f;f_<u*5pB`־P 6[Dw10i}slfbmߒkœ!9T&LzuI["A8JI6CՍ|/Zoa8DS\EQzTkr֍AlnӯJT*_%,u/ά]Y5GiKf$PU$[{K{tX@?Jn9HV6.Iy^+@=43YHj%fF}afG+@EC1::Ek}@h0:A`|=fJv]G,h܍@2VbBPL&P{ Mƭŕԇ|SS`3xUl)/|;'| Ta*ƥj~]hhh.vj}Juf|°~\*vLEۋbl1:I~T}å$± $,{OlEQ{o V1 ѥRavF t"'T&9Ki44(ס ;qʢ&iRϔQAGjGp%3>tƹE;JUY,1-*U$P3WT3e5].eKf,2ڦeY6Bc9NP|YwybߨM^$;/r?5dfxsL o򧞇5Rp2suׂ.TGoZ쇆#8 H^a7.X ׎pH湼0j%[5Vkc7\ H98'Oi㪴rm[9aIGijNUҡ'Xu/s+ fg`VR;g7js.kOٯь4Ĕm;g[]]p*<_o0"mHz B??MYpk\Ty<')"%ӄUźt/d'^w1ǹ."cQuT#./dӝ/&ܜ85003}dQ?\X` 7Nm>U Dx"rc"MlZG*y. j&qv;7͊I U.#(/Vc/iOT|l_qAi0.\o/YCիJ!)"IVMM# eobW?^~Wo8͌cOxӘv㦎qg8%ZjizpFr} I6>ne굞TK!O]hyp z|{fB-|eyT:rA\f*#&wYBLiHhreg`w9fV2y~aݮI0i@'2'Lg:6MjeE NXҚ +n_ν7o#P+ +;\`.^,y UsÔb VHPȄsV0.j =oUʛnp1@Z^' fjVҾ]#{`~H_L0c鋊ɰ5i4=gu"כ*_6s5'+`E:b ,k?PLu#0c\1x ֯NRqB^vr[Ю!ֳXfz~[zy죮kr[.IVxa_S8ՙҙ̧u.KkaO& LeQ 5ص:&lovxT2RwK?k˖2sypz?7N\~%=K_11z|Ĭg EaBنp{wy4*ʉ-?, wy/췼Թ"^tu'8cQ8(K_s ǯ1ܬڰ߼5mO2>K w_vZ95c/$$v:fH{3O;Zp7ݦl- j%EW[|?3 ܞmͻRxw;&{G]^9 ?Ĥy1dGdڏwHZ\8Qn>`6rTQ#U$VtDŽQϚG2F-S;E>Z:f|yOHU 8,"xer8w󪦆}r`m.nfm?XW- r#qm8o%1~oC!㽕|+?p98 $PqQޙ|XH) _^dtX}Y=g7F>!&Qo쏷P'&硵]C8=:DwU[]Jh }7p uj3`ΝfC}ϐ'o8K]/Vux4 r_߸ &b0s5x}E,zy!00$ %-0/ҕs3d#j֔ =LwaϾh3b ht[2 z]^ACz)3uN #( 0 \V# BOz;j(s~gx{q豜S LCjGoEm&00ENd Sw_V.O9i1hxZv[L驗JaH0}s!%V:Ύm{CBGeMQ.Nybo(8a+ -fיjSٶ xߓ5\QN O/6GiUv Ęe]ŞsN5`yKrPqHB KOA[iW$2'^{Z jwYXm"gJWy8OV}J2htݣ.x%$[o>?p -M9u8c+!zV4۽>(/BW[BmUq0bjVq(uEj:ERSnq_ p6xѼ0y4$f`i7:}\Y ~+Za.yhl ] pfC}4+%=3C84lAߵM$UIFrtˍ?J/ޛ-7+etlؑf3*9̇*c2gҕCFvbSKOe]wĖGBxU=ɘ3k2Vr}v> )jn`ԡG"(Z'uznj#n|lH5-jj>%\AH9[^B6}3> ע/}&^F}a\o^}/1(MNpVCܬ?B%JSǠ %")3Z?6+qn"g\URdV$quǾ7?i ՙyXpi6p= )jש߱Ţm$?>NrGMW"N'oKq#KNZ d{puKM%;ki˳ u ~#7ۘ4#z?~|܉Dht"-/b\z(w 9ϫZᦾwvJ.׈7Ҝ p)ԃC\* LV[uڞާq0\-bֆ%€Vh~yeEiTnl9[b}.Ԇk-?%( ڣc7ͰvkOS0A? xsw//]tOkAdJ(]<6HLaY t}b-9r+W݅DhQzrl:9ry aXC_`Nms x} A5՝!e#J/"?O!0/_߹}IqF*8&LB}Q*T̽|Ն*D X/";pٕMVȹ^0jiKJjF34ݗ^gI7yȹf;@2e[ fw ?e_C)aXY~?&x}X{I 3O}L]pBV",d;zYXJ,x ! cf`&-*Xhk 9X:''Q8Ӂֆb ~:f+O:E.i{~m`cGqGװ~]n/La^X>[,,ǞھاS|6x*@+34 Zg20Q$u@v>>INeX;?aS_Xy5~r l33*  8B65]JJg a%쮯01gݰnT<sxp*hn? /ap"rj]oY"|~O=VQ0-6kyB@kͧ1QOցm7aʘPU*Ǟ39/ 1Q-Ǚ4-e QFdء`|3 d[_P!b者iPo)yCpn; 2at&={p o޷CgvOnlB_!XsN6c0fgu]/XahߛUP{z+[E:x~FWBKXAX8Ac]"pʻ ϯ׺cz@O` X oNAe '~ᣊh1:9;Ϭ व 7sӃ@m^}l3R|\SW%qк.c7׷k 1vt/cs؈2$`>UE8S Z~ፆnbv*woР<^q,idwi #yKaE{qblK)z_W}wE9(H8{huQ}o+Z&q@Ǧ]B|!8<7*/i8Frв!ֽ>ӟ7sCZ7k}@#o>'mρK0q#w94T8%)?]XB4Q$Ifpw[(T䦉Չ cׯB4 c/a[D{ZH>m$ ?$q)SmZe[+Vjwc8}R [O~0?DFIa= ۼD\v`:V{xm8 P[e-sgH 8k~V *I h( 0n4_H"0AY$~.۳ H{֗\M7˿>軘cV"Ꮝwn;C c'%YepafXZ2U }ǯQx#a]ڷ˘"b5֍MeiO AT`sBXo| +[&Pq.=M̬F4597)r, k|_i,oAa-)֭>-V먼?+h?q5Sh…|#PXw aCi7i6/7J^%Pr  fa%QLVdM'dn쇋o`&>R 7-E`͐\:E~ i:*Jr矓hzGLF|l+c<_ab? GTm2Yұ-GV˯SJ"O kG[aUXO8Rlj n.+Ē[8TJR qxǩQ=M|=T~BNJ-&9 .2cP/vMAqgu)MM ᲏;ٰWྜ݋:omͱG&),[e2KîxyN*CH:~-$*5E8$;d~JԊ8,Xۋ3W*V=W?ex<"rx~ lЈhB҂|X*vV& .8dG ϓŊ؛x tjY80 7{QR-1N:w36B 3=vUs8T_>% cݽޫt9+ֶzk߉+wlŷ9na-D+N#S]P'{Tn.IW7OS!ąS7萒{ U$oZp.y}Ugc%4P\C1R73X"/q=#.~'r J@N=zN5=Bś8.slkkw .nU)SWqݼӡ|P1l+SBpxsٮ!\:n|<.z.ZEDRZT}۽Z=98O EJ>$5MW M.#81a|&qtEM89^d0|8Չf*#18Ք8.1?]~(X8zV- tEh2l o /4`uΒ|iVbJX^X `dX/ n,A*]h@ݤQ ړr&E*[Game{'l-vg_`װ#Sg$Xunq&W_˻cG#a!NuY X yVO)qEqX8_&_F;u(&p.h^xc^q~wCY8,Sp G٣:vNޡp0azC;r+DV6YV֨¦ {!:[o]DvW<^K8l8|?1փK|̱t2L ^DL v-{&!I=8ν# %{ذs[s؞ۜhS]D_I|5˛yӰO>lv4-V.\%E쒨/"67n@BgWGŪWUaeuǑtp U1t^Vڥ#`.<蓍}BSұ~,[z%b#ςૐul+WpLf8.15(FʑTG H9x-(ʼnq%\;]V䋫xť c!p"6awj7pP74%X3,(8^Ԑ=KE8q)^&zӋ+(Tqnہ8aF ^1'RY|T~3kFWqv*[/`0B ϸdCԨ瘾ŕ/NQpnm"qK$m<ٶn'"gK|"l8qcHN 5_ۇCfzj_%8 ur1]8)lCgcypܦ;L_GƧW8"I}{'VVMLĕK{?õ>3 i\ϻR[fX}P{Dj~a9\~<7sL292NUOi.c3$fKBl\Vy9?fH1nGR*\}хe8/zĕ]#'J+7Y÷$01UYߗ/ldf7 bkѷ> \yB;)u;T٧f%g6p٤Nn%4.e/lęS{mq1A!JIOoD^!-u۲HtFx g%/Ǝ6$qz5x%.CSXP5w cE83z֦-3&W&U(eO)}ysy*oeDٴwl;pXmM$tJ{=<:W8zs{`p[i62M U8 |ĵUةHaAEetU[[)7^z3uzI%UK&Xj9BPr~ed*IzS[~{`MCR̩'>H⡹0i K4$ҠWr|8F ]U]qGԧK&OJP%+q>Ńoamj~:$ sUhI6m48w¥@ԕ@U9Q d9Sч|<ҹ;׏"ٙ>Syor|z|N+I0jSHv. h-w@"VFKg2}`NjϑB*viV߃EN8e'V¢׌r{ zO~'f> >Ǿ]Y_э..rR=`e5+t?,_>; x9ޏ f?X 6nŌS ${8,O8a7 K%@NV4=$LJ l ֮]9d&rtkC$WR4kgϷj^XRr aXVF}pePo2.kk2r*§`Iv#q{JG[qR?߽M?Rv>O`!p3A,3~|SRW7K"]cP뵃7`ڭ_aQ֯ۤՌūH0);_d 3Oia9ûV !Qѵb ˯.`cm׿;N$5x!餮T~#6x\xY31^:)mU;rQ멳v6v7Cfs_,"$ڶ+2^1'rϭvvMvP?-]ȨEs^zA8+y 3pKk.p"6Xd?/z'mXq#ߒ֗e-cmM39eso(.~ ^8ubc$ys@#yHJbMu --g`QK1rn%l|[vT8{cwʘ@^LDhWak].;a#sgD6M6ގ_CMX+7FW#]f)-2T7pSKSx[YU_˫YBx:?n4~%\Ǐ8ӱ=OՖg<^4 t3\ Nsčumwipe/6٨.oKOxy$(k;Mp!P2e{_}XFAf r-)OL;ebl"9o!k¶j&\ssm&\p@l-;.\ŵh/BQuEz'+Zd4+;^}8E5;<0uLnC ^usM|201s|ʇ| 3K {{ jYu"%%pBD\{nt*lHCU%R2'TwOWUSu2q@"u=q6QsW`m};w %ҟA6'g$y8Ml}iƽ47?gĶ>gVJJ͜tUgJ`ͿJ\9Â\绉TIr򨱵T1[Ic5翌u\u$;}It ūy.۬ŵp9r"U=Dj !uz"us7\Sd#R|99HmP5j)WkFׯ\؉^_#qбML$R:<./:V9œX&T1:`: l>PSf(Zr~[;-F{$a@FV1)SC3eݙ؄^3.byS Uq:|. U2˜3+F@2+4JqT瀑MSg0km=_WB>I_W4&4U3C䥣4W%L|=Lt݂osW}Ƥ'# :Ar oh1$~EM ĖivvC$m[^'hmrC,>z%VWڞ%P9=/WQs%a>q?;ԲiJlYì-ě >rI,y9v-jnfѳb:Ø7+;XC=^ M7 R5$x,r+#9?$fGe!'O`*,jlÚhC |iܠU;56 8V߹?XxʨX221 _.ާeC0oSR,YxM+[zqL1k˭5wlaXyNU'YZSe>dG<%.f򥻳Myk)بhlK_ڊ;^L~\ Ren;bgo gzn A{ 7q˂(ל6|H:v/Hږ5iCGׇr^e{gAG4'IJ@ m\c7$ɀW19i} zZu1eMeUB@4`L! HLq<_~Z|_˱W{pm̅]*"2h . zY;v'(_M;S-<..@wHM ʹK4oL?PD ?FUׅJgps(-;Y k/1aQPrg3@]8Xg$.w#2 m̢#2+=puT7K|Ήv6lϧlXNn\~ƐH2p %ͨT$Qb|uN >-%2x;'O>s);Wp2J3F"ݬ%NV4jB _LK}{py0K2.NH }>Knc4ޭre"{Ŷ7q妏!lNYk;5M3?yi_3]S`Џ8UθrupDz|ڃq4! $'Ÿ"=J0䳴9e_® Nhez$r=3~&`a_7PXb!N>x8gz|8>EuL {O8R}v G?ܝnʈ"K 8"`X> u؝-Hop]#3@);v̽b )?ޔ^{y*5aw.yh]}>?'5**XW=u~(~!EY۴mv*NV'`S!~b?{Z[j! ҒH(+s\6gfqTG{ oZbOSbډ/#~_q<C c g@C@l~t%FiKz =a:.As3J}Pu Cĺd$,Xω}s?39_ _|)S{^Dq(u;454)s;Jϝj:!ƨ}OΜ*'mdTx ze5TܳܮW"]~_ < Ͱf]oTND.=P[ŁՁ0q"t@~֓W|")ݕt;2voBrV ?;ҭf14mGQNƴ%̯T3YIҭPih%sY.¹n@1UpG¬ bvQ+=:*=&? Ht}{@g4E0Y^Cۮҿ=m5,9зfnBEQe}_PN6Oۿ6C{mÖ/]Ђ;kCcؠa2rۖO u g;NYD ۜz{OA瘓Vgrǯs04> 3r/I |˯}8*u d.1p3c5=puVzM̩Ta ]rȗ;g?/-c;{_jR8d~ N*9gapͣ }_u~ +̼S j=*@L3a8btG\2ۜ~j b1AZ 唹C,'mAAd+mow:)-q7POmt[=?X}a>IZ7uqc3Ϭ%v)rbT{;։v"Rq=\&/mP8*rv`mVZiA?`~oG=yM \8ψs~xRIo,b/շvrvO'0q 줿 ~ 4`ѥuh-=4Uм-mzpϕRЧ}==I< kgZd.~=#OۑIlPlY+{d"@Jr&xAOb߯ji-Xz]d'dk0L|c΍A=^K{Q`%z f)^l_lr}*ξJ,#0<`Gy!Y;BU&!F_* ԕ4S.ƞ,Zs"2hIbvYmhb81֓~{6)v #Ya d=z5mwod6LW[7VV䃲?A3B'UA9M{ZKn8lqz~:4qm&{ n-xU]cƅӟp{IOXMQt2/;F\Iߓ30ЎK ΍?"m@l+5h|ٜmǏR /xfJN&eP.&3q`@lw}ߖMu9Q%Kkh8,#WH~-}lBB8CGVk".pQSV7k&~_tܿۢep^ȥ#XD*Y/iX*.&6 ?s(ۓXE3y})w=ąo#!_lIwJqՏwrg[%9tϬoqnF.눔,01ٞ(66f\УQL@PQ\az IBJ䥐Hi$?{bR:Ը|p.TuX~)7x?8m͛8zsbO؈ ν^cr[!bό$% y! K\ tsnl?3Ͽ[pve|E5]]ܒ\XL+#pSpV&!u<(iǥ4Xm?a%\t(2yjnik6 rf[} ;b#աtv+fB7SX:-uV|!3;F(xxcBs[hhs7|  nj|H/i5|Mno휘(u*<%* Ty!cV{{|DqCsZ U`e >BSM9FVgC 4֘DBm,83Y2WZ1C, }5TQ"reIl}~3Jh<׉u'MuP@>=N#¨W+j0,հqZί3c3= twȞ{=D-BXa2Ԋܻ zR?iwEQlJcRWˣ%X,Vu ̤|~cyw/ǁr/"SH-Zl. 0&z뿁1ٸvX.%ġ\~nua<\G&*\ʠ3I!`a@&PM݇c+RՏ"ݥ=8r'ѧ1 ; s~ٷ\b.@==0?v+di]b!igFu;d=Hv_iJlq:m͵MoT F/:àъ .M y+ێNE7)̩1+K*|]JcԲU3iLsM?;p EYu딪1`~ϵ8ZDtO`vWM?*@CPUp UUAo%P!qa<5V"v]axb`Q%mHJa(eU`4͊T}'6iiØхU {']G=[vN),GGOB+1*{[]ZbV/ssl`μ^*d&֜n$gt6ehҺc^TDA_P)SpDڽ^7%hSt/: wmVкqs(tRSҠVzlD)mОɕ.Kkr@9=rHqR9ouBv0פ^(L|cY?߹wi蚌 yG{`0[یaN310]Zqra @:jU̍CW|[q9=EO2Y Bʌٗ[7sAkh9p+# ';E3B[кれ[y6|ˁ.3T$\Jeef\HJ<5 Nf;VZ'r qAʾd7}[K5j~P c'BATSCZ#VCтM␾4?{h"fk͚smP2^ DhYք k/`䥨g9. -vY3s R__AǡeUPI>RJVo ռV2MNDQ=m1~]˗W֧,D}*T Uw$ryzZ0`N)L6`Pn_9BFOE!WR/al=$xnFJ/(mgrsZ0pC`R$1K>{7aVѧE{3BAI LJKo `Km#CaLjXz|N&=Z- fK_̊٥9PK_ƃ@c cO aUqX:IlYg|#ț9J٘a9Y+xƥ+ m42v”wGϖ.3QΦz/`}EyMQ9v2R[a4ŕîjDZpkCk" !Ss+\zDmT9u['ÅwL3RDk yeH~@?߬g`OtpqA¼ٗ'%7 gǩrDgYN'F_ܠG`Չ@C7Dw!l_LY%wX%Ji'ث !lȷXX:13陔Jg*7wԔYyY8q`GnuL91md'8=|}u$1]۱X?u'Ʊ~VRiNT2`) CEyNש@l.7@16PqZze&}\"W{4ә 7t'm6ޖM#BjD>}D UMRHd%2lu "P"v/Ij\IA=_\gՉTOvip66p{ևƧѸ_;Kߩ>!Htk1aVq %*,(HIH#UזH[Ul\Eh EB {D*YH~"ԓ)D&w _nDj[p/Ao5:rGdkq$G۸0m!kSK$RY;[J(t{S2/.uҤ6g~n#.V?r5Ꞔ\[Ytv[X. `i F2@0%i(#E/7 #٫d90[;T%\&C ZC%0 w|q#G}iBYj?E?vqs&yzm++նT/&{o-t'BTKU[=ή׭a]d:rXZB8CC̚)ԃv_ƀkðHGn@Ј6Nh>D-tOu?Y59AQ|OZzZH{l=>:k0ȇVb#m[G1tl&Dƾ{"|=xļO({"+=Oa4ן>eCGp$-=218]ԏd1E(jC/4wb瞤š11)]n.:1aKhSadL)Q%Z_O++u]~O9+}j4 r%锊wh )ܭ~X }1  ͒+6CI߆Lf{^X cEWCo&*U0p!fIhaêίG)ttkYrݼ8]]y]n|8G] W_oǘlE5*AK:f/LDs޲=."z.L'Y?A]_T C PvXV 8矿qL96'7Ѐ%tn~z+|7oEoD`7[$4?'6Uw3ŖZP#UH"'3 D#&B+">욉`hWtk4}+av9'MthtpjM\ø'_3m|U!0$C„Mvf2:B4(m6J/Q.&rU6=s;=vdoߴ&+PܔT&~k7V3zE'>fQσS"frۏ3֫g|"-Q=E?y's;1s 90^05/n|I \wg"IHףM-Mg|mKj|w@ 5$B_w wPJmVڡRDѳixcN}@YG{KL4d<λˍgTJ ӸW:W7P'k=x]lXՕcmMO}M_qNYRd!^,IOUS*kWq\2ol4fc5~<^:zFX^UOS ](O`3Cxf%Nܱ<|ڽľ90hEr ٚg`#|캟N[oLA>cd`8YtE|{`[A;J4OWeld}BoGC;$-*GRWG"5 o/ w]8 ȲW8$,GgR:C-/xs}z :$buiMFm/:Kogd5; ^fZ`j~0p֠*<:3?ECWi,_{ V‪\]r60C,1/A@JQt;y?jšG!1c(36~F>eBW.r@񱷶vw{@D L۵}Kz G`b,HVG"/d#D:#6"}F6>/@fu:aC"#}DiwDzӮrDڔ75~??7#]O%N{ 'l‚a"AΎ @˾ula0`؞RH~*5-Crמl[vXVx O?G9Kp@`g$ ;]CC]0ѳLwS>: {?[_֬K6? ;.^!I]@>dY1_u6^֖'ЫS]+%P͆8: G`JQX2!" 䵺s*]&5{f*]u@NF'+XS082-E7~Cb$7M?j?·+@;E;P6+ԕ-!cV0dIgwᄢA{%K^L^h٣dfمXuY6M<`[~eY{X4=w'_RnKs`?Q(X67 %1]wjG^P=~(rm'R;=}b`{Av,`HU.+z+ۊ(}8i>wM&?V?^#ŏ*/7,H8Цri|쿰?` mtphב%|Tv:2&itTg]_u/Tb ½X*|ڠ3SExd6?W8 gF7 }'ԗkNH1y$KG{JfQFw[a-/8^o=5DSqj2;J~5`J̓7anV/e{M,d1Xs!Dƽ3а.!dCaљ0,|kPA?^Y`Y9[~NףWX%t:JЂz:!E= ?9éO{3;,yC#>!0p=}=٧S'7LuHkc y{7qqWMPM+dv*j :M^}ϱ, Ep=,2jr:HZER#';c(G`R'@v&nOR݋@gO`80:#FcKE&$:$z=Pi ʘh·ݓbk ףi!+ɾFH g!Kի"0*e_ ~|M a\2 Jf*‰f:E!} G::Sֿ;FO T/#~@w3G1@7<;C|v23@ǎ3C]N_Ztsgb<.\ԣ\ =\' ؾx]ݎꦇ s3{ L4c˲7-yIrL/Wꍫ'в]). 0pjRhyՋ2!Qk2½'qFwB65iשs}|>> ٯ87φtiy0wԛ=Nrtt\N_O<}w kNEir[P9hfg;UcJRpU 3Ho%@?k 8+(%lZߑU6 z8)Ș1 G>._ێ]؃mMqYYw-NkyleǗ8՟!x#Ϊ 2F{F G%2q+weپj ڬ, #. :r7$fy# *bAs]$MQ=8pn<- E')h/yBW.UhH#RD}fپ2JdEdu}cM *!.u ۻ,JqDf=t|jVWV8=yx.S Xe|;)=U1"c meܼ|*.X ٛJ@u`+C~ѵE&hx:hUZr<1uH~{nf@^yV}XNq^>P'CCKzՃ XjڧZT[6 'Yh‹)bt_=!Ac0swҗ6*c Ë~2Uth]NW-m"W"S*ʶP`wUhnzQm& ?iԃp uP0Oѹ0~%lrDu@U9CR,cA b5̄J 6#V/+22]Hd;}O5ދǶU,4^6a̢n֥PwƁ<^P\@/F0m ]QzC1>$Z8mo.wBT6n ǚHg6:9~gG& cx1(8'gWcmΜG_ gӪ,ؐCa]R TюJ5}q'DZy!% mF)˅m,/WHy,ZӖrecSw>X&UhN8>SY~14{tbsSIl᜞ޖ8+=pLSW}aVe7~.kb4[b'uR[;Cƺ,1frf 65G_e,(Vr7kUZt'o,F¶S3`N['aYe֭; kՆm8\ђzv}/ܐ m{ktR?:㘮! SoҷC-WY=%"\ldmӂ/, |hSKTf ľQ~`5mъ @<`&yFD[X}aF_ExY,U ; }.se]=nYo=v;_;ژ|hgh14;Ņ$"Ќq_ xOs<M\m\?ᗼْV6N;q*LbY@|>;Fe)ll܄G 51M+Ys^d<1>l^rZ*k4=`U%PUz(3CK!{B\ *xi},i[u!o7F1jga10؄|,}.lYêpC8~;nBkz?rjQ؟+ ,?ƩO#r$V<> +cuhy!N.jh_2вmgW,Q|,몿΀*(nP7]VR0U-G G)49{K]1K>䢃qvq]effY`<71>ȏx#{Lb՝ֈ@W[ US:/6v s;N-Mx}*ȫ"o RӒΪfێyīV};N W~8=afuCR(*2 `7X5 >Wqi#'Qt/dj3Îc_ukS:&,d6/yLz>4dsoؼj uvYkam%;6 LO~c p)T(sH ~zF$R5y%tOև?ϻ;$8¾uf:,%[Kzc@>}+-y2Do:[Vq8+yH^y-\|U~bNrO/=#y6oh[>V=>I S@]#NMmCl 6iaZvz,Tݦ;k H~֔BFgy,^X'%[l=E(z\;ufBu;:x0`m:IWZ(*(,-aII**uæP?r1eۧϲs@N5)VfeA};x=b=:_(BӗP|F+uȞ[$'SMc5hHv? KmÔ&f/b[̽[奾1:/n6owdv9ŶuJ0ri?q5BJRmS,d?v mTj - kV}]OᆑEt, ͰJ7c6or{WbD,¯q5]͏VO2~o1[Evo *(AFQ@DB E DPAiF: ]˹=ٿg{3sM>O²z^Ok僽ݡR?U.ĹzHBz 0 QbM)uP}8sk[X-cd*nz-އ٩?cqT$" xDe7c8SsfU+ՠB?,"9 C. zá3[!ʽ攂0 Q0Н#EAb(i"{nwmXڸd֛w? WQ[֋ KڙUaPE_MʇiZvA 0AR0ԘR/oc@({NvJ&R8У;쟒>ru6ߠVO++ Hjl>pAaaF}y*ww;bfa9 us= B>}o?Ȗy)%s+WUqAz_24ĭ-S <%2zbXIg1JD29q7&fqfv?.1g~/6 pSR'.s+mqa().ܛ mL޶8cEgˇv59S{أc9u; ~\8,g;w+Iw[+$3E^ ׸WX9䡈8EݿQ٧3'b,$QldJ8u ۟ZBcqV6/|y.`L3\~noø5e%TR_9p|FD&R4eb[$ սB/όBIzfԇg? Cu5=1'vCڇWl*[*um*AP' Dž?B~A'b pc_zV֦ʷ=o9_p3Cq55l1LpSjSamvM fK19!5Y¯.Oac̼/j auC%`ɃJsaGLY, ~φi#fFJV-/oE h] bg`f e +2}#k_|>3S20$]T[L9Uǜ ӹd)\H0L+5${$ OԞn?-k.gyЫiWh,_|n> >J??\`pt[0ؙR_e W\?'Btgw9%?uIVE -Af C1cz0-[NtUٗ|PT:\s~o}`|.Oh?r4o,P P_XKP}j4%ׯiB:?K>xFbhd=qZat|,āOa%Ѝ:8<%H?+f z2lm2+i/9|HJTyaq0'5&ڤyzԻ0&fHn -۰.vHsj "#;IQ} o.&;aa2qAnܭAtT(I f>_V*{T o.(H-R6HT= wS,D9:ۯa"~ޥ0^nKGʊz0zZk^9˃מr]UϳH TR`g-5dh49YvڞDj;DP%"КÖH3oHm~3"u~eXL:R"<_)ij e:c'ԯsA=\5Z"uՅ.DTNLD7a<D?l;Eg\:gJ$}l}HC{n*&j=JQjz6$R B$tΆHsD017mw< )j;L~H"#F)"Ү'ƌw֔nmWyixeǻ*RDZN#q!"ǾYtDslj.IEOXTkiX#{XTe;>~L&ZbFix/do%R;<8H%غ|}NI5K4'Kpv||p8}}++~,wG[p?ֽ9qU)jVNj{E>-g@ ÙpÜ?$axIJ9gUƁ7I~ƱKǑ,3Ul;6< *QMywYW=۱,gʋCOLWyepW<Hٿ^} G.^TKDD~QZ'33I<sG[s櫓" `>'ß1=m5ƙ15O6JOv9mtǑi>Ŋw=FdL`3=TNbcfI=wlw(Ǿ#~al1gljzDm1\ 7 ,SJqm.$37cF u Z0HE x{O>6,$*GCHai](Wf2}Ձ3*Ll?.~xGWn,}TK;h|&Oj-RĦt6\//xI U;gh":|l?瘴-|{>9M{"7QiIec2-1~kƝDH>7q|_"܈:D#WRmϋŕ#sNl Qߺmg5 }ۅ–хD%T$. ?.ewS%G0,HN<6Ġ3$'8}1Qko[k ⢙jOp~m:ؠv@Cɾ )7C8#=5j\f-LZ-[Z7zhz퀋c qݪIa})q9 [CjݥM8a}V*.7)ZgFp0g5p ɉݒp>|:(FY$FJbg]/N=J|xt8>(|#e,lՍP5l.mer V.#%ۑ+R/ ~vQ4N}о26φ=©Ij^oI"|ĥˌ/u1+ۏVq.^z9S ߽sDžċ$ 3g{3u5(T^wlwVkfC< 7I]BK尻'`B=3¤aH1d~+]÷'_bBnnhJ'6+ LB["?;*5qw(cTńuǿncS Ŭ,,d.l3Tfo ]o:M@U+0ΥL'z7gsз5";\=􃻬0hʗFB|)~{ {qd;y4;` m~"~Zk]GJwbw XG/(aGц2gD7f.>Ky] c( ɥena^yṮd/]a]"en{`'i0!  ok+ a>=3RQY3a뚧.q:i'WBo֊'sjrFrOcSs7>I[:"~(Lt!릌)|^_/Dר\JۅaۡMh,O<`l0"Edtd%5lPJ OAו0XuC':mE1w)2:vP r%2Ш>&һr&EqU@_R-]|-r-Z 0~n.ǠF媕oFC3ݣŭƓ/=M{{t 5Xe7/zUN0r|#)? k?-jb{EbW!,0(X]W%d5glg@X#ClY 6!8{Fo{_2js HM}?~R^p<6.V^Op+߼$`#HѶu=j2we6^ @Rm8A]ǩV~|-9[%t4q3gGh}Kvc󮩒ns^@0HANPrj[x+X 1+Xkp ~_d7_r1dK.=4؛A+;퐐szĮ.C81!Fe)ڝ*l=wC nϽe;Ϳ `?mӜ;qp-UZ8ᅭXi]o@-cs'r|5؅\Ol1jB>S쎮q6R"т e+qLV:c6&Vz߈QgQ"zZmT /G+_+c߁U8&%5.,!ep?c6RVˣTcB\Z!+ ^QZ?ScJ?q5qgqnqp4X~:=)GWYD-$3Ⱋ£Og9.U8EӨi$q$_ٚH4-|U$zIS$QR q~#M1rMfr3Ax;UBčEvۿ,$:I֦IM/MVhRvuO7#<'Iv}+/INmh9V&m7Y4B^۟Dme5-[HV!az $-Dw kVծ$V$MtS$ZgҮ]$:f{Yj$$:a%jS=__ $ WLzgCEJFa?Lq  w|Nн}4YUo8M~YB/n?9%^h)7?O8w}39}k6H}5 fΎK3bLfÊp%hi*k7s]d3k.'ax?0jz6<,JzOҔEhPy7.3_]AG_lc0?sz-H0\E /i`<NdCIo49); G?X]G pPlwq4حV$~ cCGG`P0,z'wnuKD{uWj0?r$vHY$Qp 6}Z&RY}-#2i>4@ΛԣD-gG#T `Rx_q*jH\ h exQ[ ں} ꤠҫ+Z%!:~1pYz2}IM=~ kGHH5qfcˢF04"Lmc``,Sr:to#mj#H0j,=~GrfIYmΣݍ L;_7>KǿPώDs,(rǪ6dʡƱy;^ͻՁr6=,H~ݺ䪯lF_:GᱸSuD4JT.ɒ9{׼>,L);& _{FP S {c|{%A51;( NywR%֟֩xK@Q>Jo)zͷ.LcECw;'4yqO h+oW,35gE~,ub.RDK^y[VC_kx+cJ5Ǒ4μ: yr-oEUyEjӲs^mQ5h1;{2IzsG }V-|jgj;&gXa X6EvcJxyJ'N8/ڵ|4Z>2Y} 1Klzթ{k=*M=ϩ:_ f.d?ƼX]ʯ-!?ToɻcGׯ#&17UO2Ix/q48{{IK82X%zJ]{>̄|)훚Xwҕj>Z2"o~Cˎ*,xNOij59Ci֊{1vşۅKUaWhW{D{Oh<"EՌ'am1Ld=k.<6jqi)ۺ>{F?g ]6{0)SE 1]&V?,`~B {iJcᗠ+S3}5 VpD ϥGcp4Lv٫vPАz( tmWn@8 ?%I@r sh)u Zq-C4ZաVjw҅tVAA&ޥpH=gkW`{\ .&vbtGm%ƈbA 9Pٜm=D UbXȓ+tz%| X|<;S`ah\]Wk)qwQʸw *2o<m<˨iJ3EҴl]6"P_0{0gg^)yJY #oז7_MuP_:䆈W_g #v<< tpR0hV2I Գ(>n6+أ#DH;m;6:^f;uRw0[~h[ $Ze߽?''W>4E;KCiQ+`t^W5>V5^V|Irh6O8j*}нSҧB,3'i~MZN ާ*l_=~%%[ #0z޸d4,Z*GO1 e7ΐ! 9>=~'_,)Z2oC:"ߏ̷9&Rs0Ia䁇Pq?F:!=?=LwȥT\]K*<4䙭o?'Usx{> CttySX,/Igo9EdwbBfhD?^^WC/w]j*m o٤MF6jb@G7] %5'@_2)F&U 28D3ؗ{ߺ&{>tzO1$Suչ1s~?o_a_yyt>O5a[@pT~}z#_˶';`~"o ^I]qMǨkh֖Ѧo,,DNOa?[3oc,?"0zi/+0׺ޞH <=3 -rvGz"1OhaӘНEzvy4bry KWanD kW 'OciM ? ,SA̓Nq} M8}y)PeܯIrU*ۡ GE>Zy)(R13sjuӕ@!Oѵv%$xh>,258۶ @]Qќl/=x+&|KۙeyFanwMu͎z IoRV8 ;5 q45$]jrUY=]. [^$m6] |G-݅0~6(t)v*X4qf i)+`L bX>KSK$ʠJ ,617yήU‚/5{饤IUՖ{:t,-ҩg8l;dlIe*v4g!T.5Wj1A#c8MZ Fia+zj[y7-y; GX?;lCwbmRaإ6lVb'X0#逳tӞZڃì>xX%=YA*97(SU2ŴMjv:C?Q$RKZ 0R1h]N꾪JR򱏁X'k ?|Ëeʗ!'9/oea jlWfAbd G+)ejXfc_ouojCҺ╻yk Rlv$93LU}?qlYkx]t0[[b*^ ' 4 ; 1B쏮rT'> R HxkFwA^GsP{;T =_+-u//UZiMI0-q!!: *̽5]Ŕ *C3V= }Y37`T{-S;x",׋` ]a&czk)20N.kF0 tt]`iĢQ4(Myy 4W_vW°Ɵ*[@g#>LR 7~ު삖B3:C芧;s&wkjtdީL0h9;#v:#{BMZI/cv2w%H=F7@O7诳f9fg`Lt[*,F]?͞sP"4Lg9@a_,MU F_D쭩c>)< {cGFnP)}RÜzY>KO.c7w!?/G,;OgY%M4UI%ktYdKޏEqD+.pٱn}ͦ僔G ͐,/]UDxR\CpQBq~IE+H?{ .\Pt^gB-/Wz\P|eiN, wrp낐*K5>H|?/qdz#!8 agqzNG8M3A_mD.Ӯ78X8Lgl|pag;sqIHޓg&AZԵ_M)Ӥ`\pf-U¥)ՕA\`:Uz߄p>)hBo,R/&ȧB}tr% /ڪ{%q:`7SHі.;V+z/: Wjp~KW7+`⧆Pu5 ߋ=cfXu eq|悔Vհ* ݁E}C0`8"I.uj)fe7Ӌl$].[L"!i %~gߤ`v/?F#{vrɾ&!$/%;Ìs稇@_RgZ&ϻ]BwMJǯ\-&$TULa VBl>a10]gu/T|~ FV8'B핡πbŎ51Co|/m .$_#l;׍7`HyӮS}o˅kתLA|`H`"=g(߄GO}y.U-߿;bG>LIG{eRIWƠZiRi!99h3jitGߞއC]͠1Y50s'T{mS2a+z趽C[iDU -1e54Qh |TB@6:̻޼vJt=`N? f Cm:O&2xVXeK!W,˧=q''DҲTGݗxԧ.Œ0YnDG7 ͟WGi*CFTy^ҍ2EXFһ%NrBzøe`|tV, %pU**KL0'ߘstϰn@> JlRgeEwoV\Z0 XqrRinq4n>VHǍCL?3e(qqy$mFܸ']ִseq9sq 8[Y7- Ii. >˹YzNଵů8oQ5\H \AE\оG7rs-%:r7,^\SVf8\£\8D]aC9n'q`Ha\+dz7O+f?ҙAyDwy˞SۙoKH+Mݎ$6 \"#ա3RO\ _p늜7׸_5n٣_`~&<œkv_zf8߉mB-uFy`j=U<Џ9inzBI0e$ < n e ,vs23ӿRcKr)vZ/1#NyvB\ԁ>G'9&oP5$0"6&1 ;C죴M+ f}8H~jO?҅ȃʀ2qu>ջ:*2fQeJ(r~k籫oa0fK@f3o%su! +9%6'~g]6TPyOaC'#rtXҭU8k3Qwm5?#hR33erd&Z=F|JH˵vX0" m`[逌X+ 7V/%>$+ )-74sȂ ]xNGaf`OnRϧY]`&.,y|o==Yn k["b09Ʃvx?,D]ql,?)Xvf ܄c@Vx2L>љQzdm뗭#0w_ǻ0vzw%q6U, Ӂ.ÒxwhA,ڼ1[u{z:}ֵU<|Xx~q֊ .,TICe S0,~5Ǽʉ9 :Kp3 Va?jD^$2أj&ܯq;ŝ8pתH]hWv/\ ʹ-Oy-^j+{.bwC<̈́T׊1x-4rڽL;Jr{}6-n(88A͸}En}ⱎjU/V1n5a"ie8L =R6䢑ȋ8q8o5-{.h 6[K8j=S\  '*M68SN&UM5Ty~>YguB;)̸ ~bH6w@+qO!g=V>{[!giv?Ǚ8q!""Æ'=\82)8{utSLñE{(3F+qOgq+v?0Ӌ>!e$waj0ZHnl2$M}d4AJLKRW%\,]pJGrt9̅]iD\qB>q~;N% Br啷H{lI(ܰ5gE2rH[wI1D1I_cL0Fm<&S i BJdpmp:ߍsƆz0ږzx3oj)n]QWvXO ǺjܵMNI%$܅m=?ءw5t@iۖ>L9CbR 8hHf$ʍ%rcؿ*O!K6xzĥh5\逎8ª *x9>+A9K 0hV a3=zb&hͯY[8{/F} c(zkb'b #8)t3s!\婾xua\ 㭀}PyWSCUjKTO>`d5+Y(/kׇN+H+7žCdSm6HLyNevZq!=w3~Weq⢓/zsPԾ< 6 N˨.4l>X ;荺:Gz@fWB)50T9LZ 9¿6%''m.IF0I"~_De"O~5%"ŷ#Xa$>̳|IZnCvS1NƑаuӃts h 0 Ye`ۢE*QXHw)e ,mhI FOkޛ 3OYߠg(:ͽ)xļR#0RcoY:;ިQf2?_ Iw^tA屉a n ˢоjXZ``(.~lf҇e@-}Wjǝҟ^]ێ sexg/V TY{/,gg=iwL9mNwH>3-?䳋D$ی$*d/1\T=K|xkv-.$k˷O|)Y8?f)8S=q9ugv|b=,pj!Bbm6Nv^H7 I4v' ]vkǍK[ yoOO*iz ?*+u^)})t,W|خkYd>ܢtD$۲ItM8؃K ,#rrsצOMNA^DDeh tzx<V 8;btyc5# Xa%!J5AIS~Tw: RA_qҥ6dk?rbs+S ʰo DZ0]ނ1(W!7d8€ˡp|~H<ԡoXYJ&ޏ0ؕ{uH-"'R`ҩڝp!:w*\鄎,nд[SڑLT|*> G{\Be#}_.PF5NcЛ~X6Yn7AڧYӜ#P a;ج!?.u1 .;yrBmK% \W{ b3>X0W#ۢP]疥 WkI֐xqT;SUU.jm;aܿ!#_ī^GڝTau"XY=+]elO- )g .y\{!d% ף5#`ָg$: wfya?d_ '?fC? ~&[ \j_¦2 R@4;` &_H/:03/Z2˞RN90'@NK Q,J}@2V%^+Y?ofύ9/pC><< szTSHʱ3+|g<0u=u=tiu>.#a^{h3,n2+foma*wJ#_Bh'Y%Dx=Lt'l\17a;xA8 fI]7JDôk0MwYZ K~v-ksVQ$*}z,$%* ح{o39Y4s?~N z+i֛WxN5T/l/4d1!:H`NjAFW^`BA_',)f6uB,[y˖n[u9As " :sV[Nn(K6LP'5tÙ^X2,.YZԎ 8TIg M`* |#qf4pi0ŊjõعC'm~NqD2ԻɵͮبXj}07Ì ϼ!(m7::8+AÂn/JT+9R ޥt|ѻ-'m]p8{ķ9$k4ǾIWp$<\zOZަ;ELC86&Wzq%*>Sǃ_,+Ϩhv0=g1o∣KO|~ >GaW\op+L9O\&f1;:eu831 {q#(|b ǃ{>3??ɿ{pф'SH^36/SߎKcoEMCN=L)/;ny_`! `"V-:  2.X|3? ^my▱}-oڡ6 kS(aICV'<<9E]Swz,Huj_<k{0 _¯Yq{kX(>83f$a)B5̧'}H0|fϠYLgwneaC_v7џ)3m NqcI\jo3+.kgexȽXhqǣ.&QY P)"0Tt>,|{G=v}X|)^tIG%L %}ݲΆcq'vlIrcW+˘fKϘ`LֺګOioWӢ-WǰiQ]Vjs v|EI|&W1h$vm$pmo7׹CcpO[mDž|Ƕ)Vlw!Y tRG`@CSBlIN[ Uoiv5'{iIJSpZO8CXZNʼnڬq8IA{i 8|C XWQlNck$תJ+݊sY+w+qm=R^MCf]ӺӻיYpѼb3>ǽF2p(F]3@ѱddjhT:rѯ}-,潮BݎB{]5O6-Z أDա\[zuIy<(Wc R1O땊݌&PZtiܝ  #zCM\]}FH+RH5z߶HgNkN$r(QW; v4{c޻Ş\= +6{f(x}^>86DkH+oiՓ`!!k۸'le^U@lF+J"_\ +v f^>LD6VD*M΁ 2l^+GRku~)Y:.e6GX?zfX _8AX' _nD]<{KL"BX~U"o*J}#H>scE"=N"]蕔T'7rêR_Q\}H*lywvzvfN2 `»pKSW<)>9o0DM*=R R:gk2bJT~6b |)#eroㅙ^?1I( KYƂ6#™ <΀+3a]?J1կqpo_4>UJg!p`\(e9߉Jc81k*ۖ^? S>g8HtLd\sBY]vu~`&^(~ë͋Kj/s$Z$w{ CqzdDP#0}\$y[8++Kq@KD+SԳS i:R0ĕK79H5S>$:疏R$& <5piۿf$3ZO0>NXˮ vF8r42n;g7vr5+'|ᨒ;DH,՛8IҶ7,܁+w_`ɷ4ٗp15M\erޖS_՛ָzԮ~k\Yl܁4y엙7SXoî&~yjZz렄,ֻty@A@\"JՄvp~ 僘*ڧϒܶ^*^:IeI^ qh`6cHQ7Gq'VRʛ\(SkBwvKbWΗW2S\vA!`ǙWLi(bG}J NO*rUan~-xYL k5|̘aXS Rv"/|1V _ɶ2=ٹw6-}wʑB9z٧ p?X3&VҿR?X_D+> x'>U>1\)PsUV< QǜG9j-SO&Խ  Ul0!iq` \<]JuYC[!' tgpĹs.Y{'v\>R8'CMq0l8QGcU) *|g`_ks+ƹFgN@'slrPz}h5 *i9F,YJ 9+[?r9O'4J>pcjn(p(clGt 4L6=(q=vhvnsH?/&C ]-;+\zz _`Y̺D;dI?3|p[ytˊQb/T<&:Jj7n|Qc١ŀ)bk 2ۈӲ 9ļg|/3(CߡN>U"SM})F*1P>wO4ަmgjֹBRBP0= ]LyCY2)j t׳1۰[G%!k_Ou6=dMJ 2sgi௑Wh}/jjӖKn^kCġc:VxaǺ`h|#?i mv~ ("IGAYks0Pl[v AӮ0Gyp u(cwV9 lJ9exߏMC/rn`YR9(Vxׄ,P+1 hA# T8U:U[.,Ia鑐76E'^ oEfMTȽsY,*{y،'X9_ j,!B#UQ<097FM5۷\ :709tc-Y&%%uCۮL3uh$Fʉ @d@2Բwwe4h.4Iu;cRa[#S")r3<(32lwo`ٮRnl0zF F}rzUm/oez>pߨ_NUBejXr+ ^|6v82:uW^xHpb4`WrtMɄdQ Q]n[s 9F#cvnuG13=S%h_+ ڭ mܪBƓ?_Tn!vJ=V [缿CEN܈&3%Xtmݛig\|afȴmB>ef{~^abxcml%0j(2`.&!מ]Y<'cr4u"Y\obmxp6>{'0J(0QMâ+_pBmV}Ƨ;^TݩF/Ohͭ }:,{ ح>vV)D4xydT*bO_{C_G:82~/Zˈ\ފ;VL+1TF'6ۮ2c@V2Eyuf>eK/whk~2O –óyq5?l+=_޾=VL;,abb@z.֟V:K\%o:cI,)[t;[ah#){Yu*r .w1c0ʇneԿv(HYx ԶcN&Cq_f9CW.ᐍaDx​#Ň6=|쌮#)8brβ:ro3[bnA4+1x9?Np0Ճ*L^@!Gs'G~1áu 5sŲO/ϣ^w[ݺ9CbMaY[حD {[? pS8=S"Z]q <ʅ8C&N'+˿]3٧HH=\;V73 vg<1{bn1,x<-Ky&:+8hx?M8c FxaY.?<7Z냽q"6ES+!5!Le(-{w@ӿbЀY`!9AQE z~z [ͳXd|zoA,_d u mL}W`][1P2ם|27_4~tP>hb:0g^oP"G.Ga*ˇ!X^^$I lqW#z-̔wA#Hz2(X^SzfCTA+iSk$~CtbmDh^6z?jWWlOCzE42:/A􅲘5 v{qF>ޓ㭻bؤ%t>V㬄z ?k!\!vo?)|8`vtWn"&  :|"%QZEm%J"8 O$82bmPRN^* M^ eOR`WaxULHo.r;Έ^U=IMg {KvW$~$᳖iוߓh(rHt-,H޻/'y~;杔+ U+u5>Q%њrt؇DE&k\paUbFêF^N%1ph򥜓fu3kP$RF"H~:ќG.r!x3Z'h 9M;F)sO%Q/p@rw$e3Hww\AD@)폁? n$η޲Ý:*zo^3o=ARq%Q+Z+I&Q$<;wDY۰m՝Y[W5V%PGYI vOaa&o:e _YT y7ff^OS2p$E$7H8(ۍGD2-t?rԀ4>xmc;*y/q=Ll!_4+Dsl'r65 9 )IAI0D Y5o=\$ȕw.qgrLQe?O'ȃ%}ǡQs"6 |cv  X-5@u+FZhޭʸ/[zI3?/lkLr$i/x g2~t`?{ϖHxUfw$Pz"^]êkŃDB͋N5ǒDhy8\Eg:>ID\yDRu Bi&|u2&R>P8}t'Amy\s)|D|e+73By]/= _m}Ht.jʐ^olmgzAo5>C$\zQsH4 L{2>QD*o?57c7tA`vFξ }@ oK^J~ m~&TW=`u5XDy>KTσ H}'6}\ v&`Iў>V:2_}Be gkUaQPֱg&rlJF>^罛 `N$0 Zy(X[Nv*,L}U/ȇIݷanTViji7' qsxϵڎNq@ #u + e{B{B_ysmgsZW0Τ? -_Fn@^paV[L0mlg;,c$2 9wO9Zc g`h]Ud䒸^kp=`(e-e`Xs7bw9a-kR@@=js'=dAVc0N}Vyc$`6{0rӉzkg܀MDq*XΙqA8Q6DzNuovȼ>7&Qia,֡06GC|eF6sM" }<=:H1.پ$uqyZ{c$GW/Ucڷ7̵Oe?*dLz Fh#X17:x?lt骘31`'Qu#WQh1s5XI_Qs*qG@i CV4^U1ͤy}J{.a9#i+X.Ͽ~.|崅4KX35Q4?-zW;Y:a%q? ) 06JtNKbX^ ElSԿl#gjxv=?nx9sf_hОiDzc8x}ںC?!45qSO|Sh±pFfqC0 v]M oߣ6pΉH(|neu<ق?(ןa M %dIpei\y-]kWǍ'= A=,=e#]FQ_dp/곏6;A׋N|_kegR L긇_;lEq:7vlp嬕zO[|5SQm8@!(dÞ ԶJK鼯%qW7+5u{d~N~̫O$Jv"R^'e%Rw}RbNަ$IU@$4꜡$4s+'n懽?[Tvw"C.F%3"'Ɖas-Q3"K945nJ6Y-L4zAYf|Vɗ‰3TAjmfD)T{ތQ!R9G&TME">˼ Şݬ>.GC8u;k0T_o8ÅcbhB+Q˗X=M zʎdV$#c8f W-鴼w ƄbY% o5WKo6,Mb:\pAoẸ[C?.3 N5Ņԋ!mqJ&.isWr^G|Qǀ.Ov\[RU_2vb8)4pE)ES L\|RO{ډ%<2_킄OXmޖ^;Z*3 Nb-* ]) oRaWaW֙|(:l\ayg- 'ylŅ$)а0 24Kx> ;`|~d @UhǼ(9qҘDje7bF|;=mM^*{0'x|/=7%BC4D8"?x.Aó~PǛ*4y8s;T[ ׹sQM"^޹Q)FUwf;ATY{6G_V:qoէ,ogA"L&Lx)췹1P5l/V;Lۿ§0vrKJT|Ji nŷ`o&uh >ԏMgC(O÷`"HaA\whװ1}C n\EZ?n"J%daʢdǞOf"vC<z(ÂIP yFj'b~(g {\P@oM69%l3[Rl/'] ^[] zlѬv]=kk ȸ%,l8](njc7=g5/%`$X՛]]XJN2cuKuEدj0-ztCo* :YƨC܌]>(^M! UaO.2L;Zqh0Ѷ: ^8f2oo`Eq0/#rx l4~My;SxI ~ݍ?]GOŨ OWcwx%1hF#\\/eCЈ= [jo\O4r<}Th8zŪA 3ys 34nheK 2qW1_)-to\mj$Op\kz搜KձԸ3^MR%^<!ohqϥ*]?+\m.PjArs4W`O8G<L=}kPiyjr ŽqT 3eN 9]9=8U{S0.ȴġ&@\_8#W}/<[&[{p54yy矘ij*ˆ1awI<*v>s%j7UJF1N4;z]wvs!:o)>=$b׍ qV٣бIZ=6R8am9lŠWJl|q+{NLJy@^l'XPFCeU8}~\o歏`\a%U_~};;cGAvY*6+f[%fY:i"|Y&0wBٜr"' \_Q~ݺpH?<'('vB7?NcPB{w70ާj̫+n=*f/lԋ |eST w_cqM -vʪ _=RgRGBg)(p|\?LS~ B `.Or8e}`ӧ7AQ6$KPu=CְhDЊ,ф{55n8v.B0Z~L T@w(Ovy7T2ŒGixK^rQb+2<`X==E? LC i), 2 0|-'H>^~@Hw %PYN]wSDyt=kVc%\y ^};V #DTa? r;^y6o?GZ;_&|R@b0#RlӅ+n|`[\n0Br &*Z}R0h4, c~Q칂mJ0,JXtn MbcYj&k0dfUQ ːaRu)Xb`sZŸig}sG\„WK?M3} @ڵ]ƢNiKS`Ew 1AA $y .;5ahGMlM̆?TP M،% oy0e 3ٯs=Y7J3v09 "Le>;{V&7zügO) ż00{5Y{j$_~4K/ȩ F0=5O$4bWspP8j.Mof4vٸ6 W?BR/aNEXz[a(Ѩā1mbDX}tQ㠘k͡0!8Q[ѤYu Im[U,o̱>=/ۋav*ߠQA [(8,bi?o6Lm?OY@ 6<9wp!,/wڄGn b `#oc_^LAuLE̽{HsIq~ذ[I'ql47P ֗^ܣ@z[I_X{c܊3=m`NS|KS5VLOT "rVaMg,{'ސ<<124c23ׯ+i>β((hQ=e` }?&"wvk~ǰxí;Sxg{_bO_ϕ[m!{5<ίW1ΉmBF!_8qpfD$-Vji&~ ۳`KT>Tz>~uڨEcoTJS(Tz6lf\ v}DY3̡}6J$[Njc/3أxmPe-,N`_Əz/RHmJn;ppWD/|'X(}%Ovbv|~[r2nBD{dd'm`%A7ȐBFi\zp,Arm\*;w&h@pс5l i㷊VbXO{4U[hW\9ר)5"( J3}`-\4fT/ mVm vp](*Z7\~$Eм:ń -fGUBۭx7ͫ}%%_s$/O|nv=5l+m=4/]1]P˚r>MZsCSFp1jN|ȟ LOk&pݼ=*-C9Sw3w^;F~A[\i*W` G8dQhV;f}Q` ҕ~=4@:VaAY K'9Z/>sx=ɍw]! (G,xfô0/215%3>_ƭЗ=9%mRGT9ZNEJh :& WtIKQJ~nxvϵRwwWzXb̼\c^F֚s٨?Pa~8ρ_t] ?غzfh2 +Pnib&gny."5-D;.wUDQo]4/ j)T-էpQ>(՚e9"Փ;$DZm6H}3"JwkDjjN4J-’ĝ|fdpkǕ;qm{TDIDM>F\m2fwOS,%~9H||nW36;^YDLlj=pdʧB>L<7f_8 u_̕?]1wYPa±ͲO&硭T|Ft 9:NvÄbZv5"꾃7~A逸CkJx }Hy}fBg[f]!4]Aqcy 0aZ=Lp?g?2dnP]+lKϻy 2_܍O:o΃̩R0Ws:WS(#Ï)¡^ؽ.v> ƾVZgϦ87tm3aЋ3.6쁺Q?VG<7yT4ʼ䋆Y89?GZ`B?3u%PVM ^">]/ L$$* tbG(| Gi5rg")`Y [BcD |) 6H [+.zh?!]F6]s[u@YWaz<"61UJy{-#PHoYE',woӹ+!]dKdᾌnu-wp5lܒf>O=-[{hÇH" !#z8"훫9D \kUT"|=TIfەCq4q̠WWX.ju R׊<,MnSHys6xbH'8Bd|CuYHSP=ooiM*-ƇVԩJwDꎙ>nI FxHy7DR2lg'a!], m7O. ׼ pqu)x3F܃XVD2`dZ}+ze䌨~Q4SS541PurGT6#} Tb/xazehyXzCcq@qu.vW#|D_ر@1K7p'l~A;xgYX^L0 cʄa.Nf=c2WGb! ]8b]k 0<x@UeGt@Y2 Εr0+Qr?Xo*w/FN/+hz0!0uRnJhAa/[٬H45[W:x1HbZP^}tn@0e6PhzdK |ՅI0Hu[Z) .yCbOoJYx;, 6h  iq={8Otlɖ:j-lEU&Uh/M ymwvD#4J}8 T>r_ge %ok4 q[3|񆵏gб)^a8+-r[G9A! -U};1Cdu~ju>X>zy,JL V8 l B!fYz'JWh чYfPGMk w'&ٹV{%IX,NVi1y4C!Kh| (̤?띮Sg_,F͘ ~zx?)c(`[oqE=:ɪkdF\x"Q=cJJ՘EŦ X\R[a3Wv\Ĺ_ߤ%Z˄Fh@$gsd^$o{;,D`Goͨ .ɫ2ǵƺGN#l.~U#q=@,a]cE!·8{Q;P>>;u{޺<\8SR||72Yvwkä"EJsmP1$ "qQOwXr}HZ~ט>? FGp岽w_ 4fyvԸаg6H,ҷl@~fY9GE U ZjY<7.:~"(T?9 52rTTAYB@Zn+лo/ Ի)/M 3BW-ns";MmpzEh-p:=aO!Qb9 9qy';|2"EF`3tNs2=*ZςY^ihY5Gޭ g@[m(vJ`k  10}Q++ٴS;,}^͇&MʡCdh;Ll_y`oʃ Rp[VݛJ<plj+cЖӛ&&}xk IN8 ɖQDA`x 4.6쏨?=R6%r7sGEGӍ@ d ӹzbǁ\yjXk4ӭݬނ@lj T07Ch?qk+S f,;&YŒ6a"ݱW?e0iYM;G,/5I`1{Y< 3!L&,0>b~[LD1o8Y<i_1o;HaeT| ]v}g0g:HySf_F`䒹e,8:̗hmIEk8=0] v@>r5L^ZI9|IRaaiZf>yP4)PݫaB~_C!坕#9OL0aO}t3u~嚏vU/Y`z̷#ό_a]wr!bj@Su1-V?%9{lѓ5~XMFbC{ى-4?|JXd+ʆ2:aO\rwziuJWޮaY]c4Fvl g_@ܛ}+NJt+>ptyT]m>mZT1mw[!<"z wAboh!}_jޚ]WQgp[2b[&÷wXW,EjБyWgc qW8~H30Ƀ'E3ǿKC3*H9A>?U 2o/4{oub}Ӏ*l# ίwRct4! T1W͑?b '(C]уWB@ bh.ZOm{ۡ+PP<γC1\ޞl3JNPk6 ZPѿK {? J% `ӏ S´' #${т:vDžuXY4IF&qimH-MO}?CvfcCo.AJ3}{ zlEX^kzm 0lܔ{Z IN&6*t|v}.miz!1Pv+\n;AAsz"Uޛ8 &{Bjh1͘&^e5WP%,n0)'FOA㳬 0+_dui1_C6yCB\MG~G?Kg*_ auXٷe{+y4Hc+`lL{loslu8ճE"9u$nӜ;8\> &Œu/`֬7fhh.PbBcQwz4`f[[, /'H(_OnJv~,wu}T@*;+< eLvn]7A<$hzY?P?uL&Ҧ2̪,M~߾^)CRb].q\YNO]kij? 헨$2XDZ.m_&oH֞,FiTm²3m*A s:b/LG09w$2ȧV,x؋ nESö^qWi=V8*BM1g*)C!j7S|^rEm^W.( x@kY8^ls5}1= y!X1\)\66Dr:Iaw썣sOfٱ3SQɂm~mS0S?GbcBsoّH4"[ c=.s83zA(:( Α&UT+Ċoɶlohwgmڃoȏ]Rv/~PqOHj[}%w;KItXM jy{b,F{ ?/)W͚D8uq2h{{U"Z (pƸ`sf$= <"U8oqU%9*vQ8Yrřr%GGQ|/S gϼ.™ꁵXzbSH‰-q~aZ > ۿŗҚz#'N-%uёƒ,18z:Ԇ)NgV'͸d}w8ع#Fg Niэ6g$i32~~c>Ǒl'/~Y I]uY5y}8y'39v?ܦU|#B[{{Lql*C' WqF,>>$"/& LŠg551h>8+*#Ň LtA+H0%a3 64ϺgOԬPW%fETa7kV^lW\g!Dɺ=pr/iĪ9AǸh*QsŒ8ۣPPd]:OǴ бh5k~.. `īQHt ^xu/@q6j4(¾K$Xu-Ȗ#Nȴ.L{$E`2>uX<.W[\F;J}c9, ԺV_aP*G0A z?:Ip*;W6t[24ٳ_&U ֓YP^l1E~s:дJK{OX(; PKof׋>agO<]m c0+mJ3l"Xg ;2soÀ ]0f(Iw^Q3k>OxtϦ^q07FhGk*{v/'bX!)LC$0 tT!p 2 `GC')vbyltB܄/HL"đt c`M""֪뚼 dzo#ZfsC;mrɥ0nʴb#F #un. MU0rW(㵥WP7?$삵ӈ|bb=!D-V )_;Gsg$t#e)A ު{UĒj zE2^y$;|V`{ _`*Ysp}4_p=xf(\g<>#)RnfE=_%KC$1*7 sb(D^bǷ䕠zU3Mjaf*l[cذC6(g?KoZ#6~X8 ]SMϯJ|!aj Z_j=Pj!W~`\a8y{ǶtmqNKqW?]q`辥$ 8!/+ 2g8.J!B:_/,е)~:U aXœQal|. [,Hvk9st]o̪Uk6Y&e3vgJJ 68ǪcM0p턹R8E:>-*hX@`{:,u9(bz],-nׄImϱ̑unٻ%p{"t+܏MR)?R%R0fh"RE{\%R';DA-1%R}QbF/8O$NrЄHk\FMj#X :B ԅ+wZԿs$Rо<-D4vHys?/TS=z1p+KQ&=R$"nNч.DJ,CT~9J#2,'JN+6DO'qiys i &+D*D꓇ՒDlD[KFloT"RG\t{d4e_=Hy->cpHBq.[װR"UѤ;D_r;3aQĨn2ɇ3v<5(=#3'on׻Fz0zi˝ lNL饿.Cܤvv>z(t8,]!]?191*-儘IWZ |s9+]a϶ЃÚ,0T> :/*RkX}&6OpgzWl1Du &-7 01*%{ /^ٳ 꺬G~!!ү}p5 ׍'b`&Cf70+|~(RM~3m}2oO #)i/C[/Oy' ~AݕceVـ P&c>g3N&S){O?l?t2@Y,ݕ q CE9WÌɻ'|`j'NI4.3t4ӇqCz尠uC/7N$yC9 ûzTAgu.+~hL>7TYOӃ `Aߎ~ p%pT?-W:ٔQi{xkah/ŮSXsVZoެn70#jZ\aZ`#KtjeIKɎ[%G7p 4guLkֹDWݶQ8bhAZ-!bnΙd l'G&xn>f$R8Ȇ*?mB4_q[/u7Ήij؉[R_`tHa|S%GI"}(F"EI )w6o*'RO|Hعx#k۽jO) Ո4\?_;M`ڎטHJJd7ZOM(?yHOoH]'QH!.))e{]xʂz/5TbVJdE "S6&D*K?I`!U9t߸(dQwl# Y-#Twr~ү+P0Ї6^~o`&=~dø-;.O*;_O8F*hK"Ӱ tܿ9'r”\qc 2q-K&11JO9Gqyulb0\튭ŗ^Z`.]wV 2?Q߸IW`nC+>t}f_bjUhX+# B9mv=5O|x|k A.%~@ojF*hou.;gupzA},i >j7*N(Xo E=rZwu0&+*ˊێw@s ]h. XypH3r(&0\qHV?aM7 ֎]S}cNşq|[aztԑ YSa.t(@k}G b6g/]W~Ì@6b e[Ҫ2x"K?@y<) KưpJ̙v 冕DB? ?vG}h`Ϋ,|d2yڦKRr?Srd K&,1v2Nע6f]R.E[/sm[4=&&4w?n*ҁ&#i^%+^}R4u7W!՛#kNX]]&k]y#/)B#JgnBg[M V:\ PJxukf/0 w \SlLз]hx/iN6)]uxy~a ׾ck&gȺ{Q&TT 5nl6`S l9>cW7'O"ֽp|]a4lqHJ#m.CAﷰf)$S eݰƂBaȊ[aEu 鑶PAug+[ٻ.K=~)K=c Z2L)P59 b71J%vo$z#Z^a}&L}~yJin/?'(+fcRkd[bhl;RT#:zu3:v?z3,YCږXêR]͜ZI?ο,0[]@څsE=p.lps.TS`s2zXRLZ'Rj$~Zy u ..ܘkޟXTԁc"}A^B|8>z_?'e7>\֛4dJ.Lz֛ 4OTmcOn7ASeCG1Gɴ%=U%v!`&j"VŒZ;|06vCt__@=o*qO'^x)' \yMBQÉtm0`"&H9ԟmVogD]dvMgo&7 %[5_4!|᯾)v{p\s.3 _Ja`L 0,ʵ1̨DPj[0->k~ c0\ : ='dn?daQ`I5L-nAÞr 20O&lބ yA-gq:6NזYvŲ ,yӔ2f;`>lL{davAW[6Xch)}5/kai67[w3]oo3< $O5{J`I5a\_ZL+`輂8M2,J9^U\a~1l݃E%~0{ =TY/.'jOcVG"9Y.f2|3RB )X9E>aqMg|v5 ռIXr8aBk;-n0ݎPSc_U\}  }Uoay=o лXyBFzp7ZajN l梫m+eǟ=_2 Dž"]גj86 2=?V) BciTp{c̲/+VTd*M5g?=ϻo)[wpK{o2҇Oɟٞ1`n7F14 4"eH/So)=|}P݋Va+7W{IS Q$' y#DR6|9N<~nzzo*=n ?Ņ_ynS>)wFpcf8r>ӪI`#"%UT&)8$xi#6m|}ھ;*yt\$G8'wy=yKD${c.q|J@ :v0\Ɔj*Bm°cfKU,Ujg,GL{ _m-Jrj(ϑ7f I& :1waͯզ+lyMXW2²HÇ:X48-lܘID tkB+81Z&P󛄚^ϖ"aaYziLD4b<&J7qȻ$sa&Q=it\}~74ݽ%e.{gp#N&-9 H⌊:hg<*Pöq!{07ˏWqXcru8#[(MPS|1HBj#}9%u6v?GG&yksXȦ)sǞǴ?Bki[o/3G7aDA\l1E/RHyT1Wj7#iHOs{OMX| ŃJqwPGL9N{|H܏K)Q)uFn<.MĝkU';)8t'OnNƩ!5J"-?pVQׁղFFf),xyuo\8a>"/':t.RFӯlni%}܂[>{[q#%%NޜTrÍy,Q~"E]qH7U^joyE"e^šD*zFG#'Re6ٸC-_g\Kw$tVIX /6FbJĮZiERub=5]z5eݪMJ06nvj0DON MbFJMݙG>,,3ʱt] SϠFZE]]"eQzR7*2՘8b@l9uS^[OKn1`OM=MGFR!r ۲J2P3n2´1 u{jfcqg܆t}j+O9`z6 9+s5#VޤՏUAR=E%):k#w;쳉@ ` 0&n~g1уLܡ?5l 38͏ ]jҶ+>^8LW}V*`x"nlq2j *-EDmp>].x UIso8~w@_4og}F߰q: EoslAQ퇿NqN"d.sޔ]?v[XZ@_hPDj)/),44 oX#3D##n% y*ًS"8)O[зZbh~v'tQ}a=D}VK ?:-)Ն ;ҥ)XQq,?TJ{R/c= }X6~ѬIl[Xu v0g|^z^rZ &J\@'|.Gc?Ih GEZLkÿJjc!bMeNJV#18'CϫiΦȯWqyg/L\"fyR cY _Z0Sa5DܞoT!pl?>Lg V5&P"h= { mea_ Ǔ:I cH,0{!?k 9d yn̯<[9y*o#xto(YQ&bUG>9hYKUb9hJ-Ǭ]OCuY*Gj8/ٜ癦XY฾XTMI UN(8>"w;O\ه$)EB8.m^"L2Zq1æq|q%'{oJD*`$!?wy|R@IdkqTEW1IA_~N:m{h)&jO{-?r?ԡg# b3DZ `qCfgf*-p*,1XK\ Bo [ێ{~a g`M 'S-}qK%i&Ý6[*}<#eS7]ˊF3МO}cRfĔHJ(1ޑM 6 zBFz3/% P|W<}-DҲddgJPa۲!nǡ|u(V-Ħ4/C Sl[#. HjB׊L[),:e Μ1xT~%7OG @"P$yJJҳM΋ʑePSOV6uvV`ݓ7M?cN=c¶o跐6ya< <']=MlrRf{nNJCgFn S{ΐD`|s!T  *cO8c5`/G; 9})Ǡ*EƃwWv' _qK߉ZRtwq,-0NQ.T{ \DŽX^!xh*//0SM, |e0}5%|i] A5_uC= :E*3aV.^.%転zt=jn2Nz¬>r0b|x!]+Rm =-w`T.wС m̠{qsT{;j} k&)zk.-{wVŒCWtb8ʷ wg6k:_OT|P}DrdUrRăC/['4Fq@dLWU&6 \֣gx&`]_!h@GЦ9lIwb& ?QV/s@Etr z.NJ\3yξ rAr="PFɬC0tJi NlHKtبz2kx%CMٜ"`˞psSh&PGXgvv&bza/CmV&uw1NN;e sG2Rw+^[ ô[=`X۽40= @ΉWU*„n&*~㱶 Cr{agR)%kj=ab^WJ.~rUSg( ܳ`} Ojzy05)QW]*I?L#v0zJk>Ht!d߭&-3Ն *_4 rk- p8uNZmd)6Y lu7s$R|.]\.×|@L,5'֞]!8UFo#^Ғ/}Jsz |khMA{ihwP/v0x~'eLcuCx}kxu %t^*td0.L[jU@^09Kc/y?Aс^v[ SMڗaՊ%tf}yݘ?ָ[a0z U!/7+SbՎ 'ڧT8Vu(FJ|{Bm/?_x:Vd ZZ4;pnr) +i҆ƮpQ+k?geMi"_c}|סvás5q鋜ҚPyѬ ⅂/za9֝Urݠր7P`Ʋ'6?YL&ulpxoaQ"_-V)*K ?hJ8&ԔTVzy"x3滀3,?񒪑 eTߏ8 s$E6`˻Rg/(K)eBj}Dէn XQr,Dm^7c Pv^z82jmKGt!iG&$o Y<mMXl ŻRX$~ #8a+w.ΩIhۉCNp0FI kGI/ފ4["Y*hf5%9/"C?|* %.H=e›+2Ts9ᬄYtH*ĥs9 XcC9-Y;jӆf3Xa0yOX"gۙF'Q;wR,73BN5:_91[mt7bp_ȸ`6߆V@ghS[/Ht̄\2\X3yD6캞# b*qAZ^s+֐%o2Bpq`^iS$<H=pY>l[=|.(*9 OaS_+ӵBj\|Ձ%+>s8dq,"Mi)Lk7M1rf;ABQQ\ڜ ={< о[tZQ!rr<:b}d EzQeA \%} ru+4uLpPݠ*e9t\_- Nk/EW}ija]IakV9> 6EI CcCؚ^d/; ٌB/CC-uѴ#zL|c<F>_CKLIJ?m8;OBubN~B0?t޼ ќAVY0yy&3J9\!,u\הts q+EBE7w|[&Y7 ɺZ\hhw ROQGV`gt]VѼ)f[tSԥ\]'R5fo2S у4TPs$P@<50ʾQB< ict x;HȦ}߳$];kBgvc]ӻsϰCQ|j}%]$telUTQ<|M馋Фb2 IN4_aTiStS3g˻_;Fg);Y RA{ 0u"(zo}( 喏\לK&R[a*El]Nx'-ll!YWu5  Ï=XT!AĄ.r9rE=QVs>} hu3`}\X~TTq]ϟaOJ 0.[7 Աr.zv:}K=LNc=OV 'yv>d&=ؼeT(ƞNշݰDmHڽ.amGw8QuuR4ĺo#=/MI&br8U>qn749~nțU߻ GbŚ4I*u-d]44V"A0~\8}sBmp-|8 +eIIa{eOq:!a8Je8X\=;O:bW? 4aO0j#6Ί6PQ^Kv,\8;;/k.\ o=Qc8"u˶lq"Y}@n2} _ޱw2ov%g`V 3д;֎9Iߧ>vgpW#}KfkMކ8p';O@a/"M:ۖ[S.>|i1^w 1|6Эk9o@9߱|K.`} ?!! (8`kLTUvvd&hM[z# h@ )COy#,][x9bgT.?$<À1+$M[֧;Pݴ5B|sRI{`oU'ؕ[~ebTb3'N &:͚`E~dY,L-,.Cئ6lF,D>|j> 4%Q0<]lBD?gث׽ݛ޴>r˛kaPrU 3%v_9 H.gǯBkv0wUt;F@ś@MQEFͷ@@3"@mRFVXT@vcu@5;|zK.@=R9ɇ?NhJGh}:tCwh}Uǃ@cfy@q!GmIT ~|ִ; Ed fYT{]気ԧ8^k>/_{szU-qv :ėto $AGU>Z5PaJC?}u؛xׯ,?:-\#,Yv8UIfC HVړζF#L8`́wq2-S8*ىDڟgCu)݋E*ոQd;Evĩny)$}D8k#neTzf .<r@0 ;L֭]ub}o\J}{3Aͧ\nk_|ޟY*ž \)Bn`-gp!s;.H}?R.*(2+!쳁^XMag; z FU)_0 τ{J Erx\83QV)$_Yو__~e1M"\3L}|}7_J\Yips$DvW$ W?#[COq9HuSPuU8p!pwʐo~fNEDž|QH&xV~EW8+@gd&yq[CC/:ԯF0u˽RӴhAh6s- }A0!vn%&C=s{:FuOU 773Sȣ) yDu pIeL2hj̀nk3Ob{}] Ӟ/lVM)2Ʀw+ql^zO'j O yH8;RO`$+fB\nO-t/;_ $!KCuW̾WOt^g30gMXQZEebN[Hw07 ,%iAf.Y`.NY[kXC `]-!,!A$EY{3aFīk>|,(y# uk#0Ink5ͻMXlW F3 Y?H04y q>awW]v.܊{}ao5XZ0끑=,e%0wMR^w(Ir(=oM5>?3}՞S0tN?tFvnXz~'rZx.m țr0`7&ht9PPg} mN^Y/ a#ỏ?m |'pÁ1@J-?:ѱZMl#+'>Uxo)6$lxx ]L(?l'PEEkLQ^g- [A!ՙI>I2 J'|s_@#|㜲<-Z˜k5TrV2 t&]=q`q>E:8 Vt¦X ?IǨw^AwXq֟;>N Pkqe[!#;{ji;Ga]676)SZ9q&qEX٥A}V~fEâu.|E&J;% {1XM}*E`qf{1D%l  W>(.(@_" oO9at}f(&p@u`u'~UTXH%(d(G|:kTk8O<#< >i}'ކʠ:N<H,1ف$%T/R0kuП3qL-Ҷ4EftaNC *7ݸi~P éؐ; o{fzPsqW&agMV8#JC99Lpl%׀i F[ǐW\p9z6'Q]? = !dqBK=y;Fwax$,KO[Z`ɐ}P\Ɛ8 8>?RfRs3Z aL~f{z.yiJf8,E_ے ܲߊ*cݪ:LD(.%:D*r篸zb=#IH Etc.}5\|7^b RERYH}Wt2u?dҠHF0^ي)!٢2Bi2l{|<_ysx۹N+NGF)`&FGT|aWھ Ii?: p ^ " Uןe3n,Tލw$^ptz!DC8]{rfZ.-V"v+"@2 YΎ0/Ź04e.$znziqB/1F K I(9BD]6=&yC$%dUz׆.IzxMT~>\zK&ͱi$H,uGu:y1a%_ʮ-`6ۣX\ꆕc1AbqY:P/+`βc",fP2A:x0ò,|GF&GEqp=I~Qfe`_{اl?> &^ِ 㯂t6㟍ۼ:=E \Æ'ٰ^z&7>HJԄHil*SiA{z .M|Z =VVj*_~6p_>^^TrPWE2cǥg+in]׼Wx{C4{c׌# b T΋'Q!`I&CN媩x}=r B,4|~dafuI'\O>o8^Fao=gs0νd}MU# 6yMȗh*l ?`ZI3n}2J'rŰY?"W!o~ω/|;AQMf>'j11%H۟ sT13}-VYvo[B?|'˟G:?KgĮClJM5Y"iz6xnR{|+쵬F/xF FG>ҧh)T]2U W7ruC{4-3SADhmv("2"0`-S;'z`o+_R޸,R)z76 DEv`W vXq񻬳1@1;׸Ėɷd\ :a9? {` GNmB᤾#w&:NrrWӐ0@=׭6 sgѡwÆT qvKbeg)*~(FFs-AC/GAJlމ* '&/0fh?AR1 ՚jcTa5X8v%/kO#58 kB]pIEΩ@ SN+}3C#$k@MЖj2]q{r'Ҁߛ1V?ԦeYq>r3"c+0ʃEpBaESEhѝ>5QmM%9-Ηq֕Ik=^ S3#8pa'.LjOx|Ϸp,WrN&v<ͪb3b θ2A٥q=q(J)~ĶBG>3\8zLNn]ݬt'$ʐLByZ\yY3oWvj\lG'8RPߌ<]J9,wlܒ?SƍƲ8}\?NDV 2c78&H3d(0jFUTnѱ8sn}Ž'HYbvM! Uy{cjhlICEI4^{)}Q+E݋%_c>TY߻nL *ܱkIP KDnP 0_nWcv;#b ՇEUtFHya?ιe1zY,~f~T,!?d;硱o,٤13AV o?QfBLHQ{|F^<3LNůiC:3'JIޯD@e[[AkncP5]gHt=ޔڿ{ɢHH@zWB >ݩs JܙsEyjPQԻ=$ )~dy(-[9:_p 5%̫\wϖZ2N@g%5 0XmP f~sGk@uy1)Y)0ágh }tщMݲ#zi<=J?`cn1Pvht^ډamQjPt-͡{#y.o_}yAWAxVx (9ar[|-W sBE^(K,w#9`[ 57=VH* ^wzA + x|Q;CJ8Zʃqꚛ7a$[$ F{1Ao¶_8+wœ_fP>r|T{(s"8+tsQ_/΅51>23A]O~py~g.>3/hb;Ł3BQ85fbΓ?=.{ǷJ(SCߡ<;s7N>>ǙVX;"vL}AMv-.㨟;Y#0 KL*k8WcMĞƊ8 tk폟:tgbE^t`^G6R E dJ!Zl;\.WI Aww_!8-U I 3TlŘo87wLk/rѿg>P}*5*:#aƆ9q@LJaxYdG^SXBCOv= ~6-*{pN,9/ޘ^Obq}Y;`N!.Y:(KpfLJ̫5.JAi^Odj2- nGXy+ ]j`- 2Ԥ bC+>nTUQ rr@3q" 𶎰Bu-?CfXz9*XBOC0yPB/6=]l[]}5\bv^F=݌{b ۈ+wliK"T/t֙F, h_h-9qμg7s`'hv{ %|S/bi/i4ʑv@z@'l6-U1yK4;i7b!Y uL+|cqK+-_ށ1zzR]=a\N./[Fq=37M xEu;,ړ4eV *{V`.7W>,4h.Y2Cyğ\:{|uv}hrfblW`:w͍@*(p<];\!K[,tg,ٹӏ~%#.wVи1Sݪ{`TKi{0d8O@ΤdHjXr`7d}dnDrٟDr#H$/s@$;DT}*q?H%D2ױOH7^h ![zX))|z_v) %5I5"7fu"YA|A:RJCdctqH2O$dsw=rld6 DG/̅a>ѤY8Q_}M\+2 av * `޽N&^4ӆfL0xu](9*Y[7]z ?u,%3L*Ξ뎅2k0A|u?3헚ؼa{ T7I#e}Uy|R[f)$>r< F..t`Z|A8l1G`l]?i.5J>Ps2tK٨)dfLCa{{Tat2+BUOkE A59G:;B˹pEl<ʡ{ @3s>hIwy^No6&?j>NׂuX̢8G bl/Se $KK-=cǠ'@R՞N.Ȏ:%d%bc97n}c:=ROg$mHG#lfXyi3 +''tϪ mǵYSSQr f't {%4aK'{&{[@V:x)u׭s1=/ak62w2l+o וW, Tyex`kA29}&]BD`Wp2(s;2>ѧzKmY^өak܁MuW֐g:ɍw }&#?6)WڔJV5쳚%F0)G7-t*-C@;c1n.!,˻KNB7 MG^^Ճt{ Z߸ A]u'+H:xJ%e{(2FP}Pn#lυU9Б+c{5|OeP.z8D釨C-vNL9wVUBWLEA]z{!Ia@2wHx +/] TsCQ4Άٚ558Dwot aԉX {jEu93pĦZP&ug WIԆR) EoG\4`t."-Ô֚<ےL¢2-鮑ƠPeZI&`2{-o@p &}a=JB|XV)wGCɉWڸR+W|6![J*Cc l3qo4qVeT)xIs!ޯHv&1}l,=ui=οH AѬ}uPB[9hr]tT@?o@xe*oTd6k Ѕ\׋o1zelHb4 |UjI34*:? K<7$}la nz$M= r+*P㲧 ge NY?e`BUu2=f x?\:C:qKeEhc%dzdzI3`C.\R$8Z8 ]H)kI-l9wg-$oL "-A HI -jV z|zx 6ΉN%o̜VEu[ z?=ak;.)M9~-MŏgTjSQK{oa< OʴJw:ƃ5!KQVV]^Ht{IQ{&قŰMwI@lvy:cm-}co PSHL c6~L:MU5 '[Ɏȟ)R PL?S> E7Rֹ 3׶9v8?+L'?LH9+,Y2kt˸ڬ|UŒ8snnT坻0FR3F-G a쫙pqdJ&|m<8JT,sԹ+WkS6R^u̼j㪄c#W^Tw:#2?9Ze-~4gmQ٪P|AP7 y^{Y gB핶Rae_qƩR-uOnJʸ_,14 r}'o^S?FzcBvK: wqԧ͟O׾P?d3Lb=T0oKlaq|>ej>ӧxa^(ѸLv/+B \ FF8vh-.^ʹ:o3ipq@HհHQ94Ukv##;t*U⠀Fge"M{D$_%sG~:Hta |v qΪI+FH;eX=%5d> dcv2{S^_~қ㯒`b-|ƒkiFbn#9,ƾ|Ry$3{ACq 8om0V:uQhP7Ũ\zGv0q_шj\t"Ga~ء\,v2F>,6akP^/z&:h1k=<}hzy]:~N !yg`HqW= 7bUF}ܸX$uXΌf3+ Oayd΋ޡ<~m2WʃCwSwX=X֯}UkJ`VXW9vo- ![›~Ch lIr"njѸ]U]߹78܃V߆aiz,54s*\,`UD⊟,y)a#2)Xk ޛyh lf0z ] xvN1/Ɓ{ $q2 tۯw {i_s?_bui [<%Kc~&Lzs<5"GHDWb*ļZ-egᚬ8#d~1=}0i3 q/fF`M˙fO,ž7APd'aL\ғA ߾c­N8#jr ':xspp=C<6^S=lI)B6V4dbLE07kI)M ő8٢{8}Z .ѵ;x 8(ty/sP8RRtyJ-i^yخ٤3Mpu3 |zNJ*-7LEi\ܰHmsGJk\gbF;Hs{ęTT8xNLmu/[=. BRtFU+dLB ixT$;M&+A?0J&{:EGnC@ |E=Gأk͟0%hp6fy]' K`dv͆Fd ݡ*!ZܬACP-|) Er$,Xts譠8Sq_<7jHHm/]yWگX߅SAbz 4GO@I3*K0xAvΒqzy@KneQB=bk>Jot*|L^{jBS1!sHFωh$@͕zj2Pvq'$ 9@Gީ<*}˯V}ؐǦR UY|߰[jl)gx \+y?Z8ۇ-E,)e=lIT`Ă Kz X=8TH\_a[vBgxj -Vt8Xcq+C=9o|]n_Ke2_/aˮ(]n~vsEE(0KRqm{{ADK`/2%&r[,#^%aRQQ}H'/e%; ɫ律bBճp:X KwkP,gJ9cһGP^)K|2XusƤ;)k'C᎙DK?g*s՘<0_(bq1]{^;q|Ω{B\,Dd)0%+P>HowcW]5ۭtyC^&KB'ZL;x#8%癪;8i$δ3 :ðu% g??¬Ύ>(RM# ogiA2t𙺵96筰Bzɋ6޾x{B)vkMu"dWSN(HŠhkxJ[4aG^ ~]-]'[6´sӘ+#0!;_XUš~ZY :6'gtG%̠ #a}wُܿXYш%rwLJ@: M">BB$JȊRB ][=0*\ 0gKxG>.O߅rgLۋdVM2̋,СB6Q9h;Ik3{j<#g^\sRQkGC5 'pi:gwx%/Lt,Ƴd@=[2 gM|T,ʈ`=_ű,Wۡ޼tga J?C]t;c{@πtB̠4=.ڧuPyyg3H2`g?Pɾ8kwD801+דC&Au̠b`^\w~uW x<_582+G,+ب7N: lBd(,2–~# v)fd[$~zu:`= S3æ,ԓ>&sDըvq{'I. ga;%Eecp䰊Աr* u :"~JM%Z (誴٪'̰Q_Q)oנ5H F4^xJzM/'u 84]h޶i`cql_k}IF!^F–}U{)?s`-6<D;|`MrzƲOEl>x6fL{U`5wluNwڇ;sº}3~y%cҜF 1--"[ ?ta=oi 69/~_+x ]acYXecwגl qG_`)ik,S,V0R܍g{On?'JbOKfI n콺>qh|vHq C_?y7FFr;Fo Vcaˊc9q˘m=D?-r.eߕh.dU}+gjDq]tC4^qGK>jy+TO6Yu1S.&DOA^j8_KU# UO XmO˾boqHͮUŽgjdP gGϞKʸ)r Dz%ܳęRqI <\2o NKULKյzpCzn^%5_I\8 zX6Fs{ ?Gqys*6 ?|sf q}i6η|.ɄkbOc<=ʧ zdy\GYf?n[|Ɩ >gU޸pR9NSr~.=J5ZoK 2 DHx3o_-~H=m >M#;6TH?`̭ؐ4W>!M $MY]< uH/DEaXS?nk|&r@ˎ>3n NȈHÕOu ;W<ѩ;3Z/IO\CL+t?N1:c=79lغCpd&{ԧ >c{bk0%˻H!XyĶӦ/aQ o⎅W-8jJ3 9p򽔒<.w6(]#1ܮCP1#kbue 1b4с 'ùT&R1VDU,=_T]O%w<~h`k2_Ӭ a,\_ph&! 1/{wX1_o_^0˜mw,!x7h|h/Io9佃6nw_-{X,Cu0bAiܪt,8J$,lGD=mSi9ҁCME~:(\ 5SZ%^7 %Lv}'rڳpa^lJ}J5'6u;'4*| ӫbqCq!\q⟤8C$MH>m) rXt},w(uCC_9N:-, zI?n˔7G`=h7t=u*oJH}kst/=_nne R4_> 9(5J%c F{n7cW}!{E:;4؋nr}M 9,P>Ƥ0["y"5$$}mvb B9*6ZlfҘ =kgT ;Qȫ6 9d1bɏan\۳+P)qKs|ΧKɼrh9j ?AG"TmV'>qLStd$(2KUm4V^W!鉩4c Z$ɬ/YeG_B# 0s!7С\ ObN uD":F ޾3m*$ee 0(F,:xPf}/y=iY.RWNI߰RpKKz^OL^* aQb5GnXJxm;~Yf~rzoR0;giNi37UסWdaR(gH W( bN^i>q0T rI`5$$=%.]KAQNo{euއf'jWbY/ ';_0*?XuXy a6mGXh\SlԠ9~Zﰨ)o|f:ozby?sr>;w/ Kzj6ǯek NJ2X>@7Ć[{upưK%З*AH06Ipj]glٰF@j6Y,$)lQad _3Ywd~tvS:n{Elv'bׯ1hYW elZy{_ uaCmRXv&!7+^{4)X0c+#v];/m4úcxR;;e񳡇آ~G GI( (5ͼPV2F}Usr:6vs̞۾hkug69cʁu,&$79Dd]J}-"Z5jpjiR lbi̼; ?gCgpY>~N{)y5P.Nd,҉qk,qܹ~gq'-8Hop?qgw( P̫bO̴8|qy=NB Uy"PZ>.~Jsa,r2;E{_RzS|8O])Utd_t8g'pߎyp:oT<D#m q!znF_ݡ>86`ov{;I\ v:#cf68aO}p" ǒ.nq^y㚁.w}EOm ;s,4r=-ds sHZrHgݲ|Hr"9{ܦybB^g9;+I =O2HM}]b4Hʑge#n78e?CsqfWqNN}HV\rTe˄[{_R9I"iMq~\so 'ķL]7e5/֓*ܱU3ЧB$Q}n+GTZpO>B&B"Gt>W5])ԒKDW/9}qۙ*/=! in)=Gq.-FP~PW'/&d9B!a"?w0D8M*t)Ԡ]dg)[cֱq0_^v/t q;Nء8_I8' فs>'p$X &#|: S?%u Kf/}d `g]d$ߧ_ AjrqjzهwAK5Pb1dԛK_n}3t I29@fEef__Q&#l5C~cmG?FN@qIYYNB$fyz\ kQ2赂Xtzu  gFu˔ h_; ˟EK+aS;xfArNž! JAM'C$9$%X\%ai*#cG;8斨!=L \ֺs"o|<;x6 Ta}WQf| Œ-٦l鱐XۖMe3yf2f`1 ɉxC(ǤDŽR&lٜ=`}7o%>oxVΘfJ߼`pd_ȣ<-SK!eE\oeۅ+W qiS\ ` ޝg"i&ّy\ۚ{wc!n\xn7.5[9|ev(Dpk"d&ng6#G2b1\mI|.}kDޑ8?×*pwŠqN7!\\o9Nn2s}b7T#+pAԜ:nGatDqߨQ*pkmϋ)[] pC"G.3_kc9]_Ln*܇z˕ުBqS\R{doF5qqO,W@'ܙ'`0Gv*{&? n(rz}LvD,F}ݽ>B;_p|Oo68*3uwj`: Q8F8ݯgek4ęAJTzLUG6 7}R?Yܢ0Fەmgt #t),`X7>t^ &2~RPLXxaWyB0:Q74LB!{Lϔ#t.߹aDVu_y~fokES/8$A|eE0[y~&`qګ0$0@3I:ҹNC0bSh\7 C![LwVdZ)`?Fiu`>MUBa " Uޱ: }G&34hȅ^0/˃8.J ]!-a/B#c .h|u[40o(T[ĥNJnB}Nem = r_@)p*ݼSkZVR/Fj:ѽ< կ9-@{@19 v=u+TcLC^}QS3>D?> {;NCrṻ=}V<*Ut[ ~!LPtڿp 8wԚ0ex}117%qXiqrHm"`Z:NtTN1 ެc1Rv$f^yww9("K~qbgD)|o]1L,Hsf>o:%ha 5k33}PE y'x#8~ e4_^Ʊ3eBk35W6`q0F; #ނs17ɔL ~o7K RmqM8nf&' UwIzIo[%I[ps;jV"jw?UTVtc '"/qsDbg_Q"=+kXn~D7W9q[WrAkqL~28DVDl$y؇{^:/%Vkz߾Lz?Es.j#r%$S79^Dž=jzffn[ JVIkӳԗmǣDֵ"SBmMD{nIXcfo:8RwM i!yHzݞJnh%E^SHNnz|., ץ:ZX:Jz/7$\Z$gv2]5?Z4$ I0L970Cֻ{nuE v7[cP ̬H?9b.eM5=}-e\DbA2i^r<`_ploR,mqs{G2^'Fcw/QA KXrd ۉhj頹,~NI2=ĜXe tFcj 0,ʱoP*1k 5}{}$;u(ɏ!G $ \f*Ol n'maX"xT 6n%e`ڲ#ſίF@Dwoh+2q)KYWC޵?PKvU}I=S ;&bp`wm/谨zrpamПe)G{cĉNf(2~ULhÈH ܸ%s*wFLwW6 H@{ᙒC1)@ŜSn=܃PmbӪ<#y/qmACtb qIR|"BZafqHbt́#砢9 ,_{Lq>2 iRϱQ V/R><`u/ Z5ҷu"+,,;K +A:,n$V0׾_ fzsKNUs^OjV`]mHJrCY{kayν̱ўE }a罾',>e7UaY?+0#js 6øX`BYaQT݌ h*ZM1TX^fΫ psWXJ$?L-q7*Gh";w_ŠX6;.5+ט忓}aY:3ք bq҂6~q<1_XӄtqO#lQUVSYl,_: ll~׸2/,Pq~̰NXRb9_x {ˌ>}a87Jj&glެ2]XG`?+#*TöS9eHLF b f;Ex'[$.`>cX&=k"\\H ֚rૺǚ"?Cr$ (!?)`߳oW9&+_qbGNrL vYCʫHGwڸQA+?|pvu{-jeL4Y>^[[_=!S~yMNCWʟqr"SDzj'{7 X/8\ΪH|Վ 8~%Iox}B!.-?~VC{/OOqy<:?\+٬{.f_ $%⌱ճp\k]ݬ m- oSb ׂ.OlM}-Xb:JqdO88| ݓpWL(Ne/-ጁlo2+'qڎŘm;l+P?=5׻6p.ҕᢍ՟K8|JT$0}&^/ΚゖANc=vC+Sϊ^ +3E"g9qFo\yvhr%ο8T'S %pAFyDjuf3 NU|V4\b:.U6{ ?.s8zI!1[>}-_qmT627e(pZ% ΝcfN#q\W߷qjB70 ɑ1|կGqۀWq|/1_R2'Ž {iq5̈́\Ҹ@VLf' iH,.ܨQ3wq>[1tF_jڿ>Oo߹wh 0W^dx$|N qNX::w>ʱ\Vw.h{'B L,<: 5gK/C麗4'PF4G|F0zIbO^O i:n̈́*#?C!1hcn jM+ך׋!1Kt0iba0u+%/J4NA)r!:N(=O3,5ͨԄ9(>hxfM# 2x*d*ܮvlA%2wlOUU?#k+(682KQx6H(G(ZQ+˫>s`g%S8%Lד4Yοc?aX1o! ޹ cW%OC*{_i"I;ǑfTafy<,\K7utK25>NTzԶ0}g1zVa4wS{0P9 8`Nz%FKLtVf1Cǘ`cyVdLՀa;0ۯ! a~8<&B[A˃\1 aϑ_#c=)w:Z?ǒ2+0+RU0X;7$áZ JdD(WgYEחӒ‰꥿KgI\z&M^C'7ǥ HeaG-p4{e&Df_̆Peq s{NA+8ԪgE V>sxOK$Ǔ5-$~#=wL_BYak!j0"P$Is e*ћ^zd M{ތ,OPg3_`cDm޷AaMmp:.u#`#邠 uSitWgtILUh. ŗc  ±VN!܎pZOG:6}<- N3q X7+`Y'_<lag,evy\dAnjG =mkmY9W$] .4`ŠSx"BVV R:m[ן%X xҔo{ Ibl쐘u;EXD#owz-?T`vDB0Fu_/%pwgC- Q4fOOöQlmw㴅߾Ń/tmCM|RIǢs_*Fk YKVZasLUo0zu4.AL+?$L}><҈?`/5fz1:ȎM!Gdh8"R{7̳2h1 /l?0Wzl`:Q99J \6ܜ>b]7X2t^&X{RdSbF7R/pT0c{Ue|Ĵ%IVt=JwS$K kr:Cf*6(|=CBuٸҐ8wI 6 : ;eX &.Cx lS@'Up lzG3zزrىCP\ip+ԕ*G;B=*hֺA"LЏߟ=> 3V`ŰAo@UI Ӓ9( 7otZb}byng趃Ue.C:G+#,mZzwbVO?z'9!%y?UW5W K}91CŎ٫_P9a4?iDZLar\Jg_|..tx3~y}T=k`P.IQVE_j4*Eqf#N؃:3H:kTz /ic i e Hoo:*֖-aРVCi<Q˥#8uk Xd`h{ֹC١7٫pqL-=DPHke$9gl`H9 3)qcZPa1ES= 5vla+:wNY ~݅r9_c-ȉZHz]D bu|%</`sGn]s-D爵Y۹xB˪,;5yT34Q(xun`ZJ.nZ z'8LmR\/_lv@~E&\hW^ϒc5ha2 -z)$/CY^aаông³DZڮHV?8_Y GȈX1!Kv<Ƶ RmfؾB= Gk ;L{$^E0p`7"Pk20x?b7H m@jS.5H:Aʦw+!uE{ `ts6dԖxfߘ kC-[N,)Iv,+b8)]"v 7[*> `7y[QNW`+_/R?y'YXL`ǥri'U4xd}ţ };z~ܴրzғG5Y{~6EouO uTtשHC͢xKP/= ] +}jz^{1mOͦjP>'bZ'N~+H@GL|7K敄ϯ 4%=\O!6;ZD7_ЦcĖ 2<쥪TQl$v[/ 0V/<ElU[W;WM}PC~t5MqXQ7Cױ5{2=/ˊ=>}7`oy~Fe6,2z_P{,PS)4#\x'0P(0M58W#Ds0r߰9\4!*^85r1=#-<=[)R[#^]Opy $bg2OOFCfӕ~*~mҋ^ ,2(\.GfR=8Â3R-|z_ҟzEw(iMݾ/髏]S 4B/+`'.ǻcS84d.iP\OaˮFSRw)uЙ=n rx ⦝% .^ ŋZ]_Ҏ.|G(&( r~h٨&}+M 6zʔv8T\.c@|8GzhV\lC 8R6seR-o\ 1uùwkƍXn\PZz"칮ZlF> s9."T 2ӈϸ~Us,@ -mGM8i ٻ_\V|tian^V BâK" 79S .Ks߹dlrdd }hpJէs7'd.ܶEа6npŹ~3wp]x΋#|$Aa>/L?vZ~mAՁosTomORf<v;%sG6@FbXLFJEII eKal߷p  '9TCAzY =yvS : هc(l_ԝПj zڽ.ԅ[ e0g5&̾уV.uv_/"b/TH$|;I;^TAeGnx gD4l@VQǨ!lێ܁l*> mb}:tqR+bFkt_@[hPy>|~S#mbӱ~,Mq K]0vl݆7Zd X ;oG%<E&sHڹ{c+0tSr7S>8٢-k"rNjTBqdV-7V˙*dF% 0Ә6zhYaND#sLZ{`.LZԞ!}0zKF T_:G !9;J i}L|OFQnٻ=%̗ d)M_ $5N%|4E {RuT݌_6Q@}̈́@)45I;$v3<~g?SEF:T-}@~t~ U>t@b؍@Y{6X^sm>#=bG y5Ҳ(Jd $or٢ag|HGV@J7T(b*h@IZďsM@V7 iO g9N$ H;Ӥm l]we0lr%WLdIig :tM$6s۶KͩF@ svޑޝƪ4ȵ=r]ҁ3dԲz;k3/K˱OGg8Λ8S^O9ZudGF^a;5ssOgǒ[=5s'p\o$X.o;lU_}6>"]iƚ1ƻ38@Q& ྊM5dc˥K+q}rӇQo9{3TBMP㌖w$ tEgv/_Y f.C Qg|Xϑ~\n_Łx9}q1=9u8e>5!a5is=vznQR|_.J859l.ey6|N 'dnՌ%l'2?ES4ꌤ/ i1E$ I;X!ik >3'}Hqyyom>qRo")5\~4$ۛ Ib83F{I$44}/Jga "3)ZWj{xpptĂs[n)F;gt o|7 r^۱[ h4^e wEܠן9@O$er9&H"'/+^aTZ ʇ #E%DK&pG\OWTuO?Yfr<lZqcx(qI)" r!:QH%. ůbJN+V7>M<^AR+`xj8rƱ2 *KVQ}RaOC|@'&L!h%*Wu~^Bb5t6ӌ6=:%}邙8TP4¡w> tؐY p|{2 9<˕~^e~beNavwi /2Le5? utz_aiہ!cD+- IGGIȫ?2y7V5_={ZM~xpFS\0 Z<;kF/jW"*rǁ"^xs:qËc0=% |5sXiw >ˆyNY߷klV-879Xlɏj؟iiy/+Suc4/;NJ 5׏Aɛ"%q/7  )] I$4Ȑ1H*$2d& %It3̳}2p^\C~g>}γ~gLn^=/}32PNVG0";cp7 ZWCYmgK7b%$;=6 ._ :uhXW{:@V=ϑ\E~kͰ?/P/q{ 2kynK0h$S+j{UAjgV *_Ie2j~ ظ)tEd(}kԝ'?ցyah%znQw􈨷G1j@:S2 \zn_XWpWLwpW r tеZXf40.! Z.}Ec+tШ©vGū0^#)( f{WPN*ON(,~5-*\|q^ ԑ+sXX+)K.4ǫB}j މApX\۾=i+Fmzb j@&5VKF]Z٘ ~X\ guQ0y Or#L*j} +:lv.J!?ICcY"^u\ByQC.-YP^ HcU'^n;OPj? v2>G|Iz~% FLV@BM)u9vڢ1ZELC%Pܺ!ь2sZK0_q讖?ԢvѨv2k՗ι䆔oV1 >יF2y(yhnFue{Pl1oN?e}uہʵ$ٳo`F8"ܻ6)0MCSؼQqaIʼC? 촟XΡr#:¥ uT`@;#l_n?18G '(enoU{ U o3@S'2x*\NFR%:CbLN=}'%sqꢋ&M|^4{U^e4Ifnf mH}sr'7@Aqk1T}xT@e)_8Fk(i{"ܸݗиcΩc6(oLl޵aJkBm #' eDP߆c)qJ)XBٕ$#a|\Vx& zBjV=;ac7rG!S_*N,رòtA"?/_rWr"K#ih~|L\_ hܭ&E5#Wwk\FK> dè}{ZX`0z+~m2.WA=ʾeWîCLLp=s5~x<Sy00$zm;#b>؎/A9v &}&~ r-ϣZUh@KT74DOn~גQK!/!UāA[S lgOGo2..9N?}XS ;t2aJNTVsbL(:~>zǞNfvGCӅz}+e<%in#GץxEzLcV!;2.U[S9yRuu;Qf+RfhME;FUfF 87{,T &rb>娶;X'-p1i;|?}ǭhe JHѹ7U7me)]ҹ K6`R6^!;s6dpGp56r]m3eOnpB\.fTbW})},;Z4Xl B876c>Oȫ(]z&4t9Qv.z5Y͝j'iJE#gf/lPs |MOńް#'t` m,_{hㆈ.]P`ġ[N"ܑrE =ͳD^'"bMb4jHEɿw{?{a+FS_JAkcg~LE3 7fQQ}vLb5^V5y#҃۟\tѸy}!SlMqeVh^ORr_/ EVlZwL9,^u>)$i~^ ܔᔛOY[9H]R҃ >h}s#Qmy RњC;>^PU[ɈCbʁT{`{wʠ.u<-̅c-aYVo>y?w;Dm. ;$!/X?_2d=q/~1`{8mJkrM ƙN#Fo -Ajb+'O$a,9$7? 6햞9x"62Xc$#+Cϥ(&.UvYWk,fS_wڡ&˜bmVwA;bdۈ|< ,\ϐo> K,"|[^X*6RF,D(_}0a,ЖbZuRl6] [jܐO,^6Y!sBm~&Rȟ$bkY,/`ipx6+]Kj>&O^σ%mgvٜTRnihˠk9;~G[o=ʢeNF]c gHZZ\td/ (MQ^0HץSNj&0Igx0u5(?CXӖZ8BqLcK=s{{ }'ĕs`#h Ȃ~*0.~Ի|\o_nfxt$¨_^QVLq-FBt*&k95\eY ,jMÄ`(p\Bptadc<_q7|ڛ 8xU # l!7I-U8* An90~rO,l R}V,ؗ0~NH>_:p,\A+'';ҵ3hIX?hU6/^c02GsGp|}].Dzuf)&s~i d*| YJsͣwK[j]}ZYCAdOÈ?@HnA}8=tykvTš䓭6 &y<+KBOa#G<]~547º/X> {,OX~/ P '\'>=:Hfg`QP'HfՊ>Ϯ^uH{?=(~W"J͎Ia`O[a.S\*ޔoÆpSd!gXtV`)-uutatQ>X;#R_x $gOK9 HeRbԺ̢_!-uw \zy!b]"H5 >: X(ݗ;jUmhas|v}z(`Ґm> 8N:qhRSV寥C@)zI5aarx| sRR/b䨵qw=s-i@^%6QAjP04JIMVbFL:& `3]XTO -嫅Q0[OH_{'L|O.qUsyoZsWa2yLJ4q Lb\#at&CE.<51MM]vd5pv-0ӥauvDzBK$ua Wvf и3GI:%Qx9=0G[p>/Ԩ"fX =R2?0$.pW8FVnC4i].ζa'ĩ# 3a2Dܐif?yp,5M@@$9k9s[֊{ 'T٫c c,udJ_Rѩ L }0'ť+\;xsH* ƨs<&^f+k"`4o7WNdU0>&5Bd5(_L)E5Om_]y0VQ[sA\uYH.VU~he8PA&W"`5E6' €yt9%qԕ޷ɟ/H a>pjjB^6o~B)HNz~Wc{{)xuړ=/g xcUcZx)cx$;Lx ml237~R$s> ^3/o8 yOtK Y'@[)YAY=5vu>']s{xX8.52eI([}p`Bt¿ևC=o|8a[=;.;]`v4%B 0i ӿuw[{-xsVne zY lhֻfpUUOb"|9CojcfmA' SX \{jqƕqÒU? r7I$Oi v9ޅa3L ]6Y+"c<ՙ8 PZP jCх|4aZU‡̖VeN >QS1@[xi 4^°xnJmN |YU9( Y,U).QW?<B?\~N  lšv;h/v9/̐%atϤ֑y7)<;' mn\ď\TLAZJ\&4o\ eMsq8C5c({U! ^$Pr,k۳}p5o|Z4Oń pL$?Ri [F(s>˱R!|)8/r?SZ Г)I$کPpW t-R•sy'Sj\Ag&SԹy?~μ`~ST9_\?RQSܔvm-(33{5ӿQ?q[+;s+Y9;l;!V5ww;<ecodist/data/bump.pmgram.rda0000644000175100001440000000113613131506235015550 0ustar hornikusers r0b```b`f@& `d`aIzE ` L|@9:_?2QAqC9>n(A*%n9*ڦA`ɭ2ys;&mr067u{[irز_Pw- &r3Wrqsp`(݂'!|t@ߠ:D$ B]@M3 z.n `K˞_\ǯaɒs5Dy|/s&]c>o Wbɷ̈m>#QWn_Jx{.'a&?96~{tMi68^s~~Rf^80T{Y ;25Jɥy2/<]=ZRcN&1^Hc%E4%@%y@64)2bZ19P&[^zQ~iWZ%@2#$Pc% * P3R3S%$1Tzecodist/data/z.z1.rda0000644000175100001440000000122613131506235014125 0ustar hornikusers r0b```b`f@& `d`aq j 4P! uT:GǁJ~DEY(_qC9Pqy7[ 7(;s?禃Tb[qP槊?q..Xurk-TL\s`rXnAi}> B_ jW:oPZ"~A?[z z=B7@(E- (^e?E=d7N^i߮aڴM;~ǵ7y}t̼KmW0{| G΢ 3O-?|MvSVmx& tú㴒s7 uuJ}St~ICu")֮mFMI>ceŕ?Yanq0PO&\yN#>asW}CuO_-XbdOV5o'Aּb C 9P&[^zQ~iLx s ,/׃ Jՠ;t[saRKҊ ,$AڙCu0M(83?PsCqɜecodist/data/bump.rda0000644000175100001440000000043313131506235014265 0ustar hornikusersJ@mH O>Ff&}KuQ ecodist/R/0000755000175100001440000000000013131454521012122 5ustar hornikusersecodist/R/xmantel.R0000644000175100001440000001343613131447663013735 0ustar hornikusersxmantel <- function(formula = formula(data), data = sys.parent(), dims = NA, nperm = 1000, mrank = FALSE) { # Cross-mantel test # Written by Sarah C. Goslee # 01/01/01 # Updated 6 April 2001 # added to ecodist 10 July 2017 # # formula is y ~ x + n1 + n2 + n3 + ... # NOT y ~ x | n1 + n2 + n3 + ... # The | means something else in S-Plus formulas. # # Uses C for permutation and bootstrap routines. # # Cross-mantel is a variation of the standard Mantel test that # takes nonsymmetric full matrices such as those returned by # xdist and xbcdist. # # This version calculates partial coefficients by permuting the y matrix. # # Will calculate the simple correlation or n-th order partial correlation # between two distance matrices in either of two ways: Pearson (mrank=F) # or Spearman (mrank=T) # # A permutation test is used to calculate the significance of r. # The permutation test was designed to be relatively fast, but because of the # way this was done, there is a possibility of repeating permutations of # 1/n! where the distance matrix is n by n. In particular, for small matrices # n < 8 or so, it may be better to enumerate the permutations. # # # As an added bonus, this function offers the option of calculating # bootstrapped confidence limits for the correlation coefficient. # nboot is the number of iterations. # pboot is the level to resample at. # cboot is the desired confidence limit. # # xmantel returns a five-element list: # mantelr is the correlation. # pval1 is the one-sided p-value (null hypothesis r <= 0) (0 if nperm == 0). # pval2 is the one-sided p-value (null hypothesis r >= 0) (0 if nperm == 0). # pval3 is the two-sided p-value (null hypothesis r = 0) (0 if nperm == 0). # llim is the lower confidence limit. # ulim is the upper confidence limit. # Stuff R needs to be able to use a formula m <- match.call(expand.dots = FALSE) m2 <- match(c("formula", "data"), names(m), nomatch=0) m <- m[c(1, m2)] m[[1]] <- as.name("model.frame") m <- eval(m, parent.frame()) m <- as.matrix(m) # m is now the data for the Mantel test as # cbinded matrices # Determine the size of the matrices & do some error checking. # if dims is NA, matrices are assumed to be square # otherwise dims must be specified nr <- nrow(m) if(is.na(dims[1])) { nc <- nr } else { if(nr != dims[1]) stop("dims doesn't match data \n") nc <- dims[2] } nmat <- ncol(m) / nc if(round(nmat) != nmat) stop("Matrices don't match dims. \n") if(nmat < 2) stop("Not enough data. \n") # If there are only x and y, then use the data as is. if(nmat == 2) { ymat <- m[,1:nc] xmat <- m[,(nc+1):ncol(m)] if(mrank) { ymat <- rank(ymat) xmat <- rank(xmat) } ycor <- as.vector(ymat) xcor <- as.vector(xmat) } else { # If this is a partial Mantel test, get the regression residuals # for y ~ n1 + n2 + n3 + ... and x ~ n1 + n2 + n3 + ... ymat <- as.vector(m[,1:nc]) omat <- vector(nmat - 1, mode="list") for(i in seq(1, nmat - 1)) { omat[[i]] <- as.vector(m[, seq(i * nc + 1, (i+1) * nc)]) } omat <- do.call("cbind", omat) if(mrank) { ymat <- rank(ymat) omat <- apply(omat, 2, rank) } omat <- cbind(rep(1, length(ymat)), omat) xmat <- as.vector(omat[, 2]) omat <- omat[, -2] omat <- as.matrix(omat) ycor <- lm.fit(omat, ymat)$residuals xcor <- lm.fit(omat, xmat)$residuals } # Calculate the Mantel r mantelr <- cor(xcor, ycor) # Standardize the columns of the matrices so # that z = r and we can do 2-tailed tests. ncor <- length(xmat) w1 <- sum(xmat) / ncor w2 <- sum(xmat ^ 2) w2 <- sqrt(w2 / ncor - w1 ^ 2) xmat <- (xmat - w1) / w2 w1 <- sum(ymat) / ncor w2 <- sum(ymat ^ 2) w2 <- sqrt(w2 / ncor - w1 ^ 2) ymat <- (ymat - w1) / w2 if(nmat > 2) { for(i in 2:dim(omat)[[2]]){ curcoll <- omat[,i] w1 <- sum(curcoll) / ncor w2 <- sum(curcoll ^ 2) w2 <- sqrt(w2 / ncor - w1 ^ 2) curcoll <- (curcoll - w1) / w2 omat[,i] <- curcoll } } # If using a permutation test, start here: if(nperm > 0) { # Set up the arrays needed. zstats <- numeric(nperm) rarray <- rep(0, nr) carray <- rep(0, nc) if(nmat == 2) { cresults <- .C("xpermute", as.double(xmat), as.double(ymat), as.integer(nr), as.integer(nc), as.integer(length(xmat)), as.integer(nperm), zstats = as.double(zstats), as.double(xmat), as.integer(rarray), as.integer(carray), PACKAGE = "ecodist") } else { hmat <- solve((t(omat) %*% omat)) hmat <- omat %*% hmat %*% t(omat) hmat <- diag(dim(hmat)[[1]]) - hmat xcor <- as.vector(lm.fit(omat, xmat)$residuals) ycor <- rep(0, length(xcor)) cresults <- .C("xpermpart", as.double(as.vector(hmat)), as.double(as.vector(ymat)), as.double(xcor), as.double(ycor), as.integer(nr), as.integer(nc), as.integer(length(xmat)), as.integer(nperm), zstats = as.double(zstats), as.double(as.vector(ymat)), as.integer(rarray), as.integer(carray), PACKAGE = "ecodist") } zstats <- cresults$zstats # Calculate the p-values. pval1 <- length(zstats[zstats >= zstats[1]])/nperm pval2 <- length(zstats[zstats <= zstats[1]])/nperm pval3 <- length(zstats[abs(zstats) >= abs(zstats[1])])/nperm } # If not using a permutation test, return 0 for the p-values. else { pval1 <- 0 pval2 <- 0 pval3 <- 0 } # Return the Mantel r and the p-value. unlist(list(mantelr = mantelr, pval1 = pval1, pval2 = pval2, pval3 = pval3)) } ecodist/R/fixdmat.R0000644000175100001440000000035313034761244013707 0ustar hornikusersfixdmat <- function(v) { # Converts a row-wise distance vector to a full distance matrix. n <- (1 + sqrt(1 + 8 * length(v)))/2 dist.m <- matrix(0, n, n) dist.m[row(dist.m) < col(dist.m)] <- v dist.m <- dist.m + t(dist.m) dist.m } ecodist/R/bcdist.R0000644000175100001440000000176213130723423013522 0ustar hornikusersbcdist <- function(x, rmzero = FALSE) { # Calculates Bray-Curtis distance (1 - percent similarity) for the # rows of a matrix. # # If rmzero = TRUE, all empty rows of the matrix will be removed before calculating # distances. Otherwise the distance between empty rows will be set to 0. # # Sarah C. Goslee, November 1997 # # The same functionality appears in distance(), but bcdist is substantially faster. x <- as.matrix(x) if(rmzero == TRUE) { xsum <- apply(x, 1, sum) x <- x[xsum > 0, ] } dist.v <- rep(0, (nrow(x) * (nrow(x) - 1))/2) cresults <- .C("bcdistc", as.double(as.vector(t(x))), as.integer(nrow(x)), as.integer(ncol(x)), dist.v = as.double(dist.v), PACKAGE = "ecodist") dist.v <- cresults$dist.v ## give the results attributes similar to dist() attr(dist.v, "Size") <- nrow(x) attr(dist.v, "Labels") <- rownames(x) attr(dist.v, "Diag") <- FALSE attr(dist.v, "Upper") <- FALSE attr(dist.v, "method") <- "bray-curtis" class(dist.v) <- "dist" dist.v } ecodist/R/mgroup.R0000644000175100001440000000212113130730263013551 0ustar hornikusers# mgroup returns the Mantel correlations for group contrast # matrices computed from cluster groups across a range of # clustering levels. # The inputs are an ecological distance matrix # and a vector or matrix of cluster levels in any order. # # dlu # mgroup <- function(edist, groups, nperm=1000) { nl <- ncol(groups) if(is.null(nl)) { groups <- matrix(groups, ncol=1) nl <- 1 } outtable <- data.frame(nclust = rep(NA, nl), mantelr = rep(NA, nl), pval = rep(NA, nl)) for (i in seq_len(nl)) { # number of groups at this level: thisgroups <- groups[,i] if(is.factor(thisgroups)) { thisgroups <- as.numeric(thisgroups) } if(is.character(thisgroups)) { thisgroups <- as.numeric(factor(thisgroups)) } cl <- length(unique(groups[,i])) # create group contrast: gdist <- dist(thisgroups) gdist[gdist > 0] <- 1 # run mantel: m <- mantel(edist ~ gdist, nperm=nperm, nboot=0) outtable[["nclust"]][i] <- cl outtable[["mantelr"]][i] <- m[1] outtable[["pval"]][i] <- m[2] } outtable } ecodist/R/nmds.min.R0000644000175100001440000000175513127734276014015 0ustar hornikusersnmds.min <- function(x, dims=2) { # returns the minimum-stress configuration from nmds output. # (Results from nmds) # if dims==0, returns the overall lowest-stress configuration # Otherwise, returns the lowest-stress configuration of dimensionality dims # patched 2013-05-09 thanks to a bug report from Kellie Carim # superseded by min.nmds if(dims == 0) { x.min <- x$conf[x$stress == min(x$stress)] } else { x.dims <- sapply(x$conf, ncol) x$conf <- x$conf[x.dims == dims] x$stress <- x$stress[x.dims == dims] x$r2 <- x$r2[x.dims == dims] x.min <- x$conf[x$stress == min(x$stress)] } cat("Minimum stress for given dimensionality: ", x$stress[which.min(x$stress)], "\n") cat("r^2 for minimum stress configuration: ", x$r2[which.min(x$stress)], "\n") x.min <- x.min[[1]] x.min <- data.frame(x.min) attr(x.min, "stress") <- x$stress[which.min(x$stress)] attr(x.min, "r2") <- x$r2[which.min(x$stress)] x.min } ecodist/R/xdistance.R0000644000175100001440000000161713131447766014251 0ustar hornikusersxdistance <- function(x, y, method = "euclidean") { # calculate cross-dissimilarities between # rows of x and rows of y # returns a nonsymmetric matrix where # d[a, b] is the dissimilarity between # x[a, ] and y[b, ] # Sarah Goslee 2017-02-17, modified from legacy Splus code dated 01/01/01 if(is.null(ncol(x))) { x <- matrix(x, ncol=1) rownames(x) <- seq_len(nrow(x)) } if(is.null(ncol(y))) { y <- matrix(y, ncol=1) rownames(y) <- seq_len(nrow(y)) } if(!(ncol(x) == ncol(y))) stop("Matrices must have the same number of columns\n") x.names <- paste0("x", row.names(x)) y.names <- paste0("y", row.names(y)) x <- as.matrix(x) y <- as.matrix(y) d <- rbind(x, y) d <- full(distance(d, method=method)) d <- d[seq(1, nrow(x)), seq(nrow(x) + 1, nrow(x) + nrow(y))] rownames(d) <- x.names colnames(d) <- y.names class(d) <- "xdist" d } ecodist/R/lower.R0000644000175100001440000000037613034761246013412 0ustar hornikuserslower <- function(m) { # Takes the lower triangle of a matrix # Does NOT check for symmetric matrix m <- as.matrix(m) if(ncol(m) != nrow(m)) stop("Matrix not square.") if(ncol(m) == 1) { warning("Matrix is 1x1.") m } else m[col(m) < row(m)] } ecodist/R/crosstab.R0000644000175100001440000000645013122534732014075 0ustar hornikuserscrosstab <- function(rowlab, collab, values, type="sum", data, allrows, allcols, na.as.0 = TRUE, check.names=TRUE, ...) { # Converts field data in the form: # site, species, observation # into a site by species table # # By default, takes the sum of the data # Can also use "mean", "max" or "min" # Sarah C. Goslee # 24 Sept 2003 # ### # # if allrows or allcols exists, will expand the matrix to # include all of those elements into the rows or colums of # the results matrix # scg 20 Apr 2006 # # added data argument to simplify using data frames # added count option to type (length of matching data) # scg 2 Nov 2012 # # fixed bug with expanding single-row or single-column values using allrows or allcols # scg 17 Feb 2017 # added na.as.0 argument; scg 18 Apr 2017 # added check.names and data frame return 21 Jun 2017 if(!missing(data)) { if(mode(substitute(rowlab)) == "name") rowlab <- data[, deparse(substitute(rowlab))] if(mode(substitute(collab)) == "name") collab <- data[, deparse(substitute(collab))] if(!missing(values) & mode(substitute(values)) == "name") values <- data[, deparse(substitute(values))] } rowlab <- as.vector(rowlab) collab <- as.vector(collab) # if values are not provided, a count of combinations of rowlab and collab is returned # equivalent to table(rowlab, collab) if(missing(values)) { values <- rep(1, length(rowlab)) type <- "sum" } # if type is count and values are provided, combinations of unique values are counted if(type == "count") { values <- paste(rowlab, collab, values) values <- as.numeric(!duplicated(values)) type <- "sum" } values <- as.vector(values) results <- switch(type, mean = tapply(values, list(rowlab, collab), mean, ...), max = tapply(values, list(rowlab, collab), max, ...), min = tapply(values, list(rowlab, collab), min, ...), sum = tapply(values, list(rowlab, collab), sum, ...) ) if(!missing(allrows)) { allrows <- as.vector(allrows) allrows <- c(rownames(results), allrows) allrows <- sort(unique(allrows)) newrows <- allrows[!(allrows %in% rownames(results))] temp <- matrix(NA, ncol=ncol(results), nrow=length(newrows)) colnames(temp) <- colnames(results) rownames(temp) <- newrows results <- rbind(results, temp) if(is.numeric(rowlab)) { results <- results[order(as.numeric(rownames(results))), , drop=FALSE] } else { results <- results[order(rownames(results)), , drop = FALSE] } } if(!missing(allcols)) { allcols <- as.vector(allcols) allcols <- c(colnames(results), allcols) allcols <- sort(unique(allcols)) newcols <- allcols[!(allcols %in% colnames(results))] temp <- matrix(NA, nrow=nrow(results), ncol=length(newcols)) rownames(temp) <- rownames(results) colnames(temp) <- newcols results <- cbind(results, temp) if(is.numeric(collab)) { results <- results[, order(as.numeric(colnames(results))), drop=FALSE] } else { results <- results[, order(colnames(results)), drop = FALSE] } } if(na.as.0) results[is.na(results)] <- 0 data.frame(results, check.names=check.names) } ecodist/R/plot.mgram.R0000644000175100001440000000113313130004475014321 0ustar hornikusersplot.mgram <- function(x, pval = 0.05, xlab = "Distance", ylab = "Mantel r", ...) { # x is the output from mgram # pval is the p-value to be considered signficant # ... are additional graphics parameters x <- x$mgram pval.v <- x[, 4] pval.v[is.na(pval.v)] <- 1 plot(x[, 1], x[, 3], type = "l", xlab = xlab, ylab = ylab, ...) points(x[pval.v <= pval, 1], x[pval.v <= pval, 3], pch = 16, cex=2) points(x[pval.v > pval, 1], x[pval.v > pval, 3], pch = 1, cex=2) abline(h=0, lty=2, col="gray") invisible() } ecodist/R/pmgram.R0000644000175100001440000001733213130004471013530 0ustar hornikuserspmgram <- function(data, space, partial, breaks, nclass, stepsize, resids = FALSE, nperm = 1000) { epsilon <- 0.0000001 if( class(data) == "dist") { data <- as.matrix(as.vector(data)) } else { data <- as.matrix(data) } space <- as.vector(space) n <- ncol(full(space)) # This function does four different analyses: # If data has 1 column and partial is missing, # Multivariate correlogram # calculates a multivariate correlogram for data. # # If data has 2 columns and partial is missing, # Piecewise Mantel correlogram # calculates Mantel r between the two columns for each distance class. # # If data has 1 column and partial exists, # Partial multivariate correlogram # does a multivariate correlogram for the residuals over whole extent # # If data has 2 columns and partial exists, # Piecewise partial Mantel correlogram # calculate partial for each distance class separately # # results are: # 1 dmax # 2 ngroup # 3 piecewise mgram # 4 two-sided p-value # use breaks if it exists. # If nclass or stepsize aren't specified, use Sturge's rule to calculate nclass # classes are shifted so that they don't have to start with zero if(missing(breaks)) { if(missing(nclass)) { if(missing(stepsize)) { nclass <- round(1 + 3.3 * log10(length(space))) stepsize <- (max(space) - min(space)) / nclass } else { nclass <- round((max(space) - min(space))/stepsize) } } else { if(missing(stepsize)) { stepsize <- (max(space) - min(space)) / nclass } } breaks <- seq(0, stepsize * nclass, stepsize) } else { nclass <- length(breaks) - 1 } answer.m <- matrix(NA, nrow=nclass, ncol=4) dimnames(answer.m) <- list(NULL, c("lag", "ngroup", "pieceR", "pval")) answer.m[,4] <- rep(NA, nrow(answer.m)) # standardize so mean = 0, variance = 1 for(i in seq_len(ncol(data))) { thiscol <- data[,i] ydif <- thiscol - mean(thiscol) yvar <- sqrt(sum(ydif^2)/length(ydif)) thiscol <- ydif / yvar data[,i] <- thiscol } if(!missing(partial)) { partial <- as.matrix(as.vector(partial)) for(i in seq_len(ncol(partial))) { thiscol <- partial[,i] ydif <- thiscol - mean(thiscol) yvar <- sqrt(sum(ydif^2)/length(ydif)) thiscol <- ydif / yvar partial[,i] <- thiscol } } if(resids) { mgresids <- rep(0, length(space)) } else { mgresids <- NA } if(missing(partial)) { if(ncol(data) == 1) { colnames(answer.m)[3] <- "wtI" for(i in seq_len(nclass)) { dmin <- breaks[i] dmax <- breaks[i + 1] answer.m[i,1] <- (dmin + dmax) / 2 space.dclass <- rep(0, length(space)) space.dclass[space <= dmin] <- 1 space.dclass[space > dmax] <- 1 if(sum(space.dclass== 0) > 0) { ngroup <- length(space.dclass) - sum(space.dclass) answer.m[i,2] <- ngroup answer.m[i,3] <- (-1/ngroup) * sum(data[space.dclass == 0]) # similar to Moran's I if(resids == TRUE) { mgresids[space.dclass == 0] <- residuals(lm(data[space.dclass == 0] ~ space[space.dclass == 0])) } if(nperm > 0) { zstats <- rep(0, nperm) tmat <- matrix(0, n, n) rarray <- rep(0, n) # cat(i, "\t", answer.m[i,1], "\t", answer.m[i,2], "\t", answer.m[i,3], "\n") cresults <- .C("newpermone", as.double(data), as.integer(space.dclass), as.integer(n), as.integer(length(data)), as.integer(nperm), zstats = as.double(zstats), as.double(as.vector(tmat)), as.integer(rarray), PACKAGE = "ecodist") zstats <- cresults$zstats answer.m[i,4] <- length(zstats[abs(zstats) >= abs(zstats[1])])/nperm } } } } else { for(i in seq_len(nclass)) { dmin <- breaks[i] dmax <- breaks[i + 1] answer.m[i,1] <- dmax space.dclass <- rep(0, length(space)) space.dclass[space <= dmin] <- 1 space.dclass[space > dmax] <- 1 if(sum(space.dclass== 0) > 0) { ngroup <- length(space.dclass) - sum(space.dclass) answer.m[i,2] <- ngroup if(ncol(data) == 2) { answer.m[i, 3] <- cor(data[space.dclass == 0, 1], data[space.dclass == 0, 2]) if(resids == TRUE) { mgresids[space.dclass == 0] <- residuals(lm(data[space.dclass == 0,1] ~ data[space.dclass == 0,2])) } if(nperm > 0) { if(is.na(answer.m[i, 3])) answer.m[i, 4] <- 1 else { zstats <- rep(0, nperm) tmat <- matrix(0, n, n) rarray <- rep(0, n) xmat <- data[,1] xmat[space.dclass == 1] <- -9999 # cat(i, "\t", answer.m[i,1], "\t", answer.m[i,2], "\t", answer.m[i,3], "\n") cresults <- .C("newpermtwo", as.double(xmat), as.double(data[,2]), as.integer(n), as.integer(length(xmat)), as.integer(nperm), zstats = as.double(zstats), as.double(as.vector(tmat)), as.integer(rarray), PACKAGE = "ecodist") zstats <- cresults$zstats answer.m[i,4] <- length(zstats[abs(zstats) >= abs(zstats[1])])/nperm } } } } } } } else { if(ncol(data) == 1) { colnames(answer.m)[3] <- "wtI" for(i in seq_len(nclass)) { dmin <- breaks[i] dmax <- breaks[i + 1] answer.m[i,1] <- dmax space.dclass <- rep(0, length(space)) space.dclass[space <= dmin] <- 1 space.dclass[space > dmax] <- 1 ngroup <- sum(space.dclass== 0) answer.m[i,2] <- ngroup if(ngroup > 0) { ngroup <- sum(space.dclass== 0) data.lm <- residuals(lm(data ~ partial)) answer.m[i,3] <- (-1/ngroup) * sum(data.lm[space.dclass == 0]) # similar to Moran's I if(resids == TRUE) { mgresids[space.dclass == 0] <- residuals(lm(data[space.dclass == 0] ~ partial[space.dclass == 0])) } if(nperm > 0) { zstats <- rep(0, nperm) zstats[1] <- answer.m[i,3] for(j in 2:nperm) { xmat <- full(data) xsamp <- sample(ncol(xmat)) xmat <- xmat[xsamp, xsamp] xmat <- lower(xmat) data.lm <- residuals(lm(xmat ~ partial)) zstats[j] <- (-1/ngroup) * sum(data.lm[space.dclass == 0]) } answer.m[i,4] <- length(zstats[abs(zstats) >= abs(zstats[1])])/nperm } } } } else { for(i in seq_len(nclass)) { dmin <- breaks[i] dmax <- breaks[i + 1] answer.m[i,1] <- (dmin + dmax) / 2 space.dclass <- rep(0, length(space)) space.dclass[space <= dmin] <- 1 space.dclass[space > dmax] <- 1 if(sum(space.dclass== 0) > 0) { ngroup <- length(space.dclass) - sum(space.dclass) answer.m[i,2] <- ngroup if(ncol(data) == 2) { data1.lm <- residuals(lm(data[space.dclass == 0,1] ~ partial[space.dclass == 0,])) data2.lm <- residuals(lm(data[space.dclass == 0,2] ~ partial[space.dclass == 0,])) answer.m[i, 3] <- cor(data1.lm, data2.lm) if(resids == TRUE) { mgresids[space.dclass == 0] <- residuals(lm(data1.lm ~ data2.lm)) } if(nperm > 0) { if(is.na(answer.m[i, 3])) answer.m[i, 4] <- 1 else { zstats <- rep(0, nperm) zstats[1] <- answer.m[i,3] for(j in 2:nperm) { xmat <- data[,1] xmat[space.dclass == 1] <- -9999 xmat <- full(xmat) xsamp <- sample(ncol(xmat)) xmat <- xmat[xsamp, xsamp] xmat <- lower(xmat) xmat <- xmat[xmat != -9999] data1.lm <- residuals(lm(xmat ~ partial[space.dclass == 0,])) zstats[j] <- cor(data1.lm, data2.lm) } answer.m[i,4] <- length(zstats[abs(zstats) >= abs(zstats[1])])/nperm } } } } } } } results <- list(mgram = data.frame(answer.m), resids = mgresids) class(results) <- "mgram" results } ecodist/R/xmgram.R0000644000175100001440000000475513131454177013562 0ustar hornikusersxmgram <- function(species.xd, space.xd, breaks, nclass, stepsize, nperm = 1000, mrank = FALSE, alternative = "two.sided", trace = FALSE) # Cross-Mantel correlogram developed from mgram() # Sarah Goslee 2017-02-17 # # This function calculates a mantel correlogram for a full cross-distance (non-symmetric # but square) based on the geographic distances given in space.d, also a full cross-distance # (nonsymmetric but square) distance matrix. # nclass: number of distance classes # stepsize: width of distance classes # nperm: number of permutations for mantel test # # Default is two-tailed test (H0: rM = 0; alternative = "two.sided") # May also use one-sided test (H0: rM <= 0; alternative = "one.sided") { dims <- dim(species.xd) space.xd <- as.vector(space.xd) # use breaks if it exists. # If nclass or stepsize aren't specified, use Sturge's rule to calculate nclass # classes are shifted so that they don't have to start with zero if(missing(breaks)) { if (missing(nclass)) { if (missing(stepsize)) { nclass <- round(1 + 3.3 * log10(length(space.xd))) stepsize <- (max(space.xd) - min(space.xd))/nclass } else { nclass <- round((max(space.xd) - min(space.xd))/stepsize) } } else { if (missing(stepsize)) { stepsize <- (max(space.xd) - min(space.xd))/nclass } } breaks <- seq(0, stepsize * nclass, stepsize) } else { nclass <- length(breaks) - 1 } answer.m <- matrix(0, ncol=4, nrow=nclass) dimnames(answer.m) <- list(NULL, c("lag", "ngroup", "mantelr", "pval")) answer.m[,4] <- rep(1, nrow(answer.m)) for(i in seq_len(nclass)) { dmin <- breaks[i] dmax <- breaks[i + 1] answer.m[i,1] <- (dmin + dmax) / 2 space.dclass <- rep(0, length(space.xd)) space.dclass[space.xd <= dmin] <- 1 space.dclass[space.xd > dmax] <- 1 ngroup <- length(space.dclass) - sum(space.dclass) answer.m[i,2] <- ngroup if(ngroup > 0) { space.dclass <- matrix(space.dclass, nrow=dims[1], ncol=dims[2]) mant <- xmantel(species.xd ~ space.dclass, dims=dims, nperm=nperm, mrank=mrank) answer.m[i,3] <- mant[1] if(alternative == "two.sided") answer.m[i,4] <- mant[4] else answer.m[i,4] <- mant[2] } if(trace) cat(i, "\t", answer.m[i,2], "\t", answer.m[i, 3], "\n") } results <- list(mgram = answer.m, resids = NA) class(results) <- "mgram" results } ecodist/R/MRM.R0000644000175100001440000001213313051662140012677 0ustar hornikusersMRM <- function(formula = formula(data), data = sys.parent(), nperm = 1000, method="linear", mrank = FALSE) { # MRM: Multiple Regression on distance Matrices # Sarah Goslee 2008-07-18 # tests R^2 and regression coefficients using a # permutation test # added method argument # linear is the default, standard option # logistic adds capability to do logistic regression # - this will be much slower # mrank is ignored if method is not "linear" # Stuff R needs to be able to use a formula m <- match.call(expand.dots = FALSE) m2 <- match(c("formula", "data"), names(m), nomatch=0) m <- m[c(1, m2)] m[[1]] <- as.name("model.frame") m <- eval(m, parent.frame()) m <- as.matrix(m) # End of R stuff. m is now the data for the MRM test as # columns y, x, n1, n2, n3, ... # Determine the size of the matrices & do some error checking. n <- (1 + sqrt(1 + 8 * nrow(m)))/2 if(abs(n - round(n)) > 0.0000001) stop("Matrix not square.\n") n <- round(n) if(ncol(m) < 2) stop("Not enough data. \n") if(method == "linear") { if(mrank) { m <- apply(m, 2, rank) } # convert matrices to column order to ensure compatibility with C for(thiscol in seq_len(ncol(m))) { tempmat <- full(m[,thiscol]) m[,thiscol] <- tempmat[col(tempmat) > row(tempmat)] } # use matrix form to speed up calculations X <- m[ ,2:ncol(m), drop=FALSE] X <- cbind(rep(1, nrow(X)), X) Y <- m[ ,1, drop=FALSE] nd <- nrow(X) # only need to calculate (X'X)^-1 once XX <- crossprod(X) XX <- solve(XX) # will need to calculate Xy for each permutation XY <- crossprod(X, Y) YY <- crossprod(Y) # regression coefficients b <- XX %*% XY rownames(b) <- c("Int", colnames(X)[2:ncol(X)]) bXY <- crossprod(b, XY) SSE <- YY - bXY SSTO <- YY - sum(Y)^2/nd SSR = SSTO - SSE # R2 = 1 - SSE/SSTO R2 <- 1 - SSE/SSTO R2 <- as.vector(R2) # F* = MSR / MSE # MSR = SSR / (p - 1) # MSE = SSE / (n - p) p <- ncol(X) # number of parameters estimated F <- (SSR / (p - 1)) / (SSE / (nd - p)) R2.pval <- NA b.pval <- rep(NA, ncol(X)) F.pval <- NA if(nperm > 0) { R2.all <- numeric(nperm) # for regression coefficients, use pseudo-t of Legendre et al. 1994 b.all <- numeric(nperm*p) # try out an overall F-test for lack of fit F.all <- numeric(nperm) cresults <- .C("mrmperm", as.double(as.vector(X)), as.double(as.vector(Y)), as.integer(p), as.integer(nd), as.integer(n), as.integer(nperm), R2.all = as.double(R2.all), b.all = as.double(b.all), F.all = as.double(F.all), as.double(numeric(n*n)), as.integer(numeric(n)), as.double(as.vector(XX)), as.double(numeric(p)), as.double(0), as.double(numeric(p)), PACKAGE = "ecodist") R2.all <- cresults$R2.all R2.pval <- length(R2.all[R2.all >= R2.all[1]])/nperm F.all <- cresults$F.all F.pval <- length(F.all[F.all >= F.all[1]])/nperm # b.all contains pseudo-t of Legendre et al. 1994 b.all <- matrix(cresults$b.all, nrow=nperm, ncol=p, byrow=TRUE) b.pval <- apply(b.all, 2, function(x)length(x[abs(x) >= abs(x[1])])/nperm) } results <- list(coef=cbind(b, pval=b.pval), r.squared=c(R2=R2, pval = R2.pval),F.test=c(F=F, F.pval = F.pval)) } else { if(method == "logistic") { colnames(Y) <- "Y" newdata <- data.frame(Y=Y, X) fit1 <- glm(Y ~ ., data=newdata, family=binomial(link = "logit")) # want to save coefficients, deviance & df b <- coefficients(fit1) dev <- summary(fit1)$deviance dev.df <- summary(fit1)$df.residual b.pval <- NA dev.pval <- NA if(nperm > 0) { b.all <- matrix(NA, nrow=nperm, ncol=length(b)) b.all[1,] <- b dev.all <- rep(NA, nperm) dev.all[1] <- dev for(i in 2:nperm) { newSample <- sample(n) newY <- full(Y) newY <- newY[newSample, newSample] newY <- lower(newY) newdata <- data.frame(Y=newY, X=X) newfit <- glm(Y ~ ., data=newdata, family=binomial(link = "logit")) b.all[i,] <- coefficients(newfit) dev.all[i] <- summary(newfit)$deviance } b.pval <- apply(b.all, 2, function(x) length(x[abs(x) >= abs(x[1])])/nperm) dev.pval <- length(dev.all[dev.all >= dev.all[1]])/nperm } results <- list(coef = cbind(b, pval = b.pval), dev = c(resid.dev = dev, resid.df = dev.df, dev.pval = dev.pval)) } else { stop("method must be 'linear' or 'logistic'\n") } } results } ecodist/R/residuals.mgram.R0000644000175100001440000000012513034761246015347 0ustar hornikusersresiduals.mgram <- function(object, ...) { # for S3 "neatness" object$resids } ecodist/R/min.nmds.R0000644000175100001440000000206013130016770013765 0ustar hornikusersmin.nmds <- function(..., na.rm = FALSE, dims=2) { # returns the minimum-stress configuration from nmds output. # (Results from nmds) # if dims=0, returns the overall lowest-stress configuration # Otherwise, returns the lowest-stress configuration of dimensionality dims # patched 2013-05-09 thanks to a bug report from Kellie Carim # this function replaces nmds.min dots <- list(...) x <- dots[[1]] if(dims == 0) { x.min <- x$conf[x$stress == min(x$stress)] } else { x.dims <- sapply(x$conf, ncol) x$conf <- x$conf[x.dims == dims] x$stress <- x$stress[x.dims == dims] x$r2 <- x$r2[x.dims == dims] x.min <- x$conf[x$stress == min(x$stress)] } cat("Minimum stress for given dimensionality: ", x$stress[which.min(x$stress)], "\n") cat("r^2 for minimum stress configuration: ", x$r2[which.min(x$stress)], "\n") x.min <- x.min[[1]] x.min <- data.frame(x.min) attr(x.min, "stress") <- x$stress[which.min(x$stress)] attr(x.min, "r2") <- x$r2[which.min(x$stress)] x.min } ecodist/R/mgram.R0000644000175100001440000000500713034761246013361 0ustar hornikusersmgram <- function(species.d, space.d, breaks, nclass, stepsize, nperm = 1000, mrank = FALSE, nboot = 500, pboot=0.90, cboot=0.95, alternative = "two.sided", trace = FALSE) # Mantel correlogram # Written by Sarah C. Goslee # 10 December 1997 # Updated 13 March 2006 # # This function calculates a mantel correlogram for species.d (a # lower-triangular distance matrix) based on the geographic distances # given in space.d (also a lower-triangular distance matrix). # nclass: number of distance classes # stepsize: width of distance classes # nperm: number of permutations for mantel test # # Default is two-tailed test (H0: rM = 0; alternative = "two.sided") # May also use one-sided test (H0: rM <= 0; alternative = "one.sided") { species.d <- as.vector(species.d) space <- as.vector(space.d) # use breaks if it exists. # If nclass or stepsize aren't specified, use Sturge's rule to calculate nclass # classes are shifted so that they don't have to start with zero if(missing(breaks)) { if (missing(nclass)) { if (missing(stepsize)) { nclass <- round(1 + 3.3 * log10(length(space.d))) stepsize <- (max(space.d) - min(space.d))/nclass } else { nclass <- round((max(space.d) - min(space.d))/stepsize) } } else { if (missing(stepsize)) { stepsize <- (max(space.d) - min(space.d))/nclass } } breaks <- seq(0, stepsize * nclass, stepsize) } else { nclass <- length(breaks) - 1 } answer.m <- matrix(0, ncol=6, nrow=nclass) dimnames(answer.m) <- list(NULL, c("lag", "ngroup", "mantelr", "pval", "llim", "ulim")) answer.m[,4] <- rep(1, nrow(answer.m)) for(i in seq_len(nclass)) { dmin <- breaks[i] dmax <- breaks[i + 1] answer.m[i,1] <- (dmin + dmax) / 2 space.dclass <- rep(0, length(space.d)) space.dclass[space.d <= dmin] <- 1 space.dclass[space.d > dmax] <- 1 ngroup <- length(space.dclass) - sum(space.dclass) answer.m[i,2] <- ngroup if(ngroup > 0) { mant <- mantel(species.d ~ space.dclass, nperm=nperm, mrank=mrank, nboot=nboot, pboot=pboot, cboot=cboot) answer.m[i,3] <- mant[1] if(alternative == "two.sided") answer.m[i,4] <- mant[4] else answer.m[i,4] <- mant[2] answer.m[i,5] <- mant[5] answer.m[i,6] <- mant[6] } if(trace) cat(i, "\t", answer.m[i,2], "\t", answer.m[i, 3], "\n") } results <- list(mgram = answer.m, resids = NA) class(results) <- "mgram" results } ecodist/R/vf.R0000644000175100001440000000331013034761246012664 0ustar hornikusersvf <- function (ord, vars, nperm = 100) { vfcalc <- function(ord, vars) { lm.list <- apply(vars, 2, function(x, ord) lm(x ~ ord), ord = ord) coef.m <- sapply(lm.list, function(x) unlist(x$coefficients)) scores <- atan(coef.m[3, ]/coef.m[2, ]) scores <- t(rbind(cos(scores), sin(scores))) scores <- abs(scores) cor.m <- t(cor(ord, vars)) cor.m <- sign(cor.m) scores <- scores * cor.m coef.m <- lapply(lm.list, summary) r <- sapply(coef.m, function(x) sqrt(unlist(x$r.squared))) list(scores = scores, r = r) } ord <- as.matrix(ord) if(is.vector(vars)) { vars <- matrix(vars, ncol=1) colnames(vars) <- "var1" } else vars <- as.matrix(vars) nvars <- ncol(vars) if (any(is.na(vars))) { warning("NA values in variables will be removed\n") naindex <- apply(vars, 1, function(x) any(is.na(x))) ord <- ord[!naindex, ] vars <- vars[!naindex, ] } vf1 <- vfcalc(ord, vars) if (nperm > 0) { how.many <- rep(nrow(ord), nperm - 1) perm.ord <- lapply(how.many, function(x) sample(1:x)) r.list <- sapply(perm.ord, function(x, ord, vars, f) f(ord[x, ], vars)$r, ord = ord, vars = vars, f = vfcalc) if(nvars == 1) r.list <- matrix(r.list, nrow=1) r.list <- cbind(vf1$r, r.list) pval <- apply(r.list, 1, function(x, nperm) length(x[x >= x[1]])/nperm, nperm = nperm) } else pval <- rep(0, ncol(vars)) vfres <- cbind(vf1$scores, vf1$r, pval) dimnames(vfres)[[1]] <- dimnames(vars)[[2]] dimnames(vfres)[[2]] <- c(1:ncol(ord), "r", "pval") class(vfres) <- "vf" vfres } ecodist/R/addord.R0000644000175100001440000000645013051670436013515 0ustar hornikusersaddord <- function(origconf, fulldat, fulldist, isTrain, bfstep=10, maxit = 50, epsilon = 1e-12) { ## add new points to an ordination configuration ## by minimizing stress of new point location ## brute force, similar to PC-ORD method setgrid <- function(minvec, maxvec, nstep) { # find midpoints for each midlist <- vector(mode="list", length=length(minvec)) midlist <- lapply(seq_along(minvec), function(i){ thisstep <- (maxvec[i] - minvec[i])/nstep seq(minvec[i]+thisstep/2, maxvec[i]-thisstep/2, length=nstep) }) as.matrix(expand.grid(midlist)) } ########## if(missing(isTrain)) { isTrain <- c(rep(TRUE, nrow(origconf)), rep(FALSE, nrow(fulldat) - nrow(origconf))) } # set up extent to sample: +/- 1 sd osd <- apply(origconf, 2, sd) omin <- apply(origconf, 2, min) - osd omax <- apply(origconf, 2, max) + osd startgrid <- setgrid(omin, omax, bfstep) colnames(startgrid) <- colnames(origconf) # set up output objects fullfitconf <- data.frame(matrix(NA, nrow=nrow(fulldat), ncol=ncol(origconf))) colnames(fullfitconf) <- colnames(origconf) fullfitconf[isTrain, ] <- origconf stress.fullfit <- rep(NA, nrow(fullfitconf)) for(thispoint in seq_along(isTrain)) { if(!isTrain[thispoint]) { # fit a new point to the ordination configuration by brute force # 1. make a distance matrix that includes selected new point as the last row/col usethis <- isTrain + 0 usethis[thispoint] <- 2 # orig points are 1, focus point is 2, points to not use are 0 pointdist <- full(fulldist)[usethis > 0, usethis > 0] useord <- order(usethis[usethis > 0]) pointdist <- pointdist[useord, useord] pointdist <- lower(pointdist) # 2. which of the startgrid gives the lowest stress? pointstress <- apply(startgrid, 1, function(x) { pointconf <- rbind(origconf, x) sstress(pointdist, pointconf) }) conf <- startgrid[which.min(pointstress), ] stress2 <- min(pointstress) stress1 <- stress2 + 10 * epsilon # for stress, decreases thisstep <- (omax - omin) / (bfstep * 2) k <- 0 while(k < maxit && abs(stress1 - stress2) > epsilon) { # go finer and finer into the ordination space newmin <- as.vector(conf) - thisstep newmax <- as.vector(conf) + thisstep newgrid <- setgrid(newmin, newmax, bfstep) colnames(newgrid) <- colnames(origconf) # find stress for newgrid pointstress <- apply(newgrid, 1, function(x) { pointconf <- rbind(origconf, x) sstress(pointdist, pointconf) }) conf <- newgrid[which.min(pointstress), ] stress1 <- stress2 stress2 <- min(pointstress) thisstep <- (newmax - newmin) / (bfstep * 2) k <- k + 1 } fullfitconf[thispoint, ] <- conf stress.fullfit[thispoint] <- stress2 } } list(conf=fullfitconf, stress=stress.fullfit, isTrain=isTrain) } ecodist/R/plot.vf.R0000644000175100001440000000075713034761246013655 0ustar hornikusersplot.vf <- function (x, pval = 1, cex = 0.8, ascale = 0.9, ...) { plotlim <- par()$usr plotlim <- min((plotlim[2] - plotlim[1]), (plotlim[4] - plotlim[3])) ascale <- ascale * (plotlim/2) x <- x[x[, 4] < pval, , drop=FALSE] for (i in 1:dim(x)[[1]]) { arrows(0, 0, x[i, 1] * x[i, 3] * ascale, x[i, 2] * x[i, 3] * ascale, ...) } text(x[, 1] * x[, 3] * (ascale * 1.1), x[, 2] * x[, 3] * (ascale * 1.1), dimnames(x)[[1]], cex = cex, ...) } ecodist/R/plot.nmds.R0000644000175100001440000000310313127534032014161 0ustar hornikusersplot.nmds <- function(x, plot=TRUE, xlab="Dimensions", ...) { # dlu, modified by scg 2017-05 # plot NMDS scores by dimension dims <- seq(x$mindim, x$maxdim, by=1) # summarize and plot the nmds object x: stress x.stress <- data.frame(matrix(x$stress, nrow=length(dims), byrow=TRUE)) colnames(x.stress) <- paste0("iter", sprintf("%02d", seq_len(x$nits))) x.stress$ndim <- dims x.stress$min <- apply(x.stress[, seq_len(x$nits)], 1, min, na.rm=TRUE) x.stress$mean <- apply(x.stress[, seq_len(x$nits)], 1, mean, na.rm=TRUE) x.stress$max <- apply(x.stress[, seq_len(x$nits)], 1, max, na.rm=TRUE) # summarize and plot the nmds object x: r2 x.r2 <- data.frame(matrix(x$r2, nrow=length(dims), byrow=TRUE)) colnames(x.r2) <- paste0("iter", sprintf("%02d", seq_len(x$nits))) x.r2$ndim <- dims x.r2$min <- apply(x.r2[, seq_len(x$nits)], 1, min, na.rm=TRUE) x.r2$mean <- apply(x.r2[, seq_len(x$nits)], 1, mean, na.rm=TRUE) x.r2$max <- apply(x.r2[, seq_len(x$nits)], 1, max, na.rm=TRUE) if(plot) { par(mfrow=c(1,2)) plot(dims, x.stress$mean, ylim=c(0, max(x.stress$max)), type="b", pch=19, lwd=2, xlab=xlab, ylab="Stress", xaxt="n", ...) axis(1, at=dims, labels=sprintf("%d", dims)) lines(dims, x.stress$min, type="l", lty=2) lines(dims, x.stress$max, type="l", lty=2) plot(dims, x.r2$mean, ylim=c(0, 1), type="b", pch=19, lwd=2, xlab=xlab, ylab=expression(r^2), xaxt="n", ...) axis(1, at=dims, labels=sprintf("%d", dims)) lines(dims, x.r2$min, type="l", lty=2) lines(dims, x.r2$max, type="l", lty=2) } invisible(list(stress=x.stress, r2=x.r2)) } ecodist/R/pco.R0000644000175100001440000000261313034761246013037 0ustar hornikuserspco <- function(x, negvals = "zero", dround=0) { # Principal coordinates analysis (classical scaling) # Sarah Goslee # x is a lower-triangular dissimilarity matrix. # negvals: if "zero" then negative eigenvalues are set to zero. # if "rm" then correction method 1 from Legendre & Anderson 1999 # dround is an attempt to correct for round-off error. n <- (1 + sqrt(1 + 8 * length(x)))/2 if(abs(n - round(n)) > 0.0000001) stop("Matrix not square.\n") n <- round(n) x <- full(x) dmat <- -0.5 * x * x # Double-center the dissimilarity matrix # Subtract row and column means and add the grand mean. dr <- matrix(apply(dmat, 1, mean), nrow=n, ncol=n) dmat <- dmat - (dr + t(dr)) + mean(dmat) deigen <- eigen(dmat) if(negvals == "rm") { c1 <- min(deigen$values) if(c1 < 0) { c1 <- abs(c1) x2 <- sqrt(x^2 + 2 * c1) diag(x2) <- 0 dmat <- -0.5 * x2 * x2 dr <- matrix(apply(dmat, 1, mean), nrow=n, ncol=n) dmat <- dmat - (dr + t(dr)) + mean(dmat) deigen <- eigen(dmat) } } else { deigen$values[deigen$values < 0] <- 0 } if(dround > 0) { deigen$values <- round(deigen$values, dround) deigen$vectors <- round(deigen$vectors, dround) } eigenscale <- deigen$values eigenscale[eigenscale > 0.000000001] <- sqrt(eigenscale[eigenscale > 0.000000001]) eigenscale[eigenscale <= 0.000000001] <- 1 deigen$vectors <- sweep(deigen$vectors, 2, eigenscale, "/") deigen } ecodist/R/nmds.R0000644000175100001440000000700613034761244013216 0ustar hornikusers# Non-metric multidimensional scaling function # using the majorization algorithm from # Borg & Groenen 1997, Modern Multidimensional Scaling. # # Sarah Goslee # 20 December 1999 # # dmat is a lower-triangular distance matrix. # mindim is the minimum number of dimensions to calculate. # maxdim is the maximum number of dimensions to calculate. # nits is the number of repetitions. # iconf is the initial configuration to use. # If iconf is not specified, then a random configuration is used. # epsilon and maxit specify stopping points. # Returns a list of configurations (conf) # and a vector of final stress values (stress), # along with the cumulative and incremental r^2 for each axis. # The first nits elements are for the lowest number of dimensions. # mindim, maxdim, nits are saved as part of the returned list # # stresscalc has been updated 2016-12-27 to be compatible with vegan::metaMDS # and MASS::isoMDS. # The method of finding the optimum is unchanged. sstress <- function(dmat, newconf) { # Calculates the stress-1 function for the original and # new NMDS configurations (Kruskal 1964). # Calculate stress based on isotonic regression # of distance matrices # uses stats::isoreg instead of MASS::Shepard dmat <- as.vector(dmat) dord <- order(dmat) cmat <- as.vector(dist(newconf, "minkowski", 2)) dmat <- dmat[dord] cmat <- cmat[dord] ir <- isoreg(dmat, cmat) dmat <- ir$y cmat <- ir$yf sstresscalc <- (dmat - cmat) ^ 2 sstresscalc <- sum(sstresscalc) / sum(dmat ^ 2) sqrt(sstresscalc) } nmdscalc <- function(dmat, ndim, iconf, epsilon, maxit, trace) { # This is the optimization routine for NMDS ordination. # Use front-end nmds. # not exported n <- (1 + sqrt(1 + 8 * length(dmat))) / 2 if(missing(iconf)) { iconf <- matrix(runif(n * ndim), nrow = n, ncol = ndim) } k <- 0 conf <- iconf stress2 <- sstress(dmat, iconf) stress1 <- stress2 + 1 + epsilon while(k < maxit && abs(stress1 - stress2) > epsilon) { stress1 <- stress2 dmat.full <- full(dmat) confd.full <- full(dist(conf)) confd2.full <- confd.full confd2.full[confd.full == 0] <- 1 b <- dmat.full / confd2.full b[confd.full == 0] <- 0 bsum <- apply(b, 2, sum) b <- -1 * b diag(b) <- bsum conf <- (1 / n) * b %*% conf stress2 <- sstress(dmat, conf) if(trace) cat(k, ",\t", stress1, "\n") k <- k + 1 } list(conf = conf, stress = stress1) } nmds <- function(dmat, mindim = 1, maxdim = 2, nits = 10, iconf, epsilon = 1e-12, maxit = 500, trace=FALSE) { conf <- list(1:((maxdim - mindim + 1) * nits)) stress <- list(1:((maxdim - mindim + 1) * nits)) r2 <- list(1:((maxdim - mindim + 1) * nits)) k <- 1 for(i in mindim:maxdim) { if(trace) cat("Number of dimensions: ", i, "\n") for(j in seq_len(nits)) { if(trace) cat("Iteration number: ", j, "\n") if(!missing(iconf) && ncol(iconf) == i) { nmdsr <- nmdscalc(dmat, ndim = i, iconf=iconf, epsilon=epsilon, maxit=maxit, trace=trace) } else { nmdsr <- nmdscalc(dmat, ndim = i, epsilon=epsilon, maxit=maxit, trace=trace) } conf[[k]] <- nmdsr$conf stress[[k]] <- nmdsr$stress r2[[k]] <- cor(dmat, dist(nmdsr$conf)) ^ 2 k <- k + 1 } } results <- list(conf = conf, stress = unlist(stress), r2 = unlist(r2), mindim=mindim, maxdim=maxdim, nits=nits) class(results) <- "nmds" results } ecodist/R/cor2m.R0000644000175100001440000000077413127747042013307 0ustar hornikusers# Correlate variables from 1 matrix with variables from another # matrix. If TRIM, set rho 0.0000001) stop("Matrix not square.") n <- round(n) full <- matrix(0, n, n) full[lower.tri(full)] <- v full2 <- t(full) diag(full2) <- 0 full + full2 } ecodist/R/mantel.R0000644000175100001440000002036213127502401013524 0ustar hornikusersmantel <- function(formula = formula(data), data = sys.parent(), nperm = 1000, mrank = FALSE, nboot = 500, pboot = 0.9, cboot = 0.95) { # Mantel test # Written by Sarah C. Goslee # 27 June 2000 # Updated 5 April 2001 # # formula is y ~ x + n1 + n2 + n3 + ... # NOT y ~ x | n1 + n2 + n3 + ... # The | means something else in S-Plus formulas. # # Uses C for permutation and bootstrap routines. # # This version calculates partial coefficients by permuting the y matrix. # # Will calculate the simple correlation or n-th order partial correlation # between two distance matrices in either of two ways: Pearson (mrank=FALSE) # or Spearman (mrank=TRUE) # # A permutation test is used to calculate the significance of r. # The permutation test was designed to be relatively fast, but because of the # way this was done, there is a possibility of repeating permutations of # 1/n! where the distance matrix is n by n. In particular, for small matrices # n < 8 or so, it may be better to enumerate the permutations. # # # As an added bonus, this function offers the option of calculating # bootstrapped confidence limits for the correlation coefficient. # nboot is the number of iterations. # pboot is the level to resample at. # cboot is the desired confidence limit. # NOTE: This is not bootstrapping with replacement. That doesn't make # much sense for dissimilarities because of the possibility of duplicates. # The dissimilarity between a sample and itself is always zero. # # mantel returns a five-element list: # mantelr is the correlation. # pval1 is the one-sided p-value (null hypothesis r <= 0) (0 if nperm == 0). # pval2 is the one-sided p-value (null hypothesis r >= 0) (0 if nperm == 0). # pval3 is the two-sided p-value (null hypothesis r = 0) (0 if nperm == 0). # llim is the lower confidence limit. # ulim is the upper confidence limit. # # requires mantel.c (Included in ecodist.c.) # # Stuff R needs to be able to use a formula m <- match.call(expand.dots = FALSE) m2 <- match(c("formula", "data"), names(m), nomatch=0) m <- m[c(1, m2)] m[[1]] <- as.name("model.frame") m <- eval(m, parent.frame()) m <- as.matrix(m) # End of R stuff. m is now the data for the Mantel test as # columns y, x, n1, n2, n3, ... # Determine the size of the matrices & do some error checking. n <- (1 + sqrt(1 + 8 * nrow(m)))/2 if(abs(n - round(n)) > 0.0000001) stop("Matrix not square.\n") n <- round(n) if(ncol(m) < 2) stop("Not enough data. \n") # If there are only x and y, then use the data as is. if(dim(m)[[2]] == 2) { ymat <- as.vector(m[, 1]) xmat <- as.vector(m[, 2]) if(mrank) { ymat <- rank(ymat) xmat <- rank(xmat) } ycor <- ymat xcor <- xmat } else { ymat <- as.vector(m[, 1]) omat <- m[, -1] if(mrank) { ymat <- rank(ymat) omat <- apply(omat, 2, rank) } omat <- cbind(rep(1, length(ymat)), omat) xmat <- as.vector(omat[, 2]) omat <- omat[, -2] omat <- as.matrix(omat) ycor <- lm.fit(omat, ymat)$residuals xcor <- lm.fit(omat, xmat)$residuals } mantelr <- cor(xcor, ycor) # Convert matrices to column order for compatibility with C routines. xmat <- full(xmat) ymat <- full(ymat) xmat <- xmat[col(xmat) > row(xmat)] ymat <- ymat[col(ymat) > row(ymat)] if(dim(m)[[2]] > 2) { for(i in 2:dim(omat)[[2]]) { curcoll <- omat[, i] curcoll <- full(curcoll) curcoll <- curcoll[col(curcoll) > row(curcoll)] omat[, i] <- curcoll } } # If using a permutation test, start here: if(nperm > 0) { # Set up the arrays needed. zstats <- numeric(nperm) tmat <- matrix(0, n, n) rarray <- rep(0, n) if(dim(m)[[2]] == 2) { # Standardize the columns of the matrices so # that z = r and we can do 2-tailed tests. ncor <- length(xmat) w1 <- sum(xmat)/ncor w2 <- sum(xmat^2) w2 <- sqrt(w2/ncor - w1^2) xmat <- (xmat - w1)/w2 w1 <- sum(ymat)/ncor w2 <- sum(ymat^2) w2 <- sqrt(w2/ncor - w1^2) ymat <- (ymat - w1)/w2 cresults <- .C("permute", as.double(xmat), as.double(ymat), as.integer(n), as.integer(length(xmat)), as.integer(nperm), zstats = as.double(zstats), as.double(as.vector(tmat)), as.integer(rarray), PACKAGE = "ecodist") } else { tomat <- t(omat) hmat <- solve(tomat %*% omat) hmat <- hmat %*% tomat bmat <- rep(0, ncol(omat)) xcor <- as.vector(lm.fit(omat, xmat)$residuals) ycor <- as.vector(lm.fit(omat, ymat)$residuals) # Standardize the columns of the matrices so # that z = r and we can do 2-tailed tests. ncor <- length(xcor) w1 <- sum(xcor)/ncor w2 <- sum(xcor^2) w2 <- sqrt(w2/ncor - w1^2) xcor <- (xcor - w1)/w2 w1 <- sum(ycor)/ncor w2 <- sum(ycor^2) w2 <- sqrt(w2/ncor - w1^2) ycor <- (ycor - w1)/w2 cresults <- .C("permpart", as.double(as.vector(hmat)), bmat = as.double(bmat), as.double(as.vector(omat)), as.double(ymat), as.double(xcor), ycor = as.double(ycor), as.integer(n), as.integer(length(bmat)), as.integer(length(xmat)), as.integer(nperm), zstats = as.double(zstats), as.double(as.vector(tmat)), as.integer(rarray), PACKAGE = "ecodist") } zstats <- cresults$zstats # Calculate the p-values. pval1 <- length(zstats[zstats >= zstats[1]])/nperm pval2 <- length(zstats[zstats <= zstats[1]])/nperm pval3 <- length(zstats[abs(zstats) >= abs(zstats[1])])/nperm } else { pval1 <- 0 pval2 <- 0 pval3 <- 0 } # If not using a permutation test, return 0 for the p-values. if(nboot > 0) { if(dim(m)[[2]] == 2) { ycor <- ymat xcor <- xmat } else { xcor <- as.vector(lm.fit(omat, xmat)$residuals) ycor <- as.vector(lm.fit(omat, ymat)$residuals) } bootcor <- numeric(nboot) rarray <- numeric(n) rmat <- numeric(length(xcor)) xdif <- numeric(length(xcor)) ydif <- numeric(length(xcor)) cresults <- .C("bootstrap", as.double(xcor), as.double(ycor), as.integer(n), as.integer(length(xcor)), as.integer(nboot), as.double(pboot), bootcor = as.double(bootcor), as.integer(rarray), as.integer(rmat), as.double(xdif), as.double(ydif), PACKAGE = "ecodist") bootcor <- cresults$bootcor bootcor <- sort(bootcor) pval <- (1 - cboot)/2 llim <- quantile(bootcor, pval) ulim <- quantile(bootcor, 1 - pval) } else { llim <- 0 ulim <- 0 } c(mantelr = mantelr, pval1 = pval1, pval2 = pval2, pval3 = pval3, llim = llim, ulim = ulim) } ecodist/R/corgen.R0000644000175100001440000000540013034761244013526 0ustar hornikuserscorgen <- function (len, x, r, population = FALSE, epsilon = 0) { # remember the sign of the correlation for later rsign <- sign(r) if (rsign == 0) rsign <- 1 r <- abs(r) # need to either specify x-data or the desired vector length if (missing(x)) { if (missing(len)) { stop("Must specify x or len.\n") } else { # if x wasn't given, sample it from a normal distribution x.rand <- TRUE x <- scale(rnorm(len)) x.orig <- x } } else { # can either draw from a population or simulate an exact # correlation (within epsilon), but not both if (population == TRUE) { # if x is given, population is set to FALSE warning("If x is specified population is ignored.\n") population <- FALSE } x.rand <- FALSE len <- length(x) x.orig <- x x <- scale(x) } if (epsilon != 0) { if (population == TRUE) { warning("If epsilon is specified population is ignored.\n") population <- FALSE } } ## Here's where the real work starts # First, draw y from a normal distribution y <- scale(rnorm(len)) if (!population & x.rand) { # if exact correlations are desired, use princomp to # create uncorrelated data # UNLESS x is given - princomp would trash the # specified x values xy <- princomp(cbind(x, y))$scores x <- xy[, 1] x.orig <- x y <- xy[, 2] } # create a new y based on x and the desired correlation a <- r/sqrt(1 - r^2) y <- x * a + y if (epsilon > 0) { itcounter <- 0 # check to see if cor(x, y) meets the given tolerances # this is kludgy, but works while (abs(cor(x, y) - r) > epsilon) { # sometimes takes too long or doesn't converge # with given starting point if(itcounter > 1000) { if(x.rand) { x <- scale(rnorm(len)) x.orig <- x itcounter <- 0 } else { # hopefully never get here stop("Doesn't converge.\n") } } itcounter <- itcounter + 1 # if not within epsilon, generate a new y y <- scale(rnorm(len)) if (!population & x.rand) { xy <- princomp(cbind(x, y))$scores x <- xy[, 1] x.orig <- x y <- xy[, 2] } a <- r/sqrt(1 - r^2) y <- x * a + y } } # return x and y with the correct sign of r restored list(x = x.orig, y = y * rsign) } ecodist/R/distance.R0000644000175100001440000002005213127745552014052 0ustar hornikusersdistance <- function(x, method="euclidean", sprange=NULL, spweight=NULL, icov) { # calculates similarity and dissimilarity coefficients # as described in Legendre and Legendre 1998 # returns lower-triangle ### # Sarah Goslee # 2 March 2006 # revised 31 March 2008 # bug-fix 15 December 2008 ### # uses clever matrix math to calculate the pieces needed # by dissimilarity matrices, to make it easy to add new # indices. ### # to add a new metric: # add it to the commented list below # add it to the end of the METHODS <- c(...) list # add the code at the appropriate point at the bottom of # the function ### # Gower offers the option of dividing by the species range # if sprange=NULL no range is used # Euclidean, Manhattan, Gower allow weighting options # if spweight=NULL no weighting is used # if spweight="absence" then W is = 0 if both species are absent, # and 1 otherwise, thus deleting joint absences ### Available methods # 1: euclidean # 2: bray-curtis # 3: manhattan # 4: mahalanobis # 5: jaccard # 6: simple difference # 7: sorensen # 8: Gower # 9: Modified Gower base 10 (Anderson et al 2006) # 10: Modified Gower base 2 (Anderson et al 2006) ### Mahalanobis distance requires covariance matrix of full dataset, # making it impossible to calculate in chunks for a very large dataset. # Now can specify covariance matrix separately, to enable this. # argument icov. If missing, will be calculated from data as in previous version. pairedsum <- function(x) { ### paired sums ### returns an N by N by P matrix containing each ### combination of N <- nrow(x) P <- ncol(x) A <- numeric(N * N * P) A <- .C("psum", as.double(as.vector(t(x))), as.integer(N), as.integer(P), A = as.double(A), PACKAGE = "ecodist")$A A <- array(A, dim=c(N, N, P)) A } paireddiff <- function(x) { ### paired differences N <- nrow(x) P <- ncol(x) A <- numeric(N * N * P) A <- .C("pdiff", as.double(as.vector(t(x))), as.integer(N), as.integer(P), A = as.double(A), PACKAGE = "ecodist")$A A <- array(A, dim=c(N, N, P)) A } jointpresence <- function(x) { ### joint count of presences N <- nrow(x) P <- ncol(x) A <- numeric(N * N * P) A <- .C("jpres", as.double(as.vector(t(x))), as.integer(N), as.integer(P), A = as.double(A), PACKAGE = "ecodist")$A A <- array(A, dim=c(N, N, P)) A } jointabsence <- function(x) { ### joint count of absences N <- nrow(x) P <- ncol(x) A <- numeric(N * N * P) A <- .C("jabs", as.double(as.vector(t(x))), as.integer(N), as.integer(P), A = as.double(A), PACKAGE = "ecodist")$A A <- array(A, dim=c(N, N, P)) A } firstonly <- function(x) { ### present only in first sample N <- nrow(x) P <- ncol(x) A <- numeric(N * N * P) A <- .C("jfirst", as.double(as.vector(t(x))), as.integer(N), as.integer(P), A = as.double(A), PACKAGE = "ecodist")$A A <- array(A, dim=c(N, N, P)) A } secondonly <- function(x) { ### present only in second sample N <- nrow(x) P <- ncol(x) A <- numeric(N * N * P) A <- .C("jsec", as.double(as.vector(t(x))), as.integer(N), as.integer(P), A = as.double(A), PACKAGE = "ecodist")$A A <- array(A, dim=c(N, N, P)) A } x <- as.matrix(x) ## code borrowed from dist() METHODS <- c("euclidean", "bray-curtis", "manhattan", "mahalanobis", "jaccard", "difference", "sorensen", "gower", "modgower10", "modgower2") method <- pmatch(method, METHODS) if (is.na(method)) stop("invalid distance method") if (method == -1) stop("ambiguous distance method") N <- nrow(x) P <- ncol(x) if(method == 1) { # Euclidean distance A <- paireddiff(x) if(is.null(spweight)) { D <- sqrt(apply(A, 1:2, function(x)sum(x * x))) } else if(spweight[1] == "absence") { W <- ifelse(jointabsence(x)==1, 0, 1) D <- sqrt(apply((W^2)*A, 1:2, function(x)sum(x * x))) / apply(W, 1:2, sum) } else if(length(spweight) == ncol(x)) { W <- array(rep(spweight, each=nrow(x)^2), dim=c(nrow(x), nrow(x), ncol(x))) D <- sqrt(apply((W^2)*A, 1:2, function(x)sum(x * x))) / apply(W, 1:2, sum) } else { stop("Unknown weighting method.\n") } } if(method == 2) { # Bray-Curtis distance A <- paireddiff(x) A <- apply(A, 1:2, function(x)sum(abs(x))) B <- pairedsum(x) B <- apply(B, 1:2, sum) D <- A / B } if(method == 3) { # unstandardized manhattan distance A <- paireddiff(x) if(is.null(spweight)) { D <- apply(A, 1:2, function(x)sum(abs(x))) } else if(spweight[1] == "absence") { W <- ifelse(jointabsence(x)==1, 0, 1) D <- apply(W*A, 1:2, function(x)sum(abs(x))) / apply(W, 1:2, sum) } else if(length(spweight) == ncol(x)) { W <- array(rep(spweight, each=nrow(x)^2), dim=c(nrow(x), nrow(x), ncol(x))) D <- apply(W*A, 1:2, function(x)sum(abs(x))) / apply(W, 1:2, sum) } else { stop("Unknown weighting method.\n") } } if(method == 4) { # pairwise Mahalanobis distance # same as mahal() if(missing(icov)) { icov <- cov(x) } icov <- solve(icov) A <- paireddiff(x) A1 <- apply(A, 1, function(z)(z %*% icov %*% t(z))) D <- A1[seq(1, N*N, by=(N+1)), ] } if(method == 5) { # Jaccard distance A <- jointpresence(x) A <- apply(A, 1:2, sum) B <- firstonly(x) B <- apply(B, 1:2, sum) C <- secondonly(x) C <- apply(C, 1:2, sum) D <- 1 - A / (A + B + C) } if(method == 6) { # simple difference, NOT symmetric D <- paireddiff(x)[,,1, drop=TRUE] } if(method == 7) { # Sorensen distance A <- jointpresence(x) A <- apply(A, 1:2, sum) B <- firstonly(x) B <- apply(B, 1:2, sum) C <- secondonly(x) C <- apply(C, 1:2, sum) D <- 1 - (2*A) / (2*A + B + C) } if(method == 8) { # Gower distance # weighting A <- paireddiff(x) if(!is.null(sprange)) { if(length(sprange) == ncol(x)) { sprange <- array(rep(sprange, each=nrow(x)^2), dim=c(nrow(x), nrow(x), ncol(x))) A <- A / sprange } else { stop("sprange not recognized.\n") } } if(is.null(spweight)) { D <- apply(A, 1:2, function(x)sum(abs(x))) } else if(spweight[1] == "absence") { W <- ifelse(jointabsence(x)==1, 0, 1) D <- apply(A*W, 1:2, function(x)sum(abs(x))) / apply(W, 1:2, sum) } else if(length(spweight) == ncol(x)) { W <- array(rep(spweight, each=nrow(x)^2), dim=c(nrow(x), nrow(x), ncol(x))) D <- apply(W*A, 1:2, function(x)sum(abs(x))) / apply(W, 1:2, sum) } else { stop("Unknown weighting method.\n") } } if(method == 9) { # modified Gower, base 10 x <- ifelse(x == 0, 0, log10(x)) A <- paireddiff(x) if(is.null(spweight)) { D <- apply(A, 1:2, function(x)sum(abs(x))) } else if(spweight[1] == "absence") { W <- ifelse(jointabsence(x)==1, 0, 1) D <- apply(W*A, 1:2, function(x)sum(abs(x))) / apply(W, 1:2, sum) } else if(length(spweight) == ncol(x)) { W <- array(rep(spweight, each=nrow(x)^2), dim=c(nrow(x), nrow(x), ncol(x))) D <- apply(W*A, 1:2, function(x)sum(abs(x))) / apply(W, 1:2, sum) } else { stop("Unknown weighting method.\n") } } if(method == 10) { # modified Gower, base 2 x <- ifelse(x == 0, 0, log2(x)) A <- paireddiff(x) if(is.null(spweight)) { D <- apply(A, 1:2, function(x)sum(abs(x))) } else if(spweight[1] == "absence") { W <- ifelse(jointabsence(x)==1, 0, 1) D <- apply(W*A, 1:2, function(x)sum(abs(x))) / apply(W, 1:2, sum) } else if(length(spweight) == ncol(x)) { W <- array(rep(spweight, each=nrow(x)^2), dim=c(nrow(x), nrow(x), ncol(x))) D <- apply(W*A, 1:2, function(x)sum(abs(x))) / apply(W, 1:2, sum) } else { stop("Unknown weighting method.\n") } } ## Make the results lower triangular D <- D[col(D) < row(D)] ## give the results attributes similar to dist() attr(D, "Size") <- N attr(D, "Labels") <- rownames(x) attr(D, "Diag") <- FALSE attr(D, "Upper") <- FALSE attr(D, "method") <- METHODS[method] class(D) <- "dist" D } ecodist/vignettes/0000755000175100001440000000000013131506235013731 5ustar hornikusersecodist/vignettes/dissimilarity.Rmd0000644000175100001440000000621613131456337017277 0ustar hornikusers--- title: "Dissimilarity Cheat Sheet" author: "Sarah Goslee" date: "2017-07-12" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Dissimilarity Cheat Sheet} %\VignetteEngine{knitr::rmarkdown} --- **Things to do with dissimilarity matrices** _(ecodist functions are marked in **bold**)_ _(untested ideas marked with ?)_ Description | Notation | Name | R function ------------|----------|------|----------- Relationship between two matrices | D1 ~ D2 | Mantel test | **mantel**(D1 ~ D2) Relationship between two matrices given more | D1 ~ D2 | D3 ... Dn | Partial Mantel test | **mantel**(D1 ~ D2 + D3 + ...) ||| Spatial structure in one matrix | D1 x S | Mantel correlogram | **mgram**(D1, S) Spatial structure in one matrix given more | D1 | D2 ... Dn x S | Partial Mantel correlogram | **?mgram**(residuals(lm(D1 ~ D2 + ...)), space) Spatial structuce in one matrix | D1 x S | Multivariate correlogram | **pmgram**(D1, S) Spatial structure in one matrix given more | D1 | D2 ... Dn x S | Partial multivariate correlogram | **pmgram**(D1, S, D2) ||| Spatial structure in the relationship between two matrices | D1 ~ D2 x S | Mantel cross-correlogram | **pmgram**(cbind(lower(D1), lower(D2)), S) Spatial structure in the relationship between two matrices given more | D1 ~ D2 | D3 ... Dn x S | Partial Mantel cross-correlogram | **pmgram**(cbind(lower(D1), lower(D2)), S, D3) ||| Ordination of one matrix | | (N)MDS | **nmds**(y) or **pco**(y) Ordination of one matrix given more | | (Partial (N)MDS | **?nmds**(residuals(lm(y ~ z1 + ...))) ||| Grouping of items based on one matrix | | Cluster analysis | hclust(y) Grouping of items based on one matrix given more | | Partial cluster analysis | ?hclust(residuals(lm(y ~ z1 + ...))) Grouping of items given space | | Spatially-constrained cluster analysis | NA ||| Multiple regression | D1 ~ D2 | D3 ... Dn | Multiple regression on distance matrices | **MRM**(D1 ~ D2 + D3 + ...) **Ways to calculate dissimilarity matrices** Description | Result | R function ------------|--------|----------- From a site by sample matrix | Symmetric matrix with zero diagonals | dist(x) or **bcdist**(x) or **distance**(x) ----------------------------- **Things to do with cross-dissimilarity matrices** Description | Notation | Name | R function ------------|----------|------|----------- Relationship between two cross-dissimilarity matrices | D12 ~ D34 | Cross-Mantel test | **xmantel**(D12 ~ D34) Relationship between two cross-dissimilarity matrices given more | D12 ~ D34 | D56 ... Dn | Partial cross-Mantel test | **xmantel**(D12 ~ D34 + D56 + ...) ||| Spatial structure in one cross-dissimilarity matrix | D12 x S | Cross-Mantel correlogram | **xmgram**(D12, spaceX) Spatial structure in one cross-dissimilarity matrix given more | D12 | D34 ... Dn x S | Partial cross-Mantel correlogram | **?xmgram**(residuals(lm(D12 ~ D34 + ...)), spaceX) **Ways to calculate cross-dissimilarity matrices** Source | Result | R function -------|--------|----------- From 2 site by sample matrixes for the same sites and samples (e.g. different years) | nonsymmetric matrix with nonzero diagonals | **xdistance**(x, y) ecodist/MD50000644000175100001440000001034513131602130012223 0ustar hornikusersfad676e0ff9f24c1963ddfe4db7be457 *DESCRIPTION 92b7eabdaca7f4c268f89e0853207523 *NAMESPACE d15c8581b72d843e06f2cb687c599502 *R/MRM.R 46ede2c4d3401991a8ebb65990c90e87 *R/addord.R ae69c46352ed5e4ce2b3adbb6b3149ca *R/bcdist.R a3a0cc6bfb7ecc377d4cba84892ce45a *R/cor2m.R a6ac5872408b8e3203c99014a5a99f1f *R/corgen.R f6b193f93eb488caa65b3cc7ffeaaced *R/crosstab.R 4d1bc8e91f13cf801135cfe448e902a1 *R/distance.R 835e62b78a342d108b4532582710e698 *R/fixdmat.R a16a1c88648c2b858b3accc16c6a6cc0 *R/full.R 70f5dc838721bfd2abdfa8569793a78b *R/lower.R 44d3de7bdaaade63be5209f20917c838 *R/mantel.R a420e968cbc1d644c64144a1195d838c *R/mgram.R c64a8b075dc791f39cabf5e6d4af6a84 *R/mgroup.R 3a1c387586fdd79a8776b410c9a8fead *R/min.nmds.R 4153165ca4e9440df838a8b1a3e1988d *R/nmds.R 6b0ad2411dd62150634433984ccf84b7 *R/nmds.min.R c6e5800257e552c9b04350a9f522b9d6 *R/pco.R 2429b18210e6eb4b65fae1af7c329e27 *R/plot.mgram.R bd8887f1c5246a9a47e8766290216b93 *R/plot.nmds.R f73448c19e487680d9eda76ba6967f78 *R/plot.vf.R 9b0ecabb0aa112b1b615ccf817b8f019 *R/pmgram.R 3edb216d47fc3f2394209d4ef7f40955 *R/residuals.mgram.R 42b2064bcfaf9a58e8ebcd02fc4d3d9e *R/vf.R daaf413c5b34a8784f64e23526c52809 *R/xdistance.R deddb65651d99c96a582aa78f839752d *R/xmantel.R 87b3be79ba98bf8c1de0fdff7846e4eb *R/xmgram.R adcae7e43de1738f2320fa1564b41707 *README b323db4ec0917ac9f244c2a862fa125f *build/partial.rdb 4250ebde9c2095d6e89c15fbfdd58860 *build/vignette.rds 13c854d8d590fa79dc316628ab0b272a *data/bump.pmgram.rda 30d5b5d4e55edba01b24da1e0b460cba *data/bump.rda 6d3e215e51dab584c898839558991136 *data/graze.rda c6f3963d78b714e7184a7ea09ddf9814 *data/iris.fit.rda 487aff36b22f742501bd18d3054dfd18 *data/iris.nmds.rda cd86940eef6a822ecfd87569cb3ec77d *data/iris.vf.rda c8c954eb6921bedc8f9c24e833c08526 *data/iris.vfrot.rda b204771dff335c364aabb3a6e8f54be6 *data/z.no.rda 77a8d71949fae669d76c6a4ef95e66f5 *data/z.z1.rda f47f634fbe21cca4076998086898f770 *inst/CITATION 205271f3d799059e5f3eb4a3a3bbc568 *inst/doc/dissimilarity.Rmd aec4fa31b53f511d80d4d000101babc3 *inst/doc/dissimilarity.html ccb02bf736297228d36372c651ba4cef *man/MRM.Rd 697cee16af18f9cfc0888e1b49464c83 *man/addord.Rd 896281685766f866b18a647ca4686b05 *man/bcdist.Rd b5185d72e634620a362c362844dc8244 *man/bump.Rd ebb224fb20719ab6fab64031b0c12b14 *man/bump.pmgram.Rd e6b9ab94534537576561009f321d806c *man/cor2m.Rd 9b90d64da318102da8efc1de43e84f82 *man/corgen.Rd 400c1c34d4c579ed3e6c203d97a0757a *man/crosstab.Rd 24430cb4d9fc5343ae1a94a7d11a9563 *man/distance.Rd 81a6795b0f5396ef52c22ec614b97fa4 *man/ecodist-package.Rd 599455d49118abd375c58788d9c6291f *man/fixdmat.Rd 754485899ec74a1f60f2531a8be37127 *man/full.Rd caa6d24b2d4bb1e7b1fc83c39ce89a6c *man/graze.Rd 6053fb0e92af994b3dca4c3274cb532c *man/iris.fit.Rd be2e2868917138b9b1b3d44f81967206 *man/iris.nmds.Rd e4b5951132e9c8860cb88a350ff85658 *man/iris.vf.Rd d9db0830bb5b84e9e48b94847cade17d *man/iris.vfrot.Rd 6218940b6fdc911a672e1718488fa724 *man/lower.Rd 13671bb73e27e3785a8782ba9d419782 *man/mantel.Rd 331971ecb3387c814edac6fadfcceedb *man/mgram.Rd 104be3edc3f0ebbfd547c26660ea7df3 *man/mgroup.Rd 53043c4b5b64981c255a5d081b86142c *man/min.nmds.Rd 0362bfc7c7b01c6162b20f20159a9a48 *man/nmds.Rd 492e52c276d6c1a6684e1edffbf0f433 *man/pco.Rd 1a58c3415d985beac82eeb25767a39b9 *man/plot.mgram.Rd 9dfb72ca1556ab4b785b4c721777ae66 *man/plot.nmds.Rd 18b6edaf6860542e8b6a8adb29eff74a *man/plot.vf.Rd ecbbbf074b15ef20353d402044bb7748 *man/pmgram.Rd c197b9e39d0d96512923ffad02742ef3 *man/residuals.mgram.Rd 81ab32606567c225d4288d3bc341ea96 *man/vf.Rd 344d215a027627c44d8a1d2262e383c5 *man/xdistance.Rd 6214ce03553bbaa9950fa53c9750c46d *man/xmantel.Rd 826e19a0598836699d0486a35c185feb *man/xmgram.Rd d2c3e1dbf7218fe03c5224be0febb8d7 *man/z.no.Rd 3cf440ab38db7938ae6d2e130ab95a42 *man/z.z1.Rd 7ad45eea54b4e506438c8dd620473f96 *src/Makevars 925cb98d61564e4b1999b8950330e08a *src/ecodist.c 41278d00a33cc545da4aebc4e8f7ab43 *src/init.c 9ddd5708c58d58e3550696f3119e87ed *tests/testthat.R 80c568577c3aae89c23492c1caeb9b7d *tests/testthat/test-MRM.R abfb26f46bd56ae9975457597f9b0dd6 *tests/testthat/test-crosstab.R 3ea6ed914e3d4cdd9fb9b8dc1a912dbb *tests/testthat/test-distance.R 8bdf878f30f5cac8a974890afca58fc9 *tests/testthat/test-mantel.R 0360a6ade8130399a6be6f6588a1f751 *tests/testthat/test-mgroup.R 205271f3d799059e5f3eb4a3a3bbc568 *vignettes/dissimilarity.Rmd ecodist/README0000644000175100001440000000002413034761210012573 0ustar hornikusersecodist R package ecodist/build/0000755000175100001440000000000013131506235013020 5ustar hornikusersecodist/build/vignette.rds0000644000175100001440000000032213131506235015354 0ustar hornikusersmO0,> 1Q9y /=xm&- 旋[&lg.!BG@Pb !7ךK.MrY8]:QJƌN7F aD3CiHٝU?Ρ,mj5p&y!lͷ4K/w5T$uq^ծѰ&7| ʾecodist/build/partial.rdb0000644000175100001440000000752613131506234015156 0ustar hornikusers\[ݝ5kl0 $Ό7 5vvfG#.{1?Oy3yH)UNh%ƣg9;sFӧOݚSRi4R7T*=ק$3D6q+$ߕ6HTf>+w\iro/%[I6 *#ݏط鷚FথmLddŐc폾~rLn[MNW-zi`7?gLpT$ o\v[vC?]jNbpknƚ])^&gϜ=MΝ>U>QORbM뽉x~aNLP\jT L?9IxPr函6ꡩ)0b(^}}%uUe#ncR8hiUPߌGB>~:d 3 )^E#I (AE/PV'DŔw,^+cO}'+,CWqRrZܲ8j;˒CgȮj4maE65sC%MX4$mQI98]x4Z&Nx ړƃoS'atmSrZ哨'5|OafۥTC<,ӦDw"JK4dGw{/zT%8"HlgFErjVsLcJ Iaι[T#۪t8x]t 2\t^8JHUvcιޢ#ge꽆+t`lM@-TE^ ( "t8$GȨmoJ;xGdi VaCrTTnJwȫ6Ksc,M Nn/ccD,%t?="`bG4~ǹr m[ #{#EqPRl y41}{٥םxӀg? Lemw$[4\Regͻp;[=ܳuٶa(^}a?]\ **:٠c߁cO2d"J $~"xERVj\Q] [eKaNtVZ{cuy-6W%@_t5 ӧ^a[iImi.MBO 9>ZA򩆧[

.a/SGA/+Zv[G;$Z4Fwdjmyēya_wVbǣ:FϰӟU]A~%*/#y!&[ an u嶃$6-Y-u ȟ 4g+𾳣bfK*M{!J_k AT ŠI6}})EY?[{ڪSm Y hZI$dA90U\YiqQ_MQ |Q>fuXy-._D5l͢ LY:̥E8C~.7ГEl~EؠɁgd֎J'?i5s*+҃ȿdA&e z(`ӳX,ZC8-\Q$I?TuOVU}V@@_ȍ<;nF%LR`uHC `ӡylsy%K6jI`WKȿ4ӭrF- 0VG@/9 s3^BRn%JpPgx?Åޡ}O|; yx``E짙Y;WvV'Dn g]ʎ!|EbNJf(^}t,rGhx.Hsk-LG#_\&4]{nBdɘe.s?ޮ[Tb/*Nsan^ ]l-Np8ep4ߠlBis@g-0f%;[BJi9\c/ ū?8_pԏK`2sl8у?5N`GDfĦ9"e}>)GeјnڙMB]6(&uȌaĞ[8|-QNX18HTkzӍ"ѭV@+))WtiYTFDDfBtU?XMΎaZD5HWA(< ѧ7 J.]OSn\ X}lc⦤ylw戡MFj36'.ۇq=pևS7ktSv% 6c_# t}x*3Niz\t\ی Әa<[wibdGx5tYM'dox<#+5tmm(d.arLOZl{߿JS 8#7[uދ$ͩMC!P>@Բ#i[HJRj9AtZ&63Ǝevaf=L+f<4@mMoʑ|&Ĥ&mZLoh" zΣDhv`~ [Nss/ıJ)Ak+5`?:cn?bƂVIM+ W{QM{Mjh; z SlIf2"FrhaJϥie6:REӶhLr&|)Y=ifc,x/S=_~z5%٤VՕZP-֜F5=é>orFBD\>s~dn ,2BarxE}O-\rj5w^lAVM{Sg* >9a4~({oSLϽV Гȟ۱1zPD^h7z rI>Y?ښ з;R̕[n(}̐ t{w{D0a0& ҵ? eƫg@p5uٰ;T辔6t+\#e,-7 &r>be`T?'M)|%UXqbfyM~6^ecodist/DESCRIPTION0000644000175100001440000000143113131602130013415 0ustar hornikusersPackage: ecodist Version: 2.0.1 Date: 2017-07-12 Title: Dissimilarity-Based Functions for Ecological Analysis Authors@R: c(person("Sarah", "Goslee", role = c("aut", "cre"), email = "Sarah.Goslee@ars.usda.gov"), person("Dean", "Urban", role = "aut")) Author: Sarah Goslee [aut, cre], Dean Urban [aut] Maintainer: Sarah Goslee Depends: R (>= 3.0.0) LazyData: true Imports: stats, graphics Suggests: knitr, testthat VignetteBuilder: knitr Description: Dissimilarity-based analysis functions including ordination and Mantel test functions, intended for use with spatial and community data. License: GPL (>= 2) NeedsCompilation: yes Packaged: 2017-07-12 20:54:53 UTC; sarahg Repository: CRAN Date/Publication: 2017-07-13 05:25:44 UTC ecodist/man/0000755000175100001440000000000013131506235012474 5ustar hornikusersecodist/man/mgram.Rd0000644000175100001440000000664213131461103014070 0ustar hornikusers\name{mgram} \alias{mgram} \title{ Mantel correlogram } \description{ Calculates simple Mantel correlograms. } \usage{ mgram(species.d, space.d, breaks, nclass, stepsize, nperm = 1000, mrank = FALSE, nboot = 500, pboot = 0.9, cboot = 0.95, alternative = "two.sided", trace = FALSE) } \arguments{ \item{species.d}{ lower-triangular dissimilarity matrix. } \item{space.d}{ lower-triangular matrix of geographic distances. } \item{breaks}{ locations of class breaks. If specified, overrides nclass and stepsize. } \item{nclass}{ number of distance classes. If not specified, Sturge's rule will be used to determine an appropriate number of classes. } \item{stepsize}{ width of each distance class. If not specified, nclass and the range of space.d will be used to calculate an appropriate default. } \item{nperm}{ number of permutations to use. If set to 0, the permutation test will be omitted. } \item{mrank}{ if this is set to FALSE (the default option), Pearson correlations will be used. If set to TRUE, the Spearman correlation (correlation ranked distances) will be used. } \item{nboot}{ number of iterations to use for the bootstrapped confidence limits. If set to 0, the bootstrapping will be omitted. } \item{pboot}{ the level at which to resample the data for the bootstrapping procedure. } \item{cboot}{ the level of the confidence limits to estimate. } \item{alternative}{ default is "two.sided", and returns p-values for H0: rM = 0. The alternative is "one.sided", which returns p-values for H0: rM <= 0. } \item{trace}{ if TRUE, returns progress indicators. } } \details{ This function calculates Mantel correlograms. The Mantel correlogram is essentially a multivariate autocorrelation function. The Mantel r represents the dissimilarity in variable composition (often species composition) at a particular lag distance. } \value{ Returns an object of class mgram, which is a list with two elements. mgram is a matrix with one row for each distance class and 6 columns: \item{lag }{midpoint of the distance class.} \item{ngroup }{number of distances in that class.} \item{mantelr }{Mantel r value.} \item{pval }{p-value for the test chosen.} \item{llim }{lower bound of confidence limit for mantelr.} \item{ulim }{upper bound of confidence limit for mantelr.} resids is NA for objects calculated by mgram(). } \references{ Legendre, P. and M. Fortin. 1989. Spatial pattern and ecological analysis. Vegetatio 80:107-138. } \author{ Sarah Goslee } \seealso{ \code{\link{mantel}}, \code{\link{plot.mgram}}, \code{\link{pmgram}} } \examples{ # generate a simple surface x <- matrix(1:10, nrow=10, ncol=10, byrow=FALSE) y <- matrix(1:10, nrow=10, ncol=10, byrow=TRUE) z <- x + 3*y image(z) # analyze the pattern of z across space space <- cbind(as.vector(x), as.vector(y)) z <- as.vector(z) space.d <- distance(space, "eucl") z.d <- distance(z, "eucl") z.mgram <- mgram(z.d, space.d, nperm=0) plot(z.mgram) # data(graze) space.d <- dist(graze$sitelocation) forest.d <- dist(graze$forestpct) grasses <- graze[, colnames(graze) \%in\% c("DAGL", "LOAR10", "LOPE", "POPR")] legumes <- graze[, colnames(graze) \%in\% c("LOCO6", "TRPR2", "TRRE3")] grasses.bc <- bcdist(grasses) legumes.bc <- bcdist(legumes) # Does the relationship of composition with distance vary for # grasses and legumes? par(mfrow=c(2, 1)) plot(mgram(grasses.bc, space.d, nclass=8)) plot(mgram(legumes.bc, space.d, nclass=8)) } \keyword{ multivariate } ecodist/man/xmantel.Rd0000644000175100001440000000672713131461231014443 0ustar hornikusers\name{xmantel} \alias{xmantel} \title{ Cross-Mantel test } \description{ Simple and partial cross-Mantel tests, with options for ranked data and permutation tests. } \usage{ xmantel(formula = formula(data), data = sys.parent(), dims = NA, nperm = 1000, mrank = FALSE) } \arguments{ \item{formula}{ formula describing the test to be conducted. For this test, y ~ x will perform a simple Mantel test, while y ~ x + z1 + z2 + z3 will do a partial Mantel test of the relationship between x and y given z1, z2, z3. All variables should be either non-symmetric square cross-dissimilary matrices of class xdist, or vector forms thereof. } \item{data}{ an optional dataframe containing the variables in the model as columns of dissimilarities. By default the variables are taken from the current environment. } \item{dims}{ if the dissimilarity matrices are not square, the dimensions must be provided as \code{c(nrow, ncol)}} \item{nperm}{ number of permutations to use. If set to 0, the permutation test will be omitted. } \item{mrank}{ if this is set to FALSE (the default option), Pearson correlations will be used. If set to TRUE, the Spearman correlation (correlation ranked distances) will be used. } } \details{ If only one independent variable is given, the simple Mantel r (r12) is calculated. If more than one independent variable is given, the partial Mantel r (ryx|x1 ...) is calculated by permuting one of the original dissimilarity matrices. Note that the cross-dissimilarity functions are for research purposes, and are not well-tested. } \value{ \item{mantelr }{Mantel coefficient.} \item{pval1 }{one-tailed p-value (null hypothesis: r <= 0).} \item{pval2 }{one-tailed p-value (null hypothesis: r >= 0).} \item{pval3 }{two-tailed p-value (null hypothesis: r = 0).} } \author{ Sarah Goslee } \seealso{ \code{\link{xdistance}}, \code{\link{xmgram}} } \examples{ data(graze) ### EXAMPLE 1: Square matrices # take two subsets of sites with different dominant grass abundances # use cut-offs that produce equal numbers of sites dom1 <- subset(graze, POPR > 50 & DAGL < 20) # 8 sites dom2 <- subset(graze, POPR < 50 & DAGL > 20) # 8 sites # first two columns are site info dom.xd <- xdistance(dom1[, -c(1,2)], dom2[, -c(1,2)], "bray") # environmental and spatial distances; preserve rownames forest.xd <- xdistance(dom1[, "forestpct", drop=FALSE], dom2[, "forestpct", drop=FALSE]) sitelocation.xd <- xdistance(dom1[, "sitelocation", drop=FALSE], dom2[, "sitelocation", drop=FALSE]) # permutes rows and columns of full nonsymmetric matrix xmantel(dom.xd ~ forest.xd) xmantel(dom.xd ~ forest.xd + sitelocation.xd) plot(xmgram(dom.xd, sitelocation.xd)) ### EXAMPLE 2: Non-square matrices # take two subsets of sites with different dominant grass abundances # this produces a non-square matrix dom1 <- subset(graze, POPR > 45 & DAGL < 20) # 13 sites dom2 <- subset(graze, POPR < 45 & DAGL > 20) # 8 sites # first two columns are site info dom.xd <- xdistance(dom1[, -c(1,2)], dom2[, -c(1,2)], "bray") # environmental and spatial distances; preserve rownames forest.xd <- xdistance(dom1[, "forestpct", drop=FALSE], dom2[, "forestpct", drop=FALSE]) sitelocation.xd <- xdistance(dom1[, "sitelocation", drop=FALSE], dom2[, "sitelocation", drop=FALSE]) # permutes rows and columns of full nonsymmetric matrix xmantel(dom.xd ~ forest.xd, dims=c(13, 8)) xmantel(dom.xd ~ forest.xd + sitelocation.xd, dims=c(13, 8)) plot(xmgram(dom.xd, sitelocation.xd)) } \keyword{ multivariate } ecodist/man/min.nmds.Rd0000644000175100001440000000250513131505337014512 0ustar hornikusers\name{min.nmds} \alias{min.nmds} \alias{nmds.min} \title{ Find minimum stress configuration } \description{ Finds minimum stress configuration from output of nmds() } \usage{ \method{min}{nmds}(\dots, na.rm = FALSE, dims = 2) nmds.min(x, dims = 2) } \arguments{ \item{\dots}{ output from nmds() } \item{x}{ output from nmds() } \item{dims}{ desired dimensionality of result. If dims = 0 then the overall minimum stress configuration is chosen. By default, the best two-dimensional configuration is returned. } \item{na.rm}{Not used; there should be no NA values in a NMDS configuration.} } \value{ Configuration of minimum stress ordination (dataframe of coordinates). The stress and r^2 for the minimum stress configuration are stored as attributes. } \details{ For back-compatibility, the \code{nmds.min} function remains. } \author{ Sarah Goslee } \seealso{ \code{\link{nmds}} } \examples{ data(iris) iris.d <- dist(iris[,1:4]) ### nmds() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.nmds <- nmds(iris.d, nits=20, mindim=1, maxdim=4) ### save(iris.nmds, file="ecodist/data/iris.nmds.rda") data(iris.nmds) # examine fit by number of dimensions plot(iris.nmds) # choose the best two-dimensional solution to work with iris.nmin <- min(iris.nmds, dims=2) } \keyword{ multivariate } ecodist/man/iris.vf.Rd0000644000175100001440000000266613131461054014354 0ustar hornikusers\name{iris.vf} \alias{iris.vf} \docType{data} \title{Example for vector fitting on ordination} \description{ An object of class vf for use in the examples for \code{\link{nmds}} and \code{\link{vf}}. Many of the functions in \code{ecodist} take a long time to run, so prepared examples have been included. } \usage{data(iris.vf)} \format{ See \code{\link{vf}} for current format specification. } \author{ Sarah Goslee } \seealso{ \code{\link{nmds}}, \code{\link{vf}} } \examples{ data(iris) iris.d <- dist(iris[,1:4]) ### nmds() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.nmds <- nmds(iris.d, nits=20, mindim=1, maxdim=4) ### save(iris.nmds, file="ecodist/data/iris.nmds.rda") data(iris.nmds) # examine fit by number of dimensions plot(iris.nmds) # choose the best two-dimensional solution to work with iris.nmin <- min(iris.nmds, dims=2) # rotate the configuration to maximize variance iris.rot <- princomp(iris.nmin)$scores # rotation preserves distance apart in ordination space cor(dist(iris.nmin), dist(iris.rot)) # fit the data to the ordination as vectors ### vf() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.vf <- vf(iris.nmin, iris[,1:4], nperm=1000) ### save(iris.vf, file="ecodist/data/iris.vf.rda") data(iris.vf) plot(iris.nmin, col=as.numeric(iris$Species), pch=as.numeric(iris$Species), main="NMDS") plot(iris.vf) } \keyword{datasets} ecodist/man/crosstab.Rd0000644000175100001440000000525513131505313014606 0ustar hornikusers\name{crosstab} \alias{crosstab} \title{ Data formatting } \description{ Converts field data of the form site, species, observation into a site by species data frame. } \usage{ crosstab(rowlab, collab, values, type = "sum", data, allrows, allcols, na.as.0 = TRUE, check.names = TRUE, \dots) } \arguments{ \item{rowlab}{ row labels, e.g. site names. } \item{collab}{ column labels, e.g. species names. } \item{values}{ data values. } \item{data}{ optional data frame from which to take rowlab, collab and/or values. } \item{type}{ function to use to combine data, one of "sum" (default), "min", "max", "mean", "count". } \item{allrows}{ optional, list of all desired row names that may not appear in rowlab. } \item{allcols}{ optional, list of all desired column names that may not appear in collab. } \item{na.as.0}{ if TRUE, all NA values are replaced with 0. } \item{check.names}{ if FALSE, data frame names are not checked for syntactic validity, so that they match the input categories. Otherwise make.names() is used to adjust them. } \item{\dots}{ optional arguments to the function specified in type, such as na.rm=TRUE} } \details{ Field data are often recorded as a separate row for each site-species combination. This function reformats such data into a data frame for further analysis based on unique row and column labels. The three vectors should all be the same length (including duplicates). The three vectors may also be provided as names of columns in the data frame specified by the data argument. If allrows or allcols exists, rows and/or columns of zeros are inserted for any elements of allrows/allcols not present in rowlab/collab. If values is missing the number of occurrences of combinations of rowlab and collab will be returned. Thus, crosstab(rowlab, collab) is equivalent to table(rowlab, collab). If type is "count", the unique combinations of rowlab, collab and values will be returned. } \value{ data frame with rowlab as row headings, collab as columns, and values as the data. } \author{ Sarah Goslee } \examples{ # Make a random example plotnames <- rep(1:5, each = 6) speciesnames <- rep(c("A", "B", "C"), 10) freqdata <- runif(30) # number of samples of each species and plot crosstab(plotnames, speciesnames) # can use the data argument speciesdata <- data.frame(plots = plotnames, species = speciesnames, freq = freqdata, stringsAsFactors=FALSE) # mean frequency by species and plot crosstab(plots, species, freq, data=speciesdata, type="mean") # can specify additional possible row or column levels crosstab(plots, species, freq, data=speciesdata, type="mean", allcols=LETTERS[1:5]) } \keyword{ manip } \keyword{ multivariate } ecodist/man/fixdmat.Rd0000644000175100001440000000176313131460746014434 0ustar hornikusers\name{fixdmat} \alias{fixdmat} \title{ Distance matrix conversion } \description{ Convert a row-order lower-triangular distance matrix to a full symmetric matrix. } \usage{ fixdmat(v) } \arguments{ \item{v}{ lower-triangular distance matrix in row order. } } \details{ R distance functions such as dist and bcdist return a lower triangular distance matrix in column order. Some other programs return the lower triangular matrix in row order. To use this matrix in R functions, it must be converted from row order to column order. } \value{ full symmetric distance matrix. } \author{ Sarah Goslee } \seealso{ \code{\link{lower}}, \code{\link{full}} } \examples{ x.vec <- seq_len(6) x.vec # Make an R-style column order symmetric matrix full(x.vec) # Extract the lower triangle from a symmetric matrix # in column order lower(full(x.vec)) # Convert to or from a row order symmetric matrix fixdmat(x.vec) lower(fixdmat(x.vec)) fixdmat(c(1, 2, 4, 3, 5, 6)) } \keyword{ manip } \keyword{ multivariate } ecodist/man/xdistance.Rd0000644000175100001440000000605213131461224014746 0ustar hornikusers\name{xdistance} \alias{xdistance} \title{ Cross-distance between two datasets. } \description{ Pairwise dissimilarity calculation between rows of one dataset and rows of another, for instance across different sampling periods for the same set of sites. } \usage{ xdistance(x, y, method = "euclidean") } \arguments{ \item{x}{A site by species or other matrix or data frame.} \item{y}{A a second site by species dataset, which must have at least the same columns.} \item{method}{This function calls \code{\link{distance}} to do the calculations, and will accept any method used there, currently: "euclidean", "bray-curtis", "manhattan", "mahalanobis" (squared Mahalanobis distance), "jaccard", "difference", "sorensen", "gower", "modgower10" (modified Gower, base 10), "modgower2" (modified Gower, base 2). Partial matching will work for selecting a method.} } \details{ This function will calculate rowwise dissimilarities between any pair of matrices or data frames with the same number of columns. Note that the cross-dissimilarity functions are for research purposes, and are not well-tested. } \value{ A non-symmetric and possibly not square matrix of dissimilarities of class \code{xdist}, where \code{result <- xdistance(x, y)} produces a matrix with \code{result[a, b]} containing the dissimilarity between \code{x[a, ]} and \code{y[b, ]}. } \author{ Sarah Goslee } \seealso{ \code{\link{distance}}, \code{\link{xmantel}}, \code{\link{xmgram}}} \examples{ data(graze) ### EXAMPLE 1: Square matrices # take two subsets of sites with different dominant grass abundances # use cut-offs that produce equal numbers of sites dom1 <- subset(graze, POPR > 50 & DAGL < 20) # 8 sites dom2 <- subset(graze, POPR < 50 & DAGL > 20) # 8 sites # first two columns are site info dom.xd <- xdistance(dom1[, -c(1,2)], dom2[, -c(1,2)], "bray") # environmental and spatial distances; preserve rownames forest.xd <- xdistance(dom1[, "forestpct", drop=FALSE], dom2[, "forestpct", drop=FALSE]) sitelocation.xd <- xdistance(dom1[, "sitelocation", drop=FALSE], dom2[, "sitelocation", drop=FALSE]) # permutes rows and columns of full nonsymmetric matrix xmantel(dom.xd ~ forest.xd) xmantel(dom.xd ~ forest.xd + sitelocation.xd) plot(xmgram(dom.xd, sitelocation.xd)) ### EXAMPLE 2: Non-square matrices # take two subsets of sites with different dominant grass abundances # this produces a non-square matrix dom1 <- subset(graze, POPR > 45 & DAGL < 20) # 13 sites dom2 <- subset(graze, POPR < 45 & DAGL > 20) # 8 sites # first two columns are site info dom.xd <- xdistance(dom1[, -c(1,2)], dom2[, -c(1,2)], "bray") # environmental and spatial distances; preserve rownames forest.xd <- xdistance(dom1[, "forestpct", drop=FALSE], dom2[, "forestpct", drop=FALSE]) sitelocation.xd <- xdistance(dom1[, "sitelocation", drop=FALSE], dom2[, "sitelocation", drop=FALSE]) # permutes rows and columns of full nonsymmetric matrix xmantel(dom.xd ~ forest.xd, dims=c(13, 8)) xmantel(dom.xd ~ forest.xd + sitelocation.xd, dims=c(13, 8)) plot(xmgram(dom.xd, sitelocation.xd)) } \keyword{ multivariate } ecodist/man/cor2m.Rd0000644000175100001440000000354613127747032014024 0ustar hornikusers\name{cor2m} \alias{cor2m} \title{ Two-matrix correlation table } \description{ Generate a correlation table between the variables of two data sets, originally for comparing species abundances and environmental variables. } \usage{ cor2m(x, y, trim = TRUE, alpha = 0.05) } \arguments{ \item{x}{ A matrix or data frame of environmental (or other) variables matching the sites of x } \item{y}{ A matrix or data frame of species (or other) variables } \item{trim}{ If trim is TRUE, set rho= 0).} \item{pval3 }{two-tailed p-value (null hypothesis: r = 0).} \item{llim }{lower confidence limit.} \item{ulim }{upper confidence limit.} } \references{ Mantel, N. 1967. The detection of disease clustering and a generalized regression approach. Cancer Research 27:209-220. Smouse, P.E., J.C. Long and R.R. Sokal. 1986. Multiple regression and correlation extensions of the Mantel test of matrix correspondence. Systematic Zoology 35:62 7-632. Goslee, S.C. and Urban, D.L. 2007. The ecodist package for dissimilarity-based analysis of ecological data. Journal of Statistical Software 22(7):1-19. Goslee, S.C. 2010. Correlation analysis of dissimilarity matrices. Plant Ecology 206(2):279-286. } \author{ Sarah Goslee } \seealso{ \code{\link{mgram}}, \code{\link{mgroup}} } \examples{ data(graze) grasses <- graze[, colnames(graze) \%in\% c("DAGL", "LOAR10", "LOPE", "POPR")] legumes <- graze[, colnames(graze) \%in\% c("LOCO6", "TRPR2", "TRRE3")] grasses.bc <- bcdist(grasses) legumes.bc <- bcdist(legumes) space.d <- dist(graze$sitelocation) forest.d <- dist(graze$forestpct) # Mantel test: is the difference in forest cover between sites # related to the difference in grass composition between sites? mantel(grasses.bc ~ forest.d) # Mantel test: is the geographic distance between sites # related to the difference in grass composition between sites? mantel(grasses.bc ~ space.d) # Partial Mantel test: is the difference in forest cover between sites # related to the difference in grass composition once the # linear effects of geographic distance are removed? mantel(grasses.bc ~ forest.d + space.d) # Mantel test: is the difference in forest cover between sites # related to the difference in legume composition between sites? mantel(legumes.bc ~ forest.d) # Mantel test: is the geographic distance between sites # related to the difference in legume composition between sites? mantel(legumes.bc ~ space.d) # Partial Mantel test: is the difference in forest cover between sites # related to the difference in legume composition once the # linear effects of geographic distance are removed? mantel(legumes.bc ~ forest.d + space.d) # Is there nonlinear pattern in the relationship with geographic distance? par(mfrow=c(2, 1)) plot(mgram(grasses.bc, space.d, nclass=8)) plot(mgram(legumes.bc, space.d, nclass=8)) } \keyword{ multivariate } ecodist/man/plot.mgram.Rd0000644000175100001440000000304413131505431015041 0ustar hornikusers\name{plot.mgram} \alias{plot.mgram} \title{ Plot a Mantel correlogram } \description{ Plot a Mantel correlogram from an object of S3 class \code{mgram}, using solid symbols for significant values. } \usage{ \method{plot}{mgram}(x, pval = 0.05, xlab = "Distance", ylab = "Mantel r", \dots) } \arguments{ \item{x}{ an object of class \code{mgram} } \item{pval}{ cut-off level for statistical significance. } \item{xlab}{ x-axis label. } \item{ylab}{ y-axis label. } \item{\dots}{ optional, any additional graphics parameters. } } \value{ draws a plot (graphics device must be active). } \author{ Sarah Goslee } \seealso{ \code{\link{mgram}} } \examples{ # generate a simple surface x <- matrix(1:10, nrow=10, ncol=10, byrow=FALSE) y <- matrix(1:10, nrow=10, ncol=10, byrow=TRUE) z <- x + 3*y image(z) # analyze the pattern of z across space space <- cbind(as.vector(x), as.vector(y)) z <- as.vector(z) space.d <- distance(space, "eucl") z.d <- distance(z, "eucl") z.mgram <- mgram(z.d, space.d, nperm=0) plot(z.mgram) # data(graze) space.d <- dist(graze$sitelocation) forest.d <- dist(graze$forestpct) grasses <- graze[, colnames(graze) \%in\% c("DAGL", "LOAR10", "LOPE", "POPR")] legumes <- graze[, colnames(graze) \%in\% c("LOCO6", "TRPR2", "TRRE3")] grasses.bc <- bcdist(grasses) legumes.bc <- bcdist(legumes) # Does the relationship of composition with distance vary for # grasses and legumes? par(mfrow=c(2, 1)) plot(mgram(grasses.bc, space.d, nclass=8)) plot(mgram(legumes.bc, space.d, nclass=8)) } \keyword{ multivariate } \keyword{ hplot } ecodist/man/corgen.Rd0000644000175100001440000000454013131505367014250 0ustar hornikusers\name{corgen} \alias{corgen} \title{ Generate correlated data } \description{ Generate correlated data of a given length. } \usage{ corgen(len, x, r, population = FALSE, epsilon = 0) } \arguments{ \item{len}{ Length of vectors. } \item{x}{ Independent data. If x is specified, the population parameter is automatically set to TRUE. } \item{r}{ Desired correlation between data vectors. } \item{population}{ TRUE for vectors drawn from two populations with correlation r, otherwise r is the sample correlation. } \item{epsilon}{ Desired tolerance. } } \value{ \item{x }{First data vector, either generated by corgen or given by the user. } \item{y }{Second data vector. } } \details{ Either x or len must be specified. If epsilon = 0, it has no effect, otherwise the sampling process is repeated until the sample correlation is within epsilon of r. This option allows the production of exactly-correlated data, within the limits of epsilon. Setting epsilon > 0 invalidates the population setting; data will be correlated within that range, rather than sampled from that population.If epsilon = 0, it has no effect, otherwise the sampling process is repeated until the sample correlation is within epsilon of r. This option allows the production of exactly-correlated data, within the limits of epsilon. Setting epsilon > 0 invalidates the population setting; data will be correlated within that range, rather than sampled from that population.If epsilon = 0, it has no effect, otherwise the sampling process is repeated until the sample correlation is within epsilon of r. This option allows the production of exactly-correlated data, within the limits of epsilon. Setting epsilon > 0 invalidates the population setting; data will be correlated within that range, rather than sampled from that population. } \author{ Sarah Goslee } \examples{ # create two random variables of length 100 with correlation # of 0.10 +/- 0.01 xy <- corgen(len=100, r=.1, epsilon=0.01) with(xy, cor(x, y)) # create two random variables of length 100 drawn from a population with # a correlation of -0.82 xy <- corgen(len=100, r=-0.82, population=TRUE) with(xy, cor(x, y)) # create a variable y within 0.01 of the given correlation to x x <- 1:100 y <- corgen(x=x, r=.5, epsilon=.01)$y cor(x, y) } \keyword{ distribution } ecodist/man/iris.nmds.Rd0000644000175100001440000000141113131461044014664 0ustar hornikusers\name{iris.nmds} \alias{iris.nmds} \docType{data} \title{Example for nmds} \description{ An object of class nmds for use in the example for \code{\link{nmds}}. Many of the functions in \code{ecodist} take a long time to run, so prepared examples have been included. } \usage{data(iris.nmds)} \format{ See \code{\link{nmds}} for current format specification. } \author{ Sarah Goslee } \seealso{ \code{\link{nmds}} } \examples{ data(iris) iris.d <- dist(iris[,1:4]) ### nmds() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.nmds <- nmds(iris.d, nits=20, mindim=1, maxdim=4) ### save(iris.nmds, file="ecodist/data/iris.nmds.rda") data(iris.nmds) # examine fit by number of dimensions plot(iris.nmds) } \keyword{datasets} ecodist/man/MRM.Rd0000644000175100001440000000464613131461121013422 0ustar hornikusers\name{MRM} \alias{MRM} \title{ Multiple Regression on distance Matrices } \description{ Multiple regression on distance matrices (MRM) using permutation tests of significance for regression coefficients and R-squared. } \usage{ MRM(formula = formula(data), data = sys.parent(), nperm = 1000, method = "linear", mrank = FALSE) } \arguments{ \item{formula}{ formula describing the test to be conducted. } \item{data}{ an optional dataframe containing the variables in the model as columns of dissimilarities. By default the variables are taken from the current environment. } \item{nperm}{ number of permutations to use. If set to 0, the permutation test will be omitted. } \item{mrank}{ if this is set to FALSE (the default option), Pearson correlations will be used. If set to TRUE, the Spearman correlation (correlation ranked distances) will be used. } \item{method}{ if "linear", the default, uses multiple regression analysis. If "logistic", performs logistic regression with appropriate permutation testing. Note that this may be substantially slower.} } \details{ Performs multiple regression on distance matrices following the methods outlined in Legendre et al. 1994. Specificaly, the permutation test uses a pseudo-t test to assess significance, rather than using the regression coefficients directly. } \value{ \item{coef }{A matrix with regression coefficients and associated p-values from the permutation test (using the pseudo-t of Legendre et al. 1994).} \item{r.squared }{Regression R-squared and associated p-value from the permutation test (linear only). } \item{F.test }{F-statistic and p-value for overall F-test for lack of fit (linear only).} \item{dev }{Residual deviance, degrees of freetom, and associated p-value (logistic only).} } \references{ Lichstein, J. 2007. Multiple regression on distance matrices: A multivariate spatial analysis tool. Plant Ecology 188: 117-131. Legendre, P.; Lapointe, F. and Casgrain, P. 1994. Modeling brain evolution from behavior: A permutational regression approach. Evolution 48: 1487-1499. } \author{ Sarah Goslee } \seealso{ \code{\link{mantel}} } \examples{ data(graze) # This grass is related to forest cover but not location MRM(dist(LOAR10) ~ dist(sitelocation) + dist(forestpct), data=graze, nperm=100) # This legume is related to location but not forest cover MRM(dist(TRRE3) ~ dist(sitelocation) + dist(forestpct), data=graze, nperm=100) } \keyword{ multivariate } ecodist/man/ecodist-package.Rd0000644000175100001440000000157213131506172016013 0ustar hornikusers\name{ecodist-package} \alias{ecodist-package} \alias{ecodist} \docType{package} \title{ Dissimilarity-Based Functions for Ecological Analysis } \description{ Dissimilarity-based analysis functions including ordination and Mantel test functions, intended for use with spatial and community data. } \details{ This package contains well-established dissimilarity-based ecological analyses, such as \code{\link{nmds}} and \code{\link{mantel}}, and experimental/research analyses such as \code{\link{xmantel}}. Helper functions such as \code{\link{crosstab}} and \code{\link{cor2m}} facilitate analysis of community data. Because many of the analyses are time-consuming, this package includes worked examples that can be loaded using \code{data()}. \packageIndices{ecodist} } \author{ Sarah Goslee and Dean Urban Maintainer: Sarah Goslee } \keyword{ package } ecodist/man/full.Rd0000644000175100001440000000202513131460755013732 0ustar hornikusers\name{full} \alias{full} \title{ Full symmetric matrix } \description{ Convert a column order distance matrix to a full symmetric matrix. } \usage{ full(v) } \arguments{ \item{v}{ lower-triangular column order distance matrix. } } \details{ Converts a column order lower-triangular distance matrix as written by R functions into a symmetric matrix. Note that \code{lower()} used on a 1x1 matrix will return the single element, which may not be the correct behavior in all cases, while \code{full()} used on a single element will return a 2x2 matrix. } \value{ full symmetric matrix. } \author{ Sarah Goslee } \seealso{ \code{\link{lower}}, \code{\link{fixdmat}} } \examples{ # Given a vector: x.vec <- seq_len(6) x.vec # Make an R-style column order symmetric matrix full(x.vec) # Extract the lower triangle from a symmetric matrix # in column order lower(full(x.vec)) # Convert to or from a row order symmetric matrix fixdmat(x.vec) lower(fixdmat(x.vec)) fixdmat(c(1, 2, 4, 3, 5, 6)) } \keyword{ manip } \keyword{ multivariate } ecodist/man/mgroup.Rd0000644000175100001440000000302013131461110014257 0ustar hornikusers\name{mgroup} \alias{mgroup} \title{ Mantel test for groups } \description{ Simple and partial Mantel tests, with options for ranked data, permutation tests, and bootstrapped confidence limits. } \usage{ mgroup(edist, groups, nperm=1000) } \arguments{ \item{edist}{ a dist object or lower triangular distance vector. } \item{groups}{ a vector of group memberships (numeric, character, or factor), or a matrix or data frame with columns describing multiple sets of groups. } \item{nperm}{ number of permutations to use. If set to 0, the permutation test will be omitted. } } \details{ \code{mgroup} returns the Mantel correlations for group contrast matrices computed from cluster groups across a range of clustering levels. } \value{ \item{nclust }{Number of groups tested.} \item{mantelr }{Mantel coefficient.} \item{pval1 }{one-tailed p-value (null hypothesis: r <= 0).} } \references{ Legendre, P. and M. Fortin. 1989. Spatial pattern and ecological analysis. Vegetatio 80:107-138. } \author{ Sarah Goslee } \seealso{ \code{\link{mantel}} } \examples{ # Using a model matrix to test group membership data(iris) iris.d <- dist(iris[,1:4]) mgroup(iris.d, iris[,5]) # clustering-based example data(graze) graze.d <- dist(graze[, -c(1:2)]) graze.hclust <- hclust(graze.d) clust.groups <- data.frame( k2 = cutree(graze.hclust, k = 2), k4 = cutree(graze.hclust, k = 4), k6 = cutree(graze.hclust, k = 6), k8 = cutree(graze.hclust, k = 8)) mgroup(graze.d, clust.groups, nperm=1000) } \keyword{ multivariate } ecodist/man/z.no.Rd0000644000175100001440000000355113131461250013650 0ustar hornikusers\name{z.no} \alias{z.no} \docType{data} \title{Example for pmgram} \description{ An object of class mgram for use in the example for \code{\link{pmgram}}. Many of the functions in \code{ecodist} take a long time to run, so prepared examples have been included. } \usage{data(z.no)} \format{ See \code{\link{pmgram}} for current format specification. } \author{ Sarah Goslee } \seealso{ \code{\link{pmgram}}, \code{\link{z.z1}}, } \examples{ #### Partial pmgram example # generate a simple surface # with complex nonlinear spatial pattern x <- matrix(1:25, nrow=25, ncol=25, byrow=FALSE) y <- matrix(1:25, nrow=25, ncol=25, byrow=TRUE) # create z1 and z2 as functions of x, y # and scale them to [0, 1] z1 <- x + 3*y z2 <- y - cos(x) z1 <- (z1 - min(z1)) / (max(z1) - min(z1)) z2 <- (z2 - min(z2)) / (max(z2) - min(z2)) z12 <- (z1 + z2*2)/3 # look at patterns layout(matrix(c( 1, 1, 2, 2, 1, 1, 2, 2, 3, 3, 4, 4, 3, 3, 5, 5), nrow=4, byrow=TRUE)) image(z1, col=gray(seq(0, 1, length=20)), zlim=c(0,1)) image(z2, col=gray(seq(0, 1, length=20)), zlim=c(0,1)) image(z12, col=gray(seq(0, 1, length=20)), zlim=c(0,1)) # analyze the pattern of z across space z1 <- as.vector(z1) z2 <- as.vector(z2) z12 <- as.vector(z12) z1.d <- dist(z1) z2.d <- dist(z2) z12.d <- dist(z12) space <- cbind(as.vector(x), as.vector(y)) space.d <- dist(space) # take partial correlogram without effects of z1 ### pgram() is time-consuming, so this was generated ### in advance and saved. ### set.seed(1234) ### z.no <- pmgram(z12.d, space.d, nperm=1000, resids=FALSE) ### save(z.no, file="ecodist/data/z.no.rda") plot(z.no) # take partial correlogram of z12 given z1 ### pgram() is time-consuming, so this was generated ### in advance and saved. ### set.seed(1234) ### z.z1 <- pmgram(z12.d, space.d, z2.d, nperm=1000, resids=FALSE) ### save(z.z1, file="ecodist/data/z.z1.rda") plot(z.z1) } \keyword{datasets} ecodist/man/graze.Rd0000644000175100001440000000547413131460777014117 0ustar hornikusers\name{graze} \alias{graze} \docType{data} \title{ Site information and grazed vegetation data. } \description{ This data frame contains site location, landscape context and dominant plant species abundances for 25 of the plant species found in 50 grazed pastures in the northeastern United States. Elements are the mean values for canopy cover for ten 0.5 x 2 m quadrats. } \usage{data(graze)} \format{ A data frame with 50 observations on the following 25 variables. \describe{ \item{\code{sitelocation}}{Site location along a geographic gradient.} \item{\code{forestpct}}{Percentage forest cover within a 1-km radius.} \item{\code{ACMI2}}{Percentage canopy cover.} \item{\code{ANOD}}{Percentage canopy cover.} \item{\code{ASSY}}{Percentage canopy cover.} \item{\code{BRIN2}}{Percentage canopy cover.} \item{\code{CIAR4}}{Percentage canopy cover.} \item{\code{CIIN}}{Percentage canopy cover.} \item{\code{CIVU}}{Percentage canopy cover.} \item{\code{DAGL}}{Percentage canopy cover.} \item{\code{ELRE4}}{Percentage canopy cover.} \item{\code{GAMO}}{Percentage canopy cover.} \item{\code{LOAR10}}{Percentage canopy cover.} \item{\code{LOCO6}}{Percentage canopy cover.} \item{\code{LOPE}}{Percentage canopy cover.} \item{\code{OXST}}{Percentage canopy cover.} \item{\code{PLMA2}}{Percentage canopy cover.} \item{\code{POPR}}{Percentage canopy cover.} \item{\code{PRVU}}{Percentage canopy cover.} \item{\code{RAAC3}}{Percentage canopy cover.} \item{\code{RUCR}}{Percentage canopy cover.} \item{\code{SORU2}}{Percentage canopy cover.} \item{\code{STGR}}{Percentage canopy cover.} \item{\code{TAOF}}{Percentage canopy cover.} \item{\code{TRPR2}}{Percentage canopy cover.} \item{\code{TRRE3}}{Percentage canopy cover.} \item{\code{VEOF2}}{Percentage canopy cover.} } } \details{ Site locations fall along a southwest-northeast transect through the northeastern United States. This is a synthetic gradient calculated from latitude and longitude. Forest landcover is taken from the USGS 1992 National Land Cover Dataset. All forest classes were combined, and the percentage within 1 km of the sample sites was calculated using a GIS. } \source{ Details of these data are available in Tracy and Sanderson (2000) and Goslee and Sanderson (2010). The 1992 NLCD data can be obtained from http://www.mrlc.gov/. Species codes are from http://plants.usda.gov (2010). } \references{ Tracy, B.F. and M.A. Sanderson. 2000. Patterns of plant species richness in pasture lands of the northeast United States. Plant Ecology 149:169-180. Goslee, S.C., Sanderson, M.A. 2010. Landscape Context and Plant Community Composition in Grazed Agricultural Systems. Landscape Ecology 25:1029-1039. } \author{ Sarah Goslee } \examples{ data(graze) } \keyword{datasets} ecodist/man/bump.Rd0000644000175100001440000000106013131460666013732 0ustar hornikusers\name{bump} \alias{bump} \docType{data} \title{Nine-bump spatial pattern} \description{ A two-dimensional artificial "landscape" illustrating the kind of spatial pattern that might be seen across mountain peaks. } \usage{data(bump)} \format{ The format is: int [1:25, 1:25] 2 2 2 2 2 2 2 2 2 2 ... - attr(*, "dimnames")=List of 2 ..$ : chr [1:25] "1" "3" "5" "7" ... ..$ : chr [1:25] "V1" "V3" "V5" "V7" ... } \author{ Sarah Goslee } \seealso{ \code{\link{bump.pmgram}}, \code{\link{pmgram}} } \examples{ data(bump) image(bump) } \keyword{datasets} ecodist/man/nmds.Rd0000644000175100001440000001151413131461137013727 0ustar hornikusers\name{nmds} \alias{nmds} \title{ Non-metric multidimensional scaling } \description{ Non-metric multidimensional scaling. } \usage{ nmds(dmat, mindim = 1, maxdim = 2, nits = 10, iconf, epsilon = 1e-12, maxit = 500, trace = FALSE) } \arguments{ \item{dmat}{ lower-triangular dissimilarity matrix. } \item{mindim}{ optional, minimum number of dimensions to use. } \item{maxdim}{ optional, maximum number of dimensions to use. } \item{nits}{ optional, number of separate ordinations to use. } \item{iconf}{ optional, initial configuration. If not specified, then a random configuration is used. } \item{epsilon}{ optional, acceptable difference in stress. } \item{maxit}{ optional, maximum number of iterations. } \item{trace}{ if TRUE, will write progress indicator to the screen. } } \details{ The goal of NMDS is to find a configuration in a given number of dimensions which preserves rank-order dissimilarities as closely as possible. The number of dimensions must be specified in advance. Because NMDS is prone to finding local minima, several random starts must be used. Stress is used as the measure of goodness of fit. A lower stress indicates a better match between dissimilarity and ordination. As of ecodist 1.9, the stress calculation used is the same as in \code{MASS:isoMDS}. In previous versions it was monotonically related, so the same configurations were produced, but the absolute value was different. } \value{ \item{conf }{list of configurations.} \item{stress }{list of final stress values.} \item{r2 }{total variance explained by each configuration.} The first results are for the lowest number of dimensions (total number is (mindim - maxdim + 1) * nits). } \references{ Kruskal, J.B. 1964. Multidimensional scaling by optimizing goodness of fit to a nonmetric hypothesis. Psychometrika 29:1-27. Minchin, P.R. 1987. An evaluation of the relative robustness of techniques for ecological ordination. Vegetatio 96:89-108. } \author{ Sarah Goslee } \seealso{ \code{\link{plot.nmds}}, \code{\link{min.nmds}}, \code{\link{vf}}, \code{\link{addord}} } \examples{ data(iris) iris.d <- dist(iris[,1:4]) ### nmds() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.nmds <- nmds(iris.d, nits=20, mindim=1, maxdim=4) ### save(iris.nmds, file="ecodist/data/iris.nmds.rda") data(iris.nmds) # examine fit by number of dimensions plot(iris.nmds) # choose the best two-dimensional solution to work with iris.nmin <- min(iris.nmds, dims=2) # rotate the configuration to maximize variance iris.rot <- princomp(iris.nmin)$scores # rotation preserves distance apart in ordination space cor(dist(iris.nmin), dist(iris.rot)) # fit the data to the ordination as vectors ### vf() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.vf <- vf(iris.nmin, iris[,1:4], nperm=1000) ### save(iris.vf, file="ecodist/data/iris.vf.rda") data(iris.vf) # repeat for the rotated ordination ### vf() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.vfrot <- vf(iris.rot, iris[,1:4], nperm=1000) ### save(iris.vfrot, file="ecodist/data/iris.vfrot.rda") data(iris.vfrot) par(mfrow=c(1,2)) plot(iris.nmin, col=as.numeric(iris$Species), pch=as.numeric(iris$Species), main="NMDS") plot(iris.vf) plot(iris.rot, col=as.numeric(iris$Species), pch=as.numeric(iris$Species), main="Rotated NMDS") plot(iris.vfrot) # generate new data points to add to the ordination # this might be new samples, or a second dataset iris.new <- structure(list(Sepal.Length = c(4.6, 4.9, 5.4, 5.2, 6, 6.5, 6, 6.8, 7.3), Sepal.Width = c(3.2, 3.5, 3.6, 2.3, 2.8, 3, 2.7, 3.1, 3.2), Petal.Length = c(1.2, 1.5, 1.5, 3.5, 4.1, 4.2, 4.8, 5, 5.7), Petal.Width = c(0.26, 0.26, 0.26, 1.2, 1.3, 1.4, 1.8, 2, 2), Species = structure(c(1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L), .Label = c("setosa", "versicolor", "virginica"), class = "factor")), .Names = c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width", "Species"), class = "data.frame", row.names = c(NA, -9L)) # provide a dist object containing original and new data # provide a logical vector indicating which samples were used to # construct the original configuration iris.full <- rbind(iris, iris.new) all.d <- dist(iris.full[,1:4]) is.orig <- c(rep(TRUE, nrow(iris)), rep(FALSE, nrow(iris.new))) ### addord() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.fit <- addord(iris.nmin, iris.full[,1:4], all.d, is.orig, maxit=100) ### save(iris.fit, file="ecodist/data/iris.fit.rda") data(iris.fit) plot(iris.fit$conf, col=iris.full$Species, pch=c(18, 4)[is.orig + 1], xlab="NMDS 1", ylab="NMDS 2") title("Demo: adding points to an ordination") legend("bottomleft", c("Training set", "Added point"), pch=c(4, 18)) legend("topright", levels(iris$Species), fill=1:3) } \keyword{ multivariate } ecodist/man/iris.vfrot.Rd0000644000175100001440000000351613131461061015072 0ustar hornikusers\name{iris.vfrot} \alias{iris.vfrot} \docType{data} \title{Example for vector fitting on rotated ordination} \description{ An object of class vf for use in the examples for \code{\link{nmds}} and \code{\link{vf}}. Many of the functions in \code{ecodist} take a long time to run, so prepared examples have been included. } \usage{data(iris.vfrot)} \format{ See \code{\link{vf}} for current format specification. } \author{ Sarah Goslee } \seealso{ \code{\link{nmds}}, \code{\link{vf}} } \examples{ data(iris) iris.d <- dist(iris[,1:4]) ### nmds() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.nmds <- nmds(iris.d, nits=20, mindim=1, maxdim=4) ### save(iris.nmds, file="ecodist/data/iris.nmds.rda") data(iris.nmds) # examine fit by number of dimensions plot(iris.nmds) # choose the best two-dimensional solution to work with iris.nmin <- min(iris.nmds, dims=2) # rotate the configuration to maximize variance iris.rot <- princomp(iris.nmin)$scores # rotation preserves distance apart in ordination space cor(dist(iris.nmin), dist(iris.rot)) # fit the data to the ordination as vectors ### vf() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.vf <- vf(iris.nmin, iris[,1:4], nperm=1000) ### save(iris.vf, file="ecodist/data/iris.vf.rda") data(iris.vf) # repeat for the rotated ordination ### vf() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.vfrot <- vf(iris.rot, iris[,1:4], nperm=1000) ### save(iris.vfrot, file="ecodist/data/iris.vfrot.rda") data(iris.vfrot) par(mfrow=c(1,2)) plot(iris.nmin, col=as.numeric(iris$Species), pch=as.numeric(iris$Species), main="NMDS") plot(iris.vf) plot(iris.rot, col=as.numeric(iris$Species), pch=as.numeric(iris$Species), main="Rotated NMDS") plot(iris.vfrot) } \keyword{datasets} ecodist/man/plot.vf.Rd0000644000175100001440000000317513131505447014365 0ustar hornikusers\name{plot.vf} \alias{plot.vf} \title{ Plots fitted vectors onto an ordination diagram } \description{ Add vector fitting arrows to an existing ordination plot. } \usage{ \method{plot}{vf}(x, pval = 1, cex = 0.8, ascale = 0.9, \dots) } \arguments{ \item{x}{ an object of S3 class \code{vf}, created by \code{vf()} } \item{pval}{ optional, critical p-value for choosing variables to plot } \item{cex}{ text size } \item{ascale}{ optional, proportion of plot area to use when calculating arrow length } \item{\dots}{ optional, other graphics parameters } } \value{ Adds arrows to an existing ordination plot. Only arrows with a p-value less than pval are added. By default, all variables are shown. } \author{ Sarah Goslee } \seealso{ \code{\link{vf}}} \examples{ # Example of multivariate analysis using built-in iris dataset data(iris) iris.d <- dist(iris[,1:4]) ### nmds() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.nmds <- nmds(iris.d, nits=20, mindim=1, maxdim=4) ### save(iris.nmds, file="ecodist/data/iris.nmds.rda") data(iris.nmds) # examine fit by number of dimensions plot(iris.nmds) # choose the best two-dimensional solution to work with iris.nmin <- min(iris.nmds, dims=2) # fit the data to the ordination as vectors ### vf() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.vf <- vf(iris.nmin, iris[,1:4], nperm=1000) ### save(iris.vf, file="ecodist/data/iris.vf.rda") data(iris.vf) plot(iris.nmin, col=as.numeric(iris$Species), pch=as.numeric(iris$Species), main="NMDS") plot(iris.vf) } \keyword{ multivariate } \keyword{ hplot } ecodist/man/bump.pmgram.Rd0000644000175100001440000000204613131460654015216 0ustar hornikusers\name{bump.pmgram} \alias{bump.pmgram} \docType{data} \title{Nine-bump spatial pattern} \description{ An object of class mgram for use in the example for \code{\link{pmgram}}. Many of the functions in \code{ecodist} take a long time to run, so prepared examples have been included. } \usage{data(bump.pmgram)} \format{ See \code{\link{pmgram}} for current format specification. } \author{ Sarah Goslee } \seealso{ \code{\link{bump}}, \code{\link{pmgram}} } \examples{ data(bump) par(mfrow=c(1, 2)) image(bump, col=gray(seq(0, 1, length=5))) z <- as.vector(bump) x <- rep(1:25, times=25) y <- rep(1:25, each=25) X <- col(bump) Y <- row(bump) # calculate dissimilarities for data and space geo.dist <- dist(cbind(as.vector(X), as.vector(Y))) value.dist <- dist(as.vector(bump)) ### pgram() is time-consuming, so this was generated ### in advance and saved. ### set.seed(1234) ### bump.pmgram <- pmgram(value.dist, geo.dist, nperm=10000) ### save(bump.pmgram, file="ecodist/data/bump.pmgram.rda") data(bump.pmgram) plot(bump.pmgram) } \keyword{datasets} ecodist/man/vf.Rd0000644000175100001440000000365613131461216013407 0ustar hornikusers\name{vf} \alias{vf} \title{ Vector fitting } \description{ Fits ancillary variables to an ordination configuration. } \usage{ vf(ord, vars, nperm = 100) } \arguments{ \item{ord}{ matrix containing a 2-dimensional ordination result with axes as columns. } \item{vars}{ matrix with ancillary variables as columns. } \item{nperm}{ number of permutation for the significance test. If nperm = 0, the test will be omitted. } } \details{ Vector fitting finds the maximum correlation of the individual variables with a configuration of samples in ordination space. } \value{ an object of class vf containing matrix with the first 2 columns containing the scores for every variable in each of the 2 dimensions of the ordination space. r is the maximum correlation of the variable with the ordination space, and pval is the result of the permutation test. } \references{ Jongman, R.H.G., C.J.F. ter Braak and O.F.R. van Tongeren. 1995. Data analysis in community and landscape ecology. Cambridge University Press, New York. } \author{ Sarah Goslee } \seealso{ \code{\link{plot.vf}} } \examples{ # Example of multivariate analysis using built-in iris dataset data(iris) iris.d <- dist(iris[,1:4]) ### nmds() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.nmds <- nmds(iris.d, nits=20, mindim=1, maxdim=4) ### save(iris.nmds, file="ecodist/data/iris.nmds.rda") data(iris.nmds) # examine fit by number of dimensions plot(iris.nmds) # choose the best two-dimensional solution to work with iris.nmin <- min(iris.nmds, dims=2) # fit the data to the ordination as vectors ### vf() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.vf <- vf(iris.nmin, iris[,1:4], nperm=1000) ### save(iris.vf, file="ecodist/data/iris.vf.rda") data(iris.vf) plot(iris.nmin, col=as.numeric(iris$Species), pch=as.numeric(iris$Species), main="NMDS") plot(iris.vf) } \keyword{ multivariate } ecodist/man/z.z1.Rd0000644000175100001440000000355113131461256013574 0ustar hornikusers\name{z.z1} \alias{z.z1} \docType{data} \title{Example for pmgram} \description{ An object of class mgram for use in the example for \code{\link{pmgram}}. Many of the functions in \code{ecodist} take a long time to run, so prepared examples have been included. } \usage{data(z.z1)} \format{ See \code{\link{pmgram}} for current format specification. } \author{ Sarah Goslee } \seealso{ \code{\link{pmgram}}, \code{\link{z.no}}, } \examples{ #### Partial pmgram example # generate a simple surface # with complex nonlinear spatial pattern x <- matrix(1:25, nrow=25, ncol=25, byrow=FALSE) y <- matrix(1:25, nrow=25, ncol=25, byrow=TRUE) # create z1 and z2 as functions of x, y # and scale them to [0, 1] z1 <- x + 3*y z2 <- y - cos(x) z1 <- (z1 - min(z1)) / (max(z1) - min(z1)) z2 <- (z2 - min(z2)) / (max(z2) - min(z2)) z12 <- (z1 + z2*2)/3 # look at patterns layout(matrix(c( 1, 1, 2, 2, 1, 1, 2, 2, 3, 3, 4, 4, 3, 3, 5, 5), nrow=4, byrow=TRUE)) image(z1, col=gray(seq(0, 1, length=20)), zlim=c(0,1)) image(z2, col=gray(seq(0, 1, length=20)), zlim=c(0,1)) image(z12, col=gray(seq(0, 1, length=20)), zlim=c(0,1)) # analyze the pattern of z across space z1 <- as.vector(z1) z2 <- as.vector(z2) z12 <- as.vector(z12) z1.d <- dist(z1) z2.d <- dist(z2) z12.d <- dist(z12) space <- cbind(as.vector(x), as.vector(y)) space.d <- dist(space) # take partial correlogram without effects of z1 ### pgram() is time-consuming, so this was generated ### in advance and saved. ### set.seed(1234) ### z.no <- pmgram(z12.d, space.d, nperm=1000, resids=FALSE) ### save(z.no, file="ecodist/data/z.no.rda") plot(z.no) # take partial correlogram of z12 given z1 ### pgram() is time-consuming, so this was generated ### in advance and saved. ### set.seed(1234) ### z.z1 <- pmgram(z12.d, space.d, z2.d, nperm=1000, resids=FALSE) ### save(z.z1, file="ecodist/data/z.z1.rda") plot(z.z1) } \keyword{datasets} ecodist/man/pco.Rd0000644000175100001440000000235113131461143013543 0ustar hornikusers\name{pco} \alias{pco} \title{ Principal coordinates analysis } \description{ Principal coordinates analysis (classical scaling). } \usage{ pco(x, negvals = "zero", dround = 0) } \arguments{ \item{x}{ a lower-triangular dissimilarity matrix. } \item{negvals}{ if = "zero" sets all negative eigenvalues to zero; if = "rm" corrects for negative eigenvalues using method 1 of Legendre and Anderson 1999. } \item{dround}{ if greater than 0, attempts to correct for round-off error by rounding to that number of places. } } \details{ PCO (classical scaling, metric multidimensional scaling) is very similar to principal components analysis, but allows the use of any dissimilarity metric. } \value{ \item{values }{eigenvalue for each component. This is a measure of the variance explained by each dimension.} \item{vectors }{eigenvectors. Each column contains the scores for that dimension.} } \author{ Sarah Goslee } \seealso{ \code{\link{princomp}}, \code{\link{nmds}} } \examples{ data(iris) iris.d <- dist(iris[,1:4]) iris.pco <- pco(iris.d) # scatterplot of the first two dimensions plot(iris.pco$vectors[,1:2], col=as.numeric(iris$Species), pch=as.numeric(iris$Species), main="PCO", xlab="PCO 1", ylab="PCO 2") } \keyword{ multivariate } ecodist/man/residuals.mgram.Rd0000644000175100001440000000240713131461207016062 0ustar hornikusers\name{residuals.mgram} \alias{residuals.mgram} \title{ Residuals of a Mantel correlogram } \description{ Extracts residuals from an S3 object of class \code{mgram} (only relevant for objects created by \code{pmgram{}}). } \usage{ \method{residuals}{mgram}(object, ...) } \arguments{ \item{object}{ an object of class \code{mgram} } \item{\dots}{ additional arguments } } \value{ vector of residuals. } \author{ Sarah Goslee } \seealso{ \code{\link{pmgram}}, \code{\link{mgram}} } \examples{ #### Partial pmgram example # generate a simple surface # with complex nonlinear spatial pattern x <- matrix(1:10, nrow=10, ncol=10, byrow=FALSE) y <- matrix(1:10, nrow=10, ncol=10, byrow=TRUE) # create z1 and z2 as functions of x, y # and scale them to [0, 1] z1 <- x + 3*y z2 <- y - cos(x) z1 <- (z1 - min(z1)) / (max(z1) - min(z1)) z2 <- (z2 - min(z2)) / (max(z2) - min(z2)) z12 <- (z1 + z2*2)/3 # analyze the pattern of z across space z1 <- as.vector(z1) z2 <- as.vector(z2) z12 <- as.vector(z12) z1.d <- dist(z1) z2.d <- dist(z2) z12.d <- dist(z12) space <- cbind(as.vector(x), as.vector(y)) space.d <- dist(space) # take partial correlogram of z12 given z1 z.z1 <- pmgram(z12.d, space.d, z2.d, nperm=0, resids=TRUE) summary(residuals(z.z1)) } \keyword{ multivariate } ecodist/man/xmgram.Rd0000644000175100001440000000763213131461236014267 0ustar hornikusers\name{xmgram} \alias{xmgram} \title{Cross-Mantel correlogram } \description{ Calculates simple Mantel correlograms from cross-distance matrices. } \usage{ xmgram(species.xd, space.xd, breaks, nclass, stepsize, nperm = 1000, mrank = FALSE, alternative = "two.sided", trace = FALSE) } \arguments{ \item{species.xd}{ non-symmetric square cross-distance matrix. } \item{space.xd}{ non-symmetric square matrix of geographic distances. } \item{breaks}{ locations of class breaks. If specified, overrides nclass and stepsize. } \item{nclass}{ number of distance classes. If not specified, Sturge's rule will be used to determine an appropriate number of classes. } \item{stepsize}{ width of each distance class. If not specified, nclass and the range of space.d will be used to calculate an appropriate default. } \item{nperm}{ number of permutations to use. If set to 0, the permutation test will be omitted. } \item{mrank}{ if this is set to FALSE (the default option), Pearson correlations will be used. If set to TRUE, the Spearman correlation (correlation ranked distances) will be used. } \item{alternative}{ default is "two.sided", and returns p-values for H0: rM = 0. The alternative is "one.sided", which returns p-values for H0: rM <= 0. } \item{trace}{ if TRUE, returns progress indicators. } } \details{ This function calculates cross-Mantel correlograms. The Mantel correlogram is essentially a multivariate autocorrelation function. The Mantel r represents the dissimilarity in variable composition (often species composition) at a particular lag distance. Note that the cross-dissimilarity functions are for research purposes, and are not well-tested. } \value{ Returns an object of class mgram, which is a list with two elements. mgram is a matrix with one row for each distance class and 6 columns: \item{lag }{midpoint of the distance class.} \item{ngroup }{number of distances in that class.} \item{mantelr }{Mantel r value.} \item{pval }{p-value for the test chosen.} resids is NA for objects calculated by mgram(). } \references{ Legendre, P. and M. Fortin. 1989. Spatial pattern and ecological analysis. Vegetatio 80:107-138. } \author{ Sarah Goslee } \seealso{\code{\link{xdistance}} \code{\link{xmantel}}, \code{\link{plot.mgram}} } \examples{ # Need to develop a cross-dissimilarity example data(graze) ### EXAMPLE 1: Square matrices # take two subsets of sites with different dominant grass abundances # use cut-offs that produce equal numbers of sites dom1 <- subset(graze, POPR > 50 & DAGL < 20) # 8 sites dom2 <- subset(graze, POPR < 50 & DAGL > 20) # 8 sites # first two columns are site info dom.xd <- xdistance(dom1[, -c(1,2)], dom2[, -c(1,2)], "bray") # environmental and spatial distances; preserve rownames forest.xd <- xdistance(dom1[, "forestpct", drop=FALSE], dom2[, "forestpct", drop=FALSE]) sitelocation.xd <- xdistance(dom1[, "sitelocation", drop=FALSE], dom2[, "sitelocation", drop=FALSE]) # permutes rows and columns of full nonsymmetric matrix xmantel(dom.xd ~ forest.xd) xmantel(dom.xd ~ forest.xd + sitelocation.xd) plot(xmgram(dom.xd, sitelocation.xd)) ### EXAMPLE 2: Non-square matrices # take two subsets of sites with different dominant grass abundances # this produces a non-square matrix dom1 <- subset(graze, POPR > 45 & DAGL < 20) # 13 sites dom2 <- subset(graze, POPR < 45 & DAGL > 20) # 8 sites # first two columns are site info dom.xd <- xdistance(dom1[, -c(1,2)], dom2[, -c(1,2)], "bray") # environmental and spatial distances; preserve rownames forest.xd <- xdistance(dom1[, "forestpct", drop=FALSE], dom2[, "forestpct", drop=FALSE]) sitelocation.xd <- xdistance(dom1[, "sitelocation", drop=FALSE], dom2[, "sitelocation", drop=FALSE]) # permutes rows and columns of full nonsymmetric matrix xmantel(dom.xd ~ forest.xd, dims=c(13, 8)) xmantel(dom.xd ~ forest.xd + sitelocation.xd, dims=c(13, 8)) plot(xmgram(dom.xd, sitelocation.xd)) } \keyword{ multivariate } ecodist/man/bcdist.Rd0000644000175100001440000000242513131460612014234 0ustar hornikusers\name{bcdist} \alias{bcdist} \title{ Bray-Curtis distance } \description{ Returns the Bray-Curtis (also known as Sorenson, 1 - percent similarity) pairwise distances for the objects in the data. It is duplicated by functionality within \code{\link{distance}} but remains for backward compatibility and because it is substantially faster. } \usage{ bcdist(x, rmzero = FALSE) } \arguments{ \item{x}{ matrix or data frame with rows as samples and columns as variables (such as species). Distances will be calculated for each pair of rows. } \item{rmzero}{ If rmzero=TRUE, empty rows will be removed from the data before distances are calculated. Otherwise, the distance between two empty rows is assumed to be 0 (the default). } } \value{ This function returns a column-order lower-triangular distance matrix. The returned object has an attribute, Size, giving the number of objects, that is, nrow(x). The length of the vector that is returned is nrow(x)*(nrow(x)-1)/2. } \author{ Sarah Goslee } \seealso{ \code{\link{dist}}, \code{\link{distance}}} \examples{ data(graze) system.time(graze.bc <- bcdist(graze[, -c(1:2)])) # equivalent to but much faster than: system.time(graze.bc2 <- distance(graze[, -c(1:2)], "bray-curtis")) all.equal(graze.bc, graze.bc2) } \keyword{ multivariate }