library(ithi.utils)
load_base_libs()

library(ithi.meta)
library(ithi.xcr)
library(ithi.ihc)

Colour palettes

pal_patient <- select_palette("patient")

Parameters

db_path <- snakemake@params$db

ihc_table_path <- snakemake@input$ihc_table
tiltypes <- snakemake@params$ihc_xcr_tiltypes
tcr_diversity_file <- snakemake@input$tcr_diversity
bcr_diversity_file <- snakemake@input$bcr_diversity

Metadata

db <- src_sqlite(db_path, create = FALSE)
samples <- collect(tbl(db, "samples"))

Results

tcr_diversity <- read_xcr_diversity_file(tcr_diversity_file, db_path)
bcr_diversity <- read_xcr_diversity_file(bcr_diversity_file, db_path)

ihc_table <- fread(ihc_table_path)
ihc_table_subset <- subset(ihc_table, select = c("condensed_id", "patient_id", 
    tiltypes))

Correlations with TIL densities

diversity_cols <- c("reads", "diversity", "observedDiversity_mean", "shannonWienerIndex_mean", 
    "inverseSimpsonIndex_mean")

dat <- list(tcr = tcr_diversity, bcr = bcr_diversity)
diversity <- lapply(names(dat), function(segment) {
    x <- dat[[segment]]
    x <- subset(x, select = c("condensed_id", "patient_id", diversity_cols))
    colnames(x) <- mapvalues(colnames(x), from = diversity_cols, to = paste(segment, 
        diversity_cols, sep = "_"))
    return(x)
})
names(diversity) <- names(dat)

df <- Reduce(f = function(x, y) merge(x, y, by = c("condensed_id", "patient_id")), 
    c(diversity, list(ihc_table_subset)))

df_melted <- melt(df, id.vars = colnames(df)[!colnames(df) %in% tiltypes], measure.vars = tiltypes, 
    variable.name = "tiltype", value.name = "density")
pval_plot <- function(df_melted, variable) {
    pvals <- setNames(ddply(df_melted, .(tiltype), function(x) {
        df <- as.data.frame(x)
        corres <- cor.test(df[, "density"], df[, variable], method = "spearman")
        
        pval <- corres$p.value
        eq <- substitute(italic(P) == p, list(p = format(pval, digits = 3)))
        return(as.character(as.expression(eq)))
    }), c("tiltype", "p.value"))
    
    ggplot(df_melted, aes_string(x = "density", y = variable)) + geom_point(aes(colour = patient_id)) + 
        facet_wrap(~tiltype, scales = "free") + theme_bw() + theme_Publication() + 
        scale_color_manual(values = pal_patient) + geom_text(data = pvals, aes(x = Inf, 
        y = Inf, label = p.value), hjust = 1.1, vjust = 1.5, size = 3, parse = TRUE) + 
        ggtitle(variable)
}
pval_plot(df_melted, "tcr_reads")

pval_plot(df_melted, "bcr_reads")

pval_plot(df_melted, "tcr_diversity")

pval_plot(df_melted, "bcr_diversity")

pval_plot(df_melted, "tcr_shannonWienerIndex_mean")

pval_plot(df_melted, "bcr_shannonWienerIndex_mean")

LS0tCnRpdGxlOiAiSUhDLVhDUiBzdGF0aXN0aWNzIgpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHRydWUKICAgIHRvY19kZXB0aDogNQogICAgdG9jX2Zsb2F0OiB0cnVlCnBhcmFtczoKICBybWQ6ICJpaGNfeGNyX3N0YXRzLlJtZCIKLS0tCiAgICAgICAgICAgICAgICAgICAgICAgIGBgYHtyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQoKIyMjIyMjIyMgU25ha2VtYWtlIGhlYWRlciAjIyMjIyMjIwpsaWJyYXJ5KG1ldGhvZHMpClNuYWtlbWFrZSA8LSBzZXRDbGFzcygKICAgICJTbmFrZW1ha2UiLAogICAgc2xvdHMgPSBjKAogICAgICAgIGlucHV0ID0gImxpc3QiLAogICAgICAgIG91dHB1dCA9ICJsaXN0IiwKICAgICAgICBwYXJhbXMgPSAibGlzdCIsCiAgICAgICAgd2lsZGNhcmRzID0gImxpc3QiLAogICAgICAgIHRocmVhZHMgPSAibnVtZXJpYyIsCiAgICAgICAgbG9nID0gImxpc3QiLAogICAgICAgIHJlc291cmNlcyA9ICJsaXN0IiwKICAgICAgICBjb25maWcgPSAibGlzdCIsCiAgICAgICAgcnVsZSA9ICJjaGFyYWN0ZXIiCiAgICApCikKc25ha2VtYWtlIDwtIFNuYWtlbWFrZSgKICAgIGlucHV0ID0gbGlzdCgnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvbWl4Y3IvbWl4Y3JfcnVucy9pdGhfMV8yXzMvbWl4Y3I1L3Bvc3Rwcm9jZXNzL0lHSC9wb3N0ZmlsdGVyX2RpdmVyc2l0eV9zdGF0cy9kaXZlcnNpdHkuc3RyaWN0LnJlc2FtcGxlZC50eHQnLCAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL2FuYWx5c2lzL1JtZC9fc2l0ZS55bWwnLCAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvbWl4Y3IvbWl4Y3JfcnVucy9pdGhfMV8yXzMvbWl4Y3I1L3Bvc3Rwcm9jZXNzL1RSQi9wb3N0ZmlsdGVyX2RpdmVyc2l0eV9zdGF0cy9kaXZlcnNpdHkuc3RyaWN0LnJlc2FtcGxlZC50eHQnLCAnUm1kL2loY194Y3Jfc3RhdHMuUm1kJywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2loY190YWJsZS50c3YnLCAiYmNyX2RpdmVyc2l0eSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvbWl4Y3IvbWl4Y3JfcnVucy9pdGhfMV8yXzMvbWl4Y3I1L3Bvc3Rwcm9jZXNzL0lHSC9wb3N0ZmlsdGVyX2RpdmVyc2l0eV9zdGF0cy9kaXZlcnNpdHkuc3RyaWN0LnJlc2FtcGxlZC50eHQnLCAic2l0ZV9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvYW5hbHlzaXMvUm1kL19zaXRlLnltbCcsICJ0Y3JfZGl2ZXJzaXR5IiA9ICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9taXhjci9taXhjcl9ydW5zL2l0aF8xXzJfMy9taXhjcjUvcG9zdHByb2Nlc3MvVFJCL3Bvc3RmaWx0ZXJfZGl2ZXJzaXR5X3N0YXRzL2RpdmVyc2l0eS5zdHJpY3QucmVzYW1wbGVkLnR4dCcsICJub3RlYm9vayIgPSAnUm1kL2loY194Y3Jfc3RhdHMuUm1kJywgImloY190YWJsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvaWhjX3RhYmxlLnRzdicpLAogICAgb3V0cHV0ID0gbGlzdCgnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvd2ViL2loY194Y3Jfc3RhdHMubmIuaHRtbCcpLAogICAgcGFyYW1zID0gbGlzdChjKCdFX0NEOF9kZW5zaXR5JywgJ0VfQ0Q0X2RlbnNpdHknLCAnRV9DRDIwX2RlbnNpdHknLCAnRV9QbGFzbWFfZGVuc2l0eScsICdTX0NEOF9kZW5zaXR5JywgJ1NfQ0Q0X2RlbnNpdHknLCAnU19DRDIwX2RlbnNpdHknLCAnU19QbGFzbWFfZGVuc2l0eScsICdUX0NEOF9kZW5zaXR5JywgJ1RfQ0Q0X2RlbnNpdHknLCAnVF9DRDIwX2RlbnNpdHknLCAnVF9QbGFzbWFfZGVuc2l0eScpLCAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL21ldGFkYXRhL2RiL2ltbXVuZV9wcm9qZWN0LnNxbGl0ZTMnLCAnaXRoaS1hbmFseXNpcy1paGMteGNyLXN0YXRzJywgImloY194Y3JfdGlsdHlwZXMiID0gYygnRV9DRDhfZGVuc2l0eScsICdFX0NENF9kZW5zaXR5JywgJ0VfQ0QyMF9kZW5zaXR5JywgJ0VfUGxhc21hX2RlbnNpdHknLCAnU19DRDhfZGVuc2l0eScsICdTX0NENF9kZW5zaXR5JywgJ1NfQ0QyMF9kZW5zaXR5JywgJ1NfUGxhc21hX2RlbnNpdHknLCAnVF9DRDhfZGVuc2l0eScsICdUX0NENF9kZW5zaXR5JywgJ1RfQ0QyMF9kZW5zaXR5JywgJ1RfUGxhc21hX2RlbnNpdHknKSwgImRiIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvbWV0YWRhdGEvZGIvaW1tdW5lX3Byb2plY3Quc3FsaXRlMycsICJuYW1lIiA9ICdpdGhpLWFuYWx5c2lzLWloYy14Y3Itc3RhdHMnKSwKICAgIHdpbGRjYXJkcyA9IGxpc3QoKSwKICAgIHRocmVhZHMgPSAxLAogICAgbG9nID0gbGlzdCgnL3NoYWhsYWIvYWx6aGFuZy9jbHVzdHRtcC9wYXBlcmFuYWx5c2lzMi9paGNfeGNyX3N0YXRzLmxvZycpLAogICAgcmVzb3VyY2VzID0gbGlzdCgpLAogICAgY29uZmlnID0gbGlzdCgic3BhdGlhbF9ub3RlYm9vayIgPSAnUm1kL3NwYXRpYWxfYW5hbHlzaXMuUm1kJywgIm1tY3RtX3BhdGllbnRfYWRfc2lncGxvdCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3Jlc3VsdHMvbW1jdG1fcmVzdWx0cy9pdGhfYnktcGF0aWVudC1hbmNlc3RyeS9wbG90cy9pdGgtYnktcGF0aWVudC1hbmNlc3RyeV9zbnYtc3Zfc2lnc19tdWx0aXBhbmVsLnBkZicsICJpY2djX25vcm1hbGl6ZWRfcmVhZHNfbWF0cml4IiA9ICcvc2hhaGxhYi9hbHpoYW5nL2RhdGEvSUNHQy9PVkFVX2V4cHJfbWF0cml4LnRzdicsICJtYXN0ZXJfdmFyaWFudF9maWxlIiA9ICcvc2hhaGxhYi9hbWNwaGVyc29uL3Byb2plY3RzL2l0aDMvaXRoMy9ub3RlYm9va3MvYmVzcG9rZS9pdGhfc252cy50c3YnLCAiYmNycGh5bG9fY29ycmVsYXRpb25zX25vdGVib29rIiA9ICdSbWQvYmNyX3BoeWxvX2NvcnJlbGF0aW9ucy5SbWQnLCAidGNyX2RpdmVyc2l0eSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvbWl4Y3IvbWl4Y3JfcnVucy9pdGhfMV8yXzMvbWl4Y3I1L3Bvc3Rwcm9jZXNzL1RSQi9wb3N0ZmlsdGVyX2RpdmVyc2l0eV9zdGF0cy9kaXZlcnNpdHkuc3RyaWN0LnJlc2FtcGxlZC50eHQnLCAiY2xhc3NpZmllcl90eXBlIiA9ICdrbm4nLCAibXZjbHVzdF90aWx0eXBlcyIgPSBjKCdFX0NEOF9kZW5zaXR5JywgJ0VfQ0Q0X2RlbnNpdHknLCAnRV9DRDIwX2RlbnNpdHknLCAnRV9QbGFzbWFfZGVuc2l0eScsICdTX0NEOF9kZW5zaXR5JywgJ1NfQ0Q0X2RlbnNpdHknLCAnU19DRDIwX2RlbnNpdHknLCAnU19QbGFzbWFfZGVuc2l0eScpLCAid2FuZ19mYmlfc3RhdHVzIiA9ICcvc2hhaGxhYi9hbHpoYW5nL2RhdGEvSUNHQy9uZy4zODQ5LVMxMi50eHQnLCAiYmNycGh5bG9fdGlsdHlwZXMiID0gYygnRV9DRDhfZGVuc2l0eScsICdFX0NENF9kZW5zaXR5JywgJ0VfQ0QyMF9kZW5zaXR5JywgJ0VfUGxhc21hX2RlbnNpdHknLCAnU19DRDhfZGVuc2l0eScsICdTX0NENF9kZW5zaXR5JywgJ1NfQ0QyMF9kZW5zaXR5JywgJ1NfUGxhc21hX2RlbnNpdHknLCAnVF9DRDhfZGVuc2l0eScsICdUX0NENF9kZW5zaXR5JywgJ1RfQ0QyMF9kZW5zaXR5JywgJ1RfUGxhc21hX2RlbnNpdHknKSwgInRhYmxlX2RpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjInLCAidGNnYV9vdl9hbm5vdGF0aW9ucyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL1RDR0EvdGNnYV9vdl9hbm5vdGF0aW9uX3N1cDEzLnR4dCcsICJwcmV2YWxlbmNlX3RocmVzaG9sZCIgPSAwLjAxLCAic2l0ZV9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvYW5hbHlzaXMvUm1kL19zaXRlLnltbCcsICJpdGhfc3RhdF90eXBlcyIgPSBjKCdlbnRyb3B5JywgJ3Bvc3Rwcm9jZXNzZWRfZGl2ZXJnZW5jZScsICdjb21iaW5lZF9pdGhfbm9ybWFsaXplZCcsICdwcm9wb3J0aW9uX3N1YmNsb25hbCcpLCAiY2xvbmVfcHJldmFsZW5jZV9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvZGF0YS9pdGgvY29tcGxldGUvY2xvbmVfZGF0YS50c3YnLCAiaWdwYXJ0aXRpb25fb3V0ZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9pZ3BhcnRpdGlvbi9ydW4yMicsICJtbWN0bV9vdl9jb21iaW5lZF9yZXN1bHRfZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcmVzdWx0cy9tbWN0bV9yZXN1bHRzL2NvbWJpbmVkX292X21tY3RtL291dHB1dCcsICJ4Y3JfY2xvbmVzX25vdGVib29rIiA9ICdSbWQveGNyX2Nsb25lc19hbmFseXNpcy5SbWQnLCAiYmNyX2Nsb25vdHlwZXMiID0gJy9zaGFobGFiL2FsemhhbmcvcGlwZWxpbmVfb3V0cHV0cy9pdGhfaW1tdW5lL21peGNyL21peGNyX3J1bnMvaXRoXzFfMl8zL21peGNyNS9jbG9ub3R5cGVzL0lHSF9jbG9ub3R5cGVzX2ZpbHRlcmVkLnR4dCcsICJiZW5jaG1hcmtkaXIiID0gJy9zaGFobGFiL2FsemhhbmcvYmVuY2htYXJrcy9wYXBlcmFuYWx5c2lzMicsICJjbG9uZV90cmVlX2ZpbGUiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9kYXRhL2l0aC9jb21wbGV0ZS90cmVlX2RhdGEudHN2JywgInhjcl9tYXBwaW5nX25vdGVib29rIiA9ICdSbWQveGNyX21hcHBpbmcuUm1kJywgImljZ2Nfc3BlY2ltZW5fZmlsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL0lDR0Mvc3BlY2ltZW4udHN2JywgIm1tY3RtX2ZpbmFsX3BhdGllbnRfZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcmVzdWx0cy9tbWN0bV9yZXN1bHRzL2l0aF9ieS1wYXRpZW50X3dpdGgtb3YnLCAibG9nZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL2NsdXN0dG1wL3BhcGVyYW5hbHlzaXMyJywgInBhdGllbnRzX2Zvcl9jbG9uYWwiID0gYygxLCAyLCAzLCA0LCA3LCA5LCAxMCwgMTEsIDEyLCAxMywgMTQsIDE1LCAxNiwgMTcpLCAidGNnYV9jbGluaWNhbCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL1RDR0Evc3luYXBzZV9jbGluQWxsX2RhdGEudHN2JywgImtub3duX3N1YnR5cGVfZmlsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL2RhdGEvZXhwcmVzc2lvbi9hcnJheS9zdWJ0eXBlcy9rbm93bl9zdWJ0eXBlcy50c3YnLCAiaWhjX3J1bjEiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9kYXRhL2loYy9jZDhjZDNjZDIwL3ZhbGlkYXRlZF9zdGF0c193ZWlnaHRlZF9uZXcucmRhdGEnLCAibmFub3N0cmluZ19zaWduYXR1cmVfbm90ZWJvb2siID0gJ1JtZC9uYW5vc3RyaW5nX3NpZ25hdHVyZXMuUm1kJywgIm1tY3RtX292X2NvbWJpbmVkX3NpZ3Bsb3QiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9yZXN1bHRzL21tY3RtX3Jlc3VsdHMvY29tYmluZWRfb3ZfbW1jdG0vcGxvdHMvb3Zfc252LXN2X3NpZ3NfbXVsdGlwYW5lbC5wZGYnLCAiaXRoX3RpbF9ub3RlYm9vayIgPSAnUm1kL2l0aF90aWxfZGVuc2l0aWVzLlJtZCcsICJiY3JwaHlsb19leGFtcGxlc19ub3RlYm9vayIgPSAnUm1kL2Jjcl9waHlsb19leGFtcGxlcy5SbWQnLCAiZGVmYXVsdF9zYW1wbGVyIiA9ICdITUMnLCAicGhlbm90eXBlX3RocmVzaG9sZCIgPSAwLjg1LCAibXV0c2lnX3RpbHR5cGVzIiA9IGMoJ0VfQ0Q4X2RlbnNpdHknLCAnRV9DRDRfZGVuc2l0eScsICdFX0NEMjBfZGVuc2l0eScsICdFX1BsYXNtYV9kZW5zaXR5JywgJ1NfQ0Q4X2RlbnNpdHknLCAnU19DRDRfZGVuc2l0eScsICdTX0NEMjBfZGVuc2l0eScsICdTX1BsYXNtYV9kZW5zaXR5JywgJ1RfQ0Q4X2RlbnNpdHknLCAnVF9DRDRfZGVuc2l0eScsICdUX0NEMjBfZGVuc2l0eScsICdUX1BsYXNtYV9kZW5zaXR5JyksICJtdXRhdGlvbl9zaWduYXR1cmVfbm90ZWJvb2siID0gJ1JtZC9tdXRhdGlvbl9zaWduYXR1cmVzLlJtZCcsICJjbG9uYWxfc2FtcGxlcnMiID0gYygnSE1DJywgJ05VVFMnKSwgImludGVybWVkaWF0ZV9kaXIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL2ludGVybWVkaWF0ZXMvcnVuMicsICJqX2RpY3Rpb25hcnkiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9zdWJwcm9qZWN0cy9pbW10eXBlci9tZXRhZGF0YS9pbWd0L0hvbW9fc2FwaWVuc19UUkJKLmZhc3RhJywgIm1vbHN1YnR5cGVfdGlsdHlwZXMiID0gYygnRV9DRDhfZGVuc2l0eScsICdFX0NENF9kZW5zaXR5JywgJ0VfQ0QyMF9kZW5zaXR5JywgJ0VfUGxhc21hX2RlbnNpdHknLCAnU19DRDhfZGVuc2l0eScsICdTX0NENF9kZW5zaXR5JywgJ1NfQ0QyMF9kZW5zaXR5JywgJ1NfUGxhc21hX2RlbnNpdHknKSwgImloY194Y3Jfc3RhdHNfbm90ZWJvb2siID0gJ1JtZC9paGNfeGNyX3N0YXRzLlJtZCcsICJ0aWxfY2xhc3NpZmllcl9ub3RlYm9vayIgPSAnUm1kL3RpbF9jbGFzc2lmaWVyLlJtZCcsICJ0Y3JfY2xvbm90eXBlcyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvbWl4Y3IvbWl4Y3JfcnVucy9pdGhfMV8yXzMvbWl4Y3I1L2Nsb25vdHlwZXMvVFJCX2Nsb25vdHlwZXNfZmlsdGVyZWQudHh0JywgInhjcl9kaXN0YW5jZV9tZXRob2QiID0gJ2hvcm4nLCAiYmNyX2RpdmVyc2l0eSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvbWl4Y3IvbWl4Y3JfcnVucy9pdGhfMV8yXzMvbWl4Y3I1L3Bvc3Rwcm9jZXNzL0lHSC9wb3N0ZmlsdGVyX2RpdmVyc2l0eV9zdGF0cy9kaXZlcnNpdHkuc3RyaWN0LnJlc2FtcGxlZC50eHQnLCAidGNnYV9leHByX21hdHJpeCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL1RDR0EvZXhwcl9tYXRyaXhfbm9ybWFsaXplX3N0YW5kYXJkaXplX25vZHVwbGljYXRlcy50c3YnLCAibmFub3N0cmluZ19hbm5vdGF0aW9ucyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL2RhdGEvZXhwcmVzc2lvbi9uYW5vc3RyaW5nL3BhbmNhbmNlcl9hbm5vdGF0aW9ucy50c3YnLCAibXZjbHVzdF9uY2x1c3QiID0gMywgImluZGV4X25vdGVib29rIiA9ICdSbWQvaW5kZXguUm1kJywgImljZ2NfbW9sZWN1bGFyX3N1YnR5cGVzIiA9ICcvc2hhaGxhYi9hbHpoYW5nL2RhdGEvSUNHQy9pY2djX3ByaW1hcnlfdHVtb3VyX3N1YnR5cGVzLnRzdicsICJub3RlYm9va19kaXIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3dlYicsICJuZW9hbnRpZ2VuX2VkaXRpbmdfbm90ZWJvb2siID0gJ1JtZC9pbW11bm9lZGl0aW5nLlJtZCcsICJQTkdfUVVBTElUWSIgPSAzMDAsICJleGFtcGxlX2Fubm90YXRpb25zIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9pZ3BhcnRpdGlvbi9ydW4xMy9maW5hbF9wYXJ0aXRpb25zL2l0aDJfMi9jbHVzdDkvYW5ub3RhdGlvbnNfZmxhZ2dlZC50c3YnLCAibW1jdG1fcGF0aWVudF9hbmNlc3RyYWxfZGVzY2VuZGFudF9yZXN1bHRfZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcmVzdWx0cy9tbWN0bV9yZXN1bHRzL2l0aF9ieS1wYXRpZW50LWFuY2VzdHJ5L291dHB1dCcsICJ0aWxzX2Zvcl9jbHVzdGVyIiA9IGMoJ0VfQ0Q4X2RlbnNpdHknLCAnRV9DRDRfZGVuc2l0eScsICdFX0NEMjBfZGVuc2l0eScsICdFX1BsYXNtYV9kZW5zaXR5JywgJ1NfQ0Q4X2RlbnNpdHknLCAnU19DRDRfZGVuc2l0eScsICdTX0NEMjBfZGVuc2l0eScsICdTX1BsYXNtYV9kZW5zaXR5JyksICJwcm9wb3J0aW9uX3N1YmNsb25hbF9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvZGF0YS9pdGgvY29tcGxldGUvb2xkX3Byb3BvcnRpb25fc3ViY2xvbmFsLnRzdicsICJzdWJ0eXBlX21hcmtlcl9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvZGF0YS9leHByZXNzaW9uL25hbm9zdHJpbmcvc3VidHlwZV9tYXJrZXJzLnRzdicsICJpdGhfc3RhdHNfZmlsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL2RhdGEvaXRoL2NvbXBsZXRlL2Nsb25hbF9tZWFzdXJlcy50c3YnLCAibmFub3N0cmluZ19kYXRhIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcmVzdWx0cy9uYW5vc3RyaW5nX3Jlc3VsdHMvaXRoX2Z1bGwvcWMvbGltbWFfcXVhbnRpbGUvbm9ybWFsaXplZF9leHByZXNzaW9uX3ZvYV9sYWJlbHNfZmlsdGVyZWQudHN2JywgInhjcl9xY19ub3RlYm9vayIgPSAnUm1kL3JlcGxpY2F0ZXMuUm1kJywgIm1tY3RtX2FuY2VzdHJhbF9kZXNjZW5kYW50X3Jlc3VsdF9kaXIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9yZXN1bHRzL21tY3RtX3Jlc3VsdHMvaXRoX2J5LWFuY2VzdHJ5LXNhbXBsZS9vdXRwdXQnLCAiaW1tdHlwZXJfbGVuZ3RocyIgPSAnMTEgMTIgMTMgMTQgMTUgMTYgMTcgMTgnLCAibW1jdG1fZmluYWxfcGF0aWVudF9zaWdwbG90IiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcmVzdWx0cy9tbWN0bV9yZXN1bHRzL2l0aF9ieS1wYXRpZW50X3dpdGgtb3YvcGxvdHMvaXRoLWJ5LXBhdGllbnRfc252LXN2X3NpZ3NfbXVsdGlwYW5lbC5wZGYnLCAidGlsc19mb3JfdmFyaWFiaWxpdHkiID0gYygnRV9DRDhfZGVuc2l0eScsICdFX0NENF9kZW5zaXR5JywgJ0VfQ0QyMF9kZW5zaXR5JywgJ0VfUGxhc21hX2RlbnNpdHknLCAnU19DRDhfZGVuc2l0eScsICdTX0NENF9kZW5zaXR5JywgJ1NfQ0QyMF9kZW5zaXR5JywgJ1NfUGxhc21hX2RlbnNpdHknKSwgInNhZF9ub3RlYm9vayIgPSAnUm1kL3NwZWNpZXNfYWJ1bmRhbmNlX2Rpc3RyaWJ1dGlvbnMuUm1kJywgImRiIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvbWV0YWRhdGEvZGIvaW1tdW5lX3Byb2plY3Quc3FsaXRlMycsICJrbm93bl9zdWJ0eXBlc19tZXJnZWQiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9kYXRhL2V4cHJlc3Npb24va25vd25fc3VidHlwZXNfbWVyZ2VkLnRzdicsICJpdGhfcHJvamVjdF9yZXN1bHRzIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL2l0aDMvZGF0YS9yZXN1bHRzJywgInZhcmlhYmlsaXR5X3R5cGUiID0gJ3N0YWJpbGl6ZScsICJsaWJyYXJ5X3NpemVzIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9taXhjci9taXhjcl9ydW5zL2l0aF8xXzJfMy9taXhjcjUvbGlicmFyeV9zaXplcy50c3YnLCAibW1jdG1fc2FtcGxlX3Jlc3VsdF9kaXIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9yZXN1bHRzL21tY3RtX3Jlc3VsdHMvaXRoX2J5LXNhbXBsZS9vdXRwdXQnLCAiZHJpdmVyX21hcCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3N1YnByb2plY3RzL2RyaXZlcnMvZGF0YS9nZW5lX2xpc3RfbWFwcGVkLmJlZCcsICJpdGhfc3RhdGlzdGljc19ub3RlYm9vayIgPSAnUm1kL2l0aF9zdGF0aXN0aWNzLlJtZCcsICJpbW10eXBlcl9tb2RlbHMiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9yZXN1bHRzL2ltbXR5cGVyX3Jlc3VsdHMva2xhcmVuYmVlay9hYV92ai9ncmFkYm9vc3QnLCAic3BhdGlhbF9yZXN1bHRfZGlycyIgPSBsaXN0KCJzdHJvbWFsIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9zcGF0c2ltL2l0aDUvYWJjJywgImVwaXRoZWxpYWwiID0gJy9zaGFobGFiL2FsemhhbmcvcGlwZWxpbmVfb3V0cHV0cy9pdGhfaW1tdW5lL3NwYXRzaW0vaXRoMy9hYmMnKSwgImljZ2NfY2xpbmljYWwiID0gJy9zaGFobGFiL2FsemhhbmcvZGF0YS9JQ0dDL2Rvbm9yLk9WLUFVLnRzdicsICJtdWx0aXZpZXdjbHVzdGVyaW5nX25vdGVib29rIiA9ICdSbWQvbXVsdGl2aWV3Y2x1c3RlcmluZy5SbWQnLCAibWFzdGVyX2JyZWFrcG9pbnRfZmlsZSIgPSAnL3NoYWhsYWIvYW1jcGhlcnNvbi9wcm9qZWN0cy9pdGgzL2l0aDMvbm90ZWJvb2tzL2Jlc3Bva2UvaXRoX2JyZWFrcG9pbnRzLnRzdicsICJkcml2ZXJfYW5hbHlzaXNfbm90ZWJvb2siID0gJ1JtZC9kcml2ZXJfYW5hbHlzaXMuUm1kJywgIm1tY3RtX3NhbXBsZV9zaWdwbG90IiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcmVzdWx0cy9tbWN0bV9yZXN1bHRzL2l0aF9ieS1zYW1wbGUvcGxvdHMvaXRoLWJ5LXNhbXBsZV9zbnYtc3Zfc2lnc19tdWx0aXBhbmVsLnBkZicsICJjbG9uZV9icmFuY2hfbGVuZ3RoX2ZpbGUiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9kYXRhL2l0aC9jb21wbGV0ZS9icmFuY2hfZGF0YS50c3YnLCAieGNybWFwc2NhcGVfbm90ZWJvb2siID0gJ1JtZC94Y3JtYXBzY2FwZS5SbWQnLCAibmVvZWRpdGluZ19vdXRkaXIiID0gJy9zaGFobGFiL2FsemhhbmcvcGlwZWxpbmVfb3V0cHV0cy9pdGhfaW1tdW5lL25lb2VkaXRpbmcvcnVuNCcsICJ2X2RpY3Rpb25hcnkiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9zdWJwcm9qZWN0cy9pbW10eXBlci9tZXRhZGF0YS9pbWd0L0hvbW9fc2FwaWVuc19UUkJWLmZhc3RhJywgIm5jbHVzdHMiID0gMywgImV4YW1wbGVfbXNhX3Bsb3QiID0gJy9zaGFobGFiL2FsemhhbmcvcGlwZWxpbmVfb3V0cHV0cy9pdGhfaW1tdW5lL2lncGFydGl0aW9uL3J1bjEzL29sZC9hbGlnbm1lbnRfcGxvdHMvbXNhL2l0aDJfMi9jbHVzdDkvaW5kZWxfcmV2ZXJzZWQuaHRtbCcsICJpaGNfeGNyX3RpbHR5cGVzIiA9IGMoJ0VfQ0Q4X2RlbnNpdHknLCAnRV9DRDRfZGVuc2l0eScsICdFX0NEMjBfZGVuc2l0eScsICdFX1BsYXNtYV9kZW5zaXR5JywgJ1NfQ0Q4X2RlbnNpdHknLCAnU19DRDRfZGVuc2l0eScsICdTX0NEMjBfZGVuc2l0eScsICdTX1BsYXNtYV9kZW5zaXR5JywgJ1RfQ0Q4X2RlbnNpdHknLCAnVF9DRDRfZGVuc2l0eScsICdUX0NEMjBfZGVuc2l0eScsICdUX1BsYXNtYV9kZW5zaXR5JyksICJpaGNfcnVuMiIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL2RhdGEvaWhjL2NkNzljZDEzOGNkNjgvdmFsaWRhdGVkX3N0YXRzX3dlaWdodGVkLnJkYXRhJywgIm1tY3RtX3NhbXBsZV9hZF9zaWdwbG90IiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcmVzdWx0cy9tbWN0bV9yZXN1bHRzL2l0aF9ieS1hbmNlc3RyeS1zYW1wbGUvcGxvdHMvaXRoLWJ5LWFuY2VzdHJhbC1zYW1wbGVfc252LXN2X3NpZ3NfbXVsdGlwYW5lbC5wZGYnLCAiZmlndXJlX2dhbGxlcnlfbm90ZWJvb2siID0gJ1JtZC9maWd1cmVzLlJtZCcsICJpbW11bmVfdmFyaWFiaWxpdHlfbm90ZWJvb2siID0gJ1JtZC9pbW11bmVfdmFyaWFiaWxpdHkuUm1kJywgImljZ2NfZXhwcl9tZWx0ZWQiID0gJy9zaGFobGFiL2FsemhhbmcvZGF0YS9JQ0dDL09WQVVfZXhwcl9tZWx0ZWQudHN2JywgIm1hcHNjYXBlX25vdGVib29rIiA9ICdSbWQvbWFwc2NhcGUuUm1kJywgIm1vbHN1YnR5cGVfbm90ZWJvb2siID0gJ1JtZC9tb2xlY3VsYXJfc3VidHlwZXMuUm1kJywgIlBOR19ERU5TSVRZIiA9IDMwMCksCiAgICBydWxlID0gJ2loY194Y3Jfc3RhdHMnCikKIyMjIyMjIyMgT3JpZ2luYWwgc2NyaXB0ICMjIyMjIyMjIwoKICAgICAgICAgICAgICAgICAgICAgICAgYGBgCgoKYGBge3IgZ2xvYmFsX2NodW5rX29wdGlvbnMsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgdGlkeT1UUlVFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFKQpgYGAKCgpgYGB7cn0KbGlicmFyeShpdGhpLnV0aWxzKQpsb2FkX2Jhc2VfbGlicygpCgpsaWJyYXJ5KGl0aGkubWV0YSkKbGlicmFyeShpdGhpLnhjcikKbGlicmFyeShpdGhpLmloYykKYGBgCgojIyBDb2xvdXIgcGFsZXR0ZXMKCmBgYHtyfQpwYWxfcGF0aWVudCA8LSBzZWxlY3RfcGFsZXR0ZSgicGF0aWVudCIpCmBgYAoKIyMgUGFyYW1ldGVycwoKYGBge3J9CmRiX3BhdGggPC0gc25ha2VtYWtlQHBhcmFtcyRkYgoKaWhjX3RhYmxlX3BhdGggPC0gc25ha2VtYWtlQGlucHV0JGloY190YWJsZQp0aWx0eXBlcyA8LSBzbmFrZW1ha2VAcGFyYW1zJGloY194Y3JfdGlsdHlwZXMKdGNyX2RpdmVyc2l0eV9maWxlIDwtIHNuYWtlbWFrZUBpbnB1dCR0Y3JfZGl2ZXJzaXR5CmJjcl9kaXZlcnNpdHlfZmlsZSA8LSBzbmFrZW1ha2VAaW5wdXQkYmNyX2RpdmVyc2l0eQpgYGAKCiMjIE1ldGFkYXRhCgpgYGB7cn0KZGIgPC0gc3JjX3NxbGl0ZShkYl9wYXRoLCBjcmVhdGU9RkFMU0UpCnNhbXBsZXMgPC0gY29sbGVjdCh0YmwoZGIsICJzYW1wbGVzIikpCmBgYAoKIyMgUmVzdWx0cwoKYGBge3J9CnRjcl9kaXZlcnNpdHkgPC0gcmVhZF94Y3JfZGl2ZXJzaXR5X2ZpbGUodGNyX2RpdmVyc2l0eV9maWxlLCBkYl9wYXRoKQpiY3JfZGl2ZXJzaXR5IDwtIHJlYWRfeGNyX2RpdmVyc2l0eV9maWxlKGJjcl9kaXZlcnNpdHlfZmlsZSwgZGJfcGF0aCkKCmloY190YWJsZSA8LSBmcmVhZChpaGNfdGFibGVfcGF0aCkKaWhjX3RhYmxlX3N1YnNldCA8LSBzdWJzZXQoaWhjX3RhYmxlLCBzZWxlY3Q9YygiY29uZGVuc2VkX2lkIiwgInBhdGllbnRfaWQiLCB0aWx0eXBlcykpCmBgYAoKIyMjIENvcnJlbGF0aW9ucyB3aXRoIFRJTCBkZW5zaXRpZXMKCmBgYHtyfQpkaXZlcnNpdHlfY29scyA8LSBjKCJyZWFkcyIsICJkaXZlcnNpdHkiLCAib2JzZXJ2ZWREaXZlcnNpdHlfbWVhbiIsICJzaGFubm9uV2llbmVySW5kZXhfbWVhbiIsCiAgICAgICAgICAgICAgICAgICAgImludmVyc2VTaW1wc29uSW5kZXhfbWVhbiIpCgpkYXQgPC0gbGlzdCh0Y3I9dGNyX2RpdmVyc2l0eSwgYmNyPWJjcl9kaXZlcnNpdHkpCmRpdmVyc2l0eSA8LSBsYXBwbHkobmFtZXMoZGF0KSwKICAgICAgIGZ1bmN0aW9uKHNlZ21lbnQpIHsKICAgICAgICAgeCA8LSBkYXRbW3NlZ21lbnRdXQogICAgICAgICB4IDwtIHN1YnNldCh4LCBzZWxlY3Q9YygiY29uZGVuc2VkX2lkIiwgInBhdGllbnRfaWQiLCBkaXZlcnNpdHlfY29scykpCiAgICAgICAgIGNvbG5hbWVzKHgpIDwtIG1hcHZhbHVlcyhjb2xuYW1lcyh4KSwgZnJvbSA9IGRpdmVyc2l0eV9jb2xzLCB0bz1wYXN0ZShzZWdtZW50LCBkaXZlcnNpdHlfY29scywgc2VwPSJfIikpCiAgICAgICAgIHJldHVybih4KQogICAgICAgfSkKbmFtZXMoZGl2ZXJzaXR5KSA8LSBuYW1lcyhkYXQpCgpkZiA8LSBSZWR1Y2UoZiA9IGZ1bmN0aW9uKHgseSkgbWVyZ2UoeCx5LCBieT1jKCJjb25kZW5zZWRfaWQiLCAicGF0aWVudF9pZCIpKSwgYyhkaXZlcnNpdHksIGxpc3QoaWhjX3RhYmxlX3N1YnNldCkpKQoKZGZfbWVsdGVkIDwtIG1lbHQoZGYsIGlkLnZhcnMgPSBjb2xuYW1lcyhkZilbIWNvbG5hbWVzKGRmKSAlaW4lIHRpbHR5cGVzXSwgbWVhc3VyZS52YXJzID0gdGlsdHlwZXMsCiAgICAgICAgICAgICAgICAgIHZhcmlhYmxlLm5hbWUgPSAidGlsdHlwZSIsIHZhbHVlLm5hbWUgPSAiZGVuc2l0eSIpCmBgYAoKCmBgYHtyfQpwdmFsX3Bsb3QgPC0gZnVuY3Rpb24oZGZfbWVsdGVkLCB2YXJpYWJsZSkgewogIHB2YWxzIDwtIHNldE5hbWVzKGRkcGx5KGRmX21lbHRlZCwgLih0aWx0eXBlKSwgZnVuY3Rpb24oeCkgewogICAgZGYgPC0gYXMuZGF0YS5mcmFtZSh4KQogICAgY29ycmVzIDwtIGNvci50ZXN0KGRmWywiZGVuc2l0eSJdLCBkZlssdmFyaWFibGVdLCBtZXRob2Q9InNwZWFybWFuIikKICAgIAogICAgcHZhbCA8LSBjb3JyZXMkcC52YWx1ZQogICAgZXEgPC0gc3Vic3RpdHV0ZShpdGFsaWMoUCk9PXAsIGxpc3QocD1mb3JtYXQocHZhbCwgZGlnaXRzPTMpKSkKICAgIHJldHVybihhcy5jaGFyYWN0ZXIoYXMuZXhwcmVzc2lvbihlcSkpKQogIH0pLCBjKCJ0aWx0eXBlIiwgInAudmFsdWUiKSkKICAKICBnZ3Bsb3QoZGZfbWVsdGVkLCBhZXNfc3RyaW5nKHg9ImRlbnNpdHkiLCB5PXZhcmlhYmxlKSkgKyBnZW9tX3BvaW50KGFlcyhjb2xvdXI9cGF0aWVudF9pZCkpICsgZmFjZXRfd3JhcCh+IHRpbHR5cGUsIHNjYWxlcyA9ICJmcmVlIikgKyB0aGVtZV9idygpICsgdGhlbWVfUHVibGljYXRpb24oKSArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBwYWxfcGF0aWVudCkgKyBnZW9tX3RleHQoZGF0YT1wdmFscywgYWVzKHg9SW5mLCB5PUluZiwgbGFiZWw9cC52YWx1ZSksIGhqdXN0PTEuMSwgdmp1c3Q9MS41LHNpemU9MyxwYXJzZT1UUlVFKSArIGdndGl0bGUodmFyaWFibGUpCn0KYGBgCgpgYGB7cn0KcHZhbF9wbG90KGRmX21lbHRlZCwgInRjcl9yZWFkcyIpCmBgYAoKCmBgYHtyfQpwdmFsX3Bsb3QoZGZfbWVsdGVkLCAiYmNyX3JlYWRzIikKYGBgCgpgYGB7cn0KcHZhbF9wbG90KGRmX21lbHRlZCwgInRjcl9kaXZlcnNpdHkiKQpgYGAKCmBgYHtyfQpwdmFsX3Bsb3QoZGZfbWVsdGVkLCAiYmNyX2RpdmVyc2l0eSIpCmBgYAoKYGBge3J9CnB2YWxfcGxvdChkZl9tZWx0ZWQsICJ0Y3Jfc2hhbm5vbldpZW5lckluZGV4X21lYW4iKQpgYGAKCmBgYHtyfQpwdmFsX3Bsb3QoZGZfbWVsdGVkLCAiYmNyX3NoYW5ub25XaWVuZXJJbmRleF9tZWFuIikKYGBgCg==