ensembldb/DESCRIPTION0000644000175400017540000000440713241155731015250 0ustar00biocbuildbiocbuildPackage: ensembldb Type: Package Title: Utilities to create and use Ensembl-based annotation databases Version: 2.2.2 Authors@R: c(person(given = "Johannes", family = "Rainer", email = "johannes.rainer@eurac.edu", role = c("aut", "cre")), person(given = "Tim", family = "Triche", email = "tim.triche@usc.edu", role = "ctb"), person(given = "Christian", family = "Weichenberger", email = "christian.weichenberger@eurac.edu", role = "ctb")) Author: Johannes Rainer with contributions from Tim Triche and Christian Weichenberger. Maintainer: Johannes Rainer URL: https://github.com/jotsetung/ensembldb BugReports: https://github.com/jotsetung/ensembldb/issues Imports: methods, RSQLite (>= 1.1), DBI, Biobase, GenomeInfoDb, AnnotationDbi (>= 1.31.19), rtracklayer, S4Vectors, AnnotationHub, Rsamtools, IRanges (>= 2.11.16), ProtGenerics, Biostrings, curl Depends: BiocGenerics (>= 0.15.10), GenomicRanges (>= 1.23.21), GenomicFeatures (>= 1.29.10), AnnotationFilter (>= 1.1.9) Suggests: BiocStyle, knitr, rmarkdown, EnsDb.Hsapiens.v75 (>= 0.99.8), shiny, testthat, BSgenome.Hsapiens.UCSC.hg19, ggbio (>= 1.24.0), Gviz (>= 1.20.0), magrittr Enhances: RMySQL VignetteBuilder: knitr Description: The package provides functions to create and use transcript centric annotation databases/packages. The annotation for the databases are directly fetched from Ensembl using their Perl API. The functionality and data is similar to that of the TxDb packages from the GenomicFeatures package, but, in addition to retrieve all gene/transcript models and annotations from the database, the ensembldb package provides also a filter framework allowing to retrieve annotations for specific entries like genes encoded on a chromosome region or transcript models of lincRNA genes. Collate: Classes.R Generics.R functions-utils.R dbhelpers.R Methods.R functions-EnsDb.R functions-Filter.R Methods-Filter.R functions-create-EnsDb.R select-methods.R seqname-utils.R Deprecated.R zzz.R biocViews: Genetics, AnnotationData, Sequencing, Coverage License: LGPL RoxygenNote: 6.0.1 NeedsCompilation: no Packaged: 2018-02-15 01:01:13 UTC; biocbuild ensembldb/NAMESPACE0000644000175400017540000001431713175714743014774 0ustar00biocbuildbiocbuild## ensembldb NAMESPACE import(methods) importFrom("utils", "read.table", "str", "download.file") import("BiocGenerics") importFrom("Biobase", "createPackage", "validMsg") importMethodsFrom("ProtGenerics", "proteins") import("S4Vectors") importFrom("DBI", "dbDriver") import("RSQLite") importMethodsFrom("AnnotationDbi", "columns", "dbconn", "keys", "keytypes", "mapIds", "select") importFrom("GenomeInfoDb", "Seqinfo", "isCircular", "genome", "seqlengths", "seqnames", "seqlevels", "keepSeqlevels", "seqlevelsStyle", "seqlevelsStyle<-", "genomeStyles") importFrom("rtracklayer", "import") ## Ranges and stuff importFrom("IRanges", "IRanges", "IRangesList") importMethodsFrom("IRanges", "subsetByOverlaps") import("GenomicRanges") import("GenomicFeatures") ## AnnotationHub importFrom("AnnotationHub", "AnnotationHub") importClassesFrom("AnnotationHub", "AnnotationHub") importMethodsFrom("AnnotationHub", "query", "mcols") ## Rsamtools importClassesFrom("Rsamtools", "FaFile", "RsamtoolsFile") importFrom("Rsamtools", "FaFile") importMethodsFrom("Rsamtools", "getSeq", "indexFa", "path") importFrom("Rsamtools", "index") ## Stuff needed for protein annotations. importClassesFrom("Biostrings", "AAStringSet") importFrom("Biostrings", "AAStringSet") importFrom("curl", "curl") ## AnnotationFilter importClassesFrom("AnnotationFilter", "AnnotationFilter", "CharacterFilter", "IntegerFilter", "ExonIdFilter", "ExonRankFilter", "ExonStartFilter", "ExonEndFilter", "GeneIdFilter", "GenenameFilter", "GeneBiotypeFilter", "GeneStartFilter", "GeneEndFilter", "EntrezFilter", "SymbolFilter", "TxIdFilter", "TxNameFilter", "TxBiotypeFilter", "TxStartFilter", "TxEndFilter", "ProteinIdFilter", "UniprotFilter", "SeqNameFilter", "SeqStrandFilter", "GRangesFilter", "AnnotationFilterList" ) importMethodsFrom("AnnotationFilter", "field", "value", "condition", "supportedFilters", "convertFilter") importFrom("AnnotationFilter", "AnnotationFilter", "ExonIdFilter", "ExonRankFilter", "ExonStartFilter", "ExonEndFilter", "GeneIdFilter", "GenenameFilter", "GeneBiotypeFilter", "GeneStartFilter", "GeneEndFilter", "EntrezFilter", "SymbolFilter", "TxIdFilter", "TxNameFilter", "TxBiotypeFilter", "TxStartFilter", "TxEndFilter", "ProteinIdFilter", "UniprotFilter", "SeqNameFilter", "SeqStrandFilter", "GRangesFilter", "AnnotationFilterList", "feature" ) ## Functions export("ensDbFromAH", "ensDbFromGff", "ensDbFromGRanges", "ensDbFromGtf", "fetchTablesFromEnsembl", "listEnsDbs", "makeEnsemblSQLiteFromTables", "makeEnsembldbPackage", "runEnsDbApp", "filter" ) ## Classes exportClasses( "EnsDb", "ProtDomIdFilter", "UniprotDbFilter", "UniprotMappingTypeFilter", "OnlyCodingTxFilter", "TxSupportLevelFilter" ) ## Methods for EnsFilter exportMethods( "seqnames", "seqlevels", "show", "convertFilter" ) ## Methods for class EnsDb: exportMethods("cdsBy", "dbconn", "disjointExons", "ensemblVersion", "exons", "exonsBy", "exonsByOverlaps", "fiveUTRsByTranscript", "genes", "getGeneRegionTrackForGviz", "getGenomeFaFile", "lengthOf", "listColumns", "listGenebiotypes", "listTxbiotypes", "listTables", "metadata", "organism", "promoters", "returnFilterColumns", "returnFilterColumns<-", "seqinfo", "threeUTRsByTranscript", "toSAF", "transcripts", "transcriptsBy", "transcriptsByOverlaps", "updateEnsDb", "useMySQL", "supportedFilters", "addFilter", "activeFilter", "dropFilter" ) ## Protein data related stuff exportMethods("hasProteinData", "proteins", "listUniprotDbs", "listUniprotMappingTypes") export("listProteinColumns") ## Methods for AnnotationDbi exportMethods("columns", "keytypes", "keys", "select", "mapIds") ## Methods for GenomeInfoDb and related stuff exportMethods("seqlevelsStyle", "seqlevelsStyle<-", "supportedSeqlevelsStyles", "seqlevels") ## Constructor functions: export( "EnsDb", "EntrezidFilter", "ExonidFilter", "ExonrankFilter", "GeneidFilter", "GenebiotypeFilter", "SeqnameFilter", "SeqstrandFilter", "SeqstartFilter", "SeqendFilter", "TxidFilter", "TxbiotypeFilter", "UniprotDbFilter", "UniprotMappingTypeFilter", "OnlyCodingTxFilter", "ProtDomIdFilter", "TxSupportLevelFilter" ) ensembldb/R/0000755000175400017540000000000013241131543013731 5ustar00biocbuildbiocbuildensembldb/R/Classes.R0000644000175400017540000003446713175714743015506 0ustar00biocbuildbiocbuild##*********************************************************************** ## ## EnsBb classes ## ## Main class providing access and functionality for the database. ## ##*********************************************************************** setClass("EnsDb", representation(ensdb="DBIConnection", tables="list", .properties="list"), prototype=list(ensdb=NULL, tables=list(), .properties=list()) ) #' @title Filters supported by ensembldb #' #' @description \code{ensembldb} supports most of the filters from the #' \code{\link{AnnotationFilter}} package to retrieve specific content from #' \code{\linkS4class{EnsDb}} databases. These filters can be passed to #' the methods such as \code{\link{genes}} with the \code{filter} parameter #' or can be added as a \emph{global} filter to an \code{EnsDb} object #' (see \code{\link{addFilter}} for more details). Use the #' \code{\link{supportedFilters}} to list all filters supported for #' \code{EnsDb} object. #' #' @note For users of \code{ensembldb} version < 2.0: in the #' \code{\link[AnnotationFilter]{GRangesFilter}} from the #' \code{AnnotationFilter} package the \code{condition} parameter was #' renamed to \code{type} (to be consistent with the \code{IRanges} package) #' . In addition, the \code{condition = "overlapping"} is no longer #' recognized. To retrieve all features overlapping the range #' \code{type = "any"} has to be used. #' #' @details \code{ensembldb} supports the following filters from the #' \code{AnnotationFilter} package: #' #' \describe{ #' #' \item{GeneIdFilter}{ #' filter based on the Ensembl gene ID. #' } #' #' \item{GenenameFilter}{ #' filter based on the name of the gene as provided by Ensembl. In most cases #' this will correspond to the official gene symbol. #' } #' #' \item{SymbolFilter}{ #' filter based on the gene names. \code{\linkS4class{EnsDb}} objects don't #' have a dedicated \emph{symbol} column, the filtering is hence based on the #' gene names. #' } #' #' \item{GeneBiotype}{ #' filter based on the biotype of genes (e.g. \code{"protein_coding"}). #' } #' #' \item{GeneStartFilter}{ #' filter based on the genomic start coordinate of genes. #' } #' #' \item{GeneEndFilter}{ #' filter based on the genomic end coordinate of genes. #' } #' #' \item{EntrezidFilter}{ #' filter based on the genes' NCBI Entrezgene ID. #' } #' #' \item{TxIdFilter}{ #' filter based on the Ensembld transcript ID. #' } #' #' \item{TxNameFilter}{ #' filter based on the Ensembld transcript ID; no transcript names are #' provided in \code{\linkS4class{EnsDb}} databases. #' } #' #' \item{TxBiotypeFilter}{ #' filter based on the transcripts' biotype. #' } #' #' \item{TxStartFilter}{ #' filter based on the genomic start coordinate of the transcripts. #' } #' #' \item{TxEndFilter}{ #' filter based on the genonic end coordinates of the transcripts. #' } #' #' \item{ExonIdFilter}{ #' filter based on Ensembl exon IDs. #' } #' #' \item{ExonRankFilter}{ #' filter based on the index/rank of the exon within the transcrips. #' } #' #' \item{ExonStartFilter}{ #' filter based on the genomic start coordinates of the exons. #' } #' #' \item{ExonEndFilter}{ #' filter based on the genomic end coordinates of the exons. #' } #' #' \item{GRangesFilter}{ #' Allows to fetch features within or overlapping specified genomic region(s)/ #' range(s). This filter takes a \code{\link[GenomicRanges]{GRanges}} object #' as input and, if \code{type = "any"} (the default) will restrict #' results to features (genes, transcripts or exons) that are partially #' overlapping the region. Alternatively, by specifying #' \code{condition = "within"} it will return features located within the #' range. In addition, the \code{\link[AnnotationFilter]{GRangesFilter}} #' supports \code{condition = "start"}, \code{condition = "end"} and #' \code{condition = "equal"} filtering for features with the same start or #' end coordinate or that are equal to the \code{GRanges}. #' #' Note that the type of feature on which the filter is applied depends on #' the method that is called, i.e. \code{\link{genes}} will filter on the #' genomic coordinates of genes, \code{\link{transcripts}} on those of #' transcripts and \code{\link{exons}} on exon coordinates. #' #' Calls to the methods \code{\link{exonsBy}}, \code{\link{cdsBy}} and #' \code{\link{transcriptsBy}} use the start and end coordinates of the #' feature type specified with argument \code{by} (i.e. \code{"gene"}, #' \code{"transcript"} or \code{"exon"}) for the filtering. #' #' If the specified \code{GRanges} object defines multiple regions, all #' features within (or overlapping) any of these regions are returned. #' #' Chromosome names/seqnames can be provided in UCSC format (e.g. #' \code{"chrX"}) or Ensembl format (e.g. \code{"X"}); see #' \code{\link{seqlevelsStyle}} for more information. #' } #' #' \item{SeqNameFilter}{ #' filter based on chromosome names. #' } #' #' \item{SeqStrandFilter}{ #' filter based on the chromosome strand. The strand can be specified with #' \code{value = "+"}, \code{value = "-"}, \code{value = -1} or #' \code{value = 1}. #' } #' #' \item{ProteinIdFilter}{ #' filter based on Ensembl protein IDs. This filter is only supported if the #' \code{\linkS4class{EnsDb}} provides protein annotations; use the #' \code{\link{hasProteinData}} method to evaluate. #' } #' #' \item{UniprotFilter}{ #' filter based on Uniprot IDs. This filter is only supported if the #' \code{\linkS4class{EnsDb}} provides protein annotations; use the #' \code{\link{hasProteinData}} method to evaluate. #' } #' #' } #' #' In addition, the following filters are defined by \code{ensembldb}: #' \describe{ #' #' \item{TxSupportLevel}{ #' allows to filter results using the provided transcript support level. #' Support levels for transcripts are defined by Ensembl based on the #' available evidences for a transcript with 1 being the highest evidence #' grade and 5 the lowest level. This filter is only supported on #' \code{EnsDb} databases with a db schema version higher 2.1. #' } #' #' \item{UniprotDbFilter}{ #' allows to filter results based on the specified Uniprot database name(s). #' } #' #' \item{UniprotMappingTypeFilter}{ #' allows to filter results based on the mapping method/type that was used #' to assign Uniprot IDs to Ensembl protein IDs. #' } #' #' \item{ProtDomIdFilter}{ #' allows to retrieve entries from the database matching the provided filter #' criteria based on their protein domain ID (\emph{protein_domain_id}). #' } #' #' \item{OnlyCodingTxFilter}{ #' allows to retrieve entries only for protein coding transcripts, i.e. #' transcripts with a CDS. This filter does not take any input arguments. #' } #' #' } #' #' @param condition \code{character(1)} specifying the \emph{condition} of the #' filter. For \code{character}-based filters (such as #' \code{\link[AnnotationFilter]{GeneIdFilter}}) \code{"=="}, \code{"!="}, #' \code{"startsWith"} and \code{"endsWith"} are supported. Allowed values #' for \code{integer}-based filters (such as #' \code{\link[AnnotationFilter]{GeneStartFilter}}) are \code{"=="}, #' \code{"!="}, \code{"<"}. \code{"<="}, \code{">"} and \code{">="}. #' #' @param value The value(s) for the filter. For #' \code{\link[AnnotationFilter]{GRangesFilter}} it has to be a #' \code{\link[GenomicRanges]{GRanges}} object. #' #' @note Protein annotation based filters can only be used if the #' \code{\linkS4class{EnsDb}} database contains protein annotations, i.e. #' if \code{\link{hasProteinData}} is \code{TRUE}. Also, only protein coding #' transcripts will have protein annotations available, thus, non-coding #' transcripts/genes will not be returned by the queries using protein #' annotation filters. #' #' @name Filter-classes #' #' @seealso #' \code{\link{supportedFilters}} to list all filters supported for \code{EnsDb} #' objects. #' \code{\link{listUniprotDbs}} and \code{\link{listUniprotMappingTypes}} to #' list all Uniprot database names respectively mapping method types from #' the database. #' #' \code{\link[AnnotationFilter]{GeneIdFilter}} for more details on the #' filter objects. #' #' \code{\link{genes}}, \code{\link{transcripts}}, \code{\link{exons}}, #' \code{\link{listGenebiotypes}}, \code{\link{listTxbiotypes}}. #' #' \code{\link{addFilter}} for globally adding filters to an \code{EnsDb} #' object. #' #' @author Johannes Rainer #' @examples #' #' ## Create a filter that could be used to retrieve all informations for #' ## the respective gene. #' gif <- GeneIdFilter("ENSG00000012817") #' gif #' #' ## Create a filter for a chromosomal end position of a gene #' sef <- GeneEndFilter(10000, condition = ">") #' sef #' #' ## For additional examples see the help page of "genes". #' #' #' ## Example for GRangesFilter: #' ## retrieve all genes overlapping the specified region #' grf <- GRangesFilter(GRanges("11", ranges = IRanges(114000000, 114000050), #' strand = "+"), type = "any") #' library(EnsDb.Hsapiens.v75) #' edb <- EnsDb.Hsapiens.v75 #' genes(edb, filter = grf) #' #' ## Get also all transcripts overlapping that region. #' transcripts(edb, filter = grf) #' #' ## Retrieve all transcripts for the above gene #' gn <- genes(edb, filter = grf) #' txs <- transcripts(edb, filter = GenenameFilter(gn$gene_name)) #' ## Next we simply plot their start and end coordinates. #' plot(3, 3, pch=NA, xlim=c(start(gn), end(gn)), ylim=c(0, length(txs)), #' yaxt="n", ylab="") #' ## Highlight the GRangesFilter region #' rect(xleft=start(grf), xright=end(grf), ybottom=0, ytop=length(txs), #' col="red", border="red") #' for(i in 1:length(txs)){ #' current <- txs[i] #' rect(xleft=start(current), xright=end(current), ybottom=i-0.975, ytop=i-0.125, border="grey") #' text(start(current), y=i-0.5,pos=4, cex=0.75, labels=current$tx_id) #' } #' ## Thus, we can see that only 4 transcripts of that gene are indeed #' ## overlapping the region. #' #' #' ## No exon is overlapping that region, thus we're not getting anything #' exons(edb, filter = grf) #' #' #' ## Example for ExonRankFilter #' ## Extract all exons 1 and (if present) 2 for all genes encoded on the #' ## Y chromosome #' exons(edb, columns = c("tx_id", "exon_idx"), #' filter=list(SeqNameFilter("Y"), #' ExonRankFilter(3, condition = "<"))) #' #' #' ## Get all transcripts for the gene SKA2 #' transcripts(edb, filter = GenenameFilter("SKA2")) #' #' ## Which is the same as using a SymbolFilter #' transcripts(edb, filter = SymbolFilter("SKA2")) #' #' #' ## Create a ProteinIdFilter: #' pf <- ProteinIdFilter("ENSP00000362111") #' pf #' ## Using this filter would retrieve all database entries that are associated #' ## with a protein with the ID "ENSP00000362111" #' if (hasProteinData(edb)) { #' res <- genes(edb, filter = pf) #' res #' } #' #' ## UniprotFilter: #' uf <- UniprotFilter("O60762") #' ## Get the transcripts encoding that protein: #' if (hasProteinData(edb)) { #' transcripts(edb, filter = uf) #' ## The mapping Ensembl protein ID to Uniprot ID can however be 1:n: #' transcripts(edb, filter = TxIdFilter("ENST00000371588"), #' columns = c("protein_id", "uniprot_id")) #' } #' #' ## ProtDomIdFilter: #' pdf <- ProtDomIdFilter("PF00335") #' ## Also here we could get all transcripts related to that protein domain #' if (hasProteinData(edb)) { #' transcripts(edb, filter = pdf, columns = "protein_id") #' } #' NULL ############################################################ ## OnlyCodingTxFilter ## ## That's a special case filter that just returns transcripts ## that have tx_cds_seq_start defined (i.e. not NULL). #' @rdname Filter-classes setClass("OnlyCodingTxFilter", contains = "CharacterFilter", prototype = list( condition = "==", value = character(), field = "empty" )) #' @rdname Filter-classes OnlyCodingTxFilter <- function() { new("OnlyCodingTxFilter") } ############################################################ ## ProtDomIdFilter #' @rdname Filter-classes setClass("ProtDomIdFilter", contains = "CharacterFilter", prototype = list( condition = "==", value = "", field = "prot_dom_id" )) #' @return For \code{ProtDomIdFilter}: A \code{ProtDomIdFilter} object. #' @rdname Filter-classes ProtDomIdFilter <- function(value, condition = "==") { new("ProtDomIdFilter", condition = condition, value = as.character(value)) } ############################################################ ## UniprotDbFilter #' @rdname Filter-classes setClass("UniprotDbFilter", contains = "CharacterFilter", prototype = list( condition = "==", values = "", field = "uniprot_db" )) #' @return For \code{UniprotDbFilter}: A \code{UniprotDbFilter} object. #' @rdname Filter-classes UniprotDbFilter <- function(value, condition = "==") { new("UniprotDbFilter", condition = condition, value = as.character(value)) } ############################################################ ## UniprotMappingTypeFilter #' @rdname Filter-classes setClass("UniprotMappingTypeFilter", contains = "CharacterFilter", prototype = list( condition = "==", values = "", field = "uniprot_mapping_type" )) #' @return For \code{UniprotMappingTypeFilter}: A #' \code{UniprotMappingTypeFilter} object. #' @rdname Filter-classes UniprotMappingTypeFilter <- function(value, condition = "==") { new("UniprotMappingTypeFilter", condition = condition, value = as.character(value)) } #' @rdname Filter-classes setClass("TxSupportLevelFilter", contains = "IntegerFilter", prototype = list( condition = "==", values = 0L, field = "tx_support_level" )) #' @return For \code{TxSupportLevel}: A #' \code{TxSupportLevel} object. #' @rdname Filter-classes TxSupportLevelFilter <- function(value, condition = "==") { if (!is.numeric(value)) stop("Parameter 'value' has to be numeric") new("TxSupportLevelFilter", condition = condition, value = as.integer(value)) } ensembldb/R/Deprecated.R0000644000175400017540000001557513175714743016150 0ustar00biocbuildbiocbuild## Deprecated functions. #' @aliases ensembldb-deprecated #' #' @title Deprecated functionality #' #' @description All functions, methods and classes listed on this page are #' deprecated and might be removed in future releases. #' #' @param value The value for the filter. #' @param condition The condition for the filter. #' #' @name Deprecated NULL #> NULL #' @description \code{GeneidFilter} creates a \code{GeneIdFilter}. Use #' \code{\link[AnnotationFilter]{GeneIdFilter}} instead. #' #' @rdname Deprecated GeneidFilter <- function(value, condition = "==") { .Deprecated("GeneIdFilter") if (missing(value)) stop("A filter without a value makes no sense!") ## if(length(value) > 1){ ## if(condition=="=") ## condition="in" ## if(condition=="!=") ## condition="not in" ## } return(new("GeneIdFilter", condition = condition, value = as.character(value), field = "gene_id")) } #' @description \code{GenebiotypeFilter} creates a \code{GeneBiotypeFilter}. Use #' \code{\link[AnnotationFilter]{GeneBiotypeFilter}} instead. #' #' @rdname Deprecated GenebiotypeFilter <- function(value, condition = "=="){ .Deprecated("GeneBiotypeFilter") if(missing(value)) stop("A filter without a value makes no sense!") return(new("GeneBiotypeFilter", condition = condition, value = as.character(value), field = "gene_biotype")) } #' @description \code{EntrezidFilter} creates a \code{EntrezFilter}. Use #' \code{\link[AnnotationFilter]{EntrezFilter}} instead. #' #' @rdname Deprecated EntrezidFilter <- function(value, condition = "=="){ .Deprecated("EntrezFilter") if(missing(value)) stop("A filter without a value makes no sense!") return(new("EntrezFilter", condition = condition, value = as.character(value), field = "entrez")) } #' @description \code{TxidFilter} creates a \code{TxIdFilter}. Use #' \code{\link[AnnotationFilter]{TxIdFilter}} instead. #' #' @rdname Deprecated TxidFilter <- function(value, condition = "=="){ .Deprecated("TxIdFilter") if(missing(value)) stop("A filter without a value makes no sense!") return(new("TxIdFilter", condition = condition, value = as.character(value), field = "tx_id")) } #' @description \code{TxbiotypeFilter} creates a \code{TxBiotypeFilter}. Use #' \code{\link[AnnotationFilter]{TxBiotypeFilter}} instead. #' #' @rdname Deprecated TxbiotypeFilter <- function(value, condition="=="){ .Deprecated("TxBiotypeFilter") if(missing(value)) stop("A filter without a value makes no sense!") return(new("TxBiotypeFilter", condition=condition, value=as.character(value), field = "tx_biotype")) } #' @description \code{ExonidFilter} creates a \code{ExonIdFilter}. Use #' \code{\link[AnnotationFilter]{ExonIdFilter}} instead. #' #' @rdname Deprecated ExonidFilter <- function(value, condition="=="){ .Deprecated("ExonIdFilter") if(missing(value)) stop("A filter without a value makes no sense!") return(new("ExonIdFilter", condition=condition, value=as.character(value), field = "exon_id")) } #' @description \code{ExonrankFilter} creates a \code{ExonRankFilter}. Use #' \code{\link[AnnotationFilter]{ExonRankFilter}} instead. #' #' @rdname Deprecated ExonrankFilter <- function(value, condition="=="){ .Deprecated("ExonRankFilter") if(missing(value)) stop("A filter without a value makes no sense!") return(new("ExonRankFilter", condition=condition, value=as.integer(value), field = "exon_rank")) } #' @description \code{SeqNameFilter} creates a \code{SeqNameFilter}. Use #' \code{\link[AnnotationFilter]{SeqNameFilter}} instead. #' #' @rdname Deprecated SeqnameFilter <- function(value, condition="=="){ .Deprecated("SeqNameFilter") if(missing(value)) stop("A filter without a value makes no sense!") return(new("SeqNameFilter", condition=condition, value=as.character(value), field = "seq_name")) } #' @description \code{SeqstrandFilter} creates a \code{SeqStrandFilter}. Use #' \code{\link[AnnotationFilter]{SeqStrandFilter}} instead. #' #' @rdname Deprecated SeqstrandFilter <- function(value, condition="=="){ .Deprecated("SeqStrandFilter") if(missing(value)){ stop("A filter without a value makes no sense!") } ## checking value: should be +, -, will however be translated to -1, 1 if(class(value)=="character"){ value <- match.arg(value, c("1", "-1", "+1", "-", "+")) if(value=="-") value <- "-1" if(value=="+") value <- "+1" ## OK, now transforming to number value <- as.numeric(value) } if(!(value==1 | value==-1)) stop("The strand has to be either 1 or -1 (or \"+\" or \"-\")") return(new("SeqStrandFilter", condition=condition, value=as.character(value), field = "seq_strand")) } #' @description \code{SeqstartFilter} creates a \code{GeneStartFilter}, #' \code{TxStartFilter} or \code{ExonStartFilter} depending on the value of the #' parameter \code{feature}. Use \code{\link[AnnotationFilter]{GeneStartFilter}}, #' \code{\link[AnnotationFilter]{TxStartFilter}} and #' \code{\link[AnnotationFilter]{ExonStartFilter}} instead. #' #' @param feature For \code{SeqstartFilter} and \code{SeqendFilter}: on what type #' of feature should the filter be applied? Supported are \code{"gene"}, #' \code{"tx"} and \code{"exon"}. #' #' @rdname Deprecated SeqstartFilter <- function(value, condition=">", feature="gene"){ .Deprecated(msg = paste0("The use of 'SeqstartFilter' is deprecated. Use ", "one of 'GeneStartFilter', 'ExonStartFilter'", " or 'TxStartFilter' instead.")) feature <- match.arg(feature, c("gene", "exon", "tx")) return(new(paste0(sub("^([[:alpha:]])", "\\U\\1", feature, perl=TRUE), "StartFilter"), value = as.integer(value), condition = condition, field = paste0(feature, "_start"))) } #' @description \code{SeqendFilter} creates a \code{GeneEndFilter}, #' \code{TxEndFilter} or \code{ExonEndFilter} depending on the value of the #' parameter \code{feature}. Use \code{\link[AnnotationFilter]{GeneEndFilter}}, #' \code{\link[AnnotationFilter]{TxEndFilter}} and #' \code{\link[AnnotationFilter]{ExonEndFilter}} instead. #' #' @rdname Deprecated SeqendFilter <- function(value, condition="<", feature="gene"){ .Deprecated(msg = paste0("The use of 'SeqendFilter' is deprecated. Use ", "one of 'GeneEndFilter', 'ExonEndFilter'", " or 'TxEndFilter' instead.")) feature <- match.arg(feature, c("gene", "exon", "tx")) return(new(paste0(sub("^([[:alpha:]])", "\\U\\1", feature, perl=TRUE)), "EndFilter"), value = as.integer(value), condition = condition, field = paste0(feature, "_end")) } ensembldb/R/Generics.R0000644000175400017540000001010213175714743015624 0ustar00biocbuildbiocbuild##*********************************************************************** ## ## Generic methods ## ##*********************************************************************** ## A setGeneric("activeFilter", function(x, ...) standardGeneric("activeFilter")) setGeneric("addFilter", function(x, ...) standardGeneric("addFilter")) ## B setGeneric("buildQuery", function(x, ...) standardGeneric("buildQuery")) ## C setGeneric("cleanColumns", function(x, columns, ...) starndardGeneric("cleanColumns")) ## D setGeneric("dbSeqlevelsStyle", function(x, ...) standardGeneric("dbSeqlevelsStyle")) setGeneric("dropFilter", function(x, ...) standardGeneric("dropFilter")) ## E setGeneric("ensemblVersion", function(x) standardGeneric("ensemblVersion")) setGeneric("ensDbColumn", function(object, ...) standardGeneric("ensDbColumn")) setGeneric("ensDbQuery", function(object, ...) standardGeneric("ensDbQuery")) ## F ## if (!isGeneric("filter")) ## setGeneric("filter", function(x, ...) ## standardGeneric("filter")) setGeneric("formatSeqnamesForQuery", function(x, sn, ...) standardGeneric("formatSeqnamesForQuery")) setGeneric("formatSeqnamesFromQuery", function(x, sn, ...) standardGeneric("formatSeqnamesFromQuery")) ## G setGeneric("getGeneRegionTrackForGviz", function(x, ...) standardGeneric("getGeneRegionTrackForGviz")) setGeneric("getGenomeFaFile", function(x, ...) standardGeneric("getGenomeFaFile")) setGeneric("getGenomeTwoBitFile", function(x, ...) standardGeneric("getGenomeTwoBitFile")) setGeneric("getMetadataValue", function(x, name) standardGeneric("getMetadataValue")) setGeneric("getProperty", function(x, name=NULL, ...) standardGeneric("getProperty")) setGeneric("getWhat", function(x, ...) standardGeneric("getWhat")) ## H setGeneric("hasProteinData", function(x) standardGeneric("hasProteinData")) ## L setGeneric("lengthOf", function(x, ...) standardGeneric("lengthOf")) setGeneric("listColumns", function(x, ...) standardGeneric("listColumns")) setGeneric("listGenebiotypes", function(x, ...) standardGeneric("listGenebiotypes")) setGeneric("listTables", function(x, ...) standardGeneric("listTables")) setGeneric("listTxbiotypes", function(x, ...) standardGeneric("listTxbiotypes")) setGeneric("listUniprotDbs", function(object, ...) standardGeneric("listUniprotDbs")) setGeneric("listUniprotMappingTypes", function(object, ...) standardGeneric("listUniprotMappingTypes")) ## O setGeneric("orderResultsInR", function(x) standardGeneric("orderResultsInR")) setGeneric("orderResultsInR<-", function(x, value) standardGeneric("orderResultsInR<-")) ## P setGeneric("print", function(x, ...) standardGeneric("print")) setGeneric("properties", function(x, ...) standardGeneric("properties")) ## R setGeneric("requireTable", function(x, db, ...) standardGeneric("requireTable")) setGeneric("returnFilterColumns", function(x) standardGeneric("returnFilterColumns")) setGeneric("returnFilterColumns<-", function(x, value) standardGeneric("returnFilterColumns<-")) ## S setGeneric("seqinfo", function(x) standardGeneric("seqinfo")) setGeneric("setProperty", function(x, value=NULL, ...) standardGeneric("setProperty")) ## setGeneric("show", function(object, ...) ## standardGeneric("show")) setGeneric("supportedSeqlevelsStyles", function(x) standardGeneric("supportedSeqlevelsStyles")) ## T setGeneric("tablesByDegree", function(x, ...) standardGeneric("tablesByDegree")) setGeneric("tablesForColumns", function(x, attributes, ...) standardGeneric("tablesForColumns")) setGeneric("toSAF", function(x, ...) standardGeneric("toSAF")) ## setGeneric("transcriptLengths", function(x, with.cds_len=FALSE, ## with.utr5_len=FALSE, ## with.utr3_len=FALSE, ...) ## standardGeneric("transcriptLengths")) ## U setGeneric("updateEnsDb", function(x, ...) standardGeneric("updateEnsDb")) setGeneric("useMySQL", function(x, host = "localhost", port = 3306, user, pass) standardGeneric("useMySQL")) ensembldb/R/Methods-Filter.R0000644000175400017540000003525613175714743016734 0ustar00biocbuildbiocbuild## Methods for filter classes. #' @description Extract the field/column name from an AnnotationFilter and #' ensure that it matches the correct database column name. Depending on #' whether argument \code{db} is present, the column names are also #' prefixed with the name of the corresponding table. #' #' @param object An \code{AnnotationFilter} object. #' #' @param db An \code{EnsDb} object. #' #' @param with.tables \code{character} specifying the tables that should be #' considered when prefixing the column name. #' #' @noRd setMethod("ensDbColumn", "AnnotationFilter", function(object, db, with.tables = character()) { clmn <- .fieldInEnsDb(object@field) if (missing(db)) return(clmn) if (length(with.tables) == 0) with.tables <- names(listTables(db)) unlist(prefixColumns(db, clmn, with.tables = with.tables), use.names = FALSE) }) setMethod("ensDbColumn", "AnnotationFilterList", function(object, db, with.tables = character()) { if (length(object) == 0) return(character()) unique(unlist(lapply(object, ensDbColumn, db, with.tables = with.tables))) }) #' @title Convert an AnnotationFilter to a SQL WHERE condition for EnsDb #' #' @aliases convertFilter,AnnotationFilter,EnsDb-method #' convertFilter,AnnotationFilterList,EnsDb-method #' #' @description `convertFilter` converts an `AnnotationFilter::AnnotationFilter` #' or `AnnotationFilter::AnnotationFilterList` to an SQL where condition #' for an `EnsDb` database. #' #' @note This function *might* be used in direct SQL queries on the SQLite #' database underlying an `EnsDb` but is more thought to illustrate the #' use of `AnnotationFilter` objects in combination with SQL databases. #' This method is used internally to create the SQL calls to the database. #' #' @param object `AnnotationFilter` or `AnnotationFilterList` objects (or #' objects extending these classes). #' #' @param db `EnsDb` object. #' #' @param with.tables optional `character` vector specifying the names of the #' database tables that are being queried. #' #' @return A `character(1)` with the SQL where condition. #' #' @md #' #' @rdname convertFilter #' #' @author Johannes Rainer #' #' @examples #' #' library(EnsDb.Hsapiens.v75) #' edb <- EnsDb.Hsapiens.v75 #' #' ## Define a filter #' flt <- AnnotationFilter(~ genename == "BCL2") #' #' ## Use the method from the AnnotationFilter package: #' convertFilter(flt) #' #' ## Create a combination of filters #' flt_list <- AnnotationFilter(~ genename %in% c("BCL2", "BCL2L11") & #' tx_biotype == "protein_coding") #' flt_list #' #' convertFilter(flt_list) #' #' ## Use the filters in the context of an EnsDb database: #' convertFilter(flt, edb) #' #' convertFilter(flt_list, edb) setMethod("convertFilter", signature = c(object = "AnnotationFilter", db = "EnsDb"), function(object, db, with.tables = character()) { ensDbQuery(object, db, with.tables) }) #' @rdname convertFilter setMethod("convertFilter", signature = c(object = "AnnotationFilterList", db = "EnsDb"), function(object, db, with.tables = character()) { ensDbQuery(object, db, with.tables) }) #' @description Build the \emph{where} query for an \code{AnnotationFilter} or #' \code{AnnotationFilterList}. #' #' @noRd setMethod("ensDbQuery", "AnnotationFilter", function(object, db, with.tables = character()) { .queryForEnsDbWithTables(object, db, with.tables) }) setMethod("ensDbQuery", "AnnotationFilterList", function(object, db, with.tables = character()) { wq <- NULL if (length(object)) { wq <- ensDbQuery(object[[1]], db, with.tables = with.tables) if (length(object) > 1) { for (i in 2:length(object)) { wq <- paste(wq, .logOp2SQL(object@logOp[(i -1)]), ensDbQuery(object[[i]], db, with.tables = with.tables)) } } ## Encapsule all inside brackets. wq <- paste0("(", wq, ")") } wq }) #' Need an ensDbQuery for SeqNameFilter to support different chromosome naming #' styles #' #' @noRd setMethod("ensDbQuery", "SeqNameFilter", function(object, db, with.tables = character()) { ## val <- sQuote(value(object, db)) ## Doing all the stuff in here: vals <- value(object) clmn <- .fieldInEnsDb(field(object)) if (!missing(db)) { ## o Eventually rename the seqname based on the seqlevelsStyle. vals <- formatSeqnamesForQuery(db, vals) if (length(with.tables) == 0) with.tables <- names(listTables(db)) clmn <- unlist(prefixColumns(db, clmn, with.tables = with.tables)) } ## o Quote the values. vals <- sQuote(vals) ## o Concatenate values. if (length(vals) > 1) vals <- paste0("(", paste0(vals, collapse = ","), ")") paste(clmn, .conditionForEnsDb(object), vals) }) setMethod("ensDbQuery", "SeqStrandFilter", function(object, db, with.tables = character()) { ## We have to ensure that value is converted to +1, -1. val <- strand2num(value(object)) clmn <- .fieldInEnsDb(field(object)) if (!missing(db)) { if (length(with.tables) == 0) with.tables <- names(listTables(db)) clmn <- unlist(prefixColumns(db, clmn, with.tables = with.tables)) } paste(clmn, .conditionForEnsDb(object), val) }) setMethod("start", signature(x="GRangesFilter"), function(x, ...){ start(value(x)) }) setMethod("end", signature(x="GRangesFilter"), function(x, ...){ end(value(x)) }) setMethod("strand", signature(x="GRangesFilter"), function(x, ...){ as.character(strand(value(x))) }) #' @description \code{seqnames}: accessor for the sequence names of the #' \code{GRanges} object within a \code{GRangesFilter} #' @param x For \code{seqnames}, \code{seqlevels}: a \code{GRangesFilter} object. #' #' @rdname Filter-classes setMethod("seqnames", signature(x="GRangesFilter"), function(x){ as.character(seqnames(value(x))) }) #' @description \code{seqnames}: accessor for the \code{seqlevels} of the #' \code{GRanges} object within a \code{GRangesFilter} #' #' @rdname Filter-classes setMethod("seqlevels", signature(x="GRangesFilter"), function(x){ seqlevels(value(x)) }) setMethod("ensDbColumn", "GRangesFilter", function(object, db, with.tables = character(), ...){ feature <- object@feature feature <- match.arg(feature, c("gene", "transcript", "exon", "tx")) if(object@feature == "transcript") feature <- "tx" cols <- c(start = paste0(feature, "_seq_start"), end = paste0(feature, "_seq_end"), seqname = "seq_name", strand = "seq_strand") if (!missing(db)) { if (length(with.tables) == 0) with.tables <- names(listTables(db)) cols <- unlist(prefixColumns(db, cols, with.tables = with.tables), use.names = FALSE) ## We have to give the vector the required names! names(cols) <- 1:length(cols) names(cols)[grep(cols, pattern = "seq_name")] <- "seqname" names(cols)[grep(cols, pattern = "seq_strand")] <- "strand" names(cols)[grep(cols, pattern = "seq_start")] <- "start" names(cols)[grep(cols, pattern = "seq_end")] <- "end" } cols[c("start", "end", "seqname", "strand")] }) setMethod("ensDbQuery", "GRangesFilter", function(object, db, with.tables = character()) { cols <- ensDbColumn(object, db, with.tables) if (missing(db)) db <- NULL buildWhereForGRanges(object, cols, db = db) }) setMethod("ensDbColumn", signature(object = "OnlyCodingTxFilter"), function(object, db, ...) { "tx.tx_cds_seq_start" }) setMethod("ensDbQuery", "OnlyCodingTxFilter", function(object, db, with.tables = character()) { "tx.tx_cds_seq_start is not null" }) setMethod("ensDbColumn", "ProteinIdFilter", function(object, db, with.tables = character(), ...) { if (missing(db)) { return(callNextMethod()) } if (!hasProteinData(db)) stop("The 'EnsDb' database used does not provide", " protein annotations! A 'ProteinIdFilter' can not", " be used.") callNextMethod() }) setMethod("ensDbQuery", "ProteinIdFilter", function(object, db, with.tables = character()) { if (missing(db)) return(callNextMethod()) if (!hasProteinData(db)) stop("The 'EnsDb' database used does not provide", " protein annotations! A 'ProteinIdFilter' can not", " be used.") .queryForEnsDbWithTables(object, db, with.tables) }) setMethod("ensDbColumn", "UniprotFilter", function(object, db, with.tables = character(), ...) { if (missing(db)) return(callNextMethod()) if (!hasProteinData(db)) stop("The 'EnsDb' database used does not provide", " protein annotations! A 'UniprotFilter' can not", " be used.") callNextMethod() }) setMethod("ensDbQuery", "UniprotFilter", function(object, db, with.tables = character()) { if (missing(db)) return(callNextMethod()) if (!hasProteinData(db)) stop("The 'EnsDb' database used does not provide", " protein annotations! A 'UniprotFilter' can not", " be used.") .queryForEnsDbWithTables(object, db, with.tables) }) setMethod("ensDbColumn", "ProtDomIdFilter", function(object, db, with.tables = character(), ...) { if (missing(db)) return(callNextMethod()) if (!hasProteinData(db)) stop("The 'EnsDb' database used does not provide", " protein annotations! A 'ProtDomIdFilter' can not", " be used.") callNextMethod() }) setMethod("ensDbQuery", "ProtDomIdFilter", function(object, db, with.tables = character()) { if (missing(db)) return(callNextMethod()) if (!hasProteinData(db)) stop("The 'EnsDb' database used does not provide", " protein annotations! A 'ProtDomIdFilter' can not", " be used.") .queryForEnsDbWithTables(object, db, with.tables) }) setMethod("ensDbColumn", "UniprotDbFilter", function(object, db, with.tables = character(), ...) { if (missing(db)) return(callNextMethod()) if (!hasProteinData(db)) stop("The 'EnsDb' database used does not provide", " protein annotations! A 'UniprotDbFilter' can not", " be used.") callNextMethod() }) setMethod("ensDbQuery", "UniprotDbFilter", function(object, db, with.tables = character()) { if (missing(db)) return(callNextMethod()) if (!hasProteinData(db)) stop("The 'EnsDb' database used does not provide", " protein annotations! A 'ProteinIdFilter' can not", " be used.") .queryForEnsDbWithTables(object, db, with.tables) }) setMethod("ensDbColumn", "UniprotMappingTypeFilter", function(object, db, with.tables = character(), ...) { if (missing(db)) return(callNextMethod()) if (!hasProteinData(db)) stop("The 'EnsDb' database used does not provide", " protein annotations! A 'UniprotMappingTypeFilter' ", "can not be used.") callNextMethod() }) setMethod("ensDbQuery", "UniprotMappingTypeFilter", function(object, db, with.tables = character()) { if (missing(db)) return(callNextMethod()) if (!hasProteinData(db)) stop("The 'EnsDb' database used does not provide", " protein annotations! A 'UniprotMappingTypeFilter' can not", " be used.") .queryForEnsDbWithTables(object, db, with.tables) }) setMethod("ensDbColumn", "TxSupportLevelFilter", function(object, db, with.tables = character(), ...) { if (missing(db)) return(callNextMethod()) if (!any(listColumns(db) %in% "tx_support_level")) stop("The 'EnsDb' database used does not provide", " transcript support levels! A 'TxSupportLevelFilter' ", "can not be used.") callNextMethod() }) setMethod("ensDbQuery", "TxSupportLevelFilter", function(object, db, with.tables = character()) { if (missing(db)) return(callNextMethod()) if (!any(listColumns(db) %in% "tx_support_level")) stop("The 'EnsDb' database used does not provide", " transcript support levels! A 'TxSupportLevelFilter' ", "can not be used.") .queryForEnsDbWithTables(object, db, with.tables) }) ensembldb/R/Methods.R0000644000175400017540000025273113175714743015510 0ustar00biocbuildbiocbuild##*********************************************************************** ## ## Methods for EnsDb classes ## ##*********************************************************************** setMethod("show", "EnsDb", function(object) { if (is.null(object@ensdb)) { cat("Dash it! Got an empty thing!\n") } else { info <- dbGetQuery(object@ensdb, "select * from metadata") cat("EnsDb for Ensembl:\n") if (inherits(object@ensdb, "SQLiteConnection")) cat(paste0("|Backend: SQLite\n")) if (inherits(object@ensdb, "MySQLConnection")) cat(paste0("|Backend: MySQL\n")) for (i in 1:nrow(info)) { cat(paste0("|", info[ i, "name" ], ": ", info[ i, "value" ], "\n")) } ## gene and transcript info. cat(paste0("| No. of genes: ", dbGetQuery(object@ensdb, "select count(distinct gene_id) from gene")[1, 1], ".\n")) cat(paste0("| No. of transcripts: ", dbGetQuery(object@ensdb, "select count(distinct tx_id) from tx")[1, 1], ".\n")) if (hasProteinData(object)) cat("|Protein data available.\n") flts <- .activeFilter(object) if (is(flts, "AnnotationFilter") | is(flts, "AnnotationFilterList")) { cat("|Active filter(s):\n") show(flts) } } }) ############################################################ ## organism setMethod("organism", "EnsDb", function(object){ Species <- .getMetaDataValue(object@ensdb, "Organism") ## reformat the e.g. homo_sapiens string into Homo sapiens # Species <- gsub(Species, pattern="_", replacement=" ", fixed=TRUE) Species <- .organismName(Species) return(Species) }) ############################################################ ## metadata setMethod("metadata", "EnsDb", function(x, ...){ Res <- dbGetQuery(dbconn(x), "select * from metadata") return(Res) }) ############################################################ ## Validation ## validateEnsDb <- function(object){ ## check if the database contains all required tables... if(!is.null(object@ensdb)){ msg <- validMsg(NULL, NULL) OK <- dbHasRequiredTables(object@ensdb) if (is.character(OK)) msg <- validMsg(msg, OK) OK <- dbHasValidTables(object@ensdb) if (is.character(OK)) msg <- validMsg(msg, OK) if (hasProteinData(object)) { OK <- dbHasRequiredTables( object@ensdb, tables = .ensdb_protein_tables(dbSchemaVersion(dbconn(object)))) if (is.character(OK)) msg <- validMsg(msg, OK) OK <- dbHasValidTables( object@ensdb, tables = .ensdb_protein_tables(dbSchemaVersion(dbconn(object)))) if (is.character(OK)) msg <- validMsg(msg, OK) cdsTx <- dbGetQuery(dbconn(object), "select tx_id, tx_cds_seq_start from tx"); if (is.character(cdsTx$tx_cds_seq_start)) { suppressWarnings( cdsTx[, "tx_cds_seq_start"] <- as.numeric(cdsTx$tx_cds_seq_start) ) } cdsTx <- cdsTx[!is.na(cdsTx$tx_cds_seq_start), "tx_id"] protTx <- dbGetQuery(dbconn(object), "select distinct tx_id from protein")$tx_id if (!all(cdsTx %in% protTx)) msg <- validMsg(msg, paste0("Not all transcripts with a CDS ", "are assigned to a protein ID!")) if (!all(protTx %in% cdsTx)) msg <- validMsg(msg, paste0("Not all proteins are assigned to ", "a transcript with a CDS!")) } if (is.null(msg)) TRUE else msg } return(TRUE) } setValidity("EnsDb", validateEnsDb) setMethod("initialize", "EnsDb", function(.Object,...){ OK <- validateEnsDb(.Object) if(class(OK)=="character"){ stop(OK) } callNextMethod(.Object, ...) }) ############################################################ ## dbconn setMethod("dbconn", "EnsDb", function(x){ return(x@ensdb) }) ############################################################ ## ensemblVersion ## ## returns the ensembl version of the package. setMethod("ensemblVersion", "EnsDb", function(x){ eVersion <- getMetadataValue(x, "ensembl_version") return(eVersion) }) ############################################################ ## getMetadataValue ## ## returns the metadata value for the specified name/key setMethod("getMetadataValue", "EnsDb", function(x, name){ if(missing(name)) stop("Argument name has to be specified!") return(metadata(x)[metadata(x)$name==name, "value"]) }) ############################################################ ## seqinfo setMethod("seqinfo", "EnsDb", function(x){ Chrs <- dbGetQuery(dbconn(x), "select * from chromosome") Chr.build <- .getMetaDataValue(dbconn(x), "genome_build") Chrs$seq_name <- formatSeqnamesFromQuery(x, Chrs$seq_name) SI <- Seqinfo(seqnames=Chrs$seq_name, seqlengths=Chrs$seq_length, isCircular=Chrs$is_circular==1, genome=Chr.build) return(SI) }) ############################################################ ## seqlevels setMethod("seqlevels", "EnsDb", function(x){ Chrs <- dbGetQuery(dbconn(x), "select distinct seq_name from chromosome") Chrs <- formatSeqnamesFromQuery(x, Chrs$seq_name) return(Chrs) }) ############################################################ ## getGenomeFaFile ## ## queries the dna.toplevel.fa file from AnnotationHub matching the current ## Ensembl version ## Update: if we can't find a FaFile matching the Ensembl version we suggest ones ## that might match. setMethod("getGenomeFaFile", "EnsDb", function(x, pattern="dna.toplevel.fa"){ ah <- AnnotationHub() ## Reduce the AnnotationHub to species, provider and genome version. ah <- .reduceAH(ah, organism=organism(x), dataprovider="Ensembl", genome=unique(genome(x))) if(length(ah) == 0) stop("Can not find any ressources in AnnotationHub for organism: ", organism(x), ", data provider: Ensembl and genome version: ", unique(genome(x)), "!") ## Reduce to all Fasta files with toplevel or primary_assembly. ah <- ah[ah$rdataclass == "FaFile", ] if(length(ah) == 0) stop("No FaFiles available in AnnotationHub for organism: ", organism(x), ", data provider: Ensembl and genome version: ", unique(genome(x)), "! You might also try to use the", " 'getGenomeTwoBitFile' method instead.") ## Reduce to dna.toplevel or dna.primary_assembly. idx <- c(grep(ah$title, pattern="dna.toplevel"), grep(ah$title, pattern="dna.primary_assembly")) if(length(idx) == 0) stop("No genome assembly fasta file available for organism: ", organism(x), ", data provider: Ensembl and genome version: ", unique(genome(x)), "!") ah <- ah[idx, ] ## Get the Ensembl version from the source url. ensVers <- .ensVersionFromSourceUrl(ah$sourceurl) if(any(ensVers == ensemblVersion(x))){ ## Got it. itIs <- which(ensVers == ensemblVersion(x)) }else{ ## Get the "closest" one. diffs <- abs(ensVers - as.numeric(ensemblVersion(x))) itIs <- which(diffs == min(diffs))[1] message("Returning the Fasta file for Ensembl version ", ensVers[itIs], " since no file for Ensembl version ", ensemblVersion(x), " is available.") } ## Getting the ressource. Dna <- ah[[names(ah)[itIs]]] ## generate an index if none is available if(is.na(index(Dna))){ indexFa(Dna) Dna <- FaFile(path(Dna)) } return(Dna) }) ## Just restricting the Annotation Hub to entries matching the species and the ## genome; not yet the Ensembl version. .reduceAH <- function(ah, organism=NULL, dataprovider="Ensembl", genome=NULL){ if(!is.null(dataprovider)) ah <- ah[ah$dataprovider == dataprovider, ] if(!is.null(organism)) ah <- ah[ah$species == organism, ] if(!is.null(genome)) ah <- ah[ah$genome == genome, ] return(ah) } .ensVersionFromSourceUrl <- function(url){ url <- strsplit(url, split="/", fixed=TRUE) ensVers <- unlist(lapply(url, function(z){ idx <- grep(z, pattern="^release") if(length(idx) == 0) return(-1) return(as.numeric(unlist(strsplit(z[idx], split="-"))[2])) })) return(ensVers) } ############################################################ ## getGenomeTwoBitFile ## ## Search and retrieve a genomic DNA resource through a TwoBitFile ## from AnnotationHub. setMethod("getGenomeTwoBitFile", "EnsDb", function(x){ ah <- AnnotationHub() ## Reduce the AnnotationHub to species, provider and genome version. ah <- .reduceAH(ah, organism=organism(x), dataprovider="Ensembl", genome=unique(genome(x))) if(length(ah) == 0) stop("Can not find any ressources in AnnotationHub for organism: ", organism(x), ", data provider: Ensembl and genome version: ", unique(genome(x)), "!") ## Reduce to all Fasta files with toplevel or primary_assembly. ah <- ah[ah$rdataclass == "TwoBitFile", ] if(length(ah) == 0) stop("No TwoBitFile available in AnnotationHub for organism: ", organism(x), ", data provider: Ensembl and genome version: ", unique(genome(x)), "!") ## Reduce to dna.toplevel or dna.primary_assembly. idx <- c(grep(ah$title, pattern="dna.toplevel"), grep(ah$title, pattern="dna.primary_assembly")) if(length(idx) == 0) stop("No genome assembly fasta file available for organism: ", organism(x), ", data provider: Ensembl and genome version: ", unique(genome(x)), "!") ah <- ah[idx, ] ## Get the Ensembl version from the source url. ensVers <- .ensVersionFromSourceUrl(ah$sourceurl) if(any(ensVers == ensemblVersion(x))){ ## Got it. itIs <- which(ensVers == ensemblVersion(x)) }else{ ## Get the "closest" one. diffs <- abs(ensVers - as.numeric(ensemblVersion(x))) itIs <- which(diffs == min(diffs))[1] message("Returning the TwoBit file for Ensembl version ", ensVers[itIs], " since no file for Ensembl version ", ensemblVersion(x), " is available.") } ## Getting the ressource. Dna <- ah[[names(ah)[itIs]]] return(Dna) }) ############################################################ ## listTables setMethod("listTables", "EnsDb", function(x, ...){ if(length(x@tables)==0){ tables <- dbListTables(dbconn(x)) ## read the columns for these tables. Tables <- vector(length=length(tables), "list") for(i in 1:length(Tables)){ Tables[[ i ]] <- colnames(dbGetQuery(dbconn(x), paste0("select * from ", tables[ i ], " limit 1"))) } names(Tables) <- tables x@tables <- Tables } Tab <- x@tables Tab <- Tab[tablesByDegree(x, tab=names(Tab))] ## Manually add tx_name as a "virtual" column; getWhat will insert the tx_id into that. Tab$tx <- unique(c(Tab$tx, "tx_name")) ## Manually add the symbol as a "virtual" column. Tab$gene <- unique(c(Tab$gene, "symbol")) return(Tab) }) ############################################################ ## listColumns setMethod("listColumns", "EnsDb", function(x, table, skip.keys=TRUE, ...){ if(length(x@tables)==0){ tables <- dbListTables(dbconn(x)) ## read the columns for these tables. Tables <- vector(length=length(tables), "list") for(i in 1:length(Tables)){ Tables[[ i ]] <- colnames(dbGetQuery(dbconn(x), paste0("select * from ", tables[ i ], " limit 1"))) } names(Tables) <- tables x@tables <- Tables } Tab <- x@tables ## Manually add tx_name as a "virtual" column; getWhat will insert ## the tx_id into that. Tab$tx <- unique(c(Tab$tx, "tx_name")) ## Manually add the symbol as a "virtual" column. Tab$gene <- unique(c(Tab$gene, "symbol")) if(!missing(table)){ columns <- unlist(Tab[names(Tab) %in% table], use.names = FALSE) }else{ columns <- unlist(Tab, use.names=FALSE) } if(skip.keys){ ## remove everything that has a _pk or _fk... idx <- grep(columns, pattern="_fk$") if(length(idx) > 0) columns <- columns[ -idx ] idx <- grep(columns, pattern="_pk$") if(length(idx) > 0) columns <- columns[ -idx ] } return(unique(columns)) }) ############################################################ ## listGenebiotypes setMethod("listGenebiotypes", "EnsDb", function(x, ...){ return(dbGetQuery(dbconn(x), "select distinct gene_biotype from gene")[,1]) }) ############################################################ ## listTxbiotypes setMethod("listTxbiotypes", "EnsDb", function(x, ...){ return(dbGetQuery(dbconn(x), "select distinct tx_biotype from tx")[,1]) }) ############################################################ ## cleanColumns ## ## checks columns and removes all that are not present in database tables ## the method checks internally whether the columns are in the full form, ## i.e. gene.gene_id (.) setMethod("cleanColumns", "EnsDb", function(x, columns, ...){ if(missing(columns)) stop("No columns submitted!") ## vote of the majority full.name <- length(grep(columns, pattern=".", fixed=TRUE)) > floor(length(columns) / 2) if (full.name) { suppressWarnings( full.columns <- unlist(prefixColumns(x, unlist(listTables(x)), clean = FALSE), use.names=TRUE) ) bm <- columns %in% full.columns removed <- columns[ !bm ] } else { dbtabs <- names(listTables(x)) dbtabs <- dbtabs[dbtabs != "metadata"] bm <- columns %in% unlist(listTables(x)[dbtabs]) removed <- columns[!bm] } if(length(removed) > 0){ if (length(removed) == 1) warning("Column ", paste(sQuote(removed), collapse=", "), " is not present in the database and has been removed") else warning("Columns ", paste(sQuote(removed), collapse=", "), " are not present in the database and have been removed") } return(columns[bm]) }) ############################################################ ## tablesForColumns ## ## returns the tables for the specified columns. setMethod("tablesForColumns", "EnsDb", function(x, columns, ...){ if(missing(columns)) stop("No columns submitted!") bm <- unlist(lapply(listTables(x), function(z){ return(any(z %in% columns)) })) if(!any(bm)) return(NULL) Tables <- names(bm)[ bm ] Tables <- Tables[ !(Tables %in% c("metadata")) ] return(Tables) }) ############################################################ ## tablesByDegree ## ## returns the table names ordered by degree, i.e. edges to other tables setMethod("tablesByDegree", "EnsDb", function(x, tab=names(listTables(x)), ...){ Table.order <- c(gene = 1, tx = 2, tx2exon = 3, exon = 4, chromosome = 5, protein = 6, uniprot = 7, protein_domain = 8, entrezgene = 9, metadata = 99) Tab <- tab[ order(Table.order[ tab ]) ] return(Tab) }) ############################################################ ## hasProteinData ## ## Simply check if the database has required tables protein, uniprot ## and protein_domain. #' @title Determine whether protein data is available in the database #' #' @aliases hasProteinData #' #' @description Determines whether the \code{\linkS4class{EnsDb}} #' provides protein annotation data. #' #' @param x The \code{\linkS4class{EnsDb}} object. #' #' @return A logical of length one, \code{TRUE} if protein annotations are #' available and \code{FALSE} otherwise. #' #' @author Johannes Rainer #' #' @seealso \code{\link{listTables}} #' #' @examples #' library(EnsDb.Hsapiens.v75) #' ## Does this database/package have protein annotations? #' hasProteinData(EnsDb.Hsapiens.v75) setMethod("hasProteinData", "EnsDb", function(x) { tabs <- listTables(x) return(all(c("protein", "uniprot", "protein_domain") %in% names(tabs))) }) ############################################################ ## genes ## ## get genes from the database. setMethod("genes", "EnsDb", function(x, columns = c(listColumns(x, "gene"), "entrezid"), filter = AnnotationFilterList(), order.by = "", order.type = "asc", return.type = "GRanges"){ return.type <- match.arg(return.type, c("data.frame", "GRanges", "DataFrame")) columns <- cleanColumns(x, unique(c(columns, "gene_id"))) ## if return.type is GRanges we require columns: seq_name, gene_seq_start ## and gene_seq_end and seq_strand if(return.type=="GRanges"){ columns <- unique(c(columns, c("gene_seq_start", "gene_seq_end", "seq_name", "seq_strand"))) } filter <- .processFilterParam(filter, x) filter <- setFeatureInGRangesFilter(filter, "gene") ## Eventually add columns for the filters: columns <- addFilterColumns(columns, filter, x) retColumns <- columns ## If we don't have an order.by define one. if(all(order.by == "")){ order.by <- NULL if (any(columns == "seq_name")) order.by <- c(order.by, "seq_name") if( any(columns == "gene_seq_start")) order.by <- c(order.by, "gene_seq_start") if(is.null(order.by)) order.by <- "" } Res <- getWhat(x, columns=columns, filter=filter, order.by=order.by, order.type=order.type, startWith = "gene", join = "suggested") ## issue #48: collapse entrezid column if dbschema 2.0 is used. if (as.numeric(dbSchemaVersion(x)) > 1 & any(columns == "entrezid")) Res <- .collapseEntrezidInTable(Res, by = "gene_id") if (return.type=="data.frame" | return.type=="DataFrame") { notThere <- !(retColumns %in% colnames(Res)) if(any(notThere)) warning("Columns ", paste0("'", retColumns[notThere], "'", collapse=", "), " not found in the database!") retColumns <- retColumns[!notThere] Res <- Res[, retColumns, drop = FALSE] if(return.type=="DataFrame") Res <- DataFrame(Res) return(Res) } if (return.type=="GRanges") { metacols <- columns[ !(columns %in% c("seq_name", "seq_strand", "gene_seq_start", "gene_seq_end")) ] suppressWarnings( SI <- seqinfo(x) ) SI <- SI[as.character(unique(Res$seq_name))] GR <- GRanges(seqnames=Rle(Res$seq_name), ranges=IRanges(start=Res$gene_seq_start, end=Res$gene_seq_end), strand=Rle(Res$seq_strand), seqinfo=SI[as.character(unique(Res$seq_name))], Res[ , metacols, drop=FALSE ] ) names(GR) <- Res$gene_id return(GR) } }) ############################################################ ## transcripts: ## ## get transcripts from the database. setMethod("transcripts", "EnsDb", function(x, columns = listColumns(x, "tx"), filter = AnnotationFilterList(), order.by = "", order.type = "asc", return.type = "GRanges"){ return.type <- match.arg(return.type, c("data.frame", "GRanges", "DataFrame")) columns <- cleanColumns(x, unique(c(columns, "tx_id"))) ## if return.type is GRanges we require columns: seq_name, gene_seq_start ## and gene_seq_end and seq_strand if(return.type=="GRanges"){ columns <- unique(c(columns, c("tx_seq_start", "tx_seq_end", "seq_name", "seq_strand"))) } filter <- .processFilterParam(filter, x) filter <- setFeatureInGRangesFilter(filter, "tx") ## Eventually add columns for the filters: columns <- addFilterColumns(columns, filter, x) retColumns <- columns ## If we don't have an order.by define one. if(all(order.by == "")){ order.by <- NULL if(any(columns == "seq_name")) order.by <- c(order.by, "seq_name") if(any(columns == "tx_seq_start")) order.by <- c(order.by, "tx_seq_start") if(is.null(order.by)) order.by <- "" } Res <- getWhat(x, columns=columns, filter = filter, order.by=order.by, order.type=order.type, startWith = "tx", join = "suggested") ## issue #48: collapse entrezid column if dbschema 2.0 is used. if (as.numeric(dbSchemaVersion(x)) > 1 & any(columns == "entrezid")) Res <- .collapseEntrezidInTable(Res, by = "tx_id") if(return.type=="data.frame" | return.type=="DataFrame"){ notThere <- !(retColumns %in% colnames(Res)) if(any(notThere)) warning("Columns ", paste0("'", retColumns[notThere], "'", collapse=", "), " not found in the database!") retColumns <- retColumns[!notThere] Res <- Res[, retColumns, drop = FALSE] if(return.type=="DataFrame") Res <- DataFrame(Res) return(Res) } if(return.type=="GRanges"){ notThere <- !(columns %in% colnames(Res)) if(any(notThere)) warning(paste0("Columns ", paste(columns[notThere], collapse=", "), " not present in the result data.frame!")) columns <- columns[!notThere] metacols <- columns[ !(columns %in% c("seq_name", "seq_strand", "tx_seq_start", "tx_seq_end")) ] suppressWarnings( SI <- seqinfo(x) ) SI <- SI[as.character(unique(Res$seq_name))] GR <- GRanges(seqnames=Rle(Res$seq_name), ranges=IRanges(start=Res$tx_seq_start, end=Res$tx_seq_end), strand=Rle(Res$seq_strand), seqinfo=SI[as.character(unique(Res$seq_name))], Res[ , metacols, drop=FALSE ] ) names(GR) <- Res$tx_id return(GR) } }) ############################################################ ## promoters: ## setMethod("promoters", "EnsDb", function(x, upstream=2000, downstream=200, ...) { gr <- transcripts(x, ...) trim(suppressWarnings(promoters(gr, upstream=upstream, downstream=downstream))) } ) ############################################################ ## exons ## ## get exons from the database. setMethod("exons", "EnsDb", function(x, columns = listColumns(x, "exon"), filter = AnnotationFilterList(), order.by = "", order.type = "asc", return.type = "GRanges"){ return.type <- match.arg(return.type, c("data.frame", "GRanges", "DataFrame")) if(!any(columns %in% c(listColumns(x, "exon"), "exon_idx"))){ ## have to have at least one column from the gene table... columns <- c(columns, "exon_id") } columns <- cleanColumns(x, unique(c(columns, "exon_id"))) ## if return.type is GRanges we require columns: seq_name, gene_seq_start ## and gene_seq_end and seq_strand if(return.type=="GRanges"){ columns <- unique(c(columns, c("exon_seq_start", "exon_seq_end", "seq_name", "seq_strand"))) } filter <- .processFilterParam(filter, x) filter <- setFeatureInGRangesFilter(filter, "exon") ## Eventually add columns for the filters: columns <- addFilterColumns(columns, filter, x) retColumns <- columns ## If we don't have an order.by define one. if (order.by == "") { order.by <- NULL if (any(columns == "seq_name")) order.by <- c(order.by, "seq_name") if (any(columns == "exon_seq_start")) order.by <- c(order.by, "exon_seq_start") if(is.null(order.by)) order.by <- "" } Res <- getWhat(x, columns=columns, filter=filter, order.by=order.by, order.type=order.type, startWith = "exon", join = "suggested") ## issue #48: collapse entrezid column if dbschema 2.0 is used. if (as.numeric(dbSchemaVersion(x)) > 1 & any(columns == "entrezid")) Res <- .collapseEntrezidInTable(Res, by = "exon_id") if(return.type=="data.frame" | return.type=="DataFrame"){ notThere <- !(retColumns %in% colnames(Res)) if(any(notThere)) warning("Columns ", paste0("'", retColumns[notThere], "'", collapse=", "), " not found in the database!") retColumns <- retColumns[!notThere] Res <- Res[, retColumns, drop = FALSE] if(return.type=="DataFrame") Res <- DataFrame(Res) return(Res) } if(return.type=="GRanges"){ notThere <- !(columns %in% colnames(Res)) if(any(notThere)) warning(paste0("Columns ", paste(columns[notThere], collapse=", "), " not present in the result data.frame!")) columns <- columns[!notThere] metacols <- columns[ !(columns %in% c("seq_name", "seq_strand", "exon_seq_start", "exon_seq_end")) ] suppressWarnings( SI <- seqinfo(x) ) SI <- SI[as.character(unique(Res$seq_name))] GR <- GRanges(seqnames=Rle(Res$seq_name), ranges=IRanges(start=Res$exon_seq_start, end=Res$exon_seq_end), strand=Rle(Res$seq_strand), seqinfo=SI[as.character(unique(Res$seq_name))], Res[ , metacols, drop=FALSE ] ) names(GR) <- Res$exon_id return(GR) } }) ############################################################ ## exonsBy ## ## should return a GRangesList setMethod("exonsBy", "EnsDb", function(x, by = c("tx", "gene"), columns = listColumns(x, "exon"), filter = AnnotationFilterList(), use.names = FALSE) { by <- match.arg(by, c("tx", "gene")) bySuff <- "_id" if (use.names) { if (by == "tx") { use.names <- FALSE warning("Argument use.names ignored as no transcript names are available.") } else { columns <- unique(c(columns, "gene_name")) bySuff <- "_name" } } filter <- .processFilterParam(filter, x) ## We're applying eventual GRangesFilter to either gene or tx. filter <- setFeatureInGRangesFilter(filter, by) ## Eventually add columns for the filters: columns <- cleanColumns(x, unique(c(columns, "exon_id"))) columns <- addFilterColumns(columns, filter, x) ## Quick fix; rename any exon_rank to exon_idx. columns[columns == "exon_rank"] <- "exon_idx" ## The minimum columns we need, in addition to "columns" min.columns <- c(paste0(by, "_id"), "seq_name","exon_seq_start", "exon_seq_end", "exon_id", "seq_strand") by.id.full <- unlist(prefixColumns(x, columns = paste0(by, "_id"), clean = FALSE), use.names = FALSE) if (by == "gene") { ## tx columns have to be removed, since the same exon can be part of ## more than one tx txcolumns <- c(listColumns(x, "tx"), "exon_idx") txcolumns <- txcolumns[txcolumns != "gene_id"] torem <- columns %in% txcolumns if (any(torem)) warning("Columns ", paste(columns[ torem ], collapse = ","), " have been removed as they are not allowed if exons", " are fetched by gene.") columns <- columns[!torem] } else { min.columns <- unique(c(min.columns, "exon_idx")) columns <- c(columns, "exon_idx") } ## define the minimal columns that we need... ret_cols <- unique(columns) ## before adding the "min.columns" columns <- unique(c(columns, min.columns)) ## get the seqinfo: suppressWarnings( SI <- seqinfo(x) ) ## Resolve ordering problems. orderR <- orderResultsInR(x) if (orderR) { order.by <- "" } else { if (by == "gene") { order.by <- paste0("gene.gene_id, ", "case when seq_strand = 1 then exon_seq_start", " when seq_strand = -1 then (exon_seq_end * -1)", " end") } else { ## Funny thing is the query takes longer if I use tx2exon.tx_id! order.by <- "tx.tx_id, tx2exon.exon_idx" } } Res <- getWhat(x, columns = columns, filter = filter, order.by = order.by, skip.order.check = TRUE, startWith = by, join = "suggested") ## issue #48: collapse entrezid column if dbschema 2.0 is used. if (as.numeric(dbSchemaVersion(x)) > 1 & any(columns == "entrezid")) Res <- .collapseEntrezidInTable(Res, by = "exon_id") ## Now, order in R, if not already done in SQL. if (orderR) { if (by == "gene") { startend <- (Res$seq_strand == 1) * Res$exon_seq_start + (Res$seq_strand == -1) * (Res$exon_seq_end * -1) Res <- Res[order(Res$gene_id, startend, method = "radix"), ] } else { Res <- Res[order(Res$tx_id, Res$exon_idx, method = "radix"), ] } } SI <- SI[as.character(unique(Res$seq_name))] ## replace exon_idx with exon_rank colnames(Res)[colnames(Res) == "exon_idx"] <- "exon_rank" columns[columns == "exon_idx"] <- "exon_rank" ret_cols[ret_cols == "exon_idx"] <- "exon_rank" notThere <- !(ret_cols %in% colnames(Res)) if (any(notThere)) warning("Columns ", paste0("'", ret_cols[notThere], "'", collapse = ", "), " not found in the database!") ret_cols <- ret_cols[!notThere] columns.metadata <- ret_cols[!(ret_cols %in% c("seq_name", "seq_strand", "exon_seq_start", "exon_seq_end"))] columns.metadata <- match(columns.metadata, colnames(Res)) GR <- GRanges(seqnames = Rle(Res$seq_name), strand = Rle(Res$seq_strand), ranges = IRanges(start = Res$exon_seq_start, end = Res$exon_seq_end), seqinfo = SI, Res[, columns.metadata, drop=FALSE] ) return(split(GR, Res[, paste0(by, bySuff)])) }) ############################################################ ## transcriptsBy ## setMethod("transcriptsBy", "EnsDb", function(x, by = c("gene", "exon"), columns = listColumns(x, "tx"), filter = AnnotationFilterList()) { if (any(by == "cds")) stop("fetching transcripts by cds is not (yet) implemented.") by <- match.arg(by, c("gene", "exon")) byId <- paste0(by, "_id") min.columns <- c(paste0(by, "_id"), "seq_name", "tx_seq_start", "tx_seq_end", "tx_id", "seq_strand") ## can not have exon columns! ex_cols <- c(listColumns(x, "exon"), "exon_idx") ex_cols <- ex_cols[ex_cols != "tx_id"] torem <- columns %in% ex_cols if (any(torem)) warning("Columns ", paste(columns[ torem ], collapse=","), " have been removed as they are not allowed if", " transcripts are fetched.") columns <- columns[!torem] ## Process filters filter <- .processFilterParam(filter, x) ## GRanges filter should be based on either gene or exon coors. filter <- setFeatureInGRangesFilter(filter, by) ## Eventually add columns for the filters: columns <- addFilterColumns(columns, filter, x) ret_cols <- unique(columns) ## define the minimal columns that we need... columns <- cleanColumns(x, unique(c(columns, min.columns))) ## get the seqinfo: suppressWarnings( SI <- seqinfo(x) ) byIdFull <- unlist(prefixColumns(x, columns = byId, clean = FALSE), use.names = FALSE) orderR <- orderResultsInR(x) if (orderR) { order.by <- "" } else { order.by <- paste0(byIdFull , ", case when seq_strand = 1 then tx_seq_start", " when seq_strand = -1 then (tx_seq_end * -1) end") } Res <- getWhat(x, columns=columns, filter=filter, order.by=order.by, skip.order.check=TRUE, startWith = by, join = "suggested") ## issue #48: collapse entrezid column if dbschema 2.0 is used. if (as.numeric(dbSchemaVersion(x)) > 1 & any(columns == "entrezid")) Res <- .collapseEntrezidInTable(Res, by = "tx_id") if (orderR) { startEnd <- (Res$seq_strand == 1) * Res$tx_seq_start + (Res$seq_strand == -1) * (Res$tx_seq_end * -1) Res <- Res[order(Res[, byId], startEnd, method = "radix"), ] } SI <- SI[as.character(unique(Res$seq_name))] ## Replace exon_idx with exon_rank colnames(Res) <- gsub(colnames(Res), pattern = "exon_idx", replacement = "exon_rank", fixed = TRUE) ret_cols[ret_cols == "exon_idx"] <- "exon_rank" notThere <- !(ret_cols %in% colnames(Res)) if(any(notThere)) warning("Columns ", paste0("'", ret_cols[notThere], "'", collapse=", "), " not found in the database!") ret_cols <- ret_cols[!notThere] columns.metadata <- ret_cols[!(ret_cols %in% c("seq_name", "seq_strand", "tx_seq_start", "tx_seq_end"))] columns.metadata <- match(columns.metadata, colnames(Res)) GR <- GRanges(seqnames=Rle(Res$seq_name), strand=Rle(Res$seq_strand), ranges=IRanges(start=Res$tx_seq_start, end=Res$tx_seq_end), seqinfo=SI, Res[ , columns.metadata, drop=FALSE ] ) return(split(GR, Res[ , byId])) }) ############################################################ ## lengthOf ## for GRangesList... setMethod("lengthOf", "GRangesList", function(x, ...){ return(sum(width(reduce(x)))) ## return(unlist(lapply(width(reduce(x)), sum))) }) ## return the length of genes or transcripts setMethod("lengthOf", "EnsDb", function(x, of="gene", filter=AnnotationFilterList()){ of <- match.arg(of, c("gene", "tx")) ## get the exons by gene or transcript from the database... suppressWarnings( GRL <- exonsBy(x, by=of, filter=filter) ) return(lengthOf(GRL)) }) ####============================================================ ## transcriptLengths ## ## For TxDb: calls just the function (not method!) from the GenomicFeatures ## package. ## For EnsDb: calls the .transcriptLengths function. ####------------------------------------------------------------ ## setMethod("transcriptLengths", "TxDb", function(x, with.cds_len=FALSE, with.utr5_len=FALSE, ## with.utr3_len=FALSE){ ## return(GenomicFeatures::transcriptLengths(x, with.cds_len=with.cds_len, ## with.utr5_len=with.utr5_len, ## with.utr3_len=with.utr3_len)) ## }) ## setMethod("transcriptLengths", "EnsDb", function(x, with.cds_len=FALSE, with.utr5_len=FALSE, ## with.utr3_len=FALSE, filter=list()){ ## return(.transcriptLengths(x, with.cds_len=with.cds_len, with.utr5_len=with.utr3_len, ## with.utr3_len=with.utr3_len, filter=filter)) ## }) ## implement the method from the GenomicFeatures package .transcriptLengths <- function(x, with.cds_len=FALSE, with.utr5_len=FALSE, with.utr3_len=FALSE, filter = AnnotationFilterList()){ ## First we're going to fetch the exonsBy. ## Or use getWhat??? ## Dash, have to make two queries! filter <- .processFilterParam(filter, x) allTxs <- transcripts(x, filter=filter) exns <- exonsBy(x, filter=filter) ## Match ordering exns <- exns[match(allTxs$tx_id, names(exns))] ## Calculate length of transcripts. txLengths <- sum(width(reduce(exns))) ## Calculate no. of exons. ## build result data frame: Res <- data.frame(tx_id=allTxs$tx_id, gene_id=allTxs$gene_id, nexon=lengths(exns), tx_len=txLengths, stringsAsFactors=FALSE) if(!any(c(with.cds_len, with.utr5_len, with.utr3_len))){ ## Return what we've got thus far. return(Res) } if(with.cds_len) Res <- cbind(Res, cds_len=rep(NA, nrow(Res))) if(with.utr5_len) Res <- cbind(Res, utr5_len=rep(NA, nrow(Res))) if(with.utr3_len) Res <- cbind(Res, utr3_len=rep(NA, nrow(Res))) ## Otherwise do the remaining stuff... txs <- allTxs[!is.na(allTxs$tx_cds_seq_start)] if(length(txs) > 0){ cExns <- exns[txs$tx_id] cReg <- GRanges(seqnames=seqnames(txs), ranges=IRanges(txs$tx_cds_seq_start, txs$tx_cds_seq_end), strand=strand(txs), tx_id=txs$tx_id) cReg <- split(cReg, f=cReg$tx_id) ## Match order. cReg <- cReg[match(txs$tx_id, names(cReg))] cdsExns <- intersect(cReg, cExns) ## cExns: all exons of coding transcripts (includes untranslated ## and translated region) ## cReg: just the start-end position of the coding region of the tx. ## cdsExns: the coding part of all exons of the tx. if(with.cds_len){ ## Calculate CDS length cdsLengths <- sum(width(reduce(cdsExns))) Res[names(cdsLengths), "cds_len"] <- cdsLengths } if(with.utr3_len | with.utr5_len){ ## ! UTR is the difference between the exons and the cds-exons ## Note: order of parameters is important! utrReg <- setdiff(cExns, cdsExns) leftOfCds <- utrReg[end(utrReg) < start(cReg)] rightOfCds <- utrReg[start(utrReg) > end(cReg)] ## Calculate lengths. leftOfLengths <- sum(width(reduce(leftOfCds))) rightOfLengths <- sum(width(reduce(rightOfCds))) minusTx <- which(as.character(strand(txs)) == "-" ) if(with.utr3_len){ ## Ordering of txs and all other stuff matches. tmp <- rightOfLengths tmp[minusTx] <- leftOfLengths[minusTx] Res[names(tmp), "utr3_len"] <- tmp } if(with.utr5_len){ tmp <- leftOfLengths tmp[minusTx] <- rightOfLengths[minusTx] Res[names(tmp), "utr5_len"] <- tmp } } } return(Res) } ############################################################ ## cdsBy ## ## Return coding region ranges by tx or by gene. setMethod("cdsBy", "EnsDb", function(x, by = c("tx", "gene"), columns = NULL, filter = AnnotationFilterList(), use.names = FALSE){ by <- match.arg(by, c("tx", "gene")) filter <- .processFilterParam(filter, x) filter <- setFeatureInGRangesFilter(filter, by) columns <- cleanColumns(x, columns) ## Eventually add columns for the filters: columns <- addFilterColumns(columns, filter, x) ## Add a filter ensuring that only coding transcripts are queried. filter <- AnnotationFilterList(OnlyCodingTxFilter() ,filter) bySuff <- "_id" if (by == "tx") { ## adding exon_id, exon_idx to the columns. columns <- unique(c(columns, "exon_id", "exon_idx")) if (use.names) warning("Not considering use.names as no transcript names are", " available.") } else { columns <- unique(c("gene_id", columns)) if( use.names) { bySuff <- "_name" columns <- c(columns, "gene_name") } } byId <- paste0(by, bySuff) ## Query the data fetchCols <- unique(c(byId, columns, "tx_cds_seq_start", "tx_cds_seq_end", "seq_name", "seq_strand", "exon_idx", "exon_id", "exon_seq_start", "exon_seq_end")) ## Ordering of the results: ## Force ordering in R by default here to fix issue #11 ##orderR <- orderResultsInR(x) orderR <- TRUE if (orderR) { order.by <- "" } else { if (by == "tx") { ## Here we want to sort the exons by exon_idx order.by <- "tx.tx_id, tx2exon.exon_idx" } else { ## Here we want to sort the transcripts by tx start. order.by <- paste0("gene.gene_id, case when seq_strand = 1 then", " tx_cds_seq_start when seq_strand = -1 then", "(tx_cds_seq_end * -1) end") } } Res <- getWhat(x, columns = fetchCols, filter = filter, order.by = order.by, skip.order.check = TRUE, startWith = by, join = "suggested") ## issue #48: collapse entrezid column if dbschema 2.0 is used. if (as.numeric(dbSchemaVersion(x)) > 1 & any(columns == "entrezid")) Res <- .collapseEntrezidInTable(Res, by = "exon_id") ## Remove rows with NA in tx_cds_seq_start; that's the case for "old" ## databases. nas <- is.na(Res$tx_cds_seq_start) if (any(nas)) Res <- Res[!nas, ] ## Remove exons that are not within the cds. Res <- Res[Res$exon_seq_end >= Res$tx_cds_seq_start & Res$exon_seq_start <= Res$tx_cds_seq_end, , drop = FALSE] if (orderR) { ## And finally ordering them. if (by == "tx") { Res <- Res[order(Res$tx_id, Res$exon_idx, method = "radix"), ] } else { startend <- (Res$seq_strand == 1) * Res$tx_cds_seq_start + (Res$seq_strand == -1) * (Res$tx_cds_seq_end * -1) Res <- Res[order(Res$gene_id, startend, method = "radix"), ] } } if(nrow(Res)==0){ warning("No cds found!") return(NULL) } cdsStarts <- pmax.int(Res$exon_seq_start, Res$tx_cds_seq_start) cdsEnds <- pmin.int(Res$exon_seq_end, Res$tx_cds_seq_end) ## get the seqinfo: suppressWarnings( SI <- seqinfo(x) ) SI <- SI[as.character(unique(Res$seq_name))] ## Rename columns exon_idx to exon_rank, if present if(any(colnames(Res) == "exon_idx")){ colnames(Res)[colnames(Res) == "exon_idx"] <- "exon_rank" columns[columns == "exon_idx"] <- "exon_rank" } ## Building the result. if(length(columns) > 0){ notThere <- !(columns %in% colnames(Res)) if(any(notThere)) warning(paste0("Columns ", paste(columns[notThere], collapse=", "), " not present in the result data.frame!")) columns <- columns[!notThere] GR <- GRanges(seqnames=Rle(Res$seq_name), strand=Rle(Res$seq_strand), ranges=IRanges(start=cdsStarts, end=cdsEnds), seqinfo=SI, Res[, columns, drop=FALSE]) }else{ GR <- GRanges(seqnames=Rle(Res$seq_name), strand=Rle(Res$seq_strand), ranges=IRanges(start=cdsStarts, end=cdsEnds), seqinfo=SI) } GR <- split(GR, Res[, paste0(by, bySuff)]) ## For "by gene" we reduce the redundant ranges; ## that way we loose however all additional columns! if(by == "gene") GR <- reduce(GR) return(GR) }) ############################################################ ## getUTRsByTranscript ## getUTRsByTranscript <- function(x, what, columns = NULL, filter = AnnotationFilterList()) { filter <- .processFilterParam(filter, x) columns <- cleanColumns(x, columns) filter <- setFeatureInGRangesFilter(filter, "tx") ## Eventually add columns for the filters: columns <- addFilterColumns(columns, filter, x) columns <- unique(c(columns, "exon_id", "exon_idx")) ## Add the filter for coding tx only. filter <- AnnotationFilterList(OnlyCodingTxFilter(), filter) ## what do we need: tx_cds_seq_start, tx_cds_seq_end and exon_idx fetchCols <- unique(c("tx_id", columns, "tx_cds_seq_start", "tx_cds_seq_end", "seq_name", "seq_strand", "exon_seq_start", "exon_seq_end")) order.by <- "tx.tx_id" ## get the seqinfo: suppressWarnings( SI <- seqinfo(x) ) ## Note: doing that with a single query and some coordinate juggling ## is faster than calling exonsBy and GRangesList setdiff etc. Res <- getWhat(x, columns=fetchCols, filter=filter, order.by=order.by, skip.order.check=TRUE, startWith = "tx", join = "suggested") ## issue #48: collapse entrezid column if dbschema 2.0 is used. if (as.numeric(dbSchemaVersion(x)) > 1 & any(columns == "entrezid")) Res <- .collapseEntrezidInTable(Res, by = "exon_id") nas <- is.na(Res$tx_cds_seq_start) if (any(nas)) Res <- Res[!nas, ] ## Remove exons that are within the cds. Res <- Res[Res$exon_seq_start < Res$tx_cds_seq_start | Res$exon_seq_end > Res$tx_cds_seq_end, , drop=FALSE] if (nrow(Res) == 0) { warning(paste0("No ", what, "UTR found!")) return(NULL) } ## Rename columns exon_idx to exon_rank, if present if (any(colnames(Res) == "exon_idx")) { colnames(Res) <- sub(colnames(Res), pattern = "exon_idx", replacement = "exon_rank", fixed = TRUE) columns[columns == "exon_idx"] <- "exon_rank" } if (what == "five") { ## All those on the forward strand for which the exon start is smaller ## than the cds start and those on the reverse strand with an exon end ## larger than the cds end. Res <- Res[(Res$seq_strand > 0 & Res$exon_seq_start < Res$tx_cds_seq_start) | (Res$seq_strand < 0 & Res$exon_seq_end > Res$tx_cds_seq_end), , drop=FALSE] } else { ## Other way round. Res <- Res[(Res$seq_strand > 0 & Res$exon_seq_end > Res$tx_cds_seq_end) | (Res$seq_strand < 0 & Res$exon_seq_start < Res$tx_cds_seq_start), , drop=FALSE] } if (nrow(Res) == 0) { warning(paste0("No ", what, "UTR found!")) return(NULL) } ## Increase the cds end by 1 and decrease the start by 1, thus, ## avoiding that the UTR overlaps the cds Res$tx_cds_seq_end <- Res$tx_cds_seq_end + 1L Res$tx_cds_seq_start <- Res$tx_cds_seq_start - 1L utrStarts <- rep(0, nrow(Res)) utrEnds <- utrStarts ## Distinguish between stuff which is left of and right of the CDS: ## Left of the CDS: can be either 5' for + strand or 3' for - strand. bm <- which(Res$exon_seq_start <= Res$tx_cds_seq_start) if (length(bm) > 0) { if (what == "five") { ## 5' and left of CDS means we're having 5' CDSs bm <- bm[Res$seq_strand[bm] > 0] if(length(bm) > 0){ utrStarts[bm] <- Res$exon_seq_start[bm] utrEnds[bm] <- pmin.int(Res$exon_seq_end[bm], Res$tx_cds_seq_start[bm]) } } else { bm <- bm[Res$seq_strand[bm] < 0] if (length(bm) > 0) { utrStarts[bm] <- Res$exon_seq_start[bm] utrEnds[bm] <- pmin.int(Res$exon_seq_end[bm], Res$tx_cds_seq_start[bm]) } } } ## Right of the CDS: can be either 5' for - strand of 3' for + strand. bm <- which(Res$exon_seq_end >= Res$tx_cds_seq_end) if (length(bm) > 0) { if (what == "five") { ## Right of CDS is 5' for - strand. bm <- bm[Res$seq_strand[bm] < 0] if (length(bm) > 0) { utrStarts[bm] <- pmax.int(Res$exon_seq_start[bm], Res$tx_cds_seq_end[bm]) utrEnds[bm] <- Res$exon_seq_end[bm] } } else { ## Right of CDS is 3' for + strand bm <- bm[Res$seq_strand[bm] > 0] if (length(bm) > 0) { utrStarts[bm] <- pmax.int(Res$exon_seq_start[bm], Res$tx_cds_seq_end[bm]) utrEnds[bm] <- Res$exon_seq_end[bm] } } } notThere <- !(columns %in% colnames(Res)) if (any(notThere)) warning(paste0("Columns ", paste(columns[notThere], collapse=", "), " not present in the result data.frame!")) columns <- columns[!notThere] SI <- SI[as.character(unique(Res$seq_name))] GR <- GRanges(seqnames = Rle(Res$seq_name), strand = Rle(Res$seq_strand), ranges = IRanges(start=utrStarts, end=utrEnds), seqinfo = SI, Res[, columns, drop = FALSE]) GR <- split(GR, Res[, "tx_id"]) return(GR) } ############################################################ ## threeUTRsByTranscript ## setMethod("threeUTRsByTranscript", "EnsDb", function(x, columns = NULL, filter = AnnotationFilterList()) { filter <- .processFilterParam(filter, x) getUTRsByTranscript(x = x, what = "three", columns = columns, filter = filter) }) ############################################################ ## fiveUTRsByTranscript ## setMethod("fiveUTRsByTranscript", "EnsDb", function(x, columns = NULL, filter = AnnotationFilterList()) { filter <- .processFilterParam(filter, x) getUTRsByTranscript(x = x, what = "five", columns = columns, filter = filter) }) ############################################################ ## toSAF... function to transform a GRangesList into a data.frame ## corresponding to the SAF format. ## assuming the names of the GRangesList to be the GeneID and the ## element (GRanges) the start/end coordinates ## of an exon, transcript or the gene itself. .toSaf <- function(x){ DF <- as.data.frame(x) colnames(DF)[ colnames(DF)=="group_name" ] <- "GeneID" colnames(DF)[ colnames(DF)=="seqnames" ] <- "Chr" colnames(DF)[ colnames(DF)=="start" ] <- "Start" colnames(DF)[ colnames(DF)=="end" ] <- "End" colnames(DF)[ colnames(DF)=="strand" ] <- "Strand" return(DF[ , c("GeneID", "Chr", "Start", "End", "Strand")]) } ## for GRangesList... setMethod("toSAF", "GRangesList", function(x, ...){ return(.toSaf(x)) }) ############################################################ ## buildQuery setMethod("buildQuery", "EnsDb", function(x, columns=c("gene_id", "gene_biotype", "gene_name"), filter = AnnotationFilterList(), order.by="", order.type="asc", skip.order.check=FALSE){ return(.buildQuery(x=x, columns=columns, filter=filter, order.by=order.by, order.type=order.type, skip.order.check=skip.order.check)) }) ############################################################ ## getWhat ## ## Method that wraps the internal .getWhat function to retrieve data from the ## database. In addition, if present, we're renaming chromosome names depending ## on the ucscChromosomeNames option. ## Additional parameters: ## o startWith: the name of the database table from which the join should start ## or NULL for the default behaviour (i.e. genes-> tx etc). ## o join: the type of join that should be used; one of "join", ## "left outer join" or "suggested". setMethod("getWhat", "EnsDb", function(x, columns = c("gene_id", "gene_biotype", "gene_name"), filter = AnnotationFilterList(), order.by = "", order.type = "asc", group.by = NULL, skip.order.check = FALSE, startWith = NULL, join = "suggested") { Res <- .getWhat(x = x, columns = columns, filter = filter, order.by = order.by, order.type = order.type, group.by = group.by, skip.order.check = skip.order.check, startWith = startWith, join = join) ## Eventually renaming seqnames according to the specified style. if(any(colnames(Res) == "seq_name")) Res$seq_name <- formatSeqnamesFromQuery(x, Res$seq_name) return(Res) }) ############################################################ ## disjointExons ## ## that's similar to the code from the GenomicFeatures package. setMethod("disjointExons", "EnsDb", function(x, aggregateGenes = FALSE, includeTranscripts = TRUE, filter = AnnotationFilterList(), ...){ filter <- .processFilterParam(filter, x) exonsByGene <- exonsBy(x, by = "gene", filter = filter) exonicParts <- disjoin(unlist(exonsByGene, use.names = FALSE)) if (aggregateGenes) { foGG <- findOverlaps(exonsByGene, exonsByGene) aggregateNames <- GenomicFeatures:::.listNames(names(exonsByGene), as.list(foGG)) foEG <- findOverlaps(exonicParts, exonsByGene, select="first") gene_id <- aggregateNames[foEG] pasteNames <- GenomicFeatures:::.pasteNames(names(exonsByGene), as.list(foGG))[foEG] orderByGeneName <- order(pasteNames) exonic_rle <- runLength(Rle(pasteNames[orderByGeneName])) } else { ## drop exonic parts that overlap > 1 gene foEG <- findOverlaps(exonicParts, exonsByGene) idxList <- as.list(foEG) if (any(keep <- countQueryHits(foEG) == 1)) { idxList <- idxList[keep] exonicParts <- exonicParts[keep] } gene_id <- GenomicFeatures:::.listNames(names(exonsByGene), idxList) orderByGeneName <- order(unlist(gene_id, use.names=FALSE)) exonic_rle <- runLength(Rle(unlist(gene_id[orderByGeneName], use.names=FALSE))) } values <- DataFrame(gene_id) if (includeTranscripts) { exonsByTx <- exonsBy(x, by="tx", filter=filter) foET <- findOverlaps(exonicParts, exonsByTx) values$tx_name <- GenomicFeatures:::.listNames(names(exonsByTx), as.list(foET)) } mcols(exonicParts) <- values exonicParts <- exonicParts[orderByGeneName] exonic_part <- unlist(lapply(exonic_rle, seq_len), use.names=FALSE) exonicParts$exonic_part <- exonic_part return(exonicParts) } ) ############################################################ ## getGeneRegionTrackForGviz ## Fetch data to add as a GeneTrack. ## filter ... Used to filter the result. ## chromosome, start, end ... Either all or none has to be specified. If ## specified, the function first retrieves all ## transcripts that have an exon in the specified ## range and adds them as a TranscriptidFilter to ## the filters. The query to fetch the "real" data ## is performed afterwards. ## featureIs ... Wheter gene_biotype or tx_biotype should be ## mapped to the column feature. setMethod( "getGeneRegionTrackForGviz", "EnsDb", function(x, filter = AnnotationFilterList(), chromosome = NULL, start = NULL, end = NULL, featureIs = "gene_biotype") { featureIs <- match.arg(featureIs, c("gene_biotype", "tx_biotype")) filter <- .processFilterParam(filter, x) if(missing(chromosome)) chromosome <- NULL if(missing(start)) start <- NULL if(missing(end)) end <- NULL ## If only chromosome is specified, create a SeqNameFilter and ## add it to the filter if(is.null(start) & is.null(end) & !is.null(chromosome)){ filter <- AnnotationFilterList(filter, SeqNameFilter(chromosome)) chromosome <- NULL } if(any(c(!is.null(chromosome), !is.null(start), !is.null(end)))){ ## Require however that all are defined!!! if(all(c(!is.null(chromosome), !is.null(start), !is.null(end)))){ ## Fix eventually provided UCSC chromosome names: chromosome <- ucscToEns(chromosome) ## Define a GRangesFilter to include all features that overlap ## that region. grg <- GRangesFilter(GRanges(seqnames = chromosome, ranges = IRanges(start, end)), feature = "tx", type = "any") tids <- transcripts(x, filter = grg, columns = "tx_id")$tx_id filter <- AnnotationFilterList(filter, TxIdFilter(tids)) }else{ stop("Either all or none of arguments 'chromosome', 'start' and", " 'end' have to be specified!") } } ## Return a data.frame with columns: chromosome, start, end, width, ## strand, feature, ## gene, exon, transcript and symbol. ## 1) Query the data as we usually would. ## 2) Perform an additional query to get cds and utr, remove all entries ## from the first result for the same transcripts and rbind the ## data.frames. needCols <- c("seq_name", "exon_seq_start", "exon_seq_end", "seq_strand", featureIs, "gene_id", "exon_id", "exon_idx", "tx_id", "gene_name") ## That's the names to which we map the original columns from the EnsDb. names(needCols) <- c("chromosome", "start", "end", "strand", "feature", "gene", "exon", "exon_rank", "transcript", "symbol") txs <- transcripts(x, filter = filter, columns = needCols, return.type="data.frame") ## Rename columns idx <- match(needCols, colnames(txs)) notThere <- is.na(idx) idx <- idx[!notThere] colnames(txs)[idx] <- names(needCols)[!notThere] ## now processing the 5utr fUtr <- fiveUTRsByTranscript(x, filter = filter, columns=needCols) if(length(fUtr) > 0){ fUtr <- as(unlist(fUtr, use.names=FALSE), "data.frame") fUtr <- fUtr[, !(colnames(fUtr) %in% c("width", "seq_name", "exon_seq_start", "exon_seq_end", "strand"))] colnames(fUtr)[1] <- "chromosome" idx <- match(needCols, colnames(fUtr)) notThere <- is.na(idx) idx <- idx[!notThere] colnames(fUtr)[idx] <- names(needCols)[!notThere] ## Force being in the correct ordering: fUtr <- fUtr[, names(needCols)] fUtr$feature <- "utr5" ## Remove transcripts from the txs data.frame txs <- txs[!(txs$transcript %in% fUtr$transcript), , drop=FALSE] } tUtr <- threeUTRsByTranscript(x, filter = filter, columns=needCols) if(length(tUtr) > 0){ tUtr <- as(unlist(tUtr, use.names=FALSE), "data.frame") tUtr <- tUtr[, !(colnames(tUtr) %in% c("width", "seq_name", "exon_seq_start", "exon_seq_end", "strand"))] colnames(tUtr)[1] <- "chromosome" idx <- match(needCols, colnames(tUtr)) notThere <- is.na(idx) idx <- idx[!notThere] colnames(tUtr)[idx] <- names(needCols)[!notThere] ## Force being in the correct ordering: tUtr <- tUtr[, names(needCols)] tUtr$feature <- "utr3" ## Remove transcripts from the txs data.frame if(nrow(txs) > 0){ txs <- txs[!(txs$transcript %in% tUtr$transcript), , drop=FALSE] } } cds <- cdsBy(x, filter = filter, columns = needCols) if(length(cds) > 0){ cds <- as(unlist(cds, use.names=FALSE), "data.frame") cds <- cds[, !(colnames(cds) %in% c("width", "seq_name", "exon_seq_start", "exon_seq_end", "strand"))] colnames(cds)[1] <- "chromosome" idx <- match(needCols, colnames(cds)) notThere <- is.na(idx) idx <- idx[!notThere] colnames(cds)[idx] <- names(needCols)[!notThere] ## Force being in the correct ordering: cds <- cds[, names(needCols)] ## Remove transcripts from the txs data.frame if(nrow(txs) > 0){ txs <- txs[!(txs$transcript %in% cds$transcript), , drop=FALSE] } } if(length(fUtr) > 0){ txs <- rbind(txs, fUtr) } if(length(tUtr) > 0){ txs <- rbind(txs, tUtr) } if(length(cds) > 0){ txs <- rbind(txs, cds) } ## Convert into GRanges. suppressWarnings( SI <- seqinfo(x) ) SI <- SI[as.character(unique(txs$chromosome))] GR <- GRanges(seqnames=Rle(txs$chromosome), strand=Rle(txs$strand), ranges=IRanges(start=txs$start, end=txs$end), seqinfo=SI, txs[, c("feature", "gene", "exon", "exon_rank", "transcript", "symbol"), drop=FALSE]) return(GR) }) ####============================================================ ## properties ## ## Get access to the "hidden" .properties slot and return it. ## This ensures that we're not generating an error for objects that ## do not have yet that slot. ####------------------------------------------------------------ setMethod("properties", "EnsDb", function(x, ...){ if(.hasSlot(x, ".properties")){ return(x@.properties) }else{ warning("The present EnsDb instance has no .properties slot! ", "Please use 'updateEnsDb' to update the object!") return(list()) } }) ####============================================================ ## getProperty ## ## Return the value for the property with the specified name or ## NA if not present. ####------------------------------------------------------------ setMethod("getProperty", "EnsDb", function(x, name, default = NA){ props <- properties(x) if(any(names(props) == name)){ return(props[[name]]) }else{ return(default) } }) ####============================================================ ## setProperty ## ## Sets a property in the object. The value has to be a named vector. ####------------------------------------------------------------ setMethod("setProperty", "EnsDb", function(x, ...){ dotL <- list(...) if(length(dotL) == 0){ stop("No property specified! The property has to be submitted ", "in the format name=value!") return(x) } if(length(dotL) > 1){ warning("'setProperty' does only support setting of a single property!", " Using the first submitted one.") dotL <- dotL[1] } if(is.null(names(dotL)) | names(dotL) == "") stop("A name is required! Use name=value!") if(.hasSlot(x, ".properties")){ x@.properties[names(dotL)] <- dotL[[1]] }else{ warning("The present EnsDb instance has no .properties slot! ", "Please use 'updateEnsDb' to update the object!") } return(x) }) #' remove the property with the specified name. #' @noRd dropProperty <- function(x, name) { if (missing(name)) return(x) prps <- x@.properties if (any(names(prps) == name)) prps <- prps[names(prps) != name] x@.properties <- prps x } ####============================================================ ## updateEnsDb ## ## Update any "old" EnsDb instance to the most recent implementation. ####------------------------------------------------------------ setMethod("updateEnsDb", "EnsDb", function(x, ...){ newE <- new("EnsDb", ensdb=x@ensdb, tables=x@tables) if(.hasSlot(x, ".properties")) newE@.properties <- x@.properties return(newE) }) ####============================================================ ## transcriptsByOverlaps ## ## Just "re-implementing" the transcriptsByOverlaps methods from the ## GenomicFeature package, finetuning and adapting it for EnsDbs ####------------------------------------------------------------ setMethod("transcriptsByOverlaps", "EnsDb", function(x, ranges, maxgap = -1L, minoverlap = 0L, type = c("any", "start", "end"), columns = listColumns(x, "tx"), filter = AnnotationFilterList()) { if (missing(ranges)) stop("Parameter 'ranges' is missing!") filter <- .processFilterParam(filter, x) SLs <- unique(as.character(seqnames(ranges))) filter <- AnnotationFilterList(filter, SeqNameFilter(SLs)) columns <- cleanColumns(x, columns) subsetByOverlaps(transcripts(x, columns = columns, filter = filter), ranges, maxgap = maxgap, minoverlap = minoverlap, type = match.arg(type)) }) ####============================================================ ## exonsByOverlaps ## ####------------------------------------------------------------ setMethod("exonsByOverlaps", "EnsDb", function(x, ranges, maxgap = -1L, minoverlap = 0L, type = c("any", "start", "end"), columns = listColumns(x, "exon"), filter = AnnotationFilterList()) { if(missing(ranges)) stop("Parameter 'ranges' is missing!") filter <- .processFilterParam(filter, x) SLs <- unique(as.character(seqnames(ranges))) filter <- AnnotationFilterList(filter, SeqNameFilter(SLs)) columns <- cleanColumns(x, columns) subsetByOverlaps(exons(x, columns = columns, filter = filter), ranges, maxgap = maxgap, minoverlap = minoverlap, type = match.arg(type)) }) ############################################################ ## returnFilterColumns ## ## Method to set the option whether or not the filter columns should be ## returned too. setMethod("returnFilterColumns", "EnsDb", function(x) { return(getProperty(x, "returnFilterColumns")) }) setReplaceMethod("returnFilterColumns", "EnsDb", function(x, value) { if(!is.logical(value)) stop("'value' has to be a logical!") if(length(value) > 1) stop("'value' has to be a logical of length 1!") x <- setProperty(x, returnFilterColumns=value) return(x) }) ############################################################ ## orderResultsInR ## ## Whether the results should be ordered in R instead of in the ## SQL call setMethod("orderResultsInR", "EnsDb", function(x) { return(getProperty(x, "orderResultsInR", default = FALSE)) }) setReplaceMethod("orderResultsInR", "EnsDb", function(x, value) { if(!is.logical(value)) stop("'value' has to be a logical!") if(length(value) > 1) stop("'value' has to be a logical of length 1!") x <- setProperty(x, orderResultsInR = value) return(x) }) ############################################################ ## useMySQL ## ## Switch from RSQlite backend to a MySQL backend. #' @title Use a MySQL backend #' #' @aliases useMySQL #' #' @description Change the SQL backend from \emph{SQLite} to \emph{MySQL}. #' When first called on an \code{\linkS4class{EnsDb}} object, the function #' tries to create and save all of the data into a MySQL database. All #' subsequent calls will connect to the already existing MySQL database. #' #' @details This functionality requires that the \code{RMySQL} package is #' installed and that the user has (write) access to a running MySQL server. #' If the corresponding database does already exist users without write #' access can use this functionality. #' #' @note At present the function does not evaluate whether the versions #' between the SQLite and MySQL database differ. #' #' @param x The \code{\linkS4class{EnsDb}} object. #' #' @param host Character vector specifying the host on which the MySQL #' server runs. #' #' @param port The port on which the MySQL server can be accessed. #' #' @param user The user name for the MySQL server. #' #' @param pass The password for the MySQL server. #' #' @return A \code{\linkS4class{EnsDb}} object providing access to the #' data stored in the MySQL backend. #' #' @author Johannes Rainer #' #' @examples #' ## Load the EnsDb database (SQLite backend). #' library(EnsDb.Hsapiens.v75) #' edb <- EnsDb.Hsapiens.v75 #' ## Now change the backend to MySQL; my_user and my_pass should #' ## be the user name and password to access the MySQL server. #' \dontrun{ #' edb_mysql <- useMySQL(edb, host = "localhost", user = my_user, pass = my_pass) #' } setMethod("useMySQL", "EnsDb", function(x, host = "localhost", port = 3306, user, pass) { if (missing(user)) stop("'user' has to be specified.") if (missing(pass)) stop("'pass' has to be specified.") ## Check if RMySQL package is available. if(requireNamespace("RMySQL", quietly = TRUE)) { ## Check if we can connect to MySQL. driva <- dbDriver("MySQL") con <- dbConnect(driva, host = host, user = user, pass = pass, port = port) ## Check if database is available. dbs <- dbGetQuery(con, "show databases;") ## sqliteName should be in the format EnsDb.Hsapiens.v75! sqliteName <- .makePackageName(dbconn(x)) ## sqliteName <- sub(basename(dbfile(dbconn(x))), ## pattern = ".sqlite", replacement = "", ## fixed = TRUE) mysqlName <- SQLiteName2MySQL(sqliteName) if (nrow(dbs) == 0 | !any(dbs$Database == mysqlName)) { message("Database not available, trying to create it...", appendLF = FALSE) dbGetQuery(con, paste0("create database ", mysqlName)) message("OK") } dbDisconnect(con) ## Connect to the database and check if we've got all tables. con <- dbConnect(driva, host = host, user = user, pass = pass, dbname = mysqlName) ## If we've got no tables we try to feed the SQLite database if (length(dbListTables(con)) == 0) feedEnsDb2MySQL(x, mysql = con) ## Check if we've got all required tables. OK <- dbHasRequiredTables(con) if (is.character(OK)) stop(OK) OK <- dbHasValidTables(con) if (is.character(OK)) stop(OK) ## Check if the versions/creation date differ. metadata_pkg <- metadata(x) ## Now store the connection into the @ensdb slot ## dbDisconnect(x@ensdb) ## x@ensdb <- NULL x@ensdb <- con metadata_db <- metadata(x) cre_pkg <- metadata_pkg[metadata_pkg$name == "Creation time", "value"] cre_db <- metadata_db[metadata_db$name == "Creation time", "value"] if (cre_pkg != cre_db) { message("Creation date between the package and the information in", " the database differ:\n o package: ", cre_pkg, "\n o database: ", cre_db, ".\nYou might consider to delete", " the database and re-install it calling this function.") } return(x) } else { stop("Package 'RMySQL' not available.") } }) ############################################################ ## proteins ## ## If return type is GRanges, make a seqlevel and seqinfo for each protein, i.e. ## put each protein on its own sequence. #' @title Protein related functionality #' #' @aliases proteins #' #' @description This help page provides information about most of the #' functionality related to protein annotations in \code{ensembldb}. #' #' The \code{proteins} method retrieves protein related annotations from #' an \code{\linkS4class{EnsDb}} database. #' #' @details The \code{proteins} method performs the query starting from the #' \code{protein} tables and can hence return all annotations from the #' database that are related to proteins and transcripts encoding these #' proteins from the database. Since \code{proteins} does thus only query #' annotations for protein coding transcripts, the \code{\link{genes}} or #' \code{\link{transcripts}} methods have to be used to retrieve annotations #' for non-coding transcripts. #' #' @param object The \code{\linkS4class{EnsDb}} object. #' #' @param columns For \code{proteins}: character vector defining the columns to #' be extracted from the database. Can be any column(s) listed by the #' \code{\link{listColumns}} method. #' #' @param filter For \code{proteins}: A filter object extending #' \code{AnnotationFilter} or a list of such objects to select #' specific entries from the database. See \code{\link{Filter-classes}} for #' a documentation of available filters and use #' \code{\link{supportedFilters}} to get the full list of supported filters. #' #' @param order.by For \code{proteins}: a character vector specifying the #' column(s) by which the result should be ordered. #' #' @param order.type For \code{proteins}: if the results should be ordered #' ascending (\code{order.type = "asc"}) or descending #' (\code{order.type = "desc"}) #' #' @param return.type For \code{proteins}: character of lenght one specifying #' the type of the returned object. Can be either \code{"DataFrame"}, #' \code{"data.frame"} or \code{"AAStringSet"}. #' #' @return The \code{proteins} method returns protein related annotations from #' an \code{\linkS4class{EnsDb}} object with its \code{return.type} argument #' allowing to define the type of the returned object. Note that if #' \code{return.type = "AAStringSet"} additional annotation columns are #' stored in a \code{DataFrame} that can be accessed with the \code{mcols} #' method on the returned object. #' #' @rdname ProteinFunctionality #' #' @author Johannes Rainer #' #' @examples #' library(ensembldb) #' library(EnsDb.Hsapiens.v75) #' edb <- EnsDb.Hsapiens.v75 #' ## Get all proteins from tha database for the gene ZBTB16, if protein #' ## annotations are available #' if (hasProteinData(edb)) #' proteins(edb, filter = GenenameFilter("ZBTB16")) setMethod("proteins", "EnsDb", function(object, columns = listColumns(object, "protein"), filter = AnnotationFilterList(), order.by = "", order.type = "asc", return.type = "DataFrame") { if (!hasProteinData(object)) stop("The used EnsDb does not provide protein annotations!", " Thus, 'proteins' can not be used.") return.type <- match.arg(return.type, c("DataFrame", "AAStringSet", "data.frame")) columns <- cleanColumns(object, unique(c(columns, "protein_id"))) filter <- .processFilterParam(filter, object) filter <- setFeatureInGRangesFilter(filter, "tx") ## Eventually add columns for the filters: columns <- addFilterColumns(columns, filter, object) ## Check that we don't have any exon columns here. ex_cols <- unique(listColumns(object, c("exon", "tx2exon"))) ex_cols <- ex_cols[ex_cols != "tx_id"] if (any(columns %in% ex_cols)) { warning("Exon specific columns are not allowed for proteins. Columns ", paste0("'", columns[columns %in% ex_cols], "'", collapse = ", "), " have been removed.") columns <- columns[!(columns %in% ex_cols)] } retColumns <- columns ## Process order.by: ## If not specified we might want to order them by seq_name or tx_seq_start ## if present in parameter columns if (all(order.by == "")) { order.by <- NULL if (any(columns == "seq_name")) order.by <- "seq_name" seq_col_idx <- grep(columns, pattern = "_seq_") if (length(seq_col_idx) > 0) order.by <- c(order.by, columns[seq_col_idx[1]]) if (is.null(order.by)) order.by <- "" } ## If we're going to return a GRanges we need to know the length of the ## peptide sequence. if (return.type == "AAStringSet") { columns <- unique(c(columns, "protein_sequence")) } ## protein_id is *always* required columns <- unique(c(columns), "protein_id") ## Get the data Res <- getWhat(object, columns = columns, filter = filter, order.by = order.by, order.type = order.type, startWith = "protein", join = "suggested") ## issue #48: collapse entrezid column if dbschema 2.0 is used. if (as.numeric(dbSchemaVersion(object)) > 1 & any(columns == "entrezid")) Res <- .collapseEntrezidInTable(Res, by = "protein_id") ## Now process the result. cols_not_found <- !(retColumns %in% colnames(Res)) retColumns <- retColumns[!cols_not_found] if (any(cols_not_found)) warning("Columns ", paste0("'", retColumns[cols_not_found], "'", collapse = ", "), " not found in the database!") if (return.type == "AAStringSet") { aass <- AAStringSet(Res$protein_sequence) names(aass) <- Res$protein_id ## Add the mcols: retColumns <- retColumns[retColumns != "protein_sequence"] if (length(retColumns) > 0) mcols(aass) <- DataFrame(Res[, retColumns, drop = FALSE]) return(aass) } else { Res <- Res[, retColumns, drop = FALSE] if (return.type == "DataFrame") Res <- DataFrame(Res) return(Res) } return(NULL) }) ############################################################ ## listUniprotDbs #' @aliases listUniprotDbs #' #' @description The \code{listUniprotDbs} method lists all Uniprot database #' names in the \code{EnsDb}. #' #' @examples #' #' ## List the names of all Uniprot databases from which Uniprot IDs are #' ## available in the EnsDb #' if (hasProteinData(edb)) #' listUniprotDbs(edb) #' #' @rdname ProteinFunctionality setMethod("listUniprotDbs", "EnsDb", function(object) { if (!hasProteinData(object)) stop("The provided EnsDb database does not provide protein annotations!") res <- dbGetQuery(dbconn(object), "select distinct uniprot_db from uniprot") return(res$uniprot_db) }) ############################################################ ## listUniprotMappingTypes #' @aliases listUniprotMappingTypes #' #' @description The \code{listUniprotMappingTypes} method lists all methods #' that were used for the mapping of Uniprot IDs to Ensembl protein IDs. #' #' @examples #' #' ## List the type of all methods that were used to map Uniprot IDs to Ensembl #' ## protein IDs #' if (hasProteinData(edb)) #' listUniprotMappingTypes(edb) #' #' @rdname ProteinFunctionality setMethod("listUniprotMappingTypes", "EnsDb", function(object) { if (!hasProteinData(object)) stop("The provided EnsDb database does not provide protein annotations!") res <- dbGetQuery(dbconn(object), "select distinct uniprot_mapping_type from uniprot") return(res$uniprot_mapping_type) }) #' @description \code{supportedFilters} returns a \code{data.frame} with the #' names of all filters and the corresponding field supported by the #' \code{EnsDb} object. #' #' @param object For \code{supportedFilters}: an \code{EnsDb} object. #' #' @param ... For \code{supportedFilters}: currently not used. #' #' @return For \code{supportedFilters}: a \code{data.frame} with the names and #' the corresponding field of the supported filter classes. #' #' @rdname Filter-classes setMethod("supportedFilters", "EnsDb", function(object, ...) { .supportedFilters(object) }) #' @title Globally add filters to an EnsDb database #' #' @aliases addFilter addFilter,EnsDb-method #' #' @description These methods allow to set, delete or show globally defined #' filters on an \code{\linkS4class{EnsDb}} object. #' #' \code{addFilter}: adds an annotation filter to the \code{EnsDb} object. #' #' @details Adding a filter to an \code{EnsDb} object causes this filter to be #' permanently active. The filter will be used for all queries to the #' database and is added to all additional filters passed to the methods #' such as \code{\link{genes}}. #' #' @param x The \code{\linkS4class{EnsDb}} object to which the filter should be #' added. #' #' @param filter The filter as an #' \code{\link[AnnotationFilter]{AnnotationFilter}}, #' \code{\link[AnnotationFilter]{AnnotationFilterList}} or filter #' expression. See #' #' @return \code{addFilter} and \code{filter} return an \code{EnsDb} object #' with the specified filter added. #' #' \code{activeFilter} returns an #' \code{\link[AnnotationFilter]{AnnotationFilterList}} object being the #' active global filter or \code{NA} if no filter was added. #' #' \code{dropFilter} returns an \code{EnsDb} object with all eventually #' present global filters removed. #' #' @author Johannes Rainer #' #' @rdname global-filters #' #' @seealso \code{\link{Filter-classes}} for a list of all supported filters. #' #' @examples #' library(EnsDb.Hsapiens.v75) #' edb <- EnsDb.Hsapiens.v75 #' #' ## Add a global SeqNameFilter to the database such that all subsequent #' ## queries will be applied on the filtered database. #' edb_y <- addFilter(edb, SeqNameFilter("Y")) #' #' ## Note: using the filter function is equivalent to a call to addFilter. #' #' ## Each call returns now only features encoded on chromosome Y #' gns <- genes(edb_y) #' #' seqlevels(gns) #' #' ## Get all lincRNA gene transcripts on chromosome Y #' transcripts(edb_y, filter = ~ gene_biotype == "lincRNA") #' #' ## Get the currently active global filter: #' activeFilter(edb_y) #' #' ## Delete this filter again. #' edb_y <- dropFilter(edb_y) #' #' activeFilter(edb_y) setMethod("addFilter", "EnsDb", function(x, filter = AnnotationFilterList()) { .addFilter(x, filter) }) #' @aliases dropFilter dropFilter,EnsDb-method #' #' @description \code{dropFilter} deletes all globally set filters from the #' \code{EnsDb} object. #' #' @rdname global-filters setMethod("dropFilter", "EnsDb", function(x) { .dropFilter(x) }) #' @aliases activeFilter activeFilter,EnsDb-method #' #' @description \code{activeFilter} returns the globally set filter from an #' \code{EnsDb} object. #' #' @rdname global-filters setMethod("activeFilter", "EnsDb", function(x) { .activeFilter(x) }) ensembldb/R/dbhelpers.R0000644000175400017540000010001113175714743016034 0ustar00biocbuildbiocbuild############################################################ ## EnsDb ## Constructor function. #' @title Connect to an EnsDb object #' #' @description The \code{EnsDb} constructor function connects to the database #' specified with argument \code{x} and returns a corresponding #' \code{\linkS4class{EnsDb}} object. #' #' @details By providing the connection to a MySQL database, it is possible #' to use MySQL as the database backend and queries will be performed on #' that database. Note however that this requires the package \code{RMySQL} #' to be installed. In addition, the user needs to have access to a MySQL #' server providing already an EnsDb database, or must have write #' privileges on a MySQL server, in which case the \code{\link{useMySQL}} #' method can be used to insert the annotations from an EnsDB package into #' a MySQL database. #' #' @param x Either a character specifying the \emph{SQLite} database file, or #' a \code{DBIConnection} to e.g. a MySQL database. #' #' @return A \code{\linkS4class{EnsDb}} object. #' #' @author Johannes Rainer #' #' @examples #' ## "Standard" way to create an EnsDb object: #' library(EnsDb.Hsapiens.v75) #' EnsDb.Hsapiens.v75 #' #' ## Alternatively, provide the full file name of a SQLite database file #' dbfile <- system.file("extdata/EnsDb.Hsapiens.v75.sqlite", package = "EnsDb.Hsapiens.v75") #' edb <- EnsDb(dbfile) #' edb #' #' ## Third way: connect to a MySQL database #' \dontrun{ #' library(RMySQL) #' dbcon <- dbConnect(MySQL(), user = my_user, pass = my_pass, host = my_host, dbname = "ensdb_hsapiens_v75") #' edb <- EnsDb(dbcon) #' } EnsDb <- function(x){ options(useFancyQuotes=FALSE) if(missing(x)){ stop("No sqlite file provided!") } if (is.character(x)) { lite <- dbDriver("SQLite") con <- dbConnect(lite, dbname = x, flags=SQLITE_RO) } else if (is(x, "DBIConnection")) { con <- x } else { stop("'x' should be either a character specifying the SQLite file to", " be loaded, or a DBIConnection object providing the connection", " to the database.") } ## Check if the database is valid. OK <- dbHasRequiredTables(con) if (is.character(OK)) stop(OK) OK <- dbHasValidTables(con) if (is.character(OK)) stop(OK) tables <- dbListTables(con) ## read the columns for these tables. Tables <- vector(length=length(tables), "list") for(i in 1:length(Tables)){ Tables[[ i ]] <- colnames(dbGetQuery(con, paste0("select * from ", tables[ i ], " limit 1"))) } names(Tables) <- tables EDB <- new("EnsDb", ensdb = con, tables = Tables) EDB <- setProperty(EDB, dbSeqlevelsStyle="Ensembl") ## Add the db schema version to the properties. EDB <- setProperty(EDB, DBSCHEMAVERSION = .getMetaDataValue(con, "DBSCHEMAVERSION")) ## Setting the default for the returnFilterColumns returnFilterColumns(EDB) <- TRUE ## Defining the default for the ordering orderResultsInR(EDB) <- FALSE ## Check it again... OK <- validateEnsDb(EDB) if (is.character(OK)) stop(OK) EDB } ## loadEnsDb <- function(x) { ## ## con <- ensDb( x ) ## ## EDB <- new( "EnsDb", ensdb=con ) ## return(EnsDb(x)) ## } ## x is the connection to the database, name is the name of the entry to fetch .getMetaDataValue <- function(x, name){ return(dbGetQuery(x, paste0("select value from metadata where name='", name, "'"))[ 1, 1]) } ############################################################ ## prefixColumns ## ## Determines which tables (along with the table attributes) are required for ## the join. ## Updated version of prefixColumns: ## o Uses the order of the tables returned by listTables and adds the first ## table in which the column was found. That's different to the previous ## default of trying to join as few tables as possible but avoids problems ## with table joins between e.g. tx and protein in which not all tx_id are ## present in the protein table. prefixColumns <- function(x, columns, clean = TRUE, with.tables){ if (missing(columns)) stop("columns is empty! No columns provided!") ## first get to the tables that contain these columns Tab <- listTables(x) ## returns the tables by degree! if (!missing(with.tables)) { with.tables <- with.tables[ with.tables %in% names(Tab) ] if (length(with.tables) > 0) { Tab <- Tab[ with.tables ] } else { warning("The submitted table names are not valid in the database", " and were thus dropped.") } if (length(Tab) == 0) stop("None of the tables submitted with with.tables is present", " in the database!") } if (clean) columns <- cleanColumns(x, columns) if (length(columns) == 0) { return(NULL) } getCols <- columns result <- lapply(Tab, function(z) { if (length(getCols) > 0) { gotIt <- z[z %in% getCols] if (length(gotIt) > 0) { getCols <<- getCols[!(getCols %in% gotIt)] return(gotIt) } else { return(character()) } } }) ## If getCols length > 0 it contains columns not present in the db. result <- result[lengths(result) > 0] if (length(result) == 0) stop("None of the columns could be found in the database!") result <- mapply(result, names(result), FUN = function(z, y) { paste0(y, ".", z) }, SIMPLIFY = FALSE) return(result) } ############################################################ ## call the prefixColumns function and return just the column ## names, but in the same order than the provided columns. prefixColumnsKeepOrder <- function(x, columns, clean = TRUE, with.tables) { res <- unlist(prefixColumns(x, columns, clean, with.tables), use.names = FALSE) res_order <- sapply(columns, function(z) { idx <- grep(res, pattern = paste0("\\.", z, "$")) if (length(idx) == 0) return(NULL) return(res[idx[1]]) }) return(res_order[!is.null(res_order)]) } ############################################################ ## ** NEW JOIN ENGINE ** ## ## 1: table 1 ## 2: table 2 ## 3: on ## 4: suggested join .JOINS2 <- rbind( c("gene", "tx", "on (gene.gene_id=tx.gene_id)", "join"), c("gene", "chromosome", "on (gene.seq_name=chromosome.seq_name)", "join"), c("tx", "tx2exon", "on (tx.tx_id=tx2exon.tx_id)", "join"), c("tx2exon", "exon", "on (tx2exon.exon_id=exon.exon_id)", "join"), c("tx", "protein", "on (tx.tx_id=protein.tx_id)", "left outer join"), c("gene", "entrezgene", "on (gene.gene_id=entrezgene.gene_id)", "left outer join"), c("protein", "protein_domain", "on (protein.protein_id=protein_domain.protein_id)", "left outer join"), c("protein", "uniprot", "on (protein.protein_id=uniprot.protein_id)", "left outer join"), c("uniprot", "protein_domain", "on (uniprot.protein_id=protein_domain.protein_id)", "left outer join") ) ## Takes the names of two tables, determines how to join them and returns the ## join query row, if found. joinTwoTables <- function(a, b) { gotIt <- which((.JOINS2[, 1] %in% a & .JOINS2[, 2] %in% b) | (.JOINS2[, 2] %in% a & .JOINS2[, 1] %in% b)) if (length(gotIt) == 0) { stop("Table(s) ", paste(a, collapse = ", "), " can not be joined with ", paste(b, collapse = ", "), "!") } else { return(.JOINS2[gotIt[1], ]) } } ## x: EnsDb. ## tab: tables to join. ## join: which type of join should be used? ## startWith: optional table name from which the join should start. That's ## specifically important for a left outer join call. joinQueryOnTables2 <- function(x, tab, join = "suggested", startWith = NULL) { ## join can be join, left join, left outer join or suggested in which case ## the join defined in the .JOINS2 table will be used. join <- match.arg(join, c("join", "left join", "left outer join", "suggested")) ## Order the tables. ## Start with startWith, or with the first one. if (missing(tab)) stop("Argument 'tab' missing! Need some tables to make a join!") if (!is.null(startWith)) { if (!any(tab == startWith)) stop("If provided, 'startWith' has to be the name of one of the", " tables that should be joined!") } ## Add eventually needed tables to link the ones provided. The tables will ## be ordered by degree. tab <- addRequiredTables(x, tab) if (!is.null(startWith)) { alreadyUsed <- startWith tab <- tab[tab != startWith] } else { alreadyUsed <- tab[1] tab <- tab[-1] } Query <- alreadyUsed ## Iteratively build the query. while (length(tab) > 0) { res <- joinTwoTables(a = alreadyUsed, b = tab) newTab <- res[1:2][!(res[1:2] %in% alreadyUsed)] ## Could also use the suggested join which is in element 4. Query <- paste(Query, ifelse(join == "suggested", res[4], join), newTab, res[3]) alreadyUsed <- c(alreadyUsed, newTab) tab <- tab[tab != newTab] } return(Query) } ## this function has to first get all tables that contain the columns, ## and then select, for columns present in more than one ## x... EnsDb ## columns... the columns ## NOTE: if "startWith" is not NULL, we're adding it to the tables!!!! joinQueryOnColumns2 <- function(x, columns, join = "suggested", startWith = NULL) { columns.bytable <- prefixColumns(x, columns) ## based on that we can build the query based on the tables we've got. ## Note that the function internally ## adds tables that might be needed for the join. Query <- joinQueryOnTables2(x, tab = c(names(columns.bytable), startWith), join = join, startWith = startWith) return(Query) } ### ## Add additional tables in case the submitted tables are not directly connected ## and can thus not be joined. That's however not so complicated, since the database ## layout is pretty simple. addRequiredTables <- function(x, tab){ ## dash it, as long as I can't find a way to get connected objects in a ## graph I'll do it manually... ## if we have exon and any other table, we need definitely tx2exon if(any(tab=="exon") & length(tab) > 1){ tab <- unique(c(tab, "tx2exon")) } ## if we have chromosome and any other table, we'll need gene if(any(tab=="chromosome") & length(tab) > 1){ tab <- unique(c(tab, "gene")) } ## if we have exon and we have gene, we'll need also tx if((any(tab=="exon") | (any(tab=="tx2exon"))) & any(tab=="gene")){ tab <- unique(c(tab, "tx")) } if (hasProteinData(x)) { ## Resolve the proteins: need tx to map between proteome and genome if (any(tab %in% c("uniprot", "protein_domain", "protein")) & any(tab %in% c("exon", "tx2exon", "gene", "chromosome", "entrezgene"))) tab <- unique(c(tab, "tx")) ## Need protein. if (any(tab %in% c("uniprot", "protein_domain")) & any(tab %in% c("exon", "tx2exon", "tx", "gene", "chromosome", "entrezgene"))) tab <- unique(c(tab, "protein")) } ## entrezgene is only linked via gene if (any(tab == "entrezgene") & length(tab) > 1) tab <- unique(c(tab, "gene")) return(tablesByDegree(x, tab)) } ############################################################ ## .buildQuery ## ## The "backbone" function that builds the SQL query based on the specified ## columns, the provided filters etc. ## x an EnsDb object ## startWith: optional table from which the join should start. .buildQuery <- function(x, columns, filter = AnnotationFilterList(), order.by = "", order.type = "asc", group.by, skip.order.check=FALSE, return.all.columns = TRUE, join = "suggested", startWith = NULL) { resultcolumns <- columns ## just to remember what we really want to give back ## 1) get all column names from the filters also removing the prefix. if (!is(filter, "AnnotationFilterList")) stop("parameter 'filter' has to be an 'AnnotationFilterList'!") if (length(filter) > 0) { ## check filter! ## add the columns needed for the filter filtercolumns <- unlist(lapply(filter, ensDbColumn, x)) ## remove the prefix (column name for these) filtercolumns <- sapply(filtercolumns, removePrefix, USE.NAMES = FALSE) columns <- unique(c(columns, filtercolumns)) } ## 2) get all column names for the order.by: if (any(order.by != "")) { ## if we have skip.order.check set we use the order.by as is. if (!skip.order.check) { order.by <- checkOrderBy(orderBy = order.by, supported = columns) } }else{ order.by <- "" } ## Note: order by is now a vector!!! ## columns are now all columns that we want to fetch or that we need to ## filter or to sort. ## 3) check which tables we need for all of these columns: need.tables <- names(prefixColumns(x, columns)) ## ## Now we can begin to build the query parts! ## a) the query part that joins all required tables. joinquery <- joinQueryOnColumns2(x, columns=columns, join = join, startWith = startWith) ## b) the filter part of the query if (length(filter) > 0) { ## USE THE ensDbQuery method here!!! filterquery <- paste0(" where ", ensDbQuery(filter, x, with.tables = need.tables)) } else { filterquery <- "" } ## c) the order part of the query if (any(order.by != "")) { if (!skip.order.check) { order.by <- paste(prefixColumnsKeepOrder(x = x, columns = order.by, with.tables = need.tables), collapse=",") } orderquery <- paste(" order by", order.by, order.type) }else{ orderquery <- "" } ## And finally build the final query if(return.all.columns){ resultcolumns <- columns } finalquery <- paste0("select distinct ", paste(prefixColumnsKeepOrder(x, resultcolumns, with.tables = need.tables), collapse=","), " from ", joinquery, filterquery, orderquery ) return(finalquery) } ## remove the prefix again... removePrefix <- function(x, split=".", fixed=TRUE){ return(sapply(x, function(z){ tmp <- unlist(strsplit(z, split=split, fixed=fixed)) return(tmp[ length(tmp) ]) })) } ## just to add another layer; basically just calls buildQuery and executes the ## query ## join: what type of join should be performed. ## startWith: the name of the table from which the query should be started. .getWhat <- function(x, columns, filter = AnnotationFilterList(), order.by = "", order.type = "asc", group.by = NULL, skip.order.check = FALSE, join = "suggested", startWith = NULL) { ## That's nasty stuff; for now we support the column tx_name, which we however ## don't have in the database. Thus, we are querying everything except that ## column and filling it later with the values from tx_id. fetchColumns <- columns if(any(columns == "tx_name")) fetchColumns <- unique(c("tx_id", fetchColumns[fetchColumns != "tx_name"])) if (!is(filter, "AnnotationFilterList")) stop("parameter 'filter' has to be an 'AnnotationFilterList'!") ## Add also the global filter if present. global_filter <- .activeFilter(x) if (is(global_filter, "AnnotationFilter") | is(global_filter, "AnnotationFilterList")) filter <- AnnotationFilterList(global_filter, filter) ## If any filter is a SymbolFilter, add "symbol" to the return columns. if (length(filter) > 0) { if (any(.anyIs(filter, "SymbolFilter"))) columns <- unique(c(columns, "symbol")) ## append a filter column. } ## Catch also a "symbol" in columns if(any(columns == "symbol")) fetchColumns <- unique(c(fetchColumns[fetchColumns != "symbol"], "gene_name")) ## Shall we do the ordering in R or in SQL? if (orderResultsInR(x) & !skip.order.check) { ## Build the query Q <- .buildQuery(x = x, columns = fetchColumns, filter = filter, order.by = "", order.type = order.type, group.by = group.by, skip.order.check = skip.order.check, join = join, startWith = startWith) ## Get the data ## cat("Query: ", Q, "\n") Res <- dbGetQuery(dbconn(x), Q) ## Note: we can only order by the columns that we did get back from the ## database; that might be different for the SQL sorting! Res <- orderDataFrameBy(Res, by = checkOrderBy(order.by, fetchColumns), decreasing = order.type != "asc") } else { ## Build the query Q <- .buildQuery(x = x, columns = fetchColumns, filter = filter, order.by = order.by, order.type = order.type, group.by = group.by, skip.order.check = skip.order.check, join = join, startWith = startWith) ## Get the data ## cat("Query: ", Q, "\n") Res <- dbGetQuery(dbconn(x), Q) } ## cat("Query:\n", Q, "\n") if(any(columns == "tx_cds_seq_start")) { if (!is.integer(Res[, "tx_cds_seq_start"])) { suppressWarnings( ## column contains "NULL" if not defined and coordinates are ## characters as.numeric transforms "NULL" into NA, and ensures ## coords are numeric. Res[ , "tx_cds_seq_start"] <- as.integer(Res[ , "tx_cds_seq_start"]) ) } } if(any(columns=="tx_cds_seq_end")){ if (!is.integer(Res[, "tx_cds_seq_end"])) { suppressWarnings( ## column contains "NULL" if not defined and coordinates are ## characters as.numeric transforms "NULL" into NA, and ensures ## coords are numeric. Res[ , "tx_cds_seq_end" ] <- as.integer(Res[ , "tx_cds_seq_end" ]) ) } } ## Fix for MySQL returning 'numeric' instead of 'integer'. ## THIS SHOULD BE REMOVED ONCE THE PROBLEM IS FIXED IN RMySQL!!! int_cols <- c("exon_seq_start", "exon_seq_end", "exon_idx", "tx_seq_start", "tx_seq_end", "tx_cds_seq_start", "tx_cds_seq_end", "gene_seq_start", "gene_seq_end", "seq_strand") for (the_col in int_cols) { if (any(colnames(Res) == the_col)) if (!is.integer(Res[, the_col])) Res[, the_col] <- as.integer(Res[, the_col]) } ## Resolving the "symlinks" again. if(any(columns == "tx_name")) { Res <- data.frame(Res, tx_name = Res$tx_id, stringsAsFactors = FALSE) } if(any(columns == "symbol")) { Res <- data.frame(Res, symbol = Res$gene_name, stringsAsFactors = FALSE) } ## Ensure that the ordering is as requested. Res <- Res[, columns, drop=FALSE] Res } ############################################################ ## Check database validity. #' @description Return tables with attributes based on the provided schema. #' #' @noRd .ensdb_tables <- function(version = "1.0") { .ENSDB_TABLES <- list(`1.0` = list( gene = c("gene_id", "gene_name", "entrezid", "gene_biotype", "gene_seq_start", "gene_seq_end", "seq_name", "seq_strand", "seq_coord_system"), tx = c("tx_id", "tx_biotype", "tx_seq_start", "tx_seq_end", "tx_cds_seq_start", "tx_cds_seq_end", "gene_id"), tx2exon = c("tx_id", "exon_id", "exon_idx"), exon = c("exon_id", "exon_seq_start", "exon_seq_end"), chromosome = c("seq_name", "seq_length", "is_circular"), metadata = c("name", "value")), `2.0` = list( gene = c("gene_id", "gene_name", "gene_biotype", "gene_seq_start", "gene_seq_end", "seq_name", "seq_strand", "seq_coord_system"), tx = c("tx_id", "tx_biotype", "tx_seq_start", "tx_seq_end", "tx_cds_seq_start", "tx_cds_seq_end", "gene_id"), tx2exon = c("tx_id", "exon_id", "exon_idx"), exon = c("exon_id", "exon_seq_start", "exon_seq_end"), chromosome = c("seq_name", "seq_length", "is_circular"), entrezgene = c("gene_id", "entrezid"), metadata = c("name", "value")) ) .ENSDB_TABLES[[version]] } .ensdb_protein_tables <- function(version = "1.0") { .ENSDB_PROTEIN_TABLES <- list(`1.0` = list( protein = c("tx_id", "protein_id", "protein_sequence"), uniprot = c("protein_id", "uniprot_id", "uniprot_db", "uniprot_mapping_type"), protein_domain = c("protein_id", "protein_domain_id", "protein_domain_source", "interpro_accession", "prot_dom_start", "prot_dom_end")), `2.0` = list( protein = c("tx_id", "protein_id", "protein_sequence"), uniprot = c("protein_id", "uniprot_id", "uniprot_db", "uniprot_mapping_type"), protein_domain = c("protein_id", "protein_domain_id", "protein_domain_source", "interpro_accession", "prot_dom_start", "prot_dom_end")) ) .ENSDB_PROTEIN_TABLES[[version]] } #' @description Extract the database schema version if available in the metadata #' database column. #' #' @param x Can be either a connection object or an \code{EnsDb} object. #' #' @noRd dbSchemaVersion <- function(x) { if (is(x, "EnsDb")) { return(getProperty(x, "DBSCHEMAVERSION")) } else { tabs <- dbListTables(x) if (any(tabs == "metadata")) { res <- dbGetQuery(x, "select * from metadata") if (any(res$name == "DBSCHEMAVERSION") & any(colnames(res) == "value")) return(res[res$name == "DBSCHEMAVERSION", "value"]) } } return("1.0") } dbHasRequiredTables <- function(con, returnError = TRUE, tables = .ensdb_tables(dbSchemaVersion(con))) { tabs <- dbListTables(con) if (length(tabs) == 0) { if (returnError) return("Database does not have any tables!") return(FALSE) } not_there <- names(tables)[!(names(tables) %in% tabs)] if (length(not_there) > 0) { if (returnError) return(paste0("Required tables ", paste(not_there, collapse = ", "), " are not present in the database!")) return(FALSE) } return(TRUE) } dbHasValidTables <- function(con, returnError = TRUE, tables = .ensdb_tables(dbSchemaVersion(con))) { for (tab in names(tables)) { cols <- tables[[tab]] from_db <- colnames(dbGetQuery(con, paste0("select * from ", tab, " limit 1"))) not_there <- cols[!(cols %in% from_db)] if (length(not_there) > 0) { if (returnError) return(paste0("Table ", tab, " is missing required columns ", paste(not_there, collapse = ", "), "!")) return(FALSE) } } return(TRUE) } ############################################################ ## feedEnsDb2MySQL ## ## feedEnsDb2MySQL <- function(x, mysql, verbose = TRUE) { if (!inherits(mysql, "MySQLConnection")) stop("'mysql' is supposed to be a connection to a MySQL database.") ## Fetch the tables and feed them to MySQL. sqlite_con <- dbconn(x) tabs <- dbListTables(sqlite_con) for (the_table in tabs) { if (verbose) message("Fetch table ", the_table, "...", appendLF = FALSE) tmp <- dbGetQuery(sqlite_con, paste0("select * from ", the_table, ";")) if (verbose) message("OK\nStoring the table in MySQL...", appendLF = FALSE) ## Fix tx_cds_seq_start being a character in old databases if (any(colnames(tmp) == "tx_cds_seq_start")) { suppressWarnings( tmp[, "tx_cds_seq_start"] <- as.integer(tmp[, "tx_cds_seq_start"]) ) suppressWarnings( tmp[, "tx_cds_seq_end"] <- as.integer(tmp[, "tx_cds_seq_end"]) ) } dbWriteTable(mysql, tmp, name = the_table, row.names = FALSE) if (verbose) message("OK") } ## Create the indices. if (verbose) message("Creating indices...", appendLF = FALSE) ## Guess index length on the maximal number of characters of an ID. indexLength <- max(nchar( dbGetQuery(sqlite_con, "select distinct gene_id from gene")$gene_id )) .createEnsDbIndices(mysql, indexLength = paste0("(", indexLength, ")"), proteins = hasProteinData(x)) if (verbose) message("OK") return(TRUE) } ## Small helper function to cfeate all the indices. .createEnsDbIndices <- function(con, indexLength = "", proteins = FALSE) { indexCols <- c(chromosome = "seq_name", gene = "gene_id", gene = "gene_name", gene = "seq_name", tx = "tx_id", tx = "gene_id", exon = "exon_id", tx2exon = "tx_id", tx2exon = "exon_id") if (as.numeric(dbSchemaVersion(con)) > 1) indexCols <- c(indexCols, entrezgene = "gene_id", entrezgene = "entrezid") if (proteins) { indexCols <- c(indexCols, protein = "tx_id", protein = "protein_id", uniprot = "protein_id", uniprot = "uniprot_id", protein_domain = "protein_domain_id", protein_domain = "protein_id") } for (i in 1:length(indexCols)) { tabname <- names(indexCols)[i] colname <- indexCols[i] ## Check if we've got any values at all. if not we're not creating the ## index. ids <- dbGetQuery(con, paste0("select distinct ", colname, " from ", tabname))[, colname] if (length(ids) == 0 | all(is.na(ids))) { ## No need to make an index here! } else { if (indexLength != "") idxL <- paste0("(", min(c(max(nchar(ids)), 20)), ")") else idxL <- "" aff_rows <- dbExecute( con, paste0("create index ", tabname, "_", colname, "_idx ", "on ", tabname, " (",colname, idxL,")")) } } ## Add the one on the numeric index: aff_rows <- dbExecute(con, paste0("create index tx2exon_exon_idx_idx on ", "tx2exon (exon_idx);")) } ############################################################ ## listEnsDbs ## list databases #' @title List EnsDb databases in a MySQL server #' #' @description The \code{listEnsDbs} function lists EnsDb databases in a #' MySQL server. #' #' @details The use of this function requires that the \code{RMySQL} package #' is installed and that the user has either access to a MySQL server with #' already installed EnsDb databases, or write access to a MySQL server in #' which case EnsDb databases could be added with the \code{\link{useMySQL}} #' method. EnsDb databases follow the same naming conventions than the EnsDb #' packages, with the exception that the name is all lower case and that #' \code{"."} is replaced by \code{"_"}. #' #' @param dbcon A \code{DBIConnection} object providing access to a MySQL #' database. Either \code{dbcon} or all of the other arguments have to be #' specified. #' #' @param host Character specifying the host on which the MySQL server is #' running. #' #' @param port The port of the MySQL server (usually \code{3306}). #' #' @param user The username for the MySQL server. #' #' @param pass The password for the MySQL server. #' #' @return A \code{data.frame} listing the database names, organism name #' and Ensembl version of the EnsDb databases found on the server. #' #' @author Johannes Rainer #' #' @seealso \code{\link{useMySQL}} #' #' @examples #' \dontrun{ #' library(RMySQL) #' dbcon <- dbConnect(MySQL(), host = "localhost", user = my_user, pass = my_pass) #' listEnsDbs(dbcon) #' } listEnsDbs <- function(dbcon, host, port, user, pass) { if(requireNamespace("RMySQL", quietly = TRUE)) { if (missing(dbcon)) { if (missing(host) | missing(user) | missing(port) | missing(host)) stop("Arguments 'host', 'port', 'user' and 'pass' are required", " if 'dbcon' is not specified.") dbcon <- dbConnect(RMySQL::MySQL(), host = host, port = port, user = user, pass = pass) } dbs <- dbGetQuery(dbcon, "show databases;") edbs <- dbs[grep(dbs$Database, pattern = "^ensdb_"), "Database"] edbTable <- data.frame(matrix(ncol = 3, nrow = length(edbs))) colnames (edbTable) <- c("dbname", "organism", "ensembl_version") for (i in seq_along(edbs)) { edbTable[i, "dbname"] <- edbs[i] tmp <- unlist(strsplit(edbs[i], split = "_")) edbTable[i, "organism"] <- tmp[2] edbTable[i, "ensembl_version"] <- as.numeric(gsub(pattern = "v", replacement = "", tmp[3])) } return(edbTable) } else { stop("Required package 'RMySQL' is not installed.") } } #' Simple helper that "translates" R logical operators to SQL. #' @noRd .logOp2SQL <- function(x) { if (x == "|") return("or") if (x == "&") return("and") return(NULL) } ensembldb/R/functions-EnsDb.R0000644000175400017540000000514213175714743017076 0ustar00biocbuildbiocbuild## Functions related to EnsDb objects. #' @title Globally filter an EnsDb database #' #' @description \code{.addFilter} globally filters the provided #' \code{EnsDb} database, i.e. it returns a \code{EnsDb} object with the #' provided filter permanently set and active. #' #' @details Adding a filter to an \code{EnsDb} object causes this filter to be #' permanently active. The filter will be used for all queries to the #' databases and is added to all additional filters passed to the methods. #' #' @param x An \code{EnsDb} object on which the filter(s) should be set. #' #' @param filter An \code{\link[AnnotationFilter]{AnnotationFilterList}}, #' \code{\link[AnnotationFulter]{AnnotationFilter}} object or a filter #' expression providing the filter(s) to be set. #' #' @return For \code{.addFilter}: the \code{EnsDb} object with the filter #' globally added and enabled. #' #' For \code{.dropFilter}: the \code{EnsDb} object with all filters removed. #' #' For \code{.activeFilter}: an \code{} #' #' @author Johannes Rainer #' #' @noRd .addFilter <- function(x, filter = AnnotationFilterList()) { if (length(filter) == 0) stop("No filter provided") filter <- .processFilterParam(filter, x) ## Now, if there was no error, filter is an AnnotationFilterList got_filter <- getProperty(x, "FILTER") if (is(got_filter, "AnnotationFilter") | is(got_filter, "AnnotationFilterList")) { ## Append the new filter. filter <- AnnotationFilterList(got_filter, filter) } else { if (!is.na(got_filter)) stop("Globally set filter is not an 'AnnotationFilter' or ", "'AnnotationFilterList'") } x@.properties$FILTER <- filter x } #' @description \code{.dropFilter} drops all (globally) added filters from the #' submitted \code{EnsDb} object. #' #' @noRd .dropFilter <- function(x) { dropProperty(x, "FILTER") } #' @description \code{.activeFilter} lists the globally set and active filter(s) #' of an \code{EnsDb} object. #' #' @noRd .activeFilter <- function(x) { getProperty(x, "FILTER") } #' @aliases filter #' #' @description \code{filter} filters an \code{EnsDb} object. \code{filter} is #' an alias for the \code{addFilter} function. #' #' @rdname global-filters filter <- function(x, filter = AnnotationFilterList()) { if (is(x, "EnsDb")) addFilter(x, filter) else stop("ensembldb::filter requires an 'EnsDb' object as input. To call ", "the filter function from the stats or dplyr package use ", "stats::filter and dplyr::filter instead.") } ensembldb/R/functions-Filter.R0000644000175400017540000003217713175714743017340 0ustar00biocbuildbiocbuild## Some utility functions for Filters. ## Vector to map AnnotationFilter fields to actual database columns. ## Format: field name = database column name .ENSDB_FIELDS <- c( ## gene entrez = "entrezid", gene_biotype = "gene_biotype", gene_id = "gene_id", genename = "gene_name", symbol = "gene_name", seq_name = "seq_name", seq_strand = "seq_strand", gene_start = "gene_seq_start", gene_end = "gene_seq_end", description = "description", ## tx tx_id = "tx_id", tx_biotype = "tx_biotype", tx_name = "tx_id", tx_start = "tx_seq_start", tx_end = "tx_seq_end", tx_support_level = "tx_support_level", ## exon exon_id = "exon_id", exon_rank = "exon_idx", exon_start = "exon_seq_start", exon_end = "exon_seq_end", ## protein protein_id = "protein_id", uniprot = "uniprot_id", uniprot_db = "uniprot_db", uniprot_mapping_type = "uniprot_mapping_type", prot_dom_id = "protein_domain_id" ) ## .supportedFilters <- function(x) { ## flts <- c( ## "EntrezFilter", "GeneBiotypeFilter", "GeneIdFilter", "GenenameFilter", ## "SymbolFilter", "SeqNameFilter", "SeqStrandFilter", "GeneStartFilter", ## "GeneEndFilter", "TxIdFilter", "TxBiotypeFilter", "TxNameFilter", ## "TxStartFilter", "TxEndFilter", "ExonIdFilter", "ExonRankFilter", ## "ExonStartFilter", "ExonEndFilter", "GRangesFilter" ## ) ## if (hasProteinData(x)) ## flts <- c(flts, "ProteinIdFilter", "UniprotFilter", "UniprotDbFilter", ## "UniprotMappingTypeFilter", "ProtDomIdFilter") ## if (any(listColumns(x) == "tx_support_level")) ## flts <- c(flts, "TxSupportLevelFilter") ## return(sort(flts)) ## } .supportedFilters <- function(x) { flds <- .filterFields(x) flts <- c(.fieldToClass(flds), "GRangesFilter") flds <- c(flds, NA) idx <- order(flts) data.frame(filter = flts[idx], field = flds[idx], stringsAsFactors = FALSE) } .filterFields <- function(x) { flds <- c("entrez", "gene_biotype", "gene_id", "genename", "symbol", "seq_name", "seq_strand", "gene_start", "gene_end", "tx_id", "tx_biotype", "tx_name", "tx_start", "tx_end", "exon_id", "exon_rank", "exon_start", "exon_end") if (hasProteinData(x)) flds <- c(flds, "protein_id", "uniprot", "uniprot_db", "uniprot_mapping_type", "prot_dom_id") if (any(listColumns(x) == "tx_support_level")) flds <- c(flds, "tx_support_level") sort(flds) } .fieldToClass <- function(field) { class <- gsub("_([[:alpha:]])", "\\U\\1", field, perl=TRUE) class <- sub("^([[:alpha:]])", "\\U\\1", class, perl=TRUE) paste0(class, if (length(class)) "Filter" else character(0)) } #' Utility function to map from the default AnnotationFilters fields to the #' database columns used in ensembldb. #' #' @param x The field name to be \emph{translated}. #' @return The column name in the EnsDb database. #' @noRd .fieldInEnsDb <- function(x) { if (length(x) == 0 || missing(x)) stop("Error in .fieldInEnsDb: got empty input argument!") if (is.na(.ENSDB_FIELDS[x])) stop("Unable to map field '", x, "'!") else .ENSDB_FIELDS[x] } #' Utility function to map the condition of an AnnotationFilter to the SQL #' condition to be used in the EnsDb database. #' #' @param x An \code{AnnotationFilter}. #' #' @return A character representing the condition for the SQL call. #' @noRd .conditionForEnsDb <- function(x) { cond <- condition(x) if (length(unique(value(x))) > 1) { if (cond == "==") cond <- "in" if (cond == "!=") cond <- "not in" } if (cond == "==") cond <- "=" if (cond %in% c("startsWith", "endsWith", "contains")) cond <- "like" cond } #' Single quote character values, paste multiple values and enclose in quotes. #' #' @param x An \code{AnnotationFilter} object. #' @noRd .valueForEnsDb <- function(x) { vals <- unique(value(x)) if (is(x, "CharacterFilter")) { vals <- sQuote(gsub(unique(vals), pattern = "'", replacement = "''")) } if (length(vals) > 1) vals <- paste0("(", paste0(vals, collapse = ","), ")") ## Process the like/startsWith/endsWith if (condition(x) == "startsWith") vals <- paste0("'", unique(x@value), "%'") if (condition(x) == "endsWith") vals <- paste0("'%", unique(x@value), "'") if (condition(x) == "contains") vals <- paste0("'%", unique(x@value), "%'") vals } #' That's to build the standard query from an AnnotationFilter for EnsDb. #' #' @param x An \code{AnnotationFilter}. #' @noRd .queryForEnsDb <- function(x) { paste(.fieldInEnsDb(field(x)), .conditionForEnsDb(x), .valueForEnsDb(x)) } #' This is a slightly more sophisticated function that does also prefix the #' columns. #' @noRd .queryForEnsDbWithTables <- function(x, db, tables = character()) { clmn <- .fieldInEnsDb(field(x)) if (!missing(db)) { if (length(tables) == 0) tables <- names(listTables(db)) clmn <- unlist(prefixColumns(db, clmn, with.tables = tables)) } res <- paste(clmn, .conditionForEnsDb(x), .valueForEnsDb(x)) ## cat(" ", res, "\n") return(res) } #' Simple helper function to convert expressions to AnnotationFilter or #' AnnotationFilterList. #' #' @param x Can be an \code{AnnotationFilter}, an \code{AnnotationFilterList}, #' a \code{list} or a filter \code{expression}. This should NOT be empty! #' #' @return Returns an \code{AnnotationFilterList} with all filters. #' #' @noRd .processFilterParam <- function(x, db) { if (missing(db)) stop("Argument 'db' missing.") ## Check if x is a formula and eventually translate it. if (is(x, "formula")) res <- AnnotationFilter(x) else res <- x if (is(res, "AnnotationFilter")) res <- AnnotationFilterList(res) if (!is(res, "AnnotationFilterList")) { ## Did not get a filter expression, thus checking what we've got. if (is(res, "list")) { if (length(res)) { ## Check that all elements are AnnotationFilter objects! if (!all(unlist(lapply(res, function(z) { inherits(z, "AnnotationFilter") }), use.names = FALSE))) stop("One of more elements in 'filter' are not ", "'AnnotationFilter' objects!") res <- as(res, "AnnotationFilterList") res@logOp <- rep("&", (length(res) - 1)) } else { res <- AnnotationFilterList() } } else { stop("'filter' has to be an 'AnnotationFilter', a list of ", "'AnnotationFilter' object, an 'AnnotationFilterList' ", "or a valid filter expression!") } } supp_filters <- supportedFilters(db)$filter have_filters <- unique(.AnnotationFilterClassNames(res)) if (!all(have_filters %in% supp_filters)) stop("AnnotationFilter classes: ", paste(have_filters[!(have_filters %in% supp_filters)]), " are not supported by EnsDb databases.") res } ############################################################ ## setFeatureInGRangesFilter ## ## Simple helper function to set the @feature in GRangesFilter ## depending on the calling method. setFeatureInGRangesFilter <- function(x, feature){ for (i in seq(along.with = x)){ if (is(x[[i]], "GRangesFilter")) x[[i]]@feature <- feature if (is(x[[i]], "AnnotationFilterList")) x[[i]] <- setFeatureInGRangesFilter(x[[i]], feature = feature) } x } ############################################################ ## isProteinFilter ##' evaluates whether the filter is a protein annotation related filter. ##' @param x The object that should be evaluated. Can be an AnnotationFilter or ##' an AnnotationFilterList. ##' @return Returns TRUE if 'x' is a filter for protein annotation tables and ##' FALSE otherwise. ##' @noRd isProteinFilter <- function(x) { if (is(x, "AnnotationFilterList")) return(unlist(lapply(x, isProteinFilter))) else return(is(x, "ProteinIdFilter") | is(x, "UniprotFilter") | is(x, "ProtDomIdFilter") | is(x, "UniprotDbFilter") | is(x, "UniprotMappingTypeFilter")) } ## ############################################################ ## ## checkFilter: ## ## ## ## checks the filter argument and ensures that a list of Filter ## ## object is returned ## checkFilter <- function(x){ ## if(is(x, "list")){ ## if(length(x) == 0) ## return(x) ## ## check if all elements are Filter classes. ## if(!all(unlist(lapply(x, function(z){ ## return((is(z, "AnnotationFilter") | is(z, "GRangesFilter"))) ## }), use.names = FALSE))) ## stop("One of more elements in 'filter' are not filter objects!") ## }else{ ## if(is(x, "AnnotationFilter") | is(x, "GRangesFilter")){ ## x <- list(x) ## }else{ ## stop("'filter' has to be a filter object or a list of", ## " filter objects!") ## } ## } ## return(x) ## } #' build the \emph{where} query for a \code{GRangedFilter}. Supported conditions #' are: \code{"start"}, \code{"end"}, \code{"equal"}, \code{"within"}, #' \code{"any"}. #' #' @param grf \code{GRangesFilter}. #' #' @param columns named character vectors with the column names for start, end, #' strand and seq_name. #' #' @param db An optional \code{EnsDb} instance. Used to \emph{translate} #' seqnames depending on the specified seqlevels style. #' #' @return A character with the corresponding \emph{where} query. #' @noRd buildWhereForGRanges <- function(grf, columns, db = NULL){ condition <- condition(grf) if (!(condition %in% c("start", "end", "within", "equal", "any"))) stop("'condition' ", condition, " not supported. Condition (type) can ", "be one of 'any', 'start', 'end', 'equal', 'within'.") if( is.null(names(columns))) stop("The vector with the required column names for the", " GRangesFilter query has to have names!") if (!all(c("start", "end", "seqname", "strand") %in% names(columns))) stop("'columns' has to be a named vector with names being ", "'start', 'end', 'seqname', 'strand'!") ## Build the query to fetch all features that are located within the range quers <- sapply(value(grf), function(z) { if (!is.null(db)) { seqn <- formatSeqnamesForQuery(db, as.character(seqnames(z))) } else { seqn <- as.character(seqnames(z)) } ## start: start, seqname and strand have to match. if (condition == "start") { query <- paste0(columns["start"], "=", start(z), " and ", columns["seqname"], "='", seqn, "'") } ## end: end, seqname and strand have to match. if (condition == "end") { query <- paste0(columns["end"], "=", end(z), " and ", columns["seqname"], "='", seqn, "'") } ## equal: start, end, seqname and strand have to match. if (condition == "equal") { query <- paste0(columns["start"], "=", start(z), " and ", columns["end"], "=", end(z), " and ", columns["seqname"], "='", seqn, "'") } ## within: start has to be >= start, end <= end, seqname and strand ## have to match. if (condition == "within") { query <- paste0(columns["start"], ">=", start(z), " and ", columns["end"], "<=", end(z), " and ", columns["seqname"], "='", seqn, "'") } ## any: essentially the overlapping. if (condition == "any") { query <- paste0(columns["start"], "<=", end(z), " and ", columns["end"], ">=", start(z), " and ", columns["seqname"], "='", seqn, "'") } ## Include the strand, if it's not "*" if(as.character(strand(z)) != "*"){ query <- paste0(query, " and ", columns["strand"], " = ", strand2num(as.character(strand(z)))) } return(query) }) if(length(quers) > 1) quers <- paste0("(", quers, ")") ## Collapse now the queries. query <- paste0(quers, collapse=" or ") paste0("(", query, ")") } #' @description Helper to extract all AnnotationFilter class names from an #' AnnotationFilterList (recursively!) #' #' @param x The \code{AnnotationFilterList}. #' #' @return A \code{character} with the names of the classes. #' @noRd .AnnotationFilterClassNames <- function(x) { classes <- lapply(x, function(z) { if (is(z, "AnnotationFilterList")) return(.AnnotationFilterClassNames(z)) class(z) }) unlist(classes, use.names = FALSE) } #' @description Test if any of the filter(s) is an SymbolFilter. #' #' @noRd .anyIs <- function(x, what = "SymbolFilter") { if (is(x, "AnnotationFilter")) { is(x, what) } else { unlist(lapply(x, .anyIs, what = what)) } } ensembldb/R/functions-create-EnsDb.R0000644000175400017540000022004713241131543020323 0ustar00biocbuildbiocbuild############################################################ ## Functions related to the creation of EnsDb databases. ## Separate helper function for abbreviating the genus and species name strings ## this simply makes the first character uppercase .organismName <- function(x){ substring(x, 1, 1) <- toupper(substring(x, 1, 1)) return(x) } .abbrevOrganismName <- function(organism){ spc <- unlist(strsplit(organism, "_")) ## this assumes a binomial nomenclature has been maintained. return(paste0(substr(spc[[1]], 1, 1), spc[[2]])) } ## x has to be the connection to the database. .makePackageName <- function(x){ species <- .getMetaDataValue(x, "Organism") ensembl_version <- .getMetaDataValue(x, "ensembl_version") pkgName <- paste0("EnsDb.",.abbrevOrganismName(.organismName(species)), ".v", ensembl_version) return(pkgName) } .makeObjectName <- function(pkgName){ strs <- unlist(strsplit(pkgName, "\\.")) paste(c(strs[2:length(strs)],strs[1]), collapse="_") } ## retrieve Ensembl data ## save all files to local folder. ## returns the path where files have been saved to. fetchTablesFromEnsembl <- function(version, ensemblapi, user="anonymous", host="ensembldb.ensembl.org", pass="", port=5306, species="human"){ if(missing(version)) stop("The version of the Ensembl database has to be provided!") ## setting the stage for perl: fn <- system.file("perl", "get_gene_transcript_exon_tables.pl", package="ensembldb") ## parameters: s, U, H, P, e ## replacing white spaces with _ species <- gsub(species, pattern=" ", replacement="_") cmd <- paste0("perl ", fn, " -s ", species," -e ", version, " -U ", user, " -H ", host, " -p ", port, " -P ", pass) if(!missing(ensemblapi)){ Sys.setenv(ENS=ensemblapi) } system(cmd) if(!missing(ensemblapi)){ Sys.unsetenv("ENS") } ## we should now have the files: in_files <- c("ens_gene.txt", "ens_tx.txt", "ens_exon.txt", "ens_tx2exon.txt", "ens_chromosome.txt", "ens_metadata.txt", "ens_counts.txt") ## check if we have all files... all_files <- dir(pattern="txt") if(sum(in_files %in% all_files)!=length(in_files)) stop("Something went wrong! I'm missing some of the txt files the perl script should have generated.") } #### ## ## create a SQLite database containing the information defined in the txt files. makeEnsemblSQLiteFromTables <- function(path=".", dbname){ ## check if we have all files... in_files <- c("ens_gene.txt", "ens_tx.txt", "ens_exon.txt", "ens_tx2exon.txt", "ens_chromosome.txt", "ens_metadata.txt") ## check if we have all files... all_files <- dir(path, pattern="txt") if(sum(in_files %in% all_files)!=length(in_files)) stop("Something went wrong! I'm missing some of the txt files the", " perl script should have generated.") haveCounts <- file.exists(paste0(path, .Platform$file.sep, "ens_counts.txt")) ## read the counts - use these numbers to validate that we did read ## everything if (haveCounts) counts <- read.table(paste0(path, .Platform$file.sep, "ens_counts.txt"), sep = "\t", as.is = TRUE, header = TRUE) ## read information info <- read.table(paste0(path, .Platform$file.sep, "ens_metadata.txt"), sep="\t", as.is=TRUE, header=TRUE) species <- .organismName(info[ info$name=="Organism", "value" ]) ##substring(species, 1, 1) <- toupper(substring(species, 1, 1)) if(missing(dbname)){ dbname <- paste0("EnsDb.",substring(species, 1, 1), unlist(strsplit(species, split="_"))[ 2 ], ".v", info[ info$name=="ensembl_version", "value" ], ".sqlite") } con <- dbConnect(dbDriver("SQLite"), dbname=dbname) ## write information table dbWriteTable(con, name="metadata", info, row.names=FALSE) ## process chromosome message("Processing 'chromosome' table ... ", appendLF = FALSE) tmp <- read.table(paste0(path, .Platform$file.sep ,"ens_chromosome.txt"), sep="\t", as.is=TRUE, header=TRUE) tmp[, "seq_name"] <- as.character(tmp[, "seq_name"]) dbWriteTable(con, name="chromosome", tmp, row.names=FALSE) rm(tmp) message("OK") message("Processing 'gene' table ... ", appendLF = FALSE) ## process genes: some gene names might have fancy names... tmp <- read.table(paste0(path, .Platform$file.sep, "ens_gene.txt"), sep="\t", as.is=TRUE, header=TRUE, quote="", comment.char="" ) OK <- .checkIntegerCols(tmp) ## Check that we have the expected number of rows: if (haveCounts) if (nrow(tmp) != counts[1, "gene"]) stop("The data read from the 'ens_gene.txt' file does not match ", "the expected number of entries.") dbWriteTable(con, name="gene", tmp, row.names=FALSE) ## Check that we can read the correct number of entries if (haveCounts) { res <- dbGetQuery(con, "select count(*) from gene;")[1, 1] if (res != counts[1, "gene"]) stop("The number of rows in the 'gene' database table does not ", "match the expected number.") } rm(tmp) message("OK") if (as.numeric(info[info$name == "DBSCHEMAVERSION", "value"]) > 1) { message("Processing 'entrezgene' table ... ", appendLF = FALSE) ## process genes: some gene names might have fancy names... tmp <- read.table(paste0(path, .Platform$file.sep, "ens_entrezgene.txt"), sep="\t", as.is=TRUE, header=TRUE, quote="", comment.char="" ) dbWriteTable(con, name="entrezgene", tmp, row.names=FALSE) rm(tmp) message("OK") } message("Processing 'trancript' table ... ", appendLF = FALSE) ## process transcripts: tmp <- read.table(paste0(path, .Platform$file.sep, "ens_tx.txt"), sep="\t", as.is=TRUE, header=TRUE) ## Check that we have the expected number of rows: if (haveCounts) if (nrow(tmp) != counts[1, "tx"]) stop("The data read from the 'ens_tx.txt' file does not match the", " expected number of entries.") ## Fix the tx_cds_seq_start and tx_cds_seq_end columns: these should be integer! suppressWarnings( tmp[, "tx_cds_seq_start"] <- as.integer(tmp[, "tx_cds_seq_start"]) ) suppressWarnings( tmp[, "tx_cds_seq_end"] <- as.integer(tmp[, "tx_cds_seq_end"]) ) OK <- .checkIntegerCols(tmp) ## Fix the tx_support_level column to ensure it contains only INTEGER! if (any(colnames(tmp) == "tx_support_level")) { tsl <- strsplit(tmp$tx_support_level, split = " ", fixed = TRUE) tsl <- lapply(tsl, function(z) { if (length(z) > 1) z <- z[1] if (is.na(z)) return(NA_integer_) if (z == "NA" | z == "NULL") z <- NA as.integer(z) }) tmp$tx_support_level <- unlist(tsl, use.names = FALSE) } dbWriteTable(con, name="tx", tmp, row.names=FALSE) rm(tmp) message("OK") ## process exons: message("Processing 'exon' table ... ", appendLF = FALSE) tmp <- read.table(paste0(path, .Platform$file.sep, "ens_exon.txt"), sep = "\t", as.is = TRUE, header = TRUE) if (haveCounts) if (nrow(tmp) != counts[1, "exon"]) stop("The data read from the 'ens_exon.txt' file does not match ", "the expected number of entries.") OK <- .checkIntegerCols(tmp) dbWriteTable(con, name="exon", tmp, row.names=FALSE) rm(tmp) message("OK") message("Processing 'tx2exon' table ... ", appendLF = FALSE) tmp <- read.table(paste0(path, .Platform$file.sep, "ens_tx2exon.txt"), sep = "\t", as.is = TRUE, header = TRUE) OK <- .checkIntegerCols(tmp) dbWriteTable(con, name="tx2exon", tmp, row.names = FALSE) rm(tmp) message("OK") ## process proteins; if available. prot_file <- paste0(path, .Platform$file.sep, "ens_protein.txt") if (file.exists(prot_file)) { message("Processing 'protein' table ... ", appendLF = FALSE) tmp <- read.table(prot_file, sep = "\t", as.is = TRUE, header = TRUE) if (haveCounts) if (nrow(tmp) != counts[1, "protein"]) stop("The data read from the 'ens_protein.txt' file does not ", "match the expected number of entries.") OK <- .checkIntegerCols(tmp) dbWriteTable(con, name = "protein", tmp, row.names = FALSE) message("OK") message("Processing 'uniprot' table ... ", appendLF = FALSE) tmp <- read.table(paste0(path, .Platform$file.sep, "ens_uniprot.txt"), sep = "\t", as.is = TRUE, header = TRUE) OK <- .checkIntegerCols(tmp) dbWriteTable(con, name = "uniprot", tmp, row.names = FALSE) message("OK") message("Processing 'protein_domain' table ... ", appendLF = FALSE) tmp <- read.table(paste0(path, .Platform$file.sep, "ens_protein_domain.txt"), sep = "\t", as.is = TRUE, header = TRUE) OK <- .checkIntegerCols(tmp) dbWriteTable(con, name = "protein_domain", tmp, row.names = FALSE) message("OK") } ## Create indices message("Creating indices ... ", appendLF = FALSE) .createEnsDbIndices(con, proteins = file.exists(prot_file)) message("OK") dbDisconnect(con) ## Check if the data could be loaded. message("Checking validity of the database ... ", appendLF = FALSE) msg <- validObject(EnsDb(dbname)) if (!is.logical(msg)) stop(msg) message("OK") ## done. return(dbname) } ############################################################ ## Simply checking that some columns are integer .checkIntegerCols <- function(x, columns = c("gene_seq_start", "gene_seq_end", "tx_seq_start", "tx_seq_start", "exon_seq_start", "exon_seq_end", "exon_idx", "tx_cds_seq_start", "tx_cds_seq_end", "prot_dom_start", "prot_dom_end")) { cols <- columns[columns %in% colnames(x)] if(length(cols) > 0) { sapply(cols, function(z) { if(!is.integer(x[, z])) stop("Column '", z,"' is not of type integer!") }) } return(TRUE) } #### ## the function that creates the annotation package. ## ensdb should be a connection to an SQLite database, or a character string... makeEnsembldbPackage <- function(ensdb, version, maintainer, author, destDir=".", license="Artistic-2.0"){ if(class(ensdb)!="character") stop("ensdb has to be the name of the SQLite database!") ensdbfile <- ensdb ensdb <- EnsDb(x=ensdbfile) con <- dbconn(ensdb) pkgName <- .makePackageName(con) ensembl_version <- .getMetaDataValue(con, "ensembl_version") ## there should only be one template template_path <- system.file("pkg-template",package="ensembldb") ## We need to define some symbols in order to have the ## template filled out correctly. symvals <- list( PKGTITLE=paste("Ensembl based annotation package"), PKGDESCRIPTION="Exposes an annotation databases generated from Ensembl.", PKGVERSION=version, AUTHOR=author, MAINTAINER=maintainer, LIC=license, ORGANISM=.organismName(.getMetaDataValue(con ,'Organism')), SPECIES=.organismName(.getMetaDataValue(con,'Organism')), PROVIDER="Ensembl", PROVIDERVERSION=as.character(ensembl_version), RELEASEDATE= .getMetaDataValue(con ,'Creation time'), SOURCEURL= .getMetaDataValue(con ,'ensembl_host'), ORGANISMBIOCVIEW=gsub(" ","_", .organismName(.getMetaDataValue(con ,'Organism'))), TXDBOBJNAME=pkgName ## .makeObjectName(pkgName) ) ## Should never happen if (any(duplicated(names(symvals)))) { str(symvals) stop("'symvals' contains duplicated symbols") } createPackage(pkgname=pkgName, destinationDir=destDir, originDir=template_path, symbolValues=symvals) ## then copy the contents of the database into the extdata dir sqlfilename <- unlist(strsplit(ensdbfile, split=.Platform$file.sep)) sqlfilename <- sqlfilename[ length(sqlfilename) ] dir.create(paste(c(destDir, pkgName, "inst", "extdata"), collapse=.Platform$file.sep), showWarnings=FALSE, recursive=TRUE) db_path <- file.path(destDir, pkgName, "inst", "extdata", paste(pkgName,"sqlite",sep=".")) file.copy(ensdbfile, to=db_path) } #### ## function to create a EnsDb object (or rather the SQLite database) from ## a Ensembl GTF file. ## Limitation: ## + There is no way to get the Entrezgene ID from this file. ## + Assuming that the element 2 in a row for a transcript represents its ## biotype, since there is no explicit key transcript_biotype in element 9. ## + The CDS features in the GTF are somewhat problematic, while we're used to ## get just the coding start and end for a transcript from the Ensembl perl ## API, here we get the coding start and end for each exon. ensDbFromGtf <- function(gtf, outfile, path, organism, genomeVersion, version, ...){ options(useFancyQuotes = FALSE) message("Importing GTF file ... ", appendLF = FALSE) ## wanted.features <- c("gene", "transcript", "exon", "CDS") wanted.features <- c("exon") ## GTF <- import(con=gtf, format="gtf", feature.type=wanted.features) GTF <- import(con = gtf, format = "gtf") message("OK") ## check what we've got... ## all wanted features? if (any(!(wanted.features %in% levels(GTF$type)))) { stop(paste0("One or more required types are not in the gtf file. Need ", paste(wanted.features, collapse=","), " but got only ", paste(wanted.features[wanted.features %in% levels(GTF$type)], collapse=","), ".")) } ## transcript biotype? if (any(colnames(mcols(GTF)) == "transcript_biotype")) { txBiotypeCol <- "transcript_biotype" } else { ## that's a little weird, but it seems that certain gtf files from Ensembl ## provide the transcript biotype in the element "source" txBiotypeCol <- "source" } ## processing the metadata: ## first read the header... tmp <- readLines(gtf, n = 10) tmp <- tmp[grep(tmp, pattern = "^#")] haveHeader <- FALSE if (length(tmp) > 0) { ##message("GTF file has a header.") tmp <- gsub(tmp, pattern = "^#", replacement = "") tmp <- gsub(tmp, pattern = "^!", replacement = "") ## Splitting by " " but be careful, if there are more than one " "! hdr <- strsplit(tmp, split = " ", fixed = TRUE) hdr <- lapply(hdr, function(z) { if (length(z) > 2) z[2] <- paste(z[2:length(z)], collapse = " ") z[1:2] }) Header <- do.call(rbind, hdr) colnames(Header) <- c("name", "value") haveHeader <- TRUE } ## Check parameters Parms <- .checkExtractVersions(gtf, organism, genomeVersion, version) ensemblVersion <- Parms["version"] organism <- Parms["organism"] genomeVersion <- Parms["genomeVersion"] ## Fix for issue #75: validate versions I got with versions extracted from ## the GTF header but don't stop if something is wrong, just show a warning if (haveHeader) { header.version <- Header[Header[, "name"] == "genome-version", "value"] if (length(header.version)) { if (genomeVersion != header.version) warning("Genome version extracted from the gtf file name ('", genomeVersion, "') and genome version specified in the", " gtf file ('", header.version, "') do not match. ", "Ensure you pass the correct genome version along ", "with parameter 'genomeVersion'") } } GTF <- fixCDStypeInEnsemblGTF(GTF) ## here on -> call ensDbFromGRanges. dbname <- ensDbFromGRanges(GTF, outfile = outfile, path = path, organism = organism, genomeVersion = genomeVersion, version = ensemblVersion, ...) gtfFilename <- unlist(strsplit(gtf, split=.Platform$file.sep)) gtfFilename <- gtfFilename[length(gtfFilename)] ## updating the Metadata information... lite <- dbDriver("SQLite") con <- dbConnect(lite, dbname = dbname ) bla <- dbExecute(con, paste0("update metadata set value='", gtfFilename, "' where name='source_file';")) dbDisconnect(con) return(dbname) } ####============================================================ ## fixCDStypeInEnsemblGTF ## ## Takes an GRanges object as input and returns a GRanges object in ## which the feature type stop_codon and start_codon is replaced by ## feature type CDS. This is to fix a potential problem (bug?) in ## GTF files from Ensembl, in which the stop_codon or start_codon for ## some transcripts is outside of the CDS. ####------------------------------------------------------------ fixCDStypeInEnsemblGTF <- function(x){ if(any(unique(x$type) %in% c("start_codon", "stop_codon"))){ x$type[x$type %in% c("start_codon", "stop_codon")] <- "CDS" } return(x) } ####============================================================ ## ensDbFromAH ## ## Retrieve a GTF file from AnnotationHub and build a EnsDb object from that. ## ####------------------------------------------------------------ ensDbFromAH <- function(ah, outfile, path, organism, genomeVersion, version){ options(useFancyQuotes=FALSE) ## Input checking... if(!is(ah, "AnnotationHub")) stop("Argument 'ah' has to be a (single) AnnotationHub object.") if(length(ah) != 1) stop("Argument 'ah' has to be a single AnnotationHub resource!") if(tolower(ah$dataprovider) != "ensembl") stop("Can only process GTF files provided by Ensembl!") if(tolower(ah$sourcetype) != "gtf") stop("Resource is not a GTF file!") ## Check parameters Parms <- .checkExtractVersions(ah$title, organism, genomeVersion, version) ensFromAH <- Parms["version"] orgFromAH <- Parms["organism"] genFromAH <- Parms["genomeVersion"] gtfFilename <- ah$title message("Fetching data ... ", appendLF=FALSE) suppressMessages( gff <- ah[[1]] ) message("OK") message(" -------------") message("Proceeding to create the database.") gff <- fixCDStypeInEnsemblGTF(gff) ## Proceed. dbname <- ensDbFromGRanges(gff, outfile=outfile, path=path, organism=orgFromAH, genomeVersion=genFromAH, version=ensFromAH) ## updating the Metadata information... lite <- dbDriver("SQLite") con <- dbConnect(lite, dbname = dbname ) bla <- dbExecute(con, paste0("update metadata set value='", gtfFilename, "' where name='source_file';")) dbDisconnect(con) return(dbname) } .checkExtractVersions <- function(filename, organism, genomeVersion, version){ if(isEnsemblFileName(filename)){ ensFromFile <- ensemblVersionFromGtfFileName(filename) orgFromFile <- organismFromGtfFileName(filename) genFromFile <- genomeVersionFromGtfFileName(filename) }else{ ensFromFile <- NA orgFromFile <- NA genFromFile <- NA if(missing(organism) | missing(genomeVersion) | missing(version)) stop("The file name does not match the expected naming scheme", " of Ensembl files hence I cannot extract any information", " from it! Parameters 'organism', 'genomeVersion' and", " 'version' are thus required!") } ## Do some more testing with versions provided from the user. if(!missing(organism)){ if(!is.na(orgFromFile)){ if(organism != orgFromFile){ warning("User specified organism (", organism, ") is different to the one extracted", " from the file name (", orgFromFile, ")! Using the one defined by the user.") } } orgFromFile <- organism } if(!missing(genomeVersion)){ if(!is.na(genFromFile)){ if(genomeVersion != genFromFile){ warning("User specified genome version (", genomeVersion, ") is different to the one extracted", " from the file name (", genFromFile, ")! Using the one defined by the user.") } } genFromFile <- genomeVersion } if(!missing(version)){ if(!is.na(ensFromFile)){ if(version != ensFromFile){ warning("User specified Ensembl version (", version, ") is different to the one extracted", " from the file name (", ensFromFile, ")! Using the one defined by the user.") } } ensFromFile <- version } res <- c(orgFromFile, genFromFile, ensFromFile) names(res) <- c("organism", "genomeVersion", "version") return(res) } ####============================================================ ## ## ensDbFromGff ## ####------------------------------------------------------------ ensDbFromGff <- function(gff, outfile, path, organism, genomeVersion, version, ...){ options(useFancyQuotes=FALSE) ## Check parameters Parms <- .checkExtractVersions(gff, organism, genomeVersion, version) ensFromFile <- Parms["version"] orgFromFile <- Parms["organism"] genFromFile <- Parms["genomeVersion"] ## Reading some info from the header. tmp <- readLines(gff, n=500) if(length(grep(tmp[1], pattern="##gff-version")) == 0) stop("File ", gff, " does not seem to be a correct GFF file! ", "The ##gff-version line is missing!") gffVersion <- unlist(strsplit(tmp[1], split="[ ]+"))[2] if(gffVersion != "3") stop("This function supports only GFF version 3 files!") tmp <- tmp[grep(tmp, pattern="^#!")] if(length(tmp) > 0){ ## Check if I can extract the genome-version idx <- grep(tmp, pattern = "^#!genome-version") if (length(idx) > 0) { genFromHeader <- sub(tmp[idx], pattern = "^#!genome-version", replacement = "") genFromHeader <- gsub(genFromHeader, pattern = " ", replacement = "", fixed = TRUE) if (genFromHeader != genFromFile) { warning("Genome version extracted from file name (", genFromFile, ") does not match genome version", " defined within the gff file (", genFromHeader, "). Will use the version defined within the gff.") } } } message("Importing GFF ... ", appendLF=FALSE) suppressWarnings( theGff <- import(gff, format=paste0("gff", gffVersion)) ) message("OK") ## Works with Ensembl 83; eventually not for updated Ensembl gff files! ## what seems a little strange: exons have an ID of NA. ## Ensembl specific fields: gene_id, transcript_id, exon_id, rank, biotype. ## GFF3 fields: type, ID, Name, Parent ## check columns and subset... gffcols <- c("type", "ID", "Name", "Parent") if(!all(gffcols %in% colnames(mcols(theGff)))) stop("Required columns/fields ", paste(gffcols[!(gffcols %in% colnames(mcols(theGff)))], collapse=";"), " not present in the GFF file!") enscols <- c("gene_id", "transcript_id", "exon_id", "rank", "biotype") if(!all(enscols %in% colnames(mcols(theGff)))) stop("Required columns/fields ", paste(enscols[!(enscols %in% colnames(mcols(theGff)))], collapse=";"), " not present in the GFF file!") ## Subsetting to eventually speed up further processing. theGff <- theGff[, c(gffcols, enscols)] ## Renaming and fixing some columns: CN <- colnames(mcols(theGff)) colnames(mcols(theGff))[CN == "Name"] <- "gene_name" colnames(mcols(theGff))[CN == "biotype"] <- "gene_biotype" colnames(mcols(theGff))[CN == "rank"] <- "exon_number" theGff$transcript_biotype <- theGff$gene_biotype ## Processing that stuff... ## Replace the ID format type:ID. ids <- strsplit(theGff$ID, split=":") message("Fixing IDs ... ", appendLF=FALSE) ## For those that have length > 1 use the second element. theGff$ID <- unlist(lapply(ids, function(z){ if(length(z) > 1) return(z[2]) return(z) })) message("OK") ## Process genes... message("Processing genes ... ", appendLF=FALSE) ## Bring the GFF into the correct format for EnsDb/ensDbFromGRanges. idx <- which(!is.na(theGff$gene_id)) theGff$type[idx] <- "gene" message("OK") ## ## Can not use the lengths of chromosomes provided in the chromosome features!!! ## ## For whatever reasons chromosome Y length is incorrect!!! ## message("Processing seqinfo...", appendLF=FALSE) ## SI <- seqinfo(theGff) ## tmp <- theGff[theGff$ID %in% seqlevels(SI)] ## ## Check if we've got length for all. ## message("OK") ## Process transcripts... message("Processing transcripts ... ", appendLF=FALSE) idx <- which(!is.na(theGff$transcript_id)) ## Check if I've got multiple parents... parentGenes <- theGff$Parent[idx] if(any(lengths(parentGenes) > 1)) stop("Transcripts with multiple parents in GFF element 'Parent'", " not (yet) supported!") theGff$type[idx] <- "transcript" ## Setting the gene_id for these guys... theGff$gene_id[idx] <- unlist(sub(parentGenes, pattern="gene:", replacement="", fixed=TRUE)) ## The CDS: idx <- which(theGff$type == "CDS") parentTx <- theGff$Parent[idx] if(any(lengths(parentTx) > 1)) stop("CDS with multiple parent transcripts in GFF element 'Parent'", " not (yet) supported!") theGff$transcript_id[idx] <- unlist(sub(parentTx, pattern="transcript:", replacement="", fixed=TRUE)) message("OK") message("Processing exons ... ", appendLF=FALSE) idx <- which(!is.na(theGff$exon_id)) parentTx <- theGff$Parent[idx] if(any(lengths(parentTx) > 1)) stop("Exons with multiple parent transcripts in GFF element 'Parent'", " not (yet) supported!") theGff$transcript_id[idx] <- unlist(sub(parentTx, pattern="transcript:", replacement="", fixed=TRUE)) message("OK") theGff <- theGff[theGff$type %in% c("gene", "transcript", "exon", "CDS")] theGff <- keepSeqlevels(theGff, as.character(unique(seqnames(theGff)))) ## Now we can proceed and pass that to the next function! message(" -------------") message("Proceeding to create the database.") ## Proceed. dbname <- ensDbFromGRanges(theGff, outfile = outfile, path = path, organism = orgFromFile, genomeVersion = genFromFile, version = ensFromFile, ...) gtfFilename <- unlist(strsplit(gff, split=.Platform$file.sep)) gtfFilename <- gtfFilename[length(gtfFilename)] ## updating the Metadata information... lite <- dbDriver("SQLite") con <- dbConnect(lite, dbname = dbname ) bla <- dbExecute(con, paste0("update metadata set value='", gtfFilename, "' where name='source_file';")) dbDisconnect(con) return(dbname) } #### build a EnsDb SQLite database from the GRanges. ## we can however not get all of the information from the GRanges (yet), for example, ## the seqinfo might not be available in all GRanges objects. Also, there is no way ## we can guess the organism or the Ensembl version from the GRanges, thus, this ## information has to be provided by the user. ## x: the GRanges object or file name. If file name, the function tries to guess ## the organism, genome build and ensembl version from the file name, if not ## provided. ## ensDbFromGRanges <- function(x, outfile, path, organism, genomeVersion, version, ...){ if(!is(x, "GRanges")) stop("This method can only be called on GRanges objects!") ## check for missing parameters if(missing(organism)){ stop("The organism has to be specified (e.g. using", " organism=\"Homo_sapiens\")") } if(missing(version)){ stop("The Ensembl version has to be specified!") } ## checking the seqinfo in the GRanges object... Seqinfo <- seqinfo(x) fetchSeqinfo <- FALSE ## check if we've got some information... if(any(is.na(seqlengths(Seqinfo)))){ fetchSeqinfo <- TRUE ## means we have to fetch the seqinfo ourselfs... } if(missing(genomeVersion)){ ## is there a seqinfo in x that I could use??? if(!fetchSeqinfo){ genomeVersion <- unique(genome(Seqinfo)) if(is.na(genomeVersion) | length(genomeVersion) > 1){ stop(paste0("The genome version has to be specified as", " it can not be extracted from the seqinfo!")) } }else{ stop("The genome version has to be specified!") } } if(missing(outfile)){ ## use the organism, genome version and ensembl version as the file name. outfile <- paste0(c(organism, genomeVersion, version, "sqlite"), collapse=".") if(missing(path)) path <- "." dbname <- paste0(path, .Platform$file.sep, outfile) }else{ if(!missing(path)) warning("outfile specified, thus I will discard the path argument.") dbname <- outfile } ## that's quite some hack ## transcript biotype? if(any(colnames(mcols(x))=="transcript_biotype")){ txBiotypeCol <- "transcript_biotype" }else{ ## that's a little weird, but it seems that certain gtf files from Ensembl ## provide the transcript biotype in the element "source" txBiotypeCol <- "source" } con <- dbConnect(dbDriver("SQLite"), dbname=dbname) on.exit(dbDisconnect(con)) ## ---------------------------- ## metadata table: message("Processing metadata ... ", appendLF=FALSE) Metadata <- buildMetadata(organism, version, host="unknown", sourceFile="GRanges object", genomeVersion=genomeVersion) dbWriteTable(con, name="metadata", Metadata, overwrite=TRUE, row.names=FALSE) message("OK") ## Check if we've got column "type" if(!any(colnames(mcols(x)) == "type")) stop("The GRanges object lacks the required column 'type', sorry.") gotTypes <- as.character(unique(x$type)) gotColumns <- colnames(mcols(x)) ## ---------------------------- ## ## process genes ## we're lacking NCBI Entrezids and also the coord system, but these are not ## required columns anyway... message("Processing genes ... ") ## want to have: gene_id, gene_name, entrezid, gene_biotype, gene_seq_start, ## gene_seq_end, seq_name, seq_strand, seq_coord_system. wouldBeNice <- c("gene_id", "gene_name", "entrezid", "gene_biotype") dontHave <- wouldBeNice[!(wouldBeNice %in% gotColumns)] haveGot <- wouldBeNice[wouldBeNice %in% gotColumns] ## Just really require the gene_id... reqCols <- c("gene_id") if(length(dontHave) > 0){ mess <- paste0(" I'm missing column(s): ", paste0(sQuote(dontHave), collapse=","), ".") warning(mess, " The corresponding database column(s) will be empty!") } message(" Attribute availability:", appendLF=TRUE) for(i in 1:length(wouldBeNice)){ message(" o ", wouldBeNice[i], " ... ", ifelse(any(gotColumns == wouldBeNice[i]), yes="OK", no="Nope")) } if(!any(reqCols %in% haveGot)) stop(paste0("One or more required fields are not defined in the", " submitted GRanges object! Need ", paste(sQuote(reqCols), collapse=","), " but got only ", paste(reqCols[reqCols %in% gotColumns], collapse=","), ".")) ## Now gets tricky; special case Ensembl < 75: we've got NO gene type. if(any(gotTypes == "gene")){ ## All is fine. genes <- as.data.frame(x[x$type == "gene", haveGot]) }else{ ## Well, have to split by gene_id and process... genes <- split(x[ , haveGot], x$gene_id) gnRanges <- unlist(range(genes)) gnMcol <- as.data.frame(unique(mcols(unlist(genes)))) genes <- as.data.frame(gnRanges) ## Adding mcols again. genes <- cbind(genes, gnMcol[match(rownames(genes), gnMcol$gene_id), ]) rm(gnRanges) rm(gnMcol) } colnames(genes) <- c("seq_name", "gene_seq_start", "gene_seq_end", "width", "seq_strand", haveGot) ## Add missing cols... if(length(dontHave) > 0){ cn <- colnames(genes) for(i in 1:length(dontHave)){ genes <- cbind(genes, rep(NA, nrow(genes))) } colnames(genes) <- c(cn, dontHave) } genes <- cbind(genes, seq_coord_system=rep(NA, nrow(genes))) ## transforming seq_strand from +/- to +1, -1. strand <- rep(0L, nrow(genes)) strand[as.character(genes$seq_strand) == "+"] <- 1L strand[as.character(genes$seq_strand) == "-"] <- -1L genes[ , "seq_strand"] <- strand ## rearranging data.frame... genes <- genes[ , c("gene_id", "gene_name", "entrezid", "gene_biotype", "gene_seq_start", "gene_seq_end", "seq_name", "seq_strand", "seq_coord_system")] OK <- .checkIntegerCols(genes) dbWriteTable(con, name="gene", genes, overwrite=TRUE, row.names=FALSE) ## Done. message("OK") ## ---------------------------- ## ## process transcripts message("Processing transcripts ... ", appendLF=TRUE) ## want to have: tx_id, tx_biotype, tx_seq_start, tx_seq_end, tx_cds_seq_start, ## tx_cds_seq_end, gene_id wouldBeNice <- c("transcript_id", "gene_id", txBiotypeCol) dontHave <- wouldBeNice[!(wouldBeNice %in% gotColumns)] if(length(dontHave) > 0){ mess <- paste0("I'm missing column(s): ", paste0(sQuote(dontHave), collapse=","), ".") warning(mess, " The corresponding database columns will be empty!") } haveGot <- wouldBeNice[wouldBeNice %in% gotColumns] message(" Attribute availability:", appendLF=TRUE) for(i in 1:length(wouldBeNice)){ message(" o ", wouldBeNice[i], " ... ", ifelse(any(gotColumns == wouldBeNice[i]), yes="OK", no="Nope")) } reqCols <- c("transcript_id", "gene_id") if(!any(reqCols %in% gotColumns)) stop(paste0("One or more required fields are not defined in", " the submitted GRanges object! Need ", paste(reqCols, collapse=","), " but got only ", paste(reqCols[reqCols %in% gotColumns], collapse=","), ".")) if(any(gotTypes == "transcript")){ tx <- as.data.frame(x[x$type == "transcript" , haveGot]) }else{ tx <- split(x[, haveGot], x$transcript_id) txRanges <- unlist(range(tx)) txMcol <- as.data.frame(unique(mcols(unlist(tx)))) tx <- as.data.frame(txRanges) tx <- cbind(tx, txMcol[match(rownames(tx), txMcol$transcript_id), ]) rm(txRanges) rm(txMcol) } ## Drop columns seqnames, width and strand tx <- tx[, -c(1, 4, 5)] ## Add empty columns, eventually if(length(dontHave) > 0){ cn <- colnames(tx) for(i in 1:length(dontHave)){ tx <- cbind(tx, rep(NA, nrow(tx))) } colnames(tx) <- c(cn, dontHave) } ## Add columns for UTR tx <- cbind(tx, tx_cds_seq_start=rep(NA, nrow(tx)), tx_cds_seq_end=rep(NA, nrow(tx))) ## Process CDS... if(any(gotTypes == "CDS")){ ## Only do that if we've got type == "CDS"! ## process the CDS features to get the cds start and end of the transcript. CDS <- as.data.frame(x[x$type == "CDS", "transcript_id"]) ## startByTx <- split(CDS$start, f=CDS$transcript_id) cdsStarts <- unlist(lapply(startByTx, function(z){return(min(z, na.rm=TRUE))})) endByTx <- split(CDS$end, f=CDS$transcript_id) cdsEnds <- unlist(lapply(endByTx, function(z){return(max(z, na.rm=TRUE))})) idx <- match(names(cdsStarts), tx$transcript_id) areNas <- is.na(idx) idx <- idx[!areNas] cdsStarts <- cdsStarts[!areNas] cdsEnds <- cdsEnds[!areNas] tx[idx, "tx_cds_seq_start"] <- cdsStarts tx[idx, "tx_cds_seq_end"] <- cdsEnds }else{ mess <- paste0(" I can't find type=='CDS'! The resulting database", " will lack CDS information!") message(mess, appendLF = TRUE) warning(mess) } colnames(tx) <- c("tx_seq_start", "tx_seq_end", "tx_id", "gene_id", "tx_biotype", "tx_cds_seq_start", "tx_cds_seq_end") ## rearranging data.frame: tx <- tx[ , c("tx_id", "tx_biotype", "tx_seq_start", "tx_seq_end", "tx_cds_seq_start", "tx_cds_seq_end", "gene_id")] ## write the table. OK <- .checkIntegerCols(tx) dbWriteTable(con, name="tx", tx, overwrite=TRUE, row.names=FALSE) rm(tx) rm(CDS) rm(cdsStarts) rm(cdsEnds) message("OK") ## ---------------------------- ## ## process exons message("Processing exons ... ", appendLF=FALSE) ## Fix for issue #72: seems there are GTFs without an exon_id! if (!any(gotColumns == "exon_id") & any(gotColumns == "exon_number")) { mcols(x)$exon_id <- paste0(x$transcript_id, ":", x$exon_number) warning("No column 'exon_id' present, created artificial exon IDs by ", "concatenating the transcript ID and the exon number.") gotColumns <- c(gotColumns, "exon_id") } reqCols <- c("exon_id", "transcript_id", "exon_number") if(!all(reqCols %in% gotColumns)) stop(paste0("One or more required fields are not defined in", " the submitted GRanges object! Need ", paste(reqCols, collapse=","), " but got only ", paste(reqCols[reqCols %in% gotColumns], collapse=","), ".")) exons <- as.data.frame(x[x$type == "exon", reqCols])[, -c(1, 4, 5)] ## for table tx2exon we want to have: ## tx_id, exon_id, exon_idx t2e <- unique(exons[ , c("transcript_id", "exon_id", "exon_number")]) colnames(t2e) <- c("tx_id", "exon_id", "exon_idx") ## Force exon_idx to be an integer! t2e[, "exon_idx"] <- as.integer(t2e[, "exon_idx"]) ## Cross-check that we've got the corresponding tx_ids in the tx table! ## for table exons we want to have: ## exon_id, exon_seq_start, exon_seq_end exons <- unique(exons[ , c("exon_id", "start", "end")]) colnames(exons) <- c("exon_id", "exon_seq_start", "exon_seq_end") ## writing the tables. .checkIntegerCols(exons) .checkIntegerCols(t2e) dbWriteTable(con, name="exon", exons, overwrite=TRUE, row.names=FALSE) dbWriteTable(con, name="tx2exon", t2e, overwrite=TRUE, row.names=FALSE) message("OK") ## ---------------------------- ## ## process chromosomes message("Processing chromosomes ... ", appendLF=FALSE) if (fetchSeqinfo) { ## problem is I don't have these available... chroms <- data.frame(seq_name = unique(as.character(genes$seq_name))) chroms <- cbind(chroms, seq_length = rep(NA, nrow(chroms)), is_circular = rep(NA, nrow(chroms))) rownames(chroms) <- chroms$seq_name ## Try to get sequence lengths from Ensembl or Ensemblgenomes. sl <- tryGetSeqinfoFromEnsembl(organism, version, seqnames = chroms$seq_name) if (nrow(sl) > 0) { sl <- sl[sl[, "name"] %in% rownames(chroms), ] chroms[sl[, "name"], "seq_length"] <- sl[, "length"] } } else { ## have seqinfo available. chroms <- data.frame(seq_name = seqnames(Seqinfo), seq_length = seqlengths(Seqinfo), is_circular = isCircular(Seqinfo)) } ## write the table. dbWriteTable(con, name="chromosome", chroms, overwrite=TRUE, row.names=FALSE) rm(genes) message("OK") message("Generating index ... ", appendLF=FALSE) ## generating all indices... .createEnsDbIndices(con) message("OK") message(" -------------") message("Verifying validity of the information in the database:") checkValidEnsDb(EnsDb(dbname)) return(dbname) } ## helper function that checks that the gene, transcript and exon data in the ## EnsDb database is correct (i.e. transcript within gene coordinates, exons within ## transcript coordinates, cds within transcript) checkValidEnsDb <- function(x){ message("Checking transcripts ... ", appendLF=FALSE) tx <- transcripts(x, columns=c("gene_id", "tx_id", "gene_seq_start", "gene_seq_end", "tx_seq_start", "tx_seq_end", "tx_cds_seq_start", "tx_cds_seq_end"), return.type="DataFrame") ## check if the tx are inside the genes... isInside <- tx$tx_seq_start >= tx$gene_seq_start & tx$tx_seq_end <= tx$gene_seq_end if(any(!isInside)) stop("Start and end coordinates for ", sum(!isInside), "transcripts are not within the gene coordinates!") ## check cds coordinates notInside <- which(!(tx$tx_cds_seq_start >= tx$tx_seq_start & tx$tx_cds_seq_end <= tx$tx_seq_end)) if(length(notInside) > 0){ stop("The CDS start and end coordinates for ", length(notInside), " transcripts are not within the transcript coordinates!") } rm(tx) message("OK\nChecking exons ... ", appendLF=FALSE) ex <- exons(x, columns=c("exon_id", "tx_id", "exon_seq_start", "exon_seq_end", "tx_seq_start", "tx_seq_end", "seq_strand", "exon_idx"), return.type="data.frame") ## check if exons are within tx isInside <- ex$exon_seq_start >= ex$tx_seq_start & ex$exon_seq_end <= ex$tx_seq_end if(any(!isInside)) stop("Start and end coordinates for ", sum(!isInside), " exons are not within the transcript coordinates!") ## checking the exon index... extmp <- ex[ex$seq_strand==1, c("exon_idx", "tx_id", "exon_seq_start")] extmp <- extmp[order(extmp$exon_seq_start), ] extmp.split <- split(extmp[ , c("exon_idx")], f=factor(extmp$tx_id)) Different <- unlist(lapply(extmp.split, FUN=function(z){ return(any(z != seq(1, length(z)))) })) if(any(Different)){ stop(paste0("Provided exon index in transcript does not match with", " ordering of the exons by chromosomal coordinates for ", sum(Different), " of the ", length(Different), " transcripts encoded on the + strand!")) } extmp <- ex[ex$seq_strand==-1, c("exon_idx", "tx_id", "exon_seq_end")] extmp <- extmp[order(extmp$exon_seq_end, decreasing=TRUE), ] extmp.split <- split(extmp[ , c("exon_idx")], f=factor(extmp$tx_id)) Different <- unlist(lapply(extmp.split, FUN=function(z){ return(any(z != seq(1, length(z)))) })) if(any(Different)){ stop(paste0("Provided exon index in transcript does not match with", " ordering of the exons by chromosomal coordinates for ", sum(Different), " of the ", length(Different), " transcripts encoded on the - strand!")) } message("OK") return(TRUE) } ############################################################ ##' Fetch chromosome sequence lengths from Ensembl. ##' @param organism The organism. Has to be in the form "Homo sapiens" ##' @param ensemblVersion The Ensembl version. ##' @param seqnames The names of the chromosomes/sequences; optional. ##' @return A matrix with two columns name and seq_length. ##' @noRd tryGetSeqinfoFromEnsembl <- function(organism, ensemblVersion, seqnames, skip = FALSE){ if (skip) return(matrix(nrow = 0, ncol = 2)) message("Fetch seqlengths from ensembl ... ", appendLF=FALSE) tmp <- try( .getSeqlengthsFromMysqlFolder(organism = organism, ensembl = ensemblVersion, seqnames = seqnames) , silent = TRUE) if (is(tmp, "try-error") | is.null(tmp)) { message("FAIL") warning("Unable to retrieve sequence lengths from Ensembl.") return(matrix(nrow = 0, ncol = 2)) } colnames(tmp) <- c("name", "length") return(tmp) } buildMetadata <- function(organism="", ensemblVersion="", genomeVersion="", host="", sourceFile=""){ MetaData <- data.frame(matrix(ncol=2, nrow=11)) colnames(MetaData) <- c("name", "value") MetaData[1, ] <- c("Db type", "EnsDb") MetaData[2, ] <- c("Type of Gene ID", "Ensembl Gene ID") MetaData[3, ] <- c("Supporting package", "ensembldb") MetaData[4, ] <- c("Db created by", "ensembldb package from Bioconductor") MetaData[5, ] <- c("script_version", "0.0.1") MetaData[6, ] <- c("Creation time", date()) MetaData[7, ] <- c("ensembl_version", ensemblVersion) MetaData[8, ] <- c("ensembl_host", host) MetaData[9, ] <- c("Organism", organism ) MetaData[10, ] <- c("genome_build", genomeVersion) MetaData[11, ] <- c("DBSCHEMAVERSION", "1.0") MetaData[12, ] <- c("source_file", sourceFile) return(MetaData) } ## compare the contents of the EnsDb sqlite database generated from a GTF (file name submitted ## with x ) with the one provided by package "lib". compareEnsDbs <- function(x, y){ ## compare two EnsDbs... if(organism(x)!=organism(y)) stop("Well, at least the organism should be the same for both databases!") Messages <- rep("OK", 5) names(Messages) <- c("metadata", "chromosome", "gene", "transcript", "exon") ## comparing metadata. metadataX <- metadata(x) metadataY <- metadata(y) rownames(metadataX) <- metadataX[, 1] rownames(metadataY) <- metadataY[, 1] metadataY <- metadataY[rownames(metadataX),] cat("\nComparing metadata:\n") idx <- which(metadataX[, "value"]!=metadataY[, "value"]) if(length(idx)>0) Messages["metadata"] <- "NOTE" ## check ensembl version if(metadataX["ensembl_version", "value"] == metadataY["ensembl_version", "value"]){ cat(" Ensembl versions match.\n") }else{ cat(" WARNING: databases base on different Ensembl versions!", " Expect considerable differences!\n", sep = "") Messages["metadata"] <- "WARN" } ## genome build if(metadataX["genome_build", "value"] == metadataY["genome_build", "value"]){ cat(" Genome builds match.\n") }else{ cat(" WARNING: databases base on different Genome builds!", " Expect considerable differences!\n", sep = "") Messages["metadata"] <- "WARN" } if(length(idx)>0){ cat(" All differences: : != \n") for(i in idx){ cat(paste(" - ", metadataX[i, "name"], ":", metadataX[i, "value"], " != ", metadataY[i, "value"], "\n")) } } cat(paste0("Done. Result: ", Messages["metadata"],"\n")) ## now comparing chromosomes Messages["chromosome"] <- compareChromosomes(x, y) ## comparing genes Messages["gene"] <- compareGenes(x, y) ## comparing transcripts Messages["transcript"] <- compareTx(x, y) ## comparing exons Messages["exon"] <- compareExons(x, y) ## If we've got protein data in one of the two: if (hasProteinData(x) | hasProteinData(y)) { Messages <- c(Messages, protein = "OK") Messages["protein"] <- compareProteins(x, y) } return(Messages) } compareChromosomes <- function(x, y){ Ret <- "OK" cat("\nComparing chromosome data:\n") chromX <- as.data.frame(seqinfo(x)) chromY <- as.data.frame(seqinfo(y)) ## compare seqnames inboth <- rownames(chromX)[rownames(chromX) %in% rownames(chromY)] onlyX <- rownames(chromX)[!(rownames(chromX) %in% rownames(chromY))] onlyY <- rownames(chromY)[!(rownames(chromY) %in% rownames(chromX))] if(length(onlyX) > 0 | length(onlyY) > 0) Ret <- "WARN" cat(paste0( " Sequence names: (", length(inboth), ") common, (", length(onlyX), ") only in x, (", length(onlyY), ") only in y.\n" )) ## seqlengths: if (!all.equal(chromX[inboth, "seqlengths"], chromY[inboth, "seqlengths"])) { same <- length(which(chromX[inboth, "seqlengths"] == chromY[inboth, "seqlengths"])) different <- length(inboth) - same } else { same <- length(inboth) different <- 0 } cat(paste0( " Sequence lengths: (",same, ") identical, (", different, ") different.\n" )) if(different > 0) Ret <- "WARN" cat(paste0("Done. Result: ", Ret,"\n")) return(Ret) } compareGenes <- function(x, y){ cat("\nComparing gene data:\n") Ret <- "OK" genesX <- genes(x) genesY <- genes(y) inboth <- names(genesX)[names(genesX) %in% names(genesY)] onlyX <- names(genesX)[!(names(genesX) %in% names(genesY))] onlyY <- names(genesY)[!(names(genesY) %in% names(genesX))] if(length(onlyX) > 0 | length(onlyY) > 0) Ret <- "WARN" cat(paste0(" gene IDs: (", length(inboth), ") common, (", length(onlyX), ") only in x, (", length(onlyY), ") only in y.\n")) ## seq names same <- length( which(as.character(seqnames(genesX[inboth])) == as.character(seqnames(genesY[inboth]))) ) different <- length(inboth) - same if(different > 0) Ret <- "ERROR" cat(paste0( " Sequence names: (",same, ") identical, (", different, ") different.\n" )) ## start same <- length( which(start(genesX[inboth]) == start(genesY[inboth])) ) different <- length(inboth) - same if(different > 0) Ret <- "ERROR" cat(paste0( " Gene start coordinates: (",same, ") identical, (", different, ") different.\n" )) ## end same <- length( which(end(genesX[inboth]) == end(genesY[inboth])) ) different <- length(inboth) - same if(different > 0) Ret <- "ERROR" cat(paste0( " Gene end coordinates: (",same, ") identical, (", different, ") different.\n" )) ## strand same <- length( which(as.character(strand(genesX[inboth])) == as.character(strand(genesY[inboth]))) ) different <- length(inboth) - same if(different > 0) Ret <- "ERROR" cat(paste0( " Gene strand: (",same, ") identical, (", different, ") different.\n" )) ## name same <- length( which(genesX[inboth]$gene_name == genesY[inboth]$gene_name) ) different <- length(inboth) - same if(different > 0 & Ret!="ERROR") Ret <- "WARN" cat(paste0( " Gene names: (",same, ") identical, (", different, ") different.\n" )) ## entrezid same <- length( which(genesX[inboth]$entrezid == genesY[inboth]$entrezid) ) different <- length(inboth) - same if(different > 0 & Ret!="ERROR") Ret <- "WARN" cat(paste0( " Entrezgene IDs: (",same, ") identical, (", different, ") different.\n" )) ## gene biotype same <- length( which(genesX[inboth]$gene_biotype == genesY[inboth]$gene_biotype) ) different <- length(inboth) - same if(different > 0 & Ret!="ERROR") Ret <- "WARN" cat(paste0( " Gene biotypes: (",same, ") identical, (", different, ") different.\n" )) cat(paste0("Done. Result: ", Ret,"\n")) return(Ret) } compareTx <- function(x, y){ cat("\nComparing transcript data:\n") Ret <- "OK" txX <- transcripts(x) txY <- transcripts(y) inboth <- names(txX)[names(txX) %in% names(txY)] onlyX <- names(txX)[!(names(txX) %in% names(txY))] onlyY <- names(txY)[!(names(txY) %in% names(txX))] if(length(onlyX) > 0 | length(onlyY) > 0) Ret <- "WARN" cat(paste0(" transcript IDs: (", length(inboth), ") common, (", length(onlyX), ") only in x, (", length(onlyY), ") only in y.\n")) ## start same <- length( which(start(txX[inboth]) == start(txY[inboth])) ) different <- length(inboth) - same if(different > 0) Ret <- "ERROR" cat(paste0( " Transcript start coordinates: (",same, ") identical, (", different, ") different.\n" )) ## end same <- length( which(end(txX[inboth]) == end(txY[inboth])) ) different <- length(inboth) - same if(different > 0) Ret <- "ERROR" cat(paste0( " Transcript end coordinates: (",same, ") identical, (", different, ") different.\n" )) ## tx biotype same <- length( which(txX[inboth]$tx_biotype == txY[inboth]$tx_biotype) ) different <- length(inboth) - same if(different > 0 & Ret!="ERROR") Ret <- "WARN" cat(paste0( " Transcript biotypes: (",same, ") identical, (", different, ") different.\n" )) ## cds start ## Makes sense to just compare for those that have the same tx! txXSub <- txX[inboth] txYSub <- txY[inboth] txCdsX <- names(txXSub)[!is.na(txXSub$tx_cds_seq_start)] txCdsY <- names(txYSub)[!is.na(txYSub$tx_cds_seq_start)] cdsInBoth <- txCdsX[txCdsX %in% txCdsY] cdsOnlyX <- txCdsX[!(txCdsX %in% txCdsY)] cdsOnlyY <- txCdsY[!(txCdsY %in% txCdsX)] if((length(cdsOnlyX) > 0 | length(cdsOnlyY)) & Ret!="ERROR") Ret <- "ERROR" cat(paste0(" Common transcripts with defined CDS: (", length(cdsInBoth), ") common, (", length(cdsOnlyX), ") only in x, (", length(cdsOnlyY), ") only in y.\n")) same <- length( which(txX[cdsInBoth]$tx_cds_seq_start == txY[cdsInBoth]$tx_cds_seq_start) ) different <- length(cdsInBoth) - same if(different > 0 & Ret!="ERROR") Ret <- "ERROR" cat(paste0( " CDS start coordinates: (",same, ") identical, (", different, ") different.\n" )) ## cds end same <- length( which(txX[cdsInBoth]$tx_cds_seq_end == txY[cdsInBoth]$tx_cds_seq_end) ) different <- length(cdsInBoth) - same if(different > 0 & Ret!="ERROR") Ret <- "ERROR" cat(paste0( " CDS end coordinates: (",same, ") identical, (", different, ") different.\n" )) ## gene id same <- length( which(txX[inboth]$gene_id == txY[inboth]$gene_id) ) different <- length(inboth) - same if(different > 0) Ret <- "ERROR" cat(paste0( " Associated gene IDs: (",same, ") identical, (", different, ") different.\n" )) cat(paste0("Done. Result: ", Ret,"\n")) return(Ret) } compareProteins <- function(x, y){ cat("\nComparing protein data:\n") Ret <- "OK" if (!hasProteinData(x) | !hasProteinData(y)) { Ret <- "WARN" cat(paste0("No protein data available for one or both EnsDbs.")) return(Ret) } X <- proteins(x) Y <- proteins(y) inboth <- X$protein_id[X$protein_id %in% Y$protein_id] onlyX <- X$protein_id[!(X$protein_id %in% Y$protein_id)] onlyY <- Y$protein_id[!(Y$protein_id %in% X$protein_id)] if(length(onlyX) > 0 | length(onlyY) > 0) Ret <- "WARN" cat(paste0(" protein IDs: (", length(inboth), ") common, (", length(onlyX), ") only in x, (", length(onlyY), ") only in y.\n")) X <- X[X$protein_id %in% inboth, ] Y <- Y[Y$protein_id %in% inboth, ] ## sorting both by protein_id should be enough. X <- X[order(X$protein_id), ] Y <- Y[order(Y$protein_id), ] ## tx_id same <- length(which(X$tx_id == Y$tx_id)) different <- length(inboth) - same if(different > 0) Ret <- "ERROR" cat(paste0( " Transcript IDs: (",same, ") identical, (", different, ") different.\n" )) ## sequence same <- length(which(X$protein_sequence == Y$protein_sequence)) different <- length(inboth) - same if(different > 0) Ret <- "ERROR" cat(paste0( " Protein sequence: (",same, ") identical, (", different, ") different.\n" )) cat(paste0("Done. Result: ", Ret,"\n")) return(Ret) } compareExons <- function(x, y){ cat("\nComparing exon data:\n") Ret <- "OK" exonX <- exons(x) exonY <- exons(y) inboth <- names(exonX)[names(exonX) %in% names(exonY)] onlyX <- names(exonX)[!(names(exonX) %in% names(exonY))] onlyY <- names(exonY)[!(names(exonY) %in% names(exonX))] if(length(onlyX) > 0 | length(onlyY) > 0) Ret <- "WARN" cat(paste0(" exon IDs: (", length(inboth), ") common, (", length(onlyX), ") only in x, (", length(onlyY), ") only in y.\n")) ## start same <- length( which(start(exonX[inboth]) == start(exonY[inboth])) ) different <- length(inboth) - same if(different > 0) Ret <- "ERROR" cat(paste0( " Exon start coordinates: (",same, ") identical, (", different, ") different.\n" )) ## end same <- length( which(end(exonX[inboth]) == end(exonY[inboth])) ) different <- length(inboth) - same if(different > 0) Ret <- "ERROR" cat(paste0( " Exon end coordinates: (",same, ") identical, (", different, ") different.\n" )) ## now getting also the exon index in tx: exonX <- exons(x, columns=c("exon_id", "tx_id", "exon_idx"), return.type="DataFrame") rownames(exonX) <- paste(exonX$tx_id, exonX$exon_id, sep=":") exonY <- exons(y, columns=c("exon_id", "tx_id", "exon_idx"), return.type="DataFrame") rownames(exonY) <- paste(exonY$tx_id, exonY$exon_id, sep=":") inboth <- rownames(exonX)[rownames(exonX) %in% rownames(exonY)] onlyX <- rownames(exonX)[!(rownames(exonX) %in% rownames(exonY))] onlyY <- rownames(exonY)[!(rownames(exonY) %in% rownames(exonX))] ## tx exon idx same <- length( which(exonX[inboth, ]$exon_idx == exonY[inboth, ]$exon_idx) ) different <- length(inboth) - same if(different > 0 ) Ret <- "ERROR" cat(paste0( " Exon index in transcript models: (",same, ") identical, (", different, ") different.\n" )) cat(paste0("Done. Result: ", Ret,"\n")) return(Ret) } ####============================================================ ## isEnsemblFileName ## ## evaluate whether the file name is "most likely" corresponding ## to a file name from Ensembl, i.e. following the convention ## ...[chr].gff/gtf.gz ## The problem is that the genome version can also be . separated. ####------------------------------------------------------------ isEnsemblFileName <- function(x){ x <- basename(x) ## If we split by ., do we get at least 4 elements? els <- unlist(strsplit(x, split=".", fixed=TRUE)) if(length(els) < 4) return(FALSE) ## Can we get an Ensembl version? ensVer <- ensemblVersionFromGtfFileName(x) if(is.na(ensVer)) return(FALSE) ## If we got one, do we still have enough fields left of the version? idx <- which(els == ensVer) idx <- idx[length(idx)] if(idx < 3){ ## No way, we're missing the organism and the genome build field! return(FALSE) } ## Well, can not think of any other torture... let's assume it's OK. return(TRUE) } organismFromGtfFileName <- function(x){ return(elementFromEnsemblFilename(x, 1)) } ####============================================================ ## ensemblVersionFromGtfFileName ## ## Tries to extract the Ensembl version from the file name. If it ## finds a numeric value it returns it, otherwise it returns NA. ####------------------------------------------------------------ ensemblVersionFromGtfFileName <- function(x){ x <- basename(x) els <- unlist(strsplit(x, split=".", fixed=TRUE)) ## Ensembl version is the last numeric value in the file name. for(elm in rev(els)){ suppressWarnings( if(!is.na(as.numeric(elm))){ return(elm) } ) } return(NA) } ####============================================================ ## genomeVersionFromGtfFileName ## ## the genome build can also contain .! thus, I return everything which is not ## the first element (i.e. organism), or the ensembl version, that is one left of ## the gtf. genomeVersionFromGtfFileName <- function(x){ x <- basename(x) els <- unlist(strsplit(x, split=".", fixed=TRUE)) ensVer <- ensemblVersionFromGtfFileName(x) if(is.na(ensVer)){ stop("Can not extract the genome version from the file name!", " The file name does not follow the expected naming convention from Ensembl!") } idx <- which(els == ensVer) idx <- idx[length(idx)] if(idx < 3) stop("Can not extract the genome version from the file name!", " The file name does not follow the expected naming convention from Ensembl!") return(paste(els[2:(idx-1)], collapse=".")) } ## Returns NULL if there was a problem. elementFromEnsemblFilename <- function(x, which=1){ tmp <- unlist(strsplit(x, split=.Platform$file.sep, fixed=TRUE)) splitty <- unlist(strsplit(tmp[length(tmp)], split=".", fixed=TRUE)) if(length(splitty) < which){ warning("File ", x, " does not conform to the Ensembl file naming convention.") return(NULL) } return(splitty[which]) } ############################################################ ## Utilities to fetch sequence lengths from Ensembl's ftp server, more ## specifically from the MySQL tables there. ## These replace the (unexported) functions from GenomicFeatures used thus far. .ENSEMBL_URL <- "ftp://ftp.ensembl.org/pub/" .ENSEMBLGENOMES_URL <- "ftp://ftp.ensemblgenomes.org/pub/" ##' Get the base url containing the mysql database for the specified host, ##' orgnism and Ensembl version. ##' @details The function will first build an approximate database name (without ##' the trailing <_genome version number> as this is not easy to guess). ##' Next all directories in the base MySQL folder will be scanned for the best ##' matching folder. ##' @param type Either "ensembl" or "ensemblgenomes" ##' @param organism Character specifying the organism. Has to be the full name, ##' i.e "homo_sapiens" or "Homo sapiens". ##' @param ensembl The Ensembl version. ##' @param genone The Genome version. ##' @noRd .getEnsemblMysqlUrl <- function(type = "ensembl", organism, ensembl, genome) { type <- match.arg(type, c("ensembl", "ensemblgenomes")) if (type == "ensembl") { my_url <- paste0(.ENSEMBL_URL, "release-", ensembl, "/mysql/") db_name <- .guessDatabaseName(organism, ensembl) ## List folders; GenomicFeatures does it without 'dirlistonly', ## eventually that's what breaks on Windows? ## res <- getURL(my_url, dirlistonly = TRUE) res <- readLines(curl(my_url)) res <- gsub(res, pattern = "\r", replacement = "", fixed = TRUE) if (length(res) > 0) { ## dirs <- unlist(strsplit(res, split = "\n")) ## ## Remove the \r on Windows. ## dirs <- sub(dirs, pattern = "\r", replacement = "", fixed = TRUE) ## idx <- grep(dirs, pattern = db_name) idx <- grep(res, pattern = db_name) if (length(idx) > 1) stop("Found more than one database matching '", db_name, "' in Ensembl's ftp server!") if (length(idx) == 0) stop("No database matching '", db_name, "' found in Ensembl's", " ftp server.") db_dir <- unlist(strsplit(res[idx], split = " ", fixed = TRUE)) db_dir <- db_dir[length(db_dir)] return(paste0(my_url, db_dir)) } } else { ## That's tricky! Have to find out whether the species is in plants, ## fungi, bacteria etc. ## List dirs of bacteria, fungi, metazoa, plants, protists sub_folders <- c("bacteria", "fungi", "metazoa", "plants", "protists") db_name <- .guessDatabaseName(organism, ensembl) for (fold in sub_folders) { my_url <- paste0(.ENSEMBLGENOMES_URL, "release-", ensembl, "/", fold, "/mysql/") res <- try(readLines(curl(my_url))) if (is(res, "try-error")| length(res) == 0) next if (length(res) > 0) { res <- gsub(res, pattern = "\r", replacement = "", fixed = TRUE) idx <- grep(res, pattern = db_name) if (length(idx) > 1) stop("Found more than one database matching '", db_name, "' in Ensemblgenomes' ftp server!") if (length(idx) == 1) { db_dir <- unlist(strsplit(res[idx], split = " ", fixed = TRUE)) db_dir <- db_dir[length(db_dir)] return(paste0(my_url, db_dir)) } } ## ## Catch eventual errors ## res <- try(getURL(my_url, dirlistonly = TRUE), silent = TRUE) ## if (is(res, "try-error") | length(res) == 0) ## next ## if (length(res) > 0) { ## dirs <- unlist(strsplit(res, split = "\n")) ## ## Remove the \r on Windows. ## dirs <- sub(dirs, pattern = "\r", replacement = "", fixed = TRUE) ## idx <- grep(dirs, pattern = db_name) ## if (length(idx) == 1) ## return(paste0(my_url, dirs[idx])) ## if (length(idx) > 1) ## stop("Found more than one database matching '", db_name, ## "' in Ensembl's ftp server!") ## ## Well, then let's go to the next one. ## } } stop("No database matching '", db_name, "' found in Ensembl's", " ftp server") } } ############################################################ ## .guessDatabaseName ##' build the database name from species, ensembl version and genome version. ##' The latter is specifically difficult, as it is not quite clear how Ensembl ##' defines the Genome version number. ##' @param organism Character specifying the organism. Has to be in the format ##' "homo_sapiens" or "Homo sapiens", i.e. the full name. ##' @param ensembl The Ensembl version number. ##' @param genome The Genome version, e.g. GRCh38 (optional!). ##' @return A character representing the guessed database name in Ensembl. ##' @noRd .guessDatabaseName <- function(organism, ensembl, genome) { if (missing(organism) & missing(ensembl)) stop("'organism' and 'ensembl' are required!") ## Organism: all lower case, replace . with _ organism <- tolower(gsub(organism, pattern = ".", replacement = "_", fixed = TRUE)) organism <- gsub(organism, pattern = " ", replacement = "_", fixed = TRUE) dbname <- paste0(organism, "_core_", ensembl) ## Genome: remove all letters and keep just the numbers. if (!missing(genome)) { genome <- gsub(genome, pattern = "[a-zA-Z]", replacement = "") ## replace .0 at the end genome <- gsub(genome, pattern = ".0$", replacement = "") genome <- gsub(genome, pattern = ".", replacement = "", fixed = TRUE) genome <- gsub(genome, pattern = "_", replacement = "", fixed = TRUE) dbname <- paste0(dbname, "_", genome) } return(dbname) } ############################################################ ## .getSeqlengthsFromMysqlFolder ##' Fetch the coord_system.txt.gz and seq_region.txt.gz and extract the ##' seqlengths from there. ##' @noRd .getSeqlengthsFromMysqlFolder <- function(organism, ensembl, seqnames) { ## Test whether we have the database in ensembl mysql_url <- try(.getEnsemblMysqlUrl(type = "ensembl", organism = organism, ensembl = ensembl), silent = TRUE) if (is(mysql_url, "try-error")) { mysql_url <- try(.getEnsemblMysqlUrl(type = "ensemblgenomes", organism = organism, ensembl = ensembl), silent = TRUE) } if (is(mysql_url, "try-error")) { warning("Can not get the sequence lengths from Ensembl or", " Ensemblgenomes. Seqinfo will lack the sequence lengths.") return(NULL) } ## Get the coord_system table coord_syst <- .getReadMysqlTable(mysql_url, "coord_system.txt.gz", colnames = c("coord_system_id", "species_id", "name", "version", "rank", "attrib")) ## Subset to the ones with "default" in "attrib" coord_syst <- coord_syst[grep(coord_syst$attrib, pattern = "default"), , drop = FALSE] rownames(coord_syst) <- as.character(coord_syst$coord_system_id) ## Get the seq_region table seq_region <- .getReadMysqlTable(mysql_url, "seq_region.txt.gz", colnames = c("seq_region_id", "name", "coord_system_id", "length")) ## Sub-set to the ones matching the coord_syst_ids and from these, select ## the one entry with the smallest rank, if more than one present. seq_region <- seq_region[seq_region$coord_system_id %in% coord_syst$coord_system_id, , drop = FALSE] seq_region <- cbind(seq_region, rank = coord_syst[as.character(seq_region$coord_system_id), "rank"]) ## Sub-set to the seqlevels we've got. if (!missing(seqnames)) { seq_region <- seq_region[seq_region$name %in% seqnames, , drop = FALSE] if (!all(seqnames %in% seq_region$name)) warning("Could not determine length for all seqnames.") } sr <- split(seq_region, f = seq_region$name) if (length(sr) == 0) return(NULL) sr <- lapply(sr, function(z) { if (nrow(z) == 1) return(z) z <- z[order(z$rank), ] return(z[1, , drop = FALSE]) }) sr <- do.call(rbind, sr) rownames(sr) <- sr$name return(sr[, c("name", "length")]) } ##' Download and read a table from Ensembl ##' @param base_url the base url to the mysql folder on the server. ##' @param file_name the file name of the table. ##' @param colnames the column names. ##' @return A data.frame with the table's content. ##' @noRd .getReadMysqlTable <- function(base_url, file_name, colnames) { tmp_file <- tempfile() download.file(url = paste0(base_url, "/", file_name), destfile = tmp_file, quiet = TRUE) tmp <- read.table(tmp_file, sep = "\t", quote = "", comment.char = "", as.is = TRUE) colnames(tmp) <- colnames return(tmp) } ensembldb/R/functions-utils.R0000644000175400017540000002127213175714743017245 0ustar00biocbuildbiocbuild############################################################ ## Utility functions ############################################################ ## orderDataFrameBy ## ## Simply orders the data.frame x based on the columns specified ## with by. orderDataFrameBy <- function(x, by = "", decreasing = FALSE) { if (all(by == "") | all(is.null(by))) return(x) return(x[do.call(order, args = c(list(method = "radix", decreasing = decreasing), as.list(x[, by, drop = FALSE]))), ]) } ############################################################ ## checkOrderBy ## ## Check the orderBy argument. ## o orderBy can be a character vector or a , separated list. ## o Ensure that the columns are valid by comparing with 'supported'. ## Returns a character vector, each element representing a column ## on which sorting should be performed. checkOrderBy <- function(orderBy, supported = character()) { if (is.null(orderBy) | all(orderBy == "")) { return(orderBy) } if (length(orderBy) == 1 & length(grep(orderBy, pattern = ",")) > 0) { orderBy <- unlist(strsplit(orderBy, split = ","), use.names = FALSE) orderBy <- gsub(orderBy, pattern = " ", replacement = "", fixed = TRUE) } not_supported <- !(orderBy %in% supported) if (any(not_supported)) { warning("Columns in 'order.by' (", paste(orderBy[not_supported], collapse = ", "), ") are not in 'columns' and were thus removed.") orderBy <- orderBy[!not_supported] if (length(orderBy) == 0) orderBy <- "" } return(orderBy) } ############################################################ ## addFilterColumns ## ## This function checks the filter objects and adds, depending on the ## returnFilterColumns setting of the EnsDb, also columns for each of the ## filters, ensuring that: ## a) "Symlink" filters are added correctly (the column returned by the ## column call without db are added). ## b) GRangesFilter: the feature is set based on the specified feature parameter ## Args: addFilterColumns <- function(cols, filter = AnnotationFilterList(), edb) { if (missing(cols)) cols <- NULL gimmeAll <- returnFilterColumns(edb) if (!gimmeAll) return(cols) ## Put filter into an AnnotationFilterList if it's not already one if (is(filter, "AnnotationFilter")) filter <- AnnotationFilterList(filter) ## Or alternatively process the filters and add columns. symFilts <- c("SymbolFilter") addC <- unlist(lapply(filter, function(z) { if(class(z) %in% symFilts) return(z@field) if (is(z, "AnnotationFilterList")) return(addFilterColumns(cols = cols, filter = z, edb)) return(ensDbColumn(z)) })) return(unique(c(cols, addC))) } ############################################################ ## SQLiteName2MySQL ## ## Convert the SQLite database name (file name) to the corresponding ## MySQL database name. SQLiteName2MySQL <- function(x) { return(tolower(gsub(x, pattern = ".", replacement = "_", fixed = TRUE))) } ## running the shiny web app. runEnsDbApp <- function(...){ if(requireNamespace("shiny", quietly=TRUE)){ message("Starting the EnsDb shiny web app. Use Ctrl-C to stop.") shiny::runApp(appDir=system.file("shinyHappyPeople", package="ensembldb"), ...) }else{ stop("Package shiny not installed!") } } ############################################################ ## anyProteinColumns ## ## Check if any of 'x' are protein columns. anyProteinColumns <- function(x){ return(any(x %in% unlist(.ensdb_protein_tables(), use.names = FALSE))) } ############################################################ ## listProteinColumns ## #' @description The \code{listProteinColumns} function allows to conveniently #' extract all database columns containing protein annotations from #' an \code{\linkS4class{EnsDb}} database. #' #' @return The \code{listProteinColumns} function returns a character vector #' with the column names containing protein annotations or throws an error #' if no such annotations are available. #' #' @rdname ProteinFunctionality #' #' @examples #' #' ## List all columns containing protein annotations #' library(EnsDb.Hsapiens.v75) #' edb <- EnsDb.Hsapiens.v75 #' if (hasProteinData(edb)) #' listProteinColumns(edb) listProteinColumns <- function(object) { if (missing(object)) stop("'object' is missing with no default.") if (!is(object, "EnsDb")) stop("'object' has to be an instance of an 'EnsDb' object.") if (!hasProteinData(object)) stop("The provided EnsDb database does not contain protein annotations!") return(listColumns(object, c("protein", "uniprot", "protein_domain"))) } ############################################################ ## .ProteinsFromDataframe #' @param x \code{EnsDb} object. #' #' @param data \code{data.frame} with the results from a call to the #' \code{proteins} method; has to have required columns \code{"protein_id"} #' and \code{"protein_sequence"}. #' #' @noRd .ProteinsFromDataframe <- function(x, data) { if (!all(c("protein_id", "protein_sequence") %in% colnames(data))) stop("Reguired columns 'protein_id' and 'protein_sequence' not in 'data'!") ## Get the column names for uniprot and protein_domain uniprot_cols <- listColumns(x, "uniprot") uniprot_cols <- uniprot_cols[uniprot_cols != "protein_id"] uniprot_cols <- uniprot_cols[uniprot_cols %in% colnames(data)] if (length(uniprot_cols) > 0) warning("Don't know yet how to handle the 1:n mapping between", " protein_id and uniprot_id!") prot_dom_cols <- listColumns(x, "protein_domain") prot_dom_cols <- prot_dom_cols[prot_dom_cols != "protein_id"] prot_dom_cols <- prot_dom_cols[prot_dom_cols %in% colnames(data)] ## Create the protein part of the object, i.e. the AAStringSet. ## Use all columns other than protein_id, protein_sequence prot_cols <- colnames(data) prot_cols <- prot_cols[!(prot_cols %in% c(uniprot_cols, prot_dom_cols))] protein_sub <- unique(data[, prot_cols, drop = FALSE]) aass <- AAStringSet(protein_sub$protein_sequence) names(aass) <- protein_sub$protein_id prot_cols <- prot_cols[!(prot_cols %in% c("protein_id", "protein_sequence"))] if (length(prot_cols) > 0) { mcols(aass) <- DataFrame(protein_sub[, prot_cols, drop = FALSE]) ## drop these columns from data to eventually speed up splits data <- data[, !(colnames(data) %in% prot_cols), drop = FALSE] } ## How to process the Uniprot here??? have a 1:n mapping! ## Create the protein domain part if (length(prot_dom_cols) > 0) { message("Processing protein domains not yet implemented!") ## Split the dataframe by protein_id ## process this list to create the IRangesList. ## pranges should have the same order and the same names } else { pranges <- IRangesList(replicate(length(aass), IRanges())) names(pranges) <- names(aass) } metadata <- list(created = date()) ##return(new("Proteins", aa = aass, pranges = pranges, metadata = metadata)) } ## map chromosome strand... strand2num <- function(x){ if (is.numeric(x)) { if (x >= 0) return(1) else return(-1) } xm <- x if(xm == "+" | xm == "-") xm <- paste0(xm, 1) xm <- as.numeric(xm) if (is.na(xm)) stop("'", x, "' can not be converted to a strand!") return(xm) } num2strand <- function(x){ if(x < 0){ return("-") }else{ return("+") } } #' @description Collapses entries in the \code{"entrezid"} column of a #' \code{data.frame} or \code{DataFrame} making the rest of \code{x} unique. #' #' @param x Either a \code{data.frame} or a \code{DataFrame}. #' #' @param by \code{character(1)} defining the column by which the #' \code{"entrezid"} column should be splitted. #' #' @author Johannes Rainer #' #' @noRd .collapseEntrezidInTable <- function(x, by = "gene_id") { ## Slow version: use unique call. eg_idx <- which(colnames(x) == "entrezid") if (length(eg_idx)) { ## Avoid an additional lapply unique call. tmp <- unique(x[, c(by, "entrezid")]) egs <- split(tmp[, "entrezid"], f = factor(tmp[, by], levels = unique(tmp[, by]))) ## Use a unique call. ## x_sub <- x[match(names(egs), x[, by]), , drop = FALSE] would be much ## faster but does not work e.g. for exons or transcripts. x_sub <- unique(x[, -eg_idx, drop = FALSE]) x_sub$entrezid <- egs[x_sub[, by]] return(x_sub) } x } ensembldb/R/select-methods.R0000644000175400017540000003526713175714743017030 0ustar00biocbuildbiocbuild## That's to support and interface the AnnotionDbi package. ####============================================================ ## .getColMappings ## ## That returns a character vector of abbreviated column names ## which can be/are used by AnnotationDbi with the names correponding ## to the column names from ensembldb. ## x: is supposed to be an EnsDb object. ## all: if TRUE we return all of them, otherwise we just return those ## that should be visible for the user. ####------------------------------------------------------------ .getColMappings <- function(x, all=FALSE){ cols <- listColumns(x) if(!all){ cols <- cols[!(cols %in% c("name", "value"))] } ret <- toupper(gsub("_", replacement="", cols)) names(ret) <- cols return(ret) } ####============================================================ ## columnForKeytype ## ## Returns the appropriate column name in the database for the ## given keytypes. ####------------------------------------------------------------ ensDbColumnForColumn <- function(x, column){ maps <- .getColMappings(x) revmaps <- names(maps) names(revmaps) <- maps cols <- revmaps[column] if(any(is.na(cols))){ warning("The following columns can not be mapped to column names in the", " db: ", paste(column[is.na(cols)], collapse=", ")) cols <- cols[!is.na(cols)] } ## Fixing tx_name; tx_name should be mapped to tx_id in the database! ##cols[cols == "tx_name"] <- "tx_id" return(cols) } ####============================================================ ## columns method ## ## Just return the attributes, but as expected by the AnnotationDbi ## interface (i.e. upper case, no _). ####------------------------------------------------------------ .getColumns <- function(x){ cols <- .getColMappings(x, all=FALSE) names(cols) <- NULL return(unique(cols)) } setMethod("columns", "EnsDb", function(x) .getColumns(x) ) ####============================================================ ## keytypes method ## ## I will essentially use all of the filters here. ####------------------------------------------------------------ setMethod("keytypes", "EnsDb", function(x){ return(.filterKeytypes(withProteins = hasProteinData(x))) } ) ## This just returns some (eventually) usefull names for keys .simpleKeytypes <- function(x){ return(c("GENEID","TXID","TXNAME","EXONID","EXONNAME","CDSID","CDSNAME")) } .filterKeytypes <- function(withProteins = FALSE){ return(names(.keytype2FilterMapping(withProteins = withProteins))) } ## returns a vector mapping keytypes (names of vector) to filter names (elements). .keytype2FilterMapping <- function(withProteins = FALSE){ filters <- c(ENTREZID = "EntrezFilter", GENEID = "GeneIdFilter", GENEBIOTYPE = "GeneBiotypeFilter", GENENAME = "GenenameFilter", TXID = "TxIdFilter", TXBIOTYPE = "TxBiotypeFilter", EXONID = "ExonIdFilter", SEQNAME = "SeqNameFilter", SEQSTRAND = "SeqStrandFilter", TXNAME = "TxIdFilter", SYMBOL = "SymbolFilter") if (withProteins) { filters <- c(filters, PROTEINID = "ProteinIdFilter", UNIPROTID = "UniprotFilter", PROTEINDOMAINID = "ProtDomIdFilter") } return(filters) } filterForKeytype <- function(keytype, x, vals){ if (missing(vals)) vals <- 1 if (!missing(x)) { withProts <- hasProteinData(x) } else { withProts <- FALSE } filters <- .keytype2FilterMapping(withProts) if(any(names(filters) == keytype)){ filt <- do.call(filters[keytype], args = list(value = vals)) ## filt <- new(filters[keytype]) return(filt) }else{ stop("No filter for that keytype!") } } ####============================================================ ## keys method ## ## This keys method returns all of the keys for a specified keytype. ## There should also be an implementation without keytypes, which ## returns in our case the gene_ids ## ####------------------------------------------------------------ setMethod("keys", "EnsDb", function(x, keytype, filter, ...){ if(missing(keytype)) keytype <- "GENEID" if(missing(filter)) filter <- AnnotationFilterList() filter <- .processFilterParam(filter, x) keyt <- keytypes(x) if (length(keytype) > 1) { keytype <- keytype[1] warning("Using only first provided keytype.") } if (!any(keyt == keytype)) stop("keytype '", keytype, "' not supported! ", "Allowed choices are: ", paste0("'", keyt ,"'", collapse = ", "), ".") keytype <- match.arg(keytype, keyt) ## Map the keytype to the appropriate column name. dbColumn <- ensDbColumnForColumn(x, keytype) ## Perform the query. res <- getWhat(x, columns = dbColumn, filter = filter)[, dbColumn] return(res) }) ############################################################ ## select method ## ## We have to be carefull, if the database contains protein annotations too: ## o If the keys are DNA/RNA related, start from a DNA/RNA related table. ## o if keys are protein related: start from a protein column. ## Reason is that we do have only protein annotations for protein coding genes ## and no annotation for the remaining. Thus the type of the join (left join, ## left outer join) is crucial, as well as the table with which we start the ## query! ## What if we provide more than one filter? ## a) GenenameFilter and ProteinidFilter: doesn't really matter from which table ## we start, because the query will only return results with protein ## annotions. -> if there is one DNA/RNA related filter: don't do anything. ## b) Only protein filters: start from the highest protein table. setMethod("select", "EnsDb", function(x, keys, columns, keytype, ...) { if (missing(keys)) keys <- NULL if (missing(columns)) columns <- NULL if (missing(keytype)) keytype <- NULL return(.select(x = x, keys = keys, columns = columns, keytype = keytype, ...)) }) .select <- function(x, keys = NULL, columns = NULL, keytype = NULL, ...) { extraArgs <- list(...) ## Perform argument checking: ## columns: if (missing(columns) | is.null(columns)) columns <- columns(x) notAvailable <- !(columns %in% columns(x)) if (all(notAvailable)) stop("None of the specified columns are avaliable in the database!") if (any(notAvailable)){ warning("The following columns are not available in the database and", " have thus been removed: ", paste(columns[notAvailable], collapse = ", ")) columns <- columns[!notAvailable] } ## keys: if (is.null(keys) | missing(keys)) { ## Get everything from the database... keys <- list() } else { if (!(is(keys, "character") | is(keys, "list") | is(keys, "formula") | is(keys, "AnnotationFilter") | is(keys, "AnnotationFilterList"))) stop("Argument keys should be a character vector, an object", " extending AnnotationFilter, a filter expression", " or an AnnotationFilterList.") if (is(keys, "character")) { if (is.null(keytype)) { stop("Argument keytype is mandatory if keys is a", " character vector!") } ## Check also keytype: if (!(keytype %in% keytypes(x))) stop("keytype ", keytype, " not available in the database.", " Use keytypes method to list all available keytypes.") ## Generate a filter object for the filters. keyFilter <- filterForKeytype(keytype, x, vals = keys) ## value(keyFilter) <- keys ## keyFilter@value <- keys keys <- list(keyFilter) ## Add also the keytype itself to the columns. if (!any(columns == keytype)) columns <- c(keytype, columns) } ## Check and fix filter. keys <- .processFilterParam(keys, x) } ## Map the columns to column names we have in the database and ## add filter columns too. ensCols <- unique(c(ensDbColumnForColumn(x, columns), addFilterColumns(character(), filter = keys, x))) ## TODO @jo: Do we have to check that we are allowed to have protein filters ## or columns? ## OK, now perform the query given the filters we've got. ## Check if keys does only contain protein annotation columns; in that case ## select one of tables "protein", "uniprot", "protein_domain" in that order ## if (all(unlist(lapply(keys, isProteinFilter)))) { if (all(isProteinFilter(keys))) { startWith <- "protein_domain" if (any(unlist(lapply(keys, function(z) is(z, "UniprotFilter"))))) startWith <- "uniprot" if (any(unlist(lapply(keys, function(z) is(z, "ProteinIdFilter"))))) startWith <- "protein" } else { startWith <- NULL } ## Otherwise set startWith to NULL res <- getWhat(x, columns = ensCols, filter = keys, startWith = startWith) ## Order results if length of filters is 1. if (length(keys) == 1) { ## Define the filters on which we could sort. sortFilts <- c("GenenameFilter", "GeneIdFilter", "EntrezFilter", "GeneBiotypeFilter", "SymbolFilter", "TxIdFilter", "TxBiotypeFilter", "ExonIdFilter", "ExonRankFilter", "SeqNameFilter") if (class(keys[[1]]) %in% sortFilts) { keyvals <- value(keys[[1]]) ## Handle symlink Filter differently: if (is(keys[[1]], "SymbolFilter")) { ## sortCol <- ensDbColumn(keys[[1]]) sortCol <- keys[[1]]@field } else { sortCol <- ensDbColumn(keys[[1]]) ## sortCol <- removePrefix(ensDbColumn(keys[[1]], x)) } res <- res[order(match(res[, sortCol], keyvals)), ] } } else { ## Show a mild warning message message(paste0("Note: ordering of the results might not match ordering", " of keys!")) } colMap <- .getColMappings(x) colnames(res) <- colMap[colnames(res)] rownames(res) <- NULL if (returnFilterColumns(x)) return(res) res[, columns] } ############################################################ ## mapIds method ## ## maps the submitted keys (names of the returned vector) to values ## of the column specified by column. ## x, key, column, keytype, ..., multiVals setMethod("mapIds", "EnsDb", function(x, keys, column, keytype, ..., multiVals) { if(missing(keys)) keys <- NULL if(missing(column)) column <- NULL if(missing(keytype)) keytype <- NULL if(missing(multiVals)) multiVals <- NULL return(.mapIds(x = x, keys = keys, column = column, keytype = keytype, multiVals = multiVals, ...)) }) ## Other methods: saveDb, species, dbfile, dbconn, taxonomyId .mapIds <- function(x, keys = NULL, column = NULL, keytype = NULL, ..., multiVals = NULL) { if (is.null(keys)) stop("Argument keys has to be provided!") ## if (!(is(keys, "character") | is(keys, "list") | ## is(keys, "AnnotationFilter"))) ## stop("Argument keys should be a character vector, an object extending", ## " AnnotationFilter or a list of objects extending AnnotationFilter.") if (is.null(column)) column <- "GENEID" ## Have to specify the columns argument. Has to be keytype and column. if (is(keys, "character")){ if (is.null(keytype)) stop("Argument keytype is mandatory if keys is a character vector!") columns <- c(keytype, column) } else { ## Test if we can convert the filter. Returns ALWAYS an ## AnnotationFilterList keys <- .processFilterParam(keys, x) if(length(keys) > 1) warning("Got ", length(keys), " filter objects.", " Will use the keys of the first for the mapping!") cn <- class(keys[[1]])[1] ## Use the first element to determine the keytype... mapping <- .keytype2FilterMapping() columns <- c(names(mapping)[mapping == cn], column) keytype <- NULL } ## if(is(keys, "list") | is(keys, "AnnotationFilter")){ ## if(is(keys, "list")){ ## if(length(keys) > 1) ## warning("Got ", length(keys), " filter objects.", ## " Will use the keys of the first for the mapping!") ## cn <- class(keys[[1]])[1] ## }else{ ## cn <- class(keys)[1] ## } ## ## Use the first element to determine the keytype... ## mapping <- .keytype2FilterMapping() ## columns <- c(names(mapping)[mapping == cn], column) ## keytype <- NULL ## } res <- select(x, keys = keys, columns = columns, keytype = keytype) if(nrow(res) == 0) return(character()) ## Handling multiVals. if(is.null(multiVals)) multiVals <- "first" if(is(multiVals, "function")) stop("Not yet implemented!") if(is.character(keys)){ theNames <- keys }else{ theNames <- unique(res[, 1]) } switch(multiVals, first={ vals <- res[match(theNames, res[, 1]), 2] names(vals) <- theNames return(vals) }, list={ ## vals <- split(res[, 2], f=factor(res[, 1], levels=unique(res[, 1]))) vals <- split(res[, 2], f=factor(res[, 1], levels=unique(theNames))) return(vals) }, filter={ vals <- split(res[, 2], f=factor(res[, 1], levels=unique(theNames))) vals <- vals[unlist(lapply(vals, length)) == 1] return(unlist(vals)) }, asNA={ ## Split the vector, set all those with multi mappings NA. vals <- split(res[, 2], f=factor(res[, 1], levels=unique(theNames))) vals[unlist(lapply(vals, length)) > 1] <- NA return(unlist(vals)) }, CharacterList={ stop("Not yet implemented!") }) } ensembldb/R/seqname-utils.R0000644000175400017540000002416113175714743016666 0ustar00biocbuildbiocbuild####============================================================ ## Methods and functions to allow usage of EnsDb objects also ## with genomic resources that do not use Ensembl based ## seqnames ## We're storing the seqname style into the .properties slot ## of the EnsDb object. ####------------------------------------------------------------ .ENSOPT.SEQNOTFOUND="ensembldb.seqnameNotFound" ####============================================================ ## formatSeqnamesForQuery ## ## Formating/renamaing the seqname(s) according to the specified ## style. ## x is an EnsDb, ## sn the seqnames to convert... ## If a seqname can not be mapped NA will be returned. ####------------------------------------------------------------ setMethod("formatSeqnamesForQuery", "EnsDb", function(x, sn, ifNotFound){ return(.formatSeqnameByStyleForQuery(x, sn, ifNotFound)) }) ## Little helper function that returns eventually the argument. ## Returns MISSING if the argument was not set. .getSeqnameNotFoundOption <- function(){ notFound <- "MISSING" if(any(names(options()) == .ENSOPT.SEQNOTFOUND)){ notFound <- getOption(.ENSOPT.SEQNOTFOUND) ## Do some sanity checks? } return(notFound) } .formatSeqnameByStyleForQuery <- function(x, sn, ifNotFound){ ## Fixing ifNotFound, allowing that this can be set using options. if(missing(ifNotFound)){ ifNotFound <- .getSeqnameNotFoundOption() } ## Map whatever to Ensembl seqnames, such that we can perform queries. ## Use mapSeqlevels, or rather genomeStyles and do it hand-crafted! sst <- seqlevelsStyle(x) dbSst <- dbSeqlevelsStyle(x) if(sst == dbSst) return(sn) ## Don't like that the genomeStyles is reading the stuff form file. map <- getProperty(x, "genomeStyle") if(!is(map, "data.frame")) map <- genomeStyles(organism(x)) ## sn are supposed to be in sst style, map them to dbSst idx <- match(sn, map[, sst]) mapped <- map[idx, dbSst] if(any(is.na(mapped))){ noMap <- which(is.na(mapped)) seqNoMap <- unique(sn[noMap]) if(length(seqNoMap) > 5){ theMess <- paste0("More than 5 seqnames could not be mapped to ", "the seqlevels style of the database (", dbSst, ")!") }else{ theMess <- paste0("Seqnames: ", paste(seqNoMap, collapse=", "), " could not be mapped to ", " the seqlevels style of the database (", dbSst, ")!") } if(is.na(ifNotFound) | is.null(ifNotFound)){ ## Replacing the missing seqname mappings with ifNotFound. mapped[noMap] <- ifNotFound warnMess <- paste0(" Returning ", ifNotFound, " for these.") }else{ ## If MISSING -> STOP if(ifNotFound == "MISSING"){ stop(theMess) }else{ ## Next special case: use the original names, i.e. don't map at all. if(ifNotFound == "ORIGINAL"){ mapped[noMap] <- sn[noMap] warnMess <- "Returning the orginal seqnames for these." }else{ mapped[noMap] <- ifNotFound warnMess <- paste0(" Returning ", ifNotFound, " for these.") } } } warning(theMess, warnMess) } return(mapped) } setMethod("formatSeqnamesFromQuery", "EnsDb", function(x, sn, ifNotFound){ return(.formatSeqnameByStyleFromQuery(x, sn, ifNotFound)) }) .formatSeqnameByStyleFromQuery <- function(x, sn, ifNotFound){ ## Fixing ifNotFound, allowing that this can be set using options. if(missing(ifNotFound)){ ifNotFound <- .getSeqnameNotFoundOption() } ## Map Ensembl seqnames resulting form queries to the seqlevel style by ## seqlevelsStyle. sst <- seqlevelsStyle(x) dbSst <- dbSeqlevelsStyle(x) if(sst == dbSst) return(sn) ## Otherwise... map <- getProperty(x, "genomeStyle") if(!is(map, "data.frame")) map <- genomeStyles(organism(x)) ## sn are supposed to be in sst style, map them to dbSst idx <- match(sn, map[, dbSst]) mapped <- map[idx, sst] if(any(is.na(mapped))){ noMap <- which(is.na(mapped)) seqNoMap <- unique(sn[noMap]) if(length(seqNoMap) > 5){ theMess <- paste0("More than 5 seqnames with seqlevels style of the database (", dbSst, ") could not be mapped to the seqlevels style: ", sst, "!)") }else{ theMess <- paste0("Seqnames: ", paste(seqNoMap, collapse=", "), " with seqlevels style of the database (", dbSst, ") could not be mapped to seqlevels style: ", sst, "!") } if(is.na(ifNotFound) | is.null(ifNotFound)){ ## Replacing the missing seqname mappings with ifNotFound. mapped[noMap] <- ifNotFound warnMess <- paste0(" Returning ", ifNotFound, " for these.") }else{ ## If MISSING -> STOP if(ifNotFound == "MISSING"){ stop(theMess) }else{ ## Next special case: use the original names, i.e. don't map at all. if(ifNotFound == "ORIGINAL"){ mapped[noMap] <- sn[noMap] warnMess <- " Returning the orginal seqnames for these." }else{ mapped[noMap] <- ifNotFound warnMess <- paste0(" Returning ", ifNotFound, " for these.") } } } warning(theMess, warnMess) } return(mapped) } ####============================================================ ## dbSeqlevelsStyle ## ## Returns the seqname style used by the database. Defaults to ## Ensembl and reads the property: dbSeqlevelsStyle. ####------------------------------------------------------------ setMethod("dbSeqlevelsStyle", "EnsDb", function(x){ stl <- getProperty(x, "dbSeqlevelsStyle") if(is.na(stl)) stl <- "Ensembl" return(stl) }) ####============================================================ ## seqlevelStyle ## ## Get or set the seqlevel style. If we can't find the stype in ## GenomeInfoDb throw and error. ####------------------------------------------------------------ setMethod("seqlevelsStyle", "EnsDb", function(x){ st <- getProperty(x, "seqlevelsStyle") if(is.na(st)) st <- "Ensembl" return(st) }) setReplaceMethod("seqlevelsStyle", "EnsDb", function(x, value){ if(value == dbSeqlevelsStyle(x)){ ## Not much to do; that's absolutely fine. x <- setProperty(x, seqlevelsStyle=value) }else{ ## Have to check whether I have the mapping available in GenomeInfoDb, if not ## -> throw an error. dbStyle <- dbSeqlevelsStyle(x) ## Note that both, the db seqlevel style and the style have to be available! ## Check if we could use the mapping provided by GenomeInfoDb. genSt <- try(genomeStyles(organism(x)), silent=TRUE) if(is(genSt, "try-error")){ stop("No mapping of seqlevel styles available in GenomeInfoDb for", " species ", organism(x), "! Please refer to the Vignette of the", " GenomeInfoDb package if you would like to provide this mapping.") } if(!any(colnames(genSt) == value)){ stop("The provided seqlevels style is not known to GenomeInfoDb!") } if(!any(colnames(genSt) == dbStyle)){ stop("The seqlevels style of the database (", dbStyle, ") is not known to GenomeInfoDb!") } ## If we got that far it should be OK x <- setProperty(x, seqlevelsStyle=value) x <- setProperty(x, genomeStyle=list(genSt)) } return(x) }) ####============================================================ ## supportedSeqlevelsStyles ## ## Get all supported seqlevels styles for the species of the EnsDb ####------------------------------------------------------------ setMethod("supportedSeqlevelsStyles", "EnsDb", function(x){ map <- genomeStyles(organism(x)) cn <- colnames(map) cn <- cn[!(cn %in% c("circular", "auto", "sex"))] return(colnames(cn)) }) ####==================== OLD STUFF BELOW ==================== ###============================================================== ## Prefix chromosome names with "chr" if ucscChromosomeNames option ## is set, otherwise, use chromosome names "as is". ## This function should be used in functions that return results from ## EnsDbs. ###-------------------------------------------------------------- prefixChromName <- function(x, prefix="chr"){ ucsc <- getOption("ucscChromosomeNames", default=FALSE) if(ucsc){ ## TODO fix also the mitochondrial chromosome name. mapping <- ucscToEnsMapping() for(i in 1:length(mapping)){ x <- sub(x, pattern=names(mapping)[i], replacement=mapping[i], fixed=TRUE) } ## Replace chr if it's already there x <- gsub(x, pattern="^chr", replacement="", ignore.case=TRUE) x <- paste0(prefix, x) } return(x) } ###============================================================== ## Remove leading "chr" to fit Ensembl based chromosome names. ## This function should be called in functions that fetch data from ## EnsDbs. ###-------------------------------------------------------------- ucscToEns <- function(x){ ## TODO rename all additional chromosome names. mapping <- ucscToEnsMapping() for(i in 1:length(mapping)){ x <- sub(x, pattern=mapping[i], replacement=names(mapping)[i], fixed=TRUE) } x <- gsub(x, pattern="^chr", replacement="", ignore.case=TRUE) return(x) } ###============================================================ ## Returns a character vector, elements representing UCSC chromosome ## names with their names corresponding to the respective Ensembl ## chromosome names. ###------------------------------------------------------------ ucscToEnsMapping <- function(){ theMap <- c(MT="chrM") return(theMap) } ensembldb/R/zzz.R0000644000175400017540000000076713175714743014742 0ustar00biocbuildbiocbuild .onLoad <- function(libname, pkgname){ op <- options() ## What should be returned by default if the seqnames can not be mapped based ## on the style set by seqlevelsStyle<- ## Options: ## + NA or any other value: return this value for such cases. ## + MISSING: stop and throw an error. ## + ORIGINAL: return the original seqnames. opts.ens <- list(useFancyQuotes=FALSE, ensembldb.seqnameNotFound="ORIGINAL") options(opts.ens) invisible() } ensembldb/build/0000755000175400017540000000000013241155731014634 5ustar00biocbuildbiocbuildensembldb/build/vignette.rds0000644000175400017540000000056713241155731017203 0ustar00biocbuildbiocbuildSN0t UAHi"q"iq(`I9!w3Y;]BHXE.>MNIӇl6>EyD 9VUxurEGXp*ON3nT >U]c h2irensembldb/inst/0000755000175400017540000000000013241155731014512 5ustar00biocbuildbiocbuildensembldb/inst/NEWS0000644000175400017540000003710513241131543015212 0ustar00biocbuildbiocbuildCHANGES IN VERSION 2.2.2 ------------------------ - Fix for issue #75. CHANGES IN VERSION 2.2.1 ------------------------ - Fix for issue #72: problem with Ensembl GTF file lacking exon_id field. CHANGES IN VERSION 2.1.12 ------------------------ BUG FIXES: o Use new defaults from the IRanges package for arguments maxgap = -1L, minoverlap = 0L in transcriptsByOverlaps and exonsByOverlaps methods. CHANGES IN VERSION 2.1.12 ------------------------ BUG FIXES: o Remove RSQLite warnings (issue #54). CHANGES IN VERSION 2.1.11 ------------------------ BUG FIXES: o ensDbFromGtf failed to parse header for GTF files with more than one white space. CHANGES IN VERSION 2.1.10 ------------------------ USER VISIBLE CHANGES o supportedFilters returns a data frame with the filter class name and corresponding field (column) name. CHANGES IN VERSION 2.1.9 ------------------------ NEW FEATURES o Support for global filters in an EnsDb object. o Add filter function. CHANGES IN VERSION 2.1.8 ------------------------ NEW FEATURES o New annotations available in EnsDb objects: gene.description and tx.tx_support_level. o New TxSupportLevelFilter object. CHANGES IN VERSION 1.99.13 -------------------------- USER VISIBLE CHANGES: o Most filter classes are now imported from the AnnotationFilter package. o Parameter 'filter' supports now filter expression. o Multiple filters can be combined with & and |. o buildQuery is no longer exported. CHANGES IN VERSION 1.99.11 -------------------------- BUG FIXES: o ensDbFromGtf failed to fetch sequence length for some ensemblgenomes versions. CHANGES IN VERSION 1.99.11 -------------------------- NEW FEATURES o Retrieving also the taxonomy ID from the Ensembl databases and storing this information into the metadata table. CHANGES IN VERSION 1.99.10 -------------------------- BUG FIXES: o Fix problem on Windows systems failing to download files from Ensembl servers. CHANGES IN VERSION 1.99.6 ------------------------- BUG FIXES: o MySQL database name for useMySQL was not created as expected for GTF/GFF based EnsDbs. CHANGES IN VERSION 1.99.5 ------------------------- NEW FEATURES: o OnlyCodingTxFilter is now exported. This filter allows to query for protein coding genes. CHANGES IN VERSION 1.99.3 ------------------------- BUG FIXES: o Add two additional uniprot table columns to internal variable and fix failing unit test. CHANGES IN VERSION 1.99.3 ------------------------- BUG FIXES: o Add two additional uniprot table columns to internal variable and fix failing unit test. CHANGES IN VERSION 1.99.3 ------------------------- NEW FEATURES: o UniprotdbFilter and UniprotmappingtypeFilter. USER VISIBLE CHANGES: o Fetching Uniprot database and the type of mapping method for Uniprot IDs to Ensembl protein IDs: database columns uniprot_db and uniprot_mapping_type. CHANGES IN VERSION 1.99.2 ------------------------- BUG FIXES: o Perl script is no longer failing if no chromosome info is available. CHANGES IN VERSION 1.99.1 ------------------------- BUG FIXES: o No protein table indices were created when inserting an EnsDb with protein data to MySQL. CHANGES IN VERSION 1.99.0 ------------------------- NEW FEATURES: o The perl script to create EnsDb databases fetches also protein annotations. o Added functionality to extract protein annotations from the database (if available) ensuring backward compatibility. o Add proteins vignette. USER VISIBLE CHANGES: o Improved functionality to fetch sequence lengths for chromosomes from Ensembl or ensemblgenomes. CHANGES IN VERSION 1.5.14 ------------------------- NEW FEATURES: o listEnsDbs function to list EnsDb databases in a MySQL server. o EnsDb constructor function allows to directly connect to a EnsDb database in a MySQL server. o useMySQL compares the creation date between database and SQLite version and proposes to update database if different. CHANGES IN VERSION 1.5.13 ------------------------- NEW FEATURES: o useMySQL method to insert the data into a MySQL database and switch backend from SQLite to MySQL. CHANGES IN VERSION 1.5.12 ------------------------- USER VISIBLE CHANGES: o Add additional indices on newly created database which improves performance considerably. BUG FIXES o Fix issue #11: performance problems with RSQLite 1.0.9011. Ordering for cdsBy, transcriptsBy, UTRs by is performed in R and not in SQL. o Fix ordering bug: results were sorted by columns in alphabetical order (e.g. if order.by = "seq_name, gene_seq_start" was provided they were sorted by gene_seq_start and then by seq_name CHANGES IN VERSION 1.5.11 ------------------------- BUG FIXES o makeEnsemblSQLiteFromTables and ensDbFromGRanges perform sanity checks on the input tables. CHANGES IN VERSION 1.5.10 ------------------------- USER VISIBLE CHANGES: o Using html_document2 style for the vignette. CHANGES IN VERSION 1.5.9 ------------------------- NEW FEATURES: o New SymbolFilter. o returnFilterColumns method to enable/disable that filter columns are also returned by the methods (which is the default). o select method support for SYMBOL keys, columns and filter. o Select method does ensure result ordering matches the input keys if a single filter or only keys are provided. CHANGES IN VERSION 1.5.8 ------------------------- BUG FIXES o Fix problem with white space separated species name in ensDbFromGRanges. CHANGES IN VERSION 1.5.7 ------------------------- OTHER CHANGES o Fixed typos in documentation CHANGES IN VERSION 1.5.6 ------------------------- BUG FIXES o Fix warning fo validation of numeric BasicFilter. CHANGES IN VERSION 1.5.5 ------------------------- BUG FIXES o exonsBy: did always return tx_id, even if not present in columns argument. CHANGES IN VERSION 1.5.4 ------------------------- BUG FIXES o tx_id was removed from metadata columns in txBy. o Fixed a bug that caused exon_idx column to be character if database created from a GTF. CHANGES IN VERSION 1.5.2 ------------------------- NEW FEATURES: o Added support for column tx_name in all methods and in the keys and select methods. Values in the returned tx_name columns correspond to the tx_id. o Update documentation. CHANGES IN VERSION 1.5.1 ------------------------- BUG FIXES o tx_id was removed from metadata columns in txBy. o Fixed a bug that caused exon_idx column to be character if database created from a GTF. CHANGES IN VERSION 1.3.20 ------------------------- BUG FIXES o methods transcripts, genes etc don't result in an error when columns are specified which are not present in the database and the return.type is GRanges. o Removed the transcriptLengths method implemented in ensembldb in favor of using the one from GenomicFeatures. CHANGES IN VERSION 1.3.19 ------------------------- BUG FIXES o ensDbFromGRanges (and thus ensDbFromGtf, ensDbFromGff and ensDbFromAH) support now Ensembl GTF file formats from version 74 and before. CHANGES IN VERSION 1.3.18 ------------------------- NEW FEATURES o New ExonrankFilter to filter based on exon index/rank. CHANGES IN VERSION 1.3.17 ------------------------- BUG FIXES o Use setdiff/intersect instead of psetdiff/pintersect. CHANGES IN VERSION 1.3.16 ------------------------- BUG FIXES o Fixed failing test. CHANGES IN VERSION 1.3.15 ------------------------- NEW FEATURES o GRangesFilter now supports GRanges of length > 1. o seqlevels method for GRangesFilter. o New methods exonsByOverlaps and transcriptsByOverlaps. CHANGES IN VERSION 1.3.14 ------------------------- NEW FEATURES o seqlevelsStyle getter and setter method to change the enable easier integration of EnsDb objects with UCSC based packages. supportedSeqlevelsStyle method to list possible values. Global option "ensembldb.seqnameNotFound" allows to adapt the behaviour of the mapping functions when a seqname can not be mapped properly. o Added a seqlevels method for EnsDb objects. SIGNIFICANT USER-VISIBLE CHANGES o Add an example to extract transcript sequences directly from an EnsDb object to the vignette. o Add examples to use EnsDb objects with UCSC chromosome names to the vignette. BUG FIXES o Seqinfo for genes, transcripts and exons contain now only the seqnames returned in the GRanges, not all that are in the database. CHANGES IN VERSION 1.3.13 ------------------------- NEW FEATURES o EnsDb: new "hidden" slot to store additional properties and a method updateEnsDb to update objects to the new implementation. o New method "transcriptLengths" for EnsDb that creates a similar data.frame than the same named function in the GenomicFeatures package. BUG FIXES o fiveUTRsByTranscript and threeUTRsByTranscript returned wrong UTRs for some special cases in which the CDS start and end were in the same exon. This has been fixed. CHANGES IN VERSION 1.3.12 ------------------------- NEW FEATURES o ensDbFromGff and ensDbFromAH functions to build EnsDb objects from GFF3 files or directly from AnnotationHub ressources. o getGenomeFaFile does now also retrieve Fasta files for the "closest" Ensembl release if none is available for the matching version. SIGNIFICANT USER-VISIBLE CHANGES o Removed argument 'verbose' in ensDbFromGRanges and ensDbFromGtf. o Updated parts of the vignette. o Removed method extractTranscriptSeqs again due to some compatibility problems with GenomicRanges. BUG FIXES o Avoid wrong CDS start/end position definition for Ensembl gtf files in which the start or end codon is outside the CDS. CHANGES IN VERSION 1.3.11 ------------------------- BUG FIXES o "select" method returns now also the keytype as a column from the database. CHANGES IN VERSION 1.3.10 ------------------------- NEW FEATURES o Implemented methods columns, keys, keytypes, mapIds and select from AnnotationDbi. o Methods condition<- and value<- for BasicFilter. CHANGES IN VERSION 1.3.9 ------------------------ SIGNIFICANT USER-VISIBLE CHANGES o The shiny app now allows to return the search results. CHANGES IN VERSION 1.3.7 ------------------------ SIGNIFICANT USER-VISIBLE CHANGES o Some small changes to the vignette. BUG FIXES o Fixed a problem in an unit test. CHANGES IN VERSION 1.3.6 ------------------------ BUG FIXES o Fixed a bug in ensDbFromGRanges. CHANGES IN VERSION 1.3.5 ------------------------ NEW FEATURES o Added GRangesFilter enabling filtering using a (single!) GRanges object. o Better usability and compatibility with chromosome names: SeqnameFilter and GRangesFilter support both Ensembl and UCSC chromosome names, if option ucscChromosomeNames is set to TRUE returned chromosome/seqnames are in UCSC format. SIGNIFICANT USER-VISIBLE CHANGES o Added method "value" for BasicFilter objects. BUG FIXES o transcripts, genes, exons return now results sorted by seq name and start coordinate. CHANGES IN VERSION 1.3.4 ------------------------ NEW FEATURES o Added extractTranscriptSeqs method for EnsDb objects. SIGNIFICANT USER-VISIBLE CHANGES o Added a section to the vignette describing the use of ensembldb in Gviz. o Fixed the vignette to conform the "Bioconductor style". o Added argument use.names to exonsBy. BUG FIXES o Fixed bug with getGeneRegionTrackForGviz with only chromosome specified. o Fixed an internal problem subsetting a seqinfo. CHANGES IN VERSION 1.3.3 ------------------------ NEW FEATURES o Add method getGeneRegionTrackForGviz to enable using EnsDb databases for Gviz. BUG FIXES o cdsBy, fiveUTRsForTranscript and threeUTRsForTranscript do no longer throw an error if nothing was found but return NULL and produce a warning. CHANGES IN VERSION 1.3.2 ------------------------ NEW FEATURES o Implemented methods cdsBy, fiveUTRsForTranscript and threeUTRsForTranscript for EnsDb. CHANGES IN VERSION 1.3.1 ------------------------ BUG FIXES o Ensuring that methods exons, genes and transcripts return columns in the same order than provided with argument 'columns' for return.type 'data.frame' or 'DataFrame'. CHANGES IN VERSION 1.1.9 ------------------------ BUG FIXES o Fixed a figure placement problem that can result in an error on certain systems using a recent TexLive distribution. CHANGES IN VERSION 1.1.6 ------------------------ BUG FIXES o Fix a bug in lengthOf that caused an error if no filter was supplied. CHANGES IN VERSION 1.1.5 ------------------------ NEW FEATURES o Implemented a shiny web app to search for genes/transcripts/exons using annotation of an EnsDb annotation package (function runEnsDbApp). CHANGES IN VERSION 1.1.4 ------------------------ NEW FEATURES o Added promoters method. CHANGES IN VERSION 1.1.3 ------------------------ SIGNIFICANT USER-VISIBLE CHANGES o Added method ensemblVersion that returns the Ensembl version the package bases on. o Added method getGenomeFaFile that queries AnnotationHub to retrieve the Genome FaFile matching the Ensembl version of the EnsDb object. CHANGES IN VERSION 1.1.2 ------------------------ SIGNIFICANT USER-VISIBLE CHANGES o Added examples to the vignette for building an EnsDb using AnnotationHub along with the matching genomic sequence. o Added an example for fetching the sequences of genes, transcripts and exons to the vignette. BUG FIXES o Fixed a bug in ensDbFromGRanges and ensDbFromGtf in which the genome build version was not set even if provided. CHANGES IN VERSION 1.1.1 ------------------------ SIGNIFICANT USER-VISIBLE CHANGES o The filter argument in all functions supports now also submission of a filter object, not only of a list of filter objects. CHANGES IN VERSION 0.99.18 -------------------------- BUG FIXES o Fixed a problem in processing GTF files without header information. o Fixed a bug failing to throw an error if not all required feature types are available in the GTF. CHANGES IN VERSION 0.99.17 -------------------------- NEW FEATURES o Added new function ensDbFromGRanges that builds an EnsDB database from information provided in a GRanges object (e.g. retrieved from the AnnotationHub). CHANGES IN VERSION 0.99.16 -------------------------- SIGNIFICANT USER-VISIBLE CHANGES o Added argument outfile to ensDbFromGtf that allows to manually specify the file name of the database file. o ensDbFromGtf tries now to automatically fetch the sequence lengths from Ensembl. BUG FIXES o Fixed the function that extracts the genome build version from the gtf file name. CHANGES IN VERSION 0.99.15 -------------------------- NEW FEATURES o metadata method to extract the information from the metadata database table. o ensDbFromGtf function to generate a EnsDb SQLite file from an (Ensembl) GTF file. CHANGES IN VERSION 0.99.14 -------------------------- BUG FIXES o Fixed a problem when reading tables fetched from Ensembl that contained ' or #. CHANGES IN VERSION 0.99.13 -------------------------- SIGNIFICANT USER-VISIBLE CHANGES o Added argument "port" to the fetchTablesFromEnsembl to allow specifying the MySQL port of the database. CHANGES IN VERSION 0.99.12 -------------------------- BUG FIXES o argument "x" for method organism changed to "object". ensembldb/inst/YGRanges.RData0000644000175400017540000013416413175714743017131 0ustar00biocbuildbiocbuild7zXZi"6!Xo5])TW"nRʟ ,bDGWCJobb3kb.}]h}.kdBY; [cIIsSЛ*!z}gwM0 1a`&*,H[^~?[c9Yta>DH,0ʊZ,TE拵 Fz#Wn-QԃҺ)wxC5sLDq%Al?>lCdaەs~gޭ\)̶$˒ 4Y.0PE˦j}3|1_s޻:{(xk K;#|&H7`iKgBH7>|41r qtlW JLi {&O[y/gbN:YJ=^*qVrIU Gm!7ư ȮisJK ĵ5 6c qQ} DuH2Mw֪dFa0ۿB't<- 9;k)-*i#!asӠ XݣH6"oygp~TT6 veyƑM$6Rgس_Ka tx9w{X$Yj@-uǧ)kpkupgށϵ`Y?tBO],շFMfv$rJSz(z Dzvk=I7bG'F-% Uߘa.0j&/\X@i(`5y@(Ǥh 0 5ga+8W A0~XF?H$Z-}/8Kݙ/i6CW!-`b˂;D)]KG(*ϑ1j 7SPF[|$RkwݑvfZK$$^= J@o*vi.`=0xK+S֋No4/2Ns{<1K a Zj$kʽ Sawbhj93nr6[U m0CY:g=,G_kp$ڦHF[mRSu'`BHv;R , PH שn==Ogչuk('㗜pFUuT UFXtu>4o'EȣQ+q|5@-s<. db:}< iaOK 9~UA;E/T=%Hnrc0ishV=[Mڕ?iS=/}k'O$9^AׁHZi& ^{̍&%OmwGW̛OVoN:d0?j}ڰ0Xd? =0b1ʟ\nQEgUZuݶP`YW.\!!8ߓ fF_1DYFyG:evv_".f4X}{>v 4 6)`pQ4r+qʍu9h^+hШpoʒ8O+jGȎFZzs!y)]ꫣ,]P$/b [7;z0,VJWD3U'F瀕ku;%"&+SQ7Z A^TLmf.-Ua ~~w]<1(j$Iz(LXB<>z ƣT1n 5PBxvB9i2TgLT*W7WR08z']\Gyxkc3V Ë́] K sˍm0!CčQ׷JX,S*> d/anJ*3ZkeH$uQ soPw+V泿u[1ùωx灊ftf}K&xë!#4ISި,\uA[֌/׳01?V6{'g@F7ڴP \V137!YJݤb"Mh&VRۗa܊ߡt20K`3*[דr1XK-MAhCw FGD[m|KqTFܗMQ$l{\$y*m%,z<^m&ô-Mĝ>401<vxmzs o6Kq`-& 2]Va8+\g˴_a-G#fpbmmc y-H` ,Wz-68p@/KO3j Mږ7pe$Cݏ3M[7-^=O&d&.gX'8aVctYN >ǻqG"ДǛPr-ŇKF!)Zr/LeWxzkGP,qYP c$ }K{n+$K.uugCX1umzw@8Hu <GRU6+y(iǯ%0"i009UK',U/לf`yFeo=m avR=ѺX %pL]Qஸ1漈v™>IGnə[X#|qr߰ak7 IJ3Xď2F㺶Ő)޶4-bMp|bMw 涖/F<2 ϸnQ"t;'>#ϯ.quP71eO;Ɔ `Lmތ?Z=R]ˍjY bK.sp pqox[@>%WM䨟xX$@ŭPT yc(WLNsQw=6)QqHդjm*2]qx^aOXa[Qw&|*$IB̵ULSw2RXefD!F'i* M:\. mH0xHcFwZfѦv!zh4-k_{v^22L4V1תxѺd׆aymdEa6 \%9!$_J*ΎkVb.ʟp\e&}rJbd]}}}ǵ:T.Kzyc4d o;{T;o<]<od,b?nQ 8ؾZqWH7|m`6XWLj1I63ާك  2eCyR\HxխXEp=ZV@9eqn,ré P;RC^l/+X]̗~9(W26,߫`F}VKKjSNT1_(s;#\A.0r ?y_AYFgdF"Mo1&'zj}ݿ@'DHZ,1 0CgLtw!tӜx??!ĥmFL}c,s$tw*u|\uE&Rn~<;=Y$[l.iB':.񩬺]0˔xL fmZ^,?2D-(ۼhh\qIp88'WXj1#lR(RXMo1+ QE2 V%_%Wx$ mzq`zq 0<@W;Ѿk=&eXdQ=; tr(ÿn;l.SsXJTro]$ d>WGBŌ}s%.v ^a~Pl8TNYS0u;&&TD^ir)=ot80b鷧 #pa>eC[w_+#X9FǥO||2Xdt;;0k-AXF|Ӏ.qfl,SLm.)0Ig wETdŸ+x%z9Lxdl[ҦtIM@H 8!QH=H@雇TJ\nD AHc D,U)g`[[A<{HzMHF D-Tjt;YO)JG>6>K>6%Dzl.HBO1p<"=!'D C$DmK,']en: YsN#X|Y"b- =jxxXaL_¦~nc7BwwHNK0cEpj!Eƻͅӱugƛ s xqfw`YT'#6= iIh̰t kXh.tY`uBv-TDm%>_V2kfRb:ۓ8ڄdXlDvD9[ XĮúē]FFlN)9jΣ`;l4(۠e΄1Sk֌ow՗v+ڜnГ4E~}*)KQuk8IEDf]$vUèQ.U$6"/cz7Wi^$Mkk%l'2LSK'*z>In&9t)c6{[(|`>R"О.pvv:7p}ܳ~}GIc>*ڲۏAn;mݡGupM\['o!R}dfb&=<%Ţ*v i߶ȏ_a'\ p>_zj%{-f76f?ԣKtKJN2ʴ*$Fxqt%Rڻklʸ%N/("J8k>tV0/~J8n ű)[GE^3tr{I)VALzwx$jռT&N˛dv ۍCb6(D@qJ؎-R"iubQ$=aYX[Q͝O#r $?o?J8 `4(jCW,Hڣ`n$ƻԀogSPp+mG0p,I;DN,) f$BċfL&: Wc'uB|`f,/˲&j>Z -7A xQ,cs1Ck֏JJΒA9܉?gdc:vKϼ'hA0Az3$%Jē|N3 DkDz$C3S4cL4L ОS5~f^8~3M\e| cSHOh}?Ff0q7 +~+m< =]#>DD9bBl71 SlZ) # C (1+cL2;,<=MÛI8}~k ,ϽB;"p^Ae!wN; ,#<5 AW6 [pdlkbۗvKHl6OXDp2AL&]d 07Tp7P4ng=D~zV3Z$#&Ͻ ?O76ŋXe诘՘q.)MHE>FteH%j 157R9cG_ey+=7t>-˔qdΓ\_T3-{*jq}`Q*m,߄]ON(c N %k;U93"'K蔊!1PG)d$%ܙF|nO.Nt]F'0~T @#2(N&qf;ҡ0҈&~p~fayJŏ'3U~^*d ꭤ I*"bÖZ2\E'IG}ܯ B"2 {ٕOEi5Bth<%2RX8DEգ +}{c\}ր[#"?oVU+?OZ㡝byQ1yR! !zusP[ëJ{T27,w=HTa%psW M{<@r#~!%N͖vv  Q916֑I٠/.?~q9V2t\85 NpR")FKyx(1 nvb{kU\A梶u #S dLm@ d7}˛W4>΀:!}V~} 7N%1OnxV} }Cm[vTJZ}Noh<޷TѴq1ܕxt+iYtk(y1=Z%"Ww߰P@c ) 5e&c`  v8bbmE_LYBvX{;%G%'l=FJϪę2>;ѯT0d+ccy;{"5C$ O@_)B\{8$7ԙ'nC)y&>WeVҜIQP;d 9? wU|SKg8@c+i-A- VW>̃E0]d|g\B<b0P*0uEY䀷n.ۑcI6"f9E.m=xs: t&u7Mݖ*:fE&@= ~:I;gLWD}P۳]Xl'x/\Pvj|NqFP] DOT/.i[ \|Qp1D|2qX:Vk D6X"c9ީMUtxW!56i^-ޕ-N J&O]YS7U0ص}bsv!Y\{XP XGZ/^'V9H B_נhg,7$, e R~9!Kmkt婿ݛz[͖ήH z5c3!L+z3Oemn G ^{< ܈n'oU7 3{['Qǧ1ۅݎ7D:joclΚ.ߪ0Y5KWiN-jm:=ڼ!PH!,|E $ r-GuxOT[ _<ƳvaKTiq& }^]Aga7=,\V5'Q48nG}]]C>I y?)2$H E ѻpN}\mD(}g Mf6'VA>kCfŭOj\oRJΉ޵V0L{HY-~ !lOX[h/NB+ݳ'R.H$/F<9o$Ʌ]fNy9a07:t+(גm50Gą//K5(p!ܫCiO20ݚE>,/4̺ Ƀii9++eGJ t u|@w $BAp}5XUZ VHPI,XD 5b5!by5N xS*[S}af2"iJQoxs ne5ޝpnatBhK~Fw%b>K>~C&hg^vͯ TSOƅ"気Y_qMJҩdY *.w |GO97%Ua/bai+_쿫gH&fί}Uh,3.>oTNu)S<4 qS#|%ޟi^VWxdJ} ,@op_30G.l?]etY n>< Z> JdR|u_ӹozJI+#^=2>Œk~b7I>X`dn!̂oeKzq!`Z3é`;Ѱ}ǵ &X̪Ň#N{qљׇs*(R10tVtҏv|O$M2j{[(Tc>`ɕŕț4AIn&T1޼{up:>[xiYCkVuK͖l;#nx |Ľn%v@EwX#N2^dY"{U?G[mWD h=_91RY]Cns9_(oxI怼a m  ~,2e5Q*47 2}/4f:=&0tR7ve4֛^Զo"xNY K⥈Ye d%J0 .ˑenǩƻ VHkPן+J@Vz]3=\TGv}M42EUN.^; iȑFOBh\|ԲWZȬ$Ɓ{XD͞Q{M,SG643z<—*nyTz_ boKqO`QГPӻ>o!?Cm=J`04P9!3Qm0;3@[P7V $H&#Dٍ'~`^?.7k*m`dG21P ogE}^KW&KbE{oD@#Vȁ&1HG1;*4в@KzBA4RRfk'JT@qRUlWjWWC;|{zfys,!3Mh4dpi mμɉ!E`I'bmh٭“$;{*((3?a5ȩT̆HuAV?NjЖl4h%Qz{,r̯3߹8mK w!Y>Y[M9<ٵ 7TX$)Tm`Nr0DzlE;zjEpPq/'lPe]y2{;ggQ8ZU(\ՠ+h#)1נVa.u8:錚1:b>xN@>Ӵ(43ˋ<*-nVVd[>[Р?!JT5x;<1Ø.ɻa-;B8M6:RoDv+H|&|xq4a+ʰ@rr!Ԁ`i6-fhݏ31[o0(UWa4Ɠ0{'wιxEeTHkv>RTg.&cs"8mj97 LB=3 /$}|WԋB#$|RWѭ\\&9ʒMuH#Ӊe9z{9۞|ߋ7,7SىܓQ-S7kk:\+ؒV*`k0'<,lh.Sƛ-RS/=ĉ^Icよ%dܴZ ӓ['x@5 Fp;ERI)UjxD?]sr5$K=RP\"dȺ ej9݆T11^7eyԶ:ٌ F])j/xcD5C^A!>}#ʱo^uowClf eۉpCv~Pc&/f<(eEyJ-cל0U#)(\HNp5fgv;/B (l6(wgGkaפ: X̏ϒ0M0xFWj3Ț,-t-a9:J#ʨ7H5RjIW̗}[݄lvʌ:D8ْhZ.;&Cio~ꢟ0-WB cj`~VQR5E aJYH7/#U> M@b950z3m96Ie(m7OC3I6`۔z5My[ɘ.lQnO?Jhr5EW9V|ƭ:?5ӳ[!rρ/02FtoRC K3 Je`|TMpk em>PDHD qa|#Z>_!K;ຶ"B͔GNѴJ''GPN&şQ$UEwaULn:E>uvZ[J/yՃqC?ny'a-0qHj/pT]J(U^_7Wq2=qK?,U`3Y஻XAS9&1I`qȹJ4&f X™,͞PRZ^*xb*,cƽ1;XB4j^e.ڤ©&!}WWIAע~{UJu`f3=+ *= I+;;mmgm2FRuJcvh J/ӟ0L0~,oubx$@wp[;Rv+MϠZt3,LS w- z5JE"BN"`[\ #g]74{4qX;3mgM`|2٥!'K-={pwBgFlm\F[VBV[^6:L)\yMw^0~+?"NV-u?'R[Gg4*vT#(U44:$'넴dz`@ v`^VGS)~'yWHvSx瘟x "3AsGȪt6 ߯fi.fF{Rjz = ܬsewsઐRWcU*dކ|xT3-"ᆔլ%$lj[u@Ӝϯ6U~%k0ī{m:8.-+ޣhcq!1˪w᎝Q1s'^oXsVkOp헜&2I%F#%kٻ.%a/8m Vt!Ed8^l͢w9>k0ѽ3`>+z/3D:BXhPcd2"5.p^*rxo:ЖCG1AKު^i7 =ۀ6FҾ1Hn?넢R+^$)3&9}n VGO#uȚ5! Gb<,Jְ0D8TyNf79WAB(I-~ lA$m5QuAhhΖD+zωv p1_qۜZư39u~K0۩BIc,A;jjOɘPҴf$pSf:'=W}lBC?*!-T1㎌ldC6ٕMNHT#7l9ThzS0fM'xstH9ɿ#5>S}'Q'[Lk^J>'DFy uU4ω/  75U+ ϕyUp?S4q_$%w5OCzu QҩSKv7r<hߋ5rzKh`gdiVOH:|x'#:ae+2ӆ}bd 0St(b\xy6_YDԹ?=壵_聙"OLX3ӻ:sy'` 4Oh5ծ~a֛cƦ)7f%Ƙ0YܭSL?X-BRDpu,X==†vJ@l5Mh7s[>P0`՝8ޕu? Y^Dȱ*en;8DS>n2Cp'aNUcP^H g~J%?7M9L0[ Ui stcuA^E?1۟pϞ |\8rY (0pM0eRSDthZ" AZWn*XmU'}NoH+f':scQ YO-6Ylu}57xuNH[H L| !-q/("]KLZbOG|2R2' {ŒT3rvjlaԋ eI>#,¼/ 68dV͎#0B?w9c ) B"Ruƪ3OMe%$S2;j,'},4cdZjn_Z2UoI*;ʼn&K!goK\d|e1e*m9rOb"1A!}*"H6AfK3 TZsEQW|+]?rq}Ό{=|v[N4s"Bu: ٺmDcҎܽ0n3$.7BAG'#RW]Yoȴ‹`vhdcb֦2˺Gې f- kl]bF }֐О8.1U8 pC TîM5!>G>~^yi1n5S$˕|\=].jk$j(3k/S2ZdPAEfp踨=7Z0&ik%DRbiԵk'aC?,$WʷIsrXݝHmDyUn\ÆO]X@9Sm!mlc`3,{: *`| &Ek,"6Xl{twҀTڤb}3QvQww'e Ɓm6vu5 ,bAIVK#j,jHBq"hDzŽ:֤{r<ҥj;yRs@CcIT=˞شSj֛AG>mv*g w *沸J3=0ѠOg=3F᠓X2apTY.vT^?j>ĭ?JxxNPGac/?f8\iKc~3%9q( ˌ%Z"o=\vggx+xV ʺڬM`< svdOW4sGxFc [ؓ5z͏6ۋwrВc7":\z)FڄJ]ϵ1! AcR0B|-L!857OPP%H|u|zIH-'`K/R !dP$ .DQ`50:p2܀}QK}|AL\HzC +SN/Ynd DOZRMx;7C|bs04(~>̈́ia{(.-$eĕ;y_#])pJ-hka|ǯ˸Eni鵭R%fl=3ȭu<3OEFAl-sThAvc wNbRCO -("%5wGKƢXBݷ!G}j-G[`,e-s˟{~(g6}ަfU@] u.F-Sy"2)NO!RZS`S~5rDuy,͠^ރbf[O2%K@4Wjw?;/`C\SIYXX2@mg%DW tu*/ưV7 0ߏ޶_j+pW2!=,A$GBF!Pݼ</$[~~8 64L1| $7 -hjQgJEp|;1h'>:LTS 3J\)X"NrCX; ~jyO!MVo~rSg*'G04IAoM9mU$vxQE҉y[AU,Q5)ζ|BgGվp[F/7#:7irT"x7> 3Oq!WOs_"EO$: %1PXte1]0gTwOԇ|*V/psEiiv.pIfBrC:j`g] ET3Lm깎ehVɑ洎KdHr=E[ހA0hg^Klj%P2"SƂ 9 HAb{s]rSOcL?InU OQ ՛LVBPiOӿ D+NCZf_`x[>V&αVj^m?Fɠdڶ!&E金f4p.YV֙'T0(ѬOxIn-6fc!#Q|Xj'i6+&0ஷHGmbo(20C!ьPĚQN,"Ndo}0bC7m\2Iݬ&SCOyڵ SWc;a$l y1S!WsF!w:}GL K6^]uve~},isz+xiv9KO|8Z!g1A1MP KR =AE, *gr ̾`%\8({q ʆXͅ3I@wGn'u3Yi^q{xO31g"< 2[?VwHGmdE MAs8N5q+d;n= pKC#EƆZq Lv2EC@o$''ⅻ% f,&Z )MTN H=g/p=딬~ÌrDՏQ꼝%w'9/], F< K!%g/jAƠ>Dj8)OY=b ]Kr!P =CivEhh'eIE&JZ q>*٭䈑mwo80 `xa 6|HS_8I[G̖U!I6JB6,4ip Lad!MN_+=3(c- >bM@y[&VRZ#х`r7y:l8e s\knAhƷƠq2&?[tLpNabft c ^p>;da uں Q?"tD&#yE%.蔡hܠ]wH'0n-d?<T3qkQ>gܳɻS+"vÖGl1?s^4aeR-z^2x 3U ''D!jݴs]rsJ`t%8[ן>5I #eucƽ ;+Rzt%4?6X!d09[¸OI15l}.'TT*su>Q{NC*2 L /mKb~8_߅lDqP Wm\Ĉ5y1EKG S|(A˖M2U 14;`jaZ>4Үe΃Om~;CPPlO\۔[DC} O!OgŁe{45XC|5Jzv^1Ss ]QrehJ.z3 -VE4xٞr"Mw4gta4*w4Z^cw^x9` 8 e(RsNtGFyC+ϜiTvBıZ"uLI|$VP@zv]_z/z #ݳ>PG c>pv*dR#jQS:-O S1R@6YHUVG3Vc .RfuhNj2<տ uea}/d$ Q::xcB|Np?\\c; 24^ lEκEN.Q% Ĺ|_mA"UnN^U5:m-q_t1[˅+9&3p曠Jo@]lB*~( R&ͶxTc,o^>LKGoZ% FqM2 f? WK-D}CLyg:x*C Nˆ~'`$&\:& i~[t7C4Kul'xLyw|CGm{ YTMX EHdbor\tG͏Nrz-~jIg=bql]š5vߢk $(<ڜn6i$c1iݼMFAq#\dۑe[\gd$r4Qg[CO2dg ./uZ6? ?KHK~M qp!RIƿN6=jMag6#=/`#!4>C{:C4O}'K oB.{(ejeλ/lc|)&ROMϣA0uEyFMdm"m(}o ? no.*'Yk%,|3٫\8la!'[]^UD=C+BEB>7çfIc;ъ~TCY8ǓMtco^$A΀mق*?Y18єڮ[< [߶(ݵ[3G"Eh"VE՛mvbX a?d ܒ~>hʛTl4eFFjEtnU TK^Qo8RIl[[5pŮ xH ﮪX.p(v`Pl5q XÛ*?aKuR|~O/[;qva⸺Hҋ|j7t 9de:k KT'bO~Y!bb>yǂ`vo&D]ESxSZ.&.s']<^D-h3L'`ќ7m{ Wݷ@ ;:C3c(˸:"xKSCZJ@׏kaooJ UNH\r-h%h60Ľ:IS"R5;a[(aj;.~(L_Uilhq +xAf@RO+UQʡ;.j}bm܁1R ck |Kb(*^!P%yUSH3<ZmpeN_0\~:{(A,eD&3:p{'/2d+ͣ|PLq1Lp5bNY6;[=D4nol2PAô> 9QRsL/y7l̐Խ W&7(%0&\2-Ӎcr*]:F: ߠVc3,}z۹͡F1p3I\ע %sa!>UoN#a흥%RG_T%hK:?D{j* jk/X[<,;`!2`[UCRɑ4uR;yͺkfdYjmGަN,Vb`6|ӱ*BO26ӬJ UOXH*B2ӇĕU&$gx1-mXL`Yj@Ŭ+>63~T>%h>2.|v:0dy(>}?1?5JE[+xfė|)V#B|=B|:+DYqM:Hn yWԎK ‹]k'!Zrq>eyvR'ȼ5PGbXeœO,(j]TuN@1[@bTg g3/fQ%W.9-nh(9LX\#hLd q_^wwOui)Rg2Cֿr|u{ BQk/Uo4UؖR{wT)ĉU54U)à vPu`3E`dRB ovqdr:h @zY'K#)J,Z ګsUĎЋςjt3b^'oN:tȴL98q 5 R>p#9 OyW!:orIꕅuO9E9Qng+cC3^$;0!Aʕ@:ZD"\\6ft𙺶 >ׁm>Y/6!/,ebMozWtB#ɑ tza{sכ"xѱ ԟ1JZNC|R^o +\P*tGfVbjF{ 쁷h B3%[z%$95pX*fJh38x\%`Yqrǰz{}P(E.{*54833'OcK& |{^ 5 fEZ1c3-ɴB*v1RbD8NtN~yf~#=~R%|LTe!XƍpcP3ߎn_Uك"ӈU"B 7U )mB{]E ,{OɆi^0GٟK> u Sv[H&m`TA~=Ojfny:܆u3y'e> z9-5{=軇/l-\{W*0`{R0𫼇,Xqы-{d鷞PJ$ޔN!ϑߊF(n'+́8:SY ܣ3-=3}›*^J緋[|Y6ߪ,Y|).QcՁ!ycE08! u[[Ro2Zc8.~DTv"q*Y YYu ܗf._=(dbSP= dqR;fHؕ7N,@;đ9c`@*$4Nw#A+FNKD~NݚW6<|nN˦n+={;2,>Dym::Bq&{.iD̘jXG|֯3_l᪂Mn"QW{+|e@f7;(Oѭ'DޡT8kRh M",J}OzmTHJ!=PGqS@Xj8z9e'<!_r*0;`h;V%GmCSX9Il2z!Y" .y/L?]}y1(V'ȼh s%uKr,OiFOo5W͐k< w8|1WJSjNV`Rȴ(N>Wx]}ՓFcuy g.;9}6Uڠ9fZ {\]!NѲLz/}n֘K8ŲEp ?K4֌񹟚9\wOlNȵ d:\Y$C")0GZKCFEAfwm01yN^Vjv'ofӍ amf>v[`e ˤs -_[9DlhYmOzoQ)j<,JsZ R Yx ]4Uᯞ%,$ͩ_+&?l}Or"smUs ZFE Q7Ա?l_+)CKUIkJ.gOS`] &!YC1P2j HhɣH.0Ɗ#I ;&qk[1 *bps)N?6x,Q&}#ݝ;sL5h~?ml88ol.܈ƍ\+>EXx1ygΧŕj,?8zD$ ЌN(e6ͧ7|!%Sxtf]i7']3Lm,9ĤI.},6cኳ|VI}neΣ' Y*ګy'nu.um:yj*K n/⩸.+"ςl`5#[@CsV+Y\( Owp~8Ec4;p׹|o[w'+pWJ0 \T"riܫK1`2#iOzyxU?)t2 HFu^I۽RZ4MLB$^vTo $vp}aEbt2T(v$*н.*L&6g[lAΚMf_q;Ry /dKy6>ݞ9(xoHfû^T}ʿ EYVǷoᛨl1b Bp{YB㓂{ց9cY/W JpsGhYo0R2Z=.$:S={ڤ7~$@x|O|TM@[bK%ёkVvxn|6Ҝ MaTZ?&WSPd(t-*|1SjS1a}w>t`^ - XJWkyvއ'՘=kvU{ s֥ud##;;ys?s ĸRC.Qʤx[9nY SpJ=>X(u@t]o"WUY%sb}D7߉eL^H!D~[/w"CJ9ٟ]gB2w6әʓ5Z4%KY D HK (o57E=أM%4*P@*/ BUf'7ߴsb /,vy2{{}*P;FLX~¬aD*HR)<)fo~w򈗪EC #e_DJ8/|<{(*\>r#9䱾 O뒄TeR\ԙ>GT'1RE {T~r_DPqND ~祙Ãc.+fF@F K$进!\1 z=Yl{TEqD b{^dieXL $OEڎXş>\؄ÆWaWx@׳:0 %FxI,  xUfV:U智vAZSkZ\Cb/(]];U"rp:cX۳/bT~}b3 ~LE#T]s(CXGֳII>XPʝ"SM@yWcI<4reHcB.uCZ#^DU,;^|EٯyhUle?^B4ffO &(օпmg1$FGCv|yڿsxJNcklr0Ν98'Ю{r_tddCռȕaeu95SwpGFZʹ!+bA=C$ 1J@z VK_rA(;Wp?a7l᷐p՗%mr-sbp^!&v")uU;,~~~śԇ~yg g}n5)'SIUv[^B*M̏z@ݙD MvxBуϗLpYoy(h,g= ewׂE8a(6cZ鸓:XUV#\ySRjAriOɂ09N[2wIkߔ|붖8Pmc4顲')&ḻʨw}^Wkuo#!qY;qքN'3( +P0#'Sf:aCa (|;2VLE'R\Hk3ev)pkgrWCazK2Rq^N"UU]&e/@wt1=l,h"%-VJhgELD.2UV"#ˏ?&k oo1{o:aBU~4a+B TL!D Y[35gI %}ʬ.TǗ٥aN]'%\ ۈb"+;&g8Ec/zkKآR(L{['G͋%=}(9C3tJsm)h)nQBǓZ} G~8m6ci{@|\dt$pU1VOy,ěf%K?&}꾈 M^X{|{"| .0DԄ]KM&lz(ݍ Da= R KrG& ~5[a=>M\kM%:U/bs&Q\i}Ok7{ CDu73lDUX:g$/N، #/vY@brN~,^b"|Dsj3>5"}`Pʿd#2:CbD15:%AOES$T͞Ě`FĘzj?(f=sݒŕ:f۰}P~C!!z 8 s2:b\l^&DDF){&#SqP&MA;x;&674p:~(Dd^ŭun.3::qn2ֳ|xѫ P>MYqr;]q<tFYV~TAi,TW#tjAU I_J9ġy?]; _\E06u!W,49#M?cs10qv+6|UϝG XJǟ֦?0A鮇#Nj3K0Y[3llcA]+j֗iDy+Ve֌u r chfOȆ#]~lJa* f ;ߏ8Z=)FP^L(8C)F)&sEěpMNFf*P6 Zˏz,Hhx]U6>.t5(|`;UJq E+ujWoxD䃔}[іex4z[m2!ri""]]VAcuB*39rD[3Y4d(b&;'>;0 ld;UNCH/8o@Kֳ-B"꧖ccǷ~MA K9% 2CX:֍q~ LK~1Sss1 'v'j_0?L yUoE7-&U$?/a^˴'%~F,ֲ#6`uJ1pΩr_OM /-Îu,Ua/x/n{ ~2Ҽ^PH$y!k q3jl MܒH6eJ-q́Cx| *LbSTYw)/3p;nWr6UvQ&ZyLcuig/~fzq1ZLE@;+:0OHpu,mXj4,_@AmUbH6}diC,D%(eC#Mo3#@ES˶O©D_xK@o%1DAЍnQz~>ye~fM熅MtA!IMrt^3g4ҡ6Iɔx*U~=:2;})|@|2Vgggc?o gغLDRŁ&]V ((E JGj=m(FlkW>Tj"Vd)!=Kut"y~o2bw EZ=߿L\/%rʹXɺp6/0")Mݼ,z9YR3Kzt}b.s%UMWN]"wL0x-FHDYWvRjz_}uF'`3^ZD}Ԑ>H.1q)/Z$T}٢7))%1uJ9@0!hĴd?2Y@}oYɳ.,1(rjOʷz;fSAqߢhڄyy80ILYG:? s>ʎZ-V5?}+:z9]/1 ~Q3W-)!3Ӟ;?7kt+HDx|㙌;lF]>ii?.HV̎B}cgZXHiUƂwn%dGKV UUQ(K{~c g)\x`X4Z4`k.5ggn5}-4Uw H.E=yWKN`$ۂD݀J I.mMWbÎtgV 8&4kx6<?Y684}HpX5HR@h`Hԑ3B#x0v&fMG~QQO2$w3 i rzv9w,[71Nzȝ|:;ָN z˛>%-%Rh,OWI+F9znc.8cON璃W>bTLxߠBpsl7d$ZHT=k[ᅙ&ێ_cyT5˨(JǙտ9ńD4 0ddabcIO?Z^?HwqU`*ӡ m2o=%ÁjrϑG~wd<3Pa}~|B4tEyg .b) >* o.]^bU| $[?塦yR6]uM(Z%q:z%[ggy6. #[7Zr 8GST']Tt _"enʧ7`$ țҩ^t0(?F="'dm4belˣݢ?VR ϽzaW D 4mLPkLcTSl|5$E 2yDeB3T]Eb-|^N3ΔIp6ͣ4]ABZ,3`tUƄ:&qBܲBEѲnѭI"HC!+dL-a=\ik9 T&NOGq}=lr@V!d`9cspxDX(O2d;B{jN:Yk%OQN~YhԃSojUr@-ph}d3=r!Mkske&/QSX>) ˅hfUQt6_h|Cqo7"4h9rTKfbXcؕp]B%b ֧& ]ṁ,Z^ k!7|Q1] "[kF@@2#־Dô {e3O{?!"&2|nюJPu$W}^κzJt/UJTRb :e[5+؀؂B64(G;А xdGX@)csy$g-(N~e~V1;ђAq푣Zinȳf5.w?p4@+xO E(m <+}e#Nܫ!|Q9aN%5]-G_WU9o=Y\;\3a%&KIYVhEH@;fxL~%pH8mB8ZqƑM tm2T'!I#EJW{a(WZGE䛌LzDoc8+nU2 -\:MVz mMqȭAlUn~Cf[z8s Rmͫ>o`Rېc pޑ֓!^z)1k .El!뜸Tp1$9XR1d:hSlee7zRF/xUɗH欁Ϩ?Ɗ޴]|llB鄟9峦LE_7+z-,%6MOx4՜AH(+OCH?3u@3liuhYQk"ۏ^$_(AC`OR9(;lG.R(T1V|R]%NZ$F8wO|'yͥVt@L@h{N QgHp*h?@jy_ֻXDoʇ@Ẁ&ͩU.lvM:J1:,bn'CNhΥxAhX:X}ףp&鶐LU i}'D;y͎GT$u ~)#-;\i~I b'R- s[u]wesKM=tQL8curX7⼔K;2=BF;DaLU|m \*<^|,B((A{˛cbtCN^$bP浺'5O#e9†$W[|Ca,5 i¹vT͈LS"V,E =Uc,_sFuv%FNQ4fDNyS =7yЮG6Eї=5,{וoН@%D{aG†3G9~ͽ*d$ z_}V?VwwLKgfO4sgX?}] d&t7(Y Q(uevF!gpMk?:(GɗmZqi#ϛn Z`;[S~*C }hǎ+y p⬞?_G®S!68k꘣S:לO̦XYѶ7p꓄$/Mq"$lI) h1N hZRaTL`rQEut*ƯF$g\rȀԧAFO@4+(3' Uwm->M@p2.DEp({-e8Z{Ʉ| oLEѹÚE%@^d|6 9 ˯!`R %-ކȚؠŒӬөhT4Gl9 ؕuũU~xݻ6g頉>u3 u(.}H;lVy}/>5Ro+p2F\;L e/aTUfec*3 {.06mc! ?{~9P׉<-D]v+1j'#9rңLAϨ$(>?Ð`m|~J >4DZLY^,A΢Hjr8bE&BN1Q[2D1dN8Lʻn6!V`p7_޶4SuT<.۾$e]REd,!.\|ia7&EpGbg)~>?`9hMJ*k/DKopJQ&TEE*|@?M5pm"iAK(^>̝^tO@yAҊRp 1sڡ6QX% 3tR6sn D]Q3XAHlj $NJAW#ąmP?fOoA%/QN1%'$'wkq# j=vGfoQbu4zC'O.H  V8Rjx;g0T+ǿ_2}"uv"O,B.- ]f?>^%HK󹡗egɓ,:cš;AJU$ugEܲIi)EM&2y#==HKa;b!:2kR$}"}wN+:. 9=N/vPT./Z^ r[leܩHFҰ:0&yܚ.wrTmU't]0Kțu ^tO{/D?yA_2NbCl)|NP R_TkϬAk| Xxg86{H:G!ov7rno $]OW{ O .<&ERw:{aI=q?)x0rwPf1Nj!jM{@LEbϘlU9,zd K#jZJ`AqC0JGM \Ry:J+0&8KkǁB7]G'3Z˃h J8' $\nQ| "UcIϳB$"`}_Su2,?6revyn͞# p2o/dE%rH\IHV !1hOq!sȕUA6%أ/y]It4`} ׷ {c}t໱F+lƭM2q[ ;q=CL_ޫ+ YW(+s 06N}p`d.h˦Dw&,K+c;!Yhc0ABXd/{>OnӈWq{2vvq#VJ0YVA(`xkGGz&zlڬ$nX}|p &Lflj(RtP2Xaab~Pi,NX' 2[Z霖$-sje* ԓS"m 9|Frp`ш+h#,?ﳻۈ"ke-ݮB6Bk")p X=qRV84FҟIP* GԸ6بٶ+@d@E/ \!Cw›T$ If 9ElOB"]3;~v\Elv Ǐ #8E{,^a8jG$ GrNzM߅tXINlfˈ&tR Ͱe.vޠn%*p8=DM-W:{Nd&g xKT|mSZt̚ǩB&<| 1̉ɇ[0#Ct9 |u4nW3,g Y}jag,Cx =m.*b$5hXq&9)\חjB2zt6QIWw&B"d|įgXSd6TIfz&x*P {lJ4YZĕ<p☻)Ԣ GWTLs y"晤ɽxe y)!4;rI.4a`@%[gҡ9)q Ax)d 6zO-$dJxg"<"&c`UMrh(.ۑXH_W0Eu$5ѱ,df/c,C=:#-pd&Ϥ5 Ov0 kI^<ӟTL$=]C˭ B,@;^nA5cKR͜&"c2 +DQdW /8v3/!Mcfg0{t:xɵ_R$/XWVՈRՕg8`A=\C6Ҵ!|#k/cZϴ8}F|{;4X,ӑ4n(lQ WZgۿ (뿽q c]+8J]*Nc-9ٽhۼo%UмAd×\]%2IS;y-!$hGTݚ4>:˯h HXkKk.*r)uMzS}Z#"W hӝ 4~ 4(KS;r-бǙ}[H;CQZp\=SV›T$+ܟ-l3%zAuoIk|~51-a7VP_{&#]kc16{93Q8R7xpmi+o-#+dGuhaKC=/D0qKĉ $)z F.N?=RD##*cL$'ZN樊Wlֵ P1!ػ7f,v X:snx2hO1}3l<jDqK;Cq۞ 9Nj`["Xt&"PVj~J~Gvh$d(ٳ'/) #R$ߪocS &ix#oJ3i /BM?k r© fw+ (^ .B:N5dExf[!-|5a0f ?dۖ,2OґE`IEF Ye:2DHliUV}׉(E۔?FT*VA H Z#ݙlcP\ᐦJ1m=-Eu";+/9-8(Q$5풀ixac`zFQL,9|O10J_8c? wx]"n>0 YZensembldb/inst/chrY/0000755000175400017540000000000013175714743015431 5ustar00biocbuildbiocbuildensembldb/inst/chrY/ens_chromosome.txt0000644000175400017540000000005513175714743021212 0ustar00biocbuildbiocbuildseq_name seq_length is_circular Y 59373566 0 ensembldb/inst/chrY/ens_exon.txt0000644000175400017540000026045213175714743020021 0ustar00biocbuildbiocbuildexon_id exon_seq_start exon_seq_end ENSE00001902471 21878482 21878581 ENSE00003665408 21878165 21878359 ENSE00003572891 21877709 21877890 ENSE00003452486 21877470 21877625 ENSE00003535737 21872262 21872358 ENSE00003306433 21871337 21872146 ENSE00003587057 21870761 21870899 ENSE00003522786 21870130 21870309 ENSE00003674105 21869820 21869957 ENSE00003605358 21869033 21869632 ENSE00001928834 21868327 21868749 ENSE00001954294 21865751 21868231 ENSE00001733393 21906557 21906809 ENSE00000891759 21906271 21906439 ENSE00000652508 21905048 21905125 ENSE00000652506 21903621 21903743 ENSE00001788914 21903204 21903374 ENSE00001805865 21901414 21901548 ENSE00000652503 21897507 21897636 ENSE00000652502 21897238 21897383 ENSE00000652501 21894470 21894628 ENSE00001799734 21893932 21894051 ENSE00000652498 21893658 21893816 ENSE00001786866 21883016 21883197 ENSE00003497148 21882758 21882920 ENSE00003688313 21878482 21878601 ENSE00003664560 21878165 21878359 ENSE00003602862 21877709 21877890 ENSE00003491684 21877501 21877625 ENSE00003488142 21877238 21877385 ENSE00003534652 21872262 21872358 ENSE00003607600 21871337 21871695 ENSE00003544083 21870761 21870899 ENSE00003591494 21870130 21870309 ENSE00003484526 21869820 21869957 ENSE00003539670 21869033 21869632 ENSE00001670444 21868680 21868749 ENSE00001594027 21868327 21868526 ENSE00001945799 21867301 21868231 ENSE00001277406 21906557 21906647 ENSE00001919342 21867306 21868231 ENSE00001946630 21883016 21884353 ENSE00003582949 21882758 21882920 ENSE00003593440 21878482 21878601 ENSE00001900202 21877709 21877997 ENSE00003677957 21877501 21877625 ENSE00003607967 21877238 21877385 ENSE00003484073 21871337 21871695 ENSE00001941473 21867311 21868231 ENSE00001741626 21867949 21868231 ENSE00001692290 21870761 21870835 ENSE00001803510 21870208 21870309 ENSE00001658853 21869068 21869632 ENSE00001849878 21872262 21872492 ENSE00001940004 21871586 21872146 ENSE00001928223 21878165 21878234 ENSE00001930174 21877022 21877625 ENSE00001685428 21906557 21906597 ENSE00001652491 21883158 21883197 ENSE00002279676 21906557 21906825 ENSE00002207746 21885227 21885319 ENSE00002285913 21867303 21868231 ENSE00001402535 15016019 15016325 ENSE00001403038 15016846 15016892 ENSE00003463722 15019448 15019505 ENSE00001605860 15021271 15021318 ENSE00000862006 15023751 15023880 ENSE00000773394 15024639 15024794 ENSE00003574309 15024875 15024974 ENSE00003652139 15025630 15025765 ENSE00003536211 15026476 15026561 ENSE00001614446 15026796 15026894 ENSE00001746396 15026979 15027139 ENSE00000773388 15027542 15027686 ENSE00003534942 15027795 15027939 ENSE00000773386 15028173 15028354 ENSE00001703401 15028429 15028546 ENSE00001729063 15028819 15028972 ENSE00001722940 15029315 15029454 ENSE00001928277 15029955 15030451 ENSE00001685858 15016029 15016325 ENSE00001350052 15016769 15016892 ENSE00003656145 15025630 15025765 ENSE00001832940 15016742 15016892 ENSE00001352037 15029955 15032390 ENSE00001826669 15016760 15016892 ENSE00003643575 15019448 15019505 ENSE00001906809 15021271 15021607 ENSE00001797666 15017649 15017726 ENSE00003670172 15026476 15026561 ENSE00001937992 15024552 15024974 ENSE00001848230 15025630 15025713 ENSE00003512200 15024875 15024974 ENSE00003537802 15025630 15025765 ENSE00001948256 15026476 15026811 ENSE00001935991 15024920 15024974 ENSE00003534699 15026476 15026561 ENSE00001893350 15026796 15027139 ENSE00001811040 15027408 15027686 ENSE00003693954 15027795 15027939 ENSE00001922429 15028173 15028265 ENSE00001803243 2803322 2803487 ENSE00002223884 2821950 2822038 ENSE00003645989 2829115 2829687 ENSE00003548678 2843136 2843285 ENSE00003611496 2843552 2843695 ENSE00001649504 2844711 2844863 ENSE00001777381 2845981 2846121 ENSE00001494540 2846851 2850547 ENSE00001857352 2803541 2803810 ENSE00003626126 2843136 2843285 ENSE00003631374 2843552 2843695 ENSE00001955114 2845981 2846094 ENSE00001334555 2803546 2803810 ENSE00001597745 2829115 2829327 ENSE00001900413 2845860 2846121 ENSE00001880607 2846851 2847391 ENSE00001746216 2803112 2803487 ENSE00001368923 2846851 2850546 ENSE00001648585 2803518 2803810 ENSE00003604519 2829115 2829687 ENSE00001408731 6778727 6779023 ENSE00001494437 6780129 6780213 ENSE00001494434 6846254 6846284 ENSE00001494433 6863845 6863939 ENSE00001494431 6889490 6889578 ENSE00001793373 6893076 6893183 ENSE00003432678 6911021 6911166 ENSE00003437631 6931938 6932190 ENSE00003379331 6938237 6938369 ENSE00001213593 6938761 6938902 ENSE00001607530 6939601 6939664 ENSE00001716749 6939774 6939871 ENSE00001744765 6942601 6942661 ENSE00001731081 6948773 6948894 ENSE00001654905 6953939 6954013 ENSE00001729171 6954331 6954458 ENSE00001763966 6955308 6955473 ENSE00001593786 6958130 6958231 ENSE00001370395 6959513 6959724 ENSE00001631277 4868267 4868646 ENSE00001619635 4899947 4900052 ENSE00001755808 4900711 4900769 ENSE00000981568 4924930 4925500 ENSE00001640924 4966256 4968748 ENSE00001602875 4972385 4973485 ENSE00001350198 4924131 4925500 ENSE00001944263 4972385 4972741 ENSE00001803775 5369098 5369296 ENSE00001677522 5449816 5449839 ENSE00001322750 5605313 5610265 ENSE00001436852 4924865 4925500 ENSE00001731866 5483308 5483316 ENSE00001711324 5491131 5491145 ENSE00001779807 5605313 5605983 ENSE00001348274 6742013 6742068 ENSE00001671586 6740596 6740661 ENSE00001645681 6738047 6738094 ENSE00000652250 6736773 6736817 ENSE00001667251 6736078 6736503 ENSE00001494454 6733959 6734119 ENSE00001494452 6740596 6740649 ENSE00001651085 6736909 6736950 ENSE00001727000 6734114 6734119 ENSE00002300179 7142013 7142519 ENSE00003518103 7171978 7172146 ENSE00003489469 7193947 7194210 ENSE00003507474 7209156 7209275 ENSE00003502780 7224176 7224271 ENSE00002194667 7235397 7235474 ENSE00001494358 7239784 7239930 ENSE00001494356 7243753 7249589 ENSE00002183990 7142354 7142519 ENSE00002194098 7239784 7239909 ENSE00001877035 7194108 7194210 ENSE00001918349 7196068 7196444 ENSE00001948825 7201071 7201149 ENSE00001928357 7224176 7224264 ENSE00002210406 7142336 7142519 ENSE00003574133 7171978 7172146 ENSE00003534383 7193947 7194210 ENSE00003600341 7209156 7209275 ENSE00003520510 7224176 7224271 ENSE00001661914 7235397 7235456 ENSE00001020131 14813160 14813984 ENSE00001020125 14820567 14820626 ENSE00003651478 14821321 14821476 ENSE00003476271 14832522 14832670 ENSE00003602419 14834041 14834120 ENSE00003467347 14837046 14837158 ENSE00003693194 14838508 14838726 ENSE00003654508 14847546 14847661 ENSE00003550081 14847932 14848183 ENSE00003624888 14848345 14848483 ENSE00003487242 14850091 14850243 ENSE00003601630 14851459 14851563 ENSE00003666147 14869122 14869328 ENSE00003566318 14870436 14870572 ENSE00003557039 14872414 14872547 ENSE00003515132 14883002 14883089 ENSE00003621719 14885517 14885859 ENSE00003555621 14887405 14887500 ENSE00003655936 14888583 14888794 ENSE00003476364 14889953 14890193 ENSE00003510955 14890540 14890689 ENSE00003621863 14891460 14891580 ENSE00003560948 14898137 14898267 ENSE00003561084 14898455 14898733 ENSE00003508322 14902340 14902465 ENSE00003664000 14903432 14903557 ENSE00003547650 14904965 14905134 ENSE00003694071 14922114 14922222 ENSE00003679141 14922607 14922753 ENSE00003652645 14923570 14923716 ENSE00003564733 14924765 14924987 ENSE00003681535 14928059 14928279 ENSE00003669946 14930355 14930545 ENSE00003585886 14945614 14945787 ENSE00003635310 14949837 14949978 ENSE00003552773 14951790 14952540 ENSE00003548868 14952936 14953059 ENSE00001601104 14954166 14954391 ENSE00003586868 14954989 14955118 ENSE00003686311 14958258 14958443 ENSE00003476240 14958858 14959078 ENSE00003513236 14959164 14959252 ENSE00003654441 14968265 14968421 ENSE00003686907 14968558 14968770 ENSE00003595540 14969491 14969586 ENSE00003502466 14971204 14972764 ENSE00001869747 14813969 14813984 ENSE00003574267 14821321 14821476 ENSE00001853448 14832522 14833136 ENSE00001952418 14821369 14821476 ENSE00003642330 14832522 14832670 ENSE00003608903 14834041 14834120 ENSE00003569874 14837046 14837158 ENSE00003525307 14838508 14838726 ENSE00003468269 14847546 14847661 ENSE00003668411 14847932 14848183 ENSE00003544199 14848345 14848483 ENSE00003543968 14850091 14850243 ENSE00003678761 14851459 14851563 ENSE00003522394 14869122 14869328 ENSE00003556397 14870436 14870572 ENSE00003484639 14872414 14872547 ENSE00003494702 14883002 14883089 ENSE00003664430 14885517 14885859 ENSE00003545466 14887405 14887500 ENSE00003634092 14888583 14888794 ENSE00003562091 14889953 14890193 ENSE00003499612 14890540 14890689 ENSE00003612302 14891460 14891580 ENSE00003510705 14898137 14898267 ENSE00003494757 14898455 14898733 ENSE00003626016 14902340 14902465 ENSE00003624705 14903432 14903557 ENSE00003646476 14904965 14905134 ENSE00003683748 14922114 14922222 ENSE00003522502 14922607 14922753 ENSE00003692063 14923570 14923716 ENSE00003612215 14924765 14924987 ENSE00003491362 14928059 14928279 ENSE00003599293 14930355 14930545 ENSE00003548985 14945614 14945787 ENSE00003477744 14949837 14949978 ENSE00003471770 14951790 14952540 ENSE00003654551 14952936 14953059 ENSE00001841790 14954151 14954391 ENSE00003628831 14954989 14955118 ENSE00003640718 14958258 14958443 ENSE00003536017 14958858 14959078 ENSE00003664007 14959164 14959252 ENSE00003650241 14968265 14968421 ENSE00003632911 14968558 14968770 ENSE00003662966 14969491 14969586 ENSE00003580686 14971204 14972764 ENSE00001595780 14958970 14959078 ENSE00001746916 14971204 14971537 ENSE00001944130 14968738 14969586 ENSE00001756639 6258472 6258716 ENSE00001663636 6262141 6262300 ENSE00001595449 6269164 6269272 ENSE00001634261 6271629 6271766 ENSE00001767444 6279348 6279605 ENSE00002490412 2709527 2709668 ENSE00001709586 2710206 2710283 ENSE00001738202 2712118 2712298 ENSE00001602849 2713687 2713784 ENSE00001601989 2722641 2722812 ENSE00003667463 2733129 2733286 ENSE00003636667 2734834 2735309 ENSE00001732508 2709961 2710014 ENSE00001635459 2734834 2734903 ENSE00001859961 2722137 2722812 ENSE00003469154 2733129 2733286 ENSE00003654930 2734834 2734997 ENSE00002062109 2722771 2722812 ENSE00002034437 2796905 2797026 ENSE00002072199 2799752 2800041 ENSE00001782128 9611654 9611898 ENSE00001664883 9608070 9608229 ENSE00001800396 9601098 9601206 ENSE00001771159 9598604 9598741 ENSE00001609985 9590765 9591022 ENSE00001914170 16168097 16168271 ENSE00001617113 16168464 16168838 ENSE00001940528 16098219 16098393 ENSE00001622417 16097652 16098026 ENSE00002314376 19990147 19992100 ENSE00002282227 19990178 19992098 ENSE00002227312 19989715 19989742 ENSE00002265258 19989290 19989709 ENSE00002810788 21729199 21729368 ENSE00002783311 21749096 21749393 ENSE00002873804 21750256 21750536 ENSE00002825272 21751413 21751498 ENSE00001893165 21751969 21752133 ENSE00001826433 21729236 21729456 ENSE00001875276 21750256 21751498 ENSE00002811240 21751969 21752304 ENSE00002957208 21729268 21729368 ENSE00002829137 21751407 21751498 ENSE00002862473 21751969 21752309 ENSE00002920932 21753666 21753845 ENSE00001657009 21755285 21755479 ENSE00001617655 21757901 21758020 ENSE00001663997 21759477 21759551 ENSE00003585093 21761625 21761717 ENSE00003676904 21764102 21764197 ENSE00001621570 21765683 21766006 ENSE00002224044 21729673 21729837 ENSE00002265061 21731271 21731345 ENSE00002256441 21750256 21751735 ENSE00001793723 21729715 21729837 ENSE00001687078 21749096 21751733 ENSE00002916216 21750429 21750536 ENSE00002875419 21755285 21755603 ENSE00002833019 21750456 21750536 ENSE00002905816 21751969 21752305 ENSE00002863993 21750495 21750536 ENSE00002757214 21753806 21753845 ENSE00002783490 21755285 21755488 ENSE00002932169 21750497 21750536 ENSE00001950956 21752639 21752658 ENSE00001930064 21755285 21755537 ENSE00001279198 21754336 21754700 ENSE00001279210 21755285 21759551 ENSE00001035195 21765683 21768160 ENSE00002958230 21754974 21756047 ENSE00002880368 21759243 21759551 ENSE00002922995 21760438 21760525 ENSE00002745809 21765683 21765937 ENSE00001035136 21729235 21729368 ENSE00000891756 21749096 21749365 ENSE00001281659 21749368 21749393 ENSE00000981692 21751407 21751443 ENSE00001281628 21751446 21751498 ENSE00002836144 21751969 21752308 ENSE00001542537 21758442 21759551 ENSE00003664473 21761625 21761717 ENSE00003581743 21764102 21764197 ENSE00001493485 21765683 21767698 ENSE00001668181 20752266 20752407 ENSE00003505404 20750492 20750592 ENSE00001757235 20750017 20750130 ENSE00003519096 20749298 20749434 ENSE00003627127 20743092 20744234 ENSE00002217996 20750492 20750598 ENSE00003529279 20749298 20749434 ENSE00003568887 20743092 20744234 ENSE00001785382 24587492 24587605 ENSE00003499302 24587136 24587273 ENSE00001693495 24585740 24585978 ENSE00002290871 24587492 24587549 ENSE00003596079 24587136 24587273 ENSE00002214070 24586927 24587025 ENSE00002310424 24585887 24585978 ENSE00001917099 24291113 24291226 ENSE00003687937 24291445 24291582 ENSE00001937237 24292740 24292978 ENSE00002299728 24291169 24291226 ENSE00003671276 24291445 24291582 ENSE00002277139 24291693 24291791 ENSE00002209602 24292740 24292831 ENSE00001799711 6317509 6317545 ENSE00001638328 6318487 6318648 ENSE00001698649 6320956 6321030 ENSE00001648830 6321719 6322195 ENSE00001726416 6324113 6324226 ENSE00001799620 6325702 6325947 ENSE00001594918 6325200 6325455 ENSE00001682908 6321946 6322195 ENSE00001619344 6324014 6324226 ENSE00001729695 9548185 9548434 ENSE00001805126 9546154 9546366 ENSE00001633857 9544433 9544678 ENSE00001692562 9552835 9552871 ENSE00001658267 9551732 9551893 ENSE00001691944 9549350 9549424 ENSE00001628673 9548185 9548661 ENSE00001700737 9546154 9546267 ENSE00001717109 9544925 9545180 ENSE00001016870 15815447 15816315 ENSE00001274354 15817105 15817904 ENSE00001923202 22918050 22918052 ENSE00001677561 22918664 22918741 ENSE00001680575 22921754 22921934 ENSE00001638361 22923170 22923267 ENSE00001725100 22930691 22930862 ENSE00001734476 22941395 22941552 ENSE00001159425 22942817 22942918 ENSE00001867079 16634518 16634821 ENSE00001832496 16733889 16734377 ENSE00001420613 16634632 16634821 ENSE00003548219 16831339 16831398 ENSE00003542397 16834997 16835149 ENSE00003537524 16936068 16936253 ENSE00003686712 16941610 16942399 ENSE00001424034 16952293 16957530 ENSE00001493621 16635626 16635778 ENSE00003620397 16733901 16734471 ENSE00003691073 16834997 16835149 ENSE00003601036 16952293 16955606 ENSE00003554354 16831339 16831398 ENSE00003477208 16860499 16860609 ENSE00003610714 16733901 16734471 ENSE00003537517 16834997 16835149 ENSE00003613876 16860499 16860609 ENSE00001738756 16863561 16863682 ENSE00003625704 16936068 16936253 ENSE00003593743 16941610 16942399 ENSE00003665738 16952293 16955606 ENSE00001955812 16636409 16636588 ENSE00001955997 16733889 16734248 ENSE00001368742 16636454 16636816 ENSE00001390456 16733889 16734471 ENSE00001868567 16952293 16955527 ENSE00001493617 16734061 16734471 ENSE00001612473 16845332 16845429 ENSE00001707785 6114264 6114795 ENSE00003546295 6115397 6115474 ENSE00001623435 6115603 6115714 ENSE00001642228 6115816 6115961 ENSE00003563383 6116068 6116149 ENSE00001830098 6116844 6117054 ENSE00003503096 6114310 6114795 ENSE00001618514 6116057 6116149 ENSE00001687266 6116844 6117053 ENSE00003465137 6114310 6114795 ENSE00003510285 6115397 6115474 ENSE00001885391 6115603 6116149 ENSE00001950610 6116277 6117060 ENSE00001851117 6115664 6115961 ENSE00003591129 6116068 6116149 ENSE00001858368 6116844 6117045 ENSE00001902634 25840606 25840726 ENSE00003696150 25837904 25838019 ENSE00001591394 25827587 25828412 ENSE00003701041 25840606 25840674 ENSE00003695877 25828154 25828412 ENSE00001786049 25840606 25840710 ENSE00003695050 25837904 25838019 ENSE00001644491 25829559 25829589 ENSE00001686003 24636544 24636631 ENSE00001657597 24636733 24636819 ENSE00003636240 24647660 24647780 ENSE00003502664 24650356 24650471 ENSE00003502641 24659959 24660784 ENSE00001876694 24658785 24658899 ENSE00003543250 24659959 24660784 ENSE00001624902 24658785 24658815 ENSE00001703126 24328982 24329095 ENSE00003469687 24327008 24327120 ENSE00003536546 24326438 24326541 ENSE00001739138 24323241 24323418 ENSE00003679115 24321173 24321325 ENSE00003668781 24319048 24319162 ENSE00003531954 24317982 24318092 ENSE00003661928 24317431 24317541 ENSE00003557303 24316886 24316996 ENSE00003568885 24315852 24315962 ENSE00003638296 24315677 24315765 ENSE00003580283 24314689 24315265 ENSE00001816306 24328982 24329104 ENSE00003562722 24327008 24327120 ENSE00003591193 24326438 24326541 ENSE00003636020 24321173 24321325 ENSE00003530779 24319048 24319162 ENSE00003638449 24317982 24318092 ENSE00003576126 24317431 24317541 ENSE00003480178 24316886 24316996 ENSE00003687067 24315852 24315962 ENSE00003468889 24315677 24315765 ENSE00003578044 24314689 24315265 ENSE00001765593 24328982 24329129 ENSE00001625881 24242067 24242154 ENSE00001682815 24241879 24241965 ENSE00003673462 24230918 24231038 ENSE00003492436 24228227 24228342 ENSE00003573636 24217903 24218728 ENSE00001899711 24219791 24219905 ENSE00003488975 24217903 24218728 ENSE00001628640 24219875 24219905 ENSE00003525363 23655405 23655582 ENSE00003550074 23657496 23657648 ENSE00003651701 23659659 23659773 ENSE00003567644 23660729 23660839 ENSE00003490701 23661281 23661391 ENSE00003662908 23661826 23661936 ENSE00001594909 23662370 23662480 ENSE00003642058 23662858 23662968 ENSE00003574473 23663056 23663144 ENSE00003635823 23663556 23663854 ENSE00003480955 23655405 23655582 ENSE00003658768 23657496 23657648 ENSE00003532851 23659659 23659773 ENSE00003665479 23660729 23660839 ENSE00003491376 23661281 23661391 ENSE00003537055 23661826 23661936 ENSE00001657501 23662370 23662391 ENSE00001596885 23661276 23661391 ENSE00003604831 23662858 23662968 ENSE00003477338 23663056 23663144 ENSE00003512248 23663556 23663854 ENSE00001611088 23630044 23630517 ENSE00001715185 23631127 23631204 ENSE00001657254 23631333 23631444 ENSE00001645729 23631544 23631689 ENSE00001802624 23631798 23631879 ENSE00001543685 23632547 23632569 ENSE00003670797 20934992 20935601 ENSE00003588065 20893326 20893753 ENSE00003662804 20934992 20935601 ENSE00003613429 20932069 20932178 ENSE00001899520 20931419 20931505 ENSE00001698194 20930217 20930371 ENSE00001803454 20899531 20899616 ENSE00003604288 20893326 20893753 ENSE00001597600 20934992 20935572 ENSE00003535599 20932069 20932178 ENSE00001493553 20930807 20931505 ENSE00001674814 20934992 20935621 ENSE00001858694 20933700 20934513 ENSE00002036080 20990471 20990548 ENSE00002085962 20981241 20981672 ENSE00002062695 20952456 20952653 ENSE00002046872 20951697 20951805 ENSE00002035366 20934594 20935259 ENSE00001900148 28121696 28121764 ENSE00003701812 28124351 28124466 ENSE00001781602 28133958 28134216 ENSE00001665399 28121660 28121764 ENSE00003700592 28124351 28124466 ENSE00001707150 28132781 28132811 ENSE00001854309 27768309 27770181 ENSE00001666303 27770602 27771049 ENSE00001436475 27768264 27770483 ENSE00001786020 27624416 27624579 ENSE00001735399 27626218 27629777 ENSE00003506820 27629055 27629777 ENSE00003604808 27632781 27632852 ENSE00001668733 27600708 27600827 ENSE00001679890 27601441 27601500 ENSE00001610203 27601687 27601765 ENSE00003589912 27602885 27603234 ENSE00001637486 27603533 27603590 ENSE00001798553 27604621 27604690 ENSE00001752493 27604710 27604870 ENSE00003654675 27604947 27605021 ENSE00003649198 27605442 27605530 ENSE00003496796 27605786 27605974 ENSE00003547203 27606064 27606156 ENSE00001716410 27606239 27606329 ENSE00001635424 27606412 27606567 ENSE00001555256 27606658 27606719 ENSE00002286560 27601458 27601500 ENSE00003553650 27602885 27603234 ENSE00002324147 27603532 27603590 ENSE00003604497 27604947 27605021 ENSE00003480675 27605442 27605530 ENSE00003621244 27605786 27605974 ENSE00003668556 27606064 27606156 ENSE00001795579 27606239 27606322 ENSE00001629437 26361609 26361728 ENSE00001719001 26360936 26360995 ENSE00001728235 26360671 26360751 ENSE00001708482 26359940 26360029 ENSE00001598676 26359202 26359552 ENSE00003608732 26358846 26358903 ENSE00003588397 26357415 26357489 ENSE00003459260 26356906 26356994 ENSE00003477737 26356462 26356650 ENSE00003459192 26356280 26356372 ENSE00001742949 26356102 26356197 ENSE00001800235 26355872 26356018 ENSE00001597641 26355714 26355770 ENSE00003490496 26360936 26360978 ENSE00003609331 26360671 26360749 ENSE00003569147 26359202 26359551 ENSE00002302306 26358846 26358904 ENSE00003652688 26357415 26357489 ENSE00003586010 26356906 26356994 ENSE00003532508 26356462 26356650 ENSE00003491049 26356280 26356372 ENSE00003688093 26356114 26356197 ENSE00001654202 26337854 26338017 ENSE00001648900 26332656 26336215 ENSE00001931820 26192244 26194116 ENSE00001621868 26191376 26191823 ENSE00001491983 26191940 26194166 ENSE00001652231 20708557 20709186 ENSE00001822279 20709665 20710478 ENSE00001838947 20708577 20709186 ENSE00003536585 20750422 20750849 ENSE00001801443 20712000 20712109 ENSE00001739030 20712669 20712755 ENSE00001756006 20713803 20713957 ENSE00001661293 20744559 20744644 ENSE00003593310 20750422 20750849 ENSE00001603573 20708606 20709186 ENSE00001493572 20712669 20713351 ENSE00003551056 8774265 8774373 ENSE00001663043 8775135 8775238 ENSE00003516285 8777924 8778101 ENSE00003527480 8779987 8780139 ENSE00001644937 8782134 8782245 ENSE00001644677 8783125 8783235 ENSE00001705054 8783317 8783405 ENSE00001636903 8783812 8784114 ENSE00002323304 8777989 8778101 ENSE00002263796 8782134 8782196 ENSE00003587796 8774265 8774373 ENSE00002255439 8774933 8774966 ENSE00002234877 8775160 8775238 ENSE00003466737 8777924 8778101 ENSE00003689056 8779987 8780139 ENSE00002236871 8782134 8782184 ENSE00001091887 3447082 3447168 ENSE00001889836 3447265 3448082 ENSE00002559577 3447156 3448082 ENSE00001285919 21038954 21040114 ENSE00001702356 21034387 21034720 ENSE00001684888 21238931 21239004 ENSE00001631223 21038954 21039091 ENSE00001624668 21034389 21034720 ENSE00001747572 21237827 21237882 ENSE00001776523 21230610 21230684 ENSE00001661526 21207128 21207177 ENSE00001792674 21206428 21206581 ENSE00001594458 21094203 21094727 ENSE00001313137 21238931 21239302 ENSE00001556105 21094585 21094727 ENSE00001748128 21238931 21239281 ENSE00001720075 21210659 21210798 ENSE00001800197 21207128 21207174 ENSE00001721855 21206548 21206581 ENSE00001746218 21205049 21205232 ENSE00001626612 21203384 21203472 ENSE00001544018 8685387 8685423 ENSE00001544017 8662902 8662985 ENSE00000900348 8657041 8657343 ENSE00001272668 8651929 8652244 ENSE00001544015 8651351 8651447 ENSE00001708504 20137669 20139589 ENSE00001744590 20140025 20140052 ENSE00001639130 20140058 20140477 ENSE00002310447 20137667 20139626 ENSE00001493287 23548118 23548246 ENSE00001296914 23545799 23545855 ENSE00001325246 23545318 23545682 ENSE00001493285 23544840 23545166 ENSE00001853079 9528709 9528844 ENSE00001693371 9529322 9529526 ENSE00001729545 9531119 9531308 ENSE00001799150 9531390 9531566 ENSE00002265228 13524543 13524717 ENSE00001730908 13506553 13506659 ENSE00001631073 13505561 13505710 ENSE00001704814 13501668 13501776 ENSE00001619518 13500644 13500780 ENSE00002258116 13496241 13496470 ENSE00003436862 25119966 25120121 ENSE00003254543 25130295 25130363 ENSE00001669186 25130716 25130838 ENSE00001626256 25133904 25134040 ENSE00003262349 25138450 25138523 ENSE00001730185 25130410 25130440 ENSE00003542244 25138450 25138568 ENSE00001792376 25140628 25140745 ENSE00003677192 25143599 25143704 ENSE00003473409 25144397 25144521 ENSE00001543555 25151072 25151606 ENSE00003442800 25130434 25130440 ENSE00003516313 25138450 25138568 ENSE00003688894 25143599 25143704 ENSE00003560022 25144397 25144521 ENSE00003360806 25151072 25151553 ENSE00001698397 25151072 25151196 ENSE00001791291 25151291 25151612 ENSE00003302451 26753707 26753862 ENSE00003336765 26764036 26764104 ENSE00001619605 26764457 26764579 ENSE00001689728 26767645 26767781 ENSE00003272237 26772191 26772264 ENSE00001676764 26764151 26764181 ENSE00003549506 26772191 26772309 ENSE00001757255 26774369 26774486 ENSE00003667169 26777341 26777446 ENSE00003463186 26778139 26778263 ENSE00001625788 26784814 26784938 ENSE00001723611 26785033 26785354 ENSE00003454106 26764175 26764181 ENSE00003681954 26772191 26772309 ENSE00003623347 26777341 26777446 ENSE00003640779 26778139 26778263 ENSE00003335658 26784814 26784943 ENSE00003346171 26785033 26785295 ENSE00001864071 15591394 15592553 ENSE00003531058 15591134 15591197 ENSE00003601240 15582001 15582109 ENSE00003660729 15560897 15560946 ENSE00003557845 15526615 15526673 ENSE00003529356 15522873 15522993 ENSE00003648165 15508798 15508852 ENSE00001594460 15505739 15505773 ENSE00003527061 15481136 15481229 ENSE00003473448 15478147 15478273 ENSE00001775185 15472310 15472408 ENSE00001755119 15471647 15471866 ENSE00001291636 15469757 15469849 ENSE00001311020 15467803 15467898 ENSE00001696208 15466883 15467278 ENSE00001305759 15447443 15448215 ENSE00001624388 15438101 15438230 ENSE00001639693 15436481 15436586 ENSE00001651897 15435435 15435640 ENSE00001295816 15418066 15418130 ENSE00001591330 15417918 15417992 ENSE00001751483 15417279 15417427 ENSE00001740894 15414757 15414871 ENSE00001640284 15410837 15411024 ENSE00001785465 15409587 15409728 ENSE00001298131 15372158 15372284 ENSE00001713248 15362897 15363067 ENSE00001875480 15360259 15361762 ENSE00001385925 15591394 15592550 ENSE00001436855 15409321 15409728 ENSE00001640421 15434914 15435248 ENSE00001822678 15591394 15591420 ENSE00003612487 15591134 15591197 ENSE00003529285 15582001 15582109 ENSE00003678156 15560897 15560946 ENSE00003644070 15526615 15526673 ENSE00003505329 15522873 15522993 ENSE00003575738 15508798 15508852 ENSE00003582459 15481136 15481229 ENSE00003591211 15478147 15478273 ENSE00001899507 15472368 15472408 ENSE00001931275 15591134 15591384 ENSE00001818021 15505032 15505773 ENSE00001436854 15591394 15591858 ENSE00001493710 15508182 15508852 ENSE00001942244 15591394 15591803 ENSE00001872513 15590922 15591197 ENSE00002281428 15591394 15591545 ENSE00002277775 15470968 15471102 ENSE00001330353 15361736 15361762 ENSE00002240413 15467255 15467278 ENSE00002284432 15591394 15591551 ENSE00002258300 15434927 15435248 ENSE00002206921 15470344 15470433 ENSE00002312710 15434948 15435270 ENSE00001494622 2654896 2655740 ENSE00002201849 2655075 2655644 ENSE00002323146 2655049 2655069 ENSE00002144027 2655171 2655644 ENSE00002214525 2655145 2655168 ENSE00001543664 23756472 23756552 ENSE00001299738 23751852 23752013 ENSE00001425815 23751158 23751256 ENSE00001543661 23749387 23749548 ENSE00001543658 23746669 23746760 ENSE00001543653 23745486 23745548 ENSE00001493514 21154353 21154595 ENSE00001774474 6341536 6341671 ENSE00001632371 6340854 6341058 ENSE00001757652 6338814 6338990 ENSE00001598872 6339072 6339261 ENSE00001643163 27198221 27198251 ENSE00001775879 27197823 27197945 ENSE00001797093 27194621 27194757 ENSE00003604811 27190093 27190211 ENSE00001711311 27187916 27188033 ENSE00003547967 27184956 27185061 ENSE00003506422 27184139 27184263 ENSE00001764403 27177464 27177588 ENSE00001740581 27177048 27177369 ENSE00003378858 27198221 27198227 ENSE00003663501 27190093 27190211 ENSE00003522688 27184956 27185061 ENSE00003640409 27184139 27184263 ENSE00003450106 27177459 27177588 ENSE00003432143 27177107 27177369 ENSE00003307767 27208540 27208695 ENSE00003370731 27198298 27198366 ENSE00003266869 27190138 27190211 ENSE00001695979 26959330 26959626 ENSE00001803162 26952582 26952728 ENSE00001733013 26952216 26952307 ENSE00001602566 26951604 26951655 ENSE00001709286 26951104 26951167 ENSE00001706721 26950875 26951014 ENSE00001722493 26949403 26949474 ENSE00001757238 26946960 26947031 ENSE00001785551 26944570 26944641 ENSE00001618455 26942174 26942245 ENSE00001728003 26939797 26939868 ENSE00001655608 26937418 26937489 ENSE00001684201 26935041 26935112 ENSE00001594431 26932661 26932732 ENSE00001620779 26930284 26930355 ENSE00001604640 26920497 26920568 ENSE00001799005 26919717 26919751 ENSE00001715045 26915046 26915144 ENSE00001879735 26909216 26911072 ENSE00001759696 26959330 26959542 ENSE00001670353 26909220 26911072 ENSE00001638508 26959330 26959540 ENSE00001596582 26909222 26911072 ENSE00001710130 26959330 26959519 ENSE00001761121 26929528 26929539 ENSE00002297176 26934285 26934296 ENSE00001761952 9745272 9745748 ENSE00001787222 9744588 9744665 ENSE00001756785 9744349 9744459 ENSE00001659741 9744107 9744249 ENSE00001614961 9743913 9743997 ENSE00001783992 9743204 9743223 ENSE00001790708 25344945 25345241 ENSE00001612801 25338199 25338345 ENSE00001805705 25337833 25337924 ENSE00001701677 25337221 25337272 ENSE00001677573 25336721 25336784 ENSE00001692245 25336492 25336631 ENSE00001655036 25327351 25327497 ENSE00001644179 25326985 25327076 ENSE00001646813 25326373 25326424 ENSE00001693241 25325873 25325936 ENSE00001620467 25325644 25325783 ENSE00001793499 25316511 25316657 ENSE00001598075 25316145 25316236 ENSE00001622354 25315533 25315584 ENSE00001695781 25315033 25315096 ENSE00001646624 25314804 25314943 ENSE00001597343 25313332 25313403 ENSE00001707161 25310887 25310958 ENSE00001696683 25308496 25308567 ENSE00001742324 25306100 25306171 ENSE00001758855 25303717 25303788 ENSE00001633941 25301321 25301392 ENSE00001675126 25298944 25299015 ENSE00001697295 25289158 25289229 ENSE00001614454 25286773 25286844 ENSE00003674346 25285994 25286028 ENSE00003567366 25281322 25281420 ENSE00001730215 25275502 25277358 ENSE00001907756 25286773 25286959 ENSE00003593491 25285994 25286028 ENSE00001924070 25284357 25284428 ENSE00003490554 25281322 25281420 ENSE00001941183 25275510 25277358 ENSE00002223761 25344945 25345070 ENSE00002211619 25306111 25306171 ENSE00002216645 25276010 25276503 ENSE00002288175 25344945 25345140 ENSE00002302795 25275506 25277358 ENSE00002244340 25344945 25345157 ENSE00002220199 25275509 25277358 ENSE00001364289 28555962 28556092 ENSE00001703024 28560195 28560309 ENSE00001598245 28560476 28560649 ENSE00001623069 28564991 28565087 ENSE00001638930 28566541 28566682 ENSE00001793914 9215731 9216215 ENSE00003611070 9216823 9216900 ENSE00003508777 9217029 9217140 ENSE00003486078 9217242 9217387 ENSE00003501886 9217494 9217575 ENSE00002025193 9218270 9218480 ENSE00001605630 9160370 9160478 ENSE00002029402 9159794 9159897 ENSE00002071256 9156601 9156778 ENSE00001752142 9154548 9154700 ENSE00001625315 9152385 9152499 ENSE00001784994 9151319 9151429 ENSE00001627758 9150782 9150891 ENSE00001785135 9150234 9150344 ENSE00001784976 9149625 9149735 ENSE00001614661 9148739 9149040 ENSE00002247829 9160370 9160483 ENSE00002322909 9154670 9154700 ENSE00001696638 27648022 27648105 ENSE00001710713 27646259 27646378 ENSE00001621856 27645577 27645636 ENSE00001665831 27645311 27645391 ENSE00001614475 27644598 27644654 ENSE00001747959 27643623 27644192 ENSE00001629056 27643285 27643355 ENSE00001738683 27642139 27642262 ENSE00001745419 27641798 27641929 ENSE00001435537 22737611 22737773 ENSE00003613684 22741494 22741577 ENSE00003657245 22744476 22744579 ENSE00003465639 22746360 22746410 ENSE00001635972 22749910 22749991 ENSE00003488477 22751370 22751461 ENSE00001436409 22754227 22755040 ENSE00001900287 22737664 22737773 ENSE00003550832 22741494 22741577 ENSE00003637584 22744476 22744579 ENSE00003458723 22746360 22746410 ENSE00001848909 22749910 22750415 ENSE00001848730 22737680 22737773 ENSE00003530204 22754227 22754516 ENSE00001918431 22748604 22751461 ENSE00003571869 22754227 22754516 ENSE00001943944 22749733 22749991 ENSE00003530759 22751370 22751461 ENSE00001608723 26980064 26980276 ENSE00001761380 26997726 26997872 ENSE00001671603 26998147 26998238 ENSE00001610089 26998799 26998850 ENSE00001639000 26999287 26999350 ENSE00001609022 26999440 26999579 ENSE00001796227 27000980 27001051 ENSE00001643133 27003423 27003494 ENSE00001610738 27005813 27005884 ENSE00001694635 27008209 27008280 ENSE00001628323 27010593 27010664 ENSE00001759079 27017746 27017817 ENSE00003621500 27020123 27020194 ENSE00003476346 27041835 27041906 ENSE00003593830 27042652 27042686 ENSE00003673436 27047259 27047357 ENSE00002286159 27051331 27053183 ENSE00003521530 27039450 27039521 ENSE00001409187 27047259 27047331 ENSE00001784722 26986878 26987024 ENSE00001612288 26987299 26987390 ENSE00001607094 26987951 26988002 ENSE00001741374 26988439 26988502 ENSE00001709278 26988592 26988731 ENSE00001632077 27012989 27013060 ENSE00003646399 27015366 27015437 ENSE00002226159 26980066 26980276 ENSE00003609241 27029911 27029982 ENSE00003641574 27032296 27032367 ENSE00003582499 27034681 27034752 ENSE00002310973 27051331 27053181 ENSE00001804650 26980081 26980276 ENSE00002247728 26980008 26980276 ENSE00003688590 27020123 27020194 ENSE00003491822 27029911 27029982 ENSE00003627572 27032296 27032367 ENSE00003463917 27034681 27034752 ENSE00002242041 27037065 27037136 ENSE00003542339 27039450 27039521 ENSE00003675468 27041835 27041906 ENSE00003605405 27042652 27042686 ENSE00003571325 27047259 27047357 ENSE00002324480 26980087 26980276 ENSE00003528908 27015366 27015437 ENSE00003669768 27020123 27020194 ENSE00001693578 25525631 25525720 ENSE00001701535 25535138 25535341 ENSE00001742121 25537312 25537501 ENSE00001646556 25537590 25537702 ENSE00001671473 25538803 25538844 ENSE00001639518 25365594 25365890 ENSE00001640624 25372491 25372637 ENSE00001689126 25372912 25373003 ENSE00001736653 25373564 25373615 ENSE00001659494 25374052 25374115 ENSE00001723992 25374205 25374344 ENSE00001592425 25375745 25375816 ENSE00001676137 25378188 25378259 ENSE00001748863 25380579 25380650 ENSE00001787726 25387753 25387824 ENSE00001605577 25390137 25390208 ENSE00001607297 25399688 25399759 ENSE00001771158 25402065 25402136 ENSE00001743603 25411854 25411925 ENSE00001706458 25414238 25414309 ENSE00001690453 25416623 25416694 ENSE00001659100 25419007 25419078 ENSE00001717191 25421391 25421462 ENSE00001705999 25423775 25423846 ENSE00001622502 25426160 25426231 ENSE00001695324 25426976 25427010 ENSE00001659634 25431585 25431683 ENSE00001668820 25435647 25437503 ENSE00001603036 25365622 25365890 ENSE00001780208 25382975 25383046 ENSE00001682794 25385357 25385428 ENSE00001736828 25392533 25392604 ENSE00001674452 25394910 25394981 ENSE00001686143 25397292 25397363 ENSE00001687149 25435647 25437499 ENSE00001943922 25365695 25365890 ENSE00001865723 25435647 25436146 ENSE00001542120 25435647 25437496 ENSE00001685890 25365678 25365890 ENSE00001795799 25365680 25365890 ENSE00001656459 25435647 25437497 ENSE00001612046 25365701 25365890 ENSE00002307170 25435647 25435854 ENSE00002288552 25395727 25395738 ENSE00001494103 14532115 14532255 ENSE00003566412 14518595 14518736 ENSE00001494100 14475147 14475502 ENSE00001936584 14529689 14530093 ENSE00003683672 14518992 14519108 ENSE00001833093 14510475 14510612 ENSE00001864445 14494992 14495133 ENSE00001431292 14514046 14514385 ENSE00001494096 14532115 14532171 ENSE00001494094 14517922 14518299 ENSE00001494099 14532115 14532121 ENSE00001626669 9578193 9580010 ENSE00001628061 9582487 9582573 ENSE00001654045 9589958 9590106 ENSE00001742514 9590799 9590955 ENSE00001625965 9593786 9593864 ENSE00001637388 9593985 9594182 ENSE00001647627 9595406 9596085 ENSE00001713628 6290369 6292186 ENSE00001608925 6287806 6287892 ENSE00001661659 6280264 6280412 ENSE00001718232 6279415 6279571 ENSE00001712140 6276506 6276584 ENSE00001710562 6276188 6276385 ENSE00001697617 6274285 6274964 ENSE00001796890 5441186 5442472 ENSE00001542224 15398518 15399258 ENSE00002304178 15398518 15398647 ENSE00002218148 15398663 15399258 ENSE00002225900 28654360 28654413 ENSE00002060648 28661203 28661256 ENSE00002054613 28661802 28661855 ENSE00002062274 28671998 28672057 ENSE00001794058 28678931 28678981 ENSE00002063262 28680470 28680631 ENSE00002075791 28687117 28687236 ENSE00002083827 28688890 28688989 ENSE00001329242 28689136 28689198 ENSE00001755500 28689931 28689995 ENSE00001609863 28703135 28703199 ENSE00002050610 28704021 28704095 ENSE00001759871 28704194 28704282 ENSE00001803087 28710465 28710525 ENSE00001650788 28712325 28712406 ENSE00001785401 28716007 28716112 ENSE00001711963 28718030 28718109 ENSE00001803764 28722071 28722161 ENSE00001634122 28723571 28723641 ENSE00002035744 28725736 28725837 ENSE00001633881 28269821 28269929 ENSE00003705348 28270383 28270486 ENSE00003708504 28273195 28273372 ENSE00001648607 28275308 28275460 ENSE00001624353 28277468 28277582 ENSE00001654144 28278452 28278562 ENSE00001742721 28278645 28278732 ENSE00001733694 28279157 28279455 ENSE00002063794 28269867 28269929 ENSE00002073782 28275308 28275354 ENSE00001798056 25012691 25013903 ENSE00001786804 25692981 25693089 ENSE00003707528 25692424 25692527 ENSE00003707660 25689538 25689715 ENSE00001646086 25687450 25687602 ENSE00001635863 25685328 25685442 ENSE00001692837 25684348 25684458 ENSE00001650343 25684178 25684265 ENSE00001693911 25683455 25683753 ENSE00001782800 25692981 25693043 ENSE00001601487 25687556 25687602 ENSE00001543607 24444453 24445023 ENSE00001543606 24442945 24443935 ENSE00001610376 21664918 21665039 ENSE00002093140 21642055 21642180 ENSE00003244086 21636526 21636789 ENSE00002127178 21635791 21636030 ENSE00002119618 21628342 21629260 ENSE00002135990 21626992 21627113 ENSE00002871965 21621175 21621252 ENSE00002832419 21620810 21620965 ENSE00001709914 21617317 21618750 ENSE00002099269 21664918 21665022 ENSE00002135691 21621845 21621990 ENSE00002116806 21618943 21619003 ENSE00002114284 21618198 21618750 ENSE00002035739 21643553 21646770 ENSE00002065873 21642577 21642624 ENSE00002052301 21642051 21642180 ENSE00002063105 21636536 21636784 ENSE00002068678 21635791 21636136 ENSE00002035720 21628950 21629273 ENSE00002040446 21628330 21628593 ENSE00002087154 21618471 21618750 ENSE00001641174 14043242 14044475 ENSE00001735477 8148239 8148376 ENSE00001670231 8149742 8149851 ENSE00001794413 8149938 8150083 ENSE00001687318 8150202 8150250 ENSE00001616737 7721727 7722917 ENSE00001561333 3417693 3417851 ENSE00001755093 8286832 8287941 ENSE00001564286 23005142 23005596 ENSE00001563558 21033988 21034158 ENSE00001556375 21147061 21147740 ENSE00001551524 21148104 21148284 ENSE00001551713 3719265 3720910 ENSE00001664386 26001669 26003238 ENSE00001757650 27898535 27899017 ENSE00001733565 25813749 25813969 ENSE00001699806 25811830 25811945 ENSE00001780177 25809855 25810043 ENSE00001657364 25807367 25807496 ENSE00001601089 25805613 25805651 ENSE00001753322 7546940 7547251 ENSE00001706758 7548308 7548373 ENSE00001651867 7548569 7548661 ENSE00001608049 7548761 7548905 ENSE00001662653 7549024 7549069 ENSE00001705807 16389230 16389369 ENSE00001746889 16388092 16388491 ENSE00001722988 19894090 19894215 ENSE00001776348 19894790 19894881 ENSE00001631973 19896507 19896695 ENSE00001733982 2863108 2863314 ENSE00001607377 27577303 27577404 ENSE00001744544 27583358 27583462 ENSE00001706460 23563363 23563471 ENSE00003704369 23562809 23562912 ENSE00001600307 23559224 23559338 ENSE00001699202 23558232 23558342 ENSE00003708495 23557757 23557867 ENSE00003704715 23557586 23557674 ENSE00001654717 23556877 23557177 ENSE00001801361 23563363 23563448 ENSE00001684171 23557034 23557177 ENSE00001787469 27330861 27330920 ENSE00001786906 27329790 27329895 ENSE00001624987 28064470 28065042 ENSE00001742768 26314334 26314417 ENSE00001741857 26316061 26316180 ENSE00001756336 26316803 26316862 ENSE00001733532 26317048 26317128 ENSE00001765193 26317785 26317859 ENSE00001788990 26318248 26318816 ENSE00003551602 26319084 26319144 ENSE00003674280 26320185 26320299 ENSE00002050900 26320509 26320641 ENSE00001632235 6196093 6196270 ENSE00001760970 6206786 6206935 ENSE00001709237 6208936 6209035 ENSE00001738839 6209843 6209953 ENSE00001657532 6210351 6210461 ENSE00001682229 6210572 6210653 ENSE00001638892 6211063 6211364 ENSE00001720793 27859471 27859704 ENSE00001745042 27856055 27856417 ENSE00001645847 15342765 15343320 ENSE00001733686 8231577 8232000 ENSE00001640125 27131348 27132623 ENSE00001673618 20134179 20134244 ENSE00001701558 20134576 20135788 ENSE00001666463 15195704 15196258 ENSE00001732944 15206489 15207719 ENSE00001779327 14460540 14460702 ENSE00001715744 14461903 14462022 ENSE00001713276 14467867 14468218 ENSE00001682376 14465804 14465942 ENSE00001714515 14467867 14468226 ENSE00001803533 9638762 9638916 ENSE00001742365 9642383 9642494 ENSE00001763553 9646920 9646994 ENSE00001699801 9647680 9647718 ENSE00001593910 9650809 9650854 ENSE00001609393 21001068 21001199 ENSE00001645218 20995937 20996093 ENSE00001669340 20995776 20995804 ENSE00001648145 20995360 20995534 ENSE00001618505 20994888 20994983 ENSE00001722426 19856420 19856476 ENSE00001774330 19853796 19853911 ENSE00001697230 19841408 19841679 ENSE00001667957 25805122 25805205 ENSE00001741624 25804630 25804789 ENSE00001617890 25803986 25804144 ENSE00001732131 26641455 26641730 ENSE00001695041 26640856 26641153 ENSE00001705100 28695572 28695890 ENSE00001731067 9384401 9384693 ENSE00001688408 9384257 9384264 ENSE00001799980 9384120 9384149 ENSE00001667811 9384061 9384106 ENSE00001697848 9383769 9383780 ENSE00001645782 9383598 9383608 ENSE00001597947 9383272 9383336 ENSE00001783028 9383040 9383075 ENSE00001724466 9382966 9383038 ENSE00001668444 9382734 9382879 ENSE00001787097 9374241 9374297 ENSE00001602981 9021303 9021394 ENSE00001645114 9023211 9023412 ENSE00001632052 22973205 22973695 ENSE00001746774 22970662 22971351 ENSE00001759712 20020635 20020855 ENSE00001655699 20022478 20022686 ENSE00001640260 17053626 17053701 ENSE00003294704 17054541 17054595 ENSE00001787918 26066052 26066271 ENSE00001790627 26067398 26067657 ENSE00001775532 8218972 8220184 ENSE00003556843 24795392 24795500 ENSE00003707698 24795954 24796057 ENSE00003705095 24798766 24798943 ENSE00001787776 24800879 24801031 ENSE00001628066 24803039 24803153 ENSE00001708635 24804023 24804133 ENSE00001792249 24804216 24804303 ENSE00001783563 24804728 24805025 ENSE00002058038 24795438 24795500 ENSE00003582078 24800879 24800925 ENSE00001730385 26422392 26423173 ENSE00001660101 25880340 25880590 ENSE00001706320 25882205 25882396 ENSE00001793186 24666828 24667842 ENSE00001664773 24818605 24819006 ENSE00001659765 24817518 24817572 ENSE00001628115 24817194 24817302 ENSE00001615798 24816958 24817017 ENSE00001787460 24816763 24816836 ENSE00001747464 6587003 6587221 ENSE00001728661 19912484 19912576 ENSE00001689812 19910390 19910531 ENSE00001613966 19909863 19909948 ENSE00001614250 19612838 19612995 ENSE00001615218 19613591 19613640 ENSE00001658609 19624978 19625106 ENSE00001802978 19625354 19625447 ENSE00001752917 19626041 19626211 ENSE00001742406 19626321 19626414 ENSE00001606348 19626689 19626898 ENSE00001646418 14474827 14474869 ENSE00001596298 14482956 14483105 ENSE00001692812 14486671 14486792 ENSE00001685756 14487928 14488049 ENSE00001804752 14494139 14494272 ENSE00001603823 14494944 14495106 ENSE00001679516 14496112 14496233 ENSE00001625545 14498765 14499123 ENSE00001687009 25608612 25608682 ENSE00001681165 25618301 25618427 ENSE00001664672 27845598 27845690 ENSE00001793473 27848054 27848188 ENSE00001676006 27848630 27848709 ENSE00001665330 27843396 27843493 ENSE00001718020 27841897 27842095 ENSE00001736617 27839620 27839688 ENSE00001660147 27839476 27839534 ENSE00001747287 27831866 27831998 ENSE00001772012 27831391 27831526 ENSE00001591413 27828240 27828345 ENSE00001706519 27826017 27826133 ENSE00001681474 27824167 27824240 ENSE00001767346 27822970 27823061 ENSE00001660597 27821207 27821355 ENSE00001766514 27896136 27896353 ENSE00001667582 27894743 27895009 ENSE00001592213 25727742 25727848 ENSE00001776907 25729370 25729494 ENSE00001725078 25730031 25730140 ENSE00001700142 25731858 25732473 ENSE00001645488 25732847 25732951 ENSE00001633384 25752297 25752397 ENSE00001701227 25759032 25759186 ENSE00001700211 25760375 25760456 ENSE00001624131 25760756 25760787 ENSE00001714386 26385030 26385131 ENSE00001771613 26378973 26379077 ENSE00001677160 9323603 9323893 ENSE00001679028 9311656 9311705 ENSE00001715921 9303716 9303730 ENSE00001780929 9302377 9302423 ENSE00001670508 9302159 9302223 ENSE00001760125 9301927 9301962 ENSE00001765669 9301853 9301925 ENSE00001594565 9301621 9301766 ENSE00001723672 9293012 9293068 ENSE00001659766 9301461 9301502 ENSE00002290744 9344027 9344176 ENSE00002234593 9323618 9323761 ENSE00001723990 7569228 7569288 ENSE00001745366 7567398 7567528 ENSE00001785693 9192996 9193010 ENSE00001643138 9192690 9192799 ENSE00001806627 9190799 9190884 ENSE00001617913 9185120 9187248 ENSE00001725040 9192690 9192791 ENSE00001616038 9192458 9192603 ENSE00001645870 9190799 9190957 ENSE00001746455 9187188 9187248 ENSE00001695542 27764791 27764856 ENSE00001711695 27765188 27766400 ENSE00001622377 24344576 24344683 ENSE00001786914 24345087 24345189 ENSE00001763025 24349747 24349859 ENSE00001649733 22889140 22889383 ENSE00001795209 22891287 22891417 ENSE00001658484 22891809 22891956 ENSE00001602075 22892655 22892718 ENSE00001646110 22892828 22892926 ENSE00001782218 22895969 22896036 ENSE00001712850 22902786 22902859 ENSE00001806612 22903197 22903321 ENSE00001717995 22904714 22904786 ENSE00001712612 3646038 3647587 ENSE00001752848 9904910 9904995 ENSE00001543999 9904163 9904218 ENSE00001731603 9906266 9906760 ENSE00001617820 9905581 9905658 ENSE00001788369 9905341 9905452 ENSE00001672593 9905098 9905243 ENSE00001688242 9904910 9904991 ENSE00001713327 9904196 9904218 ENSE00001592550 20602683 20603011 ENSE00001642025 19949081 19949408 ENSE00001618473 8145122 8145229 ENSE00001629725 8144595 8144697 ENSE00001758450 8139321 8139470 ENSE00001591894 8134356 8134470 ENSE00001757932 8133375 8133485 ENSE00001666134 8133216 8133303 ENSE00001686479 8132490 8132806 ENSE00001653013 10036113 10036711 ENSE00001652052 28390498 28390720 ENSE00001638514 4669726 4670889 ENSE00001732026 20267200 20267292 ENSE00001643224 20269242 20269388 ENSE00001686603 20269833 20269988 ENSE00001722408 19838632 19838960 ENSE00001677525 19921687 19921786 ENSE00001668583 19923007 19923207 ENSE00001727103 19925402 19925469 ENSE00001635486 19925555 19925585 ENSE00001702927 19927108 19927244 ENSE00001667443 19927569 19927715 ENSE00001638683 19930805 19930910 ENSE00001673115 19932214 19932333 ENSE00001615368 19934171 19934244 ENSE00001675564 19935349 19935440 ENSE00001738547 19937061 19937209 ENSE00001674051 23799361 23800927 ENSE00001634395 10011462 10011816 ENSE00001756820 24083189 24083297 ENSE00001674806 24082632 24082735 ENSE00001673237 24079748 24079925 ENSE00001732143 24077660 24077812 ENSE00001679690 24075538 24075652 ENSE00001782041 24074558 24074668 ENSE00001745014 24074388 24074475 ENSE00001743398 24073668 24073966 ENSE00001650266 20033289 20033510 ENSE00001796711 20030904 20031124 ENSE00001805326 20028903 20029103 ENSE00001739171 20026834 20026918 ENSE00001615615 20024579 20024703 ENSE00001644643 9477858 9478325 ENSE00001634743 26829804 26831082 ENSE00001712081 19740393 19740865 ENSE00001691275 19741241 19741282 ENSE00001719617 20566775 20566932 ENSE00001722479 20566130 20566179 ENSE00001650606 20554672 20554800 ENSE00001798385 20554331 20554424 ENSE00001740686 20553567 20553737 ENSE00001660603 20553364 20553457 ENSE00001753397 20552880 20553089 ENSE00001787453 26081100 26081138 ENSE00001755017 26082813 26083036 ENSE00001689362 26084160 26084422 ENSE00001619402 26086058 26086248 ENSE00001707653 19833478 19835057 ENSE00001754048 23069230 23069448 ENSE00001631720 8239704 8240071 ENSE00001598941 16750976 16752238 ENSE00001619110 20257991 20258088 ENSE00001655047 20256569 20256769 ENSE00001663253 20254307 20254374 ENSE00001599244 20254191 20254221 ENSE00001716829 20252531 20252667 ENSE00001740285 20252060 20252206 ENSE00001722377 20248865 20248970 ENSE00001799387 20247442 20247561 ENSE00001639175 20244336 20244426 ENSE00001602332 20242567 20242716 ENSE00001740373 14649708 14649836 ENSE00001638353 14652995 14655149 ENSE00001697673 14656719 14656818 ENSE00001618557 25820526 25821539 ENSE00001760629 25082602 25082762 ENSE00001687747 25109775 25109850 ENSE00001806588 25111655 25111762 ENSE00001713773 25118431 25119431 ENSE00001715524 23473154 23473262 ENSE00001803876 23473708 23473886 ENSE00001802420 23476064 23476181 ENSE00001631333 23476493 23476523 ENSE00001792500 23478520 23478634 ENSE00001606958 23479502 23479612 ENSE00001748340 23479694 23479782 ENSE00001745595 23480206 23480383 ENSE00001655007 23480660 23480781 ENSE00001958730 24549608 24549729 ENSE00003461217 24551591 24551703 ENSE00003566508 24552172 24552275 ENSE00003512617 24557392 24557544 ENSE00003628086 24559555 24559669 ENSE00003475218 24560625 24560735 ENSE00003524115 24561176 24561286 ENSE00003544610 24561721 24561831 ENSE00003519695 24562755 24562865 ENSE00003617706 24562952 24563040 ENSE00003462282 24563452 24564028 ENSE00001775261 24549617 24549729 ENSE00003571276 24551591 24551703 ENSE00003560118 24552172 24552275 ENSE00001663738 24555299 24555476 ENSE00003481268 24557392 24557544 ENSE00003643053 24559555 24559669 ENSE00003478187 24560625 24560735 ENSE00003515241 24561176 24561286 ENSE00003518190 24561721 24561831 ENSE00003566008 24562755 24562865 ENSE00003680149 24562952 24563040 ENSE00003509588 24563452 24564028 ENSE00001594771 24454970 24455117 ENSE00001766942 10007397 10007923 ENSE00001691508 17659096 17659238 ENSE00001674716 17661491 17661821 ENSE00001733692 17663477 17663895 ENSE00001677440 17678652 17678808 ENSE00001757764 17705111 17705211 ENSE00001804714 7995171 7995279 ENSE00001711635 7997274 7997276 ENSE00001760261 7999689 7999866 ENSE00001636850 8001726 8001841 ENSE00001595014 8002167 8002203 ENSE00001745989 8010267 8010379 ENSE00001636511 8011249 8011355 ENSE00001632004 8011435 8011528 ENSE00001798989 8011943 8012244 ENSE00001794129 25204177 25204476 ENSE00001605189 25204818 25205333 ENSE00001600631 2751182 2751693 ENSE00001611586 2749724 2750402 ENSE00001616321 26631479 26631538 ENSE00001618682 26632505 26632610 ENSE00001698182 24065082 24065475 ENSE00001796451 24066464 24066548 ENSE00001650846 24066793 24066871 ENSE00001799290 24066945 24067088 ENSE00001659363 24067206 24067253 ENSE00001700980 14619111 14619171 ENSE00001778840 14600234 14600269 ENSE00001683270 14596531 14596554 ENSE00001612791 14580243 14580305 ENSE00001736429 14571502 14571559 ENSE00001608554 14567945 14567995 ENSE00001712855 14555064 14555099 ENSE00001639452 14551845 14551961 ENSE00001615810 20642973 20643106 ENSE00001622792 20648080 20648236 ENSE00001804045 20648639 20648814 ENSE00001713121 20649191 20649286 ENSE00001632993 28737695 28737748 ENSE00001691206 28733545 28733707 ENSE00001652425 28732789 28732913 ENSE00001775619 27412731 27412843 ENSE00001799498 27413254 27413355 ENSE00001705987 27415744 27415925 ENSE00001714230 27418670 27418780 ENSE00001736832 27418862 27418950 ENSE00001670100 27419364 27419678 ENSE00001801471 28081780 28082028 ENSE00001777749 28079980 28080162 ENSE00001744076 8281841 8282095 ENSE00001648363 8281078 8281495 ENSE00001761637 26837938 26838222 ENSE00001646263 26838564 26839079 ENSE00001738572 28137388 28137719 ENSE00001647752 26098309 26098440 ENSE00001779865 26093094 26093247 ENSE00001620696 26092551 26092738 ENSE00001763493 26092074 26092169 ENSE00001791861 25824651 25824982 ENSE00001806367 17053427 17053630 ENSE00001727723 23719571 23719956 ENSE00001647639 23718482 23718541 ENSE00001611070 23718159 23718285 ENSE00001757809 23717738 23717787 ENSE00001649434 20949636 20949966 ENSE00001694343 8771032 8771317 ENSE00001742226 8769642 8769780 ENSE00001769856 8769411 8769554 ENSE00001698979 8769244 8769299 ENSE00001747233 24997731 24997790 ENSE00001718178 24998757 24998862 ENSE00001743100 23695501 23695897 ENSE00001753135 23694449 23694514 ENSE00001762790 23694122 23694185 ENSE00001609952 23693890 23694035 ENSE00001788043 23693725 23693772 ENSE00001613955 27245879 27246039 ENSE00001793058 27218793 27218868 ENSE00001658199 27216881 27216988 ENSE00001702789 27209230 27210230 ENSE00001670654 9650924 9651009 ENSE00001742535 9653511 9653653 ENSE00001782038 9654904 9655122 ENSE00001628818 9213276 9213290 ENSE00001645989 9212970 9213079 ENSE00001671314 9211075 9211160 ENSE00001645127 9205412 9207525 ENSE00001623303 9212970 9213071 ENSE00003646877 9212738 9212883 ENSE00001624981 9211075 9211233 ENSE00001776488 9207466 9207525 ENSE00002237197 9234756 9235047 ENSE00002305238 9234328 9234347 ENSE00002214727 9232876 9232920 ENSE00002234764 9224460 9224505 ENSE00001705725 9213276 9213340 ENSE00001777540 9213044 9213079 ENSE00001698821 9212970 9213042 ENSE00003487206 9212738 9212883 ENSE00001776941 9212578 9212619 ENSE00001786986 9214410 9214701 ENSE00001636298 9213969 9214001 ENSE00001724614 9213752 9213783 ENSE00001641069 9213494 9213539 ENSE00002259310 9234315 9234347 ENSE00002243480 9234098 9234129 ENSE00001731628 9233840 9233885 ENSE00001702837 9233622 9233686 ENSE00001777950 9233390 9233425 ENSE00001759506 9233316 9233388 ENSE00003471081 9233084 9233229 ENSE00001630624 9232924 9232965 ENSE00001755166 14914995 14915763 ENSE00001729630 14913906 14914649 ENSE00001708301 26116730 26116841 ENSE00001718075 26114234 26114365 ENSE00001596904 26113711 26113789 ENSE00001691278 19304706 19305532 ENSE00001592952 24683194 24683352 ENSE00001667759 24683838 24683996 ENSE00001788558 19630862 19630918 ENSE00001790420 19630448 19630556 ENSE00001783650 19630277 19630367 ENSE00001800896 19628716 19629764 ENSE00001753165 22551937 22551996 ENSE00001624781 22557394 22557905 ENSE00001800341 22558157 22558682 ENSE00001796314 27540773 27540866 ENSE00001653980 27533064 27533232 ENSE00001596444 27524447 27525025 ENSE00001638780 16915885 16915913 ENSE00001750121 16913156 16913224 ENSE00001766520 16910502 16910589 ENSE00001648650 16905522 16905867 ENSE00001720861 24210845 24211859 ENSE00001806349 9558704 9558905 ENSE00001729950 9555262 9555366 ENSE00001774191 9236030 9236561 ENSE00003692666 9237169 9237246 ENSE00001747539 9237375 9237486 ENSE00001719444 9237588 9237733 ENSE00001781353 9237840 9237921 ENSE00001954357 9238616 9238826 ENSE00003617259 9236076 9236561 ENSE00003611797 9237829 9237921 ENSE00001758618 9238616 9238825 ENSE00003511805 9236076 9236561 ENSE00003461293 9237169 9237246 ENSE00003601991 9237375 9237921 ENSE00001879368 9238049 9238832 ENSE00001932930 9237436 9237733 ENSE00003565177 9237829 9237921 ENSE00001931598 9238616 9238817 ENSE00003463520 9306122 9306267 ENSE00003659094 9306374 9306455 ENSE00003525623 9307148 9307357 ENSE00001618274 9236076 9236162 ENSE00001610531 9236424 9236561 ENSE00003525860 9237375 9237921 ENSE00001724421 20442064 20442235 ENSE00001776105 20443132 20443571 ENSE00001726546 20443649 20443794 ENSE00001754461 20443924 20444031 ENSE00001804017 20444676 20444747 ENSE00001740783 20444998 20445051 ENSE00001721829 20445778 20445876 ENSE00001689481 20446357 20446440 ENSE00001600079 20446520 20446647 ENSE00001770854 19868881 19870005 ENSE00001707259 19995523 19995588 ENSE00001614194 19993979 19995178 ENSE00001610381 24329997 24330390 ENSE00001729283 24331382 24331463 ENSE00001736394 24331702 24331772 ENSE00001611617 24331860 24332003 ENSE00001675926 24332121 24332168 ENSE00001786158 2799112 2799161 ENSE00001605858 2797411 2798407 ENSE00001748625 2797042 2797083 ENSE00001628114 9684128 9684305 ENSE00001632712 9673456 9673605 ENSE00001592139 9671356 9671455 ENSE00001666942 9670438 9670548 ENSE00001734562 9669930 9670040 ENSE00001636017 9669744 9669819 ENSE00001733825 9669027 9669328 ENSE00001657129 24355478 24355590 ENSE00001754863 24356104 24356174 ENSE00001761172 24358572 24358748 ENSE00001773734 24362613 24362727 ENSE00001757026 22680157 22681114 ENSE00001688639 22669238 22669342 ENSE00001719273 22631758 22631867 ENSE00001669312 22630075 22630134 ENSE00001646929 22628314 22628553 ENSE00001717483 22627554 22627708 ENSE00001652776 22680157 22680293 ENSE00001755411 22669140 22669342 ENSE00001642256 28500435 28500565 ENSE00001701173 28494607 28494725 ENSE00001806782 28484982 28485141 ENSE00001713752 28483524 28483668 ENSE00001655231 28481793 28481866 ENSE00001777012 28479872 28479951 ENSE00001591489 28479076 28479215 ENSE00001678181 28475093 28475275 ENSE00002438533 28437195 28437284 ENSE00001666272 28427573 28427776 ENSE00001694641 28425413 28425602 ENSE00001689979 28425212 28425324 ENSE00001680774 28424070 28424111 ENSE00001638605 26236272 26236493 ENSE00001619709 26233907 26234126 ENSE00001732018 26231919 26232108 ENSE00001600167 26229975 26230103 ENSE00001682049 26227851 26227970 ENSE00001691510 20438909 20439381 ENSE00001725503 20438493 20438534 ENSE00001806707 3904538 3904761 ENSE00001708248 3968027 3968361 ENSE00001747579 27959160 27960713 ENSE00001742312 20633950 20634023 ENSE00001785470 20632556 20632756 ENSE00001687737 20630270 20630337 ENSE00001738169 20630152 20630182 ENSE00001804747 20625798 20625934 ENSE00001597616 20625334 20625501 ENSE00001629276 20622118 20622223 ENSE00001688905 20619831 20619949 ENSE00001626846 20617975 20618044 ENSE00001658632 20616779 20616869 ENSE00001653676 20615036 20615149 ENSE00001771502 23842919 23843004 ENSE00001774620 23840886 23841109 ENSE00001774789 23839132 23839321 ENSE00001793905 20309770 20310894 ENSE00001678856 3734347 3734763 ENSE00002028706 9195406 9195937 ENSE00003676294 9196545 9196622 ENSE00002045368 9196751 9196862 ENSE00001638906 9196964 9197109 ENSE00003564905 9197216 9197297 ENSE00001885622 9197992 9198202 ENSE00003489927 9195452 9195937 ENSE00001801838 9197205 9197297 ENSE00001603826 9197992 9198201 ENSE00003579602 9195452 9195937 ENSE00003593279 9196545 9196622 ENSE00001943292 9196751 9197297 ENSE00001940527 9197425 9198208 ENSE00001908923 9196812 9197109 ENSE00003618941 9197216 9197297 ENSE00001859698 9197992 9198193 ENSE00003586983 9217242 9217387 ENSE00003603865 9217494 9217575 ENSE00001720810 9218270 9218479 ENSE00002220142 9195452 9195688 ENSE00002247562 9215950 9216150 ENSE00001350919 9216153 9216215 ENSE00003564996 9216823 9216900 ENSE00003465500 9217029 9217140 ENSE00001159243 9195501 9195937 ENSE00002206433 9197216 9197317 ENSE00001806624 23023223 23024223 ENSE00001696124 24204040 24204260 ENSE00001722283 24202119 24202236 ENSE00001646198 24200144 24200332 ENSE00001630914 24197657 24197785 ENSE00001751441 24195902 24195940 ENSE00001671403 6229369 6229454 ENSE00001660336 6226725 6226867 ENSE00001785311 6225260 6225478 ENSE00001640432 27725937 27726142 ENSE00001650835 27728306 27728529 ENSE00001768767 27730334 27730512 ENSE00001734323 27732325 27732414 ENSE00001757798 27734462 27734591 ENSE00001754078 24017478 24017864 ENSE00001801282 24019109 24019276 ENSE00001669347 24019648 24019697 ENSE00001781088 7805612 7805681 ENSE00001788779 7804676 7804745 ENSE00001602297 7801735 7801840 ENSE00001712311 7801038 7801056 ENSE00001663391 24453707 24454098 ENSE00001634582 24452302 24452367 ENSE00001626840 24452072 24452217 ENSE00001668677 8841768 8842136 ENSE00001765004 8840028 8840072 ENSE00001613408 8839792 8839935 ENSE00001664411 23858456 23860106 ENSE00001675278 9342754 9342768 ENSE00001648707 9342449 9342558 ENSE00001614122 9340560 9340645 ENSE00001755116 9334896 9337009 ENSE00001615889 9342449 9342550 ENSE00001739908 9342217 9342362 ENSE00001694789 9340560 9340718 ENSE00001664818 9336950 9337009 ENSE00001596967 25669468 25669869 ENSE00001793420 25670900 25670956 ENSE00001682691 25671157 25671280 ENSE00001762358 25671373 25671516 ENSE00001653366 20694212 20694542 ENSE00001719426 20230369 20230696 ENSE00001766548 20740303 20740446 ENSE00001718469 24760122 24760228 ENSE00001757100 24758482 24758611 ENSE00001774249 24757838 24757947 ENSE00001660181 24755505 24756120 ENSE00001783530 24755021 24755131 ENSE00001683819 24735579 24735679 ENSE00001748455 24728791 24728945 ENSE00001605377 24727528 24727594 ENSE00001631605 24727136 24727229 ENSE00001743559 19691196 19691634 ENSE00001734255 19688583 19688700 ENSE00001754684 19667656 19667890 ENSE00001738421 19665922 19666006 ENSE00001606680 19664680 19665834 ENSE00001722745 24915822 24915934 ENSE00001612746 24915310 24915411 ENSE00001617577 24912745 24912921 ENSE00001806297 24909883 24909993 ENSE00001803898 24909713 24909801 ENSE00001607696 24908998 24909299 ENSE00001627359 24674428 24674648 ENSE00001652271 24676451 24676569 ENSE00001614594 24678356 24678544 ENSE00001693270 24680903 24681031 ENSE00001639643 24682748 24682786 ENSE00001679003 27164646 27165450 ENSE00001610666 28069535 28069666 ENSE00001663003 28074809 28074946 ENSE00001597803 28075090 28075126 ENSE00001638987 28075341 28075498 ENSE00001596879 28075881 28075973 ENSE00001768357 20973224 20973715 ENSE00001694457 26328624 26329218 ENSE00001592853 26063388 26063870 ENSE00001685903 27874637 27874740 ENSE00001745631 27876939 27877073 ENSE00001676858 27879431 27879535 ENSE00001724152 24118460 24118566 ENSE00001669607 24120079 24120206 ENSE00001639143 24120743 24120852 ENSE00001650621 24122570 24123185 ENSE00001633081 24123559 24123669 ENSE00001602954 24143010 24143110 ENSE00001699591 24149743 24149894 ENSE00001771661 24151091 24151156 ENSE00001632036 24151455 24151496 ENSE00001791163 20323252 20323355 ENSE00001745360 20325864 20325979 ENSE00001646564 20338099 20338370 ENSE00001732601 5075256 5076110 ENSE00001622837 26197569 26197634 ENSE00001747409 26196025 26197240 ENSE00001674006 10009199 10010334 ENSE00001636194 26102716 26102943 ENSE00001794176 26105997 26106365 ENSE00001756377 9458777 9458885 ENSE00001746468 9458236 9458339 ENSE00001745811 9454762 9454936 ENSE00001752960 9452699 9452845 ENSE00001702756 9450030 9450143 ENSE00001799300 9449062 9449172 ENSE00001670043 9448893 9448976 ENSE00001770923 9448180 9448480 ENSE00001616687 28772667 28773306 ENSE00001678149 2870953 2871258 ENSE00001757585 2947325 2947382 ENSE00001696132 2965036 2965258 ENSE00001677281 2871039 2871258 ENSE00001620860 2965036 2965097 ENSE00001694023 2970126 2970313 ENSE00001634403 25954968 25955206 ENSE00001705880 28140831 28141844 ENSE00001632978 9707273 9707748 ENSE00001683725 9708358 9708390 ENSE00001617130 8898635 8898771 ENSE00001728356 8899096 8899270 ENSE00001783134 8902714 8902829 ENSE00001750562 8904498 8904571 ENSE00001675644 8905717 8905808 ENSE00001603923 8907841 8908029 ENSE00001804178 26646410 26647652 ENSE00001788264 24214967 24215298 ENSE00001800082 27738263 27738492 ENSE00001746593 27736470 27736660 ENSE00001614266 2696023 2696259 ENSE00001714431 26250254 26250447 ENSE00001710497 26250751 26252165 ENSE00001691217 14378586 14378737 ENSE00001804878 14374685 14374811 ENSE00001737381 14373025 14373222 ENSE00001717478 9003694 9005311 ENSE00001650635 8506335 8506447 ENSE00001733122 8512173 8512368 ENSE00001613384 8512720 8512883 ENSE00001715519 8572513 8572600 ENSE00001776324 8573144 8573324 ENSE00001657190 25892713 25892840 ENSE00001765641 25887431 25887580 ENSE00001718086 25887252 25887281 ENSE00001712499 25886883 25887041 ENSE00001732839 25886405 25886500 ENSE00001623599 24195336 24195494 ENSE00001768555 24194701 24194850 ENSE00001607684 22173972 22174090 ENSE00001704650 22167626 22167714 ENSE00001699413 22163071 22163585 ENSE00001774695 6974434 6974543 ENSE00001648340 6968774 6968868 ENSE00001644797 26118927 26119025 ENSE00001599057 26120341 26120540 ENSE00001651852 26122748 26122815 ENSE00001726876 26122901 26122933 ENSE00001788414 26130439 26130572 ENSE00001741171 26130911 26131046 ENSE00001782936 26134091 26134199 ENSE00001616123 26136306 26136418 ENSE00001758121 26138195 26138268 ENSE00001695453 26139373 26139464 ENSE00001664413 26141080 26141228 ENSE00001694546 27881271 27881307 ENSE00001642941 27879374 27879595 ENSE00001689808 27877987 27878249 ENSE00001742552 27876158 27876350 ENSE00001659626 9502838 9503010 ENSE00001688131 9506532 9506619 ENSE00001679725 6388504 6388970 ENSE00001666493 23382992 23383975 ENSE00001693593 28007090 28007415 ENSE00001728711 14442350 14443562 ENSE00001767583 20285560 20285685 ENSE00001743874 20284895 20284986 ENSE00001592268 20283081 20283269 ENSE00001612213 25171741 25171991 ENSE00001761722 25172300 25172810 ENSE00001800398 9172360 9172441 ENSE00001695576 9167489 9167665 ENSE00001763167 25911619 25911730 ENSE00001732672 25909520 25909664 ENSE00001649962 25908985 25909070 ENSE00001702931 20344721 20346300 ENSE00001772654 25897335 25897907 ENSE00001767851 28050665 28050757 ENSE00001731820 28052712 28052856 ENSE00001621307 28053305 28053397 ENSE00001778513 9068524 9068856 ENSE00001789966 3550846 3551909 ENSE00001599138 26805484 26805714 ENSE00001781743 26806034 26806553 ENSE00001615694 2870354 2870667 ENSE00001670294 2849879 2849968 ENSE00001787837 2834885 2834980 ENSE00001664412 2870579 2870612 ENSE00001751906 2870354 2870442 ENSE00001659262 2869669 2869964 ENSE00001618370 20278413 20278550 ENSE00001740946 20278706 20278734 ENSE00001805102 20278947 20279105 ENSE00001724905 20279486 20279581 ENSE00001670949 25195394 25195507 ENSE00001795349 25195827 25195883 ENSE00001626354 25196049 25197342 ENSE00001715878 28157582 28157740 ENSE00001703739 28158226 28158384 ENSE00001796121 20096229 20096449 ENSE00001737699 20098617 20098835 ENSE00001743166 20100636 20100825 ENSE00001784518 20102823 20102907 ENSE00001605344 20105048 20105140 ENSE00001672475 20488139 20488576 ENSE00001640636 20491077 20491194 ENSE00001758131 20511886 20512120 ENSE00001710040 20513770 20513854 ENSE00001790139 20513942 20515096 ENSE00001706607 20691244 20691509 ENSE00001779202 27633431 27633809 ENSE00001632989 6705748 6706293 ENSE00001734013 27535139 27537421 ENSE00001598660 27537832 27537958 ENSE00001744860 8551762 8551919 ENSE00001765620 8551411 8551473 ENSE00001794752 26425509 26427287 ENSE00001781093 26425021 26425442 ENSE00001614820 26424484 26424610 ENSE00001746702 14746216 14746333 ENSE00001794515 14744661 14744805 ENSE00001629993 14731962 14732097 ENSE00001649124 14731558 14731665 ENSE00001774864 14730915 14731055 ENSE00001494279 9175073 9175622 ENSE00003638561 9176230 9176307 ENSE00001734097 9176436 9176547 ENSE00001697845 9176649 9176794 ENSE00001703875 9176901 9176982 ENSE00001897275 9177677 9177887 ENSE00003476280 9175119 9175622 ENSE00003578244 9176890 9176982 ENSE00001711997 9177677 9177886 ENSE00003579134 9175119 9175622 ENSE00003581570 9176230 9176307 ENSE00001855646 9176436 9176982 ENSE00001810355 9177110 9177893 ENSE00001825143 9176497 9176794 ENSE00003677158 9176890 9176982 ENSE00001840824 9177677 9177878 ENSE00001661126 28546758 28546808 ENSE00001647030 28547106 28547377 ENSE00001717777 14774265 14774637 ENSE00001661171 14776571 14776617 ENSE00001804864 14798442 14798535 ENSE00001769405 14802255 14802370 ENSE00001538271 14799393 14804162 ENSE00001677769 14774468 14774637 ENSE00001720726 14799614 14800184 ENSE00002231970 14774284 14774637 ENSE00002219117 14776571 14776614 ENSE00001660519 27539301 27540203 ENSE00001721076 15060008 15060090 ENSE00001690255 15059583 15059686 ENSE00001766707 15058196 15058215 ENSE00001768739 15057933 15057980 ENSE00001787917 15057797 15057831 ENSE00001595199 15057528 15057571 ENSE00001629383 15047112 15047196 ENSE00001762780 15042075 15042237 ENSE00001621226 26153058 26153384 ENSE00001789186 9461792 9462154 ENSE00001771580 9463179 9463265 ENSE00001633534 9463471 9463583 ENSE00001599361 9463670 9463810 ENSE00001743476 9463921 9463961 ENSE00001600092 24663389 24663720 ENSE00001680177 8232073 8233191 ENSE00001758106 13901758 13903233 ENSE00001797129 26549565 26549673 ENSE00001724851 26549053 26549154 ENSE00001706454 26546483 26546664 ENSE00001717052 26543636 26543746 ENSE00001779101 26543466 26543554 ENSE00001603762 26542751 26543052 ENSE00001727355 23696765 23696912 ENSE00001718460 23698774 23698886 ENSE00001661257 23699361 23699464 ENSE00003587206 23702484 23702661 ENSE00003656490 23704577 23704729 ENSE00003571694 23706740 23706854 ENSE00003569851 23707810 23707920 ENSE00003633827 23708362 23708472 ENSE00003550118 23708907 23709017 ENSE00003663549 23709939 23710049 ENSE00003674760 23710136 23710224 ENSE00003536697 23710636 23711212 ENSE00001670247 23696790 23696912 ENSE00003581140 23704577 23704729 ENSE00003460783 23706740 23706854 ENSE00003639215 23707810 23707920 ENSE00003489167 23708362 23708472 ENSE00003511329 23708907 23709017 ENSE00003525217 23709939 23710049 ENSE00003545208 23710136 23710224 ENSE00003621655 23710636 23711212 ENSE00001600029 23698778 23698886 ENSE00001632888 23710636 23711210 ENSE00001795478 23673258 23673371 ENSE00003461810 23675233 23675345 ENSE00003638069 23675820 23675923 ENSE00003462284 23702484 23702661 ENSE00003673811 23704577 23704729 ENSE00003599248 23706740 23706854 ENSE00001635427 21489455 21490459 ENSE00001789043 6172640 6173115 ENSE00001629179 6171998 6172030 ENSE00001774484 17567915 17567954 ENSE00001712382 17493473 17493722 ENSE00001710358 17460542 17460746 ENSE00001661949 3161849 3162867 ENSE00001688800 28148401 28148623 ENSE00001679843 28150422 28150540 ENSE00001627555 28152327 28152516 ENSE00001792441 28154875 28155003 ENSE00003710715 7644562 7644748 ENSE00001628915 7617404 7617512 ENSE00001624117 7597498 7597881 ENSE00001599548 7589897 7590099 ENSE00001591968 7581026 7581138 ENSE00001803550 7677195 7677302 ENSE00001675697 7673536 7673645 ENSE00001644958 7644875 7645069 ENSE00001678529 7610636 7611068 ENSE00001637728 9363082 9363096 ENSE00001601067 9362776 9362885 ENSE00001733722 9360885 9360970 ENSE00001707869 9355208 9357334 ENSE00001654072 9362776 9362877 ENSE00003461311 9362544 9362689 ENSE00001709675 9360885 9361043 ENSE00001705207 9357275 9357334 ENSE00003224946 9364215 9364506 ENSE00003096789 9363787 9363806 ENSE00003004848 9363280 9363308 ENSE00003055029 9363163 9363219 ENSE00003198125 9363082 9363148 ENSE00003165650 9362850 9362885 ENSE00003163421 9362776 9362848 ENSE00003611037 9362544 9362689 ENSE00003028414 9362384 9362425 ENSE00001611400 6131875 6131994 ENSE00001669863 6129985 6130070 ENSE00001673478 6124308 6126433 ENSE00001712586 6131875 6131976 ENSE00003709639 6131643 6131788 ENSE00001663750 6129985 6130143 ENSE00001795860 6126374 6126433 ENSE00003709660 6130047 6130143 ENSE00001688314 8240282 8240751 ENSE00001698575 28234536 28234640 ENSE00001669923 28232883 28233007 ENSE00001614971 28232234 28232346 ENSE00001661020 28229897 28230516 ENSE00001744230 28229431 28229527 ENSE00001720034 28209980 28210076 ENSE00001752268 28203178 28203341 ENSE00001592390 28201926 28201996 ENSE00001666495 9789162 9789270 ENSE00001728287 9789732 9789807 ENSE00001639523 9795049 9795161 ENSE00001648850 9796028 9796138 ENSE00001756419 9796219 9796307 ENSE00001707777 9796721 9797032 ENSE00001796289 5205786 5207005 ENSE00002291273 5205788 5206981 ENSE00001772277 27869163 27869328 ENSE00001708810 27869664 27869857 ENSE00001618426 27870239 27870333 ENSE00001635775 28354223 28354295 ENSE00001597436 28344478 28344604 ENSE00001731360 24585087 24585287 ENSE00001688179 24585622 24585931 ENSE00001696656 24592479 24592619 ENSE00001742686 24602582 24602804 ENSE00001695575 24603113 24603198 ENSE00001748239 24610377 24610495 ENSE00001686372 24610926 24611279 ENSE00001757378 24624912 24625001 ENSE00001738135 24626468 24626803 ENSE00001662296 24628604 24628689 ENSE00001781418 24628810 24629006 ENSE00001735320 24629551 24629668 ENSE00001802546 24630184 24630861 ENSE00001607267 24626684 24626803 ENSE00001677719 24630184 24630448 ENSE00001719566 24631498 24631739 ENSE00001779056 6174083 6174412 ENSE00001754002 6175464 6175541 ENSE00001765437 6175737 6175852 ENSE00001739366 6175939 6175961 ENSE00001795992 5661341 5661778 ENSE00001739581 9925635 9925740 ENSE00001645033 9926775 9927195 ENSE00001700611 26716349 26716509 ENSE00001798741 26743516 26743591 ENSE00001724601 26745396 26745503 ENSE00001655881 26752172 26753172 ENSE00001742351 16192955 16193049 ENSE00001606802 16193186 16193329 ENSE00001592567 16198415 16198480 ENSE00001620082 15272747 15274125 ENSE00001793879 15271867 15272027 ENSE00001621504 15265842 15265935 ENSE00001741426 15272805 15273460 ENSE00001721819 15271184 15271380 ENSE00001760736 20811557 20812165 ENSE00001706919 28044702 28044800 ENSE00001668409 28043278 28043483 ENSE00001658969 28027522 28027656 ENSE00001806118 28027030 28027177 ENSE00001766229 28023878 28023983 ENSE00001720050 28021112 28021230 ENSE00001705255 28019252 28019325 ENSE00001599768 28018078 28018149 ENSE00001723842 19901223 19901364 ENSE00001600158 19901042 19901070 ENSE00001782991 19900671 19900841 ENSE00001648973 19900195 19900290 ENSE00001803460 27673796 27673933 ENSE00001656819 27671351 27671435 ENSE00001682459 27670168 27670257 ENSE00001653328 27665826 27665884 ENSE00001804144 27659272 27659320 ENSE00001709330 27658448 27658543 ENSE00001598977 14077914 14078105 ENSE00001609880 14088788 14093745 ENSE00001671213 14099618 14100561 ENSE00001674255 14106187 14108092 ENSE00001623621 9928411 9928816 ENSE00001799526 23628730 23629049 ENSE00001753337 23627615 23627697 ENSE00001695538 23627270 23627386 ENSE00001794473 59001391 59001635 ENSE00001695426 6364626 6364798 ENSE00001695477 6361017 6361112 ENSE00001643114 26288505 26288642 ENSE00001795389 26291003 26291087 ENSE00001629300 26292177 26292270 ENSE00001702866 26296554 26296612 ENSE00001660124 26303118 26303166 ENSE00001619869 26303895 26303990 ENSE00001716125 17019778 17019948 ENSE00001626278 27314746 27315988 ENSE00001758513 9365489 9366020 ENSE00003678107 9366628 9366705 ENSE00001645840 9366834 9366945 ENSE00003600117 9367047 9367192 ENSE00003511199 9367299 9367380 ENSE00001900367 9368075 9368285 ENSE00003531660 9365535 9366020 ENSE00001716327 9367288 9367380 ENSE00001604245 9368075 9368284 ENSE00003623643 9365535 9366020 ENSE00003481640 9366628 9366705 ENSE00001885335 9366834 9367380 ENSE00001840919 9367508 9368291 ENSE00001860458 9366895 9367192 ENSE00003665834 9367299 9367380 ENSE00001947561 9368075 9368276 ENSE00001665114 9365535 9365621 ENSE00001608967 9365883 9366020 ENSE00003550132 9367047 9367192 ENSE00001799927 20903729 20903872 ENSE00001728219 7557118 7557589 ENSE00001660382 7556424 7556497 ENSE00001592812 7556182 7556292 ENSE00001628878 7555938 7556083 ENSE00001744875 7555780 7555844 ENSE00001601315 14365457 14365582 ENSE00001626390 14365918 14366162 ENSE00001803290 20340818 20341146 ENSE00001772292 23567656 23567881 ENSE00001707613 25872620 25872955 ENSE00001679661 25862069 25862848 ENSE00001746820 25695956 25696297 ENSE00001781854 25696762 25696800 ENSE00001650660 25697030 25697104 ENSE00001695376 25697200 25697339 ENSE00001765364 25697457 25697532 ENSE00001648735 7558552 7558878 ENSE00001646873 7560201 7560318 ENSE00001718144 7560405 7560574 ENSE00001762583 7560673 7560719 ENSE00001727148 9871697 9871796 ENSE00001611218 9871164 9871264 ENSE00001798859 9867998 9868175 ENSE00001631408 9864119 9864270 ENSE00001610747 9861966 9862080 ENSE00001695935 9860979 9861089 ENSE00001751980 9860804 9860892 ENSE00001795242 9860098 9860398 ENSE00002293458 9868005 9868142 ENSE00001661837 9385717 9386189 ENSE00001780404 9386797 9386874 ENSE00001761447 9387003 9387114 ENSE00001796958 9387216 9387360 ENSE00001609132 9387456 9387548 ENSE00001624832 9388269 9388290 ENSE00001791982 24251897 24252016 ENSE00001595474 24249032 24249149 ENSE00001710293 24248252 24248516 ENSE00001792666 24246961 24247202 ENSE00001799370 24293431 24293631 ENSE00001733114 24292787 24293096 ENSE00001657618 24286097 24286237 ENSE00001783522 24275906 24276128 ENSE00001698815 24275512 24275597 ENSE00001706895 24268215 24268333 ENSE00001789274 24267431 24267784 ENSE00001654967 24253699 24253788 ENSE00001692849 24251897 24252232 ENSE00001679112 24250011 24250096 ENSE00001694527 24249694 24249890 ENSE00001769353 24247839 24248516 ENSE00001731828 23823812 23824028 ENSE00001720641 23826649 23826863 ENSE00001658227 23828985 23829162 ENSE00001797496 23831970 23832096 ENSE00001739891 23834456 23835359 ENSE00001634813 23835770 23835894 ENSE00001793150 7672965 7673120 ENSE00001702273 7677902 7678724 ENSE00001639020 6111595 6111651 ENSE00003553084 6111336 6111481 ENSE00001663564 6110487 6110795 ENSE00001791643 6026843 6027306 ENSE00001802023 23598954 23599131 ENSE00001693799 23596577 23596729 ENSE00001692050 23594470 23594584 ENSE00001799280 23593473 23593583 ENSE00001673716 23593292 23593380 ENSE00001673218 23592583 23592883 ENSE00001735464 25917379 25917476 ENSE00001733578 25918895 25919096 ENSE00001790322 25929787 25929855 ENSE00001797275 25929940 25929970 ENSE00001737717 25930761 25930884 ENSE00001693294 25934719 25934853 ENSE00001707543 25935198 25935343 ENSE00001761870 25938390 25938496 ENSE00001624501 25941145 25941263 ENSE00001635783 25943050 25943123 ENSE00001736833 25944226 25944297 ENSE00001766910 23292756 23293067 ENSE00001794575 10027986 10029907 ENSE00001739223 26223946 26224167 ENSE00001657411 26225770 26225959 ENSE00001652940 28089415 28089750 ENSE00001752327 28099520 28100299 ENSE00001634021 20063469 20063633 ENSE00001709795 20063942 20065380 ENSE00001734007 6311475 6311676 ENSE00001620336 6315014 6315118 ENSE00001679045 20108912 20109132 ENSE00001662816 20107081 20107289 ENSE00001772499 2657868 2658369 ENSE00001762435 6768794 6768889 ENSE00001777650 6769188 6769413 ENSE00001788545 9233622 9233636 ENSE00001744623 9233316 9233425 ENSE00001769532 9231415 9231500 ENSE00001679232 9225731 9227859 ENSE00001651045 9233316 9233417 ENSE00003512039 9233084 9233229 ENSE00001780836 9231415 9231573 ENSE00001616192 9227800 9227859 ENSE00001618439 27712010 27712180 ENSE00001613903 27710269 27711710 ENSE00001697534 24548322 24548715 ENSE00001718987 24547249 24547333 ENSE00001618280 24546939 24547004 ENSE00001681425 24546709 24546852 ENSE00001658411 24546550 24546591 ENSE00001797328 28780670 28780799 ENSE00001638296 28779492 28779578 ENSE00001681574 28776794 28776896 ENSE00001741452 28774418 28774584 ENSE00001725096 28774090 28774169 ENSE00001670663 28769733 28769813 ENSE00001752207 28768659 28768755 ENSE00001687652 28767920 28768042 ENSE00001747631 28761441 28761678 ENSE00001702742 28760301 28761109 ENSE00001647502 28757860 28757954 ENSE00001744948 28747038 28747169 ENSE00001663098 28740998 28741192 ENSE00001745034 24086159 24086490 ENSE00001592977 24086970 24087008 ENSE00001710578 24087207 24087316 ENSE00001639465 24087404 24087547 ENSE00001714793 24087665 24087740 ENSE00001767839 22148951 22149738 ENSE00001716848 22148461 22148590 ENSE00001766151 20670463 20670954 ENSE00001747238 7543952 7544065 ENSE00001683875 7543407 7543512 ENSE00001737985 7540669 7540779 ENSE00001745774 7540491 7540579 ENSE00001733068 7539784 7540083 ENSE00001290990 9324922 9325425 ENSE00001663813 9326033 9326110 ENSE00003569983 9326239 9326350 ENSE00003622104 9326452 9326597 ENSE00003482640 9326704 9326785 ENSE00003512313 9327480 9327689 ENSE00001696304 9324922 9325008 ENSE00001597607 9325288 9325425 ENSE00003468775 9326239 9326350 ENSE00003536218 9326452 9326597 ENSE00003492729 9326704 9326785 ENSE00003690238 9327480 9327689 ENSE00001761519 21010150 21010221 ENSE00001788634 21011415 21011615 ENSE00001681234 21013835 21013899 ENSE00001682885 21013987 21014016 ENSE00001673336 21018235 21018371 ENSE00001695625 21018720 21018835 ENSE00001609688 21021946 21022052 ENSE00001655456 21024221 21024338 ENSE00001692470 21026120 21026187 ENSE00001762760 21027300 21027399 ENSE00001659235 21029026 21029166 ENSE00001761647 20987993 20988213 ENSE00001593456 20988983 20989106 ENSE00001801031 20989185 20989278 ENSE00001625027 20991185 20991373 ENSE00001685429 9042006 9042220 ENSE00001591638 9039003 9039209 ENSE00001627602 9036701 9036890 ENSE00001792305 9031201 9031324 ENSE00001757037 9027797 9028681 ENSE00001684075 9027238 9027361 ENSE00001723160 19737527 19737712 ENSE00001611031 19736501 19736641 ENSE00001786310 19736203 19736318 ENSE00001774959 19735972 19736125 ENSE00001686516 19735744 19735868 ENSE00001719847 19735027 19735099 ENSE00001637326 19734685 19734776 ENSE00001667900 19733897 19733995 ENSE00001663539 19733340 19733419 ENSE00001684864 19733139 19733262 ENSE00001801245 6134634 6135110 ENSE00001673942 6135717 6135794 ENSE00001616659 6135923 6136033 ENSE00001720897 6136133 6136275 ENSE00001765257 6136383 6136471 ENSE00001690000 6137170 6137316 ENSE00001716389 9748407 9748463 ENSE00001712560 9748577 9748722 ENSE00001616878 9749263 9749571 ENSE00001763631 27632787 27633012 ENSE00001727939 27633257 27633469 ENSE00003523445 26360936 26360978 ENSE00003487606 26360671 26360749 ENSE00003671977 26359202 26359551 ENSE00003601792 26358846 26358903 ENSE00003665075 26357415 26357489 ENSE00003544401 26356906 26356994 ENSE00003690828 26356462 26356650 ENSE00003689528 26356280 26356372 ENSE00003469618 26356114 26356197 ENSE00002089038 26356197 26356279 ENSE00001747437 7938643 7938764 ENSE00001676711 7936937 7938159 ENSE00001663038 20790859 20790963 ENSE00001745094 20788906 20789042 ENSE00001639312 20783952 20784123 ENSE00001691121 20771224 20771330 ENSE00001731541 20769344 20769471 ENSE00001801724 20767634 20767707 ENSE00001637732 20765910 20766045 ENSE00001620479 20764913 20765042 ENSE00001596214 20764267 20764378 ENSE00001632411 20761593 20762219 ENSE00001598287 20761106 20761217 ENSE00003465401 20750492 20750592 ENSE00003603784 20749298 20749434 ENSE00001607039 20745796 20745946 ENSE00001725327 20744540 20744606 ENSE00001768509 20743949 20744242 ENSE00003484855 27629055 27629777 ENSE00003584721 27632781 27632852 ENSE00001805078 26796955 26797681 ENSE00001651627 7859028 7859847 ENSE00001897973 15863536 15863885 ENSE00003707476 15902799 15902846 ENSE00001833379 15970382 15970604 ENSE00001943337 15980947 15981130 ENSE00001869013 15983562 15983678 ENSE00001819899 15999138 15999343 ENSE00001871038 16014754 16014848 ENSE00001853509 16017561 16017731 ENSE00001855011 16018706 16018926 ENSE00001869938 16020052 16020193 ENSE00001858305 16027646 16027704 ENSE00001665626 15863673 15863885 ENSE00001700678 15864974 15865039 ENSE00003705410 15866520 15866669 ENSE00001708493 15966324 15966457 ENSE00001755301 15970397 15970474 ENSE00001834814 15864978 15865039 ENSE00001810485 15970397 15970526 ENSE00001921850 15971548 15971701 ENSE00001942280 15980947 15981008 ENSE00001957709 15983513 15983586 ENSE00001593220 20835919 20835930 ENSE00001799029 20836103 20836201 ENSE00001736209 20837256 20837458 ENSE00001597754 20840328 20840395 ENSE00001645084 20840484 20840514 ENSE00001630093 20853209 20853313 ENSE00001777109 20855130 20855266 ENSE00001788874 20860049 20860220 ENSE00001795527 20872844 20872950 ENSE00001784531 20874704 20874802 ENSE00001748450 20876467 20876540 ENSE00001604424 20878129 20878264 ENSE00001711949 20879132 20879261 ENSE00001747846 20879796 20879907 ENSE00001683758 20881955 20882582 ENSE00001729014 20882957 20883068 ENSE00003703880 20893583 20893683 ENSE00003706916 20894741 20894877 ENSE00001642045 20898229 20898379 ENSE00001673682 20899569 20899635 ENSE00001602445 20899933 20899975 ENSE00001773752 20891768 20891909 ENSE00003709828 20894045 20894158 ENSE00003684405 20899941 20901083 ENSE00002305110 20893577 20893683 ENSE00003584068 20894741 20894877 ENSE00003459679 20899941 20901083 ENSE00001731860 24064067 24064189 ENSE00001635505 24062093 24062205 ENSE00001802644 24061513 24061616 ENSE00003593123 24056248 24056400 ENSE00003642844 24054123 24054237 ENSE00003666042 24053057 24053167 ENSE00003674429 24052505 24052615 ENSE00003502244 24051960 24052070 ENSE00003616658 24050928 24051038 ENSE00003603776 24050753 24050841 ENSE00003548786 24049765 24050341 ENSE00001683783 24064067 24064214 ENSE00001619375 24058316 24058493 ENSE00003468556 24056248 24056400 ENSE00003528506 24054123 24054237 ENSE00003480174 24053057 24053167 ENSE00003577506 24052505 24052615 ENSE00003482521 24051960 24052070 ENSE00003559850 24050928 24051038 ENSE00003547647 24050753 24050841 ENSE00003613569 24049765 24050341 ENSE00001794358 24064067 24064174 ENSE00003465760 24026223 24026799 ENSE00002228703 24064067 24064127 ENSE00002309932 24049997 24050341 ENSE00001643289 23671964 23672356 ENSE00001615364 23670909 23670974 ENSE00001713521 23670582 23670645 ENSE00001786811 23670350 23670495 ENSE00001765379 23670185 23670232 ENSE00001908333 26357107 26357382 ENSE00001666674 26329421 26329652 ENSE00001796018 26328965 26329169 ENSE00001784489 26325463 26325515 ENSE00001881074 23673224 23673371 ENSE00003564737 23675233 23675345 ENSE00003500350 23675820 23675923 ENSE00001799218 23678943 23679120 ENSE00003552000 23681036 23681188 ENSE00003596670 23683199 23683313 ENSE00003464309 23684269 23684379 ENSE00003633721 23684821 23684931 ENSE00003674912 23685366 23685476 ENSE00003567291 23686398 23686508 ENSE00003679647 23686596 23686684 ENSE00003617149 23687096 23687672 ENSE00001661847 23673249 23673371 ENSE00003675456 23681036 23681188 ENSE00003499970 23683199 23683313 ENSE00003586486 23684269 23684379 ENSE00003643888 23684821 23684931 ENSE00003501027 23685366 23685476 ENSE00003669209 23686398 23686508 ENSE00003536838 23686596 23686684 ENSE00003662366 23687096 23687672 ENSE00001659203 6175751 6175852 ENSE00001709097 6175939 6176078 ENSE00001731355 6177541 6177628 ENSE00001752741 24455006 24455117 ENSE00001595873 24457007 24457119 ENSE00002550304 24457542 24457645 ENSE00001190571 24460640 24462352 ENSE00001792479 24457011 24457119 ENSE00001683633 24460640 24460817 ENSE00001618747 24462742 24462894 ENSE00001598516 24464930 24465044 ENSE00001800192 24466510 24466611 ENSE00001753847 24466977 24467087 ENSE00001642884 24467168 24467256 ENSE00001598101 24467671 24467972 ENSE00001629733 9873804 9874161 ENSE00001690028 9875508 9875576 ENSE00001791094 9875672 9875817 ENSE00001700224 9875928 9875984 ENSE00001859492 14394177 14394465 ENSE00001686036 25163210 25163968 ENSE00002094213 26332656 26333378 ENSE00002123033 26329581 26329652 ENSE00001780671 7781463 7782131 ENSE00001751822 24040526 24040648 ENSE00001612685 24038552 24038664 ENSE00001763210 24037972 24038075 ENSE00003654373 24032707 24032859 ENSE00003581142 24030582 24030696 ENSE00003526911 24029516 24029626 ENSE00003486158 24028964 24029074 ENSE00003580424 24028419 24028529 ENSE00003605671 24027387 24027497 ENSE00003601536 24027211 24027299 ENSE00003624241 24026223 24026799 ENSE00001636167 24040526 24040673 ENSE00001665354 24034775 24034952 ENSE00003494048 24032707 24032859 ENSE00003647885 24030582 24030696 ENSE00003646572 24029516 24029626 ENSE00003489479 24028964 24029074 ENSE00003670003 24028419 24028529 ENSE00003588956 24027387 24027497 ENSE00003484557 24027211 24027299 ENSE00003612403 24026223 24026799 ENSE00001744906 24038552 24038660 ENSE00002215963 24040526 24040586 ENSE00002316782 24026455 24026799 ENSE00001592980 20290496 20290830 ENSE00001733820 20298015 20298506 ENSE00002317106 20297335 20298306 ENSE00002237968 20298308 20298913 ENSE00002019278 20952595 20952937 ENSE00002070232 26424828 26425034 ENSE00002079738 26429209 26429377 ENSE00002059695 26437416 26437493 ENSE00002051610 20941185 20941313 ENSE00002083133 20938702 20939447 ENSE00002028839 20938165 20938289 ENSE00002069932 20817932 20818076 ENSE00002063868 20817406 20817491 ENSE00002057796 20655961 20656181 ENSE00002048409 20655067 20655191 ENSE00002073771 20654896 20654988 ENSE00002045000 20652801 20652991 ENSE00002068415 20548860 20548916 ENSE00002086946 20549222 20549330 ENSE00002062200 20549411 20549520 ENSE00002049899 20550014 20551037 ENSE00002077940 6113013 6113324 ENSE00001694957 6111594 6111684 ENSE00003675853 6111336 6111481 ENSE00002079014 19888946 19889280 ENSE00002054858 19880996 19881760 ENSE00001426978 19881469 19882440 ENSE00001427537 19880862 19881467 ENSE00002086052 20702866 20702995 ENSE00002030784 20704732 20705478 ENSE00002046435 20705890 20706014 ENSE00002021560 6111568 6111670 ENSE00003683409 6111336 6111481 ENSE00002051027 6109809 6109902 ENSE00002079391 20653626 20653703 ENSE00002055245 20662506 20662937 ENSE00002063141 20691526 20691723 ENSE00002077751 20692374 20692482 ENSE00002066035 20708919 20709584 ENSE00002036613 24041541 24041925 ENSE00002083771 24042923 24043007 ENSE00002040343 24043252 24043330 ENSE00002082814 24043416 24043547 ENSE00002059714 24043665 24043706 ENSE00002088173 10037764 10037915 ENSE00002088234 9928019 9928137 ENSE00002088264 28393531 28393668 ENSE00002088309 2652790 2652894 ENSE00002088347 5742287 5742379 ENSE00002088385 26092765 26092918 ENSE00002088393 25569246 25569383 ENSE00002088421 20508009 20508124 ENSE00002088434 10033981 10034093 ENSE00002088438 20995615 20995776 ENSE00002088464 7209572 7209683 ENSE00002088480 19671654 19671769 ENSE00002088506 19734941 19735035 ENSE00002088527 5441969 5442060 ENSE00002088623 7246713 7246820 ENSE00002088634 20278734 20278893 ENSE00002088641 18360815 18360921 ENSE00002088677 20648397 20648558 ENSE00002088757 9930484 9930602 ENSE00002088783 19669744 19669856 ENSE00002088791 18448163 18448269 ENSE00002088894 27869489 27869642 ENSE00002088907 20444739 20444833 ENSE00002088936 4887117 4887307 ENSE00002088939 27606157 27606239 ENSE00002088940 7291095 7291199 ENSE00002088981 19900883 19901042 ENSE00002089054 14482123 14482230 ENSE00002089093 28075126 28075289 ENSE00002089101 7192338 7192636 ENSE00002089132 18174646 18174709 ENSE00002089135 20509921 20510033 ENSE00002089149 25887089 25887252 ENSE00002089157 18250128 18250259 ENSE00002089162 15779840 15779936 ENSE00002089234 21180869 21180973 ENSE00002089323 13340551 13340633 ENSE00002089368 4043026 4043131 ENSE00002089416 28507136 28507239 ENSE00002198122 23206485 23206610 ENSE00002174318 23204155 23204255 ENSE00002153935 23200175 23200930 ENSE00002532814 13462594 13463857 ENSE00002532407 13488005 13489271 ENSE00001685809 9304564 9305095 ENSE00001706012 9305703 9305780 ENSE00001701882 9305909 9306020 ENSE00003684179 9306122 9306267 ENSE00003459001 9306374 9306455 ENSE00003593931 9307148 9307357 ENSE00002289488 9236076 9236312 ENSE00002299255 9304829 9305095 ENSE00002495525 13477233 13478499 ENSE00002516975 13470597 13471863 ENSE00002541336 24476599 24477171 ENSE00002560807 24477716 24478647 ENSE00002607126 21853827 21856492 ENSE00002699100 13340359 13340440 ENSE00002716056 13947443 13947512 ENSE00002692672 18398127 18398238 ENSE00002709597 16364065 16364171 ENSE00002923801 21760074 21760643 ENSE00002984896 25847479 25847492 ENSE00003022139 25850384 25850398 ENSE00003135789 25850559 25850592 ENSE00003159256 21738045 21738068 ENSE00003053921 21737895 21737969 ENSE00003090195 15418467 15418484 ENSE00003068265 15418626 15418711 ENSE00003133967 15428905 15428910 ENSE00003158951 15429021 15429063 ENSE00003052018 15429068 15429181 ENSE00003105168 28114876 28114889 ENSE00002994181 28111970 28111984 ENSE00003035759 28111776 28111809 ENSE00003089533 5312577 5312605 ENSE00003100810 5306691 5306703 ENSE00001782073 9345205 9345423 ENSE00001705189 9345442 9345707 ENSE00001641329 9346315 9346392 ENSE00001803456 9346521 9346632 ENSE00001739988 9346734 9346879 ENSE00001717366 9346986 9347067 ENSE00001761223 9347762 9347784 ENSE00003671391 13551375 13551415 ENSE00003551235 13551547 13552752 ENSE00003639402 13491303 13491471 ENSE00003668884 13491863 13493369 ENSE00003649651 27809047 27809373 ENSE00003691087 13263395 13263563 ENSE00003621115 23793569 23793901 ENSE00003657297 13263065 13263272 ENSE00003625313 13262741 13262939 ENSE00003638565 13629856 13629913 ENSE00003555471 13629403 13629733 ENSE00003625865 19576759 19577094 ENSE00003697854 27605054 27605329 ensembldb/inst/chrY/ens_gene.txt0000644000175400017540000010531613175714743017763 0ustar00biocbuildbiocbuildgene_id gene_name entrezid gene_biotype gene_seq_start gene_seq_end seq_name seq_strand seq_coord_system ENSG00000012817 KDM5D 8284 protein_coding 21865751 21906825 Y -1 chromosome ENSG00000067048 DDX3Y 8653 protein_coding 15016019 15032390 Y 1 chromosome ENSG00000067646 ZFY 7544 protein_coding 2803112 2850547 Y 1 chromosome ENSG00000092377 TBL1Y 90665 protein_coding 6778727 6959724 Y 1 chromosome ENSG00000099715 PCDH11Y 83259;27328 protein_coding 4868267 5610265 Y 1 chromosome ENSG00000099721 AMELY 266 protein_coding 6733959 6742068 Y -1 chromosome ENSG00000099725 PRKY 5616 pseudogene 7142013 7249589 Y 1 chromosome ENSG00000114374 USP9Y 8287 protein_coding 14813160 14972764 Y 1 chromosome ENSG00000129816 TTTY1B 50858;100101116 lincRNA 6258472 6279605 Y 1 chromosome ENSG00000129824 RPS4Y1 6192 protein_coding 2709527 2800041 Y 1 chromosome ENSG00000129845 TTTY1 50858;100101116 lincRNA 9590765 9611898 Y -1 chromosome ENSG00000129862 VCY1B 9084;353513 protein_coding 16168097 16168838 Y 1 chromosome ENSG00000129864 VCY 9084;353513 protein_coding 16097652 16098393 Y -1 chromosome ENSG00000129873 CDY2B 9426;203611 protein_coding 19989290 19992100 Y -1 chromosome ENSG00000131002 TXLNG2P 246126 pseudogene 21729199 21768160 Y 1 chromosome ENSG00000131007 TTTY9B 83864;425057 antisense 20743092 20752407 Y -1 chromosome ENSG00000131538 TTTY6 84672;441543 lincRNA 24585740 24587605 Y -1 chromosome ENSG00000131548 TTTY6B 84672;441543 antisense 24291113 24292978 Y 1 chromosome ENSG00000147753 TTTY7 246122 lincRNA 6317509 6325947 Y 1 chromosome ENSG00000147761 TTTY7B 100101120 lincRNA 9544433 9552871 Y -1 chromosome ENSG00000154620 TMSB4Y 9087 protein_coding 15815447 15817904 Y 1 chromosome ENSG00000157828 RPS4Y2 140032 protein_coding 22918050 22942918 Y 1 chromosome ENSG00000165246 NLGN4Y 22829 protein_coding 16634518 16957530 Y 1 chromosome ENSG00000168757 TSPY2 64591 protein_coding 6114264 6117060 Y 1 chromosome ENSG00000169763 PRYP3 pseudogene 25827587 25840726 Y -1 chromosome ENSG00000169789 PRY 442862;100509646;9081 protein_coding 24636544 24660784 Y 1 chromosome ENSG00000169800 RBMY1F 159163;378951 protein_coding 24314689 24329129 Y -1 chromosome ENSG00000169807 PRY2 442862;100509646;9081 protein_coding 24217903 24242154 Y -1 chromosome ENSG00000169811 RBMY1HP pseudogene 23655405 23663854 Y 1 chromosome ENSG00000169849 TSPY14P pseudogene 23630044 23632569 Y 1 chromosome ENSG00000169953 HSFY2 159119;86614 protein_coding 20893326 20990548 Y -1 chromosome ENSG00000172283 PRYP4 pseudogene 28121660 28134216 Y 1 chromosome ENSG00000172288 CDY1 9085;253175 protein_coding 27768264 27771049 Y 1 chromosome ENSG00000172294 CSPG4P4Y 114758 pseudogene 27624416 27632852 Y 1 chromosome ENSG00000172297 GOLGA2P3Y 401634;84559 pseudogene 27600708 27606719 Y 1 chromosome ENSG00000172332 AC012005.2 401634;84559 pseudogene 26355714 26361728 Y -1 chromosome ENSG00000172342 CSPG4P3Y pseudogene 26332656 26338017 Y -1 chromosome ENSG00000172352 CDY1B 9085;253175 protein_coding 26191376 26194166 Y -1 chromosome ENSG00000172468 HSFY1 159119;86614 protein_coding 20708557 20750849 Y 1 chromosome ENSG00000173357 AC007967.3 pseudogene 8774265 8784114 Y 1 chromosome ENSG00000176679 TGIF2LY 90655 protein_coding 3447082 3448082 Y 1 chromosome ENSG00000176728 TTTY14 55410;83869 lincRNA 21034387 21239302 Y -1 chromosome ENSG00000180910 TTTY11 83866 lincRNA 8651351 8685423 Y -1 chromosome ENSG00000182415 CDY2A 9085;9426;203611;253175 protein_coding 20137667 20140477 Y 1 chromosome ENSG00000183146 CYorf17 100533178 protein_coding 23544840 23548246 Y -1 chromosome ENSG00000183385 TTTY8 84673;100101118 lincRNA 9528709 9531566 Y 1 chromosome ENSG00000183704 SLC9B1P1 protein_coding 13496241 13524717 Y -1 chromosome ENSG00000183753 BPY2 442867;9083;442868 protein_coding 25119966 25151612 Y 1 chromosome ENSG00000183795 BPY2B 442867;9083;442868 protein_coding 26753707 26785354 Y 1 chromosome ENSG00000183878 UTY 7404 protein_coding 15360259 15592553 Y -1 chromosome ENSG00000184895 SRY 6736 protein_coding 2654896 2655740 Y -1 chromosome ENSG00000184991 TTTY13 83868 lincRNA 23745486 23756552 Y -1 chromosome ENSG00000185275 CD24P4 pseudogene 21154353 21154595 Y -1 chromosome ENSG00000185700 TTTY8B 84673;100101118 lincRNA 6338814 6341671 Y -1 chromosome ENSG00000185894 BPY2C 442867;9083;442868 protein_coding 27177048 27208695 Y -1 chromosome ENSG00000187191 DAZ3 57054;57055 protein_coding 26909216 26959626 Y -1 chromosome ENSG00000187657 TSPY13P pseudogene 9743204 9745748 Y -1 chromosome ENSG00000188120 DAZ1 57135;1617 protein_coding 25275502 25345241 Y -1 chromosome ENSG00000188399 ANKRD36P1 pseudogene 28555962 28566682 Y 1 chromosome ENSG00000188656 TSPY7P pseudogene 9215731 9218480 Y 1 chromosome ENSG00000197038 RBMY1A3P 286557 pseudogene 9148739 9160483 Y -1 chromosome ENSG00000197092 GOLGA6L16P pseudogene 27641798 27648105 Y -1 chromosome ENSG00000198692 EIF1AY 9086;101060318 protein_coding 22737611 22755040 Y 1 chromosome ENSG00000205916 DAZ4 57055;57135;1617 protein_coding 26980008 27053183 Y 1 chromosome ENSG00000205936 PPP1R12BP2 pseudogene 25525631 25538844 Y 1 chromosome ENSG00000205944 DAZ2 57055;57135;1617 protein_coding 25365594 25437503 Y 1 chromosome ENSG00000206159 GYG2P1 352887 pseudogene 14475147 14532255 Y -1 chromosome ENSG00000212855 TTTY2 lincRNA 9578193 9596085 Y 1 chromosome ENSG00000212856 TTTY2B lincRNA 6274285 6292186 Y -1 chromosome ENSG00000214207 KRT18P10 pseudogene 5441186 5442472 Y 1 chromosome ENSG00000215414 PSMA6P1 5687 pseudogene 15398518 15399258 Y 1 chromosome ENSG00000215506 TPTE2P4 pseudogene 28654360 28725837 Y 1 chromosome ENSG00000215507 RBMY2DP pseudogene 28269821 28279455 Y 1 chromosome ENSG00000215537 ZNF736P11Y pseudogene 25012691 25013903 Y -1 chromosome ENSG00000215540 AC009947.3 pseudogene 25683455 25693089 Y -1 chromosome ENSG00000215560 TTTY5 83863 lincRNA 24442945 24445023 Y -1 chromosome ENSG00000215580 BCORP1 286554 pseudogene 21617317 21665039 Y -1 chromosome ENSG00000215583 ASS1P6 pseudogene 14043242 14044475 Y -1 chromosome ENSG00000215601 TSPY24P pseudogene 8148239 8150250 Y 1 chromosome ENSG00000215603 ZNF92P1Y pseudogene 7721727 7722917 Y -1 chromosome ENSG00000216777 PRRC2CP1 pseudogene 3417693 3417851 Y -1 chromosome ENSG00000216824 ZNF736P10Y pseudogene 8286832 8287941 Y -1 chromosome ENSG00000216844 AC009494.3 pseudogene 23005142 23005596 Y -1 chromosome ENSG00000217179 MTCYBP2 pseudogene 21033988 21034158 Y 1 chromosome ENSG00000217896 ZNF839P1 pseudogene 21147061 21148284 Y 1 chromosome ENSG00000218410 AC012078.2 pseudogene 3719265 3720910 Y -1 chromosome ENSG00000223362 CDY15P pseudogene 26001669 26003238 Y -1 chromosome ENSG00000223406 XKRYP5 pseudogene 27898535 27899017 Y 1 chromosome ENSG00000223407 USP9YP18 pseudogene 25805613 25813969 Y -1 chromosome ENSG00000223422 AC007274.2 pseudogene 7546940 7549069 Y 1 chromosome ENSG00000223517 AC010723.1 lincRNA 16388092 16389369 Y -1 chromosome ENSG00000223555 USP9YP23 pseudogene 19894090 19896695 Y 1 chromosome ENSG00000223600 EEF1A1P41 pseudogene 2863108 2863314 Y -1 chromosome ENSG00000223636 UBE2Q2P5Y pseudogene 27577303 27583462 Y 1 chromosome ENSG00000223637 RBMY2EP 159125 pseudogene 23556877 23563471 Y -1 chromosome ENSG00000223641 TTTY17C 474152;474151;252949 lincRNA 27329790 27330920 Y -1 chromosome ENSG00000223655 RAB9AP3 pseudogene 28064470 28065042 Y -1 chromosome ENSG00000223698 GOLGA6L11P pseudogene 26314334 26320641 Y 1 chromosome ENSG00000223744 RBMY2GP pseudogene 6196093 6211364 Y 1 chromosome ENSG00000223856 RAB9AP2 pseudogene 27856055 27859704 Y -1 chromosome ENSG00000223915 DPPA2P1 pseudogene 15342765 15343320 Y 1 chromosome ENSG00000223955 MTND6P1 pseudogene 8231577 8232000 Y -1 chromosome ENSG00000223978 ZNF736P1Y pseudogene 27131348 27132623 Y -1 chromosome ENSG00000224033 CDY8P pseudogene 20134179 20135788 Y 1 chromosome ENSG00000224035 SFPQP1 pseudogene 15195704 15207719 Y 1 chromosome ENSG00000224060 ARSEP1 pseudogene 14460540 14468226 Y 1 chromosome ENSG00000224075 TTTY22 252954 lincRNA 9638762 9650854 Y 1 chromosome ENSG00000224151 USP9YP28 pseudogene 20994888 21001199 Y -1 chromosome ENSG00000224166 PRYP1 pseudogene 19841408 19856476 Y -1 chromosome ENSG00000224169 HSFY6P pseudogene 25803986 25805205 Y -1 chromosome ENSG00000224210 TRIM60P5Y pseudogene 26640856 26641730 Y -1 chromosome ENSG00000224240 CYCSP49 pseudogene 28695572 28695890 Y 1 chromosome ENSG00000224336 FAM197Y1 protein_coding 9374241 9384693 Y -1 chromosome ENSG00000224408 USP9YP22 pseudogene 9021303 9023412 Y 1 chromosome ENSG00000224482 HSFY4P pseudogene 22970662 22973695 Y -1 chromosome ENSG00000224485 USP9YP7 pseudogene 20020635 20022686 Y 1 chromosome ENSG00000224518 AC006989.2 pseudogene 17053626 17054595 Y 1 chromosome ENSG00000224571 USP9YP13 pseudogene 26066052 26067657 Y 1 chromosome ENSG00000224634 ZNF736P6Y pseudogene 8218972 8220184 Y 1 chromosome ENSG00000224657 RBMY2BP pseudogene 24795392 24805025 Y 1 chromosome ENSG00000224827 LINC00265-2P pseudogene 26422392 26423173 Y 1 chromosome ENSG00000224866 USP9YP25 pseudogene 25880340 25882396 Y 1 chromosome ENSG00000224873 CDY13P pseudogene 24666828 24667842 Y -1 chromosome ENSG00000224917 AC016694.2 pseudogene 24816763 24819006 Y -1 chromosome ENSG00000224953 SRIP3 pseudogene 6587003 6587221 Y -1 chromosome ENSG00000224964 TRAPPC2P3 pseudogene 19909863 19912576 Y -1 chromosome ENSG00000224989 FAM41AY1 340618;100302526 lincRNA 19612838 19626898 Y 1 chromosome ENSG00000225117 ARSDP1 pseudogene 14474827 14499123 Y 1 chromosome ENSG00000225189 REREP1Y pseudogene 25608612 25618427 Y 1 chromosome ENSG00000225256 TRAPPC2P5 pseudogene 27845598 27848709 Y 1 chromosome ENSG00000225287 OFD1P13Y pseudogene 27821207 27843493 Y -1 chromosome ENSG00000225326 USP9YP19 pseudogene 27894743 27896353 Y -1 chromosome ENSG00000225466 OFD1P10Y pseudogene 25727742 25760787 Y 1 chromosome ENSG00000225491 UBE2Q2P4Y pseudogene 26378973 26385131 Y -1 chromosome ENSG00000225516 AC006156.1 protein_coding 9293012 9344176 Y -1 chromosome ENSG00000225520 TTTY16 252948 lincRNA 7567398 7569288 Y -1 chromosome ENSG00000225560 FAM197Y8 252946;100287826;100289150 antisense 9185120 9193010 Y -1 chromosome ENSG00000225609 CDY20P pseudogene 27764791 27766400 Y 1 chromosome ENSG00000225615 RBMY2UP pseudogene 24344576 24349859 Y 1 chromosome ENSG00000225624 TBL1YP1 pseudogene 22889140 22904786 Y 1 chromosome ENSG00000225653 RNF19BPY pseudogene 3646038 3647587 Y -1 chromosome ENSG00000225685 TSPY5P pseudogene 9904163 9906760 Y -1 chromosome ENSG00000225716 TCEB1P13 pseudogene 20602683 20603011 Y 1 chromosome ENSG00000225740 TCEB1P6 pseudogene 19949081 19949408 Y -1 chromosome ENSG00000225809 RBMY2KP pseudogene 8132490 8145229 Y -1 chromosome ENSG00000225840 AC010970.2 pseudogene 10036113 10036711 Y -1 chromosome ENSG00000225876 AC024067.1 pseudogene 28390498 28390720 Y -1 chromosome ENSG00000225878 SERBP1P2 pseudogene 4669726 4670889 Y -1 chromosome ENSG00000225895 TRAPPC2P8 pseudogene 20267200 20269988 Y 1 chromosome ENSG00000225896 AC007742.3 pseudogene 19838632 19838960 Y 1 chromosome ENSG00000226011 OFD1P1Y pseudogene 19921687 19937209 Y 1 chromosome ENSG00000226042 CDY10P pseudogene 23799361 23800927 Y -1 chromosome ENSG00000226061 PCMTD1P1 pseudogene 10011462 10011816 Y 1 chromosome ENSG00000226092 RBMY2AP pseudogene 24073668 24083297 Y -1 chromosome ENSG00000226116 USP9YP6 pseudogene 20024579 20033510 Y -1 chromosome ENSG00000226223 TSPY16P pseudogene 9477858 9478325 Y -1 chromosome ENSG00000226270 ZNF736P2Y pseudogene 26829804 26831082 Y 1 chromosome ENSG00000226353 TAF9P1 pseudogene 19740393 19741282 Y 1 chromosome ENSG00000226362 FAM41AY2 340618;100302526 lincRNA 20552880 20566932 Y -1 chromosome ENSG00000226369 USP9YP11 pseudogene 26081100 26086248 Y 1 chromosome ENSG00000226449 CDY5P pseudogene 19833478 19835057 Y 1 chromosome ENSG00000226504 TMEM167AP1 pseudogene 23069230 23069448 Y -1 chromosome ENSG00000226529 MTND1P1 pseudogene 8239704 8240071 Y 1 chromosome ENSG00000226555 AGKP1 pseudogene 16750976 16752238 Y 1 chromosome ENSG00000226611 OFD1P2Y pseudogene 20242567 20258088 Y -1 chromosome ENSG00000226863 SHROOM2P1 pseudogene 14649708 14656818 Y 1 chromosome ENSG00000226873 CDY14P pseudogene 25820526 25821539 Y 1 chromosome ENSG00000226906 TTTY4 474149;474150;114761 lincRNA 25082602 25119431 Y 1 chromosome ENSG00000226918 AC010086.1 pseudogene 23473154 23480781 Y 1 chromosome ENSG00000226941 RBMY1J 378949;5940;378950;159163;378948;378951 protein_coding 24454970 24564028 Y 1 chromosome ENSG00000226975 AC006987.6 pseudogene 10007397 10007923 Y -1 chromosome ENSG00000227166 STSP1 pseudogene 17659096 17705211 Y 1 chromosome ENSG00000227204 RBMY2JP pseudogene 7995171 8012244 Y 1 chromosome ENSG00000227251 TRIM60P9Y pseudogene 25204177 25205333 Y 1 chromosome ENSG00000227289 HSFY3P pseudogene 2749724 2751693 Y -1 chromosome ENSG00000227439 TTTY17B 474152;474151;252949 lincRNA 26631479 26632610 Y 1 chromosome ENSG00000227444 AC007322.5 pseudogene 24065082 24067253 Y 1 chromosome ENSG00000227447 XGPY pseudogene 14551845 14619171 Y -1 chromosome ENSG00000227494 USP9YP14 pseudogene 20642973 20649286 Y 1 chromosome ENSG00000227629 SLC25A15P1 pseudogene 28732789 28737748 Y -1 chromosome ENSG00000227633 RBMY2YP pseudogene 27412731 27419678 Y 1 chromosome ENSG00000227635 USP9YP21 pseudogene 28079980 28082028 Y -1 chromosome ENSG00000227830 TRIM60P3Y pseudogene 8281078 8282095 Y -1 chromosome ENSG00000227837 TRIM60P11Y pseudogene 26837938 26839079 Y 1 chromosome ENSG00000227867 TCEB1P11 pseudogene 28137388 28137719 Y -1 chromosome ENSG00000227871 USP9YP12 pseudogene 26092074 26098440 Y -1 chromosome ENSG00000227915 TCEB1P16 pseudogene 25824651 25824982 Y 1 chromosome ENSG00000227949 CYCSP46 pseudogene 17053427 17053630 Y -1 chromosome ENSG00000227989 AC010141.8 pseudogene 23717738 23719956 Y -1 chromosome ENSG00000228193 TCEB1P14 pseudogene 20949636 20949966 Y 1 chromosome ENSG00000228207 AC007967.2 pseudogene 8769244 8771317 Y -1 chromosome ENSG00000228240 TTTY17A 474152;474151;252949 lincRNA 24997731 24998862 Y 1 chromosome ENSG00000228257 AC010141.6 pseudogene 23693725 23695897 Y -1 chromosome ENSG00000228296 TTTY4C 474149;474150;114761 lincRNA 27209230 27246039 Y -1 chromosome ENSG00000228379 AC010891.2 lincRNA 9650924 9655122 Y 1 chromosome ENSG00000228383 FAM197Y7 252946;100287826;100289150 antisense 9205412 9235047 Y -1 chromosome ENSG00000228411 CDY4P pseudogene 14913906 14915763 Y -1 chromosome ENSG00000228465 TRAPPC2P10 pseudogene 26113711 26116841 Y -1 chromosome ENSG00000228518 SURF6P1 pseudogene 19304706 19305532 Y 1 chromosome ENSG00000228571 HSFY7P pseudogene 24683194 24683996 Y 1 chromosome ENSG00000228578 TUBB1P2 pseudogene 19628716 19630918 Y -1 chromosome ENSG00000228764 ZNF885P pseudogene 22551937 22558682 Y 1 chromosome ENSG00000228786 LINC00266-4P lincRNA 27524447 27540866 Y -1 chromosome ENSG00000228787 NLGN4Y-AS1 100874056 antisense 16905522 16915913 Y -1 chromosome ENSG00000228850 CDY12P pseudogene 24210845 24211859 Y 1 chromosome ENSG00000228890 TTTY21 252953;100101115 lincRNA 9555262 9558905 Y -1 chromosome ENSG00000228927 TSPY3 728137;100289087;7258 protein_coding 9236030 9307357 Y 1 chromosome ENSG00000228945 CLUHP2 pseudogene 20442064 20446647 Y 1 chromosome ENSG00000229129 ACTG1P2 pseudogene 19868881 19870005 Y -1 chromosome ENSG00000229138 CDY6P pseudogene 19993979 19995588 Y -1 chromosome ENSG00000229159 TSPY23P pseudogene 24329997 24332168 Y 1 chromosome ENSG00000229163 NAP1L1P2 pseudogene 2797042 2799161 Y -1 chromosome ENSG00000229208 RBMY2NP pseudogene 9669027 9684305 Y -1 chromosome ENSG00000229234 RBMY1KP pseudogene 24355478 24362727 Y 1 chromosome ENSG00000229236 TTTY10 246119 lincRNA 22627554 22681114 Y -1 chromosome ENSG00000229238 PPP1R12BP1 pseudogene 28424070 28500565 Y -1 chromosome ENSG00000229250 USP9YP31 pseudogene 26227851 26236493 Y -1 chromosome ENSG00000229302 TAF9P2 pseudogene 20438493 20439381 Y -1 chromosome ENSG00000229308 AC010084.1 lincRNA 3904538 3968361 Y 1 chromosome ENSG00000229343 CDY22P pseudogene 27959160 27960713 Y 1 chromosome ENSG00000229406 OFD1P4Y pseudogene 20615036 20634023 Y -1 chromosome ENSG00000229416 USP9YP8 pseudogene 23839132 23843004 Y -1 chromosome ENSG00000229465 ACTG1P11 pseudogene 20309770 20310894 Y 1 chromosome ENSG00000229518 UBE2V1P3 pseudogene 3734347 3734763 Y -1 chromosome ENSG00000229549 TSPY8 728403 protein_coding 9195406 9218479 Y 1 chromosome ENSG00000229551 GAPDHP17 pseudogene 23023223 23024223 Y 1 chromosome ENSG00000229553 USP9YP17 pseudogene 24195902 24204260 Y -1 chromosome ENSG00000229643 LINC00280 lincRNA 6225260 6229454 Y -1 chromosome ENSG00000229709 USP9YP36 pseudogene 27725937 27734591 Y 1 chromosome ENSG00000229725 AC007322.1 pseudogene 24017478 24019697 Y 1 chromosome ENSG00000229745 BPY2DP pseudogene 7801038 7805681 Y -1 chromosome ENSG00000229940 TSPY22P pseudogene 24452072 24454098 Y -1 chromosome ENSG00000230025 AC007967.4 pseudogene 8839792 8842136 Y -1 chromosome ENSG00000230029 CDY11P pseudogene 23858456 23860106 Y 1 chromosome ENSG00000230066 FAM197Y3 antisense 9334896 9342768 Y -1 chromosome ENSG00000230073 AC009947.2 pseudogene 25669468 25671516 Y 1 chromosome ENSG00000230377 TCEB1P7 pseudogene 20694212 20694542 Y -1 chromosome ENSG00000230412 TCEB1P12 pseudogene 20230369 20230696 Y 1 chromosome ENSG00000230458 GPM6BP1 pseudogene 20740303 20740446 Y 1 chromosome ENSG00000230476 OFD1P9Y pseudogene 24727136 24760228 Y -1 chromosome ENSG00000230663 FAM224B lincRNA 19664680 19691634 Y -1 chromosome ENSG00000230727 RBMY2WP pseudogene 24908998 24915934 Y -1 chromosome ENSG00000230814 USP9YP24 pseudogene 24674428 24682786 Y 1 chromosome ENSG00000230819 ZNF736P5Y pseudogene 27164646 27165450 Y -1 chromosome ENSG00000230854 USP9YP20 pseudogene 28069535 28075973 Y 1 chromosome ENSG00000230904 XKRYP2 pseudogene 20973224 20973715 Y -1 chromosome ENSG00000230977 AC023274.6 pseudogene 26328624 26329218 Y 1 chromosome ENSG00000231026 XKRYP4 pseudogene 26063388 26063870 Y -1 chromosome ENSG00000231141 TTTY3 114760;474148 lincRNA 27874637 27879535 Y 1 chromosome ENSG00000231159 OFD1P8Y pseudogene 24118460 24151496 Y 1 chromosome ENSG00000231311 PRYP2 pseudogene 20323252 20338370 Y 1 chromosome ENSG00000231341 VDAC1P6 pseudogene 5075256 5076110 Y -1 chromosome ENSG00000231375 CDY17P pseudogene 26196025 26197634 Y -1 chromosome ENSG00000231411 AC006987.7 pseudogene 10009199 10010334 Y -1 chromosome ENSG00000231423 RAB9AP5 pseudogene 26102716 26106365 Y 1 chromosome ENSG00000231436 RBMY3AP pseudogene 9448180 9458885 Y -1 chromosome ENSG00000231514 FAM58CP pseudogene 28772667 28773306 Y -1 chromosome ENSG00000231535 LINC00278 100873962 lincRNA 2870953 2970313 Y 1 chromosome ENSG00000231540 TCEB1P9 pseudogene 25954968 25955206 Y -1 chromosome ENSG00000231716 CDY23P pseudogene 28140831 28141844 Y -1 chromosome ENSG00000231874 TSPY18P pseudogene 9707273 9708390 Y 1 chromosome ENSG00000231988 OFD1P3Y pseudogene 8898635 8908029 Y 1 chromosome ENSG00000232003 ZNF736P12Y pseudogene 26646410 26647652 Y -1 chromosome ENSG00000232029 TCEB1P15 pseudogene 24214967 24215298 Y 1 chromosome ENSG00000232064 USP9YP33 pseudogene 27736470 27738492 Y -1 chromosome ENSG00000232195 TOMM22P2 pseudogene 2696023 2696259 Y 1 chromosome ENSG00000232205 CDY18P pseudogene 26250254 26252165 Y 1 chromosome ENSG00000232226 ARSFP1 pseudogene 14373025 14378737 Y -1 chromosome ENSG00000232235 CDY3P pseudogene 9003694 9005311 Y -1 chromosome ENSG00000232348 LINC00279 lincRNA 8506335 8512883 Y 1 chromosome ENSG00000232419 TTTY19 252952 lincRNA 8572513 8573324 Y 1 chromosome ENSG00000232424 USP9YP29 pseudogene 25886405 25892840 Y -1 chromosome ENSG00000232475 HSFY5P pseudogene 24194701 24195494 Y -1 chromosome ENSG00000232522 ZNF886P pseudogene 22163071 22174090 Y -1 chromosome ENSG00000232583 GPR143P pseudogene 6968774 6974543 Y -1 chromosome ENSG00000232585 OFD1P12Y pseudogene 26118927 26141228 Y 1 chromosome ENSG00000232614 USP9YP9 pseudogene 27876158 27881307 Y -1 chromosome ENSG00000232617 AC017019.1 pseudogene 9502838 9506619 Y 1 chromosome ENSG00000232620 TSPY17P pseudogene 6388504 6388970 Y 1 chromosome ENSG00000232634 NEFLP1 pseudogene 23382992 23383975 Y -1 chromosome ENSG00000232695 TCEB1P17 pseudogene 28007090 28007415 Y 1 chromosome ENSG00000232730 FAM8A4P pseudogene 14442350 14443562 Y 1 chromosome ENSG00000232744 USP9YP16 pseudogene 20283081 20285685 Y -1 chromosome ENSG00000232764 TRIM60P8Y pseudogene 25171741 25172810 Y 1 chromosome ENSG00000232808 TTTY20 252951 antisense 9167489 9172441 Y -1 chromosome ENSG00000232845 TRAPPC2P9 pseudogene 25908985 25911730 Y -1 chromosome ENSG00000232899 CDY9P pseudogene 20344721 20346300 Y -1 chromosome ENSG00000232910 RAB9AP1 pseudogene 25897335 25897907 Y 1 chromosome ENSG00000232914 TRAPPC2P4 pseudogene 28050665 28053397 Y 1 chromosome ENSG00000232924 TCEB1P4 pseudogene 9068524 9068856 Y 1 chromosome ENSG00000232927 USP12PY pseudogene 3550846 3551909 Y 1 chromosome ENSG00000232976 TRIM60P10Y pseudogene 26805484 26806553 Y 1 chromosome ENSG00000233070 ZFY-AS1 antisense 2834885 2870667 Y -1 chromosome ENSG00000233120 USP9YP15 pseudogene 20278413 20279581 Y 1 chromosome ENSG00000233126 ZNF736P3Y pseudogene 25195394 25197342 Y 1 chromosome ENSG00000233156 HSFY8P pseudogene 28157582 28158384 Y 1 chromosome ENSG00000233378 USP9YP34 pseudogene 20096229 20105140 Y 1 chromosome ENSG00000233522 FAM224A lincRNA 20488139 20515096 Y 1 chromosome ENSG00000233546 PRYP5 pseudogene 20691244 20691509 Y 1 chromosome ENSG00000233619 AC006328.9 pseudogene 27633431 27633809 Y -1 chromosome ENSG00000233634 GOT2P5 pseudogene 6705748 6706293 Y 1 chromosome ENSG00000233652 CICP1 pseudogene 27535139 27537958 Y 1 chromosome ENSG00000233699 TTTY18 252950 lincRNA 8551411 8551919 Y -1 chromosome ENSG00000233740 CICP2 pseudogene 26424484 26427287 Y -1 chromosome ENSG00000233774 MED14P1 pseudogene 14730915 14746333 Y -1 chromosome ENSG00000233803 TSPY4 728395 protein_coding 9175073 9177893 Y 1 chromosome ENSG00000233843 CYCSP48 pseudogene 28546758 28547377 Y 1 chromosome ENSG00000233864 TTTY15 64595 lincRNA 14774265 14804162 Y 1 chromosome ENSG00000233944 LINC00265-3P pseudogene 27539301 27540203 Y -1 chromosome ENSG00000234059 CASKP1 pseudogene 15042075 15060090 Y -1 chromosome ENSG00000234081 TCEB1P10 pseudogene 26153058 26153384 Y -1 chromosome ENSG00000234110 TSPY25P pseudogene 9461792 9463961 Y 1 chromosome ENSG00000234131 TCEB1P8 pseudogene 24663389 24663720 Y -1 chromosome ENSG00000234179 MTCYBP1 pseudogene 8232073 8233191 Y 1 chromosome ENSG00000234385 RCC2P1 pseudogene 13901758 13903233 Y -1 chromosome ENSG00000234399 RBMY2XP pseudogene 26542751 26549673 Y -1 chromosome ENSG00000234414 RBMY1A1 5940 protein_coding 23673258 23711212 Y 1 chromosome ENSG00000234529 GAPDHP19 pseudogene 21489455 21490459 Y 1 chromosome ENSG00000234583 TSPY19P pseudogene 6171998 6173115 Y -1 chromosome ENSG00000234620 HDHD1P1 pseudogene 17460542 17567954 Y -1 chromosome ENSG00000234652 AGPAT5P1 pseudogene 3161849 3162867 Y 1 chromosome ENSG00000234744 USP9YP26 pseudogene 28148401 28155003 Y 1 chromosome ENSG00000234795 RFTN1P1 pseudogene 7581026 7677302 Y -1 chromosome ENSG00000234803 FAM197Y2 252946;100287826;100289150 antisense 9355208 9364506 Y -1 chromosome ENSG00000234830 FAM197Y9 pseudogene 6124308 6131994 Y -1 chromosome ENSG00000234850 MTND2P3 pseudogene 8240282 8240751 Y 1 chromosome ENSG00000234888 OFD1P15Y pseudogene 28201926 28234640 Y -1 chromosome ENSG00000234950 RBMY2OP pseudogene 9789162 9797032 Y 1 chromosome ENSG00000235001 EIF4A1P2 pseudogene 5205786 5207005 Y -1 chromosome ENSG00000235004 USP9YP30 pseudogene 27869163 27870333 Y 1 chromosome ENSG00000235014 REREP2Y pseudogene 28344478 28354295 Y -1 chromosome ENSG00000235059 AC008175.1 101929148 lincRNA 24585087 24631739 Y 1 chromosome ENSG00000235094 AC006335.10 pseudogene 6174083 6175961 Y 1 chromosome ENSG00000235175 RPL26P37 pseudogene 5661341 5661778 Y -1 chromosome ENSG00000235193 AC006987.4 pseudogene 9925635 9927195 Y 1 chromosome ENSG00000235412 TTTY4B 474149;474150;114761 lincRNA 26716349 26753172 Y 1 chromosome ENSG00000235451 PNPLA4P1 pseudogene 16192955 16198480 Y 1 chromosome ENSG00000235462 TAB3P1 pseudogene 15265842 15274125 Y -1 chromosome ENSG00000235479 RAB9AP4 pseudogene 20811557 20812165 Y 1 chromosome ENSG00000235511 OFD1P18Y pseudogene 28018078 28044800 Y -1 chromosome ENSG00000235521 USP9YP27 pseudogene 19900195 19901364 Y -1 chromosome ENSG00000235583 AC007562.1 pseudogene 27658448 27673933 Y -1 chromosome ENSG00000235649 MXRA5P1 pseudogene 14077914 14108092 Y 1 chromosome ENSG00000235691 AC006987.5 pseudogene 9928411 9928816 Y 1 chromosome ENSG00000235719 AC010141.1 pseudogene 23627270 23629049 Y -1 chromosome ENSG00000235857 CTBP2P1 pseudogene 59001391 59001635 Y 1 chromosome ENSG00000235895 AC010154.2 pseudogene 6361017 6364798 Y -1 chromosome ENSG00000235981 AC023274.4 pseudogene 26288505 26303990 Y 1 chromosome ENSG00000236131 MED13P1 pseudogene 17019778 17019948 Y 1 chromosome ENSG00000236379 ZNF736P4Y pseudogene 27314746 27315988 Y 1 chromosome ENSG00000236424 TSPY10 728137;100289087;7258 protein_coding 9365489 9368291 Y 1 chromosome ENSG00000236429 GPM6BP2 pseudogene 20903729 20903872 Y -1 chromosome ENSG00000236435 TSPY12P pseudogene 7555780 7557589 Y -1 chromosome ENSG00000236477 RPS24P1 pseudogene 14365457 14366162 Y 1 chromosome ENSG00000236599 TCEB1P26 pseudogene 20340818 20341146 Y -1 chromosome ENSG00000236615 AC010086.5 pseudogene 23567656 23567881 Y 1 chromosome ENSG00000236620 XKRYP3 pseudogene 25862069 25872955 Y -1 chromosome ENSG00000236647 AC009947.5 pseudogene 25695956 25697532 Y 1 chromosome ENSG00000236690 AC007274.5 pseudogene 7558552 7560719 Y 1 chromosome ENSG00000236718 RBMY2QP pseudogene 9860098 9871796 Y -1 chromosome ENSG00000236786 TSPY15P pseudogene 9385717 9388290 Y 1 chromosome ENSG00000236951 AC007359.6 101929148 lincRNA 24246961 24293631 Y -1 chromosome ENSG00000237023 USP9YP3 pseudogene 23823812 23835894 Y 1 chromosome ENSG00000237048 TTTY12 83867 lincRNA 7672965 7678724 Y 1 chromosome ENSG00000237069 TTTY23B 252955;100101121 lincRNA 6110487 6111651 Y -1 chromosome ENSG00000237195 DLGAP5P1 pseudogene 6026843 6027306 Y 1 chromosome ENSG00000237269 RBMY2TP pseudogene 23592583 23599131 Y -1 chromosome ENSG00000237302 OFD1P11Y pseudogene 25917379 25944297 Y 1 chromosome ENSG00000237427 TOMM22P1 pseudogene 23292756 23293067 Y 1 chromosome ENSG00000237447 CDC27P2 pseudogene 10027986 10029907 Y -1 chromosome ENSG00000237467 USP9YP35 pseudogene 26223946 26225959 Y 1 chromosome ENSG00000237546 XKRYP6 pseudogene 28089415 28100299 Y 1 chromosome ENSG00000237558 CDY7P pseudogene 20063469 20065380 Y 1 chromosome ENSG00000237563 TTTY21B 252953;100101115 lincRNA 6311475 6315118 Y 1 chromosome ENSG00000237616 USP9YP32 pseudogene 20107081 20109132 Y -1 chromosome ENSG00000237659 RNASEH2CP1 pseudogene 2657868 2658369 Y 1 chromosome ENSG00000237701 ATP5JP1 pseudogene 6768794 6769413 Y 1 chromosome ENSG00000237802 FAM197Y6 100289188 antisense 9225731 9233636 Y -1 chromosome ENSG00000237823 CDY19P pseudogene 27710269 27712180 Y -1 chromosome ENSG00000237902 TSPY21P pseudogene 24546550 24548715 Y -1 chromosome ENSG00000237917 PARP4P1 pseudogene 28740998 28780799 Y -1 chromosome ENSG00000237968 AC007322.7 pseudogene 24086159 24087740 Y 1 chromosome ENSG00000237997 RCC2P2 pseudogene 22148461 22149738 Y -1 chromosome ENSG00000238067 XKRYP1 pseudogene 20670463 20670954 Y 1 chromosome ENSG00000238073 RBMY2HP pseudogene 7539784 7544065 Y -1 chromosome ENSG00000238074 TSPY6P 7258 protein_coding 9324922 9327689 Y 1 chromosome ENSG00000238088 OFD1P7Y pseudogene 21010150 21029166 Y 1 chromosome ENSG00000238135 USP9YP10 pseudogene 20987993 20991373 Y 1 chromosome ENSG00000238154 USP9YP4 pseudogene 9027238 9042220 Y -1 chromosome ENSG00000238191 CLUHP1 pseudogene 19733139 19737712 Y -1 chromosome ENSG00000238235 TSPY11P pseudogene 6134634 6137316 Y 1 chromosome ENSG00000239225 TTTY23 252955;100101121 lincRNA 9748407 9749571 Y 1 chromosome ENSG00000239304 DNM1P48 pseudogene 27632787 27633469 Y 1 chromosome ENSG00000239533 GOLGA2P2Y processed_transcript 26356114 26360978 Y -1 chromosome ENSG00000239893 ZNF736P9Y pseudogene 7936937 7938764 Y -1 chromosome ENSG00000240438 OFD1P5Y pseudogene 20743949 20790963 Y -1 chromosome ENSG00000240450 CSPG4P1Y 114758 lincRNA 27629055 27632852 Y 1 chromosome ENSG00000240566 AC010153.3 pseudogene 26796955 26797681 Y 1 chromosome ENSG00000241200 ZNF736P7Y pseudogene 7859028 7859847 Y -1 chromosome ENSG00000241859 KALP pseudogene 15863536 16027704 Y 1 chromosome ENSG00000242153 OFD1P6Y 83864;425057 pseudogene 20835919 20901083 Y 1 chromosome ENSG00000242389 RBMY1E 378949;378950 protein_coding 24026223 24064214 Y -1 chromosome ENSG00000242393 AC010141.4 pseudogene 23670185 23672356 Y -1 chromosome ENSG00000242425 RN7SL818P misc_RNA 26357107 26357382 Y -1 chromosome ENSG00000242854 DNM1P24 pseudogene 26325463 26329652 Y -1 chromosome ENSG00000242875 RBMY1B 378949;378948 protein_coding 23673224 23687672 Y 1 chromosome ENSG00000242879 AC006335.11 pseudogene 6175751 6177628 Y 1 chromosome ENSG00000243040 RBMY2FP 159162;100652931 pseudogene 24455006 24467972 Y 1 chromosome ENSG00000243643 TSPY20P pseudogene 9873804 9875984 Y 1 chromosome ENSG00000243980 RN7SL702P misc_RNA 14394177 14394465 Y 1 chromosome ENSG00000244000 AC006366.3 pseudogene 25163210 25163968 Y 1 chromosome ENSG00000244231 CSPG4P2Y 114758 processed_transcript 26329581 26333378 Y -1 chromosome ENSG00000244246 ZNF736P8Y pseudogene 7781463 7782131 Y -1 chromosome ENSG00000244395 RBMY1D 378949;5940;378948 protein_coding 24026223 24040673 Y -1 chromosome ENSG00000244646 AC024183.3 pseudogene 20290496 20298913 Y 1 chromosome ENSG00000248573 PRYP6 pseudogene 20952595 20952937 Y -1 chromosome ENSG00000248792 LINC00266-2P pseudogene 26424828 26437493 Y 1 chromosome ENSG00000249501 USP9YP2 pseudogene 20938165 20941313 Y -1 chromosome ENSG00000249606 TRAPPC2P7 pseudogene 20817406 20818076 Y -1 chromosome ENSG00000249634 USP9YP5 pseudogene 20652801 20656181 Y -1 chromosome ENSG00000249726 TUBB1P1 pseudogene 20548860 20551037 Y 1 chromosome ENSG00000250204 AC006335.6 pseudogene 6111336 6113324 Y -1 chromosome ENSG00000250868 AC007742.7 pseudogene 19880862 19889280 Y -1 chromosome ENSG00000250951 USP9YP1 pseudogene 20702866 20706014 Y 1 chromosome ENSG00000251275 AC006335.2 pseudogene 6109809 6111670 Y -1 chromosome ENSG00000251510 AC022486.1 lincRNA 20653626 20709584 Y 1 chromosome ENSG00000251618 AC007322.3 pseudogene 24041541 24043706 Y 1 chromosome ENSG00000251705 RNA5-8SP6 rRNA 10037764 10037915 Y 1 chromosome ENSG00000251766 RNA5SP518 rRNA 9928019 9928137 Y -1 chromosome ENSG00000251796 SNORA70 snoRNA 28393531 28393668 Y 1 chromosome ENSG00000251841 RNU6-1334P snRNA 2652790 2652894 Y 1 chromosome ENSG00000251879 AC010874.1 miRNA 5742287 5742379 Y 1 chromosome ENSG00000251917 RNU1-86P snRNA 26092765 26092918 Y -1 chromosome ENSG00000251925 SNORA70 snoRNA 25569246 25569383 Y -1 chromosome ENSG00000251953 RNA5SP522 rRNA 20508009 20508124 Y -1 chromosome ENSG00000251966 AC010970.1 miRNA 10033981 10034093 Y 1 chromosome ENSG00000251970 RNU1-41P snRNA 20995615 20995776 Y -1 chromosome ENSG00000251996 Y_RNA misc_RNA 7209572 7209683 Y 1 chromosome ENSG00000252012 RNA5SP521 rRNA 19671654 19671769 Y 1 chromosome ENSG00000252038 AC068704.1 miRNA 19734941 19735035 Y -1 chromosome ENSG00000252059 AC012667.1 miRNA 5441969 5442060 Y 1 chromosome ENSG00000252155 RNU6-941P snRNA 7246713 7246820 Y 1 chromosome ENSG00000252166 RNU1-95P snRNA 20278734 20278893 Y 1 chromosome ENSG00000252173 RNU6-109P snRNA 18360815 18360921 Y 1 chromosome ENSG00000252209 RNU1-48P snRNA 20648397 20648558 Y 1 chromosome ENSG00000252289 RNA5SP519 rRNA 9930484 9930602 Y -1 chromosome ENSG00000252315 RNA5SP520 rRNA 19669744 19669856 Y 1 chromosome ENSG00000252323 RNU6-184P snRNA 18448163 18448269 Y -1 chromosome ENSG00000252426 RNU1-107P snRNA 27869489 27869642 Y 1 chromosome ENSG00000252439 AC007241.1 miRNA 20444739 20444833 Y 1 chromosome ENSG00000252468 RNU2-57P snRNA 4887117 4887307 Y 1 chromosome ENSG00000252471 AC006328.1 miRNA 27606157 27606239 Y 1 chromosome ENSG00000252472 RNU6-521P snRNA 7291095 7291199 Y -1 chromosome ENSG00000252513 RNU1-128P snRNA 19900883 19901042 Y -1 chromosome ENSG00000252586 AC002992.1 miRNA 14482123 14482230 Y 1 chromosome ENSG00000252625 RNU1-40P snRNA 28075126 28075289 Y 1 chromosome ENSG00000252633 RN7SKP282 misc_RNA 7192338 7192636 Y -1 chromosome ENSG00000252664 AC017020.1 miRNA 18174646 18174709 Y 1 chromosome ENSG00000252667 RNA5SP523 rRNA 20509921 20510033 Y -1 chromosome ENSG00000252681 RNU1-97P snRNA 25887089 25887252 Y -1 chromosome ENSG00000252689 SNORA20 snoRNA 18250128 18250259 Y -1 chromosome ENSG00000252694 AC006371.1 miRNA 15779840 15779936 Y -1 chromosome ENSG00000252766 RNU6-255P snRNA 21180869 21180973 Y -1 chromosome ENSG00000252855 AC134878.1 miRNA 13340551 13340633 Y -1 chromosome ENSG00000252900 RNU6-303P snRNA 4043026 4043131 Y -1 chromosome ENSG00000252948 RNU6-1314P snRNA 28507136 28507239 Y 1 chromosome ENSG00000254488 RP11-65G9.1 lincRNA 23200175 23206610 Y -1 chromosome ENSG00000258567 DUX4L16 pseudogene 13462594 13463857 Y 1 chromosome ENSG00000258991 DUX4L19 pseudogene 13488005 13489271 Y 1 chromosome ENSG00000258992 TSPY1 7258 protein_coding 9236076 9307357 Y 1 chromosome ENSG00000259029 DUX4L18 pseudogene 13477233 13478499 Y 1 chromosome ENSG00000259154 DUX4L17 pseudogene 13470597 13471863 Y 1 chromosome ENSG00000259247 TTTY25P pseudogene 24476599 24478647 Y 1 chromosome ENSG00000260197 RP11-424G14.1 lincRNA 21853827 21856492 Y -1 chromosome ENSG00000263502 AC134878.2 miRNA 13340359 13340440 Y -1 chromosome ENSG00000265161 AC011293.1 miRNA 13947443 13947512 Y -1 chromosome ENSG00000265197 AC053516.1 miRNA 18398127 18398238 Y -1 chromosome ENSG00000266220 AC010723.2 miRNA 16364065 16364171 Y -1 chromosome ENSG00000267793 RP11-576C2.1 pseudogene 21760074 21760643 Y 1 chromosome ENSG00000267935 AC016752.1 protein_coding 25847479 25850592 Y 1 chromosome ENSG00000269084 AC009977.1 protein_coding 21737895 21738068 Y -1 chromosome ENSG00000269291 AC010877.1 protein_coding 15418467 15429181 Y 1 chromosome ENSG00000269393 AC007965.1 protein_coding 28111776 28114889 Y -1 chromosome ENSG00000269464 AC012067.1 protein_coding 5306691 5312605 Y -1 chromosome ENSG00000270073 AC006156.2 pseudogene 9345205 9347784 Y 1 chromosome ENSG00000270242 RP11-295P22.1 pseudogene 13551375 13552752 Y 1 chromosome ENSG00000270455 PABPC1P5 pseudogene 13491303 13493369 Y 1 chromosome ENSG00000270535 TCEB1P34 pseudogene 27809047 27809373 Y 1 chromosome ENSG00000270570 RP1-85D24.1 pseudogene 13263395 13263563 Y -1 chromosome ENSG00000271123 TCEB1P5 pseudogene 23793569 23793901 Y -1 chromosome ENSG00000271309 RP1-85D24.2 pseudogene 13263065 13263272 Y -1 chromosome ENSG00000271365 RP1-85D24.3 pseudogene 13262741 13262939 Y -1 chromosome ENSG00000271375 RP11-295P22.2 pseudogene 13629403 13629913 Y -1 chromosome ENSG00000271595 TCEB1P35 pseudogene 19576759 19577094 Y -1 chromosome ENSG00000272042 Metazoa_SRP misc_RNA 27605054 27605329 Y 1 chromosome ensembldb/inst/chrY/ens_metadata.txt0000644000175400017540000000046413175714743020623 0ustar00biocbuildbiocbuildname value Db type EnsDb Type of Gene ID Ensembl Gene ID Supporting package ensembldb Db created by ensembldb package from Bioconductor script_version 0.1.2 Creation time Wed Mar 18 09:30:54 2015 ensembl_version 75 ensembl_host manny.i-med.ac.at Organism homo_sapiens genome_build GRCh37 DBSCHEMAVERSION 1.0 ensembldb/inst/chrY/ens_tx.txt0000644000175400017540000016134513175714743017504 0ustar00biocbuildbiocbuildtx_id tx_biotype tx_seq_start tx_seq_end tx_cds_seq_start tx_cds_seq_end gene_id ENST00000469599 retained_intron 21865751 21878581 NULL NULL ENSG00000012817 ENST00000317961 protein_coding 21867301 21906809 21867881 21906420 ENSG00000012817 ENST00000382806 protein_coding 21867306 21906647 21867881 21906420 ENSG00000012817 ENST00000492117 retained_intron 21867311 21884353 NULL NULL ENSG00000012817 ENST00000440077 protein_coding 21867949 21906809 21867949 21906420 ENSG00000012817 ENST00000415360 protein_coding 21869068 21870835 21869068 21870835 ENSG00000012817 ENST00000485154 retained_intron 21871586 21872492 NULL NULL ENSG00000012817 ENST00000478891 retained_intron 21877022 21878234 NULL NULL ENSG00000012817 ENST00000447300 protein_coding 21883158 21906597 21883158 21906420 ENSG00000012817 ENST00000541639 protein_coding 21867303 21906825 21867881 21906420 ENSG00000012817 ENST00000360160 protein_coding 15016019 15030451 15016848 15030034 ENSG00000067048 ENST00000454054 protein_coding 15016029 15025765 15016848 15025765 ENSG00000067048 ENST00000336079 protein_coding 15016742 15032390 15016848 15030034 ENSG00000067048 ENST00000493363 processed_transcript 15016760 15021607 NULL NULL ENSG00000067048 ENST00000440554 protein_coding 15017649 15026561 15017691 15026561 ENSG00000067048 ENST00000469101 processed_transcript 15024552 15025713 NULL NULL ENSG00000067048 ENST00000472510 processed_transcript 15024875 15026811 NULL NULL ENSG00000067048 ENST00000463199 processed_transcript 15024920 15027139 NULL NULL ENSG00000067048 ENST00000495478 processed_transcript 15027408 15028265 NULL NULL ENSG00000067048 ENST00000383052 protein_coding 2803322 2850547 2821978 2848034 ENSG00000067646 ENST00000469869 processed_transcript 2803541 2846094 NULL NULL ENSG00000067646 ENST00000443793 protein_coding 2803546 2829327 2821978 2829327 ENSG00000067646 ENST00000478783 processed_transcript 2845860 2847391 NULL NULL ENSG00000067646 ENST00000431102 protein_coding 2803112 2850546 2821978 2848034 ENSG00000067646 ENST00000155093 protein_coding 2803518 2850546 2821978 2848034 ENSG00000067646 ENST00000449237 protein_coding 2803518 2850546 2829132 2848034 ENSG00000067646 ENST00000383032 protein_coding 6778727 6959724 6893126 6959533 ENSG00000092377 ENST00000355162 protein_coding 6778727 6959724 6893126 6959533 ENSG00000092377 ENST00000346432 protein_coding 6778727 6959724 6893126 6959533 ENSG00000092377 ENST00000333703 protein_coding 4868267 4973485 4900738 4972402 ENSG00000099715 ENST00000362095 protein_coding 4924131 4972741 4924865 4972402 ENSG00000099715 ENST00000400457 protein_coding 4924930 5610265 4924930 5605983 ENSG00000099715 ENST00000215473 protein_coding 4924865 5605983 4924865 5605983 ENSG00000099715 ENST00000215479 protein_coding 6733959 6742068 6734114 6740649 ENSG00000099721 ENST00000383036 protein_coding 6734114 6740649 6734114 6740649 ENSG00000099721 ENST00000383037 protein_coding 6736078 6740649 6736078 6740649 ENSG00000099721 ENST00000528056 processed_transcript 7142013 7249589 NULL NULL ENSG00000099725 ENST00000533551 transcribed_unprocessed_pseudogene 7142354 7239909 NULL NULL ENSG00000099725 ENST00000495163 processed_transcript 7194108 7196444 NULL NULL ENSG00000099725 ENST00000472666 processed_transcript 7201071 7224264 NULL NULL ENSG00000099725 ENST00000362758 transcribed_unprocessed_pseudogene 7142336 7235456 NULL NULL ENSG00000099725 ENST00000338981 protein_coding 14813160 14972764 14821381 14971341 ENSG00000114374 ENST00000493168 processed_transcript 14813969 14833136 NULL NULL ENSG00000114374 ENST00000426564 processed_transcript 14821369 14972764 NULL NULL ENSG00000114374 ENST00000453031 protein_coding 14958970 14971537 14958970 14971341 ENSG00000114374 ENST00000471409 processed_transcript 14968738 14972764 NULL NULL ENSG00000114374 ENST00000250776 lincRNA 6258472 6279605 NULL NULL ENSG00000129816 ENST00000250784 protein_coding 2709527 2735309 2709666 2734935 ENSG00000129824 ENST00000430575 protein_coding 2709961 2734903 2709985 2734903 ENSG00000129824 ENST00000477725 processed_transcript 2722137 2734997 NULL NULL ENSG00000129824 ENST00000515575 processed_transcript 2722771 2800041 NULL NULL ENSG00000129824 ENST00000250805 lincRNA 9590765 9611898 NULL NULL ENSG00000129845 ENST00000250823 protein_coding 16168097 16168838 16168170 16168739 ENSG00000129862 ENST00000250825 protein_coding 16097652 16098393 16097751 16098320 ENSG00000129864 ENST00000382867 protein_coding 19990147 19992100 19990147 19991772 ENSG00000129873 ENST00000544303 protein_coding 19989290 19992098 19989665 19991772 ENSG00000129873 ENST00000407724 processed_transcript 21729199 21752133 NULL NULL ENSG00000131002 ENST00000459719 retained_intron 21729236 21752304 NULL NULL ENSG00000131002 ENST00000447520 processed_transcript 21729268 21752309 NULL NULL ENSG00000131002 ENST00000445715 transcribed_unprocessed_pseudogene 21729268 21766006 NULL NULL ENSG00000131002 ENST00000538014 retained_intron 21729673 21751735 NULL NULL ENSG00000131002 ENST00000447202 retained_intron 21729715 21751733 NULL NULL ENSG00000131002 ENST00000588613 processed_transcript 21750429 21755603 NULL NULL ENSG00000131002 ENST00000589075 processed_transcript 21750456 21752305 NULL NULL ENSG00000131002 ENST00000585549 processed_transcript 21750495 21755488 NULL NULL ENSG00000131002 ENST00000587095 processed_transcript 21750497 21755488 NULL NULL ENSG00000131002 ENST00000488280 processed_transcript 21752639 21755537 NULL NULL ENSG00000131002 ENST00000253320 processed_transcript 21754336 21768160 NULL NULL ENSG00000131002 ENST00000593000 retained_intron 21754974 21756047 NULL NULL ENSG00000131002 ENST00000592697 processed_transcript 21759243 21765937 NULL NULL ENSG00000131002 ENST00000251749 transcribed_unprocessed_pseudogene 21729235 21752308 NULL NULL ENSG00000131002 ENST00000382832 transcribed_unprocessed_pseudogene 21758442 21767698 NULL NULL ENSG00000131002 ENST00000433794 antisense 20743092 20752407 NULL NULL ENSG00000131007 ENST00000545582 antisense 20743092 20750598 NULL NULL ENSG00000131007 ENST00000253838 lincRNA 24585740 24587605 NULL NULL ENSG00000131538 ENST00000538537 lincRNA 24585887 24587549 NULL NULL ENSG00000131538 ENST00000253848 antisense 24291113 24292978 NULL NULL ENSG00000131548 ENST00000545808 antisense 24291169 24292831 NULL NULL ENSG00000131548 ENST00000457100 lincRNA 6317509 6325947 NULL NULL ENSG00000147753 ENST00000276770 lincRNA 6317509 6325947 NULL NULL ENSG00000147753 ENST00000449828 lincRNA 6321946 6325947 NULL NULL ENSG00000147753 ENST00000447655 lincRNA 9544433 9548434 NULL NULL ENSG00000147761 ENST00000276779 lincRNA 9544433 9552871 NULL NULL ENSG00000147761 ENST00000415405 lincRNA 9544433 9552871 NULL NULL ENSG00000147761 ENST00000284856 protein_coding 15815447 15817904 15816216 15817139 ENSG00000154620 ENST00000288666 protein_coding 22918050 22942918 22918050 22942918 ENSG00000157828 ENST00000471252 processed_transcript 16634518 16734377 NULL NULL ENSG00000165246 ENST00000382872 protein_coding 16634632 16957530 16835029 16953142 ENSG00000165246 ENST00000355905 protein_coding 16635626 16955606 16734000 16953142 ENSG00000165246 ENST00000382868 protein_coding 16635626 16955606 16734000 16953142 ENSG00000165246 ENST00000476359 processed_transcript 16635626 16955606 NULL NULL ENSG00000165246 ENST00000481089 processed_transcript 16636409 16734248 NULL NULL ENSG00000165246 ENST00000339174 protein_coding 16636454 16955527 16734000 16953142 ENSG00000165246 ENST00000413217 protein_coding 16734061 16845429 16734061 16845417 ENSG00000165246 ENST00000297967 protein_coding 16733901 16845429 16734000 16845417 ENSG00000165246 ENST00000320701 protein_coding 6114264 6117054 6114310 6116866 ENSG00000168757 ENST00000383042 protein_coding 6114310 6117053 6114310 6116119 ENSG00000168757 ENST00000470569 retained_intron 6114310 6117060 NULL NULL ENSG00000168757 ENST00000464674 retained_intron 6115664 6117045 NULL NULL ENSG00000168757 ENST00000343584 processed_transcript 25827587 25840726 NULL NULL ENSG00000169763 ENST00000607210 transcribed_unprocessed_pseudogene 25828154 25840674 NULL NULL ENSG00000169763 ENST00000303593 transcribed_unprocessed_pseudogene 25829559 25840710 NULL NULL ENSG00000169763 ENST00000303728 protein_coding 24636544 24660784 24647712 24660217 ENSG00000169789 ENST00000477123 nonsense_mediated_decay 24636544 24660784 24647712 24658815 ENSG00000169789 ENST00000338793 protein_coding 24636544 24658815 24647712 24658815 ENSG00000169789 ENST00000303766 protein_coding 24314689 24329095 24314967 24327116 ENSG00000169800 ENST00000481858 processed_transcript 24314689 24329104 NULL NULL ENSG00000169800 ENST00000454978 protein_coding 24314689 24329129 24314967 24327116 ENSG00000169800 ENST00000303804 protein_coding 24217903 24242154 24218470 24230986 ENSG00000169807 ENST00000472391 nonsense_mediated_decay 24217903 24242154 24219875 24230986 ENSG00000169807 ENST00000341740 protein_coding 24219875 24242154 24219875 24230986 ENSG00000169807 ENST00000382759 unprocessed_pseudogene 23655405 23663854 NULL NULL ENSG00000169811 ENST00000326985 unprocessed_pseudogene 23655405 23662391 NULL NULL ENSG00000169811 ENST00000426043 unprocessed_pseudogene 23661276 23663854 NULL NULL ENSG00000169811 ENST00000303979 unprocessed_pseudogene 23630044 23632569 NULL NULL ENSG00000169849 ENST00000344884 protein_coding 20893326 20935601 20893655 20935504 ENSG00000169953 ENST00000491902 processed_transcript 20893326 20935601 NULL NULL ENSG00000169953 ENST00000382852 protein_coding 20930807 20935572 20931484 20935504 ENSG00000169953 ENST00000304790 protein_coding 20933700 20935621 20933821 20935504 ENSG00000169953 ENST00000505047 processed_transcript 20934594 20990548 NULL NULL ENSG00000169953 ENST00000306589 unprocessed_pseudogene 28121696 28134216 NULL NULL ENSG00000172283 ENST00000338673 unprocessed_pseudogene 28121660 28132811 NULL NULL ENSG00000172283 ENST00000306609 protein_coding 27768309 27771049 27768590 27770674 ENSG00000172288 ENST00000361963 protein_coding 27768264 27770483 27768590 27770212 ENSG00000172288 ENST00000333235 unprocessed_pseudogene 27624416 27629777 NULL NULL ENSG00000172294 ENST00000539489 unprocessed_pseudogene 27629055 27632852 NULL NULL ENSG00000172294 ENST00000416946 unprocessed_pseudogene 27600708 27606719 NULL NULL ENSG00000172297 ENST00000306667 unprocessed_pseudogene 27601458 27606322 NULL NULL ENSG00000172297 ENST00000423852 unprocessed_pseudogene 26355714 26361728 NULL NULL ENSG00000172332 ENST00000338706 unprocessed_pseudogene 26356114 26360978 NULL NULL ENSG00000172332 ENST00000418188 unprocessed_pseudogene 26332656 26338017 NULL NULL ENSG00000172342 ENST00000306882 protein_coding 26191376 26194116 26191751 26193835 ENSG00000172352 ENST00000382407 protein_coding 26191940 26194166 26192213 26193835 ENSG00000172352 ENST00000307393 protein_coding 20708557 20710478 20708674 20710357 ENSG00000172468 ENST00000309834 protein_coding 20708577 20750849 20708674 20750520 ENSG00000172468 ENST00000338876 nonsense_mediated_decay 20708577 20750849 20708674 20712690 ENSG00000172468 ENST00000382856 protein_coding 20708606 20713351 20708674 20712690 ENSG00000172468 ENST00000455422 transcribed_unprocessed_pseudogene 8774265 8784114 NULL NULL ENSG00000173357 ENST00000311828 processed_transcript 8777989 8782196 NULL NULL ENSG00000173357 ENST00000416687 transcribed_unprocessed_pseudogene 8774265 8782184 NULL NULL ENSG00000173357 ENST00000321217 protein_coding 3447082 3448082 3447286 3447843 ENSG00000176679 ENST00000559055 protein_coding 3447156 3448082 3447286 3447843 ENSG00000176679 ENST00000324446 lincRNA 21034387 21040114 NULL NULL ENSG00000176728 ENST00000454875 lincRNA 21034389 21239004 NULL NULL ENSG00000176728 ENST00000452584 lincRNA 21094203 21237882 NULL NULL ENSG00000176728 ENST00000331787 lincRNA 21094585 21239302 NULL NULL ENSG00000176728 ENST00000447937 lincRNA 21203384 21239281 NULL NULL ENSG00000176728 ENST00000253470 lincRNA 8651351 8685423 NULL NULL ENSG00000180910 ENST00000426790 protein_coding 20137669 20140477 20137995 20140102 ENSG00000182415 ENST00000250838 protein_coding 20137667 20139626 20137995 20139620 ENSG00000182415 ENST00000382764 protein_coding 23544840 23548246 23545072 23548149 ENSG00000183146 ENST00000329684 lincRNA 9528709 9531308 NULL NULL ENSG00000183385 ENST00000426035 lincRNA 9528709 9531566 NULL NULL ENSG00000183385 ENST00000331172 protein_coding 13496241 13524717 13496255 13524717 ENSG00000183704 ENST00000602732 protein_coding 25119966 25138523 25138491 25138523 ENSG00000183753 ENST00000331070 protein_coding 25130410 25151606 25138491 25144415 ENSG00000183753 ENST00000602818 processed_transcript 25130434 25151553 NULL NULL ENSG00000183753 ENST00000382585 protein_coding 25130410 25151612 25138491 25144415 ENSG00000183753 ENST00000602770 protein_coding 26753707 26772264 26772232 26772264 ENSG00000183795 ENST00000382392 protein_coding 26764151 26785354 26772232 26778157 ENSG00000183795 ENST00000602549 processed_transcript 26764175 26785295 NULL NULL ENSG00000183795 ENST00000331397 protein_coding 15360259 15592553 15361736 15591545 ENSG00000183878 ENST00000362096 protein_coding 15409321 15592550 15409583 15591545 ENSG00000183878 ENST00000329134 protein_coding 15434914 15592550 15434994 15591545 ENSG00000183878 ENST00000478900 processed_transcript 15472368 15591420 NULL NULL ENSG00000183878 ENST00000474365 processed_transcript 15505032 15591384 NULL NULL ENSG00000183878 ENST00000382893 protein_coding 15508182 15591858 15508784 15591545 ENSG00000183878 ENST00000479713 processed_transcript 15590922 15591803 NULL NULL ENSG00000183878 ENST00000382896 protein_coding 15361736 15591545 15361736 15591545 ENSG00000183878 ENST00000537580 protein_coding 15361736 15591545 15361736 15591545 ENSG00000183878 ENST00000538878 protein_coding 15434927 15591551 15434994 15591545 ENSG00000183878 ENST00000540140 protein_coding 15434948 15591545 15435229 15591545 ENSG00000183878 ENST00000545955 protein_coding 15435435 15591545 15435435 15591545 ENSG00000183878 ENST00000383070 protein_coding 2654896 2655740 2655030 2655644 ENSG00000184895 ENST00000525526 protein_coding 2655049 2655644 2655049 2655644 ENSG00000184895 ENST00000534739 protein_coding 2655145 2655644 2655145 2655644 ENSG00000184895 ENST00000330337 lincRNA 23745486 23756552 NULL NULL ENSG00000184991 ENST00000382840 processed_pseudogene 21154353 21154595 NULL NULL ENSG00000185275 ENST00000455570 lincRNA 6338814 6341671 NULL NULL ENSG00000185700 ENST00000328819 lincRNA 6339072 6341671 NULL NULL ENSG00000185700 ENST00000382287 protein_coding 27177048 27198251 27184245 27190170 ENSG00000185894 ENST00000602559 processed_transcript 27177107 27198227 NULL NULL ENSG00000185894 ENST00000602680 protein_coding 27190138 27208695 27190138 27190170 ENSG00000185894 ENST00000382365 protein_coding 26909216 26959626 26915081 26959332 ENSG00000187191 ENST00000446723 protein_coding 26909220 26959542 26915081 26959332 ENSG00000187191 ENST00000315357 protein_coding 26909222 26959540 26915081 26959332 ENSG00000187191 ENST00000400212 protein_coding 26929528 26959519 26929528 26959332 ENSG00000187191 ENST00000306737 protein_coding 26934285 26959519 26934285 26959332 ENSG00000187191 ENST00000338964 unprocessed_pseudogene 9743204 9745748 NULL NULL ENSG00000187657 ENST00000405239 protein_coding 25275502 25345241 25281357 25344947 ENSG00000188120 ENST00000466332 processed_transcript 25275510 25286959 NULL NULL ENSG00000188120 ENST00000382510 protein_coding 25276010 25345070 25276427 25344947 ENSG00000188120 ENST00000426000 protein_coding 25275506 25345140 25281357 25344947 ENSG00000188120 ENST00000540248 protein_coding 25275509 25345157 25281357 25344947 ENSG00000188120 ENST00000344424 unprocessed_pseudogene 28555962 28566682 NULL NULL ENSG00000188399 ENST00000431358 unprocessed_pseudogene 9215731 9218480 NULL NULL ENSG00000188656 ENST00000382670 unprocessed_pseudogene 9148739 9160478 NULL NULL ENSG00000197038 ENST00000538925 unprocessed_pseudogene 9154670 9160483 NULL NULL ENSG00000197038 ENST00000441780 unprocessed_pseudogene 27641798 27648105 NULL NULL ENSG00000197092 ENST00000361365 protein_coding 22737611 22755040 22737758 22754232 ENSG00000198692 ENST00000465253 processed_transcript 22737664 22750415 NULL NULL ENSG00000198692 ENST00000382772 protein_coding 22737680 22754516 22737758 22754232 ENSG00000198692 ENST00000464196 processed_transcript 22748604 22754516 NULL NULL ENSG00000198692 ENST00000485584 processed_transcript 22749733 22754516 NULL NULL ENSG00000198692 ENST00000382314 protein_coding 26980064 27053183 26980274 27047322 ENSG00000205916 ENST00000382296 protein_coding 26997726 27047331 26997726 27047322 ENSG00000205916 ENST00000449750 protein_coding 26980064 27053183 26980274 27047322 ENSG00000205916 ENST00000415508 protein_coding 26980066 27053181 26980274 27047322 ENSG00000205916 ENST00000440066 protein_coding 26980081 27053183 26980274 27047322 ENSG00000205916 ENST00000382432 protein_coding 26980008 27053183 26980274 27020194 ENSG00000205916 ENST00000400494 protein_coding 26980087 27053181 26980274 27020194 ENSG00000205916 ENST00000382290 protein_coding 26980008 27053183 26980274 27015437 ENSG00000205916 ENST00000416956 unprocessed_pseudogene 25525631 25538844 NULL NULL ENSG00000205936 ENST00000382449 protein_coding 25365594 25437503 25365888 25431648 ENSG00000205944 ENST00000382440 protein_coding 25365622 25437499 25365888 25431648 ENSG00000205944 ENST00000382433 protein_coding 25365695 25436146 25365888 25431648 ENSG00000205944 ENST00000382306 protein_coding 25365622 25437496 25365888 25431648 ENSG00000205944 ENST00000449947 protein_coding 25365678 25437499 25365888 25431648 ENSG00000205944 ENST00000382294 protein_coding 25365680 25437497 25365888 25431648 ENSG00000205944 ENST00000382424 protein_coding 25365695 25437497 25365888 25431648 ENSG00000205944 ENST00000400493 protein_coding 25365701 25437497 25365888 25431648 ENSG00000205944 ENST00000382431 protein_coding 25365701 25435854 25365888 25431648 ENSG00000205944 ENST00000382434 protein_coding 25365622 25395738 25365888 25395738 ENSG00000205944 ENST00000382966 processed_transcript 14475147 14532255 NULL NULL ENSG00000206159 ENST00000493160 processed_transcript 14494992 14530093 NULL NULL ENSG00000206159 ENST00000357871 processed_transcript 14514046 14532255 NULL NULL ENSG00000206159 ENST00000382963 processed_transcript 14517922 14532171 NULL NULL ENSG00000206159 ENST00000382965 transcribed_unprocessed_pseudogene 14518595 14532121 NULL NULL ENSG00000206159 ENST00000417072 lincRNA 9578193 9596085 NULL NULL ENSG00000212855 ENST00000450591 lincRNA 6274285 6292186 NULL NULL ENSG00000212856 ENST00000388836 processed_pseudogene 5441186 5442472 NULL NULL ENSG00000214207 ENST00000400275 processed_pseudogene 15398518 15399258 NULL NULL ENSG00000215414 ENST00000536206 processed_pseudogene 15398518 15399258 NULL NULL ENSG00000215414 ENST00000258589 unprocessed_pseudogene 28654360 28725837 NULL NULL ENSG00000215506 ENST00000448881 transcribed_processed_pseudogene 28269821 28279455 NULL NULL ENSG00000215507 ENST00000400476 processed_transcript 28269867 28275354 NULL NULL ENSG00000215507 ENST00000442535 processed_pseudogene 25012691 25013903 NULL NULL ENSG00000215537 ENST00000448575 transcribed_processed_pseudogene 25683455 25693089 NULL NULL ENSG00000215540 ENST00000458444 processed_transcript 25687556 25693043 NULL NULL ENSG00000215540 ENST00000400581 lincRNA 24442945 24445023 NULL NULL ENSG00000215560 ENST00000441139 processed_transcript 21617317 21665039 NULL NULL ENSG00000215580 ENST00000400605 processed_transcript 21618198 21665022 NULL NULL ENSG00000215580 ENST00000513194 transcribed_unprocessed_pseudogene 21618471 21646770 NULL NULL ENSG00000215580 ENST00000421118 processed_pseudogene 14043242 14044475 NULL NULL ENSG00000215583 ENST00000431340 unprocessed_pseudogene 8148239 8150250 NULL NULL ENSG00000215601 ENST00000415010 processed_pseudogene 7721727 7722917 NULL NULL ENSG00000215603 ENST00000404428 processed_pseudogene 3417693 3417851 NULL NULL ENSG00000216777 ENST00000403990 processed_pseudogene 8286832 8287941 NULL NULL ENSG00000216824 ENST00000406090 processed_pseudogene 23005142 23005596 NULL NULL ENSG00000216844 ENST00000407745 processed_pseudogene 21033988 21034158 NULL NULL ENSG00000217179 ENST00000403487 processed_pseudogene 21147061 21148284 NULL NULL ENSG00000217896 ENST00000405035 processed_pseudogene 3719265 3720910 NULL NULL ENSG00000218410 ENST00000421995 unprocessed_pseudogene 26001669 26003238 NULL NULL ENSG00000223362 ENST00000449659 unprocessed_pseudogene 27898535 27899017 NULL NULL ENSG00000223406 ENST00000425912 unprocessed_pseudogene 25805613 25813969 NULL NULL ENSG00000223407 ENST00000439805 unprocessed_pseudogene 7546940 7549069 NULL NULL ENSG00000223422 ENST00000435111 lincRNA 16388092 16389369 NULL NULL ENSG00000223517 ENST00000455085 unprocessed_pseudogene 19894090 19896695 NULL NULL ENSG00000223555 ENST00000414667 processed_pseudogene 2863108 2863314 NULL NULL ENSG00000223600 ENST00000413867 unprocessed_pseudogene 27577303 27583462 NULL NULL ENSG00000223636 ENST00000456360 transcribed_unprocessed_pseudogene 23556877 23563471 NULL NULL ENSG00000223637 ENST00000444169 processed_transcript 23557034 23563448 NULL NULL ENSG00000223637 ENST00000421387 lincRNA 27329790 27330920 NULL NULL ENSG00000223641 ENST00000412737 processed_pseudogene 28064470 28065042 NULL NULL ENSG00000223655 ENST00000417252 unprocessed_pseudogene 26314334 26320641 NULL NULL ENSG00000223698 ENST00000418671 unprocessed_pseudogene 6196093 6211364 NULL NULL ENSG00000223744 ENST00000443911 unprocessed_pseudogene 27856055 27859704 NULL NULL ENSG00000223856 ENST00000428060 processed_pseudogene 15342765 15343320 NULL NULL ENSG00000223915 ENST00000417434 processed_pseudogene 8231577 8232000 NULL NULL ENSG00000223955 ENST00000440402 processed_pseudogene 27131348 27132623 NULL NULL ENSG00000223978 ENST00000428380 unprocessed_pseudogene 20134179 20135788 NULL NULL ENSG00000224033 ENST00000446621 processed_pseudogene 15195704 15207719 NULL NULL ENSG00000224035 ENST00000420443 transcribed_unprocessed_pseudogene 14460540 14468218 NULL NULL ENSG00000224060 ENST00000430152 processed_transcript 14465804 14468226 NULL NULL ENSG00000224060 ENST00000445253 lincRNA 9638762 9650854 NULL NULL ENSG00000224075 ENST00000435142 unprocessed_pseudogene 20994888 21001199 NULL NULL ENSG00000224151 ENST00000412474 unprocessed_pseudogene 19841408 19856476 NULL NULL ENSG00000224166 ENST00000445573 unprocessed_pseudogene 25803986 25805205 NULL NULL ENSG00000224169 ENST00000413946 processed_pseudogene 26640856 26641730 NULL NULL ENSG00000224210 ENST00000420810 processed_pseudogene 28695572 28695890 NULL NULL ENSG00000224240 ENST00000421178 protein_coding 9374241 9384693 9374241 9384693 ENSG00000224336 ENST00000438971 unprocessed_pseudogene 9021303 9023412 NULL NULL ENSG00000224408 ENST00000415994 unprocessed_pseudogene 22970662 22973695 NULL NULL ENSG00000224482 ENST00000436723 unprocessed_pseudogene 20020635 20022686 NULL NULL ENSG00000224485 ENST00000427212 processed_pseudogene 17053626 17054595 NULL NULL ENSG00000224518 ENST00000417797 unprocessed_pseudogene 26066052 26067657 NULL NULL ENSG00000224571 ENST00000447526 processed_pseudogene 8218972 8220184 NULL NULL ENSG00000224634 ENST00000451071 transcribed_unprocessed_pseudogene 24795392 24805025 NULL NULL ENSG00000224657 ENST00000400578 processed_transcript 24795438 24800925 NULL NULL ENSG00000224657 ENST00000413372 processed_pseudogene 26422392 26423173 NULL NULL ENSG00000224827 ENST00000457708 unprocessed_pseudogene 25880340 25882396 NULL NULL ENSG00000224866 ENST00000445813 unprocessed_pseudogene 24666828 24667842 NULL NULL ENSG00000224873 ENST00000434179 unprocessed_pseudogene 24816763 24819006 NULL NULL ENSG00000224917 ENST00000413200 processed_pseudogene 6587003 6587221 NULL NULL ENSG00000224953 ENST00000443200 unprocessed_pseudogene 19909863 19912576 NULL NULL ENSG00000224964 ENST00000421205 lincRNA 19612838 19626898 NULL NULL ENSG00000224989 ENST00000443820 unprocessed_pseudogene 14474827 14499123 NULL NULL ENSG00000225117 ENST00000422655 unprocessed_pseudogene 25608612 25618427 NULL NULL ENSG00000225189 ENST00000426293 unprocessed_pseudogene 27845598 27848709 NULL NULL ENSG00000225256 ENST00000431179 unprocessed_pseudogene 27821207 27843493 NULL NULL ENSG00000225287 ENST00000412165 unprocessed_pseudogene 27894743 27896353 NULL NULL ENSG00000225326 ENST00000434110 unprocessed_pseudogene 25727742 25760787 NULL NULL ENSG00000225466 ENST00000433767 unprocessed_pseudogene 26378973 26385131 NULL NULL ENSG00000225491 ENST00000450145 protein_coding 9293012 9323893 9293012 9323893 ENSG00000225516 ENST00000423213 protein_coding 9301461 9323893 9301461 9323893 ENSG00000225516 ENST00000430032 protein_coding 9323618 9344176 9323618 9344176 ENSG00000225516 ENST00000437686 lincRNA 7567398 7569288 NULL NULL ENSG00000225520 ENST00000426661 antisense 9185120 9193010 NULL NULL ENSG00000225560 ENST00000432394 antisense 9187188 9192791 NULL NULL ENSG00000225560 ENST00000447528 unprocessed_pseudogene 27764791 27766400 NULL NULL ENSG00000225609 ENST00000453474 unprocessed_pseudogene 24344576 24349859 NULL NULL ENSG00000225615 ENST00000440297 unprocessed_pseudogene 22889140 22904786 NULL NULL ENSG00000225624 ENST00000458209 processed_pseudogene 3646038 3647587 NULL NULL ENSG00000225653 ENST00000456541 processed_transcript 9904163 9904995 NULL NULL ENSG00000225685 ENST00000426936 transcribed_unprocessed_pseudogene 9904196 9906760 NULL NULL ENSG00000225685 ENST00000443934 processed_pseudogene 20602683 20603011 NULL NULL ENSG00000225716 ENST00000429066 processed_pseudogene 19949081 19949408 NULL NULL ENSG00000225740 ENST00000418221 unprocessed_pseudogene 8132490 8145229 NULL NULL ENSG00000225809 ENST00000445125 processed_pseudogene 10036113 10036711 NULL NULL ENSG00000225840 ENST00000426199 unprocessed_pseudogene 28390498 28390720 NULL NULL ENSG00000225876 ENST00000436888 processed_pseudogene 4669726 4670889 NULL NULL ENSG00000225878 ENST00000440676 unprocessed_pseudogene 20267200 20269988 NULL NULL ENSG00000225895 ENST00000425789 processed_pseudogene 19838632 19838960 NULL NULL ENSG00000225896 ENST00000411756 unprocessed_pseudogene 19921687 19937209 NULL NULL ENSG00000226011 ENST00000452415 unprocessed_pseudogene 23799361 23800927 NULL NULL ENSG00000226042 ENST00000455560 unprocessed_pseudogene 10011462 10011816 NULL NULL ENSG00000226061 ENST00000445405 unprocessed_pseudogene 24073668 24083297 NULL NULL ENSG00000226092 ENST00000413550 unprocessed_pseudogene 20024579 20033510 NULL NULL ENSG00000226116 ENST00000449843 unprocessed_pseudogene 9477858 9478325 NULL NULL ENSG00000226223 ENST00000416040 processed_pseudogene 26829804 26831082 NULL NULL ENSG00000226270 ENST00000445421 processed_pseudogene 19740393 19741282 NULL NULL ENSG00000226353 ENST00000458627 lincRNA 20552880 20566932 NULL NULL ENSG00000226362 ENST00000427537 unprocessed_pseudogene 26081100 26086248 NULL NULL ENSG00000226369 ENST00000411487 unprocessed_pseudogene 19833478 19835057 NULL NULL ENSG00000226449 ENST00000423409 processed_pseudogene 23069230 23069448 NULL NULL ENSG00000226504 ENST00000445453 processed_pseudogene 8239704 8240071 NULL NULL ENSG00000226529 ENST00000455254 processed_pseudogene 16750976 16752238 NULL NULL ENSG00000226555 ENST00000421895 unprocessed_pseudogene 20242567 20258088 NULL NULL ENSG00000226611 ENST00000434773 unprocessed_pseudogene 14649708 14656818 NULL NULL ENSG00000226863 ENST00000431260 unprocessed_pseudogene 25820526 25821539 NULL NULL ENSG00000226873 ENST00000436568 lincRNA 25082602 25119431 NULL NULL ENSG00000226906 ENST00000437359 unprocessed_pseudogene 23473154 23480781 NULL NULL ENSG00000226918 ENST00000470460 processed_transcript 24549608 24564028 NULL NULL ENSG00000226941 ENST00000250831 protein_coding 24549617 24564028 24551595 24563750 ENSG00000226941 ENST00000414629 protein_coding 24454970 24564028 24551595 24563750 ENSG00000226941 ENST00000445779 protein_coding 24454970 24564028 24551595 24563750 ENSG00000226941 ENST00000413610 unprocessed_pseudogene 10007397 10007923 NULL NULL ENSG00000226975 ENST00000412493 unprocessed_pseudogene 17659096 17705211 NULL NULL ENSG00000227166 ENST00000425544 unprocessed_pseudogene 7995171 8012244 NULL NULL ENSG00000227204 ENST00000438459 processed_pseudogene 25204177 25205333 NULL NULL ENSG00000227251 ENST00000444242 unprocessed_pseudogene 2749724 2751693 NULL NULL ENSG00000227289 ENST00000441906 lincRNA 26631479 26632610 NULL NULL ENSG00000227439 ENST00000426983 unprocessed_pseudogene 24065082 24067253 NULL NULL ENSG00000227444 ENST00000381172 unprocessed_pseudogene 14551845 14619171 NULL NULL ENSG00000227447 ENST00000430663 unprocessed_pseudogene 20642973 20649286 NULL NULL ENSG00000227494 ENST00000456738 unprocessed_pseudogene 28732789 28737748 NULL NULL ENSG00000227629 ENST00000423333 unprocessed_pseudogene 27412731 27419678 NULL NULL ENSG00000227633 ENST00000420603 unprocessed_pseudogene 28079980 28082028 NULL NULL ENSG00000227635 ENST00000432201 processed_pseudogene 8281078 8282095 NULL NULL ENSG00000227830 ENST00000445313 processed_pseudogene 26837938 26839079 NULL NULL ENSG00000227837 ENST00000436690 processed_pseudogene 28137388 28137719 NULL NULL ENSG00000227867 ENST00000450481 unprocessed_pseudogene 26092074 26098440 NULL NULL ENSG00000227871 ENST00000444494 unprocessed_pseudogene 25824651 25824982 NULL NULL ENSG00000227915 ENST00000423569 processed_pseudogene 17053427 17053630 NULL NULL ENSG00000227949 ENST00000411585 unprocessed_pseudogene 23717738 23719956 NULL NULL ENSG00000227989 ENST00000428070 processed_pseudogene 20949636 20949966 NULL NULL ENSG00000228193 ENST00000432613 unprocessed_pseudogene 8769244 8771317 NULL NULL ENSG00000228207 ENST00000416110 lincRNA 24997731 24998862 NULL NULL ENSG00000228240 ENST00000452426 unprocessed_pseudogene 23693725 23695897 NULL NULL ENSG00000228257 ENST00000456123 lincRNA 27209230 27246039 NULL NULL ENSG00000228296 ENST00000449963 lincRNA 9650924 9655122 NULL NULL ENSG00000228379 ENST00000433321 antisense 9205412 9213290 NULL NULL ENSG00000228383 ENST00000436801 antisense 9207466 9213071 NULL NULL ENSG00000228383 ENST00000452256 antisense 9212578 9235047 NULL NULL ENSG00000228383 ENST00000432892 antisense 9212578 9214701 NULL NULL ENSG00000228383 ENST00000420524 antisense 9232924 9235047 NULL NULL ENSG00000228383 ENST00000418290 processed_pseudogene 14913906 14915763 NULL NULL ENSG00000228411 ENST00000415662 unprocessed_pseudogene 26113711 26116841 NULL NULL ENSG00000228465 ENST00000451854 processed_pseudogene 19304706 19305532 NULL NULL ENSG00000228518 ENST00000432672 unprocessed_pseudogene 24683194 24683996 NULL NULL ENSG00000228571 ENST00000422712 unprocessed_pseudogene 19628716 19630918 NULL NULL ENSG00000228578 ENST00000420174 processed_pseudogene 22551937 22558682 NULL NULL ENSG00000228764 ENST00000427373 lincRNA 27524447 27540866 NULL NULL ENSG00000228786 ENST00000434164 antisense 16905522 16915913 NULL NULL ENSG00000228787 ENST00000440679 unprocessed_pseudogene 24210845 24211859 NULL NULL ENSG00000228850 ENST00000430228 lincRNA 9555262 9558905 NULL NULL ENSG00000228890 ENST00000457222 protein_coding 9236030 9238826 9236076 9238638 ENSG00000228927 ENST00000424594 protein_coding 9236076 9238825 9236076 9237891 ENSG00000228927 ENST00000491844 processed_transcript 9236076 9238832 NULL NULL ENSG00000228927 ENST00000469322 processed_transcript 9237436 9238817 NULL NULL ENSG00000228927 ENST00000440483 protein_coding 9236030 9307357 9236076 9307170 ENSG00000228927 ENST00000427871 protein_coding 9236076 9238832 9236076 9237587 ENSG00000228927 ENST00000426660 unprocessed_pseudogene 20442064 20446647 NULL NULL ENSG00000228945 ENST00000415776 processed_pseudogene 19868881 19870005 NULL NULL ENSG00000229129 ENST00000413320 unprocessed_pseudogene 19993979 19995588 NULL NULL ENSG00000229138 ENST00000440136 unprocessed_pseudogene 24329997 24332168 NULL NULL ENSG00000229159 ENST00000414182 processed_pseudogene 2797042 2799161 NULL NULL ENSG00000229163 ENST00000434454 unprocessed_pseudogene 9669027 9684305 NULL NULL ENSG00000229208 ENST00000423480 unprocessed_pseudogene 24355478 24362727 NULL NULL ENSG00000229234 ENST00000455084 lincRNA 22627554 22681114 NULL NULL ENSG00000229236 ENST00000439472 lincRNA 22669140 22680293 NULL NULL ENSG00000229236 ENST00000367272 unprocessed_pseudogene 28424070 28500565 NULL NULL ENSG00000229238 ENST00000431405 unprocessed_pseudogene 26227851 26236493 NULL NULL ENSG00000229250 ENST00000454958 processed_pseudogene 20438493 20439381 NULL NULL ENSG00000229302 ENST00000426699 lincRNA 3904538 3968361 NULL NULL ENSG00000229308 ENST00000451423 unprocessed_pseudogene 27959160 27960713 NULL NULL ENSG00000229343 ENST00000455273 unprocessed_pseudogene 20615036 20634023 NULL NULL ENSG00000229406 ENST00000441913 unprocessed_pseudogene 23839132 23843004 NULL NULL ENSG00000229416 ENST00000425411 processed_pseudogene 20309770 20310894 NULL NULL ENSG00000229465 ENST00000439651 processed_pseudogene 3734347 3734763 NULL NULL ENSG00000229518 ENST00000287721 protein_coding 9195406 9198202 9195452 9198014 ENSG00000229549 ENST00000383000 protein_coding 9195452 9198201 9195452 9197267 ENSG00000229549 ENST00000477879 processed_transcript 9195452 9198208 NULL NULL ENSG00000229549 ENST00000436159 processed_transcript 9196812 9198193 NULL NULL ENSG00000229549 ENST00000383005 protein_coding 9195406 9218479 9195452 9218292 ENSG00000229549 ENST00000330628 protein_coding 9195452 9218479 9195452 9218292 ENSG00000229549 ENST00000537415 protein_coding 9195501 9197317 9195758 9197317 ENSG00000229549 ENST00000449858 processed_pseudogene 23023223 23024223 NULL NULL ENSG00000229551 ENST00000444617 unprocessed_pseudogene 24195902 24204260 NULL NULL ENSG00000229553 ENST00000439525 lincRNA 6225260 6229454 NULL NULL ENSG00000229643 ENST00000424581 unprocessed_pseudogene 27725937 27734591 NULL NULL ENSG00000229709 ENST00000414540 unprocessed_pseudogene 24017478 24019697 NULL NULL ENSG00000229725 ENST00000422208 unprocessed_pseudogene 7801038 7805681 NULL NULL ENSG00000229745 ENST00000427496 unprocessed_pseudogene 24452072 24454098 NULL NULL ENSG00000229940 ENST00000434308 unprocessed_pseudogene 8839792 8842136 NULL NULL ENSG00000230025 ENST00000447168 unprocessed_pseudogene 23858456 23860106 NULL NULL ENSG00000230029 ENST00000427622 antisense 9334896 9342768 NULL NULL ENSG00000230066 ENST00000414596 antisense 9336950 9342550 NULL NULL ENSG00000230066 ENST00000444350 unprocessed_pseudogene 25669468 25671516 NULL NULL ENSG00000230073 ENST00000439968 processed_pseudogene 20694212 20694542 NULL NULL ENSG00000230377 ENST00000458706 processed_pseudogene 20230369 20230696 NULL NULL ENSG00000230412 ENST00000446387 unprocessed_pseudogene 20740303 20740446 NULL NULL ENSG00000230458 ENST00000417699 unprocessed_pseudogene 24727136 24760228 NULL NULL ENSG00000230476 ENST00000458667 lincRNA 19664680 19691634 NULL NULL ENSG00000230663 ENST00000424230 unprocessed_pseudogene 24908998 24915934 NULL NULL ENSG00000230727 ENST00000434374 unprocessed_pseudogene 24674428 24682786 NULL NULL ENSG00000230814 ENST00000451173 processed_pseudogene 27164646 27165450 NULL NULL ENSG00000230819 ENST00000419224 unprocessed_pseudogene 28069535 28075973 NULL NULL ENSG00000230854 ENST00000432915 unprocessed_pseudogene 20973224 20973715 NULL NULL ENSG00000230904 ENST00000418278 unprocessed_pseudogene 26328624 26329218 NULL NULL ENSG00000230977 ENST00000414395 unprocessed_pseudogene 26063388 26063870 NULL NULL ENSG00000231026 ENST00000417334 lincRNA 27874637 27879535 NULL NULL ENSG00000231141 ENST00000449148 unprocessed_pseudogene 24118460 24151496 NULL NULL ENSG00000231159 ENST00000416652 unprocessed_pseudogene 20323252 20338370 NULL NULL ENSG00000231311 ENST00000430062 processed_pseudogene 5075256 5076110 NULL NULL ENSG00000231341 ENST00000414121 unprocessed_pseudogene 26196025 26197634 NULL NULL ENSG00000231375 ENST00000446466 unprocessed_pseudogene 10009199 10010334 NULL NULL ENSG00000231411 ENST00000437794 unprocessed_pseudogene 26102716 26106365 NULL NULL ENSG00000231423 ENST00000449381 unprocessed_pseudogene 9448180 9458885 NULL NULL ENSG00000231436 ENST00000435741 processed_pseudogene 28772667 28773306 NULL NULL ENSG00000231514 ENST00000444263 lincRNA 2870953 2965258 NULL NULL ENSG00000231535 ENST00000425031 lincRNA 2871039 2970313 NULL NULL ENSG00000231535 ENST00000418624 processed_pseudogene 25954968 25955206 NULL NULL ENSG00000231540 ENST00000451661 unprocessed_pseudogene 28140831 28141844 NULL NULL ENSG00000231716 ENST00000441642 unprocessed_pseudogene 9707273 9708390 NULL NULL ENSG00000231874 ENST00000453312 unprocessed_pseudogene 8898635 8908029 NULL NULL ENSG00000231988 ENST00000443152 processed_pseudogene 26646410 26647652 NULL NULL ENSG00000232003 ENST00000442090 processed_pseudogene 24214967 24215298 NULL NULL ENSG00000232029 ENST00000412220 unprocessed_pseudogene 27736470 27738492 NULL NULL ENSG00000232064 ENST00000430735 processed_pseudogene 2696023 2696259 NULL NULL ENSG00000232195 ENST00000438294 unprocessed_pseudogene 26250254 26252165 NULL NULL ENSG00000232205 ENST00000398758 unprocessed_pseudogene 14373025 14378737 NULL NULL ENSG00000232226 ENST00000454543 processed_pseudogene 9003694 9005311 NULL NULL ENSG00000232235 ENST00000413486 lincRNA 8506335 8512883 NULL NULL ENSG00000232348 ENST00000453955 lincRNA 8572513 8573324 NULL NULL ENSG00000232419 ENST00000445112 unprocessed_pseudogene 25886405 25892840 NULL NULL ENSG00000232424 ENST00000453726 unprocessed_pseudogene 24194701 24195494 NULL NULL ENSG00000232475 ENST00000450781 unprocessed_pseudogene 22163071 22174090 NULL NULL ENSG00000232522 ENST00000434155 unprocessed_pseudogene 6968774 6974543 NULL NULL ENSG00000232583 ENST00000427963 unprocessed_pseudogene 26118927 26141228 NULL NULL ENSG00000232585 ENST00000429406 unprocessed_pseudogene 27876158 27881307 NULL NULL ENSG00000232614 ENST00000426129 unprocessed_pseudogene 9502838 9506619 NULL NULL ENSG00000232617 ENST00000450329 unprocessed_pseudogene 6388504 6388970 NULL NULL ENSG00000232620 ENST00000436364 processed_pseudogene 23382992 23383975 NULL NULL ENSG00000232634 ENST00000414751 processed_pseudogene 28007090 28007415 NULL NULL ENSG00000232695 ENST00000435433 processed_pseudogene 14442350 14443562 NULL NULL ENSG00000232730 ENST00000430287 unprocessed_pseudogene 20283081 20285685 NULL NULL ENSG00000232744 ENST00000436338 processed_pseudogene 25171741 25172810 NULL NULL ENSG00000232764 ENST00000434487 antisense 9167489 9172441 NULL NULL ENSG00000232808 ENST00000434556 unprocessed_pseudogene 25908985 25911730 NULL NULL ENSG00000232845 ENST00000451397 unprocessed_pseudogene 20344721 20346300 NULL NULL ENSG00000232899 ENST00000449393 unprocessed_pseudogene 25897335 25897907 NULL NULL ENSG00000232910 ENST00000421750 unprocessed_pseudogene 28050665 28053397 NULL NULL ENSG00000232914 ENST00000420090 processed_pseudogene 9068524 9068856 NULL NULL ENSG00000232924 ENST00000427677 processed_pseudogene 3550846 3551909 NULL NULL ENSG00000232927 ENST00000425589 processed_pseudogene 26805484 26806553 NULL NULL ENSG00000232976 ENST00000417305 antisense 2834885 2870667 NULL NULL ENSG00000233070 ENST00000431145 antisense 2869669 2870612 NULL NULL ENSG00000233070 ENST00000442391 unprocessed_pseudogene 20278413 20279581 NULL NULL ENSG00000233120 ENST00000428264 processed_pseudogene 25195394 25197342 NULL NULL ENSG00000233126 ENST00000437934 unprocessed_pseudogene 28157582 28158384 NULL NULL ENSG00000233156 ENST00000453983 unprocessed_pseudogene 20096229 20105140 NULL NULL ENSG00000233378 ENST00000419557 lincRNA 20488139 20515096 NULL NULL ENSG00000233522 ENST00000451909 unprocessed_pseudogene 20691244 20691509 NULL NULL ENSG00000233546 ENST00000437571 processed_pseudogene 27633431 27633809 NULL NULL ENSG00000233619 ENST00000433995 processed_pseudogene 6705748 6706293 NULL NULL ENSG00000233634 ENST00000416803 processed_pseudogene 27535139 27537958 NULL NULL ENSG00000233652 ENST00000438677 lincRNA 8551411 8551919 NULL NULL ENSG00000233699 ENST00000420675 processed_pseudogene 26424484 26427287 NULL NULL ENSG00000233740 ENST00000430517 unprocessed_pseudogene 14730915 14746333 NULL NULL ENSG00000233774 ENST00000426950 protein_coding 9175073 9177887 9175119 9177699 ENSG00000233803 ENST00000383008 protein_coding 9175119 9177886 9175119 9176952 ENSG00000233803 ENST00000466036 processed_transcript 9175119 9177893 NULL NULL ENSG00000233803 ENST00000482082 processed_transcript 9176497 9177878 NULL NULL ENSG00000233803 ENST00000417124 processed_pseudogene 28546758 28547377 NULL NULL ENSG00000233843 ENST00000457658 lincRNA 14774265 14802370 NULL NULL ENSG00000233864 ENST00000440408 lincRNA 14774265 14804162 NULL NULL ENSG00000233864 ENST00000417071 lincRNA 14774468 14800184 NULL NULL ENSG00000233864 ENST00000543097 lincRNA 14774284 14776614 NULL NULL ENSG00000233864 ENST00000447588 processed_pseudogene 27539301 27540203 NULL NULL ENSG00000233944 ENST00000412870 unprocessed_pseudogene 15042075 15060090 NULL NULL ENSG00000234059 ENST00000440624 processed_pseudogene 26153058 26153384 NULL NULL ENSG00000234081 ENST00000429463 unprocessed_pseudogene 9461792 9463961 NULL NULL ENSG00000234110 ENST00000439309 processed_pseudogene 24663389 24663720 NULL NULL ENSG00000234131 ENST00000454315 processed_pseudogene 8232073 8233191 NULL NULL ENSG00000234179 ENST00000452257 processed_pseudogene 13901758 13903233 NULL NULL ENSG00000234385 ENST00000447471 unprocessed_pseudogene 26542751 26549673 NULL NULL ENSG00000234399 ENST00000382707 protein_coding 23696765 23711212 23698778 23710934 ENSG00000234414 ENST00000361046 nonsense_mediated_decay 23696790 23711212 23698778 23704609 ENSG00000234414 ENST00000303902 protein_coding 23698778 23711210 23698778 23710934 ENSG00000234414 ENST00000439108 protein_coding 23673258 23711210 23706817 23710934 ENSG00000234414 ENST00000431768 processed_pseudogene 21489455 21490459 NULL NULL ENSG00000234529 ENST00000418461 unprocessed_pseudogene 6171998 6173115 NULL NULL ENSG00000234583 ENST00000421058 unprocessed_pseudogene 17460542 17567954 NULL NULL ENSG00000234620 ENST00000455855 processed_pseudogene 3161849 3162867 NULL NULL ENSG00000234652 ENST00000421008 unprocessed_pseudogene 28148401 28155003 NULL NULL ENSG00000234744 ENST00000455527 transcribed_unprocessed_pseudogene 7581026 7644748 NULL NULL ENSG00000234795 ENST00000442584 processed_transcript 7610636 7677302 NULL NULL ENSG00000234795 ENST00000448006 antisense 9355208 9363096 NULL NULL ENSG00000234803 ENST00000418016 antisense 9357275 9362877 NULL NULL ENSG00000234803 ENST00000598351 antisense 9362384 9364506 NULL NULL ENSG00000234803 ENST00000451062 processed_transcript 6124308 6131994 NULL NULL ENSG00000234830 ENST00000452103 processed_transcript 6126374 6131976 NULL NULL ENSG00000234830 ENST00000505707 transcribed_unprocessed_pseudogene 6130047 6131976 NULL NULL ENSG00000234830 ENST00000452458 processed_pseudogene 8240282 8240751 NULL NULL ENSG00000234850 ENST00000411536 unprocessed_pseudogene 28201926 28234640 NULL NULL ENSG00000234888 ENST00000447105 unprocessed_pseudogene 9789162 9797032 NULL NULL ENSG00000234950 ENST00000422633 processed_pseudogene 5205786 5207005 NULL NULL ENSG00000235001 ENST00000545933 processed_pseudogene 5205788 5206981 NULL NULL ENSG00000235001 ENST00000430729 unprocessed_pseudogene 27869163 27870333 NULL NULL ENSG00000235004 ENST00000439103 unprocessed_pseudogene 28344478 28354295 NULL NULL ENSG00000235014 ENST00000446299 lincRNA 24585087 24630861 NULL NULL ENSG00000235059 ENST00000439653 lincRNA 24626684 24631739 NULL NULL ENSG00000235059 ENST00000445200 unprocessed_pseudogene 6174083 6175961 NULL NULL ENSG00000235094 ENST00000411983 processed_pseudogene 5661341 5661778 NULL NULL ENSG00000235175 ENST00000434709 unprocessed_pseudogene 9925635 9927195 NULL NULL ENSG00000235193 ENST00000420149 lincRNA 26716349 26753172 NULL NULL ENSG00000235412 ENST00000458328 unprocessed_pseudogene 16192955 16198480 NULL NULL ENSG00000235451 ENST00000452645 transcribed_unprocessed_pseudogene 15265842 15274125 NULL NULL ENSG00000235462 ENST00000439217 processed_transcript 15271184 15273460 NULL NULL ENSG00000235462 ENST00000415230 unprocessed_pseudogene 20811557 20812165 NULL NULL ENSG00000235479 ENST00000420889 unprocessed_pseudogene 28018078 28044800 NULL NULL ENSG00000235511 ENST00000418455 unprocessed_pseudogene 19900195 19901364 NULL NULL ENSG00000235521 ENST00000421819 unprocessed_pseudogene 27658448 27673933 NULL NULL ENSG00000235583 ENST00000420610 unprocessed_pseudogene 14077914 14108092 NULL NULL ENSG00000235649 ENST00000416843 unprocessed_pseudogene 9928411 9928816 NULL NULL ENSG00000235691 ENST00000425318 unprocessed_pseudogene 23627270 23629049 NULL NULL ENSG00000235719 ENST00000431853 processed_pseudogene 59001391 59001635 NULL NULL ENSG00000235857 ENST00000425857 unprocessed_pseudogene 6361017 6364798 NULL NULL ENSG00000235895 ENST00000445264 unprocessed_pseudogene 26288505 26303990 NULL NULL ENSG00000235981 ENST00000428342 processed_pseudogene 17019778 17019948 NULL NULL ENSG00000236131 ENST00000454995 processed_pseudogene 27314746 27315988 NULL NULL ENSG00000236379 ENST00000428845 protein_coding 9365489 9368285 9365535 9368097 ENSG00000236424 ENST00000444056 protein_coding 9365535 9368284 9365535 9367350 ENSG00000236424 ENST00000489397 processed_transcript 9365535 9368291 NULL NULL ENSG00000236424 ENST00000495839 processed_transcript 9366895 9368276 NULL NULL ENSG00000236424 ENST00000429039 protein_coding 9365535 9368284 9365535 9367069 ENSG00000236424 ENST00000432046 unprocessed_pseudogene 20903729 20903872 NULL NULL ENSG00000236429 ENST00000421279 unprocessed_pseudogene 7555780 7557589 NULL NULL ENSG00000236435 ENST00000438550 processed_pseudogene 14365457 14366162 NULL NULL ENSG00000236477 ENST00000436067 processed_pseudogene 20340818 20341146 NULL NULL ENSG00000236599 ENST00000428616 unprocessed_pseudogene 23567656 23567881 NULL NULL ENSG00000236615 ENST00000442113 unprocessed_pseudogene 25862069 25872955 NULL NULL ENSG00000236620 ENST00000444014 unprocessed_pseudogene 25695956 25697532 NULL NULL ENSG00000236647 ENST00000421675 unprocessed_pseudogene 7558552 7560719 NULL NULL ENSG00000236690 ENST00000429799 unprocessed_pseudogene 9860098 9871796 NULL NULL ENSG00000236718 ENST00000420376 unprocessed_pseudogene 9868005 9868142 NULL NULL ENSG00000236718 ENST00000457163 unprocessed_pseudogene 9385717 9388290 NULL NULL ENSG00000236786 ENST00000417910 lincRNA 24246961 24252016 NULL NULL ENSG00000236951 ENST00000419158 lincRNA 24247839 24293631 NULL NULL ENSG00000236951 ENST00000434481 unprocessed_pseudogene 23823812 23835894 NULL NULL ENSG00000237023 ENST00000413466 lincRNA 7672965 7678724 NULL NULL ENSG00000237048 ENST00000451467 lincRNA 6110487 6111651 NULL NULL ENSG00000237069 ENST00000430307 processed_pseudogene 6026843 6027306 NULL NULL ENSG00000237195 ENST00000451162 unprocessed_pseudogene 23592583 23599131 NULL NULL ENSG00000237269 ENST00000418213 unprocessed_pseudogene 25917379 25944297 NULL NULL ENSG00000237302 ENST00000418578 processed_pseudogene 23292756 23293067 NULL NULL ENSG00000237427 ENST00000425026 processed_pseudogene 10027986 10029907 NULL NULL ENSG00000237447 ENST00000435696 unprocessed_pseudogene 26223946 26225959 NULL NULL ENSG00000237467 ENST00000440468 unprocessed_pseudogene 28089415 28100299 NULL NULL ENSG00000237546 ENST00000429883 unprocessed_pseudogene 20063469 20065380 NULL NULL ENSG00000237558 ENST00000421353 lincRNA 6311475 6315118 NULL NULL ENSG00000237563 ENST00000452432 unprocessed_pseudogene 20107081 20109132 NULL NULL ENSG00000237616 ENST00000454281 processed_pseudogene 2657868 2658369 NULL NULL ENSG00000237659 ENST00000431631 processed_pseudogene 6768794 6769413 NULL NULL ENSG00000237701 ENST00000442145 antisense 9225731 9233636 NULL NULL ENSG00000237802 ENST00000450658 antisense 9227800 9233417 NULL NULL ENSG00000237802 ENST00000411668 unprocessed_pseudogene 27710269 27712180 NULL NULL ENSG00000237823 ENST00000433481 unprocessed_pseudogene 24546550 24548715 NULL NULL ENSG00000237902 ENST00000435945 unprocessed_pseudogene 28740998 28780799 NULL NULL ENSG00000237917 ENST00000426526 unprocessed_pseudogene 24086159 24087740 NULL NULL ENSG00000237968 ENST00000422174 processed_pseudogene 22148461 22149738 NULL NULL ENSG00000237997 ENST00000423438 unprocessed_pseudogene 20670463 20670954 NULL NULL ENSG00000238067 ENST00000457961 unprocessed_pseudogene 7539784 7544065 NULL NULL ENSG00000238073 ENST00000440215 protein_coding 9324922 9327689 9324922 9327502 ENSG00000238074 ENST00000446779 protein_coding 9324922 9327689 9324922 9326349 ENSG00000238074 ENST00000454643 unprocessed_pseudogene 21010150 21029166 NULL NULL ENSG00000238088 ENST00000454868 unprocessed_pseudogene 20987993 20991373 NULL NULL ENSG00000238135 ENST00000424401 unprocessed_pseudogene 9027238 9042220 NULL NULL ENSG00000238154 ENST00000435012 unprocessed_pseudogene 19733139 19737712 NULL NULL ENSG00000238191 ENST00000442607 unprocessed_pseudogene 6134634 6137316 NULL NULL ENSG00000238235 ENST00000452889 lincRNA 9748407 9749571 NULL NULL ENSG00000239225 ENST00000419538 processed_pseudogene 27632787 27633469 NULL NULL ENSG00000239304 ENST00000398377 processed_transcript 26356114 26360978 NULL NULL ENSG00000239533 ENST00000516761 miRNA 26356197 26356279 NULL NULL ENSG00000239533 ENST00000439586 processed_pseudogene 7936937 7938764 NULL NULL ENSG00000239893 ENST00000447585 unprocessed_pseudogene 20743949 20790963 NULL NULL ENSG00000240438 ENST00000306641 lincRNA 27629055 27632852 NULL NULL ENSG00000240450 ENST00000432862 processed_pseudogene 26796955 26797681 NULL NULL ENSG00000240566 ENST00000425158 processed_pseudogene 7859028 7859847 NULL NULL ENSG00000241200 ENST00000472227 transcribed_unprocessed_pseudogene 15863536 16027704 NULL NULL ENSG00000241859 ENST00000430079 processed_transcript 15863673 15970474 NULL NULL ENSG00000241859 ENST00000460561 processed_transcript 15864978 15983586 NULL NULL ENSG00000241859 ENST00000451061 transcribed_unprocessed_pseudogene 20835919 20899975 NULL NULL ENSG00000242153 ENST00000432335 processed_transcript 20891768 20901083 NULL NULL ENSG00000242153 ENST00000538268 transcribed_unprocessed_pseudogene 20893577 20901083 NULL NULL ENSG00000242153 ENST00000358944 nonsense_mediated_decay 24049765 24064189 24056368 24062201 ENSG00000242389 ENST00000382659 protein_coding 24049765 24064214 24050043 24062201 ENSG00000242389 ENST00000382673 protein_coding 24026223 24064174 24026501 24062201 ENSG00000242389 ENST00000382658 protein_coding 24049997 24064127 24050043 24062201 ENSG00000242389 ENST00000456659 unprocessed_pseudogene 23670185 23672356 NULL NULL ENSG00000242393 ENST00000485099 misc_RNA 26357107 26357382 NULL NULL ENSG00000242425 ENST00000441091 unprocessed_pseudogene 26325463 26329652 NULL NULL ENSG00000242854 ENST00000383020 protein_coding 23673224 23687672 23675237 23687394 ENSG00000242875 ENST00000382639 nonsense_mediated_decay 23673249 23687672 23675237 23681068 ENSG00000242875 ENST00000437993 unprocessed_pseudogene 6175751 6177628 NULL NULL ENSG00000242879 ENST00000303922 processed_transcript 24455006 24462352 NULL NULL ENSG00000243040 ENST00000420346 transcribed_unprocessed_pseudogene 24457011 24467972 NULL NULL ENSG00000243040 ENST00000450910 unprocessed_pseudogene 9873804 9875984 NULL NULL ENSG00000243643 ENST00000488394 misc_RNA 14394177 14394465 NULL NULL ENSG00000243980 ENST00000422002 processed_pseudogene 25163210 25163968 NULL NULL ENSG00000244000 ENST00000306853 processed_transcript 26329581 26333378 NULL NULL ENSG00000244231 ENST00000451913 processed_pseudogene 7781463 7782131 NULL NULL ENSG00000244246 ENST00000382653 nonsense_mediated_decay 24026223 24040648 24032827 24038660 ENSG00000244395 ENST00000382680 protein_coding 24026223 24040673 24026501 24038660 ENSG00000244395 ENST00000382677 protein_coding 24026223 24038660 24026501 24038660 ENSG00000244395 ENST00000418956 protein_coding 24026455 24040586 24026501 24038660 ENSG00000244395 ENST00000442362 unprocessed_pseudogene 20290496 20298506 NULL NULL ENSG00000244646 ENST00000535771 pseudogene 20297335 20298913 NULL NULL ENSG00000244646 ENST00000514804 transcribed_unprocessed_pseudogene 20952595 20952937 NULL NULL ENSG00000248573 ENST00000509776 unprocessed_pseudogene 26424828 26437493 NULL NULL ENSG00000248792 ENST00000504503 unprocessed_pseudogene 20938165 20941313 NULL NULL ENSG00000249501 ENST00000509650 unprocessed_pseudogene 20817406 20818076 NULL NULL ENSG00000249606 ENST00000511770 unprocessed_pseudogene 20652801 20656181 NULL NULL ENSG00000249634 ENST00000503144 unprocessed_pseudogene 20548860 20551037 NULL NULL ENSG00000249726 ENST00000442790 unprocessed_pseudogene 6111336 6113324 NULL NULL ENSG00000250204 ENST00000510392 unprocessed_pseudogene 19880996 19889280 NULL NULL ENSG00000250868 ENST00000354494 pseudogene 19880862 19882440 NULL NULL ENSG00000250868 ENST00000513521 unprocessed_pseudogene 20702866 20706014 NULL NULL ENSG00000250951 ENST00000506069 unprocessed_pseudogene 6109809 6111670 NULL NULL ENSG00000251275 ENST00000510613 lincRNA 20653626 20709584 NULL NULL ENSG00000251510 ENST00000509611 unprocessed_pseudogene 24041541 24043706 NULL NULL ENSG00000251618 ENST00000515896 rRNA 10037764 10037915 NULL NULL ENSG00000251705 ENST00000515957 rRNA 9928019 9928137 NULL NULL ENSG00000251766 ENST00000515987 snoRNA 28393531 28393668 NULL NULL ENSG00000251796 ENST00000516032 snRNA 2652790 2652894 NULL NULL ENSG00000251841 ENST00000516070 miRNA 5742287 5742379 NULL NULL ENSG00000251879 ENST00000516108 snRNA 26092765 26092918 NULL NULL ENSG00000251917 ENST00000516116 snoRNA 25569246 25569383 NULL NULL ENSG00000251925 ENST00000516144 rRNA 20508009 20508124 NULL NULL ENSG00000251953 ENST00000516157 miRNA 10033981 10034093 NULL NULL ENSG00000251966 ENST00000516161 snRNA 20995615 20995776 NULL NULL ENSG00000251970 ENST00000516187 misc_RNA 7209572 7209683 NULL NULL ENSG00000251996 ENST00000516203 rRNA 19671654 19671769 NULL NULL ENSG00000252012 ENST00000516229 miRNA 19734941 19735035 NULL NULL ENSG00000252038 ENST00000516250 miRNA 5441969 5442060 NULL NULL ENSG00000252059 ENST00000516346 snRNA 7246713 7246820 NULL NULL ENSG00000252155 ENST00000516357 snRNA 20278734 20278893 NULL NULL ENSG00000252166 ENST00000516364 snRNA 18360815 18360921 NULL NULL ENSG00000252173 ENST00000516400 snRNA 20648397 20648558 NULL NULL ENSG00000252209 ENST00000516480 rRNA 9930484 9930602 NULL NULL ENSG00000252289 ENST00000516506 rRNA 19669744 19669856 NULL NULL ENSG00000252315 ENST00000516514 snRNA 18448163 18448269 NULL NULL ENSG00000252323 ENST00000516617 snRNA 27869489 27869642 NULL NULL ENSG00000252426 ENST00000516630 miRNA 20444739 20444833 NULL NULL ENSG00000252439 ENST00000516659 snRNA 4887117 4887307 NULL NULL ENSG00000252468 ENST00000516662 miRNA 27606157 27606239 NULL NULL ENSG00000252471 ENST00000516663 snRNA 7291095 7291199 NULL NULL ENSG00000252472 ENST00000516704 snRNA 19900883 19901042 NULL NULL ENSG00000252513 ENST00000516777 miRNA 14482123 14482230 NULL NULL ENSG00000252586 ENST00000516816 snRNA 28075126 28075289 NULL NULL ENSG00000252625 ENST00000516824 misc_RNA 7192338 7192636 NULL NULL ENSG00000252633 ENST00000516855 miRNA 18174646 18174709 NULL NULL ENSG00000252664 ENST00000516858 rRNA 20509921 20510033 NULL NULL ENSG00000252667 ENST00000516872 snRNA 25887089 25887252 NULL NULL ENSG00000252681 ENST00000516880 snoRNA 18250128 18250259 NULL NULL ENSG00000252689 ENST00000516885 miRNA 15779840 15779936 NULL NULL ENSG00000252694 ENST00000516957 snRNA 21180869 21180973 NULL NULL ENSG00000252766 ENST00000517046 miRNA 13340551 13340633 NULL NULL ENSG00000252855 ENST00000517091 snRNA 4043026 4043131 NULL NULL ENSG00000252900 ENST00000517139 snRNA 28507136 28507239 NULL NULL ENSG00000252948 ENST00000527562 lincRNA 23200175 23206610 NULL NULL ENSG00000254488 ENST00000555130 unprocessed_pseudogene 13462594 13463857 NULL NULL ENSG00000258567 ENST00000557448 unprocessed_pseudogene 13488005 13489271 NULL NULL ENSG00000258991 ENST00000451548 protein_coding 9304564 9307357 9304610 9307170 ENSG00000258992 ENST00000423647 protein_coding 9236076 9307357 9236076 9307170 ENSG00000258992 ENST00000553347 unprocessed_pseudogene 13477233 13478499 NULL NULL ENSG00000259029 ENST00000557360 unprocessed_pseudogene 13470597 13471863 NULL NULL ENSG00000259154 ENST00000558356 unprocessed_pseudogene 24476599 24478647 NULL NULL ENSG00000259247 ENST00000566193 lincRNA 21853827 21856492 NULL NULL ENSG00000260197 ENST00000584011 miRNA 13340359 13340440 NULL NULL ENSG00000263502 ENST00000580394 miRNA 13947443 13947512 NULL NULL ENSG00000265161 ENST00000584045 miRNA 18398127 18398238 NULL NULL ENSG00000265197 ENST00000578366 miRNA 16364065 16364171 NULL NULL ENSG00000266220 ENST00000586015 transcribed_processed_pseudogene 21760074 21760643 NULL NULL ENSG00000267793 ENST00000601700 protein_coding 25847479 25850592 25847479 25850592 ENSG00000267935 ENST00000599485 protein_coding 21737895 21738068 21737895 21738068 ENSG00000269084 ENST00000595988 protein_coding 15418467 15429181 15418467 15429181 ENSG00000269291 ENST00000598545 protein_coding 28111776 28114889 28111776 28114889 ENSG00000269393 ENST00000601705 protein_coding 5306691 5312605 5306691 5312605 ENSG00000269464 ENST00000448518 unprocessed_pseudogene 9345205 9347784 NULL NULL ENSG00000270073 ENST00000605584 processed_pseudogene 13551375 13552752 NULL NULL ENSG00000270242 ENST00000603738 processed_pseudogene 13491303 13493369 NULL NULL ENSG00000270455 ENST00000604436 processed_pseudogene 27809047 27809373 NULL NULL ENSG00000270535 ENST00000603467 processed_pseudogene 13263395 13263563 NULL NULL ENSG00000270570 ENST00000604924 processed_pseudogene 23793569 23793901 NULL NULL ENSG00000271123 ENST00000604370 processed_pseudogene 13263065 13263272 NULL NULL ENSG00000271309 ENST00000605663 processed_pseudogene 13262741 13262939 NULL NULL ENSG00000271365 ENST00000604178 processed_pseudogene 13629403 13629913 NULL NULL ENSG00000271375 ENST00000604289 processed_pseudogene 19576759 19577094 NULL NULL ENSG00000271595 ENST00000606439 misc_RNA 27605054 27605329 NULL NULL ENSG00000272042 ensembldb/inst/chrY/ens_tx2exon.txt0000644000175400017540000037207413175714743020463 0ustar00biocbuildbiocbuildtx_id exon_id exon_idx ENST00000469599 ENSE00001902471 1 ENST00000469599 ENSE00003665408 2 ENST00000469599 ENSE00003572891 3 ENST00000469599 ENSE00003452486 4 ENST00000469599 ENSE00003535737 5 ENST00000469599 ENSE00003306433 6 ENST00000469599 ENSE00003587057 7 ENST00000469599 ENSE00003522786 8 ENST00000469599 ENSE00003674105 9 ENST00000469599 ENSE00003605358 10 ENST00000469599 ENSE00001928834 11 ENST00000469599 ENSE00001954294 12 ENST00000317961 ENSE00001733393 1 ENST00000317961 ENSE00000891759 2 ENST00000317961 ENSE00000652508 3 ENST00000317961 ENSE00000652506 4 ENST00000317961 ENSE00001788914 5 ENST00000317961 ENSE00001805865 6 ENST00000317961 ENSE00000652503 7 ENST00000317961 ENSE00000652502 8 ENST00000317961 ENSE00000652501 9 ENST00000317961 ENSE00001799734 10 ENST00000317961 ENSE00000652498 11 ENST00000317961 ENSE00001786866 12 ENST00000317961 ENSE00003497148 13 ENST00000317961 ENSE00003688313 14 ENST00000317961 ENSE00003664560 15 ENST00000317961 ENSE00003602862 16 ENST00000317961 ENSE00003491684 17 ENST00000317961 ENSE00003488142 18 ENST00000317961 ENSE00003534652 19 ENST00000317961 ENSE00003607600 20 ENST00000317961 ENSE00003544083 21 ENST00000317961 ENSE00003591494 22 ENST00000317961 ENSE00003484526 23 ENST00000317961 ENSE00003539670 24 ENST00000317961 ENSE00001670444 25 ENST00000317961 ENSE00001594027 26 ENST00000317961 ENSE00001945799 27 ENST00000382806 ENSE00001277406 1 ENST00000382806 ENSE00000891759 2 ENST00000382806 ENSE00000652508 3 ENST00000382806 ENSE00000652506 4 ENST00000382806 ENSE00001805865 5 ENST00000382806 ENSE00000652503 6 ENST00000382806 ENSE00000652502 7 ENST00000382806 ENSE00000652501 8 ENST00000382806 ENSE00001799734 9 ENST00000382806 ENSE00000652498 10 ENST00000382806 ENSE00001786866 11 ENST00000382806 ENSE00003497148 12 ENST00000382806 ENSE00003688313 13 ENST00000382806 ENSE00003664560 14 ENST00000382806 ENSE00003602862 15 ENST00000382806 ENSE00003491684 16 ENST00000382806 ENSE00003488142 17 ENST00000382806 ENSE00003534652 18 ENST00000382806 ENSE00003607600 19 ENST00000382806 ENSE00003544083 20 ENST00000382806 ENSE00003591494 21 ENST00000382806 ENSE00003484526 22 ENST00000382806 ENSE00003539670 23 ENST00000382806 ENSE00001670444 24 ENST00000382806 ENSE00001594027 25 ENST00000382806 ENSE00001919342 26 ENST00000492117 ENSE00001946630 1 ENST00000492117 ENSE00003582949 2 ENST00000492117 ENSE00003593440 3 ENST00000492117 ENSE00003665408 4 ENST00000492117 ENSE00001900202 5 ENST00000492117 ENSE00003677957 6 ENST00000492117 ENSE00003607967 7 ENST00000492117 ENSE00003535737 8 ENST00000492117 ENSE00003484073 9 ENST00000492117 ENSE00003587057 10 ENST00000492117 ENSE00003522786 11 ENST00000492117 ENSE00003674105 12 ENST00000492117 ENSE00003605358 13 ENST00000492117 ENSE00001928834 14 ENST00000492117 ENSE00001941473 15 ENST00000440077 ENSE00001733393 1 ENST00000440077 ENSE00000891759 2 ENST00000440077 ENSE00000652508 3 ENST00000440077 ENSE00001788914 4 ENST00000440077 ENSE00001805865 5 ENST00000440077 ENSE00000652503 6 ENST00000440077 ENSE00000652502 7 ENST00000440077 ENSE00000652501 8 ENST00000440077 ENSE00001799734 9 ENST00000440077 ENSE00000652498 10 ENST00000440077 ENSE00001786866 11 ENST00000440077 ENSE00003497148 12 ENST00000440077 ENSE00003688313 13 ENST00000440077 ENSE00003664560 14 ENST00000440077 ENSE00003602862 15 ENST00000440077 ENSE00003491684 16 ENST00000440077 ENSE00003488142 17 ENST00000440077 ENSE00003534652 18 ENST00000440077 ENSE00003607600 19 ENST00000440077 ENSE00003544083 20 ENST00000440077 ENSE00003591494 21 ENST00000440077 ENSE00003484526 22 ENST00000440077 ENSE00003539670 23 ENST00000440077 ENSE00001670444 24 ENST00000440077 ENSE00001594027 25 ENST00000440077 ENSE00001741626 26 ENST00000415360 ENSE00001692290 1 ENST00000415360 ENSE00001803510 2 ENST00000415360 ENSE00003484526 3 ENST00000415360 ENSE00001658853 4 ENST00000485154 ENSE00001849878 1 ENST00000485154 ENSE00001940004 2 ENST00000478891 ENSE00001928223 1 ENST00000478891 ENSE00003572891 2 ENST00000478891 ENSE00001930174 3 ENST00000447300 ENSE00001685428 1 ENST00000447300 ENSE00000891759 2 ENST00000447300 ENSE00000652508 3 ENST00000447300 ENSE00000652506 4 ENST00000447300 ENSE00001788914 5 ENST00000447300 ENSE00000652503 6 ENST00000447300 ENSE00000652502 7 ENST00000447300 ENSE00000652501 8 ENST00000447300 ENSE00001799734 9 ENST00000447300 ENSE00000652498 10 ENST00000447300 ENSE00001652491 11 ENST00000541639 ENSE00002279676 1 ENST00000541639 ENSE00000891759 2 ENST00000541639 ENSE00000652508 3 ENST00000541639 ENSE00000652506 4 ENST00000541639 ENSE00001788914 5 ENST00000541639 ENSE00001805865 6 ENST00000541639 ENSE00000652503 7 ENST00000541639 ENSE00000652502 8 ENST00000541639 ENSE00000652501 9 ENST00000541639 ENSE00001799734 10 ENST00000541639 ENSE00000652498 11 ENST00000541639 ENSE00002207746 12 ENST00000541639 ENSE00001786866 13 ENST00000541639 ENSE00003497148 14 ENST00000541639 ENSE00003688313 15 ENST00000541639 ENSE00003664560 16 ENST00000541639 ENSE00003602862 17 ENST00000541639 ENSE00003491684 18 ENST00000541639 ENSE00003488142 19 ENST00000541639 ENSE00003534652 20 ENST00000541639 ENSE00003607600 21 ENST00000541639 ENSE00003544083 22 ENST00000541639 ENSE00003591494 23 ENST00000541639 ENSE00003484526 24 ENST00000541639 ENSE00003539670 25 ENST00000541639 ENSE00001670444 26 ENST00000541639 ENSE00001594027 27 ENST00000541639 ENSE00002285913 28 ENST00000360160 ENSE00001402535 1 ENST00000360160 ENSE00001403038 2 ENST00000360160 ENSE00003463722 3 ENST00000360160 ENSE00001605860 4 ENST00000360160 ENSE00000862006 5 ENST00000360160 ENSE00000773394 6 ENST00000360160 ENSE00003574309 7 ENST00000360160 ENSE00003652139 8 ENST00000360160 ENSE00003536211 9 ENST00000360160 ENSE00001614446 10 ENST00000360160 ENSE00001746396 11 ENST00000360160 ENSE00000773388 12 ENST00000360160 ENSE00003534942 13 ENST00000360160 ENSE00000773386 14 ENST00000360160 ENSE00001703401 15 ENST00000360160 ENSE00001729063 16 ENST00000360160 ENSE00001722940 17 ENST00000360160 ENSE00001928277 18 ENST00000454054 ENSE00001685858 1 ENST00000454054 ENSE00001350052 2 ENST00000454054 ENSE00003463722 3 ENST00000454054 ENSE00001605860 4 ENST00000454054 ENSE00000862006 5 ENST00000454054 ENSE00000773394 6 ENST00000454054 ENSE00003574309 7 ENST00000454054 ENSE00003656145 8 ENST00000336079 ENSE00001832940 1 ENST00000336079 ENSE00003463722 2 ENST00000336079 ENSE00001605860 3 ENST00000336079 ENSE00000862006 4 ENST00000336079 ENSE00000773394 5 ENST00000336079 ENSE00003574309 6 ENST00000336079 ENSE00003652139 7 ENST00000336079 ENSE00003536211 8 ENST00000336079 ENSE00001614446 9 ENST00000336079 ENSE00001746396 10 ENST00000336079 ENSE00000773388 11 ENST00000336079 ENSE00003534942 12 ENST00000336079 ENSE00000773386 13 ENST00000336079 ENSE00001703401 14 ENST00000336079 ENSE00001729063 15 ENST00000336079 ENSE00001722940 16 ENST00000336079 ENSE00001352037 17 ENST00000493363 ENSE00001826669 1 ENST00000493363 ENSE00003643575 2 ENST00000493363 ENSE00001906809 3 ENST00000440554 ENSE00001797666 1 ENST00000440554 ENSE00003463722 2 ENST00000440554 ENSE00001605860 3 ENST00000440554 ENSE00000862006 4 ENST00000440554 ENSE00000773394 5 ENST00000440554 ENSE00003574309 6 ENST00000440554 ENSE00003652139 7 ENST00000440554 ENSE00003670172 8 ENST00000469101 ENSE00001937992 1 ENST00000469101 ENSE00001848230 2 ENST00000472510 ENSE00003512200 1 ENST00000472510 ENSE00003537802 2 ENST00000472510 ENSE00001948256 3 ENST00000463199 ENSE00001935991 1 ENST00000463199 ENSE00003537802 2 ENST00000463199 ENSE00003534699 3 ENST00000463199 ENSE00001893350 4 ENST00000495478 ENSE00001811040 1 ENST00000495478 ENSE00003693954 2 ENST00000495478 ENSE00001922429 3 ENST00000383052 ENSE00001803243 1 ENST00000383052 ENSE00002223884 2 ENST00000383052 ENSE00003645989 3 ENST00000383052 ENSE00003548678 4 ENST00000383052 ENSE00003611496 5 ENST00000383052 ENSE00001649504 6 ENST00000383052 ENSE00001777381 7 ENST00000383052 ENSE00001494540 8 ENST00000469869 ENSE00001857352 1 ENST00000469869 ENSE00003626126 2 ENST00000469869 ENSE00003631374 3 ENST00000469869 ENSE00001955114 4 ENST00000443793 ENSE00001334555 1 ENST00000443793 ENSE00002223884 2 ENST00000443793 ENSE00001597745 3 ENST00000478783 ENSE00001900413 1 ENST00000478783 ENSE00001880607 2 ENST00000431102 ENSE00001746216 1 ENST00000431102 ENSE00002223884 2 ENST00000431102 ENSE00003548678 3 ENST00000431102 ENSE00003611496 4 ENST00000431102 ENSE00001649504 5 ENST00000431102 ENSE00001777381 6 ENST00000431102 ENSE00001368923 7 ENST00000155093 ENSE00001648585 1 ENST00000155093 ENSE00002223884 2 ENST00000155093 ENSE00003645989 3 ENST00000155093 ENSE00003548678 4 ENST00000155093 ENSE00003611496 5 ENST00000155093 ENSE00001649504 6 ENST00000155093 ENSE00001777381 7 ENST00000155093 ENSE00001368923 8 ENST00000449237 ENSE00001648585 1 ENST00000449237 ENSE00003604519 2 ENST00000449237 ENSE00003548678 3 ENST00000449237 ENSE00003611496 4 ENST00000449237 ENSE00001777381 5 ENST00000449237 ENSE00001368923 6 ENST00000383032 ENSE00001408731 1 ENST00000383032 ENSE00001494437 2 ENST00000383032 ENSE00001494434 3 ENST00000383032 ENSE00001494433 4 ENST00000383032 ENSE00001494431 5 ENST00000383032 ENSE00001793373 6 ENST00000383032 ENSE00003432678 7 ENST00000383032 ENSE00003437631 8 ENST00000383032 ENSE00003379331 9 ENST00000383032 ENSE00001213593 10 ENST00000383032 ENSE00001607530 11 ENST00000383032 ENSE00001716749 12 ENST00000383032 ENSE00001744765 13 ENST00000383032 ENSE00001731081 14 ENST00000383032 ENSE00001654905 15 ENST00000383032 ENSE00001729171 16 ENST00000383032 ENSE00001763966 17 ENST00000383032 ENSE00001593786 18 ENST00000383032 ENSE00001370395 19 ENST00000355162 ENSE00001408731 1 ENST00000355162 ENSE00001494437 2 ENST00000355162 ENSE00001494433 3 ENST00000355162 ENSE00001494431 4 ENST00000355162 ENSE00001793373 5 ENST00000355162 ENSE00003432678 6 ENST00000355162 ENSE00003437631 7 ENST00000355162 ENSE00003379331 8 ENST00000355162 ENSE00001213593 9 ENST00000355162 ENSE00001607530 10 ENST00000355162 ENSE00001716749 11 ENST00000355162 ENSE00001744765 12 ENST00000355162 ENSE00001731081 13 ENST00000355162 ENSE00001654905 14 ENST00000355162 ENSE00001729171 15 ENST00000355162 ENSE00001763966 16 ENST00000355162 ENSE00001593786 17 ENST00000355162 ENSE00001370395 18 ENST00000346432 ENSE00001408731 1 ENST00000346432 ENSE00001494437 2 ENST00000346432 ENSE00001494434 3 ENST00000346432 ENSE00001494431 4 ENST00000346432 ENSE00001793373 5 ENST00000346432 ENSE00003432678 6 ENST00000346432 ENSE00003437631 7 ENST00000346432 ENSE00003379331 8 ENST00000346432 ENSE00001213593 9 ENST00000346432 ENSE00001607530 10 ENST00000346432 ENSE00001716749 11 ENST00000346432 ENSE00001744765 12 ENST00000346432 ENSE00001731081 13 ENST00000346432 ENSE00001654905 14 ENST00000346432 ENSE00001729171 15 ENST00000346432 ENSE00001763966 16 ENST00000346432 ENSE00001593786 17 ENST00000346432 ENSE00001370395 18 ENST00000333703 ENSE00001631277 1 ENST00000333703 ENSE00001619635 2 ENST00000333703 ENSE00001755808 3 ENST00000333703 ENSE00000981568 4 ENST00000333703 ENSE00001640924 5 ENST00000333703 ENSE00001602875 6 ENST00000362095 ENSE00001350198 1 ENST00000362095 ENSE00001640924 2 ENST00000362095 ENSE00001944263 3 ENST00000400457 ENSE00000981568 1 ENST00000400457 ENSE00001640924 2 ENST00000400457 ENSE00001803775 3 ENST00000400457 ENSE00001677522 4 ENST00000400457 ENSE00001322750 5 ENST00000215473 ENSE00001436852 1 ENST00000215473 ENSE00001640924 2 ENST00000215473 ENSE00001803775 3 ENST00000215473 ENSE00001731866 4 ENST00000215473 ENSE00001711324 5 ENST00000215473 ENSE00001779807 6 ENST00000215479 ENSE00001348274 1 ENST00000215479 ENSE00001671586 2 ENST00000215479 ENSE00001645681 3 ENST00000215479 ENSE00000652250 4 ENST00000215479 ENSE00001667251 5 ENST00000215479 ENSE00001494454 6 ENST00000383036 ENSE00001494452 1 ENST00000383036 ENSE00001645681 2 ENST00000383036 ENSE00001651085 3 ENST00000383036 ENSE00000652250 4 ENST00000383036 ENSE00001667251 5 ENST00000383036 ENSE00001727000 6 ENST00000383037 ENSE00001494452 1 ENST00000383037 ENSE00001645681 2 ENST00000383037 ENSE00001651085 3 ENST00000383037 ENSE00000652250 4 ENST00000383037 ENSE00001667251 5 ENST00000528056 ENSE00002300179 1 ENST00000528056 ENSE00003518103 2 ENST00000528056 ENSE00003489469 3 ENST00000528056 ENSE00003507474 4 ENST00000528056 ENSE00003502780 5 ENST00000528056 ENSE00002194667 6 ENST00000528056 ENSE00001494358 7 ENST00000528056 ENSE00001494356 8 ENST00000533551 ENSE00002183990 1 ENST00000533551 ENSE00003518103 2 ENST00000533551 ENSE00003489469 3 ENST00000533551 ENSE00003507474 4 ENST00000533551 ENSE00003502780 5 ENST00000533551 ENSE00002194667 6 ENST00000533551 ENSE00002194098 7 ENST00000495163 ENSE00001877035 1 ENST00000495163 ENSE00001918349 2 ENST00000472666 ENSE00001948825 1 ENST00000472666 ENSE00003507474 2 ENST00000472666 ENSE00001928357 3 ENST00000362758 ENSE00002210406 1 ENST00000362758 ENSE00003574133 2 ENST00000362758 ENSE00003534383 3 ENST00000362758 ENSE00003600341 4 ENST00000362758 ENSE00003520510 5 ENST00000362758 ENSE00001661914 6 ENST00000338981 ENSE00001020131 1 ENST00000338981 ENSE00001020125 2 ENST00000338981 ENSE00003651478 3 ENST00000338981 ENSE00003476271 4 ENST00000338981 ENSE00003602419 5 ENST00000338981 ENSE00003467347 6 ENST00000338981 ENSE00003693194 7 ENST00000338981 ENSE00003654508 8 ENST00000338981 ENSE00003550081 9 ENST00000338981 ENSE00003624888 10 ENST00000338981 ENSE00003487242 11 ENST00000338981 ENSE00003601630 12 ENST00000338981 ENSE00003666147 13 ENST00000338981 ENSE00003566318 14 ENST00000338981 ENSE00003557039 15 ENST00000338981 ENSE00003515132 16 ENST00000338981 ENSE00003621719 17 ENST00000338981 ENSE00003555621 18 ENST00000338981 ENSE00003655936 19 ENST00000338981 ENSE00003476364 20 ENST00000338981 ENSE00003510955 21 ENST00000338981 ENSE00003621863 22 ENST00000338981 ENSE00003560948 23 ENST00000338981 ENSE00003561084 24 ENST00000338981 ENSE00003508322 25 ENST00000338981 ENSE00003664000 26 ENST00000338981 ENSE00003547650 27 ENST00000338981 ENSE00003694071 28 ENST00000338981 ENSE00003679141 29 ENST00000338981 ENSE00003652645 30 ENST00000338981 ENSE00003564733 31 ENST00000338981 ENSE00003681535 32 ENST00000338981 ENSE00003669946 33 ENST00000338981 ENSE00003585886 34 ENST00000338981 ENSE00003635310 35 ENST00000338981 ENSE00003552773 36 ENST00000338981 ENSE00003548868 37 ENST00000338981 ENSE00001601104 38 ENST00000338981 ENSE00003586868 39 ENST00000338981 ENSE00003686311 40 ENST00000338981 ENSE00003476240 41 ENST00000338981 ENSE00003513236 42 ENST00000338981 ENSE00003654441 43 ENST00000338981 ENSE00003686907 44 ENST00000338981 ENSE00003595540 45 ENST00000338981 ENSE00003502466 46 ENST00000493168 ENSE00001869747 1 ENST00000493168 ENSE00003574267 2 ENST00000493168 ENSE00001853448 3 ENST00000426564 ENSE00001952418 1 ENST00000426564 ENSE00003642330 2 ENST00000426564 ENSE00003608903 3 ENST00000426564 ENSE00003569874 4 ENST00000426564 ENSE00003525307 5 ENST00000426564 ENSE00003468269 6 ENST00000426564 ENSE00003668411 7 ENST00000426564 ENSE00003544199 8 ENST00000426564 ENSE00003543968 9 ENST00000426564 ENSE00003678761 10 ENST00000426564 ENSE00003522394 11 ENST00000426564 ENSE00003556397 12 ENST00000426564 ENSE00003484639 13 ENST00000426564 ENSE00003494702 14 ENST00000426564 ENSE00003664430 15 ENST00000426564 ENSE00003545466 16 ENST00000426564 ENSE00003634092 17 ENST00000426564 ENSE00003562091 18 ENST00000426564 ENSE00003499612 19 ENST00000426564 ENSE00003612302 20 ENST00000426564 ENSE00003510705 21 ENST00000426564 ENSE00003494757 22 ENST00000426564 ENSE00003626016 23 ENST00000426564 ENSE00003624705 24 ENST00000426564 ENSE00003646476 25 ENST00000426564 ENSE00003683748 26 ENST00000426564 ENSE00003522502 27 ENST00000426564 ENSE00003692063 28 ENST00000426564 ENSE00003612215 29 ENST00000426564 ENSE00003491362 30 ENST00000426564 ENSE00003599293 31 ENST00000426564 ENSE00003548985 32 ENST00000426564 ENSE00003477744 33 ENST00000426564 ENSE00003471770 34 ENST00000426564 ENSE00003654551 35 ENST00000426564 ENSE00001841790 36 ENST00000426564 ENSE00003628831 37 ENST00000426564 ENSE00003640718 38 ENST00000426564 ENSE00003536017 39 ENST00000426564 ENSE00003664007 40 ENST00000426564 ENSE00003650241 41 ENST00000426564 ENSE00003632911 42 ENST00000426564 ENSE00003662966 43 ENST00000426564 ENSE00003580686 44 ENST00000453031 ENSE00001595780 1 ENST00000453031 ENSE00003654441 2 ENST00000453031 ENSE00003686907 3 ENST00000453031 ENSE00003595540 4 ENST00000453031 ENSE00001746916 5 ENST00000471409 ENSE00001944130 1 ENST00000471409 ENSE00003580686 2 ENST00000250776 ENSE00001756639 1 ENST00000250776 ENSE00001663636 2 ENST00000250776 ENSE00001595449 3 ENST00000250776 ENSE00001634261 4 ENST00000250776 ENSE00001767444 5 ENST00000250784 ENSE00002490412 1 ENST00000250784 ENSE00001709586 2 ENST00000250784 ENSE00001738202 3 ENST00000250784 ENSE00001602849 4 ENST00000250784 ENSE00001601989 5 ENST00000250784 ENSE00003667463 6 ENST00000250784 ENSE00003636667 7 ENST00000430575 ENSE00001732508 1 ENST00000430575 ENSE00001709586 2 ENST00000430575 ENSE00001738202 3 ENST00000430575 ENSE00001602849 4 ENST00000430575 ENSE00001601989 5 ENST00000430575 ENSE00003667463 6 ENST00000430575 ENSE00001635459 7 ENST00000477725 ENSE00001859961 1 ENST00000477725 ENSE00003469154 2 ENST00000477725 ENSE00003654930 3 ENST00000515575 ENSE00002062109 1 ENST00000515575 ENSE00002034437 2 ENST00000515575 ENSE00002072199 3 ENST00000250805 ENSE00001782128 1 ENST00000250805 ENSE00001664883 2 ENST00000250805 ENSE00001800396 3 ENST00000250805 ENSE00001771159 4 ENST00000250805 ENSE00001609985 5 ENST00000250823 ENSE00001914170 1 ENST00000250823 ENSE00001617113 2 ENST00000250825 ENSE00001940528 1 ENST00000250825 ENSE00001622417 2 ENST00000382867 ENSE00002314376 1 ENST00000544303 ENSE00002282227 1 ENST00000544303 ENSE00002227312 2 ENST00000544303 ENSE00002265258 3 ENST00000407724 ENSE00002810788 1 ENST00000407724 ENSE00002783311 2 ENST00000407724 ENSE00002873804 3 ENST00000407724 ENSE00002825272 4 ENST00000407724 ENSE00001893165 5 ENST00000459719 ENSE00001826433 1 ENST00000459719 ENSE00002783311 2 ENST00000459719 ENSE00001875276 3 ENST00000459719 ENSE00002811240 4 ENST00000447520 ENSE00002957208 1 ENST00000447520 ENSE00002783311 2 ENST00000447520 ENSE00002829137 3 ENST00000447520 ENSE00002862473 4 ENST00000445715 ENSE00002957208 1 ENST00000445715 ENSE00002783311 2 ENST00000445715 ENSE00002829137 3 ENST00000445715 ENSE00002862473 4 ENST00000445715 ENSE00002920932 5 ENST00000445715 ENSE00001657009 6 ENST00000445715 ENSE00001617655 7 ENST00000445715 ENSE00001663997 8 ENST00000445715 ENSE00003585093 9 ENST00000445715 ENSE00003676904 10 ENST00000445715 ENSE00001621570 11 ENST00000538014 ENSE00002224044 1 ENST00000538014 ENSE00002265061 2 ENST00000538014 ENSE00002783311 3 ENST00000538014 ENSE00002256441 4 ENST00000447202 ENSE00001793723 1 ENST00000447202 ENSE00001687078 2 ENST00000588613 ENSE00002916216 1 ENST00000588613 ENSE00002829137 2 ENST00000588613 ENSE00002920932 3 ENST00000588613 ENSE00002875419 4 ENST00000589075 ENSE00002833019 1 ENST00000589075 ENSE00002829137 2 ENST00000589075 ENSE00002905816 3 ENST00000585549 ENSE00002863993 1 ENST00000585549 ENSE00002829137 2 ENST00000585549 ENSE00002757214 3 ENST00000585549 ENSE00002783490 4 ENST00000587095 ENSE00002932169 1 ENST00000587095 ENSE00002829137 2 ENST00000587095 ENSE00002783490 3 ENST00000488280 ENSE00001950956 1 ENST00000488280 ENSE00002920932 2 ENST00000488280 ENSE00001930064 3 ENST00000253320 ENSE00001279198 1 ENST00000253320 ENSE00001279210 2 ENST00000253320 ENSE00003585093 3 ENST00000253320 ENSE00003676904 4 ENST00000253320 ENSE00001035195 5 ENST00000593000 ENSE00002958230 1 ENST00000592697 ENSE00002880368 1 ENST00000592697 ENSE00002922995 2 ENST00000592697 ENSE00003585093 3 ENST00000592697 ENSE00003676904 4 ENST00000592697 ENSE00002745809 5 ENST00000251749 ENSE00001035136 1 ENST00000251749 ENSE00000891756 2 ENST00000251749 ENSE00001281659 3 ENST00000251749 ENSE00000981692 4 ENST00000251749 ENSE00001281628 5 ENST00000251749 ENSE00002836144 6 ENST00000382832 ENSE00001542537 1 ENST00000382832 ENSE00003664473 2 ENST00000382832 ENSE00003581743 3 ENST00000382832 ENSE00001493485 4 ENST00000433794 ENSE00001668181 1 ENST00000433794 ENSE00003505404 2 ENST00000433794 ENSE00001757235 3 ENST00000433794 ENSE00003519096 4 ENST00000433794 ENSE00003627127 5 ENST00000545582 ENSE00002217996 1 ENST00000545582 ENSE00001757235 2 ENST00000545582 ENSE00003529279 3 ENST00000545582 ENSE00003568887 4 ENST00000253838 ENSE00001785382 1 ENST00000253838 ENSE00003499302 2 ENST00000253838 ENSE00001693495 3 ENST00000538537 ENSE00002290871 1 ENST00000538537 ENSE00003596079 2 ENST00000538537 ENSE00002214070 3 ENST00000538537 ENSE00002310424 4 ENST00000253848 ENSE00001917099 1 ENST00000253848 ENSE00003687937 2 ENST00000253848 ENSE00001937237 3 ENST00000545808 ENSE00002299728 1 ENST00000545808 ENSE00003671276 2 ENST00000545808 ENSE00002277139 3 ENST00000545808 ENSE00002209602 4 ENST00000457100 ENSE00001799711 1 ENST00000457100 ENSE00001638328 2 ENST00000457100 ENSE00001698649 3 ENST00000457100 ENSE00001648830 4 ENST00000457100 ENSE00001726416 5 ENST00000457100 ENSE00001799620 6 ENST00000276770 ENSE00001799711 1 ENST00000276770 ENSE00001638328 2 ENST00000276770 ENSE00001698649 3 ENST00000276770 ENSE00001648830 4 ENST00000276770 ENSE00001726416 5 ENST00000276770 ENSE00001594918 6 ENST00000276770 ENSE00001799620 7 ENST00000449828 ENSE00001682908 1 ENST00000449828 ENSE00001619344 2 ENST00000449828 ENSE00001799620 3 ENST00000447655 ENSE00001729695 1 ENST00000447655 ENSE00001805126 2 ENST00000447655 ENSE00001633857 3 ENST00000276779 ENSE00001692562 1 ENST00000276779 ENSE00001658267 2 ENST00000276779 ENSE00001691944 3 ENST00000276779 ENSE00001628673 4 ENST00000276779 ENSE00001700737 5 ENST00000276779 ENSE00001717109 6 ENST00000276779 ENSE00001633857 7 ENST00000415405 ENSE00001692562 1 ENST00000415405 ENSE00001658267 2 ENST00000415405 ENSE00001691944 3 ENST00000415405 ENSE00001628673 4 ENST00000415405 ENSE00001700737 5 ENST00000415405 ENSE00001633857 6 ENST00000284856 ENSE00001016870 1 ENST00000284856 ENSE00001274354 2 ENST00000288666 ENSE00001923202 1 ENST00000288666 ENSE00001677561 2 ENST00000288666 ENSE00001680575 3 ENST00000288666 ENSE00001638361 4 ENST00000288666 ENSE00001725100 5 ENST00000288666 ENSE00001734476 6 ENST00000288666 ENSE00001159425 7 ENST00000471252 ENSE00001867079 1 ENST00000471252 ENSE00001832496 2 ENST00000382872 ENSE00001420613 1 ENST00000382872 ENSE00003548219 2 ENST00000382872 ENSE00003542397 3 ENST00000382872 ENSE00003537524 4 ENST00000382872 ENSE00003686712 5 ENST00000382872 ENSE00001424034 6 ENST00000355905 ENSE00001493621 1 ENST00000355905 ENSE00003620397 2 ENST00000355905 ENSE00003691073 3 ENST00000355905 ENSE00003537524 4 ENST00000355905 ENSE00003686712 5 ENST00000355905 ENSE00003601036 6 ENST00000382868 ENSE00001493621 1 ENST00000382868 ENSE00003620397 2 ENST00000382868 ENSE00003554354 3 ENST00000382868 ENSE00003691073 4 ENST00000382868 ENSE00003477208 5 ENST00000382868 ENSE00003537524 6 ENST00000382868 ENSE00003686712 7 ENST00000382868 ENSE00003601036 8 ENST00000476359 ENSE00001493621 1 ENST00000476359 ENSE00003610714 2 ENST00000476359 ENSE00003548219 3 ENST00000476359 ENSE00003537517 4 ENST00000476359 ENSE00003613876 5 ENST00000476359 ENSE00001738756 6 ENST00000476359 ENSE00003625704 7 ENST00000476359 ENSE00003593743 8 ENST00000476359 ENSE00003665738 9 ENST00000481089 ENSE00001955812 1 ENST00000481089 ENSE00001955997 2 ENST00000339174 ENSE00001368742 1 ENST00000339174 ENSE00001390456 2 ENST00000339174 ENSE00003691073 3 ENST00000339174 ENSE00003537524 4 ENST00000339174 ENSE00003686712 5 ENST00000339174 ENSE00001868567 6 ENST00000413217 ENSE00001493617 1 ENST00000413217 ENSE00003554354 2 ENST00000413217 ENSE00003691073 3 ENST00000413217 ENSE00001612473 4 ENST00000297967 ENSE00003620397 1 ENST00000297967 ENSE00003554354 2 ENST00000297967 ENSE00003691073 3 ENST00000297967 ENSE00001612473 4 ENST00000320701 ENSE00001707785 1 ENST00000320701 ENSE00003546295 2 ENST00000320701 ENSE00001623435 3 ENST00000320701 ENSE00001642228 4 ENST00000320701 ENSE00003563383 5 ENST00000320701 ENSE00001830098 6 ENST00000383042 ENSE00003503096 1 ENST00000383042 ENSE00003546295 2 ENST00000383042 ENSE00001623435 3 ENST00000383042 ENSE00001642228 4 ENST00000383042 ENSE00001618514 5 ENST00000383042 ENSE00001687266 6 ENST00000470569 ENSE00003465137 1 ENST00000470569 ENSE00003510285 2 ENST00000470569 ENSE00001885391 3 ENST00000470569 ENSE00001950610 4 ENST00000464674 ENSE00001851117 1 ENST00000464674 ENSE00003591129 2 ENST00000464674 ENSE00001858368 3 ENST00000343584 ENSE00001902634 1 ENST00000343584 ENSE00003696150 2 ENST00000343584 ENSE00001591394 3 ENST00000607210 ENSE00003701041 1 ENST00000607210 ENSE00003696150 2 ENST00000607210 ENSE00003695877 3 ENST00000303593 ENSE00001786049 1 ENST00000303593 ENSE00003695050 2 ENST00000303593 ENSE00001644491 3 ENST00000303728 ENSE00001686003 1 ENST00000303728 ENSE00001657597 2 ENST00000303728 ENSE00003636240 3 ENST00000303728 ENSE00003502664 4 ENST00000303728 ENSE00003502641 5 ENST00000477123 ENSE00001686003 1 ENST00000477123 ENSE00001657597 2 ENST00000477123 ENSE00003636240 3 ENST00000477123 ENSE00003502664 4 ENST00000477123 ENSE00001876694 5 ENST00000477123 ENSE00003543250 6 ENST00000338793 ENSE00001686003 1 ENST00000338793 ENSE00001657597 2 ENST00000338793 ENSE00003636240 3 ENST00000338793 ENSE00003502664 4 ENST00000338793 ENSE00001624902 5 ENST00000303766 ENSE00001703126 1 ENST00000303766 ENSE00003469687 2 ENST00000303766 ENSE00003536546 3 ENST00000303766 ENSE00001739138 4 ENST00000303766 ENSE00003679115 5 ENST00000303766 ENSE00003668781 6 ENST00000303766 ENSE00003531954 7 ENST00000303766 ENSE00003661928 8 ENST00000303766 ENSE00003557303 9 ENST00000303766 ENSE00003568885 10 ENST00000303766 ENSE00003638296 11 ENST00000303766 ENSE00003580283 12 ENST00000481858 ENSE00001816306 1 ENST00000481858 ENSE00003562722 2 ENST00000481858 ENSE00003591193 3 ENST00000481858 ENSE00003636020 4 ENST00000481858 ENSE00003530779 5 ENST00000481858 ENSE00003638449 6 ENST00000481858 ENSE00003576126 7 ENST00000481858 ENSE00003480178 8 ENST00000481858 ENSE00003687067 9 ENST00000481858 ENSE00003468889 10 ENST00000481858 ENSE00003578044 11 ENST00000454978 ENSE00001765593 1 ENST00000454978 ENSE00003469687 2 ENST00000454978 ENSE00003536546 3 ENST00000454978 ENSE00001739138 4 ENST00000454978 ENSE00003679115 5 ENST00000454978 ENSE00003668781 6 ENST00000454978 ENSE00003531954 7 ENST00000454978 ENSE00003661928 8 ENST00000454978 ENSE00003557303 9 ENST00000454978 ENSE00003638296 10 ENST00000454978 ENSE00003580283 11 ENST00000303804 ENSE00001625881 1 ENST00000303804 ENSE00001682815 2 ENST00000303804 ENSE00003673462 3 ENST00000303804 ENSE00003492436 4 ENST00000303804 ENSE00003573636 5 ENST00000472391 ENSE00001625881 1 ENST00000472391 ENSE00001682815 2 ENST00000472391 ENSE00003673462 3 ENST00000472391 ENSE00003492436 4 ENST00000472391 ENSE00001899711 5 ENST00000472391 ENSE00003488975 6 ENST00000341740 ENSE00001625881 1 ENST00000341740 ENSE00001682815 2 ENST00000341740 ENSE00003673462 3 ENST00000341740 ENSE00003492436 4 ENST00000341740 ENSE00001628640 5 ENST00000382759 ENSE00003525363 1 ENST00000382759 ENSE00003550074 2 ENST00000382759 ENSE00003651701 3 ENST00000382759 ENSE00003567644 4 ENST00000382759 ENSE00003490701 5 ENST00000382759 ENSE00003662908 6 ENST00000382759 ENSE00001594909 7 ENST00000382759 ENSE00003642058 8 ENST00000382759 ENSE00003574473 9 ENST00000382759 ENSE00003635823 10 ENST00000326985 ENSE00003480955 1 ENST00000326985 ENSE00003658768 2 ENST00000326985 ENSE00003532851 3 ENST00000326985 ENSE00003665479 4 ENST00000326985 ENSE00003491376 5 ENST00000326985 ENSE00003537055 6 ENST00000326985 ENSE00001657501 7 ENST00000426043 ENSE00001596885 1 ENST00000426043 ENSE00003537055 2 ENST00000426043 ENSE00003604831 3 ENST00000426043 ENSE00003477338 4 ENST00000426043 ENSE00003512248 5 ENST00000303979 ENSE00001611088 1 ENST00000303979 ENSE00001715185 2 ENST00000303979 ENSE00001657254 3 ENST00000303979 ENSE00001645729 4 ENST00000303979 ENSE00001802624 5 ENST00000303979 ENSE00001543685 6 ENST00000344884 ENSE00003670797 1 ENST00000344884 ENSE00003588065 2 ENST00000491902 ENSE00003662804 1 ENST00000491902 ENSE00003613429 2 ENST00000491902 ENSE00001899520 3 ENST00000491902 ENSE00001698194 4 ENST00000491902 ENSE00001803454 5 ENST00000491902 ENSE00003604288 6 ENST00000382852 ENSE00001597600 1 ENST00000382852 ENSE00003535599 2 ENST00000382852 ENSE00001493553 3 ENST00000304790 ENSE00001674814 1 ENST00000304790 ENSE00001858694 2 ENST00000505047 ENSE00002036080 1 ENST00000505047 ENSE00002085962 2 ENST00000505047 ENSE00002062695 3 ENST00000505047 ENSE00002046872 4 ENST00000505047 ENSE00002035366 5 ENST00000306589 ENSE00001900148 1 ENST00000306589 ENSE00003701812 2 ENST00000306589 ENSE00001781602 3 ENST00000338673 ENSE00001665399 1 ENST00000338673 ENSE00003700592 2 ENST00000338673 ENSE00001707150 3 ENST00000306609 ENSE00001854309 1 ENST00000306609 ENSE00001666303 2 ENST00000361963 ENSE00001436475 1 ENST00000333235 ENSE00001786020 1 ENST00000333235 ENSE00001735399 2 ENST00000539489 ENSE00003506820 1 ENST00000539489 ENSE00003604808 2 ENST00000416946 ENSE00001668733 1 ENST00000416946 ENSE00001679890 2 ENST00000416946 ENSE00001610203 3 ENST00000416946 ENSE00003589912 4 ENST00000416946 ENSE00001637486 5 ENST00000416946 ENSE00001798553 6 ENST00000416946 ENSE00001752493 7 ENST00000416946 ENSE00003654675 8 ENST00000416946 ENSE00003649198 9 ENST00000416946 ENSE00003496796 10 ENST00000416946 ENSE00003547203 11 ENST00000416946 ENSE00001716410 12 ENST00000416946 ENSE00001635424 13 ENST00000416946 ENSE00001555256 14 ENST00000306667 ENSE00002286560 1 ENST00000306667 ENSE00001610203 2 ENST00000306667 ENSE00003553650 3 ENST00000306667 ENSE00002324147 4 ENST00000306667 ENSE00003604497 5 ENST00000306667 ENSE00003480675 6 ENST00000306667 ENSE00003621244 7 ENST00000306667 ENSE00003668556 8 ENST00000306667 ENSE00001795579 9 ENST00000423852 ENSE00001629437 1 ENST00000423852 ENSE00001719001 2 ENST00000423852 ENSE00001728235 3 ENST00000423852 ENSE00001708482 4 ENST00000423852 ENSE00001598676 5 ENST00000423852 ENSE00003608732 6 ENST00000423852 ENSE00003588397 7 ENST00000423852 ENSE00003459260 8 ENST00000423852 ENSE00003477737 9 ENST00000423852 ENSE00003459192 10 ENST00000423852 ENSE00001742949 11 ENST00000423852 ENSE00001800235 12 ENST00000423852 ENSE00001597641 13 ENST00000338706 ENSE00003490496 1 ENST00000338706 ENSE00003609331 2 ENST00000338706 ENSE00003569147 3 ENST00000338706 ENSE00002302306 4 ENST00000338706 ENSE00003652688 5 ENST00000338706 ENSE00003586010 6 ENST00000338706 ENSE00003532508 7 ENST00000338706 ENSE00003491049 8 ENST00000338706 ENSE00003688093 9 ENST00000418188 ENSE00001654202 1 ENST00000418188 ENSE00001648900 2 ENST00000306882 ENSE00001931820 1 ENST00000306882 ENSE00001621868 2 ENST00000382407 ENSE00001491983 1 ENST00000307393 ENSE00001652231 1 ENST00000307393 ENSE00001822279 2 ENST00000309834 ENSE00001838947 1 ENST00000309834 ENSE00003536585 2 ENST00000338876 ENSE00001838947 1 ENST00000338876 ENSE00001801443 2 ENST00000338876 ENSE00001739030 3 ENST00000338876 ENSE00001756006 4 ENST00000338876 ENSE00001661293 5 ENST00000338876 ENSE00003593310 6 ENST00000382856 ENSE00001603573 1 ENST00000382856 ENSE00001801443 2 ENST00000382856 ENSE00001493572 3 ENST00000455422 ENSE00003551056 1 ENST00000455422 ENSE00001663043 2 ENST00000455422 ENSE00003516285 3 ENST00000455422 ENSE00003527480 4 ENST00000455422 ENSE00001644937 5 ENST00000455422 ENSE00001644677 6 ENST00000455422 ENSE00001705054 7 ENST00000455422 ENSE00001636903 8 ENST00000311828 ENSE00002323304 1 ENST00000311828 ENSE00003527480 2 ENST00000311828 ENSE00002263796 3 ENST00000416687 ENSE00003587796 1 ENST00000416687 ENSE00002255439 2 ENST00000416687 ENSE00002234877 3 ENST00000416687 ENSE00003466737 4 ENST00000416687 ENSE00003689056 5 ENST00000416687 ENSE00002236871 6 ENST00000321217 ENSE00001091887 1 ENST00000321217 ENSE00001889836 2 ENST00000559055 ENSE00002559577 1 ENST00000324446 ENSE00001285919 1 ENST00000324446 ENSE00001702356 2 ENST00000454875 ENSE00001684888 1 ENST00000454875 ENSE00001631223 2 ENST00000454875 ENSE00001624668 3 ENST00000452584 ENSE00001747572 1 ENST00000452584 ENSE00001776523 2 ENST00000452584 ENSE00001661526 3 ENST00000452584 ENSE00001792674 4 ENST00000452584 ENSE00001594458 5 ENST00000331787 ENSE00001313137 1 ENST00000331787 ENSE00001556105 2 ENST00000447937 ENSE00001748128 1 ENST00000447937 ENSE00001776523 2 ENST00000447937 ENSE00001720075 3 ENST00000447937 ENSE00001800197 4 ENST00000447937 ENSE00001721855 5 ENST00000447937 ENSE00001746218 6 ENST00000447937 ENSE00001626612 7 ENST00000253470 ENSE00001544018 1 ENST00000253470 ENSE00001544017 2 ENST00000253470 ENSE00000900348 3 ENST00000253470 ENSE00001272668 4 ENST00000253470 ENSE00001544015 5 ENST00000426790 ENSE00001708504 1 ENST00000426790 ENSE00001744590 2 ENST00000426790 ENSE00001639130 3 ENST00000250838 ENSE00002310447 1 ENST00000382764 ENSE00001493287 1 ENST00000382764 ENSE00001296914 2 ENST00000382764 ENSE00001325246 3 ENST00000382764 ENSE00001493285 4 ENST00000329684 ENSE00001853079 1 ENST00000329684 ENSE00001693371 2 ENST00000329684 ENSE00001729545 3 ENST00000426035 ENSE00001853079 1 ENST00000426035 ENSE00001693371 2 ENST00000426035 ENSE00001799150 3 ENST00000331172 ENSE00002265228 1 ENST00000331172 ENSE00001730908 2 ENST00000331172 ENSE00001631073 3 ENST00000331172 ENSE00001704814 4 ENST00000331172 ENSE00001619518 5 ENST00000331172 ENSE00002258116 6 ENST00000602732 ENSE00003436862 1 ENST00000602732 ENSE00003254543 2 ENST00000602732 ENSE00001669186 3 ENST00000602732 ENSE00001626256 4 ENST00000602732 ENSE00003262349 5 ENST00000331070 ENSE00001730185 1 ENST00000331070 ENSE00001669186 2 ENST00000331070 ENSE00001626256 3 ENST00000331070 ENSE00003542244 4 ENST00000331070 ENSE00001792376 5 ENST00000331070 ENSE00003677192 6 ENST00000331070 ENSE00003473409 7 ENST00000331070 ENSE00001543555 8 ENST00000602818 ENSE00003442800 1 ENST00000602818 ENSE00001669186 2 ENST00000602818 ENSE00001626256 3 ENST00000602818 ENSE00003516313 4 ENST00000602818 ENSE00003688894 5 ENST00000602818 ENSE00003560022 6 ENST00000602818 ENSE00003360806 7 ENST00000382585 ENSE00001730185 1 ENST00000382585 ENSE00001669186 2 ENST00000382585 ENSE00001626256 3 ENST00000382585 ENSE00003542244 4 ENST00000382585 ENSE00001792376 5 ENST00000382585 ENSE00003677192 6 ENST00000382585 ENSE00003473409 7 ENST00000382585 ENSE00001698397 8 ENST00000382585 ENSE00001791291 9 ENST00000602770 ENSE00003302451 1 ENST00000602770 ENSE00003336765 2 ENST00000602770 ENSE00001619605 3 ENST00000602770 ENSE00001689728 4 ENST00000602770 ENSE00003272237 5 ENST00000382392 ENSE00001676764 1 ENST00000382392 ENSE00001619605 2 ENST00000382392 ENSE00001689728 3 ENST00000382392 ENSE00003549506 4 ENST00000382392 ENSE00001757255 5 ENST00000382392 ENSE00003667169 6 ENST00000382392 ENSE00003463186 7 ENST00000382392 ENSE00001625788 8 ENST00000382392 ENSE00001723611 9 ENST00000602549 ENSE00003454106 1 ENST00000602549 ENSE00001619605 2 ENST00000602549 ENSE00001689728 3 ENST00000602549 ENSE00003681954 4 ENST00000602549 ENSE00003623347 5 ENST00000602549 ENSE00003640779 6 ENST00000602549 ENSE00003335658 7 ENST00000602549 ENSE00003346171 8 ENST00000331397 ENSE00001864071 1 ENST00000331397 ENSE00003531058 2 ENST00000331397 ENSE00003601240 3 ENST00000331397 ENSE00003660729 4 ENST00000331397 ENSE00003557845 5 ENST00000331397 ENSE00003529356 6 ENST00000331397 ENSE00003648165 7 ENST00000331397 ENSE00001594460 8 ENST00000331397 ENSE00003527061 9 ENST00000331397 ENSE00003473448 10 ENST00000331397 ENSE00001775185 11 ENST00000331397 ENSE00001755119 12 ENST00000331397 ENSE00001291636 13 ENST00000331397 ENSE00001311020 14 ENST00000331397 ENSE00001696208 15 ENST00000331397 ENSE00001305759 16 ENST00000331397 ENSE00001624388 17 ENST00000331397 ENSE00001639693 18 ENST00000331397 ENSE00001651897 19 ENST00000331397 ENSE00001295816 20 ENST00000331397 ENSE00001591330 21 ENST00000331397 ENSE00001751483 22 ENST00000331397 ENSE00001740894 23 ENST00000331397 ENSE00001640284 24 ENST00000331397 ENSE00001785465 25 ENST00000331397 ENSE00001298131 26 ENST00000331397 ENSE00001713248 27 ENST00000331397 ENSE00001875480 28 ENST00000362096 ENSE00001385925 1 ENST00000362096 ENSE00003531058 2 ENST00000362096 ENSE00003601240 3 ENST00000362096 ENSE00003660729 4 ENST00000362096 ENSE00003557845 5 ENST00000362096 ENSE00003529356 6 ENST00000362096 ENSE00003648165 7 ENST00000362096 ENSE00001594460 8 ENST00000362096 ENSE00003527061 9 ENST00000362096 ENSE00003473448 10 ENST00000362096 ENSE00001775185 11 ENST00000362096 ENSE00001755119 12 ENST00000362096 ENSE00001291636 13 ENST00000362096 ENSE00001311020 14 ENST00000362096 ENSE00001696208 15 ENST00000362096 ENSE00001305759 16 ENST00000362096 ENSE00001624388 17 ENST00000362096 ENSE00001639693 18 ENST00000362096 ENSE00001651897 19 ENST00000362096 ENSE00001295816 20 ENST00000362096 ENSE00001591330 21 ENST00000362096 ENSE00001751483 22 ENST00000362096 ENSE00001740894 23 ENST00000362096 ENSE00001640284 24 ENST00000362096 ENSE00001436855 25 ENST00000329134 ENSE00001385925 1 ENST00000329134 ENSE00003531058 2 ENST00000329134 ENSE00003601240 3 ENST00000329134 ENSE00003660729 4 ENST00000329134 ENSE00003557845 5 ENST00000329134 ENSE00003529356 6 ENST00000329134 ENSE00003648165 7 ENST00000329134 ENSE00001594460 8 ENST00000329134 ENSE00003527061 9 ENST00000329134 ENSE00003473448 10 ENST00000329134 ENSE00001775185 11 ENST00000329134 ENSE00001755119 12 ENST00000329134 ENSE00001291636 13 ENST00000329134 ENSE00001311020 14 ENST00000329134 ENSE00001696208 15 ENST00000329134 ENSE00001305759 16 ENST00000329134 ENSE00001624388 17 ENST00000329134 ENSE00001639693 18 ENST00000329134 ENSE00001651897 19 ENST00000329134 ENSE00001640421 20 ENST00000478900 ENSE00001822678 1 ENST00000478900 ENSE00003612487 2 ENST00000478900 ENSE00003529285 3 ENST00000478900 ENSE00003678156 4 ENST00000478900 ENSE00003644070 5 ENST00000478900 ENSE00003505329 6 ENST00000478900 ENSE00003575738 7 ENST00000478900 ENSE00003582459 8 ENST00000478900 ENSE00003591211 9 ENST00000478900 ENSE00001899507 10 ENST00000474365 ENSE00001931275 1 ENST00000474365 ENSE00003529285 2 ENST00000474365 ENSE00003678156 3 ENST00000474365 ENSE00003644070 4 ENST00000474365 ENSE00003505329 5 ENST00000474365 ENSE00003575738 6 ENST00000474365 ENSE00001818021 7 ENST00000382893 ENSE00001436854 1 ENST00000382893 ENSE00003531058 2 ENST00000382893 ENSE00003601240 3 ENST00000382893 ENSE00003660729 4 ENST00000382893 ENSE00003557845 5 ENST00000382893 ENSE00003529356 6 ENST00000382893 ENSE00001493710 7 ENST00000479713 ENSE00001942244 1 ENST00000479713 ENSE00001872513 2 ENST00000382896 ENSE00002281428 1 ENST00000382896 ENSE00003531058 2 ENST00000382896 ENSE00003601240 3 ENST00000382896 ENSE00003660729 4 ENST00000382896 ENSE00003557845 5 ENST00000382896 ENSE00003529356 6 ENST00000382896 ENSE00003648165 7 ENST00000382896 ENSE00001594460 8 ENST00000382896 ENSE00003527061 9 ENST00000382896 ENSE00003473448 10 ENST00000382896 ENSE00001775185 11 ENST00000382896 ENSE00001755119 12 ENST00000382896 ENSE00002277775 13 ENST00000382896 ENSE00001291636 14 ENST00000382896 ENSE00001311020 15 ENST00000382896 ENSE00001696208 16 ENST00000382896 ENSE00001305759 17 ENST00000382896 ENSE00001624388 18 ENST00000382896 ENSE00001639693 19 ENST00000382896 ENSE00001651897 20 ENST00000382896 ENSE00001295816 21 ENST00000382896 ENSE00001591330 22 ENST00000382896 ENSE00001751483 23 ENST00000382896 ENSE00001740894 24 ENST00000382896 ENSE00001640284 25 ENST00000382896 ENSE00001785465 26 ENST00000382896 ENSE00001298131 27 ENST00000382896 ENSE00001713248 28 ENST00000382896 ENSE00001330353 29 ENST00000537580 ENSE00002281428 1 ENST00000537580 ENSE00003531058 2 ENST00000537580 ENSE00003601240 3 ENST00000537580 ENSE00003660729 4 ENST00000537580 ENSE00003557845 5 ENST00000537580 ENSE00003529356 6 ENST00000537580 ENSE00003648165 7 ENST00000537580 ENSE00001594460 8 ENST00000537580 ENSE00003527061 9 ENST00000537580 ENSE00003473448 10 ENST00000537580 ENSE00001775185 11 ENST00000537580 ENSE00001755119 12 ENST00000537580 ENSE00002277775 13 ENST00000537580 ENSE00001291636 14 ENST00000537580 ENSE00001311020 15 ENST00000537580 ENSE00002240413 16 ENST00000537580 ENSE00001305759 17 ENST00000537580 ENSE00001624388 18 ENST00000537580 ENSE00001639693 19 ENST00000537580 ENSE00001651897 20 ENST00000537580 ENSE00001295816 21 ENST00000537580 ENSE00001591330 22 ENST00000537580 ENSE00001751483 23 ENST00000537580 ENSE00001740894 24 ENST00000537580 ENSE00001640284 25 ENST00000537580 ENSE00001785465 26 ENST00000537580 ENSE00001298131 27 ENST00000537580 ENSE00001330353 28 ENST00000538878 ENSE00002284432 1 ENST00000538878 ENSE00003531058 2 ENST00000538878 ENSE00003601240 3 ENST00000538878 ENSE00003660729 4 ENST00000538878 ENSE00003557845 5 ENST00000538878 ENSE00003529356 6 ENST00000538878 ENSE00003648165 7 ENST00000538878 ENSE00001594460 8 ENST00000538878 ENSE00003527061 9 ENST00000538878 ENSE00003473448 10 ENST00000538878 ENSE00001755119 11 ENST00000538878 ENSE00001291636 12 ENST00000538878 ENSE00001311020 13 ENST00000538878 ENSE00001696208 14 ENST00000538878 ENSE00001305759 15 ENST00000538878 ENSE00001624388 16 ENST00000538878 ENSE00001639693 17 ENST00000538878 ENSE00001651897 18 ENST00000538878 ENSE00002258300 19 ENST00000540140 ENSE00002281428 1 ENST00000540140 ENSE00003531058 2 ENST00000540140 ENSE00003601240 3 ENST00000540140 ENSE00003660729 4 ENST00000540140 ENSE00003557845 5 ENST00000540140 ENSE00003529356 6 ENST00000540140 ENSE00003648165 7 ENST00000540140 ENSE00001594460 8 ENST00000540140 ENSE00003527061 9 ENST00000540140 ENSE00003473448 10 ENST00000540140 ENSE00001755119 11 ENST00000540140 ENSE00002206921 12 ENST00000540140 ENSE00001291636 13 ENST00000540140 ENSE00001311020 14 ENST00000540140 ENSE00001696208 15 ENST00000540140 ENSE00001305759 16 ENST00000540140 ENSE00001624388 17 ENST00000540140 ENSE00001639693 18 ENST00000540140 ENSE00001651897 19 ENST00000540140 ENSE00002312710 20 ENST00000545955 ENSE00002281428 1 ENST00000545955 ENSE00003531058 2 ENST00000545955 ENSE00003601240 3 ENST00000545955 ENSE00003660729 4 ENST00000545955 ENSE00003557845 5 ENST00000545955 ENSE00003529356 6 ENST00000545955 ENSE00003648165 7 ENST00000545955 ENSE00001594460 8 ENST00000545955 ENSE00003527061 9 ENST00000545955 ENSE00003473448 10 ENST00000545955 ENSE00001775185 11 ENST00000545955 ENSE00001755119 12 ENST00000545955 ENSE00002277775 13 ENST00000545955 ENSE00002206921 14 ENST00000545955 ENSE00001291636 15 ENST00000545955 ENSE00001311020 16 ENST00000545955 ENSE00001696208 17 ENST00000545955 ENSE00001305759 18 ENST00000545955 ENSE00001624388 19 ENST00000545955 ENSE00001639693 20 ENST00000545955 ENSE00001651897 21 ENST00000383070 ENSE00001494622 1 ENST00000525526 ENSE00002201849 1 ENST00000525526 ENSE00002323146 2 ENST00000534739 ENSE00002144027 1 ENST00000534739 ENSE00002214525 2 ENST00000330337 ENSE00001543664 1 ENST00000330337 ENSE00001299738 2 ENST00000330337 ENSE00001425815 3 ENST00000330337 ENSE00001543661 4 ENST00000330337 ENSE00001543658 5 ENST00000330337 ENSE00001543653 6 ENST00000382840 ENSE00001493514 1 ENST00000455570 ENSE00001774474 1 ENST00000455570 ENSE00001632371 2 ENST00000455570 ENSE00001757652 3 ENST00000328819 ENSE00001774474 1 ENST00000328819 ENSE00001632371 2 ENST00000328819 ENSE00001598872 3 ENST00000382287 ENSE00001643163 1 ENST00000382287 ENSE00001775879 2 ENST00000382287 ENSE00001797093 3 ENST00000382287 ENSE00003604811 4 ENST00000382287 ENSE00001711311 5 ENST00000382287 ENSE00003547967 6 ENST00000382287 ENSE00003506422 7 ENST00000382287 ENSE00001764403 8 ENST00000382287 ENSE00001740581 9 ENST00000602559 ENSE00003378858 1 ENST00000602559 ENSE00001775879 2 ENST00000602559 ENSE00001797093 3 ENST00000602559 ENSE00003663501 4 ENST00000602559 ENSE00003522688 5 ENST00000602559 ENSE00003640409 6 ENST00000602559 ENSE00003450106 7 ENST00000602559 ENSE00003432143 8 ENST00000602680 ENSE00003307767 1 ENST00000602680 ENSE00003370731 2 ENST00000602680 ENSE00001775879 3 ENST00000602680 ENSE00001797093 4 ENST00000602680 ENSE00003266869 5 ENST00000382365 ENSE00001695979 1 ENST00000382365 ENSE00001803162 2 ENST00000382365 ENSE00001733013 3 ENST00000382365 ENSE00001602566 4 ENST00000382365 ENSE00001709286 5 ENST00000382365 ENSE00001706721 6 ENST00000382365 ENSE00001722493 7 ENST00000382365 ENSE00001757238 8 ENST00000382365 ENSE00001785551 9 ENST00000382365 ENSE00001618455 10 ENST00000382365 ENSE00001728003 11 ENST00000382365 ENSE00001655608 12 ENST00000382365 ENSE00001684201 13 ENST00000382365 ENSE00001594431 14 ENST00000382365 ENSE00001620779 15 ENST00000382365 ENSE00001604640 16 ENST00000382365 ENSE00001799005 17 ENST00000382365 ENSE00001715045 18 ENST00000382365 ENSE00001879735 19 ENST00000446723 ENSE00001759696 1 ENST00000446723 ENSE00001803162 2 ENST00000446723 ENSE00001733013 3 ENST00000446723 ENSE00001602566 4 ENST00000446723 ENSE00001709286 5 ENST00000446723 ENSE00001706721 6 ENST00000446723 ENSE00001722493 7 ENST00000446723 ENSE00001757238 8 ENST00000446723 ENSE00001785551 9 ENST00000446723 ENSE00001618455 10 ENST00000446723 ENSE00001728003 11 ENST00000446723 ENSE00001655608 12 ENST00000446723 ENSE00001684201 13 ENST00000446723 ENSE00001604640 14 ENST00000446723 ENSE00001799005 15 ENST00000446723 ENSE00001715045 16 ENST00000446723 ENSE00001670353 17 ENST00000315357 ENSE00001638508 1 ENST00000315357 ENSE00001803162 2 ENST00000315357 ENSE00001733013 3 ENST00000315357 ENSE00001602566 4 ENST00000315357 ENSE00001709286 5 ENST00000315357 ENSE00001706721 6 ENST00000315357 ENSE00001722493 7 ENST00000315357 ENSE00001757238 8 ENST00000315357 ENSE00001785551 9 ENST00000315357 ENSE00001728003 10 ENST00000315357 ENSE00001684201 11 ENST00000315357 ENSE00001620779 12 ENST00000315357 ENSE00001604640 13 ENST00000315357 ENSE00001799005 14 ENST00000315357 ENSE00001715045 15 ENST00000315357 ENSE00001596582 16 ENST00000400212 ENSE00001710130 1 ENST00000400212 ENSE00001803162 2 ENST00000400212 ENSE00001733013 3 ENST00000400212 ENSE00001602566 4 ENST00000400212 ENSE00001709286 5 ENST00000400212 ENSE00001706721 6 ENST00000400212 ENSE00001722493 7 ENST00000400212 ENSE00001757238 8 ENST00000400212 ENSE00001785551 9 ENST00000400212 ENSE00001618455 10 ENST00000400212 ENSE00001728003 11 ENST00000400212 ENSE00001655608 12 ENST00000400212 ENSE00001684201 13 ENST00000400212 ENSE00001620779 14 ENST00000400212 ENSE00001761121 15 ENST00000306737 ENSE00001710130 1 ENST00000306737 ENSE00001803162 2 ENST00000306737 ENSE00001733013 3 ENST00000306737 ENSE00001602566 4 ENST00000306737 ENSE00001709286 5 ENST00000306737 ENSE00001706721 6 ENST00000306737 ENSE00001722493 7 ENST00000306737 ENSE00001757238 8 ENST00000306737 ENSE00001785551 9 ENST00000306737 ENSE00001618455 10 ENST00000306737 ENSE00001728003 11 ENST00000306737 ENSE00001655608 12 ENST00000306737 ENSE00001684201 13 ENST00000306737 ENSE00002297176 14 ENST00000338964 ENSE00001761952 1 ENST00000338964 ENSE00001787222 2 ENST00000338964 ENSE00001756785 3 ENST00000338964 ENSE00001659741 4 ENST00000338964 ENSE00001614961 5 ENST00000338964 ENSE00001783992 6 ENST00000405239 ENSE00001790708 1 ENST00000405239 ENSE00001612801 2 ENST00000405239 ENSE00001805705 3 ENST00000405239 ENSE00001701677 4 ENST00000405239 ENSE00001677573 5 ENST00000405239 ENSE00001692245 6 ENST00000405239 ENSE00001655036 7 ENST00000405239 ENSE00001644179 8 ENST00000405239 ENSE00001646813 9 ENST00000405239 ENSE00001693241 10 ENST00000405239 ENSE00001620467 11 ENST00000405239 ENSE00001793499 12 ENST00000405239 ENSE00001598075 13 ENST00000405239 ENSE00001622354 14 ENST00000405239 ENSE00001695781 15 ENST00000405239 ENSE00001646624 16 ENST00000405239 ENSE00001597343 17 ENST00000405239 ENSE00001707161 18 ENST00000405239 ENSE00001696683 19 ENST00000405239 ENSE00001742324 20 ENST00000405239 ENSE00001758855 21 ENST00000405239 ENSE00001633941 22 ENST00000405239 ENSE00001675126 23 ENST00000405239 ENSE00001697295 24 ENST00000405239 ENSE00001614454 25 ENST00000405239 ENSE00003674346 26 ENST00000405239 ENSE00003567366 27 ENST00000405239 ENSE00001730215 28 ENST00000466332 ENSE00001907756 1 ENST00000466332 ENSE00003593491 2 ENST00000466332 ENSE00001924070 3 ENST00000466332 ENSE00003490554 4 ENST00000466332 ENSE00001941183 5 ENST00000382510 ENSE00002223761 1 ENST00000382510 ENSE00001612801 2 ENST00000382510 ENSE00001805705 3 ENST00000382510 ENSE00001701677 4 ENST00000382510 ENSE00001677573 5 ENST00000382510 ENSE00001692245 6 ENST00000382510 ENSE00001655036 7 ENST00000382510 ENSE00001644179 8 ENST00000382510 ENSE00001646813 9 ENST00000382510 ENSE00001693241 10 ENST00000382510 ENSE00001620467 11 ENST00000382510 ENSE00001793499 12 ENST00000382510 ENSE00001598075 13 ENST00000382510 ENSE00001622354 14 ENST00000382510 ENSE00001695781 15 ENST00000382510 ENSE00001646624 16 ENST00000382510 ENSE00001597343 17 ENST00000382510 ENSE00001707161 18 ENST00000382510 ENSE00001696683 19 ENST00000382510 ENSE00002211619 20 ENST00000382510 ENSE00002216645 21 ENST00000426000 ENSE00002288175 1 ENST00000426000 ENSE00001612801 2 ENST00000426000 ENSE00001805705 3 ENST00000426000 ENSE00001701677 4 ENST00000426000 ENSE00001677573 5 ENST00000426000 ENSE00001692245 6 ENST00000426000 ENSE00001655036 7 ENST00000426000 ENSE00001644179 8 ENST00000426000 ENSE00001646813 9 ENST00000426000 ENSE00001693241 10 ENST00000426000 ENSE00001620467 11 ENST00000426000 ENSE00001597343 12 ENST00000426000 ENSE00001707161 13 ENST00000426000 ENSE00001696683 14 ENST00000426000 ENSE00001742324 15 ENST00000426000 ENSE00001758855 16 ENST00000426000 ENSE00001633941 17 ENST00000426000 ENSE00001675126 18 ENST00000426000 ENSE00001697295 19 ENST00000426000 ENSE00001614454 20 ENST00000426000 ENSE00003674346 21 ENST00000426000 ENSE00003567366 22 ENST00000426000 ENSE00002302795 23 ENST00000540248 ENSE00002244340 1 ENST00000540248 ENSE00001612801 2 ENST00000540248 ENSE00001805705 3 ENST00000540248 ENSE00001701677 4 ENST00000540248 ENSE00001677573 5 ENST00000540248 ENSE00001692245 6 ENST00000540248 ENSE00001597343 7 ENST00000540248 ENSE00001707161 8 ENST00000540248 ENSE00001696683 9 ENST00000540248 ENSE00001742324 10 ENST00000540248 ENSE00001758855 11 ENST00000540248 ENSE00001633941 12 ENST00000540248 ENSE00001675126 13 ENST00000540248 ENSE00001614454 14 ENST00000540248 ENSE00003674346 15 ENST00000540248 ENSE00003567366 16 ENST00000540248 ENSE00002220199 17 ENST00000344424 ENSE00001364289 1 ENST00000344424 ENSE00001703024 2 ENST00000344424 ENSE00001598245 3 ENST00000344424 ENSE00001623069 4 ENST00000344424 ENSE00001638930 5 ENST00000431358 ENSE00001793914 1 ENST00000431358 ENSE00003611070 2 ENST00000431358 ENSE00003508777 3 ENST00000431358 ENSE00003486078 4 ENST00000431358 ENSE00003501886 5 ENST00000431358 ENSE00002025193 6 ENST00000382670 ENSE00001605630 1 ENST00000382670 ENSE00002029402 2 ENST00000382670 ENSE00002071256 3 ENST00000382670 ENSE00001752142 4 ENST00000382670 ENSE00001625315 5 ENST00000382670 ENSE00001784994 6 ENST00000382670 ENSE00001627758 7 ENST00000382670 ENSE00001785135 8 ENST00000382670 ENSE00001784976 9 ENST00000382670 ENSE00001614661 10 ENST00000538925 ENSE00002247829 1 ENST00000538925 ENSE00002029402 2 ENST00000538925 ENSE00002071256 3 ENST00000538925 ENSE00002322909 4 ENST00000441780 ENSE00001696638 1 ENST00000441780 ENSE00001710713 2 ENST00000441780 ENSE00001621856 3 ENST00000441780 ENSE00001665831 4 ENST00000441780 ENSE00001614475 5 ENST00000441780 ENSE00001747959 6 ENST00000441780 ENSE00001629056 7 ENST00000441780 ENSE00001738683 8 ENST00000441780 ENSE00001745419 9 ENST00000361365 ENSE00001435537 1 ENST00000361365 ENSE00003613684 2 ENST00000361365 ENSE00003657245 3 ENST00000361365 ENSE00003465639 4 ENST00000361365 ENSE00001635972 5 ENST00000361365 ENSE00003488477 6 ENST00000361365 ENSE00001436409 7 ENST00000465253 ENSE00001900287 1 ENST00000465253 ENSE00003550832 2 ENST00000465253 ENSE00003637584 3 ENST00000465253 ENSE00003458723 4 ENST00000465253 ENSE00001848909 5 ENST00000382772 ENSE00001848730 1 ENST00000382772 ENSE00003613684 2 ENST00000382772 ENSE00003657245 3 ENST00000382772 ENSE00001635972 4 ENST00000382772 ENSE00003488477 5 ENST00000382772 ENSE00003530204 6 ENST00000464196 ENSE00001918431 1 ENST00000464196 ENSE00003571869 2 ENST00000485584 ENSE00001943944 1 ENST00000485584 ENSE00003530759 2 ENST00000485584 ENSE00003571869 3 ENST00000382314 ENSE00001608723 1 ENST00000382314 ENSE00001761380 2 ENST00000382314 ENSE00001671603 3 ENST00000382314 ENSE00001610089 4 ENST00000382314 ENSE00001639000 5 ENST00000382314 ENSE00001609022 6 ENST00000382314 ENSE00001796227 7 ENST00000382314 ENSE00001643133 8 ENST00000382314 ENSE00001610738 9 ENST00000382314 ENSE00001694635 10 ENST00000382314 ENSE00001628323 11 ENST00000382314 ENSE00001759079 12 ENST00000382314 ENSE00003621500 13 ENST00000382314 ENSE00003476346 14 ENST00000382314 ENSE00003593830 15 ENST00000382314 ENSE00003673436 16 ENST00000382314 ENSE00002286159 17 ENST00000382296 ENSE00001761380 1 ENST00000382296 ENSE00001671603 2 ENST00000382296 ENSE00001610089 3 ENST00000382296 ENSE00001639000 4 ENST00000382296 ENSE00001609022 5 ENST00000382296 ENSE00001796227 6 ENST00000382296 ENSE00001643133 7 ENST00000382296 ENSE00001610738 8 ENST00000382296 ENSE00001694635 9 ENST00000382296 ENSE00001628323 10 ENST00000382296 ENSE00001759079 11 ENST00000382296 ENSE00003621500 12 ENST00000382296 ENSE00003521530 13 ENST00000382296 ENSE00003476346 14 ENST00000382296 ENSE00003593830 15 ENST00000382296 ENSE00001409187 16 ENST00000449750 ENSE00001608723 1 ENST00000449750 ENSE00001784722 2 ENST00000449750 ENSE00001612288 3 ENST00000449750 ENSE00001607094 4 ENST00000449750 ENSE00001741374 5 ENST00000449750 ENSE00001709278 6 ENST00000449750 ENSE00001796227 7 ENST00000449750 ENSE00001643133 8 ENST00000449750 ENSE00001610738 9 ENST00000449750 ENSE00001694635 10 ENST00000449750 ENSE00001628323 11 ENST00000449750 ENSE00001632077 12 ENST00000449750 ENSE00003646399 13 ENST00000449750 ENSE00003476346 14 ENST00000449750 ENSE00003593830 15 ENST00000449750 ENSE00003673436 16 ENST00000449750 ENSE00002286159 17 ENST00000415508 ENSE00002226159 1 ENST00000415508 ENSE00001784722 2 ENST00000415508 ENSE00001612288 3 ENST00000415508 ENSE00001607094 4 ENST00000415508 ENSE00001741374 5 ENST00000415508 ENSE00001709278 6 ENST00000415508 ENSE00001796227 7 ENST00000415508 ENSE00001643133 8 ENST00000415508 ENSE00001628323 9 ENST00000415508 ENSE00003609241 10 ENST00000415508 ENSE00003641574 11 ENST00000415508 ENSE00003582499 12 ENST00000415508 ENSE00003476346 13 ENST00000415508 ENSE00003593830 14 ENST00000415508 ENSE00003673436 15 ENST00000415508 ENSE00002310973 16 ENST00000440066 ENSE00001804650 1 ENST00000440066 ENSE00001784722 2 ENST00000440066 ENSE00001612288 3 ENST00000440066 ENSE00001607094 4 ENST00000440066 ENSE00001741374 5 ENST00000440066 ENSE00001709278 6 ENST00000440066 ENSE00001761380 7 ENST00000440066 ENSE00001671603 8 ENST00000440066 ENSE00001610089 9 ENST00000440066 ENSE00001639000 10 ENST00000440066 ENSE00001609022 11 ENST00000440066 ENSE00001796227 12 ENST00000440066 ENSE00001643133 13 ENST00000440066 ENSE00001610738 14 ENST00000440066 ENSE00001694635 15 ENST00000440066 ENSE00001628323 16 ENST00000440066 ENSE00001632077 17 ENST00000440066 ENSE00003646399 18 ENST00000440066 ENSE00003609241 19 ENST00000440066 ENSE00003476346 20 ENST00000440066 ENSE00003593830 21 ENST00000440066 ENSE00003673436 22 ENST00000440066 ENSE00002286159 23 ENST00000382432 ENSE00002247728 1 ENST00000382432 ENSE00001761380 2 ENST00000382432 ENSE00001671603 3 ENST00000382432 ENSE00001610089 4 ENST00000382432 ENSE00001639000 5 ENST00000382432 ENSE00001609022 6 ENST00000382432 ENSE00001796227 7 ENST00000382432 ENSE00001643133 8 ENST00000382432 ENSE00001610738 9 ENST00000382432 ENSE00001694635 10 ENST00000382432 ENSE00001628323 11 ENST00000382432 ENSE00001632077 12 ENST00000382432 ENSE00003646399 13 ENST00000382432 ENSE00001759079 14 ENST00000382432 ENSE00003688590 15 ENST00000382432 ENSE00003491822 16 ENST00000382432 ENSE00003627572 17 ENST00000382432 ENSE00003463917 18 ENST00000382432 ENSE00002242041 19 ENST00000382432 ENSE00003542339 20 ENST00000382432 ENSE00003675468 21 ENST00000382432 ENSE00003605405 22 ENST00000382432 ENSE00003571325 23 ENST00000382432 ENSE00002286159 24 ENST00000400494 ENSE00002324480 1 ENST00000400494 ENSE00001761380 2 ENST00000400494 ENSE00001671603 3 ENST00000400494 ENSE00001610089 4 ENST00000400494 ENSE00001639000 5 ENST00000400494 ENSE00001609022 6 ENST00000400494 ENSE00001796227 7 ENST00000400494 ENSE00001643133 8 ENST00000400494 ENSE00001610738 9 ENST00000400494 ENSE00001694635 10 ENST00000400494 ENSE00001628323 11 ENST00000400494 ENSE00001632077 12 ENST00000400494 ENSE00003646399 13 ENST00000400494 ENSE00001759079 14 ENST00000400494 ENSE00003688590 15 ENST00000400494 ENSE00003675468 16 ENST00000400494 ENSE00003605405 17 ENST00000400494 ENSE00003571325 18 ENST00000400494 ENSE00002310973 19 ENST00000382290 ENSE00002247728 1 ENST00000382290 ENSE00001761380 2 ENST00000382290 ENSE00001671603 3 ENST00000382290 ENSE00001610089 4 ENST00000382290 ENSE00001639000 5 ENST00000382290 ENSE00001609022 6 ENST00000382290 ENSE00001796227 7 ENST00000382290 ENSE00001643133 8 ENST00000382290 ENSE00001610738 9 ENST00000382290 ENSE00001694635 10 ENST00000382290 ENSE00001628323 11 ENST00000382290 ENSE00001632077 12 ENST00000382290 ENSE00003528908 13 ENST00000382290 ENSE00003669768 14 ENST00000382290 ENSE00003491822 15 ENST00000382290 ENSE00003627572 16 ENST00000382290 ENSE00003463917 17 ENST00000382290 ENSE00002242041 18 ENST00000382290 ENSE00003542339 19 ENST00000382290 ENSE00003675468 20 ENST00000382290 ENSE00003605405 21 ENST00000382290 ENSE00003571325 22 ENST00000382290 ENSE00002286159 23 ENST00000416956 ENSE00001693578 1 ENST00000416956 ENSE00001701535 2 ENST00000416956 ENSE00001742121 3 ENST00000416956 ENSE00001646556 4 ENST00000416956 ENSE00001671473 5 ENST00000382449 ENSE00001639518 1 ENST00000382449 ENSE00001640624 2 ENST00000382449 ENSE00001689126 3 ENST00000382449 ENSE00001736653 4 ENST00000382449 ENSE00001659494 5 ENST00000382449 ENSE00001723992 6 ENST00000382449 ENSE00001592425 7 ENST00000382449 ENSE00001676137 8 ENST00000382449 ENSE00001748863 9 ENST00000382449 ENSE00001787726 10 ENST00000382449 ENSE00001605577 11 ENST00000382449 ENSE00001607297 12 ENST00000382449 ENSE00001771158 13 ENST00000382449 ENSE00001743603 14 ENST00000382449 ENSE00001706458 15 ENST00000382449 ENSE00001690453 16 ENST00000382449 ENSE00001659100 17 ENST00000382449 ENSE00001717191 18 ENST00000382449 ENSE00001705999 19 ENST00000382449 ENSE00001622502 20 ENST00000382449 ENSE00001695324 21 ENST00000382449 ENSE00001659634 22 ENST00000382449 ENSE00001668820 23 ENST00000382440 ENSE00001603036 1 ENST00000382440 ENSE00001640624 2 ENST00000382440 ENSE00001689126 3 ENST00000382440 ENSE00001736653 4 ENST00000382440 ENSE00001659494 5 ENST00000382440 ENSE00001723992 6 ENST00000382440 ENSE00001592425 7 ENST00000382440 ENSE00001676137 8 ENST00000382440 ENSE00001748863 9 ENST00000382440 ENSE00001780208 10 ENST00000382440 ENSE00001682794 11 ENST00000382440 ENSE00001787726 12 ENST00000382440 ENSE00001605577 13 ENST00000382440 ENSE00001736828 14 ENST00000382440 ENSE00001674452 15 ENST00000382440 ENSE00001686143 16 ENST00000382440 ENSE00001607297 17 ENST00000382440 ENSE00001771158 18 ENST00000382440 ENSE00001743603 19 ENST00000382440 ENSE00001706458 20 ENST00000382440 ENSE00001690453 21 ENST00000382440 ENSE00001659100 22 ENST00000382440 ENSE00001717191 23 ENST00000382440 ENSE00001705999 24 ENST00000382440 ENSE00001622502 25 ENST00000382440 ENSE00001695324 26 ENST00000382440 ENSE00001659634 27 ENST00000382440 ENSE00001687149 28 ENST00000382433 ENSE00001943922 1 ENST00000382433 ENSE00001640624 2 ENST00000382433 ENSE00001689126 3 ENST00000382433 ENSE00001736653 4 ENST00000382433 ENSE00001659494 5 ENST00000382433 ENSE00001723992 6 ENST00000382433 ENSE00001592425 7 ENST00000382433 ENSE00001676137 8 ENST00000382433 ENSE00001748863 9 ENST00000382433 ENSE00001787726 10 ENST00000382433 ENSE00001605577 11 ENST00000382433 ENSE00001736828 12 ENST00000382433 ENSE00001674452 13 ENST00000382433 ENSE00001771158 14 ENST00000382433 ENSE00001743603 15 ENST00000382433 ENSE00001706458 16 ENST00000382433 ENSE00001690453 17 ENST00000382433 ENSE00001659100 18 ENST00000382433 ENSE00001717191 19 ENST00000382433 ENSE00001705999 20 ENST00000382433 ENSE00001622502 21 ENST00000382433 ENSE00001695324 22 ENST00000382433 ENSE00001659634 23 ENST00000382433 ENSE00001865723 24 ENST00000382306 ENSE00001603036 1 ENST00000382306 ENSE00001640624 2 ENST00000382306 ENSE00001689126 3 ENST00000382306 ENSE00001736653 4 ENST00000382306 ENSE00001659494 5 ENST00000382306 ENSE00001723992 6 ENST00000382306 ENSE00001592425 7 ENST00000382306 ENSE00001676137 8 ENST00000382306 ENSE00001748863 9 ENST00000382306 ENSE00001780208 10 ENST00000382306 ENSE00001682794 11 ENST00000382306 ENSE00001787726 12 ENST00000382306 ENSE00001674452 13 ENST00000382306 ENSE00001743603 14 ENST00000382306 ENSE00001706458 15 ENST00000382306 ENSE00001690453 16 ENST00000382306 ENSE00001659100 17 ENST00000382306 ENSE00001717191 18 ENST00000382306 ENSE00001705999 19 ENST00000382306 ENSE00001622502 20 ENST00000382306 ENSE00001695324 21 ENST00000382306 ENSE00001659634 22 ENST00000382306 ENSE00001542120 23 ENST00000449947 ENSE00001685890 1 ENST00000449947 ENSE00001640624 2 ENST00000449947 ENSE00001689126 3 ENST00000449947 ENSE00001736653 4 ENST00000449947 ENSE00001659494 5 ENST00000449947 ENSE00001723992 6 ENST00000449947 ENSE00001592425 7 ENST00000449947 ENSE00001676137 8 ENST00000449947 ENSE00001748863 9 ENST00000449947 ENSE00001780208 10 ENST00000449947 ENSE00001682794 11 ENST00000449947 ENSE00001787726 12 ENST00000449947 ENSE00001674452 13 ENST00000449947 ENSE00001622502 14 ENST00000449947 ENSE00001695324 15 ENST00000449947 ENSE00001659634 16 ENST00000449947 ENSE00001687149 17 ENST00000382294 ENSE00001795799 1 ENST00000382294 ENSE00001640624 2 ENST00000382294 ENSE00001689126 3 ENST00000382294 ENSE00001736653 4 ENST00000382294 ENSE00001659494 5 ENST00000382294 ENSE00001723992 6 ENST00000382294 ENSE00001592425 7 ENST00000382294 ENSE00001676137 8 ENST00000382294 ENSE00001682794 9 ENST00000382294 ENSE00001743603 10 ENST00000382294 ENSE00001706458 11 ENST00000382294 ENSE00001690453 12 ENST00000382294 ENSE00001622502 13 ENST00000382294 ENSE00001695324 14 ENST00000382294 ENSE00001659634 15 ENST00000382294 ENSE00001656459 16 ENST00000382424 ENSE00001943922 1 ENST00000382424 ENSE00001640624 2 ENST00000382424 ENSE00001689126 3 ENST00000382424 ENSE00001736653 4 ENST00000382424 ENSE00001659494 5 ENST00000382424 ENSE00001723992 6 ENST00000382424 ENSE00001592425 7 ENST00000382424 ENSE00001676137 8 ENST00000382424 ENSE00001748863 9 ENST00000382424 ENSE00001780208 10 ENST00000382424 ENSE00001682794 11 ENST00000382424 ENSE00001787726 12 ENST00000382424 ENSE00001674452 13 ENST00000382424 ENSE00001771158 14 ENST00000382424 ENSE00001743603 15 ENST00000382424 ENSE00001706458 16 ENST00000382424 ENSE00001690453 17 ENST00000382424 ENSE00001659100 18 ENST00000382424 ENSE00001717191 19 ENST00000382424 ENSE00001705999 20 ENST00000382424 ENSE00001622502 21 ENST00000382424 ENSE00001695324 22 ENST00000382424 ENSE00001659634 23 ENST00000382424 ENSE00001656459 24 ENST00000400493 ENSE00001612046 1 ENST00000400493 ENSE00001640624 2 ENST00000400493 ENSE00001689126 3 ENST00000400493 ENSE00001736653 4 ENST00000400493 ENSE00001659494 5 ENST00000400493 ENSE00001723992 6 ENST00000400493 ENSE00001592425 7 ENST00000400493 ENSE00001676137 8 ENST00000400493 ENSE00001748863 9 ENST00000400493 ENSE00001780208 10 ENST00000400493 ENSE00001787726 11 ENST00000400493 ENSE00001736828 12 ENST00000400493 ENSE00001674452 13 ENST00000400493 ENSE00001607297 14 ENST00000400493 ENSE00001771158 15 ENST00000400493 ENSE00001622502 16 ENST00000400493 ENSE00001695324 17 ENST00000400493 ENSE00001659634 18 ENST00000400493 ENSE00001656459 19 ENST00000382431 ENSE00001612046 1 ENST00000382431 ENSE00001640624 2 ENST00000382431 ENSE00001689126 3 ENST00000382431 ENSE00001736653 4 ENST00000382431 ENSE00001659494 5 ENST00000382431 ENSE00001723992 6 ENST00000382431 ENSE00001592425 7 ENST00000382431 ENSE00001676137 8 ENST00000382431 ENSE00001748863 9 ENST00000382431 ENSE00001780208 10 ENST00000382431 ENSE00001682794 11 ENST00000382431 ENSE00001787726 12 ENST00000382431 ENSE00001605577 13 ENST00000382431 ENSE00001736828 14 ENST00000382431 ENSE00001674452 15 ENST00000382431 ENSE00001607297 16 ENST00000382431 ENSE00001771158 17 ENST00000382431 ENSE00001622502 18 ENST00000382431 ENSE00001695324 19 ENST00000382431 ENSE00001659634 20 ENST00000382431 ENSE00002307170 21 ENST00000382434 ENSE00001603036 1 ENST00000382434 ENSE00001640624 2 ENST00000382434 ENSE00001689126 3 ENST00000382434 ENSE00001736653 4 ENST00000382434 ENSE00001659494 5 ENST00000382434 ENSE00001723992 6 ENST00000382434 ENSE00001592425 7 ENST00000382434 ENSE00001676137 8 ENST00000382434 ENSE00001748863 9 ENST00000382434 ENSE00001780208 10 ENST00000382434 ENSE00001682794 11 ENST00000382434 ENSE00001787726 12 ENST00000382434 ENSE00001736828 13 ENST00000382434 ENSE00001674452 14 ENST00000382434 ENSE00002288552 15 ENST00000382966 ENSE00001494103 1 ENST00000382966 ENSE00003566412 2 ENST00000382966 ENSE00001494100 3 ENST00000493160 ENSE00001936584 1 ENST00000493160 ENSE00003683672 2 ENST00000493160 ENSE00003566412 3 ENST00000493160 ENSE00001833093 4 ENST00000493160 ENSE00001864445 5 ENST00000357871 ENSE00001494103 1 ENST00000357871 ENSE00003566412 2 ENST00000357871 ENSE00001431292 3 ENST00000382963 ENSE00001494096 1 ENST00000382963 ENSE00003683672 2 ENST00000382963 ENSE00003566412 3 ENST00000382963 ENSE00001494094 4 ENST00000382965 ENSE00001494099 1 ENST00000382965 ENSE00003566412 2 ENST00000417072 ENSE00001626669 1 ENST00000417072 ENSE00001628061 2 ENST00000417072 ENSE00001654045 3 ENST00000417072 ENSE00001742514 4 ENST00000417072 ENSE00001625965 5 ENST00000417072 ENSE00001637388 6 ENST00000417072 ENSE00001647627 7 ENST00000450591 ENSE00001713628 1 ENST00000450591 ENSE00001608925 2 ENST00000450591 ENSE00001661659 3 ENST00000450591 ENSE00001718232 4 ENST00000450591 ENSE00001712140 5 ENST00000450591 ENSE00001710562 6 ENST00000450591 ENSE00001697617 7 ENST00000388836 ENSE00001796890 1 ENST00000400275 ENSE00001542224 1 ENST00000536206 ENSE00002304178 1 ENST00000536206 ENSE00002218148 2 ENST00000258589 ENSE00002225900 1 ENST00000258589 ENSE00002060648 2 ENST00000258589 ENSE00002054613 3 ENST00000258589 ENSE00002062274 4 ENST00000258589 ENSE00001794058 5 ENST00000258589 ENSE00002063262 6 ENST00000258589 ENSE00002075791 7 ENST00000258589 ENSE00002083827 8 ENST00000258589 ENSE00001329242 9 ENST00000258589 ENSE00001755500 10 ENST00000258589 ENSE00001609863 11 ENST00000258589 ENSE00002050610 12 ENST00000258589 ENSE00001759871 13 ENST00000258589 ENSE00001803087 14 ENST00000258589 ENSE00001650788 15 ENST00000258589 ENSE00001785401 16 ENST00000258589 ENSE00001711963 17 ENST00000258589 ENSE00001803764 18 ENST00000258589 ENSE00001634122 19 ENST00000258589 ENSE00002035744 20 ENST00000448881 ENSE00001633881 1 ENST00000448881 ENSE00003705348 2 ENST00000448881 ENSE00003708504 3 ENST00000448881 ENSE00001648607 4 ENST00000448881 ENSE00001624353 5 ENST00000448881 ENSE00001654144 6 ENST00000448881 ENSE00001742721 7 ENST00000448881 ENSE00001733694 8 ENST00000400476 ENSE00002063794 1 ENST00000400476 ENSE00003705348 2 ENST00000400476 ENSE00003708504 3 ENST00000400476 ENSE00002073782 4 ENST00000442535 ENSE00001798056 1 ENST00000448575 ENSE00001786804 1 ENST00000448575 ENSE00003707528 2 ENST00000448575 ENSE00003707660 3 ENST00000448575 ENSE00001646086 4 ENST00000448575 ENSE00001635863 5 ENST00000448575 ENSE00001692837 6 ENST00000448575 ENSE00001650343 7 ENST00000448575 ENSE00001693911 8 ENST00000458444 ENSE00001782800 1 ENST00000458444 ENSE00003707528 2 ENST00000458444 ENSE00003707660 3 ENST00000458444 ENSE00001601487 4 ENST00000400581 ENSE00001543607 1 ENST00000400581 ENSE00001543606 2 ENST00000441139 ENSE00001610376 1 ENST00000441139 ENSE00002093140 2 ENST00000441139 ENSE00003244086 3 ENST00000441139 ENSE00002127178 4 ENST00000441139 ENSE00002119618 5 ENST00000441139 ENSE00002135990 6 ENST00000441139 ENSE00002871965 7 ENST00000441139 ENSE00002832419 8 ENST00000441139 ENSE00001709914 9 ENST00000400605 ENSE00002099269 1 ENST00000400605 ENSE00002093140 2 ENST00000400605 ENSE00003244086 3 ENST00000400605 ENSE00002127178 4 ENST00000400605 ENSE00002119618 5 ENST00000400605 ENSE00002135990 6 ENST00000400605 ENSE00002135691 7 ENST00000400605 ENSE00002871965 8 ENST00000400605 ENSE00002832419 9 ENST00000400605 ENSE00002116806 10 ENST00000400605 ENSE00002114284 11 ENST00000513194 ENSE00002035739 1 ENST00000513194 ENSE00002065873 2 ENST00000513194 ENSE00002052301 3 ENST00000513194 ENSE00002063105 4 ENST00000513194 ENSE00002068678 5 ENST00000513194 ENSE00002035720 6 ENST00000513194 ENSE00002040446 7 ENST00000513194 ENSE00002871965 8 ENST00000513194 ENSE00002832419 9 ENST00000513194 ENSE00002087154 10 ENST00000421118 ENSE00001641174 1 ENST00000431340 ENSE00001735477 1 ENST00000431340 ENSE00001670231 2 ENST00000431340 ENSE00001794413 3 ENST00000431340 ENSE00001687318 4 ENST00000415010 ENSE00001616737 1 ENST00000404428 ENSE00001561333 1 ENST00000403990 ENSE00001755093 1 ENST00000406090 ENSE00001564286 1 ENST00000407745 ENSE00001563558 1 ENST00000403487 ENSE00001556375 1 ENST00000403487 ENSE00001551524 2 ENST00000405035 ENSE00001551713 1 ENST00000421995 ENSE00001664386 1 ENST00000449659 ENSE00001757650 1 ENST00000425912 ENSE00001733565 1 ENST00000425912 ENSE00001699806 2 ENST00000425912 ENSE00001780177 3 ENST00000425912 ENSE00001657364 4 ENST00000425912 ENSE00001601089 5 ENST00000439805 ENSE00001753322 1 ENST00000439805 ENSE00001706758 2 ENST00000439805 ENSE00001651867 3 ENST00000439805 ENSE00001608049 4 ENST00000439805 ENSE00001662653 5 ENST00000435111 ENSE00001705807 1 ENST00000435111 ENSE00001746889 2 ENST00000455085 ENSE00001722988 1 ENST00000455085 ENSE00001776348 2 ENST00000455085 ENSE00001631973 3 ENST00000414667 ENSE00001733982 1 ENST00000413867 ENSE00001607377 1 ENST00000413867 ENSE00001744544 2 ENST00000456360 ENSE00001706460 1 ENST00000456360 ENSE00003704369 2 ENST00000456360 ENSE00001600307 3 ENST00000456360 ENSE00001699202 4 ENST00000456360 ENSE00003708495 5 ENST00000456360 ENSE00003704715 6 ENST00000456360 ENSE00001654717 7 ENST00000444169 ENSE00001801361 1 ENST00000444169 ENSE00003704369 2 ENST00000444169 ENSE00003708495 3 ENST00000444169 ENSE00003704715 4 ENST00000444169 ENSE00001684171 5 ENST00000421387 ENSE00001787469 1 ENST00000421387 ENSE00001786906 2 ENST00000412737 ENSE00001624987 1 ENST00000417252 ENSE00001742768 1 ENST00000417252 ENSE00001741857 2 ENST00000417252 ENSE00001756336 3 ENST00000417252 ENSE00001733532 4 ENST00000417252 ENSE00001765193 5 ENST00000417252 ENSE00001788990 6 ENST00000417252 ENSE00003551602 7 ENST00000417252 ENSE00003674280 8 ENST00000417252 ENSE00002050900 9 ENST00000418671 ENSE00001632235 1 ENST00000418671 ENSE00001760970 2 ENST00000418671 ENSE00001709237 3 ENST00000418671 ENSE00001738839 4 ENST00000418671 ENSE00001657532 5 ENST00000418671 ENSE00001682229 6 ENST00000418671 ENSE00001638892 7 ENST00000443911 ENSE00001720793 1 ENST00000443911 ENSE00001745042 2 ENST00000428060 ENSE00001645847 1 ENST00000417434 ENSE00001733686 1 ENST00000440402 ENSE00001640125 1 ENST00000428380 ENSE00001673618 1 ENST00000428380 ENSE00001701558 2 ENST00000446621 ENSE00001666463 1 ENST00000446621 ENSE00001732944 2 ENST00000420443 ENSE00001779327 1 ENST00000420443 ENSE00001715744 2 ENST00000420443 ENSE00001713276 3 ENST00000430152 ENSE00001682376 1 ENST00000430152 ENSE00001714515 2 ENST00000445253 ENSE00001803533 1 ENST00000445253 ENSE00001742365 2 ENST00000445253 ENSE00001763553 3 ENST00000445253 ENSE00001699801 4 ENST00000445253 ENSE00001593910 5 ENST00000435142 ENSE00001609393 1 ENST00000435142 ENSE00001645218 2 ENST00000435142 ENSE00001669340 3 ENST00000435142 ENSE00001648145 4 ENST00000435142 ENSE00001618505 5 ENST00000412474 ENSE00001722426 1 ENST00000412474 ENSE00001774330 2 ENST00000412474 ENSE00001697230 3 ENST00000445573 ENSE00001667957 1 ENST00000445573 ENSE00001741624 2 ENST00000445573 ENSE00001617890 3 ENST00000413946 ENSE00001732131 1 ENST00000413946 ENSE00001695041 2 ENST00000420810 ENSE00001705100 1 ENST00000421178 ENSE00001731067 1 ENST00000421178 ENSE00001688408 2 ENST00000421178 ENSE00001799980 3 ENST00000421178 ENSE00001667811 4 ENST00000421178 ENSE00001697848 5 ENST00000421178 ENSE00001645782 6 ENST00000421178 ENSE00001597947 7 ENST00000421178 ENSE00001783028 8 ENST00000421178 ENSE00001724466 9 ENST00000421178 ENSE00001668444 10 ENST00000421178 ENSE00001787097 11 ENST00000438971 ENSE00001602981 1 ENST00000438971 ENSE00001645114 2 ENST00000415994 ENSE00001632052 1 ENST00000415994 ENSE00001746774 2 ENST00000436723 ENSE00001759712 1 ENST00000436723 ENSE00001655699 2 ENST00000427212 ENSE00001640260 1 ENST00000427212 ENSE00003294704 2 ENST00000417797 ENSE00001787918 1 ENST00000417797 ENSE00001790627 2 ENST00000447526 ENSE00001775532 1 ENST00000451071 ENSE00003556843 1 ENST00000451071 ENSE00003707698 2 ENST00000451071 ENSE00003705095 3 ENST00000451071 ENSE00001787776 4 ENST00000451071 ENSE00001628066 5 ENST00000451071 ENSE00001708635 6 ENST00000451071 ENSE00001792249 7 ENST00000451071 ENSE00001783563 8 ENST00000400578 ENSE00002058038 1 ENST00000400578 ENSE00003707698 2 ENST00000400578 ENSE00003705095 3 ENST00000400578 ENSE00003582078 4 ENST00000413372 ENSE00001730385 1 ENST00000457708 ENSE00001660101 1 ENST00000457708 ENSE00001706320 2 ENST00000445813 ENSE00001793186 1 ENST00000434179 ENSE00001664773 1 ENST00000434179 ENSE00001659765 2 ENST00000434179 ENSE00001628115 3 ENST00000434179 ENSE00001615798 4 ENST00000434179 ENSE00001787460 5 ENST00000413200 ENSE00001747464 1 ENST00000443200 ENSE00001728661 1 ENST00000443200 ENSE00001689812 2 ENST00000443200 ENSE00001613966 3 ENST00000421205 ENSE00001614250 1 ENST00000421205 ENSE00001615218 2 ENST00000421205 ENSE00001658609 3 ENST00000421205 ENSE00001802978 4 ENST00000421205 ENSE00001752917 5 ENST00000421205 ENSE00001742406 6 ENST00000421205 ENSE00001606348 7 ENST00000443820 ENSE00001646418 1 ENST00000443820 ENSE00001596298 2 ENST00000443820 ENSE00001692812 3 ENST00000443820 ENSE00001685756 4 ENST00000443820 ENSE00001804752 5 ENST00000443820 ENSE00001603823 6 ENST00000443820 ENSE00001679516 7 ENST00000443820 ENSE00001625545 8 ENST00000422655 ENSE00001687009 1 ENST00000422655 ENSE00001681165 2 ENST00000426293 ENSE00001664672 1 ENST00000426293 ENSE00001793473 2 ENST00000426293 ENSE00001676006 3 ENST00000431179 ENSE00001665330 1 ENST00000431179 ENSE00001718020 2 ENST00000431179 ENSE00001736617 3 ENST00000431179 ENSE00001660147 4 ENST00000431179 ENSE00001747287 5 ENST00000431179 ENSE00001772012 6 ENST00000431179 ENSE00001591413 7 ENST00000431179 ENSE00001706519 8 ENST00000431179 ENSE00001681474 9 ENST00000431179 ENSE00001767346 10 ENST00000431179 ENSE00001660597 11 ENST00000412165 ENSE00001766514 1 ENST00000412165 ENSE00001667582 2 ENST00000434110 ENSE00001592213 1 ENST00000434110 ENSE00001776907 2 ENST00000434110 ENSE00001725078 3 ENST00000434110 ENSE00001700142 4 ENST00000434110 ENSE00001645488 5 ENST00000434110 ENSE00001633384 6 ENST00000434110 ENSE00001701227 7 ENST00000434110 ENSE00001700211 8 ENST00000434110 ENSE00001624131 9 ENST00000433767 ENSE00001714386 1 ENST00000433767 ENSE00001771613 2 ENST00000450145 ENSE00001677160 1 ENST00000450145 ENSE00001679028 2 ENST00000450145 ENSE00001715921 3 ENST00000450145 ENSE00001780929 4 ENST00000450145 ENSE00001670508 5 ENST00000450145 ENSE00001760125 6 ENST00000450145 ENSE00001765669 7 ENST00000450145 ENSE00001594565 8 ENST00000450145 ENSE00001723672 9 ENST00000423213 ENSE00001677160 1 ENST00000423213 ENSE00001679028 2 ENST00000423213 ENSE00001715921 3 ENST00000423213 ENSE00001780929 4 ENST00000423213 ENSE00001670508 5 ENST00000423213 ENSE00001760125 6 ENST00000423213 ENSE00001765669 7 ENST00000423213 ENSE00001594565 8 ENST00000423213 ENSE00001659766 9 ENST00000430032 ENSE00002290744 1 ENST00000430032 ENSE00002234593 2 ENST00000437686 ENSE00001723990 1 ENST00000437686 ENSE00001745366 2 ENST00000426661 ENSE00001785693 1 ENST00000426661 ENSE00001643138 2 ENST00000426661 ENSE00001806627 3 ENST00000426661 ENSE00001617913 4 ENST00000432394 ENSE00001725040 1 ENST00000432394 ENSE00001616038 2 ENST00000432394 ENSE00001645870 3 ENST00000432394 ENSE00001746455 4 ENST00000447528 ENSE00001695542 1 ENST00000447528 ENSE00001711695 2 ENST00000453474 ENSE00001622377 1 ENST00000453474 ENSE00001786914 2 ENST00000453474 ENSE00001763025 3 ENST00000440297 ENSE00001649733 1 ENST00000440297 ENSE00001795209 2 ENST00000440297 ENSE00001658484 3 ENST00000440297 ENSE00001602075 4 ENST00000440297 ENSE00001646110 5 ENST00000440297 ENSE00001782218 6 ENST00000440297 ENSE00001712850 7 ENST00000440297 ENSE00001806612 8 ENST00000440297 ENSE00001717995 9 ENST00000458209 ENSE00001712612 1 ENST00000456541 ENSE00001752848 1 ENST00000456541 ENSE00001543999 2 ENST00000426936 ENSE00001731603 1 ENST00000426936 ENSE00001617820 2 ENST00000426936 ENSE00001788369 3 ENST00000426936 ENSE00001672593 4 ENST00000426936 ENSE00001688242 5 ENST00000426936 ENSE00001713327 6 ENST00000443934 ENSE00001592550 1 ENST00000429066 ENSE00001642025 1 ENST00000418221 ENSE00001618473 1 ENST00000418221 ENSE00001629725 2 ENST00000418221 ENSE00001758450 3 ENST00000418221 ENSE00001591894 4 ENST00000418221 ENSE00001757932 5 ENST00000418221 ENSE00001666134 6 ENST00000418221 ENSE00001686479 7 ENST00000445125 ENSE00001653013 1 ENST00000426199 ENSE00001652052 1 ENST00000436888 ENSE00001638514 1 ENST00000440676 ENSE00001732026 1 ENST00000440676 ENSE00001643224 2 ENST00000440676 ENSE00001686603 3 ENST00000425789 ENSE00001722408 1 ENST00000411756 ENSE00001677525 1 ENST00000411756 ENSE00001668583 2 ENST00000411756 ENSE00001727103 3 ENST00000411756 ENSE00001635486 4 ENST00000411756 ENSE00001702927 5 ENST00000411756 ENSE00001667443 6 ENST00000411756 ENSE00001638683 7 ENST00000411756 ENSE00001673115 8 ENST00000411756 ENSE00001615368 9 ENST00000411756 ENSE00001675564 10 ENST00000411756 ENSE00001738547 11 ENST00000452415 ENSE00001674051 1 ENST00000455560 ENSE00001634395 1 ENST00000445405 ENSE00001756820 1 ENST00000445405 ENSE00001674806 2 ENST00000445405 ENSE00001673237 3 ENST00000445405 ENSE00001732143 4 ENST00000445405 ENSE00001679690 5 ENST00000445405 ENSE00001782041 6 ENST00000445405 ENSE00001745014 7 ENST00000445405 ENSE00001743398 8 ENST00000413550 ENSE00001650266 1 ENST00000413550 ENSE00001796711 2 ENST00000413550 ENSE00001805326 3 ENST00000413550 ENSE00001739171 4 ENST00000413550 ENSE00001615615 5 ENST00000449843 ENSE00001644643 1 ENST00000416040 ENSE00001634743 1 ENST00000445421 ENSE00001712081 1 ENST00000445421 ENSE00001691275 2 ENST00000458627 ENSE00001719617 1 ENST00000458627 ENSE00001722479 2 ENST00000458627 ENSE00001650606 3 ENST00000458627 ENSE00001798385 4 ENST00000458627 ENSE00001740686 5 ENST00000458627 ENSE00001660603 6 ENST00000458627 ENSE00001753397 7 ENST00000427537 ENSE00001787453 1 ENST00000427537 ENSE00001755017 2 ENST00000427537 ENSE00001689362 3 ENST00000427537 ENSE00001619402 4 ENST00000411487 ENSE00001707653 1 ENST00000423409 ENSE00001754048 1 ENST00000445453 ENSE00001631720 1 ENST00000455254 ENSE00001598941 1 ENST00000421895 ENSE00001619110 1 ENST00000421895 ENSE00001655047 2 ENST00000421895 ENSE00001663253 3 ENST00000421895 ENSE00001599244 4 ENST00000421895 ENSE00001716829 5 ENST00000421895 ENSE00001740285 6 ENST00000421895 ENSE00001722377 7 ENST00000421895 ENSE00001799387 8 ENST00000421895 ENSE00001639175 9 ENST00000421895 ENSE00001602332 10 ENST00000434773 ENSE00001740373 1 ENST00000434773 ENSE00001638353 2 ENST00000434773 ENSE00001697673 3 ENST00000431260 ENSE00001618557 1 ENST00000436568 ENSE00001760629 1 ENST00000436568 ENSE00001687747 2 ENST00000436568 ENSE00001806588 3 ENST00000436568 ENSE00001713773 4 ENST00000437359 ENSE00001715524 1 ENST00000437359 ENSE00001803876 2 ENST00000437359 ENSE00001802420 3 ENST00000437359 ENSE00001631333 4 ENST00000437359 ENSE00001792500 5 ENST00000437359 ENSE00001606958 6 ENST00000437359 ENSE00001748340 7 ENST00000437359 ENSE00001745595 8 ENST00000437359 ENSE00001655007 9 ENST00000470460 ENSE00001958730 1 ENST00000470460 ENSE00003461217 2 ENST00000470460 ENSE00003566508 3 ENST00000470460 ENSE00003512617 4 ENST00000470460 ENSE00003628086 5 ENST00000470460 ENSE00003475218 6 ENST00000470460 ENSE00003524115 7 ENST00000470460 ENSE00003544610 8 ENST00000470460 ENSE00003519695 9 ENST00000470460 ENSE00003617706 10 ENST00000470460 ENSE00003462282 11 ENST00000250831 ENSE00001775261 1 ENST00000250831 ENSE00003571276 2 ENST00000250831 ENSE00003560118 3 ENST00000250831 ENSE00001663738 4 ENST00000250831 ENSE00003481268 5 ENST00000250831 ENSE00003643053 6 ENST00000250831 ENSE00003478187 7 ENST00000250831 ENSE00003515241 8 ENST00000250831 ENSE00003518190 9 ENST00000250831 ENSE00003566008 10 ENST00000250831 ENSE00003680149 11 ENST00000250831 ENSE00003509588 12 ENST00000414629 ENSE00001594771 1 ENST00000414629 ENSE00003571276 2 ENST00000414629 ENSE00003560118 3 ENST00000414629 ENSE00001663738 4 ENST00000414629 ENSE00003481268 5 ENST00000414629 ENSE00003643053 6 ENST00000414629 ENSE00003478187 7 ENST00000414629 ENSE00003515241 8 ENST00000414629 ENSE00003518190 9 ENST00000414629 ENSE00003566008 10 ENST00000414629 ENSE00003680149 11 ENST00000414629 ENSE00003509588 12 ENST00000445779 ENSE00001594771 1 ENST00000445779 ENSE00003571276 2 ENST00000445779 ENSE00003560118 3 ENST00000445779 ENSE00001663738 4 ENST00000445779 ENSE00003481268 5 ENST00000445779 ENSE00003643053 6 ENST00000445779 ENSE00003478187 7 ENST00000445779 ENSE00003515241 8 ENST00000445779 ENSE00003518190 9 ENST00000445779 ENSE00003680149 10 ENST00000445779 ENSE00003509588 11 ENST00000413610 ENSE00001766942 1 ENST00000412493 ENSE00001691508 1 ENST00000412493 ENSE00001674716 2 ENST00000412493 ENSE00001733692 3 ENST00000412493 ENSE00001677440 4 ENST00000412493 ENSE00001757764 5 ENST00000425544 ENSE00001804714 1 ENST00000425544 ENSE00001711635 2 ENST00000425544 ENSE00001760261 3 ENST00000425544 ENSE00001636850 4 ENST00000425544 ENSE00001595014 5 ENST00000425544 ENSE00001745989 6 ENST00000425544 ENSE00001636511 7 ENST00000425544 ENSE00001632004 8 ENST00000425544 ENSE00001798989 9 ENST00000438459 ENSE00001794129 1 ENST00000438459 ENSE00001605189 2 ENST00000444242 ENSE00001600631 1 ENST00000444242 ENSE00001611586 2 ENST00000441906 ENSE00001616321 1 ENST00000441906 ENSE00001618682 2 ENST00000426983 ENSE00001698182 1 ENST00000426983 ENSE00001796451 2 ENST00000426983 ENSE00001650846 3 ENST00000426983 ENSE00001799290 4 ENST00000426983 ENSE00001659363 5 ENST00000381172 ENSE00001700980 1 ENST00000381172 ENSE00001778840 2 ENST00000381172 ENSE00001683270 3 ENST00000381172 ENSE00001612791 4 ENST00000381172 ENSE00001736429 5 ENST00000381172 ENSE00001608554 6 ENST00000381172 ENSE00001712855 7 ENST00000381172 ENSE00001639452 8 ENST00000430663 ENSE00001615810 1 ENST00000430663 ENSE00001622792 2 ENST00000430663 ENSE00001804045 3 ENST00000430663 ENSE00001713121 4 ENST00000456738 ENSE00001632993 1 ENST00000456738 ENSE00001691206 2 ENST00000456738 ENSE00001652425 3 ENST00000423333 ENSE00001775619 1 ENST00000423333 ENSE00001799498 2 ENST00000423333 ENSE00001705987 3 ENST00000423333 ENSE00001714230 4 ENST00000423333 ENSE00001736832 5 ENST00000423333 ENSE00001670100 6 ENST00000420603 ENSE00001801471 1 ENST00000420603 ENSE00001777749 2 ENST00000432201 ENSE00001744076 1 ENST00000432201 ENSE00001648363 2 ENST00000445313 ENSE00001761637 1 ENST00000445313 ENSE00001646263 2 ENST00000436690 ENSE00001738572 1 ENST00000450481 ENSE00001647752 1 ENST00000450481 ENSE00001779865 2 ENST00000450481 ENSE00001620696 3 ENST00000450481 ENSE00001763493 4 ENST00000444494 ENSE00001791861 1 ENST00000423569 ENSE00001806367 1 ENST00000411585 ENSE00001727723 1 ENST00000411585 ENSE00001647639 2 ENST00000411585 ENSE00001611070 3 ENST00000411585 ENSE00001757809 4 ENST00000428070 ENSE00001649434 1 ENST00000432613 ENSE00001694343 1 ENST00000432613 ENSE00001742226 2 ENST00000432613 ENSE00001769856 3 ENST00000432613 ENSE00001698979 4 ENST00000416110 ENSE00001747233 1 ENST00000416110 ENSE00001718178 2 ENST00000452426 ENSE00001743100 1 ENST00000452426 ENSE00001753135 2 ENST00000452426 ENSE00001762790 3 ENST00000452426 ENSE00001609952 4 ENST00000452426 ENSE00001788043 5 ENST00000456123 ENSE00001613955 1 ENST00000456123 ENSE00001793058 2 ENST00000456123 ENSE00001658199 3 ENST00000456123 ENSE00001702789 4 ENST00000449963 ENSE00001670654 1 ENST00000449963 ENSE00001742535 2 ENST00000449963 ENSE00001782038 3 ENST00000433321 ENSE00001628818 1 ENST00000433321 ENSE00001645989 2 ENST00000433321 ENSE00001671314 3 ENST00000433321 ENSE00001645127 4 ENST00000436801 ENSE00001623303 1 ENST00000436801 ENSE00003646877 2 ENST00000436801 ENSE00001624981 3 ENST00000436801 ENSE00001776488 4 ENST00000452256 ENSE00002237197 1 ENST00000452256 ENSE00002305238 2 ENST00000452256 ENSE00002214727 3 ENST00000452256 ENSE00002234764 4 ENST00000452256 ENSE00001705725 5 ENST00000452256 ENSE00001777540 6 ENST00000452256 ENSE00001698821 7 ENST00000452256 ENSE00003487206 8 ENST00000452256 ENSE00001776941 9 ENST00000432892 ENSE00001786986 1 ENST00000432892 ENSE00001636298 2 ENST00000432892 ENSE00001724614 3 ENST00000432892 ENSE00001641069 4 ENST00000432892 ENSE00001705725 5 ENST00000432892 ENSE00001777540 6 ENST00000432892 ENSE00001698821 7 ENST00000432892 ENSE00003487206 8 ENST00000432892 ENSE00001776941 9 ENST00000420524 ENSE00002237197 1 ENST00000420524 ENSE00002259310 2 ENST00000420524 ENSE00002243480 3 ENST00000420524 ENSE00001731628 4 ENST00000420524 ENSE00001702837 5 ENST00000420524 ENSE00001777950 6 ENST00000420524 ENSE00001759506 7 ENST00000420524 ENSE00003471081 8 ENST00000420524 ENSE00001630624 9 ENST00000418290 ENSE00001755166 1 ENST00000418290 ENSE00001729630 2 ENST00000415662 ENSE00001708301 1 ENST00000415662 ENSE00001718075 2 ENST00000415662 ENSE00001596904 3 ENST00000451854 ENSE00001691278 1 ENST00000432672 ENSE00001592952 1 ENST00000432672 ENSE00001667759 2 ENST00000422712 ENSE00001788558 1 ENST00000422712 ENSE00001790420 2 ENST00000422712 ENSE00001783650 3 ENST00000422712 ENSE00001800896 4 ENST00000420174 ENSE00001753165 1 ENST00000420174 ENSE00001624781 2 ENST00000420174 ENSE00001800341 3 ENST00000427373 ENSE00001796314 1 ENST00000427373 ENSE00001653980 2 ENST00000427373 ENSE00001596444 3 ENST00000434164 ENSE00001638780 1 ENST00000434164 ENSE00001750121 2 ENST00000434164 ENSE00001766520 3 ENST00000434164 ENSE00001648650 4 ENST00000440679 ENSE00001720861 1 ENST00000430228 ENSE00001806349 1 ENST00000430228 ENSE00001729950 2 ENST00000457222 ENSE00001774191 1 ENST00000457222 ENSE00003692666 2 ENST00000457222 ENSE00001747539 3 ENST00000457222 ENSE00001719444 4 ENST00000457222 ENSE00001781353 5 ENST00000457222 ENSE00001954357 6 ENST00000424594 ENSE00003617259 1 ENST00000424594 ENSE00003692666 2 ENST00000424594 ENSE00001747539 3 ENST00000424594 ENSE00001719444 4 ENST00000424594 ENSE00003611797 5 ENST00000424594 ENSE00001758618 6 ENST00000491844 ENSE00003511805 1 ENST00000491844 ENSE00003461293 2 ENST00000491844 ENSE00003601991 3 ENST00000491844 ENSE00001879368 4 ENST00000469322 ENSE00001932930 1 ENST00000469322 ENSE00003565177 2 ENST00000469322 ENSE00001931598 3 ENST00000440483 ENSE00001774191 1 ENST00000440483 ENSE00003692666 2 ENST00000440483 ENSE00001747539 3 ENST00000440483 ENSE00003463520 4 ENST00000440483 ENSE00003659094 5 ENST00000440483 ENSE00003525623 6 ENST00000427871 ENSE00001618274 1 ENST00000427871 ENSE00001610531 2 ENST00000427871 ENSE00003692666 3 ENST00000427871 ENSE00003525860 4 ENST00000427871 ENSE00001879368 5 ENST00000426660 ENSE00001724421 1 ENST00000426660 ENSE00001776105 2 ENST00000426660 ENSE00001726546 3 ENST00000426660 ENSE00001754461 4 ENST00000426660 ENSE00001804017 5 ENST00000426660 ENSE00001740783 6 ENST00000426660 ENSE00001721829 7 ENST00000426660 ENSE00001689481 8 ENST00000426660 ENSE00001600079 9 ENST00000415776 ENSE00001770854 1 ENST00000413320 ENSE00001707259 1 ENST00000413320 ENSE00001614194 2 ENST00000440136 ENSE00001610381 1 ENST00000440136 ENSE00001729283 2 ENST00000440136 ENSE00001736394 3 ENST00000440136 ENSE00001611617 4 ENST00000440136 ENSE00001675926 5 ENST00000414182 ENSE00001786158 1 ENST00000414182 ENSE00001605858 2 ENST00000414182 ENSE00001748625 3 ENST00000434454 ENSE00001628114 1 ENST00000434454 ENSE00001632712 2 ENST00000434454 ENSE00001592139 3 ENST00000434454 ENSE00001666942 4 ENST00000434454 ENSE00001734562 5 ENST00000434454 ENSE00001636017 6 ENST00000434454 ENSE00001733825 7 ENST00000423480 ENSE00001657129 1 ENST00000423480 ENSE00001754863 2 ENST00000423480 ENSE00001761172 3 ENST00000423480 ENSE00001773734 4 ENST00000455084 ENSE00001757026 1 ENST00000455084 ENSE00001688639 2 ENST00000455084 ENSE00001719273 3 ENST00000455084 ENSE00001669312 4 ENST00000455084 ENSE00001646929 5 ENST00000455084 ENSE00001717483 6 ENST00000439472 ENSE00001652776 1 ENST00000439472 ENSE00001755411 2 ENST00000367272 ENSE00001642256 1 ENST00000367272 ENSE00001701173 2 ENST00000367272 ENSE00001806782 3 ENST00000367272 ENSE00001713752 4 ENST00000367272 ENSE00001655231 5 ENST00000367272 ENSE00001777012 6 ENST00000367272 ENSE00001591489 7 ENST00000367272 ENSE00001678181 8 ENST00000367272 ENSE00002438533 9 ENST00000367272 ENSE00001666272 10 ENST00000367272 ENSE00001694641 11 ENST00000367272 ENSE00001689979 12 ENST00000367272 ENSE00001680774 13 ENST00000431405 ENSE00001638605 1 ENST00000431405 ENSE00001619709 2 ENST00000431405 ENSE00001732018 3 ENST00000431405 ENSE00001600167 4 ENST00000431405 ENSE00001682049 5 ENST00000454958 ENSE00001691510 1 ENST00000454958 ENSE00001725503 2 ENST00000426699 ENSE00001806707 1 ENST00000426699 ENSE00001708248 2 ENST00000451423 ENSE00001747579 1 ENST00000455273 ENSE00001742312 1 ENST00000455273 ENSE00001785470 2 ENST00000455273 ENSE00001687737 3 ENST00000455273 ENSE00001738169 4 ENST00000455273 ENSE00001804747 5 ENST00000455273 ENSE00001597616 6 ENST00000455273 ENSE00001629276 7 ENST00000455273 ENSE00001688905 8 ENST00000455273 ENSE00001626846 9 ENST00000455273 ENSE00001658632 10 ENST00000455273 ENSE00001653676 11 ENST00000441913 ENSE00001771502 1 ENST00000441913 ENSE00001774620 2 ENST00000441913 ENSE00001774789 3 ENST00000425411 ENSE00001793905 1 ENST00000439651 ENSE00001678856 1 ENST00000287721 ENSE00002028706 1 ENST00000287721 ENSE00003676294 2 ENST00000287721 ENSE00002045368 3 ENST00000287721 ENSE00001638906 4 ENST00000287721 ENSE00003564905 5 ENST00000287721 ENSE00001885622 6 ENST00000383000 ENSE00003489927 1 ENST00000383000 ENSE00003676294 2 ENST00000383000 ENSE00002045368 3 ENST00000383000 ENSE00001638906 4 ENST00000383000 ENSE00001801838 5 ENST00000383000 ENSE00001603826 6 ENST00000477879 ENSE00003579602 1 ENST00000477879 ENSE00003593279 2 ENST00000477879 ENSE00001943292 3 ENST00000477879 ENSE00001940527 4 ENST00000436159 ENSE00001908923 1 ENST00000436159 ENSE00003618941 2 ENST00000436159 ENSE00001859698 3 ENST00000383005 ENSE00002028706 1 ENST00000383005 ENSE00003676294 2 ENST00000383005 ENSE00002045368 3 ENST00000383005 ENSE00003586983 4 ENST00000383005 ENSE00003603865 5 ENST00000383005 ENSE00001720810 6 ENST00000330628 ENSE00002220142 1 ENST00000330628 ENSE00002247562 2 ENST00000330628 ENSE00001350919 3 ENST00000330628 ENSE00003564996 4 ENST00000330628 ENSE00003465500 5 ENST00000330628 ENSE00003586983 6 ENST00000330628 ENSE00003603865 7 ENST00000330628 ENSE00001720810 8 ENST00000537415 ENSE00001159243 1 ENST00000537415 ENSE00003676294 2 ENST00000537415 ENSE00002045368 3 ENST00000537415 ENSE00001638906 4 ENST00000537415 ENSE00002206433 5 ENST00000449858 ENSE00001806624 1 ENST00000444617 ENSE00001696124 1 ENST00000444617 ENSE00001722283 2 ENST00000444617 ENSE00001646198 3 ENST00000444617 ENSE00001630914 4 ENST00000444617 ENSE00001751441 5 ENST00000439525 ENSE00001671403 1 ENST00000439525 ENSE00001660336 2 ENST00000439525 ENSE00001785311 3 ENST00000424581 ENSE00001640432 1 ENST00000424581 ENSE00001650835 2 ENST00000424581 ENSE00001768767 3 ENST00000424581 ENSE00001734323 4 ENST00000424581 ENSE00001757798 5 ENST00000414540 ENSE00001754078 1 ENST00000414540 ENSE00001801282 2 ENST00000414540 ENSE00001669347 3 ENST00000422208 ENSE00001781088 1 ENST00000422208 ENSE00001788779 2 ENST00000422208 ENSE00001602297 3 ENST00000422208 ENSE00001712311 4 ENST00000427496 ENSE00001663391 1 ENST00000427496 ENSE00001634582 2 ENST00000427496 ENSE00001626840 3 ENST00000434308 ENSE00001668677 1 ENST00000434308 ENSE00001765004 2 ENST00000434308 ENSE00001613408 3 ENST00000447168 ENSE00001664411 1 ENST00000427622 ENSE00001675278 1 ENST00000427622 ENSE00001648707 2 ENST00000427622 ENSE00001614122 3 ENST00000427622 ENSE00001755116 4 ENST00000414596 ENSE00001615889 1 ENST00000414596 ENSE00001739908 2 ENST00000414596 ENSE00001694789 3 ENST00000414596 ENSE00001664818 4 ENST00000444350 ENSE00001596967 1 ENST00000444350 ENSE00001793420 2 ENST00000444350 ENSE00001682691 3 ENST00000444350 ENSE00001762358 4 ENST00000439968 ENSE00001653366 1 ENST00000458706 ENSE00001719426 1 ENST00000446387 ENSE00001766548 1 ENST00000417699 ENSE00001718469 1 ENST00000417699 ENSE00001757100 2 ENST00000417699 ENSE00001774249 3 ENST00000417699 ENSE00001660181 4 ENST00000417699 ENSE00001783530 5 ENST00000417699 ENSE00001683819 6 ENST00000417699 ENSE00001748455 7 ENST00000417699 ENSE00001605377 8 ENST00000417699 ENSE00001631605 9 ENST00000458667 ENSE00001743559 1 ENST00000458667 ENSE00001734255 2 ENST00000458667 ENSE00001754684 3 ENST00000458667 ENSE00001738421 4 ENST00000458667 ENSE00001606680 5 ENST00000424230 ENSE00001722745 1 ENST00000424230 ENSE00001612746 2 ENST00000424230 ENSE00001617577 3 ENST00000424230 ENSE00001806297 4 ENST00000424230 ENSE00001803898 5 ENST00000424230 ENSE00001607696 6 ENST00000434374 ENSE00001627359 1 ENST00000434374 ENSE00001652271 2 ENST00000434374 ENSE00001614594 3 ENST00000434374 ENSE00001693270 4 ENST00000434374 ENSE00001639643 5 ENST00000451173 ENSE00001679003 1 ENST00000419224 ENSE00001610666 1 ENST00000419224 ENSE00001663003 2 ENST00000419224 ENSE00001597803 3 ENST00000419224 ENSE00001638987 4 ENST00000419224 ENSE00001596879 5 ENST00000432915 ENSE00001768357 1 ENST00000418278 ENSE00001694457 1 ENST00000414395 ENSE00001592853 1 ENST00000417334 ENSE00001685903 1 ENST00000417334 ENSE00001745631 2 ENST00000417334 ENSE00001676858 3 ENST00000449148 ENSE00001724152 1 ENST00000449148 ENSE00001669607 2 ENST00000449148 ENSE00001639143 3 ENST00000449148 ENSE00001650621 4 ENST00000449148 ENSE00001633081 5 ENST00000449148 ENSE00001602954 6 ENST00000449148 ENSE00001699591 7 ENST00000449148 ENSE00001771661 8 ENST00000449148 ENSE00001632036 9 ENST00000416652 ENSE00001791163 1 ENST00000416652 ENSE00001745360 2 ENST00000416652 ENSE00001646564 3 ENST00000430062 ENSE00001732601 1 ENST00000414121 ENSE00001622837 1 ENST00000414121 ENSE00001747409 2 ENST00000446466 ENSE00001674006 1 ENST00000437794 ENSE00001636194 1 ENST00000437794 ENSE00001794176 2 ENST00000449381 ENSE00001756377 1 ENST00000449381 ENSE00001746468 2 ENST00000449381 ENSE00001745811 3 ENST00000449381 ENSE00001752960 4 ENST00000449381 ENSE00001702756 5 ENST00000449381 ENSE00001799300 6 ENST00000449381 ENSE00001670043 7 ENST00000449381 ENSE00001770923 8 ENST00000435741 ENSE00001616687 1 ENST00000444263 ENSE00001678149 1 ENST00000444263 ENSE00001757585 2 ENST00000444263 ENSE00001696132 3 ENST00000425031 ENSE00001677281 1 ENST00000425031 ENSE00001757585 2 ENST00000425031 ENSE00001620860 3 ENST00000425031 ENSE00001694023 4 ENST00000418624 ENSE00001634403 1 ENST00000451661 ENSE00001705880 1 ENST00000441642 ENSE00001632978 1 ENST00000441642 ENSE00001683725 2 ENST00000453312 ENSE00001617130 1 ENST00000453312 ENSE00001728356 2 ENST00000453312 ENSE00001783134 3 ENST00000453312 ENSE00001750562 4 ENST00000453312 ENSE00001675644 5 ENST00000453312 ENSE00001603923 6 ENST00000443152 ENSE00001804178 1 ENST00000442090 ENSE00001788264 1 ENST00000412220 ENSE00001800082 1 ENST00000412220 ENSE00001746593 2 ENST00000430735 ENSE00001614266 1 ENST00000438294 ENSE00001714431 1 ENST00000438294 ENSE00001710497 2 ENST00000398758 ENSE00001691217 1 ENST00000398758 ENSE00001804878 2 ENST00000398758 ENSE00001737381 3 ENST00000454543 ENSE00001717478 1 ENST00000413486 ENSE00001650635 1 ENST00000413486 ENSE00001733122 2 ENST00000413486 ENSE00001613384 3 ENST00000453955 ENSE00001715519 1 ENST00000453955 ENSE00001776324 2 ENST00000445112 ENSE00001657190 1 ENST00000445112 ENSE00001765641 2 ENST00000445112 ENSE00001718086 3 ENST00000445112 ENSE00001712499 4 ENST00000445112 ENSE00001732839 5 ENST00000453726 ENSE00001623599 1 ENST00000453726 ENSE00001768555 2 ENST00000450781 ENSE00001607684 1 ENST00000450781 ENSE00001704650 2 ENST00000450781 ENSE00001699413 3 ENST00000434155 ENSE00001774695 1 ENST00000434155 ENSE00001648340 2 ENST00000427963 ENSE00001644797 1 ENST00000427963 ENSE00001599057 2 ENST00000427963 ENSE00001651852 3 ENST00000427963 ENSE00001726876 4 ENST00000427963 ENSE00001788414 5 ENST00000427963 ENSE00001741171 6 ENST00000427963 ENSE00001782936 7 ENST00000427963 ENSE00001616123 8 ENST00000427963 ENSE00001758121 9 ENST00000427963 ENSE00001695453 10 ENST00000427963 ENSE00001664413 11 ENST00000429406 ENSE00001694546 1 ENST00000429406 ENSE00001642941 2 ENST00000429406 ENSE00001689808 3 ENST00000429406 ENSE00001742552 4 ENST00000426129 ENSE00001659626 1 ENST00000426129 ENSE00001688131 2 ENST00000450329 ENSE00001679725 1 ENST00000436364 ENSE00001666493 1 ENST00000414751 ENSE00001693593 1 ENST00000435433 ENSE00001728711 1 ENST00000430287 ENSE00001767583 1 ENST00000430287 ENSE00001743874 2 ENST00000430287 ENSE00001592268 3 ENST00000436338 ENSE00001612213 1 ENST00000436338 ENSE00001761722 2 ENST00000434487 ENSE00001800398 1 ENST00000434487 ENSE00001695576 2 ENST00000434556 ENSE00001763167 1 ENST00000434556 ENSE00001732672 2 ENST00000434556 ENSE00001649962 3 ENST00000451397 ENSE00001702931 1 ENST00000449393 ENSE00001772654 1 ENST00000421750 ENSE00001767851 1 ENST00000421750 ENSE00001731820 2 ENST00000421750 ENSE00001621307 3 ENST00000420090 ENSE00001778513 1 ENST00000427677 ENSE00001789966 1 ENST00000425589 ENSE00001599138 1 ENST00000425589 ENSE00001781743 2 ENST00000417305 ENSE00001615694 1 ENST00000417305 ENSE00001670294 2 ENST00000417305 ENSE00001787837 3 ENST00000431145 ENSE00001664412 1 ENST00000431145 ENSE00001751906 2 ENST00000431145 ENSE00001659262 3 ENST00000442391 ENSE00001618370 1 ENST00000442391 ENSE00001740946 2 ENST00000442391 ENSE00001805102 3 ENST00000442391 ENSE00001724905 4 ENST00000428264 ENSE00001670949 1 ENST00000428264 ENSE00001795349 2 ENST00000428264 ENSE00001626354 3 ENST00000437934 ENSE00001715878 1 ENST00000437934 ENSE00001703739 2 ENST00000453983 ENSE00001796121 1 ENST00000453983 ENSE00001737699 2 ENST00000453983 ENSE00001743166 3 ENST00000453983 ENSE00001784518 4 ENST00000453983 ENSE00001605344 5 ENST00000419557 ENSE00001672475 1 ENST00000419557 ENSE00001640636 2 ENST00000419557 ENSE00001758131 3 ENST00000419557 ENSE00001710040 4 ENST00000419557 ENSE00001790139 5 ENST00000451909 ENSE00001706607 1 ENST00000437571 ENSE00001779202 1 ENST00000433995 ENSE00001632989 1 ENST00000416803 ENSE00001734013 1 ENST00000416803 ENSE00001598660 2 ENST00000438677 ENSE00001744860 1 ENST00000438677 ENSE00001765620 2 ENST00000420675 ENSE00001794752 1 ENST00000420675 ENSE00001781093 2 ENST00000420675 ENSE00001614820 3 ENST00000430517 ENSE00001746702 1 ENST00000430517 ENSE00001794515 2 ENST00000430517 ENSE00001629993 3 ENST00000430517 ENSE00001649124 4 ENST00000430517 ENSE00001774864 5 ENST00000426950 ENSE00001494279 1 ENST00000426950 ENSE00003638561 2 ENST00000426950 ENSE00001734097 3 ENST00000426950 ENSE00001697845 4 ENST00000426950 ENSE00001703875 5 ENST00000426950 ENSE00001897275 6 ENST00000383008 ENSE00003476280 1 ENST00000383008 ENSE00003638561 2 ENST00000383008 ENSE00001734097 3 ENST00000383008 ENSE00001697845 4 ENST00000383008 ENSE00003578244 5 ENST00000383008 ENSE00001711997 6 ENST00000466036 ENSE00003579134 1 ENST00000466036 ENSE00003581570 2 ENST00000466036 ENSE00001855646 3 ENST00000466036 ENSE00001810355 4 ENST00000482082 ENSE00001825143 1 ENST00000482082 ENSE00003677158 2 ENST00000482082 ENSE00001840824 3 ENST00000417124 ENSE00001661126 1 ENST00000417124 ENSE00001647030 2 ENST00000457658 ENSE00001717777 1 ENST00000457658 ENSE00001661171 2 ENST00000457658 ENSE00001804864 3 ENST00000457658 ENSE00001769405 4 ENST00000440408 ENSE00001717777 1 ENST00000440408 ENSE00001661171 2 ENST00000440408 ENSE00001804864 3 ENST00000440408 ENSE00001538271 4 ENST00000417071 ENSE00001677769 1 ENST00000417071 ENSE00001661171 2 ENST00000417071 ENSE00001804864 3 ENST00000417071 ENSE00001720726 4 ENST00000543097 ENSE00002231970 1 ENST00000543097 ENSE00002219117 2 ENST00000447588 ENSE00001660519 1 ENST00000412870 ENSE00001721076 1 ENST00000412870 ENSE00001690255 2 ENST00000412870 ENSE00001766707 3 ENST00000412870 ENSE00001768739 4 ENST00000412870 ENSE00001787917 5 ENST00000412870 ENSE00001595199 6 ENST00000412870 ENSE00001629383 7 ENST00000412870 ENSE00001762780 8 ENST00000440624 ENSE00001621226 1 ENST00000429463 ENSE00001789186 1 ENST00000429463 ENSE00001771580 2 ENST00000429463 ENSE00001633534 3 ENST00000429463 ENSE00001599361 4 ENST00000429463 ENSE00001743476 5 ENST00000439309 ENSE00001600092 1 ENST00000454315 ENSE00001680177 1 ENST00000452257 ENSE00001758106 1 ENST00000447471 ENSE00001797129 1 ENST00000447471 ENSE00001724851 2 ENST00000447471 ENSE00001706454 3 ENST00000447471 ENSE00001717052 4 ENST00000447471 ENSE00001779101 5 ENST00000447471 ENSE00001603762 6 ENST00000382707 ENSE00001727355 1 ENST00000382707 ENSE00001718460 2 ENST00000382707 ENSE00001661257 3 ENST00000382707 ENSE00003587206 4 ENST00000382707 ENSE00003656490 5 ENST00000382707 ENSE00003571694 6 ENST00000382707 ENSE00003569851 7 ENST00000382707 ENSE00003633827 8 ENST00000382707 ENSE00003550118 9 ENST00000382707 ENSE00003663549 10 ENST00000382707 ENSE00003674760 11 ENST00000382707 ENSE00003536697 12 ENST00000361046 ENSE00001670247 1 ENST00000361046 ENSE00001718460 2 ENST00000361046 ENSE00001661257 3 ENST00000361046 ENSE00003581140 4 ENST00000361046 ENSE00003460783 5 ENST00000361046 ENSE00003639215 6 ENST00000361046 ENSE00003489167 7 ENST00000361046 ENSE00003511329 8 ENST00000361046 ENSE00003525217 9 ENST00000361046 ENSE00003545208 10 ENST00000361046 ENSE00003621655 11 ENST00000303902 ENSE00001600029 1 ENST00000303902 ENSE00001661257 2 ENST00000303902 ENSE00003587206 3 ENST00000303902 ENSE00003656490 4 ENST00000303902 ENSE00003571694 5 ENST00000303902 ENSE00003569851 6 ENST00000303902 ENSE00003633827 7 ENST00000303902 ENSE00003550118 8 ENST00000303902 ENSE00003663549 9 ENST00000303902 ENSE00003674760 10 ENST00000303902 ENSE00001632888 11 ENST00000439108 ENSE00001795478 1 ENST00000439108 ENSE00003461810 2 ENST00000439108 ENSE00003638069 3 ENST00000439108 ENSE00003462284 4 ENST00000439108 ENSE00003673811 5 ENST00000439108 ENSE00003599248 6 ENST00000439108 ENSE00003569851 7 ENST00000439108 ENSE00003633827 8 ENST00000439108 ENSE00003550118 9 ENST00000439108 ENSE00003663549 10 ENST00000439108 ENSE00003674760 11 ENST00000439108 ENSE00001632888 12 ENST00000431768 ENSE00001635427 1 ENST00000418461 ENSE00001789043 1 ENST00000418461 ENSE00001629179 2 ENST00000421058 ENSE00001774484 1 ENST00000421058 ENSE00001712382 2 ENST00000421058 ENSE00001710358 3 ENST00000455855 ENSE00001661949 1 ENST00000421008 ENSE00001688800 1 ENST00000421008 ENSE00001679843 2 ENST00000421008 ENSE00001627555 3 ENST00000421008 ENSE00001792441 4 ENST00000455527 ENSE00003710715 1 ENST00000455527 ENSE00001628915 2 ENST00000455527 ENSE00001624117 3 ENST00000455527 ENSE00001599548 4 ENST00000455527 ENSE00001591968 5 ENST00000442584 ENSE00001803550 1 ENST00000442584 ENSE00001675697 2 ENST00000442584 ENSE00001644958 3 ENST00000442584 ENSE00003710715 4 ENST00000442584 ENSE00001678529 5 ENST00000448006 ENSE00001637728 1 ENST00000448006 ENSE00001601067 2 ENST00000448006 ENSE00001733722 3 ENST00000448006 ENSE00001707869 4 ENST00000418016 ENSE00001654072 1 ENST00000418016 ENSE00003461311 2 ENST00000418016 ENSE00001709675 3 ENST00000418016 ENSE00001705207 4 ENST00000598351 ENSE00003224946 1 ENST00000598351 ENSE00003096789 2 ENST00000598351 ENSE00003004848 3 ENST00000598351 ENSE00003055029 4 ENST00000598351 ENSE00003198125 5 ENST00000598351 ENSE00003165650 6 ENST00000598351 ENSE00003163421 7 ENST00000598351 ENSE00003611037 8 ENST00000598351 ENSE00003028414 9 ENST00000451062 ENSE00001611400 1 ENST00000451062 ENSE00001669863 2 ENST00000451062 ENSE00001673478 3 ENST00000452103 ENSE00001712586 1 ENST00000452103 ENSE00003709639 2 ENST00000452103 ENSE00001663750 3 ENST00000452103 ENSE00001795860 4 ENST00000505707 ENSE00001712586 1 ENST00000505707 ENSE00003709639 2 ENST00000505707 ENSE00003709660 3 ENST00000452458 ENSE00001688314 1 ENST00000411536 ENSE00001698575 1 ENST00000411536 ENSE00001669923 2 ENST00000411536 ENSE00001614971 3 ENST00000411536 ENSE00001661020 4 ENST00000411536 ENSE00001744230 5 ENST00000411536 ENSE00001720034 6 ENST00000411536 ENSE00001752268 7 ENST00000411536 ENSE00001592390 8 ENST00000447105 ENSE00001666495 1 ENST00000447105 ENSE00001728287 2 ENST00000447105 ENSE00001639523 3 ENST00000447105 ENSE00001648850 4 ENST00000447105 ENSE00001756419 5 ENST00000447105 ENSE00001707777 6 ENST00000422633 ENSE00001796289 1 ENST00000545933 ENSE00002291273 1 ENST00000430729 ENSE00001772277 1 ENST00000430729 ENSE00001708810 2 ENST00000430729 ENSE00001618426 3 ENST00000439103 ENSE00001635775 1 ENST00000439103 ENSE00001597436 2 ENST00000446299 ENSE00001731360 1 ENST00000446299 ENSE00001688179 2 ENST00000446299 ENSE00001696656 3 ENST00000446299 ENSE00001742686 4 ENST00000446299 ENSE00001695575 5 ENST00000446299 ENSE00001748239 6 ENST00000446299 ENSE00001686372 7 ENST00000446299 ENSE00001757378 8 ENST00000446299 ENSE00001738135 9 ENST00000446299 ENSE00001662296 10 ENST00000446299 ENSE00001781418 11 ENST00000446299 ENSE00001735320 12 ENST00000446299 ENSE00001802546 13 ENST00000439653 ENSE00001607267 1 ENST00000439653 ENSE00001735320 2 ENST00000439653 ENSE00001677719 3 ENST00000439653 ENSE00001719566 4 ENST00000445200 ENSE00001779056 1 ENST00000445200 ENSE00001754002 2 ENST00000445200 ENSE00001765437 3 ENST00000445200 ENSE00001739366 4 ENST00000411983 ENSE00001795992 1 ENST00000434709 ENSE00001739581 1 ENST00000434709 ENSE00001645033 2 ENST00000420149 ENSE00001700611 1 ENST00000420149 ENSE00001798741 2 ENST00000420149 ENSE00001724601 3 ENST00000420149 ENSE00001655881 4 ENST00000458328 ENSE00001742351 1 ENST00000458328 ENSE00001606802 2 ENST00000458328 ENSE00001592567 3 ENST00000452645 ENSE00001620082 1 ENST00000452645 ENSE00001793879 2 ENST00000452645 ENSE00001621504 3 ENST00000439217 ENSE00001741426 1 ENST00000439217 ENSE00001721819 2 ENST00000415230 ENSE00001760736 1 ENST00000420889 ENSE00001706919 1 ENST00000420889 ENSE00001668409 2 ENST00000420889 ENSE00001658969 3 ENST00000420889 ENSE00001806118 4 ENST00000420889 ENSE00001766229 5 ENST00000420889 ENSE00001720050 6 ENST00000420889 ENSE00001705255 7 ENST00000420889 ENSE00001599768 8 ENST00000418455 ENSE00001723842 1 ENST00000418455 ENSE00001600158 2 ENST00000418455 ENSE00001782991 3 ENST00000418455 ENSE00001648973 4 ENST00000421819 ENSE00001803460 1 ENST00000421819 ENSE00001656819 2 ENST00000421819 ENSE00001682459 3 ENST00000421819 ENSE00001653328 4 ENST00000421819 ENSE00001804144 5 ENST00000421819 ENSE00001709330 6 ENST00000420610 ENSE00001598977 1 ENST00000420610 ENSE00001609880 2 ENST00000420610 ENSE00001671213 3 ENST00000420610 ENSE00001674255 4 ENST00000416843 ENSE00001623621 1 ENST00000425318 ENSE00001799526 1 ENST00000425318 ENSE00001753337 2 ENST00000425318 ENSE00001695538 3 ENST00000431853 ENSE00001794473 1 ENST00000425857 ENSE00001695426 1 ENST00000425857 ENSE00001695477 2 ENST00000445264 ENSE00001643114 1 ENST00000445264 ENSE00001795389 2 ENST00000445264 ENSE00001629300 3 ENST00000445264 ENSE00001702866 4 ENST00000445264 ENSE00001660124 5 ENST00000445264 ENSE00001619869 6 ENST00000428342 ENSE00001716125 1 ENST00000454995 ENSE00001626278 1 ENST00000428845 ENSE00001758513 1 ENST00000428845 ENSE00003678107 2 ENST00000428845 ENSE00001645840 3 ENST00000428845 ENSE00003600117 4 ENST00000428845 ENSE00003511199 5 ENST00000428845 ENSE00001900367 6 ENST00000444056 ENSE00003531660 1 ENST00000444056 ENSE00003678107 2 ENST00000444056 ENSE00001645840 3 ENST00000444056 ENSE00003600117 4 ENST00000444056 ENSE00001716327 5 ENST00000444056 ENSE00001604245 6 ENST00000489397 ENSE00003623643 1 ENST00000489397 ENSE00003481640 2 ENST00000489397 ENSE00001885335 3 ENST00000489397 ENSE00001840919 4 ENST00000495839 ENSE00001860458 1 ENST00000495839 ENSE00003665834 2 ENST00000495839 ENSE00001947561 3 ENST00000429039 ENSE00001665114 1 ENST00000429039 ENSE00001608967 2 ENST00000429039 ENSE00003678107 3 ENST00000429039 ENSE00001645840 4 ENST00000429039 ENSE00003550132 5 ENST00000429039 ENSE00003665834 6 ENST00000429039 ENSE00001604245 7 ENST00000432046 ENSE00001799927 1 ENST00000421279 ENSE00001728219 1 ENST00000421279 ENSE00001660382 2 ENST00000421279 ENSE00001592812 3 ENST00000421279 ENSE00001628878 4 ENST00000421279 ENSE00001744875 5 ENST00000438550 ENSE00001601315 1 ENST00000438550 ENSE00001626390 2 ENST00000436067 ENSE00001803290 1 ENST00000428616 ENSE00001772292 1 ENST00000442113 ENSE00001707613 1 ENST00000442113 ENSE00001679661 2 ENST00000444014 ENSE00001746820 1 ENST00000444014 ENSE00001781854 2 ENST00000444014 ENSE00001650660 3 ENST00000444014 ENSE00001695376 4 ENST00000444014 ENSE00001765364 5 ENST00000421675 ENSE00001648735 1 ENST00000421675 ENSE00001646873 2 ENST00000421675 ENSE00001718144 3 ENST00000421675 ENSE00001762583 4 ENST00000429799 ENSE00001727148 1 ENST00000429799 ENSE00001611218 2 ENST00000429799 ENSE00001798859 3 ENST00000429799 ENSE00001631408 4 ENST00000429799 ENSE00001610747 5 ENST00000429799 ENSE00001695935 6 ENST00000429799 ENSE00001751980 7 ENST00000429799 ENSE00001795242 8 ENST00000420376 ENSE00002293458 1 ENST00000457163 ENSE00001661837 1 ENST00000457163 ENSE00001780404 2 ENST00000457163 ENSE00001761447 3 ENST00000457163 ENSE00001796958 4 ENST00000457163 ENSE00001609132 5 ENST00000457163 ENSE00001624832 6 ENST00000417910 ENSE00001791982 1 ENST00000417910 ENSE00001595474 2 ENST00000417910 ENSE00001710293 3 ENST00000417910 ENSE00001792666 4 ENST00000419158 ENSE00001799370 1 ENST00000419158 ENSE00001733114 2 ENST00000419158 ENSE00001657618 3 ENST00000419158 ENSE00001783522 4 ENST00000419158 ENSE00001698815 5 ENST00000419158 ENSE00001706895 6 ENST00000419158 ENSE00001789274 7 ENST00000419158 ENSE00001654967 8 ENST00000419158 ENSE00001692849 9 ENST00000419158 ENSE00001679112 10 ENST00000419158 ENSE00001694527 11 ENST00000419158 ENSE00001595474 12 ENST00000419158 ENSE00001769353 13 ENST00000434481 ENSE00001731828 1 ENST00000434481 ENSE00001720641 2 ENST00000434481 ENSE00001658227 3 ENST00000434481 ENSE00001797496 4 ENST00000434481 ENSE00001739891 5 ENST00000434481 ENSE00001634813 6 ENST00000413466 ENSE00001793150 1 ENST00000413466 ENSE00001702273 2 ENST00000451467 ENSE00001639020 1 ENST00000451467 ENSE00003553084 2 ENST00000451467 ENSE00001663564 3 ENST00000430307 ENSE00001791643 1 ENST00000451162 ENSE00001802023 1 ENST00000451162 ENSE00001693799 2 ENST00000451162 ENSE00001692050 3 ENST00000451162 ENSE00001799280 4 ENST00000451162 ENSE00001673716 5 ENST00000451162 ENSE00001673218 6 ENST00000418213 ENSE00001735464 1 ENST00000418213 ENSE00001733578 2 ENST00000418213 ENSE00001790322 3 ENST00000418213 ENSE00001797275 4 ENST00000418213 ENSE00001737717 5 ENST00000418213 ENSE00001693294 6 ENST00000418213 ENSE00001707543 7 ENST00000418213 ENSE00001761870 8 ENST00000418213 ENSE00001624501 9 ENST00000418213 ENSE00001635783 10 ENST00000418213 ENSE00001736833 11 ENST00000418578 ENSE00001766910 1 ENST00000425026 ENSE00001794575 1 ENST00000435696 ENSE00001739223 1 ENST00000435696 ENSE00001657411 2 ENST00000440468 ENSE00001652940 1 ENST00000440468 ENSE00001752327 2 ENST00000429883 ENSE00001634021 1 ENST00000429883 ENSE00001709795 2 ENST00000421353 ENSE00001734007 1 ENST00000421353 ENSE00001620336 2 ENST00000452432 ENSE00001679045 1 ENST00000452432 ENSE00001662816 2 ENST00000454281 ENSE00001772499 1 ENST00000431631 ENSE00001762435 1 ENST00000431631 ENSE00001777650 2 ENST00000442145 ENSE00001788545 1 ENST00000442145 ENSE00001744623 2 ENST00000442145 ENSE00001769532 3 ENST00000442145 ENSE00001679232 4 ENST00000450658 ENSE00001651045 1 ENST00000450658 ENSE00003512039 2 ENST00000450658 ENSE00001780836 3 ENST00000450658 ENSE00001616192 4 ENST00000411668 ENSE00001618439 1 ENST00000411668 ENSE00001613903 2 ENST00000433481 ENSE00001697534 1 ENST00000433481 ENSE00001718987 2 ENST00000433481 ENSE00001618280 3 ENST00000433481 ENSE00001681425 4 ENST00000433481 ENSE00001658411 5 ENST00000435945 ENSE00001797328 1 ENST00000435945 ENSE00001638296 2 ENST00000435945 ENSE00001681574 3 ENST00000435945 ENSE00001741452 4 ENST00000435945 ENSE00001725096 5 ENST00000435945 ENSE00001670663 6 ENST00000435945 ENSE00001752207 7 ENST00000435945 ENSE00001687652 8 ENST00000435945 ENSE00001747631 9 ENST00000435945 ENSE00001702742 10 ENST00000435945 ENSE00001647502 11 ENST00000435945 ENSE00001744948 12 ENST00000435945 ENSE00001663098 13 ENST00000426526 ENSE00001745034 1 ENST00000426526 ENSE00001592977 2 ENST00000426526 ENSE00001710578 3 ENST00000426526 ENSE00001639465 4 ENST00000426526 ENSE00001714793 5 ENST00000422174 ENSE00001767839 1 ENST00000422174 ENSE00001716848 2 ENST00000423438 ENSE00001766151 1 ENST00000457961 ENSE00001747238 1 ENST00000457961 ENSE00001683875 2 ENST00000457961 ENSE00001737985 3 ENST00000457961 ENSE00001745774 4 ENST00000457961 ENSE00001733068 5 ENST00000440215 ENSE00001290990 1 ENST00000440215 ENSE00001663813 2 ENST00000440215 ENSE00003569983 3 ENST00000440215 ENSE00003622104 4 ENST00000440215 ENSE00003482640 5 ENST00000440215 ENSE00003512313 6 ENST00000446779 ENSE00001696304 1 ENST00000446779 ENSE00001597607 2 ENST00000446779 ENSE00001663813 3 ENST00000446779 ENSE00003468775 4 ENST00000446779 ENSE00003536218 5 ENST00000446779 ENSE00003492729 6 ENST00000446779 ENSE00003690238 7 ENST00000454643 ENSE00001761519 1 ENST00000454643 ENSE00001788634 2 ENST00000454643 ENSE00001681234 3 ENST00000454643 ENSE00001682885 4 ENST00000454643 ENSE00001673336 5 ENST00000454643 ENSE00001695625 6 ENST00000454643 ENSE00001609688 7 ENST00000454643 ENSE00001655456 8 ENST00000454643 ENSE00001692470 9 ENST00000454643 ENSE00001762760 10 ENST00000454643 ENSE00001659235 11 ENST00000454868 ENSE00001761647 1 ENST00000454868 ENSE00001593456 2 ENST00000454868 ENSE00001801031 3 ENST00000454868 ENSE00001625027 4 ENST00000424401 ENSE00001685429 1 ENST00000424401 ENSE00001591638 2 ENST00000424401 ENSE00001627602 3 ENST00000424401 ENSE00001792305 4 ENST00000424401 ENSE00001757037 5 ENST00000424401 ENSE00001684075 6 ENST00000435012 ENSE00001723160 1 ENST00000435012 ENSE00001611031 2 ENST00000435012 ENSE00001786310 3 ENST00000435012 ENSE00001774959 4 ENST00000435012 ENSE00001686516 5 ENST00000435012 ENSE00001719847 6 ENST00000435012 ENSE00001637326 7 ENST00000435012 ENSE00001667900 8 ENST00000435012 ENSE00001663539 9 ENST00000435012 ENSE00001684864 10 ENST00000442607 ENSE00001801245 1 ENST00000442607 ENSE00001673942 2 ENST00000442607 ENSE00001616659 3 ENST00000442607 ENSE00001720897 4 ENST00000442607 ENSE00001765257 5 ENST00000442607 ENSE00001690000 6 ENST00000452889 ENSE00001716389 1 ENST00000452889 ENSE00001712560 2 ENST00000452889 ENSE00001616878 3 ENST00000419538 ENSE00001763631 1 ENST00000419538 ENSE00001727939 2 ENST00000398377 ENSE00003523445 1 ENST00000398377 ENSE00003487606 2 ENST00000398377 ENSE00003671977 3 ENST00000398377 ENSE00003601792 4 ENST00000398377 ENSE00003665075 5 ENST00000398377 ENSE00003544401 6 ENST00000398377 ENSE00003690828 7 ENST00000398377 ENSE00003689528 8 ENST00000398377 ENSE00003469618 9 ENST00000516761 ENSE00002089038 1 ENST00000439586 ENSE00001747437 1 ENST00000439586 ENSE00001676711 2 ENST00000447585 ENSE00001663038 1 ENST00000447585 ENSE00001745094 2 ENST00000447585 ENSE00001639312 3 ENST00000447585 ENSE00001691121 4 ENST00000447585 ENSE00001731541 5 ENST00000447585 ENSE00001801724 6 ENST00000447585 ENSE00001637732 7 ENST00000447585 ENSE00001620479 8 ENST00000447585 ENSE00001596214 9 ENST00000447585 ENSE00001632411 10 ENST00000447585 ENSE00001598287 11 ENST00000447585 ENSE00003465401 12 ENST00000447585 ENSE00003603784 13 ENST00000447585 ENSE00001607039 14 ENST00000447585 ENSE00001725327 15 ENST00000447585 ENSE00001768509 16 ENST00000306641 ENSE00003484855 1 ENST00000306641 ENSE00003584721 2 ENST00000432862 ENSE00001805078 1 ENST00000425158 ENSE00001651627 1 ENST00000472227 ENSE00001897973 1 ENST00000472227 ENSE00003707476 2 ENST00000472227 ENSE00001833379 3 ENST00000472227 ENSE00001943337 4 ENST00000472227 ENSE00001869013 5 ENST00000472227 ENSE00001819899 6 ENST00000472227 ENSE00001871038 7 ENST00000472227 ENSE00001853509 8 ENST00000472227 ENSE00001855011 9 ENST00000472227 ENSE00001869938 10 ENST00000472227 ENSE00001858305 11 ENST00000430079 ENSE00001665626 1 ENST00000430079 ENSE00001700678 2 ENST00000430079 ENSE00003705410 3 ENST00000430079 ENSE00003707476 4 ENST00000430079 ENSE00001708493 5 ENST00000430079 ENSE00001755301 6 ENST00000460561 ENSE00001834814 1 ENST00000460561 ENSE00003705410 2 ENST00000460561 ENSE00003707476 3 ENST00000460561 ENSE00001810485 4 ENST00000460561 ENSE00001921850 5 ENST00000460561 ENSE00001942280 6 ENST00000460561 ENSE00001957709 7 ENST00000451061 ENSE00001593220 1 ENST00000451061 ENSE00001799029 2 ENST00000451061 ENSE00001736209 3 ENST00000451061 ENSE00001597754 4 ENST00000451061 ENSE00001645084 5 ENST00000451061 ENSE00001630093 6 ENST00000451061 ENSE00001777109 7 ENST00000451061 ENSE00001788874 8 ENST00000451061 ENSE00001795527 9 ENST00000451061 ENSE00001784531 10 ENST00000451061 ENSE00001748450 11 ENST00000451061 ENSE00001604424 12 ENST00000451061 ENSE00001711949 13 ENST00000451061 ENSE00001747846 14 ENST00000451061 ENSE00001683758 15 ENST00000451061 ENSE00001729014 16 ENST00000451061 ENSE00003703880 17 ENST00000451061 ENSE00003706916 18 ENST00000451061 ENSE00001642045 19 ENST00000451061 ENSE00001673682 20 ENST00000451061 ENSE00001602445 21 ENST00000432335 ENSE00001773752 1 ENST00000432335 ENSE00003703880 2 ENST00000432335 ENSE00003709828 3 ENST00000432335 ENSE00003706916 4 ENST00000432335 ENSE00003684405 5 ENST00000538268 ENSE00002305110 1 ENST00000538268 ENSE00003709828 2 ENST00000538268 ENSE00003584068 3 ENST00000538268 ENSE00003459679 4 ENST00000358944 ENSE00001731860 1 ENST00000358944 ENSE00001635505 2 ENST00000358944 ENSE00001802644 3 ENST00000358944 ENSE00003593123 4 ENST00000358944 ENSE00003642844 5 ENST00000358944 ENSE00003666042 6 ENST00000358944 ENSE00003674429 7 ENST00000358944 ENSE00003502244 8 ENST00000358944 ENSE00003616658 9 ENST00000358944 ENSE00003603776 10 ENST00000358944 ENSE00003548786 11 ENST00000382659 ENSE00001683783 1 ENST00000382659 ENSE00001635505 2 ENST00000382659 ENSE00001802644 3 ENST00000382659 ENSE00001619375 4 ENST00000382659 ENSE00003468556 5 ENST00000382659 ENSE00003528506 6 ENST00000382659 ENSE00003480174 7 ENST00000382659 ENSE00003577506 8 ENST00000382659 ENSE00003482521 9 ENST00000382659 ENSE00003559850 10 ENST00000382659 ENSE00003547647 11 ENST00000382659 ENSE00003613569 12 ENST00000382673 ENSE00001794358 1 ENST00000382673 ENSE00001635505 2 ENST00000382673 ENSE00001802644 3 ENST00000382673 ENSE00001619375 4 ENST00000382673 ENSE00003468556 5 ENST00000382673 ENSE00003528506 6 ENST00000382673 ENSE00003480174 7 ENST00000382673 ENSE00003577506 8 ENST00000382673 ENSE00003482521 9 ENST00000382673 ENSE00003559850 10 ENST00000382673 ENSE00003547647 11 ENST00000382673 ENSE00003465760 12 ENST00000382658 ENSE00002228703 1 ENST00000382658 ENSE00001635505 2 ENST00000382658 ENSE00001802644 3 ENST00000382658 ENSE00001619375 4 ENST00000382658 ENSE00003468556 5 ENST00000382658 ENSE00003528506 6 ENST00000382658 ENSE00003480174 7 ENST00000382658 ENSE00003577506 8 ENST00000382658 ENSE00003482521 9 ENST00000382658 ENSE00003547647 10 ENST00000382658 ENSE00002309932 11 ENST00000456659 ENSE00001643289 1 ENST00000456659 ENSE00001615364 2 ENST00000456659 ENSE00001713521 3 ENST00000456659 ENSE00001786811 4 ENST00000456659 ENSE00001765379 5 ENST00000485099 ENSE00001908333 1 ENST00000441091 ENSE00001666674 1 ENST00000441091 ENSE00001796018 2 ENST00000441091 ENSE00001784489 3 ENST00000383020 ENSE00001881074 1 ENST00000383020 ENSE00003564737 2 ENST00000383020 ENSE00003500350 3 ENST00000383020 ENSE00001799218 4 ENST00000383020 ENSE00003552000 5 ENST00000383020 ENSE00003596670 6 ENST00000383020 ENSE00003464309 7 ENST00000383020 ENSE00003633721 8 ENST00000383020 ENSE00003674912 9 ENST00000383020 ENSE00003567291 10 ENST00000383020 ENSE00003679647 11 ENST00000383020 ENSE00003617149 12 ENST00000382639 ENSE00001661847 1 ENST00000382639 ENSE00003564737 2 ENST00000382639 ENSE00003500350 3 ENST00000382639 ENSE00003675456 4 ENST00000382639 ENSE00003499970 5 ENST00000382639 ENSE00003586486 6 ENST00000382639 ENSE00003643888 7 ENST00000382639 ENSE00003501027 8 ENST00000382639 ENSE00003669209 9 ENST00000382639 ENSE00003536838 10 ENST00000382639 ENSE00003662366 11 ENST00000437993 ENSE00001659203 1 ENST00000437993 ENSE00001709097 2 ENST00000437993 ENSE00001731355 3 ENST00000303922 ENSE00001752741 1 ENST00000303922 ENSE00001595873 2 ENST00000303922 ENSE00002550304 3 ENST00000303922 ENSE00001190571 4 ENST00000420346 ENSE00001792479 1 ENST00000420346 ENSE00002550304 2 ENST00000420346 ENSE00001683633 3 ENST00000420346 ENSE00001618747 4 ENST00000420346 ENSE00001598516 5 ENST00000420346 ENSE00001800192 6 ENST00000420346 ENSE00001753847 7 ENST00000420346 ENSE00001642884 8 ENST00000420346 ENSE00001598101 9 ENST00000450910 ENSE00001629733 1 ENST00000450910 ENSE00001690028 2 ENST00000450910 ENSE00001791094 3 ENST00000450910 ENSE00001700224 4 ENST00000488394 ENSE00001859492 1 ENST00000422002 ENSE00001686036 1 ENST00000306853 ENSE00002094213 1 ENST00000306853 ENSE00002123033 2 ENST00000451913 ENSE00001780671 1 ENST00000382653 ENSE00001751822 1 ENST00000382653 ENSE00001612685 2 ENST00000382653 ENSE00001763210 3 ENST00000382653 ENSE00003654373 4 ENST00000382653 ENSE00003581142 5 ENST00000382653 ENSE00003526911 6 ENST00000382653 ENSE00003486158 7 ENST00000382653 ENSE00003580424 8 ENST00000382653 ENSE00003605671 9 ENST00000382653 ENSE00003601536 10 ENST00000382653 ENSE00003624241 11 ENST00000382680 ENSE00001636167 1 ENST00000382680 ENSE00001612685 2 ENST00000382680 ENSE00001763210 3 ENST00000382680 ENSE00001665354 4 ENST00000382680 ENSE00003494048 5 ENST00000382680 ENSE00003647885 6 ENST00000382680 ENSE00003646572 7 ENST00000382680 ENSE00003489479 8 ENST00000382680 ENSE00003670003 9 ENST00000382680 ENSE00003588956 10 ENST00000382680 ENSE00003484557 11 ENST00000382680 ENSE00003612403 12 ENST00000382677 ENSE00001744906 1 ENST00000382677 ENSE00001763210 2 ENST00000382677 ENSE00001665354 3 ENST00000382677 ENSE00003494048 4 ENST00000382677 ENSE00003647885 5 ENST00000382677 ENSE00003646572 6 ENST00000382677 ENSE00003489479 7 ENST00000382677 ENSE00003670003 8 ENST00000382677 ENSE00003588956 9 ENST00000382677 ENSE00003484557 10 ENST00000382677 ENSE00003612403 11 ENST00000418956 ENSE00002215963 1 ENST00000418956 ENSE00001612685 2 ENST00000418956 ENSE00001763210 3 ENST00000418956 ENSE00001665354 4 ENST00000418956 ENSE00003494048 5 ENST00000418956 ENSE00003647885 6 ENST00000418956 ENSE00003646572 7 ENST00000418956 ENSE00003489479 8 ENST00000418956 ENSE00003670003 9 ENST00000418956 ENSE00003484557 10 ENST00000418956 ENSE00002316782 11 ENST00000442362 ENSE00001592980 1 ENST00000442362 ENSE00001733820 2 ENST00000535771 ENSE00002317106 1 ENST00000535771 ENSE00002237968 2 ENST00000514804 ENSE00002019278 1 ENST00000509776 ENSE00002070232 1 ENST00000509776 ENSE00002079738 2 ENST00000509776 ENSE00002059695 3 ENST00000504503 ENSE00002051610 1 ENST00000504503 ENSE00002083133 2 ENST00000504503 ENSE00002028839 3 ENST00000509650 ENSE00002069932 1 ENST00000509650 ENSE00002063868 2 ENST00000511770 ENSE00002057796 1 ENST00000511770 ENSE00002048409 2 ENST00000511770 ENSE00002073771 3 ENST00000511770 ENSE00002045000 4 ENST00000503144 ENSE00002068415 1 ENST00000503144 ENSE00002086946 2 ENST00000503144 ENSE00002062200 3 ENST00000503144 ENSE00002049899 4 ENST00000442790 ENSE00002077940 1 ENST00000442790 ENSE00001694957 2 ENST00000442790 ENSE00003675853 3 ENST00000510392 ENSE00002079014 1 ENST00000510392 ENSE00002054858 2 ENST00000354494 ENSE00001426978 1 ENST00000354494 ENSE00001427537 2 ENST00000513521 ENSE00002086052 1 ENST00000513521 ENSE00002030784 2 ENST00000513521 ENSE00002046435 3 ENST00000506069 ENSE00002021560 1 ENST00000506069 ENSE00003683409 2 ENST00000506069 ENSE00002051027 3 ENST00000510613 ENSE00002079391 1 ENST00000510613 ENSE00002055245 2 ENST00000510613 ENSE00002063141 3 ENST00000510613 ENSE00002077751 4 ENST00000510613 ENSE00002066035 5 ENST00000509611 ENSE00002036613 1 ENST00000509611 ENSE00002083771 2 ENST00000509611 ENSE00002040343 3 ENST00000509611 ENSE00002082814 4 ENST00000509611 ENSE00002059714 5 ENST00000515896 ENSE00002088173 1 ENST00000515957 ENSE00002088234 1 ENST00000515987 ENSE00002088264 1 ENST00000516032 ENSE00002088309 1 ENST00000516070 ENSE00002088347 1 ENST00000516108 ENSE00002088385 1 ENST00000516116 ENSE00002088393 1 ENST00000516144 ENSE00002088421 1 ENST00000516157 ENSE00002088434 1 ENST00000516161 ENSE00002088438 1 ENST00000516187 ENSE00002088464 1 ENST00000516203 ENSE00002088480 1 ENST00000516229 ENSE00002088506 1 ENST00000516250 ENSE00002088527 1 ENST00000516346 ENSE00002088623 1 ENST00000516357 ENSE00002088634 1 ENST00000516364 ENSE00002088641 1 ENST00000516400 ENSE00002088677 1 ENST00000516480 ENSE00002088757 1 ENST00000516506 ENSE00002088783 1 ENST00000516514 ENSE00002088791 1 ENST00000516617 ENSE00002088894 1 ENST00000516630 ENSE00002088907 1 ENST00000516659 ENSE00002088936 1 ENST00000516662 ENSE00002088939 1 ENST00000516663 ENSE00002088940 1 ENST00000516704 ENSE00002088981 1 ENST00000516777 ENSE00002089054 1 ENST00000516816 ENSE00002089093 1 ENST00000516824 ENSE00002089101 1 ENST00000516855 ENSE00002089132 1 ENST00000516858 ENSE00002089135 1 ENST00000516872 ENSE00002089149 1 ENST00000516880 ENSE00002089157 1 ENST00000516885 ENSE00002089162 1 ENST00000516957 ENSE00002089234 1 ENST00000517046 ENSE00002089323 1 ENST00000517091 ENSE00002089368 1 ENST00000517139 ENSE00002089416 1 ENST00000527562 ENSE00002198122 1 ENST00000527562 ENSE00002174318 2 ENST00000527562 ENSE00002153935 3 ENST00000555130 ENSE00002532814 1 ENST00000557448 ENSE00002532407 1 ENST00000451548 ENSE00001685809 1 ENST00000451548 ENSE00001706012 2 ENST00000451548 ENSE00001701882 3 ENST00000451548 ENSE00003684179 4 ENST00000451548 ENSE00003459001 5 ENST00000451548 ENSE00003593931 6 ENST00000423647 ENSE00002289488 1 ENST00000423647 ENSE00002299255 2 ENST00000423647 ENSE00001706012 3 ENST00000423647 ENSE00001701882 4 ENST00000423647 ENSE00003684179 5 ENST00000423647 ENSE00003459001 6 ENST00000423647 ENSE00003593931 7 ENST00000553347 ENSE00002495525 1 ENST00000557360 ENSE00002516975 1 ENST00000558356 ENSE00002541336 1 ENST00000558356 ENSE00002560807 2 ENST00000566193 ENSE00002607126 1 ENST00000584011 ENSE00002699100 1 ENST00000580394 ENSE00002716056 1 ENST00000584045 ENSE00002692672 1 ENST00000578366 ENSE00002709597 1 ENST00000586015 ENSE00002923801 1 ENST00000601700 ENSE00002984896 1 ENST00000601700 ENSE00003022139 2 ENST00000601700 ENSE00003135789 3 ENST00000599485 ENSE00003159256 1 ENST00000599485 ENSE00003053921 2 ENST00000595988 ENSE00003090195 1 ENST00000595988 ENSE00003068265 2 ENST00000595988 ENSE00003133967 3 ENST00000595988 ENSE00003158951 4 ENST00000595988 ENSE00003052018 5 ENST00000598545 ENSE00003105168 1 ENST00000598545 ENSE00002994181 2 ENST00000598545 ENSE00003035759 3 ENST00000601705 ENSE00003089533 1 ENST00000601705 ENSE00003100810 2 ENST00000448518 ENSE00001782073 1 ENST00000448518 ENSE00001705189 2 ENST00000448518 ENSE00001641329 3 ENST00000448518 ENSE00001803456 4 ENST00000448518 ENSE00001739988 5 ENST00000448518 ENSE00001717366 6 ENST00000448518 ENSE00001761223 7 ENST00000605584 ENSE00003671391 1 ENST00000605584 ENSE00003551235 2 ENST00000603738 ENSE00003639402 1 ENST00000603738 ENSE00003668884 2 ENST00000604436 ENSE00003649651 1 ENST00000603467 ENSE00003691087 1 ENST00000604924 ENSE00003621115 1 ENST00000604370 ENSE00003657297 1 ENST00000605663 ENSE00003625313 1 ENST00000604178 ENSE00003638565 1 ENST00000604178 ENSE00003555471 2 ENST00000604289 ENSE00003625865 1 ENST00000606439 ENSE00003697854 1 ensembldb/inst/doc/0000755000175400017540000000000013241155731015257 5ustar00biocbuildbiocbuildensembldb/inst/doc/MySQL-backend.R0000644000175400017540000000213413241155654017740 0ustar00biocbuildbiocbuild## ----eval = FALSE---------------------------------------------------------- # library(ensembldb) # ## Load the EnsDb package that should be installed on the MySQL server # library(EnsDb.Hsapiens.v75) # # ## Call the useMySQL method providing the required credentials to create # ## databases and inserting data on the MySQL server # edb_mysql <- useMySQL(EnsDb.Hsapiens.v75, host = "localhost", user = "userwrite", # pass = "userpass") # # ## Use this EnsDb object # genes(edb_mysql) # ## ----eval = FALSE---------------------------------------------------------- # library(ensembldb) # library(RMySQL) # # ## Connect to the MySQL database to list the databases. # dbcon <- dbConnect(MySQL(), host = "localhost", user = "readonly", # pass = "readonly") # # ## List the available databases # listEnsDbs(dbcon) # # ## Connect to one of the databases and use that one. # dbcon <- dbConnect(MySQL(), host = "localhost", user = "readonly", # pass = "readonly", dbname = "ensdb_hsapiens_v75") # edb <- EnsDb(dbcon) # edb # ensembldb/inst/doc/MySQL-backend.Rmd0000644000175400017540000000457113175714743020276 0ustar00biocbuildbiocbuild--- title: "Using a MySQL server backend" author: "Johannes Rainer" package: ensembldb output: BiocStyle::html_document: toc_float: true vignette: > %\VignetteIndexEntry{Using a MySQL server backend} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} %\VignetteDepends{ensembldb,EnsDb.Hsapiens.v75,BiocStyle} --- # Introduction `ensembldb` uses by default, similar to other annotation packages in Bioconductor, a SQLite database backend, i.e. annotations are retrieved from file-based SQLite databases that are provided *via* packages, such as the `EnsDb.Hsapiens.v75` package. In addition, `ensembldb` allows to switch the backend from SQLite to MySQL and thus to retrieve annotations from a MySQL server instead. Such a setup might be useful for a lab running a well-configured MySQL server that would require installation of EnsDb databases only on the database server and not on the individual clients. **Note** the code in this document is not executed during vignette generation as this would require access to a MySQL server. # Using `ensembldb` with a MySQL server Installation of `EnsDb` databases in a MySQL server is straight forward - given that the user has write access to the server: ```{r eval = FALSE } library(ensembldb) ## Load the EnsDb package that should be installed on the MySQL server library(EnsDb.Hsapiens.v75) ## Call the useMySQL method providing the required credentials to create ## databases and inserting data on the MySQL server edb_mysql <- useMySQL(EnsDb.Hsapiens.v75, host = "localhost", user = "userwrite", pass = "userpass") ## Use this EnsDb object genes(edb_mysql) ``` To use an `EnsDb` in a MySQL server without the need to install the corresponding R-package, the connection to the database can be passed to the `EnsDb` constructor function. With the resulting `EnsDb` object annotations can be retrieved from the MySQL database. ```{r eval = FALSE } library(ensembldb) library(RMySQL) ## Connect to the MySQL database to list the databases. dbcon <- dbConnect(MySQL(), host = "localhost", user = "readonly", pass = "readonly") ## List the available databases listEnsDbs(dbcon) ## Connect to one of the databases and use that one. dbcon <- dbConnect(MySQL(), host = "localhost", user = "readonly", pass = "readonly", dbname = "ensdb_hsapiens_v75") edb <- EnsDb(dbcon) edb ``` ensembldb/inst/doc/MySQL-backend.html0000644000175400017540000325213713241155654020520 0ustar00biocbuildbiocbuild Using a MySQL server backend

1 Introduction

ensembldb uses by default, similar to other annotation packages in Bioconductor, a SQLite database backend, i.e. annotations are retrieved from file-based SQLite databases that are provided via packages, such as the EnsDb.Hsapiens.v75 package. In addition, ensembldb allows to switch the backend from SQLite to MySQL and thus to retrieve annotations from a MySQL server instead. Such a setup might be useful for a lab running a well-configured MySQL server that would require installation of EnsDb databases only on the database server and not on the individual clients.

Note the code in this document is not executed during vignette generation as this would require access to a MySQL server.

2 Using ensembldb with a MySQL server

Installation of EnsDb databases in a MySQL server is straight forward - given that the user has write access to the server:

library(ensembldb)
## Load the EnsDb package that should be installed on the MySQL server
library(EnsDb.Hsapiens.v75)

## Call the useMySQL method providing the required credentials to create
## databases and inserting data on the MySQL server
edb_mysql <- useMySQL(EnsDb.Hsapiens.v75, host = "localhost", user = "userwrite",
                      pass = "userpass")

## Use this EnsDb object
genes(edb_mysql)

To use an EnsDb in a MySQL server without the need to install the corresponding R-package, the connection to the database can be passed to the EnsDb constructor function. With the resulting EnsDb object annotations can be retrieved from the MySQL database.

library(ensembldb)
library(RMySQL)

## Connect to the MySQL database to list the databases.
dbcon <- dbConnect(MySQL(), host = "localhost", user = "readonly",
                   pass = "readonly")

## List the available databases
listEnsDbs(dbcon)

## Connect to one of the databases and use that one.
dbcon <- dbConnect(MySQL(), host = "localhost", user = "readonly",
                   pass = "readonly", dbname = "ensdb_hsapiens_v75")
edb <- EnsDb(dbcon)
edb
ensembldb/inst/doc/ensembldb.R0000644000175400017540000004123313241155725017343 0ustar00biocbuildbiocbuild## ----load-libs, warning=FALSE, message=FALSE------------------------------- library(EnsDb.Hsapiens.v75) ## Making a "short cut" edb <- EnsDb.Hsapiens.v75 ## print some informations for this package edb ## For what organism was the database generated? organism(edb) ## ----no-network, echo = FALSE, results = "hide"---------------------------- ## Disable code chunks that require network connection - conditionally ## disable this on Windows only. This is to avoid TIMEOUT errors on the ## Bioconductor Windows build maching (issue #47). use_network <- FALSE ## ----filters--------------------------------------------------------------- supportedFilters(edb) ## ----transcripts----------------------------------------------------------- Tx <- transcripts(edb, filter = list(GenenameFilter("BCL2L11"))) Tx ## as this is a GRanges object we can access e.g. the start coordinates with head(start(Tx)) ## or extract the biotype with head(Tx$tx_biotype) ## ----transcripts-filter-expression----------------------------------------- ## Use a filter expression to perform the filtering. transcripts(edb, filter = ~ genename == "ZBTB16") ## ----transcripts-filter---------------------------------------------------- library(magrittr) filter(edb, ~ symbol == "BCL2" & tx_biotype != "protein_coding") %>% transcripts ## ----filter-Y-------------------------------------------------------------- edb_y <- addFilter(edb, SeqNameFilter("Y")) ## All subsequent filters on that EnsDb will only work on features encoded on ## chromosome Y genes(edb_y) ## Get all lincRNAs on chromosome Y genes(edb_y, filter = ~ gene_biotype == "lincRNA") ## ----list-columns---------------------------------------------------------- ## list all database tables along with their columns listTables(edb) ## list columns from a specific table listColumns(edb, "tx") ## ----transcripts-example2-------------------------------------------------- Tx <- transcripts(edb, columns = c(listColumns(edb , "tx"), "gene_name"), filter = TxBiotypeFilter("nonsense_mediated_decay"), return.type = "DataFrame") nrow(Tx) Tx ## ----cdsBy----------------------------------------------------------------- yCds <- cdsBy(edb, filter = SeqNameFilter("Y")) yCds ## ----genes-GRangesFilter--------------------------------------------------- ## Define the filter grf <- GRangesFilter(GRanges("11", ranges = IRanges(114000000, 114000050), strand = "+"), type = "any") ## Query genes: gn <- genes(edb, filter = grf) gn ## Next we retrieve all transcripts for that gene so that we can plot them. txs <- transcripts(edb, filter = GenenameFilter(gn$gene_name)) ## ----tx-for-zbtb16, message=FALSE, fig.align='center', fig.width=7.5, fig.height=5---- plot(3, 3, pch = NA, xlim = c(start(gn), end(gn)), ylim = c(0, length(txs)), yaxt = "n", ylab = "") ## Highlight the GRangesFilter region rect(xleft = start(grf), xright = end(grf), ybottom = 0, ytop = length(txs), col = "red", border = "red") for(i in 1:length(txs)) { current <- txs[i] rect(xleft = start(current), xright = end(current), ybottom = i-0.975, ytop = i-0.125, border = "grey") text(start(current), y = i-0.5, pos = 4, cex = 0.75, labels = current$tx_id) } ## ----transcripts-GRangesFilter--------------------------------------------- transcripts(edb, filter = grf) ## ----biotypes-------------------------------------------------------------- ## Get all gene biotypes from the database. The GeneBiotypeFilter ## allows to filter on these values. listGenebiotypes(edb) ## Get all transcript biotypes from the database. listTxbiotypes(edb) ## ----genes-BCL2------------------------------------------------------------ ## We're going to fetch all genes which names start with BCL. To this end ## we define a GenenameFilter with partial matching, i.e. condition "like" ## and a % for any character/string. BCLs <- genes(edb, columns = c("gene_name", "entrezid", "gene_biotype"), filter = GenenameFilter("BCL", condition = "startsWith"), return.type = "DataFrame") nrow(BCLs) BCLs ## ----example-AnnotationFilterList------------------------------------------ ## determine the average length of snRNA, snoRNA and rRNA genes encoded on ## chromosomes X and Y. mean(lengthOf(edb, of = "tx", filter = AnnotationFilterList( GeneBiotypeFilter(c("snRNA", "snoRNA", "rRNA")), SeqNameFilter(c("X", "Y"))))) ## determine the average length of protein coding genes encoded on the same ## chromosomes. mean(lengthOf(edb, of = "tx", filter = ~ gene_biotype == "protein_coding" & seq_name %in% c("X", "Y"))) ## ----example-first-two-exons----------------------------------------------- ## Extract all exons 1 and (if present) 2 for all genes encoded on the ## Y chromosome exons(edb, columns = c("tx_id", "exon_idx"), filter = list(SeqNameFilter("Y"), ExonRankFilter(3, condition = "<"))) ## ----transcriptsBy-X-Y----------------------------------------------------- TxByGns <- transcriptsBy(edb, by = "gene", filter = SeqNameFilter(c("X", "Y"))) TxByGns ## ----exonsBy-RNAseq, message = FALSE, eval = FALSE------------------------- # ## will just get exons for all genes on chromosomes 1 to 22, X and Y. # ## Note: want to get rid of the "LRG" genes!!! # EnsGenes <- exonsBy(edb, by = "gene", filter = AnnotationFilterList( # SeqNameFilter(c(1:22, "X", "Y")), # GeneIdFilter("ENSG", "startsWith"))) # ## ----toSAF-RNAseq, message = FALSE, eval=FALSE----------------------------- # ## Transforming the GRangesList into a data.frame in SAF format # EnsGenes.SAF <- toSAF(EnsGenes) # ## ----disjointExons, message = FALSE, eval=FALSE---------------------------- # ## Create a GRanges of non-overlapping exon parts. # DJE <- disjointExons(edb, filter = AnnotationFilterList( # SeqNameFilter(c(1:22, "X", "Y")), # GeneIdFilter("ENSG%", "startsWith"))) # ## ----transcript-sequence-AnnotationHub, message = FALSE, eval = FALSE------ # library(EnsDb.Hsapiens.v75) # library(Rsamtools) # edb <- EnsDb.Hsapiens.v75 # # ## Get the FaFile with the genomic sequence matching the Ensembl version # ## using the AnnotationHub package. # Dna <- getGenomeFaFile(edb) # # ## Get start/end coordinates of all genes. # genes <- genes(edb) # ## Subset to all genes that are encoded on chromosomes for which # ## we do have DNA sequence available. # genes <- genes[seqnames(genes) %in% seqnames(seqinfo(Dna))] # # ## Get the gene sequences, i.e. the sequence including the sequence of # ## all of the gene's exons and introns. # geneSeqs <- getSeq(Dna, genes) # ## ----transcript-sequence-extractTranscriptSeqs, message = FALSE, eval = FALSE---- # ## get all exons of all transcripts encoded on chromosome Y # yTx <- exonsBy(edb, filter = SeqNameFilter("Y")) # # ## Retrieve the sequences for these transcripts from the FaFile. # library(GenomicFeatures) # yTxSeqs <- extractTranscriptSeqs(Dna, yTx) # yTxSeqs # # ## Extract the sequences of all transcripts encoded on chromosome Y. # yTx <- extractTranscriptSeqs(Dna, edb, filter = SeqNameFilter("Y")) # # ## Along these lines, we could use the method also to retrieve the coding sequence # ## of all transcripts on the Y chromosome. # cdsY <- cdsBy(edb, filter = SeqNameFilter("Y")) # extractTranscriptSeqs(Dna, cdsY) # ## ----seqlevelsStyle, message = FALSE--------------------------------------- ## Change the seqlevels style form Ensembl (default) to UCSC: seqlevelsStyle(edb) <- "UCSC" ## Now we can use UCSC style seqnames in SeqNameFilters or GRangesFilter: genesY <- genes(edb, filter = ~ seq_name == "chrY") ## The seqlevels of the returned GRanges are also in UCSC style seqlevels(genesY) ## ----seqlevelsStyle-2, message = FALSE------------------------------------- seqlevelsStyle(edb) <- "UCSC" ## Getting the default option: getOption("ensembldb.seqnameNotFound") ## Listing all seqlevels in the database. seqlevels(edb)[1:30] ## Setting the option to NA, thus, for each seqname for which no mapping is available, ## NA is returned. options(ensembldb.seqnameNotFound=NA) seqlevels(edb)[1:30] ## Resetting the option. options(ensembldb.seqnameNotFound = "ORIGINAL") ## ----extractTranscriptSeqs-BSGenome, warning = FALSE, message = FALSE------ library(BSgenome.Hsapiens.UCSC.hg19) bsg <- BSgenome.Hsapiens.UCSC.hg19 ## Get the genome version unique(genome(bsg)) unique(genome(edb)) ## Although differently named, both represent genome build GRCh37. ## Extract the full transcript sequences. yTxSeqs <- extractTranscriptSeqs(bsg, exonsBy(edb, "tx", filter = SeqNameFilter("chrY"))) yTxSeqs ## Extract just the CDS Test <- cdsBy(edb, "tx", filter = SeqNameFilter("chrY")) yTxCds <- extractTranscriptSeqs(bsg, cdsBy(edb, "tx", filter = SeqNameFilter("chrY"))) yTxCds ## ----seqlevelsStyle-restore------------------------------------------------ seqlevelsStyle(edb) <- "Ensembl" ## ----gviz-plot, message=FALSE, fig.align='center', fig.width=7.5, fig.height=2.3---- ## Loading the Gviz library library(Gviz) library(EnsDb.Hsapiens.v75) edb <- EnsDb.Hsapiens.v75 ## Retrieving a Gviz compatible GRanges object with all genes ## encoded on chromosome Y. gr <- getGeneRegionTrackForGviz(edb, chromosome = "Y", start = 20400000, end = 21400000) ## Define a genome axis track gat <- GenomeAxisTrack() ## We have to change the ucscChromosomeNames option to FALSE to enable Gviz usage ## with non-UCSC chromosome names. options(ucscChromosomeNames = FALSE) plotTracks(list(gat, GeneRegionTrack(gr))) options(ucscChromosomeNames = TRUE) ## ----message=FALSE--------------------------------------------------------- seqlevelsStyle(edb) <- "UCSC" ## Retrieving the GRanges objects with seqnames corresponding to UCSC chromosome names. gr <- getGeneRegionTrackForGviz(edb, chromosome = "chrY", start = 20400000, end = 21400000) seqnames(gr) ## Define a genome axis track gat <- GenomeAxisTrack() plotTracks(list(gat, GeneRegionTrack(gr))) ## ----gviz-separate-tracks, message=FALSE, warning=FALSE, fig.align='center', fig.width=7.5, fig.height=2.25---- protCod <- getGeneRegionTrackForGviz(edb, chromosome = "chrY", start = 20400000, end = 21400000, filter = GeneBiotypeFilter("protein_coding")) lincs <- getGeneRegionTrackForGviz(edb, chromosome = "chrY", start = 20400000, end = 21400000, filter = GeneBiotypeFilter("lincRNA")) plotTracks(list(gat, GeneRegionTrack(protCod, name = "protein coding"), GeneRegionTrack(lincs, name = "lincRNAs")), transcriptAnnotation = "symbol") ## At last we change the seqlevels style again to Ensembl seqlevelsStyle <- "Ensembl" ## ----pplot-plot, message=FALSE, fig.align='center', fig.width=7.5, fig.height=4---- library(ggbio) ## Create a plot for all transcripts of the gene SKA2 autoplot(edb, ~ genename == "SKA2") ## ----pplot-plot-2, message=FALSE, fig.align='center', fig.width=7.5, fig.height=4---- ## Get the chromosomal region in which the gene is encoded ska2 <- genes(edb, filter = ~ genename == "SKA2") strand(ska2) <- "*" autoplot(edb, GRangesFilter(ska2), names.expr = "gene_name") ## ----AnnotationDbi, message = FALSE---------------------------------------- library(EnsDb.Hsapiens.v75) edb <- EnsDb.Hsapiens.v75 ## List all available columns in the database. columns(edb) ## Note that these do *not* correspond to the actual column names ## of the database that can be passed to methods like exons, genes, ## transcripts etc. These column names can be listed with the listColumns ## method. listColumns(edb) ## List all of the supported key types. keytypes(edb) ## Get all gene ids from the database. gids <- keys(edb, keytype = "GENEID") length(gids) ## Get all gene names for genes encoded on chromosome Y. gnames <- keys(edb, keytype = "GENENAME", filter = SeqNameFilter("Y")) head(gnames) ## ----select, message = FALSE, warning=FALSE-------------------------------- ## Use the /standard/ way to fetch data. select(edb, keys = c("BCL2", "BCL2L11"), keytype = "GENENAME", columns = c("GENEID", "GENENAME", "TXID", "TXBIOTYPE")) ## Use the filtering system of ensembldb select(edb, keys = ~ genename %in% c("BCL2", "BCL2L11") & tx_biotype == "protein_coding", columns = c("GENEID", "GENENAME", "TXID", "TXBIOTYPE")) ## ----mapIds, message = FALSE----------------------------------------------- ## Use the default method, which just returns the first value for multi mappings. mapIds(edb, keys = c("BCL2", "BCL2L11"), column = "TXID", keytype = "GENENAME") ## Alternatively, specify multiVals="list" to return all mappings. mapIds(edb, keys = c("BCL2", "BCL2L11"), column = "TXID", keytype = "GENENAME", multiVals = "list") ## And, just like before, we can use filters to map only to protein coding transcripts. mapIds(edb, keys = list(GenenameFilter(c("BCL2", "BCL2L11")), TxBiotypeFilter("protein_coding")), column = "TXID", multiVals = "list") ## ----AnnotationHub-query, message = FALSE, eval = use_network-------------- # library(AnnotationHub) # ## Load the annotation resource. # ah <- AnnotationHub() # # ## Query for all available EnsDb databases # query(ah, "EnsDb") # ## ----AnnotationHub-query-2, message = FALSE, eval = use_network------------ # ahDb <- query(ah, pattern = c("Xiphophorus Maculatus", "EnsDb", 87)) # ## What have we got # ahDb # ## ----AnnotationHub-fetch, message = FALSE, eval = FALSE-------------------- # ahEdb <- ahDb[[1]] # # ## retriebe all genes # gns <- genes(ahEdb) # ## ----edb-from-ensembl, message = FALSE, eval = FALSE----------------------- # library(ensembldb) # # ## get all human gene/transcript/exon annotations from Ensembl (75) # ## the resulting tables will be stored by default to the current working # ## directory # fetchTablesFromEnsembl(75, species = "human") # # ## These tables can then be processed to generate a SQLite database # ## containing the annotations (again, the function assumes the required # ## txt files to be present in the current working directory) # DBFile <- makeEnsemblSQLiteFromTables() # # ## and finally we can generate the package # makeEnsembldbPackage(ensdb = DBFile, version = "0.99.12", # maintainer = "Johannes Rainer ", # author = "J Rainer") # ## ----gtf-gff-edb, message = FALSE, eval = FALSE---------------------------- # ## Load the AnnotationHub data. # library(AnnotationHub) # ah <- AnnotationHub() # # ## Query all available files for Ensembl release 77 for # ## Mus musculus. # query(ah, c("Mus musculus", "release-77")) # # ## Get the resource for the gtf file with the gene/transcript definitions. # Gtf <- ah["AH28822"] # ## Create a EnsDb database file from this. # DbFile <- ensDbFromAH(Gtf) # ## We can either generate a database package, or directly load the data # edb <- EnsDb(DbFile) # # # ## Identify and get the FaFile object with the genomic DNA sequence matching # ## the EnsDb annotation. # Dna <- getGenomeFaFile(edb) # library(Rsamtools) # ## We next retrieve the sequence of all exons on chromosome Y. # exons <- exons(edb, filter = SeqNameFilter("Y")) # exonSeq <- getSeq(Dna, exons) # # ## Alternatively, look up and retrieve the toplevel DNA sequence manually. # Dna <- ah[["AH22042"]] # ## ----EnsDb-from-Y-GRanges, message = FALSE, eval = use_network------------- # ## Generate a sqlite database from a GRanges object specifying # ## genes encoded on chromosome Y # load(system.file("YGRanges.RData", package = "ensembldb")) # Y # # ## Create the EnsDb database file # DB <- ensDbFromGRanges(Y, path = tempdir(), version = 75, # organism = "Homo_sapiens") # # ## Load the database # edb <- EnsDb(DB) # edb # ## ----EnsDb-from-GTF, message = FALSE, eval = FALSE------------------------- # library(ensembldb) # # ## the GTF file can be downloaded from # ## ftp://ftp.ensembl.org/pub/release-75/gtf/homo_sapiens/ # gtffile <- "Homo_sapiens.GRCh37.75.gtf.gz" # ## generate the SQLite database file # DB <- ensDbFromGtf(gtf = gtffile) # # ## load the DB file directly # EDB <- EnsDb(DB) # # ## alternatively, build the annotation package # ## and finally we can generate the package # makeEnsembldbPackage(ensdb = DB, version = "0.99.12", # maintainer = "Johannes Rainer ", # author = "J Rainer") # ensembldb/inst/doc/ensembldb.Rmd0000644000175400017540000014012513175714743017673 0ustar00biocbuildbiocbuild--- title: "Generating an using Ensembl based annotation packages" author: "Johannes Rainer" graphics: yes package: ensembldb output: BiocStyle::html_document: toc_float: true vignette: > %\VignetteIndexEntry{Generating an using Ensembl based annotation packages} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} %\VignetteDepends{ensembldb,EnsDb.Hsapiens.v75,BiocStyle,AnnotationHub,ggbio,Gviz,magrittr} --- # Introduction The `ensembldb` package provides functions to create and use transcript centric annotation databases/packages. The annotation for the databases are directly fetched from Ensembl 1 using their Perl API. The functionality and data is similar to that of the `TxDb` packages from the `GenomicFeatures` package, but, in addition to retrieve all gene/transcript models and annotations from the database, the `ensembldb` package provides also a filter framework allowing to retrieve annotations for specific entries like genes encoded on a chromosome region or transcript models of lincRNA genes. From version 1.7 on, `EnsDb` databases created by the `ensembldb` package contain also protein annotation data (see Section [11](#org5bd9a97) for the database layout and an overview of available attributes/columns). For more information on the use of the protein annotations refer to the *proteins* vignette. Another main goal of this package is to generate *versioned* annotation packages, i.e. annotation packages that are build for a specific Ensembl release, and are also named according to that (e.g. `EnsDb.Hsapiens.v75` for human gene definitions of the Ensembl code database version 75). This ensures reproducibility, as it allows to load annotations from a specific Ensembl release also if newer versions of annotation packages/releases are available. It also allows to load multiple annotation packages at the same time in order to e.g. compare gene models between Ensembl releases. In the example below we load an Ensembl based annotation package for Homo sapiens, Ensembl version 75. The `EnsDb` object providing access to the underlying SQLite database is bound to the variable name `EnsDb.Hsapiens.v75`. ```{r load-libs, warning=FALSE, message=FALSE } library(EnsDb.Hsapiens.v75) ## Making a "short cut" edb <- EnsDb.Hsapiens.v75 ## print some informations for this package edb ## For what organism was the database generated? organism(edb) ``` ```{r no-network, echo = FALSE, results = "hide" } ## Disable code chunks that require network connection - conditionally ## disable this on Windows only. This is to avoid TIMEOUT errors on the ## Bioconductor Windows build maching (issue #47). use_network <- FALSE ``` # Using `ensembldb` annotation packages to retrieve specific annotations One of the strengths of the `ensembldb` package and the related `EnsDb` databases is its implementation of a filter framework that enables to efficiently extract data sub-sets from the databases. The `ensembldb` package supports most of the filters defined in the `AnnotationFilter` Bioconductor package and defines some additional filters specific to the data stored in `EnsDb` databases. Filters can be passed directly to all methods extracting data from an `EnsDb` (such as `genes`, `transcripts` or `exons`). Alternatively it is possible with the `addFilter` or `filter` functions to add a filter directly to an `EnsDb` which will then be used in all queries on that object. The `supportedFilters` method can be used to get an overview over all supported filter classes, each of them (except the `GRangesFilter`) working on a single column/field in the database. ```{r filters } supportedFilters(edb) ``` These filters can be divided into 3 main filter types: - `IntegerFilter`: filter classes extending this basic object can take a single numeric value as input and support the conditions `=, !`, >, <, >= and <=. All filters that work on chromosomal coordinates, such as the `GeneEndFilter` extend `IntegerFilter`. - `CharacterFilter`: filter classes extending this object can take a single or multiple character values as input and allow conditions: `=, !`, "startsWith" and "endsWith". All filters working on IDs extend this class. - `GRangesFilter`: takes a `GRanges` object as input and supports all conditions that `findOverlaps` from the `IRanges` package supports ("any", "start", "end", "within", "equal"). Note that these have to be passed using the parameter `type` to the constructor function. The supported filters are: - `EntrezFilter`: allows to filter results based on NCBI Entrezgene identifiers of the genes. - `ExonEndFilter`: filter using the chromosomal end coordinate of exons. - `ExonIdFilter`: filter based on the (Ensembl) exon identifiers. - `ExonRankFilter`: filter based on the rank (index) of an exon within the transcript model. Exons are always numbered from 5' to 3' end of the transcript, thus, also on the reverse strand, the exon 1 is the most 5' exon of the transcript. - `ExonStartFilter`: filter using the chromosomal start coordinate of exons. - `GeneBiotypeFilter`: filter using the gene biotypes defined in the Ensembl database; use the `listGenebiotypes` method to list all available biotypes. - `GeneEndFilter`: filter using the chromosomal end coordinate of gene. - `GeneIdFilter`: filter based on the Ensembl gene IDs. - `GenenameFilter`: filter based on the names (symbols) of the genes. - `GeneStartFilter`: filter using the chromosomal start coordinate of gene. - `GRangesFilter`: allows to retrieve all features (genes, transcripts or exons) that are either within (setting parameter `type` to "within") or partially overlapping (setting `type` to "any") the defined genomic region/range. Note that, depending on the called method (`genes`, `transcripts` or `exons`) the start and end coordinates of either the genes, transcripts or exons are used for the filter. For methods `exonsBy`, `cdsBy` and `txBy` the coordinates of `by` are used. - `SeqNameFilter`: filter by the name of the chromosomes the genes are encoded on. - `SeqStrandFilter`: filter for the chromosome strand on which the genes are encoded. - `SymbolFilter`: filter on gene symbols; note that no database columns *symbol* is available in an `EnsDb` database and hence the gene name is used for filtering. - `TxBiotypeFilter`: filter on the transcript biotype defined in Ensembl; use the `listTxbiotypes` method to list all available biotypes. - `TxEndFilter`: filter using the chromosomal end coordinate of transcripts. - `TxIdFilter`: filter on the Ensembl transcript identifiers. - `TxNameFilter`: filter on the Ensembl transcript names (currently identical to the transcript IDs). - `TxStartFilter`: filter using the chromosomal start coordinate of transcripts. In addition to the above listed *DNA-RNA-based* filters, *protein-specific* filters are also available: - `ProtDomIdFilter`: filter by the protein domain ID. - `ProteinIdFilter`: filter by Ensembl protein ID filters. - `UniprotDbFilter`: filter by the name of the Uniprot database. - `UniprotFilter`: filter by the Uniprot ID. - `UniprotMappingTypeFilter`: filter by the mapping type of Ensembl protein IDs to Uniprot IDs. These can however only be used on `EnsDb` databases that provide protein annotations, i.e. for which a call to `hasProteinData` returns `TRUE`. `EnsDb` databases for more recent Ensembl versions (starting from Ensembl 87) provide also evidence levels for individual transcripts in the `tx_support_level` database column. Such databases support also a `TxSupportLevelFilter` filter to use this columns for filtering. A simple use case for the filter framework would be to get all transcripts for the gene *BCL2L11*. To this end we specify a `GenenameFilter` with the value *BCL2L11*. As a result we get a `GRanges` object with `start`, `end`, `strand` and `seqname` being the start coordinate, end coordinate, chromosome name and strand for the respective transcripts. All additional annotations are available as metadata columns. Alternatively, by setting `return.type` to "DataFrame", or "data.frame" the method would return a `DataFrame` or `data.frame` object instead of the default `GRanges`. ```{r transcripts } Tx <- transcripts(edb, filter = list(GenenameFilter("BCL2L11"))) Tx ## as this is a GRanges object we can access e.g. the start coordinates with head(start(Tx)) ## or extract the biotype with head(Tx$tx_biotype) ``` The parameter `columns` of the extractor methods (such as `exons`, `genes` or `transcripts)` allows to specify which database attributes (columns) should be retrieved. The `exons` method returns by default all exon-related columns, the `transcripts` all columns from the transcript database table and the `genes` all from the gene table. Note however that in the example above we got also a column `gene_name` although this column is not present in the transcript database table. By default the methods return also all columns that are used by any of the filters submitted with the `filter` argument (thus, because a `GenenameFilter` was used, the column `gene_name` is also returned). Setting `returnFilterColumns(edb) <- FALSE` disables this option and only the columns specified by the `columns` parameter are retrieved. Instead of passing a filter *object* to the method it is also possible to provide a filter *expression* written as a `formula`. The `formula` has to be written in the form `~ ` with `` being the field (database column) in the database, `` the condition for the filter object and `` its value. Use the `supportedFilter` method to get the field names corresponding to each filter class. ```{r transcripts-filter-expression } ## Use a filter expression to perform the filtering. transcripts(edb, filter = ~ genename == "ZBTB16") ``` Filter expression have to be written as a formula (i.e. starting with a `~`) in the form *column name* followed by the logical condition. Alternatively, `EnsDb` objects can be filtered directly using the `filter` function. In the example below we use the `filter` function to filter the `EnsDb` object and pass that filtered database to the `transcripts` method using the `%>%` from the `magrittr` package. ```{r transcripts-filter } library(magrittr) filter(edb, ~ symbol == "BCL2" & tx_biotype != "protein_coding") %>% transcripts ``` Adding a filter to an `EnsDb` enables this filter (globally) on all subsequent queries on that object. We could thus filter an `EnsDb` to (virtually) contain only features encoded on chromosome Y. ```{r filter-Y } edb_y <- addFilter(edb, SeqNameFilter("Y")) ## All subsequent filters on that EnsDb will only work on features encoded on ## chromosome Y genes(edb_y) ## Get all lincRNAs on chromosome Y genes(edb_y, filter = ~ gene_biotype == "lincRNA") ``` To get an overview of database tables and available columns the function `listTables` can be used. The method `listColumns` on the other hand lists columns for the specified database table. ```{r list-columns } ## list all database tables along with their columns listTables(edb) ## list columns from a specific table listColumns(edb, "tx") ``` Thus, we could retrieve all transcripts of the biotype *nonsense\_mediated\_decay* (which, according to the definitions by Ensembl are transcribed, but most likely not translated in a protein, but rather degraded after transcription) along with the name of the gene for each transcript. Note that we are changing here the `return.type` to `DataFrame`, so the method will return a `DataFrame` with the results instead of the default `GRanges`. ```{r transcripts-example2 } Tx <- transcripts(edb, columns = c(listColumns(edb , "tx"), "gene_name"), filter = TxBiotypeFilter("nonsense_mediated_decay"), return.type = "DataFrame") nrow(Tx) Tx ``` For protein coding transcripts, we can also specifically extract their coding region. In the example below we extract the CDS for all transcripts encoded on chromosome Y. ```{r cdsBy } yCds <- cdsBy(edb, filter = SeqNameFilter("Y")) yCds ``` Using a `GRangesFilter` we can retrieve all features from the database that are either within or overlapping the specified genomic region. In the example below we query all genes that are partially overlapping with a small region on chromosome 11. The filter restricts to all genes for which either an exon or an intron is partially overlapping with the region. ```{r genes-GRangesFilter } ## Define the filter grf <- GRangesFilter(GRanges("11", ranges = IRanges(114000000, 114000050), strand = "+"), type = "any") ## Query genes: gn <- genes(edb, filter = grf) gn ## Next we retrieve all transcripts for that gene so that we can plot them. txs <- transcripts(edb, filter = GenenameFilter(gn$gene_name)) ``` ```{r tx-for-zbtb16, message=FALSE, fig.align='center', fig.width=7.5, fig.height=5 } plot(3, 3, pch = NA, xlim = c(start(gn), end(gn)), ylim = c(0, length(txs)), yaxt = "n", ylab = "") ## Highlight the GRangesFilter region rect(xleft = start(grf), xright = end(grf), ybottom = 0, ytop = length(txs), col = "red", border = "red") for(i in 1:length(txs)) { current <- txs[i] rect(xleft = start(current), xright = end(current), ybottom = i-0.975, ytop = i-0.125, border = "grey") text(start(current), y = i-0.5, pos = 4, cex = 0.75, labels = current$tx_id) } ``` As we can see, 4 transcripts of the gene ZBTB16 are also overlapping the region. Below we fetch these 4 transcripts. Note, that a call to `exons` will not return any features from the database, as no exon is overlapping with the region. ```{r transcripts-GRangesFilter } transcripts(edb, filter = grf) ``` The `GRangesFilter` supports also `GRanges` defining multiple regions and a query will return all features overlapping any of these regions. Besides using the `GRangesFilter` it is also possible to search for transcripts or exons overlapping genomic regions using the `exonsByOverlaps` or `transcriptsByOverlaps` known from the `GenomicFeatures` package. Note that the implementation of these methods for `EnsDb` objects supports also to use filters to further fine-tune the query. The functions `listGenebiotypes` and `listTxbiotypes` can be used to get an overview of allowed/available gene and transcript biotype ```{r biotypes } ## Get all gene biotypes from the database. The GeneBiotypeFilter ## allows to filter on these values. listGenebiotypes(edb) ## Get all transcript biotypes from the database. listTxbiotypes(edb) ``` Data can be fetched in an analogous way using the `exons` and `genes` methods. In the example below we retrieve `gene_name`, `entrezid` and the `gene_biotype` of all genes in the database which names start with "BCL2". ```{r genes-BCL2 } ## We're going to fetch all genes which names start with BCL. To this end ## we define a GenenameFilter with partial matching, i.e. condition "like" ## and a % for any character/string. BCLs <- genes(edb, columns = c("gene_name", "entrezid", "gene_biotype"), filter = GenenameFilter("BCL", condition = "startsWith"), return.type = "DataFrame") nrow(BCLs) BCLs ``` Sometimes it might be useful to know the length of genes or transcripts (i.e. the total sum of nucleotides covered by their exons). Below we calculate the mean length of transcripts from protein coding genes on chromosomes X and Y as well as the average length of snoRNA, snRNA and rRNA transcripts encoded on these chromosomes. For the first query we combine two `AnnotationFilter` objects using an `AnnotationFilterList` object, in the second we define the query using a filter expression. ```{r example-AnnotationFilterList } ## determine the average length of snRNA, snoRNA and rRNA genes encoded on ## chromosomes X and Y. mean(lengthOf(edb, of = "tx", filter = AnnotationFilterList( GeneBiotypeFilter(c("snRNA", "snoRNA", "rRNA")), SeqNameFilter(c("X", "Y"))))) ## determine the average length of protein coding genes encoded on the same ## chromosomes. mean(lengthOf(edb, of = "tx", filter = ~ gene_biotype == "protein_coding" & seq_name %in% c("X", "Y"))) ``` Not unexpectedly, transcripts of protein coding genes are longer than those of snRNA, snoRNA or rRNA genes. At last we extract the first two exons of each transcript model from the database. ```{r example-first-two-exons } ## Extract all exons 1 and (if present) 2 for all genes encoded on the ## Y chromosome exons(edb, columns = c("tx_id", "exon_idx"), filter = list(SeqNameFilter("Y"), ExonRankFilter(3, condition = "<"))) ``` # Extracting gene/transcript/exon models for RNASeq feature counting For the feature counting step of an RNAseq experiment, the gene or transcript models (defined by the chromosomal start and end positions of their exons) have to be known. To extract these from an Ensembl based annotation package, the `exonsBy`, `genesBy` and `transcriptsBy` methods can be used in an analogous way as in `TxDb` packages generated by the `GenomicFeatures` package. However, the `transcriptsBy` method does not, in contrast to the method in the `GenomicFeatures` package, allow to return transcripts by "cds". While the annotation packages built by the `ensembldb` contain the chromosomal start and end coordinates of the coding region (for protein coding genes) they do not assign an ID to each CDS. A simple use case is to retrieve all genes encoded on chromosomes X and Y from the database. ```{r transcriptsBy-X-Y } TxByGns <- transcriptsBy(edb, by = "gene", filter = SeqNameFilter(c("X", "Y"))) TxByGns ``` Since Ensembl contains also definitions of genes that are on chromosome variants (supercontigs), it is advisable to specify the chromosome names for which the gene models should be returned. In a real use case, we might thus want to retrieve all genes encoded on the *standard* chromosomes. In addition it is advisable to use a `GeneIdFilter` to restrict to Ensembl genes only, as also *LRG* (Locus Reference Genomic) genes2 are defined in the database, which are partially redundant with Ensembl genes. ```{r exonsBy-RNAseq, message = FALSE, eval = FALSE } ## will just get exons for all genes on chromosomes 1 to 22, X and Y. ## Note: want to get rid of the "LRG" genes!!! EnsGenes <- exonsBy(edb, by = "gene", filter = AnnotationFilterList( SeqNameFilter(c(1:22, "X", "Y")), GeneIdFilter("ENSG", "startsWith"))) ``` The code above returns a `GRangesList` that can be used directly as an input for the `summarizeOverlaps` function from the `GenomicAlignments` package 3. Alternatively, the above `GRangesList` can be transformed to a `data.frame` in *SAF* format that can be used as an input to the `featureCounts` function of the `Rsubread` package 4. ```{r toSAF-RNAseq, message = FALSE, eval=FALSE } ## Transforming the GRangesList into a data.frame in SAF format EnsGenes.SAF <- toSAF(EnsGenes) ``` Note that the ID by which the `GRangesList` is split is used in the SAF formatted `data.frame` as the `GeneID`. In the example below this would be the Ensembl gene IDs, while the start, end coordinates (along with the strand and chromosomes) are those of the the exons. In addition, the `disjointExons` function (similar to the one defined in `GenomicFeatures`) can be used to generate a `GRanges` of non-overlapping exon parts which can be used in the `DEXSeq` package. ```{r disjointExons, message = FALSE, eval=FALSE } ## Create a GRanges of non-overlapping exon parts. DJE <- disjointExons(edb, filter = AnnotationFilterList( SeqNameFilter(c(1:22, "X", "Y")), GeneIdFilter("ENSG%", "startsWith"))) ``` # Retrieving sequences for gene/transcript/exon models The methods to retrieve exons, transcripts and genes (i.e. `exons`, `transcripts` and `genes`) return by default `GRanges` objects that can be used to retrieve sequences using the `getSeq` method e.g. from BSgenome packages. The basic workflow is thus identical to the one for `TxDb` packages, however, it is not straight forward to identify the BSgenome package with the matching genomic sequence. Most BSgenome packages are named according to the genome build identifier used in UCSC which does not (always) match the genome build name used by Ensembl. Using the Ensembl version provided by the `EnsDb`, the correct genomic sequence can however be retrieved easily from the `AnnotationHub` using the `getGenomeFaFile`. If no Fasta file matching the Ensembl version is available, the function tries to identify a Fasta file with the correct genome build from the *closest* Ensembl release and returns that instead. In the code block below we retrieve first the `FaFile` with the genomic DNA sequence, extract the genomic start and end coordinates for all genes defined in the package, subset to genes encoded on sequences available in the `FaFile` and extract all of their sequences. Note: these sequences represent the sequence between the chromosomal start and end coordinates of the gene. ```{r transcript-sequence-AnnotationHub, message = FALSE, eval = FALSE } library(EnsDb.Hsapiens.v75) library(Rsamtools) edb <- EnsDb.Hsapiens.v75 ## Get the FaFile with the genomic sequence matching the Ensembl version ## using the AnnotationHub package. Dna <- getGenomeFaFile(edb) ## Get start/end coordinates of all genes. genes <- genes(edb) ## Subset to all genes that are encoded on chromosomes for which ## we do have DNA sequence available. genes <- genes[seqnames(genes) %in% seqnames(seqinfo(Dna))] ## Get the gene sequences, i.e. the sequence including the sequence of ## all of the gene's exons and introns. geneSeqs <- getSeq(Dna, genes) ``` To retrieve the (exonic) sequence of transcripts (i.e. without introns) we can use directly the `extractTranscriptSeqs` method defined in the `GenomicFeatures` on the `EnsDb` object, eventually using a filter to restrict the query. ```{r transcript-sequence-extractTranscriptSeqs, message = FALSE, eval = FALSE } ## get all exons of all transcripts encoded on chromosome Y yTx <- exonsBy(edb, filter = SeqNameFilter("Y")) ## Retrieve the sequences for these transcripts from the FaFile. library(GenomicFeatures) yTxSeqs <- extractTranscriptSeqs(Dna, yTx) yTxSeqs ## Extract the sequences of all transcripts encoded on chromosome Y. yTx <- extractTranscriptSeqs(Dna, edb, filter = SeqNameFilter("Y")) ## Along these lines, we could use the method also to retrieve the coding sequence ## of all transcripts on the Y chromosome. cdsY <- cdsBy(edb, filter = SeqNameFilter("Y")) extractTranscriptSeqs(Dna, cdsY) ``` Note: in the next section we describe how transcript sequences can be retrieved from a `BSgenome` package that is based on UCSC, not Ensembl. # Integrating annotations from Ensembl based `EnsDb` packages with UCSC based annotations Sometimes it might be useful to combine (Ensembl based) annotations from `EnsDb` packages/objects with annotations from other Bioconductor packages, that might base on UCSC annotations. To support such an integration of annotations, the `ensembldb` packages implements the `seqlevelsStyle` and `seqlevelsStyle<-` from the `GenomeInfoDb` package that allow to change the style of chromosome naming. Thus, sequence/chromosome names other than those used by Ensembl can be used in, and are returned by, the queries to `EnsDb` objects as long as a mapping for them is provided by the `GenomeInfoDb` package (which provides a mapping mostly between UCSC, NCBI and Ensembl chromosome names for the *main* chromosomes). In the example below we change the seqnames style to UCSC. ```{r seqlevelsStyle, message = FALSE } ## Change the seqlevels style form Ensembl (default) to UCSC: seqlevelsStyle(edb) <- "UCSC" ## Now we can use UCSC style seqnames in SeqNameFilters or GRangesFilter: genesY <- genes(edb, filter = ~ seq_name == "chrY") ## The seqlevels of the returned GRanges are also in UCSC style seqlevels(genesY) ``` Note that in most instances no mapping is available for sequences not corresponding to the main chromosomes (i.e. contigs, patched chromosomes etc). What is returned in cases in which no mapping is available can be specified with the global `ensembldb.seqnameNotFound` option. By default (with `ensembldb.seqnameNotFound` set to "ORIGINAL"), the original seqnames (i.e. the ones from Ensembl) are returned. With `ensembldb.seqnameNotFound` "MISSING" each time a seqname can not be found an error is thrown. For all other cases (e.g. `ensembldb.seqnameNotFound = NA`) the value of the option is returned. ```{r seqlevelsStyle-2, message = FALSE } seqlevelsStyle(edb) <- "UCSC" ## Getting the default option: getOption("ensembldb.seqnameNotFound") ## Listing all seqlevels in the database. seqlevels(edb)[1:30] ## Setting the option to NA, thus, for each seqname for which no mapping is available, ## NA is returned. options(ensembldb.seqnameNotFound=NA) seqlevels(edb)[1:30] ## Resetting the option. options(ensembldb.seqnameNotFound = "ORIGINAL") ``` Next we retrieve transcript sequences from genes encoded on chromosome Y using the `BSGenome` package for the human genome from UCSC. The specified version `hg19` matches the genome build of Ensembl version 75, i.e. `GRCh37`. Note that while we changed the style of the seqnames to UCSC we did not change the naming of the genome release. ```{r extractTranscriptSeqs-BSGenome, warning = FALSE, message = FALSE } library(BSgenome.Hsapiens.UCSC.hg19) bsg <- BSgenome.Hsapiens.UCSC.hg19 ## Get the genome version unique(genome(bsg)) unique(genome(edb)) ## Although differently named, both represent genome build GRCh37. ## Extract the full transcript sequences. yTxSeqs <- extractTranscriptSeqs(bsg, exonsBy(edb, "tx", filter = SeqNameFilter("chrY"))) yTxSeqs ## Extract just the CDS Test <- cdsBy(edb, "tx", filter = SeqNameFilter("chrY")) yTxCds <- extractTranscriptSeqs(bsg, cdsBy(edb, "tx", filter = SeqNameFilter("chrY"))) yTxCds ``` At last changing the seqname style to the default value `"Ensembl"`. ```{r seqlevelsStyle-restore } seqlevelsStyle(edb) <- "Ensembl" ``` # Interactive annotation lookup using the `shiny` web app In addition to the `genes`, `transcripts` and `exons` methods it is possibly to search interactively for gene/transcript/exon annotations using the internal, `shiny` based, web application. The application can be started with the `runEnsDbApp()` function. The search results from this app can also be returned to the R workspace either as a `data.frame` or `GRanges` object. # Plotting gene/transcript features using `ensembldb` and `Gviz` and `ggbio` The `Gviz` package provides functions to plot genes and transcripts along with other data on a genomic scale. Gene models can be provided either as a `data.frame`, `GRanges`, `TxDB` database, can be fetched from biomart and can also be retrieved from `ensembldb`. Below we generate a `GeneRegionTrack` fetching all transcripts from a certain region on chromosome Y. Note that if we want in addition to work also with BAM files that were aligned against DNA sequences retrieved from Ensembl or FASTA files representing genomic DNA sequences from Ensembl we should change the `ucscChromosomeNames` option from `Gviz` to `FALSE` (i.e. by calling `options(ucscChromosomeNames = FALSE)`). This is not necessary if we just want to retrieve gene models from an `EnsDb` object, as the `ensembldb` package internally checks the `ucscChromosomeNames` option and, depending on that, maps Ensembl chromosome names to UCSC chromosome names. ```{r gviz-plot, message=FALSE, fig.align='center', fig.width=7.5, fig.height=2.3 } ## Loading the Gviz library library(Gviz) library(EnsDb.Hsapiens.v75) edb <- EnsDb.Hsapiens.v75 ## Retrieving a Gviz compatible GRanges object with all genes ## encoded on chromosome Y. gr <- getGeneRegionTrackForGviz(edb, chromosome = "Y", start = 20400000, end = 21400000) ## Define a genome axis track gat <- GenomeAxisTrack() ## We have to change the ucscChromosomeNames option to FALSE to enable Gviz usage ## with non-UCSC chromosome names. options(ucscChromosomeNames = FALSE) plotTracks(list(gat, GeneRegionTrack(gr))) options(ucscChromosomeNames = TRUE) ``` Above we had to change the option `ucscChromosomeNames` to `FALSE` in order to use it with non-UCSC chromosome names. Alternatively, we could however also change the `seqnamesStyle` of the `EnsDb` object to `UCSC`. Note that we have to use now also chromosome names in the *UCSC style* in the `SeqNameFilter` (i.e. "chrY" instead of `Y`). ```{r message=FALSE } seqlevelsStyle(edb) <- "UCSC" ## Retrieving the GRanges objects with seqnames corresponding to UCSC chromosome names. gr <- getGeneRegionTrackForGviz(edb, chromosome = "chrY", start = 20400000, end = 21400000) seqnames(gr) ## Define a genome axis track gat <- GenomeAxisTrack() plotTracks(list(gat, GeneRegionTrack(gr))) ``` We can also use the filters from the `ensembldb` package to further refine what transcripts are fetched, like in the example below, in which we create two different gene region tracks, one for protein coding genes and one for lincRNAs. ```{r gviz-separate-tracks, message=FALSE, warning=FALSE, fig.align='center', fig.width=7.5, fig.height=2.25 } protCod <- getGeneRegionTrackForGviz(edb, chromosome = "chrY", start = 20400000, end = 21400000, filter = GeneBiotypeFilter("protein_coding")) lincs <- getGeneRegionTrackForGviz(edb, chromosome = "chrY", start = 20400000, end = 21400000, filter = GeneBiotypeFilter("lincRNA")) plotTracks(list(gat, GeneRegionTrack(protCod, name = "protein coding"), GeneRegionTrack(lincs, name = "lincRNAs")), transcriptAnnotation = "symbol") ## At last we change the seqlevels style again to Ensembl seqlevelsStyle <- "Ensembl" ``` Alternatively, we can also use `ggbio` for plotting. For `ggplot` we can directly pass the `EnsDb` object along with optional filters (or as in the example below a filter expression as a `formula`). ```{r pplot-plot, message=FALSE, fig.align='center', fig.width=7.5, fig.height=4 } library(ggbio) ## Create a plot for all transcripts of the gene SKA2 autoplot(edb, ~ genename == "SKA2") ``` To plot the genomic region and plot genes from both strands we can use a `GRangesFilter`. ```{r pplot-plot-2, message=FALSE, fig.align='center', fig.width=7.5, fig.height=4 } ## Get the chromosomal region in which the gene is encoded ska2 <- genes(edb, filter = ~ genename == "SKA2") strand(ska2) <- "*" autoplot(edb, GRangesFilter(ska2), names.expr = "gene_name") ``` # Using `EnsDb` objects in the `AnnotationDbi` framework Most of the methods defined for objects extending the basic annotation package class `AnnotationDbi` are also defined for `EnsDb` objects (i.e. methods `columns`, `keytypes`, `keys`, `mapIds` and `select`). While these methods can be used analogously to basic annotation packages, the implementation for `EnsDb` objects also support the filtering framework of the `ensembldb` package. In the example below we first evaluate all the available columns and keytypes in the database and extract then the gene names for all genes encoded on chromosome X. ```{r AnnotationDbi, message = FALSE } library(EnsDb.Hsapiens.v75) edb <- EnsDb.Hsapiens.v75 ## List all available columns in the database. columns(edb) ## Note that these do *not* correspond to the actual column names ## of the database that can be passed to methods like exons, genes, ## transcripts etc. These column names can be listed with the listColumns ## method. listColumns(edb) ## List all of the supported key types. keytypes(edb) ## Get all gene ids from the database. gids <- keys(edb, keytype = "GENEID") length(gids) ## Get all gene names for genes encoded on chromosome Y. gnames <- keys(edb, keytype = "GENENAME", filter = SeqNameFilter("Y")) head(gnames) ``` In the next example we retrieve specific information from the database using the `select` method. First we fetch all transcripts for the genes *BCL2* and *BCL2L11*. In the first call we provide the gene names, while in the second call we employ the filtering system to perform a more fine-grained query to fetch only the protein coding transcripts for these genes. ```{r select, message = FALSE, warning=FALSE } ## Use the /standard/ way to fetch data. select(edb, keys = c("BCL2", "BCL2L11"), keytype = "GENENAME", columns = c("GENEID", "GENENAME", "TXID", "TXBIOTYPE")) ## Use the filtering system of ensembldb select(edb, keys = ~ genename %in% c("BCL2", "BCL2L11") & tx_biotype == "protein_coding", columns = c("GENEID", "GENENAME", "TXID", "TXBIOTYPE")) ``` Finally, we use the `mapIds` method to establish a mapping between ids and values. In the example below we fetch transcript ids for the two genes from the example above. ```{r mapIds, message = FALSE } ## Use the default method, which just returns the first value for multi mappings. mapIds(edb, keys = c("BCL2", "BCL2L11"), column = "TXID", keytype = "GENENAME") ## Alternatively, specify multiVals="list" to return all mappings. mapIds(edb, keys = c("BCL2", "BCL2L11"), column = "TXID", keytype = "GENENAME", multiVals = "list") ## And, just like before, we can use filters to map only to protein coding transcripts. mapIds(edb, keys = list(GenenameFilter(c("BCL2", "BCL2L11")), TxBiotypeFilter("protein_coding")), column = "TXID", multiVals = "list") ``` Note that, if the filters are used, the ordering of the result does no longer match the ordering of the genes. # Important notes These notes might explain eventually unexpected results (and, more importantly, help avoiding them): - The ordering of the results returned by the `genes`, `exons`, `transcripts` methods can be specified with the `order.by` parameter. The ordering of the results does however **not** correspond to the ordering of values in submitted filter objects. The exception is the `select` method. If a character vector of values or a single filter is passed with argument `keys` the ordering of results of this method matches the ordering of the key values or the values of the filter. - Results of `exonsBy`, `transcriptsBy` are always ordered by the `by` argument. - The CDS provided by `EnsDb` objects **always** includes both, the start and the stop codon. - Transcripts with multiple CDS are at present not supported by `EnsDb`. - At present, `EnsDb` support only genes/transcripts for which all of their exons are encoded on the same chromosome and the same strand. - Since a single Ensembl gene ID might be mapped to multiple NCBI Entrezgene IDs methods such as `genes`, `transcripts` etc return a `list` in the `"entrezid"` column of the resulting result object. # Getting or building `EnsDb` databases/packages Some of the code in this section is not supposed to be automatically executed when the vignette is built, as this would require a working installation of the Ensembl Perl API, which is not expected to be available on each system. Also, building `EnsDb` from alternative sources, like GFF or GTF files takes some time and thus also these examples are not directly executed when the vignette is build. ## Getting `EnsDb` databases Some `EnsDb` databases are available as `R` packages from Bioconductor and can be simply installed with the `biocLite` function from the `BiocInstaller` package. The name of such annotation packages starts with *EnsDb* followed by the abbreviation of the organism and the Ensembl version on which the annotation bases. `EnsDb.Hsapiens.v86` provides thus an `EnsDb` database for homo sapiens with annotations from Ensembl version 86. Since Bioconductor version 3.5 `EnsDb` databases can also be retrieved directly from `AnnotationHub`. ```{r AnnotationHub-query, message = FALSE, eval = use_network } library(AnnotationHub) ## Load the annotation resource. ah <- AnnotationHub() ## Query for all available EnsDb databases query(ah, "EnsDb") ``` We can simply fetch one of the databases. ```{r AnnotationHub-query-2, message = FALSE, eval = use_network } ahDb <- query(ah, pattern = c("Xiphophorus Maculatus", "EnsDb", 87)) ## What have we got ahDb ``` Fetch the `EnsDb` and use it. ```{r AnnotationHub-fetch, message = FALSE, eval = FALSE } ahEdb <- ahDb[[1]] ## retriebe all genes gns <- genes(ahEdb) ``` We could even make an annotation package from this `EnsDb` object using the `makeEnsembldbPackage` and passing `dbfile(dbconn(ahEdb))` as `ensdb` argument. ## Building annotation packages ### Directly from Ensembl databases The `fetchTablesFromEnsembl` function uses the Ensembl Perl API to retrieve the required annotations from an Ensembl database (e.g. from the main site *ensembldb.ensembl.org*). Thus, to use this functionality to build databases, the Ensembl Perl API needs to be installed (see 5 for details). Below we create an `EnsDb` database by fetching the required data directly from the Ensembl core databases. The `makeEnsembldbPackage` function is then used to create an annotation package from this `EnsDb` containing all human genes for Ensembl version 75. ```{r edb-from-ensembl, message = FALSE, eval = FALSE } library(ensembldb) ## get all human gene/transcript/exon annotations from Ensembl (75) ## the resulting tables will be stored by default to the current working ## directory fetchTablesFromEnsembl(75, species = "human") ## These tables can then be processed to generate a SQLite database ## containing the annotations (again, the function assumes the required ## txt files to be present in the current working directory) DBFile <- makeEnsemblSQLiteFromTables() ## and finally we can generate the package makeEnsembldbPackage(ensdb = DBFile, version = "0.99.12", maintainer = "Johannes Rainer ", author = "J Rainer") ``` The generated package can then be build using `R CMD build EnsDb.Hsapiens.v75` and installed with `R CMD INSTALL EnsDb.Hsapiens.v75*`. Note that we could directly generate an `EnsDb` instance by loading the database file, i.e. by calling `edb <- EnsDb(DBFile)` and work with that annotation object. To fetch and build annotation packages for plant genomes (e.g. arabidopsis thaliana), the *Ensembl genomes* should be specified as a host, i.e. setting `host` to "mysql-eg-publicsql.ebi.ac.uk", `port` to `4157` and `species` to e.g. "arabidopsis thaliana". ### From a GTF or GFF file Alternatively, the `ensDbFromAH`, `ensDbFromGff`, `ensDbFromGRanges` and `ensDbFromGtf` functions allow to build EnsDb SQLite files from a `GRanges` object or GFF/GTF files from Ensembl (either provided as files or *via* `AnnotationHub`). These functions do not depend on the Ensembl Perl API, but require a working internet connection to fetch the chromosome lengths from Ensembl as these are not provided within GTF or GFF files. Also note that protein annotations are usually not available in GTF or GFF files, thus, such annotations will not be included in the generated `EnsDb` database - protein annotations are only available in `EnsDb` databases created with the Ensembl Perl API (such as the ones provided through `AnnotationHub` or as Bioconductor packages). In the next example we create an `EnsDb` database using the `AnnotationHub` package and load also the corresponding genomic DNA sequence matching the Ensembl version. We thus first query the `AnnotationHub` package for all resources available for `Mus musculus` and the Ensembl release 77. Next we create the `EnsDb` object from the appropriate `AnnotationHub` resource. We then use the `getGenomeFaFile` method on the `EnsDb` to directly look up and retrieve the correct or best matching `FaFile` with the genomic DNA sequence. At last we retrieve the sequences of all exons using the `getSeq` method. ```{r gtf-gff-edb, message = FALSE, eval = FALSE } ## Load the AnnotationHub data. library(AnnotationHub) ah <- AnnotationHub() ## Query all available files for Ensembl release 77 for ## Mus musculus. query(ah, c("Mus musculus", "release-77")) ## Get the resource for the gtf file with the gene/transcript definitions. Gtf <- ah["AH28822"] ## Create a EnsDb database file from this. DbFile <- ensDbFromAH(Gtf) ## We can either generate a database package, or directly load the data edb <- EnsDb(DbFile) ## Identify and get the FaFile object with the genomic DNA sequence matching ## the EnsDb annotation. Dna <- getGenomeFaFile(edb) library(Rsamtools) ## We next retrieve the sequence of all exons on chromosome Y. exons <- exons(edb, filter = SeqNameFilter("Y")) exonSeq <- getSeq(Dna, exons) ## Alternatively, look up and retrieve the toplevel DNA sequence manually. Dna <- ah[["AH22042"]] ``` In the example below we load a `GRanges` containing gene definitions for genes encoded on chromosome Y and generate a `EnsDb` SQLite database from that information. ```{r EnsDb-from-Y-GRanges, message = FALSE, eval = use_network } ## Generate a sqlite database from a GRanges object specifying ## genes encoded on chromosome Y load(system.file("YGRanges.RData", package = "ensembldb")) Y ## Create the EnsDb database file DB <- ensDbFromGRanges(Y, path = tempdir(), version = 75, organism = "Homo_sapiens") ## Load the database edb <- EnsDb(DB) edb ``` Alternatively we can build the annotation database using the `ensDbFromGtf` `ensDbFromGff` functions, that extract most of the required data from a GTF respectively GFF (version 3) file which can be downloaded from Ensembl (e.g. from for human gene definitions from Ensembl version 75; for plant genomes etc, files can be retrieved from ). All information except the chromosome lengths, the NCBI Entrezgene IDs and protein annotations can be extracted from these GTF files. The function also tries to retrieve chromosome length information automatically from Ensembl. Below we create the annotation from a gtf file that we fetch directly from Ensembl. ```{r EnsDb-from-GTF, message = FALSE, eval = FALSE } library(ensembldb) ## the GTF file can be downloaded from ## ftp://ftp.ensembl.org/pub/release-75/gtf/homo_sapiens/ gtffile <- "Homo_sapiens.GRCh37.75.gtf.gz" ## generate the SQLite database file DB <- ensDbFromGtf(gtf = gtffile) ## load the DB file directly EDB <- EnsDb(DB) ## alternatively, build the annotation package ## and finally we can generate the package makeEnsembldbPackage(ensdb = DB, version = "0.99.12", maintainer = "Johannes Rainer ", author = "J Rainer") ``` # Database layout The database consists of the following tables and attributes (the layout is also shown in Figure [165](#orgfd622d5)). Note that the protein-specific annotations might not be available in all `EnsDB` databases (e.g. such ones created with `ensembldb` version < 1.7 or created from GTF or GFF files). - **gene**: all gene specific annotations. - `gene_id`: the Ensembl ID of the gene. - `gene_name`: the name (symbol) of the gene. - `gene_biotype`: the biotype of the gene. - `gene_seq_start`: the start coordinate of the gene on the sequence (usually a chromosome). - `gene_seq_end`: the end coordinate of the gene on the sequence. - `seq_name`: the name of the sequence (usually the chromosome name). - `seq_strand`: the strand on which the gene is encoded. - `seq_coord_system`: the coordinate system of the sequence. - `description`: the description of the gene. - **entrezgene**: mapping of Ensembl genes to NCBI Entrezgene identifiers. Note that this mapping can be a one-to-many mapping. - `gene_id`: the Ensembl gene ID. - `entrezid`: the NCBI Entrezgene ID. - **tx**: all transcript related annotations. Note that while no `tx_name` column is available in this database column, all methods to retrieve data from the database support also this column. The returned values are however the ID of the transcripts. - `tx_id`: the Ensembl transcript ID. - `tx_biotype`: the biotype of the transcript. - `tx_seq_start`: the start coordinate of the transcript. - `tx_seq_end`: the end coordinate of the transcript. - `tx_cds_seq_start`: the start coordinate of the coding region of the transcript (NULL for non-coding transcripts). - `tx_cds_seq_end`: the end coordinate of the coding region of the transcript. - `gene_id`: the gene to which the transcript belongs. `EnsDb` databases for more recent Ensembl releases have also a column `tx_support_level` providing the evidence level for a transcript (1 high evidence, 5 low evidence, NA no evidence calculated). - **exon**: all exon related annotation. - `exon_id`: the Ensembl exon ID. - `exon_seq_start`: the start coordinate of the exon. - `exon_seq_end`: the end coordinate of the exon. - **tx2exon**: provides the n:m mapping between transcripts and exons. - `tx_id`: the Ensembl transcript ID. - `exon_id`: the Ensembl exon ID. - `exon_idx`: the index of the exon in the corresponding transcript, always from 5' to 3' of the transcript. - **chromosome**: provides some information about the chromosomes. - `seq_name`: the name of the sequence/chromosome. - `seq_length`: the length of the sequence. - `is_circular`: whether the sequence in circular. - **protein**: provides protein annotation for a (coding) transcript. - `protein_id`: the Ensembl protein ID. - `tx_id`: the transcript ID which CDS encodes the protein. - `protein_sequence`: the peptide sequence of the protein (translated from the transcript's coding sequence after applying eventual RNA editing). - **uniprot**: provides the mapping from Ensembl protein ID(s) to Uniprot ID(s). Not all Ensembl proteins are annotated to Uniprot IDs, also, each Ensembl protein might be mapped to multiple Uniprot IDs. - `protein_id`: the Ensembl protein ID. - `uniprot_id`: the Uniprot ID. - `uniprot_db`: the Uniprot database in which the ID is defined. - `uniprot_mapping_type`: the type of the mapping method that was used to assign the Uniprot ID to an Ensembl protein ID. - **protein\_domain**: provides protein domain annotations and mapping to proteins. - `protein_id`: the Ensembl protein ID on which the protein domain is present. - `protein_domain_id`: the ID of the protein domain (from the protein domain source). - `protein_domain_source`: the source/analysis method in/by which the protein domain was defined (such as pfam etc). - `interpro_accession`: the Interpro accession ID of the protein domain. - `prot_dom_start`: the start position of the protein domain within the protein's sequence. - `prot_dom_end`: the end position of the protein domain within the protein's sequence. - **metadata**: some additional, internal, informations (Genome build, Ensembl version etc). - `name` - `value` - *virtual* columns: - `symbol`: the database does not have such a database column, but it is still possible to use it in the `columns` parameter. This column is *symlinked* to the `gene_name` column. - `tx_name`: similar to the `symbol` column, this column is *symlinked* to the `tx_id` column. The database layout: as already described above, protein related annotations (green) might not be available in each `EnsDb` database. ![img](images/dblayout.png "Database layout.") # Footnotes 1 2 3 4 5 ensembldb/inst/doc/ensembldb.html0000644000175400017540000645164513241155730020124 0ustar00biocbuildbiocbuild Generating an using Ensembl based annotation packages

1 Introduction

The ensembldb package provides functions to create and use transcript centric annotation databases/packages. The annotation for the databases are directly fetched from Ensembl 1 using their Perl API. The functionality and data is similar to that of the TxDb packages from the GenomicFeatures package, but, in addition to retrieve all gene/transcript models and annotations from the database, the ensembldb package provides also a filter framework allowing to retrieve annotations for specific entries like genes encoded on a chromosome region or transcript models of lincRNA genes. From version 1.7 on, EnsDb databases created by the ensembldb package contain also protein annotation data (see Section 11 for the database layout and an overview of available attributes/columns). For more information on the use of the protein annotations refer to the proteins vignette.

Another main goal of this package is to generate versioned annotation packages, i.e. annotation packages that are build for a specific Ensembl release, and are also named according to that (e.g. EnsDb.Hsapiens.v75 for human gene definitions of the Ensembl code database version 75). This ensures reproducibility, as it allows to load annotations from a specific Ensembl release also if newer versions of annotation packages/releases are available. It also allows to load multiple annotation packages at the same time in order to e.g. compare gene models between Ensembl releases.

In the example below we load an Ensembl based annotation package for Homo sapiens, Ensembl version 75. The EnsDb object providing access to the underlying SQLite database is bound to the variable name EnsDb.Hsapiens.v75.

library(EnsDb.Hsapiens.v75)

## Making a "short cut"
edb <- EnsDb.Hsapiens.v75
## print some informations for this package
edb
## EnsDb for Ensembl:
## |Backend: SQLite
## |Db type: EnsDb
## |Type of Gene ID: Ensembl Gene ID
## |Supporting package: ensembldb
## |Db created by: ensembldb package from Bioconductor
## |script_version: 0.3.0
## |Creation time: Thu May 18 09:15:45 2017
## |ensembl_version: 75
## |ensembl_host: localhost
## |Organism: homo_sapiens
## |taxonomy_id: 9606
## |genome_build: GRCh37
## |DBSCHEMAVERSION: 2.0
## | No. of genes: 64102.
## | No. of transcripts: 215647.
## |Protein data available.
## For what organism was the database generated?
organism(edb)
## [1] "Homo sapiens"

2 Using ensembldb annotation packages to retrieve specific annotations

One of the strengths of the ensembldb package and the related EnsDb databases is its implementation of a filter framework that enables to efficiently extract data sub-sets from the databases. The ensembldb package supports most of the filters defined in the AnnotationFilter Bioconductor package and defines some additional filters specific to the data stored in EnsDb databases. Filters can be passed directly to all methods extracting data from an EnsDb (such as genes, transcripts or exons). Alternatively it is possible with the addFilter or filter functions to add a filter directly to an EnsDb which will then be used in all queries on that object.

The supportedFilters method can be used to get an overview over all supported filter classes, each of them (except the GRangesFilter) working on a single column/field in the database.

supportedFilters(edb)
##                      filter                field
## 1              EntrezFilter               entrez
## 2             ExonEndFilter             exon_end
## 3              ExonIdFilter              exon_id
## 4            ExonRankFilter            exon_rank
## 5           ExonStartFilter           exon_start
## 6             GRangesFilter                 <NA>
## 7         GeneBiotypeFilter         gene_biotype
## 8             GeneEndFilter             gene_end
## 9              GeneIdFilter              gene_id
## 10          GeneStartFilter           gene_start
## 11           GenenameFilter             genename
## 12          ProtDomIdFilter          prot_dom_id
## 13          ProteinIdFilter           protein_id
## 14            SeqNameFilter             seq_name
## 15          SeqStrandFilter           seq_strand
## 16             SymbolFilter               symbol
## 17          TxBiotypeFilter           tx_biotype
## 18              TxEndFilter               tx_end
## 19               TxIdFilter                tx_id
## 20             TxNameFilter              tx_name
## 21            TxStartFilter             tx_start
## 22          UniprotDbFilter           uniprot_db
## 23            UniprotFilter              uniprot
## 24 UniprotMappingTypeFilter uniprot_mapping_type

These filters can be divided into 3 main filter types:

  • IntegerFilter: filter classes extending this basic object can take a single numeric value as input and support the conditions =, !, >, <, >= and <=. All filters that work on chromosomal coordinates, such as the GeneEndFilter extend IntegerFilter.
  • CharacterFilter: filter classes extending this object can take a single or multiple character values as input and allow conditions: =, !, “startsWith” and “endsWith”. All filters working on IDs extend this class.
  • GRangesFilter: takes a GRanges object as input and supports all conditions that findOverlaps from the IRanges package supports (“any”, “start”, “end”, “within”, “equal”). Note that these have to be passed using the parameter type to the constructor function.

The supported filters are:

  • EntrezFilter: allows to filter results based on NCBI Entrezgene identifiers of the genes.
  • ExonEndFilter: filter using the chromosomal end coordinate of exons.
  • ExonIdFilter: filter based on the (Ensembl) exon identifiers.
  • ExonRankFilter: filter based on the rank (index) of an exon within the transcript model. Exons are always numbered from 5’ to 3’ end of the transcript, thus, also on the reverse strand, the exon 1 is the most 5’ exon of the transcript.
  • ExonStartFilter: filter using the chromosomal start coordinate of exons.
  • GeneBiotypeFilter: filter using the gene biotypes defined in the Ensembl database; use the listGenebiotypes method to list all available biotypes.
  • GeneEndFilter: filter using the chromosomal end coordinate of gene.
  • GeneIdFilter: filter based on the Ensembl gene IDs.
  • GenenameFilter: filter based on the names (symbols) of the genes.
  • GeneStartFilter: filter using the chromosomal start coordinate of gene.
  • GRangesFilter: allows to retrieve all features (genes, transcripts or exons) that are either within (setting parameter type to “within”) or partially overlapping (setting type to “any”) the defined genomic region/range. Note that, depending on the called method (genes, transcripts or exons) the start and end coordinates of either the genes, transcripts or exons are used for the filter. For methods exonsBy, cdsBy and txBy the coordinates of by are used.
  • SeqNameFilter: filter by the name of the chromosomes the genes are encoded on.
  • SeqStrandFilter: filter for the chromosome strand on which the genes are encoded.
  • SymbolFilter: filter on gene symbols; note that no database columns symbol is available in an EnsDb database and hence the gene name is used for filtering.
  • TxBiotypeFilter: filter on the transcript biotype defined in Ensembl; use the listTxbiotypes method to list all available biotypes.
  • TxEndFilter: filter using the chromosomal end coordinate of transcripts.
  • TxIdFilter: filter on the Ensembl transcript identifiers.
  • TxNameFilter: filter on the Ensembl transcript names (currently identical to the transcript IDs).
  • TxStartFilter: filter using the chromosomal start coordinate of transcripts.

In addition to the above listed DNA-RNA-based filters, protein-specific filters are also available:

  • ProtDomIdFilter: filter by the protein domain ID.
  • ProteinIdFilter: filter by Ensembl protein ID filters.
  • UniprotDbFilter: filter by the name of the Uniprot database.
  • UniprotFilter: filter by the Uniprot ID.
  • UniprotMappingTypeFilter: filter by the mapping type of Ensembl protein IDs to Uniprot IDs.

These can however only be used on EnsDb databases that provide protein annotations, i.e. for which a call to hasProteinData returns TRUE.

EnsDb databases for more recent Ensembl versions (starting from Ensembl 87) provide also evidence levels for individual transcripts in the tx_support_level database column. Such databases support also a TxSupportLevelFilter filter to use this columns for filtering.

A simple use case for the filter framework would be to get all transcripts for the gene BCL2L11. To this end we specify a GenenameFilter with the value BCL2L11. As a result we get a GRanges object with start, end, strand and seqname being the start coordinate, end coordinate, chromosome name and strand for the respective transcripts. All additional annotations are available as metadata columns. Alternatively, by setting return.type to “DataFrame”, or “data.frame” the method would return a DataFrame or data.frame object instead of the default GRanges.

Tx <- transcripts(edb, filter = list(GenenameFilter("BCL2L11")))

Tx
## GRanges object with 17 ranges and 7 metadata columns:
##                   seqnames                 ranges strand |           tx_id
##                      <Rle>              <IRanges>  <Rle> |     <character>
##   ENST00000432179        2 [111876955, 111881689]      + | ENST00000432179
##   ENST00000308659        2 [111878491, 111922625]      + | ENST00000308659
##   ENST00000357757        2 [111878491, 111919016]      + | ENST00000357757
##   ENST00000393253        2 [111878491, 111909428]      + | ENST00000393253
##   ENST00000337565        2 [111878491, 111886423]      + | ENST00000337565
##               ...      ...                    ...    ... .             ...
##   ENST00000452231        2 [111881323, 111921808]      + | ENST00000452231
##   ENST00000361493        2 [111881323, 111921808]      + | ENST00000361493
##   ENST00000431217        2 [111881323, 111921929]      + | ENST00000431217
##   ENST00000439718        2 [111881323, 111922220]      + | ENST00000439718
##   ENST00000438054        2 [111881329, 111903861]      + | ENST00000438054
##                                tx_biotype tx_cds_seq_start tx_cds_seq_end
##                               <character>        <integer>      <integer>
##   ENST00000432179          protein_coding        111881323      111881689
##   ENST00000308659          protein_coding        111881323      111921808
##   ENST00000357757          protein_coding        111881323      111919016
##   ENST00000393253          protein_coding        111881323      111909428
##   ENST00000337565          protein_coding        111881323      111886328
##               ...                     ...              ...            ...
##   ENST00000452231 nonsense_mediated_decay        111881323      111919016
##   ENST00000361493 nonsense_mediated_decay        111881323      111887812
##   ENST00000431217 nonsense_mediated_decay        111881323      111902078
##   ENST00000439718 nonsense_mediated_decay        111881323      111909428
##   ENST00000438054          protein_coding        111881329      111902068
##                           gene_id         tx_name   gene_name
##                       <character>     <character> <character>
##   ENST00000432179 ENSG00000153094 ENST00000432179     BCL2L11
##   ENST00000308659 ENSG00000153094 ENST00000308659     BCL2L11
##   ENST00000357757 ENSG00000153094 ENST00000357757     BCL2L11
##   ENST00000393253 ENSG00000153094 ENST00000393253     BCL2L11
##   ENST00000337565 ENSG00000153094 ENST00000337565     BCL2L11
##               ...             ...             ...         ...
##   ENST00000452231 ENSG00000153094 ENST00000452231     BCL2L11
##   ENST00000361493 ENSG00000153094 ENST00000361493     BCL2L11
##   ENST00000431217 ENSG00000153094 ENST00000431217     BCL2L11
##   ENST00000439718 ENSG00000153094 ENST00000439718     BCL2L11
##   ENST00000438054 ENSG00000153094 ENST00000438054     BCL2L11
##   -------
##   seqinfo: 1 sequence from GRCh37 genome
## as this is a GRanges object we can access e.g. the start coordinates with
head(start(Tx))
## [1] 111876955 111878491 111878491 111878491 111878491 111878506
## or extract the biotype with
head(Tx$tx_biotype)
## [1] "protein_coding" "protein_coding" "protein_coding" "protein_coding"
## [5] "protein_coding" "protein_coding"

The parameter columns of the extractor methods (such as exons, genes or transcripts) allows to specify which database attributes (columns) should be retrieved. The exons method returns by default all exon-related columns, the transcripts all columns from the transcript database table and the genes all from the gene table. Note however that in the example above we got also a column gene_name although this column is not present in the transcript database table. By default the methods return also all columns that are used by any of the filters submitted with the filter argument (thus, because a GenenameFilter was used, the column gene_name is also returned). Setting returnFilterColumns(edb) <- FALSE disables this option and only the columns specified by the columns parameter are retrieved.

Instead of passing a filter object to the method it is also possible to provide a filter expression written as a formula. The formula has to be written in the form ~ <field> <condition> <value> with <field> being the field (database column) in the database, <condition> the condition for the filter object and <value> its value. Use the supportedFilter method to get the field names corresponding to each filter class.

## Use a filter expression to perform the filtering.
transcripts(edb, filter = ~ genename == "ZBTB16")
## GRanges object with 9 ranges and 7 metadata columns:
##                   seqnames                 ranges strand |           tx_id
##                      <Rle>              <IRanges>  <Rle> |     <character>
##   ENST00000335953       11 [113930315, 114121398]      + | ENST00000335953
##   ENST00000541602       11 [113930447, 114060486]      + | ENST00000541602
##   ENST00000544220       11 [113930459, 113934368]      + | ENST00000544220
##   ENST00000535700       11 [113930979, 113934466]      + | ENST00000535700
##   ENST00000392996       11 [113931229, 114121374]      + | ENST00000392996
##   ENST00000539918       11 [113935134, 114118066]      + | ENST00000539918
##   ENST00000545851       11 [114051488, 114118018]      + | ENST00000545851
##   ENST00000535379       11 [114107929, 114121279]      + | ENST00000535379
##   ENST00000535509       11 [114117512, 114121198]      + | ENST00000535509
##                                tx_biotype tx_cds_seq_start tx_cds_seq_end
##                               <character>        <integer>      <integer>
##   ENST00000335953          protein_coding        113934023      114121277
##   ENST00000541602         retained_intron             <NA>           <NA>
##   ENST00000544220          protein_coding        113934023      113934368
##   ENST00000535700          protein_coding        113934023      113934466
##   ENST00000392996          protein_coding        113934023      114121277
##   ENST00000539918 nonsense_mediated_decay        113935134      113992549
##   ENST00000545851    processed_transcript             <NA>           <NA>
##   ENST00000535379    processed_transcript             <NA>           <NA>
##   ENST00000535509         retained_intron             <NA>           <NA>
##                           gene_id         tx_name   gene_name
##                       <character>     <character> <character>
##   ENST00000335953 ENSG00000109906 ENST00000335953      ZBTB16
##   ENST00000541602 ENSG00000109906 ENST00000541602      ZBTB16
##   ENST00000544220 ENSG00000109906 ENST00000544220      ZBTB16
##   ENST00000535700 ENSG00000109906 ENST00000535700      ZBTB16
##   ENST00000392996 ENSG00000109906 ENST00000392996      ZBTB16
##   ENST00000539918 ENSG00000109906 ENST00000539918      ZBTB16
##   ENST00000545851 ENSG00000109906 ENST00000545851      ZBTB16
##   ENST00000535379 ENSG00000109906 ENST00000535379      ZBTB16
##   ENST00000535509 ENSG00000109906 ENST00000535509      ZBTB16
##   -------
##   seqinfo: 1 sequence from GRCh37 genome

Filter expression have to be written as a formula (i.e. starting with a ~) in the form column name followed by the logical condition.

Alternatively, EnsDb objects can be filtered directly using the filter function. In the example below we use the filter function to filter the EnsDb object and pass that filtered database to the transcripts method using the %>% from the magrittr package.

library(magrittr)
## 
## Attaching package: 'magrittr'
## The following object is masked from 'package:AnnotationFilter':
## 
##     not
filter(edb, ~ symbol == "BCL2" & tx_biotype != "protein_coding") %>% transcripts
## GRanges object with 1 range and 6 metadata columns:
##                   seqnames               ranges strand |           tx_id
##                      <Rle>            <IRanges>  <Rle> |     <character>
##   ENST00000590515       18 [60795445, 60829102]      - | ENST00000590515
##                             tx_biotype tx_cds_seq_start tx_cds_seq_end
##                            <character>        <integer>      <integer>
##   ENST00000590515 processed_transcript             <NA>           <NA>
##                           gene_id         tx_name
##                       <character>     <character>
##   ENST00000590515 ENSG00000171791 ENST00000590515
##   -------
##   seqinfo: 1 sequence from GRCh37 genome

Adding a filter to an EnsDb enables this filter (globally) on all subsequent queries on that object. We could thus filter an EnsDb to (virtually) contain only features encoded on chromosome Y.

edb_y <- addFilter(edb, SeqNameFilter("Y"))

## All subsequent filters on that EnsDb will only work on features encoded on
## chromosome Y
genes(edb_y)
## GRanges object with 495 ranges and 6 metadata columns:
##                   seqnames               ranges strand |         gene_id
##                      <Rle>            <IRanges>  <Rle> |     <character>
##   ENSG00000251841        Y   [2652790, 2652894]      + | ENSG00000251841
##   ENSG00000184895        Y   [2654896, 2655740]      - | ENSG00000184895
##   ENSG00000237659        Y   [2657868, 2658369]      + | ENSG00000237659
##   ENSG00000232195        Y   [2696023, 2696259]      + | ENSG00000232195
##   ENSG00000129824        Y   [2709527, 2800041]      + | ENSG00000129824
##               ...      ...                  ...    ... .             ...
##   ENSG00000224240        Y [28695572, 28695890]      + | ENSG00000224240
##   ENSG00000227629        Y [28732789, 28737748]      - | ENSG00000227629
##   ENSG00000237917        Y [28740998, 28780799]      - | ENSG00000237917
##   ENSG00000231514        Y [28772667, 28773306]      - | ENSG00000231514
##   ENSG00000235857        Y [59001391, 59001635]      + | ENSG00000235857
##                     gene_name   gene_biotype seq_coord_system      symbol
##                   <character>    <character>      <character> <character>
##   ENSG00000251841  RNU6-1334P          snRNA       chromosome  RNU6-1334P
##   ENSG00000184895         SRY protein_coding       chromosome         SRY
##   ENSG00000237659  RNASEH2CP1     pseudogene       chromosome  RNASEH2CP1
##   ENSG00000232195    TOMM22P2     pseudogene       chromosome    TOMM22P2
##   ENSG00000129824      RPS4Y1 protein_coding       chromosome      RPS4Y1
##               ...         ...            ...              ...         ...
##   ENSG00000224240     CYCSP49     pseudogene       chromosome     CYCSP49
##   ENSG00000227629  SLC25A15P1     pseudogene       chromosome  SLC25A15P1
##   ENSG00000237917     PARP4P1     pseudogene       chromosome     PARP4P1
##   ENSG00000231514     FAM58CP     pseudogene       chromosome     FAM58CP
##   ENSG00000235857     CTBP2P1     pseudogene       chromosome     CTBP2P1
##                   entrezid
##                     <list>
##   ENSG00000251841       NA
##   ENSG00000184895     6736
##   ENSG00000237659       NA
##   ENSG00000232195       NA
##   ENSG00000129824     6192
##               ...      ...
##   ENSG00000224240       NA
##   ENSG00000227629       NA
##   ENSG00000237917       NA
##   ENSG00000231514       NA
##   ENSG00000235857       NA
##   -------
##   seqinfo: 1 sequence from GRCh37 genome
## Get all lincRNAs on chromosome Y
genes(edb_y, filter = ~ gene_biotype == "lincRNA")
## GRanges object with 48 ranges and 6 metadata columns:
##                   seqnames               ranges strand |         gene_id
##                      <Rle>            <IRanges>  <Rle> |     <character>
##   ENSG00000231535        Y   [2870953, 2970313]      + | ENSG00000231535
##   ENSG00000229308        Y   [3904538, 3968361]      + | ENSG00000229308
##   ENSG00000237069        Y   [6110487, 6111651]      - | ENSG00000237069
##   ENSG00000229643        Y   [6225260, 6229454]      - | ENSG00000229643
##   ENSG00000129816        Y   [6258472, 6279605]      + | ENSG00000129816
##               ...      ...                  ...    ... .             ...
##   ENSG00000228296        Y [27209230, 27246039]      - | ENSG00000228296
##   ENSG00000223641        Y [27329790, 27330920]      - | ENSG00000223641
##   ENSG00000228786        Y [27524447, 27540866]      - | ENSG00000228786
##   ENSG00000240450        Y [27629055, 27632852]      + | ENSG00000240450
##   ENSG00000231141        Y [27874637, 27879535]      + | ENSG00000231141
##                      gene_name gene_biotype seq_coord_system       symbol
##                    <character>  <character>      <character>  <character>
##   ENSG00000231535    LINC00278      lincRNA       chromosome    LINC00278
##   ENSG00000229308   AC010084.1      lincRNA       chromosome   AC010084.1
##   ENSG00000237069      TTTY23B      lincRNA       chromosome      TTTY23B
##   ENSG00000229643    LINC00280      lincRNA       chromosome    LINC00280
##   ENSG00000129816       TTTY1B      lincRNA       chromosome       TTTY1B
##               ...          ...          ...              ...          ...
##   ENSG00000228296       TTTY4C      lincRNA       chromosome       TTTY4C
##   ENSG00000223641      TTTY17C      lincRNA       chromosome      TTTY17C
##   ENSG00000228786 LINC00266-4P      lincRNA       chromosome LINC00266-4P
##   ENSG00000240450     CSPG4P1Y      lincRNA       chromosome     CSPG4P1Y
##   ENSG00000231141        TTTY3      lincRNA       chromosome        TTTY3
##                               entrezid
##                                 <list>
##   ENSG00000231535            100873962
##   ENSG00000229308                   NA
##   ENSG00000237069     100101121,252955
##   ENSG00000229643                   NA
##   ENSG00000129816      100101116,50858
##               ...                  ...
##   ENSG00000228296 474150,474149,114761
##   ENSG00000223641 474152,474151,252949
##   ENSG00000228786                   NA
##   ENSG00000240450               114758
##   ENSG00000231141        474148,114760
##   -------
##   seqinfo: 1 sequence from GRCh37 genome

To get an overview of database tables and available columns the function listTables can be used. The method listColumns on the other hand lists columns for the specified database table.

## list all database tables along with their columns
listTables(edb)
## $gene
## [1] "gene_id"          "gene_name"        "gene_biotype"    
## [4] "gene_seq_start"   "gene_seq_end"     "seq_name"        
## [7] "seq_strand"       "seq_coord_system" "symbol"          
## 
## $tx
## [1] "tx_id"            "tx_biotype"       "tx_seq_start"    
## [4] "tx_seq_end"       "tx_cds_seq_start" "tx_cds_seq_end"  
## [7] "gene_id"          "tx_name"         
## 
## $tx2exon
## [1] "tx_id"    "exon_id"  "exon_idx"
## 
## $exon
## [1] "exon_id"        "exon_seq_start" "exon_seq_end"  
## 
## $chromosome
## [1] "seq_name"    "seq_length"  "is_circular"
## 
## $protein
## [1] "tx_id"            "protein_id"       "protein_sequence"
## 
## $uniprot
## [1] "protein_id"           "uniprot_id"           "uniprot_db"          
## [4] "uniprot_mapping_type"
## 
## $protein_domain
## [1] "protein_id"            "protein_domain_id"     "protein_domain_source"
## [4] "interpro_accession"    "prot_dom_start"        "prot_dom_end"         
## 
## $entrezgene
## [1] "gene_id"  "entrezid"
## 
## $metadata
## [1] "name"  "value"
## list columns from a specific table
listColumns(edb, "tx")
## [1] "tx_id"            "tx_biotype"       "tx_seq_start"    
## [4] "tx_seq_end"       "tx_cds_seq_start" "tx_cds_seq_end"  
## [7] "gene_id"          "tx_name"

Thus, we could retrieve all transcripts of the biotype nonsense_mediated_decay (which, according to the definitions by Ensembl are transcribed, but most likely not translated in a protein, but rather degraded after transcription) along with the name of the gene for each transcript. Note that we are changing here the return.type to DataFrame, so the method will return a DataFrame with the results instead of the default GRanges.

Tx <- transcripts(edb,
                  columns = c(listColumns(edb , "tx"), "gene_name"),
                  filter = TxBiotypeFilter("nonsense_mediated_decay"),
                  return.type = "DataFrame")
nrow(Tx)
## [1] 13812
Tx
## DataFrame with 13812 rows and 9 columns
##                 tx_id              tx_biotype tx_seq_start tx_seq_end
##           <character>             <character>    <integer>  <integer>
## 1     ENST00000495251 nonsense_mediated_decay        64085      69409
## 2     ENST00000462860 nonsense_mediated_decay        64085      69452
## 3     ENST00000483390 nonsense_mediated_decay        65739      68764
## 4     ENST00000538848 nonsense_mediated_decay        66411      68843
## 5     ENST00000567466 nonsense_mediated_decay        97578      99521
## ...               ...                     ...          ...        ...
## 13808 ENST00000496411 nonsense_mediated_decay    249149927  249153217
## 13809 ENST00000483223 nonsense_mediated_decay    249150714  249152728
## 13810 ENST00000533647 nonsense_mediated_decay    249151472  249152523
## 13811 ENST00000528141 nonsense_mediated_decay    249151590  249153284
## 13812 ENST00000530986 nonsense_mediated_decay    249151668  249153284
##       tx_cds_seq_start tx_cds_seq_end         gene_id         tx_name
##              <integer>      <integer>     <character>     <character>
## 1                68052          68789 ENSG00000234769 ENST00000495251
## 2                68052          68789 ENSG00000234769 ENST00000462860
## 3                66428          68764 ENSG00000234769 ENST00000483390
## 4                67418          68789 ENSG00000234769 ENST00000538848
## 5                98546          98893 ENSG00000261456 ENST00000567466
## ...                ...            ...             ...             ...
## 13808        249152153      249152508 ENSG00000171163 ENST00000496411
## 13809        249152153      249152508 ENSG00000171163 ENST00000483223
## 13810        249152153      249152508 ENSG00000171163 ENST00000533647
## 13811        249152203      249152508 ENSG00000171163 ENST00000528141
## 13812        249152203      249152508 ENSG00000171163 ENST00000530986
##         gene_name
##       <character>
## 1          WASH4P
## 2          WASH4P
## 3          WASH4P
## 4          WASH4P
## 5           TUBB8
## ...           ...
## 13808      ZNF692
## 13809      ZNF692
## 13810      ZNF692
## 13811      ZNF692
## 13812      ZNF692

For protein coding transcripts, we can also specifically extract their coding region. In the example below we extract the CDS for all transcripts encoded on chromosome Y.

yCds <- cdsBy(edb, filter = SeqNameFilter("Y"))
yCds
## GRangesList object of length 160:
## $ENST00000155093 
## GRanges object with 7 ranges and 3 metadata columns:
##       seqnames             ranges strand |    seq_name         exon_id
##          <Rle>          <IRanges>  <Rle> | <character>     <character>
##   [1]        Y [2821978, 2822038]      + |           Y ENSE00002223884
##   [2]        Y [2829115, 2829687]      + |           Y ENSE00003645989
##   [3]        Y [2843136, 2843285]      + |           Y ENSE00003548678
##   [4]        Y [2843552, 2843695]      + |           Y ENSE00003611496
##   [5]        Y [2844711, 2844863]      + |           Y ENSE00001649504
##   [6]        Y [2845981, 2846121]      + |           Y ENSE00001777381
##   [7]        Y [2846851, 2848034]      + |           Y ENSE00001368923
##       exon_rank
##       <integer>
##   [1]         2
##   [2]         3
##   [3]         4
##   [4]         5
##   [5]         6
##   [6]         7
##   [7]         8
## 
## $ENST00000215473 
## GRanges object with 6 ranges and 3 metadata columns:
##       seqnames             ranges strand | seq_name         exon_id
##   [1]        Y [4924865, 4925500]      + |        Y ENSE00001436852
##   [2]        Y [4966256, 4968748]      + |        Y ENSE00001640924
##   [3]        Y [5369098, 5369296]      + |        Y ENSE00001803775
##   [4]        Y [5483308, 5483316]      + |        Y ENSE00001731866
##   [5]        Y [5491131, 5491145]      + |        Y ENSE00001711324
##   [6]        Y [5605313, 5605983]      + |        Y ENSE00001779807
##       exon_rank
##   [1]         1
##   [2]         2
##   [3]         3
##   [4]         4
##   [5]         5
##   [6]         6
## 
## $ENST00000215479 
## GRanges object with 5 ranges and 3 metadata columns:
##       seqnames             ranges strand | seq_name         exon_id
##   [1]        Y [6740596, 6740649]      - |        Y ENSE00001671586
##   [2]        Y [6738047, 6738094]      - |        Y ENSE00001645681
##   [3]        Y [6736773, 6736817]      - |        Y ENSE00000652250
##   [4]        Y [6736078, 6736503]      - |        Y ENSE00001667251
##   [5]        Y [6734114, 6734119]      - |        Y ENSE00001494454
##       exon_rank
##   [1]         2
##   [2]         3
##   [3]         4
##   [4]         5
##   [5]         6
## 
## ...
## <157 more elements>
## -------
## seqinfo: 1 sequence from GRCh37 genome

Using a GRangesFilter we can retrieve all features from the database that are either within or overlapping the specified genomic region. In the example below we query all genes that are partially overlapping with a small region on chromosome 11. The filter restricts to all genes for which either an exon or an intron is partially overlapping with the region.

## Define the filter
grf <- GRangesFilter(GRanges("11", ranges = IRanges(114000000, 114000050),
                             strand = "+"), type = "any")

## Query genes:
gn <- genes(edb, filter = grf)
gn
## GRanges object with 1 range and 6 metadata columns:
##                   seqnames                 ranges strand |         gene_id
##                      <Rle>              <IRanges>  <Rle> |     <character>
##   ENSG00000109906       11 [113930315, 114121398]      + | ENSG00000109906
##                     gene_name   gene_biotype seq_coord_system      symbol
##                   <character>    <character>      <character> <character>
##   ENSG00000109906      ZBTB16 protein_coding       chromosome      ZBTB16
##                   entrezid
##                     <list>
##   ENSG00000109906     7704
##   -------
##   seqinfo: 1 sequence from GRCh37 genome
## Next we retrieve all transcripts for that gene so that we can plot them.
txs <- transcripts(edb, filter = GenenameFilter(gn$gene_name))
plot(3, 3, pch = NA, xlim = c(start(gn), end(gn)), ylim = c(0, length(txs)),
     yaxt = "n", ylab = "")
## Highlight the GRangesFilter region
rect(xleft = start(grf), xright = end(grf), ybottom = 0, ytop = length(txs),
     col = "red", border = "red")
for(i in 1:length(txs)) {
    current <- txs[i]
    rect(xleft = start(current), xright = end(current), ybottom = i-0.975,
         ytop = i-0.125, border = "grey")
    text(start(current), y = i-0.5, pos = 4, cex = 0.75, labels = current$tx_id)
}

As we can see, 4 transcripts of the gene ZBTB16 are also overlapping the region. Below we fetch these 4 transcripts. Note, that a call to exons will not return any features from the database, as no exon is overlapping with the region.

transcripts(edb, filter = grf)
## GRanges object with 4 ranges and 6 metadata columns:
##                   seqnames                 ranges strand |           tx_id
##                      <Rle>              <IRanges>  <Rle> |     <character>
##   ENST00000335953       11 [113930315, 114121398]      + | ENST00000335953
##   ENST00000541602       11 [113930447, 114060486]      + | ENST00000541602
##   ENST00000392996       11 [113931229, 114121374]      + | ENST00000392996
##   ENST00000539918       11 [113935134, 114118066]      + | ENST00000539918
##                                tx_biotype tx_cds_seq_start tx_cds_seq_end
##                               <character>        <integer>      <integer>
##   ENST00000335953          protein_coding        113934023      114121277
##   ENST00000541602         retained_intron             <NA>           <NA>
##   ENST00000392996          protein_coding        113934023      114121277
##   ENST00000539918 nonsense_mediated_decay        113935134      113992549
##                           gene_id         tx_name
##                       <character>     <character>
##   ENST00000335953 ENSG00000109906 ENST00000335953
##   ENST00000541602 ENSG00000109906 ENST00000541602
##   ENST00000392996 ENSG00000109906 ENST00000392996
##   ENST00000539918 ENSG00000109906 ENST00000539918
##   -------
##   seqinfo: 1 sequence from GRCh37 genome

The GRangesFilter supports also GRanges defining multiple regions and a query will return all features overlapping any of these regions. Besides using the GRangesFilter it is also possible to search for transcripts or exons overlapping genomic regions using the exonsByOverlaps or transcriptsByOverlaps known from the GenomicFeatures package. Note that the implementation of these methods for EnsDb objects supports also to use filters to further fine-tune the query.

The functions listGenebiotypes and listTxbiotypes can be used to get an overview of allowed/available gene and transcript biotype

## Get all gene biotypes from the database. The GeneBiotypeFilter
## allows to filter on these values.
listGenebiotypes(edb)
##  [1] "protein_coding"           "pseudogene"              
##  [3] "processed_transcript"     "antisense"               
##  [5] "lincRNA"                  "polymorphic_pseudogene"  
##  [7] "IG_V_pseudogene"          "IG_V_gene"               
##  [9] "sense_overlapping"        "sense_intronic"          
## [11] "TR_V_gene"                "misc_RNA"                
## [13] "snRNA"                    "miRNA"                   
## [15] "snoRNA"                   "rRNA"                    
## [17] "Mt_tRNA"                  "Mt_rRNA"                 
## [19] "IG_C_gene"                "IG_J_gene"               
## [21] "TR_J_gene"                "TR_C_gene"               
## [23] "TR_V_pseudogene"          "TR_J_pseudogene"         
## [25] "IG_D_gene"                "IG_C_pseudogene"         
## [27] "TR_D_gene"                "IG_J_pseudogene"         
## [29] "3prime_overlapping_ncrna" "processed_pseudogene"    
## [31] "LRG_gene"
## Get all transcript biotypes from the database.
listTxbiotypes(edb)
##  [1] "protein_coding"                    
##  [2] "processed_transcript"              
##  [3] "retained_intron"                   
##  [4] "nonsense_mediated_decay"           
##  [5] "unitary_pseudogene"                
##  [6] "non_stop_decay"                    
##  [7] "unprocessed_pseudogene"            
##  [8] "processed_pseudogene"              
##  [9] "transcribed_unprocessed_pseudogene"
## [10] "antisense"                         
## [11] "lincRNA"                           
## [12] "polymorphic_pseudogene"            
## [13] "transcribed_processed_pseudogene"  
## [14] "miRNA"                             
## [15] "pseudogene"                        
## [16] "IG_V_pseudogene"                   
## [17] "snoRNA"                            
## [18] "IG_V_gene"                         
## [19] "sense_overlapping"                 
## [20] "sense_intronic"                    
## [21] "TR_V_gene"                         
## [22] "snRNA"                             
## [23] "misc_RNA"                          
## [24] "rRNA"                              
## [25] "Mt_tRNA"                           
## [26] "Mt_rRNA"                           
## [27] "IG_C_gene"                         
## [28] "IG_J_gene"                         
## [29] "TR_J_gene"                         
## [30] "TR_C_gene"                         
## [31] "TR_V_pseudogene"                   
## [32] "TR_J_pseudogene"                   
## [33] "IG_D_gene"                         
## [34] "IG_C_pseudogene"                   
## [35] "TR_D_gene"                         
## [36] "IG_J_pseudogene"                   
## [37] "3prime_overlapping_ncrna"          
## [38] "translated_processed_pseudogene"   
## [39] "LRG_gene"

Data can be fetched in an analogous way using the exons and genes methods. In the example below we retrieve gene_name, entrezid and the gene_biotype of all genes in the database which names start with “BCL2”.

## We're going to fetch all genes which names start with BCL. To this end
## we define a GenenameFilter with partial matching, i.e. condition "like"
## and a % for any character/string.
BCLs <- genes(edb,
          columns = c("gene_name", "entrezid", "gene_biotype"),
          filter = GenenameFilter("BCL", condition = "startsWith"),
          return.type = "DataFrame")
nrow(BCLs)
## [1] 25
BCLs
## DataFrame with 25 rows and 4 columns
##       gene_name entrezid   gene_biotype         gene_id
##     <character>   <list>    <character>     <character>
## 1         BCL10     8915 protein_coding ENSG00000142867
## 2        BCL11A    53335 protein_coding ENSG00000119866
## 3        BCL11B    64919 protein_coding ENSG00000127152
## 4          BCL2      596 protein_coding ENSG00000171791
## 5        BCL2A1      597 protein_coding ENSG00000140379
## ...         ...      ...            ...             ...
## 21        BCL7C     9274 protein_coding ENSG00000099385
## 22         BCL9      607 protein_coding ENSG00000116128
## 23         BCL9      607 protein_coding ENSG00000266095
## 24        BCL9L   283149 protein_coding ENSG00000186174
## 25       BCLAF1     9774 protein_coding ENSG00000029363

Sometimes it might be useful to know the length of genes or transcripts (i.e. the total sum of nucleotides covered by their exons). Below we calculate the mean length of transcripts from protein coding genes on chromosomes X and Y as well as the average length of snoRNA, snRNA and rRNA transcripts encoded on these chromosomes. For the first query we combine two AnnotationFilter objects using an AnnotationFilterList object, in the second we define the query using a filter expression.

## determine the average length of snRNA, snoRNA and rRNA genes encoded on
## chromosomes X and Y.
mean(lengthOf(edb, of = "tx", filter = AnnotationFilterList(
                                  GeneBiotypeFilter(c("snRNA", "snoRNA", "rRNA")),
                                  SeqNameFilter(c("X", "Y")))))
## [1] 116.3046
## determine the average length of protein coding genes encoded on the same
## chromosomes.
mean(lengthOf(edb, of = "tx", filter = ~ gene_biotype == "protein_coding" &
                                  seq_name %in% c("X", "Y")))
## [1] 1920

Not unexpectedly, transcripts of protein coding genes are longer than those of snRNA, snoRNA or rRNA genes.

At last we extract the first two exons of each transcript model from the database.

## Extract all exons 1 and (if present) 2 for all genes encoded on the
## Y chromosome
exons(edb, columns = c("tx_id", "exon_idx"),
      filter = list(SeqNameFilter("Y"),
                    ExonRankFilter(3, condition = "<")))
## GRanges object with 1287 ranges and 3 metadata columns:
##                   seqnames               ranges strand |           tx_id
##                      <Rle>            <IRanges>  <Rle> |     <character>
##   ENSE00002088309        Y   [2652790, 2652894]      + | ENST00000516032
##   ENSE00001494622        Y   [2654896, 2655740]      - | ENST00000383070
##   ENSE00002323146        Y   [2655049, 2655069]      - | ENST00000525526
##   ENSE00002201849        Y   [2655075, 2655644]      - | ENST00000525526
##   ENSE00002214525        Y   [2655145, 2655168]      - | ENST00000534739
##               ...      ...                  ...    ... .             ...
##   ENSE00001632993        Y [28737695, 28737748]      - | ENST00000456738
##   ENSE00001616687        Y [28772667, 28773306]      - | ENST00000435741
##   ENSE00001638296        Y [28779492, 28779578]      - | ENST00000435945
##   ENSE00001797328        Y [28780670, 28780799]      - | ENST00000435945
##   ENSE00001794473        Y [59001391, 59001635]      + | ENST00000431853
##                    exon_idx         exon_id
##                   <integer>     <character>
##   ENSE00002088309         1 ENSE00002088309
##   ENSE00001494622         1 ENSE00001494622
##   ENSE00002323146         2 ENSE00002323146
##   ENSE00002201849         1 ENSE00002201849
##   ENSE00002214525         2 ENSE00002214525
##               ...       ...             ...
##   ENSE00001632993         1 ENSE00001632993
##   ENSE00001616687         1 ENSE00001616687
##   ENSE00001638296         2 ENSE00001638296
##   ENSE00001797328         1 ENSE00001797328
##   ENSE00001794473         1 ENSE00001794473
##   -------
##   seqinfo: 1 sequence from GRCh37 genome

3 Extracting gene/transcript/exon models for RNASeq feature counting

For the feature counting step of an RNAseq experiment, the gene or transcript models (defined by the chromosomal start and end positions of their exons) have to be known. To extract these from an Ensembl based annotation package, the exonsBy, genesBy and transcriptsBy methods can be used in an analogous way as in TxDb packages generated by the GenomicFeatures package. However, the transcriptsBy method does not, in contrast to the method in the GenomicFeatures package, allow to return transcripts by “cds”. While the annotation packages built by the ensembldb contain the chromosomal start and end coordinates of the coding region (for protein coding genes) they do not assign an ID to each CDS.

A simple use case is to retrieve all genes encoded on chromosomes X and Y from the database.

TxByGns <- transcriptsBy(edb, by = "gene", filter = SeqNameFilter(c("X", "Y")))
TxByGns
## GRangesList object of length 2908:
## $ENSG00000000003 
## GRanges object with 3 ranges and 6 metadata columns:
##       seqnames               ranges strand |           tx_id
##          <Rle>            <IRanges>  <Rle> |     <character>
##   [1]        X [99888439, 99894988]      - | ENST00000494424
##   [2]        X [99883667, 99891803]      - | ENST00000373020
##   [3]        X [99887538, 99891686]      - | ENST00000496771
##                 tx_biotype tx_cds_seq_start tx_cds_seq_end         gene_id
##                <character>        <integer>      <integer>     <character>
##   [1] processed_transcript             <NA>           <NA> ENSG00000000003
##   [2]       protein_coding         99885795       99891691 ENSG00000000003
##   [3] processed_transcript             <NA>           <NA> ENSG00000000003
##               tx_name
##           <character>
##   [1] ENST00000494424
##   [2] ENST00000373020
##   [3] ENST00000496771
## 
## $ENSG00000000005 
## GRanges object with 2 ranges and 6 metadata columns:
##       seqnames               ranges strand |           tx_id
##   [1]        X [99839799, 99854882]      + | ENST00000373031
##   [2]        X [99848621, 99852528]      + | ENST00000485971
##                 tx_biotype tx_cds_seq_start tx_cds_seq_end         gene_id
##   [1]       protein_coding         99840016       99854714 ENSG00000000005
##   [2] processed_transcript             <NA>           <NA> ENSG00000000005
##               tx_name
##   [1] ENST00000373031
##   [2] ENST00000485971
## 
## $ENSG00000001497 
## GRanges object with 6 ranges and 6 metadata columns:
##       seqnames               ranges strand |           tx_id
##   [1]        X [64732463, 64754655]      - | ENST00000484069
##   [2]        X [64732462, 64754636]      - | ENST00000374811
##   [3]        X [64732463, 64754636]      - | ENST00000374804
##   [4]        X [64732463, 64754636]      - | ENST00000312391
##   [5]        X [64732462, 64754634]      - | ENST00000374807
##   [6]        X [64740309, 64743497]      - | ENST00000469091
##                    tx_biotype tx_cds_seq_start tx_cds_seq_end
##   [1] nonsense_mediated_decay         64744901       64754595
##   [2]          protein_coding         64732655       64754595
##   [3]          protein_coding         64732655       64754595
##   [4]          protein_coding         64744901       64754595
##   [5]          protein_coding         64732655       64754595
##   [6]          protein_coding         64740535       64743497
##               gene_id         tx_name
##   [1] ENSG00000001497 ENST00000484069
##   [2] ENSG00000001497 ENST00000374811
##   [3] ENSG00000001497 ENST00000374804
##   [4] ENSG00000001497 ENST00000312391
##   [5] ENSG00000001497 ENST00000374807
##   [6] ENSG00000001497 ENST00000469091
## 
## ...
## <2905 more elements>
## -------
## seqinfo: 2 sequences from GRCh37 genome

Since Ensembl contains also definitions of genes that are on chromosome variants (supercontigs), it is advisable to specify the chromosome names for which the gene models should be returned.

In a real use case, we might thus want to retrieve all genes encoded on the standard chromosomes. In addition it is advisable to use a GeneIdFilter to restrict to Ensembl genes only, as also LRG (Locus Reference Genomic) genes2 are defined in the database, which are partially redundant with Ensembl genes.

## will just get exons for all genes on chromosomes 1 to 22, X and Y.
## Note: want to get rid of the "LRG" genes!!!
EnsGenes <- exonsBy(edb, by = "gene", filter = AnnotationFilterList(
                                          SeqNameFilter(c(1:22, "X", "Y")),
                                          GeneIdFilter("ENSG", "startsWith")))

The code above returns a GRangesList that can be used directly as an input for the summarizeOverlaps function from the GenomicAlignments package 3.

Alternatively, the above GRangesList can be transformed to a data.frame in SAF format that can be used as an input to the featureCounts function of the Rsubread package 4.

## Transforming the GRangesList into a data.frame in SAF format
EnsGenes.SAF <- toSAF(EnsGenes)

Note that the ID by which the GRangesList is split is used in the SAF formatted data.frame as the GeneID. In the example below this would be the Ensembl gene IDs, while the start, end coordinates (along with the strand and chromosomes) are those of the the exons.

In addition, the disjointExons function (similar to the one defined in GenomicFeatures) can be used to generate a GRanges of non-overlapping exon parts which can be used in the DEXSeq package.

## Create a GRanges of non-overlapping exon parts.
DJE <- disjointExons(edb, filter = AnnotationFilterList(
                  SeqNameFilter(c(1:22, "X", "Y")),
                  GeneIdFilter("ENSG%", "startsWith")))

4 Retrieving sequences for gene/transcript/exon models

The methods to retrieve exons, transcripts and genes (i.e. exons, transcripts and genes) return by default GRanges objects that can be used to retrieve sequences using the getSeq method e.g. from BSgenome packages. The basic workflow is thus identical to the one for TxDb packages, however, it is not straight forward to identify the BSgenome package with the matching genomic sequence. Most BSgenome packages are named according to the genome build identifier used in UCSC which does not (always) match the genome build name used by Ensembl. Using the Ensembl version provided by the EnsDb, the correct genomic sequence can however be retrieved easily from the AnnotationHub using the getGenomeFaFile. If no Fasta file matching the Ensembl version is available, the function tries to identify a Fasta file with the correct genome build from the closest Ensembl release and returns that instead.

In the code block below we retrieve first the FaFile with the genomic DNA sequence, extract the genomic start and end coordinates for all genes defined in the package, subset to genes encoded on sequences available in the FaFile and extract all of their sequences. Note: these sequences represent the sequence between the chromosomal start and end coordinates of the gene.

library(EnsDb.Hsapiens.v75)
library(Rsamtools)
edb <- EnsDb.Hsapiens.v75

## Get the FaFile with the genomic sequence matching the Ensembl version
## using the AnnotationHub package.
Dna <- getGenomeFaFile(edb)

## Get start/end coordinates of all genes.
genes <- genes(edb)
## Subset to all genes that are encoded on chromosomes for which
## we do have DNA sequence available.
genes <- genes[seqnames(genes) %in% seqnames(seqinfo(Dna))]

## Get the gene sequences, i.e. the sequence including the sequence of
## all of the gene's exons and introns.
geneSeqs <- getSeq(Dna, genes)

To retrieve the (exonic) sequence of transcripts (i.e. without introns) we can use directly the extractTranscriptSeqs method defined in the GenomicFeatures on the EnsDb object, eventually using a filter to restrict the query.

## get all exons of all transcripts encoded on chromosome Y
yTx <- exonsBy(edb, filter = SeqNameFilter("Y"))

## Retrieve the sequences for these transcripts from the FaFile.
library(GenomicFeatures)
yTxSeqs <- extractTranscriptSeqs(Dna, yTx)
yTxSeqs

## Extract the sequences of all transcripts encoded on chromosome Y.
yTx <- extractTranscriptSeqs(Dna, edb, filter = SeqNameFilter("Y"))

## Along these lines, we could use the method also to retrieve the coding sequence
## of all transcripts on the Y chromosome.
cdsY <- cdsBy(edb, filter = SeqNameFilter("Y"))
extractTranscriptSeqs(Dna, cdsY)

Note: in the next section we describe how transcript sequences can be retrieved from a BSgenome package that is based on UCSC, not Ensembl.

5 Integrating annotations from Ensembl based EnsDb packages with UCSC based annotations

Sometimes it might be useful to combine (Ensembl based) annotations from EnsDb packages/objects with annotations from other Bioconductor packages, that might base on UCSC annotations. To support such an integration of annotations, the ensembldb packages implements the seqlevelsStyle and seqlevelsStyle<- from the GenomeInfoDb package that allow to change the style of chromosome naming. Thus, sequence/chromosome names other than those used by Ensembl can be used in, and are returned by, the queries to EnsDb objects as long as a mapping for them is provided by the GenomeInfoDb package (which provides a mapping mostly between UCSC, NCBI and Ensembl chromosome names for the main chromosomes).

In the example below we change the seqnames style to UCSC.

## Change the seqlevels style form Ensembl (default) to UCSC:
seqlevelsStyle(edb) <- "UCSC"

## Now we can use UCSC style seqnames in SeqNameFilters or GRangesFilter:
genesY <- genes(edb, filter = ~ seq_name == "chrY")
## The seqlevels of the returned GRanges are also in UCSC style
seqlevels(genesY)
## [1] "chrY"

Note that in most instances no mapping is available for sequences not corresponding to the main chromosomes (i.e. contigs, patched chromosomes etc). What is returned in cases in which no mapping is available can be specified with the global ensembldb.seqnameNotFound option. By default (with ensembldb.seqnameNotFound set to “ORIGINAL”), the original seqnames (i.e. the ones from Ensembl) are returned. With ensembldb.seqnameNotFound “MISSING” each time a seqname can not be found an error is thrown. For all other cases (e.g. ensembldb.seqnameNotFound = NA) the value of the option is returned.

seqlevelsStyle(edb) <- "UCSC"

## Getting the default option:
getOption("ensembldb.seqnameNotFound")
## [1] "ORIGINAL"
## Listing all seqlevels in the database.
seqlevels(edb)[1:30]
## Warning in .formatSeqnameByStyleFromQuery(x, sn, ifNotFound): More than 5
## seqnames with seqlevels style of the database (Ensembl) could not be mapped
## to the seqlevels style: UCSC!) Returning the orginal seqnames for these.
##  [1] "chr1"       "chr10"      "chr11"      "chr12"      "chr13"     
##  [6] "chr14"      "chr15"      "chr16"      "chr17"      "chr18"     
## [11] "chr19"      "chr2"       "chr20"      "chr21"      "chr22"     
## [16] "chr3"       "chr4"       "chr5"       "chr6"       "chr7"      
## [21] "chr8"       "chr9"       "GL000191.1" "GL000192.1" "GL000193.1"
## [26] "GL000194.1" "GL000195.1" "GL000196.1" "GL000199.1" "GL000201.1"
## Setting the option to NA, thus, for each seqname for which no mapping is available,
## NA is returned.
options(ensembldb.seqnameNotFound=NA)
seqlevels(edb)[1:30]
## Warning in .formatSeqnameByStyleFromQuery(x, sn, ifNotFound): More than 5
## seqnames with seqlevels style of the database (Ensembl) could not be mapped
## to the seqlevels style: UCSC!) Returning NA for these.
##  [1] "chr1"  "chr10" "chr11" "chr12" "chr13" "chr14" "chr15" "chr16" "chr17"
## [10] "chr18" "chr19" "chr2"  "chr20" "chr21" "chr22" "chr3"  "chr4"  "chr5" 
## [19] "chr6"  "chr7"  "chr8"  "chr9"  NA      NA      NA      NA      NA     
## [28] NA      NA      NA
## Resetting the option.
options(ensembldb.seqnameNotFound = "ORIGINAL")

Next we retrieve transcript sequences from genes encoded on chromosome Y using the BSGenome package for the human genome from UCSC. The specified version hg19 matches the genome build of Ensembl version 75, i.e. GRCh37. Note that while we changed the style of the seqnames to UCSC we did not change the naming of the genome release.

library(BSgenome.Hsapiens.UCSC.hg19)
bsg <- BSgenome.Hsapiens.UCSC.hg19

## Get the genome version
unique(genome(bsg))
## [1] "hg19"
unique(genome(edb))
## [1] "GRCh37"
## Although differently named, both represent genome build GRCh37.

## Extract the full transcript sequences.
yTxSeqs <- extractTranscriptSeqs(bsg, exonsBy(edb, "tx",
                          filter = SeqNameFilter("chrY")))

yTxSeqs
##   A DNAStringSet instance of length 731
##       width seq                                          names               
##   [1]  5239 GCCTAGTGCGCGCGCAGTAAC...TAAATGTTTACTTGTATATG ENST00000155093
##   [2]  4023 ATGTTTAGGGTTGGCTTCTTA...TGGAAACACATCCCTTGTAA ENST00000215473
##   [3]   802 AGAGGACCAAGCCTCCCTGTG...ATAAAATGTTTTAAAAATCA ENST00000215479
##   [4]   910 TGTCTGTCAGAGCTGTCAGCC...AACACTGGTATATTTCTGTT ENST00000250776
##   [5]  1305 TTCCAGGATATGAACTCTACA...AATCCTGTGGCTGTAGGAAA ENST00000250784
##   ...   ... ...
## [727]   333 ATGGATGAAGAAGAGAAAACC...GTGAACTTTCTAGATTGCAT ENST00000604924
## [728]  1247 CATGGCGGGGTTCCTGCCTTC...CTTTGGAGTAATGTCTTAGT ENST00000605584
## [729]   199 CAGTTCTCGCTCCTGTGCAGC...TGGTCTGGGTGGCTTCTGGA ENST00000605663
## [730]   276 GCCCCAGGAGGAAAGGGGGAC...AAATAAAGAACAGCGCATTC ENST00000606439
## [731]   444 ATGGGAGCCACTGGGCTTGGC...ACGTTCATGAAGAAGACTAA ENST00000607210
## Extract just the CDS
Test <- cdsBy(edb, "tx", filter = SeqNameFilter("chrY"))
yTxCds <- extractTranscriptSeqs(bsg, cdsBy(edb, "tx",
                                           filter = SeqNameFilter("chrY")))
yTxCds
##   A DNAStringSet instance of length 160
##       width seq                                          names               
##   [1]  2406 ATGGATGAAGATGAATTTGAA...AAGAAGTTGGTCTGCCCTAA ENST00000155093
##   [2]  4023 ATGTTTAGGGTTGGCTTCTTA...TGGAAACACATCCCTTGTAA ENST00000215473
##   [3]   579 ATGGGGACCTGGATTTTGTTT...AGCAGGAGGAAGTGGATTAA ENST00000215479
##   [4]   792 ATGGCCCGGGGCCCCAAGAAG...CCAAACAGAGCAGTGGCTAA ENST00000250784
##   [5]   378 ATGAGTCCAAAGCCGAGAGCC...CTACTCCCCTATCTCCCTGA ENST00000250823
##   ...   ... ...
## [156]    63 CGCAAGGATTTAAAAGAGATG...CACCCTGTTGGCCAGGCTAG ENST00000601700
## [157]    42 CTTGATACAAAGAATCAATTTAATTTTAAGATTGTCTATCTT   ENST00000601705
## [158]    33 ATGATGACGCTTGTCCCCAGAGCCAGGACACGT            ENST00000602680
## [159]    33 ATGATGACGCTTGTCCCCAGAGCCAGGACACGT            ENST00000602732
## [160]    33 ATGATGACGCTTGTCCCCAGAGCCAGGACACGT            ENST00000602770

At last changing the seqname style to the default value "Ensembl".

seqlevelsStyle(edb) <- "Ensembl"

6 Interactive annotation lookup using the shiny web app

In addition to the genes, transcripts and exons methods it is possibly to search interactively for gene/transcript/exon annotations using the internal, shiny based, web application. The application can be started with the runEnsDbApp() function. The search results from this app can also be returned to the R workspace either as a data.frame or GRanges object.

7 Plotting gene/transcript features using ensembldb and Gviz and ggbio

The Gviz package provides functions to plot genes and transcripts along with other data on a genomic scale. Gene models can be provided either as a data.frame, GRanges, TxDB database, can be fetched from biomart and can also be retrieved from ensembldb.

Below we generate a GeneRegionTrack fetching all transcripts from a certain region on chromosome Y.

Note that if we want in addition to work also with BAM files that were aligned against DNA sequences retrieved from Ensembl or FASTA files representing genomic DNA sequences from Ensembl we should change the ucscChromosomeNames option from Gviz to FALSE (i.e. by calling options(ucscChromosomeNames = FALSE)). This is not necessary if we just want to retrieve gene models from an EnsDb object, as the ensembldb package internally checks the ucscChromosomeNames option and, depending on that, maps Ensembl chromosome names to UCSC chromosome names.

## Loading the Gviz library
library(Gviz)
library(EnsDb.Hsapiens.v75)
edb <- EnsDb.Hsapiens.v75

## Retrieving a Gviz compatible GRanges object with all genes
## encoded on chromosome Y.
gr <- getGeneRegionTrackForGviz(edb, chromosome = "Y",
                                start = 20400000, end = 21400000)
## Define a genome axis track
gat <- GenomeAxisTrack()

## We have to change the ucscChromosomeNames option to FALSE to enable Gviz usage
## with non-UCSC chromosome names.
options(ucscChromosomeNames = FALSE)

plotTracks(list(gat, GeneRegionTrack(gr)))

options(ucscChromosomeNames = TRUE)

Above we had to change the option ucscChromosomeNames to FALSE in order to use it with non-UCSC chromosome names. Alternatively, we could however also change the seqnamesStyle of the EnsDb object to UCSC. Note that we have to use now also chromosome names in the UCSC style in the SeqNameFilter (i.e. “chrY” instead of Y).

seqlevelsStyle(edb) <- "UCSC"
## Retrieving the GRanges objects with seqnames corresponding to UCSC chromosome names.
gr <- getGeneRegionTrackForGviz(edb, chromosome = "chrY",
                                start = 20400000, end = 21400000)
## Warning in .formatSeqnameByStyleForQuery(x, sn, ifNotFound): Seqnames:
## Y could not be mapped to the seqlevels style of the database (Ensembl)!
## Returning the orginal seqnames for these.
seqnames(gr)
## factor-Rle of length 218 with 1 run
##   Lengths:  218
##   Values : chrY
## Levels(1): chrY
## Define a genome axis track
gat <- GenomeAxisTrack()
plotTracks(list(gat, GeneRegionTrack(gr)))

We can also use the filters from the ensembldb package to further refine what transcripts are fetched, like in the example below, in which we create two different gene region tracks, one for protein coding genes and one for lincRNAs.

protCod <- getGeneRegionTrackForGviz(edb, chromosome = "chrY",
                                     start = 20400000, end = 21400000,
                                     filter = GeneBiotypeFilter("protein_coding"))
lincs <- getGeneRegionTrackForGviz(edb, chromosome = "chrY",
                                   start = 20400000, end = 21400000,
                                   filter = GeneBiotypeFilter("lincRNA"))

plotTracks(list(gat, GeneRegionTrack(protCod, name = "protein coding"),
                GeneRegionTrack(lincs, name = "lincRNAs")), transcriptAnnotation = "symbol")

## At last we change the seqlevels style again to Ensembl
seqlevelsStyle <- "Ensembl"

Alternatively, we can also use ggbio for plotting. For ggplot we can directly pass the EnsDb object along with optional filters (or as in the example below a filter expression as a formula).

library(ggbio)

## Create a plot for all transcripts of the gene SKA2
autoplot(edb, ~ genename == "SKA2")

To plot the genomic region and plot genes from both strands we can use a GRangesFilter.

## Get the chromosomal region in which the gene is encoded
ska2 <- genes(edb, filter = ~ genename == "SKA2")
strand(ska2) <- "*"
autoplot(edb, GRangesFilter(ska2), names.expr = "gene_name")

8 Using EnsDb objects in the AnnotationDbi framework

Most of the methods defined for objects extending the basic annotation package class AnnotationDbi are also defined for EnsDb objects (i.e. methods columns, keytypes, keys, mapIds and select). While these methods can be used analogously to basic annotation packages, the implementation for EnsDb objects also support the filtering framework of the ensembldb package.

In the example below we first evaluate all the available columns and keytypes in the database and extract then the gene names for all genes encoded on chromosome X.

library(EnsDb.Hsapiens.v75)
edb <- EnsDb.Hsapiens.v75

## List all available columns in the database.
columns(edb)
##  [1] "ENTREZID"            "EXONID"              "EXONIDX"            
##  [4] "EXONSEQEND"          "EXONSEQSTART"        "GENEBIOTYPE"        
##  [7] "GENEID"              "GENENAME"            "GENESEQEND"         
## [10] "GENESEQSTART"        "INTERPROACCESSION"   "ISCIRCULAR"         
## [13] "PROTDOMEND"          "PROTDOMSTART"        "PROTEINDOMAINID"    
## [16] "PROTEINDOMAINSOURCE" "PROTEINID"           "PROTEINSEQUENCE"    
## [19] "SEQCOORDSYSTEM"      "SEQLENGTH"           "SEQNAME"            
## [22] "SEQSTRAND"           "SYMBOL"              "TXBIOTYPE"          
## [25] "TXCDSSEQEND"         "TXCDSSEQSTART"       "TXID"               
## [28] "TXNAME"              "TXSEQEND"            "TXSEQSTART"         
## [31] "UNIPROTDB"           "UNIPROTID"           "UNIPROTMAPPINGTYPE"
## Note that these do *not* correspond to the actual column names
## of the database that can be passed to methods like exons, genes,
## transcripts etc. These column names can be listed with the listColumns
## method.
listColumns(edb)
##  [1] "seq_name"              "seq_length"            "is_circular"          
##  [4] "gene_id"               "entrezid"              "exon_id"              
##  [7] "exon_seq_start"        "exon_seq_end"          "gene_name"            
## [10] "gene_biotype"          "gene_seq_start"        "gene_seq_end"         
## [13] "seq_strand"            "seq_coord_system"      "symbol"               
## [16] "name"                  "value"                 "tx_id"                
## [19] "protein_id"            "protein_sequence"      "protein_domain_id"    
## [22] "protein_domain_source" "interpro_accession"    "prot_dom_start"       
## [25] "prot_dom_end"          "tx_biotype"            "tx_seq_start"         
## [28] "tx_seq_end"            "tx_cds_seq_start"      "tx_cds_seq_end"       
## [31] "tx_name"               "exon_idx"              "uniprot_id"           
## [34] "uniprot_db"            "uniprot_mapping_type"
## List all of the supported key types.
keytypes(edb)
##  [1] "ENTREZID"        "EXONID"          "GENEBIOTYPE"     "GENEID"         
##  [5] "GENENAME"        "PROTEINDOMAINID" "PROTEINID"       "SEQNAME"        
##  [9] "SEQSTRAND"       "SYMBOL"          "TXBIOTYPE"       "TXID"           
## [13] "TXNAME"          "UNIPROTID"
## Get all gene ids from the database.
gids <- keys(edb, keytype = "GENEID")
length(gids)
## [1] 64102
## Get all gene names for genes encoded on chromosome Y.
gnames <- keys(edb, keytype = "GENENAME", filter = SeqNameFilter("Y"))
head(gnames)
## [1] "KDM5D"   "DDX3Y"   "ZFY"     "TBL1Y"   "PCDH11Y" "AMELY"

In the next example we retrieve specific information from the database using the select method. First we fetch all transcripts for the genes BCL2 and BCL2L11. In the first call we provide the gene names, while in the second call we employ the filtering system to perform a more fine-grained query to fetch only the protein coding transcripts for these genes.

## Use the /standard/ way to fetch data.
select(edb, keys = c("BCL2", "BCL2L11"), keytype = "GENENAME",
       columns = c("GENEID", "GENENAME", "TXID", "TXBIOTYPE"))
##             GENEID GENENAME            TXID               TXBIOTYPE
## 1  ENSG00000171791     BCL2 ENST00000398117          protein_coding
## 2  ENSG00000171791     BCL2 ENST00000333681          protein_coding
## 3  ENSG00000171791     BCL2 ENST00000590515    processed_transcript
## 4  ENSG00000171791     BCL2 ENST00000589955          protein_coding
## 5  ENSG00000171791     BCL2 ENST00000444484          protein_coding
## 6  ENSG00000153094  BCL2L11 ENST00000432179          protein_coding
## 7  ENSG00000153094  BCL2L11 ENST00000308659          protein_coding
## 8  ENSG00000153094  BCL2L11 ENST00000393256          protein_coding
## 9  ENSG00000153094  BCL2L11 ENST00000393252          protein_coding
## 10 ENSG00000153094  BCL2L11 ENST00000433098 nonsense_mediated_decay
## 11 ENSG00000153094  BCL2L11 ENST00000405953          protein_coding
## 12 ENSG00000153094  BCL2L11 ENST00000415458 nonsense_mediated_decay
## 13 ENSG00000153094  BCL2L11 ENST00000436733 nonsense_mediated_decay
## 14 ENSG00000153094  BCL2L11 ENST00000437029 nonsense_mediated_decay
## 15 ENSG00000153094  BCL2L11 ENST00000452231 nonsense_mediated_decay
## 16 ENSG00000153094  BCL2L11 ENST00000361493 nonsense_mediated_decay
## 17 ENSG00000153094  BCL2L11 ENST00000431217 nonsense_mediated_decay
## 18 ENSG00000153094  BCL2L11 ENST00000439718 nonsense_mediated_decay
## 19 ENSG00000153094  BCL2L11 ENST00000438054          protein_coding
## 20 ENSG00000153094  BCL2L11 ENST00000357757          protein_coding
## 21 ENSG00000153094  BCL2L11 ENST00000393253          protein_coding
## 22 ENSG00000153094  BCL2L11 ENST00000337565          protein_coding
## Use the filtering system of ensembldb
select(edb, keys = ~ genename %in% c("BCL2", "BCL2L11") &
                tx_biotype == "protein_coding",
       columns = c("GENEID", "GENENAME", "TXID", "TXBIOTYPE"))
##             GENEID GENENAME            TXID      TXBIOTYPE
## 1  ENSG00000171791     BCL2 ENST00000398117 protein_coding
## 2  ENSG00000171791     BCL2 ENST00000333681 protein_coding
## 3  ENSG00000171791     BCL2 ENST00000589955 protein_coding
## 4  ENSG00000171791     BCL2 ENST00000444484 protein_coding
## 5  ENSG00000153094  BCL2L11 ENST00000432179 protein_coding
## 6  ENSG00000153094  BCL2L11 ENST00000308659 protein_coding
## 7  ENSG00000153094  BCL2L11 ENST00000393256 protein_coding
## 8  ENSG00000153094  BCL2L11 ENST00000393252 protein_coding
## 9  ENSG00000153094  BCL2L11 ENST00000405953 protein_coding
## 10 ENSG00000153094  BCL2L11 ENST00000438054 protein_coding
## 11 ENSG00000153094  BCL2L11 ENST00000357757 protein_coding
## 12 ENSG00000153094  BCL2L11 ENST00000393253 protein_coding
## 13 ENSG00000153094  BCL2L11 ENST00000337565 protein_coding

Finally, we use the mapIds method to establish a mapping between ids and values. In the example below we fetch transcript ids for the two genes from the example above.

## Use the default method, which just returns the first value for multi mappings.
mapIds(edb, keys = c("BCL2", "BCL2L11"), column = "TXID", keytype = "GENENAME")
##              BCL2           BCL2L11 
## "ENST00000398117" "ENST00000432179"
## Alternatively, specify multiVals="list" to return all mappings.
mapIds(edb, keys = c("BCL2", "BCL2L11"), column = "TXID", keytype = "GENENAME",
       multiVals = "list")
## $BCL2
## [1] "ENST00000398117" "ENST00000333681" "ENST00000590515" "ENST00000589955"
## [5] "ENST00000444484"
## 
## $BCL2L11
##  [1] "ENST00000432179" "ENST00000308659" "ENST00000393256" "ENST00000393252"
##  [5] "ENST00000433098" "ENST00000405953" "ENST00000415458" "ENST00000436733"
##  [9] "ENST00000437029" "ENST00000452231" "ENST00000361493" "ENST00000431217"
## [13] "ENST00000439718" "ENST00000438054" "ENST00000357757" "ENST00000393253"
## [17] "ENST00000337565"
## And, just like before, we can use filters to map only to protein coding transcripts.
mapIds(edb, keys = list(GenenameFilter(c("BCL2", "BCL2L11")),
                        TxBiotypeFilter("protein_coding")), column = "TXID",
       multiVals = "list")
## Warning in .mapIds(x = x, keys = keys, column = column, keytype = keytype, :
## Got 2 filter objects. Will use the keys of the first for the mapping!
## $BCL2
## [1] "ENST00000398117" "ENST00000333681" "ENST00000589955" "ENST00000444484"
## 
## $BCL2L11
## [1] "ENST00000432179" "ENST00000308659" "ENST00000393256" "ENST00000393252"
## [5] "ENST00000405953" "ENST00000438054" "ENST00000357757" "ENST00000393253"
## [9] "ENST00000337565"

Note that, if the filters are used, the ordering of the result does no longer match the ordering of the genes.

9 Important notes

These notes might explain eventually unexpected results (and, more importantly, help avoiding them):

  • The ordering of the results returned by the genes, exons, transcripts methods can be specified with the order.by parameter. The ordering of the results does however not correspond to the ordering of values in submitted filter objects. The exception is the select method. If a character vector of values or a single filter is passed with argument keys the ordering of results of this method matches the ordering of the key values or the values of the filter.

  • Results of exonsBy, transcriptsBy are always ordered by the by argument.

  • The CDS provided by EnsDb objects always includes both, the start and the stop codon.

  • Transcripts with multiple CDS are at present not supported by EnsDb.

  • At present, EnsDb support only genes/transcripts for which all of their exons are encoded on the same chromosome and the same strand.

  • Since a single Ensembl gene ID might be mapped to multiple NCBI Entrezgene IDs methods such as genes, transcripts etc return a list in the "entrezid" column of the resulting result object.

10 Getting or building EnsDb databases/packages

Some of the code in this section is not supposed to be automatically executed when the vignette is built, as this would require a working installation of the Ensembl Perl API, which is not expected to be available on each system. Also, building EnsDb from alternative sources, like GFF or GTF files takes some time and thus also these examples are not directly executed when the vignette is build.

10.1 Getting EnsDb databases

Some EnsDb databases are available as R packages from Bioconductor and can be simply installed with the biocLite function from the BiocInstaller package. The name of such annotation packages starts with EnsDb followed by the abbreviation of the organism and the Ensembl version on which the annotation bases. EnsDb.Hsapiens.v86 provides thus an EnsDb database for homo sapiens with annotations from Ensembl version 86.

Since Bioconductor version 3.5 EnsDb databases can also be retrieved directly from AnnotationHub.

library(AnnotationHub)
## Load the annotation resource.
ah <- AnnotationHub()

## Query for all available EnsDb databases
query(ah, "EnsDb")

We can simply fetch one of the databases.

ahDb <- query(ah, pattern = c("Xiphophorus Maculatus", "EnsDb", 87))
## What have we got
ahDb

Fetch the EnsDb and use it.

ahEdb <- ahDb[[1]]

## retriebe all genes
gns <- genes(ahEdb)

We could even make an annotation package from this EnsDb object using the makeEnsembldbPackage and passing dbfile(dbconn(ahEdb)) as ensdb argument.

10.2 Building annotation packages

10.2.1 Directly from Ensembl databases

The fetchTablesFromEnsembl function uses the Ensembl Perl API to retrieve the required annotations from an Ensembl database (e.g. from the main site ensembldb.ensembl.org). Thus, to use this functionality to build databases, the Ensembl Perl API needs to be installed (see 5 for details).

Below we create an EnsDb database by fetching the required data directly from the Ensembl core databases. The makeEnsembldbPackage function is then used to create an annotation package from this EnsDb containing all human genes for Ensembl version 75.

library(ensembldb)

## get all human gene/transcript/exon annotations from Ensembl (75)
## the resulting tables will be stored by default to the current working
## directory
fetchTablesFromEnsembl(75, species = "human")

## These tables can then be processed to generate a SQLite database
## containing the annotations (again, the function assumes the required
## txt files to be present in the current working directory)
DBFile <- makeEnsemblSQLiteFromTables()

## and finally we can generate the package
makeEnsembldbPackage(ensdb = DBFile, version = "0.99.12",
                     maintainer = "Johannes Rainer <johannes.rainer@eurac.edu>",
                     author = "J Rainer")

The generated package can then be build using R CMD build EnsDb.Hsapiens.v75 and installed with R CMD INSTALL EnsDb.Hsapiens.v75*. Note that we could directly generate an EnsDb instance by loading the database file, i.e. by calling edb <- EnsDb(DBFile) and work with that annotation object.

To fetch and build annotation packages for plant genomes (e.g. arabidopsis thaliana), the Ensembl genomes should be specified as a host, i.e. setting host to “mysql-eg-publicsql.ebi.ac.uk”, port to 4157 and species to e.g. “arabidopsis thaliana”.

10.2.2 From a GTF or GFF file

Alternatively, the ensDbFromAH, ensDbFromGff, ensDbFromGRanges and ensDbFromGtf functions allow to build EnsDb SQLite files from a GRanges object or GFF/GTF files from Ensembl (either provided as files or via AnnotationHub). These functions do not depend on the Ensembl Perl API, but require a working internet connection to fetch the chromosome lengths from Ensembl as these are not provided within GTF or GFF files. Also note that protein annotations are usually not available in GTF or GFF files, thus, such annotations will not be included in the generated EnsDb database - protein annotations are only available in EnsDb databases created with the Ensembl Perl API (such as the ones provided through AnnotationHub or as Bioconductor packages).

In the next example we create an EnsDb database using the AnnotationHub package and load also the corresponding genomic DNA sequence matching the Ensembl version. We thus first query the AnnotationHub package for all resources available for Mus musculus and the Ensembl release 77. Next we create the EnsDb object from the appropriate AnnotationHub resource. We then use the getGenomeFaFile method on the EnsDb to directly look up and retrieve the correct or best matching FaFile with the genomic DNA sequence. At last we retrieve the sequences of all exons using the getSeq method.

## Load the AnnotationHub data.
library(AnnotationHub)
ah <- AnnotationHub()

## Query all available files for Ensembl release 77 for
## Mus musculus.
query(ah, c("Mus musculus", "release-77"))

## Get the resource for the gtf file with the gene/transcript definitions.
Gtf <- ah["AH28822"]
## Create a EnsDb database file from this.
DbFile <- ensDbFromAH(Gtf)
## We can either generate a database package, or directly load the data
edb <- EnsDb(DbFile)


## Identify and get the FaFile object with the genomic DNA sequence matching
## the EnsDb annotation.
Dna <- getGenomeFaFile(edb)
library(Rsamtools)
## We next retrieve the sequence of all exons on chromosome Y.
exons <- exons(edb, filter = SeqNameFilter("Y"))
exonSeq <- getSeq(Dna, exons)

## Alternatively, look up and retrieve the toplevel DNA sequence manually.
Dna <- ah[["AH22042"]]

In the example below we load a GRanges containing gene definitions for genes encoded on chromosome Y and generate a EnsDb SQLite database from that information.

## Generate a sqlite database from a GRanges object specifying
## genes encoded on chromosome Y
load(system.file("YGRanges.RData", package = "ensembldb"))
Y

## Create the EnsDb database file
DB <- ensDbFromGRanges(Y, path = tempdir(), version = 75,
               organism = "Homo_sapiens")

## Load the database
edb <- EnsDb(DB)
edb

Alternatively we can build the annotation database using the ensDbFromGtf ensDbFromGff functions, that extract most of the required data from a GTF respectively GFF (version 3) file which can be downloaded from Ensembl (e.g. from ftp://ftp.ensembl.org/pub/release-75/gtf/homo_sapiens for human gene definitions from Ensembl version 75; for plant genomes etc, files can be retrieved from ftp://ftp.ensemblgenomes.org). All information except the chromosome lengths, the NCBI Entrezgene IDs and protein annotations can be extracted from these GTF files. The function also tries to retrieve chromosome length information automatically from Ensembl.

Below we create the annotation from a gtf file that we fetch directly from Ensembl.

library(ensembldb)

## the GTF file can be downloaded from
## ftp://ftp.ensembl.org/pub/release-75/gtf/homo_sapiens/
gtffile <- "Homo_sapiens.GRCh37.75.gtf.gz"
## generate the SQLite database file
DB <- ensDbFromGtf(gtf = gtffile)

## load the DB file directly
EDB <- EnsDb(DB)

## alternatively, build the annotation package
## and finally we can generate the package
makeEnsembldbPackage(ensdb = DB, version = "0.99.12",
                     maintainer = "Johannes Rainer <johannes.rainer@eurac.edu>",
                     author = "J Rainer")

11 Database layout

The database consists of the following tables and attributes (the layout is also shown in Figure 165). Note that the protein-specific annotations might not be available in all EnsDB databases (e.g. such ones created with ensembldb version < 1.7 or created from GTF or GFF files).

  • gene: all gene specific annotations.
    • gene_id: the Ensembl ID of the gene.
    • gene_name: the name (symbol) of the gene.
    • gene_biotype: the biotype of the gene.
    • gene_seq_start: the start coordinate of the gene on the sequence (usually a chromosome).
    • gene_seq_end: the end coordinate of the gene on the sequence.
    • seq_name: the name of the sequence (usually the chromosome name).
    • seq_strand: the strand on which the gene is encoded.
    • seq_coord_system: the coordinate system of the sequence.
    • description: the description of the gene.
  • entrezgene: mapping of Ensembl genes to NCBI Entrezgene identifiers. Note that this mapping can be a one-to-many mapping.
    • gene_id: the Ensembl gene ID.
    • entrezid: the NCBI Entrezgene ID.
  • tx: all transcript related annotations. Note that while no tx_name column is available in this database column, all methods to retrieve data from the database support also this column. The returned values are however the ID of the transcripts.

    • tx_id: the Ensembl transcript ID.
    • tx_biotype: the biotype of the transcript.
    • tx_seq_start: the start coordinate of the transcript.
    • tx_seq_end: the end coordinate of the transcript.
    • tx_cds_seq_start: the start coordinate of the coding region of the transcript (NULL for non-coding transcripts).
    • tx_cds_seq_end: the end coordinate of the coding region of the transcript.
    • gene_id: the gene to which the transcript belongs.

    EnsDb databases for more recent Ensembl releases have also a column tx_support_level providing the evidence level for a transcript (1 high evidence, 5 low evidence, NA no evidence calculated).

  • exon: all exon related annotation.
    • exon_id: the Ensembl exon ID.
    • exon_seq_start: the start coordinate of the exon.
    • exon_seq_end: the end coordinate of the exon.
  • tx2exon: provides the n:m mapping between transcripts and exons.
    • tx_id: the Ensembl transcript ID.
    • exon_id: the Ensembl exon ID.
    • exon_idx: the index of the exon in the corresponding transcript, always from 5’ to 3’ of the transcript.
  • chromosome: provides some information about the chromosomes.
    • seq_name: the name of the sequence/chromosome.
    • seq_length: the length of the sequence.
    • is_circular: whether the sequence in circular.
  • protein: provides protein annotation for a (coding) transcript.
    • protein_id: the Ensembl protein ID.
    • tx_id: the transcript ID which CDS encodes the protein.
    • protein_sequence: the peptide sequence of the protein (translated from the transcript’s coding sequence after applying eventual RNA editing).
  • uniprot: provides the mapping from Ensembl protein ID(s) to Uniprot ID(s). Not all Ensembl proteins are annotated to Uniprot IDs, also, each Ensembl protein might be mapped to multiple Uniprot IDs.
    • protein_id: the Ensembl protein ID.
    • uniprot_id: the Uniprot ID.
    • uniprot_db: the Uniprot database in which the ID is defined.
    • uniprot_mapping_type: the type of the mapping method that was used to assign the Uniprot ID to an Ensembl protein ID.
  • protein_domain: provides protein domain annotations and mapping to proteins.
    • protein_id: the Ensembl protein ID on which the protein domain is present.
    • protein_domain_id: the ID of the protein domain (from the protein domain source).
    • protein_domain_source: the source/analysis method in/by which the protein domain was defined (such as pfam etc).
    • interpro_accession: the Interpro accession ID of the protein domain.
    • prot_dom_start: the start position of the protein domain within the protein’s sequence.
    • prot_dom_end: the end position of the protein domain within the protein’s sequence.
  • metadata: some additional, internal, informations (Genome build, Ensembl version etc).
    • name
    • value
  • virtual columns:
    • symbol: the database does not have such a database column, but it is still possible to use it in the columns parameter. This column is symlinked to the gene_name column.
    • tx_name: similar to the symbol column, this column is symlinked to the tx_id column.

The database layout: as already described above, protein related annotations (green) might not be available in each EnsDb database.

img

img

ensembldb/inst/doc/proteins.R0000644000175400017540000000755213241155730017255 0ustar00biocbuildbiocbuild## ----doeval, echo = FALSE, results = "hide"-------------------------------- ## Globally switch off execution of code chunks evalMe <- FALSE haveProt <- FALSE ## ----loadlib, message = FALSE, eval = evalMe------------------------------- # library(ensembldb) # library(EnsDb.Hsapiens.v75) # edb <- EnsDb.Hsapiens.v75 # ## Evaluate whether we have protein annotation available # hasProteinData(edb) # ## ----listCols, message = FALSE, eval = evalMe------------------------------ # listTables(edb) # ## ----haveprot, echo = FALSE, results = "hide", eval = evalMe--------------- # ## Use this to conditionally disable eval on following chunks # haveProt <- hasProteinData(edb) & evalMe # ## ----a_transcripts, eval = haveProt---------------------------------------- # ## Get also protein information for ZBTB16 transcripts # txs <- transcripts(edb, filter = GenenameFilter("ZBTB16"), # columns = c("protein_id", "uniprot_id", "tx_biotype")) # txs # ## ----a_transcripts_coding_noncoding, eval = haveProt----------------------- # ## Subset to transcripts with tx_biotype other than protein_coding. # txs[txs$tx_biotype != "protein_coding", c("uniprot_id", "tx_biotype", # "protein_id")] # ## ----a_transcripts_coding, eval = haveProt--------------------------------- # ## List the protein IDs and uniprot IDs for the coding transcripts # mcols(txs[txs$tx_biotype == "protein_coding", # c("tx_id", "protein_id", "uniprot_id")]) # ## ----a_transcripts_coding_up, eval = haveProt------------------------------ # ## List all uniprot mapping types in the database. # listUniprotMappingTypes(edb) # # ## Get all protein_coding transcripts of ZBTB16 along with their protein_id # ## and Uniprot IDs, restricting to protein_id to uniprot_id mappings based # ## on "DIRECT" mapping methods. # txs <- transcripts(edb, filter = list(GenenameFilter("ZBTB16"), # UniprotMappingTypeFilter("DIRECT")), # columns = c("protein_id", "uniprot_id", "uniprot_db")) # mcols(txs) # ## ----a_genes_protdomid_filter, eval = haveProt----------------------------- # ## Get all genes that encode a transcript encoding for a protein that contains # ## a certain protein domain. # gns <- genes(edb, filter = ProtDomIdFilter("PS50097")) # length(gns) # # sort(gns$gene_name) # ## ----a_2_annotationdbi, message = FALSE, eval = haveProt------------------- # ## Show all columns that are provided by the database # columns(edb) # # ## Show all key types/filters that are supported # keytypes(edb) # ## ----a_2_select, message = FALSE, eval = haveProt-------------------------- # select(edb, keys = "ZBTB16", keytype = "GENENAME", # columns = "UNIPROTID") # ## ----a_2_select_nmd, message = FALSE, eval = haveProt---------------------- # ## Call select, this time providing a GenenameFilter. # select(edb, keys = GenenameFilter("ZBTB16"), # columns = c("TXBIOTYPE", "UNIPROTID", "PROTEINID")) # ## ----b_proteins, message = FALSE, eval = haveProt-------------------------- # ## Get all proteins and return them as an AAStringSet # prts <- proteins(edb, filter = GenenameFilter("ZBTB16"), # return.type = "AAStringSet") # prts # ## ----b_proteins_mcols, message = FALSE, eval = haveProt-------------------- # mcols(prts) # ## ----b_proteins_prot_doms, message = FALSE, eval = haveProt---------------- # ## Get also protein domain annotations in addition to the protein annotations. # pd <- proteins(edb, filter = GenenameFilter("ZBTB16"), # columns = c("tx_id", listColumns(edb, "protein_domain")), # return.type = "AAStringSet") # pd # ## ----b_proteins_prot_doms_2, message = FALSE, eval = haveProt-------------- # ## The number of protein domains per protein: # table(names(pd)) # # ## The mcols # mcols(pd) # ensembldb/inst/doc/proteins.Rmd0000644000175400017540000002655713175714743017617 0ustar00biocbuildbiocbuild--- title: "Querying protein features" author: "Johannes Rainer" graphics: yes package: ensembldb output: BiocStyle::html_document: toc_float: true vignette: > %\VignetteIndexEntry{Querying protein features} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} %\VignetteDepends{ensembldb,EnsDb.Hsapiens.v75,BiocStyle} --- From Bioconductor release 3.5 on, `EnsDb` databases/packages created by the `ensembldb` package contain also, for transcripts with a coding regions, mappings between transcripts and proteins. Thus, in addition to the RNA/DNA-based features also the following protein related information is available: - `protein_id`: the Ensembl protein ID. This is the primary ID for the proteins defined in Ensembl and each (protein coding) Ensembl transcript has one protein ID assigned to it. - `protein_sequence`: the amino acid sequence of a protein. - `uniprot_id`: the Uniprot ID for a protein. Note that not every Ensembl `protein_id` has an Uniprot ID, and each `protein_id` might be mapped to several `uniprot_id`. Also, the same Uniprot ID might be mapped to different `protein_id`. - `uniprot_db`: the name of the Uniprot database in which the feature is annotated. Can be either *SPTREMBL* or *SWISSPROT*. - `uniprot_mapping_type`: the type of the mapping method that was used to assign the Uniprot ID to the Ensembl protein ID. - `protein_domain_id`: the ID of the protein domain according to the source/analysis in/by which is was defined. - `protein_domain_source`: the source of the protein domain information, one of *pfscan*, *scanprosite*, *superfamily*, *pfam*, *prints*, *smart*, *pirsf* or *tigrfam*. - `interpro_accession`: the Interpro accession ID of the protein domain (if available). - `prot_dom_start`: the start of the protein domain within the sequence of the protein. - `prot_dom_start`: the end position of the protein domain within the sequence of the protein. Thus, for protein coding transcripts, these annotations can be fetched from the database too, given that protein annotations are available. Note that only `EnsDb` databases created through the Ensembl Perl API contain protein annotation, while databases created using `ensDbFromAH`, `ensDbFromGff`, `ensDbFromGRanges` and `ensDbFromGtf` don't. ```{r doeval, echo = FALSE, results = "hide" } ## Globally switch off execution of code chunks evalMe <- FALSE haveProt <- FALSE ``` ```{r loadlib, message = FALSE, eval = evalMe } library(ensembldb) library(EnsDb.Hsapiens.v75) edb <- EnsDb.Hsapiens.v75 ## Evaluate whether we have protein annotation available hasProteinData(edb) ``` If protein annotation is available, the additional tables and columns are also listed by the `listTables` and `listColumns` methods. ```{r listCols, message = FALSE, eval = evalMe } listTables(edb) ``` In the following sections we show examples how to 1) fetch protein annotations as additional columns to gene/transcript annotations, 2) fetch protein annotation data and 3) map proteins to the genome. ```{r haveprot, echo = FALSE, results = "hide", eval = evalMe } ## Use this to conditionally disable eval on following chunks haveProt <- hasProteinData(edb) & evalMe ``` # Fetch protein annotation for genes and transcripts Protein annotations for (protein coding) transcripts can be retrieved by simply adding the desired annotation columns to the `columns` parameter of the e.g. `genes` or `transcripts` methods. ```{r a_transcripts, eval = haveProt } ## Get also protein information for ZBTB16 transcripts txs <- transcripts(edb, filter = GenenameFilter("ZBTB16"), columns = c("protein_id", "uniprot_id", "tx_biotype")) txs ``` The gene ZBTB16 has protein coding and non-coding transcripts, thus, we get the protein ID for the coding- and `NA` for the non-coding transcripts. Note also that we have a transcript targeted for nonsense mediated mRNA-decay with a protein ID associated with it, but no Uniprot ID. ```{r a_transcripts_coding_noncoding, eval = haveProt } ## Subset to transcripts with tx_biotype other than protein_coding. txs[txs$tx_biotype != "protein_coding", c("uniprot_id", "tx_biotype", "protein_id")] ``` While the mapping from a protein coding transcript to a Ensembl protein ID (column `protein_id`) is 1:1, the mapping between `protein_id` and `uniprot_id` can be n:m, i.e. each Ensembl protein ID can be mapped to 1 or more Uniprot IDs and each Uniprot ID can be mapped to more than one `protein_id` (and hence `tx_id`). This should be kept in mind if querying transcripts from the database fetching Uniprot related additional columns or even protein ID features, as in such cases a redundant list of transcripts is returned. ```{r a_transcripts_coding, eval = haveProt } ## List the protein IDs and uniprot IDs for the coding transcripts mcols(txs[txs$tx_biotype == "protein_coding", c("tx_id", "protein_id", "uniprot_id")]) ``` Some of the n:m mappings for Uniprot IDs can be resolved by restricting either to entries from one Uniprot database (*SPTREMBL* or *SWISSPROT*) or to mappings of a certain type of mapping method. The corresponding filters are the `UniprotDbFilter` and the `UniprotMappingTypeFilter` (using the `uniprot_db` and `uniprot_mapping_type` columns of the `uniprot` database table). In the example below we restrict the result to Uniprot IDs with the mapping type *DIRECT*. ```{r a_transcripts_coding_up, eval = haveProt } ## List all uniprot mapping types in the database. listUniprotMappingTypes(edb) ## Get all protein_coding transcripts of ZBTB16 along with their protein_id ## and Uniprot IDs, restricting to protein_id to uniprot_id mappings based ## on "DIRECT" mapping methods. txs <- transcripts(edb, filter = list(GenenameFilter("ZBTB16"), UniprotMappingTypeFilter("DIRECT")), columns = c("protein_id", "uniprot_id", "uniprot_db")) mcols(txs) ``` For this example the use of the `UniprotMappingTypeFilter` resolved the multiple mapping of Uniprot IDs to Ensembl protein IDs, but the Uniprot ID *Q05516* is still assigned to the two Ensembl protein IDs *ENSP00000338157* and *ENSP00000376721*. All protein annotations can also be added as *metadata columns* to the results of the `genes`, `exons`, `exonsBy`, `transcriptsBy`, `cdsBy`, `fiveUTRsByTranscript` and `threeUTRsByTranscript` methods by specifying the desired column names with the `columns` parameter. For non coding transcripts `NA` will be reported in the protein annotation columns. In addition to retrieve protein annotations from the database, we can also use protein data to filter the results. In the example below we fetch for example all genes from the database that have a certain protein domain in the protein encoded by any of its transcripts. ```{r a_genes_protdomid_filter, eval = haveProt } ## Get all genes that encode a transcript encoding for a protein that contains ## a certain protein domain. gns <- genes(edb, filter = ProtDomIdFilter("PS50097")) length(gns) sort(gns$gene_name) ``` So, in total we got 152 genes with that protein domain. In addition to the `ProtDomIdFilter`, also the `ProteinidFilter` and the `UniprotidFilter` can be used to query the database for entries matching conditions on their protein ID or Uniprot ID. # Use methods from the `AnnotationDbi` package to query protein annotation The `select`, `keys` and `mapIds` methods from the `AnnotationDbi` package can also be used to query `EnsDb` objects for protein annotations. Supported columns and key types are returned by the `columns` and `keytypes` methods. ```{r a_2_annotationdbi, message = FALSE, eval = haveProt } ## Show all columns that are provided by the database columns(edb) ## Show all key types/filters that are supported keytypes(edb) ``` Below we fetch all Uniprot IDs annotated to the gene *ZBTB16*. ```{r a_2_select, message = FALSE, eval = haveProt } select(edb, keys = "ZBTB16", keytype = "GENENAME", columns = "UNIPROTID") ``` This returns us all Uniprot IDs of all proteins encoded by the gene's transcripts. One of the transcripts from ZBTB16, while having a CDS and being annotated to a protein, does not have an Uniprot ID assigned (thus `NA` is returned by the above call). As we see below, this transcript is targeted for non sense mediated mRNA decay. ```{r a_2_select_nmd, message = FALSE, eval = haveProt } ## Call select, this time providing a GenenameFilter. select(edb, keys = GenenameFilter("ZBTB16"), columns = c("TXBIOTYPE", "UNIPROTID", "PROTEINID")) ``` Note also that we passed this time a `GenenameFilter` with the `keys` parameter. # Retrieve proteins from the database Proteins can be fetched using the dedicated `proteins` method that returns, unlike DNA/RNA-based methods like `genes` or `transcripts`, not a `GRanges` object by default, but a `DataFrame` object. Alternatively, results can be returned as a `data.frame` or as an `AAStringSet` object from the `Biobase` package. Note that this might change in future releases if a more appropriate object to represent protein annotations becomes available. In the code chunk below we fetch all protein annotations for the gene *ZBTB16*. ```{r b_proteins, message = FALSE, eval = haveProt } ## Get all proteins and return them as an AAStringSet prts <- proteins(edb, filter = GenenameFilter("ZBTB16"), return.type = "AAStringSet") prts ``` Besides the amino acid sequence, the `prts` contains also additional annotations that can be accessed with the `mcols` method (metadata columns). All additional columns provided with the parameter `columns` are also added to the `mcols` `DataFrame`. ```{r b_proteins_mcols, message = FALSE, eval = haveProt } mcols(prts) ``` Note that the `proteins` method will retrieve only gene/transcript annotations of transcripts encoding a protein. Thus annotations for the non-coding transcripts of the gene *ZBTB16*, that were returned by calls to `genes` or `transcripts` in the previous section are not fetched. Querying in addition Uniprot identifiers or protein domain data will result at present in a redundant list of proteins as shown in the code block below. ```{r b_proteins_prot_doms, message = FALSE, eval = haveProt } ## Get also protein domain annotations in addition to the protein annotations. pd <- proteins(edb, filter = GenenameFilter("ZBTB16"), columns = c("tx_id", listColumns(edb, "protein_domain")), return.type = "AAStringSet") pd ``` The result contains one row/element for each protein domain in each of the proteins. The number of protein domains per protein and the `mcols` are shown below. ```{r b_proteins_prot_doms_2, message = FALSE, eval = haveProt } ## The number of protein domains per protein: table(names(pd)) ## The mcols mcols(pd) ``` As we can see each protein can have several protein domains with the start and end coordinates within the amino acid sequence being reported in columns `prot_dom_start` and `prot_dom_end`. Also, not all Ensembl protein IDs, like `protein_id` *ENSP00000445047* are mapped to an Uniprot ID or have protein domains. # Map peptide features within proteins to the genome Functionality to map peptide features (i.e. ranges within the amino acid sequence of the protein) to genomic coordinates are provided by the `Pbase` Bioconductor package. These rely in part on the protein annotations provided by `EnsDb` databases. See the corresponding vignette *Pbase-with-ensembldb* in that package. ensembldb/inst/doc/proteins.html0000644000175400017540000327602613241155731020030 0ustar00biocbuildbiocbuild Querying protein features

From Bioconductor release 3.5 on, EnsDb databases/packages created by the ensembldb package contain also, for transcripts with a coding regions, mappings between transcripts and proteins. Thus, in addition to the RNA/DNA-based features also the following protein related information is available:

  • protein_id: the Ensembl protein ID. This is the primary ID for the proteins defined in Ensembl and each (protein coding) Ensembl transcript has one protein ID assigned to it.
  • protein_sequence: the amino acid sequence of a protein.
  • uniprot_id: the Uniprot ID for a protein. Note that not every Ensembl protein_id has an Uniprot ID, and each protein_id might be mapped to several uniprot_id. Also, the same Uniprot ID might be mapped to different protein_id.
  • uniprot_db: the name of the Uniprot database in which the feature is annotated. Can be either SPTREMBL or SWISSPROT.
  • uniprot_mapping_type: the type of the mapping method that was used to assign the Uniprot ID to the Ensembl protein ID.
  • protein_domain_id: the ID of the protein domain according to the source/analysis in/by which is was defined.
  • protein_domain_source: the source of the protein domain information, one of pfscan, scanprosite, superfamily, pfam, prints, smart, pirsf or tigrfam.
  • interpro_accession: the Interpro accession ID of the protein domain (if available).
  • prot_dom_start: the start of the protein domain within the sequence of the protein.
  • prot_dom_start: the end position of the protein domain within the sequence of the protein.

Thus, for protein coding transcripts, these annotations can be fetched from the database too, given that protein annotations are available. Note that only EnsDb databases created through the Ensembl Perl API contain protein annotation, while databases created using ensDbFromAH, ensDbFromGff, ensDbFromGRanges and ensDbFromGtf don’t.

library(ensembldb)
library(EnsDb.Hsapiens.v75)
edb <- EnsDb.Hsapiens.v75
## Evaluate whether we have protein annotation available
hasProteinData(edb)

If protein annotation is available, the additional tables and columns are also listed by the listTables and listColumns methods.

listTables(edb)

In the following sections we show examples how to 1) fetch protein annotations as additional columns to gene/transcript annotations, 2) fetch protein annotation data and 3) map proteins to the genome.

1 Fetch protein annotation for genes and transcripts

Protein annotations for (protein coding) transcripts can be retrieved by simply adding the desired annotation columns to the columns parameter of the e.g. genes or transcripts methods.

## Get also protein information for ZBTB16 transcripts
txs <- transcripts(edb, filter = GenenameFilter("ZBTB16"),
                   columns = c("protein_id", "uniprot_id", "tx_biotype"))
txs

The gene ZBTB16 has protein coding and non-coding transcripts, thus, we get the protein ID for the coding- and NA for the non-coding transcripts. Note also that we have a transcript targeted for nonsense mediated mRNA-decay with a protein ID associated with it, but no Uniprot ID.

## Subset to transcripts with tx_biotype other than protein_coding.
txs[txs$tx_biotype != "protein_coding", c("uniprot_id", "tx_biotype",
                                          "protein_id")]

While the mapping from a protein coding transcript to a Ensembl protein ID (column protein_id) is 1:1, the mapping between protein_id and uniprot_id can be n:m, i.e. each Ensembl protein ID can be mapped to 1 or more Uniprot IDs and each Uniprot ID can be mapped to more than one protein_id (and hence tx_id). This should be kept in mind if querying transcripts from the database fetching Uniprot related additional columns or even protein ID features, as in such cases a redundant list of transcripts is returned.

## List the protein IDs and uniprot IDs for the coding transcripts
mcols(txs[txs$tx_biotype == "protein_coding",
          c("tx_id", "protein_id", "uniprot_id")])

Some of the n:m mappings for Uniprot IDs can be resolved by restricting either to entries from one Uniprot database (SPTREMBL or SWISSPROT) or to mappings of a certain type of mapping method. The corresponding filters are the UniprotDbFilter and the UniprotMappingTypeFilter (using the uniprot_db and uniprot_mapping_type columns of the uniprot database table). In the example below we restrict the result to Uniprot IDs with the mapping type DIRECT.

## List all uniprot mapping types in the database.
listUniprotMappingTypes(edb)

## Get all protein_coding transcripts of ZBTB16 along with their protein_id
## and Uniprot IDs, restricting to protein_id to uniprot_id mappings based
## on "DIRECT" mapping methods.
txs <- transcripts(edb, filter = list(GenenameFilter("ZBTB16"),
                      UniprotMappingTypeFilter("DIRECT")),
                   columns = c("protein_id", "uniprot_id", "uniprot_db"))
mcols(txs)

For this example the use of the UniprotMappingTypeFilter resolved the multiple mapping of Uniprot IDs to Ensembl protein IDs, but the Uniprot ID Q05516 is still assigned to the two Ensembl protein IDs ENSP00000338157 and ENSP00000376721.

All protein annotations can also be added as metadata columns to the results of the genes, exons, exonsBy, transcriptsBy, cdsBy, fiveUTRsByTranscript and threeUTRsByTranscript methods by specifying the desired column names with the columns parameter. For non coding transcripts NA will be reported in the protein annotation columns.

In addition to retrieve protein annotations from the database, we can also use protein data to filter the results. In the example below we fetch for example all genes from the database that have a certain protein domain in the protein encoded by any of its transcripts.

## Get all genes that encode a transcript encoding for a protein that contains
## a certain protein domain.
gns <- genes(edb, filter = ProtDomIdFilter("PS50097"))
length(gns)

sort(gns$gene_name)

So, in total we got 152 genes with that protein domain. In addition to the ProtDomIdFilter, also the ProteinidFilter and the UniprotidFilter can be used to query the database for entries matching conditions on their protein ID or Uniprot ID.

2 Use methods from the AnnotationDbi package to query protein annotation

The select, keys and mapIds methods from the AnnotationDbi package can also be used to query EnsDb objects for protein annotations. Supported columns and key types are returned by the columns and keytypes methods.

## Show all columns that are provided by the database
columns(edb)

## Show all key types/filters that are supported
keytypes(edb)

Below we fetch all Uniprot IDs annotated to the gene ZBTB16.

select(edb, keys = "ZBTB16", keytype = "GENENAME",
       columns = "UNIPROTID")

This returns us all Uniprot IDs of all proteins encoded by the gene’s transcripts. One of the transcripts from ZBTB16, while having a CDS and being annotated to a protein, does not have an Uniprot ID assigned (thus NA is returned by the above call). As we see below, this transcript is targeted for non sense mediated mRNA decay.

## Call select, this time providing a GenenameFilter.
select(edb, keys = GenenameFilter("ZBTB16"),
       columns = c("TXBIOTYPE", "UNIPROTID", "PROTEINID"))

Note also that we passed this time a GenenameFilter with the keys parameter.

3 Retrieve proteins from the database

Proteins can be fetched using the dedicated proteins method that returns, unlike DNA/RNA-based methods like genes or transcripts, not a GRanges object by default, but a DataFrame object. Alternatively, results can be returned as a data.frame or as an AAStringSet object from the Biobase package. Note that this might change in future releases if a more appropriate object to represent protein annotations becomes available.

In the code chunk below we fetch all protein annotations for the gene ZBTB16.

## Get all proteins and return them as an AAStringSet
prts <- proteins(edb, filter = GenenameFilter("ZBTB16"),
                 return.type = "AAStringSet")
prts

Besides the amino acid sequence, the prts contains also additional annotations that can be accessed with the mcols method (metadata columns). All additional columns provided with the parameter columns are also added to the mcols DataFrame.

mcols(prts)

Note that the proteins method will retrieve only gene/transcript annotations of transcripts encoding a protein. Thus annotations for the non-coding transcripts of the gene ZBTB16, that were returned by calls to genes or transcripts in the previous section are not fetched.

Querying in addition Uniprot identifiers or protein domain data will result at present in a redundant list of proteins as shown in the code block below.

## Get also protein domain annotations in addition to the protein annotations.
pd <- proteins(edb, filter = GenenameFilter("ZBTB16"),
               columns = c("tx_id", listColumns(edb, "protein_domain")),
               return.type = "AAStringSet")
pd

The result contains one row/element for each protein domain in each of the proteins. The number of protein domains per protein and the mcols are shown below.

## The number of protein domains per protein:
table(names(pd))

## The mcols
mcols(pd)

As we can see each protein can have several protein domains with the start and end coordinates within the amino acid sequence being reported in columns prot_dom_start and prot_dom_end. Also, not all Ensembl protein IDs, like protein_id ENSP00000445047 are mapped to an Uniprot ID or have protein domains.

4 Map peptide features within proteins to the genome

Functionality to map peptide features (i.e. ranges within the amino acid sequence of the protein) to genomic coordinates are provided by the Pbase Bioconductor package. These rely in part on the protein annotations provided by EnsDb databases. See the corresponding vignette Pbase-with-ensembldb in that package.

ensembldb/inst/extended_tests/0000755000175400017540000000000013175714743017546 5ustar00biocbuildbiocbuildensembldb/inst/extended_tests/extended_tests.R0000644000175400017540000010304413175714743022715 0ustar00biocbuildbiocbuild## This script comprises extended tests. ##***************************************************************** ## Gviz stuff notrun_test_genetrack_df <- function(){ do.plot <- FALSE if(do.plot){ ##library(Gviz) options(ucscChromosomeNames=FALSE) data(geneModels) geneModels$chromosome <- 7 chr <- 7 start <- min(geneModels$start) end <- max(geneModels$end) myGeneModels <- getGeneRegionTrackForGviz(edb, chromosome=chr, start=start, end=end) ## chromosome has to be the same.... gtrack <- GenomeAxisTrack() gvizTrack <- GeneRegionTrack(geneModels, name="Gviz") ensdbTrack <- GeneRegionTrack(myGeneModels, name="ensdb") plotTracks(list(gtrack, gvizTrack, ensdbTrack)) plotTracks(list(gtrack, gvizTrack, ensdbTrack), from=26700000, to=26780000) ## Looks very nice... } ## Put the stuff below into the vignette: ## Next we get all lincRNAs on chromosome Y Lncs <- getGeneRegionTrackForGviz(edb, filter=list(SeqNameFilter("Y"), GeneBiotypeFilter("lincRNA"))) Prots <- getGeneRegionTrackForGviz(edb, filter=list(SeqNameFilter("Y"), GeneBiotypeFilter("protein_coding"))) if(do.plot){ plotTracks(list(gtrack, GeneRegionTrack(Lncs, name="lincRNAs"), GeneRegionTrack(Prots, name="proteins"))) plotTracks(list(gtrack, GeneRegionTrack(Lncs, name="lincRNAs"), GeneRegionTrack(Prots, name="proteins")), from=5000000, to=7000000, transcriptAnnotation="symbol") } ## is that the same than: TestL <- getGeneRegionTrackForGviz(edb, filter=list(GeneBiotypeFilter("lincRNA")), chromosome="Y", start=5000000, end=7000000) TestP <- getGeneRegionTrackForGviz(edb, filter=list(GeneBiotypeFilter("protein_coding")), chromosome="Y", start=5000000, end=7000000) if(do.plot){ plotTracks(list(gtrack, GeneRegionTrack(Lncs, name="lincRNAs"), GeneRegionTrack(Prots, name="proteins"), GeneRegionTrack(TestL, name="compareL"), GeneRegionTrack(TestP, name="compareP")), from=5000000, to=7000000, transcriptAnnotation="symbol") } expect_true(all(TestL$exon %in% Lncs$exon)) expect_true(all(TestP$exon %in% Prots$exon)) ## Crazy amazing stuff ## system.time( ## All <- getGeneRegionTrackForGviz(edb) ## ) } notrun_test_getSeqlengthsFromMysqlFolder <- function() { ## Test this for some more seqlengths. library(EnsDb.Rnorvegicus.v79) db <- EnsDb.Rnorvegicus.v79 seq_info <- seqinfo(db) seq_lengths <- ensembldb:::.getSeqlengthsFromMysqlFolder( organism = "Rattus norvegicus", ensembl = 79, seqnames = seqlevels(seq_info)) sl <- seqlengths(seq_info) sl_2 <- seq_lengths$length names(sl_2) <- rownames(seq_lengths) checkEquals(sl, sl_2) ## Mus musculus } notrun_test_ensDbFromGtf_Gff_AH <- function() { gtf <- paste0("/Users/jo/Projects/EnsDbs/80/caenorhabditis_elegans/", "Caenorhabditis_elegans.WBcel235.80.gtf.gz") outf <- tempfile() db <- ensDbFromGtf(gtf = gtf, outfile = outf) ## use Gff gff <- paste0("/Users/jo/Projects/EnsDbs/84/canis_familiaris/gff3/", "Canis_familiaris.CanFam3.1.84.gff3.gz") outf <- tempfile() db <- ensDbFromGff(gff, outfile = outf) ## Checking one from ensemblgenomes: gtf <- paste0("/Users/jo/Projects/EnsDbs/ensemblgenomes/30/", "solanum_lycopersicum/", "Solanum_lycopersicum.GCA_000188115.2.30.chr.gtf.gz" ) outf <- tempfile() db <- ensDbFromGtf(gtf = gtf, outfile = outf) gtf <- paste0("/Users/jo/Projects/EnsDbs/ensemblgenomes/30/", "solanum_lycopersicum/", "Solanum_lycopersicum.GCA_000188115.2.30.gtf.gz" ) outf <- tempfile() db <- ensDbFromGtf(gtf = gtf, outfile = outf) ## AH library(AnnotationHub) ah <- AnnotationHub() query(ah, c("release-83", "gtf")) ah_1 <- ah["AH50418"] db <- ensDbFromAH(ah_1, outfile = outf) ah_2 <- ah["AH50352"] db <- ensDbFromAH(ah_2, outfile = outf) } notrun_test_builds <- function(){ input <- "/Users/jo/Projects/EnsDbs/83/Homo_sapiens.GRCh38.83.gtf.gz" fromGtf <- ensDbFromGtf(input, outfile=tempfile()) ## provide wrong ensembl version fromGtf <- ensDbFromGtf(input, outfile=tempfile(), version="75") ## provide wrong genome version fromGtf <- ensDbFromGtf(input, outfile=tempfile(), genomeVersion="75") EnsDb(fromGtf) ## provide wrong organism fromGtf <- ensDbFromGtf(input, outfile=tempfile(), organism="blalba") EnsDb(fromGtf) ## GFF input <- "/Users/jo/Projects/EnsDbs/83/Homo_sapiens.GRCh38.83.chr.gff3.gz" fromGff <- ensDbFromGff(input, outfile=tempfile()) EnsDb(fromGff) fromGff <- ensDbFromGff(input, outfile=tempfile(), version="75") EnsDb(fromGff) fromGff <- ensDbFromGff(input, outfile=tempfile(), genomeVersion="bla") EnsDb(fromGff) fromGff <- ensDbFromGff(input, outfile=tempfile(), organism="blabla") EnsDb(fromGff) ## AH library(AnnotationHub) ah <- AnnotationHub() fromAh <- ensDbFromAH(ah["AH47963"], outfile=tempfile()) EnsDb(fromAH) fromAh <- ensDbFromAH(ah["AH47963"], outfile=tempfile(), version="75") EnsDb(fromAH) fromAh <- ensDbFromAH(ah["AH47963"], outfile=tempfile(), genomeVersion="bla") EnsDb(fromAH) fromAh <- ensDbFromAH(ah["AH47963"], outfile=tempfile(), organism="blabla") EnsDb(fromAH) } notrun_test_ensdbFromGFF <- function(){ library(ensembldb) ##library(rtracklayer) ## VERSION 83 gtf <- "/Users/jo/Projects/EnsDbs/83/Homo_sapiens.GRCh38.83.gtf.gz" fromGtf <- ensDbFromGtf(gtf, outfile=tempfile()) egtf <- EnsDb(fromGtf) gff <- "/Users/jo/Projects/EnsDbs/83/Homo_sapiens.GRCh38.83.gff3.gz" fromGff <- ensDbFromGff(gff, outfile=tempfile()) egff <- EnsDb(fromGff) ## Compare EnsDbs ensembldb:::compareEnsDbs(egtf, egff) ## OK, only Entrezgene ID "problems" ## Compare with the one built with the Perl API library(EnsDb.Hsapiens.v83) db <- EnsDb.Hsapiens.v83 ensembldb:::compareEnsDbs(egtf, edb) ensembldb:::compareEnsDbs(egff, edb) ## OK, I get different genes... genes1 <- genes(egtf) genes2 <- genes(edb) only2 <- genes2[!(genes2$gene_id %in% genes1$gene_id)] ## That below was before the fix to include feature type start_codon and stop_codon ## to the CDS type. ## Identify which are the different transcripts: txGtf <- transcripts(egtf) txGff <- transcripts(egff) commonIds <- intersect(names(txGtf), names(txGff)) haveCds <- commonIds[!is.na(txGtf[commonIds]$tx_cds_seq_start) & !is.na(txGff[commonIds]$tx_cds_seq_start)] diffs <- haveCds[txGtf[haveCds]$tx_cds_seq_start != txGff[haveCds]$tx_cds_seq_start] head(diffs) ## What could be reasons? ## 1) alternative CDS? ## Checking the GTF: ## tx ENST00000623834: start_codon: 195409 195411. ## first CDS: 195259 195411. ## last CDS: 185220 185350. ## stop_codon: 185217 185219. ## So, why the heck is the stop codon OUTSIDE the CDS??? ## library(rtracklayer) ## theGtf <- import(gtf, format="gtf") ## ## Apparently, the GTF contains the additional elements start_codon/stop_codon. ## theGff <- import(gff, format="gff3") ## transcripts(egtf, filter=TxIdFilter(diffs[1])) ## transcripts(egff, filter=TxIdFilter(diffs[1])) ## VERSION 81 ## Try to get the same via AnnotationHub gff <- "/Users/jo/Projects/EnsDbs/81/homo_sapiens/Homo_sapiens.GRCh38.81.gff3.gz" fromGff <- ensDbFromGff(gff, outfile=tempfile()) egff <- EnsDb(fromGff) gtf <- "/Users/jo/Projects/EnsDbs/81/homo_sapiens/Homo_sapiens.GRCh38.81.gtf.gz" fromGtf <- ensDbFromGtf(gtf, outfile=tempfile()) egtf <- EnsDb(fromGtf) ## Compare those two: ensembldb:::compareEnsDbs(egff, egtf) ## Why are there some differences in the transcripts??? trans1 <- transcripts(egff) trans2 <- transcripts(egtf) onlyInGtf <- trans2[!(trans2$tx_id %in% trans1$tx_id)] ##gtfGRanges <- ah["AH47963"] library(AnnotationHub) ah <- AnnotationHub() fromAh <- ensDbFromAH(ah["AH47963"], outfile=tempfile()) ## That's human... eah <- EnsDb(fromAh) ## Compare it to gtf: ensembldb:::compareEnsDbs(eah, egtf) ## OK. Same cds starts and cds ends. ## Compare it to gff: ensembldb:::compareEnsDbs(eah, egff) ## hm. ## Compare to EnsDb library(EnsDb.Hsapiens.v81) edb <- EnsDb.Hsapiens.v81 ensembldb:::compareEnsDbs(edb, egtf) ## Problem with CDS ensembldb:::compareEnsDbs(edb, egff) ## That's fine. ## Summary: ## GTF and AH are the same. ## GFF and Perl API are the same. ## OLD STUFF BELOW. ##fromAh <- EnsDbFromAH(ah["AH47963"], outfile=tempfile(), organism="Homo sapiens", version=81) ## Try with a fancy species: gff <- "/Users/jo/Projects/EnsDbs/83/gadus_morhua/Gadus_morhua.gadMor1.83.gff3.gz" fromGtf <- ensDbFromGff(gff, outfile=tempfile()) gff <- "/Users/jo/Projects/EnsDbs/83/rattus_norvegicus/Rattus_norvegicus.Rnor_6.0.83.gff3.gz" fromGff <- ensDbFromGff(gff, outfile=tempfile()) ## That works. ## Try with a file from AnnotationHub: Gorilla gorilla. library(AnnotationHub) ah <- AnnotationHub() ah <- ah["AH47962"] res <- ensDbFromAH(ah, outfile=tempfile()) edb <- EnsDb(res) genes(edb) ## ensRel <- query(ah, c("GTF", "ensembl")) ## gtf <- "/Users/jo/Projects/EnsDbs/83/Homo_sapiens.GRCh38.83.gtf.gz" ## ## GTF ## dir.create("/tmp/fromGtf") ## fromGtf <- ensDbFromGtf(gtf, path="/tmp/fromGtf", verbose=TRUE) ## ## GFF ## dir.create("/tmp/fromGff") ## fromGff <- ensembldb:::ensDbFromGff(gff, path="/tmp/fromGff", verbose=TRUE) ## ## ZBTB16: ## ## exon: ENSE00003606532 is 3rd exon of tx: ENST00000335953 ## ## exon: ENSE00003606532 is 3rd exon of tx: ENST00000392996 ## ## the Ensembl GFF has 2 entries for this exon. } ############################################################ ## Can not perform these tests right away, as they require a ## working MySQL connection. library(EnsDb.Hsapiens.v75) edb <- EnsDb.Hsapiens.v75 dontrun_test_useMySQL <- function() { edb_mysql <- useMySQL(edb, user = "anonuser", host = "localhost", pass = "") } dontrun_test_connect_EnsDb <- function() { library(RMySQL) con <- dbConnect(MySQL(), user = "anonuser", host = "localhost", pass = "") ensembldb:::listEnsDbs(dbcon = con) ## just with user. ensembldb:::listEnsDbs(user = "anonuser", host = "localhost", pass = "", port = 3306) ## Connecting directly to a EnsDb MySQL database. con <- dbConnect(MySQL(), user = "anonuser", host = "localhost", pass = "", dbname = "ensdb_hsapiens_v75") edb_mysql <- EnsDb(con) } notrun_compareEnsDbs <- function() { res <- ensembldb:::compareEnsDbs(edb, edb) } ############################################################ ## Massive test validating the cds: ## compare the length of the CDS with the length of the encoded protein. ## Get the CDS sequence, translate that and compare to protein sequence. notrun_massive_cds_test <- function() { ## Get all CDS: tx_cds <- cdsBy(edb, by = "tx", filter = SeqNameFilter(c(1:22, "X", "Y"))) prots <- proteins(edb, filter = TxIdFilter(names(tx_cds)), return.type = "AAStringSet") checkTrue(all(names(tx_cds) %in% mcols(prots)$tx_id)) tx_cds <- tx_cds[mcols(prots)$tx_id] ## Check that the length of the protein sequence is length of CDS/3 diff_width <- sum(width(tx_cds)) != width(prots) * 3 ## Why??? I've got some many differences here??? sum(diff_width) ## Check some of them manually in Ensembl ## 1st: - strand. tx_1 <- tx_cds[diff_width][1] ## Protein: 245aa prots[diff_width][1] ## OK. ## Tx 2206bp: exns <- exonsBy(edb, filter = TxIdFilter(names(tx_1))) sum(width(exns)) ## OK. ## Now to the CDS: cds_ex1 <- "ATGGCGTCCCCGTCTCGGAGACTGCAGACTAAACCAGTCATTACTTGTTTCAAGAGCGTTCTGCTAATCTACACTTTTATTTTCTGG" cds_ex2 <- "ATCACTGGCGTTATCCTTCTTGCAGTTGGCATTTGGGGCAAGGTGAGCCTGGAGAATTACTTTTCTCTTTTAAATGAGAAGGCCACCAATGTCCCCTTCGTGCTCATTGCTACTGGTACCGTCATTATTCTTTTGGGCACCTTTGGTTGTTTTGCTACCTGCCGAGCTTCTGCATGGATGCTAAAACTG" cds_ex3 <- "TATGCAATGTTTCTGACTCTCGTTTTTTTGGTCGAACTGGTCGCTGCCATCGTAGGATTTGTTTTCAGACATGAG" cds_ex4 <- "ATTAAGAACAGCTTTAAGAATAATTATGAGAAGGCTTTGAAGCAGTATAACTCTACAGGAGATTATAGAAGCCATGCAGTAGACAAGATCCAAAATACG" cds_ex5 <- "TTGCATTGTTGTGGTGTCACCGATTATAGAGATTGGACAGATACTAATTATTACTCAGAAAAAGGATTTCCTAAGAGTTGCTGTAAACTTGAAGATTGTACTCCACAGAGAGATGCAGACAAAGTAAACAATGAA" cds_ex6 <- "GGTTGTTTTATAAAGGTGATGACCATTATAGAGTCAGAAATGGGAGTCGTTGCAGGAATTTCCTTTGGAGTTGCTTGCTTCCAA" cds_ex7 <- "CTGATTGGAATCTTTCTCGCCTACTGCCTCTCTCGTGCCATAACAAATAACCAGTATGAGATAGTGTAA" cds_seq <- c(cds_ex1, cds_ex2, cds_ex3, cds_ex4, cds_ex5, cds_ex6, cds_ex7) nchar(cds_seq) width(tx_1) ## The length should be identical: checkEquals(sum(nchar(cds_seq)), sum(width(tx_1)), checkNames = FALSE) ## OK; so WHAT??? sum(width(tx_1)) / 3 ## So, start codon is encoded into a methionine. ## Stop codon is either a TAA, TGA or TAG. UAG can be encoded into Sec (U), UAG into Pyl (O) library(Biostrings) dna_s <- DNAString(paste0(cds_ex1, cds_ex2, cds_ex3, cds_ex4, cds_ex5, cds_ex6, cds_ex7)) translate(dna_s) ## Look at that! translate(DNAString("TAA")) ## -> translates into * translate(DNAString("TGA")) ## -> translates into * translate(DNAString("TAG")) ## -> translates into * translate(DNAString("ATG")) ## -> translates into M ## Assumption: ## If the mRNA ends with a TAA, the protein sequence will be 1aa shorter than ## length(CDS)/3. ## If the mRNA ends with a TAG, UAG the AA length is length(CDS)/3 ## Check one of the mRNA where it fits: tx_2 <- tx_cds[!diff_width][1] prots[!diff_width][1] ## AA is 137 long, ends with I. sum(width(tx_2)) / 3 ## OK ## Check Ensembl: tx_2_1 <- "ATGCTAAAACTG" tx_2_2 <- "TATGCAATGTTTCTGACTCTCGTTTTTTTGGTCGAACTGGTCGCTGCCATCGTAGGATTTGTTTTCAGACATGAG" tx_2_3 <- "ATTAAGAACAGCTTTAAGAATAATTATGAGAAGGCTTTGAAGCAGTATAACTCTACAGGAGATTATAGAAGCCATGCAGTAGACAAGATCCAAAATACG" tx_2_4 <- "TTGCATTGTTGTGGTGTCACCGATTATAGAGATTGGACAGATACTAATTATTACTCAGAAAAAGGATTTCCTAAGAGTTGCTGTAAACTTGAAGATTGTACTCCACAGAGAGATGCAGACAAAGTAAACAATGAA" tx_2_5 <- "GGTTGTTTTATAAAGGTGATGACCATTATAGAGTCAGAAATGGGAGTCGTTGCAGGAATTTCCTTTGGAGTTGCTTGCTTCCAA" tx_2_6 <- "GACATT" tx_2_cds <- paste0(tx_2_1, tx_2_2, tx_2_3, tx_2_4, tx_2_5, tx_2_6) nchar(tx_2_cds) sum(width(tx_2)) ## OK. translate(DNAString(tx_2_cds)) ## Next assumption: ## If we don't have a 3' UTR the AA sequence corresponds to length(CDS)/3 tx_cds <- cdsBy(edb, by = "tx", filter = SeqNameFilter(c(1:22, "X", "Y")), columns = c("tx_seq_start", "tx_seq_end", "tx_cds_seq_start", "tx_cds_seq_end")) prots <- proteins(edb, filter = TxIdFilter(names(tx_cds)), return.type = "AAStringSet") checkTrue(all(names(tx_cds) %in% mcols(prots)$tx_id)) tx_cds <- tx_cds[mcols(prots)$tx_id] ## Calculate the CDS width. tx_cds_width <- sum(width(tx_cds)) txs <- transcripts(edb, filter = TxIdFilter(names(tx_cds))) txs <- txs[names(tx_cds)] ## Subtract 3 from the width if we've got an 3'UTR. to_subtract <- rep(3, length(tx_cds_width)) to_subtract[((end(txs) == txs$tx_cds_seq_end) & as.logical(strand(txs) == "+")) | ((start(txs) == txs$tx_cds_seq_start) & as.logical(strand(txs) == "-"))] <- 0 tx_cds_width <- tx_cds_width - to_subtract ## Check that the length of the protein sequence is length of CDS/3 diff_width <- tx_cds_width != width(prots) * 3 ## Why??? I've got some many differences here??? sum(diff_width) length(diff_width) ## AAAA, still have some that don't fit!!! tx_3 <- tx_cds[diff_width][1] prots[diff_width][1] ## AA is 259aa long, ends with T., TX is: ENST00000371584 ## WTF, we've got no START CODON!!! sum(width(tx_3)) / 3 ## OMG!!! ## Now, exclude those without a 5' UTR: no_five <- ((start(txs) == txs$tx_cds_seq_start) & as.logical(strand(txs) == "+")) | ((end(txs) == txs$tx_cds_seq_end) & as.logical(strand(txs) == "-")) still_prot <- (diff_width & !no_five) } notrun_test_getGenomeFaFile <- function(){ library(EnsDb.Hsapiens.v82) edb <- EnsDb.Hsapiens.v82 ## We know that there is no Fasta file for that Ensembl release available. Fa <- getGenomeFaFile(edb) ## Got the one from Ensembl 81. genes <- genes(edb, filter=SeqNameFilter("Y")) geneSeqsFa <- getSeq(Fa, genes) ## Get the transcript sequences... txSeqsFa <- extractTranscriptSeqs(Fa, edb, filter=SeqNameFilter("Y")) ## Get the TwoBitFile. twob <- ensembldb:::getGenomeTwoBitFile(edb) ## Get thegene sequences. ## ERROR FIX BELOW WITH UPDATED VERSIONS!!! geneSeqs2b <- getSeq(twob, genes) ## Have to fix the seqnames. si <- seqinfo(twob) sn <- unlist(lapply(strsplit(seqnames(si), split=" ", fixed=TRUE), function(z){ return(z[1]) })) seqnames(si) <- sn seqinfo(twob) <- si ## Do the same with the TwoBitFile geneSeqsTB <- getSeq(twob, genes) ## Subset to all genes that are encoded on chromosomes for which ## we do have DNA sequence available. genes <- genes[seqnames(genes) %in% seqnames(seqinfo(Dna))] ## Get the gene sequences, i.e. the sequence including the sequence of ## all of the gene's exons and introns. geneSeqs <- getSeq(Dna, genes) library(AnnotationHub) ah <- AnnotationHub() quer <- query(ah, c("release-", "Homo sapiens")) ## So, I get 2bit files and toplevel stuff. Test <- ah[["AH50068"]] } notrun_test_extractTranscriptSeqs <- function(){ ## Note: we can't run that by default as we can not assume everybody has ## AnnotationHub and the required ressource installed. ## That's how we want to test the transcript seqs. genome <- getGenomeFaFile(edb) ZBTB <- extractTranscriptSeqs(genome, edb, filter=GenenameFilter("ZBTB16")) ## Load the sequences for one ZBTB16 transcript from FA. faf <- system.file("txt/ENST00000335953.fa.gz", package="ensembldb") Seqs <- readDNAStringSet(faf) tx <- "ENST00000335953" ## cDNA checkEquals(unname(as.character(ZBTB[tx])), unname(as.character(Seqs[grep(names(Seqs), pattern="cdna")]))) ## CDS cBy <- cdsBy(edb, "tx", filter=TxIdFilter(tx)) CDS <- extractTranscriptSeqs(genome, cBy) checkEquals(unname(as.character(CDS)), unname(as.character(Seqs[grep(names(Seqs), pattern="cds")]))) ## 5' UTR fBy <- fiveUTRsByTranscript(edb, filter=TxIdFilter(tx)) UTR <- extractTranscriptSeqs(genome, fBy) checkEquals(unname(as.character(UTR)), unname(as.character(Seqs[grep(names(Seqs), pattern="utr5")]))) ## 3' UTR tBy <- threeUTRsByTranscript(edb, filter=TxIdFilter(tx)) UTR <- extractTranscriptSeqs(genome, tBy) checkEquals(unname(as.character(UTR)), unname(as.character(Seqs[grep(names(Seqs), pattern="utr3")]))) ## Another gene on the reverse strand: faf <- system.file("txt/ENST00000200135.fa.gz", package="ensembldb") Seqs <- readDNAStringSet(faf) tx <- "ENST00000200135" ## cDNA cDNA <- extractTranscriptSeqs(genome, edb, filter=TxIdFilter(tx)) checkEquals(unname(as.character(cDNA)), unname(as.character(Seqs[grep(names(Seqs), pattern="cdna")]))) ## do the same, but from other strand exns <- exonsBy(edb, "tx", filter=TxIdFilter(tx)) cDNA <- extractTranscriptSeqs(genome, exns) checkEquals(unname(as.character(cDNA)), unname(as.character(Seqs[grep(names(Seqs), pattern="cdna")]))) strand(exns) <- "+" cDNA <- extractTranscriptSeqs(genome, exns) checkTrue(unname(as.character(cDNA)) != unname(as.character(Seqs[grep(names(Seqs), pattern="cdna")]))) ## CDS cBy <- cdsBy(edb, "tx", filter=TxIdFilter(tx)) CDS <- extractTranscriptSeqs(genome, cBy) checkEquals(unname(as.character(CDS)), unname(as.character(Seqs[grep(names(Seqs), pattern="cds")]))) ## 5' UTR fBy <- fiveUTRsByTranscript(edb, filter=TxIdFilter(tx)) UTR <- extractTranscriptSeqs(genome, fBy) checkEquals(unname(as.character(UTR)), unname(as.character(Seqs[grep(names(Seqs), pattern="utr5")]))) ## 3' UTR tBy <- threeUTRsByTranscript(edb, filter=TxIdFilter(tx)) UTR <- extractTranscriptSeqs(genome, tBy) checkEquals(unname(as.character(UTR)), unname(as.character(Seqs[grep(names(Seqs), pattern="utr3")]))) } notrun_test_getCdsSequence <- function(){ ## That's when we like to get the sequence from the coding region. genome <- getGenomeFaFile(edb) tx <- extractTranscriptSeqs(genome, edb, filter=SeqNameFilter("Y")) cdsSeq <- extractTranscriptSeqs(genome, cdsBy(edb, filter=SeqNameFilter("Y"))) ## that's basically to get the CDS sequence. ## UTR sequence: tutr <- extractTranscriptSeqs(genome, threeUTRsByTranscript(edb, filter=SeqNameFilter("Y"))) futr <- extractTranscriptSeqs(genome, fiveUTRsByTranscript(edb, filter=SeqNameFilter("Y"))) theTx <- "ENST00000602770" fullSeq <- as.character(tx[theTx]) ## build the one from 5', cds and 3' compSeq <- "" if(any(names(futr) == theTx)) compSeq <- paste0(compSeq, as.character(futr[theTx])) if(any(names(cdsSeq) == theTx)) compSeq <- paste0(compSeq, as.character(cdsSeq[theTx])) if(any(names(tutr) == theTx)) compSeq <- paste(compSeq, as.character(tutr[theTx])) checkEquals(unname(fullSeq), compSeq) } notrun_test_cds <- function(){ library(TxDb.Hsapiens.UCSC.hg19.knownGene) txdb <- TxDb.Hsapiens.UCSC.hg19.knownGene cds <- cds(txdb) cby <- cdsBy(txdb, by="tx") gr <- cby[[7]][1] seqlevels(gr) <- sub(seqlevels(gr), pattern="chr", replacement="") tx <- transcripts(edb, filter=GRangesFilter(gr, condition="overlapping")) cby[[7]] ## Note: so that fits! And we've to include the stop_codon feature for GTF import! ## Make an TxDb from GTF: gtf <- "/Users/jo/Projects/EnsDbs/75/homo_sapiens/Homo_sapiens.GRCh37.75.gtf.gz" library(GenomicFeatures) Test <- makeTxDbFromGFF(gtf, format="gtf", organism="Homo sapiens") scds <- cdsBy(Test, by="tx") gr <- scds[[7]][1] tx <- transcripts(edb, filter=GRangesFilter(gr, condition="overlapping")) scds[[7]] ## Compare: ## TxDb form GTF has: 865692 879533 ## EnsDb: 865692 879533 ## Next test: gr <- scds[[2]][1] tx <- transcripts(edb, filter=GRangesFilter(gr, condition="overlapping")) tx scds[[2]] ## start_codon: 367659 367661, stop_codon: 368595 368597 CDS: 367659 368594. ## TxDb from GTF includes the stop_codon! } dontrun_benchmark_ordering_genes <- function() { .withR <- function(x, ...) { ensembldb:::orderResultsInR(x) <- TRUE genes(x, ...) } .withSQL <- function(x, ...) { ensembldb:::orderResultsInR(x) <- FALSE genes(x, ...) } library(microbenchmark) microbenchmark(.withR(edb), .withSQL(edb), times = 10) ## same microbenchmark(.withR(edb, columns = c("gene_id", "tx_id")), .withSQL(edb, columns = c("gene_id", "tx_id")), times = 10) ## R slightly faster. microbenchmark(.withR(edb, columns = c("gene_id", "tx_id"), SeqNameFilter("Y")), .withSQL(edb, columns = c("gene_id", "tx_id"), SeqNameFilter("Y")), times = 10) ## same. } ## We aim to fix issue #11 by performing the ordering in R instead ## of SQL. Thus, we don't want to run this as a "regular" test ## case. dontrun_test_ordering_cdsBy <- function() { doBench <- FALSE if (doBench) library(microbenchmark) .withR <- function(x, ...) { ensembldb:::orderResultsInR(x) <- TRUE cdsBy(x, ...) } .withSQL <- function(x, ...) { ensembldb:::orderResultsInR(x) <- FALSE cdsBy(x, ...) } res_sql <- .withSQL(edb) res_r <- .withR(edb) checkEquals(res_sql, res_r) if (dobench) microbenchmark(.withSQL(edb), .withR(edb), times = 3) ## R slightly faster. res_sql <- .withSQL(edb, filter = SeqNameFilter("Y")) res_r <- .withR(edb, filter = SeqNameFilter("Y")) checkEquals(res_sql, res_r) if (dobench) microbenchmark(.withSQL(edb, filter = SeqNameFilter("Y")), .withR(edb, filter = SeqNameFilter("Y")), times = 10) ## R 6x faster. } dontrun_test_ordering_exonsBy <- function() { doBench <- FALSE if (doBench) library(microbenchmark) .withR <- function(x, ...) { ensembldb:::orderResultsInR(x) <- TRUE exonsBy(x, ...) } .withSQL <- function(x, ...) { ensembldb:::orderResultsInR(x) <- FALSE exonsBy(x, ...) } res_sql <- .withSQL(edb) res_r <- .withR(edb) checkEquals(res_sql, res_r) if (doBench) microbenchmark(.withSQL(edb), .withR(edb), times = 3) ## about the same; R slightly faster. ## with using a SeqNameFilter in addition. res_sql <- .withSQL(edb, filter = SeqNameFilter("Y")) res_r <- .withR(edb, filter = SeqNameFilter("Y")) ## query takes longer. checkEquals(res_sql, res_r) if (doBench) microbenchmark(.withSQL(edb, filter = SeqNameFilter("Y")), .withR(edb, filter = SeqNameFilter("Y")), times = 3) ## SQL twice as fast. ## Now getting stuff by gene res_sql <- .withSQL(edb, by = "gene") res_r <- .withR(edb, by = "gene") ## checkEquals(res_sql, res_r) ## Differences due to ties if (doBench) microbenchmark(.withSQL(edb, by = "gene"), .withR(edb, by = "gene"), times = 3) ## SQL faster; ??? ## Along with a SeqNameFilter res_sql <- .withSQL(edb, by = "gene", filter = SeqNameFilter("Y")) res_r <- .withR(edb, by = "gene", filter = SeqNameFilter("Y")) ## Why does the query take longer for R??? ## checkEquals(res_sql, res_r) ## Differences due to ties if (doBench) microbenchmark(.withSQL(edb, by = "gene", filter = SeqNameFilter("Y")), .withR(edb, by = "gene", filter = SeqNameFilter("Y")), times = 3) ## SQL faster. ## Along with a GeneBiotypeFilter if (doBench) microbenchmark(.withSQL(edb, by = "gene", filter = GeneBiotypeFilter("protein_coding")) , .withR(edb, by = "gene", filter = GeneBiotypeFilter("protein_coding")) , times = 3) } dontrun_test_ordering_transcriptsBy <- function() { .withR <- function(x, ...) { ensembldb:::orderResultsInR(x) <- TRUE transcriptsBy(x, ...) } .withSQL <- function(x, ...) { ensembldb:::orderResultsInR(x) <- FALSE transcriptsBy(x, ...) } res_sql <- .withSQL(edb) res_r <- .withR(edb) checkEquals(res_sql, res_r) microbenchmark(.withSQL(edb), .withR(edb), times = 3) ## same speed res_sql <- .withSQL(edb, filter = SeqNameFilter("Y")) res_r <- .withR(edb, filter = SeqNameFilter("Y")) checkEquals(res_sql, res_r) microbenchmark(.withSQL(edb, filter = SeqNameFilter("Y")), .withR(edb, filter = SeqNameFilter("Y")), times = 3) ## SQL slighly faster. } dontrun_query_tune <- function() { ## Query tuning: library(RSQLite) con <- dbconn(edb) Q <- "select distinct tx2exon.exon_id,exon.exon_seq_start,exon.exon_seq_end,gene.seq_name,tx2exon.tx_id,gene.seq_strand,tx2exon.exon_idx from gene join tx on (gene.gene_id=tx.gene_id) join tx2exon on (tx.tx_id=tx2exon.tx_id) join exon on (tx2exon.exon_id=exon.exon_id) where gene.seq_name = 'Y'" system.time(dbGetQuery(con, Q)) Q2 <- "select distinct tx2exon.exon_id,exon.exon_seq_start,exon.exon_seq_end,gene.seq_name,tx2exon.tx_id,gene.seq_strand,tx2exon.exon_idx from exon join tx2exon on (tx2exon.exon_id = exon.exon_id) join tx on (tx2exon.tx_id = tx.tx_id) join gene on (gene.gene_id=tx.gene_id) where gene.seq_name = 'Y'" system.time(dbGetQuery(con, Q2)) Q3 <- "select distinct tx2exon.exon_id,exon.exon_seq_start,exon.exon_seq_end,gene.seq_name,tx2exon.tx_id,gene.seq_strand,tx2exon.exon_idx from tx2exon join exon on (tx2exon.exon_id = exon.exon_id) join tx on (tx2exon.tx_id = tx.tx_id) join gene on (gene.gene_id=tx.gene_id) where gene.seq_name = 'Y'" system.time(dbGetQuery(con, Q3)) Q4 <- "select distinct tx2exon.exon_id,exon.exon_seq_start,exon.exon_seq_end,gene.seq_name,tx2exon.tx_id,gene.seq_strand,tx2exon.exon_idx from tx2exon join exon on (tx2exon.exon_id = exon.exon_id) join tx on (tx2exon.tx_id = tx.tx_id) join gene on (gene.gene_id=tx.gene_id) where gene.seq_name = 'Y' order by tx.tx_id" system.time(dbGetQuery(con, Q4)) Q5 <- "select distinct tx2exon.exon_id,exon.exon_seq_start,exon.exon_seq_end,gene.seq_name,tx2exon.tx_id,gene.seq_strand,tx2exon.exon_idx from tx2exon inner join exon on (tx2exon.exon_id = exon.exon_id) inner join tx on (tx2exon.tx_id = tx.tx_id) inner join gene on (gene.gene_id=tx.gene_id) where gene.seq_name = 'Y' order by tx.tx_id" system.time(dbGetQuery(con, Q5)) Q6 <- "select distinct tx2exon.exon_id,exon.exon_seq_start,exon.exon_seq_end,gene.seq_name,tx2exon.tx_id,gene.seq_strand,tx2exon.exon_idx from gene inner join tx on (gene.gene_id=tx.gene_id) inner join tx2exon on (tx.tx_id=tx2exon.tx_id) inner join exon on (tx2exon.exon_id=exon.exon_id) where gene.seq_name = 'Y' order by tx.tx_id asc" system.time(dbGetQuery(con, Q6)) } ## implement: ## .checkOrderBy: checks order.by argument removing columns that are ## not present in the database ## orderBy columns are added to the columns. ## .orderDataFrameBy: orders the dataframe by the specified columns. notrun_test_protein_domains <- function() { res <- ensembldb:::getWhat(edb, columns = c("protein_id", "tx_id", "gene_id", "gene_name"), filter = list(ProtDomIdFilter("PF00096"))) } notrun_compare_full <- function(){ ## That's on the full thing. ## Test if the result has the same ordering than the transcripts call. allTx <- transcripts(edb) txLen <- transcriptLengths(edb, with.cds_len=TRUE, with.utr5_len=TRUE, with.utr3_len=TRUE) checkEquals(names(allTx), rownames(txLen)) system.time( futr <- fiveUTRsByTranscript(edb) ) ## 23 secs. futrLen <- sum(width(futr)) ## do I need reduce??? checkEquals(unname(futrLen), txLen[names(futrLen), "utr5_len"]) ## 3' system.time( tutr <- threeUTRsByTranscript(edb) ) system.time( tutrLen <- sum(width(tutr)) ) checkEquals(unname(tutrLen), txLen[names(tutrLen), "utr3_len"]) } notrun_compare_to_genfeat <- function(){ library(TxDb.Hsapiens.UCSC.hg19.knownGene) txdb <- TxDb.Hsapiens.UCSC.hg19.knownGene system.time( Len <- transcriptLengths(edb) ) ## Woa, 52 sec system.time( txLen <- lengthOf(edb, "tx") ) ## Faster, 31 sec checkEquals(Len$tx_len, unname(txLen[rownames(Len)])) system.time( Len2 <- transcriptLengths(txdb) ) ## :) 2.5 sec. ## Next. system.time( Len <- transcriptLengths(edb, with.cds_len = TRUE) ) ## 56 sec system.time( Len2 <- transcriptLengths(txdb, with.cds_len=TRUE) ) ## 4 sec. ## Calling the transcriptLengths of GenomicFeatures on the EnsDb. system.time( Def <- GenomicFeatures::transcriptLengths(edb) ) ## 26.5 sec system.time( WithCds <- GenomicFeatures::transcriptLengths(edb, with.cds_len=TRUE) ) ## 55 sec system.time( WithAll <- GenomicFeatures::transcriptLengths(edb, with.cds_len=TRUE, with.utr5_len=TRUE, with.utr3_len=TRUE) ) ## 99 secs ## Get my versions... system.time( MyDef <- ensembldb:::.transcriptLengths(edb) ) ## 31 sec system.time( MyWithCds <- ensembldb:::.transcriptLengths(edb, with.cds_len=TRUE) ) ## 44 sec system.time( MyWithAll <- ensembldb:::.transcriptLengths(edb, with.cds_len=TRUE, with.utr5_len=TRUE, with.utr3_len=TRUE) ) ## 63 sec ## Should be all the same!!! rownames(MyDef) <- NULL checkEquals(Def, MyDef) ## rownames(MyWithCds) <- NULL MyWithCds[is.na(MyWithCds$cds_len), "cds_len"] <- 0 checkEquals(WithCds, MyWithCds) ## rownames(MyWithAll) <- NULL MyWithAll[is.na(MyWithAll$cds_len), "cds_len"] <- 0 MyWithAll[is.na(MyWithAll$utr3_len), "utr3_len"] <- 0 MyWithAll[is.na(MyWithAll$utr5_len), "utr5_len"] <- 0 checkEquals(WithAll, MyWithAll) } ensembldb/inst/extended_tests/performance_tests.R0000644000175400017540000001720013175714743023414 0ustar00biocbuildbiocbuild############################################################ ## Compare MySQL vs SQLite backends: ## Amazing how inefficient the MySQL backend seems to be! Most ## likely it's due to RMySQL, not MySQL. dontrun_test_MySQL_vs_SQLite <- function() { ## Compare the performance of the MySQL backend against ## the SQLite backend. edb_mysql <- useMySQL(edb, user = "anonuser", pass = "") library(microbenchmark) ## genes microbenchmark(genes(edb), genes(edb_mysql), times = 5) microbenchmark(genes(edb, filter = GeneBiotypeFilter("lincRNA")), genes(edb_mysql, filter = GeneBiotypeFilter("lincRNA")), times = 5) microbenchmark(genes(edb, filter = SeqNameFilter(20:23)), genes(edb_mysql, filter = SeqNameFilter(20:23)), times = 5) microbenchmark(genes(edb, columns = "tx_id"), genes(edb_mysql, columns = "tx_id"), times = 5) microbenchmark(genes(edb, filter = GenenameFilter("BCL2L11")), genes(edb_mysql, filter = GenenameFilter("BCL2L11")), times = 5) ## transcripts microbenchmark(transcripts(edb), transcripts(edb_mysql), times = 5) microbenchmark(transcripts(edb, filter = GenenameFilter("BCL2L11")), transcripts(edb_mysql, filter = GenenameFilter("BCL2L11")), times = 5) ## exons microbenchmark(exons(edb), exons(edb_mysql), times = 5) microbenchmark(exons(edb, filter = GenenameFilter("BCL2L11")), exons(edb_mysql, filter = GenenameFilter("BCL2L11")), times = 5) ## exonsBy microbenchmark(exonsBy(edb), exonsBy(edb_mysql), times = 5) microbenchmark(exonsBy(edb, filter = SeqNameFilter("Y")), exonsBy(edb_mysql, filter = SeqNameFilter("Y")), times = 5) ## cdsBy microbenchmark(cdsBy(edb), cdsBy(edb_mysql), times = 5) microbenchmark(cdsBy(edb, by = "gene"), cdsBy(edb_mysql, by = "gene"), times = 5) microbenchmark(cdsBy(edb, filter = SeqStrandFilter("-")), cdsBy(edb_mysql, filter = SeqStrandFilter("-")), times = 5) } ## Compare the performance of doing the sorting within R or ## directly in the SQL query. dontrun_test_ordering_performance <- function() { library(RUnit) library(RSQLite) ## gene table: order by in SQL query vs R: db_con <- dbconn(edb) .callWithOrder <- function(con, query, orderBy = "", orderSQL = TRUE) { if (all(orderBy == "")) orderBy <- NULL if (orderSQL & !is.null(orderBy)) { orderBy <- paste(orderBy, collapse = ", ") query <- paste0(query, " order by ", orderBy) } res <- dbGetQuery(con, query) if (!orderSQL & !all(is.null(orderBy))) { if (!all(orderBy %in% colnames(res))) stop("orderBy not in columns!") ## Do the ordering in R res <- res[do.call(order, c(list(method = "radix"), as.list(res[, orderBy, drop = FALSE]))), ] } rownames(res) <- NULL return(res) } ####################### ## gene table ## Simple condition the_q <- "select * from gene" system.time(res1 <- .callWithOrder(db_con, query = the_q)) system.time(res2 <- .callWithOrder(db_con, query = the_q, orderSQL = FALSE)) checkIdentical(res1, res2) ## order by gene_id orderBy <- "gene_id" system.time(res1 <- .callWithOrder(db_con, query = the_q, orderBy = orderBy)) system.time(res2 <- .callWithOrder(db_con, query = the_q, orderBy = orderBy, orderSQL = FALSE)) ## SQL: 0.16, R: 0.164. checkIdentical(res1, res2) ## order by gene_name orderBy <- "gene_name" system.time(res1 <- .callWithOrder(db_con, query = the_q, orderBy = orderBy)) system.time(res2 <- .callWithOrder(db_con, query = the_q, orderBy = orderBy, orderSQL = FALSE)) checkIdentical(res1, res2) ## SQL: 0.245, R: 0.185 ## sort by gene_name and gene_seq_start orderBy <- c("gene_name", "gene_seq_start") system.time(res1 <- .callWithOrder(db_con, query = the_q, orderBy = orderBy)) system.time(res2 <- .callWithOrder(db_con, query = the_q, orderBy = orderBy, orderSQL = FALSE)) ## SQL: 0.26, R: 0.188 checkEquals(res1, res2) ## with subsetting: the_q <- "select * from gene where seq_name in ('5', 'Y')" orderBy <- c("gene_name", "gene_seq_start") system.time(res1 <- .callWithOrder(db_con, query = the_q, orderBy = orderBy)) system.time(res2 <- .callWithOrder(db_con, query = the_q, orderBy = orderBy, orderSQL = FALSE)) ## SQL: 0.031, R: 0.024 checkEquals(res1, res2) ######################## ## joining tables. the_q <- paste0("select * from gene join tx on (gene.gene_id = tx.gene_id)", " join tx2exon on (tx.tx_id = tx2exon.tx_id)") orderBy <- c("tx_id", "exon_id") system.time(res1 <- .callWithOrder(db_con, query = the_q, orderBy = orderBy)) system.time(res2 <- .callWithOrder(db_con, query = the_q, orderBy = orderBy, orderSQL = FALSE)) ## SQL: 9.6, R: 9.032 checkEquals(res1, res2) ## subsetting. the_q <- paste0("select * from gene join tx on (gene.gene_id = tx.gene_id)", " join tx2exon on (tx.tx_id = tx2exon.tx_id) where", " seq_name = 'Y'") orderBy <- c("tx_id", "exon_id") system.time(res1 <- .callWithOrder(db_con, query = the_q, orderBy = orderBy)) system.time(res2 <- .callWithOrder(db_con, query = the_q, orderBy = orderBy, orderSQL = FALSE)) ## SQL: 0.9, R: 1.6 checkEquals(res1, res2) } ## Compare the performance of inner join with left outer join. dontrun_test_outer_join_performance <- function() { Q_1 <- ensembldb:::joinQueryOnTables2(edb, tab = c("gene", "exon")) Q_2 <- ensembldb:::joinQueryOnTables2(edb, tab = c("gene", "exon"), startWith = "exon") Q_3 <- ensembldb:::joinQueryOnTables2(edb, tab = c("gene", "exon"), startWith = "exon", join = "left outer join") library(microbenchmark) library(RSQLite) microbenchmark(dbGetQuery(dbconn(edb), paste0("select * from ", Q_1)), dbGetQuery(dbconn(edb), paste0("select * from ", Q_2)), dbGetQuery(dbconn(edb), paste0("select * from ", Q_3)), times = 10) ## Result: Q_1 is a second faster (13 instead of 14). ## Check performance joining tx and genes. Q_1 <- ensembldb:::joinQueryOnTables2(edb, tab = c("tx", "gene")) Q_2 <- ensembldb:::joinQueryOnTables2(edb, tab = c("tx", "gene"), startWith = "tx") Q_3 <- ensembldb:::joinQueryOnTables2(edb, tab = c("tx", "gene"), startWith = "tx", join = "left outer join") microbenchmark(dbGetQuery(dbconn(edb), paste0("select * from ", Q_1)), dbGetQuery(dbconn(edb), paste0("select * from ", Q_2)), dbGetQuery(dbconn(edb), paste0("select * from ", Q_3)), times = 10) ## No difference. } ensembldb/inst/gff/0000755000175400017540000000000013175714743015266 5ustar00biocbuildbiocbuildensembldb/inst/gff/Devosia_geojensis.ASM96941v1.32.gff3.gz0000644000175400017540000102460513175714743023652 0ustar00biocbuildbiocbuild]s$u-\W_8A; X: LpȚ"Y4?|Ef {ڙ% `?_p|r_?_\%rSM9O_J9nAB,+SW|b+aJ}%._񽯤+p6Tz6n-K*%|)^>.vZ:'tSyKÖ 4ii^|gf}5]cr=ۥ;|q.߫˗N_2WKS57^+ٹ;\,vW_.qS;z 57 %;ŸaƙLK ɽ2/Kk'79^$/#캘%{%Wz%͕&KTzfRB어t[:./)@N떴tsNK)tʌ;͡Ha'SƦ/שGo9&R\TQ4wJ;}S酊)ZiƓd{$.C2ݡ4x:q$e8ͽ^߉IIft+wi<+7Ӝivǚt 2!-c{F s t;eXwYDZFu iZޮn1yZ&ݱ:/<}<5/#t2puq4|7DXZ4.uѝ_{,!u_2E鲹]NYbIKLAKRcM%^vt _B:{oc{*e^%НDeld`\zIe5mw.,|m^seϲֹ^)ٛ/Kx`ŗϝ_^7tdeBizSwIN CzrZV[=NR¨PpZgMgOk9uLŷ=WS(ռr|7z-EzAӉ`.uò o,ZVT.v zpiz9p6M3uiT;7{S`^MO=kY4Y{r;-X&=\3`, {[|<>z;]ixz_}xt}ś2}vwqل>vÏ4-:?ߟuz4troA{y{?_wf7 ]g*W7/>i?3nnڙ}-Th\)O/χZ_x|t|~?j.ݯJ?~ROC@k/׷u6?~qxӧ{}9ZJ}П뿆[|Hu/-s<Ȏ:vsFI4y;rxd̨dk 5dC Blkp SpHdr8@CG]lcQŎOۛq 4YA|/b&~M&4)MLh!M\]1B EUŐVÇvu x $#tAQmr! r)9L 9b6lr89T1ĭ !Mdܐ&CBl$jhb.$*h42M"I<ɴbF{SωK3'Φ=Sޙ&L5|ޞUy7y0ϫO̝D;!y; XNo䭿 qRN&J[Lɛbtk;m4ld.O:Vۜ1Q̔B:D01%LYJȔ!ʷBU Jq|Bnup|6Mc\Ule./8u8Zez"0e9u MMP?r: Beĥ2 Sw9'QGeNQ/NYuJ:&!Qh"QQS0u|NK4[ˋ5F(xZZ PfCZ4TTZ|E;*2v}TxmqTCt !6|U␨UQEH"GJJ4TѭoﯗǙ5ڌ,W,o YV-B:d0L#Ȳr,-BBo-3,2@\rޕhًSŕy|s4YS2^Si*Pb&fM&-BJ#®14^Eo ou z|y=2r.o}dN8gR7p R&!% Hx@xIBx1X]:$& ::L7p b7& 4Ih(FJ9$jjLyW LPZûχs{ֱ~rl4#ŴYil6BMʴ6VM3r"q&n41tPtCp9e]C&S))C0Rʈ>#N'Pf>agI3" k ؐ.IqNDlzeTe.b ts3{RaN%y?6WZ*:h!K% aWũ,!)KDcgIXR˯]X<4B B5j<$M_f@hd4DN:`$(uiWYaUp|\w|kW8[Kr $"vO#J!dR#,K& K&Aw+DR$! !|X_Ct%DlFaJCR(FJYcJ@cJdr~gJHR<^F{t|y|eCAPy$+9q bO4S":%D1RȲSSd'S)y/4ql8qvX0"z pκ0Hrv8pv )`XSC p:L7;́dpVe)FJ9;Av8 a;P&% 2v wCݲ@D ! ST3d6OLmuNe9>`ʬs @7LBLF2P&Kqϻ($qMvv5bB:LWL@oĄ^c.tCtDlF]CԅR(FJY]@]Ȃ`C`:w<^jTD'ʀČ`y98q!J\)gdq!q!K5Fhgՙ</<ü[fCA yysiS"A ! Bnkj0R B Bn5FvͿ|oI=yW,hq;KQw8leM[5{95B( p/e|_NR$Zny 7Q~UeOD/-ef ɫ^ _6qC0f2^e4)g$]bsҕ ӹvm6Z٘~3AUU9 η̿ Nwk@$,1{cηv>| WmQ˳tx}8C"vi3/!i2@x/2]Z.4|"_|>Є*NM]e>d~:W}6i;`Ոh)G#RWͿ4z/2Z A&4&N]Egp6*<}_|ߙ(;`6 W =086g^^fN|FIX> ޖ]&ih)0]"3,z!e`q5Wr2-DJIX>qe/@(s2v=`WüKQo:$Lˀ `LRF.qH_3?팳¶tw g~SL?Oo+zRj@|ΏvdZEsE"@Rh Vr5$]6Ij_6%6ˉ]e/̂0Rz PG`1mHJIQX>ⴑy? hҙ0v;|^><_x) @1ǟ5.qHͨ5 I-),aK?g6 3?kK!]0$b4bf"fe! )mdEE'$['U!muˌnwUg??,|^PTnr$b4g"pIARgg4Ns3Ug]g췄 8;5@S/qr$lbΧ@yH2$sM&I7["H^wjRuqOpYsRHWgHIhifb{) m3g),0)N8`xn^Wݱ7yL@Ss:9G"9R4iAҘ#iG(W/T҉$QLt T?7wE[ܤ/o,NK1$b4舛KQ,Q~7Ei>D$^,)$8IBdHvo$i$:$ ED' N$1? ԟ%JO_?]?~:~?+3)D+kK!]0$b4 iHBpR& H9!8$%T j pKQ7 kLK!-3 ! &CCwYo|T`v Rz Ҧ\ C"ihc(iC@6ȴII :.Ϸҥ xAIsa{C"#;!Qn# )idH3aa?2 vH= f`tBIi#  FryM8y (σ;VY.E-vd ܐ2}#[ RF $6HRّ/e+2 nH f`tBI)#  F.֟)BCY?<盇o 7 ՇNe G"vI>!ѩ$呬>>I}p~ಐ :KjC :CҦ4p$b4J4@ARJJT\(VZP<1#(k ńZHmވ f`tbI"   w8Ig鏹NI~|V 9jЖ.Mq}P\8M9:BUxanv[Rxr2Cƃ^đV!zE$^d^d$>N]kӏolqoBP.`E\dEF'Q6\d\dD8cvX#!tMŁ#acU8i/lCV' k o'F_y.`WS<} bxni3DF CS(H#Y @ a}QѻI2qV^nno?<*RG/@rx-^OkH뼞Q n)*D@RZ&RD"|[/yx<>y<^|vlqxB5:KR7".YDAH$KKVu&MuOy i0mY:0$+&MT҆qGM"m |LEJ w)jù U.i$G".iVKR4ȺtIMA-'3}7U'?wohbӃy:Φg$G"AN!թ$%NZNZIpPRgӋ[lz 0taBaHĈě8$De! 0%ǛMMwd]غ,k*P`Ѧas$hvmu6Ia[a[I6Gos\δ_y:y?o T^{fwj W9/5QNͦ )d55ۊ}sqqq uv;M_Hhm;D۶:mm m+m .)F\O划G0=[LW"5A;!q.GƐ}Јvj8jj%4bcur<;1n9u"h;M_HhDP;D:EP DP+`:޲ /7_phKAPYC;@r}=#5z:JA9Yu@ubva_6εatA->jV4}͊#ۿѬ4+ F֬Ьxjsp> F;wq1oAt*yt)DFpC4u<54'i!r3 _#~_E[܃-nr"0A+s$b+!y+S4A(#+G)qSy" rh\p{ +s~^#&䕝.LA#+;1\\,h7:h>.DD&ڸ!) Ii#GM&?՟Iqg@-nA܂/Gp$b4r"G8AARrr:/grs h:cb7EDFpCD!(HJYp@pMe3qq#u":GᆈN'BP6$"ZKO;mg>^n^p=['_ j1XŐkfCƪHǪƪ(UnzGWլ_.g@k-@SL8ŐߌSq8I)#SSQ4Ufӥhz;Q5Nm=Ak|t}͓#C~y!i$dIgy1I;1nqBX\$u}͓#{<4O F<޿&ϯ/SZ E[<,?:Vh凈V^'ZQBhh%*ksΊ~cN-N wdD&$.LARȉd^J$Q[/iiuuvH~"#{I$!dK$S6r"كD1՟HiqѴ: :H^g D2G"@haH"9$M$H!Niu4mB8:IdD&$.LARIAJ"KIYG]?_?}v3oNڷI!f 8MyeD&䕃.LAR&yA+Kdisi^ FuO4s$b40$tf HN4hR9yIf,~>.0a 1j\:i9\sk\3I#51לRNMΜL[ 3N71|/@S<ȉ!@bҺv<'搄vaޑy~\Nf|{y{?ڼ>.ę{KYpy✦ol7;[`R;秢.Rhm N1SUOHc=y* b})Eb~w5m+ȸ\ R2ɷdt+I4ǩ_ڧ5OK4OV>-4/<ӗ^4/+d(tPd)D@E}r)kC{)ҋ_4Ap 72.'iW=w,}OABf'1r7xBR0\ ȬHԏgR_X85!cZ2O+Eё<}W2?N0Wf%^1{ VFlo|/Ez ׷AH^qo{ڽgT1&5AXd?OuirYadty@3Pb0R.H#G1Y .Eyufʧ/x{~9}أV`CSGCҰgJ^"4){$xq-YwjlR&lң !}jMl.ش ]l6I 6.iѬS~>~z>> ?|w8OUi=XpS2xZ&>h}(/wͿOw7 }=jG>3.9I:BxpCA 7booq` pr7-D[|y#-|qw6Ipqgq-e8S6DGXb ` ig]̊6:cMaQK!]!{QFY|/E}6,%M^Mg- [.K0Kis$b4yKX&Z6roP&Ɨ3$]YZi:\A!:^a"駈9}(8C@R)b_rd(;gLB߮B_C!b0gܩ Q?g̑]Ðq)H#9g@8H9cg;碓b :m O/׋=*pީ_s$⶙fճnNAҽ>Z=z>GiCXʋ:ǛgJ~BĐk& !)+Ibr@ e1 ycdR8?sgKu~ؗS9n8DN:9qGS#S$07s86\!@j9_m!>JB/&]h3ΘZS!@^g3ƾΑ=qu;Ii#Q$P_]8㡖oUFi2G}#L4S HL#L$ֱq ~ֹu)sï@89#6I!s:)G"vB!:i$eFF/]pÚ|ETj@Vr/rq$b4"W"rEEAR."W"WD`w;噛^֤zN'jխ"PpfC"]iܕT'YJ@JU04 x`+ [ Hő}_itI $ _ _IRnj4~NJ\By$~#*M1I f] 9A1K ĐSH gjzSy /8n4DH:1I//_4o(MI7wt74m:;o'v'r${|b)H||b,Tn4M~ğrco`h[nE`K7RF"e$AA#K HI2r)e袟~TbTxg塺f= ͬ' $嬇g= z4f*SŌΨ=~m֟ۍ@z1kY5,DfJCƬ(HJyJ`JҘnvY|~y?/cտ 'Ά!Zq$b4*X% FAR*X*XTXTvi'M?ʪq*j=m@^g,zjő=Ј^itIi#^ ^ʪ Kr|[׻z]\Jw^|,xON*/+ )m\\|es!/7w|.Ooxz*Eis-G8SBsitڝY5OOXM72̅C`JL!e8!? RԩADƝ6Sa k .`*~nC×S)@G0A sBh,,[3N~5G&^I83Pbdž##ܧR.sH9"θ8G?9Fy>?|Da`4x=,̲hBqmcJL"8Þ?4IM:[jFW ÎB3Y6 0q>7\a%;r+-DH6Ĺřn%=$EgЬ°&1tuCX3%@/ cFNh& FJ/6)Sufglέxz")8C|&k>4!6bk$LCli(クk.'Z^gPuvHC/7Hh|a_ц}aMb'e$fSQh:CN; 4Hh;ԳӦIi#[w&`ݙD OQP΅xi:do;ͅd/C"@c/&e—0^LRׄdDqFaAyaҦHhŤKR6b֋I$uFةAyqwbeHhlŤ6bI<_Fg͢W/7W?;(=':^L,0G"vD㽘x/&]쑽^LR&> ՙT*i S)a6 cպS܅!z5c2V9XE@8yr`rXb,VZPN {bz޿U/(B`kuM}a#_ƾ3 L:iGL3I<b'xRmz`^: b}aQ`S__Ho6OC6O:7O`$i ΨOfu3(SQh:caQ`S_eHhOCO:O`_$ %6BqRk H=` Rk m55IkS45'3BpGM{<bku(f`tI#+(FR+Lj Z 't]r D\4 7$t  䄎 '%tNn ƩAAR Qi.Kϵionc)K|/Qp$b4"QXDAAR$ svNZTz |euRח%8qn,tIZ,,$Y>Ώ)NPGYu]i.˼Ibϒt[L&9':58ᆈN'NP<88$qb~@]וoәJoOOOLJ񥮱/_G^٨K!V^}St)83 )N )dI:/ɦh+^ܦCl@^gGtCDFpC#(HJYp@pzYqWvmwEzUD\a6i7ˆ:ie&椑 d@uɃc/'R~SRWBο|/E `CA azEZBK'pzc 2tI.>w$ &q2ꤑQU:VfH]*ϐ!5|tTG\JP%Js#F0U[OZt#5?gU.+*1@ F> !*\JF)|ģJTIƧ]^ҏo7''@x s5 0[4<^~/"OZ'Rny`rE' -V}Y~ d}8AXUH)wA#R> !5{Ή$KH0%H#Ɣ0 K)G|pmuL7w 1L|Ɍr7dU3"i2 ^3H"e8_ԊM,I+Q_n?,&b q9d 3[62~/2cF)c|cƸ2 sGZ׫kp| OJ'Z)5bRHB ( YbWHB2AD9irv@^e`fbf&K 𲿗)g$+8|!RFX,)ermN!s <iJ#_ ц mDmFimD4cwzȱ:pq֤9h P]Z/xĀ}LquHy$kLhLQИL6'&aR\=)4rG[̗5RH/ !| :t_ėR;;E/O5\~Y<⥯VՆd?MW@>hD0D *Qbed ȒvӴ&L}=ZFx,ف)ӕ%9a2 &J)edi2i2Ҥ5іvR-%_>S-5NU "vGB!*TPP#CCAˏ;늓M|H[S@ u)DF C(FJ!Y @ Ded|Y <8M R_\t]>s Uթ\tu,D\4ZVeEE1E,fE fEA̪!(pJgqJyc@S+ȦŁ=H]qURH$K]H]Ql(9~5&%٨NE|P@j]UZDE1RZWZWliݗT('jt7Sl7[xƏrtc ~xM`4NX~cFF!+ove2;}kݒE]vn ܱ%a2qwy @ǫ7:9#+!ˈ-<~#K E;M` nڹ\s69ծ/EJ,Bqm8J,woti!ReR=pqgO盇O241pphUɁ.y'BCCrF"%x,TZ7<> CF8<?B](V3#4< j)CpfYP+|L rF< *sd`cڅ]j,]?~:> lտG ֢Vq) ( nԨ'O Y⇦f) \q:Ŗ@NkRNhs9mUjR! )md]o&Ѧ>d@Wl Ayv8Z7Mɺ IG+9yA&Kk¬IIHqzŎ.n@Evm"&G"9b{) I,dMDڔu> sc>y޿>n?]?o\iSF07T:V=nVQ[QSrr%j~@ QԨ_uvHz#{Yo!뭨[oQ6z+V[ϗ&p[Fq.::WO|8O2񉺉Ii#O|"DqmA\*lnAP`VjVQZQ6jj%ժ>dCVr8~o1X@ *W6\q$RFJCS(HB$+W (WIRl)ݹILxBE- *W6}#{Q*+ FVP\̏1FRˮdvn0FyriW8* QN )md**ĝ|.+_c.㳎$Y %-]⺔ax7qrux`;, #Jό&l@PR`/)q$HJitI,)% )%q_F4 OOǟ%LSy빃PC]Sȝ {]) ѕrI#J JIbz^&=q9W+dDgrBκ2I%y 9K+TyJzA5Fm=@%:C-!_FQJCG@8#+J (JIR۹lu1sӏ[l=@X4Zg{H}ш#{(D# F$ :O|\~~=~z>>쯾- Hz@ $DF@JC(HJ!Y@J@@J2*uq.QhX Cm@^g( uC$DF@JC(HJY@J@@Jwi) <yښX%l1@| 5/p$RF(C(Hš" Ed+Fw+_srҊ#fi,niEAҐ#/XZ%iiUl@C^?_?}t8~ ߅v*r=}PıgS&cG".rؓĞ=$]˱'ؓس<(^tNÜ;>5W3k DɃ.T :V_H!Q"%H [YY$R"8LbyiW"9% Q"N )md%%H{'9ݑG:l6 8ڬ;(_6 hD6$hAbO_X^w?Tz |8ج͏IVnT|Ya_MNU 'G"vH}!gi$e}f}F4W˩.pu8.1 olv?vq#zNgG(^jNC9sL r MJڠ~}/nCFUc>W }C?,^G!a[\ؽEae\Aq4To4otwX7!֍g8RHlܘqcsڹb$2eq5Vuf X5G"Clƨ1 1jL=X@miLI w݅ HqEaFetx}Ecu3Pb7iAc4ѥH"3&`Ϙ@' HR8jPP]<^_,N@^? !}#OC'K E' OE˼/13Ӆc5XN_g=5@N? !it3DL7=1. DB#KHfsd%LQg:u?6G?@ VSFZ0bgI'8o4-3D2=MaZ0eeKr.Rtzuӛk7)RWjYؐ+@: !6|d!J)Y߸B\u,t,c%Dv9,?\ƝRNW.@: !}#^!Wgti Rҕҕq]r(iW$xPˆB٪Vgt8ĶoD+3D2=]Z.dedeMw1H BXyaƺM?Qd~̯͐e~)H&9k@H_㋭3`ut (la!`S6V[Rx~@ܙhYFgi(Ƅpr 89j`D&l.LAR a VJ\,MuQ5 (g ūHĆovHB$e %ly^2sm-M97m?-̑=$İ%)HJ95lAjJab+pIw5oT\i:ym?=̑=$%)HJ9ElAJ)\[ 3N~#{!bS6r؂TSŹ/D? 7DʢǷ45b y#:[;fH.irvH*s$呜; wlqa,;ij3y9ܡg0ǫB!;I#!idL#5rق4v*iZn>qCuƩuaO%s$b4d;$lud FN%[JR*Sɏz0D+ ö8HnhvH$厜8 qlıƕݬIq6 :;8^gv1G"knH$$8)z#]՛!@Vg6n9DܫLiW# KyZKbM; 8Ҹsj1_(4th8m7Dhp:F$4\fiB'N[ UrFr#_f9,n9EAh#/-i#"udwp-D&d|x-G8q svkxk1Y)[Bsv:[3![9I~+~hK.e.MaĐ[O0t;6[?Yܲ.\H@I_;_t,%w,> >]>?|xz0nwe=&lqBx.P7Bq I)$PX8qs :u0s/2|t|G'C-^;@K?N_8Bc| C/Ag| ul| $+i em;錽Ȧ3@ǴYhÐ酆6~m6$͉ȴ6^2ٛ6Wf9{Cˑ/nc| C/Ag| i/_4;&NyF_mtއǨ-^)5<kmXㇰ+YC@`#x5O~US!<|\bxem/x텂m/^d{s糉B5,S}y5rH#ۿq!sP4w-uKB_Ui% aFs^i|.~|.$s]q|ɒZ ^!fq7]N Ya(maʨs.D~26R$bگ)EQu1>Yr;sö8 \۩ 0(7bC>S)R2HqEi4t:Ь; k\:fŁ|̈́`ҚGU΅tWM sA߸SS)uْ笝hJ7<&M.Ьs .7_| GU.mBCc֩mHJqԚ?ⴑFlwOVtI0+L0p/A5^s0$bO5b/aH:H{ $x|^Yg}߼%l 6%8(w*eԂ ,OLy٩Θٰ"߮><+LG1oL2 ΅tyĐ]hSy6uIy$SSYRY{420ȅL!a⯃.?D\f>"w*E!ft.2\J680Xt'}yjux9>[V-ȹPy;9G"vCj3bE~*ErG\qH+w֥"εG^KCb僨yԅ2yBp84By"gPNAҁK3ʳ$[SY83V,[l~*=!:l>DJs CDQ1!^;%TMő:$7":!uRG"B#"R )udHQ"ԩVLVWtfяokwm"AV/[ ]z!{ևLvzM@Rj:^Gyzg/:c&\6K@^g<^g04fHh!3먝Y6fQY);^tv/A9_2^You@C-DlFCӷ(HY@ʒU0øl}l$CdPꀆ| [􍰕[Y'lQ/%ak~@XeV/BzozΠM`e/PT1E.D҈\eUt"ITdH"-?MV. SY5Ry T|@Őٷܤ G TI;P4e(T TITO@3+Ll)CBi0RD| JN( iܑ" Mȥ*Ũ AOzVD|K{FLzrCA#Nz$qlv~>nKڨΨIc/[1kaι|aÑH]L}ҐORN}(H#y'Shv.s.>[ КG5#ƚQX3ΚAAґKf`(5>G$͘uemD ˥/r$b4h"0JARhhQlN'QY2uҗC99 CN )md99Hr˓u;W\:i_>{2kuB9! BN )id!!HB;oBqϗ-SL/rr$b4"g"rIAR"g"gDNoO;oޝAYZO=6}#{9DN F9 9$rc  \ ]O %{'9/ճ Q=.LARɪggSyo=ޞe&t%N!T^{Hľhd2D- I $ˠȠEzr!z껫yĹ[N-Aey {@ HԤ!I I*pSHNR*k+|$t>7c)ʫ^5 zG"vi4B:`I$YGAUP)cx_mzU'w=J"m E2o^^H> FOhԂDGH⹔~ij&"F-NS{!m.Oɐ=ڌH/JQІG6Rz> յ^koql6 3J/C͡_ӐC&]z_^A *l: uF vH~#{9krפK0S6_8kaO}SHlG;Ue M!@^g`a'9MӐM.LARț'I}a%|R@afӥ yqyt'9Ӑ.LAR'?}.Xh3>Nʷ@FwWv I]XO̐.}#[Q/ EV/ P/^Tta[qSl1;C ѩ dQ_Hi 3D0:1,  #6_2:9ox!B^i([tCe DF0Cd -(HY0@0l1?bE<lq6C<W0c_s$bY٭)H1W`zwA;5:gp?nnϵ,4lX[N5`+]7JtEA#+](]FRb?S.s6||v wb1,:B|}#6"YEA>YY@U0 NY`7[L$7,:!uG"B#Y!I$,YX YXIaKLuL΄:1[ ƫ?!!1ǂ?%h(}쮏on?_+BAy<сӗ'8y'N )sdyyJiLH08WOa|~`@BkN- G"E#O!$%,OX OXIH5y>50bvy(i%8Q%N )mdQQJD}/-tfDsx!L^s,Q6۾DHvDauI#KHV(w\76b335uff$8M$N )mdMMJD}@) atf~|j+ly#`b5 DFC4 ((H#Y@FkJH-:7n$5[ .N.34~r#I.!eK.S1rrق䲕)ORd]9[b Ȫpy} I#!idK#S9NN#;FvR9OdwUQ}YFX yqyc M I#;]ԑF>= % α :[<#6N',~:#;I'!dK'S9r:فt.ۜϲy/1fIbiu&eO#s$b7id7$tid 2FN#;FvRy~eW@cL[/oK^Tv\2G"vHKvCrNK )\d'咳˩7'cǝl8!@^gK`9\Kv\2Ii#%;)\j Y::l6 3"wCM ";]dEfcreuem8!@^gE`g9,Ev,2Ii#g";).d굙})2)%ȌY_u*(2$p\|p>)D+c,cHh418$m1f Rǘ#1Gc.KPJYﱜBĺpy4 &-,AJsAȂΥ,tp e!}t=nT [7Co~@=@tJ' Y$z}Btacd{eI{=TWLos~da}ĦtŦ5LI% :Yt>a !aQӧꅀI{j̪GXh6fg_mga$>|o_޾}}eb#˲j=6V\5GŠ6#k+ hil)XꑀꑘqzB? {jՕ ́emfԗ==&|hU\H@HLOuP̎`mǵ+;N]emԗ=&|h:\H@HLX=L$\+w~<aˍ&]D-aUi.,Rܵ? 6퇗M { ~]⺃: }}uNŵ)GN`qSZ "qU"GmteXh?4N2$㨣`JQ'Q'Qg}B^'vWX5gO^UQjg>} aШgizlꙆ)ܡ\y_+ %zH~hD4DDK6MÔ2Z2Zb2Z}\gɘ"mD=WQ*g>} ahgivlڙ)ճԳԳֵ[?IZ`nU;+f@*e3I!Yf'1uJ{̯n(ujtE8Xh4Y"%p`J*q,,Qf@Qiܚh@TPGWt Cnt\)@)T9Xwv}`Mvk'mn|mXkL^y䕭)G>ye0ye>yOթ>u]m5@xxFC3!O>}2}2}'}8kxuAsEsXh?4kf`Jp55Su}²sa } qOWQOڄ>>裱EDC2>J S}8} O 1HU\=g~mLAG+2=B_FCdlL9p>>S~}Bt>]3 Q{2}=|EXX?̍L?gL` \L?S>伬d]!ǣ{v+]f3OW;WdzvB#Cd(+;\L?S~}A$k͎ܿ;R,apPĹ,~F^* T ut+4=}~yt|~y^%Q%:ݬNl ZB]_p?gp`Jq~L 5n*Fwjph:; ,+~F^ z MlFͻkSnw0J]u(u*tEXhW4#"R,0%}h~C#ɕ>tgH,u&A'+|diEAi WB ^`os- qy,) ] py,t\(\h8>?޿b&z.oi˖=t{t*jW f6q.$Snըۣ~j#\0=qyqΒfmZhm&{Y- 9iZ+M\ IxoZz\ +ǿ|zZg7}zpw<>Oo߯9<Z7k_/X=wŗkiW4/:ƒ\"4mε?tMbFZM&Z-GNuﭿ^ tWR֝B6WO_o3kzXxu=&Z-; 3\Cs)ᭁ(Cz+6 s&[4,hȒ=ަ i]$ˈݹti!Jн]J3$a?xr{sA&QESb:]PKD1yHMsA OA&KXu2 ،eTt7|]$ft?r.-D9Ѝ}J.üu@]y`f+aW/ة nr),pw77cfX 7pC dmV 08b2]<(&b-GnFDΥ\K Q74S 伄übVLf6Stt}bfӬңA۾Y!o[̴%]bƃŌgyIxvo*M)xx2ڔkңA۾& <<ʡ$>3#fQ.rHࢿA~n2A.:]Z.=_t ]Jr޻9K( CO:W;!as0 ma깔%eg~)oͯYoZ(D63"P`d)$=ѳQ %m偪 3r4۬o??ׯn?~mpO?&U-ԩ "Q+N ЈNal)H>R`Mg0! x^QՆ6 v4k!Ws7%mZ2BW9 jlカ7Pڌ[j U e;m( }q2 (Q hUTTʚ˿j]}m~o?*@J@KvI#^!e///] f'#oK/lj PR F C`S$HIMMMp&,f:7:!uFB{Q!T RR  LOjKɑ85Sg1 zC?N_oHh/4C8 AJp!!0͡>`9х1e :CݡҦ;h$! QMy %m>溛&+/ۇ<kͥ=CBoٷCÕ-BBٲ![`ܲ K|=-n.)6K8 Qz6h FC`,$H%XXXŗ˱mR+\5.Ժ!W FCd`1H%.c c&c)~cas>޽_V!O`84`U#1yMc_HXoFĈCDh1$HAEDDt5 >иh)#xh1b Yl`{%mZR+g6(;.یu(1B`6i }a"/M (ŋċȏX%|<4beNKӻO@g6d@]gUlʉY Hh4ZEUDA *"*"=ju:mm2um)4NѦSH6\@Li+;SfW q>ǧ :cbS95 @Q!Ei ("("(u4;O6WZ>y]UD:d͕ FCh<)@Jpy"y"2y>/R5s-{\3':!mFB{'y" R҆KfqyquJD;M_Hh4JDDD!AJp%"%"2%¯|ĒZr{3 tC\ ($pMp)i5k" ׄ^>eT&gUX!@]g/tC@/!B  ""´Y&{vB>bN  il)> C.|=wcNuaҦ'Hh4q4$Nlqb R҆lj''>? fNfh:8q;M?NhiH8 ''N,N|J!I&hL~x|3|_9{|6 wC\INhBiH8- 9C(ɱAhKǧn?ܿԣ%+2D+#۬ȩaHhW44$œlf RG0'a.i]GWbEmV:ݿ\gveEtqxy8] /+$r^N)9  /3="8cWnzPH-!lAc[ Yl> yg߿m=;_sN~ K2īYs?ԬiByH9Bd5gj?/S ,fh$|?2D+ȹgHh7q<$Μmqf RrǙ33ggy+581=h,_[]=nuxp3bo)ĨۼgHh'4q<$Μmqf R2Ǚ33guj, 3g wc.uaҦhHh4<$Мmf R҆34&ܾTע}Mk9L YlN֏a\TZ &(髁ˆ_[Zs wmqϥ0߈ lY{Bd7";8Z9[UqrH~ A~n2"x.:[Z.4Xt ]|Zްn]~ԐpUpuaSH}Abi3"x.:}Z>4XY}BԙMZ6g.>? Dvj8h_>#Rӧ(C+MB賖\>tO}{|}{ҍ$-*hd; F&&`\"Fpg"eDB#+ŝe"Y0+.<°c9 /m8hۻ.#Rӥ(BC+MJ%-=y[UESWۜ."pknti ʫ߁Ϳl3?w,6Oobߪw~[`S8؀x\oos)=xQ64V]҃'Y_ں=|a >=ߜ"7o~-J?il0xݩ^_H}]KN \ׯ4Z~:)ѕH1`rUuZ 1FƌΥ\gL Q2N[+6m)CYc:}/syMiYݱeA̒ꢱN!i׳N2(D8q%Wu?禹ۍ ׫:#Ezt }S3RӹCYceTJUQsus-lo5vNntmB,Hh4b2DZlb)Y] ջ\ID}u nX"W76ak!])$Cl"-FL,2d`.zKH}^ln؏LJ;y~~/& kM^ZH4 mFZH_M %ikaW}:…Y yp xF &7l-#vI-C4ŦIG\[ 0l}>4>ܿ:ݭ )PT.Xd#^(VH`&I:```敡yulIzo~T1$J_B.z#!W_   +#sLmzf-~\/ 8>eBR順+n nHg 2S,8btp^ 3\vY@@3}K#l!W_gVV'w1K˸$eubD;M_Hh4bD"F!AJp1101 H(6+˛o?ܼ{q-T{89KHh74D"AL%AJp j}@YuƝqC2 5vH树h42Ds(6ACCGo|zS&q :Cաq@:!C1 %mPPP/Z'M9fe~ FouC@S!ȥni2Dy(6A\CCazi%s*{,aNPmҧԤl)6O4t@YXb:۩gA u#4 MiHɦGH:<rMLb7K<ɐշ1`}L3 ]e$FCv@#F!bd ###s^?K›)?ٌn<xYK+x;s2q3CԺ!&ѫR_Hh4I8&!AJ.qMM1Mb}@lkkӛFU8FnҨHh4{.7dl{. R҈sfϕ.R@Y|ͦҜ)3HF׸&Ir.$ L30ϩdž.RU^=Is{.򦧹Ӳ~O~$zJ"ؙn<>_?V>`fSoӌtޞ6_?>??+k\ׄߊ2 ~v7x⇎fphn$y%ZJ/O[ T6<-縔~a|',<y,䣎 Oo=\]EmHC- DI~݃>0,+'SY]laS!ۉ5T ."pVou?DMDi J݃GBSZy,plVΥ);LWe`t6{C)-D`ac9,4~ٯ )Ϻ" k7=̐(qsAzsb91{~W%Qya LJ,"c.mm)TfhbC ,6T8h7S¾gyJ QR UJWFNg%}WTf pw[mQ@ho4¾}%(ď {p\/A;>68.LB7BյGN^- }> 挰rF6 %aR.!͐@_&jx[n_k$/r*CVٶ* 2_g.l]|*%Lk[z%Z5D@F^0r]rI!a|aH3r]pI\ mL4Q35m@]glږa;9F!= Cr߆6 }@4ܲ YX|Q_l$AH.jZB+@[4u)po  ~qrux밓]f^+f G^ȋFBg&^-"Ad},ROЭy,Pgs\V}eQ#q#.!bBq >ݻqrgk Pc`k Fe CT`S%HI333y!r7 AtmA 56J0\o @o LotXIRygs7_n?f\FSɃ`PKR|"P qh$# 8M %ƑƑQP<:ùޖޓuG;M_Hh4Gq$!AJp##1䧉m6{i,2!R]ysNFB P!d PK?<@@:ɗSf47C8 ޜah@NC %mx:0tbanqȹn?؛!@]gfoNFB{ A!!d AK6<@:t./Ƽ|ߝO=VgVpLzչHI!1lIKBcĤ3I qmVͻk3n^~8! Ǣ!VmNmHUECbѳ--AJE =XtCZc;-yݛXI^ VM.b{~0)$un0($@13(eʠ%lYBNA_??|o.}wC4ĬKY;b FE;7y# RyYz6o4GW&=ǵD=iRǘF ($tvh3l)4NPgfɮ.ܳ+ 3H=iP.Xf}aL#/o#!X cq0004MgIDP 64 auB/$TVpB( ! 8 5B͔PMcdslS~n,qHCpbj7bFB_FLClS%H9q1515_~>OL h/o2G9,`޾{>1o_J! <^5lWp da-Emꊒvq#$$(X_&`I/+K&4+E&`|8yy gkUWw#E3=hdY4Ibv9\d\cIP&L+;}GФd@ţP REdT0h×*$/\JPRc4U J~b3Ϩ?碶R'^lQNt"aСYHxTiɇQt7LXI;kFq|KMSU[ Ht?@>RUδgkdoC%e.LWh\]̐% 85Z]ÒחRE(YԭW%d<]>碶RӵC8V."aІ UH_JJ N_ixQv><6vr!PKڼQteA|2ELJ/wm0e@pK)׷ B>}0SMԨMn [}PAtuA` rE/pЦ Yr,d l-ki:8piOB'h.O cRUH2+MD(: I8.ڔ'e1 \:>wrݎ6a|):eF9}LJqmy}޹4Bu+]:F݀B ٍK)i$0J񠝾Tsb#-#i乞GSc-Ԍ:dՌ4:7"yl$1Ɋ+G(G(Gk9KgxSL<&\Oǣ)Xo:L7֫o~Hכ z$[2[\QiLOo9ңBY!o[2|}ƳM^h˹ݟ><|~/>^$əܯu~vFARgKS!]FI w񶥎(ŗ:,u<[nY/14zώ +=(>u]IF~ C`$FTTT ZRm-i}tOou6!uZT<$MW@h4jTF%1Jp=*=*=-KZRBdh˶cZ\ϧ(e} e$gF\eZ2W23+~ZB!Y}o޽>޿C+^KP KW@a~L(```׫]L$gmw{+"pBlPtJmF CD`1%FI.c c"cz~|=cLqa(^l{@/颀1YK)"0y/]-o.~fxitVe]<OW;;TWL|2K( i]_JQrL*7Ɲy3> qoNE;w!N=BD p'4:70=L QR>}":%Y_׽W@Keo?t͉ Jg_J!Q?|o#.cdUIk\*PF/o3iSK)ʴ'-}l%e 'ϔ'yܹw]yN?/I9A`<ןon߾>S>ћ..83¦j!pW dEX\ {KmNBeNo,C!6s;!Ytb}j2"yli!J+MƖTo=k =hx0m|9 ]-meDs)(BSׯ4]2|g\ݦwS^xpȐ'sv6dDrs)yB}BҞ! ɛ'tnieH@)R.,>^@\v 0)ԩ.mM` ,[`YB˅RJ8y2ssAۇI4Al4QBdHHԂ.'7:٢dNщř˴~ܗ6x ptg?)Dis«FloG5*9Ӑ#'[YGNȉE4;~G.k3&"< IhhQQBܑHh74MC.lh Rr_7&nJ^i֦ dҴAuaySS!](${٦!Mس)iel=P5(hcKd!׏  C͛ F!=6 m%HI~7fy]VK٘#LJjy{~7?<+ͤ=¬F79eBB;%5L}>b`)D+$})8#gcM:?BQHh6#bR  %mh ~ib~v1s*Dq7&ryw~p8 H]oޔTH: 텹Έ8uHI_i8O660C% CΛһ F"=4r>bM R҆W6,엩\V<6_؇/k/ϔ={a:>??[n&JA*E}@#(nRlJ)Yĕǔp)c_nY ,]StC{!$ Bv1oqu㹨Au0i40& H6\p@pLX.ml7hOhcHU=T:@}@#a]QM! oGp乼k4U%@u(-&i-@91N]]lȊCnmۖ29qHCRަC-D!2ms5?ѷ|O%YM\@/M<$QeY^)$0JD$̞pM5s~DE uNvH亼 Y!=dC2T枓.dR҆g Ce6.cI͆??~~x}ASH6x5yL]s.ɣ~hR!i)suAR -edpu]2G!dC2S枫9dLAfʜs+9O䦑4w cMPym M\#a=07;y|%HAg7޼>  9l] xw+7!"d R?\@LpsQn 1"'vrqY*cb[W 4&BH5\@LX3}liNM! ඌK?:X2$>G!\Xp}y&>< FgMP*P`M_HWypm•)G.]e ]e&]RymFw'շ5{OW;!k 9Y!g Y+ Vșvg-یͦ`q 9X>t9>h$toe RQ\X0ykr\Yi$\txiЭm,mfFqffKNǥ&g GmWF@3CF86|h3fαfəl;7o}s4 Κ=:9;U F蜇M %{9sfJ_fWHn6 `@u#@Sȣ.iy9ۤO RK3>g&}暨gfI͓W~z_Ƥ=dZ7TB;\+ F (M %:%tfJhO3q_dI6ןř=dNWj3} T#h ti @gL /aybLF>/yG#f Y,)|–?g˾oߘNF2D/.+銚Z`Wf9 Y-)yŗC X-l9\Cdhfe÷q54+Cdzz4FBgFChMC 5h3Cʥ_ qfkj4+q+CPMT򧯦k$+5}65]j ajyq$Y{gX{ 3E,hdy,:dQ R҆ˢ3EF ێ$6~=s{=\uvlk [w{s^g4OLA%T/.km+\HY]!+[] BYϗV,| uc|"< ^WO9]=(]Em߄p^Bt$I>+t~&<.n6XZ]<]_Kfh tA}IC"IIzK Q҅Ǒ<#D˔Il~ `??o ~VEQ߶Y=ؿ]PFݛ^)B{7n>ʜnFYb!/8k6X] QSOK QDz}z}bk%2-xlu?ֻM}7$lpjh0N ԗ8h7Q4$JzQ 4%ax:u0%xpSJ$8۬f6xW_>=€P:@@0 ޛxx+cF9%p ?}JIwp67:fU` w.pԹVHKӐ}v2H9v[ĶVgYgUԯ*vñD/i*!QEߋ*^F*zU My\2?㌬ h:6EC@s9m{-.iӂ-<8m Ͳ]XXfd}\k5pZ;e7HX2XC2IL,ab e..393ܫO?ߣK*fAUS[^H[#lÐMwm%HI`Rsq̑͠ݱ7 T#X/蠖Щ \./5! QMM 嚘 .-qɱ͜~y3f5U3aӯ l~F#/q C7 7o߬saf5O/UR@)6[jVHh70doRRox^ҴAf|<>ܽ]o?=U>Ps6+a2A)$ * q %w<'5+{hgE#mE.6kX{M< ăM %***wcq`/Tu*iW5.K6\@L_kAٖD=&?PkW2vhī0D 6JUU`w)<4@t}-jK mFrC$`$HI.9 9&9sle^K(mЗ4 &7H2\n@nLn1.cRroED!b b/5uIl48D6 B<\@Lyl}y|sʿʼ2qBX}AB#]q m)yu6O3ɘ؜ɲ:q+I?zoqH8ڢ G=,z\0&ro~{z{w?PAZcv(S#6 U|MI)e*I bhf +/}luV7 DDt*7Q"%"ڔ R?\@LZ׵x$fq&D*E}MB#hq&m)Y544sdhdh;t uDFB{␉,&2 RROdLdMd{!u^ BԺ!ѩR_Hh4zDGD!AJ.q="="2="Tg_-Ī|y=sƹ/_V}p_kMɥ/`hT#0M %ϸ>jKf<&.{31:!m"FB{1#D R҆!Քa$_l~]qBP蠇K FʈCh2$HI.eD eD&e9P/t_(qƍ7{\p@境ƈʅFB-r(ɦ\H2Fĕ(qSi%u/rk $[~mG 4ʨ!v /0oZLsjZ+C0\ ch|MqeES![ td9`n߾??l/s3aM@To#4>]$6:f ,0-D19r`e|l6[l94ON}ۇ;_ fWEQ&x)yf-GcF,Υ\L Q2tTңL!e6j|תlj"q/t)ES!]Bt)tTRt)K!16?o >VM K;:!Mh|ٔ8h&#R 4i JPoGJӄt!-1U VEO<69Xk!=H}C.s)Btgt)1rNlyW_wh k1X5g4FX mV_HtD}ܐ-\Zrc>|[%2;=t15[j O#˱)i-8!f\a/@C qԯ]烛bb*|.ZVuu sqYx"ȃc&s-El3q.:}F_iDrҤAu}c˹ ($ RCs))yC+͛x/C$)6sK"Z A֭@"%'!ƹHI$ݨ_i"eFHRbAxw|{uƣbEk! MSH#`͸BB{dnh4šq.@#R҈Z3WF3.d:/!|w O7vo}[ 285Pt@ᡩ6ͪ\!*anUV(Ce\*@*T 9,j\bI p?ik$) "mG/AJp11=KӔk 3Ovif/_m>Q i#X6&Pt*BS_HXejcd($HcƎJR=uXlw?{:͗c[trLҀ<9-:5 \4\dS.$HI~.uR']yY,D)ִAu~i/49i9ɦ`H6ΩNLXe<7anձ'PjN jvNsprp%H(~pG'?-vh@d0Ck 0NiӏSk$Ӑ-P-AJ8k8HTY&|83t1 uvH~Z#=М33lj R҆39ÉnkDRdm zwpżǨ Az4Mk$cӐc-4-AJc8V8дfIy˯&~~xdXӟn޿~H>@}<xYPi"?won޽N=>/}[!f`-c[ީ_h$]nQLCQL6B?H1=H1'Rȁb3:7_:on q"ՕBƶ ӕ ƚ8 &N37'N81!_&8!@mض,P{h3!3N` ́ t'&0x{n 6{\3V,6Zk!ݓ FpC g~~:|d{|9'eu}qB#Јn8l)  ĉIh 'L6_z|{tWOd S_0FPʌRnWʴ%ghڃM.Fq*MC/<©T6=lFt-jqC9<Ͻ~]B22?<UbXJAg^~:>=~~x[Tۻ<W"^iW4ΠL8KClnW8ólzeӷY6/ȓ867 s#LO,8@ɋX E/ni!ɴ{WX-dh!GB\oUs.0\&.~=CG_28eu.:]ZrtWJ.l40OӵǍ. trH{]EmPΥ\K Q҅j^+M϶aLca {KOeoekJxͰf 3Bß+s)}vQ򇮄W?l%,!c__nI}X[BgOF W7̅.ψ͹?tuSarMV<#Wx63!+:,zm˥uA./$RyHӹ^9#0%1!Aip:Xcv^ }'ā(Bm3G#nj{P_#Arǃ{P}q-L"%W5 yU5m@]g,nʬZ F!=ڌHϥh#@JP~imsvfDմAu<ɉZ F!=07!K1FhJfYgz3 -7LÜvԳ3mVWF܆yHnlmH 3mh:D۬M?n1xP5m@]g{FTz&:u{&4k" qM$kBᾉ|&~&4v6io7O?޿|~xxqcq'B"C]S!ĥ5-Qe<۔q Rp)sm<m<3m>`lqr4UO_G.% 8)Ogے+әBBM<$n6Ng\\t:+?BΖ4մ 2HմA{Ev8Esōl&Kryyfy}[?<1ژmB1D@tvI!zzW3P3S,fS),LLlJ|T?_2gG2##Ժ!Th.oQ.jt!SotJW\iSO=~\Z?˂_0,&!@=F5GDBM <$|z[r5SgB>ݙaBcBÒNP*ГG'C#/n9Fϩ)GSO]8qڌmؔ!@]gwCu@1fx1C:pfxz\} 3[+=veP]6}K#=ШC.oԻ$HI#f;)~Αm~u\kb4A'Ioүmץ¥[)L}iQvR~ l^X6w,@E{ (SqxǞ  t,>O v6ouz۽2߿r Hc5Nm׬5:6!7jCh֞j~S8/8Wvp6iŰ : &Hh4 7%HIY A~!fduѐmk@Uxk4DZ5x )iaZ@h3!@Uܿs_HX̍,=g,-A \,=3Y:zzsʄ66onDwO #"TB$fB 4! FI" 'P!,%иj/ m2tB9F$ 7>?<z ]p*c;_2]YCw@C\uЦoy< /\{<3>`}mǵ+;6u=NNN ܐ2}Q#q  g L@I,osr{]Ov PP4T鋆 mF4M4 %Uh8pfa}ȅ]8æc؄uhi 5h8 gh(AJppɅ2~vl 6m@]g(8tC@#8C&8H6\p03!rKd1m]g*jm@]g(8tC@#8C&8H6\p03> cWQM?ncu Fp:aHh 5`H2G#8DpD7Of;m_?l?UwENe4&7 eZOlQ/_]qBԺ!MvK@,CŦ@HK\X0".C,67ۻo>~us,|LqBX*]JFB{Q"!JbS"$HID,@XKL\krx!qBX,]jFB{Q#!jbS#$HIF,@X\(ʡX\ǖWvȳ',Ume*ОhTe*T R҇ P%JL'=Z{3&o#BQHh4eH4yE%HIM^@4yayegt3npbS-8f͉\1c5~ibeH̸b`L1bƅ_ZWg6?K-!@]g8`5M [XDžS\?Ilf#]]ZI{nnX!nA}S%8)ͭӐ['>%AA<['O%Oar"&͒qUwPQ*k*7Dr6Jr\r@rLZ9f:'2 ~H^^h*7Dr6JzzczK\6Ή8!@]gWuC*@W!zUOtǒ[I̩KOwT^uJ#=QVnet+ R҇VVVj^Oqnbls%7:kL3ԭ*!m꺕FB{ЭLʴV ׭ Э ӭy16S2MV~quZD;M]HhZE6-BZZaZĔ켔JXqԯ1B8̳8 F!=PyL0i H6($EBqm)EDD /K iFP6++ˌخ , iuV\aJnqmmQme~$;^ƟM0Aemw!(Ў)KP5L'w (hP<_k˝|].oؽ>ͬzȱ'\&8uq{],3voSr;63yB?+mXc%<Ö̴ㅰ%B"l9v [aKS+UZ VHF4:Dij%).N iD40"jiկ[+#`v.zo[L9"qSu~Ɍ D1"rbU"DZ6"]$B_HS"MD0ĉ4"MH!|j[U1gq+tAX\NuzSA\@TkY0gW bqc֯Ӳ4J|ij哄)G"Χ i|M2>h[q[C~T`u]`{?<~xf!l"kK{?zY5@xQAs>(7Z;LIn᩵ q2s"co+fUfXYx(Zf. E h2MC)g2>M`(PL4&S['x(rb|% t8],.lA-7ڂL9q[ OmABd@}6+7ln hT rM`S؄|o )S&MSLPNu*+a4 4ehli<44a̺!Z`SȭVS˭ȭʭiʿl~h7*!}.hd B# ]4Ш)>\# @# T#[&_)cv^bmǸʏ1=)6V #ƩKqj6*rkϣ6N4ژ&=Si8ZB{ z8]:^BG"tFC:::?f!rB>}{x_O{|hndRB`}RC ch 2*J<@1 C42c>]߻6>ܽ\}RDZeK`u )m--\4#ŔLiuJ0%6E?̿$^4|\BuVVAsA+Xh?ZY袕FLZYZYZY~Bi~ر m\BuQAsAXh?bG"vFCbGbGbGw Mcm.yVf͘B/$E)I%$@%9m7{ttc\e3T}#6*mi`a i#v6b` D.mD mD*m'̃Z!csCAq <]g,k,s B5bY#6 5"5"5'Livqls>e抾}ޘ _Ov}-|mu00Oÿyg 재͋ݧoxlp"EITN+I-J?H*qEF%unXmes_aXY&|y׎t4k.ϕ56ܼRt9kzk 5bs .6g 9q_  /5 GtAE`m_\in\inWХ(/4Bs[^h~FqM2- 7OW7ۧ?ѬԐM5E),0m}SV/3 L Q-ZI&M\.<935xa@]c֮`k3HmAl[0%DIƶ>jk-#LM}ƒ!fj3z=寪= pPT,vN &cj3 b$e3oyL#mΦÙ  Ű vH F#=0!jvH6T -sKfBN5#S̜Lf7o7ks|uY`7lB ͋* ٤ЩW⩔6 rc&fEŒpf3;8~`0ӄAtm жazN4Fֲ&g c=r6cYӬ`&ӴA 5 v8k 6 bjR3r֢)m60M Nm&~p` A0 ĕ1'H[DmHmKrb bŖŊMð8%OqQ7_wWOlSaj}T]{Zd s)$/Vm3 @|.m3 ڼ?MV Hu[E n?FB{juV)i÷Z{kVk&f$wOm&4m@]gY6 bz[6%HI7[:6:7Yً緇L!o0i Pڬ̩K BrcXR2˛zkiٙϵ͏3]>qE wP`ĩ}J!rvV?)7W\[dN;E7kiL$/ԐEJuBg;M]HhRgmv36\w[N8m\{ڴ9nޞW9` 5-POR ][&)@1Iu V/;)i')p=ulr|0Fr=jm֘ @]g/mJ(trE'wm:)iÕrrǔrg8;Ҟ_۸3w TU{|SXQ VIbRffw)o 0ي! vb+cMjH=)BQH\N RA\t@tLtq/P'Wc߮~￟w3,ѭs RH;\9gwΝ1H_3gkfb KZ%Kk 3\TC\X($Olbsڔ %m\ f=]D-K"ɩ'X <7۟~:o~xIHk\rR8k- ˅bpm RZrq9Uq)qgGsLO}qlZ(~{󲽟7^oۇzí8;lz*hnuRѝ!).2].2ՋƏ;gK~WH 3F'f:w ~ml8#A?U <*xn|r{jtxؿNqBP6 pҼA~,t*+D_il̓T :Ұ- JPGPJSe"T >M(_ԐN*k9 PY"qжO]zhR.ӥ(BK"tΥ袥Y55U]+4PQ$]Kh!Q1_yM]-+AJoqƏ1#IeL Y(5m@]g]2RBB{. %mx 8pb1Ll_w[rj,k 8Ȳ F!=PDSHpjK6<@,8X./a"mRe6kFP^S` gp$p@b`11G?t)ZNPŅk!mqa@aoۇȰ)i,6o[6>0Mte'/>7A{xsaϭE&%Cis 2/;d@&CSwH?tez,j9m@ ]7u]A#onq,br,bhS$H9c81m!'59XknRM9ͼkL37}Ӏ~5SQ֬l>]eY]tpD!Pl~.)Y7? lc4 eM7#^^_}F n<>anxZdͅ$Ў)54N]d0u tv䬏~{|E- kJְO]HUk5m)W<_50k̅וLAd.JiS2%HIddvJj~SvĈnox!@]gp-BQHh pFK  qCtMt~8!,]SN,\P':aQ %Y:a:a ubZpHO Q M?S6 $Hg%=.0ˎ~,0c)! <30˟&ms~zz^14XM^@r*p3H-$.YB͝nxr$s0%Gkyf1mn쥚./*!]ҀA۾Bq %DI. &$&l_G/ۇ]4+R8,XJt/c-!9G}GYw.lUU}z|U6P &QN$xI# Eol ]4mM#0Q/jXӾ h!j33ce 1F#=P2(F R҆333fsFϴ9DmJps79Wo{=zjӲ$6i$#b7.zSlӛ$Hy.46xn3޼n<wW\~>^yfAXu,lKP B]D&BIA\@L26acl73H; cQjYX4,RM %0005? 2mnr҂ 57 RM!V UrƺP(EmR))ŪĪĪ}rZNP+V잱Xi$ *vѬbf%AJp**2yqI^&ӖN]\oOyfAu#`jQ\HG B]ئ]IG\@L2Nm3aCc0Ħ Ň lȘ/E~m)S~Fʘ5||wt< ߇!͡5B*@ vGI.Dl$$H!JDJDJ1ym59f,r5bPy vDBG!a=0KgjRV@gS#ٯ6˗v,خqCxED9kʄFB_B]&MHrDD151ҴwO&*CdP| J($ Q"v%b(!@JpQ"Q"2Q$7mvU4^w jOR˜c}H]LRcIjl$H)Ij&4n9N䌝֮1 CP`k Bhc!AJp-bZȴes."[o>ny#uv?52 *!kFB; .&@H5\12yP خCPt` Btc AJpaD;'5q?]c#uPiS40v6ADRjI!@]g1TC5@1]4Mc %m0aoCnܺ|wL-41}o/_{&iiُW憹qX~ v||QSXn+hxT[-F1F}P i]n1՛@>8S Ęf.?o!闅68W<]_Q.QEm_(Bij [J.\4@4)O2m )laX1 U2S$6ihM~0(•IIS\NxdSڌ_nY-t / vaERbIrYI4[ ikiJ4ˑȑv`q:ő_Įb)r'Ү8Em_ikB] .\@ls+oFreN5X5]4u&?Ial+~mdc;겣FB_Bxt]G&_WfКª7|pFT/( ~32E{f>x0xuCH)gI/_c[ v8IÅ&hM UITITIkM)e<36 un5JW+uQ#^菮G Rr+()X; +K*Đ,uQ#^(ڔG R+(e̷0pt 5*Po>| ݐpeE}p|^58"X$v-5+JYBB[9.;'߸s %UɃ?9%BB:h'3 BI9 Pv_L ǬO3ש \uH)XZftc3^ 8`y 3̕4ϯҖ2/_=\?w!'>NW!G#mPÞ,)J+͓y6naaSQKyڂ|8$ɟE   tƿr)%BI?~ U|Zo*mw]dcy{~><]y&`u[*|He?'A,a^e%af&H+C6hĚ[Mnv79埿txؿ+iz}*\(ECM0'R[7r)S)0’?g-K̟-4?~}G'扆 WԐ'UA[<=r'B_in8 o$^7wyyO*8,WAh NJ:4xF S1)u r,%B9)+=)M,azś>]g/eAQӵ*pH(?A>T`'/"UJ*K~JS%̻88x`n^gOE-FFǫ4h9U 64t0r*B1 9~JMAÀ2S:Cnƻr>͟?w9Ro<25vV+) @` t0r2%BI?~)Cfb>}FKHΓSQK_:vEo t0r0 Ҕ2fX3AhnNz橨ŔAtyu'BjQ@h;zhAK2|==@QSQ)BjQ@hfzhLK2|;=@Gd>kw<ߋFۏOۛ=4|w %ҊUJ B;%D!,8"(D&іL3qv]~>loן954=RcB{ !2JQL+"3&1S4{5Sx:^켱ݝLZ1 غ!d*$+cө&%L"S..'XX1 R#.tAtOWKN E!b2]+6] RFӕӕadyxRbOsM?^w|| MNXFXrűaNCH8r0_ L4MfLyM{>J_z^EH2|o ̟xk|3xl3Qf(C9R*Gi AtL %1JpIIIT 0Jp*j1e>]c(IUCT%) 6!I.i$FI.I IB1.C ̠!ጤ)&|[ZÏy{{^mnorUz,K}%rCJ0RRBQ` _Ro,H{> mphʙ($6w~?WuFA|bsD#5IuHBj$0hۂ%FR.@(iƶW&0.~~*j1W<]_|vx~,F+Ak/2[J.Lj?~]Ki~}@Kc!5H}A:{)RBta2+MOnܸ.m藻EO3mX^W41Vϱ$v{(ҽpr?%Dq_B&82nPEO/8y9XH.}wC1tKLnuJ7%`h^wߚ[vc3|?]?RPuq%豐u$NP{)SBaW:Pgtl0:FeTyBjt8hۏ]:.KL ]t]yk^iz}˚K1cȹ?+QW(ɱg$Lm˜)!J0iLbG%Z6[*SQUӀE {^i;K> +}{tǻݕ#eC`Q.c!UH M zg)1J{^}b/!McJxƖ8<6x/Jer,VHh,,{) aRlxfI}+d؁ms4 : iM4m@(ߢ&BQH+laGohIrܡD3FhӖdjΗΕf%ʼn&_(/,rr,JEzKi )T˟QX3ҞxӐ/ %Y.MS }u]1iJ 0M |rqsz>963m[.6 _Цh36 m0 |0lի(wϏB 7\˗/zpmWw'Nrz ցUQ%cuITBA գd+AJ{h}8F99 )Bc1rvuUiS4M{hsN R҆C33Fh)_XAF5# vH vf$>)iCIMpF4QdMVur֢lMB광HhLmz\@3TχӦ)iC/hC>L 77}[ǷEy9Ä w4m@]gb-Js,J@*hAz/6 S_i0%+ǓioZc%U *vDtB4BzzV#\)hCψR1LѲNvck̷D5RPGjHhѳN4$H$7z;)|7wq6&ܹtϓenblɬiWKKBQH[h=@R6\ gEg6~0\rߘ]'+w{ο>s]}Lۧ'-g¯K]KlBRHhRWӤ4JR>N?c9ǘib6%V=whƀ Av* 걐*+R$@J*qC?cT7vʙ1\b/*Īu,\XHA ]dVw `)WFj,44X8/|d1[Oӂzo PTiwzE^JmH9pL_G? 77DOd=S|rz~%{/-ZDM>mQ6c!d BꑝZ V\ gx0qgıژO=0c:ɪGdhKn}aՇ٢>B#!{)$AJqKgʟ1;g d-ϩAu(ϱ*me_M %meeFY⊱k5qBzGhd14S.Db܃6Q3 PSi is$;7_v.+"k~ZꊪFB_BQ5]UӦJr,⊪aqODmZ-J zFB[Mմ$[ [ [Bo󻶓_GZㅅU{XV(eZFzZ6-V\@Lu!_w$yXlSj([^RuM#Snf7 RR nn n.FFF6iyvy^3t\yuVAS4fhjMS %qff yef)qe3Tr xP= g mB=]3ۦI4\=@=4aJ7g~׸ :CBBC@}.ڇmLi(@JpҤ&ND2mISOwsk2BtXX3XH5BB6laö  6,6,6&&ö_quj2 BͰ] ۦfH6\Ͱ@ͰL.qCp$wgw:# FB#SA4g2$HDdz&Ow,MoQ9k~[̛h낆FBB]t0&hHr::eO9f;ۼ 5.DO7\p/ EÍ)I  ˆ J. <( v`c?a\c=UY]]vHXBvp]d&;H6Zc!c,k! vH(EZpm҂)iåǤ`s%f-k[3g̀0jCm2-h$ mu\ AJpmmK(UT𞬉~quB;M]]Hh.6uAcBaȏF.mMU1jC2.0h$ u\ AJp1a~@7!ځo6WaӀ7:C7 Bcp]4zM R҆k h i a &10n̄y?<9ʽS:C?N]gHh/:36A::c:i؄lq/:hq;M=Z(ŮKصE%HI-v ZX8Lɐ qC~ħ 5pFB;.b. %kx؁p┆adIV_~q[ u vH b@.v]Ů1\,@Jpb9ߎܙ2M4C w=z((_ߞ.CHjQ5]Zҥ(FK~QSCnm4f|ci{Għ P_4fB]d&Hb8\@Lfcjl;4; :aYIaHPHh2"6@225?یx!_{ﯞv7袑qb22/ B]d&H9\@L6_a͋e{pxYOxƍ!Zc!`/R'DB|! $<<x;Ƕ>Qywu!͚!ԕ2쓾.h$ w| AJp3`~@Lr>f̛6z@wE88}] Hh7Z6-@ZZgZ61Ɯ6gkqZ27k B ]ߦH:\ @ L o2mnIn5NW7;}]HhҀ" 6i@,ҀҀg@71CcњH3f͸bY`e6~! .o$H. x x& dyQ3uNk|3*!m검FB{|Y <D#''^|AZ7c.\׵ t 4^&A1_fi^0π!Z65srNk~MFUGFЗШB*iTiFFF0hE⫚ڜmY3 P`KT B ]$&QI6\ @ LfmX9~7Ok5BP`S B ]ԩЦNI6\ @ L'gc&50 vH2(E mʔ)iÕqJcJ5oy}:p񎬌פm8uա"UdO]HhGTH6EJTT`4 ӸWSl_ٓwTj؍!N]uNUSW4:SM %{:::5`fFr3n<C8n!?@N.Th I6\ @ ,7?`2ɛp~y?5^cP9(2qGq4Pbu*Eq$HAթԩȢ8q3;XS1#WXZ} "C2K2Gu)+7)q, 4n͚ԯ Ͳmrf"gFrrfrf!4vf|Zt4%ҔFBbi*IS ""Ǥa$I~9?5PP l3h$ !vb AJp!!2y(mPk3yCc]gHh:C36A:C:Cd:ܲnܤ!935PP 6uA#=P t R҆  fL> GxC!@]g3TCu@3.:Cl$HI3D3D3gwe~ ?W(  vH(E`m)i4&Y?Mjs>x/(k bHv/EOmz)?Ké {=>?]?~9< 9<""BȺP $R]aHh C06AD C Cd CrӔ6ɧx)RG9=7/O79]=o'#OۛwSQh5qeԱHhoqKzlSKBıFXh7K0{l fk=<=p;4kNjK{4xJ zO8N,TS#,"R=uTOmj Sg Ī'$$%f6 tfEׄ$\m&`9E!)@LAQ媐S9Bltϓs5SQqx4Rb4S)-)GАqJ`!5yb|i@E\(,\AS)M0%}h8NJn£O|a*|5CVp3+ojU KBgBSa A' N|K.]|NjhF͡Uĩ+Z .Mc BS4&aJqsħ4|Cm;Į~XƘJ٫쥱/ͩ9^d 7' oNt˰O+~,j9}0D]o$qC%NC!rN]DΩM0%}9sb2 fl>;ÏBypZQW%pu"\S nJiᒄ) ;_y ?__$N3,h @]k$nְC\7 9u7FqS͉ y/\&m'2s/z&<VnzZ8>]P@.W:uQ@FT Љ*scEϞb=^rכnvw=kĭxY sJcQ_zNpJ”#~__?dWր0tZCQ/9 s!裰~}z,N4GK_2EG ahFlx{R8 P= #kFp^`XQX3.֌њ`y[3&`͘5L6WtԖ#pA5 6]adʨ`Xh)cj4e(7ܔ1SDM&otLX @ 2j}S!ŔM O⦌L O5~f(7V̖  `P(fb3S҇+f (f*f֏4 &Z;Ж㰉>kX:[0]tHgQ:S0%}ttt6?W [ݱ)^r~? w/W?^H hnZ0],G -uRcHD"Z"ZAywF[j~*덃@R A C.Yj )>\7K@7K4dp\n%38t~F_ǡ~n $ʆ&"Z"ID4vI!."ZjL$.% %*0˘zBh*3Ff@&]%VheQ+S0%VVVf4ra`K<>7 IWC\I,tN!iS҇I'vϚ$i -m}6xӝ25 Z0H]d҅ 5BR.AV0%x: uAjgG7/❋(d9xt]u*o#T+ȑ:\P,L+.W&jS^/M P;̼r:;۶̬6b08]As!8 ~(.\34LI~9O^[2yuX%M4UY:Bs7_Ly/1|0_AAxEg%E~txm0}z2g{kry`V&鿞Z>S/2JDܵ*b%oDԈ)qо nvȽr%DIO;~9)h9]M~ ]<]_y[gXH.mK{)RBtaW.i3m]>CάiF]k3( lR.F`aW6߇9ڔ›cͼi:77tUCwn^! tҰ %u3cqa Mb ~2`+ӴAuxim:8Ki)i|@ǯ4m(b=@RGu%Nx>헡6xm@Uge.h#Xq若Ц)hC~RXָ5ƐmsKo9\Gu#q2GرFBH^J.@JNΚ?c<'6VmY!QB+<5%Eç?\sHنDdA>>WT>k$3sE3H g5`76mJ*W) C6гFB{=^JmHIzZgԊlMҴܥvuơeR#K$s,若K6nyunayUQeFS5 "#{)  %kxY7̟.:cW9VΉRƹۼ8d"gJrjXY=޴-3zi0Xb|mfePp5 G\ D_;bU\t}lՃY$wٝ-%DI7`oRFCƔ6k>Xq+5`[ՃkwdLGz]c;V (|7nGB'yXm]l,23ލ-3z;Aۿ؋.{1_ۋ}P()wbH(3??\BSQ?m*xx̨>.mb|mA ߃yK 46S5]4<]_[N`vN}]_:KQ҅o<|2 =6_vO-`TxUT'9p.Ps('Oa^YN-apR*xSABtDTm_|BO|>RBt,>^`r62 8mr{p fEV{z,-X`J8}BA& R҉;}pdc!S\][+V E~J5"3H!9& O5H{"D $@ٽS+ `}A@uaRHzX#=Qc ql K>^}c7Wt7Ӛ;8`+ܩK B ]D&J;\ @ Lͷo5 vH(E mb)i*$3U@;npOk lz7eX_5)E~m)7d\@L4DE yU*EenXa5 ȰM %mkØ1sͮͳjI䯿m?<~<|P1ib̀evX`5)hM % -9=@N̚?ō~ _]{)gBZm28wf/a6tÙ} j3`gFBߘJmY}"LV`ԕƛeY6og8h[7efj[ʔ%g̀g&k/LMwsO h0jhxLk;bfLmvƝ߽{3p4iD]ﬢ kł]$ؼ.7[ۼ}Х(b͂JM~/e|?oꥌ m.+Nk}i]6mi;[%]͂-e ߹|6-n eԐ*`_vF{+]ve+J QR,ؓYK4n U|+va)UHuաR `@;cA.3[}0(gϬ#6vos)u/{o?`UhuR`2;cA.3[}( f̬'<NpdOMU rH9A۾.>[|Х(]>|l`tI$.}m~{Z|78\54^S GࠝQ8{lg9{S@ |=6ߌ3 ̟/_i* \0 \ R+ ً@m`QR-[ >> ְL[ߦcy3WC\+$X `R҆G-[ l~qm|@z{ u PHp;" "lĂmc,X` E{5c&vos>=7ǩ p4xգ k}Wă]xkK2G;6vf>ʲ6MT3aeSWk$3"vm!b R2;$6n3M$o3>n?ǛUipj p8PAb~*v]BŮ-T,AJ`bǂnL"FD=;}>ׇ~n EL26QeR]=j)ƮKصō%HI#9v rX`nvmc R҆ ;@GsL̃feyCFe?W-k$K\vme RG.;]vV{g.~ֿ:r;M=(ˮKtٵE%HI]v Xt:%Vh~w}{}޿rXc0uaxRHzxY#P]k /K<<@xQ.[4Ɯ5@Ps;`8VHh"컄}X yكg!9F'r9nh3~ߞG8k\7-WCc "Ė}[lYeb˾-E'!I?OM*w6 {reh"~=0HR>x9ՁR/ِv$Y !Ēg$&;\$f9~W`1Tpt.!qж;zO\fG Q҃W!Ѥf1'vvζbhi0F A=#p. Jic Et, \1_"fۧ椙y]"a.FTTe%q?3~di3.$NP5;E\H8TTe%q>qf6q(lӉ6/3!`!m~b?tJb6@84y769Cl~جg +\ .v@.3%D`{)FI>ϻOmKJOO;bh#*"%ӲpJb=Tx̆.1 U Q;0,!Ul.Ob 34TAT 4QHiIatL0$0T*|2`2l0}L$|h޿_n^?[j eVJ XqbEjVij)nEqp<47"siipj ЊXiQHhVġqYh#@Jp+!NOzynhL7w%ENC.U]@9rF#~1]7mq#Aʹ/o X\kJUϡ hwkV˜C]H[xV.աM p=TC9Z|m`YSƊ2pARHh/աouhԴHI[ou`V~ߘibVByŵ8Y&2PW4!kuZ4- RVZe'dѯеc >h(]Ox0配BBtxƍ)WB|e˰qk|ZXGuƫҦHh/ee6^ x2leMNI&vw0È h#XPiTNhu]#sC6]O?0=d6֍c%WNh-|ZQu ^#S.&M %~&֥4ϛ~$ 3 qZk$t(xE7m )6BK<~:&=өL4mɂ>yo{9\Qtl0N=kJp$y"):05.X pEiGS2]klpV+k:{$1v6r>%Dnm'6x3nl$xۜM; k4<]_Zf`5u> CcbhhS@t 11`7.b:/b`pUGZfZ>|%5Ճ>cm%uFHQ+Eq q7> 藽56ا]<]_h t]~[)?t*2]J.>ta!c"HlOeBgt8hۂ.=4S)RBt ~J2LisJ?߷y>w[$ǒĞ/eevbp‡vj(\R(-^ΉOebfsT0opD&#\UŁIC:ZD G2 8<8h'=SxR@<+Gx┇)UgmV2Њ.>- .E'bEe2-ZJ_L`2EK )LLn==<Ѽ?/ gO?)<~W}1pNO̗^JO/%yK1ؿYaK?~̹bHua'[1GPAH] Z̜d@s:m;ϳ̿Xn^^o?^SCYFԭI ~H$[F#PFH]j#ZlE$ @m ir0-cifΊ.n/ 6E"qо//Hm~A Q҅ `K9dž §[M!!5( uRE 0Jp  13͞"λ[i_v7<qqܫsx=ņ6P#t`/aSzyHzRH(nB&67A~B~Bb~v4h@o]-7ğ5V*-⩋B<)ܝsx4fh-n{7 Pgl :/ \:t Rp'se'e'3egD*fwa!qtkdSA saQHhM2FMMn楟,ۤ"3wjj6k Л4Mi$t w*wqr;%AJp**3jX0LNmOcOC&Ԑb@uۡeUiOݲHHUbZ6JUUfsER*zh]HҲk.zԦHr= 5SMO <46}#R⼩!."35 6ʾBM_f\gZzGh|3$ҩm<<)htXEܖH@E\E_Hk)BIzzfoӛ!'Wu@̶hj0m1.Mlh 0j"j"j,.> /X{ޖ4@{^EBy]g_St)!>0yN&-eF+^Mn/=t8hҡ"tKQ҅ >xg#;ڒMti *xz6KmaX_Htf/2Z&eJe3,f"[!DIm1yt9օu4icH%J󶔠J4:3μ"MQ1\e@ef)7Dόܖl'Mn *PkZ4Bi]f_SϤ)!JpgBbƶܖly1p  rH0"qо/eE_5}L W=P2qȧ@m?7}Ua@`xQ&2PDCzEW) \ FB).ȡ/וr]/n1 WCvBȮ.Pˮ#0Jz@݁1;{-l%P*!i@k-)$tPW PJ %mx+PWTZVLƆlmYǹ3LCJn/T|+!e.K B ]4j. %ek~KR]!Хi6CmҦh$t u&tQgB:#AJp}&}&PM) DiuaPiS7 4:eX2 %miii0% r[8{&>T%FlTCԽB.Ahs$H42!yNp1Gu}X#CR(ġBb Rkhāi&f#sU*{6cx[*b@.qhӈ%HI/)R)bkXzg[+^X($,;z'6wHicNH;rȂr[U!,PU-FBX b lMLLk8.-هܯN`nh 6U uA#_f]lf3HrFCFCdF5)) 9_/_uհ-VFBGb!y  7"0"3=m6d @fl6lKź٠(̆lmf)i͆̆X iN;Z o(8VRkjʶ$=V3ǶOl|b.t^|G'aDbDbMɈ3TX^J φ00Ɠ/35$w5:ݻpʪS֊b]+[δ,Jjʂ?Ȍ5vS rH/}.I(]Q \Q],Zjw pܛ rSC.M MԐ* ]SE^xjk^*DIZZOb L]SCKQ@m`5 PWT8hzښxJ QR6M&~!ӥB۳؞+H v1=m<ӥ(-O ,O ]#} 65]<^ rD]$]d3]J.nbtYa VԯPME_hWkZXᶋnkV.D9p##&B4D32M ?EO._E}_Xඋnk.%DIn[`̴032Ȝd^R[w辘!N7el]$qЮ/E˻ȶJ-]dȲwd4LKiAmK5M. ?EO{yYA.\Eºt]KW.t)!ʥ 7.0.2-a1$bwOwSCOs`ӭB6$K[P@hX6A`t>>c9 8fXN>=H"Bm!>W5:8 %o `8 Ǝ یm!>wPHVbF+@fffyV.j$SیMm!>wPHb F[@ƀƀcSB|SCTmx-`j(V¾Jط%HY`=X {? ,ZfwNB|SC_+m 񹺯/n,.Βks$H9poo1o)_ Z~!!h6ci[%@0.ks$HI19191?o,}I+75ӴA J >wـƈ)_R|xL2#8E@hsl EB]oHp\ɵ9Nm4@S³Mo뻯oB_//,W4,Ow~x=<:ݧ/#_нO2EȦ*:-+^aZ.k3$H8n[9`[¶ʛ"/@I:lHr^dv|qtI~[qOSq&HYk bDʼ lBcMglP0u8Gq-n }rx{n5'n @Z c>bAP'.XS'Ϝ)!Jpmrk5fpp>wzӌue^=/3xt|fHᇤ4BhcM<(IÕ('qyZzGı-Aʊ n!jX!A"A{.rX)!Jp1ibAtD iϝ4|x^jxu e,#q(t4t3J?\U4FƟs"8%??޽~/e~˚3n4j!g>AP.XSV) Jpm`gBKN%(.n/o/`sAڏ]cmkK Q҅oG3h4Z6Ŵŗyt8P,5dZcԍF|J]o:E*uJk(9S#HLRpiKO.z#$ Zk_Íb"zNě&K QG" Y iXT,"Gm ۋ\rH:GH OtL;ӥ(11Äش9__b̊/n1zŘM]U@hr"6W`ኯ8cı[)㣶n3{W!#Pk_R҆KHIqfs R̥tu^?>݃CYGnێmifS~5:kHM %}kk{m`iK3WyVn ۈmeS5lM %Mlll q0a$﷠iH/k Xݖ^6uW##P辦kt_ R҆+()&,NMHe ˏ/E^f/n%NCYs  B5]_ӦJ;\6@6L^L.7PmOc?h-Ӑ^ts-lFB;M شId   MZjbǶ[l ۋmeS5l(M %ell x\Z pҁ@W8lqՌy9_?޼=??ԣ I4nܖ,5 2C,SKxX2t?dw1640Θ[7ǻ/7ϻwnO4!Hg&6^? N)! d^~#NH14Vtt{ᢻ,Wt8hߧ.=ܧ\K Q҅._i$Byl2K]?%|yrwi+p]i Xzx#qAoz,OƠ ]v/ҼɌ74ѬGoM3 IcL7c*!Sv{]V2m%SBLk 2e7q\dkCQr2]Ia\/`("qXḴXcҰ&. U1c,ҫ0i>flo2ɘJq栆0bBF@a99SpG6%yh8c&ۄ>,,aO["?^ʊH٨42 d6VLH؂J=B\)DS˯4,YZfq峻ٿJ!)F7 Hl)wez$6NOi))C˯4e]f~Ms[Zyۑ4 c!F6d icz4NOi`)CC˯4c-랼˚2n/7eT)/㩋`<  ' OL2?z&'iLi.k X6ޔ\^RBBG.&K6\:t<1$c`li..+\֜Atd)<v!O]DM4 %gl<xZ~>]xGS~%QyN3QF-NuY`UԚLJ`$'}z1rg䷧F6}Wpq7w.LD&K7鶂RDO]+sAַ\$IP҄MY_idL3qAg~eYӭfW8$6VD0hOS:x]ߞr)%BIfu2aX`z4TKUhM$ k#kMjF֙&%BAchRXko3rxz\NQlS>^]UC8E]o tp=2Y ,̷:J,bǏC3<3xjeNW7XՖ@ha +w)J0+̔h?o.uzV鬶rG;+Ht$l6緧\NPry_i=N?n ɧtLCܬk.ɽѴgv_w~e62VSTRH^ǦsCo,`0U&FGbtĊ ≞+BG刁efhIv~~p{?X-%~P|YmMǛ#q(LcE<"j;]4<^tyyH."!$cM5\ѥ($Dh2KGm ڛp ~!5HSO]bRBtI<@ >.1C*n..n/o;GP"pо/K=] .<@=yŵѶ%n|~X rH"qо/K=d3]J.<۞@=YF!;k|~E`%yM+K=] tϵgkώv!CȵѶnc@e۱TA]R6]_o'Li9v{eGby&GFcպoj"̒&Tt>Q3@vxvضGmCJ / T0>ԲP~#-ˑT9ҲwhI@K(iv&an~+$ rH#qо/ImO Q҅[< X%m㓀㓘cL`e%l#t:@@uSISw}4:> %m3`g lԖ{yM{M "* \HUB! ! Rp? -דvm D5M?W@fߖݸFBG؏.ܶ %m<yf;`b8킴iFa^<}.& ݶTu h]f4JOjjL ?X=NO7?==^v緻jYQ{Mr "֝m٩\5:$8́ % lʞZ=eܬ-r\m`Z!eC.ѩ &jy t(3iV f l]"%/l[Vknާv?/ y-Q{Zxff,q/< 5Ӭދk2 P.ײ y-EO ]At8hKBFLrD@C._5pH_ ǭ_Gej(g `aJpUtt{ZA]$x楞RBt^j^j.ӴS^*tzf |?@0 @ ] P3Pό%e!kp'"~iLPC!7Jn<4R+FzС(I 5'uY %9"jZDH"VQu*كC$c1ы@aL*e.==L==]O alʵ%s>H+A57sxs-n-M첽m R' Nd`R䑦 @`XF!3r]XF Zką,&62|SyBjON\_#6XSF/k_:o\f~ef\[r{4aDF@D\ED&vZDf55#2Ddh t[ҖлY~yyz|hӜAt԰-/L "b-ϰ)9 "jB y)`I׹*ܻo9˗{xX\Y WTw5:2qDZ8 %ww n5| XձXl53s|;Mu;t05dH:wp~Xt @t% 6ľP\|{>F(H3!qp1-8vY[/B}"+J|=?лt [ J+ ꆁFBǢ |Y$7 <0 <3 K vŁo"]3!:w"áHh؃.{ж e؅ ?a17H&>Ѓ@uJ#_…]\(BIr>>/|("h @y?:Ej;mu Y2߾>wd.+pڪ?\tٕڮ̝2|Cf̸_I0k :KelgRҐiٍ!%x!.mi{+& tt͞3ޙBG3`g<6z]6F/x+ Gp4:\6`sad)!J <[l0~)B΄Pt!-ݶ[]$ņtЙچn+ J9 ] &pZoFVlts{[ـ-bm,Mm}fK Q/ XzcC)myd{{,So%ՋF `@ր z"p!(`KԂ`KQ LXBC4ZK dEO{*!]@gE}1]=9ӥ(={D4FK dEObMq[,MqE-EEQ5ELzz ]RWHiwAo*x8γ-pjP|V}_yl8yt)!J8qԖ'2_Oߐ4Utt{qg[Ԃϊ."cxl-sK Q҅x,X)3ơ-ii\,rCCTE-rs3$ OD8h6Ÿ(Uc TcJ7Ӓ ~aCCT un3u+!e겮FBGPvme׶) w-w-w),u;&Zk :%Ҥ+n(u+!W.Ⱥ Bص]]( +\ڵ@ڵL5&0k&6+ҥ6n3w+!mFBGxm׶  x-x-xn. B~0մA!0uŌFB+e9ږ3ͧ*=j#mGg ꞂFEGplW ,,?'  vH(]m)i Ø?h*gEkrW~CwFB֮^=0\ q1a749rOh`f5o)M7 ؐ1uA#_X , R2  D'ia}~x^\b5,Ww*M, yp]\u.+׆pt:ˠnwuO 9 iO/m-!hNaCu.cwzJ5 t{J3x;']m9frxBCHQ@TSmY+H3bEkb2%D={23f)@wdjh)|չ- 4W) $p/ʱ\9J/\X9&—}d$_(4]<^Fo$}!9]$DZTBtǑ&o3b[}[o~kn?K ņ_PjBS!@rD\Pq^Ll[7[N @|lK Q?3A K!.wxl}H藹Ю.F R@\v=r>7O;q+rN3LCjPgz] RDBO&^zL Re\q)s !MPMm4h/mA mFrmFJL-5?vzx).ME~!Ei>NH-Ft%)2֜HI# 7?&ҨӐ"uQi6 XcXӦ)iíX#>JhVwpqRn76ԦӬA{O6jә BBW dcL6q RO6L6N6?긭6]dӐ)ӴA7&]+dk(${[$].Iױt]F O ::Ja޺wT[ۻOn]GJOgĆX`4)X$)N]N򌵓h~*MҐiؖc{y{ֲ懟jH JM4) faeA0%8y%/jY8;fg|BN<0@`$%3 !-0AbCMͅnY8 pV<8h%jnٙ*%DH 2a!y- 6EObl +H _,uR8ӥ(ml41`o(]j=<=<ʻƨP*g6y-S?L+g2_)pY:% O۹5իņdl`!zۮ{OO̡4Bjw)pdnov_E*aqSpyHEZb&!>rE%D9Qqj9r Iv9ϻ׿2=pYQikM%/n,C?:=a_U@U_Ydc!\U UEO_G)>c}b{nْ6\AuZiSw@5::u@6T.\ЉKaB~ԐuUiSw4:5u6/Knܬp P,  t\/s7im!.MQXo춅jz(6u˦.6uq:4 |C.FLEV#Z955Q4<^ۖ`CA΅.۹PέR@t᛹6s!j,[vz#$H7fX!g=7X[bIU$*ţ0se `K- r Oփi ca[<9a=:C8pJr~C~CH.΅i1W45$]<^5lK"5"qо/i5L B&t!mIceak; myW$({읹RB\^^WBLb:q[؍?-rєbzU#E#V8XBՋ]TXSΔ)! DEőP&yK)2!-bGw oCX mYX_Jt Y/vbM;(yED)[3dCc䦆ڛ`̸%.=YČSqŌWt) sH%v]bRBtKKdo ]|9 sbܐVpuᩅJK }}$:šBZ8ӧ(,Dpf!zFy:>^ܯnn k|@= {ESSbOOhr&O:\n ?(лirCXA hUtRHPb FKHlPPЉMkpc;r[<_/+gQCXۖ,N7FBw+;,uyw)X-[,cZ؉ےů__sNK^[27$5X%TpR JTbL6cJ""8V ^2=ẗ́p뮀UѤM/2KTxX<, R2XXXƻ|L6Uw+{nHk !̪`Y Ί]fgI6ЊЊ20h2ɓZ_k dxk[QH"pR+9\\q++1DX ȿ,~8Hy\vg_j= 9dS7\&@].Ds.>Wj$Ht%t% üzܖ ^J<>~o"n*v-6@ ·H]|[H-ܹHHs6֍sǢs`ll z`v~.#ɦ(_ܲfdM[hO/ ;"ۂ"+Ht0 KwD|9(   1#dmZ4X]<^]o z]"qо/kE5L ׭=Э}btYdGRR%X>?^os!cuz[xEzv~G.z+%_3K6Sv#6MmiĻwϯ-ܧL" [ ~HGH#q(hE55L$ ע=ТDH3M͌>kj(* t T+-sBBt"D}&(p::l>[ +%M; DF u]C[BH"PСj"j-@Jp::0oDdb;ur HnHWCEzMBH.t)+:\@Q&dGL Ჩ_}ө!i6CҦk$t 8tQCZ,AJp88qddʍq##k#ÖFF^g[?햕ܷHũ!uH`S]kXiy5 6ȶmi֤ż VZ.,Z ,@X:I܉Œn$+x!?x⇀Amִ3A !\:@:#>/dEISCTQO%n/+!YtLthH& -mbtl䮉-8O%HDtKfX 45QfhhR@Dᚡ̈́(ΎfpDlW.n/V -P Wt8hjښZxK Q҅vbta|vԖ8SCP3E#SMuXܖ1t@\3E` Yu]M\1(**F”`RwԖ.{}rW:4 Y8Zn::r=B t]@WSd)!Jpб]rLr _ѩڨ ۋmFVt8hwK Q҅khβӐ";<ˇN Pqt{-!9  uQ\M[m .\s@seQHlkjK8 PN;]1ZI].E˻ȷJ"Earv_!ө!oWdWt87.bWRB ;!ve~2Mti*xXuu_}_t WPSgJ]gGѧ q1劉!mł Bw]$& ,\w@wT7./)._=ʩVs@f,oH. Bw]( 6\w@wT7q1mح.QWmF6@ ;@!#PR҆[XY1 GA56n3j!mvFBG0\C  ~\b3Ѧ-u7R_KC ӛCd @ýuHV|[_scc%e'o I'\E8عmpƘ~o68>k'xUc5qրT lMc3]vlcDWwlL !fn.n/ڵՐC]ۊ.bflLmvK Q҅ س鲺 mapD8]\ 494UO7]YҤx\*QBо=GQ87Ljg<跿!w@EjՐJTlMͷm[oUl`-hiVtt{{[΀m.bmlMmӽKQ҅o rLw~ ;EOo n"qо/6ۦf6g%]Vۀ]OC2Hc ǏLO n{[ς.M>{memk{3]J2wH蒖̝,dO7Ll}=*q/K֒g%_xe)x؛LcQC :$ >/Kg2<`Az*KIIwIei$|МӐ9km$aB_HqN%ikqεV4N REz9:ilw?>==^vv_*OQ5 2 = FI$tpħQ%H( iיϰdba/0nr4r7jGC}YdKu 2{ _7kAAV;baݚmXZABHcE(A(c&\C3>WƶsMK%4o<^@l+17jbM}@]@RBt q"tIn7Iy4MO+.XؖF3ZXEO@. (+`3itiˡ=>~0xD2\iĺ &Qi dS^Qh&a*ĊA%D II֙?dr&s9d9L"qо/VT+%]FҀ.rIA2mY{ȸ KNT7n+mћƂ9bhMeϸNQro 2GcK:obڊv:CXrEBMT7*F@h%tE!.RH+H?\ 5@ 5k-4-2Irh 2YoF8Bֶ\)urwa)z9 a8e? FT*MT]B|0Ȑ/O9tOOOa<5 aIU!ĒҘɚR*RseA.t#:T C$ṠHI)!JPMhH&vGB4%M0߮(`09. b 暂h\#bbbU.P_4W<-Y$*ކBo <=2[JRo/WZo..2oX\մ[׏Q7ΛBCj8gzΧ\L Qr˯4gF?3s~"#ۯmH*xPt tC*qо7]zΧ\K Q҅˯4]%Xж%ȚStt{VXA]$Kt)!JPp%t9M.n!=>j3]<^(VCpE+C*<=2]J.T*\~h\]P-D0!P-`jzizȅ4HI.Ҵ)Bi8UNoSw+yI%z|{Xr}m9:T8eG JW0a 3Q:FTw~,]B,Y:!qflTmK}=ϴy?yxGli)P`t.T4yze%a0J&wflCH rHL]E} r.%DIL]~ ]珃 T׳myc9{;yGgmCGr9 PWt8hO]zH˾*-RBtڲڲ/5]Bʃ&+([fԏڋu rD"p/tBE'UpE = }g* ޑ+֓W6~]<^n x"qо7]z脾RBt::GضKmcpti |{xuݼ;& !)krAikJ t|lAZj+J%聖K-qvSXՖ *)z\0!)w0n y0W j^@$  /B'VSض%xZBM B)qnSzȊ*+՚5D**z *z)*d{t!H@^J{ @"cE"H(H#᫉3JD4A"×5RC#3lZ5_EK-T"pо/⩋B<)%DI.O@"D!fK[tb`E,oʁyT`E#Jw)ce <%t Iff) GW6׀6cxṢkA!#P]*je @Jp 6~8؇Z54k>d"WCUd@#w)rEV %k )K;;zrW5ԡU:`G TꠠDEХA;XӦ)RAeqm][:W@T0V&W0Cd|;R T Oradqq)jz>^^n?4 jyP64r.k$tjz`}͝#adұ3ڷ+jrO7G$_ϯ;u 5D 5c6\W`C5bv~Crd=T#@J$*8FyK߸{-r`}]s͌'&V+]X+$l(Rql/u9O'8xc۪- 5+h`MhH7H0w)xVt t̠A`wgfG=]&6CkҦn-h$t]*jŃmHI~T<#'L/tm/_R3 ?5)@Xw*<{ X5<*AJQ!*`al2Ҁpxx:Tzkn7*!u.: E.3BzƊ:/ g: y`ٛ-xfo_'jN^/yŧk" hATtPHŕܷmT|[adG; v1 -:>|'{kn7sm tBBGsu|+T/Z %u \F֚HJ9z*'sM TpU#kQH(q.qE\+:* yֺyg8ڂkn.#6Evkv~aGtx+T/Z1Fvz+fGXt\=K-kn4"Boy!(.7p \+7܊wpì냉 MxO&6c?bS*0˷ִQH~D۷BmHIG뷂a~ vBvW ]uukM@+wu+ToZF2u++|4$ @f+WCue@+.iӕ%HI+++``8㞾-n2~5.Q 8u!Y#cPɦlڄd R Ɇ D?' q6n3+!m"FBGMٴ   tσ2;m.ݿ3ͧݱ|44+ @vCRBB.ziy"@Jp'y;IXr>f۝M#b5!AYw+́LT E"RǦ|lZˡ %|l|lhA3E38'm!ǹ3+פ!8^ e nD{ Bz"ƒ(岱es?sf۫ƔE\3 pP7 B7]tcۦK2\7@7L7vip3H_ul\iS5:llƶM6 %mlllllOvp1xj >Wup  % nHd/$cE2m))%c $c$ccDƊNJjU5@Nܐ2uX#_Ŷ\lb RRŖeg)et`-r_;UvXIu%Y#S(ɶl۔d R2+(ɖ).ϓ`-o?e5?L5 ն_RHXbClrJ^ UL7TӼ\P[iu|M_l;lKٺ/la;.m$H9p2cʃ7ˍxiK}񭛯Gt_ u-gփFBGlY,,୧/ït3/|5@R7{2=h$t vl AJp2%d胱$/ܿ|;@vX 8^l2lٺɠ/Ldm&))M LL?Dq%rʷ~y{x{Ƈd~4x^/]}q2uY&e)X2فeHOnEmi,Up ī[B}vHaE.Vk.@Jq++D3뫭HeoEELl<](ɮ) řpEH"L8L8LK5OE_4\1u;QiSw'4:;Ẹ͝ %m;;;RgH1]M>w/woV4~b в4nYh$tH u,\e!AJq1bGS`O[ⴅGjIBĺQQi QݨHFbT6BuY-|fFBG0+|· 7+<0+<3+bNFh 1 !6\Rl K/\ ťm.)] \ \bhIBإؖ,uB##PK\ R҆1 !ђslK>vozr wOwUR'^. uSQSw*4: S8ͩ %uSSS-ߕ0!!Qh&FF &DbB6B ܄̄y1):}ղm9IVEY51CBh60_{*zOFG"4{2{2{FJAŶM5/!@ W;ꖗFBX^ $-,,gJd5ےM& 6CҦnJh$t S"t1%B)!AJpS"S"0S"d'chj& 6ֶhj4:K*tyI)i_R{I%]Lhjm BЋ`{ ‹]EH6܋̋H6]8lċ7'y^9Rf"Buw@hֶs;¹]\H]ܹ̹?`^c%>_~5^_usQiSw.4:s8͹ %msss\7BLwz* vH}(žm)i,-5m 6t3 vH}(žm)i싔43ON/I4CغؖhuB##PXuڬ R҆[XYi y<BkDg5fI2bb[9 y,̊Ŭmf)YYY1lcDi_R~ݾkBn?Mu)Y#QHɱۤd RRKHɑIx!c[PϿL[ ̻WDk"_̳-2FBݠB]d&H2O2Of2OvɏChj,=7wO7ϻomn_/=]\]۲˱Nh$K]; RDܝ̝? !G;UO[vMJ2ۋmXw&438͙ %e333|ё+qbr& 6WֶrRH_Y eEʊٙ'lb[|v8ׄ!2X;l /ǺנЮ/km^)½ȼ<L˔ )zg~5eK; "˱0h$ !vqb AJp!!2!)!Im3Ynw?&]Y(uáPiNfH06Cb36A6C6Cd64q&k&N[%˗_ gBtc{  c]<1H3ccc? ϐ|/BBc`{  c]<1H6cccX>"R[e|{7kjpvC8L  T ݐ Rp&q!!1a:GϤijˏnO7|9 Bt_  _H]/H3_H_H_|Jt&V; k£n3+!mbFBGS18 Ô%^%-vӼ2~Xn~):4h@hVu%GO.JNnSr$HiVq%'%'3%gJ)̓^6Ѫ_j4]uSiSt4:h:Mӑ %m30.,{MF1B=CB_ C8T͡R(勌[T XTYTff,AU̝~tMv@6U=$OݦBX8FUbT6JÔVUVUbV 1Kmһcgw;xv Yt D϶0i/y:Ţ'uYE)Yė= ,{[?! GO-Rzw{F5RO7{KS}݃A(V>'|4LI`h.3&5L[^`$K Dnlgm˖q( Jm)-,,'t ѧ_)tM@ֶdi;[ J]mi>JJ|{pn><5}= },> w/c48/l; Ì(ox3C{ܡwfCի@*>FzTǯzkd}Qw)e|ywW >TeaO{&涶燷׻ǻonWҫ+j56eW=Vt8 .pfL Q>1h\b/ĶԪ? R[f.r=aqn޿ jH*ĺ )bA# !pfP Q2V KJ 8Π~۸< ۋMiV]$Kݿt)!JН;_Wt M7s[.!ª9 "qоO]z}uK Q҅=rK~a-]rrܮ w.`A>t鱻.%DI`g7qJKR2%Ocx87eDf[e$SAS.S()C3˯4e&F7-Pk~Att#P5]s.#zzJ] RqWZ ]rX-Hr_ܐqVtt{aZ҅ŷ%K)RBtIW.L.^_n 7 E^bxpywitń>Jc @ruM! -8#׊8Tb$Un孢a%rmA9V 7K͸P\4P /XqsaerjׄRcWk̅(<5^]΃r.6yc776؊Ks7$]ۻټؐV@uGe;o$8X)`1/V]j=3E |zF\oO.M[͊~S%͖rzԨU7jw!jw9N`CRԺ]jj3JEҝ|YnŢL kL76bn]1E^L7](pG6߸q T akEO6=Aut)!J]#[Ըhrd&G!UަDGt8h.e|L݊.DIE|d;oL|t|nKQ7ѥ!Hi/[6=:5Ab̼?ӥ(kl'}bv4$ۂ|nKkhPK`pNi5I-`]jI rNi0PЗU jRf:u[<92o>_ߠ ֻi O*!]@l8h9. }~j?]@t90PЗ t) 18R0з)j'kh0U9_ktWZpř O~ `LL81PkJXRɊ$n%{UB׊$"եv.<(I^r/+H_-m?旻M$PVxuض2`Au_ )!J^+ƒ_e>dyȖUSQUK )c`cF9~#Ȥ^3܅s*2$ iإZ~1sZoȊ/0ّQ_$:v%w.|K QW sKaQ'3 §0VWO8\yAZѽuѝ$&:Yl&(PlqE:[SYG6e:.Iq#[ &IZߒ,l%2D&Hjȸ$t F;=^X374Q4<e :ؒ*ﲈ" KQ""#XN )678M,{u5R H+Z\iRB K9r#]mUUewW}.k[UJ.|Uq`UqlUqvs=W>7X]<_9/"qб/TvEew5.%DI;2W}2.mV9|5vsGME=:(BQw]uWSD) JpIIeBM܍1#}[k7Wk#Sg*zu3=8~}aׄwҔ ~ ƙ]tk9~xtyZMN5ܐ,t"^]%:z羦(ssϢ,1Ĵ)ӠڹZO O5.@=_Ec_羋zk.DI{{R%+ mi3 ttR^C%]:R(徦/R@tJJw.S.y^E,VEx 9 t8¸"0N =ƽgtcإq4tKyjj=]4<_!t%:Ew  Q҅={Ow4c.Vb5.AǾ.1]-!J1]_t rUˤK[iUdU4RgϹNO]gR%PEvDN "=iSZ`l0汵0Oz&Orj{5^=8.q$:EuZ?%Dq ㊸O^s2Z-d̕'q36bQu.)MؐD3mBW]Vyny-[|n博~35Za%%3BKfFbmKӐ7e9|-2g-7p/13Rj!elA@,8`o\L QiDB`ۅD %jx VC` HtSA{k2]J. vH%241_\9auq,{?H3oer3%D>9e~I%Kviy[Ռͩ0?:e.R_W>ԍ [oO`(ka_[!\\T]+6Ax~ے"Ú =e:ޗvʛsP fWDT#h^7g -A~n֪A"]Ye 5 rH-"qбw]48{. nA i,5Ѭ V`FDP,]KyfR[}3}ޯ0 xa[>7B(聦X:_|k,\K /j*o61ŝuͪ>4dh2ߚD ޭ0HR,wr0rFB#ک1;wB"5-@_W^dJp3|2d 8/X"qA/R-r&%D~WO#5./+!]ؿAǾP;[|k2]J.\WOctqڮӠ;]v`hxP tǒ.Bq%] 2.F xK:6×*eV1Ws<4ؚ;<4TM"KHt" Hlo\N QrDT6wF.Zvc~lMOD*!]IdI}a ]L"bYХ(M"D$2xN_~x?{_;#q6t,pp_LoN["T㋯V#zX^-QŶEܷV9.{PP]=Y\]r .8Ӏ7dxss#5Ht2]T{o\fO QԽr;3jbe?67N kA}q%]Iep= 9W!/nOM 7Nؠ.bԡ[+RBt'U7F束HIόm.]4<_h t%]:AC ÷VR@t1U7B?=eet鷺\akx\-@X,@ HSX:1|k2]JX-@o.a.@RИ6/ps;_T 456 9~:C·V.(IÍ@boKҸU՟}|4i>N<+Kݙ`izsx{8Ӽg4OM]bSi$85*n7&$@rYo0fI #&f4ngǁk*x8 ,"qб/>ꮼr,%DIQWN#ti~l`[~~Wwor91& ({ հ eKHd}!(Pe”Ke$aeK0r \ܱm~ox||8jV@uaȧHYG⠳ T+-SBġ!]y7Bq EusN索 C>. 䳠A>tU.%DI@+VKKHgȡ̶9P14hO4d ,"qaSzD{|:;SJ)4@_^\0%OMKPmˊ/޴-L:ַ0 AbU`o\f(w\RNcN't6ꗥ61 T_|O2򠤐/mqSw)7G%R4w}yWMH3;3ĴY7'(u6,77 VCIyDBg,[K %uhЃ{~dѻate2N?mp1M; bSF"3` f㫷)AJЫ6%mgѦiyxǦH#pfI#Έ+h㚍*\H47m`L_5d*AJ2Q~ &N?c i5l|2;n~?^M-+8 $RHau(JHy0Ul7M3noփo17Ll# B{В.EsU(\zFE:n1mV/ 0dMP} BBWPNz菾wuBH)fLv:%7򕶟w6xd >*3KZ"3P]RgZB.AJp$# %sCl<Ě63wr{ҹBBg $uK6\iTHMdn&{@=yN@ nb@QﶰD47X'DEu16eRWnGw6i8=ّ.a5lX _"Bu )$+]]Z%Hqy #5Ðws mWX@gsrύTW B(c-AJp{ZȴnkM;ǁowO.Dj'$H$q}"}"Ѽ3økZ[e~S4ڒcU^F4RHEXW,P,S,$1XYW5Hc3Y)tEHm:)uttn7Q%Qm`E%UB\)$t "uQ.R.HDEEư C`<}i N~BSPFuB#ac "w,rf!A dYdYdYLiIK-Rߒ}E;M]H EZ6BEEfa$1gX[ 3-*!m꺅FBg-r" -2-2-+L 66~|M zIm1,CP`k B]4ܦQH6\@L`wU mV/wχǗ_D4tUo.CzHQdU]H"F"b6C"F"Ff"য়ͻ|!b\twVQ S*4:VhM %cVVV&2MKیM-ePƓ+!md@O]ɹ-,AJxramUH]mwYv!0W7`tǍ5:E8w綸)č3BލCG6×Ǘ9mi  !^(q=$N=J9(ĹK8E%HI% JYxvF%ngK'QGyPs=j9(ƹK8E%HI5 jYxz@v `yPP|~84>^]nK:}խY[R0*HY 38 EߚdJHx{Xxyz@fmF/wSBM- ʫ̨s#U($t:C:C[XYtᕞPy`a!mI|͌z{84wntMŘ *cH@ [GJHI `?bqڣt߇ } }U&Թ*m:M64<i3,fBLLe+M2e2/΍T)/ʿ]ʿmc RR@x쫄2m{/LYF .*H5 ~Х~= %kxPX1EVt׷H4[,3"΍Ti(> ]> mQd R҆W}@է׀vzL2҄6/w_^߁cSbtOa丂Rw{QeaReah^dUPeal1HL_>ڰ< >øq;ͅBBgs5ts54ƍHI~jw7`wq0b`g [̣곇A vD!(EPw Ơ)hyP؃gA)1ڼOk o>|?r/ϟǻ+i͗헻/w'?Xr5CceWוEg,.eX %x`كghaMRv/"OgkU^ĥ-TTkunJ̈́)Vߚ?{J}HAW,V,CWaH'P?H-$PL]HW|\g0?`Z&&`h|>>_ͧ[ 1~]΍Tok2]P %@% xC n:X [xK!@g΍Ti(e1 )iCb#شyKoUY aB.sj$t t9M)AJp03f3/e$NhK.iwC3g20nC2vj$t tQ;M)AJp0szwiXC'e?Me]Bg2dK]HB"t6SlBBaBwi:`x-f+1 !n=P-.cbFE'CM1ԴdC C CLMCTzݗ)(ȣ[ =E+ˢ B5]dQ&J@\5@5LM6 y\IfH~zy^Ea_Cuu~eSM5:1nj覦M7 %njnjn:%JHVWp|ؒ_ E-^f =2X]]p{jTt tQZM*AJq05y[pa`D[lQzQVmYf^1uVg_h$4[|oH2Bc<L.BLj:a3ĩnlBF&B"6!L\@LK+)zNvm>ieA79}=\k.]E-\$AE<y..%Kit˯?M\]=y~>+a",>ۺ(on!.m$HpQQ2QcdN6l y)eXbu.l뺘FB'l]̶bd,,e0mO_>Ϯy=:nBxpo\AISk$t7m{c R-Lamd~~q} vHnG#3PvlݎmH6|cnDz.ѵ-O›ǟNoܢg_CEJW ꢙFB'l̶fd,,tȚ#ֱ1׽u[ 2*!kꂘFB'lA̶ bd ,,g`el36 !@g(UCe0@!.2m$HI.Y Y&<3|$6w~tR>ޝo[7 0WC "캄][YÔAf̎'ige 6?b} Doj^CtP3B6.fl0%}xفp+~a}i|{zy?N}>30yy[coô_^w|Wq2q=O>_L =68 ɱ WFS ,r({.B34@eX >_>_||2px]<.7`J:7R#AF ;e 40JQB 1۝͉fmy]<>>|xWiy?`X*GH6$\R.vQ)!Jp  )\0>'`@TTt_ipnF{Q.t)j;w%UxǨM̮ǏmEv|?~O?~:jlXi\,ԯ%΍T#pй(꽅.BM_Ч(ëP-"}Xٞ7AosͶ9E fǠZUFǹd_{]=7 z֓&SvLbDz~]o" UƹU$:E'ߥƓimd)!J OTx9;>;tmKlHBl HtNKe'_RBtu<3w9υ:Y`o<o>=?ﯾebilXm\·"['pD}$-Se喉kGzTk-8VL2CeAvƱ4z+cݗUmߎ*z'<V EA@.ecKrqApїt۷֑s{=^m췚E x2  48'.|ڂGDI$~2|yYmA}W ^ƶ̰džd)* rW@C )"D}-Δd s{0;$ wwGx(68M,Oˮ 4M$:EoߥⷯiRB4= Ov\oJozd}S|g\R$vk xf9ip2`ݍb;C 6ۮ#.aW #į- ~:Ep !6Ϫ+/"I@aA}Ep]ExgK Q҅G"Lb;`6YsaiUXE⠯"jХxK QxTeu%]׺ ϟKl#ُEIA^C@?$ ,I#p(|]2ji 42o4.D1u ę,H@^CZ?$ >[3PԺuղ.)!Jp(ˢ.iMb绍 ۤ61~*4x<|.f,8oers\z;>g9rn,9,>1JOoh%2cM՗W@jO/"'y*Z:EW]iZ@1p |A7G]֝Xp| X`U,t7q{7ׁ%"]-X %<@yƒZ5mZT<./r:^Ec_D](Et) J(QnWDs"J!+ U6S|_EpmP6z/ uT {Wl\>۪UV-)=L;,yX}yԬ:0A8XvWߩYBKp-;Jc`?nljhx8x/"pб/W]U] .%a,V83:|i^8|K;3ZYg F#6ԎhEw2.Oh8 P$9϶ܹRY jE Y\*݁ ۂAbunCmu{P QrnX݆bu[S8ʅ~ @QqQya^41|}Kˇ?7XU P.WVCr_Z(@i.ChPVWYX*w& nS#˹tO򩑯|m` M"m&48u OoؿOԨ"qбOY:^[L .>tI.ɹtnˆu[5>S#UtsA[VR@ta[G.iM6'RIJxK\f˷ לr,ֹ +tzpqXb*`y5;x`^[a\$_"dAGQ%C6+xCTtwF ~j60d|MĈ(YipIk+u2'Mh[ܹ0TC<2w!#@?znpF3!X^cKtBMABk+~ix(Li>}&sّ 3k=7M8W,+ѤDAG4*r&K<>}ibjΤ\ m~o~>|^HhpFU5S#%A'2Ҳ,!J0cI!L6qΟs,-8OT"pБY:H̯4($G,\$$Fw:Ț_@48a5Axe"ߞFEJz)xuMYe%q2~`IWK) :ѹe׹˼,JjҐff+״HV05"2̒"emvYP((B˻>R)ʻ ~ܹp g^oSSPN 9 B%:K`[Yҥ(B9F[F VA &1ݗxj xziErfvѝV.F`&o=C26@-AAvȀqqHwL-N%Hy1ڜrN;;oZinpˇS57\OSفj=v%y: OG]G䡦 cqfvfuc3mvW *+H0 "v\cN;wEagfӗ?G|_呝H!SR]ck;KG Aܱ >L/ǐlͻzjj=m@gC^e_F!3Pl]-k@HIGv`y1} 7X5m@g$NְCI@O.k'%HI.Q: Q:*Q5pf =56>Nbڬt׵DBmzv}m6%Hy"]1iӴ=/7pwՄATo=-W9EFQHB]dK&[J0  v9F6qgT"փUѹ4:%虾Mϔ %遢院iOu ۼM Uѹ*m:@TM %mDDD5?`zAh$W.ƤL 1ncjו*NBU.ZoӪ$HVyVyVYِCɡҦ.9h$t w| AJp3azM4g,~SKX.C.0h$t w| AJp3N餖1 }f}C;M]`H "06AgnRqŸls3[, W@CC "D컄}[X|!bBĞ1sob#U W#ڄ [6.xE *m1"Cz ` Hz Y#3RĐCrh!KF<@ 9 nZc4jZ~>MuV}^J7K.sz `!ȥzY#RDCsh0KK<@9Cth=56쳅km,6B,ϿHS7)Ќ㧏TncNyh[SSh &֙C]H&Ba" \m0001=%fF}e s9׷_;-dUKlɡ.Qh$t. "t(BD!AJq""М&y4qA`ْ[25uP(4:FhM %mFFF1= ,)FM-|Š cbA9 EV.jEhS+$HI VVVLHfm4$O6m*ڰAXXgXuB#sQ| RΎh|"LaJSTPUG|ZT'.Xc!cl;qI@#2F d5? N?g~Neũ >cbSy+ B(cr!AJpbHSvg mڜuO@[ S`2,[T" DB&Eu_[i!P RFzx ],~iFWM-+>XZa뢗FB̅5v6K+F zL8ȶy$fPuU$P]H\rE. R]#F&w9ms3W M-+{5J/ FBи.ئqI@\52kz@iɝkH墴[,=-* Bcl!AJqbd|9~g >CҦ.Vh$t b"Vmb)iŊ#+i5;am,Mٔ4}bE;ͅ BccdR҆#+F&VL)vq l8!@g(QTC% @!Q]$M %mD1bdvMv}D;M]H Eۄ R҆ #&F&L[#9 }jw~:zŪ-ffQ:BA' A,Em)   1?ո 63[ݽ9?2D; 7FBP$bE"%HHDHDPM@LͽPOd!JqKtrBYNCK]bɱ0)cĒ#%مklʵHεn-C8.rǒ5:E,9v%ǶX) cĒ#%OHͷ\%2-fUkyxZ`H!bQzRzh\H)R(U=(Zvk%-fU}bFB̅M ňĈĈfzv@mǫ/OW_h A~cb9eB!C.2Dl!$HI.CD CD&C.ư`/]u λ2FBg!b" !"!"!Fom rWv6`l.CXX]uAB#sQ  R  觭մl]Tnq+CpXXVu1B#_ RRcͭ)?b_YWٗF\쟿}3y_Zdm1.Cz>n7WoAo-eT:Q\FBcP'έ4GU':ԉBHf[n$o-C;7]?}EPOKg }պ^i$t& *wQrz%AJp**3*͗ђmBz_+^8+$tqrkLGzkL.93`Rb17kV,Yi${[hVf4+ R.6\@Lf.O'.ηYL[F o TŦH6M0ι˴ bC8Gzaajh36im66@e6ueS#_B]ܦlJrffff)OZ})?b%wMAX[[D_mޙRB\G N+MTW0W0۳Kg\"/6'4_?g_?O/gMKZNV5+L,Kgy.Ư W|\2@24λ6|[xk&ٿANC͸EkKt vmE0^@(b bk cN5pE3U~y>>^:hlXZBe(WChx!.H ”%c@l@lqrkރޤ{`,߃nAА&-3|}C)vjxjx ֹ|^ќ)p6t8`_f) %\^3lcA63x`ÇOՄ8cqH8ĺ&0DAg8J.G S;JQ(?Hp0p&3Y[OXG3w)QiЯ.8$ 9)˕;S @(YCzVƷ Ѩ_FubGc__M_KNQ҅_ "⑍ęےQvT@^_V%7!H~_ԷPSSe{'[[a GɯJ~-^}5Ns+W.7^ >\- ܆Ml7Ԝopn99:ױfJ5 t?d_GL.~~p/BGs9v4/"qбO]zϭ\K Q҅4]˘SV;<?\ t'arD8#=" V.s(9B# G#p$&wE"9r^~~/,4]}6SCCa6^ 8pm|NM QS3m .04&vS3 Q*z4tB.T N)XC;r5 U4m~wzc#JMh3fI^?$1΂-C;r94u,+XfsyziyVhh.!z W\RH贸K=s+ \ %7lxò*6kJIi>C]; -imzxέ4F>#Mhm;H)_NIѴAuBVi%m:MJmHIiFf%eLe͞F-  64K$t(mQh R҆Ǣ=E&Lr s  0>\iSk$t!mb R҆Lj={*%gioii 8Nm47RBBg.b) %mx؃Xg al@Miph 8t37RBBg.c< %mx؃gc;Κh?%?6sUFjH "xC[X <|@8vZ43㏦ +V;jXm)a.հL֒6jXT2;Oy6K03-& PU ꚃFBMt jUTTR;6m)(<nŸ_mBns90tp{|߾ j cU)FtRHJDD6%BtJDJD`J4-v-5e*t9%% EU))FQH C":6ACC`4s̎m))|ٮl.P`G뒨Ff`,$ѱ$:I%H#Dqb>yi{qIuUiS׶4:5vѶ6mK a2Q~q'}V;M]H E4, R҆kX#аFaMHn*66[<3԰*!mFBgа.ئaI6\52 kz@;?'#Ix!@uuA6 I{T6K2f`p?iQƎķӭɹմWJVk F#_BHVcd%AՆKV#F&YyܸzF~q'} :OXW4:B5vQ6J )T7-j?͓ؖ|}4uٺ-dP xŌ M*3H/ BU cۦF|TnjNc$!fF- B;u..'h$t 9a"'mr) #LIa5r<]*6[.VǺ/0) d WF$LIc/wǧM6n1CpLƱ"h$lc".*BlS$HAUTTMv4~u-bPCҦ2h$t !vQb AJp!!2!Wc2~и >CҦ2h$t !vQb AJp!!2!dn\fm?E!b=P}t>h$tJ !vQb AJq!!2az+n9F>~)l(O0\J=($[= KBNU.E!@Uq v: U]Ŷ)W]E]EZIeG[]4nBbQVSW#45K5bK65B1VԈy7zIfmXF!Hu/uilBBhE%@kh&'YF?>ݯOWxH!b5 /A<)I q  DD]NG72yH'oWO_nS#h # u(ZSE5: (M %u(((:?`bh+#4nz&e7f7apFM acIk4%-C!i.Vj$HI.i% i%&iѻ<cbbDtrQf:CiW BJ]Ԧ_I2\J@JLccdmiŹ=<n%yϖ}::iX BJ]tԦcI>\J@JL|893z4|8z<aK!4[`б/EJm ) y^yݴ\? i|Et~`FBǿЯR*W$ ׯЯӯLq11NW)D;5uTר4:FhTM %WFFF]]q`Ί6W 3)CLjobM=q>@RF{HG{z84D̤] *P]H7R*W\xxxCJ]QsHp..#Wے_i't0P$L0&1wQ|ޜH j SwoW٪Fj|0 #`j;w%gwc+ iOn+!Y|A}a$r]D!gK Q҅ۈb;W~v4pg )P­F̴@Kf.QI|kȷ&/ VZ.Z ڑ$3ޑQ77O4:[(UCmA|.*lL)JpFxUDs{3_s=4[SwJm.@mt vlMh[,0D.Y BfK+^|ǡKg_Zi٦ujڹ?oլޝYO" }АGCix(mCO{ ?iɼNɬ)JJwJisɭ/unpgIJM,B0vj<_ݯoy?C- rb #T9?[ W_&v?_/5n=>ZKE>ڒEPШmV.Ө(y>< G9umMie3?ƫkF8d:4($G?#{ezDLaǦY/1XOT_ZXХJ[(dG.Ծ0\vkx܄0WC'üpEKVyA8v<5 d;B$GnsO[}G0?OT!pf*xmD0~> Gf>sF%:|MO^ tȖt8.r.%DIvyK&t}v#?4Yr{e]bqPdpI.m.%Z]Jmw&W!yל .{R}K<1W:}KH";X_[̚XdRk.=5<]Ū]$:Kt)!J0 fn:l,~R|}||9auh~jN-8A}m2gJ3L=}9cgFvfJvךEOae?713o!e|[PF tJgJ4L=}IXwt/gNiJ?M[94yXC5p@aP*$loYj5p^Rly  LƍZ֧eY?7A]uҦH κ./ZBa*AJp{(~11.Oz=3y_J ~nj=m@gébp4:5KnIR҆@]<-jޛOD˖r@P'rn [bm Rs3gΈ0_7Ӛ6[m.m@g`b`PH 6m 7Bx`Wm<%H.{ {}Z&Z ˧os+j&(UzP#a 3t?C[P \ @ ,Lha t^sS\3zP#3P蠡„ WBPBl9Cwpuqp?H6 B ]& %mXpNMqb+6m.7`-g«klj$tB q4tGC8*AJqu4u40utz@𻉰́kz]O U1AZՂ@ ףUjiU ZoHn@7=mv ՊUxFQH pLD8)iÓ 09m& D\̝uPFBB ] R(w gJWypw6;8C]H4rW"w6KrWrW`r ͏Is^+A>CMҦci$t ݚ$#"];Ve$rؐk&ر\VUꢝү?̮#18)A:c6K>>g>Rʑei 7׷>^~Kc&6Cai$t w|%AJp3+3ɏ4mUˮ!Ҭ Bx X ] ,f`I4?Ff YǬBzU dQH)l,m6)Ym,l,lynkoA}f֤ !TJ/BHصxY˒ f3H´ O`:zhtU:9U74zy +t1B%AJNq++0k4~sJ-V50w?K~&Q!j n+XXߴk$TwXaR,dWZ,dњii2ymx &;:p; e g4tqFC3*Ay;89s~܌ZX<}[vpzMCJW ƖFB/Hጆ.hh3$H"fl~f cbK$p[qjk9oBiNTC ^]܉NH7ܝ̝StgM 8ƒG!W0&Bc"4qHInL`LƉVH֣lo({eGCݎHvDbG6;BdvDvD`v2mI?}|׃m$M!@glH,K!+P! R҆V!=Y/ijV!Eu%,i.TTH(,Œ&HInI`I^tq9hjGDuI@gA,+PFB@A.Dh $HIAAAx3X?'| Pñ>a RÑ9l$mK iD!>e(WCԅb^B(]&K5\(@(L(an m}#*_a$!*QWCa{.plS%HGG';_R&j >CuҦk$ p6uXppg0th7X=>@~՗ !^=P,.h`pTBE/N!.qlW_f*8#BvEpF; bPLm)g$PLC|}L>Quۙ5_Pz6uB#W*.^UH6ܫW11q43qRf5_P6u?C#W3.~gH6Ϙ11?iY&̵~?ZY,߶W[Sg#JO FBGpL] %1cbGd>Vg]~9lo^o?{z[SqBԽF=$NH5(1$76&`lL?&Y. ݛ0qw?|!Pp& Ѫ ]JG~ ~r|iC8~s9 c$70kK5;rܚd3@ ^SШ F8~iטn!Z_٭I6Cڨ`[ MkK+  %mqJӆYdvaZlu$|lJ^C!AJӟpcf Ӧ-:;[UtOȼ$zlJ{qMd %Y8y`"s ֏3R#DU!@g,2/F!W8gr&2K63094MڢG*s*z&њ#e%c#uI$z!de R;pH&+m~7yϵW}ΩnMb}Ʋ걑*mzbAVh#@J0YM!+_woܩ1wyic6_z}ot&ߘSLsmطS4+/OfV%% 9Q[u`fR ع"\mfgx́+6hnDZDK&w&Y6M̂k6NRCUeZ{ge^"Q$j]Mqr_YyPiHӺ&;Mt5e!v'R2}466 GISjݕ@{|9:E֎D=~%;OpFX2Kb]7J#ekCn b9SsM4uHDӃ9V.3('ʜ+=00 1 䄩-9 ק~˰ܙn{xx=K-+25Jx=0X$IWdQe2%h+M&Gf+*!S[0.6'VCOO\O Q҇> }O:>S @EO+܋jY΍"qб]zܧV.ӥ(Bu+M@2 y6ۂMti*x0XAbgt8ǂ.=-?r.%DIfK^^(!~i! = PۺQs#=^T{jI+@JP{wJ&1ژXʱ%Ơ B;mE5FQH%(ImN)yO˟#g\]tt6svB;M`'($ P] h(6[ X Z =?@ߖzk͚}B;[A!W0Bc!4  3DKdS_zt7jW 5@R :,^B*]h2:\,@,L,6N[yL/B<63+!m꒰FB@! .ph%HI.  & 1y K/W%FmWCb^B#]4ЦK9\%@%L%?2Ale/7W&@ gYm.saQH\6]m Gv8/m@mC'9\y?ߖn87ԶQPA皺۶0BC! kpDLߖhkD' @gh+TCm^X]f,H6ZZZ 3T0mkB3*!mFB@a0.Ch3$HIn1`1j1p3m6 ŷ4m@gh1TC\z !tB @Jp!!P!3nfe6m nuPsdPHE(Ld&)MLL;pMxJ\~MT}dXuA#aW &Cb26AdddvcMMԚ MeaX74z !v1b AJp!!2!7o&?#En  ex!+P  7"0"}1L(m" /X63ȚF!W0b!} 7"0"$cLy;17{׾>~4,UOk\ ;*_%{Nx̓ % esR[Q&>c9yY+d^BN]&'K6\N@NLN`vxxȧOXHu确\O]WH(tEWm)utte76xJYvyfAu\yS5z a9vc,AJpa9a92aنN!1ޘUÇb1Nj&!QRsћkQSαdg RΑv QB[=Sa{7y[gi 4`=PҨAk$tA6 Z4ttd3 Ѩ_~0B j6Ak$ BN]4ԦAK6k hЉiΤl=֔u]iSנ5z :uѠS-AJp : :1 ڹVmӛ|=Oȳ&y aT*=º꣑4^Qt)@hT RFyB8T;6%Owws&| 1{zpک{ #u0R!Ai{ xVԉ .i-|z>ޏ|:|WFhM#JO .TQH(HutHI"h$h$h4LMOD s4m=r\ZuY#_||stZXW8hY\5#^K]L6IJKKl>ML ǧpքW!b= [^Mu3L#0R3,a703LWa{4)(!^bkYITw4:_ %Q H=Ú3}x~YrF!K8rA1C;]`ЖrWۿ~9rq?rvR}`tY9Q? c%Or aM}~貸st~DB@ᇦ.~hj=B)i!m;rLWh;fՙ3eqj$ L:uC6?T:?tb~h)ZCҦnVj$ fŬJ R҆0+'fVHqㇹ|%M[E??/Wy1D%(U:U BBX0=ĻS+ < CŻ+0&Nol"gƶp[O5bPw/7uE#8Rt9R۴/ ?Vۀc S_*~cXŶXtlRY, |[ }Vڬn R>={bV?[z"Ķdq3s96t+!sζFB/BlY+  %s=g{bζwκ=ŭY,uTS4z /{eOm^)ý x71L8=j_M۸&V >XT_k$ ٞ w'lOtq7>ߗ``l_Wϟwz<{f^0X5taͬ+S8Srj\3 Nܱc95stcfmNKnO%hT{]Vz T.5z- r]Nmޥ) Ľ x. l>W6 Czi(\<7RBBSWAS+  ^fJm͟j:-\|ߟ?wC&P g[ ùԃ>C-A R``GԊmYgM~}f;MH0mzxVZhS J0a {til. ύTY b GO4H,fG|ʏLli ߽>N\eOt1D;ej$ ]Q RG3h揆8bT~1&>csbQonJ^ХfNH6J ̜ LJ3'B @gȋ~s#uH$ bl,mY|l%r^=M:mJ?n7~w? _QDZSbÀW͋J΍TЋRmUm\5 I|lٲUS )BK?%ޮʨӚ(!Dg^V:^uT#ρХJ+ h)j@<|XjZ/M]yH-]l}mwIr. ]ck2-_xe@rLks^A 'Ůxs:fKrsu΁YM0M%¬a4[hWPCu}<$O6s]$Of?0n-AVǻ"К !{J/ vFBEADP6;]DPfv@fN5s  ~H#ЫP8CGthsD%HI#:@8iKY#IBO+W> tQ}L#AJ_>>>1i`sjKbњCJW ꊏFB/H.iS|$H"BYd6TjwyjHM0 /xɼ,5%Ns ,D5IԱKu-$y'2_#Ϡ :ƒy<?ߏf~A7Kt??>O2a~sFF跎::1+jlS_Y? nc\e⟚Jkl%4. Rb{rkS~%~ %')^D<#[fW&8P8}b@qֳQ%98A$&R:!C鄷vSL𽂫&. BF(-d[/Zt˗=OC=iv~24-{=.7/o]ݽo0YʁSgXtL v"f \﹕wn?uEO0naykB,owE!/V4'ŞE{4Hk,*=7RA)8o9$ u[4i66~@O?VFjt8ۂ.=V.ӥ(BW.%1HX]V<<_YEc xe%]FdJD&y?a|}Ypۦj3h[gpբBɢ`J[]<_=s*rFBi+n3R[:#׻c!QB0=bNA-Ƃ7 b㩕$Daғ0d6%9us1i`8Tm8VH-\]TY-wx* Tc!ԤcxXv˚gFAuaF%jK($ lT'j 64DiBfM:ma6ڬm@=B[>-VF"Ӿ/U=^Y:]ZCxo(j=7RDB@,hcGuj6%HIҴa{1Oj`ئ-w:?0dLWwCO^C/GPV}:^Tun ^T0J JAtu<DWhfg#L_Ω!i>H6 SAS+  %mxJӆx)mZҮL2/||g&f #ODzgT'4(za {bbOLm) 'ȏ/ [r!Ȝa 91u1'6sB̉6΅moSi}yX9rt+্ƈCmNkNw.¦|tJ6<*]yh(p[+ w)&Ov+5y̓sSf6m1/}]=>=N}wW}울$~`sQ\rnJ/>C<@/R>9L`ȟvdU[\w?cۋy{ {4si$/"pNyk2$H9M:wG<>iʼMՏwoazz|՟,2k(]YV[S2J;J JQ\XW2*mhym$_n:YufҦH(6Cжٔ %mfśm6Gm܌O}DiuuwϏ>>=n?7 ?kb<\U:S_i$R ˂hh[I?|A4@DO.HoYuWiS4zC^ީ6(%50/o)懢O럶w?]>ȮqfMBսn^@u7O#"Zi!P RyW@agG+CvtΚ$ħ ͼ tȚ P  < R!@yLF6’fMX}f^;MH(jH]jHmf)ikH̼q.'U7)qʬi8_TpC~Q?zR?zhsc$HI^?zJј!L-t}s3ʶj?owxۖ3Rh!F)/*khe Ԣځ5kg{ {^&:d6i$ !3]2I6;d8d9d!NIe ^/|?np;g1C ?Zz\Qom.8 ba8 %͸aaÑ`x3LlߖrxB;Y܅8`cQrwnN%^0] hmJ00s9iK:hjlM|ƢH; aߐ %waaM[5fM| C,/.,[5L-EE^tm)\^t@^tL^?;CN5YǦԷ vÖEwM H[af0 R6 3 3 @t6f5b!@g_T)vnJ^b'oMN^;yv83L_lK|eTY ֢HG $StyjƧ)yğZ< }j!؍v"/ncM ]eiSw4z WtqL+&AJpWW0ẆhR<^/[qᗚ횰3D; J' FB/Ea.m3@%HnZ`Zf&xݶ?<>-3D@P^ ]PfJG ?0dH-rCC [ЮHzn.-׶ݒ "on9݊֎mq觗۟jؚD4ħVɧj$>.Qmި)'ZZfV e\l["\~~~a8\kr5tG+!qFBA.msG%HIZZ掆iX$Ihr~ Z욘3ħ tȚ PxjۼP R{xyqҸ>L$4h-^]5UG .˚uMP#aW`,4&8i5hc _wq7s6O/13Y1otoN|k|o?eBK~̈́EkFۏkI[/flQXbW1]vyOxV/CBۡg;~'^c;|w_x6G8W]vy3(Czڡ}g9@I^K;ZjL[ڴe5;#$8dSSh%rD (Rxj9d|^S oL<ķVW";a12mIhhO/Q"ZED;0"oUm{iNY)w=5 Y`VC:jОO %N!KEB㓔$+MɤHw~"yrQ`}J7 q ^SgIZH$ !OkE*Dן>_n?ooIN?w䣢@GIi3Hb؂>>JE%}Hcc`ݏ|#uggǽioSKCO2 j t _p M(ýxOqָ9Y&~墪214*!eꆒB.f) 2T4S)$^!SS){,ȰRFa wa|#1 xxxĘ &<{.Km: 2FI ]Vm+0Jկ_VM,ej6 xjo1oHm%-zj^M]$&I7OOO۟%M[@(UwWOO5C 4o$F$x$x$Cq`M[eԏ/^91|uztLӏ,N!z,d꩑ZvO|{7 $7<0<1rdY<-yW<(yuݿ*HCX7^UXЍ}7$׍=Ѝ=э1nGx0m?4|{۬GC5"L 1Ew'yjF)хC8ɡ,޽1eFCۛs"] )hY8ԧ }1.SPhF>06},ϕR 'ycTN@TM ^”]LdJH<ܔĔ1_6JjqӒgE=D:LՔ@DbJ&SBbDD Dnѳ-r|* yv=pTwZ>@T ^šPo뭕%w5jnڲǿ;ձŔAtP)S4:E*uJ QRRJq:͌ E^`5M<_|?oyO/7;;:j}ܩE2uL Qr'SLai>?ۈ3y{sM- §{tH/CdФK2<:d~#25tӖOˣ?_\Ƀz'^L!WAp+B* k rB6]da$ KB Æ&cåadncS)#aR* k t itM4,1JpqqqԾI~bN߱ŔAt>\)SՇ5:@lĦI %eBlBlBB̫49\2{YfE=F*q :L]%V@*6X`**a*4X03k{?ϜԱŌAtP\CS:PlŦM(%cPlPlP?4y}|t+^=wOOZg aף]n-\T ^0]@HZ܁00ās^&\z;_UfΊASlXUAa#o v1l 1 Xn6X`6Xb6dOgwK HYtgϰ,g>BGl6 d ,,rqsXin9/_œ:c7TCT 7.~m$FI7X7X7+xc[#c?g-j̊D  xHH PĶHlDbQĖU0شE-O27 B$]DbVG`""%"qn>q-w73o3O]e;MsB%JG B/F!.m%FI .[ [";+iGrLTYQq9dLU1@&Xb኱% k87M9,} O?;60@ `HA/_EM(_ _K_i>Kb&2˂YPOGFrfY՗3 ͯe9ږ3ǖ3)qYHe5%&KTBT y.^k $FI88݌IA4i޼๰㑮_a>0=:b.!z(PRI@u)IpMN(ĝGqH&F?7mlԖk@"p<|`\??P}:͵?y{|x'[@QGN%69ӢRs#˗iE%dߥƳ@QBBǭҤ[\ΖjhtXYV(k(RW3%Ux!d !0{Mj/Sj.gJU:[,,J΍T"aЁ/.u}EyJPR=O*yg[~YRs9KbgQtnF|Q~w)?+bU *g26aBO[Iȿᯧ1K.GDK0рA΍TX"a1, ;KJ%nK€Yl^X-y{}-y~y}z>xUpuV}QDtn ^ SpFE%w6}Jsl⼂ap1pb)QEPeDF*t0ۂ.=V.ҥD(BwW.%)mY$tij~~CR?ERt8(:7RA8l1t9l1T}T)J8p18Li=Fޙm [ֹrGOf*!Yt, PE@t!pb1]rs,y-ܶ?wݫ86R@0WI}g@%(ι ]ι l;k$FI~]'Ohc\>16mbI?=ŚG(VyTy5zM 7tyC+1Jq77ؐ7kٶ`ъ5J BI.*phR%F#uK\rd6R 4e/'5a:_WCT` ~.Zph҂%FI粒M7-iܴN-֔At"\)SU5:&h¡I%e***/OM()?+CHo/)t9=xu<o>7<0~zھ<a~K$ni~͗9lqs|wi}A9 B;R3Hضrv.12&v}pwy}[]>[^XuH]%J_m( L`,>J^$kZ?|>^䇿}q#y9Dl)W|ZUM9 -rɖӊss%1ƉDl[i֔At1W)S54:5Xsɚ%e999CK lW^N]"{ tHA/,ŢM()MLHLSMeL[2k~>Ӳ8T0) tP<.$00M4wmlV_,ڮE#|&`t:c k7vvc+1Y{xxyX"vE<=ƾt׍]|J2׍׍׵ِ?ÄCoYt,(( t 7vpc۫: p#p#{['?sC;c{\j.nx"H Aa(uƣkRX^%sѳ-Pʣkh= ]UgWפpvcg769wv#pv#qv c ȶpu#lE[,VOuGB(8S#0ʽWp&LD)uԣkZ9طZwzU[ŶF9p***7tH/|V!>AߪZUJa[.Uj$Fiur**Y)lh xmY^*{ tH/E LMJ()ÕDܾiCזڱnEbӽ lHFC_,nRMjZH.|q&ōеEgw_n{cnE"}T4$K՘@TbL&cJbdTT"\p陘lv+1t*!e.BpR!5  wpq\-ZL`Qךxs+(4*!SBG0Rs!5 d 701rӴqɎז6n\V!>ch.TCT a..Bj2$FIn.$`.$m.<݇OI>#Yg~s3r> YޛK8K`/~ivmp}?Cl/dV >cUÉi *ܡJM('%%C k1Jh }݇|ĭAddZ@J],dI,JJ_RtqѢ^5uEQS_ü1iڒ|b& 0j$G8Mk**P$qrtΚ(P˪(JסxB.O(%wʃ'gO(?A?/<5e>=B>&Bg†]lHdCJ ōH HK~ #LE' { tH/HŎMv() I IK Iϻh&۲~03W]ɛ5LRw:7UgRנ&mo6y w'-p'-q'MqcR/ot]<#3g"؟\дURWp(m69d (-(-(M6saM[Lk+R0)4m=/JŨmoQ2[X%sqcH_1qEb=F̦:UiX-.0JpҲ$`G?ljkےMY݄t,iB0l6P w,p,qOYnbe2޲*i l]!.Ҟk$FAǥ==G=y.3abe" cEoY9Q@蹶NFI99Y8gW!>c9- 礁/<'srM()='<'G<'k'F"~N" CR*k t u],1JpغiW,MYt\)S5:캈I%eO7D2-V z{e\g';eJ s2BB!21g\f(e`d`Gd`yJ>|we)+>+  ®I% l}B+ž1T+!eBP]E5) WPQp,nk!OK*Ȑ*U%X^(요`QR+()!+i`/U~bVAtO\ RW:(M%Uw)rro w|~5'Ī_ځjp7 5xmj(zj)O˓t=)wE"}zp<$M]V@(ో<$ ׃GL\& |[搿|8<>|~}SOnoeGYOT[2\וaFm ewQ}2,0x0W=P=N4< o#燿}Ix@oBe3̅U[ ]H26*1d$ILL.NҝOw+8vܬ׳R@U(\0U%s0a$.Bn?'7joNOO2^X@ e|FʔSxF7W9H)/WDt,ƓB0|7O 7<0<1}8 6Eޫ\^CM}}h"¬ZLeN#N.4h$0ʇh42c"}_߃􍃍e=_5.5zƥb\&Rb37.=0.=1.]pf58+ħoLeNޱe.(#0YSfeqOI=O{c@mQR#s{;%[;~YNM] KPﭔ^!TA+@NoA}j ?jBU %5WPc*Ǔ*Ab_VysXrůq_^x)VjTJ'o`hdjB1(cM19rn\0`,3d&kOR|{nz'irRت"7}@Ms$ z%Ƃ:=|cM9xNPrnFnpgB،# ꑆ9UEN+!U*x_PǺ}mީR"TlbwFS-᷿;M/U~>o.R]Bcjtѫ3HtCAkS+R"t++M钛O`QBc5cUjY =J' mt06MX꩕)JPMĴ0ER-ERmG.TiNoQtFGTH#aK ZH$ _i$L8i3%}!#OOϻK}AT<PjWG:z# ^Q꩕<*Jфy4MynH#ex("« Pծ = <:vPZHQIQ )|'>Dm9_:U\?}_w.'6aս1J7 y؅9mz)L1S+_ion0=V[awmzq xP]%j p0X C|Q@ۂ/=BV.E`|+Kb7%OjPb|s9)cxQqnF!.Bqh%FIMȦ~ip9)cyxQqnF!.qhFI. "T,-jJM6K8Mj X*^TornF^B,]$K6\.@.D.{''X^>mqVMT Njs#5( Bq"&Xbqq ⱉC[CʓrtUS=ƢH2 B6]d$K2\8@8D86iěv7u6g=p9#,oMŋbs#U[C_ơ`cQ҅KHƁHvôy[$Au娪 LX ^Uj:I%M"""l>H5rTUSSI/|EUWaϡH7]CWbQՁnc95PMl

+7sډi4M" *<XqQ3;88q̟!c[ڳn"6 *!oBAa.Al $FnD`Di.ʒo(+ž1t *!eBp b 6 w "p "q ,ic$/W>!>cTCԳ 5]\/%ekkkwn~Mo3B9:s89%mssY|/@i"b0?+*j t3R7tyoh%F ]s=m,Bs|qEw܈W/+@\8P_W8(@E@E 7s&mЦΊ'ħ{eXz:Nm%e?ޭ9L}c&=q͈5$%JK9Cj_h #jן̪AGF$#zz0w/4'LspѳؖfZ;n;t*:P}5vq&Jb8P.a yҟɳ# 9g[ʡN. bCbCyFP}`>%ӸqG_haVjaj [Xc sl0%F9p sH,9xmϟ7Xvt{Y S5359v13&3Sbf̑~ڸك!M[sWqGV]Q- FG*ŨJMF(8QQQm6mőҠMԎ$(ħ[=mIT4GxTɣ%eGGG5=?xmIЛ0Vt nOO{TQi *uRG%1Jp**aØϻ}dk;^ҥCu5HqE劢i5,1 hW d5 Wtܑۚ2jkj [ؚlMQ2LL֜?N?;2+]:ȃB|ܖMUKS_X,MQR[ XI[B&sf %ZY˘!Ǔ>7YxJ],ųi( 3q'[C.L_|]ImMR:p4:fc0&Qbwp+?eI:<љv6!>b0VCK) 1uqS[Q4QR; 8E'\j l2;(iBLz1 \Jh]nZQf-Es R #&;ȕ0a3R,|wNmF9p9908st亠Ԗlv$3!>b(TCT va.ajK$FIn&`&"?LW.c-xz8޾=<_~icAt񄴭&gOH ;L]6! 1;L;LlBs5ldv/!> tD\ 5 s07YLVaVa&VaaF.o̎QS6C()mQ@.6bkmeF'b)ϟ޴Mrzww|yJ̎.D*Pr[6`-NUsӘWs97vݜݜ % oӰ# CRj7k 9ws,1Jp999Ljqp6-V2;;n:4+mܩ}D%w8=?gLLM;n14+!e&B0s17 73039yy~4C ԯnk݅tӴ-NBp) )1Jp))iz~0-{qdǰ&bki[47W% wa-.Rn$Fn-e`-eb-E{f3TnYO/?ٷ׫/<;n;6%.sD@(LDM&(M Lqv> }:]nRɣ.iGbӭ¶j~ێB0r!ݷ#0Jp!!!NS0 _2H[B|AؖUA_8QR;88!;9-ӎ%ħM|,o(~MrE`Q <9x rl1zUL;oB|XX}j MA)%e;JS1per[2yG-o:LU@hۂ2=S)#0JPw QBӧI)d׻_>_SW~y>bE͵ū# [E69R+ӠrzHėLb+M0"ΩxĻziڝ?_?TyG Bq8UX/!_NQ 4qBq 9aܯHg^&ILm \T@Uo }d OBu.^wvү@'*.w.w05~|zytԘԼsůۣӧw2a6`ڹ60 p"¦{6R * -\Eu$k)5cAǼ/Cb[lb֣bL(*!xÎOS2}a(mh]YK7)vEoӣOg-P?9bdٲGk+vf@QqO2*E+*[N$#/G _Km| pNo[on4G z,2>,?+e7|.@iVZ=v!C-y5y ,C^yߠ|t =}sdGL-\vd)VpwtwJՄ&Bۉ{XA;}S ,IՎ?1aeͶ q Ev!n+ޅo {^^};8R DqvM6c-vkn7M7a@Ne%T0hde>yI ){SS6 1_31U:ZTQA%U$ EwxYPD(C6l|"T6#0Zr%wZ~GC]S7@?}EwnuOx'6cs[iY jtزʦ\RE _c]αxnR.R"TX<8!LY-wJ( ƧۋmPɂ,rscrI$ ? YabxFp)M ​r.ˍ()xp/-ex7eec\[qکGՑLA UGhisK3Dޯ+8pU80!'tPp>1M&3x}Q["ɧREK> H u|\EJPRK>H>.d?0ԟ~~fhtSe]Nu-bPŶQ@(b9U,%T !yQ]~9ܾ?\__,O5X-."aoi!.RHd)qKH.c4Ms)-9jڶ?Rqe5ĩʶRE ҂* UlUJr\T*P%:o㴕cT9,5Y>@t8tĂ,%*$$܀2!]Ddi}ȟoNOc-m @[r5.]|?R_$\$>R"t9 rh*ɍ!;RS]4u0g?$D?$ E8u GJ8%Bp ,ǘ![XNi8qß>??W.Ï8v5}vR$͗ zm\."a/KŸt/%Bn\:`\:O2q*_rz柲zVO@mF6e =$)8h6bSM`L QR۔ؔniSMS^{NB H'j hW !QhRޮ)iT?Tx21N1l;f)hpȖѶ"–4]lIS%?HR4ᶤ&f> gbdRm<>tؚV7hkrA v|aM.֤XL)JpkkҌdl>d1nzX96-MlcAUbP]4.G FKF7Ls\H7x[puwosK~];_4a-z`r[hrA ~S t1(MŠ LP-ܠ44&g\1fL1%asŚ0n3v劍v0hΓ< LP;O8O&c!Č+M=oݲ VTx}ma}U$ :;يAddL*m?ˣQ%aL7MBÖoW0hvb7يd ,,SU 7xU:Z|%@AʁaÆ@h2_Io%ӭLQyB[E K [ab+ [a `+ P%p)m i$(ڬ'5m4Rr~~8usz YqVԚ+->ܑ֚0kXhͦl*ZwJZZ;a>y>ӘBt=@iOtrzgzY g 5\F Cc9j箽ǧOl=.UtBC0Q a<|>]+Axw`w)ׂ̝m |s<î'n&4*!?ɷW= 0\MBj9p[2pCE[|5q*^_Fa !Gl]CU~0U ٯYߠ| (bS0$i*kf~=ۯ ]khp0U IrXKǂ%=bX(iBSX4M),rmmѮ?zWa$jmſ]O)/wϧh^MCw)|orRioX.}˶eBKZ+MK2mƃ llbR-lPZ״`u}Pi䍲0{pqzD(C-W93cpl] ktBTQ’*x_Ppy*UJ*B1U|oZ#5nTV)n,< S ,"a~SØ50 %SiW)0p-S['YN:iq^cd\|==?Nr/?qLݭ'޵XԴZk -B]0[Ǎz x%)-׿,пRZdL`!m˿sVd5y1&c-lSj-lv~.C )ld U,Pl-o(iߺh5ݮyЩJhӶҒ(; gɵ9Kk뢊`JPv\r\rKsiIiW7w+X @[ xH..;uv)êvzA @V+ImOO>ilO&F,l ;YD ]h9]R0YD( q̒ ~ZLү] kt o7T"aOŖmQBןrsej*n/WlJw;]PT E¢KW|T ,IeMUZ f@T LRzUJo-#0Jp;r &ZgfM$~p?Lj݀ip<`(WCTeb ~!w)*q%cT J8Cp0R1-OtjɕvA>Ud BMR@U ,$0J>q=Tq] L0۵wtc!Xw+m}hWz!Qr &hgl7̥,ȵŏoN0WgzX'l<`4WCTf ~5wUn^lF6K!j<2vd!>b(;WCTeg v;wU^RF`3"<[u#׵(# CmR-k mˍr2 זmٺ%ݎ0ħ[ E tH/D.wʝE()Edp3DD,ΛLİ;>_?|NO|/|t{2|pAH>H {)ōˍr#H ؁;eR~@JdßS՟͎Ƃp!BA!(w#U^F`2%Y"(q00{0o"I~_^=oi7w'xg%vĶ(z8 olaGt|U.^(pĎpC0m鮼-xGB]-me}'u! ‚r+J]p(9-p/Ă6c4!%O[RyE# Ij[HYF]E=_LR]vl%[$nvMR):mIŎ2Ĩ[me[u4 vql 1Jpaz~4QvIk-ݼ=~Ǘכ;>?(# ĶڼB_G@tU6_RH`Y@hDԔY)7󴠙8Wsl~Ķ}aɏ%aa1=?O4͑ew|[Bewē!>V:ܒק-noi+uR۴%0-9r= ispz\:z{Q*2ī4Ҫ4:UKKҲ],-diIrᖖ%Sҹ.P[D qzy}{.㏊=;j>V=ci Mr]|,cI=XXX~Zz#2o˛6Y;"n1*!eB\ 5YX O^iC~k)ħ[ ͪ tHY/*ŬrMf()***M;S|ToK6QfG-C:L^Bp\U%e}N&GF~̎)ħP@ЍI!.Njp$FNN"n| "95wI!T}6UprS@藷\ʵUsm*l*8K8Ҥ~G-^U:Lի@h^U&Jb^^#^OZu-MDQO ~r*i u\'1Jp|nrm1 |xY-2vq]5mY#0Jeǖ59D`DS=JS ΔB_GL.Δkr$FI!L9L9LMg$E(ħ26SUh tcRP&uLj(7S2 P&Q$g ]Uk>%NԶ:QND&'Jb wpqqf<¢ts3՞rmaQ_4>|G.~o$F!((O>wdEơ?u -:w$G!NrKmK/PR/|)QRRRR|oK}y_8B3e-P꫖BLaY.o$F&nYy`YybY8MmR&F;n;6EI}ռ@(+żM(++.|Cm$'|[ߑ(u7`Ob[oP@;)< œmwAGܓ6P7-ɾ=ּɣ#f AnFE=Gk"N w1*|E7*<0*<1*.)g2if>숕B|Ш@¨] dTH2ܨĨ̗gȁ+m̎,)ħ[ tHQ/ ŨMF()Í  Oi8Dmn(cAt\)SW컨̾Me%e<=?C4m_=_n^!# 1VCҦ4k J4&YbJJ'Js4c>Mdiin?ߟ]w{t D@CͪFPAԅ00t8a Lbq=14)ӏraG TЏ4'T PQ'p?"?"?"!84;bn1!*!e>B!B"4 !!!b&O?@|Яmؑ=tP)S54 l%eH$};8RBl^t ^]d/H.^^^ad&yh =PȰ#9 Affxٖŋ<e/I拗 /,^!xۖ͘6ջ #C *NՋ@B/*4yQt5=Zi6Lnː><}?iՐڑ.u_`Cj[4T )  ] dHILܐ rr8n<7@djK.xv$K!6ZlFmK Œ ]̨vw(̨ͨ@̨CbcO[t.;FMQBjDi #*t1B%1Jp#*#*#j ;2K[p|:}_ŖQM7{PrAi *tB%1Jp**jz~8azM[nIt-vBB;!4  g{ۖ 0mm17Nno>RA&ȈB "ޜoˈ\a#es6P6mΓu!f< $͎!m¶@hz }x [%ipyQTǎmP=<1qGbԭB>M_@+(_M(iHn c[SRqG  VC9UAob!6Y d"")eƜ]_yw\NwFaKt@IHHUHʱ$eQKHʑH)LdZ;R&WyTU5N 59vQc,1Jq595959? )@ؖ"]њ~wK!xPn *7k rs"7&Yb|rsrs$ry鱫/mL# ۠{ҕAZUei B]d$KKV\@DOIC$aد n?t6])Sզ56hӱI%e666 x ]~SOj2UmZ_hӱ6iQRkhӑh)9{iTWuJKƪ21EiQ0h(ӗg3frQlZ" 1VCmҦMk EiQ҆k#ЦGMgsv<_bhbn͎03Ĩ[ma汪Mk EiQ҆k#ЦGMg;{F0ݿGTzuw`z[y*}7b=vQ&Zb|(9 "k =`ݟOO@cЎl3m*Dk !z"DMB(9Å#4 3Y;n1֜%Ǫ欁/4籋<6i לG9DsaZ|P-|p{22i21CXWcBЕ.ؤ+K3\W<]9OxcnfvD!>bo2UX_hcxlҌ%FI@3f<=?glSe|0r2fGPX5 x"M±(yÅ#s2do)oڏfQ;jv"ζds8 =~Y8DQ"N"Nf"4ƃQm9jGl9l2U sxc@ᆛ#0Fb:?Ok3_<<_o~>=ܿ<~gՏ_i}!U'$l$`>$b>?998c[ƹew Bj8oUCT-bJ]f4si:|J`Jd2L0ؚsfN6UA/R!5 7 0 1 KdպwD Bj3TCT}iH]4h:kHkHK~|zytoL:}=>O||0`۳ӧw2LS07c`l&ѱ_iq=Q1MvϨܜ\ oXyy a8"Wq;0EliXll6d=HBD{ HCA)D)JPbJTvjzUQӭE8.T0hǂ*=SVR"T+MH/dJATtkeQ-%U cA)T)JPbҮD"]y 2ł/9R 2ؖrO?mkr\Ϲz`u?ߦ z/@n ]B(? |t7JbΤ&@c[pCnn #!j)_A(j/("P>/ .m`G $ZmQ-~A;1-t$WE"]_]ih`AC1гmJrZWmQu#7I䒊Joi=bEiSru~H*xWPty*UJ*TI0Uݞ=!{Bjkt~\*Z_E o ;lͨKP҅ZÆuk 7DG_;>?nK(Hձ, ON TO!׻Db(%$ڋyD[; _ *?hiD[F\Px6d @0V:AװXt]J\u+N*. ǁRiO/;6aYW5[q[]pG`o8jZC) #YőwǛCk 6 3XEN/6c-8A;X:u9jkU?R"TK'pLՎd13~C$]~~H @[MX ."aЎ/.SmpUJ*\,GSmq4uA8eDcU#*n-޿o/ZptA v|rΝ~PD(ԩ-N.21FLY>]]jli=„F9Nh,"aО/2]Λy%WxJ6iW7+R[S`Z) 0Q (i.MmeDMmqܴ`uc#%S[,M=;/o?=ݿ^YG(uapH( "̩9]/%FIgNmqtIk))ULj9OKӟe/o;2k^ SaխaJ3 }tcI"?]G`pOq&+w2ߎ\OO_޿^N<(zP3 J ҞBJ!u9jk'RL%Nڑ{[;́_0G5e>bh"TCԍvat9Vhk %eyNڑ&8?N?'!/z֣2\ PA  DB08>hO1-0vοL J; ʰBE w9Ehk)1Jpu!Yg`ӐԔAtB\)SU5F \PF`*18?hQhӴ|vXmy?hϜ$osi^_~-ㅚK 8o ⬁RHΩ䜚$gQrk hΉiyEI Vs ~c\BuW`zS!U.I 2t"C6Z`\2t2tb2tNc-w~I# cyc.=+ 9uS,0Jp99-)|f8"l>̒f=z0*/V@Svo[^\K b|e?<xow>!K|"|;2g;ro;F G̶ ޙ-Ǎb[l|e[9%1̃=&LC gm5 8n>އm*9? b|eA߃ys&7Su|AMTENoEPf-"aЎ/6Y&W6YT)J-[,fNГEJn+}ӟ>]}6[ݯ^??ތe.9 Պ Y@}r"`7P|]+ cy#4Ct$Qsy=Щl+U H\dA.T)ʓ*Z Ub8ځwry=y/{UQEǽT0w{.a/_ {}PD(G FD. m&LU:ZT1U$ Ew yJ*%BI 3J\ 7sy=FѩGT :޵:>%*U *GvS%c;Y @[ \*=|+U _BW>R"T)R\){{&@NQMNJ*UI_ _T ɱ:\¢QjPrKMz&D(@3;_3RL Vr>bTCT] va.F@h2$FI )VQ-,Dl( [ tH/ m()-,@,3L?/ e2)PMO2U@_QR[XXƌ,R>c^O|Xݖ U}WPxC74) xxxH{>ϊ|C.n-x:CU@h*o&Wbt:o:o :qɄ,h"/ԙC2n1z:CU@hjo&Wbzozo z<v̦nZ>|Ϳ?(O?(yޑx5mXՀ5j*p&XbF$ׁ#Ё#сM4!8;n1ւE2cU @hjp&5Xbzpzp$z |vx`WtyK1 X،UUX/Ѕc]86$ W#P#QM4sS݄4>b,oKjƪ/EMr()v@pC[ȟ@3n2Rk!gꊰBPcE8) W#P#SStv><6S-FtH[_c}wlw 2|;}w_M#w-9;6l' @ۊhH}Ў/>m(iOav|~vٛ9.@~B-Cu?Ab?! "O7}^QQqqan'7tKQ_PTZ$(p#jZ-( % m&.j%@AJ˥D D1M̴?X;`kam:?hiSuH5FXH\GYRx\&I,s]7wqbzT7_~D_@~+y۾(`ЯN.j_sױCH#91i&x{>ӜopעEg=ҩW$٣B}]UdŚ@(E_D_g1{b0ZM=OYt*tHTт*Bu]^W{?R"Tbbs* yZHqCc9?f+O4Vn q:.p~/D^Eu) xx'[1#pN4.9NeA uv-vܴ( ڝݹvض7\s@s&a0o-ۢ"zx m"ݶ"]A v|!ҹ."tK%YHH"!|0aqxsAWw#4n3JC4 }EuIJwAQ'~H&C4"Gm §[mN%e躸>.(#0Jp%Bѻ\Ж{;`1c6aӭ읫 Bw]4zפK.\w@wLOCՙ+#^nay:=|=>?^Lw_/gSzOUXX8*i F!.ro$FY" zzz&;fs`j~y>}>?p3qJnllX| w1}|#0Jp/mɵ1uvCZ):j+Ǜo7_?* pr~cƅĬ:nflZ MAWӅB״-W \5fNS1 th*ܬFO:Z8'VC] v|1#.3̈L)JЀАƤi$cko4tKU i%M 酓e8Yd-hR 4NN&Gђ5QEKzXȐ$ZD ]^xXe*IJ$22njXX-:#M~|gGHc @[ xHd-"a/,2#.%BIccɇ#وhf3]㙊.ec>:H4X.bFLhłŒ%FcbvӖДtyyeKܦ7r:HmÍ2ئD(Ç K1r"L[OɟOq9@sX=B8Qi| unXb0D('*n`@dQӭQ[BE ( tM;`(­ssɖz0f6Cd כޗ/whqkS7@h|V@[(s?7|%snnFٹA!rLĨYOӓ2eFmu^@ l6L\ɂɒgp] gڂSOss^gNQf=>I ]TqF.Q@w]. S ],H#0q. ]H3`ILVtaRF/ H 0Œ2%FI0 xa2LM?L[x2RMOx-Bj` 2vYۦe(&`l:xK*1bcM1 |в@Zµ]\kZK2̸ܸy͔%i Wj<ɛ) m)R[w vm-0JpR;+eԽnt]q%mٶ.1JpGGGLZ#L[𸩊aI6cf[B]&4\@Dsjo2MzXG>b8սBk.{m۴ז%e^ۂ]ܨ1ɜϋhXGbXs9Ik 77{F5Pv.mSy~z!ցrl d`h֜mȕp6o<ꂌGM!5m6}rel[Ч@(6J''k9VͶw2zX@]eJk AF.CTDaagMx5̞OOWǯǗ]®'[@`85UCT& }15 ]ij*JiS@h?A-]7|js@+lr" d7}lNJ?| p s Dr"Nd~D(Ïdp$2Wm><<C(JhdUB$G%Hb~pD@$61aݐ|0nedz_e4 §[ m tHmc-v-2c F`63Mq0{ʹV2~ ePq'$ ڠ{4J*Ta "WЪQ+S;ȹKVG9MqsI`l ՖD}B#\ͮ'5e>bxRFZRF 8]ej9%e*s829h-|{^_=#5W0TZ`\ѩ%WJԺZpE`\uNTDՒ+1Su|m_=mbeҬ1 Ъ[ }[\ZF`%8Xe 3,7ٳj%_ٮg5e>bll pjIvat9Qej'%emNTClbۖAr|</YcAuu)l5}y|Y(Yp>bS>Xa2Ě~ulzP-c H uS;LQR|1Df `g~sir3 2ڌke@QFTZF, {[lX%F0~6€yz~Z+mfj=i0VcEySdـK( rv4bAQ҆khDS?lpضmvmFj+o-pO nG"mE4$KB;0-26S ,ܴ%Χo-#K,tcQ)Su,4c唱2^PF`8el,q,?M_rHB|б@:±] XH2ܱ]&0B`0v$!Fjm |DW!4 \aC.6k!$FAmlGlOb6d)>@Pǩ4ҧh UvbG&Gbvv#:|7 mR>#"ώ D5,hJTE)PA4t44yͦl)1?\$bnG"¤mPI Jbo6& rcL>@_B|Я@U¯r]*WI2ܯrrį<"-B^ž_.hX#Naca[U} wp]|;H9wpwpw监|2qq/7ߧ3 |HBkؖ(tUAo\5 d |o){RWB|etUA_ \QR  >Ѡ`O`ƈ;~:at?}r|rx)H BvؖtUAo\5d+4g@ Ͷĕysӎt ĥ[m@Wn/npmՕFIn78`78b7]~摜rFwqv `ؖsUA\5绉>[6ܴm*v!@d͇mF}|@X|]d>H3!!B<}[і5Q_-C:Lp@hb8&Abᆃ'CƸCK>m̎Q-p:LU@h"&qXb'pMFjs"\l\iB˥Cl,1Jϊ_[>k"dibƑ4-& r#5 ζ~ w|wF9q3d!p-5:9>~}aRX}Pi BťCK&Ab~|?JĶmaR84~Gb$BmCQFZa&Ir(44ޱi2zG)SOX2UK_X ,QRXXX~L ,/wd!>bh`UCT , va`.o2$FIn`y``yb`iE&2MّGtkU)Su4k廸Vɵ%ekkk5=? m1 |н@W½]+^I2ܽv)!|cnnş~G-fU:Lլ@hfbV&Jbff'fU i1ڑڒM̎1ħZWU(( CU.^Uh^F` ܫ īя!R-b8wGbMTšSi *tBO%1Jp***aӴŋwl;V{Sx~HF B!t_N#Q}t=J}l==ZmY㗷7Z1DB9US ]d|Jr gg 8_EǠVly RvlVm YQUY*QUUUn~Fv0طo_y;av!:^l)l/,RM( -,@,n<;6U卿=tyz}8^1N諸APuBg[9T:} i#1Jpw!w!x4:oX-|w<~xq,wd!Rv3lϠQ |Q  1Ɛ=)۲M1N#| 6ca[8T i]4H4iii?@8_8C|z3 Ǚ t3 b7cܭĭ! .l ;n14*!eB0bs!6  7"0"1< ACqؑ tP)S4X R%e0=ߦC2|BBqؑ tP)S54 T%e|l2i Ww~ #A C'R$h '!vqb 1Jp'!'!'a~~8$F(oّ t-ABb 6z "" OɁFMّ ݃ t(W ʪc!p.OY(`̿R0q\w<9@%Î1ħ$2F:e- pm(  H)~`f(cvD!(LllǪe>/,2M(y-,H,ɧvmwaWBbu ) tOԃBSH`+=;1 C}$iЯlؑ[Nj9i \XN,'Q:rrr?miY-SHzB\#6%=Ǫ٤n ib6Mf(2rifH̦iCl"И0v;!2Vl-m vUkI_XKckil$FIn-Z4=d6vdVv[i*t-9V% va-]Z%e4ki$4#s8?x|gci[sL}4v&Ib6lLٺlyN`5/ vNOL2UI_Lcil$FIn3f͔狲HήĶ`x||oOHٳcAPuTidOq@(469NdwF8q~tӧΞgӀ# CǩR8i i8M()8N#qr~1$rBl5QfGF-A:L>@h>QR#Fb1Ns`N>(Dы;2zn1+!e2Bp.N$K2I08Ϣ!6R-'nP?뗫/?Oy?iv0Bh(WCT`BN]Ԥ+7\N@ND>fZGؖЛo2zzx<M~|xsutwzɴ}"uW@"ȦR7ShũVbR ʼn>`#Db]ƶޥ~ZJ b1BE!.rqj5J .' '"O0G|Ķ4μx͞-Ƃ,_  }dHƩI2(%mhhhlGJ@KlK5mwBjoZЗPũ^bRR+ (Ɖ(տ~^kM_ObǶ緛yo֍;}n>7T9зQȩdRrK HȉHfH&\M+Wc[{٣Fy;~n]]sƆk@V@|`* {!Оs97iQss&ٛGgoK ~}9ݝޞ/յ^ޟ^@0Fn,@oKP(йhRKHЙIƤy3eseAP:u@/Ps9 W3P3SCȞ~E AP:u@/s9 33O#N[P~^5O_t_)l$D4i~HL =+=їI'<2z>ɖ2?}cC;D+} x8} ~ "w-roPq& f^eȍc[?7O ׯ ֹnjzϧ_.Pڸ#JZ{ zCս]u(n0a8vZ'Kt-vu޸#JC{Ҧno(Fbo6{CFFf=GJ$&4W<*=<<|X+;Zv@-],fq(E #~6՟ΉԦs~_˓ӧw2a7 M! # ~e-7LKrT +)߀\H^kqiѬr7xg2N_h%fyv\ -un*,?+eد,縚c[wP{o@6_>O_~Ã/}ejث ]*߫|7eܯWQG|A-4k4ƹY4ԧA|گ_*%8M:Z|o48||u}3 §8V_}ˏ??UjpHVݐ)>?!\?ƟPOO&O&rljLrz;>ݾ_=6)7QoUZͷkZ6жlP$ ҡKthJRsDJ2Mӣ.-.Ǟ#VS/xaZm|gP⠓)YҡR`Q[4H:ZC"b|8g:M[ɽ'4w2:ہEQCQJK%i t842 b)Kr ˪)%er|"xj>\NST+\2jk mx)C|JdA!1kiZM |@{ R-eTKYRF`82$ay3tNN)tMOz2U\_]ʣ ( H2'QD|M?@26_Uس>GPum^idO6@(.RJ=%Fn(C"|;}u=J3Տ,T8 @ ݫ xH{PW] (iJ4QD,k8 l.:jKU<ܞV8֜Ai vxV + :oޥP(]O:(C&uc!mw_Sv.n(*!SB{=*eOL%SW 6̾Βt-Sl+n5oSG-iG":ֆIڰBEzХzФ KR+Pb |gv4Mmcw?^=n{Gb_o 9m-.rJ%mF9pc T2ч9pO cڴōN~QcM2ƺJNAv}@u3Tj,"0Jp T2eH]X4tS-j+\@h>B:&CI @!azȜ2s+Mގ|1ħ[m c]B0"*H%eq* n0O?uh-g|z|t{uus|/z=Nkכ[>KC̺1d\54J 3KmRdy.S`4fL2db&!xpֳ{R[xwn^^ /#Z QvcKaSxIJH %Br$CIA$@1!KqHaSVc㷇ZBS RB_E).Bn$FI)d)䥧)T{x]u e2/mˠ?^_OWFdMCfWUz<-n z=-^`s2'ʜ? %@AL'D&D UvrRy=iyiEOKIw}e\0@(§@@?&_4'L5U4:Z8UC)oIv|1.Lx %UttJr[4|x`srz90Ք(u^i6ї0 (,tB }A 7=0}Ɣ!(otY*tz*A{ HCᜇ.y8T) P%%KO?(jGF554:hWBj~PC]X塋U*VBI n`ô )Q-*~{~}?~~y}}8}9rt6ӯ_/Z"ڟ㤊NGZiAt0)\ N%BI'M 4$r3Hï ې)RES&@h7tA ]PB?HS"NhNhp4ɹtȆi O0JK w;ADፆ.hx)Jpg4g4x̝b(VC¬IB ]TЪ%ekB<kԹ-R!R lXV6B ?koɎ%>˚vm7BkP}oHm=^ڲȼU&%~^oDf2p;3O8"F(ߠ߿?={4 ; g]z+~{9ǯ<p{ws5_{OW7χ+08q$ƶD9츞G:l eQd.JvhSF|eee4o`_.n8d5h= X uq[ϤCy;WbduǶ?͕̬ªz-3E,$EM(=?S;-3>YMU>aQa[~6UE VK.dEVHM(+cl+~BpTbG%69* T"TT^˧03'bcnFCDdѿi gI],=E[ÏhGO6ش.>.)C|x-X ~ul첎MXQN|:6uu~;;w\ǝ'C~}}B垚L#Yj݁4e}$_e/%aaafq+Q!{ tHa/ 0M()  H 3iUlGY ?tLOf52UL_fiL3QRfflq?EU(sQt=FnS :Lm@nS6&IbnSnS$n~wsL˼Ӹe.B|XAKX]d,I2XXX-s&:|2m1&\N̤tT$ *녙IL̤ͤD$gҴv֒KGqoes?ysT@n#򦪫h &_b"ܾ~&n˧:ț6dS!Fk$CT >BO]$K6\O@ODwn0ɻO4kKc3L#ʙ:7˩euJSDtw-Jj`AGМMT4%WllJ˛EWBm\YjhxXn5Zn^rE#_ͦl*b+B.5 5wސmϯCU:[,3o-3/"aЁ/DfEd6*%BI.1 1⭱*[!SS[byy[ hyyA |!..ⲩT)JpiidL0N8ׂ{?E\~֓(+<D0")A$  ͈ϻkm 2NMm @z뱺-鵺Ak ڎAĕo1Unea qΐ_tș m-i-~3%B ;`L͇ɹc?mZUTto簭te\C_8`+UJ*ooDO[v򡧦rmP[})t싗2M/#Q҅,xY62s1ϹrMr6,~B.^ǰY(<ca!r=<︄ʝƽcփPUPfSBel6rᔱ2Rւ9{2mm(^P=Q:L"@.&HbFFFQvag 4f0 { tHH_E[dݢ ,,ן7lomڲyvaPWd&BJAB %>R],%f) PTTTyg@NNM9z><; o.Hm.UCT% >_]%/I7aaaڟU!D3f=^)CR2i t vl$1Jpinٻ-^F fOM2UI_8Nd'QR{NxNxN&y.Kcb׻sE#Bp& Bu-BEbKl|ۖJ` RylK`4N$L[bnxkڞUt*g\u@wr]|';I3;O8O8OS33?%6_{9v_>]D@uס UNՆ@s((ňrMF(í((G}4;m Φ5%NOQ2U3J_Q(QRQQQSN?Ub9ANO-髪BW绨~I媆~~~v.\ưߦ-7:!>%vԶHQvbG&;Jb f5P;-?*z$;!c^ږsBx/.%^%e{Ɂc%n$lR{_OJ {9\w@c(|'wrM(}'|'G|agS~!>sA=ƖӶZNrr],'d9I2rrrrr): el[oKi/A|r@ZNrr],'d9I2rrrrrr2C4-7r{6 _>]}=OS"G'JohO 2U;A_ QR  ~i'ąˤm*끽^lI8ξ<~'R*)BH? wp 6̿+ذґ3i+b ~#9#cbӭ‡§6SQcWH[Fjt,QЧ<<:%%-HODa}NkCO&zhKH1{yXR&wX }oe2BBg938s?ENNT"aЁ7U:J [>T! ĨVK-^$grχiHn׻yF94PWwᕞ@h;| > _pU%w~Hsc.˴2}v=ӧ)ƢշAkLy>%gF%BY H6wc𤄵Y>EN6e$ :E(t e7RPRG dF2"did5e=7GatfeV@PV7|#" 2f]XKUZ{('TC8͒( XC{+D%QX&J$Dv_{v=)8M:,)Oe:iNQRiNi$F8cN-^ծGa:_l@mF_PC{+ )1Jp;*;*gBgݸ3R+ضE~tYOi x#ڒ;5RcBGr(Dd w2p2s΄0c\[bI|90t[i #*@VXE?zGu8#F`.2!qgdtmt}<^K?n_oPӭ'1 C H}GQHcil2$FIn!BYaj?̾f&\[O^k=^:LU@ST=߼1W9H3V8uU$v0#(N2.'B MPcCpdb?^|^htɪTNr"`Ё/N0.'BZ^ *BTݴ:H[-WD, @z-IAkJ2YD(Y%Y%Yeݙ!R]·۸}ZAt-LAǾXR%5M, YYY0NxEzXs)4+H h tb/NF.'B$`(_FdT'B 1c"ҷEoWw~\>@BmGۂ8 qRqF9p$@Ĉƹw-S증zx|<\WJ¯5jIJ K") \ ]څJbA$Q@]B$D~>%}[e卾#ǚ76YTCŒ7 } ],%o N؅x谲-rLysחPY0pQ$\@(݅.B%p$OQ ]ȄWzTs WChz{.c;6Rxx$8 +<>Ugi=|ɄSBWAчT屋[rQS-q?C[u9~>jMPe;>&?gWuuIt+,}b_%˸>v Ж]WgTQ~C/HЇPa0Qaaaট_5'X5e>cUCT1 a.Xl$FIEEYl~R&L75\+*p_U5_.EYLMʢ(\YL@YLDY۟9-7iB t(p"-|. n4͊n\jW 4 ~ -v1b&1ʉhhh6 !YMЯm CR*>j t 1vc(1Jp11qnN@-6T4o qo8mΧ)e "Czo[5_~ }^/vyŶ(9_~"{윰Y[4g.@eUCT4 .nZlr$FEE%geZVO!2U7D_!QR!!!s|qmVz4eY [@9ZGb}&Cb3n}$`}$b}83}8tdC[ST qBcRjfh t 3#u13R!1Jp3#3#3cn><|h˶?n5ppAŶHkՖ@DbK&[Bb|DDZyMD$l ~3zU2KK@s rV g Nso-yeHж"AW,-/|h'|B^.~jzVQYa㊅mYǼ\E-A\h+ゎ |\t@tS$9C)ЯHoX*hpXnZn\D^hh+ZK &\h@h$8mHʬ~yz,V%- b AP mV|R TzzM쥓DoUm^u8Yn{j)aq/tBE'pY"L**͘)qcE[piRYOL+tX!ܖZ!\PE _胶>h+UJ*\@#ʴ1J` @z&X&"AzzUb$UaS[77_O|T|Lٳ@Hl8(dBE&tp$W P 5!siq$// bZBtPX ¥/BE(t1    Mryglwl+Ao9~6 v_z"LS #͕.A*DJ },EuI4JyA%QR'H4;Gdw;v"K §z,S(㫲†ʌ&eFb\@D10ʴܿMOupwv/t-ĨN7x?,ЯnaE.Vk"$F9pCCy8X3_r-zssx)KiE@TzYTu4D uq\ 1Jqajz)l cQ[ޫ6ŝ^ۂ_R@s(^˵Fr+ǐҖ;jȗ §{ tH/ `pM()-,G,dwvԨmowGZ!4Y2W0T@CT |1.k$FI28282L퇸&,rl } }C4$Kc@.2&Abd>>#>5yvHxrr_ϯ_OWZѫӿ_ן}O] %|W@&xO.)f rcS<&:ƦbӷMERwamKdQX\,QXXXvZC %)b[86 Fkٖ@BA];-R!0Jϖ;ੋAlj h\0 hUS#_X雬NQ{x%)dƖ8;Uo0@elvnl٩/NMf(9NNO9E8_L8O mն薯o:ŶwVm()÷UlVO?&g!%v}IØQP+Ddѿh gI],=E[ÏhGц$}wntvb8w+|sQ_Ngj~j@W6.ߔm4 d<63j+C*@|П@Ÿ]iOK2ܟğvf6#-x:x<82/ħ{ tH/hŌMf()hh4 g,Ci@Xe,XC #g[4U>'/Cţ: a=3Uó z4.. 9bdle4~\X^ɂ&9;\%zX͸{8Ie40碈{R=׊DXR%pE U5%OԖ ?ϙOn)A&u+ \8 fgel+\W#IIԖ kMM` LNN#Y"`/)n_@(fP?G ],Ιڢa+s'_c/2^l gP~ -c}k?R"|+ JHV(!g@:Ͽ|{:ܼnkٹs~~ ͟ 63¿䏀A+㭔k5)JзRs$o4mvɍupQߴU|u)A _$ :KI' D(B /aMma_}~u)Ae%_ :K='/R |jNUs /L1pxjKooZ{DzW =' *!MIM$ :豠IsV &%BIz J蹨Iy7Kul^i ~{:O&'8Ǜ毇}AhuaT\rG⠏"̵" %{hP3繨q3ZimSPYj݆a ~[u }M]9_(v eP<u |4›if*\"0Sy0o$ Ƃ7=0V|ɛ dP< L1ndFx[,tUq |DP꼠AQBN]ԤK6\N@NDθa$9v=76V7a?7RBA .pj҅%F ' ' g8<Ս^5mFk,o ύhGPéB*rt]MQk2蜘V콛l>Fm_Q|A݆Zq?M]+V@3(E+NmZ(yõĴbnfƎ776Ԋ+!oZBA.ZqjӊF''9ceܖ f) vbq?M {s8Mbqbqfbqpls[`T&_uV\iS׊ 8wъsV,0Jp883Ծ~`7$!Hm(WCb>B,]& 7\,@,L,ޘg̔7?˛ 6T+!ojBA.jqnSFgg8NZ ${oG(1De#B@SHȹ$dQKHșI)SL?ҋ 6Ԑ+!oBA!.rnӐF!g!g!Jמ9-fLx 5s]BV@#($EBm(i% $$ 9Bf]d&3 F\f@fDf8tϟ.ѿ(]K@UG,5/GcUv֠3 G-ZY(x4ryHdgC֝+A "5EǪ쬁GPcyl%FI.;@vc8o'UY_(cylR%FI8@ql}z*Pm&\MtƼ-^Ah Aas?GUYϤИ.ؤ1KG\c<ٙ)m1Vi]Pa֣5Jw BI9]4Is%<y$Ӌr7 o-L -/-CPh}c o"ύ(OezV)#0JP]xHSޤ4{V,V2!>c o*z<7RB? [iLQRjG2Dn0yi鋩xme.B|XTvnFqI%e{ r~w[˶Hm/o7_Of%Ou`%xStn )`E 6MJ(cll'bN#myЦI((ħ{EMQйe:lI%ellMaNh[􋂎DA!>c,n΍(/_E5mW 2\5@5D_Ia$mQп~÷i&HWPU+bs#5( Qʯ&WbʯʯaoJnGBw/:^ t):7RBP~M״) W~ P~ S~sfi>8|XheNMm §{tH/`E6mB()Å``Ci\m#e{26_NJ#!R*k t !tM,1Jp!!h!/|7M`=9McnFCe:Ddѿ~igI],=E[ÏhGO;KO~mtp|{<\i85W7O 5l:=W}ʿ&_bsW P QN#?=?/ϯ/oO=??]}AT #ȟ gQ `lQazϐiܛ% M+×I)F^@ ?M @3( 0M^(yýC5ٕahjǛx44O4\ЄT-jal @ ]dH0[XV[l pIL"*|ٸE@]ÉjtQbԖg1ඹTSr\߯lQT> `<ۢOկmQ,TڢN[a<0Sr-O5- ^SOmm@==iA`Vse.m$F9s.8w|}:~;7שG>좍ü Z|m_o!S~7 }tsSujFL!&ѮV<7|/%];%OaJ)gdoIbtޒa̭rI|li+DB&+b!MDAG=4q5%M{H$CL;q#.??wlzy|w8@; d*h%.8"Q! GJ#Dp=92B.M{"2< ZW"^E?xQ`GˈOn;ib![Qwh5U-Y"Q7[~\yoe-%@Ҝ?lIf؍c6ϦiA(p W] ir HtmAUF IT?4X=;xӴ(z?q{^^:<z8imPr= ^]dW/U>Wﭬ(d W?LrD~fMޫƹ͒  rH`pб/4Ve mU;L;v l=f͗QX>wﭴz% #Gt >[eZK6ف/Cqi*kRq~=@zV | 5΍Tpj!waQN/\W0_<BrA7tAt ƹ ]:!{*]DIw80vxǼ7_ǗowϿ+Ƭ9PuctzTP8!~oe5 ư#=y;ҍ1`VKjh xxƹ ]:CU.|aNqlۖ|\j?oOO};>vIh{֣mK[4D v1l !Jq  b ܼ3DMsOΧ?䏦A}Ǟ䥭y}g`x3%ug`g`g07{< u|_g/5AVuB t*9 }B`8 Y%```S6sejol~z|9>=73Ny}RBx@ȟՠqЇQX `[ Q[ X D³m1œ/wO_lo^@L>„]LbBH8܄؄OOɂڷE@[6~{"r9KMT8"*QYBtᢲŢk휱lےSo'NS4mz5j[u?V=t٪(*U`Vݙ`9k_bT zpVyރ=AB ,,vmy|կ7-\=X(DP@t.hjAWȡE@傆  sqVO mχB˄򡮺,V8X.b״,\ė,YOKgQ\~})݇Y-> xٖuG᠏\5?dҐ[vʷz3m PGϡ\ʵT槙mL,;ۢƗ[lUmUqRXU?Z6q*D!nU9`U9lUqœm=w qb+j[լ(zaE.Vk$DnE9`E9lEy|5\Ӗ;~|||KBlR 4Wl>mqq/'|r-擄(''G Y3gx4m.'!^=؍ږ@vF }庸Q(((ݨ1K~ dRMoCL[;v5oA^x Z Qr{ x { ލӦ{ӯ0T=}J8J2ҋVV" xn%x`%xl%x?w> ҥۡ=T bga[ל},.΂oq$DI,x,x,̺/ $zwnjs1FO.5Wc_[_ Q҅>?mLfh {>K_j&l Cz\ $PM8(4`E-( 5`4`5ijw`1/=N/bi,mBF@K6/mGL|z|z:tPsG-!F^ |e4F(2 Kfd$D2 4mn L[2~;~<WˏKU_`~ 8T/mR8w/.tm(_ aÍ!a.1yW&2y`d ah[OM/vnkd'WU"W<7$.`|n2ܡ {+,WygVQ0W\i4m먇">=޹U5?U0a$ 6[~NA-?) °K~),mLyě/RwWsiBdT n% \*|HJ-#aa~ܔzoe0%BII?҄09YǑ@pmooVzc`VChStI.({+%e-zHS&a\76O۫yf~˿=Es]s;Zy^rGa,{+%w|Hsgd>L.b|C0NO]T(*(#_tWZR((.:(cB3y8)?k\0 W{,/5@s0w~{+%wG;AHvƝ?*n^݄J wV >Op{+ ~BQr; 2wҼueNjs3Bɦҥ*h t ͦ?4Х(Euw.qM4Ӹ:rnj3e>-SA7|U7AY't8:eFqGAr9Qf ~g3SQw NOZ2U A_"4P()m1=SNg0ezԽ?7.S ]4:3L[Y(_J|Q~2v!aTwzPE6~EIGu꽕u G܏RwC~xӰ&7} ) Q\UPEa -P4P(®:5gHL_OL9_zι 6 c#jىms-jI$>”p]{+D%):)$-J\3~V< @ cSj[SpGϡ0:\JwJ;ܔR~G4ٔ]]%t1-K YRF_Syoe2 7>1ʌaZHH8miy~ع4(`)y[\SH;JJF\JV~GhO;mitl0Q:1gI#>Bgp{+4%ά9h [2^iswxع Bp`y[dBF!0w轕u A\`V7~GN)睳n |">@Xi?-* 9Js(Õfu%w;ǰs.mOnLLF؝f|*=줁аC1;u:F೓*tavعx>],3 ~țAgP.zoe7 7(MUބ4}o7G&_9CJu \PД;T~oe0TJp~GBvm{im囯gf /e]UK( ZH.zoe0aDn:f>@ƽ-sڴ { 9f[_Bc:\`:eFI>ǨNÔ Cae>m[6l-A|cV\]B:]*e$FI1ˋN#1λgbGm[_Ox M!`=cؖ6D,9Qx .xoeCM1n+e&K Ҧ^aacڪǠЕe1t ⽕ʔj{ ꆈelJ.80k-mD 1~SmKJ_B7Uh{S 2M*7Kmڒm`Ati[4_L BۋI`/^L|\ǐ,Zv-Rh.HBhܖ US#_LLQaibM n@o-2֢O_[.m˦6MeTG):7|/A7XDq,8É8$%!4)#&υ) O7/VqɪtDTۧ6]t(*݂DłH}, R*JHԝ?DJHa$LN<~R*UTtoSU$ :J*UJ*T?TɄ*~Z\tG,Z0+xä*-y*!UγA~,C9N x4UFLhΰuco=|`t/'<rQ̸b :QbMĂ5{i@LTq >XS"I?RIfMyvmѦ f=' -loJ΍T% :Ja*UJ*T?T!{3ֲ+][@0ůwOW7os zVTs*=8賰{zs8Ξ=0cɞ#g q~nzTT>cxFjX:`LS V =0)e#W֭E5e>chTCT- a.6Aj $FIn$`$m)ݙRN۵Ep5;ǧ حE5iBg,4o΍HPhͩ֜fQ ͉я_IVuqQMO›s#5( t )8uS,0Jp18181xj?80G-.-PMJ 2s#5( t 7uzS+1Jp77wj:ORB uP@O 2s#UH t 7u|S+1Jp77wj?'1bז ??OCS6AHu߱):7R#BD!."pj%FI.' '"1zC$ҡz{~E !X{sI87IPpp֢Gj#0-GgW2W*ږ@@id58w54,Uj씽۳WvHv3tk [ѻ=qKPEYVts4÷C÷C>GbYہss>ʺe|[Ж_/)O:Luǣ/]M;QRہx1Η8b*jM `%|TG Зwa,.bn2%FbbfDv<-\7^Gw; } jȖБ/HMF( LD|N;'+Sz8޿}=~rV_@uסXNR@s(,RM(- ,L,0oI}9>_-esAJ ]b;+Ǐ$ o1ws33胙~LZm O:2UgQ_8EQR;88SN)aj ͼm=&L[oaMM X @7ݚ.&7@b)~a ِ` >M:uB9ӹI N*c;RȇYa>/~gNw+67K0BǾs:G%_GGb3?-l./LA|-2o% Q.unz+I2ܣdVܿPiP4<_Ϟ|v_(@ζ\kPu\&Zbuu&εsq;燁Q-R4 ]TGhTW#ʌUZa?FzV)#0 ʌܨQ=K΍A>gr W U1ƪՠ/06Y  F`5jp̥˜H@ܷOo(/RA`zN* 7BEٴKٴ$0ʭ7/6i{#MOM~)O;7-:5V) ~U ojMMޔ(M7unߥi e*O/wgav5C_§`Nզ*|s#5&) Nũ*Q2;U#pFTOc@n5:EaӥְiڎK2ְ َ퇝wi$ZpA*t7+ዩnj t/ͱ96|1qwsHM?/vޏ)qh+7RstgE JAdڬdZXc)1JpksHMԾcd ^ݩ䈇 bUS_KUGS|q'r'iq$FZw2p'!2δc>9G-&ǿtus|v\=~~}{Q  o +TS5-,%>6Yj%>K|ԖǩI,\(NE:tj2ym&!E>ǧ&WqT)E¢&m ]NMQ3AfZӌi`/ENXH#i [V$.ɆG #H6G7ҬPheu?gC bvϰۡ*h +b:mFi?r9er@`` Xg$'ħ{_/s# BN)C"1Jp9er@V:wͲU[t~j.vBzgCu磁ЧQ|.;i#1Jv>LGvvhw.\=и2j\k iA=s+ %q=D<+*r6sݑCX'Օ@Uj > _0[}neAdu4[=}3cA>:!>cVoGyPP[}ne2 u4enrgq蝕VY9wV2T͍lA![-[jJ,NvRk mS˩T;iˬ|B':8љ #w6L!l 6փ(qomҠ߈ HlC ][> KP%V٭1]lrabbM[6P'IuZe)/#am!=vZ:%B9pS`_P|И =޿.,Ty~lNl)8U +W0bH.IPpD(<@=̑lF._PEN#\>/"a/gqht94e*UJr:G 82e.gv%Kwr\OjhtpS]RTKtM鲩6M T6dSGv5Y.VPMN 5Ax./ *J/ C^@y7f$hUփ*-c tD[46pl6E~~%~33!b+znTS=ƞѶ+m3@&Hbᾑ%1O3_W3E5e>cmiޑBpl6G ,,L 2mAb#wo)kQ@#Y U@p l6 , , LL~Z2-4\ۄtw-i<.m 2???0i^&9vPW4^Dt-iBpl6 ,,D-D 1ne7m]Q@ҍ"6F`ҍҍe~ܙmFCYCYCYgaFeJV邰ħ'VLmqPBg2 eBe$Ff 2QURJBWħ$x@LBdO(gnd/= Ty=UzS4$ u\$1Jpin?c_tA =S:L{@ޓ=&Ibޓޓ#~/MX8ħx#-) cT貑 M)QF*T` 3~禍>{Gű~yzMg FiږŊR XlbMSl+ 0 Di`ɦM{aƻ_+]ł tV {G+/ZY(JvvޞO%{;e^oW W6+!oBAq.k%Fq;q;qǝv$\~8|}NW||D;m9,W.5$ u.]w)1JpRGO\\Z04`\0 t؅ږrUJ_P \(QPPPSa+>M7m)E}sE4E rX3>maI>.'׶}%iɁcۧq R[K`%`5o|}K-ﲥm[*Qp-[*϶T1}'MnZ3_PGbԽ^T>MՋ@#((ŋM^(iý((O(k]M[O|ACJ_ BGP.or$F!PyPyPM<m=P[E >chKUCTm) aK.o$FInKy`KybKǝLbN[ݽ_>mv.(!>U/CUJϣ|7T<<`8# ~|AF="r:LUD@"""&Yb""'"7&S_F4_ӂ2@@S,crlZ KҪ ȑ,5=6{R&+З/(}@e= _Gd=<{;-V//CzjFU=|7U* QUɨ廉UUUlv>C"i ˧1&x-G( ~gMT첉M(Q3|&*M~;c&r[x7/H F ot2+Ru25U-LMN(dzdzd:,m1i}J|A"}fciVCT=M i.o4%FIizizieRsm/O5!D.f= W]L r 3tq1C)1 1w1p1lv/whTn AL$!:_,lKM` B ]v( ʝڷH/>@)J=Y=g$2MEIf^V7DfcVqك@E'D!waH/bm~hgn\9ycKQ%s22k/?~g*4r}K3r.sAUޛƶΚ*Us-(Xz諶GE< x, y y$1յsKMGҘ6~yiK VٍyݘFQNnňF!xZ%-}b㷇OO¥eUˁ`&D]bFZR@è<|]N( LE띷T)qʼ42 Ђu PM*7 )7uQx ۛ `yXF\MOIւgol2!.c$F9p113-'V|_?|{/=expP6s]ͺԣ@gRyQL=s _a8?o+[g oGK˻ z dPӋ@Ө߻1Z Q2{xxKyE"EK]ZOwِ-1MR_ِy lHQ2ېؐؐ΄b? 9-9΁0ħ{tH+}UaWҪ4ԷK OVprH^Fê^MO}I 5Y4s Pʐ\C5H5k(,Ҿ[n2l)|7M&KpB4n yp!wr%FIppV oZ.ND}W_?n_>=Vw%FZQ@裨Da3D6](uatat5kKLF%/f ;e]a[:0læO%[4l4l4<%2KS)cyxWkiI %!%FI. "sYr xij7e>c]5FZQ@JCaۥK2kh–h"b [l~]BK{k⍚76wo\iFϠQv --Mq;pި%|<㦚 §{]1ҥe: l¶K%e$l$l$l˥5j_n^>^^o~:?O)wS:IcuxWJpiQ@sa;D](a aKa{beml_Jm゚AJyj}󅥁蝯[!ǭ| KbqAϏ[ypʳ9,AN{,{ƥdRw/A&O܈OLe0¦]́)ħ'Xޗ3uBg*\[bo(r c)Lyb{q9S{ g kn5:UB I踮():$t~\(fr{kV>ª{Qj.*( QTI7$㺶QO8qd?FVŔiցux_B5}U8 縮u(i9sY\Z8M6XBopr^E?p^h tY~~滲\#<ܾ̓ r̈́G7=}v6T@"}hHfB_]h\hr$ ʃ < BPB$es\_"p5(`n멹@T_ݐ zKăzOeRύHB|M/o"tCRM$0J)@GDkNFKN]2wQAŴ//& >*\׋Ib?Oqc%C+ Di3[ 5@Ufl̖(Xyf˃̖gjK\ɡrחosr ˆD5dK*BGH 9NtJ-<"Ntvsi4~O?z;]]Ls+7Gjni}=$UR 7A8Tܾ%W+HA|Ѕj@iPʅ }!PQRP Xt)i"ܸZ@=.T:LӅ@W.Ԑh J2܅!BKɑ=\_-_D 2W95@C4=' |9 (=' ,OLvbd;~}[WRd Fk95C4=' >s }Y,Q҆{N Xkn58v;g7s?>|yiuiNJA|, Ndi iTDVKdIA\Ys6 |0*n=|8Vl} :<ħ }>(aSS&c=%\xIܗ{ \AXc X[i0Ea_XzFKՓIJzK8501_nf,_ϐ6'Q?/5e,!v%F9p xہyK)q}1;xzS@tS=&3;Lf0d 3((gf@g FFW4s`At/BG!tyd nN)fS^ >ch4Clj'0>%e}}}O)GY^$ yOO8BUQ&6Ua T8D]((***<_Y-y*=|QBzVQS+@38D+]Z(yĵHyb3lC5'LI)PPwR)k t+8cX,1Jp88xn?S.!aߗ}46׷nΏ9 ud/BA%!q쒌%F.G G"s>)R0ߏA!>c ƦZ8D-]j()H2N%DZ@=glJJ"C$%K2\"@"D".ScT_)ݗK]ǖp cx_46b >J,C%K<\,@,D,.\>%$}ЛDž6Mb́ (;}cS+@WZq.XbZqZq$Zq)1ƓyQkĪ.@{Q| cx_$46c>J:C%+B\;@;D;? Lnb]˜PP#(!Tq.Xqq$?Hi5) TNX=ޗMMAa!Uq.XI\AN@ANDA?`y3LNq9p 'JsP0n_1BTǾxF)kA8)GqCgAǻǥo%Q/ȍ{Co`Bƕ鐆A|퐀(#ԗ|DG Bk<4C4>{HC=h:}H}H}? /F3e˪Piu:54!uBBe?!C4JIn@$`@$b@E?gD`ˣ?}Ue]Qu8PYD4+NhݚE\e]!E.4JI7n^$`^$b^?q qJøi8=%vOc,BתCNcžX\aKyc9D2@ _}5Y}!([_i/R:JJ?:?p\_/?~"盫4)ji_ }_(%{6@LncO_=}}>-#V;ki` } 8a (%yv4S` qeHÁ*A{ xHЇPY`i,0RR{` x`y`&-M䆳0i8D%u*, RPJp,,1l^Oe;Kaи{Á,*AzB<<}B)f˪* 2@& ԽƾTjn; }8P(%uaRL#;G?3zHj Á*A{E})ռ!h(aTNFdNGNFNF"O^,G"O_Vכ_/=W?|=G& Rwbmf(9TfFbf>3CfFfFff?J lVmWcr/'%UsےPWDbI>KBDDDv~;)X }q)@Jjސ5*i9s,QJpi9i93iN%R`Z?v] /*ƨ5}hn}$ʜ̹OeV(%ʜʜʼ#Q/_t`2Puؼ/b3BF%6!bsJ!.6g 6g&6[4p6'˯#UP :m@9 33fρͱ/}xs{ڬ;D1JiCܧ4+7\i@iLi?G"rE!Fz]SJ3B2Di.}JB)S\\lf\&ZO+]+t な(B7Y|* KPJVq0ڦyʛJ.Cd'C+D\.@.L?`im }1e*Jҍ@&%i>J.C$'I+I\.@.L%NMoG@//;7rׇ'UQ!bzR R[PS2D.}JB)ĕ”j7`c闛;\Ÿt_8݀ :8]ӥOV(%a8]8]8dV.%W/wO7W:P]ؾA\ub{+dQ]&e2@4.V1BF?͋ߌ?=~:2@htRmd(aTFFbd>#CFFFFaFqqJP(fK~:N_~r4#9u$؊׽emK}O6b%[(ۍ#q)0?R$B~~9 ϑ %l틶=Яve!XJ9!q{{0{l9O0ʮ#VPM&lW5BP6Ts͈MX컝Ks ݄Ep?WdsCXԁ'r=~Z;A1HRփ;/WXXk(ĊI#ֱ.R2.#+k[ت/Τ?]?C:"P}yJ2į/}~B)_dܯ//̯ƇiaD kq5㑴"F9xSfl_/rwF)) Ȯ?Ƒg\ax$^O8+4Ҥ´zA/P L4JQgbQoZ@Lqt$^S𩯰fu:5Lq4CS }UŨiHŨ/šPJQ5f]h3Iqq5ӑX+F_PikUC:#wsF):T.?]f٥/unvzϜOG"[v*Bԕ: S>;USS'`NN? G+= bзhi{ }W1 *>B^y>YS*dǞx]Y1F=CrBz{b%|Q'k#F Iy[MG@ߢ;m@ʷSoPy-&[垨 Sɞԗ\]ۇHw_ͭY:V0uס[OۭP蓨܊i[1 w+&VḼfe9Ҫ[4G/Ԙ!i3BҘ!ԧ1+4\cjW5b wԻ.4o쨧B)gzb;cBX~b}}ӑ8)ƪo+N4$3d1D)Hdcc3̴JꋓvH= }RP胨K\ᖸaxLƹG $3' !cT oti  7Cpg+. 7 7ˌs$2O !HԻKXntn7 V8d;ܢrHy.ƑCW/s|iG"A8v~+ qMӮPʉ;89i2Kd "]K#dPڥ :m@K٥ K K K./?JaP_]?tsE>A U-I{l'PsOj'U({,I-I-I5ӼJPs_7g 2ƨ ݭ|HP[ve-R[[[4oW |B7p9F8j.t[+PR 0i \@s002pXS$FE+۵9R>#_q5ùq([\y\ve<.R=Jq~C?ܗuu':it}_ٶ }Ֆٲ۾-B)i÷l-۲#9rm43eKCOz{!o/(%˂o9hh 8G.mPWޖm>oKޖޖe<r_vHC־Lm[ } e[R(%wee5@Vvž\k {) >>c>E1fYcKͥ/Uw ,GZ4:v-P* q-\kPJ*q1%˫ s`QCH Q ngR҇ ώ ,աϑJ_İ5uʑ$"ҍ~AVui>JvCtiקK+U\v@vL? -J"NXK",ʑ"F{ exH ЇPn dhRRЎ%r#PK!vH]t?mI@OII gzkwSʟ3 W1,U(C7Ceh|%C!2듡J.C; C;&C}c/}}Yʑ!ƪF7 4BG%@!JI".@; @;&@;(sd(u %;KCb;K1Ί;kwӔ ۄ%G2@$Xu$Q@P㨜 7p]NF)Iĝ  G`_!$Kv?굇NF.y{^_M盗d?%>+rg]e[gϺ\G?+ WX җ z~\L_wO˻zQ_hGk_pC^ ^a _PZ:a\ n_+rwrSNz_@-RlN pZyg}"S*T+!5K-TwR:ֵ}.rlGJ96Sl@ pڊ5:")nN{'53-Tw(R<HN}qѲUt_b+6eW+tCŒb]hsΒ *ڳsֶ^hza7UﳴV|*,\hxiǤSR Z5/@$o ~&~`. ^ ?0ˡTgQi:T ^qc}pn"CI+vHtsŏVQ aW!+a8MV߾5Z}jV|\Yޟ}ۧnn>My~9:s]^y(UX;wE郾y;_ ˯Qз^#qwkʿS= o==5IQ)+7DWylVjCPK#q>\SqDFG|'Hc˯4)=̼ ʸce&{ vvXid ;C `[+ yWSd5:0ER'3g#~Aǯg K+jHJN 2{ke@9P/lCV^X{go@YgvCT<~˿Hvڡ=@ 5|5" [[G\xXي!n/6_N1M;<ڐqvM?ݿ\./ mI:jhzXbB  G>TrDVҷ4 !+4&jIFb*V04iX]ڠ$(lzXۂ ݴJ# !GoB$J1`dH9o̥F{lpHeci"aЁQF8olF(BW*+3; XyөKURV?7^|TNS,1 &<ъ RV C>*; k#ʷVol\\n+ŕ[wEfJUi}dMê N,WpCFxw, }Į䈄[+q7JNҐ+IGh(hi;B矞^]nrpsT6<Z7}"୕mT%s J3gqխ75i[=Uyɴ2NdlwBkw9ꯐӛS%Z=HkuT {+3@T1t a軕'IEWfLv 4X֥t_w )"uSd{&I*&?Z~iX7MM'SN$RG^J_ڠJ^+ljX3~:޵4U|s^Cޫ^}^ >fV୚-q)ػnqKS{I\K# Ht૕{rύ:F(—,ݳSTyˏdLLuu}V-T]8V{o6a,k1E^$ >T(o֜!/Q=|?F#zXYu4zslTtowlH*=3M%Uç'|7q̩g02_gPZ??=,U}#01ʮ#YK# IqTJ䆫N$wU2pUr$?4\kRG]m4\}krGGֻ>*r#T%wx/8^.;1wJٲ5ΰC[Rӽũ]FT0W<$vw%Ux$IN*,2 ༲>ܮ K# Ht\ˍ;Uj*<4Ah.Cs{7xzq-/MmR[԰&<} '=}W M䕆L^1y >&>u%0u)b'}/- ;g]Yk$ , Rc&{MP2d d)ch)B^vF\QӽKpH^QE _-Ӑtj,ߩR#TKҩPӼsyć-v~[4:Fx8\i#|.0j/<7ۨB(Gʼ\:hrtswf;hC'`~݆U0蓨,<" a+;##ϫͫZ;Su }~i^Mx7uJ"B]W_7@mz)b]VW4K/@( h_UM~|ost兮ɢ JM6!-˲ ˑSNؔ454&EdxBn(c v1&9*J#@vؐݎi+"y V, S LY-̐"XXQd-%Eq{dZGܪJHqAy2n;yv)"+Z7D(5PEWTQ^X0K8D;\;VVr+r((&Lr ![#FK3{ɡ~BCDkzt+("VJp((fL;eJdƈ;sl`hߑt5y$ 0*(э"׍VJp((B\[O1}~A|U4:ah)t**( э׍TJF FiTq].8/5}goVtoLMb{A(qhE Yֺ8M' Sl.즉F{ O74@C M :4|C4J pH)|֣yĻf?~}/DohuቇFG uԉ5u$ iȉO ç8| *{|M2<9{8VWT0W4$2;Uj*<@=u=SY>NU*\j&w2MdwJ˷R7w痯?]N3*kAkoӈz*k*PPѤڻ!{ػ5Jo#غlj'D&2 AnhtxLFdAZà_m㐭{llWLJ{[Hfy%r<-?e#(+޼;}E {yC6ﱱy'JPo#ؼGs'/iͯw痧xP|u}߱w+Ht{c;_j/|=:t ޑ'fRӽK]w8x}*ji=jY߸ZvE _Zke}*scbT߱/ϥn՟lQD8!VT0W>DCN !!ڇsrghv..(1-Ii ޞίKunǢEecFA~{ }e!oהU====ዝJ99-#L0S" ~^V0~~7~Jo?o1gR`Ȼԣ0u|DND+ώ,v%X.#awr Y.r05š0/X. u!x %}쯉} M cշm(kT5h"AAZ\`qzN|J}v;ߧ4{wWρ\~\u _'Q%/u花$ j}[vOqˮˊ+y_qeZ;Wj+Tq@qJ,.خz\eSTtoý+ýA>TTarN ]sg[vOsKnڗwAh0%$  a<aµF9Ј WE$֔1Ʀ.}>b >cs &B?UpĊ2 J8pUTS"ȍz21K4CDE (3"0Z5ej242@dU5eˍa"rQ,MO'!etxbM(3">ZeFIp @Ś2!ygL_2ہMOm@G'qהQ@WqݐøuwEQPu<)3?39(3.ඳ 21Td!e:BTa ֩eFI :p.E"2OvruwdO:< 2MG_ych4C4  e 9Z0AQR $w̯}r͍ki |(h@i*r,ӵe(#0Jpts;bWgmҔAtۀ)T5:; kXQF`/( "QRפ0]Ve21T!eBRܛZ&)Sc/x+ !Yڧ:U0׺cEQ[&U7J++i)yur_s:3+h 5h( IT8\*{F8\b%&ɶUz;mєAFJ pݖkJ!%|,0ʝ6A]4O$`7OBF(ϟaF )AoTdxTd45ܥ!7-sZnq(2s.Fx2.)$e >cW`oof)!2@QOk,4)#᯴c pBǼt    |X_>N\t:oiڛ Clchtiz c(C<1H.c(c(c?W9+ą!>c.ŌB-fFI11I!-9ŅÁ0ħ{ =tHǠ<2c(]()= RXۼMQj{tmJk{dm3o)جf/90 M}5 WOCnGL+Q= \>jid!O_AΏ˿O?e/ЧR]> 4}$F$~mMfƒzy\8C|RwkԴ4:յӐk+.KAbVNʉX s)Br2}ۯ_G! El' /49"OCO]v(9‹OD섹bN!G^P@=Ɩ®@H2 4e)H2aMR9x 孺5L |0׷nΏWw=?ͭp<* uy4 4$$1u  IL $1_aiߜ"j⸲@={tH[_!{o-0J{?/X+KbO 2M_Aß+ʌZ٤()C}W2WsY4ob_;ċ!Hmh.4C4 >Rf6oFj.,Ҽ!~i!8.^ċ!>ctD4462ct ƂƂ!ܾ!c_|Y`x + !NCI) k T" .IXbᒰ!~?V:e|03'DaS;)xm+#4ҢBmjm㇬m|F`V_xlm.Z-@۠6M@60CleHrᶁ!~vJabM_}75L5.x< 0@/ȣgRy f`Q{ x x 1?o9@8=C :MAtY   by%O_8ӷ>񻯷h9uI44* 1L 1Jp!Mdx|M|es 3 AaîHG}&`t%``鐌ib_feYߜ|_>Ͽk"@"c}IRӴ#4`*; #L!1J2q;;;biK[D$i:]@vBoK3bԞ5Gg?D{]ڳ(\{@{D{NL\Ie1N!n ѾiJDW".HbS [gH-87hwO@"}ξLi; j1C7,|1`1lޙwyt9KeJL)ħzl/Sj†Vy.Kbۏr!LrW"RNw]vi t+ql%1Jpknc*o!_ǯO/V:/te/_jB,vY ,,,,,Rٜ=Ib|i{ J!2WK4@C4} |K!%$FIKXKXKSLtDI}/^{>{TF)HBДhi})a˔%o)a)a)1?S18/Yz{4yJ!6[hG4`C4 }eG!v#$FInGX`GXbGd\]d[Rt90 luhtiuC\:H.uuui&eo .5Go?=?}ן<zF74i4H*l 1Jqan߄ӼC3$t Ns7ԁ5*сm,1Jpx/\r\R=^:.t܀)T5:lK %ell" TXW2fO8@5Q&4` 0D ]j((D)ge_u:P8̡} e! =Wq PQpq9!8[>P״/7P;At? Ҵ4:蕕X J%QTLU // ̐㇫GDcQ 6M;A;u  )6R8ŏ<9?É1Dx=yF j C5HrQ@&77tQs8C{}c״4%)7Ěr]֔('nM9`M9bM\"\ʷrC|+[IGܷrrķ*ٗr*:ȣqJ\1ħ{}b4:_U˯%e___e G`uӸJ@R ԽƞվkzV }k冸V˵(%uooo5@qaH=r굇C:p:4Z U'Cݐu24StO\wO:p*UB|1)˭ cj.qUMS. W~M=ʓwC݀aOB >SgZ;qj8ppw Mij ~?7TN6LiWj5o'aF+ ܈@(3dq7Dw-Y< %]l@RԹ/ǓKӽw8$zaЁ"~W H߮3-")]y(o\D1>BD D]]l=Dv-y{5T%A@v"_`P{[Ao_>hOBcc7Ch{E ~u۵Tw%]@vRu;y7vXoKoP¼cUTto~U$ :eCkRߩR#TWYU*i28WV)IVEN9rh+Ht+Eg^Zz;Uj*\Z5UyTKA 4lV5E4*\agWfmzMh3Dv-]zE 4iWi+Sq}iծd;%H*jI,i}גF(—,i=YҖ*% UCOrN* `XF]iDᠣ^i{~;ODI.y y")2[R EQ?<{\SD{/O"KU8uhW,uiA >j|.Hb A샖gZؚ/BNj |x/+55k( tАkj\뚚eFI8OCfdLrKQ,CZ 2֚2 ~[Qf!V)#0JCZ˯4e, Ŝ?P/yE퐩 §{ 4C5k( t]EkZ٦()C,Ҕq2~&i^eʒ/dڈlf ;]ҥS:ꕅXB%S聋艋8?nbLY5lՔAtlH2 KCD%J2MMk71JC@I!|H+dMfAq缝{N Y\Q"L+j(3!u]az %/B@Bg_~>;"ȗ8aiD28_)+Uޛ&Us zHPzǒ$_{Ds #=+|xkY@@Igh?O ّ#ʤ™V%dfZ fn#Or)A5fk vvNfT@#C V5mj6< ic|qjyy*4t!ْBc/?\|zy_nAbV␄-|[*9joMc߅>K7lML Sq8RܰK%T" @{2FW40Wx3dow%Uހ=ɘ*%;32|_q_ySv0ütc2܎)*z~_HC}"ն ֛ƶC5B!7`So y1帔LLI'N-YE^Voo&**ՆZPVMBy;a,HRvPQA}zHm]F_%[bZ3F@Vp.1^QfnQ:>?ݞUڅy#B+},2d(C 3IbTʐʐ%ed'O}%T2Gx4)`-䦧y{a\XtZ 9Nx"aБiӐtH3F(iHMse~2.𒧾⧗tzsu! 0/M @{pHV"aЁi^=5w%Ub=zJ*ޙr9#wM+|}~y2pe7+_WwIح@h { >JžHSC~NPrKL-SH||2Wh^=~Z`N1f;/\k-(0+= ѓLCOZ-a*Rrr1y^4GG#>n?tTtoZw_մ׺j{OZ٦JPRw XލSLa|rA1f;@a-uݰc$ :Wn4 n;cjuݰ aS!!Rt8I4x637Q;c)KA 2Z 5c {Nr6c*rᆘ0cR '=1*Eij/U:[`CV3U_fa;Uj*ܽ00D.1fƕ秥7??Isъ9=2Ţ2VQ8蓨 30 ';$72 02%ڝMiZCt|/mB x v9p}9"|6(#ᯬ)3Ě2 kjM 7 0ʳcYrI1JVS^VkrFN6=1^[ "g &卛~ʗF~c`fYhXrg+L{y}2i/5UԜ޹i?Ȥ9 RN [(ەҷzQe^2jEflcE*z|9fr̮ckl%2fH_sD}o]}ߪkt]ŒTxXR4S ާ8L4Osǧu%M[f2_FǮdFǚ9}6uj;kc7Ngz?ò%Lw{V{kHtCŒmx+%Kaaǚ%>-5 8 4*-vET0NJ*#PVTJP==5UrcIa|snKQӽő]a{"aЁOUFDzl*5BI]B"[\._~zB?;b,f3iȢ O}=Qy8} "ΈGSv'R/L3"O>mAGѧO-†:j?M((OZpծOV1❄,Y懽/m@B84‡sk CԉD56庨/wO7C T!XT~}j*};dm,\sH` 08Yh-QS:` Q{C^2uƥÍ@5a >Jr6NV"_QKLL"œS!f鋩|xə̀*  evș,!lš3 AIk4? )wUO4<;Ti}^xJ1lWmG($7y5L*)ymq[Gu1N)2}/_^=F* lXJ[f*RС!7X(%dp3DB~kHV?qe3byWd[ jH t+yȭq+AE  yYli{?OO|{X57Gb}j\"b *b) !U7!7kb X n.s˙yY}):G}&<:۸ΠQQ:X?OqMAxXZޗ7TQ@W lF5cF.- #Ҳ 6OűWZ_=t/o3(T!mk2\EXGTyHkv41E]SD@W""".Yb""#"Mir-2f@OK")k t+ ]t,1Jpx/ = ۾闧o~W @Qw 5MYOґud בБёmI=)L56R , '?[=A '? R@(fl3H` ?/R *duOn0mi7k܂S1@Nc[6C4}K [!-%FI[z[z['{ͷ@K_`Rj^\(Ħ{U}PT4:燨zKՓ%]灪牪G#t˅~Ӂ??=|] Bz^j_\7R}"^K(YRQk[p/-^]ĿFi+οff¿rq~S[.>_#d%Aptl *Bqp]Hk"RpX'K -dˌbw ,QX(N:Eu)Q(K)QZv&m $!ԧ{ K2B(Q.%jTexځcfے__/Q4.D!Ԫ{K֕n@wWB(J֮Kڵm/4J%kGJKS/RlmvuFkXȇ֨z RvM5jQچרQ;Rvn97W@m[:5E#hJk-^`]SZj~k ֎]\fc%rݑta"ZZBehץ R /C;Pvty?C^N;vtaŹ"ZRT]Fi^qv!c'?Dm[2;P1,,WCԷWBeץ6exaف²#K΁4a+6;P;,W:S-k!Bcץ|R4/;P>v|3Sf8;P걇td_k!l}Q+]jžV,5 x^+VIK;ت-qf ҧ{RZ4BEcߥh웊R /{P4hлH6ױm^!>Qm1D_-,k!eߥ R/,{PX|i˶!mV~ϛڱ%ԩ{vբB/CQT]ʾ,5JEeOʗ}|-qѼ# '\ٖ]MպBߏ*:K]'5uFN$PIǔg4w.l*Ҏ C >ۢ^QBu) >K'|F%^IX'́lETu?ؑ_=cKC^RB*JCKi(Fi.^J4Hi(Fvmo1=h.Q=#mU_EZ]`wA JrQđdF7!L&s -)ԧ{RQ-AE}*ꛨ(-éT*8m -펬)ԧ{W۲zBgeVR _={zdۏ٘Ȏ=s[ִgO=cӕNBsUZPrwYN(ŗ,=YN9{xΰOwDS6[@Ȇv.:wY (,=[ {d^HHlna?|*"J_U ף@ BMUj B x7`Y}|*Ԩ-m~QBsna66B|6I6&>hHqn˧_NϿbٳ# W:L^ a&L>taKL3| L>?3M8 T{dBz tڨzI NpFi#Aq?=_*yhWOyr\(mo?goߟ~{盗㏧w|W|xp)OI7owGwuqr?y:}9=pr7hrH֌C4S"o۞wĶ>ywѷ`Sl{i-PBv>:| .\`5JHO,1֐=w"Ǘ6}r4)yLBTSB`Jh Hr)SrS-UKs# @JE:L5/)K %4RFiH H ei?sq-/ ;P*];-^߅..4;QZ] .!Zjs[[[vĸ4YH*[N #_Ѕ܅&r'5Jpr -!.;Wlnq|Zw乡PωK#5(!t9+ωV{Gh+dII;ݜw.ߗvĸtE@+8UB]phR8s.{6X3nZ-oC}no*B7t J2y1.KLRͪ!H(Lw3m!PeZ.741^Qz3o 7hҐL`m!?|`;P %#Ci!z.tu ICui9ciHcYN-yjG(JS-d-|,h\BbSYjnE@") 80q~ HO?Qm EB o yMOTR 'oHr i6l[Elut!dHB-b (-!C!Ȑ۷12m+Ȏi ]TzJ:U]Bl R PHBr6Ց,úlڶ\ݎTyB/ҫH>9!@uڢ7Mّ! ˊx8T%B]flZu8ŒaF0Ee6sܯ@QfE;rNL$Yf&U7U9Lg&3ѓ\nMΎ=Bk4+uHI LMPSX3+|-uJlΞY*Խ%䍛"VKH L]fj*"k:o&7Ӻ<9}==~x8]^z;5ͷOCⲗo.l~k{<޽?GDcbX|*Ҽ]ZR ]:-^!7ٰf~Bw=B%ӦH*RJҥV)JХ'm [ř?#b]-ceD^ד*@-=WC*RJ󥕫V)JК'mX%y'tztso2mf=0S4N $d \ZnB4M,rz3}f~s~toaH"ZE4֏Bx_XGBB g,V*K%¶|[*æ*Z-dTCH*BPXGu UhcJV!D^~m!N~~@ ASeP/*]tbe)~,#xqi]J.4tI%1faes$/Xw/;3p![V]v=-{.[-{W;Qxo;-{ /żR귔9{IV#,,#0"T%9uKr%LQP, ָ8ψd/I|>ޟގ }O0v{p\Gx/_< :geB@ԌM¥*RB}.6/ K#)xS$qBmO YHR,h!;^D35vZYFhf&CF8~x뛾i }K2[٦MߖFjQB7v*]Nm2Q2-9B`-yO?|o\gr|X\> *0PM ԥyz! 9uaS|#4Jp99@޺xç2H1$2U/ԅiNMLSjTsTs"T30-B?>/n 5S$RwcMӥoz 9uSؔo8ڜڜ\6w C^DmӯP vSM1ԥzU 9uS8nyb\qҎ(mѩ?zU :uS8]w4-t_5'F(Ԫ{TEZ@ѩ J>NN.a!;fBnNULKQҩ (@(QPDPin?9n^vJ%UO~G׵/dmJOJ-/ti(dȓ䍙)Cr_|0B}{E:] _O]ߥF9q>>۟3@,#l̎ ԧ{ VE:Lji!t 5uZSՒe8՚՚՚Bry.G. AOBDQ,cB ao Da ۄ(FaD۟}<2~°#@C0Q-SZL.`6 QZ %`bi? Sroʰ#DoE:L}/&lWh`0a7qڢ5߰#-5E>)!QeʩC&B|J{o*'C8Dn?SYv> 6T-oilte,#5ʙ+ Еe}佼p}_JmO2th*BvaTQI2QY,aTN. v600xw7twڑ"u!臾)-^H.D6)Q) %Dc4gd/3vdF>cH*ҡeJ _P(ۅB& %5Jp eB` -Dvi ;bP1$O2U/ȓBlye8yvf(k}4/dSxns)?4M56x.4;6lC m-=MIj GO3@O3o\6~0XVhK} A"u1[)!iŸFΟffŸ)-wٍ ,vž #h= 6l2r-^6]hDF#Nf@fBr s#iŶ#[qǦP5\TC:Jqm#4Jp00Nnfoنn-n=8TCTB/A.anR 339lӖQntg!kn-|.anb Rt g 3` 3a Kq1{-+^;2P~ζSM}QBcnqriwFh6lahM)&oH5'eB[>-6xxn,owEh(8#UQBʚ eIrF(k(k&(kNagB A/(wE>c*ҡe(K _ ʚP(-Q PLPVn?!?%Cwyt!H2+-.jnbVR gV3`V3aVnL& NchTU26U rMJjqW9Un#Ķ#0wdF'@NJ;n@u؄*!Ȭ*P*%~ f0+vj('!ά`V0}7)[=|upGHv@ Zk_UEkU-n&%5Jqrn-g4ɩ_`9,C}Ǹ-f-\ R [-G ޘdmd# [:..o*/T;(e_{i8H*CJ'y|j!B.d7QQs2g?pYyCtM*=G#VCTB/AG}<(mxL!SM,X?cR^ّtW1Lv$}-{B`(aB0!ۏّv-!>o//vEaWT1kMaѥVYo=cYj?jHϹ}=<ۑ/¢mjR \k[4TBgk.\+4q-QZkZ}Fvkj=#P c-PdK  [ MdKjd+ZOgxbJ1P413?dr=b:TZ0](FhR4P@(Fn?!yoqo~yF#s3"Q REZa.#4! Qڅ#F #MxdڂxB Q Pih!zL#taiHCi4a1l[yۧ 3=gtnic<jʑcbQL a (&4 D2"@=啤8ћT[W6E & 2:Ȉ]@FlR4 H@ҾҲ Ħy{sS[-#Q-SZ`.#6 QZF$#M%ރ2n;ݞlOth*B"vaUH2UD*"aiNq-ulO!th*B"vA YH2YD,"AɅ^J~&3&1m̎)ԧ{52zB.T/ex8zq$~ C6෬qv|xyi{8f/!z(P'jX ץ(.T:x8q$6a4yA2"6{ }%mX-% 5إFjJ /GP$H7o?>>. !h"[.CoAjIW(D.T*x):Rt"f Oؑx&( rS<ЋRSuj*PkJD@:beǙպm{njuBk\kN25B/BQN] թPUJRuDJllT32n5 7zpz[9UH (E:uS:V)+ TT/:il9B03Q9ecB_vz<]ZiT)_ܡe˟;lyY禶[*_9*SH #ushr#БX>`ʿ :mԏ~in~wJ{n`P7*V ^o.|# RZFZir.ܩ%w0l²;o.Wl~k쯿{<޽?11f,>ӸayQ1۰|ey Ooy$nfƯvRjH tՀTk!\rS$LD%O5< `@ii”Β_DvUt_qS>ր$BPǝ.)JЛ=81@|/;^Dӽ7MXz62)=n|WIPZ &Fb4x^O* WChrA/+,ӃO(=Ca00},=./$SHU-lr|9Ux!M)UH[ ףvWBnSSmqd}9m f!zpwSd6BIQBFM|$4J0&lёVAgUf= 4)j]H (wFEW6xy0QXy87'=Ȇil˨E9<|[ _?>4^8^OMyե*kB)JȩK 9Fi(^DNHy\&[xے u=Ǫ ԫЁem)VS-3k!,aLLSYj 3m0CJKLm?ܾ|{z^nuOow?1 !˸ؼ-jf-""i*7K350^3,{sg/:]j }ǰ\-S-.k!tLLSyYj!1Ƙ'{SۮOYǁe sE6KС/2]2M%fQڅe]%kԖg~:=~px~j^LAPU tPK Wȣ.yT%5J4iTC.O؄k8hᠻKB3pJϠ8C WxQtyQ4 Q:&hk (0?,)J:UiG CG/CUQ1h1h(=4}ACrΔK=4+tp8-q:'7ynl;2PH8*]-^MAMAD8Fi! B8)yyŒ}j'xL# >CQMSZŋ^ˋ^ gH45/^2kacXnN2Ż9veQN#$xt']VJpTG~ە9 V.6]65 ͏6oSJn 6Ԗt?%x^Qe{姽c zUU}\N^F`נ8t9tMPmIߦ8{.Hˏ P{ *:\B"oS;*Bi'|@EsrvpёW{x:?SGS8Y\Yz"dq/2]6#WN)J 48z}м$1NsVTVtoqz[V۽A@w9NJPZgݦ8{mʝL*ϜU:[\9Jv"dЁ/]6CWV)J 48Gvd8%s뗏<޾׸s8@;>o dp8R}ccj|T(_s 8kD2Dk!Hr>S[0?-9_=w5xyV:}ww\}hƴX}G~QB(^rX־(_DxmN7b7H6$P7UkP0.+7BM javbN[XLe1."z*L[O CUJ -rRԾ(8'HPԘAa*Bl[y:>ݽy9|;97eimUJ7}hJ S]m7sW}8綛ȢlIǶyw *{=ԣSH:|JzPc7+ҡe|S _؅p&)5Jpk9oȁ͒fYN$>.1tm?rxx 뛝9u-~JܶљOv68^+>+Ϛg#0{RTz*{Ц,Udï.Ѕc-ڦ(.9_)΅սSvœ9.-vs͎QvL>+>ܒPQN{#ensembldb/inst/gtf/0000755000175400017540000000000013175714743015304 5ustar00biocbuildbiocbuildensembldb/inst/gtf/Devosia_geojensis.ASM96941v1.32.gtf.gz0000644000175400017540000101630413175714743023620 0ustar00biocbuildbiocbuild0IW]-;^rPF򛄯z$C0 kPZՍV &seD&©>70I\_/7l_?0:=??ǿoqk?^M?_ϯu/!z?ݿ/?K+/qKo?/%a????O/_?ֿ'9ܯ8~e2noL= 쟾D_/3mx7Q҆Z[()_JZOD}:_:; qJq"A"DSs).gNEEtR*֎I-wpaew8+*ݭDX*A;u7{}\ȻOaK∏_P:oGW+{\gZoU/Fd#FSa+!XLV08 .?\7Ttg_GNvv׵|ATJX\?pQYfm y\6>ꐞ`0K{|dgG[qS/HdJx5C.񁓝mm;v$,%@BC`mk#$ABR$6Fz|9Vx.?B$,%@B<.??=N? yfU >},]?rxm]~| !\QMOW<$7%GU> }XtΎ:$$,%@B;|\Q#=2 q aK{?<F2r~\WHJd܏U"* 0gfСNUfx\{R{~sڇH9Vk9>d ُ?猨&(_u7b<./Jsڇ/u@#';; } Y>??0..ˬm$pΓ纵B$n`NvvUj$,%@BT=~fY œAu O{>Ft=Ύb?^[Dn/@B9/`Fzr/q[QMOװqy#5շI>},ݷvdgG[ھ a)}k#* 0)Je y+_&kTڇ!ZÑms?$ #Hs^Jpqe6 ǃB@{>|~2pxsd2HXJxsm=oR0epz #J+5?}PXΎU>F?~r+u>'`c,a<~& ܪU'z>tHhq]{l ׏ϑ8`!\LY0HWR72-GWz>|Ύ}k AB<.{<+`!,a<0/TjK;9Vx!@rG KI6?wQMy<x2H7FۗV^}PXΎU"ABR$DTr`Sf|'q;?<0`!\|Y0HyCC9jlYhdgG>Y|i<,bx e6 dqJkEz~}tm~.|$d?.W\pYfm yL'jNvv}x~ x~<+`!\TY0H&ؗ3NZ+C@,|h+<^[Dn@B<.{<g82kg8ɾMy@C`mk? !\+82kg8'{?<|9Vx.H_JE#=bچA,(! t]ΎuH@B<.Wr/qe6 dq]-1ޏ7_GNvv$ȭH_qe6 ǃ參},]?rxm]| !\+`c䙵 ^8_^ݭnC`mk?Ȕ \Qlp1Yfm y\ _^\! t]Ύu_$$/`JS|p Yfm y\`^{Gե纵_9GNvv@ZAB< `w*ˬm\Y:q\! `9㶶^Tz>缀|qe6 ǭ i}纵_q=>pxm= x,VFzf qg|RO>׭},]9rxm=$9/`po|\pYfm yKo^>:/R>׭},]9rxm=|$9/`p82kA{ 1'%\\! t=Ύ) l !\Q=3+uS>itsڇ/#';; s$H$$%@B<3r<~e\7c<̡>׭},]9rxm=Hs^Ja8KY0HL~غnC`zΑmk9?W@B< Lgq:ˬm\־|'{C>| :W3D񡄸qMg"{wlQ.?Eɵ 0qswO}O/ҕc;; v`B qS"ϯm(t(@}O.[stgw:ψ &,5`*Wz.~ď؋t7CT/o?vrLej2T8>?devAF;/{Q!F3π N91WISaB-NO䃌v:DLk Ӎ|8iI>'aӝskk3Lt:LW!Ge>hCĄ+],X y?ONwEIF&O o>HLjy~mCtcHaiy?~^oΎBm&dw2t6.K4|tgG[>9'a6c;; v91|0!NdewAv_ap9]YC@>}"5X#;; v91l0!NwϝAF;/̘R7C0'd",ftg\6&M>O q6_T~#˯m(\N7ۚR{ާd"ftg\6S1am"+ 27OxRn|3I{?~6C;;;Ww| IM>Jm"+ 2r3 ӝ y}O/Y>rcpzu' &Ȅ揌v:Dk o[wWj[nzA#;; ׿D8 |GF;"F >6!w#/aNC;; WwB08y'/d Vfg߶O~mCt5{uO Eþ>pcpzu䘐 qzC`ewAv^./KH4 _HGNwvN#L.DŽ&LӟבFVjdS~IRJI}V`Xae&ٟ?KDzhƪ{TW~ҝeDiW|{K])Fs;T~./UC;{TWf? +>{/dJAv}_Px;뼒z3v?a١ӝsӫf8rLej2„8yldevAv_AmfJrgho N  _fNwvNT IM>?.hK }Sa=c3~0tUC;;;=TWJcR yldevAv_?^.[c87íOofpΎU&m|F'd##چtK}z EXjvtg\ t6?}#ge>hCϯm(\NA[ޒJw?ok=tcاW'B IM>}ٍS~շ)ҟwv4Avoӝsӫ{DL6DŽ&Lӟ.h_T6.#VpI}v4߿o5D?'uX6}7XOyH}H'B WWOJWY;Wb 1h~.o#n3twMŷ61aiywJ킌_A~7Ir3L/% o++Կ=rLHjq]N1d2.{cb{ow?a_GNwvNE+rLHj8+|lErzi!,V?ei.C;;g/](#&cR &._|œBr\-7ΰ-N o +odȗ`By#Њ;21bD_P.2#v&Ou E8,6p9]ijjwtߧ_; +^Y8b9&,5`BpdwAF;/3p9݈s3d!] C;;gV-0!ӟFt>hC?9Y s_A>Ir:F\ޫsO /Kk>tcxR~zz&KodRS͘ #چ1cI/O ڽNwvL|O >lN%p9=9 K}z EX7ΎսS&Lӟ.n~W eI!9݈vAᔦO EXttg\: SLӟב~!ܑN#چ^Qo_npoMݿ[7ے|}D?S} 宇>woS_\q/𡴧z`|~wtgT1rK <7 2W~UEΔteb0c`"ص{b t[#b 9&,5`*nVv_APɔtxg!iܝf{>ƺ^C;;}z^1!OWd 2W~m'71 \s{`"#;;;]1aStѰOVrduƒAgON~0|~ Y;; WKf0!tjd7NOt.CIwԙuߧGNwvu䘰d yt`vAF;_$I!9"nOQ~f/HNwvNGa"{8y?/d’UflNcچYX%Y Nwv^8I|0!^Zevz<+ϯm(\N>{ul EXΎHS IM>?G h{ qz/y.Va_/HNwvNG O]LXj8y?Jv_-}.ka |kw}30|]7tcpzuﺈd qu+c3 Ӎ3{M{ _{ +^ݻ0YcR &{tnh_C={aJrJŏ@?nm+^ݻ.b9&$5`Bw@F;_BQot2vzp{zWw?@.Ύ]H1a.coJ)|“t_AD ݗqtg\O1MLHjӟe.h_CFʔBr;!g~f/=NwvN1l0!N+R #/0p9]F!{g6`"ȵ{x tY 0icBRy킌v;$>S ӥ8]M1⻟A na+^%D2„8]v |N%p9]y?5GC;;Hk2L{0!>9z#d!bL_PnaKթ3X2tcاW{\ KM6}~/*ٝ)V=d?)< _e:1W8]&#LӟFS6hCby~mCr;tNyj< _ş+^ _d qzó`ewAv_!HyRx;ݻ8dt< _ +^%äLӟ{y#f=2鴧O~mCr1y>~/^NwvNa"$8y Ytz6ai^G>~/]N:1W8%8=v|;T6hچta  A>aC;; W`:Lӟx#O6hCĄHLjy~mCr9q-)~AvΎu&.F?#Bv]fy#qzp*ϯm(`ERvCs~0|֮#:1W84D}f q:72 olNy~mCr`WxMc~/uC;; WבFL*DŽ&Lӟבx,f<)V1 lPԻҡ9G?kב+^]G$8aB 6hCby~mCr;E>}"]G:tcpzuiLӟבN216._sAvΎu&(&Hu ؤ_Px;="B'sA`2rc8⃩tmxr!A6hCyo lQN?#F WCxC>'ac;; 1Ng q_Ȏ6lNy~mCr9qyđS~}O.^7ΎN׵rLWh>Jǽ s8d#{B[|lNy~ HnN[E7ߺCřΛzv-"4` &n) ww_i dvkI~1vPn)8{Tgwkg)/DX*ATz?G HsǤ tp@o" 7١Vb++FsG^ppEj/]JkIm obuvm#$0B ~=38:ucpH+X)q#/1P+ ~.17T|1Bґ#1*/gZtNN˗Wǿ\_ >nC0msৌaȆbΈ诗{" ~\fN;k;)ǿ\E/7١V?7)/FH:a38ڄi3 nfNҋ8'PZ/ro&ʸΎB.Jl !5XMԂ qqX^0p)({1`KSFvv}S9 *QBҒiO,"lBt\.^7ڃ{1Kvpͫ|(mXQBlELD9˒k&Xr͛ǀ._6U>Ƚ9J}CD|aC9ʒkg9A%tߛ7_q |lg\aV.JDQV6OĬ!F&dɵdpإXG&͛ǀ/]WFvv6)l(!6y%2m~&WůL!615jǀ-kW+P.9#Jk.bp2!Fw'l.L/)[zǀ/o(+l^%Iňbo(^ɉmsH#K} $KK*7,Bǀ=Z;IKu%F'-;$^J~aC9˒k;j=S~TP%Xlg\a/Jޜ%+/b{!b!,l~4:~q7okW+l^]D>7C 9b7'PXB/:Htߛ7_8WؼW/Jv(!6o4++(b!`D\@H6NXPS-Ok :py@)dC yï6~bw6?ˑǸBH6wpZQ}o<| 2ryu/J:%6ÆmsȴC [Cѯs!F<ȒkjH۶8$>| 68Wؼ%Aԩs=y"WhCZYr!&n_ZAn7okׂ+l^] Dl8QBl"W@FhC,l^ZKm(t?I} ]=4ryuЇC ꡋx10*K} $kK;tߛ7[w]=4r{Q]=Dۜ zx^=t+1#bissgs͍*}9qt?I} %Xg;; WiBF IK>6Vnb76Oɥ=qZ[=ƴ5֑n7okׂ+l^] )l(!6^ YML.!V_8LOkkׂ+l^] %Jׂ͟+7!F<%\f! k¡-{1Kv-յJJXZy-hd7!F<%\ML!$xސOq$>| ֮9Wؼ(9QBҒ%kA#+ 1WrQwpBG>~\%Xtlg\aZPddF KK6?&HK>֑;'ɵ_kAGvv65G8|(!6^ YML.!V߾[NIrc`ZБpͫkA>dC ZlByJ.o(2l_Fŗ t?I} ] :ryu-h҇|(!6^ YM6OW`a>1tߛ7]v-6յJJXZT\<&hRx'NSn~\%=h{+MVPBҒxXM6OWqSF=e~\68WmlF KK6yͭ~bSr8-dsw/qt?I} ]?ryueq'J͟W_!m#B/&(Cv~\%Xlg\a%:-PBl"W$b!`t\@H6Zɗ=p[By%Xlg\a%M%J͟W'bʟi0&K} 6OB\炶_+Gvv6sPBl"vܜdžmsH#K} $x蒕" >| ֮9WؼMIM(!6^+ub!,l.[e_0tߛ7_+Gvv6Sҁ̈b1_Am'>͕LEa! >| ֮9WؼCLK>?쿈6Æms%>ae!5ma7GvvCo(FJ.%JH7#]\W+dsczY Jt?} u>-#g;;yuHfC ٛ?YM6OWz+dswHj✡炶]vpm.DJ:%J>-݄m+I Ჹ_MrKsAǀ/Yl>nyue2JHZ\<9:6!vc3J>ia ![ ςuTV\1Ks󁳝p럛%QҒ % ́؄m\p%71l<|3s%m炶_+Gvv6JVdC jbC y\q炶_+Gvv6OVPҒ %+#cbͯnEm 炶_+Gvv6쏔|F IK>?쏬&h+)ds5d|âc`pͫ+DF KK6?쏬&h!0lU|k TebsAǀ/ڕ#g;; WW(QMQBl"%gmB}=g[͛ǀ/ڕ#g;; WW(PBl"f!mBmkׂ+l^] )|(!6^ YML.RrlBd炶]v-6Wյ_y-E|†msH#K} 6qW<:Lt?} %o󑳝pͫkA?fx|(!6m~+ubc,l~N omkׂ+l^] D4PBlM8*y,:$>.{_^zOR) >| ֮9WؼCiy-ELxGmcB/^9I/\1Kv-յJWf>??10.K} $+m[v?} ] :ryu-h2JeZ2y-hde6!vc3JPql-Lhtߛ7_kAGvv6J^ddC ZlByJ.+dscXg!c`ZБpͫkA#%QBҒ%kA#+ 1)JtB9|ד Htߛ7_kAGvv6MVPҒ %kAm TWH Q=dǀ/ڵ#g;; WׂFJ.%Jׂ͟FVvbW!Ny&ްOkzZБpmkA?#(6kA/bp^Cy %>ͥrRFPIrc@,68WؼC*aD xnD y|6Yr!\όrKǀ/ڵ#g;; Wׂ~QTe##Jׂ͟^ʟms%>͍R*\v?I} ] :ryu-UȈb絠1OZm#B/KuۖOkkׂ+l^] D5cD Z71,p| ֮9Wؼ4R%,-PBl4R?mds:A^v?I} ] :ryu-hd2JHZy-hdulByJ.3lկ#kY$>| ֮9Wؼ4Rr%,-PBlXٰ 1)JoByPSq%Av5ΎB&!(Lџ׃&dJ>;gC416ϯ}0NkCjM7D_BwvZ 8):=pB2YSĝٍ!fBb`.{"t?]'@!fo.f7p* >=;f7fy2R:[Av?i'@]?vMuΉ,é4y^ >ȚQ6n1K24eS~2 |2`v٫;> K>bym`w7+cG/=wvf prR9',=pB/@.n~Nek;an6 j4(vE9{uMd yu\1\fB^*12(꿠+~A ˆ|8!{_P#mݘ=X W )P5F? هwvf߳GN6焥'Nڅmwn.  i#0 |3vî0{uO9'$=pB+ KWG evMOնd2f|g]a02NXzᄘy˅]ݘJ1 J1pl/6zKCu?'ᮽ f9aWW̥|8!fw fF]ݘJ10\f"1a1c;; W799l8!f5愵 _)1L1\f7Z'd2,7f|g]a19!ɇb1܅ٍٯT.[b㺵ago vC;;쾛wL KO6JۆޅٍٯevU| h1O(e7˰Gwvf.9|8!f fXzf7fR >Ȃ-. wqHd2,]`|g]a9aɆbK]ݘ=X 0Ő.cbKK1O(eXu|g]a朐 1{C */6;ŎtdN.C“Q˰x 59aɆbkf7fR >ٙb~J1(eנ+:נFN!焤'NCC jwavc+o2'> |A:aW5r 9',=pBPa]ݘbmv%|sO|Q_V߳+<س'sBғ'iL˞wavgbAevcbKi#?-ow:aW KO6={Cwkf7fR "p9+ydcQ7՟ƌ+|8Q3[\:&C̈rî0=l8!foٳ_Cgvcv >.|M:F?-a`C;; w8Qfg 1{CG73rgvcv>.~U_}߳(Gwv8l8!a]ݚ'sŐ̮>L@8?~]b^1r9'$=pB ܆mw evu[MQ8t]}I眐é4ka]ݘJ1 evkNz_q +}|g]a^NQKpB.Z̞ X|>.I#RSF/wvfqTzᄘ㛙01;ČSl Ϥ*߳_{=+^1D ' | C焤'N o=FXnf7fR >ȷb̮hg {ߟ8tafp"|8fO}j7#!01;ČSl o;=Q_6tîxS 8#焥'NӘ`6Յ)V?$߻"1`2>rî0{}G'CLJbvb >ȗB01;֑>.;_8A:}W'q +}|g]4Rz2=pBƈ_6;f7f y2 @? W* +^_8NHzᄘR):vavg3b0$\ttV1`W{=+zN^d y1چmwAQf2;e#iF`A:aWkP2NXzjP#, _)&+O9F߳.>b^>;p?}8!ɇgox=²01bAevxrL={(e>t}IO',=p*gX2WՅ)g8Cu 7}2eX#;; ׿qBғ'l;Hb [K>F/ +^n p: IO>.n~Div. wPLL7~0 |Vu|g]azD KO67a]ݘ=X <1$èa)?y^ݘ.'܄'ݘ.ofaό6{;(Qo>37/zo_>}>la*E{| Qa4_~x86cRyG|9a tx)?QBOKyǿuv170RFH:acD Hi%c?WRSNn_7١0Z#a#FxP=x? .K=lʇ$T4xY:;Ծ[/FʼnQ79fK@rip,ApüL|ti7~ >nC؃#,0B[&bp@%EL+}BlB8[G|#o|P+Aߌ֜!{p'/'1EE}j]PKI oZ:; eFKG6A bp@E<\_2"8 /b{[G_qsjFIG>?%Pm‹~L+EuId + BN*xpk?7١V980FX:asp@E<\L*z(IJ8)yfih+~4* II>_3cGVzbԂ 8)4Wt)ދm򑳝p~Z@Il(!;+ 1WrASBH6yRx|u\F7_vv66!_C }ns`e6!F<% d !VI'`cm󁳝p]O+}(aiɆbs`swM6KxaS̓/ q qy]vvoJY|(!O['1ul6W瓖B18}o<| ߛ+l^7W>>i%JJlBgrA_PBH67!`[}o<iGvvOZ[x@2-QB4tVzbSr@ B3q'{1Kvڑpͫ;hsOwcD 󞵑݄m\|(!{s摕܄m3╪ y\}p<޼} qlg\aJJXZyD`e&ޮ=\!\6>v'=ο/Q6Iw{82xoTweDUFD{Յ}r?:T޿:m?J#*wDJǀ?[ Y*~%xp&^QB~%xϛTub7N'>͕:,\=wKǀ|;r~P7R %$-PBϻFVzbͯRR*SK}ܸ޼y 1rlg\aꎑ,aPҒ %;FFVzb76?KyEۜ'dsCF9sMǀ/]iFvv6J)|(!6ޕXٰ 1)t:u'ژ5Nܝnݜۿs{-G/ʣȤ;`&w?s6?S\Akp@_g7#"J{OAX&5A?RuŇ)aFdC>f{4h}Zc(!0>}{oV&}{J.v͝=Kzus~^%X*vlg\a%KbU1hC,l:AM޼y ,o/~QdZؼD+C59C9̒kL)-knc#g;;UP"ćRisX"䶔 11`D\@8mDА5K)Lc@-n󑳝p+mD%JeeQ/bp%mΆms%>ヶRIKYl>p؛WPmΆ7mU'FFgɵdsLH 0_+l^CM%]J106K} $<\:0_?66g;; WwP~bD N_obS4!vcL\@lO;WNeSǀ/=\Fvv6D=iaD .14is6hC,l~ro-c`.#g;; Wpȯ|(!6ML!vc\@l5ѽTe~ S%X=\%$-PBlKdulB1 xKBH6YPי[͛ǀ/ڕ#g;; WW%%3JXZyede7!FJCQmɸBl]xi=閻S~[ǀ/ڕ#g;; WW%/3JHZyede7!vc\1xH3pl +7OVPҒ %zH<9r#m~%\fͅ;K废K>vp޼Oˇ"Jy\9mcBxie5Dv?} +Gvv}P"߷C^+U ʇms%>͕S0}mesǀ/OZvv6EܛؼIK"WRdl61Yr!\[^ژ3;ؼy ]?ryue4J͟W_ʟms%>͍pGrwn7_+Gvv6S2Ȉb1{s6hCZYr!;2Irc`pͫ+/J6rŇbobV4!vcOr!B?<'ɵ_+Gvv6HyeE ;-l6 Yr!܋XsdOkkW+l^])l(!6^YML.%TL!$mM?~\%Xlg\a7%E?7C D,^_A#mȒkSi 7okW+l^]D>C |ms%>|128r\1Kv-յ_,7C Z71cm)b76.O} \6bpd-KsAǀ.AXtlgwZ%zy-E DFmcBU;G& >| ,`󁳝pͫkAR82JeZ2\<92\SǸBl|{X $1Kv-յ(!iɇb絠܄؍ň IK%Xtlg\aZHIgdC ZPc}t bͯ: es8勉Tǀ/ڵ#g;; Wׂ&+}(!iɇb絠݄؍N ! _M htߛ7[2p8I P2%,-P*lnByJ.OZBH6. $'ɵ_ş +l^XE IK>7ϻnEVjb%=)dsyZ$1Kv׭pͫn}(Q(!6uM ORC9ȒkNQOknq+l^uC!ňbs`t!Ffɵds|?Γ,Okkw9WؼVd3JXZy׭JnB1J>nb !\65ث'ɵ_n+l^uC:ˆb].bn8Ňms%>S$>c[#g;;྿rTwPӒ y׭qiM|61Yr!)_7t?I} %Xg;; WwP"w|(!6m9l6QYr!+“u?I} ] :ryu-l(!6^ zݘ 106K} $ e:sXu?I} ] :ryu-LK>?M:11`B\@8m/^NjkIޛ_kAGvv6P"_C ZЋ\mB9Lܿ2Pn~\%Xtlg\aZ%2-PBl"&#!FeɵdsYW }o<t 68Wi%+3J]1Ÿms b?ɵds-L(G=Ok~C]lg\7d(!{1R"C9LȒk&X'AT&޼y ]?ryued2JXZye?R~b76? TA,W:炶_+Gvv6OVPBҒ%+#+ 1Wr E7 Ჹ9f {12pxn^҇l(!+ WroB7F\0: Gw?} u>-#g;;yuHIgC ٛ?YM6OWg̓=-c@@ݧelgw>-@I%,-P*m.i&hA8m '炶_qm>ryuH)dC xns`%6!FJ.R'ql.\/c`>-#g;; Wi\F KK6?YM6OWU0p33J-mki9WؼOK2JHZy؄m\p%L!$#0Kc`>-#g;; WiP"@PBlOE̤9xm'>z_$vOkkW+l^])ٌ|(!6^YM6OW{̓qo?w?I} GJ!%J͟oYM6?+^'-L!6՗!u?I} ]?ryue3JXZyed6!F\~)ds! dWM-OkkW+l^]ER<2yeE Ta>hC,l.UNIrc`ZБpͫkA#%QҒ %kA\p%+BH6W]ER$>t ڵ#g;;\Vׂ~(Q\2T\>ܛ!F\65B6nf[-c@,68WؼC9Js'bp%_cC9͒k&h N9IIrc@-+boJ:WDC>2fC9Ց%>͝ z$17Ե+Gvv{HfdC ٛ?쏬v!vg\.ds |?>PuIrc`pͫ+#%Q*Ӓ%+#cbͯ҆+dpH~Jn7okW+l^])l(!6^YM6됻AlSqM~0|֮:1W?ä0!F^ݟ+ؘ1g`3!O}0\f \s? ?9aWӘ'i N[ƼIG 033*O}0d_;+^%#F? >=;f7f:e3ia-6O(ePkw{;a쪺˕'$=p*ͮw|9a]ݚL1 W !|8kutov}7 fٟ?Ou_5a.3=rdoD}to>Eu7ro?pR01{JAy!]F®HHg֟_(+^HrNXzᄘy'ޅmw)R{P='d2,^q;tî0{}mrNHzᄘ6r01;ń&L1bPA=d2,^q;tî0{}mƉ|' ofAeavcv>.-|XAfaQ:aW?ˊt IO>JWYev+@s~2 x/vŞBdrNHzz)DXnf7fR >Wbap{oy(eX}>rî0=R䜰d 1{˞`]ݘJ1c3 !A;]x/v{)$=edĩ4oa]ݘJ1 e cŚ<Ek(eЫ}|gwfN.焥'Nu#, WcHJeIt?'A,f:aWwMrNHzᄘ]4`]f|P?$sp]3wT[ـ?iu+<0Z朰d ybvewavc+ 1\1\fG|Sp6F`6tîسwN9!ɇgoa]ݘb^m xM;} vy+O9aɆgo1;03{J1 rev7 Q7{=+S|) IO>={CWAfg2 !Ɓsd͌6F`W7b)䜰d ٳ`]ݘJ1op<1\fw!\H1(]|wv{.Ȝ|8!{.ۅٍٯ"L1\fMƑMfo w:aWorNXzᄘoewavcbc7 %?iy?i=iL9a#NӘ=|(hǘy2kq)t߳` vC;;={}l8!{of!31;ČSl ٥4;\iy? nq+^ߟ=r9'$=pB.n~|2ROcGuZ9iLsvgpғ 'iLsvevavc+ _Pb̮q`ҔcQ7+#'sBғ'dП=’01bAbP:(?SaC;; gl IO>7gXp f7fR >.L1\f&TPNPF.Yf7]|2NHzT4tX6WZ?S 0٥NRoi'o`2eXC;; z8Q0℘]<7|P'\aF=ƌSl م >:N? w:aW#XrNXzᄘ#X%vavk3:y+R{?pO(eXo}ctؗsBғ' }c", SL. >ƁJsO(eW* +zT8+5N[ J_Aavcvuv>.kiH;M:?~]b^] D'd]4f6n1c^*0h1aJv+2NLO67T*}732O}0\f7^nT͌F/OcFwvf48|8!foy.̞R >ȟb>#(MYQpa+^7&rR9',=pBTf.C[[msO(eX"'sBғ' ", SLirC29DE60s'o`2,]`|g]aIl8!fo.a]fD#S !q=?y@.]`|gwIO'$=p*n DXvf7faȂ-fw1A,f8aW@S KO6, ;i S ٥>q'o`2,]`|g]a)Ȝ|8!fo.a]ݘJ1 dn1 =aoΜ#ۧ_=m>jWzB=۝ iȉw_1E)7v Z |;&:glqsI7?>/8zæ:; qo3q`>T1s؃T>?h^RQjaܭ#+B=2} ml!]ڃ3 ng&lW*Vo>4xpuu >nC0}Gɉ>|!n.u<c ^ϴ! ipXe`S~󉤥[G P& ৌ!ȇQe3*/gZ|ipc{Yi0{7o7١V{oe7l!{?軅P=x? .Ytlȗ"#g+7=2Y'Ff .D@FHCOZ4SBqtJ=xpniP+ ~K+3m$6O :3E8I}$;^Aпa_:qLa'"?ҟ]a\@]TqΕ+HA/X_߃bjÅ|诸*(t{hTu8:{kTE;ewa.FȝawHۧRb7\ԿuDZ^ׯ_ >lCۛ70j'FzQMCA=3Ë6xMV H!$}:|,qmī[!I8FB[ / r2kš~-Dو{1`K&9W __ \F IK>wףFVbb76? TIWBcSAbDcokW5+6uMJ;9(!;0\={b!`L\@H6"~Vncokw9Wͫ |(6C ٛ?4&&'-lJ%>.;+_B@U}o<p޼I P2%,-PB OZބ؍+տ+dsX}WK?Uc`{JJHZؼao&h_%9Wͭ=^B@`ia !\xIp؛W7TF KK6xns`e6!F<%\ɷBH6΋1Okkw9Wؼ+͇%ϻ\J1`C9ʒku?} `lg\a>_fQ|(!6M0yl<HǀYrᴹ:/u~d^%XIOZޔdNcD '-1R-Jmݑ%>ͅeR浏_ |lg\a>-R(!iɇbslB)Trp[M6OWO WTܼ1Kv׭pͫn%+}(aiɆb] mKE{AH6>@֘"ܼ1K 5reu׭HIeC|u+m ͍55V+C޼y %Xg;; WilF KK66VjbSru7֊n~\%XO}Z"%QBҒ%DVjbͯb7楼[͛ǀ/}ZFvv6)l(!6ާ%Rm kL!$nLCoXt?I} ]?ryue3JHZye?Rm~&W6g ᴹV_x {1KveՕ(aiɆbۄiwrIM Bv 'ɵ_+Gvv6쏔|F IK>?쏬&h_ɥ#;BlM#%JxXBgrBm[=>vebo^])ٌ|(!{ձ 1)JByPF̡'IK%X|o>py(l(!67&h&NՇ9s"1KveՕJJHZyed%6!FJ.͙BH6]1K֮9檺?R %,-P*mWGVzbSr?7l.;46/⺟=>| ,`󁳝pͫ+? ?v%托C|6YrᲹUeTG?1KveՕ(aiɆbJML.RrlњMu?{} ]?ryued2JHZyede7!F<%\_ABH67n3wjkW+l^])l(!6^߄m+Aۜ'޺~vjkW+l^]ٟ%J͟WGV\pBH6Jq sKy%Xlg\a/J Y|(!6^J!F&O} $;A&1Kv-յ(!iɇb絠Ƌ6!vg\p%0lϚ bǀ/ڵ#g;; Wׂ~Q|(!6oMmByG8{ܣn~ZE%Xtlg\aZ/JJK>7Ԃ?11`T\@8mea喻*[߼?77noѷ7y.?/V:lBgrA!H { +-S~V%Xzlg\aHgdC mByJ.Q!Js)v?p} ]=ryut2JHZy4چm\p%ia !y_6|[c`葳pͫ #%QҒ % #+ 1)J:By2Pnjk@+l^] (iɈbБڄm3bPB8mۄy9!#Jk}ǀ.l>r는?sQ*mnׂ^J5'Cy .lju{-c@k?i90z)6gCySJuYCY=I} $T[>vebo^]D%JyeE TP>hC,l/,)nǀPvv}ߛ_|({s"vT?{>hǽw\@H6?+j~C]Obo^ݧC|‡7ާ"Wr[ʆms%>|qVY]~V%XO}Z>h7y\'-l6qYr!j _MO^wߛ7_+l^ݧCtJ͟i|ms%>ͽS'_+l^ݧC|n·b}ZȘ {'>.G&߰;>7ټu 5WXf;; WiP"5$W b!`t\@8mûZu?} ݧelg\a>-J䯠|(!6ާ"W1bc,l.P/b$炶_Fvv6DŇbC1miudɵds<̴8n۾c@6GJ:%J#+ ;+uW<,炶[68WTUiIVPBҒ%zH<9қm Ts͍rNY >vv{z7Y_dC ٛI 1Wr)Ove !{ ' sǀ/}ZFvv6D>C >-1k,Yφms%>ap)v?I} ]?ryue?P2%J͟WGVvb6?7:N+ds}PvKy%Xlg\a~|QҒ %+#+ 1Wr.^JCǀ/ڕ#g;; WW(Q QBl?WN>HǀYryʗ NOkkW+l^]ٟC KK6?V2lBRo(rloQt?I} ]?ryue3JHZyed%7!FJ.f.R;$1KveՕ(aiɆbބ؍+}K !V_[*Cǀ/ڕ#g;; WW'+}(!iɇbۄm\p^ !\y^AGg Oknpm+?ȟP*mW_Ĕl6Or!x+$1K n`+l^] D0\nlɒk| ^$1Kv-յJ!2(!6^ &v!Feɵ婳Bǀ/ڵ#g;; Wׂ~QrdZy-E 6{'p\ǡ}yYr? k׃+^]9sғ 'kBOXzf?)vg W ٕ>db~2 |֮ ;aW:rNHzᄘy} KWՒ+gG9D? k׉+^])zrr9'$=pBVevavc+ev0d'd2]3:vî0{uI地d 1K]ݘJ1anqƁ߳]vf9'==>J5fJUlݘbF)}7fͽmQ>p&) c J>oSN}C~hOFH wqmj`'͇SI}y3+llj fdb`x݉ړ%(eXo|g]a2m)6?/b朤\ݘb)>AP=a^?N6Adua)N3O5Y2{P!% @={(eXi|q2Ƌ'-OcT 1bvgvk<6%=81(eXi|q 1{Ә,~O1sSl F 1? kG;aWARΉNٟHbDWFn.e3iFҎ?7}\aͤ|)I_Ml^[ Vqn˔3![2E7ϛ8}і|oM.O"+y_D SqwoDrhhf :U>.7U4Q M]>.|aw'u2e5X=UƔ(~ܕ)rq /|OĶ{soXy}!K }ؒ/ e|goZ|8%*f&V6n3&O}0uVr蠟_;aW/N>Zq1yf7fy26>Mq|9#Q_oa;tîx"T6D> y lݙ_Rl ٽ ,7{(eX-l3N䞝' -lܬavcv_Rl ك%᩾cӘQoa;tC} ی̘졡,~aF=ƌSl 0M }1(e7˰هwvf q"_ 1xn73 Cavcv>. -Gc0 | 4tî0{}O' =D< ;C{rNXzᄘ}KWq3[ ٝ9o b sF/]rwvf9S8!fo#Y_)W.po#> |B`v{DN:焥'N]cMݘb~nmv:'7*? נ+^_9|8!foAavg3ivաc9%"waԡvkP#'sғ ' 5K]f|0\fN8PRLD~0 l>r{G5D0T=34Uˇٍ!flb`̮Tqw^o2{(e7˰GwvfA8Q}cqB.~1Zi\ݘbF)Cr7n֯83z_mi5_=U>j#WI"#}}5^_(?!6#_q^҉@nKc/{;{Tgwkۇ* R y m Ey)8ݭi_Z --:rNrw8+}$s7 DH*A n E)o%p[^^n]MuvmΕ[}|a\3Q>twp=npmݱQ!%9.)Pe[pǹww\:; w6Fveq}o- סs8 >9 n˅){7w7\_=lpm "2 B}= sw7'\!V'!p& I}wpuaSgodo&D?"w'\Kv8"6㴃 -D8[æ:; w߶}!"7|!vq|fnɩm>$v{}wpu=npmg~!R "=w)wxdJt8ز:ۇ.z=~8 3HHJT:YMU:WfDY .eilrVz|dgG7Ux< l л oYu[0a0{ݽZu';;ڊ'*q@BR$8]5fy/ y\K <foz?Wi~#7 0';;ڊxmq$d?.{<|' 0."ˬm$,\$t3C@or*';;ھes7$AnRϟ\HCNYfmRݕokNvvޏ$ABR$JoYp2e<o#^8MmxXΎ㵝>>?mu+L 0.2ˬm$wAHC]xXΎ]|C$$%@B8>CoK99Vk;~ Q}jAB{^ll/qe6 !\T J~ڇ/UFNvvDj$z0.>ʬm\xi]~ڇ.Z.dgGwںedz\QM?3 s ǽ>}񁓝mk?zNFFzEf 'CmrOjk9pxoH|s&`p8ԑe6 ǃS]ڇмt]Ύ}ں$C$H*x%fx e6 Nü)a-!7ҥ=>r؏z8H~/` Tv>HC,a<.+ y?>|2rxm$+2HWt`!\TY0HWҸ҇}纵_h+<^_ #$HWToYpj2HǔyxnC`*#';; WW@B<6HC,al{#';;ڊ:?Ⱥ|>:^J#="چAPV5R^o~#7 0';;ڊxm$:%@B/`.b2kǃ;t:>},_edgG[*$$%@B},]?rxm] \/0lpYfm y\[c=C`';; W?Di$ϟ'`p~Ofm yLmUޟukK叜h+<^[S?1xq]!`mɬm$ɢrWz>|9Vx. N$/`0>HCNYfm y~ڋ`Iޏ7[y8VwXD7x[0.:ˬm${u],؃z>׭}1|h+U>%H~=xWr/qe6 ǃe>nC`*#';; Wt KI6?YJa8=|3v\! tmkDH*$HWvFy,R=2Hp/R|sڇ.YΎ7U82HXJTz<QMO$+%N~uG\! n`Nvvˏl II>?ϑYp%d< /cWzǛ/u#';; '!} a)uY:Tq ǍȬԹnC@K?>rxqg yYG$[+“^o~#]Ύb?^_%B $,%@BDTv`Sfu3enws׿̓—;l$~j@0xIcvrIEOqחn(e:鯼?-!Hr74!t#$$,}@BW#* 0)70 N\"pzF>1ի#';;ڊ_jW#$ABR$׀ի 0:Oǃ/+TTU|HۇHUwdgG[Ul d'6HC,a<.pR4!7ҥh+]>Ȕ ُ?B$I 0^,apy<&URQާ\edgG[~:$d?J&=y\`!\lY0HW2>_Hۇ/񁓝mǫf 8؍y;d<^HMv}iX+Ύ];2HXJxqWJmx,td|Ύ]"AR $Ĥ+l)q'żqWzF>| 6rxmWf `Y.8meC:JxXΎd"$AR $㏻DTz`Sfb y?\38Ocxkl}iXΎU>d *.(3To ..3JHۇ/u#';; GH!$HGTr`̂+;'O"1T]J}ih+k| KI6 >8#=2Ft]Ύb?^[$kF \4|pYfm yLy~y,]?rxm]$8`^ƒq.fٵJHۇ/UNvv~t,$Hǟ?WIJE#=9ud qkpڻS~Ǜ.[.dgGwں)d{\QM2K${!4\&ukf{|dgG[ں/H܏x\<L#=9ud phJsڇ/u#';;  Z  A 01\\Y08=n>׭},]?rxm]$A$H_Jqd6 y{)\! t]ΎuHv| !\+`!\LY0HÝ\II~}[b9GNvv}s~ U@*9/`p%lpqYfm y\IwrAynCoKW9Vk|A:ȭH~q \8`!\|Y0H?a纵_h+<^_ *0{Q6HC,a<p nC`mk b? uo`7>FhچwZ{+C`mk? l !\+#`!\lY0HwڪW0Wz>|9Vx.H_J#=g6 ˘x?}[k2p}*_dJWG#`!\lY0H $=nC@,|h+<^[Dz$O`J~ax e6 Nd R1}xX.dgG[ںHXJxq]~D%6vqs^s$2Hghg$纵_GNvvHQK_ Y:\$+mukK叜h+<^[D>W \w#=bچAq>V.%ukKsh+<^[D0sFzEf q= {~sڇ/#';; sk#$Hs*6vY6݈Awx06Pb}ƀ/Cg;; זtFJ*%Jt.H/<68V./ EXstg\!1ab՝'+ 2_Q ae_˟>EZ}Xa&ٟ?OⷮuG5Ywڊ)JH;/Jj'-w%D_w0k]);8}肅[Nw}%V昈0,ֺrGF" ӝ_ɥ?fVpΎծ9&LE2 olNQy~mCr:LCeӟ _^NwvN|1aǵկ٭C($C+p>'aرӝsk`3Lf0!N\A& OgtzL#ϯm(!"O}O/c;; Vf$yL~ݴgN&$5`B>6*9]=kxRԙ8d7ާd",]';vcpzmI瘰d qZٓձ 2W~6>O a=o'd"H!natlY(T&#Lx:X]N ڧ3p9݊#ڃKS~2ƺtӝs> B$D IM>}>w~\v= c8/ݟ_;! +^ !)Ä&LӟwB.n >&tȜbѸZ?^sAıSkf:;~x/D?C!'B}E!;fYb/),K (ہaSg}- R F HsǜfNwKKc KgLw8+},s7 De*2Bn .gNr7Sꥭx ̽u~=nx`rKf #=ybr+& .DE#\!V'!p>ęmJ޷QJw3qSgkLN\qQWNmCtD{}w0 Ҳ7q0Jw_ 'Dx #\]|a+!p?ݭoK?7qVkwI>}'.N6(w#ϩm #}y:Xz=n컻ENE6Jw?,}るr7Ċ6Nw Mux7/nOB߷ߌ+0B- KjEl8<)y7_΍MmoODFb3#:X,#d9e6 Ǖ%4|۠Y_ΊrdgG[ۓ"~)|C" 90cFzEe 3Yњ|7Bޏ7_·';; ߞ{ :2$gC`OJqȩ#ˬm$"֚! ܙx|dgG[!r!O@B<~ F>Wa8KY0HFûJxXΎMpS }B,(3 t2H?^m>~y,]Y?rxmm}d3HHJxqu}D7Fz,\\&ޏ7_GNvvMx/$HWGTr`SfiG~'x%qiJ! tΎu) | !\Q=3+\'R8ةuޏ]tΎ5H| 8/`p9 bچA"@ 3y񁓝mk9?*%@B<.{<;"82k0oFJxXsdgG[z/HZxq= lpYfm y( wr+r! t=ΎHdJxq= ~ 0."ˬm$[!.fc+C@k?W8V~,3x3_o|\e q}I#ޟPek~#].dgG[ˏBLIFlx,${+6T嗢3翏fo$XiO౺&Qj)P[@{¥D1 mEݵҿVPާӵ_=Rq/B arx܅P׵=?3 B؋A_ZJKg{T>|B0rxm$:F?Bp+gY0HJ|CJxX Ύ]>g;| !܅Wqe6 ǝp Jާ_h+<^ۅHw!܋Fz%Ϭm$-KNWO?jj.#';;ھ{\v!@g3Tz\=B+\ 01\dY08= QjJ! n`GNvv}[ ZHS_JE#=چA8xii GC@Kw!9VT=v!@"T==Bp+u`!\lY0H?E+SUӏڇHΎb?^/H@B=qe6 amhCuUO?jKw9Vx$㏻\ L 0.&ˬm$V[wާ_h+<^ۅ$㏻\JuR82kgh/! =z|dgG[_%>?|Q 0>Dd6 ǽA>},]?rxm]$d F{|9Vx.?Br$,%@B<.(&h%R$+ \Wz~>|9Vx.?B$$%@B<.?қ#=~eUdy .$O?jzm=k#$AR q]>~`̂+}/c yܨ"KGx7 0';;  Q0x\|9Vxz$9/`pqe6 ǝe)vC@Ksh+s~ q> >xWqe6 ǽqzƼ{?<FNvvjA"ǟ{<+0."ˬm$B+uk~#].dgG[@"\+=`c,apz<%=|}纵.񑓝m~HTI#H~Y8qdY0<zY2BUxXΎU>8HW|6qe6 Fw1C>},_edgG[*H@B<"{F{e6 ._Vi뉺|! pah+<^_%Br$$%@B<{PM?3 TSJ;ۦ{?<|2rxm)dd *Ype,$kaƞQ>},_edgG[*R !)U"* 0)Jz'q k#ߟ}>g0KW9㦶 H*0FzEf qN^}>g7 0';; W@"=q \X6H8Ofm yܙül8{>l{';;ڊ: g zaW`!\dY0H?RRs.'kdgG[IJ╬Igx e6 Nyۗ>},_edgG[*HtJxq \`Eɬm$ Z}P^}>gX.dgG[ں/H|Luo`R=d6 .dqR+{~9ۇ/GNvv}>^x \U#=چA,NiAk|! t]ΎuHWd>?˿Ƚ(`c_,a<ٛ-! t]ΎuHv| !\+0.HC,apxz?~A#H{ \b|pYfm yLgWzǛH2r؏Wdǽ !UDGY0|2rxm/HHW܏Fzr2k.傐yC@._edgGw*HWd>JU.`p^82kA8W/a9ۇ/Y8Vx$A@B<.{&},]?rxm]$8H'`JE<s2kS1|! t]ΎuH^>?]${`ǍYfm1es L9ۇ/u#';; $%2HXJxq]~D6vY:^ DžT1!)>},]?rxm]~d3HHJxq]~DulYR2 .:[^oKh+<^[! l !\l3?{o y\+8+lX.dgG[QY[! | O}`&H_ehd?˿p﫰Fzr2k '߃}>g/Dk{|dgG[\_@B<==2k坶T?l\!7ҥh+U> !U.`p82kNod9jsڇ.[ΎwU )Rq `!\|Y0HpHOkz>|ΎU>h-x\< ,^glQ"چq7Ƀ\! tmk| [+>?r;g82kBz R:1\! tmk| )U.`p%_a82kR6Rk9.>׭},_edgG[* )U"* 0gfU y\⿂W4+C`*#';; WdWAB< |p Yfm y\;`n\! tmk|A=U.`p%=qszx'qk5D3R{>|9Vx.?B$$%@B<.?қ#=2 T y:P}Tmڇ/#';; s$+3HXJxq=gDulx,1HP }PXsdgG[z$}F?缀|qe6 C»! 9㾶 ZKl 9,0W'apy!>c@,&8W3D(2\ȯ6lNy~mCrG|R{gd",]9vcpzm昐 q Гٍӯf.k'qQ}ls~2|;1W84D~ qj/dA>bv:Dk ӽ0:=c3~2| ;1W8.dsLHj8qehd%.hKrΓF| _+DNwvN=1|0!N\%z2 q_F]xR j _ENwvN1E#|0!N\1AshC'aC;; Wt IM>? Y]N!6vz1qTM}&O/ڽNwvN 1l0!NX  O Z|yOvϧ EX7Ύս2LT#LӟBv(->>h,/qzϩmV8^} [{+%wΎݷod~#"ZpBm'.E[VMWŕnyy:ro7qV͓݀!N'&=p9I?OaUƒ>nLrw8+}In@>Tdq%S{H־!%=^u˟7C—Ϟ$?'I֕J59w,D)D(^`w.Ļ>'JSyxb+~o3<|muܶn!Hg/~Tv`ϼ Qiʕipqx;]<tr'f~Ύeo II>J20* 0 ɔYߍA0B+g_! n`Nvv=##!;x\< ,ȳFz%d qc<> xy,]Y:rxmu$M> GqFz\)> Ǖw%Ĺ0! tΎ%H@B<Wqe6 M Rv{Ǜ/';; WW~A"S$kP0#=ᢳچA,¦ޓWzǛ/ҵ#';; V~ g z7F+apy</oKץh+<^[Dz$kS/`p%2FzEg pxдWzǛ/5#';; V~ g :  lݽ \tY08=.yL0z<|:uGNvv#HAd Јmx,32<>~ >wޏ_k9GNvv-HVfd j8oY:b/p'^RݨDS.ZsdgGwz$$$%@*=sFTz`ǯ̒w .cl! n`h+<^[! l !=&hW OZh6C }>},]9rxiZABR$9#]2K OFz k">ɨ},]9rxm=g2HXJxq=gD7Fz,L$CC8+\Sڇ/#';; s~ i2>?缀b82kŷu dߦ'_9GNvvv!| !\ys~ 0t8Ofm y+o:Xޝv[<<|9VxJIF?缀FzEe R9hޏ7]񁓝m=A=R ,^Q|Qᢲچ8oRB}o~#].dgG[@AB/`s>HC,a<.+C`mk OV !\8KY0HJps_GNvv@"xq]"OU2kǝ+Ks{#';;ڊFH6$HFT=~f\^ Ǖ⥌ВJ9ۇ.^Ύ׵U"$ABRqYp2HF O.{>F#';;ڊx_uL#H~0Fz%d q{C?}[Y8Vkd$$,%@B؍cfwȔA bAv\! tmkd} xq ܋FzEd |i纵_FNvvL KI6?vvqȬxz>2epz|2rxm/H@B< #=چAx0^̡@z~yGNvv}@"[Tz},]9rxm=gd3HXJxq='1b<ko^Fk#(>},]9rxm=g3HHJxq='a`Sfz)qX{=|Pu)y@C`zΑmk9#$AR $9#* 0)qߺ4HMyy@C`zΑmk9l,? zΈJnx,߈ApnϑhKsh+<^[D XR/jFy<2k|Y#m1t~>|9Vxz$9/`p82kYjIyy@C`zΑmk9 )U`F?缀z0SGY0H?mջ JxXsdgG[z$:%@B<Wr?qkZ? qe}񁓝mk9?h-x\|9Vx3Br$$%@B<3қ=~f\7c<~u! t=ΎR a)Yp{1H?zaH>׭}9)dxxxD7Fz׭}Ύ$AR $Tf`Sfd<W/wWP>׭}Ύ$ABR$M?3+^~<:Oýy?>}FNvvkd$$,%@B?QMQ2 1HF@ÓukK9VxO$Gsxq \)6HCN噵 qc^oK9rx) l !;gD6vq'>Ŵp}[XwΑmk猐TLIF?3=~f\2Hp{9skusڇ/ҿsh+<^;'@"$Hǟ &ĤСL$q8Gk{>|5rxmf >Y+A=[b yּ;V>׭}=>pxgd yYpޡg y {U{>tGNvv}w! | wFTf`Sf|>ΓA"5H.E! n`Nvvwl != 0Wf )b<!^{>lԱ~|dgG7`k=t II> >xD 0gfūڋq2^gy~}t龵#';;ڊxm)dd ُ?[QMQ2d1e<.t//qP^}>gXoΎ}k:2HHJxqZ/U#=2K-V e},_edgG[*H*$\JMqe6 aްFSsB,|h+~}_jy;xLY/#=ᢲچA6xys.'kdgG[Dz$d?O pQYfm ywrWzǛ/[';; dAB<{<3ƒq6HC,a-z>|5rxm,$ | !' P 0)J“Ax;jKW9Vx$$`p~ 01\TY08=؁> {j~zΑm=k9#$ABRq=gD%7F{̬>K)q Y{~ڇ/Y8Vx}Igd xqLYp%kZy2HΙWЇ Mڇ/u#';; GH>T$#Hc`Sfb y\*F6|cE| !ձ 0) t$<$ x*7[Vvv[+JgD ٓ?+U<3^|\P8m'73q 5%Id"ܵHӝsk{䘨bEFFBvt+k όEu_:o2|2vcpzmߕd&;|!hCua ѱӝskkDsLt>?BNy~ H8^8{_Kՙ?z錄'||TgٯQw8+D~vS.G]r҉ON mȕ8^/K舼[G_ _=nC繾ߌt瘿O^p8" Ѣ?igC[9b{P+ ~yn7#r·b71B" ">ig(9b{P+ ~bnbDס=8^ A2xL#{:zjasj ~/ج7Q'E<I}pyi&0[u8~quv}07>0Bґ#a^SZ??/dp+jC0m__Ow+0B ~! yhipwrh#/w/7١VȷoFS>ߟ<:*^!Z'A S?&Nu81uv.Ln ayE . /-V 8 Ml zo›/U';; We!y| !^y iq6ze>N^g%>^} ]9rPyu}L%+4/bp%!Feɵds+y ]9ryu #J͟WkiO'pyІtKy%0U#g;;[o7%iOm~+}B즇U\@H6WQ(C d>c@,68WؼCLK>6Ißms%>.w gG4>£[ǀ/՜#g;; WsFJ>%J͟WtFVjb76OɕjvlgF){7okWv+l^]D>iC ΋\'-l6QYr!ܘCudl1Ktlgw_A(Q1T5  10"K} $ &I 4]?r؛WW%}dC ٛ?ۏ&nmk B*f?{1Kv(aiɆb5لm+n'}~[ >| ֮9Wؼ?YC IK>?珬&nl~&\/(L!${O+-c`pO[J:%J͟GVbbͯny%_+vv6!2JHZؼXM<%qP'qp\ /)4]g1K;-#g;; WDoLJb\Ďx?쏬&h+yKc !\YcbU0{1KveՕR(aiɆbձ 1)JBء1Kv-յ@)>i%Jׂ͟+7!FJ.I?ia !*/JV>| ֮9WؼCz%kAߜ16VI} \6wRo;E1Kv-յ(aiɆb絠҅6!vg\pBH6YW{1Kv-յ(!iɇb絠ձ 1Wrd1.[_2xC9Ey%Xtlg\aZ%+#Jׂ͟^ļ5Ta>hC,p\ޙPg_kAGvv6P`D ZЋ\Gl6cBV:;Aw?{} ȵkAGvv}P"w|(6kA/bpjC9L\@H6Wǡ=Eǀ/Yl>pyu-Js_Ď6Æms%>͵.DR=>| ֮9WؼC:%kA/bZ]mBN5|âCc`ZБpͫkA#%QҒ %kA#cb76? T-ͭupGw"o?w?{} ] :ryu-(P2%Jׂ͟+6!F<%naKy%itߛ7_kAGvv6UNGF KK6?V"lByJ.R\!${VR!Av?{} i8/JP>JwZ1Z!F<Į[By0@kK=>vebo^])l(!{ބ؝2)8ivjkW+l^]EI;M>?쿈'gCyL#K} $ KKM~P%Xlg\a%I J͟W_ʟms%>e%J͟WGVfb76? AH6op3)-c@@+6WտFJ!%J_A#+ 1)J=B9{i'1K n`+l^]QBҒ%́܄m\p%Pd ! wt޼y ]?ryue3JXZyede6!FJ.a/(L!\6oj$1KveՕ@2-QBl?2yJN.xGJy-c`pͫ+#%QҒ %+#+ WBW;C$>| ֮9Wؼ?R%$-PBl?2m~%:9 ByCkKZwy%w?],`󁳝pEe_cQ*m~ObJLJi0yryxxA$>vebo^](aiɆ7^߄ح sQ?}/sdvP"J[pK7{I7^J~Qe W`v/+#]\1˵vY*(=x>H%่懀QYr!\^VJI} ݃glg\a<JLK6?s+u"b!`d\@H6B ha-ϕjk9Wؼ%C>C <16gC9ϒkZ0$ϕjkwm9WؼkC2JXZy׆jb76O%ϟ|vln_pW)v?W} ܕZ/`󁳝pͫ6|(,>6OJ6cC9Ȓk6(Rn7okwm9WؼkÇms6?p+ms.hC,l,|3 Rc` #g;; Wwm|FLKF?YML.Rc\!${c֘@ukϕj{4̵67սRE KK6J"+ 1Wr@| Ჹ?ޝ+6:*tQyOR+5R,(bS=7zOd']~+0uBr:+i}7˵7Y*TPjQBw\=Ui0*K} 6puv?} ݃glg\a^ J%#ó'vcsD\@lrBjO޼} `lg\a=J&%ϟ\J~aC9͒kByj"cG -Dlk19Wؼis>?cp+b!`l\@H6V/iTU;T?ͣ;lH2? oTwL"JvLؔ(ry]+-]hOg W`K~dZk,w J[D|(!w]Ď!vc~\\@l7u_ ǀ/]Fvv6)l(!6޵!\>ϗ+dsc s:Pyc` #g;; WwmTF IK>?YByJ.RոBH6w:htߛ7_6+l^ݵ!R %,-PBlkCd6!F<%)vf !ryu%%/bp%7fC9LȒkBǛR>t o׏+:T])|(6߮&nl~&\L!$+7!S~k} Fvv{>_<7C ٛ?cp+Yʆms%>|VSg_+l^C|n·b} .bF'q!Fdɵd3_JR>| 2py3!?dC yÓ`ulBBl4ѝҚ)v?} aׂ67Wؼ%;\Ĭ#UC9̒kp3s^(j1KveՕ(aiɆb؄؍SriO͙BlzyΟ 0g_+Gvv6쏔lFLKF?V-L.R%T\!6=+HyArwJoy%Xlg\a~$dF IK>?쏬&H_CҘBH6@AG>| ֮9Wؼ?R %,-PBlXmC\R\!\67@*~%ܼ1K֮9殺?R2%$-P*mWGVzb76? z3Z[͛ǀ/Yl>pyue2JXZ\|?sFR,yTsZٟ?˹y##L$Zc#t܏RÕ|`W`׽ڊ ]ܼ1˵#g;{TQ߮TF Ia>#cbSru7%#]~0}iNwv|0gk3„<[zޙ&!W1g{ձ/gZipHA)wޭ#kޯuv}38 ~lO}fpO݂i3BEf4H /Y[G_W:; ™21B n"Tb^ϴҩj'wJ.t۾loBP 6A7M_O9t?T^uΙgNqI vB{8|=xp >nC0_N-&f .yhqwZ4sT^ K[G_D:; ?Ǒ8'FrbWlOΞip{>NGTzo›XIΎef/HT񁄼|,yo3!,pz\PדD%䛔1RމJ|2p~>M|FR#9Q "&7 b6eɵPJ[ǀ/xXl>nJms6'b&{s6l˒k̓!E '*a6o띨vv6>QQ"m·b󿜨$v#mByt -c`.|lg\a&Ϳ(YEJELn@ކ,p<Zi3 H/uT2Gwӯ `VCU7#QE'Q%}s?:\GtZuƐ.Ky kFvf| (O1)a)̆J(qP1WriAճrlnD$t)Ӝyr{~,szad`0-ď)Nq#| cw7S8ٖ-~׷SDC E@'R#K} $[/Gxu8-| u ]N2ryu=M|mχb%93wb!`L\@H6)ZId7_/+l^x _ؼEL9 [es1OȤgEoﭣŸ?6Y|0CP;}u3="޷•lIAjY} bKA i}XY,D(_$%H]$] 1m7ϒkͥ8Cd#;-A%XqխoJPBlyCTmcBN)Qn~N%pk79殺%Ƚ9JS1mB({5_ |lg\aS7% >6IKm'>.;' *C?PR> r%%Qoy^dIh&%%!%%_S))6 :T  :;kw[9ٖ-0ր^Ĉym-{œsl!<X}zaz:c-L۵xy3,~q 3If.r #0ݱ+g-Lpbplg[T)QGQB0[ ~;|[0"K} $/JJ}yǀ/_ εՍnJdZ}3X,eO9Βk*QpK'wݏikw9WؼcMܛ}ǚ-[m#efUXs<̈B2|U3>| X3ryuǚ/JY(!6߱"W=>hCZYr!2*ny:wl<| ֮9Wؼy69#JW_J}χmsH#K} $Wմ_Gvv6)iɆbU16B9ʒk0q pPj~c@]?r}uM| ̇Ris;/{y8\\@lѽ[͛ǀ/xXl>nyuM9JEObp%l6qYr!Ki>PdV1Kvߔn(!6_+bc,p&>| ֮9WؼD4PBl"WMb!`L\@H6?'E;S~c`ZБpͫkAoJPBl&OCA,p<(i" ]g\1Kv-յ7%%kA/b"еl6Yr!\kꝦ\1`K`_(+-BDÈRa4ޗ6b6NfɵޛQg]?r؛WWߔȟ|(!{1mcB9qm5y c`pͫ+oJPBl"C 106K} $[svuOkkW+l^]MIPBl"WhCZYr!&>pT-~:ewl<| n>pysoJ,F7<7OJC9˒k[1Q~1K֮9桺D }e"ss>HǀYr9L\{@O_m>ryueMz ̈bs_ČO.,p<;h[w?} ]?ryueJțl(!6_YByAH6:4Sc`pͫ+oJ,F쿈|ms%>|1ZXA޼y ]?ryue7%C %+/bp gmB9L_k~.h%Xlg\aoJd$F"& b6N} \6bI >| ֮9Wؼ |(!6_ z+ms.hC,ln4[ >| ֮9WؼD>7C ZЋ\_3l6ɓk𱇡~\%Xtlg\aZЛ%kA1ҏ#mFdɵ|<,Y$1Kv-յ7%Jׂ^JnKmB\s'FFgɵdscX-c`ZБpͫkAoJPBl"WN6hC,l~拵,Okkׂ+l^] MɐPBl;Ȣv6lϒk.NIr$1Kv-յ7%ro·b_$U>hC,p\i^=$>| ֮9WؼD~b1?6hC,l~Nz'stǀ/ڵ#g;; Wׂ~S?NC Z/b<;ydɵNB #POqMǀ/ڵ#g;; Wׂ~S"Ĉb1'Fgɵd 5RMǀ/ⵠg;; ׂ~S6Y(!6o E b6N} \6a[$>t ⵠg;;~\ׂ ySBҒ}-hdulB 6wt?U _*1/"~wH6xĮ yTF6cY`SȭF}ucɀDvƄ= ވ>t?JFv}ET() P*GI"Wl10yr!>6ݏk~]WBuK!#JȾ}K\l6Yr!w! 17Կ>Ok󁳝p޼E&%do'+k 10!K} $%0ݏkvv6ߛS"C y<+7gC9Ȓkĝ|1Kvpͫۍݔȝ&J߷?106K} $}<޼y nllg\avc7%'3J߷"&'-l6YrᲹÖMQǀ/Fvv6n7vS"Ӓ%ۍ%bJnK#mdɵ0q>^؃,y:5}@o_G/_coH2O߮oT76Ȉbؒ(ry-r'wp {z\1%2r7KPGF Ia>{͟ BH6&ƀ2W3o ǀ/Fvv6n(aiɆb"]6OCxBH6W@ hs~ͣy@2O?;WCU7۸{("="-"WO/G)Ϛ{wi'~a{.Ky r鵿>9ٛηH)dfCK_+7!F?%\&GL!$e[uRn~m%k9沺O3JHZT\YM6O $[+WӒacok+յ(aiɆ7_KYm n3Nk^n~mxXl>p؛WlF IK>xos`ulByJ.BH6?Wmk9WؼOd2JXZ}nByJ.oLB8m'wrc`#g;; W\FLKF {#m~%\BH6֛OH~ ~?2 tc;;~]UWg0|8fWkQa`v>.C_J*~?2 |2`v٫E#'qBғ'Jʰ G ×e`%{>A[fo kW+^];z)ㄥ'NW.̞.6Oyb2Gv6b_Hwvf#̑sBғ'+IOX0{2{J1ve~hY>=a7zӿ^bJ徃f` ~J2ey: :z%ΎVBD|x Qa4W>q/儋rsjeU&+w?R):x?:; w?~[*{܈Tqxn E;\l \-<,νu8@=np'aNwc\Ϝ [ !}n /6wΎm3wk܈T䃨tjۘc\SNR-n'?.8νuspΎbi`n'܍KE6}WSp!< >Hņw8+]6|!~6=pQN9u?Oڏ;vLqݭ/w6qV "gG`]ÝS8Qo|O_?6qVnaIE>w?H=p98BHI>7#=pCCMKG6vF+OaUf:ۇ/ҵ#';; GH6$H_WGTr`de,;q ǥ#JZ! tΎ㵅QHG KI6&cf y<~ZI+Ǜ.Xj~dgGOy2HeJ2Tz\Tv`Sf)qbcE#8! `NvvHQ7$,%@B<.^{]Ĥ+g yMG^C`jmk$$%@B<>#=2 BzɔA=$8! tuΎ a).Ĥ+)q A}ìdxXRsdgG[ZIe j͈j`SfÔAx8T ){?<|9Vxn !a)וձ 0gf!dpz\?SJ<|9VxJAB<ngچAf/y?>|9Vx$㯫9/`Bø6Ϭm$KG*lKsh+<^[ !)ձ 0gfA߫d<iAz>|9VxD>& z \3#=g6 Ǎko/ t?Gyȥ9GNvv!QDz3Tz\缀Gvh82k6ֱJk!{?<|Ύg"C(g x "[F{e6 !HZQ^}fXsdgG[zA$H_s^!g lpYfm y<] YC@/Ύǿ!Tzܿ~cx~g6 N@i+l~#].dgG[˿!)],Fy<2kC%}gX.dgG[ں)dd 3J y\?JA>}gXΎUnHq>~r+| 0."ˬm$3̽lK叜h+<^[CS $/`\W;a<=$=s9ۇ/u#';; ߐO@B<.Wqe6 ǭp7 C`mk#$AR $6F{,d}hqU_%B$$%@*=^W&(e=ΓA &|s}[ 0';; WDb xLKNFz%Ϭm$+'^nC`*#';; WH a)U"* 0)'쵵Jsڇ/u#';; .$H_GTr`RV ulFJxK?>r^qE KI6U^?QMOCĔAgjk ޭnCoKW9VkDH6$H~umx,^d>px/H")/`F{|2rxmoH~$$`Jx e6 NüW/susڇh^#';;ڊUj=~C"V| !߫F{Ke6 .{%>F.nCoKW9VkDH:$H~uJl1q ;nC@@/_edgGO*ߐ4\u \ lάm$bWg+uka{|dgG[*ߐ q>Odlgάm$`F;纵_h+<^_&; *0`#=چA1foWz>|2rxmoH|LU.`&~yqȩ#ˬm$Cȏqj+C`mkoH$/`p%#=g6 a+A}gz>|9Vx.DmAB<.椣n||pQYfm y!PMsڇ/u#';; CsFZxGY0HB}}xnC`mkoH֊$ Kz 0.6ˬm\CXC`z΁mǫ9 a)؃!U8}La|! t=Ύ !).(_W8SY[9! ΎJ a)RqJox,g y\ "@kwP^}>g0K叜hqS[! | 7#=2 佌'qm5D2+C@<,|h+<^[ a)qj`SfA2 ǭM9ۇ/u#';; Ar$I6`!\|Y0H0b:%asڇ/u#';; GH&$H_GT&H_ދAx^|{nC@ ||dgGO_O@*=??sM(p Yfm;'' {>Ftm~7$Gs_WFzr2k,0{iY_\! tmkܐzN>r+0.HC,a<.}0Wz>|2rxmul0#H_W|1qe6 dqxr\! aNvvrC"| !w=܋Fz%Ϭm$k+Nn7Wz>|2rxmʊ$\J#="چA= Ŭ̽ukK叜h+<^[ 頵u_6hg 6]KI{>thq[ ܏TzܾWr/q|9Vx.D0xu] ԃ(>HC,a<~&^PnC`mk!^F|=e6 a! Wz>|9Vx #H_s^Jz 0.!ˬm$k#׈Q>׭},]9rxm= H_s^J>S`82kFo msڇ/#';; sސH-xu= 6HC,a` z \0lp3kNůuasmsڇ/#';; sFH6$H_sFT{>=92H/ nukKsh+<^[ ~0U#=چAxë@{>t#';;~zsFH&$HzΈmx̬xbxZ \0W:ۇ/xX9Vx !a)qJmY:b/J9ۇ/#';; sFH:$H_s*6Fzz>|9VxD z \#=g6 <\̓WzǛ/#';; sސhxu=0qP=nNdpyܚqWz>|9VxDz$9/`p% #=ᢳچA8ܤ'C>z>|9VxDxu= lp3k0 !O>},]9rxm=gd3HHJxu='a`?30^ {?<txX8qd3HXJTz;-&Ĥ+q ǃ#` tpŖ4?DȈ']+\ 0gϯm(\Ny>}",]?vcpzm~n1„8u =212ϯm(|9].Ky9}?2|;1W8?g/0!N]#9|=8] ^N}NMﶺL>^jkɇtv)8'_/BCN~/RHZ܌`mn,!pZ[!|֒ɯ>Y):rOUro8+D%Hѩb)O\R~.ݐNǝS8ݭ ѕf[u|evΎV|N}n E;\އ\ 6ۏIN>u>ɧ Bu8?OP'j,s%B]ǔ g;Dž4v*uh{˓vjOy|ÓS9!B)ow}J¥6ES VĝS8Ul ($e'̽Ϝ{TgY̙/D"Ͻw:z2Eb%˩m҆xѕTu8z27qV#s/DD7Nw?cFܝpIGat4+n҇mȻu P+^>6bt0BͿ~nr fwL#Km#ġw o~ ]~𑓝m~&Ig م?wG,QM?3 i\$ !cA{V}=>pc7B#$H{6Fz,!7cpy<#D@[/rΎ5ߐʔd s7} h2gF ǕVxy,׃h+<؂98@r$$%@B<܁8+{1H7_Me*C@y|dgGOW*= !)Rqw8:6Fz>phU| | O}q@e6Fz,EWa yhFL VRd.]?r؏$)3HHJ_GTj`ǯҒ|G` ew! t]ΎuIH7$,%@B<.?3J~CϓA~X喙ݻOVpK叜hqW[! R w#* 0Wf@=Wa0{'4>zǛ/xX<>nxm]~ KI6wBM?3 Y2Hw 鿞*!^},]?rxm]~2HHJx}]? ox,ڈAױ"AC`mǫ a)uJnx,R}2H?OVZޏ7[׮8V|wX] T II>_sFT#=~fVq NCQRZOz~}tGNvv#$AR $d?nYp%<$K2\"һxXz?>rx~ #$H+jZ2H9W#:qݻxXΎU"$ABR$DT#=~e~'AשvWz?WiOΎU"$AR $upxm]>@"$Hkc`SfA{1HwpU{7{?<|9Vx.? 醄$H_GTz`ǯ:ٛ' E{~y,]?rxm]~3HXJxu]~D 0gf؉}+ ʒ^C`z΁mǫ9O!ݐ zN@7Fz,A#qWzǛ/';; WsB!a) 0)=Βk纵_9Nvvwߐ zNYdpy<H躔纵_9NvvH6$Hs* 0gf܏d<}k \! v=Ύ_'HJ2x}= 9Qچq}h#@z~},]9rxm= ɒ)_ x.ˬm\ɢJsڇ.@XsdgGOzRu= =0.:ˬm$ +GK! `Nvv!?@B<.^{<fLߙ q)|fz>|9Vx #$H_sFTf`SfIG`g y\?Z|^\!` h+DDx;'`6HC,a<~&J +uk~#].dgG[ǽ| !u_ W`;apy\iEv6|{?<|9Vx.Dn/@B<.WCM6HC,a},]?rxm] $/`&q{&Ix2HG9#ޭC`';; W?H:$H?Tb`$;pWz>|9Vx.?B $$%@B<.?#=2 1H怭O:g>},]?rxm]~2HXJxu]~D6Fz9.D$H \%{`!\DY0HNQДWz>tGNvvu@oH| !u@_SpYfm y\a>FG{>F*`Nvv*7$r?=|qe6 d1J9ۇ/UFNvvrC"xu \#=ᢲچAm{s_GNvv%H_`ǃYfmxLwWz>|9Vx.D> \Qlp1Yfm yܩ >[E}>gX.dgG[ں$/`p% FzEe q`?lK叜h+<^[C !]+[0!άm$ü'C`Nvvg O`J<Ee iVs_GNvv˿!QAB<.Wr/qϑ3kB/2+X|! t]ΎuR a)uYBP}2<<ɥyC@@,]?rEm]~3HHJTz\ˏ&h$xƶU0+C@<,|h+<^[! l !=Fzgk?8VW~>\ II>JYp%=ΓA9Xnuk~#].dgG[˿!9@B/`&50|pqYfm yx'w!3>׭},]?rxm] ~$/`p%c82k^x W纵_GNvv˿!q>&|9Vx.?& a)u3 t^ N纵_GNvv˿!| !]+L 01\TY0H'y>}[X.dgG[ںu #H__J#="چA,N )>׭}9GNvvs~CN>_s~ٔ|2kcES{>F#';;ڊx7$:%@B㯿IlJ>Hx۝Y0H|}xnC`ΎoH$ \#=ᢳچA,0EIޏ7]tm?=.kܐȭH*0FzhچA6|t?纵_=>pxm\$0b 0.*ˬm${ /ukK叜h+<^[ ɐxu] F1qˏ&<3 TZ ǥpSS纵_GNvv˿!K>˿܋FzEg q-]XI}?z>|9Vx.D}u0c82k&m: JxXsdgG[z%6缀t>'o`mY0H!"sJKymsڇ/#';; sFH&$H_sFT&hWq+ ofzΑm?=nj9#$AR u=gDe6FzʬTӺ!@xH>}=>nUC$$%@*={PM?3 ~/ިz>|ΎuR a)qM2(,$)'؟J9ۇ/u#';; GH.$H_GT#=~fVߏdpzށW3Jx[KGNvvk a)|~<<~e\id<ׂ~^|!7ҥh+U"$ABR$d?JDe6FzgXΎUnH| !_W 0..ˬm$rJ9ۇ/UFNvvrC"@B<  |p1Yfm yܪwr缠~>},_edgG[* a)U {x,ߏd<~}X+lO{|dgG[* !)qj`Sf'qɃ5! tmkoAR $*7Fz o>?ӏ//F[BdeOUD:W( j (kTgYa 7", Br{{Z_o KmOfPapPÙQ١yLqE;ձ*>"QR-`{0bkuv4sތtè4_ڳbT" G|$^~:xuv7#,0B .+/gZOVcO)ˆ[GZP+<ָbƊ3 .x5'^!ZԝV 8 no${:\[? >nC؃?v ~1xV=sSmbxwj=Kw[G_7١Vkn/Fx>V?a ~ ycË48DKV 8 _nII\C7';;ڊ)@$AR $I#+ 11B`8!#_.Nwf;;c??,FfC ّ?7F]&.< oB9X|:${[>| kvv6́(aiɆbڨU,߃m\p%}BH6W-{0f1KxU?@IeC yCڅm\p%oiL!$k%G/)~ac`oGvv6q +Jxmwb!,ln p t}&ټy tlg\a6PF[QBҒ% @.lK[9S0}k<{1Kvopͫc ,ߔdC yC,` 1Wr .;0@wOFm:t 67W|ֹ|(!'6XM=L._(2lpytߛ7]Lg;;~?l<2JXZT/%`6&hD_N3)w;=ey%K0#g;; WwѺ)iuJEObۀi0&K} $K`xwl<| 2ryu?HgdC ,݄m\puAH6Շk/-ݏ3kkwf9Wؼ7KM IK>YM6OWL!$kGm1KveՕ7%JW_JKdC9˒kVrSOkkW+l^](iɈbۄm\&h+uW&~?O"}o<| ֮9Wؼ4Rr%,-PBl4mĖ5{AH6wgI-mX-6V(ٌ|(6O}is`%6!FJÑBl|(o\sAǀP׮9Wͫ+oJ|(!{1`O9͒kjim炶_+Gvv6)QݺQBl"WOb!`L\@H6V8oHtߛ7_+Gvv6)Q3}e1+|=.?)v?} ]?ryueMܛ}e"EFΰ!F<ɒka^|t’n7okW+l^]Su3}eE 6Yr!\5Z-炶]7-#g;;~VMɑ P*mnr+)26hCZYr!&4c@<,68WؼD>iC xo ;mesw[ >l 䱺vvߛ%{;>[l~+ 102K} $`GKw~.h}ZFvv{>-ߔOPB\tp[P6hCɵdsch w3-c`>-#g;; Wi)QiɈb}Z.bp!FFdɵdsk0S\\1Kvpͫܔ̌(!6ߧ勘T$b6dɵɏvqKsAǀ/ڕ#g;; WWߔȝ&JW_Jmwr!ᠾmkW+l^]E:-PBl{c>l#K} \6AlKc`pͫ+))'3JW_| _!F&O} $%eK[͛ǀ/ڕ#g;; WW/DF KK6VoB1b9~0#Ac`pͫ+#%QBҒ%+4#m~%\BH6PwM[zǀ.[lgOHfdC{_YM6OW aaN a\1K `+l^] tSBҒ%́ڄm\p BSqA9, >| ֮9Wؼ4R %,-PBl4m~%:? e xs@\1Kv-յ(!iɇbJM=L.Rrl&:a\1`K g;;[{sd3JXZT<́؄m\p%0lw{HI~a\17Ե+Gvv{~|(!{JM6?+^fN(#wrmkW+l^]ٟtSҒ %+#+ 1Wr9O9dG炶_+Gvv6)E}|(!6_+Y=ˆms%>͵p3x-c`pͫ+oJ(!6_+ن 106K} $[S|\1KveՕ(!iɇbM=L.BH6w:ȏ\1/Bqlg\MK7%#.J7-Pˆms%>ͽ 0pn~.h}ZFvv{>-7%|(!{}Z.bp%EƆms8<c@ݧelgO>-7%9J>-X#mfɵpGwX-c@<,|+l^ݧDٜ%/bp|6Yr!\ 1v;9\1Kv-յ@)Ϳ)aiɆbلm\p7 !\i?N$)t?} kAGvvoAkA#%QBҒ%-ZJmByJ.RmBH6gm炶_kAGvv6tF KK6v!F<%\f5\!$pYu?} ϣP9WNCXZA޼} m>ryuoJd3%Jw݊&lKL!$+yO-EsAǀ-<2pBIBfC BI :6!F<% B}9&}o<8r _(^9ob!`d\@l%!'t?I} u>-#g;;yuYLJ7ߧ%Wbc,p

ʽ<Vp>i1zrG73X˿a?zٞ3Z0Gk]!S*WW` O__?b>jm59_~Wu8sG*<\{:1R!(!Ke''y޼dq>Nk@ԙ_~[u8 >nC0wuȈb|UP=x? .TCNyrWh~)oi"7__d{pF /.V|>N{:^-]nqsj? eY!.#F_!?yJ >HCdigCR*&ymğ[AeIX\ ,6:bϋx e>NlB)G'c`>P|w2pPsL7%h%""m΅ms%>ͅ #*T1K^?l>psߔH7/}0'bp%˰!FFdɵdsZ8¨{1K^?l>psgaM KK6sfs`7!`3Jh !\K/?hKu 5޼y Wkvv65mLF IK>oByJ.RGqlnbqaN2޼y ,[yl>pyufd2JXZؼv39m AH6wG}޼y ]9ryumMR@PBl"WhC,lƒ[͛ǀ/U#g;; Wyޔh7}E @6hC,l~N\JP7okW|+l^]M ?5C D Ԛ 1Wϒk塕Hᄧ{1K`֮9榺3R%,-P*mnWFVvb6? d3ͅ 5R*Iޛ[q'_(JQBҒi/mM6OC~B9~*'{17T |lg\7.OV)aiɆ7m&hN !\y?wߛ7_+Gvv6쏔\F IK>VoByJ.%TL!$C XmNھ޼y ]?ryue?P "%JWGVfbSrAз4ͭp3Au޼y îkAGvvͫkA#%QBҒ%ZJoB\!ΐn7o~C]-bo^(l(!{󆷠JmB4Ӕ\ ?a !܋bأ޼y ,78Wؼ~oϴT%#JmB\ By>|ԡ&jYl>ǀ| ,`󁳝pͫDJ!%J{+ 1)dsg,>*PlsAǀ/}ZFvv6)|(!6ߧ%:6!F<%\BH6y~.h%XO}Z"%QҒ %+7!F<%\!!G‘ >l ıg;;/O+ݔC zbde7!FLx%3p\~h!-mv?} u>-#g;;yuHddC ٛYM6 E>U+It?} ݧelg\a>-R(!iɇb}Z"+ 1)J@a !\wrmkW+l^]xQҒ %+#]6OWI S/3m'{@u?} |lg\a7%J'bp%m#B9qmV[͛ǀ/ڕ#g;; WWߔm>쿈,dC9Ȓk0qkHsAǀ/ڕ#g;; WWS:>-|(!6_+is6hC,lY<޼y +Gvv) P*mW_AaC9͒kA}= >| ,`󁳝pͫ+oJOf>6?+ycCy %>NL_H/, >l ıs󑳝pEPsHedC z<{8m.SBH6Q*P_?炶ݧelg\7)ٌR(!{}Z"+ 1)JUsl4Lh:s\1KvpͫDJ>%Ji&h䂫 B6#-炶_+Gvv6쏔TF IK>쏬&hұ^ͭiӆrKǀ/ڕ#g;; WWGJ>%JWGVjbSrܛ3l|pꝜ~\%Xlg\aHfdC JnByJ.ҷ4̓2cNwOkkW+l^]Sħf(!6_ٟ%,wbc,pܞ_:u?I} cZБpյ7%% _ȸ{u"K} \6w@u?I} uGvv{Ϳ)yrɇ7E 6Yr!\x>ViwǀPڕ#g;;~EueM|‡R7+/bp 6QYr!&>V+(t?I} u'-g;;yoJTkSFyÓDLiAC9ɒkZpG7BSݶ]ǀ._|o>p}&6Jy"ӹm#B9qk%$1K `+l^uDڜ%1R m#B9LNY?~\%XO}ZnJP>r+7gC}BJyμIrc`>-#g;; WilF IK>YM=<%VdSa>;Htߛ7_+l^ݧ%R%,-PBlOKd6!`3JV3lwO~/$1Kvpͫܔ/PBlOK"C6HǀQYryx8i5\ǀ/}ZFvv6rS"_g}ޘ 10&K} $!T,"~w?I} <5WXg;; WiJFfC {osA& $+Ag~\%B<,68WԂV)l(6O}is` 1)J7g !\; 73=$17Ե+}Z2-QBDVjbSrAP{s͍p3sR'ɵ_+Gvv6쏔TF KK6쏬&h+7 !I>.LOkap?m+oJ;=FJ1RC|6Yr!<J}!uc`g;; ?7J6%J?7&ĞlӏWqS=}~.h%Xlg\aC \ɽ9bc,l./[zǀ/ڕ#g;; WWߔCdQBl"&jC9Βk2╣wmkW+l^]S"|(!6_+7gChɵd3_6vKy%Xlg\ams6쿈ܖ!Fdɵd3_껟 >| ֮9WؼD5`D \I!FfɵdshV({炶[! :p MBi/mIms%>ͭ0ǻC;炶>5WXg;;yu7C ٛ6OJuC9͒kNVOq >| ֮9WؼDnPBl7-l=N} \6pPn~.h%Xlg\aoJLK>쿈 10>K} ${#LJGL~.hЇ]ڕ#g;;~>7?+R|M KK6jbO6Cvb !~zO8q[ >| ,`󁳝pͫ+#%QBҒ%#+ 1gr+Yi{1K7-#g;; W(aiɆbߴ+7!FJ. $C OΒ;炶_+Gvv6OV)!iɇbلm\p !\Akwrmbq+77%%{'b,b!`\\@ⶹ:wKҡT8 j-ׄO8SqEKanDe*2Bx ~a =xdTRP/~8}.||K +Jyǿ^G:; }?c IG> Hip L {:z]X0=Xr/oFX:a/X*/1Q!HO-$uM Jpe\gZaJf#FRP=xPbZis1tJ=xDZ^}~nqsj?9ތtdèxF=xOi%$8WAcuM#o|\gZ7ň.gك7< )/-N}7NΐNo*uvm$6 b\;^!ZԝV 8 n?>_) :'7١V6J.%J?m~́ձ 1)J<` !<>JS'(_+l^D>7C >XHǀYrᴹҙRBn~RGk|lg\7%|(!OZ"Wb!`t\@H6?EC=R>| J3ryuWJwlņms%>͍T1k S\1K4sm>pyuHfʴdD /ۄ؃SrIE}eIEOZjOV}Z)aiɆbs؄؃> !8}o4Jt?i} ݧelg\a>-J7%$-PBlOKde7!F<%isͽ1pGZ;'-_+l^ݧ%RR%,-PBlOKdulByJ.!-#g;;~ViLF IK>J}Z"cbWz+PZ|H0pޛ_m>ryuHIgdC xos`%6!FJ.!\{  O'-͛ǀ,K.l󁳝pEPߔ'>5cD z1mBnf2Et?{} u[#g;;yu׭U=Ĉ7u님p6Yr!\8}#~w?{} ݧelg\a>-(!iɇb}Z"+ 1)Ji !1`'u?{} ]?ryued3JXZ}edulByJ.ҷ4a<\:j?78Wؼ%I>C ysahCɵZH4A-c`pͫ+)y# #JWӂjQ‡؃]8esf捠NOkkW+l^]ٯ?DF IK>쏬&m96l~Optߛ7_+Gvv6g-M KK6쏬&hze !<>JQ]y%Xlg\a%+x%M!F<Ȓk͍8kNc@]?r]ued2JXZTܽ쏬v!FJ<+dsy WS~.h%Kvv6)e |(!6m~;b!`\\@l(e<{1Kv-յ7%$FmnN} $+A >| ֮9WؼD4PBl"WRdl6qYr!\ s-c`ZБpͫkAoJPBl0l=%>.;+>&Οp~.h%Xtlg\aZЛ&F10*K} $njYdsAǀ/ڵ#g;; WׂFJ*%JׂFVrb6? \!$[-!k4TG?\1Kv-յ(!iɇbڄm\p B c`ZБpͫkA#%QҒ %kA#cbͯL\!\6{!(< o/uT:Gw^׽`<\DU7N?2$cW#QJp{ӽ+N}o >t╯g;{+_(ԧ(w PzWu'bcZYrᴹ=\pt)^Sɧ9XO<;˫ȜwL(k@?;E zqXUaG{OEouпz L~*$$>^9W4g굏5ħGv֢طW8)Q3}1EʇoYrᲹc[z?ik89WؼM9J8:102K} $be L1Kvpͫ{|S"+QBl1ɽ9b6w&dɵNZU3ǀ/=Fvv6q(aiɆb="+ 'Na !\lj[,YL1Kvpͫ{DJ*%J8v!F<%Wbָ@cu?S} GvvylF KK6JUձ 1Wr|es/)ig굏_+|lg\aZP$|(!6m&l~&\wl=֚)v?S} ] :ryu-h2JXZ}-hdulB\‘͙Blň[T3ǀ/ڵ#g;; Wׂ%dʴdD Zjb6? ޜ+dsc8 j-c@bGvvi8jSz2x$Wp>hC,ln|P[>vebo^]S:C ٛ쿈YEw͇ms|\1 Kcp?P<+#QBҒ }edulByJ.RC\!$Kǫ7C ZЋ3ܖ!F&dɵ\+.?U8z!{|Tgُ!"E=+gJ}2/ q h$moHΩ}yЊYv!͂uBuvԷKЭ/FVo5BlC‡mpV HYv~i >lC0_*2_o1B .v/gid G*E=տ]_q~6}W_2'FsO}i . /2N}ڏҖꚭB0x7١V ňz+Ljo\;^!ZĝV 8 q| ]4#/Xř|\gZapFf#FVǴ܃mV*r ip+8u>uD۵[G_r33ۼ IG>j48{" ~\\w\vfa >nC0_j5o_0B JM\lx:isPtJ=xp Vhf7١V/Q=1B '/OLJip{>N4M~u[G_*33ɼ ň|-ŇbUdOe>h}>Nr& WkhtP8| <Ϫapr2u=(!iɇb̉Uē" Xϫ B85T&4_+Gvv6.JRddC :mB\<6p)pQ*b{1K`8涾涡"7 |=<^;ɵdx:9͛ǀ/xXl>py}=`%,-PBl.XM60b3͕wو{1KvRIQBҒ% JlB)$mBb@y(6okt+l^])|(!6_YM6KBvdTӿOm%Xslg\a ϛ%kω UUnmkW+l^]S"C J/bJS|=܅|c͛ǀ/g;; WS"ؼ"&%k !es+fT w޼y ,^?py}e7%2-PBlPٟܖ!F&O} 6Ju^>t ڕ#g;;~UWߔ/P*mW{ 14O%>.[<| `qpͫ+)f|(!6 6?b!,l.);(tj>| ֮9Wؼ/J|LJbSب=11wr!\jӇ_&[͛ǀ/C#g;; WW}SC ꡋԞb!`B|鴊?~ͣ寵M,.Ɛuc`בpͫ+_oJF|"F !`sl\@lnC޼y ]:ryuM%+_/bpyCURwr!Z֓ny:9пߛG/_kayO[dq)T}&J7$c^tWG'0_8v+i\kRqG(!j>:D,^#Ȓk͕S kIt?W} |GvvdH7Tܿ"&u'b6Ȓkͽ%!S{1K `+l^]{SӒ %'1R]mB: ̌;ґ[>l XpŹR_GJ*%Jx_6!F<%\fM)eHtߛ7ݵalg\7(aiɆ7ߵ!Rm BS6N)c` #g;; WwmlF IK>ڠܹ7߂m+%oiL!$#@繿[͛ǀs󁳝p޼y0(!iɇ7oxn&h_eD is}>Z(/,>| ޛ+l^7)U|(!67 11`BF)G)c`4#g;; Ww)Q$1}W/bڐ_(!`s,pKI%{1KJb+l^ݕ曒 E5$Wr[ʆms%>ͥp3 w?} g;;{oJ> {䶔 eɵAVڥG u?,} wnN4r-[laEJ*TދQB0EV0)J !܃?:("1KvspͫݔQBl9E ԇ|6qYr!<(>84閧"c ŋ,vvY|S"m·YnCI,^I!F<L\@8mn=c`rGvv6,(yQҒ %?ˍ&l~&j+dso-ݏOlhVs#g;;'-խ"%QBҒ%IVs܄m\puAH6QP'_[͍+l^j( QҒ %[EVzbSrA{s͕ct'_Y+l^"R%$-PBlEd 1)J~Bo6\ǀ/oAGvv6~ zS30[Ћ\mnϗɵds>;1K[Ёp߂~S:C y[D W@l6Yr!) wt/#}o<| nN4ryus3%]\| ȝms%>ͽceȝbǀ-A|lg\bͿ){s>/l~Wl6#is+)jA޼} k9GuoJdTxj!_3l6YrᲹc&[̻'_+|lg\aVs7%?#JEObp% m#B/VIA>~|b%X]nJtZ}׭\ɇ l61Yr!\>V@>| 5ryu׭7C [1m#B;W{"n~DK%Xlg\aHIeC lB\";2pjYg1K  :pe[PO)!iɇRisXM=L. By8qSܧ#Z~c68Wؼ-7%'3J{;s6Hǀ1Yryxk<)gyv׭pœ[@ȌR(!OZw݊&mࡺnql. { ))~Pߴ+ߴ%%2JXZYM6O%EmBgCqlg\7`{uSBҒ%dobd7!F<%isaie${1Kֶ=nJXZܽ] F<%\\!$HECc`#g;; WP\F IK>Ym ͍p[͛ǀ/]Fvv6)l(!6u+:6!F<%\BH6Շ=Ӗ|1K |lg\C{s䏌|(67&h $;DžLja ߛGJ:%J{+ 1)J~ q?AZ9?/ X_ӽC`}JMLAV~k lA'TſZ;AiAwޥ_xaSggJ݈Td_#ޖ=xIW|n[*x!L;"n? <O3}|yPm‹V7-)*X&H~ǿs:; ?? KG67bp@u4Vp46>|uro_f:;4xlO}3Bґj^ϴ{EpT!Sz[G@{QsjJfp]_tdك bp@e 68O'ѡ &Kǿ޹@uv>(D+y3Bґ#9182{" ~ ipNKt0Sz[G_,:; ?Ŧߌtd1_ ڃiVǁWEpR~בS/- :z=sP+ a<3802721B }͛ǀ/ڕ#g;; WGJ.%JGVfbͯ~lmz-?-b1?ߛ+Ϳ)g+Mw&_Cؼy ,78Wؼ~oEɐiɇbE D9ϒk͝Ta /l:| 5ryuKHfdC X܄؃+I&Wև#){1cuS"?NC|n~udO9̒k%/ Wq{ǀX{o>rx Z7LF KK6 k݄J 0pR@Mεcoa Vbo^dMJ\4$&#Ͱ!FeɵdsX-c`Z#g;; WwѺ))2-PBlE 10yr!~iy;_i+l^QD%JԺB 10.K} $k`Fx)nǀ/ڽFvv6QҒ %kEVvb6? T-͍-[;'5_l+l^iK%$-PBlVd6!FJ.vp^h~[%X-"%QҒ %{nEVjb6? AH6X-OkkW+l^](!iɇbބm+Σ 8X%wrOkkW+l^]MԌ%+/bs6hCZYr!&n,Yg1KxC@gC yC{9d#IN2Okvp?mn+#%QҒ }ed 1Wr|nBBՒ,7obqisQooJT#JE1-'-|6ɓk͝d1K `+l^])ٌl(!6mv!`3J͹BH6= >*{9H1KveՕ(!iɇbڄm+^ppܺA޼y ]?ryue2JXZ}e?R~b6? Թ\!$;*K >| ֮9Wؼ(#%JWGVjbͯ ᲹVPuc`pͫ+#QҒ %+#+ Ҋ|yB'(<~\%Xlg\aHIeC JnByJ.` BQ&H 'ɵ_+Gvv6V:2JHZ}ede7!FJ.(L!\6="7ɧ9XO(<[^FeJď)Nު -O>;k9ٖ-0,))E=#J};U- LȒkNXQ8ǀ/,Fvv6ngqSĆb,.bpu6Yr!<(!>Z6On]x6@IgC|_Y{yLxUA8mV_Khޛ_>Lj󑳝pͫ #%QҒ %́ձ 1Wr)ds5Ag>t 68W9P%$-P*mnl&h+7g !\ϛ[cok9WͫYܔY|(!{,.bp6ɓkmwrj~C]g;;yͿ)oAPB 6O?W@l6Yr!X>ں@~17Ե+͉=2JXZ7'&l~&\" ͽ;G6>~DK%X9͉"%QBҒ%+7!FJ.ȷL!\60q GݏhihIK%IK<+u: b́ɒkqX1“?Gjnlg\7n5wS2߷zn·i0:K} $Ko(mc`Vs#g;; WtF IK>o5Ym ,?\y3Cҽ%pk|lg\aVs@IɌ|(!6w 67q[1Wr)%6p c }o<| 5ryu׭HddC [ʇM=Lvk3&H^Ϊ{1Kv׭pͫnEJ&%Jw݊&h+is7z0?1K5rUu׭HfdCzu+Rm~%TAlai/,>| `qpͫܔ qJEObp%?cC9͒kƟ&^[tDؼy ]?ryue7dC \/mB7k g]v-zDiaD z_ E̐5!``By]MP17ԵkAGvv{ZЛ%doXoΛms%>.+ςrKǀ/{󁳝p_3ѴC y" ;dɵ8WG9l=>| ֮9Wؼy3#JW;4-2.Hǀ YrᲹSc^Cc`pͫ+oJHZ}ede6!hss^wl.T"P;g_+Gvv6)PBl"&#l6qYr!\j 1K~a1/2pI7%>oZ$b2Ýms%>U|kU[͛ǀ/OZvv6M9J\lȒk8c1)n7oh[#g;;'-]%$-PBYM6d1.ke?ֈ< Irc`[#g;; Wwݺ)}׭\ɯmcB~e~Irc@@uklgO[(iɈRisVd%6!d3 e ZIvsOka V]Rt7%,-PBl.XM=L.kͭ2c :}o<| 5ryu-deF IK>YM6Oesl$Ƭ3!炶_+l^ݧDU62}/b'FŦcwrᲹch"n~.h%XO}ZnJӌ(!6ߧ"W-(b!`d\@8m wX-OkkW+l^]=tS>fD /bԚ11`t\@l[;$u~\%Xzhlg\aHfdC !`%&l~&\WL!$ Ig-OkO}Z"%QBҒ%ͥ~bSr:+ds4>SNPY]ǀ/ڵ#g;; Wׂ~S:ȧ|(!6_ z+ 10!K} $ᧉ纟$>| ֮9WؼD>C ZЋ\9mB6N 'ɵ]v-67յ@%,-P*mnׂFVnbO6?K \6wrKǀ/xXl>nyu-hd3JHZ\9{\p%߂2ln gE ̻$>| ֮9Wؼ(YQҒ %kA#+ 1) x{BH60'~\%Xtlg\aZHgC ZP`v!F<%\BH6ws_gcn7okׂ+l^] zS"߂}-1I=ćm,pyqޞNIrc`ZЁpkA;),>ւaW؟??\&0B'7G/ߴk0T?l!HDwRasMN Ή= xPSvq'}'B.lS:󞉭uߩe3SK5u_6:{3XBbm!ˇr_ v}L+7+sMǿ9|\gZaqrC|!38{" ~ /VipגtʯE :r_aqsj nU<l!5sm4xJ+E4F~1x< ?_uz똰,'^oGq+y)⾒X?V߃Ԇ CꟸUH-R{r{jaX[?9';{wTxT4$ABҗ$Wa` 1gjz/ "Qr,|;pMw2%JN%MqSrA|!$ }6Qx%ъ"ټy ,O+lQx1+J͟;Y6O4q'b!,p[Iȝ7oh٪f;;,5\ɿ)aiɆ幆 9{yL.roB_RnY17_g;; ?O+ݔC y~c h_%W5S_=y%:m>ny4J7%,-PBl ؄؃ yp<8i Ίڼu ,tlg\anJHZؼ-(r{\<u|+%zK+?gy qklg\a[J7%$-PBls XM6OW Sp"c`p+(aiɆb~`6!FJ.sL!\6wp/ǡȧOPjW+l^_|(!6_YB1╴9Sa`n7okW+l^])l(!6_l؄i:Y=es-\&ɉd_y%J<, 67W|Xy2JEZr|(l߄؃SriOTe@`3L޼u u>-#g;;yuoJz%doOE =10!K} $_[K'_?w<*|QڹGwSsOGuMT}#7уoIǼsх+Q)]~'0ޥvp ޒ.Ky r+_Gvf%TWޔ}5J]"|"5QɈ؃Yr!NUY7qt?7} <=[g;; ׿%dH7\Ep=1VG\@lKkAao~9zo&mlM%QJ<\ Tq˨n927\޷UlknC>KnX~}9qՉрckV #g;{TK[5DJ.$0J}JoB1ds'%RkjGh1Kvpͫ[5ܔȷ{|(!6ߪ"Wab!`BW~ Ot?} xvS̑pEAsDɇ@>C ) hxzsS?isu(/>J-ݏl~C]bo^xDC ٛos+bc,l.%V[z?iik79WؼMd}㝋0?10"K} $3qݏlO2ՍwnJdZܽmBr~6Q_Xt?} ݪalg\aV R(aiɆb"+ WSp33ƒM >_(+ނVtSBҒ%-/m L!$[cG9mBaRcom3g;;yu;HfC ٛoqYM6OW ͝56hGy X{ P2%Jxߊ&rm ByPjhꡑpœꡛN%ID,^6HǀYry}HM~017Tm>r؛W7)ߛk;b6Zeɵ汣>v0Dǿ/~ﭣX<IjFuM)QB/=>܏YýZؿ{T/1˵<#g;{TQTF Ka6/x"]=LÞ-wl.t-[7_+l^(ŧ$ߔC ݄m\p^|sl.M;tvKy%X+]i"%QҒ %DVm~% .{'?Z|01KvWpͫܔg|(!6ߕ"Wy<b!`D\@H6ׇpu֓n7oO$]inJԧ(!6wm~; 106K} \6wjQ1KvWpͫ|SRA(!6ߕ"WroΆmsH#K} $[/L[͛ǀ/} Fvv6cpSZ1}ܛ!Feɵds^ rGt?i} ߂+*_߂~S"7Y|(6W oA/b mΆms%>.X/ {1K J3rEuWoJCxߕ"WI b!,lu²x:7/6rkE oS:SajF}DŽovO=F\tAuK_|'?=ܻ?#@~1˵ #g;{TQ{)|S"C K4GHĎ\#is#vp5W n~J`%X} (@~XLJb} IM>cCesgu)c_Ԭ]+5rx[]+)l(!|JEVfb6? dWͥ1c[>vWp޼+M2JHZw&hĽ $+boItߛ7_9Wؼ{LeF KK63қm~%Wds}x6~k%XIOZ)R|(!6oxr;/meXj1KJb+l^ݕ&R2%,-PBlJ7!`3b# $['f$1.-hͭ>7%$-PBނ6܃6!F<%\nL!$瑷[͛ǀP16r؛WJJddC ٛ1YB\Bѷ4.k?&xC!|%_{+l^c,Rr2-QBlXde7!`3J ᴹ=+ [zǀ.\+6]i"%QҒ }WmB\pslI)cvelg\ܼIMjLj/bBPճ|6ɓkwV9z17T+|lg\7)l(!{smBgrܛ3lW7[>| 5ryu׭HfC [ڄm\p BQ^Nv?} uklg\a[^7%,-PBl~bͯ: $`d'1elg\ܼH)dC yn`&h 6l|'17Եn+]nJ[P>[1RmcB|l|'1Kv׭pͫnEJ>%Jw݊&l~&\F\!$fN‘OAmkw9WؼM:{%n}Ӛܖ!FFdɵN^: Gv?I} 赫FvvI7T\|†i0!K [a!/ׁ"oKBi޷,? ~[ҩ4dE臽`oWHmosnj?cOk Iz)(rg{ϙy{TgY!痜ǍIE>s ginEe3':#%p[ k?Zz|{-wp=np+"?3aq_g>q?.:ΩmJ3A䗋9 w;:; w?}!:|!'.h(wC;!p?VX87qVX_Tdq{Q?.+Ωm>ĆY?_.,:z 3w8+v.B/} Kw'\ (Hw6Nw ' (_.):zMuv~.LE>wtE>er7ĊsjC\xqHt~h<];:;~>}/x>y|ji "OBZrOhz+<|LwΎBij!p>ŶL쁑pQYfm yL!l C`>Nvvn#y  _#IK|ax,н3kR#T<oKW]h+<^[xyC"| !_{|qe6 UļlpYfm yܨ~Y絮~y,]9rxmM |>U0U#=ᢲچA8aqC`̑mk3oHtJxuʃ܏Fzf q'a|9VxDz$㯫8/`s6HC,a<.iI'a^}C09GNvv8 )ddx;* 0gf?-q+d'_TOkC@onm?㮶(dʊr?^Wd_>HC䙵 qBJ%nkC@<,|h+<^[! l !=&Na;3Л1<tf ^u= ǹ#=g6 Dž$Ϥqnk~#]Ñm~͙ q>xө>^L 0.*ˬm$)ʨs!]sڇ/񁓝mǫ_$Ն$0IFzr2ka?j|_H! ah+<^_y2#H{JFzwfm yܚ"}@#^}[[k{|dgG[|ߐȒ>=8`!\چA3f>nCoK9VkdݐG| !}.`pޙ BhޭnC`>Y#';; ɺ!?@B?ymsڇ._ΎU!y8H*0q6HCNYfm y\Za>ZY(>׭}񁓝mkܐ@B<.^{<+Yqe6 U̠&Fw}[XΎUnHc>rS o`!\dY0HGhߦ纵Ѽ{Αm*9$$%@BWy3:6FzʬC}x2Hw_#NoSsڇH5r؏D' ءg lpYfm4&O>׭},'kdgG[>Y7$H_& b 0&,a2HXJxuGlYJg9'5}VWrKWh+V}CRԃ1F7+߾:01,apy}; hPQ #$HB3J yܚT CuF~y Nvv|)= DRS4xWT0.2ˬm$;. $o*1wV",/Y+X&TlkNsd8'@TO7Z*h1p76zhTK79.R l !"* 0gfA萯ry2Hɏ=uN5އ5_&h+<^4Dd I XM<e 0oj=Yz! tӤmk&}CrtJxuӤ/`*L=ne6 .y[q! t mk[ܐ~ !Bvģ#="چA89klK9Vx |-d=ne6 y'W.}WXΎ㵭"$ABR$[DTr`Sfd#J0{mҤ!_C`#';; ׶L II>n=Q#=2 y2HAqż{?<|n=0rxm$[\J>g82kgXw8[Cڇ-9.Y9V-Y!9@*< \#="چA;>(Gw{:W<<|Ύդ7$rkq \iqFze +eJG׵_9GNvv!QZb z >(pYfm;:+=t?OM _VxcoEf$n*7P@* 2=w"Ce?yw3aT kXKW=Rq/^D~rx]z+ft>ԑee8>gjǭ~әA-ׄO8qOb~!"qBxiaq@ n!HaXE:raqsj?ňNG6?g" A}+?J܄_>]~7ǿܗuv0 f#F hǴ q[%|_>W1xPn=w{p~3ґ P=x?J;!8 nd'!o_/Wuv4~,j nv|5Mm<{ ^ϴ ipNxSt߯u8~uv,g ~|! ۄi3B>Hb4\^8A:uOP+T??eKG6({aHiR5NN{'>ըS~P:#oբaqsj5780 7#$0Bϕރi3B>Hb4xRO)%}G(y,w8VH:47$p>?W|BT2MYfx!,]ha߅7_j32|lg\? D%ՙ\f6Yr!\Xc?B`Hi˝/glg\aFDVQ$Wh:FhC,l.&`vc`SFnjasi(!iɇbsFQ+ C~B~8ɝ5ټy <@Xg;; W7Q){s>J>d`C9ʒk#6S=py%Xslg\a*ߔ|(!6o誒!FFgɵdsoӶ`8ǎb6okU>rywR(aiɆb_GV&l~&\oBH6A:v!ᣘ͛ǀ.YNlgOJJZD R'Fw̝̒\@8m.e,sS={<| ̷U7%Jk_JoeC?T\@H6W!A"Eض_?Gvv6$M#JW^JmBэ;Hc`:Бpͫ AoJ[PFڛ!FFgɵds3tb6okׂ+l^] EM|(!6_ z+b!,li>8J_(^Ą3 @6Ndɵdse=ĀNSnQcokW+Օ7%rɇ7_S66gC9̒k'}o<| ֮9WؼoJԇÌ(!6_O6B9͒kke lH<,68W| 2ryuHIgC >-ձ 1Wr6p<J@޼y ݧelg\a>-:(aiɆb}Z"+ xo!\I“ >E{󁳝p7-{/J,C aoeC9ϒkghs@޼y u[#g;;yu׭ %doE ͹m'>͍8\"w?} u'-g;;yd3JHZ+ i;AlnVcokP9Wͫ{(ޔ!>1mByV!%'ɵ_{(+l^CDڜ%{(&bJ>bCy %>Nlj[8$>| 69WؼV2J?Ӓ%#cb6o!g>F ?ō7okw9WؼV3JXZ}׭mByJ. $KᎮ>(t?I} ݧelg\a>-(!iɇb}Zm ͕6cRtKy%pki9殺OKd2JXZTܽYM6OW_u}҃Irc@<,68WؼOK2JHZ\9څm\aoBQx8{1K׮9W|o^]=)l(!ߛ&h+)ds?7_?$>vebo^]S¿PdE ٛ" gxm'>.>&Hw 7o~C]zhlg\7>-(!{C1᭽9mB9Lnf8kLIrcokW+Օ7%%do4䶔 ;pqc`g;; ?7D % Obp ޜ 11`l\@8mnz2Irc`'-#g;; W?iTF IK>Ym~%vp<(J:A޼} ݧelg\a>-@I%,-PBlO ab6? dA,S3cuy%xjvv6Ṁbs'1s"F<L\@!?{N+"T8 }xM:uhTg`%~1 Qa4_rMxdpU![RĉqTwp}򇽇uv~v%׷f#F o@EL+W}l<_1xp}uv^%77#$0B U*/1 n=8Six Kt铿aiJ%7ߨd7#,0B /Tl‹4Vmipu)_Ұ4xp}|\gZaR2|!W)}`| ^ϴ ipXz Jo]Xu8F >nC0(=KG6K!vۂi3 nȟ!LFɏ8$cKyYC`rh+$|TP&qd2HHJX/'!&HVqX{%>0p{/>| ;'(7Be*tF KK6 ؄+J~`B06|Ԗt-ov#g;;~VLV)!iɇRisgdulByJ.)9S*~C޼y N}g;;~\=\Ƈ7%,-P*mrfs`e7!F<%\O/BH6ׇ00M&\v>b1K `+l|[n/JEΉbs托!r'Fgɵds#|t;'˓ۛGcA?_y/Z/L fJď)Nq:`gu} <ߎl?)i^ćx100&K} $[GÒǀ"n'4rAZQ(R%,-PB~o*L؄ؓcr|B}bnI}o<| n/4ryu/J6P;MFo1tsjɈmsH#K} ${`< }o<| n54ryuq8'J߷bC<N} $/Dy%X܁p?J&%J \؄؃cr+U2is)`R:OTǀ/oAGvv6~ zS"[/bG!F<L\@lR)O}/d'-c_D?Yf;;oZEJ:%J7-݄́؃++dseb hyP}rDǀPbo^os;^ޔC ٛ7XM6OWBևf_̍+l^gD>iC Fs_Ĵm#e`n ~xV%XխnJ7-|(!6j"W˞ms%>͍NtKmt'XO,~5EWE@fRQ=RQ5hiҸCP8suDmпŠˤ&B*Tu[i"wݏkizk9[v]݆DP*}\Z,6};͒k^81K \+l^݆%Ӓ%1k,L 10!K} ${G}o<| 2ryuoJ9JpIjhs!F<LȒk!%dPPn~|K%k2r{Y·-].bTmB0B~|KFvv{\(aiɆ7ߑ X W|aAQǷ_;r+l^ݑ+R%$-PBl#WdulByJ. $kXq:wl<ߢ+T~S"vőp޼7%G0È7_"W1b]|m~'>aARg_++l^_Do}/bZ ir'>.Za%jnꡑp?m)ijɈRisz">hC,lw}xE}/'K>ֶbo^_D}Ȉ7wm~W11`T\@8mE ' Dc`Gvv6DbD /bp!FFgɵd3_4vKy%Xpͫi)6gC oZ.bp%l6Yr!\k>ZYC)sc@gl>p6Dڜs\|6Yr!\Y>Z^Nv?e} %Xg;; Ww&66O@d @6hC,l0J)2Qv?e} uklg\a[@IȌ|(!6u+{\-#g;; WilF KK6YM6OWds'i=5Dv?e} ݧelg\a>-@ W7%$-PBlOKdulByJ.Wp3 AN7_+Gvv6쏔lF KK6쏬&h_uxroe -O'[ǀ/ڕ#g;; WW%)3JHZ}e?ab6g7y炶_kAGvv6tF KK6M6 72\ t?} ] :ryu-hd2JHZ}-hd 1Wr B:4>Itߛ7_kAGvv6JFfdC ZnByJ.I S:nᨳdsAǀ.]tlg\qZEu-M,C}_ zbb!`D\@H67BB X4S~.h%pa #nu-(PR"%J9{\&YdskEsAǀPbo^os2JHZl6!F<%\*ͽrAYCaoo_]7 _co/w+ uMT}2# `K=}UQJpJO`{8O>]iFvfxTGJ:0Jsw `ۃm3)V7 \[ݕflg\+ P"%JȞ}W؄i:>L!$V1.n󁳝p޼@IeʴdD ٛ7\SP FJ.`+ds%$=~ j=Fvv{c(aiɆ7c,m -{<~+KˏO7%úc9&:;9'}oy 'n@?S/mn[x[~[trO.ûƩλv㿏_dna3d@fʆMKC6g?DnZτim)(-ZM)/?.Y{LgYa~i!ϽKkbkC;vpZ[i>ZA^ѻ=nc_!4dC{i\ {Z!RP865}ڭ>~tv~x[CsډV ->O]6 k] *w՘Y{LgYa>͡MKC6k?h, k 1+qpZze?NPk(z\Of:;~Z[^~&tv~jr["$#B; ֎"" iXo>B<(tby8ouv~zϾfdtds;vuQ^ۇvYZ _5%;I6ǿt൥ߌ%FWK&^!xlxZei dpyB5 Vwރ7ǿtൕgtd1I.(_iuXkUx?/,.K]$ko_Vzy<#:; WVTތȧ(|![Sy+ /:TV HwK牎0y#@uv4v#c#F28қ ~Uzdp/`"(OQG@W9١V+け#$0Bo+#) /) pzK#s;G_R~\gZaZyqdtd1jHJn‹2VJY"8 .gG Jn߹lPrsj? .+oFd<F\ɇlxbA2p BNo#:; W>]0B 9 lxQ`YZ \[仵Ǟǿr5ȹ!ȇbބeVp%$D ~MnItރ7ǿrUȹUQaȆbU݄e+D epwYMֽDksj+꓋nFe:2bmU}$6ELxBVp1ѝGksj+oFTE#FV_JqË28j^YX gǿrUȹg3" ·bק'^p% Άep.LQa#tsG_~\gZaʪ- #FV'^J}}ɇa,"K]vpM'{Of;>5#:; Wd#{dt1ۚHnX" C(!tG7+M8rCR5ͷaȆQipkHJo‹4V8TU=OHQJ S|ZU#:;Ԋ=xeU}dd3FH:aVGRf^SZl <%{U#:;~\UVGD6c#F۪H؄eV$k!\&w>e}8~uvtIG>l‹2VBPDpH-)tރ7rMȹ9xeMfd3FX:a<[IMx?Jg);!H߬VXF7ХdP+o2Q!ȇ& 7E<\qX"H;y<{sjketd1=;E<\I,$]o(#:; WEF^dt1۾(@MxQOi+ݝ$xR~dǿr_sj+DF!c#FE&(+%dh!];>}QFuvr3T4FExY›a,.K]ˆ8~llP+ ^#c#FKGRn^SZdp)+|Nfp+E9١V/7#GzȈb}Qx OvbË28j}'kL:>U#:; WVGF!c#FVGRz^cZ|A2 L^`]as2G+WՏPip]YU3"[aT\xΆep.S͡itރ7/O7U7#l!o x|Ćep.4ԩ19#\9rC0xeM͈:#ok2/^pEEei dpkth ؓYW9١V&oFX:amMf$ /gZAPy"HwF؏֒N|Nfp+dP+ ^Y|![IMxQOiWM&O9)#\9rC0xeMfd3FX:amMf$%7E<\Ta~dhS|NfPf=ltIG>J{p &(iTwYN*1t>'} tsjfD}ˆ[U+5!^c,vA .'ouzy:';'f XO ,[^U%Y0T}mVn"1rZlX*H܌zRF &vIĮo1evac(ezj2Pm`fw$gA6ه|KRw^p%7xlxQ2VA /kI*>M$zutUDIY0Bґ#wH$R" ܔ%lpm_o]Ç f;sjk/FTkIF>w_JEEi lpyT#Oڧ\GZe}vF>Rq1B ~OW^!DV QGR?ssj>|!<2 iT3e6;֦cI>!̭8{utU/<OQ0BmŹ+ /)XTV Wj!)<|$Ṷ8{utU{8cP>=V;/=p R##Fvm| ^kOwg#qo=N(~ +@?5^;R@J-#~ZT4>2: ~pKg8amEk!·NU .N(oC9 ZIҞslݭo5,oq,/`sDܝqqQX1GN-C #ygD n~'ǻTGY>=t@"DȾ[u7k 9`-(a;YOu8s8}I7 "$ B}Y7kܝs(3IC0/1}wpS?37qV3@DX*A3N^Sp͒n/}ymsRu8Z#7qV3rn@DH*A12n eE;ּ|T68A8tM~qwݧMJw[DX*A Hwo9e-I`swp K'}wpu6)oric݀(Tqy_K\Sw$\xI!l_*Dޭ#$o~sjON*:aȆo XiW0t?O)YgS!5:C`޿Tth$~໬H$H;|w.WfIMVZd{ נɪ϶<:|OMvtU?mP]$ KI6wB=RhrƮ`xpOI! 箚8r<@$$%@=W*0[fd=.^yz?<|xɎW0$W@R $}Ћ#=gQ1=.7x"dGG[5R! HHJx~BU\-dx2W:s$~yL]sd M@"H\'>"F+xRdGG[񫵚 / !)՚ *hoW'q-/2~Dc! 0ufɎW6Rl !]PE3Kϖx2=|} ޏ7_+8{NvtUZÙ HuJ2xvgP%,x,(3e{<4R~uL]sbId jN@F{|,RLdS8GO>|8Vyr='@r$$%@B<~PE3 nfk1=1a?! 0w=gɎ9\l !_ "h:y“R]ZEO>t';:~z<\4`| 9]- }:SVK5™ O>|xɎ9+ a)qy/x,Ux2^:#H<}fdGG[N!!)/Y)FJ@{xdGG[d zN@F{E`xHCv O>>|^8Vyr&| !_L 0[fA {^d|:AC`Վm/W$S@R $W_Yp%d=U{֓N#zG<(|Iֳi`O{m@G0 "U1.P_EM~M-`^٭߼j;ɯ<ٛV{[fQgnY\N'hbM+.NXoY{vÕ7|)m|9Vyj=gd HHJxv=cYƔq''l ~tۇ/=';:*_LL KI6߮L"hraLl7BhW--Q'ۇ/=';:*_< )Ě$9='o`S"a{<%:+ۇ/=';:*_< i2%@B<~ =0Κ"a{9)C`zΞmǯs~CrJI>߮܁8`!DY0*xZ.eۇ/=';:*_4?. a) *hRMԨ\ыώ[/=';:*_< :@B<~sW `UMpd2 ǵvG<<|9Vyj=7$ Hos~q)Qd2 vd1F)ukrzΞm?=.sd]ϹIHC"a=7q268|nC@,xwh<~a lp Ef- {ܦ|^nC`zΞmǯsȭHosqWd2 ǝFCysڇ/=';:*_< @B<~sWlpQEf- {{-^&x\ukssvh<~ l !_ "hoWK C!CZnC`zΎm/sdJIN߯Tz`sfA}k2<SeepC`zΞmǯsZd z΄-Yp%ꀸ2WA(ٹn_ /Ϧ?Xy@?$ON_ZH(q1{.^'y;ٹ G2c͢^OC?##X΂~.NjU^'r[']P Pe+5oZ3[5jTSi]jv HHni'Tb`sfiWVW$镧6_{NvtUZ * a)EڀE3Kw ~@;=啧jj"힓m?=i'H$H".Yp% {Y%5j+o_x< w_zݙBGۻEK^n{{+Qg!:׼"~{gjϽJďeTG׋AE \dнzɎQT{8HD_ NW߁@tbܫC"3p ҾD6+>{Oo?poag%!"uQ<^;.}8 }26wky'w=bvwP5(o짻nBD  \vpQXGN-C`sK}kQTGYV(9!B}hq . "ZzI|HݭO`twݧo w!"7\p!ny26woӖO wGVS?58ѡV=-$6g޷l"r.)XlV0o,%l~ 5/o-;NvtU{H{oHo>]yk$eWrq_d2 ǵ%^H! 0=';:*_xA$$%@BnW'T~`2Lּ:R~C`Jmǯ'H$HoWF{ms yr{?PEQ,-Id{<:QF_=';:*_ݏ'H$H\-J{%qլWޟeG<(|Iv\c(~@G0xIc\@("ɿ&PrKj~ý~'٭y޵Mu7=G5_6}t=Ru/MDua ? LI#`!\LY0=]x)T>6yLMdGG[d$$%@B<~LB 0[fAoy2^Y&d fo$oi#O:y;s*Rjߚ@_(rw&a Ɲhnwyw-:eѧTmXz9=';z^It I_>;'e\A<d;"\'kGWfo$dI>0 G~}tf2qK'=bɿ$P"]/;ў7w-7dG`ɲCkNA=';zTKv HQ ?PE2 Bt>Oަ}ϨļHC`NA=';:*_t@` NA_,y:`!\tY0=->8'Ͷ_+;NvtU\S| !_ "hoW 0OT'Ͷ_+;NvtU\ t KI6߯LT~`sf|˓Ax4Rp|^ICmPwh<~^ | !]PYJy2<ᥕWޏ_ku{NvtUZ , a)۵ [=d=/=V=}lS{NvtUP@S~PEϙdK z!7ҩ{.hW{.|A0o\؁0.ȬedK/#啧Omo;, xɎW;!vV !`W;>HC"a=E Y>i}hqs @<$,%@=nnw!T..YƔg啧Omd&xɎW{$H$H]'Tb`Sf+|'FD )PO4>|9Vyj]>@2$Ho'Tf`̂!<d+R8O4>|9Vyj]7$M> /`2/#=9%Z` T}z! 0u]~ɎW$_@R $U2 o Me47_{NvtUZ@֊$w`p%WagȬed[ox<镧C@N]sZy@S $v= =0.ȬedÝ<8O>}j=';:ڪz ُ߮L"hoW Sп>Ů}̽8Vy~\$t%_ Fy<*2kǭpʾTRóS>! 0u]~ɎWP@R $*0[fM“A&E7ڧukSh<~.Dn@B<~. 6{N6HC"a{|Xn1W/Lttp7 ݲ8[~R y'ޖK8SY!<:Ml:3mXxʿ[@39?t~/آe6N-E|^j/F' -\wk=ߴ; /+"`_*{MU:񅈾ATY VdQ:\!VSmE/ku\[ß+::*w|{G*Fwvw%"u7\/rj&P?|&Wtw6Tdq~wGE;!<`J`sS"Uu(|?_u~Sg?|#픔"$ TP#_iiE{)E6w+xO|)69w.)XdV0 .10{$k^;! 0׍';:*a^| VXȗ\iqFzE q>kxfdGG[u R, !)۵ _؉Sf5 {^ٽm#U{yL]cs2 J 䧗lp1Ef- {ܙ6ې}uڪ=<|;xɎkAR( a)/Yp2e=Mpᳶj7_+2{NvtUZ | !]PE3ːg3e{<ZxuL]sY];0M6HC"a=KMw>kxRdGG[񫵚ɋ| !]P)J>[ {<:_JXC?|u6{NvtxZy@"V| +73tZq7SyY[s?˳)oЏ8뻽L_ZTH˨/W+IhI"?yr~Ɏ7 + !7!>KﭝKB%F\̂+F'qEk$;͛>! 0mǯ? QoAB<~0M FzE ql}TWsvG<<ߛC=qzx$I S4>HC"a=%r|l>}LMdGG[r2d ~B Xؙ͟`f {ܛw (PEϙSӥdmKůp|(sՎB$Howf,Ղ01}iY0=zi~?ݩ}+{NvtU߫\`Nl KI6UnW0*vqȬt*d`zI~j>F:=';:ڪ$$%@B㷿O"(eq ǥTfyxmǯ~?~@` ǿIE>b8-2kǍp:x_y`!DY0=ه਷O/>|L~mǯv!H\ KI6Tf`},R]2RxFOk>_}1=';:ڪ,/?D>~ 6HC"a{<%v>}@dzNvtUdr2d ُ&\Xؙv%<dokg |C`n2=';:*_& | !M&R#=3 dg4 aK9镧C`n2=';:*_&t@R $㷻$Tv`sfU {<%TԖ~>}jFLɎW|C2^F&+B0SȬedt"RU8V<oBaɎ9!QE< 97`JUFy<*2kaAR6h>}ȓmǯ~wx@"qy;0q6HC"a=%>R٧O?jh`=';:ڪ*Wh-HC"a=p՚:>}]{NvtU$$%@B㷻;&T#=gPTu vaҕ<lJ[c9gON_Z}u~q1{D=^>}rDsZ\v8 @@Bv.;QJbܹ@"a=/+]ڇ>Sis(tK[T II>' _؉!RȵlR*J}_7GzdGG[_~C"3x\xWr/SȬed+jO>|~s7$ Ho߁)m7lpqEf- {\y켯xyLdGG[Hd3HowہmEqFzE qw|Yk| XC`p=';:*_ w@"@B<~3̸@#=ZAu:h<oSw9Vyjgq6 + `]Y 0P :U~+U?o1^W)}&::~~k(Ϋ$T|762kx"O`:װ\$9W[·=;)o짵ڛaQmImBX-BnŔnayr᳭*wqWSTGY>9 IE>=ڞ:[-BÔmROw?a::~Mz{KE6jw_H5pQr .d;gο!arw|MutUJ݀Tdw (w眒Qf 1BɇϤ88}`<!).[NA}%ɔ@vwCUq88}ɎHPq!d(wC:#!;*^r/᳧*w?߉ޅMutU>?pwTZTqӼkw).)&< dw;_RفSwp~j{P}~w/FTJY2 6K{I%#OPk㛇/MzNvtU$A$$%@B,~JozFzKFy !_~YI0`UvȬedkaK7UƼ~yt'=';:ڪ՞'$'2H~vד\`ǷZA,2ݫ(|C@@MdGGOO!ZeW 0.Ȭed[=\NJw>Ax' 0';:*_텒RRd q@v-^ARUF$j7_h<~/۝Q I>b8/2kWG'!oSWh<~>A$,%@B<~>=3KID vEE֢<}ZdGG[$]@BR$㷫UϙZA>Ug5_{NvtUZ@"_xv0ALqWd2 vkw1oO>|~dGG[ߏC"x;0=nZ,2H~?kC@N]sZ񀄥$HH/n<dG4\>ç}tnwh=\NIF}*0{f)GS^)H<}OJɎ$W@BR$$T~`C!`RH}?>}=szr . !)\*(e*Ld Ȕq~?}VDUzNvtUUH* !UII8+2kvkO}DJɎWAB<~0FzE Bدu<}D{m/l II>^exn7K~?ΓAuƼsBPçϑhfU:Nvtn ЭHU20/#= Gf- {Y^{C}! O`;NvtU_%A:%AB<.o{exPEϙC&` {޽ʧC`*=';:*_ l !_PU2+]*<l7B!RӄukSsh<~D1xv=0= x Wd2 ǥ +ۇ.;{A1';:ڪ*Wsh-T{|=d8KY0WRUؿXBޏ7_sh<~=*` _$qSd2 v_ƨH<oh*=';:ڪ*W|C T F*J>b8(2k26 Oy9ۇH^dGG[^o+ 0.ȬedTm۶>O>FxɎj?~OV HXJm*do Ƿ7AF;lS9Vyj,?HHJxv,@KTqFzt}zNvtUs^$$%@=noJ"HoB8OǭpJڒ^yx?>| xɎWOt KI6T|~dGG[ߏg! *09J {\)WWޏ7_;9Vyw R( a)&Tb`sf|č.H9ux?wqTtx[o@H Ty;ۺvzgo::2|ح@/o짵⇵QG0BT{۽> .d9\!VSܭ|jN|"|7+w?~TGY;/Dd+>wsoBEbȩelNad6?/OڼuHr:M_J}  srߜw';:lhBDK>+;"G_yDgWT>6;ǎQM=!B߾'lB⃋orw::~Uwx BRzo;UpQr .L lFؗZKj3C*y7uqCzb1B/%i 0o_R:I& yr\o#=ZA8۾1?|Rq:F:__jNMvtU>/eթѡ$H~M.)qc{Ik,ćϗ=<|8Vy\x:$Hmd `sfSb=kwZRϗ=<|8Vy^8@$$%@Bc};chp7HX;0l7ґY07¤KI#N-lJ՛c9g7ON_ZHC=bxKYE?yrНKɎksQ Q@BnB| !;y{bӹkw.[fc=nt@: 07_;Qh<~|۝(v`p%_FzE q~)o qOl>ldGG[ $K;0_h1FzE D@Tg!7ҩ+&zNvtU + a)]1L\=k1=}i5 yY _;?6GKO{HUw;oďU"w6Jk_.u'JaXfo^]  ~!5uG%W'l !1,[ficb{<4FS^y! 0umǯOJl II>PE2 y26Zf~yLwdGG[}7H9 !w ##=ᢊZKkax!~q:s/H|,u*\ɯs#=ZA,ڤRml~#RɎj?~RNl !*3JT=qe=n_dV(y6|dGG[| | !\Yp]A>H!7ҩhWf !}v`p%'1Fz qłvW>}t';:ڪߐHJd8/2k(QG!78u?Ӟm?j?)dޏL*0[f8+qX{2BJ6_y=qYH$$%@B<.z<ҋ#=eV.`ZN(+ۇ/{NvtU1A$,%@B<~cB%Fy|,Ix2އ1O9C``=';:*_ v@"xvWv 0&Zyd2 }0!#^9;'#oSw9Vyj) [ ]Yp]AxTƾGC`zΞmǯs&H$Hos&Tb`ǷJW<lXRӧ_zNvtUZt@"[exv QObZATB,Sӧ_9Vy ) )ߏ*F{|,RHù &ه*_raA/|o8)LGٯN=LoĊOwEwbO'osGj/~fG n7xTGY%wD B}63w˗-2;Awۗ6ʇ`{{뮻\GZטwF1B}y'^prEEi2;)Oo[G /7ѡVfi/Fx;'V /-EZ`3I٨"`gGE#OP ~4# V ^‰ip{:6;%+Z-j{;P ~z(Di/F0B ~~&f\,lxo0GZ`Kn|d-f&;:*vMH;2\Ȼ^L]d:L|IgLF"lQL׃Ǘf;:~{k/JP\{v&wb!`|\@6Dwټy ȓ%g;:*;%Qiɇbsy;1k/ mi%Zn(f,޼y L׏vtU6?mHͿ(nbC yGZ1?.hC"ցmnt*E0ټy L^qM*(!iɇbM~+l @!Ɣ5Rߛ7_+9{vtU6\̙(قl(!6_ϙXByN. d`Kz*c6oWvv耫l~0J;31s!F&ɵlsRwCѝgUl<| 9WrgJKYPҒ %+=+3oɥva+Am\'~pec@@OlGOOZ|:전%JuÓk;yN.[SAj1<7o~C~lG\7\P"iC ٛ߯"&5l6QEr!߯"&;l 9kU* w|o<| 9WrY JXZ~]?rabg6ߒKm+Am| -P޼u +;vt^MB没#6HqEraVƗK-Oǀ/oZo+Ș 10Hu doWn[ߛ7ݧlG\7ܧ囒!iى)ṀmsH+Q$:a(AW>| s>-_d6Y(!6ߧe'yZ3b!`ZB1~Y4P>| 9WrP JXZ~Pb!vb-mnS6[?} LܼlG\eͭW%Jth+U BK ?} ݧlG\e}Z%[PҒ %$Vm'Wo橻VSGTǏmsW耫l~DbD |d̆ms]$:ͽ 0 v >| 9Wre JXZ~eb!vb-ltxHk?} ]sC XPB1q{B6E =c@@]sl(6W+3t*#mɵz;$c@,x耫l~%Ӓ%ͿYEڜ {Zn4q-msׂ耫l~D %kAwbp%!Fɵl-_ )>~.h%lG\e˵ߔ7C ZН\9mZB: t炶_kA{vtU6\ Eӕ|(!6_ S~ŏms2ցmnSU ?} 蹫zvtU=/W%J%J-ByN.n!neN޼y upred JXZW'VrbͷJ l67Ye4sAǀ/{p/Ϳ))9Jwbp%_!F<L(k*2Zkw炶_+{vtU6\ٟ(łl(!6_ٟXE|K.!o_J$Irc`p/W/4PBl~'W b!`\\@6*ѝs)>~\%lG\e˕R,(!iɇb_؉ͷ䲊B N=r$>Eܕ=g;:oZ.WS&%䛖;1Cl6Er!<&j~$1K O`w耫l~D%#J}Ąl·؉ͣVEray֏$>| 9Wre7%K̈b;1Rmi%ZByʿ:;A?~\%lG\e˕%2-PBl~?KWdži0H Hq<3Qt>;Fo+#o? }0-Gol>ҟgWj tÂG霜~.`bg]l8+yn'iy_Ih'-I'|Xo\JEkR/%yuRMQu 9QBG>›}a/-HulV>6xpu+ oC2y:TKG6P5xw%ʗNQNYxG㟯/6ѡVLif#FA h _+z=唧#[4xe x0ґ #o T~ ^ 3)V9XoA>|]m7ѡaT<4| ^!ZV V~;#o~nwPJGkFX:am*/)lzrA>|dpunsj{3!ȇb70E|'WH1Er!\^RE!=O@l<t |ݿ~yَ6wݿJXPBҒM/*}]oW SZ8 WyO@l<| L`pϻ6Dv gD op6 Era L[K{1K0__mo)(!iɇbu\ؙͷRa5& L 6g !6oaWzvtU ^%Q%,-PBB Kb!F|O.aɂ(v{_GO~ $cosU9W/wVJ砄%J~oJ,B[rA d2[ߛ7_{耫l~JA KK6ﳒXByN. yGsgszrKlR(!OZkXE6ߒ+]\!l6W:p| mݳzvtU{Jӌ(!{Yǟݵɵ_hbnyIK%Kَ;$J%JbI"Nl%\\!dۗ2‘nyl1K07-=g;:*_%[頄%JӒXE6Wls >VxwL_耫l~A:% 31OZmnSGr!ܩw~c`>-=g;:*_rP"ćb}ZH 10Hu dG~~޷c@ݧlGO}ZJTsFj}ZYGeɇms]$:vG^Z_?ඏ_y3ؼlG\e}Z%[PBҒ%+J l6Onb37_耫l~OKd JXZ~J.B>3'\imU9?q'{gs?ß< rz[oGwrk02Й 3A:?N^^ڈ@| ngsv%'3#Jﷳ"_3|2ց|{mqx|o<| ngsv%%YB$!Fɵlh!} t%s@ix(QPBҒ~tb%!vb\Hh<7o~Cp7-.(aiɆ7MKb%!F|O.RmB6ָQAJ-nayَ {D)C BaoXm\pzasmQm@y$O`w耫\nN(l(!OZ}+19J@a !\G hMTyx1K0wsp/7':(PBl~9NL_!FܤGr!| w{1?&ߛw耫\ߛQT#Jȓy&Ws6hC"ցmtDkߛ7_g;:*_ߛS"w|(!6o؛gbRdl6qEr!< ?MQ[ߛ7_{(耫l~A9JP"&$ 10Hu 6Ie?} ClG\e=)i#JP܉K?d`C9(k[c`[=g;:*_MI6gC [_Ąm΅؉ͽErAqY+gdz\p[}gˢ .2-["p59Z? |YPج|)+#8ݦ::~\w @"D}s*/)b "g `sھ{6'[G:'q[ػ\GZ~#r/ɇ~w&^!ZܑV LLHf$OW?5iOm~sjt-Ha6xe /Q#Aaj^6M;=xp- oC2NQ0b]/.lxhGZ`35BdOVu8 ;7ѡVMt1nXm-!wʼw>6xPr.ut4|0Έ܃aT\pxg؃:6+] o[G'\GZe7S#{0ӑ#}:m ^SZ,`3:Tw=S*?aǔ::*r\#ﺥ xiCfË48D=jWROVq8 6ѡVM.|!!68k:18ϥ_+! lum[G㟰3Ja~sjE9 7KG6R<E|K8`3xp8H#z! 0yEfɎJk2U$$%@B,~*32SjA萷26K~I#^} ]sRDdC q ,Bt\p%-1m.S%#im͛ǀ/ܕ=g;:*_JVC j.ByN.y)lseYmSim͛ǀ/U=g;:*_LlA KK6߯L"h+!Sڦgm;K} wvZWw_ߛG/ۚ?6oO:'qZ J50](r_[6P9kҥGH{*j >}6]}j\j՞YyGQWV%,P~jb!vb- xwL!d껗tʑtlc@,68Wr%kA IK>6Vzbsr5,!ܩg6os״耫l~U:-dA KK6߯kM"hɥX n>`iT*tc`֞p/WȪ{>߯q݉|̆msY$:ͽ%ӎt{1K0wkَ旫]JtZ~N |6Iё\@6=DCwB>| z9Wrk JHZؼXE|K.gȗL!6߾2-͛ǀ/䕯g;:*_| x񠄥%J*_[؉ͷ+u=SQYR"h'_+_;vtU6^ LA IK>߯|M"hoɕdc6+x)wrV>| |9WrA| ʇb;15_l6O#ZByD)>~ri%Ҟp/ף&J%Jט+!vb-ҷA6WRWjLD>}1K9r-(P2%JZ-B\ҐL!dk#ffO4mf=g;:~\~ (R(67߂&Vrbsrڛsmn/en>*O`w耫+%,-PBͭ0qbsrjVBݞ`/,'MKَjo~l|(!{oZ]m=\!d;Oza/,㧞ݧlG\7ܧD}ˆ7ߧe'WÞmsY$:ͽ Te1K0wp/iIbA IK>ӒXE|K.RB6ՇgQ_XOAmsi9WrD)dC >-[m\p%71m/-7[?} îɫ:vtUͯWm|%$-PB߯J"hoɕ6kN0pC=}17Թn耫旻n$%do~NLxǟi0Hu d tr)yܵ=g;:ઽZoJʈ7_ ѓ6gC9(k::hcosW耫旫J (!{C;1R6hC"ցmnM;q炶_79Wߔ|(!6N̚HmS&:͝KoWd-ٹ_ /?yD?$OΣ_^|ԙ Szs؃>(dyv|38?#"؉Agz:JЏT(#~17۹w9[j~{D JȾ{`%!F:+6B =LSǀ/oH;vtU6% oH31/mcZByi]-͛ǀ.[nَ6Ȫ>jrwbpEƅmsY$:ͣ%F(a)<~\%0ۼlG\uS"w|(!_/6|##mFɵ9_)scogAۼlG\7-7'A KK6ms`"Nm+Y,Bt")scoۼlG\7noJ>y7bIhC"ցm ƌ ;Oksw9Wr܃%~3±'vbHu dkLs 2>| snߔ,UYĈbrwbpO9L,kAYt(N_|ͣm?6oggɜZ̆o\EF[̢D{;]R5#HmQ$o`ǽk{[PO?Q-:DNNE>8}9zk=8ygw]M` q%M$ åt3JW@ 3,m짴ԛ i~#BR[*/ݐT&qVڗR8&^q8~yutU~J細f#Fm*/[ZD\iXz*Bi }#OIa~sj|{rc#5x .6h)|Ve7 , oCڃb0802#$0B HoiS2^Y)O[G@'<|mCڃ9x]l!{w'!J~Y fp+|Y-'xUu wC oCڃ0#98FԵ3/A?fË48DKV A~/Je~oC2;#Erbs\6}xhGZ`3OKϓ? 2xps?E7ѡVS`dFX:aS@CZ|fd|E#ܧToOm~sjߜ|<(Fu:2b6xL/4V7D]6<(Gӛ! 0;NvtUs!G$,%@B,M*XBZp>`>&h'N>ow8WzOoJ#NF_ R<T.FMU$:͕FozN)=g;:~\_nrP"ZqT\7Kى O8#b!`t\@mntk4̹̳6on'=g;:o/?+JFC jJ/Bq 9SZFmcod &yَjo~Pr%,-PB́^m=d\ n RT޼y lG\e]XPBҒ%b%Vnb'6ߒ A67zAy%JَȭaA KK6ﰒXE6ߓK;^ʗBSy|o<| 9Wr~d JHZ~~b!vb-J !|k ݧ#Zǀ/5=g;:*_V:(aiɆbu\)9r 6OcK)_{vtU6\,(!iɇb5[؉ͷ'L!doW+ϟ<| &BlG\e_(%]PҒ % _(+1{rIM2| 9WrY JHZؼMd+;yN.+ȷL!6*К?} L^qJ%,-PBl~?;yJ-L!6wFz[瀶_+{vtU6\ٟ(R(!6_d\؉ͷ+=W^9?y%lG\e˕%'3#JWļ=10Hu do)>~.h%lG\e˕9!JHZ~eb!vjs]f5\!dY a~sAǀ/ߛw耫l~{s JXZ払\m-ҕ9O͵P*c`p/W'J%JW'V#m\J4v{ M>~.h%sWis{Dթ3Tޯ߉/mZBZ?} ȓ%g;:*_MlA IK>6Vbbg6OW-0WkesAǀ/ܵ=g;:*_MlA KK6߯M"h% msv[ wtmsׂ耫l~ %kAwbpn!F&ɵls-ӛp%޼y ] sZЃ&6߯݉ms]$: CsAǀ/ܵ=g;:*_=(6C ZНdGx>hC"ցmg^\1K0w-hَkAJN%kAwbp\61Er!܋I?} ] sZЃ&>߯"&ycC/ZByPnfJrc`ZОp/ׂh7ؼ4+-eC9L\@6ֈ1PTmׂv耫l~% t%Ͱ!F<-kčRv{1K9W zDۜ ~-N d@6hC"ցmQ| 9Wr-AzLjb;1RmZ9lzICO#g~q|'2ǻMut8 \[;"lU=3 p9 Zni|)C{ >5wp 7ѡVMС[#jjo$>^!Z‘V /m$upIq[G㟰60xo*12b]]Pm^!ZV Sc<ӧUoz::*: ň|‡bw@7^ڐU|xhGZ Lbs{Ä5@ut4xxSt|gDè6xxWSҟgj?.x z^œN%y"OߝZW2[l{L8R7.U꣦,1[ O.P;vq^rP""&"yeC&#Zn/RFM>iu[ǀ/azvtU6D C 0;1omZB5ӧ6og&yَ{|S"ćbs晘LXr'FFɵls-S m&hͧOm<| s~1)(aiɆbc+r5m}"(?}Zb1K0w瘞p/V:(!iɇbcU<'~ҭay %[ߛ]8wp?m/IlA KK6jd+oWls+<̜[}[ǀ/=g;:*_T((iɈb UoW#W>*~ s{1`Kߛw耫*QoMԌywm+k1aL3Пirm勌_1HǀP@sڛ_AsPδcD ٛB+Uχm-)J _Jfl1K0weَ+%SPҒ %++1\p7 !\/^Jm-S>| ~s'-.(!iɇbOZm ![޼y ]sDIdC ~`%"hɥWL!6¿.Rny1K0weَ+JHZ~eb!vb-ls=hJI-͛ǀ/ܕ=g;:*_OLA KK6߯V2.ByN.sܜ)lsu"ny\1`Kܕ=g;:~~(.W'J%J~e?qbsr* !b 5u޼y ȓ%g;:*_V:(aiɆbs`V!F|O.ȗL!d{i`睶_+{vtU6\,(!iɇb^m\<͙B6&eM3?;36osW耫l~?Q2%,-PBl~?m ͣWꥅL|\1K0w-hَkA)D%kA3tn!F<L,k͵޼R:,>~.h%lG\e˵%#JׂJB`C9.kzhOsAǀ.zlG\urAiT\ޯډ†ms2ցmn/mݞ5[ߛ7]sڛ_?(?PB+wbp%Ͱ!Fܦɵlsڻkg"S|\1K0޼lG\e{oJdZؼaoY>hC"ցm\/">~.h%lG\e˕%Ml(!6_ٿfO9.k[ msW耫l~Dڜ%+wb6hC"ցm勎Γ >ܕ=g;:ષ+sBdC y z?;y dˈ@uVsAǀ/M}9:~w외w> Oc㥍#*-XV)ls'Tm<~f^aN2 `V_0_%Xet;W_I^_M>i6RrI+V ]9~cJw޺ oEHt7tmvjC9-(OyDm"dr^ QB:i\.e)ߕ:ȑ>yePfmm짻۲oDX*ATۜH5pQr .ܭDB~_u8(GTGYO wԁNEFw˻Rr \eK`ssju8/or,F"DϿGmkܽD ^Ŗncx)cݭO%~SgO?/|"\ON(wC#!i_ Ow~o짻;"C}"Qpy .x1'\#sjan僧}wt7qVOR-"d}~*KZkP>Hw_2SDozx:tgnSg|;e7", B}~j*n eun.WL lJAD9ݭOw^~SgO+ IE>w;ڰ. m)ﻙ-A(ۇ?' 0=';:ڪWLt KI6*0Jg,aLpJ:7OWY65&;:ڪ5"hY@BR$d/o{PE2 BE“ARF+I<oS9VyjOd > _Yp%+x2JOXYhޏ7_th<~ @r$$%@B<~IB%Fz|,%w<>OǛ.m?=n~* a)Rq{p@"hoq-;=og/({dGG[9. !)qy/xάtXZ ǷN(rޏ7_{h<~; @r$HoGT2.x,dڧOWjSI9VyjU II>PE3Kݾx2B/(YMSC`mǯV$- HXJxv}BeFeO6_AxTμ9<oSh<~ ?A$$%@B<~?#=eV2 6+JANۇ/=';:*_Ob KI6߮O"ȓ{rf {\S3ۇ/=';:*_$~| !]x#-`!\BY0==X+OǛ/=';:*_< )2%@B<~sq]d2 ǵ⥌O>M}L]szId [-J#` {<~y+OǛ.dGGO˧Jd]ϙPE3ː2e{<z>e}zNvtU}k$ HHJT{<ܮJ"hoCz'qqPى_5{[BtjiC`.';:*_B I !߅  0w`sZAxtҼgiQ7 ]FuQK|ewX˿F()5"MWҬK¥D) uݿyQwZp>}a9=';zT;Db qw =02rd2 ǷdHg_{h<~wLI>+# 0.ȬedüKkk=镧C@O;dGGOsHv26HC"a=p ٫C@,xwh<~HmzF{B+> 0.Ȭede.f&<}j AɎWIL II>PN| `'2KYq+ɭ d^mSw!9Vyjd . ]=k1=z0>{}L݅dGG[]Hc>B+b 0.Ȭedo6"u~yL݅dGG[]!џxv |1.ef-`xk {٫C`.=';:*_Bp@s2xv/`x ȬedK4\3ڇ/=';:*_d8#Hos~szqPd2 ǕVpS+?WiSsh<~҉@B<~ &8K(2k|IEU_Ǡ8߷pwiֆZ[^l O<_럪~gV?{J&ج|)O2~psΩJz!͗Q).&2*~3fm%e'"[ѳ!snSg?lBŽuy_eSһp@"DȮw޵ZSpqkܭ]/CWOTu8.or݇FAͷ݈.PݛmRsm/|rv&':|t7qV;"G~7sθtwȩedw<_ja>yx:|q6qV+>"oFܝp${\!đSܽS>rw ScozWy#6DȻ_l\ Z-Ou7>rw|u7MutU_o Bojnjwg\ʐ?S"m=rjN7|Swjw7qN+m[V{GD䃨w7!N3䮓 .+ȩelNWHR>yx:_oZߚM_jmw`XTzQ@_(+p/߉손$+ߵ3f?Fÿ>ڇ/]zNv\Bp@"? ?B+Y|Ud2 Ǎd'_h<~ z .;0gE0Fz qkŜO;jSw!9Vyjd . *hoW.ONR^ig>ǟ?jAK/F,Gtsp6RjjeI5"w۽po܉rvCH߼Z^ߟADG=x!sH?%jυPn\؁?0.Ȭed#\%{?}S' 0';:*_ ɐv@B<.o{| 01άeOɢSe+OǛ/=zNvtUs YO !s!K=.Ȭel2HKw|! 0uυmǯ\8 Q AB<~ >HC"a=\/E3Bڇ/=zNvtUs !saWHC"a=Kg_{.h<~Dn@B<~*vQ|pEf- {hR 꽛|! 0ujɎWW H$HoW~-){`ǭEf-`MOI<oSWh<~zDD \0lȬed[!]G#! 0ujɎWW$_@BR$㷫W*0[f:)qgS%O>|>CdGG[5$#Ho׉J>b8-2kAD(>}f_s?8V||xɎW$[@BR$*0[f+`AWd4ԙ3ڇ/u=';:*_Ol KI6߮O"(W̾tf#9<;A>[;ߓqSi쇾a6z !BxOmVAXK8.e_u:cZ&{n/Kow8}x!nKE6sJ1f \Ҋv7K p#s)u[ß::*w~ E!D|^;,br7Ċ=rj:ڗ&'n/Kww8}=xnÁKE6wv7kݽ供'2r.4Ou(|7׃Mutt;vp QT䃨v{`nZ\-rS5 nL lvJ e3*w/Oww BD6q =.+ȩels*w?WMutU>Fp7 "$ B @Jrw)ݽ";^1+Q>yx:|'7qV9߈TdqzjwG'(wo9QC>3I`swtڿPxx<|8ѡVCQ0ӑ#oNPEQ .s6ҩ@Jw=';:*sH|ff! 0ueɎW-d II>߮T&,x,d+ĤYgfoSW^h<~ IQ@R $㷫/*09TzAq/2 ;gfoSWah<~3A$$%@B<~3r#=3 16B8,𙙵Ǜ/=';:*_< Q2xvU:!#=ᢋZA 1dP^𙙵Ǜ.:dGGO$RK| +4w`. 7 `!\TY0J𙙵Ǜ.@{?qxTJdxTr`sf)E};ϔdI|LC@ ν8~ |  \YJ Y oH,ph\ P@ABJZAN&R}Շ̬=<|s>*$Q'HowRف|b o`& qm Wr33s{Z/UzNvtUS Rj%N$HowUفi+lpEf- {ܘ(P<~lf[s?W8V=\ y>~JW++`vwf- {_;l~#GVɎj?~IZowځv 0.Ȭed;+Ky3zgj_dh<~OVd HHJxvj`Ƿ̂+ O^+WR½~yL'dGG[}X@R $d%Tj`t]>O]G(<}fs{dGG[}HHJxxb`sf9z vG[`,?|! 0umǯB: a)}U2 B {^<38ۇhm*߄t@BR${ߏ'Tv`ǷJWr?ΓqX{wS^yx?>F:um~j a)_%ZY<>Zyj>}hd] R $Tv`Ƿ̂+S ½QR3ld{dGG[u@$<$7`p `#="ZAQZU9c9ۇ/{NvtU|jo7O[yk6~8N lmi1L>וּ8|ݦ::*q9 q2>sq"Nn5WWL lV*ܝ'Tݭ@˳o짻yen@DH*AT{-wEpN9ė'Z(>U^'Tnz::*wWI'0DθNニrN,sj)OɇO8|5MutU>-ܽ#"S"oow'\`.+Q6(wC#! /^6Xw:|uMutU>= IE>w (wt1OQ fkw7?_mnSgϿ/ܽ#"7|!~Sg; \!VԑSB/n'+w?_}m~Sgϫkw!0BMmm \L ZnD|;| |TGYw{ۨoDX*A>ذ.[N9Iʔ@vwAP'Jw~8w8}/DT#Do߽EbE9 !8哇ݭ@B-o㬪9? pSp!BjsޜZ{i/\!VSܽJ(n^ɻysj{wPW͈|ɇ؋{EC"a\JK*i<]<t|X';:~J\b]C-RmqkB>+0.HC qNm0|;Қuȓmǯ !=l QAhgg?! 0u|ɎW!Yrkە;07l,2kZԴk; ~yعthq{7$q/H*;0EqZqoa&F1ms?W8Vys/HU208(2kV'k6Jy=<zNvtUU: @BjL#=ZLM:s╧C`V=';:*_ou@=v`p쁑pEf- {Y^Hc?JyLdGG[񫽮Hc>vsd8)2k}jC`W=';:*_{u@"uxv\iqFzE 4>+O>|8Vy_| !=t`!\BY0ypYg_ah<~㨍( a)*Cf+uv(Saǫ&:+O>|s* - !)U*0=1k1=n~)8? ۇ.dGGOu@ + a)Rq}(=e\Z ǥ;_HmzL! O`;NvtUZt@"x\xf`!\\Y0=ҝ\ilSW9Vyj HoWفP 0.ȬedKi絵_9{NvtUZy@;0RGFz qǫ2FPCmC`zΞmǯs8#HosJ}q]d2 Ǎ !Pk縵_9{NvtUZy@S $9`CpEf- {܊@n>ҭ}L]sz zN@"H%4!SǝA ~yL]sz)d z΄-x,'c{׭}9;Nvt\ l II>jJ-Y/`xH' 纵_yxdGG[ߐ@B<.{|WC6HC"a=5õd}\! `8Vy| 97`JFy<+2kF:>}[9VǯzDf ُ d='`!\dY0>hF)<}[.dGG[u$RK| !]ӅSl 1OXQ}T纵A4MvtUU{<_@R $}*̂+Ճ)q C~?y@C`*=';:*_ | !_%R#=3 y27޺^O<}PDs{dGG[\ǿ!߫6HC"a=/dڇHsڏ_* a)'+;xBG {i)^+A~?y@Cos{dGG[oH*| !oJa8,2kZ>O>|ws~$'2Ho;܁[ş_ȕyҟ>Oo_0ݳ g8igb)<#¿7d觿Vx'Z? |b9J_a㭚`m9Ȼu8鞤b~sjOF`#Fϟ.4VpbEeԖƱwp=CumC2#_6 b jK[9ċ48DKgË48D<†mp#V 7# l3Z#@Ά::~< #oFH:aT< P5x\%++Fk]g"o_o~sjO( ň|-Ňbpyt4w^!ZԑV :00-! 0]'_oi'_$|5bN /pWd:6ĥksl ZDc`lG\&ʿ)򡄸 -/bFR6NlT,kJy06l<| 9Wrf JHZ~fb%!F|O.L!6Jֆv[ǀ/U=g;:*_<(YPBl~rs'WhC"ցm7/i#})-f1K0wgَk8JOf>߯܉ wb!`T\@67 ސ?ۚy%lG\e{Z~SBҒ%+:+37+A6Շ&A:4c`Ξp/v&J%JWw&V~bsr|nBy!5hKňc`*Ϟp/y( JuZ2~gb!F|O.Ə\!6Qo{1`K`=g;:~{1l(U6gJ.B)ҕ\ 1%\[o+;oG/:'q4QDkE1BM+Uz}Jg+ %>|z9ћr5Q%,PB^+[Jͥ0}uFyD1K0wkَ+_%[PBҒ%+_1,B\’6g !\[#_t~c`מp/W&J%JW+!F|O.K~BVǀ/ܕ=g;:*_?(l(!6_ \Xm\&[ Bu~8%:LIc`מp/WWF߯|݉*CKOɵls/S x7ǀ/ܕ=g;:*_|"(!6_EL6gC9L,k͝_>DG'-c`מp/WC*QBl~#!vbM\@6"=fSǏhsW耫l~5Q%$-PBl~5m'7-L!6QzMc@@]sD)dCl|Vnb'6ߒ+(+A6` w4?7od &yَQѲ%Jm+!F|K<=L!l6ZI<7osׂ耫l~ToC%,-PBl~4Zi:b ay楕>~R%lG\e˵J%$-PBl~4Z؉ͷ䂫[ B9k_`ny|o<| 9Wr-hA KK6߯M"hɥ,ܜ)QVny1K0w-hَkA%]PBҒ%kA+oWSii:󳓖r<|X}(.WnF&:39k :>cJo{{j##pi {ve-D{#J~tbe!Foarru5Fwe(ಏH>| .9Wr7%M1~N T4b!`b\@6:FG͛ǀ/=g;:*_.JQC ,B[riH͝4p3sFSGǏhis@耫l~(7%,-PBl~:m'1͍/핡>>t =g;:~\].NtA IK>jЉ_؉ͷ++lso bc@,68WrAR@PBl.l+՜10H 6*O~;,px[}۩o@H T;ܪ2wq Z? |[ɭ66ɇޕß{ݦ::*kXvH-aw_V5xNI. 9E gUnS {PCFq0Bґ#M E{K+[Y ޤ)ia !< ^2*G6͛ǀ.AFlGOUB.(aiɆRmpN(m ͣ )`OYۼy u+=g;:ઽ+R((iɈ7y%m' -+祒NR'v"6o8W[Pd JXZ[P`%"Nl+]BlWGOYClH,x耫\W hA IK>'-͕3abt_Ĝ\]bU}~`˹OYۼy 耫PD ψ;1&Fɵls#4ѽ$Ov>y%|oqy7%$-PBlް7Vm BwFT*޼y qlG\e-%[PҒ %{n+!F<'\4B6^zoc;ǀ/]zvtU6u+Q%$-PBl~Vb!F<'\f5\!dGK / #=ǀ/]zvtU6uD6eD [\ 1l!U$:6k}i%<՟=~g%Vَ旻n}Sr;=>ﺵ+ 1VHu d+4\[?y 耫PĆ_R wb'6w6ɵΛ66_ _>QIG':'q }" $c?>{~T߰]G\k$=~isw9ћ厑! JX LLvrp6N?o]Hүwo4YlS[S:SIU>}"`ucjTV w~s)n!oj[0r#$u0B *k"]ɟe`35ҾyӧVoJ::*8 KG6 Hoi&fpgz'Uoor P 拜_0B {\rU6HC#A<b&u(~+O7xoz\bDaT|=g^-w^MGZ "H)'o ::*- yjCňbwչi/-EZ`3xڼ*>֯RxA~ _8dGG[ / a)$ݷ+1)BUrEy\K?}_d[鄝o ;vtU6~Q"aD ّbq'&>!`B\@6W*mZj7NXTڼlG\1STl(!;wuMwbJS%=|xY$:vuZ~[ǀ/ف3ؼlG\ex_w(!6 6 b'6ɵDOCl:t mb~p?mߜ]ѯy% Ŏpͯ%A KK67|#k;y؂|By&H?}*Rm1K0pͯ?iȽ9JĬ ?cC9L,kͣ/% kYNEva _MD?^gZwds֭y>Xr /6_o٘ڍ)c(7ۘABE<>g_B}Su_D'1Jȝ~kȝ\l\@6B(7_ؼlG\ei)H%J}Ą"EƆ؉͍ErauJHy%Aَ[}>oi+ms.hC"ցm4_g"ny1K0wKp/4H\A IK>oiXE<%\B67&?|01K`nis+(!iɇRmssAb%!F<'\I3m? Vjd &yَ['-|(!6 6߈|d̆ms_$:͝Oߤy !Kc`"؞p//QBl~v'W|6QEr!&7#޼y ط_ՏyَA/J;=Fj߲ļԶ10Hu d 1 7<~R- zvtU{- %_PBҒ%do~Ab%!vfsSGqmYFNUT]js49WrKoJJeD |6OZfA|i% Cǀ/OZzvtU6D>iC '-;1)!>hC"ցm/&c`p/Wwz|(!6_ٿ+k 10Hu dkb(E>=;t)yTc(5֓YPU=PE&QcMhKpRu2JƗ*8҅i\s19ћrAA Ka6>Ym\<S\!d[g kڞƢny1K0wp/1HlA IK>cXE6W0oͽ.ny|o<t } zvtU__c(l(!_cXE6ߓKG?氹/ub߾!?vSmB\a>87^LΞmu~0߷ gHȲ䙝LL}7ٳT.n:Ў.j1ɐr(nɇ՝u@N=m F pGHB~ņy:6+ KUg~#o>/ oCy|gD7ӿ{_| ^!đV ȏ/mIȧ :1a~sj? ;~G''0xoJt1mpQE<\:6[-I<o¶ąutUӔ0U^td1Ĉk" *v[ A6x4%#_C\GZ&sp`FH:aɼP5xOi#I6^_G#o.v6ѡV4.bߢaߵF xlÆip:6K/dOZ)yLtpxɎJozD~\bw-koB* /)\tY@<.0}5ۧ] o6. 8WM/JvJ5FJ 1VHu do"6[⧏]m<| &l8\ڼlG\e7 Q"OCfD È31ub!D\@6z-͛ǀ/g;:*i\Uˆbs晘Җ:Ո10Hu do;ųcWssϿyT\:o1=ɜ5 Uu߸^E&Q/&ӕ7݋#~]|'o`'|\/15W=g;zTQ.wyP"%yϕoKGr! 1I!͛ǀ-sw"9+zqAܐTG/w#"&D`O9.k} /DN![ǀ/cXE6ߓ 6Ot{1K 'q:  JXZT\6Zm\p%oiL!d˗62_X<~J`%Aَd+dC >Xm\p%3mpx_耫l~A JUZr~J/B\Jm3BmD|ik%Vﭣmg?6oZdJ)fCU7.wLRD1,Iﮐt܏wY~9gNZ;U嚻kCَ,Uw]%SPBR%.qkCbe!F?'vZ6}o7Lcm68Wr/DdC \m\ FEOWJ.o_ {c::~x{q/FDvN*YUϼub #^?|;ilpJKgx7^q(~9akinsj? .Թό ]+b .yhGZ`3*uu?]Uu(7ѡﺈQ|C666xJ+lAWz>?|e 7ѡVM=ap8!ȇbpy1=E|K+illҙWtWo*::*a= NGF`E XiV]"OH!- gFC_DLa~m7wd y ≕\Z1R(=;ǀ/&9W%WPBҒ%/\XR9S2M<[_LO-^ۼy  {ʔ68W=]yS%OQB)<+b!`B\@6WFȊ[%tߛ7_ {ʔ68WMO@)C 2́[؉ͷjͭ%])cMx]ipՓ76D}̈ݩw7bp%nfD9*k^8ъ@E?7o~ClG\7\yP*QB+:wbp mZBy@nW?7ossZ(sdC y-tU쉑6OZfs3pd?`y%p/Ӓ(|(!6MKbe!F|O.ɏ4Bm)'v'-c`=g;:*_~n~P"w|(!6|'#4!FFɵls{@pN>7os9WrD)dC >ZY؉ͷ+M Si +;c_DOlG\MZ)(!iɇMZ\m\p] Byp@GMw͛ǀ/A?{E1oyK;S{A?2xΉ}\~B%?Xh}1te> 7#DW$o`_ڪ@>O?Wj}Xَ,UD.;(OIPB~1+yfC6?,kV[!f >+O`w耫~\~E)2RiɆmtW6Nlb,k]T/r?-ǀ/o :vtU67gD y[L T{->ht<ɑ\@6wR3gU?d} ϣ耫\{P>`D yr1'-|ܪ2Cy?-iyۿO)rox_ {f&LbK{􋼁N~8zCJ叄ZfmH2:F3[ß'd~SgOBD@"DϻA"R~ \SNoƖnjxK4ܭori݀Tdqn eE{)'%:^~tP>l[ݭOtwݧ w"{ BR"w).[NŬE`sSňu8z7qV@n8anctkܝsJOx텖 ϶:~c~Sg?ND w"s BRq:rw)l dw{^zwg n ?N7ql@Jtw)$r?q_o|\QOZq4\C`ꎅ=';:*_Yx@"| !ݵ q6hGQf2 vGW+[/]TzNvtUGD{ $;J; 0.ef- {\ȴxSwT9VúSD~RxL`!\dY0>#{槏ld{dGG[u R, a)qyJ/Ypz1e=nSOh[)9V]< ݮ܁Yc8`!\lY0!kK)gjN]sڏ_LL KI6zN@%"N<2 ILd{ 啧ls;NvtU:| !T#=gd]>Oǣqa^yz?<|9Vyj]~d HXJxv]~B%F{|,2 CLw"ٷs7ۇ/u=';:*_Hi? II>߮O"H ޏdy\ i \w{lSh<~.D~Bu_% `<¥̬ewƽ2Ky>yz8|OMJww8}̤pz7OLwot䏋twȩedw!^ jw7?_ݦ::*w/,R'/DH*AM@JvHbl."[*G'[·u-,o짻y݀Tdv}ӱqr \sNYSQdwl×'ǻTGY>߈Tqn E;\Z6w!G?|[jUTGYV}#R "o:ZRr \.d B|*w?_'::*w: IE>wbUH5pQr .~-Ow?_::*w:", BsU.[NAPU9L l (õVɻy8zV8ѡVeա/Fh#o:V!N]cGZ-`38iO/?|VZ8|f6VIFs$,%@B,Pc\X؉Ƿ2'<dԫL*I||5ֲuL^mozT_x dGG[u JL@,x,sRēA f\$jǛ."dGGO5 ) a)Rqw*3#=3 Y2w/Sk+>_xSiso HHJT{Pz 09J> {{w(V{yT,xwhW$,%@Bcn]Yp%d=/%>_xdGG[5$A} UX}f#{@"ay @ +O+lSWh<~dJxv d `!\BY0W:FO_Oy6?OZڧQ]Z-Lvg$xC=bx ,Υyr~#sZ\d"ylH\ f6ȝ K,2k[( O2>|Bs69HUJrxv-a kc m:#W9?O>iSw9Vyj' eP$,%@B<~EBFeW. q`<|DsN$%-'How؁x}2ȬedGCPh7iY_;Qh<~7$O< NXo}L]s $+)Gc7ef- {\ w1!~yL]s Q ;0{Q6HC"``U`RGtWXG*9mJeLۃ|oj8-rz0k2Jyo֖B:K{JۭWYxTGY%C܀Td1MΚ5pQ9%nvS> WßZtw絚"$ BRv7k"ݝr .݋';2ґ{jUu8*4 w8}^y[DX*AMufn eE{)Kp6w%:)|$ݭWYTGY݀Tq6^.[N|f“n{9/c>yx:|MutU><"o0w'\p!V ⏜ZngMxym=XUu(|3ޅMutt9p"c/>jw7_zp9kz6(wC#!_A)gO:rpwVu;aQnjv7Zn)]uyhAdOu8|yMutU>?ܽy|!w*(wo9K6wʐ}J#OԤ\GZ𢡊M+aȆM*0[^}$\ \>_λy/;NvtUϾo. )M}'xIɎ|A>c (\#="ZA,H{7s2k7_;th<~ʖ$$%@B<~JBvq]<diKZ?9Ǜ/Y[8Vyj_oH^x7x<3ґ?`#=Rf2 Ƿd:s2k7_;h<~G]Rw| )Ys2_h<~_JNl !1%Zؙvg {܅GO~?j7]3*';:ڪ/ϡ!!)UYY:T-+SAXKW>b}詻hq}Jd HHJT{\l\}C,ay2=n], M\kd&xɎW{d!d q@evr~O,r?ΓA8y)kC`*=';:*_mt@BR$㷻*Fz|ˬt%-dy)@w{,!9V=Z l !o%Tn`ǿ2K8 Ou>}.[UzNvtUU0B ُB\-JW {\* C~?mC`UzNvtU @R$HoPEϙCX2JOX"Y?C`*';:*_~  *;0%X6HC"a{ 騨 _h<~:}$|RF{<*[d2 vG%^[G_xdGG[U$]@R $[ؙv%dd=Q^QO>|s* + )UUϙW.)Z ^u/V=}PJɎW !_eW.Ȭed !ԙڇ..dGG[պI ~v]"E2 s ǵ2FJ꽛zH~Z+_R䪂6\E?qWTUivG $}'v^b(o_9mfmG?3Tf::*[?-leAKC6cy[ H5p@PNE0>T6=-m째BnpSeoV5pN9.Oٮ;擇ܭ\pwOuwDA3qQXGN-C`sALOZTGYwDDWݝq 86(wC#!yY/ ;'n~|MutU>W;x R "ozRj \!B>I`s7,|x9SSԇO:|= w8}ށpM+!7jw).[NAԐs$;g^!M|dݭ@k!~foW3/D'|0L6\p! "Z(txEk 铇?3~Sg>3BD>qg&0 .+ȩelB2ʇ.lgw';:ڪ''=/!/@By|坁t`ׂ0}]d2 ǥ%2C`ץ;NvtU?y]x ׈307>6HC"a=M),Y3hj7_?;NvtU?y]x l !="h2`%Tm>xGɎ}(d II>PE2 B.'qt|Icl~ C`'';:*_n $d`Z/#=ZA1Ѿ4Ǜ.@JɎ;|A2Tm&#H(;0R}BYIZAu½$\NKg [/^y|?:|s* / a)=TU2 o ǽbkKx?y]qzN HHJx~='ҋ#=gq v$ ڇ/';:*_H$HshҚb`%T}~4! 0w=gɎ9) !)J.Yp]A8P/%C >}2DdGG[d z΄/YJմ2ey\ԥXH>%}L]szoH !]̑Fy߮|30,ay<+Y$u~Cslh+<~3Br$,%@B<~3Z&vY$9y2X= oV? ]rzl0xQlpYfM`x|%!Ŀ}[0t=gW9#AR $9#*5 0kf Kdy/IJ}^!/`zΖmǯsn%Hos<SKY0H_E {Էul9Vxj=׍$9aS.ˬinnC_-'; _!QZb z <|pYfM`xJT|{=^=9[NwZϹ& KI6JؑEzR}2X=`v/_(|~!/@o8Vxj=g3HHJx\x5I݉Ď=CsKs);..csHBU:pwpuOnpq݀HTdqI@J́rw)x< $w[# OspwpuLnpqH#BR"'R(w!wyXwu/I?|f]9x]RfSg{d"H"'Rw'\Rg "@rwPBԝ5 w^wj8nwuFD2BT^w 4Vw%_bqBS_PwpCεwF&c#Fo#*9 011dpxBxG=~.BCכ0sxb7.e A9MX\x'FY|,xR=f2X=.qe%xұ=pX_8@2$,%@BV=$HOr=ΓqZyW~.C?H1{d{G[?1y ɑ?񁄬OzbOI Fz<2kǵ1ev8oǫ7Nw?1yNI6߀iO{ 0N,ay<&0wi"1&; =DHx, d_>6HC5 )YՊ]ǫolpq$H}@&vqd&OǝGTwA:^ ';ڊqN%$HzW8q@e&Fz|,xe<ZBM޵x`Pr& !)Rq{OaDLY$?x2X=T/Ļ)|Ճ_8x%L#ѷ~ 4꘤OW@("~D_p!I^1K T.C_н[N,ڭ1Br2}AB>nk$nkf``8{X!S]`7Εr2vHXJxvJMY0ez\I#@7Ε$rV2;$3#Hoy?0.6ˬil7Y~xzj9VZC2]f$0.hEg5 1Y$|GmY h=/M5o>*VW֬iENȷ=n"IғS,½B!/kF*>Kx$de |]S#f< Vû{C5߾~ {d{G[˻He ]$絟5I`*`"߾~ wNW{$/3HXJxvJMY:w Vû VQ^}C_=ZNws!B $$%@B<~BD%&Fz|,C`Z!ׇ߾~C\h9Vιsa KI69{.DT=3+>L$+cEwtxW;!$%3HHJx\8wf Edy\iRj!/t6߾~  AWB!a)]"*9 0)I-qch/voE?BUsYi֖ǵ~E<Ե𔾖'Uh5nęՏ?=&kcle gWօs k{UE{4/_;Cy];x9?vIZMw>IVDJE>w`;%ɓKlpQXQ{NMC [ ^*b[P w?^=NvSgqvwkaKE6w6V9pQN9QCI ;H_k}Ίݵ@jp2wj8nu\QV'7S(w9%5ӄ)>Ģ$u}R޵#nCqMoktIG>Iy6Sbgy!/`vBU7#$AR $'U7c9Gٷ UyĔqD:٣;*x0ݟNw?3um #HOD<NS'0KvYfM`tZYȻ÷6Ч[Nwz6?VP癿}wCWi9V;ܿjr TC>HxޞY0X=D GH|{=^= Qd{G[=UvH@B<~ ǹ#="̚q-{I#W@Clh+<~'Օ$W`$k#=ᢲ̚q#=DU֒^zz /Nw$kD]qq+0x82kǭ'W~?D0tmǯ! >Y0x{ lpYfM`͈ u]C_UNw|^lUV`$;mYfM`ZǫD_?cєW?O#wBoґtF|X~EӿPo\+g-'ۯjHvX|߾#o*pQYfM y<۽X<թ-_I rp/2%AB<~3\De'vqT3S^JJI|y=^? d{G["$AR $;ETr`̂'!.r-^B.T G7BzǒynDŸss({}Om0;xLwOmn'ʛF2C/G ƫKZ_A|XTw͢|W_T;.GA=pk*JOLSD>w*i˟U)wx{5\?{%T;U 3\{}/>E7O`dwFHa|2a J}J+xb|?o()^ ~ #w[kP+ ~xYBnтe1] /%xh {Z̓`5 `^@r8~7͵w?l#H|!w y/:ċu 7OZ̓ <[UokGߗ͵w?lWHG#F?aOtċ48DjFx)^:v8j\{ZaRoF0B ~\i<eË48DjVrޙ}I#@\;~<7ƈè4x8 yԞ)WaJvP+Xi[;T05sT0rjɀ"?'P䳥6D1wϧV^I{ͣ~ WنL*>NW ,%,PB>#׹+&!FWn%m~6W:'RyW0v]j+S?߯Y$Ďl L!6‡Y/xyW0vj旫W#%QҒ %W#+5 1kr) +Egl^=]rJHgC ZJLB\&]5VN5ͫǀ]ramDVT|]'b;10yra[!Xzy2Yc_8xؼl{\a(iɉbsqjbG6Oɵv;3Al4| Ja__W}b g;~\\?%,-P*m.*N(7؁SrA5l!6[xzgz9[W@sAbm~wNI_9QB܉6QYr!,%O.Ecsڦl{[X\)Yć$#r/tܒk]aߣK`^'0v\b{rN%d{~F 6Yra0bM+/x:vsprs|(!k͉6b$mΆms%<V369G1`[ζw62JXZO؁䒒<fsR+ů_X? p%rm·b󊝖<l6iIy 6Hmyͮ"ؼl{\o~9ч%zq웻6߈IGܣň؁ͭYraYzc?Pybm~oJ!S>y7b+hC,恰[V:{/ n5rVs;%r%[mIq!Fe5Vz O'{"yW0vp/)|(!6jMLzFlʒkc]!X65vpžVs@ɉl(![EV;yL.S͝tׯO + g; _n5)|(!6m$hO"SۗA Ik1`D-g; _nN)ٌl(!6ߜ(Z&!F|M.x԰<%-_>~ +OK$+픐C yE`LB\ fX 閯ͫǀ+ζw6^beN KK6߯쏬$l+>ɵ9;~/W'&z9c?n'!BۗmXN7!q_KچTaZkGLyfvsjONFagT##FΓTz^״Z$Ո+dp8JSC) ^;3kP+ ~r|7Uv͈b3W^ y^!ZĞV X 2Bi)O_Ur(~3;~ܜ 1J1* n΍#A3EEi5dpxokG\{Zaߌtd1m";Eo+GxnfsjONg_-d:a|8br /a{Z̓`5xL+'5xp lC0ɩ#Hl!?;<†}E<夣OV!)fsjONg;#$0B ~v4m E<<3\$/Nh)^׎?n͵w?m780 ;#,0B ~vbp'Hi%=!jpoW.OVr(~7yvsj .Fjg#F^0/1A kxӿ=}[aǙ\{Z?s7ƈ%#d ~v'bK, ^!ZV X S%߯OAɆip<20j+ ^;+5;Ԋ]5oFdEF.̕2 jcE//h+^;#tm2VI%| !{ <ȝ6HpYf!y&.,lΒkCg햯ͫǀ[ζw6\SmΆb51x6B9Βk͝U%"o_~ +7o8y%jߜJ |6YraWDrt֏@l{\6\ֿSӒ %dm~#O5b!`L\@Xmoo&6HoC=AܝEJOpkGJfvsjO:~3"720B}owr /-YZ̓`%Sa%w>+͵w?鲲͈\aJi 7^!ZܞV XD)/(<}[a倽U2kPmpyYe7ȑ *>J˳*W^B`Ë6raOy5xpo6ޡVJf}#/EaË6aOyƼp84xPj]vsj .#3*ӑ. s:08ϯ8]"wֻ¸$%Hφ_S:tX];^Rmkӗ_^9|8`ӷJ?*;/l-!S"^^럾 4xso6ޡVOsf׋!ȇ?kYPM‹6xL+x|1E %xן͵wL!aȆbv>Hi%%>+AWx+OJW?vӟvsj|!'w^!ZĞV HAX$f[G]<;d{G[!mvHXJXݶxde'!F{<<Ƚ+XlT= l{\-(!iɇ@NBn&oI&Lp'v`s,恰;ծRAWpQdm+l~3Qd3JXZݷ9ғ;KGf arrכ׏c7'j9WrsHfC D o F|M.x6g ajyIk1?D}Bl{\q HIedC 9r"6m5)',/j|Ŀ~ +LKϴ%QBҒ%gZ"$hOrm |xl.^B:kňELU;otSm&;~;Pt|T '@ͽg˥[(KZ#_\È֪֗rqkP+u#_殍'Jc81Bu )bF~3,;!=A |/'vpii/7x?e #'?!OAfċ48dԲ<^ Od÷͵w?Mb#$0B ~ҙ1.6xL+VM̈́ ?8 LkxskPmpw,3xчlw'1CP4V`5| "+G0x=sG}!ȇbpq!nL6xL+xE  DJWpqLdd I?0BZ γE<^///XE9IW=W8]B.:2JHZ򡄸sOBt\$2\o9ܭ^׏y.́(aiɆbMB\tAXmկh:gѝPؼz +i7m+l~ܴ5Ѵ%'M[Q'b$aD9͒k͍RnVJ1|}m^= ^pEW%,-PBl^Q$l&R6Ƿ/L0D Q#yW0v5g9#%Q*Ӓ%+:#+= eV"l!6.bhBegͫǀ+;[ζw6\)|(!6_YI6_ AXmT)xK_vؼz +ʳl{\au@)l(!6_ Lm-y+a/0׎}~ϖpm/|tdx%JMB1+dsx:a! X=W-g; _)QgZQBl.*l?11`l\@Xm.52jM&egͫǀ@[ζw6\)|(!6_ YI<%<}sVK}MkjegͫǀkA[ζw6\ S"%kA7b\m#js傎w',~GNW0v-hkA#%QBҒ%kA#+3 #JXaKWKEc_ص-g; _)+M>݈߯~10"Ky 67fH+o Ʈm9Wr-hd2JHZ~-hd&!v`\z(r#=Rpc_ص-g; ߸MC Z71I`C9ɒk͵p[~C\W0v-hkAwJWf>݈߯9b!`t\@XmW/_-~ +l{\a˵(aiɆb,l&@͵/* _xEo6q[(H|CDQip}vE4>X{N̓ [Y^Z|¸B޵#xz%wB'gWv}+kl!>;[1/1A6nԒwpX; W+#Ka b  /-aOy$TqB)^׎?); Q fD1 sbË48Dj0oȗ< ׎?ɔ; K ;#$0B ~v*4/S:2x7d?[Vsҝ4xpF lC0YZ,;#,0B ~v1xmVz!"X xyP7 ؍<7x7'3ÊjgT##FY'j^cZA2_zO~W˷# nC0Itd1mp@%E<<\$EX ꀲ: G^<{ }_B :&~ (r|“qNQ D%џ]ǵt᷿ԏ}]v>O^,D'}ֳO70J姄=볎|JIC6K=恰\[i^„_M=}?ii1`Ԗp/,JקnI5C9͒k ĀsvcJ 6o8W\_(6gC XIۜ 106Ky 6w>N;(OYW )nX+AC2G*>7 %w($|T|cX“t#D%џ]ޅzڅ_&R==sZζbW5gD+~!F? j`x: ut=Qǧ~~|iHd2ύQ6I"D*>c$LI &hC,恰<֓Hh{w"6 rq;%r%{mĎ*m'<V%E}cvW\nqR XcdC 9s_\d&!vd\Jw/~\SNCE _Jr6ꅻk𻻻T{YゝoD~7DmwG\>(wC=!-/KaEw}nwwWW;${O`Ioe4 V !ǯS?tx0:d{G[+~#+Ho}r 0ƛ,ay(pfUxEǽ$,%@B<~R3x\Z'F{۷C巜lh+<~.?B$,%@B<~.?2#=f<O OglUQzwj4A[x;Ed! B^@zcžT X }j.Q/ednkoE;(; qldEDʈ"''.xP=T 4SOFO7)];x&Mw>3ݽ!2d&DOvLJw'\ cr7Jsj:2ndVv(|;މ;~FD. *mONNAEb95 n{kFunXwݽ!d8DȺl Tc0>(wC=!ܝkM>|'[8T{Y~߈n>wt-ݝpt7\!VԞSHqoQ,NRȇ/b+]=lfsjm0"aTۜt-xycɕ'\YjOi$[l7"Ry` ^@wlh+$~c6;, vHHJX\ܵxDLx,xNPޓ=|[!/`ބNw?Myrބ0x__#=b̚q6bw>rճ( !)ۧQ"YOO;FKڐ= )Md{G[ބyy$' 1'`$עlY0X=nodlǫ;Nwg/{:r:W`U#=ᢲ̚q դC=|[!/`( '; _nD` (+0g%`!\DY0X=-|!{^yCmže Q* !*=c82kǃ7%:Blǫ;]lh+<~*7AB<~ ,><g5 qeyIawz_aFxW^EH*$H]GTf`Sf:CϔqaexI,uN=|[!/`.*-'; _ a)۝T"*7 0kfAPwi2ez޽}I>|C_UZNwSe II>QI_3 ~.ARu;JWy*-';ڊ*WDH.$HyU"e`ǷZUĔn|!/@Tdt<9\H9pQN9QCJɓ@r7xƒoYv8|qMw>>ۼE숐Tqn eE;D y†'n YsY,];x'3wj8+}|yw7F}ḁ~\SNCE i^Al#>yx`pl6qV"'7Db<ȾlpQX{NMC ;_b! yW?ޝbεw>RlyFOn+x,dw 4 afy /Px0=4[Nw?f:b{hJoI}Fz\į"{fM`8x R5${!KW}j芝m5;;$jirzv T `!\̚q=|+]x{!KWCWﴜlh+<~~NI>߮ـ\Fz\Ŏ'{fM`xΐÇ,=^= НOZNw*W8HȾ'0xR?Fzf5 YF,=^= ]r՚ <>6HC,az(iܲ~^C_ '; _7* l !?nL;x,&cy-0{B"o8Vx qj qe4 V;a^Iz!?P -d{G[;~)H:;)0x8Ԓe4 Vdx{!KWxW{Ȕ  lOx2< D@  xv cNw@"_Tz\_ǹ#=ᢳ̚Dx+Y1뇀 d{G[kD$HzvG<%q6{ \\Y0Hy6:?k3뇀;clh+<~7V2HXJxvwJM1bz\X3HrhVB4xb_ W?f'FzEe5 2ҦrwjVC﫴lh+<~u_%B2$,%@B<~{_%Z&Fz|,;2yݕ@,吻T{=&ݰ!QgPH9p9d7Snq#H|y];8; ww ԎKE6w:́rS#< $w[8.<|Na!/`>[Nw?>C(9OO] Vk-+vև߿Szz IW۞| '#How>yӂ?0.>ˬi7KFfCr.(Hd ~F*lp YfM`x%Խ^wG xW;DH.$Hm*= 0)9Kx߿Szz c4lh+*/$!퐐$HOr'^.N̔WA:t}b=~ AR $d=~>ғ#=e\ VO̷/o9Vxj}2HHJxv}D%'Fz|,I`xp%}AO/DCොlh+UVVt| !*W`I6{dx e4 [ /oS? }^d{G[U2%AB<~JD'Fz|,(3Sǵf!ݵ߾~ /NwY%Br$,%@B<.n{PY?X2X=޽4A^M>C_UZNw_ | !_%r#=ez2x‹:,zJyf x/l5qq.ӌ1hV~{* ~3oB+H㦖j`Om0 u#xG)~B' JAb9C?/"^IIyRwcH|{];g o4ޡVϳޤ#g' 2NHC=An۰rq7aR}倧 mfsj .Of#jMɈQipyvA}E(~i+俾^98; G6w;#,0B .nP9xJ)˗SNy(Ja<\{Za(>t19diHҊT JXE-S;~򋒛͵w?')Yeg#FnJ~^SZ?KA2A okGvfsjO.K쌐t1>2/)A"H{ Z~{ ^;g3kP+ ~~v7 #,0B ~}1xz^״>8Sc NGokGCJnfsjOdӰb? fp(^abOy$ÀK,(kEx0vEfBk2?r| !_}s"vǀ?[ζw6\S"2~F b06Ky 6+x@v@c_u-g; _.lF KK6߯$ho%ǬQPwUcׂm+l~tDm2~-F Բ10.Ky 6W*~i+Տcׂm+l~tD0~-F 6Yra*^wBwՏ}zZЖpm䨮#(6xIC&f|\@XmE5閯ͫǀq ykAwJiF6߈W!v`se\3@|ymJXPH `}lW卦;~I{,q-ՎIE> =2FoՕ+na|Zi ]BkG,bfvsjON"Fvg#F!Tj^SZx~.ۊRVK§*ߕ#x0_7kP+ ~r0[[)wFH:aaip@EcZA܈$+K H|{ ^;g3kP+ ~rp780 ;#,0B ~vް4~^SZO 5Y<'6HC=A ,|q];: ׎?͵w?5b7802;#,0B ~vgDip@%EQPM‹6xL+x${+wqvsj/#3ґ #kiV A28z0pEI 8 Wc7lh+$~>h$H+*31 1)A~a y\_]~ݛe1`p/WGJ.%JGVzb˷lVˠK()O߽Yڼz + `p)˵;%J9CQaDLEaC9ɒkSe%y7ޅc@_x6ό( Ml(6OIAV߳!v`s[;kͭQ/u[wo"6 _7m+l~}mD$ɈbJLb܉6Yra6 >uTkݛͫǀ;m+l~NjrĈb]UČ|<<恰~gb6)xf.ֿSvVO߽Yڼz +Nl{\a˕J9%k7bvqT_>hC5N;797ǀk[ζw6\d P>߯ScCކ,恰܇E䲤P|61 op8x}CC 9Xo'b@0.Ky $E؍rov:v7pr?7%dC Y&& ,eCvYf K $oy *`vp/f|F IK>6V$l TVRJi_~ +GK旛}>Ҳ?'Fe5R=Ug~[W0vp/i)Q(!6ߧe#Ol61YrarY.W?ϛm+~|)abʠ܀JtwL*ghw5,sKYm p嚻r(~;\{o}%30*mﯼ/x]j" A28|/ YaAkGXљ\{Z? 1d5'F ; /-aOy!WOTr8~r7kP+ ~R|e58Fj~G^/rʆip,A |6§ * ^;+{;Ԋ]˛#O)0BvQ$E<V;1NNv՚͵wkZ#:0Bg#/Ņip<j7N#X\{ZaoFTu #FϪ3K'^ZEi5dpk|WVC:k nC0IMn7#Hl!?, 2ZE{<V 2?}Oìw,o6ޡa ;#$0* nW. ,hǴUA2xN"«q;d{G[!񓋕w$ABR$#+3 1)&C<.&Q{ݔ1`!ڞpOnȪ{>=><'†AuQ*Ky 6!MP[R; ^pZ%/#J+5WbWN6hC,恰\i[T?};Di1`-g; _>3)|(!6ebͷ҂ia ayp%u[R=]r*|䗌l(!6_YB)I5s aURnyv#VW0v=~+v(!iɇb5m5 x\!6*~9nڼz +l{\a˵@)?dC JOB\$L!6wZA x-o Ʈl9WrN9%+=7b$kcm'<V{5lk1opu}(l(6JLB)I]jz%w$Q=upry#J~ J,>ɣl7J@,恐l.XxZvᄑ6:v-bm~D𡄬󿉉 'bR6hC,恰<ܯk1`p/Wh~eF 䲔 106K.ql[ /wDH*AT;Dܭsܝr 3I [OEO_vSg fl!wmu Sܝr v7Kƚqkt`vSgf~#"LA\ X+ @r\XϞmXXv8nnp?Qa}w)3.1l:;n/a?۞twp铻T{Y }2w#BR"Ƿ qd \SNt7Oou#׋0wùB߇3}شg#FbeW!~g@2˗1 g["gk*Nw\WDnX~m x/N3.yfM`2@~@|WCWZlh+<~r +0xFzEg5 z1% +϶D<^=]yp$*+HW_4?2kSk$yنX|0vf0?ȥHoWbnI)Fze5 IsNW ÷C^Xl90ث@"Ru<w`]}ɬiO8 _ mǯgq>_q_^CWi9Vxyk$HoW$(3k gO㻗Br}(o9Vxj->@r2$HoW*&F{|+[xMwv;FD0BT۝n^qIAU-E'!ܭU'Sv8|qMw>ݭU e+|!w (w9ېX`cnSr84sw7j8+}\; IE>wh6>(θHwǜdYKuE_Sv8j33wj8+}\?+.a_ ncɠ7:ͦ; wWd6N숐TqI On 5 w5\@uSv(|?T{ow7"'>Jw 6(wC=!բ_xs|ݵn7qV< G\!V̞SHkvS!&//Gj>wùbh~B#FȾI| Edi5 dp!?KIݬ.Px0^|mď+wȟ@B,~R1_Z|Ok `!\̚qwKx0^|mǏ+3Kd KI6T#Tz`G)t<Wv >TPzz 3xmǏ;gC&'#HO:#_/0|pYfM` >ɭTMzC_OZNwdDmu2xv HC5 ,%JWyN(-';ڊ3*W{| =ABN'ɉ0.>ˬiҋBRǫq{d{G[}Q"$ABR$#*5 0)⓪ub y\ SXPÝ˞C_g[Nwz^^x <>(p YfM` ևJ9_R_^Cwj9Vxj$㷻]mIqem2 mJ_G/N Wsd맸` |e+>vQޟO0q/!lsB`ѝDϕYWYͦ; IVkkVOWڀ/9"? VS XJ\W5gq__[W?.uB߇ܹaȆ=nR0/1m~))^v8\{Zaò$F|!? s" x=*_JR')^׎?\EkP+ ~XP\ +wFX:a5xa^״v6bh䟽Z{; _9r#Ǖ.x/-YZ̓ '_VH8okG͵w?, fCb3x ^!ZܞV H K>{bp? nCa|np!ȇQipy\=-6xL+r)dpgrAmv8~q͵w?, fD~%1ohܒ/-bOy$EۗWĥqEZo7ޡV27YÇbJK+E" "jp =Bx;kZ lC0K{~ȈbuUk9xis_bYgq_ Ʈl9WxrYNZX1~e8btmɒkCIK|g/x@m^; ^p*%Ξ%47bN!vPko͒kͅa&E W^ټz +^l{\a;%rm·b51xR6hC5RxT-__W}jpm.%-3JHZT\3V&LBkrI=J[.SůZo r ؕ-g;ZHfdC Y߯Ə$ĎzbL!6f5ӎ:l.~?~RNy/A<ςdpUqN:>)Q3~.<)ҟG"K?R 6F}_z A^,(;|PB>%$xӎC!6X$<Vx 2ǀoݛl{\+;%|(!O&f 106Ky l6 b =ߘQ=W0Ͷw6ܩ(iQҒ %́ؑUZBXmw/)Tgԏc,h9Wr|(!6߷ m+>ɏ4vt~Gr):݆O^ =v>o|^{dm]'8 #ZFrTZ=_spސ9\{V1 ,>aċ.V؀i3!H2ȗv܅}za_nV3kPKTFfg#FrVI7/kZ@n1E ߽\Pt#glC0归7#H0Fd/ ~" ѢA2w*pSR;ػ(; _Ey3 Άb(wGχip<%OfO7X/^=|kʞ ';ڊž]A%T$#H^Y]OiMBxL-x̆ y\Q.剓1cl{\bD YW|#&UŇ0.Ky l6^];+1mfsOzI c_f; 6S"wZPBl+lE10"Ky $KOO"Qؼ~ +0Cۼl{\ass;%L Jm-?11`d\3@0Y'۽Vd1E?BWk6a+?I/@X T{MYo~{f=MKYIMSo%Pvp]ɬnCIߕ]tqYߕ݀JwJ+x'vENv8k3kP+ ~Rl!?G e^״ mpVǟ?⾽Xљ\{ozޘ|g՜2/1A \ _ƒ7?ڧ* ^;lafvsjEÓbg#FٹJ4xJ+dӫku)OTv8;Ԋ5Inp`vFH:amx}HlT弡4O*Gx"5Yf^״))a`Joq+ ^9; _Ffg#Fxc ^cZ))dZ$=}[!/`}m/old]0XNJ>΄e2kbּp:%ើ  YlPIU3JXZtyd%'!vTcSBXm.cgYힾŭyW`Ƕy"eF IK>6Vjbk 6W>˪zoq+m^== g; _nS0U<'†ms%<Vk%b3^mB-nͫǀ4m+l~Vr(!iɇbT"Y<%Ȳ4!FFg5dUӗrrϼ̀gYl_f9|'!B/OU EDd:7!oOYzr8ϭn6ޡV7#rŇb3+#/x[lxhj.\$<a?y42;]_0.KS"xhl5O5ܭr/HR5eẀ%y6ko ˦Y3 @E/XbZA2RVK2; 1iO}1Y 3bK)KÆip,A RHOnc=}aa, nC0Iqn7#rӐ#g/YƆip< G\=}aa%͵w6=) 1{aTܞCOAE2*Ky$; d'o7ޡVb7|! . ^U{Z̓`5}' xanfsj N1 -X|wg"AE2jj*Sӷ:`Zfvsjtm7bY_y-d3>hkajp+hM柾4xpc͵w3~d15x /-nOy$#+ڙO_YXv8/ nC0=ߌČ!?F4ː|x&uOޤjpʷC_#NwA & 

&.&ˬy $EZ!by²DW0x;pʯ7PN;3FLjrAʆ؁9{ra/xc^{ol{\qFJ3JXZRYI6ߒK 6 _ {{c?P `prˇ6wm΍!Fe5)_tE{rW埛Goj|4$sm4T-;QrOgNg.]xKFviecz!]/d,?ǀǴmRrL2JH |J!Y-;0\ 67RSJ/dD.7v/půJȯlI^aC9Βkͭt5KS<}!ci1@lp2;%r%Wb$?;<恰y^O}op)cW0vp/(|F KK6RYI<%<$"K.ʠbY[?{yuz퐐ס?7/= G~z;,GEEv;;I?-ߟ+v0VwŚ/ZǟTRRBg/+?j(?NgM^G)!iQ @j\SNxg**n}Q%7ww>7s7 ;", *}.n %E;<"ŋz?{)_n7qVGCDH*A[u7sܝr x}.[j qPݵ+mvSgFwdqﳘ#.xr8 4Slj_Ʃtwpunpa݀(숐Tqqx@Jρtw)x;}P߮猨$hz^9aR[3 (sœ@rʾԲe|%wp,npoDe>w*Aq<n4mL$wgI=n +2!B}rt72s"SNInz+yY׬ vSgm{C$fzݝpnHeϩi$w[[.^J_pwnsnXw尻Ɲ", B'79vq9.1AyHvA8(<|Zǻ!sw7DnG"DOno@$(w9e՝)AWS0/k7ڐT{ow;2wwDX*ATۜ؀V΁tw)x;< $w{#{=؇N+];8; wӰ̑"ⶻ.#c9|pQXrj g:<|_Z{o7qVj黏˨", B}H9p9|7S0u ~%w%]np:7".#DoW¯$WlpUrONMC [,BZx:cH|y]? ]r0ղy$+7`0Ee5 ޛ2P7熇oFC<^;]#p*$2%@B<~N~O7`!\lY0X=C𴒪ߌVzz ^d{G[;$r$kh[̚qHMvQ ߌxv d{G[ !)5*B00)Iɓq&ߌVzz d{G[՘vHXJxv=fD&Fz|,xN`>ZyuxfC_u-'; _̌| II>߮͌$HOƇ'<"}z!/]rluJ ś >d]QI2K4 VE xEiC_8x=pՊy^$7`&d(e4 6[]H|{=^= ]r勋ߐ y$77`qe4 V[<"R~Z0tgW+9wHdHor 0A,azi_OtPmWcs6lh+<~ R !_ $H={GJ0Æm/;H&$H;T#=eUę 6"XGS˷oaƮo8Vxr]>@ $$%@B<~.PIOcG~/@zz .d{G[uoH ,>5{`cN-YfM׋{j}fs%^Qr L{o}ѷNIC>Jw˓ z\wCF酨:u-lxI=`Ϯ mƫɼn췸q.n!aQinuRS[‚{\SNA>\ $wK-렩GO3_MoM^;_b ^?9E[o |#?~Msauo`f,K/Sj4{SMSuq=۾Ny#"8!B):% X4֝AZE[ʭǫbMw>a67D B}RV;QnX}rjjrR'_^w?^ZvSgvwo"'Uk.k Qwn4/\byAUG^-wùBj?H!aZw%Β -d$ TP!/`mďk?d Ivjh\(`]Y0<Z ;8x5ǃU$$%@B<~RxPIOO9S8Gܡzz pC{d{G[3'!퐰d q@5 0kf`6xi<|gU!/`@Nw?y | !?xPI_3XO~'` "MlWwJ ǹ#=̚񠄉+uRzz D{JlL =]%V`I~ax e |^maRŸ/>^gp7i oqo ߄4dCt8q/-V ~! %]}TqdvTko%vB'b9pQ^sJl;K5IUr8zn6qVGJnYA"DOzR"s j.J^VR}P)Mw>ڸdqI(wC=!ܭc[/c$մC<|T됒T{Y)߈C`!>R;.\!VĞSH6VՖ: rpwPruwҩ !eQny{ݝp)lpQXrj r<&wpwpCMw^9 #Do.x{&lpQX {NMC ۅE|ީ'];Kx 3wj8+L9"da =.ݐN˞SHH,^ yW?^ ; }!aDnaa a "Ϛ,͞V0H;a<|ZyVz p#;d{G[!y$K>߀}{"ˬiؗ09VCujoc r! l !;wSYs1X=nݶxkJW lmzl$r$d=~K LI `!\TY0Tz`Sf'h|(= klh+<~Oi!xv70ɳl*\̚هH<|gf!/` '; _>?dIx B; 0SyfM y\.=EdqwfTC;l9VxY&`=.:, /|y 㟽hg?@_x{ɮ[?{d7~z6^oD)K4 ^Pr8~T{YÍ\YVQ!:Ŵ~3ۭBRY5u)N?\RBylY9p.6͵w>c)ӱ0G-1B},sj^״s!~%{p|}r8f4x`1qQ9f x_ NHCF-{Z̓ \`MgoA ^;kPmpu)780;#$0* ;aOO1Dp!X nxཆ俽:\O7kP++? naȆ?.\ hǴ!A2QuՊtʳ o7ޡVf%7QmIG>`T" /dpy!)_? ^9ػ(; _EF~g#Fl^iV wQ"H҇WA&5kGob X͵w}Us?KaUE xINHC=A{ j1@g6חP2J>T 7;J~kc=Y]-6kǀQl{\6SeMȝ|(!k]U"+1 #䲖7.w{%(s7Fב f'KAj /`?e7;#`z[Hq}G_2`Tv}^ YN a)ˆPF܋x~3ȗ%K*CmݣkG*3w'P!ȇbZހwJ+xg \J!^JL+ nC0In7#b#gO#/xEEi5dpzivy#xR>3x'w#3Bґ#gK*1/1An"1E cɛv"P§- ^;3kP+ ~r6~71xYʈip<V{o^8L]{4xp lC0 +#K#g'G^ 2E%i5dp7fEÜ5xp\\{Za𓳌ߌ20B ~v:4x\xPbGOZ̓ _nG3#xs]~\{Zas |!?4xe$?" A2[z9`^׎/\{oߌ~'gK˟mpV HҸW kw_ovsjO3" 0B .n߯܈<†ms%<VT84R|c_U-g; _lF IK>߯$l&`!B/Bzuy(+j>ޅ-:63d =6xثNKC6 {=w(;q^| ).O֖޺18ao׎33w's-;21*~,ms" CRwЈ, ^;nfo7ޡVoFT:F<2|xh{Z̓ ..ySu0xp\{Za3w1ٯW^ϋ6zOy_LmOߺYr8͵wKG6R9x B_/,3#Wm f7̓^oa#FȯgjKX2/W̘V*}"HZۗX4yM<}f!/@o8VH].q2HXJX\ܶxd%'!Fz<fD]q߉<" bA2\{I#"÷s]; gN#,0B ~#\ j dZV%5r7r"o6ޡVx<7IG>cf^SZم48S/%*|N#͵w?wR[)AEe׎xm7f-,͗ƈlĈ`9i,XV^R 6Kt +dp'~9eq=kGD;H#3ґ #[HIx_J0W/H@|B#D\{ZaM$\IG>o"hǴK ܋%qN𥄥kGDHx!KG6o"Hi%UA2xPοbBIừJWch8VHr !)b$#=R Bg6Bx -9ǀIm+T~P2%J﷔VOBn&*g a^5䉉wǯ ح%ZζweK|(i JHaob ]J†ms%<6[k cYrvc_ [ζw6|pD%ntms%<V|6Pnڼz +`7m+l~mЇ]ˇbsq+1x'Fg5)_t׏c7j9Wr %O%mlɝms% D N#p/NpU@=.Fp;~KܜH\d}""K~M惨493@i,{Z d;+695m_%TQBy~!l!$=VsjOZlGeeDaPK؅\zEi5dpdӭ ׎o6x:Fzg#F}*7CZj~9M:E=݈@:)|\{Z?9m8vFe:2bNT" TS׮hSn\v8beo7ޡV+np`vFH:a+VipN4xJ+xg k^ÕSX͵w?銵k쌰td1YW4xJ+x_C"H،AQ«7Nw?iK<vHHJXݶ8~bSj\3E<./A,B:ꤲzxy&z +;V~*l{\Xٹ7%K3`D qY,<Ӆ|ѧ !`|\@Xm.2Pn97΢<ϫJW 뛗\ݚG"ʭٺjeHkS:؂ XK-K1g*Ql{[8ugu;#JѬ?oI!F/a `t\@XmE(_׋$ǀ"lۼl{\gf")0|!=k|%Ob!`|\@Xm"ӑ+ţ?]?zDė/}[k1+_HB*KdU%LU䀝mplNIZ¼)mQBuE0+1x_0Zζljs{։c_邥ζw6?酘M%WbZIbW͓k͍M 2A:,c_=Zζw6F (YQBҒ%;iEVjbGݴbrA8A͍/)O_ $r(|=E{T{oC# ⃨4>;( G\F{Qlh&a;AܝEE{B޵#@3{kPouͮ7# FY =/-nOy$+mKNjOTv83kP+ ~Rſٝl!?/ hǴA2vNTl@kG?3x'%ߌ~!?G yB`Ë48Djx׺@{{:r r8͵w 2.F+v#/x(lxh {Z̓ _NXw@kG 1`[fvsjϘ'nߌȲ->1 J'^w6HC=A 1/g5y4; ׎;Ԋ5e'Q0B B`Ë6bOyⅤVzv՚͵wkZ#j Έ?D yEË48Dj)U tʷ# nC0I}n7#Hl! ZE<VT y[~V#X\{Za#, #F*2G^>)΋48Dja6^&.bk WGW[wxB?MFOAn#EZ<2kb |Anǀg&o9W%A.PB\~PtF m.S/I a:ԉ oͫǀk[ζw6\mSӒ %Ĵ&7;>5qBnq[nx{c_u-g; _P2J%k7b$mΆms%<V1-C?}uai1}l{\qӇR(aiɆRissade&!vd\AXmnvSnyc?P! `prOd|(!kswNB\ @6knKQY/g"zp~n]i i8#oR[ÕOo{oQi)'p U,vOi$kKkKIĹ?Rjv8~̽nᏜ߈ Vs‰;~.+jϩi+nKY?&_5Mw>I3_tRVw.8"msjZX2_twpzn7qVp;sq~7K~qQX{NMC !^ j0?Z⹻Mw>l D#^q 愋r7ĊsjnԂĹy];pgswj8+}x6s"}gwA~Mar7Ċsj//L@͗ݵ@sMwvqJ|>8nS 9=nx4O*Mw[el![%Rsܝr v*6>//Gۻ\{Z^ᙾ!ȇoqeW ?xHKqOXE/뇀Olh+$~ S'801\̚,B E˺//뇀Olh+<~ɚ;$$%@B<~JD&vqz'R/%ޮüx0=?V0x{l7Y0X=nb^¾ *oǫ;Zlh+<~RA$Howڀ?0.>ˬ nyI%[xv1 }.3xv aiȆPnynWv$~/!lJ:Rgrg.]aD#FO*K'^ j0oH:&o_=Wpqr.` Iri <|p YfM`8 yu}OJWu=pqH@B<~E exrϬi/%G{C@_~m](W~YO!K+>JW`$Fz\==az\F_zz /Nw?nΜyLI>_\Fzt̚q|wTpC_xr7lh+<~.Q | !?xP)Ts1;-_˅r=}qVϣxg }vRD{Gowテ~?'v@H Tz[2􅷵~\Whf eaI<.];xg 3gj8+}|p6 ;", B}r6sࢼr ](L $w[$|p w?y; w&FD%qYB<ȟz95 u[ ޑU&w/wJ*ݗ`,wj8+N vKVD<r` ԭ'|pQX {NMC ;/އG<*wpxٻ\{Z Ov}%|!>w \c,a O.!w ^@wlh+$~|{8H]oI#=b̚qLHw/~9ǫNo8Vxw$b'$'W#=̚qg&-q6fx0 '; <lD. oDa)ɟ?oϿ?ҊIBv~0DSoRaP( y=;h뷭O 4rr`(VN5IP{6MC`]iAߏnyصwCvSgosحFDAx6 , (w@rWxhFa_^w?^evSg,wwo,2"'u.E\nk>95 u[ 2.Hj-%j.wPb>wweA"DYodۅe\לR鲦CJ5O(Mw+nG"DoN &E;</\ $w[:G>|cZ_zoT{Ygrdw5F숐T39o95.kNCtUJ`u7"Kܿ9^ͦ;Ίuql!&a\cN'ng}|y];8; wDaG"D]w&E;. lKG6T#g,(wē@2KT:A◇o,kttNw\#c| !_#'FYngox2<>ǕR-v"D yo͉ip,A b'xO6<{%b; 6B ZèLGFwB |SyOiq3d%K, ó[" pP~8d{GoÎ(?YA*-n{Bx lN(.:ˬy $"r˳^b ǀq l{\)?N~(nC q<_m#jsƑn~ +[O7m+l~/?NFwLAm'u̎10&Ky 6Nf>Нgl^=]rMSBҒ%UJLB)#8r3+ 297yG~|fF3d .O~np|aiȆPioyVko!o, YjU{2mW?`OfSgO}vq;vDH*A֧47s"+nKsEq__sW?`On6ޡV'_w{3ґ #g> s)'7"X |I+a^r8+}r7kP+ ~Rt1YOip@E<"DjNb@|?}Zyr8x; TdG 7Fd}=FjxJ$r/6=A5_ x%3o4ޡKwIG>J,h(o+A24ֽs| ׎?; _ fD0B ~vz1xe,^!ZV X {8eY(]?y42]_0.Ct$Dgï)|:pWqv Kp xL+ vsmbrrHk_>|! #Ze%q@/rjC4$sנY͵w?9|e>!?;</&}j)UD;#x+3x'vkJ>* xȃXlxh{Z̓  oџ0xPr#X͵wY]K-u;#$0* .ώ_Tv^G1nt"HwqAohS'o7ޡVn7#8(F}U/޼HC=A <|D3<}J!/`Nw?K Y Xxh!\DY@Hb0&F]Z~ +Jf; \jBl 9QB\~vU7E9!|96T蝣(kǀavpO.mDC W1x"cC9ɒkfj]Ȋ٣;R?!m0+?7Z)rT1ƍg:ҨK)q+ =N;$/9c[[Q~0ՎU㝩?m͵9>S}#3BR#sL%. s"] d+ REj\;_J׎/;S\{Zq*Lefp`vFX:a?9SP9xOi://S_ovsjTfO20*ӑ#Cv ^SZZsE twʷ#w'7xǧp2#3ґ #'gp05 /kZ I'A")<|?!/`7?n\A | !?9{F I)q!t/!ޅZ~ +)7yBNʁR<%JO*0+; 1[rZbAS`NQ?o )UϦ4j8%q~4.;"$ * 4Sb^d'S?XWAܥ= y׎?^; }N IG>8/ HA2A;<\{ZaaȆb$Hɹ$˄QNy΋#@φgo7ޡVT n;#$0B{Ά#i5^&C<^e]H|{ ^;8?͵w?9<a#Fm[ahǴC.SoJʗ[eJ<|#fp]uWfsj:Q1B ~r9f yh1{Z̓  ^^jhw^; TwKG6UTb^cZ<A28$k4xpdo7ޡVg7xч|!?) HK&SA%E×] pIQ.$K}- YMb Tgt>KE3kbK8\ «ǀ3[ζw*7φ%QBҒ%#+5 %rk)Χ~ 誋l^;]rB͝J+j5Wb$l61YrAf6݆}?07~jyT{bR#w#BRǟ9xf;&}ʐ)n6*Cמ<}O!À{*͵w';*!ȇQpRPM‹wJ+xPWqE u7x#X\{ZaZ@:~aȆbZZ0/) nfC u˧) ^;8; jFfgT##F}kE|M+)58WFh2YF>} Da nC0Inp`vFH:aҧ48Rs" U A2MuBm׎?`OfvsjO*}v#3Bґ#g>Cp~^SZYIA28 9D 7t JW0`O~l{\b8ʛ193*uC>A2WUT+6Wǫ<^i=ܹp+D{GO}[e +@ͽ6Ž.mN~wPɦin{ro3]x?IVad6}!)']S"} dVKq^aW/wwvڇNUjG"Duvw\לǾ";J<+w7j8+}x$wP_{ B}|sw'\!VSH֋4/--^>sl8ww݇WgD~G"Do6Fܭ sܽ"bSVw^I1+w7j8+}$w_IE>w9A Hwǜ!?xH/M}`;ݝT{Yݙ߈ȣ|!>>ۍ{pEbE95 1OMS>y ;ͦ; wݽ!B47K-=.6d95 nY/ywpavsj vbaȆ隢9y O 5xGlXI0M?N4lh+$~x}~ ɑ&| !? L.gO`@'u<2J \uE3{7i ouov;!, *ݭNܭv\d!YsU0/(O.϶E]9x𹷛Mw>ĭ bz@J́4w)xH/q%wpnpY݀툰TdqYoA9pQ^sj!%;7(7y];ͦ;~[^vwjG"Dmw9p9>+nSUsvxu:Mw:ڤ:h"d}RS8E;Dde=kJw;ΊuUw"#BR"d}V0.)Aw$m/8nXww KE6uI/@΁rw)x$/'^Sv8|qMw> #vDH*A[u7sܝr I +^8T{Y~߈&!>;RT!#\!VSX~IJ_^w?^_ͦ; wܽ!"T#.YsEbE95 %$v0/k/UvSgR~#"aqI_+.)iwsE[;4Vw%6\ >|N)Kۻ\{ZTߌȵ7FOR!Aڋ .Efi5U蘗.…?EyN_G̭ڜ6^-ქ>ʼnuy:0A/{MyQp}2oB,W8:Oen6AVk!$ B}y462s࢜3*v jBI֒엗صốnq]oDX*A6v\לR^“75^5 _n7qVTQ^]tE|W ?.r$Bב$ܭ_*8IunXww ܎KE6uI@j5EyX~ik,哇o,]9xKrw7j8+}ܽ$swnG"DORz\cNc27v;ˏ_z^T{Ygrܽdwqi,'DȞIwNAfr7ĊsjVhVɗݵ׽$swKvwo$-#6wt/At'\B₋t=o95 Zxvݕ׽$wwK2wȂfFwt/Aܝpt΄7.օ=!򋠊÷S%Mw>^#R "'KJw)1.1 j3L $w%"M9NYv8+MwZc"$ B}>E;G̝p-tn-SXyIO/twpn6qVx$s\uAdqwn4eXKpwp3npq?oDt*AI T)\c=!/xi'ȵ÷S~&Mw>g\wAI 些 .+jϩi$wk'hOpwPb;Ί^Tu߈Tdt8,ݝp䃋r7ĊsjF0l'_NYv8zQen7qV "S"'Jw'\,dU!\!V@rw'Q>v8|qMw>E3q ~7\][ɩi$w;eK(<|UegT{Y~&߈|!>gR;i.6(wC=! lB hٻ\{Z&ߌ4FOzN#;uP}Vۗ7p{8w՟G/~Ow-o3SqG~J^j oko㥭}9=}m'|-Z^Ҥ5eo ם!ʮߍmvsj.|v &E;<;"HVRon'Ewp0x{&aȆb=JY?/)w \Y^8L٫׎?\?o7ޡV#Un7# +F{R" ѢA2xJ5xpuavsj[S3 ΆbT/xEEi5dp?{ bo7ޡVAUnpȈbpw6xJ+t"HRۗ[$V׎?\o7ޡVMUnv1B ~ܧ 3x$ ^!=A ^N)&hkGWkP+ ~ج*7~#ݪ0@~E\)<VQ6h+Gu=ifsj1ö'? aȆr fp@5 CZ:MA2wzggoFC ^;8; 6? IG>w&렞'Ѥ"X e?ZR"z oOlh+$~9=|+!a)bޱ#YC 0ex0g/K{L5n3*<{oq0vc>eE}3??7afcx8ՇWes2ojϔYshX0BxWJ72"? VS XqRjóak퀿QfsjmO~"ȇQo{%rq{ ^e<Sȳ^v8; _^o8s" AVmT/jmi+GxwCnfsj֙l!k(mVГ!H7"\ts^׎? IfsjOnȎ gwFH:a΅9xSZ G ``5y[4W^r7kP+ ~rwCf~/+Fn@ y /-rOy$[Ė^ kG; ݰ|!?4[mV ;0E `/0 ׎6x'w7Fng#F}ǣS" Xs"H kG{ڱ\{Za}Oތ >_}uL..`Ë48DjAە@,  8xp8Px *F?KA{XbmC1 |voME7m L{'oaU;DBlm>(@KPM`3IF\;&;T9I8* +Ӟ(${ }SnK+,xɩ8iDxwHω<9ʂ|ۓB_}NFWe3Ϳc4kEQ.41z0bT~.:Ss!M /-nOy$+)K+E=}Paݏ[{4kP+ ~\I쌐t1پ~ip@E<}Pa֕\{Zan]ߌ!?օ<2\Ei5^S§* ^9^r7kP+ ~%3xgKG6z)  nEL$LlA w0xpz nC0IoF#g^'^q+;/-vOyV״S^/͵w?|cD #g^G^Ei5dpUx9#{ ׎?`; z (wFH:aKip@%u`pH+O΅ YXUaN9Xo':vL 9j,{r#*>+N<ğ'nV/+bjÃ9in\.?^+op&5~OiEu[szBRA)h&q|L(Ae `^t{9JoWůOS5wdퟹ{eD^6̈Qio}/xNir`p.hKjp/ꔧ( ^9kvsj/ߌF/xY" "A2 U( ^;%3kP+ ~_r7Hl!?0Y|%]'6h[jpgJRNy^#vkfsjO?f_u|!?<ٻ /:V HA}bNvv_ nC%np3ґ #̳m,mV Ϣ0E /4/O_Tv8~q͵w?龸|cDsb\6K(b/-~Oy7xpv_ lC0I##g'^‹6wfOy޿Pĭ ~9nW?`; t_ 1"1YEW=/>|j)Uo!* ^;3kP+ ~}q7H *>u_, 8?ψmp-V X yyk~^׎?v5}7F\Pa~EK[ /.{Z̓`5':俾vsj/ds91B ~&se~ÌxiYth纸]R~ܦ>o4SqG}w@SK[{b\VkN}%84Kc?ܯMw>2%+DļpYrEyb95 !Tr.txT<6-ˣ +]v"ֻo(_:pH/2PGXp?nZ,V+H6bE XLZ5'nu0w/|vSg%R%|!>aq7sܝr x1[Z2zOswj8+}|n@wDX*A'y@jS < $wËw/<{O |põg|݇5?Tqqs6@́a>wq\ 8Ӛɫ頻(#}]'%8yڔ=`dž_<vZ LPLLt8{ =tuqݭKiN|]L| !iȇb$blOjQN&9e+YO,=j8$So u?ήI&>Qی!ίI"q?~.ܾSݽ:B ՗ܥ [Z'ɮI^T'ɯI"hwcWGq3%[)}buZP_w6[Thzg5TdqRcܽҴYݽ ݥ wwBmπ?>m|!_;(wp'![y*5/KBmπ@%> 2 Bܝ q+UʘSmf1߽),l;q.Bmπw$lD"Dw 6ƺ1p[N͒3I`w}r>z)wYp݉sj~ܝ'u]eD"Dw a=.;z̯KvrZw3.m;qRw u?މ#2|!߉ۓRcܽ 7) B@$jFיoN]~_HN iN"C~pWN5ktl`ē\cB C`Y$%wo2C]ojg@D;"C"car+k̩al(k/K:0qwP[3|u`tD7\AVEsjSjҖzx&3L]/ ;_-|!~an\CN9ϓny2Z)'_w6*ezgUnHEDX*Aaۓcܽȱlx7-%OxJN]/ ;_m"$ BP I1pQrʄ"{Y򸻴8*w u?WvGw r|!~Fp9nWL)r)t]T'b}~iI!y53ޣ偁~'+B7o}RINWIqlֶL޽jvapݭR^]- ;J@D"UJ] NHscN`s\\r%!oK[nbzj@T'#X#n/L8" {i5zjg(w]@ ^w3׋uWNy?YrLɇb7f,͕xס]Su|_%.h DcZ0xXbevl!W bhN6#̴rW0 /mvmzjS{Fkd#F Q1x?I6/Jʅ"-wwcbmՀwƧ?Y1B 55x, ^t \V# A'brƄ^p9],z?^w8.cNDںݭferʉBҐ!hn4- Y[[, ~)Wq7vi p}'k0}2"k0B4 a/߾ȘV Y80wjjjs߉wF+i$>?}#^ܮkLqlW3R ?.1xi p}'k 0 l!WJ1xjv%SrE [w}Z0_t1=*;/!|!Ę" }^~ ^cݍv1xX[w5P-5gd"#,0BO_ Hi)fdMC컗5 /m_d7xX[w5`5iOFdEFŏ r݀ /ྷ,1@ΓĦ8,,z=/:VV uwR<" p('@7kX]Z-Ǡu% [ȅ}6:)|?Sjd@Cc*T$!B'V =ApPXl9/4308NL"mɀg Ɓ]$!BN6^CТF[BI6kYY ^CoXX~}+ZdݕIm|!~] cǠEX{K(gl^V52'›ޏogezZH[w2`|!~U\i-rH(ܬ&i-q<{(|="Z{0V.VO9B/C܌pbu?>hM̦Q֭\-9͘;83/Rߥ!E/Ɛ{ˏN> \9{ n!e90ɬ|1êcuáIH[M98CN6ZAO"'PfNv^șw.}?;k׋u')}=ĆbeV,h=e @x텋ʼn^,#ڕmî.[ۤG{3٫Cк֓-bgcSɻuP٥-@n.֮kvʟ_3ґlAw wK1x?ع"8rQ;b^0x'،Έb,7jKڕ:/ྷؘV W&9v-w7}1xX[w5`|wjpfaȆb7fpJ6xH+oS " nQ"gvkLߩں5H 3:#'`:s/ྷ1A|{1>;h; 5xX[w5`OF, FN9@ 3u2^1F@L!'!J}ֿ|t!uZgC|amSIE>n>ۛAJ b\kI[I3|wi pk{׋uW3l!?G5/[Z>.T&H|4xi pE^0x.!ȇbHpHi% >nC߹cںOK KG6?=ܣE|OYcpn9EYմjE{f0R~o>R)֝ apOCIC>-3܉O(n6k;N9CB/_ ]'Bm;_v@DVQANs\8-ܾS 8-3I' 5t_s˨Zw~|:!ȇ=*5/z콥\`67-/m_d7xX[w5`'#E 1B .~lP_,|xEǴfp-V()ߞ@)mںw'?Q!=|" {i5tMT䨐V=bmՀ_!ȇb7^y͉@'usbR/煸[T]̕bjY۴z:q^+ |cұVNloFWyX7Aӂך~]I}!n~ՅA%uH[w2kHIC>c?lN(gR+;mR*إ W؜x^w9#Rl!~(mae\{'RZ+|/_]<.qwP[]:.#2|Aw8Z1pQsJZP&vw/tؘ |3twap"ںwwke!B-~?95 [y8|'pwipT$j~ܝ޲IE>w?S@w{Rz \wAΙ$l0+I9qwip3'j~ܝf>+X!BP̌;2%*p%l!\OjkחwZvZg:fجm|CD(cۛqE6{\PvкkON`s0NR8Z卄Pޥ-wLjzj@;d}I\V?\"{^}oYcZ`}+g&e4 wa pa}WuWaFd:aklxdžip[DLql3>o)K[oNjzj}:=#aȆb:uX*mV1v2L _e ^S׋uWO ~2"|!<r /ྷV# td?y Z5/{Z͂R+I u=K-wbmՀǞwFFH:amVA]2#{bח`B/2^0x'#rcF xu!^}oQ1F@ yi%?o rLfkٺoݕ=?L|8}ARhi[[jV {uyy MU~|iTV"mB$A+c?4dCY{"@!h E:P` `[$&e|{Y~ںq? Dq;;GDH*Aij[(E;$[  ŁNYR(_st]-] a{J2*0ґ #OS;eERt3S9una pȥk P -kd#F ӻ x JqX6UIIP c 5xX[w5`OF~_>?\P<͞ip[tLqlnRnSoK[bmՀN?#OG]CTyw&Iqlrv3uy8N ^/] hpHGFX:akhpji=La`7dLFoK[bmՀN da#F7ڹ1xi<83:' q,G]kK}nS{kEںnyT[uC|Y#!pg'B7sͭ3Uc!÷l߬-Va'e#;}o ]~wkںqg.qU|!ί\"Vfvc̽l ˖KbTr&}!wipݭZj~ܝ]LوKE6w,wk%1pQr?]l rN|l ]~w땩ںwg+w_!j%?{9:h.k&!?K4{xSEk u9K>7Yv` 2%F G-c!6}>Yji\Υm}/c6H3qvP[3`H3Z@ͬ!~iBood8;.۾Sg B>D|,pwipĥj~ܝ-Kܽ#2eqw"qKftqIN Cuj2BcwoB]Bmπ3丛"?n.ݾSLfZlWNjs_%Nch/dYL~.+@5r^88acl&!Ey~ &w@؅Gѯ]Z;]kD!rćt,qv!N(gpbK`_2y!k޽ jOfw7Ƥޮj~+cq{D."BR"d31'rS1jv2BC7^pw~`tl!~7I1pQrj Sʤpr2ӔO޽ 8|Bmπ7~%aIE>wۓcܽB@,p)n{u_ Pw!yզ;onhv?i\:c쳽OHinoh |ӉkҤv|4vap8ZvXABDH*AxTj HsZu&5W'[%Zp8j/k1:\#w3bً/>V 8)D^^-wNy1xX[w5`݌OF5M!1k&sEjm8&ѭm!oK[̩ںfL ~075bnF?/ྷV# 0ɊJ|/u9],z?^w w_iNvwn?w/K$!B:t9|Jj ^wqRMhovD)<.mbmՀ?MDFX:a{=*9/[Zhp3foK[n_bmՀ;SV/1B <j/>f-URivUw;/k澳[S8Fy;/=E|!TJ5 5J/P@X%j~'K,6?՞,ȥ9ďDN NS R-P^}CyaIjjj@'FT#F*O^/ȉip[R%ÿg;}^0h#O/w^Rcp6h?`_ÔalYz/D ^w7] ^/] <{ZjÜbh7^*3Ćip[DLhp>G-h6:"BmVEoAc[=ZxؠeZw yEπ;(R9݋yaabzj@Q?S!K8E~Egj nq+oK[tXA^?y ?3|!'O;/-(^yi5k8EG |4-wxajjjg&_t1W>ڇiuڻW!/m_d7xX[w5`OFF x†ip[DL<$A&{[tU'k2^'= L?Q|!sO'+X[pӟ8"os\Oas`,Ro_$]v;-mY{s3^% ^`#v\@o^\rxZչ軫Lm]-֝ :[:;uҐ !m؞Qof1$¯1{gvipgo u?^{|!?6Vj \2ZIH'_r6iwW u?Ξ;xKE6wO{GHwo9-eR'^]~wgj~ܝ=5qG""$ Bܝ?q s rSAzq#9*"L'2)z?GnjIH[w2 >a[fEv~A:: Nn[rHIC%[[p8ŏwGPۅ wW xvP[3 l!`*^ b| f qvVĜ>[!C_r6ySںwgJ}""Q|!Ο6{%J8sj&w1?e^WYn+ںݬ#n?` 27lf;8$ 54~.FDMrE 4vaP.ήj~vɞNZ[""BR"m?vz"o\CN^CaJ`'Y:)EV:/Ww6/2𛻻^pwr""R "E{)khw" 쥬DM!ѫ{)ԕ5ŸW=w (,j~v?d9%Gg{iw%aS.uZw @Ŝ>[Zuv{Dޥ-wbzj@}1BpXHޢcZL)9"tV-T4\w{)π?KUBmn;] ǖoF NroZw>xsj̉ DZ(3ڻZw5| S^ jC(_?U\ ^-] ̟/I ~0"ǔ|!'`?aË4-:t4U=&ϰ ٗE|SΛ+ںq9qo49bm`m `(lX ɦq9"L~Ŀ[8v_]+ X;-Nj">o?܊y㲂hE%8eeވK[n?bmՀS}>wcx C‰ipOZ`3MY_)׋uWϞ#`*>O Oh%IqlW23~]cbzj;*S_aȆb=w^$ :,Q__нaey-wyAo'DZjEں]ת#!l՜ 洵 3)OJLR[r߼|!^X=;PlwۨB/ޏpsabZd{ qBX!Xik!SvZCBkknpQmxVpd=92Bґ#O =*5̨;լɟ0vLJjr<~{] SWuWX|c#,0B ܣc ? J/|vw'd!vnWN2Y)zschlqURljg{icÊ'L\4}-W=)q!ywe8v$iN|݇}}-bE1v~4F?8"si @:?"I(iH:3R+= (;;1r-% YdV;C'FufԷ+P؅w&5vH[w2fDf|!﵁Ζ4!hQ 97>mǕ\w٥wWX^;vvM'"!, BaX{a=̊ ;Wo8^K^- ٝpv@[[шolh # ۛ9 ]ku IIb+/X8&kܕ?4uB9!ȇ|/jםAR𶄂(xc@$[$g_u U8x"mɀmF!o7-XO6lg/}-D<.mںwOK}2"Qx7^ip}ΞiKp#{gnK]-֝ ,eyhE/‡D%u ZWq?n~*l8~U/OHpoWKߔfJa`? sNl!cm0֖pSZu'Jhgk~$1뗧I (Bmπg%V~A"DC-`{ ^CR)b>Gyj&g]_&ʻ8fI.k?/Ɉqx/ .|aċ-&VEkB-7) ߏLTIJ*ʻZ;u;46{D[縏>(]wf \7oĽ@ 6lwJĻ*黴^ﮪwsv@[0lIA(('|!דgt83}>Yb$iIJfc6Bmπk8!B>y;BXN(obcN @$˓3ߊ#wtq8KmÀ[oB􈈀qv~2;On:i_KXp$P{nޏn=rS)֝ (;y 7,l!ίE.Y1pĺQbnm1%efIDۅ wWxvP[3 l`*nIE>ss{Rv \CNp {^VMNƂ[^ގcvrK8[w/9xƇ5r#9-FT&ԫ VPyw tuq"Eں_gG& -+|!?5v*~F(gbB' ֤H[F_'6/eڥ-g+g5/bmlﲉ;#A "Y1lvb퍗SqugԐsLRO엗軫>=%Dںw?TI;eC1/0;dMRocاK^5)̰߯I㱎_ "wӿwRtK-,x/x\&D}pbI?$N*|O^zN6Ã" oj;~=FKBX1B~QvRA׉ )_F⻬[EE>y+)hvol^Z9dkooXH3;8'r^kM SI^^.l_dwvP[3`s>TdEe^6>S.הuۥ-wbzj@n{m>`:2bmdl1xJ\GA`Sϓ!/^qzew'I%Dں- mn!!Biq AN %>gGV{VDۅ w>xZ\c"$ B:Q1xIe4>J/.̽{|+6.lbmՀ?=*0ґ #M {j֛Lz+&'Ex8NCB鹻U2]+==46'n纕Y>&fNn>K[[n'n >m{^;:.msSg u?ΞXDD. ۈ7\ov焋2+6ɒ9ylfJ'뻃m8UR~}w%*(iNĝ-Q4FH"x;_YIq #X7qdkLakfդLq#.k_dwZg@ٚwDqo!?7woE{2>p!IwOM]v{w'hwk׉un<mʎ|u~uvc:h+k57xQmqx庫8|U+=&,جGXvdkooX+<xw,qs;ѥ$L"0]~wgOήj~=z:G""!ΟE9[l{n ɍX8?B#_ ч=*'Vu';'S !B+OJ׳y ^wVy$y$ m-|PE9n0]zȀoysv@[0K㔶?a)bl`l8-֝>4ut+7_/N{ v+S/ޏn_ص"mɀ,[%XBtb)tv`>Hgr3Y{UjZBg6oW u?ΞKE6sOpʰup2nyF[w9nA?݇"mɮ Z@H螆ݥu7#u7[ugK(d%WIśӺZtC.͉ޏoZwyiN=mEo!&!K՛Zwq`5`I̴+^8Be/`~HՊ4͹$sulݷn9Y/q^ ?sYṗM93)1u >GĿ9Z;9C.#^-t@[0`l[bQ |Z(,l&n .yMƮiNmBNg:;r W,پP dUB %l[ujdUG7Hk!X;hBW @&&D2&!}௎%oDZ ZRgٺ{_g@[Mҏ "ok簕 @M`|*wC0U;:a7Y1v@H lClgyâm-??Jп<.|?SEںuD@BX!G#󺎁v(U~'[gqv~h vΔlhF#m7"8BF#-6`I @M4.;Nf]w]]M Fgc8[w/_&;>7H|F|22!hL*+-۲ ߎbMguߞC>|cJoOFCк>y7>.Ȼ#.{?kEں_gg.!$ B m3-!<%9HNڑߩ=*y=;pcںeg: mmKA6c:!]NAN n͖ӶhmR&d}/>r9vqm>ݫ*Eںeo9memB!iȇGJiYNF3l`KEy/1oǰ:*q^7[m%\7*xX>3/ |JPں.jIVO^t7+9`W`G_jy,q|Rݑ/bMV5lݷ罈5WKqƒx*؋/k?]3s\yyY^B>rzV a[@SU&6rƒh*?U%2}ݏďߎtv78=l35 QhfV|dtv*;e߽h ˱_iba[1uiRQx0\)NSs{on8q^`PtZ}fT8]e52u$l/y9 DjٺoAUvmj:=+<Ƞ*?Qcv)OW_~篿~LO y>Op(Ƃoc1TS&~[nw&)G_Ή9Eȷt^ݺ~H@[۷ol[7 { ۛE|͞=~#NL>W86L]]+֝ (;c*U bXbՖ!-SmmPg1_W:{ػ?=+ٺ{_gN@\= /'RWә8:d}fbZwן+/Fdd|F֭ 76;L7xd'< ioofTAtsBj{\6hUhlYIA>_=`rWeG^]>wUȎ@#F0U +Q  @[NJlF̗rBI]s֗'zŸ,]9;U!wShl~v*(]t77;OaKrFYMfѻȒػ[<=RlݽgEK::`džN$/>-38\vO$].Tr8wkol.Ud.} ʀ>j:9 @Gp=-!B/p"153sկBmPTPW U{{3 9 U>!w%oDZww/ q^@Vmԇ~l z`'O >i.Α_b.rߍ-UX!sU!Iw]I)=pxD,~2bu,o^Oj&.r} ;z(n=U^N5lݷ@z !;?`l UU%5!`%$;Zensembldb/inst/perl/0000755000175400017540000000000013175714743015466 5ustar00biocbuildbiocbuildensembldb/inst/perl/get_gene_transcript_exon_tables.pl0000644000175400017540000003454613175714743024450 0ustar00biocbuildbiocbuild#!/usr/bin/perl ##################################### ## version 0.3.1: * Add ens_counts.txt with the total counts of genes, tx, exons ## and proteins for validation that all entries were added to ## the database. ## * Extract gene descriptions and tx support level. ## version 0.3.0: * Change database layout by adding a dedicated entrezgene ## table. ## version 0.2.4: * Extract taxonomy ID and add that to metadata table. ## version 0.2.3: * Add additional columns to the uniprot table: ## o uniprot_db: the Uniprot database name. ## o uniprot_mapping_type: method by which the Uniprot ID was ## mapped to the Ensembl protein ID. ## version 0.2.2: * Transform gene coordinates always to toplevel instead of ## try-and-error transformation to chromosome. ## version 0.2.1: * Get protein IDs and (eventually) Uniprot IDs. ## version 0.0.2: * get also gene_seq_start, gene_seq_end, tx_seq_start and tx_seq_end from the database! ## * did rename chrom_start to seq_start. ## uses environment variable ENS pointing to the ## ENSEMBL API on the computer use lib $ENV{ENS} || $ENV{PERL5LIB}; use IO::File; use Getopt::Std; use strict; use warnings; use Bio::EnsEMBL::ApiVersion; use Bio::EnsEMBL::Registry; ## unification function for arrays use List::MoreUtils qw/ uniq /; my $script_version = "0.3.1"; my $min_tsl_version = 87; ## The minimal required Ensembl version providing support for the tsl method. ## connecting to the ENSEMBL data base use Bio::EnsEMBL::Registry; use Bio::EnsEMBL::ApiVersion; my $user = "anonymous"; my $host = "ensembldb.ensembl.org"; my $port = 5306; my $pass = ""; my $registry = 'Bio::EnsEMBL::Registry'; my $ensembl_version="none"; my $ensembl_database="core"; my $species = "human"; my $slice; my $coord_system_version="unknown"; ## get all gene ids defined in the database... my @gene_ids = (); my %option=(); getopts("e:hH:P:p:U:s:",\%option); if($option{ h }){ ## print help and exit. print("\nget_gene_transcript_exon_tables version ".$script_version.".\n"); print("Retrieves gene/transcript/exon annotations from Ensembl and stores it as tabulator delimited text files.\n\n"); print("usage: perl get_gene_transcript_exon_tables -e:hH:P:U:s:\n"); print("-e (required): the Ensembl version (e.g. -e 75). The function will internally check if the submitted version matches the Ensembl API version and database queried.\n"); print("-H (optional): the hostname of the Ensembl database; defaults to ensembldb.ensembl.org.\n"); print("-h (optional): print this help message.\n"); print("-p (optional): the port to access the Ensembl database.\n"); print("-P (optional): the password to access the Ensembl database.\n"); print("-U (optional): the username to access the Ensembl database.\n"); print("-s (optional): the species; defaults to human.\n"); print("\n\nThe script will generate the following tables:\n"); print("- ens_gene.txt: contains all genes defined in Ensembl.\n"); print("- ens_entrezgene.txt: contains mapping between ensembl gene_id and entrezgene ID.\n"); print("- ens_transcript.txt: contains all transcripts of all genes.\n"); print("- ens_exon.txt: contains all (unique) exons, along with their genomic alignment.\n"); print("- ens_tx2exon.txt: relates transcript ids to exon ids (m:n), along with the index of the exon in the respective transcript (since the same exon can be part of different transcripts and have a different index in each transcript).\n"); print("- ens_chromosome.txt: the information of all chromosomes (chromosome/sequence/contig names). \n"); print("- ens_protein.txt: the mapping between (protein coding) transcripts and protein IDs including also the peptide sequence.\n"); print("- ens_protein_domain.txt: provides for each protein all annotated protein domains along with their start and end coordinates on the protein sequence."); print("- ens_uniprot.txt: provides the mapping between Ensembl protein IDs and Uniprot IDs (if available). The mapping can be 1:n."); print("- ens_metadata.txt\n"); exit 0; } if(defined($option{ s })){ $species=$option{ s }; } if(defined($option{ U })){ $user=$option{ U }; } if(defined($option{ H })){ $host=$option{ H }; } if(defined($option{ P })){ $pass=$option{ P }; } if(defined($option{ p })){ $port=$option{ p }; } if(defined($option{ e })){ $ensembl_version=$option{ e }; }else{ die("The ensembl version has to be specified with the -e parameter (e.g. -e 75)"); } my $api_version="".software_version().""; if($ensembl_version ne $api_version){ die "The submitted Ensembl version (".$ensembl_version.") does not match the version of the Ensembl API (".$api_version."). Please configure the environment variable ENS to point to the correct API."; } my $ensembl_version_num = $ensembl_version + 0; print "Connecting to ".$host." at port ".$port."\n"; # $registry->load_registry_from_db(-host => $host, -user => $user, # -pass => $pass, -port => $port, # -verbose => "1"); $registry->load_registry_from_db(-host => $host, -user => $user, -pass => $pass, -port => $port); my $gene_adaptor = $registry->get_adaptor($species, $ensembl_database, "gene"); my $slice_adaptor = $registry->get_adaptor($species, $ensembl_database, "slice"); my $meta_container = $registry->get_adaptor($species, $ensembl_database, 'MetaContainer' ); ## determine the species: my $species_id = $gene_adaptor->db->species_id; my $species_ens = $gene_adaptor->db->species; ## Determine the taxonomy ID: my $taxonomy_id = 0; $taxonomy_id = $meta_container->get_taxonomy_id(); my $infostring = "# get_gene_transcript_exon_tables.pl version $script_version:\nRetrieve gene models for Ensembl version $ensembl_version, species $species from Ensembl database at host: $host\n"; print $infostring; ## preparing output files: open(GENE , ">ens_gene.txt"); print GENE "gene_id\tgene_name\tgene_biotype\tgene_seq_start\tgene_seq_end\tseq_name\tseq_strand\tseq_coord_system\tdescription\n"; open(TRANSCRIPT , ">ens_tx.txt"); print TRANSCRIPT "tx_id\ttx_biotype\ttx_seq_start\ttx_seq_end\ttx_cds_seq_start\ttx_cds_seq_end\tgene_id\ttx_support_level\n"; open(EXON , ">ens_exon.txt"); print EXON "exon_id\texon_seq_start\texon_seq_end\n"; open(ENTREZGENE, ">ens_entrezgene.txt"); print ENTREZGENE "gene_id\tentrezid\n"; # open(G2T , ">ens_gene2transcript.txt"); # print G2T "g2t_gene_id\tg2t_tx_id\n"; open(T2E , ">ens_tx2exon.txt"); print T2E "tx_id\texon_id\texon_idx\n"; open(PROTEIN, ">ens_protein.txt"); ## print PROTEIN "tx_id\tprotein_id\tuniprot_id\tprotein_sequence\n"; print PROTEIN "tx_id\tprotein_id\tprotein_sequence\n"; open(UNIPROT, ">ens_uniprot.txt"); print UNIPROT "protein_id\tuniprot_id\tuniprot_db\tuniprot_mapping_type\n"; open(PROTDOM, ">ens_protein_domain.txt"); print PROTDOM "protein_id\tprotein_domain_id\tprotein_domain_source\tinterpro_accession\tprot_dom_start\tprot_dom_end\n"; open(CHR , ">ens_chromosome.txt"); print CHR "seq_name\tseq_length\tis_circular\n"; open(COUNTS, ">ens_counts.txt"); print COUNTS "gene\ttx\texon\tprotein\n"; ##OK now running the stuff: print "Start fetching data\n"; my %done_chromosomes=(); my %done_exons=(); ## to keep track of which exons have already been saved. my $counta = 0; my $count_gene = 0; my $count_tx = 0; my $count_exon = 0; my $count_protein = 0; @gene_ids = @{$gene_adaptor->list_stable_ids()}; foreach my $gene_id (@gene_ids){ $counta++; $count_gene++; if(($counta % 2000) == 0){ print "processed $counta genes\n"; } my $orig_gene; $orig_gene = $gene_adaptor->fetch_by_stable_id($gene_id); if(defined $orig_gene){ my $do_transform=1; ## Instead of transforming to chromosome we transform to 'toplevel', ## for genes encoded on chromosome this should be the chromosome, for others ## the most "top" level sequence. ## my $gene = $orig_gene->transform("chromosome"); my $gene = $orig_gene->transform("toplevel"); if(!defined $gene){ ## gene is not on known defined chromosomes! $gene = $orig_gene; $do_transform=0; } my $coord_system = $gene->coord_system_name; my $chrom = $gene->slice->seq_region_name; my $strand = $gene->strand; ## check if we did already fetch some info for that chromosome if(exists($done_chromosomes{ $chrom })){ ## don't do anything... }else{ $done_chromosomes{ $chrom } = "done"; my $chr_slice = $gene->slice->seq_region_Slice(); my $name = $chr_slice->seq_region_name; my $length = $chr_slice->length; my $is_circular = $chr_slice->is_circular; print CHR "$name\t$length\t$is_circular\n"; my $tmp_version = $chr_slice->coord_system()->version(); if (defined $tmp_version and length $tmp_version) { $coord_system_version = $tmp_version; } # my $chr_slice_again = $slice_adaptor->fetch_by_region('chromosome', $chrom); # if(defined($chr_slice_again)){ # $coord_system_version = $chr_slice_again->coord_system()->version(); # } } ## get information for the gene. my $gene_external_name= $gene->external_name; if(!defined($gene_external_name)){ $gene_external_name=""; } my $gene_biotype = $gene->biotype; my $gene_seq_start = $gene->start; my $gene_seq_end = $gene->end; my $description = $gene->description; if(!defined($description)){ $description = "NULL"; } ## get entrezgene ID, if any... my $all_entries = $gene->get_all_DBLinks("EntrezGene"); foreach my $dbe (@{$all_entries}){ print ENTREZGENE "$gene_id\t".$dbe->primary_id."\n"; } # my %entrezgene_hash=(); # foreach my $dbe (@{$all_entries}){ # $entrezgene_hash{ $dbe->primary_id } = 1; # } # my $hash_size = keys %entrezgene_hash; # my $entrezid = ""; # if($hash_size > 0){ # $entrezid = join(";", keys %entrezgene_hash); # } print GENE "$gene_id\t$gene_external_name\t$gene_biotype\t$gene_seq_start\t$gene_seq_end\t$chrom\t$strand\t$coord_system\t$description\n"; ## process transcript(s) my @transcripts = @{ $gene->get_all_Transcripts }; ## ok looping through the transcripts foreach my $transcript (@transcripts){ $count_tx++; if($do_transform==1){ ## just to be shure that we have the transcript in chromosomal coordinations. ## $transcript = $transcript->transform("chromosome"); $transcript = $transcript->transform("toplevel"); } ##my $tx_start = $transcript->start; ##my $tx_end = $transcript->end; ## caution!!! will get undef if transcript is non-coding! my $tx_cds_start = $transcript->coding_region_start; if(!defined($tx_cds_start)){ $tx_cds_start = "NULL"; } my $tx_cds_end = $transcript->coding_region_end; if(!defined($tx_cds_end)){ $tx_cds_end = "NULL"; } my $tx_id = $transcript->stable_id; my $tx_biotype = $transcript->biotype; my $tx_seq_start = $transcript->start; my $tx_seq_end = $transcript->end; my $tx_tsl = "NULL"; if ($ensembl_version_num >= $min_tsl_version) { $tx_tsl = $transcript->tsl; if (!defined($tx_tsl)) { $tx_tsl = "NULL"; } } my $tx_description = $transcript->description; # if (!defined($tx_description)) { # $tx_description = "NULL"; # } ## write info. print TRANSCRIPT "$tx_id\t$tx_biotype\t$tx_seq_start\t$tx_seq_end\t$tx_cds_start\t$tx_cds_end\t$gene_id\t$tx_tsl\n"; ## print G2T "$gene_id\t$tx_id\n"; ## Process proteins/translations (if possible) my $transl = $transcript->translation(); if (defined($transl)) { $count_protein++; my $transl_id = $transl->stable_id(); my $prot_seq = $transl->seq(); ## Check if we could get UNIPROT ID(s): my @unip = @{ $transl->get_all_DBLinks('Uniprot%') }; if (scalar(@unip) > 0) { foreach my $uniprot (@unip) { my $unip_id = $uniprot->display_id(); my $dbn = $uniprot->dbname(); $dbn =~ s/Uniprot\///g; my $maptype = $uniprot->info_type(); print UNIPROT "$transl_id\t$unip_id\t$dbn\t$maptype\n"; ## print PROTEIN "$tx_id\t$transl_id\t$unip_id\t$prot_seq\n"; } } print PROTEIN "$tx_id\t$transl_id\t$prot_seq\n"; my $prot_doms = $transl->get_all_DomainFeatures; while ( my $prot_dom = shift @{$prot_doms}) { my $logic_name = $prot_dom->analysis()->logic_name(); my $prot_dom_id = $prot_dom->display_id(); my $interpro_acc = $prot_dom->interpro_ac(); my $prot_start = $prot_dom->start(); my $prot_end = $prot_dom->end(); print PROTDOM "$transl_id\t$prot_dom_id\t$logic_name\t$interpro_acc\t$prot_start\t$prot_end\n"; } } ## process exon(s) ##my @exons = @{ $transcript->get_all_Exons(-constitutive => 1) }; my @exons = @{ $transcript->get_all_Exons() }; ## exons always returned 5' 3' of transcript! my $current_exon_idx = 1; foreach my $exon (@exons){ if($do_transform==1){ ## $exon->transform("chromosome"); $exon->transform("toplevel"); } my $exon_start = $exon->start; my $exon_end = $exon->end; my $exon_id = $exon->stable_id; ## write info, but only if we didn't already saved this exon (exon can be ## part of more than one transcript). if(exists($done_exons{ $exon_id })){ ## don't do anything. }else{ $done_exons{ $exon_id } = 1; $count_exon++; print EXON "$exon_id\t$exon_start\t$exon_end\n"; } ## saving the exon id to this file that provides the n:m mappint; also saving ## the index of the exon in the present transcript to that. print T2E "$tx_id\t$exon_id\t$current_exon_idx\n"; $current_exon_idx++; } } } } ## want to save: ## data, ensembl host, species, ensembl version, genome build? open(INFO , ">ens_metadata.txt"); print INFO "name\tvalue\n"; print INFO "Db type\tEnsDb\n"; print INFO "Type of Gene ID\tEnsembl Gene ID\n"; print INFO "Supporting package\tensembldb\n"; print INFO "Db created by\tensembldb package from Bioconductor\n"; print INFO "script_version\t$script_version\n"; print INFO "Creation time\t".localtime()."\n"; print INFO "ensembl_version\t$ensembl_version\n"; print INFO "ensembl_host\t$host\n"; print INFO "Organism\t$species_ens\n"; print INFO "taxonomy_id\t$taxonomy_id\n"; print INFO "genome_build\t$coord_system_version\n"; print INFO "DBSCHEMAVERSION\t2.1\n"; print COUNTS "$count_gene\t$count_tx\t$count_exon\t$count_protein\n"; close(INFO); close(GENE); close(TRANSCRIPT); close(EXON); close(ENTREZGENE); ##close(G2T); close(T2E); close(CHR); close(PROTEIN); close(PROTDOM); close(UNIPROT); close(COUNTS); ensembldb/inst/perl/test_script.pl0000644000175400017540000000474513175714743020400 0ustar00biocbuildbiocbuild## uses environment variable ENS pointing to the ## ENSEMBL API on the computer use lib $ENV{ENS} || $ENV{PERL5LIB}; use IO::File; use Getopt::Std; use strict; use warnings; use Bio::EnsEMBL::ApiVersion; use Bio::EnsEMBL::Registry; ## unification function for arrays use List::MoreUtils qw/ uniq /; my $script_version = "0.2.2"; ## connecting to the ENSEMBL data base use Bio::EnsEMBL::Registry; use Bio::EnsEMBL::ApiVersion; my $user = "anonymous"; my $host = "ensembldb.ensembl.org"; my $port = 5306; my $pass = ""; my $registry = 'Bio::EnsEMBL::Registry'; my $ensembl_version="none"; my $ensembl_database="core"; my $species = "human"; my $slice; my $coord_system_version="unknown"; ## get all gene ids defined in the database... my @gene_ids = (); my $gene_id = "ENSG00000109906"; $registry->load_registry_from_db(-host => $host, -user => $user, -pass => $pass, -port => $port); my $gene_adaptor = $registry->get_adaptor($species, $ensembl_database, "gene"); my $slice_adaptor = $registry->get_adaptor($species, $ensembl_database, "slice"); my $current_gene = $gene_adaptor->fetch_by_stable_id($gene_id); print "Current gene: ".$current_gene->display_id()."\n"; my @transcripts = @{ $current_gene->get_all_Transcripts }; foreach my $transcript (@transcripts){ print "Current tx: ".$transcript->display_id()."\n"; my $transl = $transcript->translation(); if (defined($transl)) { my $transl_id = $transl->stable_id(); print "Current translation ".$transl_id."\n"; my $attr = $transl->get_all_Attributes(); foreach my $a (@{$attr}) { print "\tName: ", $a->name(), "\n"; print "\tCode: ", $a->code(), "\n"; print "\tDesc: ", $a->description(), "\n"; print "\tValu: ", $a->value(), "\n"; } my @unip = @{ $transl->get_all_DBLinks('Uniprot%') }; if (scalar(@unip) > 0) { foreach my $uniprot (@unip) { my $unip_id = $uniprot->display_id(); ##print UNIPROT "$transl_id\t$unip_id\n"; ## OK, add also ## o uniprot_db: $uniprot->dbname(); ## o uniprot_info: $uniprot->info_text(); my $dbn = $uniprot->dbname(); $dbn =~ s/Uniprot\///g; my $descr = $uniprot->description(); my $infot = $uniprot->info_text(); my $stat = $uniprot->status(); my $infotype = $uniprot->info_type(); ## mapping type. print "uniprot: ".$unip_id."\n"; print " dbname: ".$dbn."\n"; print " info_text ".$infot."\n"; ## Defines the method by which this ID was mapped (Uniprot ID was ## matched to the Ensembl protein ID). print " info_type ".$infotype."\n"; } } } } ensembldb/inst/pkg-template/0000755000175400017540000000000013175714743017116 5ustar00biocbuildbiocbuildensembldb/inst/pkg-template/DESCRIPTION0000644000175400017540000000056113175714743020626 0ustar00biocbuildbiocbuildPackage: @PKGNAME@ Title: @PKGTITLE@ Description: @PKGDESCRIPTION@ Version: @PKGVERSION@ Author: @AUTHOR@ Maintainer: @MAINTAINER@ Depends: ensembldb License: @LIC@ organism: @ORGANISM@ species: @SPECIES@ provider: @PROVIDER@ provider_version: @PROVIDERVERSION@ release_date: @RELEASEDATE@ resource_url: @SOURCEURL@ biocViews: AnnotationData, EnsDb, @ORGANISMBIOCVIEW@ ensembldb/inst/pkg-template/NAMESPACE0000644000175400017540000000035313175714743020336 0ustar00biocbuildbiocbuild##import(AnnotationDbi) #import(GenomicFeatures) import(ensembldb) ### Don't export @TXDBOBJNAME@ (the object defined in this ### package): it is created and dynamically exported at load time (refer ### to R/zzz.R for the details). ensembldb/inst/pkg-template/R/0000755000175400017540000000000013175714743017317 5ustar00biocbuildbiocbuildensembldb/inst/pkg-template/R/zzz.R0000644000175400017540000000074113175714743020301 0ustar00biocbuildbiocbuild### ### Load any db objects whenever the package is loaded. ### .onLoad <- function(libname, pkgname) { ns <- asNamespace(pkgname) path <- system.file("extdata", package=pkgname, lib.loc=libname) files <- dir(path) for(i in seq_len(length(files))){ db <- EnsDb(system.file("extdata", files[[i]], package=pkgname, lib.loc=libname)) objname <- sub(".sqlite$","",files[[i]]) assign(objname, db, envir=ns) namespaceExport(ns, objname) } } ensembldb/inst/pkg-template/man/0000755000175400017540000000000013175714743017671 5ustar00biocbuildbiocbuildensembldb/inst/pkg-template/man/package.Rd0000644000175400017540000000135713175714743021561 0ustar00biocbuildbiocbuild\name{@TXDBOBJNAME@} \docType{package} \alias{@PKGNAME@-package} \alias{@PKGNAME@} \alias{@TXDBOBJNAME@} \title{@PKGTITLE@} \description{ This package loads an SQL connection to a database containing annotations from Ensembl. For examples and help on functions see the help pages from the \code{ensembldb} package! } \note{ This data package was made from resources at @PROVIDER@ on @RELEASEDATE@ and based on the @PROVIDERVERSION@ } \author{@AUTHOR@} \examples{ ## load the library ##library(@PKGNAME@) ## list the contents that are loaded into memory ls('package:@PKGNAME@') ## show the db object that is loaded by calling it's name @PKGNAME@ ## for more examples see the ensembldb package. } \keyword{package} \keyword{data} ensembldb/inst/scripts/0000755000175400017540000000000013175714743016213 5ustar00biocbuildbiocbuildensembldb/inst/scripts/checkEnsDbs.R0000644000175400017540000000131713175714743020514 0ustar00biocbuildbiocbuild#' @description Check EnsDb sqlite files found in the specified folder. #' #' @param x \code{character(1)} with the folder in which we're looking for EnsDb #' objects. #' #' @author Johannes Rainer #' #' @noRd #' #' @examples #' dir <- "/Users/jo/tmp/ensdb_20" checkEnsDbs <- function(x) { edbs <- dir(x, pattern = ".sqlite$", full.names = TRUE) for (i in 1:length(edbs)) { message("\nChecking EnsDb: ", basename(edbs[i])) edb <- EnsDb(edbs[i]) ensembldb:::validateEnsDb(edb) ensembldb:::checkValidEnsDb(edb) ## Now check also some query calls: gns <- genes(edb) message(" version: ", ensembldb:::dbSchemaVersion(edb)) message(" OK") } } ensembldb/inst/scripts/generate-EnsDBs.R0000644000175400017540000003060713175714743021252 0ustar00biocbuildbiocbuild## Functions related to create EnsDbs by downloading and installing MySQL ## databases from Ensembl. library(RCurl) library(RMySQL) library(ensembldb) #' @description Get core database names from the specified folder. #' #' @param ftp_folder The ftp url to the per-species mysql folders. #' #' @author Johannes Rainer #' #' @noRd listCoreDbsInFolder <- function(ftp_folder) { if (missing(ftp_folder)) stop("Argument 'ftp_folder' missing!") folders <- unlist(strsplit(getURL(ftp_folder, dirlistonly = TRUE), split = "\n")) res <- t(sapply(folders, function(z) { tmp <- unlist(strsplit(z, split = "_")) return(c(folder = z, organism = paste0(tmp[1:2], collapse = "_"), type = tmp[3], version = paste0(tmp[4:length(tmp)], collapse = "_"))) })) return(res[which(res[, "type"] == "core"), ]) } #' @description Creates an EnsDb for the specified species by first downloading #' the corresponding MySQL database from Ensembl, installing it and #' subsequently creating the EnsDb database from it. #' #' @param ftp_folder The ftp url to the per-species mysql folders. If not #' provided it will use the default Ensembl ftp: #' \code{ftp://ftp.ensembl.org/pub/release-/mysql/}. #' #' @param ens_version The Ensembl version (version of the Ensembl Perl API). #' #' @param species The name of the species (e.g. "homo_sapiens"). #' #' @param user The user name for the MySQL database (write access). #' #' @param host The host on which the MySQL database is running. #' #' @param pass The password for the MySQL database. #' #' @param port The port of the MySQL database. #' #' @param local_tmp Local directory that will be used to temporarily store the #' downloaded MySQL database files. #' #' @param dropDb Whether the Ensembl core database should be deleted once the #' EnsDb has been created. #' #' @author Johannes Rainer #' #' @examples #' #' ## For Ensemblgenomes: #' ftp_folder <- "ftp://ftp.ensemblgenomes.org/pub/release-33/fungi/mysql/" #' @noRd createEnsDbForSpecies <- function(ftp_folder, ens_version = 86, species, user, host, pass, port = 3306, local_tmp = tempdir(), sub_dir = "", dropDb = TRUE) { ## if ftp_folder is missing use the default one: base_url = "ftp://ftp.ensembl.org/pub" ## (1) Get all directories from Ensembl if (missing(ftp_folder)) ftp_folder <- paste0(base_url, "/release-", ens_version, "/mysql/") res <- listCoreDbsInFolder(ftp_folder) folders <- unlist(strsplit(getURL(ftp_folder, dirlistonly = TRUE), split = "\n")) res <- t(sapply(folders, function(z) { tmp <- unlist(strsplit(z, split = "_")) return(c(folder = z, organism = paste0(tmp[1:2], collapse = "_"), type = tmp[3], version = paste0(tmp[4:length(tmp)], collapse = "_"))) })) res <- res[which(res[, "type"] == "core"), ] if (nrow(res) == 0) stop("No directories found!") if (missing(species)) species <- res[, "organism"] rownames(res) <- res[, "organism"] ## Check if we've got the species available got_specs <- species %in% rownames(res) if (!all(got_specs)) warning("No core database for species ", paste0(species[!got_specs], collapse = ", "), " found.") species <- species[got_specs] res <- res[species, , drop = FALSE] if (length(species) == 0) stop("No database for any provided species found!") ## (2) Process each species message("Going to process ", nrow(res), " species.") for (i in 1:nrow(res)) { message("Processing species: ", res[i, "organism"], " (", i, " of ", nrow(res), ")") processOneSpecies(ftp_folder = paste0(ftp_folder, res[i, "folder"]), ens_version = ens_version, species = species[i], user = user, host = host, pass = pass, port = port, local_tmp = local_tmp, dropDb = dropDb) message("Done with species: ", res[i, "organism"], ", ", nrow(res) - i, " left.") } } #' @description This function performs the actual tasks of downloading the #' database files, installing them, deleting the download, creating the #' EnsDb and deleting the database. #' #' @details While the location of the downloaded temporary MySQL database file #' can be specified, the final SQLite file as well as all intermediate files #' will be placed in the current working directory. #' #' @param ftp_folder The folder on Ensembl's ftp server containing the mysql #' database files. Has to be the full path to these files. #' #' @param ens_version The Ensembl version (version of the Ensembl Perl API). #' #' @param species The name of the species (e.g. "homo_sapiens"). #' #' @param user The user name for the MySQL database (write access). #' #' @param host The host on which the MySQL database is running. #' #' @param pass The password for the MySQL database. #' #' @param port The port of the MySQL database. #' #' @param local_tmp Local directory that will be used to temporarily store the #' downloaded MySQL database files. #' #' @param dropDb Whether the Ensembl core database should be deleted once the #' EnsDb has been created. #' #' @author Johannes Rainer #' #' @noRd processOneSpecies <- function(ftp_folder, ens_version = 86, species, user, host = "localhost", pass, port = 3306, local_tmp = tempdir(), dropDb = TRUE) { if (missing(ftp_folder)) stop("'ftp_folder' has to be specified!") if (missing(user)) stop("'user' has to be specified!") if (missing(species)) stop("'species' has to be specified!") ## (1) Download database files. res <- downloadFilesFromFtpFolder(url = ftp_folder, dest = local_tmp) ## (2) Install database. db_name <- basename(ftp_folder) res <- installEnsemblDb(dir = local_tmp, host = host, dbname = db_name, user = user, pass = pass, port = port) ## (3) Delete the downloads. fls <- dir(local_tmp, full.names = TRUE) res <- sapply(fls, unlink) ## (4) Create the EnsDb (requires the correct Ensembl API) ## They are created in the local directory. fetchTablesFromEnsembl(version = ens_version, species = species, user = user, host = host, pass = pass, port = port) DBFile <- makeEnsemblSQLiteFromTables() unlink("*.txt") ## (5) Delete the database. if (dropDb) { con <- dbConnect(MySQL(), host = host, user = user, pass = pass, port = port, dbname = "mysql") res <- dbGetQuery(con, paste("drop database ", db_name)) dbDisconnect(con) } } #' #' @description Download all files from an ftp directory to a local directory. #' #' @param url A character string specifying the url of the directory. #' #' @param dest A character string specifying the local directory. #' #' @return A character string with the path of the local directory. #' #' @author Johannes Rainer #' #' @noRd #' #' @examples #' #' ftp_dir <- "ftp://ftp.ensembl.org/pub/release-88/mysql/homo_sapiens_core_88_38" #' local_dir <- downloadFilesFromFtpFolder(ftp_dir) downloadFilesFromFtpFolder <- function(url, dest = tempdir()) { fls <- getURL(paste0(url, "/"), dirlistonly = TRUE) fls <- unlist(strsplit(fls, split = "\n")) message("Downloading ", length(fls), " files ... ", appendLF = FALSE) for (i in 1:length(fls)) { download.file(url = paste0(url, "/", fls[i]), destfile = paste0(dest, "/", fls[i]), quiet = TRUE) } message("OK") return(dest) } #' @description Install an Ensembl MySQL database downloaded from the Ensembl #' ftp server (e.g. using \link{downloadFilesFromFtpFolder}). #' #' @note The local directory is expected to correspond to the name of the #' database, i.e. \code{basename(dir)} will be used as the database name if #' argument \code{dbname} is missing. #' #' @param dir The path to the local directory where the database files are. #' #' @param host The host running the MySQL database. #' #' @param dbname The name of the database. If not provided the name of the #' provided directory will be used instead. #' #' @param user The user name for the MySQL database (rw access). #' #' @param pass The password for the MySQL database. #' #' @param port The port of the MySQL database. #' #' @author Johannes Rainer #' #' @noRd #' #' @examples #' user <- "user" #' pass <- "pass" #' dbname <- "homo_sapiens_core_88_38" #' ## set to directory returned by the downloadFilesFromFtpFolder #' dir <- local_dir #' #' installEnsemblDb(dir = dir, dbname = dbname, user = user, pass = pass) installEnsemblDb <- function(dir, host = "localhost", dbname, user, pass, port = 3306) { if (missing(dir)) stop("Argument 'dir' missing!") if (missing(dbname)) dbname <- basename(dir) if (missing(user)) stop("Argument 'user' missing!") ## Eventually unzip the files... tmp <- system(paste0("gunzip ", dir, "/*.gz")) ## Create the database con <- dbConnect(MySQL(), host = host, user = user, pass = pass, port = port, dbname = "mysql") res <- dbGetQuery(con, paste0("create database ", dbname)) dbDisconnect(con) ## Now create the tables and stuff. tmp <- system(paste0("mysql -h ", host, " -u ", user, " --password=", pass, " -P ", port, " ", dbname, " < ", dir, "/", dbname, ".sql")) ## Importing the data. cmd <- paste0("mysqlimport -h ", host, " -u ", user, " --password=", pass, " -P ", port, " ", dbname, " -L ", dir, "/*.txt") tmp <- system(cmd) } #' @description Creates EnsDb packages from all sqlite database files found in #' the directory specified with parameter \code{dir}. #' @param dir The path to the directory where the SQLite files can be found. #' @param author The author of the package. #' @param maintainer The maintainer of the package. #' @param version The version of the package. #' @noRd createPackagesFromSQLite <- function(dir = ".", author, maintainer, version) { if (missing(author) | missing(maintainer) | missing(version)) stop("Parameter 'author', 'maintainer' and 'version' are required!") edbs <- dir(dir, full.names = TRUE, pattern = ".sqlite") if (length(edbs) == 0) stop("Found no SQLite database files in the specified directory!") message("Processing ", length(edbs), " packages.") for (i in 1:length(edbs)) { message("Processing ", basename(edbs[i]), " (", i, " of ", length(edbs), ")", appendLF = FALSE) makeEnsembldbPackage(ensdb = edbs[i], version = version, author = author, maintainer = maintainer) message("OK") } } ## ftpf <- paste0("ftp://ftp.ensembl.org/pub/release-86/mysql/", ## "anas_platyrhynchos_core_86_1") ## local_dir <- tempdir() ## downloadFilesFromFtpFolder(ftpf, dest = local_dir) ## installEnsemblDb(dir = local_dir, host = "localhost", user = "jo", ## pass = "jo123", dbname = "anas_platyrhynchos_core_86_1") ## fls <- dir(local_dir, full.names = TRUE) ## res <- sapply(fls, unlink) ## fetchTablesFromEnsembl(86, species = "anas_platyrhynchos", user = "jo", ## host = "localhost", pass = "jo123", port = 3306) ## DBFile <- makeEnsemblSQLiteFromTables() ## unlink("*.txt") ## system.time(fetchTablesFromEnsembl(86, species = "anas_platyrhynchos")) ## ftpf <- paste0("ftp://ftp.ensembl.org/pub/release-86/mysql/", ## "homo_sapiens_core_86_38") ## local_dir <- tempdir() ## processOneSpecies(ftp_folder = ftpf, version = 86, ## species = "homo_sapiens", user = "jo", ## host = "localhost", ## pass = "jo123", port = 3306, local_tmp = local_dir, ## dropDb = FALSE) ## Add an issue: ## + Fix problem of non-defined sequence type "chromosome" in anas platyrhynchos ## database. -> update to the perl script. ## + Compare Hsapiens EnsDb created with new script and the "original" one. ensembldb/inst/shinyHappyPeople/0000755000175400017540000000000013175714743020025 5ustar00biocbuildbiocbuildensembldb/inst/shinyHappyPeople/server.R0000644000175400017540000002004313175714743021455 0ustar00biocbuildbiocbuild## list all packages... packs <- installed.packages() epacks <- packs[grep(packs, pattern="^Ens")] ## library(EnsDb.Hsapiens.v75) ## edb <- EnsDb.Hsapiens.v75 TheFilter <- function(input){ Cond <- input$condition ## check if we've got something to split... Vals <- input$geneName ## check if we've got , if(length(grep(Vals, pattern=",")) > 0){ ## don't want whitespaces here... Vals <- gsub(Vals, pattern=" ", replacement="", fixed=TRUE) Vals <- unlist(strsplit(Vals, split=",")) } if(length(grep(Vals, pattern=" ", fixed=TRUE)) > 0){ Vals <- unlist(strsplit(Vals, split=" ", fixed=TRUE)) } if(input$type=="Gene name"){ return(GenenameFilter(Vals, condition=Cond)) } if(input$type=="Chrom name"){ return(SeqNameFilter(Vals, condition=Cond)) } if(input$type=="Gene biotype"){ return(GeneBiotypeFilter(Vals, condition=Cond)) } if(input$type=="Tx biotype"){ return(TxBiotypeFilter(Vals, condition=Cond)) } } ## checkSelectedPackage <- function(input){ ## if(is.null(input$package)){ ## return(FALSE) ## }else{ ## require(input$package, character.only=TRUE) ## message("Assigning ", input$package, " to variable edb.") ## assign("edb", get(input$package), envir=globalenv()) ## return(TRUE) ## } ## } ## Based on the given EnsDb package name it loads the library and returns ## the object. getEdb <- function(x){ require(x, character.only=TRUE) return(get(x)) } ## Define server logic required to draw a histogram shinyServer(function(input, output) { ## Generate the select field for the package... output$packages <- renderUI( selectInput("package", "Select installed EnsDb package", as.list(epacks)) ) selectedPackage <- reactive({ names(epacks) <- epacks ## epacks <- sapply(epacks, as.symbol) ## load the package. if(length(input$package) > 0){ require(input$package, character.only=TRUE) ## Actually, should be enough to just return input$package... ##return(switch(input$package, epacks)) return(getEdb(input$package)) }else{ return(NULL) } }) ## Metadata infos output$metadata_organism <- renderText({ edb <- selectedPackage() if(!is.null(edb)){ ## db <- getEdb(edb) paste0("Organism: ", organism(edb)) } }) output$metadata_ensembl <- renderText({ edb <- selectedPackage() if(!is.null(edb)){ ## db <- getEdb(edb) md <- metadata(edb) rownames(md) <- md$name paste0("Ensembl version: ", md["ensembl_version", "value"]) } }) output$metadata_genome <- renderText({ edb <- selectedPackage() if(!is.null(edb)){ ## db <- getEdb(edb) md <- metadata(edb) rownames(md) <- md$name paste0("Genome build: ", md["genome_build", "value"]) } }) output$genename <- renderText({ if(length(input$geneName) > 0){ input$geneName }else{ return() } }) ## That's the actual queries for genes, transcripts and exons... output$Genes <- renderDataTable({ ## if(!checkSelectedPackage(input)) ## return() if(length(input$package) == 0) return(NULL) if(!is.na(input$geneName) & length(input$geneName) > 0 & input$geneName!=""){ edb <- selectedPackage() res <- genes(edb, filter=TheFilter(input), return.type="data.frame") assign(".ENS_TMP_RES", res, envir=globalenv()) return(res) } }) output$Transcripts <- renderDataTable({ if(length(input$package) == 0) return(NULL) if(!is.na(input$geneName) & length(input$geneName) > 0 & input$geneName!=""){ edb <- selectedPackage() res <- transcripts(edb, filter=TheFilter(input), return.type="data.frame") assign(".ENS_TMP_RES", res, envir=globalenv()) return(res) } }) output$Exons <- renderDataTable({ if(length(input$package) == 0) return(NULL) if(!is.na(input$geneName) & length(input$geneName) > 0 & input$geneName!=""){ edb <- selectedPackage() res <- exons(edb, filter=TheFilter(input), return.type="data.frame") assign(".ENS_TMP_RES", res, envir=globalenv()) return(res) } }) observe({ if(input$closeButton > 0){ ## OK, now, gather all the data and return it in the selected format. edb <- selectedPackage() resType <- input$returnType resTab <- input$resultTab res <- NULL ## If result type is data.frame we just return what we've got. if(resType == "data.frame"){ res <- get(".ENS_TMP_RES") }else{ ## Otherwise we have to fetch a little bit more data, thus, we perform the ## query again and return it as GRanges. if(resTab == "Genes") res <- genes(edb, filter=TheFilter(input), return.type="GRanges") if(resTab == "Transcripts") res <- transcripts(edb,filter=TheFilter(input), return.type="GRanges") if(resTab == "Exons") res <- exons(edb,filter=TheFilter(input), return.type="GRanges") } rm(".ENS_TMP_RES", envir=globalenv()) stopApp(res) } }) }) ## ## Define server logic required to draw a histogram ## shinyServer(function(input, output) { ## ## generate the select field for the package... ## output$packages <- renderUI( ## selectInput("package", "Select EnsDb package", as.list(epacks)) ## ) ## ## generating metadata info. ## output$metadata_organism <- renderText({ ## if(!checkSelectedPackage(input)) ## return() ## paste0("Organism: ", organism(edb)) ## }) ## output$metadata_ensembl <- renderText({ ## if(!checkSelectedPackage(input)) ## return() ## md <- metadata(edb) ## rownames(md) <- md$name ## paste0("Ensembl version: ", md["ensembl_version", "value"]) ## }) ## output$metadata_genome <- renderText({ ## if(!checkSelectedPackage(input)) ## return() ## md <- metadata(edb) ## rownames(md) <- md$name ## paste0("Genome build: ", md["genome_build", "value"]) ## }) ## ## output$genename <- renderText({ ## ## if(!checkSelectedPackage(input)) ## ## return() ## ## input$geneName ## ## }) ## ## That's the actual queries for genes, transcripts and exons... ## output$Genes <- renderDataTable({ ## if(!checkSelectedPackage(input)) ## return() ## if(!is.na(input$geneName) & length(input$geneName) > 0 & input$geneName!=""){ ## res <- genes(edb, filter=TheFilter(input), ## return.type="data.frame") ## return(res) ## } ## }) ## output$Transcripts <- renderDataTable({ ## if(!checkSelectedPackage(input)) ## return() ## if(!is.na(input$geneName) & length(input$geneName) > 0 & input$geneName!=""){ ## res <- transcripts(edb, filter=TheFilter(input), ## return.type="data.frame") ## return(res) ## } ## }) ## output$Exons <- renderDataTable({ ## if(!checkSelectedPackage(input)) ## return() ## if(!is.na(input$geneName) & length(input$geneName) > 0 & input$geneName!=""){ ## res <- exons(edb, filter=TheFilter(input), ## return.type="data.frame") ## return(res) ## } ## }) ## ## observe({ ## ## if(input$Close > 0){ ## ## stopApp("AAARGHHH") ## ## } ## ## }) ## }) ensembldb/inst/shinyHappyPeople/ui.R0000644000175400017540000001330613175714743020570 0ustar00biocbuildbiocbuildlibrary(shiny) ## start with runApp("jo_test") shinyUI(fluidPage( ## Application title titlePanel("Get gene/transcript/exon annotations"), fluidRow( shiny::column(3, uiOutput("packages") ), shiny::column(3, ## div( h4("EnsDb annotation:"), textOutput("metadata_organism"), textOutput("metadata_ensembl"), textOutput("metadata_genome"), " " ## ) ), shiny::column(4, h4("Hints:"), tags$li("Enter comma or whitespace separated values to search for multiple e.g. genes."), tags$li("Use % and condition like for partial matching.")) ), fluidRow( shiny::column(4, " " ) ), fluidRow( shiny::column(2, selectInput("type", NA, choices=c("Gene name", "Chrom name", "Gene biotype", "Tx biotype"), selected="Gene name") ), shiny::column(1, selectInput("condition", NA, choices=c("=", "!=", "like", "in"), selected="=") ), shiny::column(2, textInput("geneName", NA, value="") ) ), fluidRow( mainPanel( tabsetPanel( tabPanel('Genes', dataTableOutput("Genes") ), tabPanel('Transcripts', dataTableOutput("Transcripts") ), tabPanel('Exons', dataTableOutput("Exons") ) , id="resultTab" ) ) ), wellPanel( fluidRow( shiny::column(2, "Return results as " ), shiny::column(2, selectInput("returnType", NA, choices=c("data.frame", "GRanges"), selected="data.frame") ), shiny::column(2, actionButton("closeButton", "Return & close") ) ) ) )) ## shinyUI(fluidPage( ## ## Application title ## titlePanel("Get gene/transcript/exon annotations"), ## fluidRow( ## shiny::column(3, ## uiOutput("packages") ## ), ## shiny::column(3, ## ## div( ## h4("EnsDb annotation:"), ## textOutput("metadata_organism"), ## textOutput("metadata_ensembl"), ## textOutput("metadata_genome"), ## " " ## ## ) ## ), ## shiny::column(4, ## h4("Hints:"), ## tags$li("Enter comma or whitespace separated values to search for multiple e.g. genes."), ## tags$li("Use % and condition like for partial matching."), ## tags$li("The selected database is assigned to the environment variable ENS_DB.")) ## ), ## fluidRow( ## shiny::column(4, ## " " ## ) ## ## ) ## ), ## fluidRow( ## shiny::column(2, ## selectInput("type", NA, ## choices=c("Gene name", "Chrom name", ## "Gene biotype", "Tx biotype"), ## selected="Gene name") ## ), ## shiny::column(1, ## selectInput("condition", NA, ## choices=c("=", "!=", "like", "in"), ## selected="=") ## ), ## shiny::column(2, ## textInput("geneName", NA, value="") ## ), ## ## shiny::column(2, ## ## submitButton("Go!") ## ## ), ## shiny::column(2, ## actionButton("closeButton", "Return result") ## ) ## ), ## ## fluidRow( ## ## mainPanel( ## ## tabsetPanel( ## ## tabPanel('Genes', ## ## dataTableOutput("Genes") ## ## ), ## ## tabPanel('Transcripts', ## ## dataTableOutput("Transcripts") ## ## ), ## ## tabPanel('Exons', ## ## dataTableOutput("Exons") ## ## ) ## ## ) ## ## ##h4(textOutput("genename")) ## ## ) ## ## ) ## )) ensembldb/inst/txt/0000755000175400017540000000000013175714743015343 5ustar00biocbuildbiocbuildensembldb/inst/txt/ENST00000200135.fa.gz0000644000175400017540000003324213175714743020102 0ustar00biocbuildbiocbuildsVENST00000200135.fa՝ݎ%rS`υHF/Aޟ1޽ Akʜ?3ƈȬow?~?W_?N}W?u}+ϟ}5gsg59]3z} \uf:_|.R=L_s~ _{fxfa}+_ooeA޳z3}| kLxϟfn*u8t^^3TVq?K8cxϼ "<e ^^me `wj.6)ߋfD95'MsYgƳ{샑3|fŘƔ12dg}s=ُYX3=c\uϞf7k,yΥ6VŖp30˃]<~_ڜ9 yco;gw8)<;tٳjk<g+gXi|a{4*Y=ܳڎ+],3\5cn:txvǥ~X_Lia b_ϏY|hck `cf@YHLZg=HX :H2lfo 3!i3Y٠CaϠP,@fby՜h7 k&G;ĵ7=nFtd8gMP'MtDK2 {r d>C?,ֻg}; SNRIL{.!YprTn'+PPz^H~f;:nZbh&YǟgfX}k,_q13!.Aq&͙0DœӲ=d+Hc@_A_>&"YLbD}k ?_z3}o"A~2s̎'!\fk5Y O0&e#׺B d"$#$WP7ekZ-"B3Pc& 8~X;Y6kg٘ThOӜL̀ BkX́ksr%;s2 mϪ{Gm`EJ._[2_>p97Gܽ? wo{}x#^q7Gܽ? wo{}x#^q7Gܽ? wo{}x#^q7Gܽ? wo{}x#^q7Gܽ? wo{}x#-ok o`}}#D_!F70G?BѿϞ????{o_?b~g?8EA>! `쏇2=^e8XϜX9>J!Q 'uGQ#SOW;-ڄVO,$ YuLwU f5Z2@Z"şHCG 48۸J>R|~> O=6 l='257#0OWD{˯{g1N.Drύ6ʄq ,5nʰ}99͑p xE{&x .K:$@U ܷH^0RGvvw$!v$ =!]D̗˄xмMh+Լ= tzA%~kаs4d h{džA;.tWh1$|;\OVd<~=niw+V?NhӂWĝJ7vN"E..z` 3! Wn-W9sq]qs& YxO00} N.-+ FINƘwD"54hT 6ޑDg=*Uu& *//ٮ$5[R kV <-`!WGod@$Җbק߶x$/kGN3# 6]Bi!F'Pw)]c Q@!Xԗ{g>(A5xp}c/P]]cr;Sw 0s>/BV[TD~Yߵ_ͭ&Dj7>s~[huӠ~G4'fiv%m_z39xaE~$OS#؍y%'kpR'2 /sII $J{VcEw$srxx#!DU_u3l9 F/li!#lS:~>:y!/Pp;׻& >&}uG09\/xaQI^Rr+-X~-縓&vW$^&9{5OBLdjʳqܕzH ԄT@W+#jh@86kDMM-ֳ &yJT6\Mj)HgOκi#2B'd%Q !Ȅ)Q@vZԢ]`^cPT>;"b B"V`bۯ'dEsiҔf! ;!$"j :n:IT2aV*? ` -QI4ĵ!zr#tUOJgЗV >ChG|URm o204(4[JPJ̓T%>P:Q)DuEв,: &mQuٝ O*âbjnRɈ9Ԥ5?)C2sViy :[?҇!D%+cdE2W|B$ikYL>Nvs~%~QB(Ր.O2H/U䝶dӻ`|! (fbL|%Ob\"OzRf['cEy"w*ՋjD1cϭU"nD®v#OD1^X)3}#IK]nU+&6Cʂ^NDX'rEd=ˊ(sȋ*ՑIR $'Ԕy!eNZB= A/f1F"sd~ 2{#=w@!8vhS .@;j<[-ݒR\bEtWE!;/i!EϠR%Rށ~5" g _pdbFQ,ՔKa3K+ jD~cxY-K_u~ WO4JR{o2L?E)7-EセP?@tZk8 ?nf6L{5^y{G\AtXDS eZ}_0 ^֭%)2C"aUF Z]-ҹ#״-eC׈$W#fU7j=_,~ZoɝYcОU$AeN-&'恑QdiN]\قV,զ%%f 韰jbD]FϦj0aS,I!ߤӯkxeS 3[ דmsk-QJm}I9A(v=[@D AƨO˞cDe, ȮUbJn$ ws)E5t-!9-jLh;å!Ѭrbd ăՙ^ ZRl.:5{`]/M#6Xg0ѷ%BQT%]@*B$.',hMDq-F,4R]IOoc/+L`ijxU|J0SRv#2*K9jAH)͹oPv,C#'yZo^Nă+-c iaJ " '\I#r??oJ$6[ް͒үJ[[bzݱݥYt7k2X)׽ P lpMć~5a,09gkS2eXˁۅf !\]=ûOpJ^1h,(Ui9T֋ɥ% j`˓*-u:g,uwT2BϏX.8!VKYgIZ/\dIZ%ܺk"W^X9o;{B ШarVfk3周T@WiPN|RGpHpZޑ-EX{͝2yp-b#.( =':Roj &v'YB"𠡦 2c kٔ_ ik7v4{!)* ~fvkmUH4~Eyvs8G~\U8䣂=x)̂anQj&%c8v8L;u-gb~{+xj82h*hS> U܎t(}øjjJO{q pޯ (=1me@(. T:6?fFP++X,1t&26>fE1e Q v`g%p_юn!53m >zQ5?y#DsЕX.-7vX!i c$ҕzKn2ZQN$9eRv,VȏY\YY/`qƒ-Pc׏?\5n?5u`qTT/\Jc$l3!W.YL |N $b8Trՙ;@M,Hw.v- HWF:1m@HϾ^SHXhEu +՝ZBJΊ]NiP͡xfE= dʬ>kQОH:5*1)U;V'GlCF#-]e|a;S^7e*Hc [_B7n\/68 +0'm_^e>k jF޻x۠__c"E҅LE s3zHl]):B^*iFNQ<ʬ+R )ů[5܀x@`ZYsIKr&zt1E8aZWrХTƗJ8u T6al `IB}VG b0!,ޤ+]UGmH¾g^2k 4 99/PUƒK|J٬NPXjV&fP ٳTZ槽4X7`Os獿u]M Rh4@TOKqe0s=ᾬ]%S+.u;)$wA+=6cw,6lq3GIC\(˂H1!e' q`7-mok.@iOKhݿ:L;/oM*ORjVX550"NFʑF!3;Xc+ïT뭯o@9?Tl6RZѾJ4*xm;eV1F,P帹W+[i鼧,LENTYİm{%W]JH͎j< YωYIOK`'>dޔ:vѦ2ǁoGᭋn $sպW ʾ^$\`xV;^HJp7xVd+̯F=?Vŝ-[Fѣx>29`'LŎޢA7PCNc?R0pPR1gQQA_f-1O0#Ucu;[^ =JaVu! ӵ= <󮼭벷dPY#!tk7!r4jjsHmrt,0'N 78貋:vgK St{Ó۪J'6S=4[1S6PnJ;,N3 D}}Ymuӷ>z$!P#̮ `h>g1~>,FڦC$SB)H?I7cl#ԠYZf&HuŏC9{̼^%'(,qYv e<ySl?7ȏ4ahs[FEE<0+qgrŮ,9Č7BoWմR7SI]_$[,d3@RA:3ܼ54"usqU 07N;%ECU?ՆXX׾?W2Q.! |"j}|J¯B‚ϳgoh|vkT*MZ%};ۄzQ7_Pi\"*Ro鋛By+ꪗZVe 5*wkFlBgWJc*dQ)P<ĨiIQHvYѐ_ZY䊷e#LyUGw%AJ%8!XQ\1춽E=9m얠.T$r2uѲht(0" aZ]74R0э'.!&Z/H𥡠k /Ia(2p%\lyAnZsgJ }4'RG&7ayjDp ֊}N|6M\F"L(cvSxVᾭa#XeZu̗> .-!ZJt oE8lHA"fBenJ-nM5D@tI-=B`PW+Wy=/( 6Q .P~]QlͦN=-DP0,&gLlh6ۥd87?7Y B-)̚ oGCE?'iմc@lMXe߾ga"+Z.L@,"x--HE@B!NQόb (XcGF1?0'y z0^bng2!|AkAHh~ibyE26[u ;:h 5H+טƂ`>W.$fDd 0E,{26,k"" #|pVbntMR<(Ԣ̄ͷzT7nՕ,C h|% +۔)6u%BRuQ[{+aZ{2ɧx,Su)O I:=4-GR_ " !Ro%$U|={KFp^j.{XݡpGs )o*9W:X9[RF]Nn`F*okjN-IE~ ؜eu6v({mN)oe$%wD'wzӐQsNGAR\.U0jab|@JB{0E Nط8!Dq3sljr}sXFɦ.٩)*{h1Q&Z[|)Fz:.ی$!D~sLЖ'^XBZ_z6Mvi;ә%ABeCÔVTh" m΋Qq$1_ ƁK w§|_qϡn,;~쁱YGm!=gZ!U˰/?6aى&іhev4'@Nʂ)Ud_} $wN WT;ò7w, 8W<7QǸn[s89OBr6FSYS6Yf4Rjc2o *'B6""J~;N7|J y^v7ͣdD`7*?~;twt V4 +''H,yp› , `?ō¤mPsRBs;*h c8zmŁxRuPQ]wDYK'zJVgJ;Z:73(Qs8weêb˖g^kQ٩lmֆ%aADM-9;6S5`aغDR SMC 0J(MgG5h>kůvq־ ՗ESTƈ2dHxϼsdJeo̘D8J~k_FBbkuM6ة+BԀ:wWqKv~)5Cyő]&#RIK7Z d?Ee 4;L%۷}tx ` ׃sYKm<%g2۪ڌ:ԒɃb@UZyلEzkRaॺ&v\}@ьꍂ_T 8+hij_Ef ǽ~ jKS)ݕg9 # &WXEQ0"R>SX`Pp}KC9x'ެ'd |Ⓣ (;,.F!CClWE,ʎEoQןFIK{"AR:p36Y&4nT1cGa'\uwƆ)X̜.< `lPJζ{G o2y4y\%Km.~ٳA^%-TA` [-(B` ~Xkjp$"KG͝GHDFDC;yzheuniz7.Q0w1^YJ 1s~"j1 g tkcU|DGᣎ{^[x\J\}S۳chVf^zM߆24)[qí/Ȯ0"0BK+$x@h#>)x'GY ?˾c)H_ 8j oODʫZ$jv%綖T%ks1BEKpt7 ^+_IxWO Ƞw@s4 ( ۊ>v'c;$4HDzJ . P eRWŎx#ȻE\ܚ;F|1'^zv В(]D۹ g,,%;("Xj*H H I㶃*{4˜bY˩|㕋`mwtixi`;2]}fv*\] RFo {fhw׫jNvԢd e*6KI`v^Qgv'^B-)Ҡs|#He7yheK[yaw{'; 6ֵI8oQfsʰUX07BJjBfTby_[g6JW}Vc3ⶸL7:&! -\{iJl!E_) tpXlcJH0o)tEl p-2Nl. 3ҭnp? 27d^FD C%ESE@y"LͣRHjVT8$J>P,%mz1/]ߺH10uNwQȉNk٣a*5R)It<{--ZqE&ǺX?_߳a9=0DDЂ Ehh_t*2 dunEHRho݀i @m ~h)1F|]m# _ѩxVV4(1 >6|s$qbrb,Wl"M%,mʚnXkwJM ensembldb/inst/txt/ENST00000335953.fa.gz0000644000175400017540000016523713175714743020135 0ustar00biocbuildbiocbuild0VENST00000335953.faͮ-ɲ)xuUX JdP$D6XW(R=ϕyvdK p~+w9o]{ˉsX?~/Mmfv 9Y _vK?8_ۅ|z>u̿~}__gίwlgu>?99e`|{g~>v=v/{|ϋ57*Vdxo:a)|vy>fj>A׾\F\mcs4w`˲?Y=ݜ6`כxm"=(,]gwvyjO97l'<n%>o۟,#f7lа[g42.gg6?Ig;is{{l`P'S1Ź]T_HݡM#k 8V\ݟ!ɳg?I ZP={4"3]gx g\Wb|a2bM:$mdk,z˷ 9yK׻+AzY=A_S`XpdwoLahp؅îOp lй;b+/F"1^mHv''&pAbϷX&rGb]P;9 m6> 7`y&WWunUb;>$b%h I\JlUEQ$ǕuJuJP:x(}ݝY:KvgKND0/V~GV_e+#+篲ߑWlwdU;r*[Y9V~GV_e+#+篲ߑWlwdU;r*[Y9V~GV_e+#+篲ߑWlwdU;r*[Y9V~GV_e+#+篲ߑWlwdU;r*[Y9D0leLlJ^5?;a鄝Ǫ_~o_O?E!;S@o~m-,HP2@bXP,MWMErwm{TʼgւtgFJz?C^KRp kpr-e̹<&kPשH'>?dx*)٧* PMF:@|~4 onӨ*<_I}Òn 68f+( R "??{6B3 rGa_iCwu._hg%7i9q*ˆ6nbxr羿_oSDr]O*plcېVITCrt*$-(d]C{6-qMB23q% ҳ,)t_QZLM\8MjNySɺ>Z~E,;v˚Ҧ$Z,^fAʍ.Z giްY!2 |CrqT>`ިbCGx;5FT ‘*ku<(|~*ڔ(C!:492Ra),dja[KN0#Z,~t8e!]*7:c8%>OFiEO]Ii=CTG&aDZfD81X#\1r m=HqqJaـ^]I|fM1iv+CmQJ.4PQ0f|P=5;rnWhUT9rnWMMSeUT9rnWK/wUح {]chݮAE]T9]e*w*rni~W*?*vU:`ۃN_Mw*?*ͮ P y> [ <RBԀ}{cX;B{ tTF5f I(6Sn0>mO(X4`J93rgƐ8>g=lSF&ŞWXk:\ZSHۧIce +vwžacaJ(K&4y+ZI#>u݀+gh%nxՒ*ڈv5fVa])ۂ*C/<92}~菠d,I+F'D}IBI[$L3lQ'}8FP5-Nt/I9LRQ#jv<# xU㊧*Bph?y[Y%v-ݠ\.nZfЮ:"8#!&|CC3 [0I! ibp1YPH,o\%.(*]\b>7bM.<2q^XT; db{YW728BdXJ2:4e+JEz Gkubab˛vidz@ºc.MwcctUbc;qP P̴F޴}*=GN 踂9L뤜DzgC]Fr[~Z֫%.z[&޷sr^Q|Er;RmkE=]"Wz@\|WjFu!l zg2k`32?(b¶t)2J @|3exi5"- ZW00pG7`PcIpW{՛/4a@Q0CdR[MBQ'?BM:'r jzw4(ժFB}7o*uXCǧ FAK$k6h 75PHȍ}^:u j}M(4vF f"-*4rv&];UfDNXkqNz^kVA VvKZ3A׉v)>i_f$fZ[ 1D= [@ùs¬>i}@=#s*Ƣo[~߄Ϭm tʤ?01[uu5UuJ0q?>u^XݶKJn`v {'kѐN5~_jO} 7/Apv!ړ-3jhՀ r7p| ߦI^:}cq&leuXos \94qlM~##g:}rI8ONpi0ê UK{%>g7gw \V%㔅ޗ)mZuߚB1Nv{Ϸ2*Nʸ5}k͵k1A4l7ܜG= M|$AqQ$ X7.3;o]%'.P܀I Ǜ0_drU "KK.x#C#D|Lu7-굑cq>(PGAu*o![*!%wc7apkn ʸ [=wUDVfZgVi[ (xdޏ=bVY|j /%vFLhPkzb~Ġy>V݉̊7/R(*-#/?1;80q>559L^ ,|xp]c`}>l\q+ RT@HJ19Ur:[E@1ё*_A#:*mؿ&3GK'J8o~jMyrSN/ЬM ̪\v8pqoY"*Wh$:`iιֆ+Dґܴ~q&[LbNY29a֥(Ae2#A$l#Γ9DDt$IY q-2KIyRF@]<G- @ ]z5ZAduV5a-q`3uHG癱z4F6;#~xPŞY6R4 ?7H!nrQUÝ$h1vgO gk+fxd[AnzP+I7ٶ$j7vq {{tߚGC;74%>x3:jjTC t_~|ƺVd=CCMPڷqd;TkaL|Z+>MD7lM|u*?G~6J3^ED R_c~mP4&f8)wrhKY2v| XD*6lR@lζƧ׼KK$țHZ ˰I͊Pcw^c7>~ʵls$GOLhyi2iq`JW&q(r+M j8t%þ> ﰦ<^_$XojWWE]6gBU+$kxm›ltpR2#ãwp6A>Ur" ,ѯXa{> $tw~mx*d)uw{ϗcMkJ#/B?Klumqz,qgjřsv9p?!j>V C:wpbPbP87C[MБ+ۭ|>C$fڙt-*Е̫4ތ9Mc}+Z@nBA;X:{:?i`Hó|%[!c< {RE 3H67)K iSHۢr)/-}2_\4iQ컎p1Ppvo X QNeqZЂbτᵍ S=!ꛪzx 8P+(sqL>3V1oY}%FĐA~@4:jt6gNj^M2ܓ@ Dbv_*;xm/a!{ߛqVs$xb=qr+],$$o ѣLfo7F mJND3j:X m%eKK{;օե+F%Ϳ߆%)ʳD^-* ƍl Ye0He 5TV}F͓W{^NJ{'HHo._򭞐/*^^\;إ(Ao4K/ k_^pqk/El(pAyhAM[ c0Yk|٣O::q|+./MiI'v' ےwX,B (MފuUgA'zALOlθo+YO9ݗk[.gyb:Uo-dgNTC[[*t4I $ QV%,)ɓ3$:C4_<4&I3|_uv2˦Wgzc%̴@)5lXd>7v+О+H1hD36_:zQdM %ݸ8  E hXσ+D]l&s٪| GB2*@٥t(H6}r7 +x5]rPj>p cW̨JRaqOUnnQo|Cu[Y(l?c]O\F⸵Zn"yYuf6cx= Ə0垍b4Jf!M#:o"f;{u+TdsizE !a̞CGvTMRsh(->ue r%+c L:Ҁ}wbD6+ym+8.xX(-'Fζ*EVǰr,sz?;ypUp_ݞ$ #[W>O!@&+5_bq\#vU.{zźܝTv׹ Le"qu;q7+G]9 DMh U"Τ{Qc ɠ+cn+IUUUIaߥH *:,yad[j_T}a,G74K~Sy]kg׻FH"R,.d0[,aZGpWq޽  pomISSsojg62DZ=ڱ&[kWdN84hO$n.h *ڹ',龦(|xzm)cdWa>I&H Rjލqd', +5cٮy٣/^5<6AnZe9 CUA@QImZTDA|;]-W7A|QKhZG"pI<&Lb+_o1 'TLlpļh_9-1F 3qZPbؒ ĉpP F d__x{ Ѫ%'qQ!z%6;'TWwc+hxDv{K]*ʮz. k+Ys_6=GV*,%3&MaH1:$Κ*]k"mΌHcutT,05}Z GkG39^;v!2-"s$^f0L?wz z6YS[O+Z(=n_bXJa7bQ.:L-+AqeCњ8'kUBTk%z'a g,Jd'e%e߁x]Fra/Ժϋ-9eUXx[:|rsؓJSYѓc>Ll^@p1B_2yY#w_lx?vEy48S-Y b-}^5&q03.^Zѧ60wqof Aed9IX:z< 8dGqin}@>g,ŷ?kD# {2n޹Vw؈#wa1ي&(7YEǃN "VPo/+D ~ZA͊yجָ EѱtY2EяMߊc뻱 π Yp[e1pRCX mxVIHWG?AP:zɴxtĕ13 eY?%o-Kym(RE'WϙڜDai5X%IV.}A9hҮ.fͥ(=NU\VDewxC"D A%3nO)C1"\b/fy}9 r +ܚr'dN;^vZ 7ii8N7 >lXCЭ=x8c5{y>qmCh'H .mZ],^ OHR-K@/wui?|_':DT&[ 8)unVpkDA T'XIԔ&u")p{innFhXOWa`N7ryQ`(x"Y)VOMIUA7y<>T׏e8wu˷T&l+2@0>=ieCk}&L?*e( z0 FcG.=0ETp|2:; ^9<]GxZ36nhm \{Y+$Up/o{Aw:^8]GU0q\zw5:&V=tܕֱ`_* v./_]0lQx7V؁P]HILXR~-i6pd[BBG7d;~GyJ#E.u*7!>HAA=!Ȣ:^˦X'V_CTecZ4mq<.}M͂>/ Ɖ4^pp`Y8ߕ /M# :|_;0*gvPGB8ju8mxj&60h[B,zL5e~$SL\#᜶ }wDhyvEr华†Bo=әhad j yR^N"Pa3 u\ꗠgY+wo<ɱ/LdnB|',sEF;!%5PzlstL:1 {JԪyI򦊧O,3;8ijU6ז$?+@WQ3ȺdMEEr~6qC-K@jZ7:^NLвI @5F(,HkI?r2;XņQlyx!5wv T&%fһil{E tjv&nlH`neWe#f8J&<%kZAC ]U}S_# _Ah~ykC`OM%)׆g?ږ#Ϊ%AIeevG?F1,dcob]eUVduL=˹p\#cT]hJmt%фGWJ+q knӚJOO\hz`!U<̡AI}NJv'Gxa7CbJ19_A,zWfTWcF,w!)H4&XKi: q+u#\H#+dޟTFr{h֙q}TI C|3@WU羖}6퟼==p} ~[AaGA:UȏzЀmgP4qeld8E+%"z/{mȃnٚiqV&niߞGVz[77?j1L5R4CZV/2JȦ%"ʙ\9KnΏ'9%BXL k^Axc]u(IDmXcl˦O, 2iHf&y\y@7/TpLJP{^Mp22I7I5S+~G[cKd} 4f߱No0)θb;.^IH~FFug=Y>^Oi2ozՃD s=^pE/+m[͊1'D.^ (/o°C&fo8'ձN|DIlW ,30!ǁރSiPcURӽ/,ۖaj?MgE { X oYԅ+Zb׏BN@7j]w\nʻ;2[|S#ҳj*6ĭo≐Fv]ꎊ l/3vmp 3j{'T)44 i۴[yS9wS{-B"|}|_F,H۬$5n~#JG&V{׼bô5A̺E9mǁA5 @\]wb.MϚ *"s+$Vd&vl;"W8=΂y'Cc1W@R@v}DjצN*H)U֙ۡ7E>NEX Wjƹ`3תּY(iqWa7f4 <<ڞ|;1'6a9P<[&Sw@渃ߞʳr(6(cTyz1n;8UIޒ n39XJ;g+m&{ruyYuD]@U8t'B|6dCBO܍ tvW@+6SUEl.j48cJLO'GvEhٞꉳ$e &h.retIS)_Vǽ홆PiwZɃXGJn)bZٻp7S| ꗷ_&JW?1l!X!#ƨNǪ)䵁AΠ VGBJXrA!&8pp7~ûϠdR/gk-ݸkk@*JZNZЋq2i@뢂1Wjvw8G G-йcxG97Iؔ0jaӹ!5VqbC;&' =A\o"l -O_sy{Eseި~)0 .k쑿k]J-⼞Ƥg j ¤]|RL!4C`ö(3zgQҬC9$YJVJW7nPy oX]kF(17{Fh7b}-ΚAMG ̟Ҩ":ǾX;)puNh6QcѮ27ܻ`z]Kf.ϕ "KX)Me>by?>*./B\n*l!|1.6 j5 >v s=(` ds5sjN[ :M5ai/ }XsԷ(94䖸9G5(LX`kvZR bAZvWnCi|(~C׬S2!}PydLulk1xu}X?!x``5hI/J +wl>LH7bcu0Ub-mG# S|Lu4,y,{4<7ܔOt^d4A1}:ӣNw2 R@}Q6|&6]# c]wM$!&7 1yF܂{8Bt}h9QXkq{5@yၩ'LsU.B OVӱc pyLmwNBk3UJI`5ݱz"onK|+af/fEO,XY8װϏ>dLUzFj}t1û-r5L|"N 1CRR%; 7,3Paw;6.۽avVmR \$z2JD_fGuADǽoo[KGgQwAs$B̍Bo~ عuϰ,dYu8.r[>oh?52 M,&[*9gvY tEɺ 7\F?DIVÕ N>c;fԂE7oar"X]#׉ӖtU}BttL~3wJM"@[oi %g {30 }AM"/oV VRߦ0_Z{ ѝPʸzͼ6OK9^$/q"fL`]_s)%)%eؤ֫F:AQA{#{ƌZ?O`m~txqB)ߕ>.[@ Zޠ^L+1 :Fbgxڌӕ&F+욄M\Yk[qk8ڋ_vwG=v?ՏqzZfݏ6'âej}y[ #h_c.8vxS{doܣѿMQGp %Z l[\URmܔNġeRZRD?6C G{_U+㭅>++aK,p}m1̪a8u&dtSVAJ^[i3H<by_RLTݼn; @!PJUf6׳荀P$l[Y}5-lcM<` ȠN9/G5vN̐^0_0붬\lU6v @};c+NsLiՕa~)jDs4A.)j[ʫ4?H]>Fj 1@#ogj$+} m/QᘣWDLjC("lDiU ɣtT\VTx5dO`ql\dKɧ,Ai .D̿KI?^+Fx Mm?Th Ug{Z̤^&{/؟auz 6GmՑD܏IL*s o0cQŭߔ ̡8pl|Ǧ bs]×LJkfDO {/0zAȻc2}ӷVl 6(t*tx\qi^cPtr!ƍ֟oQ8QIVG~MJ[K** &CI4Jۖ'39sQ?j'py}qſ׫P&ֶ\ye@!rds^d碝ig,]qc SHm`ˤf]dy15\|RNLUobr,f! %!m Vw%p k;VtN= b"#<_ Դ`oΣR1k0m޶.h%t"w>zQQOs7Ԥ_sp0k$[>cŎ&D<5ěʚ`\O x^ݫsFqfhl9{$ŬFg&RmL}]' j4&Qɐ73WOOA?^?/b_̈́5ݿ#ؔN**vfc =c-j+>muCL" ZuhNr*rGM(fq+BOu$)LҲw!@;q+)&Kf^uG}6WA;SW` K.elLȉ7hAoӖ>s.*M7tiJ*~@@Kt_Zf҅(/! 0Í)[NR"CpJL~ڻ:#nEoo+\&q3& nhG:*w.xxC懿U$z׀Gk|b:w*"ԃ!(5wTt".2(W?`(o ȉbфƀb/pfR+`(x[~{w@uI:7(k)$j?k;) A5=c0 dM1|۶X>vKKmzt[DKw7x܃Y/x?d )5gqe/Z"\+>-:A *!6d@±1:HD6ua;ZJ} 7ZQ*)+nJ0z8-ѫHun A4:hEF'ݡJY: ھ.MːK/ âo3b~t0tN"2YAϧRjg8Kh7Yk]-0ϛ{7^ l%(u)܁5OY>C@ٰgiB f晊b0$ig_v BAхhnŪmqQ@ #w3!@#Tꬬi*e7[3-GkDR&BX zPa w0Ik5K_O:d]1kzػxNi3B >d>8#\6mnA?ooJbl@a g U:ca!h1D2t~ry0': ӫ[qhtߒ-+j%߯pA2 {<07Tr` ЧA7 A'+&<“Gډ%2uIM^m[laK+FŻ-k8 0G!_1p8 wzkāW^ۄƷ񙉖dFB6ѫZF91v*y 4%Ч'V/ miA_abH5GQ#?iJ(<3!T]HX˵_8Us:PVf_zMLPN餓N3} w6I]Ĉ 9bw7C޸'nd1{3ir JZto4(h߶S輫Q@NXY[/ϧ{# " 19ckE`7?w?xڒMovr'_.{eAu6~:|K +pD8 5v)[PvncHtB-^uRMNꃮ4 ajֲhoSc7"(mGk Ie0~kh4j}yX=ׅFީQhcft`D{m<''"Z{"ƒ9 @~{pӄ>T2s+y ?snA: 7خQUC} dZU!MK2!G91L7jƣSse~8jȐ4S.헊uq^U*:ߎݑ 1'iUZe5s'q=T*=q8bgc9ȪA ,XV?밪 eYڦ͇U{ &m!s 鴻W&Wf@HKޮ`-wAzJu5Dj9iTZH Պ^vnҢhpBwzjY*%{t)Mk#mt/oi|8m-{)plw x*Ѻ>ehٍd@Ċ(pciJ>ŝ9" ɾ,j۞9kG]bZq=1*G/%bz&;zWƎt`B'ho*Uq®JMx)H{$1deMYQ8wn!vH)5^',GߠNgOym~c".V×cъ>աgY/@dFs>Ml%8Ɏ>@;sg—PwQgz!ijf3b`6ikEs2z׋-yFǯcǓ[KGT wa_& es^5xXbŠN*edvJQpɆpojJSKud֡i%}FQOcxcv#Glu\"1Ok f@}1eQ0q.T7h5X &<Aq剨 Գu $NٕL#K M2C"1W*ԟqN#n잽W]Qh$;PE52OT(ԡN9҆|aFdL6 O_I볐|FZ;&amۻxEVj9-BI+ڈaL3.CǭWujF']/(M:Y*|\b ɝcre)z7vmE5 _n; Kg$x7fa?tNrnq'dVlD=u.X2膕[4cĎ!ј\ܗw5K@$7{qi9MGjC d&~v`cS _Ȼ|Uz 2dkܲ"_ _~0MEI0*#3q5%e p>@S{#|0u:1wBaΝ{a0w5Z/fw#ỉ,ȲRJQ<4‹'"2a$^.D}y&$Opv?a#ai1~5`,BKem:smd{@ѫ)`~Z&c ze'"Z}śV(?|19k ;{AbV&z/9+h q0xHު5~Y#}5v u C 'A#zB Ely `)̉V۹!%t~_m}#Li1b=sHM9iΜ`SRne -B&gZkoԲyK@&2J%=AaSz>ǵ#m-rߑ│ s2Rh%9ҖWJSd{#E8SRZv^auq9+^ާKGg"swZf9W-Ho!p1 5 eXACax(o$onuYA٫M&'b"%Լ+%AK[˨-tt*8MR Ҟ"Rt,'z~VQIטf6oTbqGF ,V* 0 e_%cOJjtQ:l> rF*PPlhA/C2pPvm;:켭 LYl8GaΞTsv *?g'rZUyeFtoxHp'6 *WGL>O\ǂ(> ~!pݶ48b F0wrV:mi ۺ+*J| H,׿s/g+KIdA^v9yV9qR>gO9^Cx„'aEOʤa ȱSI73HfPyUEk1"TEK4 \141nBkL\Rq[ϴ@pzb%8k]渭u8\EW5}*T*oAW-{?҉T l|GX"v;N:iNcGhx/2((p2]<kD&2Gh;: :6˾GװW;#`+jK`$Ex3ߴʍHa^ES׉Pk +)eCW\6/k&ޑ ;[b­}݆.zfaIc\#65Ђer^L,mㅠ?aYv]0n\.%Sɀ- 2v³vd`CZstMm{+>uG?i~1;hl(o1`iuNT!,𤯄(Y1uj8эKwZҤ^gvLRO@1ѤiB egôXKN|PRi;t%Xu2b}2CWVʴfC$N&~ |:!?ыGFHB?tz&qjh;SI5@ n% y$) 0=R(¼MhXk9I k2V7jU/P::sX 8Qzzaͯj\y<0dxAV~PWr#d?5nZ>[#k@hzIsW{b*~SJWSPqɮgo(VI,_wp$%|zq4G!2zd7\@M+CUIE)q!m g0K,+4?>OF*p v^=yco[)2D?}RBH':k!'ƏG) 97+HFlPɺ^Ԇb۩=W>n#"H"~wC*{=rцk8D( AnYdtF\ W\ֲuԘT ?W!%:N' *bTg#'Lk/̕^ķK!v)?KNizdK y[n{IzH+'qvJ<\$̡.IiZt݌|kz d/n*uXWWzyd+6yw7ݼy)!t +1Gr0|͘6@V %dm\!jg & {Ț>r}0Onsr;SBZs⌜PkV(T&<C,|e6ҋ6}U͒II_Ǜ?dYO~_qh-\|go9_t"oϝ'|[;$R>;pA5k-Z"/a@9w[p+hhY=kj8&i\G4 Pgly9Q,r Wdn%1D!U5$:e8HcbକJ%Dóa$( Sdzn7>WBs]__;5 Q CkNTĝ:}@֣3i=j&O^\l-<[Fj퓳\R= H:@oV-/׋*xJVT=OZNQF~ramۢc;i͡Ց:}3i}^͍_9x NBW_ \ _jn!|17xlX?I~-:QՔ>SuKO{bzj+Į&LEɃ&iy;us\\!҉uSଚ[Ot""z.JJJ̄.j_yyqf s$*nJ$jHpQqIGst ЪY~sܶ`Mp0!,dM/W_s=9_zKӂ |XER 7ng㴁6CLP0~ Of Ƒ_{4[,n'6%Tw$8)/PNߦ簋 kd+_|~bӃ݀2\ 1|(тx@H]WjSe&M;,7䄁^笅E~ϼvgYqюTZ.u⾾7*]d,cLnDLMZ 7fSqsOSYZ`|:Dh“®{g}9w˒رmW@62wURk6`d@*:bC@t 0-B«5y.C46.iym{}<pvi]I5в/n bJJ7M%]J6UH)x*_XC\Ѽ dɹP8o ݷI!sՀ0wWD(B׮791 )]aE΄zL{49u˯i(K,~d|Rn2+rR͗N& %.~DwVmYoJ{X䮹WjEOȎ|e`[4p:D?e@ ;FRv)sgފQ2H Ro<[-wu )TszyTDibE9xX|s9ԶQ#}#*/[YPCѓ Uqл =79DD/ȨS Y؊+I? oZ-92+AZ$VwWCa (a1W@u F̮#q`c<(!|J'dt޳@5n^W*PFTb%a~?2~3=8+gy5ՎŢM2@}m ӼݟoK?_3oaΙ.`|v;lB.nKI|~% Ф| |FPcNZ*'H˅U`t G(*^N/Pa^55tgd^0Y03/iDٙ@y z FJi\)=bq(f,yǢ;.Gf3q[4(-8D}rޮ®F-040mUQܽpE̱Ο~Q((} }&b uD<+;.렒cJ#3:u o)єpR&2KפK-T z>*irEZq 1r%8whXq=i<l`QQkjF"MƏ Iܬ X-owԉT"oadpQ V  Q^ ʦ@;5\C:VLOsd_΄Bc.L(g ֑PLFTSK#.~0kI B* skT򈔲yFPaTRgX7)7lQ C߆gNğ %w75x̵p4O`qݐT:[T D4Qιuc = ێ݋C]2# yj|xW0& pO=Jn gtjj!:.-o2}"{:Kw=yzooο[sqldI+ wP9gjuIz(B勎>V}U|H&a* V~Ƅe(V>$ׇEFBnQl"~w/ǻTJ13*޳X;ȶ޾NDʞw>&7AI#H$<\F+@qhԀ.z4P bw N9EwܶiۗXݷ`e rH4N"sPG6]퓜y%u\ScT]F@ # T\ Ӯ=U żŠmˀ]o1ePjL딀:l̤Ӂ$l('RNdn .XԷ y7R 9&L,Dئ' HR#8=7^׀ a *uqZx5:n,vY42% C(¼e^OQAŗp ]}6P.zOhbi>v 3O}fQ$*7c*騦ء{$,h S IitZBS8 oM7zH6 7_n-:O\KgCqΨ j y"S3ڃV+Klaiy S'@V,"V8퉲g~ dPߟ!B o˪]j-7|nBV#XL>5ioz({Q$g+QjAr,=S! 5J"I91RE@$!a=ӽEũq_p;ʇޔYvLTXU4C6\T:3>r3)W ve4P`<ŧ)sK{/\}\ŞP_M{Qbpa뤘g,O̍csikhB;-$Ԛ%%=Kq^I/ws'U0Ɍ&S!S& $B*`>zNGh.O{1%R&Y^S*`PUϾO"1B!4ꍻ:ɘ92̣V𮔳G+'(2W;u)F_a珈3?AOXEsEUG|?#fl\\Y[A@ *~鑡ם9=$u?(@n $;]POS uUFFT#.R't1Yh1LﶟVlc$Z)q6c fz?a;4zh97琣h[)2Tύ/N Nf |sx,xO ){wl(8lcͯݯ:T!Rnz 0#-P D!;$>]L8AOTjwC&  藊#@rm" LD/ppB9z+pDqG=۳ yĐkP4O?MvKqXfSoF7_0`ؘPe?]Uw~RtIH s T?o|ft3yRZgS&JwnQpNǂd B0V٣ǀlz3~"Ë,.(3H7.2}ɛoAOC& OA@ݰ X'۝Nߤl"NX2} >8nRIGrTu5kSoޓ29%]vRqKth"[՟J͟F6/N]mE1~X({ p.@h5R|+|ob /D$9{-o(.v$CUj+gD;]J;%^5rVMcΤ_zN<``@PMwVNfu䓮m (¤Uҍ6+ &YE:pݤ(ѿd$+xp8.A)lĨWG]vkv,TdbCZE'͹y0yYe4GN*Pàj}o|L0*d27Ij.a2Jՙ?`o[avzk;Dy.n!OAu jUHyJ$fw(e'dOB%'􁜫;9ZqTG+ Fa{[_зBK.DҲAosWbOsCD8vPu Aco늚KŌ xC;!br)*XThD>rWX煊@E(k;vJ[8m-]Ⱥ%҉Ii wjM˰(ejԩ߷cN eOiQˁw?.pqMe.Q;wRH8uDÕkW`Em3T?|۾yuMi:b)w GH=4oLOtRxf(v۝ ZY5+ \L z[3 sCq9`Ÿ19> ~[vn&X`k䯂yN׏.үl̾IRlq*M˲D %5%8h-BjIY7D^ >h9/dubD"!Ix v=GXC锱m㺐x7{޹y$3L,2[9EU})>w!Td Q3UϚV!b[h')9aZ j6:֍tgr>Qtmf#j}xm{R#C NrO@a0eK\So9.qU"aMK?L>RJ( ,mqj6Us# mEm%Տ찃)HOHDND5#&Z\z1*'%_X,XZ.95*4G N̸Qx{th\G Z[e$ Fzѧ>>ImW'"{Jn<7dJncvAzؐӱGc Dq_TχޞOnOpajx OJn*eƯ@<EwwbYbۗ'gmߨnMJ߯eM0%~B`X0+=~CSQL::O<_R"["ʕ_h:Æ Q5RP _&I[%S|hP$! E"qW7J2r҅Dmvi;ظʩlz]w“&2qBv}*گ6[CYY6cZ-meP ?hOc!h^,PQt\BjBzTGE]4CDɵFL hdZ`OL/P>[Q7anc9+/]6 /!`F7Pk^[oX2%-qXN;RU^X󕖞0$eq˔`j ?lMӸIUes!)g+3wttض|V ^C%+>ż#]%L*rof(XXSqZAGF5XRԴ/{ ltRиPv2 #)LH8E͙-~&%ƛ!|߅**?>nKX %af#$c+gyߍ-f=2gn C rmiiH綔yV^?|.IpX#JWa+9PE٩8ݔt,IcLx+0KN"ao"ܐ)/g82<(U8Av13-R AņMt3\FC~'qh'-W6N6AԊ~Y!1*!Cjg2'6rJ5r(B!; ZN!3qYߧ{nFlaܙR9C\C-?VAzvO|W03oL?.g'3YL.C\gCPOeWh&7X}4Q) 3dc2(T( rɅR+5g>nMeɷ^׸#T$Mݸ< +Š$*e,O'~dž+*Z=( οDuJL ā]E#z#]TC J*۾>OEuҙT5(:˧ύ.=ݯƷggZ8?TX~斦Cvp,~¾R1`]S퀉$* Oj%_`,WI:};)(?az6ϡ6nіRp4D/0gC/rTdHigxA4oq ^N݆p{7 IG_3_upџD9&Xэq\I/6#P&2 ozCgGNx:]ui@R˵'پTiW!LcC8ָd]/&0^wsƤ5c6OɎ /$Xj?%fowÍbLA[Nr*%=hfΓ,뤧6u҇<=MVTtGea“Bg]-0lx^0 $*_dQw1͵ )i/q+*M}h14Hcz*J8{99Nq0x$6| y1Q aN)Y <Z#|<` %{9^!eI;9:QA^Ԁ"{&Z!iDOZˆ4)/.pY^-ZM뜁1ܛ)妑:s+udG5 d4 },mF~~S Q yum ew[&}fIW&QQ$u%NnW}Gc 'x_\rx;iӾbԭ]g=g( *et}tppA ݽg=yhZTӼg6HABW-Ev9> -E* HKUWT bͻNQ]VE׳S_):$-+Z]ԠSЄ7,B҅Ii=(gt :!t?T#Z Z {--KDŽjI߅\AB> U4D޴K+> vu Et셹,fBPdeW n0L;kxu yDZ#o^bWd1>+IS#dNp`7O o{? >@=NOzDnΎPO{@썝~)(0.fwT02kE݀P R+N|'y8 B'xHju~~mݱ_ sPAM|_e۞"!;ث+_{a+OχQޟ'$t$ MؿVLOMiےJq4+!KB{ /} c U4!*oO+8ЗyiUQb  \ `dym*5 Yis'zN!XσH,"6V6jy[K2oB vWGXCtcn ߏ I|E5эxr)ggVCKƣH<"=B]R.dofϷv E jwUhdOnoBAEZw{;$m/1+¸QI8l0 ZQgE!O 8ʸe(bwJWC8ʚ̮1;4g^@\+ik.Hxb`w $RKb3-;$hJk mm_n8ql"z)~jFsJ 6>! /7Ch֕ ̿;r1Ǝre'G`7C73"`8_n=A娈 ]fEɋl^/IxWsoqwQGXd![;zdw&?涼\i5z-(ΔH \sޜۘll?x7%wK(Fed$(B#(M `J"1jmD5ȏ8xtZ|p},Zˏ 56|8e b7r:tbkѷƈ0c_UʵY /.3oSB&fj{cB HR'ρ%/OK"71sQAp92%ɗ7ϣ$T F́+(kӟ*fE$WCHf*R2‡'QֺMfy#-PʑOJNvv+- q1Wy6MY/1S_"Pe3n(A+`o]RX;L+۹vEƲq$i uј(otTx6oV\쮀P~mLD;(0tZNlZ6|4<*=ٵ7y,tx] ӊLP r oE }7N9vJ:u"q{#۳f vwbyOļaPG`m//Y'WwB @Wt]'vJpAI:wG' pӢ@%n=,6^c1D3+zzmnibnvIkEݡyZ؍kRSb&NS-Yb6:g$D*FFMr)Xf; C*B$$O+ҋP*1W)͋qC+D0܆pCq{6Vޘz̺-I|0>iX L-+`D)g3ȶl߿QAXx #d: S eE}ȼ̯qq&#y;7`5^rXf\?샲($jT]pV_Q.u6'4I`'Pn!nyȞ4/g;,IFx@Z߇"iV jdklK_wNc`G]{ ]U*Z-8b"U k]cGOz}̤Z@-̈́d62R!ok!6(r1ջBظ/G 3GցC%yrlnio<ӳW'8(n(|Ӥyic17 A%l[! *oJLh +}2z)}:(ze7ńsŴۨf'Ҍ/'FEs]lo]!NQ-6`#>m(D#c C ϻ3\Tkͥe>a)ŞKwhzuBi,{5P+8;sTZڌ-%g&UIh._|eٻye4gwZr]u8ޠ3fyM\XWvI%@yq7P ,ThLi_!ʔֈEm^ d2=vɹqR L42aS+ ; .lgy֫0Z\^9zUd*l)ez io!KpYP6U\@\&+yi,b'v%mRa}XQmiAI$@/ҭ3 KdMK _x =8iSvT>m_CHUWVG x;IӚ]Xդanb3V }5 1Bcvq^]oE,;ܹ%AYΕ$E1n Tup(jjaDU4NHS#-9;(jb]*nU9J [ zjYBޝQ}r^rub#$۪ML㡀gQǐCZ\1!y6yi]6Ͳ3`cڑ#,b] t{x}msF|>!. ϫDfMIb;?DQ UhP;)m]j)?6!0 R* =p?2+%4RO)n̫@u5XPn xFqf56.z=i{ =7`F(8 }ƒQY=9C>Fڳv u\=+ɵGF+WR֖$ĵe@A(̏/(J1F&3Pђ/MDAЌQIgQE\-~l(r'2VP#ۑR|C?~'9T~ӟ,%F.&GI/۟b ҝG2y_&@1X%*u0u^ghTJ;i& W8{d33m?bcxnϠǒ50#sBNקq;W$)F-)KDJǘh$(" JÌ{SzK̩0ӄ{E7#G븶:P3i|MG z)h /nSEץ!NuvN9Z`]b}2`VjISvȔJW2{]LX0W(pG..ɹeD4B-=h*` v% p8X:Q(]<[zTJ~%:=kw:΀#fEHS*3zY!ԟ|_@h*rC]y*_Y#@D,TVn8|-DCBW2bݿS C}ij~SGA֞{ٰQc2~ߑ?"` \׋j؁quDl|[GDեA/S;^RiQȅQX6-8jDU*XRx"6 u6= FѵnTBRGxkRN wwH2[ OSO,vjx̩[!i $218WnH_6ů%c@U." r^#8@Fm\u}1}kTck"@,opmOJ412ySE€WHzuK;ڨvR[!+3Hu\k/™L@nJjF&R7~7g5T '+x85@1(if9lRjfaC7E\>'!umԙ4()L2;@qm)&v |?JƐ{ 0=UT;&hej2Q)Q \lzE\}MͲzU:xܩ'm)]iSQhLɫ}J7T>z\xT:U2D0i{nqO^2s^ѿ^}z!竾ܿ/:ӫ`}?^?dO=Bv)fOZKu Q_ @c:"i;&Ń3ju~xz Yko܋iNbouJ0T<.YIGr_{R"[I['DeGweI ؆8mcH TZÛb6lE'O a`{EdN;/E˨`iؼM<ѰW\`3AI 式Zbk־W8ִx(-;`E$%%<"; LPwt/a~aEf~[z_|"}Xnd FGj tuB&_7alɢQFAwޓPsG]h7"ִ4I=յO=յs &۪}o݌a|^T%DU=ĶM &y[>(U1,[?n $_p ?hj(osj0/d<J>v+]m}E@UbFk,ŜL+[)()Iλ$]O҆!uΨ$tVav4m:HtD@jO_'`i1)#B厷:8z<~Ջާ5QJCiRFϵ1>$<)5e,d'@4gŬzbi>wM!'Y$-i4#1.$<"خHW`OnJUd<Ҥc*´P(Y>;zRХFs(+6-DrF)^*D9̽h 9EK_gTouL7aO ߏ`!$lH%5EEpVLT t.*M! Kޓd&V`b E}D #ژ#jX ~cTN#.[EޞK.N0'eᙿu%s]@V|։׻{tf0$/|-aTgitv c#fRUvkW}:o xDovrnLPdD=#rF} +/׆pFcA{}Ŏg']R˽>v@7EXQQ?Ǎ2y>mɮ꟏ak_lx=~l$[d0cykjFۨ@L.@xQ;dE~\e5'oc~Z9 *m`Wejcly)DV]^r{-08te9p6)j)'L8N?̞Y,uGlllg`76U2.-p iS<?QfFdpjp(- WnL "B5:PO`fQ0Ey3j+aU.-"2?-eJ Fz?8qG&R3"[ y&GSO|R=|Zk|zq&L(܌ls#+D"̸KAѢqMPҩiZ>[Vl1"(>sU$szTפ##`OT6q ]&ȠQ-`L:ƕ,ѧعiCn[h=e"qGĕ 2'_7M=_a̝\рQ~==lً<{Xld{ %9>ek_VIe1,)ͭ0xzW0z^)Zwӗ'Fũ3^_x0p+;ѯð-DtA),s}F=z9-*JOP֢i5&9FUEDRFN);1} wwΤ߸)oc3U\P⎣CuQu%-(Q&tǵ;u_3v r:RUu5=n#R 9a )֎hexuAVf=- +ۯ/l}-;PJ 5D{j 7ЈPeOz൱YVg-f,e_1I94.:Eu9޻H ZTBMTu}e?[Da,^\e3 eF$hqóqW3ˍX0~~Җ*Q|P04 袸UY!\'.%J|0Vs/H&J?PrP>Xru1$qtl!vD2i}-~"$NBqÚRpͰR]\UfLD .XI'SF:ҧG"[|@6ylWJc(U٥)k6\zU|HYpIbCK"T(-A3w ӯ(٬- T{m6!;A}ki8AG k*"hޡnV3 dZC@ (xUVK,;Fy=U+| l7_C`E8yyF'Urv@pcxK_:@/RdIJ,=gCGG|Cs,ŕ6$ٮXdYVHO]r"y"1dX&,lSv <jwzjة^JؼHYtuGjSl*LE89C-lViX ==P+渒Cw:goXq ]rBELNE%4Nƙ0cw?]c&ICG6C-fcJFf(v- /753JA`Vt6=9 ~%ڊ8=V]G+7"#Pڙ8&,m3ȏs٤u 㞾ch\lLwpEK1@ڔԆ륭A!\6IR'Sg_ !^S4EAzB>{E B3+Gf'ۯ Z+D9[= ,,vCϢdķ!)%XLqɃ#j 08ΒT@d%gr;+IS6S![ʵ5[cvzl:UzKsɝ_w`"GNmМ ϼuJ V hVL+eqzd]UIe&vwF Xb:b}|L QN2[#9qeNGY=1l] ÜPE==d AX WIQHfBVZ͙0.nĵ9xNAz|όPSRsnq7wqEr+_#k }z%HYv&F[s{snW/ L%:FLrߔZHY1ĚX7θ6aL@0"B2M,#tZbYR֊TJ1F`PؓaG̳Q&W/CH~y{~WO0 VXw^.p2KMR6L ?8d FRuz[OEݾAjO;ؼ7Qi~0<%S6cƲFS)EWӦ4AƎd vMkeW7{bO]BC@/ 3:q%s^ Kj! Gh&#y I>tXxޑL7EeyDwPF VP1 l-L +RI\WZL;݃4O AyUfx>3(&78*6[gM.ݓ2TV2NDP/?`p+u*nlʰتZ|bk&\;5$ӂWH򎣭r%) V)LϾ*#xR) 7uU(sA0L+Scb]*epՂ|O cP銾\ 㹷TvѣaFŬۋlDFѸĔ!8ITŬf[L”EJ}領4Z"߬K%rՎ 6e-±MfCķ?-z,GgڑqM<.ĭXO^Hfqj{WXuD7:DݙZx5W !K=ID0nyhx.$.]IZNXOŲ 6y0gQ8Gx@@7зX Kf @B= 7 gԙh@ _z-+ ÆR+ P k0cn D$JwCʩ\pzZo'+*1lͷF\ uw;ߠ"~ޛب͔8I덊/mS̜(wLy1nu/p|W f񫝲j/#%OW$(A}dp5?ܿFM׷&['fMlNLFJ,_[VOr7Q V#k- +F RY/@YscY:5GP}q&۬sNҩc5oў`L鄫W<V橇[oWj' o?ߡ-"?^`r}J#(T :K5Q#͵SVϱh,(DzR~jE|eŵVޕ/g7J}e$7ʨYNutpϭSY:W=m"  ! iWC| 9t9XS_ݹ\pM-A8t h}CjRu>n]7iKz\Ȗi"Ҫfgd7Lݨt\~:;9O)  &kgn?jh~7kOjdjճXCyĨT&qS7-n!2۞؞C+F6-`bݐ3HJ.Âh*}c-S;6.~zT)X xÃ5 IY,>R:Tw]R㬮(?-옑' ԙ.lPlI|u)8[`UKsTv[2'ko4U]O|[GHC %^'W@Z-Z}cc$bal:HG隧݋R qZx*ة:foY{(O(h֤g!O캠-B$@& H&zt'nO)AC̮ *Ub4E!vy" Ҩo&UB_w=Dfn_"]\  +0S#Լ&:1&%`?xK]#8ă z# ګ`NYcRAg{[2+O sAEn涬h,V_ xKD$p:L!<0j&͐xl磐h_ Xi^-jnC'\qR6,|@/Kz4%7^-hQ}z5# WhIN稐h bV'b)\P H=%GD}PXa!9yN(0IȎZҼ Qp;b% cD.8]pfLOUqRpy:hwNF]ɋ6⬘><07wydzYG cqoyJ}E=fҪO S@}7ʭcb~l&T^jTZ^ՖZbX@AP7Z.MV#7Qek+a5v2}TaВj~"T5iXXɖ&JI1' _7P IE11hE'[0.7}QY@$0Nmzyf=w!SeH͘J#bhs-#UvHA]3{ImE֙etL)]ilA (^*;j$ډ͸ GWm(mąqCTʁlq C_G ]Lwycܵ+lx zk$1~֚Pٯd|Ex8$FUvJcN* vs} \mp;% PH { (|WaVm| Ӊ8ՏUF|HKl}e,Ct&n<$y|%FD0+EJ~unIߪ nvּ6!/B~Ƨ0ZX>;4q'@6 9=:? (GBslCQ} J2+lz7SDZȉB[_uG5X9ws5z?N wՃUlYmA՗[J>BʱʈF}N<&lJPZ%2ȷ[<;xIᦔHJoJ_5x.ȟK3R{`'67)d UQ)կv.Daṫ{NhC'jpkA4Y+1-O@+g: T,5,T6*5l*DKgs+mwz Dd=R$HwƥF7or>ߙPBIѮB3Ce^ b{tsWļ;Xϣ5 yqS)9åܭ-E2J&Z̄;E`tч| };~©)V~6R17wR :Rٔa~y?edtIצpoϦ=jc+g^bHHڇ̺;G3V'j}OúK4#Wh$ds;5#9AUD,IFnYy>/nM6;t -!ү:76~q۬逞hۂ]X֛@ǹⶤ@\,D2ȅFz7 ܒ4hYQ:zw.aŵ1F1c="9oAtnal!_L0v~6P~pbbnEv}∡Uv˱Se ?,z잣Q}L3~%"JhT(ُOBny { >sΖ-n"{n"rW$6Eg2LF}l7bӐtʊlxuKL* cF8 {ZF[%^ Z<9#5lrty'`6NŔ-k忉ѫcꕌlF=ϓ țݦN jP+gh\.]_1 _;$f߯[O"Ͽt*NV!Bg @#`oj8.DHN.uj(DA;s"D^Yv-4:IG3'Jo4+"ivpVq"mUOye#nYұ͊=mMxUM?Y*bb#(Oe^ƭcl_eg$c s3U=^I eF΋+J.d NhV<)!49| 2ox#AaJJiwCB6)2Ph MPL,P&]#x,@\-+#'NcdUy^JF{L^WHC ZJш*W㍰rǧ;ZFQyҢ:{udK)%@; Q/]oTt(89;kωTZϏ /9Vਏ$:7w:{N~M#D7 _wB aK :D]?IM ~%O#R r:D@7qc&T#tG4ͫmoJ h@x y;zuge(̷s W?pǯqI[]fntm"u Fm86a4[̾Aݝ7rj| lTTyWĩM1Pwx {~i4ȄP?%풰 e}tErBc&9ăX^yT,p*lj)x`>-9O+Ƨ!+^ hef30}Z*.Y;Nn_OSʹ4V֊2OPM1 ӛ#v WUޣU4U:'4J]cS;Qiw+V\cbΗWѤxx "L>L@"xSmi{fOx%Aebɢ>!=gW3E ۯ1Vޘτ-!%C:@ ,|1;0)Sn!\89ew !E`Jn{Ϯwz#C瑧 nMu2ݯv4C "˧15xdD!Γv:cN(g]Gdu:O @-t:(l7/9ap+FNܩI7ʳu>|_ݯ6ͧY5H+W` Q`+# ʪ*ŵOsRԄ5"خ X(|?FQ+ cjjj34 (DoQug/=R]-(/{,OC_j[Yʿ_=/,@pF6mS4N>G5)BRA<5O.,hE !1wg}}YU{bxwKk硁h+$l﷏~@ى-5b\J5!b(F?zA2Y[KѸсep2MU) zh$D]9`ȍ;I(Iut0l*he<$q(-%;Z$V%x2AkUJ_翩ފU|f9Hm`A2nyl!jhbs$Sq+Z*e'[5ږ)۱ѿ#,)ڝP]lr7dqhg=l4 K$|w=6inNw]z܉Xޖ%J y9 &$}H>F߁>B%xbT+.N@" phW!DwDm9nI('Q_:̿Vc ?W4*HE)̷R]2nATԠ"A}T"ꯑ!3Y%VWoh@s FVNS+p"iZ*}&fn3ɒBo+USb@ʻuaę`;Ֆ#F{o##s-N=4 `8|I!IM{*'\s*8B'󆙷D=gi:J6؄HrcCK%PH ѥ>>AӸ6j]YЛS/X̶U$s3CvB\lz}J`&Yxҏj92ZqN(v0UYt$H<{ϥUҊ9OWkEQ6Ipr-CVՙ;O 3 oVUȆ2Ph-pTE9t)j[+ =mņ#%X/Secī3XpFng"$6D^|XibԧHiHV%k4nUql^JBWQ_)5Q es]n/Qh黒~t=)EzGhlqK0 I &ofډW5 $-S|aOh%͵ * ?Lt`4,'8V$>|(VydLOeP L u1~!x 8q@HodSw#L<2V)AwuVhB>;KqtDT}ğw5q^2m?Z?a*,2Z kHIlg;iwD'_3n尨*%l!!7&eW A3IG\^wCw\@Z]P|;?UjR89Qȸ R=Grvep0'3JSe ׂ>"mK5ȌC|kvGcfP\J,?>rR:ȭ+Lc mg u."YJ=Fޫ)Ǚ%y+IJɅ)8쐡6pU{~|V1@N83(q~wG/wzʘTJ.|wuμ/G5G_OfD8#yS )x''"Tbp:Jb0`-\na9)yf4Z5X%^@A9Nc-7ѩOB*ii'T rUR {"ʑ*_#xc=XopE;rIU{zce~Ldi|68$4V tN o+Lh$%6_lգ3W _h5rqj M!+4))ݽJ3 ,g_,'L B\Y=O :B 7OZЌ+|b=Eѻ w[5Bou.6r{(!73kh Ɓ&N&To<`#m md:./nB\^ %κ?D;ߘ| Ow4b{gneKѰ{!+$e<7V\xHl/ejKQXr$WZbbmlt؊ftKi1'pRSt:|G[ĸڐVQ'g тbJ4^f` ctu/$j/Y]C詈Q.Ke)4kWhI,K#H:ԈLћнDa{(dF7%*B~߷&seTWtp gR_`n 9JOz} *5JYD4o1^{ NqQF,EACtnK%_PS^z[RXٍYK,D}9tqF2¿;RZYSW7}:Kơkob$Q @/q#Jd$/޶3j>*r'Z{1G$.5Kb&, GE,t,-gIzi˘^B0#3`OQ7|ɾcMRlbYI5NʆT}5rOvBQ_0C0 H Z)Q&Bh}Ԙ: _F͜$(PLEӮC4b9H2拝yƫ@i It|qbQB) r+|mrb $+k3@%i}<]bȽp-rZOUp H 7b8ApB:$ȞO<mj{U=P잌ENL߾#֬G K67 >Hz@Kgn;U +r) -jP]Gfj;%"(Vi:;^BMw"} and \code{">="}.} \item{object}{For \code{supportedFilters}: an \code{EnsDb} object.} \item{...}{For \code{supportedFilters}: currently not used.} \item{x}{For \code{seqnames}, \code{seqlevels}: a \code{GRangesFilter} object.} } \value{ For \code{ProtDomIdFilter}: A \code{ProtDomIdFilter} object. For \code{UniprotDbFilter}: A \code{UniprotDbFilter} object. For \code{UniprotMappingTypeFilter}: A \code{UniprotMappingTypeFilter} object. For \code{TxSupportLevel}: A \code{TxSupportLevel} object. For \code{supportedFilters}: a \code{data.frame} with the names and the corresponding field of the supported filter classes. } \description{ \code{ensembldb} supports most of the filters from the \code{\link{AnnotationFilter}} package to retrieve specific content from \code{\linkS4class{EnsDb}} databases. These filters can be passed to the methods such as \code{\link{genes}} with the \code{filter} parameter or can be added as a \emph{global} filter to an \code{EnsDb} object (see \code{\link{addFilter}} for more details). Use the \code{\link{supportedFilters}} to list all filters supported for \code{EnsDb} object. \code{supportedFilters} returns a \code{data.frame} with the names of all filters and the corresponding field supported by the \code{EnsDb} object. \code{seqnames}: accessor for the sequence names of the \code{GRanges} object within a \code{GRangesFilter} \code{seqnames}: accessor for the \code{seqlevels} of the \code{GRanges} object within a \code{GRangesFilter} } \details{ \code{ensembldb} supports the following filters from the \code{AnnotationFilter} package: \describe{ \item{GeneIdFilter}{ filter based on the Ensembl gene ID. } \item{GenenameFilter}{ filter based on the name of the gene as provided by Ensembl. In most cases this will correspond to the official gene symbol. } \item{SymbolFilter}{ filter based on the gene names. \code{\linkS4class{EnsDb}} objects don't have a dedicated \emph{symbol} column, the filtering is hence based on the gene names. } \item{GeneBiotype}{ filter based on the biotype of genes (e.g. \code{"protein_coding"}). } \item{GeneStartFilter}{ filter based on the genomic start coordinate of genes. } \item{GeneEndFilter}{ filter based on the genomic end coordinate of genes. } \item{EntrezidFilter}{ filter based on the genes' NCBI Entrezgene ID. } \item{TxIdFilter}{ filter based on the Ensembld transcript ID. } \item{TxNameFilter}{ filter based on the Ensembld transcript ID; no transcript names are provided in \code{\linkS4class{EnsDb}} databases. } \item{TxBiotypeFilter}{ filter based on the transcripts' biotype. } \item{TxStartFilter}{ filter based on the genomic start coordinate of the transcripts. } \item{TxEndFilter}{ filter based on the genonic end coordinates of the transcripts. } \item{ExonIdFilter}{ filter based on Ensembl exon IDs. } \item{ExonRankFilter}{ filter based on the index/rank of the exon within the transcrips. } \item{ExonStartFilter}{ filter based on the genomic start coordinates of the exons. } \item{ExonEndFilter}{ filter based on the genomic end coordinates of the exons. } \item{GRangesFilter}{ Allows to fetch features within or overlapping specified genomic region(s)/ range(s). This filter takes a \code{\link[GenomicRanges]{GRanges}} object as input and, if \code{type = "any"} (the default) will restrict results to features (genes, transcripts or exons) that are partially overlapping the region. Alternatively, by specifying \code{condition = "within"} it will return features located within the range. In addition, the \code{\link[AnnotationFilter]{GRangesFilter}} supports \code{condition = "start"}, \code{condition = "end"} and \code{condition = "equal"} filtering for features with the same start or end coordinate or that are equal to the \code{GRanges}. Note that the type of feature on which the filter is applied depends on the method that is called, i.e. \code{\link{genes}} will filter on the genomic coordinates of genes, \code{\link{transcripts}} on those of transcripts and \code{\link{exons}} on exon coordinates. Calls to the methods \code{\link{exonsBy}}, \code{\link{cdsBy}} and \code{\link{transcriptsBy}} use the start and end coordinates of the feature type specified with argument \code{by} (i.e. \code{"gene"}, \code{"transcript"} or \code{"exon"}) for the filtering. If the specified \code{GRanges} object defines multiple regions, all features within (or overlapping) any of these regions are returned. Chromosome names/seqnames can be provided in UCSC format (e.g. \code{"chrX"}) or Ensembl format (e.g. \code{"X"}); see \code{\link{seqlevelsStyle}} for more information. } \item{SeqNameFilter}{ filter based on chromosome names. } \item{SeqStrandFilter}{ filter based on the chromosome strand. The strand can be specified with \code{value = "+"}, \code{value = "-"}, \code{value = -1} or \code{value = 1}. } \item{ProteinIdFilter}{ filter based on Ensembl protein IDs. This filter is only supported if the \code{\linkS4class{EnsDb}} provides protein annotations; use the \code{\link{hasProteinData}} method to evaluate. } \item{UniprotFilter}{ filter based on Uniprot IDs. This filter is only supported if the \code{\linkS4class{EnsDb}} provides protein annotations; use the \code{\link{hasProteinData}} method to evaluate. } } In addition, the following filters are defined by \code{ensembldb}: \describe{ \item{TxSupportLevel}{ allows to filter results using the provided transcript support level. Support levels for transcripts are defined by Ensembl based on the available evidences for a transcript with 1 being the highest evidence grade and 5 the lowest level. This filter is only supported on \code{EnsDb} databases with a db schema version higher 2.1. } \item{UniprotDbFilter}{ allows to filter results based on the specified Uniprot database name(s). } \item{UniprotMappingTypeFilter}{ allows to filter results based on the mapping method/type that was used to assign Uniprot IDs to Ensembl protein IDs. } \item{ProtDomIdFilter}{ allows to retrieve entries from the database matching the provided filter criteria based on their protein domain ID (\emph{protein_domain_id}). } \item{OnlyCodingTxFilter}{ allows to retrieve entries only for protein coding transcripts, i.e. transcripts with a CDS. This filter does not take any input arguments. } } } \note{ For users of \code{ensembldb} version < 2.0: in the \code{\link[AnnotationFilter]{GRangesFilter}} from the \code{AnnotationFilter} package the \code{condition} parameter was renamed to \code{type} (to be consistent with the \code{IRanges} package) . In addition, the \code{condition = "overlapping"} is no longer recognized. To retrieve all features overlapping the range \code{type = "any"} has to be used. Protein annotation based filters can only be used if the \code{\linkS4class{EnsDb}} database contains protein annotations, i.e. if \code{\link{hasProteinData}} is \code{TRUE}. Also, only protein coding transcripts will have protein annotations available, thus, non-coding transcripts/genes will not be returned by the queries using protein annotation filters. } \examples{ ## Create a filter that could be used to retrieve all informations for ## the respective gene. gif <- GeneIdFilter("ENSG00000012817") gif ## Create a filter for a chromosomal end position of a gene sef <- GeneEndFilter(10000, condition = ">") sef ## For additional examples see the help page of "genes". ## Example for GRangesFilter: ## retrieve all genes overlapping the specified region grf <- GRangesFilter(GRanges("11", ranges = IRanges(114000000, 114000050), strand = "+"), type = "any") library(EnsDb.Hsapiens.v75) edb <- EnsDb.Hsapiens.v75 genes(edb, filter = grf) ## Get also all transcripts overlapping that region. transcripts(edb, filter = grf) ## Retrieve all transcripts for the above gene gn <- genes(edb, filter = grf) txs <- transcripts(edb, filter = GenenameFilter(gn$gene_name)) ## Next we simply plot their start and end coordinates. plot(3, 3, pch=NA, xlim=c(start(gn), end(gn)), ylim=c(0, length(txs)), yaxt="n", ylab="") ## Highlight the GRangesFilter region rect(xleft=start(grf), xright=end(grf), ybottom=0, ytop=length(txs), col="red", border="red") for(i in 1:length(txs)){ current <- txs[i] rect(xleft=start(current), xright=end(current), ybottom=i-0.975, ytop=i-0.125, border="grey") text(start(current), y=i-0.5,pos=4, cex=0.75, labels=current$tx_id) } ## Thus, we can see that only 4 transcripts of that gene are indeed ## overlapping the region. ## No exon is overlapping that region, thus we're not getting anything exons(edb, filter = grf) ## Example for ExonRankFilter ## Extract all exons 1 and (if present) 2 for all genes encoded on the ## Y chromosome exons(edb, columns = c("tx_id", "exon_idx"), filter=list(SeqNameFilter("Y"), ExonRankFilter(3, condition = "<"))) ## Get all transcripts for the gene SKA2 transcripts(edb, filter = GenenameFilter("SKA2")) ## Which is the same as using a SymbolFilter transcripts(edb, filter = SymbolFilter("SKA2")) ## Create a ProteinIdFilter: pf <- ProteinIdFilter("ENSP00000362111") pf ## Using this filter would retrieve all database entries that are associated ## with a protein with the ID "ENSP00000362111" if (hasProteinData(edb)) { res <- genes(edb, filter = pf) res } ## UniprotFilter: uf <- UniprotFilter("O60762") ## Get the transcripts encoding that protein: if (hasProteinData(edb)) { transcripts(edb, filter = uf) ## The mapping Ensembl protein ID to Uniprot ID can however be 1:n: transcripts(edb, filter = TxIdFilter("ENST00000371588"), columns = c("protein_id", "uniprot_id")) } ## ProtDomIdFilter: pdf <- ProtDomIdFilter("PF00335") ## Also here we could get all transcripts related to that protein domain if (hasProteinData(edb)) { transcripts(edb, filter = pdf, columns = "protein_id") } } \seealso{ \code{\link{supportedFilters}} to list all filters supported for \code{EnsDb} objects. \code{\link{listUniprotDbs}} and \code{\link{listUniprotMappingTypes}} to list all Uniprot database names respectively mapping method types from the database. \code{\link[AnnotationFilter]{GeneIdFilter}} for more details on the filter objects. \code{\link{genes}}, \code{\link{transcripts}}, \code{\link{exons}}, \code{\link{listGenebiotypes}}, \code{\link{listTxbiotypes}}. \code{\link{addFilter}} for globally adding filters to an \code{EnsDb} object. } \author{ Johannes Rainer } ensembldb/man/ProteinFunctionality.Rd0000644000175400017540000001017613175714743021007 0ustar00biocbuildbiocbuild% Generated by roxygen2: do not edit by hand % Please edit documentation in R/functions-utils.R, R/Methods.R \docType{methods} \name{listProteinColumns} \alias{listProteinColumns} \alias{proteins,EnsDb-method} \alias{proteins} \alias{listUniprotDbs,EnsDb-method} \alias{listUniprotDbs} \alias{listUniprotMappingTypes,EnsDb-method} \alias{listUniprotMappingTypes} \title{Protein related functionality} \usage{ listProteinColumns(object) \S4method{proteins}{EnsDb}(object, columns = listColumns(object, "protein"), filter = AnnotationFilterList(), order.by = "", order.type = "asc", return.type = "DataFrame") \S4method{listUniprotDbs}{EnsDb}(object) \S4method{listUniprotMappingTypes}{EnsDb}(object) } \arguments{ \item{object}{The \code{\linkS4class{EnsDb}} object.} \item{columns}{For \code{proteins}: character vector defining the columns to be extracted from the database. Can be any column(s) listed by the \code{\link{listColumns}} method.} \item{filter}{For \code{proteins}: A filter object extending \code{AnnotationFilter} or a list of such objects to select specific entries from the database. See \code{\link{Filter-classes}} for a documentation of available filters and use \code{\link{supportedFilters}} to get the full list of supported filters.} \item{order.by}{For \code{proteins}: a character vector specifying the column(s) by which the result should be ordered.} \item{order.type}{For \code{proteins}: if the results should be ordered ascending (\code{order.type = "asc"}) or descending (\code{order.type = "desc"})} \item{return.type}{For \code{proteins}: character of lenght one specifying the type of the returned object. Can be either \code{"DataFrame"}, \code{"data.frame"} or \code{"AAStringSet"}.} } \value{ The \code{listProteinColumns} function returns a character vector with the column names containing protein annotations or throws an error if no such annotations are available. The \code{proteins} method returns protein related annotations from an \code{\linkS4class{EnsDb}} object with its \code{return.type} argument allowing to define the type of the returned object. Note that if \code{return.type = "AAStringSet"} additional annotation columns are stored in a \code{DataFrame} that can be accessed with the \code{mcols} method on the returned object. } \description{ The \code{listProteinColumns} function allows to conveniently extract all database columns containing protein annotations from an \code{\linkS4class{EnsDb}} database. This help page provides information about most of the functionality related to protein annotations in \code{ensembldb}. The \code{proteins} method retrieves protein related annotations from an \code{\linkS4class{EnsDb}} database. The \code{listUniprotDbs} method lists all Uniprot database names in the \code{EnsDb}. The \code{listUniprotMappingTypes} method lists all methods that were used for the mapping of Uniprot IDs to Ensembl protein IDs. } \details{ The \code{proteins} method performs the query starting from the \code{protein} tables and can hence return all annotations from the database that are related to proteins and transcripts encoding these proteins from the database. Since \code{proteins} does thus only query annotations for protein coding transcripts, the \code{\link{genes}} or \code{\link{transcripts}} methods have to be used to retrieve annotations for non-coding transcripts. } \examples{ ## List all columns containing protein annotations library(EnsDb.Hsapiens.v75) edb <- EnsDb.Hsapiens.v75 if (hasProteinData(edb)) listProteinColumns(edb) library(ensembldb) library(EnsDb.Hsapiens.v75) edb <- EnsDb.Hsapiens.v75 ## Get all proteins from tha database for the gene ZBTB16, if protein ## annotations are available if (hasProteinData(edb)) proteins(edb, filter = GenenameFilter("ZBTB16")) ## List the names of all Uniprot databases from which Uniprot IDs are ## available in the EnsDb if (hasProteinData(edb)) listUniprotDbs(edb) ## List the type of all methods that were used to map Uniprot IDs to Ensembl ## protein IDs if (hasProteinData(edb)) listUniprotMappingTypes(edb) } \author{ Johannes Rainer } ensembldb/man/convertFilter.Rd0000644000175400017540000000364613175714743017450 0ustar00biocbuildbiocbuild% Generated by roxygen2: do not edit by hand % Please edit documentation in R/Methods-Filter.R \docType{methods} \name{convertFilter,AnnotationFilter,EnsDb-method} \alias{convertFilter,AnnotationFilter,EnsDb-method} \alias{convertFilter,AnnotationFilterList,EnsDb-method} \alias{convertFilter,AnnotationFilterList,EnsDb-method} \title{Convert an AnnotationFilter to a SQL WHERE condition for EnsDb} \usage{ \S4method{convertFilter}{AnnotationFilter,EnsDb}(object, db, with.tables = character()) \S4method{convertFilter}{AnnotationFilterList,EnsDb}(object, db, with.tables = character()) } \arguments{ \item{object}{\code{AnnotationFilter} or \code{AnnotationFilterList} objects (or objects extending these classes).} \item{db}{\code{EnsDb} object.} \item{with.tables}{optional \code{character} vector specifying the names of the database tables that are being queried.} } \value{ A \code{character(1)} with the SQL where condition. } \description{ \code{convertFilter} converts an \code{AnnotationFilter::AnnotationFilter} or \code{AnnotationFilter::AnnotationFilterList} to an SQL where condition for an \code{EnsDb} database. } \note{ This function \emph{might} be used in direct SQL queries on the SQLite database underlying an \code{EnsDb} but is more thought to illustrate the use of \code{AnnotationFilter} objects in combination with SQL databases. This method is used internally to create the SQL calls to the database. } \examples{ library(EnsDb.Hsapiens.v75) edb <- EnsDb.Hsapiens.v75 ## Define a filter flt <- AnnotationFilter(~ genename == "BCL2") ## Use the method from the AnnotationFilter package: convertFilter(flt) ## Create a combination of filters flt_list <- AnnotationFilter(~ genename \%in\% c("BCL2", "BCL2L11") & tx_biotype == "protein_coding") flt_list convertFilter(flt_list) ## Use the filters in the context of an EnsDb database: convertFilter(flt, edb) convertFilter(flt_list, edb) } \author{ Johannes Rainer } ensembldb/man/global-filters.Rd0000644000175400017540000000525413175714743017525 0ustar00biocbuildbiocbuild% Generated by roxygen2: do not edit by hand % Please edit documentation in R/Methods.R, R/functions-EnsDb.R \docType{methods} \name{addFilter,EnsDb-method} \alias{addFilter,EnsDb-method} \alias{addFilter} \alias{dropFilter,EnsDb-method} \alias{dropFilter} \alias{activeFilter,EnsDb-method} \alias{activeFilter} \alias{filter} \title{Globally add filters to an EnsDb database} \usage{ \S4method{addFilter}{EnsDb}(x, filter = AnnotationFilterList()) \S4method{dropFilter}{EnsDb}(x) \S4method{activeFilter}{EnsDb}(x) filter(x, filter = AnnotationFilterList()) } \arguments{ \item{x}{The \code{\linkS4class{EnsDb}} object to which the filter should be added.} \item{filter}{The filter as an \code{\link[AnnotationFilter]{AnnotationFilter}}, \code{\link[AnnotationFilter]{AnnotationFilterList}} or filter expression. See} } \value{ \code{addFilter} and \code{filter} return an \code{EnsDb} object with the specified filter added. \code{activeFilter} returns an \code{\link[AnnotationFilter]{AnnotationFilterList}} object being the active global filter or \code{NA} if no filter was added. \code{dropFilter} returns an \code{EnsDb} object with all eventually present global filters removed. } \description{ These methods allow to set, delete or show globally defined filters on an \code{\linkS4class{EnsDb}} object. \code{addFilter}: adds an annotation filter to the \code{EnsDb} object. \code{dropFilter} deletes all globally set filters from the \code{EnsDb} object. \code{activeFilter} returns the globally set filter from an \code{EnsDb} object. \code{filter} filters an \code{EnsDb} object. \code{filter} is an alias for the \code{addFilter} function. } \details{ Adding a filter to an \code{EnsDb} object causes this filter to be permanently active. The filter will be used for all queries to the database and is added to all additional filters passed to the methods such as \code{\link{genes}}. } \examples{ library(EnsDb.Hsapiens.v75) edb <- EnsDb.Hsapiens.v75 ## Add a global SeqNameFilter to the database such that all subsequent ## queries will be applied on the filtered database. edb_y <- addFilter(edb, SeqNameFilter("Y")) ## Note: using the filter function is equivalent to a call to addFilter. ## Each call returns now only features encoded on chromosome Y gns <- genes(edb_y) seqlevels(gns) ## Get all lincRNA gene transcripts on chromosome Y transcripts(edb_y, filter = ~ gene_biotype == "lincRNA") ## Get the currently active global filter: activeFilter(edb_y) ## Delete this filter again. edb_y <- dropFilter(edb_y) activeFilter(edb_y) } \seealso{ \code{\link{Filter-classes}} for a list of all supported filters. } \author{ Johannes Rainer } ensembldb/man/hasProteinData-EnsDb-method.Rd0000644000175400017540000000143113175714743021765 0ustar00biocbuildbiocbuild% Generated by roxygen2: do not edit by hand % Please edit documentation in R/Methods.R \docType{methods} \name{hasProteinData,EnsDb-method} \alias{hasProteinData,EnsDb-method} \alias{hasProteinData} \title{Determine whether protein data is available in the database} \usage{ \S4method{hasProteinData}{EnsDb}(x) } \arguments{ \item{x}{The \code{\linkS4class{EnsDb}} object.} } \value{ A logical of length one, \code{TRUE} if protein annotations are available and \code{FALSE} otherwise. } \description{ Determines whether the \code{\linkS4class{EnsDb}} provides protein annotation data. } \examples{ library(EnsDb.Hsapiens.v75) ## Does this database/package have protein annotations? hasProteinData(EnsDb.Hsapiens.v75) } \seealso{ \code{\link{listTables}} } \author{ Johannes Rainer } ensembldb/man/listEnsDbs.Rd0000644000175400017540000000304613175714743016666 0ustar00biocbuildbiocbuild% Generated by roxygen2: do not edit by hand % Please edit documentation in R/dbhelpers.R \name{listEnsDbs} \alias{listEnsDbs} \title{List EnsDb databases in a MySQL server} \usage{ listEnsDbs(dbcon, host, port, user, pass) } \arguments{ \item{dbcon}{A \code{DBIConnection} object providing access to a MySQL database. Either \code{dbcon} or all of the other arguments have to be specified.} \item{host}{Character specifying the host on which the MySQL server is running.} \item{port}{The port of the MySQL server (usually \code{3306}).} \item{user}{The username for the MySQL server.} \item{pass}{The password for the MySQL server.} } \value{ A \code{data.frame} listing the database names, organism name and Ensembl version of the EnsDb databases found on the server. } \description{ The \code{listEnsDbs} function lists EnsDb databases in a MySQL server. } \details{ The use of this function requires that the \code{RMySQL} package is installed and that the user has either access to a MySQL server with already installed EnsDb databases, or write access to a MySQL server in which case EnsDb databases could be added with the \code{\link{useMySQL}} method. EnsDb databases follow the same naming conventions than the EnsDb packages, with the exception that the name is all lower case and that \code{"."} is replaced by \code{"_"}. } \examples{ \dontrun{ library(RMySQL) dbcon <- dbConnect(MySQL(), host = "localhost", user = my_user, pass = my_pass) listEnsDbs(dbcon) } } \seealso{ \code{\link{useMySQL}} } \author{ Johannes Rainer } ensembldb/man/makeEnsemblDbPackage.Rd0000644000175400017540000002333213175714743020561 0ustar00biocbuildbiocbuild\name{makeEnsembldbPackage} \alias{ensDbFromAH} \alias{ensDbFromGRanges} \alias{ensDbFromGtf} \alias{ensDbFromGff} \alias{makeEnsembldbPackage} \alias{fetchTablesFromEnsembl} \alias{makeEnsemblSQLiteFromTables} \title{ Generating a Ensembl annotation package from Ensembl } \description{ The functions described on this page allow to build \code{EnsDb} annotation objects/databases from Ensembl annotations. The most complete set of annotations, which include also the NCBI Entrezgene identifiers for each gene, can be retrieved by the functions using the Ensembl Perl API (i.e. functions \code{fetchTablesFromEnsembl}, \code{makeEnsemblSQLiteFromTables}). Alternatively the functions \code{ensDbFromAH}, \code{ensDbFromGRanges}, \code{ensDbFromGff} and \code{ensDbFromGtf} can be used to build \code{EnsDb} objects using GFF or GTF files from Ensembl, which can be either manually downloaded from the Ensembl ftp server, or directly form within R using \code{AnnotationHub}. The generated SQLite database can be packaged into an R package using the \code{makeEnsembldbPackage}. } \usage{ ensDbFromAH(ah, outfile, path, organism, genomeVersion, version) ensDbFromGRanges(x, outfile, path, organism, genomeVersion, version, ...) ensDbFromGff(gff, outfile, path, organism, genomeVersion, version, ...) ensDbFromGtf(gtf, outfile, path, organism, genomeVersion, version, ...) fetchTablesFromEnsembl(version, ensemblapi, user="anonymous", host="ensembldb.ensembl.org", pass="", port=5306, species="human") makeEnsemblSQLiteFromTables(path=".", dbname) makeEnsembldbPackage(ensdb, version, maintainer, author, destDir=".", license="Artistic-2.0") } \arguments{ (in alphabetical order) \item{ah}{ For \code{ensDbFromAH}: an \code{AnnotationHub} object representing a single resource (i.e. GTF file from Ensembl) from \code{AnnotationHub}. } \item{author}{ The author of the package. } \item{dbname}{ The name for the database (optional). By default a name based on the species and Ensembl version will be automatically generated (and returned by the function). } \item{destDir}{ Where the package should be saved to. } \item{ensdb}{ The file name of the SQLite database generated by \code{makeEnsemblSQLiteFromTables}. } \item{ ensemblapi }{ The path to the Ensembl perl API installed locally on the system. The Ensembl perl API version has to fit the version. } \item{genomeVersion}{ For \code{ensDbFromAH}, \code{ensDbFromGtf} and \code{ensDbFromGff}: the version of the genome (e.g. \code{"GRCh37"}). If not provided the function will try to guess it from the file name (assuming file name convention of Ensembl GTF files). } \item{gff}{ The GFF file to import. } \item{gtf}{ The GTF file name. } \item{host}{ The hostname to access the Ensembl database. } \item{license}{ The license of the package. } \item{maintainer}{ The maintainer of the package. } \item{organism}{ For \code{ensDbFromAH}, \code{ensDbFromGff} and \code{ensDbFromGtf}: the organism name (e.g. \code{"Homo_sapiens"}). If not provided the function will try to guess it from the file name (assuming file name convention of Ensembl GTF files). } \item{outfile}{ The desired file name of the SQLite file. If not provided the name of the GTF file will be used. } \item{pass}{ The password for the Ensembl database. } \item{path}{ The directory in which the tables retrieved by \code{fetchTablesFromEnsembl} or the SQLite database file generated by \code{ensDbFromGtf} are stored. } \item{port}{ The port to be used to connect to the Ensembl database. } \item{species}{ The species for which the annotations should be retrieved. } \item{user}{ The username for the Ensembl database. } \item{version}{ For \code{fetchTablesFromEnsembl}, \code{ensDbFromGRanges} and \code{ensDbFromGtf}: the Ensembl version for which the annotation should be retrieved (e.g. 75). The \code{ensDbFromGtf} function will try to guess the Ensembl version from the GTF file name if not provided. For \code{makeEnsemblDbPackage}: the version for the package. } \item{x}{ For \code{ensDbFromGRanges}: the \code{GRanges} object. } \item{...}{ Currently not used. } } \section{Functions}{ \describe{ \item{ensDbFromAH}{ Create an \code{EnsDb} (SQLite) database from a GTF file provided by \code{AnnotationHub}. The function returns the file name of the generated database file. For usage see the examples below. } \item{ensDbFromGff}{ Create an \code{EnsDb} (SQLite) database from a GFF file from Ensembl. The function returns the file name of the generated database file. For usage see the examples below. } \item{ensDbFromGtf}{ Create an \code{EnsDb} (SQLite) database from a GTF file from Ensembl. The function returns the file name of the generated database file. For usage see the examplesbelow. } \item{ensDbFromGRanges}{ Create an \code{EnsDb} (SQLite) database from a GRanges object (e.g. from \code{AnnotationHub}). The function returns the file name of the generated database file. For usage see the examples below. } \item{fetchTablesFromEnsembl}{ Uses the Ensembl Perl API to fetch all required data from an Ensembl database server and stores them locally to text files (that can be used as input for the \code{makeEnsembldbSQLiteFromTables} function). } \item{makeEnsemblSQLiteFromTables}{ Creates the SQLite \code{EnsDb} database from the tables generated by the \code{fetchTablesFromEnsembl}. } \item{makeEnsembldbPackage}{ Creates an R package containing the \code{EnsDb} database from a \code{EnsDb} SQLite database created by any of the above functions \code{ensDbFromAH}, \code{ensDbFromGff}, \code{ensDbFromGtf} or \code{makeEnsemblSQLiteFromTables}. } } } \details{ The \code{fetchTablesFromEnsembl} function internally calls the perl script \code{get_gene_transcript_exon_tables.pl} to retrieve all required information from the Ensembl database using the Ensembl perl API. As an alternative way, a EnsDb database file can be generated by the \code{ensDbFromGtf} or \code{ensDbFromGff} from a GTF or GFF file downloaded from the Ensembl ftp server or using the \code{ensDbFromAH} to build a database directly from corresponding resources from the AnnotationHub. The returned database file name can then be used as an input to the \code{makeEnsembldbPackage} or it can be directly loaded and used by the \code{EnsDb} constructor. } \note{ A local installation of the Ensembl perl API is required for the \code{fetchTablesFromEnsembl}. See \url{http://www.ensembl.org/info/docs/api/api_installation.html} for installation inscructions. A database generated from a GTF/GFF files lacks some features as they are not available in the GTF files from Ensembl. These are: NCBI Entrezgene IDs. } \value{ \code{makeEnsemblSQLiteFromTables}, \code{ensDbFromAH}, \code{ensDbFromGRanges} and \code{ensDbFromGtf}: the name of the SQLite file. } \seealso{ \code{\link{EnsDb}}, \code{\link{genes}} } \author{ Johannes Rainer } \examples{ \dontrun{ ## get all human gene/transcript/exon annotations from Ensembl (75) ## the resulting tables will be stored by default to the current working ## directory; if the correct Ensembl api (version 75) is defined in the ## PERL5LIB environment variable, the ensemblapi parameter can also be omitted. fetchTablesFromEnsembl(75, ensemblapi="/home/bioinfo/ensembl/75/API/ensembl/modules", species="human") ## These tables can then be processed to generate a SQLite database ## containing the annotations DBFile <- makeEnsemblSQLiteFromTables() ## and finally we can generate the package makeEnsembldbPackage(ensdb=DBFile, version="0.0.1", maintainer="Johannes Rainer ", author="J Rainer") ## Build an annotation database form a GFF file from Ensembl. ## ftp://ftp.ensembl.org/pub/release-83/gff3/rattus_norvegicus gff <- "Rattus_norvegicus.Rnor_6.0.83.gff3.gz" DB <- ensDbFromGff(gff=gff) edb <- EnsDb(DB) edb ## Build an annotation file from a GTF file. ## the GTF file can be downloaded from ## ftp://ftp.ensembl.org/pub/release-75/gtf/homo_sapiens/ gtffile <- "Homo_sapiens.GRCh37.75.gtf.gz" ## generate the SQLite database file DB <- ensDbFromGtf(gtf=paste0(ensemblhost, gtffile)) ## load the DB file directly EDB <- EnsDb(DB) ## Alternatively, we could fetch a GTF file directly from AnnotationHub ## and build the database from that: library(AnnotationHub) ah <- AnnotationHub() ## Query for all GTF files from Ensembl for Ensembl version 81 query(ah, c("Ensembl", "release-81", "GTF")) ## We could get the one from e.g. Bos taurus: DB <- ensDbFromAH(ah["AH47941"]) edb <- EnsDb(DB) edb } ## Generate a sqlite database for genes encoded on chromosome Y chrY <- system.file("chrY", package="ensembldb") DBFile <- makeEnsemblSQLiteFromTables(path=chrY ,dbname=tempfile()) ## load this database: edb <- EnsDb(DBFile) edb ## Generate a sqlite database from a GRanges object specifying ## genes encoded on chromosome Y load(system.file("YGRanges.RData", package="ensembldb")) Y DB <- ensDbFromGRanges(Y, path=tempdir(), version=75, organism="Homo_sapiens") edb <- EnsDb(DB) } \keyword{ data } ensembldb/man/runEnsDbApp.Rd0000644000175400017540000000161613175714743016776 0ustar00biocbuildbiocbuild\name{runEnsDbApp} \alias{runEnsDbApp} \title{ Search annotations interactively } \description{ This function starts the interactive \code{EnsDb} shiny web application that allows to look up gene/transcript/exon annotations from an \code{EnsDb} annotation package installed locally. } \usage{ runEnsDbApp(...) } \arguments{ \item{...}{ Additional arguments passed to the \code{\link[shiny]{runApp}} function from the \code{shiny} package. } } \details{ The \code{shiny} based web application allows to look up any annotation available in any of the locally installed \code{EnsDb} annotation packages. } \value{ If the button \emph{Return & close} is clicked, the function returns the results of the present query either as \code{data.frame} or as \code{GRanges} object. } \seealso{ \code{\link{EnsDb}}, \code{\link{genes}} } \author{ Johannes Rainer } \keyword{data} \keyword{shiny} ensembldb/man/useMySQL-EnsDb-method.Rd0000644000175400017540000000333013175714743020541 0ustar00biocbuildbiocbuild% Generated by roxygen2: do not edit by hand % Please edit documentation in R/Methods.R \docType{methods} \name{useMySQL,EnsDb-method} \alias{useMySQL,EnsDb-method} \alias{useMySQL} \title{Use a MySQL backend} \usage{ \S4method{useMySQL}{EnsDb}(x, host = "localhost", port = 3306, user, pass) } \arguments{ \item{x}{The \code{\linkS4class{EnsDb}} object.} \item{host}{Character vector specifying the host on which the MySQL server runs.} \item{port}{The port on which the MySQL server can be accessed.} \item{user}{The user name for the MySQL server.} \item{pass}{The password for the MySQL server.} } \value{ A \code{\linkS4class{EnsDb}} object providing access to the data stored in the MySQL backend. } \description{ Change the SQL backend from \emph{SQLite} to \emph{MySQL}. When first called on an \code{\linkS4class{EnsDb}} object, the function tries to create and save all of the data into a MySQL database. All subsequent calls will connect to the already existing MySQL database. } \details{ This functionality requires that the \code{RMySQL} package is installed and that the user has (write) access to a running MySQL server. If the corresponding database does already exist users without write access can use this functionality. } \note{ At present the function does not evaluate whether the versions between the SQLite and MySQL database differ. } \examples{ ## Load the EnsDb database (SQLite backend). library(EnsDb.Hsapiens.v75) edb <- EnsDb.Hsapiens.v75 ## Now change the backend to MySQL; my_user and my_pass should ## be the user name and password to access the MySQL server. \dontrun{ edb_mysql <- useMySQL(edb, host = "localhost", user = my_user, pass = my_pass) } } \author{ Johannes Rainer } ensembldb/readme.md0000644000175400017540000000211113175714743015321 0ustar00biocbuildbiocbuild

[![Years in Bioconductor](http://www.bioconductor.org/shields/years-in-bioc/ensembldb.svg)](http://www.bioconductor.org/packages/release/bioc/html/ensembldb.html) [![Bioconductor release build status](http://www.bioconductor.org/shields/build/release/bioc/ensembldb.svg)](http://www.bioconductor.org/packages/release/bioc/html/ensembldb.html) [![Bioconductor devel build status](http://www.bioconductor.org/shields/build/devel/bioc/ensembldb.svg)](http://www.bioconductor.org/checkResults/deve/bioc-LATEST/ensembldb) [![Travis build result](https://travis-ci.org/jotsetung/ensembldb.svg?branch=master)](https://travis-ci.org/jotsetung/ensembldb) [![codecov result](https://codecov.io/github/jotsetung/ensembldb/coverage.svg?branch=master)](https://codecov.io/github/jotsetung/ensembldb?branch=master) # `ensembldb`: build and use Ensembl-based annotation packages For more information please refer to the [vignettes/ensembldb.org](vignettes/ensembldb.org) file. ensembldb/tests/0000755000175400017540000000000013175714743014711 5ustar00biocbuildbiocbuildensembldb/tests/testthat/0000755000175400017540000000000013241155731016537 5ustar00biocbuildbiocbuildensembldb/tests/testthat.R0000644000175400017540000000016413175714743016675 0ustar00biocbuildbiocbuildlibrary(testthat) library(ensembldb) library(EnsDb.Hsapiens.v75) edb <- EnsDb.Hsapiens.v75 test_check("ensembldb") ensembldb/tests/testthat/test_Classes.R0000644000175400017540000000731113175714743021332 0ustar00biocbuildbiocbuildtest_that("OnlyCodingTxFilter constructor works", { fl <- OnlyCodingTxFilter() expect_true(is(fl, "OnlyCodingTxFilter")) }) test_that("ProtDomIdFilter constructor works", { fl <- ProtDomIdFilter("a") expect_true(is(fl, "ProtDomIdFilter")) fl <- AnnotationFilter(~ prot_dom_id %in% 1:4) expect_true(is(fl, "ProtDomIdFilter")) expect_equal(value(fl), c("1", "2", "3", "4")) expect_equal(condition(fl), "==") }) test_that("UniprotDbFilter constructor works", { fl <- UniprotDbFilter("a") expect_true(is(fl, "UniprotDbFilter")) fl <- AnnotationFilter(~ uniprot_db != "4") expect_true(is(fl, "UniprotDbFilter")) expect_equal(value(fl), "4") expect_equal(condition(fl), "!=") }) test_that("UniprotMappingTypeFilter constructor works", { fl <- UniprotMappingTypeFilter("a") expect_true(is(fl, "UniprotMappingTypeFilter")) fl <- AnnotationFilter(~ uniprot_mapping_type != "4") expect_true(is(fl, "UniprotMappingTypeFilter")) expect_equal(value(fl), "4") expect_equal(condition(fl), "!=") }) test_that("GRangesFilter works for EnsDb", { ## Testing slots gr <- GRanges("X", ranges = IRanges(123, 234), strand = "-") grf <- GRangesFilter(gr, type = "within") ## Now check some stuff expect_equal(start(grf), start(gr)) expect_equal(end(grf), end(gr)) expect_equal(as.character(strand(gr)), strand(grf)) expect_equal(as.character(seqnames(gr)), seqnames(grf)) ## Test column: ## filter alone. exp <- c(start = "gene_seq_start", end = "gene_seq_end", seqname = "seq_name", strand = "seq_strand") expect_equal(ensembldb:::ensDbColumn(grf), exp) grf@feature <- "tx" exp <- c(start = "tx_seq_start", end = "tx_seq_end", seqname = "seq_name", strand = "seq_strand") expect_equal(ensembldb:::ensDbColumn(grf), exp) grf@feature <- "exon" exp <- c(start = "exon_seq_start", end = "exon_seq_end", seqname = "seq_name", strand = "seq_strand") expect_equal(ensembldb:::ensDbColumn(grf), exp) ## filter and ensdb. exp <- c(start = "exon.exon_seq_start", end = "exon.exon_seq_end", seqname = "gene.seq_name", strand = "gene.seq_strand") expect_equal(ensembldb:::ensDbColumn(grf, edb), exp) grf@feature <- "tx" exp <- c(start = "tx.tx_seq_start", end = "tx.tx_seq_end", seqname = "gene.seq_name", strand = "gene.seq_strand") expect_equal(ensembldb:::ensDbColumn(grf, edb), exp) grf@feature <- "gene" exp <- c(start = "gene.gene_seq_start", end = "gene.gene_seq_end", seqname = "gene.seq_name", strand = "gene.seq_strand") expect_equal(ensembldb:::ensDbColumn(grf, edb), exp) exp <- paste0("(gene_seq_start>=123 and gene_seq_end<=234 and", " seq_name='X' and seq_strand = -1)") expect_equal(ensembldb:::ensDbQuery(grf), exp) ## what if we set strand to * grf2 <- GRangesFilter(GRanges("1", IRanges(123, 234)), type = "within") exp <- paste0("(gene.gene_seq_start>=123 and gene.gene_seq_end<=234", " and gene.seq_name='1')") expect_equal(ensembldb:::ensDbQuery(grf2, edb), exp) ## Now, using overlapping. grf2 <- GRangesFilter(GRanges("X", IRanges(123, 234), strand = "-"), type = "any", feature = "transcript") exp <- paste0("(tx.tx_seq_start<=234 and tx.tx_seq_end>=123 and", " gene.seq_name='X' and gene.seq_strand = -1)") expect_equal(ensembldb:::ensDbQuery(grf2, edb), exp) }) test_that("TxSupportLevelFilter works for EnsDb", { fl <- TxSupportLevelFilter(3) expect_true(is(fl, "TxSupportLevelFilter")) fl <- AnnotationFilter(~ tx_support_level == 3) expect_true(is(fl, "TxSupportLevelFilter")) }) ensembldb/tests/testthat/test_Methods-Filter.R0000644000175400017540000007001313175714743022562 0ustar00biocbuildbiocbuild test_that("ensDbColumn works", { smb <- SymbolFilter("a") expect_equal(unname(ensembldb:::ensDbColumn(smb)), "gene_name") expect_equal(unname(ensembldb:::ensDbColumn(smb, edb)), "gene.gene_name") expect_error(unname(ensembldb:::ensDbColumn(smb, edb, "tx"))) expect_equal(unname(ensembldb:::ensDbColumn(smb, edb, "gene")), "gene.gene_name") ## fl <- OnlyCodingTxFilter() expect_equal(ensembldb:::ensDbColumn(fl), "tx.tx_cds_seq_start") ## gene filters: fl <- GeneIdFilter("a") expect_equal(unname(ensembldb:::ensDbColumn(fl)), "gene_id") expect_equal(unname(ensembldb:::ensDbColumn(fl, edb)), "gene.gene_id") expect_equal(unname(ensembldb:::ensDbColumn(fl, edb, "tx")), "tx.gene_id") fl <- GenenameFilter("a") expect_equal(unname(ensembldb:::ensDbColumn(fl)), "gene_name") expect_equal(unname(ensembldb:::ensDbColumn(fl, edb)), "gene.gene_name") expect_error(unname(ensembldb:::ensDbColumn(fl, edb, "tx"))) fl <- GeneStartFilter(123) expect_equal(unname(ensembldb:::ensDbColumn(fl)), "gene_seq_start") expect_equal(unname(ensembldb:::ensDbColumn(fl, edb)), "gene.gene_seq_start") expect_error(unname(ensembldb:::ensDbColumn(fl, edb, "tx"))) fl <- GeneEndFilter(123) expect_equal(unname(ensembldb:::ensDbColumn(fl)), "gene_seq_end") expect_equal(unname(ensembldb:::ensDbColumn(fl, edb)), "gene.gene_seq_end") expect_error(unname(ensembldb:::ensDbColumn(fl, edb, "tx"))) fl <- EntrezFilter(123) expect_equal(unname(ensembldb:::ensDbColumn(fl)), "entrezid") if (as.numeric(ensembldb:::dbSchemaVersion(edb)) > 1) { expect_equal(unname(ensembldb:::ensDbColumn(fl, edb)), "entrezgene.entrezid") } else { expect_equal(unname(ensembldb:::ensDbColumn(fl, edb)), "gene.entrezid") } expect_error(unname(ensembldb:::ensDbColumn(fl, edb, "tx"))) fl <- SeqNameFilter("a") expect_equal(unname(ensembldb:::ensDbColumn(fl)), "seq_name") expect_equal(unname(ensembldb:::ensDbColumn(fl, edb)), "gene.seq_name") expect_error(unname(ensembldb:::ensDbColumn(fl, edb, "tx"))) fl <- SeqStrandFilter("a") expect_equal(unname(ensembldb:::ensDbColumn(fl)), "seq_strand") expect_equal(unname(ensembldb:::ensDbColumn(fl, edb)), "gene.seq_strand") expect_error(unname(ensembldb:::ensDbColumn(fl, edb, "tx"))) ## tx filters: fl <- TxIdFilter("a") expect_equal(unname(ensembldb:::ensDbColumn(fl)), "tx_id") expect_equal(unname(ensembldb:::ensDbColumn(fl, edb)), "tx.tx_id") expect_error(unname(ensembldb:::ensDbColumn(fl, edb, "gene"))) expect_equal(unname(ensembldb:::ensDbColumn(fl, edb, "protein")), "protein.tx_id") fl <- TxNameFilter("a") expect_equal(unname(ensembldb:::ensDbColumn(fl)), "tx_id") expect_equal(unname(ensembldb:::ensDbColumn(fl, edb)), "tx.tx_id") expect_error(unname(ensembldb:::ensDbColumn(fl, edb, "gene"))) fl <- TxBiotypeFilter("a") expect_equal(unname(ensembldb:::ensDbColumn(fl)), "tx_biotype") expect_equal(unname(ensembldb:::ensDbColumn(fl, edb)), "tx.tx_biotype") expect_error(unname(ensembldb:::ensDbColumn(fl, edb, "gene"))) fl <- TxStartFilter(123) expect_equal(unname(ensembldb:::ensDbColumn(fl)), "tx_seq_start") expect_equal(unname(ensembldb:::ensDbColumn(fl, edb)), "tx.tx_seq_start") expect_error(unname(ensembldb:::ensDbColumn(fl, edb, "gene"))) fl <- TxEndFilter(123) expect_equal(unname(ensembldb:::ensDbColumn(fl)), "tx_seq_end") expect_equal(unname(ensembldb:::ensDbColumn(fl, edb)), "tx.tx_seq_end") expect_error(unname(ensembldb:::ensDbColumn(fl, edb, "gene"))) ## exon filters: fl <- ExonIdFilter(123) expect_equal(unname(ensembldb:::ensDbColumn(fl)), "exon_id") expect_equal(unname(ensembldb:::ensDbColumn(fl, edb)), "tx2exon.exon_id") expect_equal(unname(ensembldb:::ensDbColumn(fl, edb, "tx2exon")), "tx2exon.exon_id") expect_equal(unname(ensembldb:::ensDbColumn(fl, edb, "exon")), "exon.exon_id") expect_error(unname(ensembldb:::ensDbColumn(fl, edb, "gene"))) fl <- ExonEndFilter(123) expect_equal(unname(ensembldb:::ensDbColumn(fl)), "exon_seq_end") expect_equal(unname(ensembldb:::ensDbColumn(fl, edb)), "exon.exon_seq_end") expect_error(unname(ensembldb:::ensDbColumn(fl, edb, "gene"))) fl <- ExonStartFilter(123) expect_equal(unname(ensembldb:::ensDbColumn(fl)), "exon_seq_start") expect_equal(unname(ensembldb:::ensDbColumn(fl, edb)), "exon.exon_seq_start") expect_error(unname(ensembldb:::ensDbColumn(fl, edb, "gene"))) fl <- ExonRankFilter(123) expect_equal(unname(ensembldb:::ensDbColumn(fl)), "exon_idx") expect_equal(unname(ensembldb:::ensDbColumn(fl, edb)), "tx2exon.exon_idx") expect_error(unname(ensembldb:::ensDbColumn(fl, edb, "gene"))) ## protein filters: fl <- ProteinIdFilter("a") expect_equal(unname(ensembldb:::ensDbColumn(fl)), "protein_id") expect_equal(unname(ensembldb:::ensDbColumn(fl, edb)), "protein.protein_id") expect_equal(unname(ensembldb:::ensDbColumn(fl, edb, "uniprot")), "uniprot.protein_id") expect_error(unname(ensembldb:::ensDbColumn(fl, edb, "gene"))) fl <- UniprotFilter("a") expect_equal(unname(ensembldb:::ensDbColumn(fl)), "uniprot_id") expect_equal(unname(ensembldb:::ensDbColumn(fl, edb)), "uniprot.uniprot_id") expect_error(unname(ensembldb:::ensDbColumn(fl, edb, "gene"))) fl <- ProtDomIdFilter("a") expect_equal(unname(ensembldb:::ensDbColumn(fl)), "protein_domain_id") expect_equal(unname(ensembldb:::ensDbColumn(fl, edb)), "protein_domain.protein_domain_id") expect_error(unname(ensembldb:::ensDbColumn(fl, edb, "gene"))) fl <- UniprotDbFilter("a") expect_equal(unname(ensembldb:::ensDbColumn(fl)), "uniprot_db") expect_equal(unname(ensembldb:::ensDbColumn(fl, edb)), "uniprot.uniprot_db") expect_error(unname(ensembldb:::ensDbColumn(fl, edb, "gene"))) fl <- UniprotMappingTypeFilter("a") expect_equal(unname(ensembldb:::ensDbColumn(fl)), "uniprot_mapping_type") expect_equal(unname(ensembldb:::ensDbColumn(fl, edb)), "uniprot.uniprot_mapping_type") expect_error(unname(ensembldb:::ensDbColumn(fl, edb, "gene"))) }) test_that("ensDbQuery works", { smb <- SymbolFilter("I'm a gene") expect_equal(ensembldb:::ensDbQuery(smb), "gene_name = 'I''m a gene'") expect_equal(ensembldb:::ensDbQuery(smb, edb), "gene.gene_name = 'I''m a gene'") expect_equal(ensembldb:::ensDbQuery(smb, edb, c("gene", "tx")), "gene.gene_name = 'I''m a gene'") expect_error(ensembldb:::ensDbQuery(smb, edb, "tx")) smb <- SymbolFilter(c("a", "x"), condition = "!=") expect_equal(ensembldb:::ensDbQuery(smb), "gene_name not in ('a','x')") smb <- SymbolFilter(c("a", "x"), condition = "!=") expect_equal(ensembldb:::ensDbQuery(smb, edb), "gene.gene_name not in ('a','x')") ## gene_id with tx table. fl <- GeneIdFilter("a") expect_equal(ensembldb:::ensDbQuery(fl), "gene_id = 'a'") expect_equal(ensembldb:::ensDbQuery(fl, edb), "gene.gene_id = 'a'") expect_equal(ensembldb:::ensDbQuery(fl, edb, "tx"), "tx.gene_id = 'a'") ## numeric filter(s) fl <- ExonRankFilter(21) expect_equal(ensembldb:::ensDbQuery(fl), "exon_idx = 21") expect_equal(ensembldb:::ensDbQuery(fl, edb), "tx2exon.exon_idx = 21") ## fl <- OnlyCodingTxFilter() expect_equal(ensembldb:::ensDbQuery(fl), "tx.tx_cds_seq_start is not null") ## fL <- AnnotationFilterList(GeneIdFilter("a"), TxBiotypeFilter("coding", condition = "!="), GeneStartFilter(123, condition = "<")) res <- ensembldb:::ensDbQuery(fL) expect_equal(res, paste0("(gene_id = 'a' and tx_biotype != 'coding' ", "and gene_seq_start < 123)")) res <- ensembldb:::ensDbQuery(fL, edb) expect_equal(res, paste0("(gene.gene_id = 'a' and tx.tx_biotype != ", "'coding' and gene.gene_seq_start < 123)")) fL <- AnnotationFilterList(GeneIdFilter("a"), TxBiotypeFilter("coding", condition = "!="), TxStartFilter(123, condition = "<")) res <- ensembldb:::ensDbQuery(fL, edb) expect_equal(res, paste0("(gene.gene_id = 'a' and tx.tx_biotype != ", "'coding' and tx.tx_seq_start < 123)")) res <- ensembldb:::ensDbQuery(fL, edb, c("tx", "gene", "exon")) expect_equal(res, paste0("(tx.gene_id = 'a' and tx.tx_biotype != ", "'coding' and tx.tx_seq_start < 123)")) fl <- ProteinIdFilter("a") expect_equal(unname(ensembldb:::ensDbQuery(fl)), "protein_id = 'a'") expect_equal(unname(ensembldb:::ensDbQuery(fl, edb)), "protein.protein_id = 'a'") expect_equal(unname(ensembldb:::ensDbQuery(fl, edb, "uniprot")), "uniprot.protein_id = 'a'") fl <- ProtDomIdFilter("a") expect_equal(ensembldb:::ensDbQuery(fl), "protein_domain_id = 'a'") expect_equal(ensembldb:::ensDbQuery(fl, edb), "protein_domain.protein_domain_id = 'a'") fl <- UniprotDbFilter("a") expect_equal(ensembldb:::ensDbQuery(fl), "uniprot_db = 'a'") expect_equal(ensembldb:::ensDbQuery(fl, edb), "uniprot.uniprot_db = 'a'") fl <- UniprotMappingTypeFilter("a") expect_equal(ensembldb:::ensDbQuery(fl), "uniprot_mapping_type = 'a'") expect_equal(ensembldb:::ensDbQuery(fl, edb), "uniprot.uniprot_mapping_type = 'a'") ## Seq name and seq strand. fl <- SeqNameFilter("3") expect_equal(ensembldb:::ensDbQuery(fl), "seq_name = '3'") expect_equal(ensembldb:::ensDbQuery(fl, edb), "gene.seq_name = '3'") fl <- SeqNameFilter("chr3") expect_equal(ensembldb:::ensDbQuery(fl), "seq_name = 'chr3'") expect_equal(ensembldb:::ensDbQuery(fl, edb), "gene.seq_name = 'chr3'") seqlevelsStyle(edb) <- "UCSC" expect_equal(ensembldb:::ensDbQuery(fl), "seq_name = 'chr3'") expect_equal(ensembldb:::ensDbQuery(fl, edb), "gene.seq_name = '3'") seqlevelsStyle(edb) <- "Ensembl" fl <- SeqStrandFilter("+") expect_equal(ensembldb:::ensDbQuery(fl), "seq_strand = 1") expect_equal(ensembldb:::ensDbQuery(fl, edb), "gene.seq_strand = 1") fl <- SeqStrandFilter("+1") expect_equal(ensembldb:::ensDbQuery(fl), "seq_strand = 1") expect_equal(ensembldb:::ensDbQuery(fl, edb), "gene.seq_strand = 1") fl <- SeqStrandFilter("-") expect_equal(ensembldb:::ensDbQuery(fl), "seq_strand = -1") expect_equal(ensembldb:::ensDbQuery(fl, edb), "gene.seq_strand = -1") fl <- SeqStrandFilter("-1") expect_equal(ensembldb:::ensDbQuery(fl), "seq_strand = -1") expect_equal(ensembldb:::ensDbQuery(fl, edb), "gene.seq_strand = -1") ## GRangesFilter: see test_ensDb_for_GRangesFilter }) test_that("ensDbQuery works for AnnotationFilterList", { gnf <- GenenameFilter("BCL2", condition = "!=") snf <- SeqNameFilter(4) ssf <- SeqStrandFilter("+") afl <- AnnotationFilterList(gnf, snf, ssf, logOp = c("|", "&")) Q <- ensembldb:::ensDbQuery(afl) expect_equal(Q, "(gene_name != 'BCL2' or seq_name = '4' and seq_strand = 1)") ## Nested AnnotationFilterLists. afl1 <- AnnotationFilterList(GenenameFilter("BCL2"), GenenameFilter("BCL2L11"), logOp = "|") afl2 <- AnnotationFilterList(afl1, SeqNameFilter(18)) Q <- ensembldb:::ensDbQuery(afl2, db = edb) expect_equal(Q, paste0("((gene.gene_name = 'BCL2' or gene.gene_name = ", "'BCL2L11') and gene.seq_name = '18')")) library(RSQLite) res <- dbGetQuery(dbconn(edb), paste0("select distinct gene_name from gene", " where ", Q)) expect_equal(res$gene_name, "BCL2") res2 <- genes(edb, filter = AnnotationFilterList(GenenameFilter(c("BCL2L11", "BCL2")), SeqNameFilter(18))) expect_equal(res$gene_name, res2$gene_name) ## Same with a GRangesFilter. grf <- GRangesFilter(GRanges(18, IRanges(60790600, 60790700))) afl2 <- AnnotationFilterList(afl1, grf) Q <- ensembldb:::ensDbQuery(afl2, db = edb) expect_equal(Q, paste0("((gene.gene_name = 'BCL2' or gene.gene_name = ", "'BCL2L11') and (gene.gene_seq_start<=60790700", " and gene.gene_seq_end>=60790600 and gene.seq_name", "='18'))")) res <- dbGetQuery(dbconn(edb), paste0("select distinct gene_name from gene", " where ", Q)) expect_equal(res$gene_name, "BCL2") }) test_that("ensDbQuery works for SeqNameFilter", { fl <- SeqNameFilter("3") res <- ensembldb:::ensDbQuery(fl) expect_equal(res, "seq_name = '3'") res <- ensembldb:::ensDbQuery(fl, edb) expect_equal(res, "gene.seq_name = '3'") fl <- SeqNameFilter("chr3") res <- ensembldb:::ensDbQuery(fl) expect_equal(res, "seq_name = 'chr3'") res <- ensembldb:::ensDbQuery(fl, edb) expect_equal(res, "gene.seq_name = 'chr3'") seqlevelsStyle(edb) <- "UCSC" res <- ensembldb:::ensDbQuery(fl) expect_equal(res, "seq_name = 'chr3'") res <- ensembldb:::ensDbQuery(fl, edb) expect_equal(res, "gene.seq_name = '3'") seqlevelsStyle(edb) <- "Ensembl" }) test_that("ensDbQuery works for GRangesFilter", { gr <- GRanges(seqnames = "a", ranges = IRanges(start = 1, end = 5)) F <- GRangesFilter(value = gr, type = "within") expect_equal(unname(ensembldb:::ensDbColumn(F)), c("gene_seq_start", "gene_seq_end", "seq_name", "seq_strand")) expect_equal(unname(ensembldb:::ensDbColumn(F, edb)), c("gene.gene_seq_start", "gene.gene_seq_end", "gene.seq_name", "gene.seq_strand")) expect_equal(ensembldb:::ensDbQuery(F), paste0("(gene_seq_start>=1 and gene_seq_end", "<=5 and seq_name='a')")) expect_equal(ensembldb:::ensDbQuery(F, edb), paste0("(gene.gene_seq_start>=1 and gene.gene_seq_end", "<=5 and gene.seq_name='a')")) F <- GRangesFilter(value = gr, type = "any") expect_equal(ensembldb:::ensDbQuery(F), paste0("(gene_seq_start<=5 and gene_seq_end", ">=1 and seq_name='a')")) expect_equal(ensembldb:::ensDbQuery(F, edb), paste0("(gene.gene_seq_start<=5 and gene.gene_seq_end", ">=1 and gene.seq_name='a')")) ## tx F <- GRangesFilter(value = gr, feature = "tx", type = "within") expect_equal(unname(ensembldb:::ensDbColumn(F)), c("tx_seq_start", "tx_seq_end", "seq_name", "seq_strand")) expect_equal(unname(ensembldb:::ensDbColumn(F, edb)), c("tx.tx_seq_start", "tx.tx_seq_end", "gene.seq_name", "gene.seq_strand")) ## exon F <- GRangesFilter(value = gr, feature = "exon", type = "within") expect_equal(unname(ensembldb:::ensDbColumn(F)), c("exon_seq_start", "exon_seq_end", "seq_name", "seq_strand")) expect_equal(unname(ensembldb:::ensDbColumn(F, edb)), c("exon.exon_seq_start", "exon.exon_seq_end", "gene.seq_name", "gene.seq_strand")) ## Check the buildWhere res <- ensembldb:::buildWhereForGRanges(F, columns = ensembldb:::ensDbColumn(F)) expect_equal(res,"(exon_seq_start>=1 and exon_seq_end<=5 and seq_name='a')") res <- ensembldb:::ensDbQuery(F) expect_equal(res,"(exon_seq_start>=1 and exon_seq_end<=5 and seq_name='a')") res <- ensembldb:::ensDbQuery(F, edb) expect_equal(res, paste0("(exon.exon_seq_start>=1 and exon.exon_seq_end", "<=5 and gene.seq_name='a')")) }) test_that("buildWhereForGRanges works", { grng <- GRanges(seqname = "X", IRanges(start = 10, end = 100)) ## start flt <- GRangesFilter(grng, type = "start") res <- ensembldb:::buildWhereForGRanges( flt, columns = ensembldb:::ensDbColumn(flt)) expect_equal(res, "(gene_seq_start=10 and seq_name='X')") res <- ensembldb:::buildWhereForGRanges( flt, columns = ensembldb:::ensDbColumn(flt, db = edb)) expect_equal(res, "(gene.gene_seq_start=10 and gene.seq_name='X')") ## end flt <- GRangesFilter(grng, type = "end") res <- ensembldb:::buildWhereForGRanges( flt, columns = ensembldb:::ensDbColumn(flt)) expect_equal(res, "(gene_seq_end=100 and seq_name='X')") ## equal flt <- GRangesFilter(grng, type = "equal") res <- ensembldb:::buildWhereForGRanges( flt, columns = ensembldb:::ensDbColumn(flt)) expect_equal(res, "(gene_seq_start=10 and gene_seq_end=100 and seq_name='X')") ## within flt <- GRangesFilter(grng, type = "within") res <- ensembldb:::buildWhereForGRanges( flt, columns = ensembldb:::ensDbColumn(flt)) expect_equal(res, "(gene_seq_start>=10 and gene_seq_end<=100 and seq_name='X')") ## any flt <- GRangesFilter(grng, type = "any") res <- ensembldb:::buildWhereForGRanges( flt, columns = ensembldb:::ensDbColumn(flt)) expect_equal(res, "(gene_seq_start<=100 and gene_seq_end>=10 and seq_name='X')") ## Same with a strand specified. grng <- GRanges(seqname = "X", IRanges(start = 10, end = 100), strand = "-") ## start flt <- GRangesFilter(grng, type = "start") res <- ensembldb:::buildWhereForGRanges( flt, columns = ensembldb:::ensDbColumn(flt)) expect_equal(res, "(gene_seq_start=10 and seq_name='X' and seq_strand = -1)") ## end flt <- GRangesFilter(grng, type = "end") res <- ensembldb:::buildWhereForGRanges( flt, columns = ensembldb:::ensDbColumn(flt)) expect_equal(res, "(gene_seq_end=100 and seq_name='X' and seq_strand = -1)") ## equal flt <- GRangesFilter(grng, type = "equal") res <- ensembldb:::buildWhereForGRanges( flt, columns = ensembldb:::ensDbColumn(flt)) expect_equal(res, paste0("(gene_seq_start=10 and gene_seq_end=100 and ", "seq_name='X' and seq_strand = -1)")) ## within flt <- GRangesFilter(grng, type = "within") res <- ensembldb:::buildWhereForGRanges( flt, columns = ensembldb:::ensDbColumn(flt)) expect_equal(res, paste0("(gene_seq_start>=10 and gene_seq_end<=100 and ", "seq_name='X' and seq_strand = -1)")) ## any flt <- GRangesFilter(grng, type = "any") res <- ensembldb:::buildWhereForGRanges( flt, columns = ensembldb:::ensDbColumn(flt)) expect_equal(res, paste0("(gene_seq_start<=100 and gene_seq_end>=10 and ", "seq_name='X' and seq_strand = -1)")) }) test_that("ensDbColumn works with AnnotationFilterList", { afl <- AnnotationFilterList(GeneIdFilter(123), SeqNameFilter(3)) afl2 <- AnnotationFilterList(afl, SeqNameFilter(5)) res <- ensembldb:::ensDbColumn(afl2) expect_equal(res, c("gene_id", "seq_name")) }) ############################################################ ## Using protein data based filters. test_that("ProteinIdFilter works", { pf <- ProteinIdFilter("ABC") expect_equal(value(pf), "ABC") expect_equal(field(pf), "protein_id") expect_equal(ensembldb:::ensDbQuery(pf), "protein_id = 'ABC'") if (hasProteinData(edb)) { expect_equal(ensembldb:::ensDbColumn(pf, edb), "protein.protein_id") expect_equal(ensembldb:::ensDbColumn(pf, edb, with.tables = "protein_domain"), "protein_domain.protein_id") expect_equal(ensembldb:::ensDbColumn(pf, edb, with.tables = "uniprot"), "uniprot.protein_id") expect_equal(ensembldb:::ensDbQuery(pf, edb), "protein.protein_id = 'ABC'") expect_equal(ensembldb:::ensDbQuery(pf, edb, with.tables = "uniprot"), "uniprot.protein_id = 'ABC'") } else { expect_error(ensembldb:::ensDbColumn(pf, edb)) expect_error(ensembldb:::ensDbQuery(pf, edb)) expect_error(ensembldb:::ensDbColumn(pf, edb, with.tables = "uniprot")) expect_error(ensembldb:::ensDbQuery(pf, edb, with.tables = "uniprot")) } pf <- ProteinIdFilter(c("A", "B")) expect_equal(ensembldb:::ensDbQuery(pf), "protein_id in ('A','B')") expect_error(ProteinIdFilter("B", condition = ">")) }) test_that("UniprotFilter works", { pf <- UniprotFilter("ABC") expect_equal(value(pf), "ABC") expect_equal(field(pf), "uniprot") expect_equal(unname(ensembldb:::ensDbColumn(pf)), "uniprot_id") expect_equal(ensembldb:::ensDbQuery(pf), "uniprot_id = 'ABC'") if (hasProteinData(edb)) { expect_equal(ensembldb:::ensDbColumn(pf, edb), "uniprot.uniprot_id") expect_equal(ensembldb:::ensDbColumn(pf, edb, with.tables = "uniprot"), "uniprot.uniprot_id") expect_equal(ensembldb:::ensDbQuery(pf, edb), "uniprot.uniprot_id = 'ABC'") expect_equal(ensembldb:::ensDbQuery(pf, edb, with.tables = "uniprot"), "uniprot.uniprot_id = 'ABC'") } else { expect_error(ensembldb:::ensDbColumn(pf, edb)) expect_error(ensembldb:::ensDbQuery(pf, edb)) expect_error(ensembldb:::ensDbColumn(pf, edb, with.tables = "uniprot")) expect_error(ensembldb:::ensDbQuery(pf, edb, with.tables = "uniprot")) } pf <- UniprotFilter(c("A", "B")) expect_equal(ensembldb:::ensDbQuery(pf), "uniprot_id in ('A','B')") expect_error(UniprotFilter("B", condition = ">")) }) test_that("ProtDomIdFilter works", { pf <- ProtDomIdFilter("ABC") expect_equal(value(pf), "ABC") expect_equal(field(pf), "prot_dom_id") expect_equal(unname(ensembldb:::ensDbColumn(pf)), "protein_domain_id") expect_equal(ensembldb:::ensDbQuery(pf), "protein_domain_id = 'ABC'") if (hasProteinData(edb)) { expect_equal(ensembldb:::ensDbColumn(pf, edb), "protein_domain.protein_domain_id") expect_equal(ensembldb:::ensDbColumn(pf, edb, with.tables = "protein_domain"), "protein_domain.protein_domain_id") expect_equal(ensembldb:::ensDbQuery(pf, edb), "protein_domain.protein_domain_id = 'ABC'") expect_equal(ensembldb:::ensDbQuery(pf, edb, with.tables = "protein_domain"), "protein_domain.protein_domain_id = 'ABC'") } else { expect_error(ensembldb:::ensDbColumn(pf, edb)) expect_error(ensembldb:::ensDbQuery(pf, edb)) expect_error(ensembldb:::ensDbColumn(pf, edb, with.tables = "protein_domain")) expect_error(ensembldb:::ensDbQuery(pf, edb, with.tables = "protein_domain")) } pf <- ProtDomIdFilter(c("A", "B")) expect_equal(ensembldb:::ensDbQuery(pf), "protein_domain_id in ('A','B')") expect_error(ProtDomIdFilter("B", condition = ">")) }) test_that("UniprotDbFilter works", { pf <- UniprotDbFilter("ABC") expect_equal(value(pf), "ABC") expect_equal(field(pf), "uniprot_db") expect_equal(ensembldb:::ensDbQuery(pf), "uniprot_db = 'ABC'") if (hasProteinData(edb)) { expect_equal(ensembldb:::ensDbColumn(pf, edb), "uniprot.uniprot_db") expect_equal(ensembldb:::ensDbColumn(pf, edb, with.tables = "uniprot"), "uniprot.uniprot_db") expect_equal(ensembldb:::ensDbQuery(pf, edb), "uniprot.uniprot_db = 'ABC'") expect_equal(ensembldb:::ensDbQuery(pf, edb, with.tables = "uniprot"), "uniprot.uniprot_db = 'ABC'") } else { expect_error(ensembldb:::ensDbColumn(pf, edb)) expect_error(ensembldb:::ensDbQuery(pf, edb)) expect_error(ensembldb:::ensDbColumn(pf, edb, with.tables = "uniprot")) expect_error(ensembldb:::ensDbQuery(pf, edb, with.tables = "uniprot")) } pf <- UniprotDbFilter(c("A", "B")) expect_equal(ensembldb:::ensDbQuery(pf), "uniprot_db in ('A','B')") expect_error(UniprotDbFilter("B", condition = ">")) }) test_that("UniprotMappingTypeFilter works", { pf <- UniprotMappingTypeFilter("ABC") expect_equal(value(pf), "ABC") expect_equal(field(pf), "uniprot_mapping_type") expect_equal(ensembldb:::ensDbQuery(pf), "uniprot_mapping_type = 'ABC'") expect_equal(unname(ensembldb:::ensDbColumn(pf)), "uniprot_mapping_type") if (hasProteinData(edb)) { expect_equal(ensembldb:::ensDbColumn(pf, edb), "uniprot.uniprot_mapping_type") expect_equal(ensembldb:::ensDbColumn(pf, edb, with.tables = "uniprot"), "uniprot.uniprot_mapping_type") expect_equal(ensembldb:::ensDbQuery(pf, edb), "uniprot.uniprot_mapping_type = 'ABC'") expect_equal(ensembldb:::ensDbQuery(pf, edb, with.tables = "uniprot"), "uniprot.uniprot_mapping_type = 'ABC'") } else { expect_error(ensembldb:::ensDbColumn(pf, edb)) expect_error(ensembldb:::ensDbQuery(pf, edb)) expect_error(ensembldb:::ensDbColumn(pf, edb, with.tables = "uniprot")) expect_error(ensembldb:::ensDbQuery(pf, edb, with.tables = "uniprot")) } pf <- UniprotMappingTypeFilter(c("A", "B")) expect_equal(ensembldb:::ensDbQuery(pf), "uniprot_mapping_type in ('A','B')") expect_error(UniprotMappingTypeFilter("B", condition = ">")) }) test_that("TxSupportLevelFilter works", { fl <- TxSupportLevelFilter(3) expect_equal(value(fl), 3) expect_equal(ensembldb:::ensDbQuery(fl), "tx_support_level = 3") expect_equal(unname(ensembldb:::ensDbColumn(fl)), "tx_support_level") supportsTsl <- any(supportedFilters(edb)$filter == "TxSupportLevelFilter") if (supportsTsl) { expect_equal(unname(ensembldb:::ensDbColumn(fl, edb)), "tx.tx_support_level") expect_equal(unname(ensembldb:::ensDbColumn(fl, edb, with.tables = "tx")), "tx.tx_support_level") expect_equal(unname(ensembldb:::ensDbQuery(fl, edb)), "tx.tx_support_level = 3") expect_equal(unname(ensembldb:::ensDbQuery(fl, edb, with.tables = "tx")), "tx.tx_support_level = 3") expect_error(ensembldb:::ensDbQuery(fl, edb, with.tables = "gene")) } else { expect_error(ensembldb:::ensDbColumn(fl, edb)) expect_error(ensembldb:::ensDbColumn(fl, edb, with.tables = "tx")) expect_error(ensembldb:::ensDbQuery(fl, edb)) expect_error(ensembldb:::ensDbQuery(fl, edb, with.tables = "tx")) } }) test_that("convertFilter works", { flt <- AnnotationFilter(~ genename == "BCL2") expect_equal(convertFilter(flt), "genename == 'BCL2'") expect_equal(convertFilter(flt, edb), "gene.gene_name = 'BCL2'") flt_list <- AnnotationFilter(~ genename %in% c("BCL2", "BCL2L11") & tx_biotype == "protein_coding") expect_equal( convertFilter(flt_list), "genename %in% c('BCL2', 'BCL2L11') & tx_biotype == 'protein_coding'") expect_equal( convertFilter(flt_list, edb), "(gene.gene_name in ('BCL2','BCL2L11') and tx.tx_biotype = 'protein_coding')") }) ensembldb/tests/testthat/test_Methods-with-returnFilterColumns.R0000644000175400017540000003035613175714743026342 0ustar00biocbuildbiocbuildtest_that("set returnFilterColumns works", { orig <- returnFilterColumns(edb) returnFilterColumns(edb) <- TRUE expect_equal(TRUE, returnFilterColumns(edb)) returnFilterColumns(edb) <- FALSE expect_equal(FALSE, returnFilterColumns(edb)) expect_error(returnFilterColumns(edb) <- "d") expect_error(returnFilterColumns(edb) <- c(TRUE, FALSE)) ## Restore the "original" setting returnFilterColumns(edb) <- orig }) test_that("returnFilterColumns works with_genes", { orig <- returnFilterColumns(edb) returnFilterColumns(edb) <- FALSE ## What happens if we use a GRangesFilter with return filter cols FALSE? grf <- GRangesFilter(GRanges(17, IRanges(57180000, 57233000)), type = "within") res <- genes(edb, filter = grf) expect_equal(res$gene_id, c("ENSG00000224738", "ENSG00000182628", "ENSG00000252212", "ENSG00000211514", "ENSG00000207996")) cols <- c("gene_id", "gene_name") res <- genes(edb, filter = grf, return.type = "data.frame", columns = cols) ## Expect only the columns expect_equal(colnames(res), cols) returnFilterColumns(edb) <- TRUE res <- genes(edb, filter = grf, return.type = "data.frame", columns = cols) ## Now I expect also the gene coords. expect_equal(colnames(res), c(cols, "gene_seq_start", "gene_seq_end", "seq_name", "seq_strand")) ## Use a gene biotype filter gbt <- GeneBiotypeFilter("protein_coding") returnFilterColumns(edb) <- TRUE res <- genes(edb, filter = list(gbt, grf), return.type = "data.frame", columns = cols) expect_equal(res$gene_name, "SKA2") expect_equal(colnames(res), c(cols, "gene_biotype", "gene_seq_start", "gene_seq_end", "seq_name", "seq_strand")) returnFilterColumns(edb) <- FALSE res <- genes(edb, filter = list(gbt, grf), return.type = "data.frame", columns = cols) expect_equal(colnames(res), cols) returnFilterColumns(edb) <- orig }) test_that("returnFilterColumns works with_tx", { orig <- returnFilterColumns(edb) returnFilterColumns(edb) <- FALSE ## What happens if we use a GRangesFilter with return filter cols FALSE? grf <- GRangesFilter(GRanges(17, IRanges(57180000, 57233000)), type = "within") res <- transcripts(edb, filter = grf) cols <- c("tx_id", "gene_name") res <- transcripts(edb, filter = grf, return.type = "data.frame", columns = cols) ## Expect only the columns expect_equal(colnames(res), cols) returnFilterColumns(edb) <- TRUE res <- transcripts(edb, filter = grf, return.type = "data.frame", columns = cols) ## Now I expect also the gene coords. expect_equal(colnames(res), c(cols, "tx_seq_start", "tx_seq_end", "seq_name", "seq_strand")) ## Use a gene biotype filter gbt <- GeneBiotypeFilter("protein_coding") returnFilterColumns(edb) <- TRUE res <- transcripts(edb, filter = list(gbt, grf), return.type = "data.frame", columns = cols) expect_equal(unique(res$gene_name), "SKA2") expect_equal(colnames(res), c(cols, "gene_biotype", "tx_seq_start", "tx_seq_end", "seq_name", "seq_strand")) returnFilterColumns(edb) <- FALSE res <- transcripts(edb, filter = list(gbt, grf), return.type = "data.frame", columns = cols) expect_equal(colnames(res), cols) returnFilterColumns(edb) <- orig }) test_that("returnFilterColumns works with exons", { orig <- returnFilterColumns(edb) returnFilterColumns(edb) <- FALSE ## What happens if we use a GRangesFilter with return filter cols FALSE? grf <- GRangesFilter(GRanges(17, IRanges(57180000, 57233000)), type = "within") res <- exons(edb, filter = grf) cols <- c("exon_id", "gene_name") res <- exons(edb, filter = grf, return.type = "data.frame", columns = cols) ## Expect only the columns expect_equal(colnames(res), cols) returnFilterColumns(edb) <- TRUE res <- exons(edb, filter = grf, return.type = "data.frame", columns = cols) ## Now I expect also the gene coords. expect_equal(colnames(res), c(cols, "exon_seq_start", "exon_seq_end", "seq_name", "seq_strand")) ## Use a gene biotype filter gbt <- GeneBiotypeFilter("protein_coding") returnFilterColumns(edb) <- TRUE res <- exons(edb, filter = list(gbt, grf), return.type = "data.frame", columns = cols) expect_equal(unique(res$gene_name), c("TRIM37", "SKA2")) expect_equal(colnames(res), c(cols, "gene_biotype", "exon_seq_start", "exon_seq_end", "seq_name", "seq_strand")) returnFilterColumns(edb) <- FALSE res <- exons(edb, filter = list(gbt, grf), return.type = "data.frame", columns = cols) expect_equal(colnames(res), cols) returnFilterColumns(edb) <- orig }) test_that("returnFilterColumns works with exonsBy", { orig <- returnFilterColumns(edb) returnFilterColumns(edb) <- FALSE ## What happens if we use a GRangesFilter with return filter cols FALSE? grf <- GRangesFilter(GRanges(17, IRanges(57180000, 57233000)), type = "within") ## By genes cols <- c("exon_id", "gene_name") res <- exonsBy(edb, by = "gene", filter = grf, columns = cols) res <- unlist(res) ## Expect only the columns expect_equal(colnames(mcols(res)), cols) returnFilterColumns(edb) <- TRUE res <- exonsBy(edb, by = "gene", filter = grf, columns = cols) res <- unlist(res) ## Now I expect also the gene coords, but not the seq_name and seq_strand, ## as these are redundant with data which is in the GRanges! expect_equal(colnames(mcols(res)), c(cols, "gene_seq_start", "gene_seq_end")) ## Use a gene biotype filter gbt <- GeneBiotypeFilter("protein_coding") returnFilterColumns(edb) <- TRUE res <- unlist(exonsBy(edb, by = "gene", filter = list(gbt, grf), columns = cols)) expect_equal(unique(res$gene_name), c("SKA2")) expect_equal(colnames(mcols(res)), c(cols, "gene_biotype", "gene_seq_start", "gene_seq_end")) returnFilterColumns(edb) <- FALSE res <- unlist(exonsBy(edb, by = "gene", filter = list(gbt, grf), columns = cols)) expect_equal(colnames(mcols(res)), cols) ## By tx returnFilterColumns(edb) <- FALSE cols <- c("exon_id", "gene_name") res <- exonsBy(edb, by = "tx", filter = grf, columns = cols) res <- unlist(res) ## Expect only the columns expect_equal(colnames(mcols(res)), c(cols, "exon_rank")) returnFilterColumns(edb) <- TRUE res <- exonsBy(edb, by = "tx", filter = grf, columns = cols) res <- unlist(res) ## Now I expect also the gene coords. expect_equal(colnames(mcols(res)), c(cols, "tx_seq_start", "tx_seq_end", "exon_rank")) ## Use a gene biotype filter gbt <- GeneBiotypeFilter("protein_coding") returnFilterColumns(edb) <- TRUE res <- unlist(exonsBy(edb, by = "tx", filter = list(gbt, grf), columns = cols)) expect_equal(unique(res$gene_name), c("SKA2")) expect_equal(colnames(mcols(res)), c(cols, "gene_biotype", "tx_seq_start", "tx_seq_end", "exon_rank")) returnFilterColumns(edb) <- FALSE res <- unlist(exonsBy(edb, by = "tx", filter = list(gbt, grf), columns = cols)) expect_equal(colnames(mcols(res)), c(cols, "exon_rank")) returnFilterColumns(edb) <- orig }) test_that("returnFilterColumns works with transcriptsBy", { orig <- returnFilterColumns(edb) returnFilterColumns(edb) <- FALSE ## What happens if we use a GRangesFilter with return filter cols FALSE? grf <- GRangesFilter(GRanges(17, IRanges(57180000, 57233000)), type = "within") ## By genes cols <- c("tx_id", "gene_name") res <- transcriptsBy(edb, by = "gene", filter = grf, columns = cols) res <- unlist(res) ## Expect only the columns expect_equal(colnames(mcols(res)), cols) returnFilterColumns(edb) <- TRUE res <- transcriptsBy(edb, by = "gene", filter = grf, columns = cols) res <- unlist(res) ## Now I expect also the gene coords. expect_equal(colnames(mcols(res)), c(cols, "gene_seq_start", "gene_seq_end")) ## Use a gene biotype filter gbt <- GeneBiotypeFilter("protein_coding") returnFilterColumns(edb) <- TRUE res <- unlist(transcriptsBy(edb, by = "gene", filter = list(gbt, grf), columns = cols)) expect_equal(unique(res$gene_name), c("SKA2")) expect_equal(colnames(mcols(res)), c(cols, "gene_biotype", "gene_seq_start", "gene_seq_end")) returnFilterColumns(edb) <- FALSE res <- unlist(transcriptsBy(edb, by = "gene", filter = list(gbt, grf), columns = cols)) expect_equal(colnames(mcols(res)), cols) returnFilterColumns(edb) <- orig }) test_that("returnFilterColumns works with_cdsBy", { orig <- returnFilterColumns(edb) grf <- GRangesFilter(GRanges(17, IRanges(57180000, 57233000)), type = "within") ## By tx returnFilterColumns(edb) <- FALSE cols <- c("gene_id", "gene_name") res <- cdsBy(edb, by = "tx", filter = grf, columns = cols) res <- unlist(res) ## Expect only the columns expect_equal(colnames(mcols(res)), c(cols, "exon_id", "exon_rank")) returnFilterColumns(edb) <- TRUE res <- cdsBy(edb, by = "tx", filter = grf, columns = cols) res <- unlist(res) ## Now I expect also the gene coords. expect_equal(colnames(mcols(res)), c(cols, "tx_seq_start", "tx_seq_end", "seq_name", "seq_strand", "exon_id", "exon_rank")) ## Use a gene biotype filter gbt <- GeneBiotypeFilter("protein_coding") returnFilterColumns(edb) <- TRUE res <- unlist(cdsBy(edb, by = "tx", filter = list(gbt, grf), columns = cols)) expect_equal(unique(res$gene_name), c("SKA2")) expect_equal(colnames(mcols(res)), c(cols, "gene_biotype", "tx_seq_start", "tx_seq_end", "seq_name", "seq_strand", "exon_id", "exon_rank")) returnFilterColumns(edb) <- FALSE res <- unlist(cdsBy(edb, by = "tx", filter = list(gbt, grf), columns = cols)) expect_equal(colnames(mcols(res)), c(cols, "exon_id", "exon_rank")) returnFilterColumns(edb) <- orig }) test_that("returnFilterColumns works with threeUTRsByTranscript", { orig <- returnFilterColumns(edb) grf <- GRangesFilter(GRanges(17, IRanges(57180000, 57233000)), type = "within") ## By tx returnFilterColumns(edb) <- FALSE cols <- c("gene_id", "gene_name") res <- threeUTRsByTranscript(edb, filter = grf, columns = cols) res <- unlist(res) ## Expect only the columns expect_equal(colnames(mcols(res)), c(cols, "exon_id", "exon_rank")) returnFilterColumns(edb) <- TRUE res <- threeUTRsByTranscript(edb, filter = grf, columns = cols) res <- unlist(res) ## Now I expect also the gene coords. expect_equal(colnames(mcols(res)), c(cols, "tx_seq_start", "tx_seq_end", "seq_name", "seq_strand", "exon_id", "exon_rank")) ## Use a gene biotype filter gbt <- GeneBiotypeFilter("protein_coding") returnFilterColumns(edb) <- TRUE res <- unlist(threeUTRsByTranscript(edb, filter = list(gbt, grf), columns = cols)) expect_equal(unique(res$gene_name), c("SKA2")) expect_equal(colnames(mcols(res)), c(cols, "gene_biotype", "tx_seq_start", "tx_seq_end", "seq_name", "seq_strand", "exon_id", "exon_rank")) returnFilterColumns(edb) <- FALSE res <- unlist(threeUTRsByTranscript(edb, filter = list(gbt, grf), columns = cols)) expect_equal(colnames(mcols(res)), c(cols, "exon_id", "exon_rank")) returnFilterColumns(edb) <- orig }) ensembldb/tests/testthat/test_Methods.R0000644000175400017540000011665313175714743021352 0ustar00biocbuildbiocbuild ## testing genes method. test_that("genes method works", { Gns <- genes(edb, filter = ~ genename == "BCL2") expect_identical(Gns$gene_name, "BCL2") Gns <- genes(edb, filter = SeqNameFilter("Y"), return.type = "DataFrame") expect_identical(sort(colnames(Gns)), sort(unique(c(listColumns(edb, "gene"), "entrezid")))) Gns <- genes(edb, filter = ~ seq_name == "Y" & gene_id == "ENSG00000012817", return.type = "DataFrame", columns = c("gene_id", "tx_name")) expect_identical(colnames(Gns), c("gene_id", "tx_name", "seq_name")) expect_true(all(Gns$seq_name == "Y")) expect_true(all(Gns$gene_id == "ENSG00000012817")) Gns <- genes(edb, filter = AnnotationFilterList(SeqNameFilter("Y"), GeneIdFilter("ENSG00000012817")), columns = c("gene_id", "gene_name")) ## Here we don't need the seqnames in mcols! expect_identical(colnames(mcols(Gns)), c("gene_id", "gene_name")) expect_true(all(Gns$seq_name == "Y")) expect_true(all(Gns$gene_id == "ENSG00000012817")) Gns <- genes(edb, filter = ~ seq_name == "Y" | genename == "BCL2", return.type = "DataFrame") expect_true(all(Gns$seq_name %in% c("18", "Y"))) Gns <- genes(edb, filter = AnnotationFilterList(SeqNameFilter("Y"), GenenameFilter("BCL2")), return.type = "DataFrame") expect_true(nrow(Gns) == 0) Gns <- genes(edb, filter = AnnotationFilterList(SeqNameFilter("Y"), GenenameFilter("BCL2"), logOp = "|"), return.type = "DataFrame") expect_true(all(Gns$seq_name %in% c("18", "Y"))) afl <- AnnotationFilterList(GenenameFilter(c("BCL2", "BCL2L11")), SeqNameFilter(18), logOp = "&") afl2 <- AnnotationFilterList(SeqNameFilter("Y"), afl, logOp = "|") Gns <- genes(edb, filter = afl2, columns = "gene_name", return.type = "DataFrame") expect_identical(colnames(Gns), c("gene_name", "gene_id", "seq_name")) expect_true(!any(Gns$gene_name == "BCL2L11")) expect_true(any(Gns$gene_name == "BCL2")) expect_true(all(Gns$seq_name %in% c("Y", "18"))) }) test_that("transcripts method works", { Tns <- transcripts(edb, filter = SeqNameFilter("Y"), return.type = "DataFrame") expect_identical(sort(colnames(Tns)), sort(c(listColumns(edb, "tx"), "seq_name"))) Tns <- transcripts(edb, columns = c("tx_id", "tx_name"), filter = list(SeqNameFilter("Y"), TxIdFilter("ENST00000435741"))) expect_identical(sort(colnames(mcols(Tns))), sort(c("tx_id", "tx_name"))) expect_true(all(Tns$seq_name == "Y")) expect_true(all(Tns$tx_id == "ENST00000435741")) ## Check the default ordering. Tns <- transcripts(edb, filter = list(TxBiotypeFilter("protein_coding"), SeqNameFilter("X")), return.type = "data.frame", columns = c("seq_name", listColumns(edb, "tx"))) expect_identical(order(Tns$seq_name, method = "radix"), 1:nrow(Tns)) }) test_that("promoters works", { res <- promoters(edb, filter = ~ genename == "ZBTB16") res_2 <- transcripts(edb, filter = GenenameFilter("ZBTB16")) expect_identical(length(res), length(res_2)) expect_true(all(width(res) == 2200)) }) test_that("transcriptsBy works", { ## Expect results on the forward strand to be ordered by tx_seq_start res <- transcriptsBy(edb, filter = ~ seq_name == "Y" & seq_strand == "-", by = "gene") fw <- res[[3]] expect_identical(order(start(fw)), 1:length(fw)) ## Expect results on the reverse strand to be ordered by -tx_seq_end res <- transcriptsBy(edb, filter = list(SeqNameFilter("Y"), SeqStrandFilter("-")), by = "gene") rv <- res[[3]] expect_identical(order(start(rv), decreasing = TRUE), 1:length(rv)) }) test_that("exons works", { Exns <- exons(edb, filter = SeqNameFilter("Y"), return.type = "DataFrame") expect_identical(sort(colnames(Exns)), sort(c(listColumns(edb, "exon"), "seq_name"))) ## Check correct ordering. Exns <- exons(edb, return.type = "data.frame", filter = SeqNameFilter(20:22)) expect_identical(order(Exns$seq_name, method = "radix"), 1:nrow(Exns)) }) test_that("exonsBy works", { ##ExnsBy <- exonsBy(edb, filter=list(SeqNameFilter("X")), by="tx") ExnsBy <- exonsBy(edb, filter = list(SeqNameFilter("Y")), by = "tx", columns = c("tx_name")) expect_identical(sort(colnames(mcols(ExnsBy[[1]]))), sort(c("exon_id", "exon_rank", "tx_name"))) suppressWarnings( ExnsBy <- exonsBy(edb, filter = list(SeqNameFilter("Y")), by = "tx", columns = c("tx_name"), use.names = TRUE) ) expect_identical(sort(colnames(mcols(ExnsBy[[1]]))), sort(c("exon_id", "exon_rank", "tx_name"))) ## Check what happens if we specify tx_id. ExnsBy <- exonsBy(edb, filter=list(SeqNameFilter("Y")), by="tx", columns=c("tx_id")) expect_identical(sort(colnames(mcols(ExnsBy[[1]]))), sort(c("exon_id", "exon_rank", "tx_id"))) ExnsBy <- exonsBy(edb, filter=list(SeqNameFilter("Y"), SeqStrandFilter("+")), by="gene") ## Check that ordering is on start on the forward strand. fw <- ExnsBy[[3]] expect_identical(order(start(fw)), 1:length(fw)) ## ExnsBy <- exonsBy(edb, filter=list(SeqNameFilter("Y"), SeqStrandFilter("-")), by="gene") ## Check that ordering is on start on the forward strand. rv <- ExnsBy[[3]] expect_identical(order(end(rv), decreasing = TRUE), 1:length(rv)) }) test_that("listGenebiotypes works", { GBT <- listGenebiotypes(edb) TBT <- listTxbiotypes(edb) }) ## test if we get the expected exceptions if we're not submitting ## correct filter objects test_that("Filter errors work in methods", { expect_error(genes(edb, filter="d")) expect_error(genes(edb, filter=list(SeqNameFilter("X"), "z"))) expect_error(transcripts(edb, filter="d")) expect_error(transcripts(edb, filter=list(SeqNameFilter("X"), "z"))) expect_error(exons(edb, filter="d")) expect_error(exons(edb, filter=list(SeqNameFilter("X"), "z"))) expect_error(exonsBy(edb, filter="d")) expect_error(exonsBy(edb, filter=list(SeqNameFilter("X"), "z"))) expect_error(transcriptsBy(edb, filter="d")) expect_error(transcriptsBy(edb, filter=list(SeqNameFilter("X"), "z"))) expect_error(transcripts(edb, filter = ~ other_filter == "b")) }) test_that("genes returns correct columns", { cols <- c("gene_name", "tx_id") Resu <- genes(edb, filter=SeqNameFilter("Y"), columns=cols, return.type = "data.frame") expect_identical(sort(c(cols, "seq_name", "gene_id")), sort(colnames(Resu))) Resu <- genes(edb, filter=SeqNameFilter("Y"), columns=cols, return.type = "DataFrame") expect_identical(sort(c(cols, "seq_name", "gene_id")), sort(colnames(Resu))) Resu <- genes(edb, filter=SeqNameFilter("Y"), columns=cols) expect_identical(sort(c(cols, "gene_id")), sort(colnames(mcols(Resu)))) }) test_that("transcripts return correct columns", { cols <- c("tx_id", "exon_id", "tx_biotype") Resu <- transcripts(edb, filter=SeqNameFilter("Y"), columns=cols, return.type = "data.frame") expect_identical(sort(c(cols, "seq_name")), sort(colnames(Resu))) Resu <- transcripts(edb, filter=SeqNameFilter("Y"), columns=cols, return.type = "DataFrame") expect_identical(sort(c(cols, "seq_name")), sort(colnames(Resu))) Resu <- transcripts(edb, filter=SeqNameFilter("Y"), columns=cols) expect_identical(sort(cols), sort(colnames(mcols(Resu)))) }) test_that("exons returns correct columns", { cols <- c("tx_id", "exon_id", "tx_biotype") Resu <- exons(edb, filter=SeqNameFilter("Y"), columns=cols, return.type = "data.frame") expect_identical(sort(c(cols, "seq_name")), sort(colnames(Resu))) Resu <- exons(edb, filter=SeqNameFilter("Y"), columns=cols, return.type = "DataFrame") expect_identical(sort(c(cols, "seq_name")), sort(colnames(Resu))) Resu <- exons(edb, filter=SeqNameFilter("Y"), columns=cols) expect_identical(sort(cols), sort(colnames(mcols(Resu)))) }) test_that("cdsBy works", { checkSingleTx <- function(tx, cds, do.plot=FALSE){ rownames(tx) <- tx$exon_id tx <- tx[cds$exon_id, ] ## cds start and end have to be within the correct range. expect_true(all(start(cds) >= min(tx$tx_cds_seq_start))) expect_true(all(end(cds) <= max(tx$tx_cds_seq_end))) ## For all except the first and the last we have to assume that ## exon_seq_start ## is equal to start of cds. expect_true(all(start(cds)[-1] == tx$exon_seq_start[-1])) expect_true(all(end(cds)[-nrow(tx)] == tx$exon_seq_end[-nrow(tx)])) ## just plotting the stuff... if(do.plot){ XL <- range(tx[, c("exon_seq_start", "exon_seq_end")]) YL <- c(0, 4) plot(3, 3, pch=NA, xlim=XL, ylim=YL, xlab="", yaxt="n", ylab="") ## plotting the "real" exons: rect(xleft=tx$exon_seq_start, xright=tx$exon_seq_end, ybottom=rep(0, nrow(tx)), ytop=rep(1, nrow(tx))) ## plotting the cds: rect(xleft=start(cds), xright=end(cds), ybottom=rep(1.2, nrow(tx)), ytop=rep(2.2, nrow(tx)), col="blue") } } ## Just checking if we get also tx_name cs <- cdsBy(edb, filter = SeqNameFilter("Y"), column="tx_name") expect_true(any(colnames(mcols(cs[[1]])) == "tx_name")) do.plot <- FALSE ## By tx cs <- cdsBy(edb, filter=list(SeqNameFilter("Y"), SeqStrandFilter("+"))) tx <- exonsBy(edb, filter=list(SeqNameFilter("Y"), SeqStrandFilter("+"))) ## Check for the first if it makes sense: whichTx <- names(cs)[1] whichCs <- cs[[1]] tx <- transcripts(edb, filter=TxIdFilter(whichTx), columns=c("tx_seq_start", "tx_seq_end", "tx_cds_seq_start", "tx_cds_seq_end", "exon_seq_start", "exon_seq_end", "exon_idx", "exon_id", "seq_strand"), return.type="data.frame") checkSingleTx(tx=tx, cds=whichCs, do.plot=do.plot) ## Next one: whichTx <- names(cs)[2] tx <- transcripts(edb, filter=TxIdFilter(whichTx), columns=c("tx_seq_start", "tx_seq_end", "tx_cds_seq_start", "tx_cds_seq_end", "exon_seq_start", "exon_seq_end", "exon_idx", "exon_id"), return.type="data.frame") checkSingleTx(tx=tx, cds=cs[[2]], do.plot=do.plot) ## Now for reverse strand: cs <- cdsBy(edb, filter=list(SeqNameFilter("Y"), SeqStrandFilter("-"))) whichTx <- names(cs)[1] whichCs <- cs[[1]] tx <- transcripts(edb, filter=TxIdFilter(whichTx), columns=c("tx_seq_start", "tx_seq_end", "tx_cds_seq_start", "tx_cds_seq_end", "exon_seq_start", "exon_seq_end", "exon_idx", "exon_id"), return.type="data.frame") ## order the guys by seq_start whichCs <- whichCs[order(start(whichCs))] checkSingleTx(tx=tx, cds=whichCs, do.plot=do.plot) ## Next one: whichTx <- names(cs)[2] whichCs <- cs[[2]] tx <- transcripts(edb, filter=TxIdFilter(whichTx), columns=c("tx_seq_start", "tx_seq_end", "tx_cds_seq_start", "tx_cds_seq_end", "exon_seq_start", "exon_seq_end", "exon_idx", "exon_id"), return.type="data.frame") ## order the guys by seq_start whichCs <- whichCs[order(start(whichCs))] checkSingleTx(tx=tx, cds=whichCs, do.plot=do.plot) ## Check adding columns Test <- cdsBy(edb, filter=list(SeqNameFilter("Y")), columns=c("gene_biotype", "gene_name")) }) test_that("cdsBy with gene works", { checkSingleGene <- function(whichCs, gene, do.plot=FALSE){ tx <- transcripts(edb, filter=GeneIdFilter(gene), columns=c("tx_seq_start", "tx_seq_end", "tx_cds_seq_start", "tx_cds_seq_end", "tx_id", "exon_id", "exon_seq_start", "exon_seq_end"), return.type="data.frame") XL <- range(tx[, c("tx_seq_start", "tx_seq_end")]) tx <- split(tx, f=tx$tx_id) if(do.plot){ ##XL <- range(c(start(whichCs), end(whichCs))) YL <- c(0, length(tx) + 1) plot(4, 4, pch=NA, xlim=XL, ylim=YL, yaxt="n", ylab="", xlab="") ## plot the txses for(i in 1:length(tx)){ current <- tx[[i]] rect(xleft=current$exon_seq_start, xright=current$exon_seq_end, ybottom=rep((i-1+0.1), nrow(current)), ytop=rep((i-0.1), nrow(current))) ## coding: rect(xleft = current$tx_cds_seq_start, xright = current$tx_cds_seq_end, ybottom = rep((i-1+0.1), nrow(current)), ytop = rep((i-0.1), nrow(current)), border = "blue") } rect(xleft=start(whichCs), xright=end(whichCs), ybottom=rep(length(tx)+0.1, length(whichCs)), ytop=rep(length(tx)+0.9, length(whichCs)), border="red") } } do.plot <- FALSE ## By gene. cs <- cdsBy(edb, filter=list(SeqNameFilter("Y"), SeqStrandFilter("+")), by="gene", columns=NULL) checkSingleGene(cs[[1]], gene=names(cs)[[1]], do.plot=do.plot) checkSingleGene(cs[[2]], gene=names(cs)[[2]], do.plot=do.plot) ## - strand cs <- cdsBy(edb, filter=list(SeqNameFilter("Y"), SeqStrandFilter("-")), by="gene", columns=NULL) checkSingleGene(cs[[1]], gene=names(cs)[[1]], do.plot=do.plot) checkSingleGene(cs[[2]], gene=names(cs)[[2]], do.plot=do.plot) ## looks good! cs2 <- cdsBy(edb, filter=list(SeqNameFilter("Y"), SeqStrandFilter("+")), by="gene", use.names=TRUE) }) test_that("UTRs work", { checkGeneUTRs <- function(f, t, c, tx, do.plot=FALSE){ if(any(strand(c) == "+")){ ## End of five UTR has to be smaller than any start of cds expect_true(max(end(f)) < min(start(c))) ## 3' expect_true(min(start(t)) > max(end(c))) }else{ ## 5' expect_true(min(start(f)) > max(end(c))) ## 3' expect_true(max(end(t)) < min(start(c))) } ## just plot... if(do.plot){ tx <- transcripts(edb, filter=TxIdFilter(tx), columns=c("exon_seq_start", "exon_seq_end"), return.type="data.frame") XL <- range(c(start(f), start(c), start(t), end(f), end(c), end(t))) YL <- c(0, 4) plot(4, 4, pch=NA, xlim=XL, ylim=YL, yaxt="n", ylab="", xlab="") ## five UTR rect(xleft=start(f), xright=end(f), ybottom=0.1, ytop=0.9, col="blue") ## cds rect(xleft=start(c), xright=end(c), ybottom=1.1, ytop=1.9) ## three UTR rect(xleft=start(t), xright=end(t), ybottom=2.1, ytop=2.9, col="red") ## all exons rect(xleft=tx$exon_seq_start, xright=tx$exon_seq_end, ybottom=3.1, ytop=3.9) } } ## check presence of tx_name fUTRs <- fiveUTRsByTranscript(edb, filter = TxIdFilter("ENST00000155093"), column = "tx_name") expect_true(any(colnames(mcols(fUTRs[[1]])) == "tx_name")) do.plot <- FALSE fUTRs <- fiveUTRsByTranscript(edb, filter = list(SeqNameFilter("Y"), SeqStrandFilter("+"))) tUTRs <- threeUTRsByTranscript(edb, filter = list(SeqNameFilter("Y"), SeqStrandFilter("+"))) cds <- cdsBy(edb, "tx", filter = list(SeqNameFilter("Y"), SeqStrandFilter("+"))) ## Check a TX: tx <- names(fUTRs)[1] checkGeneUTRs(fUTRs[[tx]], tUTRs[[tx]], cds[[tx]], tx = tx, do.plot = do.plot) tx <- names(fUTRs)[2] checkGeneUTRs(fUTRs[[tx]], tUTRs[[tx]], cds[[tx]], tx = tx, do.plot = do.plot) tx <- names(fUTRs)[3] checkGeneUTRs(fUTRs[[tx]], tUTRs[[tx]], cds[[tx]], tx = tx, do.plot = do.plot) ## Reverse strand fUTRs <- fiveUTRsByTranscript(edb, filter = list(SeqNameFilter("Y"), SeqStrandFilter("-"))) tUTRs <- threeUTRsByTranscript(edb, filter = list(SeqNameFilter("Y"), SeqStrandFilter("-"))) cds <- cdsBy(edb, "tx", filter = list(SeqNameFilter("Y"), SeqStrandFilter("-"))) ## Check a TX: tx <- names(fUTRs)[1] checkGeneUTRs(fUTRs[[tx]], tUTRs[[tx]], cds[[tx]], tx = tx, do.plot = do.plot) tx <- names(fUTRs)[2] checkGeneUTRs(fUTRs[[tx]], tUTRs[[tx]], cds[[tx]], tx = tx, do.plot = do.plot) tx <- names(fUTRs)[3] checkGeneUTRs(fUTRs[[tx]], tUTRs[[tx]], cds[[tx]], tx = tx, do.plot = do.plot) res_1 <- ensembldb:::getUTRsByTranscript(edb, what = "five", filter = TxIdFilter("ENST00000335953")) res_2 <- fiveUTRsByTranscript(edb, filter = TxIdFilter("ENST00000335953")) expect_identical(res_1, res_2) res_1 <- ensembldb:::getUTRsByTranscript(edb, what = "three", filter = TxIdFilter("ENST00000335953")) res_2 <- threeUTRsByTranscript(edb, filter = TxIdFilter("ENST00000335953")) expect_identical(res_1, res_2) }) test_that("lengthOf works", { system.time( lenY <- lengthOf(edb, "tx", filter=SeqNameFilter("Y")) ) ## Check what would happen if we do it ourselfs... system.time( lenY2 <- sum(width(reduce(exonsBy(edb, "tx", filter=SeqNameFilter("Y"))))) ) expect_identical(lenY, lenY2) ## Same for genes. system.time( lenY <- lengthOf(edb, "gene", filter= ~ seq_name == "Y") ) ## Check what would happen if we do it ourselfs... system.time( lenY2 <- sum(width(reduce(exonsBy(edb, "gene", filter=SeqNameFilter("Y"))))) ) expect_identical(lenY, lenY2) ## Just using the transcriptLengths res <- ensembldb:::.transcriptLengths(edb, filter = GenenameFilter("ZBTB16")) res_2 <- lengthOf(edb, "tx", filter = GenenameFilter("ZBTB16")) expect_identical(sort(res$tx_len), unname(sort(res_2))) ## also cds lengths etc. res <- ensembldb:::.transcriptLengths(edb, filter = GenenameFilter("ZBTB16"), with.cds_len = TRUE, with.utr5_len = TRUE, with.utr3_len = TRUE) expect_identical(colnames(res), c("tx_id", "gene_id", "nexon", "tx_len", "cds_len", "utr5_len", "utr3_len")) tx <- transcripts(edb, filter = list(GenenameFilter("ZBTB16"), TxBiotypeFilter("protein_coding"))) expect_true(all(!is.na(res[names(tx), "cds_len"]))) expect_equal(unname(res[names(tx), "tx_len"]), unname(rowSums(res[names(tx), c("utr5_len", "cds_len", "utr3_len")]))) }) ####============================================================ ## ExonRankFilter ## ####------------------------------------------------------------ test_that("ExonRankFilter works with methods", { txs <- transcripts(edb, columns=c("exon_id", "exon_idx"), filter=SeqNameFilter(c("Y"))) txs <- txs[order(names(txs))] txs2 <- transcripts(edb, columns=c("exon_id"), filter=list(SeqNameFilter(c("Y")), ExonRankFilter(3))) txs2 <- txs[order(names(txs2))] ## hm, that's weird somehow. exns <- exons(edb, columns=c("tx_id", "exon_idx"), filter=list(SeqNameFilter("Y"), ExonRankFilter(3))) expect_true(all(exns$exon_idx == 3)) exns <- exons(edb, columns=c("tx_id", "exon_idx"), filter=list(SeqNameFilter("Y"), ExonRankFilter(3, condition="<"))) expect_true(all(exns$exon_idx < 3)) }) test_that("buildQuery and getWhat works", { library(RSQLite) Q <- buildQuery(edb, columns = c("gene_name", "gene_id")) expect_identical(Q, "select distinct gene.gene_name,gene.gene_id from gene") gf <- GeneIdFilter("ENSG00000000005") Q <- buildQuery(edb, columns = c("gene_name", "exon_idx"), filter = AnnotationFilterList(gf)) res <- dbGetQuery(dbconn(edb), Q) Q_2 <- paste0("select * from gene join tx on (gene.gene_id=tx.gene_id)", " join tx2exon on (tx.tx_id=tx2exon.tx_id) where", " gene.gene_id = 'ENSG00000000005'") res_2 <- dbGetQuery(dbconn(edb), Q_2) expect_identical(res, unique(res_2[, colnames(res)])) res_3 <- ensembldb:::getWhat(edb, columns = c("gene_name", "exon_idx"), filter = AnnotationFilterList(gf)) expect_identical(res_3, unique(res_2[, colnames(res_3)])) }) test_that("toSaf works", { txs <- transcriptsBy(edb, filter = GenenameFilter("ZBTB16")) saf <- ensembldb:::.toSaf(txs) expect_identical(nrow(saf), sum(lengths(txs))) saf2 <- toSAF(txs) expect_identical(saf2, saf) }) test_that("disjointExons works", { dje <- disjointExons(edb, filter = GenenameFilter("ZBTB16")) exns <- exons(edb, filter = GenenameFilter("ZBTB16")) ## Expect that dje is shorter than exns, since overlapping exon parts have ## been fused. expect_true(length(dje) < length(exns)) dje <- disjointExons(edb, filter = GenenameFilter("ZBTB16"), aggregateGenes = TRUE) expect_true(length(dje) < length(exns)) }) test_that("getGeneRegionTrackForGviz works", { res <- getGeneRegionTrackForGviz(edb, filter = GenenameFilter("ZBTB16")) expect_true(all(res$feature %in% c("protein_coding", "utr5", "utr3"))) ## Do the same without a filter: ## LLLLL res2 <- getGeneRegionTrackForGviz(edb, chromosome = "11", start = 113930000, end = 113935000) expect_true(all(res2$symbol == "ZBTB16")) }) test_that("filter columns are correctly added in methods", { filtList <- AnnotationFilterList(GenenameFilter("a"), ExonStartFilter(123), SymbolFilter("b"), TxIdFilter("c")) res <- ensembldb:::addFilterColumns(cols = c("a"), filter = filtList, edb = edb) expect_identical(res, c("a", "gene_name", "exon_seq_start", "symbol", "tx_id")) res <- ensembldb:::addFilterColumns(filter = filtList, edb = edb) expect_identical(res, c("gene_name", "exon_seq_start", "symbol", "tx_id")) ## New filts filtList <- AnnotationFilterList(GenenameFilter("a"), ExonStartFilter(123), SymbolFilter("b"), TxIdFilter("c")) res <- ensembldb:::addFilterColumns(cols = c("a"), filter = filtList, edb = edb) expect_identical(res, c("a", "gene_name", "exon_seq_start", "symbol", "tx_id")) res <- ensembldb:::addFilterColumns(filter = filtList, edb = edb) expect_identical(res, c("gene_name", "exon_seq_start", "symbol", "tx_id")) }) test_that("supportedFilters works", { res <- ensembldb:::.supportedFilters(edb) if (!hasProteinData(edb)) expect_equal(nrow(res), 19) else expect_equal(nrow(res), 24) res <- supportedFilters(edb) if (!hasProteinData(edb)) expect_equal(nrow(res), 19) else expect_equal(nrow(res), 24) }) ## Here we check if we fetch what we expect from the database. test_that("GRangesFilter works in queries", { do.plot <- FALSE zbtb <- genes(edb, filter = GenenameFilter("ZBTB16")) txs <- transcripts(edb, filter = GenenameFilter("ZBTB16")) ## Now use the GRangesFilter to fetch all tx txs2 <- transcripts(edb, filter = GRangesFilter(zbtb)) expect_equal(txs$tx_id, txs2$tx_id) ## Exons: exs <- exons(edb, filter = GenenameFilter("ZBTB16")) exs2 <- exons(edb, filter = GRangesFilter(zbtb)) expect_equal(exs$exon_id, exs2$exon_id) ## Now check the filter with "overlapping". intr <- GRanges("11", ranges = IRanges(114000000, 114000050), strand = "+") gns <- genes(edb, filter = GRangesFilter(intr, type = "any")) expect_equal(gns$gene_name, "ZBTB16") ## txs <- transcripts(edb, filter = GRangesFilter(intr, type = "any")) expect_equal(sort(txs$tx_id), sort(c("ENST00000335953", "ENST00000541602", "ENST00000392996", "ENST00000539918"))) if(do.plot){ plot(3, 3, pch=NA, xlim=c(start(zbtb), end(zbtb)), ylim=c(0, length(txs2))) rect(xleft=start(intr), xright=end(intr), ybottom=0, ytop=length(txs2), col="red", border="red") for(i in 1:length(txs2)){ current <- txs2[i] rect(xleft=start(current), xright=end(current), ybottom=i-0.975, ytop=i-0.125, border="grey") text(start(current), y=i-0.5,pos=4, cex=0.75, labels=current$tx_id) } ## OK, that' OK. } ## OK, now for a GRangesFilter with more than one GRanges. ir2 <- IRanges(start=c(2654890, 2709520, 28111770), end=c(2654900, 2709550, 28111790)) grf2 <- GRangesFilter(GRanges(rep("Y", length(ir2)), ir2), type = "any") Test <- transcripts(edb, filter = grf2) expect_equal(names(Test), c("ENST00000383070", "ENST00000250784", "ENST00000598545")) }) test_that("show works", { res <- capture.output(show(edb)) expect_equal(res[1], "EnsDb for Ensembl:") expect_equal(res[9], "|ensembl_version: 75") }) test_that("organism method works", { res <- organism(edb) expect_equal(res, "Homo sapiens") }) test_that("metadata method works", { res <- metadata(edb) expect_equal(res, dbGetQuery(dbconn(edb), "select * from metadata")) }) test_that("ensemblVersion works", { expect_equal(ensemblVersion(edb), "75") }) test_that("getMetadataValue works", { expect_error(ensembldb:::getMetadataValue(edb)) }) test_that("seqinfo and seqlevels work", { si <- seqinfo(edb) expect_true(is(si, "Seqinfo")) sl <- seqlevels(edb) library(RSQLite) chrs <- dbGetQuery(dbconn(edb), "select seq_name from chromosome")[, 1] expect_true(all(sl %in% chrs)) expect_true(all(seqlevels(si) %in% chrs)) }) test_that("ensVersionFromSourceUrl works", { res <- ensembldb:::.ensVersionFromSourceUrl( "ftp://ftp.ensembl.org/release-85/gtf") expect_equal(res, 85) }) test_that("listBiotypes works", { res <- listTxbiotypes(edb) library(RSQLite) res_2 <- dbGetQuery(dbconn(edb), "select distinct tx_biotype from tx")[, 1] expect_true(all(res %in% res_2)) res <- listGenebiotypes(edb) res_2 <- dbGetQuery(dbconn(edb), "select distinct gene_biotype from gene")[, 1] expect_true(all(res %in% res_2)) }) test_that("listTables works", { res <- listTables(edb) schema_version <- ensembldb:::dbSchemaVersion(edb) if (!hasProteinData(edb)) { expect_equal(names(res), names(ensembldb:::.ensdb_tables(schema_version))) } else { expect_equal( sort(names(res)), sort(unique(c(names(ensembldb:::.ensdb_tables(schema_version)), names(ensembldb:::.ensdb_protein_tables( schema_version)))))) } ## Repeat with deleting the cached tables edb@tables <- list() res <- listTables(edb) if (!hasProteinData(edb)) { expect_equal(names(res), names(ensembldb:::.ensdb_tables(schema_version))) } else { expect_equal( sort(names(res)), sort(unique(c(names(ensembldb:::.ensdb_tables(schema_version)), names(ensembldb:::.ensdb_protein_tables( schema_version)))))) } }) test_that("listColumns works", { res <- listColumns(edb, table = "gene") expect_equal(res, c(ensembldb:::.ensdb_tables(ensembldb:::dbSchemaVersion(dbconn(edb)))$gene, "symbol")) res <- listColumns(edb, table = "tx") expect_equal(res, c(ensembldb:::.ensdb_tables(ensembldb:::dbSchemaVersion(dbconn(edb)))$tx, "tx_name")) res <- listColumns(edb, table = "exon") expect_equal(res, c(ensembldb:::.ensdb_tables(ensembldb:::dbSchemaVersion(dbconn(edb)))$exon)) res <- listColumns(edb, table = "chromosome") expect_equal(res, c(ensembldb:::.ensdb_tables(ensembldb:::dbSchemaVersion(dbconn(edb)))$chromosome)) res <- listColumns(edb, table = "tx2exon") expect_equal(res, c(ensembldb:::.ensdb_tables(ensembldb:::dbSchemaVersion(dbconn(edb)))$tx2exon)) if (hasProteinData(edb)) { res <- listColumns(edb, table = "protein") expect_equal(res, ensembldb:::.ensdb_protein_tables(ensembldb:::dbSchemaVersion(dbconn(edb)))$protein) res <- listColumns(edb, table = "uniprot") expect_equal(res, ensembldb:::.ensdb_protein_tables(ensembldb:::dbSchemaVersion(dbconn(edb)))$uniprot) res <- listColumns(edb, table = "protein_domain") expect_equal(res, ensembldb:::.ensdb_protein_tables(ensembldb:::dbSchemaVersion(dbconn(edb)))$protein_domain) } ## Repeat with deleting the cached tables edb@tables <- list() res <- listColumns(edb, table = "gene") expect_equal(res, c(ensembldb:::.ensdb_tables(ensembldb:::dbSchemaVersion(dbconn(edb)))$gene, "symbol")) res <- listColumns(edb, table = "tx") expect_equal(res, c(ensembldb:::.ensdb_tables(ensembldb:::dbSchemaVersion(dbconn(edb)))$tx, "tx_name")) res <- listColumns(edb, table = "exon") expect_equal(res, c(ensembldb:::.ensdb_tables(ensembldb:::dbSchemaVersion(dbconn(edb)))$exon)) res <- listColumns(edb, table = "chromosome") expect_equal(res, c(ensembldb:::.ensdb_tables(ensembldb:::dbSchemaVersion(dbconn(edb)))$chromosome)) res <- listColumns(edb, table = "tx2exon") expect_equal(res, c(ensembldb:::.ensdb_tables(ensembldb:::dbSchemaVersion(dbconn(edb)))$tx2exon)) if (hasProteinData(edb)) { res <- listColumns(edb, table = "protein") expect_equal(res, ensembldb:::.ensdb_protein_tables(ensembldb:::dbSchemaVersion(dbconn(edb)))$protein) res <- listColumns(edb, table = "uniprot") expect_equal(res, ensembldb:::.ensdb_protein_tables(ensembldb:::dbSchemaVersion(dbconn(edb)))$uniprot) res <- listColumns(edb, table = "protein_domain") expect_equal(res, ensembldb:::.ensdb_protein_tables(ensembldb:::dbSchemaVersion(dbconn(edb)))$protein_domain) } }) test_that("cleanColumns works", { cols <- c("gene_id", "tx_id", "tx_name") res <- ensembldb:::cleanColumns(edb, cols) expect_equal(cols, res) cols <- c(cols, "not there") suppressWarnings( res <- ensembldb:::cleanColumns(edb, cols) ) expect_equal(cols[1:3], res) cols <- c("gene_id", "protein_id", "tx_id", "protein_sequence") suppressWarnings( res <- ensembldb:::cleanColumns(edb, cols) ) if (hasProteinData(edb)) { expect_equal(res, cols) } else { expect_equal(res, cols[c(1, 3)]) } ## with full names: cols <- c("gene.gene_id", "protein.protein_id", "tx.tx_id", "protein.protein_sequence") suppressWarnings( res <- ensembldb:::cleanColumns(edb, cols) ) if (hasProteinData(edb)) { expect_equal(res, cols) } else { expect_equal(res, cols[c(1, 3)]) } }) test_that("tablesForColumns works", { expect_error(ensembldb:::tablesForColumns(edb)) res <- ensembldb:::tablesForColumns(edb, columns = "tx_id") if (hasProteinData(edb)) expect_equal(res, c("tx", "tx2exon", "protein")) else expect_equal(res, c("tx", "tx2exon")) res <- ensembldb:::tablesForColumns(edb, columns = "seq_name") expect_equal(res, c("gene", "chromosome")) if (hasProteinData(edb)) { res <- ensembldb:::tablesForColumns(edb, columns = "protein_id") expect_equal(res, c("protein", "uniprot", "protein_domain")) } }) test_that("tablesByDegree works", { res <- ensembldb:::tablesByDegree(edb, tab = c("chromosome", "gene", "tx")) expect_equal(res, c("gene", "tx", "chromosome")) }) test_that("updateEnsDb works", { edb2 <- updateEnsDb(edb) expect_equal(edb2@tables, edb@tables) expect_true(.hasSlot(edb2, ".properties")) }) test_that("properties work", { origProps <- ensembldb:::properties(edb) expect_equal(ensembldb:::getProperty(edb, "foo"), NA) expect_error(ensembldb:::setProperty(edb, "foo")) edb <- ensembldb:::setProperty(edb, foo="bar") expect_equal(ensembldb:::getProperty(edb, "foo"), "bar") expect_equal(length(ensembldb:::properties(edb)), length(origProps) + 1) expect_true(any(names(ensembldb:::properties(edb)) == "foo")) edb <- ensembldb:::dropProperty(edb, "foo") expect_true(all(names(ensembldb:::properties(edb)) != "foo")) }) ## Compare the results for genes call with and without ordering in R test_that("ordering works in genes calls", { orig <- ensembldb:::orderResultsInR(edb) ensembldb:::orderResultsInR(edb) <- FALSE res_sql <- genes(edb, return.type = "data.frame") ensembldb:::orderResultsInR(edb) <- TRUE res_r <- genes(edb, return.type = "data.frame") rownames(res_sql) <- NULL rownames(res_r) <- NULL expect_equal(res_sql, res_r) ## Join tx table ensembldb:::orderResultsInR(edb) <- FALSE res_sql <- genes(edb, columns = c("gene_id", "tx_id"), return.type = "data.frame") ensembldb:::orderResultsInR(edb) <- TRUE res_r <- genes(edb, columns = c("gene_id", "tx_id"), return.type = "data.frame") rownames(res_sql) <- NULL rownames(res_r) <- NULL expect_equal(res_sql, res_r) ## Join tx table and use an SeqNameFilter ensembldb:::orderResultsInR(edb) <- FALSE res_sql <- genes(edb, columns = c("gene_id", "tx_id"), filter = SeqNameFilter("Y")) ensembldb:::orderResultsInR(edb) <- TRUE res_r <- genes(edb, columns = c("gene_id", "tx_id"), filter = SeqNameFilter("Y")) expect_equal(res_sql, res_r) ensembldb:::orderResultsInR(edb) <- orig }) test_that("transcriptLengths works",{ ## With filter. daFilt <- SeqNameFilter("Y") allTxY <- transcripts(edb, filter = daFilt) txLenY <- transcriptLengths(edb, filter = daFilt) expect_equal(names(allTxY), txLenY$tx_id) rownames(txLenY) <- txLenY$tx_id ## Check if lengths are OK: txLenY2 <- lengthOf(edb, "tx", filter = daFilt) expect_equal(unname(txLenY2[txLenY$tx_id]), txLenY$tx_len) ## Include the cds, 3' and 5' UTR txLenY <- transcriptLengths(edb, with.cds_len = TRUE, with.utr5_len = TRUE, with.utr3_len = TRUE, filter=daFilt) ## sum of 5' CDS and 3' has to match tx_len: txLen <- rowSums(txLenY[, c("cds_len", "utr5_len", "utr3_len")]) expect_equal(txLenY[txLenY$cds_len > 0, "tx_len"], unname(txLen[txLenY$cds_len > 0])) ## just to be sure... expect_equal(txLenY[txLenY$utr3_len > 0, "tx_len"], unname(txLen[txLenY$utr3_len > 0])) ## Seems to be OK. ## Next check the 5' UTR lengths: that also verifies the fiveUTR call. futr <- fiveUTRsByTranscript(edb, filter = daFilt) futrLen <- sum(width(futr)) rownames(txLenY) <- txLenY$tx_id expect_equal(unname(futrLen), txLenY[names(futrLen), "utr5_len"]) ## 3' tutr <- threeUTRsByTranscript(edb, filter=daFilt) tutrLen <- sum(width(tutr)) expect_equal(unname(tutrLen), txLenY[names(tutrLen), "utr3_len"]) }) test_that("transcriptsByOverlaps works", { ir2 <- IRanges(start = c(2654890, 2709520, 28111770), end = c(2654900, 2709550, 28111790)) gr2 <- GRanges(rep("Y", length(ir2)), ir2) grf2 <- GRangesFilter(gr2, type = "any") Test <- transcripts(edb, filter = grf2) Test2 <- transcriptsByOverlaps(edb, gr2) expect_equal(names(Test), names(Test2)) ## on one strand. gr2 <- GRanges(rep("Y", length(ir2)), ir2, strand = rep("-", length(ir2))) grf2 <- GRangesFilter(gr2, type = "any") Test <- transcripts(edb, filter = grf2) Test2 <- transcriptsByOverlaps(edb, gr2) expect_equal(names(Test), names(Test2)) ## Combine with filter... gr2 <- GRanges(rep("Y", length(ir2)), ir2) Test3 <- transcriptsByOverlaps(edb, gr2, filter = SeqStrandFilter("-")) expect_equal(names(Test), names(Test3)) }) test_that("exonsByOverlaps works", { ir2 <- IRanges(start=c(2654890, 2709520, 28111770), end=c(2654900, 2709550, 28111790)) gr2 <- GRanges(rep("Y", length(ir2)), ir2) grf2 <- GRangesFilter(gr2, type = "any") Test <- exons(edb, filter = grf2) Test2 <- exonsByOverlaps(edb, gr2) expect_equal(names(Test), names(Test2)) ## on one strand. gr2 <- GRanges(rep("Y", length(ir2)), ir2, strand=rep("-", length(ir2))) grf2 <- GRangesFilter(gr2, type = "any") Test <- exons(edb, filter = grf2) Test2 <- exonsByOverlaps(edb, gr2) expect_equal(names(Test), names(Test2)) ## Combine with filter... gr2 <- GRanges(rep("Y", length(ir2)), ir2) Test3 <- exonsByOverlaps(edb, gr2, filter=SeqStrandFilter("-")) expect_equal(names(Test), names(Test3)) }) test_that("methods work with global filter", { g_f <- SeqNameFilter(18) edb_2 <- ensembldb:::.addFilter(edb, g_f) ## gns gns <- genes(edb_2) expect_equal(gns, genes(edb, filter = g_f)) edb_2 <- ensembldb:::.addFilter(edb_2, TxBiotypeFilter("protein_coding")) gns_2 <- genes(edb_2) expect_true(all(seqlevels(gns_2) == "18")) expect_true(length(gns) > length(gns_2)) ## Combine with additional filter: gns_2 <- genes(edb_2, filter = SeqStrandFilter("+")) expect_true(all(as.character(strand(gns_2)) == "+")) gns <- genes(edb_2, filter = GenenameFilter("ZBTB16")) expect_true(length(gns) == 0) gns <- genes(edb_2, filter = GenenameFilter("BCL2")) expect_true(all(gns$symbol == "BCL2")) ## transcripts txs <- transcripts(edb_2, filter = ~ genename == "BCL2") expect_true(all(txs$genename == "BCL2")) expect_true(all(txs$tx_biotype == "protein_coding")) ## exonsBy exs <- exonsBy(edb_2, "gene") }) ensembldb/tests/testthat/test_Protein-related-tests.R0000644000175400017540000002673013175714743024141 0ustar00biocbuildbiocbuild ############################################################ ## Getting protein data in other methods. test_that("genes works with proteins", { if (hasProteinData(edb)) { res <- genes(edb, columns = c("gene_name", "gene_id", "protein_id", "uniprot_id", "tx_id", "tx_biotype"), filter = GenenameFilter("ZBTB16"), return.type = "data.frame") ## have a 1:n mapping of protein_id to uniprot id: expect_true(length(unique(res$protein_id)) < nrow(res)) expect_equal(colnames(res), c("gene_name", "gene_id", "protein_id", "uniprot_id", "tx_id", "tx_biotype")) ## All protein_coding have an uniprot_id expect_true(all(!is.na(res[res$tx_biotype == "protein_coding", "uniprot_id"]))) ## combine with cdsBy: cds <- cdsBy(edb, columns = c("tx_biotype", "protein_id"), filter = GenenameFilter("ZBTB16")) codingTx <- unique(res[!is.na(res$protein_id), "tx_id"]) expect_equal(sort(names(cds)), sort(codingTx)) ## Next one fetching also protein domain data. res <- genes(edb, columns = c("gene_name", "tx_id", "protein_id", "protein_domain_id"), filter = GenenameFilter("ZBTB16"), return.type = "data.frame") expect_equal(colnames(res), c("gene_name", "tx_id", "protein_id", "protein_domain_id", "gene_id")) expect_true(nrow(res) > length(unique(res$protein_id))) expect_true(nrow(res) > length(unique(res$tx_id))) } }) test_that("transcripts works with proteins", { if (hasProteinData(edb)) { res <- transcripts(edb, columns = c("tx_biotype", "protein_id", "uniprot_id"), filter = TxIdFilter("ENST00000335953"), return.type = "data.frame") ## 1:1 mapping for tx_id <-> protein_id expect_true(nrow(unique(res[, c("tx_id", "protein_id")])) == 1) ## Mapping tx_id -> uniprot_id is (0,1):n expect_true(nrow(res) > length(unique(res$tx_id))) ## Add protein domains. res <- transcripts(edb, columns = c("tx_biotype", "protein_id", "uniprot_id", "protein_domain_id"), filter = TxIdFilter("ENST00000335953"), return.type = "data.frame") resL <- split(res, f = res$uniprot_id) ## All have the same protein domains: resM <- do.call(rbind, lapply(resL, function(z) z$protein_domain_id)) expect_equal(nrow(unique(resM)), 1) } }) ## exons test_that("exons works with proteins", { if (hasProteinData(edb)) { ## Check if a call that includes a protein_id returns same data than one ## without. exns <- exons(edb, filter = GenenameFilter("BCL2L11"), return.type = "data.frame") exns_2 <- exons(edb, filter = GenenameFilter("BCL2L11"), return.type = "data.frame", columns = c("exon_id", "protein_id")) expect_equal(sort(unique(exns$exon_id)), sort(unique(exns_2$exon_id))) ## ZBTB16 exns <- exons(edb, filter = GenenameFilter("ZBTB16"), return.type = "data.frame") exns_2 <- exons(edb, filter = GenenameFilter("ZBTB16"), return.type = "data.frame", columns = c("exon_id", "protein_id")) expect_equal(sort(unique(exns$exon_id)), sort(unique(exns_2$exon_id))) } }) ## exonsBy test_that("exonsBy works with proteins", { if (hasProteinData(edb)) { exns <- exonsBy(edb, filter = GenenameFilter("ZBTB16"), columns = "tx_biotype") exns_2 <- exonsBy(edb, filter = GenenameFilter("ZBTB16"), columns = c("protein_id", "tx_biotype")) expect_equal(names(exns), names(exns_2)) exns <- unlist(exns) exns_2 <- unlist(exns_2) expect_true(any(is.na(exns_2$protein_id))) expect_equal(exns$exon_id, exns_2$exon_id) } }) ## transcriptsBy test_that("transcriptsBy works with proteins", { if (hasProteinData(edb)) { txs <- transcriptsBy(edb, filter = GenenameFilter("ZBTB16"), columns = "gene_biotype") txs_2 <- transcriptsBy(edb, filter = GenenameFilter("ZBTB16"), columns = c("protein_id", "gene_biotype")) expect_equal(names(txs), names(txs_2)) txs <- unlist(txs) txs_2 <- unlist(txs_2) expect_true(any(is.na(txs_2$protein_id))) expect_equal(start(txs), start(txs_2)) } }) ## cdsBy test_that("cdsBy works with proteins", { if (hasProteinData(edb)) { cds <- cdsBy(edb, filter = GenenameFilter("ZBTB16"), columns = "gene_biotype") cds_2 <- cdsBy(edb, filter = GenenameFilter("ZBTB16"), columns = c("protein_id", "gene_biotype")) expect_equal(names(cds), names(cds_2)) cds <- unlist(cds) cds_2 <- unlist(cds_2) expect_true(all(!is.na(cds_2$protein_id))) expect_equal(start(cds), start(cds_2)) } }) ## fiveUTRsByTranscript test_that("fiveUTRsByTranscript works with proteins", { if (hasProteinData(edb)) { utrs <- fiveUTRsByTranscript(edb, filter = GenenameFilter("ZBTB16"), columns = "tx_biotype") utrs_2 <- fiveUTRsByTranscript(edb, filter = GenenameFilter("ZBTB16"), columns = c("protein_id", "gene_biotype")) expect_equal(names(utrs), names(utrs_2)) utrs <- unlist(utrs) utrs_2 <- unlist(utrs_2) expect_true(all(!is.na(utrs_2$protein_id))) expect_equal(start(utrs), start(utrs_2)) } }) test_that("genes works with protein filters", { ## o ProteinIdFilter pif <- ProteinIdFilter("ENSP00000376721") if (hasProteinData(edb)) { gns <- genes(edb, filter = pif, return.type = "data.frame") expect_equal(gns$gene_name, "ZBTB16") } ## o UniprotFilter uif <- UniprotFilter("Q71UL7_HUMAN") if (hasProteinData(edb)) { gns <- genes(edb, filter = uif, return.type = "data.frame", columns = c("protein_id", "gene_name", "tx_id")) expect_true("ENSP00000376721" %in% gns$protein_id) expect_true(nrow(gns) == 2) } ## o ProtDomIdFilter pdif <- ProtDomIdFilter("PF00096") if (hasProteinData(edb)) { gns <- genes(edb, filter = list(pdif, GenenameFilter("ZBTB%", "startsWith")), return.type = "data.frame", column = c("gene_name", "gene_biotype")) expect_true(all(gns$gene_biotype == "protein_coding")) } }) test_that("proteins works", { if (hasProteinData(edb)) { ## Check return type. prts_DF <- proteins(edb, filter = GenenameFilter("ZBTB16")) expect_true(is(prts_DF, "DataFrame")) prts_df <- proteins(edb, filter = GenenameFilter("ZBTB16"), return.type = "data.frame") expect_true(is(prts_df, "data.frame")) prts_aa <- proteins(edb, filter = GenenameFilter("ZBTB16"), return.type = "AAStringSet") expect_true(is(prts_aa, "AAStringSet")) ## Check content. library(RSQLite) res_q <- dbGetQuery( dbconn(edb), paste0("select tx.tx_id, protein_id, gene_name from ", "protein left outer join tx on (protein.tx_id=", "tx.tx_id) join gene on (gene.gene_id=", "tx.gene_id) where gene_name = 'ZBTB16'")) expect_equal(res_q$tx_id, prts_df$tx_id) expect_equal(res_q$protein_id, prts_df$protein_id) expect_equal(prts_df$protein_id, names(prts_aa)) ## Add protein domain information to the proteins. prts_df <- proteins(edb, filter = ProteinIdFilter(c("ENSP00000338157", "ENSP00000443013")), columns = c("protein_id", "protein_domain_id", "uniprot_id"), return.type = "data.frame") ## Check if we have all data that we expect: uniprots <- dbGetQuery(dbconn(edb), paste0("select uniprot_id from uniprot where", " protein_id in ('ENSP00000338157',", "'ENSP00000443013')"))$uniprot_id expect_true(all(uniprots %in% prts_df$uniprot_id)) protdoms <- dbGetQuery(dbconn(edb), paste0("select protein_domain_id from", " protein_domain where protein_id", " in ('ENSP00000338157',", "'ENSP00000443013')"))$protein_domain_id expect_true(all(protdoms %in% prts_df$protein_domain_id)) } }) test_that("proteins works with uniprot mapping", { ## ZBTB16 and the mapping of 1 protein to two Uniprot IDs, one with DIRECT ## mapping type. if (hasProteinData(edb)) { prts <- proteins(edb, filter = GenenameFilter("ZBTB16"), columns = c("uniprot_id", "uniprot_db", "uniprot_mapping_type"), return.type = "DataFrame") ## NOTE: this is true for Ensembl 86, but might not be the case for 75! ## Here we have the n:m mapping: ## Q05516 is assigned to ENSP00000338157 and ENSP00000376721, ## Each of the two proteins is however also annotated to a second ## Uniprot ID: A0A024R3C6 ## If we use the UniprotMappingTypeFilter with only DIRECT mapping ## we expect to reduce it to the 1:n mapping between Uniprot and Ensembl prts <- proteins(edb, filter = list(GenenameFilter("ZBTB16"), UniprotMappingTypeFilter("DIRECT")), columns = c("uniprot_id", "uniprot_db", "uniprot_mapping_type"), return.type = "DataFrame") expect_true(all(prts$uniprot_mapping_type == "DIRECT")) ## Check the UniprotDbFilter prts <- proteins(edb, filter = list(GenenameFilter("ZBTB16"), UniprotDbFilter("SPTREMBL")), columns = c("uniprot_id", "uniprot_db", "protein_id"), return.type = "DataFrame") expect_true(all(prts$uniprot_db == "SPTREMBL")) } }) test_that("isProteinFilter works", { ## TRUE expect_true(ensembldb:::isProteinFilter(ProteinIdFilter("a"))) expect_true(ensembldb:::isProteinFilter(UniprotFilter("a"))) expect_true(ensembldb:::isProteinFilter(ProtDomIdFilter("a"))) expect_true(ensembldb:::isProteinFilter(UniprotDbFilter("a"))) expect_true(ensembldb:::isProteinFilter(UniprotMappingTypeFilter("a"))) ## FALSE expect_true(!ensembldb:::isProteinFilter(GeneIdFilter("a"))) expect_true(!ensembldb:::isProteinFilter(SymbolFilter("a"))) expect_true(!ensembldb:::isProteinFilter(3)) expect_true(!ensembldb:::isProteinFilter("dfdf")) }) ensembldb/tests/testthat/test_SymbolFilter.R0000644000175400017540000000771313175714743022356 0ustar00biocbuildbiocbuild test_that("SymbolFilter works for gene", { sf <- SymbolFilter("SKA2") gnf <- GenenameFilter("SKA2") returnFilterColumns(edb) <- FALSE gns_sf <- genes(edb, filter = sf) gns_gnf <- genes(edb, filter = gnf) expect_equal(gns_sf, gns_gnf) returnFilterColumns(edb) <- TRUE gns_sf <- genes(edb, filter=sf) expect_equal(gns_sf$gene_name, gns_sf$symbol) ## Hm, what happens if we use both? gns <- genes(edb, filter=list(sf, gnf)) ## All fine. }) test_that("SymbolFilter works for tx", { sf <- SymbolFilter("SKA2") gnf <- GenenameFilter("SKA2") returnFilterColumns(edb) <- FALSE tx_sf <- transcripts(edb, filter=sf) tx_gnf <- transcripts(edb, filter=gnf) expect_equal(tx_sf, tx_gnf) returnFilterColumns(edb) <- TRUE tx_sf <- transcripts(edb, filter=sf, columns=c("gene_name")) expect_equal(tx_sf$gene_name, tx_sf$symbol) }) test_that("SymbolFilter works for exons", { sf <- SymbolFilter("SKA2") gnf <- GenenameFilter("SKA2") returnFilterColumns(edb) <- FALSE ex_sf <- exons(edb, filter=sf) ex_gnf <- exons(edb, filter=gnf) expect_equal(ex_sf, ex_gnf) returnFilterColumns(edb) <- TRUE ex_sf <- exons(edb, filter=sf, columns=c("gene_name")) expect_equal(ex_sf$gene_name, ex_sf$symbol) }) test_that("SymbolFilter works", { sf <- SymbolFilter("SKA2") res <- genes(edb, filter = sf, return.type = "data.frame") expect_equal(res$gene_id, "ENSG00000182628") ## We need now also a column "symbol"! expect_equal(res$symbol, res$gene_name) ## Asking explicitely for symbol res <- genes(edb, filter = sf, return.type = "data.frame", columns = c("symbol", "gene_id")) expect_equal(colnames(res), c("symbol", "gene_id")) ## Some more stuff, also shuffling the order. res <- genes(edb, filter = sf, return.type = "data.frame", columns = c("gene_name", "symbol", "gene_id")) expect_equal(colnames(res), c("gene_name", "symbol", "gene_id")) res <- genes(edb, filter = sf, return.type = "data.frame", columns = c("gene_id", "gene_name", "symbol")) expect_equal(colnames(res), c("gene_id", "gene_name", "symbol")) ## And with GRanges as return type. res <- genes(edb, filter = sf, return.type = "GRanges", columns = c("gene_id", "gene_name", "symbol")) expect_equal(colnames(mcols(res)), c("gene_id", "gene_name", "symbol")) ## Combine tx_name and symbol res <- genes(edb, filter = sf, columns = c("tx_name", "symbol"), return.type = "data.frame") expect_equal(colnames(res), c("tx_name", "symbol", "gene_id")) expect_true(all(res$symbol == "SKA2")) ## Test for transcripts res <- transcripts(edb, filter=sf, return.type="data.frame") expect_true(all(res$symbol == "SKA2")) res <- transcripts(edb, filter = sf, return.type = "data.frame", columns = c("symbol", "tx_id", "gene_name")) expect_true(all(res$symbol == "SKA2")) expect_equal(res$symbol, res$gene_name) expect_equal(colnames(res), c("symbol", "tx_id", "gene_name")) ## Test for exons res <- exons(edb, filter=sf, return.type="data.frame") expect_true(all(res$symbol == "SKA2")) res <- exons(edb, filter = c(sf, TxBiotypeFilter("nonsense_mediated_decay")), return.type = "data.frame", columns = c("symbol", "tx_id", "gene_name")) expect_true(all(res$symbol == "SKA2")) expect_equal(res$symbol, res$gene_name) expect_equal(colnames(res), c("symbol", "tx_id", "gene_name", "exon_id", "tx_biotype")) ## Test for exonsBy res <- exonsBy(edb, filter=sf) expect_true(all(unlist(res)$symbol == "SKA2")) res <- exonsBy(edb, filter = c(sf, TxBiotypeFilter("nonsense_mediated_decay")), columns = c("symbol", "tx_id", "gene_name")) expect_true(all(unlist(res)$symbol == "SKA2")) expect_equal(unlist(res)$symbol, unlist(res)$gene_name) }) ensembldb/tests/testthat/test_dbhelpers.R0000644000175400017540000005116713175714743021715 0ustar00biocbuildbiocbuild test_that("prefixColumns works", { res <- ensembldb:::prefixColumns(edb, columns = "a") expect_true(is.null(res)) expect_error(ensembldb:::prefixColumns(edb, columns = "a", clean = FALSE)) res <- ensembldb:::prefixColumns(edb, columns = c("gene_id", "a"), clean = FALSE) expect_equal(names(res), "gene") expect_equal(res$gene, "gene.gene_id") ## The "new" prefixColumns function ALWAYS returns the first table in which ## a column was found; tables are ordered as in listTables res <- ensembldb:::prefixColumns(edb, columns = c("tx_id", "gene_id", "tx_biotype")) want <- list(gene = "gene.gene_id", tx = c("tx.tx_id", "tx.tx_biotype")) expect_equal(res, want) ## res <- ensembldb:::prefixColumns(edb, columns = c("exon_idx", "seq_name", "gene_id")) want <- list(gene = c("gene.gene_id", "gene.seq_name"), tx2exon = "tx2exon.exon_idx") expect_equal(res, want) ## res <- ensembldb:::prefixColumns(edb, columns = c("exon_idx", "seq_name", "gene_id", "exon_id")) want <- list(gene = c("gene.gene_id", "gene.seq_name"), tx2exon = c("tx2exon.exon_id", "tx2exon.exon_idx")) expect_equal(res, want) if (hasProteinData(edb)) { res <- ensembldb:::prefixColumns(edb, columns = c("tx_id", "protein_id")) want <- list(tx = "tx.tx_id", protein = "protein.protein_id") expect_equal(res, want) ## res <- ensembldb:::prefixColumns(edb, columns = c("uniprot_id", "protein_domain_id")) want <- list(uniprot = "uniprot.uniprot_id", protein_domain = "protein_domain.protein_domain_id") expect_equal(res, want) ## res <- ensembldb:::prefixColumns(edb, columns = c("uniprot_id", "protein_domain_id", "protein_id", "tx_id")) want = list(tx = "tx.tx_id", protein = "protein.protein_id", uniprot = "uniprot.uniprot_id", protein_domain = "protein_domain.protein_domain_id") expect_equal(res, want) } }) ############################################################ ## Test the new join engine. ## o use the startWith argument. ## o change the join argument. test_that("joinTwoTables works", { ## Check errors: expect_error(ensembldb:::joinTwoTables(a = "gene", b = "dont exist")) expect_error(ensembldb:::joinTwoTables(a = c("a", "b"), b = "gene")) ## Working example: res <- ensembldb:::joinTwoTables(a = c("a", "gene"), b = "tx") expect_equal(sort(res[1:2]), c("gene", "tx")) expect_equal(res[3], "on (gene.gene_id=tx.gene_id)") ## Error expect_error(ensembldb:::joinTwoTables(a = "tx", b = "exon")) ## Working example: res <- ensembldb:::joinTwoTables(a = c("tx"), b = c("exon", "tx2exon")) expect_equal(sort(res[1:2]), c("tx", "tx2exon")) expect_equal(res[3], "on (tx.tx_id=tx2exon.tx_id)") res <- ensembldb:::joinTwoTables(a = c("chromosome", "gene", "tx"), b = c("exon", "protein", "tx2exon")) expect_equal(sort(res[1:2]), c("tx", "tx2exon")) expect_equal(res[3], "on (tx.tx_id=tx2exon.tx_id)") }) test_that("joinQueryOnTables2 and joinQueryOnColumns2 work", { ## exceptions expect_error(ensembldb:::joinQueryOnTables2(edb, tab = c("a", "exon"))) res <- ensembldb:::joinQueryOnTables2(edb, tab = c("gene", "exon")) want <- paste0("gene join tx on (gene.gene_id=tx.gene_id) join", " tx2exon on (tx.tx_id=tx2exon.tx_id) join", " exon on (tx2exon.exon_id=exon.exon_id)") ## The "default" order is gene->tx->tx2exon->exon expect_equal(res, want) res <- ensembldb:::joinQueryOnColumns2(edb, columns = c("exon_seq_start", "gene_name")) expect_equal(res, want) ## Same but in the order: exon->tx2exon->tx->gene res <- ensembldb:::joinQueryOnTables2(edb, tab = c("gene", "exon"), startWith = "exon") want <- paste0("exon join tx2exon on (tx2exon.exon_id=exon.exon_id)", " join tx on (tx.tx_id=tx2exon.tx_id) join", " gene on (gene.gene_id=tx.gene_id)") expect_equal(res, want) res <- ensembldb:::joinQueryOnColumns2(edb, columns = c("exon_seq_start", "gene_name"), startWith = "exon") expect_equal(res, want) ## That would be less expensive, but with "startWith" we force it to start ## from table exon, instead of just using tx2exon and tx. res <- ensembldb:::joinQueryOnColumns2(edb, columns = c("exon_id", "gene_id"), startWith = "exon") expect_equal(res, want) ## Check proteins too. if (hasProteinData(edb)) { res <- ensembldb:::joinQueryOnTables2(edb, tab = c("protein", "gene", "exon")) ## That should be: gene->tx->tx2exon->exon->protein want <- paste0("gene join tx on (gene.gene_id=tx.gene_id) join", " tx2exon on (tx.tx_id=tx2exon.tx_id) join", " exon on (tx2exon.exon_id=exon.exon_id) left outer join", " protein on (tx.tx_id=protein.tx_id)") expect_equal(res, want) res <- ensembldb:::joinQueryOnColumns2(edb, columns = c("protein_id", "gene_name", "exon_seq_start")) expect_equal(res, want) res <- ensembldb:::joinQueryOnTables2(edb, tab = c("protein", "gene"), startWith = "protein") want <- paste0("protein left outer join tx on (tx.tx_id=protein.tx_id)", " join gene on (gene.gene_id=tx.gene_id)") expect_equal(res, want) res <- ensembldb:::joinQueryOnColumns2(edb, columns = c("protein_id", "gene_name"), startWith = "protein") expect_equal(res, want) } }) test_that("addRequiredTables works", { have <- c("exon", "gene") need <- c("exon", "gene", "tx2exon", "tx") expect_equal(sort(need), sort(ensembldb:::addRequiredTables(edb, have))) have <- c("exon", "chromosome") need <- c("exon", "tx2exon", "tx", "gene", "chromosome") expect_equal(sort(need), sort(ensembldb:::addRequiredTables(edb, have))) have <- c("chromosome", "tx") need <- c("chromosome", "tx", "gene") expect_equal(sort(need), sort(ensembldb:::addRequiredTables(edb, have))) if (hasProteinData(edb)) { have <- c("uniprot", "exon") need <- c("uniprot", "exon", "protein", "tx", "tx2exon") expect_equal(sort(need), sort(ensembldb:::addRequiredTables(edb, have))) have <- c("uniprot", "chromosome") need <- c("uniprot", "chromosome", "protein", "tx", "gene") expect_equal(sort(need), sort(ensembldb:::addRequiredTables(edb, have))) have <- c("protein_domain", "gene") need <- c("protein_domain", "gene", "protein", "tx") expect_equal(sort(need), sort(ensembldb:::addRequiredTables(edb, have))) have <- c("protein", "exon") need <- c("protein", "exon", "tx", "tx2exon") expect_equal(sort(need), sort(ensembldb:::addRequiredTables(edb, have))) } }) test_that(".buildQuery with filter works", { columns <- c("gene_id", "gene_name", "exon_id") gnf <- GenenameFilter("BCL2") Q <- ensembldb:::.buildQuery(edb, columns = columns, filter = AnnotationFilterList(gnf)) want <- paste0("select distinct gene.gene_id,gene.gene_name,", "tx2exon.exon_id from gene join tx on (gene.gene_id", "=tx.gene_id) join tx2exon on (tx.tx_id=tx2exon.tx_id)", " where (gene.gene_name = 'BCL2')") expect_equal(Q, want) library(RSQLite) res <- dbGetQuery(dbconn(edb), Q) expect_equal(unique(res$gene_name), "BCL2") ## Two GeneNameFilters combined with or gnf2 <- GenenameFilter("BCL2L11") columns <- c("gene_id", "gene_name", "exon_id") Q <- ensembldb:::.buildQuery(edb, columns = columns, filter = AnnotationFilterList(gnf, gnf2, logOp = "|")) want <- paste0("select distinct gene.gene_id,gene.gene_name,", "tx2exon.exon_id from gene join tx on (gene.gene_id", "=tx.gene_id) join tx2exon on (tx.tx_id=tx2exon.tx_id)", " where (gene.gene_name = 'BCL2' or gene.gene_name = ", "'BCL2L11')") expect_equal(Q, want) res <- dbGetQuery(dbconn(edb), Q) expect_true(all(res$gene_name %in% c("BCL2", "BCL2L11"))) ## Combine with a SeqnameFilter. snf <- SeqNameFilter(2) flt <- AnnotationFilterList(gnf, gnf2, snf, logOp = c("|", "&")) Q <- ensembldb:::.buildQuery(edb, columns = columns, filter = flt) want <- paste0("select distinct gene.gene_id,gene.gene_name,", "tx2exon.exon_id,gene.seq_name from gene join tx on (", "gene.gene_id=tx.gene_id) join tx2exon on (tx.tx_id=", "tx2exon.tx_id) where (gene.gene_name = 'BCL2' or ", "gene.gene_name = 'BCL2L11' and gene.seq_name = '2')") expect_equal(Q, want) res <- dbGetQuery(dbconn(edb), Q) expect_true(all(res$gene_name %in% c("BCL2", "BCL2L11"))) ## now with a nested AnnotationFilterList: flt <- AnnotationFilterList(AnnotationFilterList(gnf, gnf2, logOp = "|"), snf, logOp = "&") Q <- ensembldb:::.buildQuery(edb, columns = columns, filter = flt) want <- paste0("select distinct gene.gene_id,gene.gene_name,", "tx2exon.exon_id,gene.seq_name from gene join tx on (", "gene.gene_id=tx.gene_id) join tx2exon on (tx.tx_id=", "tx2exon.tx_id) where ((gene.gene_name = 'BCL2' or ", "gene.gene_name = 'BCL2L11') and gene.seq_name = '2')") expect_equal(Q, want) res <- dbGetQuery(dbconn(edb), Q) expect_true(all(res$gene_name %in% c("BCL2L11"))) ## If we only want to get BCL2L11 back: flt <- AnnotationFilterList(GenenameFilter(c("BCL2", "BCL2L11")), snf, logOp = "&") Q <- ensembldb:::.buildQuery(edb, columns = columns, filter = flt) want <- paste0("select distinct gene.gene_id,gene.gene_name,", "tx2exon.exon_id,gene.seq_name from gene join tx on (", "gene.gene_id=tx.gene_id) join tx2exon on (tx.tx_id=", "tx2exon.tx_id) where (gene.gene_name in ('BCL2','BCL2L11'", ") and gene.seq_name = '2')") expect_equal(Q, want) res <- dbGetQuery(dbconn(edb), Q) expect_true(all(res$gene_name == "BCL2L11")) ## Check with a GRangesFilter. grf <- GRangesFilter(GRanges(seqnames = 18, IRanges(60790600, 60790700))) flt <- AnnotationFilterList(grf) Q <- ensembldb:::.buildQuery(edb, columns = columns, filter = flt) want <- paste0("select distinct gene.gene_id,gene.gene_name,tx2exon.", "exon_id,gene.gene_seq_start,gene.gene_seq_end,gene.seq_name", ",gene.seq_strand from gene join tx on (gene.gene_id", "=tx.gene_id) join tx2exon on (tx.tx_id=tx2exon.tx_id) ", "where ((gene.gene_seq_start<=60790700 and gene.gene_seq", "_end>=60790600 and gene.seq_name='18'))") expect_equal(Q, want) res <- dbGetQuery(dbconn(edb), Q) expect_true(all(res$gene_name == "BCL2")) }) test_that("buildQuery with startWith works", { columns <- c("gene_id", "gene_name", "exon_id") Q <- ensembldb:::.buildQuery(edb, columns = columns) want <- paste0("select distinct gene.gene_id,gene.gene_name,", "tx2exon.exon_id from gene join tx on (gene.gene_id", "=tx.gene_id) join tx2exon on (tx.tx_id=tx2exon.tx_id)") expect_equal(Q, want) ## Different if we use startWith = exon Q <- ensembldb:::.buildQuery(edb, columns = columns, startWith = "exon") want <- paste0("select distinct gene.gene_id,gene.gene_name,", "tx2exon.exon_id from exon join tx2exon on (tx2exon.exon_id", "=exon.exon_id) join tx on (tx.tx_id=tx2exon.tx_id)", " join gene on (gene.gene_id=tx.gene_id)") expect_equal(Q, want) Q <- ensembldb:::.buildQuery(edb, columns = c("gene_id", "tx_biotype")) want <- paste0("select distinct gene.gene_id,tx.tx_biotype from gene ", "join tx on (gene.gene_id=tx.gene_id)") expect_equal(Q, want) Q <- ensembldb:::.buildQuery(edb, columns = c("gene_id", "tx_biotype"), startWith = "exon") want <- paste0("select distinct gene.gene_id,tx.tx_biotype from exon ", "join tx2exon on (tx2exon.exon_id=exon.exon_id) join ", "tx on (tx.tx_id=tx2exon.tx_id) join ", "gene on (gene.gene_id=tx.gene_id)") expect_equal(Q, want) if (hasProteinData(edb)) { ## Protein columns. Q <- ensembldb:::.buildQuery(edb, columns = c("protein_id", "uniprot_id", "protein_domain_id")) want <- paste0("select distinct protein.protein_id,uniprot.uniprot_id,", "protein_domain.protein_domain_id from protein left ", "outer join protein_domain on (protein.protein_id=", "protein_domain.protein_id) left outer join ", "uniprot on (protein.protein_id=uniprot.protein_id)") expect_equal(Q, want) ## start at protein Q <- ensembldb:::.buildQuery(edb, columns = c("protein_id", "uniprot_id", "protein_domain_id"), startWith = "protein") want <- paste0("select distinct protein.protein_id,uniprot.uniprot_id,", "protein_domain.protein_domain_id from protein left ", "outer join protein_domain on (protein.protein_id=", "protein_domain.protein_id) left outer join ", "uniprot on (protein.protein_id=uniprot.protein_id)") expect_equal(Q, want) ## start at uniprot. Q <- ensembldb:::.buildQuery(edb, columns = c("protein_id", "uniprot_id", "protein_domain_id"), startWith = "uniprot") want <- paste0("select distinct protein.protein_id,uniprot.uniprot_id,", "protein_domain.protein_domain_id from uniprot left ", "outer join protein on (protein.protein_id=", "uniprot.protein_id) left outer join", " protein_domain on (protein.protein_id=", "protein_domain.protein_id)") expect_equal(Q, want) ## join with tx. Q <- ensembldb:::.buildQuery(edb, columns = c("tx_id", "protein_id", "uniprot_id", "gene_id")) want <- paste0("select distinct tx.tx_id,protein.protein_id,", "uniprot.uniprot_id,gene.gene_id from gene join ", "tx on (gene.gene_id=tx.gene_id) left outer join protein", " on (tx.tx_id=protein.tx_id) left outer join uniprot on", " (protein.protein_id=uniprot.protein_id)") expect_equal(Q, want) ## if we started from protein: Q <- ensembldb:::.buildQuery(edb, columns = c("tx_id", "protein_id", "uniprot_id", "gene_id"), startWith = "protein") want <- paste0("select distinct tx.tx_id,protein.protein_id,", "uniprot.uniprot_id,gene.gene_id from protein left outer", " join tx on (tx.tx_id=protein.tx_id) join gene on", " (gene.gene_id=tx.gene_id) left outer join uniprot on", " (protein.protein_id=uniprot.protein_id)") expect_equal(Q, want) } }) ## This test is an important one as it checks that we don't miss any entries ## from the database, e.g. if we query gene and join with protein that we don't ## miss any non-coding transcripts, or if we join protein with uniprot or ## protein_domain that we don't miss any values. test_that("query is valid", { ## Check RNA/DNA tables; shouldn't be a problem there, though. Ygns <- genes(edb, filter = SeqNameFilter("Y"), return.type = "data.frame") Ytxs <- transcripts(edb, filter = SeqNameFilter("Y"), return.type = "data.frame", columns = c("gene_id", "tx_id", "tx_biotype")) Yexns <- exons(edb, filter = SeqNameFilter("Y"), return.type = "data.frame", columns = c("exon_id", "gene_id")) expect_true(all(unique(Ygns$gene_id) %in% unique(Yexns$gene_id))) expect_true(all(unique(Ygns$gene_id) %in% unique(Ytxs$gene_id))) ## Check gene with protein if (hasProteinData(edb)) { library(RSQLite) ## Simulate what a simple join would do: gns_f <- dbGetQuery(dbconn(edb), paste0("select gene.gene_id, tx.tx_id, tx_biotype, ", "protein_id from gene join tx on ", "(gene.gene_id=tx.gene_id) join protein on ", "(tx.tx_id=protein.tx_id) ", "where seq_name = 'Y'")) ## We expect that gns_f is smaller, but that all protein_coding tx are ## there. expect_true(length(unique(gns_f$gene_id)) < length(unique(Ygns$gene_id))) expect_true(all(unique(Ytxs[Ytxs$tx_biotype == "protein_coding", "tx_id"]) %in% unique(gns_f$tx_id))) ## Now test the "real" query: Ygns_2 <- genes(edb, filter = SeqNameFilter("Y"), return.type = "data.frame", columns = c("gene_id", "tx_id", "tx_biotype", "protein_id")) ## We expect that ALL genes are present and ALL tx: expect_true(all(unique(Ygns$gene_id) %in% unique(Ygns_2$gene_id))) expect_true(all(unique(Ygns$tx_id) %in% unique(Ygns_2$tx_id))) ## Get all the tx with protein_id txs <- transcripts(edb, columns = c("tx_id", "protein_id"), return.type = "data.frame") txids <- dbGetQuery(dbconn(edb), "select tx_id from tx;")[, "tx_id"] protids <- dbGetQuery(dbconn(edb), "select protein_id from protein;")[, "protein_id"] expect_true(all(txids %in% txs$tx_id)) expect_true(all(protids %in% txs$protein_id)) ## Check protein with uniprot uniprotids <- dbGetQuery(dbconn(edb), "select uniprot_id from uniprot")$uniprot_id ## Check protein with protein domain ## Check protein_domain with uniprot } }) test_that(".getWhat works", { library(RSQLite) Q_2 <- paste0("select * from gene join tx on (gene.gene_id=tx.gene_id)", " join tx2exon on (tx.tx_id=tx2exon.tx_id) where", " gene.gene_id = 'ENSG00000000005'") res_2 <- dbGetQuery(dbconn(edb), Q_2) gf <- GeneIdFilter("ENSG00000000005") res_3 <- ensembldb:::.getWhat(edb, columns = c("gene_name", "exon_idx"), filter = AnnotationFilterList(gf)) expect_identical(res_3, unique(res_2[, colnames(res_3)])) }) test_that(".logOp2SQL works", { expect_equal(ensembldb:::.logOp2SQL("|"), "or") expect_equal(ensembldb:::.logOp2SQL("&"), "and") expect_equal(ensembldb:::.logOp2SQL("dfdf"), NULL) }) ensembldb/tests/testthat/test_extractTranscriptSeqs.R0000644000175400017540000000552313175714743024320 0ustar00biocbuildbiocbuild test_that("extractTranscriptSeqs works with BSGenome", { library(BSgenome.Hsapiens.UCSC.hg19) bsg <- BSgenome.Hsapiens.UCSC.hg19 ## Changing the seqlevels tyle to UCSC seqlevelsStyle(edb) <- "UCSC" ZBTB <- extractTranscriptSeqs(bsg, edb, filter=GenenameFilter("ZBTB16")) ## Load the sequences for one ZBTB16 transcript from FA. faf <- system.file("txt/ENST00000335953.fa.gz", package="ensembldb") Seqs <- readDNAStringSet(faf) tx <- "ENST00000335953" ## cDNA expect_equal(unname(as.character(ZBTB[tx])), unname(as.character(Seqs[grep(names(Seqs), pattern="cdna")]))) ## CDS cBy <- cdsBy(edb, "tx", filter=TxIdFilter(tx)) CDS <- extractTranscriptSeqs(bsg, cBy) expect_equal(unname(as.character(CDS)), unname(as.character(Seqs[grep(names(Seqs), pattern="cds")]))) ## 5' UTR fBy <- fiveUTRsByTranscript(edb, filter=TxIdFilter(tx)) UTR <- extractTranscriptSeqs(bsg, fBy) expect_equal(unname(as.character(UTR)), unname(as.character(Seqs[grep(names(Seqs), pattern="utr5")]))) ## 3' UTR tBy <- threeUTRsByTranscript(edb, filter=TxIdFilter(tx)) UTR <- extractTranscriptSeqs(bsg, tBy) expect_equal(unname(as.character(UTR)), unname(as.character(Seqs[grep(names(Seqs), pattern="utr3")]))) ## Another gene on the reverse strand: faf <- system.file("txt/ENST00000200135.fa.gz", package="ensembldb") Seqs <- readDNAStringSet(faf) tx <- "ENST00000200135" ## cDNA cDNA <- extractTranscriptSeqs(bsg, edb, filter=TxIdFilter(tx)) expect_equal(unname(as.character(cDNA)), unname(as.character(Seqs[grep(names(Seqs), pattern="cdna")]))) ## do the same, but from other strand exns <- exonsBy(edb, "tx", filter=TxIdFilter(tx)) cDNA <- extractTranscriptSeqs(bsg, exns) expect_equal(unname(as.character(cDNA)), unname(as.character(Seqs[grep(names(Seqs), pattern="cdna")]))) strand(exns) <- "+" cDNA <- extractTranscriptSeqs(bsg, exns) expect_true(unname(as.character(cDNA)) != unname(as.character(Seqs[grep(names(Seqs), pattern="cdna")]))) ## CDS cBy <- cdsBy(edb, "tx", filter=TxIdFilter(tx)) CDS <- extractTranscriptSeqs(bsg, cBy) expect_equal(unname(as.character(CDS)), unname(as.character(Seqs[grep(names(Seqs), pattern="cds")]))) ## 5' UTR fBy <- fiveUTRsByTranscript(edb, filter=TxIdFilter(tx)) UTR <- extractTranscriptSeqs(bsg, fBy) expect_equal(unname(as.character(UTR)), unname(as.character(Seqs[grep(names(Seqs), pattern="utr5")]))) ## 3' UTR tBy <- threeUTRsByTranscript(edb, filter=TxIdFilter(tx)) UTR <- extractTranscriptSeqs(bsg, tBy) expect_equal(unname(as.character(UTR)), unname(as.character(Seqs[grep(names(Seqs), pattern="utr3")]))) }) ensembldb/tests/testthat/test_functions-EnsDb.R0000644000175400017540000000476013175714743022743 0ustar00biocbuildbiocbuildtest_that(".addFilter .dropFilter and .activeFilter work", { gf <- GenenameFilter("BCL2") ## .addFilter and .activeFilter edb_2 <- ensembldb:::.addFilter(edb, filter = gf) expect_equal(AnnotationFilterList(gf), ensembldb:::getProperty(edb_2, "FILTER")) expect_equal(AnnotationFilterList(gf), ensembldb:::.activeFilter(edb_2)) edb_2 <- ensembldb:::.addFilter(edb_2, filter = gf) expect_equal(AnnotationFilterList(AnnotationFilterList(gf), AnnotationFilterList(gf)), ensembldb:::getProperty(edb_2, "FILTER")) edb_2 <- ensembldb:::.addFilter(edb, filter = ~ tx_id == 3 & tx_biotype == "protein_coding") flts <- ensembldb:::.activeFilter(edb_2) expect_equal(flts, ensembldb:::getProperty(edb_2, "FILTER")) expect_equal(flts, AnnotationFilter(~ tx_id == 3 & tx_biotype == "protein_coding")) ## Errors expect_error(ensembldb:::.addFilter(edb, "blabla")) expect_error(ensembldb:::filter(edb, "blabla")) expect_error(ensembldb:::.addFilter(edb)) ## .dropFilter edb_2 <- ensembldb:::.dropFilter(edb_2) expect_equal(ensembldb:::.activeFilter(edb_2), NA) ## Same but with the methods. gf <- GenenameFilter("BCL2") ## .addFilter and .activeFilter edb_2 <- addFilter(edb, filter = gf) expect_equal(AnnotationFilterList(gf), ensembldb:::getProperty(edb_2, "FILTER")) edb_2 <- filter(edb, filter = gf) expect_equal(AnnotationFilterList(gf), ensembldb:::getProperty(edb_2, "FILTER")) expect_equal(AnnotationFilterList(gf), activeFilter(edb_2)) edb_2 <- addFilter(edb_2, filter = gf) expect_equal(AnnotationFilterList(AnnotationFilterList(gf), AnnotationFilterList(gf)), ensembldb:::getProperty(edb_2, "FILTER")) edb_2 <- addFilter(edb, filter = ~ tx_id == 3 & tx_biotype == "protein_coding") flts <- activeFilter(edb_2) expect_equal(flts, ensembldb:::getProperty(edb_2, "FILTER")) expect_equal(flts, AnnotationFilter(~ tx_id == 3 & tx_biotype == "protein_coding")) ## Errors expect_error(addFilter(edb, "blabla")) expect_error(addFilter(edb)) ## .dropFilter edb_2 <- dropFilter(edb_2) expect_equal(activeFilter(edb_2), NA) }) ensembldb/tests/testthat/test_functions-Filter.R0000644000175400017540000003024513175714743023172 0ustar00biocbuildbiocbuild test_that(".fieldInEnsDb works", { expect_equal(unname(ensembldb:::.fieldInEnsDb("symbol")), "gene_name") expect_equal(unname(ensembldb:::.fieldInEnsDb("gene_biotype")), "gene_biotype") expect_equal(unname(ensembldb:::.fieldInEnsDb("entrez")), "entrezid") expect_equal(unname(ensembldb:::.fieldInEnsDb("gene_id")), "gene_id") expect_equal(unname(ensembldb:::.fieldInEnsDb("genename")), "gene_name") expect_equal(unname(ensembldb:::.fieldInEnsDb("seq_name")), "seq_name") expect_equal(unname(ensembldb:::.fieldInEnsDb("tx_id")), "tx_id") expect_equal(unname(ensembldb:::.fieldInEnsDb("tx_biotype")), "tx_biotype") expect_equal(unname(ensembldb:::.fieldInEnsDb("tx_name")), "tx_id") expect_equal(unname(ensembldb:::.fieldInEnsDb("exon_id")), "exon_id") expect_equal(unname(ensembldb:::.fieldInEnsDb("exon_rank")), "exon_idx") expect_equal(unname(ensembldb:::.fieldInEnsDb("protein_id")), "protein_id") expect_equal(unname(ensembldb:::.fieldInEnsDb("uniprot")), "uniprot_id") expect_equal(unname(ensembldb:::.fieldInEnsDb("uniprot_db")), "uniprot_db") expect_equal(unname(ensembldb:::.fieldInEnsDb("uniprot_mapping_type")), "uniprot_mapping_type") expect_equal(unname(ensembldb:::.fieldInEnsDb("prot_dom_id")), "protein_domain_id") expect_equal(unname(ensembldb:::.fieldInEnsDb("description")), "description") expect_equal(unname(ensembldb:::.fieldInEnsDb("tx_support_level")), "tx_support_level") expect_error(ensembldb:::.fieldInEnsDb("aaa")) }) test_that(".conditionForEnsDb works", { smb <- SymbolFilter("a") expect_equal(condition(smb), "==") expect_equal(ensembldb:::.conditionForEnsDb(smb), "=") smb <- SymbolFilter(c("a", "b", "c")) expect_equal(ensembldb:::.conditionForEnsDb(smb), "in") smb <- SymbolFilter(c("a", "b", "c"), condition = "!=") expect_equal(ensembldb:::.conditionForEnsDb(smb), "not in") smb <- SymbolFilter(c("a"), condition = "!=") expect_equal(ensembldb:::.conditionForEnsDb(smb), "!=") smb <- SymbolFilter(c("a"), condition = "startsWith") expect_equal(ensembldb:::.conditionForEnsDb(smb), "like") smb <- SymbolFilter(c("a"), condition = "endsWith") expect_equal(ensembldb:::.conditionForEnsDb(smb), "like") ## Tests for numeric filters fl <- GeneStartFilter(4) expect_equal(ensembldb:::.conditionForEnsDb(fl), "=") fl <- GeneStartFilter(4, condition = ">") expect_equal(ensembldb:::.conditionForEnsDb(fl), ">") fl <- GeneStartFilter(4, condition = ">=") expect_equal(ensembldb:::.conditionForEnsDb(fl), ">=") fl <- GeneStartFilter(4, condition = "<") expect_equal(ensembldb:::.conditionForEnsDb(fl), "<") fl <- GeneStartFilter(4, condition = "<=") expect_equal(ensembldb:::.conditionForEnsDb(fl), "<=") fl <- TxSupportLevelFilter(4, condition = "<=") expect_equal(ensembldb:::.conditionForEnsDb(fl), "<=") }) test_that(".valueForEnsDb works", { smb <- SymbolFilter("a") expect_equal(ensembldb:::.valueForEnsDb(smb), "'a'") smb <- SymbolFilter(c("a", "b", "b", "c")) expect_equal(ensembldb:::.valueForEnsDb(smb), "('a','b','c')") smb <- SymbolFilter("a", condition = "startsWith") expect_equal(ensembldb:::.valueForEnsDb(smb), "'a%'") smb <- SymbolFilter("a", condition = "endsWith") expect_equal(ensembldb:::.valueForEnsDb(smb), "'%a'") ## Tests for numeric filters fl <- GeneStartFilter(4) expect_equal(ensembldb:::.valueForEnsDb(fl), 4) }) test_that(".queryForEnsDb works", { smb <- SymbolFilter("a") expect_equal(ensembldb:::.queryForEnsDb(smb), "gene_name = 'a'") smb <- SymbolFilter(c("a", "x"), condition = "!=") expect_equal(ensembldb:::.queryForEnsDb(smb), "gene_name not in ('a','x')") ## Tests for numeric filters fl <- GeneStartFilter(5, condition = "<=") expect_equal(ensembldb:::.queryForEnsDb(fl), "gene_seq_start <= 5") fl <- TxSupportLevelFilter(5, condition = "<=") expect_equal(ensembldb:::.queryForEnsDb(fl), "tx_support_level <= 5") }) test_that(".queryForEnsDbWithTables works", { smb <- SymbolFilter("a") expect_equal(ensembldb:::.queryForEnsDbWithTables(smb), "gene_name = 'a'") smb <- SymbolFilter(c("a", "x"), condition = "!=") expect_equal(ensembldb:::.queryForEnsDbWithTables(smb), "gene_name not in ('a','x')") ## With edb smb <- SymbolFilter("a") expect_equal(ensembldb:::.queryForEnsDbWithTables(smb, edb), "gene.gene_name = 'a'") smb <- SymbolFilter(c("a", "x"), condition = "!=") expect_equal(ensembldb:::.queryForEnsDbWithTables(smb, edb), "gene.gene_name not in ('a','x')") ## With edb, tables smb <- SymbolFilter("a") expect_equal(ensembldb:::.queryForEnsDbWithTables(smb, edb, c("gene", "tx")), "gene.gene_name = 'a'") fl <- GeneIdFilter("b") expect_equal(ensembldb:::.queryForEnsDbWithTables(fl, edb), "gene.gene_id = 'b'") expect_equal(ensembldb:::.queryForEnsDbWithTables(fl, edb, c("tx", "gene")), "tx.gene_id = 'b'") fl <- GeneIdFilter("b", condition = "contains") expect_equal(ensembldb:::.queryForEnsDbWithTables(fl, edb, c("tx", "gene")), "tx.gene_id like '%b%'") ## Entrez if (as.numeric(ensembldb:::dbSchemaVersion(edb)) > 1) { fl <- EntrezFilter("g") expect_equal(ensembldb:::.queryForEnsDbWithTables(fl, edb), "entrezgene.entrezid = 'g'") fl <- EntrezFilter("g", condition = "endsWith") expect_equal(ensembldb:::.queryForEnsDbWithTables(fl, edb), "entrezgene.entrezid like '%g'") } else { fl <- EntrezFilter("g") expect_equal(ensembldb:::.queryForEnsDbWithTables(fl, edb), "gene.entrezid = 'g'") fl <- EntrezFilter("g", condition = "endsWith") expect_equal(ensembldb:::.queryForEnsDbWithTables(fl, edb), "gene.entrezid like '%g'") } ## Numeric filters fl <- TxStartFilter(123) expect_equal(ensembldb:::.queryForEnsDbWithTables(fl, edb), "tx.tx_seq_start = 123") expect_error(ensembldb:::.queryForEnsDbWithTables(fl, edb, "gene")) if (any(listColumns(edb) == "tx_support_level")) { fl <- TxSupportLevelFilter(3) expect_equal(ensembldb:::.queryForEnsDbWithTables(fl, edb), "tx.tx_support_level = 3") } }) test_that(".processFilterParam works", { ## Check that the processFilterParam does what we expect. Check input and ## return ALWAYS an AnnotationFilterList object. snf <- SeqNameFilter(c("Y", 9)) res <- ensembldb:::.processFilterParam(snf, db = edb) expect_true(is(res, "AnnotationFilterList")) expect_equal(res[[1]], snf) ## - single filter gif <- GeneIdFilter("BCL2", condition = "!=") res <- ensembldb:::.processFilterParam(gif, db = edb) expect_true(is(res, "AnnotationFilterList")) expect_equal(res[[1]], gif) ## - list of filters snf <- SeqNameFilter("X") res <- ensembldb:::.processFilterParam(list(gif, snf), edb) expect_true(is(res, "AnnotationFilterList")) expect_true(length(res) == 2) expect_equal(res[[1]], gif) expect_equal(res[[2]], snf) expect_equal(res@logOp, "&") ## - AnnotationFilterList afl <- AnnotationFilterList(gif, snf, logOp = "|") res <- ensembldb:::.processFilterParam(afl, edb) expect_true(is(res, "AnnotationFilterList")) expect_equal(afl, res) afl <- AnnotationFilterList(gif, snf, logOp = "&") res <- ensembldb:::.processFilterParam(afl, edb) expect_true(is(res, "AnnotationFilterList")) expect_equal(afl, res) ## - filter expression res <- ensembldb:::.processFilterParam(~ gene_id != "BCL2" | seq_name == "X", edb) expect_true(is(res, "AnnotationFilterList")) expect_equal(res, AnnotationFilterList(gif, snf, logOp = "|")) flt <- ~ gene_id != "BCL2" | seq_name == "X" res <- ensembldb:::.processFilterParam(flt, edb) expect_true(is(res, "AnnotationFilterList")) expect_equal(res, AnnotationFilterList(gif, snf, logOp = "|")) res <- ensembldb:::.processFilterParam(~ gene_id != "BCL2", edb) expect_true(is(res, "AnnotationFilterList")) expect_equal(res, AnnotationFilterList(gif)) ## - Errors expect_error(ensembldb:::.processFilterParam(db = edb)) expect_error(ensembldb:::.processFilterParam(4, edb)) expect_error(ensembldb:::.processFilterParam(list(afl, "a"), edb)) expect_error(ensembldb:::.processFilterParam("a", edb)) expect_error(ensembldb:::.processFilterParam(~ gene_bla == "14", edb)) ## Errors for filters that are not supported. expect_error(ensembldb:::.processFilterParam(CdsEndFilter(123), edb)) ## Same with calls from within a function. testFun <- function(filter = AnnotationFilterList()) { ensembldb:::.processFilterParam(filter, db = edb) } res <- testFun() expect_true(is(res, "AnnotationFilterList")) expect_true(length(res) == 0) res <- testFun(filter = ~ gene_id == 4) expect_true(is(res, "AnnotationFilterList")) expect_equal(res[[1]], GeneIdFilter(4)) res <- testFun(filter = GenenameFilter("BCL2")) expect_true(is(res, "AnnotationFilterList")) expect_equal(res[[1]], GenenameFilter("BCL2")) res <- testFun(filter = AnnotationFilterList(GenenameFilter("BCL2"))) expect_true(is(res, "AnnotationFilterList")) expect_equal(res[[1]], GenenameFilter("BCL2")) gene <- "ZBTB16" otherFun <- function(gn) { testFun(filter = GenenameFilter(gn)) } res <- otherFun(gene) }) test_that("setFeatureInGRangesFilter works", { afl <- AnnotationFilterList(GeneIdFilter(123), SeqNameFilter(3), GRangesFilter(GRanges())) afl2 <- AnnotationFilterList(afl, GRangesFilter(GRanges())) res <- ensembldb:::setFeatureInGRangesFilter(afl, feature = "tx") expect_equal(res[[3]]@feature, "tx") res <- ensembldb:::setFeatureInGRangesFilter(afl2, feature = "tx") expect_equal(res[[2]]@feature, "tx") expect_equal(res[[1]][[3]]@feature, "tx") }) test_that(".AnnottionFilterClassNames works", { afl1 <- AnnotationFilter(~ genename == 3 & seq_name != 5) expect_equal(.AnnotationFilterClassNames(afl1), c("GenenameFilter", "SeqNameFilter")) afl2 <- AnnotationFilter(~ gene_start > 13 | seq_strand == "+") expect_equal(.AnnotationFilterClassNames(afl2), c("GeneStartFilter", "SeqStrandFilter")) afl3 <- AnnotationFilterList(afl1, SymbolFilter(4)) expect_equal(.AnnotationFilterClassNames(afl3), c("GenenameFilter", "SeqNameFilter", "SymbolFilter")) afl4 <- AnnotationFilterList(afl2, afl3) expect_equal(.AnnotationFilterClassNames(afl4), c("GeneStartFilter", "SeqStrandFilter", "GenenameFilter", "SeqNameFilter", "SymbolFilter")) }) test_that(".anyIs works", { sf <- SymbolFilter("d") expect_true(ensembldb:::.anyIs(sf, "SymbolFilter")) expect_false(ensembldb:::.anyIs(GenenameFilter(3), "SymbolFilter")) flts <- AnnotationFilterList(sf, TxIdFilter("b")) expect_true(any(ensembldb:::.anyIs(flts, "SymbolFilter"))) expect_false(any(ensembldb:::.anyIs(flts, "BLa"))) ## Additional nesting. flts <- AnnotationFilterList(flts, GenenameFilter("2")) expect_true(any(ensembldb:::.anyIs(flts, "SymbolFilter"))) expect_true(any(ensembldb:::.anyIs(flts, "GenenameFilter"))) expect_true(any(ensembldb:::.anyIs(flts, "TxIdFilter"))) }) test_that(".fieldToClass works", { expect_equal(ensembldb:::.fieldToClass("gene_id"), "GeneIdFilter") }) test_that(".filterFields works", { res <- ensembldb:::.filterFields(edb) if (hasProteinData(edb)) { expect_true(any(res == "uniprot")) } expect_true(!any(res == "g_ranges")) }) test_that(".supportedFilters works", { res <- ensembldb:::.supportedFilters(edb) expect_true(class(res) == "data.frame") expect_equal(res[res$filter == "GRangesFilter", "field"], as.character(NA)) expect_equal(res[res$filter == "ExonIdFilter", "field"], "exon_id") expect_equal(res[res$filter == "GenenameFilter", "field"], "genename") }) ensembldb/tests/testthat/test_functions-create-EnsDb.R0000644000175400017540000002370313175714743024202 0ustar00biocbuildbiocbuild test_that(".organismName, .abbrevOrganismName and .makePackageName works", { res <- ensembldb:::.organismName("homo_sapiens") expect_equal(res, "Homo_sapiens") res <- ensembldb:::.abbrevOrganismName("homo_sapiens") expect_equal(res, "hsapiens") res <- ensembldb:::.makePackageName(dbconn(edb)) expect_equal(res, "EnsDb.Hsapiens.v75") }) test_that("ensDbFromGRanges works", { load(system.file("YGRanges.RData", package="ensembldb")) suppressWarnings( DB <- ensDbFromGRanges(Y, path=tempdir(), version=75, organism="Homo_sapiens", skip = TRUE) ) db <- EnsDb(DB) expect_equal(unname(genome(db)), "GRCh37") Test <- makeEnsembldbPackage(DB, destDir = tempdir(), version = "0.0.1", author = "J Rainer", maintainer = "") expect_true(ensembldb:::checkValidEnsDb(db)) }) test_that("ensDbFromGtf and Gff works", { gff <- system.file("gff/Devosia_geojensis.ASM96941v1.32.gff3.gz", package="ensembldb") gtf <- system.file("gtf/Devosia_geojensis.ASM96941v1.32.gtf.gz", package="ensembldb") suppressWarnings( db_gff <- EnsDb(ensDbFromGff(gff, outfile = tempfile(), skip = TRUE)) ) suppressWarnings( db_gtf <- EnsDb(ensDbFromGtf(gtf, outfile = tempfile(), skip = TRUE)) ) expect_equal(ensemblVersion(db_gtf), "32") expect_equal(ensemblVersion(db_gff), "32") res <- ensembldb:::compareChromosomes(db_gtf, db_gff) expect_equal(res, "OK") res <- ensembldb:::compareGenes(db_gtf, db_gff) expect_equal(res, "WARN") ## differences in gene names and Entrezid. res <- ensembldb:::compareTx(db_gtf, db_gff) expect_equal(res, "OK") res <- ensembldb:::compareExons(db_gtf, db_gff) expect_equal(res, "OK") ## Compare them all in one call res <- ensembldb:::compareEnsDbs(db_gtf, db_gff) expect_equal(unname(res["metadata"]), "NOTE") expect_equal(unname(res["chromosome"]), "OK") expect_equal(unname(res["transcript"]), "OK") expect_equal(unname(res["exon"]), "OK") }) test_that("isEnsemblFileName", { res <- ensembldb:::isEnsemblFileName("Caenorhabditis_elegans.WS210.60.gtf.gz") expect_true(res) res <- ensembldb:::isEnsemblFileName("Caenorhabditis_elegans_fdf.60.dfd.gtf.gz") expect_true(!res) fn <- "Caenorhabditis_elegans.WS210.60.gtf.gz" res <- ensembldb:::ensemblVersionFromGtfFileName(fn) expect_equal(res, "60") res <- ensembldb:::organismFromGtfFileName(fn) expect_equal(res, "Caenorhabditis_elegans") res <- ensembldb:::genomeVersionFromGtfFileName(fn) expect_equal(res, "WS210") res <- ensembldb:::elementFromEnsemblFilename(fn, which = 1) expect_equal(res, "Caenorhabditis_elegans") res <- ensembldb:::elementFromEnsemblFilename(fn, which = 2) expect_equal(res, "WS210") res <- ensembldb:::elementFromEnsemblFilename(fn, which = 3) expect_equal(res, "60") res <- ensembldb:::elementFromEnsemblFilename(fn, which = 4) expect_equal(res, "gtf") }) test_that("processEnsemblFileNames works", { Test <- "Homo_sapiens.GRCh38.83.gtf.gz" expect_true(ensembldb:::isEnsemblFileName(Test)) expect_equal(ensembldb:::organismFromGtfFileName(Test), "Homo_sapiens") expect_equal(ensembldb:::genomeVersionFromGtfFileName(Test), "GRCh38") expect_equal(ensembldb:::ensemblVersionFromGtfFileName(Test), "83") Test <- "Homo_sapiens.GRCh38.83.chr.gff3.gz" expect_true(ensembldb:::isEnsemblFileName(Test)) expect_equal(ensembldb:::organismFromGtfFileName(Test), "Homo_sapiens") expect_equal(ensembldb:::genomeVersionFromGtfFileName(Test), "GRCh38") expect_equal(ensembldb:::ensemblVersionFromGtfFileName(Test), "83") Test <- "Gadus_morhua.gadMor1.83.gff3.gz" expect_true(ensembldb:::isEnsemblFileName(Test)) expect_equal(ensembldb:::organismFromGtfFileName(Test), "Gadus_morhua") expect_equal(ensembldb:::genomeVersionFromGtfFileName(Test), "gadMor1") expect_equal(ensembldb:::ensemblVersionFromGtfFileName(Test), "83") Test <- "Solanum_lycopersicum.GCA_000188115.2.30.chr.gtf.gz" expect_true(ensembldb:::isEnsemblFileName(Test)) expect_equal(ensembldb:::organismFromGtfFileName(Test), "Solanum_lycopersicum") expect_equal(ensembldb:::genomeVersionFromGtfFileName(Test), "GCA_000188115.2") expect_equal(ensembldb:::ensemblVersionFromGtfFileName(Test), "30") Test <- "ref_GRCh38.p2_top_level.gff3.gz" expect_equal(ensembldb:::isEnsemblFileName(Test), FALSE) ensembldb:::organismFromGtfFileName(Test) expect_error(ensembldb:::genomeVersionFromGtfFileName(Test)) ##checkException(ensembldb:::ensemblVersionFromGtfFileName(Test)) }) test_that("checkExtractVersions works", { fn <- "Devosia_geojensis.ASM96941v1.32.gff3.gz" res <- ensembldb:::.checkExtractVersions(fn) expect_equal(unname(res["organism"]), "Devosia_geojensis") expect_equal(unname(res["genomeVersion"]), "ASM96941v1") expect_equal(unname(res["version"]), "32") suppressWarnings( res <- ensembldb:::.checkExtractVersions(fn, organism = "Homo_sapiens") ) expect_equal(unname(res["organism"]), "Homo_sapiens") expect_error(ensembldb:::.checkExtractVersions("afdfhjd")) }) test_that("buildMetadata works", { res <- ensembldb:::buildMetadata(organism = "Mus_musculus", ensemblVersion = "88", genomeVersion = "38") expect_equal(colnames(res), c("name", "value")) expect_equal(res[res$name == "Organism", "value"], "Mus_musculus") }) test_that("guessDatabaseName works", { ## Testing real case examples. genome <- "Rnor_5.0" organism <- "Rattus_norvegicus" ensembl <- "75" res <- ensembldb:::.guessDatabaseName(organism, ensembl) expect <- "rattus_norvegicus_core_75" expect_equal(res, expect) genome <- "GRCm38" organism <- "Mus_musculus" expect <- "mus_musculus_core_75_38" res <- ensembldb:::.guessDatabaseName(organism, ensembl, genome = genome) expect_equal(expect, res) }) test_that("getEnsemblMysqlUrl works", { check_getReadMysqlTable <- function(url) { res <- ensembldb:::.getReadMysqlTable(url, "coord_system.txt.gz", colnames = c("coord_system_id", "species_id", "name", "version", "rank", "attrib")) expect_true(nrow(res) > 0) } ## Only run this if we have access to Ensembl. tmp <- try( RCurl::getURL(ensembldb:::.ENSEMBL_URL, dirlistonly = TRUE, .opts = list(timeout = 5, maxredirs = 2)) ) if (!is(tmp, "try-error")) { res <- ensembldb:::.getEnsemblMysqlUrl(type = "ensembl", organism = "macaca mulatta", ensembl = 85) expect_equal(res, paste0(ensembldb:::.ENSEMBL_URL, "release-85/", "mysql/macaca_mulatta_core_85_10")) check_getReadMysqlTable(res) ## Next. res <- ensembldb:::.getEnsemblMysqlUrl(type = "ensembl", organism = "Bos taurus", ensembl = 61) expect_equal(res, paste0(ensembldb:::.ENSEMBL_URL, "release-61/", "mysql/bos_taurus_core_61_4j")) check_getReadMysqlTable(res) ## Next res <- ensembldb:::.getEnsemblMysqlUrl(type = "ensembl", organism = "Ficedula albicollis", ensembl = 77) expect_equal(res, paste0(ensembldb:::.ENSEMBL_URL, "release-77/", "mysql/ficedula_albicollis_core_77_1")) } ## ensemblgenomes tmp <- try( RCurl::getURL(ensembldb:::.ENSEMBLGENOMES_URL, dirlistonly = TRUE, .opts = list(timeout = 5, maxredirs = 2)) ) if (!is(tmp, "try-error")) { ## check fungi res <- ensembldb:::.getEnsemblMysqlUrl(type = "ensemblgenomes", organism = "fusarium_oxysporum", ensembl = 21) db_name <- "fusarium_oxysporum_core_21_74_2" expect_equal(res, paste0(ensembldb:::.ENSEMBLGENOMES_URL, "release-21/", "fungi/mysql/", db_name)) check_getReadMysqlTable(res) ## Next one db_name <- "solanum_lycopersicum_core_28_81_250" res <- ensembldb:::.getEnsemblMysqlUrl(type = "ensemblgenomes", organism = "solanum_lycopersicum", ensembl = 28) expect_equal(res, paste0(ensembldb:::.ENSEMBLGENOMES_URL, "release-28/", "plants/mysql/", db_name)) check_getReadMysqlTable(res) } }) test_that("getSeqlengthsFromMysqlFolder works", { library(curl) ch <- new_handle(timeout = 5) handle_setopt(ch, timeout = 5) tmp <- try( ## RCurl::getURL(ensembldb:::.ENSEMBL_URL, dirlistonly = TRUE, ## .opts = list(timeout = 5, maxredirs = 2)) readLines(curl(ensembldb:::.ENSEMBL_URL, handle = ch)) ) if (!is(tmp, "try-error")) { ## Compare seqlengths we've in EnsDb.Hsapiens.v75 with the expected ## ones. seq_info <- seqinfo(edb) seq_lengths <- ensembldb:::.getSeqlengthsFromMysqlFolder( organism = "Homo sapiens", ensembl = 75, seqnames = seqlevels(seq_info)) sl <- seqlengths(seq_info) sl_2 <- seq_lengths$length names(sl_2) <- rownames(seq_lengths) expect_true(all(names(sl) %in% names(sl_2))) expect_equal(sl, sl_2[names(sl)]) } }) ensembldb/tests/testthat/test_functions-utils.R0000644000175400017540000001407713175714743023112 0ustar00biocbuildbiocbuild test_that("orderDataFrameBy works", { res <- exons(edb, filter = GenenameFilter("ZBTB16"), return.type = "DataFrame") ## Order by end res_2 <- ensembldb:::orderDataFrameBy(res, by = "exon_seq_end") idx <- order(res_2$exon_seq_end) expect_equal(idx, 1:nrow(res_2)) }) test_that("addFilterColumns works for AnnotationFilterList", { afl <- AnnotationFilterList(GenenameFilter(2), SymbolFilter(23)) afl2 <- AnnotationFilterList(SeqNameFilter(4), afl) res <- ensembldb:::addFilterColumns(cols = "gene_biotype", filter = afl, edb) expect_equal(res, c("gene_biotype", "gene_name", "symbol")) res <- ensembldb:::addFilterColumns(cols = "gene_biotype", filter = afl2, edb) expect_equal(res, c("gene_biotype", "seq_name", "gene_name", "symbol")) }) test_that("functions work for encapsuled AnnotationFilterLists", { fl <- AnnotationFilterList(GenenameFilter("a"), AnnotationFilterList(TxIdFilter("b"))) res <- ensembldb:::.processFilterParam(fl, edb) expect_equal(res, fl) res <- ensembldb:::setFeatureInGRangesFilter(fl, "gene") expect_equal(res, fl) res <- ensembldb:::addFilterColumns("z", fl, edb) expect_equal(res, c("z", "gene_name", "tx_id")) res <- ensembldb:::getWhat(edb, filter = fl) ## Check if content is the same flts1 <- ~ genename == "BCL2" & tx_biotype == "protein_coding" res1 <- transcripts(edb, filter = flts1) flts2 <- AnnotationFilterList( AnnotationFilterList(GenenameFilter("BCL2"), AnnotationFilterList( TxBiotypeFilter("protein_coding")) )) res2 <- transcripts(edb, filter = flts2) expect_equal(res1, res2) }) ## Here we want to test if we get always also the filter columns back. test_that("multiFilterReturnCols works also with symbolic filters", { cols <- ensembldb:::addFilterColumns(edb, cols = c("exon_id"), filter = SymbolFilter("SKA2")) expect_equal(cols, c("exon_id", "symbol")) ## Two filter cols <- ensembldb:::addFilterColumns(edb, cols = c("exon_id"), filter = list(SymbolFilter("SKA2"), GenenameFilter("SKA2"))) expect_equal(cols, c("exon_id", "symbol", "gene_name")) cols <- ensembldb:::addFilterColumns(edb, cols = c("exon_id"), filter = list(SymbolFilter("SKA2"), GenenameFilter("SKA2"), GRangesFilter( GRanges("3", IRanges(3, 5) )))) expect_equal(cols, c("exon_id", "symbol", "gene_name", "gene_seq_start", "gene_seq_end", "seq_name", "seq_strand")) cols <- ensembldb:::addFilterColumns(edb, cols = c("exon_id"), filter = list(SymbolFilter("SKA2"), GenenameFilter("SKA2"), GRangesFilter( GRanges("3", IRanges(3, 5) ), feature = "exon"))) expect_equal(cols, c("exon_id", "symbol", "gene_name", "exon_seq_start", "exon_seq_end", "seq_name", "seq_strand")) ## SeqStartFilter and GRangesFilter ssf <- TxStartFilter(123) cols <- ensembldb:::addFilterColumns(edb, cols = c("exon_id"), filter = list(SymbolFilter("SKA2"), GenenameFilter("SKA2"), GRangesFilter( GRanges("3", IRanges(3, 5) ), feature = "exon"), ssf)) expect_equal(cols, c("exon_id", "symbol", "gene_name", "exon_seq_start", "exon_seq_end", "seq_name", "seq_strand", "tx_seq_start")) }) test_that("SQLiteName2MySQL works", { have <- "EnsDb.Hsapiens.v75" want <- "ensdb_hsapiens_v75" expect_equal(ensembldb:::SQLiteName2MySQL(have), want) }) test_that("anyProteinColumns works", { expect_true(ensembldb:::anyProteinColumns(c("gene_id", "protein_id"))) expect_true(!ensembldb:::anyProteinColumns(c("gene_id", "exon_id"))) }) test_that("listProteinColumns works", { if (hasProteinData(edb)) { res <- listProteinColumns(edb) expect_true(any(res == "protein_id")) expect_true(any(res == "uniprot_id")) expect_true(any(res == "protein_domain_id")) ## That's new columns fetched for Uniprot: expect_true(any(res == "uniprot_db")) expect_true(any(res == "uniprot_mapping_type")) } else { expect_error(listProteinColumns(edb)) } }) test_that("strand2num works", { expect_equal(ensembldb:::strand2num("+"), 1) expect_equal(ensembldb:::strand2num("+1"), 1) expect_equal(ensembldb:::strand2num("-"), -1) expect_equal(ensembldb:::strand2num("-1"), -1) expect_equal(ensembldb:::strand2num(1), 1) expect_equal(ensembldb:::strand2num(5), 1) expect_equal(ensembldb:::strand2num(-1), -1) expect_equal(ensembldb:::strand2num(-5), -1) expect_error(ensembldb:::strand2num("a")) }) test_that("num2strand works", { expect_equal(ensembldb:::num2strand(1), "+") expect_equal(ensembldb:::num2strand(-1), "-") }) ensembldb/tests/testthat/test_select-methods.R0000644000175400017540000004330413175714743022657 0ustar00biocbuildbiocbuild test_that("columns works", { cols <- columns(edb) ## Don't expect to see any _ there... expect_equal(length(grep(cols, pattern="_")), 0) }) test_that("keytypes works", { keyt <- keytypes(edb) expect_equal(all(c("GENEID", "EXONID", "TXID") %in% keyt), TRUE) }) test_that("ensDbColumnForColumn works", { Test <- ensembldb:::ensDbColumnForColumn(edb, "GENEID") expect_equal(unname(Test), "gene_id") Test <- ensembldb:::ensDbColumnForColumn(edb, c("GENEID", "TXID")) expect_equal(unname(Test), c("gene_id", "tx_id")) suppressWarnings( Test <- ensembldb:::ensDbColumnForColumn(edb, c("GENEID", "TXID", "bla")) ) expect_equal(unname(Test), c("gene_id", "tx_id")) }) test_that("keys works", { ## get all gene ids ids <- keys(edb, "GENEID") expect_true(length(ids) > 0) expect_equal(length(ids), length(unique(ids))) ## get all tx ids ids <- keys(edb, "TXID") expect_true(length(ids) > 0) ## Get the TXNAME... nms <- keys(edb, "TXNAME") expect_equal(nms, ids) expect_equal(length(ids), length(unique(ids))) ## get all gene names ids <- keys(edb, "GENENAME") expect_true(length(ids) > 0) expect_equal(length(ids), length(unique(ids))) ## get all seq names ids <- keys(edb, "SEQNAME") expect_true(length(ids) > 0) expect_equal(length(ids), length(unique(ids))) ## get all seq strands ids <- keys(edb, "SEQSTRAND") expect_true(length(ids) > 0) expect_equal(length(ids), length(unique(ids))) ## get all gene biotypes ids <- keys(edb, "GENEBIOTYPE") expect_true(length(ids) > 0) expect_equal(ids, listGenebiotypes(edb)) ## Now with protein data. if (hasProteinData(edb)) { library(RSQLite) ls <- keys(edb, "PROTEINID") ls_2 <- dbGetQuery(dbconn(edb), "select distinct protein_id from protein")$protein_id expect_equal(sort(ls), sort(ls_2)) ## ks <- keys(edb, "UNIPROTID") ks_2 <- dbGetQuery(dbconn(edb), "select distinct uniprot_id from uniprot")$uniprot_id expect_equal(sort(ks), sort(ks_2)) ## ks <- keys(edb, "PROTEINDOMAINID") ks_2 <- dbGetQuery(dbconn(edb), paste0("select distinct protein_domain_id from", " protein_domain"))$protein_domain_id expect_equal(sort(ks), sort(ks_2)) } ## keys with filter: res <- keys(edb, "GENENAME", filter = ~ genename == "BCL2") expect_equal(res, "BCL2") }) test_that("select method works", { .comprehensiveCheckForGene <- function(x) { ## Check if we've got all of the transcripts. txs <- dbGetQuery( dbconn(edb), paste0("select tx_id from tx where gene_id = '", x$GENEID[1], "';")) expect_equal(sort(txs$tx_id), sort(unique(x$TXID))) ## Check if we've got all exons. exs <- dbGetQuery( dbconn(edb), paste0("select exon_id from tx2exon where tx_id in (", paste0("'", txs$tx_id, "'", collapse = ", "),")")) a <- sort(unique(exs$exon_id)) b <- sort(unique(x$EXONID)) a <- a[!is.na(a)] b <- b[!is.na(b)] expect_equal(a, b) if (hasProteinData(edb)) { ## Check if we've got all proteins prt <- dbGetQuery( dbconn(edb), paste0("select protein_id from protein where tx_id in (", paste0("'", txs$tx_id, "'", collapse = ", "), ")")) a <- sort(prt$protein_id) b <- sort(unique(x$PROTEINID)) a <- a[!is.na(a)] b <- b[!is.na(b)] expect_equal(a, b) ## Check if we've got all uniprots. res <- dbGetQuery( dbconn(edb), paste0("select uniprot_id from uniprot where ", "protein_id in (", paste0("'", prt$protein_id, "'", collapse = ", ") ,")")) a <- sort(unique(res$uniprot_id)) b <- sort(unique(x$UNIPROTID)) a <- a[!is.na(a)] b <- b[!is.na(b)] expect_equal(a, b) ## Check if we've got all protein_domains. res <- dbGetQuery( dbconn(edb), paste0("select protein_domain_id from protein_domain ", "where protein_id in (", paste0("'", prt$protein_id, "'", collapse = ", "), ")")) a <- sort(unique(res$protein_domain_id)) b <- sort(unique(x$PROTEINDOMAINID)) a <- a[!is.na(a)] b <- b[!is.na(b)] expect_equal(a, b) } } library(RSQLite) ## 1) Test: ## Provide GenenameFilter. gf <- GenenameFilter("BCL2") Test <- select(edb, keys = gf) expect_true(all(Test$GENENAME == "BCL2")) .comprehensiveCheckForGene(Test) Test2 <- select(edb, keys = ~ symbol == "BCL2") expect_equal(Test, Test2) ## ZBTB16 tmp <- select(edb, keys = GenenameFilter("ZBTB16")) .comprehensiveCheckForGene(tmp) ## BCL2L11 tmp <- select(edb, keys = GenenameFilter("BCL2L11")) .comprehensiveCheckForGene(tmp) ## NR3C1 tmp <- select(edb, keys = GenenameFilter("NR3C1")) .comprehensiveCheckForGene(tmp) ## Combine GenenameFilter and TxBiotypeFilter. Test2 <- select(edb, keys = ~ symbol == "BCL2" & tx_biotype == "protein_coding") expect_equal(Test$EXONID[Test$TXBIOTYPE == "protein_coding"], Test2$EXONID) ## Choose selected columns. Test3 <- select(edb, keys = gf, columns = c("GENEID", "GENENAME", "SEQNAME")) expect_equal(unique(Test[, c("GENEID", "GENENAME", "SEQNAME")]), Test3) ## Provide keys. Test4 <- select(edb, keys = "BCL2", keytype = "GENENAME") expect_equal(Test[, colnames(Test4)], Test4) gns <- keys(edb, "GENEID") ## Just get stuff from the tx table; should be faster. Test <- select(edb, keys = gns, columns = c("GENEID", "SEQNAME"), keytype = "GENEID") expect_equal(all(Test$GENEID == gns), TRUE) ## Get all lincRNA genes Test <- select(edb, keys = "lincRNA", columns = c("GENEID", "GENEBIOTYPE", "GENENAME"), keytype = "GENEBIOTYPE") Test2 <- select(edb, keys = GeneBiotypeFilter("lincRNA"), columns = c("GENEID", "GENEBIOTYPE", "GENENAME")) expect_equal(Test[, colnames(Test2)], Test2) ## All on chromosome 21 Test <- select(edb, keys = "21", columns = c("GENEID", "GENEBIOTYPE", "GENENAME"), keytype = "SEQNAME") Test2 <- select(edb, keys = ~ seq_name == "21", columns = c("GENEID", "GENEBIOTYPE", "GENENAME")) expect_equal(Test[, colnames(Test2)], Test2) ## What if we can't find it? Test <- select(edb, keys = "bla", columns = c("GENEID", "GENENAME"), keytype = "GENENAME") expect_equal(colnames(Test), c("GENEID", "GENENAME")) expect_true(nrow(Test) == 0) ## TXNAME Test <- select(edb, keys = "ENST00000000233", columns = c("GENEID", "GENENAME"), keytype = "TXNAME") expect_equal(Test$TXNAME, "ENST00000000233") ## Check what happens if we just add TXNAME and also TXID. Test2 <- select(edb, keys = list(gf, TxBiotypeFilter("protein_coding")), columns = c("TXID", "TXNAME", "GENENAME", "GENEID")) expect_equal(colnames(Test2), c("TXID", "TXNAME", "GENENAME", "GENEID", "TXBIOTYPE")) ## Protein stuff. if (hasProteinData(edb)) { ## Test: ## o if we're fetching with PROTEINID keys we're just getting protein ## coding tx, i.e. those with a tx_cds_seq_start not NULL AND we get ## also those with a uniprot ID null. pids <- c("ENSP00000338157", "ENSP00000437716", "ENSP00000443013", "ENSP00000376721", "ENSP00000445047") res <- select(edb, keys = pids, keytype = "PROTEINID", columns = c("TXID", "TXCDSSEQSTART", "TXBIOTYPE", "PROTEINID", "UNIPROTID", "PROTEINDOMAINID")) expect_equal(sort(pids), sort(unique(res$PROTEINID))) res_2 <- select(edb, keys = ProteinIdFilter(pids), columns = c("TXID", "TXCDSSEQSTART", "TXBIOTYPE", "PROTEINID", "UNIPROTID", "PROTEINDOMAINID")) expect_equal(sort(pids), sort(unique(res_2$PROTEINID))) expect_equal(res, res_2) expect_true(all(!is.na(res$TXCDSSEQSTART))) ## Do we have all of the uniprot ids? tmp <- dbGetQuery(dbconn(edb), paste0("select uniprot_id from uniprot where ", "protein_id in (", paste0("'", pids,"'", collapse = ", "),")")) a <- sort(unique(res$UNIPROTID)) b <- sort(unique(tmp$uniprot_id)) a <- a[!is.na(a)] b <- b[!is.na(b)] expect_equal(a, b) ## Do we have all protein domain ids? tmp <- dbGetQuery(dbconn(edb), paste0("select protein_domain_id from protein_domain ", "where protein_id in (", paste0("'", pids,"'", collapse = ", "),")")) a <- sort(unique(res$PROTEINDOMAINID)) b <- sort(unique(tmp$protein_domain_id)) a <- a[!is.na(a)] b <- b[!is.na(b)] expect_equal(a, b) ## o if we're fetching with uniprot and protein id filter we get all ## even if they don't have a protein domain. upids <- c("ZBT16_HUMAN", "Q71UL7_HUMAN", "Q71UL6_HUMAN", "Q71UL5_HUMAN") res <- select(edb, keys = upids, keytype = "UNIPROTID", columns = c("PROTEINID", "UNIPROTID", "PROTEINDOMAINID")) } }) test_that("mapIds works", { ## Simple... map gene ids to gene names allgenes <- keys(edb, keytype = "GENEID") randordergenes <- allgenes[sample(1:length(allgenes), 100)] mi <- mapIds(edb, keys = allgenes, keytype = "GENEID", column = "GENENAME") expect_equal(allgenes, names(mi)) ## Ordering should always match the ordering of the input: mi <- mapIds(edb, keys = randordergenes, keytype = "GENEID", column = "GENENAME") expect_equal(randordergenes, names(mi)) ## Handle multi mappings. ## o first first <- mapIds(edb, keys = randordergenes, keytype = "GENEID", column = "TXID") expect_equal(names(first), randordergenes) ## o list lis <- mapIds(edb, keys = randordergenes, keytype = "GENEID", column = "TXID", multiVals = "list") expect_equal(names(lis), randordergenes) Test <- lapply(lis, function(z){return(z[1])}) expect_equal(first, unlist(Test)) ## o filter filt <- mapIds(edb, keys = randordergenes, keytype = "GENEID", column = "TXID", multiVals = "filter") expect_equal(filt, unlist(lis[unlist(lapply(lis, length)) == 1])) ## o asNA asNA <- mapIds(edb, keys = randordergenes, keytype = "GENEID", column = "TXID", multiVals = "asNA") ## Check what happens if we provide 2 identical keys. Test <- mapIds(edb, keys = c("BCL2", "BCL2L11", "BCL2"), keytype = "GENENAME", column = "TXID") expect_equal(names(Test), c("BCL2", "BCL2L11", "BCL2")) expect_true(length(unique(Test)) == 2) ## Submit Filter: Test <- mapIds(edb, keys = SeqNameFilter("Y"), column = "GENEID", multiVals = "list") TestS <- select(edb, keys = Test[[1]], columns = "SEQNAME", keytype = "GENEID") expect_equal(unique(TestS$SEQNAME), "Y") ## Submit 2 filter.LLLLL Test <- mapIds(edb, keys = ~ seq_name == "Y" & seq_strand == "-", multiVals = "list", column = "GENEID") TestS <- select(edb, keys = Test[[1]], keytype = "GENEID", columns = c("SEQNAME", "SEQSTRAND")) expect_true(all(TestS$SEQNAME == "Y")) expect_true(all(TestS$SEQSTRAND == -1)) ## Now using protein annotations: if (hasProteinData(edb)) { library(RSQLite) txids <- keys(edb, keytype = "TXID", filter = GenenameFilter("ZBTB16")) mapd <- mapIds(edb, keys = txids, keytype = "TXID", column = "GENENAME") expect_equal(names(mapd), txids) expect_true(all(mapd == "ZBTB16")) ## Map to protein ids. mapd <- mapIds(edb, keys = txids, keytype = "TXID", column = "PROTEINID") res <- dbGetQuery(dbconn(edb), paste0("select protein_id from protein where tx_id in", " (", paste0("'", txids,"'", collapse = ", "), ")")) pids <- mapd[!is.na(mapd)] expect_true(all(pids %in% res$protein_id)) ## multi-mapping: ## proteins and uniprot. mapd <- mapIds(edb, keys = pids, keytype = "PROTEINID", column = "UNIPROTID", multiVals = "list") mapd <- mapd[!is.na(mapd)] res <- dbGetQuery(dbconn(edb), paste0("select protein_id, uniprot_id from uniprot ", "where protein_id in (", paste0("'", pids, "'", collapse = ", "), ")")) res <- split(res$uniprot_id, res$protein_id) expect_equal(mapd, res[names(mapd)]) ## Just to ensure: tmp <- proteins(edb, filter = ProteinIdFilter(pids), columns = c("uniprot_id", "protein_id")) upids <- tmp$uniprot_id[!is.na(tmp$uniprot_id)] expect_true(all(res$uniprot_id %in% upids)) ## map protein ids to gene name mapd <- mapIds(edb, keys = pids, keytype = "PROTEINID", column = "GENENAME") expect_true(all(mapd == "ZBTB16")) } }) ## Test if the results are properly sorted if we submit a single filter or just keys. test_that("select results are properly sorted", { ks <- c("ZBTB16", "BCL2", "SKA2", "BCL2L11") ## gene_id res <- select(edb, keys = ks, keytype = "GENENAME") expect_equal(unique(res$GENENAME), ks) res <- select(edb, keys = GenenameFilter(ks)) expect_equal(unique(res$GENENAME), ks) ## Using two filters; res <- select(edb, keys = list(GenenameFilter(ks), TxBiotypeFilter("nonsense_mediated_decay"))) ## We don't expect same sorting here! expect_true(!all(unique(res$GENENAME) == ks[ks %in% unique(res$GENENAME)])) res2 <- select(edb, keys = ~ genename == ks & tx_biotype == "nonsense_mediated_decay") expect_equal(res, res2) ## symbol res <- select(edb, keys = ks, keytype = "SYMBOL", columns = c("GENENAME", "SYMBOL", "SEQNAME")) expect_equal(res$SYMBOL, ks) expect_equal(res$GENENAME, ks) ## tx_biotype ks <- c("retained_intron", "nonsense_mediated_decay") res <- select(edb, keys = ks, keytype = "TXBIOTYPE", columns = c("GENENAME", "TXBIOTYPE")) expect_equal(unique(res$TXBIOTYPE), ks) res <- select(edb, keys = TxBiotypeFilter(ks), keytype = "TXBIOTYPE", columns = c("GENENAME", "TXBIOTYPE")) expect_equal(unique(res$TXBIOTYPE), ks) }) test_that("select works with symbol as keytype", { ks <- c("ZBTB16", "BCL2", "SKA2", "BCL2L11") res <- select(edb, keys = ks, keytype = "GENENAME") res2 <- select(edb, keys = ks, keytype = "SYMBOL") expect_equal(res, res2) res <- select(edb, keys = GenenameFilter(ks), columns = c("TXNAME", "SYMBOL", "GENEID")) expect_equal(colnames(res), c("TXNAME", "SYMBOL", "GENEID", "GENENAME")) res <- select(edb, keys = ~ symbol == ks, columns=c("GENEID")) expect_equal(colnames(res), c("GENEID", "SYMBOL")) expect_equal(res$SYMBOL, ks) res <- select(edb, keys = list(SeqNameFilter("Y"), GeneBiotypeFilter("lincRNA")), columns = c("GENEID", "SYMBOL")) expect_equal(colnames(res), c("GENEID", "SYMBOL", "SEQNAME", "GENEBIOTYPE")) expect_true(all(res$SEQNAME == "Y")) }) test_that("select works with txname", { ## TXNAME as a column ks <- c("ZBTB16", "BCL2", "SKA2") res <- select(edb, keys = ks, keytype = "GENENAME", columns = c("TXNAME")) expect_equal(colnames(res), c("GENENAME", "TXNAME")) }) test_that(".keytype2FilterMapping works", { ## Check whether or not we're getting protein columns. res <- ensembldb:::.keytype2FilterMapping() expect_equal(names(res), c("ENTREZID", "GENEID", "GENEBIOTYPE", "GENENAME", "TXID", "TXBIOTYPE", "EXONID", "SEQNAME", "SEQSTRAND", "TXNAME", "SYMBOL")) res <- ensembldb:::.keytype2FilterMapping(TRUE) expect_true(all(c("PROTEINID", "UNIPROTID", "PROTEINDOMAINID") %in% names(res))) }) test_that("keytypes works", { keyt <- c("ENTREZID", "GENEID", "GENEBIOTYPE", "GENENAME", "TXID", "TXBIOTYPE", "EXONID", "SEQNAME", "SEQSTRAND", "TXNAME", "SYMBOL") res <- keytypes(edb) if (hasProteinData(edb)) { expect_equal(res, sort(c(keyt, "PROTEINID", "UNIPROTID", "PROTEINDOMAINID"))) } else { expect_equal(res, sort(keyt)) } }) test_that("filterForKeytype works", { res <- ensembldb:::filterForKeytype("SYMBOL") expect_true(is(res, "SymbolFilter")) if (hasProteinData(edb)) { res <- ensembldb:::filterForKeytype("PROTEINDOMAINID", edb) expect_true(is(res, "ProtDomIdFilter")) } res <- ensembldb:::filterForKeytype("TXID") expect_true(is(res, "TxIdFilter")) }) ensembldb/tests/testthat/test_seqLevelStyle.R0000644000175400017540000004324113175714743022540 0ustar00biocbuildbiocbuild## Tests related to setting seqLevelsStyle test_that("seqlevelsStyle works", { orig <- getOption("ensembldb.seqnameNotFound") options(ensembldb.seqnameNotFound = NA) edb <- EnsDb.Hsapiens.v75 SL <- seqlevels(edb) ucscs <- paste0("chr", c(1:22, "X", "Y", "M")) seqlevelsStyle(edb) <- "UCSC" suppressWarnings( SL2 <- seqlevels(edb) ) expect_equal(sort(ucscs), sort(SL2[!is.na(SL2)])) ## Check if we throw an error message options(ensembldb.seqnameNotFound = "MISSING") expect_error(seqlevels(edb)) ## Check if returning original names works. options(ensembldb.seqnameNotFound = "ORIGINAL") suppressWarnings( SL3 <- seqlevels(edb) ) idx <- which(SL3 %in% ucscs) expect_equal(sort(SL[-idx]), sort(SL3[-idx])) options(ensembldb.seqnameNotFound=orig) }) test_that("seqinfo works with seqlevelsStyle", { edb <- EnsDb.Hsapiens.v75 orig <- getOption("ensembldb.seqnameNotFound") options(ensembldb.seqnameNotFound="MISSING") seqlevelsStyle(edb) <- "UCSC" expect_error(seqinfo(edb)) options(ensembldb.seqnameNotFound="ORIGINAL") suppressWarnings( si <- seqinfo(edb) ) options(ensembldb.seqnameNotFound=orig) }) test_that("getWhat works with seqlevelsStyle", { orig <- getOption("ensembldb.seqnameNotFound") edb <- EnsDb.Hsapiens.v75 seqlevelsStyle(edb) <- "Ensembl" ensRes <- ensembldb:::getWhat(edb, columns=c("seq_name", "seq_strand")) seqlevelsStyle(edb) <- "UCSC" suppressWarnings( ucscRes <- ensembldb:::getWhat(edb, columns=c("seq_name", "seq_strand")) ) seqlevelsStyle(edb) <- "NCBI" suppressWarnings( ncbiRes <- ensembldb:::getWhat(edb, columns=c("seq_name", "seq_strand")) ) options(ensembldb.seqnameNotFound=orig) }) test_that("SeqNameFilter works with seqlevelsStyle", { orig <- getOption("ensembldb.seqnameNotFound") options(ensembldb.seqnameNotFound="MISSING") edb <- EnsDb.Hsapiens.v75 seqlevelsStyle(edb) <- "Ensembl" snf <- SeqNameFilter("chrX") snfEns <- SeqNameFilter(c("X", "Y")) snfNo <- SeqNameFilter(c("bla", "blu")) snfSomeNo <- SeqNameFilter(c("bla", "X")) seqlevelsStyle(edb) <- "Ensembl" expect_equal(value(snf), "chrX") ## That makes no sense for a query though. expect_equal(value(snf), "chrX") expect_equal(value(snfEns), c("X", "Y")) seqlevelsStyle(edb) <- "UCSC" expect_equal(ensembldb:::ensDbQuery(snf, edb), "gene.seq_name = 'X'") expect_error(ensembldb:::ensDbQuery(snfEns, edb)) expect_error(ensembldb:::ensDbQuery(snfNo, edb)) expect_error(ensembldb:::ensDbQuery(snfSomeNo, edb)) ## Setting the options to "ORIGINAL" options(ensembldb.seqnameNotFound="ORIGINAL") expect_equal(ensembldb:::ensDbQuery(snf, edb), "gene.seq_name = 'X'") suppressWarnings( expect_equal(ensembldb:::ensDbQuery(snfEns, edb), "gene.seq_name in ('X','Y')") ) suppressWarnings( expect_equal(ensembldb:::ensDbQuery(snfNo, edb), "gene.seq_name in ('bla','blu')") ) suppressWarnings( expect_equal(ensembldb:::ensDbQuery(snfSomeNo, edb), "gene.seq_name in ('bla','X')") ) ## snf <- SeqNameFilter(c("chrX", "Y")) suppressWarnings( expect_equal(ensembldb:::ensDbQuery(snf, edb), "gene.seq_name in ('X','Y')") ) options(ensembldb.seqnameNotFound=orig) }) test_that("genes works with seqlevelsStyles", { orig <- getOption("ensembldb.seqnameNotFound") edb <- EnsDb.Hsapiens.v75 ## Here we want to test whether the result returned by the function does really ## work when changing the seqnames. seqlevelsStyle(edb) <- "Ensembl" ensAll <- genes(edb) ens21Y <- genes(edb, filter=SeqNameFilter(c("Y", "21"))) expect_equal(sort(as.character(unique(seqnames(ens21Y)))), c("21", "Y")) gr <- GRanges(seqnames="Y", ranges=IRanges(start=1, end=59373566), strand="+") ensY <- genes(edb, filter=GRangesFilter(gr)) expect_equal(seqlevels(ensY), "Y") expect_equal(unique(as.character(strand(ensY))), "+") ## Check UCSC stuff seqlevelsStyle(edb) <- "UCSC" options(ensembldb.seqnameNotFound="ORIGINAL") ## Just visually inspect the seqinfo and seqnames for the "all" query. ucscAll <- genes(edb) as.character(unique(seqnames(ucscAll))) ucsc21Y <- genes(edb, filter=SeqNameFilter(c("chrY", "chr21"))) expect_equal(sort(seqlevels(ucsc21Y)), c("chr21", "chrY")) expect_equal(sort(names(ens21Y)), sort(names(ucsc21Y))) ## GRangesFilter. gr <- GRanges(seqnames="chrY", ranges=IRanges(start=1, end=59373566), strand="+") ucscY <- genes(edb, filter=GRangesFilter(gr)) expect_equal(seqlevels(ucscY), "chrY") expect_equal(unique(as.character(strand(ucscY))), "+") expect_equal(sort(names(ensY)), sort(names(ucscY))) options(ensembldb.seqnameNotFound=orig) }) test_that("transcripts works with seqlevelsStyle", { orig <- getOption("ensembldb.seqnameNotFound") edb <- EnsDb.Hsapiens.v75 seqlevelsStyle(edb) <- "Ensembl" ens21Y <- transcripts(edb, filter = SeqNameFilter(c("Y", "21"))) expect_equal(sort(seqlevels(ens21Y)), c("21", "Y")) gr <- GRanges(seqnames="Y", ranges=IRanges(start=1, end=59373566), strand="+") ensY <- transcripts(edb, filter=GRangesFilter(gr)) expect_equal(seqlevels(ensY), "Y") expect_equal(unique(as.character(strand(ensY))), "+") ## Check UCSC stuff seqlevelsStyle(edb) <- "UCSC" options(ensembldb.seqnameNotFound="ORIGINAL") ucsc21Y <- transcripts(edb, filter=SeqNameFilter(c("chrY", "chr21"))) expect_equal(sort(seqlevels(ucsc21Y)), c("chr21", "chrY")) expect_equal(sort(names(ens21Y)), sort(names(ucsc21Y))) ## GRangesFilter. gr <- GRanges(seqnames="chrY", ranges=IRanges(start=1, end=59373566), strand="+") ucscY <- transcripts(edb, filter=GRangesFilter(gr)) expect_equal(seqlevels(ucscY), "chrY") expect_equal(unique(as.character(strand(ucscY))), "+") expect_equal(sort(names(ensY)), sort(names(ucscY))) options(ensembldb.seqnameNotFound=orig) }) test_that("transcriptsBy works with seqlevelsStyle", { orig <- getOption("ensembldb.seqnameNotFound") edb <- EnsDb.Hsapiens.v75 seqlevelsStyle(edb) <- "Ensembl" ens21Y <- transcriptsBy(edb, filter=SeqNameFilter(c("Y", "21"))) expect_equal(sort(seqlevels(ens21Y)), c("21", "Y")) gr <- GRanges(seqnames="Y", ranges=IRanges(start=1, end=59373566), strand="+") ensY <- transcriptsBy(edb, filter=GRangesFilter(gr)) expect_equal(seqlevels(ensY), "Y") suppressWarnings( expect_equal(unique(as.character(unlist(strand(ensY)))), "+") ) ## Check UCSC stuff seqlevelsStyle(edb) <- "UCSC" options(ensembldb.seqnameNotFound="ORIGINAL") ucsc21Y <- transcriptsBy(edb, filter=SeqNameFilter(c("chrY", "chr21"))) expect_equal(sort(seqlevels(ucsc21Y)), c("chr21", "chrY")) expect_equal(sort(names(ens21Y)), sort(names(ucsc21Y))) ## GRangesFilter. gr <- GRanges(seqnames="chrY", ranges=IRanges(start=1, end=59373566), strand="+") ucscY <- transcriptsBy(edb, filter=GRangesFilter(gr)) expect_equal(seqlevels(ucscY), "chrY") suppressWarnings( expect_equal(unique(as.character(unlist(strand(ucscY)))), "+") ) expect_equal(sort(names(ensY)), sort(names(ucscY))) options(ensembldb.seqnameNotFound=orig) }) test_that("exons works with seqlevelsStyle", { orig <- getOption("ensembldb.seqnameNotFound") edb <- EnsDb.Hsapiens.v75 seqlevelsStyle(edb) <- "Ensembl" ens21Y <- exons(edb, filter=SeqNameFilter(c("Y", "21"))) expect_equal(sort(seqlevels(ens21Y)), c("21", "Y")) gr <- GRanges(seqnames="Y", ranges=IRanges(start=1, end=59373566), strand="+") ensY <- exons(edb, filter=GRangesFilter(gr)) expect_equal(seqlevels(ensY), "Y") expect_equal(unique(as.character(strand(ensY))), "+") ## Check UCSC stuff seqlevelsStyle(edb) <- "UCSC" options(ensembldb.seqnameNotFound="ORIGINAL") ucsc21Y <- exons(edb, filter=SeqNameFilter(c("chrY", "chr21"))) expect_equal(sort(seqlevels(ucsc21Y)), c("chr21", "chrY")) expect_equal(sort(names(ens21Y)), sort(names(ucsc21Y))) ## GRangesFilter. gr <- GRanges(seqnames="chrY", ranges=IRanges(start=1, end=59373566), strand="+") ucscY <- exons(edb, filter=GRangesFilter(gr)) expect_equal(seqlevels(ucscY), "chrY") expect_equal(unique(as.character(strand(ucscY))), "+") expect_equal(sort(names(ensY)), sort(names(ucscY))) options(ensembldb.seqnameNotFound=orig) }) test_that("exonsBy works with seqlevelsStyle", { orig <- getOption("ensembldb.seqnameNotFound") edb <- EnsDb.Hsapiens.v75 seqlevelsStyle(edb) <- "Ensembl" ens21Y <- exonsBy(edb, filter=SeqNameFilter(c("Y", "21"))) expect_equal(sort(seqlevels(ens21Y)), c("21", "Y")) gr <- GRanges(seqnames="Y", ranges=IRanges(start=1, end=59373566), strand="+") ensY <- exonsBy(edb, filter=GRangesFilter(gr)) expect_equal(seqlevels(ensY), "Y") suppressWarnings( expect_equal(unique(as.character(unlist(strand(ensY)))), "+") ) ## Check UCSC stuff seqlevelsStyle(edb) <- "UCSC" options(ensembldb.seqnameNotFound="ORIGINAL") ucsc21Y <- exonsBy(edb, filter=SeqNameFilter(c("chrY", "chr21"))) expect_equal(sort(seqlevels(ucsc21Y)), c("chr21", "chrY")) expect_equal(sort(names(ens21Y)), sort(names(ucsc21Y))) ## GRangesFilter. gr <- GRanges(seqnames="chrY", ranges=IRanges(start=1, end=59373566), strand="+") ucscY <- exonsBy(edb, filter=GRangesFilter(gr)) expect_equal(seqlevels(ucscY), "chrY") suppressWarnings( expect_equal(unique(as.character(unlist(strand(ucscY)))), "+") ) expect_equal(sort(names(ensY)), sort(names(ucscY))) options(ensembldb.seqnameNotFound=orig) }) test_that("cdsBy works with seqlevelsStyle", { orig <- getOption("ensembldb.seqnameNotFound") edb <- EnsDb.Hsapiens.v75 seqlevelsStyle(edb) <- "Ensembl" ens21Y <- cdsBy(edb, filter=SeqNameFilter(c("Y", "21"))) expect_equal(sort(seqlevels(ens21Y)), c("21", "Y")) gr <- GRanges(seqnames="Y", ranges=IRanges(start=1, end=59373566), strand="+") ensY <- cdsBy(edb, filter=GRangesFilter(gr)) expect_equal(seqlevels(ensY), "Y") suppressWarnings( expect_equal(unique(as.character(unlist(strand(ensY)))), "+") ) ## Check UCSC stuff seqlevelsStyle(edb) <- "UCSC" options(ensembldb.seqnameNotFound="ORIGINAL") ucsc21Y <- cdsBy(edb, filter=SeqNameFilter(c("chrY", "chr21"))) expect_equal(sort(seqlevels(ucsc21Y)), c("chr21", "chrY")) expect_equal(sort(names(ens21Y)), sort(names(ucsc21Y))) ## GRangesFilter. gr <- GRanges(seqnames="chrY", ranges=IRanges(start=1, end=59373566), strand="+") ucscY <- cdsBy(edb, filter=GRangesFilter(gr)) expect_equal(seqlevels(ucscY), "chrY") suppressWarnings( expect_equal(unique(as.character(unlist(strand(ucscY)))), "+") ) expect_equal(sort(names(ensY)), sort(names(ucscY))) options(ensembldb.seqnameNotFound=orig) }) test_that("threeUTRsByTranscript works with seqlevelsStyle", { orig <- getOption("ensembldb.seqnameNotFound") edb <- EnsDb.Hsapiens.v75 seqlevelsStyle(edb) <- "Ensembl" ens21Y <- threeUTRsByTranscript(edb, filter=SeqNameFilter(c("Y", "21"))) expect_equal(sort(seqlevels(ens21Y)), c("21", "Y")) gr <- GRanges(seqnames="Y", ranges=IRanges(start=1, end=59373566), strand="+") ensY <- threeUTRsByTranscript(edb, filter=GRangesFilter(gr)) expect_equal(seqlevels(ensY), "Y") suppressWarnings( expect_equal(unique(as.character(unlist(strand(ensY)))), "+") ) ## Check UCSC stuff seqlevelsStyle(edb) <- "UCSC" options(ensembldb.seqnameNotFound="ORIGINAL") ucsc21Y <- threeUTRsByTranscript(edb, filter=SeqNameFilter(c("chrY", "chr21"))) expect_equal(sort(seqlevels(ucsc21Y)), c("chr21", "chrY")) expect_equal(sort(names(ens21Y)), sort(names(ucsc21Y))) ## GRangesFilter. gr <- GRanges(seqnames="chrY", ranges=IRanges(start=1, end=59373566), strand="+") ucscY <- threeUTRsByTranscript(edb, filter=GRangesFilter(gr)) expect_equal(seqlevels(ucscY), "chrY") suppressWarnings( expect_equal(unique(as.character(unlist(strand(ucscY)))), "+") ) expect_equal(sort(names(ensY)), sort(names(ucscY))) options(ensembldb.seqnameNotFound=orig) }) test_that("fiveUTRsByTranscript works with seqlevelsStyle", { orig <- getOption("ensembldb.seqnameNotFound") edb <- EnsDb.Hsapiens.v75 seqlevelsStyle(edb) <- "Ensembl" ens21Y <- fiveUTRsByTranscript(edb, filter=SeqNameFilter(c("Y", "21"))) expect_equal(sort(seqlevels(ens21Y)), c("21", "Y")) gr <- GRanges(seqnames="Y", ranges=IRanges(start=1, end=59373566), strand="+") ensY <- fiveUTRsByTranscript(edb, filter=GRangesFilter(gr)) expect_equal(seqlevels(ensY), "Y") suppressWarnings( expect_equal(unique(as.character(unlist(strand(ensY)))), "+") ) ## Check UCSC stuff seqlevelsStyle(edb) <- "UCSC" options(ensembldb.seqnameNotFound="ORIGINAL") ucsc21Y <- fiveUTRsByTranscript(edb, filter=SeqNameFilter(c("chrY", "chr21"))) expect_equal(sort(seqlevels(ucsc21Y)), c("chr21", "chrY")) expect_equal(sort(names(ens21Y)), sort(names(ucsc21Y))) ## GRangesFilter. gr <- GRanges(seqnames="chrY", ranges=IRanges(start=1, end=59373566), strand="+") ucscY <- fiveUTRsByTranscript(edb, filter=GRangesFilter(gr)) expect_equal(seqlevels(ucscY), "chrY") suppressWarnings( expect_equal(unique(as.character(unlist(strand(ucscY)))), "+") ) expect_equal(sort(names(ensY)), sort(names(ucscY))) options(ensembldb.seqnameNotFound=orig) }) test_that("seting and getting seqlevelsStyle works", { edb <- EnsDb.Hsapiens.v75 ## Testing the getter/setter for the seqlevelsStyle. expect_equal(seqlevelsStyle(edb), "Ensembl") expect_equal(NA, ensembldb:::getProperty(edb, "seqlevelsStyle")) seqlevelsStyle(edb) <- "Ensembl" expect_equal(seqlevelsStyle(edb), "Ensembl") expect_equal("Ensembl", ensembldb:::getProperty(edb, "seqlevelsStyle")) ## Try NCBI. seqlevelsStyle(edb) <- "NCBI" expect_equal(seqlevelsStyle(edb), "NCBI") ## Try UCSC. seqlevelsStyle(edb) <- "UCSC" expect_equal(seqlevelsStyle(edb), "UCSC") ## Error checking: expect_error(seqlevelsStyle(edb) <- "bla") }) test_that("formatting seqnames for query works with seqlevelsStyle", { ## Testing if the formating/mapping between seqnames works as expected ## We want to map anything TO Ensembl. ## Check also the warning messages! ucscs <- c("chr1", "chr3", "chr1", "chr9", "chrM", "chr1", "chrX") enses <- c("1", "3", "1", "9", "MT", "1", "X") ## reset edb <- EnsDb.Hsapiens.v75 ## Shouldn't do anything here. seqlevelsStyle(edb) ensembldb:::dbSeqlevelsStyle(edb) got <- ensembldb:::formatSeqnamesForQuery(edb, enses) expect_equal(got, enses) ## Change the seqlevels to UCSC seqlevelsStyle(edb) <- "UCSC" ## If ifNotFound is not specified we suppose to get an error. options(ensembldb.seqnameNotFound="MISSING") expect_error(ensembldb:::formatSeqnamesForQuery(edb, enses)) ## With specifying ifNotFound suppressWarnings( got <- ensembldb:::formatSeqnamesForQuery(edb, enses, ifNotFound=NA) ) expect_equal(all(is.na(got)), TRUE) ## Same by setting the option options(ensembldb.seqnameNotFound=NA) suppressWarnings( got <- ensembldb:::formatSeqnamesForQuery(edb, enses) ) expect_equal(all(is.na(got)), TRUE) ## Now the working example: got <- ensembldb:::formatSeqnamesForQuery(edb, ucscs) expect_equal(got, enses) ## What if one is not mappable: suppressWarnings( got <- ensembldb:::formatSeqnamesForQuery(edb, c(ucscs, "asdfd"), ifNotFound=NA) ) expect_equal(got, c(enses, NA)) }) test_that("formating seqnames from query works with seqlevelsStyle", { ucscs <- c("chr1", "chr3", "chr1", "chr9", "chrM", "chr1", "chrX") enses <- c("1", "3", "1", "9", "MT", "1", "X") edb <- EnsDb.Hsapiens.v75 ## Shouldn't do anything here. seqlevelsStyle(edb) ensembldb:::dbSeqlevelsStyle(edb) got <- ensembldb:::formatSeqnamesFromQuery(edb, enses) expect_equal(got, enses) ## Change the seqlevels to UCSC seqlevelsStyle(edb) <- "UCSC" ## If ifNotFound is not specified we suppose to get an error. options(ensembldb.seqnameNotFound="MISSING") expect_error(ensembldb:::formatSeqnamesFromQuery(edb, ucsc)) ## With specifying ifNotFound suppressWarnings( got <- ensembldb:::formatSeqnamesFromQuery(edb, ucscs, ifNotFound=NA) ) expect_equal(all(is.na(got)), TRUE) ## Same using options options(ensembldb.seqnameNotFound=NA) suppressWarnings( got <- ensembldb:::formatSeqnamesFromQuery(edb, ucscs, ifNotFound=NA) ) expect_equal(all(is.na(got)), TRUE) ## Now the working example: got <- ensembldb:::formatSeqnamesFromQuery(edb, enses) expect_equal(got, ucscs) ## What if one is not mappable: suppressWarnings( got <- ensembldb:::formatSeqnamesFromQuery(edb, c(enses, "asdfd"), ifNotFound=NA) ) expect_equal(got, c(ucscs, NA)) suppressWarnings( got <- ensembldb:::formatSeqnamesFromQuery(edb, c(enses, "asdfd")) ) expect_equal(got, c(ucscs, NA)) }) test_that("prefixChromName works", { res <- ensembldb:::ucscToEns("chrY") expect_equal(res, "Y") res <- ensembldb:::prefixChromName("Y") expect_equal(res, "Y") useU <- getOption("ucscChromosomeNames", default = FALSE) options(ucscChromosomeNames = TRUE) res <- ensembldb:::prefixChromName("Y") expect_equal(res, "chrY") options(ucscChromosomeNames = useU) }) ensembldb/tests/testthat/test_validity.R0000644000175400017540000000072113175714743021560 0ustar00biocbuildbiocbuild test_that("validity functions work", { OK <- ensembldb:::dbHasRequiredTables(dbconn(edb)) expect_true(OK) ## Check the tables OK <- ensembldb:::dbHasValidTables(dbconn(edb)) expect_true(OK) }) test_that("validateEnsDb works", { expect_true(ensembldb:::validateEnsDb(edb)) }) test_that("compareProteins works", { if (hasProteinData(edb)) { res <- ensembldb:::compareProteins(edb, edb) expect_equal(res, "OK") } }) ensembldb/vignettes/0000755000175400017540000000000013241155731015545 5ustar00biocbuildbiocbuildensembldb/vignettes/MySQL-backend.Rmd0000644000175400017540000000457113175714743020564 0ustar00biocbuildbiocbuild--- title: "Using a MySQL server backend" author: "Johannes Rainer" package: ensembldb output: BiocStyle::html_document: toc_float: true vignette: > %\VignetteIndexEntry{Using a MySQL server backend} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} %\VignetteDepends{ensembldb,EnsDb.Hsapiens.v75,BiocStyle} --- # Introduction `ensembldb` uses by default, similar to other annotation packages in Bioconductor, a SQLite database backend, i.e. annotations are retrieved from file-based SQLite databases that are provided *via* packages, such as the `EnsDb.Hsapiens.v75` package. In addition, `ensembldb` allows to switch the backend from SQLite to MySQL and thus to retrieve annotations from a MySQL server instead. Such a setup might be useful for a lab running a well-configured MySQL server that would require installation of EnsDb databases only on the database server and not on the individual clients. **Note** the code in this document is not executed during vignette generation as this would require access to a MySQL server. # Using `ensembldb` with a MySQL server Installation of `EnsDb` databases in a MySQL server is straight forward - given that the user has write access to the server: ```{r eval = FALSE } library(ensembldb) ## Load the EnsDb package that should be installed on the MySQL server library(EnsDb.Hsapiens.v75) ## Call the useMySQL method providing the required credentials to create ## databases and inserting data on the MySQL server edb_mysql <- useMySQL(EnsDb.Hsapiens.v75, host = "localhost", user = "userwrite", pass = "userpass") ## Use this EnsDb object genes(edb_mysql) ``` To use an `EnsDb` in a MySQL server without the need to install the corresponding R-package, the connection to the database can be passed to the `EnsDb` constructor function. With the resulting `EnsDb` object annotations can be retrieved from the MySQL database. ```{r eval = FALSE } library(ensembldb) library(RMySQL) ## Connect to the MySQL database to list the databases. dbcon <- dbConnect(MySQL(), host = "localhost", user = "readonly", pass = "readonly") ## List the available databases listEnsDbs(dbcon) ## Connect to one of the databases and use that one. dbcon <- dbConnect(MySQL(), host = "localhost", user = "readonly", pass = "readonly", dbname = "ensdb_hsapiens_v75") edb <- EnsDb(dbcon) edb ``` ensembldb/vignettes/MySQL-backend.org0000644000175400017540000000526313175714743020630 0ustar00biocbuildbiocbuild#+TITLE: Using a MySQL server backend #+AUTHOR: Johannes Rainer #+EMAIL: johannes.rainer@eurac.edu #+OPTIONS: ^:{} toc:nil #+PROPERTY: header-args :exports code #+PROPERTY: header-args :session *R* #+BEGIN_EXPORT html --- title: "Using a MySQL server backend" author: "Johannes Rainer" package: ensembldb output: BiocStyle::html_document: toc_float: true vignette: > %\VignetteIndexEntry{Using a MySQL server backend} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} %\VignetteDepends{ensembldb,EnsDb.Hsapiens.v75,BiocStyle} --- #+END_EXPORT ** Introduction =ensembldb= uses by default, similar to other annotation packages in Bioconductor, a SQLite database backend, i.e. annotations are retrieved from file-based SQLite databases that are provided /via/ packages, such as the =EnsDb.Hsapiens.v75= package. In addition, =ensembldb= allows to switch the backend from SQLite to MySQL and thus to retrieve annotations from a MySQL server instead. Such a setup might be useful for a lab running a well-configured MySQL server that would require installation of EnsDb databases only on the database server and not on the individual clients. *Note* the code in this document is not executed during vignette generation as this would require access to a MySQL server. ** Using =ensembldb= with a MySQL server Installation of =EnsDb= databases in a MySQL server is straight forward - given that the user has write access to the server: #+BEGIN_SRC R :ravel eval = FALSE library(ensembldb) ## Load the EnsDb package that should be installed on the MySQL server library(EnsDb.Hsapiens.v75) ## Call the useMySQL method providing the required credentials to create ## databases and inserting data on the MySQL server edb_mysql <- useMySQL(EnsDb.Hsapiens.v75, host = "localhost", user = "userwrite", pass = "userpass") ## Use this EnsDb object genes(edb_mysql) #+END_SRC To use an =EnsDb= in a MySQL server without the need to install the corresponding R-package, the connection to the database can be passed to the =EnsDb= constructor function. With the resulting =EnsDb= object annotations can be retrieved from the MySQL database. #+BEGIN_SRC R :ravel eval = FALSE library(ensembldb) library(RMySQL) ## Connect to the MySQL database to list the databases. dbcon <- dbConnect(MySQL(), host = "localhost", user = "readonly", pass = "readonly") ## List the available databases listEnsDbs(dbcon) ## Connect to one of the databases and use that one. dbcon <- dbConnect(MySQL(), host = "localhost", user = "readonly", pass = "readonly", dbname = "ensdb_hsapiens_v75") edb <- EnsDb(dbcon) edb #+END_SRC ensembldb/vignettes/ensembldb.Rmd0000644000175400017540000014012513175714743020161 0ustar00biocbuildbiocbuild--- title: "Generating an using Ensembl based annotation packages" author: "Johannes Rainer" graphics: yes package: ensembldb output: BiocStyle::html_document: toc_float: true vignette: > %\VignetteIndexEntry{Generating an using Ensembl based annotation packages} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} %\VignetteDepends{ensembldb,EnsDb.Hsapiens.v75,BiocStyle,AnnotationHub,ggbio,Gviz,magrittr} --- # Introduction The `ensembldb` package provides functions to create and use transcript centric annotation databases/packages. The annotation for the databases are directly fetched from Ensembl 1 using their Perl API. The functionality and data is similar to that of the `TxDb` packages from the `GenomicFeatures` package, but, in addition to retrieve all gene/transcript models and annotations from the database, the `ensembldb` package provides also a filter framework allowing to retrieve annotations for specific entries like genes encoded on a chromosome region or transcript models of lincRNA genes. From version 1.7 on, `EnsDb` databases created by the `ensembldb` package contain also protein annotation data (see Section [11](#org5bd9a97) for the database layout and an overview of available attributes/columns). For more information on the use of the protein annotations refer to the *proteins* vignette. Another main goal of this package is to generate *versioned* annotation packages, i.e. annotation packages that are build for a specific Ensembl release, and are also named according to that (e.g. `EnsDb.Hsapiens.v75` for human gene definitions of the Ensembl code database version 75). This ensures reproducibility, as it allows to load annotations from a specific Ensembl release also if newer versions of annotation packages/releases are available. It also allows to load multiple annotation packages at the same time in order to e.g. compare gene models between Ensembl releases. In the example below we load an Ensembl based annotation package for Homo sapiens, Ensembl version 75. The `EnsDb` object providing access to the underlying SQLite database is bound to the variable name `EnsDb.Hsapiens.v75`. ```{r load-libs, warning=FALSE, message=FALSE } library(EnsDb.Hsapiens.v75) ## Making a "short cut" edb <- EnsDb.Hsapiens.v75 ## print some informations for this package edb ## For what organism was the database generated? organism(edb) ``` ```{r no-network, echo = FALSE, results = "hide" } ## Disable code chunks that require network connection - conditionally ## disable this on Windows only. This is to avoid TIMEOUT errors on the ## Bioconductor Windows build maching (issue #47). use_network <- FALSE ``` # Using `ensembldb` annotation packages to retrieve specific annotations One of the strengths of the `ensembldb` package and the related `EnsDb` databases is its implementation of a filter framework that enables to efficiently extract data sub-sets from the databases. The `ensembldb` package supports most of the filters defined in the `AnnotationFilter` Bioconductor package and defines some additional filters specific to the data stored in `EnsDb` databases. Filters can be passed directly to all methods extracting data from an `EnsDb` (such as `genes`, `transcripts` or `exons`). Alternatively it is possible with the `addFilter` or `filter` functions to add a filter directly to an `EnsDb` which will then be used in all queries on that object. The `supportedFilters` method can be used to get an overview over all supported filter classes, each of them (except the `GRangesFilter`) working on a single column/field in the database. ```{r filters } supportedFilters(edb) ``` These filters can be divided into 3 main filter types: - `IntegerFilter`: filter classes extending this basic object can take a single numeric value as input and support the conditions `=, !`, >, <, >= and <=. All filters that work on chromosomal coordinates, such as the `GeneEndFilter` extend `IntegerFilter`. - `CharacterFilter`: filter classes extending this object can take a single or multiple character values as input and allow conditions: `=, !`, "startsWith" and "endsWith". All filters working on IDs extend this class. - `GRangesFilter`: takes a `GRanges` object as input and supports all conditions that `findOverlaps` from the `IRanges` package supports ("any", "start", "end", "within", "equal"). Note that these have to be passed using the parameter `type` to the constructor function. The supported filters are: - `EntrezFilter`: allows to filter results based on NCBI Entrezgene identifiers of the genes. - `ExonEndFilter`: filter using the chromosomal end coordinate of exons. - `ExonIdFilter`: filter based on the (Ensembl) exon identifiers. - `ExonRankFilter`: filter based on the rank (index) of an exon within the transcript model. Exons are always numbered from 5' to 3' end of the transcript, thus, also on the reverse strand, the exon 1 is the most 5' exon of the transcript. - `ExonStartFilter`: filter using the chromosomal start coordinate of exons. - `GeneBiotypeFilter`: filter using the gene biotypes defined in the Ensembl database; use the `listGenebiotypes` method to list all available biotypes. - `GeneEndFilter`: filter using the chromosomal end coordinate of gene. - `GeneIdFilter`: filter based on the Ensembl gene IDs. - `GenenameFilter`: filter based on the names (symbols) of the genes. - `GeneStartFilter`: filter using the chromosomal start coordinate of gene. - `GRangesFilter`: allows to retrieve all features (genes, transcripts or exons) that are either within (setting parameter `type` to "within") or partially overlapping (setting `type` to "any") the defined genomic region/range. Note that, depending on the called method (`genes`, `transcripts` or `exons`) the start and end coordinates of either the genes, transcripts or exons are used for the filter. For methods `exonsBy`, `cdsBy` and `txBy` the coordinates of `by` are used. - `SeqNameFilter`: filter by the name of the chromosomes the genes are encoded on. - `SeqStrandFilter`: filter for the chromosome strand on which the genes are encoded. - `SymbolFilter`: filter on gene symbols; note that no database columns *symbol* is available in an `EnsDb` database and hence the gene name is used for filtering. - `TxBiotypeFilter`: filter on the transcript biotype defined in Ensembl; use the `listTxbiotypes` method to list all available biotypes. - `TxEndFilter`: filter using the chromosomal end coordinate of transcripts. - `TxIdFilter`: filter on the Ensembl transcript identifiers. - `TxNameFilter`: filter on the Ensembl transcript names (currently identical to the transcript IDs). - `TxStartFilter`: filter using the chromosomal start coordinate of transcripts. In addition to the above listed *DNA-RNA-based* filters, *protein-specific* filters are also available: - `ProtDomIdFilter`: filter by the protein domain ID. - `ProteinIdFilter`: filter by Ensembl protein ID filters. - `UniprotDbFilter`: filter by the name of the Uniprot database. - `UniprotFilter`: filter by the Uniprot ID. - `UniprotMappingTypeFilter`: filter by the mapping type of Ensembl protein IDs to Uniprot IDs. These can however only be used on `EnsDb` databases that provide protein annotations, i.e. for which a call to `hasProteinData` returns `TRUE`. `EnsDb` databases for more recent Ensembl versions (starting from Ensembl 87) provide also evidence levels for individual transcripts in the `tx_support_level` database column. Such databases support also a `TxSupportLevelFilter` filter to use this columns for filtering. A simple use case for the filter framework would be to get all transcripts for the gene *BCL2L11*. To this end we specify a `GenenameFilter` with the value *BCL2L11*. As a result we get a `GRanges` object with `start`, `end`, `strand` and `seqname` being the start coordinate, end coordinate, chromosome name and strand for the respective transcripts. All additional annotations are available as metadata columns. Alternatively, by setting `return.type` to "DataFrame", or "data.frame" the method would return a `DataFrame` or `data.frame` object instead of the default `GRanges`. ```{r transcripts } Tx <- transcripts(edb, filter = list(GenenameFilter("BCL2L11"))) Tx ## as this is a GRanges object we can access e.g. the start coordinates with head(start(Tx)) ## or extract the biotype with head(Tx$tx_biotype) ``` The parameter `columns` of the extractor methods (such as `exons`, `genes` or `transcripts)` allows to specify which database attributes (columns) should be retrieved. The `exons` method returns by default all exon-related columns, the `transcripts` all columns from the transcript database table and the `genes` all from the gene table. Note however that in the example above we got also a column `gene_name` although this column is not present in the transcript database table. By default the methods return also all columns that are used by any of the filters submitted with the `filter` argument (thus, because a `GenenameFilter` was used, the column `gene_name` is also returned). Setting `returnFilterColumns(edb) <- FALSE` disables this option and only the columns specified by the `columns` parameter are retrieved. Instead of passing a filter *object* to the method it is also possible to provide a filter *expression* written as a `formula`. The `formula` has to be written in the form `~ ` with `` being the field (database column) in the database, `` the condition for the filter object and `` its value. Use the `supportedFilter` method to get the field names corresponding to each filter class. ```{r transcripts-filter-expression } ## Use a filter expression to perform the filtering. transcripts(edb, filter = ~ genename == "ZBTB16") ``` Filter expression have to be written as a formula (i.e. starting with a `~`) in the form *column name* followed by the logical condition. Alternatively, `EnsDb` objects can be filtered directly using the `filter` function. In the example below we use the `filter` function to filter the `EnsDb` object and pass that filtered database to the `transcripts` method using the `%>%` from the `magrittr` package. ```{r transcripts-filter } library(magrittr) filter(edb, ~ symbol == "BCL2" & tx_biotype != "protein_coding") %>% transcripts ``` Adding a filter to an `EnsDb` enables this filter (globally) on all subsequent queries on that object. We could thus filter an `EnsDb` to (virtually) contain only features encoded on chromosome Y. ```{r filter-Y } edb_y <- addFilter(edb, SeqNameFilter("Y")) ## All subsequent filters on that EnsDb will only work on features encoded on ## chromosome Y genes(edb_y) ## Get all lincRNAs on chromosome Y genes(edb_y, filter = ~ gene_biotype == "lincRNA") ``` To get an overview of database tables and available columns the function `listTables` can be used. The method `listColumns` on the other hand lists columns for the specified database table. ```{r list-columns } ## list all database tables along with their columns listTables(edb) ## list columns from a specific table listColumns(edb, "tx") ``` Thus, we could retrieve all transcripts of the biotype *nonsense\_mediated\_decay* (which, according to the definitions by Ensembl are transcribed, but most likely not translated in a protein, but rather degraded after transcription) along with the name of the gene for each transcript. Note that we are changing here the `return.type` to `DataFrame`, so the method will return a `DataFrame` with the results instead of the default `GRanges`. ```{r transcripts-example2 } Tx <- transcripts(edb, columns = c(listColumns(edb , "tx"), "gene_name"), filter = TxBiotypeFilter("nonsense_mediated_decay"), return.type = "DataFrame") nrow(Tx) Tx ``` For protein coding transcripts, we can also specifically extract their coding region. In the example below we extract the CDS for all transcripts encoded on chromosome Y. ```{r cdsBy } yCds <- cdsBy(edb, filter = SeqNameFilter("Y")) yCds ``` Using a `GRangesFilter` we can retrieve all features from the database that are either within or overlapping the specified genomic region. In the example below we query all genes that are partially overlapping with a small region on chromosome 11. The filter restricts to all genes for which either an exon or an intron is partially overlapping with the region. ```{r genes-GRangesFilter } ## Define the filter grf <- GRangesFilter(GRanges("11", ranges = IRanges(114000000, 114000050), strand = "+"), type = "any") ## Query genes: gn <- genes(edb, filter = grf) gn ## Next we retrieve all transcripts for that gene so that we can plot them. txs <- transcripts(edb, filter = GenenameFilter(gn$gene_name)) ``` ```{r tx-for-zbtb16, message=FALSE, fig.align='center', fig.width=7.5, fig.height=5 } plot(3, 3, pch = NA, xlim = c(start(gn), end(gn)), ylim = c(0, length(txs)), yaxt = "n", ylab = "") ## Highlight the GRangesFilter region rect(xleft = start(grf), xright = end(grf), ybottom = 0, ytop = length(txs), col = "red", border = "red") for(i in 1:length(txs)) { current <- txs[i] rect(xleft = start(current), xright = end(current), ybottom = i-0.975, ytop = i-0.125, border = "grey") text(start(current), y = i-0.5, pos = 4, cex = 0.75, labels = current$tx_id) } ``` As we can see, 4 transcripts of the gene ZBTB16 are also overlapping the region. Below we fetch these 4 transcripts. Note, that a call to `exons` will not return any features from the database, as no exon is overlapping with the region. ```{r transcripts-GRangesFilter } transcripts(edb, filter = grf) ``` The `GRangesFilter` supports also `GRanges` defining multiple regions and a query will return all features overlapping any of these regions. Besides using the `GRangesFilter` it is also possible to search for transcripts or exons overlapping genomic regions using the `exonsByOverlaps` or `transcriptsByOverlaps` known from the `GenomicFeatures` package. Note that the implementation of these methods for `EnsDb` objects supports also to use filters to further fine-tune the query. The functions `listGenebiotypes` and `listTxbiotypes` can be used to get an overview of allowed/available gene and transcript biotype ```{r biotypes } ## Get all gene biotypes from the database. The GeneBiotypeFilter ## allows to filter on these values. listGenebiotypes(edb) ## Get all transcript biotypes from the database. listTxbiotypes(edb) ``` Data can be fetched in an analogous way using the `exons` and `genes` methods. In the example below we retrieve `gene_name`, `entrezid` and the `gene_biotype` of all genes in the database which names start with "BCL2". ```{r genes-BCL2 } ## We're going to fetch all genes which names start with BCL. To this end ## we define a GenenameFilter with partial matching, i.e. condition "like" ## and a % for any character/string. BCLs <- genes(edb, columns = c("gene_name", "entrezid", "gene_biotype"), filter = GenenameFilter("BCL", condition = "startsWith"), return.type = "DataFrame") nrow(BCLs) BCLs ``` Sometimes it might be useful to know the length of genes or transcripts (i.e. the total sum of nucleotides covered by their exons). Below we calculate the mean length of transcripts from protein coding genes on chromosomes X and Y as well as the average length of snoRNA, snRNA and rRNA transcripts encoded on these chromosomes. For the first query we combine two `AnnotationFilter` objects using an `AnnotationFilterList` object, in the second we define the query using a filter expression. ```{r example-AnnotationFilterList } ## determine the average length of snRNA, snoRNA and rRNA genes encoded on ## chromosomes X and Y. mean(lengthOf(edb, of = "tx", filter = AnnotationFilterList( GeneBiotypeFilter(c("snRNA", "snoRNA", "rRNA")), SeqNameFilter(c("X", "Y"))))) ## determine the average length of protein coding genes encoded on the same ## chromosomes. mean(lengthOf(edb, of = "tx", filter = ~ gene_biotype == "protein_coding" & seq_name %in% c("X", "Y"))) ``` Not unexpectedly, transcripts of protein coding genes are longer than those of snRNA, snoRNA or rRNA genes. At last we extract the first two exons of each transcript model from the database. ```{r example-first-two-exons } ## Extract all exons 1 and (if present) 2 for all genes encoded on the ## Y chromosome exons(edb, columns = c("tx_id", "exon_idx"), filter = list(SeqNameFilter("Y"), ExonRankFilter(3, condition = "<"))) ``` # Extracting gene/transcript/exon models for RNASeq feature counting For the feature counting step of an RNAseq experiment, the gene or transcript models (defined by the chromosomal start and end positions of their exons) have to be known. To extract these from an Ensembl based annotation package, the `exonsBy`, `genesBy` and `transcriptsBy` methods can be used in an analogous way as in `TxDb` packages generated by the `GenomicFeatures` package. However, the `transcriptsBy` method does not, in contrast to the method in the `GenomicFeatures` package, allow to return transcripts by "cds". While the annotation packages built by the `ensembldb` contain the chromosomal start and end coordinates of the coding region (for protein coding genes) they do not assign an ID to each CDS. A simple use case is to retrieve all genes encoded on chromosomes X and Y from the database. ```{r transcriptsBy-X-Y } TxByGns <- transcriptsBy(edb, by = "gene", filter = SeqNameFilter(c("X", "Y"))) TxByGns ``` Since Ensembl contains also definitions of genes that are on chromosome variants (supercontigs), it is advisable to specify the chromosome names for which the gene models should be returned. In a real use case, we might thus want to retrieve all genes encoded on the *standard* chromosomes. In addition it is advisable to use a `GeneIdFilter` to restrict to Ensembl genes only, as also *LRG* (Locus Reference Genomic) genes2 are defined in the database, which are partially redundant with Ensembl genes. ```{r exonsBy-RNAseq, message = FALSE, eval = FALSE } ## will just get exons for all genes on chromosomes 1 to 22, X and Y. ## Note: want to get rid of the "LRG" genes!!! EnsGenes <- exonsBy(edb, by = "gene", filter = AnnotationFilterList( SeqNameFilter(c(1:22, "X", "Y")), GeneIdFilter("ENSG", "startsWith"))) ``` The code above returns a `GRangesList` that can be used directly as an input for the `summarizeOverlaps` function from the `GenomicAlignments` package 3. Alternatively, the above `GRangesList` can be transformed to a `data.frame` in *SAF* format that can be used as an input to the `featureCounts` function of the `Rsubread` package 4. ```{r toSAF-RNAseq, message = FALSE, eval=FALSE } ## Transforming the GRangesList into a data.frame in SAF format EnsGenes.SAF <- toSAF(EnsGenes) ``` Note that the ID by which the `GRangesList` is split is used in the SAF formatted `data.frame` as the `GeneID`. In the example below this would be the Ensembl gene IDs, while the start, end coordinates (along with the strand and chromosomes) are those of the the exons. In addition, the `disjointExons` function (similar to the one defined in `GenomicFeatures`) can be used to generate a `GRanges` of non-overlapping exon parts which can be used in the `DEXSeq` package. ```{r disjointExons, message = FALSE, eval=FALSE } ## Create a GRanges of non-overlapping exon parts. DJE <- disjointExons(edb, filter = AnnotationFilterList( SeqNameFilter(c(1:22, "X", "Y")), GeneIdFilter("ENSG%", "startsWith"))) ``` # Retrieving sequences for gene/transcript/exon models The methods to retrieve exons, transcripts and genes (i.e. `exons`, `transcripts` and `genes`) return by default `GRanges` objects that can be used to retrieve sequences using the `getSeq` method e.g. from BSgenome packages. The basic workflow is thus identical to the one for `TxDb` packages, however, it is not straight forward to identify the BSgenome package with the matching genomic sequence. Most BSgenome packages are named according to the genome build identifier used in UCSC which does not (always) match the genome build name used by Ensembl. Using the Ensembl version provided by the `EnsDb`, the correct genomic sequence can however be retrieved easily from the `AnnotationHub` using the `getGenomeFaFile`. If no Fasta file matching the Ensembl version is available, the function tries to identify a Fasta file with the correct genome build from the *closest* Ensembl release and returns that instead. In the code block below we retrieve first the `FaFile` with the genomic DNA sequence, extract the genomic start and end coordinates for all genes defined in the package, subset to genes encoded on sequences available in the `FaFile` and extract all of their sequences. Note: these sequences represent the sequence between the chromosomal start and end coordinates of the gene. ```{r transcript-sequence-AnnotationHub, message = FALSE, eval = FALSE } library(EnsDb.Hsapiens.v75) library(Rsamtools) edb <- EnsDb.Hsapiens.v75 ## Get the FaFile with the genomic sequence matching the Ensembl version ## using the AnnotationHub package. Dna <- getGenomeFaFile(edb) ## Get start/end coordinates of all genes. genes <- genes(edb) ## Subset to all genes that are encoded on chromosomes for which ## we do have DNA sequence available. genes <- genes[seqnames(genes) %in% seqnames(seqinfo(Dna))] ## Get the gene sequences, i.e. the sequence including the sequence of ## all of the gene's exons and introns. geneSeqs <- getSeq(Dna, genes) ``` To retrieve the (exonic) sequence of transcripts (i.e. without introns) we can use directly the `extractTranscriptSeqs` method defined in the `GenomicFeatures` on the `EnsDb` object, eventually using a filter to restrict the query. ```{r transcript-sequence-extractTranscriptSeqs, message = FALSE, eval = FALSE } ## get all exons of all transcripts encoded on chromosome Y yTx <- exonsBy(edb, filter = SeqNameFilter("Y")) ## Retrieve the sequences for these transcripts from the FaFile. library(GenomicFeatures) yTxSeqs <- extractTranscriptSeqs(Dna, yTx) yTxSeqs ## Extract the sequences of all transcripts encoded on chromosome Y. yTx <- extractTranscriptSeqs(Dna, edb, filter = SeqNameFilter("Y")) ## Along these lines, we could use the method also to retrieve the coding sequence ## of all transcripts on the Y chromosome. cdsY <- cdsBy(edb, filter = SeqNameFilter("Y")) extractTranscriptSeqs(Dna, cdsY) ``` Note: in the next section we describe how transcript sequences can be retrieved from a `BSgenome` package that is based on UCSC, not Ensembl. # Integrating annotations from Ensembl based `EnsDb` packages with UCSC based annotations Sometimes it might be useful to combine (Ensembl based) annotations from `EnsDb` packages/objects with annotations from other Bioconductor packages, that might base on UCSC annotations. To support such an integration of annotations, the `ensembldb` packages implements the `seqlevelsStyle` and `seqlevelsStyle<-` from the `GenomeInfoDb` package that allow to change the style of chromosome naming. Thus, sequence/chromosome names other than those used by Ensembl can be used in, and are returned by, the queries to `EnsDb` objects as long as a mapping for them is provided by the `GenomeInfoDb` package (which provides a mapping mostly between UCSC, NCBI and Ensembl chromosome names for the *main* chromosomes). In the example below we change the seqnames style to UCSC. ```{r seqlevelsStyle, message = FALSE } ## Change the seqlevels style form Ensembl (default) to UCSC: seqlevelsStyle(edb) <- "UCSC" ## Now we can use UCSC style seqnames in SeqNameFilters or GRangesFilter: genesY <- genes(edb, filter = ~ seq_name == "chrY") ## The seqlevels of the returned GRanges are also in UCSC style seqlevels(genesY) ``` Note that in most instances no mapping is available for sequences not corresponding to the main chromosomes (i.e. contigs, patched chromosomes etc). What is returned in cases in which no mapping is available can be specified with the global `ensembldb.seqnameNotFound` option. By default (with `ensembldb.seqnameNotFound` set to "ORIGINAL"), the original seqnames (i.e. the ones from Ensembl) are returned. With `ensembldb.seqnameNotFound` "MISSING" each time a seqname can not be found an error is thrown. For all other cases (e.g. `ensembldb.seqnameNotFound = NA`) the value of the option is returned. ```{r seqlevelsStyle-2, message = FALSE } seqlevelsStyle(edb) <- "UCSC" ## Getting the default option: getOption("ensembldb.seqnameNotFound") ## Listing all seqlevels in the database. seqlevels(edb)[1:30] ## Setting the option to NA, thus, for each seqname for which no mapping is available, ## NA is returned. options(ensembldb.seqnameNotFound=NA) seqlevels(edb)[1:30] ## Resetting the option. options(ensembldb.seqnameNotFound = "ORIGINAL") ``` Next we retrieve transcript sequences from genes encoded on chromosome Y using the `BSGenome` package for the human genome from UCSC. The specified version `hg19` matches the genome build of Ensembl version 75, i.e. `GRCh37`. Note that while we changed the style of the seqnames to UCSC we did not change the naming of the genome release. ```{r extractTranscriptSeqs-BSGenome, warning = FALSE, message = FALSE } library(BSgenome.Hsapiens.UCSC.hg19) bsg <- BSgenome.Hsapiens.UCSC.hg19 ## Get the genome version unique(genome(bsg)) unique(genome(edb)) ## Although differently named, both represent genome build GRCh37. ## Extract the full transcript sequences. yTxSeqs <- extractTranscriptSeqs(bsg, exonsBy(edb, "tx", filter = SeqNameFilter("chrY"))) yTxSeqs ## Extract just the CDS Test <- cdsBy(edb, "tx", filter = SeqNameFilter("chrY")) yTxCds <- extractTranscriptSeqs(bsg, cdsBy(edb, "tx", filter = SeqNameFilter("chrY"))) yTxCds ``` At last changing the seqname style to the default value `"Ensembl"`. ```{r seqlevelsStyle-restore } seqlevelsStyle(edb) <- "Ensembl" ``` # Interactive annotation lookup using the `shiny` web app In addition to the `genes`, `transcripts` and `exons` methods it is possibly to search interactively for gene/transcript/exon annotations using the internal, `shiny` based, web application. The application can be started with the `runEnsDbApp()` function. The search results from this app can also be returned to the R workspace either as a `data.frame` or `GRanges` object. # Plotting gene/transcript features using `ensembldb` and `Gviz` and `ggbio` The `Gviz` package provides functions to plot genes and transcripts along with other data on a genomic scale. Gene models can be provided either as a `data.frame`, `GRanges`, `TxDB` database, can be fetched from biomart and can also be retrieved from `ensembldb`. Below we generate a `GeneRegionTrack` fetching all transcripts from a certain region on chromosome Y. Note that if we want in addition to work also with BAM files that were aligned against DNA sequences retrieved from Ensembl or FASTA files representing genomic DNA sequences from Ensembl we should change the `ucscChromosomeNames` option from `Gviz` to `FALSE` (i.e. by calling `options(ucscChromosomeNames = FALSE)`). This is not necessary if we just want to retrieve gene models from an `EnsDb` object, as the `ensembldb` package internally checks the `ucscChromosomeNames` option and, depending on that, maps Ensembl chromosome names to UCSC chromosome names. ```{r gviz-plot, message=FALSE, fig.align='center', fig.width=7.5, fig.height=2.3 } ## Loading the Gviz library library(Gviz) library(EnsDb.Hsapiens.v75) edb <- EnsDb.Hsapiens.v75 ## Retrieving a Gviz compatible GRanges object with all genes ## encoded on chromosome Y. gr <- getGeneRegionTrackForGviz(edb, chromosome = "Y", start = 20400000, end = 21400000) ## Define a genome axis track gat <- GenomeAxisTrack() ## We have to change the ucscChromosomeNames option to FALSE to enable Gviz usage ## with non-UCSC chromosome names. options(ucscChromosomeNames = FALSE) plotTracks(list(gat, GeneRegionTrack(gr))) options(ucscChromosomeNames = TRUE) ``` Above we had to change the option `ucscChromosomeNames` to `FALSE` in order to use it with non-UCSC chromosome names. Alternatively, we could however also change the `seqnamesStyle` of the `EnsDb` object to `UCSC`. Note that we have to use now also chromosome names in the *UCSC style* in the `SeqNameFilter` (i.e. "chrY" instead of `Y`). ```{r message=FALSE } seqlevelsStyle(edb) <- "UCSC" ## Retrieving the GRanges objects with seqnames corresponding to UCSC chromosome names. gr <- getGeneRegionTrackForGviz(edb, chromosome = "chrY", start = 20400000, end = 21400000) seqnames(gr) ## Define a genome axis track gat <- GenomeAxisTrack() plotTracks(list(gat, GeneRegionTrack(gr))) ``` We can also use the filters from the `ensembldb` package to further refine what transcripts are fetched, like in the example below, in which we create two different gene region tracks, one for protein coding genes and one for lincRNAs. ```{r gviz-separate-tracks, message=FALSE, warning=FALSE, fig.align='center', fig.width=7.5, fig.height=2.25 } protCod <- getGeneRegionTrackForGviz(edb, chromosome = "chrY", start = 20400000, end = 21400000, filter = GeneBiotypeFilter("protein_coding")) lincs <- getGeneRegionTrackForGviz(edb, chromosome = "chrY", start = 20400000, end = 21400000, filter = GeneBiotypeFilter("lincRNA")) plotTracks(list(gat, GeneRegionTrack(protCod, name = "protein coding"), GeneRegionTrack(lincs, name = "lincRNAs")), transcriptAnnotation = "symbol") ## At last we change the seqlevels style again to Ensembl seqlevelsStyle <- "Ensembl" ``` Alternatively, we can also use `ggbio` for plotting. For `ggplot` we can directly pass the `EnsDb` object along with optional filters (or as in the example below a filter expression as a `formula`). ```{r pplot-plot, message=FALSE, fig.align='center', fig.width=7.5, fig.height=4 } library(ggbio) ## Create a plot for all transcripts of the gene SKA2 autoplot(edb, ~ genename == "SKA2") ``` To plot the genomic region and plot genes from both strands we can use a `GRangesFilter`. ```{r pplot-plot-2, message=FALSE, fig.align='center', fig.width=7.5, fig.height=4 } ## Get the chromosomal region in which the gene is encoded ska2 <- genes(edb, filter = ~ genename == "SKA2") strand(ska2) <- "*" autoplot(edb, GRangesFilter(ska2), names.expr = "gene_name") ``` # Using `EnsDb` objects in the `AnnotationDbi` framework Most of the methods defined for objects extending the basic annotation package class `AnnotationDbi` are also defined for `EnsDb` objects (i.e. methods `columns`, `keytypes`, `keys`, `mapIds` and `select`). While these methods can be used analogously to basic annotation packages, the implementation for `EnsDb` objects also support the filtering framework of the `ensembldb` package. In the example below we first evaluate all the available columns and keytypes in the database and extract then the gene names for all genes encoded on chromosome X. ```{r AnnotationDbi, message = FALSE } library(EnsDb.Hsapiens.v75) edb <- EnsDb.Hsapiens.v75 ## List all available columns in the database. columns(edb) ## Note that these do *not* correspond to the actual column names ## of the database that can be passed to methods like exons, genes, ## transcripts etc. These column names can be listed with the listColumns ## method. listColumns(edb) ## List all of the supported key types. keytypes(edb) ## Get all gene ids from the database. gids <- keys(edb, keytype = "GENEID") length(gids) ## Get all gene names for genes encoded on chromosome Y. gnames <- keys(edb, keytype = "GENENAME", filter = SeqNameFilter("Y")) head(gnames) ``` In the next example we retrieve specific information from the database using the `select` method. First we fetch all transcripts for the genes *BCL2* and *BCL2L11*. In the first call we provide the gene names, while in the second call we employ the filtering system to perform a more fine-grained query to fetch only the protein coding transcripts for these genes. ```{r select, message = FALSE, warning=FALSE } ## Use the /standard/ way to fetch data. select(edb, keys = c("BCL2", "BCL2L11"), keytype = "GENENAME", columns = c("GENEID", "GENENAME", "TXID", "TXBIOTYPE")) ## Use the filtering system of ensembldb select(edb, keys = ~ genename %in% c("BCL2", "BCL2L11") & tx_biotype == "protein_coding", columns = c("GENEID", "GENENAME", "TXID", "TXBIOTYPE")) ``` Finally, we use the `mapIds` method to establish a mapping between ids and values. In the example below we fetch transcript ids for the two genes from the example above. ```{r mapIds, message = FALSE } ## Use the default method, which just returns the first value for multi mappings. mapIds(edb, keys = c("BCL2", "BCL2L11"), column = "TXID", keytype = "GENENAME") ## Alternatively, specify multiVals="list" to return all mappings. mapIds(edb, keys = c("BCL2", "BCL2L11"), column = "TXID", keytype = "GENENAME", multiVals = "list") ## And, just like before, we can use filters to map only to protein coding transcripts. mapIds(edb, keys = list(GenenameFilter(c("BCL2", "BCL2L11")), TxBiotypeFilter("protein_coding")), column = "TXID", multiVals = "list") ``` Note that, if the filters are used, the ordering of the result does no longer match the ordering of the genes. # Important notes These notes might explain eventually unexpected results (and, more importantly, help avoiding them): - The ordering of the results returned by the `genes`, `exons`, `transcripts` methods can be specified with the `order.by` parameter. The ordering of the results does however **not** correspond to the ordering of values in submitted filter objects. The exception is the `select` method. If a character vector of values or a single filter is passed with argument `keys` the ordering of results of this method matches the ordering of the key values or the values of the filter. - Results of `exonsBy`, `transcriptsBy` are always ordered by the `by` argument. - The CDS provided by `EnsDb` objects **always** includes both, the start and the stop codon. - Transcripts with multiple CDS are at present not supported by `EnsDb`. - At present, `EnsDb` support only genes/transcripts for which all of their exons are encoded on the same chromosome and the same strand. - Since a single Ensembl gene ID might be mapped to multiple NCBI Entrezgene IDs methods such as `genes`, `transcripts` etc return a `list` in the `"entrezid"` column of the resulting result object. # Getting or building `EnsDb` databases/packages Some of the code in this section is not supposed to be automatically executed when the vignette is built, as this would require a working installation of the Ensembl Perl API, which is not expected to be available on each system. Also, building `EnsDb` from alternative sources, like GFF or GTF files takes some time and thus also these examples are not directly executed when the vignette is build. ## Getting `EnsDb` databases Some `EnsDb` databases are available as `R` packages from Bioconductor and can be simply installed with the `biocLite` function from the `BiocInstaller` package. The name of such annotation packages starts with *EnsDb* followed by the abbreviation of the organism and the Ensembl version on which the annotation bases. `EnsDb.Hsapiens.v86` provides thus an `EnsDb` database for homo sapiens with annotations from Ensembl version 86. Since Bioconductor version 3.5 `EnsDb` databases can also be retrieved directly from `AnnotationHub`. ```{r AnnotationHub-query, message = FALSE, eval = use_network } library(AnnotationHub) ## Load the annotation resource. ah <- AnnotationHub() ## Query for all available EnsDb databases query(ah, "EnsDb") ``` We can simply fetch one of the databases. ```{r AnnotationHub-query-2, message = FALSE, eval = use_network } ahDb <- query(ah, pattern = c("Xiphophorus Maculatus", "EnsDb", 87)) ## What have we got ahDb ``` Fetch the `EnsDb` and use it. ```{r AnnotationHub-fetch, message = FALSE, eval = FALSE } ahEdb <- ahDb[[1]] ## retriebe all genes gns <- genes(ahEdb) ``` We could even make an annotation package from this `EnsDb` object using the `makeEnsembldbPackage` and passing `dbfile(dbconn(ahEdb))` as `ensdb` argument. ## Building annotation packages ### Directly from Ensembl databases The `fetchTablesFromEnsembl` function uses the Ensembl Perl API to retrieve the required annotations from an Ensembl database (e.g. from the main site *ensembldb.ensembl.org*). Thus, to use this functionality to build databases, the Ensembl Perl API needs to be installed (see 5 for details). Below we create an `EnsDb` database by fetching the required data directly from the Ensembl core databases. The `makeEnsembldbPackage` function is then used to create an annotation package from this `EnsDb` containing all human genes for Ensembl version 75. ```{r edb-from-ensembl, message = FALSE, eval = FALSE } library(ensembldb) ## get all human gene/transcript/exon annotations from Ensembl (75) ## the resulting tables will be stored by default to the current working ## directory fetchTablesFromEnsembl(75, species = "human") ## These tables can then be processed to generate a SQLite database ## containing the annotations (again, the function assumes the required ## txt files to be present in the current working directory) DBFile <- makeEnsemblSQLiteFromTables() ## and finally we can generate the package makeEnsembldbPackage(ensdb = DBFile, version = "0.99.12", maintainer = "Johannes Rainer ", author = "J Rainer") ``` The generated package can then be build using `R CMD build EnsDb.Hsapiens.v75` and installed with `R CMD INSTALL EnsDb.Hsapiens.v75*`. Note that we could directly generate an `EnsDb` instance by loading the database file, i.e. by calling `edb <- EnsDb(DBFile)` and work with that annotation object. To fetch and build annotation packages for plant genomes (e.g. arabidopsis thaliana), the *Ensembl genomes* should be specified as a host, i.e. setting `host` to "mysql-eg-publicsql.ebi.ac.uk", `port` to `4157` and `species` to e.g. "arabidopsis thaliana". ### From a GTF or GFF file Alternatively, the `ensDbFromAH`, `ensDbFromGff`, `ensDbFromGRanges` and `ensDbFromGtf` functions allow to build EnsDb SQLite files from a `GRanges` object or GFF/GTF files from Ensembl (either provided as files or *via* `AnnotationHub`). These functions do not depend on the Ensembl Perl API, but require a working internet connection to fetch the chromosome lengths from Ensembl as these are not provided within GTF or GFF files. Also note that protein annotations are usually not available in GTF or GFF files, thus, such annotations will not be included in the generated `EnsDb` database - protein annotations are only available in `EnsDb` databases created with the Ensembl Perl API (such as the ones provided through `AnnotationHub` or as Bioconductor packages). In the next example we create an `EnsDb` database using the `AnnotationHub` package and load also the corresponding genomic DNA sequence matching the Ensembl version. We thus first query the `AnnotationHub` package for all resources available for `Mus musculus` and the Ensembl release 77. Next we create the `EnsDb` object from the appropriate `AnnotationHub` resource. We then use the `getGenomeFaFile` method on the `EnsDb` to directly look up and retrieve the correct or best matching `FaFile` with the genomic DNA sequence. At last we retrieve the sequences of all exons using the `getSeq` method. ```{r gtf-gff-edb, message = FALSE, eval = FALSE } ## Load the AnnotationHub data. library(AnnotationHub) ah <- AnnotationHub() ## Query all available files for Ensembl release 77 for ## Mus musculus. query(ah, c("Mus musculus", "release-77")) ## Get the resource for the gtf file with the gene/transcript definitions. Gtf <- ah["AH28822"] ## Create a EnsDb database file from this. DbFile <- ensDbFromAH(Gtf) ## We can either generate a database package, or directly load the data edb <- EnsDb(DbFile) ## Identify and get the FaFile object with the genomic DNA sequence matching ## the EnsDb annotation. Dna <- getGenomeFaFile(edb) library(Rsamtools) ## We next retrieve the sequence of all exons on chromosome Y. exons <- exons(edb, filter = SeqNameFilter("Y")) exonSeq <- getSeq(Dna, exons) ## Alternatively, look up and retrieve the toplevel DNA sequence manually. Dna <- ah[["AH22042"]] ``` In the example below we load a `GRanges` containing gene definitions for genes encoded on chromosome Y and generate a `EnsDb` SQLite database from that information. ```{r EnsDb-from-Y-GRanges, message = FALSE, eval = use_network } ## Generate a sqlite database from a GRanges object specifying ## genes encoded on chromosome Y load(system.file("YGRanges.RData", package = "ensembldb")) Y ## Create the EnsDb database file DB <- ensDbFromGRanges(Y, path = tempdir(), version = 75, organism = "Homo_sapiens") ## Load the database edb <- EnsDb(DB) edb ``` Alternatively we can build the annotation database using the `ensDbFromGtf` `ensDbFromGff` functions, that extract most of the required data from a GTF respectively GFF (version 3) file which can be downloaded from Ensembl (e.g. from for human gene definitions from Ensembl version 75; for plant genomes etc, files can be retrieved from ). All information except the chromosome lengths, the NCBI Entrezgene IDs and protein annotations can be extracted from these GTF files. The function also tries to retrieve chromosome length information automatically from Ensembl. Below we create the annotation from a gtf file that we fetch directly from Ensembl. ```{r EnsDb-from-GTF, message = FALSE, eval = FALSE } library(ensembldb) ## the GTF file can be downloaded from ## ftp://ftp.ensembl.org/pub/release-75/gtf/homo_sapiens/ gtffile <- "Homo_sapiens.GRCh37.75.gtf.gz" ## generate the SQLite database file DB <- ensDbFromGtf(gtf = gtffile) ## load the DB file directly EDB <- EnsDb(DB) ## alternatively, build the annotation package ## and finally we can generate the package makeEnsembldbPackage(ensdb = DB, version = "0.99.12", maintainer = "Johannes Rainer ", author = "J Rainer") ``` # Database layout The database consists of the following tables and attributes (the layout is also shown in Figure [165](#orgfd622d5)). Note that the protein-specific annotations might not be available in all `EnsDB` databases (e.g. such ones created with `ensembldb` version < 1.7 or created from GTF or GFF files). - **gene**: all gene specific annotations. - `gene_id`: the Ensembl ID of the gene. - `gene_name`: the name (symbol) of the gene. - `gene_biotype`: the biotype of the gene. - `gene_seq_start`: the start coordinate of the gene on the sequence (usually a chromosome). - `gene_seq_end`: the end coordinate of the gene on the sequence. - `seq_name`: the name of the sequence (usually the chromosome name). - `seq_strand`: the strand on which the gene is encoded. - `seq_coord_system`: the coordinate system of the sequence. - `description`: the description of the gene. - **entrezgene**: mapping of Ensembl genes to NCBI Entrezgene identifiers. Note that this mapping can be a one-to-many mapping. - `gene_id`: the Ensembl gene ID. - `entrezid`: the NCBI Entrezgene ID. - **tx**: all transcript related annotations. Note that while no `tx_name` column is available in this database column, all methods to retrieve data from the database support also this column. The returned values are however the ID of the transcripts. - `tx_id`: the Ensembl transcript ID. - `tx_biotype`: the biotype of the transcript. - `tx_seq_start`: the start coordinate of the transcript. - `tx_seq_end`: the end coordinate of the transcript. - `tx_cds_seq_start`: the start coordinate of the coding region of the transcript (NULL for non-coding transcripts). - `tx_cds_seq_end`: the end coordinate of the coding region of the transcript. - `gene_id`: the gene to which the transcript belongs. `EnsDb` databases for more recent Ensembl releases have also a column `tx_support_level` providing the evidence level for a transcript (1 high evidence, 5 low evidence, NA no evidence calculated). - **exon**: all exon related annotation. - `exon_id`: the Ensembl exon ID. - `exon_seq_start`: the start coordinate of the exon. - `exon_seq_end`: the end coordinate of the exon. - **tx2exon**: provides the n:m mapping between transcripts and exons. - `tx_id`: the Ensembl transcript ID. - `exon_id`: the Ensembl exon ID. - `exon_idx`: the index of the exon in the corresponding transcript, always from 5' to 3' of the transcript. - **chromosome**: provides some information about the chromosomes. - `seq_name`: the name of the sequence/chromosome. - `seq_length`: the length of the sequence. - `is_circular`: whether the sequence in circular. - **protein**: provides protein annotation for a (coding) transcript. - `protein_id`: the Ensembl protein ID. - `tx_id`: the transcript ID which CDS encodes the protein. - `protein_sequence`: the peptide sequence of the protein (translated from the transcript's coding sequence after applying eventual RNA editing). - **uniprot**: provides the mapping from Ensembl protein ID(s) to Uniprot ID(s). Not all Ensembl proteins are annotated to Uniprot IDs, also, each Ensembl protein might be mapped to multiple Uniprot IDs. - `protein_id`: the Ensembl protein ID. - `uniprot_id`: the Uniprot ID. - `uniprot_db`: the Uniprot database in which the ID is defined. - `uniprot_mapping_type`: the type of the mapping method that was used to assign the Uniprot ID to an Ensembl protein ID. - **protein\_domain**: provides protein domain annotations and mapping to proteins. - `protein_id`: the Ensembl protein ID on which the protein domain is present. - `protein_domain_id`: the ID of the protein domain (from the protein domain source). - `protein_domain_source`: the source/analysis method in/by which the protein domain was defined (such as pfam etc). - `interpro_accession`: the Interpro accession ID of the protein domain. - `prot_dom_start`: the start position of the protein domain within the protein's sequence. - `prot_dom_end`: the end position of the protein domain within the protein's sequence. - **metadata**: some additional, internal, informations (Genome build, Ensembl version etc). - `name` - `value` - *virtual* columns: - `symbol`: the database does not have such a database column, but it is still possible to use it in the `columns` parameter. This column is *symlinked* to the `gene_name` column. - `tx_name`: similar to the `symbol` column, this column is *symlinked* to the `tx_id` column. The database layout: as already described above, protein related annotations (green) might not be available in each `EnsDb` database. ![img](images/dblayout.png "Database layout.") # Footnotes 1 2 3 4 5 ensembldb/vignettes/ensembldb.org0000644000175400017540000024515213175714743020234 0ustar00biocbuildbiocbuild#+TITLE: Generating and using Ensembl-based annotation packages #+AUTHOR: Johannes Rainer #+EMAIL: johannes.rainer@eurac.edu #+DESCRIPTION: #+KEYWORDS: #+LANGUAGE: en #+OPTIONS: ^:{} toc:nil #+PROPERTY: header-args :exports code #+PROPERTY: header-args:R :session *R* #+EXPORT_SELECT_TAGS: export #+EXPORT_EXCLUDE_TAGS: noexport #+BEGIN_EXPORT html --- title: "Generating an using Ensembl based annotation packages" author: "Johannes Rainer" graphics: yes package: ensembldb output: BiocStyle::html_document: toc_float: true vignette: > %\VignetteIndexEntry{Generating an using Ensembl based annotation packages} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} %\VignetteDepends{ensembldb,EnsDb.Hsapiens.v75,BiocStyle,AnnotationHub,ggbio,Gviz,magrittr} --- #+END_EXPORT * How to export this to a =Rnw= vignette :noexport: Use =ox-ravel= from the =orgmode-accessories= package to export this file to a =Rnw= file. After export edit the generated =Rnw= in the following way: 1) Delete all =\usepackage= commands. 2) Move the =<