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))))
Switch theme
Default
Coral
Gold
Steel
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=