If we want to use PLIER, we need to construct prior information matrices for zebrafish. We’ll do that using two sources: WikiPathways and ZFIN

Setup

`%>%` <- dplyr::`%>%`

rr # BiocManager::install(c(, , .Dr.eg.db), # update = FALSE) # install.packages() library(rWikiPathways) library(XML) library(org.Dr.eg.db)

Loading required package: AnnotationDbi
Loading required package: stats4
Loading required package: BiocGenerics
Loading required package: parallel

Attaching package: ‘BiocGenerics’

The following objects are masked from ‘package:parallel’:

    clusterApply, clusterApplyLB, clusterCall, clusterEvalQ, clusterExport, clusterMap, parApply,
    parCapply, parLapply, parLapplyLB, parRapply, parSapply, parSapplyLB

The following objects are masked from ‘package:stats’:

    IQR, mad, sd, var, xtabs

The following objects are masked from ‘package:base’:

    anyDuplicated, append, as.data.frame, basename, cbind, colMeans, colnames, colSums, dirname, do.call,
    duplicated, eval, evalq, Filter, Find, get, grep, grepl, intersect, is.unsorted, lapply, lengths, Map,
    mapply, match, mget, order, paste, pmax, pmax.int, pmin, pmin.int, Position, rank, rbind, Reduce,
    rowMeans, rownames, rowSums, sapply, setdiff, sort, table, tapply, union, unique, unsplit, which,
    which.max, which.min

Loading required package: Biobase
Welcome to Bioconductor

    Vignettes contain introductory material; view with 'browseVignettes()'. To cite Bioconductor, see
    'citation(\Biobase\)', and for packages 'citation(\pkgname\)'.

Loading required package: IRanges
Loading required package: S4Vectors

Attaching package: ‘S4Vectors’

The following object is masked from ‘package:base’:

    expand.grid

rr pathway_dir <- file.path(, ) dir.create(pathway_dir, showWarnings = FALSE, recursive = TRUE)

WikiPathways

rr # download current version of WikiPathway pathways # this is CC0 downloadPathwayArchive(organism = rerio, format = , destpath = pathway_dir, date = 0190110)

trying URL 'http://data.wikipathways.org/20190110/gmt/wikipathways-20190110-gmt-Danio_rerio.gmt'
Content type 'unknown' length 40448 bytes (39 KB)
==================================================
downloaded 39 KB
[1] \wikipathways-20190110-gmt-Danio_rerio.gmt\

Read the .gmt file in and convert to binary matrix

rr zebrafish_wp_list <- GSA::GSA.read.gmt(file.path(pathway_dir, -20190110-gmt-Danio_rerio.gmt))

Read 83 records
Read 4510 items
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182831
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82

Clean up the list to make it more amenable to the binary prior information matrix we’ll need for use with PLIER.

rr names(zebrafish_wp_list\(genesets) <- make.names( # remove hyphens gsub(\ \, \_\, # convert spaces to underscores gsub(\%WikiPathways_20190110%\, \ \, # remove date, WP information gsub(\%Danio rerio\, \\, # remove species information zebrafish_wp_list\)geneset.names)) ) ) # remove pathway names and descriptions zebrafish_wp_list <- zebrafish_wp_list$genesets

We’re going to use ZFIN identifiers instead of Entrez IDs, which are what are used in WikiPathways.

rr # our goal is to get a binary matrix that represents gene-pathway relationships # to do this, we first need to melt the list into a data.frame zebrafish_wp_binary_df <- reshape2::melt(zebrafish_wp_list) %>% # get sensible column names dplyr::mutate(Gene = value, Pathway = L1) %>% dplyr::select(Gene:Pathway) %>% # conversion from Entrez IDs to ZFIN IDs with mapIds – this should be 1:1 dplyr::mutate(ZFIN = mapIds(org.Dr.eg.db, keys = as.character(Gene), keytype = , column = )) %>% # drop Entrez IDs dplyr::select(-Gene) %>% # drop records missing ZFIN ids dplyr::filter(!is.na(ZFIN)) %>% # unique records only, just in case dplyr::distinct() %>% # get binary matrix, where the first column will be gene and the columns are # pathways reshape2::dcast(ZFIN ~ Pathway, fun.aggregate = length)

'select()' returned 1:1 mapping between keys and columns
Using ZFIN as value column: use value.var to override.

rr # now a more PLIER friendly format zebrafish_wp_binary_mat <- zebrafish_wp_binary_df %>% tibble::column_to_rownames() %>% as.matrix() saveRDS(zebrafish_wp_binary_mat, file.path(pathway_dir, _rerio_wikipathways_prior_info.RDS))

ZFIN

Given the licensing of the ZFIN resource and the fact that downloading via the web interface has the advantage of including the archive date in the file name/header and including the column names, we’ve obtained these files via the downloads webpage using the date that is currently the most recent archive (2019-01-25).

rr wildtype_expression_file <- file.path(pathway_dir, -expression_fish_2019.01.25.txt) # we’re only going to use the in situ data wildtype_expression_df <- readr::read_tsv(wildtype_expression_file, skip = 1) %>% dplyr::filter(Assay == in situ hybridization) %>% dplyr::select(-X15)

Missing column names filled in: 'X15' [15]Parsed with column specification:
cols(
  `Gene ID` = col_character(),
  `Gene Symbol` = col_character(),
  `Fish Name` = col_character(),
  `Super Structure ID` = col_character(),
  `Super Structure Name` = col_character(),
  `Sub Structure ID` = col_character(),
  `Sub Structure Name` = col_character(),
  `Start Stage` = col_character(),
  `End Stage` = col_character(),
  Assay = col_character(),
  `Publication ID` = col_character(),
  `Probe ID` = col_character(),
  `Antibody ID` = col_character(),
  `Fish ID` = col_character(),
  X15 = col_character()
)
number of columns of result is not a multiple of vector length (arg 1)201048 parsing failures.
row # A tibble: 5 x 5 col     row col   expected   actual     file                                                    expected   <int> <chr> <chr>      <chr>      <chr>                                                   actual 1     1 NA    15 columns 14 columns 'data/pathways/wildtype-expression_fish_2019.01.25.txt' file 2     2 NA    15 columns 14 columns 'data/pathways/wildtype-expression_fish_2019.01.25.txt' row 3     3 NA    15 columns 14 columns 'data/pathways/wildtype-expression_fish_2019.01.25.txt' col 4     4 NA    15 columns 14 columns 'data/pathways/wildtype-expression_fish_2019.01.25.txt' expected 5     5 NA    15 columns 14 columns 'data/pathways/wildtype-expression_fish_2019.01.25.txt'
... ................................. ... ........................................................................................... ........ ........................................................................................................................................................................................................................ ...... ..................................................................................................................... .... ..................................................................................................................... ... ..................................................................................................................... ... ..................................................................................................................... ........ .....................................................................................................................
See problems(...) for more details.

We’re hoping to get two gene sets from this ZFIN information: 1) anatomical structure and 2) developmental stage. Parsing this by stage-tissue pairs ends up being extremely sparse, so we can’t approach it that way and get anything useful.

Stages

rr stage_file <- file.path(pathway_dir, _ontology_2019.01.25.txt) stage_df <- readr::read_tsv(stage_file, skip = 1) %>% # drop column associated with parsing error dplyr::select(-X6)

Missing column names filled in: 'X6' [6]Parsed with column specification:
cols(
  `Stage ID` = col_character(),
  `Stage OBO ID` = col_character(),
  `Stage Name` = col_character(),
  `Begin Hours` = col_double(),
  `End Hours` = col_double(),
  X6 = col_character()
)
number of columns of result is not a multiple of vector length (arg 1)45 parsing failures.
row # A tibble: 5 x 5 col     row col   expected  actual    file                                          expected   <int> <chr> <chr>     <chr>     <chr>                                         actual 1     1 NA    6 columns 5 columns 'data/pathways/stage_ontology_2019.01.25.txt' file 2     2 NA    6 columns 5 columns 'data/pathways/stage_ontology_2019.01.25.txt' row 3     3 NA    6 columns 5 columns 'data/pathways/stage_ontology_2019.01.25.txt' col 4     4 NA    6 columns 5 columns 'data/pathways/stage_ontology_2019.01.25.txt' expected 5     5 NA    6 columns 5 columns 'data/pathways/stage_ontology_2019.01.25.txt'
... ................................. ... ............................................................................... ........ ............................................................................................................................................................................................................ ...... ......................................................................................................... .... ......................................................................................................... ... ......................................................................................................... ... ......................................................................................................... ........ .........................................................................................................
See problems(...) for more details.

rr stage_ordered_factor <- factor(stage_df\(`Stage Name`[-1], # drop unknown levels = stage_df\)Stage Name[-1], ordered = TRUE) stage_ordered_factor

 [1] Zygote:1-cell              Cleavage:2-cell            Cleavage:4-cell            Cleavage:8-cell           
 [5] Cleavage:16-cell           Cleavage:32-cell           Cleavage:64-cell           Blastula:128-cell         
 [9] Blastula:256-cell          Blastula:512-cell          Blastula:1k-cell           Blastula:High             
[13] Blastula:Oblong            Blastula:Sphere            Blastula:Dome              Blastula:30%-epiboly      
[17] Gastrula:50%-epiboly       Gastrula:Germ-ring         Gastrula:Shield            Gastrula:75%-epiboly      
[21] Gastrula:90%-epiboly       Gastrula:Bud               Segmentation:1-4 somites   Segmentation:5-9 somites  
[25] Segmentation:10-13 somites Segmentation:14-19 somites Segmentation:20-25 somites Segmentation:26+ somites  
[29] Pharyngula:Prim-5          Pharyngula:Prim-15         Pharyngula:Prim-25         Pharyngula:High-pec       
[33] Hatching:Long-pec          Hatching:Pec-fin           Larval:Protruding-mouth    Larval:Day 4              
[37] Larval:Day 5               Larval:Day 6               Larval:Days 7-13           Larval:Days 14-20         
[41] Larval:Days 21-29          Juvenile:Days 30-44        Juvenile:Days 45-89        Adult                     
44 Levels: Zygote:1-cell < Cleavage:2-cell < Cleavage:4-cell < Cleavage:8-cell < ... < Adult

rr gene_stages_list <- list() for (current_gene in unique(wildtype_expression_df$Gene ID)) {

# initialize vector to hold all the stages for the current gene current_gene_stages <- vector()

# data.frame filtered to current gene only current_gene_df <- wildtype_expression_df %>% dplyr::filter(Gene ID == current_gene)

# all rows in current_gene_df for (gene_row_iter in 1:nrow(current_gene_df)) { # pull pertinent stage information from this row start_stage <- current_gene_df\(`Start Stage`[gene_row_iter] end_stage <- current_gene_df\)End Stage[gene_row_iter]

# find the indices corresponding to the stages and extract the stage
# names from the ordered factor vector
start_index <- which(stage_ordered_factor == start_stage)
end_index <- which(stage_ordered_factor == end_stage)
covered_stages <- as.character(stage_ordered_factor[start_index:end_index])
current_gene_stages <- append(current_gene_stages,
                              covered_stages)

} gene_stages_list[[current_gene]] <- current_gene_stages }

We want to go from this list to a binary matrix for use with PLIER

rr gene_stages_binary_mat <- reshape2::melt(gene_stages_list) %>% # remove any duplicate stages dplyr::distinct() %>% # sensible column names dplyr::mutate(Stage = value, Gene = L1) %>% dplyr::select(Stage:Gene) %>% # and finally, get a PLIER-friendly binary matrix reshape2::dcast(Gene ~ Stage, fun.aggregate = length) %>% tibble::column_to_rownames() %>% as.matrix()

Using Gene as value column: use value.var to override.

rr # save to file saveRDS(gene_stages_binary_mat, file = file.path(pathway_dir, _stages_prior_info.RDS))

Tissues

We’ll use the adult stage only to do the gene-tissue mapping.

rr # filter to only adult adult_wt_df <- wildtype_expression_df %>% dplyr::filter(End Stage == ) # then we can get a list by tissue -> binary matrix adult_tissue_wt_binary_mat <- reshape2::melt( # this gives us a list that we’re melting into a data.frame split(adult_wt_df\(`Gene ID`, adult_wt_df\)Super Structure Name)) %>% # setting informative column names dplyr::mutate(Gene = value, Tissue = L1) %>% dplyr::select(Gene:Tissue) %>% # filtering out any duplicate records dplyr::distinct() %>% # and finally, get a PLIER-friendly binary matrix reshape2::dcast(Gene ~ Tissue, fun.aggregate = length) %>% tibble::column_to_rownames() %>% as.matrix()

Using Tissue as value column: use value.var to override.

rr # save the RDS to file saveRDS(adult_tissue_wt_binary_mat, file.path(pathway_dir, _adult_tissue_prior_info.RDS))

Session info

rr sessionInfo()

R version 3.5.1 (2018-07-02)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Debian GNU/Linux 9 (stretch)

Matrix products: default
BLAS: /usr/lib/openblas-base/libblas.so.3
LAPACK: /usr/lib/libopenblasp-r0.2.19.so

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C               LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
 [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=C              LC_PAPER=en_US.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C             LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] parallel  stats4    stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] bindrcpp_0.2.2       org.Dr.eg.db_3.7.0   AnnotationDbi_1.44.0 IRanges_2.16.0       S4Vectors_0.20.1    
[6] Biobase_2.42.0       BiocGenerics_0.28.0  XML_3.98-1.16        rWikiPathways_1.2.0 

loaded via a namespace (and not attached):
 [1] Rcpp_0.12.18     plyr_1.8.4       pillar_1.3.0     compiler_3.5.1   bindr_0.1.1      bitops_1.0-6    
 [7] tools_3.5.1      digest_0.6.17    bit_1.1-14       RSQLite_2.1.1    memoise_1.1.0    tibble_1.4.2    
[13] pkgconfig_2.0.2  rlang_0.2.2      cli_1.0.1        DBI_1.0.0        rstudioapi_0.7   curl_3.2        
[19] yaml_2.2.0       stringr_1.3.1    dplyr_0.7.6      httr_1.3.1       knitr_1.20       hms_0.4.2       
[25] caTools_1.17.1.1 bit64_0.9-7      tidyselect_0.2.4 glue_1.3.0       R6_2.2.2         fansi_0.3.0     
[31] RJSONIO_1.3-1.1  GSA_1.03         readr_1.1.1      reshape2_1.4.3   purrr_0.2.5      blob_1.1.1      
[37] magrittr_1.5     assertthat_0.2.0 utf8_1.1.4       stringi_1.2.4    crayon_1.3.4    
LS0tCnRpdGxlOiAiQ29uc3RydWN0IF9EYW5pbyByZXJpb18gcHJpb3IgaW5mb3JtYXRpb24gbWF0cmljZXMiCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogVFJVRQogICAgdG9jX2Zsb2F0OiBUUlVFCmF1dGhvcjogSi4gVGFyb25pIGZvciBDQ0RMCmRhdGU6IDIwMTkKLS0tCgpJZiB3ZSB3YW50IHRvIHVzZSBgUExJRVJgLCB3ZSBuZWVkIHRvIGNvbnN0cnVjdCBwcmlvciBpbmZvcm1hdGlvbiBtYXRyaWNlcwpmb3IgemVicmFmaXNoLgpXZSdsbCBkbyB0aGF0IHVzaW5nIHR3byBzb3VyY2VzOiAKW1dpa2lQYXRod2F5c10oaHR0cHM6Ly93d3cud2lraXBhdGh3YXlzLm9yZy9pbmRleC5waHAvV2lraVBhdGh3YXlzKSBhbmQgCltaRklOXShodHRwczovL3pmaW4ub3JnLykKCiMjIFNldHVwCgpgYGB7cn0KYCU+JWAgPC0gZHBseXI6OmAlPiVgCmBgYAoKYGBge3J9CiMgQmlvY01hbmFnZXI6Omluc3RhbGwoYygicldpa2lQYXRod2F5cyIsICJHU0EiLCAib3JnLkRyLmVnLmRiIiksCiMgICAgICAgICAgICAgICAgICAgICAgdXBkYXRlID0gRkFMU0UpCiMgaW5zdGFsbC5wYWNrYWdlcygiWE1MIikKbGlicmFyeShyV2lraVBhdGh3YXlzKQpsaWJyYXJ5KFhNTCkKbGlicmFyeShvcmcuRHIuZWcuZGIpCmBgYAoKYGBge3J9CnBhdGh3YXlfZGlyIDwtIGZpbGUucGF0aCgiZGF0YSIsICJwYXRod2F5cyIpCmRpci5jcmVhdGUocGF0aHdheV9kaXIsIHNob3dXYXJuaW5ncyA9IEZBTFNFLCByZWN1cnNpdmUgPSBUUlVFKQpgYGAKCiMjIFdpa2lQYXRod2F5cwoKYGBge3J9CiMgZG93bmxvYWQgY3VycmVudCB2ZXJzaW9uIG9mIFdpa2lQYXRod2F5IHBhdGh3YXlzCiMgdGhpcyBpcyBDQzAKZG93bmxvYWRQYXRod2F5QXJjaGl2ZShvcmdhbmlzbSA9ICJEYW5pbyByZXJpbyIsIGZvcm1hdCA9ICJnbXQiLAogICAgICAgICAgICAgICAgICAgICAgIGRlc3RwYXRoID0gcGF0aHdheV9kaXIsIGRhdGUgPSAiMjAxOTAxMTAiKQpgYGAKClJlYWQgdGhlIGAuZ210YCBmaWxlIGluIGFuZCBjb252ZXJ0IHRvIGJpbmFyeSBtYXRyaXgKCmBgYHtyfQp6ZWJyYWZpc2hfd3BfbGlzdCA8LSAKICBHU0E6OkdTQS5yZWFkLmdtdChmaWxlLnBhdGgocGF0aHdheV9kaXIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAid2lraXBhdGh3YXlzLTIwMTkwMTEwLWdtdC1EYW5pb19yZXJpby5nbXQiKSkKYGBgCgpDbGVhbiB1cCB0aGUgbGlzdCB0byBtYWtlIGl0IG1vcmUgYW1lbmFibGUgdG8gdGhlIGJpbmFyeSBwcmlvciBpbmZvcm1hdGlvbgptYXRyaXggd2UnbGwgbmVlZCBmb3IgdXNlIHdpdGggUExJRVIuCgpgYGB7cn0KbmFtZXMoemVicmFmaXNoX3dwX2xpc3QkZ2VuZXNldHMpIDwtIG1ha2UubmFtZXMoICAjIHJlbW92ZSBoeXBoZW5zCiAgIyByZW1vdmUgZGF0ZSwgV1AgaW5mb3JtYXRpb24sIGNvbnZlcnQgc3BhY2VzIHRvIHVuZGVyc2NvcmVzCiAgZ3N1YigiJVdpa2lQYXRod2F5c18yMDE5MDExMCV8ICIsICJfIiwgIAogICAgICAgZ3N1YigiJURhbmlvIHJlcmlvIiwgIiIsICAjIHJlbW92ZSBzcGVjaWVzIGluZm9ybWF0aW9uCiAgICAgICAgICAgIHplYnJhZmlzaF93cF9saXN0JGdlbmVzZXQubmFtZXMpKSkKIyByZW1vdmUgcGF0aHdheSBuYW1lcyBhbmQgZGVzY3JpcHRpb25zCnplYnJhZmlzaF93cF9saXN0IDwtIHplYnJhZmlzaF93cF9saXN0JGdlbmVzZXRzCmBgYAoKV2UncmUgZ29pbmcgdG8gdXNlIFpGSU4gaWRlbnRpZmllcnMgaW5zdGVhZCBvZiBFbnRyZXogSURzLCB3aGljaCBhcmUgd2hhdCBhcmUKdXNlZCBpbiBXaWtpUGF0aHdheXMuCgpgYGB7cn0KIyBvdXIgZ29hbCBpcyB0byBnZXQgYSBiaW5hcnkgbWF0cml4IHRoYXQgcmVwcmVzZW50cyBnZW5lLXBhdGh3YXkgcmVsYXRpb25zaGlwcwojIHRvIGRvIHRoaXMsIHdlIGZpcnN0IG5lZWQgdG8gbWVsdCB0aGUgbGlzdCBpbnRvIGEgZGF0YS5mcmFtZQp6ZWJyYWZpc2hfd3BfYmluYXJ5X2RmIDwtIHJlc2hhcGUyOjptZWx0KHplYnJhZmlzaF93cF9saXN0KSAlPiUKICAjIGdldCBzZW5zaWJsZSBjb2x1bW4gbmFtZXMKICBkcGx5cjo6bXV0YXRlKEdlbmUgPSB2YWx1ZSwgUGF0aHdheSA9IEwxKSAlPiUKICBkcGx5cjo6c2VsZWN0KEdlbmU6UGF0aHdheSkgJT4lCiAgIyBjb252ZXJzaW9uIGZyb20gRW50cmV6IElEcyB0byBaRklOIElEcyB3aXRoIG1hcElkcyAtLSB0aGlzIHNob3VsZCBiZSAxOjEKICBkcGx5cjo6bXV0YXRlKFpGSU4gPSBtYXBJZHMob3JnLkRyLmVnLmRiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2V5cyA9IGFzLmNoYXJhY3RlcihHZW5lKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtleXR5cGUgPSAiRU5UUkVaSUQiLCBjb2x1bW4gPSAiWkZJTiIpKSAlPiUKICAjIGRyb3AgRW50cmV6IElEcwogIGRwbHlyOjpzZWxlY3QoLUdlbmUpICU+JQogICMgZHJvcCByZWNvcmRzIG1pc3NpbmcgWkZJTiBpZHMKICBkcGx5cjo6ZmlsdGVyKCFpcy5uYShaRklOKSkgJT4lCiAgIyB1bmlxdWUgcmVjb3JkcyBvbmx5LCBqdXN0IGluIGNhc2UKICBkcGx5cjo6ZGlzdGluY3QoKSAlPiUKICAjIGdldCBiaW5hcnkgbWF0cml4LCB3aGVyZSB0aGUgZmlyc3QgY29sdW1uIHdpbGwgYmUgZ2VuZSBhbmQgdGhlIGNvbHVtbnMgYXJlCiAgIyBwYXRod2F5cwogIHJlc2hhcGUyOjpkY2FzdChaRklOIH4gUGF0aHdheSwgZnVuLmFnZ3JlZ2F0ZSA9IGxlbmd0aCkKYGBgCgpgYGB7cn0KIyBub3cgYSBtb3JlIFBMSUVSIGZyaWVuZGx5IGZvcm1hdAp6ZWJyYWZpc2hfd3BfYmluYXJ5X21hdCA8LSB6ZWJyYWZpc2hfd3BfYmluYXJ5X2RmICU+JQogIHRpYmJsZTo6Y29sdW1uX3RvX3Jvd25hbWVzKCJaRklOIikgJT4lCiAgYXMubWF0cml4KCkKc2F2ZVJEUyh6ZWJyYWZpc2hfd3BfYmluYXJ5X21hdCwgCiAgICAgICAgZmlsZS5wYXRoKHBhdGh3YXlfZGlyLCAiRGFuaW9fcmVyaW9fd2lraXBhdGh3YXlzX3ByaW9yX2luZm8uUkRTIikpCmBgYAoKIyMgWkZJTgoKR2l2ZW4gdGhlIFtsaWNlbnNpbmcgb2YgdGhlIFpGSU4gcmVzb3VyY2VdKGh0dHBzOi8vemZpbi5vcmcvd2FycmFudHkuaHRtbCkgYW5kIAp0aGUgZmFjdCB0aGF0IGRvd25sb2FkaW5nIHZpYSB0aGUgd2ViIGludGVyZmFjZSBoYXMgdGhlIGFkdmFudGFnZSBvZiBpbmNsdWRpbmcgCnRoZSBhcmNoaXZlIGRhdGUgaW4gdGhlIGZpbGUgbmFtZS9oZWFkZXIgYW5kIGluY2x1ZGluZyB0aGUgY29sdW1uIG5hbWVzLCB3ZSd2ZSAKb2J0YWluZWQgdGhlc2UgZmlsZXMgdmlhIHRoZSAKW2Rvd25sb2FkcyB3ZWJwYWdlXShodHRwczovL3pmaW4ub3JnL2Rvd25sb2Fkcy9hcmNoaXZlLzIwMTkuMDEuMjUpIHVzaW5nIHRoZQpkYXRlIHRoYXQgaXMgY3VycmVudGx5IHRoZSBtb3N0IHJlY2VudCBhcmNoaXZlIChgMjAxOS0wMS0yNWApLgoKYGBge3J9CndpbGR0eXBlX2V4cHJlc3Npb25fZmlsZSA8LSAKICBmaWxlLnBhdGgocGF0aHdheV9kaXIsICJ3aWxkdHlwZS1leHByZXNzaW9uX2Zpc2hfMjAxOS4wMS4yNS50eHQiKQojIHdlJ3JlIG9ubHkgZ29pbmcgdG8gdXNlIHRoZSBpbiBzaXR1IGRhdGEKd2lsZHR5cGVfZXhwcmVzc2lvbl9kZiA8LSByZWFkcjo6cmVhZF90c3Yod2lsZHR5cGVfZXhwcmVzc2lvbl9maWxlLCBza2lwID0gMSkgJT4lCiAgZHBseXI6OmZpbHRlcihBc3NheSA9PSAibVJOQSBpbiBzaXR1IGh5YnJpZGl6YXRpb24iKSAlPiUKICBkcGx5cjo6c2VsZWN0KC1YMTUpCmBgYAoKV2UncmUgaG9waW5nIHRvIGdldCB0d28gZ2VuZSBzZXRzIGZyb20gdGhpcyBaRklOIGluZm9ybWF0aW9uOiAxKSBhbmF0b21pY2FsCnN0cnVjdHVyZSBhbmQgMikgZGV2ZWxvcG1lbnRhbCBzdGFnZS4KUGFyc2luZyB0aGlzIGJ5IHN0YWdlLXRpc3N1ZSBwYWlycyBlbmRzIHVwIGJlaW5nIGV4dHJlbWVseSBzcGFyc2UsIHNvIHdlIGNhbid0CmFwcHJvYWNoIGl0IHRoYXQgd2F5IGFuZCBnZXQgYW55dGhpbmcgdXNlZnVsLgoKIyMjIFN0YWdlcwoKYGBge3J9CnN0YWdlX2ZpbGUgPC0gZmlsZS5wYXRoKHBhdGh3YXlfZGlyLCAic3RhZ2Vfb250b2xvZ3lfMjAxOS4wMS4yNS50eHQiKQpzdGFnZV9kZiA8LSByZWFkcjo6cmVhZF90c3Yoc3RhZ2VfZmlsZSwgc2tpcCA9IDEpICU+JQogICMgZHJvcCBjb2x1bW4gYXNzb2NpYXRlZCB3aXRoIHBhcnNpbmcgZXJyb3IKICBkcGx5cjo6c2VsZWN0KC1YNikKYGBgCgpgYGB7cn0Kc3RhZ2Vfb3JkZXJlZF9mYWN0b3IgPC0gZmFjdG9yKHN0YWdlX2RmJGBTdGFnZSBOYW1lYFstMV0sICAjIGRyb3AgdW5rbm93bgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gc3RhZ2VfZGYkYFN0YWdlIE5hbWVgWy0xXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyZWQgPSBUUlVFKQpzdGFnZV9vcmRlcmVkX2ZhY3RvcgpgYGAKYGBge3J9CmdlbmVfc3RhZ2VzX2xpc3QgPC0gbGlzdCgpCmZvciAoY3VycmVudF9nZW5lIGluIHVuaXF1ZSh3aWxkdHlwZV9leHByZXNzaW9uX2RmJGBHZW5lIElEYCkpIHsKICAKICAjIGluaXRpYWxpemUgdmVjdG9yIHRvIGhvbGQgX2FsbF8gdGhlIHN0YWdlcyBmb3IgdGhlIGN1cnJlbnQgZ2VuZQogIGN1cnJlbnRfZ2VuZV9zdGFnZXMgPC0gdmVjdG9yKCkKICAKICAjIGRhdGEuZnJhbWUgZmlsdGVyZWQgdG8gY3VycmVudCBnZW5lIG9ubHkKICBjdXJyZW50X2dlbmVfZGYgPC0gd2lsZHR5cGVfZXhwcmVzc2lvbl9kZiAlPiUKICAgIGRwbHlyOjpmaWx0ZXIoYEdlbmUgSURgID09IGN1cnJlbnRfZ2VuZSkKICAKICAjIGFsbCByb3dzIGluIGN1cnJlbnRfZ2VuZV9kZgogIGZvciAoZ2VuZV9yb3dfaXRlciBpbiAxOm5yb3coY3VycmVudF9nZW5lX2RmKSkgewogICAgIyBwdWxsIHBlcnRpbmVudCBzdGFnZSBpbmZvcm1hdGlvbiBmcm9tIHRoaXMgcm93CiAgICBzdGFydF9zdGFnZSA8LSBjdXJyZW50X2dlbmVfZGYkYFN0YXJ0IFN0YWdlYFtnZW5lX3Jvd19pdGVyXQogICAgZW5kX3N0YWdlIDwtIGN1cnJlbnRfZ2VuZV9kZiRgRW5kIFN0YWdlYFtnZW5lX3Jvd19pdGVyXQogICAgCiAgICAjIGZpbmQgdGhlIGluZGljZXMgY29ycmVzcG9uZGluZyB0byB0aGUgc3RhZ2VzIGFuZCBleHRyYWN0IHRoZSBzdGFnZQogICAgIyBuYW1lcyBmcm9tIHRoZSBvcmRlcmVkIGZhY3RvciB2ZWN0b3IKICAgIHN0YXJ0X2luZGV4IDwtIHdoaWNoKHN0YWdlX29yZGVyZWRfZmFjdG9yID09IHN0YXJ0X3N0YWdlKQogICAgZW5kX2luZGV4IDwtIHdoaWNoKHN0YWdlX29yZGVyZWRfZmFjdG9yID09IGVuZF9zdGFnZSkKICAgIGlmIChlbmRfaW5kZXggPj0gc3RhcnRfaW5kZXgpIHsKICAgICAgY292ZXJlZF9zdGFnZXMgPC0gCiAgICAgICAgYXMuY2hhcmFjdGVyKHN0YWdlX29yZGVyZWRfZmFjdG9yW3N0YXJ0X2luZGV4OmVuZF9pbmRleF0pCiAgICAgIGN1cnJlbnRfZ2VuZV9zdGFnZXMgPC0gYXBwZW5kKGN1cnJlbnRfZ2VuZV9zdGFnZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdmVyZWRfc3RhZ2VzKQogICAgfSAKICB9CiAgZ2VuZV9zdGFnZXNfbGlzdFtbY3VycmVudF9nZW5lXV0gPC0gY3VycmVudF9nZW5lX3N0YWdlcwp9CmBgYAoKV2Ugd2FudCB0byBnbyBmcm9tIHRoaXMgbGlzdCB0byBhIGJpbmFyeSBtYXRyaXggZm9yIHVzZSB3aXRoIFBMSUVSCgpgYGB7cn0KZ2VuZV9zdGFnZXNfYmluYXJ5X21hdCA8LSByZXNoYXBlMjo6bWVsdChnZW5lX3N0YWdlc19saXN0KSAlPiUKICAjIHJlbW92ZSBhbnkgZHVwbGljYXRlIHN0YWdlcwogIGRwbHlyOjpkaXN0aW5jdCgpICU+JQogICMgc2Vuc2libGUgY29sdW1uIG5hbWVzCiAgZHBseXI6Om11dGF0ZShTdGFnZSA9IHZhbHVlLCBHZW5lID0gTDEpICU+JQogIGRwbHlyOjpzZWxlY3QoU3RhZ2U6R2VuZSkgJT4lCiAgIyBhbmQgZmluYWxseSwgZ2V0IGEgUExJRVItZnJpZW5kbHkgYmluYXJ5IG1hdHJpeAogIHJlc2hhcGUyOjpkY2FzdChHZW5lIH4gU3RhZ2UsIGZ1bi5hZ2dyZWdhdGUgPSBsZW5ndGgpICU+JQogIHRpYmJsZTo6Y29sdW1uX3RvX3Jvd25hbWVzKCJHZW5lIikgJT4lCiAgYXMubWF0cml4KCkKIyBzYXZlIHRvIGZpbGUKc2F2ZVJEUyhnZW5lX3N0YWdlc19iaW5hcnlfbWF0LAogICAgICAgIGZpbGUgPSBmaWxlLnBhdGgocGF0aHdheV9kaXIsIAogICAgICAgICAgICAgICAgICAgICAgICAgIlpGSU5fc3RhZ2VzX3ByaW9yX2luZm8uUkRTIikpCmBgYAoKIyMjIFRpc3N1ZXMKCldlJ2xsIHVzZSB0aGUgYWR1bHQgc3RhZ2UgX29ubHlfIHRvIGRvIHRoZSBnZW5lLXRpc3N1ZSBtYXBwaW5nLgoKYGBge3J9CiMgZmlsdGVyIHRvIG9ubHkgYWR1bHQKYWR1bHRfd3RfZGYgPC0gd2lsZHR5cGVfZXhwcmVzc2lvbl9kZiAlPiUKICBkcGx5cjo6ZmlsdGVyKGBFbmQgU3RhZ2VgID09ICJBZHVsdCIpCgojIHRoZW4gd2UgY2FuIGdldCBhIGxpc3QgYnkgdGlzc3VlIC0+IGJpbmFyeSBtYXRyaXgKYWR1bHRfdGlzc3VlX3d0X2JpbmFyeV9tYXQgPC0gCiAgcmVzaGFwZTI6Om1lbHQoCiAgICAjIHRoaXMgZ2l2ZXMgdXMgYSBsaXN0IHRoYXQgd2UncmUgbWVsdGluZyBpbnRvIGEgZGF0YS5mcmFtZQogICAgc3BsaXQoYWR1bHRfd3RfZGYkYEdlbmUgSURgLAogICAgICAgICAgYWR1bHRfd3RfZGYkYFN1cGVyIFN0cnVjdHVyZSBOYW1lYCkpICU+JQogICMgc2V0dGluZyBpbmZvcm1hdGl2ZSBjb2x1bW4gbmFtZXMKICBkcGx5cjo6bXV0YXRlKEdlbmUgPSB2YWx1ZSwgVGlzc3VlID0gTDEpICU+JQogIGRwbHlyOjpzZWxlY3QoR2VuZTpUaXNzdWUpICU+JQogICMgZmlsdGVyaW5nIG91dCBhbnkgZHVwbGljYXRlIHJlY29yZHMKICBkcGx5cjo6ZGlzdGluY3QoKSAlPiUKICAjIGFuZCBmaW5hbGx5LCBnZXQgYSBQTElFUi1mcmllbmRseSBiaW5hcnkgbWF0cml4CiAgcmVzaGFwZTI6OmRjYXN0KEdlbmUgfiBUaXNzdWUsIGZ1bi5hZ2dyZWdhdGUgPSBsZW5ndGgpICU+JQogIHRpYmJsZTo6Y29sdW1uX3RvX3Jvd25hbWVzKCJHZW5lIikgJT4lCiAgYXMubWF0cml4KCkKCiMgc2F2ZSB0aGUgUkRTIHRvIGZpbGUKc2F2ZVJEUyhhZHVsdF90aXNzdWVfd3RfYmluYXJ5X21hdCwgCiAgICAgICAgZmlsZS5wYXRoKHBhdGh3YXlfZGlyLCAiWkZJTl9hZHVsdF90aXNzdWVfcHJpb3JfaW5mby5SRFMiKSkKYGBgCgojIyBTZXNzaW9uIGluZm8KCmBgYHtyfQpzZXNzaW9uSW5mbygpCmBgYAo=