1 Annotation version: 20170614

1.1 Orgdb

The Orgdb packages provide a quick and dirty method for gathering annotation data, lets see what we get!

mouse_pkg <- "Mus.musculus"
if ("Mus.musculus" %in% .packages(all.available=TRUE)) {
  tt <- sm(library("Mus.musculus"))
} else {
  please_install("Mus.musculus")
  tt <- sm(library("Mus.musculus"))
}
mm_tx_org <- sm(load_orgdb_annotations(Mus.musculus, keytype="ensembltrans",
                                       fields=c("definition", "genename")))

2 Extract useful biomart data

Now that we have the mouse data loaded into a big data frame, the goal is to pull out the most useful parts of it. We will also combine that information with the extant orgdb data.

mm_tx_genes <- mm_tx_org$genes
## The inclusion of the 'definition' columns means that we also end up with a bunch
## of redundant entries, like 200,000 of them; therefore I am going to whittle down
## the list.
tt <- sm(library(Mus.musculus))
##mm_go <- load_orgdb_go(orgdb=Mus.musculus)
mm_go <- load_biomart_go(species="mmusculus")
## The biomart annotations file already exists, loading from it.
mm_annot <- load_biomart_annotations(species="mmusculus")
## The biomart annotations file already exists, loading from it.
mm_annot <- mm_annot[["annotation"]]
mm_lengths <- mm_annot[, c("geneID", "length")]
rownames(mm_lengths) <- make.names(mm_lengths[["geneID"]], unique=TRUE)
colnames(mm_lengths) <- c("ID", "length")

mm_tx_unique <- !grepl(pattern="\\.", x=rownames(mm_tx_genes))
mm_tx_genes <- mm_tx_genes[mm_tx_unique, ]
##mmtx_annotations <- get_biomart_annotations(species="mmusculus")
mart <- biomaRt::useMart(biomart="ENSEMBL_MART_ENSEMBL", host="dec2015.archive.ensembl.org")
dataset <- paste0("mmusculus_gene_ensembl")
ensembl <- try(biomaRt::useDataset(dataset, mart=mart))
lots_of_rows <- biomaRt::listAttributes(ensembl)  ## List of possible attributes
## wanted_attributes <- c("ensembl_gene_id", "ensembl_transcript_id", "ensembl_peptide_id", "chromosome_name", "start_position","end_position","description", "entrezgene","hgnc_symbol","hgnc_id","uniprot_sptrembl","uniprot_swissprot","uniprot_genename")  ## attributes Lucia and I chose, but too many
wanted_attributes_global <- c("ensembl_gene_id", "ensembl_transcript_id", "chromosome_name",
                              "start_position", "end_position", "strand", "description")
wanted_attributes_names <- c("ensembl_gene_id", "ensembl_transcript_id", "entrezgene", "hgnc_symbol", "hgnc_id")
wanted_attributes_uniprot <- c("ensembl_gene_id", "ensembl_transcript_id", "uniprot_sptrembl", "uniprot_swissprot")

wanted_global_annotations <- biomaRt::getBM(attributes=wanted_attributes_global, mart=ensembl)
dim(wanted_global_annotations)
## [1] 114083      7
wanted_names_annotations <- biomaRt::getBM(attributes=wanted_attributes_names, mart=ensembl)
wanted_uniprot_annotations <- biomaRt::getBM(attributes=wanted_attributes_uniprot, mart=ensembl)
dim(wanted_uniprot_annotations)
## [1] 57040     4
wanted_global_annotations <- data.table::as.data.table(wanted_global_annotations)
wanted_names_annotations <- data.table::as.data.table(wanted_names_annotations)
wanted_uniprot_annotations <- data.table::as.data.table(wanted_uniprot_annotations)

2.1 Merge them together

Now let us bring together these data sources into a (hopefully) comprehesive table.

wanted_annotations <- merge(wanted_global_annotations,
                            wanted_names_annotations,
                            by.x="ensembl_transcript_id",
                            by.y="ensembl_transcript_id",
                            all.y=TRUE)
wanted_annotations <- merge(wanted_annotations,
                            wanted_uniprot_annotations,
                            by.x="ensembl_transcript_id",
                            by.y="ensembl_transcript_id",
                            all.x=TRUE)
wanted_annotations <- as.data.frame(wanted_annotations)
wanted_annotations <- wanted_annotations[, c(
  "ensembl_transcript_id", "ensembl_gene_id", "chromosome_name", "start_position", "end_position",
  "strand", "description", "entrezgene", "hgnc_symbol", "hgnc_id", "uniprot_sptrembl",
  "uniprot_swissprot")]

length(unique(wanted_annotations$ensembl_gene_id))
## [1] 22684
rownames(wanted_annotations) <- make.names(wanted_annotations[["ensembl_gene_id"]], unique=TRUE)
pander::pander(sessionInfo())

R version 3.4.4 (2018-03-15)

**Platform:** x86_64-pc-linux-gnu (64-bit)

locale: LC_CTYPE=en_US.utf8, LC_NUMERIC=C, LC_TIME=en_US.utf8, LC_COLLATE=en_US.utf8, LC_MONETARY=en_US.utf8, LC_MESSAGES=en_US.utf8, LC_PAPER=en_US.utf8, LC_NAME=C, LC_ADDRESS=C, LC_TELEPHONE=C, LC_MEASUREMENT=en_US.utf8 and LC_IDENTIFICATION=C

attached base packages: parallel, stats4, stats, graphics, grDevices, utils, datasets, methods and base

other attached packages: Mus.musculus(v.1.3.1), TxDb.Mmusculus.UCSC.mm10.knownGene(v.3.4.0), org.Mm.eg.db(v.3.5.0), GO.db(v.3.5.0), OrganismDbi(v.1.20.0), GenomicFeatures(v.1.30.3), GenomicRanges(v.1.30.3), GenomeInfoDb(v.1.14.0), AnnotationDbi(v.1.40.0), IRanges(v.2.12.0), S4Vectors(v.0.16.0), Biobase(v.2.38.0), BiocGenerics(v.0.24.0) and hpgltools(v.2018.03)

loaded via a namespace (and not attached): Rcpp(v.0.12.16), lattice(v.0.20-35), prettyunits(v.1.0.2), Rsamtools(v.1.30.0), Biostrings(v.2.46.0), assertthat(v.0.2.0), rprojroot(v.1.3-2), digest(v.0.6.15), foreach(v.1.4.4), R6(v.2.2.2), plyr(v.1.8.4), backports(v.1.1.2), RSQLite(v.2.0), evaluate(v.0.10.1), httr(v.1.3.1), ggplot2(v.2.2.1), BiocInstaller(v.1.28.0), pillar(v.1.2.1), zlibbioc(v.1.24.0), rlang(v.0.2.0.9001), progress(v.1.1.2), curl(v.3.1), lazyeval(v.0.2.1), data.table(v.1.10.4-3), blob(v.1.1.0), Matrix(v.1.2-12), rmarkdown(v.1.9), devtools(v.1.13.5), RMySQL(v.0.10.14), BiocParallel(v.1.12.0), pander(v.0.6.1), stringr(v.1.3.0), RCurl(v.1.95-4.10), bit(v.1.1-12), biomaRt(v.2.34.2), munsell(v.0.4.3), DelayedArray(v.0.4.1), compiler(v.3.4.4), rtracklayer(v.1.38.3), pkgconfig(v.2.0.1), base64enc(v.0.1-3), htmltools(v.0.3.6), SummarizedExperiment(v.1.8.1), tibble(v.1.4.2), GenomeInfoDbData(v.1.0.0), roxygen2(v.6.0.1), codetools(v.0.2-15), matrixStats(v.0.53.1), XML(v.3.98-1.10), withr(v.2.1.2), GenomicAlignments(v.1.14.1), bitops(v.1.0-6), commonmark(v.1.4), grid(v.3.4.4), RBGL(v.1.54.0), gtable(v.0.2.0), DBI(v.0.8), magrittr(v.1.5), scales(v.0.5.0.9000), graph(v.1.56.0), stringi(v.1.1.7), XVector(v.0.18.0), xml2(v.1.2.0), iterators(v.1.0.9), tools(v.3.4.4), bit64(v.0.9-7), yaml(v.2.1.18), colorspace(v.1.3-2), memoise(v.1.1.0) and knitr(v.1.20)

message(paste0("This is hpgltools commit: ", get_git_commit()))
## If you wish to reproduce this exact build of hpgltools, invoke the following:
## > git clone http://github.com/abelew/hpgltools.git
## > git reset 7de4503f6bb5724c28cce24af5dbee22bb1c0cae
## R> packrat::restore()
## This is hpgltools commit: Thu Apr 12 22:08:53 2018 -0400: 7de4503f6bb5724c28cce24af5dbee22bb1c0cae
message(paste0("Saving to ", savefile))
## Saving to 01_annotation_mmusculus_v20170614.rda.xz
tmp <- sm(saveme(filename=savefile))
LS0tCnRpdGxlOiAiSS5zY2FwdWxhcmlzIDIwMTc6IEluZmVjdGVkIG1pY2UgYW5ub3RhdGlvbiBpbmZvcm1hdGlvbi4iCmF1dGhvcjogImF0YiBhYmVsZXdAZ21haWwuY29tIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKIGh0bWxfZG9jdW1lbnQ6CiAgY29kZV9kb3dubG9hZDogdHJ1ZQogIGNvZGVfZm9sZGluZzogc2hvdwogIGZpZ19jYXB0aW9uOiB0cnVlCiAgZmlnX2hlaWdodDogNwogIGZpZ193aWR0aDogNwogIGhpZ2hsaWdodDogZGVmYXVsdAogIGtlZXBfbWQ6IGZhbHNlCiAgbW9kZTogc2VsZmNvbnRhaW5lZAogIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgdGhlbWU6IHJlYWRhYmxlCiAgdG9jOiB0cnVlCiAgdG9jX2Zsb2F0OgogICAgY29sbGFwc2VkOiBmYWxzZQogICAgc21vb3RoX3Njcm9sbDogZmFsc2UKLS0tCgo8c3R5bGU+CiAgYm9keSAubWFpbi1jb250YWluZXIgewogICAgbWF4LXdpZHRoOiAxNjAwcHg7CiAgfQo8L3N0eWxlPgoKYGBge3Igb3B0aW9ucywgaW5jbHVkZT1GQUxTRX0KaWYgKCFpc1RSVUUoZ2V0MCgic2tpcF9sb2FkIikpKSB7CiAgbGlicmFyeShocGdsdG9vbHMpCiAgdHQgPC0gZGV2dG9vbHM6OmxvYWRfYWxsKCJ+L2hwZ2x0b29scyIpCiAga25pdHI6Om9wdHNfa25pdCRzZXQocHJvZ3Jlc3M9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICB2ZXJib3NlPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgd2lkdGg9OTAsCiAgICAgICAgICAgICAgICAgICAgICAgZWNobz1UUlVFKQogIGtuaXRyOjpvcHRzX2NodW5rJHNldChlcnJvcj1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgICBmaWcud2lkdGg9OCwKICAgICAgICAgICAgICAgICAgICAgICAgZmlnLmhlaWdodD04LAogICAgICAgICAgICAgICAgICAgICAgICBkcGk9OTYpCiAgb2xkX29wdGlvbnMgPC0gb3B0aW9ucyhkaWdpdHM9NCwKICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICBrbml0ci5kdXBsaWNhdGUubGFiZWw9ImFsbG93IikKICBnZ3Bsb3QyOjp0aGVtZV9zZXQoZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplPTEwKSkKICB2ZXIgPC0gIjIwMTcwNjE0IgogIHByZXZpb3VzX2ZpbGUgPC0gcGFzdGUwKCIwMV9hbm5vdGF0aW9uX21tdXNjdWx1c192IiwgdmVyLCAiLlJtZCIpCgogIHRtcCA8LSB0cnkoc20obG9hZG1lKGZpbGVuYW1lPWdzdWIocGF0dGVybj0iXFwuUm1kIiwgcmVwbGFjZT0iXFwucmRhXFwueHoiLCB4PXByZXZpb3VzX2ZpbGUpKSkpCiAgcm1kX2ZpbGUgPC0gcGFzdGUwKCIwMV9hbm5vdGF0aW9uX21tdXNjdWx1c192IiwgdmVyLCAiLlJtZCIpCiAgc2F2ZWZpbGUgPC0gZ3N1YihwYXR0ZXJuPSJcXC5SbWQiLCByZXBsYWNlPSJcXC5yZGFcXC54eiIsIHg9cm1kX2ZpbGUpCn0KYGBgCgojIEFubm90YXRpb24gdmVyc2lvbjogYHIgdmVyYAoKIyMgT3JnZGIKClRoZSBPcmdkYiBwYWNrYWdlcyBwcm92aWRlIGEgcXVpY2sgYW5kIGRpcnR5IG1ldGhvZCBmb3IgZ2F0aGVyaW5nIGFubm90YXRpb24KZGF0YSwgbGV0cyBzZWUgd2hhdCB3ZSBnZXQhCgpgYGB7ciBtb3VzZV9hbm5vdGF0aW9uc30KbW91c2VfcGtnIDwtICJNdXMubXVzY3VsdXMiCmlmICgiTXVzLm11c2N1bHVzIiAlaW4lIC5wYWNrYWdlcyhhbGwuYXZhaWxhYmxlPVRSVUUpKSB7CiAgdHQgPC0gc20obGlicmFyeSgiTXVzLm11c2N1bHVzIikpCn0gZWxzZSB7CiAgcGxlYXNlX2luc3RhbGwoIk11cy5tdXNjdWx1cyIpCiAgdHQgPC0gc20obGlicmFyeSgiTXVzLm11c2N1bHVzIikpCn0KbW1fdHhfb3JnIDwtIHNtKGxvYWRfb3JnZGJfYW5ub3RhdGlvbnMoTXVzLm11c2N1bHVzLCBrZXl0eXBlPSJlbnNlbWJsdHJhbnMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWVsZHM9YygiZGVmaW5pdGlvbiIsICJnZW5lbmFtZSIpKSkKYGBgCgojIEV4dHJhY3QgdXNlZnVsIGJpb21hcnQgZGF0YQoKTm93IHRoYXQgd2UgaGF2ZSB0aGUgbW91c2UgZGF0YSBsb2FkZWQgaW50byBhIGJpZyBkYXRhIGZyYW1lLCB0aGUgZ29hbCBpcyB0bwpwdWxsIG91dCB0aGUgbW9zdCB1c2VmdWwgcGFydHMgb2YgaXQuICBXZSB3aWxsIGFsc28gY29tYmluZSB0aGF0IGluZm9ybWF0aW9uCndpdGggdGhlIGV4dGFudCBvcmdkYiBkYXRhLgoKYGBge3IgZXh0cmFjdF9iaW9tYXJ0fQptbV90eF9nZW5lcyA8LSBtbV90eF9vcmckZ2VuZXMKIyMgVGhlIGluY2x1c2lvbiBvZiB0aGUgJ2RlZmluaXRpb24nIGNvbHVtbnMgbWVhbnMgdGhhdCB3ZSBhbHNvIGVuZCB1cCB3aXRoIGEgYnVuY2gKIyMgb2YgcmVkdW5kYW50IGVudHJpZXMsIGxpa2UgMjAwLDAwMCBvZiB0aGVtOyB0aGVyZWZvcmUgSSBhbSBnb2luZyB0byB3aGl0dGxlIGRvd24KIyMgdGhlIGxpc3QuCnR0IDwtIHNtKGxpYnJhcnkoTXVzLm11c2N1bHVzKSkKIyNtbV9nbyA8LSBsb2FkX29yZ2RiX2dvKG9yZ2RiPU11cy5tdXNjdWx1cykKbW1fZ28gPC0gbG9hZF9iaW9tYXJ0X2dvKHNwZWNpZXM9Im1tdXNjdWx1cyIpCgptbV9hbm5vdCA8LSBsb2FkX2Jpb21hcnRfYW5ub3RhdGlvbnMoc3BlY2llcz0ibW11c2N1bHVzIikKbW1fYW5ub3QgPC0gbW1fYW5ub3RbWyJhbm5vdGF0aW9uIl1dCm1tX2xlbmd0aHMgPC0gbW1fYW5ub3RbLCBjKCJnZW5lSUQiLCAibGVuZ3RoIildCnJvd25hbWVzKG1tX2xlbmd0aHMpIDwtIG1ha2UubmFtZXMobW1fbGVuZ3Roc1tbImdlbmVJRCJdXSwgdW5pcXVlPVRSVUUpCmNvbG5hbWVzKG1tX2xlbmd0aHMpIDwtIGMoIklEIiwgImxlbmd0aCIpCgptbV90eF91bmlxdWUgPC0gIWdyZXBsKHBhdHRlcm49IlxcLiIsIHg9cm93bmFtZXMobW1fdHhfZ2VuZXMpKQptbV90eF9nZW5lcyA8LSBtbV90eF9nZW5lc1ttbV90eF91bmlxdWUsIF0KIyNtbXR4X2Fubm90YXRpb25zIDwtIGdldF9iaW9tYXJ0X2Fubm90YXRpb25zKHNwZWNpZXM9Im1tdXNjdWx1cyIpCm1hcnQgPC0gYmlvbWFSdDo6dXNlTWFydChiaW9tYXJ0PSJFTlNFTUJMX01BUlRfRU5TRU1CTCIsIGhvc3Q9ImRlYzIwMTUuYXJjaGl2ZS5lbnNlbWJsLm9yZyIpCmRhdGFzZXQgPC0gcGFzdGUwKCJtbXVzY3VsdXNfZ2VuZV9lbnNlbWJsIikKZW5zZW1ibCA8LSB0cnkoYmlvbWFSdDo6dXNlRGF0YXNldChkYXRhc2V0LCBtYXJ0PW1hcnQpKQpsb3RzX29mX3Jvd3MgPC0gYmlvbWFSdDo6bGlzdEF0dHJpYnV0ZXMoZW5zZW1ibCkgICMjIExpc3Qgb2YgcG9zc2libGUgYXR0cmlidXRlcwojIyB3YW50ZWRfYXR0cmlidXRlcyA8LSBjKCJlbnNlbWJsX2dlbmVfaWQiLCAiZW5zZW1ibF90cmFuc2NyaXB0X2lkIiwgImVuc2VtYmxfcGVwdGlkZV9pZCIsICJjaHJvbW9zb21lX25hbWUiLCAic3RhcnRfcG9zaXRpb24iLCJlbmRfcG9zaXRpb24iLCJkZXNjcmlwdGlvbiIsICJlbnRyZXpnZW5lIiwiaGduY19zeW1ib2wiLCJoZ25jX2lkIiwidW5pcHJvdF9zcHRyZW1ibCIsInVuaXByb3Rfc3dpc3Nwcm90IiwidW5pcHJvdF9nZW5lbmFtZSIpICAjIyBhdHRyaWJ1dGVzIEx1Y2lhIGFuZCBJIGNob3NlLCBidXQgdG9vIG1hbnkKd2FudGVkX2F0dHJpYnV0ZXNfZ2xvYmFsIDwtIGMoImVuc2VtYmxfZ2VuZV9pZCIsICJlbnNlbWJsX3RyYW5zY3JpcHRfaWQiLCAiY2hyb21vc29tZV9uYW1lIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInN0YXJ0X3Bvc2l0aW9uIiwgImVuZF9wb3NpdGlvbiIsICJzdHJhbmQiLCAiZGVzY3JpcHRpb24iKQp3YW50ZWRfYXR0cmlidXRlc19uYW1lcyA8LSBjKCJlbnNlbWJsX2dlbmVfaWQiLCAiZW5zZW1ibF90cmFuc2NyaXB0X2lkIiwgImVudHJlemdlbmUiLCAiaGduY19zeW1ib2wiLCAiaGduY19pZCIpCndhbnRlZF9hdHRyaWJ1dGVzX3VuaXByb3QgPC0gYygiZW5zZW1ibF9nZW5lX2lkIiwgImVuc2VtYmxfdHJhbnNjcmlwdF9pZCIsICJ1bmlwcm90X3NwdHJlbWJsIiwgInVuaXByb3Rfc3dpc3Nwcm90IikKCndhbnRlZF9nbG9iYWxfYW5ub3RhdGlvbnMgPC0gYmlvbWFSdDo6Z2V0Qk0oYXR0cmlidXRlcz13YW50ZWRfYXR0cmlidXRlc19nbG9iYWwsIG1hcnQ9ZW5zZW1ibCkKZGltKHdhbnRlZF9nbG9iYWxfYW5ub3RhdGlvbnMpCndhbnRlZF9uYW1lc19hbm5vdGF0aW9ucyA8LSBiaW9tYVJ0OjpnZXRCTShhdHRyaWJ1dGVzPXdhbnRlZF9hdHRyaWJ1dGVzX25hbWVzLCBtYXJ0PWVuc2VtYmwpCndhbnRlZF91bmlwcm90X2Fubm90YXRpb25zIDwtIGJpb21hUnQ6OmdldEJNKGF0dHJpYnV0ZXM9d2FudGVkX2F0dHJpYnV0ZXNfdW5pcHJvdCwgbWFydD1lbnNlbWJsKQpkaW0od2FudGVkX3VuaXByb3RfYW5ub3RhdGlvbnMpCgp3YW50ZWRfZ2xvYmFsX2Fubm90YXRpb25zIDwtIGRhdGEudGFibGU6OmFzLmRhdGEudGFibGUod2FudGVkX2dsb2JhbF9hbm5vdGF0aW9ucykKd2FudGVkX25hbWVzX2Fubm90YXRpb25zIDwtIGRhdGEudGFibGU6OmFzLmRhdGEudGFibGUod2FudGVkX25hbWVzX2Fubm90YXRpb25zKQp3YW50ZWRfdW5pcHJvdF9hbm5vdGF0aW9ucyA8LSBkYXRhLnRhYmxlOjphcy5kYXRhLnRhYmxlKHdhbnRlZF91bmlwcm90X2Fubm90YXRpb25zKQpgYGAKCiMjIE1lcmdlIHRoZW0gdG9nZXRoZXIKCk5vdyBsZXQgdXMgYnJpbmcgdG9nZXRoZXIgdGhlc2UgZGF0YSBzb3VyY2VzIGludG8gYSAoaG9wZWZ1bGx5KSBjb21wcmVoZXNpdmUKdGFibGUuCgpgYGB7ciBtZXJnZXN9CndhbnRlZF9hbm5vdGF0aW9ucyA8LSBtZXJnZSh3YW50ZWRfZ2xvYmFsX2Fubm90YXRpb25zLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgd2FudGVkX25hbWVzX2Fubm90YXRpb25zLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkueD0iZW5zZW1ibF90cmFuc2NyaXB0X2lkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5Lnk9ImVuc2VtYmxfdHJhbnNjcmlwdF9pZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGwueT1UUlVFKQp3YW50ZWRfYW5ub3RhdGlvbnMgPC0gbWVyZ2Uod2FudGVkX2Fubm90YXRpb25zLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgd2FudGVkX3VuaXByb3RfYW5ub3RhdGlvbnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBieS54PSJlbnNlbWJsX3RyYW5zY3JpcHRfaWQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkueT0iZW5zZW1ibF90cmFuc2NyaXB0X2lkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsbC54PVRSVUUpCndhbnRlZF9hbm5vdGF0aW9ucyA8LSBhcy5kYXRhLmZyYW1lKHdhbnRlZF9hbm5vdGF0aW9ucykKd2FudGVkX2Fubm90YXRpb25zIDwtIHdhbnRlZF9hbm5vdGF0aW9uc1ssIGMoCiAgImVuc2VtYmxfdHJhbnNjcmlwdF9pZCIsICJlbnNlbWJsX2dlbmVfaWQiLCAiY2hyb21vc29tZV9uYW1lIiwgInN0YXJ0X3Bvc2l0aW9uIiwgImVuZF9wb3NpdGlvbiIsCiAgInN0cmFuZCIsICJkZXNjcmlwdGlvbiIsICJlbnRyZXpnZW5lIiwgImhnbmNfc3ltYm9sIiwgImhnbmNfaWQiLCAidW5pcHJvdF9zcHRyZW1ibCIsCiAgInVuaXByb3Rfc3dpc3Nwcm90IildCgpsZW5ndGgodW5pcXVlKHdhbnRlZF9hbm5vdGF0aW9ucyRlbnNlbWJsX2dlbmVfaWQpKQpyb3duYW1lcyh3YW50ZWRfYW5ub3RhdGlvbnMpIDwtIG1ha2UubmFtZXMod2FudGVkX2Fubm90YXRpb25zW1siZW5zZW1ibF9nZW5lX2lkIl1dLCB1bmlxdWU9VFJVRSkKYGBgCgpgYGB7ciBzYXZlbWV9CnBhbmRlcjo6cGFuZGVyKHNlc3Npb25JbmZvKCkpCm1lc3NhZ2UocGFzdGUwKCJUaGlzIGlzIGhwZ2x0b29scyBjb21taXQ6ICIsIGdldF9naXRfY29tbWl0KCkpKQptZXNzYWdlKHBhc3RlMCgiU2F2aW5nIHRvICIsIHNhdmVmaWxlKSkKdG1wIDwtIHNtKHNhdmVtZShmaWxlbmFtZT1zYXZlZmlsZSkpCmBgYAo=