1 Paths

dir.single.cohort <- "../DATASETS"
dir.gasparoni <- file.path(dir.single.cohort, "GASPARONI/step9_single_cpg_pval")
dir.london <- file.path(dir.single.cohort, "LONDON/step7_single_cpg_pval")
dir.mtsinai <- file.path(dir.single.cohort, "MtSinai/step7_single_cpg_pval")
dir.rosmap <- file.path(dir.single.cohort, "ROSMAP/step9_single_cpg_pval")
dir.meta.single.cpg <- "../meta_analysis_single_cpg_results/"
dir.data <- "./DATASETS"
dir.fig <- "./FIGURES"

2 Estimation of inflation

library(dplyr)
library(bacon)
library(GWASTools)

2.1 Auxiliary functions

estimation_of_inflation <- function(data){
  ### 1. Compute genomic inflation factor before bacon adjustment
  data$zvalue <- data$Estimate / data$StdErr
  data$chisq <- (data$zvalue) ^ 2

  # inflation factor - last term is median from chisq distrn with 1 df  
  inflationFactor <- median(data$chisq,na.rm = TRUE) / qchisq(0.5, 1)
  print("lambda")
  print(inflationFactor)

  # genome-wide sig cpgs
  sig <- ifelse(data$pValue < 2.4e-7, 1, 0)
  # table(sig)  # 1 sig

  ### 2. bacon analysis
  bc <- bacon(
    teststatistics = NULL,
    effectsizes =  data$Estimate,
    standarderrors = data$StdErr,
    na.exclude = TRUE
  )

  # inflation factor
  print("lambda.bacon")
  print(inflation(bc))
  
  ### 3. Create final dataset
  data.with.inflation <- data.frame(
    data,
    Estimate.bacon = bacon::es(bc),
    StdErr.bacon = bacon::se(bc),
    pValue.bacon = pval(bc),
    fdr.bacon = p.adjust(pval(bc), method = "fdr"),
    stringsAsFactors = FALSE
  )
  data.with.inflation <- data.with.inflation %>% select(-c(zvalue, chisq))
  return(
    list("data.with.inflation" = data.with.inflation, 
          "inflationFactor" =   inflationFactor,
          "estimatedInflation" = inflation(bc)
         )
    )
}

2.2 GASPARONI

est.inflation <- estimation_of_inflation(res)
## [1] "lambda"
## [1] 1.002218
## [1] "lambda.bacon"
##   sigma.0 
## 0.9852269
res.with.inflation <- est.inflation$data.with.inflation


cohort <- "GASPARONI"
write.csv(
    res.with.inflation,
    file.path(dir.data, cohort, "single_cpg_pVal_df.csv"),
    row.names = FALSE
)

# genome-wide sig cpgs
sig.fdr <- ifelse(res.with.inflation$fdr.bacon < 0.05, 1, 0)
# table(sig.fdr)   # 2 sig

2.3 LONDON

est.inflation <- estimation_of_inflation(res)
## [1] "lambda"
## [1] 1.208283
## [1] "lambda.bacon"
##  sigma.0 
## 1.082232
res.with.inflation <- est.inflation$data.with.inflation

cohort <- "LONDON"

write.csv(
    res.with.inflation,
    file.path(dir.data, cohort, "single_cpg_pVal_df.csv"),
    row.names = FALSE
)

# genome-wide sig cpgs
sig.fdr <- ifelse(res.with.inflation$fdr.bacon < 0.05, 1, 0)
# table(sig.fdr)   # 11 sig

2.4 MTSINAI

est.inflation <- estimation_of_inflation(res)
## [1] "lambda"
## [1] 1.248826
## [1] "lambda.bacon"
##  sigma.0 
## 1.077693
res.with.inflation <- est.inflation$data.with.inflation

cohort <- "MTSINAI"

write.csv(
    res.with.inflation,
    file.path(dir.data, cohort, "single_cpg_pVal_df.csv"),
    row.names = FALSE
)

# genome-wide sig cpgs
sig.fdr <- ifelse(res.with.inflation$fdr.bacon < 0.05, 1, 0)
# table(sig.fdr)   # 0 sig

2.5 ROSMAP

est.inflation <- estimation_of_inflation(res)
## [1] "lambda"
## [1] 1.015642
## [1] "lambda.bacon"
##  sigma.0 
## 1.001666
res.with.inflation <- est.inflation$data.with.inflation

cohort <- "ROSMAP"

write.csv(
    res.with.inflation,
    file.path(dir.data, cohort, "single_cpg_pVal_df.csv"),
    row.names = FALSE
)

# genome-wide sig cpgs
sig.fdr <- ifelse(res.with.inflation$fdr.bacon < 0.05, 1, 0)
# table(sig.fdr)   # 34 sig

3 Session information

devtools::session_info()
## ─ Session info ───────────────────────────────────────────────────────────────
##  setting  value                       
##  version  R version 4.0.2 (2020-06-22)
##  os       macOS Catalina 10.15.6      
##  system   x86_64, darwin17.0          
##  ui       X11                         
##  language (EN)                        
##  collate  en_US.UTF-8                 
##  ctype    en_US.UTF-8                 
##  tz       America/New_York            
##  date     2020-08-11                  
## 
## ─ Packages ───────────────────────────────────────────────────────────────────
##  package      * version  date       lib source        
##  assertthat     0.2.1    2019-03-21 [1] CRAN (R 4.0.2)
##  backports      1.1.8    2020-06-17 [1] CRAN (R 4.0.2)
##  bacon        * 1.16.0   2020-04-27 [1] Bioconductor  
##  base64enc      0.1-3    2015-07-28 [1] CRAN (R 4.0.2)
##  Biobase      * 2.48.0   2020-04-27 [1] Bioconductor  
##  BiocGenerics * 0.34.0   2020-04-27 [1] Bioconductor  
##  BiocParallel * 1.22.0   2020-04-27 [1] Bioconductor  
##  bit            4.0.3    2020-07-30 [1] CRAN (R 4.0.2)
##  bit64          4.0.2    2020-07-30 [1] CRAN (R 4.0.2)
##  blob           1.2.1    2020-01-20 [1] CRAN (R 4.0.2)
##  broom          0.7.0    2020-07-09 [1] CRAN (R 4.0.2)
##  callr          3.4.3    2020-03-28 [1] CRAN (R 4.0.2)
##  cli            2.0.2    2020-02-28 [1] CRAN (R 4.0.2)
##  colorspace     1.4-1    2019-03-18 [1] CRAN (R 4.0.2)
##  conquer        1.0.1    2020-05-06 [1] CRAN (R 4.0.2)
##  crayon         1.3.4    2017-09-16 [1] CRAN (R 4.0.2)
##  DBI            1.1.0    2019-12-15 [1] CRAN (R 4.0.2)
##  desc           1.2.0    2018-05-01 [1] CRAN (R 4.0.2)
##  devtools       2.3.1    2020-07-21 [1] CRAN (R 4.0.2)
##  digest         0.6.25   2020-02-23 [1] CRAN (R 4.0.2)
##  DNAcopy        1.62.0   2020-04-27 [1] Bioconductor  
##  dplyr        * 1.0.1    2020-07-31 [1] CRAN (R 4.0.2)
##  ellipse      * 0.4.2    2020-05-27 [1] CRAN (R 4.0.2)
##  ellipsis       0.3.1    2020-05-15 [1] CRAN (R 4.0.2)
##  evaluate       0.14     2019-05-28 [1] CRAN (R 4.0.1)
##  fansi          0.4.1    2020-01-08 [1] CRAN (R 4.0.2)
##  fs             1.5.0    2020-07-31 [1] CRAN (R 4.0.2)
##  gdsfmt         1.24.1   2020-06-16 [1] Bioconductor  
##  generics       0.0.2    2018-11-29 [1] CRAN (R 4.0.2)
##  ggplot2      * 3.3.2    2020-06-19 [1] CRAN (R 4.0.2)
##  glue           1.4.1    2020-05-13 [1] CRAN (R 4.0.2)
##  gtable         0.3.0    2019-03-25 [1] CRAN (R 4.0.2)
##  GWASExactHW    1.01     2013-01-05 [1] CRAN (R 4.0.2)
##  GWASTools    * 1.34.0   2020-04-27 [1] Bioconductor  
##  htmltools      0.5.0    2020-06-16 [1] CRAN (R 4.0.2)
##  knitr          1.29     2020-06-23 [1] CRAN (R 4.0.2)
##  lattice        0.20-41  2020-04-02 [1] CRAN (R 4.0.2)
##  lifecycle      0.2.0    2020-03-06 [1] CRAN (R 4.0.2)
##  lmtest         0.9-37   2019-04-30 [1] CRAN (R 4.0.2)
##  logistf        1.23     2018-07-19 [1] CRAN (R 4.0.2)
##  magrittr       1.5      2014-11-22 [1] CRAN (R 4.0.2)
##  Matrix         1.2-18   2019-11-27 [1] CRAN (R 4.0.2)
##  MatrixModels   0.4-1    2015-08-22 [1] CRAN (R 4.0.2)
##  matrixStats    0.56.0   2020-03-13 [1] CRAN (R 4.0.2)
##  memoise        1.1.0    2017-04-21 [1] CRAN (R 4.0.2)
##  mgcv           1.8-31   2019-11-09 [1] CRAN (R 4.0.2)
##  mice           3.10.0.1 2020-08-02 [1] CRAN (R 4.0.2)
##  munsell        0.5.0    2018-06-12 [1] CRAN (R 4.0.2)
##  nlme           3.1-148  2020-05-24 [1] CRAN (R 4.0.2)
##  pillar         1.4.6    2020-07-10 [1] CRAN (R 4.0.2)
##  pkgbuild       1.1.0    2020-07-13 [1] CRAN (R 4.0.2)
##  pkgconfig      2.0.3    2019-09-22 [1] CRAN (R 4.0.2)
##  pkgload        1.1.0    2020-05-29 [1] CRAN (R 4.0.2)
##  prettyunits    1.1.1    2020-01-24 [1] CRAN (R 4.0.2)
##  processx       3.4.3    2020-07-05 [1] CRAN (R 4.0.2)
##  ps             1.3.3    2020-05-08 [1] CRAN (R 4.0.2)
##  purrr          0.3.4    2020-04-17 [1] CRAN (R 4.0.2)
##  quantreg       5.61     2020-07-09 [1] CRAN (R 4.0.2)
##  quantsmooth    1.54.0   2020-04-27 [1] Bioconductor  
##  R6             2.4.1    2019-11-12 [1] CRAN (R 4.0.2)
##  Rcpp           1.0.5    2020-07-06 [1] CRAN (R 4.0.2)
##  remotes        2.2.0    2020-07-21 [1] CRAN (R 4.0.2)
##  rlang          0.4.7    2020-07-09 [1] CRAN (R 4.0.2)
##  rmarkdown      2.3      2020-06-18 [1] CRAN (R 4.0.2)
##  rprojroot      1.3-2    2018-01-03 [1] CRAN (R 4.0.2)
##  RSQLite        2.2.0    2020-01-07 [1] CRAN (R 4.0.2)
##  sandwich       2.5-1    2019-04-06 [1] CRAN (R 4.0.2)
##  scales         1.1.1    2020-05-11 [1] CRAN (R 4.0.2)
##  sessioninfo    1.1.1    2018-11-05 [1] CRAN (R 4.0.2)
##  SparseM        1.78     2019-12-13 [1] CRAN (R 4.0.2)
##  stringi        1.4.6    2020-02-17 [1] CRAN (R 4.0.2)
##  stringr        1.4.0    2019-02-10 [1] CRAN (R 4.0.2)
##  survival       3.2-3    2020-06-13 [1] CRAN (R 4.0.2)
##  testthat       2.3.2    2020-03-02 [1] CRAN (R 4.0.2)
##  tibble         3.0.3    2020-07-10 [1] CRAN (R 4.0.2)
##  tidyr          1.1.1    2020-07-31 [1] CRAN (R 4.0.2)
##  tidyselect     1.1.0    2020-05-11 [1] CRAN (R 4.0.2)
##  usethis        1.6.1    2020-04-29 [1] CRAN (R 4.0.2)
##  vctrs          0.3.2    2020-07-15 [1] CRAN (R 4.0.2)
##  withr          2.2.0    2020-04-20 [1] CRAN (R 4.0.2)
##  xfun           0.16     2020-07-24 [1] CRAN (R 4.0.2)
##  yaml           2.2.1    2020-02-01 [1] CRAN (R 4.0.2)
##  zoo            1.8-8    2020-05-02 [1] CRAN (R 4.0.2)
## 
## [1] /Library/Frameworks/R.framework/Versions/4.0/Resources/library
LS0tDQp0aXRsZTogIlNlbnNpdGl2aXR5IEFuYWx5c2lzIC0gZXN0aW1hdGlvbiBvZiBnZW5vbWljIGluZmxhdGlvbiINCmF1dGhvcjogIkxhbnl1IFpoYW5nLCBUaWFnbyBDLiBTaWx2YSwgTGlseSBXYW5nIg0KZGF0ZTogImByIFN5cy5EYXRlKClgIg0Kb3V0cHV0Og0KICBybWFya2Rvd246Omh0bWxfZG9jdW1lbnQ6DQogICAgdGhlbWU6IGx1bWVuDQogICAgdG9jOiB0cnVlDQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgZGZfcHJpbnQ6IHBhZ2VkDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIHRvY19mbG9hdDoNCiAgICAgIGNvbGxhcHNlZDogeWVzDQogICAgdG9jX2RlcHRoOiAzDQplZGl0b3Jfb3B0aW9uczoNCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGlubGluZSAgICANCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgd2FybmluZyA9IEZBTFNFKQ0KYGBgDQoNCiMgUGF0aHMNCg0KYGBge1J9DQpkaXIuc2luZ2xlLmNvaG9ydCA8LSAiLi4vREFUQVNFVFMiDQpkaXIuZ2FzcGFyb25pIDwtIGZpbGUucGF0aChkaXIuc2luZ2xlLmNvaG9ydCwgIkdBU1BBUk9OSS9zdGVwOV9zaW5nbGVfY3BnX3B2YWwiKQ0KZGlyLmxvbmRvbiA8LSBmaWxlLnBhdGgoZGlyLnNpbmdsZS5jb2hvcnQsICJMT05ET04vc3RlcDdfc2luZ2xlX2NwZ19wdmFsIikNCmRpci5tdHNpbmFpIDwtIGZpbGUucGF0aChkaXIuc2luZ2xlLmNvaG9ydCwgIk10U2luYWkvc3RlcDdfc2luZ2xlX2NwZ19wdmFsIikNCmRpci5yb3NtYXAgPC0gZmlsZS5wYXRoKGRpci5zaW5nbGUuY29ob3J0LCAiUk9TTUFQL3N0ZXA5X3NpbmdsZV9jcGdfcHZhbCIpDQpkaXIubWV0YS5zaW5nbGUuY3BnIDwtICIuLi9tZXRhX2FuYWx5c2lzX3NpbmdsZV9jcGdfcmVzdWx0cy8iDQpkaXIuZGF0YSA8LSAiLi9EQVRBU0VUUyINCmRpci5maWcgPC0gIi4vRklHVVJFUyINCmBgYA0KDQojIEVzdGltYXRpb24gb2YgaW5mbGF0aW9uDQoNCmBgYHtSLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgcmVzdWx0ID0gImhpZGUifQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoYmFjb24pDQpsaWJyYXJ5KEdXQVNUb29scykNCmBgYA0KDQojIyBBdXhpbGlhcnkgZnVuY3Rpb25zDQoNCmBgYHtSfQ0KZXN0aW1hdGlvbl9vZl9pbmZsYXRpb24gPC0gZnVuY3Rpb24oZGF0YSl7DQogICMjIyAxLiBDb21wdXRlIGdlbm9taWMgaW5mbGF0aW9uIGZhY3RvciBiZWZvcmUgYmFjb24gYWRqdXN0bWVudA0KICBkYXRhJHp2YWx1ZSA8LSBkYXRhJEVzdGltYXRlIC8gZGF0YSRTdGRFcnINCiAgZGF0YSRjaGlzcSA8LSAoZGF0YSR6dmFsdWUpIF4gMg0KDQogICMgaW5mbGF0aW9uIGZhY3RvciAtIGxhc3QgdGVybSBpcyBtZWRpYW4gZnJvbSBjaGlzcSBkaXN0cm4gd2l0aCAxIGRmICANCiAgaW5mbGF0aW9uRmFjdG9yIDwtIG1lZGlhbihkYXRhJGNoaXNxLG5hLnJtID0gVFJVRSkgLyBxY2hpc3EoMC41LCAxKQ0KICBwcmludCgibGFtYmRhIikNCiAgcHJpbnQoaW5mbGF0aW9uRmFjdG9yKQ0KDQogICMgZ2Vub21lLXdpZGUgc2lnIGNwZ3MNCiAgc2lnIDwtIGlmZWxzZShkYXRhJHBWYWx1ZSA8IDIuNGUtNywgMSwgMCkNCiAgIyB0YWJsZShzaWcpICAjIDEgc2lnDQoNCiAgIyMjIDIuIGJhY29uIGFuYWx5c2lzDQogIGJjIDwtIGJhY29uKA0KICAgIHRlc3RzdGF0aXN0aWNzID0gTlVMTCwNCiAgICBlZmZlY3RzaXplcyA9ICBkYXRhJEVzdGltYXRlLA0KICAgIHN0YW5kYXJkZXJyb3JzID0gZGF0YSRTdGRFcnIsDQogICAgbmEuZXhjbHVkZSA9IFRSVUUNCiAgKQ0KDQogICMgaW5mbGF0aW9uIGZhY3Rvcg0KICBwcmludCgibGFtYmRhLmJhY29uIikNCiAgcHJpbnQoaW5mbGF0aW9uKGJjKSkNCiAgDQogICMjIyAzLiBDcmVhdGUgZmluYWwgZGF0YXNldA0KICBkYXRhLndpdGguaW5mbGF0aW9uIDwtIGRhdGEuZnJhbWUoDQogICAgZGF0YSwNCiAgICBFc3RpbWF0ZS5iYWNvbiA9IGJhY29uOjplcyhiYyksDQogICAgU3RkRXJyLmJhY29uID0gYmFjb246OnNlKGJjKSwNCiAgICBwVmFsdWUuYmFjb24gPSBwdmFsKGJjKSwNCiAgICBmZHIuYmFjb24gPSBwLmFkanVzdChwdmFsKGJjKSwgbWV0aG9kID0gImZkciIpLA0KICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRQ0KICApDQogIGRhdGEud2l0aC5pbmZsYXRpb24gPC0gZGF0YS53aXRoLmluZmxhdGlvbiAlPiUgc2VsZWN0KC1jKHp2YWx1ZSwgY2hpc3EpKQ0KICByZXR1cm4oDQogICAgbGlzdCgiZGF0YS53aXRoLmluZmxhdGlvbiIgPSBkYXRhLndpdGguaW5mbGF0aW9uLCANCiAgICAgICAgICAiaW5mbGF0aW9uRmFjdG9yIiA9ICAgaW5mbGF0aW9uRmFjdG9yLA0KICAgICAgICAgICJlc3RpbWF0ZWRJbmZsYXRpb24iID0gaW5mbGF0aW9uKGJjKQ0KICAgICAgICAgKQ0KICAgICkNCn0NCiAgDQpgYGANCg0KIyMgR0FTUEFST05JDQoNCmBgYHtSLCBpbmNsdWRlID0gRkFMU0V9DQpyZXMgPC0gcmVhZC5jc3YoDQogICAgZmlsZS5wYXRoKGRpci5nYXNwYXJvbmksICJHYXNwYXJvbmlfc2luZ2xlX2NwZ19wVmFsX2RmLmNzdiIpDQopDQpgYGANCg0KYGBge1J9DQplc3QuaW5mbGF0aW9uIDwtIGVzdGltYXRpb25fb2ZfaW5mbGF0aW9uKHJlcykNCnJlcy53aXRoLmluZmxhdGlvbiA8LSBlc3QuaW5mbGF0aW9uJGRhdGEud2l0aC5pbmZsYXRpb24NCg0KDQpjb2hvcnQgPC0gIkdBU1BBUk9OSSINCndyaXRlLmNzdigNCiAgICByZXMud2l0aC5pbmZsYXRpb24sDQogICAgZmlsZS5wYXRoKGRpci5kYXRhLCBjb2hvcnQsICJzaW5nbGVfY3BnX3BWYWxfZGYuY3N2IiksDQogICAgcm93Lm5hbWVzID0gRkFMU0UNCikNCg0KIyBnZW5vbWUtd2lkZSBzaWcgY3Bncw0Kc2lnLmZkciA8LSBpZmVsc2UocmVzLndpdGguaW5mbGF0aW9uJGZkci5iYWNvbiA8IDAuMDUsIDEsIDApDQojIHRhYmxlKHNpZy5mZHIpICAgIyAyIHNpZw0KDQpgYGANCg0KYGBge1IsIGluY2x1ZGUgPSBGQUxTRSwgZXZhbD1GQUxTRX0NCiMjIyA1LiBQbG90cw0KcFZhbHVlIDwtIGRhdGEuZnJhbWUoDQogIHBWYWx1ZSA9IHJlcy53aXRoLmluZmxhdGlvbiRwVmFsdWUsDQogIHR5cGUgPSAicFZhbHVlIiwNCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEYpDQoNCnBWYWx1ZS5iYWNvbiA8LSBkYXRhLmZyYW1lKA0KICBwVmFsdWUgPSByZXMud2l0aC5pbmZsYXRpb24kcFZhbHVlLmJhY29uLA0KICB0eXBlID0gInBWYWx1ZS5iYWNvbiIsDQogIHN0cmluZ3NBc0ZhY3RvcnMgPSBGKQ0KcGxvdF9kZiA8LSByYmluZChwVmFsdWUsIHBWYWx1ZS5iYWNvbikNCg0KDQpoaXN0Lmdhc3Bhcm9uaSA8LSBnZ3Bsb3QocGxvdF9kZiwgYWVzKHBWYWx1ZSwgZmlsbCA9IHR5cGUpKSArDQogIGdlb21faGlzdG9ncmFtKGFscGhhID0gMC4zLCBwb3NpdGlvbiA9ICJpZGVudGl0eSIpICsNCiAgbGFicyh0aXRsZSA9IHBhc3RlMCgiSGlzdG9ncmFtIG9mIHB2YWx1ZXMgaW4gIiwgY29ob3J0LCAiIGNvaG9ydCIpKSArDQogIHRoZW1lX2J3KCkNCg0KIyBwZGYocGFzdGUwKGRpci5maWcsICIvIiwgY29ob3J0LCAiX3B2YWxIaXN0LnBkZiIpKQ0KaGlzdC5nYXNwYXJvbmkNCiMgZGV2Lm9mZigpDQoNCnFxUGxvdChyZXMud2l0aC5pbmZsYXRpb24kcFZhbHVlLCBjaSA9IFRSVUUsIG1haW4gPSBwYXN0ZTAoY29ob3J0LCAiIGNvaG9ydCIpKSArDQp0ZXh0KA0KICB4ID0gMC41LCANCiAgeSA9IDYuMiwNCiAgbGFiZWxzID0gYnF1b3RlKGxhbWJkYSA9PSAuKGZvcm1hdChlc3QuaW5mbGF0aW9uJGluZmxhdGlvbkZhY3RvcixkaWdpdHMgPSA0KSkpLA0KICBwb3MgPSA0DQopICsNCnRleHQoDQogIHggPSAwLjUsIA0KICB5ID0gNS40LA0KIGxhYmVscyA9IGJxdW90ZShsYW1iZGFbYmFjb25dID09IC4oZm9ybWF0KGVzdC5pbmZsYXRpb24kZXN0aW1hdGVkSW5mbGF0aW9uLGRpZ2l0cyA9IDQpKSksDQogIHBvcyA9IDQNCikNCnFxcGxvdC5nYXNwYXJvbmkgPC0gcmVjb3JkUGxvdCgpDQoNCnBkZihwYXN0ZTAoZGlyLmZpZywgIi8iLCBjb2hvcnQsICJfcXFQbG90cy5wZGYiKSkNCnFxcGxvdC5nYXNwYXJvbmkNCmRldi5vZmYoKQ0KYGBgDQoNCiMjIExPTkRPTg0KDQpgYGB7UiwgaW5jbHVkZSA9IEZBTFNFfQ0KcmVzIDwtIHJlYWQuY3N2KA0KICAgIGZpbGUucGF0aChkaXIubG9uZG9uLCAiTG9uZG9uX1BGQ19zaW5nbGVfY3BnX3BWYWxfZGYuY3N2IikNCikNCmBgYA0KDQpgYGB7Un0NCmVzdC5pbmZsYXRpb24gPC0gZXN0aW1hdGlvbl9vZl9pbmZsYXRpb24ocmVzKQ0KcmVzLndpdGguaW5mbGF0aW9uIDwtIGVzdC5pbmZsYXRpb24kZGF0YS53aXRoLmluZmxhdGlvbg0KDQpjb2hvcnQgPC0gIkxPTkRPTiINCg0Kd3JpdGUuY3N2KA0KICAgIHJlcy53aXRoLmluZmxhdGlvbiwNCiAgICBmaWxlLnBhdGgoZGlyLmRhdGEsIGNvaG9ydCwgInNpbmdsZV9jcGdfcFZhbF9kZi5jc3YiKSwNCiAgICByb3cubmFtZXMgPSBGQUxTRQ0KKQ0KDQojIGdlbm9tZS13aWRlIHNpZyBjcGdzDQpzaWcuZmRyIDwtIGlmZWxzZShyZXMud2l0aC5pbmZsYXRpb24kZmRyLmJhY29uIDwgMC4wNSwgMSwgMCkNCiMgdGFibGUoc2lnLmZkcikgICAjIDExIHNpZw0KDQpgYGANCg0KYGBge1IsaW5jbHVkZSA9IEZBTFNFLCBldmFsPUZBTFNFfQ0KIyMjIDUuIFBsb3RzDQpwVmFsdWUgPC0gZGF0YS5mcmFtZSgNCiAgcFZhbHVlID0gcmVzLndpdGguaW5mbGF0aW9uJHBWYWx1ZSwNCiAgdHlwZSA9ICJwVmFsdWUiLA0KICBzdHJpbmdzQXNGYWN0b3JzID0gRikNCg0KcFZhbHVlLmJhY29uIDwtIGRhdGEuZnJhbWUoDQogIHBWYWx1ZSA9IHJlcy53aXRoLmluZmxhdGlvbiRwVmFsdWUuYmFjb24sDQogIHR5cGUgPSAicFZhbHVlLmJhY29uIiwNCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEYpDQpwbG90X2RmIDwtIHJiaW5kKHBWYWx1ZSwgcFZhbHVlLmJhY29uKQ0KDQpoaXN0LmxvbmRvbiA8LSBnZ3Bsb3QocGxvdF9kZiwgYWVzKHBWYWx1ZSwgZmlsbCA9IHR5cGUpKSArDQogIGdlb21faGlzdG9ncmFtKGFscGhhID0gMC4zLHBvc2l0aW9uPSJpZGVudGl0eSIpICsNCiAgbGFicyh0aXRsZSA9IHBhc3RlMCgiSGlzdG9ncmFtIG9mIHB2YWx1ZXMgaW4gIiwgY29ob3J0LCAiIGNvaG9ydCIpKSArDQogIHRoZW1lX2J3KCkNCg0KIyBwZGYocGFzdGUwKGRpci5maWcsICIvIiwgY29ob3J0LCAiX3B2YWxIaXN0LnBkZiIpKQ0KaGlzdC5sb25kb24NCiNkZXYub2ZmKCkNCg0KDQpwIDwtIGdncGxvdChyZXMud2l0aC5pbmZsYXRpb24sIGFlcyhzYW1wbGUgPSBwVmFsdWUpKQ0KcCArIHN0YXRfcXEoKSArIHN0YXRfcXFfbGluZSgpDQoNCnFxUGxvdChyZXMud2l0aC5pbmZsYXRpb24kcFZhbHVlLCBjaSA9IFRSVUUsIG1haW4gPSBwYXN0ZTAoY29ob3J0LCAiIGNvaG9ydCIpKSArDQp0ZXh0KA0KICB4ID0gMC41LCANCiAgeSA9IDcuNSwNCiAgbGFiZWxzID0gYnF1b3RlKGxhbWJkYSA9PSAuKGZvcm1hdChlc3QuaW5mbGF0aW9uJGluZmxhdGlvbkZhY3RvcixkaWdpdHMgPSA0KSkpLA0KICBwb3MgPSA0DQopICsgdGV4dCgNCiAgeCA9IDAuNSwgDQogIHkgPSA2LjUsDQogbGFiZWxzID0gYnF1b3RlKGxhbWJkYVtiYWNvbl0gPT0gLihmb3JtYXQoZXN0LmluZmxhdGlvbiRlc3RpbWF0ZWRJbmZsYXRpb24sZGlnaXRzID0gNCkpKSwNCiAgcG9zID0gNA0KKQ0KcXFwbG90LmxvbmRvbiA8LSByZWNvcmRQbG90KCkNCg0KIyBTYXZlDQpwZGYocGFzdGUwKGRpci5maWcsICIvIiwgY29ob3J0LCAiX3FxUGxvdHMucGRmIikpDQpxcXBsb3QubG9uZG9uDQpkZXYub2ZmKCkNCmBgYA0KDQojIyBNVFNJTkFJDQoNCmBgYHtSLCBpbmNsdWRlID0gRkFMU0V9DQpyZXMgPC0gcmVhZC5jc3YoDQogICAgZmlsZS5wYXRoKGRpci5tdHNpbmFpLCAiTXRTaW5haV9zaW5nbGVfY3BnX3BWYWxfZGYuY3N2IikNCikNCmBgYA0KDQpgYGB7Un0NCmVzdC5pbmZsYXRpb24gPC0gZXN0aW1hdGlvbl9vZl9pbmZsYXRpb24ocmVzKQ0KcmVzLndpdGguaW5mbGF0aW9uIDwtIGVzdC5pbmZsYXRpb24kZGF0YS53aXRoLmluZmxhdGlvbg0KDQpjb2hvcnQgPC0gIk1UU0lOQUkiDQoNCndyaXRlLmNzdigNCiAgICByZXMud2l0aC5pbmZsYXRpb24sDQogICAgZmlsZS5wYXRoKGRpci5kYXRhLCBjb2hvcnQsICJzaW5nbGVfY3BnX3BWYWxfZGYuY3N2IiksDQogICAgcm93Lm5hbWVzID0gRkFMU0UNCikNCg0KIyBnZW5vbWUtd2lkZSBzaWcgY3Bncw0Kc2lnLmZkciA8LSBpZmVsc2UocmVzLndpdGguaW5mbGF0aW9uJGZkci5iYWNvbiA8IDAuMDUsIDEsIDApDQojIHRhYmxlKHNpZy5mZHIpICAgIyAwIHNpZw0KDQpgYGANCg0KYGBge1IsaW5jbHVkZSA9IEZBTFNFLCBldmFsPUZBTFNFfQ0KIyMjIDUuIFBsb3RzDQpwVmFsdWUgPC0gZGF0YS5mcmFtZSgNCiAgcFZhbHVlID0gcmVzLndpdGguaW5mbGF0aW9uJHBWYWx1ZSwNCiAgdHlwZSA9ICJwVmFsdWUiLA0KICBzdHJpbmdzQXNGYWN0b3JzID0gRikNCg0KcFZhbHVlLmJhY29uIDwtIGRhdGEuZnJhbWUoDQogIHBWYWx1ZSA9IHJlcy53aXRoLmluZmxhdGlvbiRwVmFsdWUuYmFjb24sDQogIHR5cGUgPSAicFZhbHVlLmJhY29uIiwNCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEYpDQpwbG90X2RmIDwtIHJiaW5kKHBWYWx1ZSwgcFZhbHVlLmJhY29uKQ0KDQoNCmhpc3QubXRzaW5haSA8LSBnZ3Bsb3QocGxvdF9kZiwgYWVzKHBWYWx1ZSwgZmlsbCA9IHR5cGUpKSArDQogIGdlb21faGlzdG9ncmFtKGFscGhhID0gMC4zLCBwb3NpdGlvbiA9ICJpZGVudGl0eSIpICsNCiAgbGFicyh0aXRsZSA9IHBhc3RlMCgiSGlzdG9ncmFtIG9mIHB2YWx1ZXMgaW4gIiwgY29ob3J0LCAiIGNvaG9ydCIpKSArDQogIHRoZW1lX2J3KCkNCg0KIyBwZGYocGFzdGUwKGRpci5maWcsICIvIiwgY29ob3J0LCAiX3B2YWxIaXN0LnBkZiIpKQ0KaGlzdC5tdHNpbmFpDQojIGRldi5vZmYoKQ0KDQoNCnFxUGxvdChyZXMud2l0aC5pbmZsYXRpb24kcFZhbHVlLCBjaSA9IFRSVUUsIG1haW4gPSBwYXN0ZTAoY29ob3J0LCAiIGNvaG9ydCIpKSArDQp0ZXh0KA0KICB4ID0gMC41LCANCiAgeSA9IDYuMiwNCiAgbGFiZWxzID0gYnF1b3RlKGxhbWJkYSA9PSAuKGZvcm1hdChlc3QuaW5mbGF0aW9uJGluZmxhdGlvbkZhY3RvcixkaWdpdHMgPSA0KSkpLA0KICBwb3MgPSA0DQopICsgdGV4dCgNCiAgeCA9IDAuNSwgDQogIHkgPSA1LjQsDQogbGFiZWxzID0gYnF1b3RlKGxhbWJkYVtiYWNvbl0gPT0gLihmb3JtYXQoZXN0LmluZmxhdGlvbiRlc3RpbWF0ZWRJbmZsYXRpb24sZGlnaXRzID0gNCkpKSwNCiAgcG9zID0gNA0KKQ0KcXFQbG90Lm10c2luYWkgPC0gcmVjb3JkUGxvdCgpDQoNCnBkZihwYXN0ZTAoZGlyLmZpZywgIi8iLCBjb2hvcnQsICJfcXFQbG90cy5wZGYiKSkNCnFxUGxvdC5tdHNpbmFpDQpkZXYub2ZmKCkNCmBgYA0KDQojIyBST1NNQVANCg0KYGBge1IsIGluY2x1ZGUgPSBGQUxTRX0NCnJlcyA8LSByZWFkLmNzdigNCiAgICBmaWxlLnBhdGgoZGlyLnJvc21hcCwgIlJPU01BUF9QRkNfc2luZ2xlX2NwZ19wVmFsX2RmLmNzdiIpDQopDQpgYGANCg0KYGBge1Igcm9zbWFwfQ0KZXN0LmluZmxhdGlvbiA8LSBlc3RpbWF0aW9uX29mX2luZmxhdGlvbihyZXMpDQpyZXMud2l0aC5pbmZsYXRpb24gPC0gZXN0LmluZmxhdGlvbiRkYXRhLndpdGguaW5mbGF0aW9uDQoNCmNvaG9ydCA8LSAiUk9TTUFQIg0KDQp3cml0ZS5jc3YoDQogICAgcmVzLndpdGguaW5mbGF0aW9uLA0KICAgIGZpbGUucGF0aChkaXIuZGF0YSwgY29ob3J0LCAic2luZ2xlX2NwZ19wVmFsX2RmLmNzdiIpLA0KICAgIHJvdy5uYW1lcyA9IEZBTFNFDQopDQoNCiMgZ2Vub21lLXdpZGUgc2lnIGNwZ3MNCnNpZy5mZHIgPC0gaWZlbHNlKHJlcy53aXRoLmluZmxhdGlvbiRmZHIuYmFjb24gPCAwLjA1LCAxLCAwKQ0KIyB0YWJsZShzaWcuZmRyKSAgICMgMzQgc2lnDQpgYGANCg0KYGBge1IsaW5jbHVkZSA9IEZBTFNFLCBldmFsPUZBTFNFfQ0KIyMjIDUuIFBsb3RzDQpwVmFsdWUgPC0gZGF0YS5mcmFtZSgNCiAgcFZhbHVlID0gcmVzLndpdGguaW5mbGF0aW9uJHBWYWx1ZSwNCiAgdHlwZSA9ICJwVmFsdWUiLA0KICBzdHJpbmdzQXNGYWN0b3JzID0gRikNCg0KcFZhbHVlLmJhY29uIDwtIGRhdGEuZnJhbWUoDQogIHBWYWx1ZSA9IHJlcy53aXRoLmluZmxhdGlvbiRwVmFsdWUuYmFjb24sDQogIHR5cGUgPSAicFZhbHVlLmJhY29uIiwNCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEYpDQoNCnBsb3RfZGYgPC0gcmJpbmQocFZhbHVlLCBwVmFsdWUuYmFjb24pDQoNCmhpc3Qucm9zbWFwIDwtIGdncGxvdChwbG90X2RmLCBhZXMocFZhbHVlLCBmaWxsID0gdHlwZSkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYWxwaGEgPSAwLjMscG9zaXRpb249ImlkZW50aXR5IikgKw0KICBsYWJzKHRpdGxlID0gcGFzdGUwKCJIaXN0b2dyYW0gb2YgcHZhbHVlcyBpbiAiLCBjb2hvcnQsICIgY29ob3J0IikpICsNCiAgdGhlbWVfYncoKQ0KDQojIHBkZihwYXN0ZTAoZGlyLmZpZywgIi8iLCBjb2hvcnQsICJfcHZhbEhpc3QucGRmIikpDQpoaXN0LnJvc21hcA0KIyBkZXYub2ZmKCkNCg0KDQpxcVBsb3QocmVzLndpdGguaW5mbGF0aW9uJHBWYWx1ZSwgY2kgPSBUUlVFLCBtYWluID0gcGFzdGUwKGNvaG9ydCwgIiBjb2hvcnQiKSkgKw0KdGV4dCgNCiAgeCA9IDAuNSwgDQogIHkgPSA5LA0KICBsYWJlbHMgPSBicXVvdGUobGFtYmRhID09IC4oZm9ybWF0KGVzdC5pbmZsYXRpb24kaW5mbGF0aW9uRmFjdG9yLGRpZ2l0cyA9IDQpKSksDQogIHBvcyA9IDQNCikgKyB0ZXh0KA0KICB4ID0gMC41LA0KICB5ID0gOCwNCiAgbGFiZWxzID0gYnF1b3RlKGxhbWJkYVtiYWNvbl0gPT0gLihmb3JtYXQoZXN0LmluZmxhdGlvbiRlc3RpbWF0ZWRJbmZsYXRpb24sZGlnaXRzID0gNCkpKSwNCiAgcG9zID0gNA0KKQ0KcXFQbG90LnJvc21hcCA8LSByZWNvcmRQbG90KCkNCg0KcGRmKHBhc3RlMChkaXIuZmlnLCAiLyIsIGNvaG9ydCwgIl9xcVBsb3RzLnBkZiIpKQ0KcXFQbG90LnJvc21hcA0KZGV2Lm9mZigpDQpgYGANCg0KDQpgYGB7UiBzaW5nbGVfY3BnX21ldGEsIGluY2x1ZGUgPSBGQUxTRSwgZXZhbCA9IEZBTFNFfQ0KIyMgU2luZ2xlLWNwZyBtZXRhDQpyZXMgPC0gcmVhZC5jc3YoDQogICAgZmlsZS5wYXRoKGRpci5tZXRhLnNpbmdsZS5jcGcsICJtZXRhX2FuYWx5c2lzX3NpbmdsZV9jcGdfZGYuY3N2IikNCikNCmBgYA0KDQpgYGB7UiwgaW5jbHVkZSA9IEZBTFNFLCBldmFsID0gRkFMU0V9DQplc3QuaW5mbGF0aW9uIDwtIGVzdGltYXRpb25fb2ZfaW5mbGF0aW9uKHJlcykNCnJlcy53aXRoLmluZmxhdGlvbiA8LSBlc3QuaW5mbGF0aW9uJGRhdGEud2l0aC5pbmZsYXRpb24NCg0KcmVzLndpdGguaW5mbGF0aW9uIDwtIHJlcy53aXRoLmluZmxhdGlvblsNCiAgICAsYyhncmVwKCJHQVNQQVJPTkl8TVRTSU5BSXxMT05ET058Uk9TTUFQIiwgY29sbmFtZXMocmVzLndpdGguaW5mbGF0aW9uKSwgaWdub3JlLmNhc2UgPSBULCBpbnZlcnQgPSBUKSwNCiAgICAgICBncmVwKCJHQVNQQVJPTkl8TVRTSU5BSXxMT05ET058Uk9TTUFQIiwgY29sbmFtZXMocmVzLndpdGguaW5mbGF0aW9uKSwgaWdub3JlLmNhc2UgPSBULCBpbnZlcnQgPSBGKQ0KICAgICAgKV0NCndyaXRlLmNzdigNCiAgICByZXMud2l0aC5pbmZsYXRpb24sDQogICAgZmlsZS5wYXRoKGRpci5kYXRhLCAibWV0YV9hbmFseXNpc19zaW5nbGVfY3BnX2RmLmNzdiIpLA0KICAgIHJvdy5uYW1lcyA9IEZBTFNFDQopDQoNCiMgZ2Vub21lLXdpZGUgc2lnIGNwZ3MNCnNpZy5mZHIgPC0gaWZlbHNlKHJlcy53aXRoLmluZmxhdGlvbiRmZHIuYmFjb24gPCAwLjA1LCAxLCAwKQ0KIyB0YWJsZShzaWcuZmRyKSAgICMgMjQ1OSBzaWcNCmBgYA0KDQpgYGB7UiwgaW5jbHVkZSA9IEZBTFNFLCBldmFsID0gRkFMU0V9DQojIyMgNS4gUGxvdHMNCnBWYWx1ZSA8LSBkYXRhLmZyYW1lKA0KICBwVmFsdWUgPSByZXMud2l0aC5pbmZsYXRpb24kcFZhbC5maW5hbCwNCiAgdHlwZSA9ICJwVmFsdWUiLA0KICBzdHJpbmdzQXNGYWN0b3JzID0gRikNCg0KcFZhbHVlLmJhY29uIDwtIGRhdGEuZnJhbWUoDQogIHBWYWx1ZSA9IHJlcy53aXRoLmluZmxhdGlvbiRwVmFsLmZpbmFsLmJhY29uLA0KICB0eXBlID0gInBWYWx1ZS5iYWNvbiIsDQogIHN0cmluZ3NBc0ZhY3RvcnMgPSBGKQ0KcGxvdF9kZiA8LSByYmluZChwVmFsdWUsIHBWYWx1ZS5iYWNvbikNCg0KIyBwZGYoZmlsZS5wYXRoKGRpci5maWcsIm1ldGFfcHZhbEhpc3QucGRmIikpDQpnZ3Bsb3QocGxvdF9kZiwgYWVzKHBWYWx1ZSwgZmlsbCA9IHR5cGUpKSArDQogIGdlb21faGlzdG9ncmFtKGFscGhhID0gMC4zLHBvc2l0aW9uPSJpZGVudGl0eSIpICsNCiAgbGFicyh0aXRsZSA9ICJIaXN0b2dyYW0gb2YgcHZhbHVlcyBpbiBtZXRhIGFuYWx5c2lzIikgKw0KICB0aGVtZV9idygpDQojIGRldi5vZmYoKQ0KDQoNCnFxcGxvdC5tZXRhIDwtIHFxUGxvdChyZXMud2l0aC5pbmZsYXRpb24kcFZhbC5maW5hbCwgY2kgPSBUUlVFLCBtYWluID0gIk1ldGEgYW5hbHlzaXMiKSArDQp0ZXh0KA0KICB4ID0gMC41LCANCiAgeSA9IDE1LA0KICBsYWJlbHMgPSBicXVvdGUobGFtYmRhID09IC4oZm9ybWF0KGVzdC5pbmZsYXRpb24kaW5mbGF0aW9uRmFjdG9yLGRpZ2l0cyA9IDQpKSksDQogIHBvcyA9IDQNCikgKyB0ZXh0KA0KICB4ID0gMC41LA0KICB5ID0gMTQsDQogbGFiZWxzID0gYnF1b3RlKGxhbWJkYVtiYWNvbl0gPT0gLihmb3JtYXQoZXN0LmluZmxhdGlvbiRlc3RpbWF0ZWRJbmZsYXRpb24sZGlnaXRzID0gNCkpKSwNCiAgcG9zID0gNA0KKQ0KcXFwbG90Lm1ldGEgPC0gcmVjb3JkUGxvdCgpDQpgYGANCg0KYGBge1IsIGV2YWwgPSBGQUxTRSwgaW5jbHVkZSA9IEZBTFNFfQ0KcGRmKGZpbGUucGF0aChkaXIuZmlnLCJtZXRhX3FxUGxvdHMucGRmIikpDQpxcXBsb3QubWV0YQ0KZGV2Lm9mZigpDQpgYGANCg0KDQpgYGB7UiBmaW5hbF9wbG90LCBpbmNsdWRlID0gRkFMU0UsIGV2YWwgPSBGQUxTRX0NCmxpYnJhcnkoY293cGxvdCkNCnNhdmUocXFQbG90LnJvc21hcCxxcXBsb3QuZ2FzcGFyb25pLHFxcGxvdC5sb25kb24scXFQbG90Lm10c2luYWksZmlsZSA9ICJxcXBsb3RzLnJkYSIpDQpwZGYoIlN1cHBsZW1lbnRhcnlfRmlndXJlXzEucGRmIix3aWR0aCA9IDksIGhlaWdodCA9IDkpDQpwbG90X2dyaWQocXFwbG90Lmdhc3Bhcm9uaSwgcXFwbG90LmxvbmRvbixxcVBsb3QubXRzaW5haSwgcXFQbG90LnJvc21hcCwgbmNvbCA9IDIsbnJvdyA9IDIsc2NhbGUgPSAwLjgpDQpkZXYub2ZmKCkNCmBgYA0KDQojIFNlc3Npb24gaW5mb3JtYXRpb24NCmBgYHtSfQ0KZGV2dG9vbHM6OnNlc3Npb25faW5mbygpDQpgYGA=