index.html preprocessing.html

1 Annotation version: 20170703

There are a few methods of importing annotation data into R. The following are two attempts, the second is currently being used in these analyses.

1.1 AnnotationHub

AnnotationHub is a newer service and has promise to be an excellent top-level resource for gathering annotation data.

## This doesn't quite work yet
tt <- sm(library(AnnotationHub))
ah <- AnnotationHub()
orgdbs <- query(ah, "OrgDb")
leishmanias <- query(ah, c("OrgDB", "Leishmania"))

1.2 OrganismDbi

AnnotationHub is the new and fancier version of what OrganismDb does. Keith already made these for the parasites though, lets try and use one of those.

The OrganismDb packages are installable via Keith’s builder: https://github.com/elsayed-lab/eupathdb-organismdb

I did a git pull of it, changed a couple small things and ran ‘make lbraziliensis’. This pulls the annotations down from a mix of Najib’s directory on the cluster and the TriTrypdb. As a result, it currently gets the version 27 of the TriTrypDB data. It may be useful for me to download a newer revision (but I am reasonably certain not much (or anything) has changed for braziliensis in a while).

After 5 or so minutes a brand new package ‘Leishmania.braziliensis’ appeared in my R environment.

testing_panamensis <- make_tritrypdb_organismdbi("lpanamensis")
testing_braziliensis <- make_tritrypdb_organismdbi("lbraziliensis")
testing_donovani <- make_tritrypdb_organismdbi("ldonovani")
testing_mexicana <- make_tritrypdb_organismdbi("lmexicana")
testing_major <- make_tritrypdb_organismdbi("lmajor")
testing_donovani_eu <- make_eupath_organismdbi("donovani")
tmp <- sm(try(library("Leishmania.major.Friedlin")))
if (class(tmp) == "try-error") {
  tmp <- make_tritrypdb_organismdbi("lmajor")
}
tmp <- sm(library("org.Lmajor.friedlin.eg.db"))
tmp <- sm(library("TxDb.Lmajor.friedlin.TriTrypDB28"))
Leishmania.major.Friedlin
## OrganismDb Object:
## # Includes GODb Object:  GO.db 
## # With data about:  Gene Ontology 
## # Includes OrgDb Object:  org.Lmajor.friedlin.eg.db 
## # Gene data about:  Leishmania major.friedlin 
## # Taxonomy Id:   
## # Includes TxDb Object:  TxDb.Lmajor.friedlin.TriTrypDB28 
## # Transcriptome data about:  Leishmania major 
## # Based on genome:  NA 
## # The OrgDb gene id GID is mapped to the TxDb gene id GENEID .
lm_org <- sm(load_orgdb_annotations(Leishmania.major.Friedlin, keytype="geneid"))
lm_annotations <- lm_org[["genes"]]

1.3 Read a gff file

In this instance, it might be smarter to actually read the annotations from a gff file, primarily because I modified the gff file to include an entry for the LmjF.26.0890 3’ UTR.

lm_gff_annotations <- load_gff_annotations(gff="reference/lmajor_modified.gff", type="gene")
## Trying attempt: rtracklayer::import.gff3(gff, sequenceRegionsAsSeqinfo=TRUE)
## Warning in as.data.frame(mcols(x), ...): Arguments in '...' ignored

## Warning in as.data.frame(mcols(x), ...): Arguments in '...' ignored
## Had a successful gff import with rtracklayer::import.gff3(gff, sequenceRegionsAsSeqinfo=TRUE)
## Warning in as.data.frame(mcols(x), ...): Arguments in '...' ignored
## Returning a df with 24 columns and 9379 rows.
head(lm_gff_annotations)
##    seqnames start   end width strand    source type score phase           ID         Name
## 37  LmjF.01  3704  4702   999      - TriTrypDB gene    NA    NA LmjF.01.0010 LmjF.01.0010
## 41  LmjF.01  5790  7439  1650      - TriTrypDB gene    NA    NA LmjF.01.0020 LmjF.01.0020
## 45  LmjF.01  9061 11067  2007      - TriTrypDB gene    NA    NA LmjF.01.0030 LmjF.01.0030
## 49  LmjF.01 12073 12642   570      - TriTrypDB gene    NA    NA LmjF.01.0040 LmjF.01.0040
## 53  LmjF.01 15025 17022  1998      - TriTrypDB gene    NA    NA LmjF.01.0050 LmjF.01.0050
## 57  LmjF.01 18137 18886   750      - TriTrypDB gene    NA    NA LmjF.01.0060 LmjF.01.0060
##                               description size       web_id molecule_type organism_name
## 37 hypothetical+protein,+unknown+function  999 LmjF.01.0010          <NA>          <NA>
## 41        hypothetical+protein,+conserved 1650 LmjF.01.0020          <NA>          <NA>
## 45       Kinesin-13+1,+putative+(KIN13-1) 2007 LmjF.01.0030          <NA>          <NA>
## 49 hypothetical+protein,+unknown+function  570 LmjF.01.0040          <NA>          <NA>
## 53                  carboxylase,+putative 1998 LmjF.01.0050          <NA>          <NA>
## 57        hypothetical+protein,+conserved  750 LmjF.01.0060          <NA>          <NA>
##    translation_table topology localization Dbxref    locus_tag        Alias Parent
## 37              <NA>     <NA>         <NA>        LmjF.01.0010 32143805....       
## 41              <NA>     <NA>         <NA>        LmjF.01.0020 32143805....       
## 45              <NA>     <NA>         <NA>        LmjF.01.0030 KIN13-1,....       
## 49              <NA>     <NA>         <NA>        LmjF.01.0040 32143805....       
## 53              <NA>     <NA>         <NA>        LmjF.01.0050 32143805....       
## 57              <NA>     <NA>         <NA>        LmjF.01.0060 32143805....       
##    Ontology_term
## 37              
## 41              
## 45              
## 49              
## 53              
## 57
rownames(lm_gff_annotations) <- paste0("exon_", make.names(lm_gff_annotations[["Name"]], unique=TRUE), ".1")

In contrast, it is possible to load most annotations of interest directly from the gff files used in the alignments. More in-depth information for the human transcriptome may be extracted from biomart.

1.4 Getting ontology data

## While testing, I called this desc, that will need to change.
lm_tooltips <- make_tooltips(annotations=lm_gff_annotations, desc_col="description")

##rownames(lm_annotations) <- paste0("exon_", rownames(lm_annotations), ".1")
##lm_lengths <- lm_annotations[, c("geneid", "width")]
##colnames(lm_lengths) <- c("ID", "width")

lm_goids <- as.data.frame(load_orgdb_go(Leishmania.major.Friedlin, keytype="TXID",
                                        columns=c("TXNAME","GO")))
## This is an organismdbi, that should be ok.
lm_goids <- lm_goids[, c("TXNAME", "GO", "ONTOLOGY", "TERM")]
colnames(lm_goids) <- c("ID", "GO", "ont", "name")
new_ids <- gsub(pattern="-1$", replacement="\\.1", x=lm_goids[["ID"]])
new_ids <- paste0("exon_", new_ids)
lm_goids[["ID"]] <- new_ids

2 Putting the pieces together

The macrophage experiment has samples across 2 contexts, the host and parasite. The following block sets up one experiment for each. If you open the all_samples-species.xlsx files, you will note immediately that a few different attempts were made at ascertaining the most likely experimental factors that contributed to the readily apparent batch effects.

Question: Are there any human reads in this data? I assume no, but will happily map human if so.

2.1 The parasite transcriptome mappings

parasite_expt <- create_expt("sample_sheet/all_samples.xlsx", gene_info=lm_gff_annotations)
## wt_1/processed/outputs/tophat_lmajor/accepted_paired.count.xz contains 9470 rows.
## wt_2/processed/outputs/tophat_lmajor/accepted_paired.count.xz contains 9470 rows and merges to 9470 rows.
## wt_3/processed/outputs/tophat_lmajor/accepted_paired.count.xz contains 9470 rows and merges to 9470 rows.
## odd3_1/processed/outputs/tophat_lmajor/accepted_paired.count.xz contains 9470 rows and merges to 9470 rows.
## odd3_2/processed/outputs/tophat_lmajor/accepted_paired.count.xz contains 9470 rows and merges to 9470 rows.
## odd3_3/processed/outputs/tophat_lmajor/accepted_paired.count.xz contains 9470 rows and merges to 9470 rows.
## Bringing together the count matrix and gene information.
## Some annotations were lost in merging, setting them to 'undefined'.
chosen_colors <- list(
    "wt" = "#AA3939",
    "odd3" = "#067300")
    
parasite_expt <- set_expt_colors(expt=parasite_expt, colors=chosen_colors)

At this point, we should have everything necessary to perform some analyses.

index.html

3 The Experiment Design

3.1 Parasite

knitr::kable(parasite_expt$design)
sampleid condition batch file
wt_1 wt_1 wt null wt_1/processed/outputs/tophat_lmajor/accepted_paired.count.xz
wt_2 wt_2 wt null wt_2/processed/outputs/tophat_lmajor/accepted_paired.count.xz
wt_3 wt_3 wt null wt_3/processed/outputs/tophat_lmajor/accepted_paired.count.xz
odd_1 odd_1 odd3 null odd3_1/processed/outputs/tophat_lmajor/accepted_paired.count.xz
odd_2 odd_2 odd3 null odd3_2/processed/outputs/tophat_lmajor/accepted_paired.count.xz
odd_3 odd_3 odd3 null odd3_3/processed/outputs/tophat_lmajor/accepted_paired.count.xz

4 Changelog

pander::pander(sessionInfo())

R version 3.4.1 (2017-06-30)

**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: hpgltools(v.2017.01), TxDb.Lmajor.friedlin.TriTrypDB28(v.28.0), org.Lmajor.friedlin.eg.db(v.28.0), Leishmania.major.Friedlin(v.28.0), GO.db(v.3.4.1), OrganismDbi(v.1.18.0), GenomicFeatures(v.1.28.4), GenomicRanges(v.1.28.4), GenomeInfoDb(v.1.12.2), AnnotationDbi(v.1.38.2), IRanges(v.2.10.3), S4Vectors(v.0.14.3), Biobase(v.2.36.2) and BiocGenerics(v.0.22.0)

loaded via a namespace (and not attached): bit64(v.0.9-7), foreach(v.1.4.3), assertthat(v.0.2.0), highr(v.0.6), pander(v.0.6.1), RBGL(v.1.52.0), blob(v.1.1.0), GenomeInfoDbData(v.0.99.0), Rsamtools(v.1.28.0), yaml(v.2.1.14), backports(v.1.1.0), RSQLite(v.2.0), lattice(v.0.20-35), glue(v.1.1.1), digest(v.0.6.12), RColorBrewer(v.1.1-2), XVector(v.0.16.0), colorspace(v.1.3-2), htmltools(v.0.3.6), Matrix(v.1.2-11), plyr(v.1.8.4), XML(v.3.98-1.9), pkgconfig(v.2.0.1), devtools(v.1.13.3), biomaRt(v.2.32.1), zlibbioc(v.1.22.0), scales(v.0.5.0), openxlsx(v.4.0.17), BiocParallel(v.1.10.1), tibble(v.1.3.4), ggplot2(v.2.2.1), withr(v.2.0.0), SummarizedExperiment(v.1.6.3), lazyeval(v.0.2.0), magrittr(v.1.5), crayon(v.1.3.2), evaluate(v.0.10.1), memoise(v.1.1.0), xml2(v.1.1.1), graph(v.1.54.0), BiocInstaller(v.1.26.1), tools(v.3.4.1), data.table(v.1.10.4), matrixStats(v.0.52.2), stringr(v.1.2.0), munsell(v.0.4.3), DelayedArray(v.0.2.7), bindrcpp(v.0.2), Biostrings(v.2.44.2), compiler(v.3.4.1), rlang(v.0.1.2), grid(v.3.4.1), RCurl(v.1.95-4.8), iterators(v.1.0.8), base64enc(v.0.1-3), rmarkdown(v.1.6), bitops(v.1.0-6), testthat(v.1.0.2), gtable(v.0.2.0), codetools(v.0.2-15), DBI(v.0.7), roxygen2(v.6.0.1), R6(v.2.2.2), GenomicAlignments(v.1.12.2), knitr(v.1.17), dplyr(v.0.7.2), rtracklayer(v.1.36.4), bit(v.1.1-12), rprojroot(v.1.2), bindr(v.0.1), commonmark(v.1.4), stringi(v.1.1.5) and Rcpp(v.0.12.12)

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 739e4a10345a89efb17b37e7de07c5811491ccea
## R> packrat::restore()
## This is hpgltools commit: Thu Aug 31 11:24:06 2017 -0400: 739e4a10345a89efb17b37e7de07c5811491ccea
this_save <- paste0(gsub(pattern="\\.Rmd", replace="", x=rmd_file), "-v", ver, ".rda.xz")
message(paste0("Saving to: ", this_save))
## Saving to: 01_annotation-v20170703.rda.xz
tmp <- sm(saveme(filename=this_save))
LS0tCnRpdGxlOiAiUk5BU2VxIG8gTC5tYWpvciBvZGQzIHZzLiB3dDogQ29sbGVjdGluZyBhbm5vdGF0aW9uLiIKYXV0aG9yOiAiYXRiIGFiZWxld0BnbWFpbC5jb20iCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogaHRtbF9kb2N1bWVudDoKICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgY29kZV9mb2xkaW5nOiBzaG93CiAgZmlnX2NhcHRpb246IHRydWUKICBmaWdfaGVpZ2h0OiA3CiAgZmlnX3dpZHRoOiA3CiAgaGlnaGxpZ2h0OiBkZWZhdWx0CiAga2VlcF9tZDogZmFsc2UKICBtb2RlOiBzZWxmY29udGFpbmVkCiAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgc2VsZl9jb250YWluZWQ6IHRydWUKICB0aGVtZTogcmVhZGFibGUKICB0b2M6IHRydWUKICB0b2NfZmxvYXQ6CiAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICBzbW9vdGhfc2Nyb2xsOiBmYWxzZQotLS0KCjxzdHlsZT4KICBib2R5IC5tYWluLWNvbnRhaW5lciB7CiAgICBtYXgtd2lkdGg6IDE2MDBweDsKfQo8L3N0eWxlPgoKYGBge3Igb3B0aW9ucywgaW5jbHVkZT1GQUxTRX0KbGlicmFyeSgiaHBnbHRvb2xzIikKdHQgPC0gc20oZGV2dG9vbHM6OmxvYWRfYWxsKCJ+L2hwZ2x0b29scyIpKQprbml0cjo6b3B0c19rbml0JHNldChwcm9ncmVzcz1UUlVFLAogICAgICAgICAgICAgICAgICAgICB2ZXJib3NlPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgIHdpZHRoPTkwLAogICAgICAgICAgICAgICAgICAgICBlY2hvPVRSVUUpCmtuaXRyOjpvcHRzX2NodW5rJHNldChlcnJvcj1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgZmlnLndpZHRoPTgsCiAgICAgICAgICAgICAgICAgICAgICBmaWcuaGVpZ2h0PTgsCiAgICAgICAgICAgICAgICAgICAgICBkcGk9OTYpCm9sZF9vcHRpb25zIDwtIG9wdGlvbnMoZGlnaXRzID0gNCwKICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAga25pdHIuZHVwbGljYXRlLmxhYmVsID0gImFsbG93IikKZ2dwbG90Mjo6dGhlbWVfc2V0KGdncGxvdDI6OnRoZW1lX2J3KGJhc2Vfc2l6ZT0xMCkpCnNldC5zZWVkKDEpCnZlciA8LSAiMjAxNzA3MDMiCnByZXZpb3VzX2ZpbGUgPC0gImluZGV4LlJtZCIKCnRtcCA8LSB0cnkoc20obG9hZG1lKGZpbGVuYW1lPXBhc3RlMChnc3ViKHBhdHRlcm49IlxcLlJtZCIsIHJlcGxhY2U9IiIsIHg9cHJldmlvdXNfZmlsZSksICItdiIsIHZlciwgIi5yZGEueHoiKSkpKQoKcm1kX2ZpbGUgPC0gIjAxX2Fubm90YXRpb24uUm1kIgpgYGAKCmBgYHtyIHJlbmRlcmluZywgaW5jbHVkZT1GQUxTRSwgZXZhbD1GQUxTRX0Kcm1hcmtkb3duOjpyZW5kZXIocm1kX2ZpbGUpCgpybWFya2Rvd246OnJlbmRlcihybWRfZmlsZSwgb3V0cHV0X2Zvcm1hdD0icGRmX2RvY3VtZW50IikKYGBgCgpbaW5kZXguaHRtbF0oaW5kZXguaHRtbCkgW3ByZXByb2Nlc3NpbmcuaHRtbF0ocHJlcHJvY2Vzc2luZy5odG1sKQoKIyBBbm5vdGF0aW9uIHZlcnNpb246IGByIHZlcmAKClRoZXJlIGFyZSBhIGZldyBtZXRob2RzIG9mIGltcG9ydGluZyBhbm5vdGF0aW9uIGRhdGEgaW50byBSLiAgVGhlIGZvbGxvd2luZyBhcmUgdHdvIGF0dGVtcHRzLCB0aGUKc2Vjb25kIGlzIGN1cnJlbnRseSBiZWluZyB1c2VkIGluIHRoZXNlIGFuYWx5c2VzLgoKIyMgQW5ub3RhdGlvbkh1YgoKQW5ub3RhdGlvbkh1YiBpcyBhIG5ld2VyIHNlcnZpY2UgYW5kIGhhcyBwcm9taXNlIHRvIGJlIGFuIGV4Y2VsbGVudCB0b3AtbGV2ZWwgcmVzb3VyY2UgZm9yIGdhdGhlcmluZwphbm5vdGF0aW9uIGRhdGEuCgpgYGB7ciBkYXRhX2lucHV0X2dlbm9tZSwgZXZhbD1GQUxTRX0KIyMgVGhpcyBkb2Vzbid0IHF1aXRlIHdvcmsgeWV0CnR0IDwtIHNtKGxpYnJhcnkoQW5ub3RhdGlvbkh1YikpCmFoIDwtIEFubm90YXRpb25IdWIoKQpvcmdkYnMgPC0gcXVlcnkoYWgsICJPcmdEYiIpCmxlaXNobWFuaWFzIDwtIHF1ZXJ5KGFoLCBjKCJPcmdEQiIsICJMZWlzaG1hbmlhIikpCmBgYAoKIyMgT3JnYW5pc21EYmkKCkFubm90YXRpb25IdWIgaXMgdGhlIG5ldyBhbmQgZmFuY2llciB2ZXJzaW9uIG9mIHdoYXQgT3JnYW5pc21EYiBkb2VzLiAgS2VpdGggYWxyZWFkeSBtYWRlIHRoZXNlIGZvciB0aGUKcGFyYXNpdGVzIHRob3VnaCwgbGV0cyB0cnkgYW5kIHVzZSBvbmUgb2YgdGhvc2UuCgpUaGUgT3JnYW5pc21EYiBwYWNrYWdlcyBhcmUgaW5zdGFsbGFibGUgdmlhIEtlaXRoJ3MgYnVpbGRlcjoKaHR0cHM6Ly9naXRodWIuY29tL2Vsc2F5ZWQtbGFiL2V1cGF0aGRiLW9yZ2FuaXNtZGIKCkkgZGlkIGEgZ2l0IHB1bGwgb2YgaXQsIGNoYW5nZWQgYSBjb3VwbGUgc21hbGwgdGhpbmdzIGFuZCByYW4gJ21ha2UgbGJyYXppbGllbnNpcycuClRoaXMgcHVsbHMgdGhlIGFubm90YXRpb25zIGRvd24gZnJvbSBhIG1peCBvZiBOYWppYidzIGRpcmVjdG9yeSBvbiB0aGUgY2x1c3RlciBhbmQgdGhlIFRyaVRyeXBkYi4KQXMgYSByZXN1bHQsIGl0IGN1cnJlbnRseSBnZXRzIHRoZSB2ZXJzaW9uIDI3IG9mIHRoZSBUcmlUcnlwREIgZGF0YS4gIEl0IG1heSBiZSB1c2VmdWwgZm9yIG1lCnRvIGRvd25sb2FkIGEgbmV3ZXIgcmV2aXNpb24gKGJ1dCBJIGFtIHJlYXNvbmFibHkgY2VydGFpbiBub3QgbXVjaCAob3IgYW55dGhpbmcpIGhhcyBjaGFuZ2VkCmZvciBicmF6aWxpZW5zaXMgaW4gYSB3aGlsZSkuCgpBZnRlciA1IG9yIHNvIG1pbnV0ZXMgYSBicmFuZCBuZXcgcGFja2FnZSAnTGVpc2htYW5pYS5icmF6aWxpZW5zaXMnIGFwcGVhcmVkIGluIG15IFIgZW52aXJvbm1lbnQuCgpgYGB7ciBtYWtlX29yZ2RiLCBldmFsPUZBTFNFfQp0ZXN0aW5nX3BhbmFtZW5zaXMgPC0gbWFrZV90cml0cnlwZGJfb3JnYW5pc21kYmkoImxwYW5hbWVuc2lzIikKdGVzdGluZ19icmF6aWxpZW5zaXMgPC0gbWFrZV90cml0cnlwZGJfb3JnYW5pc21kYmkoImxicmF6aWxpZW5zaXMiKQp0ZXN0aW5nX2Rvbm92YW5pIDwtIG1ha2VfdHJpdHJ5cGRiX29yZ2FuaXNtZGJpKCJsZG9ub3ZhbmkiKQp0ZXN0aW5nX21leGljYW5hIDwtIG1ha2VfdHJpdHJ5cGRiX29yZ2FuaXNtZGJpKCJsbWV4aWNhbmEiKQp0ZXN0aW5nX21ham9yIDwtIG1ha2VfdHJpdHJ5cGRiX29yZ2FuaXNtZGJpKCJsbWFqb3IiKQpgYGAKCmBgYHtyIG1ha2VfZXVwYXRoZGIsIGV2YWw9RkFMU0V9CnRlc3RpbmdfZG9ub3ZhbmlfZXUgPC0gbWFrZV9ldXBhdGhfb3JnYW5pc21kYmkoImRvbm92YW5pIikKYGBgCgpgYGB7ciBsbV9vcmdkYn0KdG1wIDwtIHNtKHRyeShsaWJyYXJ5KCJMZWlzaG1hbmlhLm1ham9yLkZyaWVkbGluIikpKQppZiAoY2xhc3ModG1wKSA9PSAidHJ5LWVycm9yIikgewogIHRtcCA8LSBtYWtlX3RyaXRyeXBkYl9vcmdhbmlzbWRiaSgibG1ham9yIikKfQp0bXAgPC0gc20obGlicmFyeSgib3JnLkxtYWpvci5mcmllZGxpbi5lZy5kYiIpKQp0bXAgPC0gc20obGlicmFyeSgiVHhEYi5MbWFqb3IuZnJpZWRsaW4uVHJpVHJ5cERCMjgiKSkKTGVpc2htYW5pYS5tYWpvci5GcmllZGxpbgpsbV9vcmcgPC0gc20obG9hZF9vcmdkYl9hbm5vdGF0aW9ucyhMZWlzaG1hbmlhLm1ham9yLkZyaWVkbGluLCBrZXl0eXBlPSJnZW5laWQiKSkKbG1fYW5ub3RhdGlvbnMgPC0gbG1fb3JnW1siZ2VuZXMiXV0KYGBgCgojIyBSZWFkIGEgZ2ZmIGZpbGUKCkluIHRoaXMgaW5zdGFuY2UsIGl0IG1pZ2h0IGJlIHNtYXJ0ZXIgdG8gYWN0dWFsbHkgcmVhZCB0aGUgYW5ub3RhdGlvbnMgZnJvbSBhIGdmZiBmaWxlLApwcmltYXJpbHkgYmVjYXVzZSBJIG1vZGlmaWVkIHRoZSBnZmYgZmlsZSB0byBpbmNsdWRlIGFuIGVudHJ5IGZvciB0aGUgTG1qRi4yNi4wODkwIDMnIFVUUi4KCmBgYHtyIGxtX2Zyb21fZ2ZmfQpsbV9nZmZfYW5ub3RhdGlvbnMgPC0gbG9hZF9nZmZfYW5ub3RhdGlvbnMoZ2ZmPSJyZWZlcmVuY2UvbG1ham9yX21vZGlmaWVkLmdmZiIsIHR5cGU9ImdlbmUiKQpoZWFkKGxtX2dmZl9hbm5vdGF0aW9ucykKcm93bmFtZXMobG1fZ2ZmX2Fubm90YXRpb25zKSA8LSBwYXN0ZTAoImV4b25fIiwgbWFrZS5uYW1lcyhsbV9nZmZfYW5ub3RhdGlvbnNbWyJOYW1lIl1dLCB1bmlxdWU9VFJVRSksICIuMSIpCmBgYAoKSW4gY29udHJhc3QsIGl0IGlzIHBvc3NpYmxlIHRvIGxvYWQgbW9zdCBhbm5vdGF0aW9ucyBvZiBpbnRlcmVzdCBkaXJlY3RseSBmcm9tIHRoZSBnZmYgZmlsZXMgdXNlZCBpbgp0aGUgYWxpZ25tZW50cy4gIE1vcmUgaW4tZGVwdGggaW5mb3JtYXRpb24gZm9yIHRoZSBodW1hbiB0cmFuc2NyaXB0b21lIG1heSBiZSBleHRyYWN0ZWQgZnJvbSBiaW9tYXJ0LgoKIyMgR2V0dGluZyBvbnRvbG9neSBkYXRhCgpgYGB7ciBvbnRvbG9neX0KIyMgV2hpbGUgdGVzdGluZywgSSBjYWxsZWQgdGhpcyBkZXNjLCB0aGF0IHdpbGwgbmVlZCB0byBjaGFuZ2UuCmxtX3Rvb2x0aXBzIDwtIG1ha2VfdG9vbHRpcHMoYW5ub3RhdGlvbnM9bG1fZ2ZmX2Fubm90YXRpb25zLCBkZXNjX2NvbD0iZGVzY3JpcHRpb24iKQoKIyNyb3duYW1lcyhsbV9hbm5vdGF0aW9ucykgPC0gcGFzdGUwKCJleG9uXyIsIHJvd25hbWVzKGxtX2Fubm90YXRpb25zKSwgIi4xIikKIyNsbV9sZW5ndGhzIDwtIGxtX2Fubm90YXRpb25zWywgYygiZ2VuZWlkIiwgIndpZHRoIildCiMjY29sbmFtZXMobG1fbGVuZ3RocykgPC0gYygiSUQiLCAid2lkdGgiKQoKbG1fZ29pZHMgPC0gYXMuZGF0YS5mcmFtZShsb2FkX29yZ2RiX2dvKExlaXNobWFuaWEubWFqb3IuRnJpZWRsaW4sIGtleXR5cGU9IlRYSUQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sdW1ucz1jKCJUWE5BTUUiLCJHTyIpKSkKbG1fZ29pZHMgPC0gbG1fZ29pZHNbLCBjKCJUWE5BTUUiLCAiR08iLCAiT05UT0xPR1kiLCAiVEVSTSIpXQpjb2xuYW1lcyhsbV9nb2lkcykgPC0gYygiSUQiLCAiR08iLCAib250IiwgIm5hbWUiKQpuZXdfaWRzIDwtIGdzdWIocGF0dGVybj0iLTEkIiwgcmVwbGFjZW1lbnQ9IlxcLjEiLCB4PWxtX2dvaWRzW1siSUQiXV0pCm5ld19pZHMgPC0gcGFzdGUwKCJleG9uXyIsIG5ld19pZHMpCmxtX2dvaWRzW1siSUQiXV0gPC0gbmV3X2lkcwpgYGAKCiMgUHV0dGluZyB0aGUgcGllY2VzIHRvZ2V0aGVyCgpUaGUgbWFjcm9waGFnZSBleHBlcmltZW50IGhhcyBzYW1wbGVzIGFjcm9zcyAyIGNvbnRleHRzLCB0aGUgaG9zdCBhbmQgcGFyYXNpdGUuICBUaGUgZm9sbG93aW5nIGJsb2NrCnNldHMgdXAgb25lIGV4cGVyaW1lbnQgZm9yIGVhY2guICBJZiB5b3Ugb3BlbiB0aGUgYWxsX3NhbXBsZXMtc3BlY2llcy54bHN4IGZpbGVzLCB5b3Ugd2lsbCBub3RlCmltbWVkaWF0ZWx5IHRoYXQgYSBmZXcgZGlmZmVyZW50IGF0dGVtcHRzIHdlcmUgbWFkZSBhdCBhc2NlcnRhaW5pbmcgdGhlIG1vc3QgbGlrZWx5IGV4cGVyaW1lbnRhbApmYWN0b3JzIHRoYXQgY29udHJpYnV0ZWQgdG8gdGhlIHJlYWRpbHkgYXBwYXJlbnQgYmF0Y2ggZWZmZWN0cy4KClF1ZXN0aW9uOiAgQXJlIHRoZXJlIGFueSBodW1hbiByZWFkcyBpbiB0aGlzIGRhdGE/ICBJIGFzc3VtZSBubywgYnV0IHdpbGwgaGFwcGlseSBtYXAgaHVtYW4gaWYgc28uCgojIyBUaGUgcGFyYXNpdGUgdHJhbnNjcmlwdG9tZSBtYXBwaW5ncwoKYGBge3IgcGFyYXNpdGVfZXhwdH0KcGFyYXNpdGVfZXhwdCA8LSBjcmVhdGVfZXhwdCgic2FtcGxlX3NoZWV0L2FsbF9zYW1wbGVzLnhsc3giLCBnZW5lX2luZm89bG1fZ2ZmX2Fubm90YXRpb25zKQpjaG9zZW5fY29sb3JzIDwtIGxpc3QoCiAgICAid3QiID0gIiNBQTM5MzkiLAogICAgIm9kZDMiID0gIiMwNjczMDAiKQogICAgCnBhcmFzaXRlX2V4cHQgPC0gc2V0X2V4cHRfY29sb3JzKGV4cHQ9cGFyYXNpdGVfZXhwdCwgY29sb3JzPWNob3Nlbl9jb2xvcnMpCmBgYAoKQXQgdGhpcyBwb2ludCwgd2Ugc2hvdWxkIGhhdmUgZXZlcnl0aGluZyBuZWNlc3NhcnkgdG8gcGVyZm9ybSBzb21lIGFuYWx5c2VzLgoKW2luZGV4Lmh0bWxdKGluZGV4Lmh0bWwpCgojIFRoZSBFeHBlcmltZW50IERlc2lnbgoKIyMgUGFyYXNpdGUKCmBgYHtyIGthYmxlX3BhcmFzaXRlfQprbml0cjo6a2FibGUocGFyYXNpdGVfZXhwdCRkZXNpZ24pCmBgYAoKIyBDaGFuZ2Vsb2cKCmBgYHtyIHNhdmVtZX0KcGFuZGVyOjpwYW5kZXIoc2Vzc2lvbkluZm8oKSkKbWVzc2FnZShwYXN0ZTAoIlRoaXMgaXMgaHBnbHRvb2xzIGNvbW1pdDogIiwgZ2V0X2dpdF9jb21taXQoKSkpCnRoaXNfc2F2ZSA8LSBwYXN0ZTAoZ3N1YihwYXR0ZXJuPSJcXC5SbWQiLCByZXBsYWNlPSIiLCB4PXJtZF9maWxlKSwgIi12IiwgdmVyLCAiLnJkYS54eiIpCm1lc3NhZ2UocGFzdGUwKCJTYXZpbmcgdG86ICIsIHRoaXNfc2F2ZSkpCnRtcCA8LSBzbShzYXZlbWUoZmlsZW5hbWU9dGhpc19zYXZlKSkKYGBgCg==