rotl/0000755000176200001440000000000015132225442011232 5ustar liggesusersrotl/tests/0000755000176200001440000000000015132136164012376 5ustar liggesusersrotl/tests/tree_of_life.json0000644000176200001440000000705615132136164015723 0ustar liggesusers{ "test_mrca_normal_input": { "test_function": "tol_mrca", "test_input": {"ott_ids":[412129, 536234]}, "tests": { "of_type": ["dict","Response is of wrong type"] , "equals": [ [["nearest_taxon_mrca_rank","'superorder'"],"Fails that nearest_taxon_mrca_rank contains superorder"] ], "contains": [ ["nearest_taxon_mrca_ott_id","Doesn't contain nearest_taxon_mrca_ott_id"] ] } }, "test_mrca_empty_list_input": { "test_function": "tol_mrca", "test_input": {"ott_ids":[]}, "tests": { "error": [ ["ValueError","Return wrong kind of error, or did return error"] ] } }, "test_mrca_empty_list_input_two": { "test_function": "tol_mrca", "test_input": {"ott_ids":[], "node_ids":[]}, "tests": { "error": [ ["ValueError","Return wrong kind of error, or did return error"] ] } }, "test_mrca_non_existing_node": { "test_function": "tol_mrca", "test_input": {"ott_ids":[4259824365942365972436598732]}, "tests": { "error": [ ["OpenTreeService.OpenTreeError","Return wrong kind of error, or did return error"] ] } }, "test_mrca_non_existing_empty": { "test_function": "tol_mrca", "test_input": "null", "tests": { "error": [ ["ValueError","Return wrong kind of error, or did return error"] ] } }, "test_subtree_demo": { "test_function": "tol_subtree", "test_input": {"ott_id":3599390}, "tests": { "of_type": ["dict","Response is of wrong type"] , "contains": [ ["newick","Doesn't contain a newick string"] ] } }, "test_subtree_null": { "test_function": "tol_subtree", "test_input": {}, "tests": { "error": [ ["ValueError","Return wrong kind of error, or did return error"] ], "of_type": ["jfdsm"] } }, "test_induced_tree_good": { "test_function": "tol_induced_tree", "test_input": {"ott_ids":[292466, 501678, 267845, 666104, 316878, 102710, 176458]}, "tests": { "of_type": ["dict","Response is of wrong type"] , "contains": [ ["subtree","Doesn't contain a subtree string"] ] } }, "test_induced_tree_null": { "test_function": "tol_induced_tree", "test_input": {}, "tests": { "error": [ ["ValueError","Return wrong kind of error, or did return error"] ], "of_type": ["something"] } }, "test_about": { "test_function": "tol_about", "test_input": {}, "tests": { "contains": [ ["root_taxon_name","Output doesn't contain root_taxon_name"], ["num_source_studies","Output doesn't contain num_source_studies"], ["taxonomy_version","Output doesn't contain taxonomy_version"], ["root_ott_id","Output doesn't contain root_ott_id"], ["num_tips","Output doesn't contain num_tips"] ] } } } rotl/tests/testthat/0000755000176200001440000000000015132136164014236 5ustar liggesusersrotl/tests/testthat/test-tree_to_labels.R0000644000176200001440000000423415132136164020324 0ustar liggesuserscontext("test tree_to_labels") test_that("basic tree 1", { tree1 <- "((raccon:19.19959,bear:6.80041)InnerNode1:0.84600,((sea_lion:11.99700,seal:12.00300)InnerNode2:7.52973,((monkey:100.85930,cat:47.14069):20.59201,weasel:18.87953):2.09460):3.87382,dog:25.46154);" res_tree1 <- tree_to_labels(tree1) expect_equal(res_tree1$tip_label, c("raccon", "bear", "sea_lion", "seal", "monkey", "cat", "weasel", "dog")) expect_equal(res_tree1$edge_label, c("InnerNode1", "InnerNode2")) }) test_that("basic tree 2", { tree2 <- "(Bovine:0.69395,(Gibbon:0.36079,(Orang:0.33636,(Gorilla:0.17147,(Chimp:0.19268, Human:0.11927):0.08386):0.06124):0.15057):0.54939,Mouse:1.21460):0.10;" res_tree2 <- tree_to_labels(tree2) expect_equal(res_tree2$tip_label, c("Bovine", "Gibbon", "Orang", "Gorilla", "Chimp", "Human", "Mouse")) expect_equal(res_tree2$edge_label, character(0)) }) test_that("basic tree 3", { tree3 <- "(Bovine:0.69395,(Hylobates:0.36079,(Pongo:0.33636,(G._Gorilla:0.17147, (P._paniscus:0.19268,H._sapiens:0.11927):0.08386):0.06124):0.15057):0.54939, Rodent:1.21460);" res_tree3 <- tree_to_labels(tree3) expect_equal(res_tree3$tip_label, c("Bovine", "Hylobates", "Pongo", "G._Gorilla", "P._paniscus", "H._sapiens", "Rodent")) expect_equal(res_tree3$edge_label, character(0)) }) test_that("only 1 tip", { tree_tip <- "A;" res_tree_tip <- tree_to_labels(tree_tip) expect_equal(res_tree_tip$tip_label, "A") expect_equal(res_tree_tip$edge_label, character(0)) }) test_that("only 1 tip with parentheses", { tree_tip <- "(A);" res_tree_tip <- tree_to_labels(tree_tip) expect_equal(res_tree_tip$tip_label, "A") expect_equal(res_tree_tip$edge_label, character(0)) }) test_that("only 1 tip and 1 internal", { tree_tip <- "(A)B;" res_tree_tip <- tree_to_labels(tree_tip) expect_equal(res_tree_tip$tip_label, "A") expect_equal(res_tree_tip$edge_label, "B") }) test_that("tree with singletons", { tree_sing <- "(((((A)cats,B)dogs,(C,D)ducks)frogs)animals,E)fungi;" res_tree_sing <- tree_to_labels(tree_sing) expect_equal(res_tree_sing$tip_label, LETTERS[1:5]) expect_equal(res_tree_sing$edge_label, c("cats", "dogs", "ducks", "frogs", "animals", "fungi")) }) rotl/tests/testthat/test-api-studies.R0000644000176200001440000001354015132136164017570 0ustar liggesuserscontext("studies API tests") ########################### ## .studies_find_studies ## ########################### test_that("argument verbose needs to be logical for .studies_find_studies", { skip_on_cran() expect_error( .studies_find_studies(NULL, NULL, "123", FALSE), "logical" ) }) test_that("argument exact needs to be logical for .studies_find_studies", { skip_on_cran() expect_error( .studies_find_studies(NULL, NULL, TRUE, "123"), "logical" ) }) test_that("argument property needs to be character for .studies_find_studies", { skip_on_cran() expect_error( .studies_find_studies(123, NULL, TRUE, TRUE), "character" ) }) test_that("argument value needs to be character for .studies_find_studies", { skip_on_cran() ## there is an error but not because of the argument "value" is ## character, it looks like a number so it's OK. Failure is ## because of the value doesn't exist. expect_error( .studies_find_studies("test", "123", TRUE, TRUE), "Study property test is unknown" ) }) test_that("both property & value need to be provided for .studies_find_studies", { skip_on_cran() expect_error( .studies_find_studies("test", NULL, TRUE, TRUE), "Must supply" ) }) test_that("both property & value need to be provided for .studies_find_studies", { skip_on_cran() expect_error( .studies_find_studies(NULL, "test", TRUE, TRUE), "Must supply" ) }) ########################### ## .studies_find_trees ## ########################### test_that("argument verbose needs to be logical for .studies_find_trees", { skip_on_cran() expect_error( .studies_find_trees(NULL, NULL, "123", FALSE), "logical" ) }) test_that("argument exact needs to be logical for .studies_find_trees", { skip_on_cran() expect_error( .studies_find_trees(NULL, NULL, TRUE, "123"), "logical" ) }) test_that("argument property needs to be character for .studies_find_trees", { skip_on_cran() expect_error( .studies_find_trees(123, NULL, TRUE, TRUE), "character" ) }) test_that("argument value needs to be character for .studies_find_trees", { skip_on_cran() ## there is an error but not because of the argument "value" is ## character, it looks like a number so it's OK. Failure is ## because of the value doesn't exist. expect_error(.studies_find_trees("test", "123", TRUE, TRUE)) }) test_that("both property & value need to be provided for .studies_find_trees", { skip_on_cran() expect_error( .studies_find_trees("test", NULL, TRUE, TRUE), "Must supply" ) }) test_that("both property & value need to be provided for .studies_find_trees", { skip_on_cran() expect_error( .studies_find_trees(NULL, "test", TRUE, TRUE), "Must supply" ) }) test_that("exact works as intended", { skip_on_cran() expect_equal(length(.studies_find_studies("ot:focalCladeOTTTaxonName", "felidae", exact = TRUE )$matched_studies), 0) }) test_that("exact works as intended", { skip_on_cran() expect_true(length(.studies_find_studies("ot:focalCladeOTTTaxonName", "Felidae", exact = TRUE )$matched_studies) >= 1) }) ############################################################################ ## .get_study ## ############################################################################ test_that("study_id isn't NULL for .get_study", { skip_on_cran() expect_error( .get_study(NULL, "test"), "Must supply" ) }) test_that("study_id is character for .get_study", { skip_on_cran() expect_error( .get_study(TRUE, "test"), "character" ) }) ############################################################################ ## .get_study_tree ## ############################################################################ test_that("study_id isn't NULL for .get_study_tree", { skip_on_cran() expect_error( .get_study_tree(NULL, NULL), "Must supply" ) }) test_that("study_id isn't NULL for .get_study_tree", { skip_on_cran() expect_error( .get_study_tree("123", NULL), "Must supply" ) }) test_that("study_id isn't NULL for .get_study_tree", { skip_on_cran() expect_error( .get_study_tree(NULL, "123"), "Must supply" ) }) test_that("study_id is character for .get_study", { skip_on_cran() expect_error( .get_study_tree(TRUE, "test"), "character" ) }) test_that("study_id is character for .get_study", { skip_on_cran() expect_error( .get_study_tree("test", TRUE), "character" ) }) ############################################################################ ## .get_study_subtree ## ############################################################################ test_that("study_id isn't NULL for .get_study_subtree", { skip_on_cran() expect_error( .get_study_subtree(NULL, NULL, NULL), "Must supply" ) }) test_that("tree_id isn't NULL for .get_study_subtree", { skip_on_cran() expect_error( .get_study_subtree("123", NULL, "123"), "Must supply" ) }) test_that("subtree_id isn't NULL for .get_study_subtree", { skip_on_cran() expect_error( .get_study_subtree(NULL, "123", "123"), "Must supply" ) }) test_that("study_id isn't NULL for .get_study_subtree", { skip_on_cran() expect_error( .get_study_subtree("123", "123", NULL), "Must supply" ) }) test_that("study_id is character for .get_study", { skip_on_cran() expect_error( .get_study_subtree(TRUE, "test", "test"), "character" ) }) test_that("tree_id is character for .get_study", { skip_on_cran() expect_error( .get_study_subtree("test", TRUE, "test"), "character" ) }) test_that("subtree_id is character for .get_study", { skip_on_cran() expect_error( .get_study_subtree("test", "test", TRUE), "character" ) }) rotl/tests/testthat/test-api-tol.R0000644000176200001440000000433115132136164016704 0ustar liggesuserscontext("Tree of Life API") ############################################################################ ## .tol_about ## ############################################################################ test_that("include_source_list is logical for .tol_about", { skip_on_cran() expect_error( .tol_about("true"), "logical" ) }) ############################################################################ ## .tol_mrca ## ############################################################################ test_that("neither ott_ids nor node_ids are NULL for .tol_mrca", { skip_on_cran() expect_error( .tol_mrca(NULL), "Must provide" ) }) ############################################################################ ## .tol_subtree ## ############################################################################ test_that("ott_id is not NULL", { skip_on_cran() expect_error( .tol_subtree(ott_id = NULL, node_id = NULL), "Must provide" ) }) ############################################################################ ## .tol_induced_subtree ## ############################################################################ test_that("ott_ids is not NULL", { skip_on_cran() expect_error( .tol_induced_subtree(ott_ids = NULL), "Must provide" ) }) test_that("NAs are not accepted for ott_ids", { skip_on_cran() expect_error( .tol_induced_subtree(ott_ids = c(123, NA, 456)), "NAs are not allowed" ) }) #################### ## .tol_node_info ## #################### test_that("include_lineage must be logical with .tol_node_info", { skip_on_cran() expect_error( .tol_node_info(ott_id = "ott_123", include_lineage = "123"), "logical" ) }) test_that("ott_id must be a numeric with .tol_node_info", { skip_on_cran() expect_error( .tol_node_info(ott_id = "test"), "look like numbers" ) }) test_that("node_id must be a character with .tol_node_info", { skip_on_cran() expect_error( .tol_node_info(node_id = 123), "must look like" ) }) rotl/tests/testthat/test-api-taxonomy.R0000644000176200001440000000535515132136164017773 0ustar liggesuserscontext("taxonomy API") ############################################################################ ## .taxonomy_taxon_info ## ############################################################################ test_that("ott_id is not null for .taxonomy_taxon_info", { skip_on_cran() expect_error( .taxonomy_taxon_info(NULL), "must supply" ) }) test_that("ott_id is of length 1 for .taxonomy_taxon_info", { skip_on_cran() expect_error( .taxonomy_taxon_info(c(123, 456, 789)), "Must only supply" ) }) test_that("ott_id is a numeric for .taxonomy_taxon_info", { skip_on_cran() expect_error( .taxonomy_taxon_info(TRUE), "look like numbers" ) }) test_that("include_lineage is a flag", { skip_on_cran() expect_error( .taxonomy_taxon_info(ott_id = 515698, include_lineage = c(TRUE, FALSE)), "is not a flag" ) expect_error( .taxonomy_taxon_info(ott_id = 515698, include_lineage = c("na")), "is not a flag" ) expect_error( .taxonomy_taxon_info(ott_id = 515698, include_lineage = c(1235)), "is not a flag" ) }) test_that("list_terminal_descendants is a flag", { skip_on_cran() expect_error( .taxonomy_taxon_info(ott_id = 515698, include_terminal_descendants = c(TRUE, FALSE)), "is not a flag" ) expect_error( .taxonomy_taxon_info(ott_id = 515698, include_terminal_descendants = c("na")), "is not a flag" ) expect_error( .taxonomy_taxon_info(ott_id = 515698, include_terminal_descendants = c(1235)), "is not a flag" ) }) ############################################################################ ## .taxonomy_subtree ## ############################################################################ test_that("ott_id is not null for .taxonomy_subtree", { skip_on_cran() expect_error( .taxonomy_subtree(NULL), "must supply" ) }) test_that("ott_id is of length 1 for .taxonomy_subtree", { skip_on_cran() expect_error( .taxonomy_subtree(c(123, 456, 789)), "Must only supply" ) }) test_that("ott_id is a numeric for .taxonomy_subtree", { skip_on_cran() expect_error( .taxonomy_subtree(TRUE), "look like numbers" ) }) ############################################################################ ## .taxonomy_mrca ## ############################################################################ test_that("ott_id is not null for .taxonomy_lica", { skip_on_cran() expect_error( .taxonomy_mrca(NULL), "must supply" ) }) test_that("ott_id is a numeric for .taxonomy_lica", { skip_on_cran() expect_error( .taxonomy_mrca(TRUE), "look like numbers" ) }) rotl/tests/testthat/test-API.R0000644000176200001440000001345515132136164015757 0ustar liggesusers#### ## Making use of the shared OpenTree testing architecture #### ## The R, Python and Ruby wrappers for the Open Tree share a very similar design, ## allowing them to make use of a single test suite for the low-level functions ## (thus, the tests both checkvan individual library works as expected, and that ## the different libraries stay in line with each other). ## ## This file pulls the current version of the test from a github repo ## (https://github.com/OpenTreeOfLife/shared-api-tests) and translates the json ## files into tests that run in testthat. This takes a considerable amount of ## infrastructure so I'll briefly described the rational here. ## ## The JSON test-specificaton is defined at the github repo linked above, to ## translate these tests I have created custom testthat expectation-functionals ## (contains(), (key_has_value()... ). Because many of the test blocks in the ## JSON files have multiple expectiatoins (i.e. many key-value pairs for ## test_equals) there are functions starting with `test_` that run an entire ## test block for a given expectation. Since many of these tests require ## translation between R-objects and JSON encoded strings there is a set of ## convienence functions to automate that step and a function "test_map" that ## returns the appropriate test_* function for r given JSON test block. ## ## Finally, testthat_json_test uses the above functions to runs an entire test ## from a JSON object, and run_shared_tests() runs every tests in a JSON file. # functionals that start with a response contains <- function(key_name) { function(x) { expectation(key_name %in% names(x), sprintf("Missing key name: %s", key_name)) } } key_has_value <- function(key, value) { function(x) { if (length(value) == 0) { expectation( length(x[[key]]) == 0, paste("Key", key, "is not empty") ) } else if (length(value) == 1) { expectation( x[[key]] == value, paste("Key", key, "doesn't have value", value) ) } else { expectation( all(x[[key]] %in% value), paste("Key", key, "doesn't contain all of", value) ) } } } value_is_longer_than <- function(key, len) { function(x) { expectation( length(x[[key]]) > len, paste("Value for key", key, "is shorter than", len) ) } } value_is_error <- function(key_name) { function(x) { expectation( x[[key_name]] == "error", sprintf("Key %s is not 'error'", key_name) ) } } ## Functions to test entire test blocks with the above expectations test_contains <- function(response, test_block) { key_names <- test_block[, 1] sapply(key_names, function(k) expect_that(response, contains(k))) } test_equals <- function(response, test_block) { kv_pairs <- sapply(test_block, "[[", 1) for (i in 1:length(kv_pairs)) { expect_that(response, key_has_value(kv_pairs[[1]], kv_pairs[[2]])) } } test_of_type <- function(response, test_block) { rtype <- type_map(test_block[[1]]) expect_that(response, is_a(rtype)) } test_deep_equals <- function(response, test_block) { cat("*") expect_true(TRUE) } test_length_greater_than <- function(response, test_block) { vl_pairs <- sapply(test_block, "[[", 1) apply(vl_pairs, 2, function(v) { expect_that(response, value_is_longer_than(v[[1]], v[[2]])) }) } test_contains_error <- function(response, test_block) { errs <- test_block[, 1] sapply(errs, function(e) expect_that(reponse, contains_error(e))) } ## convience functions obj_map <- function(input) { if (is.character(input) & length(input) == 1) { switch(tolower(input), "true" = TRUE, "false" = FALSE, "null" = NULL, input ) } else { input } } json_to_r <- function(test_input) { if (length(test_input) == 0) { return(test_input) } return(lapply(test_input, obj_map)) } type_map <- function(json_type) { switch(json_type, "dict" = "list", stop(sprintf("unknown json type in testing file: %s", json_type)) ) } test_map <- function(test_type) { switch(test_type, "contains" = test_contains, "equals" = test_equals, "deep_equals" = test_deep_equals, "error" = stop("Error tests should be handled first"), "length_greater_than" = test_length_greater_than, "of_type" = test_of_type, stop(sprintf("Unkown error type in JSON test: %s", test_type)) ) } make_request <- function(json_test) { test_fxn <- paste0(".", json_test$test_function) do.call(what = test_fxn, args = json_to_r(json_test$test_input)) } testthat_json_test <- function(test_obj, test_name) { tests_to_run <- names(test_obj[[test_name]]$tests) if (length(tests_to_run) == 1) { if (grepl("error", tests_to_run)) { expect_error(make_request(test_obj[[test_name]])) } } else { response <- make_request(test_obj[[test_name]]) for (i in 1:length(tests_to_run)) { test_block <- test_obj[[test_name]]$tests[[tests_to_run[i]]] test_fxn <- test_map(tests_to_run[i]) test_fxn(response, test_block) } } } run_shared_test <- function(json_obj) { all_tests <- names(json_obj) for (i in 1:length(all_tests)) { test_that(all_tests[i], { skip_on_cran() testthat_json_test(json_obj, all_tests[i]) }) } } ## if (identical(Sys.getenv("NOT_CRAN"), "true")) { ## base_url <- "https://raw.githubusercontent.com/OpenTreeOfLife/shared-api-tests/master/" ## apis <- c("graph_of_life", ## "studies", ## "taxonomy", ## "tree_of_life", ## "tnrs" ## ) ## for(i in 1:length(apis)){ ## context( paste(apis[i], "API") ) ## test_text <- httr::GET(paste0(base_url, apis[i], ".json")) ## test_description <- jsonlite::fromJSON(httr::content(test_text)) ## run_shared_test(test_description) ## } ## } rotl/tests/testthat/test-tnrs.R0000644000176200001440000000560215132136164016327 0ustar liggesuserscontext("tnrs") ############################################################################ ## tnrs_match_names ## ############################################################################ test_that("tnrs_match_names fails if incorrect context is provided", { skip_on_cran() expect_error( tnrs_match_names("felis", context_name = "Cats"), "Check possible values using tnrs_contexts" ) }) test_that("tnrs_match_names warns if single invalid name provided", { skip_on_cran() expect_warning( tnrs_match_names("fluffy", do_approximate_matching = FALSE), "are not matched" ) }) test_that("tnrs_match_names warns if at least one name is not matched", { skip_on_cran() expect_warning( tnrs_match_names(c("fluffy", "felis"), do_approximate_matching = FALSE), "are not matched" ) }) test_that("tnrs_match_names warns if some names are duplicated", { skip_on_cran() expect_warning(tnrs_match_names(c("pan", "pongo", "Pan", "pongo", "felis", "feLis"))) }) test_that("object returned by tnrs_match_names have the correct data type", { skip_on_cran() birds <- c("stercorarius parasiticus", "ficedula albicollis", "sterna dougallii") taxa <- tnrs_match_names(birds, do_approximate_matching = FALSE) expect_true(is.logical(taxa[["approximate_match"]])) expect_true(is.logical(taxa[["is_synonym"]])) expect_equal(sum(taxa[["score"]]), 3) }) test_that("tnrs_match_names deals correctly with non-exact matches", { skip_on_cran() birds <- c("stercorarius parasiticus", "ficedula albicollis", "sternadougallii") expect_warning( taxa <- tnrs_match_names(birds, do_approximate_matching = FALSE), "are not matched" ) expect_equal(nrow(taxa), 3L) expect_equivalent( taxa[match("sternadougallii", taxa[["search_string"]]), ], list("sternadougallii", NA_character_, NA, NA_real_, NA_integer_, NA, NA_character_, NA_integer_) ) }) ## everything else is covered by the match_names + the API tests ############################################################################ ## tnrs_contexts ## ############################################################################ test_that("tnrs_contexts", { skip_on_cran() tc <- tnrs_contexts() expect_true(inherits(tc, "tnrs_contexts")) expect_true(all(names(tc) %in% c("ANIMALS", "MICROBES", "FUNGI", "PLANTS", "LIFE"))) }) ############################################################################ ## tnrs_infer_context ## ############################################################################ test_that("tnrs_infer_context", { skip_on_cran() tic <- tnrs_infer_context(c("Felis", "Leo")) expect_equal(tic[["context_name"]], "Mammals") expect_equal(tic[["context_ott_id"]], 244265) expect_equal(tic[["ambiguous_names"]][[1]], "Leo") }) rotl/tests/testthat/test-studies.R0000644000176200001440000004521215132136164017022 0ustar liggesusersif (FALSE) { context("test of studies") ############################################################################ ## studies_properties ## ############################################################################ test_that("studies_properties is a list with 2 elements (if breaks, need to update documentation)", { skip_on_cran() expect_true(all(names(studies_properties() %in% c("tree_properties", "study_properties")))) }) ############################################################################ ## get_study ## ############################################################################ test_that("get_study returns an error when asking for a study that doesn't exist", { skip_on_cran() expect_error(get_study("tt_666666")) }) test_that("get_study generates a phylo object", { skip_on_cran() tr <- get_study("pg_719", object_format = "phylo") expect_true(inherits(tr, "multiPhylo")) expect_equal(length(tr), 3) expect_true(length(tr[[1]]$tip.label) > 1) }) test_that("get_study returns an error if file is specied but file_format is not", { skip_on_cran() expect_error( get_study("pg_719", file = "test"), "must be specified" ) }) test_that("get_study generates a nexml object", { skip_on_cran() tr <- get_study("pg_719", object_format = "nexml") expect_true(inherits(tr, "nexml")) }) test_that("get_study generates a newick file", { skip_on_cran() ff <- tempfile() tr <- get_study("pg_719", file_format = "newick", file = ff) expect_true(tr) expect_true(grepl("^\\(", readLines(ff, n = 1, warn = FALSE))) }) test_that("get_study generates a nexus file", { skip_on_cran() ff <- tempfile() tr <- get_study("pg_719", file_format = "nexus", file = ff) expect_true(tr) expect_true(grepl("^#NEXUS", readLines(ff, n = 1, warn = FALSE))) }) test_that("get_study generates a nexml file", { skip_on_cran() ff <- tempfile() tr <- get_study("pg_719", file_format = "nexml", file = ff) expect_true(tr) expect_true(grepl("^<\\?xml", readLines(ff, n = 1, warn = FALSE))) }) test_that("get_study generates a json file", { skip_on_cran() ff <- tempfile() tr <- get_study("pg_719", file_format = "json", file = ff) expect_true(tr) expect_true(grepl("^\\{", readLines(ff, n = 1, warn = FALSE))) }) ############################################################################ ## get_study_tree ## ############################################################################ test_that("get_study_tree returns error when tree doesn't exist", { skip_on_cran() expect_error(get_study_tree("2655", "tree5555")) }) test_that("get_study_tree returns error when study doesn't exist", { skip_on_cran() expect_error(get_study_tree("5555555", "tree555555")) }) test_that("get_study_tree generates nexus file", { skip_on_cran() ff <- tempfile(fileext = ".nex") tt <- get_study_tree("pg_1144", "tree2324", file_format = "nexus", file = ff ) expect_true(tt) expect_true(grepl("^#NEXUS", readLines(ff, n = 1, warn = FALSE))) }) test_that("get_study_tree generates newick file", { skip_on_cran() ff <- tempfile(fileext = ".tre") tt <- get_study_tree("pg_1144", "tree2324", file_format = "newick", file = ff ) expect_true(tt) expect_true(grepl("^\\(", readLines(ff, n = 1, warn = FALSE))) }) test_that("get_study_tree generates json file", { skip_on_cran() ff <- tempfile(fileext = ".json") tt <- get_study_tree("pg_1144", "tree2324", file_format = "json", file = ff ) expect_true(tt) expect_true(grepl("^\\{", readLines(ff, n = 1, warn = FALSE))) }) test_that("get_study_tree returns a phylo object", { skip_on_cran() tt <- get_study_tree("pg_1144", "tree2324", object_format = "phylo") expect_true(inherits(tt, "phylo")) expect_true(length(tt$tip.label) > 1) }) ### Test types of labels with phylo objects test_that("get_study_tree returns a phylo object and ott_id for tip labels", { skip_on_cran() tt <- get_study_tree("pg_1144", "tree2324", object_format = "phylo", tip_label = "ott_id" ) expect_true(inherits(tt, "phylo")) expect_true(length(tt$tip.label) > 1) expect_true(grepl("^[0-9]+$", tt$tip.label[1])) }) test_that("get_study_tree returns a phylo object and ott_taxon_names for tip labels", { skip_on_cran() tt <- get_study_tree("pg_1144", "tree2324", object_format = "phylo", tip_label = "ott_taxon_name" ) expect_true(inherits(tt, "phylo")) expect_true(length(tt$tip.label) > 1) expect_true(sum(!grepl("^[A-Za-z]+(_[a-z]+)?$", tt$tip.label)) < 3) }) test_that("get_study_tree returns a phylo object and original labels for tip labels", { skip_on_cran() tt <- get_study_tree("pg_1144", "tree2324", object_format = "phylo", tip_label = "original_label" ) expect_true(inherits(tt, "phylo")) expect_true(length(tt$tip.label) > 1) expect_equal(sum(!grepl("^[A-Za-z]+_[a-z]+$", tt$tip.label)), 45) }) ### Test types of labels with files (skipping json for now because there is no good way of doing it) test_that("get_study_tree returns an error if file is given but file format is not", { skip_on_cran() expect_error( get_study_tree(study_id = "pg_1144", tree_id = "tree2324", file = "test"), "must be specified" ) }) test_that("get_study_tree returns nexus file and ott_id for tip labels", { skip_on_cran() ff <- tempfile(fileext = ".nex") tt <- get_study_tree("pg_1144", "tree2324", file_format = "nexus", tip_label = "ott_id", file = ff ) expect_true(tt) tr <- rncl::read_nexus_phylo(ff) expect_true(length(tr$tip.label) > 1) expect_true(grepl("^[0-9]+$", tr$tip.label[1])) }) test_that("get_study_tree returns a phylo object and ott_taxon_names for tip labels", { skip_on_cran() ff <- tempfile(fileext = ".tre") tt <- get_study_tree("pg_1144", "tree2324", file_format = "newick", tip_label = "ott_taxon_name", file = ff ) expect_true(tt) tr <- rncl::read_newick_phylo(ff) expect_true(length(tr$tip.label) > 1) expect_true(sum(!grepl("^[A-Za-z]+(_[a-z]+)?$", tr$tip.label)) < 3) }) ############################################################################ ## get_study_subtree ## ############################################################################ test_that("get_study_subtree returns an error when study_id doesn't exist", { skip_on_cran() expect_error(get_study_subtree("pg_55555", "tree55555", subtree_id = "node555555")) }) test_that("get_study_subtree returns an error when tree_id doesn't exist", { skip_on_cran() expect_error(get_study_subtree("pg_1144", "tree55555", subtree_id = "node555555")) }) test_that("get_study_subtree returns an error when the subtree_id is invalid", { skip_on_cran() expect_error(get_study_subtree("pg_1144", "tree2324", "foobar")) }) test_that("get_study_subtree returns a phylo object", { skip_on_cran() tt <- get_study_subtree("pg_420", "tree522", subtree_id = "ingroup", object_format = "phylo" ) sub_tt <- get_study_subtree("pg_420", "tree522", subtree_id = "node208580", object_format = "phylo" ) expect_true(inherits(tt, "phylo")) expect_true(length(tt$tip.label) > 1) expect_true(inherits(sub_tt, "phylo")) expect_true(length(sub_tt$tip.label) > 1) expect_true(length(tt$tip.label) > length(sub_tt$tip.label)) }) test_that("get_study_subtree fails if file name is given but no file format", { skip_on_cran() expect_error(get_study_subtree("pg_420", "tree522", subtree_id = "ingroup", file = "test" ), "must be specified") }) test_that("get_study_subtree returns a nexus file", { skip_on_cran() ff <- tempfile(fileext = ".nex") tt <- get_study_subtree("pg_420", "tree522", subtree_id = "ingroup", file_format = "nexus", file = ff ) expect_true(tt) expect_true(grepl("^#NEXUS", readLines(ff, n = 1, warn = FALSE))) }) test_that("get_study_subtree returns a newick file", { skip_on_cran() ff <- tempfile(fileext = ".tre") tt <- get_study_subtree("pg_420", "tree522", subtree_id = "ingroup", file_format = "newick", file = ff ) expect_true(tt) expect_true(grepl("^\\(", readLines(ff, n = 1, warn = FALSE))) }) test_that("get_study_subtree can deduplicate labels", { skip_on_cran() expect_warning( get_study_subtree( study_id = "pg_710", tree_id = "tree1277", tip_label = "ott_taxon_name", subtree_id = "ingroup", deduplicate = TRUE ), "and have been modified" ) }) test_that("get_study_subtree fails with duplicate labels", { skip_on_cran() expect_error( get_study_subtree( study_id = "pg_710", tree_id = "tree1277", tip_label = "ott_taxon_name", subtree_id = "ingroup", deduplicate = FALSE ), "has already been encountered" ) }) ############################################################################ ## get_study_meta ## ############################################################################ if (identical(Sys.getenv("NOT_CRAN"), "true")) { sm <- get_study_meta("pg_719") } test_that("get_study meta returns a study_meta object", { skip_on_cran() expect_true(inherits(sm, "study_meta")) }) test_that("get_tree_ids method for study_meta", { skip_on_cran() expect_equal(get_tree_ids(sm), c("tree1294", "tree1295", "tree1296")) }) test_that("get_publication method for study_meta", { skip_on_cran() expect_equal(attr(get_publication(sm), "DOI"), "http://dx.doi.org/10.1600/036364411X605092") }) test_that("candidate_for_synth method for study_meta", { skip_on_cran() expect_true(candidate_for_synth(sm) %in% get_tree_ids(sm)) }) test_that("get_study_year method for study_meta", { skip_on_cran() expect_equal(get_study_year(sm), 2011) }) ############################################################################ ## tol_about ## ############################################################################ test_that("tol_about returns class tol_summary", { skip_on_cran() expect_true(inherits(tol_about(), "tol_summary")) }) test_that("study_about", { skip_on_cran() ta <- source_list(tol_about(TRUE)) expect_true(inherits(ta, "data.frame")) expect_true(nrow(ta) > 100) expect_equal(names(ta), c("study_id", "tree_id", "git_sha")) }) ############################################################################ ## studies_find_studies ## ############################################################################ test_that("single study detailed=TRUE", { skip_on_cran() res <- studies_find_studies( property = "ot:studyId", value = "ot_248", detailed = TRUE ) expect_true(inherits(res, "data.frame")) expect_true(inherits(res, "matched_studies")) expect_true(all(names(res) %in% c( "study_ids", "n_trees", "tree_ids", "candidate", "study_year", "title", "study_doi" ))) expect_true(nrow(res) >= 1L) expect_equal(res[["study_ids"]], "ot_248") expect_equal(res[["n_trees"]], "1") expect_equal(res[["candidate"]], "Tr76302") expect_equal(res[["study_year"]], "2014") expect_equal(res[["study_doi"]], "http://dx.doi.org/10.1016/j.cub.2014.06.060") expect_equal(res[["title"]], "'Phylogenomic Resolution of the Class Ophiuroidea Unlocks a Global Microfossil Record'") expect_true(length(attr(res, "metadata")) > 0) expect_true(length(attr(res, "found_trees")) > 0) }) test_that("single study detailed=FALSE", { skip_on_cran() res <- studies_find_studies( property = "ot:studyId", value = "ot_248", detailed = FALSE ) expect_true(inherits(res, "data.frame")) expect_true(inherits(res, "study_ids")) expect_true(inherits(res, "matched_studies")) expect_match(attr(res, "found_trees"), "list of the trees associated") expect_equal(names(res), "study_ids") expect_equal(res[1, 1], "ot_248") expect_equal(nrow(res), 1L) expect_equal(ncol(res), 1L) expect_true(length(attr(res, "metadata")) > 0) expect_true(length(attr(res, "found_trees")) > 0) }) test_that("multiple studies detailed=TRUE", { skip_on_cran() res <- studies_find_studies( property = "ot:focalCladeOTTTaxonName", value = "mammalia", detailed = TRUE ) expect_true(inherits(res, "data.frame")) expect_true(inherits(res, "matched_studies")) expect_true(all(names(res) %in% c( "study_ids", "n_trees", "tree_ids", "candidate", "study_year", "title", "study_doi" ))) expect_true(nrow(res) >= 8L) expect_true(length(attr(res, "metadata")) > 0) expect_true(length(attr(res, "found_trees")) > 0) }) test_that("multiple studies detailed=FALSE", { skip_on_cran() res <- studies_find_studies( property = "ot:focalCladeOTTTaxonName", value = "mammalia", detailed = FALSE ) expect_true(inherits(res, "study_ids")) expect_true(inherits(res, "matched_studies")) expect_true(inherits(res, "data.frame")) expect_equal(ncol(res), 1L) expect_true(nrow(res) >= 8) expect_equal(names(res), "study_ids") expect_true(length(attr(res, "metadata")) > 0) expect_true(length(attr(res, "found_trees")) > 0) }) ############################################################################ ## studies_find_trees ## ############################################################################ test_that("studies_find_trees single study detailed=FALSE", { skip_on_cran() res <- studies_find_trees( property = "ot:studyId", value = "ot_248", detailed = FALSE ) expect_true(inherits(res, "data.frame")) expect_true(inherits(res, "matched_studies")) expect_match(attr(res, "found_trees")[[1]], "Tr76302") expect_equal(names(res), c( "study_ids", "n_matched_trees", "match_tree_ids" )) expect_equal(res[1, 1], "ot_248") expect_equal(nrow(res), 1L) expect_equal(ncol(res), 3L) expect_true(length(attr(res, "metadata")) > 0) expect_true(length(attr(res, "found_trees")) > 0) }) test_that("studies_find_trees single study detailed=TRUE", { skip_on_cran() res <- studies_find_trees( property = "ot:studyId", value = "ot_248", detailed = TRUE ) expect_true(inherits(res, "data.frame")) expect_true(inherits(res, "matched_studies")) expect_equal(names(res), c( "study_ids", "n_trees", "tree_ids", "candidate", "study_year", "title", "study_doi", "n_matched_trees", "match_tree_ids" )) expect_equal(nrow(res), 1L) expect_equal(res[["study_ids"]], "ot_248") expect_equal(res[["n_trees"]], "1") expect_equal(res[["candidate"]], "Tr76302") expect_equal(res[["study_year"]], "2014") expect_equal(res[["study_doi"]], "http://dx.doi.org/10.1016/j.cub.2014.06.060") expect_equal(res[["title"]], "'Phylogenomic Resolution of the Class Ophiuroidea Unlocks a Global Microfossil Record'") expect_equal(res[["tree_ids"]], "Tr76302") expect_true(length(attr(res, "metadata")) > 0) expect_true(length(attr(res, "found_trees")) > 0) }) test_that("studies_find_trees multiple studies detailed=TRUE", { skip_on_cran() res <- studies_find_trees( property = "ot:ottTaxonName", value = "Echinodermata", detailed = TRUE ) expect_true(inherits(res, "data.frame")) expect_true(inherits(res, "matched_studies")) expect_equal(names(res), c( "study_ids", "n_trees", "tree_ids", "candidate", "study_year", "title", "study_doi", "n_matched_trees", "match_tree_ids" )) expect_true(nrow(res) >= 5L) expect_true(length(attr(res, "metadata")) > 0) expect_true(length(attr(res, "found_trees")) > 0) }) test_that("studies_find_trees multiple studies detailed=FALSE", { skip_on_cran() res <- studies_find_trees( property = "ot:ottTaxonName", value = "Echinodermata", detailed = FALSE ) expect_true(inherits(res, "data.frame")) expect_true(inherits(res, "matched_studies")) expect_equal(names(res), c( "study_ids", "n_matched_trees", "match_tree_ids" )) expect_true(nrow(res) >= 5L) expect_true(length(attr(res, "metadata")) > 0) expect_true(length(attr(res, "found_trees")) > 0) }) ############################################################################ ## list_trees ## ############################################################################ test_that("list_trees with studies_find_studies and detailed = FALSE", { skip_on_cran() expect_match( list_trees(studies_find_studies( property = "ot:focalCladeOTTTaxonName", value = "Aves", detailed = FALSE )), "If you want to get a list of the trees associated with the studies" ) }) test_that("list_trees with studies_find_studies and detailed = TRUE", { skip_on_cran() res <- studies_find_studies( property = "ot:focalCladeOTTTaxonName", value = "mammalia", detailed = TRUE ) expect_true(inherits(list_trees(res), "list")) expect_true(length(list_trees(res)) >= 8) expect_true(sum(names(list_trees(res)) %in% c( "pg_2647", "ot_308", "pg_2812", "ot_109", "pg_2582", "pg_1428", "ot_755", "pg_2550" )) >= 8) }) test_that("list_trees with studies_find_trees and detailed=FALSE", { skip_on_cran() res <- studies_find_trees( property = "ot:ottTaxonName", value = "Echinodermata", detailed = FALSE ) lt <- list_trees(res) expect_true(inherits(lt, "list")) expect_true(length(names(lt)) >= 5L) expect_true(all(sapply(lt, length) >= 1L)) }) test_that("list_trees with studies_find_trees and detailed=TRUE", { skip_on_cran() res <- studies_find_trees( property = "ot:ottTaxonName", value = "Echinodermata", detailed = TRUE ) lt <- list_trees(res) expect_true(inherits(lt, "list")) expect_true(length(names(lt)) >= 5L) expect_true(all(sapply(lt, length) >= 1L)) }) } rotl/tests/testthat/test-deduplicate_labels.R0000644000176200001440000000313115132136164021141 0ustar liggesuserstr_string <- " ((A,A),A 1); ((B.1,B,C),B); ((D,D_1),D.1); ((('A 1','A 1'),A.1),'A 1'); ((('A A A','A A A'),A.1),'A 1'); ((((A_1:0.1,B__2:0.1)cats:0.1,(A_1:0.1,A_1:0.1)dogs:0.1)mammals:0.1):0.1)fur:0.1; " file_dup <- tempfile() cat(tr_string, file = file_dup, sep = "\n") ############################################################################ ## parse_newick ## ############################################################################ context("parse_newick") test_that("parse newick works correctly", { prsed_str <- parse_newick(file_dup) expect_true(is.character(prsed_str)) expect_equal(length(prsed_str), 6L) }) ############################################################################ ## deduplicate_labels ## ############################################################################ context("deduplicate_labels") test_that("deduplicate labels works on made up example", { expect_warning( dedup_tr <- deduplicate_labels(file_dup), "Some tip labels were duplicated" ) expect_true(file.exists(dedup_tr)) expect_warning(phylo_tr <- rncl::read_newick_phylo(file = dedup_tr), "Dropping singleton") expect_true(inherits(phylo_tr, "multiPhylo")) expect_equal(phylo_tr[[6]]$tip.label, c("A_1_1", "B__2", "A_1_2", "A_1")) }) test_that("deduplicate labels works on a OTL study", { skip_on_cran() expect_warning( get_study_tree(study_id = "pg_710", tree_id = "tree1277", tip_label = "ott_taxon_name"), "Some tip labels were duplicated" ) }) unlink(file_dup) rotl/tests/testthat/test-api-tnrs.R0000644000176200001440000000400715132136164017074 0ustar liggesuserscontext("tnrs API") ############################################################################ ## .tnrs_match_names ## ############################################################################ test_that("names argument is provided for .tnrs_match_names", { skip_on_cran() expect_error( .tnrs_match_names(NULL, NULL, TRUE, NULL, FALSE), "must supply" ) }) test_that("names argument is character for .tnrs_match_names", { skip_on_cran() expect_error( .tnrs_match_names(TRUE, NULL, TRUE, NULL, FALSE), "character" ) }) test_that("names and ids have the same lengths for .tnrs_match_names", { skip_on_cran() expect_error( .tnrs_match_names("Felis", NULL, TRUE, c("abc", "def"), FALSE), "same length" ) }) test_that("ids must be character for .tnrs_match_names", { skip_on_cran() expect_error( .tnrs_match_names("Felis", NULL, TRUE, TRUE, FALSE), "character" ) }) test_that("do_approximate_matching is logical for .tnrs_match_names", { skip_on_cran() expect_error( .tnrs_match_names("Felis", NULL, "true", NULL, FALSE), "logical" ) }) test_that("include_suppressed is logical for .tnrs_match_names", { skip_on_cran() expect_error( .tnrs_match_names("Felis", NULL, TRUE, NULL, "true"), "logical" ) }) test_that("context_name is character for .tnrs_match_names", { skip_on_cran() expect_error( .tnrs_match_names("Felis", TRUE, TRUE, NULL, FALSE, TRUE), "character" ) }) ############################################################################ ## .tnrs_infer_context ## ############################################################################ test_that("names is not NULL for .tnrs_infer_context", { skip_on_cran() expect_error( .tnrs_infer_context(NULL), "Must supply" ) }) test_that("names is character for .tnrs_infer_context", { skip_on_cran() expect_error( .tnrs_infer_context(TRUE), "character" ) }) rotl/tests/testthat/test-tol.R0000644000176200001440000003537615132136164016152 0ustar liggesusers############################################################################ ## tol_about ## ############################################################################ context("test tol_about (and in turn print.tol_summary)") if (identical(Sys.getenv("NOT_CRAN"), "true")) { req <- tol_about(include_source_list = TRUE) } test_that("Names in object returned are correct/match the docs", { skip_on_cran() expect_true(all(names(req) %in% c( "source_list", "date_created", "root", "num_source_trees", "taxonomy_version", "num_source_studies", "filtered_flags", "synth_id", "source_id_map" ))) expect_true(all(names(req$root) %in% c("taxon", "num_tips", "node_id"))) expect_true(all(names(req$root$taxon) %in% c("tax_sources", "name", "unique_name", "rank", "ott_id"))) expect_true(all(names(source_list(req)) %in% c( "study_id", "tree_id", "git_sha" ))) expect_error( source_list(tol_about(include_source_list = FALSE)), "has been created using" ) expect_true(nrow(source_list(req)) > 1) expect_true(all(grepl("^(ot|pg)", source_list(req)[["study_id"]]))) expect_true(all(grepl("^tr", source_list(req)[["tree_id"]], ignore.case = TRUE))) }) test_that("tol_node tax_rank method", { skip_on_cran() expect_true(inherits( tax_rank(req), c("otl_rank", "list") )) expect_equal(tax_rank(req)[[1]], "no rank") }) test_that("tol_node ott_id method", { skip_on_cran() expect_true(inherits( ott_id(req), c("otl_ott_id", "list") )) expect_equal(ott_id(req)[[1]], 93302) expect_equal(names(ott_id(req)), "cellular organisms") }) test_that("tol_node tax_sources", { skip_on_cran() expect_true(inherits( tax_sources(req), c("otl_tax_sources", "list") )) expect_true(any(grepl("ncbi", tax_sources(req)[[1]]))) expect_equal(names(tax_sources(req)), "cellular organisms") }) test_that("tol_node unique_name", { skip_on_cran() expect_true(inherits( unique_name(req), c("otl_unique_name", "list") )) expect_equal(unique_name(req)[[1]], "cellular organisms") expect_equal(names(unique_name(req)), "cellular organisms") }) test_that("tol_node tax_name", { skip_on_cran() expect_true(inherits( tax_name(req), c("otl_name", "list") )) expect_equal(tax_name(req)[[1]], "cellular organisms") expect_equal(names(tax_name(req)), "cellular organisms") }) ### ott_id() -------------------------------------------------------------------- test_that("taxonomy_taxon_info with ott_id for tol_about", { skip_on_cran() expect_equal( ott_id(req), ott_id(taxonomy_taxon_info(ott_id(req))) ) }) ## can't do that, it's pulling the whole tree ## test_that("taxonomy_subtree with ott_id for tol_about", { ## taxonomy_subtree(ott_id = ott_id(req)) ## }) test_that("tol_node_info with ott_id for tol_about", { skip_on_cran() expect_equal( ott_id(req), ott_id(tol_node_info(ott_id(req))) ) }) ## can't do that, it's pulling the whole tree ## test_that("tol_subtree with ott_id for tol_about", { ## tol_subtree(ott_id = ott_id(req)) ## }) test_that("tol_mrca with ott_id for tol_about", { skip_on_cran() expect_equal( ott_id(req)[1], ott_id(tol_mrca(ott_id(req)))[1] ) }) test_that("tol_induced_subtree with ott_id for tol_about", { skip_on_cran() expect_error( tol_induced_subtree(ott_id(req)), "least two valid" ) }) test_that("taxonomy_mrca with ott_id for tol_about", { skip_on_cran() expect_equal( ott_id(req), ott_id(taxonomy_mrca(ott_id(req))) ) }) ############################################################################ ## tol_subtree ## ############################################################################ context("test tol_subtree") test_that("tol_subtree fails if ott_id is invalid", { skip_on_cran() expect_error(tol_subtree(ott_id = 6666666)) }) test_that("tol_subtree fails if more than one ott_id is provided", { skip_on_cran() expect_error( tol_subtree(ott_id = c(666666, 6666667)), "Please provide a single" ) }) test_that("tol_subtree fails if ott_id doesn't look like a number", { skip_on_cran() expect_error( tol_subtree(ott_id = "111A1111"), "must look like numbers" ) }) test_that("tol_subtree returns a phylo object by default", { skip_on_cran() expect_warning( expect_true(inherits(tol_subtree(ott_id = 81461), "phylo")), "Dropping" ) }) test_that("tol_subtree returns a newick file when providing a file argument", { skip_on_cran() ff <- tempfile(fileext = ".tre") tr <- tol_subtree(ott_id = 81461, file = ff) expect_true(tr) expect_true(grepl("^\\(", readLines(ff, n = 1, warn = FALSE))) }) ############################################################################ ## tol_induced_subtree ## ############################################################################ context("test tol_induced_subtree") test_that("warning for node ids that are not in TOL graph", { skip_on_cran() expect_error( tol_induced_subtree(ott_ids = c(357968, 867416, 939325, 9999999)), "not found" ) }) test_that("error if ott_ids provided don't look like numbers", { skip_on_cran() expect_error( tol_induced_subtree(ott_ids = c("13242", "kitten")), "must look like numbers" ) }) ## test_that("warning for ott ids not in tree", ## ???) test_that("tol_induced_subtree generates a newick file when providing a file argument", { skip_on_cran() ff <- tempfile(fileext = ".tre") tr <- tol_induced_subtree(ott_ids = c(292466, 267845, 292466), file = ff) expect_true(tr) expect_true(grepl("^\\(", readLines(ff, n = 1, warn = FALSE))) }) ############################################################################ ## tol_mrca ## ############################################################################ if (identical(Sys.getenv("NOT_CRAN"), "true")) { birds <- tol_mrca(ott_ids = c(412129, 292466)) hol <- tol_mrca(c(431586, 957434)) mono <- tol_mrca(ott_ids = c(962377, 79623)) } test_that("tol_mrca fails if ott_ids are not numbers", { skip_on_cran() expect_error( tol_mrca(ott_ids = c(13243, "a13415")), "must look like numbers" ) }) test_that("tol_mrca returns a list", { skip_on_cran() expect_true(inherits(birds, "list")) expect_true(inherits(birds, "tol_mrca")) expect_true(all(names(birds) %in% c( "mrca", "source_id_map", "synth_id" ))) }) test_that("methods for tol_mrca where the node is a taxon", { skip_on_cran() expect_true(inherits( tax_sources(hol), c("otl_tax_sources", "list") )) expect_true(inherits( unique_name(hol), c("otl_unique_name", "list") )) expect_true(inherits( tax_name(hol), c("otl_name", "list") )) expect_true(inherits( tax_rank(hol), c("otl_rank", "list") )) expect_true(inherits( ott_id(hol), c("otl_ott_id", "list") )) expect_true(length(tax_sources(hol)[[1]]) > 1) expect_true(any(grepl("worms", tax_sources(hol)[[1]]))) expect_equal(unique_name(hol)[[1]], "Holothuria") expect_equal(tax_name(hol)[[1]], "Holothuria") expect_equal(tax_rank(hol)[[1]], "genus") expect_equal(ott_id(hol)[[1]], 924443) expect_equal(names(tax_sources(hol)), "Holothuria") expect_true(all(names(source_list(hol)) %in% c( "tree_id", "study_id", "git_sha" ))) expect_equal(attr(tax_sources(hol), "taxon_type"), "mrca") }) test_that("methods for tol_mrca where the node is not a taxon", { skip_on_cran() expect_true(inherits(birds, "list")) expect_true(inherits( tax_sources(birds), c("otl_tax_sources", "list") )) expect_true(inherits( unique_name(birds), c("otl_unique_name", "list") )) expect_true(inherits( tax_name(birds), c("otl_name", "list") )) expect_true(inherits( tax_rank(birds), c("otl_rank", "list") )) expect_true(inherits( ott_id(birds), c("otl_ott_id", "list") )) expect_true(length(tax_sources(birds)[[1]]) >= 1) expect_true(any(grepl("ncbi", tax_sources(birds)[[1]]))) expect_equal(unique_name(birds)[[1]], "Aves") expect_equal(tax_name(birds)[[1]], "Aves") expect_equal(tax_rank(birds)[[1]], "class") expect_equal(ott_id(birds)[[1]], 81461) expect_equal(names(ott_id(birds)), "Aves") expect_true(all(names(source_list(birds)) %in% c( "tree_id", "study_id", "git_sha" ))) expect_equal(attr(tax_sources(birds), "taxon_type"), "mrca") }) ### ott_id() -------------------------------------------------------------------- test_that("taxonomy_taxon_info with ott_id for tol_mrca", { skip_on_cran() expect_equal( ott_id(mono)[1], ott_id(taxonomy_taxon_info(ott_id(mono)))[1] ) }) test_that("taxonomy_subtree with ott_id for tol_mrca", { skip_on_cran() tt <- taxonomy_subtree(ott_id = ott_id(mono)) expect_true(length(tt[["tip_label"]]) > 10) expect_true(length(tt[["edge_label"]]) > 7) }) test_that("tol_node_info with ott_id for tol_mrca", { skip_on_cran() expect_equal( ott_id(mono)[1], ott_id(tol_node_info(ott_id(mono)))[1] ) }) test_that("tol_subtree with ott_id for tol_mrca", { skip_on_cran() expect_warning( tt <- tol_subtree(ott_id = ott_id(mono)), "Dropping" ) expect_true(inherits(tt, "phylo")) expect_true(length(tt$tip.label) > 1) expect_true(length(tt$node.label) > 1) }) test_that("tol_mrca with ott_id for tol_mrca", { skip_on_cran() expect_equal( ott_id(mono)[1], ott_id(tol_mrca(ott_id(mono)))[1] ) }) test_that("tol_induced_subtree with ott_id for tol_mrca", { skip_on_cran() expect_error( tol_induced_subtree(ott_id(mono)), "least two valid" ) }) test_that("taxonomy_mrca with ott_id for tol_mrca", { skip_on_cran() expect_equivalent( ott_id(mono), ott_id(taxonomy_mrca(ott_id(mono))) ) }) ############################################################################ ## strip_ott_ids ## ############################################################################ test_that("OTT ids can be striped from tip labels to allow taxon-matching", { skip_on_cran() genera <- c("Perdix", "Cinclus", "Struthio") expect_warning(tr <- tol_induced_subtree(ott_ids = c(102710, 267845, 292466))) expect_true(all(strip_ott_ids(tr$tip.label) %in% genera)) }) ############################################################################ ## tol_node_info ## ############################################################################ if (identical(Sys.getenv("NOT_CRAN"), "true")) { tol_info <- tol_node_info(ott_id = 81461) tol_lin <- tol_node_info(ott_id = 81461, include_lineage = TRUE) tol_mono <- tol_node_info(ott_id = 962396) } test_that("tol node info.", { skip_on_cran() expect_true(all(names(tol_info) %in% c( "node_id", "num_tips", "partial_path_of", "query", "source_id_map", "supported_by", "synth_id", "taxon", "terminal" ))) expect_true(inherits(tol_info, "tol_node")) }) ### methods --------------------------------------------------------------------- test_that("tol_node tax_rank method", { skip_on_cran() expect_true(inherits( tax_rank(tol_info), c("otl_tax_rank", "list") )) expect_equal(tax_rank(tol_info)[[1]], "class") }) test_that("tol_node ott_id method", { skip_on_cran() expect_true(inherits( ott_id(tol_info), c("otl_ott_id", "list") )) expect_equal(ott_id(tol_info)[[1]], 81461) expect_equal(names(ott_id(tol_info)), "Aves") }) test_that("tol_node tax_sources", { skip_on_cran() expect_true(inherits( tax_sources(tol_info), c("otl_tax_sources", "list") )) expect_true(any(grepl("worms", tax_sources(tol_info)[[1]]))) expect_equal(names(tax_sources(tol_info)), "Aves") }) test_that("tol_node unique_name", { skip_on_cran() expect_true(inherits( unique_name(tol_info), c("otl_unique_name", "list") )) expect_equal(unique_name(tol_info)[[1]], "Aves") expect_equal(names(unique_name(tol_info)), "Aves") }) test_that("tol_node tax_name", { skip_on_cran() expect_true(inherits( tax_name(tol_info), c("otl_name", "list") )) expect_equal(tax_name(tol_info)[[1]], "Aves") expect_equal(names(tax_name(tol_info)), "Aves") }) test_that("tol_node source_list method", { skip_on_cran() expect_true(inherits(source_list(tol_info), "data.frame")) expect_true(all(names(source_list(tol_info)) %in% c("study_id", "tree_id", "git_sha"))) }) test_that("tol_node tol_lineage", { skip_on_cran() expect_error(tol_lineage(tol_info), "needs to be created") expect_true(inherits(tol_lineage(tol_lin), "data.frame")) expect_true(nrow(tol_lineage(tol_lin)) > 1) expect_true(all(names(tol_lineage(tol_lin)) %in% c( "node_id", "num_tips", "is_taxon" ))) expect_true(all(grepl("^(ott|mrca)", tol_lineage(tol_lin)[["node_id"]]))) }) test_that("tol_node tax_lineage", { skip_on_cran() expect_error(tax_lineage(tol_info), "needs to be created") expect_true(inherits(tax_lineage(tol_lin), "data.frame")) expect_true(nrow(tax_lineage(tol_lin)) > 1) expect_true(all(names(tax_lineage(tol_lin)) %in% c( "rank", "name", "unique_name", "ott_id" ))) expect_true(any(grepl("no rank", tax_lineage(tol_lin)[["rank"]]))) expect_true(any(grepl("cellular organisms", tax_lineage(tol_lin)[["name"]]))) }) ### ott_id() -------------------------------------------------------------------- test_that("taxonomy_taxon_info with ott_id for tol_info", { skip_on_cran() expect_equivalent( ott_id(tol_mono), ott_id(taxonomy_taxon_info(ott_id(tol_mono))) ) }) test_that("taxonomy_subtree with ott_id for tol_info", { skip_on_cran() tt <- taxonomy_subtree(ott_id = ott_id(tol_mono)) expect_true(length(tt[["tip_label"]]) > 10) expect_true(length(tt[["edge_label"]]) > 7) }) test_that("tol_node_info with ott_id for tol_info", { skip_on_cran() expect_equivalent( ott_id(tol_mono), ott_id(tol_node_info(ott_id(tol_mono))) ) }) test_that("tol_subtree with ott_id for tol_info", { skip_on_cran() expect_warning( tt <- tol_subtree(ott_id = ott_id(tol_mono)), "Dropping" ) expect_true(inherits(tt, "phylo")) expect_true(length(tt$tip.label) > 1) expect_true(length(tt$node.label) > 1) }) test_that("tol_mrca with ott_id for tol_info", { skip_on_cran() expect_equivalent( ott_id(tol_mono), ott_id(tol_mrca(ott_id(tol_mono))) ) }) test_that("tol_induced_subtree with ott_id for tol_info", { skip_on_cran() expect_error( tol_induced_subtree(ott_id(tol_mono)), "least two valid" ) }) test_that("taxonomy_mrca with ott_id for tol_info", { skip_on_cran() expect_equivalent( ott_id(tol_mono), ott_id(taxonomy_mrca(ott_id(tol_mono))) ) }) rotl/tests/testthat/test-taxonomy.R0000644000176200001440000002736115132136164017225 0ustar liggesuserscontext("taxonomy") ############################################################################ ## taxonomy about ## ############################################################################ test_that("taxonomy_about is a list", { skip_on_cran() tt <- taxonomy_about() expect_true(inherits(tt, "list")) }) test_that("taxonomy_about has the names listed in documentation (if it breaks update documentation)", { skip_on_cran() tt <- taxonomy_about() expect_true(all(names(tt) %in% c("weburl", "author", "name", "source", "version"))) }) ############################################################################ ## taxon Info ## ############################################################################ test_that("taxonomy taxon info", { skip_on_cran() tid <- 515698 tt <- taxonomy_taxon_info(tid) expect_equal(tt[[1]][["ott_id"]], tid) expect_true(inherits(tt, "taxon_info")) }) test_that("taxonomy with include_lineage=TRUE", { skip_on_cran() tt <- taxonomy_taxon_info(515698, include_lineage = TRUE) expect_true(exists("lineage", tt[[1]])) expect_true(length(tt[[1]]$lineage) > 1) }) test_that("taxonomy with include_lineage=FALSE", { skip_on_cran() tt <- taxonomy_taxon_info(515698, include_lineage = FALSE) expect_false(exists("lineage", tt[[1]])) }) test_that("taxonomy with include_terminal_descendants=TRUE", { skip_on_cran() tt <- taxonomy_taxon_info(515698, include_terminal_descendants = TRUE) expect_true(exists("terminal_descendants", tt[[1]])) expect_true(length(tt[[1]][["terminal_descendants"]]) > 1) }) test_that("taxonomy with include_terminal_descendants=FALSE", { skip_on_cran() tt <- taxonomy_taxon_info(515698, include_terminal_descendants = FALSE) expect_false(exists("terminal_descendants", tt[[1]])) }) if (identical(Sys.getenv("NOT_CRAN"), "true")) { tid <- c(957430, 337928, 631176) tax_info <- taxonomy_taxon_info(tid) } test_that("taxonomy_taxon tax_rank method", { skip_on_cran() expect_true(inherits( tax_rank(tax_info), c("otl_tax_rank", "list") )) expect_equal( names(tax_rank(tax_info)), c( "Actinopyga", "Acanthaster", "Garrettia (genus in Opisthokonta)" ) ) expect_equal( unlist(unname(tax_rank(tax_info))), rep("genus", 3) ) }) test_that("taxonomy_taxon ott_taxon_name method", { skip_on_cran() expect_true(inherits( tax_name(tax_info), c("otl_tax_info", "list") )) expect_equal( names(tax_name(tax_info)), c( "Actinopyga", "Acanthaster", "Garrettia (genus in Opisthokonta)" ) ) expect_equal( unlist(unname(tax_name(tax_info))), c("Actinopyga", "Acanthaster", "Garrettia") ) }) test_that("taxonomy_taxon synonyms method", { skip_on_cran() expect_true(inherits( synonyms(tax_info), c("otl_synonyms", "list") )) expect_equal( names(synonyms(tax_info)), c( "Actinopyga", "Acanthaster", "Garrettia (genus in Opisthokonta)" ) ) expect_true(all(c("Diamema", "Centrechinus") %in% synonyms(tax_info)[[3]])) }) test_that("taxonomy_taxon is_suppressed method", { skip_on_cran() expect_true(inherits( is_suppressed(tax_info), c("otl_is_suppressed", "list") )) expect_equal( names(is_suppressed(tax_info)), c( "Actinopyga", "Acanthaster", "Garrettia (genus in Opisthokonta)" ) ) expect_equal( unlist(unname(is_suppressed(tax_info))), c(FALSE, FALSE, FALSE) ) }) test_that("taxonomy_taxon flags method", { skip_on_cran() expect_true(inherits( flags(tax_info), c("otl_flags", "list") )) expect_equal( names(flags(tax_info)), c( "Actinopyga", "Acanthaster", "Garrettia (genus in Opisthokonta)" ) ) expect_equal( unlist(unname(flags(tax_info))), NULL ) }) test_that("higher taxonomy method", { skip_on_cran() expect_error(tax_lineage(tax_info), "needs to be created") lg <- tax_lineage(taxonomy_taxon_info(tid, include_lineage = TRUE)) expect_true(inherits(lg, "list")) expect_true(inherits(lg[[1]], "data.frame")) expect_true(all(names(lg[[1]]) %in% c("rank", "name", "unique_name", "ott_id"))) expect_true(any(grepl("no rank", lg[[1]][["rank"]]))) expect_true(any(grep("life", lg[[1]][["name"]]))) }) ### ott_id() -------------------------------------------------------------------- test_that("taxonomy_taxon_info with ott_id for tax_info", { skip_on_cran() expect_equivalent( ott_id(tax_info), ott_id(taxonomy_taxon_info(ott_id(tax_info))) ) }) test_that("taxonomy_subtree with ott_id for tax_info", { skip_on_cran() expect_error( taxonomy_subtree(ott_id = ott_id(tax_info)), "supply one" ) }) test_that("tol_node_info with ott_id for tax_info", { skip_on_cran() expect_error( tol_node_info(ott_id(tax_info)), "provide a single" ) }) test_that("tol_subtree with ott_id for tax_info", { skip_on_cran() expect_error( tol_subtree(ott_id = ott_id(tax_info)), "provide a single" ) }) test_that("tol_mrca with ott_id for tax_info", { skip_on_cran() expect_equivalent( list("Euleutheroza" = 317277), ott_id(tol_mrca(ott_id(tax_info))) ) }) test_that("tol_induced_subtree with ott_id for tax_info", { skip_on_cran() expect_warning( expect_true(inherits( tol_induced_subtree(ott_id(tax_info)), "phylo" )) ) }) test_that("taxonomy_mrca with ott_id for tax_info", { skip_on_cran() expect_equivalent( list("Euleutheroza" = 317277), ott_id(taxonomy_mrca(ott_id(tax_info))) ) }) test_that("ott_id subset works", { skip_on_cran() expect_true(inherits(ott_id(tax_info), "otl_ott_id")) expect_true(inherits(ott_id(tax_info)[1], "otl_ott_id")) expect_true(!is.null(names(ott_id(tax_info)))) }) ############################################################################ ## taxon subtree ## ############################################################################ test_that("taxonomy subtree raw output", { skip_on_cran() tt <- taxonomy_subtree(515698, output_format = "raw") expect_true(inherits(tt, "list")) expect_identical(names(tt), "newick") }) test_that("taxonomy subtree returns warning if file is provided with something else than newick output", { skip_on_cran() expect_warning( taxonomy_subtree(515698, output_format = "raw", file = "/foo/bar"), "ignored" ) }) test_that("taxonomy subtree writes a 'valid' newick file", { skip_on_cran() ff <- tempfile(fileext = ".tre") tt <- taxonomy_subtree(515698, output_format = "newick", file = ff) expect_true(tt) expect_true(grepl("^\\(", readLines(ff, n = 1, warn = FALSE))) }) test_that("taxonomy subtree returns a valid newick string", { skip_on_cran() tt <- taxonomy_subtree(515698, output_format = "newick") expect_true(inherits(ape::read.tree(text = tt), "phylo")) }) test_that("taxonomy subtree returns a valid phylo object", { skip_on_cran() tt <- taxonomy_subtree(515698, output_format = "phylo") expect_true(inherits(tt, "phylo")) }) test_that("taxonomy subtree returns valid internal node names", { skip_on_cran() tt <- taxonomy_subtree(515698, output_format = "taxa") expect_true(inherits(tt, "list")) expect_equal(length(tt), 2) expect_equal(length(tt$tip_label), 32) expect_equal(length(tt$edge_label), 2) }) test_that("taxonomy subtree works if taxa has only 1 descendant", { skip_on_cran() tt <- taxonomy_subtree(ott_id = 3658331, output_format = "taxa") expect_true(inherits(tt, "list")) expect_equal(length(tt), 2) expect_true(inherits(tt$tip_label, "character")) }) ############################################################################ ## taxonomic MRCA ## ############################################################################ if (identical(Sys.getenv("NOT_CRAN"), "true")) { tax_mrca <- taxonomy_mrca(ott_ids = c(515698, 590452, 643717)) tax_mrca_mono <- taxonomy_mrca(ott_ids = c(79623, 962377)) } test_that("taxonomic most recent common ancestor", { skip_on_cran() expect_true(inherits(tax_mrca, "taxon_mrca")) expect_true(inherits(tax_mrca, "list")) }) test_that("mrca tax_rank method", { skip_on_cran() expect_equal( tax_rank(tax_mrca)[1], list("Asterales" = "order") ) }) test_that("mrca tax_name method", { skip_on_cran() expect_equal( tax_name(tax_mrca)[1], list("Asterales" = "Asterales") ) }) test_that("mrca ott_id method", { skip_on_cran() expect_equivalent( ott_id(tax_mrca)[1], list("Asterales" = 1042120) ) expect_true(inherits(ott_id(tax_mrca), "otl_ott_id")) }) test_that("mrca unique_name method", { skip_on_cran() expect_equal( unique_name(tax_mrca)[1], list("Asterales" = "Asterales") ) expect_true(inherits( unique_name(tax_mrca), "otl_unique_name" )) }) test_that("mrca tax_sources method", { skip_on_cran() ## issue with their taxonomy skip("need to fixed upstream") expect_equal( tax_sources(tax_mrca)[1], list( "Asterales" = c( "ncbi:4209", "worms:234044", "gbif:414", "irmng:10011" ) ) ) expect_true(inherits( tax_sources(tax_mrca), "otl_tax_sources" )) }) test_that("mrca is_suppressed method", { skip_on_cran() expect_true(inherits( is_suppressed(tax_mrca), c("otl_is_suppressed", "list") )) expect_equal( is_suppressed(tax_mrca)[1], list("Asterales" = FALSE) ) }) test_that("mrca flags method", { skip_on_cran() expect_true(inherits( flags(tax_mrca), c("otl_flags", "list") )) expect_equal( flags(tax_mrca)[1], list("Asterales" = NULL) ) }) ### ott_id() -------------------------------------------------------------------- test_that("taxonomy_taxon_info with ott_id for tax_mrca", { skip_on_cran() expect_equivalent( ott_id(tax_mrca_mono), ott_id(taxonomy_taxon_info(ott_id(tax_mrca_mono))) ) }) test_that("taxonomy_subtree with ott_id for tax_mrca", { skip_on_cran() tt <- taxonomy_subtree(ott_id = ott_id(tax_mrca_mono)) expect_true(length(tt[["tip_label"]]) > 10) expect_true(length(tt[["edge_label"]]) > 1) }) test_that("tol_node_info with ott_id for tax_mrca", { skip_on_cran() expect_equivalent( ott_id(tax_mrca_mono), ott_id(tol_node_info(ott_id(tax_mrca_mono))) ) }) test_that("tol_subtree with ott_id for tax_mrca", { skip_on_cran() expect_warning( tt <- tol_subtree(ott_id = ott_id(tax_mrca_mono)), "Dropping" ) expect_true(inherits(tt, "phylo")) expect_true(length(tt$tip.label) > 1) expect_true(length(tt$node.label) > 1) }) test_that("tol_mrca with ott_id for tax_mrca", { skip_on_cran() expect_equivalent( ott_id(tax_mrca_mono), ott_id(tol_mrca(ott_id(tax_mrca_mono))) ) }) test_that("tol_induced_subtree with ott_id for tax_mrca", { skip_on_cran() expect_error( tol_induced_subtree(ott_id(tax_mrca_mono)), "least two valid" ) }) test_that("taxonomy_mrca with ott_id for tax_mrca", { skip_on_cran() expect_equivalent( ott_id(tax_mrca_mono), ott_id(taxonomy_mrca(ott_id(tax_mrca_mono))) ) }) test_that("ott_id subset works", { skip_on_cran() expect_true(inherits(ott_id(tax_mrca_mono), "otl_ott_id")) expect_true(inherits(ott_id(tax_mrca_mono)[1], "otl_ott_id")) expect_true(!is.null(names(ott_id(tax_mrca_mono)))) }) ### is_in_tree() --------------------------------------------------------------- if (identical(Sys.getenv("NOT_CRAN"), "true")) { spp <- c("Tyrannosaurus rex", "Velociraptor", "Fabaceae", "Solanaceae") ot_names <- tnrs_match_names(spp) ot_ids <- ott_id(ot_names) } test_that("test is_in_tree", { skip_on_cran() in_tree <- is_in_tree(ot_ids) expect_equal(sum(in_tree), 4) expect_true(all(names(in_tree) %in% spp)) }) rotl/tests/testthat/test-external.R0000644000176200001440000000276215132215267017171 0ustar liggesusersif (FALSE) { context("Study external data") if (identical(Sys.getenv("NOT_CRAN"), "true")) { all_sources <- c( "doi", "pubmed_id", "external_data_url", "popset_ids", "nucleotide_ids" ) all_data <- study_external_IDs("pg_1940") } test_that("We can recover dois, pmids, NCBI IDs", { skip_on_cran() skip("NCBI seems to be down") expect_that(all_data, is_a("study_external_data")) expect_named(all_data) }) test_that("We can handle studies with missing external IDs", { skip_on_cran() skip("NCBI seems to be down") expect_warning( missing_data <- study_external_IDs("ot_97"), "skipping NCBI" ) expect_named(missing_data) expect_that(missing_data, is_a("study_external_data")) expect_equal(sum(is.na(match(all_sources, names(missing_data)))), 2) # we really skipped the NCBI }) test_that("The print functions for external data objects work", { skip_on_cran() skip("NCBI seems to be down") missing_data <- study_external_IDs("ot_91") expect_output(print(all_data), "External data identifiers for study") expect_output(print(missing_data), "External data identifiers for study") }) context("Taxon external data") test_that("We can recover external IDs for Open Tree taxa", { skip_on_cran() skip("NCBI seems to be down") gibbon_IDs <- taxon_external_IDs(712902) expect_that(gibbon_IDs, is_a("data.frame")) expect_equal(names(gibbon_IDs), c("source", "id")) }) } rotl/tests/testthat/test-base.R0000644000176200001440000000331315132136164016250 0ustar liggesuserscontext("base functions") test_that("otl_url returns the correct strings", { skip_on_cran() expect_match(otl_url(dev = TRUE), "^https://devapi.opentreeoflife.org$") expect_match(otl_url(dev = FALSE), "^https://api.opentreeoflife.org$") }) test_that("otl_version", { skip_on_cran() expect_equal(otl_version(), "v3") expect_equal(otl_version("foobar"), "foobar") }) test_that("otl_ottid_from_label", { skip_on_cran() expect_equal( otl_ottid_from_label("flkdjfs_ott314343"), 314343 ) }) test_that("errors that would otherwise not get caught in phylo_from_otl", { expect_error( phylo_from_otl(list(something = "((A, B), C);")), "Cannot find tree" ) expect_error(phylo_from_otl(999), "I don't know how to deal with this format") }) ############################################################################ ## check_numeric ## ############################################################################ test_that("check_numeric works on integer", { expect_true(check_numeric("123")) expect_true(check_numeric(123)) expect_true(check_numeric(123L)) expect_true(check_numeric(list(123))) }) test_that("check_numeric fails if there are characters", { expect_false(check_numeric("A123")) expect_false(check_numeric("1A23")) expect_false(check_numeric("123A")) expect_false(check_numeric("12-3")) }) test_that("check_numeric fails with more exotic types", { expect_false(check_numeric(NA)) expect_false(check_numeric(TRUE)) expect_false(check_numeric(1.23)) expect_false(check_numeric(0.9999999999999)) }) test_that( "check_numeric fails if more than 1 element provided", expect_error(check_numeric(c(1, 2))) ) rotl/tests/testthat/test-match_names.R0000644000176200001440000003224615132136164017624 0ustar liggesuserscontext("match names") hol_ott_id <- 924443 ############################################################################ ## check_args_match_names ## ############################################################################ context("check_args_match_names") if (identical(Sys.getenv("NOT_CRAN"), "true")) { rsp <- tnrs_match_names(names = c("holothuria", "diadema", "fromia")) } test_that( "error generated if object provided isn't created by tnrs_match_names", expect_error( rotl:::check_args_match_names(letters), "was not created using" ) ) test_that("error generated if no argument is provided", { skip_on_cran() expect_error( rotl:::check_args_match_names(rsp), "You must specify" ) }) test_that("error generated if row_number and taxon_name are provided", { skip_on_cran() expect_error( rotl:::check_args_match_names(rsp, row_number = 1, taxon_name = "holothuria" ), "must use only one of " ) }) test_that("error generated if row_number and ott_id are provided", { skip_on_cran() expect_error( rotl:::check_args_match_names(rsp, row_number = 1, ott_id = hol_ott_id ), "must use only one of" ) }) test_that("error generated if ott_id and taxon_name are provided", { skip_on_cran() expect_error( rotl:::check_args_match_names(rsp, taxon_name = "holothuria", ott_id = hol_ott_id ), "must use only one of" ) }) test_that("error generated if row_number is not numeric", { skip_on_cran() expect_error( rotl:::check_args_match_names(rsp, row_number = TRUE), "must be a numeric" ) }) test_that("error generated if ott_id is not numeric", { skip_on_cran() expect_error( rotl:::check_args_match_names(rsp, ott_id = TRUE), "must look like a number" ) }) test_that("error generated if taxon_name is not character", { skip_on_cran() expect_error( rotl:::check_args_match_names(rsp, taxon_name = TRUE), "must be a character" ) }) test_that("error generated if row_number if not one of the row", { skip_on_cran() expect_error( rotl:::check_args_match_names(rsp, row_number = 10), "is not a valid row number" ) expect_error( rotl:::check_args_match_names(rsp, row_number = 1.5), "is not a valid row number" ) expect_error( rotl:::check_args_match_names(rsp, row_number = 0), "is not a valid row number" ) }) test_that("error generated if invalid taxon_name", { skip_on_cran() expect_error( rotl:::check_args_match_names(rsp, taxon_name = "echinodermata"), "Can't find" ) expect_error( rotl:::check_args_match_names(rsp, taxon_name = NA_character_), "Can't find" ) }) test_that("error generated if invalid ott id", { skip_on_cran() expect_error( rotl:::check_args_match_names(rsp, ott_id = 66666), "Can't find" ) }) test_that("error generated if more than 1 value for row_number is provided", { skip_on_cran() expect_error( rotl:::check_args_match_names(rsp, row_number = c(1, 2, 3)), "You must supply a single element" ) }) test_that("error generated if more than 1 value for taxon_name is provided", { skip_on_cran() expect_error( rotl:::check_args_match_names(rsp, taxon_name = c("holothuria", "diadema")), "You must supply a single element" ) }) test_that("error generated if more than 1 value for ott_id is provided", { skip_on_cran() expect_error( rotl:::check_args_match_names(rsp, ott_id = c(5004030, 4930522, 240396)), "only 1 element should be provided" ) }) ############################################################################ ## inspect.match_names ## ############################################################################ context("inspect.match_names") if (identical(Sys.getenv("NOT_CRAN"), "true")) { rsp <- tnrs_match_names(names = c("holothuria", "diadema", "fromia")) expect_warning(rsp_na <- tnrs_match_names(names = c( "diadema", "fluffy", "hemichordata", "escherichia" ))) diadema_ids <- c(4930522, 631176, 643831, 6356093, 4024672) } test_that("correct data is being returned when asked to lookup by taxon name", { skip_on_cran() tt <- inspect(rsp, taxon_name = "diadema")[["ott_id"]] expect_true(all(tt %in% diadema_ids)) }) test_that("correct data is being returned when asked to lookup by ott_id", { skip_on_cran() tt <- inspect(rsp, ott_id = ott_id(rsp)[2])[["ott_id"]] expect_true(all(tt %in% diadema_ids)) }) test_that("correct data is being returned when asked to lookup by row number", { skip_on_cran() tt <- inspect(rsp, row_number = 2)[["ott_id"]] expect_true(all(tt %in% diadema_ids)) }) ## with missing data test_that("correct data is being returned when asked to lookup by taxon name (with missing data)", { skip_on_cran() tt <- inspect(rsp_na, taxon_name = "diadema")[["ott_id"]] expect_true(all(tt %in% diadema_ids)) expect_true(is.na(inspect(rsp_na, taxon_name = "fluffy")[["ott_id"]])) }) test_that("correct data is being returned when asked to lookup by ott_id (with missing data)", { skip_on_cran() tt <- inspect(rsp_na, ott_id = ott_id(rsp)[2])[["ott_id"]] expect_true(all(tt %in% diadema_ids)) }) test_that("correct data is being returned when asked to lookup by row number (with missing data)", { skip_on_cran() tt <- inspect(rsp_na, row_number = 1)[["ott_id"]] expect_true(all(tt %in% diadema_ids)) expect_true(is.na(inspect(rsp_na, row_number = 2)[["ott_id"]])) }) ############################################################################ ## synonyms.match_names ## ############################################################################ context("list_synonym_match_names") if (identical(Sys.getenv("NOT_CRAN"), "true")) { tax_rsp <- c("Holothuria", "Diadema", "Fromia") rsp <- tnrs_match_names(names = tax_rsp) tax_rsp_na <- c("Holothuria", "Diadema", "fluffy", "Fromia") expect_warning(rsp_na <- tnrs_match_names(names = tax_rsp_na)) } test_that("synonyms", { skip_on_cran() tt <- synonyms(rsp) expect_true(inherits(tt, "list")) expect_equal( names(tt), c("Holothuria", "Diadema", "Fromia") ) }) test_that("correct synonyms are being returned when asked to look up by taxon name", { skip_on_cran() tt <- synonyms(rsp, taxon_name = "holothuria") expect_true(any(grepl("^Holothuria", names(tt)))) }) test_that("holothuria is present in each element of the list", { skip_on_cran() tt <- synonyms(rsp, taxon_name = "holothuria") expect_true(all(sapply(tt, function(x) any(grepl("holothuria", x, ignore.case = TRUE))))) expect_true(any(grepl("Halodeima", tt[["Holothuria"]]))) }) test_that("correct synonyms are being returned when asked to look up by row number", { skip_on_cran() tt <- synonyms(rsp, row_number = 1) expect_true(any(grepl("^Holothuria", names(tt)))) expect_true(any(grepl("Halodeima", tt[["Holothuria"]]))) }) test_that("correct synonyms are being returned when asked to look up by ott id", { skip_on_cran() tt <- synonyms(rsp, ott_id = 924443) expect_true(any(grepl("^Holothuria", names(tt)))) expect_true(any(grepl("Halodeima", tt[["Holothuria"]]))) }) ## with missing data test_that("synonyms", { skip_on_cran() tt <- synonyms(rsp_na) expect_true(inherits(tt, "list")) expect_equal( names(tt), c("Holothuria", "Diadema", "Fromia") ) }) test_that("correct synonyms are being returned when asked to look up by taxon name", { skip_on_cran() tt <- synonyms(rsp_na, taxon_name = "holothuria") expect_true(any(grepl("^Holothuria", names(tt)))) expect_true(is.na(synonyms(rsp_na, taxon_name = "fluffy")[[1]])) }) test_that("correct synonyms are being returned when asked to look up by row number", { skip_on_cran() tt <- synonyms(rsp_na, row_number = 1) expect_true(any(grepl("^Holothuria", names(tt)))) expect_true(any(grepl("Halodeima", tt[["Holothuria"]]))) expect_true(is.na(synonyms(rsp_na, row_number = 3)[[1]])) }) test_that("correct synonyms are being returned when asked to look up by ott id", { skip_on_cran() tt <- synonyms(rsp_na, ott_id = 924443) expect_true(any(grepl("^Holothuria", names(tt)))) expect_true(any(grepl("Halodeima", tt[["Holothuria"]]))) }) ############################################################################ ## update.match_names ## ############################################################################ context("update.match_names") if (identical(Sys.getenv("NOT_CRAN"), "true")) { rsp <- tnrs_match_names(names = c("holothuria", "diadema", "fromia")) } test_that("error message if missing both new arguments", { skip_on_cran() expect_error( update(rsp, row_number = 1), "You must specify either" ) }) test_that("error message if both new arguments are provided", { skip_on_cran() expect_error( update(rsp, row_number = 1, new_row_number = 1, new_ott_id = 6666 ), "You must use only" ) }) test_that("error message if wrong new row number provided", { skip_on_cran() expect_error( update(rsp, row_number = 1, new_row_number = 10 ), "is not a valid row number" ) expect_error( update(rsp, row_number = 1, new_row_number = 1.5 ), "is not a valid row number" ) }) test_that("error message if wrong new ott id provided", { skip_on_cran() expect_error( update(rsp, row_number = 1, new_ott_id = 66666 ), "Can't find" ) }) test_that("it works correctly when providing a new row number", { skip_on_cran() new_rsp <- update( rsp, row_number = 2, new_row_number = 2 ) expect_equal( new_rsp[new_rsp$search_string == "diadema", "ott_id"], 4024672 ) }) test_that("it works correctly when providing a new ott id", { skip_on_cran() new_rsp <- update(rsp, row_number = 2, new_ott_id = 631176 ) expect_equal( new_rsp[new_rsp$search_string == "diadema", "ott_id"], 631176L ) }) test_that("it produces warning when trying to update with unmatched name", { skip_on_cran() expect_warning(new_rsp <- update(rsp_na, row_number = 3, new_row_number = 1)) expect_identical(new_rsp, rsp_na) }) ############################################################################ ## flags method ## ############################################################################ context("flags method for class match_names") if (identical(Sys.getenv("NOT_CRAN"), "true")) { tax_rsp <- c( "Tyrannosaurus", "Helicoplacus", "Ctenocystis", "Holothuria", "Echinoidea" ) rsp <- tnrs_match_names(tax_rsp) } test_that("flags with no arguments", { skip_on_cran() flags_rsp <- flags(rsp) expect_equal(length(flags_rsp), 5) expect_equivalent( sapply(flags_rsp, length), c(2, 3, 3, 0, 0) ) }) test_that("flags with row number", { skip_on_cran() flags_rsp <- flags(rsp, 1) expect_true(inherits(flags_rsp, "list")) expect_equal(length(flags_rsp), 1) expect_equal(length(flags_rsp[[1]]), 2) expect_true(inherits(flags_rsp[[1]], "character")) expect_equal(names(flags_rsp), tax_rsp[1]) }) test_that("flags with taxon name", { skip_on_cran() flags_rsp <- flags(rsp, taxon_name = "Tyrannosaurus") expect_true(inherits(flags_rsp, "list")) expect_equal(length(flags_rsp), 1) expect_equal(length(flags_rsp[[1]]), 2) expect_true(inherits(flags_rsp[[1]], "character")) expect_equal(names(flags_rsp), tax_rsp[1]) }) test_that("flags with ott id", { skip_on_cran() flags_rsp <- flags(rsp, ott_id = 664348) expect_true(inherits(flags_rsp, "list")) expect_equal(length(flags_rsp), 1) expect_equal(length(flags_rsp[[1]]), 2) expect_true(inherits(flags_rsp[[1]], "character")) expect_equal(names(flags_rsp), tax_rsp[1]) }) ############################################################################ ## ott_id method ## ############################################################################ context("ott_id method for class match_names") if (identical(Sys.getenv("NOT_CRAN"), "true")) { tax_rsp <- c( "Tyrannosaurus", "Helicoplacus", "Ctenocystis", "Holothuria", "Echinoidea" ) rsp <- tnrs_match_names(tax_rsp) } test_that("ott_id with no arguments", { skip_on_cran() expect_true(inherits(ott_id(rsp), "list")) expect_true(inherits(ott_id(rsp), "otl_ott_id")) expect_equal(names(ott_id(rsp)), tax_rsp) expect_equal(ott_id(rsp)[["Holothuria"]][[1]], hol_ott_id) }) test_that("ott_id with row number", { skip_on_cran() expect_equal(length(ott_id(rsp, 4)), 1) expect_true(inherits(ott_id(rsp, 4), "list")) expect_equivalent(ott_id(rsp, 4)[[1]], hol_ott_id) }) test_that("ott_id with taxon name", { skip_on_cran() expect_equal(length(ott_id(rsp, taxon_name = "Holothuria")), 1) expect_true(inherits(ott_id(rsp, taxon_name = "Holothuria"), "list")) expect_equivalent(ott_id(rsp, taxon_name = "Holothuria")[[1]], hol_ott_id) }) test_that("ott_id with ott id", { skip_on_cran() expect_equal(length(ott_id(rsp, ott_id = hol_ott_id)), 1) expect_true(inherits(ott_id(rsp, ott_id = hol_ott_id), "list")) expect_equivalent(ott_id(rsp, ott_id = hol_ott_id)[[1]], hol_ott_id) }) rotl/tests/test-all.R0000644000176200001440000000005115132136164014242 0ustar liggesusers### library(testthat) test_check("rotl") rotl/MD50000644000176200001440000001307015132225442011543 0ustar liggesusersf057b822e57d898b3fb96afc026903b1 *DESCRIPTION 41ba68f62ff5f58f05f96a0dbd08b282 *LICENSE 06d664adfd9fbca93f72d9400ff8280f *NAMESPACE bfc68bc0bcade0460930d8b7ef0d48cc *NEWS.md aa0c5512f4964c3b6d85e395c963e589 *R/api-collections.R 86061c453d64643efc0cbe908effd59d *R/api-studies.R b3a6b05fc5aa2e15408b2da1e6331dcc *R/api-taxonomy.R 1a7c38aa3ccd21261bcb76e2a871cb12 *R/api-tnrs.R ec27ba53ea6d782485cc3da48804e936 *R/api-tol.R 39209af4d1ef86c2b7003bcf1cfef639 *R/base.R 58ac44eb552c57b7b5ad996a340864f9 *R/deduplicate_labels.R c282a05519f66d3c1cb9bf86041e6202 *R/external_data.R 0606c16b6ddaac8e75772c87909d38b5 *R/is_in_tree.R 3878617ce289c163bb45f85f12b1e47c *R/match_names.R 9b6e56ea7e296aadd1c89c6ee15fa01a *R/methods.R 893f3974b2ec020b5622a05e78f0b8dd *R/rotl-package.R 4287a98267e95dc25eff28255d007199 *R/studies-methods.R 451a2522c0cbdb4b560dd2801c289112 *R/studies-utils.R f55a79a766b3f9d4ad02697abc17f3b3 *R/studies.R d89b501ece90eab10dd2fb8d7232caa3 *R/tax_utils.R 6d90827266175c5ebb665801ea8a410b *R/taxonomy.R 72f6609bc4b83f3e2fbe8cf3fc9f3351 *R/tnrs.R 404502f1cdda25c249b9f8fb254f9022 *R/tol.R ad3ff267fb90ff6fd2dff89df96ce91d *R/tree_to_labels.R b5ff4845bb30a4f13128968802bd436f *R/utils.R 2fb272d2bf67637162f1ed63866779e2 *README.md 0f05d2fc6a35851b2417c8e33d50421a *build/vignette.rds 1ea5dccec217a81c69bc033902ee7688 *inst/CITATION 92ba95c95d8c6054358645634e4b1c9e *inst/doc/data_mashups.Rmd 81e5ca71da4b560bbc96517675780a8c *inst/doc/data_mashups.html af8e73b4164c1324e410342cc12685d3 *inst/doc/meta-analysis.Rmd 6eb4d29d3a762557d889d517b52d729d *inst/doc/meta-analysis.html 9bc821e6b9ee10cba615b39734ac0028 *inst/doc/rotl.Rmd 14574a97029634d233d201e1a22ab95b *inst/doc/rotl.html 09d93b49b2b38f2495761ea86e134006 *inst/extdata/egg.csv d27a70b4799cd0a916da68498ce7c206 *inst/extdata/mcmcglmm_model.rds 5e5eb20ee387ba7192c62e629a3383f2 *inst/extdata/protist_mutation_rates.csv 92d945e47e67be085ec743a29553ea52 *man/figures/logo.svg a4362ce73d3fe17b67f91d2ee52a790e *man/get_study.Rd 9ea4f8a5f6be294fd97bdc457abf6bae *man/get_study_meta.Rd 9fca983d47fba5ba13677709195e04ba *man/get_study_subtree.Rd 591828cdbe98fa325027c8e29a811c2c *man/get_study_tree.Rd 7376b3c8fbc5c5d83c06e9c2756fbb35 *man/is_in_tree.Rd 3d7f4aed52e1e28cee96a6af087ba46c *man/list_trees.Rd e0386442684f2019f009dbd9dc75b9b3 *man/match_names-methods.Rd 86f892122bec47b0709f53c7478c55ab *man/match_names.Rd 0dfd04a5158aa82c246273317e401ba7 *man/rotl.Rd ea8938c2220f0b358930fbaa9b9af738 *man/source_list.Rd 216476335bfc2e2662b67e1f074d12d2 *man/strip_ott_ids.Rd 23971a71f7542c37d227907fa53a6cb2 *man/studies_find_studies.Rd ed222b203dc9608d285cf8ef2d0ca28e *man/studies_find_trees.Rd b52b8d1f1701bf1d7d1b4549d56ccc90 *man/studies_properties.Rd 53b91ea154206361b51b7009446151d5 *man/study_external_IDs.Rd ed749cd0a9f5e22fe03fbf6ad5b62f43 *man/synonyms.match_names.Rd ccb54bd7485bddbe4ee59b4e117a0b21 *man/tax_lineage.Rd db9ed55536b7db87701316de1e5d4493 *man/taxon_external_IDs.Rd 5f58b0e589b08000432acb5656fc2be2 *man/taxonomy-methods.Rd bfa968f3077b514685be218b29fce467 *man/taxonomy_about.Rd 9e413800692050313d47ebf6826df7b9 *man/taxonomy_mrca.Rd e79a02b62df2443b9735df8b73a84b1b *man/taxonomy_subtree.Rd d50ea7664ac97dc3be5e5406b123237c *man/taxonomy_taxon_info.Rd c01395cc8ca421b4e607c110fd714a53 *man/tnrs_contexts.Rd a16c0de937a7de364fbff3a7e1581c44 *man/tnrs_infer_context.Rd 505e5385efa0a7f66806944ec3562979 *man/tnrs_match_names.Rd 77722d24a582203deedc23fed440a9de *man/tol_about.Rd e03f7ad6f93233aec8d33d2c2ad413b1 *man/tol_induced_subtree.Rd 3883e1b54ea67950604698ea7475f5af *man/tol_mrca.Rd 2b2f4d0884d0d00060591db5b6be3c78 *man/tol_node_info.Rd ca675fcf48a69da215dd88bf3a6a8c0b *man/tol_subtree.Rd 2e5f11fd503ac9afd3daeada3fec43ec *tests/test-all.R 5b611ae9eae9a69fd1cafffe4e925de1 *tests/testthat/test-API.R 847fbfea80d45a1a998d6c16eda0502a *tests/testthat/test-api-studies.R dbdaeaa0e8aac809ed49ae0ca436ad77 *tests/testthat/test-api-taxonomy.R 02e21c42744195ba63bcaaefc86c5375 *tests/testthat/test-api-tnrs.R 9bf4fff54c13e1931a77faa40c9e32fe *tests/testthat/test-api-tol.R eefbe86daadd328ef5837146060dce9d *tests/testthat/test-base.R b6b8b458e2e877cd627dedbfb6f7da67 *tests/testthat/test-deduplicate_labels.R 0b94ae2d8de9ad8df87a1e6f73f2772a *tests/testthat/test-external.R c6aebf00170ade5a4572ec53a0e71db0 *tests/testthat/test-match_names.R 0c807fdb420f96c40bc09a5d561c5b2d *tests/testthat/test-studies.R 8eefc6855139bdf7511a70470c057122 *tests/testthat/test-taxonomy.R b06a334ee5e9ca61992453c8fec5d4f6 *tests/testthat/test-tnrs.R f4167dc0933dbc3ef1406a2f3f5e3339 *tests/testthat/test-tol.R 538d0e358c91e50b80fd1cc51233ffea *tests/testthat/test-tree_to_labels.R fb4b19651907e0fdb26e6f4c0581af83 *tests/tree_of_life.json 92ba95c95d8c6054358645634e4b1c9e *vignettes/data_mashups.Rmd 1e442403d805c8f8fe0473056e090a67 *vignettes/data_mashups.Rmd.orig 7b7181f2a45dae90941465a17f54a290 *vignettes/fig-vignettes-birds_in_a_tree-1.png ebf4b8f237add5f156cd3186801bb1b7 *vignettes/fig-vignettes-eggs_in_a_funnel-1.png d1219d2d6e6cb64467eb10fc6632b742 *vignettes/fig-vignettes-subtree-1.png 3001085b123e24bd037666dc94b8e8c1 *vignettes/fig-vignettes-unnamed-chunk-1-1.png 475c9f2a596f0414e3a66d87d3859315 *vignettes/fig-vignettes-unnamed-chunk-16-1.png 38f45d4549effa9cb88ae20534576cf4 *vignettes/fig-vignettes-unnamed-chunk-3-1.png bf830a81e6384f420a1d0b901d7c7127 *vignettes/fig-vignettes-unnamed-chunk-8-1.png af8e73b4164c1324e410342cc12685d3 *vignettes/meta-analysis.Rmd 1dea2ebdb20b4f4b536a754cbfa000c1 *vignettes/meta-analysis.Rmd.orig 9bc821e6b9ee10cba615b39734ac0028 *vignettes/rotl.Rmd e5562a04a1aa84df4b1b313bb499c1f5 *vignettes/rotl.Rmd.orig da8cb33974fa673158fea8ccf2d8bbac *vignettes/vignette.css rotl/R/0000755000176200001440000000000015132136164011435 5ustar liggesusersrotl/R/is_in_tree.R0000644000176200001440000000421515132136164013702 0ustar liggesusers##' Some valid taxonomic names do not occur in the Synthetic ##' Tree. This convenience function allows you to check whether a ##' given Open Tree Taxonomy identifier (OTT id) is in the tree. A taxonomic ##' name may not occur in the synthetic tree because (1) it is an ##' extinct or invalid taxon, or (2) it is part of a group that is not ##' monophyletic in the tree. ##' ##' @title Check that OTT ids occur in the Synthetic Tree ##' @param ott_ids a vector of Open Tree Taxonomy identifiers ##' @param ... additional arguments to customize the API request (see ##' \code{\link{rotl}} package documentation). ##' @return A named logical vector. \code{TRUE} indicates that the OTT ##' id is in the synthetic tree, and \code{FALSE} that it is not. ##' @examples ##' \dontrun{ ##' plant_families <- c("Asteraceae", "Solanaceae", "Poaceae", "Amaranthaceae", ##' "Zamiaceae", "Araceae", "Juncaceae") ##' matched_names <- tnrs_match_names(plant_families) ##' ## This fails because some ott ids are not in the tree ##' ## plant_tree <- tol_induced_subtree(ott_id(matched_names)) ##' ## So let's check which ones are actually in the tree first: ##' in_tree <- is_in_tree(ott_id(matched_names)) ##' ## This now works: ##' plant_tree <- tol_induced_subtree(ott_id(matched_names)[in_tree]) ##' } ##' ##' @export is_in_tree <- function(ott_ids, ...) UseMethod("is_in_tree") ##' @export is_in_tree.otl_ott_id <- function(ott_ids, ...) { in_tree <- vapply(ott_ids, function(ottid) { test <- try(tol_node_info(ottid, ...), silent = TRUE) if (inherits(test, "try-error")) { if (grepl("was not found", test) && grepl(paste0("'ott", ottid, "'"), test)) { } else { warning("something seems off, check your internet connection?") } return(FALSE) } else { ott_id(test)[[1]] == ottid } }, logical(1), USE.NAMES = TRUE) in_tree } ##' @export is_in_tree.default <- function(ott_ids, ...) { chk_ids <- vapply(ott_ids, check_numeric, logical(1)) if (all(chk_ids)) { is_in_tree.otl_ott_id(ott_ids) } else { stop("Invalid format for ott_ids (they should look like numbers)") } } rotl/R/tax_utils.R0000644000176200001440000000413715132136164013601 0ustar liggesusers## all extended-taxon-descriptors have: ## - ott_id ## - name ## - rank ## - unique_name ## - tax_sources ## and they may have ## - flags ## - synonyms ## - is_suppressed ## builds the functions to access the content of the taxon descriptors. ## slot: the name of the list element we need to access ## flatten: if the list element is a list, make it a vector ## optional: is the slot found in all taxon descriptors or only in some tax_access_factory <- function(slot, flatten, optional) { function(tax) { if ((!exists(slot, tax))) { if (optional) { warning("This object doesn't have ", sQuote(slot), call. = FALSE) return(NULL) } else { stop("Invalid taxon object", call. = FALSE) } } else { if (flatten) { unlist(tax[[slot]]) } else { tax[[slot]] } } } } .tax_ott_id <- tax_access_factory("ott_id", flatten = FALSE, optional = FALSE) .tax_name <- tax_access_factory("name", flatten = FALSE, optional = FALSE) .tax_rank <- tax_access_factory("rank", flatten = FALSE, optional = FALSE) .tax_sources <- tax_access_factory("tax_sources", flatten = TRUE, optional = FALSE ) .tax_unique_name <- tax_access_factory("unique_name", flatten = FALSE, optional = FALSE ) ## optional .tax_flags <- tax_access_factory("flags", flatten = TRUE, optional = TRUE) .tax_is_suppressed <- tax_access_factory("is_suppressed", flatten = FALSE, optional = TRUE ) .tax_synonyms <- tax_access_factory("synonyms", flatten = TRUE, optional = TRUE) ## Does the slot element represent a taxon? is_taxon <- function(slot) { if (all(c( "ott_id", "name", "rank", "tax_sources", "unique_name" ) %in% names(slot))) { TRUE } else { FALSE } } ### adds a class to the objects returned by the methods add_otl_class <- function(res, .f) { ## we need a prefix to avoid class name conflict ## apparently the class "name" already exists class(res) <- c( paste0("otl_", as.list(environment(.f))[["slot"]]), class(res) ) res } ##' @export `[.otl_ott_id` <- function(x, i, ...) { r <- NextMethod() class(r) <- class(x) r } rotl/R/api-tnrs.R0000644000176200001440000000354515132136164013324 0ustar liggesusers##' @importFrom jsonlite unbox ##' @importFrom httr content ## Match taxon names .tnrs_match_names <- function(names = NULL, context_name = NULL, do_approximate_matching = TRUE, ids = NULL, include_suppressed = FALSE, ...) { if (is.null(names)) { stop("You must supply a ", sQuote("names"), " argument") } else if (!is.character(names)) { stop( "Argument ", sQuote("names"), " must be of class ", sQuote("character") ) } if (!is.null(ids)) { if (length(ids) != length(names)) { stop( "Arguments ", sQuote("ids"), " and ", sQuote("names"), " must be of the same length" ) } else if (!is.character(ids)) { stop( "Argument ", sQuote("ids"), " must be of class ", sQuote("character") ) } } check_is_flag(do_approximate_matching) check_is_flag(include_suppressed) if (!is.null(context_name)) { check_is_string(context_name) context_name <- jsonlite::unbox(context_name) } q <- list( names = names, context_name = context_name, do_approximate_matching = jsonlite::unbox(do_approximate_matching), ids = ids, include_suppressed = jsonlite::unbox(include_suppressed) ) toKeep <- sapply(q, is.null) q <- q[!toKeep] res <- otl_POST("tnrs/match_names", body = q, ...) res } ##' @importFrom httr content ## Get OpenTree TNRS contexts .tnrs_contexts <- function(...) { res <- otl_POST("tnrs/contexts", body = list(), ...) res } ## Infer taxonomic context from a set of names .tnrs_infer_context <- function(names = NULL, ...) { if (is.null(names)) { stop("Must supply a \'names\' argument") } else if (!is.character(names)) { stop("Argument \'names\' must be of class \"character\"") } q <- list(names = names) res <- otl_POST("tnrs/infer_context", body = q, ...) res } rotl/R/deduplicate_labels.R0000644000176200001440000000256215132136164015372 0ustar liggesusers## Create a vector (character) that contains the NEWICK tree strings ## found in a file parse_newick <- function(file) { trs <- readLines(file, warn = FALSE) trs <- strsplit(trs, split = ";") trs <- sapply(trs, function(x) gsub("^\\s+|\\s+$", "", x)) trs <- unlist(trs) trs <- gsub("\\s", "_", trs) trs <- trs[nchar(trs) > 0] trs } ## Internal function to be used by `deduplicate_labels` that: ## 1. identify duplicated labels ## 2. make them unique ## 3. replace the duplicated labels by their unique counterparts dedup_lbl <- function(tr_str) { tr_lbl <- tree_to_labels(tr_str, remove_quotes = TRUE)$tip_label tr_lbl_unq <- make.unique(tr_lbl, sep = "_") if (!identical(tr_lbl, tr_lbl_unq)) { for (i in seq_along(tr_lbl)) { tr_str <- sub( paste0("([\\(|,]\\'?)\\Q", tr_lbl[i], "\\E(\\'?[:|\\)|,])"), paste0("\\1", tr_lbl_unq[i], "\\2"), tr_str ) } warning("Some tip labels were duplicated and have been modified: ", paste(tr_lbl[duplicated(tr_lbl)], collapse = ", "), call. = FALSE ) } paste0(tr_str, ";") } ## Main function: takes a file with potentially duplicated tip labels ## and reate a new file with unique labels deduplicate_labels <- function(file) { tr_strs <- parse_newick(file) tr_dedup <- sapply(tr_strs, dedup_lbl) tmp_tr <- tempfile() cat(tr_dedup, file = tmp_tr, sep = "\n") tmp_tr } rotl/R/tnrs.R0000644000176200001440000003150715132136164012554 0ustar liggesusers##' Match taxonomic names to the Open Tree Taxonomy. ##' ##' Accepts one or more taxonomic names and returns information about ##' potential matches for these names to known taxa in the Open Tree ##' Taxonomy. ##' ##' This service uses taxonomic contexts to disambiguate homonyms and misspelled ##' names; a context may be specified using the \code{context_name} argument. ##' The default value for \code{context_name} is "All life". If no context is ##' specified (i.e., \code{context_name} is set to \code{NULL}), then the ##' context will be inferred (i.e., the shallowest taxonomic context that ##' contains all unambiguous names in the input). Taxonomic contexts are ##' uncontested higher taxa that have been selected to allow limits to be ##' applied to the scope of TNRS searches (e.g. 'match names only within ##' flowering plants'). Once a context has been identified (either ##' user-specified or inferred), all taxon name matches will performed only ##' against taxa within that context. For a list of available taxonomic ##' contexts, see \code{\link{tnrs_contexts}}. ##' ##' A name is considered unambiguous if it is not a synonym and has ##' only one exact match to any taxon name in the entire taxonomy. ##' ##' When the name search returns multiple matches, the taxon with the highest ##' match score is returned. If the name returned is not the one you intended, ##' you can use the \code{inspect} function to check the other taxa returned by ##' your search. The ##' \href{https://docs.ropensci.org/rotl/articles/rotl.html#how-to-change-the-ott-ids-assigned-to-my-taxa}{Getting ##' Started vignette} has more information on how to do this. ##' ##' Several functions listed in the \sQuote{See also} section can be ##' used to inspect and manipulate the object generated by this ##' function. ##' ##' ##' @title Match names to the Open Tree Taxonomy ##' @param names taxon names to be queried. Currently limited to 10,000 names ##' for exact matches and 2,500 names for approximate matches (character ##' vector) ##' @param context_name name of the taxonomic context to be searched (length-one ##' character vector or \code{NULL}). Must match (case sensitive) one of the ##' values returned by \code{\link{tnrs_contexts}}. Default to "All life". ##' @param do_approximate_matching A logical indicating whether or not to ##' perform approximate string (a.k.a. \dQuote{fuzzy}) matching. Using ##' \code{FALSE} will greatly improve speed. Default, however, is \code{TRUE}. ##' @param ids A vector of ids to use for identifying names. These will be ##' assigned to each name in the names array. If ids is provided, then ids and ##' names must be identical in length. ##' @param include_suppressed Ordinarily, some quasi-taxa, such as incertae ##' sedis buckets and other non-OTUs, are suppressed from TNRS results. If ##' this parameter is true, these quasi-taxa are allowed as possible TNRS ##' results. ##' @param ... additional arguments to customize the API request (see ##' \code{\link{rotl}} package documentation). ##' @return A data frame summarizing the results of the query. The original ##' query output is appended as an attribute to the returned object (and can ##' be obtained using \code{attr(object, "original_response")}). ##' @seealso \code{\link{inspect.match_names}}, ##' \code{\link{update.match_names}}, \code{\link{synonyms.match_names}}. ##' @examples \dontrun{ ##' deuterostomes <- tnrs_match_names(names=c("echinodermata", "xenacoelomorpha", ##' "chordata", "hemichordata")) ##' } ##' @importFrom stats setNames ##' @export tnrs_match_names <- function(names = NULL, context_name = "All life", do_approximate_matching = TRUE, ids = NULL, include_suppressed = FALSE, ...) { if (!is.null(context_name) && !context_name %in% unlist(tnrs_contexts(...))) { stop( "The ", sQuote("context_name"), " is not valid. Check possible values using tnrs_contexts()" ) } ## take care of duplicated names if (any(duplicated(tolower(names)))) { names <- tolower(names) warning("Some names were duplicated: ", paste(sQuote(names[duplicated(names)]), collapse = ", "), ".", call. = FALSE ) names <- unique(names) } res <- .tnrs_match_names( names = names, context_name = context_name, do_approximate_matching = do_approximate_matching, ids = ids, include_suppressed = include_suppressed, ... ) check_tnrs(res) match_ids <- highest_match_score(res) if (!identical(length(res[["results"]]), length(match_ids))) { stop( "The number of matches and the number of 'results' elements should", " be the same." ) } summary_match <- mapply( function(rid, mid) { build_summary_match( res, res_id = rid, match_id = mid, initial_creation = TRUE ) }, seq_along(res[["results"]]), match_ids, SIMPLIFY = FALSE ) ## add taxon names with no maches summary_match <- do.call("rbind", summary_match) summary_match <- as.data.frame(summary_match, stringsAsFactors = FALSE) summary_match$search_string <- gsub("\\\\", "", summary_match$search_string) ## reorder to match original query ordr <- match(tolower(names), tolower(summary_match$search_string)) stopifnot(identical(length(match_ids), length(ordr))) summary_match <- summary_match[ordr, ] match_ids <- match_ids[ordr] summary_match[["approximate_match"]] <- convert_to_logical(summary_match[["approximate_match"]]) summary_match[["is_synonym"]] <- convert_to_logical(summary_match[["is_synonym"]]) summary_match[["flags"]] <- convert_to_logical(summary_match[["flags"]]) has_original_match <- !is.na(summary_match[["number_matches"]]) json_coords <- data.frame( search_string = names, original_order = as.numeric(rownames(summary_match)), match_id = match_ids, has_original_match = has_original_match, row.names = seq_along(names), stringsAsFactors = FALSE ) attr(summary_match, "original_order") <- as.numeric(rownames(summary_match)) attr(summary_match, "original_response") <- res attr(summary_match, "match_id") <- match_ids attr(summary_match, "has_original_match") <- has_original_match attr(summary_match, "json_coords") <- json_coords class(summary_match) <- c("match_names", "data.frame") rownames(summary_match) <- NULL summary_match } ##' @importFrom stats na.omit convert_to_logical <- function(x) { if (all(stats::na.omit(x) %in% c("TRUE", "FALSE"))) { x <- as.logical(x) } else { x } } check_tnrs <- function(req) { no_match <- req[["unmatched_names"]] if (any(vapply(no_match, length, integer(1)) > 0)) { warning( paste(unlist(no_match), collapse = ", "), " are not matched", call. = FALSE ) } } tnrs_columns <- list( "search_string" = function(x) x[["search_string"]], "unique_name" = function(x) .tax_unique_name(x[["taxon"]]), "approximate_match" = function(x) x[["is_approximate_match"]], "score" = function(x) x[["score"]], "ott_id" = function(x) .tax_ott_id(x[["taxon"]]), "is_synonym" = function(x) x[["is_synonym"]], "flags" = function(x) paste(.tax_flags(x[["taxon"]]), collapse = ", ") ) summary_row_factory <- function(res, res_id, match_id, columns = tnrs_columns) { res_address <- res[["results"]][[res_id]][["matches"]][[match_id]] ret <- sapply(columns, function(f) f(res_address)) n_match <- length(res[["results"]][[res_id]][["matches"]]) c(ret, number_matches = n_match) } build_summary_match <- function(res, res_id, match_id = NULL, initial_creation) { if (length(res_id) > 1 && (!is.null(match_id) && length(match_id) > 1)) { stop("Something is wrong. Please contact us.") } build_summary_row <- function(rid) { if (is.null(match_id)) { match_id <- seq_len(length(res[["results"]][[rid]][["matches"]])) } if (identical(length(match_id), 0L) || is.null(res[["results"]][[rid]][["matches"]][match_id][[1]])) { return(build_empty_row(tolower(res[["results"]][[rid]][["name"]]))) } res <- lapply(match_id, function(mid) { summary_row_factory(res, rid, mid) }) if (identical(length(match_id), 1L)) { unlist(res) } else { res } } summary_row <- lapply(res_id, build_summary_row) if (identical(length(res_id), 1L)) { summary_row <- unlist(summary_row, recursive = FALSE) } ## Needed if only 1 row returned if (!inherits(summary_row, "list")) { summary_row <- list(summary_row) } summary_match <- do.call("rbind", summary_row) summary_match <- data.frame(summary_match, stringsAsFactors = FALSE) names(summary_match) <- c(names(tnrs_columns), "number_matches") clean_tnrs_summary(summary_match) } ##' @importFrom stats setNames build_empty_row <- function(x) { no_match_row <- stats::setNames( rep(NA, length(tnrs_columns) + 1), c(names(tnrs_columns), "number_matches") ) no_match_row[1] <- x no_match_row } lowest_ott_id <- function(rsp) { vapply(seq_along(rsp[["results"]]), function(x) { .r <- build_summary_match( res = rsp, res_id = x, match_id = NULL, initial_creation = TRUE ) .r <- .r[(!as.logical(.r[["is_synonym"]])) & !is.na(.r[["flags"]]) & .r[["flags"]] == "", ] if (nrow(.r) > 0) { which.min(.r[["ott_id"]]) } else { 1L } }, integer(1)) } highest_match_score <- function(rsp) { vapply(seq_along(rsp[["results"]]), function(x) { .r <- build_summary_match( res = rsp, res_id = x, match_id = NULL, initial_creation = TRUE ) .r <- .r[(!as.logical(.r[["is_synonym"]])) & !is.na(.r[["flags"]]) & .r[["flags"]] == "", ] if (nrow(.r) > 0) { which.max(.r[["score"]]) } else { 1L } }, integer(1)) } clean_tnrs_summary <- function(summary_match) { summary_match[["approximate_match"]] <- convert_to_logical(summary_match[["approximate_match"]]) summary_match[["score"]] <- as.numeric(summary_match[["score"]]) summary_match[["is_synonym"]] <- convert_to_logical(summary_match[["is_synonym"]]) summary_match[["flags"]] <- convert_to_logical(summary_match[["flags"]]) summary_match[["ott_id"]] <- as.integer(summary_match[["ott_id"]]) summary_match[["number_matches"]] <- as.integer(summary_match[["number_matches"]]) summary_match } ##' This function returns a list of pre-defined taxonomic contexts ##' (i.e. clades) which can be used to limit the scope of tnrs ##' queries. ##' ##' Taxonomic contexts are available to limit the scope of TNRS ##' searches. These contexts correspond to uncontested higher taxa ##' such as 'Animals' or 'Land plants'. This service returns a list ##' containing all available taxonomic context names, which may be ##' used as input (via the \code{context_name} argument in other ##' functions) to limit the search scope of other services including ##' \code{\link{tnrs_match_names}}. ##' @title TNRS contexts ##' @param ... additional arguments to customize the API request (see ##' \code{\link{rotl}} package documentation). ##' @return Returns invisibly a list for each major clades (e.g., ##' animals, microbes, plants, fungi, life) whose elements ##' contains the possible contexts. ##' @export tnrs_contexts <- function(...) { res <- .tnrs_contexts(...) class(res) <- "tnrs_contexts" res } ##' @export print.tnrs_contexts <- function(x, ...) { cat("Possible contexts:\n") lapply(x, function(t) { res <- unlist(t) cat(" ", res[1], "\n") if (length(res) > 1) { lapply(seq(2, length(res), by = 5), function(l) { m <- ifelse(l + 5 <= length(res), l + 4, length(res)) cat(" ", paste(res[l:m], collapse = ", "), "\n") }) } }) } ##' Return a taxonomic context given a list of taxonomic names ##' ##' Find the least inclusive taxonomic context that includes all the ##' unambiguous names in the input set. Unambiguous names are names ##' with exact matches to non-homonym taxa. Ambiguous names (those ##' without exact matches to non-homonym taxa) are indicated in ##' results. ##' ##' @title Infer the taxonomic context from a list of names ##' @param names Vector of taxon names. ##' @param ... additional arguments to customize the API request (see ##' \code{\link{rotl}} package documentation). ##' @return A list including the context name, the context ott id and ##' possibly the names in the query that have an ambiguous ##' taxonomic meaning in the query. ##' @examples ##' \dontrun{ ##' res <- tnrs_infer_context(names=c("Stellula calliope", "Struthio camelus")) ##' } ##' @export tnrs_infer_context <- function(names = NULL, ...) { res <- .tnrs_infer_context(names = names, ...) return(res) } rotl/R/api-studies.R0000644000176200001440000001356715132136164014023 0ustar liggesusers##' @importFrom jsonlite unbox ##' @importFrom httr content ## Return a list of studies from the OpenTree docstore that match a given properties .studies_find_studies <- function(property = NULL, value = NULL, verbose = FALSE, exact = FALSE, ...) { if (!is.logical(verbose)) stop("Argument \'verbose\' should be logical") if (!is.logical(exact)) stop("Argument \'exact\' should be logical") req_body <- list() if (!is.null(property)) { if (!is.character(property)) { stop("Argument \'property\' must be of class \"character\"") } req_body$property <- jsonlite::unbox(property) } else { stop("Must supply a \'property\' argument") } if (!is.null(value)) { if (!is.character(value)) { if (check_numeric(value)) { value <- as.character(value) } else { stop("Argument \'value\' must be of class \"character\"") } } req_body$value <- jsonlite::unbox(value) } else { stop("Must supply a \'value\' argument") } req_body$verbose <- jsonlite::unbox(verbose) req_body$exact <- jsonlite::unbox(exact) res <- otl_POST( path = "studies/find_studies/", body = req_body, ... ) res } ##' @importFrom jsonlite unbox ##' @importFrom httr content ## Return a list of trees from the OpenTree docstore that match a given properties .studies_find_trees <- function(property = NULL, value = NULL, verbose = FALSE, exact = FALSE, ...) { if (!is.logical(verbose)) { stop("Argument \'verbose\' must be of class \"logical\"") } if (!is.logical(exact)) { stop("Argument \'exact\' must be of class \"logical\"") } req_body <- list() if (!is.null(property)) { if (!is.character(property)) { stop("Argument \'property\' must be of class \"character\"") } req_body$property <- jsonlite::unbox(property) } else { stop("Must supply a \'property\' argument") } if (!is.null(value)) { if (!is.character(value)) { if (check_numeric(value)) { value <- as.character(value) } else { stop("Argument \'value\' must be of class \"character\"") } } req_body$value <- jsonlite::unbox(value) } else { stop("Must supply a \'value\' argument") } res <- otl_POST( path = "studies/find_trees", body = c( req_body, verbose = jsonlite::unbox(verbose), exact = jsonlite::unbox(exact) ), ... ) res } ##' @importFrom httr content ## Return a list of properties that can be used to search studies and trees .studies_properties <- function() { res <- otl_POST(path = "studies/properties/", body = list()) res } ##' @importFrom httr content ## Get a study from the OpenTree docstore .get_study <- function(study_id = NULL, format = c("", "nexus", "newick", "nexml", "json"), ...) { if (is.null(study_id)) { stop("Must supply a \'study_id\' argument") } else if (!is.character(study_id)) { if (check_numeric(study_id)) { study_id <- as.character(study_id) } else { stop("Argument \'study_id\' must be of class \"character\"") } } format <- match.arg(format) res <- otl_GET( path = paste("study", paste0(study_id, otl_formats(format)), sep = "/" ), ... ) res } ##' @importFrom httr content ## Get a tree in a study from the OpenTree docstore .get_study_tree <- function(study_id = NULL, tree_id = NULL, format = c("json", "newick", "nexus"), tip_label = c("ot:originallabel", "ot:ottid", "ot:otttaxonname"), ...) { if (is.null(study_id)) { stop("Must supply a \'study_id\' argument") } else if (!is.character(study_id)) { stop("Argument \'study_id\' must be of class \"character\"") } if (is.null(tree_id)) { stop("Must supply a \'tree\' argument") } else if (!is.character(tree_id)) { stop("Argument \'tree\' must be of class \"character\"") } format <- match.arg(format) tip_label <- match.arg(tip_label) tip_label <- paste0("/?tip_label=", tip_label) tree_file <- paste0(tree_id, otl_formats(format), tip_label) res <- otl_GET(path = paste("study", study_id, "tree", tree_file, sep = "/"), ...) res } ##' @importFrom httr content .get_study_meta <- function(study_id, ...) { otl_GET(path = paste("study", study_id, "meta", sep = "/"), ...) } ##' @importFrom httr content .get_study_subtree <- function(study_id, tree_id, subtree_id, format = c("newick", "nexus", "nexml"), tip_label = c("ot:originallabel", "ot:ottid", "ot:otttaxonname"), ...) { if (is.null(study_id)) { stop("Must supply a \'study_id\' argument") } else if (!is.character(study_id)) { stop("Argument \'study_id\' must be of class \"character\"") } if (is.null(tree_id)) { stop("Must supply a \'tree\' argument") } else if (!is.character(tree_id)) { stop("Argument \'tree\' must be of class \"character\"") } if (is.null(subtree_id)) { stop("Must supply a \'subtree\' argument") } else if (!is.character(subtree_id)) { stop("Argument \'subtree\' must be of class \"character\"") } format <- match.arg(format) format <- otl_formats(format) tip_label <- match.arg(tip_label) url_stem <- paste("study", study_id, "subtree", paste0(tree_id, format), sep = "/") res <- otl_GET(path = paste0(url_stem, "?subtree_id=", subtree_id, "&tip_label=", tip_label), ...) res } ### Let's not worry about those for now, as their results could be ### obtained using get_study_tree get_study_otu <- function(study_id, otu = NULL, ...) { otl_GET(path = paste("study", study_id, "otu", otu, sep = "/"), ...) } get_study_otus <- function(study_id, otus, ...) { otl_GET(path = paste("study", study_id, "otu", otus, sep = "/"), ...) } get_study_otumap <- function(study_id, ...) { otl_GET(path = paste("study", study_id, "otumap", sep = "/")) } rotl/R/studies-methods.R0000644000176200001440000000520215132136164014700 0ustar liggesusers ### list_trees ----------------------------------------------------------------- ##' List trees ids in objects returned by ##' \code{\link{studies_find_studies}} and ##' \code{\link{studies_find_trees}} ##' ##' \code{list_trees} returns all trees associated with a particular ##' study when used on an object returned by ##' \code{\link{studies_find_studies}}, but only the trees that match ##' the search criteria when used on objects returned by ##' \code{\link{studies_find_trees}}. ##' ##' @param matched_studies an object created by ##' \code{studies_find_trees} or \code{studies_find_studies}. ##' @param study_id a \code{study_id} listed in the object returned by ##' \code{studies_find_trees} ##' @param ... Currently unused ##' @return \code{list_trees} returns a list of the tree_ids for each ##' study that match the requested criteria. If a \code{study_id} ##' is provided, then only the trees for this study are returned ##' as a vector. ##' @seealso \code{\link{studies_find_studies}} and ##' \code{\link{studies_find_trees}}. The help for these functions ##' have examples demonstrating the use of \code{list_trees}. ##' @export list_trees <- function(matched_studies, ...) UseMethod("list_trees") ##' @rdname list_trees ##' @export list_trees.matched_studies <- function(matched_studies, study_id, ...) { res <- attr(matched_studies, "found_trees") if (missing(study_id)) { res } else { if (is.na(match(study_id, names(res)))) { stop(sQuote(study_id), " isn't a valid id.") } else { res[[study_id]] } } } ##' @export ##' @rdname get_study_meta get_tree_ids <- function(sm) UseMethod("get_tree_ids") ##' @export ##' @rdname get_study_meta get_publication <- function(sm) UseMethod("get_publication") ##' @export ##' @rdname get_study_meta candidate_for_synth <- function(sm) UseMethod("candidate_for_synth") ##' @export ##' @rdname get_study_meta get_study_year <- function(sm) UseMethod("get_study_year") ##' @export ##' @rdname get_study_meta get_tree_ids.study_meta <- function(sm) { unlist(sm[["nexml"]][["treesById"]][[sm[["nexml"]][["^ot:treesElementOrder"]][[1]]]][["^ot:treeElementOrder"]]) } ##' @export ##' @rdname get_study_meta get_publication.study_meta <- function(sm) { pub <- sm[["nexml"]][["^ot:studyPublicationReference"]] attr(pub, "DOI") <- sm[["nexml"]][["^ot:studyPublication"]][["@href"]] pub } ##' @export ##' @rdname get_study_meta candidate_for_synth.study_meta <- function(sm) { unlist(sm[["nexml"]][["^ot:candidateTreeForSynthesis"]]) } ##' @export ##' @rdname get_study_meta get_study_year.study_meta <- function(sm) { sm[["nexml"]][["^ot:studyYear"]] } rotl/R/match_names.R0000644000176200001440000003362115132136164014044 0ustar liggesusers## internal function that match the arguments provided to the correct ## row number in the data frame representing the Open Tree Taxonomy ## for a series of matched names. check_args_match_names <- function(response, row_number, taxon_name, ott_id) { orig_order <- attr(response, "original_order") if (is.null(orig_order)) { stop( sQuote(substitute(response)), " was not created using ", sQuote("tnrs_match_names") ) } if (missing(row_number) && missing(taxon_name) && missing(ott_id)) { stop( "You must specify one of ", sQuote("row_number"), sQuote("taxon_name"), " or ", sQuote("ott_id") ) } else if (!missing(row_number) && missing(taxon_name) && missing(ott_id)) { if (!is.numeric(row_number)) { stop(sQuote("row_number"), " must be a numeric.") } if (!all(row_number %in% orig_order)) { stop(sQuote("row_number"), " is not a valid row number.") } i <- orig_order[row_number] } else if (missing(row_number) && !missing(taxon_name) && missing(ott_id)) { if (!is.character(taxon_name)) { stop(sQuote("taxon_name"), " must be a character.") } i <- orig_order[match(tolower(taxon_name), response$search_string)] if (any(is.na(i))) { stop("Can't find ", taxon_name) } } else if (missing(row_number) && missing(taxon_name) && !missing(ott_id)) { if (!check_numeric(ott_id)) { stop(sQuote("ott_id"), " must look like a number.") } i <- orig_order[match(ott_id, response$ott_id)] if (any(is.na(i))) stop("Can't find ", ott_id) } else { stop( "You must use only one of ", sQuote("row_number"), sQuote("taxon_name"), " or ", sQuote("ott_id"), "." ) } if (length(i) > 1) { stop("You must supply a single element for each argument.") } i } match_row_number <- function(response, row_number, taxon_name, ott_id) { ## all the checks on the validity of the arguments are taken care ## by check_args_match_names() if (missing(row_number) && missing(taxon_name) && missing(ott_id)) { stop( "You must specify one of ", sQuote("row_number"), " ", sQuote("taxon_name"), " ", sQuote("ott_id") ) } else if (!missing(row_number) && (missing(taxon_name) && missing(ott_id))) { i <- row_number } else if (!missing(taxon_name) && (missing(row_number) && missing(ott_id))) { i <- match(tolower(taxon_name), response[["search_string"]]) } else if (!missing(ott_id) && (missing(row_number) && missing(taxon_name))) { i <- match(ott_id, response[["ott_id"]]) } else { stop( "You must use only one of ", sQuote("row_number"), " ", sQuote("taxon_name"), " ", sQuote("ott_id") ) } if (length(i) > 1) { stop("You must supply a single element for each argument.") } i } ##' Taxonomic names may have different meanings in different taxonomic ##' contexts, as the same genus name can be applied to animals and ##' plants for instance. Additionally, the meaning of a taxonomic name ##' may have change throughout its history, and may have referred to a ##' different taxon in the past. In such cases, a given names might ##' have multiple matches in the Open Tree Taxonomy. These functions ##' allow users to inspect (and update) alternative meaning of a given ##' name and its current taxonomic status according to the Open Tree ##' Taxonomy. ##' ##' To inspect alternative taxonomic meanings of a given name, you ##' need to provide the object resulting from a call to the ##' tnrs_match_names function, as well as one of either the row number ##' corresponding to the name in this object, the name itself (as used ##' in the original query), or the ott_id listed for this name. ##' ##' To update one of the name, you also need to provide the row number ##' in which the name to be replaced appear or its ott id. ##' ##' @title Inspect and Update alternative matches for a name returned ##' by tnrs_match_names ##' @param response an object generated by the ##' \code{\link{tnrs_match_names}} function ##' @param row_number the row number corresponding to the name to ##' inspect ##' @param taxon_name the taxon name corresponding to the name to ##' inspect ##' @param ott_id the ott id corresponding to the name to inspect ##' @param ... currently ignored ##' @return a data frame ##' @seealso \code{\link{tnrs_match_names}} ##' @examples ##' \dontrun{ ##' matched_names <- tnrs_match_names(c("holothuria", "diadema", "boletus")) ##' inspect(matched_names, taxon_name="diadema") ##' new_matched_names <- update(matched_names, taxon_name="diadema", ##' new_ott_id = 631176) ##' new_matched_names ##' } ##' @export ##' @rdname match_names inspect.match_names <- function(response, row_number, taxon_name, ott_id, ...) { i <- check_args_match_names(response, row_number, taxon_name, ott_id) j <- match_row_number(response, row_number, taxon_name, ott_id) if (attr(response, "has_original_match")[j]) { res <- attr(response, "original_response") summary_match <- build_summary_match(res, res_id = i, match_id = NULL, initial_creation = FALSE ) } else { summary_match <- response[j, ] } clean_tnrs_summary(summary_match) } ##' @export ##' @rdname match_names inspect <- function(response, ...) UseMethod("inspect") ##' @param object an object created by \code{\link{tnrs_match_names}} ##' @param new_row_number the row number in the output of ##' \code{\link{inspect}} to replace the taxa specified by ##' \code{row_number}, \code{taxon_name}, or \code{ott_id}. ##' @param new_ott_id the ott id of the taxon to replace the taxa ##' specified by \code{row_number}, \code{taxon_name}, or ##' \code{ott_id}. ##' @export ##' @rdname match_names ##' @importFrom stats update update.match_names <- function(object, row_number, taxon_name, ott_id, new_row_number, new_ott_id, ...) { response <- object i <- check_args_match_names(response, row_number, taxon_name, ott_id) j <- match_row_number(response, row_number, taxon_name, ott_id) res <- attr(response, "original_response") if (!attr(response, "has_original_match")[j]) { warning( "There is no match for this name, ", "so there is nothing to replace it with." ) return(response) } tmpRes <- res$results[[i]] if (missing(row_number)) { if (!missing(taxon_name)) { rnb <- match(tolower(taxon_name), response$search_string) } else if (!missing(ott_id)) { rnb <- match(ott_id, response$ott_id) } } else { rnb <- row_number } if (missing(new_row_number) && missing(new_ott_id)) { stop( "You must specify either ", sQuote("new_row_number"), " or ", sQuote("new_ott_id") ) } else if (!missing(new_row_number) && missing(new_ott_id)) { if (!new_row_number %in% seq_len(length(tmpRes$matches))) { stop(sQuote("new_row_number"), " is not a valid row number.") } j <- new_row_number } else if (missing(new_row_number) && !missing(new_ott_id)) { all_ott_id <- sapply( lapply( tmpRes[["matches"]], function(x) x[["taxon"]] ), function(x) .tax_ott_id(x) ) j <- match(new_ott_id, all_ott_id) if (any(is.na(j))) stop("Can't find ", new_ott_id) } else { stop( "You must use only one of ", sQuote("new_row_number"), " or ", sQuote("new_ott_id") ) } if (length(j) > 1) stop("You must supply a single element for each argument") summ_match <- summary_row_factory(res, res_id = i, match_id = j) response[rnb, ] <- summ_match attr(response, "match_id")[rnb] <- j clean_tnrs_summary(response) } ## Access the elements for a given match: ## is_synonym, score, nomenclature_code, is_approximate_match, taxon get_list_element <- function(response, i, list_name) { list_content <- lapply( response[["results"]][[i]][["matches"]], function(x) { x[[list_name]] } ) list_content } match_names_method_factory <- function(list_name) { function(tax, row_number, taxon_name, ott_id, ...) { response <- tax res <- attr(response, "original_response") no_args <- all(c( missing(row_number), missing(taxon_name), missing(ott_id) )) if (no_args) { res_i <- attr(response, "original_order")[attr(response, "has_original_match")] ret <- lapply(res_i, function(i) { get_list_element(res, i, list_name) }) names(ret) <- sapply(res_i, function(i) { get_list_element(res, i, "matched_name")[[1]] }) ## ret is already in the correct order so we can use a sequence ## to extract the correct element ret <- mapply(function(x, i) { ret[[x]][i] }, seq_along(ret), attr(response, "match_id")[attr(response, "has_original_match")]) if (all(sapply(ret, length) == 1)) { ret <- unlist(ret, use.names = TRUE) } } else { i <- check_args_match_names(response, row_number, taxon_name, ott_id) j <- match_row_number(response, row_number, taxon_name, ott_id) if (attr(response, "has_original_match")[j]) { ret <- get_list_element(res, i, list_name)[attr(response, "match_id")[j]] } else { ret <- list( ott_id = NA_character_, name = response[["search_string"]][j], unique_name = NA_character_, rank = NA_character_, tax_sources = NA_character_, flags = NA_character_, synonyms = NA_character_, is_suppressed = NA_character_ ) ret <- list(ret) } } ret } } match_names_taxon_method_factory <- function(.f) { function(tax, row_number, taxon_name, ott_id, ...) { extract_tax_list <- match_names_method_factory("taxon") tax_info <- extract_tax_list(tax, row_number = row_number, taxon_name = taxon_name, ott_id = ott_id ) res <- lapply(tax_info, function(x) .f(x)) names(res) <- vapply(tax_info, function(x) .tax_unique_name(x), character(1)) res <- add_otl_class(res, .f) res } } ##' \code{rotl} provides a collection of functions that allows users ##' to extract relevant information from an object generated by ##' \code{\link{tnrs_match_names}} function. ##' ##' These methods optionally accept one of the arguments ##' \code{row_number}, \code{taxon_name} or \code{ott_id} to retrieve ##' the corresponding information for one of the matches in the object ##' returned by the \code{\link{tnrs_match_names}} function. ##' ##' If these arguments are not provided, these methods can return ##' information for the matches currently listed in the object ##' returned by \code{\link{tnrs_match_names}}. ##' ##' @title \code{ott_id} and \code{flags} for taxonomic names matched ##' by \code{tnrs_match_names} ##' @param tax an object returned by \code{\link{tnrs_match_names}} ##' @param row_number the row number corresponding to the name for ##' which to list the synonyms ##' @param taxon_name the taxon name corresponding to the name for ##' which to list the synonyms ##' @param ott_id the ott id corresponding to the name for which to ##' list the synonyms ##' @param ... currently ignored ##' @return A list of the ott ids or flags for the taxonomic names ##' matched with \code{\link{tnrs_match_names}}, for either one or ##' all the names. ##' @examples ##' \dontrun{ ##' rsp <- tnrs_match_names(c("Diadema", "Tyrannosaurus")) ##' rsp$ott_id # ott id for match currently in use ##' ott_id(rsp) # similar as above but elements are named ##' ##' ## flags() is useful for instance to determine if a taxon is extinct ##' flags(rsp, taxon_name="Tyrannosaurus") ##' } ##' @export ##' @rdname match_names-methods ott_id.match_names <- match_names_taxon_method_factory(.tax_ott_id) ##' @export ##' @rdname match_names-methods flags.match_names <- match_names_taxon_method_factory(.tax_flags) ##' When querying the Taxonomic Name Resolution Services for a ##' particular taxonomic name, the API returns as possible matches all ##' names that include the queried name as a possible synonym. This ##' function allows you to explore other synonyms for an accepted ##' name, and allows you to determine why the name you queried is ##' returning an accepted synonym. ##' ##' To list synonyms for a given taxonomic name, you need to provide ##' the object resulting from a call to the ##' \code{\link{tnrs_match_names}} function, as well as one of either ##' the row number corresponding to the name in this object, the name ##' itself (as used in the original query), or the ott_id listed for ##' this name. Otherwise, the synonyms for all the currently matched ##' names are returned. ##' ##' @title List the synonyms for a given name ##' @param tax a data frame generated by the ##' \code{\link{tnrs_match_names}} function ##' @param row_number the row number corresponding to the name for ##' which to list the synonyms ##' @param taxon_name the taxon name corresponding to the name for ##' which to list the synonyms ##' @param ott_id the ott id corresponding to the name for which to ##' list the synonyms ##' @param ... currently ignored ##' @return a list whose elements are all synonym names (as vectors of ##' character) for the taxonomic names that match the query (the ##' names of the elements of the list). ##' @examples ##' \dontrun{ ##' echino <- tnrs_match_names(c("Diadema", "Acanthaster", "Fromia")) ##' ## These 3 calls are identical ##' synonyms(echino, taxon_name="Acanthaster") ##' synonyms(echino, row_number=2) ##' synonyms(echino, ott_id=337928) ##' } ##' @export synonyms.match_names <- match_names_taxon_method_factory(.tax_synonyms) ##' @export tax_sources.match_names <- match_names_taxon_method_factory(.tax_sources) ##' @export tax_rank.match_names <- match_names_taxon_method_factory(.tax_rank) ##' @export is_suppressed.match_names <- match_names_taxon_method_factory(.tax_is_suppressed) ##' @export unique_name.match_names <- match_names_taxon_method_factory(.tax_unique_name) ##' @export tax_name.match_names <- match_names_taxon_method_factory(.tax_name) rotl/R/methods.R0000644000176200001440000000625715132136164013235 0ustar liggesusers############################################################################ ## methods ## ############################################################################ ##' Methods for dealing with objects containing taxonomic information ##' (Taxonomy, TNRS endpoints) ##' ##' This is the page for the generic methods. See the help pages for ##' \code{\link{taxonomy_taxon_info}}, \code{\link{taxonomy_mrca}}, and ##' \code{\link{tnrs_match_names}} for more information. ##' ##' @title Methods for Taxonomy ##' @param tax an object returned by \code{\link{taxonomy_taxon_info}}, ##' \code{\link{taxonomy_mrca}}, or \code{\link{tnrs_match_names}} ##' @param ... additional arguments (see ##' \code{\link{tnrs_match_names}}) ##' @rdname taxonomy-methods ##' @export tax_rank <- function(tax, ...) { UseMethod("tax_rank") } ##' @export ##' @rdname taxonomy-methods ott_id <- function(tax, ...) { UseMethod("ott_id") } ##' @export ##' @rdname taxonomy-methods synonyms <- function(tax, ...) { UseMethod("synonyms") } ##' @export ##' @rdname taxonomy-methods tax_sources <- function(tax, ...) UseMethod("tax_sources") ##' @export ##' @rdname taxonomy-methods is_suppressed <- function(tax, ...) UseMethod("is_suppressed") ##' @export ##' @rdname taxonomy-methods unique_name <- function(tax, ...) UseMethod("unique_name") ##' @export ##' @rdname taxonomy-methods tax_name <- function(tax, ...) UseMethod("tax_name") ### flags ----------------------------------------------------------------------- ##' @export ##' @rdname match_names-methods flags <- function(tax, ...) UseMethod("flags") ### ##' Retrieve the detailed information for the list of studies used in ##' the Tree of Life. ##' ##' @title List of studies used in the Tree of Life ##' ##' @details This function takes the object resulting from ##' \code{tol_about(study_list = TRUE)}, \code{tol_mrca()}, ##' \code{tol_node_info()}, and returns a data frame listing the ##' \code{tree_id}, \code{study_id} and \code{git_sha} for the ##' studies currently included in the Tree of Life. ##' ##' @param tax a list containing a \code{source_id_map} slot. ##' @param ... additional arguments (currently unused) ##' ##' @return a data frame ##' @export source_list <- function(tax, ...) UseMethod("source_list") ##' Extract the lineage information (higher taxonomy) from an object ##' returned by \code{\link{taxonomy_taxon_info}}. ##' ##' The object passed to this function must have been created using ##' the argument \code{include_lineage=TRUE}. ##' ##' @title Lineage of a taxon ##' @param tax an object created by \code{\link{taxonomy_taxon_info}} ##' using the argument \code{include_lineage=TRUE}. ##' @param ... additional arguments (currently unused). ##' @return A list with one slot per taxon that contains a data frame ##' with 3 columns: the taxonomy rank, the name, and unique name ##' for all taxa included in the lineage of the taxon up to the ##' root of the tree. ##' @rdname tax_lineage ##' @export tax_lineage <- function(tax, ...) UseMethod("tax_lineage") ##' @export ##' @rdname tol_node_info tol_lineage <- function(tax, ...) UseMethod("tol_lineage") rotl/R/api-tol.R0000644000176200001440000001042315132136164013125 0ustar liggesusers##' @importFrom jsonlite unbox ##' @importFrom httr content ## Summary information about the OpenTree Tree of Life .tol_about <- function(include_source_list = FALSE, ...) { check_is_flag(include_source_list) q <- list(include_source_list = jsonlite::unbox(include_source_list)) res <- otl_POST(path = "tree_of_life/about", body = q, ...) res } ##' @importFrom jsonlite unbox ##' @importFrom httr content ## Get summary information about a node in the OpenTree Tree of Life .tol_node_info <- function(ott_id = NULL, node_id = NULL, include_lineage = FALSE, ...) { check_is_flag(include_lineage) if (is.null(ott_id) && is.null(node_id)) { stop("Must provide either ", sQuote("ott_id"), " or ", sQuote("node_id")) } if (!is.null(ott_id) && !is.null(node_id)) { stop("Must provide either ", sQuote("ott_id"), " or ", sQuote("node_id"), ", not both.") } if (!is.null(ott_id)) { ott_id <- check_ott_ids(ott_id) if (length(ott_id) != 1) { stop("Please provide a single ", sQuote("ott_id"), call. = FALSE) } q <- list(ott_id = jsonlite::unbox(ott_id), include_lineage = jsonlite::unbox(include_lineage)) } else { if (!check_valid_node_id(node_id)) { stop("Argument ", sQuote("node_id"), " must look like \'ott123\' or \'mrcaott123ott456\'.") } q <- list(node_id = jsonlite::unbox(node_id), include_lineage = jsonlite::unbox(include_lineage)) } res <- otl_POST(path = "tree_of_life/node_info", body = q, ...) res } ##' @importFrom httr content ## Get the MRCA of a set of nodes .tol_mrca <- function(ott_ids = NULL, node_ids = NULL, ...) { if (is.null(ott_ids) && is.null(node_ids)) { stop("Must provide ", sQuote("ott_ids"), " or ", sQuote("node_ids"), " (or both).") } q <- list() if (!is.null(ott_ids)) { ott_ids <- check_ott_ids(ott_ids) q$ott_ids <- ott_ids } if (!is.null(node_ids)) { check_node_ids(node_ids) q$node_ids <- node_ids } res <- otl_POST(path = "tree_of_life/mrca", body = q, ...) res } # ignoring 'include_lineage' for subtree below. arguson only ##' @importFrom jsonlite unbox ##' @importFrom httr content ## Get a subtree from the OpenTree Tree of Life .tol_subtree <- function(ott_id = NULL, node_id = NULL, label_format = NULL, ...) { if (is.null(ott_id) && is.null(node_id)) { stop("Must provide either ", sQuote("ott_id"), " or ", sQuote("node_id")) } if (!is.null(ott_id) && !is.null(node_id)) { stop("Must provide either ", sQuote("ott_id"), " or ", sQuote("node_id"), ", not both.") } if (!is.null(ott_id)) { ott_id <- check_ott_ids(ott_id) if (length(ott_id) != 1) { stop("Please provide a single ", sQuote("ott_id")) } q <- list(ott_id = jsonlite::unbox(ott_id)) } else { if (!check_valid_node_id(node_id)) { stop("Argument ", sQuote("node_id"), " must look like \'ott123\' or \'mrcaott123ott456\'.") } q <- list(node_id = jsonlite::unbox(node_id)) } if (!is.null(label_format)) { if (!check_label_format(label_format)) { stop( sQuote("label_format"), " must be one of: ", sQuote("name"), ", ", sQuote("id"), ", or ", sQuote("name_and_id") ) } q$label_format <- jsonlite::unbox(label_format) } res <- otl_POST(path = "tree_of_life/subtree", body = q, ...) res } ##' @importFrom httr content ## Get an induced subtree from the OpenTree Tree of Life from a set of nodes .tol_induced_subtree <- function(ott_ids = NULL, node_ids = NULL, label_format = NULL, ...) { if (is.null(ott_ids) && is.null(node_ids)) { stop("Must provide ", sQuote("ott_ids"), " or ", sQuote("node_ids"), " (or both).") } q <- list() if (!is.null(label_format)) { if (!check_label_format(label_format)) { stop( sQuote("label_format"), " must be one of: ", sQuote("name"), ", ", sQuote("id"), ", or ", sQuote("name_and_id") ) } q$label_format <- jsonlite::unbox(label_format) } if (!is.null(ott_ids)) { ott_ids <- check_ott_ids(ott_ids) q$ott_ids <- ott_ids } if (!is.null(node_ids)) { check_node_ids(node_ids) q$node_ids <- node_ids } if ((length(ott_ids) + length(node_ids)) < 2) { stop("At least two valid ", sQuote("ott_ids"), " or ", sQuote("node_ids"), " must be provided.") } res <- otl_POST("tree_of_life/induced_subtree", body = q, ...) res } rotl/R/tol.R0000644000176200001440000006070615132136164012367 0ustar liggesusers .source_list <- function(tax, ...) { if (!exists("source_id_map", tax)) { ## it should only be missing with tol_about when using ## include_source_list=FALSE stop( "Make sure that your object has been created using ", sQuote("tol_about(include_source_list = TRUE)") ) } tt <- lapply(tax[["source_id_map"]], function(x) { c(x[["study_id"]], x[["tree_id"]], x[["git_sha"]]) }) tt <- do.call("rbind", tt) setNames( as.data.frame(tt, stringsAsFactors = FALSE), c("study_id", "tree_id", "git_sha") ) } ##' Basic information about the Open Tree of Life (the synthetic tree) ##' ##' @title Information about the Tree of Life ##' ##' @details Summary information about the current draft tree of life, ##' including information about the list of trees and the taxonomy ##' used to build it. The object returned by \code{tol_about} can ##' be passed to the taxonomy methods (\code{tax_name()}, ##' \code{tax_rank()}, \code{tax_sources()}, \code{ott_id}), to ##' extract relevant taxonomic information for the root of the ##' synthetic tree. ##' ##' @param include_source_list Logical (default = ##' \code{FALSE}). Return an ordered list of source trees. ##' @param tax an object created with a call to \code{tol_about}. ##' @param ... additional arguments to customize the API call (see ##' \code{\link{rotl}} for more information). ##' ##' @return An invisible list of synthetic tree summary statistics: ##' ##' \describe{ ##' ##' \item{date_created}{String. The creation date of the tree.} ##' ##' \item{num_source_studies}{Integer. The number of studies ##' (publications)used as sources.} ##' ##' \item{num_source_trees}{The number of trees used as sources ##' (may be >1 tree per study).} ##' ##' \item{taxonomy_version}{The Open Tree Taxonomy version used ##' as a source.} ##' ##' \item{filtered_flags}{List. Taxa with these taxonomy flags were ##' not used in construction of the tree.} ##' ##' \item{root}{List. Describes the root node:} ##' \describe{ ##' \item{node_id}{String. The canonical identifier of the node.} ##' ##' \item{num_tips}{Numeric. The number of descendant tips.} ##' ##' \item{taxon}{A list of taxonomic properties:} ##' \describe{ ##' \item{ott_id}{Numeric. The OpenTree Taxonomy ID (ott_id).} ##' ##' \item{name}{String. The taxonomic name of the queried node.} ##' ##' \item{unique_name}{String. The string that uniquely ##' identifies the taxon in OTT.} ##' ##' \item{rank}{String. The taxonomic rank of the taxon in OTT.} ##' ##' \item{tax_sources}{List. A list of identifiers for taxonomic ##' sources, such as other taxonomies, that define taxa judged ##' equivalent to this taxon.} ##' } ##' } ##' ##' \item{source_list}{List. Present only if ##' \code{include_source_list} is \code{TRUE}. The sourceid ##' ordering is the precedence order for synthesis, with ##' relationships from earlier trees in the list having priority ##' over those from later trees in the list. See ##' \code{source_id_map} below for study details.} ##' ##' \item{source_id_map}{Named list of lists. Present only if ##' \code{include_source_list} is \code{TRUE}. Names correspond to ##' the \sQuote{sourceids} used in \code{source_list} ##' above. Source trees will have the following properties:} ##' ##' \describe{ ##' \item{git_sha}{String. The git SHA identifying a particular source ##' version.} #' ##' \item{tree_id}{String. The tree id associated with the study id used.} ##' ##' \item{study_id}{String. The study identifier. Will typically include ##' a prefix ("pg_" or "ot_").} ##' } ##' ##' \item{synth_id}{The unique string for this version of the tree.} ##' } ##' @seealso \code{\link{source_list}} to explore the list of studies ##' used in the synthetic tree (see example). ##' ##' @examples ##' \dontrun{ ##' res <- tol_about() ##' tax_sources(res) ##' ott_id(res) ##' studies <- source_list(tol_about(include_source_list=TRUE))} ##' @rdname tol_about ##' @export tol_about <- function(include_source_list = FALSE, ...) { res <- .tol_about(include_source_list = include_source_list, ...) class(res) <- c("tol_summary", class(res)) res } ##' @export print.tol_summary <- function(x, ...) { cat("\nOpenTree Synthetic Tree of Life.\n\n") cat("Tree version: ", x$synth_id, "\n", sep = "") cat("Taxonomy version: ", x$taxonomy, "\n", sep = "") cat("Constructed on: ", x$date_created, "\n", sep = "") cat("Number of terminal taxa: ", x$root$num_tips, "\n", sep = "") cat("Number of source trees: ", x$num_source_trees, "\n", sep = "") cat("Number of source studies: ", x$num_source_studies, "\n", sep = "") cat("Source list present: ", ifelse(exists("source_list", x), "true", "false"), "\n", sep = "") cat("Root taxon: ", x$root$taxon$name, "\n", sep = "") cat("Root ott_id: ", x$root$taxon$ott_id, "\n", sep = "") cat("Root node_id: ", x$root$node_id, "\n", sep = "") } tol_about_method_factory <- function(.f) { function(tax, ...) { res <- list(.f(tax[["root"]][["taxon"]])) names(res) <- .tax_unique_name(tax[["root"]][["taxon"]]) res <- add_otl_class(res, .f) res } } ##' @export ##' @rdname tol_about tax_rank.tol_summary <- tol_about_method_factory(.tax_rank) ##' @export ##' @rdname tol_about tax_sources.tol_summary <- tol_about_method_factory(.tax_sources) ##' @export ##' @rdname tol_about unique_name.tol_summary <- tol_about_method_factory(.tax_unique_name) ##' @export ##' @rdname tol_about tax_name.tol_summary <- tol_about_method_factory(.tax_name) ##' @export ##' @rdname tol_about ott_id.tol_summary <- tol_about_method_factory(.tax_ott_id) ##' @export ##' @rdname source_list source_list.tol_summary <- .source_list ##' Most Recent Common Ancestor for a set of nodes ##' ##' @title MRCA of taxa from the synthetic tree ##' ##' @details Get the MRCA of a set of nodes on the current synthetic ##' tree. Accepts any combination of node ids and ott ids as ##' input. Returns information about the most recent common ##' ancestor (MRCA) node as well as the most recent taxonomic ##' ancestor (MRTA) node (the closest taxonomic node to the MRCA ##' node in the synthetic tree; the MRCA and MRTA may be the same ##' node). If they are the same, the taxonomic information will be ##' in the \code{mrca} slot, otherwise they will be in the ##' \code{nearest_taxon} slot of the list. If any of the specified ##' nodes is not in the synthetic tree an error will be returned. ##' ##' Taxonomic methods (\code{tax_sources()}, \code{ott_id()}, ##' \code{unique_name()}, ...) are available on the objects ##' returned by \code{tol_mrca()}. If the MRCA node is MRTA, the ##' name of the object returned by these methods will start with ##' \sQuote{ott}, otherwise it will start with \sQuote{mrca}. ##' ##' @param ott_ids Numeric vector. The ott ids for which the MRCA is desired. ##' @param node_ids Character vector. The node ids for which the MRCA is desired. ##' @param tax an object returned by \code{tol_mrca()}. ##' @param ... additional arguments to customize the API call (see ##' \code{\link{rotl}} for more information). ##' ##' @return An invisible list of the MRCA node properties: ##' ##' \describe{ ##' ##' \item{mrca}{List of node properties.} ##' ##' \describe{ ##' \item{node_id}{String. The canonical identifier of the node.} ##' ##' \item{num_tips}{Numeric. The number of descendant tips.} ##' ##' \item{taxon}{A list of taxonomic properties. Only returned if ##' the queried node is a taxon. (If the node is not a taxon, a ##' \code{nearest_taxon} list is returned (see below)).} ##' ##' \describe{ ##' \item{ott_id}{Numeric. The OpenTree Taxonomy ID (ottID).} ##' ##' \item{name}{String. The taxonomic name of the queried node.} ##' ##' \item{unique_name}{String. The string that uniquely ##' identifies the taxon in OTT.} ##' ##' \item{rank}{String. The taxonomic rank of the taxon in OTT.} ##' ##' \item{tax_sources}{List. A list of identifiers for taxonomic ##' sources, such as other taxonomies, that define taxa judged ##' equivalent to this taxon.} ##' } ##' ##' The following properties list support/conflict for the node across ##' synthesis source trees. All properties involve sourceid keys and ##' nodeid values (see \code{source_id_map} below) Not all properties are ##' are present for every node. ##' ##' \item{partial_path_of}{List. The edge below this synthetic tree node ##' is compatible with the edge below each of these input tree nodes (one ##' per tree). Each returned element is reported as sourceid:nodeid.} ##' ##' \item{supported_by}{List. Input tree nodes (one per tree) that support ##' this synthetic tree node. Each returned element is reported as ##' sourceid:nodeid.} ##' ##' \item{terminal}{List. Input tree nodes (one per tree) that are equivalent ##' to this synthetic tree node (via an exact mapping, or the input tree ##' terminal may be the only terminal descended from this synthetic tree node. ##' Each returned element is reported as sourceid:nodeid.} ##' ##' \item{conflicts_with}{Named list of lists. Names correspond to ##' sourceid keys. Each list contains input tree node ids (one or more per tree) ##' that conflict with this synthetic node.} ##' } ##' ##' \item{nearest_taxon}{A list of taxonomic properties of the nearest rootward ##' taxon node to the MRCA node. Only returned if the MRCA node is a not taxon ##' (otherwise the \code{taxon} list above is returned).} ##' ##' \describe{ ##' \item{ott_id}{Numeric. The OpenTree Taxonomy ID (ottID).} ##' ##' \item{name}{String. The taxonomic name of the queried node.} ##' ##' \item{unique_name}{String. The string that uniquely ##' identifies the taxon in OTT.} ##' ##' \item{rank}{String. The taxonomic rank of the taxon in OTT.} ##' ##' \item{tax_sources}{List. A list of identifiers for taxonomic ##' sources, such as other taxonomies, that define taxa judged ##' equivalent to this taxon.} ##' } ##' ##' \item{source_id_map}{Named list of lists. Names correspond to the ##' sourceid keys used in the support/conflict properties of the \code{mrca} ##' list above. Source trees will have the following properties:} ##' ##' \describe{ ##' \item{git_sha}{The git SHA identifying a particular source ##' version.} ##' ##' \item{tree_id}{The tree id associated with the study id used.} ##' ##' \item{study_id}{The study identifier. Will typically include ##' a prefix ("pg_" or "ot_").} ##' } ##' The only sourceid that does not correspond to a source tree is the taxonomy, ##' which will have the name "ott"+`taxonomy_version`, and the value is the ##' ott_id of the taxon in that taxonomy version. "Taxonomy" will only ever ##' appear in \code{supported_by}. ##' ##' } ##' ##' @examples ##' \dontrun{ ##' birds_mrca <- tol_mrca(ott_ids=c(412129, 119214)) ##' ott_id(birds_mrca) ##' tax_sources(birds_mrca) ##' } ##' @rdname tol_mrca ##' @export tol_mrca <- function(ott_ids = NULL, node_ids = NULL, ...) { res <- .tol_mrca(ott_ids = ott_ids, node_ids = node_ids, ...) class(res) <- c("tol_mrca", class(res)) return(res) } ##' @export print.tol_mrca <- function(x, ...) { cat("\nOpenTree MRCA node.\n\n") cat("Node id: ", x$mrca$node_id, "\n", sep = "") cat("Number of terminal descendants: ", x$mrca$num_tips, "\n", sep = "") if (is_taxon(x[["mrca"]][["taxon"]])) { cat("Is taxon: TRUE\n") cat("Name: ", x$mrca$taxon$name, "\n", sep = "") cat("ott id: ", x$mrca$taxon$ott_id, "\n", sep = "") } else { cat("Is taxon: FALSE\n") cat("Nearest taxon:\n") cat(" Name: ", x$nearest_taxon$name, "\n", sep = "") cat(" ott id: ", x$nearest_taxon$ott_id, "\n", sep = "") } } tol_mrca_method_factory <- function(.f) { function(tax, ...) { if (is_taxon(tax[["mrca"]][["taxon"]])) { res <- list(.f(tax[["mrca"]][["taxon"]])) names(res) <- .tax_unique_name(tax[["mrca"]][["taxon"]]) attr(res, "taxon_type") <- "mrca" } else { res <- list(.f(tax[["nearest_taxon"]])) names(res) <- .tax_unique_name(tax[["nearest_taxon"]]) attr(res, "taxon_type") <- "nearest_taxon" } res <- add_otl_class(res, .f) res } } ##' @export ##' @rdname tol_mrca tax_sources.tol_mrca <- tol_mrca_method_factory(.tax_sources) ##' @export ##' @rdname tol_mrca unique_name.tol_mrca <- tol_mrca_method_factory(.tax_unique_name) ##' @export ##' @rdname tol_mrca tax_name.tol_mrca <- tol_mrca_method_factory(.tax_name) ##' @export ##' @rdname tol_mrca tax_rank.tol_mrca <- tol_mrca_method_factory(.tax_rank) ##' @export ##' @rdname tol_mrca ott_id.tol_mrca <- tol_mrca_method_factory(.tax_ott_id) ##' @export ##' @rdname tol_mrca source_list.tol_mrca <- .source_list ##' Extract a subtree from the synthetic tree from an Open Tree node id. ##' ##' @title Extract a subtree from the synthetic tree ##' ##' @details Given a node, return the subtree of the synthetic tree descended ##' from that node. The start node may be specified using either a node id ##' or an ott id, but not both. If the specified node is not in the ##' synthetic tree an error will be returned. There is a size limit of ##' 25000 tips for this method. ##' ##' @param ott_id Numeric. The ott id of the node in the tree that should ##' serve as the root of the tree returned. ##' @param node_id Character. The node id of the node in the tree that should ##' serve as the root of the tree returned. ##' @param label_format Character. Defines the label type; one of ##' \dQuote{\code{name}}, \dQuote{\code{id}}, or ##' \dQuote{\code{name_and_id}} (the default). ##' @param file If specified, the function will write the subtree to a ##' file in newick format. ##' @param ... additional arguments to customize the API call (see ##' \code{\link{rotl}} for more information). ##' ##' @return If no value is specified to the \code{file} argument ##' (default), a phylogenetic tree of class \code{phylo}. ##' Otherwise, the function returns invisibly a logical indicating ##' whether the file was successfully created. ##' ##' @examples ##' \dontrun{ ##' res <- tol_subtree(ott_id=241841)} ##' @export tol_subtree <- function(ott_id = NULL, node_id = NULL, label_format = NULL, file, ...) { res <- .tol_subtree( ott_id = ott_id, node_id = node_id, label_format = label_format, ... ) if (!missing(file)) { unlink(file) cat(res$newick, file = file) return(invisible(file.exists(file))) } else { phy <- phylo_from_otl(res) return(phy) } } ##' Return the induced subtree on the synthetic tree that relates a list of nodes. ##' ##' @title Subtree from the Open Tree of Life ##' ##' @details Return a tree with tips corresponding to the nodes identified in ##' the input set that is consistent with the topology of the current ##' synthetic tree. This tree is equivalent to the minimal subtree ##' induced on the draft tree by the set of identified nodes. ##' ##' @param ott_ids Numeric vector. OTT ids indicating nodes to be used as tips ##' in the induced tree. ##' @param node_ids Character vector. Node ids indicating nodes to be used as ##' tips in the induced tree. ##' @param label_format Character. Defines the label type; one of ##' \dQuote{\code{name}}, \dQuote{\code{id}}, or \dQuote{\code{name_and_id}} ##' (the default). ##' @param file If specified, the function will write the subtree to a file in ##' newick format. ##' @param ... additional arguments to customize the API call (see ##' \code{\link{rotl}} for more information). ##' ##' @return If no value is specified to the \code{file} argument ##' (default), a phylogenetic tree of class \code{phylo}. ##' ##' Otherwise, the function returns invisibly a logical indicating ##' whether the file was successfully created. ##' ##' Note that the tree returned when specifying a file name with the ##' \code{file} argument is the \dQuote{raw} Newick string returned by Open ##' Tree of Life. This string contains singleton nodes, and therefore will ##' be different from the tree returned as a \code{phylo} object which will ##' not contain these singleton nodes. ##' ##' @examples ##' \dontrun{ ##' ## Result as a `phylo` object ##' res <- tol_induced_subtree(ott_ids = c(292466, 267845, 316878, 102710)) ##' ##' ## Raw Newick string from Open Tree of Life ##' tree_file <- tempfile(fileext = ".tre") ##' tol_induced_subtree(ott_ids = c(292466, 267845, 316878, 102710), ##' file=tree_file) ##' ##' } ##' @export tol_induced_subtree <- function(ott_ids = NULL, node_ids = NULL, label_format = NULL, file, ...) { res <- .tol_induced_subtree( ott_ids = ott_ids, node_ids = node_ids, label_format = label_format, ... ) if (!missing(file)) { unlink(file) cat(res$newick, file = file) return(file.exists(file)) } else { phy <- phylo_from_otl(res) return(phy) } } ##' Strip OTT ids from tip labels ##' @param tip_labels a character vector containing tip labels (most ##' likely the \code{tip.label} element from a tree returned by ##' \code{\link{tol_induced_subtree}} ##' @param remove_underscores logical (defaults to FALSE). If set to ##' TRUE underscores in tip labels are converted to spaces ##' @return A character vector containing the contents of ##' \code{tip_labels} with any OTT ids removed. ##' ##' @examples ##' \dontrun{ ##' genera <- c("Perdix", "Setophaga", "Cinclus", "Struthio") ##' tr <- tol_induced_subtree(ott_ids=c(102710, 285198, 267845, 292466)) ##' tr$tip.label %in% genera ##' tr$tip.label <- strip_ott_ids(tr$tip.label) ##' tr$tip.label %in% genera ##' } ##' @export strip_ott_ids <- function(tip_labels, remove_underscores = FALSE) { stripped <- sub("_ott\\d+$", "", tip_labels) if (remove_underscores) { return(gsub("_", " ", stripped)) } stripped } ##' Get summary information about a node in the synthetic tree ##' ##' @title Node info ##' ##' @details Returns summary information about a node in the graph. The ##' node of interest may be specified using either a node id or an ##' taxon id, but not both. If the specified node or OTT id is not ##' in the graph, an error will be returned. ##' ##' If the argument \code{include_lineage=TRUE} is used, you can ##' use \code{tax_lineage()} or \code{tol_lineage} to return the ##' taxonomic information or the node information for all the ##' ancestors to this node, down to the root of the tree. ##' ##' ##' @param ott_id Numeric. The OpenTree taxonomic identifier. ##' @param node_id Character. The OpenTree node identifier. ##' @param include_lineage Logical (default = FALSE). Whether to return the ##' lineage of the node from the synthetic tree. ##' @param ... additional arguments to customize the API call (see ##' ?rotl for more information) ##' ##' @return \code{tol_node_info} returns an invisible list of summary ##' information about the queried node: ##' ##' \describe{ ##' ##' \item{node_id}{String. The canonical identifier of the node.} ##' ##' \item{num_tips}{Numeric. The number of descendant tips.} ##' ##' \item{partial_path_of}{List. The edge below this synthetic tree node ##' is compatible with the edge below each of these input tree nodes (one ##' per tree). Each returned element is reported as sourceid:nodeid.} ##' ##' \item{query}{ The node id that resolved to this node. This can differ ##' from the node_id field if the query id is not canonical. } ##' ##' \item{taxon}{A list of taxonomic properties. Only returned if ##' the queried node is a taxon. Each source has:} ##' ##' \describe{ ##' \item{ott_id}{Numeric. The OpenTree Taxonomy ID (ottID).} ##' ##' \item{name}{String. The taxonomic name of the queried node.} ##' ##' \item{unique_name}{String. The string that uniquely ##' identifies the taxon in OTT.} ##' ##' \item{rank}{String. The taxonomic rank of the taxon in OTT.} ##' ##' \item{tax_sources}{List. A list of identifiers for taxonomic ##' sources, such as other taxonomies, that define taxa judged ##' equivalent to this taxon.} ##' } ##' ##' The following properties list support/conflict for the node across ##' synthesis source trees. All properties involve sourceid keys and ##' nodeid values (see \code{source_id_map} below). ##' ##' \item{supported_by}{List. Input tree nodes (one per tree) that support ##' this synthetic tree node. Each returned element is reported as ##' sourceid:nodeid.} ##' ##' \item{terminal}{List. Input tree nodes (one per tree) that are ##' equivalent to this synthetic tree node (via an exact mapping, or the ##' input tree terminal may be the only terminal descended from this ##' synthetic tree node. Each returned element is reported as ##' sourceid:nodeid.} ##' ##' \item{conflicts_with}{Named list of lists. Names correspond to ##' sourceid keys. Each list contains input tree node ids (one or more per ##' tree) that conflict with this synthetic node.} ##' } ##' ##' \code{tol_lineage} and \code{tax_lineage} return data ##' frames. \code{tol_lineage} indicate for each ancestor its ##' node identifier, the number of tips descending from that ##' node, and whether it corresponds to a taxonomic level. ##' ##' @examples ##' \dontrun{ ##' birds <- tol_node_info(ott_id=81461, include_lineage=TRUE) ##' source_list(birds) ##' tax_rank(birds) ##' ott_id(birds) ##' tax_lineage(birds) ##' tol_lineage(birds)} ##' @export tol_node_info <- function(ott_id = NULL, node_id = NULL, include_lineage = FALSE, ...) { res <- .tol_node_info( ott_id = ott_id, node_id = node_id, include_lineage = include_lineage, ... ) class(res) <- c("tol_node", class(res)) return(res) } tol_node_method_factory <- function(.f) { function(tax, ...) { if (exists("taxon", tax)) { res <- setNames( list(.f(tax[["taxon"]])), .tax_unique_name(tax[["taxon"]]) ) } else if (exists("node_id", tax)) { res <- setNames(tax[["node_id"]], tax[["node_id"]]) } else { res <- NA } res <- add_otl_class(res, .f) res } } ##' @export print.tol_node <- function(x, ...) { cat("\nOpenTree node.\n\n") cat("Node id: ", x$node_id, "\n", sep = "") cat("Number of terminal descendants: ", x$num_tips, "\n", sep = "") if (is_taxon(x[["taxon"]])) { cat("Is taxon: TRUE\n") cat("Name: ", x$taxon$name, "\n", sep = "") cat("Rank: ", x$taxon$rank, "\n", sep = "") cat("ott id: ", x$taxon$ott_id, "\n", sep = "") } else { cat("Is taxon: FALSE\n") } } ##' @export ##' @param tax an object returned by \code{tol_node_info}. ##' @rdname tol_node_info tax_rank.tol_node <- tol_node_method_factory(.tax_rank) ##' @export ##' @rdname tol_node_info tax_sources.tol_node <- tol_node_method_factory(.tax_sources) ##' @export ##' @rdname tol_node_info unique_name.tol_node <- tol_node_method_factory(.tax_unique_name) ##' @export ##' @rdname tol_node_info tax_name.tol_node <- tol_node_method_factory(.tax_name) ##' @export ##' @rdname tol_node_info ott_id.tol_node <- tol_node_method_factory(.tax_ott_id) ##' @export ##' @rdname tol_node_info source_list.tol_node <- .source_list ##' @export ##' @rdname tol_node_info tax_lineage.tol_node <- function(tax, ...) { check_lineage(tax) lg <- lapply(tax[["lineage"]], function(x) { if (exists("taxon", x)) { build_lineage(x[["taxon"]]) } else { NULL } }) lg <- do.call("rbind", lg) as.data.frame(lg, stringsAsFactors = FALSE) } ##' @export ##' @rdname tol_node_info tol_lineage.tol_node <- function(tax, ...) { check_lineage(tax) lg <- lapply(tax[["lineage"]], function(x) { c( "node_id" = x[["node_id"]], "num_tips" = x[["num_tips"]], "is_taxon" = exists("taxon", x) ) }) lg <- do.call("rbind", lg) as.data.frame(lg, stringsAsFactors = FALSE) } rotl/R/tree_to_labels.R0000644000176200001440000000265515132136164014553 0ustar liggesusers## Function to extract tip and edge labels from newick formatted strings ## useful when the tree is too small to be read in by ape/rncl. ## tr needs to be a newick formatted tree string ## - missing tips are removed (OK for OTL as it won't happen) tree_to_labels <- function(tr, remove_quotes = TRUE) { n_right <- unlist(gregexpr("\\)", tr)) n_left <- unlist(gregexpr("\\(", tr)) if (n_right[1] == -1) n_right <- 0 else n_right <- length(n_right) if (n_left[1] == -1) n_left <- 0 else n_left <- length(n_left) if (!identical(n_right, n_left)) { stop("invalid newick string, numbers of ( and ) don't match") } ## remove white spaces tr <- gsub("\\s+", "", tr) ## remove branch lengths tr <- gsub(":[0-9]+(\\.[0-9]+)?", "", tr) ## TODO?: remove comments if (n_right < 1) { ## if only 1 tip tip_lbl <- gsub(";$", "", tr) edge_lbl <- character(0) } else { ## extract edge labels edge_lbl <- unlist(strsplit(tr, ")")) edge_lbl <- grep("^[^\\(]", edge_lbl, value = T) edge_lbl <- gsub("(,|;).*$", "", edge_lbl) edge_lbl <- edge_lbl[nzchar(edge_lbl)] ## extract tips tip_lbl <- unlist(strsplit(tr, ",")) tip_lbl <- gsub("^\\(*", "", tip_lbl) tip_lbl <- gsub("\\).*$", "", tip_lbl) tip_lbl <- tip_lbl[nzchar(tip_lbl)] } if (remove_quotes) { tip_lbl <- gsub("^(\\\"|\\\')(.+)(\\\'|\\\")$", "\\2", tip_lbl) } list(tip_label = tip_lbl, edge_label = edge_lbl) } rotl/R/api-taxonomy.R0000644000176200001440000000421715132136164014211 0ustar liggesusers##' @importFrom httr content ## Summary information about the OpenTree Taxonomy (OTT) .taxonomy_about <- function(...) { res <- otl_POST(path = "/taxonomy/about", body = list(), ...) res } ##' @importFrom jsonlite unbox ##' @importFrom httr content ## Information about an OpenTree Taxonomy (OTT) taxon .taxonomy_taxon_info <- function(ott_id = NULL, include_children = FALSE, include_lineage = FALSE, include_terminal_descendants = FALSE, ...) { ott_id <- check_ott_ids(ott_id) if (length(ott_id) > 1) { stop("Must only supply one ", sQuote("ott_id"), " argument") } check_is_flag(include_children) check_is_flag(include_lineage) check_is_flag(include_terminal_descendants) q <- list( ott_id = jsonlite::unbox(ott_id), include_children = jsonlite::unbox(include_children), include_lineage = jsonlite::unbox(include_lineage), include_terminal_descendants = jsonlite::unbox(include_terminal_descendants) ) res <- otl_POST(path = "/taxonomy/taxon_info", body = q, ...) res } ##' @importFrom jsonlite unbox ##' @importFrom httr content ## Get a subtree from the OpenTree Taxonomy (OTT) taxonomic tree .taxonomy_subtree <- function(ott_id = NULL, label_format = NULL, ...) { ott_id <- check_ott_ids(ott_id) if (length(ott_id) > 1) { stop("Must only supply one ", sQuote("ott_id"), " argument") } q <- list(ott_id = jsonlite::unbox(ott_id)) if (!is.null(label_format)) { if (!check_label_format(label_format)) { stop( sQuote("label_format"), " must be one of: ", sQuote("name"), ", ", sQuote("id"), ", or ", sQuote("name_and_id") ) } q$label_format <- jsonlite::unbox(label_format) } res <- otl_POST(path = "/taxonomy/subtree", body = q, ...) res } ##' @importFrom httr content ## Get the most recent common ancestor (MRCA) from nodes in the OpenTree Taxonomy (OTT) .taxonomy_mrca <- function(ott_ids = NULL, ...) { ott_ids <- check_ott_ids(ott_ids) q <- list(ott_ids = ott_ids) res <- otl_POST(path = "/taxonomy/mrca", body = q, ...) res } rotl/R/utils.R0000644000176200001440000000144015132136164012717 0ustar liggesusersrotl_is_flag <- function(x) { identical(length(x), 1L) && rlang::is_bare_logical(x) && !is.na(x) } rotl_is_string <- function(x) { identical(length(x), 1L) && rlang::is_bare_character(x) && !is.na(x) } check_factory <- function(f, x, arg_name, msg) { if (f(x)) { return(TRUE) } stop( paste0( "Argument ", sQuote(arg_name), msg ), call. = FALSE ) } check_is_flag <- function(x) { arg_name <- deparse(substitute(x)) check_factory( rotl_is_flag, x, arg_name, " is not a flag (a length one logical vector)." ) } check_is_string <- function(x) { arg_name <- deparse(substitute(x)) check_factory( rotl_is_string, x, arg_name, " is not a string (a length one character vector)." ) } rotl/R/base.R0000644000176200001440000001341215132136164012473 0ustar liggesusersotl_base_url <- function(dev = FALSE) { if (dev) { return("devapi.opentreeoflife.org") } "api.opentreeoflife.org" } otl_url <- function(dev = FALSE) { paste0("https://", otl_base_url(dev)) } otl_version <- function(version) { if (missing(version)) { return("v3") } else { return(version) } } ##' @importFrom rlang interrupt is_otl_online <- function(dev = FALSE) { is_online <- !is.null(curl::nslookup(otl_base_url(dev), error = FALSE)) if (!is_online) { message("No internet connection or the Open Tree of Life's API is down.") rlang::interrupt() } } # Take a request object and return list (if JSON) or plain text (if another # type) ##' @importFrom httr content ##' @importFrom jsonlite fromJSON otl_parse <- function(req) { if (grepl("application/json", req[["headers"]][["content-type"]])) { return(jsonlite::fromJSON(httr::content(req, "text", encoding = "UTF-8"), simplifyVector = FALSE)) } txt <- httr::content(req, as = "text", encoding = "UTF-8") if (identical(txt, "")) { stop("No output to parse; check your query.", call. = FALSE) } txt } otl_check_error <- function(cont) { if (is.list(cont)) { if (exists("description", cont)) { if (exists("Error", cont$description)) { stop(paste("Error: ", cont$description$error, "\n", sep = "")) } else if (exists("message", cont)) { stop(paste("Message: ", cont$descrption$message, "\n", sep = "")) } } } } ## Check and parse result of query ##' @importFrom rlang interrupt otl_check <- function(req) { early_stop <- function(m) { message(m) rlang::interrupt() } tryCatch({ if (!req$status_code < 400) { msg <- otl_parse(req) stop("HTTP failure: ", req$status_code, "\n", msg, call. = FALSE) } desc <- otl_parse(req) otl_check_error(desc) desc }, error = function(e) early_stop(e), warning = function(w) early_stop(w) ) } ##' @importFrom httr GET otl_GET <- function(path, url = otl_url(...), otl_v = otl_version(...), ...) { is_otl_online() req <- httr::GET(url, path = paste(otl_v, path, sep = "/"), ...) otl_check(req) } ##' @importFrom jsonlite toJSON ##' @importFrom httr POST otl_POST <- function(path, body, url = otl_url(...), otl_v = otl_version(...), ...) { is_otl_online() stopifnot(is.list(body)) body_json <- ifelse(length(body), jsonlite::toJSON(body), "") req <- httr::POST(url, path = paste(otl_v, path, sep = "/"), body = body_json, ... ) otl_check(req) } otl_formats <- function(format) { switch(tolower(format), "nexus" = ".nex", "newick" = ".tre", "nexml" = ".nexml", "json" = ".json", "" ) # fall through is no extension = nex(j)son } ## Strip all characters except the ottId from a OpenTree label (internal or terminal) otl_ottid_from_label <- function(label) { return(as.numeric(gsub("(.+[ _]ott)([0-9]+)", "\\2", label))) } ##' @importFrom rncl read_newick_phylo phylo_from_otl <- function(res, dedup = FALSE) { if (is.list(res)) { if (!is.null(res$newick)) { tree <- res$newick } else if (!is.null(res$subtree)) { tree <- res$subtree } else { stop("Cannot find tree") } } else if (is.character(res)) { tree <- res } else { stop("I don't know how to deal with this format.") } if (grepl("\\(", tree)) { fnm <- tempfile() cat(tree, file = fnm) if (!dedup) { phy <- rncl::read_newick_phylo(fnm) } else { dedup_tr <- deduplicate_labels(fnm) phy <- rncl::read_newick_phylo(dedup_tr) unlink(dedup_tr) } unlink(fnm) } else { phy <- tree_to_labels(tree)$tip_label } return(phy) } nexml_from_otl <- function(res) { if (!requireNamespace("RNeXML", quietly = TRUE)) { stop("The RNeXML package is needed to use the nexml file format") } fnm <- tempfile() cat(res, file = fnm) phy <- RNeXML::nexml_read(x = fnm) unlink(fnm) phy } ## check if the argument provided looks like a number (can be coerced ## to integer/numeric). check_numeric <- function(x) { if (is.null(x)) { return(FALSE) } if (length(x) != 1) { stop("only 1 element should be provided") } if (!is.numeric(x)) { x <- as.character(x) if (any(is.na(x))) { return(FALSE) } return(grepl("^[0-9]+$", x)) } else { return(x %% 1 == 0) } } ## Check that ott_ids are not NULL, not NAs and look like numbers check_ott_ids <- function(ott_ids) { if (!is.null(ott_ids)) { if (inherits(ott_ids, "otl_ott_id")) { ## convert objects returned by ott_id method to a vector ott_ids <- unlist(ott_ids) } if (any(is.na(ott_ids))) { stop("NAs are not allowed") } if (!all(sapply(ott_ids, check_numeric))) { stop(sQuote("ott_ids"), " must look like numbers.") } } else { stop("You must supply some OTT ids.") } ott_ids } ## all nodes have a node_id (character, e.g. "ott12345" or "mrcaott123ott456") check_valid_node_id <- function(x) { if (length(x) != 1) { stop("only 1 element should be provided") } if (!is.character(x)) { return(FALSE) } if (grepl("^mrcaott\\d+ott\\d+", x) || grepl("^ott\\d+", x)) { return(TRUE) } else { return(FALSE) } } check_node_ids <- function(node_ids) { if (!is.null(node_ids)) { if (!is.character(node_ids)) { stop("Argument ", sQuote("node_ids"), " must be of type character.") } if (any(is.na(node_ids))) { stop("NAs are not allowed") } if (!all(sapply(node_ids, check_valid_node_id))) { stop(sQuote("node_ids"), " must look like \'ott123\' or \'mrcaott123ott456\'.") } } } # node labels for tree_of_life subtree and induced_subtree # might also be useful for taxonomy queries check_label_format <- function(x) { if (x %in% c("name", "id", "name_and_id")) { return(TRUE) } else { return(FALSE) } } rotl/R/rotl-package.R0000644000176200001440000000354315132140102014121 0ustar liggesusers##' An Interface to the Open Tree of Life API ##' ##' The Open Tree of Life is an NSF funded project that is generating ##' an online, comprehensive phylogenetic tree for 1.8 million ##' species. \code{rotl} provides an interface that allows you to ##' query and retrieve the parts of the tree of life that is of ##' interest to you. ##' ##' \code{rotl} provides function to most of the end points the API ##' provides. The documentation of the API is available at: ##' \url{https://github.com/OpenTreeOfLife/opentree/wiki/Open-Tree-of-Life-APIs} ##' ##' @section Customizing API calls: ##' ##' All functions that use API end points can take 2 arguments to ##' customize the API call and are passed as \code{...} arguments. ##' ##' \describe{ ##' ##' \item{ \code{otl_v}}{This argument controls which version ##' of the API your call is using. The default value for this ##' argument is a call to the non-exported function ##' \code{otl_version()} which returns the current version of the ##' Open Tree of Life APIs (v2).} ##' ##' \item{ \code{dev_url}}{This argument controls whether to use ##' the development version of the API. By default, \code{dev_url} ##' is set to \code{FALSE}, using \code{dev_url = TRUE} in your ##' function calls will use the development version.} ##' ##' } ##' ##' For example, to use the development version of the API, you ##' could use: \code{tnrs_match_names("anas", dev_url=TRUE)} ##' ##' Additional arguments can also be passed to the ##' \code{\link[httr]{GET}} and \code{\link[httr]{POST}} methods. ##' ##' ##' @section Acknowledgments: ##' ##' This package was started during the Open Tree of Life Hackathon ##' organized by the OpenTree of Life, the NESCent Hackathon ##' Interoperability Phylogenetic group, and Arbor. ##' ##' @name rotl ##' @import ape "_PACKAGE" NULL rotl/R/studies.R0000644000176200001440000005107415132136164013247 0ustar liggesusers##' Return the list of study properties that can be used to search ##' studies and trees used in the synthetic tree. ##' ##' The list returned has 2 elements \code{tree_properties} and ##' \code{studies_properties}. Each of these elements lists additional ##' arguments to customize the API request properties that can be used ##' to search for trees and studies that are contributing to the ##' synthetic tree. The definitions of these properties are available ##' from ##' \url{https://github.com/OpenTreeOfLife/phylesystem-api/wiki/NexSON} ##' ##' @title Properties of the Studies ##' @param ... additional arguments to customize the API request (see ##' \code{\link{rotl}} package documentation). ##' @return A list of the study properties that can be used to find ##' studies and trees that are contributing to the synthetic tree. ##' @seealso \code{\link{studies_find_trees}} ##' @export ##' @examples ##' \dontrun{ ##' all_the_properties <- studies_properties() ##' unlist(all_the_properties$tree_properties) ##' } studies_properties <- function(...) { res <- .studies_properties(...) lapply(res, unlist) } ##' Return the identifiers of studies that match given properties ##' ##' @title Find a Study ##' @param exact Should exact matching be used? (logical, default ##' \code{FALSE}) ##' @param property The property to be searched on (character) ##' @param value The property value to be searched on (character) ##' @param detailed If \code{TRUE} (default), the function will return ##' a data frame that summarizes information about the study (see ##' \sQuote{Value}). Otherwise, it only returns the study ##' identifiers. ##' @param verbose Should the output include all metadata (logical ##' default \code{FALSE}) ##' @param ... additional arguments to customize the API request (see ##' \code{\link{rotl}} package documentation). ##' @return If \code{detailed=TRUE}, the function returns a data frame ##' listing the study id (\code{study_ids}), the number of trees ##' associated with this study (\code{n_trees}), the tree ids (at ##' most 5) associated with the studies (\code{tree_ids}), the ##' tree id that is a candidate for the synthetic tree if any ##' (\code{candidate}), the year of publication of the study ##' (\code{study_year}), the title of the publication for the ##' study (\code{title}), and the DOI (Digital Object Identifier) ##' for the study (\code{study_doi}). ##' ##' If \code{detailed=FALSE}, the function returns a data frame ##' with a single column containing the study identifiers. ##' @seealso \code{\link{studies_properties}} which lists properties ##' against which the studies can be ##' searched. \code{\link{list_trees}} that returns a list for all ##' tree ids associated with a study. ##' @export ##' @examples ##' \dontrun{ ##' ## To match a study for which the identifier is already known ##' one_study <- studies_find_studies(property="ot:studyId", value="pg_719") ##' list_trees(one_study) ##' ##' ## To find studies pertaining to Mammals ##' mammals <- studies_find_studies(property="ot:focalCladeOTTTaxonName", ##' value="mammalia") ##' ## To extract the tree identifiers for each of the studies ##' list_trees(mammals) ##' ## ... or for a given study ##' list_trees(mammals, "ot_308") ##' ##' ## Just the identifiers without other information about the studies ##' mammals <- studies_find_studies(property="ot:focalCladeOTTTaxonName", ##' value="mammalia", detailed=FALSE) ##' } studies_find_studies <- function(property = NULL, value = NULL, verbose = FALSE, exact = FALSE, detailed = TRUE, ...) { .res <- .studies_find_studies( property = property, value = value, verbose = verbose, exact = exact, ... ) res <- vapply( .res[["matched_studies"]], function(x) x[["ot:studyId"]], character(1) ) if (detailed) { dat <- summarize_meta(res) } else { meta_raw <- .res dat <- data.frame(study_ids = res, stringsAsFactors = FALSE) attr(dat, "found_trees") <- paste( "If you want to get a list of the", "trees associated with the studies,", "use", sQuote("detailed = TRUE") ) class(dat) <- c("study_ids", class(dat)) attr(dat, "metadata") <- meta_raw } class(dat) <- c("matched_studies", class(dat)) dat } ##' @export print.study_ids <- function(x, ...) { print(format(x), ...) } ##' Return a list of studies for which trees match a given set of ##' properties ##' ##' The list of possible values to be used as values for the argument ##' \code{property} can be found using the function ##' \code{\link{studies_properties}}. ##' ##' @title Find Trees ##' @param property The property to be searched on (character) ##' @param value The property-value to be searched on (character) ##' @param verbose Should the output include all metadata? (logical, ##' default \code{FALSE}) ##' @param exact Should exact matching be used for the value? ##' (logical, default \code{FALSE}) ##' @param detailed Should a detailed report be provided? If ##' \code{TRUE} (default), the output will include metadata about ##' the study that include trees matching the property. Otherwise, ##' only information about the trees will be provided. ##' @param ... additional arguments to customize the API request (see ##' \code{\link{rotl}} package documentation). ##' @return A data frame that summarizes the trees found (and their ##' associated studies) for the requested criteria. If a study has ##' more than 5 trees, the \code{tree_ids} of the first ones will ##' be shown, followed by \code{...} to indicate that more are ##' present. ##' ##' If \code{detailed=FALSE}, the data frame will include the ##' study ids of the study (\code{study_ids}), the number of trees ##' in this study that match the search criteria ##' (\code{n_matched_trees}), the tree ids that match the search ##' criteria (\code{match_tree_ids}). ##' ##' If \code{detailed=TRUE}, in addition of the fields listed ##' above, the data frame will also contain the total number of ##' trees associated with the study (\code{n_trees}), all the tree ##' ids associated with the study (\code{tree_ids}), the tree id ##' that is a potential candidate for inclusion in the synthetic ##' tree (if any) (\code{candidate}), the year the study was ##' published (\code{study_year}), the title of the study ##' (\code{title}), the DOI for the study (\code{study_doi}). ##' ##' @seealso \code{\link{studies_properties}} which lists properties ##' the studies can be searched on. \code{\link{list_trees}} for ##' listing the trees that match the query. ##' @export ##' @importFrom stats setNames ##' @examples ##' \dontrun{ ##' res <- studies_find_trees(property="ot:ottTaxonName", value="Drosophila", ##' detailed=FALSE) ##' ## summary of the trees and associated studies that match this criterion ##' res ##' ## With metadata about the studies (default) ##' res <- studies_find_trees(property="ot:ottTaxonName", value="Drosophila", ##' detailed=TRUE) ##' ## The list of trees for each study that match the search criteria ##' list_trees(res) ##' ## the trees for a given study ##' list_trees(res, study_id = "pg_2769") ##' } studies_find_trees <- function(property = NULL, value = NULL, verbose = FALSE, exact = FALSE, detailed = TRUE, ...) { .res <- .studies_find_trees( property = property, value = value, verbose = verbose, exact = exact, ... ) study_ids <- vapply( .res[["matched_studies"]], function(x) x[["ot:studyId"]], character(1) ) n_matched_trees <- vapply( .res[["matched_studies"]], function(x) length(x[["matched_trees"]]), numeric(1) ) match_tree_ids <- lapply( .res[["matched_studies"]], function(x) { sapply( x[["matched_trees"]], function(y) y[["ot:treeId"]] ) } ) # this one doesn't return all of the treeids. confusing, bc trees are what is wanted # tree_str <- vapply(match_tree_ids, limit_trees, character(1)) tree_str <- sapply(match_tree_ids, function(x) paste(x, collapse = ", ")) res <- data.frame(study_ids, n_matched_trees, match_tree_ids = tree_str, stringsAsFactors = FALSE ) if (detailed) { meta <- summarize_meta(study_ids) # the next bit seems really slow (JWB) res <- merge(meta, res) attr(res, "metadata") <- attr(meta, "metadata") } else { attr(res, "metadata") <- .res } attr(res, "found_trees") <- stats::setNames(match_tree_ids, study_ids) class(res) <- c("matched_studies", class(res)) res } ##' Returns the trees associated with a given study ##' ##' If \code{file_format} is missing, the function returns an object ##' of the class \code{phylo} from the \code{ape} package ##' (default), or an object of the class \code{nexml} from the ##' \code{RNeXML} package. ##' ##' Otherwise \code{file_format} can be either \code{newick}, ##' \code{nexus}, \code{nexml} or \code{json}, and the function will ##' generate a file of the selected format. In this case, a file name ##' needs to be provided using the argument \code{file}. If a file ##' with the same name already exists, it will be silently ##' overwritten. ##' ##' @title Get all the trees associated with a particular study ##' @param study_id the study ID for the study of interest (character) ##' @param object_format the class of the object the query should ##' return (either \code{phylo} or \code{nexml}). Ignored if ##' \code{file_format} is specified. ##' @param file_format the format of the file to be generated ##' (\code{newick}, \code{nexus}, \code{nexml} or \code{json}). ##' @param file the file name where the output of the function will be ##' saved. ##' @param ... additional arguments to customize the API request (see ##' \code{\link{rotl}} package documentation). ##' @return if \code{file_format} is missing, an object of class ##' \code{phylo} or \code{nexml}, otherwise a logical indicating ##' whether the file was successfully created. ##' @seealso \code{\link{get_study_meta}} ##' @export ##' @importFrom jsonlite toJSON ##' @examples ##' \dontrun{ ##' that_one_study <- get_study(study_id="pg_719", object_format="phylo") ##' if (require(RNeXML)) { ## if RNeXML is installed get the object directly ##' nexml_study <- get_study(study_id="pg_719", object_format="nexml") ##' } else { ## otherwise write it to a file ##' get_study(study_id="pg_719", file_format="nexml", file=tempfile(fileext=".nexml")) ##' } ##' } get_study <- function(study_id = NULL, object_format = c("phylo", "nexml"), file_format, file, ...) { object_format <- match.arg(object_format) if (!missing(file)) { if (!missing(file_format)) { file_format <- match.arg(file_format, c("newick", "nexus", "nexml", "json")) res <- .get_study(study_id, format = file_format) unlink(file) if (identical(file_format, "json")) { cat(jsonlite::toJSON(res), file = file) } else { cat(res, file = file) } return(invisible(file.exists(file))) } else { stop(sQuote("file_format"), " must be specified.") } } else if (identical(object_format, "phylo")) { file_format <- "newick" res <- .get_study(study_id = study_id, format = file_format, ...) res <- phylo_from_otl(res) } else if (identical(object_format, "nexml")) { file_format <- "nexml" res <- .get_study(study_id = study_id, format = file_format, ...) res <- nexml_from_otl(res) } else { stop("Something is very wrong. Contact us.") } res } ##' Returns a specific tree from within a study ##' ##' @title Study Tree ##' @param study_id the identifier of a study (character) ##' @param tree_id the identifier of a tree within the study ##' @param object_format the class of the object to be returned ##' (default and currently only possible value \code{phylo} from ##' the \code{ape} package). ##' @param tip_label the format of the tip ##' labels. \dQuote{\code{original_label}} (default) returns the ##' original labels as provided in the study, ##' \dQuote{\code{ott_id}} labels are replaced by their ott IDs, ##' \dQuote{\code{ott_taxon_name}} labels are replaced by their ##' Open Tree Taxonomy taxon name. ##' @param file_format the format of the file to be generated ##' (\code{newick} default, \code{nexus}, or \code{json}). ##' @param file the file name where the output of the function will be ##' saved. ##' @param deduplicate logical (default \code{TRUE}). If the tree ##' returned by the study contains duplicated taxon names, should they ##' be made unique? It is normally illegal for NEXUS/Newick tree ##' strings to contain duplicated tip names. This is a workaround to ##' circumvent this requirement. If \code{TRUE}, duplicated tip labels ##' will be appended \code{_1}, \code{_2}, etc. ##' @param ... additional arguments to customize the API request (see ##' \code{\link{rotl}} package documentation). ##' @return if \code{file_format} is missing, an object of class ##' \code{phylo}, otherwise a logical indicating whether the file ##' was successfully created. ##' @export ##' @importFrom jsonlite toJSON ##' @examples ##' \dontrun{ ##' tree <- get_study_tree(study_id="pg_1144", tree_id="tree2324") ##' ##' ## comparison of the first few tip labels depending on the options used ##' head(get_study_tree(study_id="pg_1144", tree_id="tree2324", tip_label="original_label")$tip.label) ##' head(get_study_tree(study_id="pg_1144", tree_id="tree2324", tip_label="ott_id")$tip.label) ##' head(get_study_tree(study_id="pg_1144", tree_id="tree2324", tip_label="ott_taxon_name")$tip.label) ##' } get_study_tree <- function(study_id = NULL, tree_id = NULL, object_format = c("phylo"), tip_label = c("original_label", "ott_id", "ott_taxon_name"), file_format, file, deduplicate = TRUE, ...) { object_format <- match.arg(object_format) tip_label <- match.arg(tip_label) tip_label <- switch(tip_label, original_labels = "ot:originallabel", ott_id = "ot:ottid", ott_taxon_name = "ot:otttaxonname" ) if (!missing(file)) { if (!missing(file_format)) { file_format <- match.arg(file_format, c("newick", "nexus", "json")) if (missing(file)) stop("You must specify a file to write your output") res <- .get_study_tree( study_id = study_id, tree_id = tree_id, format = file_format, tip_label = tip_label, ... ) unlink(file) if (identical(file_format, "json")) { cat(jsonlite::toJSON(res), file = file) } else { cat(res, file = file) } return(invisible(file.exists(file))) } else { stop(sQuote("file_format"), " must be specified.") } } else if (identical(object_format, "phylo")) { file_format <- "newick" res <- .get_study_tree( study_id = study_id, tree_id = tree_id, format = file_format, tip_label = tip_label, ... ) res <- phylo_from_otl(res, dedup = deduplicate) } else { stop("Something is very wrong. Contact us.") } res } ##' Retrieve metadata about a study in the Open Tree of Life datastore ##' ##' \code{get_study_meta} returns a long list of attributes for the ##' studies that are contributing to the synthetic tree. To help with ##' the extraction of relevant information from this list, several ##' helper functions exists: \describe{ ##' ##' \item{get_tree_ids}{The identifiers of the trees ##' associated with the study.} ##' ##' \item{get_publication}{The citation information of the ##' publication for the study. The DOI (or URL) for the study is ##' available as an attribute to the returned object (i.e., ##' \code{attr(object, "DOI")} ).} ##' ##' \item{candidate_for_synth}{The identifier of the tree(s) from ##' the study used in the synthetic tree. This is a subset of the ##' result of \code{get_tree_ids}.} ##' ##' \item{get_study_year}{The year of publication of the study.} ##' } ##' ##' @title Study Metadata ##' @param study_id the study identifier (character) ##' @param ... additional arguments to customize the API request (see ##' \code{\link{rotl}} package documentation). ##' @param sm an object created by \code{get_study_meta} ##' @return named-list containing the metadata associated with the ##' study requested ##' @export ##' @examples ##' \dontrun{ ##' req <- get_study_meta("pg_719") ##' get_tree_ids(req) ##' candidate_for_synth(req) ##' get_publication(req) ##' get_study_year(req) ##' } get_study_meta <- function(study_id, ...) { res <- .get_study_meta(study_id = study_id, ...) class(res) <- "study_meta" attr(res, "study_id") <- study_id res } ##' @export print.study_meta <- function(x, ...) { cat("Metadata for OToL study ", attr(x, "study_id"), ". Contents:\n", sep = "") cat(paste0(" $nexml$", names(x$nexml)), sep = "\n") } ##' Retrieve subtree from a specific tree in the Open Tree of Life data store ##' ##' @title Study Subtree ##' @param study_id the study identifier (character) ##' @param tree_id the tree identifier (character) ##' @param object_format the class of the object returned by the ##' function (default, and currently only possibility \code{phylo} ##' from the \code{ape} package) ##' @param tip_label the format of the tip ##' labels. \dQuote{\code{original_label}} (default) returns the ##' original labels as provided in the study, ##' \dQuote{\code{ott_id}} labels are replaced by their ott IDs, ##' \dQuote{\code{ott_taxon_name}} labels are replaced by their ##' Open Tree Taxonomy taxon name. ##' @param file_format character, the file format to use to save the ##' results of the query (possible values, \sQuote{newick} or ##' \sQuote{nexus}). ##' @param file character, the path and file name where the output ##' should be written. ##' @param deduplicate logical (default \code{TRUE}). If the tree ##' returned by the study contains duplicated taxon names, should ##' they be made unique? It is normally illegal for NEXUS/Newick ##' tree strings to contain duplicated tip names. This is a ##' workaround to circumvent this requirement. If \code{TRUE}, ##' duplicated tip labels will be appended \code{_1}, \code{_2}, ##' etc. ##' @param subtree_id, either a node id that specifies a subtree or ##' \dQuote{ingroup} which returns the ingroup for this subtree. ##' @param ... additional arguments to customize the API request (see ##' \code{\link{rotl}} package documentation). ##' @export ##' @examples ##' \dontrun{ ##' small_tr <- get_study_subtree(study_id="pg_1144", tree_id="tree5800", subtree_id="node991044") ##' ingroup <- get_study_subtree(study_id="pg_1144", tree_id="tree5800", subtree_id="ingroup") ##' nexus_file <- tempfile(fileext=".nex") ##' get_study_subtree(study_id="pg_1144", tree_id="tree5800", subtree_id="ingroup", file=nexus_file, ##' file_format="nexus") ##' } get_study_subtree <- function(study_id, tree_id, subtree_id, object_format = c("phylo"), tip_label = c("original_label", "ott_id", "ott_taxon_name"), file_format, file, deduplicate = TRUE, ...) { object_format <- match.arg(object_format) tip_label <- match.arg(tip_label) tip_label <- switch(tip_label, original_labels = "ot:originallabel", ott_id = "ot:ottid", ott_taxon_name = "ot:otttaxonname" ) if (!missing(file)) { if (!missing(file_format)) { if (missing(file)) stop("You must specify a file to write your output") file_format <- match.arg(file_format, c("newick", "nexus")) res <- .get_study_subtree( study_id = study_id, tree_id = tree_id, subtree_id = subtree_id, format = file_format, tip_label = tip_label, ... ) unlink(file) cat(res, file = file) return(invisible(file.exists(file))) } else { stop(sQuote("file_format"), " must be specified.") } } else if (identical(object_format, "phylo")) { file_format <- "newick" res <- .get_study_subtree( study_id = study_id, tree_id = tree_id, subtree_id = subtree_id, format = file_format, tip_label = tip_label, ... ) res <- phylo_from_otl(res, dedup = deduplicate) ## NeXML should be possible for both object_format and file_format but it seems there ## is something wrong with the server at this time (FM - 2015-06-07) ## } else if (identical(object_format, "nexml")) { ## file_format <- "nexml" ## res <- .get_study_subtree(study_id, tree_id, subtree_id, format=file_format) ## res <- nexml_from_otl(res) } else { stop("Something is very wrong. Contact us.") } res } rotl/R/external_data.R0000644000176200001440000001150615132136164014376 0ustar liggesusers##' Get external identifiers for data associated with an Open Tree study ##' ##' Data associated with studies contributing to the Open Tree synthesis may ##' be available from other databases. In particular, trees and alignments ##' may be available from treebase and DNA sequences and bibliographic ##' information associated with a given study may be available from the NCBI. ##' This function retrieves that information for a given study. ##' ##' @param study_id An open tree study ID ##' @return A study_external_data object (which inherits from a list) which ##' contains some of the following. ##' @return doi, character, the DOI for the paper describing this study ##' @return external_data_url, character, a URL to an external data repository ##' (e.g. a treebase entry) if one exists. ##' @return pubmed_id character, the unique ID for this study in the NCBI's pubmed database ##' @return popset_ids character, vector of IDs for the NCBI's popset database ##' @return nucleotide_ids character, vector of IDs for the NCBI's nucleotide database ##' @seealso studies_find_studies (used to discover study IDs) ##' @importFrom httr parse_url ##' @importFrom rentrez entrez_search ##' @importFrom rentrez entrez_link ##' @examples ##' \dontrun{ ##' flies <- studies_find_studies(property="ot:focalCladeOTTTaxonName", value="Drosophilidae") ##' study_external_IDs(flies[2,]$study_ids) ##' } ##' @export study_external_IDs <- function(study_id) { meta <- get_study_meta(study_id) data_deposit <- meta[["nexml"]][["^ot:dataDeposit"]][["@href"]] url <- attr(get_publication(meta), "DOI") doi <- parse_url(url)$path pmid <- get_pmid(doi, study_id) res <- list( doi = doi, pubmed_id = pmid, external_data_url = data_deposit ) if (!is.null(pmid)) { res$popset_ids <- entrez_link(dbfrom = "pubmed", db = "popset", id = pmid)[["links"]][["pubmed_popset"]] res$nucleotide_ids <- entrez_link(dbfrom = "pubmed", db = "nuccore", id = pmid)[["links"]][["pubmed_nuccore"]] } structure(res, class = c("study_external_data", "list"), id = study_id) } ##' Get external identifiers for data associated with an Open Tree taxon ##' ##' The Open Tree taxonomy is a synthesis of multiple reference taxonomies. This ##' function retrieves identifiers to external taxonomic records that have ##' contributed the rank, position and definition of a given Open Tree taxon. ##' ##' @param taxon_id An open tree study ID ##' @return a data.frame in which each row represents a unique record in an ##' external database. The column "source" provides and abbreviated name for the ##' database, and "id" the unique ID for the record. ##' @seealso tnrs_matchnames, which can be used to search for taxa by name. ##' @seealso taxonomy_taxon, for more information about a given taxon. ##' @examples ##' \dontrun{ ##' gibbon_IDs <- taxon_external_IDs(712902) ##' } ##' @export taxon_external_IDs <- function(taxon_id) { taxon_info <- taxonomy_taxon_info(taxon_id) srcs <- taxon_info[[1]][["tax_sources"]] res <- do.call(rbind.data.frame, strsplit(unlist(srcs), ":")) names(res) <- c("source", "id") res } #' @export print.study_external_data <- function(x, ...) { cat("External data identifiers for study", attr(x, "study_id"), "\n") cat(" $doi: ", x[["doi"]], "\n") if (!is.null(x$pubmed_id)) { cat(" $pubmed_id: ", x[["pubmed_id"]], "\n") } if (!is.null(x$popset_ids)) { cat(" $popset_ids: vector of", length(x[["popset_ids"]]), "IDs \n") } if (!is.null(x$nucleotide_ids)) { cat(" $nucleotide_ids: vector of", length(x[["nucleotide_ids"]]), "IDs\n") } if (nchar(x[["external_data_url"]]) > 0) { cat(" $external_data_url", x[["external_data_url"]], "\n") } cat("\n") } ## Maybe include these functions to get summary information about a ## set of linked sequences? # summarize_nucleotide_data <- function(id_vector){ # summs <- entrez_summary(db="nuccore", id=id_vector) # interesting <- extract_from_esummary(summs, c("uid", "title", "slen", "organism", "completeness"), simplify=FALSE) # do.call(rbind.data.frame, interesting) # } # # summarize_popset_data <- function(id_vector){ # summs <- entrez_summary(db="popset", id=id_vector) # interesting <- extract_from_esummary(summs, c("uid", "title"), simplify=FALSE) # do.call(rbind.data.frame, interesting) # } # # Un-exported function to convert doi->pmid. Also takes study_id as an argument in # order to provide a helpful error message when 0 or >1 pmids are returned. get_pmid <- function(doi, study_id) { pubmed_search <- entrez_search(db = "pubmed", term = paste0(doi, "[DOI]")) if (length(pubmed_search$ids) == 0) { warning("Could not find PMID for study'", study_id, "', skipping NCBI data") return(NULL) } if (length(pubmed_search$ids) > 1) { warning("Found more than one PMID matching study'", study_id, "', skipping NCBI data") return(NULL) } pubmed_search$ids } rotl/R/taxonomy.R0000644000176200001440000002453415132136164013446 0ustar liggesusers##' Summary information about the Open Tree Taxonomy (OTT) ##' ##' Return metadata and information about the taxonomy ##' itself. Currently, the available metadata is fairly sparse, but ##' includes (at least) the version, and the location from which the ##' complete taxonomy source files can be downloaded. ##' ##' @title Information about the Open Tree Taxonomy ##' @param ... additional arguments to customize the API request (see ##' \code{\link{rotl}} package documentation). ##' @return A list with the following properties: ##' \describe{ ##' ##' \item{weburl}{String. The release page for this version ##' of the taxonomy.} ##' ##' \item{author}{String. The author string.} ##' ##' \item{name}{String. The name of the taxonomy.} ##' ##' \item{source}{String. The full identifying information for ##' this version of the taxonomy.} ##' ##' \item{version}{String. The version number of the taxonomy.} ##' } ##' @examples ##' \dontrun{ ##' taxonomy_about() ##' } ##' @export taxonomy_about <- function(...) { res <- .taxonomy_about(...) return(res) } ##' Information about taxa. ##' ##' Given a vector of ott ids, \code{taxonomy_taxon_info} returns ##' information about the specified taxa. ##' ##' The functions \code{tax_rank}, \code{tax_name}, and ##' \code{synonyms} can extract this information from an object ##' created by the \code{taxonomy_taxon_info()}. ##' ##' @title Taxon information ##' @param ott_ids the ott ids of the taxon of interest (numeric or ##' character containing only numbers) ##' @param include_children whether to include information about all ##' the children of this taxon. Default \code{FALSE}. ##' @param include_lineage whether to include information about all ##' the higher level taxa that include the \code{ott_ids}. ##' Default \code{FALSE}. ##' @param include_terminal_descendants whether to include the list of ##' terminal \code{ott_ids} contained in the \code{ott_ids} ##' provided. ##' @param ... additional arguments to customize the API request (see ##' \code{\link{rotl}} package documentation). ##' @param tax an object generated by the \code{taxonomy_taxon_info} ##' function ##' @return \code{taxonomy_taxon_info} returns a list detailing ##' information about the taxa. \code{tax_rank} and ##' \code{tax_name} return a vector. \code{synonyms} returns a ##' list whose elements are the synonyms for each of the ##' \code{ott_id} requested. ##' ##' @seealso \code{\link{tnrs_match_names}} to obtain \code{ott_id} ##' from a taxonomic name. ##' @examples ##' \dontrun{ ##' req <- taxonomy_taxon_info(ott_id=515698) ##' tax_rank(req) ##' tax_name(req) ##' synonyms(req) ##' } ##' @export taxonomy_taxon_info <- function(ott_ids, include_children = FALSE, include_lineage = FALSE, include_terminal_descendants = FALSE, ...) { res <- lapply(ott_ids, function(x) { .taxonomy_taxon_info( ott_id = x, include_children = include_children, include_lineage = include_lineage, include_terminal_descendants = include_terminal_descendants, ... ) }) names(res) <- ott_ids class(res) <- "taxon_info" return(res) } ##' Given an ott id, return the inclusive taxonomic subtree descended ##' from the specified taxon. ##' ##' If the output of this function is exported to a file, the only ##' possible value for the \code{output_format} argument is ##' \dQuote{\code{newick}}. If the file provided already exists, it ##' will be silently overwritten. ##' ##' @title Taxonomy subtree ##' @param ott_id The ott id of the taxon of interest. ##' @param output_format the format of the object to be returned. See ##' the \sQuote{Return} section. ##' @param label_format Character. Defines the label type; one of ##' \dQuote{\code{name}}, \dQuote{\code{id}}, or ##' \dQuote{\code{name_and_id}} (the default). ##' @param ... additional arguments to customize the API request (see ##' \code{\link{rotl}} package documentation). ##' @param file the file name where to save the output of the ##' function. Ignored unless \code{output_format} is set to ##' \dQuote{\code{phylo}}. ##' @return If the \code{file} argument is missing: \describe{ ##' ##' \item{\dQuote{\code{taxa}}}{ a list of the taxa names ##' (species) in slot \code{tip_label}, and higher-level taxonomy ##' (e.g., families, genera) in slot \code{edge_label}, descending ##' from the taxa corresponding to the \code{ott_id} provided. } ##' ##' \item{\dQuote{\code{newick}}}{ a character vector containing ##' the newick formatted string corresponding to the taxonomic ##' subtree for the \code{ott_id} provided. } ##' ##' \item{\dQuote{\code{phylo}}}{ an object of the class ##' \code{phylo} from the \code{ape} package. } ##' ##' \item{\dQuote{\code{raw}}}{ the direct output from the API, ##' i.e., a list with an element named \sQuote{newick} that ##' contains the subtree as a newick formatted string. } ##' ##' } ##' ##' If a \code{file} argument is provided (and ##' \code{output_format} is set to \dQuote{\code{phylo}}), a ##' logical indicating whether the file was successfully created. ##' ##' @examples ##' \dontrun{ ##' req <- taxonomy_subtree(ott_id=515698) ##' plot(taxonomy_subtree(ott_id=515698, output_format="phylo")) ##' } ##' @export taxonomy_subtree <- function(ott_id = NULL, output_format = c("taxa", "newick", "phylo", "raw"), label_format = NULL, file, ...) { output_format <- match.arg(output_format) res <- .taxonomy_subtree(ott_id = ott_id, label_format = label_format, ...) if (!missing(file) && !identical(output_format, "newick")) { warning( sQuote("file"), " argument is ignored, you can only write newick tree strings to a file." ) } if (identical(output_format, "raw")) { return(res) } else if (identical(output_format, "newick")) { res <- res$newick if (!missing(file)) { unlink(file) cat(res, file = file) invisible(return(file.exists(file))) } } else if (identical(output_format, "phylo")) { res <- phylo_from_otl(res) } else { ## in all other cases use tree_to_labels res <- tree_to_labels(res) } return(res) } ##' Taxonomic Least Inclusive Common Ancestor (MRCA) ##' ##' Given a set of OTT ids, get the taxon that is the most recent common ##' ancestor (the MRCA) of all the identified taxa. ##' ##' @title Taxonomic MRCA ##' @param ott_ids a vector of ott ids for the taxa whose MRCA is to ##' be found (numeric). ##' @param tax an object generated by the \code{taxonomy_mrca} ##' function ##' @param ... additional arguments to customize the API request (see ##' \code{\link{rotl}} package documentation). ##' @return \describe{ ##' ##' \item{\code{taxonomy_mrca}}{ returns a list about the ##' taxonomic information relating to the MRCA for the ott_ids ##' provided. } ##' ##' \item{\code{tax_rank}}{ returns a character vector of the ##' taxonomic rank for the MRCA. } ##' ##' \item{\code{tax_name}}{ returns a character vector the ##' Open Tree Taxonomy name for the MRCA. } ##' ##' \item{\code{ott_id}}{ returns a numeric vector of the ott id ##' for the MRCA. } ##' ##' } ##' @examples ##' \dontrun{ ##' req <- taxonomy_mrca(ott_ids=c(515698,590452,643717)) ##' tax_rank(req) ##' tax_name(req) ##' ott_id(req) ##' } ##' @export taxonomy_mrca <- function(ott_ids = NULL, ...) { res <- .taxonomy_mrca(ott_ids = ott_ids, ...) class(res) <- c("taxon_mrca", class(res)) return(res) } ### methods for taxonomy_taxon_info --------------------------------------------- taxon_info_method_factory <- function(.f) { function(tax, ...) { res <- lapply(tax, .f) names(res) <- vapply(tax, .tax_unique_name, character(1)) res <- add_otl_class(res, .f) res } } ##' @export ##' @rdname taxonomy_taxon_info tax_rank.taxon_info <- taxon_info_method_factory(.tax_rank) ##' @export ##' @rdname taxonomy_taxon_info tax_name.taxon_info <- taxon_info_method_factory(.tax_name) ##' @export ##' @rdname taxonomy_taxon_info unique_name.taxon_info <- taxon_info_method_factory(.tax_unique_name) ##' @export ##' @rdname taxonomy_taxon_info synonyms.taxon_info <- taxon_info_method_factory(.tax_synonyms) ##' @export ##' @rdname taxonomy_taxon_info ott_id.taxon_info <- taxon_info_method_factory(.tax_ott_id) ##' @export ##' @rdname taxonomy_taxon_info tax_sources.taxon_info <- taxon_info_method_factory(.tax_sources) ##' @export ##' @rdname taxonomy_taxon_info is_suppressed.taxon_info <- taxon_info_method_factory(.tax_is_suppressed) ##' @export ##' @rdname taxonomy_taxon_info flags.taxon_info <- taxon_info_method_factory(.tax_flags) ### methods for taxonomy_mrca --------------------------------------------------- taxon_mrca_method_factory <- function(.f) { function(tax, ...) { res <- list(.f(tax[["mrca"]])) names(res) <- .tax_unique_name(tax[["mrca"]]) res <- add_otl_class(res, .f) res } } ##' @export ##' @rdname taxonomy_mrca tax_rank.taxon_mrca <- taxon_mrca_method_factory(.tax_rank) ##' @export ##' @rdname taxonomy_mrca tax_name.taxon_mrca <- taxon_mrca_method_factory(.tax_name) ##' @export ##' @rdname taxonomy_mrca ott_id.taxon_mrca <- taxon_mrca_method_factory(.tax_ott_id) ##' @export ##' @rdname taxonomy_mrca unique_name.taxon_mrca <- taxon_mrca_method_factory(.tax_unique_name) ##' @export ##' @rdname taxonomy_mrca tax_sources.taxon_mrca <- taxon_mrca_method_factory(.tax_sources) ##' @export ##' @rdname taxonomy_mrca flags.taxon_mrca <- taxon_mrca_method_factory(.tax_flags) ##' @export ##' @rdname taxonomy_mrca is_suppressed.taxon_mrca <- taxon_mrca_method_factory(.tax_is_suppressed) ### method for extracting higher taxonomy from taxonomy_taxon_info calls ------- get_lineage <- function(tax) { check_lineage(tax) lg <- lapply(tax[["lineage"]], build_lineage) lg <- do.call("rbind", lg) as.data.frame(lg, stringsAsFactors = FALSE) } build_lineage <- function(x) { c( "rank" = .tax_rank(x), "name" = .tax_name(x), "unique_name" = .tax_unique_name(x), "ott_id" = .tax_ott_id(x) ) } check_lineage <- function(tax) { if (!exists("lineage", tax)) { stop( "The object needs to be created using ", sQuote("include_lineage=TRUE") ) } } ##' @export ##' @rdname tax_lineage tax_lineage.taxon_info <- function(tax, ...) { lapply(tax, get_lineage) } rotl/R/api-collections.R0000644000176200001440000000145415132136164014651 0ustar liggesusers## This endpoint currently returns JSON in XML with mime type as text/html .collection_find_collections <- function(property = NULL, value = NULL, verbose = FALSE, ...) { check_is_flag(verbose) req_body <- list() req_body$verbose <- verbose res <- otl_POST( path = "collections/find_collections", body = req_body, ... ) res } .collection_properties <- function(...) { req_body <- list() res <- otl_POST( path = "collections/properties", body = req_body, ... ) res } .get_collection <- function(owner_id = NULL, collection_name = NULL, ...) { check_is_string(owner_id) check_is_string(collection_name) req_body <- list() res <- otl_GET(path = paste("collections", owner_id, collection_name, sep = "/" ), ...) res } rotl/R/studies-utils.R0000644000176200001440000000472015132136164014401 0ustar liggesusers## Unexported function that generates a data frame summarizing the metadata. ## This function is used by both studies_find_studies and studies_find_trees, ## to generate the output when using the argument detailed=TRUE ##' @importFrom stats setNames summarize_meta <- function(study_ids) { fill <- function(x) { if (length(unlist(x))) { x } else { "" } } meta_raw <- lapply(study_ids, function(x) get_study_meta(x)) ## Extract the metadata meta <- lapply(meta_raw, function(m) { c( tree_ids = fill(list(get_tree_ids(m))), study_year = fill(get_study_year(m)), publication = fill(get_publication(m)), doi = fill(attr(get_publication(m), "DOI")), candidate = fill(list(candidate_for_synth(m))) ) }) ## Convert into a data frame dat <- lapply(meta, function(m) { c( n_trees = length(m[["tree_ids"]]), tree_ids = limit_trees(m[["tree_ids"]]), candidate = paste(m[["candidate"]], collapse = ", "), study_year = m[["study_year"]], title = fill(extract_title(m[["publication"]])), study_doi = m[["doi"]] ) }) dat <- do.call("rbind", dat) dat <- cbind(study_ids = study_ids, dat) rownames(dat) <- NULL dat <- data.frame(dat, stringsAsFactors = FALSE) ## Add list of found trees as attributes found_trees <- lapply(meta, function(m) { m[["tree_ids"]] }) found_trees <- stats::setNames(found_trees, study_ids) attr(dat, "found_trees") <- found_trees attr(dat, "metadata") <- meta_raw dat } ## Unexported function that attempts to extract title from the ## citation information associated with the study information. The ## function gets the element that follows what looks like a year in ## the string. ## pub_orig: the publication string extracted from the study metadata ## split_char: the character on which the bibliographic elements are ## separated with. (currently only deals with . and ,) extract_title <- function(pub_orig, split_char = "\\.") { pub <- unlist(strsplit(pub_orig, split = split_char)) pub <- gsub("^\\s|\\s$", "", pub) which_year <- grep("^\\d{4}[a-z]?$", pub) res <- pub[which_year + 1] if (length(res) > 0) { return(res) } else if (split_char == ",") { return(character(0)) } else { extract_title(pub_orig, ",") } } ## Unexported function that limit the display of tree_ids to the first ## 5 values. limit_trees <- function(x) { if (length(x) > 5) { x <- c(x[1:5], "...") } paste(x, collapse = ", ") } rotl/vignettes/0000755000176200001440000000000015132222605013240 5ustar liggesusersrotl/vignettes/data_mashups.Rmd.orig0000644000176200001440000002052015132136164017317 0ustar liggesusers--- title: "Connecting data to Open Tree trees" author: "David Winter" date: "`r Sys.Date()`" output: rmarkdown::html_vignette: css: vignette.css vignette: > %\VignetteIndexEntry{Connecting data to Open Tree trees} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} \usepackage[utf8]{inputenc} --- ```{r setup, include=FALSE} knitr::opts_chunk$set(fig.path = "fig-vignettes-") ``` ## Combining data from OToL and other sources. One of the major goals of `rotl` is to help users combine data from other sources with the phylogenetic trees in the Open Tree database. This examples document describes some of the ways in which a user might connect data to trees from Open Tree. ## Get Open Tree IDs to match your data. Let's say you have a dataset where each row represents a measurement taken from one species, and your goal is to put these measurements in some phylogenetic context. Here's a small example: the best estimate of the mutation rate for a set of unicellular Eukaryotes along with some other property of those species which might explain the mutation rate: ```{r, data} csv_path <- system.file("extdata", "protist_mutation_rates.csv", package = "rotl") mu <- read.csv(csv_path, stringsAsFactors = FALSE) mu ``` If we want to get a tree for these species we need to start by finding the unique ID for each of these species in the Open Tree database. We can use the Taxonomic Name Resolution Service (`tnrs`) functions to do this. Before we do that we should see if any of the taxonomic contexts, which can be used to narrow a search and avoid conflicts between different codes, apply to our group of species: ```{r, context} library(rotl) tnrs_contexts() ``` Hmm, none of those groups contain all of our species. In this case we can search using the `All life` context and the function `tnrs_match_names`: ```{r, match} taxon_search <- tnrs_match_names(names = mu$species, context_name = "All life") knitr::kable(taxon_search) ``` Good, all of our species are known to Open Tree. Note, though, that one of the names is a synonym. _Saccharomyces pombe_ is older name for what is now called _Schizosaccharomyces pombe_. As the name suggests, the Taxonomic Name Resolution Service is designed to deal with these problems (and similar ones like misspellings), but it is always a good idea to check the results of `tnrs_match_names` closely to ensure the results are what you expect. In this case we have a good ID for each of our species so we can move on. Before we do that, let's ensure we can match up our original data to the Open Tree names and IDs by adding them to our `data.frame`: ```{r, munge} mu$ott_name <- unique_name(taxon_search) mu$ott_id <- taxon_search$ott_id ``` ## Find a tree with your taxa Now let's find a tree. There are two possible options here: we can search for published studies that include our taxa or we can use the 'synthetic tree' from Open Tree. We can try both approaches. ### Published trees Before we can search for published studies or trees, we should check out the list of properties we can use to perform such searches: ```{r, properties} studies_properties() ``` We have `ottIds` for our taxa, so let's use those IDs to search for trees that contain them. Starting with our first species _Tetrahymena thermophila_ we can use `studies_find_trees` to do this search. ```{r taxon_count} studies_find_trees(property = "ot:ottId", value = as.character(ott_id(taxon_search)[1])) ``` Well... that's not very promising. We can repeat that process for all of the IDs to see if the other species are better represented. ```{r, all_taxa_count} hits <- lapply(mu$ott_id, studies_find_trees, property = "ot:ottId", detailed = FALSE) sapply(hits, function(x) sum(x[["n_matched_trees"]])) ``` OK, most of our species are not in any of the published trees available. You can help fix this sort of problem by [making sure you submit your published trees to Open Tree](https://tree.opentreeoflife.org/curator). ### A part of the synthesis tree Thankfully, we can still use the complete Tree of Life made from the combined results of all of the published trees and taxonomies that go into Open Tree. The function `tol_induced_subtree` will fetch a tree relating a set of IDs. Using the default arguments you can get a tree object into your R session: ```{r subtree, fig.width=7, fig.height=4} ott_in_tree <- ott_id(taxon_search)[is_in_tree(ott_id(taxon_search))] tr <- tol_induced_subtree(ott_ids = ott_in_tree) plot(tr) ``` ### Connect your data to the tips of your tree Now we have a tree for of our species, how can we use the tree and the data together? The package `phylobase` provide an object class called `phylo4d`, which is designed to represent a phylogeny and data associated with its tips. In order to get our tree and data into one of these objects we have to make sure the labels in the tree and in our data match exactly. That's not quite the case at the moment (tree labels have underscores and IDs appended): ```{r, match_names} mu$ott_name[1] tr$tip.label[4] ``` `rotl` provides a convenience function `strip_ott_ids` to deal with these. ```{r, sub} tr$tip.label <- strip_ott_ids(tr$tip.label, remove_underscores = TRUE) tr$tip.label %in% mu$ott_name ``` Ok, now the tips are together we can make a new dataset. The `phylo4d()` functions matches tip labels to the row names of a `data.frame`, so let's make a new dataset that contains just the relevant data and has row names to match the tree ```{r phylobase} library(phylobase) mu_numeric <- mu[, c("mu", "pop.size", "genome.size")] rownames(mu_numeric) <- mu$ott_name tree_data <- phylo4d(tr, mu_numeric) ``` And now we can plot the data and the tree together ```{r, fig.width=7, fig.height=5} plot(tree_data) ``` ## Find external data associated with studies, trees and taxa from Open Tree In the above example we looked for a tree that related species in another dataset. Now we will go the other way, and try to find data associated with Open Tree records in other databases. ### Get external data from a study Let's imagine you were interested in extending or reproducing the results of a published study. If that study is included in Open Tree you can find it via `studies_find_studies` or `studies_find_trees` and retrieve the published trees with `get_study`. `rotl` will also help you find external. The function `study_external_IDs` retrieves the DOI for a given study, and uses that to gather some more data: ```{r} extra_data <- try(study_external_IDs("pg_1980"), silent = TRUE) if (!inherits(extra_data, "try-error")) { extra_data } ``` Here the returned object contains an `external_data_url` (in this case a link to the study in Treebase), a pubmed ID for the paper and a vector IDs for the NCBI's nucleotide database. The packages `treebase` and `rentrez` provide functions to make use of these IDs within R. As an example, let's use `rentrez` to download the first two DNA seqences and print them. ```{r} library(rentrez) seqs <- try(entrez_fetch(db = "nucleotide", id = extra_data$nucleotide_ids[1:2], rettype = "fasta"), silent = TRUE) if (inherits(seqs, "try-error")) { cat("NCBI temporarily down.") } else { cat(seqs) } ``` You could further process these sequences in R with the function `read.dna` from `ape` or save them to disk by specifying a file name with `cat`. ### Find a OTT taxon in another taxonomic database It is also possible map an Open Tree taxon to a record in another taxonomic database. For instance, if we wanted to search for data about one of the tips of the sub-tree we fetched in the example above we could do so using `taxon_external_IDs`: ```{r} Tt_ids <- taxon_external_IDs(mu$ott_id[2]) Tt_ids ``` A user could then use `rgbif` to find locality records using the gbif ID or `rentrez` to get genetic or bibliometric data about from the NCBI's databases. ## What next The demonstration gets you to the point of visualizing your data in a phylogenetic context. But there's a lot more you do with this sort of data in R. For instance, you could use packages like `ape`, `caper`, `phytools` and `mcmcGLMM` to perform phylogenetic comparative analyses of your data. You could gather more data on your species using packages that connect to trait databases like `rfishbase`, `AntWeb` or `rnpn` which provides data from the US National Phenology Network. You could also use `rentrez` to find genetic data for each of your species, and use that data to generate branch lengths for the phylogeny. rotl/vignettes/rotl.Rmd.orig0000644000176200001440000002565615132142274015644 0ustar liggesusers--- title: "How to use rotl?" author: "François Michonneau" date: "`r Sys.Date()`" output: rmarkdown::html_vignette: css: vignette.css vignette: > %\VignetteIndexEntry{How to use rotl?} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} \usepackage[utf8]{inputenc} --- ```{r setup, include=FALSE} knitr::opts_chunk$set(fig.path = "fig-vignettes-") ``` `rotl` provides an interface to the Open Tree of Life (OTL) API and allows users to query the API, retrieve parts of the Tree of Life and integrate these parts with other R packages. The OTL API provides services to access: * the **Tree of Life** a.k.a. TOL (the synthetic tree): a single draft tree that is a combination of **the OTL taxonomy** and the **source trees** (studies) * the **Taxonomic name resolution services** a.k.a. TNRS: the methods for resolving taxonomic names to the internal identifiers used by the TOL and the GOL (the `ott ids`). * the **Taxonomy** a.k.a. OTT (for Open Tree Taxonomy): which represents the synthesis of the different taxonomies used as a backbone of the TOL when no studies are available. * the **Studies** containing the source trees used to build the TOL, and extracted from the scientific literature. In `rotl`, each of these services correspond to functions with different prefixes: | Service | `rotl` prefix | |---------------|---------------| | Tree of Life | `tol_` | | TNRS | `tnrs_` | | Taxonomy | `taxonomy_` | | Studies | `studies_` | `rotl` also provides a few other functions and methods that can be used to extract relevant information from the objects returned by these functions. ## Demonstration of a basic workflow The most common use for `rotl` is probably to start from a list of species and get the relevant parts of the tree for these species. This is a two step process: 1. the species names need to be matched to their `ott_id` (the Open Tree Taxonomy identifiers) using the Taxonomic name resolution services (TNRS) 1. these `ott_id` will then be used to retrieve the relevant parts of the Tree of Life. ### Step 1: Matching taxonomy to the `ott_id` Let's start by doing a search on a diverse group of taxa: a tree frog (genus _Hyla_), a fish (genus _Salmo_), a sea urchin (genus _Diadema_), and a nautilus (genus _Nautilus_). ```{r} library(rotl) taxa <- c("Hyla", "Salmo", "Diadema", "Nautilus") resolved_names <- tnrs_match_names(taxa) ``` It's always a good idea to check that the resolved names match what you intended: `r knitr::kable(resolved_names)` The column `unique_name` sometimes indicates the higher taxonomic level associated with the name. The column `number_matches` indicates the number of `ott_id` that corresponds to a given name. In this example, our search on _Diadema_ returns 2 matches, and the one returned by default is indeed the sea urchin that we want for our query. The argument `context_name` allows you to limit the taxonomic scope of your search. _Diadema_ is also the genus name of a fungus. To ensure that our search is limited to animal names, we could do: ```{r} resolved_names <- tnrs_match_names(taxa, context_name = "Animals") ``` If you are trying to build a tree with deeply divergent taxa that the argument `context_name` cannot fix, see "How to change the ott ids assigned to my taxa?" in the FAQ below. ### Step 2: Getting the tree corresponding to our taxa Now that we have the correct `ott_id` for our taxa, we can ask for the tree using the `tol_induced_subtree()` function. By default, the object returned by `tol_induced_subtree` is a phylo object (from the [ape](https://cran.r-project.org/package=ape) package), so we can plot it directly. ```{r, fig.width=7, fig.height=4} my_tree <- tol_induced_subtree(ott_ids = resolved_names$ott_id) plot(my_tree, no.margin = TRUE) ``` ## FAQ ### How to change the ott ids assigned to my taxa? If you realize that `tnrs_match_names` assigns the incorrect taxonomic group to your name (e.g., because of synonymy) and changing the `context_name` does not help, you can use the function `inspect`. This function takes the object resulting from `tnrs_match_names()`, and either the row number, the taxon name (you used in your search in lowercase), or the `ott_id` returned by the initial query. To illustrate this, let's re-use the previous query but this time pretending that we are interested in the fungus _Diadema_ and not the sea urchin: ```{r} taxa <- c("Hyla", "Salmo", "Diadema", "Nautilus") resolved_names <- tnrs_match_names(taxa) resolved_names inspect(resolved_names, taxon_name = "diadema") ``` In our case, we want the second row in this data frame to replace the information that initially matched for _Diadema_. We can now use the `update()` function, to change to the correct taxa (the fungus not the sea urchin): ```{r} resolved_names <- update(resolved_names, taxon_name = "diadema", new_row_number = 2 ) ## we could also have used the ott_id to replace this taxon: ## resolved_names <- update(resolved_names, taxon_name = "diadema", ## new_ott_id = 4930522) ``` And now our `resolved_names` data frame includes the taxon we want: `r knitr::kable(resolved_names)` ### How do I know that the taxa I'm asking for is the correct one? The function `taxonomy_taxon_info()` takes `ott_ids` as arguments and returns taxonomic information about the taxa. This output can be passed to some helpers functions to extract the relevant information. Let's illustrate this with our _Diadema_ example ```{r} diadema_info <- taxonomy_taxon_info(631176) tax_rank(diadema_info) synonyms(diadema_info) tax_name(diadema_info) ``` In some cases, it might also be useful to investigate the taxonomic tree descending from an `ott_id` to check that it's the correct taxon and to determine the species included in the Open Tree Taxonomy: ```{r} diadema_tax_tree <- taxonomy_subtree(631176) diadema_tax_tree ``` By default, this function return all taxa (including self, and internal) descending from this `ott_id` but it also possible to return `phylo` object. ### How do I get the tree for a particular taxonomic group? If you are looking to get the tree for a particular taxonomic group, you need to first identify it by its node id or ott id, and then use the `tol_subtree()` function: ```{r, fig.width=7, fig.height=4} mono_id <- tnrs_match_names("Monotremata") mono_tree <- tol_subtree(ott_id = ott_id(mono_id)) plot(mono_tree) ``` ### How do I find trees from studies focused on my favourite taxa? The function `studies_find_trees()` allows the user to search for studies matching a specific criteria. The function `studies_properties()` returns the list of properties that can be used in the search. ```{r} furry_studies <- studies_find_studies(property = "ot:focalCladeOTTTaxonName", value = "Mammalia") furry_ids <- furry_studies$study_ids ``` Now that we know the `study_id`, we can ask for the meta data information associated with this study: ```{r} furry_meta <- get_study_meta("pg_2550") get_publication(furry_meta) ## The citation for the source of the study get_tree_ids(furry_meta) ## This study has 10 trees associated with it candidate_for_synth(furry_meta) ## None of these trees are yet included in the OTL ``` Using `get_study("pg_2550")` would returns a `multiPhylo` object (default) with all the trees associated with this particular study, while `get_study_tree("pg_2550", "tree5513")` would return one of these trees. ### The tree returned by the API has duplicated tip labels, how can I work around it? You may encounter the following error message: ``` Error in rncl(file = file, ...) : Taxon number 39 (coded by the token Pratia angulata) has already been encountered in this tree. Duplication of taxa in a tree is prohibited. ``` This message occurs as duplicate labels are not allowed in the NEXUS format and it is stricly enforced by the part of the code used by `rotl` to import the trees in memory. If you use a version of `rotl` more recent than 0.4.1, this should not happen by default for the function `get_study_tree`. If it happens with another function, please [let us know](https://github.com/ropensci/rotl/issues). The easiest way to work around this is to save the tree in a file, and use APE to read it in memory: ```{r, eval=FALSE} get_study_tree( study_id = "pg_710", tree_id = "tree1277", tip_label = "ott_taxon_name", file = "/tmp/tree.tre", file_format = "newick" ) tr <- ape::read.tree(file = "/tmp/tree.tre") ``` ### How do I get the higher taxonomy for a given taxa? If you encounter a taxon name you are not familiar with, it might be useful to obtain its higher taxonomy to see where it fits in the tree of life. We can combine several taxonomy methods to extract this information easily. ```{r} giant_squid <- tnrs_match_names("Architeuthis") tax_lineage(taxonomy_taxon_info(ott_id(giant_squid), include_lineage = TRUE)) ``` ### Why are OTT IDs discovered with `rotl` missing from an induced subtree? Some taxonomic names that can be retrieved through the taxonomic name resolution service are not part of the Open Tree's synthesis tree. These are usually traditional higher-level taxa that have been found to be paraphyletic. For instance, if you wanted to fetch a tree relating the three birds that go into a [Turkducken](https://en.wikipedia.org/wiki/Turducken) as well as the pork used for stuffing, you might search for the turkey, duck, chicken, and pork genera: ```{r} turducken <- c("Meleagris", "Anas", "Gallus", "Sus") taxa <- tnrs_match_names(turducken, context_name = "Animals") taxa ``` We have the OTT ids for each genus, however, if we tried to get the induced subtree from these results, we would get an error: ```{r, error=TRUE} tr <- tol_induced_subtree(ott_id(taxa)) ``` As the error message suggests, some of the taxa are not found in the synthetic tree. This occurs for 2 main reasons: either the taxa is invalid, or it is part of a group that is not monophyletic in the synthetic tree. There are two ways to get around this issue: (1) removing the taxa that are not part of the Open Tree; (2) using the complete species name. #### Removing the taxa missing from the synthetic tree To help with this situation, `rotl` provides a way to identify the OTT ids that are not part of the synthetic tree. The function `is_in_tree()` takes the output of the `ott_id()` function and returns a vector of logical indicating whether the taxa are part of the synthetic tree. We can then use to only keep the taxa that appear in the synthetic tree: ```{r} in_tree <- is_in_tree(ott_id(taxa)) in_tree tr <- tol_induced_subtree(ott_id(taxa)[in_tree]) ``` #### Using the full taxonomic names The best way to avoid these problems is to specify complete species names (species being the lowest level of classification in the Open Tree taxonomy they are guaranteed to be monophyletic): ```{r, fig.width=7, fig.height=4} turducken_spp <- c("Meleagris gallopavo", "Anas platyrhynchos", "Gallus gallus", "Sus scrofa") taxa <- tnrs_match_names(turducken_spp, context_name = "Animals") tr <- tol_induced_subtree(ott_id(taxa)) plot(tr) ``` rotl/vignettes/fig-vignettes-unnamed-chunk-3-1.png0000644000176200001440000003664615132142365021575 0ustar liggesusers‰PNG  IHDRø XEa=iCCPkCGColorSpaceGenericRGB8U]hU>›¹³+$΃Ԧ¦’þ5”´lRÑ„Úèþe³mÜ,“l´AÉìÝi&3ãü¤i)>AÁ¨à“àÿ[Á'!j«í‹-¢´P¢ƒ(øÐúG¡Ò ë¹3³»“¸k½ËÜùæœï~çÞsîÞ ¸,[–Þ%,®-åÓâ³ÇæÄÄ:tÁ}Ð }Ð-+Ž•*•&ã¿Úíï ÆÞ×ö·÷ÿgë®PGˆÝ…ج8Ê"âeþŲ]€AûÈ ×bø Ä;lœ âõWžð²Ï™‘2ˆ_E,(ªŒþÄÛˆç#öZsðÛŽ<5¨­)"ËEÉ6«šN#Ó½ƒû¶EÝkÄÛƒO³0}߸ö—*r–ᇟUäÜtˆ¯.i³Åÿe¹i ñ#]»¼…r ñ>ÄcU{¼èt©ª7ÑÀ+§Ô™g߃xuÁ<ÊÆîDüµ1_œ u~Rœ æàâ*-°z÷#°Mi*ˆËWh6Çòˆø¸æf}î-gi:×Ð9¥fŠA,î‹ãòV§>ÄW©ž—Bý_-·Æ%=†^œ tÈ0uüõúvW™â’9 Œ%/VµñBÈWµ'¤_¶tâÜÈMÛ“ÊŸ¿ŸåP““í\>ĘÉ@Á„yì0`D i|[`£§ èh¡è¥h¡øÕàìßÂ)ùþ·TjþÈëèÑ0B¦ÿ#ðЪÂïhU#¼ ~yh«uÐ fp#Ô1I/I’ƒø"“ä0!£ ’'ÉSdŒdÑ:J5Ç–"sdó¹ÑÔy#RŸ7‹¼‹èwAÆþgd˜à´ÏÅJŸ7ØÏØÏkÊ•×n^:}nW‹»FVŸ»Ösét$gj-tÈÚÔrÏÿÂ_ç×°_ç7Z þ~ëÛV·5ë4ÌV }ºo[ÄGó=Nd>¥-Ula³£¢Y5VúË}¹x»g[üä÷É?’kÉ÷’&ãÞä>áÎsŸrŸq߀È]à.r_r_qsŸGjÔyï4k± æi—QÜŸBZØ-<(d…=ÂÃÂdKO膄 a/zv7«]»ǰod«}¬€©sìn¬³Öá?TF–'|¦ãï3Nnã„#I?"…m»z„íõ¦v~K=Ú¯Æsñl<b|_|4>?Âpƒß‹¾QìñÔré²ËâŒi´µšêŠÃÉäãb ¯2* åÀ (ëºè»Ѧµ—hå°{28ÂoIþýÛy¥esŸ8ü';÷Z¶9à¬ÐûhË6€gã½ï¬>¦xöRx'Äbß8ÕƒÃÁWOÏ«ëõ[xn%ÞØ|½^ÿûýz}óÔ߸ ÿÿ%x ÅcÖË8eXIfMM*‡i ø  ½Ë]r9IDATx휼յÿWH@Ð ÜÝÝ‹)-´¸»¶ÅŠópyX Z¤X‘ Å¡E‚S\Ü!„ û¿~ë±Ïrzráò&73÷|÷çsÏ™Ù3³gíï>™ß^k¯IäÅ(€ t+cu«ÞÐ@€‚Ï€ Ð ðÝpPé @ç7@è†øn8¨t©{P>ìwß}×=;G¯ Ò ð¥#¥Á2¬±Æ¶êª«ŽÔÔË/¿l½{÷¶o¿ýv¤úÎìœqƦvT¶Ùf;ùä“í›o¾‰v?úè£Î4Õésyä»ì²ËâºO>ùÄŽ8âˆFÚß`ƒ lÚi§µ•VZÉÜ8¦¯¿þÚ6Ùd»þúëGª?î¸ãl–Yf±¹æšË.¹ä’Ʊ›o¾ÙV\qE›cŽ9lÇw´Ï?ÿ¼qluֱ駟¾ñwî¹çƱ¡C‡Új«­í­²Ê*vÛm·5®a¨!½&G@ÕL1Åi¶ÙfK>úhÃ4Ç´øâ‹7ö;»ñÎ;ï¤ 'œ0ù!.u¡OŸ~úizüñÇÓ 3ÌÐÙæ:}þrË-—\ ãºÓN;-m¾ùæ6–Zj©tÌ1Ç„m§Ÿ~zÚc=â˜O>Òå—_žæ›o>½Îš† Ò¸æÄOL.âÉ'&éµ×^KsÏ=wò‰@zõÕWÓÔSO^|ñÅhÏ'éØcë>øàƒ4å”S¦·ß~;‰‡þ†Ç6Úh£tÒI'Ŷ®íß¿1bDã~l@õ"€_ÃIYw7ù7ÞˆPôÞ{ïmòPsyøá‡má…Ž]yáo¼±M5ÕT¶ÖZkÙ Aƒ¢~ذa6Ï<ó„W® 0[tÑEÃk÷ÉAx›nº©}øá‡ö›ßüÆ\ðÍ'vwØa»é¦›¢-}üþ÷¿·ûî»/ö]xmÞyçµ…ZÈÎ9çœÆ9Å×_ÝV_}õ°kË-·lxâk¯½¶Ýÿý¶ûî»ÛÑGmtPÜçoû›]sÍ5Ö³gÏðÐÕ÷vÚ)" j÷ì³Ï¶»îºË9äóIM7Ýtq»Ï>ûÌŽ:ê(;묳L÷t1¶gžyÆÆgœØöIKxâjwÒI'5ö¸î–[n‰lyÿý÷ÃÎqÇ7Ž=ûì³6ÿüóǶ »}õÕWaWTðÔ@½æ#XÛ\ðÒòË/Ÿ\ÄÒÄOœÞzë­è¶ê<œœ|:-½ôÒé„Nˆs.¼ðÂ4çœsÆ9>ø`ò°t“‹uœ+OØ' ÉÃÕqÍ¿þõ¯´È"‹Äy.¨ÉÅ2¶]@ÓSO=Ûßÿ}xüº¿þt¥§çŸ>M6Ùdáý6näòv=\žN=õÔðŠå‘¯»îºqŠO«–ýÅ_DtÂÃèqž<ùÙgŸ=yØ<õë×/ùÒA£YõUÅ'É'ún¸!¹pÇ5>¡I.Ì#y÷:Q‘ ŸP¤Yg5yÈ?®õIQ\ç¡øÔ§OŸ`’½öÚk#’!FŠžÜxãù߀@ ô*kJ²Â +ØxãÇŒ¿, mÚÎÎ;ïõ‚ .Þµ¼ì‹.ºÈäÍ?öØcvÊ)§„wï"ž´‡—mòÉ'·?þ8ˆ=ñĶÀ 4èåý^½zÙK/½dZ–×.7Ÿ'~½õÖ3­Á¿÷Þ{æB׿òÊ+±6ïáîðŽß|óM»÷Þ{#bà„ð–7ò Ÿh„÷¼Ûn»Eõ.»ìÞú—_~^¶î×·o_“ÍF·e–YÆä=¿ð æK6pà@k¬±læ™gnxåÚW‘½9z¡}]£„;yä²WùÊ·½öÚK‡£h ý¼óγ-¶ØÂ\ä£NžþwÜ}÷‰ŠùÒ@D0`@ÜÛ'U¦HÈ4ÓLóCK|Au$PšÀKÜ/¾øbüñëÈ›+B@!f Íï~÷»°h»í¶³­¶ÚÊÖ_ý»û:³ùº¹¹wl÷ÜsO„Ÿ†v3ÎòÉ'afU(±mÍ5׌cûƒ>¸±-qSž{ì!žºVík2 ¢kó$@a…Ö•è¦ýùçŸ÷Žøðè¹ÇÞ¨RB ’ãTòDCÛ …Kh݃Ön„ñòÏûJŽSX^œ‹^“œ\$ðZ È“-¨¢Àï³Ï>±Ä0ãŒ3ÚŸþô'Ó·Âú¹(O¼â×2ÁØcmîµÇawV¢JB¤@õ$PšÀë!+qGàëùC¨’Õò¨%à*K,±DD…®ºê*óD³ß}÷Ý×þøãÆ-=ÓÞ_w‹ºÖð%ÖŠ èú\š×ßU/&ZZ¯ yEò¤@oèÍE0$æZÛ×$EužH}_½ ÁWÑrÀ¶ÛnkË.»¬i’¥e‘¼´'ðÔŽ@%–aµò¤Ñ—A“6~Œ€W cJ¤“0‹¼j­¹çp~ñXÞÖëa:gT¿cE4©è¨H¤'šh¢ðŒ‹çÉ.Õ«ÈvÝ#'Ñ©NI~z¥­ÙnUQŸrò§xÞ¨lÕ½uMq‘¯S(_¿&@ ÞøzÖC€Z` ¾%*!@õ&€À×{ü°€ Ð’ß •€ z@àë=~X@hIo‰…J@€@½ ðõ?¬‡ ´$€À·ÄB% @ ÞøzÖC€Z@à[b¡€ Po|½Çë!@- ð-±P @¨7¾Þã‡õ€ –ø–X¨„ Ô›_ïñÃz@€@K|K,TB€êM¯÷øa= @ %¾%*!@õ&€À×{ü°€ Ð’ß •€ z@àë=~X@hIo‰…J@€@½ ðõ?¬‡ ´$€À·ÄB% @ ÞøzÖC€Z@à[b¡€ Po|½Çë!@- ð-±P @¨7¾Þã‡õ€ –ø–X¨„ Ô›_ïñÃz@€@K|K,TB€êM¯÷øa= @ %¾%*!@õ&€À×{ü°€ Ð’ß •€ z@àë=~X@hIo‰…J@€@½ ðõ?¬‡ ´$€À·ÄB% @ ÞøzÖC€Z@à[b¡€ Po|½Çë!@- ð-±P @¨7¾Þã‡õ€ –ø–X¨„ Ô›_ïñÃz@€@K|K,TB€êM¯÷øa= @ %¾%*!@õ&€À×{ü°€ Ð’ß •€ z@àë=~X@hIo‰…J@€@½ ðõ?¬‡ ´$€À·ÄB% @ ÞøzÖC€Z@à[b¡€ Po|½Çë!@- ð-±P @¨7¾Þã‡õ€ –ø–X¨„ Ô›_ïñÃz@€@K|K,TB€êM¯÷øa= @ %¾%*!@õ&€À×{ü°€ Ð’ß •€ z@àë=~X@hIo‰…J@€@½ ðõ?¬‡ ´$€À·ÄB% @ ÞøzÖC€Z@à[b¡€ Po|½Çë!@- ð-±P @¨7¾Þã‡õ€ –ø–X¨¬/¿üÒ¾þúë*™Ôi[Þzë­N_Sõ ¾ûî;ûðënf—Ø÷ý÷ßÛ;ï¼Ó%÷êÌM¾ýöÛQžÞѱQ^ÄZ@àk5\íeìYgeK-µ”Í1Ç6ÅSØ +¬`C† ­>ùä;âˆ#÷8ãŒ3ìå—_Žým¶ÙÆN>ù䯱Ÿºqæ™gÚE]ôSOï²óRJ6ñÄÛСC;uÏ7ß|ÓÖYg›zê©mžyæ±~ýúÙùçŸÿ“Ú¸å–[l饗îðÜGyÄ.»ì²8çž{î±\°Ãó[œvÚiíþçZêt]ÑžŽ.^|ñÅíçˆf±ýæßŸö7Ø`SVZi%øà4÷Üs§§Ÿ~:` 6,í¶ÛniÞyç­pN;í´ä¶¸‡{di 'LþÐŽ}`¦O?ý´S÷ÿç?ÿ™\ “{xº®+NV¿žzê©NÝÊ'XÉ=ùÄ'¹ýºýöÛÓ”SN™®¼òÊmëƒ>H¯¿þz‡ç-·Üréúë¯sN:餴Ã;tx~óÁÙJ/¾øb{ï½÷’OR“OÞ’O:¢.<úè£é÷¿ÿ}k¬±Òÿ÷çêhCÜôç£4묳¦»ï¾;ŽŸxâ‰iÅWL}ôQzíµ×âߥGÔײQ]V–i|Y$iç¾ûîKî±§7Þxc$z˜éÁ–'’W]uUZ~ùåCp$ï¾ûnœ¯úÿú¯ÿJo¼qZ`Ró¾NÒñÙf›-®w¯2®ÓÃuÒI'M“O>yr%õïß?3Î8ñ@”0©- µ„c¿ýö‹‡ &Åe4Tøpï3=ôÐCQ£ëöÞ{ïx»7–®»îº´óÎ;DZ·ß~;m²É&iši¦I)H¯¾újÔñÅÉ=Þtà 7¤9çœ3¹Çœüñ8võÕWǤ'vüýètàÆ®î)PvÙe—ôùçŸçÓß_|qÚgŸ}b»í¶K×^{mZ}õÕÓ/~ñ‹ô—¿ü¥q^qc½õÖK{íµW±*¶5ù’P©¸÷þøÇ?¦_ýêWq S.›m¶YºãŽ;bwÀ€Ñ1:ûì³£N×ôêÕ+Í8ãŒ!6›nºi:ôÐCÓ*«¬’¦šjªä”ÜTºæškâz+AÓïCåÆolØ"±Zl±ÅÒÃ?œ¾ùæ›ô§?ý)¹§©þæ2ªþ7ÛóÒK/¥6Ú(&4zæÝu×]¹‰˜yä‘ýↄqµÕV‹ë¶Øb‹ô /ÄábûGuTã÷wÁ$ï²Ë.ÿòï!·©¾ºw»š¨éw£>ª¸ÇŸN=õÔ´ûî»7~_ª×¿'ý{ѤSÌŠ¶ë¸ŠÚÒïæ¶Ûn‹}MhõïÁ#ß]à£øZ S{y 'ÄCª£^ë#¯åÁ ÏB]yý*øÃ’‡“¼?Eš÷%zнòÊ+éÉ'ŸLÓM7]<ü%¦ý›o¾9i[b¼ãŽ;¦Ï>û,ýë_ÿJ‹,²H´/FBèëêñ –G›# qÂò€Š‡ý÷ß?y(4}üñÇ!hL0A:à€â¡*{d¿î¥É…D^åþûïO}úôIÛo¿}ˆ¾Äu×]wcу:(¶õá!׆ª½;ï¼3""MŒš‹&EÇ{lT{8¼4‰¯˜Ê#o.H‰o³Øè¼[o½5DFÛ;í´SŒÍ3Ï<“{ì±°_ÞŸÊd“MÜÅN‰ÔóÏ?õò5¹Ó¸jB¥¢sä+Òà¡ìÔ·oߨàb""T箼òÊÉCÇqL“7±Q¤`æ™gމ”HÜÅBüu„K¼UFÕÿ¢=š i²¥ß§®»ð þhÀ?äi«ïÍeĈñ{”è><Î[wÝuã´bûÅߟÎS$iöÙg ‰~cù7QlÿòË/>­½öÚ1ñÔ±¹PŸ{î¹Ós½˜ËƒoÒoP“°\4±Ô¤W“"M.çŸþ¤(¥øzŒS[Y)¤è ­±Æ!È­üSRÞ”ŠB”=y‘*¾VŸ9äØnÞ×ÃVÂZ MË‹’°}õÕWiì±Çnx»¿þõ¯Ã+VÇ|ÚvÛm£My_,=0¶×C8‡3ã„>d«Ä@EoÝW¶ª( OYamyjzxæ°ÄC"§}y¿Åc‡~x#L+QSt"yƒ Š] £&(ê“<·ì1æsõ-ÏVžšlò•Äôì³ÏÆa+Ai.ªWD#ÛY<îkºá«Naá¢×þË_þ2 80w’I&‰Ë4!Òò‡DE1U;aE$Dš(¨èþâ¢"o¸8i‘¸¯¿þúqLâ©Iœ&k¹}Ewt?M"rÑyŠ6tÔÿ¢=úíhb "® Çk sÑØäß`®Ó÷_ÿúט€ä:õKásý&Ší7ÿþÄQýÔùŠZé^Šä¢qP$HŒîôÉ\sQì‰'žh®Ï]lš‹~wóbäLÑ©‰&š(=÷ÜsqúÖ[oÿš¯e¿šzUµñí0ó Pc¿¸¡þ)áKíêzå7»p›{þqŸlŸOZìè£6_–ˆë|y!ƼØ'mÏ0à [d¯’¼Tt?cǶ>Æo¼Wm»›OŸ¨Êß—q,ÿ;Ô+{žG`¾FŸó]uþ±”¢u³œÝ\Jƒ]܈‡¾FZ·íâÛs»&ÊhWB–’½´î«5åSN9%’”tª s¬}+ËX‰j.b±V©$!ýåÒ¼¯z­•º‡ Cþo$i]÷óÉD¬G+¡KÉ{ÊH×:»ŠÖCµv­õQÝ[ëòJ¸kU”à¥d°\”ð¤Wÿ]tѤuie9«¨M­¥*1Ð,ú©z÷”#ùKÛ*Ť=%¼ù<Î×kxJîR¿T”€¨d°<Av+㿹(á,gÜ‹­’ùr%¾µ*ÊPÒ¢Öƒ•‰­ä+%úÉ_b‰<‰%—\2¹v¸Ç1«¤F1vñŽÄ>½’¥$F]ç Œ.¾£´Kÿ^•§Ì}EÎúV‚]æªöôzW^«×ï$'ÓimÛ#:%~[£êÑeŸkŒ” âQ•È9ðÈE´áË Üˆ¨(|è>ºF<ôÛ‘¹Û/þþt\o蹪qÖo)Û¨µwýî”ô©±RîÖÏ‹Eù#Zûo.y?gàçãJìTNBsQÞÆÔ'ƒÁNý¤Ô‡€¼†R _ Fi" ¤¨üúSÓ¡x¨éôsв”[µ+±ÕTEm·:GDz8h{TE"’²Ê2×;‰ª£X”ÝÝÙÒÑ5:–…·³íþØùz%:6 n~>gÂ7ŸSÜoÕF«ìîâ5ÅíŸ2Åóõþ¶Æ¸3¥h^#kG96î¥ÿèûýüÛ*Þ¿Ø~ñ÷—ÏQÅ»¹è7\¼¶ùx™ûJÔý(õ"ðŸ 4U9`_[Èk¹­:íYÑ­ªR¬­JqV e£J*ÓZì%š)ñME!P­÷*l¬p¼ÖR‹ëË:Ç3ÌõÕ©ÒÑ5ëÔMZœ¬p½ÂëÅâ¾Ã{„"ª=R<Ür»¹ äYÛ-ÏmUùSÆ¡x–ô×™R´G9Ês(%¸)d®„ˎʨƣØ~ñ÷—ÛUõÕï8_[Ö·ò(õ#€À×o̰¸&”§¤<%Æi _ë¬ZÇvï>ÖjÒ•Ÿd¦Öƒ}¥‘Xø“.ªùIî•›&4Ík×5ïæw=p(£/JòPÒÉøã_Fs]Þ†¿?lÊDÎÉ+]n7„ ”H€,úaÒ @ *øªŒv@€J$€À—“¦ @U!€ÀWe$°€ P"¾D˜4@¨ ¾*#€  ð%¤)@€@U ðU ì€ ”H/&MA€ªB¯ÊH` @ D|‰0i € P|UF; @%@àK„IS€ ª@à«2Ø@(‘_"Lš‚ T…_•‘À@€@‰øaÒ @ *øªŒv@€J$€À—“¦ @U!€ÀWe$°€ P"¾D˜4@¨ ¾*#€  ð%¤)@€@U ðU ì€ ”H/&MA€ªB¯ÊH` @ D|‰0i € P|UF; @%@àK„IS€ ª@à«2Ø@(‘_"Lš‚ T…_•‘À@€@‰øaÒ @ *øªŒv@€J$€À—“¦ @U!€ÀWe$°€ P"¾D˜4@¨ ¾*#€  ð%¤)@€@U ðU ì€ ”H/&MA€ªB¯ÊH` @ D|‰0i € P|UF; @%@àK„IS€ ª@à«2Ø@(‘_"Lš‚ T…_•‘À@€@‰øaÒ @ *øªŒv@€J$€À—“¦ @U!€ÀWe$°€ P"¾D˜4@¨ ¾*#€  ð%¤)@€@U ðU ì€ ”H/&MA€ªB¯ÊH` @ D½Êjkøðá6xð`ëÝ»wYMvi;C† ±aÆué=¹ @`t(Màûöík °ž={Ž.[Gk»C‡µ>}úŒÖ{Ð8 @ «”&ðW\qEWÙáŒ3ΰ—_~9š}ä‘Gì²Ë.‹í/¾øÂ¶ÜrËèËÚk¯m÷ßãÖC‡µÕV[-ú'›o»í¶Æ±+¯¼Ò–[n9›i¦™lƒ 60µ“Ëa‡f -´-¸à‚vÖYgåj{ë­·lúé§éïwÞ‰ãgŸ}vذÄKØ€×°tc‰îºë®tÈ!‡@£¾ùæ›4å”S¦k¯½6}ÿý÷aÑ™gž™\ðÔºý÷ß?í³Ï>?z^™'¸ˆ¦ 'œ0}ûí·Ñ¬ sºþúëc{‹-¶H²Iå•W^IK.¹dlëc£6J'tRì¿øâ‹©ÿþiĈéµ×^KSL1Eœ¯6·ÝvÛ´Ç{Äyâ°êª«¦aÆ¥÷ß?M=õÔIת¸ˆ'ÝOöèïÝwßún¸!-¶Øbé£>Jb«ëŸ{î¹8Æ Ð} àÁwãÉ[]»6ÖXcÙ×_m={ö´=zD7¶Új+;å”Sì»ï¾3}ûóŸÿl³Í6›Í7ß|vâ‰'6ºúè£Ú /ï¼óÎkW\q…Í8ãŒ7»Ùf›™‹§íµ×^k|"a:WÞò‘Gi_}õUãXq£ÕyòÚ_|ñ°wÓM7µì¥ï¾ûîöÆoØUW]eò¸Ud‡ ¶=ÿüó±ÿì³ÏÚüóÏÛ.ìq_õYý¿æškâ|íËS•Í7ß<úÔ»wo›tÒIƒÏ'Ÿ|Çn¼ñFó „Ýyç6Î8ã˜O’¢þüóÏ·}÷Ý7ÎïÕ«WD8! @Ýœ@÷»t®gxðã5ºÏ–§:öØc§wÞ9yèy¤Û¹ §ÕW_=ê_xá…Ô¯_¿ôôÓOÇ9“O>yz饗Ò}÷Ý×ÿñ Ow饗N.°éÖ[oM¯¾újr¡K.äéH¿øÅ/’O Ò|V^yåtÉ%—Œt?íŒê}’ }\£ˆ‚ÎÏeà 7Lp@Þåè¦zuóùK[uÏC¼áõÕ¹Ó{î¹§­·Þz¶Ã;ØÜsÏm.žá©sÌ1¶ë®»F×ÖZk-ÛÒ×µ'žxbóp¶M4ÑDöñÇÛ!CÂC–'~Ë-·Äúý 'œ^®"ºÞÃÓ&O^®‹¯zè¡ñ§5m•­·Þ:¼î7Þ8öóGGçù„ÂÖYgó0½½þúë¶À Xß¾}ãRyÑZŸßi§l·Ýv‹„Aåx¸<ÖÂgžyæè‡‡Ümši¦É·‹o#{×]w][i¥•ÇÁÐÚ»OJÍ…?<~õIÌ?üpüñãû¢‹.²VX!¢çž{n¬÷Ë»8p ]pÁöØ€º)n:qét·ºƒ¿üòËwºßU¼ÀÊF2Kµ¼ù|0ê:ê¨$ÏWòNýŸf¬9{‚]r!Œs´n}ðÁǶÖñµFîIz±óÍ7'«Ç¶OÒÛo¿ÛúðzúÕ¯~ÕØÏ§ÈÀã?§jý?¯¹«Â““‡Ø“ ~Dä«üñáÇŽ躼ήº7ß|3Í5×\ÉCëù”ÿøV$c‘EùzUÜ}÷Ýq_mûä'y¢^0Xc5"ªðÐCéèÆXƒï¦·ºvËCÛáÑ×ÁåMkú‰'ž0±‡÷yï½÷š‡ÚÍE<<ß©¦šÊòú»úî‚kË,³L`Ð:¹”åž½ù\ÙÑyzOÙë.ÆqºÚÎëêŸþ¹Í1ÇöØcÙ{ï½g>I‰5z(ûå™ç¢Ü‚¼Îî¡ýÈ W¿¹ÈEÞº/=äÝÈ?PäBe¿ýö‹>çƒO=õTDÔ®ú¨\­Õ{b_Dšû˜¯ãè>øî3–Ý¢'¾†nÓN;m$Ô©C>¹¶Aƒ…xûÚ²yæx„ìÎVÂÚqÇ¡x›^õÏ<óLˆ¸ê%öEAÓ¾^‰j çÿóŸÿÔi¦P»’Ï6Ùd“ØÏ§D9%Ïi¡¢ûÎ9眱­p¸ïTÜcŽä7÷Òcßsb‚¢MôzŸôT¶ß~ûùû:yìçM4´T ¢ÉÀé§ŸnZ®Pñ(DãÕiˆÀüJš¿Ëáòbð” çQ†x=Î…;®W ?rbIÂ' IJ"TQ2ú«°¼G,Òú믉}:æûÉß(ˆ>è~ze.-¨Ïþÿ Œ´|ó tO=Ô­n>‡ùIÝ“—(+{H?颊¤„*¢ŠYõóÍ‘÷©ðrNX+¶¤´É&›¬XõÚþ©íµ:Ov*j O_E6+ñ/—æý\¯o…Ø=û½(Õ¶¼wýï‘Ï•§ÞŠ—’øeÀsϤø†@÷'@œ®ûqm{¨5ëVb¥•)îi¯Õ}e§þriÞæý|ž¾õ.{g˸ãŽkúkUFÅK™õ@ ½°ß^ãMo!@ M ðm2Ðt€Ú‹ß^ãMo!@ M ðm2Ðt€Ú‹ß^ãMo!@ M ðm2Ðt€Ú‹ß^ãMo!@ M ðm2Ðt€Ú‹ß^ãMo!@ M ðm2Ðt€Ú‹ß^ãMo!@ M ðm2Ðt€Ú‹ß^ãMo!@ M ðm2Ðt€Ú‹ß^ãMo!@ M ðm2Ðt€Ú‹ß^ãMo!@ M ðm2Ðt€Ú‹ß^ãMo!@ M ðm2Ðt€Ú‹ß^ãMo!@ M ðm2Ðt€Ú‹ß^ãMo!@ M ðm2Ðt€Ú‹ß^ãMo!@ M ðm2Ðt€Ú‹ß^ãMo!@ M ðm2Ðt€Ú‹ß^ãMo!@ M ðm2Ðt€Ú‹ß^ãMo!@ M ðm2Ðt€Ú‹ß^ãMo!@ M ðm2Ðt€Ú‹ß^ãMo!@ M ðm2Ðt€Ú‹ß^ãMo!@ Môj“~þh7ß}÷]»ûî»íˆ#ŽøÑs«zÂ!CªjvA€@@à¾øâ‹Ûˆ#¬_¿~]<åÝnàÀå5FK€ PküÃ׿Ó_Ë$“LRgó±€J$À|‰0i € P|UF; @%@àK„IS€ ª@à«2Ø@(‘_"Lš‚ T…_•‘À@€@‰øaÒ @ *øªŒv@€J$€À—“¦ @U!€ÀWe$°€ P"¾D˜4@¨ ¾*#€  ð%¤)@€@U ðU ì€ ”H/&MA€ªB¯ÊH` @ D|‰0i € P|UF; @%@àK„IS€ ª@à«2Ø@(‘_"Lš‚ T…_•‘À@€@‰øaÒ @ *øªŒv@€J$€À—“¦ @U!€ÀWe$°€ P"¾D˜4@¨ ¾*#€  ð%¤)@€@U ðU ì€ ”H/&MA€ªB¯ÊH` @ D|‰0i € P|UF; @%@àK„IS€ ª@à«2Ø@(‘_"Lš‚ T…_•‘ÀÔœ@Jɾû÷ó!Ð} ðÝg,éIÉyä»ì²Ë¢ÕO>ùÄŽ8âˆÆn¾ùf[qÅmŽ9æ°wÜÑ>ÿüó8öÍ7ߨŸÿüg›o¾ùl–Yf±“N:©qÍСCmµÕV‹úUVYÅn»í¶Æ±³Ï>ÛfuV[b‰%lÀ€úŽ6:²/_÷Å_Ø‚ .h—_~y®²Ã;ÌZh¡¨?묳õ/¼ð‚m´ÑFa‡®yôÑGÇ~̾¯¿þÚ6Ùd»þúë×°Œa>ë¦tË/¿|7éI5º±ÜrË%¬0æ´ÓNK›o¾yl¿úê«iê©§N/¾øbúöÛo“ [:öØcãØ©§žšÖ\sÍôÕW_¥?ü0M?ýôé¾ûî‹c.žÉ?¶umÿþýÓˆ#Ò 7Ü[l±ôÑG%Ÿ ¤UW]5=÷Üsq^G£²/_£¶ÖYgä˜ôÒK/Eõ™gží6,½ÿþû~èà²Ë.›Î8ãŒ8鍊nJÓN;múþûï;´O÷ðÉCò MÜgÈ!q=€À˜'€?†'XÜþ? \uÕU¶ë®»Ú{ìaSL1…íµ×^öôÓO›‹ Í0à æâ]}õÕvøá‡‡ç(SåÈ# ¯Zžð­·Þu.RáUÏ6ÛláYŸxâ‰Q¯×_ÝV_}u›jª©lË-·´ÁƒDZµ×^Ûî¿ÿ~Û}÷Ýí裶ƒ:(îû·¿ýÍ\˜íñÇO¼gÏž6餓Ú|×-¼ðÂvúé§Ûxãg“M6™Í8ãŒ6|øð8öì³ÏÚüóÏÛ.ìæ“Óõ矾í»ï¾ÑN¯^½LÞý•W^çýûâBÿØy磿²o¦™fŠjŸ¤ØW\a½{÷ŽûõèÑÃ=øÃl‡vˆóYd‘¨»Žì“g×]wÙ!‡c5ÝtÓåÛó Œic~Žeöå—_ÖúOáž{î™\“ xzùå—“‹PrÁM¯¼òJ:á„Ò¯ýë@æ‚”< ^±O’¼SyµºÆE,Í>ûìqž zrOo½õVò0têׯ_Òùòžu½¼nátÌ1Ǥu×]7®‘×-/Ý…;y˜;ùä yX>ÎËãå"Ÿ|<´ž|b«ß·ÜrKò‰Cxùª¼öÚk“OP’‡ô£½o¼1ΕÍò‚sÙpà Óð²Ï—’OÒ¥—^šV^yåÜtã[÷S¤A\}ݼQŸ7¶Ùf›°Sû£²OÇòµçœsN0V¨^cz‚ÁýË# pƒ 6(¯Á1Ð’¼NyÇòÞ]Èíí·ß6ÿ§b"7wÛØcmM4QX¦ó´îë“§¹Ì2ËØ AƒÂ[•ÇêáóðB×Zk­ðÎ'žxb{íµ×âú?þØ.¼ðÂðÆwÛm·ho—]v oÝ'IáÙ/°ÀÖ·oßðÀ=,í;î¸ *ZC?ï¼ól‹-¶ˆuëÆßW+Ûþþ÷¿‡—îá÷X[Ÿyæ™MvxˆÜ¦™fš¸dÑEµsÏ=7Öçï¼óN8p ]pÁ?Û¾‹/¾Ø|ðAûÇ?þaûí·ŸÉ/±ÒÚ»l¼ýöÛm¬±Fä)šðÀØ=÷ÜÓ¡}:˜¯ÕX(zA*D ó ¬€Àÿ'à¶jä5{X»qpë­·/^“L2IxäÚ–-o¹U9ꨣÂs–÷,oÔÿù¥wÞy'm»í¶á½çk´žî¡õðØ÷ÙgŸ´ÿþûÇ!Of O?ŸWüözr‘‹èB®—§îK éŽ;îÈUéøã9W¨}ŸÄÄ®O6’OÌÒ„N˜ÖXc°á¡‡úYö=óÌ3©OŸ>é”SNI>IH>IIÛm·]zê©§ò­ߊl¸ø7öåo¿ýöÉ'±>ŸŒÊ¾|\ßK.¹dD\ŠulCc–ÀÈS÷ M<0¥= ÈSÖºð<óÌ{ì1sñhÀ§¨õvyâZçÖººŠ'wYqýדÔ‹Õ:¼¼á{ï½×ÔöÁž³ÖÜ]äÍEµÑ¶²Æ}`L0=ñÄõrmË›WyóÍ7ÃkÏÉ ×Z»"*×]wùÄÁyœ×‘}¹!E|Ÿð Š@à+2˜ñ¿²€gÚ—Ø©øú|^¢[ +©N®„6‰Òf›mÂé™â1 +dÜqÇ™¯ÍG{šDäWÕÔöÉ}:èž°Í9çœq^q[âëž½½÷Þ{qLápMÔÖ»ï¾"©ä?%ËÒK/ö©îÓO?5£D>ÝW!tϸWíÜÓ·½÷ÞÛ”l÷sìóõvS’¢þN>ùäXŽÐë•>-ázè¡a–&JÔò…Ê%—\ay½þWœôtd_\èJLTÒž–P(€@u ðÕ ,qEAâ¾²Ð=A.²¿U_x‰¬²í—Zj©¨Wf¼<ÙõÖ[/ÄX€•VZ)DhœqÆ ÖR½›®Ìv­ßK”µ¯¢Ly]«ãšhÍZ‘ ™& Æyç7²öµf®6/ºè¢È¦W¼Öêõ—×÷µN/û=2î§}Or‹(„‡ë#J!¡—è+ÿ@åçØþ𡈄&CŠˆ¨è~ŠPhÍ_ýSÉïö{HßüUºˆdÛµF¯(ɨì‹ü£y,r=߀À˜%ÐC+cÖîòȃ׫gJÆ+%¹)”Þª(4®Ä½œ0–ÏQè<'ôé?ŒüñG:GѽÆ×™¢¸&#y’‘¯UÒêä¹7—Ÿk_s;y_Þ»þrßr}GßÙ×ÑuƒÆ~̱ç΀ ÑF€ýhCKÀ 1Gsì¹3 @`´@àGZ† Œ9ü˜cÏ!@£ÀÿçD!pcëIEND®B`‚rotl/vignettes/fig-vignettes-unnamed-chunk-1-1.png0000644000176200001440000005045315132136164021563 0ustar liggesusers‰PNG  IHDRøh4,~k pHYs  ÒÝ~ü IDATxœìÝy@Ìùÿð÷gf:¦ƒÎé>•R*‰ºuÈQ¹BY!’Ú±Žr”]¹o¾Eî#÷/)­ëÊ"iI‰H§N]s~~DRŸjfÊf?^¿Ìçó>^ïûœÏ|>Ÿ™ÅpGÈ‹ÒÓø¾ è€ä è€ä è€äh=]à«§OŸ&&&¾zõª´´TLLLUUÕÊÊj̘1òòò=]øÃà©~III6l066;v¬‰‰ ƒÁhll,((¸sçN||¼ŠŠJDD„††FO— þ“ èèaþþþòòò«V­jïÌ=55uÙ²e ,?~ü¿\ zzRCCÃØ±c&L˜ÐiKÿáÇþ;µÒ€  ]ÅÅŧOŸ~ôèQee¥ªªª“““———¨¨h7Náãã3~üøqãÆñÓ˜ËåŽ?>88xĈÝX =xêb[¶l™:uª’’RTTÔ©S§-Zôþý{{{û;wît×ñññÊÊÊ|¦à?ÿt¯85­F†´Hïi L„sÏ-r1R“gh[LŒºUÊC!VN\½¾²¼¼r¿‘«¯•áá•©›&š«ËÉÈ*ê õ?ò’‰"š¯zG㤇›;ÿ~,ÜIßn}‡ *NÆ Kß@Gm9e«ùq—wMµÐfÈ«Y/L*Áë“giÚmÃC!Γ•f‹RYÅpKo®›`¡­(§lä¶ìb>›x±_|:1^oÜÂÙVêò²JúvóNd74­ZÀÚB¯y¸ÕËPQF±Ï0ÿ™Ÿ A1­tÿ§ þË*++GÕq›úúú#Ft:TccãÕ«W««« ÷N˜0¡¬¬L˜q|íÚµW¯^¦gÝ_óõ¥tÜBw_¸÷º’ݼ™õ0ÌTÓ#:ë§öùvW•á›sŸ®6Uý²ž[÷b‡‹‚ÝŽ·\œý`©ñ°–—nxÅç§é›-¹Sƒ³3"-”ÖÝ/g5ä_œk¬4îx1WqrÃnÃó:ûCÜ-«uYnÎæaª±y8¯êÞRs€«L¢Ùø«‡p4öã0ãÞš›”±«ÂÙOW›Š÷ H*æ°ócFöít¥”ËÊÙá(ë]Ä«>?EÕm_Ç9™‘z!·˜mËcåǸ© ¿UÂb•Þ³VrÜõšK°ØæÃTsÜCœÖÇïL^=³ìn¤ cÈú8ÂÔVsÜCœ¦7ãìçqÍW?aá\‚bZÿµ“ü›±ÑÑÑÏŸ?—’’êéB0oÞ|pwwâM¢òèXÝ3ãr/ùÉcˆÚ[Ï!`óÂÝS• ½Ë KyH‹‚Pã³S»rÌ~ÕC¨íÍ诟nž¹‰ºüÆ|cQ„¢È+Ê–½ùÀB&t„ðŠ…lYùÞXmQ•ÖÌØÔ´ªœkë§O[pÔî0-4ô¹óÕg)¦RXmÜ8­„&×zvck¾êÁ‹· !„…JÅÚ«Š‚*:„ØïJz+ÉQ…© áœᅫSª Á ÉÓúæ+܌ࢢ¢ººº>ì Íþýû'OnýÙœPQ9xð`¡Éðà©©©{;޳y´~ááÇ¥Lqªs/oÜ—Þ„­Ê@wÎéM'rðÆW‡Ã~Kȧµñ!T{/bfŒòïûæôù|®HÕw¥¸ywz ]øçº½™6öÒxñ™¹³d×SeÔ´”$©TÆe21eE ŒWù(æh*“Íæ óÖ³‹·ÙBXÎ!­%ª:=HuW7¥Ä•[s=‡ÓAy¢nc4.¯ßr¯œƒÊØáë~ýÞv±ß| b?Œ‰JxÏâV¦m[w¡—ûè~bBÕ†Øi1.°¸•iÛ¢.*xŒ5!*¦Í’:€ŸÌêÕ«CCCkkk ÷¦§§§¦¦vý7g<<<þïÿþOˆŽÅÅÅ’’’Â]·¡¨O?|ñWñc¾& ’ô޺Αy.N.0¤Š<·RfÿH]†¶Ûq¥Èè@ý¡dþý¬*¥ÿÆEbû5•ô=/lÛ>MM}êªy ëé˜{îÆ¼üLo/ <_.ÖfvI¾ê¡¨Ö2åhUu~”¨}Ü\*xN^v!Ôöàˆ†œØk•:g€*Ã`òÓ1³µ(mÛr*LÒÁ]éШ>ʆ““ô7ž,*\mTU'îÆa* ý|¯šì8µÄ„†¨Å´é'ÌûÿŽ5kÖܸq£§«ÿ=W®\±··ÏÍÍmµýÒ¥KÆ +,,äsœôôôöN˜0¡ã„‚‚‚ºå[ ]Üüöª¾ñ5Ý5žÐ_tê.$¿F€p\\\TUU,X@§Ó‡.''—ŸŸíÚ5SSÓË—/÷êÕ«[fùý÷߃‚‚’““EDDøìòøñã·oß:;;wK€‡UõôÀ±WŽ+„ùÌôc‚ €Xÿþý/]ºôþýû´´´ÌÌÌ!C†ÌŸ?¿{Õ500˜:ujHHÈÞ½{;ºñùEaaapp°p|Ÿêç˜gØEœtïžws„¢Û,Þ×G›ß7óï‚€Žhhh¨««ëéé™™™}ñgΜY\\|866VBB‚pâââ„„„¬¬¬ììl=====½±cÇêêê6ær¹Ë—/ûöí¶mÛúôéÓr—‘‘‘““SDDĹsç\\\6oÞ<|øðn\,øIÀ5z¾zðàÁÌ™39ÔÞÕƒ±{÷noooww÷êêêV{‹ŠŠüýýýýýEDDüýý:4oÞ<55µ+VŒ7.;;»U{‡ãíí­¡¡qæÌ™V)ß Ã°‰'^¾|ù?þ8wî\×— ~:¸ –.]zÿþ}ºô¬5kÖܸq£§«ÿ >|:thII Ÿí¯^½:jÔ(‡Ó¼åÑ£GC† ¹}û6aûçÏŸÛÚÚ&$$´Üò¿ÿýÏ™L¦‹‹Ëƒøl@8£à³   Ý»w3 >Û1bøðáû÷ïozùúõëøøxÂöÆÆÆÉÉÉ{÷î½sçNÓ–¿þú«¦¦fîܹ|Î(**zäÈ‘… r8>»€àÒ MîÞ½«  `nn.P¯… =z´¾¾Çñ€€€Ã‡+))uÐ^BBâĉ¿ýö[}}=BhíÚµëÖ­hFeee//¯#GŽÔ«üÓÓóœMµr2òš=–Ïmv(„âd¬±¼ö9·+c ûÞâ~Ã6å“v}Wô „ÐBCCí%&&6a„˗/'&&ZZZêëëwÚENNnîܹ{÷îÍÌÌÔ××WQQtÒÀÀÀ¸¸8A{}VcÙ¸5…‡Ò +*?ü½ÝòqÈ„?±„L8<«ÃÏ#8÷o•" Î*ÿŒfph§·:U°]ß=ˆÇãåää Ñ×ÃÃãâÅ‹'Ožœ={6Ÿ]&Ožœ””tñâE!f””””––.))¢/÷]Úà «)~ò4„‰«Ù.YjÊ)¬À^™ºi¢¹ºœŒ¬¢ÎPÿ#/™!„_ q2TUT5´ó´–p BÜ¢+Ë ”åätW¤”áŽÆI7wþýX¸“¾Ýú,Ncî¹E.Fjò m‹‰Q·Jy¨éÃ¥o £¶‚œŒ²Õü¸Ë»¦Zh3äÕ¬&•àõɳ4í¶¿á!„çÉJ3ƒE©,‚b¸¥7×M°ÐV”S6r[v1ŸB¬œ¸ {}eyyå~#W_+Ã[¾Fø¶òo¼Íßçª0êP)ŽBÜW†(O½P‘}Àþé.ÁÔÜæ]Äœ¨þn!Ð}¸ HéÇS§Nº»½½½­­­@]F5~üøââbáfþvÝ_óõ¥tÜBw_¸÷º’ݼ™›³y˜ªGl^#Ϋº·Ô\#à*ÇYÃL5=¢³>qjŸowU¾9§¡Í–Ƨ«ME•ÆD¿¬çÖ½Øá¢`·ã-—x4öã0ãÞš›”±pvF¤…’úû嬆ü‹s•Æ/æáì§«MÅû$sØù1#{‰ö ºRÊeåìp”uŽ.âUŸŸ¢ê¶¯ˆ‡ãœÌH ½[̶å±òcÜÔ††ß*a±Jo‡Y+9îzÍåUœǰÛð¼ŽÇþ7EËj]Ö×›çüðMåÜÖ vÜÜéȘWÉÃqîë­6j¾ñ5ìK‡m|Å!˜úË.âCÔfð]¯¹ÂýiäÏÑ—••%&&æääôt!ðððèø:/è^õõõ™™™ÊÊÊB€ã¸ ß\ÕÐÐxøð¡‚‚‚p3ª©©eee 8°wïÞ‚õ”°ß|ëÊ€}‡ã7N[éóQf û/‹#—yê‰kú_ÈWeVÖ㔚êqž]ˆgNØ7ÓHŠŠŒçì<¢öQ´Í !Š’gˆŸ‚ôl­4ŽUÂ…`4„¤\ƒ-D¸//•ŒŽX`%'‚äF‡™Åߪõ‡UÇÃÏY‰Jã ¨m`>ÃQ‘B“±¨|æS-.m?Êê× 7ªü½K“*]£¬(­Š¡—$M·[|Ζ!‚ÍoÁCuNܪG£ñÊ^<|V m9ùäÛÉ-Ž'£õrˆG˜öµr¼°MƒÜ c ×_¾U7yLerR¾ó'iôOÓø¥ÍÔœ´Ïs"¼˜hv]L¸$-‘<è'OžüæÍqqñž.Dÿ­jI€B¡ˆˆˆðºvaÇñεÀår)Š ½Zv¥Ñ„ùï—¦2ÔoõP¿Õˆ[{;îùÓÇ4¤<Û`V˜²!é5OQÏH²WBñJŠÊ•ÍÕš®'Óû:OèËJÚßj âd CU©©Œò9“xmGC!Š’š2 !Ä+/«dhª‹6mTÔÔ •—VñB˜˜¸8†BF¡ÓéBÃ0 Ca²N#M—%ß®±zTê²ÚZŒw½uyœ'ÉÅuW— 1Yõy>-3JÞÛkËñœe‘SM‚jTm|ö®ó1úü-·¶ $¡EåÜ’ÂÖ hŠîct¶_¾Wo™Ÿ”çü«ƒÔ×CÝvê¾ÍûÁà”!úÎ >¾I:&..Þ¿ÿ˜˜¡GÀ0ŒÍìrê»wïtuuKJJÔÔÔ„˜±°°ÐÉÉIRRRÐŽ•GÇêž—{ÉOCÔÞz›&èžÊ(/Ê }î|õYŠ©V7N+!„É)ô.+,å!- BÏNíÊ1Òz‹Ù¯z5%ñWxññ¶£!„¢P©Bˆ"¯([öæ ™ÐÂ+>²eå{SPE‡¥c —‘zQIg/äŒX6Lœ </y9y¯°G1.b!Né‹ô*%u¬¶ Jkflê ZUεõÓ§-8jÿç\5 "\ áTöµrÙ¶ 4û”ŽR›ôç ü×Îóì%úrï-j=uâÀÑàêÝsnÆ€ „;¿~þü¹¾¾~ß¾}ÿùç>»ÔÖÖr¹ÜÁƒß¿_ˆB=211¢coÇq6Ö/<ü¸”‰#NuîåûÒû°•ç2™˜Œ²¢Æ«|s4•Éfsˆ¹‡;çô¦9 xã«Ãa¿%äÓ¶ÞB#:ÛÄ9£µDÕw¥¸ywz ]øçº½™6öÒÖNQwuSJ\¹5ÇÑs8”'ªé6Fãòú-÷Ê9ø§Œ¾®á×?áxñ™¹³d×SeÔ´”$©TÚ—üŽðM  ¨úcFõJX¾ùåˆI¶ô–Ç¡ý© áàüÿÝvH +úÿ¹›±ð)00ðñãÇBtŒŒŒLLL¼yóf`` Ÿ]¶nÝ“““ããã#ÄŒnnnBtÄqÇyå÷wÏv0dHÑÅ%ä´-'¬J|ËÂq^ÅÍWU;¦¶Ó·Äüf­¨1íÜGþéÙÙÃú(+(é ›uèy=Ž·ÙÂ~ºzà ÈLŽã_ÿL8ëq˜é—–8Þðêô|'5†–ùøßos>w°ò ÇqvzøËß³88޳ï/1¾)‡Û4Á*QÆôKµŸ×Ò¶<æÛ„eîÆêŠ *†Î¡òØ8ŽóªR7z™ªÊË3Tû:|ÙØòhð5û›Ê àì'+û‹iÿÕ€ã8Ž7ßqm;õ×]ÄœhðîAŽãøÓ§O'Mš$h¯šškkk‹…㸧§'??NŸŸ?lØ06›ã¸»»{NNŽ “†……={VÐ^dÀÍßi¯ê_ÓÓuü÷À¥BÈÌÌL\\üúõëõZ³fÍüù󛹉‰‰Y°`AÛŸ-k©´´Ô××7&&¦é>êÚµkCCCqA.½zõêÞ½{ãǨN2à°ªÒ{å8Þ¡ó«< z>Û¾}ûªU«òòòølòäÉÊÊJoo聯 ãøñãþþþ'Nœ |†'%%ÅÓÓsóæÍÆÆÆM[hmmÁçŒUUU3fÌØ·o_ëÛŸ?ºÄ9&ž }#V¸Ãoò èlbÙ²e^^^VVV߯ zЫW¯¦OŸ¾cÇKKËŽ[îÙ³'%%åÌ™3bbb-·×ÕÕmÙ²åÊ•+...JJJåååÏŸ?¿|ùrÿþýW­ZÕöÙùàà`:¾~ýz*µ£¯ÆçååMŸ>ý?þ°µµnuà§AÀ7JKKýüüú÷ï¿|ùrYYÙ¶ ²²²Â ֭[×^43™Ì›7o>þüùóçÎÎÎRRR„B»wï¾páBDDá/_666îÞ½ûâÅ‹±±±B/ ü´ è pñâÅ;wÊÊÊ:99ihhÈÊÊ–””dgg_¿~]QQqåÊ•FFFüŒóäÉ>óÇk×®}ñâ…±±±ššZmmmaaá­[·šÎåýüü„û†ô´ëÇ·oßþðáCvv¶©©©®®®½½½@_Sâ?è›°Ùì;wîdggÿóÏ? :::ÖÖÖüü(&€Ú¥¦¦6eÊÇŸ={fffö/Ì(""âèèèè蘓“£¢¢ÒÁÕøOÝÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉÑzºH¨¶¶öêÕ«yyyÏŸ?ïÛ·¯¶¶¶³³³‚‚BO×~Rôt§wïÞ­^½º  ÀÕÕµ_¿~¶¶¶åååyyy~~~¢¢¢&&&tÏÌÌ<þü£G>~ü(&&¦¦¦æâââéé)##ó¯-=Ý&...::zýúõÖÖÖ­vÍ›7ïåË—K–,6lØÒ¥K1 kÕàÍ›7‹/–””ôññY²d‰¤¤$BèÝ»wÉÉÉcÆŒ;vì¢E‹¨Tê¿´@.p€î±wïÞ?ÿü3%%¥mÊ7144LHHhll\°`A«]wïÞõññY½zõÑ£G]]]›R!¤©©póæM‘qãÆÕÖÖ~ß5’‚  ܼy3%%åàÁƒbbb4Ã0lÍš5†ÅÆÆ6o|ùòåòåË“’’LMM {Q©Ô Ìš5ËÏÏÇãuoåàgA@Wq¹Ü•+WtèPee%BÇñÀÀÀ£GÊÊÊvÜkìØ± 8xð`7T ~2ôtÕÿýßÿ¹¹¹ÉÉÉñÙžF£-\¸pïÞ½M}mlltttøé¸xñ⃲Ùl¡Kv‘¡Q)*MDDDDDÒ~çÛ6ŸØ÷6xGÝåcNÆ‹ÁkŸs…®¨û|©¹gK"œ}oq¿a›r¸ˆ“>`HÔ‹½6zºêüùóS§N¨Ë˜1c®]»†Š‹‹›={6Ÿ½ÄÅÅGŒqóæMA+l67¥ŽÍf³RC t~ý«žÍf³ën†h·É^IƧÅ-òŸÇbq„žõ3\ˆËN8ÎwÓ65ó¯Åê„)²S4ã€C;½Õ{îV:=]UXXÈç)y311111±†††’’ þ;º¸¸t%è‰pKo®›`¡­(§lä¶ìb>q_8¹êJ¨uHüípsçß…;éÛ­ÏbW¦nšh®.'#«¨3ÔÿÈKæ—Š®,w6P–“Óu\‘’y–¦Ýö7<„âc…¥o £¶‚œŒ²Õü¸Ë»¦Zh3äÕ¬&•àD ÄÉX3È~áº)†ŠròŠ}œÂ®~ÄBx; Ô²æÄÚV%•á„ËDˆ“þuu;.²1÷Ü"#5y†¶ÅĨ[¥<„ЧãõÆ-œm¥./«¤o7ïDvÑ)Ãâf🺠å‰|kùàñJÐ%OžˆûáÒ%ÎÉ;ÒéÆóÛ9ðîRýÖ$.`DˆZÛÃþºýµ|ô K.]ºTPP0hРž.D-_òx<§£ËŸ>}ª®®nll¤Óém÷ ý •Je2™Š`Ÿª) —Ëm*¸ã²ùƒ'M·[|Ζ!‚ÍoÁCuNܪÒmñކI¹[*ˆ ¤é!#@^A”YUXSjªkš.«P”#<7l¼‚†…®³?üü‹ÅËf'ªïµt zÐ% †††“&MêéB„'!!ÑñiõÔ©Sû÷ïollÜ^á²þÇVVVuuuõzÿþ½žžžªªª3á–×]]2ÄdÕç Zf”µzŠ’šrSNð S"B6$½æ)êIVã_>QªJM 0 †&ë4ÒtYòí«×I¥.«­ÅBÇBÃ(t:Ca†aí€EA™ÑôI Ã0„wP@[­Jêh–æÕuT$¯¼¬’¡©ÞtÆMQÔÔ •—VñÂhêZjMïÔbZºÊå…e<$×vv"|¯¥[@ÐÐU êêêüwa³ÙŸ>}’”””““+**RQQá³ãµk×lmm…*“EV^NÞ+ìQŒ‹BˆSú"½JI‚X-›P©B/>úÜùê³S)¬6nœV—­¾æ‹1\FêE%½[0bÙ0q„:üÜÑN¨MD¶_@[­¿yÜÎ,eÍ«ëE^Q¶ìÍ2¡#„W|(dËÊ÷¦ „s ÞòP Bì‚w%½•ä0¢ÙÛd-ÝnÆÐUžžžgÏž¨ËÕ«WíììB'NOù?˜Ý‚€®òöö>{ölÇwt[Âq|ãÆAAAM}‹‹‹ùé¸gÏžI“&‰‹‹ _kTÃ{­Rç PeL¾bº#f¶!Z_K³´æ¿þæEmêªy ëé˜{îÆ¼üLo/ <_N˜–Ô>n. <'/;>î4@ ³jbb´KOïèeª‘’úа"ï¸}>*B“tpW:4ª²áä$ý§Ãó{;•x-$(\K—.½ÿ¾@]¹íÙ³çôéÓ=]Å÷Åãñž>}Úq›‹/úúúò9`ddä¦M›š_>zôÈÑѱ®®®ã^·nÝrssc±X|ÎÒ“¸ù;íU}ãkzºŽï«æ¸'Ã÷bcO—Á8£ Œ;VOOoñâÅÞ˜ýßÿþ—Ú¼ÅÂÂbÑ¢E£FÊÏÏo¯×ñãÇ###Oœ8!""ÒmE'VUúc¯Ç;ü—º%7zºÇêÕ«544<<<^½zEØ ¸¸xÆŒÙÙÙ‡nu»nÔ¨Q;wîô÷÷ MOOoÞ^WW×ôû Ïž=KJJâÿWzP]âÏ„¾+Ü{õt)ßÝfñ¾ ‹þ!xê€n4þ|{{û%K–ˆŠŠŽ3ÆØØXAA¡ºº:;;;))éýû÷aaaíÝJ511¹zõêõë×cccÿùç ø\®„„„££ãþýûúölÏ’ô<üÞ³§‹øWÐ4‡yhötü  ;™™™]¼x±  àòåË'OžÌÎÎÖÓÓÓÑÑY¾|¹A§ÝœœœœœB999***RRRß¿d@~ôt?uuõ9sæ „ž|xŸ>}¾S)¾¸t$A$A$A$A$A$A$¿^ùc‰ŒŒzô¨‚‚BÛ½† ]‰ŠŠJnn®ººzZZZ{e6©¬¬lyÊ/***&&&ôìgÞ>vñ•òp}IÞëK·³ƒïÍÒnü{¹ƒ÷ö;S¢GPb?ÜÞõìƒÛ–rù[l‰p2âçÓÊ\˜Æšø-žvéVÞ‘êÝn–;â—ºÏf˜î›4èdZœ5v?ÂcâÌ“«Áé¿O\ún^ò«­üÝãqºfÓI™L Œ!„Õ0èÔæTõSãþÞé^²oT›I›÷ŽÎ ïpEíý]~=…ãk¶iÏ{}°íñþ¯ª« èA—hjj^»víìÙ³=]ˆ¦OŸÞ¯_¿æ— eee´OKK+++{ñâ…A«]8Žw%èÅÄÄŠŠŠDEEËËËUUU;n,""RTTÔ2Ùedd„ znî[éB<M¾ÿèˆcaCD(lÿ ò ¢ÌªÂzœRS]ÓtºŒI¹[*ˆ ¤IÜ€ªãáç¬D¥q Ô60Ÿá¨H¡ÉXT>ó©–W|õlºÝâs¶ „l~ ªsâVE€É…xæ„}3¤¨ÈxÎÎ#j%:=|íO#Ôª7^œÔvÒ Ý¯o묨½b¾ô ‰ÆŸÖ¦=¥ÃÕS èA—Lœ8qâĉ=]E—ôêÕ«W¯^4øý÷ßÇŒ3dȽ8.üÂ>|°²²’””´´´|úôiÇ?}úÔò>­ð¨z¡·3×[~ûß>¯0%"dCÒkž¢ž‘d5®ôy3EIM™ÖQLL\C! £Ðét !„a†!Ä-),®»ºdˆÉªÏMµÌ( Ü’¢resµ¦‹Øô¾Îú"Na•_kûS´E8)ŽZ}§+"¬áK¯vÆo«óÁÿUôt®ƒß#£ÓéUUU\^oŽãÕÕÕMë888¬[·nÙ²e ñm³;w› :ÿµ }î|õYŠ©V7N«ùv…JÅ:lÐ.Ь¼œ¼WØ£1„§ôEz•’:5[¡wYa)iQj|vjWŽÙ¯- ùœ­ÜŠU¸¶à !œ”‚X-›t¶"Â>÷jgüÖ…8\ßÜŒ KÜÜÜ’““…蘞ž>pàÀ¦?Óét­[·¶¬¯¯ [ºt©ðUvç0™˜Œ²¢Æ«|s4•ÉfskÐEÃmŒÆåõ[î•sðO;|]ïÂEÌ=Ü9§7ÈiÀ_û-!ŸÖ|fŽI÷¢çþý ”‡^ÄîIªô“Îd2 'mÞÛùŠ:«¡ýñ»z¸¾/zºdÒ¤I±±±B\ÀÙµk×´i_¯î†††>yòdýúõÎ7™PPPàéé¹téÒ–_­ênµ©«æ5¬¤c`î¹óò3½½$ð|9.@TÃ{­Rç PeL¾bº#f¶‰<·RfÿH]†¶Ûq¥Èè@ýægi&³ÂǼ]b¦,¯ät^ÍÁP ‡i}-ÍÒ˜$ªLÚ¼÷bm'+¢vVá¢ø<ž‚¬§›aý]¶l™———••Õ÷+è'·yófCCÃÑ£G÷t!à+ÇŸ={fffÖ^ƒ+V˜™™y{{ó?fzzzTTT«›Ø8Žoß¾ýìÙ³ŽŽŽuuuÿýwaaáúõë-,,„_À Ϊ­Ã%¥Ä„¿ÇMŽº\£ «V¬X1räHSSÓ–ótàãÇÁÁÁgΜiµð… ¥¦¦>xð@II)<<\__ÿ;”üÃD{þ—Ü~„º=]%%%uìØ±)S¦ìÝ»·Ó[¦ïÞ½óõõݲeK{—bDEEÔÕÕUTTà×+A·€kôtmmíóçχ††nÙ²¥Õ]¿f<ïèÑ£ÞÞÞ{÷îµ¶¶þ—+?3zº‡ªªjJJŠ´´´½½ýÒ¥KoݺUXXÈf³‹‹‹íø î?”—/_Ι3¯t#’½ªªêäÉ“zº~5=GßÓUHnÆÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐÉAÐðca±X/_¾|øðá£G {º@´ž.r*..þçŸ=zTZZjhh¨¥¥Õi—û÷ïoß¾½¸¸ØÐÐPEEåéÓ§111ïß¿wtt\¸p¡¬¬ì¿P6 %zºYBBÂÎ;{õê5`À%%¥ôôô£GLŸ>}úôéT*µm—ÚÚÚ¹sçÒh´uëÖéêê¶ÜÅårÇŒ4eÊ”k€T èh‹ÅºyófZZZ^^ž©©©½½ý€:h_[[ëçç§­­}öìÙV'à ;wîtqq9~ü¸ŠŠJË]ååå^^^Ë–-swwo;&•Jõðð9rä¼yórssW®\Ù-K?¸F±S§NÙÛÛß»wÏÒÒrîܹZZZ{öìqvv~þü9a{&“éåå5sæÌÍ›7·½ÌB§Ó—.]ºiÓ¦ñãÇ—••5og³Ù>>>QQQ„)ßLTT466öÝ»wÇŽëúÒÀÏÎè YTTtýúu:Þ¼ÑËËëíÛ·~~~vvv­º,Z´Èßß¿ã¼8pàÖ­[ýüü’’’š¶DGG9rذaüTµgÏ''§‘#G*((¸ ðSƒ3zZ‹ÿþýÿþ÷¿–)ßD[[;>>~ÅŠ¥¥¥-·ÿóÏ?ÅÅÅÞÞÞ>dÈ##£K—.!„˜LæÉ“'çÍ›Çga¢¢¢+V¬Ø´iŸí‰ñJïl›i×—!E塞?ü—Í7‹y!ÄÉXc1xísî7m9éá†D½àÔ%xi¬»î¼¬îù»bß[Üoئœvá1È×þ·Á;ê.ûëŒMnXz¾ãøÆ·nÝÚ^™ˆˆˆ¨¨¨–8ÊçK–,‰E]¿~}äÈ‘"""ü—çææ–ššŠã8ÿ]¾Uÿ0rôÄ#T¿c + Ÿœ ?:Åwo{ÁÅ'œÇëRÿîYøcÓÅâm§Úé­Þâ†z§ko"Ä+ɸñ´˜÷uƦ?7 =ßxøðáàÁƒ¥¥¥;h3bĈ´´4^‹zøðá!Cøœ‚Á`|úô‰ÅbݸqÃÕÕU ò0 300ÈÉɨW3¼èTÄ^ñ¥ç¢gXiö—R1÷ٺɇù÷‚¦¥p‹®,w6P–“Óu\‘RöM‚á•©›&š«ËÉÈ*ê õ?ò’‰šN`-}µäd”­æÇ]Þ5ÕB›!¯f½0©¯Ož¥i·ýMÓ§…'+Í ¥²ðª‡;}k)2úXNÞþ úó¹ç¹©É3´-&FÝ*åu6r»]Ù/\7ÅPQN^±SØÕx;e#VN\½¾²¼¼r¿‘«¯µ\''=ÜÜù÷cáNúvë³8ÜÒ›ë&Xh+Ê)¹-»˜ÏFq³øÏ?]Àmg:ÂcHxèZNÄnsX¸/÷L^œ\u%Ô:äâãÏ36M-Üß;\£ÿ±p8œâââ¼¼¼ž.„_ ECCƒð‘Áÿ Çd2›_>~üxðàÁöÒÔÔÌÏÏWVVnzI¥R)N›´´´òòòòóóµµµ¬ikkçææjhhˆŠŠ zäëï¥Ü×»]çk/)×Íw\Bˆƒ'ë­€[O 5òw{Ù¬‹ ¢ö¥ïõÁ¥ÛÙÁw‹fi7þ½ÜÁ{û)Ñ#(q2âçÓÊ\˜Æšø-žvéVÞ‘êÝn–;â—ºO5ÊÌÌÌÌÌ|rýLôª1êßF|¬ZÃöÝç‰K7ƒ àrrrýõWmÖ®]Ôr‹——W\\ŸS¤¤¤4=8?vìØ .TÞÇ1 ëÝ»·@½šQ4¦­žU5!ààƒ‚Z»"óäÂßÎ+Íš5L´ã~8‡ÉÄd”%0^壘£©L6›øY‘ogSwuSJ\¹5ÇÑs8!Q+×òƒ‘G_Öñê_‰:–ËEQõÝG)$nÞ^Ãcþ¹no¦‡}G7ÂêBX6^|f®Ã¬ÙõT5-%I*•ÖæãKÓ¡r£qyý–{åüSÆ_×ð럄yÀ¦ÓCGxXšº¶¼yÔ%ô´¶~ýú°°°—/_î=vìØÇ=<Å&hœ,†¢ XzzGÿ+S”Ô‡†yÇíóQiçcE3¾»–]©ë¿q‘Ø>GME%}ÏKÛ¶O#îM5 9±×*uÎU†Áä+¦;bfk “—:ÂÂh}-ÍÒ˜\¬bÒ6pA,]ºôþýûuéYkÖ¬¹qãFOWþ{òòòlllvïÞ]__ß¼±   `æÌ™m»ÜºuËÝÝÉdv0,Ç 8tèP󖬬,''§Ž{5»wïÞèÑ£ù]À›¿Ó^Õ7¾¦§ëøÙ v3¶¶¶Ößß_LL¬;Þbþ ïÞ½SPPpppèéBÀŒŽŽÎõë×÷ïß?jÔ(„¤¤dUU•¢¢bPP““a[[ÛÂÂÂ1cÆ9r¤ù±Ë–>}úhllìçç×¼ÑÈÈhÆŒ3gÎBëêÒ*º=X·nÝìÙ³¯_¿.hÇÊÊÊ]»v½~ýšÿ.™™™ššš“'OQTTqé»I^çœ_ñk,mî©Í#e\·ü½s´”İQÃs¯\+Åâ¾LL®wóLy¶irðS‡C™Åïn¯V8áW‚ã•ç—-ÈrÏûX’¾ZöHxì+ý /ƒ¸W˜î›Ôo[ZaIfÌ Û3cò9±åd>ħ•}|)Øoq¶ßŸy,•8²#¾EFÖý>uKý줼Oö }šöÍ[I›Ú^p[/9&—I°(Ôñø¼w¬‹ŸUt#Ú÷ôÇÑØØ.!!ÑÓ…`÷îÝ=]ÅO¤¢¢âÝ»w4¸|ùò’%KbccåååùîÝ»<سgÏ/¿üÂg—Û·oëêê6¿çñxOŸ>%lÌ`0TUU*©-Ь\ïOÿT$NÆ…xæ„}3¤¨ÈxÎÎ#j%°í¥íGYýzáF•¿wIbR¥k”5gË¥’Ñ ¬äDÜè°@#³ø[µ>®4¯ìÅÃgÚ–“O¾ŒB̦ð⤳év‹ÏÙ2D²ù-x¨Î‰[AÓø.˜ªãáç¬D¥q Ô60Ÿá¨H¡ÉXT>ó©G¨©RÖݸÿ“œqyfi¸|ê.f‹0JëÚ8V´Z²Xn"Á¢Æ}p|âuù ¿ŠîDò ŠŠêéÀNNNNNN®ƒQQQÉÉÉ›6mRWWhdKKK:Î1¿þúkhhhÓËüüü^½z 0@ y‚WUÖHËöþúÙžWRT®l®Öt!šÞ×yBßæŒF!LÖi¤é²äÛ5V¯“J]V[‹ñ•U24ÕEBQ55hå¥U¼Þ^[Žç,‹œjT£jã¶uÑçKÛÜ’Â⺫K†˜¬ú<¢–¥¡ÓÓX¼¹&&.Ž!„†Qèt:†Â0 kެòuÃ5›Ò¦ÝG“úO˱ÚÔ6±Í’ÙwÏ,ªÃñùY—@«èN$zºÎÖÖÖÖÖVˆŽT*ÕÎÎN .šššƒþå—_&MšT^^+ÄÔ|ãJ!qóîô»ðÏu{3m<ì¥ñâ3sfÈ®§Ê¨i)IR©4Ê—A(nc4.¯ßr¯œƒÊØáë~ýÑ =&Ý‹žû÷ƒRjx»'©J€k×¢V®å#¾¬ãÕ¿<u,÷›"ÛÖ&6°õ’Åú,ªãñ‰×Õ…Ut'z~8ƒ Z¼xñìÙ³;¾¦$$Îó?¬¤ét:]V×å÷7#ö'®·“j¹_|x乕2ûGê2´ÝŽ+EFêSi}-ÍÒ˜\¬E!j7… ž“—BÑ,=½£ÿ•©FJêCʼãöù¨`”>þ‰ísÔTTÒ÷¼d°mû4ìË ‰ê!'öZ¥Î Ê0˜|ÅtGÌl-¢¢™Ì óv‰™²¼’Óy5CAjì5rÓÙ"{]µåuǧØ“myI„ 6z›%‹,ª“ñ©†ëêÊ*º†ã=ôøâ½Ûåd¶àå1éÎwΪ­Ã%¥Ä¾×ÕëGO¯Îè‚à°ªÒ{å8Þáû§¨‰;ø†$yHÄ a„óõ„TbÐob_¬V¯‡/£0ô°½ÖªmêwWZ¸9j[FÚ‘«Õ‚‡E‹¶€ƒ "o¢ÖC‚ •*šW’ÜpgÝlÜtÕ±ßÏ»Ìw²°OžüöÙ]xÊ¡Ð<åPèžr(ô Òô*Ò= ÀÏ¡ÐÓUo ¿_Ôöj ðÈ•#Y2o7OI\^Ç©­²˜¬’n‹ê6í Îã>€'wÖª]Ž3ÞÛ0¨»Näï*Îò§óìÂq1ïRWêëö.—ýö™UûZný÷ ÂxõXî?ÚG C¡ §;óe‰ð}ù òr÷8E~,å=A°Åim|ž²ì¯uÿ³øÃ`€ =9¶PäiïèÀ¥“eÙú%ÿ¥²67°üÅàØ÷NöêÀµ|rœ9éYv¡²¥ IRO»Ñ®ˆ˜²99À²ó ¢ç²+Î.ÚûêÂöëõ!!2í ÀÏ¡Ð3È÷í9NˆSX:ft'Wo œ`àÌ[»C$¹÷eÀ™"Ûr´AV]hSþ„¦ ‡©rªƒ©k.ÆÚ>î#°:zr¼™!>9åU×bž›bù©òVø§™·ßÚööÿÿÀ‹Ú]¹kù…\ÚAóÐÑÓŸz'lŞ曎"ßvtõ„·$·áƒÅäe÷‡Æ¶ÄÛÔÝ=tßÌŒ‹ßlßIä÷>ј‡B@Ît»WÑsëþ²ë, ðr¢.»Ú—ؾbõ¥Êƒ“Ÿ_àeÑüí Àƒ¡Ð0AU·íÙ„Ï¥Ås¸¯-¯™åü¯æé7æG90 …kù ÐÕ}QÌÏ>“m¬).qÎøâPqiöÌïJ(o©¥ ‡BÀ“‘åèlÏR×—W9E/žÆ&X,B«Ñ2 …BÀnHrtû–øÄØW¸¬x)hðÄŽ—Þ>=7r.åR;í 9¬Ñ0Cß®ìÛ6bF|B°@y<¿Dùû¤\Ã¥ Bð(˜†5MÚi‘Aîù+šv` þw…ù§iÏçÔ>üÊhÆ £x釆y“=&á~X°:zƘ4ƒškO×·]º®¶øÉò#WŽdɼ]Ü<%qy§¶Êb²Jº1\ VA¡`„ªí“•A¾¡)ë6¥%ÏŸ*œñÂß[ïRÇŒ½…ëÓÏ…}Ú9PœlKp¥™»£;ߨXÔƒ7€Pè`èÊ[÷Noê?/õww´¶ÿ ì>¶òFöú¼.UPßZÛ–±%ZlgC‹Ë—fl ?_׆5z° =tò–+‹2_w¿7ÿ΄þñµ˜Î‹”¯~e{ˆ\åuMÃc;ÔõíÝx38X)`wªDÐPz¬7.Ù‹C1¢<^Òú.å}Oœ9é;#b–Í^áÓߣÏÙÐØr´3(·rÎT°¦n0ÒZ°üÅÍe½‚y æŠíTW›O7z,L² ‚¼© CjnšFÓw¶¼¬º]y—ãæ??>1RâˆÛ¥À(ô 0^=ýUÍ•¯È³Åá©áb3k1FÍÐÀà°nüÔdÙ Ä|»_ü áW…€A&Ýð?i'8»:ñ,»fºYñZDjAÃÞXÏ‹û[[~,&ê.\Œ`„¡ÿäŽäY“]<½½\&ÏH|ïd?åÌ AèÎ|Y"|_>¨¼Ü=N*VA¡`€±¯híê#îoT\½«Q«U}ß¿íY¶fmQå8<[(ò´wtÀÃ*á—„¥hËVùLRH[YW—­úÍשТ¥<óIÓõÃ/‡n¿$õ´íÃ8)›“0a t¡£`€ _`w¾I>~+¬ª«Ia+p£<á ò}{ŽbO–N3F«7 +`:€\éÆ7½e±ÁÍ qÁb;UOcù‘Ž€½•RÊ%­¼u ñÚcmÅa¯:z&°}Wj©Ú›à˽3t‡;uéîÊæCkü¨W_x3C|ÚÊ«®QÞB `9tô ±q•4Áãâ ÎQèç?ÕÍ¢5vãõ;škŸ-õýJ$âÛŽöa¼%¹ ,Æà Ð…‹±ŒPµ}²îå?•*}¼4Êîüø]ÅŸm˜mO3ÝîUôܺo8ÇÆYà…— mÿ l¯D’ÛèúIEND®B`‚rotl/vignettes/fig-vignettes-unnamed-chunk-8-1.png0000644000176200001440000007047615132142366021602 0ustar liggesusers‰PNG  IHDRø XEa=iCCPkCGColorSpaceGenericRGB8U]hU>›¹³+$΃Ԧ¦’þ5”´lRÑ„Úèþe³mÜ,“l´AÉìÝi&3ãü¤i)>AÁ¨à“àÿ[Á'!j«í‹-¢´P¢ƒ(øÐúG¡Ò ë¹3³»“¸k½ËÜùæœï~çÞsîÞ ¸,[–Þ%,®-åÓâ³ÇæÄÄ:tÁ}Ð }Ð-+Ž•*•&ã¿Úíï ÆÞ×ö·÷ÿgë®PGˆÝ…ج8Ê"âeþŲ]€AûÈ ×bø Ä;lœ âõWžð²Ï™‘2ˆ_E,(ªŒþÄÛˆç#öZsðÛŽ<5¨­)"ËEÉ6«šN#Ó½ƒû¶EÝkÄÛƒO³0}߸ö—*r–ᇟUäÜtˆ¯.i³Åÿe¹i ñ#]»¼…r ñ>ÄcU{¼èt©ª7ÑÀ+§Ô™g߃xuÁ<ÊÆîDüµ1_œ u~Rœ æàâ*-°z÷#°Mi*ˆËWh6Çòˆø¸æf}î-gi:×Ð9¥fŠA,î‹ãòV§>ÄW©ž—Bý_-·Æ%=†^œ tÈ0uüõúvW™â’9 Œ%/VµñBÈWµ'¤_¶tâÜÈMÛ“ÊŸ¿ŸåP““í\>ĘÉ@Á„yì0`D i|[`£§ èh¡è¥h¡øÕàìßÂ)ùþ·TjþÈëèÑ0B¦ÿ#ðЪÂïhU#¼ ~yh«uÐ fp#Ô1I/I’ƒø"“ä0!£ ’'ÉSdŒdÑ:J5Ç–"sdó¹ÑÔy#RŸ7‹¼‹èwAÆþgd˜à´ÏÅJŸ7ØÏØÏkÊ•×n^:}nW‹»FVŸ»Ösét$gj-tÈÚÔrÏÿÂ_ç×°_ç7Z þ~ëÛV·5ë4ÌV }ºo[ÄGó=Nd>¥-Ula³£¢Y5VúË}¹x»g[üä÷É?’kÉ÷’&ãÞä>áÎsŸrŸq߀È]à.r_r_qsŸGjÔyï4k± æi—QÜŸBZØ-<(d…=ÂÃÂdKO膄 a/zv7«]»ǰod«}¬€©sìn¬³Öá?TF–'|¦ãï3Nnã„#I?"…m»z„íõ¦v~K=Ú¯Æsñl<b|_|4>?Âpƒß‹¾QìñÔré²ËâŒi´µšêŠÃÉäãb ¯2* åÀ (ëºè»Ѧµ—hå°{28ÂoIþýÛy¥esŸ8ü';÷Z¶9à¬ÐûhË6€gã½ï¬>¦xöRx'Äbß8ÕƒÃÁWOÏ«ëõ[xn%ÞØ|½^ÿûýz}óÔ߸ ÿÿ%x ÅcÖË8eXIfMM*‡i ø  ½Ë]r@IDATxí¸%E™þ •ÕÅuAQYÅE” *K8 ¢0ÌH’(9  C’ "9ç! A„qÑ!ë"QQP–eëº[ÿ÷÷-Õÿ¾gιsï̹Lßsßïyî9§»«ª«ÞêÛo}¡û›#K’Å#`Œ€è)ÞÑS£ñ`Œ€0FÀ@Àï Á#`Œ@"`‚ïÁIõŒ€0FÀ˜à} #`Œ€èALð=8©’0FÀ¼¯#`Œ€0=ˆ€ ¾'ÕC2FÀ#`‚÷5`Œ€0F 0Á÷à¤zHFÀ#`L𾌀0FÀô &øœTÉ#`Œ€ Þ×€0FÀDÀ߃“ê!#`Œ€0Áû0FÀ#Ѓ˜à{pR=$#`Œ€0&x_FÀ#`z|Nª‡dŒ€0FÀïkÀ#`Œ@"`‚ïÁIõŒ€0FÀ˜à} #`Œ€èALð=8©’0FÀ¼¯#`Œ€0=ˆ€ ¾'ÕC2FÀ#`‚÷5`Œ€0F 0Á÷à¤zHFÀ#`L𾌀0FÀô &øœTÉ#`Œ€ Þ×€0FÀDÀ߃“ê!#`Œ€0Áû0FÀ#Ѓ˜à{pR=$#`Œ€0&x_FÀ#`z|Nª‡dŒ€0FÀïkÀ#`Œ@"`‚ïÁIõŒ€0FÀ˜à} #`Œ€èALð=8©’0FÀ¼¯#`Œ€0=ˆ€ ¾'ÕC2FÀ#`‚÷5`Œ€0F 0Á÷à¤zHFÀ#`L𾌀0FÀô &øœTÉ#`Œ€ Þ×€0FÀDÀ߃“ê!#`Œ€0Áû0FÀ#Ѓ˜à{pR=$#`Œ€0&x_FÀ#`z|Nª‡dŒ€0FÀïkÀ#`Œ@"`‚ïÁIõŒ€0FÀ˜à} #`Œ€èALð=8©’0FÀ¼¯#`Œ€0=ˆ€ ¾'ÕC2FÀ#`‚÷5`Œ€0F 0Á÷à¤zHFÀ#`L𾌀0FÀô &øœT©÷xã7Ò¼óΛæ™gžôÿøéþáâ7Û_ýêWûðÎ;ïœN?ýô~ËôwðßøF:ÿüóû+Òï±oûÛéøãï·ÌÌ<÷ÜsÓóÏ??³ÕûÔûÛßþ–æ›o¾Öƒ‘™Á·ÞïŸüä'éꫯžî”?üpZh¡…Ò_ÿú×>ÇïrË-—þçþ§Ï~6®¼òÊ4vìØjÿÿøÇ´Ã;¤e–Y&m¾ùæ‰6‹üÛ¿ý[ÚvÛmãØÊ+¯œèrñŧ¥–ZªÏß?ýÓ?%ÚâZk=6nܸҤ¿›†@¶#0¬øÎw¾“7Úh£÷ù¿øE~óÍ7\¾µàG?úÑSííµ×òQG•çž{îü¹Ï}®ÚÏý×Í[n¹e~Ç;Þ‘O<ñÄê˜gùÀŒíçž{.3E¾ð…/ä3Ï<36o½õÖ¼È"‹äÿýßÿÍ¿ÿýï3},Zä8 Êýö·¿­ö?ýôÓùcûX¾ï¾ûJ“þn©aýqwŒ€˜ÜÈ?üð>¥~ýë_ç­·Þ:/¼ðÂyûí·ÏÒòâøï~÷»¼ì²ËÆûšk®É‡vXÞo¿ýò ,7ÞxãŠ_xá…¼Î:ëä~ðƒRøÙÏ~õÿã?þ#ÿÝßý]þË_þ’ÿû¿ÿ;KÏþð‡³4¾|ýõ×W}&˜O>ùäüñ<¯²Ê*ù‘G‰c¯¬ YZaÁÒK/üãDZþÚ“¦™×^{í¼Øb‹å]vÙ%H§:™~<ûì³qŒ¾Çþð‡¼Új«eiÆYZo~衇2ç’öÕÀgùå—ßÿùŸÿ™¥u¡m¸á†Õâ…º›m¶YU¾ž­ç¹÷Þ{+|£bíãºë®ËŸúÔ§òK,Äü§?ýiº~o°Áù]ïzW”PH é#E ÚSO=5ï¶ÛnYVƒ²;¿üòËùK_úR¾óÎ;£ú„ü×ýW`ÎEVXa… 1sìÚk¯ë‚c,˜ûÖÅÒYg•¿ùÍo–êÕ7嘟;ÚçÍCÀ&ú¦™TÜ#0¤­…‰¶ÃT+’KK.¹dÒÍ;L¨ÒôâðOúÓ$IsÌ1GzàÒ9眓¤¥¦'žx"‰ÄÓƒ>˜DiÍ5×L믿~z饗Ò'>ñ‰´ï¾ûFýG}4‰(Ó»ßýî´ÿþûGûÓ¦MK'N S°´½(wóÍ7'iraþò—¿œ9äØODlI€8ÿW¾ò•„yé¯=Î/­1=öØca‚ÿÁ~uʇˆ?=:3&}öÙQîÉ'ŸL"·tÙe—E1p™sÎ9ã7ægÆ€`‚~Ï{Þ“¤y§µÖZ+úÁþ‚kxÒŸúyÀ®àKE~ô£¥vÚ)]tÑE1ö{î¹'‰ðSk¿£ˆ5ÊhÑ•þüç?§Q£F%Yi’gI‹’ÒdºüòËÓ®»îšžyæ™>ó/M?Æ-òN/¾øb’Öu´8K"â˜_vh‘óŽÉ_ £´É&›ÄuÁ1ú±é¦›¦w¾ól†€ÙÑG})ûÊ÷G‘è/øYŒ@óÖî‘0ÀÔ.²Îh¤EÐÄÐEL± ó.Ûò}gùdc?Zªeùe³H?´Þ5ÖX£Ú‰30Új©ÿꫯ†9¼h™ÆM ÒÉZdi~å•W¢ ù°óßÿý߇Öá…†&é9òÈ#óî»ïžûkrZdä}öÙ'‹ðBC-ŽAå .¸ 6Ï8ãŒ> y¢Ù9æ˜cÂÀöøñãóJ+­”1­£áóŠ+®˜'Mššm'<[ÏSð)ç)ßXCèC-P²46ëý¾ôÒKózë­û™/ŽwÞy±»Ó{«|àÈZ¸µîÎZÜ„¥~k &{¬Xv¸vø]-¦ò'?ùÉüúë¯×wç-¶Ø"ŸrÊ)}ö±Áõ¥x˜—ézG£xWƒ×êšnŽéŸÿùŸÕ'wfd ðÞ÷¾7M˜0!‹Vµà‚ Æ_=ShnhrEJ`<T¿Ñ¼4O4xÝØ“H8‰¬c?"ç$nl£ÕÊü›ÐÚeê­­,åÐòEŽÆ1‚Ôt— í™ú2CWš"–-&úm6.¹ä’$WAhã§vZŸþqa<"ëø .X1䃎múûéO:~ó!·@‘Æ6Öù¸cìhÄÇ{lhºhç¯Ø ÏÖóÔñ­N¦hðàZ‹A}NJ¿©®s,×ChÑXZèøÉÏke~õ«_%¬&XUZ…¾}ö³Ÿí³ˇLúI œ„†¿è¢‹ÆüRH‹®°2PoÊ”)éýïUWfÿtà 7$¹ª}å‡Ua%ϾìòwC0ÁpbJ4ê‹»˜è˜€‹pÇ„ê"ÿy˜R!+DÚ}|Cvܼ‰ò¦ ¤[ˆ33ÚDæK+OòùF>8f|üÞk¯½Â4Oä~Ú’Ÿ;tÐA骫®ªÈã÷ߘù9?õ ™qŒÅÀÞ{ïžzê©x€}H½=ÈQ}±`AÑ3&EdÉH „q~ýë_/‡Ã;Á4û@ÁfAšÒ@cáðÃþ0mµÕV1vùÉcñBýŒð¬Ÿ§à[X?0³sŽ:^œ òmí7/Í:ªã€Ìo¼ñÆ$kHšþùÓí·ßž¶Ùf›ªyÎGD|ýš(9V¿6Xýæ¹b.RÁ„:œ—ÅÝwß]- J[²T$ÿ…û ìã›ybNp¯X†š0Ë ˆÅbf7zL©™þY™·D@ë1¦¸Â‹éS;_õkX½…9˜úºYg?Ãd-¿j–Ö‘÷%ÀND&z-t£Çÿå_þ%Ü"0 ¸…É›Hmùž#`k®¹æŠ.*aÚH{ZDÀuhs0æôº(v 3N„ 2ÎÃ8‹|ä#ÉZ(Ä&&hp Pà=¢Ç‹Ë@‹‡,Í9ÌâÅ„Þ ÏÖóÔñ-ç-ߊ‡S?Ûz-q3ÔûÍ1\)²ð³`VǤÞ*ò}gùö[wǶ,ŒyòäÉÕ1ià8É-0"àŽè|D’ÀwL;!:^ˆéiAsˆÆÒ|d7 aî¢( µšaåÓ-Uì¡u¡±4÷øã']hâhwõzõmùºCcĤ½êª«†¹]‘ë¡ù¡!œF]L½<½úê«'=ÖÏn£¥Ó'´Z‚»Ð@åß­“`0̾òG÷ÑVÑ(gÔž¢¶Ã* Dh«<ÇÍ8êÂóÿ¡ñ\6ç!x ‹CúƒÉ-KƒœWeé#¨‡¥¡h¿ðl=OßrÞò-?zà¥EUúÚ×¾…ÌO½ß”¥/hÖhìu©÷§¾¿UK/ǰRпúã’æÌçW\óCùÖC{Çb.üɇÍáÀDO^«(j>DÉ8,ÍG`Ö ÍïæìïájòÁ—€Ùß÷ÀLQÓ³rã¥>/Ñ)~ìéÏÂŒ/¹˜ŸõxUR W˜¤¹•àÛ/ÇÚÕoÝG[õöêÇémµ3GSŽs%^7Ý×ëc&ÇwÍ­BŒŒ·“Ì*ž´ûïÿþï}|Ûìkí7ýì¯Ô™êög¥o®;´üçÞОǭ#0ÄÌ ¹ÓµÔçñ*þŠ ½£ù—}h‚ƒ‘ÖöêugÔ㯓ôGšEkíT—ý3:u˱zàZÙ×ÚïþúYêÌÊ÷P·?+}sÝ¡EÀ&ú¡Å×­žF3Ïl[Œ€hÖà›7'î‘6àÛæÏbŒ@ó°ß¼9qŒ€0FÀÌ2&øY†Ð #`Œ€h&øæÍ‰{dŒ€0F`–0ÁÏ2„nÀ#`Œ@ó0Á7oNÜ##`Œ€0³Œ€ ~–!tFÀ#`š‡€ ¾ysâ#`Œ€˜eLð³ ¡0o/¼ê”W ZŒ@ðê`2ÔYF.&ø‘;÷ù0C€ä*¤û$AHIšrñÅW£ çùå—_^m7å aÎ<óÌÙÖD¼¯~¨EêÜsÏ=]â˜þÎû®*NʜۤÃÝzë­#Y ^¦NZ•£Þæ›ožÈÉNòòÛ×…÷ìS—¤@Eh¼õ?R#¤ü%1I}hW™ùJµ¤lxIø¢ßúÖ·"ïIA{ÀDjáå—_>yä‘Uÿh&øf̃{afˆÀÁù¹_}õÕÈvçw¦oûÛ‘ ÊüL¢—ž°KÈï^2µu©ÉA5óä“O¦\pº¤/ƒjd…!¼x )ìJÿ_‘üàA l1¯ûí·_&ÛJe›”z7²Ä7.‘%°Èú믟 U2¿AÈäoGH¾så•WÆð²Ë.ëƒû­·Þ‹ ü± Ú ÛœRüF_x?×¢hƒ 6HÇ{lôƒä=d¥C”Ž6=òÈ#IipÓC=¹ë§L™ÇüÑ Lð͘÷Â̲®ar-ÙÓH?zã7ÆMÍ^9¿#E)DfFšR4¼±cǦ^x!ÚW>÷DVÒ™BDÓ¦MK×_}R.ñÐÞŽ>úèôç?ÿ9Êr#gÑ@Û‹/¾x-RXwÝuÓ ,¶ÝvÛ>$Z#©cI {ûí·§_þò—‘öòQ®÷H‘ºÊ*«A”A“"Â@S%½«òÍ—C}¾ÇFmç=ðÀÓ!‡Ri©×^{m"ë#ãÚqÇ™îzêUˆòì³Ïmuá…ŽþuÖY¡ÕÒ§¢å£Ecy`|i!.ð#¥î-·Ü’H¥ n¤ÁE°ž(Ïzü®t÷é§Ÿý‡x?þøô¹Ï}.2Ü1oÈ¥—^ÄËoRîbÁA®»îºôÎw¾34tÒº*?|:ùä“ãc#ë塇u]tÑØÏ}fÁpÏ=÷Dr ~ðƒqŒì´¹ÄKD»Ì š=cF°0O '®A÷@çÍ7ß ­>ú£ȬdÊë<€R.b†iJY7ú,si¾ï¾ûúœèÁÌ"¶,È"”Ìõ:~üø¬T¡YÉ`òöÛo嵈6D"YDÙ–—E‚Qw5ÖÈÒ*£¬ˆ#Ú|â‰'²²ÆeY²0k¡‘?úÑæSO=5+yž0aBéF§žz*k1EzY¹Ë³È:+Û\Ób!+Gy~ã7â|óÏ?ôƒZˆd-<òäÉ“³4þ,ò‰:õ‘kùäsÏ=7ú:jÔ¨¬ðq.™¨£¯Ô¥[mµUŒŸúŒã˜cމ¦ÀH$—Áò„NÈÊöå¨#Ë"Õ¬ETÙÇqðÉe½o?êƒ8hA’Ÿþù¬K–Ù:Ž)o}>î¸ãâwý£Ó¸eÏ"È|Ûm·e~ï³Ï>Y “ Ú`>é§KY‹²hV¹îóRK-•ej|ËÜr¾#çœsNÖ,~ó!¬>ö±ÅõÃDôÕñòC¦ÿh÷î»ïŽ]²dz9œ/¼ðÂŒNn‚F“ÕÃ]ýõ¯ä¢éy³Í6ËúÓŸb´ä‰H“ÍŸúÔ§ª›-$±qó—)·Ï±uÖY'Kƒz|@î›nºilK£ŒòåàZk­•¯¾úê XE~ÿûßgùžƒ¤ä÷Í'tR9”e>Îcƌɲ*d™w3¤P„E´ÞüÛßþ6KÝÉÒãäË U Ú:i±ÈQºÙXpH[ÏÏ>ûlT¡=Hw×]wmÈgÒ¤IÑÎÃ"9å”SòJ+­¿ù€ào¾ùæh"kF–†‹ ¶[ñ“ß9ï¾ûî ’»ãŽ;âwùèoÜ´-Í7ƒ²É&›ä .¸ ~—™¾ó’K.™!fÈa^˜7ê±èa&ËF©ß2ççƒ:¨Ú'‹KÞk¯½¢<;8∘—ª€~¼þúëY®” 7ޱ€’¦*&Ë@Õ®¬=Y>ûX -½ôұЫ úG#p6¹ÙlHÑŠ8vØaa›Í]ñéŠù¼E¬,ÆÃÿ½ï}/I[Jo¼q˜x¥á…™xÙe—<üðÃáWÅT]ó>"­:m¹å– ³,‚œk°È{ÞóžT\=öXœ£Ã|­…EÔÁL^—A1éâ×åz.‚I>®ú‡É»H©GŸÈH‡Éá¼"ŒR¬ú–•"üÁeÁs”Ã<Œ¹ÿ5&kLï/½ôR`ƒyœöˆÀTÛ d¿Ã´Ž[Ê-³Ì2D&«DºÿþûÓ¼óÎfkLÑ}Õ¨ÂïñÇOZì„ë„ße¢°>ú7}&Ýn‰› ?²º”ªñ­HøÅ1‘3ïûî»o¸C¤¡Wõp¹`–Çg_„~Ê"P6Ãqâ‰'VÛ¸2´0©¶ À[{íµÃÃØ\àW¿ŽdÉI²œ¾Ì3eðÙãÆÙpà cªFýc¶#`‚ŸÍS Õy’É-iE=›{âÓ7nâøÒ‰ŒF *¶ñq#ƒLµñRÅ—. 6¶¥õÇ7¤ÎŸë Á×.í¾" öáÇÿìg?U2¿W„LT5çe ÉDžðW8ñÑÏ5×\qãÇ_ŒH“Ž@®‰'F V!2ŽA¨fIËL2Q§•W^™Ý!ô?p«àÿæEdbB%.Ò%`¸Úf!©C¢üæÉÚ-¾dÚ`{›m¶‰æž{î¹X(à³W™î8â_ÆŸ_â¨Áa›¸ͨSÆ^Žƒ}§q³+ ü×lYäÈý„MTþs̸˵Ͳ]Z¤ŸÄ-!د,jʾý÷ß?m±Å®/ç&f?»,-1¥ßÒàãüüæZaÑsþùç'Y*’¬šAîcÊ"’mK3ø¿e|3úâ^#Ð"¦ÑàÊãK¯¼òJ"JšÇ—ùÉ+Í”À/ˆ¢£<‹ˆmLæéê&iñXÑøˆLÜñ¸‹45꣑#DiÇ‚’ç EqÍãS qA2~ &|Ô!Â\.…¨G{œBƒ$YTiÝ.ûå‚HÒA&œË Ú¤,:è8†ÖÍâ£! ”rȨŽç,‹ &,8 wã2ù¼?p.åd"K xS¿fé/ß`ÕiÜõ9c~r“Ë!ªƒ{‰V‡ø±à0~„`<‚+æ€JºÌ1·<W„…Fy„l—„ÏqѾYlÕ… <,:àÆ|²HPlCRìDëÑf!u¹B‹¯×÷ï  bË*<~DE .2’ÀßJ0Ámø=ñgãg%È !pŒý"ƒðÍ*Ú9ÊŠŒÂ×L™«`1¶ípA„o·ø÷Øc8íÊlAgÅ‹¯–ÿöãß®ûzñaF ý¥LÊ•`:|È´ƒÀFðZiÜù™gž)›Õ7à[F xÒ(ã¸ÌóðE"瑵"p#|Åiá! ÒNEäGÛZðvŒ‘@>‘}–ÖøÑÿ"üïŠÜc“@:-tÊ¡>߯­Èù&Äï.‚ϲ2Dp •‰ æ|‰o ^ ÈÓO?ñZ¸„¾ŽeˆÇߺÈusÿm‡  E,ñ üÕã´PÌZ¸Ä8刘„Ò.ã%O‹¦è+±–f!0ÝiÀ:£ñ]Àg…Ÿ«Û‚É Ê&ún#Û»íaRE»B[­ &TüõEx þÑþuLÌEDnaâÇ-"w9V¾iŸó~٥ͮnN/ÇØÏ_Ýl]ŽÍè×Ö´S´_,h‘Ä hÔhœøägU°`ýÀDÞ é4nÎN`ˆìŠ;€ób–çÙó2Æz_˜3bZ¯ƒz™Ößæ²µ\}ŠÀJ‚¹¾Uˆ½ÀÕ3Ð묵¾·‡ûà‡_·nºŽ@=P­ÞxÜÙ?˜›nܹ¡c–]a…¢yü×í¤SûQ;B¢ LÐÅ Ý®ÍþöXFP ¦gž7çYïúy Ân ®…n‘;}ê4îúB‡…Iëâï$õ9ëT¦u§¹l-WßfÑŽÜ)ƒƒ?K30Á7s^Ü+#0Û@+“I8"¼g['ÚœXÏfÇKyÐ\ ¨+ 6E½Ë!`‚÷e`Œ@0sóh[Óm·¼å­i}sŒ@p}gÅ}2FÀ#0‹˜àg@W7FÀ#ÐDLðMœ÷É#`ŒÀ,"`‚ŸE]Ý#`Œ@0Á7qVÜ'#`Œ€0³ˆ€ ~tu#`Œ€0MDÀßÄYqŸŒ€0FÀÌ"&øYÐÕ€0FÀ4|gÅ}23@€Ô©üYŒ@'x¯½ed#`‚ÙóïÑ3HKzRòÁ/¸à‚‘¶SYâªQ¼¨¤3­vvøñÕ¯~5y晎Îúî¡lÿºë®KʘTÖºHMÛ_•.) [EfùØ@úÑzðÿÅ/~»I[Rº²ãðÃô¶Ì')pëBºWeŒt»¼¶·U”Q.m·Ýv}v“–÷ø—¿óÎ;/Ž“Ëž4°ûØÇâÚ!ÅnÒå’’˜ë”À$4*B²¡Í7ß<-sAšZKà ›œeÆ:r(Äéb‡ÕÞlS7äHÅúÈ#Äu³ÍºÑGÊÑ×^{-ö}÷»ßÍ;î¸ã€ ]ªòª¨ìÌÊöI»÷Þ{G·DùÍ7ßìØEåKôºÊ×±L7̨­ç(ý’¦‡HÙ{ÓM7Åï³Î:+¯½öÚYYÜ2iX?ô¡e‘m;餓²2ée½“?¿ð y饗ÎÊÇDÎyË-·Œt¹'žxbìãC9àã:Qö½Ìyù+©†I±«…F”½õÖ[#¥¯ò¿G:ßüãUJ^僯ÒÌR˜4º&LÈôÿŒ3ÎÈ»ï¾{´áæ šÓ•f÷ÄßìùéõÞAàÊ,6!CZÜü'Nœè]íYï‘ÏܘÉå^'ðo¼1r{“ü¶Ûn‹àJõ™¯½öڼ뮻V’Ÿ¼ä67n\ä'¿»4Ê r“‹üàÒþªzÚWÔL¾tiŽA ×_}U‡öÙ^wÝu³,Õ8ªoýx饗òÆoœÉÁñÿxÙe—q‘¯BBŽ:ê¨ÈwNÞsr™#·ÜrKä»ç7¹Ôɱ>uêỔó“ã]Úmì£ÌÌô­÷ƒvŠÈÚÁýƒ´Ÿ}öÙ¼Øb‹Eþuyƒ 6ÈÊŒe _ÊHCŽ& Ð…^8úÇBfþùçÏÒ–óO~ò“rŠø&ç;¸Ïžs)½uu\Ù÷‚ø¯¹æšÈk_°0`þ ~\gÌ-çd±8vìØR4ßqÇyýõ×mê°0àœä”·4'›i˜EÅÝžœvÚia¾¬§ÿìÖHHþBÚÐ%—\2‰œú4KñõÖ[/=÷Üs±ó*&ØÉ“'§ïÿû‘RUdæéÝvÛ-²±éVu>ùÉOFþôx OjYY•Ò§?ýéhº˜;î¸0¯¹æš‰vn¸á†0‹ï»ï¾Ñ&æïNíKÓŽóO›6-ú©B˜tIïJû"»tÈ!‡D^tÌȘ‚ë"²I"Á„ÉSõ˜1cÒC=”HKZ[RÆ’Ò”c"¡$-4ƒ4ÊôÌ3ÏÄïå—_>i‘D¤IÄ•Ø>ýôÓcüŒïì³ÏNÒPÓ]wÝߌg0ý­÷£ÞwÒÛî´ÓNI‹ŒÈηÅ[$‘o=ztü‘Ãs;n–G}4iá‘JJWòÂ_yå•颋. Sýg?ûÙÀ‹\õÌéIk+­?-ºè¢I ½$ROZ¤_|±«L&Mšùå|ðÁèç%í&›lRuù€H›nºi´‹éŸy)òÊ+¯Ticµ(KZ ¤UVY%òØs ž{î¹¥¨¿‚€ ¾!án o¤)Ç •m·…›0‚´¼þúëIfÚô‡?ü!Èò•Æ—vÞyçtôÑG§¿þõ¯ñ â^uÕUSÉŸ‘Q¶ç"›œ´Òô«_ý*HEhÂg+­3IÛ¢»ì²K:öØc#Øó´k€<ñå’?’‚ œ5ÖX#ýò—¿ âa±ÂjÈQfâ|ˆ,‰X|ÐŒUšs—Ù>M™2%}ä#‰?Œ²—I;­µÖZ‘WZh´Cß Tú°Ã;63Û_iÓÑh¸öqØa‡%þ7ÂâDZt,VXذ a dÆQȲŒ™E ¤Mª\søË!xb1>ñ‰O$üþW\qEbÅq„ùE˜7}œƒEÌëé˜cމÅQ)~,œÀa‘³ÜrË•ÃIšzu ÒÅ_<]}õÕq^ŸŒóXšƒ€ ¾9sáž cd6 ­”èP2çœsN×47{‚³öØc¸±C$e! Ss’Ÿ5nÀ”hŠÈw$Î6„PúMù§žz*ÈN¾þèƒÜ´Ñ6Ú(~ó†Iîx¤Sû,h[¦õ(ÇG©Ç˜ )Èyì±Çb¡µÚ†‹ÐwƉÖNß!+´p,eCYÇí¬X,ÁúÀ¢‚ó³ha±rÏ=÷ÌTK?JÛåÌ.¼ð²}dÑPgüøñÕï2±C6ÄŽÅaŸ}ö‰ÅÄ*wFàF¹¯|å+aÉ€à‹€kYP”}yæÀB†˜YH`e  ¤÷¿ÿý¡³@Â*P G›à†¥X¬X@±añeiŽ¢oÎ\¸'F #+¬°BÂJ€y½.DKsƒæ8D†æ^r‘¿=´bÌÓøÀâ‚¶‚ÑÎ^}õÕ iÌÆGsÏ=w|º±Ÿù†+­Ÿm·7×\s…ù»]û êªH€:ô-j%E¦ÝQi›60ëÍ’:#ã«[OX¤0~ÆÇx!Y, Š/ ‰ 7Üòã‡f‹)üæ›oN3ÛßÒhü­Å7Lç¶ùácÇŒŽu¤,nÀ¢,N uÌèE–Yf™0­³ éã^(Âb§NÂì§/¶1áãB*‚•‚¾•9Ç ^œ—…j‘÷¾÷½±ˆb›èy4{Lñ‹«ú9èÇB -ÇüÑLðÍ™ ÷ÄtD€G•Þýîw'̨hæ>UüÕ§žzjhÅ.‹4DÊ ±£™q3Æ$Ï1'Ÿ|r>„Éàß§Ìo¼‘\WióELÐäñq#´OYÎß_ûÔÁǯ ±¨§hë0ŸCl´_×4[·£‚>;}G mÚƒ\ )LÿŒc¥•V 24õm¶Ù&H LqáÃǤ¹Bü˜üYp`@E;ž™þÖû|ëKî½ÅLòW]uUÚzë­Ó“O>[, O<ñD¥•Ó^±¶`!³âV —cä15æž±Ö¥•à™â еE‰X øÙYp±h*.ÚR ]XXxpÍŸ€E¤,ĘT§åš`ñ§§êÝðï&   Ü2ˆN ñcrCêÛߦLäÓE5w»"ã,¿u–Ÿ6"¿¥¹F4|9H3_|ñÅY&úˆH'2^7ç8,í4±eilYZaìQg‘e–æ‘äZä#<2ŽÉ|Þ'âZ¾þÌÿu‰D?蠃ʩs§ö)@9"Õy´‹|ÚAh_müæƒyù‡«íòƒ¨rÎ+"hs¢ÏEÆñ„O‘‰=ÆA¹<0vqÄYš{)}à4„'÷ôMšmìlµøˆÈý¨Üò!³uŒGà8‘èˆ>æQ¤Û<ñ Å@fŽEÞ½®…I`¢ ·ˆø§ o™k¹SÆ\-âéˆÏ1®æ\¦ù¬w(d-t¢ŽÉò“÷ÑüZlÄ·¬8Ч8udzÏ´]„§¤Íǵ#3Ÿy,eü=û˜ƒ.4a¡Ñô>¬¶Újácêv?1{±ÂרÛM»½·=÷Ü3ü˜‹‡ZÐððÖ5®ú9Ñà)ƒ™½.%è “z«  7¡,\%¨«Ôé¯}úÄ_ñÙ–:ƒùFónSk}4xõÚÅ+´–e­–¿z@û»Ñ_Ú)¢gÖ÷]¶ùÆ fhúfðz?:õ²¼Å§°ê T¤± èë æúv¸Š¨Ýq8Ènöâï³A#P¡SE̾Åô[/ÃÍ¿v2Pr§n§²ýµß©OíúÒiߌÈzƒ!/ÊCíH²ý¥ý"®µ ‹úB¤Nî”íÔ7Žu"\Žu’™Y\aÞïï\íÆÕéüÞÿö#`üÛ¹ÏhŒ€0F`È0Á9Ä>0FÀ·ööº·¿>ã À³ÁøÏk¶‚®ô|“D ãSµ#`š‚€ ¾)31ýà1&kü|ê€ÛÒ$cpd1FÀ4|SfbúÁKNx¾W Aën²ŽQôõ·µÕù·0F`v `‚ 꼤¢¼ƒ{€UTŒí"žTÙ…Œ€0FÀt@ÀߘÖÝçŸþt¯„l-33Û˜vy·Å#`Œ@70Á͵×^{€%WŒà,‚á,F`0𢤿g”ÓžË#Ð{ø1¹Þ›S¨‡ M¨^šÈ¶à‚ &½â4r‰ÏÌI2Â{é‘3Ï<³Zh⊪g›™¶yCc»Ä13ÓVuÀ€÷Ñ7]xûßQGÝäíp¼´÷Üì’ú|“­ïòË/®”»­R“‘Lu$Ç© 9äIEK.Þc_„wìó.zÞ½¿ùæ›Gpo9vøá‡GήÒßÙl³ÍÒ‡?üá>_ÿú×#“]ë~¶I‹k$¼ªÖ2ûÊwÑzè¡™wa[†·ã]ôÊÇïW×^mšuÃÍJ R½G}0#•å(ëõ¯™w½ëµ·Y¯Mê¼ý®»îLSÓ•UŠÓ¬ëÓíïæåqÏz“Z7›²¶”Í-‹¼¢}p–[nÈÎ5£†[ç›÷ä+ã\Tãóå=þʶ—¹ŠœtÒIñÎ~=-’•=./½ôÒY¯ÓßÊö—)ÏØÆŽ›wß}÷¨Æ{ÿeýÌz\7+«_V滬Yc›¾ðÇ»íÉ¡Àýüe?ßäWà½ü²v–®ø{€MÉ20ÁÏFð»xê¡&x¡èß‘`¥Þm“pÓœ8qbì7n\V ÙLRiN™í믿>+‡x$ )å~÷»ßEÂn¶$oQ gÞrË-ã­WšVIk¸‰K˶¹ñ*Y–6••-Ú-}i=/‰\;ì°¼æškFÂY ¢è)§œ’!ÿ"$j!iÉïÿû¼Ê*«DÒ’ÐÐeE+Ų´ßHèBÂY1b¿2ÃEûô ‚QÎø ~ó›ßÌʺVÕWö´¬,t±­ÌjÑ> vÎ>ûìªLý‡‚j3‰`X<Ñ¿²P–†Û±ŸÌ…²®Q‘ åÄOŒ&!wæN™Ø²ÒÖæK.¹$+}ë4?rÁêøQNilƒäØ`aG=’Í0æ©S§F™Öë®».Æ©´°$˸êó½Ád½b8SF)w3sÏ<! äËBþ+|Ÿy¡õ ¶lƒïŽ;îÈÏ ö’øòW*âéúË~%OT|ëƒë“dH&÷:*ÿm‚8VCRÒ?$°¾í5Á+_yuƒo“Ó‹ÝÜô•5È ·dq›j->"ù~ûí—¦L™þ]|¼ºñG¶7úJnóÑ£Gǘomä…Cô—q 2GÆ6Y:y×Á„œòäX×BgºÇTEð‘g1’ŽèÃ"äGo×OŽÑþkú.vd†£>kƹꪫ`ÿ™ùê4?œ§ž™°¾ÍؤµG]¹A’È–Ó÷YOŒ3fLºæšk’RÅö™ï_|1ΣX”#<þy¥ ŽÇ‚?þxpb@À•ø |âZˆE=>À`ä6Ú(i‘Yí'Ÿ<¾wYA’ˆ¿OBYn’)mŸ$’å)°”•¡jË?‡€ ~px¹´h‹$&³éDµ“eLyËûd+ঠQÊ‚¤MäŽ@$ÜŒ!w¤.¿! ™Ùù¿¥EÅoH“*YÄ—DP™YíHiÊyêç-$¹#² T}àåK.BŠdHb¦ å=¯nþÔá¼Ê¹ëÛ,ºÊ=ôÐ f¬) X,ÞXH±h¨ ×®Œ;ï¼3vã‚a Š}è3߬÷íž{î©4fÈ•mEÃGXXÄ2<òwê©§Æ\pqñÔÉý\gXhW\3¸1Š`Qb‡»¢U°†`î/®ƒÖãÞ&øáäRF`¶"0×\s…¦ ‘¡©b:EóÁŠi©“sÙ.¤É6uÙÆD à_ÇŸŽ/ß,dW´ËR¢ƒ°1ÝBZøWø”®¾úê0©·žòmw^ÚD B4»¢r^üÜ.B{œ‡2ôM2S4u˜‰¹ñ÷·ˆ@ó4GH xY rÈ!•·DÜ*˜½<òÈ´Új«…Ö\0诟œß8 ðÁÂP^A éãƒFï/vg'œx\O5„fÌ|³@` ZÌýœ‡?͹UôHeÌ–ÌÜçž{nà^ŸoêÐ}ç™|\,/‹0ÄÿŽÐ}eÉ‚Rç¹÷¤Éßxã¡™Ó?þŠfO{Ä+`]âr.Fí»,(ÚGS%X€¹ÁfEó®×£-ú‚©{ ‚™9.VŠz=4bþˆÏèOÚõ§u¾9O½Öízû¼A‘؈| 2о´=—8öÁ+—4@` D<˜ŽBš%N´Ò¢™æ”E#Ô#qAðÐ FÐæ#3êgäÎyXL –ܩ׎ÜÙ?3 ¢:éÒF]ж\ß×îw»þ´ÎwëyZ·ëíÎÌ«‘Ú×úyü»;˜à»ƒ£[1F`@¼Æw€Å¡GÀ?ôû FÀ?ÏìËÀ¼½ Ü!ôööËg3FÀ#`fü,€çªFÀ#`šŠ€ ¾©3ã~#`Œ€˜L𳞫#`Œ€h*&ø¦ÎŒûeŒ€0F`0ÁÏx®jŒ€0F ©˜à›:3î—0FÀY@À? ๪0F`¤"À[Îy¥¯¥¹˜à›;7àýà¼ò³¼‚•×ÕòúÖ~ðƒU™Áþàä´Ãûʇ‹œy晑#žþ’#ýòË/Ÿ¥®/¸à‚‰lkM’ÝsÌ1Óu Båõ¹$†¨ù­žà¥ŽëÈ0Gr’¾L:µj–z¼u<í$ÏùùÏ^ãï—§.I‡êBV9í”?’Þ d¼#y ÉkHZC² "dì#["ý ;"×z«î–±s^ËÀ0Á+—4³ ÞÎÍ­${!;ä|ì±ÇÎtŸH Áµ{_ùL7:„I•Jº\2”!ßþö·gêïQY iÈ6×$ü>÷¹ÏM×%r´“þ¶dk›®@›?øÁ"å-‡Zñ#_ýç?ÿùÈ"8nܸHá[š ­+™ãH Ñ“ê¯+¯¼2ò “ž E^ýõÈáþÈ#ÄbYèÚ'³dÎâ… v,XX\ò†C®c²õ‘\‡œu¡}XrÉ%•ä¦ÞÆHým‚©3ïq[Èg¾îºë†F´ýöÛÇ8~ñ‹_Ä;ÞX`ȹ=eÊ”j|×]w]hMhOd.„;Ý{iõÔa.‹Ü~ûí¡í3/dëclXX”î¹çži‡vˆ¢,ØÇ‚åâ‹/Ž´³Ì‚µ ôŸmú´ÝvÛÅ5M=Ë Ð*Ê2¸ï¾û²þ釤ú'Ìúg’¶ÝèìA@Ä™uϺ!fÝ$£"…Øw 'd™7³nšYùÃãØ~ô£,Í'?ñÄù±ÇË",¢cºqgiSÑŽ´Ø|ê©§f¥eÍ&LÈ"Ÿ(#-7Ú’É6KÃÊÒö³È4wÚÏùdjº|ˆ\¢oü>í´Ó²ÌÏY‹‹øàƒQNEpYÚa”cüÊñžµð‰vE6Y™Ü²ùùçŸÏ"Â,3p£]ÆCåiϲ’ä7Þx£_<(+bËZLÄÿÛ²‚d‘p¦/ŒIZs´¿×^{õùßQeeÖ"!ËL•£=êŒ5*+OÖÂ#‹Ü³RÊNZ¸äý÷ß?ÆLƒ"È|ÜqÇEÛõY2²r¯GßéÇüóÏ)EmÌ÷m·Ý–ù]ǯԧÏ\7Ì™-±[¹èóRK-•µèÉÊE_aÉA®5D ½¬aü.J"”çwÞ¼Î:ë术07Ì#"ÒÎ"ôª˜Ayôèѱ­ÅbÌ+s½É&›äï}ï{U9ÿN63È‘‹_ž~úé„i³ôpüîk®¹ftùàƒíÿsIñŠÖ'r ›¼éºÁ'U”G£DC\zé¥c{íµ×˜ 4CL¥hQhø~‘]vÙ%L¦h«˜P±`Æl{×]wEæívûÑŽ—]vÙh‡úök¯½¦[ê¡Í}úÓŸ®Ê•óÌ3OÒ¢7̱hoóÍ7_Œ…äøÊññbÆEÃæ<GãÄ<ŒVI¾u´~ü¹hˆœ“>Ú9ÇðãëãÇä™Yyå•ÓäÉ“ã|ð =4SÒÞÒVÃ;,°§1cƤk®¹&¬)h÷;ï¼3»C¨‹u„ã´Q¬/hù7Þxc€V­ÅY:å”S"<øþüç?G}-BÒf›möVkÿ÷¦hÕ˜±Á+ Z®}ËàøÿÈ®žKa‡€´­ i{êïøÚ!xibqãÇDZ_¤”$­;nšÒ Â¼ŠyWkü0c—@'9—0ßÒèãæzÕUWP8_ fÂDŒ”›-äqÁ$ÎÁ_»ýZ¸YˆH»Œ¦÷Ýwß0ýCd,&ÚÅ `^xá…ÓK/½T™µ!HiÝÑ¿ËBâᇪû¦1#æ›nZæï’‹‚?묳¢Ôa±$ëAG–s×ûÈÂë©§ž l ñzf=,ÀX°Ñ'ŽÍ1ÇѤ,/Ñ_úEߢËùÀ›},Š”ùKH·ä¢¯ãWÊ®´ÒJ±8ÀD. 9•9ÂSêá’àšÃg_¤¡—Íø®²ÀbaÊ€„©Ÿz¸ˆû`qÂuXŸ·G}4É¢×3 \ô…vÀògg Sô]j¨°‰~¨¾Ý›o¾9üñÓ{DxazŬÛ*˜<1ßb^Gø½Ç{„©ó´|ß±S6¦{L¶ºÙgÝüc¿%‹¸ã7"Ì0ÙÒž|ö±_7ã0Ûc†í´Ÿ‚І³<¿¥yFŸEòY>çp°“+æ_iÞlVBÿ0ñbÖ!„9s3fp\"Œ0ïSA–ˆ¬`¬¨»Å[„{¡4$ÿuæÁ_êã_†ìeA?µ´ÔˆÀ—»ûmà÷Æ¥ÁA,Nˆ„…cdü˜ûqk€9šhx¤´ÇyñgÁýAô>Qæ›´æX°` 5X@šÅ]žÀܼ +$dÑÀâ‰ÅQ½¿e.!ø²°(çæ›öñá3.ÚcñU|ç¸8d± ÂÓ:~\àFÿYhIcŽgÑió¤“NŠG‰ÍàyxºN¬ô¥,)Ÿ~,Bp5°ˆ‚ðâ Xü/QDV•´Új«Å5K”<‹ÆRw™”²ÌU‰²/ûü=0æ@ÙXQ— Z"HH&Õ®7Oà7«,)•Bƒå‘¢^nh¯qnªhô¼ÄA£þõ¯AY¥Lý››9dS©êǰâ™Ñ~b Zˆ¼U Aþ8O'As…PJa)‡vq¢="œ§Þýg!0Xé4¶þðh=ÁˆÅrQ?Ö®O,Ðò‹¬ÌK=­ÞÆ@~ã÷ç¯øÍK® SÌi+~”ÁºÀ\µ;7c*VˆÒÞŒ¾9mÕ3ªa¨/œfTÇdž€5øá4d¥¸ r#f¥Ýma勿`é}Fª“;#Æì‰FFÊsä˜[o¹å–Ž`ôGŽíȆÚí¯“nëÉÐÆ‹u¡õXÙ†pÚ „_'ýÖóô×ÿví•}íÆÀ±Á´×ŽÜ;µAÐÁy˜¸±È°ðjG°¥ùFsç¯Uê„ߊe!ðNÒiLʳ¿~¾þÊÕq4¹×éÞokðÝòq-ñøÚÁp‹* !·^Õà;a†¿ôî»ï Kf[ËìE-s62èa¦·¡@ÀüP ê6@CÀ/ÍŸ¥9 åâ··¡FÀQôC°Û7FÀ#00ÁÏÐ}J#`Œ€0C€ ~¨vûFÀ#`f&øÙºOiŒ€0F`¨0Á5Ânß#`ŒÀl@À?@÷)€0FÀ 5&ø¡FØí#`º€oñ{;„7ËñfDËðGÀ?üçÐ#ðZVÞWÞXÆkNy(ï;ŸYáÕ¥´Ã Wš$¼[¿žztfúÆ+b:ꨙ©ZÕ!±ï˜Œð®~ÞˆÐåòË/¯ª~øáñ¾uÞ)O"º|ç;ßIýèG#I ï~oRÌòÎöº€…·á•¿’˜wËoµÕVñnzÎÅ-‹ðêbeüK¼ãž„B\Wuá5¼F÷¦›nªïöïáŠï¢·ô&zf¾÷Þ{{sp31ªáœ.¶u¸Jø©5Û¥m-Ûi›6_|ñN‡gÛ~Ò“êí{³tþÓN;-ë5½³Ô†ˆ:“Ât BŠX½f7KÓŽ*J–“E”ñ[IT"Å-)fI‡ªÄ3YdÇ”Ü%ë“Y ­H««ÜðUZ\‘sVòž¬wÉge¼«º¢Ä1Y‹»¬wØGjZÎ]Ò“²W (KšÚEY$ÒȾþúëY/=Ê%Ý-éaÏ>ûì(§Å^¤ß]f™eÈM’•Ĩ:— _¬Áו™û=b «Ûºë®ZZI‹ÖH¦µX 2{M™2¥Â‡dFhrd#µ)ù ÐÔÐìJV0Ò¨Ò&õ•»;R‚–HAJv0²}ñõ"íö“4„¦XR–W±’D†”³dW#n«`~ì±Ç"µ(}7n\d4£ïÖ' oæEÖ³RŸv/»ì²è'™ÍÈv'rKÊ— jH0D&82êÝpà ¥Zô‡mò,´ÐBI ƒ8&2L›m¶YŸô¦¥¯™Ò²}ôÑI9ÊCk/¸ò–º’1ŽLo¤Ê%'À•W^“’À+4Ö 4zæ€>’€K ó¼×^{EŠ`ö—¹¢¤Ç]}õÕÓøÃD²°ÂÂC™=÷Ü3ÒüRnùå—}`Gv82ô•ÌlÔ/Xˆè“”x/>ïægŽ,=€Àð]›¸ç3BÀ|_„zAƒGÓIeݤ³næ1@‘bìS^ñ,ÂȺ‘g¥icJj’—\rÉ,ÒÈ"ÎÐàDôqL)f³È%Ú‘y8+û`h&LÈ"à(£\áÑ–È(+iV’Ð;íç|2ÿF]>Ð é/‚V-ó{h§'NÌk¬±Fì¯<þøã¡AwÜq¡¢ÙÊôEÐtµÉœ[fè,BΔGÐREXYù²Þ¿ãTšÝr“gå:ÏÊœ–ш•B6p*õ8ÇäÉ“3}G+F”å1‹ãwýCyͳÒíF;hÑŒA&õ̼(©OÞqÇ£m¥÷ -2uQöè‹™yãšág™Ù³FY){+í™ãØ£Á×­ ZÌE½uÖY'ëÕ·qîúyÊo-£Ol3z9”/¼ðÂr “AÃ<ðÀ“̾¡u’p¦ä/<š"¾o´@r²£Í‘'ÿ<šä<9ÇIoŒvÙi?9×É ^¤¾ýÚk¯¥©S§F{;ì°Ch‹¥\ù¦Ohüûî»oä­ßf›mÂêÀq4s|Ñä³'ûÙä'yÎEú‘w\DÚçóÏ?šªH1Òãžþù‘+Z<Ú=õZ;I™Ð¬Éʇó¼>ŽØ©8ñG;ä73fLºæšk¢?d…D‹'Ú8õë9ÐÑ¢ÑÔѾÑÌI኿œùcŸ+¡¥k§ã8†øçëÙó˜/-J¢˜’‚¶5\÷ZÄ5@;$Zª[À«RÎÕ.×{ðǰDÀÉf†å´õn§1ñbþŠ)#&Q²« '00ïJ# ƒ|!¹"ŒIZw’oµ")ð“ê&Ü|EyHâáS87| ˜Ì‹x‡ ÁÜ~ì±ÇFà¤vÁÄ9 Ãvû§M›–¤…–¦Â é"6Ùí>ùÉOÆb‚ú­ÁËç\í¦ ‘bJF,ƒ'¤Ä5C_‘'Ÿ|2,$uà/&ì"e|Ô“¥#úÃ1ð`!„@ª+¯¼rü®æUšoµ‹@GÌâuÆ_ýn] @¢\{ßýîw#…/ÄÌpÐÓ>n\ Eè'Ø×¥„HÀ‹.²Ö„+CÖ™ÀW i_Y\1çòýWÍ<úè£iÔ¨QÕ6?8é…-½€ ¾7æ±gF…o¿q·…t±ÜPÑž†“/M?.Ú&Zb]ÐÔ¸‰³€A—™8|½ÜÐ!H (¹áËÔ$é¡aâ'G«-É*ø.´R4v4z™rÃŽ5m˜ÅDë~¢¿ñCRˆ‚¾Ò}÷Ýȇ…~rüÆDysÎ7Þ¸œ6¾9w½/*Ä=iÒ¤ V, ¤¼…(¿ñoqC¬õ”ÈlrUZŸå,z ýƒ:(Lu‡ÜŠuƒß;ï¼sŸ¾ákg õœçŒòÅR€Å BJ|}e!PÆEüÀé§Ÿå }üäE˜Ã: ³Ÿ¾Ô5o"ÜÁ“(xò¦oK,±Dls^¬ œ—Åar®s-!Œƒ9d.‹`a(‹¾²ÏßÛè‡÷üõdï!ynˆCñ‡¦3íe›àV qÒ¨O‚åè;ÂxÂ#˜Žk‹ñ"Ô“¿ùE# ~øá¬ÅCµ¿þã^=vJ[<Ç8´0ŠÃ"ø,kH–e"¶yÔO‹yG rã›nºiäG ä{쑵èŠv嶨Ÿ.kqsN ]t&xŽ`F¹&2w%àRñ Y ¬…FõwÏ=÷DUùùã<ÔáZ íº(¾aÈþ÷êçñï·98U¬U<ŒÐДtón9ÒÜM´üÁu[Д4ªû7»}ŽÙÕàþð‡4÷ÜsW]@ÃDå0“uñcWßúI W ¸ªGƒF‹o•vû1ÿ¢=sp½óË_=`¬~¼ü¦/˜”µ )»â›à¾b!ès e,æšk®j,øÉù«›×[ª j³]?°~`](.p¨³¿±ÐHà V˜ c¤šù@…Û=Ö °µô>öÁ÷þ{„#ÌøurgȘbñÛ4Åsò˜áYät’yæ™§Ó¡¶äNáv¤_'µÖ!°X§¾ „Ü9g+‘c:/æóÖ>ÍÌv»~°©/HZqèoì3C¸­cÈ8XtÍ̹Ò¶Ë4ûà›7'î‘è ø¬õVv ú›§ .¸à€’· ºñY¨@*Û:YÎLSʪ¹ç©Kî÷zZÔvíÕË·;ÞniZyÏ?BšVû!Í­²é¥UW]5v•„0””¯»îº ù7Þ8M™2%­¶ÚjéÖ[oM«¯¾z:î¸ã¢ï/ ¸NíAü$BÞxã´á†¦qãÆÅ6I•H4¤lu‘Ú’çüõ÷åGAô,Öà{vj=°^E€üìë®»näó.ùáI&£´¡IéH#×8¤Q2ùÌg>“”î5r™+Íi,ê9á_|ñÅh“úÛn»m"7xò—+ÅhÒ9çœSvG^óÖýd*#;Ö òD”ò5rÊ£¹’1 ¸U «Ç{,ò™ÓÈ í¹öÚk#§=ù×ãÚm·Ýª&.¼ðÂtÈ!‡Äöž{î vÈv·ùæ›Çûø©øá‡G.t6›l²IEŽ¥|ÕØ[?:áò•¯|%)ÕlœŸEç… /ºè¢Èê7mÚ´ gÆHBž’hüøñi¿ýö k 6¥0rçt$RšÙ¤ô®a©)äNÖ¸Ní±p'¾wß}÷ȯtºÑ{p%§=™ôÈKOR"ËB€t±–ÞDÀùàûÎëpÍ_…ˆ3r¦K3¬r€“o\æè| 'Džñ‹/¾8rSOæà¼ä’Kfr­‹8³ÞKŸÉëŽì´ÓNY¦ðh‡|ñ2cç¿üå/y„ Yed6޶D²‘+]YÔ²H;òœ“O½u?ç#Oy‘^ôíÓN;-ËüžElyâĉy5Ö(Ūoòºëö›¥ÅfrÝ“Ãý¼ó΋ã"áÈ{OžyÊ‘7^ÄZÕÝn»íòÉ'ŸÛôó¹çžË“&Mмíì¤þ /œÏ<óÌ,âqi!Ô§|l¼õAŽõN¸(‰OþЇ>”÷»ßepàzÛm·~ZxDw愜ðä–gÌäqW Û¬„?‘Ç]ž¯¸âŠ8Ç•å-æ†|÷Ê—K÷NíÕûª…CÞf›mê»òõ×_Ÿ_|ñ¼ãŽ;Fÿ´€èsܽ€Mô=¼˜cÅŽ¶W76}¸h"™!é&í¢Ñ '<­KD˜|ðÁé…^í·˜ZÑzñ1ã×eŒhs˜k‘£>:xài饗Žíµ×^;½öÚkñ ±i±ÅKø¾‘]vÙ%Lÿä(Ç?Ï5ôÀ„eà®»î íq»ý¸–]vÙh‡ú6ç:ujÔÛa‡*í²*¬ô ß}÷Ý"­ð3&ýä'?Ih´ÚwÞ9~óÁ¹°>¼ôÒK‘*w‰%–HW]uUÕê;6‰ð¢øm½|Õ˜~ô‡ š=ãœo¾ùóçŸ>ÌñÄIˆ6B“Æú@Ê^æeòäÉ1X8¾ùÍo†¶ß_‹ð4zôè°t€É‘Gyìùþþ÷¿Ú}§ö°â XF´` ËGìÐóvúé§'-îÂzÀyµ¸)‡ý=B0Á÷ðDuà 7„o¸ ²zõÕW‡¬»ÒüÒñÇ?díEÃäïÆŸ+ 1rÊ)éÞ{ï ßy9xÒºÓý÷ߟæwÞ -2ÈA ˜‘¥—¢éoû[ߘ—[n¹ ALæE¼Ã|Œ`nÇ ±BT\pAœƒó´Ûé³0õ1Q¯·Þzü ÒÆôOÊZíâ ø-·Ü2ÊóA?¸&Ÿs‘úâ…ÍSO=çŸÒHÿ6ByˆÁ…ð³Ÿý,úrß}÷Uåãà[ÃuÂ¥~nLá,J~vLÿEÞñŽw$Læôã]ïzW7¬µÖZ|ÇBŠ ºO<±T‹>crG:µWž9Áe±È"‹TõÏ?ÿüðµcöG¸(' GUÆ?Fšx‹h ºQgEþ6¦?MéÈË/¿œ¥™çsÏ=wº.ÉŸ¥ý…y˜ƒü––¦wL½Òð¢ŽH=ÌÒ˜’EPY¤û7Ø`ƒ¬›üæãá‡3;sqçwÆ~ißa¶—Ÿ?ÎÓn?1/c–GdAŠ>‹ä³¬á"`?æmZÆôÜ*+¯¼rVdzµûßøF–ßóÌ3÷Ó¦{ù¿£-gzóÍ7à €UÓ¿îªÑWž@ƒ® šºbœÍ~4c¢Ç1Ï£1cm(Ây°"iŽ;‚>×eÑh1K|¸Ì2ËD}ŽSA£¦ RÊÇFí£.¡ŸŠAˆÒõߌ«Y ä7æ|Ù# ü´X‹zGqDÂ(Þ zäN~ýôï|'m±Åe§ö¨‡‘ùuá|ZÔÄ.æ€C®ËÈBÀ&ú‘5ßí0DÓ¼´ÞôÈ#¤K.¹¤Ï¸¹cîVÀ\Â, Kk ²§ ÑÝp@fj¢À!z¨IÒnë~Êó 6‹"åiÄ/½âŠ+†{¥•VŠú 6›ÎUùA‚˜º!WüÈ<~†é™èý:ÁCÚD™—çÉy2@AoÑgÈò„üxr—û([¤¾]Ê—cå»?\dýˆøÜ"ø¶qû'A ¦piô3 +¢ëyÌaÄ=°¢Þe—]û‰•XýõÃÆS,Xx†é¯=f< 7Ï<óDÙò!ËGÄà`A!k@å*)eüÝûÌ¢÷‡éð¹B YŽÚ/S•DZ¨ùì³ÏF@!€ Q£)ž}öÙ±Ýú±@Dø[+‹‡Vi·Ÿ˜€÷½ï}•¶\¯ÃüòW¯~¬þ›¾{P ëÇê¿)×Jnå8>~¹úøí˱Á|wÂ…q–q€=‹–‚ÁuhÎXZ…[.m¶;öúë¯Gà^kþÚk-[߯ºŽÄãXF&ø‘7ç± ¾{ÓC@Z;š(¦j´=‚®rëe@YÌ ùbñ¼—‡ë±ŽL¿TïXÔŒ€NIimÓ8ºõ:¹3?‘çž{.sÝ9餓²2f-n"¥ñÒK/õ²­ø­·!FyÆ5vìØ¼ûî»Gµ³Î:+Ò+[aV.†¬$GYYK“ú¶?dK'7l†å  =)W{Z`ª¬då켃ííÍ!9Íã?ž^yå•Ä+mÉÞF†9d½õÖ‹´¦±¡ÒÌžzꩉ„'"ñÈ‚¶Æk$‘U•u®žîú믬pdW#KšòÂGSº GÊY2Í‘P¨¤Tí´_ùâÓn»íVº‘.¼ðÂÈŽÇ2ë‘mmñÅÔ¶hi­BÉ¤ÇøÈ>§›yU„q“am¡… ÜH?‹—ìoEÐÚyÝ/‰cÈÜG¶;LHÉ»Új«¥I“&•âç¡hŽŒ‡Ô¹ÎCCgœqFœ‡ìwdŸk'ƒoRç2Çh눈0­°Â ñ»>wìÿÚ×¾üDj‘¬' é+ ã%kߎ;«>ÆK&?Þ@I½þÎÓižKûå»ÝõÃxëçiÅ“ „\ûüQŸD>X§xmñ5×\S]÷K,±D¤N&s!É‚(ƒNJ_4~RÿbÃBÆõGùw¾ó‘Z˜1"dL¼òÊ+ÃêQR“<¨‘Ò¨å†;3â°?ãK@¦Æ|óÍ7WEÖYIeò 'œuÓÊ_|qVšÖ8®ljY$–ï¼óάüàY$Ÿ•F5‹Ü³nbYfú,ÂÉûï¿ÖM;êˆà³n’ñ[7ñ¬›fæ-H eYé²²”åƒ:(ÊÍ?ÿüYÙëòC=”•Ž6‹4²òšg-²ÌžQæ´ÓN‹ó¡!Mœ81Žq Óþ½öÚ++-mÔåC„œO>ùäØÖ;æó=÷Ü“E¼™þ¢Uµ Úٺ뮛EÞY¹çÆ-âÏZðDÛŒK7ì¬ô¬Q]‹À‡ Ê¡™RòäÉYæØ(C8?Úà´iÓ2uDœ¹¿yÐ"!4=0A:‡s1w"Œ,ÊÊ/ZiTz룿ótšïýèGYi„«f´ˆ‰k†J5œEt¡3®ñãÇÇu„¥hûí·:J\ý§´Ý­¶Ú*Ê1n%3Šk‡k¯¿ótšçªSúÑéúi=O+ž¥ -~[ðC¸¶•9£m#Zlf¹#bÞøAÇÿ„?Yé’³qQ®þA[üßÜ}÷ÝõÝùŠ+®ˆkO‹˜û>²‘ÒwÃ&øþ/mŽ9æÈJûZ”–„Ên`ܼ!Yd̘1 ³}ß}÷eiCYÚpÆ ‰!ÒH+äž{î™!G³;Ä. 9“$B=Î!?e–ö“•²5öI«îC¶»òÂGˆCIoâüô™¾ ö³8öeø€`§L™Û ÄÂx•ï<¼*øÖH2‚³4î8çm·Ý$ZLÊôWªÖ¬8‡ kš`Á¢œóÑšò½‡™–~³°a‘Tdƒ 6ˆúýÍÃ¥—^d@þÎÄEEYÀAXŒ¡.ý§Ó|³’5¢jBße—]b{ÅW̲Bdiè¢/ÂÆüÌ6 !ð@¸¾õ­oÅbíM6Ù$+s?cî;§Óú»~êç©ãY¯¿Å[äSN9¥¾+ÈùÄO ’gÁÂÿ„Ï>¥ûÍO=õT”;æ¹.ÌÕrË-Wµ“ÕW_=É÷h¡ÙTyW#Í îÔˆE@7ÝôôÓO'À,ÿ‡ù¼'L˜ò—&kü|05rüþûïÓ$&EÌÒæWiË¥hú¾¿¥…&S•³Ó$fwÓ3ÛÒ6“n¤Id–¤™¥å—_>IS2ºI†¹wÙe—s`Nfå0¥‘öfR¶1ï“–ŒvÌ/ùÚûÛÿÓŸþ4Ñ>¢…_Ò8IËŠmÒÀÊ·š.»ì²$Í0Lþq öiV–†Øƒ{B„¸œwÞy1VpB8ÆŸnÔI‹žbd?.„r~p”vXˆ`ÓZk­E‘ÌÞ"Ž0ùvš‡úX¤õw<ftpÙzë­Ã #âœ.oüÌÌ7ç,ØÑiƆ+†ÿ7æW$–DnaªÆ_„±"O>ùdÚo¿ý’Sá¢Á]!ëJcl"ïøÝé<ì4ÿQñ­þ®Ÿúyêx–úô ‚¸“êBà®Ìñ¸%pTÈõ OÒb1ŠcöÇ%²÷Þ{Ç6n›µ×^;óÊÿ_i¾4úôÝï~7Ò1+6£jÔ· ¾QÓáÎðÇ?Yý&3ÒQ!j¾HÝ_Zöqã•)7ü¥DÚãG„174_87@i9AÊå¦Ì1üúåÆÁã‡Æg¯?ãÿøÇªMÊC Üü—\rÉ t‚ö!ü¡EˆX†üñqr BfŸL¼‘«ž(ävû~]| ä»ð §¹çž;D=C&,^ zY4úô¿8 RäR›1åðÑ‚ ñEn¿ýöðÑCbøê‹ÐýCÀ].ƒ©we}ˆý` « l|ÖæBb€t:>^iÒ¬ÓèÑ£Ó¸qã’¬'©ÙMý™™olÂb‰þÓ6}“ùæ›/®b&ÊâLi§IV˜è„È6u˜sb Â’†¸Óy:ÍÿÆoçࣿë§õ󫯾:~uÔQáSÅ4=×\s…Ù•"جÀ¢Œ{Á,bÍ"Á¬dìÃD/s8fKLí«®ºjÃÏ­Ç¿â·?L½lYŒïSùÃ?œe=¨\"Û,­¨ã~jøRiµ •©_ ‘Ê??*&øº|ÿûßϘÎü·ÒĤÊ6}Å”‹ˆà²‚«bœ"ÎŒßц¹ž²¸E >Œ3~ñ¥ï±ÇY‹ ¨Óß<`ê.fýNçÁíæ`ŒÜrË-1îØ¨}ôwžvóMUÚÅ?Žàv™sÎ9c¾eͨpåú ž~0ï¸4ˆÝàúТ-p ¾ˆ4‹È|á”+Òé<æ¿Ô+ß®ŸÖóÔñ,u‰MÑ¢®lÆ·´³?¢…eŒƒÿDÖebø ®„k¾¸€À˜¹mž‚ ~áÿ÷“¬­Å³m|c¦Â13F€@)nZuá&Ì#\ܬF•W^yå¸yQ?·Ì’YÈAr“´¬¼È"‹TMPFšHµÍnèíÕ2ÀoO{2QW76'* Ý{ï½Ñ60qNEðWM(Ê:ãïe?&á×EÚ퇔ñ}âwçfK q7h‚ ÑäB€`«@På\,,x̉…aÑ&ý`á >öà%m?ð£MÆJ >V™ê£ ôƒÅAYz¾º"¾þæG³ ?OÎCÛ2ÉGŸÀÂj÷cçi7ß´{Øa‡Å£p`!³r5ß;ï¼s–ÖN‘ uüÊ\Kà^÷e³(È©O`%š`ÌIÚÝÑF§óp¬Ý<³¿.®ŸÖóÔñ¤¾´ï¦c1V—²¸£ïŒ‰ESY_‚Ä™[þä‰CÏ+• ‹ vü¨Šà{çZ’æ×ÏõÔT™ƒŽ5άà#0(tã‰q`Ân'º'oµ;4Ý>̬øç‰…(¦~µÃO¹Á$‹¯³ÓËm¤u‡¹ºµqÌÐü)¸©Ï¡NûyüH|}Ê– Žá¨»0ʱòÝ©o‡ &wüÒ²p”&Ú~Ó_L¾ŸR¨¿yTãžÑyÈ–´p*ÍN÷Ýßy(ÜnlœŸk€X‰þ¤æ´‰yZÄ×§:1`V°èï<æ¹OƒÚh7oíÎÓzµ¶S¶ëØ—}å÷×î­Ê@Ç1Ðö†ªœ ~¨u»F`"€¿‘g|ñgÖɤÍ'=ÏŒã³æ†é—@µa8TwÙô<&øžŸbÐ ‚ÙÐÔ žk"ày Yhò&÷V„¼mš…€ ¾YóáÞ#`Œ€è ïèJ+nÄ#`Œ€h&øFM‡;cŒ€0F ;˜à»ƒ£[1FÀ#Ð(LðšwÆ#`Œ@w0ÁwG·bŒ€0F Q˜à5îŒ0FÀî `‚ïŽnÅ#`Œ@£0Á7j:Ü#`Œ€0ÝAÀßÝŠ0FÀF!`‚oÔt¸3FÀ#`ºƒ€ ¾;8º#`Œ€0BÀߨépgŒ€0FÀt|wpt+FÀ#`…€ ¾QÓáÎ#`Œ€è&øîàèVŒ€0FÀ4 |£¦Ã1FÀ#ÐLðÝÁÑ­#`Œ€h&øFM‡;cŒ€0F ;˜à»ƒ£[1FÀ#Ð(LðšwÆ#`Œ@w0ÁwG·bŒ€0F Q˜à5îŒ0FÀî `‚ïŽnÅ#`Œ@£0Á7j:Ü#`Œ€0ÝAÀßÝŠ0FÀF!`‚oÔt¸3FÀ#`ºƒ€ ¾;8º#`Œ€0BÀߨépgŒ€0FÀt|wpt+FÀ#`…€ ¾QÓáÎ#`Œ€è&øîàèVŒ€0FÀ4 |£¦Ã1FÀ#ÐLðÝÁÑ­#`Œ€h&øFM‡;cŒ€0F ;˜à»ƒ£[1FÀ#Ð(LðšwÆ#`Œ@w0ÁwG·bŒ€0F Q˜à5îŒ0FÀî `‚ïŽnÅ#`Œ@£0Á7j:Ü#`Œ€0ÝAÀßÝŠ0FÀF!`‚oÔt¸3FÀ#`ºƒ€ ¾;8º#`Œ€0BÀߨépgŒ€0FÀt|wpt+FÀ#`…€ ¾QÓáÎ#`Œ€è&øîàèVŒ€0FÀ4 |£¦Ã1FÀ#ÐLðÝÁÑ­#`Œ€h&øFM‡;cŒ€0F ;˜à»ƒ£[1FÀ#Ð(LðšwÆ#`Œ@w0ÁwG·bŒ€0F Q˜à5îŒ0FÀî `‚ïŽnÅ#`Œ@£0Á7j:Ü#`Œ€0ÝAÀßÝŠ0FÀF!`‚oÔt¸3FÀ#`ºƒ€ ¾;8º#`Œ€0BÀߨépgŒ€0FÀt|wpt+FÀ#`…€ ¾QÓáÎ#`Œ€è&øîàèVŒ€0FÀ4 |£¦Ã1FÀ#ÐLðÝÁÑ­#`Œ€h&øFM‡;cŒ€0F ;˜à»ƒ£[1FÀ#Ð(LðšwÆ#`Œ@w0ÁwG·bŒ€0F Q˜à5îŒ0FÀî `‚ïŽnÅ#`Œ@£0Á7j:Ü#`Œ€0ÝAàÿy„ž;ˆiIEND®B`‚rotl/vignettes/rotl.Rmd0000644000176200001440000006156515132142375014706 0ustar liggesusers--- title: "How to use rotl?" author: "François Michonneau" date: "2026-01-15" output: rmarkdown::html_vignette: css: vignette.css vignette: > %\VignetteIndexEntry{How to use rotl?} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} \usepackage[utf8]{inputenc} --- `rotl` provides an interface to the Open Tree of Life (OTL) API and allows users to query the API, retrieve parts of the Tree of Life and integrate these parts with other R packages. The OTL API provides services to access: * the **Tree of Life** a.k.a. TOL (the synthetic tree): a single draft tree that is a combination of **the OTL taxonomy** and the **source trees** (studies) * the **Taxonomic name resolution services** a.k.a. TNRS: the methods for resolving taxonomic names to the internal identifiers used by the TOL and the GOL (the `ott ids`). * the **Taxonomy** a.k.a. OTT (for Open Tree Taxonomy): which represents the synthesis of the different taxonomies used as a backbone of the TOL when no studies are available. * the **Studies** containing the source trees used to build the TOL, and extracted from the scientific literature. In `rotl`, each of these services correspond to functions with different prefixes: | Service | `rotl` prefix | |---------------|---------------| | Tree of Life | `tol_` | | TNRS | `tnrs_` | | Taxonomy | `taxonomy_` | | Studies | `studies_` | `rotl` also provides a few other functions and methods that can be used to extract relevant information from the objects returned by these functions. ## Demonstration of a basic workflow The most common use for `rotl` is probably to start from a list of species and get the relevant parts of the tree for these species. This is a two step process: 1. the species names need to be matched to their `ott_id` (the Open Tree Taxonomy identifiers) using the Taxonomic name resolution services (TNRS) 1. these `ott_id` will then be used to retrieve the relevant parts of the Tree of Life. ### Step 1: Matching taxonomy to the `ott_id` Let's start by doing a search on a diverse group of taxa: a tree frog (genus _Hyla_), a fish (genus _Salmo_), a sea urchin (genus _Diadema_), and a nautilus (genus _Nautilus_). ``` r library(rotl) taxa <- c("Hyla", "Salmo", "Diadema", "Nautilus") resolved_names <- tnrs_match_names(taxa) ``` It's always a good idea to check that the resolved names match what you intended: |search_string |unique_name |approximate_match | score| ott_id|is_synonym |flags | number_matches| |:-------------|:-----------|:-----------------|-----:|-------:|:----------|:-----|--------------:| |hyla |Hyla |FALSE | 1| 1062216|FALSE | | 1| |salmo |Salmo |FALSE | 1| 982359|FALSE | | 1| |diadema |Diadema |FALSE | 1| 4930522|FALSE | | 4| |nautilus |Nautilus |FALSE | 1| 616358|FALSE | | 1| The column `unique_name` sometimes indicates the higher taxonomic level associated with the name. The column `number_matches` indicates the number of `ott_id` that corresponds to a given name. In this example, our search on _Diadema_ returns 2 matches, and the one returned by default is indeed the sea urchin that we want for our query. The argument `context_name` allows you to limit the taxonomic scope of your search. _Diadema_ is also the genus name of a fungus. To ensure that our search is limited to animal names, we could do: ``` r resolved_names <- tnrs_match_names(taxa, context_name = "Animals") ``` If you are trying to build a tree with deeply divergent taxa that the argument `context_name` cannot fix, see "How to change the ott ids assigned to my taxa?" in the FAQ below. ### Step 2: Getting the tree corresponding to our taxa Now that we have the correct `ott_id` for our taxa, we can ask for the tree using the `tol_induced_subtree()` function. By default, the object returned by `tol_induced_subtree` is a phylo object (from the [ape](https://cran.r-project.org/package=ape) package), so we can plot it directly. ``` r my_tree <- tol_induced_subtree(ott_ids = resolved_names$ott_id) ``` ``` ## Warning in collapse_singles(tr, show_progress): Dropping singleton nodes with labels: Chordata ott125642, mrcaott42ott658, Craniata (subphylum in Deuterostomia) ott947318, Vertebrata (subphylum in Deuterostomia) ott801601, Gnathostomata (superclass in phylum ## Chordata) ott278114, Teleostomi ott114656, Sarcopterygii ott458402, Dipnotetrapodomorpha ott4940726, Tetrapoda ott229562, Amphibia ott544595, Batrachia ott471197, Anura ott991547, mrcaott114ott3129, mrcaott114ott37876, mrcaott114ott18818, Neobatrachia ott535804, ## mrcaott114ott309463, mrcaott114ott177, mrcaott177ott7464, mrcaott177ott2199, mrcaott177ott29310, mrcaott177ott1321, Hylidae ott535782, mrcaott177ott17126, mrcaott177ott43017, mrcaott177ott2732, mrcaott2732ott3289, mrcaott3289ott40328, mrcaott3289ott173489, ## mrcaott3289ott110534, mrcaott3289ott489758, mrcaott3289ott59160, Actinopterygii ott773483, Actinopteri ott285821, Neopterygii ott471203, Teleostei ott212201, Osteoglossocephalai ott5506109, Clupeocephala ott285819, Euteleosteomorpha ott5517919, mrcaott274ott392, ## mrcaott274ott595, Protacanthopterygii ott1024043, mrcaott274ott3887, mrcaott3887ott9371, Salmoniformes ott216171, Salmonidae ott739933, mrcaott3887ott28511, Salmoninae ott936925, mrcaott31485ott79094, Ambulacraria ott6520512, Echinodermata ott451020, Eleutherozoa ## ott317277, Echinozoa ott669475, Echinoidea ott669472, mrcaott360ott26831, mrcaott360ott3985, mrcaott360ott367, mrcaott360ott362, Acroechinoidea ott5677511, mrcaott362ott220009, mrcaott220009ott3651075, Diadematoida ott631174, Diadematidae ott631173, ## mrcaott220009ott357021, Protostomia ott189832, mrcaott49ott6612, Lophotrochozoa ott155737, mrcaott56ott519, mrcaott56ott5497, Mollusca ott802117, mrcaott56ott1881, mrcaott1881ott102410, Cephalopoda ott7368, Nautiloidea ott854446, Nautilida ott854452, Nautilidae ## ott616361 ``` ``` r plot(my_tree, no.margin = TRUE) ``` ![plot of chunk unnamed-chunk-3](fig-vignettes-unnamed-chunk-3-1.png) ## FAQ ### How to change the ott ids assigned to my taxa? If you realize that `tnrs_match_names` assigns the incorrect taxonomic group to your name (e.g., because of synonymy) and changing the `context_name` does not help, you can use the function `inspect`. This function takes the object resulting from `tnrs_match_names()`, and either the row number, the taxon name (you used in your search in lowercase), or the `ott_id` returned by the initial query. To illustrate this, let's re-use the previous query but this time pretending that we are interested in the fungus _Diadema_ and not the sea urchin: ``` r taxa <- c("Hyla", "Salmo", "Diadema", "Nautilus") resolved_names <- tnrs_match_names(taxa) resolved_names ``` ``` ## search_string unique_name approximate_match score ott_id is_synonym flags number_matches ## 1 hyla Hyla FALSE 1 1062216 FALSE 1 ## 2 salmo Salmo FALSE 1 982359 FALSE 1 ## 3 diadema Diadema FALSE 1 4930522 FALSE 4 ## 4 nautilus Nautilus FALSE 1 616358 FALSE 1 ``` ``` r inspect(resolved_names, taxon_name = "diadema") ``` ``` ## search_string unique_name approximate_match score ott_id is_synonym flags number_matches ## 1 diadema Diadema FALSE 1 4930522 FALSE 4 ## 2 diadema Diademoides FALSE 1 4024672 TRUE sibling_higher 4 ## 3 diadema Garrettia (genus in Opisthokonta) FALSE 1 631176 TRUE 4 ## 4 diadema Hypolimnas FALSE 1 643831 TRUE 4 ``` In our case, we want the second row in this data frame to replace the information that initially matched for _Diadema_. We can now use the `update()` function, to change to the correct taxa (the fungus not the sea urchin): ``` r resolved_names <- update(resolved_names, taxon_name = "diadema", new_row_number = 2 ) ## we could also have used the ott_id to replace this taxon: ## resolved_names <- update(resolved_names, taxon_name = "diadema", ## new_ott_id = 4930522) ``` And now our `resolved_names` data frame includes the taxon we want: |search_string |unique_name |approximate_match | score| ott_id|is_synonym |flags | number_matches| |:-------------|:-----------|:-----------------|-----:|-------:|:----------|:--------------|--------------:| |hyla |Hyla |FALSE | 1| 1062216|FALSE | | 1| |salmo |Salmo |FALSE | 1| 982359|FALSE | | 1| |diadema |Diademoides |FALSE | 1| 4024672|TRUE |sibling_higher | 4| |nautilus |Nautilus |FALSE | 1| 616358|FALSE | | 1| ### How do I know that the taxa I'm asking for is the correct one? The function `taxonomy_taxon_info()` takes `ott_ids` as arguments and returns taxonomic information about the taxa. This output can be passed to some helpers functions to extract the relevant information. Let's illustrate this with our _Diadema_ example ``` r diadema_info <- taxonomy_taxon_info(631176) tax_rank(diadema_info) ``` ``` ## $`Garrettia (genus in Opisthokonta)` ## [1] "genus" ## ## attr(,"class") ## [1] "otl_rank" "list" ``` ``` r synonyms(diadema_info) ``` ``` ## $`Garrettia (genus in Opisthokonta)` ## [1] "Centrechinus" "Diadema" "Diamema" ## ## attr(,"class") ## [1] "otl_synonyms" "list" ``` ``` r tax_name(diadema_info) ``` ``` ## $`Garrettia (genus in Opisthokonta)` ## [1] "Garrettia" ## ## attr(,"class") ## [1] "otl_name" "list" ``` In some cases, it might also be useful to investigate the taxonomic tree descending from an `ott_id` to check that it's the correct taxon and to determine the species included in the Open Tree Taxonomy: ``` r diadema_tax_tree <- taxonomy_subtree(631176) diadema_tax_tree ``` ``` ## $tip_label ## [1] "Garrettia_parva_ott6356094" "Garrettia_rotella_ott6356095" "Diadema_savignyi_ott395692" "Diadema_palmeri_ott836860" "Diadema_setosum_ott631175" "Diadema_paucispinum_ott312263" ## [7] "unclassified_Diadema_ott7669081" "Diadema_africanum_ott4147369" "Diadema_antillarum_scensionis_ott220009" "Diadema_antillarum_antillarum_ott4147370" "Diadema_mexicanum_ott639130" "Diademasp.SP04-BIO_4_JGLCO_AYott7072105" ## [13] "Diademasp.SP03-BIO_3_JGLCO_AYott7072104" "Diademasp.SP02-BIO_2_JGLCO_AYott7072103" "Diadema_sp._DSM1_ott219999" "Diadema_sp._DSM6_ott771059" "Diademasp.ACOSTI-NIOTSU3ott7072098" "Diademasp.LI03-BIO_JGLCO_AYott7072102" ## [19] "Diademasp.LI02-BIO_JGLCO_AYott7072101" "Diademasp.LI01-BIO_JGLCO_AYott7072100" "Diademasp.ACOSTI-NIOTSU4ott7072099" "Diadema_sp._seto35_ott66618" "Diadema_sp._seto18_ott66623" "Diadema_sp._seto19_ott66624" ## [25] "Diadema_sp._seto38_ott66625" "Diadema_sp._DJN9_ott66626" "Diademasp.CS-2014ott5502179" "Diadema_sp._seto17_ott587478" "Diadema_sp._SETO15_ott587479" "Diadema_sp._dsm5_ott587480" ## [31] "Diadema_sp._DSM4_ott587481" "Diadema_sp._DSM3_ott587482" "Diadema_sp._DSM2_ott587483" "Diadema_sp._seto10_ott587484" "Diadema_sp._seto9_ott587485" "Diadema_sp._DSM8_ott587486" ## [37] "Diadema_sp._DSM7_ott587487" "Diadema_sp._seto16_ott312262" "Diadema_africana_ott5502180" "Diadema_principeana_ott5725746" "Diadema_vetus_ott5725747" "Diadema_regnyi_ott7669077" ## [43] "Diadema_amalthei_ott7669073" "Diadema_affine_ott7669072" "Diadema_subcomplanatum_ott7669079" "Diadema_ruppelii_ott7669078" "Diadema_calloviensis_ott7669074" "Diadema_megastoma_ott7669075" ## [49] "Diadema_priscum_ott7669076" "Garrettia_biangulata_ott7669080" "Diadema_ascensionis_ott4950423" "Diadema_lobatum_ott4950422" ## ## $edge_label ## [1] "Diadema_antillarum_ott1022356" "'Garrettia(genusinOpisthokonta" "ott631176'" ``` By default, this function return all taxa (including self, and internal) descending from this `ott_id` but it also possible to return `phylo` object. ### How do I get the tree for a particular taxonomic group? If you are looking to get the tree for a particular taxonomic group, you need to first identify it by its node id or ott id, and then use the `tol_subtree()` function: ``` r mono_id <- tnrs_match_names("Monotremata") mono_tree <- tol_subtree(ott_id = ott_id(mono_id)) ``` ``` ## Warning in collapse_singles(tr, show_progress): Dropping singleton nodes with labels: Tachyglossus ott16047, Tachyglossus aculeatus ott16038, Ornithorhynchus ott962391, Obdurodon ott3615207, Steropodon ott3615209, Teinolophos ott4119276 ``` ``` r plot(mono_tree) ``` ![plot of chunk unnamed-chunk-8](fig-vignettes-unnamed-chunk-8-1.png) ### How do I find trees from studies focused on my favourite taxa? The function `studies_find_trees()` allows the user to search for studies matching a specific criteria. The function `studies_properties()` returns the list of properties that can be used in the search. ``` r furry_studies <- studies_find_studies(property = "ot:focalCladeOTTTaxonName", value = "Mammalia") furry_ids <- furry_studies$study_ids ``` Now that we know the `study_id`, we can ask for the meta data information associated with this study: ``` r furry_meta <- get_study_meta("pg_2550") get_publication(furry_meta) ## The citation for the source of the study ``` ``` ## [1] "O'Leary, Maureen A., Marc Allard, Michael J. Novacek, Jin Meng, and John Gatesy. 2004. \"Building the mammalian sector of the tree of life: Combining different data and a discussion of divergence times for placental mammals.\" In: Cracraft J., & Donoghue M., eds. Assembling the Tree of Life. pp. 490-516. Oxford, United Kingdom, Oxford University Press." ## attr(,"DOI") ## [1] "" ``` ``` r get_tree_ids(furry_meta) ## This study has 10 trees associated with it ``` ``` ## [1] "tree5513" "tree5515" "tree5516" "tree5517" "tree5518" "tree5519" "tree5520" "tree5521" "tree5522" "tree5523" ``` ``` r candidate_for_synth(furry_meta) ## None of these trees are yet included in the OTL ``` ``` ## NULL ``` Using `get_study("pg_2550")` would returns a `multiPhylo` object (default) with all the trees associated with this particular study, while `get_study_tree("pg_2550", "tree5513")` would return one of these trees. ### The tree returned by the API has duplicated tip labels, how can I work around it? You may encounter the following error message: ``` Error in rncl(file = file, ...) : Taxon number 39 (coded by the token Pratia angulata) has already been encountered in this tree. Duplication of taxa in a tree is prohibited. ``` This message occurs as duplicate labels are not allowed in the NEXUS format and it is stricly enforced by the part of the code used by `rotl` to import the trees in memory. If you use a version of `rotl` more recent than 0.4.1, this should not happen by default for the function `get_study_tree`. If it happens with another function, please [let us know](https://github.com/ropensci/rotl/issues). The easiest way to work around this is to save the tree in a file, and use APE to read it in memory: ``` r get_study_tree( study_id = "pg_710", tree_id = "tree1277", tip_label = "ott_taxon_name", file = "/tmp/tree.tre", file_format = "newick" ) tr <- ape::read.tree(file = "/tmp/tree.tre") ``` ### How do I get the higher taxonomy for a given taxa? If you encounter a taxon name you are not familiar with, it might be useful to obtain its higher taxonomy to see where it fits in the tree of life. We can combine several taxonomy methods to extract this information easily. ``` r giant_squid <- tnrs_match_names("Architeuthis") tax_lineage(taxonomy_taxon_info(ott_id(giant_squid), include_lineage = TRUE)) ``` ``` ## $`564394` ## rank name unique_name ott_id ## 1 family Architeuthidae Architeuthidae 564393 ## 2 order Oegopsida Oegopsida 43352 ## 3 superorder Decapodiformes Decapodiformes 854107 ## 4 infraclass Neocoleoidea Neocoleoidea 329546 ## 5 subclass Coleoidea Coleoidea 7371 ## 6 class Cephalopoda Cephalopoda 7368 ## 7 phylum Mollusca Mollusca 802117 ## 8 no rank Lophotrochozoa Lophotrochozoa 155737 ## 9 no rank Protostomia Protostomia 189832 ## 10 no rank Bilateria Bilateria 117569 ## 11 no rank Eumetazoa Eumetazoa 641038 ## 12 kingdom Metazoa Metazoa 691846 ## 13 no rank Holozoa Holozoa 5246131 ## 14 no rank Opisthokonta Opisthokonta 332573 ## 15 domain Eukaryota Eukaryota 304358 ## 16 no rank cellular organisms cellular organisms 93302 ## 17 no rank life life 805080 ``` ### Why are OTT IDs discovered with `rotl` missing from an induced subtree? Some taxonomic names that can be retrieved through the taxonomic name resolution service are not part of the Open Tree's synthesis tree. These are usually traditional higher-level taxa that have been found to be paraphyletic. For instance, if you wanted to fetch a tree relating the three birds that go into a [Turkducken](https://en.wikipedia.org/wiki/Turducken) as well as the pork used for stuffing, you might search for the turkey, duck, chicken, and pork genera: ``` r turducken <- c("Meleagris", "Anas", "Gallus", "Sus") taxa <- tnrs_match_names(turducken, context_name = "Animals") taxa ``` ``` ## search_string unique_name approximate_match score ott_id is_synonym flags number_matches ## 1 meleagris Meleagris FALSE 1 446481 FALSE 2 ## 2 anas Anas FALSE 1 765185 FALSE 1 ## 3 gallus Gallus FALSE 1 153562 FALSE 3 ## 4 sus Sus FALSE 1 730021 FALSE 1 ``` We have the OTT ids for each genus, however, if we tried to get the induced subtree from these results, we would get an error: ``` r tr <- tol_induced_subtree(ott_id(taxa)) ``` ``` ## Warning in collapse_singles(tr, show_progress): Dropping singleton nodes with labels: Mammalia ott244265, Theria (subclass in Deuterostomia) ott229558, Eutheria (in Deuterostomia) ott683263, mrcaott42ott3607383, mrcaott42ott3607429, mrcaott42ott3607455, ## mrcaott42ott72667, Boreoeutheria ott5334778, Laurasiatheria ott392223, mrcaott1548ott4697, mrcaott1548ott6790, mrcaott1548ott3607484, mrcaott1548ott4942380, mrcaott1548ott4942547, mrcaott1548ott3021, Artiodactyla ott622916, mrcaott1548ott21987, Suina ott916745, ## Suidae ott730008, Sauropsida ott639642, Sauria ott329823, mrcaott246ott2982, mrcaott246ott31216, mrcaott246ott3602822, mrcaott246ott4143599, mrcaott246ott3600976, mrcaott246ott4132107, Aves ott81461, Neognathae ott241846, mrcaott4765ott4131031, Galliformes ## ott837585, mrcaott4765ott6520194, mrcaott4765ott109888, mrcaott4765ott75785, mrcaott4765ott104461, mrcaott4765ott151684, mrcaott4765ott54193, mrcaott4765ott3596087, mrcaott4765ott415487, mrcaott4765ott51354, mrcaott4765ott781249, mrcaott4765ott53700, ## mrcaott4765ott572162, mrcaott4765ott446490, Meleagridinae ott781250, mrcaott49310ott51349, mrcaott49310ott49319, mrcaott49310ott153554, mrcaott153554ott867027, mrcaott30843ott4947869, Anseriformes ott241841, mrcaott30843ott714464, Anatidae ott765193, ## mrcaott30843ott88380, mrcaott30843ott1082830, mrcaott30843ott75874, mrcaott30843ott432041, mrcaott30843ott30847, mrcaott30843ott166683, mrcaott30843ott30845, mrcaott30845ott30850 ``` As the error message suggests, some of the taxa are not found in the synthetic tree. This occurs for 2 main reasons: either the taxa is invalid, or it is part of a group that is not monophyletic in the synthetic tree. There are two ways to get around this issue: (1) removing the taxa that are not part of the Open Tree; (2) using the complete species name. #### Removing the taxa missing from the synthetic tree To help with this situation, `rotl` provides a way to identify the OTT ids that are not part of the synthetic tree. The function `is_in_tree()` takes the output of the `ott_id()` function and returns a vector of logical indicating whether the taxa are part of the synthetic tree. We can then use to only keep the taxa that appear in the synthetic tree: ``` r in_tree <- is_in_tree(ott_id(taxa)) in_tree ``` ``` ## Meleagris Anas Gallus Sus ## TRUE FALSE TRUE TRUE ``` ``` r tr <- tol_induced_subtree(ott_id(taxa)[in_tree]) ``` ``` ## Warning in collapse_singles(tr, show_progress): Dropping singleton nodes with labels: Mammalia ott244265, Theria (subclass in Deuterostomia) ott229558, Eutheria (in Deuterostomia) ott683263, mrcaott42ott3607383, mrcaott42ott3607429, mrcaott42ott3607455, ## mrcaott42ott72667, Boreoeutheria ott5334778, Laurasiatheria ott392223, mrcaott1548ott4697, mrcaott1548ott6790, mrcaott1548ott3607484, mrcaott1548ott4942380, mrcaott1548ott4942547, mrcaott1548ott3021, Artiodactyla ott622916, mrcaott1548ott21987, Suina ott916745, ## Suidae ott730008, Sauropsida ott639642, Sauria ott329823, mrcaott246ott2982, mrcaott246ott31216, mrcaott246ott3602822, mrcaott246ott4143599, mrcaott246ott3600976, mrcaott246ott4132107, Aves ott81461, Neognathae ott241846, Galloanserae ott5839486, ## mrcaott4765ott4131031, Galliformes ott837585, mrcaott4765ott6520194, mrcaott4765ott109888, mrcaott4765ott75785, mrcaott4765ott104461, mrcaott4765ott151684, mrcaott4765ott54193, mrcaott4765ott3596087, mrcaott4765ott415487, mrcaott4765ott51354, ## mrcaott4765ott781249, mrcaott4765ott53700, mrcaott4765ott572162, mrcaott4765ott446490, Meleagridinae ott781250, mrcaott49310ott51349, mrcaott49310ott49319, mrcaott49310ott153554, mrcaott153554ott867027 ``` #### Using the full taxonomic names The best way to avoid these problems is to specify complete species names (species being the lowest level of classification in the Open Tree taxonomy they are guaranteed to be monophyletic): ``` r turducken_spp <- c("Meleagris gallopavo", "Anas platyrhynchos", "Gallus gallus", "Sus scrofa") taxa <- tnrs_match_names(turducken_spp, context_name = "Animals") tr <- tol_induced_subtree(ott_id(taxa)) ``` ``` ## Warning in collapse_singles(tr, show_progress): Dropping singleton nodes with labels: Mammalia ott244265, Theria (subclass in Deuterostomia) ott229558, Eutheria (in Deuterostomia) ott683263, mrcaott42ott3607383, mrcaott42ott3607429, mrcaott42ott3607455, ## mrcaott42ott72667, Boreoeutheria ott5334778, Laurasiatheria ott392223, mrcaott1548ott4697, mrcaott1548ott6790, mrcaott1548ott3607484, mrcaott1548ott4942380, mrcaott1548ott4942547, mrcaott1548ott3021, Artiodactyla ott622916, mrcaott1548ott21987, Suina ott916745, ## Suidae ott730008, Sus ott730021, Sauropsida ott639642, Sauria ott329823, mrcaott246ott2982, mrcaott246ott31216, mrcaott246ott3602822, mrcaott246ott4143599, mrcaott246ott3600976, mrcaott246ott4132107, Aves ott81461, Neognathae ott241846, mrcaott4765ott4131031, ## Galliformes ott837585, mrcaott4765ott6520194, mrcaott4765ott109888, mrcaott4765ott75785, mrcaott4765ott104461, mrcaott4765ott151684, mrcaott4765ott54193, mrcaott4765ott3596087, mrcaott4765ott415487, mrcaott4765ott51354, mrcaott4765ott781249, mrcaott4765ott53700, ## mrcaott4765ott572162, mrcaott4765ott446490, Meleagridinae ott781250, Meleagris ott446481, mrcaott49310ott51349, mrcaott49310ott49319, mrcaott49310ott153554, mrcaott153554ott867027, Gallus ott153562, mrcaott153554ott240568, mrcaott30843ott4947869, Anseriformes ## ott241841, mrcaott30843ott714464, Anatidae ott765193, mrcaott30843ott88380, mrcaott30843ott1082830, mrcaott30843ott75874, mrcaott30843ott432041, mrcaott30843ott30847, mrcaott30843ott166683, mrcaott30843ott30845, mrcaott30845ott30850, mrcaott30850ott82415, ## mrcaott30850ott82420, mrcaott30850ott656780, mrcaott30850ott82414, mrcaott30850ott82425, mrcaott30850ott765188, mrcaott30850ott332079, mrcaott30850ott30858, mrcaott30850ott90669, mrcaott30850ott30855, mrcaott30850ott604172, mrcaott30850ott339494, ## mrcaott30850ott82410, mrcaott30850ott604175, mrcaott30850ott190881, mrcaott190881ott604182 ``` ``` r plot(tr) ``` ![plot of chunk unnamed-chunk-16](fig-vignettes-unnamed-chunk-16-1.png) rotl/vignettes/vignette.css0000644000176200001440000000726615132136164015616 0ustar liggesusersbody { background-color: #fff; margin: 1em auto; max-width: 700px; overflow: visible; padding-left: 2em; padding-right: 2em; font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 14px; line-height: 1.35; } #header { text-align: center; } #TOC { clear: both; margin: 0 0 10px 10px; padding: 4px; width: 400px; border: 1px solid #CCCCCC; border-radius: 5px; background-color: #f6f6f6; font-size: 13px; line-height: 1.3; } #TOC .toctitle { font-weight: bold; font-size: 15px; margin-left: 5px; } #TOC ul { padding-left: 40px; margin-left: -1.5em; margin-top: 5px; margin-bottom: 5px; } #TOC ul ul { margin-left: -2em; } #TOC li { line-height: 16px; } table { margin: 1em auto; border-width: 1px; border-color: #DDDDDD; border-style: outset; border-collapse: collapse; } table th { border-width: 2px; padding: 5px; border-style: inset; } table td { border-width: 1px; border-style: inset; line-height: 18px; padding: 5px 5px; } table, table th, table td { border-left-style: none; border-right-style: none; } table thead, table tr.even { background-color: #f7f7f7; } p { margin: 0.5em 0; } blockquote { background-color: #f6f6f6; padding: 0.25em 0.75em; } hr { border-style: solid; border: none; border-top: 1px solid #777; margin: 28px 0; } dl { margin-left: 0; } dl dd { margin-bottom: 13px; margin-left: 13px; } dl dt { font-weight: bold; } ul { margin-top: 0; } ul li { list-style: circle outside; } ul ul { margin-bottom: 0; } pre, code { background-color: #f7f7f7; border-radius: 3px; color: #333; white-space: pre-wrap; } pre { /*white-space: pre-wrap; /* Wrap long lines */ border-radius: 3px; margin: 5px 0px 10px 0px; padding: 10px; } pre:not([class]) { background-color: #f7f7f7; } code { font-family: Consolas, Monaco, 'Courier New', monospace; font-size: 85%; } p > code, li > code { padding: 2px 0px; } div.figure { text-align: center; } img { background-color: #FFFFFF; padding: 2px; border: 1px solid #DDDDDD; border-radius: 3px; border: 1px solid #CCCCCC; margin: 0 5px; } h1 { margin-top: 0; font-size: 35px; line-height: 40px; } h2 { border-bottom: 4px solid #f7f7f7; padding-top: 10px; padding-bottom: 2px; font-size: 145%; } h3 { border-bottom: 2px solid #f7f7f7; padding-top: 10px; font-size: 120%; } h4 { border-bottom: 1px solid #f7f7f7; margin-left: 8px; font-size: 105%; } h5, h6 { border-bottom: 1px solid #ccc; font-size: 105%; } a { color: #0033dd; text-decoration: none; } a:hover { color: #6666ff; } a:visited { color: #800080; } a:visited:hover { color: #BB00BB; } a[href^="http:"] { text-decoration: underline; } a[href^="https:"] { text-decoration: underline; } /* Class described in https://benjeffrey.com/posts/pandoc-syntax-highlighting-css Colours from https://gist.github.com/robsimmons/1172277 */ code > span.kw { color: #555; font-weight: bold; } /* Keyword */ code > span.dt { color: #902000; } /* DataType */ code > span.dv { color: #40a070; } /* DecVal (decimal values) */ code > span.bn { color: #d14; } /* BaseN */ code > span.fl { color: #d14; } /* Float */ code > span.ch { color: #d14; } /* Char */ code > span.st { color: #d14; } /* String */ code > span.co { color: #888888; font-style: italic; } /* Comment */ code > span.ot { color: #007020; } /* OtherToken */ code > span.al { color: #ff0000; font-weight: bold; } /* AlertToken */ code > span.fu { color: #900; font-weight: bold; } /* Function calls */ code > span.er { color: #a61717; background-color: #e3d2d2; } /* ErrorTok */ rotl/vignettes/fig-vignettes-birds_in_a_tree-1.png0000644000176200001440000002244615132142363021777 0ustar liggesusers‰PNG  IHDRhhzåaÕiCCPkCGColorSpaceGenericRGB8U]hU>›¹³+$΃Ԧ¦’þ5”´lRÑ„Úèþe³mÜ,“l´AÉìÝi&3ãü¤i)>AÁ¨à“àÿ[Á'!j«í‹-¢´P¢ƒ(øÐúG¡Ò ë¹3³»“¸k½ËÜùæœï~çÞsîÞ ¸,[–Þ%,®-åÓâ³ÇæÄÄ:tÁ}Ð }Ð-+Ž•*•&ã¿Úíï ÆÞ×ö·÷ÿgë®PGˆÝ…ج8Ê"âeþŲ]€AûÈ ×bø Ä;lœ âõWžð²Ï™‘2ˆ_E,(ªŒþÄÛˆç#öZsðÛŽ<5¨­)"ËEÉ6«šN#Ó½ƒû¶EÝkÄÛƒO³0}߸ö—*r–ᇟUäÜtˆ¯.i³Åÿe¹i ñ#]»¼…r ñ>ÄcU{¼èt©ª7ÑÀ+§Ô™g߃xuÁ<ÊÆîDüµ1_œ u~Rœ æàâ*-°z÷#°Mi*ˆËWh6Çòˆø¸æf}î-gi:×Ð9¥fŠA,î‹ãòV§>ÄW©ž—Bý_-·Æ%=†^œ tÈ0uüõúvW™â’9 Œ%/VµñBÈWµ'¤_¶tâÜÈMÛ“ÊŸ¿ŸåP““í\>ĘÉ@Á„yì0`D i|[`£§ èh¡è¥h¡øÕàìßÂ)ùþ·TjþÈëèÑ0B¦ÿ#ðЪÂïhU#¼ ~yh«uÐ fp#Ô1I/I’ƒø"“ä0!£ ’'ÉSdŒdÑ:J5Ç–"sdó¹ÑÔy#RŸ7‹¼‹èwAÆþgd˜à´ÏÅJŸ7ØÏØÏkÊ•×n^:}nW‹»FVŸ»Ösét$gj-tÈÚÔrÏÿÂ_ç×°_ç7Z þ~ëÛV·5ë4ÌV }ºo[ÄGó=Nd>¥-Ula³£¢Y5VúË}¹x»g[üä÷É?’kÉ÷’&ãÞä>áÎsŸrŸq߀È]à.r_r_qsŸGjÔyï4k± æi—QÜŸBZØ-<(d…=ÂÃÂdKO膄 a/zv7«]»ǰod«}¬€©sìn¬³Öá?TF–'|¦ãï3Nnã„#I?"…m»z„íõ¦v~K=Ú¯Æsñl<b|_|4>?Âpƒß‹¾QìñÔré²ËâŒi´µšêŠÃÉäãb ¯2* åÀ (ëºè»Ѧµ—hå°{28ÂoIþýÛy¥esŸ8ü';÷Z¶9à¬ÐûhË6€gã½ï¬>¦xöRx'Äbß8ÕƒÃÁWOÏ«ëõ[xn%ÞØ|½^ÿûýz}óÔ߸ ÿÿ%x ÅcÖË8eXIfMM*‡i h hx•o IDATxíÝ ŒÕÀñv—vYJ•‡lц4Ó -TE TŠB¢-ÑØj|ÕbjASúÐRli´P·„GcŒm´µ¡¶‰-R[±R¤¥”G$„‚ /ylå±l=·‚wîìî=wîÌ™ïÜûŸ„pgî™s¾ùÉÇpîÌ™N­,‚  N ³ºˆ@ #@‚æD@”  •v a!€$hÎ@@© ZiÇ @‚æ@”  •v a!€$hÎ@@© ZiÇ @‚æ@”  •v a!€$hÎ@@© ZiÇ @‚æ@”  •v a!€$hÎ@@© ZiÇ @‚æ@”  •v a!€$hÎ@@© ZiÇ @‚æ@”  •v a!€$hÎ@@© ZiÇ @‚æ@”  •v a!€$hÎ@@© ZiÇ @‚æ@”  •v a!€$hÎ@@© ZiÇ @‚æ@”  •v a!€$hÎ@@© ZiÇ @‚æ@”  •v a!€$hÎ@@© ZiÇ @‚æ@”  •v a!€$hÎ@@© ZiÇ @‚æ@”  •v a!€$hÎ@@© ZiÇ @‚æ@”  •v a!€$hÎ@@© ZiÇ @‚æ@”  •v a!€$hÎ@@© ZiÇ @‚æ@”  •v a!€$hÎ@@© ZiÇ @‚æ@”  •v a!€$hÎ@@© ZiÇ @‚æ@” tQa!€@ Œ9Rêë륢¢"Q…_ýêWÒÐÐhÅTN‚.F}@ ÁƒËóÏ?/555‰ÔïK¥ qøÒSĉe'@‚.».ç€@À†8|é)âDÈ_ü⥥¥Eºví¨céÒ¥™±îÀFE+$hEA( Œ@uuµ|÷»ß•þýûèÙ³g`]Û Z[ Œ1B.¸à‚Ø"߸q£œvì˜,Z´Hr‡4¾þõ¯‡¶å‹Ãå÷$h—Ú´…©Üwß}bÆ¡s$¬¬¬L%ÛFIжR”Co&MšäeìÜíe·4”ƒWÐåÐË#ž lß¾]®¿þúÀ\›6m’æææHcÐ/¼ðB›CcÆŒ ý©‰Š­©7ˆ2ÿþ÷¿C7ß|sä;1~ô£ÉÕW_úA𪫮"A‡¤Ù€$$°nݺÌÕröLxæîÙ³gËÀj5™j¹‚NÆ•Z@ %»ï¾[.¿ür1·å[¶mÛ–9·îËß$h_zŠ8@ÀJ`È!òÄOæyž:ujfߣGê0WÖ:u lÓ´B‚ÖÔÄ‚‰¼ÿþûrÏ=÷„îƒf²¤D¸“«ôøñãräÈ‘ÌVr­P3¥%púôéÄèàÁƒ2qâÄÀm5ÚÔÔ$æÉÁì7¥¼ôÒKmU¿+èœ.Z¼x±,_¾\†žó « О€ãMzyíµ×¬š0ùt[í¨° :§S† &wÜqGfR–œ¯XEvÆŽÛÎ7l.F€]Œû"€€:;vˆ¹g:wÞ¶奱m©° HH`ýúõ Õì¾ZæâpoN‹ €€• ÚŠ‰B €€{Æ Ý›Ó"80¯Ë2KîüÏO>ù¤ôîÝÛq4öÍ‘ í­(‰ž ˜UæÌ™#ýúõ öÛñHÐîb|˜5k–Õ‹dÍìxõõõ2hÐ ŸOHÐ^uÁ"€@¶ÀÖ­[åþûïÏ;Gôo¼ÞÈ®Gëg´Öž!.È+`†(ÌœÎuuu–mii‘•+WJ¯^½ån¿ývéÞ½{`›¦´¦Þ HD`ÆŒ™ùur$ìÜY÷l$èDN*E ¼Þ{ï=ùíoëü ÷îÝ+65Íœ9Óylq4H‚ŽC‘:(sqãÆ‰yÄÚõrâÄ 9{ö¬ëfµG‚vFMC”®€yç_Ë_þò«w ®Y³&S®K—`ÊûÔ§>e5gGÇfÚ F›V´‹$(ðÐCɨQ£B?šÙ+m&UJ0´«&AwÈ×  YàÔ©S²oß>9yòd‡aöïß_yä¹ð ;,§íK´¶!°0C&ñæ]äVðÖ[o‰y[’o Ú·#^8/ðâ‹/žÿÜчiÓ¦å}˜¥£ýÓúŽ–<í"€€33 2eÊ”Ðx3ö;ëBÚøÓŸþÔöÊ·ê~ŒF9á!€I  “Ô¥n@ Æ ‹ÀcWðCÀ<éhnÉ˽ç™1h?ú(@ „  .ó·O WÐ>õV±šùoÍdæC† )`/Š"Pšk×®3¡ º4û×»£ª®®Î<Úúýïß»Ø ¸îºë.•ú¢ TTTH·nݤ¡¡!z%ì‰@‰ìÙ³GæÎš‹cÞ¼y¡Iü52CšzƒX@  ´9›]MMM"íÅU) :.IêAµW_}µÚØ: Œû ;Òá;@ E® Sħip#°xñâ6ßIxË-·d~«qEá­p]¸{ €€gÏ=÷œìß¿_Ž;øÓÚÚªúH¸‚VÝ=‡… ¬Zµ*sUœ=Gt§NäË_þ²\tÑE…V—jytªü4Žq <öØc2zôhɾCÃL7jõöm!AûÖcÄ‹ ˜«äo~ó›g6nÜ(s%½ 4HÌ3Z´Öž!.È+`@1 e'^ó~ÂܱåîÝ»ËOúS©¬¬ ÔiîîÝ»w`›¦´¦Þ (Hàú믗¡C‡ïúõëåĉÒ·oßóu­\¹òügŸ> }ê-bE€À°aä±±QêêêÎoŸ:uªôèÑãüºÏ¸ÍÎçÞ#v(i® Kº{98Úxøá‡Kb*Ú·ß~;twÆîÝ»Å<€’}›]Û "LØßž Û@ 5—^zIæÌ™“Zûq5ÜV~ýõ×ãª>õz¸‚N½ ÷}úô‘éÓ§»o8æÍpî17‘juŒA§ÊOã €@û\A·oÃ7  \`Ë–-rÛm·…^köòåËÅüoBëB‚ÖÚ3Ä…yþþ÷¿KçÎÑÌ[‡4/$hͽCl С@©ÜïÜÞAFÿ§§½ÙŽ ‹Wб0R å-`Þšý±}Ì;„{ï½Wzöì©6n´Ú®!0üøÇ?þ!Ó¦Mó'à#­ªªR3 Zu÷~˜«ÐqãÆù¬GQ’ =ê¬$B}íµ×äÖ[o•áÇ'Q=u*0ó#³è AçôÑöíÛåg?û™üæ7¿ÉùƯU3Ý¢Í-Dýû÷—‰'Ê’%Kü:@¢-J`ìØ±EíuçeË–‰9ç´,æª_ó0 :çL¹ï¾ûÄüñ}Ù´i“˜7³  Ià‡?üaæóbî]ŽóxÌ«±HÐqŠRx+`®ž¿ño¨~Í”&\îƒÖÔÄ‚d 0Ä‘…ÁGÐ+°ÿþÈsn´wTæ}„Ùï3l¯\ZÛIÐiÉÓ.$`~ؼä’KbMÒÏ<óŒÔ×ׇËÂ$h—Ú´…‘ÌûW¬X!µµµ‘ëðmGÆ }ë1âE² A—MWs  à›C¾õñ"ƒÀ®]»döìÙ1Ôôÿ*Ì^š—Ï~ö³™»ví“—Æ8XA ¿øÅ/¤¡¡!¶PÖ®]ªëŠ+®s—Dö²~ýz9{ö¬óû  $ .”d‡£þ3WÐ껈ˆ_ îG½»wï ÒL¦ÿ‡?ü!°}üøñ¡7 ˜+ù¾}û†¶vü`eëÖ­rêÔ©ÜÍ¡usl---’ýÆïÍ›7Ë‘#GHÐ!-6 €@Y ˜û‹+**ÇÞÖ=ÇfªÒGy$ïÛ¹W­Zª/Pù‡+&Ù?ýôÓÿ!˜©Ps¯æÛÚWÛ6® µõñ Pfæ¶¹/|á yçÄøÉO~b• ÛâÛ¶m›Ìš5+4Ø¢E‹¤®®®­]Tl#A«è‚@(3fÌÈ$ÝìÿÌ8·™Í1{ŒýùçŸÏ yäNÒÔ«W¯(Í:Û‡팚†@ nƒÊܹs%;ÑîØ±Cª««M 2$°îË Ú—ž"N ˜9ÏGŒ¦0C&¹cß¡=Ù@‚ö¤£ìöîÝ+?ÿùÏÅÜE’oùêW¿*mÝ’o?Wß“ ]IÓ%°{÷n™0aBà긩©IŽ?¸‚ž9s¦ÔÔÔXMª¤ýJ›]Ô)ÃÎ Pˆ@ss³lذ!d=*­­­y«1·ãå.“'O])å+_É-æí: ÚÛ®#pü0Oô™é²ï‡Þ³gOæéBÿŽ&ùˆIÐÉÓ|(ðì³Ï†,þõ¯®¨C:Ø`†7Ö­[y ÒOúÓVC!„èW$èDy©òعs§˜§õ²óxuÒ‹™Àÿå—_Žœd?ñ‰ODÞ7éc3õ“ ](Ó%.ðÊ+¯„î†0ãÃI/æ‘îR^HХܻŽÌ•lîRUU•»‰õ˜°¿@0Š#€®¸‚v%M; šÀå—_.={ö MÈdæèÈž³#µÛi˜ÝŒï›:$¿ÿýï%ß¼¿æ¾ÔÜ d|?vâG Wà²Ë.cÂþ\ÖÓøÜç>'6¯!2Ó0>ñÄéJËe/ðŸÿüG®»îºD/Ì%‡fÂþ²?Û@‚6nÜXPù(…Í-€šç}nï˜âhO†í P2æasÛ_eeeà˜xil€ƒ@À½€™ÿÃÇ…Ûì|ì5bF² A—E7s à£cÐ>ö1#à€™¿yöìÙª#ýÎw¾x]–¶`IÐÚz„x(¥K—JïÞ½Uæ·©8´êÓ‡àðW`ôèÑþ¯$rÆ •ta €¹\A犰Ž%'ðÔSOIuuuè>è)S¦ˆy3¸Ö…+h­=C\ ›€y åÈ‘#ròäÉÀ›w!ÆD„Џ‚Ž€Æ.å!ÐØØ(C‡-ƒ-ƒ£üÒ—¾$_|±WGJ‚öª»Ö¥ÀüùóåŽ;îpÙ$m%$ðî»ïÊ™3gª=¹jIÐÉÙR³çæjëÛßþ¶çGAøF`ýúõòÎ;ïHKKKÄü©¢¢"°MÓ ZSo $"ЫW/Y²dIèGÂÇ\õ½Ú$èDN*EMË–-ÓŽu,ÜÅaMEA@À­ Ú­7­!€Ö qXSQ|5j”˜96ºvíš7\&ìÏKD@ >aÆÉÓO?­úmݶGˇ­å@Ç q8§¹Ò'Áß P+V¬È$âÎ?ºbÿþýRSSãÝñ‘ ½ë²x6sä¾òÊ+2vìØx+.Ú¶nÝZGQ~‡0räÈÐA:tH,X =zô|÷àƒJÏž=Û4­ 5õF ±\yå•bþKÈà­°‰¯[¾õ­oe†<ºt ¦<íCÁh}Õ'n@ o¼±ƒoõ~õÑ Þ‰ (K® Ë²Û9hJWÀÜÛlÆšs‡3Ú:âk¯½Võ$è¶zm à­€yƒ÷øñã3&å;ˆÏþó$è|H|Ä%pá…ʬY³xÔ;.PêA \Ìš5ö±_Ž?.gÏžõ1ôPÌ q„HØ€€;É“'gþ;î®ÅÒoiË–-ÒÜÜ8Ð={ödæáèÔ©S`{}}½d?ÐøRÁ ZA'Bù \rÉ%ÒØØX¾ ¹™,)÷”‰'ÊÀ›¦/^,&Ik]HÐZ{†¸@ 6#FÈÂ… C“%ÅÖ@B‘ ‚¥ZHG`ß¾}rË-·n³Û¼y³>|˜N—Ð* ð5kÖ„(¦M›&uuu¡íÚ7p­½‡ˆŠxûí·Åü [YY¨‹—Æ8XAÀM›6‰ÍÛ¶móç Ê4Òµk×zyä\A{ÙmíBÀ\uuíÚ5oSæ©5’ A'¡J%!`;O°æûhK¢#Êø HÐeÜù:I \sÍ5Ò¯_¿$›(ºn3o‡æIÐEw1 €@['OžÌÜ{ÜÖwZ¶™—Éj^HК{‡ØðXÀŒßç¾EÛãÃI%t&ìO…F@ü\Aç7¢x.ðè£fæáȽú®»î²š7:­Ã'A§%O» àLàoû›LŸ>=ôƒ`EE…³¢4D‚Ž¢Æ> I`Ñ¢EÒ¿Éö3Reìdæˆ6oOü2uêÔ@r/\(Ù=HÐÉúR;‰ ˜û‚¯¹æšÄê7ïÚµ+Öú{ì1«7´üñ üØ^&Aç.Ï>ûl(¿øâ‹rÓM7…¶çî«m­­GˆK¡C‡ÊÒ¥K-KG+–û¨v´Z>ÚkÊ”)­t𩾾>tÜAñÀWï½÷ž¼úê«»3Ìãåæ©Í‹/¾8PVû Z{$0jÔ(Ù¸q£dßfgîì0óIû¶ }ë1âEüñÐ÷o¾ùfæ!ó°Kö2lذÀ|ÙßiøL‚ÖР‰ ˜S—/_ƒæA•DÙ©È/ôX}þ¢•`²¤hnì…$.@‚Nœ˜@hŒAGsc/HP`ß¾}rà 7D¾ÕÎ64&ì·•¢ ð¡Àºuë°ø@€!N@@© ZiÇ À4甼Àu×]'§N <]hÚ¼÷°OŸ>jŸ­¶k â0IxÁ‚2`À€@•um+$hm=B< P”À­·Þš¹RΞ‹ã7Þ'NXÍWTã1ïL‚Ž”ê(DÀ$ 6²Ëù²f_–°€™ÃzΜ9bfÄ;·Ìž=[zôèqnÕ›¿IÐÞt–¢@ß¾}eÙ²e‘íÝwß´_©ïTUU%]tQà•Wüà¡$ýÐCImm­Z´Ú®!°rXµjUäÃ4oTIz1Œ˜ÄæÓ²e˖Л¾}ôQ1‰;ûÍ+æ˜Ì[V4/$hͽCl¤,ðÀÈÀSŽ¢°æ÷»ß…±¹‹ÃÇ…íc¯3ŽÚz¥”£¦#7ÓØØº.re)ïH‚N¹hâ8tè¼üòËVcËãÇW=ÌA‚Ž÷Ü 6HY`̘1²gϱùµ¥¥%åh;nžݱß"€€góæÍó,âöÃe.ŽömøHU€+èTùi\ìÚµ+sgGçÎÁkÒ~ýú%>çt1ÇG‚.F}@À I“&e^éÖ­[ Þ§žzJÌ eµ.$h­=C\ ›ÀðáÃeáÂ…¡É’bk ¡ŠHÐ ÁR-Ä+0bÄ1Æç> hÓÊæÍ›åðáÃ$h,Ê €… \z饲bÅ «û›sëž6mšê¡ŒÜxÏ­s}N‚¿@ dvîÜ)S¦L =aÈKcK¶Ë90ðEàõ×_÷%Ô@œ\A8XAÀ£GÊ«¯¾êOÀEFj¦ Õþä_‘‡Ú"a~|ò“Ÿ”?ÿùÏ~C”&AŸ9s&†šü©‚íO_)•+WÖK}ÅÌmætηÜtÓM™‡O²_yÕÞ>‹/¼y¥½rim'A§%O» ˆ€yZмdÀæmݽ{÷N$†¸*%AÇ%I=  BÀ\9›äÜÐР"žb‚ A£Ç¾ àL`÷îÝ2þü¼ÃMMMÒÜÜì,®$"A'©KÝ ›Àܹs3©TTTtXçš5k¤²²2PÆLAj¶ån¿ûî»C/’ ì˜ò :å y°0?þÙ,m=¾víZ™1cFèiB›mÚLª :)YêETÌíx¿þõ¯„›{ÆG-ƒN%¦¨’ £Ê±¨¸ñÆ3÷K;vì||§OŸ–ÖÖÖóë¾|èôAÐþEí‹.q"€€ &ÈwÞºõ® K«øÃ ¸‚ÖÔÄ‚‰˜©JÍ8tî„£F mK$€ˆ•rŽÝ@¤‚/èJº5êG° A[SQp+@‚vëMk €€µ ÚšŠ‚ €€[´[oZC¬HÐÖTDÜ  ÝzÓ `-@‚¶¦¢  àV€íÖ›Ö@k´5@·$h·Þ´†X  ­©(ˆ¸ A»õ¦5@ÀZ€mMEA@À­ Ú­7­!€Ö$hk* "€nHÐn½i ° A[SQp+@‚vëMk €€µ ÚšŠ‚ €€[´[oZC¬HÐÖTDÜ  ÝzÓ `-@‚¶¦¢  àV€íÖ›Ö@k´5@·$h·Þ´†X  ­©(ˆ¸ A»õ¦5@ÀZ€mMEA@À­ Ú­7­!€Ö$hk* "€nHÐn½i ° A[SQp+@‚vëMk €€µ ÚšŠ‚ €€[´[oZC¬HÐÖTDÜ  ÝzÓ `-@‚¶¦¢  àV€íÖ›Ö@k´5@·$h·Þ´†X  ­©(ˆ¸ A»õ¦5@ÀZ€mMEA@À­ Ú­7­!€Ö$hk* "€nHÐn½i ° A[SQp+@‚vëMk €€µ ÚšŠ‚ €€[´[oZC¬HÐÖTDÜ  ÝzÓ `-@‚¶¦¢  àV€íÖ›Ö@k´5@·$h·Þ´†X  ­©(ˆ¸ A»õ¦5@ÀZ€mMEA@À­ Ú­7­!€Ö$hk* "€nHÐn½i ° A[SQp+@‚vëMk €€µ ÚšŠ‚ €€[´[oZC¬HÐÖTDÜ  ÝzÓ `-@‚¶¦¢  àV€íÖ›Ö@k´5@·$h·Þ´†X  ­©(ˆ¸ A»õ¦5@ÀZ€mMEA@À­ Ú­7­!€Ö$hk* "€nþá$¨Ô9%)IEND®B`‚rotl/vignettes/fig-vignettes-eggs_in_a_funnel-1.png0000644000176200001440000004424215132142351022144 0ustar liggesusers‰PNG  IHDR°ØŠž¶©iCCPkCGColorSpaceGenericRGB8U]hU>›¹³+$΃Ԧ¦’þ5”´lRÑ„Úèþe³mÜ,“l´AÉìÝi&3ãü¤i)>AÁ¨à“àÿ[Á'!j«í‹-¢´P¢ƒ(øÐúG¡Ò ë¹3³»“¸k½ËÜùæœï~çÞsîÞ ¸,[–Þ%,®-åÓâ³ÇæÄÄ:tÁ}Ð }Ð-+Ž•*•&ã¿Úíï ÆÞ×ö·÷ÿgë®PGˆÝ…ج8Ê"âeþŲ]€AûÈ ×bø Ä;lœ âõWžð²Ï™‘2ˆ_E,(ªŒþÄÛˆç#öZsðÛŽ<5¨­)"ËEÉ6«šN#Ó½ƒû¶EÝkÄÛƒO³0}߸ö—*r–ᇟUäÜtˆ¯.i³Åÿe¹i ñ#]»¼…r ñ>ÄcU{¼èt©ª7ÑÀ+§Ô™g߃xuÁ<ÊÆîDüµ1_œ u~Rœ æàâ*-°z÷#°Mi*ˆËWh6Çòˆø¸æf}î-gi:×Ð9¥fŠA,î‹ãòV§>ÄW©ž—Bý_-·Æ%=†^œ tÈ0uüõúvW™â’9 Œ%/VµñBÈWµ'¤_¶tâÜÈMÛ“ÊŸ¿ŸåP““í\>ĘÉ@Á„yì0`D i|[`£§ èh¡è¥h¡øÕàìßÂ)ùþ·TjþÈëèÑ0B¦ÿ#ðЪÂïhU#¼ ~yh«uÐ fp#Ô1I/I’ƒø"“ä0!£ ’'ÉSdŒdÑ:J5Ç–"sdó¹ÑÔy#RŸ7‹¼‹èwAÆþgd˜à´ÏÅJŸ7ØÏØÏkÊ•×n^:}nW‹»FVŸ»Ösét$gj-tÈÚÔrÏÿÂ_ç×°_ç7Z þ~ëÛV·5ë4ÌV }ºo[ÄGó=Nd>¥-Ula³£¢Y5VúË}¹x»g[üä÷É?’kÉ÷’&ãÞä>áÎsŸrŸq߀È]à.r_r_qsŸGjÔyï4k± æi—QÜŸBZØ-<(d…=ÂÃÂdKO膄 a/zv7«]»ǰod«}¬€©sìn¬³Öá?TF–'|¦ãï3Nnã„#I?"…m»z„íõ¦v~K=Ú¯Æsñl<b|_|4>?Âpƒß‹¾QìñÔré²ËâŒi´µšêŠÃÉäãb ¯2* åÀ (ëºè»Ѧµ—hå°{28ÂoIþýÛy¥esŸ8ü';÷Z¶9à¬ÐûhË6€gã½ï¬>¦xöRx'Äbß8ÕƒÃÁWOÏ«ëõ[xn%ÞØ|½^ÿûýz}óÔ߸ ÿÿ%x ÅcÖË8eXIfMM*‡i ° ص…¿!@IDATxíØEÒÇÅ„ ¨ˆáÁŒ FDúè#×½{w·ÒJ+å™rÓ½¿ÿþûnÊ”)®Y³f®W¯^îOúSÓ#-C ~ø¡›>}ºkß¾½[{íµsPl¬‹b¡Jäxÿý÷;Úù.»ìR¢«7¾©ü1¥Ë-·œ[f™eRÜ{ì1÷ÙgŸ¹¤¸G¦M›æ>ÿüs·É&›¸6mÚD_5x?gÎ÷ÜsϹVXÁm¸á†‰~Éç믿î:vìèºuë–è§ÜŽEù¦‚2ÒK,¨‰¿]wÝ5ÌÙ6ÛlúéÝ»·º'¹…qóí·ßG}tpÙe—5"ô‚ì»ï¾šÏÛn»­Ñq46àìÙ³ƒÖ­[‡8]y啪ìá®»î:-ÇСC3æ¥ØX;þŒ+Á‹E]Tñ•Ác R«î$„i„ß”ï«FR¨©S§2èU)/bÛm·úùÇ?þ{Óðã}÷ݧáöØcŒ/¹äõsì±ÇfôSîÅø¦Ê*ùÁ‰'ž˜6¢YmµÕôõo¿ý椸æÍ›»·ß~Û-½ôÒ.ÉÍÇÕØë™gžé.ºè"ý56F´íÚµs]»vml÷üóÏ;a®OŸ>nüøñnñÅot\Õ°ØX;þrb<|øp÷믿ª¤^Î|TzÚH>Ÿ~ú©C´ñƇÙíÔ©Sx?aÂwøá‡«D:øMʨQ£TûTà¨K]1¾©Š``x ª‹âh~õÕWîÒK/U†%Òš£± ~Ë&Åm‡vpK-µ”›9s¦vÞ_~ù¥ªñ„ã»\0Œö‹/¾p7ÜpƒCÜÞ`ƒ œHqªê{á…TDÇ#qÃ$÷Ûo¿0œ¿AÝ)Ò•ÃÿB -äzöìéD"TÿøYl±Å\Ë–-•Ù~ýõ×îšk®ñAS®ûÛßTMÙP~³¥ðé§ŸÖrㆺãúë¯w"Mª—ï¿ÿÞ=òÈ#?­Zµr`åU³¿üò‹2ìW\Ñ1`¸óÎ;ŒõŸ{Ê|×]w)“\wÝuUE¹ú꫇ÞHW$'÷Ö[o¹:¸}öÙÇ/å þùg÷ç?ÿÙ­¿þúŽúÁ/t衇jÝ…Ån¨êç ƒÒ8ñÅÚ!O<ñ„{ï½÷ÌN;íªQóÁ3)~ò@Ùöß÷øã»§žzJ+"%jû<į Õ1~‰ó–[nQœú÷ïï>þøc÷æ›oºÁƒkljpGEµÊ*«¸ƒ>Ø]{íµŽï´“([]-¹ä’úýö™gžqO>ùdZ4tš2âWwTý¨¦[´há¶ß~{·Ùf›¥ù÷?üðƒâCœ0É5ÖXà 8Pë‹¶xÅW¨š ÕðÍ7߬ùà;%=Ú-j°=z¸Aƒù(õJÒŽßxã ­[Þ/»ì²úîwÞq“&MR&.'NTµÞ¿úê«ê|åc dP,²È"t6úž´DêT?{™#y|E?Hìµ×^êW.ú>þçUˆäKæó¯ò’yƒ@ê=Š5wß}·ÆIÞ|Y„aï¾û®úÏOÄã—ÎPãßtÓMµì2€Ñgél5þ¤¿lu,|àñ¢ŒÜwîÜYã‰Z£6l˜>Ó~ð#sÀŠ¿Ì&%©˜ã7S]Èã)Dô=~·ÝvÓø9æMŸo†õqá…&¦£ \Ô?u@]—WûËܦ>“wéõÇ{êuË-· ±Àíì³ÏÓøç?ÿ~Û¼óad^HýƒW7”jÝøú§J©~rÁ:Lð¿7 4^¾¡µÖZ+yå@˜yè<Ò¶…ñ /¼°ú _&Üx¢ ìÔ?XR¨ïLßc\…È7ÄwHXÒå›&Nž3©³µ¦lOæÕ¡<ï¼óÎaI²µç†úX"‰SÙâË–gâtü•‹|C¨øïÞ{ïUæCäÌGDú@FÚ(£n2úDP"E<Ëdª>‹Ä¥Åó‡ R6v‘†ó-ÄyòÉ'0Ï8ñ±‹”´mÛVïÏ;ï¼à¤“N dÔ¬Þ£$‡2`õ|€|¤Ä/#6õÛP~sIK#ùï˜\pÁ¿H)Š“ŒÃÎDFÁ| < TFXZnòÄïÈ#Ô|ŠJ4j½—Q¿úI@" ýë_tÿÐ 'œ ï)?Ø‹ SŸEÒ÷äE¤/u Z¯2ªÔôÕCìÏ30˜Ä³Ï>0?I‡J>)Åšg:Ò œà·ûÕës¶º#Ž(Åã20Ú éxæC»L¢†êÿ Qé?ýôS@[õõcpÓ€Ð÷Ýwa»^uÕU“’ ²Õ¢ Ìi§0&Òç½HìH ʰD-À|h ÞD=ÈH;-}Ñ:"9‡rˆ~»<ã—8ÁÌ30ž=#`À³hô»¼ñÆõl Úm?ÌO‹¡D^<ƒ/uíL[ ÔM ½Â0Ä“ küÄiï½÷Ö8`b˜¥÷¤;yòä¸×¼y¡"MjBœ à=ã9ú=Ƙ¯'ò$†mÁ¿þõ¯@ŒÆ4I ,—þÄ30‘º‘Ä´ ®}Þ(p¶öÜPKøø7ÕP|¹ä™8gn'¥*$1 3Hù1$nh­#®æ¡s;Þ‚Ç»‰àf̘áäÃsˆÖ·ß~»ú%ÒÙjVQù@‡v˜Š²ùË_Ô/é #u¨U 1„Uêðß?Ò’‘£Z‘ÄvD~ÔŸI‡Òèu. µê<Ôf¨ˆ˜ké¡üæ›ó]>ÿÒ©†eôÑG5÷”Uý$Ôí¸ãŽª¯GM¥ÓN;͉ÄêV^y娳ÞûùHa"Nªr…A¨ú¨í T:`/Ž“Ñoˆ=V‘¨n©7TV¨_o½õVÅ]føiGÕ´¨>Q©A/¾øb¢oæuPÅ‘æ$°ø‚°VÍÏÄþë(šæ›z&¢®"é¦ÉVÇòí©š†€´Eð’<¬;ÜQa1ß‹ºµj¤!C†ð*#e««x@êŒoM˜£é[çÅ„‰¨ª5 ù¤Ý3-#fU5ƒ)s®qB/Ú'ƒ'FªîD]¡ZôÄ÷†*¢=A´'Ú.jy‹>H0ŽïU$õŠà©§žªuÀ7$¶úãë_ÔÛÔ·WsR7¹`F¹‘Á®–‡4hw"qé[úŒ¦êOʵ sÖ*»(5ô=z¿¨HQÓ£Âd:$åÓþiƒ¨ßQõû:Â2[{&í†úØx޲ŗkž+bŒ’¤±Ó‚ÐAGžÎ’ù>::R>2€øåC÷Üsƒ0'AeñŒv44¢8É(ÂÑá½üòËúAñq“‡lù%ž|ÓŠ§ sŨƒAsRžü4ó‹ž`€tŽ™æ@¾™·BgÍïòË/wçž{®ã#÷å Í=ôÐCïHÁøé(éðaätÖÌ3f#Âxò̧åÝý•ù:`:Çm·ÝV?j&à}7OŸN4O R :È8ù|fj“tì`Jþ<ö<ƒ 7DûTyŠ›o{wÍVWÞ_ô:kÖ,5©gàÁ÷#*^}íË #|­k†ïJ$Fÿ^ñÏD=ƒF̹™OeðÁ¼eóÅA'Ä )J¯S…o·¼¤ý0h„Ñži1¥ô’~¼ä%:ý0ˆÿØC‡Ø ë7°®ä*ª3'zõÁD4´õÖ[ë,Á†}þùçkZ|Œ’'#G:c/#=ßA«‡„?F~¾>¼”çcÔ;ñ‰*W¥PÖáÝqÇ:b÷~ §KTzþ¶Ák¶:s$^:QIi\tÈXÚzÂ@ˆv‰$D O Q¶ºŠ‡¥-3Ò†ÉÐ^10òä땵GÔ+?ê+W™ñÞÂ+ßÌ È·‚ñŽg\þŠgÿ­…3¸ñƒˆx=Ó”yPe^ Îø¶@$E˜Ah£FÂ`žq¢oìØ±êŒj¤_¿~aù°¤j(¿ù¦OÛ?Ë\„ÞbQIùE÷®LD Ô2ÌûKêPü;®X‹¡ö€é€'’ äG}^Õ€tÊR,™°D*‚ÀùŒ3ÎPIƒðŒàHx•ŒzJøƒaE†”'†*êKÄ8ññ ™0R¤s•¹Uýà·BáO7ÛsCuLX¤ˆöue´óB[€ªõ '86DÙê*KF$j:¨ÿi¯¨äPuÁ`:ê(¸ðž[T%èãD‰ñŽ2Z€— ¼ÔàýæzåÛBòaB[£‡j"OQé´¡8³a+<|ó˜±óƒÐª4…P¯‚/}ßeØsÏ=Ã(³}|_ø3fŒ~Çôyž†‘Dnòiÿ¨áùÎQO¢6F;à%òlí9[É’Þ6_Îy©¤lÔ‡HLš/&‚¥´|Ha>“ܘÅpC:õ/#š@:Ó0 –BlHg§ï¥óÕ…Ë"¨&TE}† FnDˆz*œ˜&-&[}Rñž…Ì~a!yÿ¤±é„mCùÍ–V$[z+Ò¦¦#£è”WÂ̰ Òè€ËˆRýøIc,"&Òå£ ¨_,²Ä´9 ÆÂi %x/>T'å¥ã 0ØÀ¼@òÑj^0PÀX!NÞˆƒ,I ‹A’"±¨÷(Ö8`á-C1:ð†%~ñg¾xÆã÷F y’UóÆ$zek“„¦¯ù¦=^|ñÅVŽ”×[x ¤óÕEêXˆaÜÄ{¬Ð’(—ºŠqƒÔøˆ3úcÂ’ËGÞaL"ë¡$%­n²Ì ü>hkàOX {¼Ö¨žd…¾7nœ:a…Ú¬'Ê$Ï«RÞa<#Ì$ÀP òF´9OÂèկ̗y§¬X‡ÿ{Cüln@{"]Ú7FAIäû¤wÞÍ9‡¨ê4Np©G½dúãFx/ßb á-}“Œ8ðŸ­ý{#ŽãŽ;.Ì}®ho®”­=gëcãßT¶ø²å™L¡V«)D,s2‘HijM•ôžë­Ø’Þ{7Ò5†šÏz·Æ^³å·Pi‰Ô¤œÍ§G'$£iÿ˜v¥ãBV~tbÙæÖPݾPxfËKô}¦:i)cmKÞ¿·Ìb†õ%!Q?¢RQ/¯½öšv|2ùïƒd¼f««Œ^°$ƒ_.D^E5™‹×¼ü0P¤L~iL>³aÝP\´+,0ýà©!¿¹¾+Dœ|gÙÚ{$DöAëqãÆåª|^VYeU1sÔÎå—_®ëØÊ—KÙ0ê Œ zÙÆ(éœ)ö=¼öÚkCœž|òI=#l…VÝì¦qŒ;Öp aà6ÞxcU­µÖZ‘hì¶)$©f’mSµ°†€!P¤00_`:Ôk®¹FŸ}ö™{ï½÷T]=hÑûµkÓ`Ð0yòdÖóŒGuTÓ#¶ CÀ¨aX´¼l,k›ËF)ü}‡Ô¢N`æTl[SUxœ-FCÀ¨-²2°Ú*nå–3ÿƒ:¨r3h93 C ÂH1⨰¼ivØT˜Œ CÀ0 (910æfŠyJðG}äØ v‰%–еfï¾ûn˜Ç;ï¼Óí»ï¾á³Ý†€!` ‘qö»s¼ ë‘86ƒÝ8¾øâ‹‚#wÑE9¬î^|ñEµrÄLæÌ™OÇ"4 CÀ¨22°«¯¾ÚM:ÕùõH[mµ•[i¥•î…¦|ÐrÊ)®K—.î´ÓNs^x¡naõÉ'Ÿ:©ºˆi™Í‹Yú`d†@­"‘±ÓûÝù5J -´švÃÔ M]»vUéËÇÛ¿]ƒ¶ýöÛ»¯¾úÊ;Û5Þÿ}•š×_}Ç–OÇ|¡ÊëißÈ0 |ÈÈÀÚµkç`bQºçž{TÕu+ÄýСCÝ^{í•r0â1Ç£æäG}t!’¨‹80xùÿë_ÿÒò²Ç"í²»J%{)ræ è»wïngÏUb%Yž F £=ŒƒÎ…¶Ÿ~ú©ÎMÍž=ÛM™2¥àÅÙf›mܬY³tÁt4rvéÕ«—¾‹ºÛ}:?üðƒžŽÌÉqzùå—»ÆW¡ædNÕìÇ]wÝUiAÚ72 C ÛG½õÖ[îöÛow~ø¡2˜ £åb›'mO…qG«V­rJ“/¿ü2Ñ/ªÈZ>NC˜gŸ}6±ì={öLt/§ã;ï¼2/ŸÔŸo¿ývb;ð~ìj†€G #»÷Þ{Õ¬=º¸–ãäÙ-⤓Nòá‹~ÅŒþƒ>Ðm­²%öôÓOëYUIþ^}õÕŒg…%ù¯67Bœš5k¦§jo²É&ñWefnuÑEÕ“œ}fØ…C!#CÀ0rA #cÞ䪫®r_|±;äC4.Ž“ã7r‰·`~¢ÇŒd‹•¿$B%ê÷Lz_ín<óÌ3zÎ¥V1"U3Æ~øáºÆÉ)’IŒ CÀÈŒF¦C¹ôÒKµ,•¥s#ß|óM.y¯9?<òˆ4hZ`²¸Û*\¤Kæ¹2Ñ€T2fEŽÅá$áÇgò®3›nº©;öØc]ïÞ½SÎ#˨À/=ôPÝò¶ÛnÓ+ Öï¿ÿ~c5ªØÌûá‡.ÊÐÊ)¥å¤*KµD‰%¸ï¾û9,Øzë­9#,ƒŽ@¬ý7ÅQ¶Š FŽȉĨ½2hÑ¢EЭ[·àúë¯oJÔaXÙÝ= ½ð¹Òn¤×rSv~Ë.»l0gΜ@¬‘NÔMÔn,ön0ë2~ýõ×ýÈ!C‰”ôX`@Ö5®˜/eî+Ë×0O{ì±G V•ÅLÒâÎÑÀ„íOÎÿ xàB™—zB@,ƃ—^z©,EnPƒ#·lÙұЕ'ƒ0©–ÃÍ;WÏ ãL2Žtá´â+¯¼²ÉVTœ\pAJ~0H9çœstæñ˜l¶Ùf›¿þõ¯Ž´ã„*®yóÿh†1\™>}zÚ^’_ýµ&— »»¬¤$ÒÀ’`Têd=DµN´wÚø%—\âdÀRQÅe ¾ý}ÿý÷ÚøçŠÊ¬e¦.ÈÈÀúôé£g€ fÍãÆs¬×b·ŒBÓ£>ªóml[Å~ˆÀ09<“y’»ï¾»ÐIV\|2|IËËâî?ýô“ûüóÏUµ+RkZï@§ˆAÄzë­çV]uUe|,‹€Q¶oßÞm°ÁÞ«^YL¾æšk¦¸•ò!É%É­”y*vZ 0Ö]w]wØa‡¹#<Ò‰ÆÁUR™Yâ€J?J0Y@F†@% ÆÀzôèáþùϺ×^{Íí²Ë.®sçÎáïïÿ»•bÁóMÇùØc%ÆËœˆ¨ÓßÕ’ã_þò—”â,³Ì2*e5´&j„ )aüR­ßÅŸN‡94öšüÛßþ¦Ûvy智Ç%g½í°Ã:÷ä%7O)¯¡D‰A {pÖ2a ÅÒO047­¸g©¥–JɃÌzøS m‹@š"{2BïØ±£cqœâ :þ¾1Ïì8pà@5!]Ô–0Jv”`ˆ ³–‰2¢.  TæÌ õMœü6_qw– ÄGÎQ?§Ÿ~zøˆõ!ª:$ßr;† Â¼ãŽ;´þÏ=÷\-9óTì´“T¶InÅÎG¦øùÖYƲÿþû뾚H‹ãÇÏäÝÜ ’#ÐŒ™·L©²™nÛ¶mu­){ë‰1G&ïMrG5ÆB\vûÀÜQÞŸþô'ÇÎôŒÆ›JÞŒ¾?@¤ÌwÞ9¥ˆmÚ´ 礼Ú5y~'ÖPaµ>qbT¿úê«§ÍsÅýùg¤2ÆÄ‰U…%F;º ‹_Ê+‹Í‘Ũ¤àÉbM³cí”ËÍ´YªÂ&ÙÑOU= £’ˆü1W—놕”wËKñ`þzŸ}öqHì%'X‰ÊI-eb=u`Ì¥¨Uàµ×^›ä½âÝÊa…(fïÁèÑ£ÒiFŒDê`‘ò“IBÿb`ˆ!K°ÆkX z¿ÒÑ…~â7Òjýy¿ ]e‡• _¿~a¼¤qÝu×Å£¬êççž{.©…m¹ %ª@v  dÀÈ|o¹³céy#PN+DF‰$ËÁ­·ÞȈ8‘W »prDG°ÝvÛ%ú¯tÇR30pC‰)À@21Ý"ݦøeƒLè}ûöM1/3"9 #ôb“g<¬Æ<ßßû«¨gœÄª1¹Ñ@v÷.¿üòD?ñ0ÙžeQ ó«XYfóÚè÷´[_6=ÿüó_¥d ÌP®gŸ}v †•–EËO"PN–6&·sP¨ñØ‘5"†2ŠÕù ïÇ®™5t)GÄà“͉“–" Òzâ‰'t11*TÔ‰¨ ×Yg—íL4L3Ñüùó3½JqÇ¿Ü"ºÙKOXBQŒ9ëR”ÉÒ0rA ãDÃŽ;î¨ç±Õ:y6ö2éH" ‹¨Ë¸aO®i”ÒÛÖÑ6™·$¿W\qEx.a)óaiU8qºEL£Ùí<`ôͽÿ±ÎDöÍ‹©˜g1\Ðuk¬ÁŠÿdk¦`ï½÷.x^é3ÇÕ³gO]7—k—¬Äè#í‘$U Åò,8ï¼ó2·‘iz)?ÔYù’0™G4NW"=õÔS‰y¦]Òì&åC–£”$H^=íëŒ#jªd G çÚ¥Ô!sz²Wd5d¿îòXN ,mŒ|ƒ_E2ÐÅ«ÕXC…T!²˜—y#Ùø8 «|ŒdȉÉè9`>(N0å]wÝ5LG,CSæ¶Ä1=#ÓTCÏ?ÿ|e>ä7W’µe!c”´£í3â’:çšF1ý¡žÏh~Y¬]õ'Ÿ‡ç«Êl N¨ÞPY²Ë‡ì§Y;äRÚ³Ç,z‹Ë\‚›Ÿ#PQ Œ²ó¡3i/*-½ç9“]‰±jtr…b`4ÄG‡Ñ,ßQ.–bèù³íBAÇsDÚ‹¦çï‘Þ8p4JrìŠZ¡Éž{QçŒ÷ø• Æˆlú0’Ç`³DÇZQTcã©„¥0àYˆäŠAcóÎ÷ÁN+ì„Á(Qâ°?$uÙ¨7êl÷ ¿¡­ù¶Í•jcŒ“! s΀€¬=M3&Ëà5t®8FÎ]³•”èñ5£l„iqµ2²B10NŽŽ~Xñû8 ¬ØbÜÈŽàÓGâjŠß AƒÒâ–Õ-[Fí¶Ûn’I&‹<Ú{nr‚öÉ'Ÿ`¾ï‰Sª1¦¸å–[²2QTQHËìIYlŠJÉ´‰lKŠŸjiKv¢ÑöˆÚõå—_®ö"UtþÑôÈ.Aá÷/‹÷s²v¦PÉÀ䬩@&üÖAì…ˆ9w¦ýüÔSÿŠÑ¡Æ™–fÏHW± ÀÚ§—tEjn,ÅG½ÄV(’3ÈRòNz¨¹äÔßkH?Xâ9Z6æó8ɩݜ“¾£ƒCB,7‰±G˜'ŸoÌÙ™‡-4±Ç!sÓ`QTé’~­ÔK1|ÛõWë¹PE20̰ãªÔ]pæj¤B10Dìh'ÊÎíŒ\èèÙ¹¿˜D'Ž!Šo`ñ+ªÍ¦¨©ÄÒ.-î¤y¹Æ–QöÖL‹¦ïËQ ª?±| Ýü;T€r”Oš;ªîrSҦɴ‹B3W–TDÛÞˆ#Ê]tK¿F`é¿5•£~r*]9XƽÙ›/nò‹Y0®Ö3qˆ$›¤b^.z†æû'œp‚nÃÔXl0{æ¬*0—V“ ûñá'‰XîÀa¤lÿÕXºè¢‹tÓfžcîÙ³P$zZTlì‰r_pÁ‰åg£ZÌáãä·zŠ»—òY¡;YŒ’¤ 4¦ø…$ÌÊ9µÙ›øÊz/ÿhWC ÑȺδ°InižÊí‰År}ú¤Ì=79%0F»‰=÷˜ ã|!Ö´0ÑW b}Žì®¦ÏtÞì!艵g{íµ—lôµ’˜H9aÃñ (i®&åßG¯XÛe2ˆHŒu}X,–c—Hº%Öz †D¢O)e¤]z饺|~ïG>²“N:I-"Ù“‘¶QOÄ^˜Ñzg—b 4ê S+k*´'Ö¨æCËÀ|!Du“(ø÷M½rx#ë?N<ñDÝúÇC”‹Q‘¬‰Ãt½Øëºuë–Ò1ÑI 7‘„=‘vb˜·‹ÚÑ{Éze»!öôq0¯T¬IÖ̈êëGÙ½¿Áýs‰«ÖýÐXÄNÝ1ŸÈò #C ÜT$£SÃ0ãÎ1cåÔ\L…Y+Thb¡eÔÔ¦ÅÆ©þ”ÙRK`H'X‘ùNžr“‰ >«.½„A€ì–î&Mš¤Ïb‘âdLÝÕ¡€]»vM9½˜ƒe$´.`’ F%êF=|R¶`rbºÜ`˜¦¼”ã.Ü!CœXêb²k‚&Rˆa‡Hdaœ”M]à?_õ@Z$·4OæP1Ȧ¼.É ¦b2h1J„@F&;?8™ŒvXÝAvHÇS+4aÍ'R–‹¢(\ݱª¨ \Öø’,ےܲF”£™ËpcÇŽU¦‰¥]teÅ3Ï<ão›t•9Æ´ð2a›æf†€!`T:X»víôxûhDähЍSAî·Ùf=%X¶)J‰O ;vcZŠ{±`œQb—ïRæA,Ù¢Éë}’[š§0ÿ—s©Ô'fÞ˜­'1µ¢2/†€!`”ŒÇ© ùpô†ÌéúŽWç8Š)S¦%Ã0 ™oK‹†)‹]ÓÜ‹éÀz(™‡Rõ)ªº‹/¾ØÉ^lÅL2%n1jp²…“»á†Ôz8묳Rü4æA¶s²¯¡+D=ZFŒ\U¬õhLa-Œ!`Ô<͘Hô¥d±¨ìÀáÆçd«=_ˆŽ”³£ÄúI¹ž§äãlêõŒ3Îp²ÆÆÉV'MŠ †,¦æ:·Ô¤ˆJX¶YrrP¡ã¯¦ÎyÈá€NÖõéùJ¾²“.ÊöÏv5 C _ÐêÈ2'ë5ó Údÿ)˜X69Y÷å?üpÇ®̈ys˜ˆSᘯ)¥DŇVΚ5+Ñ»˜Å‡F‰*Ð1¾»CS²øÊ+¯¤0/â’ Sì×—8çÖ”´,¬!`¥@ …a¨!» ¨õ§£ÂŠüå¸'«ÿ‹–7Y¬ª'éÊÙIy§!;•«ä˜æÌIÄõJ²‹½žl ¾žì’ Fü{»†€!Pɤ00TˆXÛɆ°:WÂdT+VA0%‡1Êf¹ºr¢¬î9(G”ä”ô[láø%sXIǬ'ù­E·Ž;ê±ì P8æ^ÖÙ…slµX^+“!`Ô>) ,ªBd¤Îd?RM”Š¡BdÍóS<ð€“#6tîMεr²G šîÓáÊÑlØ}#8äC\ß¾},‚Öù0$n#CÀ0ªV."¦òrŽ•.âõ@2φåã˜1cæôÆÀ<2M»¢šmŒz6ž*Òìi§æd+(+ÅHF6›{³gCÀ0І@Z#‡:~tNì¾!GÌ-q±lUå{ì1'Û'y§ð*çQ9vž0ªÎY;&§äj¦Ø)dæÌ™M¶­œZN C Hc`²¼ªñd×ï´ücÎŽI=ç’`–t¬¿b®†3Ç8'ŠÑ=e1·q*d9ê%.vñÌË—™¥HË…>ËÇoWCÀ0â¤íÄÚsyHÎZrrRg5Ÿs>ê†]&0óf+)våÀÀ€þ%—\âäh]t[¨´,ž¦#4w†µjÜbµé)Y †€!`dF M‹ze-W)ãÞ½{‡Iqú¬ìœ®;b„ŽvSôìÙÓm¹å–îñÇóÃ>™Ô¡‘!`¥B M+UÂÙÒ¹ñÆÕÜ;›?{_zØf롇ri?xð`5Ç?ï¼óJŸKÑ0ê%°ºF¦Î ÏÀ×_]wYA…›¶ä³lÞì½!`EC QcLMtìÆÁ"cîùaXQ*bdo*©Ò Í<6 f·Û’…Òàn©†@ÓH”À0kRt &Îí*]uÕU¥HÆÒ† –bUÈÙdìƒÉ¢g#CÀ0*4†©|dƒú´|ÛbÕ4HªÞ Ð8áf ,ŽŠ=†@%!ÆÀ8—˨¾`éË¢„›‘!`•Œ@âX%gØòVx°&ôKXË5räÈ’lâ\ø’XŒ†€!PO¤hYËŸ>}ºÛqÇ‹¦k‰8Ó‹ ¡ÚõªcÌ䫨¥…_½ûÌŸ?_7¾®†º*të¹ìlnÞ¹sgÇiñ•@–;yòä²ä§nX%Tt1òpúé§»M7ÝT÷­,Fü•ç“O>©[‘Õ#Å“×ìÓÊiñÕ2Ø*dÝœzê©®W¯^º™@!ã­Æ¸L…Xµfy6 CÀpÆÀ¬†€!`T%ÆÀª²Ú,Ó†€!`ÆÀ¬ †€!`T%ÆÀª²Ú,Ó†€!`ÆÀ¬ †€!`T%fF_•Õö¿L³á2ë êq-ëa~üñG·ÔRKý:ºûôÓOÝ +¬PG%þ_Që¹ìõüÍÿ¯üçÎX{6 CÀ¨ L…XÕd™4 CÀˆ#` ,Žˆ=†€!`TÆÀª¢š,“†€!`qŒÅ±gCÀ0 ª@ÀXUT“eÒ0 C Ž€1°8"öl†€!P«Šj²L†€!`Ä0GÄž+_ýµâóX¬ r€§?x´XiX¼†@µ ` ¬Zj*–Ï_|Ñ­²Ê*)¿O>ù$æ«öïºë.·ñƧìñÇ×C=Ù•¢oß¾nÞ¼y)ïkåaΜ9nµÕVsœ€ë©ÖÛ {øðáníµ×Ö߉'žèüæ›o¾qýúõs+¯¼²[k­µÜK/½äa©™ëwÜ¡WvêÔÉ <ØÍ˜1#,ÛFm”òý_uÕUỺ¹‘ÑœQ"på•W fÏžþäc¯Â’ä–e鬂#FË/¿|°þú뇾üòË@WðÌ3Ï?üðC0tèÐàÐC ß×ÊÍÍ7ßtëÖ-Xh¡…‚wß}7,V­·ƒk¯½6Øa‡‚ï¿ÿ^Ûn»m€´÷Þ{#GŽ „¡÷Ýw_°âŠ+²µXˆMµßÈvYÁ²Ë.«õýÇ—\rI@ù!Ú}Ë–-ÃoŸ~à»ï¾«ö"ç“Àªt¨òꫯº-¶ØBT_`ܪ«®ê\pÁ*-MölOž<Ù1¿îºëR<#téÒE¥²Å[ÌwÜqŽQk-Ñ/¿üâÆç&L˜àZ·nR´ZoH^cÆŒqK,±„þÖ[o=÷ÔSO)>ø ;æ˜c\óæÍÝN;íädpãž|òÉ|ªùA˜–»óÎ;]ÇŽõ;ßl³ÍÜÓO?­E¢Þ»wïîÚ´iㄹ«* ­š‹Û¨¼klå4}útwñÅ»^½z©aÔ¨QåÏTs°×^{¹óÏ?ßµhÑ"%•?üÐÉÈ;tCÈf§túµB /¼°›2eŠ2êx™j½l¸á†õ$¶?~¼‰LëøçŸÖÜcûüóÏýcÕ_i×|ßžDòtÛm·>Rï3gÎtë®»®Û`ƒ \Ïž=H`ÞkÝ\UiU‹:É]~ùåîý÷ßwÓ¦Ms]t‘ûꫯª´4϶¨RÜâ‹/F€ÕêrǼ® ĈãÖ[ou»ì²K±×ˆ×¼í-@E ÖHÁ¦›nÈú—@,Ó±R«ˆ|;=öXŠ=éÉÇ,¹ä’A‡‚Þ½{¢J*v6Ê¿7«ö¨õvо}û@ºÚ”fõЬY³‚5ÖX#ÀXêS§Nõ°ÔÄuذa)åö8ÌŸ?_—°Œ@v êÔ`ß}÷­©%¹V È\呯¿þZM«1¥¯gBúb$Šj©©žÛêEaìõXíj™IÁãÖ¹õ†1°z©i+§!`5†@}Ûk¬2­8†€!`ÔÆÀê©¶­¬†€!`ÔÆÀj¨2­(†€!`ÔÆÀê©¶­¬†€!`ÔÆÀj¨2­(†€!`ÔÆÀê©¶­¬†€!`ÔÆÀj¨2­(†€!`ÔÆÀê©¶­¬†€!`ÔÆÀj¨2­(†€!`ÔÆÀê©¶­¬†€!`ÔÆÀj¨2­(†€!`ÔÆÀê©¶­¬†€!`ÔÆÀj¨2­(†€!`ÔÆÀê©¶­¬†€!`ÔÆÀj¨2­(†€!`ÔÆÀê©¶­¬†€!`ÔÆÀj¨2­(†€!`ÔÆÀê©¶­¬5‹À×_í~ùå—”òýöÛo.‚7ü|ñÅ)n<ÿñÇ)nÙ’ÒËÆÞ…FÀX¡µø*:ÝfÍš…¿…^ØuèÐÁ]xá…ËóðáÃÝ 'œÐ`|«­¶š{õÕWô“ÏËŸþÙí»ï¾Z.nΜ9ŽtÞ{ï=ï¤×I“&¹+®¸BïÏ9ç׺uk×µkWײeKwðÁ»Ÿ~úIß]ýõ!NQÌÖZk-}ÿú믻ÓN;MïíÏ(ÆÀÊ…¼¥[6¾üòK‡t2wî\wÛm·iGüØc$?Gy¤;üðÃŒëþûïw;wnÐO>//¸àe> -´»å–[\Ÿ>}ÜgŸ}–ÍäÉ“ÝÖ[oíyäwõÕW+#EƒÑÍœ9Ó~úéa˜-¶ØBq+ÿóŒ·W¯^ê?Î ÃÀvc”c`%Ù’¨,š7oî\pA·è¢‹º=z¸ÕW_];p:ç8Àí¸ãŽ®K—.nþüùî‰'žpë®»®J*{î¹§ûꫯœ{î¹®cÇŽú~ܸqê>~üxwÇwèýÍ7ßìVYe·ôÒK»~ýú¹o¿ýVÝar~ø¡Þ?ù䓎xñ³ûî»»Ï?ÿ\ÝaJH†[n¹¥¦=pà@÷ã?ê»èÌgìØ±n§vRgT„äe„ .ê—ûçŸ^ËüÝwß9pXvÙeÕKÛ¶mŒo¯½ö ƒ ySô·Àÿë2úöíëFŽú·C Ôü¯5–:eKÏ(3¨Þî»ï>÷òË/»wÞYLg½õÖs¨×`¸uÔQî7Þp-Z´Pw²ävÝu×9üóCuøÁ(‚© Š;ì°Ã*»wß}×Á0®¼òJ-ñ¬Y³ô=þa<Ûo¿½{å•WÔàÁƒÕŒì¬³ÎrÇwœ{饗”ñÜyçú.úÇ;¬—¾P‹N™2EpÔ÷HX¨a\;ì°ƒ[j©¥\ûöíÝ!‡âîºë.efÄåéßÿþ·æ™|ûß‹/¾è_»­¶ÚJ|è`7†@‰h^âô,9C ì 5!I|ÿý÷jø0jÔ(‡‚:l‘EQ5Ò*¶nݺ9¤èì³ÏvÛn»­;ÿüó•1í³Ï>nã7Öwwß}wÈDp üï¿ÿîž{î9•ÒxOÜQ‚i0ÿÄÜtÆg¨4„vÛm·P²"ÝÙ³g«{ôoÆŒn¥•VŠ:e¼÷êC<,±ÄîñÇw'NtH”±M›6îÁŒtÿIDATt~ž Uë=÷ܓߒK.é6Ø`uÃÿ7ß|£ªXæÐŒ R#` ¬Ôˆ[zeG鉉 ‰„{O0˜„„„„CG¥O>ùÄÁ8<ðÀÐy“M6 ï¹YÝtÓMnĈîè£V)k̘1®½H<ž`HÑpÌ‹-³Ì2Žø¡å—_Þ{u‹/¾¸ûõ×_Ãgóþûï»å–[Î?6x…!YBX'"­ 4HóæÍÓ|î¿ÿþZfü¬½öÚîá‡æ6#ÁøÉÃ:묓ѽ0Š…€©‹…¬Å[±l¸á†®gÏžÚAG™F½æ Æ{øj5˜\«V­ª@OÓ¦MS¦æŸ¹n³Í6îwÞqÌsÁ|†}­Ì Fè µ!–’«®ºª:yFêß']Ûµk—h¬÷‹4ˆ*“¹=¨ÿþ†ê Ž?þx÷Ö[o¥™Þ{?ñ+¦÷H‹äÁÈ(ÆÀʺ¥YÀ¼¦NªLˆ £òÛh£Ô"¯wïÞ:Æ\zH.Q# ,1ÑG ‡¡ Û¨ûÂ?F"^5È\Z§NtnÊûÉvEòan+a¼ãöÄØèÑ£un 7Ê€y=¡gœHi0¾øÏÇñÑG©tŠŠ‘!Pþ7Ü,Gê–¦!PÁ`Ì!Åú믯óXXã]sÍ5*¥a\1`ÀeRHjXäaÁ|„ú¹5óFÌaå%Þ¡b\sÍ5Ý +¬ V‘÷Þ{oÔKÖ{ØÛo¿­R“g´Ç{¨ä 42Ê€1°r niD€¹¸!C†¨ù|£m0*æöŽ8â]Ý G{i›+"¸µ!P X€†W*úøãSŒ@J•®¥cD0 ,ІÝ†€!`T &UMUYF CÀ0¢‹¢a÷†€!`Uƒ€1°ª©*˨!`†@c`Q4ìÞ0 C j0V5Ue5 CÀˆ"` ,ІÝ†€!`T ÆÀª¦ª,£†€!`QŒEѰ{CÀ0 ªAÀXÕT•eÔ0 C Š€1°(vo†€!P5«šª²Œ†€!`D0EÃî CÀ0ªc`USU–QCÀ0 (ÆÀ¢hؽ!`†@Õ ðÿH¨%Îq³cIEND®B`‚rotl/vignettes/data_mashups.Rmd0000644000176200001440000004603315132142351016362 0ustar liggesusers--- title: "Connecting data to Open Tree trees" author: "David Winter" date: "2026-01-15" output: rmarkdown::html_vignette: css: vignette.css vignette: > %\VignetteIndexEntry{Connecting data to Open Tree trees} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} \usepackage[utf8]{inputenc} --- ## Combining data from OToL and other sources. One of the major goals of `rotl` is to help users combine data from other sources with the phylogenetic trees in the Open Tree database. This examples document describes some of the ways in which a user might connect data to trees from Open Tree. ## Get Open Tree IDs to match your data. Let's say you have a dataset where each row represents a measurement taken from one species, and your goal is to put these measurements in some phylogenetic context. Here's a small example: the best estimate of the mutation rate for a set of unicellular Eukaryotes along with some other property of those species which might explain the mutation rate: ``` r csv_path <- system.file("extdata", "protist_mutation_rates.csv", package = "rotl") mu <- read.csv(csv_path, stringsAsFactors = FALSE) mu ``` ``` ## species mu pop.size genome.size ## 1 Tetrahymena thermophila 7.61e-12 1.12e+08 1.04e+08 ## 2 Paramecium tetraurelia 1.94e-11 1.24e+08 7.20e+07 ## 3 Chlamydomonas reinhardtii 2.08e-10 1.00e+08 1.12e+08 ## 4 Dictyostelium discoideum 2.90e-11 7.40e+06 3.40e+07 ## 5 Saccharomyces cerevisiae 3.30e-10 1.00e+08 1.25e+08 ## 6 Saccharomyces pombe 2.00e-10 1.00e+07 1.25e+08 ``` If we want to get a tree for these species we need to start by finding the unique ID for each of these species in the Open Tree database. We can use the Taxonomic Name Resolution Service (`tnrs`) functions to do this. Before we do that we should see if any of the taxonomic contexts, which can be used to narrow a search and avoid conflicts between different codes, apply to our group of species: ``` r library(rotl) tnrs_contexts() ``` ``` ## Possible contexts: ## Animals ## Birds, Tetrapods, Mammals, Amphibians, Vertebrates ## Arthropods, Molluscs, Nematodes, Platyhelminthes, Annelids ## Cnidarians, Arachnids, Insects ## Fungi ## Basidiomycetes, Ascomycetes ## All life ## Bacteria ## SAR group, Archaea, Excavata, Amoebozoa, Centrohelida ## Haptophyta, Apusozoa, Diatoms, Ciliates, Forams ## Land plants ## Hornworts, Mosses, Liverworts, Vascular plants, Club mosses ## Ferns, Seed plants, Flowering plants, Monocots, Eudicots ## Rosids, Asterids, Asterales, Asteraceae, Aster ## Symphyotrichum, Campanulaceae, Lobelia ``` Hmm, none of those groups contain all of our species. In this case we can search using the `All life` context and the function `tnrs_match_names`: ``` r taxon_search <- tnrs_match_names(names = mu$species, context_name = "All life") knitr::kable(taxon_search) ``` |search_string |unique_name |approximate_match | score| ott_id|is_synonym |flags | number_matches| |:-------------------------|:-------------------------|:-----------------|-----:|------:|:----------|:-----|--------------:| |tetrahymena thermophila |Tetrahymena thermophila |FALSE | 1| 180195|FALSE | | 1| |paramecium tetraurelia |Paramecium tetraurelia |FALSE | 1| 568130|FALSE | | 1| |chlamydomonas reinhardtii |Chlamydomonas reinhardtii |FALSE | 1| 33153|FALSE | | 1| |dictyostelium discoideum |Dictyostelium discoideum |FALSE | 1| 160850|FALSE | | 1| |saccharomyces cerevisiae |Saccharomyces cerevisiae |FALSE | 1| 356221|FALSE | | 1| |saccharomyces pombe |Schizosaccharomyces pombe |FALSE | 1| 990004|TRUE | | 1| Good, all of our species are known to Open Tree. Note, though, that one of the names is a synonym. _Saccharomyces pombe_ is older name for what is now called _Schizosaccharomyces pombe_. As the name suggests, the Taxonomic Name Resolution Service is designed to deal with these problems (and similar ones like misspellings), but it is always a good idea to check the results of `tnrs_match_names` closely to ensure the results are what you expect. In this case we have a good ID for each of our species so we can move on. Before we do that, let's ensure we can match up our original data to the Open Tree names and IDs by adding them to our `data.frame`: ``` r mu$ott_name <- unique_name(taxon_search) mu$ott_id <- taxon_search$ott_id ``` ## Find a tree with your taxa Now let's find a tree. There are two possible options here: we can search for published studies that include our taxa or we can use the 'synthetic tree' from Open Tree. We can try both approaches. ### Published trees Before we can search for published studies or trees, we should check out the list of properties we can use to perform such searches: ``` r studies_properties() ``` ``` ## $tree_properties ## [1] "ot:specifiedRoot" "ot:unrootedTree" "ot:nodeLabelTimeUnit" "xsi:type" "ot:MRCAName" "ot:nodeLabelDescription" "ot:nearestTaxonMRCAOttId" ## [8] "ot:reasonsToExcludeFromSynthesis" "ot:curatedType" "ot:nearestTaxonMRCAName" "ot:studyId" "ot:nodeLabelMode" "rootedge" "nodeById" ## [15] "tb:type.tree" "ot:branchLengthDescription" "ot:messages" "ot:rootNodeId" "ot:inGroupClade" "ot:ottId" "ot:branchLengthMode" ## [22] "ot:MRCAOttId" "ot:ottTaxonName" "tb:quality.tree" "tb:kind.tree" "ot:outGroupEdge" "ntips" "edgeBySourceId" ## [29] "label" "meta" "tb:ntax.tree" "ot:tag" "ot:branchLengthTimeUnit" ## ## $study_properties ## [1] "tb:identifier.study.tb1" "id" "ot:taxonLinkPrefixes" "ot:studyYear" "prism:publicationName" "dc:title" "prism:creationDate" "xmlns" ## [9] "skos:changeNote" "skos:historyNote" "ot:notIntendedForSynthesis" "ot:otusElementOrder" "dc:date" "xhtml:license" "prism:startingPage" "prism:publicationDate" ## [17] "ot:focalCladeOTTTaxonName" "prism:section" "prism:pageRange" "ot:messages" "ot:studyPublicationReference" "ot:curatorName" "ot:dataDeposit" "prism:number" ## [25] "ot:agents" "dc:publisher" "treesById" "dcterms:bibliographicCitation" "ot:treesElementOrder" "prism:modificationDate" "tb:identifier.study" "about" ## [33] "ntrees" "nexmljson" "ot:comment" "dc:contributor" "dc:creator" "prism:volume" "tb:title.study" "treebaseId" ## [41] "prism:endingPage" "generator" "version" "ot:studyId" "ot:candidateTreeForSynthesis" "otusById" "prism:doi" "dc:subject" ## [49] "ot:studyPublication" "ot:focalClade" "ot:annotationEvents" "ot:tag" "nexml2json" ``` We have `ottIds` for our taxa, so let's use those IDs to search for trees that contain them. Starting with our first species _Tetrahymena thermophila_ we can use `studies_find_trees` to do this search. ``` r studies_find_trees(property = "ot:ottId", value = as.character(ott_id(taxon_search)[1])) ``` ``` ## study_ids n_trees tree_ids candidate study_year title study_doi ## 1 ot_1587 1 tree1 2015 'Phylogenomic analyses reveal subclass Scuticociliatia as the sister group of subclass Hymenostomatia within class Oligohymenophorea' http://dx.doi.org/10.1016/j.ympev.2015.05.007 ## 2 ot_1589 1 tree1 2015 'Phylogenomic analyses reveal subclass Scuticociliatia as the sister group of subclass Hymenostomatia within class Oligohymenophorea' http://dx.doi.org/10.1016/j.ympev.2015.05.007 ## 3 ot_2037 4 tree10, tree11, tree12, tree13 2018 http://dx.doi.org/10.1038/s41586-018-0708-8 ## 4 ot_409 2 tree1, tree2 tree2 2015 Tree of life reveals clock-like speciation and diversification http://dx.doi.org/10.1093/molbev/msv037 ## 5 ot_564 1 Tr85317 Tr85317 2015 'The alveolate translation initiation factor 4E family reveals a custom toolkit for translational control in core dinoflagellates' http://dx.doi.org/10.1186/s12862-015-0301-9 ## 6 ot_579 1 Tr60046 2013 'Convergent evolution of heat-inducibility during subfunctionalization of the Hsp70 gene family' http://dx.doi.org/10.1186/1471-2148-13-49 ## 7 ot_700 1 tree1 tree1 2016 'A new view of the tree of life' http://dx.doi.org/10.1038/nmicrobiol.2016.48 ## 8 ot_73 1 tree1 tree1 2013 Deep relationships of Rhizaria revealed by phylogenomics: A farewell to Haeckel’s Radiolaria http://dx.doi.org/10.1016/j.ympev.2012.12.011 ## 9 ot_766 1 Tr85440 2015 'Bacterial proteins pinpoint a single eukaryotic root' http://dx.doi.org/10.1073/pnas.1420657112 ## 10 ot_767 1 tree1 tree1 2016 'Untangling the early diversification of eukaryotes: a phylogenomic study of the evolutionary origins of Centrohelida http://dx.doi.org/10.1098/rspb.2015.2802 ## 11 ot_87 1 Tr64119 Tr64119 2014 'Dinoflagellate phylogeny revisited: Using ribosomal proteins to resolve deep branching dinoflagellate clades' http://dx.doi.org/10.1016/j.ympev.2013.10.007 ## n_matched_trees match_tree_ids ## 1 1 tree1 ## 2 1 tree1 ## 3 3 tree10, tree13, tree11 ## 4 1 tree2 ## 5 1 Tr85317 ## 6 1 Tr60046 ## 7 1 tree1 ## 8 1 tree1 ## 9 1 Tr85440 ## 10 1 tree1 ## 11 1 Tr64119 ## [ reached 'max' / getOption("max.print") -- omitted 16 rows ] ``` Well... that's not very promising. We can repeat that process for all of the IDs to see if the other species are better represented. ``` r hits <- lapply(mu$ott_id, studies_find_trees, property = "ot:ottId", detailed = FALSE) sapply(hits, function(x) sum(x[["n_matched_trees"]])) ``` ``` ## [1] 51 51 128 71 18 89 ``` OK, most of our species are not in any of the published trees available. You can help fix this sort of problem by [making sure you submit your published trees to Open Tree](https://tree.opentreeoflife.org/curator). ### A part of the synthesis tree Thankfully, we can still use the complete Tree of Life made from the combined results of all of the published trees and taxonomies that go into Open Tree. The function `tol_induced_subtree` will fetch a tree relating a set of IDs. Using the default arguments you can get a tree object into your R session: ``` r ott_in_tree <- ott_id(taxon_search)[is_in_tree(ott_id(taxon_search))] tr <- tol_induced_subtree(ott_ids = ott_in_tree) ``` ``` ## Warning in collapse_singles(tr, show_progress): Dropping singleton nodes with labels: mrcaott2ott276, mrcaott2ott142555, mrcaott2ott1551, mrcaott2ott7623, Chloroplastida ott361838, Chlorophyta ott979501, mrcaott185ott42071, mrcaott185ott1426, mrcaott1426ott1544, ## mrcaott1544ott8659, mrcaott1544ott15345, mrcaott1544ott9282, mrcaott9389ott818260, mrcaott9389ott23557, mrcaott23557ott527099, mrcaott148ott902, SAR ott5246039, Alveolata ott266751, Ciliophora (phylum in subkingdom SAR) ott302424, Intramacronucleata ott340382, ## mrcaott1546ott1671, Conthreep ott5248773, mrcaott1671ott16129, Peniculia ott1002116, Paramecium (genus in subkingdom SAR) ott568126, mrcaott11752ott13570, Hymenostomatia ott5257367, Tetrahymena (genus in subkingdom SAR) ott47284, mrcaott295406ott523463, ## mrcaott295406ott523462, mrcaott3973ott4738988, Amoebozoa ott1064655, mrcaott3973ott15653, mrcaott3973ott26103, mrcaott26103ott273110, mrcaott26103ott229626, Dictyostelia ott835575, mrcaott26103ott59686, Dictyosteliales ott4008839, Dictyosteliaceae ott4008841, ## Dictyostelium ott999665, mrcaott42ott240665, Opisthokonta ott332573, Nucletmycea ott5246132, Fungi ott352914, mrcaott109ott3465, mrcaott109ott67172, mrcaott109ott1423, mrcaott109ott9352, h2007-2 ott5576447, h2007-1 ott5584405, Dikarya ott656316, ## mrcaott235ott3445, saccharomyceta ott1098854, Saccharomycotina ott971714, Saccharomycetes (class in h2007-2) ott989999, Saccharomycetales ott4085960, Saccharomycetaceae ott989994, Saccharomyces ott908546, Schizosaccharomycetes ott921286, Schizosaccharomycetidae ## ott5670481, Schizosaccharomycetales ott508517, Schizosaccharomycetaceae ott990009, Schizosaccharomyces ott990008 ``` ``` r plot(tr) ``` ![plot of chunk subtree](fig-vignettes-subtree-1.png) ### Connect your data to the tips of your tree Now we have a tree for of our species, how can we use the tree and the data together? The package `phylobase` provide an object class called `phylo4d`, which is designed to represent a phylogeny and data associated with its tips. In order to get our tree and data into one of these objects we have to make sure the labels in the tree and in our data match exactly. That's not quite the case at the moment (tree labels have underscores and IDs appended): ``` r mu$ott_name[1] ``` ``` ## $`Tetrahymena thermophila` ## [1] "Tetrahymena thermophila" ``` ``` r tr$tip.label[4] ``` ``` ## [1] "Dictyostelium_discoideum_ott160850" ``` `rotl` provides a convenience function `strip_ott_ids` to deal with these. ``` r tr$tip.label <- strip_ott_ids(tr$tip.label, remove_underscores = TRUE) tr$tip.label %in% mu$ott_name ``` ``` ## [1] TRUE TRUE TRUE TRUE TRUE TRUE ``` Ok, now the tips are together we can make a new dataset. The `phylo4d()` functions matches tip labels to the row names of a `data.frame`, so let's make a new dataset that contains just the relevant data and has row names to match the tree ``` r library(phylobase) ``` ``` ## Error in `library()`: ## ! there is no package called 'phylobase' ``` ``` r mu_numeric <- mu[, c("mu", "pop.size", "genome.size")] rownames(mu_numeric) <- mu$ott_name tree_data <- phylo4d(tr, mu_numeric) ``` ``` ## Error in `phylo4d()`: ## ! could not find function "phylo4d" ``` And now we can plot the data and the tree together ``` r plot(tree_data) ``` ``` ## Error: ## ! object 'tree_data' not found ``` ## Find external data associated with studies, trees and taxa from Open Tree In the above example we looked for a tree that related species in another dataset. Now we will go the other way, and try to find data associated with Open Tree records in other databases. ### Get external data from a study Let's imagine you were interested in extending or reproducing the results of a published study. If that study is included in Open Tree you can find it via `studies_find_studies` or `studies_find_trees` and retrieve the published trees with `get_study`. `rotl` will also help you find external. The function `study_external_IDs` retrieves the DOI for a given study, and uses that to gather some more data: ``` r extra_data <- try(study_external_IDs("pg_1980"), silent = TRUE) ``` ``` ## Warning in check_xml_errors(x): Invalid db name specified: popset ``` ``` r if (!inherits(extra_data, "try-error")) { extra_data } ``` Here the returned object contains an `external_data_url` (in this case a link to the study in Treebase), a pubmed ID for the paper and a vector IDs for the NCBI's nucleotide database. The packages `treebase` and `rentrez` provide functions to make use of these IDs within R. As an example, let's use `rentrez` to download the first two DNA seqences and print them. ``` r library(rentrez) seqs <- try(entrez_fetch(db = "nucleotide", id = extra_data$nucleotide_ids[1:2], rettype = "fasta"), silent = TRUE) if (inherits(seqs, "try-error")) { cat("NCBI temporarily down.") } else { cat(seqs) } ``` ``` ## NCBI temporarily down. ``` You could further process these sequences in R with the function `read.dna` from `ape` or save them to disk by specifying a file name with `cat`. ### Find a OTT taxon in another taxonomic database It is also possible map an Open Tree taxon to a record in another taxonomic database. For instance, if we wanted to search for data about one of the tips of the sub-tree we fetched in the example above we could do so using `taxon_external_IDs`: ``` r Tt_ids <- taxon_external_IDs(mu$ott_id[2]) Tt_ids ``` ``` ## source id ## 1 silva AY102613 ## 2 ncbi 5888 ## 3 gbif 7415807 ``` A user could then use `rgbif` to find locality records using the gbif ID or `rentrez` to get genetic or bibliometric data about from the NCBI's databases. ## What next The demonstration gets you to the point of visualizing your data in a phylogenetic context. But there's a lot more you do with this sort of data in R. For instance, you could use packages like `ape`, `caper`, `phytools` and `mcmcGLMM` to perform phylogenetic comparative analyses of your data. You could gather more data on your species using packages that connect to trait databases like `rfishbase`, `AntWeb` or `rnpn` which provides data from the US National Phenology Network. You could also use `rentrez` to find genetic data for each of your species, and use that data to generate branch lengths for the phylogeny. rotl/vignettes/fig-vignettes-unnamed-chunk-16-1.png0000644000176200001440000003710415132142375021650 0ustar liggesusers‰PNG  IHDRø XEa=iCCPkCGColorSpaceGenericRGB8U]hU>›¹³+$΃Ԧ¦’þ5”´lRÑ„Úèþe³mÜ,“l´AÉìÝi&3ãü¤i)>AÁ¨à“àÿ[Á'!j«í‹-¢´P¢ƒ(øÐúG¡Ò ë¹3³»“¸k½ËÜùæœï~çÞsîÞ ¸,[–Þ%,®-åÓâ³ÇæÄÄ:tÁ}Ð }Ð-+Ž•*•&ã¿Úíï ÆÞ×ö·÷ÿgë®PGˆÝ…ج8Ê"âeþŲ]€AûÈ ×bø Ä;lœ âõWžð²Ï™‘2ˆ_E,(ªŒþÄÛˆç#öZsðÛŽ<5¨­)"ËEÉ6«šN#Ó½ƒû¶EÝkÄÛƒO³0}߸ö—*r–ᇟUäÜtˆ¯.i³Åÿe¹i ñ#]»¼…r ñ>ÄcU{¼èt©ª7ÑÀ+§Ô™g߃xuÁ<ÊÆîDüµ1_œ u~Rœ æàâ*-°z÷#°Mi*ˆËWh6Çòˆø¸æf}î-gi:×Ð9¥fŠA,î‹ãòV§>ÄW©ž—Bý_-·Æ%=†^œ tÈ0uüõúvW™â’9 Œ%/VµñBÈWµ'¤_¶tâÜÈMÛ“ÊŸ¿ŸåP““í\>ĘÉ@Á„yì0`D i|[`£§ èh¡è¥h¡øÕàìßÂ)ùþ·TjþÈëèÑ0B¦ÿ#ðЪÂïhU#¼ ~yh«uÐ fp#Ô1I/I’ƒø"“ä0!£ ’'ÉSdŒdÑ:J5Ç–"sdó¹ÑÔy#RŸ7‹¼‹èwAÆþgd˜à´ÏÅJŸ7ØÏØÏkÊ•×n^:}nW‹»FVŸ»Ösét$gj-tÈÚÔrÏÿÂ_ç×°_ç7Z þ~ëÛV·5ë4ÌV }ºo[ÄGó=Nd>¥-Ula³£¢Y5VúË}¹x»g[üä÷É?’kÉ÷’&ãÞä>áÎsŸrŸq߀È]à.r_r_qsŸGjÔyï4k± æi—QÜŸBZØ-<(d…=ÂÃÂdKO膄 a/zv7«]»ǰod«}¬€©sìn¬³Öá?TF–'|¦ãï3Nnã„#I?"…m»z„íõ¦v~K=Ú¯Æsñl<b|_|4>?Âpƒß‹¾QìñÔré²ËâŒi´µšêŠÃÉäãb ¯2* åÀ (ëºè»Ѧµ—hå°{28ÂoIþýÛy¥esŸ8ü';÷Z¶9à¬ÐûhË6€gã½ï¬>¦xöRx'Äbß8ÕƒÃÁWOÏ«ëõ[xn%ÞØ|½^ÿûýz}óÔ߸ ÿÿ%x ÅcÖË8eXIfMM*‡i ø  ½Ë]r9­IDATxí¸EÓ¶+!8!xp‚»»Kpww·À‹»»kÐww—àÜ-8Á‚÷þ멟™wÏIödÃ;É™Ùs÷uÝ‘žšî»7ûtUõl:%/F @ ©tnªÞÐ@€‚Ï€ Єø&Tº@@àù @€šß„ƒJ— @<Ÿ@€@@à›pPé @ç3@hB|*]‚  ð| @MHoÂA¥K€ žÏ @  ðM8¨t € €Àó€ 4!¾ •.A€x>€ &$€À7á Ò%@€Ïg€ Єø&Tº@@àù @€šß„ƒJ— @<Ÿ@€@@à›pPé @ç3@hB|*]‚  ð| @MHoÂA¥K€ žÏ @  ðM8¨t € €Àó€ 4!¾ •.A€x>€ &$€À7á Ò%@€Ïg€ Єø&Tº@@àù @€šß„ƒJ— @<Ÿ@€@@à›pPé @ç3@hB|*]‚  ð| @MHoÂA¥K€ žÏ @  ðM8¨t € €Àó€ 4!¾ •.A€x>€ &$€À7á Ò%@€Ïg€ Єø&Tº@@àù @€šß„ƒJ— @<Ÿ@€@@à›pPé @ç3@hB|*]‚  ð| @MHoÂA¥Kå&ðÃ?ØSLa«®ºj»7ôÏ?ÿ´qÇ×¾ýöÛ6Û2pà@;î¸ãÚ¬3¸“SM5•½û;Uر=öØÃN8á„Âì5b¨5ÿû¿ÿ³÷ßß¾üòK›~úéù»á†¬®ÛxãmÚi§µW\ÑÞyçüv묳N‹ë.¹ä’üœ6dî¹ç¶¿þú+?^ÏÞ†nØÂ–Ú´Í6Ûä×±Ñ1 ðcœée‰H(—\rI{ñÅÛ½U¯¾úª9æ˜6öØc·Ù–Ë/¿Ü^ýõ6ë´>ùÉ'Ÿ˜hê©§n}ªÐý'Ÿ|Òæšk®BmÉX-/¾øÂvß}w›|òɃã#=øàƒé©§ž ¡Õñ·ß~;M<ñÄqL‰ðÁ¬SIbÓ«W¯ôÛo¿Å„@غôéÓ'uîÜ9{î¹iÀ€1Q°«ì°Ãéè£NöIÀ‰'ž˜4i`Î8ãŒQçÇLÓM7]ºë®»Ò¯¿þâ/V‘=Mô¾Ûn»¥i¦™&rÊ)!Rj£Ä÷šk® ‘“ø>ðÀIöFe”ô÷߇ MVZi¥Ø®Çàƒ>ˆÉÍ}÷Ýâ(Ñ~ùå—ã>ê›hÒ³ï¾û¦í·ß>lIÜ5Q‘À>÷Üs1AQßT4Y0DsÎ9'Ž×¾Ô»¾–‡¶÷Úk¯¸gf[6$¬³Ì2Kºí¶Ûr“îA'•Ç„Cµ­¶Ú*?§I‘&Qšøˆ™lfEc£"¡¾à‚ ²Ã©-{Y%Á&›l’íòÞÁ ðlÀénû‡*OV¢¢¢/lyn*†M4L¯½öZìËË•¨H<å]«¨ÞÎ;}}/°ÀÉóÜé÷ßOÖá夓NЉCvð¼óÎKë®»nìÎ7ß|Iž±®•ªüòË/éÎ;ïŒ(B¶ï¡áÜË•Ÿ|òÉQwï½÷Nûï¿l/±ÄéC‰m½H´k÷g›m¶ôøãÇy ¹û˜QÛ$“Lb}ô‘tÐAqÎÖÜÃëd÷˜cމãµ/.žæâ–r6r¹.®¦ûhá–‹{ì±öè£FYy^Þ¸F÷÷P¶©í*Z°¥ÜýW_}eW^yeØÐq­)ð(6£ø„ÁÇ;¾ãŒ5=퀔ƒ-rí…&úYVŽü_ÑÔDD)…±ëM&þ•a.‚!@ˆ~$Íw€}ó)=‚ 0$ÿ]¦9¤šœ‡ @ 2øÊ  … 4Noœ5!@•!€ÀWf¨h( @ q|㬨 @¨ ¾2CEC!@@àgEM@€@e ð•* @hœß8+jB€*C¯ÌPÑP@€@ãøÆYQ€ P|e†Š†B€'€À7Ίš€ Ê@à+3T4€ Ð8¾qVÔ„ T†_™¡¢¡€ Æ ð³¢& @ 2øÊ  … 4Noœ5!@•!€ÀWf¨h( @ q|㬨 @¨ ¾2CEC!@@àgEM@€@e ð•* @hœß8+jB€*C¯ÌPÑP@€@ãøÆYQ€ P|e†Š†B€'Ð¥ñª»æK,a³Î:k%!üðÃöÞ{ïU²í4€þ¾An?ýô“m·Ýv Ö.WµÏ>ûÌÎ;ï¼r5ŠÖ@€À0%€À7ˆwôÑG·Yf™¥ÁÚåª6æ˜cÚh£V®FÑ@¦ÈÁS¼‡ ´¾}¸sW@€À0%€ÀS¼‡ ´¾}¸sWØ7ß|c)%HHàÏ?ÿ,Ц Pm|µÇÖWŒÀ?þh;M;í´6×\sÙØcm»ï¾»5"L7Þx£-½ôÒÑãõ×_ßÎ=÷ÜvëýðnËwß}gGydÞß³Ï>ÛÞ}÷Ý|_ÚŸm¶ÙZ°£É'Ÿ<ÿ[sÍ5ók;ì°ƒ9眳ËO>ù$¯Ÿ]ûùçŸÇujÇ:ë¬c“N:©-µÔRööÛoÑ^^  güpÎí:.Ú2Ë,žxâ ûàƒìµ×^³»ï¾ÛŽ>úè!‚yî¹çlî¹çŽzµÛC¼pT¨½íö0¸U˜¼âŠ+¬_¿~±ýÅ_Ø>ûìc=zôˆý/¿üÒŽ:ê¨`£'FºtùïÃA×_½rÊ)öÌ3ÏÄßE]×Hø5?þ¸Ýwß}vøá‡Û;ï¼çî¼óÎïìšgŸ}Ö&œpÂ8·ÒJ+Ù<óÌc~øaýYg5D{Q´¾ sËŽIàÐC ¡èÝ»·?þøa’I&±«¯¾:9‡• ©& }ôQüðÒM7Ýd»ì²K^çâ‹/¶ƒ:(öŸ~úi[n¹åBwÞygSô uÑýöÞ{oS;zöìi·Ýv›í´ÓNQMñ†nhÝ»w7 ÛÃ?œ_>,Ú¢(Æž{îiSL1…-¼ðÂvË-·ÄýÄK}’ðžp 6ÿüóÛo¿ýfo¼qœW{%ì›m¶Y>Ò õ÷¥—^² &˜À$ÒbÞ­[·¸fÓM7µk¯½ÖFuÔˆ¢têÔÉä«ÜqÇ¶à‚ ZŸ>}l¤‘FŠëu\¬GaÛh£ìã?¶vØÁN=õT²¶ìE^ Ð<Hi€Àâ‹/Þ@­rVqo#ùP9×Zå”\TÚì± zZ~ù哇‰Ó[o½•&šh¢ôÊ+¯Ä5ã7^r/3=øàƒÉÃÊqÌÃûÉÅ/·¹Å[$Ø×gÖE*ù„ ­¸âŠéœsÎÉëeûï¿Zk­µÒ·ß~›üÇ’ÿÞC:à€Ò_ý•\dÓ‰'ž˜¾ÿþût饗¦gœ1», ‹¶ì±ÇÑNµÅ'qÝÛ…:ù„'Ýu×]±½×^{¥í·ß>Ú¥©­*Ë.»lºà‚ b[/.ÈiÄGŒ~L5ÕTiúé§O>1ÈÏkãšk®‰{®²Ê*aGçÅÀS(iÑEMcŒ1F0T]ý’ ÛǸlµÕV:Ü¢´¶×â$;δȇҾHT©K@ÂáÞ`òœmÔéÛ·oÒg*û»ì²Ëâ¸DÝ߅ظ‚òÈ#$MÒÆk¬äwr/6m½õÖQß½îtà 7ä÷•ð»§ûd‰á/¿ü’Ü㌠C^Ñ7$œ3qÇaÙöPtºîºëÒï¿ÿ"«ºÞ½ç8§ýaÑ»§®]»&ÏuëQV[mµäѸ¿„Úr9ޝ±ÆÉCíÿ¿RÍ«{èéÅ_Ìø:˜´è€&³Ï>{L² :æyôÔ¹sç\ÄÕ7Mšü—+£š‡îÓ–[nÛš yD$Ú¡óbåi–Ì\Ü£µ½ü$hÿMVµGø€{B ÷Üs)L«ÐmU˪«®j.šV.Öb;•^½z™{бíbÿ¬°x¹àG¸^ùb-ÊS(YáqŸD}4›cŽ9bû×_µ×_Ý\ÈbÿòË/°õUW]egžy¦¹`Æñìå©§žŠ|²{ãqH¶ÿøã°çž³{ì±öè£F›šVÚ@E÷/º- ¥«JdEás…âµNAcŸ1RŸ>øà¬Z¼kaœþÏ…™gž9?î|ÛEÜÜ#·^xÁ[`§…w»í¶›i’“Ou˜§*BÔGe”Èó뜮ÓReß}÷µõÖ[Ï´²^EL² ”&@Ù"GsïÝ<…Ò¦=Õ£@ Ý´CÔ ’·T(µª¥ê9xº¤PiÕ‹¯ü޼®{¤Ñ÷¶“òÎ ½«(L¿òÊ+Ƕ{Ò‘SVÈWEyy…«•OW¨ß½õ¡ûÄ!Î+¬ï^uòÇÀbß«å¹x¥üq¼¤mQˆÞ'¾ÿúë¯Ó ,Yd‘¨â‡tÉ%—Ä¶Ò .öÉM‹ýaÑŸ4Dˆ> {Ä!¹‡aïÿüç?ù:_õi‹Ú~h[Ÿ_ô–öIaäÏ}%|»ùæ›S=‚Ÿ/$Lþ¸aG1󅊱¯<»/:Œm¥.”o÷§b…VH§vZlûd,ùÄ*Òmًʼ@ àÁ·ÛÔŠw4Z¯•× o+,î¢j‹-¶˜éQ.•ÕW_Ýäm»ÐÆêm_Ðeýû÷sòšuîùçŸïU^µN+m ¶^xá…‘N˜a†L÷TmQô4€ú¬ßÐêuqQØ[Q ­žWûç›o>ûꫯ"êqå•WF{ô"^+ý³¢”‚‰[{íµãÉE´ _«íåÅk…þ¼óΫáµb?{Æ^ÛeO hUýO"È®žhð ™ù‚ÃXq¯G÷ hË^ÖÞ!Ð:ibÑ7®Ú=•‹S¾­ŠETé1#÷ȪØ|óUãñ¼röøW%;QÓh‰Í€Bx$`­‹~áNáñF‹„Hâ<¸¢s }g¡ëÚ:÷Þ{o¤>$Þ* {Ÿ~úéùéø"´xÔ,{´¬öÚzÛÿ¶-™=­SÐ_m¸^çôÈ›&!â¥ubX›^È®oý®ÇÖ× µ.JoèO¢ßºhò5î¸ã¶>ûÙSȾ¶´e¯¶Û^ðà‡iîHl3O{pP†FÜu}=qÒ9å—•ãÖ³îú±哵p,+ò‚‡F܇t¿¶Ú™ÝSž»þZ—ZÁ÷õ¦¿FŠ&ƒw]«ˆD•hm«ž¸«^½ñiË^kûìC`x@à‡eîÐÊhÅý«¯¾?n£Å‘¨S æ €À7Ç8Ò ü+úéÜìçsÿ•.‚JK`Ð`i›Jà @h”ß()êA€*D¯Ð`ÑT@€@£øFIQ€ P!|…‹¦B€%€À7JŠz€ @à+4X4€ Ð(¾QRÔƒ Tˆ_¡Á¢©€ F ð’¢ @ Bø M… 4Jo”õ @"€ÀWh°h* @ Q|£¤¨@¨¾BƒES!@@à%E=@€@…t©P[iê¿$0pà@ëÛ·¯õêÕë_ZhßËú÷ïo]»vmßFpw@#€ÀWlÀþMs§žzjëÝ»·uïÞýß\Þî×hrÒ¯_¿vo € P%|•Fë_¶u´ÑF³ž={þË«Ûÿ²اŸ~Úþ ¡€*D€|…‹¦B€%€À7JŠz€ @à+4X4€ Ð(¾QRÔƒ Tˆ_¡Á¢©€ F ð’¢ @ Bø M… 4Jo”õ @"€ÀWh°h* @ Q|£¤¨@¨¾BƒES!@@à%E=@€@… ð,š @h”ß()êA€*D¯Ð`ÑT@€@£øFIQ€ P!|…‹¦V›@ÿþý­S§NvÌ1Ç Ò‘wÞÙFaûé§Ÿ9W{`ýõ×·sÏ=·öÐ0ÙN)Y·nÝìÓO?&ö3£7Þx£-½ôÒ±;¼ú–Ý»ˆ÷ï¾ûÎŽ<òÈÜÔÙgŸmï¾ûn¾Ÿmì¿ÿþ¶ÖZke»ùû?þhsÎ9§]sÍ5ù±§žzÊæšk.›l²Él»í¶3EëÒÚÞ=÷Üc3Ì0ƒÍ4ÓL¶É&›äãöÇØ~ûíg³Í6›M3Í4vÊ)§´6Å~@à›xpéZ¹<÷Üs6Î8ãØ[o½Õ¢ao¿ý¶Ýzë­ñ=ú裷8×zG6æž{îÖ‡ ßÿûï¿í±Ç³‰'ž¸pÛµkûS»][§ÌÛW\q…õë×/šøÅ_Ø>ûìc=zôhÑäóÎ;ÏN:é$›gžyZÿóÏ?m£6²_|1?'[šœsÎ9öþûïÛ'Ÿ|b?üp‹ëZÛÓ$aë­·ŽÏÐ믿b~ÔQGÅ5²óòË/ÛÓO?§žzª=ñÄ-ì±Ó¼øæ[zV2°¥–ZÊ$èµeß}÷µ%—\2îÏ?ÿÜ6Þxc›tÒIã‹ûƒ>ˆê´>úÈfuÖØ?âˆ#lúé§·%–XÂäÁeEä†nhÝ»w·•VZ©…@ÜtÓMá1N;í´vß}÷ÙüóÏo¿ýö›É“–= Ž<Ê«¯¾Ú.¿üò0)qXn¹åB¸i ´.šì½÷Þ6É$“XÏž=í¶Ûn³vÚ)ªéœ¼È馛.Äçä“OÎ/ÏD½¶o¾=÷ÜÓ¦˜b [xá…í–[nÉëo±ÅvÚi§E¿Yd{æ™gòsêƒXhR²ýöÛÛ€L÷–÷ú믿æõ8à“§ÝÖ}òʾQ¯^ïÞ½í ƒ²;ï¼ÓN8ᄜ¥Æ.+:wÿý÷›x·øwÜ1Ú6öØcÛTSM—|ðÁ1Iyä‘c\n¿ýöèS[öeùý÷ßmê©§Žj?ÿüsîõk2xÖYgÙ(£Œ“Ë)§œ²‹Ì.ïMJÀÃ?”,¾øâ Ԣʰ ðÀ¤Ã?|X˜®6W\qÅtá…¦ñÇ?¿¯{ÉÉCÔÉE!¹w•\L’>kþEŸ¾ÿþûtüñǧ­¶Ú*ê?øàƒÉÅ7¶UWõÞ{ï½ôÒK/%ç&Ǧ¿þú+¹(¦O<1®¿ôÒKÓŒ3Î×xè7¹¤W_}5¹W—\p“ OœÛm·Ý’‡p“‡pÓ+¯¼’<4œŽ;î¸8§ûôéÓ'¹'õÁ½Â8^ûâ!ãäžgúöÛo“{˜É#É…4ª¸ §å—_>¹7š²å€¨#Yý5×\3îã¡ñä8äžÔÇo¾ù&m°ÁÁP'ÕÏ×^{-ê© >ñ‰:mÝ'*ÿóR¯žOtÂö]wÝ•´½×^{%ŸXw]ª¶/´ÐBéË/¿L]ºtI_ýunVmwo?]yå•É'DqÜ'#i´ÑFKfO>‰KL0AòÐ}~M[öôùñÉcò4GÜÓÓAùuÙÆÝwß}×gŒÒ1h¦Gi€€¾ä(íC Y^Â"qu/*¾ôEsÁ Q’8=úè£É½Ð4Ë,³„P뼄Mç$Üî%&Å&÷ÖB@%ÒYYyå•C$uNB òË/¿$÷ Ó„Nû«¬²Jºà‚ b[/î§u×]7öÝóM‡rHlëe¾ùæK÷Þ{oìk‚ ñ’½?þ8D:¯è7 º„LEB¥{^wÝu±/Q—èª]HuH<òHúðÃÓXcõ³¾y˜;uíÚ5y#®ÕËj«­–<¢¦ÙqÞ››@—& LЭ&"à¢bwÜqG„\«Ú-÷|ÍÅ:òì ×*Lï‚nîÁÆb*…åW˜Ü…¯Eî[áWnó‰fäTul™e–Éqh1•{úqc=6l+ô«…{ û×Xä^]àókzžcŽ9b_yàlñž ¹ŸŸS¨~³Í6³«®ºÊÎ<óLsÁÍmhC‹Â~V_T´PíÉlßpà ¦¼±Êä“OkÔ&債˜Lõ³¾y4"®Sz!+.â®~þùçÍÏ<§\à£_.²æz„¶õYQš@© …ÏUt/¥->ûì3»ùæ›Myê'Ÿ|²î}â¢^Újî©4ÂcŒµÅP!v•ÕW_=Úªüùã?ncŽ9f¤-Šßa‡L9rúH“Ì;ï¼Á[9|÷àmÛm· _VÄÂËzö|Òf»ï¾{ÜwóÍ7ët¥.”ÞPQŠc›m¶1ŸpE*(òÒ! ðb˜«ÝÉVXÁ”;Ôµª ¦rç\­fÖŠzå¢%ª.åÒµÀÎ=µøòwO3º*QRéܹsˆ ¾Ì5X`̽à8'±×⬙gž9röâ$;Êã*-”˜+×®m‰¸ÄGmP]åh%„*Z(žJñV{%tgœqF½Ú”ÙQ}­ü¯Ý×¢.µI9a­ ¸øâ‹cÁž„×£1aC.QÏ j[}{ã7rÁ”mML$ÆÊ›K 2q×9M<ºu$„Zðæ©€Ø—ý̶ú%Q÷´…ýç?ÿ ûêC&Ì­ï£ý¬´U¯oß¾ù$Fk´ N«Ø•—Èj¢Å“ZàɸHÀ—]vÙ|]„¸j­ÅW_}c¬ë3–šô4ÒH1ªgO“}~V]uÕ¬É1¶kÝ_ ð4AÖäˆÒÁ4w€¢¸Þ¢/ŽeG´¤œº{fÑu幕G^o½õbÿÐC¼v”›Už[an…~ÎöÅp‘ÿö/ûG+äíâ\âz­È™kÇ¿èÓ%—\Ç•—v¡N¾ ,öBÖåêŽ÷¯ºä–|á]òÅxQG/î±çû¾Ø-+ìëQ³ç•}C!z¥¾WžÙ'ÉÀE•,­Ý×Å-rÅÚW^^¡wåö³¾¹ÐGˆÞ' ª’Qៗ¶ê‰»G ¢¦{éa¿öÚlÛ2&å¿[…äýQÄkSšAýÐq}^”jh]ZÛóèIž–ñ}1úì(Í¡5J‡P:&<ø6¡£»íC@ªç]ãæòˆµJ\!^y`ZE¯²ë®»š RxÓž‹6­´Ösâ=ôPx‡òÊå‘xàá±{®;BûZY®"Ï_!`òðÀõl´®QQÈZ«Ù>úèßêZý½ð ¹·«zÚWº@Eáb­\Wh[Þ¬žË–7Y[yMyÏòP=¯žµê(´,Ï_y£ŠT(z¡"&:§þËsU;²ße—]¢žRºæúë¯ïVõÔ7µMQyízæ[!~­Ø—‡ê Ól±Å‹úY¿ÅKLµr^‘ •¶îþyi«ž"Z=/º·¼p=½à çrŠœÈsÏ¢ ù ßPÿÕµ_E“óÏ??˜)Å!ûJ‹Ô–ÁÙÓsøwEyäõë™zE'ôˆœÚ”ý΀ìh<ÅœÒ1tÒ¼¦ctõë¥/BŠ/ÙÿÍ WC 1ú e[EaX=–…t³º ¿»W?T“ó•êÆWºCÅ=øì,7žÕ«÷®öH4|5ø U|1^äÖ5™P‘XŸ~úé-„ÅÙ UŠE!~ýéž*zäMù{­cÐW–0;üŽÖpåä-­ïSïºzõÄY“‰«Ú$n=õlÖ;®þ‰·ÖP MQ¿víÂÐ\KÝæ$0è¿Öæì'½‚@¥ IÜÕ™ÌCmÝ1åùõ+tµEM7ÝÔ|Õv,8“(+/Ûhi«=òP•#—÷ê¡èÈ“g‰ÌþЮŸç®¿¬È{Ÿ}öÙócƒë»"C[Zß§ÞõõêÕN24±šÉE½{É£Zq—-ĽÑŽ{¾Á±ÇƒoÕJK@+÷µÈMaj-ôR¸¨¢ÍñGca~gpü¿ÜK‹ïäÅë)  о1N†À7Šj€ P KÑ @€@¡øBqb € P|9ÆV@€ %€ÀŠc€ r@àË1´€ P(¾Pœƒ ”ƒ_Žq € B ð…âÄ @ ørŒ­€ J/'Æ @å €À—ch @ P|¡81@(¾ã@+ @…@à ʼn1@€@9 ðåZ@(”_(NŒA€ÊA/Ç8Ð @€@¡øBqb € P|9ÆV@€ %€ÀŠc€ r@àË1´€ P(¾Pœƒ ”ƒ_Žq € B ð…âÄ @ ørŒ­€ J/'Æ @å €À—ch @ P|¡81@(¾ã@+ @…@à ʼn1@€@9 ðåZ@(”_(NŒA€ÊA/Ç8Ð @€@¡øBqb € P|9ÆV@€ %€ÀŠc€ r@àË1´¢ƒøòË/-¥T©^ÿòË/öÍ7ßTªÍCÓØ?ÿüshªS¥'€À—~ˆh`³ }ôÑ6ÖXcÙ ,`O<±m¹å–öûï¿—¾‹<ð€uïÞÝæ™gûðÃÿçö~÷Ýwvä‘GævÎ>ûl{÷ÝwmÀ€6ùä“òwÍ5×DÝ»îºË–\rI›a†lûí··~ø!·¡:ÓN;m´ñüóÏÏ‹ïŽ;îhSM5•­¸âŠöÜsÏåç²+¯¼Ò¶Øb‹l7Þ;ì0›k®¹lÎ9ç´sÏ=·Å9v P þ¥Ci€Àâ‹/Þ@-ª@ >Éäâ•>ýôÓ¨ôã?¦UVY%í¿ÿþõ/*É™õ×_?zê©…µæÌ3ÏL›nºiØûüóÏS×®]“{Ðé?þHÚÏþ.½ôÒ䓊ôí·ß¦÷ß?ù¤(õë×/ên´ÑFé¸ãŽ ·ß~{šwÞyÓ×_<ÒfŸ}öäQ’8çÂöÞ{ïØvqOË,³LlëEûê[çÎÓI'”?çœsÒ²Ë.›~þùç°“Ý7¯À*@@aBJø Q¥Mî}¦É&›,U~ï½÷ÒóÏ?×m»í¶éŽ;îÈm¬·Þzé±Ç‹ýÞ½{§Yf™%¹7™Î;ï¼¼NíFß¾}C”¦˜bŠ´ÓN;%÷nãô'Ÿ|’6ß|ó4ᄦ 6Ø õïß?Žo³Í6É=×°ëÞjúàƒÒrË-—&˜`‚´Ùf›¥·Þz+ê­°Â iä‘G޶«}ï¼óNØQ=÷ˆÓC=TÛŒ|»ž=‰ûØcÆo¼tüñÇ'µw¤‘F ¡Í/ö ùÜsÏâ®ãÿýwúâ‹/ò*;ï¼sÚk¯½bÁL÷ÜsO~N}»ä’KÒG}ýþõ×_ósºï÷ߟ>þøã¤×÷Ýw_šrÊ)[ôCÂîQ†¸FI&™$=óÌ3¹ 6 PÔÈJ„Ú¹‘“N:©­±ÆíÜ n_U.°6Ûl³Ùª«®j/½ô’xàæ"d#Ž8bÞ%…¦]@mÖYgü|·nÝìÍ7ߌóK/½´=ù䓿ž­-´ÐBöúë¯GÈ<¿Ø7–Xb ;ôÐC#¬ìB÷òIƒ¹'j.€Ö«W/ÛsÏ=#ü}ÄG˜O6lºé¦³=öØÃfši&sÏÖvÙeÓ5î­Çýn¾ùfs¡6)4¯ôBÏž=ãß‚êéü1Çí©m‹{âaspö~úé§hãi§f‹.º¨)®P»‹½¹'fþúë/›cŽ9ÂöÊ+¯\kÚ^|ñE»è¢‹LázñêÒ¥K°Õú€Œ§®sŸ@Ù+¯¼b—]vYØpáŽ>èݽöø8p 3Î8æQsÌ1[ÜëÚk¯5Ÿ(Ø#Œ}Õ5T…@—ª4´½Ûyá…Fδ½ÛÁý«I@b*ñ¹í¶ÛÌ=ð5 ÜÕW_9^‰“òÏ3Î8ctPÂ4ꨣÆgîÕW_5÷ºÍ½y[i¥•ìþûï7÷x¡ëï¼óÎÈï+g,s¯Ö܃·C9$DJ®\÷W_}Ç%’° .¸ÀÜ“ŽI€ { ÄUbì^pÔQ^Â}ú駇@»Wlî ‡0¶nŒ‡ÖëÚ“Xz¸ÝYd}ôÑÍ#1ÉÄ]¶4qЧµ¸ëܽ÷Þkú÷èQ†È¹«Ïšeâ®:â§|¼&С(ºo=bRÓ„aši¦DÜ=b¹wP˜Ö î1Þ+C  aÚªPxÙÅ2ï†ÂçîaFN^|ðÁä ºòó.ünÏ(¬í‚—|Y„Ò³ãµïÊ'+ŒïѦä§Ž:ꨤPvëâ"™<¢Þzë­“ w¾¯°ô(£Œ’´Nà„NH:¯âƒ´Î:ëDØÛ'#q¿Å[,¿.ÛhËÞ³Ï>›\P³ªá…ò}m¸ø'_x×âXíŽG"oîBžÄFùø¬(ü®”‚Ú®¶e,t^9}Ÿ4dUãý”SN$=P[áä“OŽuµÇ؆@oªÌTŒ†V™€V‰o¸á†yÆcŒ§Ë;–÷þÚk¯E˜9« Ï[«·ûí·ðØåQ+T®²/Ê˪åïO=õT„ÞþW^Þ­k“}E²r÷Ýw›/ò‹0·çŸ³Ãú¯õ µÒ\ž®Îöüz„å^xáðæsCÿl(•PÏž*ÿórà 7ØW\aävØ!Þ?ûì³x¤,»§òöz´L“‰šÚ”…éúVQ^kÜó} ²Ú¢¢ç÷µÀ=ä˜p\wÝu6ýôÓǹڗ¶ì)å¥"4±ñn-Rê‹Ö Œ;Imkb£4„Êå—_®û¨mZŸ ”„¯¢ô‡¯šzšHH°U”ÚP_|Õ|ìg/­^c£µ *š`uÖY‘‰¼@ Jªf hgœqF<Ê¥ÛîÝ&÷~cEºúæ+µ]<Ó¾ûî›\ø“ ytÛ”Eø^áyÏ+'ªAp¼ýöÛaÏ=×ä‚6TIáj_Ø—æŸþ°á|\«ðº/>Ëíèñ2­(WØ~¾ùæKp@œsÑLžÛŽp·hŹÂ못öÚk'µ×=ëÜN¶QÏžÎ+ä¯øê— |rñŽUùÙµzÜÍ<ÛÍßµ*^Ì) !µ«Ú:è `&nµ¡}=A°Új«Å9…ý³'2£z¤NýËVÌë¸/ð‹”„îåëÒšk®³kx‡@U°Š¾J³1ÚÚ´8M+¿õW[´r\ »j‹Õž×‚·,ì\{¼v[¶åõ·^&OT^÷Š®W½N:Õ­ê_náÙz޾nìD={úñõS÷QŸÕ÷zýÎleïõ8ÔÚÌêfïö?«¯wµI¿n×·ÚëØ†@Y ðe Ú@(9øab € P|YF‚v@€ $€ÀS€ ²@àË2´€ P ¾@˜˜‚ ”…_–‘ €  ðÂÄ @ ,ø²Œí€ H/&¦ @e!€À—e$h @ @|01@( ¾,#A; @@à „‰)@€@Y ðe Ú@(_ LLA€ÊB/ËHÐ@€@øab € P|YF‚v@€ $€ÀS€ ²@àË2´€ P ¾@˜˜‚ ”…_–‘ €  ðÂÄ @ ,ø²Œí€ H/&¦ @e!€À—e$h @ @|01@( ¾,#A; @@à „‰)@€@Y ðe Ú@(_ LLA€ÊB/ËHÐ@€@øab € P|YF‚v@€ $€ÀS€ ²@àË2´€ P ¾@˜˜‚ ”…_–‘ €  ðÂÄ @ ,ø²Œí€ H/&¦ @e!€À—e$h @ @|01@( ¾,#A; @@à „‰)@€@Y ðe Ú@(_ LLA€ÊB/ËHÐ@€@øab € P|YF‚v@€ $€ÀS€ ²@àË2´€ P ¾@˜˜‚ ”…_–‘ €  ðÂÄ @ ,ø²Œí€ H/&¦ @e!€À—e$h @ @|01@( ¾,#A; @@à „‰)@€@Y ðe Ú@(_ LLA€ÊB/ËHÐ@€@øab € P|YF‚v@€ $€ÀS€ ²@àË2´€ P ¾@˜˜‚ ”…_–‘ €  ðÂÄ @ ,ø²Œí€ HàÿŒ%¼ s4(IEND®B`‚rotl/vignettes/meta-analysis.Rmd0000644000176200001440000005014115132142363016456 0ustar liggesusers--- title: "Using the Open Tree synthesis in a comparative analysis" author: "David Winter" date: "2026-01-15" output: rmarkdown::html_vignette: css: vignette.css vignette: > %\VignetteIndexEntry{Using the Open Tree synthesis in a comparative analysis} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} %\VignetteEncoding{UTF-8} --- ## Phylogenetic Comparative Methods The development of phylogenetic comparative methods has made phylogenies and important source of data in fields as diverse as ecology, genomic and medicine. Comparative methods can be used to investigate patterns in the evolution of traits or the diversification of lineages. In other cases a phylogeny is treated as a "nuisance parameter", allowing with the autocorrelation created by the shared evolutionary history of the different species included to be controlled for. In many cases finding a tree that relates the species for which trait data are available is a rate-limiting step in such comparative analyses. Here we show how the synthetic tree provided by Open Tree of Life (and made available in R via `rotl`) can help to fill this gap. ## A phylogenetic meta-analysis To demonstrate the use of `rotl` in a comparative analysis, we will partially reproduce the results of [Rutkowska _et al_ 2014](https://doi.org/10.1111/jeb.12282). Very briefly, this study is a meta-analysis summarising the results of multiple studies testing for systematic differences in the size of eggs which contain male and female offspring. Such a difference might mean that birds invest more heavily in one sex than the other. Because this study involves data from 51 different species, Rutkowska _et al_ used a phylogenetic comparative approach to account for the shared evolutionary history among some of the studied-species. ### Gather the data If we are going to reproduce this analysis, we will first need to gather the data. Thankfully, the data is available as supplementary material from the publisher's website. We provide a copy of this data with the package: ``` r library(rotl) ``` ``` r ## This dataset is available from the publisher's study website: egg_data <- read.csv(system.file("extdata", "egg.csv", package = "rotl"), stringsAsFactors = FALSE ) ## } head(egg_data) ``` ``` ## animal Spp Lndim Measure Neggs Nclutches ESr Type StudyID Year D EN Zr VZr ## 1 Zonotrichia_leucophrys White-crowned sparrow 0.000000000 volume 294 73 0.14004594 stat Mead1987 1987 3.421918 85.91673 0.14097244 0.012060292 ## 2 Passer_domesticus House sparrow 0.009407469 volume 149 31 0.11175203 stat Cordero2000 2000 4.045161 36.83413 0.11222075 0.029555954 ## 3 Serinus_canaria Canary 0.000000000 volume 52 21 0.49679140 stat Leitner2006 2006 2.180952 23.84279 0.54503712 0.047978211 ## 4 Turdus_merula European blackbird 0.021189299 volume 82 54 0.38598540 stat Martyka2010 2010 1.414815 57.95812 0.40707397 0.018195675 ## 5 Agelaius_phoeniceus Red-winged blackbird 0.218316086 volume 394 106 0.07410136 raw Weatherhead1985 1985 3.173585 124.14982 0.07423744 0.008254242 ## 6 Quiscalus_mexicanus Great-tailed grackle 0.281894985 mass 822 205 0.05178834 raw Teather1989 1989 3.407805 241.21099 0.05183471 0.004197959 ``` The most important variable in this dataset is `Zr`, which is a [normalized effect size](https://en.wikipedia.org/wiki/Fisher_transformation) for difference ,in size between eggs that contain males and females. Values close to zero come from studies that found the sex of an egg's inhabitant had little effect in its size, while large positive or negative values correspond to studies with substantial sex biases (towards males and females respectively). Since this is a meta-analysis we should produce the classic [funnel plot](https://en.wikipedia.org/wiki/Funnel_plot) with effects-size on the y-axis and precision (the inverse of the sample standard error) on the x-axis. Here we calculate precision from the sample variance (`Vzr`): ``` r plot(1 / sqrt(egg_data$VZr), egg_data$Zr, pch = 16, ylab = "Effect size (Zr)", xlab = "Precision (1/SE)", main = "Effect sizes for sex bias in egg size among 51 brid species" ) ``` ![plot of chunk eggs_in_a_funnel](fig-vignettes-eggs_in_a_funnel-1.png) In order to use this data later on we need to first convert it to a standard `data.frame`. We can also convert the `animal` column (the species names) to lower case, and remove the underscores in their names, which will make it easier to match names later on: ``` r egg_data <- as.data.frame(egg_data) ## Convert taxon names to lower case egg_data$animal <- tolower(egg_data$animal) ## Let's remove the underscores (_) from the taxon names egg_data$animal <- gsub("_", " ", egg_data$animal) ``` ### Find the species in OTT We can use the OTL synthesis tree to relate these species. To do so we first need to find Open Tree Taxonomy (OTT) IDs for each species. We can do that with the Taxonomic Name Resolution Service function `tnrs_match_names`: ``` r taxa <- tnrs_match_names(unique(egg_data$animal), context_name = "Animals") head(taxa) ``` ``` ## search_string unique_name approximate_match score ott_id is_synonym flags number_matches ## 1 zonotrichia leucophrys Zonotrichia leucophrys FALSE 1 265553 FALSE 1 ## 2 passer domesticus Passer domesticus FALSE 1 745175 FALSE 1 ## 3 serinus canaria Serinus canaria FALSE 1 464865 FALSE sibling_higher 1 ## 4 turdus merula Turdus merula FALSE 1 568572 FALSE 1 ## 5 agelaius phoeniceus Agelaius phoeniceus FALSE 1 226605 FALSE 1 ## 6 quiscalus mexicanus Quiscalus mexicanus FALSE 1 743411 FALSE 1 ``` All of these species are in OTT, but a few of them go by different names in the Open Tree than we have in our data set. Because the tree `rotl` fetches will have Open Tree names, we need to create a named vector that maps the names we have for each species to the names Open Tree uses for them: ``` r taxon_map <- structure(taxa$search_string, names = taxa$unique_name) ``` Now we can use this map to retrieve "data set names" from "OTT names": ``` r taxon_map["Anser caerulescens"] ``` ``` ## Anser caerulescens ## "chen caerulescens" ``` ### Get a tree Now we can get the tree. There are really too many tips here to show nicely, so we will leave them out of this plot ``` r tr <- tol_induced_subtree(ott_id(taxa)[is_in_tree(ott_id(taxa))]) ``` ``` ## Warning in collapse_singles(tr, show_progress): Dropping singleton nodes with labels: mrcaott246ott92263, mrcaott246ott1858, mrcaott246ott3600042, mrcaott246ott7113, Passeriformes ott1041547, mrcaott246ott3212, mrcaott246ott428578, mrcaott246ott44866, ## mrcaott246ott5929, mrcaott246ott96288, mrcaott246ott310390, mrcaott246ott176461, mrcaott246ott22325, mrcaott246ott10351, mrcaott246ott72472, mrcaott246ott5934, mrcaott246ott3599436, mrcaott246ott1566, mrcaott1566ott3598440, mrcaott1566ott496009, ## mrcaott1566ott35326, mrcaott1566ott92668, mrcaott1566ott24297, mrcaott1566ott22300, mrcaott22300ott35350, mrcaott22300ott32651, mrcaott22300ott547548, mrcaott22300ott67150, mrcaott22300ott130294, mrcaott22300ott7660860, mrcaott22300ott416087, ## mrcaott22300ott416089, mrcaott22300ott107840, mrcaott113980ott364210, mrcaott113980ott3598839, mrcaott3598839ott5341363, mrcaott19467ott431648, mrcaott19467ott401023, mrcaott19467ott252687, mrcaott19467ott233446, mrcaott19467ott378061, mrcaott19467ott1046624, ## mrcaott19467ott161293, mrcaott19467ott46396, mrcaott46396ott46399, mrcaott46399ott168083, mrcaott168083ott691103, mrcaott2175ott600902, mrcaott2175ott259082, mrcaott2175ott59905, mrcaott2175ott2224, mrcaott2224ott366470, mrcaott3364ott310375, mrcaott3364ott4083, ## mrcaott4083ott35042, mrcaott4083ott35053, mrcaott4083ott370807, mrcaott4083ott469177, mrcaott4083ott11712, mrcaott4083ott52094, mrcaott4083ott95949, Erythrura ott465905, mrcaott24017ott24025, mrcaott24025ott596763, mrcaott24025ott389884, mrcaott24025ott453058, ## mrcaott24025ott865473, mrcaott24025ott141501, mrcaott141501ott389883, mrcaott141501ott3597689, mrcaott141501ott865472, mrcaott141501ott3597698, mrcaott105913ott596770, mrcaott105913ott3599583, mrcaott105913ott543841, mrcaott105913ott124463, ## mrcaott124463ott445491, mrcaott445491ott7068429, mrcaott445491ott708327, mrcaott4088ott95302, mrcaott4088ott8371, mrcaott4088ott138768, mrcaott4088ott28339, mrcaott4088ott5616, mrcaott5616ott6023, mrcaott6023ott243614, mrcaott6023ott101225, mrcaott6023ott125079, ## mrcaott125079ott463026, mrcaott125079ott765405, Zonotrichia (genus in domain Eukaryota) ott789032, mrcaott125079ott265547, mrcaott125079ott265554, mrcaott5620ott254662, mrcaott5620ott29804, mrcaott29804ott998133, mrcaott29804ott449562, mrcaott29804ott86894, ## mrcaott29804ott93045, mrcaott93045ott264496, mrcaott264496ott264500, mrcaott264500ott3597163, mrcaott264500ott283668, Quiscalus ott743410, mrcaott283673ott673386, mrcaott283673ott741944, mrcaott283673ott735243, mrcaott213448ott213452, mrcaott213448ott1009279, ## mrcaott213448ott213451, mrcaott213454ott430627, Agelaius ott617799, mrcaott430627ott617797, mrcaott430627ott3597159, mrcaott99175ott364331, Xanthocephalus ott364336, mrcaott6366ott28332, mrcaott6366ott88283, mrcaott6366ott341465, mrcaott6366ott157599, ## mrcaott6366ott178457, mrcaott6366ott405215, mrcaott6366ott238137, mrcaott6366ott6375, mrcaott6375ott119724, mrcaott6375ott328909, mrcaott328909ott464865, mrcaott464865ott1083724, Haemorhous ott3601758, mrcaott9416ott580155, mrcaott9416ott840030, ## mrcaott9416ott96147, mrcaott9416ott749634, Passer ott515158, mrcaott9416ott7661508, mrcaott9416ott25628, mrcaott9416ott407763, mrcaott9416ott407764, mrcaott9416ott68955, mrcaott9416ott73636, mrcaott73636ott5859927, mrcaott73636ott995847, mrcaott1488ott63797, ## mrcaott1488ott284404, mrcaott1488ott107463, mrcaott1488ott17016, mrcaott1488ott16185, Hirundinidae ott897681, mrcaott16185ott67921, mrcaott16185ott67916, mrcaott67916ott368059, mrcaott67916ott67920, mrcaott67920ott3597799, Delichon ott922719, ## mrcaott44217ott107476, mrcaott107476ott177058, mrcaott107476ott446183, mrcaott107476ott337755, mrcaott107476ott337752, mrcaott337752ott374222, mrcaott337752ott337762, mrcaott337752ott3598087, mrcaott337752ott496789, mrcaott2375ott73144, mrcaott2375ott124085, ## mrcaott2375ott71358, mrcaott2375ott814750, mrcaott2375ott61147, mrcaott61147ott84656, mrcaott61147ott123763, mrcaott123763ott258794, mrcaott4820ott294599, mrcaott4820ott75981, mrcaott4820ott379708, mrcaott4820ott17162, mrcaott4820ott20998, mrcaott4820ott20989, ## mrcaott4820ott58860, mrcaott4820ott23690, mrcaott4820ott20996, mrcaott4820ott749725, mrcaott4820ott11462, mrcaott4820ott140440, mrcaott4820ott197505, mrcaott4820ott75978, mrcaott4820ott11315, mrcaott4820ott5933, mrcaott5933ott662804, mrcaott5933ott60465, ## mrcaott5933ott25637, mrcaott25637ott473431, mrcaott25637ott199843, mrcaott25637ott111993, mrcaott25637ott183621, mrcaott183621ott282315, mrcaott282315ott501241, mrcaott501241ott597018, mrcaott686165ott686168, mrcaott60456ott75990, mrcaott60456ott894604, Pica ## ott776480, Falconiformes ott212187, Falconidae ott212186, mrcaott47588ott225286, mrcaott47588ott748842, mrcaott47588ott3596147, Falco ott786441, mrcaott179290ott624976, mrcaott179290ott624973, mrcaott179290ott3596145, mrcaott179290ott624974, ## mrcaott179290ott432111, mrcaott179290ott285806, Cerchneis ott3596159, mrcaott5272ott928360, mrcaott5272ott7145, mrcaott5272ott24121, Scolopacidae ott887699, mrcaott24121ott217797, mrcaott24121ott45306, mrcaott24121ott55408, mrcaott24121ott420370, ## mrcaott24121ott654830, mrcaott24121ott214779, mrcaott24121ott1090732, mrcaott7639ott306220, mrcaott7639ott57833, mrcaott7639ott738512, mrcaott7639ott279504, mrcaott7639ott47401, mrcaott47401ott234666, mrcaott234666ott341044, mrcaott234666ott651058, ## mrcaott234666ott341047, mrcaott234666ott285543, mrcaott285543ott341030, mrcaott285543ott341032, mrcaott285543ott738509, mrcaott285543ott966606, mrcaott285543ott966604, mrcaott22965ott80679, mrcaott22965ott154126, mrcaott22965ott373759, mrcaott22965ott282132, ## mrcaott22965ott414141, mrcaott22965ott335737, mrcaott22965ott509055, mrcaott22965ott324050, mrcaott22965ott910287, mrcaott22965ott353849, mrcaott22965ott335736, mrcaott22965ott526679, mrcaott22965ott75913, mrcaott75913ott515357, mrcaott75913ott119602, ## mrcaott75913ott993041, mrcaott425206ott887691, mrcaott425206ott515355, mrcaott241571ott993045, mrcaott241571ott1026258, mrcaott241571ott254356, mrcaott241571ott704181, mrcaott704181ott4947414, mrcaott147723ott219032, Stercorariidae ott168297, Stercorarius ## ott742632, mrcaott742640ott742641, mrcaott57823ott57827, mrcaott57823ott242771, mrcaott57823ott80080, mrcaott57823ott112937, mrcaott112937ott673638, mrcaott112937ott129402, mrcaott112937ott242776, mrcaott242776ott3596974, mrcaott242776ott3596977, ## mrcaott242776ott313115, mrcaott242776ott413796, mrcaott5481ott9830, mrcaott9830ott86672, mrcaott9830ott90560, mrcaott9830ott324158, mrcaott9830ott55044, mrcaott9830ott285638, mrcaott9830ott117726, Sulidae ott452462, mrcaott170197ott403772, Sula ott160486, ## mrcaott170197ott5859716, mrcaott170197ott429615, mrcaott429615ott1030312, Procellariiformes ott452461, Diomedeidae ott85277, mrcaott71459ott320282, Phoebastria ott941509, mrcaott320282ott320284, Sphenisciformes ott494366, Spheniscidae ott494367, ## mrcaott60413ott3600120, mrcaott60413ott4130813, mrcaott60413ott4130835, mrcaott60413ott4130832, mrcaott60413ott3600127, mrcaott60413ott4130831, mrcaott60413ott3600124, mrcaott60413ott3600128, mrcaott60413ott3600129, mrcaott60413ott4130848, mrcaott60413ott4130817, ## mrcaott60413ott494361, mrcaott60413ott60417, mrcaott60413ott3600131, mrcaott60413ott7068884, Eudyptes ott494364, mrcaott60413ott88590, mrcaott88590ott7068880, mrcaott88590ott116946, Pygoscelis ott494365, mrcaott134466ott783352, mrcaott5021ott198671, ## mrcaott5021ott75792, Cuculiformes ott212171, mrcaott75792ott212172, mrcaott75792ott3601282, mrcaott75792ott119216, mrcaott119216ott526771, mrcaott119216ott169265, mrcaott169265ott550039, mrcaott169265ott462546, mrcaott462546ott3596360, mrcaott462546ott3596355, ## mrcaott462546ott1050027, Cuculus ott1041429, mrcaott549514ott7068132, mrcaott549514ott3596308, mrcaott549514ott3596307, mrcaott549514ott3596306, mrcaott549514ott792626, mrcaott17146ott57819, Columbiformes ott363030, mrcaott28925ott45505, mrcaott45505ott604973, ## mrcaott45505ott50388, mrcaott45505ott277822, mrcaott45505ott51607, mrcaott51607ott67614, mrcaott51607ott331474, mrcaott51607ott277817, mrcaott51607ott320359, mrcaott320359ott493986, mrcaott320359ott767317, mrcaott320359ott921832, mrcaott320359ott938416, ## mrcaott4765ott4131031, Galliformes ott837585, mrcaott4765ott6520194, mrcaott4765ott109888, mrcaott4765ott75785, m ``` ``` r plot(tr, show.tip.label = FALSE) ```
plot of chunk birds_in_a_tree

plot of chunk birds_in_a_tree

There are a few things to note here. First, the tree has no branch lengths. At present this is true for the whole of the Open Tree synthetic tree. Some comparative methods require either branch lengths or an ultrametric tree. Before you can use one of those methods you will need to get a tree with branch lengths. You could try looking for published trees made available by the Open Tree with `studies_find_trees`. Alternatively, you could estimate branch lengths from the toplogy of a phylogeny returned by `tol_induced_subtree`, perhaps by downloading DNA sequences from the NCBI with `rentrez` or "hanging" the tree on nodes of known-age using penalized likelihood method in `ape::chronos`. In this case, we will use only the topology of the tree as input to our comparative analysis, so we can skip these steps. Second, the tip labels contain OTT IDs, which means they will not perfectly match the species names in our dataset or the taxon map that we created earlier: ``` r tr$tip.label[1:4] ``` ``` ## [1] "Ficedula_albicollis_ott107840" "Luscinia_svecica_ott274225" "Turdus_merula_ott568572" "Sturnus_unicolor_ott366470" ``` Finally, the tree contains node labels for those nodes that match a higher taxonomic group, and empty character vectors (`""`) for all other nodes. Some comparative methods either do no expect node labels at all, or require all labeled nodes to have a unique name (meaning multiple "empty" labels will cause and error). We can deal with all these details easily. `rotl` provides the convenience function `strip_ott_ids` to remove the extra information from the tip labels. With the IDs removed, we can use our taxon map to replace the tip labels in the tree with the species names from dataset. ``` r otl_tips <- strip_ott_ids(tr$tip.label, remove_underscores = TRUE) tr$tip.label <- taxon_map[ otl_tips ] ``` Finally, we can remove the node labels by setting the `node.label` attribute of the tree to `NULL`. ``` r tr$node.label <- NULL ``` ``` r egg_data <- egg_data[egg_data$animal %in% tr$tip.label, ] ``` ### Perform the meta-analysis Now we have data and a tree, and we know the names in the tree match the ones in the data. It's time to do the comparative analysis. Rutkowska _et al_. used `MCMCglmm`, a Bayesian MCMC approach to fitting multi-level models,to perform their meta-analysis, and we will do the same. Of course, to properly analyse these data you would take some care in deciding on the appropriate priors to use and inspect the results carefully. In this case, we are really interested in using this as a demonstration, so we will just run a simple model. Specifically we sill fit a model where the only variable that might explain the values of `Zr` is the random factor `animal`, which corresponds to the phylogenetic relationships among species. We also provide `Zvr` as the measurement error variance, effectively adding extra weight to the results of more powerful studies. Here's how we specify and fit that model with `MCMCglmm`: ``` r set.seed(123) if (require(MCMCglmm, quietly = TRUE)) { pr <- list( R = list(V = 1, nu = 0.002), G = list(G1 = list(V = 1, nu = 0.002)) ) model <- MCMCglmm(Zr ~ 1, random = ~animal, pedigree = tr, mev = egg_data$VZr, prior = pr, data = egg_data, verbose = FALSE ) } else { model <- readRDS(file = system.file("extdata", "mcmcglmm_model.rds", package = "rotl")) } ``` Now that we have a result we can find out how much phylogenetic signal exists for sex-biased differences in egg-size. In a multi-level model we can use variance components to look at this, specifically the proportion of the total variance that can be explained by phylogeny is called the phylogenetic reliability, _H_. Let's calculate the _H_ for this model: ``` r var_comps <- colMeans(model$VCV) var_comps["animal"] / sum(var_comps) ``` ``` ## animal ## 0.00313885 ``` It appears there is almost no phylogenetic signal to the data. The relationships among species explain much less that one percent of the total variance in the data. If you were wondering, Rutkowska _et al_. report a similar result, even after adding more predictors to their model most of the variance in `Zr` was left unexplained. ## What other comparative methods can I use in R? Here we have demonstrated just one comparative analysis that you might do in R. There are an ever-growing number of packages that allow an ever-growing number of analysis to performed in R. Some "classics" like ancestral state reconstruction, phylogenetic independent contrasts and lineage through time plots are implemented in `ape`. Packages like `phytools`, `caper` and `diversitree` provide extensions to these methods. The [CRAN Phylogenetics Taskview](https://github.com/bomeara/PhylogeneticsTaskView/blob/main/Phylogenetics.md) gives a good idea of the diversity of packages and analyses that can be completed in R (note that this links to a draft of the next version of the Taskview as it is currently unavailable from CRAN). rotl/vignettes/fig-vignettes-subtree-1.png0000644000176200001440000005767415132142347020355 0ustar liggesusers‰PNG  IHDRø XEa=iCCPkCGColorSpaceGenericRGB8U]hU>›¹³+$΃Ԧ¦’þ5”´lRÑ„Úèþe³mÜ,“l´AÉìÝi&3ãü¤i)>AÁ¨à“àÿ[Á'!j«í‹-¢´P¢ƒ(øÐúG¡Ò ë¹3³»“¸k½ËÜùæœï~çÞsîÞ ¸,[–Þ%,®-åÓâ³ÇæÄÄ:tÁ}Ð }Ð-+Ž•*•&ã¿Úíï ÆÞ×ö·÷ÿgë®PGˆÝ…ج8Ê"âeþŲ]€AûÈ ×bø Ä;lœ âõWžð²Ï™‘2ˆ_E,(ªŒþÄÛˆç#öZsðÛŽ<5¨­)"ËEÉ6«šN#Ó½ƒû¶EÝkÄÛƒO³0}߸ö—*r–ᇟUäÜtˆ¯.i³Åÿe¹i ñ#]»¼…r ñ>ÄcU{¼èt©ª7ÑÀ+§Ô™g߃xuÁ<ÊÆîDüµ1_œ u~Rœ æàâ*-°z÷#°Mi*ˆËWh6Çòˆø¸æf}î-gi:×Ð9¥fŠA,î‹ãòV§>ÄW©ž—Bý_-·Æ%=†^œ tÈ0uüõúvW™â’9 Œ%/VµñBÈWµ'¤_¶tâÜÈMÛ“ÊŸ¿ŸåP““í\>ĘÉ@Á„yì0`D i|[`£§ èh¡è¥h¡øÕàìßÂ)ùþ·TjþÈëèÑ0B¦ÿ#ðЪÂïhU#¼ ~yh«uÐ fp#Ô1I/I’ƒø"“ä0!£ ’'ÉSdŒdÑ:J5Ç–"sdó¹ÑÔy#RŸ7‹¼‹èwAÆþgd˜à´ÏÅJŸ7ØÏØÏkÊ•×n^:}nW‹»FVŸ»Ösét$gj-tÈÚÔrÏÿÂ_ç×°_ç7Z þ~ëÛV·5ë4ÌV }ºo[ÄGó=Nd>¥-Ula³£¢Y5VúË}¹x»g[üä÷É?’kÉ÷’&ãÞä>áÎsŸrŸq߀È]à.r_r_qsŸGjÔyï4k± æi—QÜŸBZØ-<(d…=ÂÃÂdKO膄 a/zv7«]»ǰod«}¬€©sìn¬³Öá?TF–'|¦ãï3Nnã„#I?"…m»z„íõ¦v~K=Ú¯Æsñl<b|_|4>?Âpƒß‹¾QìñÔré²ËâŒi´µšêŠÃÉäãb ¯2* åÀ (ëºè»Ѧµ—hå°{28ÂoIþýÛy¥esŸ8ü';÷Z¶9à¬ÐûhË6€gã½ï¬>¦xöRx'Äbß8ÕƒÃÁWOÏ«ëõ[xn%ÞØ|½^ÿûýz}óÔ߸ ÿÿ%x ÅcÖË8eXIfMM*‡i ø  ½Ë]r@IDATxíœ\Åò¶+!¸»“àîîÁÝ/.Á.îîvq¿@€‹»;$¸»»»»Ó_=õ§Ïwv23٬ٷ¿=Ò§O÷Ó'ç­ª®ÙôH^LED@D@D ©ôlªÑh0" " " A@¯AD@D@š€¾ 'UC ¼žhBø&œT ID@D@$ðzD@D@D  Hà›pR5$Àë&$ oÂIÕD@D@D@¯g@D@D@š€¾ 'UC ¼žhBø&œT ID@D@$ðzD@D@D  Hà›pR5$Àë&$ oÂIÕD@D@D@¯g@D@D@š€¾ 'UC ¼žhBø&œT ID@D@$ðzD@D@D  Hà›pR5$Àë&$ oÂIÕD@D@D@¯g@D@D@š€¾ 'UC ¼žhBø&œT ID@D@$ðzD@D@D  Hà›pR5$Àë&$ oÂIÕD@D@D@¯g@D@D@š€¾ 'UC ¼žhBø&œT ID@D@$ðzD@D@D  Hà›pR5$Àë&$ oÂIÕD@D@D@¯g@D@D@š€¾ 'UC ¼žhBø&œT ID@D@$ðzD@D@D  Hà›pR5$Àë&$ oÂIÕD@D@D@¯g@D@D@š€¾ 'UC ¼žhBø&œT ID@D@$ðzD@D@D  Hà›pR5$Àë&$ oÂIÕD@D@D@¯g@D@D@š€¾ 'µQ‡ôÐCÙ,³ÌbSL1…M=õÔ¶ð Ûo¼1ØáPÿÍ7ߤÞwÞiK,±Ä Ç»ÊÆ»À t•î4M?xÞzë­NÏÓO?mW]uU´ýí·ßÚÑG]Üç¼ó΋ç·oß¾vöÙgÇüñGÛj«­âÜšk®i>úhqî÷ß·vÚÉfœqF[}õÕösá™^j©¥löÙg·]vÙžÿþû|Ê®¾úêho¡…²þýûÇËt­·ÞzåCÚîn’Štþ¢Kã7^ºîºëÒ_ý=:óÌ3“ }ÝÞ}ðÁi¬±ÆªZç‹/¾Hï¾ûnÕs]áà 'œüÅߺÒ4}ày{ì±;m<‹,²HºñÆ£ýSO=5m´ÑF±}ÓM7¥yæ™'}õÕW‰gy饗N/½ôRœëׯ_ÚgŸ}bÛ 4ÿüóÇ6›l²IÚc=bÿÉ'ŸL.è±ýå—_¦i¦™&Ýÿý±¿×^{%7b›{Í=÷܉:?ÿüsšuÖYÓçŸçòÇYg•†n¸tÄGäCúÝ X7³†Ü üùçŸiôÑG/^žtñ×_M·ÜrKúã?¢Ç‡vXšvÚiÓ¼óΛn»í¶8výõ×§%—\2íºë®iÜqÇM+¯¼r¼`9¹á†¦{î¹']zé¥iºé¦kñsÅWÄõ×^{mši¦™Òä“Ožhÿ§Ÿ~Šãß}÷]Úb‹-Ò$“Lm>þøãqœ~ò²Åð˜yæ™ÓþóŸ8ÎLJ~˜6Þxã4Á¤u×]7!6õŽo°Áɽ¬èÿøãŸN<ñĨχ{hiÑEMN8aŸ~úiœãø!‡’Ü3K³Í6[Œ•±O6ÙdÉ£a åF6ß|óÄ‹Þ#!i¢‰&J·Þzk:ãŒ3Ò¤“NuˆW_}5-³Ì2ù’h{å•WjŽçã?N믿~šxâ‰Óf›m–Þ~ûíâúÓN;-xº×YRqòï 1VlÁL=öXQ¥Ö|¸×œ¶Ûn»´ãŽ;¦qÆ'æû¹çž ¡ëÝ»wºù曣 žÄoÅWŒqž~úéEÛõú]TòwÞy'˜`p"Î0¢Ðf¯^½âYA8ÇsÌèËù矟ÖXc˜³¨èÇsL:øàƒãe”QŠg’óôïå—_Nï½÷^<+¿üòK¾,ÚãÙÃøcþr¹ãŽ;Ò +¬»·ß~{>Ïé\PìÃÂ#É£‰ëTº/ |÷û.7r<öa‡6m»í¶!.åráñ°eBœzÊx^~ùåéë¯¿Ž—ÚÝwßçðìñ˜ðäyI¿öÚkÑ6ÂüÃ?¤‡~8^°xNÔñp~ºøâ‹ãZ¼³vØ!^ЧœrJœãÄñÇŸ–]vÙèm"ÀÏ?ÿ|D04ößÿôÙgŸ…g·ß~ûÕ‰såúèáèè3FU60ê͇‡±£ÿ×\sM<=zôH+­´RÌ/c[mµÕâô‹ûúòGòpwm´Ñâ>õú]îÛo¿ý|O>ùä„ðuÔQi•UV‰*>ø`0åYáùÁ@Áh¢Ï&Ï`.k­µVÚwß}†|³áˆÇ=âˆ#¦gŸ}6yx?aäåâ¡üxþ‰Ì5×\ c%æ…6yžyÞég.ÌוW^»<zxô#q*Ý—€¾ûÎ}—9!Éùæ›/<òÈ a¥dïþ™gž)úŒ8ááór;ðÀ‹ã¾†ŸxšcŒ1Šãlàâuùº~GX0rAÜ BA?0(x™Þwß}q±D éç048Ç‹qËÑîOô Öq_OM={öL/¼ðBÑ.‚LÁ@È}äE½ýöÛ‡±Á9_ß-Æ‹xŒ:ê¨-D1ºì²ËBX|¹±ŸtÒI1Ú  ð„z)D)Þÿýè;¢õÔSOÕì7KăñSyúÍ>ýÉíҬʯ#î£>ŠÃe"Yo>0*ðˆ)\ËØòò cëçž6…çáÌcŒ¨G½~çºü>çœs cŽ}æ‰È‚Î3‡1EA¨ç)Z„å1nˆB0·^xaœ#ºB¤‘ÇÂ8a›Hžz.< yIŠç?G€8Ï3ŽÁ€w^ñsŽçŽD0^‰¨ñ\N«tc½º[ÎÆÛqüeèÚÕè:ë¬cn6©ICîÉ™¿Lö=œiî‘Å}|­±¸{µ±í‹yÈ:¶IXr6ᙋ®•ë¿øâ‹¶é¦›š‹ŸM9å”Qß=dsÏ(¶ù`,.æ±ïë¢æž´Í0à 枼yä‘qœä¦œ@å/‹¢{Ð7Ì0ÃD=Îñã¡ÜªÇxàëÓ§O$Wq‹cÜ‹múºçž{š‹®yÜ\Í#œ2‘›‡ÝcÛ½ÀàæáýØçÃÅÒÜð‰z¾,,8Îubf£Þ`Ã\¸gn(¶`̹ýë_æâI¨ù"ïhÇ£:q_ØÞ{ï½æF®yôÂ<_À<Ò‘«ëw7# ïfÞ‘ÃåEäÉCæžr»šEXÝKŠ,a^|²Ý3‹—*//^йxò’¹ç/x÷¤"˘sG8²‘*Š{Uñ"Ý}÷Ým¹å–‹c\GùÍA²Ú&„€s¾vÇ0&|­8^ʈ3ÂëK枣!°ˆ0ÙÛ¹xŽ@ˆe­ãÎb‹-–«ÇË{#FdS# î}†øÑþœsÎiî¡…‚AAñ5åýG¸1ŽÜÓ3÷ôâ…ŸoÏIˆ]AÍLiá #†R«ßôáðã‡zô‚qåÑóuróP²yþB<Œ£\ª,îç 2Œ’ZóAßÜë5  m¸Û|06Œ ÷ìÍ#1÷¨@Y\så•WÚ"‹,bSL1…­¹æšöÃ?çØàGÑ—o¼±ÅqíˆÀðR¥]tÑVÔê^UÖXcôÅ_tÈ ÿý÷4Þxã¥ë®».ýõ×_Ñæ™gž™\ð;¤ýr#'œpBò—qù¶;‰Àü‘ž{­ó ½ûî»uëtÄÉSO=5m´ÑFÑÔ'Ÿ|’FuÔDÿ(K,±Dò?dÛW_}ušk®¹b›%—\2]uÕU‰køqC!ιñ™&šh¢ôè£&žßVX! 0 Î-¼ðÂÉ ˆØ¾å–[Ò$“LÏõ;3ÆwÜôÖ[oŽ7ß|óôïÿ;êÑÆå—_žf™e¬„ôÞ{ïÅq}ˆ@[ ȃb“Htž={†ç2Ì0ÃX=â›l²‰tÒIªtÑ·½÷ÞÛ¦™fó üñE7ð©;á„Úzë­gxc”ZÇñ¦¨»ÔRKÙL÷È]sÍ5Ö·oßø¶Þzkûì³ÏâÇ=ôÐð¬ðÈ\l·Ýv³Þ½{‡÷yýõ×ç&l‹-¶°³Ï>;¼´‰'žØðPÝX Oõ«¯¾ŠÈIJË.[\C{nD†çW«ß..¶Á˜‹…¹0˜‹Eqýé§Ÿn3Ϲñ¬ó,å?÷Ì33pà@;ðÀã>DTD ]Újt·ëäÁ:ãéÁÓ:û°Ã›¶ÝvÛä"Ýâ†.èÉ1Ž{ø3¹@§çŸ>¼"<,y'ãðÐöÛo¿šÇitúé§OV ÏÒ_Úiì±ÇŽ{eÌîÉE8yˆ5ùK<Îù ;ù²AÂûç¾»îºkZ~ùåÓ×_Ü`HãŒ3Núî»ï¢.^ÝüóÏŸèçqÇ—Æk¬h‡6Zh¡äb’\8Ò#ŒPD+Î?ÿüð‰^Tž&Ï ýá>.®i³Í6‹ûÁŠ1áY¾òÊ+q?<ÍriK»=ôPx›.‚É…'½üòËá±Þu×]éË/¿Œ~ºÐÆmÜðJ/¾øbÑŸñÇ?)9úè£ã8ýÇÃõ‹`Ç|SàƒG[ÿ‰'žã§ž nrñ ¯9(}ÔšxÓÇ[o½5Øï¾ûîÉ ¸bÎh‚HóåaúäFM´êbϤfÉCêÉ Œä‚óæ¦9Í0Ã É «ˆ>á}W+Ì÷ª,Ì—‡þÓÝwß§þüóÏøíZ<ë•õµ/CJ€5#•Vàå¤Ò’@G <­ûúxšo¾ùÒÈ#\„L9ŽX"¼}Ý4^´÷Ýw_¼°7B¨÷ž{î©yüûï¿OîE¥^x!êÓ.‚LÁ@xã7bûóÏ?Oîe¦vØ!öÝkLîYÅö§Ÿ~áݲˆ®²Ê*ɽÕÄ9·¸ÓK/½u=ã‰ÿ@àÝÓ‹]¶ï¿ÿ~ôñyê©§jöÛ=Û4ÓL3Åø¹‘§ßðÀà ܜۥX• ÂVS½v=*Ðâž<™m_pÁi›m¶‰Û¬¸âŠÉ£± ³C9$¶ç™gžä^ls„õ矎qÞùcŒ1â|-þîýÆóPõs?æ¹\êÍ ÷Äxdþ)þG¥þýûÇvþxøá‡Ó”SNËB9 ÷¬£ ¬guÖ˜#ÂçÌ3†¾Œµ²ì±Ça`• ûsÎ9gñ|•Ïaàz¤|HÛ"Ð&úÏfÚÿèÞ»·h+¯¼²ù‹³] Üë²Å_Ü\ÔÍÐüE!Ó7Þ8í§úºh„½¹ O.®'|ìë§îÌç8ÄGT=þÀDˆxÆgŒ>»8š{a±íh„\]tк¿Ä#¬ËÉgžyÆH¶¢²m¶ÙÌ½ÔØçcÄGŒP+õHÔr1‹sì»Ŷÿ 5©gs€p³{¤6`À€8F¸¶V¿÷Úk/s1lñ_ö¥¸ðÛ‘GË$|¹pÙ˜cŽçò‡‹~UõÚ}úé§muÖ‰°2íPæÞ{,7°OÈ™„4 K'$¬}üñÇæyæN,­ÀVBõýúõ³K/½Ô|=ÜÜ(2–6\4ã|-þ0c¬,©äÂÒ€{Æy7~×›Úf9e”QF‰ºÌ !örqÃÒ^ýõx™kçÿƒ$áu_[7¸ôêÕ+þ£¥-·Ü2š o$ß±¬Ás 7~¢î½÷Þk¥(nÅÒÒK/m+­´’uÔQÅñ¼Aûnå]ý6À·.t/¸C °Þɺ¦{W!”4ÊZ:ë(ݛ2aâŒðzH3„E„ÉFÎ…õnÖƒkgýuå\>Dѽ³xA_|ñÅÆÚ8bLûîeÅZ·‡ÓCĸËBÁ>u1JXw¾ùæ›C 8Náe½á†Æ6bŽ1”×VEþË]a‡C¥Zýf½ýðÃ7÷Ž£-ú@AèøVëÇk­µV¬ÿï³Ï>Æ8ÊeHÛEÌè»'¥E3†Ï|P6xSÆ‚¨{ˆÛvÚi§àÃ>ÂÆº5Æߌ@„ù_zÆÀ=0lêñǰA|=b÷Bìâl¤ÅAÿ¨7/žW| ‘͆ÝÉ'Ÿýá$ÿƒÉ—^Ì£8±–žs¸‹/Í„ÑÃõvò#†n¸wö1><ϪGW8Å£ ‘›Á?ÍóRYàŒAÃs§"í%г½ èzh/_¿ŽÄ1‚`âõ ÆxL¼hÄ$*’»ð~)ˆ5"MAPHŒm´Ñj§M=—,0?ýôSˆ%Ip¼äñà0<¸/FFù…‹`lp …7Œ ^øÔÍí#Dô £ä{ÅŽ0_Ó$¬ìñ× t/°!ñ‹zx¥ˆ É\/BŠG‰ðV–!mÎå¾#ø*IjÄÖ³ÆÃSeN|8bæPŒ7{ïD`0:hÏ–ß2¼àS?¼IÐó°v´Kb[µÿº¹Þ¼Ð·Ìn$¹ÁŽBòœ¯ŸÇ6Âïó!â'D8Oacƒg„ù€3FÅ—$ CŽqbðyØÞÊâN=懨W5qç<_ ÅhȆÇTD Íü…¡Ò Zƒo¤vTaý“¯‘<å™íñµ¢œ´Äº)뛪O|ýˆ¯‘pGa-Ú_˜qÎ…5¹Ö=î"œHË…d0QÇ® G¬ísÖ@]„b͖Ķœl—¯ãSµsœW¡I@ßJúøV‚RµÁ ôÍ÷âù.7¡çü½êÁ^¨ " "0´?°TU:‚…Œî;ï¼SâÞ@Õ†ˆ@Uòà«bô <øA™èˆˆ€ˆ@×% ¾ëÎz&" " m& o3:](" " ]—€¾ëÎz&" " m& o3:](" " ]—€¾ëÎz&" " m& o3:](" " ]—€¾ëÎz&" " m& o3:](" " ]—€¾ëÎz&" " m& o3:](" " ]—€¾ëÎz&" " m& o3:](" " ]—€¾ëÎz&" " m& o3:](" " ]—€¾ëÎz&" " m& o3:]("ШþøãFíºú-­& o5*Uìl ,°€ ;ì°6ÜpÃÙè£n}ûöµÇ{¬¸ím·Ýf .¸`±_mã‰'ž°Ë.»¬Ú©vkm»ë¬³ŽuÖY–RŠ1|ôÑGíºok.¾öÚkmñŪ›m¶™x≭¹¬Õuêq_o½õìŒ3Îhu[]±Y\wûí·ÛtÓMg3Ì0ƒm¸á†Vžë•W^Ù&›l²âçÜsÏëêµW4¬ è(þ"RiE]´µT¥­Ü£J#4Rzþù磉ï¾û.õïß?5ÖXéí·ßŽc_|ñEz÷ÝwëÞb‘EI7ÞxcÝ:m9ÙÚv§šjªôøã'ÆóÜsϵåVC|Íž{î™vÛm·¸îÍ7ßLß~ûí·Qï‚zÜ'Ÿ|òôè£Ö»ü=Wž§SO=5m´ÑFÅý]œ“`©gÏžé?ÿùOqüµ×^KM4QŒã÷ßO+¬°B0`@œwC í±Ç±ÍõK-µTlÿý÷i’I&I¯¾újìsÌ1É Ø†×xã—>þøãôÉ'ŸÄÏ/¿üçjµ'õ!LKU¥$ð­€ÔŽ*ûˆ#ŽÂXnfÖYgMîÇ!÷’Ò=÷ÜÛî=¥%–X"¹Ç•:è 8¶âŠ+¦^½z%DçÁLË,³LÑ/n^þ¯¼òJzçwâ/á~ýú/i*ŸvÚii¦™fJ³Ï>{:ûì³i—6/îõ×_?M<ñÄÉ=æÂq1yô!ñ2¿è¢‹ aØrË-ÓÍ7ß\ôeíµ×N<ð@B$¸×å—_žúô铿šk®h{ƒ 6HãŒ3NÚu×]‹kÊï½÷^ZuÕUÓøãŸŽ?þøÄ³y饗&„e¶ÙfKýõWÂ@Úb‹-B„Ü› £#·á^mšvÚiÓ¼óΛÜ;Ãðá~îu&¤¤ë®».WOeî7ÜpC܃ëo½õÖä—ôóÏ?GÝC9$M3Í4ÑŸÜ.':züµæ¯<ÿGqDsÌ1ƒãù矟Þÿýè×wÞÏÇÀ‹ñ!ú'tRzæ™gÒ?üP‡óLó™2/°EØy~0ä(<ƒÛl³Ml3÷´yõÕW+'êµêC:˜€¾•@y‰ªt^ÂóÍ7ß 7XsÍ5ÓÇñæßzë­è 'œ0ñ²Æ»G”ð–u<1„Žõ#ŒbÇÅ´gæ!Ò„—}òÉ'Ç‹û¨£ŽJ«¬²J´ÿᇦ駟>!ÔÜA/·Ë g>ñ¢ÇsCä)ó¦£>:¶1B²7øŽ:ꨉ{Ñ.¹Ë.»¤Ï?ÿ<ùòCˆÆ ãÂXÉâ ùBŒã~úé§1&Œ ¼Ð»îº+Œêr~‡vH¿þúk:å”SÂâø™gž†žþW\BÏqÄÝCÐé믿NxªYÈ8—¹¿ôÒKaˆ „O?ýtb0À(¾,\˜ŸgŸ}6 /úJéÈñ×›¿ò<1ÿ!\þùgô…¹ÅƒÏQæƒÈ‘‡ÙÓÌ3Ï¢ÁEaþ0¶rùñÇc¾ò¸8çK#!æÌÉ|U}Ù"Œ ÌQF%í¾ûîq|píåûè·t |+IòRWé<ˆÑvÛm7È ð2}ý2BócŒ1FœßtÓMÓ¾ûî[Ô½ï¾û‚åk«!Rù!T<7D™—ýSO=•Î9çœB쨇íëýaE@|oºé¦h‚ú_}õU‹v¯¹æšðº³` òì{ì±ióÍ7kç™gžtÇw¤/¿ü2 ?üð!Ìœxã7BDØF„ñàÊB -T„މ <•Ϻl!Ò£6Z´Q¾?õà‚(ˆ>2V:˜ÁˆqcÌä‚Ñã¹ -¸µ b ÆsAû#Ž—î¡ó¨ƒ—¹ß~û/c^ê|=Ê×QCÄðèè¥Ü.^5_Cð|×[l±q¡Ëцì¥ÓbOñ°®ñ-„Û— ¢Ý,╞%ûù\\ü÷Ñ ¢¼YÚD°0tU¢¾6† }Ä£§ˆ0g¾ÚE¿aB;?ýôS´K”áËÜáëKqo_Rˆ¯â 3Ì0q?®ç댎ë=«¿˜·Ž­ùãÆåy*oG§þþ¨xæ“yöeŠ¨á‰‚Á…æðî»ïŽãë©$ª±î kÂÌ¥ q¬µ–×ò=$Ÿ<Š\c­•¤5J¹]ÖtI¬"QÏ8²¯©ãË‘]Î6 kn8°™ÜŽl{’°öÚk¯äFL$ð‘tGòY.œãën¹°ÖË×í* ëäôŸä6Ö¹= Ý|UÌö\Hc-™Æãždœò%ˆè7×{„"Wœr¨Krœ(eîä&x)òH,„a.‡zhdõÓ®‡í‹$¶Ž½ù+Ïùd¹3§¹äuyíÊ…o 0ï$Ù-»ì²‘hÈy!ÉE`ÎÈ '#¾%ÀœrœgaàßYùäSÀN´GÂ9 ”zíåvõ[:’@ë áÙÚ䮸?â¡>,„x¸Í¢o+TÛ;—¯Ç#õ¤³8ä¢9kó•…õ}êáYUÂÏ9Ï•Ûå×{Ò_>]÷7!klþç§# éopų÷ŸÊRMt¨Óš~"Z9a°²Ýj÷jm»•m n¿ÿò<Õ3T*Ûg ¢š¸S¯Ús–¯¯&wïzíåvõ[:‚À îKG´ª6D`(@hÈ &;¼5B8»ª[‹€ˆ@§ßihÕðÐ"0å”SÉM*" "Рȃïγ¯±‹€ˆ€4- |ÓN­&" "Ð Hà»óìkì" " MK@ß´S«‰€ˆ€tgøî<û»ˆ€ˆ@ÓÀ7íÔj`" " Ý™€¾;ϾÆ." "д$ðM;µ˜ˆ€ˆ@w& ïγ¯±‹€ˆ€4- |ÓN­&" "Ð Hà»óìkì" " MK@ß´S«‰€ˆ€tgøî<û»ˆ€ˆ@ÓÀ7íÔj`" " Ý™€¾;ϾÆ." "д$ðM;µ˜ˆ@=üñG½ÓC|®£Ûâè¨ ¯¢Ý¡Cà¿ÿý¯ 7ÜpñÓ³gOf˜aŠýK/½´n§Î8ã {óÍ7ëÖ©vr‚ &°×_½Ú©.}¬<ÞvØÁŽ8âˆ.ÝßZœo»í6[pÁ£ï묳ŽuÖY2Žo¾ùÆ;ì°¢­2¯|çe–Yf±²(ß~ûí6ÝtÓÙ 3Ì`n¸¡}ôÑG¹º]~ùå6õÔSÛ\sÍe<«•¥Z{gŸ}v\3ß|óÙi§Öâ’•W^Ù&›l²âçÜsÏmq^;"Ð!’J«,ºè¢­ª×Ù•®¾úêtòÉ'wöm†jûsÏ=wºè¢‹ZÕ‡O>ù$:ê¨É_Ô­ªŸ+}ðÁi¬±ÆÊ» ó»r¼óÏ?ºë®»ºlÿëqþâ‹/Ò»ï¾}Ÿjª©Òã?Þ!ã8õÔSÓFmmUòúì³Ï’‹}ôÑÓ¼óÎ[Üïûï¿O“L2IzõÕWãØ1Ç“¶ÝvÛØ¾é¦›Ïä—_~™~þùç4묳¦Ï?ÿ<ÎÕjkæ™gžôÕW_¥ßÿ=-½ôÒ饗^Šk÷xã—>þøãDÿøùå—_âœ>D # ȃï3ItÚsÏ=gsÎ9g‹&ï¸ãëÛ·oxDþò5êá5ùKÚ~ýõWÛ`ƒ ìÇ´Å[Ìð†&šh"{öÙgíšk®‰ëØßzë­Í_ÈÑî“O>isÌ1‡í¶Ûnæ/[[e•U›{íµ×lÙe—-î‡çÆù‹ß¶Øb Ã+[d‘Elâ‰'6<Ð3Ï<3¼0cÀ;yä‘ÍÅÂ\hÍE6Ö·/»ì²ðüñò<^ö°Ã¿é[.x†7Üpƒ¹bx`ô¨ëºx¦xë}úô1Ö„Ÿ‡‰#Áõ.ás Ÿ¶r_sûx‚åñ2†é§ŸÞN:é$ëÑ£GôÝCÈѦ‹‰=üðÃ6ùä“ÇåV¶ûï¿?¼dÆæ?ÖŒë / o™5 žë‘GQ“§žz*¢xî”õ×_߈¸¸aóY3;LèŸ/;Þtk8Ðg")äOŒ1Ɖ!‚‚×N$Ƨˆ(0—e^ô-?WO?ý´ ÊåÁ4~Ühˆ¹ö—­¹±óM¤ƒùÎÅE?"Iì×jÏCúIr77€ìª«®27£ ¢nÔÄsîÆ«¹1Ïó«"I@OTGÒìfmù¥¹çe#Ž8b»FN‚UN¶B´*ÃóîÇ‹–p8aXn¹åbÑt/1¶yiÓV~é¾øâ‹&}ÿý÷#¤Ž¨¾¥pÂÓÂý„àK am^⼘IÄbŒBëpßW\1ê#,+P—d*BÙîÇ9>ýRèßꫯ^ôðz6Z9D‹Bòý!ì^YÊãe ôq§¼ð Ñ}ážK-µTq9cDpé‚E8ŸB{­â™ sÎÒ/ŸÃ0É‚X‹3†F…:îõÇvk8°ô‚ˆ1—KîsŽ€º×§Ê¼r] _s7ÚäC¶Ë.»ÄsÄÒeŠ)¦0Ï cí\¸ŽgãùPƒ•íí·ß~±Tá‘“06H å¹¢”“"aÏ9ž™¼úèðŒ;Šb±Í6ÛÍ!æ´‡’‹:^"ÈÚ-/k²ž)ˆ—'WÅ6ëÓˆéÅ_ëÆˆ0‚€ñ€ÇЧ‹pS<ù)¼õE@Xñ‚C¡mÖ™saŸH…>‚ÆËï›5Ûìéz"UÔÁèàšýë_±Ïû¬#³>Žw÷À„!âK±F\0êWŽaÌÆ çaG{ˆ™Ûˆ(±ÇÛEÐX—Îbʹ֎‹¼‚l„q÷&—Ì}‰¢äB¤€ºõ8sßÌŸ¶ØÖr€ipîÉÜ­ jAT ñ§TòŠƒþÁ½1ƲÇìKƒŒç†¶Ë÷ºñÆ#§qçRÙ×úòŒ]qÅaŒò bt‘óÁõÌ/ÍÄåD#xs¤%·©ß"Ðþ´#ZS"мñÎÊ<ˆ0~¥ Z„q~¼5^Œx@$]!ÔY4H’ÂkEhðpù azÄAA²ç‹@ñòÍOë„Nˆ¯D•=ö\Á,ß«,VxÇ$Q! ¾Iô“þáaçþáññ¢§>K ô‹¥ ê:ÎÞ^î¿Ëã…ÞiîS¹=¼óÇ{,– ¸Žd¯SN9…Í7¾ê•K¹zã¢M¢¸â¡"R$mÀÛ¥ÐG¶7ÝtÓºœ¹/,B8 ¸­å@_0†˜cÊé§Ÿ7†Œóœ•yEÅ¿?˜¯ò3ÆÒ ÏÆ q'™Ž>b

0¦>ó‚QåëìaPðÌåÉÑ–/Ö^{í"ª“ÛÔoèòà[I‘µ¼ì•µò’N©F&5ßÇmÆ‚hò$lY.ˆ3Þ¸'ŽEÆ»….¼*Ö_mOZ²}öÙ'B³Ù³bMžub^ÒdÉ“ùޱ@¶2Ÿ…‘û”š}ÄqÈÞ{®³ÓN;±çcîO)_ÿïÿ;ÖWlúÀ2Ôkû¬ëR8¬ºêª!ÀxÝ9”KÄ¢²”Ç‹·JVw¹=¸1>îc‘ÕŽH±NOá¾°Ê…¾·f\s@X>þ‡/™à„Ä1`ЍwÞyÁ¼gîË ÆÂL¿[Ëûì¸ãŽÁ 0c›ùe^TÂêÌ}~><29æ #±\È’çß7m­à{ïxîˆ,?Ð…ÌOÄ+_:H{ðÁð„Ì0ôÈó๠p_–;0(ˆú`àU~G¾EãÚvèážÆÿ}¤t‡Kñ^ÊëªCkÌ$yRôŒé¡Õ…⾄›_’×þ‰ÂW¯²¨æûá-áõÖÊÀƒâ…›×„óuõ~óõ2–±µµTëëàÚâkvˆv½2¸ñ–¯ÅK$ÒQ‹M¹nk· €!Å¿sÉ{bå¹Ö¶YY¯5¸£‚ŸrãDNFi¤èãðâZÿ6B±Ä~.D*à˜Ç×û×ñ‘—Êué#Çy6UD ³ȃo%Y2¶»Bá»Ç¬;wÇR)î0@¸ë‰7^tk ùX &ÄÝžR­¯ƒkopâÎõƒoùñÝêÊqቓ1N©êð®~óÍ7vØa‡ ¶ÝÖÖlCm¨ðûï¿Ûˆ#Žh_}õ•ÝvÛm¶à‚ ¶¡•ê—œqÆöæ›oÆÉ'žxÂ.»ì²¢âÊ+¯l“M6Yñsî¹ççŽ9æ›jª©l†f°‹/¾¸8~ûí·ÛtÓMÇ7ÜpÃAæì×_µõ×_ßn¼ñÆâš?ü0ŽqÝrË-g?þxqîõ×_·…^8ÚÜ~ûíí»ï¾+ÎiC†& üФ¯{þøã{î¹çìÉ'Ÿ ‘à%Éþ•W^i<ð@Q¯«nüõ×_Ñω&š¨Ã»ˆ8!"ƒ+­­7¸vÚržÿ—ƒ ãlî¹ç¶K/½´-Í rͧŸ~j{î¹§õéÓ'Îíºë®6Ê(£Äö—_~i>ú¨=öØc!¸ˆîlçN8á„048vë­·Ú‘Gi¿ýö›ýðöùæ›Û 7Ü`/½ô’Í2Ë,vøá‡Ç5<ƒW\q…Í3Ï<Ñÿ9çœ3Žóѯ_?›þùí•W^±-¶ØÂ¶ÝvÛ8‡A³âŠ+FûœãO7_~ùåÅuÚ¡I@?4éëÞ+—qÇ×xéòbF@÷Þ{o›fšiâ¥|üñÇçj¶å–[Æ yæ™g¶C9$¼½õÖ[ÏÆ|[a…ìÞ{ﺼܩÃK|òÉ'!úä“O /Ž{í¶ÛnE›wÜq‡õíÛ7þCÿüó˜ïá‡><è#Ž8ÂÎ:ë,{÷Ýw­wïÞö /Øpà Þ:ÏÓ”SN÷ÿé§ŸŠÑÙgŸÿ?ÃÏä“NZôñ’K.±í¶ŽeDèIDATÛ.öyV¾øâ‹Ø¾ð m‘E±…Z(öéÏõ×__\§ ª<´¨Ò@®¾úêtòÉ'·»Ç‹.ºh»Ûð[:õÔSÓùçŸß®ŸW_}5¹ˆ¤¥–Zªè“‹KrAO. É_ÂÉ=-»ì²ÉC¥‰úN8azþùç£þ$“L’üÅšn¾ùæôÞ{ï%§ãŽ;.y ù 8M?ýôQÏE6 ;ì°i—]vI.QÏ…>¹H¦·ß~;õêÕ+¹°$÷Äâ¾wÝuWr/1-¹ä’Q‡FÎ<óÌĸ]À’ É…6Úv‘LG}tl»0$>Ķ&ɽºèwkïþýáFIr£&¹š~ùå—tâ‰'&æî­·ÞJ.¸‰{¹ñ‘*ë¹È&7–’{²Á©¿Zýu1M.fÉÅ5ùL”^~ùåš\¶Ùf›ä¢½v/>ú÷Úk¯EýGy$¹§›Ö]wÝtÀ”‡Û?üprï?¹‘\8ÓK,‘<ãÚ}÷Ý“1—ðãy Ÿ4æ˜c¦e–Y&¹WŸ¨K¹é¦›â¸‡îÓL3Í”fuÖx.â¤0ž7¼Ò ,>øàƒ8åkîñû¿ÿýoÛl³ÿ=1žù=÷ÜÇ»Xž»€‘ ‡‡ÏÆí/ßðÖ¹/c¤À.G#âÀß,“@=æšâFO‹ºÌA{ÿæ¿o§_"Ð~CӺн‡œ@Wòà‡¼÷µ¯ðPlòuÒ„×èëªÉ“ÕÞo.x‡¾?xÐþä'åä!ãä먹Zxwk®¹fx„xîxpÔ§øÚkáAfÏ/“‚‡L(xõx®.nñÃöFm”¨Ë±Êâ"ŸÜI.”É'¹PUþøã¼›xÆ}];ö¹§ nlï±ÇiŸ}ö)êUnÀà ‚äK6©ìEÃÇ=ªÓŸþýû—Ò¾çxûløZ{ò¥…ÇòÏ ^?Ñ_&HnLµxN}!¹A”«ë· UòàÛo#©…vÀ f}÷ÿû_Uï‡uf_ˆ$¶‰'žØî¾ûîHzòº=óÌ3æ!ë¢$d‘è…—'˺/ ž™¿øc›5b¼ÚìmÑN^«~ÿý÷#‚@û¼C2µñœËë²$i‘ ˜3ÿY›%—€Ä­\è;íRZsÿ|]þM¿ðZ)x°¬ûãSXKÆ«œqÆc<×cìD"ÈW ÔãGc½þºam¸°Y-.ŒVx茑ñò³ÕW_=²×}i%Ö¹©Sé³ÖÜ8ÇÍXgÇ›ÿöÛoè YðXàSÈp‡ QÚrÁÛ Š8Î<ˆ Ñyê©§""OÒOÖøsaœ$w–ûIDˆ$;¾%Aä‡HQŽDŒ<òÈqŒëÑ”óÎ;/7§ß"0T ü_Lj¨vA7ïî÷L[$Ø•™êE¬wŒ’ÞH2£ (å—9u Õ"îˆF]®#Ѫ,¶9$œÛááW3'É!¦,ðâG\ Á"¡{^êô!‹+K ²ÿI΢ÝÖÞ?.,}ÐçîGXÈ'{œ‚1ãql—ë!„eªÇ¯^1`2¯z\Ê vÙP"y¥¾.‡(’ðF˜>ÑiÿÀøb©ãÎ;ïŒC„ä™3–x.l 1JyŒ´Ibag²ë×^{í˜?²à=#戯"ÐÌFó„àS0¹žú¹x”&ú„A— _ÍË™ñW]uU„ø="m2fž½öÚË<Ï –…òµú-C“€~hÒ×½ƒÁ‹——vµÂÚ.K–2/ßüÒçåZêvØ!²ÇûöíkÎlwÄžµR^ȬÉSðäÊ×!Òy1Úo¿ýb}›Lt²ãñ0ñÖXÇÅ€@@ñLYÎ^+íÒWÄaCdøVc’ûÓN.5ô‡âH¿0@hñÂØ¡”ëÑŸ²À×ãW«¿D-Xãf̹ÔâRølì°fNÖ9âéK$á‰c$0•…,}2ã‰Ä-Î9çÄX}™!ŒÖþ)ô‡þò·0º` ",‚O¡  ?¾µÀ·,è…¿'À3Â÷Ö‰î0WåèA%;®áÛˆ:ý°'Ëžë)xë›l²Iô£¦ü펨 Šz°@0ï¯[!¾v„ÁKª=8p`{šøÇ¯%!,{ÇõnŽwÍWâ©¶§  ˆLeÁƒ'ù¨CµBè}¤‘Fªvzˆ1ÚB )xZ^zÈ VÖËÇóïZü†´¿µ¸äû”ÿý÷áåÖbU®[­D`™Çš—DòuŒÙ¿ý÷ÈÇòo¾æÇ¹jF_³ËK0¹þà~–Çp¡ÍráЏ—¡òym‹ÀÐ"ÐòIZ½Ð}[M€  áÊöÖ+­´FÜâÛ^q§jâÎqB½õ Ñ…a¨W¯µçÊ&×T,ŽWÖãX¹Ôâ7¤ý­Å¥|¯¼ ¶¶Të†AÙ8 ß¡\깞੸sOÿJ^ùÖÅ6‘§z÷**jCþaøx{oǢ¯.mOÉë¸íiC׊€ˆ€t] ÑwݹéÔž5bˆ¾S¨qh2J²k² ÕpD@D@Dx=" " "Є$ðM8©’ˆ€ˆ€Hàõ ˆ€ˆ€ˆ@À7á¤jH" " " ×3 " " MH@ß„“ª!‰€ˆ€ˆ€^Ï€ˆ€ˆ€4! |Nª†$" " x=" " "Є$ðM8©’ˆ€ˆ€Hàõ ˆ€ˆ€ˆ@À7á¤jH" " " ×3Ð% |ýõ×]²_ê”´†ÀüÑšjª#J@ß©xÕøøý÷ßmï½÷¶ &˜Àæšk.›uÖYí¨£Ž*š¸ÿþûmöÙg/öË묳ŽuÖYåC¾}íµ×Úâ‹/Þé÷é 7H)Ùè£n}ôQÝîì°ÃvÄGÔ­3¤'ËœŸxâ »ì²Ë¢‰Ûn»Í\pÁØÞl³ÍìÄO¢¦Ï8ã {óÍ7ãšr»8øàƒmŽ9æˆç­ü\}øá‡¶þúëÛtÓMgË-·œ=þøãƒÜó’K.±M6Ù¤Åñ•W^Ù&›l²âçÜsÏó­i¯ECÚ!!àÿpUº!E]´Ëz¥•VJë­·^úöÛo£oŸ~úiòiºå–[bÿ„NH[mµUÕ~O5ÕTÉ_¶UÏuÖÁ=÷Ü3í¶ÛnÕ|—j×=ÒôÜsÏ ¶OóÏ?ºë®»[oH*”9/²È"éÆoŒË¿øâ‹ôî»ïƶ uñÜ´¦íO>ù$:ꨉqQÊížyæ™i饗N?ýôSúüóÏÓDM”^ýõ¨·ÄK¤SN9%¶¯¾úêä†hlóñä“O&74SÏž=ÓþóŸâ8ýo¼ñÒÇœ¸/?¿üòKœ¯×^Ñ€6D äÁ‰5¤ºFફ®²W_}Õ.ºè"m´Ñâ>þR´ÿýï6Ì0Ãľ¿@m '´¥–Z*¼ü“N:)Ž»A`ï½÷žÍ<óÌö×_E`ši¦±Yf™ÅŽ?þø¢Ï[l±…}öÙæ/s›x≠Ð_æáUá ~õÕWöÚk¯Ù²Ë.[\C¨Õ¡èÛûï¿o«­¶ZÜÛ {ä‘GlÎ9猺×]w]ÜŠ)¦°Ã?Ü~þùç8î"`Ûo¿½ýûßÿ¶qÇ×Ü °çŸÞæ™gëÓ§¹ñõ¸çz÷î^éõ×__ôaË-·4öñÿ©§žZœ»æšk¬oß¾æ"d[o½µ}öÙgqîûï¿7®›tÒIm•UV1<ÔÊòã?Úb‹-fx“\ÿì³ÏÚwÜíM=õÔvÌ1ÇQ ^3sC©ÕŸ?ÿü3Ɔ—ÿ™fšÉ˜3J½y¡½K/½4ørÈ!V‹³€öÐCÙŽ;îhnüÙÎ;ïø—_~ik¬±†¹`ǽÊÕæ¯}Þyçµ_ýÕ6Ø`«lw£6²+®¸ÂFqDsÌ1­GöÍ7ßD³xçÛm·]l3Ÿ.Þ±ýÁØ.»ìbD˜Ãü\p’çŒH}wƒÁÆ|~øáãºZíÅI}ˆ@{ ´Ñ0Ðe N «yðk¯½v:òÈ#ëR~ú铇MÓtÁJc=vÔ¿çž{’‡îcÛ=¹@'}&7’ brAsxbx˜?î¸ãÒXc•8à€äžZh¡ä/ÛôÃ?¤F!¹ Å5çŸ~Za…’ ]Z`’‹k"²À±á†.¹A~øáäË áÁá­á•]|ñÅqýN;í÷q!Nx™.‰HÅ[o½}pƒ!êíºë®iùå—Ož{íŒ3Î8é»ï¾‹s“L2Ir!NŒÓŠð9Á½Çúë®ãáýôpyr “>Uœä"•\äÒÀÓË/¿íá»h¦%—\2Ý~ûíq‘“£>:¶kõÎx¯ÜF{íµWr£#®©7/´ç˜n¾ùæôÎ;ïÔäüàƒFÿ`LaþàHËžtœôZóÂ\î¾ûîÑ7W¶›¯¿üòËcN˜/7^òáÄýy~ˆ.¹qÇóy7‚AŽBq’¨” i™e–I£Œ2JÜ»hÌ7ªµW>¯mh+kë…º®± t5Ÿm¶Ù’¯µÖ„êi¼8_xá…¨ƒH#n”c=6m¾ùæÅqÄŽ.‚:í´Ó¦ûî»/ÇáôÒK/E=÷þÓ|óÍÛ| ð7ÝtSì#8îEFøÖ=ÑôÔSO%÷[Ôw/y¤! ^Ü„usAÜW_}õØ…³¯çƶ{¶‰>ä°2}èׯ_ôp1¡Û\ÜëNî5Gˆ˜k^|ñÅ8•vÜ[Oo¼ñF'”ì‘‚W`¸0>üöÛoÁ *–>N?ýôä^v!^x`Qã‚ .HÛl³Mì{Ä!¹w_·?C3Î8cazè¡É#q=ý®6/ô£'aõ8c€aQ`8ÆcÄvyþãÀßõæêÿþQ³Ün¾žç£ƒeÀ€ùpüÆp˜rÊ)“G9‚^.J<3åây%éé§ŸŽCQˆ=FF.õÚËuô[ÚB W{#º¾1 øš¢‘Õ r„” SWd›|òÉí™gž‰¶ HT!Ì=à 3Ä6a`ÒØ&$NžBR“ K„‹¹žÄ(Ä9öW\qÅØö8æëËÒç€æž¡ù‹=Ž‘ØG(œD©\ÜÓŒ$,·„ê]Üò)󀹨Æ>÷É!uBà$Ò/ û,+ðÛ œÝÆ ÿ !R—)Û¬çâ^uñ"åëŸ\Ð>ðÀ±ÆÎ Ú=äN^¼¼saà 7Œ]Ä|Øa‡õj°~üöÛo›‡¤ a¢ðBfí>—[o½5ÖYYk÷0¯yè5ŸŠµV^ò´Øeñ¢ÏŒ'ú@F6ë·åë18Ü«³}÷Ý׸OY¼¸ƒÑõ(y´ r¸†µ]Ö~é+}b]›u_÷Ìc]ÕUWÍ·Žß´Åz31g훾Ðå•W^)Œ$‡GA¥˜æþPŸyÈ¢É>ã%¯ Þ¼Ð^6θ¦gÎQ—5nJù¾lo»í¶q<Ô›r6È^ÏFS¹]ž ´œOÇi§Íž|òÉñ<ñm‚<¯•_ç¤/åõwOŒ1‘‡A!G‚¾ñ¼·¦½¸H"ÐVmqûut4 /¼0ÖƒYóeýÛÅ%Î!^ãä/Úâ¶îY&°Èœf-œ¬dOÈKîAFB dBf¥ÝLHšÂº4×°ÞM¹òÊ+c½9vüÿn•Ü;LÜ3 Ë„TÝ ˆ5{ήeB¶µ{è±ÎïÆA¬Ç ÿpã%Ñ…°¹'ZEØÚ…12º=é-α~Κ;abÂæÕÆÍÚ1ë¹y­—±ù; Ös}ôÑ´ð ¡r–üë†Ñvþ€ÏH#9ùc>ï¼ób÷Þ{ïMž0˜XñäºÈ9àD­þN{,Pè_kæ…öX È¥g–dr&?K\G¦;sAîDe©5/¬¹³t“K¹]2ôÉ= ðL±ÔâI}±Ïóà_™‹m7„"€åŸrñhDäJäc´ÇZ}Κ'ßÁ“=ãtkÚËíè·´…€ÖàÛBM×t8ÄÌ=Öä¡éHXcMž¤;„ƒâÞV"),÷2Ã`}”ºÄ£À3¤CàX—'áŽÂ d4 kêîAÅ6ûì³O‹Ä'÷šS¯^½Šõmê°>îžf?F„gJ‡ˆsŽuWÖíùª÷f­š²ß~û%’çrApH¤¸§—úôé“OÅØiagí˜$7 ‰…ÕÆÍ9¾>Ƹsر^  B’YÐfÞ8é¬yÓv¹À±s¯5D.ß—10J­þAÿsAøh‡Ro^h/¯¿S·g$1:H Äˆò¥„1SkÚÈ¥Ö¼Ï@‚&Æ¥Ü.Ï!Ï I{‘CQ.±Q^—ÇXõ¨Cˆ<âOÂÆepí•ÛÖ¶´…@.j«÷¯ëD £ *ækO|©­Å“¹Œr[‹'‡E¨ºüNr[„w ÑV+í½/ëöü”ÃõÕîS>æâ!e–* køüä¯Vž¯µÏWÂ<­Öé6>µ8³ô0¤ã©v_`Dι”Êvë±#,ÏWòÜl5 0D}Âÿ•¥-íU¶¡}¨F@_ŠŽuK$ôñ½xÖŒ{챚BÞ-áhÐ"  G@ßpS¦w"dç“©Ýlgõ[튀ˆ@5øjTtLD@D@œ€þTmƒO º/" " ÕHà«QÑ1hpøŸ@u_D@D@ªÀW£¢c" " "Ðà$ð >꾈€ˆ€T# ¯FEÇD@D@D Á Hà|Õ}¨F@_ŠŽ‰€ˆ€ˆ@ƒÀ7øªû" " "P€¾' oð T÷E@D@D  |5*:&" "  N@ßà¨î‹€ˆ€ˆ@5øjTtLD@D@œ€¾Á'PÝj$ðը蘈€ˆ€48 |ƒO º/" " ÕHà«QÑ1hpøŸ@u_D@D@ªÀW£¢c" " "Ðà$ð >꾈€ˆ€T# ¯FEÇD@D@D Á Hà|Õ}¨F@_ŠŽ‰€ˆ€ˆ@ƒÀ7øªû" " "P€¾' oð T÷E@D@D  |5*:&" "  N@ßà¨î‹€ˆ€ˆ@5øjTtLD@D@œ€¾Á'PÝj$ðը蘈€ˆ€48 |ƒO º/" " ÕHà«QÑ1hpøŸ@u_D@D@ªÀW£¢c" " "Ðà$ð >꾈€ˆ€T# ¯FEÇD@D@D Á Hà|Õ}¨F@_ŠŽ‰€ˆ€ˆ@ƒÀ7øªû" " "P€¾' oð T÷E@D@D  |5*:&" "  N@ßà¨î‹€ˆ€ˆ@5øjTtLD@D@œ€¾Á'PÝj$ðը蘈€ˆ€48 |ƒO º/" " ÕHà«QÑ1hpøŸ@u_D@D@ªÀW£¢c" " "Ðà$ð >꾈€ˆ€T# ¯FEÇD@D@D Á Hà|Õ}¨F@_ŠŽ‰€ˆ€ˆ@ƒÀ7øªû" " "P€¾' oð T÷E@D@D  |5*:&" "  N@ßà¨î‹€ˆ€ˆ@5øjTtLD@D@œ€¾Á'PÝj$ðը蘈€ˆ€48 |ƒO º/" " ÕHà«QÑ1hpøŸ@u_D@D@ªÀW£¢c" " "Ðà$ð >꾈€ˆ€T# ¯FEÇD@D@D Á Hà|Õ}¨F@_ŠŽ‰€ˆ€ˆ@ƒøÉV—ÇÖLLIEND®B`‚rotl/vignettes/meta-analysis.Rmd.orig0000644000176200001440000002341215132142232017411 0ustar liggesusers--- title: "Using the Open Tree synthesis in a comparative analysis" author: "David Winter" date: "`r Sys.Date()`" output: rmarkdown::html_vignette: css: vignette.css vignette: > %\VignetteIndexEntry{Using the Open Tree synthesis in a comparative analysis} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} %\VignetteEncoding{UTF-8} --- ```{r setup, include=FALSE} knitr::opts_chunk$set(fig.path = "fig-vignettes-") ``` ## Phylogenetic Comparative Methods The development of phylogenetic comparative methods has made phylogenies and important source of data in fields as diverse as ecology, genomic and medicine. Comparative methods can be used to investigate patterns in the evolution of traits or the diversification of lineages. In other cases a phylogeny is treated as a "nuisance parameter", allowing with the autocorrelation created by the shared evolutionary history of the different species included to be controlled for. In many cases finding a tree that relates the species for which trait data are available is a rate-limiting step in such comparative analyses. Here we show how the synthetic tree provided by Open Tree of Life (and made available in R via `rotl`) can help to fill this gap. ## A phylogenetic meta-analysis To demonstrate the use of `rotl` in a comparative analysis, we will partially reproduce the results of [Rutkowska _et al_ 2014](https://doi.org/10.1111/jeb.12282). Very briefly, this study is a meta-analysis summarising the results of multiple studies testing for systematic differences in the size of eggs which contain male and female offspring. Such a difference might mean that birds invest more heavily in one sex than the other. Because this study involves data from 51 different species, Rutkowska _et al_ used a phylogenetic comparative approach to account for the shared evolutionary history among some of the studied-species. ### Gather the data If we are going to reproduce this analysis, we will first need to gather the data. Thankfully, the data is available as supplementary material from the publisher's website. We provide a copy of this data with the package: ```{r load-package} library(rotl) ``` ```{r egg_data} ## This dataset is available from the publisher's study website: egg_data <- read.csv(system.file("extdata", "egg.csv", package = "rotl"), stringsAsFactors = FALSE ) ## } head(egg_data) ``` The most important variable in this dataset is `Zr`, which is a [normalized effect size](https://en.wikipedia.org/wiki/Fisher_transformation) for difference ,in size between eggs that contain males and females. Values close to zero come from studies that found the sex of an egg's inhabitant had little effect in its size, while large positive or negative values correspond to studies with substantial sex biases (towards males and females respectively). Since this is a meta-analysis we should produce the classic [funnel plot](https://en.wikipedia.org/wiki/Funnel_plot) with effects-size on the y-axis and precision (the inverse of the sample standard error) on the x-axis. Here we calculate precision from the sample variance (`Vzr`): ```{r eggs_in_a_funnel, fig.width=6, fig.height=3} plot(1 / sqrt(egg_data$VZr), egg_data$Zr, pch = 16, ylab = "Effect size (Zr)", xlab = "Precision (1/SE)", main = "Effect sizes for sex bias in egg size among 51 brid species" ) ``` In order to use this data later on we need to first convert it to a standard `data.frame`. We can also convert the `animal` column (the species names) to lower case, and remove the underscores in their names, which will make it easier to match names later on: ```{r, clean_eggs} egg_data <- as.data.frame(egg_data) ## Convert taxon names to lower case egg_data$animal <- tolower(egg_data$animal) ## Let's remove the underscores (_) from the taxon names egg_data$animal <- gsub("_", " ", egg_data$animal) ``` ### Find the species in OTT We can use the OTL synthesis tree to relate these species. To do so we first need to find Open Tree Taxonomy (OTT) IDs for each species. We can do that with the Taxonomic Name Resolution Service function `tnrs_match_names`: ```{r birds} taxa <- tnrs_match_names(unique(egg_data$animal), context_name = "Animals") head(taxa) ``` All of these species are in OTT, but a few of them go by different names in the Open Tree than we have in our data set. Because the tree `rotl` fetches will have Open Tree names, we need to create a named vector that maps the names we have for each species to the names Open Tree uses for them: ```{r bird_map} taxon_map <- structure(taxa$search_string, names = taxa$unique_name) ``` Now we can use this map to retrieve "data set names" from "OTT names": ```{r odd_duck} taxon_map["Anser caerulescens"] ``` ### Get a tree Now we can get the tree. There are really too many tips here to show nicely, so we will leave them out of this plot ```{r birds_in_a_tree, fig.width=5, fig.height=5, fig.align='center'} tr <- tol_induced_subtree(ott_id(taxa)[is_in_tree(ott_id(taxa))]) plot(tr, show.tip.label = FALSE) ``` There are a few things to note here. First, the tree has no branch lengths. At present this is true for the whole of the Open Tree synthetic tree. Some comparative methods require either branch lengths or an ultrametric tree. Before you can use one of those methods you will need to get a tree with branch lengths. You could try looking for published trees made available by the Open Tree with `studies_find_trees`. Alternatively, you could estimate branch lengths from the toplogy of a phylogeny returned by `tol_induced_subtree`, perhaps by downloading DNA sequences from the NCBI with `rentrez` or "hanging" the tree on nodes of known-age using penalized likelihood method in `ape::chronos`. In this case, we will use only the topology of the tree as input to our comparative analysis, so we can skip these steps. Second, the tip labels contain OTT IDs, which means they will not perfectly match the species names in our dataset or the taxon map that we created earlier: ```{r tip_lab} tr$tip.label[1:4] ``` Finally, the tree contains node labels for those nodes that match a higher taxonomic group, and empty character vectors (`""`) for all other nodes. Some comparative methods either do no expect node labels at all, or require all labeled nodes to have a unique name (meaning multiple "empty" labels will cause and error). We can deal with all these details easily. `rotl` provides the convenience function `strip_ott_ids` to remove the extra information from the tip labels. With the IDs removed, we can use our taxon map to replace the tip labels in the tree with the species names from dataset. ```{r clean_tips} otl_tips <- strip_ott_ids(tr$tip.label, remove_underscores = TRUE) tr$tip.label <- taxon_map[ otl_tips ] ``` Finally, we can remove the node labels by setting the `node.label` attribute of the tree to `NULL`. ```{r remove_nodes} tr$node.label <- NULL ``` ```{r match_species_tree} egg_data <- egg_data[egg_data$animal %in% tr$tip.label, ] ``` ### Perform the meta-analysis Now we have data and a tree, and we know the names in the tree match the ones in the data. It's time to do the comparative analysis. Rutkowska _et al_. used `MCMCglmm`, a Bayesian MCMC approach to fitting multi-level models,to perform their meta-analysis, and we will do the same. Of course, to properly analyse these data you would take some care in deciding on the appropriate priors to use and inspect the results carefully. In this case, we are really interested in using this as a demonstration, so we will just run a simple model. Specifically we sill fit a model where the only variable that might explain the values of `Zr` is the random factor `animal`, which corresponds to the phylogenetic relationships among species. We also provide `Zvr` as the measurement error variance, effectively adding extra weight to the results of more powerful studies. Here's how we specify and fit that model with `MCMCglmm`: ```{r model} set.seed(123) if (require(MCMCglmm, quietly = TRUE)) { pr <- list( R = list(V = 1, nu = 0.002), G = list(G1 = list(V = 1, nu = 0.002)) ) model <- MCMCglmm(Zr ~ 1, random = ~animal, pedigree = tr, mev = egg_data$VZr, prior = pr, data = egg_data, verbose = FALSE ) } else { model <- readRDS(file = system.file("extdata", "mcmcglmm_model.rds", package = "rotl")) } ``` Now that we have a result we can find out how much phylogenetic signal exists for sex-biased differences in egg-size. In a multi-level model we can use variance components to look at this, specifically the proportion of the total variance that can be explained by phylogeny is called the phylogenetic reliability, _H_. Let's calculate the _H_ for this model: ```{r PhyH} var_comps <- colMeans(model$VCV) var_comps["animal"] / sum(var_comps) ``` It appears there is almost no phylogenetic signal to the data. The relationships among species explain much less that one percent of the total variance in the data. If you were wondering, Rutkowska _et al_. report a similar result, even after adding more predictors to their model most of the variance in `Zr` was left unexplained. ## What other comparative methods can I use in R? Here we have demonstrated just one comparative analysis that you might do in R. There are an ever-growing number of packages that allow an ever-growing number of analysis to performed in R. Some "classics" like ancestral state reconstruction, phylogenetic independent contrasts and lineage through time plots are implemented in `ape`. Packages like `phytools`, `caper` and `diversitree` provide extensions to these methods. The [CRAN Phylogenetics Taskview](https://github.com/bomeara/PhylogeneticsTaskView/blob/main/Phylogenetics.md) gives a good idea of the diversity of packages and analyses that can be completed in R (note that this links to a draft of the next version of the Taskview as it is currently unavailable from CRAN). rotl/NAMESPACE0000644000176200001440000000620415132136164012455 0ustar liggesusers# Generated by roxygen2: do not edit by hand S3method("[",otl_ott_id) S3method(candidate_for_synth,study_meta) S3method(flags,match_names) S3method(flags,taxon_info) S3method(flags,taxon_mrca) S3method(get_publication,study_meta) S3method(get_study_year,study_meta) S3method(get_tree_ids,study_meta) S3method(inspect,match_names) S3method(is_in_tree,default) S3method(is_in_tree,otl_ott_id) S3method(is_suppressed,match_names) S3method(is_suppressed,taxon_info) S3method(is_suppressed,taxon_mrca) S3method(list_trees,matched_studies) S3method(ott_id,match_names) S3method(ott_id,taxon_info) S3method(ott_id,taxon_mrca) S3method(ott_id,tol_mrca) S3method(ott_id,tol_node) S3method(ott_id,tol_summary) S3method(print,study_external_data) S3method(print,study_ids) S3method(print,study_meta) S3method(print,tnrs_contexts) S3method(print,tol_mrca) S3method(print,tol_node) S3method(print,tol_summary) S3method(source_list,tol_mrca) S3method(source_list,tol_node) S3method(source_list,tol_summary) S3method(synonyms,match_names) S3method(synonyms,taxon_info) S3method(tax_lineage,taxon_info) S3method(tax_lineage,tol_node) S3method(tax_name,match_names) S3method(tax_name,taxon_info) S3method(tax_name,taxon_mrca) S3method(tax_name,tol_mrca) S3method(tax_name,tol_node) S3method(tax_name,tol_summary) S3method(tax_rank,match_names) S3method(tax_rank,taxon_info) S3method(tax_rank,taxon_mrca) S3method(tax_rank,tol_mrca) S3method(tax_rank,tol_node) S3method(tax_rank,tol_summary) S3method(tax_sources,match_names) S3method(tax_sources,taxon_info) S3method(tax_sources,taxon_mrca) S3method(tax_sources,tol_mrca) S3method(tax_sources,tol_node) S3method(tax_sources,tol_summary) S3method(tol_lineage,tol_node) S3method(unique_name,match_names) S3method(unique_name,taxon_info) S3method(unique_name,taxon_mrca) S3method(unique_name,tol_mrca) S3method(unique_name,tol_node) S3method(unique_name,tol_summary) S3method(update,match_names) export(candidate_for_synth) export(flags) export(get_publication) export(get_study) export(get_study_meta) export(get_study_subtree) export(get_study_tree) export(get_study_year) export(get_tree_ids) export(inspect) export(is_in_tree) export(is_suppressed) export(list_trees) export(ott_id) export(source_list) export(strip_ott_ids) export(studies_find_studies) export(studies_find_trees) export(studies_properties) export(study_external_IDs) export(synonyms) export(tax_lineage) export(tax_name) export(tax_rank) export(tax_sources) export(taxon_external_IDs) export(taxonomy_about) export(taxonomy_mrca) export(taxonomy_subtree) export(taxonomy_taxon_info) export(tnrs_contexts) export(tnrs_infer_context) export(tnrs_match_names) export(tol_about) export(tol_induced_subtree) export(tol_lineage) export(tol_mrca) export(tol_node_info) export(tol_subtree) export(unique_name) import(ape) importFrom(httr,GET) importFrom(httr,POST) importFrom(httr,content) importFrom(httr,parse_url) importFrom(jsonlite,fromJSON) importFrom(jsonlite,toJSON) importFrom(jsonlite,unbox) importFrom(rentrez,entrez_link) importFrom(rentrez,entrez_search) importFrom(rlang,interrupt) importFrom(rncl,read_newick_phylo) importFrom(stats,na.omit) importFrom(stats,setNames) importFrom(stats,update) rotl/LICENSE0000644000176200001440000000011715132136164012240 0ustar liggesusersYEAR: 2017 COPYRIGHT HOLDER: Francois Michonneau, Joseph W. Brown, David Winterrotl/NEWS.md0000644000176200001440000001640215132136473012340 0ustar liggesusers# rotl 3.1.1 * Update formatting of the documentation to solve CRAN checks (#148 by @villegar). # rotl 3.1.0 ## Breaking change * `tnrs_match_names` now returns the taxon with the highest matching score instead of the one with the lowest OTT id (issues #127 and #143 reported by @ajrominger). # rotl 3.0.14 * Make sure that the package fails gracefully when there is no internet connection. * The vignettes are now pre-computed. # rotl 3.0.12 * The default argument `context_name` for the function `tnrs_match_names` was changed from `NULL` to `All life`. This changes is made to address what could lead to unexpected results. Previously, the context was inferred based on the first match when several names were provided (see #134 reported by @LunaSare, and https://github.com/OpenTreeOfLife/feedback/issues/528)/ * The "Suggest" dependency `fulltext` was removed following its archival from CRAN. # rotl 3.0.11 ## Other changes * When none of the names provided to `tnrs_match_names` had a match in the Open Tree of Life, an error was thrown and nothing was returned. To make the behavior of the function more consistent with other situations, when none of the names provided have a match, a tibble is returned and a warning is issued. ## Bug Fix * When attempting to match a name that did not exist in the tree, an error was thrown (bug #128, PR #129, @daijiang) # rotl 3.0.10 * Small fixes following updates to the Open Tree of Life API (no visible change for users). * Updated documentation to reflect new value in output of `tol_node_info()`. # rotl 3.0.9 * Small fixes following updates to the Open Tree of Life API. # rotl 3.0.7 * Minor update to vignette to address change to TNRS endpoint (underscores can't be included in the taxon names anymore). # rotl 3.0.6 * Minor update to address warnings seen on CRAN. # rotl 3.0.5 ## New features * The data types in the data frame returned by `tnrs_match_names` are consistent, and remain the same even after using `update()`. ## Other changes * Small internal changes that reflect changes in the data structures returned by the API. # rotl 3.0.4 ## New features * To improve stability of results across releases of the Open Tree Taxonomy, the TNRS match with the lowest OTT id is returned instead of the first one in case a name is shared across multiple domains (related to #88) * A warning is issued when users attempt to use TNRS on duplicated names. ## Other changes * Fix typos and workaround broken API to retrieve supplementary materials in vignette. # rotl 3.0.3 ## New features * The function `get_study_subtree` gains the argument `tip_label` to control the formatting of the tip labels, #90, reported by @bomeara * The new function `is_in_tree` takes a list of OTT ids (i.e., the output of `ott_id()`), and returns a vector of logical indicating whether they are included in the synthetic tree (workaround #31). ## Bug fixes * The function `get_study_subtree` ignored the argument `subtree_id`, #89 reported by @bomeara ## Other chaanges * `citation("rotl")` now includes the reference to the Open Tree of Life publication. * The "How to use rotl?" vignette was updated to document the behavior of v3 of the OTL API which returns an HTTP error code 400 when the request for induced subtree includes taxa that are not in the synthetic tree (fix #84) # rotl 3.0.1 * Fix tests and vignette to reflect changes accompanying release 6.1 of the synthetic tree * Add section in vignette "How to use rotl?" about how to get the higher taxonomy from a given taxon. * Add `CITATION` file with MEE manuscript information (#82) # rotl 3.0.0 * `rotl` now interacts with v3.0 of the Open Tree of Life APIs. The documentation has been updated to reflect the associated changes. More information about the v3.0 of the Open Tree of Life APIs can be found [on their wiki](https://github.com/OpenTreeOfLife/germinator/wiki/Open-Tree-of-Life-Web-APIs). ## New features * New methods: `tax_sources`, `is_suppressed`, `tax_rank`, `unique_name`, `name`, `ott_id`, for objects returned by `tnrs_match_names()`, `taxonomy_taxon_info()`, `taxonomy_taxon_mrca()`, `tol_node_info()`, `tol_about()`, and `tol_mrca()`. Each of these methods have their own class. * New method `tax_lineage()` to extract the higher taxonomy from an object returned by `taxonomy_taxon_info()` (initially suggested by Matt Pennell, #57). * New method `tol_lineage()` to extract the nodes towards the root of the tree. * New print methods for `tol_node_info()` and `tol_mrca()`. * New functions `study_external_IDs()` and `taxon_external_IDs()` that return the external identifiers for a study and associated trees (e.g., DOI, TreeBase ID); and the identifiers of taxon names in taxonomic databases. The vignette "Data mashup" includes an example on how to use it. * The function `strip_ott_id()` gains the argument `remove_underscores` to remove underscores from tips in trees returned by OTL. ## Changes * Rename method `ott_taxon_name()` to `tax_name()` for consistency. * Rename method `synth_sources()` and `study_list()` to `source_list()`. * Refactor how result of query is checked and parsed (invisible to the user). ## Bug fixes * Fix bug in `studies_find_studies()`, the arguments `verbose` and `exact` were ignored. * The argument `only_current` has been dropped for the methods associated with objects returned by `tnrs_match_names()` * The print method for `tnrs_context()` duplicated some names. * `inspect()`, `update()` and `synonyms()` methods for `tnrs_match_names()` did not work if the query included unmatched taxa. # rotl 0.5.0 * New vignette: `meta-analysis` * Added arguments `include_lineage` and `list_terminal_descendants` to `taxonomy_taxon()` * Improve warning and format of the result if one of the taxa requested doesn't match anything `tnrs_match_names`. * In the data frame returned by `tnrs_match_names`, the columns `approximate_match`, `is_synonym` and `is_deprecated` are now `logical` (instead of `character`) [issue #54] * New utility function `strip_ott_ids` removes OTT id information from a character vector, making it easier to match tip labels in trees returned by `tol_induced_subtree` to taxonomic names in other data sources. This function can also remove underscores from the taxon names. * New method `list_trees` returns a list of tree ids associated with studies. The function takes the output of `studies_find_studies` or `studies_find_trees`. * `studies_find_studies` and `studies_find_trees` gain argument `detailed` (default set to `TRUE`), that produces a data frame summarizing information (title of the study, year of publication, DOI, ids of associated trees, ...) about the studies matching the search criteria. * `get_study_tree` gains argument `deduplicate`. When `TRUE`, if the tree returned for a given study contains duplicated tip labels, they will be made unique before being parsed by NCL by appending a suffix (`_1`, `_2`, `_3`, etc.). (#46, reported by @bomeara) * New method `get_study_year` for objects of class `study_meta` that returns the year of publication of the study. * A more robust approach is used by `get_tree_ids` to identify the tree ids in the metadata returned by the API # rotl 0.4.1 * Initial CRAN release on July, 24th 2015 rotl/inst/0000755000176200001440000000000015132222605012205 5ustar liggesusersrotl/inst/CITATION0000644000176200001440000000327115132136164013351 0ustar liggesusersc( bibentry( header = "To cite rotl in publications use:", bibtype = "Article", title = "{rotl}: an R package to interact with the Open Tree of Life data", author = c( as.person("Francois Michonneau"), as.person("Joseph W. Brown"), as.person("David J. Winter") ), journal = "Methods in Ecology and Evolution", year = "2016", volume = "7", number = "12", pages = "1476-1481", doi = "10.1111/2041-210X.12593", textVersion = paste("Michonneau, F., Brown, J. W. and Winter, D. J. (2016), rotl: an R package to interact with the Open Tree of Life data. Methods in Ecology and Evolution. 7(12):1476-1481. doi:10.1111/2041-210X.12593") ), bibentry( header = "You should also cite the source data from the Open Tree of Life", title = "Open Tree of Life Synthetic Tree", bibtype = "misc", author = c( as.person("OpenTreeOfLife"), as.person("Benjamin Redelings"), as.person("Luna Luisa Sanchez Reyes"), as.person("Karen A. Cranston"), as.person("Jim Allman"), as.person("Mark T. Holder"), as.person("Emily Jane McTavish")), year = "2019", version = "12.3", publisher = "Zenodo", doi = "10.5281/zenodo.3937741", url = "https://doi.org/10.5281/zenodo.3937741", textVersion = paste("OpenTree et al. Open Tree of Life Synthetic Tree. doi:0.5281/zenodo.39377411") ) ) rotl/inst/doc/0000755000176200001440000000000015132222605012752 5ustar liggesusersrotl/inst/doc/data_mashups.html0000644000176200001440000021350315132222604016314 0ustar liggesusers Connecting data to Open Tree trees

Connecting data to Open Tree trees

David Winter

2026-01-15

Combining data from OToL and other sources.

One of the major goals of rotl is to help users combine data from other sources with the phylogenetic trees in the Open Tree database. This examples document describes some of the ways in which a user might connect data to trees from Open Tree.

Get Open Tree IDs to match your data.

Let’s say you have a dataset where each row represents a measurement taken from one species, and your goal is to put these measurements in some phylogenetic context. Here’s a small example: the best estimate of the mutation rate for a set of unicellular Eukaryotes along with some other property of those species which might explain the mutation rate:

csv_path <- system.file("extdata", "protist_mutation_rates.csv", package = "rotl")
mu <- read.csv(csv_path, stringsAsFactors = FALSE)
mu
##                     species       mu pop.size genome.size
## 1   Tetrahymena thermophila 7.61e-12 1.12e+08    1.04e+08
## 2    Paramecium tetraurelia 1.94e-11 1.24e+08    7.20e+07
## 3 Chlamydomonas reinhardtii 2.08e-10 1.00e+08    1.12e+08
## 4  Dictyostelium discoideum 2.90e-11 7.40e+06    3.40e+07
## 5  Saccharomyces cerevisiae 3.30e-10 1.00e+08    1.25e+08
## 6       Saccharomyces pombe 2.00e-10 1.00e+07    1.25e+08

If we want to get a tree for these species we need to start by finding the unique ID for each of these species in the Open Tree database. We can use the Taxonomic Name Resolution Service (tnrs) functions to do this. Before we do that we should see if any of the taxonomic contexts, which can be used to narrow a search and avoid conflicts between different codes, apply to our group of species:

library(rotl)
tnrs_contexts()
## Possible contexts:
##    Animals 
##       Birds, Tetrapods, Mammals, Amphibians, Vertebrates 
##       Arthropods, Molluscs, Nematodes, Platyhelminthes, Annelids 
##       Cnidarians, Arachnids, Insects 
##    Fungi 
##       Basidiomycetes, Ascomycetes 
##    All life 
##    Bacteria 
##       SAR group, Archaea, Excavata, Amoebozoa, Centrohelida 
##       Haptophyta, Apusozoa, Diatoms, Ciliates, Forams 
##    Land plants 
##       Hornworts, Mosses, Liverworts, Vascular plants, Club mosses 
##       Ferns, Seed plants, Flowering plants, Monocots, Eudicots 
##       Rosids, Asterids, Asterales, Asteraceae, Aster 
##       Symphyotrichum, Campanulaceae, Lobelia

Hmm, none of those groups contain all of our species. In this case we can search using the All life context and the function tnrs_match_names:

taxon_search <- tnrs_match_names(names = mu$species, context_name = "All life")
knitr::kable(taxon_search)
search_string unique_name approximate_match score ott_id is_synonym flags number_matches
tetrahymena thermophila Tetrahymena thermophila FALSE 1 180195 FALSE 1
paramecium tetraurelia Paramecium tetraurelia FALSE 1 568130 FALSE 1
chlamydomonas reinhardtii Chlamydomonas reinhardtii FALSE 1 33153 FALSE 1
dictyostelium discoideum Dictyostelium discoideum FALSE 1 160850 FALSE 1
saccharomyces cerevisiae Saccharomyces cerevisiae FALSE 1 356221 FALSE 1
saccharomyces pombe Schizosaccharomyces pombe FALSE 1 990004 TRUE 1

Good, all of our species are known to Open Tree. Note, though, that one of the names is a synonym. Saccharomyces pombe is older name for what is now called Schizosaccharomyces pombe. As the name suggests, the Taxonomic Name Resolution Service is designed to deal with these problems (and similar ones like misspellings), but it is always a good idea to check the results of tnrs_match_names closely to ensure the results are what you expect.

In this case we have a good ID for each of our species so we can move on. Before we do that, let’s ensure we can match up our original data to the Open Tree names and IDs by adding them to our data.frame:

mu$ott_name <- unique_name(taxon_search)
mu$ott_id <- taxon_search$ott_id

Find a tree with your taxa

Now let’s find a tree. There are two possible options here: we can search for published studies that include our taxa or we can use the ‘synthetic tree’ from Open Tree. We can try both approaches.

Published trees

Before we can search for published studies or trees, we should check out the list of properties we can use to perform such searches:

studies_properties()
## $tree_properties
##  [1] "ot:specifiedRoot"                 "ot:unrootedTree"                  "ot:nodeLabelTimeUnit"             "xsi:type"                         "ot:MRCAName"                      "ot:nodeLabelDescription"          "ot:nearestTaxonMRCAOttId"        
##  [8] "ot:reasonsToExcludeFromSynthesis" "ot:curatedType"                   "ot:nearestTaxonMRCAName"          "ot:studyId"                       "ot:nodeLabelMode"                 "rootedge"                         "nodeById"                        
## [15] "tb:type.tree"                     "ot:branchLengthDescription"       "ot:messages"                      "ot:rootNodeId"                    "ot:inGroupClade"                  "ot:ottId"                         "ot:branchLengthMode"             
## [22] "ot:MRCAOttId"                     "ot:ottTaxonName"                  "tb:quality.tree"                  "tb:kind.tree"                     "ot:outGroupEdge"                  "ntips"                            "edgeBySourceId"                  
## [29] "label"                            "meta"                             "tb:ntax.tree"                     "ot:tag"                           "ot:branchLengthTimeUnit"         
## 
## $study_properties
##  [1] "tb:identifier.study.tb1"       "id"                            "ot:taxonLinkPrefixes"          "ot:studyYear"                  "prism:publicationName"         "dc:title"                      "prism:creationDate"            "xmlns"                        
##  [9] "skos:changeNote"               "skos:historyNote"              "ot:notIntendedForSynthesis"    "ot:otusElementOrder"           "dc:date"                       "xhtml:license"                 "prism:startingPage"            "prism:publicationDate"        
## [17] "ot:focalCladeOTTTaxonName"     "prism:section"                 "prism:pageRange"               "ot:messages"                   "ot:studyPublicationReference"  "ot:curatorName"                "ot:dataDeposit"                "prism:number"                 
## [25] "ot:agents"                     "dc:publisher"                  "treesById"                     "dcterms:bibliographicCitation" "ot:treesElementOrder"          "prism:modificationDate"        "tb:identifier.study"           "about"                        
## [33] "ntrees"                        "nexmljson"                     "ot:comment"                    "dc:contributor"                "dc:creator"                    "prism:volume"                  "tb:title.study"                "treebaseId"                   
## [41] "prism:endingPage"              "generator"                     "version"                       "ot:studyId"                    "ot:candidateTreeForSynthesis"  "otusById"                      "prism:doi"                     "dc:subject"                   
## [49] "ot:studyPublication"           "ot:focalClade"                 "ot:annotationEvents"           "ot:tag"                        "nexml2json"

We have ottIds for our taxa, so let’s use those IDs to search for trees that contain them. Starting with our first species Tetrahymena thermophila we can use studies_find_trees to do this search.

studies_find_trees(property = "ot:ottId", value = as.character(ott_id(taxon_search)[1]))
##    study_ids n_trees                       tree_ids candidate study_year                                                                                                                                 title                                     study_doi
## 1    ot_1587       1                          tree1                 2015 'Phylogenomic analyses reveal subclass Scuticociliatia as the sister group of subclass Hymenostomatia within class Oligohymenophorea' http://dx.doi.org/10.1016/j.ympev.2015.05.007
## 2    ot_1589       1                          tree1                 2015 'Phylogenomic analyses reveal subclass Scuticociliatia as the sister group of subclass Hymenostomatia within class Oligohymenophorea' http://dx.doi.org/10.1016/j.ympev.2015.05.007
## 3    ot_2037       4 tree10, tree11, tree12, tree13                 2018                                                                                                                                         http://dx.doi.org/10.1038/s41586-018-0708-8
## 4     ot_409       2                   tree1, tree2     tree2       2015                                                                        Tree of life reveals clock-like speciation and diversification       http://dx.doi.org/10.1093/molbev/msv037
## 5     ot_564       1                        Tr85317   Tr85317       2015    'The alveolate translation initiation factor 4E family reveals a custom toolkit for translational control in core dinoflagellates'   http://dx.doi.org/10.1186/s12862-015-0301-9
## 6     ot_579       1                        Tr60046                 2013                                      'Convergent evolution of heat-inducibility during subfunctionalization of the Hsp70 gene family'     http://dx.doi.org/10.1186/1471-2148-13-49
## 7     ot_700       1                          tree1     tree1       2016                                                                                                      'A new view of the tree of life'  http://dx.doi.org/10.1038/nmicrobiol.2016.48
## 8      ot_73       1                          tree1     tree1       2013                                          Deep relationships of Rhizaria revealed by phylogenomics: A farewell to Haeckel’s Radiolaria http://dx.doi.org/10.1016/j.ympev.2012.12.011
## 9     ot_766       1                        Tr85440                 2015                                                                                'Bacterial proteins pinpoint a single eukaryotic root'     http://dx.doi.org/10.1073/pnas.1420657112
## 10    ot_767       1                          tree1     tree1       2016                 'Untangling the early diversification of eukaryotes: a phylogenomic study of the evolutionary origins of Centrohelida      http://dx.doi.org/10.1098/rspb.2015.2802
## 11     ot_87       1                        Tr64119   Tr64119       2014                        'Dinoflagellate phylogeny revisited: Using ribosomal proteins to resolve deep branching dinoflagellate clades' http://dx.doi.org/10.1016/j.ympev.2013.10.007
##    n_matched_trees         match_tree_ids
## 1                1                  tree1
## 2                1                  tree1
## 3                3 tree10, tree13, tree11
## 4                1                  tree2
## 5                1                Tr85317
## 6                1                Tr60046
## 7                1                  tree1
## 8                1                  tree1
## 9                1                Tr85440
## 10               1                  tree1
## 11               1                Tr64119
##  [ reached 'max' / getOption("max.print") -- omitted 16 rows ]

Well… that’s not very promising. We can repeat that process for all of the IDs to see if the other species are better represented.

hits <- lapply(mu$ott_id, studies_find_trees, property = "ot:ottId", detailed = FALSE)
sapply(hits, function(x) sum(x[["n_matched_trees"]]))
## [1]  51  51 128  71  18  89

OK, most of our species are not in any of the published trees available. You can help fix this sort of problem by making sure you submit your published trees to Open Tree.

A part of the synthesis tree

Thankfully, we can still use the complete Tree of Life made from the combined results of all of the published trees and taxonomies that go into Open Tree. The function tol_induced_subtree will fetch a tree relating a set of IDs.

Using the default arguments you can get a tree object into your R session:

ott_in_tree <- ott_id(taxon_search)[is_in_tree(ott_id(taxon_search))]
tr <- tol_induced_subtree(ott_ids = ott_in_tree)
## Warning in collapse_singles(tr, show_progress): Dropping singleton nodes with labels: mrcaott2ott276, mrcaott2ott142555, mrcaott2ott1551, mrcaott2ott7623, Chloroplastida ott361838, Chlorophyta ott979501, mrcaott185ott42071, mrcaott185ott1426, mrcaott1426ott1544,
## mrcaott1544ott8659, mrcaott1544ott15345, mrcaott1544ott9282, mrcaott9389ott818260, mrcaott9389ott23557, mrcaott23557ott527099, mrcaott148ott902, SAR ott5246039, Alveolata ott266751, Ciliophora (phylum in subkingdom SAR) ott302424, Intramacronucleata ott340382,
## mrcaott1546ott1671, Conthreep ott5248773, mrcaott1671ott16129, Peniculia ott1002116, Paramecium (genus in subkingdom SAR) ott568126, mrcaott11752ott13570, Hymenostomatia ott5257367, Tetrahymena (genus in subkingdom SAR) ott47284, mrcaott295406ott523463,
## mrcaott295406ott523462, mrcaott3973ott4738988, Amoebozoa ott1064655, mrcaott3973ott15653, mrcaott3973ott26103, mrcaott26103ott273110, mrcaott26103ott229626, Dictyostelia ott835575, mrcaott26103ott59686, Dictyosteliales ott4008839, Dictyosteliaceae ott4008841,
## Dictyostelium ott999665, mrcaott42ott240665, Opisthokonta ott332573, Nucletmycea ott5246132, Fungi ott352914, mrcaott109ott3465, mrcaott109ott67172, mrcaott109ott1423, mrcaott109ott9352, h2007-2 ott5576447, h2007-1 ott5584405, Dikarya ott656316,
## mrcaott235ott3445, saccharomyceta ott1098854, Saccharomycotina ott971714, Saccharomycetes (class in h2007-2) ott989999, Saccharomycetales ott4085960, Saccharomycetaceae ott989994, Saccharomyces ott908546, Schizosaccharomycetes ott921286, Schizosaccharomycetidae
## ott5670481, Schizosaccharomycetales ott508517, Schizosaccharomycetaceae ott990009, Schizosaccharomyces ott990008
plot(tr)
plot of chunk subtree
plot of chunk subtree

Connect your data to the tips of your tree

Now we have a tree for of our species, how can we use the tree and the data together?

The package phylobase provide an object class called phylo4d, which is designed to represent a phylogeny and data associated with its tips. In order to get our tree and data into one of these objects we have to make sure the labels in the tree and in our data match exactly. That’s not quite the case at the moment (tree labels have underscores and IDs appended):

mu$ott_name[1]
## $`Tetrahymena thermophila`
## [1] "Tetrahymena thermophila"
tr$tip.label[4]
## [1] "Dictyostelium_discoideum_ott160850"

rotl provides a convenience function strip_ott_ids to deal with these.

tr$tip.label <- strip_ott_ids(tr$tip.label, remove_underscores = TRUE)
tr$tip.label %in% mu$ott_name
## [1] TRUE TRUE TRUE TRUE TRUE TRUE

Ok, now the tips are together we can make a new dataset. The phylo4d() functions matches tip labels to the row names of a data.frame, so let’s make a new dataset that contains just the relevant data and has row names to match the tree

library(phylobase)
## Error in `library()`:
## ! there is no package called 'phylobase'
mu_numeric <- mu[, c("mu", "pop.size", "genome.size")]
rownames(mu_numeric) <- mu$ott_name
tree_data <- phylo4d(tr, mu_numeric)
## Error in `phylo4d()`:
## ! could not find function "phylo4d"

And now we can plot the data and the tree together

plot(tree_data)
## Error:
## ! object 'tree_data' not found

Find external data associated with studies, trees and taxa from Open Tree

In the above example we looked for a tree that related species in another dataset. Now we will go the other way, and try to find data associated with Open Tree records in other databases.

Get external data from a study

Let’s imagine you were interested in extending or reproducing the results of a published study. If that study is included in Open Tree you can find it via studies_find_studies or studies_find_trees and retrieve the published trees with get_study. rotl will also help you find external. The function study_external_IDs retrieves the DOI for a given study, and uses that to gather some more data:

extra_data <- try(study_external_IDs("pg_1980"), silent = TRUE)
## Warning in check_xml_errors(x): Invalid db name specified: popset
if (!inherits(extra_data, "try-error")) {
  extra_data
}

Here the returned object contains an external_data_url (in this case a link to the study in Treebase), a pubmed ID for the paper and a vector IDs for the NCBI’s nucleotide database. The packages treebase and rentrez provide functions to make use of these IDs within R.

As an example, let’s use rentrez to download the first two DNA seqences and print them.

library(rentrez)
seqs <- try(entrez_fetch(db = "nucleotide", id = extra_data$nucleotide_ids[1:2], rettype = "fasta"), silent = TRUE)

if (inherits(seqs, "try-error")) {
  cat("NCBI temporarily down.")
} else {
  cat(seqs)
}
## NCBI temporarily down.

You could further process these sequences in R with the function read.dna from ape or save them to disk by specifying a file name with cat.

Find a OTT taxon in another taxonomic database

It is also possible map an Open Tree taxon to a record in another taxonomic database. For instance, if we wanted to search for data about one of the tips of the sub-tree we fetched in the example above we could do so using taxon_external_IDs:

Tt_ids <- taxon_external_IDs(mu$ott_id[2])
Tt_ids
##   source       id
## 1  silva AY102613
## 2   ncbi     5888
## 3   gbif  7415807

A user could then use rgbif to find locality records using the gbif ID or rentrez to get genetic or bibliometric data about from the NCBI’s databases.

What next

The demonstration gets you to the point of visualizing your data in a phylogenetic context. But there’s a lot more you do with this sort of data in R. For instance, you could use packages like ape, caper, phytools and mcmcGLMM to perform phylogenetic comparative analyses of your data. You could gather more data on your species using packages that connect to trait databases like rfishbase, AntWeb or rnpn which provides data from the US National Phenology Network. You could also use rentrez to find genetic data for each of your species, and use that data to generate branch lengths for the phylogeny.

rotl/inst/doc/rotl.html0000644000176200001440000037461115132222605014634 0ustar liggesusers How to use rotl?

How to use rotl?

François Michonneau

2026-01-15

rotl provides an interface to the Open Tree of Life (OTL) API and allows users to query the API, retrieve parts of the Tree of Life and integrate these parts with other R packages.

The OTL API provides services to access:

  • the Tree of Life a.k.a. TOL (the synthetic tree): a single draft tree that is a combination of the OTL taxonomy and the source trees (studies)
  • the Taxonomic name resolution services a.k.a. TNRS: the methods for resolving taxonomic names to the internal identifiers used by the TOL and the GOL (the ott ids).
  • the Taxonomy a.k.a. OTT (for Open Tree Taxonomy): which represents the synthesis of the different taxonomies used as a backbone of the TOL when no studies are available.
  • the Studies containing the source trees used to build the TOL, and extracted from the scientific literature.

In rotl, each of these services correspond to functions with different prefixes:

Service rotl prefix
Tree of Life tol_
TNRS tnrs_
Taxonomy taxonomy_
Studies studies_

rotl also provides a few other functions and methods that can be used to extract relevant information from the objects returned by these functions.

Demonstration of a basic workflow

The most common use for rotl is probably to start from a list of species and get the relevant parts of the tree for these species. This is a two step process:

  1. the species names need to be matched to their ott_id (the Open Tree Taxonomy identifiers) using the Taxonomic name resolution services (TNRS)
  2. these ott_id will then be used to retrieve the relevant parts of the Tree of Life.

Step 1: Matching taxonomy to the ott_id

Let’s start by doing a search on a diverse group of taxa: a tree frog (genus Hyla), a fish (genus Salmo), a sea urchin (genus Diadema), and a nautilus (genus Nautilus).

library(rotl)
taxa <- c("Hyla", "Salmo", "Diadema", "Nautilus")
resolved_names <- tnrs_match_names(taxa)

It’s always a good idea to check that the resolved names match what you intended:

search_string unique_name approximate_match score ott_id is_synonym flags number_matches
hyla Hyla FALSE 1 1062216 FALSE 1
salmo Salmo FALSE 1 982359 FALSE 1
diadema Diadema FALSE 1 4930522 FALSE 4
nautilus Nautilus FALSE 1 616358 FALSE 1

The column unique_name sometimes indicates the higher taxonomic level associated with the name. The column number_matches indicates the number of ott_id that corresponds to a given name. In this example, our search on Diadema returns 2 matches, and the one returned by default is indeed the sea urchin that we want for our query. The argument context_name allows you to limit the taxonomic scope of your search. Diadema is also the genus name of a fungus. To ensure that our search is limited to animal names, we could do:

resolved_names <- tnrs_match_names(taxa, context_name = "Animals")

If you are trying to build a tree with deeply divergent taxa that the argument context_name cannot fix, see “How to change the ott ids assigned to my taxa?†in the FAQ below.

Step 2: Getting the tree corresponding to our taxa

Now that we have the correct ott_id for our taxa, we can ask for the tree using the tol_induced_subtree() function. By default, the object returned by tol_induced_subtree is a phylo object (from the ape package), so we can plot it directly.

my_tree <- tol_induced_subtree(ott_ids = resolved_names$ott_id)
## Warning in collapse_singles(tr, show_progress): Dropping singleton nodes with labels: Chordata ott125642, mrcaott42ott658, Craniata (subphylum in Deuterostomia) ott947318, Vertebrata (subphylum in Deuterostomia) ott801601, Gnathostomata (superclass in phylum
## Chordata) ott278114, Teleostomi ott114656, Sarcopterygii ott458402, Dipnotetrapodomorpha ott4940726, Tetrapoda ott229562, Amphibia ott544595, Batrachia ott471197, Anura ott991547, mrcaott114ott3129, mrcaott114ott37876, mrcaott114ott18818, Neobatrachia ott535804,
## mrcaott114ott309463, mrcaott114ott177, mrcaott177ott7464, mrcaott177ott2199, mrcaott177ott29310, mrcaott177ott1321, Hylidae ott535782, mrcaott177ott17126, mrcaott177ott43017, mrcaott177ott2732, mrcaott2732ott3289, mrcaott3289ott40328, mrcaott3289ott173489,
## mrcaott3289ott110534, mrcaott3289ott489758, mrcaott3289ott59160, Actinopterygii ott773483, Actinopteri ott285821, Neopterygii ott471203, Teleostei ott212201, Osteoglossocephalai ott5506109, Clupeocephala ott285819, Euteleosteomorpha ott5517919, mrcaott274ott392,
## mrcaott274ott595, Protacanthopterygii ott1024043, mrcaott274ott3887, mrcaott3887ott9371, Salmoniformes ott216171, Salmonidae ott739933, mrcaott3887ott28511, Salmoninae ott936925, mrcaott31485ott79094, Ambulacraria ott6520512, Echinodermata ott451020, Eleutherozoa
## ott317277, Echinozoa ott669475, Echinoidea ott669472, mrcaott360ott26831, mrcaott360ott3985, mrcaott360ott367, mrcaott360ott362, Acroechinoidea ott5677511, mrcaott362ott220009, mrcaott220009ott3651075, Diadematoida ott631174, Diadematidae ott631173,
## mrcaott220009ott357021, Protostomia ott189832, mrcaott49ott6612, Lophotrochozoa ott155737, mrcaott56ott519, mrcaott56ott5497, Mollusca ott802117, mrcaott56ott1881, mrcaott1881ott102410, Cephalopoda ott7368, Nautiloidea ott854446, Nautilida ott854452, Nautilidae
## ott616361
plot(my_tree, no.margin = TRUE)
plot of chunk unnamed-chunk-3
plot of chunk unnamed-chunk-3

FAQ

How to change the ott ids assigned to my taxa?

If you realize that tnrs_match_names assigns the incorrect taxonomic group to your name (e.g., because of synonymy) and changing the context_name does not help, you can use the function inspect. This function takes the object resulting from tnrs_match_names(), and either the row number, the taxon name (you used in your search in lowercase), or the ott_id returned by the initial query.

To illustrate this, let’s re-use the previous query but this time pretending that we are interested in the fungus Diadema and not the sea urchin:

taxa <- c("Hyla", "Salmo", "Diadema", "Nautilus")
resolved_names <- tnrs_match_names(taxa)
resolved_names
##   search_string unique_name approximate_match score  ott_id is_synonym flags number_matches
## 1          hyla        Hyla             FALSE     1 1062216      FALSE                    1
## 2         salmo       Salmo             FALSE     1  982359      FALSE                    1
## 3       diadema     Diadema             FALSE     1 4930522      FALSE                    4
## 4      nautilus    Nautilus             FALSE     1  616358      FALSE                    1
inspect(resolved_names, taxon_name = "diadema")
##   search_string                       unique_name approximate_match score  ott_id is_synonym          flags number_matches
## 1       diadema                           Diadema             FALSE     1 4930522      FALSE                             4
## 2       diadema                       Diademoides             FALSE     1 4024672       TRUE sibling_higher              4
## 3       diadema Garrettia (genus in Opisthokonta)             FALSE     1  631176       TRUE                             4
## 4       diadema                        Hypolimnas             FALSE     1  643831       TRUE                             4

In our case, we want the second row in this data frame to replace the information that initially matched for Diadema. We can now use the update() function, to change to the correct taxa (the fungus not the sea urchin):

resolved_names <- update(resolved_names,
  taxon_name = "diadema",
  new_row_number = 2
)

## we could also have used the ott_id to replace this taxon:
## resolved_names <- update(resolved_names, taxon_name = "diadema",
##                          new_ott_id = 4930522)

And now our resolved_names data frame includes the taxon we want:

search_string unique_name approximate_match score ott_id is_synonym flags number_matches
hyla Hyla FALSE 1 1062216 FALSE 1
salmo Salmo FALSE 1 982359 FALSE 1
diadema Diademoides FALSE 1 4024672 TRUE sibling_higher 4
nautilus Nautilus FALSE 1 616358 FALSE 1

How do I know that the taxa I’m asking for is the correct one?

The function taxonomy_taxon_info() takes ott_ids as arguments and returns taxonomic information about the taxa. This output can be passed to some helpers functions to extract the relevant information. Let’s illustrate this with our Diadema example

diadema_info <- taxonomy_taxon_info(631176)
tax_rank(diadema_info)
## $`Garrettia (genus in Opisthokonta)`
## [1] "genus"
## 
## attr(,"class")
## [1] "otl_rank" "list"
synonyms(diadema_info)
## $`Garrettia (genus in Opisthokonta)`
## [1] "Centrechinus" "Diadema"      "Diamema"     
## 
## attr(,"class")
## [1] "otl_synonyms" "list"
tax_name(diadema_info)
## $`Garrettia (genus in Opisthokonta)`
## [1] "Garrettia"
## 
## attr(,"class")
## [1] "otl_name" "list"

In some cases, it might also be useful to investigate the taxonomic tree descending from an ott_id to check that it’s the correct taxon and to determine the species included in the Open Tree Taxonomy:

diadema_tax_tree <- taxonomy_subtree(631176)
diadema_tax_tree
## $tip_label
##  [1] "Garrettia_parva_ott6356094"               "Garrettia_rotella_ott6356095"             "Diadema_savignyi_ott395692"               "Diadema_palmeri_ott836860"                "Diadema_setosum_ott631175"                "Diadema_paucispinum_ott312263"           
##  [7] "unclassified_Diadema_ott7669081"          "Diadema_africanum_ott4147369"             "Diadema_antillarum_scensionis_ott220009"  "Diadema_antillarum_antillarum_ott4147370" "Diadema_mexicanum_ott639130"              "Diademasp.SP04-BIO_4_JGLCO_AYott7072105" 
## [13] "Diademasp.SP03-BIO_3_JGLCO_AYott7072104"  "Diademasp.SP02-BIO_2_JGLCO_AYott7072103"  "Diadema_sp._DSM1_ott219999"               "Diadema_sp._DSM6_ott771059"               "Diademasp.ACOSTI-NIOTSU3ott7072098"       "Diademasp.LI03-BIO_JGLCO_AYott7072102"   
## [19] "Diademasp.LI02-BIO_JGLCO_AYott7072101"    "Diademasp.LI01-BIO_JGLCO_AYott7072100"    "Diademasp.ACOSTI-NIOTSU4ott7072099"       "Diadema_sp._seto35_ott66618"              "Diadema_sp._seto18_ott66623"              "Diadema_sp._seto19_ott66624"             
## [25] "Diadema_sp._seto38_ott66625"              "Diadema_sp._DJN9_ott66626"                "Diademasp.CS-2014ott5502179"              "Diadema_sp._seto17_ott587478"             "Diadema_sp._SETO15_ott587479"             "Diadema_sp._dsm5_ott587480"              
## [31] "Diadema_sp._DSM4_ott587481"               "Diadema_sp._DSM3_ott587482"               "Diadema_sp._DSM2_ott587483"               "Diadema_sp._seto10_ott587484"             "Diadema_sp._seto9_ott587485"              "Diadema_sp._DSM8_ott587486"              
## [37] "Diadema_sp._DSM7_ott587487"               "Diadema_sp._seto16_ott312262"             "Diadema_africana_ott5502180"              "Diadema_principeana_ott5725746"           "Diadema_vetus_ott5725747"                 "Diadema_regnyi_ott7669077"               
## [43] "Diadema_amalthei_ott7669073"              "Diadema_affine_ott7669072"                "Diadema_subcomplanatum_ott7669079"        "Diadema_ruppelii_ott7669078"              "Diadema_calloviensis_ott7669074"          "Diadema_megastoma_ott7669075"            
## [49] "Diadema_priscum_ott7669076"               "Garrettia_biangulata_ott7669080"          "Diadema_ascensionis_ott4950423"           "Diadema_lobatum_ott4950422"              
## 
## $edge_label
## [1] "Diadema_antillarum_ott1022356"  "'Garrettia(genusinOpisthokonta" "ott631176'"

By default, this function return all taxa (including self, and internal) descending from this ott_id but it also possible to return phylo object.

How do I get the tree for a particular taxonomic group?

If you are looking to get the tree for a particular taxonomic group, you need to first identify it by its node id or ott id, and then use the tol_subtree() function:

mono_id <- tnrs_match_names("Monotremata")
mono_tree <- tol_subtree(ott_id = ott_id(mono_id))
## Warning in collapse_singles(tr, show_progress): Dropping singleton nodes with labels: Tachyglossus ott16047, Tachyglossus aculeatus ott16038, Ornithorhynchus ott962391, Obdurodon ott3615207, Steropodon ott3615209, Teinolophos ott4119276
plot(mono_tree)
plot of chunk unnamed-chunk-8
plot of chunk unnamed-chunk-8

How do I find trees from studies focused on my favourite taxa?

The function studies_find_trees() allows the user to search for studies matching a specific criteria. The function studies_properties() returns the list of properties that can be used in the search.

furry_studies <- studies_find_studies(property = "ot:focalCladeOTTTaxonName", value = "Mammalia")
furry_ids <- furry_studies$study_ids

Now that we know the study_id, we can ask for the meta data information associated with this study:

furry_meta <- get_study_meta("pg_2550")
get_publication(furry_meta) ## The citation for the source of the study
## [1] "O'Leary, Maureen A., Marc Allard, Michael J. Novacek, Jin Meng, and John Gatesy. 2004. \"Building the mammalian sector of the tree of life: Combining different data and a discussion of divergence times for placental mammals.\" In: Cracraft J., & Donoghue M., eds. Assembling the Tree of Life. pp. 490-516. Oxford, United Kingdom, Oxford University Press."
## attr(,"DOI")
## [1] ""
get_tree_ids(furry_meta) ## This study has 10 trees associated with it
##  [1] "tree5513" "tree5515" "tree5516" "tree5517" "tree5518" "tree5519" "tree5520" "tree5521" "tree5522" "tree5523"
candidate_for_synth(furry_meta) ## None of these trees are yet included in the OTL
## NULL

Using get_study("pg_2550") would returns a multiPhylo object (default) with all the trees associated with this particular study, while get_study_tree("pg_2550", "tree5513") would return one of these trees.

The tree returned by the API has duplicated tip labels, how can I work around it?

You may encounter the following error message:

Error in rncl(file = file, ...) : Taxon number 39 (coded by the token Pratia
angulata) has already been encountered in this tree. Duplication of taxa in a
tree is prohibited.

This message occurs as duplicate labels are not allowed in the NEXUS format and it is stricly enforced by the part of the code used by rotl to import the trees in memory.

If you use a version of rotl more recent than 0.4.1, this should not happen by default for the function get_study_tree. If it happens with another function, please let us know.

The easiest way to work around this is to save the tree in a file, and use APE to read it in memory:

get_study_tree(
  study_id = "pg_710", tree_id = "tree1277",
  tip_label = "ott_taxon_name", file = "/tmp/tree.tre",
  file_format = "newick"
)
tr <- ape::read.tree(file = "/tmp/tree.tre")

How do I get the higher taxonomy for a given taxa?

If you encounter a taxon name you are not familiar with, it might be useful to obtain its higher taxonomy to see where it fits in the tree of life. We can combine several taxonomy methods to extract this information easily.

giant_squid <- tnrs_match_names("Architeuthis")
tax_lineage(taxonomy_taxon_info(ott_id(giant_squid), include_lineage = TRUE))
## $`564394`
##          rank               name        unique_name  ott_id
## 1      family     Architeuthidae     Architeuthidae  564393
## 2       order          Oegopsida          Oegopsida   43352
## 3  superorder     Decapodiformes     Decapodiformes  854107
## 4  infraclass       Neocoleoidea       Neocoleoidea  329546
## 5    subclass          Coleoidea          Coleoidea    7371
## 6       class        Cephalopoda        Cephalopoda    7368
## 7      phylum           Mollusca           Mollusca  802117
## 8     no rank     Lophotrochozoa     Lophotrochozoa  155737
## 9     no rank        Protostomia        Protostomia  189832
## 10    no rank          Bilateria          Bilateria  117569
## 11    no rank          Eumetazoa          Eumetazoa  641038
## 12    kingdom            Metazoa            Metazoa  691846
## 13    no rank            Holozoa            Holozoa 5246131
## 14    no rank       Opisthokonta       Opisthokonta  332573
## 15     domain          Eukaryota          Eukaryota  304358
## 16    no rank cellular organisms cellular organisms   93302
## 17    no rank               life               life  805080

Why are OTT IDs discovered with rotl missing from an induced subtree?

Some taxonomic names that can be retrieved through the taxonomic name resolution service are not part of the Open Tree’s synthesis tree. These are usually traditional higher-level taxa that have been found to be paraphyletic.

For instance, if you wanted to fetch a tree relating the three birds that go into a Turkducken as well as the pork used for stuffing, you might search for the turkey, duck, chicken, and pork genera:

turducken <- c("Meleagris", "Anas", "Gallus", "Sus")
taxa <- tnrs_match_names(turducken, context_name = "Animals")
taxa
##   search_string unique_name approximate_match score ott_id is_synonym flags number_matches
## 1     meleagris   Meleagris             FALSE     1 446481      FALSE                    2
## 2          anas        Anas             FALSE     1 765185      FALSE                    1
## 3        gallus      Gallus             FALSE     1 153562      FALSE                    3
## 4           sus         Sus             FALSE     1 730021      FALSE                    1

We have the OTT ids for each genus, however, if we tried to get the induced subtree from these results, we would get an error:

tr <- tol_induced_subtree(ott_id(taxa))
## Warning in collapse_singles(tr, show_progress): Dropping singleton nodes with labels: Mammalia ott244265, Theria (subclass in Deuterostomia) ott229558, Eutheria (in Deuterostomia) ott683263, mrcaott42ott3607383, mrcaott42ott3607429, mrcaott42ott3607455,
## mrcaott42ott72667, Boreoeutheria ott5334778, Laurasiatheria ott392223, mrcaott1548ott4697, mrcaott1548ott6790, mrcaott1548ott3607484, mrcaott1548ott4942380, mrcaott1548ott4942547, mrcaott1548ott3021, Artiodactyla ott622916, mrcaott1548ott21987, Suina ott916745,
## Suidae ott730008, Sauropsida ott639642, Sauria ott329823, mrcaott246ott2982, mrcaott246ott31216, mrcaott246ott3602822, mrcaott246ott4143599, mrcaott246ott3600976, mrcaott246ott4132107, Aves ott81461, Neognathae ott241846, mrcaott4765ott4131031, Galliformes
## ott837585, mrcaott4765ott6520194, mrcaott4765ott109888, mrcaott4765ott75785, mrcaott4765ott104461, mrcaott4765ott151684, mrcaott4765ott54193, mrcaott4765ott3596087, mrcaott4765ott415487, mrcaott4765ott51354, mrcaott4765ott781249, mrcaott4765ott53700,
## mrcaott4765ott572162, mrcaott4765ott446490, Meleagridinae ott781250, mrcaott49310ott51349, mrcaott49310ott49319, mrcaott49310ott153554, mrcaott153554ott867027, mrcaott30843ott4947869, Anseriformes ott241841, mrcaott30843ott714464, Anatidae ott765193,
## mrcaott30843ott88380, mrcaott30843ott1082830, mrcaott30843ott75874, mrcaott30843ott432041, mrcaott30843ott30847, mrcaott30843ott166683, mrcaott30843ott30845, mrcaott30845ott30850

As the error message suggests, some of the taxa are not found in the synthetic tree. This occurs for 2 main reasons: either the taxa is invalid, or it is part of a group that is not monophyletic in the synthetic tree. There are two ways to get around this issue: (1) removing the taxa that are not part of the Open Tree; (2) using the complete species name.

Removing the taxa missing from the synthetic tree

To help with this situation, rotl provides a way to identify the OTT ids that are not part of the synthetic tree. The function is_in_tree() takes the output of the ott_id() function and returns a vector of logical indicating whether the taxa are part of the synthetic tree. We can then use to only keep the taxa that appear in the synthetic tree:

in_tree <- is_in_tree(ott_id(taxa))
in_tree
## Meleagris      Anas    Gallus       Sus 
##      TRUE     FALSE      TRUE      TRUE
tr <- tol_induced_subtree(ott_id(taxa)[in_tree])
## Warning in collapse_singles(tr, show_progress): Dropping singleton nodes with labels: Mammalia ott244265, Theria (subclass in Deuterostomia) ott229558, Eutheria (in Deuterostomia) ott683263, mrcaott42ott3607383, mrcaott42ott3607429, mrcaott42ott3607455,
## mrcaott42ott72667, Boreoeutheria ott5334778, Laurasiatheria ott392223, mrcaott1548ott4697, mrcaott1548ott6790, mrcaott1548ott3607484, mrcaott1548ott4942380, mrcaott1548ott4942547, mrcaott1548ott3021, Artiodactyla ott622916, mrcaott1548ott21987, Suina ott916745,
## Suidae ott730008, Sauropsida ott639642, Sauria ott329823, mrcaott246ott2982, mrcaott246ott31216, mrcaott246ott3602822, mrcaott246ott4143599, mrcaott246ott3600976, mrcaott246ott4132107, Aves ott81461, Neognathae ott241846, Galloanserae ott5839486,
## mrcaott4765ott4131031, Galliformes ott837585, mrcaott4765ott6520194, mrcaott4765ott109888, mrcaott4765ott75785, mrcaott4765ott104461, mrcaott4765ott151684, mrcaott4765ott54193, mrcaott4765ott3596087, mrcaott4765ott415487, mrcaott4765ott51354,
## mrcaott4765ott781249, mrcaott4765ott53700, mrcaott4765ott572162, mrcaott4765ott446490, Meleagridinae ott781250, mrcaott49310ott51349, mrcaott49310ott49319, mrcaott49310ott153554, mrcaott153554ott867027

Using the full taxonomic names

The best way to avoid these problems is to specify complete species names (species being the lowest level of classification in the Open Tree taxonomy they are guaranteed to be monophyletic):

turducken_spp <- c("Meleagris gallopavo", "Anas platyrhynchos", "Gallus gallus", "Sus scrofa")
taxa <- tnrs_match_names(turducken_spp, context_name = "Animals")
tr <- tol_induced_subtree(ott_id(taxa))
## Warning in collapse_singles(tr, show_progress): Dropping singleton nodes with labels: Mammalia ott244265, Theria (subclass in Deuterostomia) ott229558, Eutheria (in Deuterostomia) ott683263, mrcaott42ott3607383, mrcaott42ott3607429, mrcaott42ott3607455,
## mrcaott42ott72667, Boreoeutheria ott5334778, Laurasiatheria ott392223, mrcaott1548ott4697, mrcaott1548ott6790, mrcaott1548ott3607484, mrcaott1548ott4942380, mrcaott1548ott4942547, mrcaott1548ott3021, Artiodactyla ott622916, mrcaott1548ott21987, Suina ott916745,
## Suidae ott730008, Sus ott730021, Sauropsida ott639642, Sauria ott329823, mrcaott246ott2982, mrcaott246ott31216, mrcaott246ott3602822, mrcaott246ott4143599, mrcaott246ott3600976, mrcaott246ott4132107, Aves ott81461, Neognathae ott241846, mrcaott4765ott4131031,
## Galliformes ott837585, mrcaott4765ott6520194, mrcaott4765ott109888, mrcaott4765ott75785, mrcaott4765ott104461, mrcaott4765ott151684, mrcaott4765ott54193, mrcaott4765ott3596087, mrcaott4765ott415487, mrcaott4765ott51354, mrcaott4765ott781249, mrcaott4765ott53700,
## mrcaott4765ott572162, mrcaott4765ott446490, Meleagridinae ott781250, Meleagris ott446481, mrcaott49310ott51349, mrcaott49310ott49319, mrcaott49310ott153554, mrcaott153554ott867027, Gallus ott153562, mrcaott153554ott240568, mrcaott30843ott4947869, Anseriformes
## ott241841, mrcaott30843ott714464, Anatidae ott765193, mrcaott30843ott88380, mrcaott30843ott1082830, mrcaott30843ott75874, mrcaott30843ott432041, mrcaott30843ott30847, mrcaott30843ott166683, mrcaott30843ott30845, mrcaott30845ott30850, mrcaott30850ott82415,
## mrcaott30850ott82420, mrcaott30850ott656780, mrcaott30850ott82414, mrcaott30850ott82425, mrcaott30850ott765188, mrcaott30850ott332079, mrcaott30850ott30858, mrcaott30850ott90669, mrcaott30850ott30855, mrcaott30850ott604172, mrcaott30850ott339494,
## mrcaott30850ott82410, mrcaott30850ott604175, mrcaott30850ott190881, mrcaott190881ott604182
plot(tr)
plot of chunk unnamed-chunk-16
plot of chunk unnamed-chunk-16
rotl/inst/doc/rotl.Rmd0000644000176200001440000006156515132142375014420 0ustar liggesusers--- title: "How to use rotl?" author: "François Michonneau" date: "2026-01-15" output: rmarkdown::html_vignette: css: vignette.css vignette: > %\VignetteIndexEntry{How to use rotl?} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} \usepackage[utf8]{inputenc} --- `rotl` provides an interface to the Open Tree of Life (OTL) API and allows users to query the API, retrieve parts of the Tree of Life and integrate these parts with other R packages. The OTL API provides services to access: * the **Tree of Life** a.k.a. TOL (the synthetic tree): a single draft tree that is a combination of **the OTL taxonomy** and the **source trees** (studies) * the **Taxonomic name resolution services** a.k.a. TNRS: the methods for resolving taxonomic names to the internal identifiers used by the TOL and the GOL (the `ott ids`). * the **Taxonomy** a.k.a. OTT (for Open Tree Taxonomy): which represents the synthesis of the different taxonomies used as a backbone of the TOL when no studies are available. * the **Studies** containing the source trees used to build the TOL, and extracted from the scientific literature. In `rotl`, each of these services correspond to functions with different prefixes: | Service | `rotl` prefix | |---------------|---------------| | Tree of Life | `tol_` | | TNRS | `tnrs_` | | Taxonomy | `taxonomy_` | | Studies | `studies_` | `rotl` also provides a few other functions and methods that can be used to extract relevant information from the objects returned by these functions. ## Demonstration of a basic workflow The most common use for `rotl` is probably to start from a list of species and get the relevant parts of the tree for these species. This is a two step process: 1. the species names need to be matched to their `ott_id` (the Open Tree Taxonomy identifiers) using the Taxonomic name resolution services (TNRS) 1. these `ott_id` will then be used to retrieve the relevant parts of the Tree of Life. ### Step 1: Matching taxonomy to the `ott_id` Let's start by doing a search on a diverse group of taxa: a tree frog (genus _Hyla_), a fish (genus _Salmo_), a sea urchin (genus _Diadema_), and a nautilus (genus _Nautilus_). ``` r library(rotl) taxa <- c("Hyla", "Salmo", "Diadema", "Nautilus") resolved_names <- tnrs_match_names(taxa) ``` It's always a good idea to check that the resolved names match what you intended: |search_string |unique_name |approximate_match | score| ott_id|is_synonym |flags | number_matches| |:-------------|:-----------|:-----------------|-----:|-------:|:----------|:-----|--------------:| |hyla |Hyla |FALSE | 1| 1062216|FALSE | | 1| |salmo |Salmo |FALSE | 1| 982359|FALSE | | 1| |diadema |Diadema |FALSE | 1| 4930522|FALSE | | 4| |nautilus |Nautilus |FALSE | 1| 616358|FALSE | | 1| The column `unique_name` sometimes indicates the higher taxonomic level associated with the name. The column `number_matches` indicates the number of `ott_id` that corresponds to a given name. In this example, our search on _Diadema_ returns 2 matches, and the one returned by default is indeed the sea urchin that we want for our query. The argument `context_name` allows you to limit the taxonomic scope of your search. _Diadema_ is also the genus name of a fungus. To ensure that our search is limited to animal names, we could do: ``` r resolved_names <- tnrs_match_names(taxa, context_name = "Animals") ``` If you are trying to build a tree with deeply divergent taxa that the argument `context_name` cannot fix, see "How to change the ott ids assigned to my taxa?" in the FAQ below. ### Step 2: Getting the tree corresponding to our taxa Now that we have the correct `ott_id` for our taxa, we can ask for the tree using the `tol_induced_subtree()` function. By default, the object returned by `tol_induced_subtree` is a phylo object (from the [ape](https://cran.r-project.org/package=ape) package), so we can plot it directly. ``` r my_tree <- tol_induced_subtree(ott_ids = resolved_names$ott_id) ``` ``` ## Warning in collapse_singles(tr, show_progress): Dropping singleton nodes with labels: Chordata ott125642, mrcaott42ott658, Craniata (subphylum in Deuterostomia) ott947318, Vertebrata (subphylum in Deuterostomia) ott801601, Gnathostomata (superclass in phylum ## Chordata) ott278114, Teleostomi ott114656, Sarcopterygii ott458402, Dipnotetrapodomorpha ott4940726, Tetrapoda ott229562, Amphibia ott544595, Batrachia ott471197, Anura ott991547, mrcaott114ott3129, mrcaott114ott37876, mrcaott114ott18818, Neobatrachia ott535804, ## mrcaott114ott309463, mrcaott114ott177, mrcaott177ott7464, mrcaott177ott2199, mrcaott177ott29310, mrcaott177ott1321, Hylidae ott535782, mrcaott177ott17126, mrcaott177ott43017, mrcaott177ott2732, mrcaott2732ott3289, mrcaott3289ott40328, mrcaott3289ott173489, ## mrcaott3289ott110534, mrcaott3289ott489758, mrcaott3289ott59160, Actinopterygii ott773483, Actinopteri ott285821, Neopterygii ott471203, Teleostei ott212201, Osteoglossocephalai ott5506109, Clupeocephala ott285819, Euteleosteomorpha ott5517919, mrcaott274ott392, ## mrcaott274ott595, Protacanthopterygii ott1024043, mrcaott274ott3887, mrcaott3887ott9371, Salmoniformes ott216171, Salmonidae ott739933, mrcaott3887ott28511, Salmoninae ott936925, mrcaott31485ott79094, Ambulacraria ott6520512, Echinodermata ott451020, Eleutherozoa ## ott317277, Echinozoa ott669475, Echinoidea ott669472, mrcaott360ott26831, mrcaott360ott3985, mrcaott360ott367, mrcaott360ott362, Acroechinoidea ott5677511, mrcaott362ott220009, mrcaott220009ott3651075, Diadematoida ott631174, Diadematidae ott631173, ## mrcaott220009ott357021, Protostomia ott189832, mrcaott49ott6612, Lophotrochozoa ott155737, mrcaott56ott519, mrcaott56ott5497, Mollusca ott802117, mrcaott56ott1881, mrcaott1881ott102410, Cephalopoda ott7368, Nautiloidea ott854446, Nautilida ott854452, Nautilidae ## ott616361 ``` ``` r plot(my_tree, no.margin = TRUE) ``` ![plot of chunk unnamed-chunk-3](fig-vignettes-unnamed-chunk-3-1.png) ## FAQ ### How to change the ott ids assigned to my taxa? If you realize that `tnrs_match_names` assigns the incorrect taxonomic group to your name (e.g., because of synonymy) and changing the `context_name` does not help, you can use the function `inspect`. This function takes the object resulting from `tnrs_match_names()`, and either the row number, the taxon name (you used in your search in lowercase), or the `ott_id` returned by the initial query. To illustrate this, let's re-use the previous query but this time pretending that we are interested in the fungus _Diadema_ and not the sea urchin: ``` r taxa <- c("Hyla", "Salmo", "Diadema", "Nautilus") resolved_names <- tnrs_match_names(taxa) resolved_names ``` ``` ## search_string unique_name approximate_match score ott_id is_synonym flags number_matches ## 1 hyla Hyla FALSE 1 1062216 FALSE 1 ## 2 salmo Salmo FALSE 1 982359 FALSE 1 ## 3 diadema Diadema FALSE 1 4930522 FALSE 4 ## 4 nautilus Nautilus FALSE 1 616358 FALSE 1 ``` ``` r inspect(resolved_names, taxon_name = "diadema") ``` ``` ## search_string unique_name approximate_match score ott_id is_synonym flags number_matches ## 1 diadema Diadema FALSE 1 4930522 FALSE 4 ## 2 diadema Diademoides FALSE 1 4024672 TRUE sibling_higher 4 ## 3 diadema Garrettia (genus in Opisthokonta) FALSE 1 631176 TRUE 4 ## 4 diadema Hypolimnas FALSE 1 643831 TRUE 4 ``` In our case, we want the second row in this data frame to replace the information that initially matched for _Diadema_. We can now use the `update()` function, to change to the correct taxa (the fungus not the sea urchin): ``` r resolved_names <- update(resolved_names, taxon_name = "diadema", new_row_number = 2 ) ## we could also have used the ott_id to replace this taxon: ## resolved_names <- update(resolved_names, taxon_name = "diadema", ## new_ott_id = 4930522) ``` And now our `resolved_names` data frame includes the taxon we want: |search_string |unique_name |approximate_match | score| ott_id|is_synonym |flags | number_matches| |:-------------|:-----------|:-----------------|-----:|-------:|:----------|:--------------|--------------:| |hyla |Hyla |FALSE | 1| 1062216|FALSE | | 1| |salmo |Salmo |FALSE | 1| 982359|FALSE | | 1| |diadema |Diademoides |FALSE | 1| 4024672|TRUE |sibling_higher | 4| |nautilus |Nautilus |FALSE | 1| 616358|FALSE | | 1| ### How do I know that the taxa I'm asking for is the correct one? The function `taxonomy_taxon_info()` takes `ott_ids` as arguments and returns taxonomic information about the taxa. This output can be passed to some helpers functions to extract the relevant information. Let's illustrate this with our _Diadema_ example ``` r diadema_info <- taxonomy_taxon_info(631176) tax_rank(diadema_info) ``` ``` ## $`Garrettia (genus in Opisthokonta)` ## [1] "genus" ## ## attr(,"class") ## [1] "otl_rank" "list" ``` ``` r synonyms(diadema_info) ``` ``` ## $`Garrettia (genus in Opisthokonta)` ## [1] "Centrechinus" "Diadema" "Diamema" ## ## attr(,"class") ## [1] "otl_synonyms" "list" ``` ``` r tax_name(diadema_info) ``` ``` ## $`Garrettia (genus in Opisthokonta)` ## [1] "Garrettia" ## ## attr(,"class") ## [1] "otl_name" "list" ``` In some cases, it might also be useful to investigate the taxonomic tree descending from an `ott_id` to check that it's the correct taxon and to determine the species included in the Open Tree Taxonomy: ``` r diadema_tax_tree <- taxonomy_subtree(631176) diadema_tax_tree ``` ``` ## $tip_label ## [1] "Garrettia_parva_ott6356094" "Garrettia_rotella_ott6356095" "Diadema_savignyi_ott395692" "Diadema_palmeri_ott836860" "Diadema_setosum_ott631175" "Diadema_paucispinum_ott312263" ## [7] "unclassified_Diadema_ott7669081" "Diadema_africanum_ott4147369" "Diadema_antillarum_scensionis_ott220009" "Diadema_antillarum_antillarum_ott4147370" "Diadema_mexicanum_ott639130" "Diademasp.SP04-BIO_4_JGLCO_AYott7072105" ## [13] "Diademasp.SP03-BIO_3_JGLCO_AYott7072104" "Diademasp.SP02-BIO_2_JGLCO_AYott7072103" "Diadema_sp._DSM1_ott219999" "Diadema_sp._DSM6_ott771059" "Diademasp.ACOSTI-NIOTSU3ott7072098" "Diademasp.LI03-BIO_JGLCO_AYott7072102" ## [19] "Diademasp.LI02-BIO_JGLCO_AYott7072101" "Diademasp.LI01-BIO_JGLCO_AYott7072100" "Diademasp.ACOSTI-NIOTSU4ott7072099" "Diadema_sp._seto35_ott66618" "Diadema_sp._seto18_ott66623" "Diadema_sp._seto19_ott66624" ## [25] "Diadema_sp._seto38_ott66625" "Diadema_sp._DJN9_ott66626" "Diademasp.CS-2014ott5502179" "Diadema_sp._seto17_ott587478" "Diadema_sp._SETO15_ott587479" "Diadema_sp._dsm5_ott587480" ## [31] "Diadema_sp._DSM4_ott587481" "Diadema_sp._DSM3_ott587482" "Diadema_sp._DSM2_ott587483" "Diadema_sp._seto10_ott587484" "Diadema_sp._seto9_ott587485" "Diadema_sp._DSM8_ott587486" ## [37] "Diadema_sp._DSM7_ott587487" "Diadema_sp._seto16_ott312262" "Diadema_africana_ott5502180" "Diadema_principeana_ott5725746" "Diadema_vetus_ott5725747" "Diadema_regnyi_ott7669077" ## [43] "Diadema_amalthei_ott7669073" "Diadema_affine_ott7669072" "Diadema_subcomplanatum_ott7669079" "Diadema_ruppelii_ott7669078" "Diadema_calloviensis_ott7669074" "Diadema_megastoma_ott7669075" ## [49] "Diadema_priscum_ott7669076" "Garrettia_biangulata_ott7669080" "Diadema_ascensionis_ott4950423" "Diadema_lobatum_ott4950422" ## ## $edge_label ## [1] "Diadema_antillarum_ott1022356" "'Garrettia(genusinOpisthokonta" "ott631176'" ``` By default, this function return all taxa (including self, and internal) descending from this `ott_id` but it also possible to return `phylo` object. ### How do I get the tree for a particular taxonomic group? If you are looking to get the tree for a particular taxonomic group, you need to first identify it by its node id or ott id, and then use the `tol_subtree()` function: ``` r mono_id <- tnrs_match_names("Monotremata") mono_tree <- tol_subtree(ott_id = ott_id(mono_id)) ``` ``` ## Warning in collapse_singles(tr, show_progress): Dropping singleton nodes with labels: Tachyglossus ott16047, Tachyglossus aculeatus ott16038, Ornithorhynchus ott962391, Obdurodon ott3615207, Steropodon ott3615209, Teinolophos ott4119276 ``` ``` r plot(mono_tree) ``` ![plot of chunk unnamed-chunk-8](fig-vignettes-unnamed-chunk-8-1.png) ### How do I find trees from studies focused on my favourite taxa? The function `studies_find_trees()` allows the user to search for studies matching a specific criteria. The function `studies_properties()` returns the list of properties that can be used in the search. ``` r furry_studies <- studies_find_studies(property = "ot:focalCladeOTTTaxonName", value = "Mammalia") furry_ids <- furry_studies$study_ids ``` Now that we know the `study_id`, we can ask for the meta data information associated with this study: ``` r furry_meta <- get_study_meta("pg_2550") get_publication(furry_meta) ## The citation for the source of the study ``` ``` ## [1] "O'Leary, Maureen A., Marc Allard, Michael J. Novacek, Jin Meng, and John Gatesy. 2004. \"Building the mammalian sector of the tree of life: Combining different data and a discussion of divergence times for placental mammals.\" In: Cracraft J., & Donoghue M., eds. Assembling the Tree of Life. pp. 490-516. Oxford, United Kingdom, Oxford University Press." ## attr(,"DOI") ## [1] "" ``` ``` r get_tree_ids(furry_meta) ## This study has 10 trees associated with it ``` ``` ## [1] "tree5513" "tree5515" "tree5516" "tree5517" "tree5518" "tree5519" "tree5520" "tree5521" "tree5522" "tree5523" ``` ``` r candidate_for_synth(furry_meta) ## None of these trees are yet included in the OTL ``` ``` ## NULL ``` Using `get_study("pg_2550")` would returns a `multiPhylo` object (default) with all the trees associated with this particular study, while `get_study_tree("pg_2550", "tree5513")` would return one of these trees. ### The tree returned by the API has duplicated tip labels, how can I work around it? You may encounter the following error message: ``` Error in rncl(file = file, ...) : Taxon number 39 (coded by the token Pratia angulata) has already been encountered in this tree. Duplication of taxa in a tree is prohibited. ``` This message occurs as duplicate labels are not allowed in the NEXUS format and it is stricly enforced by the part of the code used by `rotl` to import the trees in memory. If you use a version of `rotl` more recent than 0.4.1, this should not happen by default for the function `get_study_tree`. If it happens with another function, please [let us know](https://github.com/ropensci/rotl/issues). The easiest way to work around this is to save the tree in a file, and use APE to read it in memory: ``` r get_study_tree( study_id = "pg_710", tree_id = "tree1277", tip_label = "ott_taxon_name", file = "/tmp/tree.tre", file_format = "newick" ) tr <- ape::read.tree(file = "/tmp/tree.tre") ``` ### How do I get the higher taxonomy for a given taxa? If you encounter a taxon name you are not familiar with, it might be useful to obtain its higher taxonomy to see where it fits in the tree of life. We can combine several taxonomy methods to extract this information easily. ``` r giant_squid <- tnrs_match_names("Architeuthis") tax_lineage(taxonomy_taxon_info(ott_id(giant_squid), include_lineage = TRUE)) ``` ``` ## $`564394` ## rank name unique_name ott_id ## 1 family Architeuthidae Architeuthidae 564393 ## 2 order Oegopsida Oegopsida 43352 ## 3 superorder Decapodiformes Decapodiformes 854107 ## 4 infraclass Neocoleoidea Neocoleoidea 329546 ## 5 subclass Coleoidea Coleoidea 7371 ## 6 class Cephalopoda Cephalopoda 7368 ## 7 phylum Mollusca Mollusca 802117 ## 8 no rank Lophotrochozoa Lophotrochozoa 155737 ## 9 no rank Protostomia Protostomia 189832 ## 10 no rank Bilateria Bilateria 117569 ## 11 no rank Eumetazoa Eumetazoa 641038 ## 12 kingdom Metazoa Metazoa 691846 ## 13 no rank Holozoa Holozoa 5246131 ## 14 no rank Opisthokonta Opisthokonta 332573 ## 15 domain Eukaryota Eukaryota 304358 ## 16 no rank cellular organisms cellular organisms 93302 ## 17 no rank life life 805080 ``` ### Why are OTT IDs discovered with `rotl` missing from an induced subtree? Some taxonomic names that can be retrieved through the taxonomic name resolution service are not part of the Open Tree's synthesis tree. These are usually traditional higher-level taxa that have been found to be paraphyletic. For instance, if you wanted to fetch a tree relating the three birds that go into a [Turkducken](https://en.wikipedia.org/wiki/Turducken) as well as the pork used for stuffing, you might search for the turkey, duck, chicken, and pork genera: ``` r turducken <- c("Meleagris", "Anas", "Gallus", "Sus") taxa <- tnrs_match_names(turducken, context_name = "Animals") taxa ``` ``` ## search_string unique_name approximate_match score ott_id is_synonym flags number_matches ## 1 meleagris Meleagris FALSE 1 446481 FALSE 2 ## 2 anas Anas FALSE 1 765185 FALSE 1 ## 3 gallus Gallus FALSE 1 153562 FALSE 3 ## 4 sus Sus FALSE 1 730021 FALSE 1 ``` We have the OTT ids for each genus, however, if we tried to get the induced subtree from these results, we would get an error: ``` r tr <- tol_induced_subtree(ott_id(taxa)) ``` ``` ## Warning in collapse_singles(tr, show_progress): Dropping singleton nodes with labels: Mammalia ott244265, Theria (subclass in Deuterostomia) ott229558, Eutheria (in Deuterostomia) ott683263, mrcaott42ott3607383, mrcaott42ott3607429, mrcaott42ott3607455, ## mrcaott42ott72667, Boreoeutheria ott5334778, Laurasiatheria ott392223, mrcaott1548ott4697, mrcaott1548ott6790, mrcaott1548ott3607484, mrcaott1548ott4942380, mrcaott1548ott4942547, mrcaott1548ott3021, Artiodactyla ott622916, mrcaott1548ott21987, Suina ott916745, ## Suidae ott730008, Sauropsida ott639642, Sauria ott329823, mrcaott246ott2982, mrcaott246ott31216, mrcaott246ott3602822, mrcaott246ott4143599, mrcaott246ott3600976, mrcaott246ott4132107, Aves ott81461, Neognathae ott241846, mrcaott4765ott4131031, Galliformes ## ott837585, mrcaott4765ott6520194, mrcaott4765ott109888, mrcaott4765ott75785, mrcaott4765ott104461, mrcaott4765ott151684, mrcaott4765ott54193, mrcaott4765ott3596087, mrcaott4765ott415487, mrcaott4765ott51354, mrcaott4765ott781249, mrcaott4765ott53700, ## mrcaott4765ott572162, mrcaott4765ott446490, Meleagridinae ott781250, mrcaott49310ott51349, mrcaott49310ott49319, mrcaott49310ott153554, mrcaott153554ott867027, mrcaott30843ott4947869, Anseriformes ott241841, mrcaott30843ott714464, Anatidae ott765193, ## mrcaott30843ott88380, mrcaott30843ott1082830, mrcaott30843ott75874, mrcaott30843ott432041, mrcaott30843ott30847, mrcaott30843ott166683, mrcaott30843ott30845, mrcaott30845ott30850 ``` As the error message suggests, some of the taxa are not found in the synthetic tree. This occurs for 2 main reasons: either the taxa is invalid, or it is part of a group that is not monophyletic in the synthetic tree. There are two ways to get around this issue: (1) removing the taxa that are not part of the Open Tree; (2) using the complete species name. #### Removing the taxa missing from the synthetic tree To help with this situation, `rotl` provides a way to identify the OTT ids that are not part of the synthetic tree. The function `is_in_tree()` takes the output of the `ott_id()` function and returns a vector of logical indicating whether the taxa are part of the synthetic tree. We can then use to only keep the taxa that appear in the synthetic tree: ``` r in_tree <- is_in_tree(ott_id(taxa)) in_tree ``` ``` ## Meleagris Anas Gallus Sus ## TRUE FALSE TRUE TRUE ``` ``` r tr <- tol_induced_subtree(ott_id(taxa)[in_tree]) ``` ``` ## Warning in collapse_singles(tr, show_progress): Dropping singleton nodes with labels: Mammalia ott244265, Theria (subclass in Deuterostomia) ott229558, Eutheria (in Deuterostomia) ott683263, mrcaott42ott3607383, mrcaott42ott3607429, mrcaott42ott3607455, ## mrcaott42ott72667, Boreoeutheria ott5334778, Laurasiatheria ott392223, mrcaott1548ott4697, mrcaott1548ott6790, mrcaott1548ott3607484, mrcaott1548ott4942380, mrcaott1548ott4942547, mrcaott1548ott3021, Artiodactyla ott622916, mrcaott1548ott21987, Suina ott916745, ## Suidae ott730008, Sauropsida ott639642, Sauria ott329823, mrcaott246ott2982, mrcaott246ott31216, mrcaott246ott3602822, mrcaott246ott4143599, mrcaott246ott3600976, mrcaott246ott4132107, Aves ott81461, Neognathae ott241846, Galloanserae ott5839486, ## mrcaott4765ott4131031, Galliformes ott837585, mrcaott4765ott6520194, mrcaott4765ott109888, mrcaott4765ott75785, mrcaott4765ott104461, mrcaott4765ott151684, mrcaott4765ott54193, mrcaott4765ott3596087, mrcaott4765ott415487, mrcaott4765ott51354, ## mrcaott4765ott781249, mrcaott4765ott53700, mrcaott4765ott572162, mrcaott4765ott446490, Meleagridinae ott781250, mrcaott49310ott51349, mrcaott49310ott49319, mrcaott49310ott153554, mrcaott153554ott867027 ``` #### Using the full taxonomic names The best way to avoid these problems is to specify complete species names (species being the lowest level of classification in the Open Tree taxonomy they are guaranteed to be monophyletic): ``` r turducken_spp <- c("Meleagris gallopavo", "Anas platyrhynchos", "Gallus gallus", "Sus scrofa") taxa <- tnrs_match_names(turducken_spp, context_name = "Animals") tr <- tol_induced_subtree(ott_id(taxa)) ``` ``` ## Warning in collapse_singles(tr, show_progress): Dropping singleton nodes with labels: Mammalia ott244265, Theria (subclass in Deuterostomia) ott229558, Eutheria (in Deuterostomia) ott683263, mrcaott42ott3607383, mrcaott42ott3607429, mrcaott42ott3607455, ## mrcaott42ott72667, Boreoeutheria ott5334778, Laurasiatheria ott392223, mrcaott1548ott4697, mrcaott1548ott6790, mrcaott1548ott3607484, mrcaott1548ott4942380, mrcaott1548ott4942547, mrcaott1548ott3021, Artiodactyla ott622916, mrcaott1548ott21987, Suina ott916745, ## Suidae ott730008, Sus ott730021, Sauropsida ott639642, Sauria ott329823, mrcaott246ott2982, mrcaott246ott31216, mrcaott246ott3602822, mrcaott246ott4143599, mrcaott246ott3600976, mrcaott246ott4132107, Aves ott81461, Neognathae ott241846, mrcaott4765ott4131031, ## Galliformes ott837585, mrcaott4765ott6520194, mrcaott4765ott109888, mrcaott4765ott75785, mrcaott4765ott104461, mrcaott4765ott151684, mrcaott4765ott54193, mrcaott4765ott3596087, mrcaott4765ott415487, mrcaott4765ott51354, mrcaott4765ott781249, mrcaott4765ott53700, ## mrcaott4765ott572162, mrcaott4765ott446490, Meleagridinae ott781250, Meleagris ott446481, mrcaott49310ott51349, mrcaott49310ott49319, mrcaott49310ott153554, mrcaott153554ott867027, Gallus ott153562, mrcaott153554ott240568, mrcaott30843ott4947869, Anseriformes ## ott241841, mrcaott30843ott714464, Anatidae ott765193, mrcaott30843ott88380, mrcaott30843ott1082830, mrcaott30843ott75874, mrcaott30843ott432041, mrcaott30843ott30847, mrcaott30843ott166683, mrcaott30843ott30845, mrcaott30845ott30850, mrcaott30850ott82415, ## mrcaott30850ott82420, mrcaott30850ott656780, mrcaott30850ott82414, mrcaott30850ott82425, mrcaott30850ott765188, mrcaott30850ott332079, mrcaott30850ott30858, mrcaott30850ott90669, mrcaott30850ott30855, mrcaott30850ott604172, mrcaott30850ott339494, ## mrcaott30850ott82410, mrcaott30850ott604175, mrcaott30850ott190881, mrcaott190881ott604182 ``` ``` r plot(tr) ``` ![plot of chunk unnamed-chunk-16](fig-vignettes-unnamed-chunk-16-1.png) rotl/inst/doc/data_mashups.Rmd0000644000176200001440000004603315132142351016074 0ustar liggesusers--- title: "Connecting data to Open Tree trees" author: "David Winter" date: "2026-01-15" output: rmarkdown::html_vignette: css: vignette.css vignette: > %\VignetteIndexEntry{Connecting data to Open Tree trees} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} \usepackage[utf8]{inputenc} --- ## Combining data from OToL and other sources. One of the major goals of `rotl` is to help users combine data from other sources with the phylogenetic trees in the Open Tree database. This examples document describes some of the ways in which a user might connect data to trees from Open Tree. ## Get Open Tree IDs to match your data. Let's say you have a dataset where each row represents a measurement taken from one species, and your goal is to put these measurements in some phylogenetic context. Here's a small example: the best estimate of the mutation rate for a set of unicellular Eukaryotes along with some other property of those species which might explain the mutation rate: ``` r csv_path <- system.file("extdata", "protist_mutation_rates.csv", package = "rotl") mu <- read.csv(csv_path, stringsAsFactors = FALSE) mu ``` ``` ## species mu pop.size genome.size ## 1 Tetrahymena thermophila 7.61e-12 1.12e+08 1.04e+08 ## 2 Paramecium tetraurelia 1.94e-11 1.24e+08 7.20e+07 ## 3 Chlamydomonas reinhardtii 2.08e-10 1.00e+08 1.12e+08 ## 4 Dictyostelium discoideum 2.90e-11 7.40e+06 3.40e+07 ## 5 Saccharomyces cerevisiae 3.30e-10 1.00e+08 1.25e+08 ## 6 Saccharomyces pombe 2.00e-10 1.00e+07 1.25e+08 ``` If we want to get a tree for these species we need to start by finding the unique ID for each of these species in the Open Tree database. We can use the Taxonomic Name Resolution Service (`tnrs`) functions to do this. Before we do that we should see if any of the taxonomic contexts, which can be used to narrow a search and avoid conflicts between different codes, apply to our group of species: ``` r library(rotl) tnrs_contexts() ``` ``` ## Possible contexts: ## Animals ## Birds, Tetrapods, Mammals, Amphibians, Vertebrates ## Arthropods, Molluscs, Nematodes, Platyhelminthes, Annelids ## Cnidarians, Arachnids, Insects ## Fungi ## Basidiomycetes, Ascomycetes ## All life ## Bacteria ## SAR group, Archaea, Excavata, Amoebozoa, Centrohelida ## Haptophyta, Apusozoa, Diatoms, Ciliates, Forams ## Land plants ## Hornworts, Mosses, Liverworts, Vascular plants, Club mosses ## Ferns, Seed plants, Flowering plants, Monocots, Eudicots ## Rosids, Asterids, Asterales, Asteraceae, Aster ## Symphyotrichum, Campanulaceae, Lobelia ``` Hmm, none of those groups contain all of our species. In this case we can search using the `All life` context and the function `tnrs_match_names`: ``` r taxon_search <- tnrs_match_names(names = mu$species, context_name = "All life") knitr::kable(taxon_search) ``` |search_string |unique_name |approximate_match | score| ott_id|is_synonym |flags | number_matches| |:-------------------------|:-------------------------|:-----------------|-----:|------:|:----------|:-----|--------------:| |tetrahymena thermophila |Tetrahymena thermophila |FALSE | 1| 180195|FALSE | | 1| |paramecium tetraurelia |Paramecium tetraurelia |FALSE | 1| 568130|FALSE | | 1| |chlamydomonas reinhardtii |Chlamydomonas reinhardtii |FALSE | 1| 33153|FALSE | | 1| |dictyostelium discoideum |Dictyostelium discoideum |FALSE | 1| 160850|FALSE | | 1| |saccharomyces cerevisiae |Saccharomyces cerevisiae |FALSE | 1| 356221|FALSE | | 1| |saccharomyces pombe |Schizosaccharomyces pombe |FALSE | 1| 990004|TRUE | | 1| Good, all of our species are known to Open Tree. Note, though, that one of the names is a synonym. _Saccharomyces pombe_ is older name for what is now called _Schizosaccharomyces pombe_. As the name suggests, the Taxonomic Name Resolution Service is designed to deal with these problems (and similar ones like misspellings), but it is always a good idea to check the results of `tnrs_match_names` closely to ensure the results are what you expect. In this case we have a good ID for each of our species so we can move on. Before we do that, let's ensure we can match up our original data to the Open Tree names and IDs by adding them to our `data.frame`: ``` r mu$ott_name <- unique_name(taxon_search) mu$ott_id <- taxon_search$ott_id ``` ## Find a tree with your taxa Now let's find a tree. There are two possible options here: we can search for published studies that include our taxa or we can use the 'synthetic tree' from Open Tree. We can try both approaches. ### Published trees Before we can search for published studies or trees, we should check out the list of properties we can use to perform such searches: ``` r studies_properties() ``` ``` ## $tree_properties ## [1] "ot:specifiedRoot" "ot:unrootedTree" "ot:nodeLabelTimeUnit" "xsi:type" "ot:MRCAName" "ot:nodeLabelDescription" "ot:nearestTaxonMRCAOttId" ## [8] "ot:reasonsToExcludeFromSynthesis" "ot:curatedType" "ot:nearestTaxonMRCAName" "ot:studyId" "ot:nodeLabelMode" "rootedge" "nodeById" ## [15] "tb:type.tree" "ot:branchLengthDescription" "ot:messages" "ot:rootNodeId" "ot:inGroupClade" "ot:ottId" "ot:branchLengthMode" ## [22] "ot:MRCAOttId" "ot:ottTaxonName" "tb:quality.tree" "tb:kind.tree" "ot:outGroupEdge" "ntips" "edgeBySourceId" ## [29] "label" "meta" "tb:ntax.tree" "ot:tag" "ot:branchLengthTimeUnit" ## ## $study_properties ## [1] "tb:identifier.study.tb1" "id" "ot:taxonLinkPrefixes" "ot:studyYear" "prism:publicationName" "dc:title" "prism:creationDate" "xmlns" ## [9] "skos:changeNote" "skos:historyNote" "ot:notIntendedForSynthesis" "ot:otusElementOrder" "dc:date" "xhtml:license" "prism:startingPage" "prism:publicationDate" ## [17] "ot:focalCladeOTTTaxonName" "prism:section" "prism:pageRange" "ot:messages" "ot:studyPublicationReference" "ot:curatorName" "ot:dataDeposit" "prism:number" ## [25] "ot:agents" "dc:publisher" "treesById" "dcterms:bibliographicCitation" "ot:treesElementOrder" "prism:modificationDate" "tb:identifier.study" "about" ## [33] "ntrees" "nexmljson" "ot:comment" "dc:contributor" "dc:creator" "prism:volume" "tb:title.study" "treebaseId" ## [41] "prism:endingPage" "generator" "version" "ot:studyId" "ot:candidateTreeForSynthesis" "otusById" "prism:doi" "dc:subject" ## [49] "ot:studyPublication" "ot:focalClade" "ot:annotationEvents" "ot:tag" "nexml2json" ``` We have `ottIds` for our taxa, so let's use those IDs to search for trees that contain them. Starting with our first species _Tetrahymena thermophila_ we can use `studies_find_trees` to do this search. ``` r studies_find_trees(property = "ot:ottId", value = as.character(ott_id(taxon_search)[1])) ``` ``` ## study_ids n_trees tree_ids candidate study_year title study_doi ## 1 ot_1587 1 tree1 2015 'Phylogenomic analyses reveal subclass Scuticociliatia as the sister group of subclass Hymenostomatia within class Oligohymenophorea' http://dx.doi.org/10.1016/j.ympev.2015.05.007 ## 2 ot_1589 1 tree1 2015 'Phylogenomic analyses reveal subclass Scuticociliatia as the sister group of subclass Hymenostomatia within class Oligohymenophorea' http://dx.doi.org/10.1016/j.ympev.2015.05.007 ## 3 ot_2037 4 tree10, tree11, tree12, tree13 2018 http://dx.doi.org/10.1038/s41586-018-0708-8 ## 4 ot_409 2 tree1, tree2 tree2 2015 Tree of life reveals clock-like speciation and diversification http://dx.doi.org/10.1093/molbev/msv037 ## 5 ot_564 1 Tr85317 Tr85317 2015 'The alveolate translation initiation factor 4E family reveals a custom toolkit for translational control in core dinoflagellates' http://dx.doi.org/10.1186/s12862-015-0301-9 ## 6 ot_579 1 Tr60046 2013 'Convergent evolution of heat-inducibility during subfunctionalization of the Hsp70 gene family' http://dx.doi.org/10.1186/1471-2148-13-49 ## 7 ot_700 1 tree1 tree1 2016 'A new view of the tree of life' http://dx.doi.org/10.1038/nmicrobiol.2016.48 ## 8 ot_73 1 tree1 tree1 2013 Deep relationships of Rhizaria revealed by phylogenomics: A farewell to Haeckel’s Radiolaria http://dx.doi.org/10.1016/j.ympev.2012.12.011 ## 9 ot_766 1 Tr85440 2015 'Bacterial proteins pinpoint a single eukaryotic root' http://dx.doi.org/10.1073/pnas.1420657112 ## 10 ot_767 1 tree1 tree1 2016 'Untangling the early diversification of eukaryotes: a phylogenomic study of the evolutionary origins of Centrohelida http://dx.doi.org/10.1098/rspb.2015.2802 ## 11 ot_87 1 Tr64119 Tr64119 2014 'Dinoflagellate phylogeny revisited: Using ribosomal proteins to resolve deep branching dinoflagellate clades' http://dx.doi.org/10.1016/j.ympev.2013.10.007 ## n_matched_trees match_tree_ids ## 1 1 tree1 ## 2 1 tree1 ## 3 3 tree10, tree13, tree11 ## 4 1 tree2 ## 5 1 Tr85317 ## 6 1 Tr60046 ## 7 1 tree1 ## 8 1 tree1 ## 9 1 Tr85440 ## 10 1 tree1 ## 11 1 Tr64119 ## [ reached 'max' / getOption("max.print") -- omitted 16 rows ] ``` Well... that's not very promising. We can repeat that process for all of the IDs to see if the other species are better represented. ``` r hits <- lapply(mu$ott_id, studies_find_trees, property = "ot:ottId", detailed = FALSE) sapply(hits, function(x) sum(x[["n_matched_trees"]])) ``` ``` ## [1] 51 51 128 71 18 89 ``` OK, most of our species are not in any of the published trees available. You can help fix this sort of problem by [making sure you submit your published trees to Open Tree](https://tree.opentreeoflife.org/curator). ### A part of the synthesis tree Thankfully, we can still use the complete Tree of Life made from the combined results of all of the published trees and taxonomies that go into Open Tree. The function `tol_induced_subtree` will fetch a tree relating a set of IDs. Using the default arguments you can get a tree object into your R session: ``` r ott_in_tree <- ott_id(taxon_search)[is_in_tree(ott_id(taxon_search))] tr <- tol_induced_subtree(ott_ids = ott_in_tree) ``` ``` ## Warning in collapse_singles(tr, show_progress): Dropping singleton nodes with labels: mrcaott2ott276, mrcaott2ott142555, mrcaott2ott1551, mrcaott2ott7623, Chloroplastida ott361838, Chlorophyta ott979501, mrcaott185ott42071, mrcaott185ott1426, mrcaott1426ott1544, ## mrcaott1544ott8659, mrcaott1544ott15345, mrcaott1544ott9282, mrcaott9389ott818260, mrcaott9389ott23557, mrcaott23557ott527099, mrcaott148ott902, SAR ott5246039, Alveolata ott266751, Ciliophora (phylum in subkingdom SAR) ott302424, Intramacronucleata ott340382, ## mrcaott1546ott1671, Conthreep ott5248773, mrcaott1671ott16129, Peniculia ott1002116, Paramecium (genus in subkingdom SAR) ott568126, mrcaott11752ott13570, Hymenostomatia ott5257367, Tetrahymena (genus in subkingdom SAR) ott47284, mrcaott295406ott523463, ## mrcaott295406ott523462, mrcaott3973ott4738988, Amoebozoa ott1064655, mrcaott3973ott15653, mrcaott3973ott26103, mrcaott26103ott273110, mrcaott26103ott229626, Dictyostelia ott835575, mrcaott26103ott59686, Dictyosteliales ott4008839, Dictyosteliaceae ott4008841, ## Dictyostelium ott999665, mrcaott42ott240665, Opisthokonta ott332573, Nucletmycea ott5246132, Fungi ott352914, mrcaott109ott3465, mrcaott109ott67172, mrcaott109ott1423, mrcaott109ott9352, h2007-2 ott5576447, h2007-1 ott5584405, Dikarya ott656316, ## mrcaott235ott3445, saccharomyceta ott1098854, Saccharomycotina ott971714, Saccharomycetes (class in h2007-2) ott989999, Saccharomycetales ott4085960, Saccharomycetaceae ott989994, Saccharomyces ott908546, Schizosaccharomycetes ott921286, Schizosaccharomycetidae ## ott5670481, Schizosaccharomycetales ott508517, Schizosaccharomycetaceae ott990009, Schizosaccharomyces ott990008 ``` ``` r plot(tr) ``` ![plot of chunk subtree](fig-vignettes-subtree-1.png) ### Connect your data to the tips of your tree Now we have a tree for of our species, how can we use the tree and the data together? The package `phylobase` provide an object class called `phylo4d`, which is designed to represent a phylogeny and data associated with its tips. In order to get our tree and data into one of these objects we have to make sure the labels in the tree and in our data match exactly. That's not quite the case at the moment (tree labels have underscores and IDs appended): ``` r mu$ott_name[1] ``` ``` ## $`Tetrahymena thermophila` ## [1] "Tetrahymena thermophila" ``` ``` r tr$tip.label[4] ``` ``` ## [1] "Dictyostelium_discoideum_ott160850" ``` `rotl` provides a convenience function `strip_ott_ids` to deal with these. ``` r tr$tip.label <- strip_ott_ids(tr$tip.label, remove_underscores = TRUE) tr$tip.label %in% mu$ott_name ``` ``` ## [1] TRUE TRUE TRUE TRUE TRUE TRUE ``` Ok, now the tips are together we can make a new dataset. The `phylo4d()` functions matches tip labels to the row names of a `data.frame`, so let's make a new dataset that contains just the relevant data and has row names to match the tree ``` r library(phylobase) ``` ``` ## Error in `library()`: ## ! there is no package called 'phylobase' ``` ``` r mu_numeric <- mu[, c("mu", "pop.size", "genome.size")] rownames(mu_numeric) <- mu$ott_name tree_data <- phylo4d(tr, mu_numeric) ``` ``` ## Error in `phylo4d()`: ## ! could not find function "phylo4d" ``` And now we can plot the data and the tree together ``` r plot(tree_data) ``` ``` ## Error: ## ! object 'tree_data' not found ``` ## Find external data associated with studies, trees and taxa from Open Tree In the above example we looked for a tree that related species in another dataset. Now we will go the other way, and try to find data associated with Open Tree records in other databases. ### Get external data from a study Let's imagine you were interested in extending or reproducing the results of a published study. If that study is included in Open Tree you can find it via `studies_find_studies` or `studies_find_trees` and retrieve the published trees with `get_study`. `rotl` will also help you find external. The function `study_external_IDs` retrieves the DOI for a given study, and uses that to gather some more data: ``` r extra_data <- try(study_external_IDs("pg_1980"), silent = TRUE) ``` ``` ## Warning in check_xml_errors(x): Invalid db name specified: popset ``` ``` r if (!inherits(extra_data, "try-error")) { extra_data } ``` Here the returned object contains an `external_data_url` (in this case a link to the study in Treebase), a pubmed ID for the paper and a vector IDs for the NCBI's nucleotide database. The packages `treebase` and `rentrez` provide functions to make use of these IDs within R. As an example, let's use `rentrez` to download the first two DNA seqences and print them. ``` r library(rentrez) seqs <- try(entrez_fetch(db = "nucleotide", id = extra_data$nucleotide_ids[1:2], rettype = "fasta"), silent = TRUE) if (inherits(seqs, "try-error")) { cat("NCBI temporarily down.") } else { cat(seqs) } ``` ``` ## NCBI temporarily down. ``` You could further process these sequences in R with the function `read.dna` from `ape` or save them to disk by specifying a file name with `cat`. ### Find a OTT taxon in another taxonomic database It is also possible map an Open Tree taxon to a record in another taxonomic database. For instance, if we wanted to search for data about one of the tips of the sub-tree we fetched in the example above we could do so using `taxon_external_IDs`: ``` r Tt_ids <- taxon_external_IDs(mu$ott_id[2]) Tt_ids ``` ``` ## source id ## 1 silva AY102613 ## 2 ncbi 5888 ## 3 gbif 7415807 ``` A user could then use `rgbif` to find locality records using the gbif ID or `rentrez` to get genetic or bibliometric data about from the NCBI's databases. ## What next The demonstration gets you to the point of visualizing your data in a phylogenetic context. But there's a lot more you do with this sort of data in R. For instance, you could use packages like `ape`, `caper`, `phytools` and `mcmcGLMM` to perform phylogenetic comparative analyses of your data. You could gather more data on your species using packages that connect to trait databases like `rfishbase`, `AntWeb` or `rnpn` which provides data from the US National Phenology Network. You could also use `rentrez` to find genetic data for each of your species, and use that data to generate branch lengths for the phylogeny. rotl/inst/doc/meta-analysis.Rmd0000644000176200001440000005014115132142363016170 0ustar liggesusers--- title: "Using the Open Tree synthesis in a comparative analysis" author: "David Winter" date: "2026-01-15" output: rmarkdown::html_vignette: css: vignette.css vignette: > %\VignetteIndexEntry{Using the Open Tree synthesis in a comparative analysis} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} %\VignetteEncoding{UTF-8} --- ## Phylogenetic Comparative Methods The development of phylogenetic comparative methods has made phylogenies and important source of data in fields as diverse as ecology, genomic and medicine. Comparative methods can be used to investigate patterns in the evolution of traits or the diversification of lineages. In other cases a phylogeny is treated as a "nuisance parameter", allowing with the autocorrelation created by the shared evolutionary history of the different species included to be controlled for. In many cases finding a tree that relates the species for which trait data are available is a rate-limiting step in such comparative analyses. Here we show how the synthetic tree provided by Open Tree of Life (and made available in R via `rotl`) can help to fill this gap. ## A phylogenetic meta-analysis To demonstrate the use of `rotl` in a comparative analysis, we will partially reproduce the results of [Rutkowska _et al_ 2014](https://doi.org/10.1111/jeb.12282). Very briefly, this study is a meta-analysis summarising the results of multiple studies testing for systematic differences in the size of eggs which contain male and female offspring. Such a difference might mean that birds invest more heavily in one sex than the other. Because this study involves data from 51 different species, Rutkowska _et al_ used a phylogenetic comparative approach to account for the shared evolutionary history among some of the studied-species. ### Gather the data If we are going to reproduce this analysis, we will first need to gather the data. Thankfully, the data is available as supplementary material from the publisher's website. We provide a copy of this data with the package: ``` r library(rotl) ``` ``` r ## This dataset is available from the publisher's study website: egg_data <- read.csv(system.file("extdata", "egg.csv", package = "rotl"), stringsAsFactors = FALSE ) ## } head(egg_data) ``` ``` ## animal Spp Lndim Measure Neggs Nclutches ESr Type StudyID Year D EN Zr VZr ## 1 Zonotrichia_leucophrys White-crowned sparrow 0.000000000 volume 294 73 0.14004594 stat Mead1987 1987 3.421918 85.91673 0.14097244 0.012060292 ## 2 Passer_domesticus House sparrow 0.009407469 volume 149 31 0.11175203 stat Cordero2000 2000 4.045161 36.83413 0.11222075 0.029555954 ## 3 Serinus_canaria Canary 0.000000000 volume 52 21 0.49679140 stat Leitner2006 2006 2.180952 23.84279 0.54503712 0.047978211 ## 4 Turdus_merula European blackbird 0.021189299 volume 82 54 0.38598540 stat Martyka2010 2010 1.414815 57.95812 0.40707397 0.018195675 ## 5 Agelaius_phoeniceus Red-winged blackbird 0.218316086 volume 394 106 0.07410136 raw Weatherhead1985 1985 3.173585 124.14982 0.07423744 0.008254242 ## 6 Quiscalus_mexicanus Great-tailed grackle 0.281894985 mass 822 205 0.05178834 raw Teather1989 1989 3.407805 241.21099 0.05183471 0.004197959 ``` The most important variable in this dataset is `Zr`, which is a [normalized effect size](https://en.wikipedia.org/wiki/Fisher_transformation) for difference ,in size between eggs that contain males and females. Values close to zero come from studies that found the sex of an egg's inhabitant had little effect in its size, while large positive or negative values correspond to studies with substantial sex biases (towards males and females respectively). Since this is a meta-analysis we should produce the classic [funnel plot](https://en.wikipedia.org/wiki/Funnel_plot) with effects-size on the y-axis and precision (the inverse of the sample standard error) on the x-axis. Here we calculate precision from the sample variance (`Vzr`): ``` r plot(1 / sqrt(egg_data$VZr), egg_data$Zr, pch = 16, ylab = "Effect size (Zr)", xlab = "Precision (1/SE)", main = "Effect sizes for sex bias in egg size among 51 brid species" ) ``` ![plot of chunk eggs_in_a_funnel](fig-vignettes-eggs_in_a_funnel-1.png) In order to use this data later on we need to first convert it to a standard `data.frame`. We can also convert the `animal` column (the species names) to lower case, and remove the underscores in their names, which will make it easier to match names later on: ``` r egg_data <- as.data.frame(egg_data) ## Convert taxon names to lower case egg_data$animal <- tolower(egg_data$animal) ## Let's remove the underscores (_) from the taxon names egg_data$animal <- gsub("_", " ", egg_data$animal) ``` ### Find the species in OTT We can use the OTL synthesis tree to relate these species. To do so we first need to find Open Tree Taxonomy (OTT) IDs for each species. We can do that with the Taxonomic Name Resolution Service function `tnrs_match_names`: ``` r taxa <- tnrs_match_names(unique(egg_data$animal), context_name = "Animals") head(taxa) ``` ``` ## search_string unique_name approximate_match score ott_id is_synonym flags number_matches ## 1 zonotrichia leucophrys Zonotrichia leucophrys FALSE 1 265553 FALSE 1 ## 2 passer domesticus Passer domesticus FALSE 1 745175 FALSE 1 ## 3 serinus canaria Serinus canaria FALSE 1 464865 FALSE sibling_higher 1 ## 4 turdus merula Turdus merula FALSE 1 568572 FALSE 1 ## 5 agelaius phoeniceus Agelaius phoeniceus FALSE 1 226605 FALSE 1 ## 6 quiscalus mexicanus Quiscalus mexicanus FALSE 1 743411 FALSE 1 ``` All of these species are in OTT, but a few of them go by different names in the Open Tree than we have in our data set. Because the tree `rotl` fetches will have Open Tree names, we need to create a named vector that maps the names we have for each species to the names Open Tree uses for them: ``` r taxon_map <- structure(taxa$search_string, names = taxa$unique_name) ``` Now we can use this map to retrieve "data set names" from "OTT names": ``` r taxon_map["Anser caerulescens"] ``` ``` ## Anser caerulescens ## "chen caerulescens" ``` ### Get a tree Now we can get the tree. There are really too many tips here to show nicely, so we will leave them out of this plot ``` r tr <- tol_induced_subtree(ott_id(taxa)[is_in_tree(ott_id(taxa))]) ``` ``` ## Warning in collapse_singles(tr, show_progress): Dropping singleton nodes with labels: mrcaott246ott92263, mrcaott246ott1858, mrcaott246ott3600042, mrcaott246ott7113, Passeriformes ott1041547, mrcaott246ott3212, mrcaott246ott428578, mrcaott246ott44866, ## mrcaott246ott5929, mrcaott246ott96288, mrcaott246ott310390, mrcaott246ott176461, mrcaott246ott22325, mrcaott246ott10351, mrcaott246ott72472, mrcaott246ott5934, mrcaott246ott3599436, mrcaott246ott1566, mrcaott1566ott3598440, mrcaott1566ott496009, ## mrcaott1566ott35326, mrcaott1566ott92668, mrcaott1566ott24297, mrcaott1566ott22300, mrcaott22300ott35350, mrcaott22300ott32651, mrcaott22300ott547548, mrcaott22300ott67150, mrcaott22300ott130294, mrcaott22300ott7660860, mrcaott22300ott416087, ## mrcaott22300ott416089, mrcaott22300ott107840, mrcaott113980ott364210, mrcaott113980ott3598839, mrcaott3598839ott5341363, mrcaott19467ott431648, mrcaott19467ott401023, mrcaott19467ott252687, mrcaott19467ott233446, mrcaott19467ott378061, mrcaott19467ott1046624, ## mrcaott19467ott161293, mrcaott19467ott46396, mrcaott46396ott46399, mrcaott46399ott168083, mrcaott168083ott691103, mrcaott2175ott600902, mrcaott2175ott259082, mrcaott2175ott59905, mrcaott2175ott2224, mrcaott2224ott366470, mrcaott3364ott310375, mrcaott3364ott4083, ## mrcaott4083ott35042, mrcaott4083ott35053, mrcaott4083ott370807, mrcaott4083ott469177, mrcaott4083ott11712, mrcaott4083ott52094, mrcaott4083ott95949, Erythrura ott465905, mrcaott24017ott24025, mrcaott24025ott596763, mrcaott24025ott389884, mrcaott24025ott453058, ## mrcaott24025ott865473, mrcaott24025ott141501, mrcaott141501ott389883, mrcaott141501ott3597689, mrcaott141501ott865472, mrcaott141501ott3597698, mrcaott105913ott596770, mrcaott105913ott3599583, mrcaott105913ott543841, mrcaott105913ott124463, ## mrcaott124463ott445491, mrcaott445491ott7068429, mrcaott445491ott708327, mrcaott4088ott95302, mrcaott4088ott8371, mrcaott4088ott138768, mrcaott4088ott28339, mrcaott4088ott5616, mrcaott5616ott6023, mrcaott6023ott243614, mrcaott6023ott101225, mrcaott6023ott125079, ## mrcaott125079ott463026, mrcaott125079ott765405, Zonotrichia (genus in domain Eukaryota) ott789032, mrcaott125079ott265547, mrcaott125079ott265554, mrcaott5620ott254662, mrcaott5620ott29804, mrcaott29804ott998133, mrcaott29804ott449562, mrcaott29804ott86894, ## mrcaott29804ott93045, mrcaott93045ott264496, mrcaott264496ott264500, mrcaott264500ott3597163, mrcaott264500ott283668, Quiscalus ott743410, mrcaott283673ott673386, mrcaott283673ott741944, mrcaott283673ott735243, mrcaott213448ott213452, mrcaott213448ott1009279, ## mrcaott213448ott213451, mrcaott213454ott430627, Agelaius ott617799, mrcaott430627ott617797, mrcaott430627ott3597159, mrcaott99175ott364331, Xanthocephalus ott364336, mrcaott6366ott28332, mrcaott6366ott88283, mrcaott6366ott341465, mrcaott6366ott157599, ## mrcaott6366ott178457, mrcaott6366ott405215, mrcaott6366ott238137, mrcaott6366ott6375, mrcaott6375ott119724, mrcaott6375ott328909, mrcaott328909ott464865, mrcaott464865ott1083724, Haemorhous ott3601758, mrcaott9416ott580155, mrcaott9416ott840030, ## mrcaott9416ott96147, mrcaott9416ott749634, Passer ott515158, mrcaott9416ott7661508, mrcaott9416ott25628, mrcaott9416ott407763, mrcaott9416ott407764, mrcaott9416ott68955, mrcaott9416ott73636, mrcaott73636ott5859927, mrcaott73636ott995847, mrcaott1488ott63797, ## mrcaott1488ott284404, mrcaott1488ott107463, mrcaott1488ott17016, mrcaott1488ott16185, Hirundinidae ott897681, mrcaott16185ott67921, mrcaott16185ott67916, mrcaott67916ott368059, mrcaott67916ott67920, mrcaott67920ott3597799, Delichon ott922719, ## mrcaott44217ott107476, mrcaott107476ott177058, mrcaott107476ott446183, mrcaott107476ott337755, mrcaott107476ott337752, mrcaott337752ott374222, mrcaott337752ott337762, mrcaott337752ott3598087, mrcaott337752ott496789, mrcaott2375ott73144, mrcaott2375ott124085, ## mrcaott2375ott71358, mrcaott2375ott814750, mrcaott2375ott61147, mrcaott61147ott84656, mrcaott61147ott123763, mrcaott123763ott258794, mrcaott4820ott294599, mrcaott4820ott75981, mrcaott4820ott379708, mrcaott4820ott17162, mrcaott4820ott20998, mrcaott4820ott20989, ## mrcaott4820ott58860, mrcaott4820ott23690, mrcaott4820ott20996, mrcaott4820ott749725, mrcaott4820ott11462, mrcaott4820ott140440, mrcaott4820ott197505, mrcaott4820ott75978, mrcaott4820ott11315, mrcaott4820ott5933, mrcaott5933ott662804, mrcaott5933ott60465, ## mrcaott5933ott25637, mrcaott25637ott473431, mrcaott25637ott199843, mrcaott25637ott111993, mrcaott25637ott183621, mrcaott183621ott282315, mrcaott282315ott501241, mrcaott501241ott597018, mrcaott686165ott686168, mrcaott60456ott75990, mrcaott60456ott894604, Pica ## ott776480, Falconiformes ott212187, Falconidae ott212186, mrcaott47588ott225286, mrcaott47588ott748842, mrcaott47588ott3596147, Falco ott786441, mrcaott179290ott624976, mrcaott179290ott624973, mrcaott179290ott3596145, mrcaott179290ott624974, ## mrcaott179290ott432111, mrcaott179290ott285806, Cerchneis ott3596159, mrcaott5272ott928360, mrcaott5272ott7145, mrcaott5272ott24121, Scolopacidae ott887699, mrcaott24121ott217797, mrcaott24121ott45306, mrcaott24121ott55408, mrcaott24121ott420370, ## mrcaott24121ott654830, mrcaott24121ott214779, mrcaott24121ott1090732, mrcaott7639ott306220, mrcaott7639ott57833, mrcaott7639ott738512, mrcaott7639ott279504, mrcaott7639ott47401, mrcaott47401ott234666, mrcaott234666ott341044, mrcaott234666ott651058, ## mrcaott234666ott341047, mrcaott234666ott285543, mrcaott285543ott341030, mrcaott285543ott341032, mrcaott285543ott738509, mrcaott285543ott966606, mrcaott285543ott966604, mrcaott22965ott80679, mrcaott22965ott154126, mrcaott22965ott373759, mrcaott22965ott282132, ## mrcaott22965ott414141, mrcaott22965ott335737, mrcaott22965ott509055, mrcaott22965ott324050, mrcaott22965ott910287, mrcaott22965ott353849, mrcaott22965ott335736, mrcaott22965ott526679, mrcaott22965ott75913, mrcaott75913ott515357, mrcaott75913ott119602, ## mrcaott75913ott993041, mrcaott425206ott887691, mrcaott425206ott515355, mrcaott241571ott993045, mrcaott241571ott1026258, mrcaott241571ott254356, mrcaott241571ott704181, mrcaott704181ott4947414, mrcaott147723ott219032, Stercorariidae ott168297, Stercorarius ## ott742632, mrcaott742640ott742641, mrcaott57823ott57827, mrcaott57823ott242771, mrcaott57823ott80080, mrcaott57823ott112937, mrcaott112937ott673638, mrcaott112937ott129402, mrcaott112937ott242776, mrcaott242776ott3596974, mrcaott242776ott3596977, ## mrcaott242776ott313115, mrcaott242776ott413796, mrcaott5481ott9830, mrcaott9830ott86672, mrcaott9830ott90560, mrcaott9830ott324158, mrcaott9830ott55044, mrcaott9830ott285638, mrcaott9830ott117726, Sulidae ott452462, mrcaott170197ott403772, Sula ott160486, ## mrcaott170197ott5859716, mrcaott170197ott429615, mrcaott429615ott1030312, Procellariiformes ott452461, Diomedeidae ott85277, mrcaott71459ott320282, Phoebastria ott941509, mrcaott320282ott320284, Sphenisciformes ott494366, Spheniscidae ott494367, ## mrcaott60413ott3600120, mrcaott60413ott4130813, mrcaott60413ott4130835, mrcaott60413ott4130832, mrcaott60413ott3600127, mrcaott60413ott4130831, mrcaott60413ott3600124, mrcaott60413ott3600128, mrcaott60413ott3600129, mrcaott60413ott4130848, mrcaott60413ott4130817, ## mrcaott60413ott494361, mrcaott60413ott60417, mrcaott60413ott3600131, mrcaott60413ott7068884, Eudyptes ott494364, mrcaott60413ott88590, mrcaott88590ott7068880, mrcaott88590ott116946, Pygoscelis ott494365, mrcaott134466ott783352, mrcaott5021ott198671, ## mrcaott5021ott75792, Cuculiformes ott212171, mrcaott75792ott212172, mrcaott75792ott3601282, mrcaott75792ott119216, mrcaott119216ott526771, mrcaott119216ott169265, mrcaott169265ott550039, mrcaott169265ott462546, mrcaott462546ott3596360, mrcaott462546ott3596355, ## mrcaott462546ott1050027, Cuculus ott1041429, mrcaott549514ott7068132, mrcaott549514ott3596308, mrcaott549514ott3596307, mrcaott549514ott3596306, mrcaott549514ott792626, mrcaott17146ott57819, Columbiformes ott363030, mrcaott28925ott45505, mrcaott45505ott604973, ## mrcaott45505ott50388, mrcaott45505ott277822, mrcaott45505ott51607, mrcaott51607ott67614, mrcaott51607ott331474, mrcaott51607ott277817, mrcaott51607ott320359, mrcaott320359ott493986, mrcaott320359ott767317, mrcaott320359ott921832, mrcaott320359ott938416, ## mrcaott4765ott4131031, Galliformes ott837585, mrcaott4765ott6520194, mrcaott4765ott109888, mrcaott4765ott75785, m ``` ``` r plot(tr, show.tip.label = FALSE) ```
plot of chunk birds_in_a_tree

plot of chunk birds_in_a_tree

There are a few things to note here. First, the tree has no branch lengths. At present this is true for the whole of the Open Tree synthetic tree. Some comparative methods require either branch lengths or an ultrametric tree. Before you can use one of those methods you will need to get a tree with branch lengths. You could try looking for published trees made available by the Open Tree with `studies_find_trees`. Alternatively, you could estimate branch lengths from the toplogy of a phylogeny returned by `tol_induced_subtree`, perhaps by downloading DNA sequences from the NCBI with `rentrez` or "hanging" the tree on nodes of known-age using penalized likelihood method in `ape::chronos`. In this case, we will use only the topology of the tree as input to our comparative analysis, so we can skip these steps. Second, the tip labels contain OTT IDs, which means they will not perfectly match the species names in our dataset or the taxon map that we created earlier: ``` r tr$tip.label[1:4] ``` ``` ## [1] "Ficedula_albicollis_ott107840" "Luscinia_svecica_ott274225" "Turdus_merula_ott568572" "Sturnus_unicolor_ott366470" ``` Finally, the tree contains node labels for those nodes that match a higher taxonomic group, and empty character vectors (`""`) for all other nodes. Some comparative methods either do no expect node labels at all, or require all labeled nodes to have a unique name (meaning multiple "empty" labels will cause and error). We can deal with all these details easily. `rotl` provides the convenience function `strip_ott_ids` to remove the extra information from the tip labels. With the IDs removed, we can use our taxon map to replace the tip labels in the tree with the species names from dataset. ``` r otl_tips <- strip_ott_ids(tr$tip.label, remove_underscores = TRUE) tr$tip.label <- taxon_map[ otl_tips ] ``` Finally, we can remove the node labels by setting the `node.label` attribute of the tree to `NULL`. ``` r tr$node.label <- NULL ``` ``` r egg_data <- egg_data[egg_data$animal %in% tr$tip.label, ] ``` ### Perform the meta-analysis Now we have data and a tree, and we know the names in the tree match the ones in the data. It's time to do the comparative analysis. Rutkowska _et al_. used `MCMCglmm`, a Bayesian MCMC approach to fitting multi-level models,to perform their meta-analysis, and we will do the same. Of course, to properly analyse these data you would take some care in deciding on the appropriate priors to use and inspect the results carefully. In this case, we are really interested in using this as a demonstration, so we will just run a simple model. Specifically we sill fit a model where the only variable that might explain the values of `Zr` is the random factor `animal`, which corresponds to the phylogenetic relationships among species. We also provide `Zvr` as the measurement error variance, effectively adding extra weight to the results of more powerful studies. Here's how we specify and fit that model with `MCMCglmm`: ``` r set.seed(123) if (require(MCMCglmm, quietly = TRUE)) { pr <- list( R = list(V = 1, nu = 0.002), G = list(G1 = list(V = 1, nu = 0.002)) ) model <- MCMCglmm(Zr ~ 1, random = ~animal, pedigree = tr, mev = egg_data$VZr, prior = pr, data = egg_data, verbose = FALSE ) } else { model <- readRDS(file = system.file("extdata", "mcmcglmm_model.rds", package = "rotl")) } ``` Now that we have a result we can find out how much phylogenetic signal exists for sex-biased differences in egg-size. In a multi-level model we can use variance components to look at this, specifically the proportion of the total variance that can be explained by phylogeny is called the phylogenetic reliability, _H_. Let's calculate the _H_ for this model: ``` r var_comps <- colMeans(model$VCV) var_comps["animal"] / sum(var_comps) ``` ``` ## animal ## 0.00313885 ``` It appears there is almost no phylogenetic signal to the data. The relationships among species explain much less that one percent of the total variance in the data. If you were wondering, Rutkowska _et al_. report a similar result, even after adding more predictors to their model most of the variance in `Zr` was left unexplained. ## What other comparative methods can I use in R? Here we have demonstrated just one comparative analysis that you might do in R. There are an ever-growing number of packages that allow an ever-growing number of analysis to performed in R. Some "classics" like ancestral state reconstruction, phylogenetic independent contrasts and lineage through time plots are implemented in `ape`. Packages like `phytools`, `caper` and `diversitree` provide extensions to these methods. The [CRAN Phylogenetics Taskview](https://github.com/bomeara/PhylogeneticsTaskView/blob/main/Phylogenetics.md) gives a good idea of the diversity of packages and analyses that can be completed in R (note that this links to a draft of the next version of the Taskview as it is currently unavailable from CRAN). rotl/inst/doc/meta-analysis.html0000644000176200001440000022317115132222604016414 0ustar liggesusers Using the Open Tree synthesis in a comparative analysis

Using the Open Tree synthesis in a comparative analysis

David Winter

2026-01-15

Phylogenetic Comparative Methods

The development of phylogenetic comparative methods has made phylogenies and important source of data in fields as diverse as ecology, genomic and medicine. Comparative methods can be used to investigate patterns in the evolution of traits or the diversification of lineages. In other cases a phylogeny is treated as a “nuisance parameterâ€, allowing with the autocorrelation created by the shared evolutionary history of the different species included to be controlled for.

In many cases finding a tree that relates the species for which trait data are available is a rate-limiting step in such comparative analyses. Here we show how the synthetic tree provided by Open Tree of Life (and made available in R via rotl) can help to fill this gap.

A phylogenetic meta-analysis

To demonstrate the use of rotl in a comparative analysis, we will partially reproduce the results of Rutkowska et al 2014. Very briefly, this study is a meta-analysis summarising the results of multiple studies testing for systematic differences in the size of eggs which contain male and female offspring. Such a difference might mean that birds invest more heavily in one sex than the other.

Because this study involves data from 51 different species, Rutkowska et al used a phylogenetic comparative approach to account for the shared evolutionary history among some of the studied-species.

Gather the data

If we are going to reproduce this analysis, we will first need to gather the data. Thankfully, the data is available as supplementary material from the publisher’s website. We provide a copy of this data with the package:

library(rotl)
## This dataset is available from the publisher's study website:
egg_data <- read.csv(system.file("extdata", "egg.csv", package = "rotl"),
  stringsAsFactors = FALSE
)
## }
head(egg_data)
##                   animal                   Spp       Lndim Measure Neggs Nclutches        ESr Type         StudyID Year        D        EN         Zr         VZr
## 1 Zonotrichia_leucophrys White-crowned sparrow 0.000000000  volume   294        73 0.14004594 stat        Mead1987 1987 3.421918  85.91673 0.14097244 0.012060292
## 2      Passer_domesticus         House sparrow 0.009407469  volume   149        31 0.11175203 stat     Cordero2000 2000 4.045161  36.83413 0.11222075 0.029555954
## 3        Serinus_canaria                Canary 0.000000000  volume    52        21 0.49679140 stat     Leitner2006 2006 2.180952  23.84279 0.54503712 0.047978211
## 4          Turdus_merula    European blackbird 0.021189299  volume    82        54 0.38598540 stat     Martyka2010 2010 1.414815  57.95812 0.40707397 0.018195675
## 5    Agelaius_phoeniceus  Red-winged blackbird 0.218316086  volume   394       106 0.07410136  raw Weatherhead1985 1985 3.173585 124.14982 0.07423744 0.008254242
## 6    Quiscalus_mexicanus  Great-tailed grackle 0.281894985    mass   822       205 0.05178834  raw     Teather1989 1989 3.407805 241.21099 0.05183471 0.004197959

The most important variable in this dataset is Zr, which is a normalized effect size for difference ,in size between eggs that contain males and females. Values close to zero come from studies that found the sex of an egg’s inhabitant had little effect in its size, while large positive or negative values correspond to studies with substantial sex biases (towards males and females respectively). Since this is a meta-analysis we should produce the classic funnel plot with effects-size on the y-axis and precision (the inverse of the sample standard error) on the x-axis. Here we calculate precision from the sample variance (Vzr):

plot(1 / sqrt(egg_data$VZr), egg_data$Zr,
  pch = 16,
  ylab = "Effect size (Zr)",
  xlab = "Precision (1/SE)",
  main = "Effect sizes for sex bias in egg size among 51 brid species"
)
plot of chunk eggs_in_a_funnel
plot of chunk eggs_in_a_funnel

In order to use this data later on we need to first convert it to a standard data.frame. We can also convert the animal column (the species names) to lower case, and remove the underscores in their names, which will make it easier to match names later on:

egg_data <- as.data.frame(egg_data)
## Convert taxon names to lower case
egg_data$animal <- tolower(egg_data$animal)
## Let's remove the underscores (_) from the taxon names
egg_data$animal <- gsub("_", " ", egg_data$animal)

Find the species in OTT

We can use the OTL synthesis tree to relate these species. To do so we first need to find Open Tree Taxonomy (OTT) IDs for each species. We can do that with the Taxonomic Name Resolution Service function tnrs_match_names:

taxa <- tnrs_match_names(unique(egg_data$animal), context_name = "Animals")
head(taxa)
##            search_string            unique_name approximate_match score ott_id is_synonym          flags number_matches
## 1 zonotrichia leucophrys Zonotrichia leucophrys             FALSE     1 265553      FALSE                             1
## 2      passer domesticus      Passer domesticus             FALSE     1 745175      FALSE                             1
## 3        serinus canaria        Serinus canaria             FALSE     1 464865      FALSE sibling_higher              1
## 4          turdus merula          Turdus merula             FALSE     1 568572      FALSE                             1
## 5    agelaius phoeniceus    Agelaius phoeniceus             FALSE     1 226605      FALSE                             1
## 6    quiscalus mexicanus    Quiscalus mexicanus             FALSE     1 743411      FALSE                             1

All of these species are in OTT, but a few of them go by different names in the Open Tree than we have in our data set. Because the tree rotl fetches will have Open Tree names, we need to create a named vector that maps the names we have for each species to the names Open Tree uses for them:

taxon_map <- structure(taxa$search_string, names = taxa$unique_name)

Now we can use this map to retrieve “data set names†from “OTT namesâ€:

taxon_map["Anser caerulescens"]
##  Anser caerulescens 
## "chen caerulescens"

Get a tree

Now we can get the tree. There are really too many tips here to show nicely, so we will leave them out of this plot

tr <- tol_induced_subtree(ott_id(taxa)[is_in_tree(ott_id(taxa))])
## Warning in collapse_singles(tr, show_progress): Dropping singleton nodes with labels: mrcaott246ott92263, mrcaott246ott1858, mrcaott246ott3600042, mrcaott246ott7113, Passeriformes ott1041547, mrcaott246ott3212, mrcaott246ott428578, mrcaott246ott44866,
## mrcaott246ott5929, mrcaott246ott96288, mrcaott246ott310390, mrcaott246ott176461, mrcaott246ott22325, mrcaott246ott10351, mrcaott246ott72472, mrcaott246ott5934, mrcaott246ott3599436, mrcaott246ott1566, mrcaott1566ott3598440, mrcaott1566ott496009,
## mrcaott1566ott35326, mrcaott1566ott92668, mrcaott1566ott24297, mrcaott1566ott22300, mrcaott22300ott35350, mrcaott22300ott32651, mrcaott22300ott547548, mrcaott22300ott67150, mrcaott22300ott130294, mrcaott22300ott7660860, mrcaott22300ott416087,
## mrcaott22300ott416089, mrcaott22300ott107840, mrcaott113980ott364210, mrcaott113980ott3598839, mrcaott3598839ott5341363, mrcaott19467ott431648, mrcaott19467ott401023, mrcaott19467ott252687, mrcaott19467ott233446, mrcaott19467ott378061, mrcaott19467ott1046624,
## mrcaott19467ott161293, mrcaott19467ott46396, mrcaott46396ott46399, mrcaott46399ott168083, mrcaott168083ott691103, mrcaott2175ott600902, mrcaott2175ott259082, mrcaott2175ott59905, mrcaott2175ott2224, mrcaott2224ott366470, mrcaott3364ott310375, mrcaott3364ott4083,
## mrcaott4083ott35042, mrcaott4083ott35053, mrcaott4083ott370807, mrcaott4083ott469177, mrcaott4083ott11712, mrcaott4083ott52094, mrcaott4083ott95949, Erythrura ott465905, mrcaott24017ott24025, mrcaott24025ott596763, mrcaott24025ott389884, mrcaott24025ott453058,
## mrcaott24025ott865473, mrcaott24025ott141501, mrcaott141501ott389883, mrcaott141501ott3597689, mrcaott141501ott865472, mrcaott141501ott3597698, mrcaott105913ott596770, mrcaott105913ott3599583, mrcaott105913ott543841, mrcaott105913ott124463,
## mrcaott124463ott445491, mrcaott445491ott7068429, mrcaott445491ott708327, mrcaott4088ott95302, mrcaott4088ott8371, mrcaott4088ott138768, mrcaott4088ott28339, mrcaott4088ott5616, mrcaott5616ott6023, mrcaott6023ott243614, mrcaott6023ott101225, mrcaott6023ott125079,
## mrcaott125079ott463026, mrcaott125079ott765405, Zonotrichia (genus in domain Eukaryota) ott789032, mrcaott125079ott265547, mrcaott125079ott265554, mrcaott5620ott254662, mrcaott5620ott29804, mrcaott29804ott998133, mrcaott29804ott449562, mrcaott29804ott86894,
## mrcaott29804ott93045, mrcaott93045ott264496, mrcaott264496ott264500, mrcaott264500ott3597163, mrcaott264500ott283668, Quiscalus ott743410, mrcaott283673ott673386, mrcaott283673ott741944, mrcaott283673ott735243, mrcaott213448ott213452, mrcaott213448ott1009279,
## mrcaott213448ott213451, mrcaott213454ott430627, Agelaius ott617799, mrcaott430627ott617797, mrcaott430627ott3597159, mrcaott99175ott364331, Xanthocephalus ott364336, mrcaott6366ott28332, mrcaott6366ott88283, mrcaott6366ott341465, mrcaott6366ott157599,
## mrcaott6366ott178457, mrcaott6366ott405215, mrcaott6366ott238137, mrcaott6366ott6375, mrcaott6375ott119724, mrcaott6375ott328909, mrcaott328909ott464865, mrcaott464865ott1083724, Haemorhous ott3601758, mrcaott9416ott580155, mrcaott9416ott840030,
## mrcaott9416ott96147, mrcaott9416ott749634, Passer ott515158, mrcaott9416ott7661508, mrcaott9416ott25628, mrcaott9416ott407763, mrcaott9416ott407764, mrcaott9416ott68955, mrcaott9416ott73636, mrcaott73636ott5859927, mrcaott73636ott995847, mrcaott1488ott63797,
## mrcaott1488ott284404, mrcaott1488ott107463, mrcaott1488ott17016, mrcaott1488ott16185, Hirundinidae ott897681, mrcaott16185ott67921, mrcaott16185ott67916, mrcaott67916ott368059, mrcaott67916ott67920, mrcaott67920ott3597799, Delichon ott922719,
## mrcaott44217ott107476, mrcaott107476ott177058, mrcaott107476ott446183, mrcaott107476ott337755, mrcaott107476ott337752, mrcaott337752ott374222, mrcaott337752ott337762, mrcaott337752ott3598087, mrcaott337752ott496789, mrcaott2375ott73144, mrcaott2375ott124085,
## mrcaott2375ott71358, mrcaott2375ott814750, mrcaott2375ott61147, mrcaott61147ott84656, mrcaott61147ott123763, mrcaott123763ott258794, mrcaott4820ott294599, mrcaott4820ott75981, mrcaott4820ott379708, mrcaott4820ott17162, mrcaott4820ott20998, mrcaott4820ott20989,
## mrcaott4820ott58860, mrcaott4820ott23690, mrcaott4820ott20996, mrcaott4820ott749725, mrcaott4820ott11462, mrcaott4820ott140440, mrcaott4820ott197505, mrcaott4820ott75978, mrcaott4820ott11315, mrcaott4820ott5933, mrcaott5933ott662804, mrcaott5933ott60465,
## mrcaott5933ott25637, mrcaott25637ott473431, mrcaott25637ott199843, mrcaott25637ott111993, mrcaott25637ott183621, mrcaott183621ott282315, mrcaott282315ott501241, mrcaott501241ott597018, mrcaott686165ott686168, mrcaott60456ott75990, mrcaott60456ott894604, Pica
## ott776480, Falconiformes ott212187, Falconidae ott212186, mrcaott47588ott225286, mrcaott47588ott748842, mrcaott47588ott3596147, Falco ott786441, mrcaott179290ott624976, mrcaott179290ott624973, mrcaott179290ott3596145, mrcaott179290ott624974,
## mrcaott179290ott432111, mrcaott179290ott285806, Cerchneis ott3596159, mrcaott5272ott928360, mrcaott5272ott7145, mrcaott5272ott24121, Scolopacidae ott887699, mrcaott24121ott217797, mrcaott24121ott45306, mrcaott24121ott55408, mrcaott24121ott420370,
## mrcaott24121ott654830, mrcaott24121ott214779, mrcaott24121ott1090732, mrcaott7639ott306220, mrcaott7639ott57833, mrcaott7639ott738512, mrcaott7639ott279504, mrcaott7639ott47401, mrcaott47401ott234666, mrcaott234666ott341044, mrcaott234666ott651058,
## mrcaott234666ott341047, mrcaott234666ott285543, mrcaott285543ott341030, mrcaott285543ott341032, mrcaott285543ott738509, mrcaott285543ott966606, mrcaott285543ott966604, mrcaott22965ott80679, mrcaott22965ott154126, mrcaott22965ott373759, mrcaott22965ott282132,
## mrcaott22965ott414141, mrcaott22965ott335737, mrcaott22965ott509055, mrcaott22965ott324050, mrcaott22965ott910287, mrcaott22965ott353849, mrcaott22965ott335736, mrcaott22965ott526679, mrcaott22965ott75913, mrcaott75913ott515357, mrcaott75913ott119602,
## mrcaott75913ott993041, mrcaott425206ott887691, mrcaott425206ott515355, mrcaott241571ott993045, mrcaott241571ott1026258, mrcaott241571ott254356, mrcaott241571ott704181, mrcaott704181ott4947414, mrcaott147723ott219032, Stercorariidae ott168297, Stercorarius
## ott742632, mrcaott742640ott742641, mrcaott57823ott57827, mrcaott57823ott242771, mrcaott57823ott80080, mrcaott57823ott112937, mrcaott112937ott673638, mrcaott112937ott129402, mrcaott112937ott242776, mrcaott242776ott3596974, mrcaott242776ott3596977,
## mrcaott242776ott313115, mrcaott242776ott413796, mrcaott5481ott9830, mrcaott9830ott86672, mrcaott9830ott90560, mrcaott9830ott324158, mrcaott9830ott55044, mrcaott9830ott285638, mrcaott9830ott117726, Sulidae ott452462, mrcaott170197ott403772, Sula ott160486,
## mrcaott170197ott5859716, mrcaott170197ott429615, mrcaott429615ott1030312, Procellariiformes ott452461, Diomedeidae ott85277, mrcaott71459ott320282, Phoebastria ott941509, mrcaott320282ott320284, Sphenisciformes ott494366, Spheniscidae ott494367,
## mrcaott60413ott3600120, mrcaott60413ott4130813, mrcaott60413ott4130835, mrcaott60413ott4130832, mrcaott60413ott3600127, mrcaott60413ott4130831, mrcaott60413ott3600124, mrcaott60413ott3600128, mrcaott60413ott3600129, mrcaott60413ott4130848, mrcaott60413ott4130817,
## mrcaott60413ott494361, mrcaott60413ott60417, mrcaott60413ott3600131, mrcaott60413ott7068884, Eudyptes ott494364, mrcaott60413ott88590, mrcaott88590ott7068880, mrcaott88590ott116946, Pygoscelis ott494365, mrcaott134466ott783352, mrcaott5021ott198671,
## mrcaott5021ott75792, Cuculiformes ott212171, mrcaott75792ott212172, mrcaott75792ott3601282, mrcaott75792ott119216, mrcaott119216ott526771, mrcaott119216ott169265, mrcaott169265ott550039, mrcaott169265ott462546, mrcaott462546ott3596360, mrcaott462546ott3596355,
## mrcaott462546ott1050027, Cuculus ott1041429, mrcaott549514ott7068132, mrcaott549514ott3596308, mrcaott549514ott3596307, mrcaott549514ott3596306, mrcaott549514ott792626, mrcaott17146ott57819, Columbiformes ott363030, mrcaott28925ott45505, mrcaott45505ott604973,
## mrcaott45505ott50388, mrcaott45505ott277822, mrcaott45505ott51607, mrcaott51607ott67614, mrcaott51607ott331474, mrcaott51607ott277817, mrcaott51607ott320359, mrcaott320359ott493986, mrcaott320359ott767317, mrcaott320359ott921832, mrcaott320359ott938416,
## mrcaott4765ott4131031, Galliformes ott837585, mrcaott4765ott6520194, mrcaott4765ott109888, mrcaott4765ott75785, m
plot(tr, show.tip.label = FALSE)
plot of chunk birds_in_a_tree

plot of chunk birds_in_a_tree

There are a few things to note here. First, the tree has no branch lengths. At present this is true for the whole of the Open Tree synthetic tree. Some comparative methods require either branch lengths or an ultrametric tree. Before you can use one of those methods you will need to get a tree with branch lengths. You could try looking for published trees made available by the Open Tree with studies_find_trees. Alternatively, you could estimate branch lengths from the toplogy of a phylogeny returned by tol_induced_subtree, perhaps by downloading DNA sequences from the NCBI with rentrez or “hanging†the tree on nodes of known-age using penalized likelihood method in ape::chronos. In this case, we will use only the topology of the tree as input to our comparative analysis, so we can skip these steps.

Second, the tip labels contain OTT IDs, which means they will not perfectly match the species names in our dataset or the taxon map that we created earlier:

tr$tip.label[1:4]
## [1] "Ficedula_albicollis_ott107840" "Luscinia_svecica_ott274225"    "Turdus_merula_ott568572"       "Sturnus_unicolor_ott366470"

Finally, the tree contains node labels for those nodes that match a higher taxonomic group, and empty character vectors ("") for all other nodes. Some comparative methods either do no expect node labels at all, or require all labeled nodes to have a unique name (meaning multiple “empty†labels will cause and error).

We can deal with all these details easily. rotl provides the convenience function strip_ott_ids to remove the extra information from the tip labels. With the IDs removed, we can use our taxon map to replace the tip labels in the tree with the species names from dataset.

otl_tips <- strip_ott_ids(tr$tip.label, remove_underscores = TRUE)
tr$tip.label <- taxon_map[ otl_tips ]

Finally, we can remove the node labels by setting the node.label attribute of the tree to NULL.

tr$node.label <- NULL
egg_data <- egg_data[egg_data$animal %in% tr$tip.label, ]

Perform the meta-analysis

Now we have data and a tree, and we know the names in the tree match the ones in the data. It’s time to do the comparative analysis. Rutkowska et al. used MCMCglmm, a Bayesian MCMC approach to fitting multi-level models,to perform their meta-analysis, and we will do the same. Of course, to properly analyse these data you would take some care in deciding on the appropriate priors to use and inspect the results carefully. In this case, we are really interested in using this as a demonstration, so we will just run a simple model.

Specifically we sill fit a model where the only variable that might explain the values of Zr is the random factor animal, which corresponds to the phylogenetic relationships among species. We also provide Zvr as the measurement error variance, effectively adding extra weight to the results of more powerful studies. Here’s how we specify and fit that model with MCMCglmm:

set.seed(123)
if (require(MCMCglmm, quietly = TRUE)) {
  pr <- list(
    R = list(V = 1, nu = 0.002),
    G = list(G1 = list(V = 1, nu = 0.002))
  )

  model <- MCMCglmm(Zr ~ 1,
    random = ~animal,
    pedigree = tr,
    mev = egg_data$VZr,
    prior = pr,
    data = egg_data,
    verbose = FALSE
  )
} else {
  model <- readRDS(file = system.file("extdata", "mcmcglmm_model.rds", package = "rotl"))
}

Now that we have a result we can find out how much phylogenetic signal exists for sex-biased differences in egg-size. In a multi-level model we can use variance components to look at this, specifically the proportion of the total variance that can be explained by phylogeny is called the phylogenetic reliability, H. Let’s calculate the H for this model:

var_comps <- colMeans(model$VCV)
var_comps["animal"] / sum(var_comps)
##     animal 
## 0.00313885

It appears there is almost no phylogenetic signal to the data. The relationships among species explain much less that one percent of the total variance in the data. If you were wondering, Rutkowska et al. report a similar result, even after adding more predictors to their model most of the variance in Zr was left unexplained.

What other comparative methods can I use in R?

Here we have demonstrated just one comparative analysis that you might do in R. There are an ever-growing number of packages that allow an ever-growing number of analysis to performed in R. Some “classics†like ancestral state reconstruction, phylogenetic independent contrasts and lineage through time plots are implemented in ape. Packages like phytools, caper and diversitree provide extensions to these methods. The CRAN Phylogenetics Taskview gives a good idea of the diversity of packages and analyses that can be completed in R (note that this links to a draft of the next version of the Taskview as it is currently unavailable from CRAN).

rotl/inst/extdata/0000755000176200001440000000000015132136164013643 5ustar liggesusersrotl/inst/extdata/protist_mutation_rates.csv0000644000176200001440000000053615132136164021206 0ustar liggesusersspecies,mu,pop.size,genome.size Tetrahymena thermophila,7.61E-012,1.12E+008,1.04E+008 Paramecium tetraurelia,1.94E-011,1.24E+008,7.20E+007 Chlamydomonas reinhardtii,2.08E-010,1.00E+008,1.12E+008 Dictyostelium discoideum,2.9E-011,7.40E+006,3.40E+007 Saccharomyces cerevisiae,3.3E-010,1.00E+008,1.25E+008 Saccharomyces pombe,2E-010,1.00E+007,1.25E+008 rotl/inst/extdata/egg.csv0000644000176200001440000002111515132136164015122 0ustar liggesusersanimal,Spp,Lndim,Measure,Neggs,Nclutches,ESr,Type,StudyID,Year,D,EN,Zr,VZr Zonotrichia_leucophrys,White-crowned sparrow,0,volume,294,73,0.140045943,stat,Mead1987,1987,3.421917808,85.91673339,0.140972438,0.012060292 Passer_domesticus,House sparrow,0.009407469,volume,149,31,0.11175203,stat,Cordero2000,2000,4.04516129,36.83413078,0.112220753,0.029555954 Serinus_canaria,Canary,0,volume,52,21,0.4967914,stat,Leitner2006,2006,2.180952381,23.84279476,0.545037117,0.047978211 Turdus_merula,European blackbird,0.021189299,volume,82,54,0.3859854,stat,Martyka2010,2010,1.414814815,57.95811518,0.40707397,0.018195675 Agelaius_phoeniceus,Red-winged blackbird,0.218316086,volume,394,106,0.07410136,raw,Weatherhead1985,1985,3.173584906,124.1498216,0.074237439,0.008254242 Quiscalus_mexicanus,Great-tailed grackle,0.281894985,mass,822,205,0.051788336,raw,Teather1989,1989,3.407804878,241.2109934,0.05183471,0.004197959 Taeniopygia_guttata,Zebra finch,-0.010812869,mass,116,24,-0.05636213,stat,Rutkowska2005,2005,4.066666667,28.52459016,-0.056421926,0.039177906 Taeniopygia_guttata,Zebra finch,-0.010812869,mass,90,20,0,stat,Rutkowska2002,2002,3.8,23.68421053,0,0.048346056 Vanellus_vanellus,Northern lapwing,-0.029825984,volume,114,32,0.03014961,stat,Lislevand2005,2005,3.05,37.37704918,0.03015875,0.029089175 Philomachus_pugnax,Ruff,0.22184875,volume,120,30,0.03462025,stat,Thuman2003,2003,3.4,35.29411765,0.034634091,0.030965392 Luscinia_svecica,Bluethroat,0,volume,102,18,-0.1468127,stat,Lifjeld2005,2005,4.733333333,21.54929577,-0.147881353,0.053910402 Sturnus_unicolor,Spotless starling,0.025305865,mass,153,34,-0.133824538,stat,Cordero2001,2001,3.8,40.26315789,-0.134632122,0.026836158 Branta_canadensis,Canada goose,0.061028185,mass,242,44,-0.006674089,stat,Leblanc1987,1987,4.6,52.60869565,-0.006674188,0.020157756 Falco_tinnunculus,Eurasian kestrel,-0.080479586,mass,132,33,-0.1910071,stat,Martinez-Padilla2007,2007,3.4,38.82352941,-0.193382195,0.027914614 Falco_tinnunculus,Eurasian kestrel,-0.080479586,mass,108,28,0.2165249,stat,Blanco2003,2003,3.285714286,32.86956522,0.220007175,0.033478894 Larus_michahellis,Yellow-legged gull,0.091409863,mass,1068,669,-0.06718163,stat,Rubolini2009,2009,1.477130045,723.0236794,-0.067282976,0.001388843 Cincloramphus_cruralis,Brown songlark,0.363356588,mass,44,17,0.1439293,stat,Isaksson2010,2010,2.270588235,19.37823834,0.144935702,0.061056628 Pavo_cristatus,Peafowl,0.119205592,mass,3313,205,0.005428755,stat,Petrie2001,2001,13.12878049,252.3463625,0.005428808,0.004010486 Parus_caeruleus,Blue tit,0.010299957,mass,192,21,0.07261821,stat,Cichon2003,2003,7.514285714,25.5513308,0.072746264,0.044343281 Larus_argentatus,Herring gull,0.049687784,mass,79,30,0.1160999,stat,Bogdanova2006,2006,2.306666667,34.24855491,0.116625804,0.03200148 Larus_fuscus,Lesser black-backed gull,0.064503231,mass,60,22,0.124354,stat,Bogdanova2005,2005,2.381818182,25.19083969,0.125001014,0.045063639 Corvus_monedula,Jackdaw,0.041392685,mass,226,70,0.2033713,stat,Arnold2003,2003,2.782857143,81.21149897,0.206246808,0.012785844 Carpodacus_mexicanus,House finch,0.002809678,volume,378,84,-0.075561895,raw,Badyaev2006,2006,3.8,99.47368421,-0.075706199,0.010365521 Carpodacus_mexicanus,House finch,0,volume,304,64,-0.072529696,raw,Badyaev2006,2006,4,76,-0.072657281,0.01369863 Sterna_hirundo,Common Tern,0.008600172,volume,427,158,0,raw,Fletcher2004,2004,2.362025316,180.7770632,0,0.005625023 Lonchura_striata,Bengalese finch,-0.021189299,mass,116,34,0.09239892,stat,Soma2007,2007,2.929411765,39.59839357,0.092663229,0.027323604 Molothrus_bonariensis,Ring-billed gull,0.078874433,mass,90,30,-0.000377536,stat,Chin2012,2012,2.6,34.61538462,-0.000377536,0.03163017 Pica_pica,Magpie,0.063358906,volume,43,8,-0.036738337,raw,Slagsvold1992,1992,4.5,9.555555556,-0.036754879,0.152542373 Corvus_corone,Hooded crow,0.049218023,volume,103,31,0.073794034,raw,Slagsvold1992,1992,2.858064516,36.03837472,0.073928423,0.030267833 Taeniopygia_guttata,Zebra finch,-0.010812869,mass,133,22,-0.03994883,stat,Pariser2012,2012,5.036363636,26.40794224,-0.039970102,0.042720543 Delichon_urbicum,House martin,0,mass,90,35,0.03076685,stat,Gil2006,2006,2.257142857,39.87341772,0.030776563,0.027119808 Xanthocephalus_xanthocephalus,Yellow-headed blackbird,0.247321812,mass,90,23,-0.088294337,raw,Richter1983,1983,3.330434783,27.02349869,-0.088524861,0.04162591 Larus_delawarensis,Ring-billed gull,0.06069784,mass,110,37,0.053696485,raw,Meathrel1987,1987,2.578378378,42.66247379,0.053748182,0.025212749 Cincloramphus_cruralis,Brown songlark,0.363356588,volume,95,40,-0.3293106,stat,Magrath2003,2003,2.1,45.23809524,-0.342054801,0.02367531 Larus_ridibundus,Black-headed gull,0,mass,60,20,0.1391671,stat,Groothuis2006,2006,2.6,23.07692308,0.140076126,0.049808429 Anseranas_semipalmata,Magpie goose,0.125672077,mass,60,16,-0.110406595,raw,Whitehead1990,1990,3.2,18.75,-0.11085851,0.063492063 Sterna_hirundo,Common Tern,0,volume,108,40,0.073872636,raw,Gonzalez-Solis2005,2005,2.36,45.76271186,0.074007456,0.023384859 Falco_tinnunculus,Eurasian kestrel,-0.080479586,mass,80,16,0.097815848,raw,Wu2010,2010,4.2,19.04761905,0.098129617,0.06231454 Larus_delawarensis,Shiny cowbird,0.035472318,volume,90,90,-0.07294093,stat,Tuero2012,2012,1,90,-0.073070702,0.011494253 Pygoscelis_antarcticus,Chinstrap penguin,0.058509856,volume,264,132,0.03094903,stat,Fargallo2006,2006,1.8,146.6666667,0.030958917,0.006960557 Phoebastria_irrorata,Waved albatross,0.091157684,volume,224,224,-0.088469783,stat,Awkerman2007,2007,1,224,-0.088701688,0.004524887 Passer_domesticus,House sparrow,0.009407469,volume,77,19,0.05470045,stat,Wetzel2012,2012,3.442105263,22.37003058,0.054755105,0.051626145 Sula_nebouxii,Blue-footed booby,-0.147287056,mass,76,56,-0.2611557,stat,D'Alba2007,2007,1.285714286,59.11111111,-0.267348297,0.017821782 Stercorarius_parasiticus,Parasitic jaeger,-0.063477845,volume,534,267,0.1397023,stat,Janssen2006,2006,1.8,296.6666667,0.140621937,0.003405221 Ficedula_albicollis,Collared flycatcher,0.013679697,volume,1162,198,0.04804496,stat,Bowers2013,2013,4.894949495,237.3875361,0.048081979,0.004266438 Sterna_dougallii,Roseate tern,0,mass,440,146,-0.062868359,raw,Szczys2005,2005,2.610958904,168.5204617,-0.062951384,0.006041549 Centrocercus_urophasianus,Greater sage-grouse,0.261995252,volume,146,20,0.06614164,stat,Atamian2010,2010,6.04,24.17218543,0.066238344,0.04723178 Phasianus_colchicus,Ring-necked pheasant,0.140492874,mass,106,15,0.4531655,stat,Rubolini2007,2007,5.853333333,18.10933941,0.488676681,0.06618423 Taeniopygia_guttata,Zebra finch,-0.010812869,mass,43,15,0,raw,Clotfelter1996,1996,2.493333333,17.2459893,0,0.070195195 Larus_fuscus,Lesser black-backed gull,-0.010812869,volume,304,101,-0.00990453,raw,Bradbury1999,1999,2.607920792,116.5679575,-0.009904854,0.008805301 Sturnus_vulgaris,European starling,0.01616166,mass,354,69,0.04996099,stat,Love2011,2011,4.304347826,82.24242424,0.050002622,0.012619503 Erythrura_gouldiae,Gouldian finch,0,volume,1473,324,-0.019559388,stat,Pryke2009,2009,3.837037037,383.8899614,-0.019561883,0.00262543 Larus_ridibundus,Black-headed gull,0,volume,147,49,0.05453834,stat,Lezalova2005,2005,2.6,56.53846154,0.05459251,0.018678161 Aythya_ferina,Common pochard,0,volume,185,26,0.1957707,stat,Lezalova2013a,2014,5.892307692,31.39686684,0.198330883,0.035215153 Aythya_fuligula,Tufted duck,0.026629385,volume,46,7,-0.04923335,stat,Lezalova2013b,2014,5.457142857,8.429319372,-0.049273187,0.184185149 Aythya_affinis,Lesser scaup,0.031791834,volume,38,5,-0.143657133,raw,Dawson1996,1996,6.28,6.050955414,-0.144657788,0.32776618 Chen_caerulescens,Lesser snow goose,0.037500891,mass,85,22,-0.089455106,raw,Ankney1980,1980,3.290909091,25.82872928,-0.089694871,0.043804453 Falco_sparverius,American kestrels,-0.036212173,volume,170,34,0.093153037,raw,Anderson1997,1997,4.2,40.47619048,0.093423893,0.026683609 Columba_livia,Domestic pigeon,0,mass,63,16,0.3301501,stat,Pike2005,2005,3.35,18.80597015,0.342996707,0.063267233 Zonotrichia_leucophrys,White-crowned sparrow,0,mass,38,11,0.06348392,stat,Bonier2007,2007,2.963636364,12.82208589,0.063569411,0.101811368 Quiscalus_major,Boat-tailed grackle,0.268544242,mass,122,41,-0.056059589,raw,Bancroft1984,1984,2.580487805,47.2778828,-0.056118426,0.022584639 Cuculus_canorus,Common cuckoo,0.042879996,volume,71,38,0.1527316,stat,Fossoy2012,2012,1.694736842,41.89440994,0.153936091,0.025710636 Eudyptes_chrysocome,Rockhopper penguin,0.037301411,mass,213,194,0.1191936,stat,Poisbleau2010,2010,1.078350515,197.5239006,0.119762927,0.005140756 Larus_michahellis,Yellow-legged gull,0.091409863,volume,124,48,-0.003408011,stat,Perez2006,2006,2.266666667,54.70588235,-0.003408024,0.019340159 Gallus_gallus,Red Junglefowl,0.080943092,volume,220,71,-0.08467843,stat,Parker2005,2005,2.678873239,82.12407992,-0.084881699,0.012638378 rotl/inst/extdata/mcmcglmm_model.rds0000644000176200001440000036167215132136164017350 0ustar liggesusers‹ìýwTÔKÓ0Š¢dEQ1'@AÁ€‚D‹œsÎa`fâ£$É9 ’“ä$Yr+EE@%**`FQ¹ó›çy¿ï}Ÿïž³Î]ëþw¶k±‹î®®®ÜU=l0ÜFCC³•†–ŽŽf+-å[Z6Ê(_´;)_o¡¹f‰@™€ôá,©]44Ý·Ÿd²¤Œ+IáÞ˜Š—ŽÇÖ‹”+ró)0§-±Q`Ø=ålþz ]eÜ:þ´7ˆ26.•  Ìw{ï °ÁÖ‹éÖ§Ê(ðZ‘ÃÖËΊ?ÆèÜ—ì¼t¡üïn dõì^*>»ôI ´Ø•ŠÑ’“3éþ-ÃØ|jùÌGUʾè®'Œ^ O¬"k+5#°s=ºÍßcû¬G½?P`SRæl½±«Ž:_6¶ÀÁ[ã_ZG(°ÎÜË㣷X„ÉÕr¾VÓƒðÓK)ã„Ãn5Tüš·áw°óáîQ ¼i9,ŒÑU9â°Ž­?åIÂôà¥vg÷ÃoØDïÃðn¤ï6Äø/Ë9£Á €óO0XEs¶å5&§’äYŒþ­Ùx]Œ~RËçPê¹&];?WêØ„é6EÝNÆ—°qéãýo1ú…SY]·)0ÍWR—zNfžš%æ]ù9M]ßþ¸£“¶w: Û—@·¬I™ï¾eô±ß£{½ßÃO—â±ÅÖ›ô/ÜÄð=÷ýÀÆ»Z1|ü·}ÍDi6ŸxËâ F'‚øzvn±F= ™kˆ©Ñ˜> Û£Ö°ó³Ë‡©ë…ÖŠèÃOG=§j ­Ý·ébð¦ž` ¦üü6 ŠÿugÜ¿sÛ—rpb Æ_ñoëGØ8oÞZÃËu‹ª¾¿]4Çø³4“ìÀƹg‹rƒ1úr!þ˜> $lïcþÒÝGÕ›ÍkuIÌ_xgF±qVX`°žiL £{‹ˆ»‹ñ_ÉN;·rî †Ë?mtó§?u1{ÕVsTaòåƒÖ'ÌïZmD±óyŒW0:õº’Û°ñã>óßõ¶5`ã<ýªŒ~û™ž/˜þB7„ç1:AÒ=ŒÏyÆ:ÌïÛ—\y°óC>~*0Åô¹ïŒ ¶¯”gñUOr;[0ºQmÇ 1:Ö/šš19¼¿‰Pý¦,îð ª?ä5|FT~í @¯S²ã^Ý¡ð«…A§0Ïv켊W*‰Ý:Uö.l=ÕPüÆW¢ú̪½§ ã°qq%ÿ‹DŒNèÇßÔürÊ ãÓoN×ÊZ¾JµKçl F7iÒð%ÆGAµÔ ýn‘ƒ‘˜œ^ƒ«Ê^„»F§[Új ×þÊÄaz*t…cØy·ª8c÷S`d05ÎEÝbxÝQš†rßé ¡ÔürIÉÛ—i--ŠKOF6zÑ€+W7Õ¯›Èµß)›ª>Ô|2e^ŠÍ§èšÑ­Q  ÷Qlœç1Jƒáe×2WSã•A.–:o]9é1Ûa4ƒAœÓǨþós: ÓwþÀ»!l¾Næ‘uaán˜ü)W~q`ô éê_Qn¿ù4‰ñÛöÜý6ŸÌ‰Ãâ·È®Ô»ƒÊìþ`ë·…Ks0?ëhâ¨åÁø4«ö‹óF‡1ùšYLwbú¨\Q*Áöݺ|>³Ÿ\hÆ—3ãÛ9ªž¾:íÇèÜq>‰ñS-ñâ &×½ÙhŸuL¿L<¬BÁŒŒ®Y[ 5>ÍßLqaÐÇ~‡ow¦Äwx—'&_J®IáꡜÔxž'Ûcç—×kÚÙbrEàX1½}ëÏÁλU׎áW•Ö|ÇòlΞ–gT»ç½¡ÒW»F1@wžP¦Ç*uÝØ9UÛ Î˜ß˜ézRùª“µÃìœ(ª@s‘2ß(‰¯Çæ36ÛË1?)vÛÅ¥‰Å[œàLÞÛ•þƒ˜\7Ï[ïÃø+Ø+ÒŒù)á…•^^–”5¿8Ñäcü”°/n¡úßÛJ5ŒÎµ2­jjœ3ܹ„ÉQ~©1“+Y³š?ÊèŽ/b~[0ôóƒÚ¨kžØ|‰Ügª?ªgÙaôË[M„0¹â= Ú©òZhöbvI–ŠÇÖ+˜¨þæRÍŠÇÖ]N’ÿ`ð–ߊÆW\mÍUŒk‘Yj|Jºˆcô«ôDF) „–½e±óÃÍ„©÷mÕ±Oò1~s$°s 2LQídªïJÙ×ísôY 6®lÀf¯½ëg1: ™Eüؼ×í = æî5F_‰«ç0xãk æ‡9äÞ6L?ÝqÔ:!ûüK_LޤÂ) ¯PÞ  ÓÓ­ œ!&gÃåO°õ(¢þ ?Úøu5NcåŒM«WÁäô<€§ÞëiódŒO¡cظ’ØËíO'=£Ú›Kƒ “÷æCWÊ|w<îê!l¾ðNÕã+ÃŒ›¿&…D°ùFš.M-J>¨=ù‰z/ Ñ`üÕØ,`q·’Ê´s)øío+ò0}¦p~ÅðnÓèÝÇôÒã0¾“·9'¹“/ŸùÄiŒnmƒŒ[°¯“²¯;Ƈ–ÓC]¬ÔU',ŽçŽìÀä%dþºƒÁãï4TÿöëÉÇäŒæºúŠJÿî}fl=ö÷~,ÏCPÛf¯ºð+4^édÜ5ŒŸFŽkÔ<¼ôòÕ?˜b…±qhÔ­½X!bòz*ßÛŠÑ»ñ}»ç!à¢Þ›\Ï¿bú&.%cã¢}z˜Ñ6<Ô|r3jƒÉê{ø1}ÜÙ]ËC³¶w0ÿÏY”ÿŠá߬ŒÇ`ùL¦#»HL?YoöõîÂìö£ŽžbŸî$ !,‹Ž]µ¤Æå{ÑMŒŸpÇbzì÷îo·¨~÷znƒYÙT 3ì6ÀÖ3[¶œÂÆÕù+X<»Ží÷¥ÆãÃ'x ¿K‰gVÓô^¡ÆoÝwª¿×fùRøèv“®Äòw7™Éè5ÝÙ#?RãŽF¡£—çØKõÓ§7lr‹Àlœÿ¡—FØÿy†Ô›RãŠÆcá6–¿ùl÷`ãÛ÷/cr%ñª¯Põ˾݃žÑÞ’X<¯Ù`çz0®´SÇ<Ü1z)ü.bçÕ8?I•?ôl$5Nc Ô819ÞqÞÃôŸ£Tð¯û†ûxæzŒØ=Q jù½½ÈQ^lßõÝW–0:ñ{“ïbã`)U,/„ÐÝ¢æõö¡Ér*¿Í‰Ü=»°sÔ:hbu#4Üø¶@±cw2ƒ:Æ”Ï(Jbv¬§{OÕ+ó­Eì¼ ·ïÅØ¾´+Í0(q3ÑÄä/zu-Ó[5–^(ü²sSÆÝ ±L˜žo~ØCÕgý¾6nÌOËâ©|–Ç&'bû‚8Ç0½$jœ>ŒÍû¤‹cy´›$t›šÏÊìõS±x/á5ãÃøÉšòÇä½µnö‹C˜ÞSñÒýÆã'ß­K ãOsµ]•ªŸc»Z±}éIBv˜ß^?·¢‹K "ƒ©}Püî÷˜~K{{þe7XlýFá 6Î9w9§=V¤ö%y2ÞÔº°¤ôæÿécڂعý›–˜Þ]ó ܰsmï¥ýÆðRÞS祈ÂScX<%øTíÄô\Ž…a“Ï_¾ÃkØdٽ˟ÝÖÓ°†Ñ‰¨—"ar•êdì ÃâúeL8¶¿loÂÒ_ û0¼U¼ŠV?ubù½Ûoù-F·8ó§ÌfujÝî¶óaÛE<˜°z½ðÑU)3Ì¿Ný ÅôV(—qÛW7hâŒÅuÝ»x-l\ØO»Ó“RÑw¬þlèÂæËö™?Àü'¯Âããö±ïM˜œ·L7îavÊ0|ROÅ#7RóUØ…Uìü¤ûûþÞÄ`Èc#l_“÷ ¬^¹! 5‚­çÙkY`øÒøL/5ùßö`~PÌh¯ŒÑx4ƒõ…uç‰-¦—¦-Ôü\80é«âà׿ÿc+ÌT{KñÇèú2¢öŸI ¯¿`þh©õ–ÚϦˆý´Çìus\óÛ†÷Æ›˜œ¾õFú˜Ÿ62ÍxcûÛ\?/aóutŽcùÀ¡"ÇÛßÌp¥ ;¯çXá"æW?òRóˆòj}Ôv'n£ÁÒ0€É“ÏaBµO€¸¦v*&7Kš/¦ÿh5&l_æ¬v^Ô¤5o¦X¼[Ãâ§úÇ<•¶]dŒnÚ«ƒ[©þ–÷d¶©bxnÚ¢JÔ<òSj –¯K:üöÝ¢@Ò!jßtßËÓGfÊ”†*«ÿˆjG=SªŸÜ¾€åƒTwܘ¼Yj^vÌa[J¥úÇ#Ž –·oPëþ›‘Ϥ±sšUUw`òùŠ*Àè^¯ªÂêÿn;]2F?q¥ü5U®¯g˜½£fvr½‰’Ôþ(úÀ¯u̯ã¢í¨}ØÓg0ýÞÊß?ŒùWrLë[Œ¯V©nJµc³ýh>iì¼ÔÂki»°wÒŠ°ÛXüÒ°ý5ľã˜|Ù QW1»YMb~˜dÓÃùwËáÁm˜Ÿ,Áðý–Úîcz7‹”\ÅøV•ÇøË>Ç<‚ñu»yïŒïÔw^=˜<…œï±÷œîd!?jZZx`ãçÖý¹6,~³ŸwRߊߚ2`ônÜŽ|‹ÑÉ×{ëˆÍ‡œûÑÉIPŽÁä»ÁÅŽ5nP[úžzæ·Š°¼•¾,‹é­DjõâÖo{Ý Ìõ©5Ø;SˆÄ¬:F¿ôü;ŒÎu‡^,Nº‹·ŒìÆè šPëÊâ™_ _9[>ŸÅæoUà ˜¾B>ÒRó@[rùÌbe>óº Ÿ¹Ò¢Øyy´#X$ú5~3qòT}Äþ±¦Úù~7–G ¾68(Ð ÷«“!ðøY ¶«lgÇÞOZBîPü‚/ŸÃðËä®|¤êýšË[ZŽëaõSÐb¿7¶~몛7¦Ï”+Gè°ø«›8ŒŸgÑsm ‹ÃvÏ ìœ+_Imر,Þ»sÓ{obùÌÅ'µ’zžk!Unˆp*Ý…äï˜Þ<û$qÔ1·ÒaìœâëX]Ö]|ëã 6_λù›od¸§Õ?uŽ{º0ÿ-\~â…é¯~¿–%–î=¥æ‰’ŠPÌžÙñ!IŸ·´¿—`üå~ÀSã³-P÷­.vîéíÔüÚΚˆÙ›­«_»“L©Ÿ+ܬ§¾OÓ{%bñvã@3ÆRHL1vnö±+LNwî û1¼z’êv,OÒbç%Áî(½õ& ã?S¸HÓo¶Û);Ì®ÁBöÔwö’Í6ŒÏXµ#–T:Á X=ÜíIŠòÇÞùœeOQûì”$f~OŒN73¶/sj5ïV$¥SûÑ‚ñ/*Ô8ßÕ€ñ¤<Œn&Ã…*qÕØ|—k.ðïÁèø>½·†ùÇ#Q%,Ï8ò>­ëqäRõÒÆñÓOÜúð:&—ÃËjå5´;¯€ ó›/J*íÄðšŒö6c°úNVU¿{ "°º¬!R„–*ßAɳØú­÷ª»°±Gf_=…Ù!éóD'F·°äkÁ3ì¶ÏTùš‹búì }ÖÕ›ÝF½1ؾÛYQFØû`ÿQ¬Þ„èÝ[±þ¬;óñ‰LÎòb ³ùÙ>u*¾@çmwŒžqöy©`ÿõ0ö Òmü:œZ¯Z_Áaï}Ýfº¼©[oŒÁ¬)†Ÿq鵬$–s±Ï‹ºå™?Põv»×ÿfçÔIz /ùñµŸªh«Ú‹ùŸwr2gUkO±¼ÕÊ¡¡…ïl­ÑÄôT9Ïá•¥%`~‹çð£~Ssï9L?Ù¤¯©ÜX‹=ƒÝ/):;©ïùý³¼ÂÄá\ æ‡‚c7Îaï¼N¹Ù˜$N5cù9ìÏíZl={µ’úù@} ÇšÔ÷ïÚùVLïý-0XÒŠñ“Ç»ÃËÇiÆÒXãòS©õSrj¥¶¯èö¹›1ûì_¶ØÄê¹ p óÇ䂿ש/¦}±q]‹õ¾1ëìÅüâþîafß"; æ—ñ³ÔÏ»ó‡õj1¹òÌ”žS×+7ø1~]è°Ïi v¤jª¶‘,¬®×Þû £ïûÑæ%6_õ× «S»SÙMü¨~¿ÇZ×äç]KxåÝkªÔ:…0ZEµ_;© “·ÇÐý3F§¨»°Ã+>QMi8Á¬é"õø¶âÌqìý¤ZÑ„ ³cÄ›qyL/eü T=¼·›;Šå½©£’˜¸µv²PùT$¿Áø/Ž ™Åô™Ÿ™zãçV¡ÓQÊyÝúׂ¨õø/N°ùÚÁ·O0Øf=¤†ÅiUøYêç­…,ú»0»D‹)cú)ä‰ïÆìê”è­çHßÇ䏿üùFo@!ê)æIb¸9l½îC3µ?¯Ï”IÀøí°¥Ö3ù¡Tý¤¼^ÁÖÓ‹¬©y§òj5Þ×å°û£×9°ù´ïç0ùÊ«ôé¿RÆíê?‚1½¥snã£ÄÖm¡ÆeOÞüULÞzœ•f§Ò´¬iÌž…iB/vañõ›Å £òe »7ºI}©ý\°¥{#“¿$_ÆÎ«?y…ó—àìý¡;K£“̺;‘ªß{êÖ0½­ïþŒ—rß›‹÷Ž»,8¬jØ‚Å[÷9Éyjœ\£Òß'œ‰Ñ¯y”Hõ7Ç jž¾]pÆËc‰åæÆT;eIž£ÚŤÈÛ­§1Bý\÷&«3vñý)ê;Yé\Qw¦ü£ÃÊÃ-4t4Øó,­ 뎰Ý­ØÇëÔ¥ÿ‰ÂDAq²rÄc]3Û¿ðhþR¾vý7œíòñ£ÓÐ/5º&/GIMcšh$è ˜xº-íêû¬ÄÛÉàÎà#µ2° ®™M\Gª%ÀvÇà—3"`Åž»Åé`¢{c¼v@¢ÛŒxÄÏ»h86éïó †€°>žc&˜†—IÞ«y@¸a~!Àö ØÎ§:òäöAð±AÞÃ@¸*£|8° ò\'vz!öcEsÅ,w¶„Ƥ‚uòèèmnŠ<øåg_J‰ÕÇ„hHðê|P® þ:Ýw¶ìh•™Š4(öv˧ˋgQ53ñõ`jIvØKÑ‹¼øzjëSaíZb~Ñ:{›Eú?ím£#*›{=AQ]¨µÇ…’Ç$‹$}ô”ÀØãWíÂNJÞfâaÎ~ ú»>ç^˧]%a9ù™ûÒŽC¶ Q&bŒeë#ÿþû»q‡F°ScôWg¢³ë§ûÊîιÁ}Z¿XàJ\¥í® '›v¶$Ú…ƒ–•ÈÓI•ã`µë:›_%Nó6„ÓSU@¼+PÄ4ýH(Ê®q·ÙÉd¦«Ö F’áZ”| þÝ¢¸ö ˜- ‰Ür}Ù‚æGø\0cpÞÅ… '³ðÔ8@Vùs¿ðVÐR¿=ÓŸ9ZBSq¥8AûHÚâÎ+ ãž+#`™úLÒ=bÓA&Àò¬BŽèdßnÙ ðß߸Ÿ05špxÒÇvÂüË‹O¦@¯;§þéFJ~Rfi'|mzܶ?‡(ö^ /›+;Óš;\´Àö׃GÚC×ß¹Ó°}7¸D{7Z-qB°?ËòÓúpMyà÷ž‚HúʳšpB›E˜ÃyûÚÁégàJÏÁ3Û~¼v,zÛŒ7Õù¦ñl(¥3§T¶€ºŽr¥Pš h6z óš€U¸°‹» XU/uwÒ}å³IK Ð4›˜î¤ç£ª­u2´q€ŽšœùúMË”s­÷k§üŒ[ù7‚ê/æÀ5—Ó§ 8¬Õ†•§A÷°½Ž‡)h ÁGÙ ˜Ú¬ú7T4#H‰"z ÇÀ®Éèƒ@í¥ë`©é®¿qiX]´ôÕ¼ÄÛô®•1 0lÕŸ°â“í$›®ƒZrÓ_¯ÁqçúÊÿûçePK XøZv4ŸÞ7úõ|\²¬¬7WrÀ•Єc`î‡kûä'¼Ó!2rÁxcd¸ZŠõ¾Yš¿£6g6Ú*Àº~êÇÀòS°ýTTáêúÞ›ñ{ìA}¾Fòwi ¨^?Ä{'Å›{¸eÙíáòdZnþa'ݲ¯õ—ö\6㬴ô4í²9Oõа ¸øÌLìi›&ið€ëWù{ºq¬4æW/®TCüölC´nqä²è‰+à¤vxoÜö pÞ>fò+ŸLd¬–CvЃÖÝG§œQ÷u­ìâM):± õáˆqÕê6«õ™bu«®sL±`˜“Ζ ÒmM“;ÄTä>3f³N‚̽{N˜†àÒ~þ3YA§@|WvìÈÛÄsè‚Ò©¦ ™ÃŒ »¬¦Ö!V ¦Rûé=RëA§Ÿÿæ÷|U0 ©v%ýŽƒ·³ObOìƒTÑüf—ûÓtŠà&âi³‹3‚`ºZ»-uˆ,”ð%™/ÌÁJÖ³FbÙ/UFµ§€ç¶LÖ. ðhLY;rü)8÷ ?é“OÆKx“kŽà·óHVãðx‡ÙD õà·6Ñ$q\GZ2^RìVÁ Ǹ Þº/·P…ëZºCÕ!Õ`yÕµúÚË^P8ií’ù ¤‡Ï8±ãgAY}ôQWq/h忞3‘Í×feBÎpyOÜ+úG ýÆ\`ñ[*HG‹ùükÄÅݯðâ@ßý‘_Í÷`*©’š¦ë øÆÓê{p2 Ëúû­Ã='pdJ"}T» äòMæŒjJÞgÒüÒTn¤}b×ÙÁL"gÙ²KT’SfGiIûuí—’nÕî[Y¯u=ACtË0˜îCea¿T÷6ÐúºàUR êΙ|Wu@ÂñƒÑï‡q Âiß!­a’N‘E ué ÷Äð¤—òs0Q᭾ȓšUc¸ƒ!×Áp<®÷Hù'0†µ˜¢|`|îݘ¾/ho Ë‚q´{>î®:(Iw]fU5¥È‚Cü‹y öõÞÇ]¦/<»H«“Å ®œ îto(u¦½à¾T°±~l¹œ~Èéõ¶/”À:Ÿ=¬ä3 ¤ãg<÷€µ•I”fÛy°˜¥Ÿ-•\ïHŸÆØ h”3ãJ@ÁyJTÍ4¤gÕÙުƂlŠ{ßuŽó äµÅ*ƒ<è¤mçUOµ“kýa nû.=/Ý ¼q;×·€}§í2˜ä )Ý4N4ÿý†þO)¤þ\9%õ}Üš%Æ„¹lÁÚw‚/ÈBt’˜ª¹Ž€Áø#Yþ¨0ù¨Ê%ÁJéûs´¾´ö÷po-˜—Ypb ð÷ÞØóЃÏÜö3«@Üø}…I´ß‚ï¬9`\½“yùR %d?ÏÜ´£ëžÇçÙ½ÁëQ¡åÖ­¬6åÉAðž…Làvfǰ{Y<iÖg~éRê–‘mLLvàøa2À×â¥^+ªœpÙÀƒ*í;=ÁÒòè»Otò [®°6nCMo9‚ÖI~J^4Œ““ò–©Ox 0ð,$N¾‰×mŒ¶÷:EÀ±y_¸êÛ60ix{™ ÿÈ;¥X~N«ý‰·Áü|öââÁË@z˜Ç»@ÿ L§ÏEOù©5möÅc+ˆ+'3)l‡w¥ôsš&ô5$䣛ƒ`?{Kˆ½\øGa/E\‹ac}u¥o÷Ö@‹ñ)íDT H>‘ÝTëU]ü8ÙyvàH>Ï@¨Y³}åË+zÃé(øy‡\e¢ôIßN/BEù—ÜP®~¦Ö½qdD[¢áÔaP)àLvm<×{Qèí~e!øøè1Ÿ¼Y´¦ÆO$s)þ}Ufäþø(èk¥ÑIO05ÂñË 5RÚgï'ÕìáÆ™©l°ú¡1¹šåD–ÑÚ—‡±üÇKÙˆ˜Ë-®Jë‚Àù–‘›CQy¤ÀKx">Õ0„ ø‚;Ͻ ÛêôÀuîìï&Í«²Å®d‰¾¼yÀT§ú¸U7|Àqœ¿ ÿΚm‡gGˆaLí 5˜ýYϸô·îÏ%MéÜgwK+OÐ f?Íðâ>è¯,d6˜¢fŠy û;ÐaoÛqÄäsbh+¯@¯ö½%SÉË_vÈ’b_žY\,Ϻ3q~µ­Á·Ýù êOôk£ƒÍ÷ú«æ-Üû0 *h 긾?ÒŽ÷7R:_}€Äê¤ çKàÁ½Å\Ÿ샕:"IÙ—Æö”¿"ÜI ×Þ€ÁÄ6vIÐU™ÙÕ;k ²X›%®€^#É’õ«!ªLç¾ˀƛÍ"ŠÉuJ»~Òwñۦ.ƒÆÉ©ã_lTA?¥ã‰åÁÏ ½¹ÜE*‘£ÅCÁ ×1¿ã´r©›YéÚoA]Fq>¦9ôWš·X—ã[hüäÀL<@þ¸ßpT‡ùñ'‰@n •l£ôíÛžMºzõÞ•yŠnü¸— ömË"ñã€Æƒ0 ,]Ü^ÿê'Dvwί,&åkÓàwÈÓô«8˜¦å\.TÒRÞ¥ðoqà{ÖVðëå9ðXâˆÍ§ äý§ð¥¶”8ÕU¶’<Ú}Æb–6,Þ]%E”¾ôEô­3{À¿ô¶×ê/ààøË€÷%' =çÞ­‚ƒË.†[ e­=|âï"ÅžFrÂß™Á·sd;ÙÕÀò°Z ì¥'×_ƒqKÉw›»ÁIצè ç*èzW·›‰‚¾éì1ÊýEP‘ï3ŸYË¡ŠNÜÇ Uþ­£Üè7ˆ;䜑Y= òçv+IÓßÙgòŠ]7(uÍ뉯냠·ÿ–Nˆ97(v7^Où š¼ÁçFV€NÃÃrp!\¢}ËhìMU›¶.‚fhÁÜ£¬HÐÓÙ =ê‡QàW°Ô¿uáR5¸|Hûp5¦fé?Á ³¯ÿiªÈ'†u1Ö‰à‡ Ÿî‚P†«®Fš'HölãrÙ %‘%):þ³RO׃š/>Ã6ô”ÚÙ ¿u¾èƉÃ9€kvÞ•÷ì' ÖÊ.À5T&]ˆÈÓïGãÞÜc½+§ý ”8gn4ÊÜÌ‘ÕûW@?÷Ì„3o ØÄ”÷ØòüëRoîeJîEíÊ/ë JÿF\µp÷“ç×LÊ(u¸Ô†XÞ¬Ø_'6¨AHG|N¨¦÷„Ìwò‚Ò–,¿¦çR'}Uc…ÿ›d‰É_"\ê¬ØÆšÉ…ŒF +ÑWõ‚C„õÖêUý@j0ð¨Œ+H16½õù6@]Ôw7J]E>7¸Çó6(š›[/y‚pæ\bÆènÐݺ¥„~b´ãµ+h“Áó°jf\ã®_Pÿ {öÝ;Ú÷<ë­ÞDHÉAгG×[ÏRê¬C+¦¼\@\•$pÚ ãU³ìù@òÖÍ:ég'ABôçÝ¥â“úSu) ¤ùö<ra ÏßYS¶±`ÀºîÓ-sŒÆ/øÒ3F€#«äŠß·×`øãLêÈŸ³ ú1Þ9Š¥Dªø?ÞÎs‘g¹5â (½ùZÞÿ>˜0“-.¦ƒnÅáÍf2+تÎü¢µù F?;ÅU¶€%÷Äq¥3÷O{asxȬì, &ZÀìgÅF®ÿapj•z¡q÷'h0Ú$ä9?}c§•ÛŸèAÅ:àGg<ˆîÔzÔD÷äVX«%Ì]@û“,cÉÁŸ”8xpôÂ#{PÜ8Ðþ{ö$˜YŸÔ‚¦,°< ÷€{8olè®4p4ûº¤R6 6×½fE¿xy޲Õ׺Ï`¸²Fwâ%€‘;ïKËbÊý}-^2DTlÊm)qYœ&§ æ3:™¯èFÁ ¹.Ÿæûcò¡S `#|v¯K¤;h­LºÏo΃wôâµPöØöçU²1è O¾wê]‚ij¹ö qÆïpô=eÝ_áø¤¶ L™[wÕ\j×C4 /4Vø¶±O^b\=^ü~Lý.&Š=œÆU2_‘98”8‹¡/×Á±¬ð…¼®ørÍü œƒô‘£IG Kmïœz:„+¥,Ò]ƒ”¦ ä²]ÊqøˆzÉûßp“ïή`Bû8 _’‡Ç¢¹… óǶ%?{¸å3ç”÷ˆù¶­~ªÝQðPªl(Žm7âá?”Àä§“ñnàlræ_Œ€›TË­íû¶îâpÅlÜGPÿ53Ùƒ½~ÔV´òŒÒݰÐnò§ÄŸ»ÀÜ½È ¶¬¬ø6Ò¼mͰÐç7 =™óÙ5ý0˜òâ|Žs‚™àºbÏ Õåb :Pq¿eçhŠzo­²H3¡¤Ï@,T×^y™F‡Œ«F@7ìP»JÞ0>­J¼®åÝĶ„ kÃsnrõ>nõÏþIÈØµü2’Ÿ•nqWì‘ÉŸóÛþ ÍxÒapåÚð—CË;^´‚K¬o¤I²èVï|ÙFŠ´Ï—ƒ8Á…ïÆ¨¨v„2vm{lÅ þr%QœíZàsg“Ys¥~˜Ô>¢w¬öÏ$Œ\XG/K™Ò‚dÐ2®¹–2Üμë_å=. /£‰—å#oAVLq‹ó©´ØX¼î6 ŠRWƒÏŠù—l&æ:i $qTÝæë&hŠþ25H=Z&é-‘ËÊ u÷é…60ñr|Ëvï$ÈD~F§Ò”£'77`_ÌŒ'N(·å¡'g¤»À´³3íÒ¥*p|k)qéþðª>ñ N,‚®³êH݇¤áŠus^ Ì”'zíèµ5YÒ5WP1=)™g Ñ®¾Ÿ»FÁ]ô'óBNå¸ ~{9´l…ÉùÚàý|r9ò~2û^¦[Hß;GFª ƒó›Å SÝ÷à~;½vzOípÛœô½—uàüåáÌ­Ni óÚÿÑßÕl j¦‚ŸRmÕ~g'û\Õpï';ÇÒ±I¯»¿Ot¦þ¡på¹#!(V‡Êâ{¸ÀƸåÁ‹“ à–$~Z<ùŸ;q™°õ „圿#«Ô )Œ±²õ²nšöÛœít\Ë̶”ª·„`Ó¤,‹³ùñqÐf œ"¯èKÎTCð«¸ÃÄ#åàrRaCZÐÈ2²‘’Õþ`±KÿmöŠžgOÐoÛz TL.*ÌÑiOFRj“5µ'´«n`|è óS7ÐrM¼å‹Žε?ÚðQ¸¸)eïÂ7’¹Ãè©Ýì|Z fDwMmÓ|Ï×­·€A·ü¯‚g7ÁÂó寥-Ù /B}» æ¯j“ì›Á³4ìÁJþ±òo ‘Îç ƒ>^ýàŸªôD)TË^Z¨^òÕ*ñ+/k ¤xgïPüðà&>uv°Êê—Þ&ÐÓÞÝ`•Â&lËÞ›•“wׄçA©0»bëLhÕZ‹9ƒAk­dÉvOp11ï–åÂ\‡‘à9Ь˜8>8r p9³¶Ó%`6 t?X ç·¹Ÿ.¥Ôé:ý÷3®(©æ µÙv° |•W+úçÕ¤Ä[<@“áù+¼0à÷Lÿi]ÏéZ>2ñÄÐÊ'Ur@\gÞ6óÙŸà«í7Á0Ð îÜ;놵dÁ¥HxlxÐìg«ŽX“¯Qú<âþB¡ ýú¸æé«Ipù»ÜòFh xX­Ç¹‚¾1qˆI ZëF¬çA•§ô‘PÇpð*ÐæE‰úV)[¸¶öYç²oxKÿEü™›–Ñh{Y ¢§^ì ?e/ú ¿”¾åŽqŽ/7‡ÁyÁ9:ciÀõ|.æ<Æ 6?uÞ7šù€×‰‚¶ Í!ðꟚNËÏx‡m8O@˜Ãn!æßà@§ ”yŒ‹¼ÄBH±@â4ÿ0™fü&ë]VÀäI8 {y<¸g[*§uK‚Õ[_ƒ/xAo¥4MÅû9•Rž}†ÖämÅÙàZzY%ö»à•‹B^¿“÷Ã7é¬Zƒ÷RM˜Ü'°±=üˆvôèšÿ}ȉ´b–ëžîü~9ümç Ÿ<~ß ,÷ðH+º<â\*ŸÝ"Ø,Û³­$t»¢ì¬B A*/£'ê‘XœQ>'rì\_LØ„þ•ëvn~p8gXw½üžù±\LÒ§b†ýÞž;Á¼úÚ¶ßåΠ¹óŽíÀÓS ˆ'§ðí4~± -xÒ‹çô[ƒ³Í=Åumð^cŽd=¯ އs\U WùŒ†u£QpŒ1ƒŸ?ZÀhü\—Ûƒ.ð9.dfS<Ú‰öXDÁ(ájïÌd؉NŸìúäçŠ1U}¯€x:ŽÕÆð+\çéy”?ûl£ãâGº=Á–°ïá0z ^W´._‰Ó—2cç^VÇÕl‘DÉ­`Ö@«6¿ÿ˜YTVœÛ'rÏ„¸Å7}@mÈ¿F ²%?MGYí@ºêÝòƒwWÀü®LÂõ7o@?=\çï'OЪ£¥¥Uz¶?²â×cðÀ-<±½ VÆUŠ×uŸöVÊê: èMj¾"g6HÎ6E%ЪNôÕÝ1.âL1yë@òaU ßAÁ ©Ýú·W ŽY HÏÓ íÚ »ö€á›8Ã}¦e`õåQ¢ð_?ÐÞxb^Ó!š]LÂ-Ž`ø‰wÏw‹0øôÍÕúT˜Þ½¸ÐÀ1 2ÌÍOÜØ~€rmší£9P­Ïûpgò#´¥m<½Òû?ˆâ-¹ßuÏ}ã@+´®íulhN%¤rôË£Þ·Wªkß áß°~UYoà6رXÌý®â­•¸I) ]Orö yÅg¾ƒ±í\‰à&Èe}w—qmù±Ö”[¿Á:Y[[cèxÛïÖ'E·ýB’»÷¬žµ rÜ8Áè™O×Cµ`gÈxïs<+GX™‚-³½û¨Ô0þ~õ4+X“m Ð0ˆèIòý ¶?_{ŽkEg™XÐè¬Ï4Y‰—ðˆv"èòI*ƃµƒñ·º“4 j:tÃ×[Ô ‡v~7¼ÙjIfÓ8ÙÅ:''•Ú´¿b à#ùåÁ³àmáhИg ί’Ÿ ;ùƒï¡1ùðð'w~{ìœ æs4_rn¸‚Xžõ6ï; ¯ÂÐ99Z¥ËNëÂi€‡—2, ×Ïk³¯‹Ó€ßÀãOõË`}e›Íúƒd°ý3 üýXT¬ªÈ>CR‚± ðl„”ØÙà[BøÌ }Þæ ø°ðÚ|Zã±!Í÷4àâ+¯ÀÐÁºnåË6ØÁÂ0ìñìàŽ½ÿöG\Ýi¶È¾\“ÞÓý “n&z^ä—Þ|;) &æß½ž=ܹÝ3­—}^®Z‚ïÖ9peÏ«>ôÛìv-k ºO¿&¹æg¥ëŽ(€Áy|GXûÒq> ºÒ§/ó[ƒ–ÙËêló¿`ïZc3#×~k~¼TõìO/ßÇîEh1ÿ¶8À–‰{-9Ó9%éÖÀ^r¿ãÆéQÐÝX°ßsl,… Þ¼:K}¯µsï³ÁÚÕOØ[£lwÛÐy¦}ÂÅð*Ãg`£áªçÆp6Dž k±y š,ï¿éH·´¯%«#®TüÊŽì ’y–kš­Z›`\&ñ>¦ë;^É}0ú´¼­3ߣÁóOޫף1°?®#ËZö ŒžpñSô§O?¶A“ýÔKwxwÚ¿’l«íùv0ª6ͪl2­Õ÷‚Žr0¹kñ5TšÈ<é“ïâHœ’•ˆ›gÚÇZ¾iÚ¸EŽ\ç . ïö¤èty•ǀ̩m+5»Û@Ïè•¿rê-°îmûK8 žµ‘»“­¤Á²Pûî /åþð=‘XdE¶ÃÑ–én ÷+ï~ëÍ0%š*¸Àt×_.÷ð°êú­2ß;¦B¹L_Ÿä‰çÅŸ±‚åìk{is ¦¦t?Ñ@}½¹¾`#°?Yú‚óŒ˜"yä‚'é¬#ï/zÀK ¥sWÁè/Súàú¼eôÀþï ?¸Ïú¤l=˜½KÈÝ>dúR%¯ZK½U¡»8¼©·ä‡ëÒ­•å@ËwàwHÈ;0¼÷`åü^Àñßj(oz d]–RE\û)Ú(µ¬Ê¢;™õσܵC}¡ýO@÷Ê߀íýµ Ê­CÞ £Ô]fjúæßÈPAûÓ lÙW^Ópà &CØ\POîX®!ÛհוÓC0Þ³Q§†6(òɉYòƒ^0 Lø® Œ/÷ÜʧÐ9ZSys×Ðõ°otût tždõ«î}Û훨o€ñɨØg×]ÀÞþ¼˜ÉpÙ»y‚«ú›ˆff×fÀ/ÂåÐüD8Ïßw–Ùžé:L¿}\Pu³‰’g^W¬o_mÂQ­ƒ’1màn“xçÄè^À-žyú˜O<þIŒŸ×‡áe'É N°ÒظðÚTtfNîâ<®A¼f}þ`s¿þ&éåaÐlLøìÚº›†úøÈNp8¼ѱS‚·™óe~^ƒdºxóÛÀïËåÝÛÀÙç™PK?3¸‰eª÷í3€ëóÁÜÓÏSÀ^Íßaëñ|pú!-Öø¼ñíŒ"€€÷ìÍ—iqC/²|ßK©¯ºñ|7ŸÇ¸ä&Ã-ôóÒt®«æé°ÿvæjÜ2Çîšg[1Ùú)&aƒnPÒùýùÚKÐ6 |.Ÿië’YÇIÐú;mkÂÆŽéÃ)  =0½öЉ„ê"Ïùø*°¸´¾Åù&ø¾Ç}wk=ŸÆwé9<›g ÌÝ<ê  àQt0£p¿ËìøxDAi˜œ’ r¬óä…ªÇÁx¡9^lÈü„ffûèï€G\‚–¼œ.¸]zòT댸¶ßÌTÛVLï<Sò7»¬˜ãl=˜óO´Ísº€ÇP̆ãœø'4ÙZQê=Ëy{[…>Ø~mõ~“ö|nÙz%5TBX„oè¼ã4xv\½2Ÿë¶®½=¬`céV²þÖ¼š']¶uáðÉb[0žÍäíñÙP=¯ h ¬}h;ØÏ¥ƒ¥­;ÞÐÕÌ­v´ ÔþÙ›¾5äÀ,ëÏ„8©§üUrí^h¬×C•+>u@¼’ŽóØzlvϧ‚÷•kæ+ýàtõG傤¸ßÑws`˜½y’ÝkÅp°:V–&ÊÜ«ÑCGÀ²ù† wÕ/02e¸ý .ø>;ûE›Hcž*œû`Yp‚÷<è^ëubcµ–_ &@h‘úí|\ˆô3|ÒÖ«`¶·¢íÞ«y qªhlg ä1îkÛò–Áøjiå*² X‡‡èî½­¸iÌ%Кà`»à$r&*•VN¯{Àý4XZzªñ¼Lw‡Tål€ÃÌ“{{ž;€ðÄK—x¯'cäªÄ@p»7À±5¼Ci6ŸÑÙNÌYàÀP\ŒÜ|ðk¤ÎŠfçë@Ëôº¬‡>(ݘ)‹¡{ºøÛÓëýÇ@-y`kXèQP¹Pî)¥iV\݉,¤E¾pè÷ÐÚ¨mI €h5Û‹‹'éAèïWÓ0"übë —ÑØYàä-ü{«èײºtõ ØDÿæîÚ ÆÛ…ÿº‹)•ÅÇÖ““[Á„>.LÁ¤û‹$r­³@ƒA¸ &¬Ïµ¶”›{Ü`éI°ãs+½^?öálù:`×8ÒÙ¶|ÞD¾`ªëË#»ÔBÎÓ‚I2.#çÉ[Àëù*¥HPòè]Ö¯¯Ÿþˆ/·kW"àÏÜáԈ̢Ðw\™Ø ¶yž‚·8‚Ñã• âw[0;”ræÉ½ 0³šf”ÒY¤ÜÏצtºA¾tuòû²/EoÑeø·`²M`‹óKfPškÎ'ì¼Ëp’üc&pHr¸W †ó¬žûiÁ^â½Þ[Ž ŽèøÂCƒ¬‰çOúôÀUÆ@©þ¡7Ødå7qà2)Ãòg×:øÜQql¹Òëa— ÂAïˌְæ*ã×-[§™wœëVp]+ñ“žª xŸ›)¤ Hƒ`z3®²µ‹ ýâž¹ëñh0Ÿæ=ôÈq XÕGéçóƒW™¤]—¸ž~0·çÏšDuéfÀYNÑnHý¸ÉHoo¿ÖvÕ'ĸgL~¢ëDØŒì?þ#Ö ÈÃÊÌÛ3’A‹·^¾CE ìÞ©Fò'5ƒÁÙ¾Ï/‡‚ÎÅ“ûšq† 'Éf¤Ý ãZÜð™@9yÝ$|½ü)ñÈg™®¼§ä]->17[OCB£I™ù‹Cà¾GðéP±-8>z ÜûÀ¬ùþŒãucá¥2#ðøò&Nõð9Às¬Åüš]-aŸç.Íà|G:1È ¤›»E?¢³_AÙ¦;§Á•ðt/T ÈNò«¼/ÁæðÐËØ `Šonâþ®—?æß² ÖAÕ{ÿ,ƒåá3DâSp8ßt’âÃRšßƒnFçÈíPP$¾²x° ƒ4Ÿo,p‚:ûh9:äãê2e?ÝÓž³Ú/Ž€‹u#×íÛ Á“o““*f/÷,WFÎÞÁÃv/?(T \‘ÛÏ Ò¡©Ê3*ÿ¾¨3’ßB{t·û»+ƒÖÇ¥4áp°ûpëðë%°ñçʲW¿O? 6<×)á á¹9@Ðj¯á÷®›À!|¨½}·¨õÔ¸®Û¨w>á_:W™{,úúA¥¼ßìƒ|"è\$¼?jL7n¹ŠƒnµgÞëÏ. ºS)(_tD~ª´C+èÛ+{q\— Y–ÉJ”úoÙ—³®)LÇ̾̈FàöD?eu™ð44·íKíÍNÓxqPÍ ­9Ñ&Ëø.“€l!' Y 4®CJ>`!½OÚþà·]|ä[FÃÓħë ƒk–U8ódh$¥[øàêÊÏp+¬Ò•á:ò©IÌîfk î.VR/T²ýû´(yÇq{F?8e¾Þzðó:¸õV?ÓÖ¸¢ÓÝ7|¦Áå~lqä™sÎÍ+Ü ý´Úùp™èÌ6< Vþ :sKÌçTÁ¨ÝöŽƒTà?v©«'u@Q’J²hž¤“àz„ýí%ÇPêìqãît+Y°ßqíi†ÆE¸Æ½¢àU ö`ÂÅhÆ÷›ò’€rPËÝ73@ ½Ô” ¶ièÊ¡´à´©OÃ9|1¿¯$ J~j§YEˆ/¤Ól“Ñ-EO `‘óÆ[¹Ìé¿ÊpòSY;ÙL¦z0Í~žßÝW†& C²Íæ`¾¸ë§˜Ì]0¹wL*švßiœµ«í-CÅ´2@ÈÞª Yh Š%8Ôó äN*š‹2F}w"~Œ²Ûކ,ÍáÞ®ó=Œ `ù6L®Wë1x:„p3égÓA©{a7ÀnÏ á–öDpRο_?(N©· Ɤ²€»èÃÖ/ÿ€Íæ…¢•Jà’ÆÐ|üc0øZ_˜8Û´LëÄ[l;À!}bÞMcà¥û>½Lž‚{GŒÈ‹à{ÛÚ³ p¦ô§¹>ƒ.©G¦—R¯jå^Õ—½D©«üwv õáJíGσ¨GtÜ‚(ºþ²|ÈAši癩–€Õ£3äÀ°ðŒ(ÊOV`û.Ñ;¯IÐvm–Ò½ºC¬w>Ñ‚`òžº¾c”<}!ÈóÏ:è/ë—™ð냷IIq¥¡ à_|>évIlÆ| G¿‚±ªà¼úR"xi%¦"CÁ“Ž æ « ®ÖËb;wªQêÖЙSp ¶^j·ôý<Ï(u€¦ö¯¨Èà\ÐÙy0˜øðOîó‰L‚Bòûݧ}jÁü¦yZ¡Ç_À¼ôŒ±â«Ù]‡Xÿ«˜ãùц`¥˜$ÇÙ|,MÇù„s@OÉ·»HyÌØßdÓcü›ai—€ðñu±{q>˜\ú²·Þ¢ ,…+hž ë`Ë%ôãI£'8kû(Ø=£ôéÆÍûž"°Ÿ«¸À¬*YË•©æ SrâWÅ5Z aÌ ca;ØÊö«^6.“»ö÷Šø¨uVWä¬$bcœ„ƒ¥Ê§öø½`źµÒ›^ ÜUìUvâîÎf0;e¼rQñ/hÒÜ:J÷H *ßÞÖ> ®:æãocuÁ—k¢9¿È…×¾~;DéWW&õµ¶€ ßÚç± { Ÿ+ü³·„t:‡ b°ð7Xy1x:†óF´”º‘¹lKâu] sï ÿF•WO­ñ?üÜ `>r*júë<øÝÞ÷ó¥^p¶½¬Vyà8è¼è¸ î¶âO¾Ó?sxáUF±{9Óñ_càˆ–ÔNÉk'pÚ0r¸¼&p·tE"*Nîw{E?ûooÂÀIÉ»;ÌÄyµï)G3U¥ÕÀI¼·D³ í.³Zü,¸qM ¯îæ›Çv  (Qj&åg3E¾}c›SQÙ]5;À²õ>36 WØ^Ÿ¼D‰;>z昈2н¡­þ®¾ti× Û)}dˆ·l ³!X« ­¡Ôíg¼;Žqˆƒg–Ì”ï7%ðQ;áfpv쥫|í@|ÖʯÖï64„ÎznîFòƒ·£`ñ”4qn°IÝ Ò‡Àž´¨c´Ø ¸ôÈK[ÞÛ,±áãÁ•›]/Ïû{Tdö!ƒÜç ÓzÍlÓ« ¬KbF55ÁÔÇ­ºQ°ÜÚªVb΃uÉ&é_Aín‚…­H˜‹o±šÄæG©·8¸=»è–öRŒ£.Ô‹ÛÅ% iåödå«ÞÊ“\±”:Ä¢§»ôy4ûeý¡·½ æó¸ÝØû &{èë†Ä~гeÒ?ËÚbÛvÛûæ( `¹Ç‡ÎnIçŸoUÂ"xÇ1Èlô®l²¾om)8 ¸§¥¥ý`ð£êïéRЪ9¸ýyåuÀ‹™%ž·K©´ òž0ò¼rÛùÚA ¶¿Ãoú'C¥~Öb°¬ ºÇNÉÖ.ÅI¯@n5 ^™”t‚ÌÞ?ƒ˜’ßÎ,`ð wϪ;ÍßÏ]­HÂ×½`_ xê Î7 ¾i{`kÕspØ&Ù»Þ( vé:^´´Ÿ)ùAìÑzç Ÿ¦$‡(}÷›v:ŽB0\[–ûÐtý8âöœ­•æ¨ñ§×)õWÇæÇñ¯x¦ ô©ðo€Ë¤‹k÷æÄ@Êu{gmm6\VÊÿ2øø­Ú«¶â@åÌc¿L›0YóÈÍ¡ãÉÂçÅC¯ìJ{`Ò·r +3êË€ÎêžêS-0gt_ â±#ßàÏ÷ýQ-uw-CpÙ×¾òª*Øq–)k?:CñãɱôÕRpx2(„ÊŸ€-þë¸8È:èiü´ìÁ+nýë¿oÙ¤ùŸ¿„žö_ó[±ùÿü¥ó´ÿþ}ð VN$G+‡º¹¸ºó8â=y/ÿ¯ïøñîVÿõ+å=œHînÿ"K‹‘ýðûèé6iþo=öµ•í_ìÒ2ü_ìa$8»:z8Xýǯ¸gá“sò$¹:;9âÜ)ã?ÿ&ù_ë[þ-öMl5vý÷ Æù–ÿú„oÛAÅü××ÎÃÿ&ÉÿþÍúÿõ«üÿ»&ÿ‹ÿþ£N‡ÿõ­ƒÃ““þÿ±œô›ÿ[&†Íÿå¿,÷/Ö1v·þçÏUüoÀþZ,Ôâý·ÿ…÷oñ±Ó™þ‹9úÿºþïo­Üÿ÷¬û“›áÿ7¹éþÍÙÏíÿõ§ÔdÔdˆŽŽÿåN|Bÿa :]'ì·±ýKš­ÿaìÿŒ–ÿeô¿ÿIGû_"ü7Çø?ÖþÛºÔÿ¹Np ù?œíâ(üï3¶þ_£€iõÿÒzÿ=šÿÃòÿ‰ó¿øúÿâ5ÿwÞÕÕÙ•Ïïú_äBê¿iìÿÅ_ÿCK[äiþoüD•d…ý¬ÿô¯m6ŽŽ>|6VîVÿÞýŸÚg²Á{’¬œ¬ñÿú[´o‘­¿qÖ;ñ{ÈmúòÒt¸2"ë¥?Þ*{âæZŽüBv¾vMÍ"r„úQŽÈ1q´Æmq‘.´Õd) [õS‚·žû"kõ ò(ÂU_{©ÐŒlRïýþ:ŒÏ¸Ÿÿ¼Ù(hFÞþ•†œ/É¡–k7‘íVYÞ+÷‘ýGõc/ý²ã÷?ï3!7ÔìM""{sƒrîÍ3È©_óƒü¥KÈùÙιñ‡“ˆ”%uûáûE„½”E3÷Ùím£ê‘D„{gõFc"î䕳QŸ‘ÝmŸ˜íÇ‘³ßL ôv:dACúÂ.dí{pn¼¢‘”|ôê=óýåáÌ_)¯‘­Àø#ŸŸeÈ^ðÙߣYwyÝ\é¡r«Ùñpm¼Âíêüª4²cºz¼ˆ{7è·6J® ;Óìms—‘uà‘-’8Dd«§»©ú9àÞ~~G–B䨂¥Ÿ"‡Áj^çȪzùlÍ™$„y} O áí‹ §i½î^såþ”ãˆK·ãòW„oÙ}Ðær²éeá­%žCγ£s„]ÃÈÆ‡7û9·("?'K&¿ñCä³:}NµÈ6Î.FUͽ9ÊOÅ ;—VCö¬ÈòÝ®cÑÕˆH`ª÷úó‘&¶š;¨ !«‡¯rY,éAû Œú=dsÊåá£#›ÈÞèµZ¸vr>¦›Ì«¨Š\ª”½ûn† ç¿4'…o!7keÝNíIän·UOtÙ3m)ËGŽIUbê©2È©úÇË4ÈŽuŸÍ­ªZd}ðKc˜$rŒÐi‘FÈþ(φL•r<)t;¶=¹u8–n^@κ?ÊÆÕ‘íE‘³LÙ‘­Ó¾Ê•ÐEää¸Ä7· 9ÜËú¸ï)3²m>ÿnów>ræc?{UOÙ—Ä]³øò‘%ø¦Ø‘³py³6órüz;pK†rýlá>3ä¼o$Ñ—%¹º´Ö]ÏÔDä@ÙΡ%=ä"jè?pä$r™:Ò·ù ãH–urøíÊ;ðŒ9{°wI#ògýhäŽH¥¯>ú2lº¥{ûZéòP’MÀoD|ù–¦Ü”b7†gƒòvZˆ”ã÷½æ:²ã':W4!'æ÷¦Ü)ÓÈõØá]suy4)\a1ÙòöižQ@Öös]~Ⱥà!ÇaF&dG.+/W|€œâ˜ÖÒov!Ò1Iú¦`Dú¶Ó´þ’ÅÞOäðbŸÚß—‘}~¾û“Û$ä¼®­¼£¯Ùž­9•2ŸV»\´òYÓ÷ãi¯%d{$tù¯çäl8À¿¹Z‰l—Gc²l"‘»$ ¶@ä}ú³á[‘Ýåß®½Rˆ%½7_ò1½]ŽÌFÖáz‘Êy2ÈÚàf–ß^D¬]ÙÈúŬ¸b4Dö#+>õÌ¥È>`Rm,N ¹«GÝñ^B®'üF|)ù¥s§t¯U+"ùß|Ò,Ë‹—öN+"+=Ï7{¿#û[¬Ÿ¥¼FD¢´N´Ð2rܧ;ôp?"²Þža?‰Hõ:1¬Ã>Ç+<—vÙ>¤¹º>vÙÒßt7/ýƒ^‰¥œæ”G•ÚŸ*yÓÈY¿ÇðвÙ&UTzä²ÙÒ³ßEÙxþýøû–rÌ&O+W½@dÙ¡ºDÿ*dåOwŸî“²Ã1^ ’ÙŽÜ n'¯E¾ÓÞ/³F6ñÛƒÚ[‘mñËWÌ,ƒÓ)=IˆäÝñP~‘Oõ+mÿ(FñïK9AbȾh×,ÛoäüõkáW"ø±ÄRJA¸S©9´:ÿó¡o×µ dg¾å"Kq0²k\o½ƒé.¯ß­ Ó1nã¦ÏˆÌ4ÍR*äH"MÏLýÙ°Ƈ^—Æ8YÀÙ)y2Ogº"âGÀg5DJ5¿ë-e„ì>wܤµYE.oͺcî"²¤fåAÁ&äúÌ8èëoväzyìeZ0rù6¹l*ˆœ$÷š²l Äaˆ{ÏAdôªüÕ5 „ q~d‹ˆåÁ½!Ǧ‘ã’1û$ƒ*~íô!½GdÁðó$DzwÉÛérü"wX4ý9"ä<`ºòî rÈ,?^8B‘·Êµðb2" 7Ñ%ñ ÂÐ1'®‘;ȲVÿAÎí%Dˆ%Æû`BÄ m¯ +ËÿÜþYëäl\‘œ˜/‹6ÎJÙw§!'£ãô;cS‘s¿xkÀ4rùá”v³W¹ØOoñ OFöor¾ÿ®Ú‰ˆ{—êišUK„PAS&‘_<Ꞔ½ÈåÆŸwê%Ù÷©iOrܵT2¥O¹ÿ¶œc¡øQ8ÿ9·kDØå1c"$Ú /\·ZCý[nÞVaFÄÕŽ]§¢‘õ½Dd‡O•µ üFv;²nÕäÓ × BÜÙ¥Ûˆìàóu~ÿ{dwÅÙ/¾@øÆÞÙ—_ÈFå•í´ø²&Þ|Uþ™ïc¡3Ó°D$“%V<ÙrÿÙáõøÂë%92‡þD¸¿WËisYAé൪^y½¹9µÿÊSé_C„$|²R8 ²f)3¡-CÖ^7Ï:¯š!üÂþïÇ+ˆhËçÍá‹HŒ•è+ãSdnðvc^á>"žöR»z) 9U:Øù-ö r>ÂeÝDD¾Y-5ö9ޱ’ã)ñ–K+M¹OªÏ†»T­!2³ž%«À-älz¤F‘E¹1ª8êÿdEnR_~³§4"×Mv‰å»#ˆ|÷ð]å0dÛ`Ç—<€”¯_þ³ŽÜ¸?ÐV£àݾ ‘/ôH_å2Cö}el=w!+ÑB¾¤´MdÇv§x«O ²}òògÄ`6"†‰zLf ç“ãÅ ‘“VùþsYžÈÉðÇÌWMÊ}l•>¯Ù§92?FÉŸo|Ë–;Ã3s!Î/‘ÏÄñÞÖ·È*”ýÛvm„ŸÌ¢Ñ­ @NƒZ=Þ¿4͇KIqDDâx9­Üc€AW!{"›²fZ‰ŠW”sþõMñQüŸÿׇëÈÁ>€OÉ" 9ÕÕg?¢¿lÈg,i‘ÅÄê~Ì7Èièîñ™–ßÈi»Åäãã ÈnXˆsþ«:"V$‹´C¸Ž %úUQÈ~+]x@®SD®ýûùÊŽíÓˆ|9ô$_ÿ äÀ¹ŸnOÒ.DŠ“Ìð¨²B¤ŽÝªt#‘³(;ûd"~ • ú“‹¬ûtå¿l"‚òþ_¶4bȱRVt÷ &rÒ¯´}ñŠ9×ØèœŒ\Oõq®;j —"² xkŠŸÓp.r§#²Oê‰hƒâ§¼ÛtÜ!ù©X%dÝñ·Ð_BÙÆD=Õ囥ä ¾W~‡kì9Ó¾ rX'³H}€\s¾»Û.¨!{v÷þçéä¬XaÐuJ?ÃYXY%†ln^Þˆˆ9N¹U&nb[îÙÞOˆ”y¼÷¾•4¥çYÍg>‰ìêÝ4Ò¥€R?ü-×7»Œ¬ÊëÓžK*"{"¸ bŸÞl½“+².þÀ"+Ù„Lm+çv=ÙDæœòiRß"‘mòû»:b¿‰´®P¦¬-f×9jÅ-뼦9²;¬w¢'÷rÕñm«´@¶ÝOs"»/e|;Dg‘Cš¸.×#—Âüv½JJ5X_š=„ðsð§ÏkYŽ›¶¼Kéà ÒÇOòSö/}i\ÕGv T)r&V—Ò«Bø?™IaCˆà¾}½iá3rŠÝ7—¢‰]õSç2,‘ÝĹ•ýF±È¡„£8„i9Ø}A£"UçoÓólËÈîå¥/²¯ùȵóþ;D6:à*(„œÜ|«üS)õ¿^Ð÷-—íõ4±sÈáôƒ™uUdë÷Ðj‰í.rôÒÜ9¿N h8œV"pÁ}÷‘í‰OÂë/(ö>´·/I¹íðÊQáEvóÖ'·Ô? øù’­ÿ“ÈÉ|óaüÄ<Â?6l~8P‹ìŠjœ\O!œÚ¡©WȦêì|Ÿpu'c-zi†³{ZÀ¹$Õ˜„F(#×Â’7 Ø3ûy%·£×‘«Þë»r?µóüŽ—¸~ä²ï]ž½3r¹Ú.ÞZy‘*sx’/É"7æ ãڄÈÌ÷Ö?·º¹{'X®!!÷ñ ‹ç]Èýç9áÈgkÈõ‚‡ËBÂ$²½Ýp¼©·_ä°nóvE¶¿îŒÍÏïFö¹–,lM<È1(fý„«rüÝ#ܯŽÜü¬Ó“ñÈñUl™dë9dgÓvÉ=ªáï¿o¼7M‰#ÎäB-D¼·{«ÕÖÓÈv¸3adYoíû¼”<¹Rðe?ßwJlóc)pDöÇyŽTE¶}z+×e ’ªžÉzÊSdw·kFÖí5"¹)ý!%Õ"¼Š3OÊ=J\Æ/Šü,yIágƾv_ rbøT8Jé»\yXL5‘ËÆË±ç\ÆÈéö>_Ç5ÈA§:ÇKÉ÷K¢/i#‘]þëhŒ9"4ÙÔ·Pø˜»˜!>mŒˆ9w~$:Ä!¢S>cÌW/äô³ìwÏ¡(„GoWo-!»¿bZü#sˆP+´Æ­A雨zžóûRüJ_Hÿ‘ª,rILž${|@.ÃNö[@d?‹œO6fÈñq–k*‘—ý/̦ԅڤK&ü¿‘«˜ÄïºßxJ}ÁÊZ;…È ~ê²È>þ5ÃPÑ0rZ~øµmi¹ä_»8 Oé»ä¾—þ¥ô»W?Çñ¤äãÛÅå’ž!üøy©-[æ£|ýݪ+²ßîVô*é#rQê6jƒiä–oz‹Ëç ")2ŠÚ“‡ì_£…‘!ÈnUEàÆJŸÖ\ÐÿÙÿr¾·é.•6†ˆYåÕ*ý”<"{#}áÌ ]"²w¡‰•bENi—ÈýÍ÷ÑÏŒöòƒÈîáÀ¯Üš1„ÏØoð—ÒG“ž]3ýrTY·u^ºÃD‡ˆ+1²ã•ÉÈY]èÊPªrÞ&À(ѵA±~4½yM¢)uQ¯œ6óë„÷|‘¶¸J¹÷¸Zf2g#«Ž¡Èí«Èo•÷\G ²}[0ñ÷E"ݪÂ]Ÿ ø‰e¦#‰‘¶‡GITÞGø’gKCŽ“ˆœEbÉN–¦Ä½ªªËm.„e+uÈó'"˜yÚ½çcAvÑ‘ºç“ñá ¶öŒ79ì2 ÈÈ9SãýÞJÿ¿Z.CBDÍ+ãxd×yð[Q?%Ÿp_ØŸNé߬®„!ä¼PB4ºë‹ìv]¶è8Ë‚H ,ż€œß7ý)b£j‚Ÿ¬!Ü•ñõÁÝá¿}ÒëWíYD:¥?õ—Ò7¾°ý^«¤‰pnL„ýÈíÄ£=–Å”þýá§(­4²ß+Æ|{²mm?Ë0^ÌÉèGºY_©a<<±ŒÌ{ñø!ÇwcJ¾U18*K’Dö[V¹?#ÿ…‹íìÈF޽`k¥_m=Öx¹<.w}ÒD6¹R•)Gäí|—’-\Èö‘ˆã/õ‰v«”øÐeDÌWêNs@N¡¼ •ïÛ)}Øö=g>u#§&ž7qN#r×[Ïö ^Š];Ù¥ÔëÍ%ï{!Ú›?Û†¬?Xʧ¿Žˆl¿ý¢ÈzßAž`Rdàïǘ7Gé¿×úšj÷½@„ƒ‚\/iþÝÕ0r’õÚSuY7¼¸óJÑüÎ-¼º7ŽÈ´)'eOÌ"O2ôæ_ë†XË£Ï_}›Ó¾’öˆpNoEl QÎi;½gÙ³†A;ÿ äô&êŽýsJ¿SÝÍÀÑ÷‘BMóØ_FŽÑûÜ­¸'(}{֟²ä|©\.iårÞóg ÔºËç_¦5Nä²Ë¿^Éj‘‰l¸D"%·ˆN²§Sòí7!ƒEJ]þkæýgäö3Oȶ-¹äÓk¥û„ìcû™3iî ×ë ,ø¹Ûȱ‰í}¦ŽÈgýz~õ!q{~ñŠŸ­'ò~/D^Aî/é”>õ¨ÑßìׯÈZ›è–XeŒð}¯žwQîQ¢m]Š®³ "0 'Í:%oDï!Wº#òC¡r[È@.gv+šŸH@ƒ×Ï+?¦ô½Dg~äl5ê*™Œëwöx«VD®(ŒdENÓšîbGd&­7[–s³5Ô-_En:cvöG!r mê¥{eˆTô&¯éò"²î^Q*¶Aøœ ³á󂈤ü3>—{'²3<ÛÝ õ ¹&üx滀ìC_쨽r Mꦕ—\!B´ôƒx'rÌ=§ø]†rÏX‰§Žn¡Ô•{ØJN"§‡A“J”þ0þÕƒ}‘{øÊJ£Sȵ(m»P¯r:.‘ƒÈ'â"ºŸC®–Jâ:Ï#¼Gmœ±Âk?Ƚ‹l*Ät„uÿ®¦A°D¬ªïzÂÈm›ãâ5®:D6Ü«r0é)"·ÐÏÝÿv‹Ò×Gß¾ÖMÉÇ>MK™ˆÙkÝàKSFö´/?)ô#ò¾» µ ‘]yÚZƆ²¥7þ>2ƒˆ* 2´+²Èš{[-»° ¥d‰(ލ¡Ô/<®iSÈÅüLY°¨-""Å×L®îˆÄ^zæxïND(ÿö*ðw5ÂÿšP9ñò"==µ¥…ˆRtyüVBÈ~GiŒ¸o8rÔËà^¤èñL 9de‰üÚüˆœvÖL8~Ûƒìõ%×½w"{'©ŠSnœÈ¾ìR¿ñÂ/JŸv/nïf²ÿ°ü*ýÛNdÏŸèc4E©ïÜT<ò‘ë—AM»gù¥††Ð#Ç×ÎÅ—:#{ÙUÕ¿ ‘cÏÐq·oÈÚDj蛯²µXÉâ¯@D|Àûãgß#üwfîAw; >m™­.E½Ìj·_ÈnŒ¦øÂÝ“È&Ú…nýŽlò>?Z[¥èÿ¼rt‘ó") áΔ³"’©Ö³4Ë¿”xv’ÓEÖÏ„=Û„ì÷•éíL•@ÎS‡C_!²nfÁ´Ìäñü—H! réÈÉþØƒÜµŠ®5É["׫î¸Bò*r9¯¬èؤD©þϸ2„[ú«Ù^÷Ù¸·IÈhÄ!ÜÀ§ ¹Mˆ4|ò퉣˔:¨ëŒu"D;È^н…\¶l|y¾ô ¹H°ÞNþ€Hèƒæ”|uXU¡OZ9târÇiÉ%ÎèfÂYd«Tr Øk?²³—‰üCFBb®D]F]¡ºeÍÒÈyã-“ø^d—ý:$~šÒ'=,¼hI€ì>ñ¥žyLék‚tƒwSú»ŠØlæ Çˆ”ÿø$ÏŸyDÜsþåŸï‘ˆÐ“S¥ëô9x&‰ç°æ#—›ì#gÏ §ÏžÌä]_ÁÌ“µDnX¾\”GÈýÆëȸ1äž…ÿf 3ŒÈ¯N°¶É2!ÛŒ=º\Agñãödï_Ü¿x|ਠrØ*o¸³±‘ìßû&ЀìÚÌ„¬FvŒ|}~aAÈþËKNcÍ d}Á±éÝ­GH/õ¬cK0¥~”i[ÔbkGg_~š9û98Èzš‹ì™ä‡_.0!—MŽ“³‘CyE¡É‘X§†ß’)õÍò5ÒØI>D¾t¸/<9Jv²Î!ü¡÷ /-)ýˆõ€œ­"Øh>xd ²Ò¹ß¿2‘ˆjE¤å5“KÖ¡Ë”ü¶gþ‘áå`äºÜsd˜sR¿¿õôÖSä8¦±SRšr ?k¢Ü;Ã3 Ÿ´)ùò’ÌGì=Œkybs)¹ØÞeùáp ¹ÿȾ¯ôärWu~ꀼrÙ”šRê/ ?NUäÚØr¡gï&r£õžÒü¢HŸìï:D¹ïRc÷ ;Ø8µ÷+²?‘jêìåƒ ø7+/Í­žB§•äðcNmn"Ï”í3¼™ƒÚ{†ŽP꬈s}‡®7ìóÑXJ=sÚìë±x„Û¨¦9Tˆ¬KqZžþ£”|8Si¿dŠlÄêÒ»qˆØôRƒ©”9*_zC~Q†ÈŽqñ¹"{(õª„EwþGЧi¬&ŒƒâÁï¿5Òa<ÎèçgJž-ÞÓúrÂÛ-³ÅÀ ÂÙ¿K‘ËzAñÛO_•ü[‘Ùニ[{>#[5ñ¼í_’Ù‰ôÈžN{¿ùßMä|‘ÕS‡™€ÈZË¡þí”ûTÍÎÎ_9·f‘GÛ©Ú¡¹„ÎLöœ6DÄbÅWše‡MmFçdð#dC㸽q½ ÙI÷ ½3ñAÄÔ ï›D"‡ÚV<’0A¤&±ZÓ­Èá¤ð¢e³#²Ý_ûÃDZ%¢²føæýþð↥½ÈM¡ãËÃnJ½=¨me=Q„\Gy¹Ê홞Áð|e²ß|eFˆªBN§—û¤G#R½üã²—…ÈFQñ'Ÿ|rÙž2n±ô9fì1èÃ!ûBý}K©”¼w|ŸÆÍ©yJ½:}·•ù=rªþré ¥®U¬áý=0‰ìdŒ%\)vM²ýÊÜz9d˜Õ''ªRêч—¥ODSê ÏE9{‘ãÙ1²“Ž rñÒù %Ƈð.¸¿íY”{d.S«Bx/ÂOŸˆs<‰;ûw=ž¾ƒì2EÕý…i»ÞãqìS‘zµˆÈ£ÆÇ¯ôßGöÎ÷<é(ùc$÷º× ²wOEø]ÈNpÜâɽwˆ¸óŒÞad¿<Æul‘‡,.ŒDä„c;ÏßsA®:GÓ(ûÉ,²sw+"çØgøP–7”úÞ½‰tžŒˆ×£9s„‘½‚äØÝõJd·v¾)ª& n¸•¾Ûkƒˆ‡3:"»)ýš:í–S¡LˆÌn©Ì\õ9†.Fî "!ÇÂöÕ½¯žQâò Ñ.ö0rY¶89”ÊŠÈã/1!wËÓ;¾ wm…—‡Ûëù²’¨[ÈÍ*íÂÅœäqùz¨~¬9rݵr@J¹+·Ñ·WïDŽ\“)õ+AR\©ÙÙ.×&ñ¬\¦Ô³_+ltý½µw·#Û”{dJ¿@ú¼lÅŒ\ôŠò? Û7™o<­\}K¤¡²» Õn8N±Ÿƒ\ÉòÞWˆôþ‘@Ò1d­µuš^[ ‘ê8Í›.¥ÿÿþÇçô´ú2úÿúA“íwÀæŽÞ¨—,u˜‡Kv#0ù“¼‘—Ä;[d‰ç¢ÁHô†$mçnP¾aóÜoäFòV GAqý`ý¢Þ&h¤¿ßâ)r éÖq`ü½\¸:¼L”lNHw¾9¹ žwîù®Ø Ø?¾h æY88þ€y(Kq“#ÀÖŠ0±cŽ`*üTZ¨ÝŒGÓ®Š¿crû© ¥Ýáá¿¿nŒ"Aœœ­ 3;éÀùáÈð‰¿‚§œ ÞWç õþûRŽ!@ª}eɬ…o-¥]çÀJp]Õæ±Ø¸ÞyœðÏê6¬g'óóêFXmreœúó¼øUØ’[Ás½Êc*î=.|íå<) ¦ôh[d&hF«ösuD€0Ãé„]W@dSÀ(°;¤-™Ô#>=ö+\Ÿ“Al÷ÜÝ¿;ê@’ðú5+Û+L˜ Œ‘éÅÒ•@F°¸RÕ{¾5 œžœI®ùÊ¢ÇâÖ {@²3qnxK ˆ—Ö7¾à :Ý+v¶²?€X‘ðgsú<¸{ÆÅÞcKŸvgrYÔIpŸïøæú™RGL —À"<¨K:ì.(NÝÌ |]Rúœ]åÁÈ2Œ7drLè}[hîƒô.ö˜ÀxP[øËjŽ`0•y ¹¹ö^Êøøâ=s€øåïÔ’UØ}tz±-ò¸h·ä†+ŒùØï›n,Ù`ò€~û42“*;FÁ:wÕŽM%pŒU>j0NIÿGXÆ! LtZk0‚–Âò·7jG€oøÐ¢ƒHJø²ãËf@ÉÀ£äP\¨4l üŠ{ê¸Ëë‰æÏ᪯?çû“ ÿ'W€½dϨ¾55Ý¥·–ÒÖú/é´nÖ‚ò«Ö÷ï #AK¸Z:œ™¤ô ^ŒÇƒJAB¦.l:Æ:æêDÁ’Ïl›×íÐè8'Ô9vã ZµÞt@ô×$â=Á5&<„¡µ|ß>>gÉuü—=Fut=À‹ç!ßá½ÓàÒ€X÷%ôCЃSת®BÌÉiÂD8:/ö}*ÿ ’Óƒó¦¬kñ˜Drø¤cFט!p¿(ïeðMQ2µ½ ¡¶tŠŸ¼!,7£³ý>x´UŠx5g€-G|MOÖO =û…£ýk¸u¶˜Ãm`y(ÞxOÄv0 T“ÙÓ† "v<÷ÀÒ€1!È<HÒûöå®H‚›ŠýW+éŸ`ãcžbÁ¶øtV}FS p¹Åz— øñ£.U,2@Ò܃Ûe>ûŽå,…À?㯮½â¿ÏŽÒ¶lzàrY(çÎøZN(s‹^Ë’+½ùÓ¼àÞYÞ¾˜{< §Mœê~‚ÞëØéñøw`™Ãpñä›eÐkê,e<= ÊÌ+SqC`ê?õ)í}È}MK :wdʼnâö¯ÁÓ\较¥‡ÝÝÈ[K€[o)£ç®(‡K+a¤±Hèqõ?îf¾:öQpq+Ûª ö^AFŒiü`o\¶s›¿?¸å*Ó¾òóµ”§z‡”Á(ÍñÅF0þ¹ÝÁrGÈïÐ|6¸ò¤ž¸H§±E;\ѱ'@V¶kìä|ˆ^þøm¯`žécó`ÁÁeǮ݃4ýûŸ/+@k‡{#v¬<¬È4µ{€øc vu/ö6÷rœ[ž¢}ÆegÁÝûù†«)øÌÐmçå«…kÇbäëJÁ›£qÐîxòønQæ{ËÕl Ø6~¹°ÇƒéÚÆþ¯>#`¤7sçv XÜ‘|Û{Apr6ûof€•޶íÑm<Å:ì³” ×cœk®Ç¨ƒ­_k™çEŠ]K&‹­úoBÐÌø‹ÇãàsBü³óø:[©Ù³ƒGŒÜÙ}ŸÏBØÎ®gÛyJ cÌÖ˦{øð-‰³ÀÁfWöƒ¿§äeïÖS`åÿòõ6ÿG`â’>þàø!Ð áå0•Uïµoƒ)”|XSÓ¹c:.hÝdJAÙÍ»3BA-‡ø­d?µµ¬ÆÉ Ðûtñ½pÿ6 ›<Œ˜Œ·üö“Þõý«`õÈvjQ?lõ™DŒ’u™×KÒ ož"¤~ôØG>~tºú¥F×äå(©iL]O·å¢]]`Ÿ5x;9Ü|¤V–Á5³‰ëHµØîürFd¬Øs·8ìRtoŒ÷ÏRt›o`’øy ÇF ý}>ÁÖÇ“cÌóÀðr É{57Ì/ØÛùTGžÜ>Þ!6È{XWe”¶ãCžëÄN/ Ä~¬h®˜âΖИôB°N½ÍMñƒ¿üìK)ñ¡ú˜# ^ÊCÁ_§ûÎö­2Sq‚ÅÞnYâtY`ñ,ªf&¾L-É{)z‘_Om}* ²]kBÌ/úAgo³Hÿ§ mtDes¯'(ª µö¸Pò˜d‘¤ž{üª]ØIÉÛL<ÌÃÙAW£ÀçÜ«`ùT£«$,‡"?s_úÀ1ðbÈv!ÊÄ€CŒ±l½càß7îÐvjŒþêLô`výt_Ù}#Ð97¸Oë \‰«´ÝärÓΖD»pвy:©r¬v]gó+£ÄiÞ†pzª ˆwŠ˜¦? ¥SÙ5î ;™ÌtÕ:ôÁH2\‹’Ä¿[׳E!‘»S /[ÐüŸ f λX ädžÈ*¿sîÞ Zê·gú3ÇAKh*®ô'h¿I[ÜydÜse,óAŸé@ºGl:ÈXžUÈìÛ 2þû÷¦æAóÂOú8ÐN˜yñÉèuçÔ?=ÃHÉOÊ,í„ï MoƒÛöçÅÞ‹áes…`gZs‡ë‘ØþzðH{è:à;×b¶ï—hïF«%NögY~úB®)üÞSI_yV³Î@h³ˆsøC o_;8ýl\é9xfÛï‚׎Eb›à¦:ß4žM¥tã”ÊP×Q®J-ÃFa^° vbqw«ê¥îNºo \b`6iišfÓô`TµµN†6ð‘B“3ß@¿ÉaY˜rŽ£õ~픟q`+ÿFPýŸærúµÚp ²à4è6 ×ñ0 d#ò(S›Uÿ†Šƒ†`)QDôØ5}p`¨]¢t,5Ýõ7.íë¢ëƒ–¾:€—x›Þµ2†­úVÜ`²ýdóÑuPKnúë58â\_ùÿ¼ j) _ËŽ‚æÓûF¿žK–•õæJ¸šp ÌýpMcŸü„w:DF.oŒlWK±Þ7K³àwÔæÌF[X×OýX~ ¡ŸŠ*\½@ß{3^c=¨Ï×Hþ.MÕë‡xï¤X‚`s·,»=\žLËÍ?ì¢[öµþÒ‚Ëfœ•–ž ]6ç©ÞcvŸ™é=­cÓ$ pý*O7΀•ÆüêÅ•jˆßÁ~‚mˆÒ-Ž\=qœÔïÛ^ÎÛÇL~峃‰ŒÕrÈzкÛâè”3 ò¾®•]¼c )E'V#ð´>1®ZÝrõ¢¾"S  nµÃuŽ)ŒsÂÙ’Aº­ir‡˜*€ÜgÆlÖI¹wÏéÓ\ÚÏ&+舯ñêÑŽ=y»‚xî]P:Õt!s˜t—ÕÔ:Ä*ÁTj?½Gj=èôóßüž¯ ¦!Õ®¤ßQ`ðvöIì© }*š?à òršN\ÀDê*î­üâ×s& ùÚ¬ÌCÈ.ï‰{EÿH¤ß˜ ,~Kéèc1Ÿ͸¸[ã^è»?ò«ùþL%URÓt}ßxZ}NtY¿u¸çŽLI¤jw\¾ÉœQMÉûLš_šÊ-€´OìÑà:;˜Iä,[vI€JrÊì(-‰b¿®ýRÒ­ Ú}+ëµ®'hˆnÓý`¨,ì—êÞB_¼J*AÝ93ƒïªH8~0úý0T8í;¤5¬@Ò)²(¡.äžžôR~&*¼ÕyÒ@³j w0ä:ŽÇõ)ÿưóQ”ŒÏ½Ó÷åíÍC¤qY0ŽvÏÇÝU%é®Ë¬ª Ypˆ1Ô¾Þû¸Ëô%giu²¸Áµ‚sÁî ¥Î´·Ü— 6Ö-—Ó¹1½Þö…X糇•|¦rƒtüŒç°¶2‰Òl;³ô³e£ò€ëéÓ[r¦b\é(8O‰ª™Æô¬:Û[ÕXMqï»Îqä¼¶Xeô¯ ò\ ê©vr­? Äm_Ã¥ç% ”7nçúp£ï´]3€b!¥›Æ æ¿ßÐÿ)…ÔŸ+§¤¾Ïƒ[³Ä˜0—-XûNðY(€NSõ ×0$ˆ"U¹$X)}ßbŽÖ—6Оààî­ór NŒþ>Ã{zð™Û>pfÕ‚¿¯0 ‚ö»Sð5Œ«w2/_ ¤äƒìç™›`tÝóø<»7x=*´Üº£‚UÃæ¯<9Þ³Ðs” ÜÎìv/‹"ÍúÌ/]JÝ20²‰É?LøZÜ ÔkE•îÁ xP¥}§'XZ}÷‰NtËÖÆmH é-GÐ:ÉOÉ‹†qcC`RÞ2õ /ž…ÄÉ7qàºÑö^§86ï W}Û& o/sáŸy§ ËÏ)pÕ¢?±ãÖ ˜ŸÏ^\¥ˆJÉ'²›j½ °‹';ÏÉÇãy"5k¶¯|yRïo2?ï‹£L”>©ñûÀé%P¨(ÿ’ÂÊÕÏÔº7®‚ŒhK4œ: !œÉn¢ÿöþ¨ÊðÿEUBÀ@ÅÂl”TàCww7‹îîî¤KBB¤¥-”P ¤DQEå¬wýþ{Ÿ}ö½ûÌ9sï{ïŒÌ0žú>ß~¿Ïû0kAÍ’­‡¥8š[_s?ÚMú׋—¡7$’û†›ìßÂâƒwŸ?†–j:µØ˜HÏcY9BG9µmúîE˜Nïi˜šÈéå±Ù~°Úø¸f|ÏOX]ý1n!…¨™¼’ªôNÍ6ZíGTåÞB/ÞD}ºFqÖî·O3ÔjÂuæøïFa„®µ-£)…7 Ô«ßÃuŸ’N/ëQ8}ø=Ýû'{­"èÚ Ú—óYS¯Z‚væÙLÀæÄgwSOh†°¥¹ ­%í×Yõ†QI5 r uúç­›ö@*7Žªò š5ï$É™6^¶–åÌ&dûrL›…’`rÜî`Ð7(® ùÀpã3”†´jbCöÃâ{Ý”iÓZ„t?Œ ^ R-Û÷‡j‰ðxw)µãÅ{$W_Ì”v:¿(öµFZëa²¿Ìá¦Bw¤3 s]Et »M}À+Øj2œm†üÔ–îikHîblºÍƯ: UÌ|ׇ¶ò«Õb²Ivˆ¹~Òr€`×­2†‰óP>·3<sõꆥ+ýõóOp/ãÕ¹Ç+«=ʽ ÍÙP÷â'¢Ûµõ:À+›N.`²~Ìž—až+¨…hЛ±å—Ðk.ý®|y+5,Š/ü ïê6C>Z6ßO~~‘ä¥îM-Á¤¿¢ÃìÆ#¨^ýÖ~U÷7ís‰< ©[eÅh®@≔Lç%r]gñrôër4w^Q5b‡LWCXêרp†œxü êõ+´ !E8G5¿^Ï›gú´¼JxáÌÃìh¨Ùå¿+–ª)º&yÙ £š½¤°‘\· ¯*Qï€ñŽ„€Ü0m¾|—Éé´ &|&s 6{ä‡nÐW˜h<¿rú\5\¾Ž¦ÍÎÃ,èšaÆOhwÜ»?œ& ©äˆÎ½z yP/ýéx2]5”Ó=!rÿ{P+›#$2eùæDoBÝúOÚÑ:(ÊrZfZGBS¶Iç[;,‹/ÚÓž ³&7Þ-ù`7¶ë&ce'Ìê+/žŽÊÁ÷} ¯nÓAóÂQÒYrœÓ7èæ öÃljïÇC;¡•wlÔ‰³qWïXsüz˜è«ÛYB0©YüeL>¿Y}4v< ÷Ã'—ôËÉu¸èŠ@…¥L™…YÕ+B;´œ51· wBg;8!»vÓÆ_“³@Ú˜¯BmqWˆÓ3¸òù:PhóÝ\W9ŸèÛæy2FFæoú=Á›5“œùx+4Ö­-¥‚Z¢Ze¯š3<÷ø*dÝAWHÝk¥ß0Þ¶ãö¾{_áYgú*JTÁ?Žï[n9N®³˜ 8Ù`µüââÙ£vÐITÈq´;‘+—kÅž†ÿÏ[s%¯! ú§ê\` ÄNm{ÀãÂeÏßÙÖñÐf\öé¿ Ýç§}iÖGÁQdÑïÛKèü8–6øç8>$:Ål¼ ¾*®×ó]À÷$ïÚ¿dÄV_Jùß…¶>½³ñ™ hTìYmrf„µÂÔ/*‹¿ÐýÙ!¨¸&ì£dÝ…%ÕéÕ~˜ÚkŽ6ÃðgÅJžÿ8¶ˆŽ(ßú åõIùNÃÐÒs\¼þ‰òæ?j=Á¿Yõa#õ$«…Œ\ öIb}éîŸä8èÝwú¡dVvµýž> Cóêh̆ݣQ³Ëf¸GrƇoI‡ƒá×9ùò1X„yMóñ‚Q®œé×ÚÏÐY\¢>4èºsŽ›”Ÿß‰"¡ü|°¸º¯µÇ™—%é’Ò90šRÏzAý^7݃޲Án¿TPø„4,xow‰v‡êâ˜ûìê,Øc/½†œß)zÐ{çØ åÂäãyvP>æ·'ö¶$vV8 մ€¾e˵s pe^“4¢üVó ÷¤„àºÿÑrßwføI醙²°ó©b#Ø—: Üü‡ò¢) ø²Mý šAFß¾‹Q{‘­¸}Fé~"eSt¨ÚœR¾E™{ö*•¾û˧v™ÙN!üþÞsRˆr(ž ”Žƒ3W|kÊ“0[8vBn?œ¯[k¥Ùle}I|#ܬöü ì•…þOGU«[10{m‘;;27Ñæ+v¬…Ù™Šé„þkjìŽ4ïßl-^|B>]2Vkô‚㫟[ìaä^¬_Þ ÓS}Ö¼‰êÚÏçWPËýìš±œf´>Â{YæÎ$4ؘÂy¥Qw›7Ï@E È{ÝÄ3¨–Gò\ü «"%µÅñ‹ÐeÖK®zœæ6ùüè<â¯JS‡Çn)7 0P8ã&‰˜w ÿìCæ–…ñtr~J–½Â^±M¡c?gþôâgàÅ÷¼pe[ñ;+4fÖ…M#-p‰÷ÖOñ€æ¥Žñ–8èÊP=]>—S—ó«E |}'Ã#SzøK–ÆlS…ÏUz•mÊäúaLm¯æ!˜îœJ<½/ñ²ÂhLèò^ È€8ûÃcoï/BnÛésßK¡;:~uð• $dÖ:·ñÊ›0·iȈ ‡ü©q&}#õtÈ íS²øº þ_Úi» ªŸÑ½ õ˜[ç[í¡ïå0Ïtûô SÅ£ßÃb½cYê¾Ã0›é±«Ûo ½ÑCr­B ×?tL¬³éçÎUÁaÞDèÜÝ÷ðª>Ô[+ƒ`áFuѰ¿8P±lÄ ÒÔÕd¯M÷ ˜«(aà …AƒÃ"ù&0ŽuõýÜùîü?é_ç6B7וûÛø©˜ŠR Ôàýtl!ún ‚÷/×(r†ï}»£•xáôêM¦Æ;¸_Ϩ™ÜR²ík³G¿à6#vAs¼N_L]éƒ3§íw¼áðöÚJŸJüdkªv:9"âsUýíŸ,‰§f[vƒ¿Ol–s=\¹ânqŸ…)syb÷Y6Xè5÷Ž–†ÛEÁ£‚)#9qè@Ìs½MÒÍ&è/)Q}tƒóÃôÃnPuM¾â{s?Ì\ïÇê}áoÉ Ëm“Z^Âs²æ”³Õ ÄQI°©dEBG>ƒÑôOøªùÒö´À}s퀪\ŠyŸ ô9Ánºj¯¹sùœgµs3O8Ô^P9*|çO°H.¬„Bí¬‡ér‚+¤w<DÜEQ)‡é2ž„GÙCžö °÷*Úo± ó§tn‘°ëø`aRl …döE¥¾»0·Ôè9—þŽá·någÁ¡“'שv ¿|Õnô„¯Í­‹Rëáwq×tà×t8+³P~À ÷Y­!2íˆc™lð²vCÔÚ×B$îψ¸wœõãŸ4¸Ezåi4À†ewH½0Ìß s%뾃ž£~–þ%¤¨¨ÿ~ƒñy½¯GG­àœ¶r)™|~ Ñcl xëçwæ7E‚á4òëw³+LL˯[A­ôçóQÑ30sßÍ| Lî$–÷úÎä|W~Gø‘>ÂwÞ+‘Ôf@ìÊãG—‹á>¢9kݺf1çŒÔß0CmM·veø;8i׫ݵn»ÒM»€Hž½$2ºtë»CÊð}LÍþrço¸,s t˜Ý­”ÿ²êìCX4R'uu‚ó¯‘ÙS8Æèê*ÁÜçfÖx ùüÖ\w†zw«Ÿ÷͇·Øß›\Y«ˆ(ˆj°>/‹Ø‰‘MÎÃLð¢9ýK¶çL6=gýryN¯b3çÞÀ#wB–Çs?Œ5>Ç:HÇC#óæÑ×äzR?qLFý"3Ô7ºüÄ ÑëÓe–¿‚OàÕúFãÐ^Nô`I÷Vß´iX&8Û‘¶ÿé쯔ª…ÿ¯É?ü‡ÿðþÃøÿá?ü‡ÿðþÃøÿá?ü‡ÿðþÃøÿá?ü‡ÿðþÃøÿ hÆÎ½5þD8ÒÔ„Ö AO{ùÉÊðØ_û4¸ã¬8LŒ“ËX²¡fXut ýtólŸ‚ÙÏ%÷ÓÃâ§ú»Cx*l Vé‡×ý‰ÞôLx&Ú3<†8}ÓÓÈÕ¤S=œB]þ{a3H R•µrõJãßÌUÉßµO} ^Ûú2>*Ii¬÷?ÀdŸ÷õÅê‡p½wÉG}à7—…å4{®Ãî‹ñwÞ¸ ¶Tš‰Â¦?좯/Œ¥d~û>=ë÷f¥Ü«Ìþî.îÆ5©g-©W~ÃÊKõ ÃŒöb’¶U',™H©ñ‡rà[JúÌ’–>ghÓ5|6rZ|Z€Þ³~õÕwkàâ+%MÛÎ ·« §WXàaLðx2³ÏÞ}ûà W÷5k%Æ— ?Èy4èþ(Ô3 ùOò}C oÙåù1è}÷zò`’[§ZÎû¼„YµÐ©+'øàÊ’_ÍüÛ ¶›7]».acá¯)_nÃè¸Xí^™Bhÿ˜µLb­‡q‰/5랣Ð;zZ˪†ãÕ9Faç~ÍbŠ¿U>œ«z;î£s%w-a6^Âų£â /Ea?™»[„z v";VŽ>†ÆÊk»mûaÂ[øêÅqhky-x—sW?^oånX$oµ öL‡]Ò™È*'°PvÕtãÚ 3 +yŽ H¶…Úò >‚ÊÆwßÔÅZ!ækÂè`Öy¿ò½›ƒE µ1@¥EuzåBïâ:¿ƒôBò½î§9 q¶L}…çŸ\W¯‡Ï`w@]‚±ü t‡ØN•õ§EóleMÎ+(•mòî°{‰ë“©,Э6È®ån„3•é÷Âö«Ð¿eü5\l=œ9„2ÆÞ&ÂÊjBB(aNTT}ÓÕ´VÒ¹*Á .´o=âï‰)ú§ŽcœÚº[÷€Æ¤“ÙsMQ¨;n=Rsõ4_¿Œäž†DâTy~á](tXÞZóM²ãÏ̇z —™*áœÂ »Ckæ&ÜŒ #¬¼ÓI¹*—ßW…|Ž×Vv!hé? z´º'\G÷†@íÓ-ÆL~èO6|86Ôg§—,äçÞøÖôÆó0;•ºíw2¬À]w欳ÌÛçá$«Ð¡0[Óe£*ªgé-òѯ“®Ê[µ2õÔg°Ôøµ;R&îŠ6÷³ÕžÂõƒUiÖ\|þº7h¼Ÿ‡ß¾™¥‚¯0|áW5|ã¬Ø&vyÊôÁ9ËþMà"<;¯[—3Ã…“Þ+µŒD%9ËiŠI¹):sÚ»igx¤øá"ÞSQù÷)ÜGö~ƒ»Õtò–!+ØîZëzÏø<Üz9éYÕ§`e¬¥-ü >ìSì|·Äá˜VèÄýQ&ù ‡—í n"o±ÁfÊA!Þφ`¼¯7¹á‹ÌåïÍž=‡Õ ?/´ùêE_åØ@åÂñƒNË« ÙñGIÖ¬W.Wá­ í/72¾†UgIØutÜêê~ï±½ê^Wã ~„añÚÖVhê¾ð—K»óîÖ¿$¡=ð¬‰Þšb*“"µ[Sœäç‡ï¡äbSjX°Æšd¸AóWþÝ–ËÐå·2 U°Á`Ë_6÷È8˜vþ–ŸížOÝס|è{žùð÷ #L¦_ÚÛ‰Á*-#°kHAZš3÷Btaw¸lÄ*îté¢9$#ÀÓæ¸ç/˜íO{NíW îØ/Zp}Úüx×ÎïÐêÛa~X¢†o“ò6ôAK´´á°)´]êL‹Üù`??XgrJab̹å$¡êÛó;4ô-tn÷.ž<Æ 3®+õWçá좱±Lf ‚–~ò7ˆn…iyl½ÖIH0ß ¿? 7ܯ»ºó i?¹îÚ5uíÞ ,h+¨~ºÁšeñA€²tVÞKÿ ‡USas÷$<âÙú­?–ÂNC í:ÐÛ¶R«xs…,Ÿ¤€±4Cn%}WòúñmW Ètö]«¼¼å4<ìÜ>í‡úÓŒ~Õw åc½a•#n»Ý?Õx²Â#ß-wÝã^UØî݇–c7³ÂóôüЩø4rÄ{Â|¡ö‘ð¬‚O­kUßž“Î%T¾? ;©‚°Œ((%Ï ŸT†ŽýÊ=ªû&°¢ù±b; %¦ÐU¥z¸d d¯³Ž…Û×?”áòs„ÓÿÙ·Ó;¥9 ÀQâ¶iLìÙ·ßR‡‡­Îöã6bðu°^u¬€)§àùÑ–s°(iÊ3õšþýÞ¡°°Ë”b¿x VmÇ¢Ûæ7@W%ÿ#I†¹ŒGÂc ¶äò6ô ´ø,–éä`å\z(Mï„§7¿=ܲ”îíÐFØlûäÓTØ)úÛ¯;PÇb ïàmÙÖ«Ý’¥__w&\&µu¼wÁl¶0Øä]7¹>¼°ŸçÒwø®>s)øúÍ4³m<Ñymxvߎ ',pÀêÙ-£S:.¡ãÕÆàïÏãPÓë!}¾:1óÒi‡1¨þ}k­¿z ©IPë™\zAgRu±çlb¬GÏ-¯uº ß=·Ùo­«ƒópb§¦ýCXƒ¹U;ˉ ˜X»[ê¸êÂÈtSkOÍ_H\ö½õG†Ùç8FuYa¬”úWñœk¶£¡:flä/øÔÂêrh6ûæ°öXíšMå†÷…m£ÅûpþQùZÄî7´Üìig 9kcûR&¦ûËÓù7F‚¤ž'Û¿&M—,Ø«~ÁhhBgÃn ø>9þEÍÊzUÊ¡¹wa]xˆó$´tº]û7B[O±ùW½>HÍ¢¿hÀŠfꔘùGn¯h½ýb6å•7Ð’ó{Cþ7ô,ƒ^Ì- C‡ñ¬yd¨:ÌÞY ăê(+ÓiG)HêËWš:î‚¥Rü.÷?b0ežV~Úƒ­¡UÚ+°Ÿº½í©=,xGÇ]¯¡gÎUÉAp{v»‡u]8¼Ã׬>¡¶€™€ÓÙ]»’ ó&zµ÷W?DógYÍÖBÕ L‘U ²—¦Êã¨@ÃòúäòýýPLéY¾ò§¯zŠª”­+y£Íˆfþݿԅž=›“Hà¯f9s˜<¿\Â,ø¹–Û!™YŸÜQèçµ£\Û«h`•ÐüqNø,b¬þæmÙ ½ ¼Ýdajü¡åðØ:è³Ð$DH»Bì~±Pžy64Yiy ¯EÃüD³NóUC¸'ì “†í)·²°º>ØEjG1¨Ã¶a°£™i|^EÐÕ¶ÃdïÅГTÐO1ËÌš‡¥¦¯Œnª9Þbüúò),÷ú²»v&Ãò؃ÊÑÙdú¯G7Ã:ß“ûÊ.è>Z\±ún CæÔcC·Gah:¹^Tý ùù0¡Qß©²cß|Éz‹µ/·œ‡>ÃÙµNãôh* m†¥ËÀE©Gt°¿èz6 ¡:³Œž;©ÞÀNèæ{Ar';ÄÂÓä¦äÉþ?pF}° <Û46ø»ËAõ†Ã\:o$ìÞ_Ùórþlyn Ó Íý%Tâ 嬓V)²†Li¡ÙÍ;¿ yXƈŸ.Êu]ɬ–=ÐÍiÝ:7 Òí-'אָ‡É|„d·ê#xÚ‡²Ói쇓AŸèíˆK°Ývˆ·¹-ŽrwëúÉõvaÝSþpçÐòåÌX¬žᯔ…K:mÓ!ð5?=z¼q j›­ÛiaŸ1:ë¦ÌK±{ŸÆSf@roãûq¾×ÍuÂÌ€æ(Ûg=hØÜï&׫ªyÂZçÈu•ÿæÎáÞPx/Û¶ï$ø=b.x ãúËä+ TÒ^ˆî+…éÃcÎAõðŒ*.H‘f„]'œ­×Ԝ›D5îB£ŸñÖ¾!e¸S¶ÕÞÛOÎÓ§ƒ=ÿ,CkA«\ŸK Þú¥%•:ܰù|Øíœ2,ž½ö%íû =îY¥¹dx©&§’¢ÃáIM°×P€«ù‚ÀæÍ °½Ò¬Ù.!æs-ÏžÃ-c'Çr ¢ö+&:$ê«|½}ɽ°º{J0p Ò)ï¶õ©Ñe£ô"¿°ì÷Œ3eƒéôfÆ?û`w  (V¦2%6݆‰ÁóS¼¹Ð”õí*–[…Ñk–‡%—Y`°Ÿk5"ýH^–¸—@ÿÜ—íuÆ­0á­X3t3 ÖlÈÐkÚ1|Ïg*NÓ«C>{!³2Íꥇ~UPô inX< ’O5|nÞŸÆñÒkôRàó³ú^ñé”O½ìõ3‡UU á綉/®/jƒµÄ}…óz…пewûl1¬Tkðõ’`*çÈû&ò›Û·Ã”q]¥7(Üåíä7 '#éwªå¯© ظ»<^þÌšë¡—ö÷IN‚:Ì9ï‡|r: éൺë»`ê9娰]'£nmn’†á½Å32¡²æÊ>ꇂÐÑ®œ¿®v®êFÏçã5`ÏÉ6ÚTP 碀ï¿1“Ï«‹cZªkaqjéó³àÛÐÊãýÙ]J õŽ~í8Eˆ.‘N|Ò›‚Êg©Üî_«0^Št|÷²w$½€Ê)]ütPí~øö^ü®í,{³g*£Å·âƒOŸþhùä·ª/þ{™Çòž-}J®£>è>HÞYù¶ãÔ‡!‘v+:·Ø‰¬Ÿ6¹¶F^­?Àz÷Œýµ—ùFú`IM{R—Š\7Ò—¯MÓ€sû–È÷¡ÐÝ-·¸û@TŸÿáb—n€Ñà‘˜É¯³ð»¾ãç7r½àd}^±r× ØkõŒ´ÄÂÝZðÑá·*ð3ˆW9ÙîWéüzV¯ ›s½5“°ñÚLÍ›¾ºöç—ÎÞ*…_TÅáN°“ñ³ûö*ŽŠLtÞ]É0äÜß¶­† ²7õÂQ°»T¥ú&\¨¶ÖXNÃm´„Û*f—_=²¥ýƒàdѩԟM°âûöiBü[®mêIËiˬøè,2½<|Žw§hèã¢Ê¡qIMém]54¨–I´ÈçÈPo‰ '˜« ¯ %×íǼÛ÷³ Â3[|Â÷›,|¹iï5ƒmKÙÇSm°zÑBŸ¨ ó·+Ê<Ç=a6s)¥wþ1Œ‡mFOô݃ƒÍ_7íŒ~ØÙ¼Q×}Ó ³ŒèskßYsL–‰ö̸p¹sü¤¿D£s˜µóžB½%ÀpÕ«æ¥qߨ¨ÀÀÓ•Úv~˜¬»®Xj§¾ÚýŒ¯P¼•dlÍwF‚kMÇ,™aF»êQæ-·'gÜÒÇ% sÎê¬3´7º™“æ€jîOF˜vWf‹'×!ÆwºÊžÆBÏ/ûõeÍšµkÄß…¢óסдfäÑ:Î5†­¶!ß`×Ck &XH>b>¾6 N?çå#¢8`ÆÚG¯û¶ Ùß×5‡ÙpYÙèýhÿ¨ú{´Ìª×voxZKÁ~Ã䓯0M¾z'ºž®;ì†UÛ[ËUÿÏpÔ‘½ÏX⓪à ,äü`îáRrñ4©?&ʱC6P=ØðÝShÇ•þvÚh íÞîm%Y`eônF¸"¤%V¶Û!¾ yjqÏ6ñÀ²qCPKÕSØ3ˆt/7ˆÁ6CÝ‹Šê39?|²²'Aó$éÓ„H?ùÜýªšµ:Ëóåyü áÇš°íxä›bž‡‘ë¯öÕÏ¿ZBŒ*ȧ¿çmÎ,Ýž€¨ë†Žššœ—ÍüÒ7.Ó¶= -f?öÈ/Ë"|Ky¹kžCo¬èiIÿK8»RÇïê#Ÿ[ÙyåÖk‰Cýã¶êEUè 2q»Œ„Õëý+{¿Ý„剾?ª%¡¼R{Ë$|=Hç}í*…`{°\Níá1²=ËøXû¡>ž›W‡`MÛ¯ÅÇ8 { {ͽ °œ”Ø}¡÷Ê>Ú}-ñÑïÄW²?OFªÿô¯#ú™þÓO| <åãá©þëcàiMmLíÿ«µÛÍÅÕÃÁÒ“óüÿ딃¥»éÓx8Ú¸»­ùòiòêNöÿù4yªy4]›#·ú٢佺®e1í&·+H#½É˜f)–HŒËUä1·5ùêM2FÜ– %ú¨ëÉí®´çÃÝÁä¶^™d ¹¿Ë{G 1^B½ Z…Èþוy÷Æ b]êîѵ%¿ÍíüYsb^ž[(úþvƈàÏÄP¤hç/Î !èK†úú,²¾KøGhWWEo/•DáœzL´³ÛaL`Ý3Y‚î+³[ÿ•\'dˆ}+gvKó¯ø§?~CøÓŸÚ„½jªY«ù  úi#áw-üÄ~ z‹: ¢}ã€Ï,Áw]/C=ÑÎתÊ%è·»ó…Ð_ø ï,A‡Äms›à3Wj}-á÷ms®Äþ¡>úÜqÌ‚XWÆñæEO’›› º1­t:æ#M„Þßø(~Sž°çÅòë?ߤðûk[½ŽH<'æÕ2G “†^Ž Ä~/ä“ ºµ ,ÄxšŽà[‚¯d¥©½{O%í’J®‘d‚Nø‡ß”üzÄ‘àÓoFÞÂÇÍaŠ]:¦K ºÇtÆ > «E‡Èô»,øvGrzõ}”#æE¹tºÄL{‚‰vͯ,3BOE®ØOìw¥ê`üN2F®á¥Ä9¿Ûb^WŒŠŽ$Áw†t8%¿œ“Õ!Öe™‹ñí²ÃÑ ÞÁkàJÇÖEñëFç‚ïÔUJ>™0*#úS5 ©—ÈèÂþ…Ÿhç{<^CÌË©¡¯¦Ä+­d<¥ß¼r”ÐcŽýãPƒNî§øÏÏÉBß=oû‰þZñ‡ŠDÔFDºò§^øÅJÐ+¢®{AvD\õéy4ÁoëS÷DÊA3"~‹mËìÉØ\nû‡¿Î[–KøY{#k ÁÿÃiÅy"Î/éî!äkÚh@|ÓHWå¢l)±îÊù“Á„ý$Ãk9¾œÖÏÏPôôÕq'Aç†kìa‚Ÿj¡‘Ý„\·§c}– ýÒq0tЏ3s º†­Í”ø4z5A|g |ì6Ùx}¿ 9þ»";ùò¥æéq©~ϳÎvÄþWëTl­ ¹¢Ì ½»ŸKìw¥¶;’˜_Uví;‘gs·5?¡Ø=ÿå …¾BBÙ]ù<×T =V)il&ö©Ú@r"üÆPÓÂW­„Ý3ÂÎÉüÒkÎûD,ëˆþÌÕ¶«„Ÿ”¸maS!â-û!ïõJÿ>B®Ë'Íwünçk"ü”4bJ¡—Ÿ-*IÉ/Žk ~JYÞ¬¥øß|¥"A' \µšç´7Îr\=×MÈ•¢RDÉåÔ{Ï~[ØÿŽðƒš˜O¢¿Tò³<Å•²m úW[ôy¹= Û(ò«tvIMxNŒWн¦ø›K5£%1îrØùWüy¾j® |˜{ NSâSÄE _¥É÷˜¬@4o/DìiÈKyÞVí* øYŸ+Dì«ý€v‚b'-Wòº.Ÿ}OR‰ve½%{Õk†'è$esý^×+4 ÌÛ®w“à+ùã‰/½gŒ#ü0×¹»•ÐOaW¥NÈ99îKÈq±h‚–˜W$¥]EèéÊŠ™!gýùKCÄxŒ•Öb~¬ÞË|JœÆK’ŒO¯“'äôÜeIy®7¤Ï;|òì÷ Ú•VÝ\Äú ›à'{³)³ò^~àªMîïJ4f&ú‹ö›)è|ež"úDoòý k:UTÉù æð'Ês©„g6Áß5‹×DÜáÊÅrµ<òü¶ùŠ|B_E©¿ó®¯Ñ¼KèåŽýó„¼M¹)õ„|ô‡ŽtkêÅ¥;$èž‹%Ú~3z„ß]Éfò!è\ÁŽòº®8*ZBµñ¢ÂŽDÏì%ÊÀ.RÖ¯Fé}_Cño¿;„œ±lÂ/(ôoÝ%j·®øß;‰Nb]ØÖ sÄí)·ˆvˆ¨‚‘B©¯Pòz[ÿØU ¿MÉì=Ûˆ”:öf  Q7¢þÒ·×d;v¥Ð*üáꔌaǺçÔï(z¥¿ò†Ø/Óí{ ±.ýBÓ.ÂJÝôUù‹x^$z«&Ò ™?vr»+i4žŽÐóå÷Û(ú¬ÛÑÊNøidq"…Ï«ñ)ÉĺڃϽ$+ÝCôûdy´Ë†ç:%Ÿ•Ûi¥ñ^ÊixŠà'{”ÇŸ÷ÊëHÃ_d ¥{G™—á÷?n¢*Û(úÙ¿¥…X—q‘Ç–ðÛ°‹D»¬0:„rJÜúŽÐoé›î;ÿ±ÛÙxbüRéÑÎ=q>‰h§?’¡œKòŽ)uaiÙi6Âÿ3zž©qûÞ_5!ôîš_HœÍ`};ý71/õ/å9Õ^täOI>U› =רHûœÏ_ê1¯~]°a÷«–—ˆüÙe>IùÇlDÕ‰Úr•©gn âz<.’X_¾=in‚ˆ/éÀļRKySV¢~ê ò{—ßÂ[k‚nIÖOñAÂJ”ºÝmóƒFÛø<èˆz½è¡°¨!á_G~†z+’̼E¬«íÓw"âºöm¢*Ñ.ºOµ™Ð“ÿÅâï¬DýYßLô—ï0ê%ü'ʯ…àãúþW VnvÊÔª£Ìsn ä«ˆÓ¥‰ý/ÞÝñ÷2¡t‰uÞ¯Œ‰zåÒYÕAb<ßNÕ˜˜_(fyÐ˵‚oÛ?(Yo'GÐ|8Eœ ‘scÈšÐKãZJ~.Ꙉ"ôU±ûë_‚ÿŠg‹ô{Hõ'èúÒ1SΟ¥_~!üÑDužržMøiGØ;æòsqÂoëßé­rúÖéj~Ú@7åM¬ouý*±þZÕ½„|9I1„݌uÇ?¼hq‡‹ðïæ=} „Ÿ¾ÑÝKÌ÷›k½KèÝ0Zä#Áà€‚Á_Î úA‚¯ëMÛß|§½õºCÈStðñ>§+…ÇR‡–íZ ø¹rw¦•ˆßœ§”÷ %ó´½K×£ç :šóDèIÜ$¹8B¾Kl,ÄÁ 5eï(ÏÁ‚f›b"oe,œÍ#ôV*º…òžâÊo; Âui׈÷L¡BÓJý²“Ûl :aöÝDœt•¬ÜJÐæÖ§Ô•%S¿h ¾r×~>Nô_©°$ú ý@EÉ­)W§Þ“û³Â¸‰øÌã"ö˧l'â¡£óqN@¹ámÊs0õRÅÎ ü…¥¦ç¡.‡o\”÷Yn~fƒÄó?«÷±oäo”z¼üü=×íÅóö½BŠó$ö¯bóyFðS`qS _[–ˆ¯Ø-õ”úÙÖí/å¼ßyó&E›ø%äˆúìcŠh_}»‡8^no¡Ô5¡›Ÿ}%ìUúcRï7Ž¢¼?¸*ÜA©‡ªkORè^W¦m'öO[˜"¾9WÝÇ\ ¾ TÖSê¤è·NýÕœ7(ö3¹µ†è¯u/ä&Ö]–ìºBÈŸ¢U#J¡¯ó•R7–›° «1óÛõ_”ýÏO³õšß2Êû…ÒgÒí΄Þå‰:­ËÃàå%¢¿0bØ‚˜_2t™DðQ(cNøgŠáŸDÿµjzJœlZ­$ôuýÕ±Ÿ„Þ³dëÊ'NóêÞs+õm¶‘QÅoŒØx ÿPÜÆÕA¬g®¡§uYæ¿&Öçlw"ÖEÞ3T$ôç;¨·à§iKÇzbý®T{â9Ý%í2IÌo|O9¿ßhHó»Nœœýtù•±¼!äk¨ë'øoºŸÒ@¼‡ 8)›AáOZ˜8gt]•ôÞGN€ðå‰?@ìW0i¾Î™LÚ”/öØ‘ËÄü‹=gX`ð—x_ÛUøØ!‘à³¹ù€&Q?¿¹ïMŒ_vó&ô™za/5£{ˆýóï,qØæ™Iìsá«M+A'þÙ"Þ»ò2º/ùÌÅ'­’²ŸkEnù³Q‘º¯S¾zó¼'bFi³Ëî!ö) 3&ê²®’+úˆþ«œ«o‰þÚÛZDýSë°­“ðߢ…!/Bu;mUMˆ|t{˜’'J+Âí {æ$†^$ø¼¢ö½”à/ï½%%>[ƒ4æ5ˆ}n ä×úH¶ðdÂÞLEDýÚ•rÖ€r¯pùš åýT W2o—vÓü_ +!öÍÙ_hJÈéÎ~z'1¯ÎFa‘'J‚¨‹ˆýRöòÏ”]y•NðŸÅ[¬Lè7Çíˆ-a×;Ê{öÒÕ@&‚ÏxŽ&:!õD=ÜåiãO¼çs’8B9g§^¤çò$ètѳë²&¶QònÅÅ Êy´ðùyJœo©'øBƒM¾ A7‹öt*…„¨j¢?”Í¿–Àk§¹¶t|‡o/þqC—_–È3œO_㚬yý„¶²ÎúIXX&ä²ï¡ÔQ1ýëˆý Iâ#DñŲb^£îö&«odçRô»­0ЍËê£ù¨(òí9NŒ_y§°…h{d%õŠJèÖXûYøa‡‹ŸG;ºE¥_ Ÿû0}>K‘¯é7?¡Ïîð'íD½Ù¥ÛG¬»ž£K¼¬õßGÔ›ˆÝºŽ8Ÿue=:´HÈyµÄØð?~¶C‰2ÿlÇuw‚ž^!ñùi»hùuñB¥Kïe$¥^5¿`F¼ïëÊ4Ô($ð²FÙƒ¢fÄüÌs/%Dˆ<”GÜuIÑ¿§èíz·ÿ{ÂÎic4òļ”GK”óTEkÕvÂü¼SRˆ8«Z&òVW«²*Ѿ±®bP…ÐSå,;1¯¬?=‰ð[KV?Ê=LÝåí'ýäØ|Mc'òXlø1âù’ª¾™òþ¢àþ´2—B鸈ya=”üPøáÙ¥Ä{NǼÂ?’'šˆüñçz 1žó±’r?PLSº‘•ˆã ÊûïšÙBï ÷›ßXÚNð“ϹɖÈÇ…ézbD›¤Qê§”´J/b]ñõ—ÏöÙ¹`¼JÔs§q„ðÇ”\á×i#“¾D»¶Ùƒò¼3ìè&üâîÖ3¾Åf, ¿Lœ¦Üv hÖråÊ>¥ŒW®püº¼¦&îi?Xõš¢¦Álâü\§¶ý Aß÷ƒÅ8Ñ_õב¨S»ÒXôý(~¿ÍžR×ä$½$òn€¥N!=®¢Ø¯ŠÅ¦“÷ŽŽûg‚NqWQ!1¯äDT5ùÀ ÃÆ3”÷À×e¦ïOªeôé;F½·x.E襜‹–¢‡w¶3ûˆ¼7±O„ð·–Ž>eœ_ü—ćNú,ÈJ»Mðs¥Èqy¿.­€`J=~é‹ãi¢¿¦o~ˆÀVó~E"N«"Sî/ZŠ6jm!ì+ G览#±‹°{¸c²?1ž+Vr—#Àéó‚^tÌ0áÌfˆñÚ÷M”óy]–xFÁo»5¥ž)è§è'ud`‘Ï(6§äÊ· ”x_–$žˆŒ]f%úÓ¿Ÿ¨'ä»Z¥Eó•ÜnSúBè-ã Ã)r€»v-%.ïäÏ òÖ™™:v*KÏž$ìY”Î3²…ˆ¯ßM ú¡_æˆçF—ͽ3”ó\ˆ‰{)_RÎûÕ¾ÀAøKH<ñþ¡+››å A'…qk2E¿#Ûj—½-oýLì—z×{#ïí·6šç¡ú ±©D¼u™¥Ä3÷…þÞ,‚~ÕàÃdŠ¿9TPòôõÂc¶DK¾j¤G±S¶È Š}oÆï&ËÛ¥©[{xi&m‰º¾Õ³ºA]A3¡SŠú4 >– ílŸS °uæÖßMµ!½|ÉÈôÜIc‘Aqb{S–$´ÆªºO¶$AÛqèXʵ÷ãߟ°¬s"É3kS!XV×°ç´'Ô»m­%~Àª"éÏêäI¸{&ÄßfÊ€O›“syÌa¸O=oÿf ­,ѽú:s0Ž î‹¸™‰ËÙA/K!Ú¡õÞÉU º&œ¡c}Чñm^sWb[Xâ‚9 øú/ =š“uš:ìlÛÏe~€å‡Ó‰žÜ¹°úòwbδ¶G¢¿ÁE­9/Rú9œ÷ÿ¾ì¶1ú½4¯Ù_‰Á&ëbå›öÇ0ÏûhË$³õU»>(ÓÃLVëGD&3H£æÊg×CUzáÛ+Ž85À¼ÉÊ^"B¾,–åSÕö(eN(‡|ýº ¯fï dv~9Ùè)„}ý¾ëƒÔŸ γ,m8¦0o`° Ùy“Ì]éËÀýsê-«5{Ñòî]Q4Ty«Å"éé!¶«›ûL¢%äóIBâµQ°hÖ>SË“S† ^×ܾۡ;§c¶Ï¥Uk¼©aå¯beä ׸ÈPÚ–føÎ?:aÂv þ Õ5<àÅñàÔží“p©¿É¸#é>‚w힨FÜá81Òh$‚œÞÜûtõ;¢^‹LöÍ DÃø‘ /þx¦@ ÷ù9Ï«Ã7UºßÀú­£¨e>y#"ÑlJ}Ã]x´Vòy5eš5ñÚ쟰yòËŒê¯Ìꕘâö´Â„9Qo[ÔÉ<ßÖ Z¾[ŽÛ0Ñ^Ÿl”±;òEà&o÷ÕTì',|ŒR™æ`™Á¨µÞ@.W¸Â¯›åÀòù>—ªâpVÙf¶E>;öçÎíyŒ ?Ï_¼`‡ßg1k&Mø†žçɽñ¾&£rìü§aRz¡»`’îWÛÞä…Á³hRß±ö'4_ÆO>O| “\Ú3‡_-@³±£lýÑ1ÈÑ/VL$ôÃÀâSú»VH~MO>q‚V‚ïw.A{xs¯ õw˜xØÞо2³Áæò5ÏàÔcn1ÁÊoHw\ýáÇÞtª–å1ùÜÊ×)…ÃÎ+Xw}:ìôÊ73øûÃ-¯OŽê…7Œ–R‡5™å ›î0²kp=ô~n°7Ù” ©M*OúAtÈEôäsÈØšïz ‰Îg‡g‹Áþ÷íÜà>vÉc£Î;tnýû bL4ï~ŽW@õ5ûJüc˜z˜:¯©Ù«=IT·ƒ´½¾¤›õ¬9Šw蕇»÷7çK®ð™¢ÞÀyªûã¤jKeàÍÚÐgûGž¾kåÂÎäc©Ÿv¤•_.,‰0XZÙùÕgºš=¹7®—Âø†È|÷ii˜IZ< Su5ë} að™KAXœÓµ°8%Xûµ”{ž!Ûµt¬ÄôþeO=_küè9| ~vz¾Œ@^SE;ÆxÄIßñù8"6w>ÙÀQŠÌgÖ^] ðá žd:† !†vêÁßSä¼w˘ú¿dð}—Œç½˜¡ÁÇÉj0ùÞKßúRÉùðÚµŽMÛ Í|€Û¼Ñ²Á9M[3á˜kõ­tçM(.e§®…æ§3ïxï3ÀYÿAÔX¢-,7ö®»ÿ¦­'ÞhåÃZ‹ŽOï3ÔK—Å_ΉAÊ(UjoÝsh² ~øàxZeºR’äÔôLåæ`ðè{º-oé„]vOòõ”(¸Óúˆ.ö,À5«‘moµ¬7õ}9Æ·S–¼µŽ»ïÀ&¶;Îûg;‚eܦë™`#xÒEÙ¡6ŸŽÒFÁü@Jœ!w>tÎÙxÌé’Ñé@ëݰžMsàÈ»‡M}œ{”A—ÛÔ ‡aV^ Ũhª˜†Õææð¸Œ"˜§<~|콿üìÊÈñ¡ðˆkæ ¼8œÇî_Gï¿[*9º’$e²½Ý²©³aü$æÚTb Lœí·“õ"%¸œÖ2Ì ‰Î%ú‘ûPßÞÄwÿÓf¨éî•_Ýî %ž–;.ä<&R,â£) =_5¯7“ó6ý@Î#hmi8û9O&ÃÊ¥¹dùéïeôì‡mŽ‹•xìãô$ê¢`ùîûÛçö °U\ï¯DGð£÷ÊïêBýDßÕ_q!¡ÒzK°#$'L¬l#¡jÊ7<&¦[˜üÊÉqš¿Â›‘&ÁÎ >ƒŒ^Éɹæn ‰±:aó(hAW$R•œ¿—Ôì†á¾[öÐ’(lzh™CZ§-QIñ×Ãz!€„Ü[§û¼ë ªt}ê~Ös¨òL$”=<µW|éo6_€¸{žøY“hÑíÊðˆÏ€x Éqé\¨ç\¯_!ó¿a'ib*§w±zÒ$@-ivüÌÐ4»r놭'ç'¹m¤ïP£±0cøÃL¶÷›Èò™"Ø\»ÁöPÖ¿zªõ‡Á²c)®~ÃV¸Äz7˜ÎDˆÿÆ…á-ÈõüÞV˜„‹_9>æCxßYúÈpÞ°´{òI\iX9¦ÛnÁkÓ«V]˜Mt¼j8žÙ Z½ÔÊf(©ËUò¤sCU§Ác€S¦‘¼ŽÝ]`Z=×ÕAý r¥Ú†c&ÆP1ì a…nÕºZqªXòFóŒM}ƒV£ý/yój©?`-õŠ[id®y} K‚a®8$Ç= =Ú4êP¾iÁú02iM áÌe“̧ MZ•õ>f°ÀÍ6¡²e˜¨¸k­œÛóâ°>_uX Ígt.>‰vÖ¨);ô7üiÚ· Ŕƿ^}Ï!Èö•ë÷ÏóPL |ýµ|T†ïêþzÚ—lSóÕÅ\¸’Íhéï#@y‡Ô¨w¢£_ë­ 2ÀÕD ûÕÜ4üöY[i­€yÝÄž…a‡*®põ‚–÷j¢ò6;(Í^ù]– …0fΩ&ànºÃ.Áb‡ócéy{Á¿vGË/µ~œ7(Þ‚óÕUúÌjrÞ§SùÒxÕ6;ö-³ÀP(wÁ¤Sò)©Ó©lÈöëÜ)*Ö…®+Ù/5<¡Ì¿v;¡#Çë—æÞ ež¯¯½J+¡ä”•yJXBïu?H€üA»v1eSˆ8F'Õf@rHç°—ÜSèËsVŸáH‡JÕ3³Ý¡aÐyžÐ½÷ê'èa)îÿ)èxûLË—j«Ì=6Ï% ë^`vK ²bç´!]ÈÌõ&Š_oØb0çé7TêÙìp­8øÚú¹Î´³àÞ‘ óG& àÜQg=" ó–ˆÒÏkà\/–8å¹ æ¦ú1*­'a¶½Ð~þP‚+&:|Ø„Éç¾7¹ª_Z¡6ÊÊ>Ð]£«pæ}Ë»´¯ì8hà3³¡çØGm¸W~_ ã†ÚÛ#øÎ˜ ½êÍô ç‚Èù çiÖª1tÃ<̲xÃëa‘ɺM-Qˆ˜½0´ÞÓèŠÛG·c›ÜËaµfyê—¹néd £³…Ãû±@_ãKäz­¸rÔ=A»åÛ6{ÂÄdßÛOÔRи*½ôÜÂ*Þ’$ÕÃ\伨“ ô¬úW›'>Y AÛ³ÈjìU\Ö[ßîàƒCÓŽH…ùVè×ÏŸg³†ófnÑ?'àªJshÓ•>Ìyóf÷yØ<Èç|Mó“'bÇtý`Ó’>=òÈ WmžÓIo@¨;«¼ì%$^ž\ÎlŽ‹»Y?£žAÈF¿³v&ˆ¿žRôGz;‚‹£â˜¡¥$ûmôöT×SƤBdHbU±[g·p™I̲€5å@"GÔMð4©´-~yÑw—tè˜ù íçzæ1ùœÔð½çè¤+®~É å€\õÅ®aˆó7ÇâÈH‡Lq㇚%[Kq>4·¾0æ~´šô‡//)BoH$÷ 7Ù¿…Åï> -Õtj±1+žÇ ²þr„ŽrjÛôÝ‹0ÞÓ05‘ÓÊc³ý`µñqÍøžŸ°ºúcÜB" Q3y%Uéšm<´Ú¨Ê½…^¼ˆút6â¬/Ü9nŸf¨Õ„ëÌñß*Â]k[:GS o¨W¿‡ë>%^Ö£pú6ð;{ºöOöZEеAµ/糦^ ´6í̳™€Í‰Ïî&¦žÐ a9J;rZKÚ¯³ê !£’jäþêôÏ[7í5€TnUå4kÞI’3l¼l-Ë™MÈöå˜6 %Áä¸;ÝÁ oP\òáÆg( iÕĆì‡Å÷º)Ó¦µé~¼¤Z¶ïÕáñîRjÇ‹÷H®¾˜)ít~Qìk´ÖÃ.d™ÃM„îHg溊è@w›ú€W°Õe8Û& ù©-ÝÓÖ(ÜÅØ$tš 6&Œ_u@ª2˜ù®'måW«Ådÿ’ìsý¤åÁ®[e ç¡|xâÀ h¥¶™ìþ µ¥è…N›BHóík/édûìrœã$ÓV³3Ôæ¡$.3×”­Å¦µæe{¡~`-•£Ÿ$ ¥ø½‚ƒfŸ%ù9\¤-‚|ngx2æêÕ KWú êçŸà^Æ«s!VVz”{#@š;³¡îÅOD·këu-€W6\Àdü˜= .1  =Wx²H6sùç"¿%À÷¸5÷×ó3ð˜c/ yçG,ˬÉqÚ÷XCÎT–7·3ž¶‚ÅFïÎÒbò¹t$öʱíIð/»îu©ú ì~isŽ„)êΉ·ao»q‹:í¨š« úû†lO]IÞïô00Û<¸ÁÙ¤jl|P- ;Ñ 7cË/¡×\ú]ùòV8jX_8øÞÕm†|:0´l<¾Ÿüü"ÉKÝ3šZ‚IE‡ÙGP½ú­ýªîoÚçÿxR'¶ÊŠÑ\Ä)™ÎKäºÎâåè×å>hî¼¢jÄ™®†°Ô¯!Pá 9ñøAÔëWhBŠpŽj~½ž7 Î(ô0hy•ð™‡ÙÑP9²ËW,TStMòþ²AG5{Ia#¹n.^U¢Þã ¹`Ú|ù.“Ó3hLøLæ@möÈÝ ¯0Ñx~åô¹j¸|M›‡YÐ5ÃŒŸÐî¸w8MRÉ{õ4 ò ^úÓ-ðdºj(§{Bäþ÷ V6GHdÊò͉ބºÿôŸ´£uP”å´Ì´Ž„¦l“ηvX_:´§=fMn¼[òÿÀnl×MÆÊN˜ÕW^<•ƒïû^ݦƒæ…£þ¤³ä8§oÐÍì‡ÙÔÞ‡v.B+ïØ¨g),â®Þ±æøõ0ÑW·³„`6R³øË<˜|~³úhìxî‡O.é—“ëpÑ K ˜2= ³ªW„vh9kbn12î„ÎvpBví¦¿&g´1_…x^p})Õÿk…s;b"h¡bŸb\´^B÷ªFXåÁ«¹T'ßàѾ }Úâ®=¦gpåóu Ð6滹®r>Ñ·Íó:dŒŒÌßô{‚7k&9óñVh¬[[J3:µDµÊ^5gxîñ/TȺƒ®º×J¿a¼mÇí}÷¾Â³ÎôU”¨$‚ß·Ürœ\g1/p²ÁjùÅųGí “¨ãhw "W.׊=9 !þŸ·æJ^C@ôOÕ¹ÀˆÚö€Ç…Êž¿³'¬ã¡Í¸ìÓ%~ºÏOûÒ¬‚£È¢ß·—Ðùq,mðÏq(|HtŠÙx|U\®ç»€ïIÞµ~Ȉ­¾”ò¿ m}zgã3ШسÚäÌk…©_T¡û³CP!p-LØGÈ» KªÓ«ý0µ5Öm†áÏŠ•<ÿ=plQ¾õÊë-’ò†¡¥ç¸xý äÍÔz&‚³êÃFêH.2V ¹@í“ÄúÒÝ?ÉqлïôC;Ȭìjû=}†æ‡Uј »G£f–ÍpäŒß’ïsòåc°óšæÿâ£\9Ó¯µŸ¡³¸D}hÐuç7)!?¿EBùù`qu_ÿj39.KÒ%¥s`4¥žõ‚ú1¼nº-eƒÝ~© ð iXðßîíÕÅ1÷ÙÕY°Ç>(^z 9†?/Rô 80öαÊ…ÉÇóì |ÌoOìm9Hì¬pªi…}Ë–kçàʼ&iDù#¬æîI -Àuÿ£å¾ïÌ0ð;“Ò'0 3eaçSÅF°/u¸ù% åE#Rðe›ú4ƒŒ¾}£ö"[qûŒÒý Dʦ.èP µ18¥|‹2÷ìU*}÷—Oí2³-œBøý¼ç¤åP<(g®øÖ”'`¶pì„Ü6~8_·ÖJ³ÝÙÊú’øF¸YíùØ+ ýŸŽªV·b`öÚ"wvdn¢ÍW6ìX ³3Ó  ÿü×ÔØ3hÞ¿ÙZ¼ø„|ºd¬ÖèÇ=V?·ØÃȽX;¾¼¦§ú4¬yÕµžÏ¯ 6–ûÙ5c 8Íh}„!÷²ÌHh°1…óJ£î6ožŠ@‘÷º‰gP-6ä¹øVEJj‹ã¡Ë¬—\õ8 ÌmòùÐyÄ_•¦ÝRn> 8` pÆM1ï>þÙ9†Ì- ãéäü”,{…½b›8BÇ~Î2üé‡EÏÁ‹ïyáʶâwVh.̬ ›FZàï­ŸâÍ=Jã-qЕ¡zº|.§.=æW‹@øúN†G¦ôð—,9ئ Ÿ«ô*Û”ÉõØÚ^ÍC0Ý9•4xz^&âe…)ИÐå½qö‡ÇÞÞ_„ܶÓç¾—Bwtüêà+HȬu:2nã•7anÓ9.ø RãLúFêéÚ§dñu*ü¿ ´ÓvAU?£9zAê1·†O·ÚCßËažéö 覊G¿‡ÅzDzÔ}‡a6ÓcW·ßz£‡äZ„@®è˜Xg ::ÒÏ«‚ü‰Ð¹»ïáU}¨·V ÁÂ%Œê¢7`q bÙˆ¤©«É^›îA1WQÂ&À ƒ‡EòM`ëêû¹ó1ÜùÒ¿Îm„n®+÷·ñ)R1¥¨ÁûéØBôÝïÿ^®Qä ßûvG+ñÂéÕ›Lwp¿žQ3¹-¤dÛ×f~ÁmFì‚æx-œ¾<˜ºÒ!gNÛï>xÃáíµ•>•4øÉÖTítrDÄçªúÛ?YOÍ$¶ìŸØ,-æz¸rÅÝâ> SæòÄî³l°Ðkî9, ·‹‚GSFrâÐyÒºWˆÈ=yCB¶ ©ëã%ê$ÜžþÛˆéh²rLDëLbp1ÛøxB¢>ôY,ÓÁ1ú‚–ÈT5B^$ì±Ú{.‡¥Wĸuá,.-Ríã-Zó9kÉzž>Dðn?äõÏHÏÐ|€˜çz›¤›MÐ_R¢úè=æ‡é‡Ý êš|Å÷æ~˜¹ÞÕy˜7é]Yî€ôÍÆHšvšJÅ—;†k`xšËĺQxn 3_ í.©_…O.ÃØsü×ÜÚhñYñÅ/ÀèåO5»&x–Eô®%ç‹~ÿæP±\8­hßãTß ÿ4Ù!Ùpq•¿(2V8gá*Á ã×Z²¹»?ñ¼Ù­†œ@ÿø¥»šj[ëMS9 Ï´Ðûàö$äåßZâ…lQNź©L¨Ö˜ êÚ—@»¥F¤tƒ'\ôº$ØCAši×å>! •ŠÑ}ƒG`Ö“;m=Y “ˆž»!ÜЙep?ZF®ÓÕïßͼ •>sà 0¦î{‘_#­“Š¢‚ÍP¡}úÂß’–Û&ÿ´¼„çdÍ)g«ˆ£’<`SÉŠ„Ž|£éŸðUó¥íi;ûæÚU ¸ó>ès‚ÝtÕ^sçò9Ïjçfžp¨½< rTø"Ο`‘\X …ÚYÓåWHïx&ˆ¸‹¢RÓe< ޲‡<í`ïU´ßb%æOéÜ"#`×ñÁ¤Ø Éì‹J}wan©Ñs.ý%ÃoÝÊÏ.‚C'O®Sí8~øªÝè _;›[¥ÖÃïâ®éÀ¯épVf¡:ü€î²ZCdÚÇ2Ùàe톨µ¯…HÜŸqï8ëÇ?ip‹ôÊÓ6h€ Ë:îza˜¿æJÖ}=Gý,ýJ IQQÿüãóz_ŽZÁ9måR2ùü¢ÇØðÖ ÎïÌoŠ(Ãiä×ïfW>˜(˜–^·‚ZéÏ磢g`æ¾›ù@˜*ÜI:,ïõÉù®üŽð#}„ï¼W"©Í€Ø•Ç'Ž.Ã}DsÖºu#ÌbΩ¿a†ÚšníÊðwpÒ®?V»k Üv¥›v‘< zI"d:téÖw‡”áû˜šýåÎßpYæè0»[)ÿeÕÙ‡°h¤Nêê:ç-^#³!¦pŒ3ÐÔU‚¹Ïͬñòù­¹î õî>xî:ùF:Òáöµ»§!ìôýŸ ÑìðºfõtÓ¡n8>ûÜD*? ‹#Ë ÛYK ß¸ïWê ìX_§ÛÒ6¿ËR®üðäû;ÝÓ?“š•oRÅaù•'c—#Î~Ú%¨h>cÉŽI?ÈK–9ÎpƒO%;ŠÑ…‚Û7^S”…Ôñîö.š4ȧxïjõŠ!Ç?MËQk,}V?ï›o±¿7¹²VQÕ`}^±#›œ‡™àEsú—lÏ7˜lzÎúåòœ^;ÅfνGî„,ç~k|ŽuއFæÍ£¯Éõ¤~☌úEf¨o::tù‰)¢×§Ë,ŸÀ«õÇ¡½œèÀ2“$î­¾iÓ°Lp¶#mÿ ÒÙ_)T ÿûÆûøÿá?ü‡ÿðþÃøÿá?ü‡ÿðþÃøÿá?ü‡ÿðþÃøÿá?ü‡ÿðÿŸÐ(Œ{kü-ˆp¤© ­‚žöò“•á;°¿öipÇYq˜'—;±dCͰêè@ú5èæÙ.„?³;ŸKÅOõw †>ð:Tجүû3¼é™ðL´gxxð"ì·òЇþ†=µ4OR´0ôнBmâaÃÁmô~,†\Çê\¡?¹†åj"ÜsLäÒ»D`:﫽y„š‹eéòÞO¡½OŠGnútÌJrÚáZv^>þ»",åŠC_¾•„ûžËÔ¦-à=w-BòÓXXïyHõø4Ìþfv¤‡jÜBíðæð{ïpðµ¿5ÌìµRžß5…É61—!XÍÜQ8eûsû·1”†@£3ÆÖ4\¢ù™wbJÂøÐ Ü ¾K°u}8j Ë®hÙ¹`B§(!¬~Oü6ž¹¨ÇÚÞž›aTÀðûªT6ß°î>-fŽÜ¢ùI}1 /|±7'zï›ÃÉ☦̲¼—è£OjÀaOÞ.aij¸JeÖ/ë>†Cœ!~þh†îón½ð9ÀchQòjÉvï7òC7I¸{j¬¶ü}“‡;ßÃù©L\Õ½°:šÀh¡óawLÏÃ:6!q°ËÖ¤n>‚×Õó´àrHüÙ‰ñ*xçð%‹¬ƒa=•âìÎ^WVœØÁÉ'<ì‚«>Pìw㺦h ‰ÒŸm!Võv¡÷íÝO {õ Z‘ê?yBµ–ŠŠJö ¬d'Þd{Ëâ×CÖÂ0Õ«’ S‡eú¼¨iØFhŽ©¼pÎj_.ŸŒ,T«“}56 ÂE.N;6>Œ²‘›ÈóBkÖýíæ‡ö~ó³¢'óa©VszË6è¼JÐÙaPÓ/“yÿúAmeÈèZ»T:=èx› ó‰sÛwãThúæj~$·Î¼®g} qú¦!7¦«I7¦z8…ºü÷Âf:¤*kå ë•Æ¿7*˜ ª’¿kŸú&@5¼¶õe| T&’ÒXï€É>ïë‹Õázï’úÀo. Ëiö\‡Ýã%î¼pl©4…MØE'^_KÉü8ö}zÖïÍJ¹W!™ýÝ]ÜjRÏZR¯ü†yŠššrÿCxÛmÕ²‰:·<"[·-Â’±¹n¡ûħóâluÖßþœÈ«AF:™GE°¦·s,úFß…2ÂÜÙÉBûæ+hGݹèû^Ö?_z>>sV'ñx(wÔeé/&‚ÄæÃ;¨– S":2 !0·×ûV{x ø ú/ùz+C‰Ä¼ùk¢>, ?–f5öÃÑ6ÞéâÑ8Êפÿx ‘/½ 7ÁÛØA»!ßN/Rž 8ú×¹T@*2þÎß9¥ÀhfÍ—ÜK®È7gð¾Ñ)yÚŽ±Ù¨–-8.ó¦Ãã⑇°“j,Ë‚kà×óèSCÝÌ/0X,÷¦ÀúÏX ïwfW|”—ê†íÅ$m«NX2‘RãåÀ·0”ô™%$-}ÎЦk ùlä´ø´½gýê«ïÖÀÅWJš¶nWN¯°ÀØ4àñdfž½ûö‡®îkÖJŒ/AóhÐýQ¨gòŸäû†@Þ²Ëóc"Ð7úîõäÁ $·Nµœ÷y ³j¡SWNðÁ•%¿šù·l7oºv]ÂÆÃ_S¾Ü†Ñq±Ú½2…Ðþ1k™ÄZã_jÖ=G¡!vô´—9T Ç«sŒþÂÎ-üšÅ~«|8WõvÜGçJîZÂl$¼„‹!fGÅ^Š Â~2w·õìDv:¬} •×vÛö„·ðÕ‹ã6ÐÖòZ:ñ.æ®~¼ÞÊݰHÞjAí™»¤3‘U:O`¡ìªéƵfVòl µå|•ᄅ‹µBÌׄÑÁ¬ ò~å{7‹@jc€J‹ê*ôÊ…ÞÅu~é…ä{ÝOsâl™ú Ï?¹®^ŸÁcùè±*!ëO‹æÙÊšœWP*ÛäÝa÷6-Ö'SY [m]ËÝg*Óï…íW¡Ëøk¸Øz8seŒ½M„•Õ„„PÂ,œ¨©ú¦«!h­¤sU‚\hßzÄ=ÞSôOÇ08µu·>>îI'³çš¢PwÜz¤æêh¾~É= ‰Ä©òü»Pè°¼µæ›(dÇŸ ˜õ@/3UÂ9…v‡ÖÌM¸AFXy§“r!T/¿/®: ù¯­ìBÐÒ(ôh/tO¸*Žî Ú§[Œ™üПløpl¨ ÎN/% XÈϽñ­é?Œça2v*uÛïdX56ºî(<ÌYg™·ÏÃIV¡Ca¶¦ËFUTÏÒ!Zä£_']•·jeê©Ï`©ñkw¤L<Ümîg«=…ë«Ò¬¹>øüuoÐx?¿;|3K_aøÂ¯jøÆ3X±Mìò”éƒs–ý/šÀExv^·.g† '½ÿVj5‰Jþr–Ó„“rStæ ´wÓÎðHñÃE¼§¢òïS¸ìý0,w«éä-CV°ÝµÖõžñy¸õrÒ³ªOÁ*ÊXK[ø|اØùn‰Ã1­Ð‰û£&4Lò/ÛAÝDÞbƒÍ2”ƒB½Ÿ Áx_orØËß›={$«~_hóÕ‹¾Ê±Ë…ã;!œ–W:³â’¬5„Y!®\®þÂ[Ú;^8nd| «Î’°ê<è¸ÕÕýÞÿb{Õ;½®ÆAüÃâµ­­ÐÔ}á/—væÝ­IB{àY½5ÅT &Ej·¦8ÉÏßCÉŦ԰`5Épƒæ¯ü»-—¡Ëoe@ª`ƒÁ–¿lî‘q0íü-?Û=ž<º¯CùÐ÷<óáïF˜L¿´·3‚UZF`×:‚´4gî…èÂîpÙˆUÜèÒEsHF<€§ÍqÎ_40ÛŸö,œÚ®ܱ_&´àú´ùñ®ß¡Õ·Ãü°D ß&åmè7‚–hiÃaSh»Ô™¹óÁ~~°Îä” ÂÄ™sËIBÕ·çwhè[èÜî]Ic.h†Ü Jú®åõãÛ®éì»VyyËhxØ5¸}Úõ§ýªï@ËÇzÃ*GÜv»ªñd…G¾[îºÇ½4ª°=Ü»-Ç:>nf…çéù¡S9þñiäˆ÷„ùBí#áY ŸZת¾=&K¨|vRaQP0Jž>© û•{T÷M`3DócÅvJL¡«Jõ>pÉÈ^g ¶;¯(Ãåç§ÿ³0n§wJs€£ÄmÓ˜:سo¿¥8[íÇmÄàë `½êXSNÁó£-ç`QÒ”!gþê5 üû½Caa—)Å~ñ¬ÚŽE·Ío€®JþF’ s?Ž„Ç@mɇemèhñY,ÓÉ1ÀʹôPšÞ-Oo~yЖ šUÁ'éíy ²èôb® ô÷³ëý>‡ØäŠR søíÛ)gGB¨þžëõöÂq_ËÁÛ×/óåÇÖUÃX~îQZÞá˜ø'a.°³;i! ß —í«‡Øª{aÕheh0¿(æÙÑF8ÍÞµßÏ õÓß¾Ã,¸ºIÛ†œg^V,oøØ Ò>ÕÝ"q­p·H¾qèñv˜½96üèÔYx>ø“œ8« ûG‘•ƒ0U^9ýÒ@êS‡·< ‰`ÎLÃ{þư¸[wÙf|Ôú’>»¶CcUGË2ºö{¢Ú7K „ÁèTÖç%„¦P']? ¿/ÛÔå¶2ÀÉç Oó}z¸ d)ÝÛ¡°Ùöɧ©°Sô·_w Ž?Ä"ÞÁÛ²­W7º$K¾¾îL¸Lj êxï‚Ùla°É»nr}xa?Ï¥ïð]}çRð?ôšifÚx¢óÚðì¾NXà€Õ³[F9¦t0\>BÇ«ÝYÁߟÆ¡¦×Cú|ubæ¥Ó.cPýû<ÖZ=ô2R“ Ö3¹ô‚ΤêbÏÙÄ*Xž[^ët¾{n³ßZWçáÄNMû‡°x’DßÅ¡iiâÝ™…0û]n{Šƒ²ΩIòÂ0Ï—â©~®½×M‰ýºð㙚¾Gs IªR’p;74¬zL®m—‚²w”î­Çžrþf‘p˜®ƒ×hëìAxôÇ­8ÌèÂ?©ÑÚ”\ï™ÌÚ™1UhÁúk‹÷«ô/ð¹bíu±¾Q¾á³“ðl¾0›çkWî;ŒQ°0q+]ž÷„WÓ˜«=C'H{Œ–XKCo:‹óŽ?7$Â5½Nß|sªv–0±v·ÔqÕ…‘é¦Öžš¿¸ì{-ê$ ³ÏqŒê²Â>X)õ¯â38×lGCu$ÌØÈ_ð©…ÕåÐlöÍ7`í±Ú5›Ê ï ÚF‹÷á(ü£òµˆÜoh¹ÙÓÎ@sÖÆö¥L$L÷—§óoŒI=O8¶/Lš.Y°Wý‚ÑЄΆÝð}rü‹š• ô8ª”CsïÂ(>ºðçIhét»öo„¶žbó¯z}šE;ЀÍÔ)1ó0Ü^ÑzûÅ,lÊ+o %ç1ö†ünèY½˜[†ãYóÈPu˜½³4ˆ;ÕQV¦ÓŽRÔ—¯4uÜK¥ø]îÄ`Ê<7¬ü´[C« ´W`?5t{ÛS{XðŽŽ»$^CÏœ«’ƒàöìvëºpx‡¯Y}Bm3§³»v%AæMôjï¯~ˆçÏ²š­…ªA˜„#«d/M•ÇQ?€†åõÉåûû¡˜Ò³."|äO_õU1„)[WòF›7;Íü»© ={7'‘À_Í4ræ0 xþ~5¸„Yðr ,·C2³>¹£ÐÎkG¹¶WÑÀ*¡ùãœð1XÄXýÍÛ²zxÿº ÈÂÔøCËá±uÐg¡Iˆv…Øýb¡<ólh²Òò^‹†ù‰f櫆pOØ"6& ÛSneau}°‹ÔŽb*P‡mÃ`G3Ó&ø¼Š¡«m‡ÉÞ-Š¡'© Ÿb–™;4KM_ÝT!r½ÅøõåSXîõewíL†å±•£³Éô^Žn†u¾'÷•]Ð}´¸bõ݆̩džnÂÐtr½¨úòó9`B£¾ ReǾ/ø’õk_n9}†³kÆé!;-ÐT@Ú K—‹Rè`Ñõl@B tf=wR½Ð;ÍyÖPØì‰jÿÂA‚vöèÓ¡{šp×–­{à ‹Ì^ÙŠwäsŠøX=ï%3˜ÉÌÅ÷vëA•þ§ðäÌY(©¼öwBÒÍ’2+üPUâ]ûçŒòûCžB±u­ú¦H¨*è?N‰x…us »à 遲îw7¶7¼C G>Žâg>Pù0·Ê¡úŠš#L!\ÛAbáäeîq„g÷–V˜7SÉág…Íé5]Ï`ãìSätG–{DT!ò[êV-Fíé,žÖBOâãDÙ‰~˜TíꛀÑב4úØø³[jðBãq«pôb Ü•ôê#ÔUaöKÀnÑ„¤@÷¥òÝaä¸N­°ÚQI¯»•«+þ0MëU{ã*¥À®K'=¶B›‰ißáPaZÃË£eÙ”âS“3pH?â¸nçGH’$î®q„Ñ×Ûœ1×…`á[~I¬Øº;«.øFÂúR OÂý70ÐO*“fóá@ß|+NXé²­“åx ç÷¸Y²ayÇ1On© Z[é<¿¥¼†^rBuy‰.Ô³ÇW\¶ì†ã;®ýÚjGàbõCçÇ l"}·‡±ØÂñXþù4.;x“h?§Ëo† ûaãŒ×—àpçŒç‘‹á0‰;yéþÞëPnõáVéö©GóIQö]xö ˜yy @Eq²UVĪ".ÅS¼ðhY´¦®K†éÞÖ/`6YS»Y€ŽsÉ-®‘†°ÖÚóTŒijÓºA÷Šæ¡,{Õb¼´Ž|~×üô.ŸœºÇ÷fNF‘ÏÅSœº¥Ï`"½ÿOIÏ[hûæl#c®D®]mq0Ïž¸[Í4ü¬~{†nüü• 2-ânv¸ûXÓ_«ü‚ 5 ’{•—1ñ¶,Ãçnœ¼CsÄ–#Îé8FBóËÌBÆv˜³•si”„ãÔۃ˦=SMþ¤©`ïSEÔé¡1d+_:µ‘ÛF®ba4ÉÉüÐa-Lëb´ žsÁ«\DÛ¶Ó®G{g¶ý™©‘Ÿ[ƒz N’2¶ýJ/à&.¶¡- ¶Õ‡ا `y¨óP,wøo ç9ú ™)P嬓j—…í[…h®‹MÐ>~ïóøÀn¨Ÿ9¼£ÉLš8ìlh³â®%õŸY¹”eýÈåbøÝeb¾,ôÎÇé.¼#ç]µ>q—[Ž"©A¿Üh„îÛ¸‡ûK¬áð°W®»Wæ§ìÿ îg…¶’ï\¹.<¾¼JPØs–¬Kq¿¦ß@•×çéûs3àžmϰ 6…XSׯ؇40üœc°y®¤á×§Âáì$õ‘s{úÇãƒ7ÃÀ²©ñàÀ7¸žÿ`í*̃«3·ÿY€ÉžcVV¯ ` ÒEu§Ô/&F¤6½ƒÆ5åŽÁëᱚç1îe€L°ÊӕסÄò¸Ü96 R µYŸnÃàÎqµñƒÝhÞÀvý:„8’-r o8¾m¡2fvöÖÛ¹ ]}ö‚äNvˆ…§ÉMÉ“ýàŒú`A#x¶ilðw—ƒê ‡¹tÞHØ%¼¿²çå,üÙòxìá÷ȩ́¾úGpà=™— ’jÛ5.ï X%ùóXÞƒâüÛ7²1½Pìuý¦9(u q ΄0ýZã{÷!õ¾á{©d¨ž!½cŽƒ"Ý¥+nE‚ШöÌùÙZá›eƒ d Î÷S¾ -в“ób “€ÄÆC)²äúoÁ÷`mc< %Ί€Ç½¬óB:ºpÒJý¸@ Ë5§UvÆÁDmµÃ Q Ùᕃ‡ê¡ÿ÷ªã©ó6p6–<+]û5®ý²>ÐÛ!fw– gæƒ}k¡;0i5¼\u³& éc_ ¾FD¬¥þ„F²Š›B¢¯JCœí$¤Ò.Ò».AÉ] ´Ž§÷WÚw¨’óŽÎú ™÷iá˜õrÝîÏËpÛç­t¬µfÅG».ùLÂèfÞ‡f.ˆ'\½Àµáj§=å^PŸ®‘û õ™9ú NÐm³¾a/ËJJßm`X|Q>E*‡©…ØFAÚÙVzà¹Î~®×•a*»MÙÊgÀ¾(íS;…²­7…ÞÝÆüÝν .ÞxëÕl,™ÃÏ5¦À:ýææôÍp\ÕZspà.Hq¿/$õ‰Ârb³aE¨6l¸OgìWiþãµíÅÃ$gŽò–ë‚Íž™Ž¾0°•È¢«ƒAÎÓ‚®{× £OÛ/Ñd£7[~ ˆß‚þíý¢±¤LhÛ~¨|ܦšûK¨ÄAÊY'­Rd ™ÒB³›w~Aò°Œ?]0”뺒Y-{ ›Óº/tn¤Û[NÞY_“ùÉnÕGð´e§ÓØ'ƒ>ÑÛ—`»íos[2å îÖõ ’ëíº§üáÎÿ åË™?°X==Â_) —tÚ¦Bàk~zôxã:Ô 6[·ÓÂ>ctÖM™–b÷>§Ì€äÞÇ÷ã |¯›ë, „™ÍQ¶Ïzа¹#ÞM®WUó„µ$Αë*ÿÍ'½¡<ð^¶mßIð{Ä&\ ñ@Æõ—ÉV¨¤¼ÝW Ӈǜƒ"êáU\"Í»Nþ8[¯1¨9…7‰jÜ…F?ã­}CÊ q§l«½·Ÿœ§O{þY†Ö‚V¹>—¼õKK*u¸a9òù°Û9eX<{íKÚ÷z ܳJsÉðRMN%E‡Ã“š$`¯¡WóÍ›`%z¥ÿX³\BÌçZž=‡[ÆNŽ'ä:@EíWLtHÔWùzû’{a9t÷”`à¤SÞm=êS£ËFéEaÙ3îgÊÓé-ÌŒöÁ4î@AP¬Le.Jlº ƒç§"xs¡)ëÛU,· £×,K.³À`?×jDú9>¼,q/)€þ¹/ÛëŒ[aÂ[±fèf¬Ùx~ 5xÂIÍGÚö ù|¡×´cø&,žÏTœ¦W‡|öBfešÔKýª éAÒܰx$ŸkøÜ¼ >ã¥×è¥Àçgõ½âÓ5(ŸzÙëg«ª@ÃÏ m_\_Ôk‰û çõ ¡ËîöÙb.X©×àë%ÁT(>Α÷7Lä79¶%n‡)ãºJoQ¸ËÛÉoNFÒïTË_SA°qwy¼ü™: þ 4×C/íu˜sÞùätÒÁ?ju×wÁÔsÊQa»",NFÝÚÜ$ Ã#z‹gdþBeÍ•}Ô¡£]9]í(\ÕžÏÇkÀž“m´© ÎEßc&ŸWÇ´T×ÂâÔÒçgÁ·¡•Çû³»”êýÚq‹]"ø¤7•ÏR¹Ý¿Va¼éøîe9 88îHz•Sº†yè Úýðí½ø#0\ÛYöfÏ0TF‹oÅŸ?ýÑòÉo=T;_ü÷2?Žå<[ú”\G}Ð}¼9 ²òmÇ©C"íVtn±Y?mrmŒ ½Z€õî)ûk/óôÁ’šö¤.¹n¤/_›¦çö-‘ïC¡»[nq÷4¨>ÿÃÅ.Ý£Á#1“_gáw}ÇÏoäzÁÉú¼bå®°×êiˆ…»µà£ÃoUàg„¯r²Ý¯Òøõ¬^A7çzk&aãµ™š7}/tíÏ/½U ¾¨ŠÃ;`'ãg÷íU™è¼»’a(ȹ¿m[  d?nê…£`w©JõM¸Pm1¬±œ†Ûh ·UÌ.¿zdKûÁÉ¢S©?›`Å÷íÓ„ ø%¶\ÛÔ“–Ó–YñÐYdzyø9îNÑÐÇE•Cã’šÒÛºjhP-“h7Ï‘¡ÞAN:0ÿV^J®Ûy·ïg„g¶ø„ï7Yø(rÓÞkÛ(–²§Ú`õ$¢…>QæoW”yŽ{ÂlæRJïücÛŒžè»›¿nÚý°³y£®û¦fÑçÖ¾³æ˜,í™qárçøI/ˆFç0kç=…zK€áªW'ÌKã¿QQÿ¦+µíü0Yw?\±ÔN}µ)ú_¡x+ÉØšï"ŒךŽY2ÃŒvÕ£Ì[nOθ¥K@/æœÕY%fhot;3'ÍÕÜ=žŒ0í®<ÌO®CŒït•=…ž_öëË0š5k׈¿ E æ¯+B;¡iÍÈ£uœ j [mC¾Á®)†ÖL°|Ä||mœ~ÎËGDqÀŒµ^÷m,²¿¯k.<³á²²Ñû=ÐþQõ÷h™T¯íÞð´2 –‚ý†É'a"š|õNt=/\w Ø «¶·–«þŸá¨#{Ÿ±Ä&UÁ7XÈùÁÜÃ¥äâ hR L”c‡l z°á»§ÐŽ+ýí´ÑÚ½ÝÛ>J²ÀÊèÝŒpE*HK¬l·C|AòÔâžmâeㆠ–ª§°gé^nƒm†ºÕgr~ødeO‚æIÒ§ ‘~ò¹ûU5kt–çËóøAÃ5aÛñ È7Å<#×_í«žµ„UO…=ÎÛœYº=#Q× 5598/›+ø¥o\¦m{ZÌ ì‘_–Eø–<òr×<‡ÞXÑÓ’þ—pv¥ŽßÕG>·²óʭׇúÇmÕ‹ªÐdâvÿ «×ûWö~» Ë|TKBy¥ö–IøzÎûÚU +Àö`¹œÚÃcd?{–ñ± öC}<7¯Áš¶_‹q.ööš{`9)±ûBï•ÿÅGËSýŸ|´<Õû²wSGSûÿjívsquçp°ôä<ÿßÿ:å`énú_ã4Ž6înÿïýzâwÓØ¥¢ý_¬YOrruð°7ýÏ0 1üç?KiWÿ#ÙúÿB KkÿÛü×›(¤þó»ù¿ð`‘î¿mGõ?o÷Ÿ&•#Éþ¿ÿioÿ?ðLóÿÏô«ÿÅÁÓºÿù¿"þwk_ÛºFôž÷?üü·yÿ%ãÿA&šÿ 2¹þÿï½îÿƒ¤´ÿ·$eXý?Júß§þ7úïb¯ýŸÄ]û_¢þ&û÷¢³2õps³1uü_÷ÿħý¿'¾ëŸ–dê`cïó_-F'W+GSûSÿÕýß¿=jþ¦µ¿^ö[ÁÛ7Ý&ÏÏMFÊÝtÖüߨ{ø(Šÿÿoïn¯QBïz“–KBÕ½zïM%\’Kr)wÇ%¡«¨HG¤H¤I¯Ò‘z*H)‚¥Ãÿ5w»—ÝÍ…ÈG?Ÿïç÷ÿ$†ÝÙÛ©Ïiï÷ÌL=Ì6)NâÆýò¸Ï‘'$ñЃ­?ý²Ÿ¸F„µ+ü¤|vlyêÕ§Än>²iùŒæ$¡]¥Ðy'‘˜vC÷r®c$zÙ{gG6_Gb'oöàÂhÒ«ZZõF÷ò‘ØæF®|2…8ÍMÉú÷¦‘¶Iú®†;IÒoíJ<ƒ¤üù¼èNÝP›JÖ °Ç“¤ÞÝU|Y8öt¸ÕÌl&Îãy.Ÿ>x†ØgD¬låØÍCIÚÉ-)ß¼¬Eœ].<½¿I¨]·ºþE’à(´äö°«Ä‘öÁµš—ƒHòö¿úÁ@ÖÕ¸þòÙlâ¬Y¦ú[]›’¤ãÞ‹ºŸ¸ÞäjþR†8íëd8BR¬ü@5=™8øn_†ï~—8 ùlP®ˆ»ïÆUѸ>hòÝk]Ißz=†ì-Qžôý©Äf¾û<â:ª;2#f-I~殺÷xYâL/³Õ²¿qÝë6š Nì¿uèþ/$ÖÓx×îyçÆ ±ï?#ñge½ƒ|ãŽïo–ؑؿJ÷çòIbÅÓñÎÅk‰ÃpóŠ“Îw©âA—v!®c†7¿:$0pÝ…æ$&ééå­#“˜¯×éI¢ká¢E-öÇ8ýïS§m%öR–ºÚµûyÞYmNE~OOŸ×$Ÿ*Ôvó$iöì´£+íÄù¨S«Ü»=$¡úòJ³ËÏÖ ¾gW‡A¿Uî$”vãE?qöØ[çå%$áÆ±13bG’´t~Bèæ"ÄU¨Û?gIâ¾VÏÜ»"Hü¨Æg[ÛÐëõnŒü’Ä ï:²Õ¬HÓ}ÚŒþ5 ’ø·ŸÎxR‘ÄŒ¯0¦}ÝÂÄš^³Ýo†oHÒûgÚž×’¤µµaPø5â.78ùÈ Ô/ßåi¼Ëº‘؇L;ºqÔ§¤Ï¢ù× žkA¬]û]*øÇi’4/ï½Æ%.’øøÆG‡Ý )ªq],Lâ÷ç]y¡Lyb_ÝyLÞï’èªáGÆM)M2o=:Ù$h§¥õþæ9I>_Rå²ÍH\ë[Ï:GœÝ6UéÑ0ŠÄ#æ~Sâ8I<¢ÚQ¸ocÛïÅoÏæ $)_ºÎµZzЏšXõÙ¥Ä:D³Ss·?IŒÖÕi"©Ý§õšø¨$I>ô§zçÂû©É9tóF’0ÿìyC®C$9B_)$ÿb°åVÜ¢‰«Òž–¦ßê£ü 05´>IšôsgoçC÷Ö+O¶’¸Á¹>-Ör‰®4ù«ugb{|pÐÖ÷“ÄÞªÚ¹æH¿}´ùؼ1$njß‹ºë·‰]_ªb¯µ÷ˆK.×7aCˆ½îÚããßYC’ª’çë^ʼn­ ÓkbH’زŸáÜn øý"ζÄ>¹÷¶=Iâ½-ÓÔ±wHß_ß]㳸,– ]KÜÇ{ }ð¬ q78yvÊÐpÒ÷3W&¾J–‚ïä-º~]7mGQÒ{èùEçßkO¢?ùÈùëпèÃ]•:GR®õ"õïF’äÅOò ´ß$®ÐáÅ»ÿl'öëæŽãI¹ß´x½©'HÜWûô ¯ß'É_„.*=çâ»Ô=§öDb_Ë P…Ä(å¨pdé³¢Û¾¯V^#qcã?XDOâkm:ßcÉ"g;‘t|ãQâìµxâg³›ä§Õ#’tL™¶«é›tNÕoøD’té«?Ÿ-ÍCâ ^[ͬkMúŽûzíÑÄuêО3|AÒ÷óç×Û-8H\ƒ®¿óÎŽOHJе?µùퟪÆÉ\(GÃ뼑úU ‰ J¿ðvXc’¼©G­­¿“ä=ªi+[Hü-A•F§˜]?úŒ$’¸£‡nÚûŒ$æž1oùl†¸Ç«~m%q%|ðKá›$±aIºzŠØ¾Ýõóš¾OHlëó ç!1ñÓÎ=õ"é](—æÝö}ˆýík­óÚ\$¡âóÜý?'¶®R Óèo-RÏÌEâZ}oéG6’Rfp¼Ç’Pê·†_&ŽÍOfµÞó;‰›`›Ør8Cbr-|[½èÓZuçw‰íJáß&ñ ckDìº%äîÒ»û¯Oi¾“ÄWîßö-óâX’œ8øêâš­iÞ ËgÄ5o䲈“÷IÊɼöýŸ:ÁÛLÍØÆhO–UÞwéïÄeèÚ'oÈ<â|§Äò¹ÚT]ë”nó’ÔˆûÏÊLú–¸_–yóƶ#ĵ­ø¶Ö­>! kkNþp/I¹ÒêãÏ‘ÔO*Þ*Ò©-Ü­ÜéüÌH\µv4~«Â»$i÷Â/úk½95'LyI l˜Ï\@Žž}{®ÕŽî$nhÃ}%\ýHìÂuê7Ÿ‡?/†îþ©&Ê'·r?"ÉIï×l5ƒ8V­þòv%‰uí­6¾šDýx§pÈ—ˆãÀ¶ÒÖ?#Sԙå¯ÄïÃÊþò ‰_<±îû›K‘è-µt[:Š$±šM|zâþ)¾BáB㉫aî\Á¦sÄÕ`Xùš{>'Ée kòO"öq–ééK­Ä¾%_MÑ‘ÄY¯L™3s+øûÚ}>“Äì^Ó¥Ùý—$®Uá' L}’²¤I½|û;G·% §ÎsĹ<¶sù’=Hß½3×7iº›$ŽqÞ9´á$q~rûöäØâÔ_h?¼â}âܺâFxG=‰½œkºïDb®”Û:¾ó&ÝþÑÜçƒU$¡Ò@Ò!h#±•ŒTÄñ±öÿúØF’0³û[sÖ“w»ôpö½ÑÄþsÌþ~Çâ_ÿºj3éۺ›\ç2$ijï©ùô6’Г+XíÜNâzrUuqþ}{ÿ‡#ï¶äI\hCvOõ$b³»¸g¾æ$ñrüÜz­ê’„ûu¾ìRõ’°uë¬2ïÛȇ«^®ž@bÌ—ÿeä’rùþ][kÔã“'õþ²"Ò¯Úà'«o'öm__Ý,–ÄO鹢DZ*ĹDÏ¿‘8žÕø¹r—­Ä•çL¡ÜóÀmž“Õß! Ω©?öíBÒj-œ0±÷n´ÛÏ×m+þÕì~Üù)¨OÍõÕþSÿF‰‹¿@?Ð:µ¹DúLht¢PÏïI|Hûv!WÃHrñÕEjéÄ-ÞÝ »FçÞì·æiWjësðžþ"¼ÄO$>záñ«ý÷èRA{ùéf{=ý£T’F¢ù£wÜ~Jó·sOèI’R>ÛZ½‹ ýUf‰†³“èKß8|î’@6?6ÔYDbæš—»km!ÑÇŸ¿U­EuôCÆ<,û!ÚÓÙ ?q^.K¬'®6<5ÑE¿nvæÁgsˆkzžVã–‘”ÕŽ»{¡~+øN‘5;BHŸÁ³ßj¶µ7yw퀮ƒ¾DÿÚ¾ýù”§$N·öVï˜*$¶PÑ{7·&½o¶ -?ù(I˜ÄTjX}±û¨ZÜ¡ŸILÚÓß÷ªMâG~ßò¥V$®Ì›ß0¢ßöò̆˜‡ItÚ¼”­·Ht³ í‹&#Ñ)ž%%k¨ËÒpÏ5Ÿ/¸céߦøëIuµ‘ûIJBËÓ;~îLÜÍÖlœ÷e â$oæÿþ\qâ®´»ì£”ö¤o¹ºMÆÛbPΙ²W+N%®“ËýFž¢œ.®jìœFâ&Öª4–kIb¶¼˜3äM I3ê‡.5FýÒ¾æùÁň{ìïìþ1š$?rý5yqõgZ•¶$©n™´=yÞ öò?ן3ôcŒgÊÎY²´>‰Öàéˆ1¥q-Z±õ‰þÑ8³ú®»ÄþEé];­Ñ¯rg¶¡î\Ÿm‡uŸzº|üþÚýÍûït#‰Eæ8×´A<ÇoÑu)±í{l°r€Ä¥™­½r8ÆæwyR’âî6ùòô>$ñÇ7nî9–$/žÿ‘þIN¼OŽÕ-B¬ß={§F$ñ¬ùëÖqUIÒòß*äÙy¸Þ>PÄF©ƒ–™Œþסª¾6“„ÏM©Ÿç2I®¼ï£öwHÂàƒÖk¶‘”þLîÂ:â¼8õØûkjÇíÑîÞIÊÝ t ù]|hÁÝ,Ä]rKÿ¯ZW%‰¿Ä”W­Þ‡r~-aÈÑrÄÑûåÁOü…Ø÷Xwpï ’8w¹“sW"Ñmó‡­8Ob—VâóÜœN¢W•Û§çb¿PÖs.$‘ô°üía#Z÷œ—~]€8ËÔh™Zòcâîzq[Óljó—Ü;úŽÛCúº®™•ä$}ßÚÜhã’mľä«*ÍMHªaq¯ã‹WÍ_‡Ì\¶Ž¤ ßçÑ};I;==2êÄV’öøð‘Ç'îZé}¯Œ?CV®)½v×"꫼Æn’ðdÃÉ_~ÉG’föÉU`m’2tÌ£rîº$åÙŽ7?ÜÓŽ¤Ž™wæS’r~ìBËÆ7Hbì&sÚ¨ÕĶóæ·ÛÏGe'ΉíHâ·çc­le’p%>Ïø#{I »ûÞõäí¯ï®ù'êÁMƒs}B’JW)}dYI’°»ëí›” ö6]ß~4é’¸më…&©‰=µåsû„ÄÖÚYeÒvpùéÕºœEx.$­(4‰8¸»sŽ}4 ã.w•\ït }Ÿž=y¢B/âXYhPJžå$¹ó²Ï¢«¢¾¿Vï¬:e$Iœ`{plLo×}mìêõÇåÚÓëEâ¿Úðð³äq$Þ1[7æAâx¼ðÙŽb£ˆíSòëy×Hâ‹úë¹LâV„ý^±=ÆMvœ¨3åª[X·Cmš¾ŸM<ãJ¿EúþöIå{ƒ¯×à¨¯îÆ¾KRÏpO®O\7†Ô*ú%ú…ìæ·ë<#îúo>[õ̆þ刼yWüD\WÝ®I:Iúô"w`î÷ÄqãàƒM×ξ³ß«½·Æ]͸?¿yñî[÷Æ”è‡úxŸ©QÓ Ç‰ít•ê2Ii¶úGÍ7I2¥Î=?á7Ò·¥§ç&þIýμ ‹W‰¹=GåŸE’.’+G~ûˆ$ÞiòùŒÓÖ}½çÞëĹýeZÄ”“$~Æ¢e­÷ iRzĨã$aàÚr÷›"ɱÅi1§(é{Ñqü‹”Ã$i|HßãGâúRÓ¤ãïßW¿çß/xŠô]¹mïÏñ÷Iß>®Z}êÍD?òÚÒs擾“7ZZ$bœ1õJµÏ»Ä“¤¾ÌØ&ay‰cŠÙµgÝv?ø]uƒ"EIâÁ½Of.?IlÓ wq´ýø{ïÜ/Y—ÄlúμA¯!ñ·Ç49½d"q¶ kx`r{â4†èÞÜúù§=6u7‰ÿ샪oF¿hWÓN†‹Ë‰­ß©)Wï Ý«°þçdž/‰uË‘¦÷ïäšwª¾±e9Iøõë_œúšØç-þø—÷QNú|‘b7»iø¨7—ì$¶ǯH9C\3ì¹¾œØÜ·iÓweb;ŸQ¬ßc÷n¿Ä›5s‘ÄÑ{Gv©1‘Äü¼Àæé—ÏÄéÝ]ÄùEû› «®Áøÿ΢HW‰ïðyÈíÓ6’ø]Ñ7 Ì݃ú¤b­ÂS1~³~|dØBœWÄ÷Ü6ˆ$5ˆÚR=±7Ï5?¼*OÅw¾ó¸Þh’ªÛO/0n<•ð犖HôâT}÷¸Â$µÜ¡ü}æcü~ðdÙzêÆ$©`ý ®ÌO6n®Î^Fz»Èéu£ILÃåºâ?Þ ½?ÛqõI•Á$åvëîi½Pß¶î^²‰ÝB’F«îT¼G¢ëÔª½¹L‰mZækv(ÆËÃ6–ú¶Á—Þ`ëÝöûIì̈%“J4% f÷] ª@j•QúlWbW³4 ñ³[z&ŸL&ŽaUÇ/¹¹ã0Sþjw=ı¶Ê¥qµ*×Ö_ûm~ZùZÚ‘ôýõu ®°ë髞vðÙq#‰¹Õ§ÙÔ??&ñž ÷>‰)T´Ê‡í¿!݇ ÖͺŒñ÷ï»×®(tŠÄ ýàÍ g‰ý—ëo}R×NM†ü°cé4³æÔ†óí»ûà7®œß~š¸Ô“Ê7)÷3I¿©í}/q?­¿þнû$i“£Ð‚â $î®·ëŸ$ðgMýÊùO“¤¼Ÿð›ëœ"ŽK£6$Àxg™‡ Þý+±{çp•¤$et¡4kÅ1nŸñ|ÎÂõÄi^ÔtÂí?ˆ3ÿó“|Û­¤ï½+ƒô¿—%}ƒ†¬ni}I\ñ¢?‹G=¾¾Þ™2SQßþÖ}R ôËŸ\¸”ôÐIRÏ KØôq­Ùu£æ.I»Çð³¸?¾’Ëvy%q“õ oG\Õ‡\Ùñd7Io”T§Ñx”Óž>«úçW5´âý©§–ìùâË‹½HL§øÔÏ–ö"¶ÝçOlE;Ÿ°jRg,‰ãø\e™G¨7Fçw-I#®ƒa‹øé¤oµ|-z—OÒ÷\£Õ÷‡1îçê:ë§õ˜Û2‘÷ŸerÛ¬‰kñœ‘ÜÐzÄñbÊÚí•Ê—¾ã%Õ¯ˆ3†_uÃ\¤vþmLž=£ˆk’z²yûBbŸ{iÖÚWI̮ѷ[Î%¶¯ž¾û}PboõøÓ™óÄÕ=k:>!îñ‰®E’†Ê½¢á{$þíUçZ]s“¸õ¾¹Õè;’2óF¢±6š|º‡ ýÊüe[ÎÇÁ¡gZ¾‰ñá§·Ý]›¤ ÿ|É’ž•ˆ{îSخΤoXå©oNC\寨Zü âîÓ²Qç¢5ˆ-}„z\¯žÄÖiß̆ŸŒ%±‹ëwï¼—$Ö Z»ŸïC’ó¶¹¾ã“8’jL¹ú^…UÄÕ£`ë¢~ ®õÚË;ÿ˜‡qýè•ïyP\{í ¢%I7ì­9¥IRŸý­gó=ÄUhÛø¢zÄES~ŸþôM’ íþç‘ $¾õšHõí&$¦¢qE™ðHŒ#s˜?b9ú/UÜS~zJúö®¶ðÃz $ž´¸¨w§{™oª•Þ•‡Ä-úãüÏ–Û“[—;k&ö*ÝÕa‰Ð̪c #I¹¿ÓhÐp’Òõdýé¯"«-OŒŒ#É3fÔ}òò7âȳüÇ”?ò“¤n–Gòõ IŽˆÅ•RË’¤…æ=½®<Á8mû¸‚/Ç“¤[7ÎOý#IªóÙÀž?¡—ªß:}6qßßß!ñ8âß+âÀ÷û´$¥Ü{o|ú“$5ùmé²'sHÊŽ"ÃN§þAbÞŽ8ðÇ ¶$!êöŒ:‹÷’xÛû7KW¿Il*îOK„{õÂöê.ˆG×/–¥>!‰'™ùµ¶•'±£ûaìŸ$vÖ½C¿ßAú×h5z®ó'boy ºÚ¢¼ÄþNÇãSú¼ÏŽÆœìBbWV²úZ’Tha×<“ß$Îß&?,å’0­ÌµõK«Çû§7»¶Ì'1KÆçª2“Ø×uitüÎrbg~îüý±]$yžyw¿q Iôµ6¯ºDbÓ6½Ù~‰Þ{÷Ö•™k‰ýûò¿–+yýü[«Åì&q£“›˜ÇÎ#}UOv—ô}³Ì=“ë±×Ò½‡úªx›æ»‡“äï¢Cfžfˆ½ï¸žÓÆW' -™ß¿0ILjVwäsI«¿¯á¨$yë°. ×5&Χ¿ÖÔ7*H¿¼øÑ§ç0N:8§vÍû$ñnÍÉÕc\3´Ë‡ù0~I\<öKÃÐÃÄ>ûpù*Ï!ñùkœ}þçH·ã«¥]‡Ir¿ ¾Ê;›ôVæÇ#Õ«ǽ~WÐ×Õ¤I­•ë~íf„¤}~qä¸õIÚ ÛÝ#¿'®óåònj¢' Óów©0´:‰ÿÍ4qÀ“ŠÄvµtáŽE’d¶Y<ßÎ'ö¤gÛÿYC7õ~øIÑe$QWs÷àO†’¤ûgËöê0”ÄÔJY{}Þ!Òurõ”õ¢ÿ¹éjÇ›Irõ³w/T?K’“›ÝúÃL’¤oöýÙ+zÒ÷eð©3?ÿF’-·v ±çýéû_]èßÜxÏ~²|MâZ9¡øîá_Küãïò^&¶b¹wÆíƒñHÌÞ¦ I\‘§ëŠ–Pkç{nÿø%‰¿µ¢nãfí‰#¬ïŒb P¿åÿåP÷%¾/û;úïÎûaÞ$ådû<–ÆhGß\†vçû ÜÝN¨/Í‘¿u§óanüøòÚTÒ7a[®‡É¥HÚÃ/w¶<úIk~z˜ó‡dÒf™}ß¼ƒþWT•ÁÍ˶!îo××ÚQð%IUø©ÃýöÄ~Ï‘x8¨ڻɽƖÞAù|üTðI*7ùgÿt’òaœíÒíS$vÞŽ9ŽÛ‘䇅¢Û^6×………zLûŠ$ëÞß¼ã@ ô³F¼±û»b$z×'÷ŠÔ‹þLåw”ú”D?]ΛCb¾‰îØoÈ1Ô‡–$]{‡Ä6Ú»jª'šÄ¯=Û^ÿM.’ÒÊ|Éuj!q¥ŒûtfÝü课å™ýòùcý±'InQôÏgí§¸ÓãzšËÞC=;?ÿƳù‰-ñF1ümt}RÓ§Pnï>h9d#y÷pÑ«ìŽ{$¡mëF³LÏIbÍ ï–›ú$i:îýâ%qÖÎÛ¯³!ޏ:.¾1lÈf´§m‡DçÆ®c›tľ,yÝ›Ä?ü©ÇŽÊ=Hüüç;,,FbWLÿî̇‡H,“búöÑZ’ØxÇëo$ñ“kÝ\÷p$I^±ÑFÞ|›Ø×Ö¿ÕñÜF’\>üjŸu)$¡ðЇo7~“Ä¿9jÆ…š—IRááó×\+HR›o¹ЃþöþNÖ˜ç÷±ªC%—–ëQcÉn’ôòü»q£–Gåg‹NMì«›^xv‰mÑâqÍf I_Ó¤ÓQ×’”éÇtßM’æt+tm2ê½Ò…ÚOûéôWÏmÛh¸IËî›+1è×¶X^õÙÞ3$1²—%Ä|ðÀ°ñ-’<ýÝÕ?kƒþèÁËF?£ß¾¹_$)ÕOº[“¾ý;ߊ¨_“ØúF¿Ø<íÈå/:./Hl?ö*7.¥‰éÈžÓvêHì«Êö^kžúª“x ˆíÙgåwßþ“Q©‹ù~ãw«² šÂU‚z‚š~È«,áÕt`tT£†þÈc‚É%ü–z’WD>˜üŒO½¦ L!˜Â0E`ŠÂ Lq˜0%aJÁ”†) S¦LyÍŠ0•`*ÃT© S ¦:Ì05`jÂÔ‚© S&Æ  S¦L}˜0 aÁ¼ ó OÓU™8.&C“„ñ%’̺‰=Eâ$‚ñ+›dhaÀ‰ÃšbKe2TŽ‚¼n…OÔ©YG¼ ɸ5g܆f܆e܆gÜÖ͸­—q[ß«©S[r_Gr"¹7KîC%÷a’ûpÉ}]É}=ɽÄ߉¿!C$þ†Hü ‘ø"ñ7DâoˆÄ߉¿!ÍÍÍÍÍÍÍÍÍÍC%þ†Jü •ø*ñ7Tâo¨ÄßP‰¿¡C%þ†Jü “ø&ñ7Lâo˜Äß0‰¿aÃ$þ†Iü “ø&ñ7\âo¸Äßp‰¿áÃ%þ†Såõ–©JKGšÍcs¥UU’8€ñU3ÿç;óä\ÿ+®Š¢‹³Æ¤9Ýb-Ëd4lÄ™!6>²­5Ím ü½Ë“d·1ò"ɉ޽LZJT-ýˆñµw´Ý¤mý¨ØÞÑö“¶1´ ¥m^!ä´í¡í Ø®Ò6°6ãk³hÛJÛ5ÚþÒ6–¶e¥…PѶ‘¶™´M-Ád´½´¤ími[FÛJÚFÒ¶‘¶¹´¥mj¨:ÁŒ¯M¥m6m÷h;Ma¤1¦í*mçi»HÛI±mµ0¾¶¶Ë´¥m?mSiÛ&Ä+§ïÀ”ËÅæÿÝ?šbf•bÞe—_ʼzUÑüó†æKmæo凷?Ö&¦ LS˜f0ÍaZÀ´„iÓ¦ L[˜v0ía:Àt„éÓ¦ LW˜n0ÝazÀô„éó6Ì;0ïÂô†‰b| ÊV˜hÚ…¡µKLÄ!)cÓ“­QÖäh{Œ39Ùç‚bÒݱÞdsg,è?žŠ—4[Óô·þDW¾î—žUF>Ö–Œäq:¢ÒÝð;=E‘€v ¾iMq%Ð’C#™9t1Nw?úÖév:lŠ!¼KÁ›ØŒ°‰E‰åÊH±(ÇY“cœQiv‡#Ý“ž‘¯EdïSÁC?jÿk±,Óòmõfg”ÝíFø3åª-=v +͆PÓáŒ4Ѝ#Ç©1HžÔ(1«;FÊ”õTšm[´3}€Ýž)åmn‡<¦Ç[‘§âëBò× vwº#Ö©,1^ÒÝöX{4ÞfŠ¿ïµÕoCÈÒü¯‹É^#k­ý­n)CEeRóÖ›¤¼½C±ÍômW‚=Ù™b¡åÁ•ï°”‘Ä ¹nu{k «Ûšj—¦œ„~V|¦S¸QœtoÆÓÚÊéΔî(éé)Ñ€ÚÞÏ_“‹ï(nÔnZ—¥»Á¼•.“ÊTùŸ£ä&£ŠÈœ»4ßðÚwQdŸËÚÏ ì©Ò ë1«•-ªÙÔ¨T[ŠÝeMNÉ(bÄ$Øb]ŽræP&P´›;om+ÍC1VT:QgÄÅ¡jQ¦žð2.=ÙŸ]AÅ[Ú øÁð®lÙ62Ê»R¸K³úçt²v’­ s¶.B³u–­‹ðl]ÔÍÖE½l]ˆ…Y§XíìÔÉÞIHöNÌÙ; ÍÞIXöN³wR7{'õ²w’}ê†dŸº!Ù§nHö©’}ê†dŸº!Ù§nHö©’}ê†dŸº!Ù§®9ûÔ5gŸºæìSל}êš³O]sö©kÎ>uÍÙ§®9ûÔ5gŸº¡Ù§nhö©š}ê†fŸº¡Ù§nhö©š}ê†fŸº¡Ù§nhö©–}ê†eŸºaÙ§nXö©–}ê†eŸºaÙ§nXö©–}ê†eŸºáÙ§nxö©ž}ê†gŸºáÙ§nx˜o ¬¬(gÿèÿZ¦‘sý/¹n)U¦ÜãŸwó»UÉL;ûÐ0ȳüfQ~[“Ò_½Øù_߸œ1ù÷–üÊ)µæÿ¾ûM~_×k#§ÎkĬpW·èÅc~×ñö% áw¯Y«ÊûùCš þÐY“ßùðQ\M×N~û]/?ì“ÄïŠÞ¹úé–™üž¤¹3·NlÇÏ-¸¢öŒ £ùóÏìûuâM~ex«ð±¹ñû4Ò¬zÉï¾rfØ…VðÞÈÓaAËÏù-÷R“LƒGñ›‚ÚŒêØ‚ÿîÏ„iOîæ×˜Ãvm?ü1¿«ÊЉ…J™ùÝ;ç7|~®Ý[ ¿íýng64ù™ß«­X¸DË=üÙþCîå{Ô†ÿ¹ãóµE†iøýûkžh6¬;¿ó×UÆ´cù#Å‚¢Wì<ÌOÚŸ— Îïhä\˜[ó&¿sxH™]‹øÕ½Î¯]bnÄo;ľW¼ç#~Ëž©«-|â«ʉSäÌ_*–W*ä¼JŠÈæhß0%hsÒD”b”àD¼B‚#jé¼›ËøGè‚5Dn5Ë­¡rk˜Ü.·Ö•[ëÉ­bŸA/£¶Â^GaQØÍ {¨Â¦°‡+ìuöz »"|!Šð…(¢_ˆ"|!Šð…(¢_ˆ"|!Šð…(ÂgV„ϬŸY>³"|fEøÌŠð™á3+ÂgV„Ϭ_¨"|¡Šð…*ª_¨"|¡Šð…*ª_¨"|¡Šð…)¦_˜"|aŠð…)¦_˜"|aŠð…)¦_¸"|áŠð…+®_¸"|™z¸9ÚS9WáïßӳɨM•YWJURð›¶è$÷´å*ÏÈ[ú⌼Õ/ÆÈ{Eyo 0#ïäg佄 FÞc¨)¹{â½Ør˜Œ^E8#ïa„1òÞFFÞó•Ü‹­¿ŽÉè‘Ô—Ü‹=ŽÉè©bä½–F’{±·_p'ö´B:ˆ= “Ñˉ”Ü‹z1j!]EÝ–Éè •fä½¢–Œ¼‡ÔLr/êÓg2zN¢ÞŒ´'Õ‘ÉÜ«j#±‹º8ÁÂ;¥>-´œˆº8ôOì‘Ua2÷ÎÄ{Qg§¢ð\ÔÝ©Àdôàz1™{s⽨ßS•ÉèåEIîE½Úó£eŠ–-±ÑkmÆW6h˽Ò2AË-+´,Ñ2EË-kb¹ WZ6‚_™óŸ^i e‚– ±Ð+- b9 W “‘ïôJóž–Z&Äü§×¦BžÒ¼ó•^iÞÒ¼o)ɧ²’¼j#ɯrBž•ò­œw4ßiþÓòÐI¸v–ägy!OÅüª$䙘_•…<«"䕘/Õ„¼óá !/ªûòH6¢ úXô–{Öy…4,"ıŒ–ÊÂ7j ùTWHo^H·æBüÛ ñè.„‡– ªïEu¼¨^Õå¢ú[Tg‹êh …ÁÀ’3fÌT˜0³`æÂ|³f̘õ0`6ÁlÙ C`¶Ãì„Ù ³f?ÌA˜ïaŽÀüsæ$Ìi˜30?Áœ‡¹ó3Ì/0Waèö¨7`nÁ܆ùæÌ˜?aÁ e|»Ñ ƒ3f4ÌX˜Oa>ƒ™3f Ì4˜/`¾„™ 3›ñíZ2fÌB˜Å0Ka–ì„Y ó-Ì:F.‘üŽñÖEÿ’dï5&Jåb ¿3;+!ýSé÷d¢,¿héõgp傪WN’pÉ%q2š_N&“§¾Îœ¸Lö*—ÙýÃr+¹ ôò2¹´õ/‰»äâÚW ¿ zÅdür)r–"E¹ úÀ2× ( ÿ§$uraõëÊí ·åbðÚÒÀ‹1ù×Ä}25¹ ýoIÉÝê)¼¶ÈP¦ò èËT#þeñá«d’rE€€‚Æzr¿fÄ¿,Ó“+'d-4”+*¼žT®º•<ôUÊÿfY©\›"“CŽdïÿòš#ÙË‘ìåHör${ÂÃÉã”ogˆ=Â5KûßLö_vÿm÷…÷Åkº¦°?ÉÒýú¦GÓÞ-Òæ5¿ÿ“ß~³Àª†Võü7Ç?ëüò½šÍû‡ û×ôÿ~6ïoüÃñ}®°_ø¯)o¾÷*ìû_óû(ìßÿÃá °¯}Íß_UØw+ìÑÿ±ò® ÏÉ!£ûœKhñ—¿wëâžïs½§Îòý힘~­µàŸ ¿·>Éßo”hx#|ð?õ}ñªjhÒ]Ét‰D#“t(¡«¯tÔŽÉjÍZÚk®Y“‹Yº³œ‚®’\¥‹Ó^µ<]¼70—«+—­¹¨E³°Â·ó1‡Hˆ"—@KÜ¥KÝEQŒrÉ»r“fqÁ—¸^½ˆ‹¶¤KãË2Y/‘´\^t#.Â’.¶ïEñ‹(z)Çdˆk”ËêÅ{éòzé2ûÚL†HFºì¾2“!Ò‘.Á—.ůÁdˆi-ÍïEqŒ(Š‘º—n>-Ý„Z|o܈âé½r“jñ^\ ×’É-H7¯óXúå"ºfŒ|³kq“ë¶Œ|ãké¦×ÊͯÅÅ}=˜ì7ÄôìU"‘-)GJFhy—–o±<ÓòÌd,à’–%ZV”Û0ˆy.様'Mùæàbº(Ó¡—åFßÒ ¾©ø†ÖpTt#ݼ›nÚ=”ñoÒÍ|ÌøÄ6£`Æ1>‘ ] FE6TTCÅ4_1>Q ](FE5t±Õ,b|â™UŒOD#.Ä2Œ‡ñ-ÛÁø‹Ñ…bßb±CŒoÁ](v⯋pöæOˆòm¥Ü;“>‹Òð\é^”+Ý+õ²’¯g÷L¿÷é,õËùÅïˆú Yé×TõZ5™ô|D}…^¥¼×Ýr^Ðõˆ<÷}£Kë¼½ÿìÂë×sõ ßúiÐß L¶¼IÕÂjƾnºY”úArw*¿>˜=„ôÓA‘.~=…;¥ž’¥“Çgõ•ñõ•áö=_è×+¯Ô‡l)äÏß-G>}“ÏÄïùõš:x½YæO—×M÷¿X.³*×™ô}z+•ú¤–‚½‚Ü¿,yõXz«–ˆ¡ÔªöëóùÒýéßN_Ÿ>äE¿>  WkiâÍÏY¥o¦p‹ú»rý¢ù~}Kß÷:ûõ}}׫úÂ>}`K#¯þç×þ‡yòǧõPßsQ?S®ó~½eß5¥<3@7tç×ï,²þÀõû/[”zQ¢ž³¨ç)êúž÷´T_óKgîfI¿ž•¨ªÔÏô=¿iiP¯ÎýËÔ˶¼ŠåK¬÷Äï‹ùÚròÉÎ=Û¾ë/W¢;QϳΡI±?†·±(ô”×ìô7Å+WëŽ6þ2R> ©¨ óï}Q)Ó‹v´áïôôa2:N´c,v,h§Wzšˆ¨$v¢hdžv>hõ*î|PYˆ™ØIwKvzè`BÜ©BÜÁBÜÙ‚†Vì\ÓAˆ¸C†´“œÉØICÚ1¦ÅKìÓNí$ˆºfbçXÜBÚ1¦q'±Ó*îJA;bÇWÜ‘€/QGŒv8ÄŽ(¨ˆ» ˆ6:à ]q¢ìÓÁE åè¯o€Œ©ü72FT@“fŒ¸ÕI ŒÉ#dLn!cÄ¢2c YdŒþ/fŒN’1……Œ ”1ZIÆ2JEÆ”2‡•dLñ¿—1YõD3q¨§rT[›®¯ƒ¡^銥¿ßþ»áô„óm².¸wÿSåÙÎuúxkz*•€äØsì9öÿa;ÃÒFQ%ﺩ¤ ƒPÐç¬tŠ"ˆ‘´ìu= 5°Qþ}]@p¨îìL«î6Ö”èXQÀ©îÙMl8";ˆsÕmìÖhá^ÛÌ>À+þ¶“Õë5ôl©öØt«øe}[?D6F¿«›´ŒÚC¼é%úÖ«“x×£?½ìŽ~64‚Ýh£¢þši6·è%gM±'ÃÙ%ݯ{ ¡ûag4z²dÒÓ ³ã“SR˜ÌsåênV·/L˜Ì³âÿƒµæ7Èøf2©:ÝæŠÎhŽ`|Ê裟BúƧ”.åü fã›í¤[bQ%õÏŸ¢:݋΀Ng| ët«,ålèlÆ{¤¡V”*±Ïg|³£t;-ªÌ¾ˆñ)´Ó­µ¨Rû2ƧØN·ÙZÉdÌžÒ-·¨’ûZƧè.Φnd| ï›™Ò»wv•Àlc2fYé¶\»ßlëÆ·=×>&ðÌëaÆ·]×QÆ·e×1Æ?ëݺëãÛ¾ëGÆ·…×YÆ·×9Æ·•ׯ·×%Æ·¥×eÆ·­×Æ·µ×5Æ·½×uÆ·Å×MÆ·Í×oŒo«¯;Œo»¯»Œo˯ûŒoÛ¯?ßÖ_ßö_ß`Oß6`Ï_úR¨?ñŸwK0ðïÝ ü{·ÿÞíÁÀ¿w‹0ðïÝ&Œn IWwƒïvaàß»eø÷nþ½[‡ïöaàß»…ø§Ûˆ©À¿ ü«À¿*ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«jûøWøWøWøWøWøWÕ[´e‚±À€øWøWøWøWøW*âT:¯ ÿª0à_þUà_þéd„ ü«º{ÛFÕÓÛ0*ð¯ÿ*ð¯ÿ*ð¯êþUà_þUà_þUà_þUà_þUà_þUà_þUà_þéI÷tì«ÿ*ð¯ÿ*ð¯ÿ*ðOÏßVøWøWøWÕPð¯ÿ*ð¯ÿ*ð¯ÿ*ð¯ÿ*ð¯ÿ*ð¯ÿ*ð¯ÿ*ð¯ú ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«À¿ ü«èV€/}Í> þYÚÿ,øgÁ? þYðÏ‚ü³àŸÿ,øgsûºvl^ß8›ÿl~ß Hü³àŸÿ,øgÁ? þYðÏ‚ü³àŸÿ,øgÁ? þYðÏ‚ü³àŸÿ,øgÁ? þYðÏ‚ü³àŸÿ,øgÁ? þYðÏ‚ü³àŸÿ,øgÁ? þYðÏ‚ü³àŸÿ,øgÁ? þÙÆ´/þYðÏ‚ü³àŸÿ,øg[Ó‰ðÏ‚ü³àŸÿ,øgÁ? þYðÏ‚¶;íçÁô¤=?ðÏ‚ü³àŸÿ,øgÁ? þYðÏ‚ü³àŸÿ,øgÁ? þYðÏ‚ü³´{ þYðÏ‚ü³àŸÿ,øgÁ? þYðÏ‚ü³àŸÿ,øgÁ? þYðÏ‚ü³àŸÿ,øgÁ? þYðÏ‚ü³àŸÿ,øgÁ? þYðÏ‚ü³àŸÿ,øgÁ? þYðÏ‚ü³àŸÿ,øgÁ? þYðÏ‚ü³àŸÿ,øgÁ? þYðÏ‚ü³àŸÿ,øgÁ? þYðÏ‚ü³àŸÿ,øgÁ? þYðÏ‚ü³àŸÿ,øgÁ? þYðÏ‚ü³àŸÿ,øgÁ? þYðÏ‚ü³àŸÿ,øgÁ? þYðÏ‚ü³àŸÿ,øgÁ? þYðÏ‚ü³àŸÿ,øgÁ? þYðÏ‚ü³àŸÿ,øgÁ? þYðÏ‚ü³àŸÿ,øgÁ? þYðÏ‚ü³àŸÿ,øgÁ? þYðÏ‚ü³àŸÿ,øgÁ?rÑ.¿ü«Á¿5øWƒ5øWƒ5øWƒ5øWƒ5øWƒ5øWƒ5øWƒ5øWƒ5øWƒ5øWƒ5ø§Z9jð¯ÿjð¯ÿjð¯ÿjð¯ÿjð¯ÿjð¯ÿjð¯ÿjð¯ÿjð¯ÿjð¯ÿjð¯ÿjð¯ÿjð¯ÿjð¯ÿjð¯ÿjð¯ÿjð¯ÿjð¯ÿjð¯ÿjð¯ÿj𯎤Ã7ð¯ÿjð¯ÿjð¯ÿjð¯ÿjð¯ÿjð¯ÿjð¯îDÇ›0à_Ý•Ž°`À¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«Á¿ü«_ú†ûaEþ5x ÿð¯ÿð¯ÿð¯ÿð¯ÿð¯ÿð¯ÿð¯ÿð¯ÿð¯ÿð¯ÿð¯ÿº0ø×€ ø×€ ø×€ ø×€ ø×€ ø×€ ø×€ ø×€ •1€ ø×€ ø×€ ø×€ ø×€ ø×€ ø×€ ø×€ ø×€ Oš0à_þ5à_þ5à_þ5à_þ5à_þ5­é, ø×P¹"ø×€ ø×€Mg:;Ceà_þ5à_þ5à_þ5à_þ5à_C5©À¿†Nဠø×€ ø×€ ø×€ ø×€ ø×$ÓYð¯ÿð¯ÿð¯¡kÅÀ¿ükÀ¿ük¨ÈükÀ¿ükÀ¿ükÀ¿ükÀ¿ükÀ¿ükÀ¿ükÀ¿ükÀ¿ükÀ¿ükÀ¿ükÀ¿ükÀ¿ükÀ¿ükÀ¿ükÀ¿ükÀ¿ükÀ¿ükÀ¿ükÀ¿ükÀ¿ükÀ¿ükÀ¿ükÀ¿ükÀ¿ükÀ¿ükÀ¿ükÀ¿ükÀ¿ükÀ¿ükÀ¿ükÀ¿ükÀ¿ükÀ¿ükÀ¿ükè¢wð¯ÿð¯ÿð¯ÿð¯ÿð¯ÿð¯ÿð¯ÿð¯ÿð¯ÿð¯ÿð¯ÿªþ5à_þ5à_þ5à_þ5à_þ5à_þ5à_þ5à_þ5à_þ5à_þ5à_þ5à_þ5à_þ5à_þ5à_þ5à_þ5à_þ5à_þ5à_þ5à_þ5à_C§_ û‹€-ø×‚-ø×â¡ükÁ¿ükÁ¿ükÁ¿ükÁ¿ükÁ¿ükÁ¿ükÁ¿ükÁ¿ükÁ¿ükÁ¿ükÁ¿ükÁ¿ükÁ¿ükÁ¿ükÁ¿ükÁ¿ükÁ¿ükÁ¿ükÁ¿ükÁ¿ükÁ¿ükÁ¿ükÁ¿ükÁ¿ükÁ¿ükÁ¿ükÁ¿ükÁ¿ükÁ¿ükÁ¿ükÁ¿ük›Ò`ð¯ÿZð¯ÿZð¯ÿÚ¶t. ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚-ø×‚íKß4?þ9ðÏüsàŸÃ üsàŸÿøçÀ?þ9ðÏüsàŸÿøçÀ?þ9ðÏüsàŸÿøçÀ?þ9ðÏüsàŸÿøçÀ?þ9ðÏüsàŸÿøçÀ?þ9ðÏüsàŸÿøçÀ?þ9ðÏüsàŸÿøçÀ?þ9ðÏüsàŸÿøçÀ?þ9ðÏüsàŸÿøçZSAÕ k¶aÀ?þ¹ŽTHþ9ðÏüsàŸÿøçÀ?þ9ðÏüsàŸëCõ `À?þ9ðÏÙ¨ÌüsàŸÿøçÀ?þ9ðÏüsàŸÿøçÀ?þ9ðÏüsàŸÿøçÀ?þ9ðÏüsàŸÿøçÀ?þ9ðÏüsàŸÿøçÀ?þ9ðÏüsàŸÿøçÀ?þ9ðÏüsàŸÿøçÀ?þ9ðÏüsàŸÿøçÀ?þ9ðÏüsàŸÿøçÀ?þ9ðÏüsàŸÿøçÀ?þ9ðÏüsàŸÿøçÀ?þ9ðÏüsàŸÿøçÀ?þ9ðÏüsàŸÿøçÀ?þ9ðÏüsàŸÿøçÀ?þ9ðÏüsàŸÿøçÀ?þ9ðÏüsàŸÿøçÀ?þ9ðÏüsàŸÿøçÀ?þ9ðÏüsàŸÿøçÀ?þ9ðÏüsàŸÿøçÀ?þ9ðÏî¥Oħÿ:ð¯ÿ:ð¯ÿ:ð¯ÃKø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×ø×½ô‰÷õà_þõà_þõà_þõà_zð¯ÿzð¯ÿzð¯ÿzð¯ÿzð¯ÿzð¯ÿzð¯ÿzð¯ÿzð¯ÿzð¯ÿzð¯ÿzð¯ÿzð¯ÿzð¯ÿzð¯ÿzð¯ÿzð¯ÿzð¯ÿzð¯ÿzð¯ÿzð¯ÿzð¯ÿzð¯ÿzð¯ÿzð¯ÿzð¯ÿzð¯ÿzð¯ÿzð¯ÿúHªÎþõà_þõà_þõà_þõm¨f ø×ƒ=ø×w¤j!0à_þõà_þõà_þõà_þõà_þõà_þõà_þõà_þõà_þõà_G5C`À¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ¿üëÁ?U˜ÚŒüÀ¿üÀ¿üÀ¿üÀ¿Ž àßþ àßþ àßþ àßþ àßþ àßþ àßþ àßþ àßþ àßþ àßþ àßþ àßþ àßþ àßþ àßþ àßþ àßþ àßþ àßþ àßþ àßþ àßþ àßþ àßþ àßþ àßþ àßþ àßþ àßþ àßþ àßþ àßþ àßþ àßОnóþ àßþ àßþ àßþ àßþ àßþ àßþ àßþ àßþ àßCU•aÀ¿üÀ¿üÀ¿üÀ¿üÀ¿üœt»2ðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿðoÿ†—¾Áàßþàßþàßþàßþà߇FðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoÿFðoŒ¥ 0àßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßþàßøÒ§Òkÿ&ðoÿ&ðoÿ&ðoÿ&ðoÿ&ðo‚cø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ø7ªß.S}×vðêùûØUYmn-*ÈSÁ{Ž‚<“£ @rä™y🣠þsä™y🣠Ïä(ȃÿy&GAüç(È39 òà?GAžÉQÿÿ)yÙž®ìϼòKöm`M|'^æö}2gÈÏä ùs†ü9Cþœ!Î?gÈŸ3äÏòç ùs†ü9Cþœ!Î?gÈÿ>ä—ËôI62Ý'Ó·ŒGùõþÉ9bÒÓ\N»#-5*5Í鶉îÿŸÌ½ÞátÇÚÞý^sg¸“ë DtsupìŒÄ­ÇhVðDÅdÞ W•ñ<Û£: åD÷‚ýÚüÖÿVסÝŠ0Uð]Ídù'Ï’ˆ”t$Í«Õ,´m¤Ž²ø’¦M¿ì?Ôø¯|¨qƇØ7Ϲðã©ï6gñA½Õ‘fÜ+SÄà}'x˜i~ÉAߊÞ²N­×ý“Ç·y'‡?.j¾OtÛî.òŸ@'Ú3ÿ¨ß¿ò#»£ŸÿG¢cÅUù£TW²NºÐò-–˜@üèÑ©6w?[¬àADVä\ÿ·®Ê¹ÙoýD‹S0ã›ã¤s±AŒoŽ”Î§Ò¹V:Jçfé|,S­ÍdÌËÒyV:ßja|ó§t.–ΟÒùZ:ïJçBé+·¥Õi]Á/:JçJéü¬0ÿ*/ëÉQi).Á“ϱç7Ú׺VÔsì­>íÜ{vz~Èó{ìº_ziƒG.h¾Ês0üa¹cÚ%üüq…×%­‹öìùhל–7îyVýD}çfmÏ.ã„°M5ŒžßækmëÙyð‹Õikçz¾]_°.{v¦g@ËÂŽ[Úiž–ŒïYúKϦÙ}¾»>ª…ghÍïÏØ_ÁCNîœT=r?aæIÃÃyv_]ºÌ훞•ßý½Q߯³rþ'ÃÇ”õLî·ðÃçcôž÷?é–{ä[ü#zNyò(Ñ3ùb«‘Ú¶Ã<ËjÄü^«K~™ÍU%<ù]~Nûå\¡ÍAžµï}Õµe½yϾ»U]êñŸÔ®öî ¿zV•­ÑÜÑŸpï›™ÛßÇïÙØÈݲ.?µç‰*a *¡ ’QzP_ð“È¥ßéÃø¤TŠ@% TZÑMˆ+•‚P D !ü=3‰…lýlÉ©ŒüŒu­÷È{©Å,µ„J-aRK¸ÔRWj©'µÔ}§–:µe¶:2[ˆÌ&;¥¾N¨Ì&³…Ëlue¶z2›,,!²°„ÈÂ" Kˆ,,!²°„ÈÂ" Kˆ,,!²°„ÈÂb–…Å, ‹Y³,,fYX̲°˜ea1ËÂb–…Å, K¨,,¡²°„ÊÂ* K¨,,¡²°„ŠaÉë¢G]Ge:hÞå=h>*óA󩾃æ£ÍÇXÝ.g¬£24ošÊ|Ð|_ñDù(ÙAó’ÇʃæSăæ£4/?Y>*ðAóƒ2šÊ|Ð|²pÐ|”â ù´Œƒæ£ÍÛă棔Í' ÍG)ššÊ|Ð|š÷ ù(ùAó©¾壔͋ϕÍÇ ÍG)š‘4¥Æ{¦|”ü yá¡ò yzÆ|”ô ù8zž|T€ƒæ}/24ïÊ8h>JyмM8h>*óAó.ÿAóQšO¥‰ªÕ{ |T¦ƒæ…çòƒæƒ’½@d>^Þ÷<óñò¾çŽ—÷½ p¼¼ï…ìxùü®{²3ÅC3F~Â|ªä„ù¨'Ì‹ËG)O˜ñ0¥8a>ÆwÂ|”ì„ùÉ óQN˜÷?ˆÊt¼ïhù(ù ó.k?gT¦æ­â óQ™O˜Ï“`sD:`>Ú{À|Tææ­Þ3ã£Ì O•Ì‹…æž_ÀÅYcÒœT„ÿ‚‘Ÿ0S¨{‚=ÍV#Æíì‚iyÆ­øíÎôT›â!I«Hñ…üMiªÚ¬ŽàèdkLR´Ý-õP°“-¶F»#ŸÍô®¹ÛfM«‘fµ'ãm¼o“EL½lH˜`D=&!ëGAíœî´ôàd«‹ú"NLtJ‹»y“Óm¨ÂœÖ41É;»œiÈ…Ô`äŸ;9ãg¹h¤b­ÁñN§ÿðˆ DÍ[8‚“ÐX¸mÉÙ<ÏßÅÔÙ¿F²-žÆy$¾ÉÓ˜&opªÓF’„§º6kœ³¿ÿð Úà4»Ö\-lndi¼ôCEÛØhûåKÏÑøOî‘®ÅZŬ2ùòO–”E:SPwAjŠe­±ÍroS¸ ê„ðÔˆ¶''˽åÚZã]v[†hŠcƒc2ÊL€ Ìå HŠÕÊUxVDHÁ›56@©ÉÊûÀÉ›¯±7‘„oIœçò…V–×Ò «lÎÝ9Áîãì/ Z¾H<„+«+Ø…¤K÷G)owk?xÑŠŠ(Õ_¹"+-5âœÎ4y§3Z„,¨ƒX='Zmñ6‡"m,jçØà¸ä1Ö4Ô4â«\9k TFŒ x©CñIE×¥F¼›Á+MZ‡Í[ \H³TTMYg^vå0Ÿ¿VPp–§¹¯+á}.ˬÊ#d‹Ë‰ÆÆŸØ¦.éq4‰bÓcÄÌÎ%Ý«t—øUñ™ÃÙ_–Ùù"Ð ¡Ý/1gýUl¡_ì²ÇÛœbº½²Ž,ÐØ™UM–[=¬$§ØçïäŒIJpº\™¼¨¼¢þ@UÜ*ÅÛæ­0„ Føã?nR¿Ô˜Q¿ýóÕó÷Þ\ùàîÞ =»öñ?'Dö>ì𠯘gíé{/ü×™£×\‹ï;?hò eÿï§_ßs¦å-¿‚/\(©l¸çÛ/ÚÛÎMS¼òëãæjJ]àOE4|>žœå·‹xXþæŸü'E+Û°5¿Èµ¬÷äÓáüÊ[ÌýzV?¿N²~ËwF>^Ó)æú÷Uýþ|øåÃ1'Ÿöˆáý¶N©¸úß…ð+ëµÊ]³Ú|~‘¹ø÷[‰áõÿîðÂ77u˜Å¯(°oÌÀÝ1þ÷¤°vï²Ñ¢Ýî9US»»>â—ýÁ<ã^.å×w+Yy|Ùîbúy¶ŸiÛ§“{Œg¥¥Ð°Ö‹æðc5Å~¼0s¾ÿ»GvŽØ¼ƒûŠßötÉüI]?S¦'ÿÙØåó¦-¨ÆdñÇÏh²y7)Ú›ŸÝ\s{æ‚Bü\sÇ¢Ço®ñÌwåÃüïgr´ÖñÚ ~XÅÏðî¯wŸ˜ø¹Åª/\v­®?ý¿Ý°bË“ Tã.ˆÉhÒ¹~´'dû›6MŠÕ_[euÿÏ~íß}ÿ÷CûOÆð_ññ_‹Í¿öÿ†°þÝýÐù¥¤š‚^S:§Gµð¨¤šÎ»Ñ¹C:oG»ÕtFjÔNg|š’TËõ4Ýa›j碔„ñÍÉÑù7ªE5æj3^­3ÿ·¨2ÕÊýD°SC5q£„ß5ò}×;ïF5þè ýEÆ7gG5‡ 3ÞÝ¥©VšWc6Ñ÷M¯?ѾÝY½Z´ß|#Ë£Ú¯¼`§š¼tÎj™Òºå§Œ´ðÎ'R­jª.|Ÿj«R©ÕÌf|*A(ç‹»Wûº¤O+Ç+8$üžº£’:·HçH-ŒOk·œðN/øEÝPÍmªíM¥ U¿‚„û !† iAÛ1ª•IµÉw é@Ýç Í[ªIçRéü*•dPMt­àW9á›ô÷U…4¡Ú»µ…tñ ×¶ýÆ ¿ÌÁo™±ç^ɉ#ù •ŸîËŸ^ó¬„ãn{~õ£vŸìWÿÎ/Æ„œïáYzöƒÆÕúRZï?óÂèžùnþë[ååjx¶ïß^{´H϶²U§æéSÉ3¸[«2;Ÿðìuß\qõçÇüõ…?*7l¼gUÈ‘õßݽÎoOn6¨îñù~úuúmÜ~õÔ6Sóüw6›ðõû¼çÄ¢›Ái7ùýúü¥êýqÓ³¦×ðÇVÏê íú´Ïó§?ë¿I›ûùÝžz[™]לU=s÷ÖýØ®?¿ú—jî%¼í™—öF›ME®ó³>ìÑ+´Ê3Ϻ/Ò«žlz„_ò~‰ÜâjzNHÞÙn ‘ßv¤?åöNÏ–È­ö}sœ_}½cõ•ývñé_ÖޕϳziĖ˦ò³Vk׸Ižuó,\Òq?¿TµzÄ7U¾÷Y·Û¶øýü¶K;ŽŸ>š_8½g÷‹A=+‹V0œ]]•_y{áäoߘƟcÓ0D ¿gX‹c§ó÷ùE“‡Ì³ÄÍñLÖõi_eÓwü’[©Ú·ÍËø}yÕ‹T·ìžEa¥Š¾µ¹²g{ÌÛ} ÛyÖ]1gÓ&üúÓg¹*^äO”­ñó„^µù•–Á®z‡*y–®9µxÇŠ+üޱk?™ø¿õã»~Ì{’n–zÜøDqÏÚeCÚ?rƒ‘·½:/ð÷j·°&¹}ݯü·ÝŽÕ_ˆàÞõ¿9ÕÿñXü§’ÿ¯û©8±¸-quê×ÅX»cmngHíÚâ|¿©Ížæ°¹ñHœ®7µµºÓ&YCjû%7y»c¬Šñl‚ï{â4¿©‹ï1‰Ò„ÜÒÓ’œýSéÏk‡z(Jr·±§&ÛúY±—Æ. é)Vž˜ý´Ç%Ú’¥Ž$Ѩ“ 1’ÈlëͰ ªÑÁkÇÐÎÅwÆÆÔ±SâM®NéÑNŒíx&Æ%WËTkRjªÓ!I c[šÛn“xmŒôNƒK¾•»±3>Öêpö³JRUöÐÝ·Ãé›?º­±­¶~ÒüÈü(W³d›w‚ÏD Œ¾³3EG=AÈýéÝ9ÙŸŠr°þ+š:Ðy~úqÿuÍíÉÒ uBœÓ¼ïOÀ¶´,`ü.-om­„§%HÓ¦¹ÛéLKH·§JÓÆ;¦÷®úbJçoît ²&#ÿ:#cR%©ÆuO—䈡Kº·,øÃš«™ÕMç‰Ò‹èŸdsûJ–¿t·¥ ²%K~ilR9"9Zšˆ¦VVGjªÍ!ù”±±³¿Íðø¥•ÆÎƒb ”†Ð‘fM±[¥GZÀįç‰Lv¦ÅÙ’½)YßÖÆnkltº{ ž‰EQ߯Ù…Î/<5tpL²IËjK^ºrg<«c¶zí¸µ?ʹ$ÆG’Æ ÔóG Âè|®üe¬ƒÝаŒ´qؽ¥²®?2ÍíŒK×ĒjlæU¥e³ƒÓžl³Ê2¶ƒÍm$My”Ë$ïשô]è{÷6>"ìK|FØóx—°WñÂõ˜p=*¸?%<ûQøÍQÁ~Râþ¤`Ž îöLÞ+ÜŸöYÞ!q¿[øý‰ñ·§û9‰›S¾ˇ…=”Þ }·EØ—ù„àžß;“^_/ØbêS¸ïÔåE-A5ßÚ~ÞšnQ¹§VMkÀñÎ-ø“¶‚Êbˆ:xõ†Sd­Ð:ÍjY‚š4iÒòE Kž8ïŸE/\MfïŸ%ÿíÛ·¯‡Þô¿Ï¯xolYab§?¶òçt.eNžla«U«œ· ¥ZÄauŽE[Jç™}ð¡‹…MËýM›vC,êÜ®¼²¸‡…‹l5£àËþïÒ& öJʈØ^¼Eçt:ŽþÄ¢9HÿYò ï¹s~;2ë²¥`ÅFµyÖ ß7ÎÛôüØ„RÍìa§ŽîÛka„߉¿7L§_XØKÍ—tÉä{îWÍz&·[L£ƒïØÂ?˜Ø²Âü›ƒÅ÷–“SæÞ‹1X4—ßJziä-E«ü±}ü;U-EìG§¶Œ³¨ïõð/râ9§ôá”w,ùê.xp®TŒ%ÏjËÀ·ç¿ãO‘ KŒuž³:^*â臖b¥7t¼ùI‹±óÞŠü×ÅðYŒÂU·vøÓØÛ­,šy'÷wüª;ÿ´Ô¼>Oû™ø»–[êøÞ–+W®Æ”j­£k‘ï Ì÷—‡®ƒ–lÞæ’¥qâ΃åºß±Ô=µÍ¶ÙµÂÒæÉÜa‹î÷´D¦,ë–—±8*‘ô†…†Z o=:…¹`©»¢JÒ¿íµ4^Yqçèo-óçÏ_òç$KØØ™ó÷<}ÃÒ¤ìŠ*Ö™Œ¥UÛëß…<=i‰´Ûí¶Y‹³íõíGZ†O«ýþ±&ë,æ>Çt‰]eqŽ)w8➥þ¸ ê›ÍM–ˆ2Gæ{溥~í3ç×t©néÒvTÈãì–ç;œš4¿¾¥³qÓέ™wî KäÁiU Ï[m‰h·óVå-åKöÝYÆÒXs½ßàÕ- × ¤=·DÞ9XéÂÄC–†œ†žëCKÓ.~¿c¹ii6sàµ9òZêXÕ0ø×–âû~³K³GÒÕbÎU{GáÄ–nC}Ï£»víß`Ž%YGxïMÎ\ciûi½ËcN涸G/^¼æ«Ž–”¥q«K¸fYlAßÌj=º±¥Þ{TZý¥%¤ÄóÅWKU·Ôyëq噋[Þ­Ð31QUÉÒeüÇÿ˜»ÊÒÿÅ›-ª5|ÓҦɭv{¶ð¶éA«o°Ÿ=ìYúéSKÑÐßÜÛ2ÞRÿxå/ÊtZš4º¸i¹Ò–ï»äm}¨·¥ê¼_û-QÍÒ|î„E—ò²4¹7„ë³½ž%a厵oö²´îÕ«WCŠ¥Ëˆßo]›eË?rMÐóíÏWò3#o|Ð%×%~ágÓgvÙs‰Ÿøõå‚á·óC¯MŸ1æÈ}¾oK†“Çgñóò[ŸÇèqÿP¯ÿÕ¾qïUŸ·Ÿµ6¶ùþ Ýø%_T¸ÉV ãg ú½À©®¿ó“ç5*QfHþËÏèO}|˜ÿºBŦK«šønÛ¹þû{üŠÆGü6¥ïJi3·Ïð©ü‚o«ÎˆT‰ŸýÁ\…rñßäŸ|xÈÁøÑµúÝþÆ5Ÿÿ¤Á°e3ŒàÇæá^<\‰ïoŒüªvéüŒ'¸^Ï?»ÎñgPM~ÇðªÏ×~ÁÏ|1ârr—âüü ý?-~¸ ?cWë·„ýÈÏoÿ|gÃ7ñÓö¾;e?~Ú[Ý«¬üžç }oÌ›mâWFhò”ö!?õž¹Ó‡3®ò+®­|±™ÂÝæ“#ŠóC>ZÚêøŽb¼{äÊâ¿ýñ¿ØñÝ£}\å'òÆDoû”OºÒ¤øäoûð}®hðóÃÎüöiÓø…5wŒ=Wj!¿ònj™wâÖ𫵿÷ÓÐ?øô¿ÿåèü¨ÓÚD½ƒ·}xëåW5çó“‚{W›ty$?G·!íÆ}ø=“¬êå“ÎðÇŸ”~ù‡ã ~AʨÑ%¶äægtº·âI)¿2¤…~Þºü¦ öíoîÕñSƒSúOy¿5ÿEçË“J}ŧçX³Ç½yü¤C¿›Yq?êçJÖǾ“hË©r Ñ7WŠèÙ^î¿$¼÷qµÝýIr3¿eÓGò5oÁ_rÝ]^àb$&÷Os=ËϯQÕ;ï°‡_<º åýu=K/w]v…îã.´?3/ÝI%Ûžó_ooé~m°gûo»×Ø£x¶5œ]ô½ÉÅ<ƒ»Å®~™0׳—xR&-mʬZçÞ¶Î%=«ê§k?ˆšÍogÙŸÇÕŠï×hظ¼öGüêYìÝÙˆÿîlív¹6Žä £ÿp¬­¿?®õ¬¯OMô¬±¶®ßʳzúâ+ë Oõ‡cý†=lÑ]µ2fŸŽŽ*<æåüê[Ëèæ ÷Ìë÷g¾#ûŠð³>þ¥fÓ[•<ë}¶îâ¶¼ü’a—Ögöœø¥þÑ;Ü.~Ûmõº¼ éž-ÖúÕnßâøÕ÷*¨Yú*¿±ŒvÏÞo§yV»ý~ô¶–ü¬5«Hù„žuk+[ó¾}‘_ªÿÉ=¢N.ÏÑ’ôAñåùm/¯¶‹¸[_8Óüþ¢?‡zV–šüpØÔÏø•^ªêÍNæ/4ôé¡™7Åð{†µxɨc>çM¿;9aÒÏd½nëíÝíù%÷Ç..ùà#~_ô¯úrû“=‹t=4 êtÏöaµ¬ñ‘gÝŸoÕÿ¬wk~ýÙ'ŠM?ÊŸ¸¿0ýàéüÊf…¾kUƳtó¸_·>îÁïø¶ÆðÆ}Ãù­ ÷¾¿åÙKOÒÍ ÷.Iô¬Ýôýô†—n(¸¢Z˜ÿÃ{lȸ'$TâøE%öüUâ J%ŽTâ`B%öûUâ`B%j0ªÄaë-°þ±ëV°þ!ëW&eýФ¬_‰”õ+²~åQÖ¯8Êú•FY¿Â(ëWeýŠ¢¬_I”õ+ˆ²~åPÖ¯Êú•BY¿B(ëWeýŠ ¬_ ”õ+€²~åOÖ¯øÉú•>Y¿Â'ëWödýŠž¬_É“õ+x²~åNÖ¯ØÉú•:Y¿B'ëWædCý~„úýõûæ÷#ÌïG˜ß0¿a~?Âü~„ùýóûæ÷#ÌïG¸ßp¿á~?Âý~„ûý{m]¬ åó{Ž=Çþ¿k÷5ÕCßþIÿˆÉJæ %³Jætysº¼9]^æÿ¥.¯Lw5çïþ/gf0Ãøº:6Nïº`+ãÙ>ôò••$Ú^ßµŸÑüç÷_ìíUf‹çô‹ƒooð‹çÒ{½Í%RçñÇ×hZÓþçÑÝ\ߨû­ç÷¯ïW¾0o1ÿcJžƒm·ïåŸOüNëG§<çzï¾âÊÇü¹ýVçÇÞöüÞùRÉ)ïÿá¹y!²¹æ#ÏÓàÊ5¢» ò<µ5ÏÌ÷¡H¥!aÍæYT³Ï lñs{þzõ·ºœœà¹•ÈzýŠ?ð¼Ý7úG_ñw;·>¢ýîÏ£õFôkøˆ¿s±wÁ1+ÆóßU³ª«sÿlRž“¹~/á¹<ªÖ£äºgï¼Ø·çþÔÐ3ûϵFLjÂß+Zs_òÄéž{›‹ šÜåGÏ/Ï:§–œìy<çåÑfŸ,å_Lødü¤©_xvx»oÁ+,šîcj—)ñܳ—Ä4þÈ}Òsce­&Õ?_å¹u·ÑôÊ}<»ߘôö Æsѹ±c;Ž÷ìÖÜ îvhµÐ¾[S~êù=ÁÓó½ÁzÖŸLeß\º‹¸-bÞ¬…Áž‡M¹âq!<—Úé¿jô˜ç³×z¿×1ÔsñÀ{Ç9v¢Ê÷lI»™óù£®ý¿p4ð鿸ÜôS<[¦}óFÄžø›^ëÑü½SƒŽÕÊsßóÇÛ?…¬Ý»’¿5{Ðá3#<¿ ïøÝ­¨“ž?­+®„÷ ³¨4ÜœNé3ngY Å.©ºNM±¡ɸ5g܆f܆e܆gÜÖ͸­—q[ß«©S[r_Gr"¹7KîC%÷a’ûpÉ}]É}=ɽÄ߉¿!C$þ†Hü ‘ø"ñ7DâoˆÄ߉¿!ÍÍÍÍÍÍÍÍÍÍC%þ†Jü •ø*ñ7Tâo¨ÄßP‰¿¡C%þ†Jü “ø&ñ7Lâo˜Äß0‰¿aÃ$þ†Iü “ø&ñ7\âo¸Äßp‰¿áÃ%þ†SwŠtK‘šqn«w±A&’¼5˜°C ­e-•bOM°¯pbð/q3höš3jE[ZÍ8#¯®Œu‚ss9Oržä<ÉyòŸ¢Øº*¥_:èÒ}Òh­Æµ[Îõ÷ª()y…BM—5Í» €w_õœ™Ÿ¡I¥’n+¦‹²#ÆÆ¹rRî_K9ZE±9új9új}µ¿\zô.·ÓåLõoÁäü1Š4â|&§#s•\¥Dã ¾ýÜ; äDçí(¸S„–ŽQLÒ¿L›s·çù2ÕûŽ6¢wþy]TxÀµ:ÕNgÎå{¹ö°%¼XÐüÏeÜ?‚ɼ%¾PÇfÚ?ˆÉ™¡õßçÌÐúîÿ'ghe3³¦*-tsJ›+­*#?0"gSýœ«ð÷90$.N<0$(Ãÿk#†ö 5EÊãìl±x=@¹Ë9=ÐPÞ˜G´MKwÐŽ$m.ç’(N™ û PA¡‹àÚ¢®B€-…kQáZR¸ ×rµ‚p­$\«Wa;5˵¦p­-\ë×áj®¡Â5L¸† ׺µžp­/\׆µ‘p}S¸¾%\yáj¯C}W¡Sb‰ì{cÁ)Ø#{ÁÞD°7ìM{3ÁÞL°7ìÍ{ ÁÞB°·ì-{+ÁÞJ°·ì­{ÁÞF°·ìm{;ÁÞN°·ìí{ÁÞÁâ»ÉtvKl¬÷,’¬ÎûÑ óS¯Ñçd˜W^Ãöê$ë/²9ýE&p±qNšx묬úËúËÊ;:¯š…¿/!XCäV³Ü*·†É­árk]¹µžÜêß©CFm…½ŽÂ¢°›öP…=LaWØë*ìõvEøBá Q„/D¾EøBá Q„/D¾EøBá Q„ϬŸY>³"|fEøÌŠð™á3+ÂgV„ϬŸY¾PEøBá U„/T¾PEøBá U„/T¾PEøBá S„/L¾0EøÂá S„/L¾0EøÂá S„/L¾pEøÂá W„/\¾pEøDuçœÁAÎU~ýÏ X‡¸¥ÊÂH=Îèç÷ 0yöãk°iÃOWú±Á¦ÚHÒNm´Ë_¥'mÈÅŽmÄk3¾F—vhÃL;´“@ãÒBDhãN}Ú)(Ádth#OfÚÀÓÆ˜6ö´‘§;í4ÐŽí„ )Ìø:´ÓAnÚÑ  ?$íÐŽ mØiC/vhšÐÎ íXÐŽí¼ÐNíc‚ÿõάC8‡ù÷棘‡Y埘wÙå—2¯^•G4ļ¡ùR›ùÛQoÇœŽéøŽ é8‚NÇ{tŒGÇut,GÇotÌFÇitlÖñãE‡Ht;#º¥.ÝÚ—Û%õÕ“ñm•K £ÇzÑ£Èè_t{á>0V˜h˜:v£3t[c:ÚO€±3¾-“ß6Ä)Œo{b'Œ ¦/ãÛ™NGÐIzR=Œ­?ãÛ"y ãÛ^x0ãÛZø=ºíùŒo±ç‡Œ·~ Ø!ÿúò¯… /—O5¾¦ô¬1é3s€g¡ž…xàYÝÏêxæßªRòÌß]—=¬èaH ‡æ@C= ô0<ÐúÖ ô0PŒBÅ($PŒBÅ($PŒBÅ($PŒBÅ($PŒBÅ($PŒÌbd#s ™ÅÈ(Fæ@12Š‘9PŒÌbd£Ð@1 £Ð@1 £Ð@1 #ÿ£°ð0ð1mEýoŸÖ&þ:ð¡m%„·¯8»­¸à$ë#ÜD/ŸäV<ó[…%¯:×­‚àæ¯ïVJpûÊSÞŠ޲8ìM uÖg¾\dyô›ß‡À'À‰>d}\A1 ΃?žÅ±pÊ׊ÓáÄ×Y'&à+ÏŠCèȸÂòwŠ“ã‚Ä"«8@N,ÊY#WDö>ÓqrbY~Å©rbšg}¸œõWž1'F=ÐQs)ðĹBò×òƒçü%&ðùsòיޡ+&{à4º¢2™¥+ {/;›®˜?m³8¢®Œ$^¯8©N BVÖù NÀsë2Š\æãë‚ÅwÙœbWÜ“¬³} t¦˜}¶ë±Wp'&@V݉ï³:ïN @Àcï Ë_*N¿+¨xë;OH•Ô¾î´*âzÁª5ý+ý¶Y»ÉÖ…9[¡ÙºËÖEx¶.êfë¢^¶.ÄŽB‰¬S¬vöNêdï$${'æì„fï$,{'áÙ;©›½“zÙ;É>uC²OÝìS7$ûÔ É>uC²OÝìS7$ûÔ É>uC²OÝìSל}êš³O]sö©kÎ>uÍÙ§®9ûÔ5gŸºæìSל}êš³OÝÐìS74ûÔ Í>uC³OÝÐìS74ûÔ Í>uC³OÝÐìS74ûÔ Ë>uòOݰìS7,ûÔ Ë>uòOݰìS7,ûÔ Ë>uòOÝðìS7<ûÔ Ï>uóOÝðìS7“Àé£ÿkAGÎõ¿äº¥T™rÞÍïV%0íì;üAà Ïò›EùmMJõbçC~}ãrÆäß[ò+§Ôšÿûî7ù}]¯œ:¯°Â]Ý¢ù]ÇwTØ—4„ß=¼f­*ïwämh6øCgM~çÃGq5];ùíot½ü°O¿+zçê§[fò{’æÎÜ:±?·àŠÚ3.ŒæÏ>³ï׉7ù•á­ÂÇæ~ÄïÐH³>ê%¿ûÊ™a?ZÁx#O‡-?ç·ÜKM2 Åo j3:¨c þ»?¦=¹7š_cÛµýðÇü®*C'*eæwïð4¾œ¼„?ýÒôeôíküî&?]ï­{ÂïO;Tõ3'¿«`¤g]éüþRýwí9ÕßÙ¹€©z›füŽU¿ß)º1‰?8¡èmû“ ü‘`kdÌçOùoæ9Öì!øþÉZ“ AüfwHo6¤¿öíÅݪ\0ò«ê¥¬R7¨Ä*Ô£lHçh~[áýÎìƒ_vñKgMcq~å†eÊN½Ë¯¹r7áŸÙü£)Ÿwˆ¬Äé÷2ÏÊ_ßã<8¹¸z¥‹üíÒÎÉíßæ·l/LN.ûœ_Üðù¹vo1ü¶÷»ÙÐäg~¯¶bá-÷ðgû¹—ïQþçŽÏצá÷ï¯y¢Ù°îüÎ_WÓvŽå Š^±ó0»ø]4­—ýo9¯U|©‰qöKB!M!Õë¥PÀíe´ô\å´XÑËm÷Ïœ)]g|¦W2†ûB¸t9šs9šs=Mr4çr4çr4çr4çr4çr®ÿýšsÊUþ~f“©Ÿ)û’Ú›ÀÞ]O-Ù˜ïïœé#ëÀéÄ~i/1Ž8ÿ^·x«le¨õ->ÝOºs_ï`5%«v”}@•[’êL:†n1}Ä=ÊAíÚ{»šTE)«E¼pãíJݨn24w.¹tW¬5Í&¤—VŒ†X'©jgý¤¶²ÿëKE_ Õ’Ò¡ø“/\iÞÉ×¹ö•QuÎÀ'ëÏßH™ŒÌ2ÿ¿/3ò ¨9Õg9{´úw¹•WZý¨Þ‘#Æ&ÛôT-ÆP¶Qo-ù¼.½Iu%£!ÉbºWÑØÈ7Mp¸Å=Õ’à)kJo{‘á¬# IœÅ%3Š:0pÃìÿI.G|jš;=&-Ý-Û¢–Uºs§8cmÉ5¥«X'OÉôÔ*ò¤¨Úà/¥E®X{jZM—Ûçmðƒ¤¥'Þš)@4(5}[+\ë³Øs-7%»Ãš\3«/L©i1éi.§ÝáÝt÷U Ž¿êR“‚>“‰kEóœ–ÍWrÉöPÎÙ|?çOö§(MTo\Ò1–÷•bíÖxZ¿²¸Éöòþkxqm»YS»R5uEóã_²°¿ˆŠÇåt¤ÚúåïyûŸäuºíñ^Š_—}ágn´P¨¼¸,zôº8§;…*&y_kñÚ(lwÃÑ+ž• ´ýMF°ÜVG¬3åµ|`žË}0ò!OFÄé~ËpÍÔEË4±Ü±kDç–LÖÝ}±½Uí&&:¸3¸p¦üÂŽ:55Õ)ZMˆGšÝáL±û˜<gÚ@[ZT›=:=Y|j² @)²9Ò2šblå~œx$÷ Ÿð5¼0ždþ¦è|]ñeà »üÃA~—òïô?ÏüuÐ@‰ßLH—Ó0(Mñ ÞæD»ê¶Çø]Xå.ŒƒìÑòô3¤%Ðñɱ¢¯ƒìiÎhÿ6ÿ:Ç ï/pjs÷³ÅÊ85È[t±" í½¸m–GH6î—>ô”‡dyÌ@GHÏ>QÃw„I ^Pu% ¯ž²îÈ8î_¨>2yÂIœ«ªKê”L/xȦ§xª¡:FìF+ó'cè!}/ÉPÙø¤‚¬ñUÈTìòTÊ4̯¬¨9Y³!Ê1þ{Ž Ì±çØsìÿ‡GvʇԾʊ„}òœÓ+sN¯ôž^)oG+([F[||=DñÜ{¶RæFIãsª¦ócE$'cR¾(æ§b{*æ§"þú‚¡kƒéPŽŠö©HŸ®n*˜Â7è:aª.@×ÓuÅtMrÁеÇTE€ª ÐuÊ…ïZŸ A{át}òÛ‚û¦Âs:*h.„®e¦cNª^@×4‹ë”ë ~RUƒÂwú0¾uÊt½2]»L×EwâJUèZçBø{*2}Äž˜ta°Vº"X+] ¬•®ÖJÿj¥«~µÒå¾Zé:_N¶À—“­ìådKz9ÙZ^N¶ˆ—“­ÞådËv9Ùz]N¶P—“­ÐådKs9Ùš\N¶—“­ÂådËo9Ùº[N¶à–“­´ådKl9ÙÚZN¶¨–“­¦ådËh9ÙúYN¶p–“­˜ådKe9ÙYN¶8–“­ŠådËa9Ù:XN¶–“­|ådK^9ÙZWN¶È5oàÕ­ù²ZÖš7ðzÖ‚¯XÈZ ë¬y/]-õšÕB¯Z¬Z꯬R-üÊå©AY¬K-õ‚ÔüY®D Êb j¬×žæ´è4(‹Õ¦AY,3 Êb}iáW.,ÍhEiÞÀKI Ê5¤ù²Z<”Ūт¯X.Z ëu¢…_¹@4w •¡AY, Íp-hP‹@ƒ²Xý™?ËeŸù²Zï™+ÀBÏüY®ð,šÍÒÎ|Y­éÌx1gî@«8‹e·|³@Öë6sZ°™'àJÍB¯Z¢™/«µ™ù²Z”™'àj̼—aæ–¯¿ü :²Qt¡î ö4[·³?H¦å·â·[8ÓSmЇ\$­"Å©¢üMiªÚ¬ŽàèdkLR´Ý-ÎQìd‹­ÑßîˆÇg3½kî¶YÓj¤YíÉxïÆÛdS/&QIÈúQP;§;-=8ÙêêŸqz¢¦Sz\œpolœœnCæ´Šeù:»œiÈ…Ô`ª‘œñ³\4R±Öàx§3Õ_Í!jÞœ„ÆÂmKÎæyþž(¦Îþ5’Ñ‘¤±’LL6¦Éœêtă‘$á©®ƒÍçìï?^“†68Í?©—«…ÍMÕ1¤*ÚÆFÛ/_zÖˆÆrt­ð(Ö*f•É—²¤ ð(Ò™‚z0¸ =©F(ké<,Jî2¨ÂS#Úžœ,÷–kkwÙm^ )Ž ŽÉ(320—/ )V7*WáY!lÖØ¥&+ï'o¾ÆÞD¾%qžËZY^Hƒ¬²9wç»c`pŒ³¿$hù"ñ®¬®`’.Ý¥¼Ý­ýà=D+*¢T刬|´Ôˆs:ÓhäÎh² bõœhµÅÛüŠH´±¨cƒã’ÆXé±²â«\9k TFŒ x©CñIE×¥F¼›Á+MZ‡Í[ \H³TTMYg^vå0Ÿ¿VPp–§¹¯+á}.ˬÊ#d‹Ë‰ÆÆŸØ¦.éq4‰bÓcÄÌÎ%Ý«t—øUñ™ÃÙ_–Ùù"Ð ¡Ý/1gýUl¡_ì²ÇÛüò¯¬# 4vfU“åB+É)6Äù;9c’œ.B&/*¯¨?P•·JGñ¶y+ …,™ÿ¸IýRcFyüöÏWÏß{såGü»{ƒöìÚÇÿ`œÙû°Ã3¼bžµ§ï½ð_gŽ^s-¾ï4þ mtȃ–ü¿Ÿ~}Ï™–´ü ¾p¡¤²ážo¿ho;7ýMñʯ›«)u=‚?Ñðùxr–ß:,âaù›òŸ­plÃÖ|ü"ײޓO‡ó+?n1÷ëYAüü:Éú-ßùxM§˜ëßWõûóá—Çœ|^Ø#†÷Û:¥â꯬×*wÍjóùEæâßwl$†×ÿ»Ã ßÜÔa¿¢À¾1w[Äpøß“ÂÚý½ËF‹v¸çTMìîúˆ_öóŒ{¹”_ß­dåñe»‹éçÙ~¦mŸNî1ž•–BÃZ/šÃÕûñÂÌùþïÙ9bóî+~ÛÓ%ó'uýL™žügc—Ï›¶ “Å?£ÉæÝ¤ho~vsÍí™ ñsÍ‹¿¹Æ3gtÜ•ó¿ŸÉýÑZÇk7øa?ÿÁ»¿Þ}bâ竾pÙµºþôÿvÊ-O*Ðݼ‚˜Œ&ëG{B¶¿iÓ¤XýµUV÷ÿì×þÝ÷?´ÿd ÿÿµØükßøoëß Ñß ÿ¸]Øó9ã›Åëûhzô ãÛeÎÔÑn5Õ~¢»õM‡¹3ŒñîÒ§¡‹`rÝÅ•0¾Y8:ãö3¾3ˆñjŪ–H¾E%T÷ÁN uF ¿käû®w¦ ïTt±ÓEÆ7K׆aØÂðáSm€}"ãÛ1°ºàêCí6Ø'Áld|3Œ4ntön1ã›ñ£vºK %<Áøv ü)#-¼3ˆt]0.|ÿã[4ER3¾…Rùß)a'Rö+Æ·ðêð{êŽ.º¢³‰tVÔ3Sø}§ü¢nèB+º8‹.´ª"ø$Ü é4LH ÚŽÕC|éâ¯ÝB:P÷yCó¶)ÞÓÙS:£JzÑ…cZÁ¯rÂ7éï« i²ñÍèŠÛ¾FðÛ~ã†_æà·ÌØs¯äÄ‘ü…ŽÊO÷ŒåO¯yVÂq·=¿úQ»Oö«çcBÎwð,=ûAãj}ï0Â?óÂèžùnþë[ååjx¶ïß^{´H϶²U§æéSÉ3¸[«2;Ÿðìuß\qõçÇüõ…?*7l¼gUÈ‘õßݽÎoOn6¨îñù~úuúmÜ~õÔ6Sóüw6›ðõû¼çÄ¢›Ái7ùýúü¥êýqÓ³¦×ðÇVÏê íú´Ïó§?ë¿I›ûùÝÇêî­û±]~õ/ÕÜK>xÛ3/í6›Š\çg}Ø£Wh•gžu_¤W=Ùô¿äý¹ÅÕôœ(¼³Ý@#¿íH~Êíž-‘3Zíûæ8¿úzÇê+ûíâ7Ó¿¬½+ŸgõÒˆ-—Låg­*þÖ®q“<ëæ?X¸¤ã~~©jõˆoª|ï9²n·mñû;ùm—v?9|4¿pzÏîƒzV­`8»º*¿òöÂÉß¾1?Ç,:?¦aˆ~ϰÇ>Nçïó‹&™g‰›ã™¬ëӾʦïø%·Rµo›—ñûòª©nÙ=‹ÂJ}kseÏö˜·û¶ó¬»:bΦ;Møõ§/ÎrU¼ÈŸ([ãç ½jó+-ƒ]õUò,]sjñŽWøc×~22ñ+~ëÇvý2˜÷$Ý,õ¸ñ‰âžµË†´~ä#o{5t^à5îÕnÿ`Mrûº_ùo»«¿Áÿ¼ësªÿã±øO%ÿ_÷S¡•у¸:õë‰b ¬é²gHíÚâ|¿©Ížæ°¹ñHœ®7µµºÓ&YCjû%7y»c¬Šñl‚ï{â4¿©‹ï1ù÷Øì”ž–äìŸJ^;,ÐCÿvšmì©É¶~VG¬Ä¥±KBzŠÕ'fíq‰¶d©#I4êdDÃ_GŒ$²Ûzg3lƒjt°ÆÚ14‡sñ±1uì”x“«Sz´cc;ž‰qÉÕ2ÕšDuÁ$)aì@ÕÅl¯‘ÞipÉ·r7vÆÇZÎ~VIªÊú£áv8½qóG·±5v ÕÖOš™åj–lóN0à™MaggŠ4Žz: ‚ûÓ»s²5>*ä`ýW>4u óüôãþëšÛ“¥Aê„8§y3ÞŸ€miYÀø]ZÞÚZ1OK¦Ms·Ó™–nO•¦wLï+\õÅ”ÎßÜédMFþuFƤJRëž.ÉC—toYð‡5W3«›Î;¥ Ñ?Éæö•,!ènKdK–üÒØ¤rDr´4M­¬ŽÔT›Cò)ccg›áñK+Å ( ¡)"Íšb·J Ž´€‰_Ï™ìL‹³%{S²¾?¬ÝÖØèt÷@<ó/@mãì‡Bçž:¸&Ù¤eµ ‰%/]¹3žÕ1[=ŒöGÜÚå\c„#ÉaCêù#át>Wþ2ÖÁî EXFÚ8ìÞRéߺ1@s;ãÒð%±¤›9AÕ@iÙìà´§F'Û¬²Œí`sÛISå2Éûu*ozÁº0G`NœA¯Z· =fÝÂõ˜p=*¸?%<ûQøÍQÁ~Râþ¤`Ž îÑóÖíÌOÂ;ð=Ñýná÷g$nÄßžìç$n賃0‡aÎ á¡ïÎ †¾ÛsHxNÝá{g2Â+{kêS¸ïÔåE-A5ßÚ~ÞšnQ¹§VMkÀñÎ-ø“¶‚Êbˆ:xõ†Sd­Ð:ÍjY‚š4iÒòE Kž8ïŸE/\MfïŸ%ÿíÛ·¯‡Þô¿Ï¯xolYab§?¶òçt.eNžla«U«œ· ¥ZÄauŽE[Jç™}ð¡‹…MËýM›vC,êÜ®¼²¸‡…‹l5£àËþïÒ& öJʈØ^¼Eçt:ŽþÄ¢9HÿYò ï¹s~;2ë²¥`ÅFµyÖ ß7ÎÛôüØ„RÍìa§ŽîÛka„߉¿7L§_XØKÍ—tÉä{î_ÚóLn·˜F9ß9°…0±e…ù7‹ï-&§Ì½c°h.¿•ôÒÈ[ŠVùcûøwªZŠØ„OmgQßëá)^ä†EsN;éÃ)ïXòÕ]ðà\©KžÕ–oÏÇž"6–ë¼Í%KãÄËu¿c©{j›m³k…¥Í“¹ÃÝïi‰2LYÖ-/cqT"é µ4Þzt sÁRwE•¤Ûki¼2²âÎÑßZ"æÏŸ¿äÏI–°±3çïyú†¥IÙU¬3K«¶×¿ yzÒi·Ûm³",gÛëÛ´ ŸVûýcMÖYÌ}Ž7è»ÊâS(îpÄ=KýqÔ7››,eŽÌÿöÌuKýÚgίéRÝÒ¥í¨Ç?Ø-=Îw85i~}Kg!â¦[3ïÜ–ȃӪž·ÚÑnç­Ë[Ê—ì»'8²Œ¥±æz¿Á«;[$8®H{n‰¼s°Ò…‰‡, 9 ;=ׇ–¦]ü~ÇrÓÒlæÀks&äµÔ-°ªað¯=,!Ä÷ýf—f><¤«Åœ«öŽÂ‰ ,݆úžGwíÚ5¾ÁK²ŽðÞ›:=œ¹ÆÒöÓz—ÇœÌmq^¼xÍW-)KãV—pͲ؂¾™ÕztcK½7 ö¨´úKKH‰ç‹¯–ªn©óÖãÊ3¶¼[¡gb¢ª’¥Ëø/þ1w•¥ÿ‹7[Tkø¦¥M“[íö6(lámÓƒV/Þ` >{سôÓ§–¢¡5¾¹·e¼¥þñÊ_”;é´4itÿpÓr¥-!ßwÉÛúPoKÕy¿ö-Z¢š¥ùÜ ‹.ådiro×g{=KÂÊjßìeiÝ«W¯.†K—¿ßº6ËÊäèÞåèÞÉtïüúqªów6,¸ÚnŠþ$¹¿™ß²éƒ#ùš·à/¹î./p1’?“ûƒ§¹žåçרêwØÃ/]Ðòþºž¥—».»¢_ÇüÌKwRɶçü×›Ç[º_ìÙþÛî5ö¨žm g}or1Ïàn±«_&Ìõì%ž”IK›ò«Ö¹·­sIϪúéÚ¢fóÛÇYöçqµâû56.¯ý¿zÖ{÷E6â¿;[»]®#yÂè?k«Ãïk=ëëS=k¬ƒ-‡ë·ò¬ž¾øÊºÂSýáX¿a[tW­ŒÙ§££ yù¿úÖã2ºyÃ=óúý™ïȾ"ü¬©ÙôV%ϺEŸ­»¸-/¿dØ¥õGç™='~©ô·‹ßv[½.oBºg‹µ~µÛ·8~õ½Êj–¾Êo,£Ý³÷ÛižÕßn¿½­%?kÍ*R>a„gÝÚÊÖ¼o_ä—êr¨“Ës´d#}P|y~ÛË«í"îVçÎ4¿¿èÏ¡ž•¥&?6õ3~僗ªz³“ù Í}zhæM1üža-^2ê˜ÏùEÓïNN˜4À3Y¯Ûz{w{~Éý±‹K>øˆßý«¾ÜþdÏ¢] ¨:ݳ}XÅA-k|äY÷ç[õ?ëÝš_cö‰bÓò'î/L?xº¿²Y¡ïšF•ñ,Ý<î×­{ð;¾­1¼qßp~ë½ïoyöÒ“t³Âý‡K=k7}?½á¥ ®¨~êÿø–X~®Ä ‰Œ­(Äž¿JD©ÄÑJL¨Ä~¿JL¨D F•8ìaý£Ö?6býà Ö?Dcýʤ¬_‘”õ+‘²~RÖ¯<ÊúGY¿Ò(ëWeýÊ¢¬_Q”õ+‰²~QÖ¯ÊúCY¿R(ëWeýÊ ¬_”õ+²~PÖ¯üÉú?Y¿Ò'ëWødýÊž¬_Ñ“õ+y²~OÖ¯ÜÉú;Y¿R'ëWèdýÊœ¬S'Ö¿ëßȉõoáÄú7obýÛ6±þ ›XÿVM¬“&Ö¿=ëߘ‰õoÉÄú7cbýÛ0±þ ˜XÿÖK¬Ó%Ö¿Ý+n´”MužÓ,f˜œò9Ò¿œ!DÎ"«!DNW'§«“ÓÕaþ_êêä4ï9Ò¿œ®¯¢ë›3«“3«ã›Õvd½µi±6•mÚ¦îìݵm±vq1œ®­ÍššîÕµílññ¢¦£¡]Lr:â‹ÔM;‹ 4]2ö1ÕuNKز‰øª§Í*:S‰Ù¦íÄÐÒ‚oÞDÅðÊö”‘m7“å®0Yî<£ÜW&ÓÆ3Òc|O²ØaF²‡7[ÐniWPÃø <3›é(1†Þ·-_ù¶•bC-ÿB¬L®îw+èKey˜4bÞõ³ºf,¸Ðõ“¥¯ÖÛÏŸ—º4;Ô*YÝÞZÙ¥T×ño¯ɸ5g܆f܆e܆gÜÖ͸­—q[ß«©S[r_Gr"¹7KîC%÷a’ûpÉ}]É}=ɽÄ߉¿!C$þ†Hü ‘ø"ñ7DâoˆÄ߉¿!ÍÍÍÍÍÍÍÍÍÍC%þ†Jü •ø*ñ7Tâo¨ÄßP‰¿¡C%þ†Jü “ø&ñ7Lâo˜Äß0‰¿aÃ$þ†Iü “ø&ñ7\âo¸Äßp‰¿áÃ%þ†Swjt㇚qn«WI\¹5’ÿ¼-“Å .ÂÆÊ*Ç¢‹r»)ÅÆ³‘m›õÑ%l§:LƸì?î)û/l›…ײßú½VòZ¨QâÄ=Ç–m.æ-£H¯ÙÙQÁÙ†õu6öÍ&ÉRÒ#Ð'ſٸy=o6ªNâMsñ¦±xÓ† °JZºƒ2ð/ž¬ãÿŽÞe‹µÇ»mô[ZaKZŠèïã›ÿàC·;i"º- @Xß"jèV'-C·$i%˜Ö‚iËøKx·W·Xé$˜Œokjèˆî C*tLÁ¼-˜wC·t‰ŒU0}ß\ÏëÌ÷¼Åøç{¼ñŽÞ7Ü6âØ\ø}}&c{úíöB|: ÷…ðwL¸–žLÆb“žBø{ ¦óÿ¯ù¶a®ÍŸöM„´o&I{ZÎÄòEÓž–­vŠ´ï¤H{Z¶ÄívÄ´˘öQBÚ[pÔG¸Ò*!È/¡óœ³»IÎî&ÞÊÙÝDö¾.ÂÈÇÚ…ù¸;?#ƒ1òñxM&óØ\¼ÇÅ&cÌÎÈÇïaŒ|,_‡‘ëC%÷âØZÇdŒ÷ëKîű6ÇdÌbäs$÷âx<¿àN“‹4ˆcs “1‡)¹Çìj!]Åq;ËdÌ3”fäs-ùüC3ɽ8Ö/ÎdÌKˆczé6Ñ=akŽ™óë¦Zþß7«ôÆõ1 úÚÂï´Â÷»¥YÛCø;Bêûjs¢AÿFŠvKäç]ñ׃Óž$HøŽ`·XJö݃þï®wùSüó¿Sz]FZ ß/&|G°[ºœ ßïN‚½î á~)Ú-o¢ï» îÿUpgéÊûÜ·~'†S°[Þ)#_UñþÝj>}ßUùã!Ø-Q¹¿õåá°Dù{ñ*¤ƒ¥Kyz©ÿÚ¿óç†/<âïÄð vKOÅïþê÷ÅüñÅI¦÷B9°ôÜÒˆþez/”#K焤ýÅïxmÿ…rjé9!íÝ"Mfz/”s‹ùs_þžWòQ°[:Þå×?–‚?–íhF^õó!–oñ*rÒep¬ð™P®ž’^>+ˆv¡œ>÷—O1œÁ žÞúêüòñÒÍÿû,®b=béÙ%ì n•ßë!Kx!ß÷ÄpTÒQ°[ÚzËÇR!ž*å5SúÊÓ9ë÷‚?–NÁ>{Vüv»áãSQî³-¿“QÙU¬¯,Å¿k™…] —¼fí^ §.¡~²ˆõ”X.*dñûì¾÷O»ÿ»öwø^7ýÅr.–åï_×.poùÛE½á·ÿ»ÓûuËÏk懯¿Sîefái…—™©^ýËÏøfâé•®T¸A¢pTËdC ŒOðA¯TPed2„žÔPaˆIðCnæžSAU“¡´LM>&CyYVRC…N´e¡B•BÂUTh¦† ˜¨ Š \Š W*0Ñ0T놞‘ÀøN ê,TmÆÅøNРJ;ôÜfºˆ‡ž@A…‰ï3>âGŒït‡á0#aFÃŒ…ùæ3ÆwÂÃd˜)0Ó`¾€ù’ñ&1fÌ<˜0 ßiKa–ì„Y ó- ]I-DÒ3ƒ·þ‹½×˜•KþΤ¬\rô÷5måR#¹Déõ'nåò©WÎ lÉp2Ñ™_<&£¾ÎT¸Lä*ÕýÃâ*¹|ôb2¹õ/I¹äRÚW˼ÉwÅdüä}ráq–’D¹üù•».× (ÿ§trõëŠëÉ´åÒïÚÒÀ‹1ùפ|2í¹üüo ‰Ûª'¼¶¤P¦é —ãË4"þe©á«D‘rù@ùbõ¹j_!â_åÉu²–Êõ^Oð)×XÈJ ú*‡³ˆT®D‘ÍÒÞöš#ÐËèåôrzÂÃã”o'†=Â5Kûßö_vÿm÷…÷Åkº¦°?ÉÒýú¦GÓÞ-Òæ5¿ÿ“ß~³Àª†Võü7Ç?ëüò½šÍû‡ û×ôÿ~6ïoüÃñ}®°_ø¯)o¾÷*ìû_óû(ìßÿÃá °¯}Íß_UØw+ìÑÿ±ò® ÏÉ!£ûœKhñ—¿wëâžïs½§Îòý힘~­µàŸ ¿·>Éßo”hx#|ð?õ}ñê«ÿ+*HÒmsè‹J™^´cüK*Yé ClZd[+z5|ÊgÞUNx+mx*’¢œB¦’\¥KÎ^µ¥‹xo`oñ¢ÜêÅÈÈ%)¢…¾O¸b2$*¶…‘n#JZ”ÛĈ÷âr-q—¸mŒ(Y—bI·“)Ëd½­L -fD7âÒ*é*ñ^”®ˆ’•rL†4F¹x/Ý’F¼†2ÛÕ„1ò­‚*3éÖ5Ò-lj0R˜@[Úˆ÷¢´E”´HÝK·»‘n{#¾·nDé‹ô^¹-Žx/.{kÉdH¤Ûåˆy,ýŽri\3F¾½Ž¸­N[F¾ÕŽt›åv;â’½Lö[ðzö* È–”#%#´¼KË·Xžiù f2–eIË-+ÒòA˃˜çb~Šy"n}%¦·˜.Êtè%ć†Jfèr.*¡Kº¨tÆÎø¤3ti•ÌP© ]ÞEëœÁŒO"ó!ã“Ê|Ìø¤2£`Æ1>‰ ]öE%2TC¥0ôÜo*‰¡Ë¿¨$†.£’˜EŒOú²ŠñI`Äe`‚Ô…ñ0¾%`;ß0ºüëã[FϧËÀèò¯]B°³~B”Z+¥Ù™´T”î„çJ÷¢Ô[é^©•Ô<»ïdú½O«`©_z/~GÔ:ÈJk¦ª×ªÉ¤½#j9(´},å½î–ó‚V¨ä¹ïëä[ZàíÜg^¿ö¢¨ÝøÖOƒ†ü^`²åMªìU3öuÓÍ¢Ôú‘»SùµdÄôè!¤‡˜Štñk×(Ü)µ,<>»¨e¨Œ·¨­¨ ·ïùB¿¶ø{¥–cK!þn9òi‘|&~ϯ­ÔÁëÍ2º¼nºÿÅr™U¹Î¤¥èÓf\©Ôµ4ìäþeÉ«¨ªÐFµD ¥Vµ_KÏ—îOÿvúú´/úµümYKo~vÈ*}3…[ÔÊ•k Í÷kQú¾×Ù¯Åë»^ÍÐöiùZyµŠ8¿öï?Ì“?>­‡úž‹Z—òp÷k#û®y,噺¡8¿Öf‘õ†¬ßÙ¢Ôvµ—EíMQ»Ó÷¼§¥úš_:s7Kúµ§DmO¥Ö¥ïùMKƒzuî\¦^¶åU,_b½'~_Ì×–“OvîÙö]¹݉ڛuMŠý1¼E¡í¥¼f§•)^ù»Zw´ñ—‘Ù 2ºþgþNO&£ãD;ÆbÇ‚vz¥ûŠêFb'ŠvlhçƒV¯â~•…˜‰qi§‡&Äý'Ä})Äý*hhÅÎ5„ˆû^H;Éù˜Œý1¤cZ¼ÄÎ1í”ÑN‚¨J&vŽÅ='¤c:÷ç;­â^´“!v|Å}hñUÀh‡CìˆÒЏg€Øi£ÚÑ)ÊŽ0\ÔðåG•@ùQùo䇨V&Íqß’@ù‘GÈÜB~ˆCe~²Èý_Ì$? ù(?´’ü(&ä:‹ü()ä +Éâ/?²ê€fÂOO¥©¶6]_‡¾Ì›9Óß‹o ÿ/ žy‡{áÌ]§¹Ó1Ì+wÐ?-î¥/uJ¾dïý,nU!¹W)‚¤·¦§R!BÖÏeQá„÷º8§;%c_íˆó¥àpKnýÇøŽ'¥N·=Þî°&×{# FÔ¿’„!½f\o´¤žkpíÜðVÄÕuêa¶Iq7î—Ç}Ž%vó‘MËg4' í*…Î;1ˆÄ´º—s#ÑËÞ;;²ù:;yû³F“^ÕÒª7º—Ä6ï0rå“)ÄinJÖ¿7$°MÒw5ÜI’~kWêìà$åÏçEwꆒØT²n€=ž$õâËjı§Ã­ff3qÏsùôÁ3Ä>#båÁ›W‰íâµÌåÃ$±à&mØ ‰Û^½ë±±Ittù†ÕGÝ#‰+Ž1…”&ÎÁ>hlÒ¤Z¡Ák‘˜AE/Ÿ^¼‹Ø[캺ß,’Ôàû/žLºHBNøx!I =þ¢äŒ Äõ¨w˃«Ôå¹þ~z£¾óËÆ$QÿVé¹!ñOµì·–Û$ñ}e6]n@b>(‘g½%šÄX­™Öæ&IŽþõÞuWqý-ô›»EIòþeUÓO„ë²Õ—W›@lÇÆ\,2«-±%ÍíqNÝŸDo_·¤ð¤Ò$~¬&wƒéĶ>_ÑØ[Iì®\UWÄ¿Aœ?»ô=‰XõËë× —eâ¥ÁÄU½óÓÝŽ$a\â˜6m‘¸á‚ýí} \MÝ×ÿI¤H…J2$2Fé ¦[J$$Òtçù–Ì„Ìc¤ÌY)2<™ò°ˆ ™‡eL„ ’éŽ{wsÜÜÇóø½¿÷ýüùØŸ}ö9ûž½öÚëì½vkíõm7DÊÁ6«NCøg‘Y‹¹ÛÏ3Ü=æó%Þ¬&˜g‹Ö‡×ÞK˜ç cÝNyö\³¯ ¹;pæ·\Ò±ßPfô›»|È¿œÂÚ8o‚˜¨þ )€Øèµ‚\o‚ذ^ÞÅÔu MÌp”ä ²íïo]ï‰ÈÔ"zSF&DY•ÿ¹Ëͤ³†ºìë nÞá£gF HÛ°wÎÏŽ‡ØüCÒ­_Aø>õÆ™A èêboøÅ2‹ô²„G ‹RâðÀ $ÇV=·¸l‚½]ž|ý´ä6ö½‚ú€xË‚I£ÊËAÑÓÀá6ÃäÎi{‡]é›SôVH@ƺÚ9w$È-..o<TÊ»¦¯ Š)^å•Ò5xâ©fm@y»Y6gØ&P\ª{qUTH>©:žºj òÑ6‡ÝÏ„‚âõй0~&Ïöîu®ü!Dé}"÷€Œ(ÍKŒžü ø·ci#ðq3¸zÆ[äÂ5ÒïvLQÛ|ù¶,=Ñvi!¨ZX›=8Š+‰3û>Z¢¦cÇí½Ó¢Äž5¢ÖŸme]×DŠÔ´´~§A¶ÀðeÊòà láîR'k*ßšŒØÍŒÁÇ{Åè¼8\·¸ÿS7¯[{i§äCú7È=ûíÖµY‡fJÿu <þyû1% h–Pú%NäÁ§œ¾¾HAé•y«¢gCìhN"+» (,†Þ¼?³ˆN÷ÿ¤:áü9½Í×¹_nü×ÒÙ«!jfÐìþxBǮ8˜?³ìãªÊ¶µÈnžŸ‹%DŒvôÜh+ˆ' Ì_ృæìï\ªÖ$ÇãóË_&½ODáÄå—ÌYái›KÌ ûADPÜ=ó·7@¼ÉôuïfwÏï0—] R½yg-Ætç›6 Ü0Ïôü8ˆìè|qArKœÅzUäwAå±a[?ƒ¤Èmi{[oàùf~ðý£äCvî> ¢ëylÜÚì*ˆ.êåX*{CtÜ—çŸ6éjEaÿŒë ðÊÛµxbDL¬}¼ö«1 ЬÛ5Þ³>Ä [º¤¢9HνÓ?žÑ ëËã³€`ó­"#ãs ñ0lÇh”±‡žñÒ¦ƒ¢ÝIŸúÏÝpùË\ïâf÷ò÷ªÃÅ•‡7ÁxaSŸ¥Ù.i C?¸ÎŽ?ÂÔjþ®w‰Í±‚°ø¢´¢I~9cšüq¼øiSOLkQÒ’Pp{å ’m•&ã„OAÁši=쾄O˜ceW @ZÞÇÚ5åðÖœ6ìþ¤$+Yi-7\Äû›¡ÚÐu ³°øÄÀËk!³»¸Â3‡ž^³³xóù Ç51¾ãÁ¢àô4àq¯‰¯¸òÐmK¯óÉG{ñ‘d…´¬c2? ä'{¤šN.å{YòòCA).Ô‹›¹Ä÷Ö¼û”a|ó’ÝØ^_PÎb¯ÏZ ŠëçNpÌA¹ìó“A[΂bü“#rf€Ô¬dËí ñõO¯K¾1.G3:Ǭ‰žÙè;ÃÙ½Ar0ØqzÄKœÔ[¾Ó×ø/™µ›+…¨fAÓƒx—Î¥<õ D VmÚ±Õ6Þû’ Œ{óÐò)ˆºÇ‚øÑuàþyâþe%Dû {\„(þò¢õ)w!̸öH¿p/ñ5å*@Ðösƒ1>7(Qj”ð"¿ôJÓ_k <«IÓ¸ µ™àdzA‹çÝï~µYvå¾'_/‘»Äg&QÆ©ÃõÓf@Ô˜åöò#[l™3öBðóƶºéð¦îeöøãþÇß~ÌÀ^ÌD¥KDå€b]í¾ÝƒbÓìíùå Í7žY(Ç¿·µµç÷Æ×“íö3•/AanÊØòÍvô31u}¥C?˜BŒGù'›¥‚ê«MÏÒ£AqÔú¨oÿ Ø#rHšz ¤Åý§wû\13Ú>k2d ^oçqùâz pÌéÝËn$ˆsS‰3ƒ× ‰É_AÔxÿæZã¶€àÒ­³Î¬þ ×1 V€¼Í›‹¿€Ì?Ͳóª8¿¿ÓI5_ï[¼¨óÇ^'Ë_…µÀçÏÇ!ãSKäjÛ¶õuà; —«õ"lÞÖâ Ü‚UX`ædñÏ[éÑϘ‰ ø lu«°Î0àÅw?ÝLÑ©{õ{n+ÂÛùŸ{Û—§Êg *@"žìà3jÈví^}®ÎNˆVœê´(\FÝ|aÉXydyG[ÞÙ÷ dõG\hY ¢ólÛ‡oÛ—ÉÙ- òã–¡s@\«öAÎè& ºÍ·³´XŠî Œ[Õ/E·„6'—ÄÖ²v£D3.p_1:#„‡¨m5ä®66í€_žÐ'þóZˆÊÝè]þxý-+˜HÓ½\ž ²¡é‚ëE ßЦy0(O­ÝçÕ'Dóä/ÎíÏùŒ²²¤hÈ ïøÍl[òÙ¥Îþ†ýÀx…3¢Š[^p"ý*6~ž ‚vã`°Ùà65¾‰ì6DŒYebf=¬6ñÙ†}020dì­IsAx?êLÜû Û–·þñ®lPúÚõ4°qJXJCC.B Ì;Eå#½»›Ë!ºüòÅ‘>౺×:i/®ðÏm! û‚è£k”;­ì¸‡ÿa³äpg¿ßõuw"D1§·y8»¤Ê_q}ñyÃoã$Ö»›8ŽQ·~#÷×-YaÏ1¯n¯ÅáDf0þ=9þâÜì6ð#S¯>s"[˜â¬`Bô“ÑÓb "99ssÊ>‚¨‘O•béâÃö\\_ÅÒk!r\Fç …AÙŒœÒ j#s‡ÊñD^ýÜ«S?{\™÷Þv*¾ž®K!` ×u¿¾D¢õÞooÅ “þxÛAº[öªw(>¿™h²'‡áÖõò>#³Æõ6[ë×ÂcŸ“?¯nÖ³°¨maµåT¶/„=íÏj“t K±vÝí7·pZ'Þ¹ûûñÀùЮÀŸ}~LÒ½þÀ³™’ݹ®·}-Ø5øDÆnbH?ƒHï;~VâBˆ”é×ìœ"X ÷î'K€ß°•ËçÉÀ"v©ãy¤Ÿ9÷@å½çÀ¦ÕÍ@=/´U»\Û ©([»x-âFárŽÙ>j›ŠqI­ŸÃG\N·u¬ ¼%Žíæø@Ô¡/&ötÁ¼9—îãó‹ŸCÑ„¦ šßyDîÍHT(ÞŽJ: ª5ïbÅAìb{Ò¤3ÛÜwÛ?ßÏØnHÏpƒèåÝ>Κ×Ï­ÚúÔ…È›õÖÚŸx•-Oèëã^¬3j¢Ý1~)\ø’6td7ˆHÛ|ͽˆGó[Õæ(Ÿt·LQ›Ÿ{¹gÁAú³K_!ÌÖ;Ùãíl,yz4À­„о©þ !jÔýŠV™n 0}88Ì 6ˆ¬ƒZç¬e‚*`|ö‚ôQ 8ryñZ«) *Ouhàz$É"Žªt7(7¬ËJÇ¿£=â˜÷›÷çsî˜2ˆ²^P~߇ K¹ÑÆ ÿ}Iyö™CAÔdƒ|ϼŸ‹¬ye÷ô#áŒ<àÅÖ¯È*~ ²ù  Ò1ƒë«,ë‚ünÊ•É{º€¬lVäÔÜã hýʹâ:>ÞÖñ湉î j~hÌߎ zÕFo÷i\ÎK/µYØ×³ o>î…à½gOe‚h㹪DlÄÞçQÑí8&OW@ä®6óÃCr@xÇöH!CÊÄÃfõÕ†-÷ήo r›.>1ͧƒ*èîÑ>üAþ°AŽrÁIPZ<©ý‡XÊ^Ù=¤aúšK˜^c´-4s‘5(O\»}/ÄŽ]^Q.„Ø+œ`¼^ â–Z^ÜÞ¹AeÓ½šp@ÐðŠ¥—Atô𯘻 Œñù,LÌ®¯¼ÃÒcøw¹ð‘ˇ-·pzîˆ3-–‚ÌàÕ†+Óð}—ªƒñˆÁ üx+ÿš](ÈvZŒ—šìIÀöÅ‘ñù¾Äõ–¾t6ˆ¹o®Ì Þ°¬èÝûp:t]Ñ£0økö¿_,Y|ÙººóތهÔO9Mçw!<~±©D_Üü.>^&ûe[?|ßÔ8çšÓx\®†²‡žàÊÅK £ŸòùŒö¯'ƒb¨5¯¢G‚ôÂ*U’¥­Vãzá!s¸Ó'P¹õü´ë×/g™šfÞEñ„õƒ¼Fƒxá]ƒ¼çAVzöÍÁ’P®›ÔõÔP|ßåmðnë|¿Ûëõ¼fqø||º~>‰W{£‹‡žÞzï¾Yû… Äõc6%>¥Ï‘ƒœBˆY7b“Ý8+P4Û2§Ñ ¾ ÅŸOÑ _Ʋýø>mïú“¯'>ù±¯±ÉùÀ_•¶Ý÷$>xµœõbÔUŒËj]ÞÇ$ÑÖûm°å]ÙÕ•Ò ^ÄðàßÅêÚ^þ/·‚"îóÖ«æ×A¹óè©ûürP†+Ã]×âzdIFáÍ L:àÞO„ï3RŠ;- äƒX‰Í÷b›‚,™©8¹÷ð'ŒÔïÖÄ DgOU®Ý‘Ü–þàûháÕI#Ê›»@ÔÁ¿˜û k¿lž×ô% Äîž—äòzŒº=ÄÇWçJJ.ðOé8|.®è3ÄèîàÆ]O~ô_÷ìöÝÿ`´"åÍ®?ùH^tì|h¯¿ùåúznʈœþp2.'á+¥B#ÖŸ9§gúqàn¹Z’'-Å*¡ñê%½ñï~ÀåN;à <šÆ}ÞÈ8ÑScÍ=5;°ËàŸ]Ö8{Å=¼Ÿ ÑŠa ¯ô{Ú½ã|ÿÿ"ÍSÁþàeŒ²\ýeÕ¹ñÆ“ø|ÒÖÑ2ß¿EL¿˜ /ÞÂ9:DfÝF²7a_ãÍÎ9 ³>>âƒë\ÌŸ³c꥗ÙýFÅ™†3[¿`Le¦=­ç ½ýß7^¼Ëô ‘Ûb ‡ñ,!¦õ¹Fá›ñýûÙ|[WýÞ 6w³›º³dÛÜØa xŸâ QÝwÔµ¾Y a‹sUv˜Ò2ßa±¡ø|ë;¬¹—ÐijZé½hû"»fÛ0 ºÍúZñø~9á@‹?»åot·Ã¯üÎ@ôZô¥Íú€`ÿ:å=;86›ÕòVõkyôÈëüu>G’ò% Kè¸(ýi6¾«ß¨Ó«# Ëêpoc{P~—ý±#>®-eâ7¸¾¾wË“)'ÎRùÙOWëAÔ³pï”wÓßøÓ„9¼ÉeaÕaªßV6qBÝ?àûï—¹Y™×gÅšÒÓî>é5ÃE2¯‰—s2–CÔžëû‹ü†pBçâ¢c7@¡¿´Wëû0ú•g°òS úè¶ïÜër”Yl±¯sP™[>àíìqkßèˆMgp²®ƒìÞœýâkø~gûƒV¹A˜0âBq7εˆh{ß·¯ú¼!uÈ™i}ËÞ‚¼Ñç|ÎÀà|]<Þð¥-(Í&îö‰ø ~ãÈÅ||ßçZ`“‚Ï·oÙÖöÃõòÊ;÷Äïåóá¶ààJPY9¨ý ÄóO­Äöƒjz±1÷ÁNPAc7ó«ƒ@a?±8§2F÷;õX„ËiHÅâŽï6¯#«my ¾OmòeõÝPˆÂYœ ÜÜ¢k‡ñu”/ص4P <ޱ-VÏs)ÒcAq–&à¬e§†ýÂZ/‚Ñg¦wéþ¾ïå¸È@qEå¾@õΦ7â(¶m˜mï ²/ÉYÇÚÙ€ÂÐÿž^éGqv•2]!&àù<““s@±T?‰y,„ïý‘ÕíD˜[æ³9¸k>Ž<ß…Âþ®mk¢`û#{ü+AµèýÕ‰‘Ž N¸Þ ³û$àßUØ¿D¼Y®[Ÿõø ¤k;÷{牯3=’nëáze#›î ;_àÓß.|ÖÝ*·+ÄÎ\–žÒT“ë³O€’Ý>¥gòË*Y u@ì¿ÿ”CrëßzÒ÷$(,Ž.² ¢´ä—+>öAçwïßw§~™Dµ­—iãì‰ï#gmžµ×_:¨’oeX§Ô©®àC¿»†ªXÚlíÔò„ ðÒÞMù´¸•7}[ßb‚ðr»²9ƒçߣöNl7Ø:¯Çø™ Êw[ÑöÎÇN;Dž<¬ZåRùõ9ÈLvÜ”¾mâ¡îcƒXæ±­]Œ-ˆS™'C‹+ñ}Ú±æ_øYiQÊ[;-r×ïbê.ò½Tåg‹®âýõÈ;ºH[Oê¼p«Ä^Ï3¶WniN“„1o!j¸GÞÛñA0ªl•Ó¶SÀçN~ÚÒþ)pßµ=+Âëë§úéâýZ¹=¦DùØfÇ£m zn8$ÔzѼ>÷òÎÿ.ýçn”ß¡O^d§4SŽð¿šþÿže½§äBÔ…N Íí³@l‘d’ÔäÏ“Î'H‹@¸r}¡§Ä̺Vé²å¡5+Ï?ÏXÿ“²¼ÃAÕ+6rƒâ(»ôï'ÍòÁõŸÏ——N\ \ÃE3U»AÐw‡^Ï®øþv¿ô¶ÿ ^ Hèg:ÈN _ÓÙÅá2,·)Ù—Ñd“od+m†¨ôEÆöŒµ ÜØãê‹ Är$›˜¹q R!²äËàì]÷ :ö`OO¿yêÕ³âµY <ßæqëæ¥¸žŸw¸ST.ðæJ¼˜ó7Rïcùµ’W ìióº¾âëÄ?àáó•õ€¾¹½AòW$cí „Ê!ËÙƒÀgK“Íc,A$öv™ýY¶ÛéîsºäpB`êÞÞ ÿøØÁ°‡9ˆVß¶°ß'ÝÐ5¼öd½rHêtß×ÄNmˆï_DÛæ¯6Š¿ÂuÚtøüøºÜúün6ðrÖdÊ.€$.±ÇÓu \nsó¢}'½Ž3R˜½^Xýá1ŽÆå]½b—ݽ`–Ä®â¾æyE­Mz‚`E£@»x{à?¯¿dle[à>ji9åŠ'Hjy›ü¹„âOÇÞ2ö€è`ØûVÛAT×!wÂŒx—ß² QŽÒ¬'›ÎAP’½tßT\ô<øÈ¿q6Hìo½ºc $ïgñ—ׂØÐûü­bCP~mu½àþs¤m[ÀËBÓÛç+pý¦t’0¿(v&ZçÎ\ Rwþ‡¿L·iƒã¼[áø~$êT?ðš|ÜkÕL"ŽŸ,»¹øÏ2]z{ûŒ­\Õ´>¿5zx.¸ÛTP•æ4;oû×ßßmº¼é2HóýLÜ{ãë¨ó…ü}l|Ý9ÇàÕ|¾dz>Fü=Ì®ôæ×’P Ž¿—´€Ø÷«û\z ±}o$È/K`ÌZ›Ó[GàúרúÚÕŸûsÌ¿BŒþØÛƒËý@øZ&º`Ö_ï’Bç·Ì§á”Ûæo@Ü:i„|ÌhNåqï•]‡èM9deÓ@òÞ"ràƒz ¸“j¼| HêNÎÎÉk†ëY³:çþÕ"OÌxÝÄu>®Ï´ù¦ÅBˆü˜îŒ5ÝQ[#ýã&^ÁçÃ;éâ’ÝãÔ®”#‘ÀϺåg¸Õ¤ý™÷×SA!]°p­K#\_í9êȺçø8b7C@ÒÏêÝ'¿dàÝX´}ϳ›¸Õ¸¢ÒÆó8e)~²´Ïªë¸Ü¾zã3ñŒ¼`õ¨VÎk ôíñGýÏ rHÙ:å=ˆk± ûòä]MãŒx ðßVš01_OŠD=A~`•âÊÁº Ü.Ù»¥¶ øïoç´þæ~EƒS›Bt抿 ¦žƒhLZÿÏŠ,õÎÉ{2|ð“Ÿî}?$™¸Ðs8³ÜžùIçGá{¥ °Ì|?¼wOà÷œ³êŽÃ[Îܼ§Äbú*?{×·Ï ‰ˆº¹TW:¶e¤‰AQÇ ¸Kz.ˆ¿äÍÉYûOiãRæ‚p·÷…Ô[ º_¿Þ© ¬¿ôƨ’³ ]a>oXn$ˆ7 µ(IÂç½–~Ëo?ÄõÕ£Œž‚l{9³†ëµývtütªDž¡î >®‰‚7FzdÅÈÝKÀõѳÝz·ž‹ëq§7®1©}¾Bà Ê1Ï<Ü€«Œü’½ _G¬ôßælÜ›¡­HÛ€ô¯“f ÷ƒˆçùqãög v,h‰Ë‹4××£è(®„¶ì~ò8ˆåÇÅÕÆç‹É§¹bÕÂ$àšˆucÔ¥cO€7ŶS5ˆKófص(Å…iŠóÛ€bQ “.Ç”  h>%ÿ½ÂØëÁÑOý@>ÿ*7Áø®ßÇf »(€ßµb®íg÷uÏ?Z‘¢—]²æì˜¼e1[Ÿ˜GßzÅ¡ÙGðýÚ }½v † ° ïo”ñ ¤ f›Ç Aº!û…yÑUü»ìÄÍ·eé¨6yI¦ ¸q}´Ë+CˆÅÂÛ›”Cì¾Mœ»åAÌ݇©[æl‚˜ˆdÇ®kæÁènӆΕɜ²&ý ¶ÿÁ:ÙÛM@jwµ×_yî=|r&‚ 43±CY7\Ÿ}³-:Pâc/Ÿýu´>6,=¦À÷ Â×_§F´š Ê ÍgŠ×=Á"ƽ•÷Fƒ Ïî}³ƒÙ rôȾŸ¤Ï–Ró">=ÇH¼äQþµ ë ñá.Û°,fŠÚ`¯üqõÝ·ª¾y¸Ÿÿ-¯‚^ÒŠBU[%";TÁ}&ÂCó"úYˆÿ˶?)¬q£¡¸sÕÒðÄC‹‹‡šWßùQ›}{¦ñ™¨ÆVׯ†VׯFVׯVׯÆsׯ†sׯFsׯs×'a¹;‘°ÜHXîN$,w'–» Ë݉„!ïDÂw"aÈ;‘0äHí2Hí2Hí2Hí2Hí2Hí2Hí2Hí2Hí2Hí2Hí2Ií2Ií2Ií2Ií2Ií2Ií2Ií2Ií2Ií2Ií²Hí²Hí²Hí²Hí²Hí²Hí²Hí²Hí²Hí²Hí²Ií²Ií²Ií²Ií²Ií²Ií²Ií²Ií²Ií²Ií:“Úu&µëLj×™Ô®3©]g¢]êTT¿ƒŒ8gÍUÄv¤2ð ûÿÿ™cU±¿Í¦Ø¯ràû~±#è ŠÄ‚BLÜh‘"=ba >b¡²ÑÐF,Äâ…CbáꊩbA$#bÑ$Fbj©¡ŠXЈ…ŽX›aÕ &±°‹±¨ :àD,hÄB‰Þ±4ìh…©Bb¡%+bq%¾2¢ÇÄbH,ÎÄbF,nhAtÇÔ 2±˜‹±` ! Oˆa¿|ò‚¿û¿ûG4†5;]ãE«1>hlÈaÿáxPü—k:@‰|Éɇ‘ß2ý€_M‡‘x8öýá? “ÏH>H„i$0Þ÷_)¦×H TàI‰©ØoDèÆÑõ  á K„q$ ¡'aêpŽS0ÊB­ çúî™}{¦ }¢vLv Çû#ßcj¹ÇÒr­åž³–{.Zî¹j¹‡‚5 Ý« wG¹é¤í&CÛM¦¶›,m7ÙÚn:k»é¢í¦«¶›ÚzÄÐÖ#†¶1´õˆ¡­G m=bhëC[ÚzÄÐÖ#†¶1µõˆ©­GLm=bjëS[˜ÚzÄÔÖ#¦¶1µõˆ©­G,m=biëK[XÚzÄÒÖ#–¶U µÔÜÔŽ8gUõT{¸Hôkíñ(›ižþ ,¥µ¦JÍa6QÚ£|Zÿ”ÖBsMÅü´ÓÔù;1<[hêþ0xgM¥âg"ªk£ÙTS£ÆhšU-h•‰Z¨9d¦9¢AKäLôòBfÒÓâ“¡Ç5DÂD üa@LD¶à—–Ôg´ØefHdi¡0‘(×è² åùwÍ,ÿ *%âyÍ/Q×øqWKTËjÎk!iA}L }V%1ÚcHRþ¬)å±–(hV” ßCkLyN‰‰Ö´Š·5Dд!õë‘: 5쬭q‡«EîûðíÐ3±Ÿ­«zRShÔŠ¶ðÓhø´F¡FóØÂ2#Ôú=¯)4"@k`jKêCZÜ5sÚSr˜jë¥*¶Ã@Ïžø4×ÑAsQõÇššk0tÖ`ê¬ÁÒYƒ­³†³Î.:k¸ê¬…f5s¬«î*Nº«0tWaê®ÂÒ]…­»Š³î*.º«¸ê®¢›» ÝÜeèæ.C7wº¹ËÐÍ]†nî2ts—¡›» ÝÜeèæ.S7w™º¹ËÔÍ]¦nî2us—©›»LÝÜeêæ.S7w™º¹ËÒÍ]–nî²ts—¥›»,ÝÜeéæ.K7wYº¹ËÒÍ]–nî²us—­›»lÝÜeëæ.[7wÙº¹ËÖÍ]¶nî²us—­›»Îº¹ë¬›»Îº¹ë¬›»Îº¹ë̦Y¦ý·­¿óÿ%ù¡6­?ÜÏåäêI¦,¿5‚sÖhü‘O­8G½Z®ùrü=g_ïÖõ$/}8;“7¿ÌíÉ9T2;eSÎY»WuÓ¾|àœ¸šcwZ<‘“;ÓÁ±ÃdιýÞ¦Ê8ÇßWðÇ9Ç:=x.月<¾û㡵œ“âk/ÄÙhžÙuÕ¹œ ë N?^ò”³Ó¹¿óüœ3ozÔÞ7ê+'·¸ á¦E&'¯³Éà->Ë8‡^LjëO˜Ã9h6`®™?Î_ïË+_Ïåìa²O»0s¢Cü‹LNnΑÞ$éœ_믎,+áäzÝ~V·’s&öœYÇÅrÎ sÏ#{[Žãœi1æÄÉëÝ9Ç×·àÍÉÙõò…Õ1çl¢U™°ÒŽs±U„gÔ²œœ%OM®x¿ç\(ÏwL22ãd«aµ­9Y÷ íp§g—«t—~·vœsÁ¶Œ€HÎQ˱qg:s¶ß]-w¨gÍÙ¹{žmÊ+ΞâW‚/ Öqò.I— ölǹ÷ÕdçãIœ‹oò·Ù·»ËÙ_'#@â7œsè˜%äo_ÆÙÖýsá ^çèä¡û½îsNÕikÙÌç$çÖ˜‰¯V àÜ÷ÿœÕ$¡6ç̇kÞ Ã8Çïª{|>çbS³ÈÌã8WÅgL!a&'§‡<µAížœã3‚‚iœÝ¡EYéÌœ£çjM²©à:™²ÛýíŒÿ +b­ß.3˜v ZïßÚ`ÕAâí5cÈÔŒEw O=5¼Aà4´W·ùÍß‹ðñ"üº_.‹ðÙ"|´âñ„o,¿s'‚¸/ÅS žVaêàíDàö­xJÇS&žö`ÕAÛd.¸0uàöã˜:pû)L¼ÜNm¿ˆ§Ë˜:x{>žnà©O·ñT„§»xº§‡xz„§Çx*ÅÓ3<•áé%ž^ã‰?þOxªÄÓ'ìÛÿ-h$Î[=|ŽÑÃç-=\îõpY×ÃåX—i=3<áó“.§z¸ êár§g­^þÔ/t–$KAª¤ ZRÀ1)蜴O n);•ŠØJ…_Õ†íÊ¢”(ÈšNO' N¨Ô’ xI¡…†^J¡…†sJ¡…AEù¤‚‰R1K)´PÁ7™Z˜Z˜ZjÀ±¤"aRa'©€ÀZˆ™ZXZXZ¨0Æ4ˆc -, -¬!0Õ·kDÜýX¾?%þÅ`È ÕøÇ8Æ¿CøWAÿ,ð?CõýWн?Èû#À܌«[÷ç lk­ýÓÖŒÇû°üßÀÄÿ6ýQÚþß@Òÿ†úýoæ¿¡~Cýþ†úý õ‹–ŸßP¿ßþ@¢×Ü}€õFƒf…P±ªÐ­8ƒ¯'±‹ :NúUjÏÖµãJÖÆV¡å ô„Þ£Aõ©B×A(Aè÷Þí:?™×-¼ =FƒT…Ò£A#ªB=BèHš²»ç7t`:ZRÚ’{såIü?•©êýCº©Q¤|4ïoªy¦üª•í •Ý‡[¨Ñ}|(¿«FÅ âhEߪBïaC}Þ‘ö|d'2šVzQ:Ø(wj»nT:Ü#úåµ(° ‘¹ýôï*•w)m‰ŽŠBûÝß}?uÿÓ¿{®‘÷C=ˆß=G¨Sñë׳~º}œº‡$ÆŽlÒçÒwÏ BwB(RÍ ¡?ù—RÆë—Ÿ¦÷~ƒˆ|Tõ}ÐQ¤Ðw8‡ƒZŒÐžªÐ¡ú“ZN?WÉ'¢¡D¡ïixüÇKý½ Õ……æ÷@v1~ùÊžfrw¶P¿†æ‡Êß¡ÿÑòïøKåsÍÏ5í¸i¥.×ôý-UŸtÔ1]òû/¿doªBÃkJûO e:š—®úˆND—f~ªB%DraWÃïu½ïW×ÿ·åÿ4}?Ë$çHþk@cûÛeÍw_…>GG¯£—ÿÓüþYùùÉñ¨¶ÇÒ§vÚP§k~„Oy-MN7C 2ŽÖÁª¡FqºVmô$a A‡û‘q“Œ8m†U»U©!Ví^…Œ•QšXY£Š…&G.WD" L„!Š0¸4ŪÛi®‰[hÊÈh£)·ÂÔF([¬ÚàDä„ñ¬µÕ$â>2 ¶×” C2ò!tiÞÖ«våꢩOõž£& vIš0ê†<äæE$ëvùrѼ0ê%7MŽŒºÝ5Ï £al"£I»cÕÆ]"iÜÀ¾Õ'Œz„ÏS“#£nÍsoMN®B&$Ò_sMä(ÂMy &¤É‘Ák°&GˆÐ„Q/«F&Œz„!M ±Š ÓäÈK$Â`ªÉ‡kòšW5´ôÙGÁ*\ò‹d–MB $äŽ5B¾™j…©e‡BF¹@²@BÆÓU3V=HcÒ[Ãoo_hx6XÃÄ`M_QÿÂ1u"@‚ A… BÁ ˜:‚þ@8[Ac"ì!S¡IÀÔ(ѳñ4Oó15RôbL„§dL½S£F¯ÅÓ:L¬d¦FŒNÅÓ6ªñ¸FK"ÕþüKínZŒËNZmà¿Ê@GµQÿ¬¹N›M›jýîJ&õäŸYù(ÞTûù¿2j3·kuOøiK!ÅÓjǧxDüc«áL‘Tû¿Vû¢÷ªkA•CÄ?6åQ}j¶Rý~ÎðIõX¨É ú#Ÿ‡ÿ°‰”êDñãÂoƒÞ3ÿmÐûmÐûmÐûmÐÓÜümÐÃÔ›òÃèÃG4yåê?`ÿíúÿí²šÞ/?Yÿ­\Ycý}}.ÅŽl2à'ß»ªü´ñ®îw…ü‡û_óx©ŸÔñü=­üâ'Û/×ñ¼ô÷÷3­|缩Ÿ¿£•ÏüäûßÒÊç1ýoh嬟üý#Z9—VŽü“w:=ùç† úýí÷=»{ò¼ñ$ýŸ—M«¬ÿØq˯£ÿÛ|RMßó·Íº—:OøUïG¹zþoK??¦7@ý Ýwa5I‹ýÉ#iD­öÚ¬(×4”é‘rò‘³:G×F˜öCèôÃèõ0ª%YQjiÞÝ«Æ|@m×ÉØ‘¥…~zãBÛ‘eÅ"x·Åj>ø®í<ªƒŽV‘P¡kd]A–•ÖXµ5†~X]“Í“ÏwŪ-.äÃôí±j‹ ù`=ù€}¬Ú £íÀ=ºFÖdi!×'‡”&‡–FÏÝ5uõ…|M=®Ñ±7¬Úr@IƘüúÑ8oŒÂ…®ˆQÃY“CYÓCZ£#{Á˜î0×ÚîýÈBƒ¾-òwDÿFy'Ë7’gB>[aÕDzȲDÈ =¸s4žhLú`Ô߈/t>„júCßMÛMXgˆ£]„e†’›ÅU…ÞÆ¦cj«Ì<-ÀÔâØa‘!,1„f ¦¶ÄÇ¿K qŒ°Ä¤ajëË.LmAÇÀ4Vì¦>–ƒ©€Ç¿ò0õ°s˜úqüëÚß·ÐhUÖ¯!«5Ýšý— ½žæ>½>²zÓëÓ½j²šëzÏw¿W{dTYïÑ{×AM^3¿k罃¼hÞ>îm¾ÕÛÁÑx!ï #åj%ßÝwÊ7å^½UÞ‹È»±×íñ_6NrïI8{9Dÿ,ßÜé^?ÔzzU^2ˆÁ~ >ÐøRå]C«G÷>rrD]F^†ô~#oE:Ýêû©UÞBè÷t/GÍøü[9R{‘,Fï«òVü­™íU|ùY¾ÿM¹¬I®¿óRT{3î¤{‰ºwÓ”í¨íÕø½"ïTš7ª»GˆéÅ3h¯éRRP ²ÒCl&Pü —Å« ¨EÊ5± Aq/ÈJrC¬:>Y1&Ä )Ç„RF( È• )Ç(æY1&6 (>RZQ¬ BÉ@Š/Š3@ˆr#¤ˆ3)mĆƒPtÑ&…®›‹.êñè m<Úÿ‹ñ@neäñ@qK´‡‰f<hÆm éãaTÃxþÍñ¨KKÍøh:¤ñhªýÆ£¹fLj‘ÆÃúßGM èwŸŸ!a͈áú™¯Ï^«ñ{ôô„¶ÑÚˆ:bº¦ å§÷;QÂÐò#FÇvßåßåßåÿËX-bQÔ£jlzä…A3÷k‘ÿ2a†‘7'm7ˆ¸õ UóucMEý¹MÝ"¤‘ÑÈl©?Ôs(Z8<k®jFDj®ëx Çr£Ño‡DÈ¢åÈîo8„#ŒÞlèÅÃ;…Œêú^>žˆÐ`tŠZ ‚®‚TñK(‹ãâK ¦\Kðb¹*Ô¤/B*”ŒCtŽ®ò(¨M·®^ô(l2$¢_ó%RhîËÿ&oVtrotl/README.md0000644000176200001440000001572115132141421012511 0ustar liggesusers [![R-CMD-check](https://github.com/ropensci/rotl/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/ropensci/rotl/actions/workflows/R-CMD-check.yaml) [![](https://www.r-pkg.org/badges/version/rotl)](https://www.r-pkg.org/pkg/rotl) [![CRAN RStudio mirror downloads](https://cranlogs.r-pkg.org/badges/rotl)](https://www.r-pkg.org/pkg/rotl) [![](https://badges.ropensci.org/17_status.svg)](https://github.com/ropensci/software-review/issues/17) [![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) [![Codecov test coverage](https://codecov.io/gh/ropensci/rotl/graph/badge.svg)](https://app.codecov.io/gh/ropensci/rotl) # rotl: An R interface to Open Tree API `rotl` is an R package to interact with the Open Tree of Life data APIs. It was initially developed as part of the NESCENT/OpenTree/Arbor hackathon. Client libraries to interact with the Open Tree of Life API also exists for [Python](https://github.com/OpenTreeOfLife/pyopentree) and [Ruby](https://github.com/SpeciesFileGroup/bark). ## Installation The current stable version is available from CRAN, and can be installed by typing the following at the prompt in R: ``` r install.packages("rotl") ``` If you want to test the development version, you first need to install the `remotes` package. ``` r install.packages("remotes") ``` Then you can install `rotl` using: ``` r remotes::install_github("ropensci/rotl") ``` ## Vignettes There are three vignettes: - Start by checking out the “How to use `rotl`?†by typing: `vignette("rotl", package="rotl")` after installing the package. - Then explore how you can use `rotl` with other packages to combine your data with trees from the Open Tree of Life project by typing: `vignette("data_mashups", package="rotl")`. - The vignette “Using the Open Tree Synthesis in a comparative analysis†demonstrates how you can reproduce an analysis of a published paper by downloading the tree they used, and data from the supplementary material: `vignette("meta-analysis", package="rotl")`. The vignettes are also available from CRAN: [How to use `rotl`?](https://cran.r-project.org/package=rotl/vignettes/rotl.html), [Data mashups](https://cran.r-project.org/package=rotl/vignettes/data_mashups.html), and [Using the Open Tree synthesis in a comparative analysis](https://cran.r-project.org/package=rotl/vignettes/meta-analysis.html). ## Quick start ### Get a little bit of the big Open Tree tree Taxonomic names are represented in the Open Tree by numeric identifiers, the `ott_ids` (Open Tree Taxonomy identifiers). To extract a portion of a tree from the Open Tree, you first need to find `ott_ids` for a set of names using the `tnrs_match_names` function: ``` r library(rotl) apes <- c("Pongo", "Pan", "Gorilla", "Hoolock", "Homo") (resolved_names <- tnrs_match_names(apes)) ``` ## search_string unique_name approximate_match score ott_id is_synonym ## 1 pongo Pongo FALSE 1 417949 FALSE ## 2 pan Pan FALSE 1 417957 FALSE ## 3 gorilla Gorilla FALSE 1 417969 FALSE ## 4 hoolock Hoolock FALSE 1 712902 FALSE ## 5 homo Homo FALSE 1 770309 FALSE ## flags number_matches ## 1 2 ## 2 sibling_higher 2 ## 3 sibling_higher 1 ## 4 1 ## 5 extinct_inherited, sibling_higher 1 Now we can get the tree with just those tips: ``` r tr <- tol_induced_subtree(ott_ids = ott_id(resolved_names)) ``` ## Warning in collapse_singles(tr, show_progress): Dropping singleton nodes with ## labels: mrcaott83926ott6145147, mrcaott83926ott3607728, mrcaott83926ott3607876, ## mrcaott83926ott3607873, mrcaott83926ott3607687, mrcaott83926ott3607716, ## mrcaott83926ott3607689, mrcaott83926ott3607732, mrcaott770295ott3607719, ## mrcaott770295ott3607692, Ponginae ott1082538, Hylobatidae ott166544 ``` r plot(tr) ``` ![](https://i.imgur.com/m9pusZk.png) The code above can be summarized in a single pipe: ``` r library(magrittr) ## or expressed as a pipe: c("Pongo", "Pan", "Gorilla", "Hoolock", "Homo") %>% tnrs_match_names() %>% ott_id() %>% tol_induced_subtree() %>% plot() ``` ## Warning in collapse_singles(tr, show_progress): Dropping singleton nodes with ## labels: mrcaott83926ott6145147, mrcaott83926ott3607728, mrcaott83926ott3607876, ## mrcaott83926ott3607873, mrcaott83926ott3607687, mrcaott83926ott3607716, ## mrcaott83926ott3607689, mrcaott83926ott3607732, mrcaott770295ott3607719, ## mrcaott770295ott3607692, Ponginae ott1082538, Hylobatidae ott166544 ![](https://i.imgur.com/6o95mvV.png) ## Citation and Manuscript To cite `rotl` in publications pleases use: > Michonneau, F., Brown, J. W. and Winter, D. J. (2016), rotl: an R > package to interact with the Open Tree of Life data. Methods in > Ecology and Evolution. 7(12):1476-1481. doi: > [10.1111/2041-210X.12593](https://doi.org/10.1111/2041-210X.12593) You may also want to cite the paper for the Open Tree of Life > Hinchliff, C. E., et al. (2015). Synthesis of phylogeny and taxonomy > into a comprehensive tree of life. Proceedings of the National Academy > of Sciences 112.41 (2015): 12764-12769 doi: > [10.1073/pnas.1423041112](https://doi.org/10.1073/pnas.1423041112) The manuscript in *Methods in Ecology and Evolution* includes additional examples on how to use the package. The manuscript and the code it contains are also hosted on GitHub at: ## Versioning Starting with v3.0.0 of the package, the major and minor version numbers (the first 2 digits of the version number) will be matched to those of the API. The patch number (the 3rd digit of the version number) will be used to reflect bug fixes and other changes that are independent from changes to the API. `rotl` can be used to access other versions of the API (if they are available) but most likely the high level functions will not work. Instead, you will need to parse the output yourself using the “raw†returns from the unexported low-level functions (all prefixed with a `.`). For instance to use the `tnrs/match_names` endpoint for `v2` of the API: ``` r rotl:::.tnrs_match_names(c("pan", "pango", "gorilla", "hoolock", "homo"), otl_v = "v2") ``` ### Code of Conduct Please note that this project is released with a [Contributor Code of Conduct](https://github.com/ropensci/rotl/blob/master/CONDUCT.md). By participating in this project you agree to abide by its terms. [![](https://ropensci.org/public_images/github_footer.png)](https://ropensci.org/) rotl/build/0000755000176200001440000000000015132222605012327 5ustar liggesusersrotl/build/vignette.rds0000644000176200001440000000045315132222605014670 0ustar liggesusers‹…RÁNÃ0 õÚnl“ûˆ;½räÀ4!qM›Ä E­¡‘š¤j2ªÞøqN— v qˆcû½ØÏVžçA2Ž ŠÉ—d&t.\ ÌœŸsË_$7ž2éFæ>¿hù5W¼lèÓZÛ²‹‡…®î´R˜Y¡Þ˜«É¬f*¶­™%c<ófgÉØ#˜VQ‚Z1¡g™–¯¹ïÈ‚ˆ ø^7®øÞ sZnO„,V–¸ŽÔCfÝL]bX ~ÝË?òàû<‰ÈŒ|½±â’ör'>™¬E‰°ö'ˆŸVkïŽ6Þ9[!í0Ë™>`Ûèšâa#š°IC³s÷/>ȇÏSEYÉMP’s·Òôµ¦÷}}{A1:Yrotl/man/0000755000176200001440000000000015132136164012007 5ustar liggesusersrotl/man/taxonomy_subtree.Rd0000644000176200001440000000436115132136164015711 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/taxonomy.R \name{taxonomy_subtree} \alias{taxonomy_subtree} \title{Taxonomy subtree} \usage{ taxonomy_subtree( ott_id = NULL, output_format = c("taxa", "newick", "phylo", "raw"), label_format = NULL, file, ... ) } \arguments{ \item{ott_id}{The ott id of the taxon of interest.} \item{output_format}{the format of the object to be returned. See the \sQuote{Return} section.} \item{label_format}{Character. Defines the label type; one of \dQuote{\code{name}}, \dQuote{\code{id}}, or \dQuote{\code{name_and_id}} (the default).} \item{file}{the file name where to save the output of the function. Ignored unless \code{output_format} is set to \dQuote{\code{phylo}}.} \item{...}{additional arguments to customize the API request (see \code{\link{rotl}} package documentation).} } \value{ If the \code{file} argument is missing: \describe{ \item{\dQuote{\code{taxa}}}{ a list of the taxa names (species) in slot \code{tip_label}, and higher-level taxonomy (e.g., families, genera) in slot \code{edge_label}, descending from the taxa corresponding to the \code{ott_id} provided. } \item{\dQuote{\code{newick}}}{ a character vector containing the newick formatted string corresponding to the taxonomic subtree for the \code{ott_id} provided. } \item{\dQuote{\code{phylo}}}{ an object of the class \code{phylo} from the \code{ape} package. } \item{\dQuote{\code{raw}}}{ the direct output from the API, i.e., a list with an element named \sQuote{newick} that contains the subtree as a newick formatted string. } } If a \code{file} argument is provided (and \code{output_format} is set to \dQuote{\code{phylo}}), a logical indicating whether the file was successfully created. } \description{ Given an ott id, return the inclusive taxonomic subtree descended from the specified taxon. } \details{ If the output of this function is exported to a file, the only possible value for the \code{output_format} argument is \dQuote{\code{newick}}. If the file provided already exists, it will be silently overwritten. } \examples{ \dontrun{ req <- taxonomy_subtree(ott_id=515698) plot(taxonomy_subtree(ott_id=515698, output_format="phylo")) } } rotl/man/list_trees.Rd0000644000176200001440000000244015132136164014453 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/studies-methods.R \name{list_trees} \alias{list_trees} \alias{list_trees.matched_studies} \title{List trees ids in objects returned by \code{\link{studies_find_studies}} and \code{\link{studies_find_trees}}} \usage{ list_trees(matched_studies, ...) \method{list_trees}{matched_studies}(matched_studies, study_id, ...) } \arguments{ \item{matched_studies}{an object created by \code{studies_find_trees} or \code{studies_find_studies}.} \item{...}{Currently unused} \item{study_id}{a \code{study_id} listed in the object returned by \code{studies_find_trees}} } \value{ \code{list_trees} returns a list of the tree_ids for each study that match the requested criteria. If a \code{study_id} is provided, then only the trees for this study are returned as a vector. } \description{ \code{list_trees} returns all trees associated with a particular study when used on an object returned by \code{\link{studies_find_studies}}, but only the trees that match the search criteria when used on objects returned by \code{\link{studies_find_trees}}. } \seealso{ \code{\link{studies_find_studies}} and \code{\link{studies_find_trees}}. The help for these functions have examples demonstrating the use of \code{list_trees}. } rotl/man/source_list.Rd0000644000176200001440000000151115132136164014627 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods.R, R/tol.R \name{source_list} \alias{source_list} \alias{source_list.tol_summary} \title{List of studies used in the Tree of Life} \usage{ source_list(tax, ...) \method{source_list}{tol_summary}(tax, ...) } \arguments{ \item{tax}{a list containing a \code{source_id_map} slot.} \item{...}{additional arguments (currently unused)} } \value{ a data frame } \description{ Retrieve the detailed information for the list of studies used in the Tree of Life. } \details{ This function takes the object resulting from \code{tol_about(study_list = TRUE)}, \code{tol_mrca()}, \code{tol_node_info()}, and returns a data frame listing the \code{tree_id}, \code{study_id} and \code{git_sha} for the studies currently included in the Tree of Life. } rotl/man/tnrs_contexts.Rd0000644000176200001440000000200515132136164015210 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/tnrs.R \name{tnrs_contexts} \alias{tnrs_contexts} \title{TNRS contexts} \usage{ tnrs_contexts(...) } \arguments{ \item{...}{additional arguments to customize the API request (see \code{\link{rotl}} package documentation).} } \value{ Returns invisibly a list for each major clades (e.g., animals, microbes, plants, fungi, life) whose elements contains the possible contexts. } \description{ This function returns a list of pre-defined taxonomic contexts (i.e. clades) which can be used to limit the scope of tnrs queries. } \details{ Taxonomic contexts are available to limit the scope of TNRS searches. These contexts correspond to uncontested higher taxa such as 'Animals' or 'Land plants'. This service returns a list containing all available taxonomic context names, which may be used as input (via the \code{context_name} argument in other functions) to limit the search scope of other services including \code{\link{tnrs_match_names}}. } rotl/man/tax_lineage.Rd0000644000176200001440000000163315132136164014561 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods.R, R/taxonomy.R \name{tax_lineage} \alias{tax_lineage} \alias{tax_lineage.taxon_info} \title{Lineage of a taxon} \usage{ tax_lineage(tax, ...) \method{tax_lineage}{taxon_info}(tax, ...) } \arguments{ \item{tax}{an object created by \code{\link{taxonomy_taxon_info}} using the argument \code{include_lineage=TRUE}.} \item{...}{additional arguments (currently unused).} } \value{ A list with one slot per taxon that contains a data frame with 3 columns: the taxonomy rank, the name, and unique name for all taxa included in the lineage of the taxon up to the root of the tree. } \description{ Extract the lineage information (higher taxonomy) from an object returned by \code{\link{taxonomy_taxon_info}}. } \details{ The object passed to this function must have been created using the argument \code{include_lineage=TRUE}. } rotl/man/get_study.Rd0000644000176200001440000000374215132136164014313 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/studies.R \name{get_study} \alias{get_study} \title{Get all the trees associated with a particular study} \usage{ get_study( study_id = NULL, object_format = c("phylo", "nexml"), file_format, file, ... ) } \arguments{ \item{study_id}{the study ID for the study of interest (character)} \item{object_format}{the class of the object the query should return (either \code{phylo} or \code{nexml}). Ignored if \code{file_format} is specified.} \item{file_format}{the format of the file to be generated (\code{newick}, \code{nexus}, \code{nexml} or \code{json}).} \item{file}{the file name where the output of the function will be saved.} \item{...}{additional arguments to customize the API request (see \code{\link{rotl}} package documentation).} } \value{ if \code{file_format} is missing, an object of class \code{phylo} or \code{nexml}, otherwise a logical indicating whether the file was successfully created. } \description{ Returns the trees associated with a given study } \details{ If \code{file_format} is missing, the function returns an object of the class \code{phylo} from the \code{ape} package (default), or an object of the class \code{nexml} from the \code{RNeXML} package. Otherwise \code{file_format} can be either \code{newick}, \code{nexus}, \code{nexml} or \code{json}, and the function will generate a file of the selected format. In this case, a file name needs to be provided using the argument \code{file}. If a file with the same name already exists, it will be silently overwritten. } \examples{ \dontrun{ that_one_study <- get_study(study_id="pg_719", object_format="phylo") if (require(RNeXML)) { ## if RNeXML is installed get the object directly nexml_study <- get_study(study_id="pg_719", object_format="nexml") } else { ## otherwise write it to a file get_study(study_id="pg_719", file_format="nexml", file=tempfile(fileext=".nexml")) } } } \seealso{ \code{\link{get_study_meta}} } rotl/man/rotl.Rd0000644000176200001440000000472515132140124013255 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/rotl-package.R \docType{package} \name{rotl} \alias{rotl-package} \alias{rotl} \title{An Interface to the Open Tree of Life API} \description{ The Open Tree of Life is an NSF funded project that is generating an online, comprehensive phylogenetic tree for 1.8 million species. \code{rotl} provides an interface that allows you to query and retrieve the parts of the tree of life that is of interest to you. } \details{ \code{rotl} provides function to most of the end points the API provides. The documentation of the API is available at: \url{https://github.com/OpenTreeOfLife/opentree/wiki/Open-Tree-of-Life-APIs} } \section{Customizing API calls}{ All functions that use API end points can take 2 arguments to customize the API call and are passed as \code{...} arguments. \describe{ \item{ \code{otl_v}}{This argument controls which version of the API your call is using. The default value for this argument is a call to the non-exported function \code{otl_version()} which returns the current version of the Open Tree of Life APIs (v2).} \item{ \code{dev_url}}{This argument controls whether to use the development version of the API. By default, \code{dev_url} is set to \code{FALSE}, using \code{dev_url = TRUE} in your function calls will use the development version.} } For example, to use the development version of the API, you could use: \code{tnrs_match_names("anas", dev_url=TRUE)} Additional arguments can also be passed to the \code{\link[httr]{GET}} and \code{\link[httr]{POST}} methods. } \section{Acknowledgments}{ This package was started during the Open Tree of Life Hackathon organized by the OpenTree of Life, the NESCent Hackathon Interoperability Phylogenetic group, and Arbor. } \seealso{ Useful links: \itemize{ \item \url{https://docs.ropensci.org/rotl/} \item \url{https://github.com/ropensci/rotl} \item Report bugs at \url{https://github.com/ropensci/rotl/issues} } } \author{ \strong{Maintainer}: Francois Michonneau \email{francois.michonneau@gmail.com} (\href{https://orcid.org/0000-0002-9092-966X}{ORCID}) Authors: \itemize{ \item Joseph Brown (\href{https://orcid.org/0000-0002-3835-8062}{ORCID}) \item David Winter (\href{https://orcid.org/0000-0002-6165-0029}{ORCID}) } Other contributors: \itemize{ \item Scott Chamberlain (\href{https://orcid.org/0000-0003-1444-9135}{ORCID}) [reviewer] } } rotl/man/study_external_IDs.Rd0000644000176200001440000000256215132136164016114 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/external_data.R \name{study_external_IDs} \alias{study_external_IDs} \title{Get external identifiers for data associated with an Open Tree study} \usage{ study_external_IDs(study_id) } \arguments{ \item{study_id}{An open tree study ID} } \value{ A study_external_data object (which inherits from a list) which contains some of the following. doi, character, the DOI for the paper describing this study external_data_url, character, a URL to an external data repository (e.g. a treebase entry) if one exists. pubmed_id character, the unique ID for this study in the NCBI's pubmed database popset_ids character, vector of IDs for the NCBI's popset database nucleotide_ids character, vector of IDs for the NCBI's nucleotide database } \description{ Data associated with studies contributing to the Open Tree synthesis may be available from other databases. In particular, trees and alignments may be available from treebase and DNA sequences and bibliographic information associated with a given study may be available from the NCBI. This function retrieves that information for a given study. } \examples{ \dontrun{ flies <- studies_find_studies(property="ot:focalCladeOTTTaxonName", value="Drosophilidae") study_external_IDs(flies[2,]$study_ids) } } \seealso{ studies_find_studies (used to discover study IDs) } rotl/man/tnrs_match_names.Rd0000644000176200001440000000714215132136164015627 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/tnrs.R \name{tnrs_match_names} \alias{tnrs_match_names} \title{Match names to the Open Tree Taxonomy} \usage{ tnrs_match_names( names = NULL, context_name = "All life", do_approximate_matching = TRUE, ids = NULL, include_suppressed = FALSE, ... ) } \arguments{ \item{names}{taxon names to be queried. Currently limited to 10,000 names for exact matches and 2,500 names for approximate matches (character vector)} \item{context_name}{name of the taxonomic context to be searched (length-one character vector or \code{NULL}). Must match (case sensitive) one of the values returned by \code{\link{tnrs_contexts}}. Default to "All life".} \item{do_approximate_matching}{A logical indicating whether or not to perform approximate string (a.k.a. \dQuote{fuzzy}) matching. Using \code{FALSE} will greatly improve speed. Default, however, is \code{TRUE}.} \item{ids}{A vector of ids to use for identifying names. These will be assigned to each name in the names array. If ids is provided, then ids and names must be identical in length.} \item{include_suppressed}{Ordinarily, some quasi-taxa, such as incertae sedis buckets and other non-OTUs, are suppressed from TNRS results. If this parameter is true, these quasi-taxa are allowed as possible TNRS results.} \item{...}{additional arguments to customize the API request (see \code{\link{rotl}} package documentation).} } \value{ A data frame summarizing the results of the query. The original query output is appended as an attribute to the returned object (and can be obtained using \code{attr(object, "original_response")}). } \description{ Match taxonomic names to the Open Tree Taxonomy. } \details{ Accepts one or more taxonomic names and returns information about potential matches for these names to known taxa in the Open Tree Taxonomy. This service uses taxonomic contexts to disambiguate homonyms and misspelled names; a context may be specified using the \code{context_name} argument. The default value for \code{context_name} is "All life". If no context is specified (i.e., \code{context_name} is set to \code{NULL}), then the context will be inferred (i.e., the shallowest taxonomic context that contains all unambiguous names in the input). Taxonomic contexts are uncontested higher taxa that have been selected to allow limits to be applied to the scope of TNRS searches (e.g. 'match names only within flowering plants'). Once a context has been identified (either user-specified or inferred), all taxon name matches will performed only against taxa within that context. For a list of available taxonomic contexts, see \code{\link{tnrs_contexts}}. A name is considered unambiguous if it is not a synonym and has only one exact match to any taxon name in the entire taxonomy. When the name search returns multiple matches, the taxon with the highest match score is returned. If the name returned is not the one you intended, you can use the \code{inspect} function to check the other taxa returned by your search. The \href{https://docs.ropensci.org/rotl/articles/rotl.html#how-to-change-the-ott-ids-assigned-to-my-taxa}{Getting Started vignette} has more information on how to do this. Several functions listed in the \sQuote{See also} section can be used to inspect and manipulate the object generated by this function. } \examples{ \dontrun{ deuterostomes <- tnrs_match_names(names=c("echinodermata", "xenacoelomorpha", "chordata", "hemichordata")) } } \seealso{ \code{\link{inspect.match_names}}, \code{\link{update.match_names}}, \code{\link{synonyms.match_names}}. } rotl/man/get_study_tree.Rd0000644000176200001440000000434515132136164015332 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/studies.R \name{get_study_tree} \alias{get_study_tree} \title{Study Tree} \usage{ get_study_tree( study_id = NULL, tree_id = NULL, object_format = c("phylo"), tip_label = c("original_label", "ott_id", "ott_taxon_name"), file_format, file, deduplicate = TRUE, ... ) } \arguments{ \item{study_id}{the identifier of a study (character)} \item{tree_id}{the identifier of a tree within the study} \item{object_format}{the class of the object to be returned (default and currently only possible value \code{phylo} from the \code{ape} package).} \item{tip_label}{the format of the tip labels. \dQuote{\code{original_label}} (default) returns the original labels as provided in the study, \dQuote{\code{ott_id}} labels are replaced by their ott IDs, \dQuote{\code{ott_taxon_name}} labels are replaced by their Open Tree Taxonomy taxon name.} \item{file_format}{the format of the file to be generated (\code{newick} default, \code{nexus}, or \code{json}).} \item{file}{the file name where the output of the function will be saved.} \item{deduplicate}{logical (default \code{TRUE}). If the tree returned by the study contains duplicated taxon names, should they be made unique? It is normally illegal for NEXUS/Newick tree strings to contain duplicated tip names. This is a workaround to circumvent this requirement. If \code{TRUE}, duplicated tip labels will be appended \code{_1}, \code{_2}, etc.} \item{...}{additional arguments to customize the API request (see \code{\link{rotl}} package documentation).} } \value{ if \code{file_format} is missing, an object of class \code{phylo}, otherwise a logical indicating whether the file was successfully created. } \description{ Returns a specific tree from within a study } \examples{ \dontrun{ tree <- get_study_tree(study_id="pg_1144", tree_id="tree2324") ## comparison of the first few tip labels depending on the options used head(get_study_tree(study_id="pg_1144", tree_id="tree2324", tip_label="original_label")$tip.label) head(get_study_tree(study_id="pg_1144", tree_id="tree2324", tip_label="ott_id")$tip.label) head(get_study_tree(study_id="pg_1144", tree_id="tree2324", tip_label="ott_taxon_name")$tip.label) } } rotl/man/is_in_tree.Rd0000644000176200001440000000263115132136164014420 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/is_in_tree.R \name{is_in_tree} \alias{is_in_tree} \title{Check that OTT ids occur in the Synthetic Tree} \usage{ is_in_tree(ott_ids, ...) } \arguments{ \item{ott_ids}{a vector of Open Tree Taxonomy identifiers} \item{...}{additional arguments to customize the API request (see \code{\link{rotl}} package documentation).} } \value{ A named logical vector. \code{TRUE} indicates that the OTT id is in the synthetic tree, and \code{FALSE} that it is not. } \description{ Some valid taxonomic names do not occur in the Synthetic Tree. This convenience function allows you to check whether a given Open Tree Taxonomy identifier (OTT id) is in the tree. A taxonomic name may not occur in the synthetic tree because (1) it is an extinct or invalid taxon, or (2) it is part of a group that is not monophyletic in the tree. } \examples{ \dontrun{ plant_families <- c("Asteraceae", "Solanaceae", "Poaceae", "Amaranthaceae", "Zamiaceae", "Araceae", "Juncaceae") matched_names <- tnrs_match_names(plant_families) ## This fails because some ott ids are not in the tree ## plant_tree <- tol_induced_subtree(ott_id(matched_names)) ## So let's check which ones are actually in the tree first: in_tree <- is_in_tree(ott_id(matched_names)) ## This now works: plant_tree <- tol_induced_subtree(ott_id(matched_names)[in_tree]) } } rotl/man/tnrs_infer_context.Rd0000644000176200001440000000177115132136164016221 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/tnrs.R \name{tnrs_infer_context} \alias{tnrs_infer_context} \title{Infer the taxonomic context from a list of names} \usage{ tnrs_infer_context(names = NULL, ...) } \arguments{ \item{names}{Vector of taxon names.} \item{...}{additional arguments to customize the API request (see \code{\link{rotl}} package documentation).} } \value{ A list including the context name, the context ott id and possibly the names in the query that have an ambiguous taxonomic meaning in the query. } \description{ Return a taxonomic context given a list of taxonomic names } \details{ Find the least inclusive taxonomic context that includes all the unambiguous names in the input set. Unambiguous names are names with exact matches to non-homonym taxa. Ambiguous names (those without exact matches to non-homonym taxa) are indicated in results. } \examples{ \dontrun{ res <- tnrs_infer_context(names=c("Stellula calliope", "Struthio camelus")) } } rotl/man/get_study_subtree.Rd0000644000176200001440000000430715132136164016042 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/studies.R \name{get_study_subtree} \alias{get_study_subtree} \title{Study Subtree} \usage{ get_study_subtree( study_id, tree_id, subtree_id, object_format = c("phylo"), tip_label = c("original_label", "ott_id", "ott_taxon_name"), file_format, file, deduplicate = TRUE, ... ) } \arguments{ \item{study_id}{the study identifier (character)} \item{tree_id}{the tree identifier (character)} \item{subtree_id, }{either a node id that specifies a subtree or \dQuote{ingroup} which returns the ingroup for this subtree.} \item{object_format}{the class of the object returned by the function (default, and currently only possibility \code{phylo} from the \code{ape} package)} \item{tip_label}{the format of the tip labels. \dQuote{\code{original_label}} (default) returns the original labels as provided in the study, \dQuote{\code{ott_id}} labels are replaced by their ott IDs, \dQuote{\code{ott_taxon_name}} labels are replaced by their Open Tree Taxonomy taxon name.} \item{file_format}{character, the file format to use to save the results of the query (possible values, \sQuote{newick} or \sQuote{nexus}).} \item{file}{character, the path and file name where the output should be written.} \item{deduplicate}{logical (default \code{TRUE}). If the tree returned by the study contains duplicated taxon names, should they be made unique? It is normally illegal for NEXUS/Newick tree strings to contain duplicated tip names. This is a workaround to circumvent this requirement. If \code{TRUE}, duplicated tip labels will be appended \code{_1}, \code{_2}, etc.} \item{...}{additional arguments to customize the API request (see \code{\link{rotl}} package documentation).} } \description{ Retrieve subtree from a specific tree in the Open Tree of Life data store } \examples{ \dontrun{ small_tr <- get_study_subtree(study_id="pg_1144", tree_id="tree5800", subtree_id="node991044") ingroup <- get_study_subtree(study_id="pg_1144", tree_id="tree5800", subtree_id="ingroup") nexus_file <- tempfile(fileext=".nex") get_study_subtree(study_id="pg_1144", tree_id="tree5800", subtree_id="ingroup", file=nexus_file, file_format="nexus") } } rotl/man/taxon_external_IDs.Rd0000644000176200001440000000167515132136164016101 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/external_data.R \name{taxon_external_IDs} \alias{taxon_external_IDs} \title{Get external identifiers for data associated with an Open Tree taxon} \usage{ taxon_external_IDs(taxon_id) } \arguments{ \item{taxon_id}{An open tree study ID} } \value{ a data.frame in which each row represents a unique record in an external database. The column "source" provides and abbreviated name for the database, and "id" the unique ID for the record. } \description{ The Open Tree taxonomy is a synthesis of multiple reference taxonomies. This function retrieves identifiers to external taxonomic records that have contributed the rank, position and definition of a given Open Tree taxon. } \examples{ \dontrun{ gibbon_IDs <- taxon_external_IDs(712902) } } \seealso{ tnrs_matchnames, which can be used to search for taxa by name. taxonomy_taxon, for more information about a given taxon. } rotl/man/match_names.Rd0000644000176200001440000000500015132136164014550 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/match_names.R \name{inspect.match_names} \alias{inspect.match_names} \alias{inspect} \alias{update.match_names} \title{Inspect and Update alternative matches for a name returned by tnrs_match_names} \usage{ \method{inspect}{match_names}(response, row_number, taxon_name, ott_id, ...) inspect(response, ...) \method{update}{match_names}(object, row_number, taxon_name, ott_id, new_row_number, new_ott_id, ...) } \arguments{ \item{response}{an object generated by the \code{\link{tnrs_match_names}} function} \item{row_number}{the row number corresponding to the name to inspect} \item{taxon_name}{the taxon name corresponding to the name to inspect} \item{ott_id}{the ott id corresponding to the name to inspect} \item{...}{currently ignored} \item{object}{an object created by \code{\link{tnrs_match_names}}} \item{new_row_number}{the row number in the output of \code{\link{inspect}} to replace the taxa specified by \code{row_number}, \code{taxon_name}, or \code{ott_id}.} \item{new_ott_id}{the ott id of the taxon to replace the taxa specified by \code{row_number}, \code{taxon_name}, or \code{ott_id}.} } \value{ a data frame } \description{ Taxonomic names may have different meanings in different taxonomic contexts, as the same genus name can be applied to animals and plants for instance. Additionally, the meaning of a taxonomic name may have change throughout its history, and may have referred to a different taxon in the past. In such cases, a given names might have multiple matches in the Open Tree Taxonomy. These functions allow users to inspect (and update) alternative meaning of a given name and its current taxonomic status according to the Open Tree Taxonomy. } \details{ To inspect alternative taxonomic meanings of a given name, you need to provide the object resulting from a call to the tnrs_match_names function, as well as one of either the row number corresponding to the name in this object, the name itself (as used in the original query), or the ott_id listed for this name. To update one of the name, you also need to provide the row number in which the name to be replaced appear or its ott id. } \examples{ \dontrun{ matched_names <- tnrs_match_names(c("holothuria", "diadema", "boletus")) inspect(matched_names, taxon_name="diadema") new_matched_names <- update(matched_names, taxon_name="diadema", new_ott_id = 631176) new_matched_names } } \seealso{ \code{\link{tnrs_match_names}} } rotl/man/tol_subtree.Rd0000644000176200001440000000302015132136164014620 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/tol.R \name{tol_subtree} \alias{tol_subtree} \title{Extract a subtree from the synthetic tree} \usage{ tol_subtree(ott_id = NULL, node_id = NULL, label_format = NULL, file, ...) } \arguments{ \item{ott_id}{Numeric. The ott id of the node in the tree that should serve as the root of the tree returned.} \item{node_id}{Character. The node id of the node in the tree that should serve as the root of the tree returned.} \item{label_format}{Character. Defines the label type; one of \dQuote{\code{name}}, \dQuote{\code{id}}, or \dQuote{\code{name_and_id}} (the default).} \item{file}{If specified, the function will write the subtree to a file in newick format.} \item{...}{additional arguments to customize the API call (see \code{\link{rotl}} for more information).} } \value{ If no value is specified to the \code{file} argument (default), a phylogenetic tree of class \code{phylo}. Otherwise, the function returns invisibly a logical indicating whether the file was successfully created. } \description{ Extract a subtree from the synthetic tree from an Open Tree node id. } \details{ Given a node, return the subtree of the synthetic tree descended from that node. The start node may be specified using either a node id or an ott id, but not both. If the specified node is not in the synthetic tree an error will be returned. There is a size limit of 25000 tips for this method. } \examples{ \dontrun{ res <- tol_subtree(ott_id=241841)} } rotl/man/get_study_meta.Rd0000644000176200001440000000372615132136164015323 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/studies-methods.R, R/studies.R \name{get_tree_ids} \alias{get_tree_ids} \alias{get_publication} \alias{candidate_for_synth} \alias{get_study_year} \alias{get_tree_ids.study_meta} \alias{get_publication.study_meta} \alias{candidate_for_synth.study_meta} \alias{get_study_year.study_meta} \alias{get_study_meta} \title{Study Metadata} \usage{ get_tree_ids(sm) get_publication(sm) candidate_for_synth(sm) get_study_year(sm) \method{get_tree_ids}{study_meta}(sm) \method{get_publication}{study_meta}(sm) \method{candidate_for_synth}{study_meta}(sm) \method{get_study_year}{study_meta}(sm) get_study_meta(study_id, ...) } \arguments{ \item{sm}{an object created by \code{get_study_meta}} \item{study_id}{the study identifier (character)} \item{...}{additional arguments to customize the API request (see \code{\link{rotl}} package documentation).} } \value{ named-list containing the metadata associated with the study requested } \description{ Retrieve metadata about a study in the Open Tree of Life datastore } \details{ \code{get_study_meta} returns a long list of attributes for the studies that are contributing to the synthetic tree. To help with the extraction of relevant information from this list, several helper functions exists: \describe{ \item{get_tree_ids}{The identifiers of the trees associated with the study.} \item{get_publication}{The citation information of the publication for the study. The DOI (or URL) for the study is available as an attribute to the returned object (i.e., \code{attr(object, "DOI")} ).} \item{candidate_for_synth}{The identifier of the tree(s) from the study used in the synthetic tree. This is a subset of the result of \code{get_tree_ids}.} \item{get_study_year}{The year of publication of the study.} } } \examples{ \dontrun{ req <- get_study_meta("pg_719") get_tree_ids(req) candidate_for_synth(req) get_publication(req) get_study_year(req) } } rotl/man/taxonomy_taxon_info.Rd0000644000176200001440000000445715132136164016412 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/taxonomy.R \name{taxonomy_taxon_info} \alias{taxonomy_taxon_info} \alias{tax_rank.taxon_info} \alias{tax_name.taxon_info} \alias{unique_name.taxon_info} \alias{synonyms.taxon_info} \alias{ott_id.taxon_info} \alias{tax_sources.taxon_info} \alias{is_suppressed.taxon_info} \alias{flags.taxon_info} \title{Taxon information} \usage{ taxonomy_taxon_info( ott_ids, include_children = FALSE, include_lineage = FALSE, include_terminal_descendants = FALSE, ... ) \method{tax_rank}{taxon_info}(tax, ...) \method{tax_name}{taxon_info}(tax, ...) \method{unique_name}{taxon_info}(tax, ...) \method{synonyms}{taxon_info}(tax, ...) \method{ott_id}{taxon_info}(tax, ...) \method{tax_sources}{taxon_info}(tax, ...) \method{is_suppressed}{taxon_info}(tax, ...) \method{flags}{taxon_info}(tax, ...) } \arguments{ \item{ott_ids}{the ott ids of the taxon of interest (numeric or character containing only numbers)} \item{include_children}{whether to include information about all the children of this taxon. Default \code{FALSE}.} \item{include_lineage}{whether to include information about all the higher level taxa that include the \code{ott_ids}. Default \code{FALSE}.} \item{include_terminal_descendants}{whether to include the list of terminal \code{ott_ids} contained in the \code{ott_ids} provided.} \item{...}{additional arguments to customize the API request (see \code{\link{rotl}} package documentation).} \item{tax}{an object generated by the \code{taxonomy_taxon_info} function} } \value{ \code{taxonomy_taxon_info} returns a list detailing information about the taxa. \code{tax_rank} and \code{tax_name} return a vector. \code{synonyms} returns a list whose elements are the synonyms for each of the \code{ott_id} requested. } \description{ Information about taxa. } \details{ Given a vector of ott ids, \code{taxonomy_taxon_info} returns information about the specified taxa. The functions \code{tax_rank}, \code{tax_name}, and \code{synonyms} can extract this information from an object created by the \code{taxonomy_taxon_info()}. } \examples{ \dontrun{ req <- taxonomy_taxon_info(ott_id=515698) tax_rank(req) tax_name(req) synonyms(req) } } \seealso{ \code{\link{tnrs_match_names}} to obtain \code{ott_id} from a taxonomic name. } rotl/man/tol_mrca.Rd0000644000176200001440000001336515132136164014106 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/tol.R \name{tol_mrca} \alias{tol_mrca} \alias{tax_sources.tol_mrca} \alias{unique_name.tol_mrca} \alias{tax_name.tol_mrca} \alias{tax_rank.tol_mrca} \alias{ott_id.tol_mrca} \alias{source_list.tol_mrca} \title{MRCA of taxa from the synthetic tree} \usage{ tol_mrca(ott_ids = NULL, node_ids = NULL, ...) \method{tax_sources}{tol_mrca}(tax, ...) \method{unique_name}{tol_mrca}(tax, ...) \method{tax_name}{tol_mrca}(tax, ...) \method{tax_rank}{tol_mrca}(tax, ...) \method{ott_id}{tol_mrca}(tax, ...) \method{source_list}{tol_mrca}(tax, ...) } \arguments{ \item{ott_ids}{Numeric vector. The ott ids for which the MRCA is desired.} \item{node_ids}{Character vector. The node ids for which the MRCA is desired.} \item{...}{additional arguments to customize the API call (see \code{\link{rotl}} for more information).} \item{tax}{an object returned by \code{tol_mrca()}.} } \value{ An invisible list of the MRCA node properties: \describe{ \item{mrca}{List of node properties.} \describe{ \item{node_id}{String. The canonical identifier of the node.} \item{num_tips}{Numeric. The number of descendant tips.} \item{taxon}{A list of taxonomic properties. Only returned if the queried node is a taxon. (If the node is not a taxon, a \code{nearest_taxon} list is returned (see below)).} \describe{ \item{ott_id}{Numeric. The OpenTree Taxonomy ID (ottID).} \item{name}{String. The taxonomic name of the queried node.} \item{unique_name}{String. The string that uniquely identifies the taxon in OTT.} \item{rank}{String. The taxonomic rank of the taxon in OTT.} \item{tax_sources}{List. A list of identifiers for taxonomic sources, such as other taxonomies, that define taxa judged equivalent to this taxon.} } The following properties list support/conflict for the node across synthesis source trees. All properties involve sourceid keys and nodeid values (see \code{source_id_map} below) Not all properties are are present for every node. \item{partial_path_of}{List. The edge below this synthetic tree node is compatible with the edge below each of these input tree nodes (one per tree). Each returned element is reported as sourceid:nodeid.} \item{supported_by}{List. Input tree nodes (one per tree) that support this synthetic tree node. Each returned element is reported as sourceid:nodeid.} \item{terminal}{List. Input tree nodes (one per tree) that are equivalent to this synthetic tree node (via an exact mapping, or the input tree terminal may be the only terminal descended from this synthetic tree node. Each returned element is reported as sourceid:nodeid.} \item{conflicts_with}{Named list of lists. Names correspond to sourceid keys. Each list contains input tree node ids (one or more per tree) that conflict with this synthetic node.} } \item{nearest_taxon}{A list of taxonomic properties of the nearest rootward taxon node to the MRCA node. Only returned if the MRCA node is a not taxon (otherwise the \code{taxon} list above is returned).} \describe{ \item{ott_id}{Numeric. The OpenTree Taxonomy ID (ottID).} \item{name}{String. The taxonomic name of the queried node.} \item{unique_name}{String. The string that uniquely identifies the taxon in OTT.} \item{rank}{String. The taxonomic rank of the taxon in OTT.} \item{tax_sources}{List. A list of identifiers for taxonomic sources, such as other taxonomies, that define taxa judged equivalent to this taxon.} } \item{source_id_map}{Named list of lists. Names correspond to the sourceid keys used in the support/conflict properties of the \code{mrca} list above. Source trees will have the following properties:} \describe{ \item{git_sha}{The git SHA identifying a particular source version.} \item{tree_id}{The tree id associated with the study id used.} \item{study_id}{The study identifier. Will typically include a prefix ("pg_" or "ot_").} } The only sourceid that does not correspond to a source tree is the taxonomy, which will have the name "ott"+`taxonomy_version`, and the value is the ott_id of the taxon in that taxonomy version. "Taxonomy" will only ever appear in \code{supported_by}. } } \description{ Most Recent Common Ancestor for a set of nodes } \details{ Get the MRCA of a set of nodes on the current synthetic tree. Accepts any combination of node ids and ott ids as input. Returns information about the most recent common ancestor (MRCA) node as well as the most recent taxonomic ancestor (MRTA) node (the closest taxonomic node to the MRCA node in the synthetic tree; the MRCA and MRTA may be the same node). If they are the same, the taxonomic information will be in the \code{mrca} slot, otherwise they will be in the \code{nearest_taxon} slot of the list. If any of the specified nodes is not in the synthetic tree an error will be returned. Taxonomic methods (\code{tax_sources()}, \code{ott_id()}, \code{unique_name()}, ...) are available on the objects returned by \code{tol_mrca()}. If the MRCA node is MRTA, the name of the object returned by these methods will start with \sQuote{ott}, otherwise it will start with \sQuote{mrca}. } \examples{ \dontrun{ birds_mrca <- tol_mrca(ott_ids=c(412129, 119214)) ott_id(birds_mrca) tax_sources(birds_mrca) } } rotl/man/taxonomy-methods.Rd0000644000176200001440000000165715132136164015626 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods.R \name{tax_rank} \alias{tax_rank} \alias{ott_id} \alias{synonyms} \alias{tax_sources} \alias{is_suppressed} \alias{unique_name} \alias{tax_name} \title{Methods for Taxonomy} \usage{ tax_rank(tax, ...) ott_id(tax, ...) synonyms(tax, ...) tax_sources(tax, ...) is_suppressed(tax, ...) unique_name(tax, ...) tax_name(tax, ...) } \arguments{ \item{tax}{an object returned by \code{\link{taxonomy_taxon_info}}, \code{\link{taxonomy_mrca}}, or \code{\link{tnrs_match_names}}} \item{...}{additional arguments (see \code{\link{tnrs_match_names}})} } \description{ Methods for dealing with objects containing taxonomic information (Taxonomy, TNRS endpoints) } \details{ This is the page for the generic methods. See the help pages for \code{\link{taxonomy_taxon_info}}, \code{\link{taxonomy_mrca}}, and \code{\link{tnrs_match_names}} for more information. } rotl/man/studies_find_studies.Rd0000644000176200001440000000477615132136164016534 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/studies.R \name{studies_find_studies} \alias{studies_find_studies} \title{Find a Study} \usage{ studies_find_studies( property = NULL, value = NULL, verbose = FALSE, exact = FALSE, detailed = TRUE, ... ) } \arguments{ \item{property}{The property to be searched on (character)} \item{value}{The property value to be searched on (character)} \item{verbose}{Should the output include all metadata (logical default \code{FALSE})} \item{exact}{Should exact matching be used? (logical, default \code{FALSE})} \item{detailed}{If \code{TRUE} (default), the function will return a data frame that summarizes information about the study (see \sQuote{Value}). Otherwise, it only returns the study identifiers.} \item{...}{additional arguments to customize the API request (see \code{\link{rotl}} package documentation).} } \value{ If \code{detailed=TRUE}, the function returns a data frame listing the study id (\code{study_ids}), the number of trees associated with this study (\code{n_trees}), the tree ids (at most 5) associated with the studies (\code{tree_ids}), the tree id that is a candidate for the synthetic tree if any (\code{candidate}), the year of publication of the study (\code{study_year}), the title of the publication for the study (\code{title}), and the DOI (Digital Object Identifier) for the study (\code{study_doi}). If \code{detailed=FALSE}, the function returns a data frame with a single column containing the study identifiers. } \description{ Return the identifiers of studies that match given properties } \examples{ \dontrun{ ## To match a study for which the identifier is already known one_study <- studies_find_studies(property="ot:studyId", value="pg_719") list_trees(one_study) ## To find studies pertaining to Mammals mammals <- studies_find_studies(property="ot:focalCladeOTTTaxonName", value="mammalia") ## To extract the tree identifiers for each of the studies list_trees(mammals) ## ... or for a given study list_trees(mammals, "ot_308") ## Just the identifiers without other information about the studies mammals <- studies_find_studies(property="ot:focalCladeOTTTaxonName", value="mammalia", detailed=FALSE) } } \seealso{ \code{\link{studies_properties}} which lists properties against which the studies can be searched. \code{\link{list_trees}} that returns a list for all tree ids associated with a study. } rotl/man/taxonomy_about.Rd0000644000176200001440000000211315132136164015343 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/taxonomy.R \name{taxonomy_about} \alias{taxonomy_about} \title{Information about the Open Tree Taxonomy} \usage{ taxonomy_about(...) } \arguments{ \item{...}{additional arguments to customize the API request (see \code{\link{rotl}} package documentation).} } \value{ A list with the following properties: \describe{ \item{weburl}{String. The release page for this version of the taxonomy.} \item{author}{String. The author string.} \item{name}{String. The name of the taxonomy.} \item{source}{String. The full identifying information for this version of the taxonomy.} \item{version}{String. The version number of the taxonomy.} } } \description{ Summary information about the Open Tree Taxonomy (OTT) } \details{ Return metadata and information about the taxonomy itself. Currently, the available metadata is fairly sparse, but includes (at least) the version, and the location from which the complete taxonomy source files can be downloaded. } \examples{ \dontrun{ taxonomy_about() } } rotl/man/strip_ott_ids.Rd0000644000176200001440000000163515132136164015171 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/tol.R \name{strip_ott_ids} \alias{strip_ott_ids} \title{Strip OTT ids from tip labels} \usage{ strip_ott_ids(tip_labels, remove_underscores = FALSE) } \arguments{ \item{tip_labels}{a character vector containing tip labels (most likely the \code{tip.label} element from a tree returned by \code{\link{tol_induced_subtree}}} \item{remove_underscores}{logical (defaults to FALSE). If set to TRUE underscores in tip labels are converted to spaces} } \value{ A character vector containing the contents of \code{tip_labels} with any OTT ids removed. } \description{ Strip OTT ids from tip labels } \examples{ \dontrun{ genera <- c("Perdix", "Setophaga", "Cinclus", "Struthio") tr <- tol_induced_subtree(ott_ids=c(102710, 285198, 267845, 292466)) tr$tip.label \%in\% genera tr$tip.label <- strip_ott_ids(tr$tip.label) tr$tip.label \%in\% genera } } rotl/man/studies_find_trees.Rd0000644000176200001440000000562715132136164016172 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/studies.R \name{studies_find_trees} \alias{studies_find_trees} \title{Find Trees} \usage{ studies_find_trees( property = NULL, value = NULL, verbose = FALSE, exact = FALSE, detailed = TRUE, ... ) } \arguments{ \item{property}{The property to be searched on (character)} \item{value}{The property-value to be searched on (character)} \item{verbose}{Should the output include all metadata? (logical, default \code{FALSE})} \item{exact}{Should exact matching be used for the value? (logical, default \code{FALSE})} \item{detailed}{Should a detailed report be provided? If \code{TRUE} (default), the output will include metadata about the study that include trees matching the property. Otherwise, only information about the trees will be provided.} \item{...}{additional arguments to customize the API request (see \code{\link{rotl}} package documentation).} } \value{ A data frame that summarizes the trees found (and their associated studies) for the requested criteria. If a study has more than 5 trees, the \code{tree_ids} of the first ones will be shown, followed by \code{...} to indicate that more are present. If \code{detailed=FALSE}, the data frame will include the study ids of the study (\code{study_ids}), the number of trees in this study that match the search criteria (\code{n_matched_trees}), the tree ids that match the search criteria (\code{match_tree_ids}). If \code{detailed=TRUE}, in addition of the fields listed above, the data frame will also contain the total number of trees associated with the study (\code{n_trees}), all the tree ids associated with the study (\code{tree_ids}), the tree id that is a potential candidate for inclusion in the synthetic tree (if any) (\code{candidate}), the year the study was published (\code{study_year}), the title of the study (\code{title}), the DOI for the study (\code{study_doi}). } \description{ Return a list of studies for which trees match a given set of properties } \details{ The list of possible values to be used as values for the argument \code{property} can be found using the function \code{\link{studies_properties}}. } \examples{ \dontrun{ res <- studies_find_trees(property="ot:ottTaxonName", value="Drosophila", detailed=FALSE) ## summary of the trees and associated studies that match this criterion res ## With metadata about the studies (default) res <- studies_find_trees(property="ot:ottTaxonName", value="Drosophila", detailed=TRUE) ## The list of trees for each study that match the search criteria list_trees(res) ## the trees for a given study list_trees(res, study_id = "pg_2769") } } \seealso{ \code{\link{studies_properties}} which lists properties the studies can be searched on. \code{\link{list_trees}} for listing the trees that match the query. } rotl/man/studies_properties.Rd0000644000176200001440000000220315132136164016227 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/studies.R \name{studies_properties} \alias{studies_properties} \title{Properties of the Studies} \usage{ studies_properties(...) } \arguments{ \item{...}{additional arguments to customize the API request (see \code{\link{rotl}} package documentation).} } \value{ A list of the study properties that can be used to find studies and trees that are contributing to the synthetic tree. } \description{ Return the list of study properties that can be used to search studies and trees used in the synthetic tree. } \details{ The list returned has 2 elements \code{tree_properties} and \code{studies_properties}. Each of these elements lists additional arguments to customize the API request properties that can be used to search for trees and studies that are contributing to the synthetic tree. The definitions of these properties are available from \url{https://github.com/OpenTreeOfLife/phylesystem-api/wiki/NexSON} } \examples{ \dontrun{ all_the_properties <- studies_properties() unlist(all_the_properties$tree_properties) } } \seealso{ \code{\link{studies_find_trees}} } rotl/man/figures/0000755000176200001440000000000015132136164013453 5ustar liggesusersrotl/man/figures/logo.svg0000644000176200001440000035014715132136164015146 0ustar liggesusers rotl/man/tol_node_info.Rd0000644000176200001440000001036315132136164015117 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods.R, R/tol.R \name{tol_lineage} \alias{tol_lineage} \alias{tol_node_info} \alias{tax_rank.tol_node} \alias{tax_sources.tol_node} \alias{unique_name.tol_node} \alias{tax_name.tol_node} \alias{ott_id.tol_node} \alias{source_list.tol_node} \alias{tax_lineage.tol_node} \alias{tol_lineage.tol_node} \title{Node info} \usage{ tol_lineage(tax, ...) tol_node_info(ott_id = NULL, node_id = NULL, include_lineage = FALSE, ...) \method{tax_rank}{tol_node}(tax, ...) \method{tax_sources}{tol_node}(tax, ...) \method{unique_name}{tol_node}(tax, ...) \method{tax_name}{tol_node}(tax, ...) \method{ott_id}{tol_node}(tax, ...) \method{source_list}{tol_node}(tax, ...) \method{tax_lineage}{tol_node}(tax, ...) \method{tol_lineage}{tol_node}(tax, ...) } \arguments{ \item{tax}{an object returned by \code{tol_node_info}.} \item{...}{additional arguments to customize the API call (see ?rotl for more information)} \item{ott_id}{Numeric. The OpenTree taxonomic identifier.} \item{node_id}{Character. The OpenTree node identifier.} \item{include_lineage}{Logical (default = FALSE). Whether to return the lineage of the node from the synthetic tree.} } \value{ \code{tol_node_info} returns an invisible list of summary information about the queried node: \describe{ \item{node_id}{String. The canonical identifier of the node.} \item{num_tips}{Numeric. The number of descendant tips.} \item{partial_path_of}{List. The edge below this synthetic tree node is compatible with the edge below each of these input tree nodes (one per tree). Each returned element is reported as sourceid:nodeid.} \item{query}{ The node id that resolved to this node. This can differ from the node_id field if the query id is not canonical. } \item{taxon}{A list of taxonomic properties. Only returned if the queried node is a taxon. Each source has:} \describe{ \item{ott_id}{Numeric. The OpenTree Taxonomy ID (ottID).} \item{name}{String. The taxonomic name of the queried node.} \item{unique_name}{String. The string that uniquely identifies the taxon in OTT.} \item{rank}{String. The taxonomic rank of the taxon in OTT.} \item{tax_sources}{List. A list of identifiers for taxonomic sources, such as other taxonomies, that define taxa judged equivalent to this taxon.} } The following properties list support/conflict for the node across synthesis source trees. All properties involve sourceid keys and nodeid values (see \code{source_id_map} below). \item{supported_by}{List. Input tree nodes (one per tree) that support this synthetic tree node. Each returned element is reported as sourceid:nodeid.} \item{terminal}{List. Input tree nodes (one per tree) that are equivalent to this synthetic tree node (via an exact mapping, or the input tree terminal may be the only terminal descended from this synthetic tree node. Each returned element is reported as sourceid:nodeid.} \item{conflicts_with}{Named list of lists. Names correspond to sourceid keys. Each list contains input tree node ids (one or more per tree) that conflict with this synthetic node.} } \code{tol_lineage} and \code{tax_lineage} return data frames. \code{tol_lineage} indicate for each ancestor its node identifier, the number of tips descending from that node, and whether it corresponds to a taxonomic level. } \description{ Get summary information about a node in the synthetic tree } \details{ Returns summary information about a node in the graph. The node of interest may be specified using either a node id or an taxon id, but not both. If the specified node or OTT id is not in the graph, an error will be returned. If the argument \code{include_lineage=TRUE} is used, you can use \code{tax_lineage()} or \code{tol_lineage} to return the taxonomic information or the node information for all the ancestors to this node, down to the root of the tree. } \examples{ \dontrun{ birds <- tol_node_info(ott_id=81461, include_lineage=TRUE) source_list(birds) tax_rank(birds) ott_id(birds) tax_lineage(birds) tol_lineage(birds)} } rotl/man/match_names-methods.Rd0000644000176200001440000000355615132136164016227 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/match_names.R, R/methods.R \name{ott_id.match_names} \alias{ott_id.match_names} \alias{flags.match_names} \alias{flags} \title{\code{ott_id} and \code{flags} for taxonomic names matched by \code{tnrs_match_names}} \usage{ \method{ott_id}{match_names}(tax, row_number, taxon_name, ott_id, ...) \method{flags}{match_names}(tax, row_number, taxon_name, ott_id, ...) flags(tax, ...) } \arguments{ \item{tax}{an object returned by \code{\link{tnrs_match_names}}} \item{row_number}{the row number corresponding to the name for which to list the synonyms} \item{taxon_name}{the taxon name corresponding to the name for which to list the synonyms} \item{ott_id}{the ott id corresponding to the name for which to list the synonyms} \item{...}{currently ignored} } \value{ A list of the ott ids or flags for the taxonomic names matched with \code{\link{tnrs_match_names}}, for either one or all the names. } \description{ \code{rotl} provides a collection of functions that allows users to extract relevant information from an object generated by \code{\link{tnrs_match_names}} function. } \details{ These methods optionally accept one of the arguments \code{row_number}, \code{taxon_name} or \code{ott_id} to retrieve the corresponding information for one of the matches in the object returned by the \code{\link{tnrs_match_names}} function. If these arguments are not provided, these methods can return information for the matches currently listed in the object returned by \code{\link{tnrs_match_names}}. } \examples{ \dontrun{ rsp <- tnrs_match_names(c("Diadema", "Tyrannosaurus")) rsp$ott_id # ott id for match currently in use ott_id(rsp) # similar as above but elements are named ## flags() is useful for instance to determine if a taxon is extinct flags(rsp, taxon_name="Tyrannosaurus") } } rotl/man/taxonomy_mrca.Rd0000644000176200001440000000331315132136164015156 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/taxonomy.R \name{taxonomy_mrca} \alias{taxonomy_mrca} \alias{tax_rank.taxon_mrca} \alias{tax_name.taxon_mrca} \alias{ott_id.taxon_mrca} \alias{unique_name.taxon_mrca} \alias{tax_sources.taxon_mrca} \alias{flags.taxon_mrca} \alias{is_suppressed.taxon_mrca} \title{Taxonomic MRCA} \usage{ taxonomy_mrca(ott_ids = NULL, ...) \method{tax_rank}{taxon_mrca}(tax, ...) \method{tax_name}{taxon_mrca}(tax, ...) \method{ott_id}{taxon_mrca}(tax, ...) \method{unique_name}{taxon_mrca}(tax, ...) \method{tax_sources}{taxon_mrca}(tax, ...) \method{flags}{taxon_mrca}(tax, ...) \method{is_suppressed}{taxon_mrca}(tax, ...) } \arguments{ \item{ott_ids}{a vector of ott ids for the taxa whose MRCA is to be found (numeric).} \item{...}{additional arguments to customize the API request (see \code{\link{rotl}} package documentation).} \item{tax}{an object generated by the \code{taxonomy_mrca} function} } \value{ \describe{ \item{\code{taxonomy_mrca}}{ returns a list about the taxonomic information relating to the MRCA for the ott_ids provided. } \item{\code{tax_rank}}{ returns a character vector of the taxonomic rank for the MRCA. } \item{\code{tax_name}}{ returns a character vector the Open Tree Taxonomy name for the MRCA. } \item{\code{ott_id}}{ returns a numeric vector of the ott id for the MRCA. } } } \description{ Taxonomic Least Inclusive Common Ancestor (MRCA) } \details{ Given a set of OTT ids, get the taxon that is the most recent common ancestor (the MRCA) of all the identified taxa. } \examples{ \dontrun{ req <- taxonomy_mrca(ott_ids=c(515698,590452,643717)) tax_rank(req) tax_name(req) ott_id(req) } } rotl/man/tol_about.Rd0000644000176200001440000000761415132136164014276 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/tol.R \name{tol_about} \alias{tol_about} \alias{tax_rank.tol_summary} \alias{tax_sources.tol_summary} \alias{unique_name.tol_summary} \alias{tax_name.tol_summary} \alias{ott_id.tol_summary} \title{Information about the Tree of Life} \usage{ tol_about(include_source_list = FALSE, ...) \method{tax_rank}{tol_summary}(tax, ...) \method{tax_sources}{tol_summary}(tax, ...) \method{unique_name}{tol_summary}(tax, ...) \method{tax_name}{tol_summary}(tax, ...) \method{ott_id}{tol_summary}(tax, ...) } \arguments{ \item{include_source_list}{Logical (default = \code{FALSE}). Return an ordered list of source trees.} \item{...}{additional arguments to customize the API call (see \code{\link{rotl}} for more information).} \item{tax}{an object created with a call to \code{tol_about}.} } \value{ An invisible list of synthetic tree summary statistics: \describe{ \item{date_created}{String. The creation date of the tree.} \item{num_source_studies}{Integer. The number of studies (publications)used as sources.} \item{num_source_trees}{The number of trees used as sources (may be >1 tree per study).} \item{taxonomy_version}{The Open Tree Taxonomy version used as a source.} \item{filtered_flags}{List. Taxa with these taxonomy flags were not used in construction of the tree.} \item{root}{List. Describes the root node:} \describe{ \item{node_id}{String. The canonical identifier of the node.} \item{num_tips}{Numeric. The number of descendant tips.} \item{taxon}{A list of taxonomic properties:} \describe{ \item{ott_id}{Numeric. The OpenTree Taxonomy ID (ott_id).} \item{name}{String. The taxonomic name of the queried node.} \item{unique_name}{String. The string that uniquely identifies the taxon in OTT.} \item{rank}{String. The taxonomic rank of the taxon in OTT.} \item{tax_sources}{List. A list of identifiers for taxonomic sources, such as other taxonomies, that define taxa judged equivalent to this taxon.} } } \item{source_list}{List. Present only if \code{include_source_list} is \code{TRUE}. The sourceid ordering is the precedence order for synthesis, with relationships from earlier trees in the list having priority over those from later trees in the list. See \code{source_id_map} below for study details.} \item{source_id_map}{Named list of lists. Present only if \code{include_source_list} is \code{TRUE}. Names correspond to the \sQuote{sourceids} used in \code{source_list} above. Source trees will have the following properties:} \describe{ \item{git_sha}{String. The git SHA identifying a particular source version.} \item{tree_id}{String. The tree id associated with the study id used.} \item{study_id}{String. The study identifier. Will typically include a prefix ("pg_" or "ot_").} } \item{synth_id}{The unique string for this version of the tree.} } } \description{ Basic information about the Open Tree of Life (the synthetic tree) } \details{ Summary information about the current draft tree of life, including information about the list of trees and the taxonomy used to build it. The object returned by \code{tol_about} can be passed to the taxonomy methods (\code{tax_name()}, \code{tax_rank()}, \code{tax_sources()}, \code{ott_id}), to extract relevant taxonomic information for the root of the synthetic tree. } \examples{ \dontrun{ res <- tol_about() tax_sources(res) ott_id(res) studies <- source_list(tol_about(include_source_list=TRUE))} } \seealso{ \code{\link{source_list}} to explore the list of studies used in the synthetic tree (see example). } rotl/man/tol_induced_subtree.Rd0000644000176200001440000000406215132136164016322 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/tol.R \name{tol_induced_subtree} \alias{tol_induced_subtree} \title{Subtree from the Open Tree of Life} \usage{ tol_induced_subtree( ott_ids = NULL, node_ids = NULL, label_format = NULL, file, ... ) } \arguments{ \item{ott_ids}{Numeric vector. OTT ids indicating nodes to be used as tips in the induced tree.} \item{node_ids}{Character vector. Node ids indicating nodes to be used as tips in the induced tree.} \item{label_format}{Character. Defines the label type; one of \dQuote{\code{name}}, \dQuote{\code{id}}, or \dQuote{\code{name_and_id}} (the default).} \item{file}{If specified, the function will write the subtree to a file in newick format.} \item{...}{additional arguments to customize the API call (see \code{\link{rotl}} for more information).} } \value{ If no value is specified to the \code{file} argument (default), a phylogenetic tree of class \code{phylo}. Otherwise, the function returns invisibly a logical indicating whether the file was successfully created. Note that the tree returned when specifying a file name with the \code{file} argument is the \dQuote{raw} Newick string returned by Open Tree of Life. This string contains singleton nodes, and therefore will be different from the tree returned as a \code{phylo} object which will not contain these singleton nodes. } \description{ Return the induced subtree on the synthetic tree that relates a list of nodes. } \details{ Return a tree with tips corresponding to the nodes identified in the input set that is consistent with the topology of the current synthetic tree. This tree is equivalent to the minimal subtree induced on the draft tree by the set of identified nodes. } \examples{ \dontrun{ ## Result as a `phylo` object res <- tol_induced_subtree(ott_ids = c(292466, 267845, 316878, 102710)) ## Raw Newick string from Open Tree of Life tree_file <- tempfile(fileext = ".tre") tol_induced_subtree(ott_ids = c(292466, 267845, 316878, 102710), file=tree_file) } } rotl/man/synonyms.match_names.Rd0000644000176200001440000000346715132136164016465 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/match_names.R \name{synonyms.match_names} \alias{synonyms.match_names} \title{List the synonyms for a given name} \usage{ \method{synonyms}{match_names}(tax, row_number, taxon_name, ott_id, ...) } \arguments{ \item{tax}{a data frame generated by the \code{\link{tnrs_match_names}} function} \item{row_number}{the row number corresponding to the name for which to list the synonyms} \item{taxon_name}{the taxon name corresponding to the name for which to list the synonyms} \item{ott_id}{the ott id corresponding to the name for which to list the synonyms} \item{...}{currently ignored} } \value{ a list whose elements are all synonym names (as vectors of character) for the taxonomic names that match the query (the names of the elements of the list). } \description{ When querying the Taxonomic Name Resolution Services for a particular taxonomic name, the API returns as possible matches all names that include the queried name as a possible synonym. This function allows you to explore other synonyms for an accepted name, and allows you to determine why the name you queried is returning an accepted synonym. } \details{ To list synonyms for a given taxonomic name, you need to provide the object resulting from a call to the \code{\link{tnrs_match_names}} function, as well as one of either the row number corresponding to the name in this object, the name itself (as used in the original query), or the ott_id listed for this name. Otherwise, the synonyms for all the currently matched names are returned. } \examples{ \dontrun{ echino <- tnrs_match_names(c("Diadema", "Acanthaster", "Fromia")) ## These 3 calls are identical synonyms(echino, taxon_name="Acanthaster") synonyms(echino, row_number=2) synonyms(echino, ott_id=337928) } } rotl/DESCRIPTION0000644000176200001440000000426315132225442012745 0ustar liggesusersPackage: rotl Title: Interface to the 'Open Tree of Life' API Version: 3.1.1 Authors@R: c(person(given = "Francois", family = "Michonneau", role = c("aut", "cre"), email = "francois.michonneau@gmail.com", comment = c(ORCID = "0000-0002-9092-966X")), person(given = "Joseph", family = "Brown", role = "aut", comment = c(ORCID = "0000-0002-3835-8062")), person(given = "David", family = "Winter", role = "aut", comment = c(ORCID = "0000-0002-6165-0029")), person(given = "Scott", family = "Chamberlain", role = "rev", comment = c(ORCID = "0000-0003-1444-9135"))) Description: An interface to the 'Open Tree of Life' API to retrieve phylogenetic trees, information about studies used to assemble the synthetic tree, and utilities to match taxonomic names to 'Open Tree identifiers'. The 'Open Tree of Life' aims at assembling a comprehensive phylogenetic tree for all named species. License: BSD_2_clause + file LICENSE URL: https://docs.ropensci.org/rotl/, https://github.com/ropensci/rotl BugReports: https://github.com/ropensci/rotl/issues Depends: R (>= 3.1.1) Imports: ape, curl (>= 3.0.0), httr, jsonlite, rentrez, rlang, rncl (>= 0.6.0) Suggests: knitr (>= 1.12), MCMCglmm, phylobase, readxl, rmarkdown (>= 0.7), RNeXML, testthat VignetteBuilder: knitr Encoding: UTF-8 X-schema.org-isPartOf: https://ropensci.org X-schema.org-keywords: metadata, ropensci, phylogenetics, independant-contrasts, biodiversity X-schema.org-relatedLink: https://codemeta.github.io/codemetar RoxygenNote: 7.3.3 NeedsCompilation: no Packaged: 2026-01-15 17:36:05 UTC; francois Author: Francois Michonneau [aut, cre] (ORCID: ), Joseph Brown [aut] (ORCID: ), David Winter [aut] (ORCID: ), Scott Chamberlain [rev] (ORCID: ) Maintainer: Francois Michonneau Repository: CRAN Date/Publication: 2026-01-15 18:00:02 UTC