library(DBI)
library(tidyverse)
library(data.table)
library(ggplot2)
library(ggbeeswarm)
con <- DBI::dbConnect(RPostgreSQL::PostgreSQL(), 
                      dbname="kooplex-ebi",
                      host = "157.181.153.9",
                      port = "6543",
                      user = "kooplex_ebi_read_user",
                      password = "secret"
)

Allele frequency of defining mutations of specific Pangolin variants

voc_data <- tbl(con, "lineage_def") %>%
  collect() %>% as.data.table()
voc_data[,.(num_mutations=.N),.(pango,description,variant_id)]

Analysis of the allele frequency distributions per mutation for each lineage

B.1.1.318

variant <- "VUI202102/04"
voc_data[variant_id==variant, .(gene, pos, ref_pos_alt,codon_change, amino_acid_change)]
variant_positions <- voc_data[variant_id==variant, pos]
n_var <- length(variant_positions)

variant_data <- tbl(con, "vcf") %>%
  filter(pos %in% variant_positions) %>%
  filter(ann_num==1) %>%
  filter(af>0.1) %>%
  inner_join(filter(tbl(con, "lineage10pct"), variant_id==variant), by = "ena_run" )%>%
  collect() %>% as.data.table()

Allele frequency distribution per mutation (AA level)

if (nrow(variant_data)>0) {
  ggplot(variant_data) + 
  geom_quasirandom(aes(x=paste0(pos,' ',hgvs_p), y=af), alpha=0.1) +
  scale_y_continuous(limits = c(0.1,1)) +
  facet_grid(. ~ gene_name, scales="free_x", space = "free_x") +
  theme_bw() +
  theme(axis.text.x = element_text(angle=45,hjust=1)) +
  labs(y="Allele frequency", x="AA variation")
}

Allele frequency distribution per mutation (nt level)

if (nrow(variant_data)>0) {
  ggplot(variant_data) + 
  geom_quasirandom(aes(x=paste0(pos,' ',ref,'>',alt), y=af), alpha=0.1) +
  scale_y_continuous(limits = c(0.1,1)) +
  facet_grid(. ~ gene_name, scales="free_x", space = "free_x") +
  theme_bw() +
  theme(axis.text.x = element_text(angle=45,hjust=1)) +
  labs(y="Allele frequency", x="nt variation")
}

Number of samples with all variant mutations as a function of AF threshold

if (nrow(variant_data)>0) {
  variant_data[,af_cat:=cut(af,seq(0,1,0.01), labels = seq(0.01,1,0.01))]
  plotdata <- variant_data[,.N,.(ena_run,af_cat)][order(af_cat,decreasing = T),.(cum_freq=cumsum(N),af_cat),.(ena_run)][cum_freq==n_var,.N,af_cat][order(af_cat, decreasing = T),.(af_cat,cum_freq=cumsum(N))]
  plotdata[,af_cat:=as.numeric(as.character(af_cat))]
  
  ggplot(plotdata) + 
    geom_point(aes(x=af_cat, y=cum_freq)) +
    scale_x_continuous(limits = c(0.1,1)) +
    theme_bw() +
    theme(axis.text.x = element_text(angle=45,hjust=1)) +
    labs(x="AF threshold",y="N_samples")
}

B.1.351

variant <- "VOC202012/02"
voc_data[variant_id==variant, .(gene, pos, ref_pos_alt,codon_change, amino_acid_change)]
variant_positions <- voc_data[variant_id==variant, pos]
n_var <- length(variant_positions)

variant_data <- tbl(con, "vcf") %>%
  filter(pos %in% variant_positions) %>%
  filter(ann_num==1) %>%
  filter(af>0.1) %>%
  inner_join(filter(tbl(con, "lineage10pct"), variant_id==variant), by = "ena_run" )%>%
  collect() %>% as.data.table()

Allele frequency distribution per mutation (AA level)

if (nrow(variant_data)>0) {
  ggplot(variant_data) + 
  geom_quasirandom(aes(x=paste0(pos,' ',hgvs_p), y=af), alpha=0.1) +
  facet_grid(. ~ gene_name, scales="free_x", space = "free_x") +
  theme_bw() +
  theme(axis.text.x = element_text(angle=45,hjust=1)) +
  labs(y="Allele frequency", x="AA variation")
}

Allele frequency distribution per mutation (nt level)

if (nrow(variant_data)>0) {
  ggplot(variant_data) + 
  geom_quasirandom(aes(x=paste0(pos,' ',ref,'>',alt), y=af), alpha=0.1) +
  facet_grid(. ~ gene_name, scales="free_x", space = "free_x") +
  theme_bw() +
  theme(axis.text.x = element_text(angle=45,hjust=1)) +
  labs(y="Allele frequency", x="nt variation")
}

Number of samples with all variant mutations as a function of AF threshold

if (nrow(variant_data)>0) {
  variant_data[,af_cat:=cut(af,seq(0,1,0.01), labels = seq(0.01,1,0.01))]
  plotdata <- variant_data[,.N,.(ena_run,af_cat)][order(af_cat,decreasing = T),.(cum_freq=cumsum(N),af_cat),.(ena_run)][cum_freq==n_var,.N,af_cat][order(af_cat, decreasing = T),.(af_cat,cum_freq=cumsum(N))]
  plotdata[,af_cat:=as.numeric(as.character(af_cat))]
  
  ggplot(plotdata) + 
    geom_point(aes(x=af_cat, y=cum_freq)) + 
    theme_bw() +
    theme(axis.text.x = element_text(angle=45,hjust=1)) +
    labs(x="AF threshold",y="N_samples")
}

A.23.1

variant <- "VUI202102/01"
voc_data[variant_id==variant, .(gene, pos, ref_pos_alt,codon_change, amino_acid_change)]
variant_positions <- voc_data[variant_id==variant, pos]
n_var <- length(variant_positions)

variant_data <- tbl(con, "vcf") %>%
  filter(pos %in% variant_positions) %>%
  filter(ann_num==1) %>%
  filter(af>0.1) %>%
  inner_join(filter(tbl(con, "lineage10pct"), variant_id==variant), by = "ena_run" )%>%
  collect() %>% as.data.table()

Allele frequency distribution per mutation (AA level)

if (nrow(variant_data)>0) {
  ggplot(variant_data) + 
  geom_quasirandom(aes(x=paste0(pos,' ',hgvs_p), y=af), alpha=0.1) +
  facet_grid(. ~ gene_name, scales="free_x", space = "free_x") +
  theme_bw() +
  theme(axis.text.x = element_text(angle=45,hjust=1)) +
  labs(y="Allele frequency", x="AA variation")
}

Allele frequency distribution per mutation (nt level)

if (nrow(variant_data)>0) {
  ggplot(variant_data) + 
  geom_quasirandom(aes(x=paste0(pos,' ',ref,'>',alt), y=af), alpha=0.1) +
  facet_grid(. ~ gene_name, scales="free_x", space = "free_x") +
  theme_bw() +
  theme(axis.text.x = element_text(angle=45,hjust=1)) +
  labs(y="Allele frequency", x="nt variation")
}

Number of samples with all variant mutations as a function of AF threshold

if (nrow(variant_data)>0) {
  variant_data[,af_cat:=cut(af,seq(0,1,0.01), labels = seq(0.01,1,0.01))]
  plotdata <- variant_data[,.N,.(ena_run,af_cat)][order(af_cat,decreasing = T),.(cum_freq=cumsum(N),af_cat),.(ena_run)][cum_freq==n_var,.N,af_cat][order(af_cat, decreasing = T),.(af_cat,cum_freq=cumsum(N))]
  plotdata[,af_cat:=as.numeric(as.character(af_cat))]
  
  ggplot(plotdata) + 
    geom_point(aes(x=af_cat, y=cum_freq)) + 
    theme_bw() +
    theme(axis.text.x = element_text(angle=45,hjust=1)) +
    labs(x="AF threshold",y="N_samples")
}

B.1.324.1

variant <- "VUI202103/01"
voc_data[variant_id==variant, .(gene, pos, ref_pos_alt,codon_change, amino_acid_change)]
variant_positions <- voc_data[variant_id==variant, pos]
n_var <- length(variant_positions)

variant_data <- tbl(con, "vcf") %>%
  filter(pos %in% variant_positions) %>%
  filter(ann_num==1) %>%
  filter(af>0.1) %>%
  inner_join(filter(tbl(con, "lineage10pct"), variant_id==variant), by = "ena_run" )%>%
  collect() %>% as.data.table()

Allele frequency distribution per mutation (AA level)

if (nrow(variant_data)>0) {
  ggplot(variant_data) + 
  geom_quasirandom(aes(x=paste0(pos,' ',hgvs_p), y=af), alpha=0.1) +
  facet_grid(. ~ gene_name, scales="free_x", space = "free_x") +
  theme_bw() +
  theme(axis.text.x = element_text(angle=45,hjust=1)) +
  labs(y="Allele frequency", x="AA variation")
}

Allele frequency distribution per mutation (nt level)

if (nrow(variant_data)>0) {
  ggplot(variant_data) + 
  geom_quasirandom(aes(x=paste0(pos,' ',ref,'>',alt), y=af), alpha=0.1) +
  facet_grid(. ~ gene_name, scales="free_x", space = "free_x") +
  theme_bw() +
  theme(axis.text.x = element_text(angle=45,hjust=1)) +
  labs(y="Allele frequency", x="nt variation")
}

Number of samples with all variant mutations as a function of AF threshold

if (nrow(variant_data)>0) {
  variant_data[,af_cat:=cut(af,seq(0,1,0.01), labels = seq(0.01,1,0.01))]
  plotdata <- variant_data[,.N,.(ena_run,af_cat)][order(af_cat,decreasing = T),.(cum_freq=cumsum(N),af_cat),.(ena_run)][cum_freq==n_var,.N,af_cat][order(af_cat, decreasing = T),.(af_cat,cum_freq=cumsum(N))]
  plotdata[,af_cat:=as.numeric(as.character(af_cat))]
  
  ggplot(plotdata) + 
    geom_point(aes(x=af_cat, y=cum_freq)) + 
    theme_bw() +
    theme(axis.text.x = element_text(angle=45,hjust=1)) +
    labs(x="AF threshold",y="N_samples")
}

B.1.1.7

variant <- "VOC202012/01"
voc_data[variant_id==variant, .(gene, pos, ref_pos_alt,codon_change, amino_acid_change)]
variant_positions <- voc_data[variant_id==variant, pos]
n_var <- length(variant_positions)

variant_data <- tbl(con, "vcf") %>%
  filter(pos %in% variant_positions) %>%
  filter(ann_num==1) %>%
  filter(af>0.1) %>%
  inner_join(filter(tbl(con, "lineage10pct"), variant_id==variant), by = "ena_run" )%>%
  collect() %>% as.data.table()

Allele frequency distribution per mutation (AA level)

if (nrow(variant_data)>0) {
  ggplot(variant_data) + 
  geom_quasirandom(aes(x=paste0(pos,' ',hgvs_p), y=af), alpha=0.1) +
  facet_grid(. ~ gene_name, scales="free_x", space = "free_x") +
  theme_bw() +
  theme(axis.text.x = element_text(angle=45,hjust=1)) +
  labs(y="Allele frequency", x="AA variation")
}

Allele frequency distribution per mutation (nt level)

if (nrow(variant_data)>0) {
  ggplot(variant_data) + 
  geom_quasirandom(aes(x=paste0(pos,' ',ref,'>',alt), y=af), alpha=0.1) +
  facet_grid(. ~ gene_name, scales="free_x", space = "free_x") +
  theme_bw() +
  theme(axis.text.x = element_text(angle=45,hjust=1)) +
  labs(y="Allele frequency", x="nt variation")
}

Number of samples with all variant mutations as a function of AF threshold

if (nrow(variant_data)>0) {
  variant_data[,af_cat:=cut(af,seq(0,1,0.01), labels = seq(0.01,1,0.01))]
  plotdata <- variant_data[,.N,.(ena_run,af_cat)][order(af_cat,decreasing = T),.(cum_freq=cumsum(N),af_cat),.(ena_run)][cum_freq==n_var,.N,af_cat][order(af_cat, decreasing = T),.(af_cat,cum_freq=cumsum(N))]
  plotdata[,af_cat:=as.numeric(as.character(af_cat))]
  
  ggplot(plotdata) + 
    geom_point(aes(x=af_cat, y=cum_freq)) + 
    theme_bw() +
    theme(axis.text.x = element_text(angle=45,hjust=1)) +
    labs(x="AF threshold",y="N_samples")
}

B.1.525

variant <- "VUI202102/03"
voc_data[variant_id==variant, .(gene, pos, ref_pos_alt,codon_change, amino_acid_change)]
variant_positions <- voc_data[variant_id==variant, pos]
n_var <- length(variant_positions)

variant_data <- tbl(con, "vcf") %>%
  filter(pos %in% variant_positions) %>%
  filter(ann_num==1) %>%
  filter(af>0.1) %>%
  inner_join(filter(tbl(con, "lineage10pct"), variant_id==variant), by = "ena_run" )%>%
  collect() %>% as.data.table()

Allele frequency distribution per mutation (AA level)

if (nrow(variant_data)>0) {
  ggplot(variant_data) + 
  geom_quasirandom(aes(x=paste0(pos,' ',hgvs_p), y=af), alpha=0.1) +
  facet_grid(. ~ gene_name, scales="free_x", space = "free_x") +
  theme_bw() +
  theme(axis.text.x = element_text(angle=45,hjust=1)) +
  labs(y="Allele frequency", x="AA variation")
}

Allele frequency distribution per mutation (nt level)

if (nrow(variant_data)>0) {
  ggplot(variant_data) + 
  geom_quasirandom(aes(x=paste0(pos,' ',ref,'>',alt), y=af), alpha=0.1) +
  facet_grid(. ~ gene_name, scales="free_x", space = "free_x") +
  theme_bw() +
  theme(axis.text.x = element_text(angle=45,hjust=1)) +
  labs(y="Allele frequency", x="nt variation")
}

Number of samples with all variant mutations as a function of AF threshold

if (nrow(variant_data)>0) {
  variant_data[,af_cat:=cut(af,seq(0,1,0.01), labels = seq(0.01,1,0.01))]
  plotdata <- variant_data[,.N,.(ena_run,af_cat)][order(af_cat,decreasing = T),.(cum_freq=cumsum(N),af_cat),.(ena_run)][cum_freq==n_var,.N,af_cat][order(af_cat, decreasing = T),.(af_cat,cum_freq=cumsum(N))]
  plotdata[,af_cat:=as.numeric(as.character(af_cat))]
  
  ggplot(plotdata) + 
    geom_point(aes(x=af_cat, y=cum_freq)) + 
    theme_bw() +
    theme(axis.text.x = element_text(angle=45,hjust=1)) +
    labs(x="AF threshold",y="N_samples")
}

B.1.617

variant <- "India"
voc_data[variant_id==variant, .(gene, pos, ref_pos_alt,codon_change, amino_acid_change)]
variant_positions <- voc_data[variant_id==variant, pos]
n_var <- length(variant_positions)

variant_data <- tbl(con, "vcf") %>%
  filter(pos %in% variant_positions) %>%
  filter(ann_num==1) %>%
  filter(af>0.1) %>%
  inner_join(filter(tbl(con, "lineage10pct"), variant_id==variant), by = "ena_run" )%>%
  collect() %>% as.data.table()

Allele frequency distribution per mutation (AA level)

if (nrow(variant_data)>0) {
  ggplot(variant_data) + 
  geom_quasirandom(aes(x=paste0(pos,' ',hgvs_p), y=af), alpha=0.1) +
  facet_grid(. ~ gene_name, scales="free_x", space = "free_x") +
  theme_bw() +
  theme(axis.text.x = element_text(angle=45,hjust=1)) +
  labs(y="Allele frequency", x="AA variation")
}

Allele frequency distribution per mutation (nt level)

if (nrow(variant_data)>0) {
  ggplot(variant_data) + 
  geom_quasirandom(aes(x=paste0(pos,' ',ref,'>',alt), y=af), alpha=0.1) +
  facet_grid(. ~ gene_name, scales="free_x", space = "free_x") +
  theme_bw() +
  theme(axis.text.x = element_text(angle=45,hjust=1)) +
  labs(y="Allele frequency", x="nt variation")
}

Number of samples with all variant mutations as a function of AF threshold

if (nrow(variant_data)>0) {
  variant_data[,af_cat:=cut(af,seq(0,1,0.01), labels = seq(0.01,1,0.01))]
  plotdata <- variant_data[,.N,.(ena_run,af_cat)][order(af_cat,decreasing = T),.(cum_freq=cumsum(N),af_cat),.(ena_run)][cum_freq==n_var,.N,af_cat][order(af_cat, decreasing = T),.(af_cat,cum_freq=cumsum(N))]
  plotdata[,af_cat:=as.numeric(as.character(af_cat))]
  
  ggplot(plotdata) + 
    geom_point(aes(x=af_cat, y=cum_freq)) + 
    theme_bw() +
    theme(axis.text.x = element_text(angle=45,hjust=1)) +
    labs(x="AF threshold",y="N_samples")
}

P.2

variant <- "VUI202101/01"
voc_data[variant_id==variant, .(gene, pos, ref_pos_alt,codon_change, amino_acid_change)]
variant_positions <- voc_data[variant_id==variant, pos]
n_var <- length(variant_positions)

variant_data <- tbl(con, "vcf") %>%
  filter(pos %in% variant_positions) %>%
  filter(ann_num==1) %>%
  filter(af>0.1) %>%
  inner_join(filter(tbl(con, "lineage10pct"), variant_id==variant), by = "ena_run" )%>%
  collect() %>% as.data.table()

Allele frequency distribution per mutation (AA level)

if (nrow(variant_data)>0) {
  ggplot(variant_data) + 
  geom_quasirandom(aes(x=paste0(pos,' ',hgvs_p), y=af), alpha=0.1) +
  facet_grid(. ~ gene_name, scales="free_x", space = "free_x") +
  theme_bw() +
  theme(axis.text.x = element_text(angle=45,hjust=1)) +
  labs(y="Allele frequency", x="AA variation")
}

Allele frequency distribution per mutation (nt level)

if (nrow(variant_data)>0) {
  ggplot(variant_data) + 
  geom_quasirandom(aes(x=paste0(pos,' ',ref,'>',alt), y=af), alpha=0.1) +
  facet_grid(. ~ gene_name, scales="free_x", space = "free_x") +
  theme_bw() +
  theme(axis.text.x = element_text(angle=45,hjust=1)) +
  labs(y="Allele frequency", x="nt variation")
}

Number of samples with all variant mutations as a function of AF threshold

if (nrow(variant_data)>0) {
  variant_data[,af_cat:=cut(af,seq(0,1,0.01), labels = seq(0.01,1,0.01))]
  plotdata <- variant_data[,.N,.(ena_run,af_cat)][order(af_cat,decreasing = T),.(cum_freq=cumsum(N),af_cat),.(ena_run)][cum_freq==n_var,.N,af_cat][order(af_cat, decreasing = T),.(af_cat,cum_freq=cumsum(N))]
  plotdata[,af_cat:=as.numeric(as.character(af_cat))]
  
  ggplot(plotdata) + 
    geom_point(aes(x=af_cat, y=cum_freq)) + 
    theme_bw() +
    theme(axis.text.x = element_text(angle=45,hjust=1)) +
    labs(x="AF threshold",y="N_samples")
}

P.3

variant <- "VUI202103/02"
voc_data[variant_id==variant, .(gene, pos, ref_pos_alt,codon_change, amino_acid_change)]
variant_positions <- voc_data[variant_id==variant, pos]
n_var <- length(variant_positions)

variant_data <- tbl(con, "vcf") %>%
  filter(pos %in% variant_positions) %>%
  filter(ann_num==1) %>%
  filter(af>0.1) %>%
  inner_join(filter(tbl(con, "lineage10pct"), variant_id==variant), by = "ena_run" )%>%
  collect() %>% as.data.table()

Allele frequency distribution per mutation (AA level)

if (nrow(variant_data)>0) {
  ggplot(variant_data) + 
  geom_quasirandom(aes(x=paste0(pos,' ',hgvs_p), y=af), alpha=0.1) +
  scale_y_continuous(limits = c(0.1,1)) +
  facet_grid(. ~ gene_name, scales="free_x", space = "free_x") +
  theme_bw() +
  theme(axis.text.x = element_text(angle=45,hjust=1)) +
  labs(y="Allele frequency", x="AA variation")
}

Allele frequency distribution per mutation (nt level)

if (nrow(variant_data)>0) {
  ggplot(variant_data) + 
  geom_quasirandom(aes(x=paste0(pos,' ',ref,'>',alt), y=af), alpha=0.1) +
  scale_y_continuous(limits = c(0.1,1)) +
  facet_grid(. ~ gene_name, scales="free_x", space = "free_x") +
  theme_bw() +
  theme(axis.text.x = element_text(angle=45,hjust=1)) +
  labs(y="Allele frequency", x="nt variation")
}

Number of samples with all variant mutations as a function of AF threshold

if (nrow(variant_data)>0) {
  variant_data[,af_cat:=cut(af,seq(0,1,0.01), labels = seq(0.01,1,0.01))]
  plotdata <- variant_data[,.N,.(ena_run,af_cat)][order(af_cat,decreasing = T),.(cum_freq=cumsum(N),af_cat),.(ena_run)][cum_freq==n_var,.N,af_cat][order(af_cat, decreasing = T),.(af_cat,cum_freq=cumsum(N))]
  plotdata[,af_cat:=as.numeric(as.character(af_cat))]
  
  ggplot(plotdata) + 
    geom_point(aes(x=af_cat, y=cum_freq)) + 
    scale_x_continuous(limits = c(0.1,1)) +
    theme_bw() +
    theme(axis.text.x = element_text(angle=45,hjust=1)) +
    labs(x="AF threshold",y="N_samples")
}

P.1

variant <- "VOC202101/02"
voc_data[variant_id==variant, .(gene, pos, ref_pos_alt,codon_change, amino_acid_change)]
variant_positions <- voc_data[variant_id==variant, pos]
n_var <- length(variant_positions)

variant_data <- tbl(con, "vcf") %>%
  filter(pos %in% variant_positions) %>%
  filter(ann_num==1) %>%
  filter(af>0.1) %>%
  inner_join(filter(tbl(con, "lineage10pct"), variant_id==variant), by = "ena_run" )%>%
  collect() %>% as.data.table()

Allele frequency distribution per mutation (AA level)

if (nrow(variant_data)>0) {
  ggplot(variant_data) + 
  geom_quasirandom(aes(x=paste0(pos,' ',hgvs_p), y=af), alpha=0.1) +
  facet_grid(. ~ gene_name, scales="free_x", space = "free_x") +
  theme_bw() +
  theme(axis.text.x = element_text(angle=45,hjust=1)) +
  labs(y="Allele frequency", x="AA variation")
}

Allele frequency distribution per mutation (nt level)

if (nrow(variant_data)>0) {
  ggplot(variant_data) + 
  geom_quasirandom(aes(x=paste0(pos,' ',ref,'>',alt), y=af), alpha=0.1) +
  facet_grid(. ~ gene_name, scales="free_x", space = "free_x") +
  theme_bw() +
  theme(axis.text.x = element_text(angle=45,hjust=1)) +
  labs(y="Allele frequency", x="nt variation")
}

Number of samples with all variant mutations as a function of AF threshold

if (nrow(variant_data)>0) {
  variant_data[,af_cat:=cut(af,seq(0,1,0.01), labels = seq(0.01,1,0.01))]
  plotdata <- variant_data[,.N,.(ena_run,af_cat)][order(af_cat,decreasing = T),.(cum_freq=cumsum(N),af_cat),.(ena_run)][cum_freq==n_var,.N,af_cat][order(af_cat, decreasing = T),.(af_cat,cum_freq=cumsum(N))]
  plotdata[,af_cat:=as.numeric(as.character(af_cat))]
  
  ggplot(plotdata) + 
    geom_point(aes(x=af_cat, y=cum_freq)) + 
    theme_bw() +
    theme(axis.text.x = element_text(angle=45,hjust=1)) +
    labs(x="AF threshold",y="N_samples")
}

B.1.1.7 + E484K

variant <- "VOC202102/02"
voc_data[variant_id==variant, .(gene, pos, ref_pos_alt,codon_change, amino_acid_change)]
variant_positions <- voc_data[variant_id==variant, pos]
n_var <- length(variant_positions)

variant_data <- tbl(con, "vcf") %>%
  filter(pos %in% variant_positions) %>%
  filter(ann_num==1) %>%
  filter(af>0.1) %>%
  inner_join(filter(tbl(con, "lineage10pct"), variant_id==variant), by = "ena_run" )%>%
  collect() %>% as.data.table()

Allele frequency distribution per mutation (AA level)

if (nrow(variant_data)>0) {
  ggplot(variant_data) + 
  geom_quasirandom(aes(x=paste0(pos,' ',hgvs_p), y=af), alpha=0.1) +
  scale_y_continuous(limits = c(0.1,1)) +
  facet_grid(. ~ gene_name, scales="free_x", space = "free_x") +
  theme_bw() +
  theme(axis.text.x = element_text(angle=45,hjust=1)) +
  labs(y="Allele frequency", x="AA variation")
}

Allele frequency distribution per mutation (nt level)

if (nrow(variant_data)>0) {
  ggplot(variant_data) + 
  geom_quasirandom(aes(x=paste0(pos,' ',ref,'>',alt), y=af), alpha=0.1) +
  scale_y_continuous(limits = c(0.1,1)) +
  facet_grid(. ~ gene_name, scales="free_x", space = "free_x") +
  theme_bw() +
  theme(axis.text.x = element_text(angle=45,hjust=1)) +
  labs(y="Allele frequency", x="nt variation")
}

Number of samples with all variant mutations as a function of AF threshold

if (nrow(variant_data)>0) {
  variant_data[,af_cat:=cut(af,seq(0,1,0.01), labels = seq(0.01,1,0.01))]
  plotdata <- variant_data[,.N,.(ena_run,af_cat)][order(af_cat,decreasing = T),.(cum_freq=cumsum(N),af_cat),.(ena_run)][cum_freq==n_var,.N,af_cat][order(af_cat, decreasing = T),.(af_cat,cum_freq=cumsum(N))]
  plotdata[,af_cat:=as.numeric(as.character(af_cat))]
  
  ggplot(plotdata) + 
    geom_point(aes(x=af_cat, y=cum_freq)) + 
    scale_x_continuous(limits = c(0,1)) +
    theme_bw() +
    theme(axis.text.x = element_text(angle=45,hjust=1)) +
    labs(x="AF threshold",y="N_samples")
}

LS0tCnRpdGxlOiAiQWxsZWxlIGZyZXF1ZW5jeSB0aHJlc2hvbGQgYW5hbHlzaXMiCm91dHB1dDogaHRtbF9ub3RlYm9vawphdXRob3JzOiBEYXZpZCBGLiBOaWV1d2VuaHVpanNlCi0tLQoKYGBge3J9CmxpYnJhcnkoREJJKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShkYXRhLnRhYmxlKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZ2diZWVzd2FybSkKYGBgCgoKYGBge3J9CmNvbiA8LSBEQkk6OmRiQ29ubmVjdChSUG9zdGdyZVNRTDo6UG9zdGdyZVNRTCgpLCAKICAgICAgICAgICAgICAgICAgICAgIGRibmFtZT0ia29vcGxleC1lYmkiLAogICAgICAgICAgICAgICAgICAgICAgaG9zdCA9ICIxNTcuMTgxLjE1My45IiwKICAgICAgICAgICAgICAgICAgICAgIHBvcnQgPSAiNjU0MyIsCiAgICAgICAgICAgICAgICAgICAgICB1c2VyID0gImtvb3BsZXhfZWJpX3JlYWRfdXNlciIsCiAgICAgICAgICAgICAgICAgICAgICBwYXNzd29yZCA9ICJzZWNyZXQiCikKYGBgCgojIEFsbGVsZSBmcmVxdWVuY3kgb2YgZGVmaW5pbmcgbXV0YXRpb25zIG9mIHNwZWNpZmljIFBhbmdvbGluIHZhcmlhbnRzCmBgYHtyfQp2b2NfZGF0YSA8LSB0YmwoY29uLCAibGluZWFnZV9kZWYiKSAlPiUKICBjb2xsZWN0KCkgJT4lIGFzLmRhdGEudGFibGUoKQp2b2NfZGF0YVssLihudW1fbXV0YXRpb25zPS5OKSwuKHBhbmdvLGRlc2NyaXB0aW9uLHZhcmlhbnRfaWQpXQpgYGAKCiMgQW5hbHlzaXMgb2YgdGhlIGFsbGVsZSBmcmVxdWVuY3kgZGlzdHJpYnV0aW9ucyBwZXIgbXV0YXRpb24gZm9yIGVhY2ggbGluZWFnZQoKIyMgQi4xLjEuMzE4CmBgYHtyfQp2YXJpYW50IDwtICJWVUkyMDIxMDIvMDQiCmBgYAoKYGBge3J9CnZvY19kYXRhW3ZhcmlhbnRfaWQ9PXZhcmlhbnQsIC4oZ2VuZSwgcG9zLCByZWZfcG9zX2FsdCxjb2Rvbl9jaGFuZ2UsIGFtaW5vX2FjaWRfY2hhbmdlKV0KYGBgCgpgYGB7cn0KdmFyaWFudF9wb3NpdGlvbnMgPC0gdm9jX2RhdGFbdmFyaWFudF9pZD09dmFyaWFudCwgcG9zXQpuX3ZhciA8LSBsZW5ndGgodmFyaWFudF9wb3NpdGlvbnMpCgp2YXJpYW50X2RhdGEgPC0gdGJsKGNvbiwgInZjZiIpICU+JQogIGZpbHRlcihwb3MgJWluJSB2YXJpYW50X3Bvc2l0aW9ucykgJT4lCiAgZmlsdGVyKGFubl9udW09PTEpICU+JQogIGZpbHRlcihhZj4wLjEpICU+JQogIGlubmVyX2pvaW4oZmlsdGVyKHRibChjb24sICJsaW5lYWdlMTBwY3QiKSwgdmFyaWFudF9pZD09dmFyaWFudCksIGJ5ID0gImVuYV9ydW4iICklPiUKICBjb2xsZWN0KCkgJT4lIGFzLmRhdGEudGFibGUoKQpgYGAKCiMjIyBBbGxlbGUgZnJlcXVlbmN5IGRpc3RyaWJ1dGlvbiBwZXIgbXV0YXRpb24gKEFBIGxldmVsKQpgYGB7cn0KaWYgKG5yb3codmFyaWFudF9kYXRhKT4wKSB7CiAgZ2dwbG90KHZhcmlhbnRfZGF0YSkgKyAKICBnZW9tX3F1YXNpcmFuZG9tKGFlcyh4PXBhc3RlMChwb3MsJyAnLGhndnNfcCksIHk9YWYpLCBhbHBoYT0wLjEpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLjEsMSkpICsKICBmYWNldF9ncmlkKC4gfiBnZW5lX25hbWUsIHNjYWxlcz0iZnJlZV94Iiwgc3BhY2UgPSAiZnJlZV94IikgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LGhqdXN0PTEpKSArCiAgbGFicyh5PSJBbGxlbGUgZnJlcXVlbmN5IiwgeD0iQUEgdmFyaWF0aW9uIikKfQpgYGAKCiMjIyBBbGxlbGUgZnJlcXVlbmN5IGRpc3RyaWJ1dGlvbiBwZXIgbXV0YXRpb24gKG50IGxldmVsKQpgYGB7cn0KaWYgKG5yb3codmFyaWFudF9kYXRhKT4wKSB7CiAgZ2dwbG90KHZhcmlhbnRfZGF0YSkgKyAKICBnZW9tX3F1YXNpcmFuZG9tKGFlcyh4PXBhc3RlMChwb3MsJyAnLHJlZiwnPicsYWx0KSwgeT1hZiksIGFscGhhPTAuMSkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAuMSwxKSkgKwogIGZhY2V0X2dyaWQoLiB+IGdlbmVfbmFtZSwgc2NhbGVzPSJmcmVlX3giLCBzcGFjZSA9ICJmcmVlX3giKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUsaGp1c3Q9MSkpICsKICBsYWJzKHk9IkFsbGVsZSBmcmVxdWVuY3kiLCB4PSJudCB2YXJpYXRpb24iKQp9CmBgYAoKIyMjIE51bWJlciBvZiBzYW1wbGVzIHdpdGggYWxsIHZhcmlhbnQgbXV0YXRpb25zIGFzIGEgZnVuY3Rpb24gb2YgQUYgdGhyZXNob2xkCmBgYHtyfQppZiAobnJvdyh2YXJpYW50X2RhdGEpPjApIHsKICB2YXJpYW50X2RhdGFbLGFmX2NhdDo9Y3V0KGFmLHNlcSgwLDEsMC4wMSksIGxhYmVscyA9IHNlcSgwLjAxLDEsMC4wMSkpXQogIHBsb3RkYXRhIDwtIHZhcmlhbnRfZGF0YVssLk4sLihlbmFfcnVuLGFmX2NhdCldW29yZGVyKGFmX2NhdCxkZWNyZWFzaW5nID0gVCksLihjdW1fZnJlcT1jdW1zdW0oTiksYWZfY2F0KSwuKGVuYV9ydW4pXVtjdW1fZnJlcT09bl92YXIsLk4sYWZfY2F0XVtvcmRlcihhZl9jYXQsIGRlY3JlYXNpbmcgPSBUKSwuKGFmX2NhdCxjdW1fZnJlcT1jdW1zdW0oTikpXQogIHBsb3RkYXRhWyxhZl9jYXQ6PWFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGFmX2NhdCkpXQogIAogIGdncGxvdChwbG90ZGF0YSkgKyAKICAgIGdlb21fcG9pbnQoYWVzKHg9YWZfY2F0LCB5PWN1bV9mcmVxKSkgKwogICAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMC4xLDEpKSArCiAgICB0aGVtZV9idygpICsKICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LGhqdXN0PTEpKSArCiAgICBsYWJzKHg9IkFGIHRocmVzaG9sZCIseT0iTl9zYW1wbGVzIikKfQpgYGAKCiMjIEIuMS4zNTEKYGBge3J9CnZhcmlhbnQgPC0gIlZPQzIwMjAxMi8wMiIKYGBgCgpgYGB7cn0Kdm9jX2RhdGFbdmFyaWFudF9pZD09dmFyaWFudCwgLihnZW5lLCBwb3MsIHJlZl9wb3NfYWx0LGNvZG9uX2NoYW5nZSwgYW1pbm9fYWNpZF9jaGFuZ2UpXQpgYGAKCmBgYHtyfQp2YXJpYW50X3Bvc2l0aW9ucyA8LSB2b2NfZGF0YVt2YXJpYW50X2lkPT12YXJpYW50LCBwb3NdCm5fdmFyIDwtIGxlbmd0aCh2YXJpYW50X3Bvc2l0aW9ucykKCnZhcmlhbnRfZGF0YSA8LSB0YmwoY29uLCAidmNmIikgJT4lCiAgZmlsdGVyKHBvcyAlaW4lIHZhcmlhbnRfcG9zaXRpb25zKSAlPiUKICBmaWx0ZXIoYW5uX251bT09MSkgJT4lCiAgZmlsdGVyKGFmPjAuMSkgJT4lCiAgaW5uZXJfam9pbihmaWx0ZXIodGJsKGNvbiwgImxpbmVhZ2UxMHBjdCIpLCB2YXJpYW50X2lkPT12YXJpYW50KSwgYnkgPSAiZW5hX3J1biIgKSU+JQogIGNvbGxlY3QoKSAlPiUgYXMuZGF0YS50YWJsZSgpCmBgYAoKIyMjIEFsbGVsZSBmcmVxdWVuY3kgZGlzdHJpYnV0aW9uIHBlciBtdXRhdGlvbiAoQUEgbGV2ZWwpCmBgYHtyfQppZiAobnJvdyh2YXJpYW50X2RhdGEpPjApIHsKICBnZ3Bsb3QodmFyaWFudF9kYXRhKSArIAogIGdlb21fcXVhc2lyYW5kb20oYWVzKHg9cGFzdGUwKHBvcywnICcsaGd2c19wKSwgeT1hZiksIGFscGhhPTAuMSkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAuMSwxKSkgKwogIGZhY2V0X2dyaWQoLiB+IGdlbmVfbmFtZSwgc2NhbGVzPSJmcmVlX3giLCBzcGFjZSA9ICJmcmVlX3giKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUsaGp1c3Q9MSkpICsKICBsYWJzKHk9IkFsbGVsZSBmcmVxdWVuY3kiLCB4PSJBQSB2YXJpYXRpb24iKQp9CmBgYAoKIyMjIEFsbGVsZSBmcmVxdWVuY3kgZGlzdHJpYnV0aW9uIHBlciBtdXRhdGlvbiAobnQgbGV2ZWwpCmBgYHtyfQppZiAobnJvdyh2YXJpYW50X2RhdGEpPjApIHsKICBnZ3Bsb3QodmFyaWFudF9kYXRhKSArIAogIGdlb21fcXVhc2lyYW5kb20oYWVzKHg9cGFzdGUwKHBvcywnICcscmVmLCc+JyxhbHQpLCB5PWFmKSwgYWxwaGE9MC4xKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMC4xLDEpKSArCiAgZmFjZXRfZ3JpZCguIH4gZ2VuZV9uYW1lLCBzY2FsZXM9ImZyZWVfeCIsIHNwYWNlID0gImZyZWVfeCIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT00NSxoanVzdD0xKSkgKwogIGxhYnMoeT0iQWxsZWxlIGZyZXF1ZW5jeSIsIHg9Im50IHZhcmlhdGlvbiIpCn0KYGBgCgojIyMgTnVtYmVyIG9mIHNhbXBsZXMgd2l0aCBhbGwgdmFyaWFudCBtdXRhdGlvbnMgYXMgYSBmdW5jdGlvbiBvZiBBRiB0aHJlc2hvbGQKYGBge3J9CmlmIChucm93KHZhcmlhbnRfZGF0YSk+MCkgewogIHZhcmlhbnRfZGF0YVssYWZfY2F0Oj1jdXQoYWYsc2VxKDAsMSwwLjAxKSwgbGFiZWxzID0gc2VxKDAuMDEsMSwwLjAxKSldCiAgcGxvdGRhdGEgPC0gdmFyaWFudF9kYXRhWywuTiwuKGVuYV9ydW4sYWZfY2F0KV1bb3JkZXIoYWZfY2F0LGRlY3JlYXNpbmcgPSBUKSwuKGN1bV9mcmVxPWN1bXN1bShOKSxhZl9jYXQpLC4oZW5hX3J1bildW2N1bV9mcmVxPT1uX3ZhciwuTixhZl9jYXRdW29yZGVyKGFmX2NhdCwgZGVjcmVhc2luZyA9IFQpLC4oYWZfY2F0LGN1bV9mcmVxPWN1bXN1bShOKSldCiAgcGxvdGRhdGFbLGFmX2NhdDo9YXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoYWZfY2F0KSldCiAgCiAgZ2dwbG90KHBsb3RkYXRhKSArIAogICAgZ2VvbV9wb2ludChhZXMoeD1hZl9jYXQsIHk9Y3VtX2ZyZXEpKSArCiAgICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLjEsMSkpICsKICAgIHRoZW1lX2J3KCkgKwogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUsaGp1c3Q9MSkpICsKICAgIGxhYnMoeD0iQUYgdGhyZXNob2xkIix5PSJOX3NhbXBsZXMiKQp9CmBgYAoKIyMgQS4yMy4xCmBgYHtyfQp2YXJpYW50IDwtICJWVUkyMDIxMDIvMDEiCmBgYAoKYGBge3J9CnZvY19kYXRhW3ZhcmlhbnRfaWQ9PXZhcmlhbnQsIC4oZ2VuZSwgcG9zLCByZWZfcG9zX2FsdCxjb2Rvbl9jaGFuZ2UsIGFtaW5vX2FjaWRfY2hhbmdlKV0KYGBgCgpgYGB7cn0KdmFyaWFudF9wb3NpdGlvbnMgPC0gdm9jX2RhdGFbdmFyaWFudF9pZD09dmFyaWFudCwgcG9zXQpuX3ZhciA8LSBsZW5ndGgodmFyaWFudF9wb3NpdGlvbnMpCgp2YXJpYW50X2RhdGEgPC0gdGJsKGNvbiwgInZjZiIpICU+JQogIGZpbHRlcihwb3MgJWluJSB2YXJpYW50X3Bvc2l0aW9ucykgJT4lCiAgZmlsdGVyKGFubl9udW09PTEpICU+JQogIGZpbHRlcihhZj4wLjEpICU+JQogIGlubmVyX2pvaW4oZmlsdGVyKHRibChjb24sICJsaW5lYWdlMTBwY3QiKSwgdmFyaWFudF9pZD09dmFyaWFudCksIGJ5ID0gImVuYV9ydW4iICklPiUKICBjb2xsZWN0KCkgJT4lIGFzLmRhdGEudGFibGUoKQpgYGAKCiMjIyBBbGxlbGUgZnJlcXVlbmN5IGRpc3RyaWJ1dGlvbiBwZXIgbXV0YXRpb24gKEFBIGxldmVsKQpgYGB7cn0KaWYgKG5yb3codmFyaWFudF9kYXRhKT4wKSB7CiAgZ2dwbG90KHZhcmlhbnRfZGF0YSkgKyAKICBnZW9tX3F1YXNpcmFuZG9tKGFlcyh4PXBhc3RlMChwb3MsJyAnLGhndnNfcCksIHk9YWYpLCBhbHBoYT0wLjEpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLjEsMSkpICsKICBmYWNldF9ncmlkKC4gfiBnZW5lX25hbWUsIHNjYWxlcz0iZnJlZV94Iiwgc3BhY2UgPSAiZnJlZV94IikgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LGhqdXN0PTEpKSArCiAgbGFicyh5PSJBbGxlbGUgZnJlcXVlbmN5IiwgeD0iQUEgdmFyaWF0aW9uIikKfQpgYGAKCiMjIyBBbGxlbGUgZnJlcXVlbmN5IGRpc3RyaWJ1dGlvbiBwZXIgbXV0YXRpb24gKG50IGxldmVsKQpgYGB7cn0KaWYgKG5yb3codmFyaWFudF9kYXRhKT4wKSB7CiAgZ2dwbG90KHZhcmlhbnRfZGF0YSkgKyAKICBnZW9tX3F1YXNpcmFuZG9tKGFlcyh4PXBhc3RlMChwb3MsJyAnLHJlZiwnPicsYWx0KSwgeT1hZiksIGFscGhhPTAuMSkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAuMSwxKSkgKwogIGZhY2V0X2dyaWQoLiB+IGdlbmVfbmFtZSwgc2NhbGVzPSJmcmVlX3giLCBzcGFjZSA9ICJmcmVlX3giKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUsaGp1c3Q9MSkpICsKICBsYWJzKHk9IkFsbGVsZSBmcmVxdWVuY3kiLCB4PSJudCB2YXJpYXRpb24iKQp9CmBgYAoKIyMjIE51bWJlciBvZiBzYW1wbGVzIHdpdGggYWxsIHZhcmlhbnQgbXV0YXRpb25zIGFzIGEgZnVuY3Rpb24gb2YgQUYgdGhyZXNob2xkCmBgYHtyfQppZiAobnJvdyh2YXJpYW50X2RhdGEpPjApIHsKICB2YXJpYW50X2RhdGFbLGFmX2NhdDo9Y3V0KGFmLHNlcSgwLDEsMC4wMSksIGxhYmVscyA9IHNlcSgwLjAxLDEsMC4wMSkpXQogIHBsb3RkYXRhIDwtIHZhcmlhbnRfZGF0YVssLk4sLihlbmFfcnVuLGFmX2NhdCldW29yZGVyKGFmX2NhdCxkZWNyZWFzaW5nID0gVCksLihjdW1fZnJlcT1jdW1zdW0oTiksYWZfY2F0KSwuKGVuYV9ydW4pXVtjdW1fZnJlcT09bl92YXIsLk4sYWZfY2F0XVtvcmRlcihhZl9jYXQsIGRlY3JlYXNpbmcgPSBUKSwuKGFmX2NhdCxjdW1fZnJlcT1jdW1zdW0oTikpXQogIHBsb3RkYXRhWyxhZl9jYXQ6PWFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGFmX2NhdCkpXQogIAogIGdncGxvdChwbG90ZGF0YSkgKyAKICAgIGdlb21fcG9pbnQoYWVzKHg9YWZfY2F0LCB5PWN1bV9mcmVxKSkgKyAKICAgIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAuMSwxKSkgKwogICAgdGhlbWVfYncoKSArCiAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT00NSxoanVzdD0xKSkgKwogICAgbGFicyh4PSJBRiB0aHJlc2hvbGQiLHk9Ik5fc2FtcGxlcyIpCn0KYGBgCgojIyBCLjEuMzI0LjEKYGBge3J9CnZhcmlhbnQgPC0gIlZVSTIwMjEwMy8wMSIKYGBgCgpgYGB7cn0Kdm9jX2RhdGFbdmFyaWFudF9pZD09dmFyaWFudCwgLihnZW5lLCBwb3MsIHJlZl9wb3NfYWx0LGNvZG9uX2NoYW5nZSwgYW1pbm9fYWNpZF9jaGFuZ2UpXQpgYGAKCmBgYHtyfQp2YXJpYW50X3Bvc2l0aW9ucyA8LSB2b2NfZGF0YVt2YXJpYW50X2lkPT12YXJpYW50LCBwb3NdCm5fdmFyIDwtIGxlbmd0aCh2YXJpYW50X3Bvc2l0aW9ucykKCnZhcmlhbnRfZGF0YSA8LSB0YmwoY29uLCAidmNmIikgJT4lCiAgZmlsdGVyKHBvcyAlaW4lIHZhcmlhbnRfcG9zaXRpb25zKSAlPiUKICBmaWx0ZXIoYW5uX251bT09MSkgJT4lCiAgZmlsdGVyKGFmPjAuMSkgJT4lCiAgaW5uZXJfam9pbihmaWx0ZXIodGJsKGNvbiwgImxpbmVhZ2UxMHBjdCIpLCB2YXJpYW50X2lkPT12YXJpYW50KSwgYnkgPSAiZW5hX3J1biIgKSU+JQogIGNvbGxlY3QoKSAlPiUgYXMuZGF0YS50YWJsZSgpCmBgYAoKIyMjIEFsbGVsZSBmcmVxdWVuY3kgZGlzdHJpYnV0aW9uIHBlciBtdXRhdGlvbiAoQUEgbGV2ZWwpCmBgYHtyfQppZiAobnJvdyh2YXJpYW50X2RhdGEpPjApIHsKICBnZ3Bsb3QodmFyaWFudF9kYXRhKSArIAogIGdlb21fcXVhc2lyYW5kb20oYWVzKHg9cGFzdGUwKHBvcywnICcsaGd2c19wKSwgeT1hZiksIGFscGhhPTAuMSkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAuMSwxKSkgKwogIGZhY2V0X2dyaWQoLiB+IGdlbmVfbmFtZSwgc2NhbGVzPSJmcmVlX3giLCBzcGFjZSA9ICJmcmVlX3giKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUsaGp1c3Q9MSkpICsKICBsYWJzKHk9IkFsbGVsZSBmcmVxdWVuY3kiLCB4PSJBQSB2YXJpYXRpb24iKQp9CmBgYAoKIyMjIEFsbGVsZSBmcmVxdWVuY3kgZGlzdHJpYnV0aW9uIHBlciBtdXRhdGlvbiAobnQgbGV2ZWwpCmBgYHtyfQppZiAobnJvdyh2YXJpYW50X2RhdGEpPjApIHsKICBnZ3Bsb3QodmFyaWFudF9kYXRhKSArIAogIGdlb21fcXVhc2lyYW5kb20oYWVzKHg9cGFzdGUwKHBvcywnICcscmVmLCc+JyxhbHQpLCB5PWFmKSwgYWxwaGE9MC4xKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMC4xLDEpKSArCiAgZmFjZXRfZ3JpZCguIH4gZ2VuZV9uYW1lLCBzY2FsZXM9ImZyZWVfeCIsIHNwYWNlID0gImZyZWVfeCIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT00NSxoanVzdD0xKSkgKwogIGxhYnMoeT0iQWxsZWxlIGZyZXF1ZW5jeSIsIHg9Im50IHZhcmlhdGlvbiIpCn0KYGBgCgojIyMgTnVtYmVyIG9mIHNhbXBsZXMgd2l0aCBhbGwgdmFyaWFudCBtdXRhdGlvbnMgYXMgYSBmdW5jdGlvbiBvZiBBRiB0aHJlc2hvbGQKYGBge3J9CmlmIChucm93KHZhcmlhbnRfZGF0YSk+MCkgewogIHZhcmlhbnRfZGF0YVssYWZfY2F0Oj1jdXQoYWYsc2VxKDAsMSwwLjAxKSwgbGFiZWxzID0gc2VxKDAuMDEsMSwwLjAxKSldCiAgcGxvdGRhdGEgPC0gdmFyaWFudF9kYXRhWywuTiwuKGVuYV9ydW4sYWZfY2F0KV1bb3JkZXIoYWZfY2F0LGRlY3JlYXNpbmcgPSBUKSwuKGN1bV9mcmVxPWN1bXN1bShOKSxhZl9jYXQpLC4oZW5hX3J1bildW2N1bV9mcmVxPT1uX3ZhciwuTixhZl9jYXRdW29yZGVyKGFmX2NhdCwgZGVjcmVhc2luZyA9IFQpLC4oYWZfY2F0LGN1bV9mcmVxPWN1bXN1bShOKSldCiAgcGxvdGRhdGFbLGFmX2NhdDo9YXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoYWZfY2F0KSldCiAgCiAgZ2dwbG90KHBsb3RkYXRhKSArIAogICAgZ2VvbV9wb2ludChhZXMoeD1hZl9jYXQsIHk9Y3VtX2ZyZXEpKSArCiAgICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLjEsMSkpICsKICAgIHRoZW1lX2J3KCkgKwogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUsaGp1c3Q9MSkpICsKICAgIGxhYnMoeD0iQUYgdGhyZXNob2xkIix5PSJOX3NhbXBsZXMiKQp9CmBgYAoKIyMgQi4xLjEuNwpgYGB7cn0KdmFyaWFudCA8LSAiVk9DMjAyMDEyLzAxIgpgYGAKCmBgYHtyfQp2b2NfZGF0YVt2YXJpYW50X2lkPT12YXJpYW50LCAuKGdlbmUsIHBvcywgcmVmX3Bvc19hbHQsY29kb25fY2hhbmdlLCBhbWlub19hY2lkX2NoYW5nZSldCmBgYAoKYGBge3J9CnZhcmlhbnRfcG9zaXRpb25zIDwtIHZvY19kYXRhW3ZhcmlhbnRfaWQ9PXZhcmlhbnQsIHBvc10Kbl92YXIgPC0gbGVuZ3RoKHZhcmlhbnRfcG9zaXRpb25zKQoKdmFyaWFudF9kYXRhIDwtIHRibChjb24sICJ2Y2YiKSAlPiUKICBmaWx0ZXIocG9zICVpbiUgdmFyaWFudF9wb3NpdGlvbnMpICU+JQogIGZpbHRlcihhbm5fbnVtPT0xKSAlPiUKICBmaWx0ZXIoYWY+MC4xKSAlPiUKICBpbm5lcl9qb2luKGZpbHRlcih0YmwoY29uLCAibGluZWFnZTEwcGN0IiksIHZhcmlhbnRfaWQ9PXZhcmlhbnQpLCBieSA9ICJlbmFfcnVuIiApJT4lCiAgY29sbGVjdCgpICU+JSBhcy5kYXRhLnRhYmxlKCkKYGBgCgojIyMgQWxsZWxlIGZyZXF1ZW5jeSBkaXN0cmlidXRpb24gcGVyIG11dGF0aW9uIChBQSBsZXZlbCkKYGBge3J9CmlmIChucm93KHZhcmlhbnRfZGF0YSk+MCkgewogIGdncGxvdCh2YXJpYW50X2RhdGEpICsgCiAgZ2VvbV9xdWFzaXJhbmRvbShhZXMoeD1wYXN0ZTAocG9zLCcgJyxoZ3ZzX3ApLCB5PWFmKSwgYWxwaGE9MC4xKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMC4xLDEpKSArCiAgZmFjZXRfZ3JpZCguIH4gZ2VuZV9uYW1lLCBzY2FsZXM9ImZyZWVfeCIsIHNwYWNlID0gImZyZWVfeCIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT00NSxoanVzdD0xKSkgKwogIGxhYnMoeT0iQWxsZWxlIGZyZXF1ZW5jeSIsIHg9IkFBIHZhcmlhdGlvbiIpCn0KYGBgCgojIyMgQWxsZWxlIGZyZXF1ZW5jeSBkaXN0cmlidXRpb24gcGVyIG11dGF0aW9uIChudCBsZXZlbCkKYGBge3J9CmlmIChucm93KHZhcmlhbnRfZGF0YSk+MCkgewogIGdncGxvdCh2YXJpYW50X2RhdGEpICsgCiAgZ2VvbV9xdWFzaXJhbmRvbShhZXMoeD1wYXN0ZTAocG9zLCcgJyxyZWYsJz4nLGFsdCksIHk9YWYpLCBhbHBoYT0wLjEpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLjEsMSkpICsKICBmYWNldF9ncmlkKC4gfiBnZW5lX25hbWUsIHNjYWxlcz0iZnJlZV94Iiwgc3BhY2UgPSAiZnJlZV94IikgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LGhqdXN0PTEpKSArCiAgbGFicyh5PSJBbGxlbGUgZnJlcXVlbmN5IiwgeD0ibnQgdmFyaWF0aW9uIikKfQpgYGAKCiMjIyBOdW1iZXIgb2Ygc2FtcGxlcyB3aXRoIGFsbCB2YXJpYW50IG11dGF0aW9ucyBhcyBhIGZ1bmN0aW9uIG9mIEFGIHRocmVzaG9sZApgYGB7cn0KaWYgKG5yb3codmFyaWFudF9kYXRhKT4wKSB7CiAgdmFyaWFudF9kYXRhWyxhZl9jYXQ6PWN1dChhZixzZXEoMCwxLDAuMDEpLCBsYWJlbHMgPSBzZXEoMC4wMSwxLDAuMDEpKV0KICBwbG90ZGF0YSA8LSB2YXJpYW50X2RhdGFbLC5OLC4oZW5hX3J1bixhZl9jYXQpXVtvcmRlcihhZl9jYXQsZGVjcmVhc2luZyA9IFQpLC4oY3VtX2ZyZXE9Y3Vtc3VtKE4pLGFmX2NhdCksLihlbmFfcnVuKV1bY3VtX2ZyZXE9PW5fdmFyLC5OLGFmX2NhdF1bb3JkZXIoYWZfY2F0LCBkZWNyZWFzaW5nID0gVCksLihhZl9jYXQsY3VtX2ZyZXE9Y3Vtc3VtKE4pKV0KICBwbG90ZGF0YVssYWZfY2F0Oj1hcy5udW1lcmljKGFzLmNoYXJhY3RlcihhZl9jYXQpKV0KICAKICBnZ3Bsb3QocGxvdGRhdGEpICsgCiAgICBnZW9tX3BvaW50KGFlcyh4PWFmX2NhdCwgeT1jdW1fZnJlcSkpICsgCiAgICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLjEsMSkpICsKICAgIHRoZW1lX2J3KCkgKwogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUsaGp1c3Q9MSkpICsKICAgIGxhYnMoeD0iQUYgdGhyZXNob2xkIix5PSJOX3NhbXBsZXMiKQp9CmBgYAoKIyMgQi4xLjUyNQpgYGB7cn0KdmFyaWFudCA8LSAiVlVJMjAyMTAyLzAzIgpgYGAKCmBgYHtyfQp2b2NfZGF0YVt2YXJpYW50X2lkPT12YXJpYW50LCAuKGdlbmUsIHBvcywgcmVmX3Bvc19hbHQsY29kb25fY2hhbmdlLCBhbWlub19hY2lkX2NoYW5nZSldCmBgYAoKYGBge3J9CnZhcmlhbnRfcG9zaXRpb25zIDwtIHZvY19kYXRhW3ZhcmlhbnRfaWQ9PXZhcmlhbnQsIHBvc10Kbl92YXIgPC0gbGVuZ3RoKHZhcmlhbnRfcG9zaXRpb25zKQoKdmFyaWFudF9kYXRhIDwtIHRibChjb24sICJ2Y2YiKSAlPiUKICBmaWx0ZXIocG9zICVpbiUgdmFyaWFudF9wb3NpdGlvbnMpICU+JQogIGZpbHRlcihhbm5fbnVtPT0xKSAlPiUKICBmaWx0ZXIoYWY+MC4xKSAlPiUKICBpbm5lcl9qb2luKGZpbHRlcih0YmwoY29uLCAibGluZWFnZTEwcGN0IiksIHZhcmlhbnRfaWQ9PXZhcmlhbnQpLCBieSA9ICJlbmFfcnVuIiApJT4lCiAgY29sbGVjdCgpICU+JSBhcy5kYXRhLnRhYmxlKCkKYGBgCgojIyMgQWxsZWxlIGZyZXF1ZW5jeSBkaXN0cmlidXRpb24gcGVyIG11dGF0aW9uIChBQSBsZXZlbCkKYGBge3J9CmlmIChucm93KHZhcmlhbnRfZGF0YSk+MCkgewogIGdncGxvdCh2YXJpYW50X2RhdGEpICsgCiAgZ2VvbV9xdWFzaXJhbmRvbShhZXMoeD1wYXN0ZTAocG9zLCcgJyxoZ3ZzX3ApLCB5PWFmKSwgYWxwaGE9MC4xKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMC4xLDEpKSArCiAgZmFjZXRfZ3JpZCguIH4gZ2VuZV9uYW1lLCBzY2FsZXM9ImZyZWVfeCIsIHNwYWNlID0gImZyZWVfeCIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT00NSxoanVzdD0xKSkgKwogIGxhYnMoeT0iQWxsZWxlIGZyZXF1ZW5jeSIsIHg9IkFBIHZhcmlhdGlvbiIpCn0KYGBgCgojIyMgQWxsZWxlIGZyZXF1ZW5jeSBkaXN0cmlidXRpb24gcGVyIG11dGF0aW9uIChudCBsZXZlbCkKYGBge3J9CmlmIChucm93KHZhcmlhbnRfZGF0YSk+MCkgewogIGdncGxvdCh2YXJpYW50X2RhdGEpICsgCiAgZ2VvbV9xdWFzaXJhbmRvbShhZXMoeD1wYXN0ZTAocG9zLCcgJyxyZWYsJz4nLGFsdCksIHk9YWYpLCBhbHBoYT0wLjEpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLjEsMSkpICsKICBmYWNldF9ncmlkKC4gfiBnZW5lX25hbWUsIHNjYWxlcz0iZnJlZV94Iiwgc3BhY2UgPSAiZnJlZV94IikgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LGhqdXN0PTEpKSArCiAgbGFicyh5PSJBbGxlbGUgZnJlcXVlbmN5IiwgeD0ibnQgdmFyaWF0aW9uIikKfQpgYGAKCiMjIyBOdW1iZXIgb2Ygc2FtcGxlcyB3aXRoIGFsbCB2YXJpYW50IG11dGF0aW9ucyBhcyBhIGZ1bmN0aW9uIG9mIEFGIHRocmVzaG9sZApgYGB7cn0KaWYgKG5yb3codmFyaWFudF9kYXRhKT4wKSB7CiAgdmFyaWFudF9kYXRhWyxhZl9jYXQ6PWN1dChhZixzZXEoMCwxLDAuMDEpLCBsYWJlbHMgPSBzZXEoMC4wMSwxLDAuMDEpKV0KICBwbG90ZGF0YSA8LSB2YXJpYW50X2RhdGFbLC5OLC4oZW5hX3J1bixhZl9jYXQpXVtvcmRlcihhZl9jYXQsZGVjcmVhc2luZyA9IFQpLC4oY3VtX2ZyZXE9Y3Vtc3VtKE4pLGFmX2NhdCksLihlbmFfcnVuKV1bY3VtX2ZyZXE9PW5fdmFyLC5OLGFmX2NhdF1bb3JkZXIoYWZfY2F0LCBkZWNyZWFzaW5nID0gVCksLihhZl9jYXQsY3VtX2ZyZXE9Y3Vtc3VtKE4pKV0KICBwbG90ZGF0YVssYWZfY2F0Oj1hcy5udW1lcmljKGFzLmNoYXJhY3RlcihhZl9jYXQpKV0KICAKICBnZ3Bsb3QocGxvdGRhdGEpICsgCiAgICBnZW9tX3BvaW50KGFlcyh4PWFmX2NhdCwgeT1jdW1fZnJlcSkpICsKICAgIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAuMSwxKSkgKwogICAgdGhlbWVfYncoKSArCiAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT00NSxoanVzdD0xKSkgKwogICAgbGFicyh4PSJBRiB0aHJlc2hvbGQiLHk9Ik5fc2FtcGxlcyIpCn0KYGBgCgojIyBCLjEuNjE3CmBgYHtyfQp2YXJpYW50IDwtICJJbmRpYSIKYGBgCgpgYGB7cn0Kdm9jX2RhdGFbdmFyaWFudF9pZD09dmFyaWFudCwgLihnZW5lLCBwb3MsIHJlZl9wb3NfYWx0LGNvZG9uX2NoYW5nZSwgYW1pbm9fYWNpZF9jaGFuZ2UpXQpgYGAKCmBgYHtyfQp2YXJpYW50X3Bvc2l0aW9ucyA8LSB2b2NfZGF0YVt2YXJpYW50X2lkPT12YXJpYW50LCBwb3NdCm5fdmFyIDwtIGxlbmd0aCh2YXJpYW50X3Bvc2l0aW9ucykKCnZhcmlhbnRfZGF0YSA8LSB0YmwoY29uLCAidmNmIikgJT4lCiAgZmlsdGVyKHBvcyAlaW4lIHZhcmlhbnRfcG9zaXRpb25zKSAlPiUKICBmaWx0ZXIoYW5uX251bT09MSkgJT4lCiAgZmlsdGVyKGFmPjAuMSkgJT4lCiAgaW5uZXJfam9pbihmaWx0ZXIodGJsKGNvbiwgImxpbmVhZ2UxMHBjdCIpLCB2YXJpYW50X2lkPT12YXJpYW50KSwgYnkgPSAiZW5hX3J1biIgKSU+JQogIGNvbGxlY3QoKSAlPiUgYXMuZGF0YS50YWJsZSgpCmBgYAoKIyMjIEFsbGVsZSBmcmVxdWVuY3kgZGlzdHJpYnV0aW9uIHBlciBtdXRhdGlvbiAoQUEgbGV2ZWwpCmBgYHtyfQppZiAobnJvdyh2YXJpYW50X2RhdGEpPjApIHsKICBnZ3Bsb3QodmFyaWFudF9kYXRhKSArIAogIGdlb21fcXVhc2lyYW5kb20oYWVzKHg9cGFzdGUwKHBvcywnICcsaGd2c19wKSwgeT1hZiksIGFscGhhPTAuMSkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAuMSwxKSkgKwogIGZhY2V0X2dyaWQoLiB+IGdlbmVfbmFtZSwgc2NhbGVzPSJmcmVlX3giLCBzcGFjZSA9ICJmcmVlX3giKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUsaGp1c3Q9MSkpICsKICBsYWJzKHk9IkFsbGVsZSBmcmVxdWVuY3kiLCB4PSJBQSB2YXJpYXRpb24iKQp9CmBgYAoKIyMjIEFsbGVsZSBmcmVxdWVuY3kgZGlzdHJpYnV0aW9uIHBlciBtdXRhdGlvbiAobnQgbGV2ZWwpCmBgYHtyfQppZiAobnJvdyh2YXJpYW50X2RhdGEpPjApIHsKICBnZ3Bsb3QodmFyaWFudF9kYXRhKSArIAogIGdlb21fcXVhc2lyYW5kb20oYWVzKHg9cGFzdGUwKHBvcywnICcscmVmLCc+JyxhbHQpLCB5PWFmKSwgYWxwaGE9MC4xKSArCiAgZmFjZXRfZ3JpZCguIH4gZ2VuZV9uYW1lLCBzY2FsZXM9ImZyZWVfeCIsIHNwYWNlID0gImZyZWVfeCIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLjEsMSkpICsKICB0aGVtZV9idygpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT00NSxoanVzdD0xKSkgKwogIGxhYnMoeT0iQWxsZWxlIGZyZXF1ZW5jeSIsIHg9Im50IHZhcmlhdGlvbiIpCn0KYGBgCgojIyMgTnVtYmVyIG9mIHNhbXBsZXMgd2l0aCBhbGwgdmFyaWFudCBtdXRhdGlvbnMgYXMgYSBmdW5jdGlvbiBvZiBBRiB0aHJlc2hvbGQKYGBge3J9CmlmIChucm93KHZhcmlhbnRfZGF0YSk+MCkgewogIHZhcmlhbnRfZGF0YVssYWZfY2F0Oj1jdXQoYWYsc2VxKDAsMSwwLjAxKSwgbGFiZWxzID0gc2VxKDAuMDEsMSwwLjAxKSldCiAgcGxvdGRhdGEgPC0gdmFyaWFudF9kYXRhWywuTiwuKGVuYV9ydW4sYWZfY2F0KV1bb3JkZXIoYWZfY2F0LGRlY3JlYXNpbmcgPSBUKSwuKGN1bV9mcmVxPWN1bXN1bShOKSxhZl9jYXQpLC4oZW5hX3J1bildW2N1bV9mcmVxPT1uX3ZhciwuTixhZl9jYXRdW29yZGVyKGFmX2NhdCwgZGVjcmVhc2luZyA9IFQpLC4oYWZfY2F0LGN1bV9mcmVxPWN1bXN1bShOKSldCiAgcGxvdGRhdGFbLGFmX2NhdDo9YXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoYWZfY2F0KSldCiAgCiAgZ2dwbG90KHBsb3RkYXRhKSArIAogICAgZ2VvbV9wb2ludChhZXMoeD1hZl9jYXQsIHk9Y3VtX2ZyZXEpKSArCiAgICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLjEsMSkpICsKICAgIHRoZW1lX2J3KCkgKwogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUsaGp1c3Q9MSkpICsKICAgIGxhYnMoeD0iQUYgdGhyZXNob2xkIix5PSJOX3NhbXBsZXMiKQp9CmBgYAoKIyMgUC4yCmBgYHtyfQp2YXJpYW50IDwtICJWVUkyMDIxMDEvMDEiCmBgYAoKYGBge3J9CnZvY19kYXRhW3ZhcmlhbnRfaWQ9PXZhcmlhbnQsIC4oZ2VuZSwgcG9zLCByZWZfcG9zX2FsdCxjb2Rvbl9jaGFuZ2UsIGFtaW5vX2FjaWRfY2hhbmdlKV0KYGBgCgpgYGB7cn0KdmFyaWFudF9wb3NpdGlvbnMgPC0gdm9jX2RhdGFbdmFyaWFudF9pZD09dmFyaWFudCwgcG9zXQpuX3ZhciA8LSBsZW5ndGgodmFyaWFudF9wb3NpdGlvbnMpCgp2YXJpYW50X2RhdGEgPC0gdGJsKGNvbiwgInZjZiIpICU+JQogIGZpbHRlcihwb3MgJWluJSB2YXJpYW50X3Bvc2l0aW9ucykgJT4lCiAgZmlsdGVyKGFubl9udW09PTEpICU+JQogIGZpbHRlcihhZj4wLjEpICU+JQogIGlubmVyX2pvaW4oZmlsdGVyKHRibChjb24sICJsaW5lYWdlMTBwY3QiKSwgdmFyaWFudF9pZD09dmFyaWFudCksIGJ5ID0gImVuYV9ydW4iICklPiUKICBjb2xsZWN0KCkgJT4lIGFzLmRhdGEudGFibGUoKQpgYGAKCiMjIyBBbGxlbGUgZnJlcXVlbmN5IGRpc3RyaWJ1dGlvbiBwZXIgbXV0YXRpb24gKEFBIGxldmVsKQpgYGB7cn0KaWYgKG5yb3codmFyaWFudF9kYXRhKT4wKSB7CiAgZ2dwbG90KHZhcmlhbnRfZGF0YSkgKyAKICBnZW9tX3F1YXNpcmFuZG9tKGFlcyh4PXBhc3RlMChwb3MsJyAnLGhndnNfcCksIHk9YWYpLCBhbHBoYT0wLjEpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLjEsMSkpICsKICBmYWNldF9ncmlkKC4gfiBnZW5lX25hbWUsIHNjYWxlcz0iZnJlZV94Iiwgc3BhY2UgPSAiZnJlZV94IikgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LGhqdXN0PTEpKSArCiAgbGFicyh5PSJBbGxlbGUgZnJlcXVlbmN5IiwgeD0iQUEgdmFyaWF0aW9uIikKfQpgYGAKCiMjIyBBbGxlbGUgZnJlcXVlbmN5IGRpc3RyaWJ1dGlvbiBwZXIgbXV0YXRpb24gKG50IGxldmVsKQpgYGB7cn0KaWYgKG5yb3codmFyaWFudF9kYXRhKT4wKSB7CiAgZ2dwbG90KHZhcmlhbnRfZGF0YSkgKyAKICBnZW9tX3F1YXNpcmFuZG9tKGFlcyh4PXBhc3RlMChwb3MsJyAnLHJlZiwnPicsYWx0KSwgeT1hZiksIGFscGhhPTAuMSkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAuMSwxKSkgKwogIGZhY2V0X2dyaWQoLiB+IGdlbmVfbmFtZSwgc2NhbGVzPSJmcmVlX3giLCBzcGFjZSA9ICJmcmVlX3giKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUsaGp1c3Q9MSkpICsKICBsYWJzKHk9IkFsbGVsZSBmcmVxdWVuY3kiLCB4PSJudCB2YXJpYXRpb24iKQp9CmBgYAoKIyMjIE51bWJlciBvZiBzYW1wbGVzIHdpdGggYWxsIHZhcmlhbnQgbXV0YXRpb25zIGFzIGEgZnVuY3Rpb24gb2YgQUYgdGhyZXNob2xkCmBgYHtyfQppZiAobnJvdyh2YXJpYW50X2RhdGEpPjApIHsKICB2YXJpYW50X2RhdGFbLGFmX2NhdDo9Y3V0KGFmLHNlcSgwLDEsMC4wMSksIGxhYmVscyA9IHNlcSgwLjAxLDEsMC4wMSkpXQogIHBsb3RkYXRhIDwtIHZhcmlhbnRfZGF0YVssLk4sLihlbmFfcnVuLGFmX2NhdCldW29yZGVyKGFmX2NhdCxkZWNyZWFzaW5nID0gVCksLihjdW1fZnJlcT1jdW1zdW0oTiksYWZfY2F0KSwuKGVuYV9ydW4pXVtjdW1fZnJlcT09bl92YXIsLk4sYWZfY2F0XVtvcmRlcihhZl9jYXQsIGRlY3JlYXNpbmcgPSBUKSwuKGFmX2NhdCxjdW1fZnJlcT1jdW1zdW0oTikpXQogIHBsb3RkYXRhWyxhZl9jYXQ6PWFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGFmX2NhdCkpXQogIAogIGdncGxvdChwbG90ZGF0YSkgKyAKICAgIGdlb21fcG9pbnQoYWVzKHg9YWZfY2F0LCB5PWN1bV9mcmVxKSkgKwogICAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMC4xLDEpKSArCiAgICB0aGVtZV9idygpICsKICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LGhqdXN0PTEpKSArCiAgICBsYWJzKHg9IkFGIHRocmVzaG9sZCIseT0iTl9zYW1wbGVzIikKfQpgYGAKCiMjIFAuMwpgYGB7cn0KdmFyaWFudCA8LSAiVlVJMjAyMTAzLzAyIgpgYGAKCmBgYHtyfQp2b2NfZGF0YVt2YXJpYW50X2lkPT12YXJpYW50LCAuKGdlbmUsIHBvcywgcmVmX3Bvc19hbHQsY29kb25fY2hhbmdlLCBhbWlub19hY2lkX2NoYW5nZSldCmBgYAoKYGBge3J9CnZhcmlhbnRfcG9zaXRpb25zIDwtIHZvY19kYXRhW3ZhcmlhbnRfaWQ9PXZhcmlhbnQsIHBvc10Kbl92YXIgPC0gbGVuZ3RoKHZhcmlhbnRfcG9zaXRpb25zKQoKdmFyaWFudF9kYXRhIDwtIHRibChjb24sICJ2Y2YiKSAlPiUKICBmaWx0ZXIocG9zICVpbiUgdmFyaWFudF9wb3NpdGlvbnMpICU+JQogIGZpbHRlcihhbm5fbnVtPT0xKSAlPiUKICBmaWx0ZXIoYWY+MC4xKSAlPiUKICBpbm5lcl9qb2luKGZpbHRlcih0YmwoY29uLCAibGluZWFnZTEwcGN0IiksIHZhcmlhbnRfaWQ9PXZhcmlhbnQpLCBieSA9ICJlbmFfcnVuIiApJT4lCiAgY29sbGVjdCgpICU+JSBhcy5kYXRhLnRhYmxlKCkKYGBgCgojIyMgQWxsZWxlIGZyZXF1ZW5jeSBkaXN0cmlidXRpb24gcGVyIG11dGF0aW9uIChBQSBsZXZlbCkKYGBge3J9CmlmIChucm93KHZhcmlhbnRfZGF0YSk+MCkgewogIGdncGxvdCh2YXJpYW50X2RhdGEpICsgCiAgZ2VvbV9xdWFzaXJhbmRvbShhZXMoeD1wYXN0ZTAocG9zLCcgJyxoZ3ZzX3ApLCB5PWFmKSwgYWxwaGE9MC4xKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMC4xLDEpKSArCiAgZmFjZXRfZ3JpZCguIH4gZ2VuZV9uYW1lLCBzY2FsZXM9ImZyZWVfeCIsIHNwYWNlID0gImZyZWVfeCIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT00NSxoanVzdD0xKSkgKwogIGxhYnMoeT0iQWxsZWxlIGZyZXF1ZW5jeSIsIHg9IkFBIHZhcmlhdGlvbiIpCn0KYGBgCgojIyMgQWxsZWxlIGZyZXF1ZW5jeSBkaXN0cmlidXRpb24gcGVyIG11dGF0aW9uIChudCBsZXZlbCkKYGBge3J9CmlmIChucm93KHZhcmlhbnRfZGF0YSk+MCkgewogIGdncGxvdCh2YXJpYW50X2RhdGEpICsgCiAgZ2VvbV9xdWFzaXJhbmRvbShhZXMoeD1wYXN0ZTAocG9zLCcgJyxyZWYsJz4nLGFsdCksIHk9YWYpLCBhbHBoYT0wLjEpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLjEsMSkpICsKICBmYWNldF9ncmlkKC4gfiBnZW5lX25hbWUsIHNjYWxlcz0iZnJlZV94Iiwgc3BhY2UgPSAiZnJlZV94IikgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LGhqdXN0PTEpKSArCiAgbGFicyh5PSJBbGxlbGUgZnJlcXVlbmN5IiwgeD0ibnQgdmFyaWF0aW9uIikKfQpgYGAKCiMjIyBOdW1iZXIgb2Ygc2FtcGxlcyB3aXRoIGFsbCB2YXJpYW50IG11dGF0aW9ucyBhcyBhIGZ1bmN0aW9uIG9mIEFGIHRocmVzaG9sZApgYGB7cn0KaWYgKG5yb3codmFyaWFudF9kYXRhKT4wKSB7CiAgdmFyaWFudF9kYXRhWyxhZl9jYXQ6PWN1dChhZixzZXEoMCwxLDAuMDEpLCBsYWJlbHMgPSBzZXEoMC4wMSwxLDAuMDEpKV0KICBwbG90ZGF0YSA8LSB2YXJpYW50X2RhdGFbLC5OLC4oZW5hX3J1bixhZl9jYXQpXVtvcmRlcihhZl9jYXQsZGVjcmVhc2luZyA9IFQpLC4oY3VtX2ZyZXE9Y3Vtc3VtKE4pLGFmX2NhdCksLihlbmFfcnVuKV1bY3VtX2ZyZXE9PW5fdmFyLC5OLGFmX2NhdF1bb3JkZXIoYWZfY2F0LCBkZWNyZWFzaW5nID0gVCksLihhZl9jYXQsY3VtX2ZyZXE9Y3Vtc3VtKE4pKV0KICBwbG90ZGF0YVssYWZfY2F0Oj1hcy5udW1lcmljKGFzLmNoYXJhY3RlcihhZl9jYXQpKV0KICAKICBnZ3Bsb3QocGxvdGRhdGEpICsgCiAgICBnZW9tX3BvaW50KGFlcyh4PWFmX2NhdCwgeT1jdW1fZnJlcSkpICsgCiAgICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLjEsMSkpICsKICAgIHRoZW1lX2J3KCkgKwogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUsaGp1c3Q9MSkpICsKICAgIGxhYnMoeD0iQUYgdGhyZXNob2xkIix5PSJOX3NhbXBsZXMiKQp9CmBgYAoKIyMgUC4xCmBgYHtyfQp2YXJpYW50IDwtICJWT0MyMDIxMDEvMDIiCmBgYAoKYGBge3J9CnZvY19kYXRhW3ZhcmlhbnRfaWQ9PXZhcmlhbnQsIC4oZ2VuZSwgcG9zLCByZWZfcG9zX2FsdCxjb2Rvbl9jaGFuZ2UsIGFtaW5vX2FjaWRfY2hhbmdlKV0KYGBgCgpgYGB7cn0KdmFyaWFudF9wb3NpdGlvbnMgPC0gdm9jX2RhdGFbdmFyaWFudF9pZD09dmFyaWFudCwgcG9zXQpuX3ZhciA8LSBsZW5ndGgodmFyaWFudF9wb3NpdGlvbnMpCgp2YXJpYW50X2RhdGEgPC0gdGJsKGNvbiwgInZjZiIpICU+JQogIGZpbHRlcihwb3MgJWluJSB2YXJpYW50X3Bvc2l0aW9ucykgJT4lCiAgZmlsdGVyKGFubl9udW09PTEpICU+JQogIGZpbHRlcihhZj4wLjEpICU+JQogIGlubmVyX2pvaW4oZmlsdGVyKHRibChjb24sICJsaW5lYWdlMTBwY3QiKSwgdmFyaWFudF9pZD09dmFyaWFudCksIGJ5ID0gImVuYV9ydW4iICklPiUKICBjb2xsZWN0KCkgJT4lIGFzLmRhdGEudGFibGUoKQpgYGAKCiMjIyBBbGxlbGUgZnJlcXVlbmN5IGRpc3RyaWJ1dGlvbiBwZXIgbXV0YXRpb24gKEFBIGxldmVsKQpgYGB7cn0KaWYgKG5yb3codmFyaWFudF9kYXRhKT4wKSB7CiAgZ2dwbG90KHZhcmlhbnRfZGF0YSkgKyAKICBnZW9tX3F1YXNpcmFuZG9tKGFlcyh4PXBhc3RlMChwb3MsJyAnLGhndnNfcCksIHk9YWYpLCBhbHBoYT0wLjEpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLjEsMSkpICsKICBmYWNldF9ncmlkKC4gfiBnZW5lX25hbWUsIHNjYWxlcz0iZnJlZV94Iiwgc3BhY2UgPSAiZnJlZV94IikgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LGhqdXN0PTEpKSArCiAgbGFicyh5PSJBbGxlbGUgZnJlcXVlbmN5IiwgeD0iQUEgdmFyaWF0aW9uIikKfQpgYGAKCiMjIyBBbGxlbGUgZnJlcXVlbmN5IGRpc3RyaWJ1dGlvbiBwZXIgbXV0YXRpb24gKG50IGxldmVsKQpgYGB7cn0KaWYgKG5yb3codmFyaWFudF9kYXRhKT4wKSB7CiAgZ2dwbG90KHZhcmlhbnRfZGF0YSkgKyAKICBnZW9tX3F1YXNpcmFuZG9tKGFlcyh4PXBhc3RlMChwb3MsJyAnLHJlZiwnPicsYWx0KSwgeT1hZiksIGFscGhhPTAuMSkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAuMSwxKSkgKwogIGZhY2V0X2dyaWQoLiB+IGdlbmVfbmFtZSwgc2NhbGVzPSJmcmVlX3giLCBzcGFjZSA9ICJmcmVlX3giKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUsaGp1c3Q9MSkpICsKICBsYWJzKHk9IkFsbGVsZSBmcmVxdWVuY3kiLCB4PSJudCB2YXJpYXRpb24iKQp9CmBgYAoKIyMjIE51bWJlciBvZiBzYW1wbGVzIHdpdGggYWxsIHZhcmlhbnQgbXV0YXRpb25zIGFzIGEgZnVuY3Rpb24gb2YgQUYgdGhyZXNob2xkCmBgYHtyfQppZiAobnJvdyh2YXJpYW50X2RhdGEpPjApIHsKICB2YXJpYW50X2RhdGFbLGFmX2NhdDo9Y3V0KGFmLHNlcSgwLDEsMC4wMSksIGxhYmVscyA9IHNlcSgwLjAxLDEsMC4wMSkpXQogIHBsb3RkYXRhIDwtIHZhcmlhbnRfZGF0YVssLk4sLihlbmFfcnVuLGFmX2NhdCldW29yZGVyKGFmX2NhdCxkZWNyZWFzaW5nID0gVCksLihjdW1fZnJlcT1jdW1zdW0oTiksYWZfY2F0KSwuKGVuYV9ydW4pXVtjdW1fZnJlcT09bl92YXIsLk4sYWZfY2F0XVtvcmRlcihhZl9jYXQsIGRlY3JlYXNpbmcgPSBUKSwuKGFmX2NhdCxjdW1fZnJlcT1jdW1zdW0oTikpXQogIHBsb3RkYXRhWyxhZl9jYXQ6PWFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGFmX2NhdCkpXQogIAogIGdncGxvdChwbG90ZGF0YSkgKyAKICAgIGdlb21fcG9pbnQoYWVzKHg9YWZfY2F0LCB5PWN1bV9mcmVxKSkgKyAKICAgIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAuMSwxKSkgKwogICAgdGhlbWVfYncoKSArCiAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT00NSxoanVzdD0xKSkgKwogICAgbGFicyh4PSJBRiB0aHJlc2hvbGQiLHk9Ik5fc2FtcGxlcyIpCn0KYGBgCgojIyBCLjEuMS43ICsgRTQ4NEsKYGBge3J9CnZhcmlhbnQgPC0gIlZPQzIwMjEwMi8wMiIKYGBgCgpgYGB7cn0Kdm9jX2RhdGFbdmFyaWFudF9pZD09dmFyaWFudCwgLihnZW5lLCBwb3MsIHJlZl9wb3NfYWx0LGNvZG9uX2NoYW5nZSwgYW1pbm9fYWNpZF9jaGFuZ2UpXQpgYGAKCmBgYHtyfQp2YXJpYW50X3Bvc2l0aW9ucyA8LSB2b2NfZGF0YVt2YXJpYW50X2lkPT12YXJpYW50LCBwb3NdCm5fdmFyIDwtIGxlbmd0aCh2YXJpYW50X3Bvc2l0aW9ucykKCnZhcmlhbnRfZGF0YSA8LSB0YmwoY29uLCAidmNmIikgJT4lCiAgZmlsdGVyKHBvcyAlaW4lIHZhcmlhbnRfcG9zaXRpb25zKSAlPiUKICBmaWx0ZXIoYW5uX251bT09MSkgJT4lCiAgZmlsdGVyKGFmPjAuMSkgJT4lCiAgaW5uZXJfam9pbihmaWx0ZXIodGJsKGNvbiwgImxpbmVhZ2UxMHBjdCIpLCB2YXJpYW50X2lkPT12YXJpYW50KSwgYnkgPSAiZW5hX3J1biIgKSU+JQogIGNvbGxlY3QoKSAlPiUgYXMuZGF0YS50YWJsZSgpCmBgYAoKIyMjIEFsbGVsZSBmcmVxdWVuY3kgZGlzdHJpYnV0aW9uIHBlciBtdXRhdGlvbiAoQUEgbGV2ZWwpCmBgYHtyfQppZiAobnJvdyh2YXJpYW50X2RhdGEpPjApIHsKICBnZ3Bsb3QodmFyaWFudF9kYXRhKSArIAogIGdlb21fcXVhc2lyYW5kb20oYWVzKHg9cGFzdGUwKHBvcywnICcsaGd2c19wKSwgeT1hZiksIGFscGhhPTAuMSkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAuMSwxKSkgKwogIGZhY2V0X2dyaWQoLiB+IGdlbmVfbmFtZSwgc2NhbGVzPSJmcmVlX3giLCBzcGFjZSA9ICJmcmVlX3giKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUsaGp1c3Q9MSkpICsKICBsYWJzKHk9IkFsbGVsZSBmcmVxdWVuY3kiLCB4PSJBQSB2YXJpYXRpb24iKQp9CmBgYAoKIyMjIEFsbGVsZSBmcmVxdWVuY3kgZGlzdHJpYnV0aW9uIHBlciBtdXRhdGlvbiAobnQgbGV2ZWwpCmBgYHtyfQppZiAobnJvdyh2YXJpYW50X2RhdGEpPjApIHsKICBnZ3Bsb3QodmFyaWFudF9kYXRhKSArIAogIGdlb21fcXVhc2lyYW5kb20oYWVzKHg9cGFzdGUwKHBvcywnICcscmVmLCc+JyxhbHQpLCB5PWFmKSwgYWxwaGE9MC4xKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMC4xLDEpKSArCiAgZmFjZXRfZ3JpZCguIH4gZ2VuZV9uYW1lLCBzY2FsZXM9ImZyZWVfeCIsIHNwYWNlID0gImZyZWVfeCIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT00NSxoanVzdD0xKSkgKwogIGxhYnMoeT0iQWxsZWxlIGZyZXF1ZW5jeSIsIHg9Im50IHZhcmlhdGlvbiIpCn0KYGBgCgojIyMgTnVtYmVyIG9mIHNhbXBsZXMgd2l0aCBhbGwgdmFyaWFudCBtdXRhdGlvbnMgYXMgYSBmdW5jdGlvbiBvZiBBRiB0aHJlc2hvbGQKYGBge3J9CmlmIChucm93KHZhcmlhbnRfZGF0YSk+MCkgewogIHZhcmlhbnRfZGF0YVssYWZfY2F0Oj1jdXQoYWYsc2VxKDAsMSwwLjAxKSwgbGFiZWxzID0gc2VxKDAuMDEsMSwwLjAxKSldCiAgcGxvdGRhdGEgPC0gdmFyaWFudF9kYXRhWywuTiwuKGVuYV9ydW4sYWZfY2F0KV1bb3JkZXIoYWZfY2F0LGRlY3JlYXNpbmcgPSBUKSwuKGN1bV9mcmVxPWN1bXN1bShOKSxhZl9jYXQpLC4oZW5hX3J1bildW2N1bV9mcmVxPT1uX3ZhciwuTixhZl9jYXRdW29yZGVyKGFmX2NhdCwgZGVjcmVhc2luZyA9IFQpLC4oYWZfY2F0LGN1bV9mcmVxPWN1bXN1bShOKSldCiAgcGxvdGRhdGFbLGFmX2NhdDo9YXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoYWZfY2F0KSldCiAgCiAgZ2dwbG90KHBsb3RkYXRhKSArIAogICAgZ2VvbV9wb2ludChhZXMoeD1hZl9jYXQsIHk9Y3VtX2ZyZXEpKSArIAogICAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwxKSkgKwogICAgdGhlbWVfYncoKSArCiAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT00NSxoanVzdD0xKSkgKwogICAgbGFicyh4PSJBRiB0aHJlc2hvbGQiLHk9Ik5fc2FtcGxlcyIpCn0KYGBgCg==