Setup

library(ithi.utils)
load_base_libs()
library(ithi.meta)
library(ithi.clones)
library(ithi.lohhla)

library(ape)
library(phylobase)
library(phytools)
library(igraph)
clone_tree_file <- snakemake@input$clone_tree_file
clone_branch_length_file <- snakemake@input$clone_branch_length_file
clone_prevalence_file <- snakemake@input$clone_prevalence_file
clola_result_dir <- snakemake@input$clola_result_dir

db_path <- snakemake@params$db
clola_result_filenames <- list.files(file.path(clola_result_dir, "clola_condensed_results"), 
    recursive = TRUE, full.names = TRUE, pattern = "clola_results.tsv")

tree_branch_data <- read_clone_tree_data(clone_tree_file, clone_branch_length_file, 
    clone_prevalence_file, db_path)
node_mapping <- tree_node_mapping(clone_tree_file)

trees <- lapply(tree_branch_data, function(x) x$tree)

Analysis

Our goal here is to reconstruct the clonal origin of LOHHLA.

We’ve run the clonal LOHHLA (CLOLA) model in another pipeline – we’ll just visualize the results here.

This is a little preliminary still – so the LOHHLA, as called in the following plots, is pretty rudimentary. We’re just using the genotype mode for each clone – i.e. the most common genotype each clone is assigned to. In actuality, we should be doing something like checking the 95% confidence interval of allele 1/allele 2 copy number to confidently call LOHHLA.

I can quickly implement that when I get a bit of time.

## Map for CN anchoring part of model
model_map <- list(nb = "Negative binomial", mult_factor = "Multiplicative factor (lognormal)", 
    nbbin = "Negative binomial (binmedian)", student = "LogR Student t")

## Map for priors on stayrate
prior_map <- list(truncnormal = "Truncated normal", uniform = "Uniform")
for (clola_result_filename in clola_result_filenames) {
    model_type <- basename(dirname(dirname(clola_result_filename)))
    prior_type <- basename(dirname(clola_result_filename))
    
    model_type <- model_map[[model_type]]
    prior_type <- prior_map[[prior_type]]
    
    header_str <- paste("Model type: ", model_type, "; ", "Stayrate prior type: ", 
        prior_type, sep = "")
    cat("### ", header_str, "\n\n")
    
    clola_results <- fread(clola_result_filename)
    clola_results_split <- split(clola_results, f = list(clola_results$patient_id))
    clola_results_remapped <- lapply(clola_results_split, function(df) {
        patient_id <- as.character(df$patient_id[1])
        df$clone_id <- ithi.meta::df_as_map(df = node_mapping[[as.character(patient_id)]], 
            df$clone_id, from = "from", to = "to")
        labels <- trees[[patient_id]]@label
        df$clone_name <- labels[df$clone_id]
        return(df)
    }) %>% rbind.fill
    
    patients <- unique(clola_results_remapped$patient_id)
    
    for (pat in patients) {
        cat("#### Patient ", pat, "\n\n")
        
        info <- subset(clola_results_remapped, patient_id == pat)
        hla_types <- sort(unique(info$hla_locus))
        
        for (locus in hla_types) {
            cat("##### Locus ", locus, "\n\n")
            plot_tree(clola_results_remapped, trees, as.character(pat), locus, 
                colour_mode = "loh90")
        }
        cat("\n")
    }
    
}

Model type: Multiplicative factor (lognormal); Stayrate prior type: Truncated normal

Patient 1

Locus hla_a

Locus hla_b

Locus hla_c

Patient 2

Locus hla_a

Locus hla_b
Locus hla_c

Patient 3

Locus hla_a

Locus hla_b
Locus hla_c

Patient 4

Locus hla_a

Locus hla_c

Patient 7

Locus hla_a

Locus hla_b

Locus hla_c

Patient 9

Locus hla_b

Locus hla_c

Patient 10

Locus hla_a

Locus hla_c

Patient 11

Locus hla_b

Locus hla_c

Patient 12

Locus hla_a

Locus hla_b
Locus hla_c

Patient 13

Locus hla_a

Locus hla_b

Locus hla_c

Patient 14

Locus hla_b

Locus hla_c

Patient 15

Locus hla_a

Locus hla_b

Locus hla_c

Patient 16

Locus hla_a

Locus hla_b
Locus hla_c

Patient 17

Locus hla_a

Locus hla_b
Locus hla_c

Model type: Multiplicative factor (lognormal); Stayrate prior type: Uniform

Patient 1

Locus hla_a

Locus hla_b

Locus hla_c

Patient 2

Locus hla_a

Locus hla_b
Locus hla_c

Patient 3

Locus hla_a

Locus hla_b
Locus hla_c

Patient 4

Locus hla_a

Locus hla_c

Patient 7

Locus hla_a

Locus hla_b

Locus hla_c

Patient 9

Locus hla_b

Locus hla_c

Patient 10

Locus hla_a

Locus hla_c

Patient 11

Locus hla_b

Locus hla_c

Patient 12

Locus hla_a

Locus hla_b
Locus hla_c

Patient 13

Locus hla_a

Locus hla_b

Locus hla_c

Patient 14

Locus hla_b

Locus hla_c

Patient 15

Locus hla_a

Locus hla_b

Locus hla_c

Patient 16

Locus hla_a

Locus hla_b
Locus hla_c

Patient 17

Locus hla_a

Locus hla_b
Locus hla_c

Model type: Negative binomial; Stayrate prior type: Truncated normal

Patient 1

Locus hla_a

Locus hla_b

Locus hla_c

Patient 2

Locus hla_a

Locus hla_b
Locus hla_c

Patient 3

Locus hla_a

Locus hla_b
Locus hla_c

Patient 4

Locus hla_a

Locus hla_c

Patient 7

Locus hla_a

Locus hla_b

Locus hla_c

Patient 9

Locus hla_b

Locus hla_c

Patient 10

Locus hla_a

Locus hla_c

Patient 11

Locus hla_b

Locus hla_c

Patient 12

Locus hla_a

Locus hla_b
Locus hla_c

Patient 13

Locus hla_a

Locus hla_b

Locus hla_c

Patient 14

Locus hla_b

Locus hla_c

Patient 15

Locus hla_a

Locus hla_b

Locus hla_c

Patient 16

Locus hla_a

Locus hla_b
Locus hla_c

Patient 17

Locus hla_a

Locus hla_b

Locus hla_c

Model type: Negative binomial; Stayrate prior type: Uniform

Patient 1

Locus hla_a

Locus hla_b

Locus hla_c

Patient 2

Locus hla_a

Locus hla_b
Locus hla_c

Patient 3

Locus hla_a

Locus hla_b
Locus hla_c

Patient 4

Locus hla_a

Locus hla_c

Patient 7

Locus hla_a

Locus hla_b

Locus hla_c

Patient 9

Locus hla_b

Locus hla_c

Patient 10

Locus hla_a

Locus hla_c

Patient 11

Locus hla_b

Locus hla_c

Patient 12

Locus hla_a

Locus hla_b
Locus hla_c

Patient 13

Locus hla_a

Locus hla_b

Locus hla_c

Patient 14

Locus hla_b

Locus hla_c

Patient 15

Locus hla_a

Locus hla_b

Locus hla_c

Patient 16

Locus hla_a

Locus hla_b
Locus hla_c

Patient 17

Locus hla_a

Locus hla_b
Locus hla_c

Model type: Negative binomial (binmedian); Stayrate prior type: Truncated normal

Patient 1

Locus hla_a

Locus hla_b

Locus hla_c

Patient 2

Locus hla_a

Locus hla_b
Locus hla_c

Patient 3

Locus hla_a

Locus hla_b
Locus hla_c

Patient 4

Locus hla_a

Locus hla_c

Patient 7

Locus hla_a

Locus hla_b
Locus hla_c

Patient 9

Locus hla_b

Locus hla_c

Patient 10

Locus hla_a

Locus hla_c

Patient 11

Locus hla_b

Locus hla_c

Patient 12

Locus hla_a

Locus hla_b
Locus hla_c

Patient 13

Locus hla_a

Locus hla_b

Locus hla_c

Patient 14

Locus hla_b

Locus hla_c

Patient 15

Locus hla_a

Locus hla_b

Locus hla_c

Patient 16

Locus hla_a

Locus hla_b
Locus hla_c

Patient 17

Locus hla_a

Locus hla_b
Locus hla_c

Model type: Negative binomial (binmedian); Stayrate prior type: Uniform

Patient 1

Locus hla_a

Locus hla_b

Locus hla_c

Patient 2

Locus hla_a

Locus hla_b
Locus hla_c

Patient 3

Locus hla_a

Locus hla_b
Locus hla_c

Patient 4

Locus hla_a

Locus hla_c

Patient 7

Locus hla_a

Locus hla_b
Locus hla_c

Patient 9

Locus hla_b

Locus hla_c

Patient 10

Locus hla_a

Locus hla_c

Patient 11

Locus hla_b

Locus hla_c

Patient 12

Locus hla_a

Locus hla_b
Locus hla_c

Patient 13

Locus hla_a

Locus hla_b

Locus hla_c

Patient 14

Locus hla_b

Locus hla_c

Patient 15

Locus hla_a

Locus hla_b

Locus hla_c

Patient 16

Locus hla_a

Locus hla_b
Locus hla_c

Patient 17

Locus hla_a

Locus hla_b
Locus hla_c

Model type: LogR Student t; Stayrate prior type: Truncated normal

Patient 1

Locus hla_a

Locus hla_b

Locus hla_c

Patient 2

Locus hla_a

Locus hla_b
Locus hla_c

Patient 3

Locus hla_a

Locus hla_b
Locus hla_c

Patient 4

Locus hla_a

Locus hla_c

Patient 7

Locus hla_a

Locus hla_b
Locus hla_c

Patient 9

Locus hla_b

Locus hla_c

Patient 10

Locus hla_a

Locus hla_c

Patient 11

Locus hla_b

Locus hla_c

Patient 12

Locus hla_a

Locus hla_b
Locus hla_c

Patient 13

Locus hla_a

Locus hla_b

Locus hla_c

Patient 14

Locus hla_b

Locus hla_c

Patient 15

Locus hla_a

Locus hla_b

Locus hla_c

Patient 16

Locus hla_a

Locus hla_b
Locus hla_c

Patient 17

Locus hla_a

Locus hla_b

Locus hla_c

Model type: LogR Student t; Stayrate prior type: Uniform

Patient 1

Locus hla_a

Locus hla_b

Locus hla_c

Patient 2

Locus hla_a

Locus hla_b
Locus hla_c

Patient 3

Locus hla_a

Locus hla_b
Locus hla_c

Patient 4

Locus hla_a

Locus hla_c

Patient 7

Locus hla_a

Locus hla_b
Locus hla_c

Patient 9

Locus hla_b

Locus hla_c

Patient 10

Locus hla_a

Locus hla_c

Patient 11

Locus hla_b

Locus hla_c

Patient 12

Locus hla_a

Locus hla_b
Locus hla_c

Patient 13

Locus hla_a

Locus hla_b

Locus hla_c

Patient 14

Locus hla_b

Locus hla_c

Patient 15

Locus hla_a

Locus hla_b

Locus hla_c

Patient 16

Locus hla_a

Locus hla_b
Locus hla_c

Patient 17

Locus hla_a

Locus hla_b

Locus hla_c

LS0tCnRpdGxlOiAiQ2xvbmFsIExPSEhMQSByZXN1bHRzIgotLS0KICAgICAgICAgICAgICAgICAgICAgICAgYGBge3IsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CgojIyMjIyMjIyBTbmFrZW1ha2UgaGVhZGVyICMjIyMjIyMjCmxpYnJhcnkobWV0aG9kcykKU25ha2VtYWtlIDwtIHNldENsYXNzKAogICAgIlNuYWtlbWFrZSIsCiAgICBzbG90cyA9IGMoCiAgICAgICAgaW5wdXQgPSAibGlzdCIsCiAgICAgICAgb3V0cHV0ID0gImxpc3QiLAogICAgICAgIHBhcmFtcyA9ICJsaXN0IiwKICAgICAgICB3aWxkY2FyZHMgPSAibGlzdCIsCiAgICAgICAgdGhyZWFkcyA9ICJudW1lcmljIiwKICAgICAgICBsb2cgPSAibGlzdCIsCiAgICAgICAgcmVzb3VyY2VzID0gImxpc3QiLAogICAgICAgIGNvbmZpZyA9ICJsaXN0IiwKICAgICAgICBydWxlID0gImNoYXJhY3RlciIKICAgICkKKQpzbmFrZW1ha2UgPC0gU25ha2VtYWtlKAogICAgaW5wdXQgPSBsaXN0KCcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9jbG9sYS9ydW42JywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2Nsb25lcy9jbG9uZV9kYXRhLnRzdicsICdub3RlYm9va3MvY2xvbGFfaXRoLlJtZCcsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvdHJlZV9kYXRhLnRzdicsICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvYnJhbmNoX2RhdGEudHN2JywgImNsb2xhX3Jlc3VsdF9kaXIiID0gJy9zaGFobGFiL2FsemhhbmcvcGlwZWxpbmVfb3V0cHV0cy9pdGhfaW1tdW5lL2Nsb2xhL3J1bjYnLCAiY2xvbmVfYnJhbmNoX2xlbmd0aF9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvYnJhbmNoX2RhdGEudHN2JywgImNsb25lX3ByZXZhbGVuY2VfZmlsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvY2xvbmVzL2Nsb25lX2RhdGEudHN2JywgImNsb25lX3RyZWVfZmlsZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvY2xvbmVzL3RyZWVfZGF0YS50c3YnLCAibm90ZWJvb2siID0gJ25vdGVib29rcy9jbG9sYV9pdGguUm1kJyksCiAgICBvdXRwdXQgPSBsaXN0KCcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy9yZXZpZXcvbm90ZWJvb2tzL3J1bjIvY2xvbGEubmIuaHRtbCcpLAogICAgcGFyYW1zID0gbGlzdCgnY2xvbGFfaXRoX2FuYWx5c2lzJywgJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9tZXRhZGF0YS9kYi9pbW11bmVfcHJvamVjdC5zcWxpdGUzJywgIm5hbWUiID0gJ2Nsb2xhX2l0aF9hbmFseXNpcycsICJkYiIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL21ldGFkYXRhL2RiL2ltbXVuZV9wcm9qZWN0LnNxbGl0ZTMnKSwKICAgIHdpbGRjYXJkcyA9IGxpc3QoKSwKICAgIHRocmVhZHMgPSAxLAogICAgbG9nID0gbGlzdCgnL3NoYWhsYWIvYWx6aGFuZy9jbHVzdHRtcC9wYXBlcnJldmlldzIvbm90ZWJvb2tzL2Nsb2xhX2l0aF9hbmFseXNpcy5sb2cnKSwKICAgIHJlc291cmNlcyA9IGxpc3QoKSwKICAgIGNvbmZpZyA9IGxpc3QoImNsb2xhX3Jlc3VsdF9kaXIiID0gJy9zaGFobGFiL2FsemhhbmcvcGlwZWxpbmVfb3V0cHV0cy9pdGhfaW1tdW5lL2Nsb2xhL3J1bjYnLCAicHJldmFsZW5jZV90aHJlc2hvbGQiID0gMC4wMSwgInZhcmlhYmlsaXR5X3R5cGUiID0gJ3N0YWJpbGl6ZScsICJ0Y2dhX292X2Fubm90YXRpb25zIiA9ICcvc2hhaGxhYi9hbHpoYW5nL2RhdGEvVENHQS90Y2dhX292X2Fubm90YXRpb25fc3VwMTMudHh0JywgIml0aF9zdGF0cyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvaXRoX3N0YXRpc3RpY3MudHN2JywgImxvaGhsYV9pY2djX291dGRpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvbG9oaGxhL3J1bjFfaWNnYycsICJ0aWxfY2x1c3RlcnNfb3V0cHV0IiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy9pbnRlcm1lZGlhdGVzL3J1bjIvdGlsX2NsdXN0ZXJzX291dHB1dC50eHQnLCAibG9nZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL2NsdXN0dG1wL3BhcGVycmV2aWV3MicsICJ4Y3JfZ3JhcGhzX3JkcyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jldmlldy9kYXRhX29iamVjdHMveGNyX2dyYXBoX3Jlc3VsdHMucmRzJywgImRiIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvbWV0YWRhdGEvZGIvaW1tdW5lX3Byb2plY3Quc3FsaXRlMycsICJuYW5vc3RyaW5nX2Fubm90YXRpb25zIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvZGF0YS9leHByZXNzaW9uL25hbm9zdHJpbmcvcGFuY2FuY2VyX2Fubm90YXRpb25zLnRzdicsICJmaW5uaGVfcGlwZWxpbmVfcmVzdWx0c19kaXIiID0gJy9zaGFobGFiL2FsemhhbmcvcGlwZWxpbmVfb3V0cHV0cy9pdGhfaW1tdW5lL2Zpbm5oZS9ydW4xJywgInJlZnNlcV9nZW5lX2ZpbGUiID0gJy9zaGFobGFiL2FsemhhbmcvZGF0YS9nZW5vbWUvaGcxOS9yZWZzZXFfZ2VuZXMuYmVkJywgImJjcl9kaXZlcnNpdHkiID0gJy9zaGFobGFiL2FsemhhbmcvcGlwZWxpbmVfb3V0cHV0cy9pdGhfaW1tdW5lL21peGNyL21peGNyX3J1bnMvaXRoXzFfMl8zL21peGNyNS9wb3N0cHJvY2Vzcy9JR0gvcG9zdGZpbHRlcl9kaXZlcnNpdHlfc3RhdHMvZGl2ZXJzaXR5LnN0cmljdC5yZXNhbXBsZWQudHh0JywgInRjZ2FfcGFwZXJfc3VidHlwZXNfcmF3IiA9ICcvc2hhaGxhYi9hbHpoYW5nL2RhdGEvVENHQS9UQ0dBXzQ4OV9VRS5rNC50eHQnLCAic29tYXRpY19jb2RpbmdfcmVzdWx0X2RpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvc29tYXRpY19jb2RpbmdfdmFyaWFudHMnLCAiYXJyYXlfbm1mX3N1YnR5cGVzIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvZGF0YS9leHByZXNzaW9uL2FycmF5L3N1YnR5cGVzL25tZl9zdWJ0eXBlcy50eHQnLCAibW9sc3VidHlwZXMiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL21vbHN1YnR5cGVzLnRzdicsICJzbnZfdGFibGUiID0gJy9zaGFobGFiL2FtY3BoZXJzb24vcHJvamVjdHMvaXRoMy9pdGgzL25vdGVib29rcy9iZXNwb2tlL2l0aF9zbnZzLnRzdicsICJpaGNfdGFibGUiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2loY190YWJsZS50c3YnLCAidGlsc19mb3JfdmFyaWFiaWxpdHkiID0gYygnVF9DRDhfZGVuc2l0eScsICdUX0NENF9kZW5zaXR5JywgJ1RfQ0QyMF9kZW5zaXR5JywgJ1RfUGxhc21hX2RlbnNpdHknKSwgImNsb25lX3RyZWVzIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9jbG9uZXMvdHJlZV9kYXRhLnRzdicsICJub3RlYm9va19kaXIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3Jldmlldy9ub3RlYm9va3MvcnVuMicsICJoZV9yZXN1bHRzX2RpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL2l0aGkvZmlubl9yZXN1bHRzL2hlX291dHB1dF9Ob3YyOScsICJwYXRpZW50c19mb3JfY2xvbmFsIiA9IGMoMSwgMiwgMywgNCwgNywgOSwgMTAsIDExLCAxMiwgMTMsIDE0LCAxNSwgMTYsIDE3KSwgImxvaGhsYV9zdXBwb3J0aXZlX3NpdGVfdGhyZXNob2xkIiA9IDkwLjAsICJrbm93bl9zdWJ0eXBlc19hcnJheSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL2RhdGEvZXhwcmVzc2lvbi9hcnJheS9zdWJ0eXBlcy9rbm93bl9zdWJ0eXBlcy50c3YnLCAidGlsY2x1c3Rlcl9zdXBlcnZpc2VkX2lweW5iIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmV2aWV3L2lweS90aWxjbHVzdGVyX3N1cGVydmlzZWRtdWx0aWNsYXNzLmlweW5iJywgInRjZ2FfcGFwZXJfc3VidHlwZXNfcG9zc2lsaG91ZXR0ZSIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL1RDR0EvVENHQV80ODlfVUUuazQucG9zU2lsaG91ZXR0ZS50eHQnLCAiaXRoX3N0YXRfdHlwZXMiID0gYygnZW50cm9weScsICdwb3N0cHJvY2Vzc2VkX2RpdmVyZ2VuY2UnLCAnY29tYmluZWRfaXRoX25vcm1hbGl6ZWQnLCAncHJvcG9ydGlvbl9zdWJjbG9uYWwnKSwgImJyZWFrcG9pbnRfdGFibGUiID0gJy9zaGFobGFiL2FtY3BoZXJzb24vcHJvamVjdHMvaXRoMy9pdGgzL25vdGVib29rcy9iZXNwb2tlL2l0aF9icmVha3BvaW50cy50c3YnLCAiYWxsX3RpbHR5cGVzIiA9IGMoJ1RfQ0Q4X2RlbnNpdHknLCAnVF9DRDRfZGVuc2l0eScsICdUX0NEMjBfZGVuc2l0eScsICdUX1BsYXNtYV9kZW5zaXR5JywgJ0VfQ0Q4X2RlbnNpdHknLCAnRV9DRDRfZGVuc2l0eScsICdFX0NEMjBfZGVuc2l0eScsICdFX1BsYXNtYV9kZW5zaXR5JywgJ1NfQ0Q4X2RlbnNpdHknLCAnU19DRDRfZGVuc2l0eScsICdTX0NEMjBfZGVuc2l0eScsICdTX1BsYXNtYV9kZW5zaXR5JyksICJjbG9uZV9icmFuY2hfbGVuZ3RocyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvY2xvbmVzL2JyYW5jaF9kYXRhLnRzdicsICJpaGNfZmVhdHVyZXNfb3V0cHV0IiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy9pbnRlcm1lZGlhdGVzL3J1bjIvaWhjX2ZlYXR1cmVzX291dHB1dC50eHQnLCAiaWNnY19leHByX21hdCIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL0lDR0MvT1ZBVV9leHByX21hdHJpeC50c3YnLCAicm9vbmV5X211dHNpZ2N2X2ZpbGUiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9leHRlcm5hbC9vdGhlcl9wYXBlcnMvbW1jNi54bHN4JywgImNvcHludW1iZXJfdGFibGUiID0gJy9zaGFobGFiL2FsemhhbmcvZGF0YS9pdGhpL21hc3Rlcl9jb3B5bnVtYmVyX2ZpbGUudHN2JywgIm1tY3RtX2ZpbmFsX3BhdGllbnRfZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcmVzdWx0cy9tbWN0bV9yZXN1bHRzL2l0aF9ieS1wYXRpZW50X3dpdGgtb3YnLCAibmFub3N0cmluZ19kYXRhIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcmVzdWx0cy9uYW5vc3RyaW5nX3Jlc3VsdHMvaXRoX2Z1bGwvcWMvbGltbWFfcXVhbnRpbGUvbm9ybWFsaXplZF9leHByZXNzaW9uX3ZvYV9sYWJlbHNfZmlsdGVyZWQudHN2JywgImlncGFydGl0aW9uX291dGRpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvaWdwYXJ0aXRpb24vcnVuMjInLCAiYmVuY2htYXJrZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL2JlbmNobWFya3MvcGFwZXJyZXZpZXcyJywgInR1bW91cl9wdXJpdHkiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL3R1bW91cl9wdXJpdHkudHN2JywgInRjZ2Ffbm9uc3RkX2V4cHIiID0gJy9zaGFobGFiL2FsemhhbmcvZGF0YS9UQ0dBL2V4cHJfbWF0cml4X25vcm1hbGl6ZV9ub2R1cGxpY2F0ZXMudHN2JywgIm5lb2VkaXRpbmdfb3V0ZGlyIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9uZW9lZGl0aW5nL3J1bjYnLCAieGNyX3RhYmxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi94Y3JfdGFibGUudHN2JywgIml0aF9pY2djX2JjIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9pdGhfaWNnY19tZXJnZWRfYmMudHN2JywgImRpc3RhbmNlX21ldGhvZCIgPSAnaG9ybicsICJpbWFnZV9zdW1tYXJ5MiIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL2l0aGkveXVhbl9oZWNyX2ltYWdlX3Jlc3VsdHNfMi5jc3YnLCAidGNnYV9vdl9iYW1fZGlyIiA9ICcvc2hhaGxhYi9hcmNoaXZlL2ltbXVuZV9wcm9qZWN0L1RDR0EtT1YvYmFtJywgInNudl9jbHVzdGVyX2RpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9wcm9qZWN0cy9JVEhfSW1tdW5lL3BhcGVyL3Jlc3VsdHMvdGFibGVzL3J1bjIvY2xvbmVzL3Nudl9jbHVzdGVyJywgImxvaGhsYV90Y2dhX291dGRpciIgPSAnL3NoYWhsYWIvYWx6aGFuZy9waXBlbGluZV9vdXRwdXRzL2l0aF9pbW11bmUvbG9oaGxhL3J1bjhfdGNnYScsICJsb2hobGFfbWlzbWF0Y2hfc2l0ZV90aHJlc2hvbGQiID0gNS4wLCAiaWNnY19zdWJ0eXBlcyIgPSAnL3NoYWhsYWIvYWx6aGFuZy9kYXRhL0lDR0MvaWNnY19wcmltYXJ5X3R1bW91cl9zdWJ0eXBlcy50c3YnLCAiYXJyYXlfZXhwcmVzc2lvbl9maWxlIiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvZGF0YS9leHByZXNzaW9uL2FycmF5L2dlbmVfZXhwcnNfcm1hX2JhdGNoX2NvcnJlY3RlZC50eHQnLCAidG90YWxfdGlsdHlwZXMiID0gYygnVF9DRDhfZGVuc2l0eScsICdUX0NENF9kZW5zaXR5JywgJ1RfQ0QyMF9kZW5zaXR5JywgJ1RfUGxhc21hX2RlbnNpdHknKSwgImljZ2Nfc3BlY2ltZW4iID0gJy9zaGFobGFiL2FsemhhbmcvZGF0YS9JQ0dDL3NwZWNpbWVuLnRzdicsICJlcGl0b3Blc191bmlxdWVfZmlsdGVyZWQiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2VwaXRvcGVzX3VuaXF1ZV9maWx0ZXJlZC50c3YnLCAiY2xvbmVfcHJldmFsZW5jZXMiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3RhYmxlcy9ydW4yL2Nsb25lcy9jbG9uZV9kYXRhLnRzdicsICJyZW1peHRfY2VsbHVsYXJpdHlfcGxvaWR5IiA9ICcvc2hhaGxhYi9hbHpoYW5nL3Byb2plY3RzL0lUSF9JbW11bmUvcGFwZXIvcmVzdWx0cy90YWJsZXMvcnVuMi9yZW1peHRfY2VsbHVsYXJpdHlfcGxvaWR5LnRzdicsICJ0aWxzX2Zvcl9jbHVzdGVyIiA9IGMoJ0VfQ0Q4X2RlbnNpdHknLCAnRV9DRDRfZGVuc2l0eScsICdFX0NEMjBfZGVuc2l0eScsICdFX1BsYXNtYV9kZW5zaXR5JywgJ1NfQ0Q4X2RlbnNpdHknLCAnU19DRDRfZGVuc2l0eScsICdTX0NEMjBfZGVuc2l0eScsICdTX1BsYXNtYV9kZW5zaXR5JyksICJ0Y3JfZGl2ZXJzaXR5IiA9ICcvc2hhaGxhYi9hbHpoYW5nL3BpcGVsaW5lX291dHB1dHMvaXRoX2ltbXVuZS9taXhjci9taXhjcl9ydW5zL2l0aF8xXzJfMy9taXhjcjUvcG9zdHByb2Nlc3MvVFJCL3Bvc3RmaWx0ZXJfZGl2ZXJzaXR5X3N0YXRzL2RpdmVyc2l0eS5zdHJpY3QucmVzYW1wbGVkLnR4dCcsICJ0YWJsZV9kaXIiID0gJy9zaGFobGFiL2FsemhhbmcvcHJvamVjdHMvSVRIX0ltbXVuZS9wYXBlci9yZXN1bHRzL3Jldmlldy90YWJsZXMvcnVuMicsICJpbWFnZV9zdW1tYXJ5IiA9ICcvc2hhaGxhYi9hbHpoYW5nL2RhdGEvaXRoaS95dWFuX2hlY3JfaW1hZ2VfcmVzdWx0cy5jc3YnKSwKICAgIHJ1bGUgPSAnY2xvbGFfaXRoX2FuYWx5c2lzJwopCiMjIyMjIyMjIE9yaWdpbmFsIHNjcmlwdCAjIyMjIyMjIyMKCiAgICAgICAgICAgICAgICAgICAgICAgIGBgYAoKCiMjIFNldHVwCgpgYGB7ciBnbG9iYWxfY2h1bmtfb3B0aW9ucywgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCB0aWR5PVRSVUUsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGNhY2hlPVRSVUUpICNjYWNoZT1UUlVFCmBgYAoKYGBge3J9CmxpYnJhcnkoaXRoaS51dGlscykKbG9hZF9iYXNlX2xpYnMoKQpsaWJyYXJ5KGl0aGkubWV0YSkKbGlicmFyeShpdGhpLmNsb25lcykKbGlicmFyeShpdGhpLmxvaGhsYSkKCmxpYnJhcnkoYXBlKQpsaWJyYXJ5KHBoeWxvYmFzZSkKbGlicmFyeShwaHl0b29scykKbGlicmFyeShpZ3JhcGgpCmBgYAoKYGBge3IsIGV2YWwgPSBUUlVFfQpjbG9uZV90cmVlX2ZpbGUgPC0gc25ha2VtYWtlQGlucHV0JGNsb25lX3RyZWVfZmlsZQpjbG9uZV9icmFuY2hfbGVuZ3RoX2ZpbGUgPC0gc25ha2VtYWtlQGlucHV0JGNsb25lX2JyYW5jaF9sZW5ndGhfZmlsZQpjbG9uZV9wcmV2YWxlbmNlX2ZpbGUgPC0gc25ha2VtYWtlQGlucHV0JGNsb25lX3ByZXZhbGVuY2VfZmlsZQpjbG9sYV9yZXN1bHRfZGlyIDwtIHNuYWtlbWFrZUBpbnB1dCRjbG9sYV9yZXN1bHRfZGlyCgpkYl9wYXRoIDwtIHNuYWtlbWFrZUBwYXJhbXMkZGIKYGBgCgpgYGB7cn0KY2xvbGFfcmVzdWx0X2ZpbGVuYW1lcyA8LSBsaXN0LmZpbGVzKGZpbGUucGF0aChjbG9sYV9yZXN1bHRfZGlyLCAiY2xvbGFfY29uZGVuc2VkX3Jlc3VsdHMiKSwgcmVjdXJzaXZlID0gVFJVRSwgZnVsbC5uYW1lcyA9IFRSVUUsIHBhdHRlcm4gPSAiY2xvbGFfcmVzdWx0cy50c3YiKQoKdHJlZV9icmFuY2hfZGF0YSA8LSByZWFkX2Nsb25lX3RyZWVfZGF0YShjbG9uZV90cmVlX2ZpbGUsIGNsb25lX2JyYW5jaF9sZW5ndGhfZmlsZSwgY2xvbmVfcHJldmFsZW5jZV9maWxlLCBkYl9wYXRoKQpub2RlX21hcHBpbmcgPC0gdHJlZV9ub2RlX21hcHBpbmcoY2xvbmVfdHJlZV9maWxlKQoKdHJlZXMgPC0gbGFwcGx5KHRyZWVfYnJhbmNoX2RhdGEsIGZ1bmN0aW9uKHgpIHgkdHJlZSkKYGBgCgojIyBBbmFseXNpcwoKT3VyIGdvYWwgaGVyZSBpcyB0byByZWNvbnN0cnVjdCB0aGUgY2xvbmFsIG9yaWdpbiBvZiBMT0hITEEuIAoKV2UndmUgcnVuIHRoZSBjbG9uYWwgTE9ISExBIChDTE9MQSkgbW9kZWwgaW4gYW5vdGhlciBwaXBlbGluZSAtLSB3ZSdsbCBqdXN0IHZpc3VhbGl6ZSB0aGUgcmVzdWx0cyBoZXJlLiAKClRoaXMgaXMgYSBsaXR0bGUgcHJlbGltaW5hcnkgc3RpbGwgLS0gc28gdGhlIExPSEhMQSwgYXMgY2FsbGVkIGluIHRoZSBmb2xsb3dpbmcgcGxvdHMsIGlzIHByZXR0eSBydWRpbWVudGFyeS4gV2UncmUganVzdCB1c2luZyB0aGUgZ2Vub3R5cGUgbW9kZSBmb3IgZWFjaCBjbG9uZSAtLSBpLmUuIHRoZSBtb3N0IGNvbW1vbiBnZW5vdHlwZSBlYWNoIGNsb25lIGlzIGFzc2lnbmVkIHRvLiBJbiBhY3R1YWxpdHksIHdlIHNob3VsZCBiZSBkb2luZyBzb21ldGhpbmcgbGlrZSBjaGVja2luZyB0aGUgOTVcJSBjb25maWRlbmNlIGludGVydmFsIG9mIGFsbGVsZSAxL2FsbGVsZSAyIGNvcHkgbnVtYmVyIHRvIGNvbmZpZGVudGx5IGNhbGwgTE9ISExBLiAKCkkgY2FuIHF1aWNrbHkgaW1wbGVtZW50IHRoYXQgd2hlbiBJIGdldCBhIGJpdCBvZiB0aW1lLiAKCmBgYHtyfQojIyBNYXAgZm9yIENOIGFuY2hvcmluZyBwYXJ0IG9mIG1vZGVsCm1vZGVsX21hcCA8LSBsaXN0KCduYic9J05lZ2F0aXZlIGJpbm9taWFsJywKICAgICAgICAgICAgICAgICAgJ211bHRfZmFjdG9yJz0nTXVsdGlwbGljYXRpdmUgZmFjdG9yIChsb2dub3JtYWwpJywKICAgICAgICAgICAgICAgICAgJ25iYmluJz0nTmVnYXRpdmUgYmlub21pYWwgKGJpbm1lZGlhbiknLAogICAgICAgICAgICAgICAgICAnc3R1ZGVudCc9J0xvZ1IgU3R1ZGVudCB0JwogICAgICAgICAgICAgICAgICApCgojIyBNYXAgZm9yIHByaW9ycyBvbiBzdGF5cmF0ZQpwcmlvcl9tYXAgPC0gbGlzdCgndHJ1bmNub3JtYWwnPSdUcnVuY2F0ZWQgbm9ybWFsJywKICAgICAgICAgICAgICAgICAgJ3VuaWZvcm0nPSdVbmlmb3JtJykKCmBgYAoKYGBge3IsIHJlc3VsdHMgPSAnYXNpcyd9CmZvciAoY2xvbGFfcmVzdWx0X2ZpbGVuYW1lIGluIGNsb2xhX3Jlc3VsdF9maWxlbmFtZXMpIHsKICBtb2RlbF90eXBlIDwtIGJhc2VuYW1lKGRpcm5hbWUoZGlybmFtZShjbG9sYV9yZXN1bHRfZmlsZW5hbWUpKSkKICBwcmlvcl90eXBlIDwtIGJhc2VuYW1lKGRpcm5hbWUoY2xvbGFfcmVzdWx0X2ZpbGVuYW1lKSkKICAKICBtb2RlbF90eXBlIDwtIG1vZGVsX21hcFtbbW9kZWxfdHlwZV1dCiAgcHJpb3JfdHlwZSA8LSBwcmlvcl9tYXBbW3ByaW9yX3R5cGVdXQogIAogIGhlYWRlcl9zdHIgPC0gcGFzdGUoIk1vZGVsIHR5cGU6ICIsIG1vZGVsX3R5cGUsICI7ICIsICJTdGF5cmF0ZSBwcmlvciB0eXBlOiAiLCBwcmlvcl90eXBlLCBzZXAgPSAiIikKICBjYXQoIiMjIyAiLCBoZWFkZXJfc3RyLCAiXG5cbiIpCiAgCiAgY2xvbGFfcmVzdWx0cyA8LSBmcmVhZChjbG9sYV9yZXN1bHRfZmlsZW5hbWUpCiAgY2xvbGFfcmVzdWx0c19zcGxpdCA8LSBzcGxpdChjbG9sYV9yZXN1bHRzLCBmPWxpc3QoY2xvbGFfcmVzdWx0cyRwYXRpZW50X2lkKSkKICBjbG9sYV9yZXN1bHRzX3JlbWFwcGVkIDwtIGxhcHBseShjbG9sYV9yZXN1bHRzX3NwbGl0LCBmdW5jdGlvbihkZikgewogICAgcGF0aWVudF9pZCA8LSBhcy5jaGFyYWN0ZXIoZGYkcGF0aWVudF9pZFsxXSkKICAgIGRmJGNsb25lX2lkIDwtIGl0aGkubWV0YTo6ZGZfYXNfbWFwKGRmID0gbm9kZV9tYXBwaW5nW1thcy5jaGFyYWN0ZXIocGF0aWVudF9pZCldXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZiRjbG9uZV9pZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZyb20gPSAiZnJvbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0byA9ICJ0byIpCiAgICBsYWJlbHMgPC0gdHJlZXNbW3BhdGllbnRfaWRdXUBsYWJlbAogICAgZGYkY2xvbmVfbmFtZSA8LSBsYWJlbHNbZGYkY2xvbmVfaWRdCiAgICByZXR1cm4oZGYpCiAgfSkgJT4lIHJiaW5kLmZpbGwKICAKICBwYXRpZW50cyA8LSB1bmlxdWUoY2xvbGFfcmVzdWx0c19yZW1hcHBlZCRwYXRpZW50X2lkKQoKICBmb3IgKHBhdCBpbiBwYXRpZW50cykgewogICAgY2F0KCIjIyMjIFBhdGllbnQgIiwgcGF0LCAiXG5cbiIpCiAgICAKICAgIGluZm8gPC0gc3Vic2V0KGNsb2xhX3Jlc3VsdHNfcmVtYXBwZWQsIHBhdGllbnRfaWQgPT0gcGF0KQogICAgaGxhX3R5cGVzIDwtIHNvcnQodW5pcXVlKGluZm8kaGxhX2xvY3VzKSkKICAgIAogICAgZm9yIChsb2N1cyBpbiBobGFfdHlwZXMpIHsKICAgICAgY2F0KCIjIyMjIyBMb2N1cyAiLCBsb2N1cywgIlxuXG4iKQogICAgICBwbG90X3RyZWUoY2xvbGFfcmVzdWx0c19yZW1hcHBlZCwgdHJlZXMsIGFzLmNoYXJhY3RlcihwYXQpLCBsb2N1cywgY29sb3VyX21vZGUgPSAibG9oOTAiKQogICAgfQogICAgY2F0KCJcbiIpCiAgfQogIAp9CmBgYAoKCgo=