AnnotationHub/DESCRIPTION0000644000175400017540000000377513200446560016073 0ustar00biocbuildbiocbuildPackage: AnnotationHub Type: Package Title: Client to access AnnotationHub resources Version: 2.10.1 Authors@R: c(person("Martin", "Morgan", email="martin.morgan@roswellpark.org", role="cre"), person("Marc", "Carlson", role="ctb"), person("Dan", "Tenenbaum", role="ctb"), person("Sonali", "Arora", role="ctb")) biocViews: Infrastructure, DataImport, GUI, ThirdPartyClient Maintainer: Bioconductor Package Maintainer Description: This package provides a client for the Bioconductor AnnotationHub web resource. The AnnotationHub web resource provides a central location where genomic files (e.g., VCF, bed, wig) and other resources from standard locations (e.g., UCSC, Ensembl) can be discovered. The resource includes metadata about each resource, e.g., a textual description, tags, and date of modification. The client creates and manages a local cache of files retrieved by the user, helping with quick and reproducible access. License: Artistic-2.0 Depends: BiocGenerics (>= 0.15.10) Imports: utils, methods, grDevices, RSQLite, BiocInstaller, curl, AnnotationDbi (>= 1.31.19), S4Vectors, interactiveDisplayBase, httr, yaml Suggests: IRanges, GenomicRanges, GenomeInfoDb, VariantAnnotation, Rsamtools, rtracklayer, BiocStyle, knitr, AnnotationForge, rBiopaxParser, RUnit, GenomicFeatures, MSnbase, mzR, Biostrings, SummarizedExperiment, ExperimentHub, gdsfmt Enhances: AnnotationHubData Collate: AnnotationHubOption.R AllGenerics.R Hub-class.R db-utils.R readMetadataFromCsv.R AnnotationHub-class.R AnnotationHubResource-class.R BEDResource-class.R ProteomicsResource-class.R EpigenomeResource-class.R EnsDbResource-class.R utilities.R sql-utils.R Hub-utils.R cache-utils.R zzz.R VignetteBuilder: knitr NeedsCompilation: yes Author: Martin Morgan [cre], Marc Carlson [ctb], Dan Tenenbaum [ctb], Sonali Arora [ctb] Packaged: 2017-11-08 00:18:56 UTC; biocbuild AnnotationHub/NAMESPACE0000644000175400017540000000417713175714307015611 0ustar00biocbuildbiocbuildimport(methods) import(BiocGenerics) import(RSQLite) import(S4Vectors) importFrom(stats, setNames) importFrom(grDevices, rgb) importFrom(utils, packageVersion, read.csv, read.delim, unzip, capture.output, read.table, .DollarNames ) importFrom(httr, GET, content, parse_url, progress, write_disk, stop_for_status, status_code, use_proxy ) importFrom(yaml, yaml.load) importFrom(interactiveDisplayBase, display) importFrom(BiocInstaller, biocVersion, isDevel) importMethodsFrom(AnnotationDbi, dbconn, dbfile) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Export S4 classes ### exportClasses( Hub, AnnotationHub, AnnotationHubResource ) export(readMetadataFromCsv) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Export S4 methods for generics not defined in AnnotationHub ### exportMethods( names, length, "$", "[", subset, "[[", as.list, c, show, fileName, display, mcols, dbconn, dbfile ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Export S4 generics defined in AnnotationHub + export corresponding ### methods ### export( cache, "cache<-", query, hubUrl, hubCache, hubDate, snapshotDate, "snapshotDate<-", getHub, listResources, loadResources, package ) exportMethods( cache, "cache<-", query, hubUrl, hubCache, hubDate, snapshotDate, "snapshotDate<-", getHub ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Export non-generic functions ### export( .Hub, AnnotationHub, display, removeCache, getAnnotationHubOption, setAnnotationHubOption, possibleDates, mcols, .httr_proxy, .hub_option_key, .db_close, recordStatus ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Export S3 methods ### S3method(.DollarNames, Hub) S3method(as.list, Hub) ### Also export them thru the export() directive so that (a) they can be ### called directly, (b) tab-completion on the name of the generic shows them, ### and (c) methods() doesn't asterisk them. export( .DollarNames.Hub, as.list.Hub ) AnnotationHub/NEWS0000644000175400017540000001524013200427466015056 0ustar00biocbuildbiocbuildCHANGES IN VERSION 2.10.1 ------------------------ BUG FIXES o Prompt for permission when downloading many (more than AnnotationHubOption("MAX_DOWNLOADS")) resources. CHANGES IN VERSION 2.10.0 ------------------------ NEW FEATURES o AnnotationHub will now work offline utilizing argument 'localHub'; will also use this option automatically if no internet connection is detected. o Added new GDSResource class o Added documentation for creating an AnnotationHub package MODIFICATIONS o Modified tags vector when passed to display to improve speed of display querying o Moved readMetadataFromCsv from AnnotationHubData. o Removed listResources and loadResource from AnnotationHub; not implemented and only valid in ExperimentHub BUG FIXES o Expose snapshot less than or equal to release date o Force rebuild of index if index file corrput or out of date CHANGES IN VERSION 2.8.0 ------------------------ NEW FEATURES o add .get1,RDSResource-method o add RdsResource class o add EnsDb dispatch class o expose rdatapath in metadata MODIFICATIONS o modify records exposed as metadata - expose records added <= snapshot date - expose a single OrgDb per organism per BioC version o edits to .get1,GenomicScores-method and .get1,GenomicScoresResource-method o work on biocVersion and snapshotDate relationship: - snapshotDate() must be <= biocVersion() release date - possibleDates() are now filtered by snapshotDate() o remove GenomicScoresResource; Robert Castelo will handle loading these resources in his GenomicScores software package o Changed show method for hub object - removed sourcelastmodifieddate - added rdatadateadded BUG FIXES o fix bug in ordering of output from .uid0() o fix bugs in 'snapshotDate<-' method CHANGES IN VERSION 2.6.0 ------------------------ NEW FEATURES o add vignette section on sharing resources on clusters o add 'preparerclass' to index.rda to allow search by package name for ExperimentHub objects o add GenomicScoresResource class for Robert Castelo MODIFICATIONS o return 'tags' metadata as list instead of comma-separated character vector o move AnnotationHubRecipes vignette to AnnotationHubData o move listResources() and loadResources() from ExperimentHub o expose additional fields in .DB_RESOURCE_FIELDS() o modify cache path to avoid creating a '~' directory on Mac o use https: NCBI rul in documentation o modify .get1,EpiExpressionTextResource-method to use 'gene_id' column as row names CHANGES IN VERSION 2.4.0 ------------------------ NEW FEATURES o add new status codes '4' and '5' to 'statuses' mysql table; change 'status_id' field to '4' for all removed records to date o add getRecordStatus() generic o add package() generic o create 'Hub' VIRTUAL class - add new .Hub() base constructor for all hubs - add getAnnotationHubOption() and setAnnotationHubOption() - promote cache() to generic - add getHub() getter for AnnotationHubResource class - add getUrl(), getCache(), getDate() getters - export as few db helpers as possible o add 'EpigenomeRoadmapNarrowAllPeaks' and 'EpigenomeRoadmapNarrowFDR' classes MODIFICATIONS o distinguish between broad and narrow peak files in EpigenomeRoadmapFileResource dispatch class o don't use cache for AnnotationHub SQLite connection - originally introduced so could be closed if needed, but creates complexity - instead, open / close connection around individual queries (not a performance concern) - expose hub, cache, proxy in AnnotationHub constructor - document dbconn,Hub-method, dbfile,Hub-method, .db_close o snapshotDate now uses timestamp (last date any row was modified) instead of rdatadateadded o .require fails rather than emits warning - unit test on .require() - also, cache(hub[FALSE]) does not create spurious error o work on removed records and biocVersion - .uid0() was reorganized and no longer groups by record_id - metadata is returned for records with biocversion field <= current biocVersion instead of an exact match with the current version - metadata is not returned for removed records BUG FIXES o Work around httr() progress() bug by disabling progress bar CHANGES IN VERSION 2.2.0 ------------------------ SIGNIFICANT USER-VISIBLE CHANGES o seqinfo(GRanges) for all genomes supported by GenomeInfoDb now contain seqlengths. CHANGES IN VERSION 2.1.21 -------------------------- SIGNIFICANT USER-VISIBLE CHANGES o fileName() returns the cache path on the disk for a file that has been cached and NA for files which have not been cached. o The error message (when file is not downloaded from the hub) displays the AnnotationHub name, title, and reason for failure. CHANGES IN VERSION 2.1 ---------------------- NEW FEATURES o as.list() splits AnnotationHub instances into a list of instances, each with a single record. c() concatenates hubs. BUG FIXES o cache<- now behaves as documented, e.g., removing the cached version of the file. CHANGES IN VERSION 2.0.0 ------------------------ NEW FEATURES o AnnotationHub is all new. We basically rewrote the entire thing. o The back end is new (new database, new way of tracking/routing data etc.) o The front end is new (new AnnotationHub object, new methods, new behaviors, new ways of finding and downloading data) o The metadata has also been cleaned up and made more consistent/searchable o The recipes that are used to populate these data have also been cleaned up. o There is also a new vignette to explain how to use the new AnnotationHub in detail IMPROVEMENTS SINCE LAST TIME o The old way of finding data (an enormous tree of paths), was not really scalable to the amount of data we have to provide access to. So we junked it. Now you have a number of better methods to allow you to search for terms instead. o The new hub interface can be searched using a new display method, but it can *also* be searched entirely from the command line. This allows you to use it in examples and scripts in a way that is friendlier for reproducible research. o For users who want to contribute valuable new annotation resources to the AnnotationHub, it is now possible to write a recipe and test that it works for yourself. Then once you are happy with it, you can contact us and we can add data to the AnnotationHub. AnnotationHub/R/0000755000175400017540000000000013200427466014556 5ustar00biocbuildbiocbuildAnnotationHub/R/AllGenerics.R0000644000175400017540000000345713175714307017106 0ustar00biocbuildbiocbuild### ========================================================================= ### All Generics ### ------------------------------------------------------------------------- ### ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Hub objects ### setGeneric("hubCache", signature="x", function(x) standardGeneric("hubCache") ) setGeneric("hubUrl", signature="x", function(x) standardGeneric("hubUrl") ) setGeneric("hubDate", signature="x", function(x) standardGeneric("hubDate") ) setGeneric("snapshotDate", function(x, ...) standardGeneric("snapshotDate") ) setGeneric("snapshotDate<-", signature="x", function(x, value) standardGeneric("snapshotDate<-") ) setGeneric("package", signature="x", function(x, value) standardGeneric("package") ) ## cache returns either the path to the URL or the local path (in a cache) ## along the way it downloads the resource that it locates ## Already expecting multiple ids from .dataPathIds(), (potentially) ## This is the path based on the RdataPath? (currenntly its based on resouce_id) setGeneric("cache", signature="x", function(x, ...) standardGeneric("cache") ) setGeneric("cache<-", signature="x", function(x, ..., value) standardGeneric("cache<-") ) setGeneric("recordStatus", signature="hub", function(hub, record) standardGeneric("recordStatus") ) setGeneric("listResources", signature="hub", function(hub, package, filterBy=character()) standardGeneric("listResources") ) setGeneric("loadResources", signature="hub", function(hub, package, filterBy=character()) standardGeneric("loadResources") ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### AnnotationHubResource objects ### setGeneric("getHub", signature="x", function(x) standardGeneric("getHub") ) AnnotationHub/R/AnnotationHub-class.R0000644000175400017540000000555413175714307020572 0ustar00biocbuildbiocbuild### ========================================================================= ### AnnotationHub objects ### ------------------------------------------------------------------------- ### setClass("AnnotationHub", contains="Hub") ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Constructor ### ## Add code to check : https://annotationhub.bioconductor.org/metadata/highest_id ## And if not, delete the DB so it will be re-downloaded... AnnotationHub <- function(..., hub=getAnnotationHubOption("URL"), cache=getAnnotationHubOption("CACHE"), proxy=getAnnotationHubOption("PROXY"), localHub=FALSE) { connect <- curl::has_internet() if (!connect && !localHub){ message("No internet connection using 'localHub=TRUE'") localHub <- !connect } .Hub("AnnotationHub", hub, cache, proxy, localHub, ...) } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Subsetting ### .Hub_get1 <- function(x) { if (!length(x)) stop("no records found for the given index") if (length(x) != 1L) stop("'i' must be length 1") ## Add 'Resource' postfix to DispatchClass name className <- sprintf("%sResource", .dataclass(x)) if (is.null(getClassDef(className))) { msg <- sprintf("'%s' not available in this version of the package; use biocLite() to update?", names(x)) stop(paste(strwrap(msg, exdent=2), collapse="\n"), call.=FALSE) } tryCatch({ class <- new(className, hub=x) }, error=function(err) { stop("failed to create 'HubResource' instance", "\n name: ", names(x), "\n title: ", x$title, "\n reason: ", conditionMessage(err), call.=FALSE) }) tryCatch({ .get1(class) }, error=function(err) { stop("failed to load resource", "\n name: ", names(x), "\n title: ", x$title, "\n reason: ", conditionMessage(err), call.=FALSE) }) } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### cache method ### setMethod("cache", "AnnotationHub", function(x, ...) { callNextMethod(x, cache.root=".AnnotationHub", cache.fun=setAnnotationHubOption, proxy=getAnnotationHubOption("PROXY"), max.downloads=getAnnotationHubOption("MAX_DOWNLOADS")) } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### show method ### setMethod("show", "AnnotationHub", function(object) { len <- length(object) cat(sprintf("%s with %d record%s\n", class(object), len, ifelse(len == 1L, "", "s"))) cat("# snapshotDate():", snapshotDate(object), "\n") callNextMethod(object) }) AnnotationHub/R/AnnotationHubOption.R0000644000175400017540000000316713175714307020656 0ustar00biocbuildbiocbuild### ========================================================================= ### Code for setting options. Most are set in R/zzz.R when the object is ### instantiated or used internally for dispatch on different 'Hub's. ### ------------------------------------------------------------------------- ### .AH_hub_options <- new.env(parent=emptyenv()) .hub_option_key <- function(key0=c("URL", "CACHE", "PROXY", "MAX_DOWNLOADS")) match.arg(key0) getAnnotationHubOption <- function(arg) { arg <- .hub_option_key(toupper(arg)) .AH_hub_options[[arg]] } setAnnotationHubOption <- function(arg, value) { key <- .hub_option_key(toupper(trimws(arg))) .AH_hub_options[[key]] <- switch(key, URL=, CACHE={ value <- as.character(value) stopifnot(isSingleString(value)) value }, MAX_DOWNLOADS={ value <- as.integer(value) stopifnot(isSingleInteger(value)) value }, PROXY={ if (is.null(value) || inherits(value, "request")) value else if (isSingleString(value)) { .httr_proxy(value) } else { txt <- "'value' must be an httr proxy request (use_proxy()), character(1), or NULL" stop(paste(strwrap(txt, exdent=2), collapse="\n")) } }) } .httr_proxy <- function(value) { rm <- parse_url(value) if (is.null(rm$scheme)) stop("PROXY 'value' does not include scheme (e.g., 'http://')") rm$url <- paste0(rm$scheme, "://", rm$hostname) if (!is.null(rm$port)) rm$port <- as.integer(rm$port) do.call(use_proxy, rm[c("url", "port", "username", "password")]) } AnnotationHub/R/AnnotationHubResource-class.R0000644000175400017540000001733113175714307022276 0ustar00biocbuildbiocbuild### ========================================================================= ### AnnotationHubResource objects ### ------------------------------------------------------------------------- ### setClass("AnnotationHubResource", representation(hub="Hub")) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Accessors ### setMethod("hubCache", "AnnotationHubResource", function(x) hubCache(x@hub) ) setMethod("hubUrl", "AnnotationHubResource", function(x) hubUrl(x@hub) ) setMethod("getHub", "AnnotationHubResource", function(x) x@hub ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Show ### setMethod("show", "AnnotationHubResource", function(object) { cat("class:", class(object), "\n") }) setGeneric(".get1", function(x, ...) { stopifnot(is(x, "AnnotationHubResource"), length(x) == 1L) standardGeneric(".get1") }) setMethod(".get1", "AnnotationHubResource", function(x, ...) { msg <- sprintf("no '.get1' method defined for object of class %s, consider defining your own.", sQuote(class(x))) stop(paste(strwrap(msg), collapse="\n")) }) ## ## implementations ## ## FaFile setClass("FaFileResource", contains="AnnotationHubResource") setMethod(".get1", "FaFileResource", function(x, ...) { .require("Rsamtools") fa <- cache(getHub(x)) Rsamtools::FaFile(file=fa[1],index=fa[2]) }) ## Rds / RDS ## Michael's AHCytoData is the only package (I think) that uses RDS. ## Added Rds to be compatible with Rda naming scheme. setClass("RdsResource", contains="AnnotationHubResource") setMethod(".get1", "RdsResource", function(x, ...) readRDS(cache(getHub(x)))) setClass("RDSResource", contains="RdsResource") setMethod(".get1", "RDSResource", function(x, ...) callNextMethod(x, ...)) ## Rda setClass("RdaResource", contains="AnnotationHubResource") setMethod(".get1", "RdaResource", function(x, ...) { get(load(cache(getHub(x)))) }) setClass("data.frameResource", contains="RdaResource") setClass("GRangesResource", contains="RdaResource") setMethod(".get1", "GRangesResource", function(x, ...) { .require("GenomicRanges") gr <- callNextMethod(x, ...) .tidyGRanges(x, gr) }) setClass("VCFResource", contains="RdaResource") setMethod(".get1", "VCFResource", function(x, ...) { .require("VariantAnnotation") callNextMethod(x, ...) }) ## UCSC chain file setClass("ChainFileResource", contains="AnnotationHubResource") ## trace(AnnotationHub:::.get1, tracer=browser, signature ="ChainFileResource") setMethod(".get1", "ChainFileResource", function(x, ...) { .require("rtracklayer") .require("GenomeInfoDb") chain <- cache(getHub(x)) tf <- .gunzip(chain, tempfile()) tf <- rtracklayer::import.chain(tf) tf[GenomeInfoDb::sortSeqlevels(names(tf))] }) setClass("TwoBitFileResource", contains="AnnotationHubResource") setMethod(".get1", "TwoBitFileResource", function(x, ...) { .require("rtracklayer") bit <- cache(getHub(x)) rtracklayer::TwoBitFile(bit) }) setClass("GTFFileResource", contains="AnnotationHubResource") setMethod(".get1", "GTFFileResource", function(x, ...) { message("Importing File into R ..") .require("rtracklayer") .require("GenomeInfoDb") yy <- getHub(x) gtf <- rtracklayer::import(cache(yy), format="gtf", genome=yy$genome, ...) .tidyGRanges(x, gtf) }) setClass("GFF3FileResource", contains="AnnotationHubResource") setMethod(".get1", "GFF3FileResource", function(x, ...) { .require("rtracklayer") yy <- getHub(x) rtracklayer::import(cache(yy), format="GFF", ...) }) setClass("BigWigFileResource", contains="AnnotationHubResource") setMethod(".get1", "BigWigFileResource", function(x, ...) { .require("rtracklayer") er <- cache(getHub(x)) rtracklayer::BigWigFile(er) }) setClass("dbSNPVCFFileResource", contains="AnnotationHubResource") setMethod(".get1", "dbSNPVCFFileResource", function(x, ...) { .require("VariantAnnotation") withCallingHandlers({ ## retrieve the resource er <- cache(getHub(x)) }, warning=function(w) { if (grepl("^Failed to parse headers:", conditionMessage(w))[1]) ## warning() something different, or... invokeRestart("muffleWarning") }) VariantAnnotation::VcfFile(file=er[1],index=er[2]) }) ## SQLiteFile setClass("SQLiteFileResource", contains="AnnotationHubResource") setMethod(".get1", "SQLiteFileResource", function(x, ...) { AnnotationDbi::loadDb(cache(getHub(x))) }) ## GRASP2 SQLiteFile setClass("GRASPResource", contains="SQLiteFileResource") setMethod(".get1", "GRASPResource", function(x, ...) { RSQLite::dbConnect(RSQLite::SQLite(), cache(getHub(x)), flags=RSQLite::SQLITE_RO) }) setClass("ZipResource", contains="AnnotationHubResource") setMethod(".get1", "ZipResource", function(x, filenames, ...) { zip <- cache(getHub(x)) for (fl in filenames) unzip(zip, fl, exdir=tempdir()) file.path(tempdir(), filenames) }) setClass("ChEAResource", contains="ZipResource") setMethod(".get1", "ChEAResource", function(x, ...) { fl <- callNextMethod(x, filenames="chea-background.csv") read.csv(fl, header=FALSE, stringsAsFactors=FALSE, col.names=c("s.no","TranscriptionFactor", "TranscriptionFactor-PubmedID", "TranscriptionFactorTarget", "PubmedID", "Experiment", "CellType", "Species","DateAdded")) }) setClass("BioPaxResource", contains="RdaResource") setMethod(".get1", "BioPaxResource", function(x, ...) { .require("rBiopaxParser") callNextMethod(x, ...) }) setClass("PazarResource", contains="AnnotationHubResource") setMethod(".get1", "PazarResource", function(x, ...) { .require("GenomicRanges") er <- cache(getHub(x)) colClasses <- setNames(c(rep("character", 6), rep("integer", 2), rep("factor", 2), "character", "NULL"), c("PazarTFID","EnsemblTFAccession", "TFName", "PazarGeneID", "EnsemblGeneAccession", "Chr", "GeneStart", "GeneEnd", "Species", "ProjectName","PMID", "AnalysisMethod")) dat <- read.delim(er, header=FALSE, col.names=names(colClasses), na.strings="-", colClasses=colClasses) if (!anyNA(dat[["GeneStart"]])) { dat <- GenomicRanges::makeGRangesFromDataFrame(dat, keep.extra.columns=TRUE) dat <- .tidyGRanges(x, dat) } dat }) setClass("CSVtoGrangesResource", contains="AnnotationHubResource") setMethod(".get1", "CSVtoGrangesResource", function(x, ...) { .require("GenomicRanges") yy <- getHub(x) dat <- read.csv(cache(yy), header=TRUE, stringsAsFactors=FALSE) dat <- dat[,!(names(dat) %in% "width")] gr <- GenomicRanges::makeGRangesFromDataFrame(dat, keep.extra.columns=TRUE) .tidyGRanges(x, gr) }) setClass("ExpressionSetResource", contains="RdaResource") setMethod(".get1", "ExpressionSetResource", function(x, ...) { .require("Biobase") callNextMethod(x, ...) }) # GDS setClass("GDSResource", contains="AnnotationHubResource") setMethod(".get1", "GDSResource", function(x, ...) { .require("gdsfmt") yy <- cache(getHub(x)) dat <- gdsfmt::openfn.gds(yy) }) ## H5FileResource setClass("H5FileResource", contains = "AnnotationHubResource") setMethod(".get1", "H5FileResource", function(x, ...) { .require("rhdf5") cache(getHub(x)) }) AnnotationHub/R/BEDResource-class.R0000644000175400017540000000301613175714307020112 0ustar00biocbuildbiocbuild## THis file contains methods for all BED files setClass("BEDFileResource", contains="AnnotationHubResource") setMethod(".get1", "BEDFileResource", function(x, ...) { .require("rtracklayer") yy <- getHub(x) dat <- rtracklayer::BEDFile(cache(yy)) gr <- rtracklayer::import(dat, format="bed", genome=yy$genome, ...) .tidyGRanges(x, gr) }) setClass("UCSCBroadPeakResource", contains="BEDFileResource") setMethod(".get1", "UCSCBroadPeakResource", function(x, ...) { broadPeaksmcols <- c(signalValue="numeric", pValue="numeric", qValue="numeric") callNextMethod(x, extraCols=broadPeaksmcols) }) setClass("UCSCNarrowPeakResource", contains="BEDFileResource") setMethod(".get1", "UCSCNarrowPeakResource", function(x, ...) { narrowPeaksmcols <- c( signalValue="numeric", pValue="numeric", qValue="numeric", peak="numeric") callNextMethod(x, extraCols=narrowPeaksmcols) }) setClass("UCSCBEDRnaElementsResource", contains="BEDFileResource") setMethod(".get1", "UCSCBEDRnaElementsResource", function(x, ...) { mcols <- c(name="character", score="integer", strand="character", level="numeric", signif="numeric", score2="numeric") callNextMethod(x, extraCols=mcols) }) setClass("UCSCGappedPeakResource", contains="BEDFileResource") setMethod(".get1", "UCSCGappedPeakResource", function(x, ...) { gappedPeakmcols <- c(signalValue="numeric", pValue="numeric", qValue="numeric") callNextMethod(x, extraCols=gappedPeakmcols) }) AnnotationHub/R/EnsDbResource-class.R0000644000175400017540000000056113175714307020515 0ustar00biocbuildbiocbuild### ========================================================================= ### EnsDb objects ### ------------------------------------------------------------------------- ### setClass("EnsDbResource", contains="AnnotationHubResource") setMethod(".get1", "EnsDbResource", function(x, ...) { .require("ensembldb") EnsDb(cache(getHub(x))) }) AnnotationHub/R/EpigenomeResource-class.R0000644000175400017540000001226513175714307021436 0ustar00biocbuildbiocbuild### ========================================================================= ### Epigenome Objects ### ------------------------------------------------------------------------- ### ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### EpiMetadata, EpiExpression, EpichmmModel Objects ### setClass("EpiMetadataResource", contains="AnnotationHubResource") setMethod(".get1", "EpiMetadataResource", function(x, ...) { read.delim(cache(getHub(x))) }) setClass("EpiExpressionTextResource", contains="AnnotationHubResource") setMethod(".get1", "EpiExpressionTextResource", function(x, ...) { yy <- cache(getHub(x)) data <- read.table(yy, header=TRUE, row.names=1) if(grepl("chr" ,rownames(data)[1])){ .require("SummarizedExperiment") data <- SummarizedExperiment::SummarizedExperiment( assays=as.matrix(data[,-c(1:2)]), rowRanges=.makeGrFromCharacterString(data)) } data }) setClass("EpichmmModelsResource", contains="AnnotationHubResource") setMethod(".get1", "EpichmmModelsResource", function(x, ...) { .require("rtracklayer") yy <- getHub(x) gr <- rtracklayer::import(cache(yy), format="bed", genome="hg19") gr <- .mapAbbr2FullName(gr) .tidyGRanges(x, gr) }) ## helper function which changes 'chr10:100011323-100011459<-1' to gr! .makeGrFromCharacterString <- function(data) { nms = sub("<-*1", "", rownames(data)) lst = strsplit(nms, "[:-]") v = function(x, i) vapply(x, "[[", "character", i) gr = GenomicRanges::GRanges(v(lst, 1), IRanges::IRanges(as.integer(v(lst, 2)), as.integer(v(lst, 3)))) mcols(gr) = data[,1:2] gr } ## this data is got from : ## chromhmmSegmentations/ChmmModels/coreMarks/jointModel/final/labelmap_15_coreMarks.tab ## chromhmmSegmentations/ChmmModels/coreMarks/jointModel/final/colormap_15_coreMarks.tab ## the bed file has abbr - and these 3 columns are helpful for collaborators. .mapAbbr2FullName <- function(gr) { map <- as.data.frame(matrix(c( "1_TssA", "Active TSS", "Red", rgb(255,0,0, maxColorValue=255), "2_TssAFlnk", "Flanking Active TSS", "Orange Red", rgb(255,69,0, maxColorValue=255), "3_TxFlnk", "Transcr. at gene 5' and 3'", "LimeGreen", rgb(50,205,50, maxColorValue=255), "4_Tx", "Strong transcription", "Green", rgb(0,128,0, maxColorValue=255), "5_TxWk", "Weak transcription", "DarkGreen", rgb(0,100,0, maxColorValue=255), "6_EnhG", "Genic enhancers", "GreenYellow", rgb(194,225,5, maxColorValue=255), "7_Enh", "Enhancers", "Yellow", rgb(255,255,0, maxColorValue=255), "8_ZNF/Rpts", "ZNF genes & repeats", "Medium Aquamarine", rgb(102,205,170, maxColorValue=255), "9_Het", "Heterochromatin", "PaleTurquoise", rgb(138,145,208, maxColorValue=255), "10_TssBiv", "Bivalent/Poised TSS", "IndianRed", rgb(205,92,92, maxColorValue=255), "11_BivFlnk", "Flanking Bivalent TSS/Enh", "DarkSalmon", rgb(233,150,122, maxColorValue=255), "12_EnhBiv", "Bivalent Enhancer", "DarkKhaki", rgb(189,183,107, maxColorValue=255), "13_ReprPC", "Repressed PolyComb", "Silver", rgb(128,128,128, maxColorValue=255), "14_ReprPCWk", "Weak Repressed PolyComb", "Gainsboro", rgb(192,192,192, maxColorValue=255), "15_Quies", "Quiescent/Low", "White", rgb(255,255,255, maxColorValue=255)), byrow=TRUE, nrow=15), stringsAsFactors=FALSE) colnames(map) <- c("abbr", "name", "color_name", "color_code") ##perform the mapping toMatch <- mcols(gr)$name newdf <- map[match(toMatch, map$abbr),] mcols(gr) <- newdf gr } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### EpigenomeRoadmap* Objects ### ### These classes are similar to the UCSCBroadPeak, UCSCNarrowPeak, family. ### The individual methods add 'extraCols' then dispatch through ### BEDFileResource. setClass("EpigenomeRoadmapFileResource", contains="AnnotationHubResource") ## NOTE: This dispatch class encompasses both broad and narrow peak - ## (Precursors were UCSCNarrowPeak and UCSCBroadPeak?) setMethod(".get1", "EpigenomeRoadmapFileResource", function(x, ...) { .require("rtracklayer") yy <- getHub(x) extraCols=c(signalValue="numeric", pValue="numeric", qValue="numeric") if (grepl("narrow", yy$sourceurl)) extraCols=c(extraCols, peak="numeric") gr <- rtracklayer::import(cache(yy), format="bed", genome=yy$genome, extraCols=extraCols) .tidyGRanges(x, gr) }) setClass("EpigenomeRoadmapNarrowAllPeaksResource", contains="BEDFileResource") setMethod(".get1", "EpigenomeRoadmapNarrowAllPeaksResource", function(x, ...) { narrowAllPeaks <- c(peakTagDensity="numeric") callNextMethod(x, extraCols=narrowAllPeaks) }) setClass("EpigenomeRoadmapNarrowFDRResource", contains="BEDFileResource") setMethod(".get1", "EpigenomeRoadmapNarrowFDRResource", function(x, ...) { narrowFDR <- c(peakTagDensity="numeric", zScore="numeric") callNextMethod(x, extraCols=narrowFDR) }) AnnotationHub/R/Hub-class.R0000644000175400017540000003455013175714307016535 0ustar00biocbuildbiocbuild### ========================================================================= ### Hub objects ### ------------------------------------------------------------------------- ### setClass("Hub", representation("VIRTUAL", hub="character", ## equivalent to cache URL cache="character", ## equivalent to cache CACHE ## FIXME: why was @date defined as data type 'character' date="character", .db_path="character", .db_index="character", .db_uid="integer" ) ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Constructor for subclasses ### .Hub <- function(.class, url, cache, proxy, localHub=FALSE, ...) { db_path <- .create_cache(cache, .class) if (!localHub){ db_path <- .db_get(db_path, url, proxy) tryCatch({ db_date <- .restrictDateByVersion(db_path) }, error=function(err) { stop("failed to connect", "\n reason: ", conditionMessage(err), "\n Consider rerunning with 'localHub=TRUE'") }) } else { if (!file.exists(db_path)) stop("Local database does not exist.", "\n Repeat call with 'localHub=FALSE'") dates <-.possibleDates(db_path) db_date <- dates[length(dates)] } db_uid <- .db_uid0(db_path, db_date) hub <- new(.class, cache=cache, hub=url, date=db_date, .db_path=db_path, .db_uid=db_uid, ...) message("snapshotDate(): ", snapshotDate(hub)) if (!localHub){ index <- .db_create_index(hub) .db_index(hub) <- index } else{ index <- file.path(dirname(db_path), "index.rds") if (!file.exists(index)) stop("Index file not created.", "\n Repeat call with 'localHub=FALSE'") .db_index(hub) <- index hub <- .subsethub(hub) } hub } .subsethub <- function(hub){ myX = .named_cache_path(hub) locFiles = setdiff(dir(hubCache(hub)), c("annotationhub.sqlite3", "index.rds")) dx = which(basename(myX) %in% locFiles) files = names(myX[dx]) hub[files] } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Validity ### .valid.Hub <- function(object) { message <- NULL if (!isSingleString(hubUrl(object))) stop("'hubUrl(object)' must be a single string (url)") if (!isSingleString(hubCache(object))) stop("'hubCache(object)' must be a single string (directory path)") message } setValidity("Hub", function(object) { problems <- .valid.Hub(object) if (is.null(problems)) TRUE else problems } ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Accessors ### setMethod("hubCache", "Hub", function(x) x@cache ) setMethod("hubUrl", "Hub", function(x) x@hub ) setMethod("hubDate", "Hub", function(x) x@date ) setMethod("package", "Hub", function(x) character() ) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### cache methods ### ## FIXME: rather not pass cache.root and cache.fun setMethod("cache", "Hub", function(x, ..., cache.root, cache.fun, proxy, max.downloads) .cache_internal(x, cache.root=cache.root, cache.fun=cache.fun, proxy=proxy, max.downloads=max.downloads) ) setReplaceMethod("cache", "Hub", function(x, ..., value) { stopifnot(identical(value, NULL)) cachepath <- .cache_path(x, .datapathIds(x)) result <- unlink(cachepath) status <- file.exists(cachepath) if (any(status)) warning("failed to unlink cache files:\n ", paste(sQuote(.cache_path(x)[status]), collapse="\n ")) x }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Accessor-like methods ### setMethod("mcols", "Hub", function(x) DataFrame(.resource_table(x))) setMethod("names", "Hub", function(x) { as.character(names(.db_uid(x))) }) setMethod("fileName", signature=(object="Hub"), function(object, ...) { cachepath <- .named_cache_path(object) cachepath[!file.exists(cachepath)] <- NA_character_ cachepath }) setMethod("length", "Hub", function(x) length(.db_uid(x)) ) setMethod("snapshotDate", "Hub", function(x) x@date) setReplaceMethod("snapshotDate", "Hub", function(x, value) { if (length(value) != 1L) stop("'value' must be a single date or character string") tryCatch({ fmt_value <- as.POSIXlt(value) }, error=function(err) { stop("'value' must be a single date or character string") }) ## 'value' must be < biocVersion() release date restrict <- .restrictDateByVersion(dbfile(x)) dates <- .possibleDates(dbfile(x)) valid_range <- range(dates[as.POSIXlt(dates) <= as.POSIXlt(restrict)]) if (as.POSIXlt(value) > max(valid_range) || as.POSIXlt(value) < min(valid_range)) stop("'value' must be in the range of possibleDates(x)") new(class(x), cache=hubCache(x), hub=hubUrl(x), date=as.character(value), .db_path=x@.db_path, .db_index=x@.db_index, .db_uid=.db_uid0(x@.db_path, value)) }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Subsetting ### setMethod("[", c("Hub", "numeric", "missing"), function(x, i, j, ..., drop=TRUE) { idx <- na.omit(match(i, seq_along(.db_uid(x)))) ## seq_along creates a special problem for show()... .db_uid(x) <- .db_uid(x)[idx] x }) setMethod("[", c("Hub", "logical", "missing"), function(x, i, j, ..., drop=TRUE) { i[is.na(i)] <- FALSE .db_uid(x) <- .db_uid(x)[i] x }) setMethod("[", c("Hub", "character", "missing"), function(x, i, j, ..., drop=TRUE) { idx <- na.omit(match(i, names(.db_uid(x)))) .db_uid(x) <- .db_uid(x)[idx] x }) setReplaceMethod("[", c("Hub", "numeric", "missing", "Hub"), function(x, i, j, ..., value) { .db_uid(x)[i] <- .db_uid(value) x }) setReplaceMethod("[", c("Hub", "logical", "missing", "Hub"), function(x, i, j, ..., value) { .db_uid(x)[i] <- .db_uid(value) x }) setReplaceMethod("[", c("Hub", "character", "missing", "Hub"), function(x, i, j, ..., value) { idx <- match(i, names(.db_uid(x))) isNA <- is.na(idx) .db_uid(x)[idx[!isNA]] <- .db_uid(value)[!isNA] x }) setMethod("[[", c("Hub", "numeric", "missing"), function(x, i, j, ...) { .Hub_get1(x[i]) }) setMethod("[[", c("Hub", "character", "missing"), function(x, i, j, ...) { if (length(i) != 1L) stop("'i' must be length 1") idx <- match(i, names(.db_uid(x))) if (is.na(idx)) stop(recordStatus(x, i)$status) .Hub_get1(x[idx]) }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### $, query() and subset() methods ### setMethod("$", "Hub", function(x, name) { switch(name, "tags"=unname(.collapse_as_string(x, .tags)), "rdataclass"=unname(.collapse_as_string(x, .rdataclass)), "rdatapath"=unname(.collapse_as_string(x, .rdatapath)), "sourceurl"=unname(.collapse_as_string(x, .sourceurl)), "sourcetype"=unname(.collapse_as_string(x, .sourcetype)), .resource_column(x, name)) ## try to get it from main resources table }) .DollarNames.Hub <- function(x, pattern="") { values <- c(.resource_columns(), "tags", "rdataclass", "sourceurl", "sourcetype") grep(pattern, values, value=TRUE) } setGeneric("query", function(x, pattern, ...) standardGeneric("query"), signature="x") setMethod("query", "Hub", function(x, pattern, ignore.case=TRUE, pattern.op=`&`) { tbl <- .db_index_load(x) idx <- logical() for (pat in pattern) { idx0 <- grepl(pat, tbl, ignore.case=ignore.case) if (length(idx)) idx <- pattern.op(idx, idx0) # pattern.op for combining patterns else idx <- idx0 } x[idx] }) setMethod("subset", "Hub", function(x, subset) { tbl <- mcols(x) idx <- S4Vectors:::evalqForSubset(subset, tbl) x[idx] }) as.list.Hub <- function(x, ..., use.names=TRUE) { ans <- lapply(seq_along(x), function(i, x) x[i], x) if (use.names) names(ans) <- names(x) ans } ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Coercion ### setMethod("as.list", "Hub", as.list.Hub) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Combining ### setMethod("c", "Hub", function(x, ..., recursive=FALSE) { if (!identical(recursive, FALSE)) stop("'recursive' argument not supported") if (missing(x)) args <- unname(list(...)) else args <- unname(list(x, ...)) .test <- function(args, fun, what) { ans <- unique(vapply(args, fun, character(1))) if (length(ans) != 1L) stop(sprintf("'%s' differs between arguments", what)) } .test(args, hubCache, "hubCache") .test(args, hubUrl, "hubUrl") .test(args, snapshotDate, "snapshotDate") .test(args, dbfile, "dbfile") db_uid <- unlist(lapply(unname(args), .db_uid)) if (length(db_uid) == 0 && is.null(names(db_uid))) names(db_uid) <- character() udb_uid <- unique(db_uid) idx <- match(udb_uid, db_uid) .db_uid <- setNames(udb_uid, names(db_uid)[idx]) initialize(args[[1]], .db_uid=.db_uid) }) ## FIXME: ## trace (as below) wasn't working (not sure why) ## trace(subset, browser(), signature='AnnotationHub') ## debug(AnnotationHub:::.subset) ## Tests: ## library(AnnotationHub);debug(AnnotationHub:::.subset);ah = AnnotationHub() ## ahs <- subset(ah, ah$genome=='ailMel1') ## ahs <- subset(ah, ah$rdataclass=='VCF') ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### Show ### .pprintf0 <- function(fmt, ...) paste(strwrap(sprintf(fmt, ...), exdent=2), collapse="\n# ") .pprintf1 <- function(column, values, width=getOption("width") - 1L) { answer <- sprintf("# $%s: %s", column, paste(values, collapse=", ")) ifelse(nchar(answer) > width, sprintf("%s...\n", substring(answer, 1L, width - 3L)), sprintf("%s\n", answer)) } .show <- function(object) { if (!length(object)) return(NULL) .some <- function(elt, nh, nt, fill="...", width=getOption("width") - 13L) { answer <- if (length(elt) < nh + nt + 1L) elt else c(head(elt, nh), fill, tail(elt, nt)) ifelse(nchar(answer) > width, sprintf("%s...", substring(answer, 1L, width-3L)), answer) } cat(.pprintf1("dataprovider", .count_resources(object, "dataprovider"))) cat(.pprintf1("species", .count_resources(object, "species"))) cat(.pprintf1("rdataclass", .count_join_resources(object, "rdatapaths", "rdataclass"))) shown <- c("dataprovider", "species", "rdataclass", "title") cols <- paste(setdiff(names(mcols(object[0])), shown), collapse=", ") cat(.pprintf0("# additional mcols(): %s", cols), "\n") cat(.pprintf0("# retrieve records with, e.g., 'object[[\"%s\"]]'", names(object)[[1]]), "\n") if (len <- length(object)) { nhead <- get_showHeadLines() ntail <- get_showTailLines() title <- .title_data.frame(object) rownames <- paste0(" ", .some(rownames(title), nhead, ntail)) out <- matrix(c(.some(rep("|", len), nhead, ntail, fill=""), .some(title[[1]], nhead, ntail)), ncol=2L, dimnames=list(rownames, c("", "title"))) cat("\n") print(out, quote=FALSE, right=FALSE) } } .show1 <- function(object) { rsrc <- .resource_table(object) size <- .collapse_as_string(object, .sourcesize) date <- .collapse_as_string(object, .sourcelastmodifieddate) cat("# names(): ", names(object)[[1]], "\n", sep="") if (length(package(object)) > 0L) cat("# package(): ", package(object)[[1]], "\n", sep="") cat(.pprintf1("dataprovider", rsrc[["dataprovider"]])) cat(.pprintf1("species", rsrc[["species"]])) cat(.pprintf1("rdataclass", rsrc[["rdataclass"]])) cat(.pprintf1("rdatadateadded", rsrc[["rdatadateadded"]])) cat(.pprintf1("title", rsrc[["title"]])) cat(.pprintf1("description", rsrc[["description"]])) cat(.pprintf1("taxonomyid", rsrc[["taxonomyid"]])) cat(.pprintf1("genome", rsrc[["genome"]])) cat(.pprintf1("sourcetype", rsrc[["sourcetype"]])) cat(.pprintf1("sourceurl", rsrc[["sourceurl"]])) cat(.pprintf1("sourcesize", size)) cat(.pprintf0("# $tags: %s", rsrc[["tags"]]), "\n") cat(.pprintf0("# retrieve record with 'object[[\"%s\"]]'", names(object)[[1]]), "\n") } setMethod("show", "Hub", function(object) { if (length(object) == 1) .show1(object) else .show(object) }) ### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ### display ### .display <- function(object, ...) { #metadata- do not touch md <- mcols(object) #create a data frame copy for edits called df df <- as.data.frame(md) #dropping column names drops <-c("title", "taxonomyid", "sourceurl") df <- df[,!(names(df) %in% drops), drop=FALSE] # speeds up search by making character df$tags <- vapply(unname(unclass(md$tags)), base::paste, character(1), collapse=", ") summaryMessage = capture.output(show(object)) serverOptions= list( bSortClasses=TRUE, aLengthMenu = c(1000, 5000, "All"), iDisplayLength = 1000, "sDom" = '<"top"i>rt<"top"f>lt<"bottom"p><"clear">') d <- display(object =df, summaryMessage = summaryMessage, serverOptions = serverOptions) idx <- rownames(d) object[idx] } setMethod("display", signature(object="Hub"), function(object) .display(object) ) setMethod("recordStatus", "Hub", function(hub, record) { if (!is.character(record)) stop("'record' must be a character") if (length(record) != 1L) stop("'record' must be length 1") conn <- dbconn(hub) query <- paste0("SELECT status FROM statuses WHERE id IN ", "(SELECT status_id FROM resources WHERE ah_id = '", record, "')") status=.db_query(conn, query) if (nrow(status) == 0L) status <- "record not found in database" data.frame(record=record, status=status) }) AnnotationHub/R/Hub-utils.R0000644000175400017540000001055413175714307016566 0ustar00biocbuildbiocbuild## and hubUrl (https://annotationhub.bioconductor.org/) .hub_metadata_path <- function(hub) { paste(hub, "metadata", sep="/") } ## The following helper was previously not used (and now is), but we ## do need a way to have a path for the data that is separate from the ## path for the .sqlite metadata (they don't need to always be at the ## same server) - IOW these should be decoupled anyhow). .hub_data_path <- function(hub) { ## "http://gamay:9393/fetch" ## "https://annotationhub.bioconductor.org/fetch" sprintf("%s/fetch", hub) } .hub_resource_path <- function(hub, resource) { sprintf("%s/%s", hub, resource) } ## example of hub resource (sometimes convenient) ## hub = 'https://annotationhub.bioconductor.org/metadata/annotationhub.sqlite3' .hub_cache_resource <- function(hubpath, cachepath, proxy) { ## retrieve file from hub to cache tryCatch({ tmp <- tempfile() ## Download the resource in a way that supports https if (interactive() && (packageVersion("httr") > "1.0.0")) { response <- GET(hubpath, progress(), write_disk(tmp), proxy) cat("\n") ## line break after progress bar } else { response <- GET(hubpath, write_disk(tmp), proxy) } if (length(status_code(response))) { # FTP requests return empty status code, see # https://github.com/hadley/httr/issues/190 if (status_code(response) != 302L) stop_for_status(response) } if (!all(file.exists(dirname(cachepath)))) dir.create(dirname(cachepath), recursive=TRUE) file.copy(from=tmp, to=cachepath) file.remove(tmp) TRUE }, error=function(err) { warning("download failed", "\n hub path: ", sQuote(hubpath), "\n cache path: ", sQuote(cachepath), "\n reason: ", conditionMessage(err), call.=FALSE) FALSE }) } ## This is the function that gets stuff (metadata AND files) from S3 .hub_resource <- function(hub, resource, cachepath, proxy, overwrite=FALSE) { len <- length(resource) if (len > 0L) { msg <- sprintf("retrieving %d resource%s", len, if (len > 1L) "s" else "") message(msg) } if (length(cachepath)) { test <- file.exists(cachepath) if (!overwrite && any(test)) { bad <- cachepath[test] stop("download destination(s) exists", "\n ", paste(sQuote(bad), collapse="\n ")) } } hubpath <- .hub_resource_path(hub, resource) mapply(.hub_cache_resource, hubpath, cachepath, MoreArgs=list(proxy)) } ### -------------------------------------------------------------------------- ### snapshotDate helpers ## returns the release date for biocVersion() .biocVersionDate <- function(biocversion) { if (length(biocversion) > 1L) stop("length(biocversion) must == 1") yaml <- content(GET("http://bioconductor.org/config.yaml"), encoding="UTF-8", as="text") obj <- yaml.load(yaml) release_dates <- obj$release_dates version_date <- release_dates[biocversion == names(release_dates)] ## convert to snapshot format if (length(version_date)) as.character(as.POSIXlt(version_date[[1]], format='%m/%d/%Y')) else character() } ## single date closest to the release date for biocVersion() .restrictDateByVersion <- function(path) { dates <- as.POSIXlt(.possibleDates(path), format='%Y-%m-%d') restrict <- as.POSIXlt(.biocVersionDate(biocVersion()), format='%Y-%m-%d') if (length(restrict)) ## release as.character(max(dates[dates <= restrict])) else ## devel as.character(max(dates)) } ## all possible dates .possibleDates <- function(path) { conn <- .db_open(path) on.exit(.db_close(conn)) query <- 'SELECT DISTINCT rdatadateadded FROM resources' dateAdded <- .db_query(conn, query)[[1]] query <- 'SELECT DATE(timestamp) FROM timestamp' dateModified <- .db_query(conn, query)[[1]] c(dateAdded, dateModified) } ## dates restricted by snapshotDate (and hence biocVersion()) possibleDates <- function(x) { path <- dbfile(x) dates <- .possibleDates(path) restrict <- .restrictDateByVersion(path) dates[as.POSIXlt(dates) <= as.POSIXlt(restrict)] } AnnotationHub/R/ProteomicsResource-class.R0000644000175400017540000000145313175714307021647 0ustar00biocbuildbiocbuildsetClass("mzRpwizResource", contains="AnnotationHubResource") setMethod(".get1", "mzRpwizResource", function(x, ...) { .require("mzR") yy <- cache(getHub(x)) mzR::openMSfile(yy, backend = "Ramp") }) setClass("mzRidentResource", contains="AnnotationHubResource") setMethod(".get1", "mzRidentResource", function(x, ...) { .require("mzR") yy <- cache(getHub(x)) mzR::openIDfile(yy) }) setClass("MSnSetResource", contains="RdaResource") setMethod(".get1", "MSnSetResource", function(x, ...) { .require("MSnbase") callNextMethod(x, ...) }) setClass("AAStringSetResource", contains="AnnotationHubResource") setMethod(".get1", "AAStringSetResource", function(x, ...) { .require("Biostrings") yy <- cache(getHub(x)) Biostrings::readAAStringSet(yy) }) AnnotationHub/R/cache-utils.R0000644000175400017540000000671413200427466017112 0ustar00biocbuildbiocbuild .cache_path <- function(hub, path, cache.root=NULL, cache.fun=NULL) { cache <- hubCache(hub) ## FIXME: when would 'cache' be missing? if (missing(cache)) { if (any(is.null(cache.root) | is.null(cache.fun))) stop("'cache.root' and 'cache.fun' must be set if cache is missing") ## this section replaces .cache_path_default if (file.exists(cache) && file.info(cache)$isdir) return(cache) if (file.exists(cache) && !file.info(cache)$isdir) { txt <- sprintf("default cache exists but is not a directory\n %s", sQuote(cache)) warning(txt) cache <- NULL } if (!is.null(cache) && interactive()) { txt <- sprintf("create cache at %s?", sQuote(cache)) ans <- .ask(txt, values=c("y", "n")) if (ans == "n") { cache <- file.path(tempdir(), cache.root) message(sprintf("using temporary cache %s", sQuote(cache))) } } else { cache <- file.path(tempfile()) } ## FIXME: cache.fun("CACHE", cache) } else if (missing(path)) { cache } else { file.path(cache, path) } } .create_cache <- function(cache, .class) { if (file.exists(cache)) { if (!file.info(cache)$isdir) stop("cache ", sQuote(cache), " exists but is not a directory") } else dir.create(cache, recursive=TRUE) sqlitefile <- paste0(tolower(.class), ".sqlite3") file.path(cache, sqlitefile) } .cache_internal <- function(x, cache.root, cache.fun, proxy, max.downloads) { cachepath <- .named_cache_path(x, cache.root, cache.fun) need <- !file.exists(cachepath) if (any(need)) { hubpath <- .hub_resource_path(.hub_data_path(hubUrl(x)), basename(cachepath)[need]) message("downloading from ", paste0(sQuote(hubpath), collapse="\n ")) } else { message("loading from cache ", paste0(sQuote(cachepath), collapse="\n ")) } if (sum(need) > max.downloads) { if (!interactive()) { txt <- sprintf("resources needed (%d) exceeds max.downloads (%d)", sum(need), max.downloads) stop(txt) } ans <- .ask(sprintf("download %d resources?", sum(need)), c("y", "n")) if (ans == "n") return(cachepath[!need]) } ok <- .hub_resource(.hub_data_path(hubUrl(x)), basename(cachepath)[need], cachepath[need], proxy=proxy) if (!all(ok)) stop(sprintf("%d resources failed to download", sum(!ok))) cachepath } .named_cache_path <- function(x, cache.root, cache.fun) { stopifnot(is(x, "Hub")) path <- .datapathIds(x) setNames(.cache_path(x, path, cache.root, cache.fun), names(path)) } removeCache <- function(x) { reply <- .ask("Delete cache file", c("y", "n")) cache <- hubCache(x) if (reply == "y") { rv <- tryCatch({ if (file.exists(cache)) { status <- unlink(cache, recursive=TRUE, force=TRUE) if (status == 1) stop("'unlink()' failed to remove directory") } TRUE }, error=function(err) { warning("'clearCache()' failed", "\n database: ", sQuote(cache), "\n reason: ", conditionMessage(err), call.=FALSE) FALSE }) } else rv <- FALSE rv } AnnotationHub/R/db-utils.R0000644000175400017540000001163513175714307016436 0ustar00biocbuildbiocbuild### ========================================================================= ### db helpers for Hub objects ### ------------------------------------------------------------------------- ### .db_open <- function(path) { tryCatch({ conn <- dbConnect(SQLite(), path) }, error=function(err) { stop("failed to connect to local data base", "\n database: ", sQuote(path), "\n reason: ", conditionMessage(err), call.=FALSE) }) conn } .db_close <- function(conn) { if (!is.null(conn)) if (RSQLite::dbIsValid(conn)) dbDisconnect(conn) invisible(conn) } .db_query <- function(path, query) { if (is.character(path)) { path <- .db_open(path) on.exit(.db_close(path)) } dbGetQuery(path, query) } .db_current <- function(path, hub, proxy) { tryCatch({ url <- paste0(hub, '/metadata/database_timestamp') onlineTime <- as.POSIXct(content(GET(url, proxy))) db_path <- .db_get_db(path, hub, proxy) sql <- "SELECT * FROM timestamp" localTime <- as.POSIXct(.db_query(db_path, sql)[[1]]) onlineTime == localTime }, error=function(e) { warning("database may not be current", "\n database: ", sQuote(path), "\n reason: ", conditionMessage(e), call.=FALSE) ## TRUE even though not current, e.g., no internet connection TRUE }) } ## Helpers to get a fresh metadata DB connection .db_get_db <- function(path, hub, proxy) { ## download or cache tryCatch({ need <- !file.exists(path) .hub_resource(.hub_metadata_path(hub), basename(path)[need], path[need], proxy) }, error=function(err) { stop("failed to create local data base", "\n database: ", sQuote(path), "\n reason: ", conditionMessage(err), call.=FALSE) }) path } .db_is_valid <- function(path) { conn <- .db_open(path) on.exit(.db_close(conn)) ## Some very minor testing to make sure metadata DB is intact. tryCatch({ ## required tables present? expected <- c("biocversions", "input_sources", "location_prefixes", "rdatapaths", "recipes", "resources", "statuses", "tags", "timestamp") if (!all(expected %in% dbListTables(conn))) stop("missing tables") ## any resources? sql <- "SELECT COUNT(id) FROM resources" if (.db_query(conn, sql)[[1]] == 0L) warning("empty 'resources' table; database may be corrupt") }, error=function(err) { stop("database is corrupt; remove it and try again", "\n database: ", sQuote(path), "\n reason: ", conditionMessage(err), call.=FALSE) }) TRUE } .db_get <- function(path, hub, proxy) { update <- !file.exists(path) if (!update && !file.size(path)) { file.remove(path) update <- TRUE } if (!update && !.db_current(path, hub, proxy)) { file.remove(path) update <- TRUE } if (update) message("updating metadata: ", appendLF=FALSE) db_path <- .db_get_db(path, hub, proxy) .db_is_valid(db_path) db_path } .db_index_file <- function(x) file.path(hubCache(x), "index.rds") .db_index_load <- function(x) readRDS(.db_index_file(x))[names(x)] .db_uid0 <- function(path, .date){ tryCatch({ uid <- .uid0(path, .date) sort(uid) }, error=function(err) { stop("failed to connect to local data base", "\n database: ", sQuote(path), "\n reason: ", conditionMessage(err), call.=FALSE) }) } .db_create_index <- function(x) { fl <- .db_index_file(x) if (file.exists(fl)) { if (file.mtime(fl) > file.mtime(dbfile(x)) && length(x) == length(readRDS(fl))) return(fl) } tryCatch({ tbl <- .resource_table(x) tbl <- setNames(do.call("paste", c(tbl, sep="\r")), rownames(tbl)) saveRDS(tbl, fl) }, error=function(err) { stop("failed to create index", "\n hubCache(): ", hubCache(x), "\n reason: ", conditionMessage(err)) }) fl } .db_index <- function(x) slot(x, ".db_index") `.db_index<-` <- function(x, ..., value) { if (length(value) > 1L) stop("'value' must be length 1") if (!is(value, "character")) stop("'value' must be a character") slot(x, ".db_index") <- value x } .db_uid <- function(x) slot(x, ".db_uid") `.db_uid<-` <- function(x, ..., value) { bad <- value[!value %in% .db_uid(x)] if (any(bad)) stop("invalid subscripts: ", paste(sQuote(S4Vectors:::selectSome(bad)), collapse=", ")) slot(x, ".db_uid") <- value x } setMethod("dbconn", "Hub", function(x) .db_open(dbfile(x)) ) setMethod("dbfile", "Hub", function(x) x@.db_path ) AnnotationHub/R/readMetadataFromCsv.R0000644000175400017540000000613313175714307020564 0ustar00biocbuildbiocbuild### ========================================================================= ### readMetadataFromCsv() ### ------------------------------------------------------------------------- ### ## High level helper used to check metadata in 'Hub' packages. readMetadataFromCsv <- function(pathToPackage, fileName=character()) { if (!length(fileName)) fileName <- "metadata.csv" path <- file.path(pathToPackage, "inst", "extdata") meta <- read.csv(file.path(path, fileName), colClasses="character", stringsAsFactors=FALSE) mat <- rbind(c("Title", "character"), c("Description", "character"), c("BiocVersion", "character"), c("Genome", "character"), c("SourceType", "character"), c("SourceUrl", "character"), c("SourceVersion", "character"), c("Species", "character"), c("TaxonomyId", "integer"), c("Coordinate_1_based", "logical"), c("DataProvider", "character"), c("Maintainer", "character"), c("RDataClass", "character"), c("DispatchClass", "character"), c("RDataPath", "character")) expected <- mat[,1] missing <- !expected %in% names(meta) if (any(missing)) stop("missing fields in metadata file ", fileName, ": ", paste(expected[missing], collapse=", ")) extra<- !names(meta) %in% expected ## All fields length 1 apply(meta, 1, function(xx) { valid <- sapply(xx, function(field) length(field) == 1L) if (any(!valid)) stop("all fields in ", fileName, " must be a character ", "string of length 1") } ) ## Populate required fields missing <- is.na(nchar(meta$DataProvider)) if (any(missing)) { meta$DataProvider[missing] <- "NA" message("missing values for 'DataProvider set to 'NA''") } if (any(is.na(meta$Coordinate_1_based))) { meta$Coordinate_1_based <- TRUE message("missing values for 'Coordinate_1_based set to TRUE'") } else { meta$Coordinate_1_based <- as.logical(meta$Coordinate_1_based) } ## Enforce data type meta$TaxonomyId <- as.integer(meta$TaxonomyId) meta$BiocVersion <- package_version(meta$BiocVersion) ## Location_Prefix not specified -> data in S3 if (all(is.null(Location_Prefix <- meta$Location_Prefix))) { meta$Location_Prefix <- 'http://s3.amazonaws.com/annotationhub/' ## Location_Prefix specified -> data at other location } if(all( (meta$Location_Prefix == 'http://s3.amazonaws.com/annotationhub/') || (meta$Location_Prefix == 'http://s3.amazonaws.com/experimenthub/')) ){ package <- basename(pathToPackage) test <- vapply(meta$RDataPath, startsWith, logical(1), package) if (!all(test)){ stop("RDataPath must start with package name: ", package) } } ## Real time assignments meta$RDataDateAdded <- rep(Sys.time(), nrow(meta)) meta } AnnotationHub/R/sql-utils.R0000644000175400017540000002705213175714307016650 0ustar00biocbuildbiocbuild.id_as_single_string <- function(x) paste(sprintf("'%s'", .db_uid(x)), collapse=", ") .query_as_data.frame <- function(x, query) { tbl <- .db_query(dbfile(x), query) ridx <- match(names(x), tbl$ah_id) cidx <- match("ah_id", names(tbl)) rownames(tbl) <- tbl$ah_id tbl[ridx, -cidx, drop=FALSE] } ## FIXME: Should be removed. ## This is redundant with the filter criteria in .uid0() and ## does not reuse ids already discovered (i.e., it's an independent ## query that may not match up and has no checks to confirm). .names_for_ids <- function(conn, ids){ query <- sprintf( 'SELECT resources.id, resources.ah_id FROM resources, biocversions WHERE biocversion == "%s" AND biocversions.resource_id == resources.id', biocVersion()) mtchData <- .db_query(conn, query) names(ids) <- mtchData[mtchData[[1]] %in% ids,][[2]] ids } ## This function filters the local annotationhub.sqlite metadata db and ## defines the subset exposed by AnnotationHub(). .uid0 <- function(path, date) { conn <- .db_open(path) on.exit(.db_close(conn)) ## General filter: ## All AnnotationHub resources (except OrgDbs, see below) are ## available from the time they are added -> infinity unless ## they are removed from the web or by author request. The ## snapshot date can be changed by the user. We want to return records ## with no rdatadateremoved and with rdatadateadded <= snapshot. ## All OrgDbs are omitted in the first filter and selectively ## exposed in the second filter. ## NOTE: biocversions filter distinguishes between release and devel; ## this is not caught by rdatadate added filter because the timestamp ## is updated with each modification and currently someone using ## an old version of Bioconductor will still get the current db ## which will have a timestamp > the date when the old version of ## Bioconductor was valid. ## NOTE: The 'date' variable is the snapshotDate(). query1 <- sprintf( 'SELECT resources.id FROM resources, rdatapaths, biocversions WHERE resources.rdatadateadded <= "%s" AND biocversions.biocversion <= "%s" AND resources.rdatadateremoved IS NULL AND rdatapaths.rdataclass != "OrgDb" AND biocversions.resource_id == resources.id AND rdatapaths.resource_id == resources.id', date, biocVersion()) biocIds1 <- .db_query(conn, query1)[[1]] ## OrgDb sqlite files: ## ## OrgDbs are the single resource designed to expire at the end of a ## release cycle. The sqlite files are built before a release, added to the ## devel branch then propagate to the new release branch. For the ## duration of a release cycle both release and devel share the same ## OrgDb packages. Before the next release, new files are built, added ## to devel, propagated to release and so on. ## ## When new sqlite files are added to the hub they are stamped ## with the devel version which immediately becomes the new release version. ## For this reason, the devel code loads OrgDbs with the release version ## e.g., ## ifelse(isDevel(), biocversion - 0.1, biocversion) ## ## NOTE: Because OrgDbs are valid for a full devel cycle they are ## not filtered by snapshotDate(); the OrgDbs are valid for all ## snapshotDates for a given biocVersion() biocversion <- as.numeric(as.character(biocVersion())) orgdb_release_version <- ifelse(isDevel(), biocversion - 0.1, biocversion) query2 <- sprintf( 'SELECT resources.id FROM resources, biocversions, rdatapaths WHERE biocversions.biocversion == "%s" AND rdatapaths.rdataclass == "OrgDb" AND resources.rdatadateremoved IS NULL AND biocversions.resource_id == resources.id AND rdatapaths.resource_id == resources.id', orgdb_release_version) biocIds2 <- .db_query(conn, query2)[[1]] ## make unique and sort allIds = sort(unique(c(biocIds1, biocIds2))) ## match id to ah_id query <- paste0('SELECT ah_id FROM resources ', 'WHERE id IN (', paste0(allIds, collapse=","), ')', 'ORDER BY id') names(allIds) <- .db_query(conn, query)[[1]] allIds } ## FIXME: On one hand it's convenient to have helpers for each of these fields. ## Yet the main (only?) use case is probably mcols() and show() in ## which case we want all of these and it's inefficient to search ## the same table multiple times for the different fields. ## helper to retrieve tags .tags <- function(x) { query <- sprintf( 'SELECT DISTINCT tag, resource_id AS id FROM tags WHERE resource_id IN (%s)', .id_as_single_string(x)) .db_query(dbfile(x), query) } ## helper for extracting rdataclass .rdataclass <- function(x) { query <- sprintf( 'SELECT DISTINCT rdataclass, resource_id AS id FROM rdatapaths WHERE resource_id IN (%s)', .id_as_single_string(x)) .db_query(dbfile(x), query) } ## helper for extracting rdatapath .rdatapath <- function(x) { query <- sprintf( 'SELECT DISTINCT rdatapath, resource_id AS id FROM rdatapaths WHERE resource_id IN (%s)', .id_as_single_string(x)) .db_query(dbfile(x), query) } ## helper for extracting sourceUrls .sourceurl <- function(x) { query <- sprintf( 'SELECT DISTINCT sourceurl, resource_id AS id FROM input_sources WHERE resource_id IN (%s)', .id_as_single_string(x)) .db_query(dbfile(x), query) } ## helper for extracting sourcetype .sourcetype <- function(x) { query <- sprintf( 'SELECT DISTINCT sourcetype, resource_id AS id FROM input_sources WHERE resource_id IN (%s)', .id_as_single_string(x)) .db_query(dbfile(x), query) } .sourcesize <- function(x) { query <- sprintf( 'SELECT DISTINCT sourcesize, resource_id AS id FROM input_sources WHERE resource_id IN (%s)', .id_as_single_string(x)) .db_query(dbfile(x), query) } .sourcelastmodifieddate <- function(x) { query <- sprintf( 'SELECT DISTINCT sourcelastmodifieddate, resource_id AS id FROM input_sources WHERE resource_id IN (%s)', .id_as_single_string(x)) .db_query(dbfile(x), query) } ## Helper to collapse many to one fields (like above) into one space .collapse_as_string <- function(x, FUN) { uid <- .db_uid(x) tbl <- FUN(x) lst <- vapply(split(tbl[[1]], tbl[["id"]]), paste0, character(1), collapse=", ") lst <- lst[match(uid, names(lst))] setNames(lst, names(uid)) # allows for x with no tags } .collapse_as_list <- function(x, FUN) { uid <- .db_uid(x) tbl <- FUN(x) lst <- split(tbl[[1]], tbl$id) lst <- lst[match(uid, names(lst))] setNames(lst, names(uid)) # allows for x with no tags } ## Used in mcols() .DB_RESOURCE_FIELDS <- paste(sep=".", collapse=", ", "resources", c("ah_id", "title", "dataprovider", "species", "taxonomyid", "genome", "description", "coordinate_1_based", "maintainer", "rdatadateadded", "preparerclass")) .resource_table <- function(x) { query <- sprintf( 'SELECT %s FROM resources WHERE resources.id IN (%s)', .DB_RESOURCE_FIELDS, .id_as_single_string(x)) tbl <- .query_as_data.frame(x, query) tbl[["tags"]] <- I(.collapse_as_list(x, .tags)) tbl[["rdataclass"]] <- .collapse_as_string(x, .rdataclass) tbl[["rdatapath"]] <- .collapse_as_string(x, .rdatapath) tbl[["sourceurl"]] <- .collapse_as_string(x, .sourceurl) tbl[["sourcetype"]] <- .collapse_as_string(x, .sourcetype) tbl } .resource_columns <- function() strsplit(gsub("resources.", "", .DB_RESOURCE_FIELDS), ", ")[[1]] .resource_column <- function(x, name) { valid <- .resource_columns() if (!name %in% valid) { msg <- sprintf("%s is not a resource data column", sQuote(name)) stop(msg) } query <- sprintf( 'SELECT ah_id, %s FROM resources WHERE id IN (%s)', name, .id_as_single_string(x)) .query_as_data.frame(x, query)[[1]] } ## This is used by cache to get the rDataPath ID for a resource .datapathIds <- function(x) { query <- sprintf( 'SELECT DISTINCT resources.ah_id, rdatapaths.id FROM resources, rdatapaths WHERE resources.id IN (%s) AND resources.id == rdatapaths.resource_id', .id_as_single_string(x)) result <- .db_query(dbfile(x), query) setNames(result[[2]], result[[1]]) } ## .dataclass <- function(x) { query <- sprintf( 'SELECT DISTINCT r.ah_id AS ah_id, rdp.dispatchclass FROM rdatapaths AS rdp, resources AS r WHERE r.id = rdp.resource_id AND rdp.resource_id IN (%s)', .id_as_single_string(x)) .query_as_data.frame(x, query)[[1]] } ## .title_data.frame <- function(x) { query <- sprintf( "SELECT ah_id, title FROM resources WHERE resources.id IN (%s)", .id_as_single_string(x)) .query_as_data.frame(x, query) } .count_resources <- function(x, column, limit=10) { query <- sprintf( "SELECT %s FROM resources WHERE resources.id IN (%s) GROUP BY %s ORDER BY COUNT(%s) DESC LIMIT %d", column, .id_as_single_string(x), column, column, limit) .db_query(dbfile(x), query)[[column]] } .count_join_resources <- function(x, table, column, limit=10) { query <- sprintf( "SELECT %s FROM resources, %s WHERE resources.id IN (%s) AND %s.resource_id == resources.id GROUP BY %s ORDER BY COUNT(%s) DESC LIMIT %d", column, table, .id_as_single_string(x), table, column, column, limit) .db_query(dbfile(x), query)[[column]] } ## make a function to create a view whenever the DB is updated.. ## SQL will look kind of like the one used for go: ## CREATE VIEW go AS ## SELECT _id,go_id,evidence, 'BP' AS 'ontology' FROM go_bp ## UNION ## SELECT _id,go_id,evidence, 'CC' FROM go_cc ## UNION ## SELECT _id,go_id,evidence, 'MF' FROM go_mf; ## SO now we just need to decide on which views we want/need. ## So really we want to 1st refactor the show method (and make hard decisions there) ## And the view we create here should reflect those ideas. ## CREATE VIEW hub AS ## SELECT * FROM resources AS r, rdatapaths AS rdp, input_sources AS ins WHERE r.id=rdp.resource_id AND r.id=ins.resource_id LIMIT 2; ## Sonali better date query ## SELECT * FROM resources where rdatadateadded <= "2013-03-19" GROUP BY title ORDER BY rdatadateadded DESC limit 2; ## Example: ## SELECT COUNT(id) AS theCount, `Tag` from `images-tags` ## GROUP BY `Tag` ## ORDER BY theCount DESC ## LIMIT 20 ## SELECT id FROM ## (SELECT * FROM ## (SELECT * FROM resources where rdatadateadded <= "2013-03-19") ## AS res GROUP BY title ORDER BY rdatadateadded DESC limit 1); ## SELECT MAX(id) FROM (SELECT id FROM (select * from resources where ah_id in ('AH523','AH22249')) AS res GROUP BY title) AS res; ## same issue ## Here is an example that actually does get close: ## SELECT max(id) as mid, id, ah_id, title FROM (select * from resources where ah_id in ('AH523','AH22249','AH524','AH22250')) AS res GROUP BY maintainer; ## Basically I would just want it like this: ## SELECT max(id) as mid FROM (select * from resources where ah_id in ('AH523','AH22249','AH524','AH22250')) AS res GROUP BY maintainer; ## And then group by title instead so pretty much like this: ## SELECT max(id) as id FROM (SELECT * FROM resources where rdatadateadded <= "2013-03-19") AS res GROUP BY title; AnnotationHub/R/utilities.R0000644000175400017540000001153713175714307016727 0ustar00biocbuildbiocbuild.require <- function(pkg) { result <- TRUE if (length(grep(sprintf("package:%s", pkg), search())) != 0L) return(invisible(result)) message("require(", dQuote(pkg), ")") handler <- function(err) { msg <- sprintf("require(%s) failed: %s", dQuote(pkg), conditionMessage(err)) stop(msg) } result <- tryCatch(suppressPackageStartupMessages( require(pkg, quietly=TRUE, character.only=TRUE) ), error=handler) if (!result) handler(simpleError("use biocLite() to install package?")) invisible(result) } .ask <- function(txt, values) { txt <- sprintf("%s [%s] ", txt, paste(values, collapse="/")) repeat { ans <- tolower(trimws(readline(txt))) if (ans %in% values) break } ans } .gunzip <- function(file, destination) { bufferSize <- 1e7 fin <- gzfile(file, "rb") fout <- file(destination, "wb") on.exit({ close(fin) close(fout) }) repeat { x <- readBin(fin, raw(0L), bufferSize, 1L) if (length(x) == 0L) break writeBin(x, fout, size=1L) } invisible(destination) } ## tidyGRanges .metadataForAH <- function(x, ...) { stopifnot(length(getHub(x)) == 1) meta <- getHub(x) list(AnnotationHubName=names(meta), `File Name`=basename(meta$sourceurl), `Data Source`=meta$sourceurl, `Provider`=meta$dataprovider, `Organism`=meta$species, `Taxonomy ID`=meta$taxonomyid ) } .guessIsCircular <- function(x) { ans <- GenomeInfoDb::isCircular(x) idx <- is.na(ans) test <- names(ans) %in% c("MT", "MtDNA", "dmel_mitochondrion_genome", "Mito", "chrM") ans[idx] <- test[idx] ans } # tasks we want .tidyGRanges() to do: # 1. add metdata() to GRanges containing the names() of hub object # 2. sortSeqlevels() # 3. fill the seqinfo with correct information # for step 3 - comparison is done with existingSeqinfo and # GenomeInfoDb::Seqinfo() - currently if its not the same, seqinfo is replaced. .tidyGRanges <- function(x, gr, sort=TRUE, guess.circular=TRUE, addGenome=TRUE, metadata=TRUE, genome=getHub(x)$genome) { if (metadata) metadata(gr) <- .metadataForAH(x) ## BEWARE: ## 1) GenomeInfoDb::Seqinfo doesnt sortSeqlevels - so we need to ## sortSeqlevels before comparison else identical wont work. ## 2) case - the input GRanges might have a subset of seqlevels whereas ## the GenomeInfoDb::Seqinfo returns all seqlevels with scaffolds ## from an assembly. ## 3)only 10-15 genomes supported by GenomeInfoDb::Seqinfo tryCatch({ loadNamespace("GenomeInfoDb") }, error=function(err) { ## quietly return un-tidied GRanges (?) return(gr) }) if (sort) gr <- GenomeInfoDb::sortSeqlevels(gr) existingSeqinfo <- GenomeInfoDb::seqinfo(gr) ## Not all Genome's are supported by GenomeInfoDb::Seqinfo newSeqinfo <- tryCatch({ GenomeInfoDb::Seqinfo(genome=genome) }, error= function(err) { NULL }) if (is.null(newSeqinfo)) { message("using guess work to populate seqinfo") ## use guess work to populate if (guess.circular) GenomeInfoDb::isCircular(existingSeqinfo) <- .guessIsCircular(existingSeqinfo) if (addGenome) GenomeInfoDb::genome(existingSeqinfo) <- genome if (sort || guess.circular || addGenome) { new2old <- match(GenomeInfoDb::seqlevels(existingSeqinfo), GenomeInfoDb::seqlevels(gr)) GenomeInfoDb::seqinfo(gr, new2old=new2old) <- existingSeqinfo } return(gr) } newSeqinfo <- newSeqinfo[GenomeInfoDb::seqlevels(gr)] # comapre the current and new seqinfo diffSeqlengths <- setdiff(GenomeInfoDb::seqlengths(newSeqinfo), GenomeInfoDb::seqlengths(existingSeqinfo)) diffSeqnames <- setdiff(GenomeInfoDb::seqnames(newSeqinfo), GenomeInfoDb::seqnames(existingSeqinfo)) diffGenome <- identical(unique(GenomeInfoDb::genome(newSeqinfo)), unique(GenomeInfoDb::genome(existingSeqinfo))) diffIscircular <- identical(table(GenomeInfoDb::isCircular(newSeqinfo)), table(GenomeInfoDb::isCircular(existingSeqinfo))) len <- c(length(diffSeqlengths), length(diffSeqnames)) # if its the same dont replace if(all(unique(len)==0 & diffGenome & diffIscircular)) return(gr) ## Replace incorrect seqinfo if (sort || guess.circular || addGenome) { new2old <- match(GenomeInfoDb::seqlevels(gr), GenomeInfoDb::seqlevels(newSeqinfo)) GenomeInfoDb::seqinfo(gr, new2old=new2old) <- newSeqinfo } gr } AnnotationHub/R/zzz.R0000644000175400017540000000250513175714307015544 0ustar00biocbuildbiocbuild.CACHE_ROOT <- ".AnnotationHub" .onLoad <- function(libname, pkgname, ...) { ## options from getOption or Sys.env or default, in that order if (is.null(getAnnotationHubOption("MAX_DOWNLOADS"))) { opt <- getOption("ANNOTATION_HUB_MAX_DOWNLOADS", 10L) opt <- Sys.getenv("ANNOTATION_HUB_MAX_DOWNLOADS", opt) opt <- as.integer(opt) setAnnotationHubOption("MAX_DOWNLOADS", opt) } if (is.null(getAnnotationHubOption("URL"))) { opt <- getOption("ANNOTATION_HUB_URL", "https://annotationhub.bioconductor.org") opt <- Sys.getenv("ANNOTATION_HUB_URL", opt) setAnnotationHubOption("URL", opt) } if (is.null(getAnnotationHubOption("CACHE"))) { path <- switch(.Platform$OS.type, unix = path.expand("~/"), windows= file.path(gsub("\\\\", "/", Sys.getenv("HOME")), "AppData")) opt <- getOption("ANNOTATION_HUB_CACHE", file.path(path, .CACHE_ROOT)) opt <- Sys.getenv("ANNOTATION_HUB_CACHE", opt) setAnnotationHubOption("CACHE", opt) } if (is.null(getAnnotationHubOption("PROXY"))) { opt <- getOption("ANNOTATION_HUB_PROXY", "") opt <- Sys.getenv("ANNOTATION_HUB_PROXY", opt) if (nzchar(opt)) setAnnotationHubOption("PROXY", opt) } } AnnotationHub/build/0000755000175400017540000000000013200446560015450 5ustar00biocbuildbiocbuildAnnotationHub/build/vignette.rds0000644000175400017540000000052313200446560020007 0ustar00biocbuildbiocbuild}RK0nQzOs0Y܊m"m\[Mx/yjB,b;l]Z8qq1.H8,Wp2QK@$ iBgP%"˭jz7frAQxbF#$YzmV=&lFΌRnl!Qe:GKpϰ\c8݊^hLϒ(@EuwTLpQO C^mHf[ T\smX}1օܜ|%Ywʲ0;RZwmTP9z>AAnnotationHub/inst/0000755000175400017540000000000013200446560015326 5ustar00biocbuildbiocbuildAnnotationHub/inst/doc/0000755000175400017540000000000013200446560016073 5ustar00biocbuildbiocbuildAnnotationHub/inst/doc/AnnotationHub-HOWTO.R0000644000175400017540000001436413200446544021677 0ustar00biocbuildbiocbuild## ----style, echo = FALSE, results = 'asis', warning=FALSE----------------------------------------- options(width=100) suppressPackageStartupMessages({ ## load here to avoid noise in the body of the vignette library(AnnotationHub) library(GenomicFeatures) library(Rsamtools) library(VariantAnnotation) }) BiocStyle::markdown() ## ----less-model-org------------------------------------------------------------------------------- library(AnnotationHub) ah <- AnnotationHub() query(ah, "OrgDb") orgdb <- query(ah, "OrgDb")[[1]] ## ----less-model-org-select------------------------------------------------------------------------ keytypes(orgdb) columns(orgdb) egid <- head(keys(orgdb, "ENTREZID")) select(orgdb, egid, c("SYMBOL", "GENENAME"), "ENTREZID") ## ---- eval=FALSE---------------------------------------------------------------------------------- # url <- "http://egg2.wustl.edu/roadmap/data/byFileType/peaks/consolidated/broadPeak/E001-H3K4me1.broadPeak.gz" # filename <- basename(url) # download.file(url, destfile=filename) # if (file.exists(filename)) # data <- import(filename, format="bed") ## ----results='hide'------------------------------------------------------------------------------- library(AnnotationHub) ah = AnnotationHub() epiFiles <- query(ah, "EpigenomeRoadMap") ## ------------------------------------------------------------------------------------------------- epiFiles ## ------------------------------------------------------------------------------------------------- unique(epiFiles$species) unique(epiFiles$genome) ## ------------------------------------------------------------------------------------------------- table(epiFiles$sourcetype) ## ------------------------------------------------------------------------------------------------- sort(table(epiFiles$description), decreasing=TRUE) ## ------------------------------------------------------------------------------------------------- metadata.tab <- query(ah , c("EpigenomeRoadMap", "Metadata")) metadata.tab ## ----echo=FALSE, results='hide'------------------------------------------------------------------- metadata.tab <- ah[["AH41830"]] ## ------------------------------------------------------------------------------------------------- metadata.tab <- ah[["AH41830"]] ## ------------------------------------------------------------------------------------------------- metadata.tab[1:6, 1:5] ## ------------------------------------------------------------------------------------------------- bpChipEpi <- query(ah , c("EpigenomeRoadMap", "broadPeak", "chip", "consolidated")) ## ------------------------------------------------------------------------------------------------- allBigWigFiles <- query(ah, c("EpigenomeRoadMap", "BigWig")) ## ------------------------------------------------------------------------------------------------- seg <- query(ah, c("EpigenomeRoadMap", "segmentations")) ## ------------------------------------------------------------------------------------------------- E126 <- query(ah , c("EpigenomeRoadMap", "E126", "H3K4ME2")) E126 ## ----echo=FALSE, results='hide'------------------------------------------------------------------- peaks <- E126[['AH29817']] ## ------------------------------------------------------------------------------------------------- peaks <- E126[['AH29817']] seqinfo(peaks) ## ------------------------------------------------------------------------------------------------- metadata(peaks) ah[metadata(peaks)$AnnotationHubName]$sourceurl ## ----takifugu-gene-models------------------------------------------------------------------------- query(ah, c("Takifugu", "release-80")) ## ----takifugu-data-------------------------------------------------------------------------------- gtf <- ah[["AH47101"]] dna <- ah[["AH47477"]] head(gtf, 3) dna head(seqlevels(dna)) ## ----takifugu-seqlengths-------------------------------------------------------------------------- keep <- names(tail(sort(seqlengths(dna)), 25)) gtf_subset <- gtf[seqnames(gtf) %in% keep] ## ----takifugu-txdb-------------------------------------------------------------------------------- library(GenomicFeatures) # for makeTxDbFromGRanges txdb <- makeTxDbFromGRanges(gtf_subset) ## ----takifugu-exons------------------------------------------------------------------------------- library(Rsamtools) # for getSeq,FaFile-method exons <- exons(txdb) length(exons) getSeq(dna, exons) ## ------------------------------------------------------------------------------------------------- chainfiles <- query(ah , c("hg38", "hg19", "chainfile")) chainfiles ## ----echo=FALSE, results='hide'------------------------------------------------------------------- chain <- chainfiles[['AH14150']] ## ------------------------------------------------------------------------------------------------- chain <- chainfiles[['AH14150']] chain ## ------------------------------------------------------------------------------------------------- library(rtracklayer) gr38 <- liftOver(peaks, chain) ## ------------------------------------------------------------------------------------------------- genome(gr38) <- "hg38" gr38 ## ----echo=FALSE, results='hide', message=FALSE---------------------------------------------------- query(ah, c("GRCh38", "dbSNP", "VCF" )) vcf <- ah[['AH57960']] ## ----message=FALSE-------------------------------------------------------------------------------- variants <- readVcf(vcf, genome="hg19") variants ## ------------------------------------------------------------------------------------------------- rowRanges(variants) ## ------------------------------------------------------------------------------------------------- seqlevelsStyle(variants) <-seqlevelsStyle(peaks) ## ------------------------------------------------------------------------------------------------- overlap <- findOverlaps(variants, peaks) overlap ## ------------------------------------------------------------------------------------------------- idx <- subjectHits(overlap) == 3852 overlap[idx] ## ------------------------------------------------------------------------------------------------- peaks[3852] rowRanges(variants)[queryHits(overlap[idx])] ## ------------------------------------------------------------------------------------------------- sessionInfo() AnnotationHub/inst/doc/AnnotationHub-HOWTO.Rmd0000644000175400017540000002635313175714307022227 0ustar00biocbuildbiocbuild--- title: "AnnotationHub How-To's" output: BiocStyle::html_document: toc: true vignette: > % \VignetteIndexEntry{AnnotationHub: AnnotationHub HOW TO's} % \VignetteDepends{AnnotationHub, GenomicFeatures, Rsamtools} % \VignetteEngine{knitr::rmarkdown} --- ```{r style, echo = FALSE, results = 'asis', warning=FALSE} options(width=100) suppressPackageStartupMessages({ ## load here to avoid noise in the body of the vignette library(AnnotationHub) library(GenomicFeatures) library(Rsamtools) library(VariantAnnotation) }) BiocStyle::markdown() ``` **Package**: `r Biocpkg("AnnotationHub")`
**Authors**: `r packageDescription("AnnotationHub")[["Author"]] `
**Modified**: Sun Jun 28 10:41:23 2015
**Compiled**: `r date()` # Accessing Genome-Scale Data ## Non-model organism gene annotations _Bioconductor_ offers pre-built `org.*` annotation packages for model organisms, with their use described in the [OrgDb](http://bioconductor.org/help/workflows/annotation/Annotation_Resources/#OrgDb) section of the Annotation work flow. Here we discover available `OrgDb` objects for less-model organisms ```{r less-model-org} library(AnnotationHub) ah <- AnnotationHub() query(ah, "OrgDb") orgdb <- query(ah, "OrgDb")[[1]] ``` The object returned by AnnotationHub is directly usable with the `select()` interface, e.g., to discover the available keytypes for querying the object, the columns that these keytypes can map to, and finally selecting the SYMBOL and GENENAME corresponding to the first 6 ENTREZIDs ```{r less-model-org-select} keytypes(orgdb) columns(orgdb) egid <- head(keys(orgdb, "ENTREZID")) select(orgdb, egid, c("SYMBOL", "GENENAME"), "ENTREZID") ``` ## Roadmap Epigenomics Project All Roadmap Epigenomics files are hosted [here](http://egg2.wustl.edu/roadmap/data/byFileType/). If one had to download these files on their own, one would navigate through the web interface to find useful files, then use something like the following _R_ code. ```{r, eval=FALSE} url <- "http://egg2.wustl.edu/roadmap/data/byFileType/peaks/consolidated/broadPeak/E001-H3K4me1.broadPeak.gz" filename <- basename(url) download.file(url, destfile=filename) if (file.exists(filename)) data <- import(filename, format="bed") ``` This would have to be repeated for all files, and the onus would lie on the user to identify, download, import, and manage the local disk location of these files. `r Biocpkg("AnnotationHub")` reduces this task to just a few lines of _R_ code ```{r results='hide'} library(AnnotationHub) ah = AnnotationHub() epiFiles <- query(ah, "EpigenomeRoadMap") ``` A look at the value returned by `epiFiles` shows us that `r length(epiFiles)` roadmap resources are available via `r Biocpkg("AnnotationHub")`. Additional information about the files is also available, e.g., where the files came from (dataprovider), genome, species, sourceurl, sourcetypes. ```{r} epiFiles ``` A good sanity check to ensure that we have files only from the Roadmap Epigenomics project is to check that all the files in the returned smaller hub object come from _Homo sapiens_ and the `r unique(epiFiles$genome)` genome ```{r} unique(epiFiles$species) unique(epiFiles$genome) ``` Broadly, one can get an idea of the different files from this project looking at the sourcetype ```{r} table(epiFiles$sourcetype) ``` To get a more descriptive idea of these different files one can use: ```{r} sort(table(epiFiles$description), decreasing=TRUE) ``` The 'metadata' provided by the Roadmap Epigenomics Project is also available. Note that the information displayed about a hub with a single resource is quite different from the information displayed when the hub references more than one resource. ```{r} metadata.tab <- query(ah , c("EpigenomeRoadMap", "Metadata")) metadata.tab ``` So far we have been exploring information about resources, without downloading the resource to a local cache and importing it into R. One can retrieve the resource using `[[` as indicated at the end of the show method ```{r echo=FALSE, results='hide'} metadata.tab <- ah[["AH41830"]] ``` ```{r} metadata.tab <- ah[["AH41830"]] ``` The metadata.tab file is returned as a _data.frame_. The first 6 rows of the first 5 columns are shown here: ```{r} metadata.tab[1:6, 1:5] ``` One can keep constructing different queries using multiple arguments to trim down these `r length(epiFiles)` to get the files one wants. For example, to get the ChIP-Seq files for consolidated epigenomes, one could use ```{r} bpChipEpi <- query(ah , c("EpigenomeRoadMap", "broadPeak", "chip", "consolidated")) ``` To get all the bigWig signal files, one can query the hub using ```{r} allBigWigFiles <- query(ah, c("EpigenomeRoadMap", "BigWig")) ``` To access the 15 state chromatin segmentations, one can use ```{r} seg <- query(ah, c("EpigenomeRoadMap", "segmentations")) ``` If one is interested in getting all the files related to one sample ```{r} E126 <- query(ah , c("EpigenomeRoadMap", "E126", "H3K4ME2")) E126 ``` Hub resources can also be selected using `$`, `subset()`, and `display()`; see the main [_AnnotationHub_ vignette](AnnotationHub.html) for additional detail. Hub resources are imported as the appropriate _Bioconductor_ object for use in further analysis. For example, peak files are returned as _GRanges_ objects. ```{r echo=FALSE, results='hide'} peaks <- E126[['AH29817']] ``` ```{r} peaks <- E126[['AH29817']] seqinfo(peaks) ``` BigWig files are returned as _BigWigFile_ objects. A _BigWigFile_ is a reference to a file on disk; the data in the file can be read in using `rtracklayer::import()`, perhaps querying these large files for particular genomic regions of interest as described on the help page `?import.bw`. Each record inside `r Biocpkg("AnnotationHub")` is associated with a unique identifier. Most _GRanges_ objects returned by `r Biocpkg("AnnotationHub")` contain the unique AnnotationHub identifier of the resource from which the _GRanges_ is derived. This can come handy when working with the _GRanges_ object for a while, and additional information about the object (e.g., the name of the file in the cache, or the original sourceurl for the data underlying the resource) that is being worked with. ```{r} metadata(peaks) ah[metadata(peaks)$AnnotationHubName]$sourceurl ``` ## Ensembl GTF and FASTA files for TxDb gene models and sequence queries _Bioconductor_ represents gene models using 'transcript' databases. These are available via packages such as `r Biocannopkg("TxDb.Hsapiens.UCSC.hg38.knownGene")` or can be constructed using functions such as `r Biocpkg("GenomicFeatures")`::`makeTxDbFromBiomart()`. _AnnotationHub_ provides an easy way to work with gene models published by Ensembl. Let's see what Ensembl's Release-80 has in terms of data for pufferfish, _Takifugu rubripes_. ```{r takifugu-gene-models} query(ah, c("Takifugu", "release-80")) ``` We see that there is a GTF file descrbing gene models, as well as various DNA sequences. Let's retrieve the GTF and top-level DNA sequence files. The GTF file is imported as a _GRanges_ instance, the DNA sequence as a compressed, indexed Fasta file ```{r takifugu-data} gtf <- ah[["AH47101"]] dna <- ah[["AH47477"]] head(gtf, 3) dna head(seqlevels(dna)) ``` Let's identify the 25 longest DNA sequences, and keep just the annotations on these scaffolds. ```{r takifugu-seqlengths} keep <- names(tail(sort(seqlengths(dna)), 25)) gtf_subset <- gtf[seqnames(gtf) %in% keep] ``` It is trivial to make a TxDb instance of this subset (or of the entire gtf) ```{r takifugu-txdb} library(GenomicFeatures) # for makeTxDbFromGRanges txdb <- makeTxDbFromGRanges(gtf_subset) ```` and to use that in conjunction with the DNA sequences, e.g., to find exon sequences of all annotated genes. ```{r takifugu-exons} library(Rsamtools) # for getSeq,FaFile-method exons <- exons(txdb) length(exons) getSeq(dna, exons) ``` There is a one-to-one mapping between the genomic ranges contained in `exons` and the DNA sequences returned by `getSeq()`. Some difficulties arise when working with this partly assembled genome that require more advanced GenomicRanges skills, see the `r Biocpkg("GenomicRanges")` vignettes, especially "_GenomicRanges_ HOWTOs" and "An Introduction to _GenomicRanges_". ## liftOver to map between genome builds Suppose we wanted to lift features from one genome build to another, e.g., because annotations were generated for hg19 but our experimental analysis used hg18. We know that UCSC provides 'liftover' files for mapping between genome builds. In this example, we will take our broad Peak _GRanges_ from E126 which comes from the 'hg19' genome, and lift over these features to their 'hg38' coordinates. ```{r} chainfiles <- query(ah , c("hg38", "hg19", "chainfile")) chainfiles ``` We are interested in the file that lifts over features from hg19 to hg38 so lets download that using ```{r echo=FALSE, results='hide'} chain <- chainfiles[['AH14150']] ``` ```{r} chain <- chainfiles[['AH14150']] chain ``` Perform the liftOver operation using `rtracklayer::liftOver()`: ```{r} library(rtracklayer) gr38 <- liftOver(peaks, chain) ``` This returns a _GRangeslist_; update the genome of the result to get the final result ```{r} genome(gr38) <- "hg38" gr38 ``` ## Working with dbSNP Variants One may also be interested in working with common germline variants with evidence of medical interest. This information is available at [NCBI](https://www.ncbi.nlm.nih.gov/variation/docs/human_variation_vcf/). Query the dbDNP files in the hub: ```{r echo=FALSE, results='hide', message=FALSE} query(ah, c("GRCh38", "dbSNP", "VCF" )) vcf <- ah[['AH57960']] ``` This returns a _VcfFile_ which can be read in using `r Biocpkg("VariantAnnotation")`; because VCF files can be large, `readVcf()` supports several strategies for importing only relevant parts of the file (e.g., particular genomic locations, particular features of the variants), see `?readVcf` for additional information. ```{r message=FALSE} variants <- readVcf(vcf, genome="hg19") variants ``` `rowRanges()` returns information from the CHROM, POS and ID fields of the VCF file, represented as a _GRanges_ instance ```{r} rowRanges(variants) ``` Note that the broadPeaks files follow the UCSC chromosome naming convention, and the vcf data follows the NCBI style of chromosome naming convention. To bring these ranges in the same chromosome naming convention (ie UCSC), we would use ```{r} seqlevelsStyle(variants) <-seqlevelsStyle(peaks) ``` And then finally to find which variants overlap these broadPeaks we would use: ```{r} overlap <- findOverlaps(variants, peaks) overlap ``` Some insight into how these results can be interpretted comes from looking a particular peak, e.g., the 3852nd peak ```{r} idx <- subjectHits(overlap) == 3852 overlap[idx] ``` There are three variants overlapping this peak; the coordinates of the peak and the overlapping variants are ```{r} peaks[3852] rowRanges(variants)[queryHits(overlap[idx])] ``` # sessionInfo ```{r} sessionInfo() ``` AnnotationHub/inst/doc/AnnotationHub-HOWTO.html0000644000175400017540000273713413200446545022454 0ustar00biocbuildbiocbuild AnnotationHub How-To’s

Contents

Package: AnnotationHub
Authors: Martin Morgan [cre], Marc Carlson [ctb], Dan Tenenbaum [ctb], Sonali Arora [ctb]
Modified: Sun Jun 28 10:41:23 2015
Compiled: Tue Nov 7 19:17:44 2017

1 Accessing Genome-Scale Data

1.1 Non-model organism gene annotations

Bioconductor offers pre-built org.* annotation packages for model organisms, with their use described in the OrgDb section of the Annotation work flow. Here we discover available OrgDb objects for less-model organisms

library(AnnotationHub)
ah <- AnnotationHub()
## snapshotDate(): 2017-10-27
query(ah, "OrgDb")
## AnnotationHub with 1019 records
## # snapshotDate(): 2017-10-27 
## # $dataprovider: ftp://ftp.ncbi.nlm.nih.gov/gene/DATA/
## # $species: Escherichia coli, 'Caballeronia concitans', 'Chlorella vulgaris'_C-169, 'Frankia cas...
## # $rdataclass: OrgDb
## # additional mcols(): taxonomyid, genome, description, coordinate_1_based, maintainer,
## #   rdatadateadded, preparerclass, tags, rdatapath, sourceurl, sourcetype 
## # retrieve records with, e.g., 'object[["AH57964"]]' 
## 
##             title                                                                         
##   AH57964 | org.Ag.eg.db.sqlite                                                           
##   AH57965 | org.At.tair.db.sqlite                                                         
##   AH57966 | org.Bt.eg.db.sqlite                                                           
##   AH57967 | org.Cf.eg.db.sqlite                                                           
##   AH57968 | org.Gg.eg.db.sqlite                                                           
##   ...       ...                                                                           
##   AH58988 | org.Flavobacterium_piscicida.eg.sqlite                                        
##   AH58989 | org.Bacteroides_fragilis_YCH46.eg.sqlite                                      
##   AH58990 | org.Pseudomonas_mendocina_ymp.eg.sqlite                                       
##   AH58991 | org.Salmonella_enterica_subsp._enterica_serovar_Typhimurium_str._LT2.eg.sqlite
##   AH58992 | org.Acinetobacter_baumannii.eg.sqlite
orgdb <- query(ah, "OrgDb")[[1]] 
## loading from cache '/home/biocbuild//.AnnotationHub/64710'

The object returned by AnnotationHub is directly usable with the select() interface, e.g., to discover the available keytypes for querying the object, the columns that these keytypes can map to, and finally selecting the SYMBOL and GENENAME corresponding to the first 6 ENTREZIDs

keytypes(orgdb)
##  [1] "ACCNUM"       "ENSEMBL"      "ENSEMBLPROT"  "ENSEMBLTRANS" "ENTREZID"     "ENZYME"      
##  [7] "EVIDENCE"     "EVIDENCEALL"  "GENENAME"     "GO"           "GOALL"        "ONTOLOGY"    
## [13] "ONTOLOGYALL"  "PATH"         "PMID"         "REFSEQ"       "SYMBOL"       "UNIGENE"     
## [19] "UNIPROT"
columns(orgdb)
##  [1] "ACCNUM"       "ENSEMBL"      "ENSEMBLPROT"  "ENSEMBLTRANS" "ENTREZID"     "ENZYME"      
##  [7] "EVIDENCE"     "EVIDENCEALL"  "GENENAME"     "GO"           "GOALL"        "ONTOLOGY"    
## [13] "ONTOLOGYALL"  "PATH"         "PMID"         "REFSEQ"       "SYMBOL"       "UNIGENE"     
## [19] "UNIPROT"
egid <- head(keys(orgdb, "ENTREZID"))
select(orgdb, egid, c("SYMBOL", "GENENAME"), "ENTREZID")
## 'select()' returned 1:1 mapping between keys and columns
##   ENTREZID          SYMBOL      GENENAME
## 1  1267437 AgaP_AGAP012606 AGAP012606-PA
## 2  1267439 AgaP_AGAP012559 AGAP012559-PA
## 3  1267440 AgaP_AGAP012558 AGAP012558-PA
## 4  1267447 AgaP_AGAP012586 AGAP012586-PA
## 5  1267450 AgaP_AGAP012834 AGAP012834-PA
## 6  1267459 AgaP_AGAP012589 AGAP012589-PA

1.2 Roadmap Epigenomics Project

All Roadmap Epigenomics files are hosted here. If one had to download these files on their own, one would navigate through the web interface to find useful files, then use something like the following R code.

url <- "http://egg2.wustl.edu/roadmap/data/byFileType/peaks/consolidated/broadPeak/E001-H3K4me1.broadPeak.gz"
filename <-  basename(url)
download.file(url, destfile=filename)
if (file.exists(filename))
   data <- import(filename, format="bed")

This would have to be repeated for all files, and the onus would lie on the user to identify, download, import, and manage the local disk location of these files.

AnnotationHub reduces this task to just a few lines of R code

library(AnnotationHub)
ah = AnnotationHub()
## snapshotDate(): 2017-10-27
epiFiles <- query(ah, "EpigenomeRoadMap")

A look at the value returned by epiFiles shows us that 18248 roadmap resources are available via AnnotationHub. Additional information about the files is also available, e.g., where the files came from (dataprovider), genome, species, sourceurl, sourcetypes.

epiFiles
## AnnotationHub with 18248 records
## # snapshotDate(): 2017-10-27 
## # $dataprovider: BroadInstitute
## # $species: Homo sapiens
## # $rdataclass: BigWigFile, GRanges, data.frame
## # additional mcols(): taxonomyid, genome, description, coordinate_1_based, maintainer,
## #   rdatadateadded, preparerclass, tags, rdatapath, sourceurl, sourcetype 
## # retrieve records with, e.g., 'object[["AH28856"]]' 
## 
##             title                                 
##   AH28856 | E001-H3K4me1.broadPeak.gz             
##   AH28857 | E001-H3K4me3.broadPeak.gz             
##   AH28858 | E001-H3K9ac.broadPeak.gz              
##   AH28859 | E001-H3K9me3.broadPeak.gz             
##   AH28860 | E001-H3K27me3.broadPeak.gz            
##   ...       ...                                   
##   AH49540 | E058_mCRF_FractionalMethylation.bigwig
##   AH49541 | E059_mCRF_FractionalMethylation.bigwig
##   AH49542 | E061_mCRF_FractionalMethylation.bigwig
##   AH49543 | E081_mCRF_FractionalMethylation.bigwig
##   AH49544 | E082_mCRF_FractionalMethylation.bigwig

A good sanity check to ensure that we have files only from the Roadmap Epigenomics project is to check that all the files in the returned smaller hub object come from Homo sapiens and the hg19 genome

unique(epiFiles$species)
## [1] "Homo sapiens"
unique(epiFiles$genome)
## [1] "hg19"

Broadly, one can get an idea of the different files from this project looking at the sourcetype

table(epiFiles$sourcetype)
## 
##    BED BigWig    GTF    Zip    tab 
##   8298   9932      3     14      1

To get a more descriptive idea of these different files one can use:

sort(table(epiFiles$description), decreasing=TRUE)
## 
##                       Bigwig File containing -log10(p-value) signal tracks from EpigenomeRoadMap Project 
##                                                                                                     6881 
##                       Bigwig File containing fold enrichment signal tracks from EpigenomeRoadMap Project 
##                                                                                                     2947 
##                          Narrow ChIP-seq peaks for consolidated epigenomes from EpigenomeRoadMap Project 
##                                                                                                     2894 
##                           Broad ChIP-seq peaks for consolidated epigenomes from EpigenomeRoadMap Project 
##                                                                                                     2534 
##                          Gapped ChIP-seq peaks for consolidated epigenomes from EpigenomeRoadMap Project 
##                                                                                                     2534 
##                              Narrow DNasePeaks for consolidated epigenomes from EpigenomeRoadMap Project 
##                                                                                                      131 
##                                           15 state chromatin segmentations from EpigenomeRoadMap Project 
##                                                                                                      127 
##      Broad domains on enrichment for DNase-seq for consolidated epigenomes from EpigenomeRoadMap Project 
##                                                                                                       78 
##                                         RRBS fractional methylation calls from EpigenomeRoadMap Project  
##                                                                                                       51 
##                       Whole genome bisulphite fractional methylation calls from EpigenomeRoadMap Project 
##                                                                                                       37 
##                               MeDIP/MRE(mCRF) fractional methylation calls from EpigenomeRoadMap Project 
##                                                                                                       16 
## GencodeV10 gene/transcript coordinates and annotations corresponding to hg19 version of the human genome 
##                                                                                                        3 
##                                       RNA-seq read count matrix for intronic protein-coding RNA elements 
##                                                                                                        2 
##                                                      RNA-seq read counts matrix for ribosomal gene exons 
##                                                                                                        2 
##                                                          RPKM expression matrix for ribosomal gene exons 
##                                                                                                        2 
##                                                                    Metadata for EpigenomeRoadMap Project 
##                                                                                                        1 
##                                                           RNA-seq read counts matrix for non-coding RNAs 
##                                                                                                        1 
##                                                      RNA-seq read counts matrix for protein coding exons 
##                                                                                                        1 
##                                                      RNA-seq read counts matrix for protein coding genes 
##                                                                                                        1 
##                                                           RNA-seq read counts matrix for ribosomal genes 
##                                                                                                        1 
##                                                               RPKM expression matrix for non-coding RNAs 
##                                                                                                        1 
##                                                          RPKM expression matrix for protein coding exons 
##                                                                                                        1 
##                                                          RPKM expression matrix for protein coding genes 
##                                                                                                        1 
##                                                                RPKM expression matrix for ribosomal RNAs 
##                                                                                                        1

The ‘metadata’ provided by the Roadmap Epigenomics Project is also available. Note that the information displayed about a hub with a single resource is quite different from the information displayed when the hub references more than one resource.

metadata.tab <- query(ah , c("EpigenomeRoadMap", "Metadata"))
metadata.tab
## AnnotationHub with 1 record
## # snapshotDate(): 2017-10-27 
## # names(): AH41830
## # $dataprovider: BroadInstitute
## # $species: Homo sapiens
## # $rdataclass: data.frame
## # $rdatadateadded: 2015-05-11
## # $title: EID_metadata.tab
## # $description: Metadata for EpigenomeRoadMap Project
## # $taxonomyid: 9606
## # $genome: hg19
## # $sourcetype: tab
## # $sourceurl: http://egg2.wustl.edu/roadmap/data/byFileType/metadata/EID_metadata.tab
## # $sourcesize: 18035
## # $tags: c("EpigenomeRoadMap", "Metadata") 
## # retrieve record with 'object[["AH41830"]]'

So far we have been exploring information about resources, without downloading the resource to a local cache and importing it into R. One can retrieve the resource using [[ as indicated at the end of the show method

## loading from cache '/home/biocbuild//.AnnotationHub/47270'
metadata.tab <- ah[["AH41830"]]
## loading from cache '/home/biocbuild//.AnnotationHub/47270'

The metadata.tab file is returned as a data.frame. The first 6 rows of the first 5 columns are shown here:

metadata.tab[1:6, 1:5]
##    EID    GROUP   COLOR          MNEMONIC                                   STD_NAME
## 1 E001      ESC #924965            ESC.I3                                ES-I3 Cells
## 2 E002      ESC #924965           ESC.WA7                               ES-WA7 Cells
## 3 E003      ESC #924965            ESC.H1                                   H1 Cells
## 4 E004 ES-deriv #4178AE ESDR.H1.BMP4.MESO H1 BMP4 Derived Mesendoderm Cultured Cells
## 5 E005 ES-deriv #4178AE ESDR.H1.BMP4.TROP H1 BMP4 Derived Trophoblast Cultured Cells
## 6 E006 ES-deriv #4178AE       ESDR.H1.MSC          H1 Derived Mesenchymal Stem Cells

One can keep constructing different queries using multiple arguments to trim down these 18248 to get the files one wants. For example, to get the ChIP-Seq files for consolidated epigenomes, one could use

bpChipEpi <- query(ah , c("EpigenomeRoadMap", "broadPeak", "chip", "consolidated"))

To get all the bigWig signal files, one can query the hub using

allBigWigFiles <- query(ah, c("EpigenomeRoadMap", "BigWig"))

To access the 15 state chromatin segmentations, one can use

seg <- query(ah, c("EpigenomeRoadMap", "segmentations"))

If one is interested in getting all the files related to one sample

E126 <- query(ah , c("EpigenomeRoadMap", "E126", "H3K4ME2"))
E126
## AnnotationHub with 6 records
## # snapshotDate(): 2017-10-27 
## # $dataprovider: BroadInstitute
## # $species: Homo sapiens
## # $rdataclass: BigWigFile, GRanges
## # additional mcols(): taxonomyid, genome, description, coordinate_1_based, maintainer,
## #   rdatadateadded, preparerclass, tags, rdatapath, sourceurl, sourcetype 
## # retrieve records with, e.g., 'object[["AH29817"]]' 
## 
##             title                                  
##   AH29817 | E126-H3K4me2.broadPeak.gz              
##   AH30868 | E126-H3K4me2.narrowPeak.gz             
##   AH31801 | E126-H3K4me2.gappedPeak.gz             
##   AH32990 | E126-H3K4me2.fc.signal.bigwig          
##   AH34022 | E126-H3K4me2.pval.signal.bigwig        
##   AH40177 | E126-H3K4me2.imputed.pval.signal.bigwig

Hub resources can also be selected using $, subset(), and display(); see the main AnnotationHub vignette for additional detail.

Hub resources are imported as the appropriate Bioconductor object for use in further analysis. For example, peak files are returned as GRanges objects.

## require("rtracklayer")
## loading from cache '/home/biocbuild//.AnnotationHub/35257'
peaks <- E126[['AH29817']]
## loading from cache '/home/biocbuild//.AnnotationHub/35257'
seqinfo(peaks)
## Seqinfo object with 93 sequences (1 circular) from hg19 genome:
##   seqnames       seqlengths isCircular genome
##   chr1            249250621      FALSE   hg19
##   chr2            243199373      FALSE   hg19
##   chr3            198022430      FALSE   hg19
##   chr4            191154276      FALSE   hg19
##   chr5            180915260      FALSE   hg19
##   ...                   ...        ...    ...
##   chrUn_gl000245      36651      FALSE   hg19
##   chrUn_gl000246      38154      FALSE   hg19
##   chrUn_gl000247      36422      FALSE   hg19
##   chrUn_gl000248      39786      FALSE   hg19
##   chrUn_gl000249      38502      FALSE   hg19

BigWig files are returned as BigWigFile objects. A BigWigFile is a reference to a file on disk; the data in the file can be read in using rtracklayer::import(), perhaps querying these large files for particular genomic regions of interest as described on the help page ?import.bw.

Each record inside AnnotationHub is associated with a unique identifier. Most GRanges objects returned by AnnotationHub contain the unique AnnotationHub identifier of the resource from which the GRanges is derived. This can come handy when working with the GRanges object for a while, and additional information about the object (e.g., the name of the file in the cache, or the original sourceurl for the data underlying the resource) that is being worked with.

metadata(peaks)
## $AnnotationHubName
## [1] "AH29817"
## 
## $`File Name`
## [1] "E126-H3K4me2.broadPeak.gz"
## 
## $`Data Source`
## [1] "http://egg2.wustl.edu/roadmap/data/byFileType/peaks/consolidated/broadPeak/E126-H3K4me2.broadPeak.gz"
## 
## $Provider
## [1] "BroadInstitute"
## 
## $Organism
## [1] "Homo sapiens"
## 
## $`Taxonomy ID`
## [1] 9606
ah[metadata(peaks)$AnnotationHubName]$sourceurl
## [1] "http://egg2.wustl.edu/roadmap/data/byFileType/peaks/consolidated/broadPeak/E126-H3K4me2.broadPeak.gz"

1.3 Ensembl GTF and FASTA files for TxDb gene models and sequence queries

Bioconductor represents gene models using ‘transcript’ databases. These are available via packages such as TxDb.Hsapiens.UCSC.hg38.knownGene or can be constructed using functions such as GenomicFeatures::makeTxDbFromBiomart().

AnnotationHub provides an easy way to work with gene models published by Ensembl. Let’s see what Ensembl’s Release-80 has in terms of data for pufferfish, Takifugu rubripes.

query(ah, c("Takifugu", "release-80"))
## AnnotationHub with 7 records
## # snapshotDate(): 2017-10-27 
## # $dataprovider: Ensembl
## # $species: Takifugu rubripes
## # $rdataclass: FaFile, GRanges
## # additional mcols(): taxonomyid, genome, description, coordinate_1_based, maintainer,
## #   rdatadateadded, preparerclass, tags, rdatapath, sourceurl, sourcetype 
## # retrieve records with, e.g., 'object[["AH47101"]]' 
## 
##             title                                     
##   AH47101 | Takifugu_rubripes.FUGU4.80.gtf            
##   AH47475 | Takifugu_rubripes.FUGU4.cdna.all.fa       
##   AH47476 | Takifugu_rubripes.FUGU4.dna_rm.toplevel.fa
##   AH47477 | Takifugu_rubripes.FUGU4.dna_sm.toplevel.fa
##   AH47478 | Takifugu_rubripes.FUGU4.dna.toplevel.fa   
##   AH47479 | Takifugu_rubripes.FUGU4.ncrna.fa          
##   AH47480 | Takifugu_rubripes.FUGU4.pep.all.fa

We see that there is a GTF file descrbing gene models, as well as various DNA sequences. Let’s retrieve the GTF and top-level DNA sequence files. The GTF file is imported as a GRanges instance, the DNA sequence as a compressed, indexed Fasta file

gtf <- ah[["AH47101"]]
## loading from cache '/home/biocbuild//.AnnotationHub/52579'
## using guess work to populate seqinfo
dna <- ah[["AH47477"]]
## loading from cache '/home/biocbuild//.AnnotationHub/53323'
##     '/home/biocbuild//.AnnotationHub/53324'
head(gtf, 3)
## GRanges object with 3 ranges and 19 metadata columns:
##         seqnames         ranges strand |   source       type     score     phase            gene_id
##            <Rle>      <IRanges>  <Rle> | <factor>   <factor> <numeric> <integer>        <character>
##   [1] scaffold_1 [10422, 11354]      - |  ensembl       gene      <NA>      <NA> ENSTRUG00000003702
##   [2] scaffold_1 [10422, 11354]      - |  ensembl transcript      <NA>      <NA> ENSTRUG00000003702
##   [3] scaffold_1 [10422, 11354]      - |  ensembl       exon      <NA>      <NA> ENSTRUG00000003702
##       gene_version gene_source   gene_biotype      transcript_id transcript_version
##          <numeric> <character>    <character>        <character>          <numeric>
##   [1]            1     ensembl protein_coding               <NA>               <NA>
##   [2]            1     ensembl protein_coding ENSTRUT00000008740                  1
##   [3]            1     ensembl protein_coding ENSTRUT00000008740                  1
##       transcript_source transcript_biotype exon_number            exon_id exon_version  protein_id
##             <character>        <character>   <numeric>        <character>    <numeric> <character>
##   [1]              <NA>               <NA>        <NA>               <NA>         <NA>        <NA>
##   [2]           ensembl     protein_coding        <NA>               <NA>         <NA>        <NA>
##   [3]           ensembl     protein_coding           1 ENSTRUE00000055472            1        <NA>
##       protein_version   gene_name transcript_name
##             <numeric> <character>     <character>
##   [1]            <NA>        <NA>            <NA>
##   [2]            <NA>        <NA>            <NA>
##   [3]            <NA>        <NA>            <NA>
##   -------
##   seqinfo: 2056 sequences (1 circular) from FUGU4 genome; no seqlengths
dna
## class: FaFile 
## path: /home/biocbuild//.AnnotationHub/53323
## index: /home/biocbuild//.AnnotationHub/53324
## isOpen: FALSE 
## yieldSize: NA
head(seqlevels(dna))
## [1] "scaffold_1" "scaffold_2" "scaffold_3" "scaffold_4" "scaffold_5" "scaffold_6"

Let’s identify the 25 longest DNA sequences, and keep just the annotations on these scaffolds.

keep <- names(tail(sort(seqlengths(dna)), 25))
gtf_subset <- gtf[seqnames(gtf) %in% keep]

It is trivial to make a TxDb instance of this subset (or of the entire gtf)

library(GenomicFeatures)         # for makeTxDbFromGRanges
txdb <- makeTxDbFromGRanges(gtf_subset)
## Warning in .get_cds_IDX(type, phase): The "phase" metadata column contains non-NA values for features of type stop_codon. This
##   information was ignored.

and to use that in conjunction with the DNA sequences, e.g., to find exon sequences of all annotated genes.

library(Rsamtools)               # for getSeq,FaFile-method
exons <- exons(txdb)
length(exons)
## [1] 66219
getSeq(dna, exons)
##   A DNAStringSet instance of length 66219
##         width seq                                                               names               
##     [1]    72 ATGGCCTATCAGTTGTACAGGAATACCACTC...CCTGCAGGAGAGTCTGGACGAGCTTATCCAG scaffold_1
##     [2]   105 ACTCAGCAGATCACCCCTCAGCTGGCTCTCC...TAATCGTGTCCGCAACCGTGTGAACTTCAGG scaffold_1
##     [3]   156 GGTTCTCTCAACACCTACCGGTTCTGTGACA...GAGCGAATCCATGCAAAACAAACTGGATAAA scaffold_1
##     [4]    88 CAAACCAATCTCCTCGCTGTCTCTTCTCGTT...CATCAGCCAGAGGGACGGATCATCTCAGGTT scaffold_1
##     [5]   271 AGACGAGATGAGTGAGGACGCATTCAACGCC...AACACAGTGTGGAGACTTCAGAGGACGCCAC scaffold_1
##     ...   ... ...
## [66215]    67 ACGACTGGATGACAACATCAGGACCGTGGTA...TCAGACCAATGTGGGTCAGGATGGCAGACAG scaffold_9
## [66216]    50 TCTTTGGCTAATATTGACGATGTGGTAAACAAGATTCGTCTGAAGATTCG                scaffold_9
## [66217]    81 GTATTTCCCAGCCAAGACCCGCTGGACAGGG...ATACATCAACACACTGTTTCCCACCGAGCAG scaffold_9
## [66218]    87 ATGATGGAGGATGAAGAATTTGAATTTGCGG...GACCCCAGAGGTGCAGCTAGCAATTGAACAG scaffold_9
## [66219]   213 GACGACATCCTCGTGTGGGGCCGCTCTAGGG...GACAGCTGCTGTTCGCCTGTTTCCCCCCCCC scaffold_9

There is a one-to-one mapping between the genomic ranges contained in exons and the DNA sequences returned by getSeq().

Some difficulties arise when working with this partly assembled genome that require more advanced GenomicRanges skills, see the GenomicRanges vignettes, especially “GenomicRanges HOWTOs” and “An Introduction to GenomicRanges”.

1.4 liftOver to map between genome builds

Suppose we wanted to lift features from one genome build to another, e.g., because annotations were generated for hg19 but our experimental analysis used hg18. We know that UCSC provides ‘liftover’ files for mapping between genome builds.

In this example, we will take our broad Peak GRanges from E126 which comes from the ‘hg19’ genome, and lift over these features to their ‘hg38’ coordinates.

chainfiles <- query(ah , c("hg38", "hg19", "chainfile"))
chainfiles
## AnnotationHub with 2 records
## # snapshotDate(): 2017-10-27 
## # $dataprovider: UCSC
## # $species: Homo sapiens
## # $rdataclass: ChainFile
## # additional mcols(): taxonomyid, genome, description, coordinate_1_based, maintainer,
## #   rdatadateadded, preparerclass, tags, rdatapath, sourceurl, sourcetype 
## # retrieve records with, e.g., 'object[["AH14108"]]' 
## 
##             title                   
##   AH14108 | hg38ToHg19.over.chain.gz
##   AH14150 | hg19ToHg38.over.chain.gz

We are interested in the file that lifts over features from hg19 to hg38 so lets download that using

## loading from cache '/home/biocbuild//.AnnotationHub/18245'
chain <- chainfiles[['AH14150']]
## loading from cache '/home/biocbuild//.AnnotationHub/18245'
chain
## Chain of length 25
## names(25): chr1 chr2 chr3 chr4 chr5 chr6 chr7 chr8 ... chr18 chr19 chr20 chr21 chr22 chrX chrY chrM

Perform the liftOver operation using rtracklayer::liftOver():

library(rtracklayer)
gr38 <- liftOver(peaks, chain)

This returns a GRangeslist; update the genome of the result to get the final result

genome(gr38) <- "hg38"
gr38
## GRangesList object of length 153266:
## [[1]] 
## GRanges object with 1 range and 5 metadata columns:
##       seqnames               ranges strand |        name     score signalValue    pValue    qValue
##          <Rle>            <IRanges>  <Rle> | <character> <numeric>   <numeric> <numeric> <numeric>
##   [1]     chr1 [28667912, 28670147]      * |      Rank_1       189    10.55845  22.01316  18.99911
## 
## [[2]] 
## GRanges object with 1 range and 5 metadata columns:
##       seqnames               ranges strand |   name score signalValue   pValue   qValue
##   [1]     chr4 [54090990, 54092984]      * | Rank_2   188     8.11483 21.80441 18.80662
## 
## [[3]] 
## GRanges object with 1 range and 5 metadata columns:
##       seqnames               ranges strand |   name score signalValue   pValue   qValue
##   [1]    chr14 [75293392, 75296621]      * | Rank_3   180     8.89834 20.97714 18.02816
## 
## ...
## <153263 more elements>
## -------
## seqinfo: 23 sequences from hg38 genome; no seqlengths

1.5 Working with dbSNP Variants

One may also be interested in working with common germline variants with evidence of medical interest. This information is available at NCBI.

Query the dbDNP files in the hub:

This returns a VcfFile which can be read in using r Biocpkg("VariantAnnotation"); because VCF files can be large, readVcf() supports several strategies for importing only relevant parts of the file (e.g., particular genomic locations, particular features of the variants), see ?readVcf for additional information.

variants <- readVcf(vcf, genome="hg19")
variants
## class: CollapsedVCF 
## dim: 111138 0 
## rowRanges(vcf):
##   GRanges with 5 metadata columns: paramRangeID, REF, ALT, QUAL, FILTER
## info(vcf):
##   DataFrame with 58 columns: RS, RSPOS, RV, VP, GENEINFO, dbSNPBuildID, SAO, SSR, WGT, VC, PM, T...
## info(header(vcf)):
##                 Number Type    Description                                                         
##    RS           1      Integer dbSNP ID (i.e. rs number)                                           
##    RSPOS        1      Integer Chr position reported in dbSNP                                      
##    RV           0      Flag    RS orientation is reversed                                          
##    VP           1      String  Variation Property.  Documentation is at ftp://ftp.ncbi.nlm.nih.g...
##    GENEINFO     1      String  Pairs each of gene symbol:gene id.  The gene symbol and id are de...
##    dbSNPBuildID 1      Integer First dbSNP Build for RS                                            
##    SAO          1      Integer Variant Allele Origin: 0 - unspecified, 1 - Germline, 2 - Somatic...
##    SSR          1      Integer Variant Suspect Reason Codes (may be more than one value added to...
##    WGT          1      Integer Weight, 00 - unmapped, 1 - weight 1, 2 - weight 2, 3 - weight 3 o...
##    VC           1      String  Variation Class                                                     
##    PM           0      Flag    Variant is Precious(Clinical,Pubmed Cited)                          
##    TPA          0      Flag    Provisional Third Party Annotation(TPA) (currently rs from PHARMG...
##    PMC          0      Flag    Links exist to PubMed Central article                               
##    S3D          0      Flag    Has 3D structure - SNP3D table                                      
##    SLO          0      Flag    Has SubmitterLinkOut - From SNP->SubSNP->Batch.link_out             
##    NSF          0      Flag    Has non-synonymous frameshift A coding region variation where one...
##    NSM          0      Flag    Has non-synonymous missense A coding region variation where one a...
##    NSN          0      Flag    Has non-synonymous nonsense A coding region variation where one a...
##    REF          0      Flag    Has reference A coding region variation where one allele in the s...
##    SYN          0      Flag    Has synonymous A coding region variation where one allele in the ...
##    U3           0      Flag    In 3' UTR Location is in an untranslated region (UTR). FxnCode = 53 
##    U5           0      Flag    In 5' UTR Location is in an untranslated region (UTR). FxnCode = 55 
##    ASS          0      Flag    In acceptor splice site FxnCode = 73                                
##    DSS          0      Flag    In donor splice-site FxnCode = 75                                   
##    INT          0      Flag    In Intron FxnCode = 6                                               
##    R3           0      Flag    In 3' gene region FxnCode = 13                                      
##    R5           0      Flag    In 5' gene region FxnCode = 15                                      
##    OTH          0      Flag    Has other variant with exactly the same set of mapped positions o...
##    CFL          0      Flag    Has Assembly conflict. This is for weight 1 and 2 variant that ma...
##    ASP          0      Flag    Is Assembly specific. This is set if the variant only maps to one...
##    MUT          0      Flag    Is mutation (journal citation, explicit fact): a low frequency va...
##    VLD          0      Flag    Is Validated.  This bit is set if the variant has 2+ minor allele...
##    G5A          0      Flag    >5% minor allele frequency in each and all populations              
##    G5           0      Flag    >5% minor allele frequency in 1+ populations                        
##    HD           0      Flag    Marker is on high density genotyping kit (50K density or greater)...
##    GNO          0      Flag    Genotypes available. The variant has individual genotype (in SubI...
##    KGPhase1     0      Flag    1000 Genome phase 1 (incl. June Interim phase 1)                    
##    KGPhase3     0      Flag    1000 Genome phase 3                                                 
##    CDA          0      Flag    Variation is interrogated in a clinical diagnostic assay            
##    LSD          0      Flag    Submitted from a locus-specific database                            
##    MTP          0      Flag    Microattribution/third-party annotation(TPA:GWAS,PAGE)              
##    OM           0      Flag    Has OMIM/OMIA                                                       
##    NOC          0      Flag    Contig allele not present in variant allele list. The reference s...
##    WTD          0      Flag    Is Withdrawn by submitter If one member ss is withdrawn by submit...
##    NOV          0      Flag    Rs cluster has non-overlapping allele sets. True when rs set has ...
##    CAF          .      String  An ordered, comma delimited list of allele frequencies based on 1...
##    COMMON       1      Integer RS is a common SNP.  A common SNP is one that has at least one 10...
##    CLNHGVS      .      String  Variant names from HGVS.    The order of these variants correspon...
##    CLNALLE      .      Integer Variant alleles from REF or ALT columns.  0 is REF, 1 is the firs...
##    CLNSRC       .      String  Variant Clinical Chanels                                            
##    CLNORIGIN    .      String  Allele Origin. One or more of the following values may be added: ...
##    CLNSRCID     .      String  Variant Clinical Channel IDs                                        
##    CLNSIG       .      String  Variant Clinical Significance, 0 - Uncertain significance, 1 - no...
##    CLNDSDB      .      String  Variant disease database name                                       
##    CLNDSDBID    .      String  Variant disease database ID                                         
##    CLNDBN       .      String  Variant disease name                                                
##    CLNREVSTAT   .      String  no_assertion - No assertion provided, no_criteria - No assertion ...
##    CLNACC       .      String  Variant Accession and Versions                                      
## geno(vcf):
##   SimpleList of length 0:

rowRanges() returns information from the CHROM, POS and ID fields of the VCF file, represented as a GRanges instance

rowRanges(variants)
## GRanges object with 111138 ranges and 5 metadata columns:
##               seqnames             ranges strand | paramRangeID            REF                ALT
##                  <Rle>          <IRanges>  <Rle> |     <factor> <DNAStringSet> <DNAStringSetList>
##   rs786201005        1 [1014143, 1014143]      * |         <NA>              C                  T
##   rs672601345        1 [1014316, 1014316]      * |         <NA>              C                 CG
##   rs672601312        1 [1014359, 1014359]      * |         <NA>              G                  T
##   rs115173026        1 [1020217, 1020217]      * |         <NA>              G                  T
##   rs201073369        1 [1020239, 1020239]      * |         <NA>              G                  C
##           ...      ...                ...    ... .          ...            ...                ...
##   rs527236200       MT     [15943, 15943]      * |         <NA>              T                  C
##   rs118203890       MT     [15950, 15950]      * |         <NA>              G                  A
##   rs199474700       MT     [15965, 15965]      * |         <NA>              A                  G
##   rs199474701       MT     [15967, 15967]      * |         <NA>              G                  A
##   rs199474699       MT     [15990, 15990]      * |         <NA>              C                  T
##                    QUAL      FILTER
##               <numeric> <character>
##   rs786201005      <NA>           .
##   rs672601345      <NA>           .
##   rs672601312      <NA>           .
##   rs115173026      <NA>           .
##   rs201073369      <NA>           .
##           ...       ...         ...
##   rs527236200      <NA>           .
##   rs118203890      <NA>           .
##   rs199474700      <NA>           .
##   rs199474701      <NA>           .
##   rs199474699      <NA>           .
##   -------
##   seqinfo: 25 sequences from hg19 genome; no seqlengths

Note that the broadPeaks files follow the UCSC chromosome naming convention, and the vcf data follows the NCBI style of chromosome naming convention. To bring these ranges in the same chromosome naming convention (ie UCSC), we would use

seqlevelsStyle(variants) <-seqlevelsStyle(peaks)

And then finally to find which variants overlap these broadPeaks we would use:

overlap <- findOverlaps(variants, peaks)
overlap
## Hits object with 10904 hits and 0 metadata columns:
##           queryHits subjectHits
##           <integer>   <integer>
##       [1]        35       20333
##       [2]        36       20333
##       [3]        37       20333
##       [4]        38       20333
##       [5]        41        7733
##       ...       ...         ...
##   [10900]    110761       21565
##   [10901]    110762       21565
##   [10902]    110763       21565
##   [10903]    110764       21565
##   [10904]    110765       21565
##   -------
##   queryLength: 111138 / subjectLength: 153266

Some insight into how these results can be interpretted comes from looking a particular peak, e.g., the 3852nd peak

idx <- subjectHits(overlap) == 3852
overlap[idx]
## Hits object with 39 hits and 0 metadata columns:
##        queryHits subjectHits
##        <integer>   <integer>
##    [1]    102896        3852
##    [2]    102897        3852
##    [3]    102898        3852
##    [4]    102899        3852
##    [5]    102900        3852
##    ...       ...         ...
##   [35]    102930        3852
##   [36]    102931        3852
##   [37]    102932        3852
##   [38]    102933        3852
##   [39]    102934        3852
##   -------
##   queryLength: 111138 / subjectLength: 153266

There are three variants overlapping this peak; the coordinates of the peak and the overlapping variants are

peaks[3852]
## GRanges object with 1 range and 5 metadata columns:
##       seqnames               ranges strand |        name     score signalValue    pValue    qValue
##          <Rle>            <IRanges>  <Rle> | <character> <numeric>   <numeric> <numeric> <numeric>
##   [1]    chr22 [50622494, 50626143]      * |   Rank_3852        79     6.06768  10.18943   7.99818
##   -------
##   seqinfo: 93 sequences (1 circular) from hg19 genome
rowRanges(variants)[queryHits(overlap[idx])]
## GRanges object with 39 ranges and 5 metadata columns:
##               seqnames               ranges strand | paramRangeID            REF                ALT
##                  <Rle>            <IRanges>  <Rle> |     <factor> <DNAStringSet> <DNAStringSetList>
##     rs6151429    chr22 [50625049, 50625049]      * |         <NA>              T                  C
##     rs6151428    chr22 [50625182, 50625182]      * |         <NA>              C                A,T
##   rs774153480    chr22 [50625182, 50625182]      * |         <NA>              C           CG,CGGGG
##   rs199476388    chr22 [50625204, 50625204]      * |         <NA>              A                C,G
##    rs74315482    chr22 [50625213, 50625213]      * |         <NA>              G                  A
##           ...      ...                  ...    ... .          ...            ...                ...
##   rs199476369    chr22 [50625936, 50625936]      * |         <NA>              C                  G
##     rs2071421    chr22 [50625988, 50625988]      * |         <NA>              T                  C
##    rs74315475    chr22 [50626033, 50626033]      * |         <NA>              T                  A
##   rs398123419    chr22 [50626052, 50626052]      * |         <NA>              C                  A
##   rs398123418    chr22 [50626057, 50626057]      * |         <NA>              G                  A
##                    QUAL      FILTER
##               <numeric> <character>
##     rs6151429      <NA>           .
##     rs6151428      <NA>           .
##   rs774153480      <NA>           .
##   rs199476388      <NA>           .
##    rs74315482      <NA>           .
##           ...       ...         ...
##   rs199476369      <NA>           .
##     rs2071421      <NA>           .
##    rs74315475      <NA>           .
##   rs398123419      <NA>           .
##   rs398123418      <NA>           .
##   -------
##   seqinfo: 25 sequences from hg19 genome; no seqlengths

2 sessionInfo

sessionInfo()
## R version 3.4.2 (2017-09-28)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 16.04.3 LTS
## 
## Matrix products: default
## BLAS: /home/biocbuild/bbs-3.6-bioc/R/lib/libRblas.so
## LAPACK: /home/biocbuild/bbs-3.6-bioc/R/lib/libRlapack.so
## 
## locale:
##  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C               LC_TIME=en_US.UTF-8       
##  [4] LC_COLLATE=C               LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
##  [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                  LC_ADDRESS=C              
## [10] LC_TELEPHONE=C             LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       
## 
## attached base packages:
## [1] stats4    parallel  stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] BSgenome.Hsapiens.UCSC.hg19_1.4.0 BSgenome_1.46.0                  
##  [3] rtracklayer_1.38.0                VariantAnnotation_1.24.1         
##  [5] SummarizedExperiment_1.8.0        DelayedArray_0.4.1               
##  [7] matrixStats_0.52.2                Rsamtools_1.30.0                 
##  [9] Biostrings_2.46.0                 XVector_0.18.0                   
## [11] GenomicFeatures_1.30.0            AnnotationDbi_1.40.0             
## [13] Biobase_2.38.0                    GenomicRanges_1.30.0             
## [15] GenomeInfoDb_1.14.0               IRanges_2.12.0                   
## [17] S4Vectors_0.16.0                  AnnotationHub_2.10.1             
## [19] BiocGenerics_0.24.0               BiocStyle_2.6.0                  
## 
## loaded via a namespace (and not attached):
##  [1] progress_1.1.2                lattice_0.20-35               htmltools_0.3.6              
##  [4] yaml_2.1.14                   interactiveDisplayBase_1.16.0 blob_1.1.0                   
##  [7] XML_3.98-1.9                  rlang_0.1.4                   DBI_0.7                      
## [10] BiocParallel_1.12.0           bit64_0.9-7                   GenomeInfoDbData_0.99.1      
## [13] stringr_1.2.0                 zlibbioc_1.24.0               memoise_1.1.0                
## [16] evaluate_0.10.1               knitr_1.17                    biomaRt_2.34.0               
## [19] httpuv_1.3.5                  BiocInstaller_1.28.0          curl_3.0                     
## [22] Rcpp_0.12.13                  xtable_1.8-2                  backports_1.1.1              
## [25] mime_0.5                      bit_1.1-12                    RMySQL_0.10.13               
## [28] digest_0.6.12                 stringi_1.1.5                 bookdown_0.5                 
## [31] shiny_1.0.5                   grid_3.4.2                    rprojroot_1.2                
## [34] tools_3.4.2                   bitops_1.0-6                  magrittr_1.5                 
## [37] RCurl_1.95-4.8                tibble_1.3.4                  RSQLite_2.0                  
## [40] pkgconfig_2.0.1               Matrix_1.2-11                 prettyunits_1.0.2            
## [43] assertthat_0.2.0              rmarkdown_1.6                 httr_1.3.1                   
## [46] R6_2.2.2                      GenomicAlignments_1.14.0      compiler_3.4.2
AnnotationHub/inst/doc/AnnotationHub.R0000644000175400017540000000446313200446556021003 0ustar00biocbuildbiocbuild## ----style, echo = FALSE, results = 'asis'--------------------------------- BiocStyle::markdown() ## ----library, message=FALSE------------------------------------------------ library(AnnotationHub) ## ----AnnotationHub--------------------------------------------------------- ah = AnnotationHub() ## ----show------------------------------------------------------------------ ah ## ----dataprovider---------------------------------------------------------- unique(ah$dataprovider) ## ----species--------------------------------------------------------------- head(unique(ah$species)) ## ----rdataclass------------------------------------------------------------ head(unique(ah$rdataclass)) ## ----dm1------------------------------------------------------------------- dm <- query(ah, c("ChainFile", "UCSC", "Drosophila melanogaster")) dm ## ----show2----------------------------------------------------------------- df <- mcols(dm) ## ----length---------------------------------------------------------------- length(ah) ## ----subset---------------------------------------------------------------- ahs <- query(ah, c('inparanoid8', 'ailuropoda')) ahs ## ----display, eval=FALSE--------------------------------------------------- # d <- display(ah) ## ----dm2------------------------------------------------------------------- dm dm["AH15146"] ## ----dm3------------------------------------------------------------------- dm[["AH15146"]] ## ----show-2---------------------------------------------------------------- ah ## ----snapshot-------------------------------------------------------------- snapshotDate(ah) ## ----possibleDates--------------------------------------------------------- pd <- possibleDates(ah) pd ## ----setdate, eval=FALSE--------------------------------------------------- # snapshotDate(ah) <- pd[1] ## ----clusterOptions1, eval=FALSE------------------------------------------- # library(AnnotationHub) # hub <- AnnotationHub() # gr <- hub[["AH50773"]] ## downloaded once # txdb <- makeTxDbFromGRanges(gr) ## build on the fly ## ----clusterOptions2, eval=FALSE------------------------------------------- # library(AnnotationDbi) ## if not already loaded # txdb <- loadDb("/locationToFile/mytxdb.sqlite") ## ----sessionInfo----------------------------------------------------------- sessionInfo() AnnotationHub/inst/doc/AnnotationHub.Rmd0000644000175400017540000002063613175714307021327 0ustar00biocbuildbiocbuild--- title: "AnnotationHub: Access the AnnotationHub Web Service" output: BiocStyle::html_document: toc: true vignette: > % \VignetteIndexEntry{AnnotationHub: Access the AnnotationHub Web Service} % \VignetteDepends{AnnotationHub} % \VignetteEngine{knitr::rmarkdown} % \VignetteEncoding{UTF-8} --- ```{r style, echo = FALSE, results = 'asis'} BiocStyle::markdown() ``` **Package**: `r Biocpkg("AnnotationHub")`
**Authors**: `r packageDescription("AnnotationHub")[["Author"]] `
**Modified**: 27 May, 2016
**Compiled**: `r date()` The `AnnotationHub` server provides easy _R / Bioconductor_ access to large collections of publicly available whole genome resources, e.g,. ENSEMBL genome fasta or gtf files, UCSC chain resources, ENCODE data tracks at UCSC, etc. # AnnotationHub objects The `r Biocpkg("AnnotationHub")` package provides a client interface to resources stored at the AnnotationHub web service. ```{r library, message=FALSE} library(AnnotationHub) ``` The `r Biocpkg("AnnotationHub")` package is straightforward to use. Create an `AnnotationHub` object ```{r AnnotationHub} ah = AnnotationHub() ``` Now at this point you have already done everything you need in order to start retrieving annotations. For most operations, using the `AnnotationHub` object should feel a lot like working with a familiar `list` or `data.frame`. Lets take a minute to look at the show method for the hub object ah ```{r show} ah ``` You can see that it gives you an idea about the different types of data that are present inside the hub. You can see where the data is coming from (dataprovider), as well as what species have samples present (species), what kinds of R data objects could be returned (rdataclass). We can take a closer look at all the kinds of data providers that are available by simply looking at the contents of dataprovider as if it were the column of a data.frame object like this: ```{r dataprovider} unique(ah$dataprovider) ``` In the same way, you can also see data from different species inside the hub by looking at the contents of species like this: ```{r species} head(unique(ah$species)) ``` And this will also work for any of the other types of metadata present. You can learn which kinds of metadata are available by simply hitting the tab key after you type 'ah$'. In this way you can explore for yourself what kinds of data are present in the hub right from the command line. This interface also allows you to access the hub programatically to extract data that matches a particular set of criteria. Another valuable types of metadata to pay attention to is the rdataclass. ```{r rdataclass} head(unique(ah$rdataclass)) ``` The rdataclass allows you to see which kinds of R objects the hub will return to you. This kind of information is valuable both as a means to filter results and also as a means to explore and learn about some of the kinds of annotation objects that are widely available for the project. Right now this is a pretty short list, but over time it should grow as we support more of the different kinds of annotation objects via the hub. Now lets try getting the Chain Files from UCSC using the query and subset methods to selectively pare down the hub based on specific criteria. The query method lets you search rows for specific strings, returning an `AnnotationHub` instance with just the rows matching the query. From the show method, one can easily see that one of the dataprovider is UCSC and there is a rdataclass for ChainFile One can get chain files for Drosophila melanogaster from UCSC with: ```{r dm1} dm <- query(ah, c("ChainFile", "UCSC", "Drosophila melanogaster")) dm ``` Query has worked and you can now see that the only species present is Drosophila melanogaster. The metadata underlying this hub object can be retrieved by you ```{r show2} df <- mcols(dm) ``` By default the show method will only display the first 5 and last 5 rows. There are already thousands of records present in the hub. ```{r length} length(ah) ``` Lets look at another example, where we pull down only Inparanoid8 data from the hub and use subset to return a smaller base object (here we are finding cases where the genome column is set to panda). ```{r subset} ahs <- query(ah, c('inparanoid8', 'ailuropoda')) ahs ``` We can also look at the `AnnotationHub` object in a browser using the `display()` function. We can then filter the `AnnotationHub` object for _chainFile__ by either using the Global search field on the top right corner of the page or the in-column search field for `rdataclass'. ```{r display, eval=FALSE} d <- display(ah) ``` ![](display.png) Displaying and filtering the Annotation Hub object in a browser By default 1000 entries are displayed per page, we can change this using the filter on the top of the page or navigate through different pages using the page scrolling feature at the bottom of the page. We can also select the rows of interest to us and send them back to the R session using 'Return rows to R session' button ; this sets a filter internally which filters the `AnnotationHub` object. The names of the selected AnnotationHub elements displayed at the top of the page. # Using `AnnotationHub` to retrieve data Looking back at our chain file example, if we are interested in the file dm1ToDm2.over.chain.gz, we can gets its metadata using ```{r dm2} dm dm["AH15146"] ``` We can download the file using ```{r dm3} dm[["AH15146"]] ``` Each file is retrieved from the AnnotationHub server and the file is also cache locally, so that the next time you need to retrieve it, it should download much more quickly. # Configuring `AnnotationHub` objects When you create the `AnnotationHub` object, it will set up the object for you with some default settings. See `?AnnotationHub` for ways to customize the hub source, the local cache, and other instance-specific options, and `?getAnnotationHubOption` to get or set package-global options for use across sessions. If you look at the object you will see some helpful information about it such as where the data is cached and where online the hub server is set to. ```{r show-2} ah ``` By default the `AnnotationHub` object is set to the latest `snapshotData` and a snapshot version that matches the version of _Bioconductor_ that you are using. You can also learn about these data with the appropriate methods. ```{r snapshot} snapshotDate(ah) ``` If you are interested in using an older version of a snapshot, you can list previous versions with the `possibleDates()` like this: ```{r possibleDates} pd <- possibleDates(ah) pd ``` Set the dates like this: ```{r setdate, eval=FALSE} snapshotDate(ah) <- pd[1] ``` # AnnotationHub objects in a cluster environment Resources in AnnotationHub aren't loaded with the standard `R` package approach and therefore can't be loaded on cluster nodes with library(). There are a couple of options to sharing AnnotationHub objects across a cluster when researchers are using the same R install and want access to the same annotations. As an example, we create a TxDb object from a GRanges stored in AnnotationHub contributed by contributed by Timothée Flutre. The GRanges was created from a GFF file and contains gene information for Vitis vinifera. * Download once and build on the fly One option is that each user downloads the resource with hub[["AH50773"]] and the GRanges is saved in the cache. Each subsequent call to hub[["AH50773"]] retrieves the resource from the cache which is very fast. The necessary code extracts the resource then calls makeTxDbFromGRanges(). ```{r clusterOptions1, eval=FALSE} library(AnnotationHub) hub <- AnnotationHub() gr <- hub[["AH50773"]] ## downloaded once txdb <- makeTxDbFromGRanges(gr) ## build on the fly ``` * Build once and share Another approach is that one user builds the TxDb and saves it as a .sqlite file. The cluster admin installs this in a common place on all cluster nodes and each user can load it with loadDb(). Loading the file is as quick and easy as calling library() on a TxDb package. Once the .sqlite file is install each user's code would include: ```{r clusterOptions2, eval=FALSE} library(AnnotationDbi) ## if not already loaded txdb <- loadDb("/locationToFile/mytxdb.sqlite") ``` # Session info ```{r sessionInfo} sessionInfo() ``` AnnotationHub/inst/doc/AnnotationHub.html0000644000175400017540000354622513200446557021561 0ustar00biocbuildbiocbuild AnnotationHub: Access the AnnotationHub Web Service

Contents

Package: AnnotationHub
Authors: Martin Morgan [cre], Marc Carlson [ctb], Dan Tenenbaum [ctb], Sonali Arora [ctb]
Modified: 27 May, 2016
Compiled: Tue Nov 7 19:18:46 2017

The AnnotationHub server provides easy R / Bioconductor access to large collections of publicly available whole genome resources, e.g,. ENSEMBL genome fasta or gtf files, UCSC chain resources, ENCODE data tracks at UCSC, etc.

1 AnnotationHub objects

The AnnotationHub package provides a client interface to resources stored at the AnnotationHub web service.

library(AnnotationHub)

The AnnotationHub package is straightforward to use. Create an AnnotationHub object

ah = AnnotationHub()
## snapshotDate(): 2017-10-27

Now at this point you have already done everything you need in order to start retrieving annotations. For most operations, using the AnnotationHub object should feel a lot like working with a familiar list or data.frame.

Lets take a minute to look at the show method for the hub object ah

ah
## AnnotationHub with 42282 records
## # snapshotDate(): 2017-10-27 
## # $dataprovider: BroadInstitute, Ensembl, UCSC, ftp://ftp.ncbi.nlm.nih.go...
## # $species: Homo sapiens, Mus musculus, Drosophila melanogaster, Bos taur...
## # $rdataclass: GRanges, BigWigFile, FaFile, TwoBitFile, Rle, ChainFile, O...
## # additional mcols(): taxonomyid, genome, description,
## #   coordinate_1_based, maintainer, rdatadateadded, preparerclass,
## #   tags, rdatapath, sourceurl, sourcetype 
## # retrieve records with, e.g., 'object[["AH2"]]' 
## 
##             title                                                           
##   AH2     | Ailuropoda_melanoleuca.ailMel1.69.dna.toplevel.fa               
##   AH3     | Ailuropoda_melanoleuca.ailMel1.69.dna_rm.toplevel.fa            
##   AH4     | Ailuropoda_melanoleuca.ailMel1.69.dna_sm.toplevel.fa            
##   AH5     | Ailuropoda_melanoleuca.ailMel1.69.ncrna.fa                      
##   AH6     | Ailuropoda_melanoleuca.ailMel1.69.pep.all.fa                    
##   ...       ...                                                             
##   AH58988 | org.Flavobacterium_piscicida.eg.sqlite                          
##   AH58989 | org.Bacteroides_fragilis_YCH46.eg.sqlite                        
##   AH58990 | org.Pseudomonas_mendocina_ymp.eg.sqlite                         
##   AH58991 | org.Salmonella_enterica_subsp._enterica_serovar_Typhimurium_s...
##   AH58992 | org.Acinetobacter_baumannii.eg.sqlite

You can see that it gives you an idea about the different types of data that are present inside the hub. You can see where the data is coming from (dataprovider), as well as what species have samples present (species), what kinds of R data objects could be returned (rdataclass). We can take a closer look at all the kinds of data providers that are available by simply looking at the contents of dataprovider as if it were the column of a data.frame object like this:

unique(ah$dataprovider)
##  [1] "Ensembl"                              
##  [2] "UCSC"                                 
##  [3] "RefNet"                               
##  [4] "Inparanoid8"                          
##  [5] "NHLBI"                                
##  [6] "ChEA"                                 
##  [7] "Pazar"                                
##  [8] "NIH Pathway Interaction Database"     
##  [9] "Haemcode"                             
## [10] "BroadInstitute"                       
## [11] "PRIDE"                                
## [12] "Gencode"                              
## [13] "CRIBI"                                
## [14] "Genoscope"                            
## [15] "MISO, VAST-TOOLS, UCSC"               
## [16] "UWashington"                          
## [17] "Stanford"                             
## [18] "dbSNP"                                
## [19] "ftp://ftp.ncbi.nlm.nih.gov/gene/DATA/"

In the same way, you can also see data from different species inside the hub by looking at the contents of species like this:

head(unique(ah$species))
## [1] "Ailuropoda melanoleuca" "Anolis carolinensis"   
## [3] "Bos taurus"             "Caenorhabditis elegans"
## [5] "Callithrix jacchus"     "Canis familiaris"

And this will also work for any of the other types of metadata present. You can learn which kinds of metadata are available by simply hitting the tab key after you type ‘ah$’. In this way you can explore for yourself what kinds of data are present in the hub right from the command line. This interface also allows you to access the hub programatically to extract data that matches a particular set of criteria.

Another valuable types of metadata to pay attention to is the rdataclass.

head(unique(ah$rdataclass))
## [1] "FaFile"        "GRanges"       "data.frame"    "Inparanoid8Db"
## [5] "TwoBitFile"    "ChainFile"

The rdataclass allows you to see which kinds of R objects the hub will return to you. This kind of information is valuable both as a means to filter results and also as a means to explore and learn about some of the kinds of annotation objects that are widely available for the project. Right now this is a pretty short list, but over time it should grow as we support more of the different kinds of annotation objects via the hub.

Now lets try getting the Chain Files from UCSC using the query and subset methods to selectively pare down the hub based on specific criteria. The query method lets you search rows for specific strings, returning an AnnotationHub instance with just the rows matching the query.

From the show method, one can easily see that one of the dataprovider is UCSC and there is a rdataclass for ChainFile

One can get chain files for Drosophila melanogaster from UCSC with:

dm <- query(ah, c("ChainFile", "UCSC", "Drosophila melanogaster"))
dm
## AnnotationHub with 45 records
## # snapshotDate(): 2017-10-27 
## # $dataprovider: UCSC
## # $species: Drosophila melanogaster
## # $rdataclass: ChainFile
## # additional mcols(): taxonomyid, genome, description,
## #   coordinate_1_based, maintainer, rdatadateadded, preparerclass,
## #   tags, rdatapath, sourceurl, sourcetype 
## # retrieve records with, e.g., 'object[["AH15102"]]' 
## 
##             title                     
##   AH15102 | dm3ToAnoGam1.over.chain.gz
##   AH15103 | dm3ToApiMel3.over.chain.gz
##   AH15104 | dm3ToDm2.over.chain.gz    
##   AH15105 | dm3ToDm6.over.chain.gz    
##   AH15106 | dm3ToDp3.over.chain.gz    
##   ...       ...                       
##   AH15142 | dm2ToDroVir3.over.chain.gz
##   AH15143 | dm2ToDroWil1.over.chain.gz
##   AH15144 | dm2ToDroYak1.over.chain.gz
##   AH15145 | dm2ToDroYak2.over.chain.gz
##   AH15146 | dm1ToDm2.over.chain.gz

Query has worked and you can now see that the only species present is Drosophila melanogaster.

The metadata underlying this hub object can be retrieved by you

df <- mcols(dm)

By default the show method will only display the first 5 and last 5 rows. There are already thousands of records present in the hub.

length(ah)
## [1] 42282

Lets look at another example, where we pull down only Inparanoid8 data from the hub and use subset to return a smaller base object (here we are finding cases where the genome column is set to panda).

ahs <- query(ah, c('inparanoid8', 'ailuropoda'))
ahs
## AnnotationHub with 1 record
## # snapshotDate(): 2017-10-27 
## # names(): AH10451
## # $dataprovider: Inparanoid8
## # $species: Ailuropoda melanoleuca
## # $rdataclass: Inparanoid8Db
## # $rdatadateadded: 2014-03-31
## # $title: hom.Ailuropoda_melanoleuca.inp8.sqlite
## # $description: Inparanoid 8 annotations about Ailuropoda melanoleuca
## # $taxonomyid: 9646
## # $genome: inparanoid8 genomes
## # $sourcetype: Inparanoid
## # $sourceurl: http://inparanoid.sbc.su.se/download/current/Orthologs/A.me...
## # $sourcesize: NA
## # $tags: c("Inparanoid", "Gene", "Homology", "Annotation") 
## # retrieve record with 'object[["AH10451"]]'

We can also look at the AnnotationHub object in a browser using the display() function. We can then filter the AnnotationHub object for _chainFile__ by either using the Global search field on the top right corner of the page or the in-column search field for `rdataclass’.

d <- display(ah)

Displaying and filtering the Annotation Hub object in a browser

By default 1000 entries are displayed per page, we can change this using the filter on the top of the page or navigate through different pages using the page scrolling feature at the bottom of the page.

We can also select the rows of interest to us and send them back to the R session using ‘Return rows to R session’ button ; this sets a filter internally which filters the AnnotationHub object. The names of the selected AnnotationHub elements displayed at the top of the page.

2 Using AnnotationHub to retrieve data

Looking back at our chain file example, if we are interested in the file dm1ToDm2.over.chain.gz, we can gets its metadata using

dm
## AnnotationHub with 45 records
## # snapshotDate(): 2017-10-27 
## # $dataprovider: UCSC
## # $species: Drosophila melanogaster
## # $rdataclass: ChainFile
## # additional mcols(): taxonomyid, genome, description,
## #   coordinate_1_based, maintainer, rdatadateadded, preparerclass,
## #   tags, rdatapath, sourceurl, sourcetype 
## # retrieve records with, e.g., 'object[["AH15102"]]' 
## 
##             title                     
##   AH15102 | dm3ToAnoGam1.over.chain.gz
##   AH15103 | dm3ToApiMel3.over.chain.gz
##   AH15104 | dm3ToDm2.over.chain.gz    
##   AH15105 | dm3ToDm6.over.chain.gz    
##   AH15106 | dm3ToDp3.over.chain.gz    
##   ...       ...                       
##   AH15142 | dm2ToDroVir3.over.chain.gz
##   AH15143 | dm2ToDroWil1.over.chain.gz
##   AH15144 | dm2ToDroYak1.over.chain.gz
##   AH15145 | dm2ToDroYak2.over.chain.gz
##   AH15146 | dm1ToDm2.over.chain.gz
dm["AH15146"]
## AnnotationHub with 1 record
## # snapshotDate(): 2017-10-27 
## # names(): AH15146
## # $dataprovider: UCSC
## # $species: Drosophila melanogaster
## # $rdataclass: ChainFile
## # $rdatadateadded: 2014-12-15
## # $title: dm1ToDm2.over.chain.gz
## # $description: UCSC liftOver chain file from dm1 to dm2
## # $taxonomyid: 7227
## # $genome: dm1
## # $sourcetype: Chain
## # $sourceurl: http://hgdownload.cse.ucsc.edu/goldenpath/dm1/liftOver/dm1T...
## # $sourcesize: NA
## # $tags: c("liftOver", "chain", "UCSC", "genome", "homology") 
## # retrieve record with 'object[["AH15146"]]'

We can download the file using

dm[["AH15146"]]
## loading from cache '/home/biocbuild//.AnnotationHub/19241'
## Chain of length 11
## names(11): chr2L chr2R chr3L chr3R chr4 chrX chrU chr2h chr3h chrXh chrYh

Each file is retrieved from the AnnotationHub server and the file is also cache locally, so that the next time you need to retrieve it, it should download much more quickly.

3 Configuring AnnotationHub objects

When you create the AnnotationHub object, it will set up the object for you with some default settings. See ?AnnotationHub for ways to customize the hub source, the local cache, and other instance-specific options, and ?getAnnotationHubOption to get or set package-global options for use across sessions.

If you look at the object you will see some helpful information about it such as where the data is cached and where online the hub server is set to.

ah
## AnnotationHub with 42282 records
## # snapshotDate(): 2017-10-27 
## # $dataprovider: BroadInstitute, Ensembl, UCSC, ftp://ftp.ncbi.nlm.nih.go...
## # $species: Homo sapiens, Mus musculus, Drosophila melanogaster, Bos taur...
## # $rdataclass: GRanges, BigWigFile, FaFile, TwoBitFile, Rle, ChainFile, O...
## # additional mcols(): taxonomyid, genome, description,
## #   coordinate_1_based, maintainer, rdatadateadded, preparerclass,
## #   tags, rdatapath, sourceurl, sourcetype 
## # retrieve records with, e.g., 'object[["AH2"]]' 
## 
##             title                                                           
##   AH2     | Ailuropoda_melanoleuca.ailMel1.69.dna.toplevel.fa               
##   AH3     | Ailuropoda_melanoleuca.ailMel1.69.dna_rm.toplevel.fa            
##   AH4     | Ailuropoda_melanoleuca.ailMel1.69.dna_sm.toplevel.fa            
##   AH5     | Ailuropoda_melanoleuca.ailMel1.69.ncrna.fa                      
##   AH6     | Ailuropoda_melanoleuca.ailMel1.69.pep.all.fa                    
##   ...       ...                                                             
##   AH58988 | org.Flavobacterium_piscicida.eg.sqlite                          
##   AH58989 | org.Bacteroides_fragilis_YCH46.eg.sqlite                        
##   AH58990 | org.Pseudomonas_mendocina_ymp.eg.sqlite                         
##   AH58991 | org.Salmonella_enterica_subsp._enterica_serovar_Typhimurium_s...
##   AH58992 | org.Acinetobacter_baumannii.eg.sqlite

By default the AnnotationHub object is set to the latest snapshotData and a snapshot version that matches the version of Bioconductor that you are using. You can also learn about these data with the appropriate methods.

snapshotDate(ah)
## [1] "2017-10-27"

If you are interested in using an older version of a snapshot, you can list previous versions with the possibleDates() like this:

pd <- possibleDates(ah)
pd
##  [1] "2013-03-19" "2013-03-21" "2013-03-26" "2013-04-04" "2013-04-29"
##  [6] "2013-06-24" "2013-06-25" "2013-06-26" "2013-06-27" "2013-10-29"
## [11] "2013-11-20" "2013-12-19" "2014-02-12" "2014-02-13" "2014-03-31"
## [16] "2014-04-27" "2014-05-11" "2014-05-13" "2014-05-14" "2014-05-22"
## [21] "2014-07-02" "2014-07-09" "2014-12-15" "2014-12-24" "2015-01-08"
## [26] "2015-01-14" "2015-03-09" "2015-03-11" "2015-03-12" "2015-03-25"
## [31] "2015-03-26" "2015-05-06" "2015-05-07" "2015-05-08" "2015-05-11"
## [36] "2015-05-14" "2015-05-21" "2015-05-22" "2015-05-26" "2015-07-17"
## [41] "2015-07-27" "2015-07-31" "2015-08-10" "2015-08-13" "2015-08-14"
## [46] "2015-08-17" "2015-08-26" "2015-12-28" "2015-12-29" "2016-01-25"
## [51] "2016-03-07" "2016-05-03" "2016-05-25" "2016-06-06" "2016-07-20"
## [56] "2016-08-15" "2016-10-11" "2016-11-03" "2016-11-08" "2016-11-09"
## [61] "2016-11-13" "2016-11-14" "2016-12-22" "2016-12-28" "2017-01-05"
## [66] "2017-02-07" "2017-04-03" "2017-04-04" "2017-04-05" "2017-04-10"
## [71] "2017-04-11" "2017-04-13" "2017-04-24" "2017-04-25" "2017-05-31"
## [76] "2017-06-06" "2017-06-07" "2017-06-08" "2017-06-29" "2017-07-11"
## [81] "2017-08-28" "2017-08-31" "2017-09-07" "2017-10-18" "2017-10-23"
## [86] "2017-10-24" "2017-10-27" "2017-10-27"

Set the dates like this:

snapshotDate(ah) <- pd[1]

4 AnnotationHub objects in a cluster environment

Resources in AnnotationHub aren’t loaded with the standard R package approach and therefore can’t be loaded on cluster nodes with library(). There are a couple of options to sharing AnnotationHub objects across a cluster when researchers are using the same R install and want access to the same annotations.

As an example, we create a TxDb object from a GRanges stored in AnnotationHub contributed by contributed by Timothée Flutre. The GRanges was created from a GFF file and contains gene information for Vitis vinifera.

  • Download once and build on the fly

One option is that each user downloads the resource with hub[[“AH50773”]] and the GRanges is saved in the cache. Each subsequent call to hub[[“AH50773”]] retrieves the resource from the cache which is very fast.

The necessary code extracts the resource then calls makeTxDbFromGRanges().

library(AnnotationHub)
hub <- AnnotationHub()
gr <- hub[["AH50773"]]  ## downloaded once
txdb <- makeTxDbFromGRanges(gr)  ## build on the fly
  • Build once and share

Another approach is that one user builds the TxDb and saves it as a .sqlite file. The cluster admin installs this in a common place on all cluster nodes and each user can load it with loadDb(). Loading the file is as quick and easy as calling library() on a TxDb package.

Once the .sqlite file is install each user’s code would include:

library(AnnotationDbi)  ## if not already loaded
txdb <- loadDb("/locationToFile/mytxdb.sqlite")

5 Session info

sessionInfo()
## R version 3.4.2 (2017-09-28)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 16.04.3 LTS
## 
## Matrix products: default
## BLAS: /home/biocbuild/bbs-3.6-bioc/R/lib/libRblas.so
## LAPACK: /home/biocbuild/bbs-3.6-bioc/R/lib/libRlapack.so
## 
## locale:
##  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=en_US.UTF-8        LC_COLLATE=C              
##  [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
##  [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       
## 
## attached base packages:
## [1] stats4    parallel  stats     graphics  grDevices utils     datasets 
## [8] methods   base     
## 
## other attached packages:
##  [1] BSgenome.Hsapiens.UCSC.hg19_1.4.0 BSgenome_1.46.0                  
##  [3] rtracklayer_1.38.0                VariantAnnotation_1.24.1         
##  [5] SummarizedExperiment_1.8.0        DelayedArray_0.4.1               
##  [7] matrixStats_0.52.2                Rsamtools_1.30.0                 
##  [9] Biostrings_2.46.0                 XVector_0.18.0                   
## [11] GenomicFeatures_1.30.0            AnnotationDbi_1.40.0             
## [13] Biobase_2.38.0                    GenomicRanges_1.30.0             
## [15] GenomeInfoDb_1.14.0               IRanges_2.12.0                   
## [17] S4Vectors_0.16.0                  AnnotationHub_2.10.1             
## [19] BiocGenerics_0.24.0               BiocStyle_2.6.0                  
## 
## loaded via a namespace (and not attached):
##  [1] progress_1.1.2                lattice_0.20-35              
##  [3] htmltools_0.3.6               yaml_2.1.14                  
##  [5] interactiveDisplayBase_1.16.0 blob_1.1.0                   
##  [7] XML_3.98-1.9                  rlang_0.1.4                  
##  [9] DBI_0.7                       BiocParallel_1.12.0          
## [11] bit64_0.9-7                   GenomeInfoDbData_0.99.1      
## [13] stringr_1.2.0                 zlibbioc_1.24.0              
## [15] memoise_1.1.0                 evaluate_0.10.1              
## [17] knitr_1.17                    biomaRt_2.34.0               
## [19] httpuv_1.3.5                  BiocInstaller_1.28.0         
## [21] curl_3.0                      Rcpp_0.12.13                 
## [23] xtable_1.8-2                  backports_1.1.1              
## [25] mime_0.5                      bit_1.1-12                   
## [27] RMySQL_0.10.13                digest_0.6.12                
## [29] stringi_1.1.5                 bookdown_0.5                 
## [31] shiny_1.0.5                   grid_3.4.2                   
## [33] rprojroot_1.2                 tools_3.4.2                  
## [35] bitops_1.0-6                  magrittr_1.5                 
## [37] RCurl_1.95-4.8                tibble_1.3.4                 
## [39] RSQLite_2.0                   pkgconfig_2.0.1              
## [41] Matrix_1.2-11                 prettyunits_1.0.2            
## [43] assertthat_0.2.0              rmarkdown_1.6                
## [45] httr_1.3.1                    R6_2.2.2                     
## [47] GenomicAlignments_1.14.0      compiler_3.4.2
AnnotationHub/inst/doc/CreateAnAnnotationPackage.R0000644000175400017540000000173613200446557023224 0ustar00biocbuildbiocbuild## ---- TxDb_Metadata, eval=FALSE-------------------------------------------- # metadata <- AnnotationHubMetadata( # Description="Gene Annotation for Vitis vinifera", # Genome="IGGP12Xv0", # Species="Vitis vinifera", # SourceUrl="http://genomes.cribi.unipd.it/DATA/V2/V2.1/V2.1.gff3", # SourceLastModifiedDate=as.POSIXct("2014-04-17"), # SourceVersion="2.1", # RDataPath="community/tflutre/", # TaxonomyId=29760L, # Title="Vvinifera_CRIBI_IGGP12Xv0_V2.1.gff3.Rdata", # BiocVersion=package_version("3.3"), # Coordinate_1_based=TRUE, # DataProvider="CRIBI", # Maintainer="Timothée Flutre % \VignetteIndexEntry{AnnotationHub: Creating An AnnotationHub Package} % \VignetteEngine{knitr::rmarkdown} % \VignetteEncoding{UTF-8} --- # Overview The `AnnotationHubData` package provides tools to acquire, annotate, convert and store data for use in Bioconductor's `AnnotationHub`. BED files from the Encode project, gtf files from Ensembl, or annotation tracks from UCSC, are examples of data that can be downloaded, described with metadata, transformed to standard `Bioconductor` data types, and stored so that they may be conveniently served up on demand to users via the AnnotationHub client. While data are often manipulated into a more R-friendly form, the data themselves retain their raw content and are not filtered or curated like those in [ExperimentHub](http://bioconductor.org/packages/ExperimentHub/). Each resource has associated metadata that can be searched through the `AnnotationHub` client interface. # New resources ## Family of resources Multiple, related resources are added to `AnnotationHub` by creating a software package similar to the existing annotation packages. The package itself does not contain data but serves as a light weight wrapper around scripts that generate metadata for the resources added to `AnnotationHub`. At a minimum the package should contain a man page describing the resources. Vignettes and additional `R` code for manipulating the objects are optional. Creating the package involves the following steps: 1. Notify `Bioconductor` team member: Man page and vignette examples in the software package will not work until the data are available in `AnnotationHub`. Adding the data to AWS S3 and the metadata to the production database involves assistance from a `Bioconductor` team member. Please read the section "Uploading Data to S3". 2. Building the software package: Below is an outline of package organization. The files listed are required unless otherwise stated. * inst/extdata/ - metadata.csv: This file contains the metadata in the format of one row per resource to be added to the `AnnotationHub` database. The file should be generated from the code in inst/scripts/make-metadata.R where the final data are written out with write.csv(..., row.names=FALSE). The required column names and data types are specified in `AnnotationHub::readMetadataFromCsv()`. See ?`readMetadataFromCsv` for details. If necessary, metadata can be broken up into multiple csv files instead having of all records in a single "metadata.csv". * inst/scripts/ - make-data.R: A script describing the steps involved in making the data object(s). This includes where the original data were downloaded from, pre-processing, and how the final R object was made. Include a description of any steps performed outside of `R` with third party software. Output of the script should be files on disk ready to be pushed to S3. If data are to be hosted on a personal web site instead of S3, this file should explain any manipulation of the data prior to hosting on the web site. For data hosted on a public web site with no prior manipultaion this file is not needed. - make-metadata.R: A script to make the metadata.csv file located in inst/extdata of the package. See ?`readMetadataFromCsv` for a description of the metadata.csv file, expected fields and data types. The `readMetadataFromCsv()` function can be used to validate the metadata.csv file before submitting the package. * vignettes/ OPTIONAL vignette(s) describing analysis workflows. * R/ OPTIONAL functions to enhance data exploration. * man/ - package man page: OPTIONAL. The package man page serves as a landing point and should briefly describe all resources associated with the package. There should be an \alias entry for each resource title either on the package man page or individual man pages. - resource man pages: OPTIONAL. Man page(s) should describe the resource (raw data source, processing, QC steps) and demonstrate how the data can be loaded through the `AnnotationHub` interface. For example, replace "SEARCHTERM*" below with one or more search terms that uniquely identify resources in your package. ``` library(AnnotationHub) hub <- AnnotationHub() myfiles <- query(hub, "SEARCHTERM1", "SEARCHTERM2") myfiles[[1]] ## load the first resource in the list ``` * DESCRIPTION / NAMESPACE The scripts used to generate the metadata will likely use functions from AnnotationHub or AnnotationHubData which should be listed in Depends/Imports as necessary. 3. Data objects: Data are not formally part of the software package and are stored separately in AWS S3 buckets. The author should follow instructions in the section "Uploading Data to S3" 4. Confirm valid metadata: Confirm the data in inst/exdata/metadata.csv are valid by running AnnotationHubData:::makeAnnotationHubMetadata() on your package. Please address and warnings or errors. 5. Package review: Submit the package to the [tracker](https://github.com/Bioconductor/Contributions) for review. The primary purpose of the package review is to validate the metadata in the csv file(s). It is ok if the package fails R CMD build and check because the data and metadata are not yet in place. Once the metadata.csv is approved, records are added to the production database. At that point the package man pages and vignette can be finalized and the package should pass R CMD build and check. ## Individual resources Individual objects of a standard class can be added to the hub by providing only the data and metadata files or by creating a package as described in the `Family of Resources` section. OrgDb, TxDb and BSgenome objects are well defined `Bioconductor` classes and methods to download and process these objects already exist in `AnnotationHub`. When adding only one or two objects the overhead of creating a package may be unnecessary. The goal of the package is to provide structure for metadata generation and makes sense when there are plans to update versions or add new organisms in the future. Make sure the OrgDb, TxDb or BSgenome object you want to add does not already exist in the [Biocondcutor annotation repository](http://www.bioconductor.org/packages/release/BiocViews.html#___AnnotationData) Providing just data and metadata files involves the following steps: 1. Notify `Bioconductor` team member: Adding the data to AWS S3 and the metadata to the production database involves assistance from a `Bioconductor` team member. Please read the section "Uploading Data to S3". 2. Prepare the data: In the case of an OrgDb object, only the sqlite file is stored in S3. See makeOrgPackageFromNCBI() and makeOrgPackage() in the `AnnotationForge` package for help creating the sqlite file. BSgenome objects should be made according to the steps outline in the [BSgenome vignette](http://www.bioconductor.org/packages/3.4/bioc/vignettes/BSgenome/inst/doc/BSgenomeForge.pdf). TxDb objects will be made on-the-fly from a GRanges with GenomicFeatures::makeTxDbFromGRanges() when the resource is downloaded from `AnnotationHub`. Data should be provided as a GRanges object. See GenomicRanges::makeGRangesFromDataFrame() or rtracklayer::import() for help creating the GRanges. 3. Generate metadata: Prepare a .R file that generates metadata for the resource(s) by calling the `AnnotationHubData::AnnotationHubMetadata()` constructor. Argument details are found on the ?`AnnotationHubMetadata` man page. As an example, this piece of code generates the metadata for the Vitis vinifera TxDb Timothée Flutre contributed to `AnnotationHub`: ```{r, TxDb_Metadata, eval=FALSE} metadata <- AnnotationHubMetadata( Description="Gene Annotation for Vitis vinifera", Genome="IGGP12Xv0", Species="Vitis vinifera", SourceUrl="http://genomes.cribi.unipd.it/DATA/V2/V2.1/V2.1.gff3", SourceLastModifiedDate=as.POSIXct("2014-04-17"), SourceVersion="2.1", RDataPath="community/tflutre/", TaxonomyId=29760L, Title="Vvinifera_CRIBI_IGGP12Xv0_V2.1.gff3.Rdata", BiocVersion=package_version("3.3"), Coordinate_1_based=TRUE, DataProvider="CRIBI", Maintainer="Timothée Flutre = the date of the Bioconductor release being used - 'rdatadateadded' >= today's date - 'rdatadateremoved' is NULL / NA - 'biocVersion' is <= to the Bioconductor version being used Once a record is added to AnnotationHub it is visable from that point forward until stamped with 'rdatadateremoved'. For example, a record added on May 1, 2017 with 'biocVersion' 3.6 will be visible in all snapshots >= May1, 2017 and in all Bioconductor versions >= 3.6. # Uploading Data to S3 Instead of providing the data files via dropbox, ftp, etc. we will grant temporary access to an S3 bucket where you can upload your data. Please email Lori.Shepherd@roswellpark.org for access. You will be given access to the 'AnnotationContributor' user. Ensure that the `AWS CLI` is installed on your machine. See instructions for installing `AWS CLI` [here](https://aws.amazon.com/cli/). Once you have requested access you will be emailed a set of keys. There are two options to set the profile up for AnnotationContributor 1. Update your `.aws/config` file to include the following updating the keys accordingly: ``` [profile AnnotationContributor] output = text region = us-east-1 aws_access_key_id = **** aws_secret_access_key = **** ``` 2. If you can't find the `.aws/config` file, Run the following command entering appropriate information from above ``` aws configure --profile AnnotationContributor ``` After the configuration is set you should be able to upload resources using ``` aws --profile AnnotationContributor s3 cp test_file.txt s3://annotation-contributor/test_file.txt --acl public-read ``` Please upload the data with the appropriate directory structure, including subdirectories as necessary (i.e. top directory must be software package name, then if applicable, subdirectories of versions, ...) Once the upload is complete, email Lori.Shepherd@roswellpark.org to continue the process AnnotationHub/inst/doc/CreateAnAnnotationPackage.html0000644000175400017540000263742213200446560023772 0ustar00biocbuildbiocbuild Creating An AnnotationHub Package

Contents

1 Overview

The AnnotationHubData package provides tools to acquire, annotate, convert and store data for use in Bioconductor’s AnnotationHub. BED files from the Encode project, gtf files from Ensembl, or annotation tracks from UCSC, are examples of data that can be downloaded, described with metadata, transformed to standard Bioconductor data types, and stored so that they may be conveniently served up on demand to users via the AnnotationHub client. While data are often manipulated into a more R-friendly form, the data themselves retain their raw content and are not filtered or curated like those in ExperimentHub.
Each resource has associated metadata that can be searched through the AnnotationHub client interface.

2 New resources

2.1 Family of resources

Multiple, related resources are added to AnnotationHub by creating a software package similar to the existing annotation packages. The package itself does not contain data but serves as a light weight wrapper around scripts that generate metadata for the resources added to AnnotationHub.

At a minimum the package should contain a man page describing the resources. Vignettes and additional R code for manipulating the objects are optional.

Creating the package involves the following steps:

  1. Notify Bioconductor team member:
    Man page and vignette examples in the software package will not work until the data are available in AnnotationHub. Adding the data to AWS S3 and the metadata to the production database involves assistance from a Bioconductor team member. Please read the section “Uploading Data to S3”.

  2. Building the software package:
    Below is an outline of package organization. The files listed are required unless otherwise stated.

  • inst/extdata/

    • metadata.csv: This file contains the metadata in the format of one row per resource to be added to the AnnotationHub database. The file should be generated from the code in inst/scripts/make-metadata.R where the final data are written out with write.csv(…, row.names=FALSE). The required column names and data types are specified in AnnotationHub::readMetadataFromCsv(). See ?readMetadataFromCsv for details.

    If necessary, metadata can be broken up into multiple csv files instead having of all records in a single “metadata.csv”.

  • inst/scripts/

    • make-data.R:
      A script describing the steps involved in making the data object(s). This includes where the original data were downloaded from, pre-processing, and how the final R object was made. Include a description of any steps performed outside of R with third party software. Output of the script should be files on disk ready to be pushed to S3. If data are to be hosted on a personal web site instead of S3, this file should explain any manipulation of the data prior to hosting on the web site. For data hosted on a public web site with no prior manipultaion this file is not needed.

    • make-metadata.R:
      A script to make the metadata.csv file located in inst/extdata of the package. See ?readMetadataFromCsv for a description of the metadata.csv file, expected fields and data types. The readMetadataFromCsv() function can be used to validate the metadata.csv file before submitting the package.

  • vignettes/

    OPTIONAL vignette(s) describing analysis workflows.

  • R/

    OPTIONAL functions to enhance data exploration.

  • man/

    • package man page:
      OPTIONAL. The package man page serves as a landing point and should briefly describe all resources associated with the package. There should be an entry for each resource title either on the package man page or individual man pages.

    • resource man pages:
      OPTIONAL. Man page(s) should describe the resource (raw data source, processing, QC steps) and demonstrate how the data can be loaded through the AnnotationHub interface. For example, replace “SEARCHTERM*" below with one or more search terms that uniquely identify resources in your package.

    library(AnnotationHub)
    hub <- AnnotationHub()
    myfiles <- query(hub, "SEARCHTERM1", "SEARCHTERM2")
    myfiles[[1]]  ## load the first resource in the list
  • DESCRIPTION / NAMESPACE
    The scripts used to generate the metadata will likely use functions from AnnotationHub or AnnotationHubData which should be listed in Depends/Imports as necessary.

  1. Data objects:
    Data are not formally part of the software package and are stored separately in AWS S3 buckets. The author should follow instructions in the section “Uploading Data to S3”

  2. Confirm valid metadata:
    Confirm the data in inst/exdata/metadata.csv are valid by running AnnotationHubData:::makeAnnotationHubMetadata() on your package. Please address and warnings or errors.

  3. Package review:
    Submit the package to the tracker for review. The primary purpose of the package review is to validate the metadata in the csv file(s). It is ok if the package fails R CMD build and check because the data and metadata are not yet in place. Once the metadata.csv is approved, records are added to the production database. At that point the package man pages and vignette can be finalized and the package should pass R CMD build and check.

2.2 Individual resources

Individual objects of a standard class can be added to the hub by providing only the data and metadata files or by creating a package as described in the Family of Resources section.

OrgDb, TxDb and BSgenome objects are well defined Bioconductor classes and methods to download and process these objects already exist in AnnotationHub. When adding only one or two objects the overhead of creating a package may be unnecessary. The goal of the package is to provide structure for metadata generation and makes sense when there are plans to update versions or add new organisms in the future.

Make sure the OrgDb, TxDb or BSgenome object you want to add does not already exist in the
Biocondcutor annotation repository

Providing just data and metadata files involves the following steps:

  1. Notify Bioconductor team member:
    Adding the data to AWS S3 and the metadata to the production database involves assistance from a Bioconductor team member. Please read the section “Uploading Data to S3”.

  2. Prepare the data:
    In the case of an OrgDb object, only the sqlite file is stored in S3. See makeOrgPackageFromNCBI() and makeOrgPackage() in the AnnotationForge package for help creating the sqlite file. BSgenome objects should be made according to the steps outline in the BSgenome vignette. TxDb objects will be made on-the-fly from a GRanges with GenomicFeatures::makeTxDbFromGRanges() when the resource is downloaded from AnnotationHub. Data should be provided as a GRanges object. See GenomicRanges::makeGRangesFromDataFrame() or rtracklayer::import() for help creating the GRanges.

  3. Generate metadata:
    Prepare a .R file that generates metadata for the resource(s) by calling the AnnotationHubData::AnnotationHubMetadata() constructor. Argument details are found on the ?AnnotationHubMetadata man page.

As an example, this piece of code generates the metadata for the Vitis vinifera TxDb Timothée Flutre contributed to AnnotationHub:

metadata <- AnnotationHubMetadata(
    Description="Gene Annotation for Vitis vinifera",
    Genome="IGGP12Xv0",
    Species="Vitis vinifera",
    SourceUrl="http://genomes.cribi.unipd.it/DATA/V2/V2.1/V2.1.gff3",
    SourceLastModifiedDate=as.POSIXct("2014-04-17"),
    SourceVersion="2.1",
    RDataPath="community/tflutre/",
    TaxonomyId=29760L, 
    Title="Vvinifera_CRIBI_IGGP12Xv0_V2.1.gff3.Rdata",
    BiocVersion=package_version("3.3"),
    Coordinate_1_based=TRUE,
    DataProvider="CRIBI",
    Maintainer="Timothée Flutre <timothee.flutre@supagro.inra.fr",
    RDataClass="GRanges",
    DispatchClass="GRanges",
    SourceType="GFF",
    RDataDateAdded=as.POSIXct(Sys.time()),
    Recipe=NA_character_,
    PreparerClass="None",
    Tags=c("GFF", "CRIBI", "Gene", "Transcript", "Annotation"),
    Notes="chrUn renamed to chrUkn"
)
  1. Add data to S3 and metadata to the database:
    This last step is done by the Biocondcutor team member.

3 Additional resources

Metadata for new versions of the data can be added to the same package as they become available.

  • The titles for the new versions should be unique and not match the title of any resource currently in AnnotationHub. Good practice would be to include the version and / or genome build in the title. If the title is not unique, the AnnotationHub object will list multiple files with the same title. The user will need to use ‘rdatadateadded’ to determine which is the most current.

  • Make data available: see section on “Uploading Data to S3”

  • Update make-metadata.R with the new metadata information

  • Generate a new metadata.csv file. The package should contain metadata for all versions of the data in AnnotationHub so the old file should remain. When adding a new version it might be helpful to write a new csv file named by version, e.g., metadata_v84.csv, metadata_85.csv etc.

  • Bump package version and commit to git

  • Notify Lori.Shepherd@Roswellpark.org that an update is ready and a team member will add the new metadata to the production database; new resources will not be visible in AnnotationHub until the metadata are added to the database.

Contact Lori.Shepherd@roswellpark.org or maintainer@bioconductor.org with any questions.

4 Bug fixes

A bug fix may involve a change to the metadata, data resource or both.

4.1 Update the resource

  • The replacement resource must have the same name as the original and be at the same location (path).

  • Notify Lori.Shepherd@roswellpark.org that you want to replace the data and make the files available: see section “Uploading Data to S3”.

4.2 Update the metadata

New metadata records can be added for new resources but modifying existing records is discouraged. Record modification will only be done in the case of bug fixes.

  • Notify Lori.Shepherd@roswellpark.org that you want to change the metadata

  • Update make-metadata.R and regenerate the metadata.csv file

  • Bump the package version and commit to git

5 Remove resources

When a resource is removed from AnnotationHub two things happen: the ‘rdatadateremoved’ field is populated with a date and the ‘status’ field is populated with a reason why the resource is no longer available. Once these changes are made, the AnnotationHub() constructor will not list the resource among the available ids. An attempt to extract the resource with ‘[[’ and the AH id will return an error along with the status message.

In general, resources are only removed when they are no longer available (e.g., moved from web location, no longer provided etc.).

To remove a resource from AnnotationHub contact Lori.Shepherd@roswellpark.org or maintainer@bioconductor.org.

6 Versioning

Versioning of resources is handled by the maintainer. If you plan to provide incremental updates to a file for the same organism / genome build, we recommend including a version in the title of the resource so it is easy to distinguish which is most current.

If you do not include a version, or make the title unique in some way, multiple files with the same title will be listed in the AnnotationHub object. The user will can use the ‘rdatadateadded’ metadata field to determine which file is the most current.

7 Visibility

Several metadata fields control which resources are visible when a user invokes AnnotationHub(). Records are filtered based on these criteria:

  • ‘snapshotdate’ >= the date of the Bioconductor release being used
  • ‘rdatadateadded’ >= today’s date
  • ‘rdatadateremoved’ is NULL / NA
  • ‘biocVersion’ is <= to the Bioconductor version being used

Once a record is added to AnnotationHub it is visable from that point forward until stamped with ‘rdatadateremoved’. For example, a record added on May 1, 2017 with ‘biocVersion’ 3.6 will be visible in all snapshots >= May1, 2017 and in all Bioconductor versions >= 3.6.

8 Uploading Data to S3

Instead of providing the data files via dropbox, ftp, etc. we will grant temporary access to an S3 bucket where you can upload your data. Please email Lori.Shepherd@roswellpark.org for access.

You will be given access to the ‘AnnotationContributor’ user. Ensure that the AWS CLI is installed on your machine. See instructions for installing AWS CLI here. Once you have requested access you will be emailed a set of keys. There are two options to set the profile up for AnnotationContributor

  1. Update your .aws/config file to include the following updating the keys accordingly:
[profile AnnotationContributor]
output = text
region = us-east-1
aws_access_key_id = ****
aws_secret_access_key = ****
  1. If you can’t find the .aws/config file, Run the following command entering appropriate information from above
aws configure --profile AnnotationContributor

After the configuration is set you should be able to upload resources using

aws --profile AnnotationContributor s3 cp test_file.txt s3://annotation-contributor/test_file.txt --acl public-read

Please upload the data with the appropriate directory structure, including subdirectories as necessary (i.e. top directory must be software package name, then if applicable, subdirectories of versions, …)

Once the upload is complete, email Lori.Shepherd@roswellpark.org to continue the process

AnnotationHub/inst/scripts/0000755000175400017540000000000013175714307017025 5ustar00biocbuildbiocbuildAnnotationHub/inst/scripts/shinyTest.R0000644000175400017540000001473713175714307021156 0ustar00biocbuildbiocbuildlibrary(shiny) ##################################################### ## the original demo as a function: # display2 <- # function(df, ...) # { # app <- list( # ui = fluidPage( # title = 'Row selection in DataTables', # sidebarLayout( # sidebarPanel(textOutput('rows_out')), # mainPanel(dataTableOutput('tbl')), # position = 'right' # ) # ) # , # server = function(input, output) { # output$rows_out <- renderText({ # paste(c('You selected these rows on the page:', # input$rows), # collapse = ' ') # }) # output$tbl <- renderDataTable( # df, # options = list(pageLength = 10), # callback = "function(table) { # table.on('click.dt', 'tr', function() { # $(this).toggleClass('selected'); # Shiny.onInputChange('rows', # table.rows('.selected').indexes().toArray()); # }); }") # } # ) # # ## selectively use the RStudio viewer pane (if available) # viewer <- getOption("viewer") # if (!is.null(viewer)){ # runApp(app, launch.browser = rstudio::viewer, ...) # }else{ # runApp(app, ...) # } # } ##################################################### ## my function that tries to just use indexes: display2 <- function(df, ...) { rowNames <- rownames(df) dt <- data.frame(rownames=rowNames,df) ## define the app app <- list( ui = fluidPage( title = 'The data from your data.frame', sidebarLayout( sidebarPanel(textOutput('rows_out'), br(), actionButton("btnSend", "Send Rows")), mainPanel(dataTableOutput('tbl')), position = 'left' ) ) , server = function(input, output) { output$rows_out <- renderText({ paste(c('You selected these rows on the page:', input$rows), collapse = ' ') }) output$tbl <- renderDataTable( dt, options = list(pageLength = 20), callback = "function(table) { table.on('click.dt', 'tr', function() { $(this).toggleClass('selected'); Shiny.onInputChange('rows', table.rows('.selected').indexes().toArray()); }); }") observe({ if(input$btnSend > 0) isolate({ #print(input$rows) idx <- as.integer(input$rows) + 1 stopApp(returnValue = df[idx,]) }) }) }) ## selectively use the RStudio viewer pane (if available) viewer <- getOption("viewer") if (!is.null(viewer)){ runApp(app, launch.browser = rstudio::viewer, ...) }else{ runApp(app, ...) } } ## usage: ## display2(mtcars) ## original: ## table.rows('.selected').indexes().toArray()); ## This is kind of the same thing ## table.rows( $('.selected').closest('tr') ).indexes().toArray()); ## And this gets just the 1st one ## table.rows( $('.selected').closest('tr')[0] ).indexes().toArray()); ##################################################### ## my function that just get the row data (like before) display2 <- function(df, ...) { rowNames <- rownames(df) dt <- data.frame(rownames=rowNames,df) ## define the app app <- list( ui = fluidPage( title = 'The data from your data.frame', sidebarLayout( sidebarPanel(textOutput('rows_out'), br(), actionButton("btnSend", "Send Rows")), mainPanel(dataTableOutput('tbl')), position = 'left' ) ) , server = function(input, output) { output$rows_out <- renderText({ paste(c('You selected these rows on the page:', input$rows), collapse = ' ') }) output$tbl <- renderDataTable( dt, options = list(pageLength = 50), callback = "function(table) { table.on('click.dt', 'tr', function() { $(this).toggleClass('selected'); Shiny.onInputChange('rows', table.rows('.selected').indexes().toArray()); Shiny.onInputChange('tbl', table.rows('.selected').indexes().toArray()); }); }") ## TODO: change the above callback so that it returns rowRanges (not just indexes) observe({ if(input$btnSend > 0) isolate({ #print(input$rows) # idx <- as.integer(input$rows) + 1 # stopApp(returnValue = df[idx,]) # dfVec <- input$myTable # df <- as.data.frame(matrix(data=dfVec, ncol=dim(df)[2], # byrow=TRUE)) # names(df) <- colNames stopApp(returnValue = input$tbl) }) }) }) ## selectively use the RStudio viewer pane (if available) viewer <- getOption("viewer") if (!is.null(viewer)){ runApp(app, launch.browser = rstudio::viewer, ...) }else{ runApp(app, ...) } } ## usage: ## display2(mtcars) AnnotationHub/inst/scripts/test.R0000644000175400017540000001541613175714307020136 0ustar00biocbuildbiocbuild## Things to do with the new hub ## 1) fix the downloads (currently broken) ## 2) get working set of examples scripted. ## 3) make working functions for missing stuff. ## load library(AnnotationHub) ah <- AnnotationHub() ## show ah ## get metadata for first value ah[1] ## extract 1st value foo = ah[[1]] ## extract 2nd value (problem with back end?) bar = ah[[2]] ## subset ah by genome ahs <- ah[grep('ailMel1', ah$genome)] ## subset it by tags ahs <- ah[grep('broadPeak', ah$tags)] ## or subset by names (if known) ah['AH3'] ah[c('AH3','AH4')] ## cache up values from the web. cache(ah[1:3]) cache(ah[[3]]) ## TROUBLE???: but this doesn't really make sense does it? ## Shouldn't the thing passed to cache always be a hub object??? ## So shouldn't it really be more like this? cache(ah[3]) ## vs this which seems to work without a hitch: baz <- ah[[5]] ## use query to subset ahs <- query(ah, 'inparanoid8') ## This is fine! (arguments were flipped) # trace("query", browser, signature ="AnnotationHub") foo <- ahs[[1]] ## use subset in the traditional way ahsub <- subset(ah, ah$genome=='ailMel1') ## ADD: ## display ## possibleDates -- compute on client SELECT DISTINCT rdatadateadded FROM... ## snapshotDate (setter and getter) ## snapshotVersion -- i.e. BiocInstaller::biocVersion() ## and hubUrl (https://annotationhub.bioconductor.org/) ######################## ## MORE things to test: ## ## Tests for different file types to each come down and be A-OK ## resource ID for: ## VCF: 7220 foo = ah[['7220']] ## GRanges: 522 foo = ah[['522']] ## data.frame: 7831 foo = ah[['7831']] ## SQLite: 10366 foo = ah[['10366']] ## fasta file: 3 ## This example is HUGE (need smaller one) foo = ah[['3']] ################################################# ## Test for verifying that my change works. ## ## Testing 1st requires that I can do this (because the recipe is old) ## select id,rdatapath,resource_id from rdatapaths where resource_id ='3'; ## (and get two records) ## ## To use gamay do this: ## options(ANNOTATION_HUB_URL="http://gamay:9393") library(AnnotationHub); ah = AnnotationHub(); #trace(".get1", browser, signature = "FaFileResource") #debug(AnnotationHub:::.AnnotationHub_get1) ##trace("show", browser, signature = "AnnotationHub") fa = ah[['3']] ## test the 'repaired' ensembl 75 fasta files. fa = ahs[['10725']] ## Now I just need to change it so that it uses the ah_id from the resources ## table (instead of the actual 'id') ################################################## ## code to hack in a value for the fasta file for ah[['3']] ## BASICALLY you have to add a row to rdatapaths such that ## something like this: ## SELECT * FROM rdatapaths WHERE resource_id = '3' limit 4; ## will return more than one row ## This appears to be on default prod now for at least one resource. ## BUT: what is the file that is called 15107 in my cache? How are these named? ## Is it the id from rdatapaths? Or the resource_id? ## And shouldn't it be the AHID from resources? ## OR perhaps should the AHID be associated with the value from rdatapaths? ################################################## ## The answer is that it's the 'id' from rdatapaths that you want to used for ## cached files (and that the methods should access). And for the UI, ## the user should type in the 'AHID' names (and names should be modified to ## use this) ################################################## ## The SQL to fix existing records needs to just add one row to rdatapaths for ## each .fa file in the resources table ## Subquery: ## SELECT rdatapath || '.fai', rdataclass, resource_id FROM rdatapaths ## WHERE rdataclass='FaFile'; ## ## 1st drop the 'extra' one ## DELETE FROM rdatapaths where id = 15107; ## ## Full query: ## INSERT INTO rdatapaths (rdatapath, rdataclass, resource_id) ## SELECT rdatapath || '.fai', rdataclass, resource_id FROM rdatapaths ## WHERE rdataclass='FaFile'; ## But for MySQL the subquery will probably look more like this: ## SELECT concat(rdatapath, '.fai'), rdataclass, resource_id FROM rdatapaths ## WHERE rdataclass='FaFile'; ## Full MySQL query: ## INSERT INTO rdatapaths (rdatapath, rdataclass, resource_id) ## SELECT concat(rdatapath, '.fai'), rdataclass, resource_id FROM rdatapaths ## WHERE rdataclass='FaFile'; ################################################## ## SQL Code to correct the missing version bump ## SELECT DISTINCT '3.1', resource_id FROM biocversions limit 4; ######### ## INSERT INTO biocversions (biocversion, resource_id) SELECT ## DISTINCT '3.1', resource_id FROM biocversions; ############################################################# ## Instructions for connecting to the back end DB directly: ## on gamay just connect to the DB like this: ## mysql -p -u ahuser annotationhub ## ## ## And for production just log in FIRST ## ssh ubuntu@annotationhub.bioconductor.org # it has your key ## ## Then back up the DB like so: ## mysqldump -p -u ahuser annotationhub | gzip > dbdump_201410211449.sql.gz ## ## And proceed as above. ## ############################################################# ## For browsing around the data resources: ################################################################# ## Switching from numbers to AH IDs. ## show method fails because subsetting is now wonky ## debug(AnnotationHub:::.show) ## subsetting probably expects that the numbers in names() can be ## used as indices somehow... ## trace("[", browser, signature = c("AnnotationHub", "numeric", "missing")) ## ah[2] library(AnnotationHub) ah <- AnnotationHub() #trace("[", browser, signature = c("AnnotationHub", "character", "missing")) ah['AH3'] #trace("[", browser, signature = c("AnnotationHub", "numeric", "missing")) trace("[<-", browser, signature = c("AnnotationHub", "numeric", "missing", "AnnotationHub")) ah[2] ## Problem with show method for single bracket subsets... ## Happens with single items and in the case below where (one item is dropped) ## debug(AnnotationHub:::.show) ash = ah[1:3] ash ## This works now trace("[[", browser, signature = c("AnnotationHub", "character", "missing")) debug(AnnotationHub:::.AnnotationHub_get1) ah[['AH3']] ## TODO: this doesn't work (yet) - low priority though ah[[c('AH3','AH4')]] ## is the same as: ah[[2]] ########################################################## ## Issue with chain files. ## trace(AnnotationHub:::.get1, tracer=browser, signature ="ChainFileResource") library(AnnotationHub) ah <- AnnotationHub() ahs <- subset(ah, ah$genome=='hg38') ahs <- ahs[1] ahs[[1]] ## URL generated: chain <- "/home/mcarlson/.AnnotationHub/18058" ## trace(AnnotationHub:::.get1, tracer=browser, signature ="ChainFileResource") ## Things I tried: ## rtracklayer::import.chain(chain) ## rtracklayer::import.chain(path=chain, format='chain') AnnotationHub/inst/unitTests/0000755000175400017540000000000013175714307017340 5ustar00biocbuildbiocbuildAnnotationHub/inst/unitTests/test_AnnotationHub-class.R0000644000175400017540000000214513175714307024400 0ustar00biocbuildbiocbuildtest_open <- function() { ## valid connection, including on second try checkTrue(RSQLite::dbIsValid(dbconn(AnnotationHub()))) checkTrue(RSQLite::dbIsValid(dbconn(AnnotationHub()))) } test_query <- function() { ah = AnnotationHub() q1 <- query(ah, c("GTF", "Ensembl", "Homo sapiens")) checkTrue("AH7558" %in% names(q1)) nm <- c("title", "dataprovider", "species", "taxonomyid", "genome", "description", "tags", "rdataclass", "sourceurl", "sourcetype") checkTrue(all(nm %in% names(mcols(q1)))) } test_NA_subscript <- function() { ah <- AnnotationHub() checkIdentical(0L, length(ah[NA])) checkIdentical(0L, length(ah[NA_character_])) checkIdentical(0L, length(ah[NA_integer_])) } test_as.list_and_c <- function() { ah <- AnnotationHub() cc <- selectMethod("c", "AnnotationHub") checkIdentical(ah[1:5], do.call("cc", as.list(ah[1:5]))) checkIdentical(ah[1:5], c(ah[1:2], ah[3:5])) checkIdentical(ah[FALSE], c(ah[FALSE], ah[FALSE])) checkIdentical(ah[1:5], c(ah[FALSE], ah[1:5])) checkIdentical(ah[1:5], c(ah[1:4], ah[3:5])) # unique() ids } AnnotationHub/inst/unitTests/test_cache.R0000644000175400017540000000113013175714307021560 0ustar00biocbuildbiocbuildtest_cache_datapathIds <- function() { ## map hub identifiers AH123 to cached identifier(s) hub <- AnnotationHub() ## 1:1 mapping result <- AnnotationHub:::.datapathIds(hub["AH28854"]) checkIdentical(result, structure(34294L, .Names = "AH28854")) ## 1:several mapping result <- AnnotationHub:::.datapathIds(hub["AH169"]) checkIdentical(result, structure(c(169L, 14130L), .Names = c("AH169", "AH169"))) ## unknown identifier result <- AnnotationHub:::.datapathIds(hub["AH0"]) checkIdentical(result, setNames(integer(), character())) } AnnotationHub/inst/unitTests/test_tidyGRanges.R0000644000175400017540000000270113175714307022742 0ustar00biocbuildbiocbuildtest_tidyGRanges <- function() { # Case 1 - GRanges does not have any seqinfo gr <- GenomicRanges::GRanges(paste0("chr", c(1, 10, "M", 2, 3)), IRanges::IRanges(1, 1)) gr1 <- AnnotationHub:::.tidyGRanges(gr=gr, metadata=FALSE, genome="hg19") chr <- paste0("chr", c(1, 2, 3, 10, "M")) checkIdentical(chr, GenomeInfoDb::seqlevels(gr1)) checkIdentical(setNames(rep("hg19", 5), chr), GenomeInfoDb::genome(gr1)) checkIdentical(setNames(rep(c(FALSE, TRUE), c(4, 1)), chr), GenomeInfoDb::isCircular(gr1)) # case -2 genome not supported by GenomeInfoDb::Seqinfo gr2 <- AnnotationHub:::.tidyGRanges(gr=gr, metadata=FALSE, genome="calJac3") checkIdentical(setNames(rep("calJac3", 5), chr), GenomeInfoDb::genome(gr2)) checkIdentical(setNames(rep(c(FALSE, TRUE), c(4, 1)), chr), GenomeInfoDb::isCircular(gr2)) # case -3 GRanges has incorrect/missing seqinfo GenomeInfoDb::seqlengths(gr) <- c(1,2,3,4,5) GenomeInfoDb::isCircular(gr) <- rep(FALSE,5) GenomeInfoDb::genome(gr) <- "hg19" gr1 <- AnnotationHub:::.tidyGRanges(gr=gr, metadata=FALSE, genome="hg19") chr <- paste0("chr", c(1, 2, 3, 10, "M")) checkIdentical(chr, GenomeInfoDb::seqlevels(gr1)) checkIdentical(setNames(rep("hg19", 5), chr), GenomeInfoDb::genome(gr1)) checkIdentical(setNames(rep(c(FALSE, TRUE), c(4, 1)), chr), GenomeInfoDb::isCircular(gr1)) } AnnotationHub/inst/unitTests/test_utilities.R0000644000175400017540000000012713175714307022535 0ustar00biocbuildbiocbuildtest_require <- function() { checkException(AnnotationHub:::.require("xxx_foo")) } AnnotationHub/man/0000755000175400017540000000000013175714307015134 5ustar00biocbuildbiocbuildAnnotationHub/man/AnnotationHub-class.Rd0000644000175400017540000002741013175714307021303 0ustar00biocbuildbiocbuild\name{AnnotationHub-objects} \docType{class} % Classes \alias{class:AnnotationHub} \alias{AnnotationHub-class} \alias{class:Hub} \alias{Hub-class} % Constructor \alias{.Hub} \alias{AnnotationHub} % Accessor-like methods \alias{mcols,Hub-method} \alias{cache} \alias{cache,Hub-method} \alias{cache,AnnotationHub-method} \alias{cache<-} \alias{cache<-,Hub-method} \alias{hubUrl} \alias{hubUrl,Hub-method} \alias{hubCache} \alias{hubCache,Hub-method} \alias{hubDate} \alias{hubDate,Hub-method} \alias{package} \alias{package,Hub-method} \alias{removeCache} \alias{possibleDates} \alias{snapshotDate} \alias{snapshotDate,Hub-method} \alias{snapshotDate<-} \alias{snapshotDate<-,Hub-method} \alias{dbconn,Hub-method} \alias{dbfile,Hub-method} \alias{.db_close} \alias{recordStatus} \alias{recordStatus,Hub-method} % List-like \alias{length,Hub-method} \alias{names,Hub-method} \alias{fileName,Hub-method} % Subsetting: \alias{$,Hub-method} \alias{[[,Hub,character,missing-method} \alias{[[,Hub,numeric,missing-method} \alias{[,Hub,character,missing-method} \alias{[,Hub,logical,missing-method} \alias{[,Hub,numeric,missing-method} \alias{[<-,Hub,character,missing,Hub-method} \alias{[<-,Hub,logical,missing,Hub-method} \alias{[<-,Hub,numeric,missing,Hub-method} \alias{subset,Hub-method} \alias{query} \alias{query,Hub-method} \alias{display} \alias{display,Hub-method} % as.list / c \alias{as.list.Hub} \alias{as.list,Hub-method} \alias{c,Hub-method} % show method: \alias{show,Hub-method} \alias{show,AnnotationHub-method} \alias{show,AnnotationHubResource-method} \title{AnnotationHub objects and their related methods and functions} \description{ Use \code{AnnotationHub} to interact with Bioconductor's AnnotationHub service. Query the instance to discover and use resources that are of interest, and then easily download and import the resource into R for immediate use. Use \code{AnnotationHub()} to retrieve information about all records in the hub. If working offline, add argument \code{localHub=TRUE} to work with a local, non-updated hub; It will only have resources available that have previously been downloaded. Discover records in a hub using \code{mcols()}, \code{query()}, \code{subset()}, \code{[}, and \code{display()}. Retrieve individual records using \code{[[}. On first use of a resource, the corresponding files or other hub resources are downloaded from the internet to a local cache. On this and all subsequent uses the files are quickly input from the cache into the R session. \code{AnnotationHub} records can be added (and sometimes removed) at any time. \code{snapshotDate()} restricts hub records to those available at the time of the snapshot. \code{possibleDates()} lists snapshot dates valid for the current version of Bioconductor. The location of the local cache can be found (and updated) with \code{getAnnotationHubCache} and \code{setAnnotationHubCache}; \code{removeCache} removes all cache resources. } \section{Constructors}{ \describe{ \item{}{ \code{AnnotationHub(..., hub=getAnnotationHubOption("URL"), cache=getAnnotationHubOption("CACHE"), proxy=getAnnotationHubOption("PROXY"), localHub=FALSE)}: Create an \code{AnnotationHub} instance, possibly updating the current database of records. } } } \section{Accessors}{ In the code snippets below, \code{x} and \code{object} are AnnotationHub objects. \describe{ \item{}{ \code{hubCache(x)}: Gets the file system location of the local AnnotationHub cache. } \item{}{ \code{hubUrl(x)}: Gets the URL for the online hub. } \item{}{ \code{length(x)}: Get the number of hub records. } \item{}{ \code{names(x)}: Get the names (AnnotationHub unique identifiers, of the form AH12345) of the hub records. } \item{}{ \code{fileName(x)}: Get the file path of the hub records as stored in the local cache (AnnotationHub files are stored as unique numbers, of the form 12345). NA is returned for those records which have not been cached. } \item{}{ \code{mcols(x)}: Get the metadata columns describing each record. Columns include: \describe{ \item{title}{Record title, frequently the file name of the object.} \item{dataprovider}{Original provider of the resource, e.g., Ensembl, UCSC.} \item{species}{The species for which the record is most relevant, e.g., \sQuote{Homo sapiens}.} \item{taxonomyid}{NCBI taxonomy identifier of the species.} \item{genome}{Genome build relevant to the record, e.g., hg19.} \item{description}{Textual description of the resource, frequently automatically generated from file path and other information available when the record was created.} \item{tags}{Single words added to the record to facilitate identification, e.g,. TCGA, Roadmap.} \item{rdataclass}{The class of the R object used to represent the object when imported into R, e.g., \code{GRanges}, \code{VCFFile}.} \item{sourceurl}{Original URL of the resource.} \item{sourectype}{Format of the original resource, e.g., BED file.} } } \item{}{ \code{dbconn(x)}: Return an open connection to the underyling SQLite database.} \item{}{ \code{dbfile(x)}: Return the full path the underyling SQLite database.} \item{}{ \code{.db_close(conn)}: Close the SQLite connection \code{conn} returned by \code{dbconn(x)}.} } } \section{Subsetting and related operations}{ In the code snippets below, \code{x} is an AnnotationHub object. \describe{ \item{}{ \code{x$name}: Convenient reference to individual metadata columns, e.g., \code{x$species}. } \item{}{ \code{x[i]}: Numerical, logical, or character vector (of AnnotationHub names) to subset the hub, e.g., \code{x[x$species == "Homo sapiens"]}. } \item{}{ \code{x[[i]]}: Numerical or character scalar to retrieve (if necessary) and import the resource into R. } \item{}{ \code{query(x, pattern, ignore.case=TRUE, pattern.op= `&`)}: Return an AnnotationHub subset containing only those elements whose metadata matches \code{pattern}. Matching uses \code{pattern} as in \code{\link{grepl}} to search the \code{as.character} representation of each column, performing a logical \code{`&`} across columns. e.g., \code{query(x, c("Homo sapiens", "hg19", "GTF"))}. \describe{ \item{\code{pattern}}{A character vector of patterns to search (via \code{grepl}) for in any of the \code{mcols()} columns.} \item{\code{ignore.case}}{A logical(1) vector indicating whether the search should ignore case (TRUE) or not (FALSE).} \item{\code{pattern.op}}{Any function of two arguments, describing how matches across pattern elements are to be combined. The default \code{`&`} requires that only records with \emph{all} elements of \code{pattern} in their metadata columns are returned. \code{`&`}, \code{`|`} and \code{`!`} are most notably available. See \code{"?&"} or \code{?base::Ops} for more information.} } } \item{}{ \code{subset(x, subset)}: Return the subset of records containing only those elements whose metadata satisfies the \emph{expression} in \code{subset}. The expression can reference columns of \code{mcols(x)}, and should return a logical vector of length \code{length(x)}. e.g., \code{subset(x, species == "Homo sapiens" & genome=="GRCh38")}. } \item{}{ \code{display(object)}: Open a web browser allowing for easy selection of hub records via interactive tabular display. Return value is the subset of hub records identified while navigating the display. } \item{}{ \code{recordStatus(hub, record)}: Returns a \code{data.frame} of the record id and status. \code{hub} must be a \code{Hub} object and \code{record} must be a \code{character(1)}. Can be used to discover why a resource was removed from the hub. } } } \section{Cache and hub management}{ In the code snippets below, \code{x} is an AnnotationHub object. \describe{ \item{}{ \code{snapshotDate(x)} and \code{snapshotDate(x) <- value}: Gets or sets the date for the snapshot in use. \code{value} should be one of \code{possibleDates()}. } \item{}{ \code{possibleDates(x)}: Lists the valid snapshot dates for the version of Bioconductor that is being run (e.g., BiocInstaller::biocVersion()). } \item{}{ \code{cache(x)} and \code{cache(x) <- NULL}: Adds (downloads) all resources in \code{x}, or removes all local resources corresponding to the records in \code{x} from the cache. In this case, \code{x} would typically be a small subset of AnnotationHub resources. } \item{}{ \code{hubUrl(x)}: Gets the URL for the online AnnotationHub. } \item{}{ \code{hubCache(x)}: Gets the file system location of the local AnnotationHub cache. } \item{}{ \code{removeCache(x)}: Removes local AnnotationHub database and all related resources. After calling this function, the user will have to download any AnnotationHub resources again. } } } \section{Coercion}{ In the code snippets below, \code{x} is an AnnotationHub object. \describe{ \item{}{ \code{as.list(x)}: Coerce x to a list of hub instances, one entry per element. Primarily for internal use. } \item{}{ \code{c(x, ...)}: Concatenate one or more sub-hub. Sub-hubs must reference the same AnnotationHub instance. Duplicate entries are removed. } } } \author{Martin Morgan, Marc Carlson, Sonali Arora, and Dan Tenenbaum} \examples{ ## create an AnnotationHub object library(AnnotationHub) ah = AnnotationHub() ## Summary of available records ah ## Detail for a single record ah[1] ## and what is the date we are using? snapshotDate(ah) ## how many resources? length(ah) ## from which resources, is data available? head(sort(table(ah$dataprovider), decreasing=TRUE)) ## from which species, is data available ? head(sort(table(ah$species),decreasing=TRUE)) ## what web service and local cache does this AnnotationHub point to? hubUrl(ah) hubCache(ah) ### Examples ### ## One can search the hub for multiple strings ahs2 <- query(ah, c("GTF", "77","Ensembl", "Homo sapiens")) ## information about the file can be retrieved using ahs2[1] ## one can further extract information from this show method ## like the sourceurl using: ahs2$sourceurl ahs2$description ahs2$title ## We can download a file by name like this (using a list semantic): gr <- ahs2[[1]] ## And we can also extract it by the names like this: res <- ah[["AH28812"]] ## the gtf file is returned as a GenomicRanges object and contains ## data about which organism it belongs to, its seqlevels and seqlengths seqinfo(gr) ## each GenomicRanges contains a metadata slot which can be used to get ## the name of the hub object and other associated metadata. metadata(gr) ah[metadata(gr)$AnnotationHubName] ## And we can also use "[" to restrict the things that are in the ## AnnotationHub object (by position, character, or logical vector). ## Here is a demo of position: subHub <- ah[1:3] if(interactive()) { ## Display method involves user interaction through web interface ah2 <- display(ah) } ## recordStatus recordStatus(ah, "TEST") recordStatus(ah, "AH7220") } \keyword{classes} \keyword{methods} AnnotationHub/man/AnnotationHub-package.Rd0000644000175400017540000000061213175714307021564 0ustar00biocbuildbiocbuild\name{AnnotationHub-package} \alias{AnnotationHub-package} \docType{package} \title{Light-weight AnnotationHub 3.0 Client} \description{ Client for discovery and retrieval of Bioconductor annotation resources. } \author{Martin Morgan \url{mtmorgan@fhcrc.org}} \keyword{ package } \seealso{\code{AnnotationHub-class}} \examples{ \dontrun{ library(AnnotationHub) hub = AnnotationHub() hub } } AnnotationHub/man/AnnotationHubResource-class.Rd0000644000175400017540000000134313175714307023010 0ustar00biocbuildbiocbuild\name{AnnotationHubResource-objects} \docType{class} % Classes \alias{class:AnnotationHubResource} \alias{AnnotationHubResource-class} % Constructor % Accessor-like methods \alias{getHub} \alias{getHub,AnnotationHubResource-method} \alias{hubCache,AnnotationHubResource-method} \alias{hubUrl,AnnotationHubResource-method} \title{AnnotationHubResource objects and their related methods and functions} \description{ This class is utilized internally. AnnotationHubResources are created as an intermediate 'on the fly' process when loading a resource. It's accessor methods are used internally. } \author{Bioconductor Core Team} \seealso{\link{AnnotationHub-class}} \keyword{internal} \keyword{classes} \keyword{methods} AnnotationHub/man/getAnnotationHubOption.Rd0000644000175400017540000000440213175714307022065 0ustar00biocbuildbiocbuild\name{getAnnotationHubOption} \alias{getAnnotationHubOption} \alias{setAnnotationHubOption} \title{Get and set options for default AnnotationHub behavior.} \description{ These functions get or set options for creation of new \sQuote{AnnotationHub} instances. } \usage{ getAnnotationHubOption(arg) setAnnotationHubOption(arg, value) } \arguments{ \item{arg}{The character(1) hub options to set. see \sQuote{Details} for current options.} \item{value}{The value to be assigned to the hub option.} } \details{ Supported options include: \describe{ \item{\dQuote{URL}:}{character(1). The base URL of the annotation hub. Default: \url{https://annotationhub.bioconductor.org}} \item{\dQuote{CACHE}:}{character(1). The location of the hub cache. Default: \dQuote{.AnnotationHub} in the user home directory.} \item{\dQuote{MAX_DOWNLOADS}:}{numeric(1). The integer number of downloads allowed before triggering an error. This is to help avoid accidental download of a large number of AnnotationHub members.} \item{\dQuote{PROXY}:}{\code{request} object returned by \code{httr::use_proxy()}. The \code{request} object describes a proxy connection allowing Internet access, usually through a restrictive firewall. Setting this option sends all AnnotationHub requests through the proxy. Default: NULL. In \code{setHubOption("PROXY", value)}, \code{value} can be one of NULL, a \code{request} object returned by \code{httr::use_proxy()}, or a well-formed URL as character(1). The URL can be completely specified by \code{http://username:password@proxy.dom.com:8080}; \code{username:password} and port (e.g. \code{:8080}) are optional.} } Default values may also be determined by system and global R environment variables visible \emph{before} the package is loaded. Use options or variables preceeded by \dQuote{ANNOTATION_HUB_}, e.g., \code{options(ANNOTATION_HUB_MAX_DOWNLOADS=10)} prior to package load sets the default number of downloads to 10. } \value{The requested or successfully set option.} \author{Martin Morgan \url{mtmorgan@fhcrc.org}} \examples{ getAnnotationHubOption("URL") \dontrun{ setAnnotationHubOption("CACHE", "~/.myHub") } } \keyword{ manip } AnnotationHub/man/listResources.Rd0000644000175400017540000000071513175714307020274 0ustar00biocbuildbiocbuild\name{utilities} \alias{utilities} \alias{listResources} \alias{loadResources} \title{ Utility functions for discovering package-specific Hub resources. } \description{ List and load resources from ExperimentHub filtered by package name and optional search terms. Not Implemented for AnnotationHub. } \details{ Currently \code{listResources} and \code{loadResources} are only meaningful for \code{ExperimentHub} objects. } \keyword{utilities} AnnotationHub/man/readMetadataFromCsv.Rd0000644000175400017540000001626713175714307021313 0ustar00biocbuildbiocbuild\name{readMetadataFromCsv} \alias{readMetadataFromCsv} \alias{metadata.csv} \title{ Reads csv files of resource metadata into a data.frame } \description{ Reads metadata files located in the "inst/extdata" package directory into a data.frame. } \usage{ readMetadataFromCsv(pathToPackage, fileName=character()) } \arguments{ \item{pathToPackage}{ Full path to data package including package name; no trailing slash. } \item{fileName}{ Name of single metadata file located in "inst/extdata". If none is provided the function looks for a file named "metadata.csv". } } \details{ \itemize{ \item{readMetadataFromCsv:}{ Reads a .csv file of metadata located in "inst/extdata". \code{readMetadataFromCsv} performs checks for required columns and data types and can be used by package authors to validate their metadata before submitting the package for review. The function is used internally by \code{AnnotationHubData::makeAnnotationHubMetadata}. The rows of the .csv file(s) represent individual \code{Hub} resources (i.e., data objects) and the columns are the metadata fields. All fields should be a single character string of length 1. Required Fields in metadata file: \itemize{ \item Title: \code{character(1)}. Name of the resource. This can be the exact file name (if self-describing) or a more complete description. \item Description: \code{character(1)}. Brief description of the resource, similar to the 'Description' field in a package DESCRIPTION file. \item BiocVersion: \code{character(1)}. The first Bioconductor version the resource was made available for. Unless removed from the hub, the resource will be available for all versions greater than or equal to this field. \item Genome: \code{character(1)}. Genome. \item SourceType: \code{character(1)}. Format of original data, e.g., FASTA, BAM, BigWig, etc. \item SourceUrl: \code{character(1)}. Optional location of original data files. Multiple urls should be provided as a comma separated string. \item SourceVersion: \code{character(1)}. Version of original data. \item Species: \code{character(1)}. Species. \item TaxonomyId: \code{character(1)}. Taxonomy ID. \item Coordinate_1_based: \code{logical}. TRUE if data are 1-based. \item DataProvider: \code{character(1)}. Name of company or institution that supplied the original (raw) data. \item Maintainer: \code{character(1)}. Maintainer name and email in the following format: Maintainer Name . \item RDataClass: \code{character(1)}. R / Bioconductor class the data are stored in, e.g., GRanges, SummarizedExperiment, ExpressionSet etc. \item DispatchClass: \code{character(1)}. Determines how data are loaded into R. The value for this field should be \sQuote{Rda} if the data were serialized with \code{save()} and \sQuote{Rds} if serialized with \code{saveRDS}. The filename should have the appropriate \sQuote{rda} or \sQuote{rds} extension. A number of dispatch classes are pre-defined in AnnotationHub/R/AnnotationHubResource-class.R with the suffix \sQuote{Resource}. For example, if you have sqlite files, the AnnotationHubResource-class.R defines SQLiteFileResource so the DispatchClass would be SQLiteFile. Contact maintainer@bioconductor.org if you are not sure which class to use. \item Location_Prefix: \code{character(1)}. Do not include this field if data are stored in AWS S3; it will be generated automatically. If data will be accessed from a location other than AWS S3 this field should be the base url. \item RDataPath: \code{character(1)}.This field should be the remainder of the path to the resource. The \code{Location_Prefix} will be prepended to \code{RDataPath} for the full path to the resource. If the resource is stored in Bioconductor's AWS S3 buckets, it should start with the name of the package associated with the metadata and should not start with a leading slash. It should include the resource file name. \item Tags: \code{character() vector}. \sQuote{Tags} are search terms used to define a subset of resources in a \code{Hub} object, e.g, in a call to \code{query}. For ExperimentHub resources, \sQuote{Tags} are automatically generated from the \sQuote{biocViews} in the DESCRIPTION. \sQuote{Tags} values supplied by the user are not be entered in the database and are not part of the formal metadata. This 'controlled vocabulary' approach was taken to limit the search terms to a well defined set and may change in the future. \sQuote{Tags} for AnnotationHub resources are a free-form field of search terms defined by the user. The package name is added as one of the \sQuote{Tags} before the metadata are finalized. Multiple \sQuote{Tags} are specified as a colon separated string, e.g., tags for two resources would look like this: \preformatted{ Tags=c("tag1:tag2:tag3", "tag1:tag3") } } NOTE: The metadata file can have additional columns beyond the 'Required Fields' listed above. These values are not added to the Hub database but they can be used in package functions to provide an additional level of metadata on the resources. } } } \value{ A data.frame with one row per resource and columns for the Required Fields described above. Additional auto-generated columns, e.g., RDataDateAdded and PreparerClass may also be present and are used by internal functions when generating the final metadata. } \seealso{ \itemize{ \item \code{\link[AnnotationHubData]{makeAnnotationHubMetadata}} } } \examples{ ## Each row of the metadata file represents a resource added to one of ## the 'Hubs'. This example creates a metadata.csv file for a single resource. ## In the case of multiple resources, the arguments below would be character ## vectors that produced multiple rows in the data.frame. meta <- data.frame( Title = "RNA-Sequencing dataset from study XYZ", Description = paste0("RNA-seq data from study XYZ containing 10 normal ", "and 10 tumor samples represented as a", "SummarizedExperiment"), BiocVersion = "3.4", Genome = "GRCh38", SourceType = "BAM", SourceUrl = "http://www.path/to/original/data/file", SourceVersion = "Jan 01 2016", Species = "Homo sapiens", TaxonomyId = 9606, Coordinate_1_based = TRUE, DataProvider = "GEO", Maintainer = "Your Name ", RDataClass = "SummarizedExperiment", DispatchClass = "Rda", ResourceName = "FileName.rda" ) \dontrun{ ## Write the data out and put in the inst/extdata directory. write.csv(meta, file="metadata.csv", row.names=FALSE) ## Test the validity of metadata.csv with readMetadataCsv(): readMetadataFromCsv("path/to/mypackage") } } \keyword{methods} AnnotationHub/tests/0000755000175400017540000000000013175714307015523 5ustar00biocbuildbiocbuildAnnotationHub/tests/runTests.R0000644000175400017540000000005413175714307017474 0ustar00biocbuildbiocbuildBiocGenerics:::testPackage("AnnotationHub") AnnotationHub/vignettes/0000755000175400017540000000000013200446560016361 5ustar00biocbuildbiocbuildAnnotationHub/vignettes/AnnotationHub-HOWTO.Rmd0000644000175400017540000002635313175714307022515 0ustar00biocbuildbiocbuild--- title: "AnnotationHub How-To's" output: BiocStyle::html_document: toc: true vignette: > % \VignetteIndexEntry{AnnotationHub: AnnotationHub HOW TO's} % \VignetteDepends{AnnotationHub, GenomicFeatures, Rsamtools} % \VignetteEngine{knitr::rmarkdown} --- ```{r style, echo = FALSE, results = 'asis', warning=FALSE} options(width=100) suppressPackageStartupMessages({ ## load here to avoid noise in the body of the vignette library(AnnotationHub) library(GenomicFeatures) library(Rsamtools) library(VariantAnnotation) }) BiocStyle::markdown() ``` **Package**: `r Biocpkg("AnnotationHub")`
**Authors**: `r packageDescription("AnnotationHub")[["Author"]] `
**Modified**: Sun Jun 28 10:41:23 2015
**Compiled**: `r date()` # Accessing Genome-Scale Data ## Non-model organism gene annotations _Bioconductor_ offers pre-built `org.*` annotation packages for model organisms, with their use described in the [OrgDb](http://bioconductor.org/help/workflows/annotation/Annotation_Resources/#OrgDb) section of the Annotation work flow. Here we discover available `OrgDb` objects for less-model organisms ```{r less-model-org} library(AnnotationHub) ah <- AnnotationHub() query(ah, "OrgDb") orgdb <- query(ah, "OrgDb")[[1]] ``` The object returned by AnnotationHub is directly usable with the `select()` interface, e.g., to discover the available keytypes for querying the object, the columns that these keytypes can map to, and finally selecting the SYMBOL and GENENAME corresponding to the first 6 ENTREZIDs ```{r less-model-org-select} keytypes(orgdb) columns(orgdb) egid <- head(keys(orgdb, "ENTREZID")) select(orgdb, egid, c("SYMBOL", "GENENAME"), "ENTREZID") ``` ## Roadmap Epigenomics Project All Roadmap Epigenomics files are hosted [here](http://egg2.wustl.edu/roadmap/data/byFileType/). If one had to download these files on their own, one would navigate through the web interface to find useful files, then use something like the following _R_ code. ```{r, eval=FALSE} url <- "http://egg2.wustl.edu/roadmap/data/byFileType/peaks/consolidated/broadPeak/E001-H3K4me1.broadPeak.gz" filename <- basename(url) download.file(url, destfile=filename) if (file.exists(filename)) data <- import(filename, format="bed") ``` This would have to be repeated for all files, and the onus would lie on the user to identify, download, import, and manage the local disk location of these files. `r Biocpkg("AnnotationHub")` reduces this task to just a few lines of _R_ code ```{r results='hide'} library(AnnotationHub) ah = AnnotationHub() epiFiles <- query(ah, "EpigenomeRoadMap") ``` A look at the value returned by `epiFiles` shows us that `r length(epiFiles)` roadmap resources are available via `r Biocpkg("AnnotationHub")`. Additional information about the files is also available, e.g., where the files came from (dataprovider), genome, species, sourceurl, sourcetypes. ```{r} epiFiles ``` A good sanity check to ensure that we have files only from the Roadmap Epigenomics project is to check that all the files in the returned smaller hub object come from _Homo sapiens_ and the `r unique(epiFiles$genome)` genome ```{r} unique(epiFiles$species) unique(epiFiles$genome) ``` Broadly, one can get an idea of the different files from this project looking at the sourcetype ```{r} table(epiFiles$sourcetype) ``` To get a more descriptive idea of these different files one can use: ```{r} sort(table(epiFiles$description), decreasing=TRUE) ``` The 'metadata' provided by the Roadmap Epigenomics Project is also available. Note that the information displayed about a hub with a single resource is quite different from the information displayed when the hub references more than one resource. ```{r} metadata.tab <- query(ah , c("EpigenomeRoadMap", "Metadata")) metadata.tab ``` So far we have been exploring information about resources, without downloading the resource to a local cache and importing it into R. One can retrieve the resource using `[[` as indicated at the end of the show method ```{r echo=FALSE, results='hide'} metadata.tab <- ah[["AH41830"]] ``` ```{r} metadata.tab <- ah[["AH41830"]] ``` The metadata.tab file is returned as a _data.frame_. The first 6 rows of the first 5 columns are shown here: ```{r} metadata.tab[1:6, 1:5] ``` One can keep constructing different queries using multiple arguments to trim down these `r length(epiFiles)` to get the files one wants. For example, to get the ChIP-Seq files for consolidated epigenomes, one could use ```{r} bpChipEpi <- query(ah , c("EpigenomeRoadMap", "broadPeak", "chip", "consolidated")) ``` To get all the bigWig signal files, one can query the hub using ```{r} allBigWigFiles <- query(ah, c("EpigenomeRoadMap", "BigWig")) ``` To access the 15 state chromatin segmentations, one can use ```{r} seg <- query(ah, c("EpigenomeRoadMap", "segmentations")) ``` If one is interested in getting all the files related to one sample ```{r} E126 <- query(ah , c("EpigenomeRoadMap", "E126", "H3K4ME2")) E126 ``` Hub resources can also be selected using `$`, `subset()`, and `display()`; see the main [_AnnotationHub_ vignette](AnnotationHub.html) for additional detail. Hub resources are imported as the appropriate _Bioconductor_ object for use in further analysis. For example, peak files are returned as _GRanges_ objects. ```{r echo=FALSE, results='hide'} peaks <- E126[['AH29817']] ``` ```{r} peaks <- E126[['AH29817']] seqinfo(peaks) ``` BigWig files are returned as _BigWigFile_ objects. A _BigWigFile_ is a reference to a file on disk; the data in the file can be read in using `rtracklayer::import()`, perhaps querying these large files for particular genomic regions of interest as described on the help page `?import.bw`. Each record inside `r Biocpkg("AnnotationHub")` is associated with a unique identifier. Most _GRanges_ objects returned by `r Biocpkg("AnnotationHub")` contain the unique AnnotationHub identifier of the resource from which the _GRanges_ is derived. This can come handy when working with the _GRanges_ object for a while, and additional information about the object (e.g., the name of the file in the cache, or the original sourceurl for the data underlying the resource) that is being worked with. ```{r} metadata(peaks) ah[metadata(peaks)$AnnotationHubName]$sourceurl ``` ## Ensembl GTF and FASTA files for TxDb gene models and sequence queries _Bioconductor_ represents gene models using 'transcript' databases. These are available via packages such as `r Biocannopkg("TxDb.Hsapiens.UCSC.hg38.knownGene")` or can be constructed using functions such as `r Biocpkg("GenomicFeatures")`::`makeTxDbFromBiomart()`. _AnnotationHub_ provides an easy way to work with gene models published by Ensembl. Let's see what Ensembl's Release-80 has in terms of data for pufferfish, _Takifugu rubripes_. ```{r takifugu-gene-models} query(ah, c("Takifugu", "release-80")) ``` We see that there is a GTF file descrbing gene models, as well as various DNA sequences. Let's retrieve the GTF and top-level DNA sequence files. The GTF file is imported as a _GRanges_ instance, the DNA sequence as a compressed, indexed Fasta file ```{r takifugu-data} gtf <- ah[["AH47101"]] dna <- ah[["AH47477"]] head(gtf, 3) dna head(seqlevels(dna)) ``` Let's identify the 25 longest DNA sequences, and keep just the annotations on these scaffolds. ```{r takifugu-seqlengths} keep <- names(tail(sort(seqlengths(dna)), 25)) gtf_subset <- gtf[seqnames(gtf) %in% keep] ``` It is trivial to make a TxDb instance of this subset (or of the entire gtf) ```{r takifugu-txdb} library(GenomicFeatures) # for makeTxDbFromGRanges txdb <- makeTxDbFromGRanges(gtf_subset) ```` and to use that in conjunction with the DNA sequences, e.g., to find exon sequences of all annotated genes. ```{r takifugu-exons} library(Rsamtools) # for getSeq,FaFile-method exons <- exons(txdb) length(exons) getSeq(dna, exons) ``` There is a one-to-one mapping between the genomic ranges contained in `exons` and the DNA sequences returned by `getSeq()`. Some difficulties arise when working with this partly assembled genome that require more advanced GenomicRanges skills, see the `r Biocpkg("GenomicRanges")` vignettes, especially "_GenomicRanges_ HOWTOs" and "An Introduction to _GenomicRanges_". ## liftOver to map between genome builds Suppose we wanted to lift features from one genome build to another, e.g., because annotations were generated for hg19 but our experimental analysis used hg18. We know that UCSC provides 'liftover' files for mapping between genome builds. In this example, we will take our broad Peak _GRanges_ from E126 which comes from the 'hg19' genome, and lift over these features to their 'hg38' coordinates. ```{r} chainfiles <- query(ah , c("hg38", "hg19", "chainfile")) chainfiles ``` We are interested in the file that lifts over features from hg19 to hg38 so lets download that using ```{r echo=FALSE, results='hide'} chain <- chainfiles[['AH14150']] ``` ```{r} chain <- chainfiles[['AH14150']] chain ``` Perform the liftOver operation using `rtracklayer::liftOver()`: ```{r} library(rtracklayer) gr38 <- liftOver(peaks, chain) ``` This returns a _GRangeslist_; update the genome of the result to get the final result ```{r} genome(gr38) <- "hg38" gr38 ``` ## Working with dbSNP Variants One may also be interested in working with common germline variants with evidence of medical interest. This information is available at [NCBI](https://www.ncbi.nlm.nih.gov/variation/docs/human_variation_vcf/). Query the dbDNP files in the hub: ```{r echo=FALSE, results='hide', message=FALSE} query(ah, c("GRCh38", "dbSNP", "VCF" )) vcf <- ah[['AH57960']] ``` This returns a _VcfFile_ which can be read in using `r Biocpkg("VariantAnnotation")`; because VCF files can be large, `readVcf()` supports several strategies for importing only relevant parts of the file (e.g., particular genomic locations, particular features of the variants), see `?readVcf` for additional information. ```{r message=FALSE} variants <- readVcf(vcf, genome="hg19") variants ``` `rowRanges()` returns information from the CHROM, POS and ID fields of the VCF file, represented as a _GRanges_ instance ```{r} rowRanges(variants) ``` Note that the broadPeaks files follow the UCSC chromosome naming convention, and the vcf data follows the NCBI style of chromosome naming convention. To bring these ranges in the same chromosome naming convention (ie UCSC), we would use ```{r} seqlevelsStyle(variants) <-seqlevelsStyle(peaks) ``` And then finally to find which variants overlap these broadPeaks we would use: ```{r} overlap <- findOverlaps(variants, peaks) overlap ``` Some insight into how these results can be interpretted comes from looking a particular peak, e.g., the 3852nd peak ```{r} idx <- subjectHits(overlap) == 3852 overlap[idx] ``` There are three variants overlapping this peak; the coordinates of the peak and the overlapping variants are ```{r} peaks[3852] rowRanges(variants)[queryHits(overlap[idx])] ``` # sessionInfo ```{r} sessionInfo() ``` AnnotationHub/vignettes/AnnotationHub.Rmd0000644000175400017540000002063613175714307021615 0ustar00biocbuildbiocbuild--- title: "AnnotationHub: Access the AnnotationHub Web Service" output: BiocStyle::html_document: toc: true vignette: > % \VignetteIndexEntry{AnnotationHub: Access the AnnotationHub Web Service} % \VignetteDepends{AnnotationHub} % \VignetteEngine{knitr::rmarkdown} % \VignetteEncoding{UTF-8} --- ```{r style, echo = FALSE, results = 'asis'} BiocStyle::markdown() ``` **Package**: `r Biocpkg("AnnotationHub")`
**Authors**: `r packageDescription("AnnotationHub")[["Author"]] `
**Modified**: 27 May, 2016
**Compiled**: `r date()` The `AnnotationHub` server provides easy _R / Bioconductor_ access to large collections of publicly available whole genome resources, e.g,. ENSEMBL genome fasta or gtf files, UCSC chain resources, ENCODE data tracks at UCSC, etc. # AnnotationHub objects The `r Biocpkg("AnnotationHub")` package provides a client interface to resources stored at the AnnotationHub web service. ```{r library, message=FALSE} library(AnnotationHub) ``` The `r Biocpkg("AnnotationHub")` package is straightforward to use. Create an `AnnotationHub` object ```{r AnnotationHub} ah = AnnotationHub() ``` Now at this point you have already done everything you need in order to start retrieving annotations. For most operations, using the `AnnotationHub` object should feel a lot like working with a familiar `list` or `data.frame`. Lets take a minute to look at the show method for the hub object ah ```{r show} ah ``` You can see that it gives you an idea about the different types of data that are present inside the hub. You can see where the data is coming from (dataprovider), as well as what species have samples present (species), what kinds of R data objects could be returned (rdataclass). We can take a closer look at all the kinds of data providers that are available by simply looking at the contents of dataprovider as if it were the column of a data.frame object like this: ```{r dataprovider} unique(ah$dataprovider) ``` In the same way, you can also see data from different species inside the hub by looking at the contents of species like this: ```{r species} head(unique(ah$species)) ``` And this will also work for any of the other types of metadata present. You can learn which kinds of metadata are available by simply hitting the tab key after you type 'ah$'. In this way you can explore for yourself what kinds of data are present in the hub right from the command line. This interface also allows you to access the hub programatically to extract data that matches a particular set of criteria. Another valuable types of metadata to pay attention to is the rdataclass. ```{r rdataclass} head(unique(ah$rdataclass)) ``` The rdataclass allows you to see which kinds of R objects the hub will return to you. This kind of information is valuable both as a means to filter results and also as a means to explore and learn about some of the kinds of annotation objects that are widely available for the project. Right now this is a pretty short list, but over time it should grow as we support more of the different kinds of annotation objects via the hub. Now lets try getting the Chain Files from UCSC using the query and subset methods to selectively pare down the hub based on specific criteria. The query method lets you search rows for specific strings, returning an `AnnotationHub` instance with just the rows matching the query. From the show method, one can easily see that one of the dataprovider is UCSC and there is a rdataclass for ChainFile One can get chain files for Drosophila melanogaster from UCSC with: ```{r dm1} dm <- query(ah, c("ChainFile", "UCSC", "Drosophila melanogaster")) dm ``` Query has worked and you can now see that the only species present is Drosophila melanogaster. The metadata underlying this hub object can be retrieved by you ```{r show2} df <- mcols(dm) ``` By default the show method will only display the first 5 and last 5 rows. There are already thousands of records present in the hub. ```{r length} length(ah) ``` Lets look at another example, where we pull down only Inparanoid8 data from the hub and use subset to return a smaller base object (here we are finding cases where the genome column is set to panda). ```{r subset} ahs <- query(ah, c('inparanoid8', 'ailuropoda')) ahs ``` We can also look at the `AnnotationHub` object in a browser using the `display()` function. We can then filter the `AnnotationHub` object for _chainFile__ by either using the Global search field on the top right corner of the page or the in-column search field for `rdataclass'. ```{r display, eval=FALSE} d <- display(ah) ``` ![](display.png) Displaying and filtering the Annotation Hub object in a browser By default 1000 entries are displayed per page, we can change this using the filter on the top of the page or navigate through different pages using the page scrolling feature at the bottom of the page. We can also select the rows of interest to us and send them back to the R session using 'Return rows to R session' button ; this sets a filter internally which filters the `AnnotationHub` object. The names of the selected AnnotationHub elements displayed at the top of the page. # Using `AnnotationHub` to retrieve data Looking back at our chain file example, if we are interested in the file dm1ToDm2.over.chain.gz, we can gets its metadata using ```{r dm2} dm dm["AH15146"] ``` We can download the file using ```{r dm3} dm[["AH15146"]] ``` Each file is retrieved from the AnnotationHub server and the file is also cache locally, so that the next time you need to retrieve it, it should download much more quickly. # Configuring `AnnotationHub` objects When you create the `AnnotationHub` object, it will set up the object for you with some default settings. See `?AnnotationHub` for ways to customize the hub source, the local cache, and other instance-specific options, and `?getAnnotationHubOption` to get or set package-global options for use across sessions. If you look at the object you will see some helpful information about it such as where the data is cached and where online the hub server is set to. ```{r show-2} ah ``` By default the `AnnotationHub` object is set to the latest `snapshotData` and a snapshot version that matches the version of _Bioconductor_ that you are using. You can also learn about these data with the appropriate methods. ```{r snapshot} snapshotDate(ah) ``` If you are interested in using an older version of a snapshot, you can list previous versions with the `possibleDates()` like this: ```{r possibleDates} pd <- possibleDates(ah) pd ``` Set the dates like this: ```{r setdate, eval=FALSE} snapshotDate(ah) <- pd[1] ``` # AnnotationHub objects in a cluster environment Resources in AnnotationHub aren't loaded with the standard `R` package approach and therefore can't be loaded on cluster nodes with library(). There are a couple of options to sharing AnnotationHub objects across a cluster when researchers are using the same R install and want access to the same annotations. As an example, we create a TxDb object from a GRanges stored in AnnotationHub contributed by contributed by Timothée Flutre. The GRanges was created from a GFF file and contains gene information for Vitis vinifera. * Download once and build on the fly One option is that each user downloads the resource with hub[["AH50773"]] and the GRanges is saved in the cache. Each subsequent call to hub[["AH50773"]] retrieves the resource from the cache which is very fast. The necessary code extracts the resource then calls makeTxDbFromGRanges(). ```{r clusterOptions1, eval=FALSE} library(AnnotationHub) hub <- AnnotationHub() gr <- hub[["AH50773"]] ## downloaded once txdb <- makeTxDbFromGRanges(gr) ## build on the fly ``` * Build once and share Another approach is that one user builds the TxDb and saves it as a .sqlite file. The cluster admin installs this in a common place on all cluster nodes and each user can load it with loadDb(). Loading the file is as quick and easy as calling library() on a TxDb package. Once the .sqlite file is install each user's code would include: ```{r clusterOptions2, eval=FALSE} library(AnnotationDbi) ## if not already loaded txdb <- loadDb("/locationToFile/mytxdb.sqlite") ``` # Session info ```{r sessionInfo} sessionInfo() ``` AnnotationHub/vignettes/CreateAnAnnotationPackage.Rmd0000644000175400017540000003415213175714307024033 0ustar00biocbuildbiocbuild--- title: "Creating An AnnotationHub Package" author: "Valerie Obenchain and Lori Shepherd" date: "Modified: October 2016. Compiled: `r format(Sys.Date(), '%d %b %Y')`" output: BiocStyle::html_document: toc: true vignette: > % \VignetteIndexEntry{AnnotationHub: Creating An AnnotationHub Package} % \VignetteEngine{knitr::rmarkdown} % \VignetteEncoding{UTF-8} --- # Overview The `AnnotationHubData` package provides tools to acquire, annotate, convert and store data for use in Bioconductor's `AnnotationHub`. BED files from the Encode project, gtf files from Ensembl, or annotation tracks from UCSC, are examples of data that can be downloaded, described with metadata, transformed to standard `Bioconductor` data types, and stored so that they may be conveniently served up on demand to users via the AnnotationHub client. While data are often manipulated into a more R-friendly form, the data themselves retain their raw content and are not filtered or curated like those in [ExperimentHub](http://bioconductor.org/packages/ExperimentHub/). Each resource has associated metadata that can be searched through the `AnnotationHub` client interface. # New resources ## Family of resources Multiple, related resources are added to `AnnotationHub` by creating a software package similar to the existing annotation packages. The package itself does not contain data but serves as a light weight wrapper around scripts that generate metadata for the resources added to `AnnotationHub`. At a minimum the package should contain a man page describing the resources. Vignettes and additional `R` code for manipulating the objects are optional. Creating the package involves the following steps: 1. Notify `Bioconductor` team member: Man page and vignette examples in the software package will not work until the data are available in `AnnotationHub`. Adding the data to AWS S3 and the metadata to the production database involves assistance from a `Bioconductor` team member. Please read the section "Uploading Data to S3". 2. Building the software package: Below is an outline of package organization. The files listed are required unless otherwise stated. * inst/extdata/ - metadata.csv: This file contains the metadata in the format of one row per resource to be added to the `AnnotationHub` database. The file should be generated from the code in inst/scripts/make-metadata.R where the final data are written out with write.csv(..., row.names=FALSE). The required column names and data types are specified in `AnnotationHub::readMetadataFromCsv()`. See ?`readMetadataFromCsv` for details. If necessary, metadata can be broken up into multiple csv files instead having of all records in a single "metadata.csv". * inst/scripts/ - make-data.R: A script describing the steps involved in making the data object(s). This includes where the original data were downloaded from, pre-processing, and how the final R object was made. Include a description of any steps performed outside of `R` with third party software. Output of the script should be files on disk ready to be pushed to S3. If data are to be hosted on a personal web site instead of S3, this file should explain any manipulation of the data prior to hosting on the web site. For data hosted on a public web site with no prior manipultaion this file is not needed. - make-metadata.R: A script to make the metadata.csv file located in inst/extdata of the package. See ?`readMetadataFromCsv` for a description of the metadata.csv file, expected fields and data types. The `readMetadataFromCsv()` function can be used to validate the metadata.csv file before submitting the package. * vignettes/ OPTIONAL vignette(s) describing analysis workflows. * R/ OPTIONAL functions to enhance data exploration. * man/ - package man page: OPTIONAL. The package man page serves as a landing point and should briefly describe all resources associated with the package. There should be an \alias entry for each resource title either on the package man page or individual man pages. - resource man pages: OPTIONAL. Man page(s) should describe the resource (raw data source, processing, QC steps) and demonstrate how the data can be loaded through the `AnnotationHub` interface. For example, replace "SEARCHTERM*" below with one or more search terms that uniquely identify resources in your package. ``` library(AnnotationHub) hub <- AnnotationHub() myfiles <- query(hub, "SEARCHTERM1", "SEARCHTERM2") myfiles[[1]] ## load the first resource in the list ``` * DESCRIPTION / NAMESPACE The scripts used to generate the metadata will likely use functions from AnnotationHub or AnnotationHubData which should be listed in Depends/Imports as necessary. 3. Data objects: Data are not formally part of the software package and are stored separately in AWS S3 buckets. The author should follow instructions in the section "Uploading Data to S3" 4. Confirm valid metadata: Confirm the data in inst/exdata/metadata.csv are valid by running AnnotationHubData:::makeAnnotationHubMetadata() on your package. Please address and warnings or errors. 5. Package review: Submit the package to the [tracker](https://github.com/Bioconductor/Contributions) for review. The primary purpose of the package review is to validate the metadata in the csv file(s). It is ok if the package fails R CMD build and check because the data and metadata are not yet in place. Once the metadata.csv is approved, records are added to the production database. At that point the package man pages and vignette can be finalized and the package should pass R CMD build and check. ## Individual resources Individual objects of a standard class can be added to the hub by providing only the data and metadata files or by creating a package as described in the `Family of Resources` section. OrgDb, TxDb and BSgenome objects are well defined `Bioconductor` classes and methods to download and process these objects already exist in `AnnotationHub`. When adding only one or two objects the overhead of creating a package may be unnecessary. The goal of the package is to provide structure for metadata generation and makes sense when there are plans to update versions or add new organisms in the future. Make sure the OrgDb, TxDb or BSgenome object you want to add does not already exist in the [Biocondcutor annotation repository](http://www.bioconductor.org/packages/release/BiocViews.html#___AnnotationData) Providing just data and metadata files involves the following steps: 1. Notify `Bioconductor` team member: Adding the data to AWS S3 and the metadata to the production database involves assistance from a `Bioconductor` team member. Please read the section "Uploading Data to S3". 2. Prepare the data: In the case of an OrgDb object, only the sqlite file is stored in S3. See makeOrgPackageFromNCBI() and makeOrgPackage() in the `AnnotationForge` package for help creating the sqlite file. BSgenome objects should be made according to the steps outline in the [BSgenome vignette](http://www.bioconductor.org/packages/3.4/bioc/vignettes/BSgenome/inst/doc/BSgenomeForge.pdf). TxDb objects will be made on-the-fly from a GRanges with GenomicFeatures::makeTxDbFromGRanges() when the resource is downloaded from `AnnotationHub`. Data should be provided as a GRanges object. See GenomicRanges::makeGRangesFromDataFrame() or rtracklayer::import() for help creating the GRanges. 3. Generate metadata: Prepare a .R file that generates metadata for the resource(s) by calling the `AnnotationHubData::AnnotationHubMetadata()` constructor. Argument details are found on the ?`AnnotationHubMetadata` man page. As an example, this piece of code generates the metadata for the Vitis vinifera TxDb Timothée Flutre contributed to `AnnotationHub`: ```{r, TxDb_Metadata, eval=FALSE} metadata <- AnnotationHubMetadata( Description="Gene Annotation for Vitis vinifera", Genome="IGGP12Xv0", Species="Vitis vinifera", SourceUrl="http://genomes.cribi.unipd.it/DATA/V2/V2.1/V2.1.gff3", SourceLastModifiedDate=as.POSIXct("2014-04-17"), SourceVersion="2.1", RDataPath="community/tflutre/", TaxonomyId=29760L, Title="Vvinifera_CRIBI_IGGP12Xv0_V2.1.gff3.Rdata", BiocVersion=package_version("3.3"), Coordinate_1_based=TRUE, DataProvider="CRIBI", Maintainer="Timothée Flutre = the date of the Bioconductor release being used - 'rdatadateadded' >= today's date - 'rdatadateremoved' is NULL / NA - 'biocVersion' is <= to the Bioconductor version being used Once a record is added to AnnotationHub it is visable from that point forward until stamped with 'rdatadateremoved'. For example, a record added on May 1, 2017 with 'biocVersion' 3.6 will be visible in all snapshots >= May1, 2017 and in all Bioconductor versions >= 3.6. # Uploading Data to S3 Instead of providing the data files via dropbox, ftp, etc. we will grant temporary access to an S3 bucket where you can upload your data. Please email Lori.Shepherd@roswellpark.org for access. You will be given access to the 'AnnotationContributor' user. Ensure that the `AWS CLI` is installed on your machine. See instructions for installing `AWS CLI` [here](https://aws.amazon.com/cli/). Once you have requested access you will be emailed a set of keys. There are two options to set the profile up for AnnotationContributor 1. Update your `.aws/config` file to include the following updating the keys accordingly: ``` [profile AnnotationContributor] output = text region = us-east-1 aws_access_key_id = **** aws_secret_access_key = **** ``` 2. If you can't find the `.aws/config` file, Run the following command entering appropriate information from above ``` aws configure --profile AnnotationContributor ``` After the configuration is set you should be able to upload resources using ``` aws --profile AnnotationContributor s3 cp test_file.txt s3://annotation-contributor/test_file.txt --acl public-read ``` Please upload the data with the appropriate directory structure, including subdirectories as necessary (i.e. top directory must be software package name, then if applicable, subdirectories of versions, ...) Once the upload is complete, email Lori.Shepherd@roswellpark.org to continue the process AnnotationHub/vignettes/display.png0000644000175400017540000051453613175714307020562 0ustar00biocbuildbiocbuildPNG  IHDR m]sRGBgAMA a pHYs(JIDATx^TUgr%AR4V,lEĎOn0뵻__T,,TT$;kz?3wݝX:q8gsMGd &Sժvʞ>3v}o_@x?3aWdF1lv`hj+l5!S;oQs>ָW/5 7McXۿZ\a|svy}uku4BZD?~1ۮ~>X A {=nCi2opg7pdWp ɰt[t"gȇX >j=\>x߫_EE%1tai97^C?{a\5Umu0`,_}k8>HQr Y>U/4:%}yT/"B8{:>&~cz%h'b_1Qp(={vkݟӁ.>ʹ幣` %4hɘ:­n8Ci>ܴEnqa+I}S2 ]N^e[e;\zB_w$]akgӮ gh[uvÆSs|8CyD]9>t<˜qcBE9R&_M ,]0.)>x:Oh2ư<"ָDDDTv6j0ho؛7\nݕ؝y ӶIJ'@:Hߕs?͞Z> m 'L;DDDDj$w`/QѫŲ/1Iͻl‹~]'՘7tgiB 9_jʱĚ[폖Gff>Iͫ]`j3bG+H175 ήf0o g^:Cc}~}uݒBZ>V1V-'_谨'2d]m& 9`pK3IRNB:rj奏]j5<\55I3I~CpyD 6c$׸˂C;fs`o&7߯XLrL2glE5@pB3 |C!tY \"""""""":|L'?L ׂDO~ bdCρg"98NeVy6YTr_v{ 0V^\^m03iOЋK,+nt+1{mhҵmS~Ĝ u<㬻? Vm;R~uW?n$c|6E~^(+OB>YX;c5o[pV`}6c%Tg 4S,/wFmSBnЮa2KKbE4NNCТU3W`HNH8|&|땂 ѻwom:@e<2!!M4ѩeHLJI~6 7`SN:a8!u}4\(*FAC!Ծ5zڳ5*K-{$sJ.yP9=gwBٴ?0%.} ө TW rQg^kk[biu^FJT4<' fP=9/GoNvUN($"""" .3j^I~HWcLtD'h4w.#h,gZطÒ]3pޑ}5;t'/*?荤唰?Dss{9UDG?zUE nõ:aU @~:/_IWK筮ޏ$Jcs<W_=!JΪ4,++A+<_jqI@K^e2^dzJ,:pxкuk]{LD 77W).-%in)Zj#<NUA1H]7zc^wf>T`kAJ*B:jblS:j=,-C_ }V_ܺŕPI&6ۛPQ]D (֤ 3'Mqcs7་9\s<_VX uc}T,4޿eK啕(. /Cq'd /:K)/ ,[=&v}.#cձ) `HY݁}b忳lǯX|3қɾ8ΰ t",6Q34*[p2^~xہ_BÉΈgc$"Xy*ʂ㷯ˡ>e\~yVq0zY [).`rJ{;gʻ\jd\G7 Q~ 5i!_͌-HJjxS:,6+\XH̴lAoȓ7n;&IIIغuZIҜn>c6!9Ѯ Ehۮ<sAm۶U5Ժ`mAmBrH߂0ꑹYq;ng[Z1_7~[fevr2 W 1CVĩy7w CG]Dى+2 nhsvH+d%1t`i;<+} ˀuڻGՎ_vZ }=(qj?{/ G{GI: NQ|..8ڤ.XMkNg&Cm&jYJ8i,s/}椐tpʊw?k1b򕵈xvxrx`;չJBo*o<|z}gF˟ăC1/t:06kht{휛"vһ3lǯpzꚧq_? ˋxCa?64&} NԶt=pefwr\%UE&lsвML8SmƘ P1YaMBL <'CO :ȵ`/#+X8.3*YPN͐s;S/JXN'9 m(ۄeS+{ ZE$UZZ;o֬Ǥkɓ'%֠A̗vᤓN±={{'$鷬.Pde F dK@ff*RjOl>8C̨p*\x7>*PV=*݉{ơ)!tI€oèPQ?G072lNÍx4x$u88ܥE((,B 3(f;GmRyeM_Yk", Xp7o.B'F݃{ --.Z\rŵ'DˣuӠw(\ &?~=.u9.}qz%ٌ5;b=A:3:gKakn ΂'{e}к}{+/OfWX[+^8CZ%fVw /35.YZvu1KWoy#ozܯ98m&?,v )#;z64Ó}sdfL[؎nYs ɨPb lρ$[l[ pPs?^rܥ%/In5<^S"$Ae_b:pCNaxG~|eL$[s͋j=oŸGDa :g5-[cJn8bڟ>g۫}ziKupf%VO7܇G& Uz^vzW=O ~f1 kԜ4<>B)BMw_3i>?-HXU9‹ʭ0Wڐ)h׽'Vm݆Ev9(T"9-7` Kl@/&A)k͚5Xb-[?SNŌ3tǥKbz> `˥a9#o00 ~ILKK2&vU}[R>:l",_^%f$¢mk-f8WOK D#ӛ!ê W끹qd%IfxUAk;u+;懯ŇF[=͎$e`B|J"Ғ #g\r"ғU^1j|JRm@hc!^T 65:,dk.Q(k 7..+2>Mːlu?eze!]_yflU`:ݵ3-B?oi &*wlb]%^j|c[T@`>|[Lqx4LQ6+>lV|x\2:\&[Rw n>:ecbӪOf1WԸ;ozBnu<È^G=F˱G!UeWzn}I] HҿoQRkgTYRVΪG݋Nh*38刏ybպ1DϬmje3}kL>PSTaaVl]#R_ǭiӑW a9_۶!e;V;UAnT2.N7k&X=0tP}8#лwotM6'ɤЄ'$#$!5ŤƗ6$X&2e}RkL:W#饫3f0IN^u>i&~=} ,">5֪"p|;xƋou!3V塘MR43a}٪m b>ѯw.0]͂'o?xڞ uY?7<8DUS10DX[uUWk;LRy<(/s ]٨c[kq:_[sXtIHՁJXz" nol.-ES$ABsx=x(O's^{_n4!. ٶ|Ct﷐igع^:]ۿl{:WM߮jr=D4oh'vl u]Ht#@ Xo3qԢ.jjl`I7Xvw 76U %+G6B?9M2%,tVXN3| HIKZ2,/y/+ nI!RdVU$I KO1HII._,#A M ꀚ*ZcR{Lb$pZTPݒ'>*OьC׋ݏ^G_{4Y`ϟ`.{2^s2•B?H<}xp`=ڀdl9Yk6yb.[m{gW2M.R#vh5:m $bX/c%5;*+iLgBOw!Ψϛ9'SuǠڵsv\*Yԙ .%ͶD$ b)ğ+}U~+v@WDMM0Ǹ~$t#E3x奧} GG93r Gpc'|5ƍjMB95|zjs8Oj9KWgaUߩϊ}=*A֭9ND>;fSQ>LV,]@sa?)|@i/ OB ߌ.'Jmp'Z4Hc? g#Y&(.ި=UbfTԌ$UԪf $3mHԔdiu^reNp衇9/'B]ʘVSQj-Ή9>G?UR4fVۖ/r}VX< nLXxll)cM>86au0ـb/!,Nm%%p<-(jc@TSbbٻ2ڼkGOnPhC Mr,qn'l30( бCz oEP[5g;Qyf/.kZs;t҃zu9VĂu/8ƶ֤Ǚ0Eݶ0 ƢIڼ1|G>~/]:_u9;,0YqjUy{\Tʹ)9fU?@&HU)yj F΁ 'IMKLI-ՄϨEp˹!(ZVx${,Fˇ>Wٛ"p2cl}4fRy9uM-gMj}ul^7*<[lHL`Xۆ_edMI{6؛mA&wBpwT3gEt7= >t,|+ cJj3~Gp(2ӑG SSHLGÍ^<V, "$,*4k˷zȃ,v-;B*[U<%HHOOU)St,jt,mGYY 6n܌xUJNIQJU,`RJMf#)IHiC]avbŊUHTxUhEkt Pn ny  RDž9/݁'fV"A?7~C/sCJT؟Y~wê60""""o" 3Y>ؤ7Ty£ٌ${~ʗ[\գO-ɯ8ߣ^ IiP | 7e"4b T&Ф1dW#pf<MfS`x~}'aF(\Y"npyob~258i~)"3 `Q`ؠ} #"""""""N EfbYƫ~q58PƋi,d|h0Z8PRD~~$T械EEt8t^Or< URrJ2kjJ veddHޘߡƍc˖-z܎jkPd; KNNFII.K^ ۶mڵ԰TAnӁL$$$0F$ؒ{DoCaA/,hڴ7mTfgg#//ok1FDDDDDD IA\Q߶-6oFaa9X$$& ==. .NS׌ILL Bt+//W׷ 6 8~_ZR8\\[ѴIt^@aDDDDDDDnpi)[`XC:]v9tM3Nfn[ fxx8 ؼir ,?ZD<0evaDDDDDDD`$ իנCڵ+JKKuM&I 5 qqq!Ñ_&˗/_~A۶ѲE dee؎b0( 3alي<ڷzvZ`FG2N`$ZaF%REJmx: d uB*TVrhH⤄DWU~q[lgU7fr-5 #"""""z.Ђ$4M4eIpDt0 w&aC`f͛a 7wKսJ*+`z0AeX\pιF\}8vjcZ)MNI dBDDDDDDDUäƊQaْNvFyYipG jmOE:msp)l8O+ɹXth 0 7SԴ?X>ń館@ntr/%5|* md`ʑ1܉\+|[m%&DDDDDDD]ȕQ8 lɸ͛7#33SޠvJ>\>@fjLbA=vt}%:KMT2Ay~:WKs` 3Sɸ#%BWVVFI>gu4p$.~WlvyyBi#_̂2pN\/ٿ Mnltd79or`j|XZ׏hOCYU>^lIjr~,U˄rnyȑ7oϟ#/n{Hٍb=MEfW '+j~sI9OMy|65vaGIRX/,,DMQ^Y de>y0!WKﯱxpaOLq-\}gyX98~ۇs,=n\.ָB M2xL~'#f3 XTk4G =F?O'O?Ӿ #L䪳r5= Cޚ`b\rqc.[c{tJ]aJ=_+M9q>_/GqBZ9f>|=;`gcsQa䫏xt7q &p~~]p.~ώ_?{' qht581a^v{f?6jDm$p0yqnBRI.ZnT9 #/T5,>=j0OgT垒qx%.]}.}]8q% .n"Mp™c%qŏkƈn6z%A- @_\\v]B F LAWOU54= =u%uNػ7X7 O>=}cCr]1pt+^/<:twZ7hG^ Cj-#VisN9=_~ޝ"ٕe#h6t4Ǜ`IHC|_x5huxhߢ=|o_Vr ǏQ]:P0Ӊ˞ g鄎Fz4 ÔW˜q8Th.jsBnrƓ@SRSuPq7q(!F0O$(v{ЪMkסf%^:/ nyA\sd64k>}3/o_a@+ H"""""""6r:^\R EjIs/ &@pdؘH/qhsT/V,\ShSu -Hk4Yrze: )AS3Ƽ)]FFr}Cmq.?\Ou&g01^cå˽ͪ5^$G J`>!!!^%%%^ ,= Uddd`ժUܹ`,Z1G5{ ddz$Q851%p8ԫ 6{`RVJ@8غes/O"n &X☏q]u3~=վ{ڕe2l={4Y5WO(kWiG~ʟ/LGC AQI֭U\Nykq.y-ޮ_XvíަN#gB^I= ^,_6)>?bߚ 8&ȼ,KDDDDDDDEEH.P.}j{CI% (=x=R-=5LNnhs]5+^Skߘ.}#F VMQj9nM0ʧˆK~ lCո00}8W`Y(In}[6q Z^{ ̓_»dpi$*U56XWmr.k.B\$O<%6ɧ> z{eX +K[Fd!}UƏ߽߹_w'zV|CؚjVI2,d#2,U1&v#X +drGKo:_K3VǺׯsR `ָG0qf}2t[pm 1y( 4-x{S`z:4Vߖb[~:.kLi0撖pק3jJL.\z0 58neB0"s}d⏿ CmDMTt?  +*6Uކ@&;.RT|w1^ZjE77ēn\ 3 ǝ63+v-7߄nݻa#;17nbݺu7u}|/14V<*Tݞ&ueꋶ E6&+ oD/* ;\q|n*>:j6ڣ87ƽ#%@6emhӦ~e9j^YBr[MLI q)"DV߁|Sj>oR/uÈ>٩`4R M™g R+Lxs!x<^#'O *V0aK5r/IQY_ctWg‰ugeeaeXd)вe $%% AjI M#x&Ai:ÌB%UV5kЮm;Tc"G]KY ۍo]tAF  :Rk*(FDDDDDDD%fZaB R# EEhڴ9iɕAjJޙ 01Փ 3͚5?|M4с/dAA;P """""""yKv]7ڰa#-_^{GnWs!%Xf;cgWbEj}IpqK.ß.EV-t VFf"""""""N$g_ZZ ep8ؼy3: 驩0LRh!h ɮٱN333QQQҲ2,\7nDfF6ld$$$ 11QB#"""""" {=~)mڵG6a1taR[E !M ujР֯_ڗizXx֭֬CEY JCDDDDDDDQv HIL@J$"""""""]g6QTR}jMM EV`ƖbV -9iHJjU;$LW:PPTr5oJ"eny'ZV 2u  XaI9e7@Vzٺ!#-tԐl7mANFz<^umP3Ljݸi)In֝lz9o**вY6ll:IDDDDDDDt@ZmXfڵj5KͰV Ih`驺S]!Iɍy[zlجu]FDDDDDIpV\\AEyYp MuO6Zv{sZ"3mXo`[>ms"%9)8v()+G:>۵b@hlی~ ?&ȡ'Q&1D7>%:Xqh.38vk*8XX Ik7nANvC$'%֔l^vzu&!R5{T^^@>Tt_$^Mgbڙ$].~ 7}ߥ2R^~!za<_iRPZ5fB?rQ~h{"y`Gƙ́P:]51NU9=t0o n$UJ~8#l6gZ%%$$nWIȫ쯱Mv8 W9&"$ɰlLۓe7M Mv ;WXђGCaɘxzkFv<!aVpvzSK7ufZ=j >R3pI UVVl/۳G|7jXo VTVmtUow'َĤ$Cy/'Ij*j$$dw{(+CO0La O9}U'Rؕ+Vbuzv!Ysu1̲t8Sqmfl,`qi9Ւ(%ItZt)֬YQZz$QO,((.Q'?Źn:@ftu;O?`tŚ`Y_lEEE(,,'|3f:XTb+C3$ lH|Y-`|)cKR.~wttƌ_v4PLNym :> 1ۂ֭[ 9i"s~`䟒}ǟyT+t @HJs/_qjM /XGg}^`3#t;? r=P}~}z;t8 -Bzzz0cZvhBZ@X׃˖b@]7bEqYHK Nn/Gyjt(ڵk1d4owT9) M#q1rߗ$6/WX!}= &(//P$Ҭi39~zs:$%"@pEWX5uEW_C*6]6#$ƚ5kT΢kpgtv#@(I\{ hܸ.8)Snܸo>92^^eww , ID*))SO?s;nC TZw~+JhO'C V{ ut$N9ПY5d^7nChԨ**^+!!1fXEpllrH 6"?[C%RSФI6.}>h̴v 4LR'afZ *(]QȱTK/ԦMk}r& (­gãזͲc_:(}`Caʕ:#'K/'l޼yKKV'A *uU]bРAՂCrx۷/g_#?MtɗbL8Qgٿ&"""]3gҵ)R33a=HBgXn\uI!{'ˏ߅ }7бA8Y6a=WYo>4ŠУE:,l^RԸ~h}^Mr] Ѿ>DNRZ_F g֭xzOBMqQ*HM&dQYT`dd"2bT - >`[o>|l'7T+&T6A= re~][icƌcwq+2t᧏ A&6g; Z}dxHO3d$|{)5O&l3I9nv{o<ޤc49{BxqjyNC>VیM!91ܟ _}"1)AGkܸڶi բ/B99rSFb܉m[Gl7uTd\jHɰP &'N,rcʍ!tE"uݻw-1نZP 5_:~wq… Icǎc=ףaÆz\].Ԏ쯐 oopDx wyС+9O\'^zi"YQÌhswbqxG{7U:in%.㏪0/[1Kl/H}ɏRعkcRQjj\ƾcnM#߁3׿U">|Z&?~U QʪqYqB鯈gFλjƙosj[%d;SLgaTǥ~|VҲ gDj]>`Ѣ￱yflܴ 5.3+SjCiY) uKV-[I&8k`XܵRa`W\ut*I nږ=G2%I]O/.sUeYE$7&)o8)o޼Yod2M:MR$iV*I0kެ9 |'XxIרܼ~߯ [mIa;W({tI" `y~(5P˭oj/7]u:O'FQ&ڇӘ7o*AVj ZRvر5ja E]ж][def3gnj2$)JrڗSLAvFp9݌m[F `Ŋz~ HcO3q 1FFm&#%"lŜ]$JM[oS.ƛ۩S'}\0<ܳN3&$ir]N@&7iب!N;׻C/9;w=cAAA!^} v5g8;jࢋqO#»}BWH&?&'5C6)y|<:UR||22*IUIi&kug? %#9T ZI^ҩxu^śoEqM_Фbȍ)۪U&pvv%MLC?4QT믿sT'[޽Ed뒏ZuoI`Q axp%_>y/W$|w<ÃcK~k >$}{HԷ"/cN--ǝwr c'^[_C/~O'U٠a8AH^'ˌdv -g!A;'5/ٹyz?6L0`sOGʐQ`h4DV:`:|L뉳F F捑ݦN>|`yQ4ǘ1724Sۯ/^x9<ģvVEe_SN>{HO0pp]ێvU>r|u}xxcꄓNǝNN<Î9G9z*J8]ΐw߿t8N$$&wM+V#x'A$9gL}I$rv?9^z~vw{OW\k)W}٫'<_U$xW;ktS>+?PS=uQ$;\,@+u;k\\ؒN9і_!0C%t/E%UjI?q2"""-qOȫ)_ HکnR\r톫qׅm"Y%{A^wi:C%w]SLZxoolO݆ۂgCORLU<=wݸ'0aVRl /5L@C#Z=ShP5 4}pG9XDC{)O{;f< ]NcLa:UL.֫^/?s N88ΰyJ-wGsϵiO_~ gcC̪vkw%IŜ2 _q5;"tT>Ӥ|) Hjţq͵aY"9)%w$; w5kWIDt]אJ(g׻ヌ;'~{ /Rypmkz$xr$#YæPGH^=푖eђ_m Nu6"veBN4l@(ir9t ~9K&$ښ.oYN&Y%J:.1R;LYnL$J;vvyݏ5 <'tdF#(7Pv' I`K.0y/}IT\?z>}oi pfLH_҅>d0:..}-B c]Z GH^?8,͡ Kԁ9-EAഋmW @jv~1|*??qؕ'6vr~x-#Ϲ|nFB}/WLۖX-{e=c۶8aп`|Q -{~~g]aȐ4?!Q\F仭|Z;O)2y<-RjQ7-m/#) wLg4<Y9%9r8"l_,+HDM # .l ZTwI^Df$MUP@-ѡ}{'J{U­[Bq̰u _݉R $]UnOLG5T7^R'\޻JA8Y|s=`]Zj:oeXr#Jw6uz2+V`UdExчG_^~O>.\qť: м-yݻ*K`4|+UTJ^l޴ۢRoۢMXH+ބx{*ԅ6Nr3ٚDY'%ظa#&DHe$IpJ*p!Q]HD9!ґt.XɅn43@nXiR)ÑI9$YF~$&AO_LxbA?~ߨJ#<^nVǖ:{GtSLZND__$>qDi$x%,Y34&CI4>꒏$Q&}c6y/dR咈`$g_`C^ixw1o =.2v$Gy,z衷KFypUԚ/3pZlیuK㛏F4BNķqZbxX[6`)ӟ^M 0kGt#-'`jQ`5Qŷ1G7Gɋa[!s`? =I_O*O 鲝z'fk֮We.HxmFM]h;C{\<@KS>UW|nI9SO^(Эdzf|IX$RiE* _z]V-?qJNNKɃj滫Iڣ{wݕY;aeXv g|Y"wfVuY₋Fs/.j}9q{^-u])66QX\Z+&qIEgik\w/QOYfŒK0$Y/ *HIs9GG3%"T=j}rKD 6L>|xp$%/_U7fzd?X{M7iF9} |A3fL r:Hg4h.IYG7߬mԆڝE_L3IoR]IGC xKKPuGSO$|v%iDDDt2Y?t!>[ RĐHigI!HIk O)hekfdOSw2k|UD RV4r9n8,+O>Ǟ|ei"?'tio{ǃ_=}qB@#:+מ~(*x?6[P_AD{T3V{_WP:yktλ#>}N7NIMA*ɽjQ(gU fѝt/e())Ve%2iUӤd/MdcժU6廫Ijɫ[&֡:Nӵd <.wW\ 9cl,w܃Nw,Q7FYi9yՅZQ$F+<07Tb/t&c9F_\RIjE$6'|^i6HDDDD;՘̯Zk@uGןcN헟%_|㤉4m.HXi,Rͷީa.MeR)ĎL(}xt _ʑҟ%+ѽS;DkIja}Xl -[D.]0d@Զ$ıCz>Jjֽ[:xrU GI YKroVC]TTv8=8u3= *ScVR#nҁ 6a˖Ju/`\F԰j]qڠeMdΝB"Y'L줐}jv)&?DbݧH hinzY8HHX_ZT@-7߈@EZsb @ugff῟OYRޖnmz[IDRRJH9\uݻw 5v7{B&\0 ՂJ Mr0wB<ؓhѲ9= Ip}I E-ʨ:$tŗIl]clÆxgt_pr|9 =ROIH'oM֭n)T2pHt-[}KTKf&`XEEaS7=&oHIS9nnu KKpZ]Yʴze &ѸyKנ{Ƕ:lTIcv5 + F"!>Q/ S0S;CDDDDDI!ȣ#0"5X$|J{I}F͐KcN>cfΜ9sk]I#H`>`X4^ͮ[gdžn7 5 Vlp 3!ƥe2m5!)2Q8%@B:kđ_PMst%&MKYm չA* `v۶nc5$`$}g>$P(V$(jWo *!! O#P_a]w]mݶ5W-iK!ףc9.+\QQ)#1-ht>r4 %""""X}ͯ&k$hźO#ZF̐IRr2V\JJ Fr*4np'e4֮eWmVI%`"}aE#e~i(4k4j|E!f<8X`6-U> 1jf mDz39Bjd{92,0i&5X!\ !#3%%ep]HS'j 9ZUFn︺'NgӺ ="Rܩe$Օ" Ri:bFi$7ʁZ-Z .\Y,4Ϯ#Ȱ{DDpgH_^ڒԔDT`-UjuiFmBJrJTY[jQV*j-$P{P(UDK2?d[Cɻm*ԴRxr*'xb~5GGzu IΕ4yIV #MGeWIwݕ z0)1>mu׌$y/2П\%fT˫.I)\ށY3,ҡMs`C޶+ ߂ûvRr7!))%l#%%%hߨ}/n:$ϧ+Gk*EUaN7,YYhߢY0d[݈m(۲Z?N ؇v^bD>%:XHs+l@VuE [bqذkՐ 6Gb|\`\ܮ%aDDDDDDTQm\6mC >etЦ]Pd+D"5`Ö|4LGƈod4NbKA r3ѪY#,+q uێLVD\n^[ qv4LEfz a[<(w8PPTmjJ R6'qv|fE%eHOM ڴS0,|3p^ _Xry}-fxdQf*,#""""""":ؘfTT:OS3  ye?N1FDDDDDDDD EfZl!aDDDDDDDDtkסsp(2 #"""""""Bjs ˯Ef+a""""""""?` Qa#ЧW/z*FyQF+OUW9A{Qq@[1D^& -\ɽqQ~+Gyֽ x |kX iy_L|870MX ۜE?^^ :=I9=u*^s6A'oBa~mx#y\s[Xq)OW=K`to0mGQ%KųD=52S {lY.yτǮĮ2.I+xavXꍸ48. |[kaoG{.87w?5cE;pb%Kmþz m> =|=+yw$~?vW2uN ~ťum>G!ƃ_Dk :lޅyw 1̓COpc@8qruZeI=d&3w=#^Zi!;L _yr0ٓv VN,~D9wW`fC_߂@CSֽ{%~/#lWV ' ? 'a3!;\ >SvmmXc/\;+`X$t:PXV5jbP0YVp8%l Aup4ƒv4=6LǪжDDDDDDD_08~,έϜ6F Z o ˜[ODΜ'qݓf"ƼxCxw1~d3x <<+>6C?`ݐ#/扸'1xqn|(ՙk{s h;x!d .}n>*ۿj}E'Oa:c|doq sX|pcZ"A3R=_x r0ʰi9G4Eߡ-73eš|^xՓh1!A n' _vZ.F_ޕ >YMÖZ_C8<8݄DhUAC٦M( ƾ>g_>qF<NO~JwX)>>r9Pt|>wg~5ĚpڻCuFa] 𚭰#/6f%=ǐg5 nIJ$,!eqW㸞]k1PXXCz"qX^G؜s,eş++/[?קנW #;u(zo|/>|ZPfdn6a 0 4=H4lh⛇3Qi~{\ }CG]c-78~\X;nćD}Ʌ wh`ʇ?_ɸjHVTb߁~gW<l(c-TsI.|3㻿`r1;O4ŝ šհ|(:o9rEO֮1ט1bU͋ra8퓂 m;زѫ{zr#ZC窦mfdtlj( 肥sM X'cx'X5an.aD넓1x{r{DNBٮlD]Gm [^z6B= Ny I0XF lAQq^;cc,{ }nƏoMG֙#!>8.e͍} 7#K?ECnGJh Һ9M~tԯxW$L\ܪzU'_yZ5.V^&s@dFɎРM ;r($VC۔a%O)Z넮`,9퇢SZ"'ngLx:ٸS_g 9eX0oc >sנјPx|U!w@.]%$un^H\4k9JV uó5=`n=+-(pn?p-Fvgd|9N>im;݊FG܄'~ߦwQkNAdÈ7jq!eN >-"`162РA#} l1#564: nVVu(^3o+/;tm)XQ\D  dž-a8.>.\{+˴aG5C1iC6OEVZ=&GwGً-,E'bG?YM"([Sˑ:8ypRs0qNqG߭?s#s`ntx ײڙcIeVU{鷯8IPA?{^vd6mdK|72j>9}o}_߿Nkw_턋.& cԅX8#dCNCcuUە-đCѥ}{.G_09(-!3_Rk(>ZkSfW$~u < c'p!h`,+)ܭE~v05)sŽoލ{~NLj+#=juE"""""""y?_L*[^~#񸎸qyyxQu( ^;kck<GY7?[dmCѸp˒}2xV<珻"uR)'nyk<0ǮW >7o}XCā߷# jtm!A5|hF%FL2~$"""""""Y; {zqhTl>3Tvxf y=HyW= [,0Ïpis;=& lr{~QWc@{hqSqowDjX3h;x!d .}n>*ۿRW<6Lb5›3=Wc~[ajI h\,X(|]l|C벟;z>vzݷ/J7θoG?TnӍ}p#WEq y瘞l,XuOSW;6GQwѢ93ykPTJVP5lcmhBi?w| M1 %N!j6"O͞C۔a%O)Z넮`,9퇢SZ"'ngLx:ٸS_g ʊ*6Dy=1Wi?w|fAJ* P3#u[$,S4hR6|} C8lt\ؐա%lcqp []ULvT386dc@Tdu달cyh~twR~"Fyo iUrPg 8Jm,AJmmȭӾ$"""""""5!fj^ y8|G,끮Y؛Eg,Ə+31wCX3/ߏgO?萓XPWAuѷ1)l ﱏ5ޱa@\v[dfW2.o>< nEC7tGwh6WԾSݸ`ĕxr!H0SrOxa ]}1}o y-gz9qjD|[ j6,#{icÒWWn;Ǎ݌\BwW฀|E_^cMDDDDDDD7Jp0{l3hR3@` Q` Q` Q`Tn7,KQu A%??wDDDDDDDDՙ& сN\lٲ͚5 %"""""""4g %:0IH&X"""""""L~%8LDDDDDDDDtPcaDDDDDDDDTo0FDDDDDDDDaDDDDDDDDTo0FDDDDDDDDaDDDDDDDDTo0FDDDDDDDDaDDDDDDDDTo0FDDDDDDDDaDDDDDDDDTo0FDDDDDDDDaDDDDDDDDTo0FDDDDDDDDaDDDDDDDDTo0FDDDDDDDDaDDDDDDDDTo0FDDDDDDDDaDDDDDDDDTo0FDDDDDDDDaDDDDDDDDToJpN CDDDDDDDDD{GFFFphp0@fDDDDDDDDTo0FDDDDDDDDaDDDDDDDDTo0FDDDDDDDDaDDDDDDDDTo0FDDDDDDDDaDDDDDDDDTo0FDDDDDDDDaDDDDDDDDTo0FDDDDDDDDaDDDDDDDDTo0FDDDDDDDDaDDDDDDDDTo0FDDDDDDDDaDDDDDDDDTo0FDDDDDDDDaDDDDDDDDTo0FDDDDDDDDaDDDDDDDDToJp^ðqFv6 YYYhڴ)L&Sp,k; D ɗ̊ jx,zf:do֬Yp,kw:8y<#11!`XѢE $$$l>p[ЎYb9;2Tt-8; |>*++n:~$"aAgF.]`*e5wzZWo~=sٳ&""}`B')J\.,\!CȯIDDD~G\HDD""""""""z0""""""""7 #"""""""zcMqIGO^?Tfmf(<vӁWٟ"?җ9.p> !""11cmNCDDD_ڻ0<{%Ƽnkmk²ȱ:y07*">4N:$tLfDDh*sqhWv{VtZ)>Z\+݉OׅGٲ0~(shX[1$ToS.alKDD;`ADDDD^Gy~ BE|ń߅K7o>7U/7nmOV-9Jû.‰<.Ȑ_cp>83uxm cI=d&3w=#^Z-_b$__GQN\/Ѿxݳ߲+{Ypq{7ks.Nu?^b VgNA{S%0k=>xo}8ƏEꋥ<5f|>^e*>K k6o-/@+XT~cqUJ.Y۪7s⼣!8>pϘu:8wp{W_7Ka 'F"gΓIbhqSqowX[aԇvt{Ld~*u9 l:s-7#7Ǎ{ָ#"#߳xn弗p[Vd:vx:x] 3]q,wr)8ccHDDDD{ Rcbhj|My :<_Q~]h@=$#LyPJyq=bܭ"-D߱̏S9X\?WV_ OEA9ح9iz35-zQ>07{_~:td|]8~O7\c?{Ɲ䙟cz~0;ph5VXL[,BO%R_}RB>wjuqEpOŇCj5""W#?=/q!^yQd{jQ4]Lr _!:0.2ȴ#qӍ#І0"""fÄ9]y5_ވOM.kƙ` 7򗯅y?tN76]}َXQABK }ON>,%k k7NM pWz`M:f{2BkÆ5j]Pr1;O4ŝ !T33l si7mսuCxc/Eb:dc<ޞ^=PV3QclEQ/v8>0qu典")D_..\_ho<Ɣ^cǸ[j=GNCDDDD+]weFWD4=l8uӥS^ o!Fs*a+W|팡m0guBQ0s̜C))Ԟ&X)w|UzqЀXa>ϿW_ד0wpq+l;O&{ck}Ԟ1pd"L}16|[BDDH]c._/a#K(DąֺUZk[ֶѪV{[q!e{/!(  }I=.ɓg?w#xjR 􎶙/2~ )D~6!"""BQ0~2_~cZDĈWcK' psx^B6t!֨޴4oާ%Qljl?ͪIe,KA?^)b(a\X^a*bQ,TR&OWc-x'1rTKF[  ᯃDD[T1`" rmًAPrIǿBm(Q,_!~ꌮӮ_IDDD 4fCax>3Gc_ᯇ1`@崛¼F1??˷py\Ly(SQ5TуcmT[a-;e\}/@VC8ҽAKcZ#~7qjLjQ$ |QI9^9.ϓH~up"[adZ4:s \ ayGEs^>SD#.$&Mh"Ƥ)qo_³iY+_3/,7"@~XHl@Z3>vNj}1i0|Yc@w# s&11gf|1y&Ģo`|K#Դ 'yeѠA}7GbV kd0Aj p>sG o Qo=CC,9$?3>u#1xPLz7^5t:s io0~{Ƙ[W߯ IޙHE t-Cѳ1!oV<'  R.K. 1ъ?QE)ֽ'j֬X&""WT(Tt%''CUeDDDDDDDD3 #""""""""` ÈHg0FDDDDDDDD:0"""""""" ΐ"N~:ajj\bcq;{NF}ŊCNR!""VT(TtߟsH""<3LϞ=Cbbrvz@X@DDDQh˧OrIDDZg)ɳ!((HNNVI$r-6]faDDDDDDDD3x$ ÈHg0FDDDDDDDD:0"""""""" `0taDDDDDDDD3 #""""""""` ÈHg0FDDDDDDDD:0"""""""" `0taDDDDDDDD3 #""""""""` ÈHg0FDDDDDDDD:0"""""""" `0)cYxü.XD؏icRQ0YV w_p=A2_z V*--ļOP?4 :y_t5 7d[I6CDN4F9ڏeHEvoeJFZ/_-\K+5-Uyy\KϮ-~PQ"hEj<*#yeHEސZ7 ;u7Tpaaa033St&HMM g)?v.g{*8t?r$"m~L{ːtVò;8Eg4U %MsM5#O_q-N@9(ۻ7ORÑw"ɐJHIIA\\b]A=otѽ9nst?{">Ê`anv\#JuAP@12Ki?MAf]1vdQ~4Sti^޵}Xx:DDC,?aHs >{ǧ?om洭)NAݳ%ɷAkn1ξRLT\ʫX<6=cAiyvT^ۜlONchSm?wBqۛtWY?_lX-_˵硓<`ퟟ}}yy”wqgD}ZcE.f^oU~Vk_lW9ٍc\ݺB)w?Tw;H{x0r[oSTiWXz\Rkdx}#} ʩN^6YWcǧoY MA4Nm(]j}?Ū OW {ǜ' {|..܄9;o`ܵt#د߿Wމ+V ΊDwb#2o%޳&ǣSK1ءPll{2cHԪ!~3CU!0yv<nObxVsŔIQŷ=p ϊ#wmvV#RC`\b8|snQ[,f,S,'0vB Hsj+< 3C.e*ثc0;|%PT\_/m}FS{3( ӏcQ f6`ȸjץӟgoQḳgL6I{;P$x5fm~=cI!7}J?M!E(ҝvە][Ԯ*ڽBNJ/>-y)N6 sw]"^:8_/u^aS՗j;ވ @vlx..;6`UIt:Cw8 S&%z`o%(_;*N9T,ˣGj1K~|,9ʈϤ>bpW寵DƍPJ{2}9aKW,??-_^ 3^ /KEq ^5u%{cXd֍+j,<W cm7V&vU*N$ɮ8-_{w4O-%>sydء :H+k yܗ.=0for|۱!E <ӸS· UUQXf1lX<܎-T6Qys? cXm=UO{R!u 1rnlް pl }yv Q=Lۺv-AO[ =Ԙ;ªA)x|9]ohvKP>glnirhWoy*\Nv 6~ngy((̱c:^\<[ *AoU6OSykNGUMtsG}Xow{/DȐ8GcaⱐuƹĻ퍨=#:Ixz_qjkQF~b]**Ȥ`^ ~jfYf@ժU2eS%J(_!7X#;5#vq9^nF <8^oPw+N?.Ѭ*+:uL$Uѩ3Wq? Ag/ LLjZ(VV'EhӲ%ZnHr]Wր{+ԷchzhJ4&DU>#1Gc`/~iZ~//zW9lOWn+~!T6`*OC'|KlPkF)y9\IȫSjdfw VgvQ\LOfvf+޷~%_U{us;+~muY;"*4{=˜_aRP R횧

:z2ԉ&0iqZ H•]pP%%r9ApGT2#d5*87^S XZ|W4MQvlgg+">\JRᨓ7 x^K_>F+hdb\u'V|g m5@\.\Vq{+$<= -vGobnQ 궸ʳfW#\RW@L#j֫z\p4N-zͤpZ~E݌b*K8DU>"/8 @Sao}xtĬ[YNS^۬Tyl tG7]0yʏn;ȋo][D)rHCvc k~mqKUz-ZcDc DK;*gye+H`Y+j{|.ѫ>Y/y繽 :GfN 놾hg-.:D=0z WM]q765wB~@mmm +:ŋ+?uFŗ ?C@ t?8$~kAX{uFg(A ? Q".<_O =A%Z%IQ2*wlcaj!t/1'}#'``-3ͤZff!8w; FaX'/wxDS=X9={LL{ttz*=++&c<_*_ BYϐSGEH$8!W|:o c"7v,p7_vq_w8o8ϝĝ(=I ~T)_@9\(gR Ö,Ÿ^pLK`Y2,D\%t["4U灸νגoOOɧ9K<|Rxe-E?zs*?^bk3-2N.e*$>O6piu\2[1o_d{*6gPIjY:ya#ZƘ1uq.]K_yϹʭ{e(tY2~ngw*~,5۸jUZ6OSclPccи}QN̨(8vwC3?lTr+IK]sЫ>ߞ>;ވ>XY @llZky]ޡoJX%]F(l[me]ʤ89 N]=QFIB4?\*g w啶+m*G]lgD#_IWx^?eH2}N֊kbYxB9ox2?WqϔFe:sѠM娋팈Tx=XVDsK૯ LP eH$:$$Dq3B*X^aaO0wP4H™Eaڜ=x C~_y)N`/Xm)G]mgD#hٷcQwU?K$? !uLt #""""""""` ÈHg0FDDDDDDDD:0"""""""" `0taDDDDDDDD3 #""""""""!D. @DDDDDDDDMD=xf=300"""""""" `0taDDDDDDDD3 #""""""""` ÈHgHr-Y8GT lrR^i;<.8뢁HDڎ`Yi-C"$i #?J^i#?sz.G~`9 XV *42Iq-^>x?y\puxmӞJ]D #""""""""` ÈHg0FDDDDDDDD:CcaB-3s,6c;\Gizް~u]iBͯ:ζBDT4Bb7[ ʕyNiĞƈ{{J|+V""]gI`Y\|A_\GNK\"Yʕ0難{:]+mE" oeJFpfhm%Ky8H\3]*@/4vSw0w ;=J"%֏ü.8 Z7 ;u7TT3;w|:."r[p||䗗[|!&cpsR4vS+ upDMXq<B1/v᧰reDuM<*)zwJ.q!R IQՁI$.Z3D&1JIr~)!DZ|U./p3{ͦheC]ziWE[d;.n<`s;'T.fk1vDAUBqiIb}<#pYPz9mkVo>LYEcCť ?>6. xu_FD)y :2݂"l` W.zP4F.X{T|}#/3Th5~#\$IS|:|Lo/c 0g%Q` **0reOuXJâ!0RA  qN[/{<6[BDZmRQ/:\Š|ۿ*C"M=`ڴ W%c*ЃUm#.I`;} Q⟖5Z>y#?].Qx*KY2]Į}w#)Ym'mސ&2J@q'Ą q3J2!9g7 DJlQ1b_>mqa<*9A~s?+% Tv4[ݺy aך}4Ŝ*A`̸UO"c׎%3ض"2C.e* _gDyI4Ovn=l{*=YS–m$#sF^~=㮫_n@$B*!S@RU8Nyk}3e!Asjnȇv~]ysSf߇%/e[$9Cvm}i-!*4 ElI/T)'c q;}"vcʯGejIJ( STɏ`إ8(5QD<Zq?FHn}֋ϳ(p3&oB~]Da putڂgZx?KcC^Zud$=uNٌ-8yu)89y=eOKahqѶ. ag_ӳAް_V|,#f^hSoRT7c`PB^нS?h!]]a+ ưw+{/=Fhk;tC`$vϮFD!Q32̫ǽѭod/v {_ *I~E=HAqMɃTD޹@1 ZѹU3% Ͱ{R"|BVнo4TiBS·'pKv ѻ_OKyᇛ/3}HuzofHzvW!֥CƮ2u %p'8ch=x8\1M|vAE;_I ߞ2t1c_!"$ ajo&ȟv{ԯjU}h~*eK(w?TwDDC@*.(\K6Jb[ebغyNA1-8ūGcbX8s_&sEq76o؆\ſew6iO*=u3@S>d<ٵOSäo)˰5@~bJؐV 52H}x)s8ʇ'bȏL3%}nODӒ`ȟxT|e"zV(5Fs/3q)Y|B:pxC5:y#sCjXcR|<Ǣ,,gAq({y BDƃwxW.sc=$|߬lET,+Nl*;i~h"?A~JNxS"d$n bF@8y*F@“Xn?P|KG8U1? oe[N|}K%A|),JNNH57_*}C@RYDH?r r݊u&w+.j*O~Cޥ=Qq'D~ 7$Ot7zC1{bEũ[9@񥇸GK%嘻q%D\Ue707W,% (H~!~eIE8p[UGˮ1tH7Ԑ_% 2c=TFGiߞ"qm\{) ғAbd1dQlrQmy nU/>V_އf!\Ө;~Up{i, }ۧ#f|bp1E1crVܻpTbRQ^=ԫ劄qmqP5UcX+(| EWNj/s#U1@ ;zYܮq^LGR2^ s,kZJ`V MWrJZǂt# !8:b̩Yg*kơAPE:y#KoMr-WfAF<~[{EʆXj|,9(Ss83*] լąظ|6 s7FN;IPQL$X}%gd S+`]J<wk5ze %hO,G=nֈde:8N=S 9#Ǹk)nQ=63J`'t-lZ˗,s #5a$FQE|B$sJWv0:+!"RҚPb&=>B ą#F jy*KpYԷv(Sc=Ċ&y^-P B4BPQYWHx%(_>[E\@u.0 {%ߢ%؏Os" NZ cj jcW4NJdUдNGvT)Ts+HoҨ/ܞ'DBd ڤ|ʖiB^WcK=(ֵ2yLX%Z\<8ssA1^=C) RߕWE]iJ9ѻH۰ԗz+WCckvx}žWi"/2Jx{`צM{n^>]7@<@'lgDDDbsG?r>} eg[ ]:AY^8' xYnKiD팈H$$]?IM2z0sAb1}XpW+-"]#U|>}WD?K(z/qr{cL~LBN:8 +liTe QJt"j0HF੭$iRBcݬ8pGStAX\܊(B%ϼQ-c D+z/aO0)1UCBO fi3 q^uדh%!hhL=*e#%oCo~!N_OAvh :qc,^ʥ?;!v lZ dEĝKoCHQqVq^YG?] ChUˡW{tc هsOOHǤ\Tq}%Wue!cʫtu[eZz ;f 0-jm껒q]mcX‘<ѷv3s$d#U>͗) 3]2>r7qkXz5JA?έ.je@!N gH/T/g)O?"7)b<<;y ˢLiK#d|{M+q~qN!}yXʷ'HZUoG\Pʼn2\^;[7ReVU Z=ޗʯs.q,q0QEe5 Yrs++oGPLWjz/~= jlx~n7F6n.czg*L3ˊ2PFD=4pבd[m&NxG(:s_"A*U%ak[+ )/`d%2E?5 l`zp@FIaJDs -[[a%Kڰ9X@ūbKH );b/U?- Ty!6w\JA!SпS $;ケ8!ESـH`Ȉ!(} @~UZ%)8:JO n8]cln_N@늡8$o=UoPHE8})6++^rōg21IԹ0WElޢ}-ܡFNGC8#ǿiT3# q\x 4^$=+ŵ@C)ԧ8=;:`9V://Mf{T`ÜImX:@{tխ׹i;iACAK"B"{scbb /K">6fd5 7* AuTw1E+A AХuKTt(VcLVڛ7͔b;op;M=>B|` fk׶T^9b&ģM~yg8D&e! R_4 K*\.AGMa۹VuYnpqzds!Qo5VuA/LoY|O>=IsˊYG 嫔R$FY3_K+gdnR~n>N$B&.p0*>8$g oA'Wu&,$f0M-$":)BcʼnH{uB`z؇ډz#R!-w>BM8]'Թ2,E2Bg[KeW"0+ilb6JǏ%zpt0Wz=C2"`7ޣ |=X""?Wmz} B-X|~ho%=*Z*7&nӋ`P)Jɐ`>a1k^DF <6Mյ.|o7vJ('br-/vVY}<}(_QP[!%KyH2"|3N?cl5Wwx?A陗Irb3$CXf,<.(/Ol7?,MB*~m%X?ߖeַq7A۰yն7)1U&h>x";'ŇL>5|TZfFSwNOK2 !U&wg(ȐO"!#*G]B=*Vy{^T`',2>Ej5mD@v7wAN%/UCinY6{K'wa|G÷Om'1ُyfNȨ_ЧIIH,)h5X 쪠$wO#%S~8B룼u>O).Eԃ{ed qlQ >k%d "^<\Q9R|u?<2Ȓ N L U3-Av_e{|Q(#Ԑi3X8/eMWxVL-ݍo8! 51RIă 20C~qсK߾)j-;4>s bnؖ<ڡaآbCDíGӒ¤#.AnlpZZq47oad+ILIqX;6QqDq;p-!|96 I}kmR՗o`a۪^k$0rigU>/m&R^ hVYШ`XcK$4ARΰW>JWi*< u\`kelJ9f:+'b^_U7µxvyMFf5` 1 K,b$poցK|z\q ~pvt: 6 HRDX2{:{X>8ֳkFpߟQܾ{n3p0 4. C5Ӣa&7{& xWa(NA~J| [7{bޏۗy=X%"`Σ ;s%Ui S=XTn77݇xG\߁rMW.TĿ FT|236ap ܽsW,ʙ3p!u 3X!/ q UźЩ5jXEKp?݃+w#x,X4)o(<:Nfܒ¬BTIl_/oxxv9v]r?B~ GZ,e=u;E܆Tq}TnR0_$Q5 =GZ>(mY C3rRʊ4E.5$4FRo~30pAvH 8'oV7<-_s(><2pR ʠ.."jRWDf%1þ{^lX/NƢ&0tMqs,&h F64LvjtR*>neUVeYɉsa&=KhAcl>˜"UVD$Z=H kLQfE)fxs4>C´L2tBelߥV=k7͢-ۙ\H\VPbX,Æ+mQCD=8l I •Ma Kw&N""*8B$}vlgvTl{KTPUVB؅'P&,yDADDZgsa< K< D }Ƚ/NliFڈ0"""""""z' 6IDDDDDDDD3 #""""""""` ÈHg0FDDDDDDDD:0"&D\LşDz pErE޼_}!cwcplWtk0F ]հ!J(&fS:#1 mdI@ aD:LbZ۶ ~U$֦6\MDDDDDGoH}\"" 9;쥻H &⁵ `ϲغi%ڏd/K a?IaϪع{롤{YX Gx|$WoG{8lZJ-sK&C pf0ݪ$z#%<./ 7nXeJ[B/ 3W)[6Q1jiuLE}Tq!.5"n .o[XLc\=q6u[4vQ6*{+U3fh,H˓#Y-\JHSxh_uN~a`_6mX)+X{U(c\"5i-X þEK0Yt,IзlÖCHQʫ~4ƉϷX"V))N'⪣?cXN#J(@z -Gӑ#PU8=[.!V|>$Rn`-Thb`X(jJJ0laC);ۮ N=\k&R[xZ4C932OEv.t S<{IU[%K>h3d wēt7KzBQ|6R-Ţa12bFÁHVr`KyX}WTk~ m[X)\}]ۢRYz}HśX9zE=ϊpý KU>&~\D~P ڠ}` 7aPu42qӹm'QqvfJmt.eVw:6r^E)N?A .+ B\QԫR_HH$A*7j M75& GK떨P vF'eRu؋{,1-1FR^%$05MƱ.|<-2[5e0" g5nbXbNEي6@bOOHO%vD onP449$Hx Wi`L0H5w/S#<+3W,?0$JAz^H÷ZqS=k8c(HI.k'J9 yRlX,seX&?ŋg[KyebF@Of%G~dDDDDDb0HIL+7Q*{aٸ!} fnvЭUZP!GH$xX9" ?Ej}㕏 0r+xA~ܹm'kb<=9ԱzWc9bka]0Fd{?[ 5q?;p-!|96 IɊtB+/#(2#.Anlp*YmgԻCE>̝l^+v$mXF}Nb &Pœ7È4'=yO܋ l`ww>BDb褴k pu|;m~ĹA7:F {ؽh .dz{}n_ܶӘ篐f:Nb=gcx8x:!$0PhNg&7{& xWa(NQa0HI`RZ8!x,,g8ߢ1 C}S\=> #j Z-Θ1Li:a.}1з9pbPMF6wqtD,^U@P}ۯܷ(Ĭ&: {?`@8uTMUy{I+՗#QCz[/° P.'(_Irvr BRUj4Om$7CDDDDDT #""nE{uRV uk_T+ƧlaDDDDDk #"|[gcasqE!DZ_cƸrܸ:gFp C*>(],}҃ $HR ?/!"zWjN1^%ɪdž{oEJ%\0_&Ś="""""~ QJ ƙQx|:l=ӗaS`RK/x93xWq\׀b9hhc>`dr0HR}fT'gaδ@i?ÈIԭ2 Ѡ+$'!oHc϶(RMEcuï93k>nAۆ^)x[sqӼ :5vJ{> DRT*.K`nym\.{[ o""""""`,=k8:CC=0U2"`o\%1G+74>%{f1D!<qW` TMނO!Z=R<)6U2L)L+2)^ZI""""0""*X}觅²Reat3ȐO"!#*G]BC4xNM=KDڃsƐʦ]DĄV; '0a  #"" sa< K< D i Fڈ0"""""""z' 6eDDDDDDDD3 #""""""""` ÈHg0FDDDDDDDD:&IDDEs®ʿ3qDo" YڰDIimUy~I6b0E0k0E.WVòdiK+IG\. ZՀY x &]fa@;~MDDDEa8O'""D}s'rvGGRhUʖCZ}Ѫ!BoH}\"""]v7,2-'!Y6[7đCq =`i cyHt9غa [U2_ycԮlRT3mqzغm'n0]0/ 6?,W)QP^=PLLJqUYxvq߈4J26%"3Èq7QStr*z4ÍS^,8d)oO€`h DHĩ`r4>9UسR!LYIq@(*4@굥X=0l<CF Ac8p8K zg?75OOpT 3DDDDDSu""* ͔س=<\­ tlB` fk׶T^9b!S jo:;ơ&6) id^@ S۷K/i|֮78}*!yAhR6uiHUZ!.vN s[&mжa,#"""""`dD> %LJ÷Z I ۻ5[zQiBPrz" +~_OVZZa[Kôe> aVJ?H_'.ك5+!Mt4aDDTpRqv/a1X"nղr/}z#n;3EKNv)CR< Lbb6pu G8.S4aDDT@ad @Q֎ļMϗѺic;@% ._?C@̍Xt7^ᘀxJ [̎ aDDT@0p<<.&f60;w!" ǎkH FtR~$0Ѓeņ(;vE?oMW-\L #""""D QDa_=z/6NcڣC}S\=> #j Z-3߰gh^*p 67AP ^  #""""HA\\""""""""mשrH{0"""""""" `0taDDDDDDDD3 #""""""""` ÈHg0FDDDDDDDD:0"""""""" `0taDDDDDDDD3$H(H۹)GÈ /$""""""""` ÈHg0FDDDDDDDD:0"""""""" `0taDDDDDDDD3 #""""""""` ÈHghh0L@ɱh AB\-t=DrUsc3RPJy D劷$ъhu2BCl2mB61q?"Ye,ZF=1fy*|_IX} n}fq&/٘԰X9qzohV_FX"!)'5uwո*ËDEѿmĵ0/x˛#2{={l_-^d`G~ ֣'V?bߋ"T2QOyn6KbihkWhIa̲""&h YIalÚB? k ^;vBBrUسc>FJnUUPSh3KxYfuj <_x\{!u G 2ŚhMA[Ʀ& \|)V 7~m-Vx\>;:/d k [* ش-M"<[PPqccx dkQJFaO3a8ӢvwyP^a9 Bp^j \06Ѣ+݄ŏԋª^B>SOu}iAr-EeN7%kǚB /Hsy}D=4ވrlJz]B$ͧ\ĖΔ&i= <3L@m86ۡm9n8<fbuX{%цXwurmߟxBylbJ{pĽHGYIxFG!Ot3Yi='Eӯzio9PXLe<* olhTK?O@2E&1F=0| H/Pcšգ|j7G/ nzhg %6ļF HxC0dv6$Iٴ9*[+IJRKCmi},d+5bN?~SڠOO,xkZk ؎um}@xg=bf;cgu仳Q>/n,N"J$Yu0m{ûnk|nF=.ըyGKo}>};-9ޗV]~nZr7;n*W?f~. Ʀۅkifֲ""͖}PƶsP d׶BX\̏Ԍ1 mQƭ \MѤ@s[?x\YO }hc{wڔY ɠgW<{>ĥ !,r- <\Qx`\NjQvE-[)מݡm[/829jBzE:/^ᆪ1[c!nH|K``i Vha0',z?UzIDATȯQ+$ V~ƊZ3g@Ų$/0onTvK&iPP̷hŲ]/&)6ؾKz,݌o®N_ZO 5u~_Iw.yhn|SF{@yiVHJ7Qk5X$`C(F+0I`5a-KeRiyQ0cg[KC(JKko8_&.9bpwZ+:_!,4=ibR՗\sɻUr79nzmee` W#*)loVmB BuAx{'SUj(M.+"^ gЬ  PAc] {q)x7Ԯ͆E}r 6N^>?ۑ0dHNHrP*m$IB\CǏCpl z6F]^O1y{NdqሓָUX=K4/Р0@͸iG_^ݑ>nhU5[ic#l|= 6E_ 5uåGсK(0Vo y)2X#<zyрmSyWYULmN~>[Z{א@hr%ӃT"NHד/nV }Y8)c`PQWQtb&úg>!hYzFK?#%}g/zyڛ7.ޤhUä~pwS![0C?`h=ѧbB&qx|\=cʐxH+h^RݗU]~jmJ9כs2-u chũm/m\gT[./C!hegSʟ4HϬ惈gJIsAKԵN0 Xա)/& @^Cal306)&-@YaL|."??Ē!? aB>XDADvQB!/=$q"#Z`LS : 'wgX`L<%-wd Dc IQܳJ&~Kźo7[e@F&oL(1G+e(QHO׺('(2:x<Jj:,:K`w;,wM]R7D}XXAϮ.:©Ï$Dk0n1']_5IHe%]49o|db;Oq#`ZO(Ṉ2uG>\߅ 7#r ;xN+Cߛ!U}S8c)q[kT{*]m}\y1)!8%۶F gwަD.Y>W eED,}1 b? ,Rlå0 =PݬԼD$ ABk ~wmty)OgF^ m`"Nɑ!3.ő8v}Kqb˾j"A~?lʿߒc!nO1LSJh7|&wM eƆXnZۆTjkny8KU;=\_ʭ7vRh):ym# oR2*0Wȗ4HG=sO¢d,]kSZ" _||7uk֬_ --_UI F.u.÷oB^Tq!7C[+}+ËK*㱴S_% m}N9+q#&֤ Z\GOƝ/6s#N-M`fZUtl<\`^eypV/LF~͌PGg ^JSe=<^ 7d! h :gPlu9gqqjYfb>ok_=\Cbj %E0 SIqڊ<]ISi_ck6T x|s?uFiW>7".,v+~|b6o K߷\{m0mU-$0SOcux-)&pn9*cFUVD)4*nsk;Ė@ہY)].m}:ߓnӗ?ood Ww74U-u0M;?=1is j[8ouc+q_i?GDhQ: +jÖçq^%Zz_~J-<ߏvb>`Cax>3Gc_ᯇ1`@e0/s1aeXw菪fA~(Ѹ?y8y:NYbv(P%52{Õ0c0l5,?|Mb%TD>Ƌ$9u4/oz:mKg_c}\K|?8V]Ͼ>9?aܲ=)2]J]njb雸yz5&_G5-_kRqq^6-)l Da7&MYp~,'M"$0Iu9sAqzdL9WO2>YnHې<ν/}:QUV*渝kUļ*:TMp Z7ؐ=1#'EH3hP0,FcGt.eiti_)t a߷Qa_Auz%'x&~6 Oƿ31_& VCp|9jV,^3aFR/0pٛaX?"FOţX9,hr/Ǥcodm7?2VZT($f51fLt/>3¤XⲢԶ,ObrJ040L|>~(us?oETI;h"wۣvsOD.Ő ̰L/o #嵳0vx:OªMu _ ۺI⾴Q肜Q ]89^ÿaзk| 捨L,4)od۹+")Ժ1~Z4 B{-Z;`bO3:1p;_򛛫MvjtR*>neUVeYɉsNMKپ0fHi R.Q6aE34iW6$ܞ xd鄨>XŔ4lgvr"ٗjsYBJ½y=~ش'[""Agi&Ir L"(%XY"ա,#0Y{zU[e;bۋ\_eEᕘ%*h m #"R) A翶|PL+Q1 JHMKGepsz_aڏ4aDDDDDDDD3= ÈHg0FDDDDDDDD:0"""""""" `0Hɂ7_>X\CT]0 Y"oޯ>/ iBwbPX.ە98Z"""""*< 2S$DZ}N-ށ63xlUWȒr5Èt } HW}[OO8Y_Ȓ.DDDDDGDNܶ>Ѩ09œ2D\ICZ=.(ٸѪL^7tlZZwqS,d+sY,:VMŴǓ/:K S0ٷ#zY01\荤.h#֓qI?oz޵д؜^TLYU}(9?7 ;,m#\IF٤agst{IKÜ/ymoi2+-ƨS9z'~^LV'o43{ڈ`KFM;sMqNG @u57/ Yksl'1ey4K|J]Cl[IXP,j/, ~/BҏbpwZ+:_!Lܔ\HI:>.2XDAQS`g>oX8e0s DȟTgK}Dz,݌o;qxF-S>uIl5OzS6Bt(,w46&7øyK1wL#ĭOc wpA0ZfAҁ0pjkODs/'""""1FCfT:5wz}P3^n}X!&(Yv$ lR5 `~e <|IuX?2-kTWþaZ/]؈sʣ|Aqrph+C"ĤrN4.ޤhUä~pe0Vo yXQԩR_A*zҜ/fTdm); ?<syvGi_UMOl%kpu4uF|.(נ;ڻJ`q6+JwSkD~zH0FL<yLhgb(]N&HLѺ$wa?bd̹.ʥߘ^bs0 qS{Ty]$00~s-u{&w#SbPUm#X҇d){BɄS_vFiRi+`Z7+b> C׎+8c֯;;&nLLhTȑ B戀L[Ͼ7l܆m۔{wR|v-0Cܶ(";2 L cy9w^;QAby ɇg'+oDDDDD0"c1sXh#C7p1 cgl;^ KB?>d {p~ ,]e,O%akk+>l`t5&M݂*Ymgx!]fJcp: k' BaI߳d6.0xv~{"C6trÈ4Ff;~q`+b0Iu9sAqzdL9WO2>Zpl8+_#ӷm3OcZ#~7qjLjQ /m);R¦@4vcҔ8q7/{bٴ,ʞjIkGs|| ńaݡ?)_DDDDDDǨDM1Swܞ?Ŕ !|e `bO3:1p;_XqSqYdӾĐVIg7z‰Q ]89^ÿaзk| 捨 SWc徝D֍Ӣh[BE{3¤XWگOQ"21q'$L5><&""""""aDDDDDDDD; #""""""""$Hg0"""""""" `0taDDDDDDDD3 #""""""""`C~W, HV+ c搎h\2EHq˿탖uĘ|2+Y.]+獔ЯKTPJyyGD q/"\|0"" ~7l 0%߈xh &l "% `C/|=g1掮FJuAu/ݬ1{omq`;w~H%ÈHk$P/ ZG`GƸBeY?kG~-pu Q"솺uoD_\ϫcCQ*m Tz@=їW`wZD_b۹7sdK :=#; iL^؀KEj* #""""z Q2G+$$<prf_3ò9ߡd F|,0&>Wbq!*{Hv2L){BɄ@Z&ƛGsFh:o+=cs'""""zIQ -\YL$r qnڽ0H aXuèAV\Lŋ#q0yB_4* zb0<(ۓCm9}h< ˏq&|$sp""""w4i#<^NH czx2>% %.RCH2,UAUpsHOAl wk}:uRo?3v(3}lw勈(O #"" !EQ?q;&N]ׯu.F~:>J6lk0e6+a/`ؼ/jXþqo?8v׎#z(M0K$Q"* f59La>_{b˰Uޢ>UWǟbϹ 8{p ? +O/#""""  #""!m) ƣ擥py L ~J\[lMd{xVIwfw8fwb=j7D_ YpIf51fLt/>3¤XoG%O =mĤ/G>s.ViaDDDDDJ"DDD*)v\4Cv5a|nOcP\Ά*jCDDDDT0""@l>7^EPK<86EC5XjaਨQQ3ÈH$!\}%4?c{yR+)jCDDDD #""""""""雷Hg0FDDDDDDDD:0"""""""" `0taDDDDDDDD3 #""""""""` ÈHgHr P.sssS.i m;rODDDDDDDDڮSSeDDDDDDDD3 #""""""""` ÈHg0FDDDDDDDD:0"""""""" `0taDDDDDDDD3 #""""""""` I"wQrIgƑV#G88KInyI_Ac(Wdv࿿ϡT0S$ׅ|J(%Dgw]Prp+m =ʢ?i?w/Kµ }<ð#5ܳߘ5c76A ôƹMb%سs#.\W oR^BlYwS'"|:iQ>z:Oy~Qb.X@8l6oX'"(.%t8w_GNC| (ТK>%ٻ&?㟤d#PVK67P"*{)C@AQ2 SD{U@G&M@i ԒW$<}rϺˣB'?"jL07ߙ[Vs9im~{عr&kW`ղ>K7H1 Ixǻ}}+~>q+-1+|n<eobh4LonWejWe%Oȝ5HaŇ+a ~~i3g!_{W,zmAoegCS~C6ǒQeVHÅECX~zZlp~T8&3rshcĂCp%9y~Dv])_sˇ3{9LK+wP+wLUH~i.ZG+-&,MOjtLy8ޭ~͟7rQ Z?ưhmDȮ.,[t{ް "=hW/NAe)B?f$[X E33MȽ7o~""z߀sx?w@RkO^7,+2f=~*W> :L\]ы>gGeN L<:փCJGSNlCkf,bToш|rd{VN %,9x6Qdqr-E}y^6n5S'}Z"d̐kSH<xm3Gznm;ZPg.<#k`>ĮNlЂwr"K(K 7]YLa2 )A=oR4]>[<H)ŜbM}'Ql/X/ 8&H:k?VG ;^OmYH\fIZ?;ջ,x4jFkw#E<2^*i-r'CU cioܜ0o),S\J¹l'ngǣD`?IY:ٓg]Zʍۛ?#.o>ARUiCP~kA<8Wa46}h%pm\wwH'_68!CܰwBܙޙ'`(be=?S'fBp;ɎXT֯;N͞D1p 3%mSG~A L>ϼ&Zw5Qf|/g,]46SIv._p%2+/OofYۜ\8=Gޗ/Y|_aXd.H(M7µK"#+\]1NFᢙB/fϷ]XxJ;+QyJKa={xVrDR}cYV.*.<)e)Nl^Md`6c~dUiI&=)4xk=+D~*=S .$ o ] V[;_?[=/}[Hg0fPdMlb)S={~X I-7F?-ODU-XXF!zaʓ^l:>l]3jcd%h& ζI]|ԑmY.<ˊI?p:I vO"$HLc %FNhݢ)gɆ <> /[ y^|У;,[YdOLҘbm(4~hQk$.h'*-q܎j*if.*~_KJ"Bq XnK,G(&ꫝ+G4NIۃ$? `4;?eԧ1Ds ƞK(ۉRm L)N GC pUnwxxa=WneЂb{c20;ZzIM~}K2ux{F=CÏvZC>ٲ1 s4Gpv2 .dՌґ&O 6X[*B (? ~|%o{Xrg&Uֲ)ýkX@]qcy6I9U#57'NrȇL0#5YГtx4nH#S|$'{3ƙf}h`0Z5 [n!ࡵ&9S9(Iw׃sT™]wSeCfF5]sa_Z'W%OϜ$Ķo,\v^\T[mMy}7T j7{.|n"6Yv~;)T_ I+_/VFbzV~z:ȷ*CvǓcm=fofxeb:6ۿ]Cc)oDMWde%"qY̜ 9㟜 9ItLAvw3w ۸OXU!Q )l6Un/q2jK:CK'A!u0|e{'q_28lAmy`=) i|QGɮ_} %1.:ȣkW LQMȈ[|$ ̍9$&e[\WqO:A=~ޛ!9'}~Na=C/ހTI77&Wg;PlT5:a5fo⾵O_||iM ] X/sǏO3q2|{N3='W7Y=!k{8[ ];},ڎۆv̷gYx϶9$JkME z9IBn@|0|:=?#R3%-\b`nb`p/3byIN]}ḑ8Ce,_44k*@L}K4ӒB4|1d%c=ӋO2# s?.dK3&3\z)2>wޭ_ Sqnje< Wd.5[T2߉/ﻌ$92i.m9S'79=2n<: ]"̘:-~G0ϰ[c&xֶњ爬xf IbI#9&yrm(4پ{:s!^~^~Y=PznkErs/@<m#!bGtlrwz^ɇj췬D$.L ŵ`EGۣ}?x~aμUw;N i1$LnC)ksJUԆ v籤-L wf<<'ONIuQ3&"E2#gNė}?n;=#̉ߡx ;W q.Y'k".?5ȘMY`fZ2^GOa=xo~#!Ӌ˜H):X|yzȁMaUx| Ap0XO*[mۇXO3/.gA嘦"޺%+d bӒXr"u?É%92: !1ZIpe8Zqw8(cJk;?M_{0y(h y^TXS`47;ζW-ט6:uH,ٺa-R'o84-*m$z1#̛UV"b/*iS%*tHc{Upaq|c$f9iII`pJJtl3"gHX҅9x.\9,ەpnK]̡SG8;HGB!9j&̚p/ɜ͏Q.郿2$#o6d'זm<7[fƒS$*ՂփjT)Ϗ? dن;q37Qq3+%g9iᒭ]j"=}Y =jŶ . yZVsINmʚS>ށ$VbF^8C+Xhj-xh5Y߿|8wKGudJ)h&]z`1{:޾XѼ5Yn/b1߼wi=]%ը ʖ{p*dK/3VH򓬚:Osj^ŝdyHW9iX9oApˈ{:/ng9}%}D>"8ܻ{#Lye=4V܆Ǒ^cz܊2?QU^QU0bk$+Vdqm8!+x#ƌyJDE.|)S8]78epTĥ7{o8[/U^fO,ikf۷9r>?~Nxߟl/̀s-Y}ܯ3c*/&x4HpRVyT|GMfvܟA|Ř|-ѰbF_G0w<=*@}@Ғj]{PĸUS䗥q.ӛur\Vb:̐'6ڞdRl8:`ӴMM^XI_0k_LFкޘ;#ݵ, f],i~w˘lr~ օ"cj4ݏ*\gMȺp,ڙIC*r؜RKʥ86k Ъv.b֓ƞهkWz܋R.x}ܵ^ Ni7Ϸcǰ^QLdu"ȧ]q}Oe9nGmez,hNk}OmO'cCW&xJD|N,YI3#kθv<pme/f\jNΥbf|wG5.HL}5+H$y#Ҹ\V^YpcMG%i\Hxb.3CÖH AWٷhû:WQ$"r3[t.W(qUYY|/q.=Dg""hfHwp>+s^~8'Frm^&a""Ѧ4.bqߔM*N3$.R0LDDDDDDD^aiR H` H` c{ge-y|w2Oh[b^>yxg~c?\Z3sed&Ry} Ϝ3SlYҹ^eR-8a~EzЮ^.cm cYL ${l ?ȁDr10?w367wNcoYb?y>vX񽸞3dztlڰcW̤y;I NfGq7`I\H#;-bڐ)DWkߓX0ENe DYId6OofYKBsw"" ƲxLuVpøg1rױ,Y4/f{'EQߟ슼gͮ Y{-GVxd9L[Zo9\d(UL "HXS2g,Yl: R8gRw/-۹⛒ґ 8gk{)պe+9v#S]_vo&"""rgMa{&wY^]EHX3?6o}-`:gp.Y5tDHq~>K6\ Fױ|As0k_{J:e8} SakSgg˜x[T lYzU{Ale=<4"6CnGT佮Ci\!aGԔl[~Goƚe ^H)xU:DzG۪gD ]偗غ,SPJ *NCh^Ì'ǘC&Cu`wq.ߛ;&y"""""| عy䘅|ŋ%k! M5H<FJҠAMfER"W"o+u32KVUp9^Acםiِٲ!o jz[j *ۙH(*dx*>ՑS$+8XMj+svjKr9භXrg&Uֲ)ýk!u,z=H F#0j'Dn?e{RzUOߙ9䓟-/{2nJzy{ WC.dՌґ&O 6X[*B (? ~d(&b3֦h,ڍdˡ;$Ξ 2x~ 6ctПy{ΰ18d$G(osN9$A];},ڎۆ  D욙Gd+C:m߁5e<:~ei޵+'GM!'a,A8} Lr5 9o% k $xpĸ'Nj}$*'wgEO#oGeL r?VpL^tcEȂO4$"$LG\{vLODXDDDD$)&b 8.q`g?/՜|4)]qvOI8Ͻ8q +<}k7mGs ZOHg3VH򓬚:Osj^ŝdyH,."6Fs!7|jN]8˹}/g$yUQkN"播]j"=}Y =jŶDiX%#׍aaER5 ZR۱cz( T&_XzTE#e=i܂6+ 'NYХ?R`L]hU;Q+|1G]` k/>Tϕ0ʠiT=VnJ$b5y'mBdSRg;ZYp`ɏl_׬ډ%2lm """үIJ\a""w)߲INiQ;]0xqy#; {c v?-,euK0c\-cyșX2JO ihˏxy 8#fgGe<:փCJGSNlCEDDDDD"0?w3pøg1rױ,Y4퇯ҹ_h!fLⅿ7nN[7YJ)e`\$ :ǂ?w;;%r{9MRɞ$4=?=2PTntam3އV~|gv=ˊI?p:I vOl]3jcd/iI&=)X_=) RƀC$0y'‰ Xf$cʝTYR| c6 SIMrfIDžgne:!2q֠fٷ Izd ?|њDy|O10!l٘|spSͣko{3\V2#M*Lm QT(JQ<n#ȶom0U/ހTIl[dp%MtVN٨k:thOaj}3Xdy5M7vR(` ƒ('JUS }5VF2#Ien<|Nt!1)2lpIm7# ?u[gG,>l@kKp"""""DD$v#XX  euKWc680E»Kp/.>^ʜ yޥf*8Y;ј*M!-/taYzC9$Jkx#/L)HMDDDDDDG""b'H):tY|y*I MaU Y`e!ߗ  s'Xk'Ȇuk¶6s0ގIvz;┪ 8~ǶğcI[aDDDDD 08o-rlbo9u$6Oe)))K{Yr#g/\5@|f}sY.]ᓵ*yG̲k1{:޾dE~C#gpq|-=FBZdtǎt!G-Á w˷v"$zf"""""o<DDn^d&}3T%.8!uuI KX8 f- iZ~vde5߯B&vS@|dֺ Z1ncՔ/enmD+CBKլ8Sf:K}'l"""""4%X쯓g""" Á3n]4!_pme/f\jNΥpSGDDDĮW1Hܡa""b7 AWٷhû:m\a""bGwp>+s^~8'Frm^&a""""vH3$.R0LDDDDDDD^a2I7 xC07 xC07 xC07 xC07 +ٳgmDDDDDDD$˖-H0IIH` H` H` H` H` Ha0 msl[t sч2?dmMřl00q6m#gMED筷cv,] m4>We:ˏS3?gWoϚ Б&KQJu3h^mXYLW󧴪U}_{4ݷmd$D佁K7৳Owq;֥|1JTnLr+\0ˬOSd&;AIwVֳ/`͙w58&e=n|^u*tcw*Ż+OW?x%fo(ulM=h/H/]y <??G^L1'ß`:?7@UTz}!ňɌj#>dSxu9u㩩qJJ 93M=-7=_`a8k:?kDƣǟ/Zi7~GQY|׽WNYnW iLU?೰!rQE-ry-Vh)k=̟ʲ3~%c:2~B zat5KxJ^&jQ,/X/ ϔ31k58uϲ8b)[x$KkbnXl,-kyXtb- h{oKbXrd\KE-E5Xl$s_V^KzS,gmˣ|t,YsȒ_Toryg,Si,oGPQ?vp6U%"䩔38YfV~a-އBr%8*;O\]~?fY6kص!KxPJcM̍ :^lFƕ(^2>[kѮ&Tl>W%8|,Vլ}sa>[;kQxtêQo'LvfHDɗ4'p$qM7@_krވKC@lO#2\J͙w2 ZǸR=m&xāU:.g4׆sJ8l?]KQȜYRy>4kh_-.&i43ņ7iߘɸ.X܃ru3dp70}xޯEbB>(қ5su)QJqZ1>`kt]L'Z"7w܎|ʗޥt}Oj?Zb~=}e%"kC˶]gLOʙ1X.:rsAAO>pIٲ%ktڹM5b`KrXK#_os.iHapNwA.YP:ܶ,1q>jh@SӬN:ߌm㒿9z1ي#O2%(^ƶ€J Oů@Z= {Ef0$HK=lN`0{=.>wFQԆD;R9Y~ݓ6Q潏oƣªlDO]ѧ0^+qQ%LYHU/+MҬbr\2; zIڟ֞^[p"J4ˠ]Bl!C~LӦM>7·S EݗF\#w1=F+?Qz~yvF]VnoפAVz`m=AزөS#K^^f7syG*i4~e(A' #MQ#u-~0B<̂PMMap5@r`-1sNzhp&ylH~s)qi\(ӄ~Ci:k]F ݣ}l<rS,<8cAb<jgkF.=̊}TOłCfL\elkXv;ֹ=}c _L6g<&FlDq5/fdݔA9gPT}i45}a^~^~IF;`nuY 7_-س6t:jUI?m#!bZ%;y8K+1R_exx[`f̛i۶6cl/}rqns܎jۄQU0jS8h+3L:TBaz1#̛UV"b/*nr=JM6ɟ3'9mZQ==aO+2&Yo %Yrd[d%i[Չ #a3^=AMTh[1 I_k2N}'ϭؼ9#>ynTT7%O}~L^7d֘|AR5N8eG>ֹ-c֝lk9?~?&CpfZz$*Ҋv0){k&^iE!wF/ Ӌ.ߊ0t.ǭ(UYEuۑouY3$*DB~^u*熳b7bx7D>Q0!GmaaK.JiǿZc )g=95ӷ} UpۑK1L]{`d45Qu=)c/Gonzά-;}8!5Նb9v }_|˚%=y̋+34gW-Iwx*ڷӰxW!;Q||؆_R^0Y,Pr~؞?$j3M'ҭO~ .1gp W([3G%M&aЫ-m?ǽCܽO=}c~ѕs%3p`ϭ')k<}J$ȹMYyK6Ɍu2 .|sh"v݆QZc|܊*?QU^նQU0nZ-U|K!FxƌHQe%"v`=nbnw**JL7X9]"fOpHh[dJ>#IȾ4.U$WV&NNn[[hf^eHla""p%#1r~z橌Ytu!a"qًm"oB=53"QKrYE!2{fϟ-5.OmDDD &1lv^-M^ʵMIDDI}iyYCR!"Q0LDDDDDDDD }'""""""""a""""""""o(&""""""""a""""""""o(&""""""""a"BZz6g {nOgl ^̫g37IY*2YI[FL2z2]Ry} rQE-rl DWl5F3O!bm ciVN@WϖH??8\x*]EDDDD^?; ]xxxPGLtf/`(WUhg:!k}ZѬ?uR̳->azͥ)eefߚipA!k-1}]zR,9>|tOuOzR=Cb[3U5<=Qٗ,cQ'sT5k,hNstH ɃFx"H5/ז{y4tuSӵMLڐ%<(Y1&mFU!lFƕ(^2>kѮu?yPV_UkDMf9=Ȅ_3]S|?"I|1-;X ='X7'ݾqt코gMgե3SYL kv郱̙ukMxYi>El,;Sֺg3-vȰmބ%fF嗟Pݼѣ7s/xe4"OpHG$3y?_ɟжi'a"H-x ,\3UM㣽mߋ;yztp{Set挪i״i70o<,Gm."""""ϧ` s^e<'nXs:Nv_0_+xģJLëޏgdYHJhSE+e訆$7WEw|>Z$/˶Mqߵwlgf }ϜdU6maq{֤"˧H( wd \|hԗA-延:kPEµh*7CXt"O388`43Fa$n1a]S)W"Uو.T+ջ2OaVh%LYHU/+MҬbr\􀈈H`sߚFvҿFm?o֣(] rP^q g_ѿS+>Yu N9(y.n9˓/u^ ?&G>QҥK<*0w|=pJE\Im'W=,S$cTa77$£DF4LH) 1N.g+: חc^;SZ< !EwN^ CI% $_~g9eK1YR%}ntщR&"""""QR0Lx['D}z;Ѳ&e׼6uSˀ`&dDl}퐦.c2c֬YBOg8G|Y>EXh ESuˊ^;ap.xx`?왏MDDDD$P0LĮqsF8N"5ic8?/mwwbZ6mP:_Z} l 8?'^ϙKCOH5;^GlHFʔ)^ˠKe<+|}"?9:o:ӏ`>|mK"f^4$"Nȕ+;8z/쓘{x'ם#mD욑Ӭ5.^||ͩ ⭇9u.|"drKdtSG#6FRxee\<bv\l[ÈK4IiED;=5?z/봢m#1:GkǨrplJڵ̐nD>)[Oĝ5nӞ̸^_7 |bM e֝#9\*Н)4䭧'$M&aЫ-m?ǽCܽnQ^y>Eg+oCORxHEQXy+܋{h3tf0>)"""""1`=7eb(j C07t&""""""""a""""""""o(&""""""""a""""""""o(&""""""""a""{7at6EY𻸎R%*7Ǐ[h[meY6jM=m'wl+fbϯSY~϶@DDDDDt Hwgw݋pejo/JH|>a|Ä&"""""qa""ˌڟ֞^[p"`pb4:`FªlDO]ѧ0^+qX07a""P WRd`&YJ-du;Jf"\93\?iɸi>/u=sJ HHwS^~RDDDDD,DD$vpu =ɂ9l m+G8pҋ@33d'gCz{ǝKw?Mc=uܿ @&MY{%R2xi"""""')&""v"ir~gd;/2s|k6M! ,<"茓т%Ȍb~a+<'Rʌӕwr9 9;ږH\` #˷r ?ܑ0xzu#i"Ǎy 퇎ϙ  -(ؑ4QAfiQ=_.^Ty+`Vp /\䆷 "h#ºGػfG%yVr}m 0Q |Ѝoɕ++4gW-Iwx*ڷӰxW!uDsH[? åBat#2D41 %*ILE=m4 }ވkoIAnc&"""""qbe{.""Znbnw**J86)ۉ0 ap?WnqfT,G:D0&""v 6a ;&/ZOӂ$7""""" xC߳H` H` H_7W5'm9$';%ա-Ѷ8f8>>f߰e,>?'ZDDDDDba"" er.Ζ@\;e?W?cmsO vJSx8^He""32;y'w(nO͐mB6IAx3t+QlYy 㽁˵ ٸKTg 8zz #Ã͇j `]R%4ۤ `ך[~cp(NXr߶s86_ [QwM@ڴ 5ЊH;O?^Uin.naެxY7ӏgh/cba@%N&'45?[X:5|& Kd4\5S΋syS%*LJ#s94-ym XFS3friD,RKJo94<)_Xu8B)Z+#k<E29ɔ;'/$ WF/FZER?WRۀQ cN@bWsNmRL߰EPXJȁ0n*&"""":)&""o|9F ,ǔpq~#wq,(9*vp%q8=^m$QB5wSDDDDD?`)'Rʌӕ2sN;g!GrG۲xfnMuh'N>KǸ吖l)^!""""" H+j$/nD{I^mEɂDXMJOD!:C|3s<ާX~ _NAM3DDDDDDDD$P0LDDDDDDDD DDDDDDDD$P0LDDDDDDDD DDDDDDDD$P0LDDDDDDDD DDDDDDDD$P0LDDDDDDDD DDDDDDDD$P0LDDDDDDDD DDDDDDDD$P0LDDDDDDDD ?wY3ef{&wj0d2ٞH\l{&w2I7 xC07 xC07 xC07 xC07 xC074f{gTå43i:<Ea|v}F2mMٴm:c0qan*79mQ8QU׿96)CZs$=RZlK > J:,K6wmXYL2sիJ/_gpYE'-A/QyG2{8,]q]R'ek&16*%f+ȶ2>C}kVhάo,m6,\hf-+{Rc^|w V }.}ՋT^|+S*+3fy ~~l5; ,N>yӅ | >6^[I]|": `ցӍ]>ی㡟vϬȸ> plݺ|h%cJT?2kaǀ9ܮ҇) e&t/ƍ}2lDȮ.לhZ\ ֙H(k=>aɘ.,O|Bz3| :cz0oA%}(i\n<2駟)c0vxmfe%"q],bYO~qslb3WoؖEtEgr#mAc.Fö4ZҁtWR1+fO{ֽ{nHz/M<)Z ?D3ë=wZk۩ݕU\8r'^&aE;޻+= PzgzIā%[xc]hڥ9$|L̛ I-O ߰L=-jQ޳"÷FWǮhD}[4D.);_>JrgO^7-+찥[xxt;}2Sv 0sxծL֖=g6:g5qapf6_ 8ږ>vn]FwinOKHST"byy?q)C*|>q8G?-ymL73{3j\a 7 4xxvk&}[TLrάQӓjmFڿ׻Dǂe nWۺ/JS`ق߅U|թTAoX~uI|E& k$J!0gmWN$tq78u[e۰oĄ3Q}1MK^6qp@Mjd龥 lY?z油&ӵL xRA'F,?Ya"}P*)Wwh~KoB߶Rٳ ab}"+컘#ODVo^/Fբb׵o k^ƋkiOW)طC؉O*͐b3a>;>Ց z@̀Kdɚ,]#>Dϛz^c=dT=ɘ8/5֣h [^J˅[SáL]n`6&"kNE<DŽ$='ĄO[:}w(`~'6>Ŵa,:ǵhfMO;+8WD+72o'{o6?͸-ܳb-<)1 ɔkm\vdԐfds8٫o\Cs'K˲[x4iBӐ'm嘖?ckat kF5󌙴}˙WP!3H~߳SFe>G\(U 1۸Lъ 6$2g?SO}xḃ=gFLϮQ]zjeI!&ˮԜL`O2kv23SӼc6s7a+6U_|?(5}`H6r%gR_́|s++OjlX8u,c>sTu.&ꫝar*-g'{% +w wKS[SlYʆ{T7~.d |Ng#ao ]| IEQQ fLŤX>/WRn|l7NKQۃ>C:Rp> ۙ!=}|FuzLl@Rɇr)OWHË^!ޛHΟҢdNS%2MZ ߌ Pgt6 [`dj0?5O'NhYmA*t0RICl`=`4`4:`}ip0Z_=ω$'K H^&m3!x\ɡz߮zT.oH#Yΰ$n6AR!g>}c_XP/>oAy)֠'_6 W:y}w ͩTE*5I<ާ-dh݇V%s1gYZ̋E˱6u_rd8DuۑouYN ì:zu%gRKqgT{z]yc6 DMWde%"q٫']T)$9S9J& {OQk ䷟c>Q W`O#h77f=uM#-~ܾpKwM+cbrVjCX,ܟYphGl /ĸ|^.VpI(iq:gv9pqt"E֔'{D37SjLb 8>&KzNyfKo8DuQm0759rpQk{Ŗϐd;k##TVKICNoYH\6ډYGb~ijR'Z`h9ԍ%dMKDd{N}fm+YgY;E婴PwŁi/Fkol6Zo l9~rl;5fq22xީMׯ_>_~h:n }"gnzo N X:h[bQKdoe#otS+͍3@-۔2&gCzYP_wIv>Ϧ!Z=ƒc8RY\dlo.;\P'7fԍ7o! WbO }as[{d|lxna͏fnۜ^S6q575dhA9gPT}i45}a^~^~IF;`nuYAB(p~?3DROtHȺXm@?Y9?CH}S[V"zQVnD_ӬY̲=~PX3q!'??N֬mczYc2q澃 .m֣&N4*ȦI80P \T*GNǞ:5zhe_*p"yL8]ɱAc3sf'^_1^\yasE}6ތ|\<ᄅ@Gp2XO(g!S XO0>}s:4zۋcpOc7T!濩K$?YrVViI%wsِ)RXq+CG,sƶooHmm\əwȮi~š~,=Uj0zj]Rykzǘ8ۆK_\cz6aè{ /3[!.¬%#:scF7D^U᱕xj-+/Gr*4jJVvWd-u?qŘ g%]했Y]ZX²ٵeRs+)ݘIv_0eysC籇HTOSt(ˢ;2d ھV2u'|w>7-Z5iTs?Ǿ[G)ntzqTS%GgCl?ov=o ISo.`ķ+y7f8WlFĎ.ۘ5q|=xiH)h&]K6aqHC/ri*Zټm#+~C=XSO?H P㐺52^orMrخrۄi1Xn?‘<.{ʗow;g.:ApHR-)gYc=qϖCؽt<|6"@q>Ħ'v gܹm<͊4V܆Ǒ^cz܊2?QU^QU0C* Pqn8!+x#ƌyJDE}rlvU9:tI0[S+ny:0^xNw܄7#|ѩ _$ij2փQ:傟baod嘚bqj'>z͜4b̜oZL\t5`Ưy7MwLKYd,l?,|Dڿu>?<̞zj>)C c|×Z@k;) ~2[km Y7- [e2NN`K<ڢȧ]q}Oe9nGme̐5[[NOz%U cF$ި`XٞLVDĮm=Q!g&۔.ǻ*${2E- ' m]+H$y#Ҹ\V^Y85loί?7U&؊HקJ|y Y> ^rkwosv /OH@H`ˎvn+HyҸ\VQgطqv r?8D3DDd_?0[ g9Ѵl DW;l;dJTx*]Wby} nj дKsI@Wϖ|L̛ Ibm<"""""΀EŇ3FxzzRa7&mE`J3G1zT)gl!k} vqY8 +SBmr>Glͷӡ⿗WњV:|0lnr [߶Rٳ ayS_kq֓ >J,]vYj4EQߟQ}#&؈TO"m'ETC[5h)LMM73{3j\a 7î ,LN5hoY߳'Okjm"""""ѡ`3N߯!Y/q- vo bR߱JۘNAt =xy#f?l1MI]?[3s13=6n*SF"ox:ndָdl3fycl5+S⽋1~z2=FueoBj2o'{o6?͸- ^H|͙<.aͰ$zFtIu ^n:˜K0Nh:~ʒ >)o}ݡ1wiSoP1]Lҡ|\[fg\DDDDDO0;u ަj)T55%X,nӏSHTjHIytYR},WZ3pX}/`'gXoW=lp*CM7 ,a,l!C>*9Ҫe^7/pϚTd e_XP/>oAy)֠'_6 Wꬑ?Eɜd{7KܷN}B$iXu0>bhp"L7ЗF1cC*LsYA!Z8̐pw>Q]/9<P3za\dS/"""""a"v5oKg̀8fmI"jwpx5ˀ'}y.n9ʒ7 ] ?&gqV|+V y貀[w攒9:#{ Y"ϧH(׏\9m"1a&BNpt>[ѩOsITP@ B^u"o o!H|EIwwmi:&%sύN8:"kJCn?H sąx*OB>Mg ^mszMe:Sˀ`&dDl}퐺1-dBc VVCOg8G|Y>EXh ESuˊ^;ap.xx`?왏MDDDD$P0LĮqkό$ީNno=w{`պDgKY~d{>g_j @,p{ˆHH_:b9WgE{OG3'RIvrkhc~_ےY2b;sfN$f dOh[&"""""1E0fpUSm> ݤKԸzbӎ\~s3||\o艵lNwF"""""ct*b $)Շas>t?F,E>_7 Y7- [e2NN`K!77{ҫ;_rIoiA~C>|>+` XS$1YY>KJ{-``?Mb/+7v1{a>q$70to\fB}RDDDDDbbe{3"{B~&.ΪEDDDD$9;xH3DDDDDDDD$P0LDDDDDDDD ]&)"""""""/EIJ\a""""""""o(&""""""""a""""""""o(&""""""""a""""""""o(&""/>ؔil ^K0kClہV{yj ^ߒ~3wd[4]6gl DDDDDM`~ǘm+-U폌Z31`5B][҇) e&t/ƍ}2l țM03ϬܑjESvWzVqʝx|gv:SwWj{HKpyDDDDD$^Q0LDDb߳ܮ6t>ao3L4H`* I> Z+L 8>j ;chT*R"ҤDR]{@-dh݇V%s1gYZ̋= }Il:6BD7x4S>.my3,V9㋈Hfӆ嬟t ^?+0ũk䳫?劷g]m ye4^T۞Ashb?URߣn#%1%꼼 |X?}zGݱ.yPrcz[ڄ^f}ڜ%7 OPe~!lμf4)A/vcbϯSY~/6;=;ׯdW)mԞ^_/W/xo^xr"q+-1+|EYco!G~DzLD$γ`'ѕl c,?O?t~>=ǎEܞz:;FLc: ۈW â+rz7ȷSS&|3Εs\g>z,s[o|'zLNqt&~ֈG'Qi?_o2,T{LMeW 9ܮ Әԫga%BvwVZv7X6[aLS{?egKt~=we R+'kFѡMX_$rR_p+ӟ)3f0#c(jqxmfe%"qcSI,ݰY[d[g>c82$i=ZV[NFjmjbӢfRf.UGU/qфH}~w}ūnk92XѢᏪ,GFlݽ,_,ghl|M'gZj{͖m}-ewNZf*fyls{w_Kb,^7[,a,>k!lk.sPOK^-LT%<(SӶr9@çiϡ{ /QF}qFw5;'W0Yek^|+g wOeDk_{S8oDZdmg/_|)#{GR{Czڮqwq7"5 y3E {WWc=ϲ1=UleLm܀LûpjKC>-(<zVapږ\ߝ[wMzR/ZwxESRUx.luػ *RoG.{^1] kSej?f/c)fݟ>45A_z7gں&=S V>H+a{_.rO%8KlŎ۱oaJxs%~ߓ꓎~xzm??ZzyjkY}{4qhNTl(Q10¢?BâpI7rA 1~Pk6DMe=/.Ǿ>Y1X,[˅P(]۳td+ܶ,1E>7CSӨF&Nڈj-3s٘Ev*%Fur{/[`yHzOǴem&q3k%|e誘6EŸ5Ȓ𼶚s~UL{αpr}8/f y#[ab¶tMtzy_f\uK:2ndSr:[-n`d+AxpHWX?w#C >=V^!wdrDg}c&[AWkaէӢŴLaпp”j{STM)vqXgm5\)BNcfzmmA}W"DI-\/uD7]n j3x1|G*>;m,35dЧslx3ƀ9 yx-C ƌ1OP\}i,X.xO\b7/r܎kʕ<s\u.!ꫝazG0U(Gfg'^.K&V ~ٙ.QQ:D']amZlGM o-o%Oͭ3"f/B39 Һ[.Fk[C5ti>OݬHw3JycSmIS6lk[hP$e dCC'Vq"}fO<ړ\ݎr5^r>l'-+I̞:)W1[IsrJ5q#J?0f=tcO{1^(+ƌo*B,/, N:Ŕj}`-1Nԙsϳ.Tq7簙 ׄ2ߢw l;q>2[dNF\h lXX^17-㛣AdW]qgZU 'Ɇ߻8 hl&n.9g'W' &tzY22{ c[d )f0=r ',&茓т%zRa1[Wk?DaR.k|5fqq|6v3aS7UWcw߰߭5 H7r~( H62l%5}߼q"}Lpv''1?]kQg>"~,س}4g[+_F܋LmCqO[ =n=6"}% g@u mg\,)f-Ϲ?9fDzJD]-fTkQs_Uҙm>l|JF2x~'KK\9ԁ+ `׽\x=?O??x~Ԝ,оtV][7hT'>Z| N7 9Z2'/)o`!e$g Y3o1[eq6$ ΀̓.\<C|qfźV܆ҧ =nŹ?qU^qU8CB(t_7!K $,AƆnO3%++v ȪeIv䡖k~[Wk[(N^v{ѳgDZ- !>yonfڀt>ESp|FR,ub:uM3ѽlCsXث)kSyFg0|<`*nI@Ғ^sc'\Mdvׂ=N/13ofG:3|6/NwޘclnAXa&uX jۂ6qP>G$ {). 3[nq¯6s~y*K8zuÄR}AQ 1TBdoatf>g=Z%ܨ.̞|kpL1 e<{(׾w8zLWZ;"] Raw]*ȱux/;K-6Wї>mOq+b"RPȷ'ܭ@?äKUV"b +sN9ߢ84qlR>8ڙ3*%8I2t#="X3&Kٗ&沊Ey{S߀`+""0d9Q}|?_ٌkë $ry٭e?cǾt}ib.8UVB&}y|q?DD3DDd>y%/!/eWÂDDI}i{Y=%phZA&wL >ތl1`p!eOoL}h97bAۂ,ѡDyx-C ƌuĺ"6]n j3x1|G 5twé|1kUʍR_qDy+әbb[H1t~1f^Ʒ >i=e7L>=άyҢE>OsÚTl)r`a)z3i~8`F uGs<,Kfoa|6ŧGK}};1cI1zM1c}*IN/X8}Gvr҉ s}?QT˟@PMDuDDDDDDk˺~UӺ?sLFdq5`pEZ1\OЯ}3AI_\xw[KvGKF\ UxT` WBq-zyR:#N{ YbOL\:|sR䎼1!9ݦ0A6"N(pr>[R_sI\2Q(-/Bv !K/el$Ubd{?tLEt?7:Diq&"""""qR0LSX1#eRfo] |m #֣9~P  f,#fk |Vk6a<~zşܱH$Kmpu=y}|}N`pc ΅Q'=Q$ ص0lIQ-?V:{/Lwxˈ{D=m V@QOHFNܯ!iӦ>z~1C|3 HRDNNµDfw-x'EDDDD$A,V" ;=LZ7:0I: $CIHa""""""""d(&""""""""Ia""""""""d(&""""""""Ia""""""""d(&""OìS!OݳoW<(Q>fnjm^|ҘwKo@9f[0u~r6O޵-a""x=R>][ux  9LQKwo෥Yu."y)&""ƽt GtGBJ.Xkf0e;֧ 5ģZ'J[a"""""(&""ϙ;'W0Ye<=Q@Vu2/Žn7ja!9W$_ˑ^j"b}wBpވKd` &l[)4s7`9ܱ.6]”NuXƒ>?k0tPSJ,H ug?êz ?6%oL9p_?)I:ِ6uCFG `pph/X8}Gvr҉ s}+&""""RP0LDD/ ȓ6prqC {)rE,v'OɬD^K^>SR˰.}p) ~`hiܬԝ s2wRojJ 3d.2L##Sy=OVH`<_'\`5[`0ږ _'L9Y}* sL kBoQ}y\6`V?)>TZi"""""()&""v"N>%r?eCic!'L ,&茓т%̌bvUek?ʉ4y.ވLL\rNԎe""""")&""vH𺷚AxvOw$ci_r]^ߤUMj搱:#>CKKԶm,\|_1Mr@95f^sc'\MdvׂDLDDDDD7\DD2]š_)[4w7qlR>8ڙ3**DDDDDDf0a>Z ׯrrl}}5UDDDDD$hf+}! y)Ӭ'U}}#""""" @0I2=$ H`$ H`$ ȋ=m0Tm IO/fnjm=DDv{ob` 𺽘l/ݣL,\ץIUm""""""M0Iɜ79G 0j4,(;;3EOމulV#:RգjvW%ŵ']R0LDDKZiɊ+ߠ"ڲp 6G17ȊE g<Ȣ~ͩ~9d*?dGoE>9B9a|oNTb[Le yߗ2ŬA7=Ӆб6{PFk9A5Y!9W$_ӑ^j"4ڔ4W e:ww3 ׇSb 7ᅰ&)t@oM]-ȲooJxX7|(㶟uGnۖĆP*drԐAv`Yw1'ltuvoȸMl.n`d+Aڄz&"""""Ϝa""|!Eq X y"#:gru0\>ˍPR]#n,݄#g9^,'ٻbӎP<Eŝ0O3|< Ӏ%St!P,7L|כ!Mz;V<[)yc6΁m7DDrʈG唁yR%N.NÙ p na"""""a""bnjx#'׏rސiZip=!VrXno¶u?U/@h0 7,`m_&͙@5ʗ;f;9~A\:#Cic!'BhmB8iDIt.""v-_cjg:.cX0/fh~Q;y} f_& j2pyw'ؾ`(~o9ށ4-(gYl=x+1/&K&b硣a>FlbyfDDľ%{6>ђ,FE?w) T1S$Ü[ jΆMٰ;.e:dc<%,uY/ߺ?=NU"3~LS2Mÿ!>Mj"""""be{.""""""""R""""""""d(&""""""""Ia""""""""d(&""""""""Ia""""""""d(&""""""""Ia""""""""d(&""""""""Ia""""""""d(&""""""""Ia""""""""d(&""""""""Ibe{̝:uLDDDDDDD9r؞$5f2lDDDDDDD$svv=Ix+fp &Ķ(RTm lB-eIg[gbe-"Ǽs1S]t&Bm/f7Sֽ.AxgSŶįMkӳ4Ug}D"Uw}٪h?|){E% ?yyB?aۻ>ooM3WV&%2__OrYp6,ׂe ̵д'U%o1]Ò1=A~ŷq{>\-VvUV"g0r#kط5dg/88<әM?Ɲ]3:b]zNɤN0\ywҧq' m1utc<2´3ЫMs>_Ijjփۍ~q'`rb\ۋ/?HLrMՆUZ>AG1[\CoLtkz5 Юj.nmGC|%*yMܢs_$vϥ^?q7ٛif1+cpwxaɋfe%"],fw0o4z-GXODZ)([5e[1˙\m ";-]/@\$?Ew =9s['#C[@:6SˇorúCwlevE^zۺo|7:?-$&nw;Sg'{H+2';뻌) аccIa6-!H7_u<$+N[3c84gykыK&P;FǮ(o-"{Nۿ49x+_>E} /?y춬D$1Ön!vgrTe=!MYh!:|5qf6O8ږc_o6$'_}5r#Ӻa !9~{jW{X7ݢ8nXfY,}=0ڥx}?e8;?-yaL2K#L&tlW" 4|O+8M]*~ͱ=yzRH6^zX{XsjC[Uӑ>[{f=cעwtȆ~Ԭ?nлv+.F\R$fp0!:]櫫iS׭1=ɻfz>oj:Ϳ響ݳ)GRmr8ZO.e4p7Au.ǻh%s!Ԛ{Y [+%`};oܴ*?枇)oLb O\}U#>LA-|SM.@yGDŭYkFKEOocՃ}b+]BOVo^|/rԞ ')طc8v #kvهҙ3Q|VkC9аb\d!ɞ5j:L4߈z]c_#r8[[\>C2EHy>;-(G7K(Cnyi33S0fc1Fᢼ!iɳGv2ݧbrWo|Ջ;tpw`T?y+a~;{<{2֧oHc!wvA5&ƏJ@Ødm(4~hqk,y`'.ԛ9nǵmeJʥp[ܼ_iWDޭP(Tיߞf ٘ E PB]H틷l}BhV2YrYӼF7׆KU]Bڟ8=޼q;m.+Hˈ-@ ՗Ʒ\w =sz" {{-s|mNJ%&XؓclUNK@NoYHb9ډ mMOzY=XBahЍ%~x^"b= OOΡe,M z~6MN{1|( Lsdm:520Z{csX ݷ9G o=7\,fAۖ0isF?0hG^ot#;4Suϴ4>< 1f|xW"xd}Meap)~P mI\=+?{|ػ!$g]zlPKwIf2ϖSZ=­cGb<-% 9{(P[-g’,_n{XÚh9ZbȾ~l׏xlaݟ[۲1=fl[T4a Xn ՗Ƴ\c˻w࿏۟8Roz^XޮZmm;3RO|Hĺcۼq%!Aꫝ߲,|ԳAGY6)dւ,=f @q!o`\7͌1]-FΞE|փbO#Ŝ|pۄxcs|l עK[9(wR$C2sO e˴%z$9 1?[Κc̚qz NL˾*URDYqcfnș*~a%tzY22 ˙]uǶ_٦ޭ'ֳ멅Y,Wh:L @F yqf +фr|oRv6~?-#ɳ=wR&M#5.dدs9AVccf毋X*3ң/f)ZO0 ՗>m&8*|(/ũ}91¬% 9z9njH/WYEб캝M˓/W.r5ݴ&9>OɈ[7Ȟc4dܞ6[UW1rv>2jV7pYx:vg&JAЌczƴTݕbӾf|l]Ϣ0i|DL8eIwv_Ï;eזܕ~&MϴHN*|(6}ƠHU1m=N/2LcJ[QK~ۗ3qOڻ#KקG/acec~wRᵤXzj`#98f97z1ulkG:"|R4!})f9Sb5rٮrۀ1xy#;2bdz˗7.ԯ!e$ul8.eۡc$Fo &_dx-sIv.o|yӬXʞPy{_u>ǭ8'Ëc6 gH^wY2# g 26$p /Ř8/YY}`X$aKnjV̈́iZ&%ρSшG1}>r'$ ݆ҝ.DzHJ \ᔹNWs?z2E;R v+JDl!f96S6,Nhjx%/0]g='K}f|\ Ⲣ'%f44'E/oLٛ5bg\!C5Ni= aԑy=^ʾ1=|8O¯6s^q&ҩ&ѷ|}dU0ˡT3U 0Y?K(?M~:֯d'mi)7bG̞l=X%ߝá1Ui6lmgIt+ZkcΦ-۬7_\*Zd=>_#~u+K'YV{v\YV )(X5FycC2xJDbe{̙L1h]3]ʺ)[0#2M>!Ċ%8I1b#]"X3&Kٗ&沊Eğ3|y]f$nΉ}$Ev43LD>BβcWb?6I$B@H``WV=;ݚX3&qKח&沊C\ee<ɾ0[4ID43LD$N&._/mtҋHԗ&#ii.e;׷6o~c=yif$F `$FNDDDDDDDD DDDDDDDD$P0LDDDDDDDD DDDDDDDD$P0LDDDDDDDD D0,ׂelKD^|Cb[d>VꐽEI|}=m5f_ -G057UV%+Di#(ft+[Bu-G0$̘ ;6 ${l !@ڼSµUYDDDDsr(ڽWOOO|vf֫F4xkP /O5n66,5#ץ7UZcO.PZOg[l+p*N9O/*77u,>U_ ׭1=ɻ~Cm#XIT1{;`};oܴ*?uSӥL҈=)S ?ƕȫ2#>K+8M]*ZMm5Cg ;\oHw5bQ珙I 1Oy8 &$K1̛?jMĺ"6=k۟n15]DyLI3̛8a7WƣGK}!#uf-μJ6 /+UO;CnMX4r%оbFocrOXZSf17wEcw`T?y+a~}b)Ր>~x巕n;7[ܼJ"K4k3ܰ&~g/R] /tg` [5R'4)Tobr֕R_fpph0_vE!E iWr1=׎w pu{oqA4̍uJClvm '_'$Ϟ9oHI4iԸa#WwF̉ogs9AVcsǶ$fnƣ?[Ƨl'1q"u8]ͱ̍#r99S9ږHBQ0LĮq6d ?&.c{~2~ HInNk!:K'ٹh#Ess_oBP9K4nyP3!7;pdRF X™Lz^bOWu4bc$ul`ȥl;t_+V13,Y{v4wog TSݶ$5V9^k#J^n|LlܒzťE=t%[pM~:֯d'mi)7bGqjS$1Ui6ܾ gIt+"΋ONbfp/Lיx=:@?Rߟ""""" +gdE G>&ΪEDDDD$9;"/fH`$LRDDDDDDD]&)fH`$ H`$ H`ooM3WV>]ۂSkl[ȳ`$w1 ZޥԙLT 0hE"]lŌ8a^ \,EϞkHU;=ẇm yv DozmG")Z}\8v7`w;Sg'{H+qqÞ@] #cr(v*lȳ`oj:bӥL҈=)S ?ƕ\i D{|7J~)OkRӛ*-XCq& 2iyt.""ϗ?uqH:Ja"""""Ϝa""|9'_WmG'L\2jV7p GҗOq^82ԥk1“5xWMӄ{9;ʾM1h>RUkLoy:]zl㻹 #׎ҩ4,'&t93t3.q"oc2P2t.cB++EDDDD$,VϜG.neoZw7Ԇt+C*DDDD슳sL-b43LDD!,0v.émMW+ī H0#&._/mt[oDDDDfIb`' IbEDDDDDDD$P0LDDDDDDDD DDDDDDDD$P0LDDDDDDDD DDDDDDDD$P0LDDDDDDDD DDDDDDDD$P0LDDDDDDDD DDDDDDDD$0XlϟSNٞHb#G3DDDDDDDDD^$]&)""""""""Ia""""""""d(&""""""""Ia""""""""d(&""""""""Ia""""""""d(&""""""""Ia""""""""d(&""""""""Ia""""""""d(&""""""""I,ҋ2x\emq8L^:EmQ].ޖm lBΧig[hA:39e-"?m3kg'GefCŶ®ev4ⅇG *l͐{jb?oY[Th=d1e#% ?yyB֫N=OqAxϜ_ ڷ%2_[KKz=rz6fɅ5_ 6_/go1]]xv~RHܒ\=aD^[wOsMۧ%u&/T*Ru0u:~]s>fvwSG(:lZBmr mdyzг|5p{2eIto^ݪ/-BM O=]Q-Z=/Ebirڏț4Άӟhv[V"aKtx;S/r9f7מs&G,]r=惚8P6,8ږ6|};_2RāUz1#R-l`h9dOG %/tKOi[YS4н~H8zb#[Uÿ׻ĚK+ج5/Q@Vy2/Žn7jqRlA('r7m\kE.N.oh՘%gϳ{L8q~U)}S7`945A_z7gں&=S V>H+aW_{'zu%zbطx%_II^H?_^ޗ>t=WtKF\S|BIDAT LЅ  rP?H}rDy+әøtZ6)8l#.Rbl y~4b7x{{6p֨,Ys:" :v`v7ݦ.`d77p%ژNo9L/KyXw1'ltuvoS+XdrԐAv`<&wo'Yx 53f ף<%{lCqxk,y`'.ԛ9nǵmeJj]+6Vr=Q~byWKj칬D$`حCkʑى׽˒|{\*iFx(A( n|;3,:YDud N*8ڐbxt'*:7cӢzqNF|3oȎT.U:1Wa]Gn1g#w=g7fo:Txly+Ѩ|jn1; ~LԏyYؗp,7B\:5:) L|fmH)nI3|P0ѓ[ׅ*&w0; 8X_/w0pǺ[I!Yjҹrf(iJ;x"T9̛ܭKYwqhǻERtl슜zM1c}*Iě7vgɇS`>J͐|i@) h{C2ɚ,-ZxtDZ P}i5Kq0^כ9nǾmef5J9d[m8 U'Pؓ\ݎr5^r>l'-+I̞:)W1[7KQ*uƍ(xØЍ%?Qx}Pί iU=* n%铜 0Yd)ӊ~H~fA4zonŠÓ% .:µg\|.3*12=ş?㘊l5脋ir}k5?Le━yR:EN.yasdyJf%s0̠pYѝZPR\')\HN+I}TXn]c%$I"JQ#w ~8rkR^1x(W~oUo"?X•kiK)#ƻ.X7&.>9G8ِnS NGX_Jcc׾]xd8# 8_/o>.zEqmJ^|K8aBdVl'dm乶nQUҟ%P}S[V"Ev"Cwp+,nxxf8,t*~{ 3!d)y hm%s3iYOv=gb͡>ڈt]%+GmK hЈ;{|.nV&'b@;l_sxYG1Ûx`yD# oz/ N1󆚭F_g0s1p$},6^OۿoqkOJ2Y7}W }t2BXud3rut?ęìJZo~iXpЈ)Wjf6[{dyc րl׏xlaݟk[ٴy׼vgTʹh1r?[mCq*.`'ԛx.m.+x|z'2nXoX\L7KΏ+ R_$fᣞ:IQq(,a1χ!X#BdB&Ȃ1}.GփӷrLI\D̉mG*Yz#,P{r/o~B| ˫83-TIid]}46px7+uJdd;8yǶĉgcRЋ;`*;n:;qh~_o2K}sh5ݸ8N>Rͩ`͇fN+߱oVoW #)ȉ7"mڴG\/fȰ~Ɖy3ٝxp v El1pceҜ nY|qsk> ՗>m&x{ TpvY5ɒBaNzccFD^U"jvNOɟ;7mQ%VvΧd-C?udϕnO-:}+CJWZB܋s?u}:kZ0Ⲣ'%fƴ>CsAg&ɕx]嚟' ԅ ?9S%ia^¾1%*ִy͜hh=AJf~9^]0᫃T¢GP%cFLLR5ǿĖ-:̚NGKZ~ޥ~YޞSޘoqtbn:)C c =k_ҿu :zB=&ѫD k[ jΆMٰ;.e:dc<%~u+K'YV{v\k3oAk}{_f%ؐi cF,^`XٞH LWw%MYcάQT/AH9٥IJ1e_ʾ41U,WV&Oۛ<[͎f'CVèp*'f7(X^U L$q0_gǗ{۰}nM,8KsY!22˫_$"&"'+}! y)Ӭ'U} "OKq4j1r`]r~c=`$NDDDDDDDD DDDDDDDD$P0LDDDDDDDD DDDDDDDD$P0LDDDDDDDD D04l̒ a%"/PìS!O곙~AT+AQ2_[KKz=_+z"""""(&/ol D6g AUӫn 6JնXDDDDD^D0c4S+%&OWm<"""""/΀E%+Ѫ!S\!4b/eyQ҇?6x *gR?,M14默ö+́Yԯ9ռiCqm#.a+Ӝ۾bh뚔(NƃX׽cO.)_ZOj[l+p 6G17Ȋ:G}V㪯Q]dYpGRnn=6DC6кLKV]A78&릦[ҩ.KxPҧ>mrU_|?+PDE٪5<(؏o/ća"vtsJzC)t-yG=w2XvgjȠOfd;0s` 9 (}u}c2@9 :v`v7ݦ.`d77p%<NƳhj70f[w%btOVǿގ;)s,\NYbވVnG}&C&[AלF۪GħD!]妓,[|>|72uTyLY/f1vwfͼ,]汴hY`V3qQ6S0L΅\;doQxIƼ;E[ `TfxçK$BYRRmZ+B -6.-ag})K.xH^ n€ q߳]lgf [}dS-a|֤bO,7L|כ!M[5RS?{!ga_Z7{ u,>=X  N1;h2S!Or~;#hNUkpA4̍]>ZlGM o-o%Oͭ3o?= """"(&b\7^Z}e2z%[.*::~u N28;Ͽ\r%_K;\0Oj/ꍗWģKr7mtϓqqr~gӘ"w 6 7u@ù˿يO}&ߘNBiqxµg\|)#d##Syݖc*Kv G'H~6a"vΘ(]~NJQ. O:5{Rk[ٴy׼vgTʹ e`0f0[_;dhĔXX ~ֳx\c>m?E"YBh Suvscp.|x`:쑏MDDDD$P0LĮqe N"hm9uկ س}4g[+_F#%m{'rngz@7r~( H62l%gŶG2'gwr5uFmI,܈G}ONbD8,FT}>[t]ưbao_> 9Z29%tSG#6Fxe=CQvLjoo|N\l[̀K)""""" `=LAabԺYfHҡ`$LRDDDDDDDD $C0I2 $C0I2 $C0y~Wf -BΧig[`zu;35޾-3W̶3_/g]ۂeYr! 󵵴3^x?uÃLmilHDDDD$)S0LDDc4?a;v9zO˸ֹ81+^&̶I47mlVŶ(A/ol v{oFۖ ۋzl$q H"rRBs|˶_~⋅=d>n_OF{biQ3 aup$s]{Ѱ࣬Hl8=HDDDD$S0LDD3 wN``xz|+:> wOeDk_{S8oDZ#b39Od鲥A,gyRFq"oz~'r90|xwX.naJT,AItˏ QżܰV a[&|:/3}z>pI7rA  bF\SC3A.p;4Arbdv఍l_{ߺC*{<,Ch3 Es ew t oF0x.sLemےذJT%wX :v`v7ݦ.`d77pxXly$""""":FHNh}i- r#̵XR`A4'n1x0d}d̟9?bua=43htn7wdG*O*٫0.p 0ŝ0O3|< Ӏ%St!P6JJ^]~)6ţjܢfKYwqhǻERtlDDr@<)m''L\%CЋ;`*;n:;qh~_\ˉ4y.ވ| 8KɕѶ,{/Lwxˈ{3[zml>| ђ,FE?w)F"""""7\DD2]š_)[4w7qlR>8ڙ3*JyJ&""vr0j~.\ɭ xWa""bGL\~'d`2LjXW$DDDDDDDD$""""""""d(&""""""""Ia""""""""d(&""""""""Ia""""""""d(&""""""""Ia""""""""d(&""""""""Ia""""""""d,VܩSlDDDDDDD$ˑ#H\a&LDDDDDDD;ggg3CIH`$ H`$ H`$ H`$ H`$ Ha0 gob-g:j{piBl"K1ж&BZ6ı{0qfq*6_&ۢ(zM1!û/ٶx*NYRt ǻ=,%%~hZu?JSn{/G@m+"Uwk٪h?|){E*>iIu^P|X!sz8vyT+IZm0/Q"]i[1 Ά`ZbX<=:d/}5 X, O#qKry}DJD3 Yna`h>o[n5<vcSQJkr˶,3|=b>3=q 02*Gi//lo:=?OdGցt0mju?g=毅5we6n(v~VhBxrD[{g;t)^'OEr^_.c4ؘwRXMK&GW- =NJX8.M|)YZb uQ)+ʛEˣEHS~o9Mʗ|QoAjgËO^4-+I찥[:٨\*Ur9~ןs捦,\ir>惚8b BҧVfmKqƙddB3)۱oE=-q ûױk[0[z`KpgwZ˜.meZFT-IjM6DhqV,q>TtUc'71{rl.ұp*n /*77#upzƴE 4 YN) q7M>rƙLݜ V]櫫iS׭1=ɻfz>oj:Ϳ響ݳ)G Jж[9v-KòTu.ǻh%s!Ԛ{Y [DK&}0iU#=/Sޘ.P:$63GfOj4A_zf鎯Ѿ.=UJ9՗^ɻcݟx޼q;mc+;KN=>7_f=OVGK!O__Sb-+o/2NAY>Μbb>_9аb\d!ɞ5j:L4߈l 3{q7Ttz|迖todTWޘ"/֢hpKߌٜZm1{/٘7 TOK8>&>ezs^ߡsf_B^ in)MY0%eʂc_^&,'2gz?*73q6nX|c#; g{F t2=0cyМc7ڃ33/\v-<>!۾1#uf-μJ6Cyi3e' 7.rtQy+;ϺQ-?mxuG\(U )BbQ珙I 1OYmLX4r%оbƇyyX0m6O?gT3wZOb#sidz'c}M4&21A{Y0a'YZaT3obD=yJ؆KM(X.xO\b7/r܎kʕܕKyҚlg4[%K-GqչvʞJD/ :]d*Wםxͳ4Y(JZ879JtG?s7}YVih$쩅Z=1KGi}NWHGQS<@zBoBLT7NKA/v[8+u;|(QGJ.:Tf owږCַ}_.AgG_z/#;|BNUo&+jl12_# I_zzY2D<[: O;b]~#sepph[`4`4:`}ip0Z_st?&bH. #uj乽NFxp-y^>w9rAߡmXm x5_=^m%#c!E iWrA=捅`SHowӝ7?q}w ðPE*ԥAܾxއ-dnދf%s%wi5͋nĸcm(4^K%8͋c6rS·Y䖵qeZNDl%y37vC|-sz6 S_$fOsTL]ˮt)5%e(*r3J?w0ԮO߫G27&Ca!3̗CRhaJTބ83Wqƽ.9Ź@ʘZ~~ ,IҒ{g yy\g$ed'"f1%j G'Ҽ-'{3Sz~)p|&.9Jz'vŝ6]cÀ1 !!f1`--䟔~&wswIGaL}euO}X~ĥJ)9MMܭ&rsp9ЛdŨ;7_ |cT rcٓI+P|W˸֣z+̛4y͊&k/`JWK5HTIsu[>Qñ_X:c<:|J w dz4/#yEcPduiTkx.('27nG6o;9Rؑ#OXMv;K>^hQhʯTW">7Y%(Qs~a\Rd#3̙)aogвe%JSg?]Mr/8 ;8־M?s>R 2oSpշ)RG[ƒK<;y6&>,` Fa̷u>Qanxk>d<- N>.Ooq1-GٿٴzD%;~H ! f3Qj ?$Sb|hɯTW"Y[kw'A\Hx_ :z4 2IZk1bL:y9f|/C*2%Z.B ɐҁdlٝ'K,IKP`[.ϓGBA\GS!_|Y[% NQWT‰$te/'M=ȒE\t/.G1_ÿ~Af O +Mc3S'@dIo3;3ՠ{Y9~Gypq;ESβMQ*nk9ef #3f).4iR+ .`5e-n'RX9r}7 "͌E_ЭY5J_| l.}.oݎlwp]~{ƥPeGKv+-bUZOGMʓ;kV^5d0t"#n)2=1+xIɐ%)^uX{lYc'8\w>nKѰ- ]I{t<Lg۱vRkJNkLϘ=;S|>WmY4%YTNS.NJ/2d{?{e|7΅k%oF>o-ynw xU6 ]FiDkۭHپěl#6j!~^I[iuhi[D$vE0NwS33.٨Y%5r{qC;k ]]ƠvmjPs4v;rk-gk} {3}PW9%Qw,UKVt wf ףY˟bݦ3K!X㐜fX,2[6yq4@%ogcԆNRo,ӿr[ыeƤ0;//wnL9rĭp㾦U :|޺Yuc ύb?X;;g˸EPġeݭSV%^~a0|1%+g˺|/{ϾBw0R`J|j6BX$Y~}R5V89&ϽgƓ",'O clJؤ ˤ׶1T)]2U+3d]>eٸ2JWY2nbLۏ-۩5ƫ*m"""""Q`H,\zN߷X&Ke2xGoAH;xmty#ޣW,d:^sӗ.A >)iMˁz4 &&ݧ78UM?nw,I0"6f}/}Log1I=ބ䔀,,Odδ>|hvp:2 )ק8̥|ٙ_bðBcPa:<FT WLLn5uL&w.ߏ=G?co̾N37C~OKqm<Ps-S6O0X.܉(O& j@F'0)мC7BPEqG=$~4)S1p'ZWEr~AX 'yK6א*޶̤mփŲ.[i6ɅZfQ:E2swl @)7kw\][54.WE0ܸedTS"ȯ288`4͌Q*'OsA~$h8AmP.[||-f=)a;ty;,ģhE:rd-Q $֕e'}J+y/ rI 7HYi] ܲaSzl˓ N)q?:G<ٗ&{gOrg'?@C^U/f'Y#VNȕ-0j{9t<0+JVw[0ħ` S r?c]?g+*)חcZ9SJ MCȇ@nsw+ahl$QB3wltLDd7:DLp~8'DL0XΘ_]))‹;Ѡn~6ƴlD[욃*F2z҇Ap0L,Rc’,_n{Τiܖx\>("A|gt`p)<=VN"ap~z Yg3';=*ѻn"""""B0X-f12M: Vu~NCf(+%~zb֣Cن͌We|r'dKӕ ]ws$v `HfpӇ0q.<˗N"u%I \ei^;E=|=/qት;<qpB]W|4nS3QuOs|R[…n^"J*1xʘ70tRv=&1j/f6U ċB~^-}cⷃ'8;L)"""""`{yM|NΪEDDDD$9;dx7H=DDDDDDDDn(&""""""""vCIKmg DDDDDDDDn(&""""""""vC0 P0LDDb|Qs xyAҲ$N> Y=PL *jMc|st{=kĂOw/ʗDlz.qfv\,לeWNm{`9ާX~6ve:yZd \0HAw9` mbTQzzfNr٨Ҡ 1D,#""""" H\SRr+ogؽYz}JP k~wF^ӝSd4q$kzgl Ҡ}#OYDD$ƙ;V\|l0?όJUvlu5!]d, -dj,4bA=w ɖ0t3 }W7oPj#gpmSjH%(S1]pi&`XZT*YeҤ{w_擜IW,[ϱ{{z#Q)me)7к6I/gW)Qtb궛hED$f\fɤd|"sCӯLf0vؙ!CL7>|Ŗ $MGLɘF̈kB7G*q3* 47:wZ|kV딙L\ {kS2xGoAH;/cJᗓmC9>(Yž\zN߷X&KewHX8YDDb|qld~ -%Lޱ-j ӐyRqopƴH0mc+;e\0 0q0CA!m@n |؎!]/8F4lv@^ ވ RBMl="/3J8qpmA(<,܉(O& j@F'"""""!DD$f9 wȀUW_ E22ڝlE=zvVd?zI+QݏT)E"]"kE-JGYI)̝[,|X0ctxt\AQ6e \^xk&|n?j~&` R,@g"""""DD$fpu +pcd}z`|fHDI^+fVfQIKw=y=Kf1-m.J 嚽2{7l'wUrrzNiO^މu(DDDDD욂a""K#UԘ/_>)jZ]񃦱˙ĩ G Wy2& I^NzFL=Ȓ6,X c[jϕG-;U sv~.9&~`nnńO44oO;X[R0LDDb #4 GsX&vM1DŽ1^sظ/7A$6EI, x_ oG;pʖ=z, g-Q%?~린J60pF gY?}|$"[Z=0_DDDD$*t,""1iLN ݾSd}8;杕r㾦U :|+na)(\>7^?^3FwujC[q7_%x%}긳i`K4J3dD-ҟQ枻*JG+ {0,Ճ;2bM@Ǽ?gLDDDDD3-l_мثX;e IS8MڟU"q:H qvv;3LDDb CE֌ǘUzvcO^䩚 H4P0Ew_-ENJ5LyAy#3L"DDDDDDD(&qP0LDDDDDDDD솂a""""""""b7 ` DDDDDDDDn(&""""""""vC0 0-l_sމH\9sf;#Fa"""""""""on` DDDDDDDDn(&""""""""vC0 P0LDDDDDDDD솂a""""""""b7 ` DDDDDDDDn`=(G˕\7[ꅩ=_mBA"mM4=lS =!;>ؓ=sixD+8k|EIj}w֒C"po`ံԯ\TيAp;69 f}Mje)b+~LA뉉,2/F/yg%k3ܳ[ŅW.T̃R՚k~`IWq>ۊncsuqmW#FHmKtxc,lf9=XD$΋0=كg'Y5i?}K ˆSEpvޗts3s\ RI}^1(m7RP&OJ wB;}z}88s̽FVØ`.Sz%݉)|aΣҼDTj紹k3;wutXUweZjp7XocT˜q _Kg? 8.:0i0z0WˆQnԟߢ=m'Q R//\ yk(txcɛ;iXܣt!s S< [n3?8eTs۠Pww7,… Y_UƙLoYǥ̅jM7}`#ܻ|isMoofbGxΚ*l3ggwoosŸm,ӼRfOܷ|~$ۛ7xZRx{)sUOlk+͋T07<>>7]cETtC/u)O_cD$v{H4VPbLװ3)_AOpIL31k+pR&dgHdߏxg/!w E-]cAzpq3R2;?͘ 7צp2k<46jˁX|1㓹`ar&v$ϛ`|n,@iڽ ?t#o?ר4p.FU!14t1n&dJxaX&X8~Ygi#cnencHAHޘѣu ^G9k"7{[L\ o!]7o%8ZW:3ndC߼w P>KO2?O%3c7 Ƀ}8m+TfC|ԅ'A9olRtfs4'q뻁&, ,T_|:1,oF}5>am.{e.o˩Eu~Ge {S7`snXS2J9ͼ;If<iGo1(6HҀ(]tQJOd"7oݎlڈ+٫:y=̴;XO2>J^(_p7?3E#Ry_Haf/i*#*Kjac9} e⌆*ZO*tڌT+ ,<Fi|$OV&6R$nH}ch?Lw55]mOឋX<1]i^ >qΆ\5<;=뽊{D{>*B;0Gn]±GGnK@Ru@=iW=2pgHmb$>4+,Ѫi /r7ȄiM(/eRn֢FGӟL>:#&*,288`4X-FG,&YD_ %/ {wLȩ,އp8^)>n9^x[>(|oD-gOhCG־z6fφJ ،2rSnO5Mxufw }ڏR#ӨX"|x۾ -{ѢD6g/K1^?2Puik.('R7nGڣ,';Vs&Eed+1YMxiKg-l'Nw_H\*G5ϱ5MAB,9g(G$/>Q'1}wmF7I 3Ǐ?$8R:D!χE{1tu#c}./gIG< Io3;3L8zGyNd|7W7e;Xdu2! |Ϛ)$Ȕ'lHLd,^^̠e-n'RJ ws}3G$} X{Lg̝ GZ5e(Ukt[ v;i߉Bg=ou dM[JR(̲%_pfz*ns| jɖlW MݝЪi/--kY0 mF!yݯ h[֗}ʀ9}^v};2ߜ4k(KތR%FΦ9a*} IwM{~qeRK^#Gؾx$XaԮ:&J|/{-u?/N"{6]}hE{`vLO8V 0i:FѾ,}*8,I7i+.T'(܍$F}5;qlbZ4IW.Ǧmct-#IK4y=,fۑ]9'O,D|̀Kz]sv.̐_{7^4+tZ26.}<Vl_EMOv??5 Qwuhi[D$vE0މOښaKvjUKC_kjMgLB~2!?Pu$3"q$ƀ[̘Փ޿2_':tci0j>j~tSLZ9/r\gt6;(s {&5=)hF }$~d J7^sR+ڷ͸6Bn+zQ=̘CfХyhӉegpvr%JwaI})}{9:|ń;v[[Xw9hwlJ ${l~!]B+Wag7Og"ٗ3iՒxxxPLr&-cPj)GJ1Cަ'cYtkph{1lM7~yǷO3̫xeZ ZƉ{ L3jRڣ `տ0"\ ?|K>ъ!?l+#Jx| csdIWYc&y!U(s/)O<)޿VeZJ֯Hݩ Lpu S:ԡbQUG۸zWfȺ4е^HޖeOZ +*m"""""Q`H,pz]Gl#IA|7k `aQ6&w ֔ olKeNoDh';8ǂ].,`Θ;8v}7p#<mƳhhj60zn[a:El{lt3֖a )X8~Ygi#cnudS"ȯOqHMy+ř\}Ǩ¼cPa:<, ,T_|ߪ+s"߰FdrٝBcdTȇG4*+ޏzdIDh^ *d:?_{,僂W1F4}rxMfҶEH,͛x*1p`3MѺ=$\c˳FwCRpbHJ~JYX;ÿ1J a7ȏ1}=*dρYU#Q<܁= p{=Q/'JեzFk]ȐCO½ ODb9<ͨ~/}TU:< Հ-+kpdMϛy]epJe+Kx8ߓ}i>s>]%K yUl\E'{"[a $sy(kcJ_l7ǣF@H)%y1N.1ED)!L[܉Bd#&9mcb2& G'fNMDDDDD"`H,gLP c崎KyӾv͞s #ԥӴ?욋j2fAp0L,R6dլ^m{ "SnY<.arGNP K3:Aa08v{~~}YQ+'08?aͳӓ͞[]7{`H̍-; VyZ1:qm[՘4g=[֠dT8=gsogq?%yR=y@LYp}ˆ$KJ ˑƳ"J睧#̉Rݜy| E QﯗIXH=N51q^9g$kG0. jF󴁌]'%l5IJ\箿r ; fȯu~O à| q7_#?[F|ʝ8s1{-|KDtSE#6FhN9z Y̶#'ػrOYpM6.Q۫/ؔ*0t68΁ S3Ij4%m"6:G $,ًQmrrz>mގ!?ޠD)t[ ΆM٠+eĘd{<}] y=[Kyb:lx9h7s=wZ%ܭ8i_-һ"NH(c =R?зUs:}{&ѣhHo,_^sR+ڷ͸6D+^D2P[#׍ΪEDDDDDD3LDDDDDDDD쇂a""""""""b7t ` DDDDDDDDn(&""""""""vC0 HJf@ۀtq>Mj;ޥ>yPZszmL٬9o """""o;DD$ >ɪIփj紹k3;wum<%.-mDDDDD`!81+4c{a?W sX;>,buz1Ur/XǥW&"""""oDD$;M?Ga7Cu4~-[UTRh;Pdw&s,]>ӈqE%{1Τ){8L߯iT8ܧ =ep-LPE=(Vni"""""o DD$f\b]d9ʦf0Ɛփؑ1#gMGLe%Yz2eDƔ4bF\ YrA\yaNih1:oF6͇oՍ9mS.|_DDDDD$nS0LDDbЬDvF90\ 4t|i֟KYcZQ`$iz1ɤ[˭?2j1˸`*舃 8 ;=뽊{D{>*B;0Gn]1EDDDDD HrJIl ''_-de;ً121`xC\VvV2TneHB|Ț@=`0>3$"(ە[iz6\A"N:ҺG '%߳-JDDDDD$S0LDDbxʝ]>Ùjvy9$M |8HVWDr"i 8wC#_&5dMh&"""""qa""KIQ)%al?rG2n{m9&J|/{-u?/NfafE{^)Uadl:pghJ~_M05*1dF/ ]G6W6:~ g'W¼YybR_J^Π_1a3uN]p9hLDDDDD6^DD SZ!<5?jD'NQxH3LDDb CV凸r&gf܊> ha""p W|qK2MӣA>򍈈DDDDDDDDDn: DDDDDDDDn(&""""""""vC0 P0LDD:p@[W.GQ*lŠd]O96@DDDDD DDte S)v']w;_>6K >ɪI6@DDDDD^DD$n3V jMN7mD0W$7%ykA811-]d Vu#W"""""Gg ǖ1E5X%!xgexǏ nUEh}|?b-LPE=(Vnzq;aQ ʁT{0c%׀"NZi+["u&g27eK!P8J""s0noݰd8<~s&3oNҷϢţa[moՍ9mS.|_W/_sFJf{'CaV޸69D-gY0d98Z,=2g"cJW5"""""qED$Ƙ#{5G><*էQD\ѳMfҶEH,͛x*B;0Gn]1_W}kp'k[G־W)""""б[V**:;>7ƇpJNl 'Ẃx@`bN|I0 q5pv<w JHGd8>A01&-hRNk.uȚp gor '_M \"=sl_ CpTap)tH`3w-`jL3-kP2w*cFS[&0&)zmbڲMlݲfji_9"""""w)&""1ƭ`gwgC&lЕy2bLm2=.h.<Bt3_վnƵDfw·mtr_Φm8 vQ(LëCDDDDD.^DDDDDDDD䭦a""""""""b7 ` DDDDDDDDn(&""""""""vC0 P0LDDDDDDDD솂a""""""""b7 ` DDDDDDDDn(&""""""""vC0 P0LDDDDDDDD솂a""""""""b7 ` DDDDDDDDn"""o <==d2نJTԟ}Z:흈ш+I$6TDD)&""vH0!6F£ۻ7kʶwoƹsȜ9ӛ4<7ؼm^Tpp0ˋw}GGG$EDnX{Ya%R LD$zZ[qW` 뭑a""Xok=."" a}FzM[z` DDDDDDDDn(&""""""""vC0 ݈`9 f}Mje)Ajb z8|V63>-IF,lz]O96 ,l֜ xy-/k|JՒ)Q9VlL<=o?a?!o&ƶIX.3vrӖ]WL/ l-li0ye̽`)Wј^ߡ!|X{0QS1!|ts'ӻԧR1JUkN9ZƷ=S%| N{ ӇOkƣh%X' |݈,+Z>3,*EXTDDDDD0'}Nj3eJﺤ;1/:<7wNn ~'Y5i^tfDS.am=9GLcT~ts~ƧXȏm𳢼6MxL۹輸7;}V_ᵜ6Ge@%n=ų|~fho*y*&fVXt=e\ޙk/k7fBs=)v)x%\@ׂԻFGM7e@g/aj\Յݯ)Ė2=OE^OU5l@L73[1YfuI.'ۀuo x +.q?fs6Ptv~o,k]xsQLe3}-W97MaLYd xOo3l'ߜ{._<UfW,7u5uqCDDޜ cc,\y)\& ,>g3&GM)ulX1z=۰)bߏ&e SQV1yn9$˓t xE?#:6yT䩚_Csx!ӭۗ%>,엘HC4Ońٽ3X|=Ây)VZ%gu\ TMt: m~|/ی?|Z ^tbѱj nBqXnvjY$U;ЫV-߆=?l){-v@_оM>sXo RSTAҸ:8&*x6 &g̾NŘ #)9NU7lŴYMjz**'p Zu3yr2Y!&^?LF/&~/Hė-1jRyc8\;ØCi`jKcODD&f*fL&3=y! v 3!;M?Ga7߯pu S:ԡbQUGC .0^jN˹eSLG82r;*E,•h^vˍ2XGIi"Th4UiZF"v7J2g9D.[ʌY#ȁӨ>3.pO%>zkH0u S{pagQ)w|[rVȅ]Vʲf3e[Bٞ{ø?DdGZ)[nг67ș߲W/ICp[D3~l:YwmZKP@~:N g֔Cz(R" {[tf#>jK<(h\ DD,;g/,/3g̉= c ػxӒŽM<8~٨R(mYFˌqV ?K=錻CXx,E07}lZTLa>-V=rم-stOItH.=' )T (U4ކ`fW| t OW]i87KDX;5\t/=X}D.=:pxpte+q=qhL\SQ6GrJ^:[r|nU?A,(^{1O dǁ_f}DDl\rC9mCȌU[9q1> &gAY%E/lر۸ki0U7VyL^z|SQx2n:rt8[g9Y=eɑ}*Uȃ7v'یg0m`-ܶ,twCZbGƌ53mzn{Pb%Yz2eDƔod\֖|C7o>\"ZGמBdeʷR^$ 8=# 5n(vzqjX?;~yO #Fe{<~|'zǾU9%#7q'hDxyeF\bkT8EfY`%<0q ŽGό&en= rA\yb;ek}'w܍ҢZiJ:ɋQ-=9 |/μU7V4'h=V>;.c؛wÚTyP\.S茫%aA,!8=do|3^doѿg;lc Zh~ \x^_ǷI9/3O/'ŹMw0v &|C)>+6Fb e̹m`vngI]3I.9Œ<.FIdp"OT~4 #/=Gk@"n<{8pThLe˸?,m`&2<\<7 \1;\]61OZh̭0/ 24qx|N!ţ:P19~ӕP/t7CNh4k9Zw{{|T(*w`D^cPnprtZ~/4ץ,gtDo4:`96688`4D/E@@ 6Z>3ƑUd˷h$ؖXC+z!l߈ލ28"ޖ "_}zy> G־`E@s܎>%7 xX^y2fIJzT˳xf"NmZ~Z֊ RqKp^a3,'Jb_}I<V.3H^'*G\Ұ|]|^5e\0)ؘbOjU<~ߟ@L\mJILܐ~{8e^2eQv6$mfY/Z<;NO1WS*yãR}KHOtzf&Lݵ7-y+`]u؍9|R6nu AViY33~8e{g-b6}E'+Wf2?8.`wP>nӁ5rc>߮y"o,Xu]+gbE9Fas~h1o%~ػ6Ƹh xr䟤$[u25#au缯Scg8!A2 d櫜l[טߟl:%M4;ka΃|X0g/SХeq4D'i*7LIwMq˓iǒNb$_lXNJ0+cW>-'j;ff~x씒g%Bx@`bOg$q¤??pVUӪXqTHp [0>HΫ¨n'/r5s!ۣid./|阘mn%;:4s2[)>bJrez).ːOF)#v7\)e IO}hXѿ߇g &?T>ʄ9 ;'5̢]_i/TUÑu,v4}>oJw{((3wp&O4k&A͟Z) ?,NԮ]YӨ2%}R%p=| g+Df Z~?rR4unA߬j3#Ѩf&|g~4,np1 {!KւV K Bb7+}&>z ?S¤{r0$8Iv=B\|ӗXtbڢ5l>E,I"`ڏɈ\hݲ$ #9%cRoZZf.;ƬT:=cSҌ[ 2YגP`6FIAFmoL3xi,K0y.jݲ+o;)F>lWaܱO]M+%=|UqopL䪖2!u:{mڴN<5R'fπ{8ijQ5dMb94&@wi .D$W~aoI[!?:JDIÙ_3>/(^bd5揓?Zǿ;Ɣ$`Lx1Ϻ-H qzn_I) OpِdɒY^IqACWqUΕ򂹱e:c"A42Y+fQa?cYg8&x??_5/="3&Vo%ϝq~ˠvy9$M |8HXMMw0r0KbdzuϿGfLA$MZY?[$2-^t{okWcҜ lYSbUn=՗};P6J@B9q/y'r~9b 2gBfepL/ӽMr'g1nB<̍#i4 rei´/ed0$;ǩq<{1Ф`Xw#5# g^Qs2X)՘iXg՜2R&}򾗞^|qJޥٹ4{dy0S:au7۫Gy6*F~-m,7Dn0 h[֗}ʀ9}^v};2ߜ4k;/ؔ*0t68΁ S3Ij4%u GR)N8}&u9mQrsMgPa$E٦|C/ɸ=>NF^u6և^uA{b'~9GrI Z@e|NI&-; Mz} C&fc>Cobc &x~n'0Ѭyc;3BΧ)HB4g82vϯKvbs{:y?FD6g<~ח#i,O??d+8=_F1QL~ٳfoyqYS̽C+ +ER]gll{m=fѲ=q9:f3n5Q&)64l![%迌Q0N_yj@%I7Wa .q/I\*S1Lj[\“w?厳vc@# +H v?|d/ @4v?\~t"j:&'{hL`h.XNFOʚ-ᚹe5]v5dg.LLo0r 8 >y,.fy?g ɘ 'Cygɗ%mL.cigc>&Y~Fp7zzsJf/dl%Bl%5 !9cVqdㅼ\ogЪK\%YL?S"""1.Fa8a "+7NgP/7l*Jih5NBt3_վnƵDfwW 3PEn⒅R,XIP2JgfO3&Đ(ti=tb_Y.\1%E+kF+8M@Pdohߜ$W]*=O6~%{X. vN1~tRMV|OxWw}K=/fN㳴[KZ~0<<"}dO3d/F]y;x9_[`X,[{;3ffXF_0l#G&G^{kԗҷ3WLLݱSi*_y 'ݿݻw:֫$7ٲ/o>3UG2[!m8^5uE\ߍ%mXY^yfzPߝ }PAW]+ˈ1x.'l\.SsI|~bK\{;?.$IjۇƄ9(&ן9_)%SiwU?ʑ/qFBCz]pێsgwCbk2#;s$gw%ŧH"ש;\}_x RHCV 2/yq9t)#O7Нl?zeJ)S*Fn58mR\:Ci=Cp/1 3iRȯZqq:m(cĎuqz ̙b<[.xqFXS))$bcfDw5+O ^r_ud&}L]d#Awi/?w d-Z:rڞW,^H c|١8ߗfinYNf ZT/ w0@QE '9 A+Eso~Bz(NݐQRȒ'0nU_7 BӐ%z\dʮޕŝ9 {$^6 M\lwN)eri0*#C>_P8Ѳ{;u$+MEHhd-#V@>tP x]̔u]ț;]'_.g+'dPTo 's:ɏpޣGId)swt_u,_{ƭv)qc\cYD<ԎzQ0,J/,ӆߓX~.~Ǘ3"{dj1ܽ-`ͮY\uXNm"ӘP9ᛦ|'$ռZ0,X0,ņ|4<N[l6m]/Y: 3*:Q*|:jƨj cJ= ^!>>y}e)_ D3i*vaښ߿0Q."o1Ej{g㉈H` DDDDDDDDn(&""""""""vC0 0>H\bȫRk"""vՕ{>H\bȫR0LDDF$Iݻ!&"GXkkmȫ2-lEDDzAAAxzzd ?ݛuv;[#=¬0'''P` &)""""""""vC0 P0LDDDDDDDD솂a""""""""b7 ` DDDDDDDDn(&""""""""vC0 P0LDDDDDDDD솂a""""""""b7 ` DDDDDDDDn(&""""""""vC0 P0LDDDDDDDD솂a""""""""b7 ` DDDDDDDDn(&""""""""vC0 P0LDDDDDDDD솂a""""""""b7 ` DDDDDDDDn(&""""""""vC0 P0LDDDDDDDD솂a""""""""b'!v{IENDB`