Stat: Beta Diversity Visualisation(phyloseq_beta_diversity.py v5.1.0)

## Import packages
library(phyloseq)
library(ggplot2)
library(gridExtra)
library(reshape2)
source(file.path(params$libdir, "graphical_methods.R"))
## Alternative to source all extra function from a github repo
## source("https://raw.githubusercontent.com/mahendra-mariadassou/phyloseq-extended/master/load-extra-functions.R")

## Setting variables
  ## The Phyloseq object (format rdata)
  # phyloseq <- ""

  ## The experiment variable that you want to analyse
  # varExp <- ""

  ## The methods of beta diversity you want to compute
  ## to see all available distance methods, type distanceMethodList
  ## The most common one are : cc for Jaccard, bray for Bray-Curtis, unifrac and wunifrac for Unifrac and weighted Unifrac
  ## N.B. if the tree is not available in your RData, you cannot choose Unifrac or Weighted Unifrac
  ## You may precise multiple distance by separating them by a comma
  # methods <- ""

## Create input and parameters dataframe
  # params <- data.frame( "phyloseq" = phylose, "varExp" = varExp, "methods" = methods)

## Load data
  ## the phyloseq object
load(params$phyloseq) 

## store methods in list
methods <- as.list(strsplit(params$methods, ",")[[1]])

## Order samples according to grouping variable
sampleOrder <- levels(reorder(sample_names(data), as.numeric(get_variable(data, params$varExp)))) 

Distance as heatmap plot(s)

for (method in methods){
  dist.a <- distance(data, method = method)
  a <- as.matrix(dist.a)
  write.table(a, paste(sep="", method, ".tsv"), sep="\t", quote=FALSE, col.names=NA)
  pa <- plot_dist_as_heatmap(dist.a, order = sampleOrder, title = paste("Heatmap plot of the beta distance :",method)) + 
    theme(plot.title = element_text(hjust = 0.5))
  plot(pa)
}

Reproducibility token

sessioninfo::session_info()
─ Session info ───────────────────────────────────────────────────────────────
 setting  value
 version  R version 4.1.2 (2021-11-01)
 os       Ubuntu 24.04.2 LTS
 system   x86_64, linux-gnu
 ui       X11
 language fr_FR:en
 collate  en_US.utf8
 ctype    en_US.utf8
 tz       Europe/Paris
 date     2026-01-14
 pandoc   2.19.2 @ /home/maria/miniforge3/envs/frogs@5.1.0/bin/ (via rmarkdown)

─ Packages ───────────────────────────────────────────────────────────────────
 package          * version   date (UTC) lib source
 ade4               1.7-22    2023-02-06 [1] CRAN (R 4.1.3)
 ape                5.7-1     2023-03-13 [1] CRAN (R 4.1.3)
 Biobase            2.54.0    2021-10-26 [1] Bioconductor
 BiocGenerics       0.40.0    2021-10-26 [1] Bioconductor
 biomformat         1.22.0    2021-10-26 [1] Bioconductor
 Biostrings         2.62.0    2021-10-26 [1] Bioconductor
 bitops             1.0-7     2021-04-24 [1] CRAN (R 4.1.3)
 bslib              0.5.0     2023-06-09 [1] CRAN (R 4.1.3)
 cachem             1.0.8     2023-05-01 [1] CRAN (R 4.1.3)
 cli                3.6.1     2023-03-23 [1] CRAN (R 4.1.3)
 cluster            2.1.4     2022-08-22 [1] CRAN (R 4.1.3)
 codetools          0.2-19    2023-02-01 [1] CRAN (R 4.1.3)
 colorspace         2.1-0     2023-01-23 [1] CRAN (R 4.1.3)
 crayon             1.5.2     2022-09-29 [1] CRAN (R 4.1.3)
 data.table         1.14.8    2023-02-17 [1] CRAN (R 4.1.3)
 digest             0.6.31    2022-12-11 [1] CRAN (R 4.1.3)
 dplyr              1.1.2     2023-04-20 [1] CRAN (R 4.1.3)
 evaluate           0.21      2023-05-05 [1] CRAN (R 4.1.3)
 fansi              1.0.4     2023-01-22 [1] CRAN (R 4.1.3)
 farver             2.1.1     2022-07-06 [1] CRAN (R 4.1.3)
 fastmap            1.1.1     2023-02-24 [1] CRAN (R 4.1.3)
 foreach            1.5.2     2022-02-02 [1] CRAN (R 4.1.3)
 generics           0.1.3     2022-07-05 [1] CRAN (R 4.1.3)
 GenomeInfoDb       1.30.1    2022-01-30 [1] Bioconductor
 GenomeInfoDbData   1.2.7     2026-01-14 [1] Bioconductor
 ggplot2          * 3.4.2     2023-04-03 [1] CRAN (R 4.1.3)
 glue               1.6.2     2022-02-24 [1] CRAN (R 4.1.3)
 gridExtra        * 2.3       2017-09-09 [1] CRAN (R 4.1.3)
 gtable             0.3.3     2023-03-21 [1] CRAN (R 4.1.3)
 highr              0.10      2022-12-22 [1] CRAN (R 4.1.3)
 htmltools          0.5.5     2023-03-23 [1] CRAN (R 4.1.3)
 igraph             1.3.5     2022-09-22 [1] CRAN (R 4.1.3)
 IRanges            2.28.0    2021-10-26 [1] Bioconductor
 iterators          1.0.14    2022-02-05 [1] CRAN (R 4.1.3)
 jquerylib          0.1.4     2021-04-26 [1] CRAN (R 4.1.3)
 jsonlite           1.8.5     2023-06-05 [1] CRAN (R 4.1.3)
 knitr              1.43      2023-05-25 [1] CRAN (R 4.1.3)
 labeling           0.4.2     2020-10-20 [1] CRAN (R 4.1.3)
 lattice            0.21-8    2023-04-05 [1] CRAN (R 4.1.3)
 lifecycle          1.0.3     2022-10-07 [1] CRAN (R 4.1.3)
 magrittr           2.0.3     2022-03-30 [1] CRAN (R 4.1.3)
 MASS               7.3-58.3  2023-03-07 [1] CRAN (R 4.1.3)
 Matrix             1.5-4.1   2023-05-18 [1] CRAN (R 4.1.3)
 mgcv               1.8-42    2023-03-02 [1] CRAN (R 4.1.3)
 multtest           2.50.0    2021-10-26 [1] Bioconductor
 munsell            0.5.0     2018-06-12 [1] CRAN (R 4.1.3)
 nlme               3.1-162   2023-01-31 [1] CRAN (R 4.1.3)
 permute            0.9-7     2022-01-27 [1] CRAN (R 4.1.3)
 phyloseq         * 1.38.0    2021-10-26 [1] Bioconductor
 pillar             1.9.0     2023-03-22 [1] CRAN (R 4.1.3)
 pkgconfig          2.0.3     2019-09-22 [1] CRAN (R 4.1.3)
 plyr               1.8.8     2022-11-11 [1] CRAN (R 4.1.3)
 R6                 2.5.1     2021-08-19 [1] CRAN (R 4.1.3)
 Rcpp               1.0.10    2023-01-22 [1] CRAN (R 4.1.3)
 RCurl              1.98-1.12 2023-03-27 [1] CRAN (R 4.1.3)
 reshape2         * 1.4.4     2020-04-09 [1] CRAN (R 4.1.3)
 rhdf5              2.38.1    2022-03-10 [1] Bioconductor
 rhdf5filters       1.6.0     2021-10-26 [1] Bioconductor
 Rhdf5lib           1.16.0    2021-10-26 [1] Bioconductor
 rlang              1.1.1     2023-04-28 [1] CRAN (R 4.1.3)
 rmarkdown          2.22      2023-06-01 [1] CRAN (R 4.1.3)
 rstudioapi         0.14      2022-08-22 [1] CRAN (R 4.1.3)
 S4Vectors          0.32.4    2022-03-24 [1] Bioconductor
 sass               0.4.6     2023-05-03 [1] CRAN (R 4.1.3)
 scales           * 1.2.1     2022-08-20 [1] CRAN (R 4.1.3)
 sessioninfo        1.2.2     2021-12-06 [1] CRAN (R 4.1.3)
 stringi            1.7.6     2021-11-29 [1] CRAN (R 4.1.1)
 stringr            1.5.0     2022-12-02 [1] CRAN (R 4.1.3)
 survival           3.5-5     2023-03-12 [1] CRAN (R 4.1.3)
 tibble             3.2.1     2023-03-20 [1] CRAN (R 4.1.3)
 tidyselect         1.2.0     2022-10-10 [1] CRAN (R 4.1.3)
 utf8               1.2.3     2023-01-31 [1] CRAN (R 4.1.3)
 vctrs              0.6.2     2023-04-19 [1] CRAN (R 4.1.3)
 vegan              2.6-4     2022-10-11 [1] CRAN (R 4.1.3)
 withr              2.5.0     2022-03-03 [1] CRAN (R 4.1.3)
 xfun               0.39      2023-04-20 [1] CRAN (R 4.1.3)
 XVector            0.34.0    2021-10-26 [1] Bioconductor
 yaml               2.3.7     2023-01-23 [1] CRAN (R 4.1.3)
 zlibbioc           1.40.0    2021-10-26 [1] Bioconductor

 [1] /home/maria/miniforge3/envs/frogs@5.1.0/lib/R/library

──────────────────────────────────────────────────────────────────────────────
LS0tCmNvcHlyaWdodDogIkNvcHlyaWdodCAoQykgMjAyNSBJTlJBRSIKbGljZW5zZTogIkdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIgpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6CiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKcGFyYW1zOgogICBwaHlsb3NlcToKICAgICAgdmFsdWU6IHgKICAgdmFyRXhwOgogICAgICB2YWx1ZTogeAogICBtZXRob2RzOgogICAgICB2YWx1ZTogeAogICBsaWJkaXI6CiAgICAgIHZhbHVlOiB4CiAgIHZlcnNpb246CiAgICAgIHZhbHVlOiB4CiAgIHRvb2w6CiAgICAgIHZhbHVlOiB4Ci0tLQoKPG1ldGEgaHR0cC1lcXVpdj0iQ29udGVudC1UeXBlIiBjb250ZW50PSJ0ZXh0L2h0bWw7IGNoYXJzZXQ9VVRGLTgiIC8+CjxtZXRhIG5hbWU9ImF1dGhvciIgY29udGVudD0iVGEgVGhpIE5nYW4gLSBTSUdFTkFFL0dBQkkgJiBNYXJpYSBCZXJuYXJkIC0gU0lHRU5BRS9HQUJJIiAvPgo8bWV0YSBuYW1lPSJ2ZXJzaW9uIiBjb250ZW50PSI1LjEuMCIgLz4KPG1ldGEgbmFtZT0iY29weXJpZ2h0IiBjb250ZW50PSJDb3B5cmlnaHQgKEMpIDIwMjUgSU5SQUUiIC8+CgoKYGBge3IsIGVjaG89RkFMU0UsIHJlc3VsdHM9ImFzaXMifQpDVVJSRU5UX0RJUiA8LSBrbml0cjo6b3B0c19rbml0JGdldCgib3V0cHV0LmRpciIpCmlmIChpcy5udWxsKENVUlJFTlRfRElSKSkgewogIENVUlJFTlRfRElSIDwtIGdldHdkKCkKfQpUSEVNRV9ESVIgPC0gbm9ybWFsaXplUGF0aCgKICBmaWxlLnBhdGgoZGlybmFtZShDVVJSRU5UX0RJUiksICJzdGF0aWMiKSwKICB3aW5zbGFzaCA9ICIvIiwKICBtdXN0V29yayA9IEZBTFNFCikKCmpzX3RoZW1lX2ZpbGUgPC0gbm9ybWFsaXplUGF0aCgKICBmaWxlLnBhdGgoVEhFTUVfRElSLCAianMiLCAidGhlbWUuanMiKSwKICB3aW5zbGFzaCA9ICIvIiwKICBtdXN0V29yayA9IEZBTFNFCikKCmxpbmVzIDwtIHJlYWRMaW5lcyhqc190aGVtZV9maWxlLCB3YXJuID0gRkFMU0UpCgpzZXAgPC0gd2hpY2goZ3JlcGwoIl4vLyMjIiwgdHJpbXdzKGxpbmVzKSkpCgppZiAobGVuZ3RoKHNlcCkgPCAyKSB7CiAgc3RvcCgiVGFnIG5vdCBmb3VuZCBpbiB0aGVtZS5qczogJy8vIyMnIikKfQoKanNfY29kZSA8LSBsaW5lc1soc2VwWzFdICsgMSk6KHNlcFsyXSAtIDEpXQoKY2F0KCI8c2NyaXB0PlxuIikKY2F0KGpzX2NvZGUsIHNlcCA9ICJcbiIpCmNhdCgiXG48L3NjcmlwdD4iKQpgYGAKCjxkaXYgc3R5bGU9ImRpc3BsYXk6ZmxleDsgYWxpZ24taXRlbXM6Y2VudGVyOyBnYXA6MTVweDsgbWFyZ2luLWJvdHRvbToyMHB4OyI+CiAgPGltZyBpZD0ibG9nbyIgc3JjPSJkYXRhOmltYWdlL3BuZztiYXNlNjQsIiBhbHQ9IkZST0dTIGxvZ28iIHN0eWxlPSJoZWlnaHQ6MTgwcHg7Ij4KICA8aDEgc3R5bGU9Im1hcmdpbjowOyI+U3RhdDogQmV0YSBEaXZlcnNpdHkgVmlzdWFsaXNhdGlvbjxpPjxzcGFuIGNsYXNzPSJ0ZXh0LWFjY2VudCI+KGByIHBhcmFtcyR0b29sYCB2YHIgcGFyYW1zJHZlcnNpb25gKTwvc3Bhbj48L2k+PC9oMT4KPC9kaXY+Cgo8c2NyaXB0PgoKJChmdW5jdGlvbiAoKSB7CiAgdXBkYXRlX2xvZ28oQ1VSUkVOVF9USEVNRSk7Cn0pOwoKCjwvc2NyaXB0PgoKPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KOnJvb3QgewoJCQktLWZyb2dzQ29sb3I6ICMwM0E1QTg7IAoJCQktLWZyb2dzQ29sb3JIb3ZlcjogaHNsKGZyb20gdmFyKC0tZnJvZ3NDb2xvcikgaCBjYWxjKHMgKyA0KSBjYWxjKGwgLSAzKSAvIDEpOwoJCQktLWZyb2dzUHJlQ29sb3I6IGhzbChmcm9tIHZhcigtLWZyb2dzQ29sb3IpIGggcyBsIC8gMC4xKTsKCQl9Ci50ZXh0LWFjY2VudCB7CiAgY29sb3I6ICM1OTVjNWY7Cn0KLm1haW4tY29udGFpbmVyewoJbWF4LXdpZHRoOiA3NSUgIWltcG9ydGFudDsKfQpoMXsKCWNvbG9yOiB2YXIoLS1mcm9nc0NvbG9yKTsKfQpoMnsKCWNvbG9yOiB2YXIoLS1mcm9nc0NvbG9yKTsKfQphIHsKCWNvbG9yOiB2YXIoLS1mcm9nc0NvbG9yKTsKfQphOmhvdmVyewoJY29sb3I6IHZhcigtLWZyb2dzQ29sb3JIb3Zlcik7Cn0KLm5hdi1waWxscyA+IGxpLmFjdGl2ZSA+IGEsIC5uYXYtcGlsbHMgPiBsaS5hY3RpdmUgPiBhOmZvY3VzewoJY29sb3I6ICNmZmY7CgliYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1mcm9nc0NvbG9yKTsKCWJvcmRlci1jb2xvcjogI2RlZTJlNiAjZGVlMmU2ICNmZmY7Cn0KLm5hdi1waWxscyA+IGxpLmFjdGl2ZSA+IGE6aG92ZXIgewoJYmFja2dyb3VuZC1jb2xvcjogdmFyKC0tZnJvZ3NDb2xvckhvdmVyKTsKfQouYnV0dG9uIHsKICAgIGJhY2tncm91bmQtY29sb3I6IHZhcigtLWZyb2dzQnV0dG9uQ29sb3IpIDsKICAgIGJvcmRlciAgICAgICAgICA6IG5vbmU7CiAgICBjb2xvciAgICAgICAgICAgOiB3aGl0ZTsKICAgIHBhZGRpbmcgICAgICAgICA6IDVweCAxMHB4OwogICAgdGV4dC1hbGlnbiAgICAgIDogY2VudGVyOwogICAgdGV4dC1kZWNvcmF0aW9uIDogbm9uZTsKICAgIGRpc3BsYXkgICAgICAgICA6IGlubGluZS1ibG9jazsKICAgIGZvbnQtc2l6ZSAgICAgICA6IDEycHg7CiAgICBtYXJnaW4gICAgICAgICAgOiA0cHggMnB4OwogICAgY3Vyc29yICAgICAgICAgIDogcG9pbnRlcjsKICAgIGJvcmRlci1yYWRpdXMgICA6IDhweDsKfQpoNCB7IAogICAgZGlzcGxheSAgICAgIDogYmxvY2s7CiAgICBmb250LXNpemUgICAgOiAxZW07CiAgICBtYXJnaW4tdG9wICAgOiAxLjMzZW07CiAgICBtYXJnaW4tYm90dG9tOiAxLjMzZW07CiAgICBtYXJnaW4tbGVmdCAgOiAwOwogICAgbWFyZ2luLXJpZ2h0IDogMDsKICAgIGZvbnQtd2VpZ2h0ICA6IGJvbGQ7CiAgICBjb2xvciAgICAgICAgOiB2YXIoLS1mcm9nc0NvbG9yKTsKfQpjb2RlLnJ7IC8qIENvZGUgYmxvY2sgKi8KICBmb250LXNpemU6IDExcHg7Cn0KcHJlewogIGZvbnQtc2l6ZTogMTFweCA7CiAgYmFja2dyb3VuZC1jb2xvcjogdmFyKC0tZnJvZ3NQcmVDb2xvcikgIWltcG9ydGFudDsKfQouZnJvZ3N2ZXJzaW9uewoJcG9zaXRpb246IGFic29sdXRlOwoJcmlnaHQ6IDUlOwoJY29sb3I6IHZhcigtLWZyb2dzQ29sb3IpOwoJZm9udC1zdHlsZTogaXRhbGljOwoJZm9udC1zaXplOiBzbWFsbGVyOwoJcGFkZGluZzo4cHg7Cn0KLmZyb2dzdmVyc2lvbiA+IGF7Cglib3JkZXI6IG5vbmUgIWltcG9ydGFudDsKCWRpc3BsYXk6IGlubGluZS1ibG9jazsKfQojdGhlbWVjaG9pY2V7CiAgYm9yZGVyLXJhZGl1czogMC4yNWVtOwogIGJhY2tncm91bmQtY29sb3I6IHdoaXRlOwogIGJvcmRlcjogMXB4IHNvbGlkICNkZWUyZTY7CiAgZm9udC13ZWlnaHQ6IDQwMDsKICBsaW5lLWhlaWdodDogMS41OwogIHBhZGRpbmc6IC4zNzVyZW0gMi4yNXJlbSAuMzc1cmVtIC43NXJlbTsKfQo8L3N0eWxlPgoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgZXJyb3IgPSBUUlVFKQpgYGAKCmBgYHtyIGltcG9ydCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KIyMgSW1wb3J0IHBhY2thZ2VzCmxpYnJhcnkocGh5bG9zZXEpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkocmVzaGFwZTIpCnNvdXJjZShmaWxlLnBhdGgocGFyYW1zJGxpYmRpciwgImdyYXBoaWNhbF9tZXRob2RzLlIiKSkKIyMgQWx0ZXJuYXRpdmUgdG8gc291cmNlIGFsbCBleHRyYSBmdW5jdGlvbiBmcm9tIGEgZ2l0aHViIHJlcG8KIyMgc291cmNlKCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vbWFoZW5kcmEtbWFyaWFkYXNzb3UvcGh5bG9zZXEtZXh0ZW5kZWQvbWFzdGVyL2xvYWQtZXh0cmEtZnVuY3Rpb25zLlIiKQoKIyMgU2V0dGluZyB2YXJpYWJsZXMKICAjIyBUaGUgUGh5bG9zZXEgb2JqZWN0IChmb3JtYXQgcmRhdGEpCiAgIyBwaHlsb3NlcSA8LSAiIgoKICAjIyBUaGUgZXhwZXJpbWVudCB2YXJpYWJsZSB0aGF0IHlvdSB3YW50IHRvIGFuYWx5c2UKICAjIHZhckV4cCA8LSAiIgoKICAjIyBUaGUgbWV0aG9kcyBvZiBiZXRhIGRpdmVyc2l0eSB5b3Ugd2FudCB0byBjb21wdXRlCiAgIyMgdG8gc2VlIGFsbCBhdmFpbGFibGUgZGlzdGFuY2UgbWV0aG9kcywgdHlwZSBkaXN0YW5jZU1ldGhvZExpc3QKICAjIyBUaGUgbW9zdCBjb21tb24gb25lIGFyZSA6IGNjIGZvciBKYWNjYXJkLCBicmF5IGZvciBCcmF5LUN1cnRpcywgdW5pZnJhYyBhbmQgd3VuaWZyYWMgZm9yIFVuaWZyYWMgYW5kIHdlaWdodGVkIFVuaWZyYWMKICAjIyBOLkIuIGlmIHRoZSB0cmVlIGlzIG5vdCBhdmFpbGFibGUgaW4geW91ciBSRGF0YSwgeW91IGNhbm5vdCBjaG9vc2UgVW5pZnJhYyBvciBXZWlnaHRlZCBVbmlmcmFjCiAgIyMgWW91IG1heSBwcmVjaXNlIG11bHRpcGxlIGRpc3RhbmNlIGJ5IHNlcGFyYXRpbmcgdGhlbSBieSBhIGNvbW1hCiAgIyBtZXRob2RzIDwtICIiCgojIyBDcmVhdGUgaW5wdXQgYW5kIHBhcmFtZXRlcnMgZGF0YWZyYW1lCiAgIyBwYXJhbXMgPC0gZGF0YS5mcmFtZSggInBoeWxvc2VxIiA9IHBoeWxvc2UsICJ2YXJFeHAiID0gdmFyRXhwLCAibWV0aG9kcyIgPSBtZXRob2RzKQoKIyMgTG9hZCBkYXRhCiAgIyMgdGhlIHBoeWxvc2VxIG9iamVjdApsb2FkKHBhcmFtcyRwaHlsb3NlcSkgCgojIyBzdG9yZSBtZXRob2RzIGluIGxpc3QKbWV0aG9kcyA8LSBhcy5saXN0KHN0cnNwbGl0KHBhcmFtcyRtZXRob2RzLCAiLCIpW1sxXV0pCgojIyBPcmRlciBzYW1wbGVzIGFjY29yZGluZyB0byBncm91cGluZyB2YXJpYWJsZQpzYW1wbGVPcmRlciA8LSBsZXZlbHMocmVvcmRlcihzYW1wbGVfbmFtZXMoZGF0YSksIGFzLm51bWVyaWMoZ2V0X3ZhcmlhYmxlKGRhdGEsIHBhcmFtcyR2YXJFeHApKSkpIApgYGAKCiMgey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHN9CgpgYGB7PWh0bWx9CjxkaXYgY2xhc3M9InJvdyI+CiAgPGRpdiBzdHlsZT0iZmxvYXQ6cmlnaHQiPgogIDxzZWxlY3QgaWQ9InRoZW1lY2hvaWNlIgogICAgICAgICAgY2xhc3M9ImZvcm0tc2VsZWN0IGZvcm0tc2VsZWN0LXNtIgogICAgICAgICAgc3R5bGU9IndpZHRoOiBhdXRvOyIKICAgICAgICAgIG9uY2hhbmdlPSJ1cGRhdGVfdGhlbWVfUm1kKHRoaXMudmFsdWUpIgogICAgICAgICAgYXJpYS1sYWJlbD0iU3dpdGNoIHRoZW1lIj4KICAgIDxvcHRpb24gc2VsZWN0ZWQgZGlzYWJsZWQgdmFsdWU9IiI+U3dpdGNoIHRoZW1lPC9vcHRpb24+CiAgICA8b3B0aW9uIGRpc2FibGVkIHZhbHVlPSJEZWZhdWx0VGhlbWUiPkRlZmF1bHQ8L29wdGlvbj4KICAgIDxvcHRpb24gdmFsdWU9IkNvcmFsVGhlbWUiPkNvcmFsPC9vcHRpb24+CiAgICA8b3B0aW9uIHZhbHVlPSJHb2xkVGhlbWUiPkdvbGQ8L29wdGlvbj4KICAgIDxvcHRpb24gdmFsdWU9IlN0ZWVsVGhlbWUiPlN0ZWVsPC9vcHRpb24+CiAgPC9zZWxlY3Q+CiAgPC9kaXY+CjwvZGl2PgpgYGAKCiMjIERpc3RhbmNlIGFzIGhlYXRtYXAgcGxvdChzKQpgYGB7ciwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9Niwgd2FybmluZz1GQUxTRX0KCmZvciAobWV0aG9kIGluIG1ldGhvZHMpewogIGRpc3QuYSA8LSBkaXN0YW5jZShkYXRhLCBtZXRob2QgPSBtZXRob2QpCiAgYSA8LSBhcy5tYXRyaXgoZGlzdC5hKQogIHdyaXRlLnRhYmxlKGEsIHBhc3RlKHNlcD0iIiwgbWV0aG9kLCAiLnRzdiIpLCBzZXA9Ilx0IiwgcXVvdGU9RkFMU0UsIGNvbC5uYW1lcz1OQSkKICBwYSA8LSBwbG90X2Rpc3RfYXNfaGVhdG1hcChkaXN0LmEsIG9yZGVyID0gc2FtcGxlT3JkZXIsIHRpdGxlID0gcGFzdGUoIkhlYXRtYXAgcGxvdCBvZiB0aGUgYmV0YSBkaXN0YW5jZSA6IixtZXRob2QpKSArIAogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCiAgcGxvdChwYSkKfQpgYGAKCiMjIFJlcHJvZHVjaWJpbGl0eSB0b2tlbgoKYGBge3Igc2Vzc2lvbiwgZWNobz1UUlVFLCBldmFsPVRSVUV9CnNlc3Npb25pbmZvOjpzZXNzaW9uX2luZm8oKQpgYGA=