1 Introduction

This document is intended to provide a general overview of the TMRC2 samples which have thus far been sequenced. In some cases, this includes only those samples starting in 2019; in other instances I am including our previous (2015-2016) samples.

In all cases the processing performed was:

  1. Default trimming was performed.
  2. Hisat2 was used to map the remaining reads against the Leishmania panamensis genome revision 36.
  3. The alignments from hisat2 were used to count reads/gene against the revision 36 annotations with htseq.
  4. These alignments were also passed to the pileup functionality of samtools and the vcf/bcf utilities in order to make a matrix of all observed differences between each sample with respect to the reference.

The analyses in this document use the matrices of counts/gene from #3 and variants/position from #4 in order to provide some images and metrics describing the samples we have sequenced so far.

2 Annotations

Everything which follows depends on the Existing TriTrypDB annotations revision 46, circa 2019. The following block loads a database of these annotations and turns it into a matrix where the rows are genes and columns are all the annotation types provided by TriTrypDB.

The same database was used to create a matrix of orthologous genes between L.panamensis and all of the other species in the TriTrypDB.

tt <- sm(library(EuPathDB))
tt <- sm(library(org.Lpanamensis.MHOMCOL81L13.v46.eg.db))
pan_db <- org.Lpanamensis.MHOMCOL81L13.v46.eg.db
all_fields <- columns(pan_db)

all_lp_annot <- sm(load_orgdb_annotations(
    pan_db,
    keytype="gid",
    fields=c("annot_gene_entrez_id", "annot_gene_name",
             "annot_strand", "annot_chromosome", "annot_cds_length",
             "annot_gene_product")))$genes

lp_go <- sm(load_orgdb_go(pan_db))
lp_lengths <- all_lp_annot[, c("gid", "annot_cds_length")]
colnames(lp_lengths)  <- c("ID", "length")

orthos <- sm(EuPathDB::extract_eupath_orthologs(db=pan_db))

hisat_annot <- all_lp_annot
## rownames(hisat_annot) <- paste0("exon_", rownames(hisat_annot), ".E1")

3 Sample Estimation

The process of sample estimation takes two primary inputs:

  1. The sample sheet, which contains all the metadata we currently have on hand, including filenames for the outputs of #3 and #4 above.
  2. The gene annotations.

An expressionset is primary data structure used in R to examine RNASeq data. It is comprised of annotations, metadata, and expression data. In the case of our processing pipeline, the location of the expression data is provided by the filenames in the metadata.

3.1 Generate expressionsets

The first lines of the following block create the Expressionset. All of the following lines perform various normalizations and generate plots from it.

sample_sheet <- glue::glue("sample_sheets/tmrc2_samples_{ver}.xlsx")
lp_expt <- sm(create_expt(sample_sheet,
                          gene_info=hisat_annot,
                          id_column="hpglidentifier",
                          file_column="lpanamensisv36hisatfile"))
lp_expt <- set_expt_conditions(lp_expt, fact="zymodemecategorical")

libsizes <- plot_libsize(lp_expt)
## The scale difference between the smallest and largest
## libraries is > 10. Assuming a log10 scale is better, set scale = FALSE if not.
libsizes$plot

## I think samples 7,10 should be removed at minimum, probably also 9,11
nonzero <- plot_nonzero(lp_expt)
nonzero$plot
## Warning: ggrepel: 11 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

plot_boxplot(lp_expt)
## This data will benefit from being displayed on the log scale.
## If this is not desired, set scale='raw'
## Some entries are 0.  We are on log scale, adding 1 to the data.
## Changed 2659 zero count features.

3.2 Distribution Visualization

Najib’s favorite plots are of course the PCA/TNSE. These are nice to look at in order to get a sense of the relationships between samples. They also provide a good opportunity to see what happens when one applies different normalizations, surrogate analyses, filters, etc. In addition, one may set different experimental factors as the primary ‘condition’ (usually the color of plots) and surrogate ‘batches’.

all_norm <- sm(normalize_expt(lp_expt, norm="quant", transform="log2", convert="cpm",
                              batch=FALSE, filter=TRUE))
plot_pca(all_norm, plot_title="PCA of parasite expression values")$plot
## Warning in MASS::cov.trob(data[, vars]): Probable convergence failure

## Warning in MASS::cov.trob(data[, vars]): Probable convergence failure

plot_corheat(all_norm, title="Correlation heatmap of parasite expression values
(Same legend as above)")$plot

plot_sm(all_norm)$plot
## Performing correlation.

sm(plot_variance_coefficients(all_norm))$plot

sm(plot_sample_cvheatmap(all_norm))$plot

## NULL

3.2.1 Notes

The following samples are much lower coverage:

  • TMRC20002
  • TMRC20006
  • TMRC20007
  • TMRC20008

At this time, we do not have very many samples, so the set of metrics/plots is fairly limited. There is really only one factor in the metadata which we can use for performing differential expression analyses, the ‘zymodeme’.

4 Zymodeme analyses

The following sections perform a series of analyses which seek to elucidate differences between the zymodemes 2.2 and 2.3 either through differential expression or variant profiles.

4.1 Differential expression

4.1.1 With respect to zymodeme attribution

zy_expt <- subset_expt(lp_expt, subset="condition=='z2.2'|condition=='z2.3'")
## Using a subset expression.
## There were 30, now there are 16 samples.
zy_de <- sm(all_pairwise(zy_expt, filter=TRUE, model_batch="svaseq"))
zy_table <- sm(combine_de_tables(zy_de, excel=glue::glue("excel/zy_tables-v{ver}.xlsx")))
zy_sig <- sm(extract_significant_genes(zy_table, excel=glue::glue("excel/zy_sig-v{ver}.xlsx")))

4.2 With respect to cure/failure

cf_expt <- set_expt_conditions(lp_expt, fact="clinicalcategorical")
cf_norm <- sm(normalize_expt(cf_expt, filter=TRUE, norm="quant", transform="log2",
                             convert="cpm", batch="svaseq"))
plot_pca(cf_norm)$plot
## Warning in MASS::cov.trob(data[, vars]): Probable convergence failure

## Warning in MASS::cov.trob(data[, vars]): Probable convergence failure
cf_de <- sm(all_pairwise(cf_expt, filter=TRUE, model_batch="svaseq"))
cf_table <- sm(combine_de_tables(cf_de, excel=glue::glue("excel/cf_tables-v{ver}.xlsx")))
cf_sig <- sm(extract_significant_genes(cf_table, excel=glue::glue("excel/cf_sig-v{ver}.xlsx")))

4.3 Ontology searches

colnames(lp_go)
## [1] "GID"      "GO"       "EVIDENCE" "ONTOLOGY"
lp_go <- lp_go[, c("GID", "GOALL")]
## Error in `[.data.frame`(lp_go, , c("GID", "GOALL")): undefined columns selected
colnames(lp_go) <- c("ID", "GO")

## Gene categories more represented in the 2.3 group.
zy_go_up <- sm(simple_goseq(sig_genes=zy_sig[["deseq"]][["ups"]][[1]],
                            go_db=lp_go, length_db=lp_lengths))

## Gene categories more represented in the 2.2 group.
zy_go_down <- sm(simple_goseq(sig_genes=zy_sig[["deseq"]][["downs"]][[1]],
                              go_db=lp_go, length_db=lp_lengths))

4.3.1 A couple plots from the differential expression

4.3.1.1 Number of genes in agreement among DE methods, 2.3 more than 2.2

zy_table[["venns"]][[1]][["p_lfc1"]][["up_noweight"]]

4.3.1.2 Number of genes in agreement among DE methods, 2.2 more than 2.3

zy_table[["venns"]][[1]][["p_lfc1"]][["down_noweight"]]

4.3.1.3 MA plot of the differential expression between the zymodemes.

zy_table$plots[[1]][["deseq_ma_plots"]][["plot"]]

4.3.1.4 goseq ontology plots of groups of genes, 2.3 more than 2.2

zy_go_up$pvalue_plots$bpp_plot_over

4.3.1.5 goseq ontology plots of groups of genes, 2.2 more than 2.3

zy_go_down$pvalue_plots$bpp_plot_over

4.4 Zymodeme enzyme gene IDs

Najib read me an email listing off the gene names associated with the zymodeme classification. I took those names and cross referenced them against the Leishmania panamensis gene annotations and found the following:

They are:

  1. ALAT: LPAL13_120010900 – alanine aminotransferase
  2. ASAT: LPAL13_340013000 – aspartate aminotransferase
  3. G6PD: LPAL13_000054100 – glucase-6-phosphate 1-dehydrogenase
  4. NH: LPAL13_14006100, LPAL13_180018500 – inosine-guanine nucleoside hydrolase
  5. MPI: LPAL13_320022300 (maybe) – mannose phosphate isomerase (I chose phosphomannose isomerase)

Given these 6 gene IDs (NH has two gene IDs associated with it), I can do some looking for specific differences among the various samples.

4.4.1 Expression levels of zymodeme genes

The following creates a colorspace (red to green) heatmap showing the observed expression of these genes in every sample.

my_genes <- c("LPAL13_120010900", "LPAL13_340013000", "LPAL13_000054100",
              "LPAL13_140006100", "LPAL13_180018500", "LPAL13_320022300",
              "other")
my_names <- c("ALAT", "ASAT", "G6PD", "NHv1", "NHv2", "MPI", "other")

zymo_expt <- exclude_genes_expt(all_norm, ids=my_genes, method="keep")
## Before removal, there were 8636 entries.
## Now there are 6 entries.
## Percent of the counts kept after filtering: 0.086, 0.081, 0.084, 0.083, 0.083, 0.085, 0.086, 0.083, 0.084, 0.087, 0.083, 0.084, 0.083, 0.084, 0.083, 0.083, 0.085, 0.085, 0.083, 0.083, 0.083, 0.083, 0.081, 0.081, 0.085, 0.085, 0.081, 0.082, 0.087, 0.081
## There are 30 samples which kept less than 90 percent counts.
##      TMRC20001 TMRC20002 TMRC20004 TMRC20005 TMRC20006 TMRC20029 TMRC20007
##      TMRC20008 TMRC20027 TMRC20028 TMRC20032 TMRC20015 TMRC20009 TMRC20010
##      TMRC20016 TMRC20011 TMRC20012 TMRC20013 TMRC20017 TMRC20014 TMRC20018
##      TMRC20019 TMRC20020 TMRC20021 TMRC20022 TMRC20025 TMRC20024 TMRC20033
##      TMRC20026 TMRC20031
test <- plot_sample_heatmap(zymo_expt, row_label=my_names)

4.5 Empirically observed Zymodeme genes from differential expression analysis

In contrast, the following plots take the set of genes which are shared among all differential expression methods (|lfc| >= 1.0 and adjp <= 0.05) and use them to make categories of genes which are increased in 2.3 or 2.2.

shared_zymo <- intersect_significant(zy_table)
## Deleting the file excel/intersect_significant.xlsx before writing the tables.

up_shared <- shared_zymo[["ups"]][[1]][["data"]][["all"]]
rownames(up_shared)
##  [1] "LPAL13_000033300" "LPAL13_000012000" "LPAL13_310031300" "LPAL13_000038400"
##  [5] "LPAL13_340039600" "LPAL13_210015500" "LPAL13_050005000" "LPAL13_310039200"
##  [9] "LPAL13_000038500" "LPAL13_270034100" "LPAL13_170015400" "LPAL13_350044000"
## [13] "LPAL13_200013000" "LPAL13_340039700" "LPAL13_000041000" "LPAL13_330021800"
## [17] "LPAL13_240009700" "LPAL13_140019300" "LPAL13_140019100" "LPAL13_320038700"
## [21] "LPAL13_330021900" "LPAL13_260031400" "LPAL13_210005000" "LPAL13_280037900"
## [25] "LPAL13_350073200" "LPAL13_160014200" "LPAL13_000010600" "LPAL13_140019200"
## [29] "LPAL13_230011500" "LPAL13_230011200" "LPAL13_310028500" "LPAL13_230011300"
## [33] "LPAL13_250025700"
upshared_expt <- exclude_genes_expt(all_norm, ids=rownames(up_shared), method="keep")
## Before removal, there were 8636 entries.
## Now there are 33 entries.
## Percent of the counts kept after filtering: 0.322, 0.258, 0.232, 0.224, 0.246, 0.236, 0.230, 0.222, 0.255, 0.249, 0.269, 0.341, 0.229, 0.338, 0.333, 0.239, 0.220, 0.337, 0.237, 0.236, 0.337, 0.224, 0.228, 0.341, 0.221, 0.255, 0.247, 0.227, 0.233, 0.230
## There are 30 samples which kept less than 90 percent counts.
##      TMRC20001 TMRC20002 TMRC20004 TMRC20005 TMRC20006 TMRC20029 TMRC20007
##      TMRC20008 TMRC20027 TMRC20028 TMRC20032 TMRC20015 TMRC20009 TMRC20010
##      TMRC20016 TMRC20011 TMRC20012 TMRC20013 TMRC20017 TMRC20014 TMRC20018
##      TMRC20019 TMRC20020 TMRC20021 TMRC20022 TMRC20025 TMRC20024 TMRC20033
##      TMRC20026 TMRC20031

4.5.1 Heatmap of zymodeme gene expression increased in 2.3 vs. 2.2

test <- plot_sample_heatmap(upshared_expt, row_label=rownames(up_shared))

4.5.2 Heatmap of zymodeme gene expression increased in 2.2 vs. 2.3

down_shared <- shared_zymo[["downs"]][[1]][["data"]][["all"]]
downshared_expt <- exclude_genes_expt(all_norm, ids=rownames(down_shared), method="keep")
## Before removal, there were 8636 entries.
## Now there are 85 entries.
## Percent of the counts kept after filtering: 0.574, 0.970, 0.881, 0.885, 0.935, 0.857, 0.881, 0.899, 0.571, 0.539, 0.790, 0.528, 0.922, 0.505, 0.552, 0.920, 0.876, 0.535, 0.909, 0.933, 0.539, 0.910, 0.918, 0.542, 0.952, 0.665, 0.930, 0.930, 0.904, 0.880
## There are 30 samples which kept less than 90 percent counts.
##      TMRC20001 TMRC20002 TMRC20004 TMRC20005 TMRC20006 TMRC20029 TMRC20007
##      TMRC20008 TMRC20027 TMRC20028 TMRC20032 TMRC20015 TMRC20009 TMRC20010
##      TMRC20016 TMRC20011 TMRC20012 TMRC20013 TMRC20017 TMRC20014 TMRC20018
##      TMRC20019 TMRC20020 TMRC20021 TMRC20022 TMRC20025 TMRC20024 TMRC20033
##      TMRC20026 TMRC20031
test <- plot_sample_heatmap(downshared_expt, row_label=rownames(down_shared))

5 SNP profiles

In this block, I am combining our previous samples and our new samples in the hopes of finding variant positions which help elucidate aspects of either the new or old samples. In other words, we do not know the zymodeme annotations for the old samples nor the strain identities (or the shortcut ‘chronic vs. self-healing’) for the new samples. We may be able to make educated guesses given the variant profiles. There are some differences in how the previous and current data sets were analyzed (though I have since redone the old samples so it should be trivial to remove those differences now).

old_expt <- sm(create_expt("sample_sheets/tmrc2_samples_20191203.xlsx",
                           file_column="tophat2file"))

tt <- lp_expt$expressionset
rownames(tt) <- gsub(pattern="^exon_", replacement="", x=rownames(tt))
rownames(tt) <- gsub(pattern="\\.E1$", replacement="", x=rownames(tt))
lp_expt$expressionset <- tt

tt <- old_expt$expressionset
rownames(tt) <- gsub(pattern="^exon_", replacement="", x=rownames(tt))
rownames(tt) <- gsub(pattern="\\.1$", replacement="", x=rownames(tt))
old_expt$expressionset <- tt

new_snps <- sm(count_expt_snps(lp_expt, annot_column="bcftable"))
## Error: 'preprocessing/tmrc20001/outputs/vcfutils_lpanamensis_v36/concatenated_lpanamensis_v36_count.txt' does not exist in current working directory ('/mnt/sshfs_10186/cbcbsub00/fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019').
old_snps <- sm(count_expt_snps(old_expt, annot_column="bcftable", snp_column=2))

both_snps <- combine_expts(new_snps, old_snps)
## Error in combine_expts(new_snps, old_snps): object 'new_snps' not found
both_norm <- sm(normalize_expt(both_snps, transform="log2", convert="cpm", filter=TRUE))
## Error in normalize_expt(both_snps, transform = "log2", convert = "cpm", : object 'both_snps' not found
## strains <- both_norm[["design"]][["strain"]]
both_norm <- set_expt_conditions(both_norm, fact="strain")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'pData': object 'both_norm' not found

5.1 Plot of SNP profiles for zymodemes

The following plot shows the SNP profiles of all samples (old and new) where the colors at the top show either the 2.2 strains (orange), 2.3 strains (green), the previous samples (purple), or the various lab strains (pink etc).

tt <- plot_disheat(both_norm)
## Error in plot_heatmap(expt_data, expt_colors = expt_colors, expt_design = expt_design, : object 'both_norm' not found
snp_sets <- get_snp_sets(both_snps, factor="condition")
## Error in get_snp_sets(both_snps, factor = "condition"): object 'both_snps' not found
both_expt <- combine_expts(lp_expt, old_expt)
snp_genes <- sm(snps_vs_genes(both_expt, snp_sets, expt_name_col="chromosome"))
## Error in snps_vs_genes(both_expt, snp_sets, expt_name_col = "chromosome"): object 'snp_sets' not found
snp_subset <- sm(snp_subset_genes(
  both_expt, both_snps,
  genes=c("LPAL13_120010900", "LPAL13_340013000", "LPAL13_000054100",
          "LPAL13_140006100", "LPAL13_180018500", "LPAL13_320022300")))
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'fData': object 'both_snps' not found
## zymo_heat <- plot_sample_heatmap(snp_subset, row_label=rownames(exprs(snp_subset)))

6 Clinical response for new samples

clinical_sets <- get_snp_sets(new_snps, factor="clinicalresponse")
## Error in get_snp_sets(new_snps, factor = "clinicalresponse"): object 'new_snps' not found
clinical_genes <- sm(snps_vs_genes(lp_expt, clinical_sets, expt_name_col="chromosome"))
## Error in snps_vs_genes(lp_expt, clinical_sets, expt_name_col = "chromosome"): object 'clinical_sets' not found
clinical_snps <- snps_intersections(lp_expt, clinical_sets, chr_column="chromosome")
## Error in snps_intersections(lp_expt, clinical_sets, chr_column = "chromosome"): object 'clinical_sets' not found
head(as.data.frame(clinical_snps$inters[["Failure"]]))
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'head': error in evaluating the argument 'x' in selecting a method for function 'as.data.frame': object 'clinical_snps' not found
head(as.data.frame(clinical_snps$inters[["Cure"]]))
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'head': error in evaluating the argument 'x' in selecting a method for function 'as.data.frame': object 'clinical_snps' not found
head(clinical_snps$gene_summaries$Failure)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'head': object 'clinical_snps' not found
head(clinical_snps$gene_summaries$Cure)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'head': object 'clinical_snps' not found
annot <- fData(lp_expt)
clinical_interest <- as.data.frame(clinical_snps[["gene_summaries"]][["Cure"]])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'as.data.frame': object 'clinical_snps' not found
clinical_interest <- merge(clinical_interest, as.data.frame(clinical_snps[["gene_summaries"]][["Failure"]]), by="row.names")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'merge': object 'clinical_interest' not found
rownames(clinical_interest) <- clinical_interest[["Row.names"]]
## Error in eval(expr, envir, enclos): object 'clinical_interest' not found
clinical_interest[["Row.names"]] <- NULL
## Error in clinical_interest[["Row.names"]] <- NULL: object 'clinical_interest' not found
colnames(clinical_interest) <- c("cure_snps","fail_snps")
## Error in colnames(clinical_interest) <- c("cure_snps", "fail_snps"): object 'clinical_interest' not found
annot <- merge(annot, clinical_interest, by="row.names")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'y' in selecting a method for function 'merge': object 'clinical_interest' not found
rownames(annot) <- annot[["Row.names"]]
annot[["Row.names"]] <- NULL
fData(lp_expt$expressionset) <- annot

7 Zymodeme for new samples

The heatmap produced here should show the variants only for the zymodeme genes.

new_sets <- get_snp_sets(new_snps, factor="phenotypiccharacteristics")
## Error in get_snp_sets(new_snps, factor = "phenotypiccharacteristics"): object 'new_snps' not found
snp_genes <- sm(snps_vs_genes(lp_expt, new_sets, expt_name_col="chromosome"))
## Error in snps_vs_genes(lp_expt, new_sets, expt_name_col = "chromosome"): object 'new_sets' not found
new_zymo_norm  <-  normalize_expt(new_snps, filter=TRUE, convert="cpm", norm="quant", transform=TRUE)
## Error in normalize_expt(new_snps, filter = TRUE, convert = "cpm", norm = "quant", : object 'new_snps' not found
new_zymo_norm <- set_expt_conditions(new_zymo_norm, fact="phenotypiccharacteristics")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'pData': object 'new_zymo_norm' not found
zymo_heat <- plot_disheat(new_zymo_norm)
## Error in plot_heatmap(expt_data, expt_colors = expt_colors, expt_design = expt_design, : object 'new_zymo_norm' not found
zymo_subset <- snp_subset_genes(lp_expt, new_snps,
                                genes=c("LPAL13_120010900", "LPAL13_340013000", "LPAL13_000054100",
                                        "LPAL13_140006100", "LPAL13_180018500", "LPAL13_320022300"))
## Error: subscript contains invalid names
zymo_subset <- set_expt_conditions(zymo_subset, fact="phenotypiccharacteristics")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'pData': object 'zymo_subset' not found
## zymo_heat <- plot_sample_heatmap(zymo_subset, row_label=rownames(exprs(snp_subset)))

des <- both_norm$design
## Error in eval(expr, envir, enclos): object 'both_norm' not found
undef_idx <- is.na(des[["strain"]])
## Error in eval(expr, envir, enclos): object 'des' not found
des[undef_idx, "strain"] <- "unknown"
## Error in des[undef_idx, "strain"] <- "unknown": object 'des' not found
##hmcols <- colorRampPalette(c("yellow","black","darkblue"))(256)
correlations <- hpgl_cor(exprs(both_norm))
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'exprs': object 'both_norm' not found
zymo_missing_idx <- is.na(des[["phenotypiccharacteristics"]])
## Error in eval(expr, envir, enclos): object 'des' not found
des[zymo_missing_idx, "phenotypiccharacteristics"] <- "unknown"
## Error in des[zymo_missing_idx, "phenotypiccharacteristics"] <- "unknown": object 'des' not found
mydendro <- list(
  "clustfun" = hclust,
  "lwd" = 2.0)
col_data <- as.data.frame(des[, c("phenotypiccharacteristics", "clinicalcategorical")])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'as.data.frame': object 'des' not found
unknown_clinical <- is.na(col_data[["clinicalcategorical"]])
## Error in eval(expr, envir, enclos): object 'col_data' not found
row_data <- as.data.frame(des[, c("strain")])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'as.data.frame': object 'des' not found
colnames(col_data) <- c("zymodeme", "outcome")
## Error in colnames(col_data) <- c("zymodeme", "outcome"): object 'col_data' not found
col_data[unknown_clinical, "outcome"] <- "undefined"
## Error in col_data[unknown_clinical, "outcome"] <- "undefined": object 'col_data' not found
colnames(row_data) <- c("strain")
## Error in colnames(row_data) <- c("strain"): object 'row_data' not found
myannot <- list(
  "Col" = list("data" = col_data),
  "Row" = list("data" = row_data))
## Error in eval(expr, envir, enclos): object 'col_data' not found
myclust <- list("cuth" = 1.0,
                "col" = BrewerClusterCol)
mylabs <- list(
  "Row" = list("nrow" = 4),
  "Col" = list("nrow" = 4))
hmcols <- colorRampPalette(c("darkblue", "beige"))(170)
map1 <- annHeatmap2(
  correlations,
  dendrogram=mydendro,
  annotation=myannot,
  cluster=myclust,
  labels=mylabs,
  col=hmcols)
## Error in annHeatmap2(correlations, dendrogram = mydendro, annotation = myannot, : object 'correlations' not found
plot(map1)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'plot': object 'map1' not found

8 Using Variant profiles to make guesses about strains and chronic/self-healing

The following uses the same information to make some guesses about the strains used in the new samples.

des <- both_norm$design
## Error in eval(expr, envir, enclos): object 'both_norm' not found
undef_idx <- is.na(des[["strain"]])
## Error in eval(expr, envir, enclos): object 'des' not found
des[undef_idx, "strain"] <- "unknown"
## Error in des[undef_idx, "strain"] <- "unknown": object 'des' not found
##hmcols <- colorRampPalette(c("yellow","black","darkblue"))(256)
correlations <- hpgl_cor(exprs(both_norm))
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'exprs': object 'both_norm' not found
mydendro <- list(
  "clustfun" = hclust,
  "lwd" = 2.0)
col_data <- as.data.frame(des[, c("condition")])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'as.data.frame': object 'des' not found
row_data <- as.data.frame(des[, c("strain")])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'as.data.frame': object 'des' not found
colnames(col_data) <- c("condition")
## Error in colnames(col_data) <- c("condition"): object 'col_data' not found
colnames(row_data) <- c("strain")
## Error in colnames(row_data) <- c("strain"): object 'row_data' not found
myannot <- list(
  "Col" = list("data" = col_data),
  "Row" = list("data" = row_data))
## Error in eval(expr, envir, enclos): object 'col_data' not found
myclust <- list("cuth" = 1.0,
                "col" = BrewerClusterCol)
mylabs <- list(
  "Row" = list("nrow" = 4),
  "Col" = list("nrow" = 4))
hmcols <- colorRampPalette(c("darkblue", "beige"))(170)
map1 <- annHeatmap2(
  correlations,
  dendrogram=mydendro,
  annotation=myannot,
  cluster=myclust,
  labels=mylabs,
  col=hmcols)
## Error in annHeatmap2(correlations, dendrogram = mydendro, annotation = myannot, : object 'correlations' not found
plot(map1)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'plot': object 'map1' not found
pheno <- subset_expt(lp_expt, subset="condition=='z2.2'|condition=='z2.3'")
## Using a subset expression.
## There were 30, now there are 16 samples.
pheno_snps <- sm(count_expt_snps(pheno, annot_column="bcftable"))
## Error: 'preprocessing/tmrc20001/outputs/vcfutils_lpanamensis_v36/concatenated_lpanamensis_v36_count.txt' does not exist in current working directory ('/mnt/sshfs_10186/cbcbsub00/fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/lpanamensis_tmrc_2019').
xref_prop <- table(pheno_snps$conditions)
## Error in eval(quote(list(...)), env): object 'pheno_snps' not found
pheno_snps$conditions
## Error in eval(expr, envir, enclos): object 'pheno_snps' not found
idx_tbl <- exprs(pheno_snps) > 5
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'exprs': object 'pheno_snps' not found
new_tbl <- data.frame(row.names=rownames(exprs(pheno_snps)))
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'rownames': error in evaluating the argument 'object' in selecting a method for function 'exprs': object 'pheno_snps' not found
for (n in names(xref_prop)) {
  new_tbl[[n]] <- 0
  idx_cols <- which(pheno_snps[["conditions"]] == n)
  prop_col <- rowSums(idx_tbl[, idx_cols]) / xref_prop[n]
  new_tbl[n] <- prop_col
}
## Error in eval(expr, envir, enclos): object 'xref_prop' not found
new_tbl[["ratio"]] <- (new_tbl[["z2.2"]] - new_tbl[["z2.3"]])
## Error in eval(expr, envir, enclos): object 'new_tbl' not found
keepers <- grepl(x=rownames(new_tbl), pattern="LpaL13")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'grepl': error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'new_tbl' not found
new_tbl <- new_tbl[keepers, ]
## Error in eval(expr, envir, enclos): object 'new_tbl' not found
new_tbl[["SNP"]] <- rownames(new_tbl)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'new_tbl' not found
new_tbl[["Chromosome"]] <- gsub(x=new_tbl[["SNP"]], pattern="chr_(.*)_pos_.*", replacement="\\1")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'gsub': object 'new_tbl' not found
new_tbl[["Position"]] <- gsub(x=new_tbl[["SNP"]], pattern=".*_pos_(\\d+)_.*", replacement="\\1")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'gsub': object 'new_tbl' not found
new_tbl <- new_tbl[, c("SNP", "Chromosome", "Position", "ratio")]
## Error in eval(expr, envir, enclos): object 'new_tbl' not found
library(CMplot)
## Much appreciate for using CMplot.
## Full description, Bug report, Suggestion and the latest codes:
## https://github.com/YinLiLin/CMplot
CMplot(new_tbl)
## Error in is.data.frame(x): object 'new_tbl' not found
if (!isTRUE(get0("skip_load"))) {
  pander::pander(sessionInfo())
  message(paste0("This is hpgltools commit: ", get_git_commit()))
  message(paste0("Saving to ", savefile))
  tmp <- sm(saveme(filename=savefile))
}
## If you wish to reproduce this exact build of hpgltools, invoke the following:
## > git clone http://github.com/abelew/hpgltools.git
## > git reset 3866d0ef3d5bf766f01b092108ec06406921447c
## This is hpgltools commit: Mon Mar 22 15:33:04 2021 -0400: 3866d0ef3d5bf766f01b092108ec06406921447c
## Saving to tmrc2_02sample_estimation_v202103.rda.xz
tmp <- loadme(filename=savefile)
LS0tCnRpdGxlOiAiVE1SQzIgQ29tcHJlaGVuc2l2ZSBEYXRhIEFuYWx5c2lzOiAyMDIxMDMiCmF1dGhvcjogImF0YiBhYmVsZXdAZ21haWwuY29tIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKIGh0bWxfZG9jdW1lbnQ6CiAgY29kZV9kb3dubG9hZDogdHJ1ZQogIGNvZGVfZm9sZGluZzogc2hvdwogIGZpZ19jYXB0aW9uOiB0cnVlCiAgZmlnX2hlaWdodDogNwogIGZpZ193aWR0aDogNwogIGhpZ2hsaWdodDogZGVmYXVsdAogIGtlZXBfbWQ6IGZhbHNlCiAgbW9kZTogc2VsZmNvbnRhaW5lZAogIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgdGhlbWU6IHJlYWRhYmxlCiAgdG9jOiB0cnVlCiAgdG9jX2Zsb2F0OgogICBjb2xsYXBzZWQ6IGZhbHNlCiAgIHNtb290aF9zY3JvbGw6IGZhbHNlCi0tLQoKPHN0eWxlPgogIGJvZHkgLm1haW4tY29udGFpbmVyIHsKICAgIG1heC13aWR0aDogMTYwMHB4OwogIH0KPC9zdHlsZT4KCmBgYHtyIG9wdGlvbnMsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoaHBnbHRvb2xzKQp0dCA8LSBzbShkZXZ0b29sczo6bG9hZF9hbGwoIn4vaHBnbHRvb2xzIikpCmtuaXRyOjpvcHRzX2tuaXQkc2V0KHByb2dyZXNzPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgIHZlcmJvc2U9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgd2lkdGg9OTAsCiAgICAgICAgICAgICAgICAgICAgIGVjaG89VFJVRSkKa25pdHI6Om9wdHNfY2h1bmskc2V0KGVycm9yPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgICBmaWcud2lkdGg9OCwKICAgICAgICAgICAgICAgICAgICAgIGZpZy5oZWlnaHQ9OCwKICAgICAgICAgICAgICAgICAgICAgIGRwaT05NikKb2xkX29wdGlvbnMgPC0gb3B0aW9ucyhkaWdpdHM9NCwKICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzPUZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgIGtuaXRyLmR1cGxpY2F0ZS5sYWJlbD0iYWxsb3ciKQpnZ3Bsb3QyOjp0aGVtZV9zZXQoZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplPTEyKSkKdmVyIDwtICIyMDIxMDMiCnJ1bmRhdGUgPC0gZm9ybWF0KFN5cy5EYXRlKCksIGZvcm1hdD0iJVklbSVkIikKCiMjIHRtcCA8LSB0cnkoc20obG9hZG1lKGZpbGVuYW1lPWdzdWIocGF0dGVybj0iXFwuUm1kIiwgcmVwbGFjZT0iXFwucmRhXFwueHoiLCB4PXByZXZpb3VzX2ZpbGUpKSkpCnJtZF9maWxlIDwtICJ0bXJjMl8wMnNhbXBsZV9lc3RpbWF0aW9uX3YyMDIxMDMuUm1kIgpzYXZlZmlsZSA8LSBnc3ViKHBhdHRlcm49IlxcLlJtZCIsIHJlcGxhY2U9IlxcLnJkYVxcLnh6IiwgeD1ybWRfZmlsZSkKCmxpYnJhcnkoSGVhdHBsdXMpCmBgYAoKIyBJbnRyb2R1Y3Rpb24KClRoaXMgZG9jdW1lbnQgaXMgaW50ZW5kZWQgdG8gcHJvdmlkZSBhIGdlbmVyYWwgb3ZlcnZpZXcgb2YgdGhlIFRNUkMyIHNhbXBsZXMKd2hpY2ggaGF2ZSB0aHVzIGZhciBiZWVuIHNlcXVlbmNlZC4gIEluIHNvbWUgY2FzZXMsIHRoaXMgaW5jbHVkZXMgb25seSB0aG9zZQpzYW1wbGVzIHN0YXJ0aW5nIGluIDIwMTk7IGluIG90aGVyIGluc3RhbmNlcyBJIGFtIGluY2x1ZGluZyBvdXIgcHJldmlvdXMKKDIwMTUtMjAxNikgc2FtcGxlcy4KCkluIGFsbCBjYXNlcyB0aGUgcHJvY2Vzc2luZyBwZXJmb3JtZWQgd2FzOgoKMS4gIERlZmF1bHQgdHJpbW1pbmcgd2FzIHBlcmZvcm1lZC4KMi4gIEhpc2F0MiB3YXMgdXNlZCB0byBtYXAgdGhlIHJlbWFpbmluZyByZWFkcyBhZ2FpbnN0IHRoZSBMZWlzaG1hbmlhCiAgICBwYW5hbWVuc2lzIGdlbm9tZSByZXZpc2lvbiAzNi4KMy4gIFRoZSBhbGlnbm1lbnRzIGZyb20gaGlzYXQyIHdlcmUgdXNlZCB0byBjb3VudCByZWFkcy9nZW5lIGFnYWluc3QgdGhlCiAgICByZXZpc2lvbiAzNiBhbm5vdGF0aW9ucyB3aXRoIGh0c2VxLgo0LiAgVGhlc2UgYWxpZ25tZW50cyB3ZXJlIGFsc28gcGFzc2VkIHRvIHRoZSBwaWxldXAgZnVuY3Rpb25hbGl0eSBvZiBzYW10b29scwogICAgYW5kIHRoZSB2Y2YvYmNmIHV0aWxpdGllcyBpbiBvcmRlciB0byBtYWtlIGEgbWF0cml4IG9mIGFsbCBvYnNlcnZlZAogICAgZGlmZmVyZW5jZXMgYmV0d2VlbiBlYWNoIHNhbXBsZSB3aXRoIHJlc3BlY3QgdG8gdGhlIHJlZmVyZW5jZS4KClRoZSBhbmFseXNlcyBpbiB0aGlzIGRvY3VtZW50IHVzZSB0aGUgbWF0cmljZXMgb2YgY291bnRzL2dlbmUgZnJvbSAjMyBhbmQKdmFyaWFudHMvcG9zaXRpb24gZnJvbSAjNCBpbiBvcmRlciB0byBwcm92aWRlIHNvbWUgaW1hZ2VzIGFuZCBtZXRyaWNzIGRlc2NyaWJpbmcKdGhlIHNhbXBsZXMgd2UgaGF2ZSBzZXF1ZW5jZWQgc28gZmFyLgoKIyBBbm5vdGF0aW9ucwoKRXZlcnl0aGluZyB3aGljaCBmb2xsb3dzIGRlcGVuZHMgb24gdGhlIEV4aXN0aW5nIFRyaVRyeXBEQiBhbm5vdGF0aW9ucyByZXZpc2lvbgo0NiwgY2lyY2EgMjAxOS4gIFRoZSBmb2xsb3dpbmcgYmxvY2sgbG9hZHMgYSBkYXRhYmFzZSBvZiB0aGVzZSBhbm5vdGF0aW9ucyBhbmQKdHVybnMgaXQgaW50byBhIG1hdHJpeCB3aGVyZSB0aGUgcm93cyBhcmUgZ2VuZXMgYW5kIGNvbHVtbnMgYXJlIGFsbCB0aGUKYW5ub3RhdGlvbiB0eXBlcyBwcm92aWRlZCBieSBUcmlUcnlwREIuCgpUaGUgc2FtZSBkYXRhYmFzZSB3YXMgdXNlZCB0byBjcmVhdGUgYSBtYXRyaXggb2Ygb3J0aG9sb2dvdXMgZ2VuZXMgYmV0d2VlbgpMLnBhbmFtZW5zaXMgYW5kIGFsbCBvZiB0aGUgb3RoZXIgc3BlY2llcyBpbiB0aGUgVHJpVHJ5cERCLgoKYGBge3IgYW5ub3R9CnR0IDwtIHNtKGxpYnJhcnkoRXVQYXRoREIpKQp0dCA8LSBzbShsaWJyYXJ5KG9yZy5McGFuYW1lbnNpcy5NSE9NQ09MODFMMTMudjQ2LmVnLmRiKSkKcGFuX2RiIDwtIG9yZy5McGFuYW1lbnNpcy5NSE9NQ09MODFMMTMudjQ2LmVnLmRiCmFsbF9maWVsZHMgPC0gY29sdW1ucyhwYW5fZGIpCgphbGxfbHBfYW5ub3QgPC0gc20obG9hZF9vcmdkYl9hbm5vdGF0aW9ucygKICAgIHBhbl9kYiwKICAgIGtleXR5cGU9ImdpZCIsCiAgICBmaWVsZHM9YygiYW5ub3RfZ2VuZV9lbnRyZXpfaWQiLCAiYW5ub3RfZ2VuZV9uYW1lIiwKICAgICAgICAgICAgICJhbm5vdF9zdHJhbmQiLCAiYW5ub3RfY2hyb21vc29tZSIsICJhbm5vdF9jZHNfbGVuZ3RoIiwKICAgICAgICAgICAgICJhbm5vdF9nZW5lX3Byb2R1Y3QiKSkpJGdlbmVzCgpscF9nbyA8LSBzbShsb2FkX29yZ2RiX2dvKHBhbl9kYikpCmxwX2xlbmd0aHMgPC0gYWxsX2xwX2Fubm90WywgYygiZ2lkIiwgImFubm90X2Nkc19sZW5ndGgiKV0KY29sbmFtZXMobHBfbGVuZ3RocykgIDwtIGMoIklEIiwgImxlbmd0aCIpCgpvcnRob3MgPC0gc20oRXVQYXRoREI6OmV4dHJhY3RfZXVwYXRoX29ydGhvbG9ncyhkYj1wYW5fZGIpKQoKaGlzYXRfYW5ub3QgPC0gYWxsX2xwX2Fubm90CiMjIHJvd25hbWVzKGhpc2F0X2Fubm90KSA8LSBwYXN0ZTAoImV4b25fIiwgcm93bmFtZXMoaGlzYXRfYW5ub3QpLCAiLkUxIikKYGBgCgojIFNhbXBsZSBFc3RpbWF0aW9uCgpUaGUgcHJvY2VzcyBvZiBzYW1wbGUgZXN0aW1hdGlvbiB0YWtlcyB0d28gcHJpbWFyeSBpbnB1dHM6CgoxLiAgVGhlIHNhbXBsZSBzaGVldCwgd2hpY2ggY29udGFpbnMgYWxsIHRoZSBtZXRhZGF0YSB3ZSBjdXJyZW50bHkgaGF2ZSBvbiBoYW5kLAogICAgaW5jbHVkaW5nIGZpbGVuYW1lcyBmb3IgdGhlIG91dHB1dHMgb2YgIzMgYW5kICM0IGFib3ZlLgoyLiAgVGhlIGdlbmUgYW5ub3RhdGlvbnMuCgpBbiBleHByZXNzaW9uc2V0IGlzIHByaW1hcnkgZGF0YSBzdHJ1Y3R1cmUgdXNlZCBpbiBSIHRvIGV4YW1pbmUgUk5BU2VxIGRhdGEuICBJdAppcyBjb21wcmlzZWQgb2YgYW5ub3RhdGlvbnMsIG1ldGFkYXRhLCBhbmQgZXhwcmVzc2lvbiBkYXRhLiAgSW4gdGhlIGNhc2Ugb2Ygb3VyCnByb2Nlc3NpbmcgcGlwZWxpbmUsIHRoZSBsb2NhdGlvbiBvZiB0aGUgZXhwcmVzc2lvbiBkYXRhIGlzIHByb3ZpZGVkIGJ5IHRoZQpmaWxlbmFtZXMgaW4gdGhlIG1ldGFkYXRhLgoKIyMgR2VuZXJhdGUgZXhwcmVzc2lvbnNldHMKClRoZSBmaXJzdCBsaW5lcyBvZiB0aGUgZm9sbG93aW5nIGJsb2NrIGNyZWF0ZSB0aGUgRXhwcmVzc2lvbnNldC4gIEFsbCBvZiB0aGUKZm9sbG93aW5nIGxpbmVzIHBlcmZvcm0gdmFyaW91cyBub3JtYWxpemF0aW9ucyBhbmQgZ2VuZXJhdGUgcGxvdHMgZnJvbSBpdC4KCmBgYHtyIG5ld19zYW1wbGVzX2hpc2F0fQpzYW1wbGVfc2hlZXQgPC0gZ2x1ZTo6Z2x1ZSgic2FtcGxlX3NoZWV0cy90bXJjMl9zYW1wbGVzX3t2ZXJ9Lnhsc3giKQpscF9leHB0IDwtIHNtKGNyZWF0ZV9leHB0KHNhbXBsZV9zaGVldCwKICAgICAgICAgICAgICAgICAgICAgICAgICBnZW5lX2luZm89aGlzYXRfYW5ub3QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgaWRfY29sdW1uPSJocGdsaWRlbnRpZmllciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZV9jb2x1bW49ImxwYW5hbWVuc2lzdjM2aGlzYXRmaWxlIikpCmxwX2V4cHQgPC0gc2V0X2V4cHRfY29uZGl0aW9ucyhscF9leHB0LCBmYWN0PSJ6eW1vZGVtZWNhdGVnb3JpY2FsIikKCmxpYnNpemVzIDwtIHBsb3RfbGlic2l6ZShscF9leHB0KQpsaWJzaXplcyRwbG90CiMjIEkgdGhpbmsgc2FtcGxlcyA3LDEwIHNob3VsZCBiZSByZW1vdmVkIGF0IG1pbmltdW0sIHByb2JhYmx5IGFsc28gOSwxMQpub256ZXJvIDwtIHBsb3Rfbm9uemVybyhscF9leHB0KQpub256ZXJvJHBsb3QKcGxvdF9ib3hwbG90KGxwX2V4cHQpCmBgYAoKIyMgRGlzdHJpYnV0aW9uIFZpc3VhbGl6YXRpb24KCk5hamliJ3MgZmF2b3JpdGUgcGxvdHMgYXJlIG9mIGNvdXJzZSB0aGUgUENBL1ROU0UuICBUaGVzZSBhcmUgbmljZSB0byBsb29rIGF0IGluCm9yZGVyIHRvIGdldCBhIHNlbnNlIG9mIHRoZSByZWxhdGlvbnNoaXBzIGJldHdlZW4gc2FtcGxlcy4gIFRoZXkgYWxzbyBwcm92aWRlIGEKZ29vZCBvcHBvcnR1bml0eSB0byBzZWUgd2hhdCBoYXBwZW5zIHdoZW4gb25lIGFwcGxpZXMgZGlmZmVyZW50IG5vcm1hbGl6YXRpb25zLApzdXJyb2dhdGUgYW5hbHlzZXMsIGZpbHRlcnMsIGV0Yy4gIEluIGFkZGl0aW9uLCBvbmUgbWF5IHNldCBkaWZmZXJlbnQKZXhwZXJpbWVudGFsIGZhY3RvcnMgYXMgdGhlIHByaW1hcnkgJ2NvbmRpdGlvbicgKHVzdWFsbHkgdGhlIGNvbG9yIG9mIHBsb3RzKSBhbmQKc3Vycm9nYXRlICdiYXRjaGVzJy4KCmBgYHtyIHByZV9xdWVzdGlvbnN9CmFsbF9ub3JtIDwtIHNtKG5vcm1hbGl6ZV9leHB0KGxwX2V4cHQsIG5vcm09InF1YW50IiwgdHJhbnNmb3JtPSJsb2cyIiwgY29udmVydD0iY3BtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmF0Y2g9RkFMU0UsIGZpbHRlcj1UUlVFKSkKcGxvdF9wY2EoYWxsX25vcm0sIHBsb3RfdGl0bGU9IlBDQSBvZiBwYXJhc2l0ZSBleHByZXNzaW9uIHZhbHVlcyIpJHBsb3QKCnBsb3RfY29yaGVhdChhbGxfbm9ybSwgdGl0bGU9IkNvcnJlbGF0aW9uIGhlYXRtYXAgb2YgcGFyYXNpdGUgZXhwcmVzc2lvbiB2YWx1ZXMKKFNhbWUgbGVnZW5kIGFzIGFib3ZlKSIpJHBsb3QKcGxvdF9zbShhbGxfbm9ybSkkcGxvdApzbShwbG90X3ZhcmlhbmNlX2NvZWZmaWNpZW50cyhhbGxfbm9ybSkpJHBsb3QKc20ocGxvdF9zYW1wbGVfY3ZoZWF0bWFwKGFsbF9ub3JtKSkkcGxvdApgYGAKCiMjIyBOb3RlcwoKVGhlIGZvbGxvd2luZyBzYW1wbGVzIGFyZSBtdWNoIGxvd2VyIGNvdmVyYWdlOgoKKiBUTVJDMjAwMDIKKiBUTVJDMjAwMDYKKiBUTVJDMjAwMDcKKiBUTVJDMjAwMDgKCkF0IHRoaXMgdGltZSwgd2UgZG8gbm90IGhhdmUgdmVyeSBtYW55IHNhbXBsZXMsIHNvIHRoZSBzZXQgb2YgbWV0cmljcy9wbG90cyBpcwpmYWlybHkgbGltaXRlZC4gIFRoZXJlIGlzIHJlYWxseSBvbmx5IG9uZSBmYWN0b3IgaW4gdGhlIG1ldGFkYXRhIHdoaWNoIHdlIGNhbgp1c2UgZm9yIHBlcmZvcm1pbmcgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYW5hbHlzZXMsIHRoZSAnenltb2RlbWUnLgoKIyBaeW1vZGVtZSBhbmFseXNlcwoKVGhlIGZvbGxvd2luZyBzZWN0aW9ucyBwZXJmb3JtIGEgc2VyaWVzIG9mIGFuYWx5c2VzIHdoaWNoIHNlZWsgdG8gZWx1Y2lkYXRlCmRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIHp5bW9kZW1lcyAyLjIgYW5kIDIuMyBlaXRoZXIgdGhyb3VnaCBkaWZmZXJlbnRpYWwKZXhwcmVzc2lvbiBvciB2YXJpYW50IHByb2ZpbGVzLgoKIyMgRGlmZmVyZW50aWFsIGV4cHJlc3Npb24KCiMjIyBXaXRoIHJlc3BlY3QgdG8genltb2RlbWUgYXR0cmlidXRpb24KCmBgYHtyIHp5bW9fZGUsIGZpZy5zaG93PSJoaWRlIn0KenlfZXhwdCA8LSBzdWJzZXRfZXhwdChscF9leHB0LCBzdWJzZXQ9ImNvbmRpdGlvbj09J3oyLjInfGNvbmRpdGlvbj09J3oyLjMnIikKenlfZGUgPC0gc20oYWxsX3BhaXJ3aXNlKHp5X2V4cHQsIGZpbHRlcj1UUlVFLCBtb2RlbF9iYXRjaD0ic3Zhc2VxIikpCnp5X3RhYmxlIDwtIHNtKGNvbWJpbmVfZGVfdGFibGVzKHp5X2RlLCBleGNlbD1nbHVlOjpnbHVlKCJleGNlbC96eV90YWJsZXMtdnt2ZXJ9Lnhsc3giKSkpCnp5X3NpZyA8LSBzbShleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKHp5X3RhYmxlLCBleGNlbD1nbHVlOjpnbHVlKCJleGNlbC96eV9zaWctdnt2ZXJ9Lnhsc3giKSkpCmBgYAoKIyMgV2l0aCByZXNwZWN0IHRvIGN1cmUvZmFpbHVyZQoKYGBge3IgY3VyZWZhaWxfZGUsIGZpZy5zaG93PSJoaWRlIn0KY2ZfZXhwdCA8LSBzZXRfZXhwdF9jb25kaXRpb25zKGxwX2V4cHQsIGZhY3Q9ImNsaW5pY2FsY2F0ZWdvcmljYWwiKQpjZl9ub3JtIDwtIHNtKG5vcm1hbGl6ZV9leHB0KGNmX2V4cHQsIGZpbHRlcj1UUlVFLCBub3JtPSJxdWFudCIsIHRyYW5zZm9ybT0ibG9nMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udmVydD0iY3BtIiwgYmF0Y2g9InN2YXNlcSIpKQpwbG90X3BjYShjZl9ub3JtKSRwbG90CgpjZl9kZSA8LSBzbShhbGxfcGFpcndpc2UoY2ZfZXhwdCwgZmlsdGVyPVRSVUUsIG1vZGVsX2JhdGNoPSJzdmFzZXEiKSkKY2ZfdGFibGUgPC0gc20oY29tYmluZV9kZV90YWJsZXMoY2ZfZGUsIGV4Y2VsPWdsdWU6OmdsdWUoImV4Y2VsL2NmX3RhYmxlcy12e3Zlcn0ueGxzeCIpKSkKY2Zfc2lnIDwtIHNtKGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoY2ZfdGFibGUsIGV4Y2VsPWdsdWU6OmdsdWUoImV4Y2VsL2NmX3NpZy12e3Zlcn0ueGxzeCIpKSkKYGBgCgojIyBPbnRvbG9neSBzZWFyY2hlcwoKYGBge3IgZ28sIHNpZy5zaG93PSJoaWRlIn0KY29sbmFtZXMobHBfZ28pCmxwX2dvIDwtIGxwX2dvWywgYygiR0lEIiwgIkdPQUxMIildCmNvbG5hbWVzKGxwX2dvKSA8LSBjKCJJRCIsICJHTyIpCgojIyBHZW5lIGNhdGVnb3JpZXMgbW9yZSByZXByZXNlbnRlZCBpbiB0aGUgMi4zIGdyb3VwLgp6eV9nb191cCA8LSBzbShzaW1wbGVfZ29zZXEoc2lnX2dlbmVzPXp5X3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1sxXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnb19kYj1scF9nbywgbGVuZ3RoX2RiPWxwX2xlbmd0aHMpKQoKIyMgR2VuZSBjYXRlZ29yaWVzIG1vcmUgcmVwcmVzZW50ZWQgaW4gdGhlIDIuMiBncm91cC4KenlfZ29fZG93biA8LSBzbShzaW1wbGVfZ29zZXEoc2lnX2dlbmVzPXp5X3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV1bWzFdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ29fZGI9bHBfZ28sIGxlbmd0aF9kYj1scF9sZW5ndGhzKSkKYGBgCgojIyMgQSBjb3VwbGUgcGxvdHMgZnJvbSB0aGUgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24KCiMjIyMgTnVtYmVyIG9mIGdlbmVzIGluIGFncmVlbWVudCBhbW9uZyBERSBtZXRob2RzLCAyLjMgbW9yZSB0aGFuIDIuMgoKYGBge3IgZGVfcGxvdHN9Cnp5X3RhYmxlW1sidmVubnMiXV1bWzFdXVtbInBfbGZjMSJdXVtbInVwX25vd2VpZ2h0Il1dCmBgYAoKIyMjIyBOdW1iZXIgb2YgZ2VuZXMgaW4gYWdyZWVtZW50IGFtb25nIERFIG1ldGhvZHMsIDIuMiBtb3JlIHRoYW4gMi4zCgpgYGB7ciBkZV9wbG90c30KenlfdGFibGVbWyJ2ZW5ucyJdXVtbMV1dW1sicF9sZmMxIl1dW1siZG93bl9ub3dlaWdodCJdXQpgYGAKCiMjIyMgTUEgcGxvdCBvZiB0aGUgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYmV0d2VlbiB0aGUgenltb2RlbWVzLgoKYGBge3Igb3RoZXJfcGxvdHN9Cnp5X3RhYmxlJHBsb3RzW1sxXV1bWyJkZXNlcV9tYV9wbG90cyJdXVtbInBsb3QiXV0KYGBgCgojIyMjIGdvc2VxIG9udG9sb2d5IHBsb3RzIG9mIGdyb3VwcyBvZiBnZW5lcywgMi4zIG1vcmUgdGhhbiAyLjIKCmBgYHtyIGdvc2VxX3VwfQp6eV9nb191cCRwdmFsdWVfcGxvdHMkYnBwX3Bsb3Rfb3ZlcgpgYGAKCiMjIyMgZ29zZXEgb250b2xvZ3kgcGxvdHMgb2YgZ3JvdXBzIG9mIGdlbmVzLCAyLjIgbW9yZSB0aGFuIDIuMwoKYGBge3IgZ29zZXFfZG93bn0KenlfZ29fZG93biRwdmFsdWVfcGxvdHMkYnBwX3Bsb3Rfb3ZlcgpgYGAKCiMjIFp5bW9kZW1lIGVuenltZSBnZW5lIElEcwoKTmFqaWIgcmVhZCBtZSBhbiBlbWFpbCBsaXN0aW5nIG9mZiB0aGUgZ2VuZSBuYW1lcyBhc3NvY2lhdGVkIHdpdGggdGhlIHp5bW9kZW1lCmNsYXNzaWZpY2F0aW9uLiAgSSB0b29rIHRob3NlIG5hbWVzIGFuZCBjcm9zcyByZWZlcmVuY2VkIHRoZW0gYWdhaW5zdCB0aGUKTGVpc2htYW5pYSBwYW5hbWVuc2lzIGdlbmUgYW5ub3RhdGlvbnMgYW5kIGZvdW5kIHRoZSBmb2xsb3dpbmc6CgpUaGV5IGFyZToKCjEuIEFMQVQ6IExQQUwxM18xMjAwMTA5MDAgLS0gYWxhbmluZSBhbWlub3RyYW5zZmVyYXNlCjIuIEFTQVQ6IExQQUwxM18zNDAwMTMwMDAgLS0gYXNwYXJ0YXRlIGFtaW5vdHJhbnNmZXJhc2UKMy4gRzZQRDogTFBBTDEzXzAwMDA1NDEwMCAtLSBnbHVjYXNlLTYtcGhvc3BoYXRlIDEtZGVoeWRyb2dlbmFzZQo0LiBOSDogTFBBTDEzXzE0MDA2MTAwLCBMUEFMMTNfMTgwMDE4NTAwIC0tIGlub3NpbmUtZ3VhbmluZSBudWNsZW9zaWRlIGh5ZHJvbGFzZQo1LiBNUEk6IExQQUwxM18zMjAwMjIzMDAgKG1heWJlKSAtLSBtYW5ub3NlIHBob3NwaGF0ZSBpc29tZXJhc2UgKEkgY2hvc2UgcGhvc3Bob21hbm5vc2UgaXNvbWVyYXNlKQoKR2l2ZW4gdGhlc2UgNiBnZW5lIElEcyAoTkggaGFzIHR3byBnZW5lIElEcyBhc3NvY2lhdGVkIHdpdGggaXQpLCBJIGNhbiBkbyBzb21lCmxvb2tpbmcgZm9yIHNwZWNpZmljIGRpZmZlcmVuY2VzIGFtb25nIHRoZSB2YXJpb3VzIHNhbXBsZXMuCgojIyMgRXhwcmVzc2lvbiBsZXZlbHMgb2Ygenltb2RlbWUgZ2VuZXMKClRoZSBmb2xsb3dpbmcgY3JlYXRlcyBhIGNvbG9yc3BhY2UgKHJlZCB0byBncmVlbikgaGVhdG1hcCBzaG93aW5nIHRoZSBvYnNlcnZlZApleHByZXNzaW9uIG9mIHRoZXNlIGdlbmVzIGluIGV2ZXJ5IHNhbXBsZS4KCmBgYHtyIHp5bW9kZW1lc30KbXlfZ2VuZXMgPC0gYygiTFBBTDEzXzEyMDAxMDkwMCIsICJMUEFMMTNfMzQwMDEzMDAwIiwgIkxQQUwxM18wMDAwNTQxMDAiLAogICAgICAgICAgICAgICJMUEFMMTNfMTQwMDA2MTAwIiwgIkxQQUwxM18xODAwMTg1MDAiLCAiTFBBTDEzXzMyMDAyMjMwMCIsCiAgICAgICAgICAgICAgIm90aGVyIikKbXlfbmFtZXMgPC0gYygiQUxBVCIsICJBU0FUIiwgIkc2UEQiLCAiTkh2MSIsICJOSHYyIiwgIk1QSSIsICJvdGhlciIpCgp6eW1vX2V4cHQgPC0gZXhjbHVkZV9nZW5lc19leHB0KGFsbF9ub3JtLCBpZHM9bXlfZ2VuZXMsIG1ldGhvZD0ia2VlcCIpCnRlc3QgPC0gcGxvdF9zYW1wbGVfaGVhdG1hcCh6eW1vX2V4cHQsIHJvd19sYWJlbD1teV9uYW1lcykKYGBgCgojIyBFbXBpcmljYWxseSBvYnNlcnZlZCBaeW1vZGVtZSBnZW5lcyBmcm9tIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2lzCgpJbiBjb250cmFzdCwgdGhlIGZvbGxvd2luZyBwbG90cyB0YWtlIHRoZSBzZXQgb2YgZ2VuZXMgd2hpY2ggYXJlIHNoYXJlZCBhbW9uZwphbGwgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gbWV0aG9kcyAofGxmY3wgPj0gMS4wIGFuZCBhZGpwIDw9IDAuMDUpIGFuZCB1c2UgdGhlbQp0byBtYWtlIGNhdGVnb3JpZXMgb2YgZ2VuZXMgd2hpY2ggYXJlIGluY3JlYXNlZCBpbiAyLjMgb3IgMi4yLgoKYGBge3Igenltb2RlbWVfZ2VuZXNfZW1waXJpY2FsfQpzaGFyZWRfenltbyA8LSBpbnRlcnNlY3Rfc2lnbmlmaWNhbnQoenlfdGFibGUpCnVwX3NoYXJlZCA8LSBzaGFyZWRfenltb1tbInVwcyJdXVtbMV1dW1siZGF0YSJdXVtbImFsbCJdXQpyb3duYW1lcyh1cF9zaGFyZWQpCnVwc2hhcmVkX2V4cHQgPC0gZXhjbHVkZV9nZW5lc19leHB0KGFsbF9ub3JtLCBpZHM9cm93bmFtZXModXBfc2hhcmVkKSwgbWV0aG9kPSJrZWVwIikKYGBgCgojIyMgSGVhdG1hcCBvZiB6eW1vZGVtZSBnZW5lIGV4cHJlc3Npb24gaW5jcmVhc2VkIGluIDIuMyB2cy4gMi4yCgpgYGB7ciB6eW1vZW1wdXB9CnRlc3QgPC0gcGxvdF9zYW1wbGVfaGVhdG1hcCh1cHNoYXJlZF9leHB0LCByb3dfbGFiZWw9cm93bmFtZXModXBfc2hhcmVkKSkKYGBgCgojIyMgSGVhdG1hcCBvZiB6eW1vZGVtZSBnZW5lIGV4cHJlc3Npb24gaW5jcmVhc2VkIGluIDIuMiB2cy4gMi4zCgpgYGB7ciB6eW1vZW1kb3dufQpkb3duX3NoYXJlZCA8LSBzaGFyZWRfenltb1tbImRvd25zIl1dW1sxXV1bWyJkYXRhIl1dW1siYWxsIl1dCmRvd25zaGFyZWRfZXhwdCA8LSBleGNsdWRlX2dlbmVzX2V4cHQoYWxsX25vcm0sIGlkcz1yb3duYW1lcyhkb3duX3NoYXJlZCksIG1ldGhvZD0ia2VlcCIpCnRlc3QgPC0gcGxvdF9zYW1wbGVfaGVhdG1hcChkb3duc2hhcmVkX2V4cHQsIHJvd19sYWJlbD1yb3duYW1lcyhkb3duX3NoYXJlZCkpCmBgYAoKIyBTTlAgcHJvZmlsZXMKCkluIHRoaXMgYmxvY2ssIEkgYW0gY29tYmluaW5nIG91ciBwcmV2aW91cyBzYW1wbGVzIGFuZCBvdXIgbmV3IHNhbXBsZXMgaW4gdGhlCmhvcGVzIG9mIGZpbmRpbmcgdmFyaWFudCBwb3NpdGlvbnMgd2hpY2ggaGVscCBlbHVjaWRhdGUgYXNwZWN0cyBvZiBlaXRoZXIgdGhlCm5ldyBvciBvbGQgc2FtcGxlcy4gIEluIG90aGVyIHdvcmRzLCB3ZSBkbyBub3Qga25vdyB0aGUgenltb2RlbWUgYW5ub3RhdGlvbnMgZm9yCnRoZSBvbGQgc2FtcGxlcyBub3IgdGhlIHN0cmFpbiBpZGVudGl0aWVzIChvciB0aGUgc2hvcnRjdXQgJ2Nocm9uaWMKdnMuIHNlbGYtaGVhbGluZycpIGZvciB0aGUgbmV3IHNhbXBsZXMuICBXZSBtYXkgYmUgYWJsZSB0byBtYWtlIGVkdWNhdGVkIGd1ZXNzZXMKZ2l2ZW4gdGhlIHZhcmlhbnQgcHJvZmlsZXMuICBUaGVyZSBhcmUgc29tZSBkaWZmZXJlbmNlcyBpbiBob3cgdGhlIHByZXZpb3VzIGFuZApjdXJyZW50IGRhdGEgc2V0cyB3ZXJlIGFuYWx5emVkICh0aG91Z2ggSSBoYXZlIHNpbmNlIHJlZG9uZSB0aGUgb2xkIHNhbXBsZXMgc28KaXQgc2hvdWxkIGJlIHRyaXZpYWwgdG8gcmVtb3ZlIHRob3NlIGRpZmZlcmVuY2VzIG5vdykuCgpgYGB7ciBvbGRuZXdfdmFyaWFudHN9Cm9sZF9leHB0IDwtIHNtKGNyZWF0ZV9leHB0KCJzYW1wbGVfc2hlZXRzL3RtcmMyX3NhbXBsZXNfMjAxOTEyMDMueGxzeCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGVfY29sdW1uPSJ0b3BoYXQyZmlsZSIpKQoKdHQgPC0gbHBfZXhwdCRleHByZXNzaW9uc2V0CnJvd25hbWVzKHR0KSA8LSBnc3ViKHBhdHRlcm49Il5leG9uXyIsIHJlcGxhY2VtZW50PSIiLCB4PXJvd25hbWVzKHR0KSkKcm93bmFtZXModHQpIDwtIGdzdWIocGF0dGVybj0iXFwuRTEkIiwgcmVwbGFjZW1lbnQ9IiIsIHg9cm93bmFtZXModHQpKQpscF9leHB0JGV4cHJlc3Npb25zZXQgPC0gdHQKCnR0IDwtIG9sZF9leHB0JGV4cHJlc3Npb25zZXQKcm93bmFtZXModHQpIDwtIGdzdWIocGF0dGVybj0iXmV4b25fIiwgcmVwbGFjZW1lbnQ9IiIsIHg9cm93bmFtZXModHQpKQpyb3duYW1lcyh0dCkgPC0gZ3N1YihwYXR0ZXJuPSJcXC4xJCIsIHJlcGxhY2VtZW50PSIiLCB4PXJvd25hbWVzKHR0KSkKb2xkX2V4cHQkZXhwcmVzc2lvbnNldCA8LSB0dAoKbmV3X3NucHMgPC0gc20oY291bnRfZXhwdF9zbnBzKGxwX2V4cHQsIGFubm90X2NvbHVtbj0iYmNmdGFibGUiKSkKb2xkX3NucHMgPC0gc20oY291bnRfZXhwdF9zbnBzKG9sZF9leHB0LCBhbm5vdF9jb2x1bW49ImJjZnRhYmxlIiwgc25wX2NvbHVtbj0yKSkKCmJvdGhfc25wcyA8LSBjb21iaW5lX2V4cHRzKG5ld19zbnBzLCBvbGRfc25wcykKYm90aF9ub3JtIDwtIHNtKG5vcm1hbGl6ZV9leHB0KGJvdGhfc25wcywgdHJhbnNmb3JtPSJsb2cyIiwgY29udmVydD0iY3BtIiwgZmlsdGVyPVRSVUUpKQoKIyMgc3RyYWlucyA8LSBib3RoX25vcm1bWyJkZXNpZ24iXV1bWyJzdHJhaW4iXV0KYm90aF9ub3JtIDwtIHNldF9leHB0X2NvbmRpdGlvbnMoYm90aF9ub3JtLCBmYWN0PSJzdHJhaW4iKQpgYGAKCiMjIFBsb3Qgb2YgU05QIHByb2ZpbGVzIGZvciB6eW1vZGVtZXMKClRoZSBmb2xsb3dpbmcgcGxvdCBzaG93cyB0aGUgU05QIHByb2ZpbGVzIG9mIGFsbCBzYW1wbGVzIChvbGQgYW5kIG5ldykgd2hlcmUgdGhlCmNvbG9ycyBhdCB0aGUgdG9wIHNob3cgZWl0aGVyIHRoZSAyLjIgc3RyYWlucyAob3JhbmdlKSwgMi4zIHN0cmFpbnMgKGdyZWVuKSwgdGhlCnByZXZpb3VzIHNhbXBsZXMgKHB1cnBsZSksIG9yIHRoZSB2YXJpb3VzIGxhYiBzdHJhaW5zIChwaW5rIGV0YykuCgpgYGB7ciBwbG90dGluZ192YXJpYW50c30KdHQgPC0gcGxvdF9kaXNoZWF0KGJvdGhfbm9ybSkKCnNucF9zZXRzIDwtIGdldF9zbnBfc2V0cyhib3RoX3NucHMsIGZhY3Rvcj0iY29uZGl0aW9uIikKYm90aF9leHB0IDwtIGNvbWJpbmVfZXhwdHMobHBfZXhwdCwgb2xkX2V4cHQpCnNucF9nZW5lcyA8LSBzbShzbnBzX3ZzX2dlbmVzKGJvdGhfZXhwdCwgc25wX3NldHMsIGV4cHRfbmFtZV9jb2w9ImNocm9tb3NvbWUiKSkKCnNucF9zdWJzZXQgPC0gc20oc25wX3N1YnNldF9nZW5lcygKICBib3RoX2V4cHQsIGJvdGhfc25wcywKICBnZW5lcz1jKCJMUEFMMTNfMTIwMDEwOTAwIiwgIkxQQUwxM18zNDAwMTMwMDAiLCAiTFBBTDEzXzAwMDA1NDEwMCIsCiAgICAgICAgICAiTFBBTDEzXzE0MDAwNjEwMCIsICJMUEFMMTNfMTgwMDE4NTAwIiwgIkxQQUwxM18zMjAwMjIzMDAiKSkpCiMjIHp5bW9faGVhdCA8LSBwbG90X3NhbXBsZV9oZWF0bWFwKHNucF9zdWJzZXQsIHJvd19sYWJlbD1yb3duYW1lcyhleHBycyhzbnBfc3Vic2V0KSkpCmBgYAoKIyBDbGluaWNhbCByZXNwb25zZSBmb3IgbmV3IHNhbXBsZXMKCmBgYHtyIHNucF9jbGluaWNhbH0KY2xpbmljYWxfc2V0cyA8LSBnZXRfc25wX3NldHMobmV3X3NucHMsIGZhY3Rvcj0iY2xpbmljYWxyZXNwb25zZSIpCmNsaW5pY2FsX2dlbmVzIDwtIHNtKHNucHNfdnNfZ2VuZXMobHBfZXhwdCwgY2xpbmljYWxfc2V0cywgZXhwdF9uYW1lX2NvbD0iY2hyb21vc29tZSIpKQpjbGluaWNhbF9zbnBzIDwtIHNucHNfaW50ZXJzZWN0aW9ucyhscF9leHB0LCBjbGluaWNhbF9zZXRzLCBjaHJfY29sdW1uPSJjaHJvbW9zb21lIikKaGVhZChhcy5kYXRhLmZyYW1lKGNsaW5pY2FsX3NucHMkaW50ZXJzW1siRmFpbHVyZSJdXSkpCmhlYWQoYXMuZGF0YS5mcmFtZShjbGluaWNhbF9zbnBzJGludGVyc1tbIkN1cmUiXV0pKQoKaGVhZChjbGluaWNhbF9zbnBzJGdlbmVfc3VtbWFyaWVzJEZhaWx1cmUpCmhlYWQoY2xpbmljYWxfc25wcyRnZW5lX3N1bW1hcmllcyRDdXJlKQoKYW5ub3QgPC0gZkRhdGEobHBfZXhwdCkKY2xpbmljYWxfaW50ZXJlc3QgPC0gYXMuZGF0YS5mcmFtZShjbGluaWNhbF9zbnBzW1siZ2VuZV9zdW1tYXJpZXMiXV1bWyJDdXJlIl1dKQpjbGluaWNhbF9pbnRlcmVzdCA8LSBtZXJnZShjbGluaWNhbF9pbnRlcmVzdCwgYXMuZGF0YS5mcmFtZShjbGluaWNhbF9zbnBzW1siZ2VuZV9zdW1tYXJpZXMiXV1bWyJGYWlsdXJlIl1dKSwgYnk9InJvdy5uYW1lcyIpCnJvd25hbWVzKGNsaW5pY2FsX2ludGVyZXN0KSA8LSBjbGluaWNhbF9pbnRlcmVzdFtbIlJvdy5uYW1lcyJdXQpjbGluaWNhbF9pbnRlcmVzdFtbIlJvdy5uYW1lcyJdXSA8LSBOVUxMCmNvbG5hbWVzKGNsaW5pY2FsX2ludGVyZXN0KSA8LSBjKCJjdXJlX3NucHMiLCJmYWlsX3NucHMiKQphbm5vdCA8LSBtZXJnZShhbm5vdCwgY2xpbmljYWxfaW50ZXJlc3QsIGJ5PSJyb3cubmFtZXMiKQpyb3duYW1lcyhhbm5vdCkgPC0gYW5ub3RbWyJSb3cubmFtZXMiXV0KYW5ub3RbWyJSb3cubmFtZXMiXV0gPC0gTlVMTApmRGF0YShscF9leHB0JGV4cHJlc3Npb25zZXQpIDwtIGFubm90CmBgYAoKIyBaeW1vZGVtZSBmb3IgbmV3IHNhbXBsZXMKClRoZSBoZWF0bWFwIHByb2R1Y2VkIGhlcmUgc2hvdWxkIHNob3cgdGhlIHZhcmlhbnRzIG9ubHkgZm9yIHRoZSB6eW1vZGVtZSBnZW5lcy4KCmBgYHtyIG5ld196eW1vfQpuZXdfc2V0cyA8LSBnZXRfc25wX3NldHMobmV3X3NucHMsIGZhY3Rvcj0icGhlbm90eXBpY2NoYXJhY3RlcmlzdGljcyIpCnNucF9nZW5lcyA8LSBzbShzbnBzX3ZzX2dlbmVzKGxwX2V4cHQsIG5ld19zZXRzLCBleHB0X25hbWVfY29sPSJjaHJvbW9zb21lIikpCm5ld196eW1vX25vcm0gIDwtICBub3JtYWxpemVfZXhwdChuZXdfc25wcywgZmlsdGVyPVRSVUUsIGNvbnZlcnQ9ImNwbSIsIG5vcm09InF1YW50IiwgdHJhbnNmb3JtPVRSVUUpCm5ld196eW1vX25vcm0gPC0gc2V0X2V4cHRfY29uZGl0aW9ucyhuZXdfenltb19ub3JtLCBmYWN0PSJwaGVub3R5cGljY2hhcmFjdGVyaXN0aWNzIikKenltb19oZWF0IDwtIHBsb3RfZGlzaGVhdChuZXdfenltb19ub3JtKQoKenltb19zdWJzZXQgPC0gc25wX3N1YnNldF9nZW5lcyhscF9leHB0LCBuZXdfc25wcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW5lcz1jKCJMUEFMMTNfMTIwMDEwOTAwIiwgIkxQQUwxM18zNDAwMTMwMDAiLCAiTFBBTDEzXzAwMDA1NDEwMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTFBBTDEzXzE0MDAwNjEwMCIsICJMUEFMMTNfMTgwMDE4NTAwIiwgIkxQQUwxM18zMjAwMjIzMDAiKSkKCnp5bW9fc3Vic2V0IDwtIHNldF9leHB0X2NvbmRpdGlvbnMoenltb19zdWJzZXQsIGZhY3Q9InBoZW5vdHlwaWNjaGFyYWN0ZXJpc3RpY3MiKQojIyB6eW1vX2hlYXQgPC0gcGxvdF9zYW1wbGVfaGVhdG1hcCh6eW1vX3N1YnNldCwgcm93X2xhYmVsPXJvd25hbWVzKGV4cHJzKHNucF9zdWJzZXQpKSkKCmRlcyA8LSBib3RoX25vcm0kZGVzaWduCnVuZGVmX2lkeCA8LSBpcy5uYShkZXNbWyJzdHJhaW4iXV0pCmRlc1t1bmRlZl9pZHgsICJzdHJhaW4iXSA8LSAidW5rbm93biIKCiMjaG1jb2xzIDwtIGNvbG9yUmFtcFBhbGV0dGUoYygieWVsbG93IiwiYmxhY2siLCJkYXJrYmx1ZSIpKSgyNTYpCmNvcnJlbGF0aW9ucyA8LSBocGdsX2NvcihleHBycyhib3RoX25vcm0pKQoKenltb19taXNzaW5nX2lkeCA8LSBpcy5uYShkZXNbWyJwaGVub3R5cGljY2hhcmFjdGVyaXN0aWNzIl1dKQpkZXNbenltb19taXNzaW5nX2lkeCwgInBoZW5vdHlwaWNjaGFyYWN0ZXJpc3RpY3MiXSA8LSAidW5rbm93biIKbXlkZW5kcm8gPC0gbGlzdCgKICAiY2x1c3RmdW4iID0gaGNsdXN0LAogICJsd2QiID0gMi4wKQpjb2xfZGF0YSA8LSBhcy5kYXRhLmZyYW1lKGRlc1ssIGMoInBoZW5vdHlwaWNjaGFyYWN0ZXJpc3RpY3MiLCAiY2xpbmljYWxjYXRlZ29yaWNhbCIpXSkKdW5rbm93bl9jbGluaWNhbCA8LSBpcy5uYShjb2xfZGF0YVtbImNsaW5pY2FsY2F0ZWdvcmljYWwiXV0pCnJvd19kYXRhIDwtIGFzLmRhdGEuZnJhbWUoZGVzWywgYygic3RyYWluIildKQpjb2xuYW1lcyhjb2xfZGF0YSkgPC0gYygienltb2RlbWUiLCAib3V0Y29tZSIpCmNvbF9kYXRhW3Vua25vd25fY2xpbmljYWwsICJvdXRjb21lIl0gPC0gInVuZGVmaW5lZCIKCmNvbG5hbWVzKHJvd19kYXRhKSA8LSBjKCJzdHJhaW4iKQpteWFubm90IDwtIGxpc3QoCiAgIkNvbCIgPSBsaXN0KCJkYXRhIiA9IGNvbF9kYXRhKSwKICAiUm93IiA9IGxpc3QoImRhdGEiID0gcm93X2RhdGEpKQpteWNsdXN0IDwtIGxpc3QoImN1dGgiID0gMS4wLAogICAgICAgICAgICAgICAgImNvbCIgPSBCcmV3ZXJDbHVzdGVyQ29sKQpteWxhYnMgPC0gbGlzdCgKICAiUm93IiA9IGxpc3QoIm5yb3ciID0gNCksCiAgIkNvbCIgPSBsaXN0KCJucm93IiA9IDQpKQpobWNvbHMgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCJkYXJrYmx1ZSIsICJiZWlnZSIpKSgxNzApCm1hcDEgPC0gYW5uSGVhdG1hcDIoCiAgY29ycmVsYXRpb25zLAogIGRlbmRyb2dyYW09bXlkZW5kcm8sCiAgYW5ub3RhdGlvbj1teWFubm90LAogIGNsdXN0ZXI9bXljbHVzdCwKICBsYWJlbHM9bXlsYWJzLAogIGNvbD1obWNvbHMpCnBsb3QobWFwMSkKYGBgCgojIFVzaW5nIFZhcmlhbnQgcHJvZmlsZXMgdG8gbWFrZSBndWVzc2VzIGFib3V0IHN0cmFpbnMgYW5kIGNocm9uaWMvc2VsZi1oZWFsaW5nCgpUaGUgZm9sbG93aW5nIHVzZXMgdGhlIHNhbWUgaW5mb3JtYXRpb24gdG8gbWFrZSBzb21lIGd1ZXNzZXMgYWJvdXQgdGhlIHN0cmFpbnMKdXNlZCBpbiB0aGUgbmV3IHNhbXBsZXMuCgpgYGB7ciBvbGRfYW5kX25ld19jaHJvbmljfQpkZXMgPC0gYm90aF9ub3JtJGRlc2lnbgp1bmRlZl9pZHggPC0gaXMubmEoZGVzW1sic3RyYWluIl1dKQpkZXNbdW5kZWZfaWR4LCAic3RyYWluIl0gPC0gInVua25vd24iCiMjaG1jb2xzIDwtIGNvbG9yUmFtcFBhbGV0dGUoYygieWVsbG93IiwiYmxhY2siLCJkYXJrYmx1ZSIpKSgyNTYpCmNvcnJlbGF0aW9ucyA8LSBocGdsX2NvcihleHBycyhib3RoX25vcm0pKQoKbXlkZW5kcm8gPC0gbGlzdCgKICAiY2x1c3RmdW4iID0gaGNsdXN0LAogICJsd2QiID0gMi4wKQpjb2xfZGF0YSA8LSBhcy5kYXRhLmZyYW1lKGRlc1ssIGMoImNvbmRpdGlvbiIpXSkKcm93X2RhdGEgPC0gYXMuZGF0YS5mcmFtZShkZXNbLCBjKCJzdHJhaW4iKV0pCmNvbG5hbWVzKGNvbF9kYXRhKSA8LSBjKCJjb25kaXRpb24iKQpjb2xuYW1lcyhyb3dfZGF0YSkgPC0gYygic3RyYWluIikKbXlhbm5vdCA8LSBsaXN0KAogICJDb2wiID0gbGlzdCgiZGF0YSIgPSBjb2xfZGF0YSksCiAgIlJvdyIgPSBsaXN0KCJkYXRhIiA9IHJvd19kYXRhKSkKbXljbHVzdCA8LSBsaXN0KCJjdXRoIiA9IDEuMCwKICAgICAgICAgICAgICAgICJjb2wiID0gQnJld2VyQ2x1c3RlckNvbCkKbXlsYWJzIDwtIGxpc3QoCiAgIlJvdyIgPSBsaXN0KCJucm93IiA9IDQpLAogICJDb2wiID0gbGlzdCgibnJvdyIgPSA0KSkKaG1jb2xzIDwtIGNvbG9yUmFtcFBhbGV0dGUoYygiZGFya2JsdWUiLCAiYmVpZ2UiKSkoMTcwKQptYXAxIDwtIGFubkhlYXRtYXAyKAogIGNvcnJlbGF0aW9ucywKICBkZW5kcm9ncmFtPW15ZGVuZHJvLAogIGFubm90YXRpb249bXlhbm5vdCwKICBjbHVzdGVyPW15Y2x1c3QsCiAgbGFiZWxzPW15bGFicywKICBjb2w9aG1jb2xzKQpwbG90KG1hcDEpCmBgYAoKYGBge3IgdGhlcmVzYV9pZGVhfQpwaGVubyA8LSBzdWJzZXRfZXhwdChscF9leHB0LCBzdWJzZXQ9ImNvbmRpdGlvbj09J3oyLjInfGNvbmRpdGlvbj09J3oyLjMnIikKcGhlbm9fc25wcyA8LSBzbShjb3VudF9leHB0X3NucHMocGhlbm8sIGFubm90X2NvbHVtbj0iYmNmdGFibGUiKSkKCnhyZWZfcHJvcCA8LSB0YWJsZShwaGVub19zbnBzJGNvbmRpdGlvbnMpCnBoZW5vX3NucHMkY29uZGl0aW9ucwppZHhfdGJsIDwtIGV4cHJzKHBoZW5vX3NucHMpID4gNQpuZXdfdGJsIDwtIGRhdGEuZnJhbWUocm93Lm5hbWVzPXJvd25hbWVzKGV4cHJzKHBoZW5vX3NucHMpKSkKZm9yIChuIGluIG5hbWVzKHhyZWZfcHJvcCkpIHsKICBuZXdfdGJsW1tuXV0gPC0gMAogIGlkeF9jb2xzIDwtIHdoaWNoKHBoZW5vX3NucHNbWyJjb25kaXRpb25zIl1dID09IG4pCiAgcHJvcF9jb2wgPC0gcm93U3VtcyhpZHhfdGJsWywgaWR4X2NvbHNdKSAvIHhyZWZfcHJvcFtuXQogIG5ld190Ymxbbl0gPC0gcHJvcF9jb2wKfQpuZXdfdGJsW1sicmF0aW8iXV0gPC0gKG5ld190YmxbWyJ6Mi4yIl1dIC0gbmV3X3RibFtbInoyLjMiXV0pCmtlZXBlcnMgPC0gZ3JlcGwoeD1yb3duYW1lcyhuZXdfdGJsKSwgcGF0dGVybj0iTHBhTDEzIikKbmV3X3RibCA8LSBuZXdfdGJsW2tlZXBlcnMsIF0KbmV3X3RibFtbIlNOUCJdXSA8LSByb3duYW1lcyhuZXdfdGJsKQpuZXdfdGJsW1siQ2hyb21vc29tZSJdXSA8LSBnc3ViKHg9bmV3X3RibFtbIlNOUCJdXSwgcGF0dGVybj0iY2hyXyguKilfcG9zXy4qIiwgcmVwbGFjZW1lbnQ9IlxcMSIpCm5ld190YmxbWyJQb3NpdGlvbiJdXSA8LSBnc3ViKHg9bmV3X3RibFtbIlNOUCJdXSwgcGF0dGVybj0iLipfcG9zXyhcXGQrKV8uKiIsIHJlcGxhY2VtZW50PSJcXDEiKQpuZXdfdGJsIDwtIG5ld190YmxbLCBjKCJTTlAiLCAiQ2hyb21vc29tZSIsICJQb3NpdGlvbiIsICJyYXRpbyIpXQpsaWJyYXJ5KENNcGxvdCkKQ01wbG90KG5ld190YmwpCmBgYAoKYGBge3Igc2F2ZW1lfQppZiAoIWlzVFJVRShnZXQwKCJza2lwX2xvYWQiKSkpIHsKICBwYW5kZXI6OnBhbmRlcihzZXNzaW9uSW5mbygpKQogIG1lc3NhZ2UocGFzdGUwKCJUaGlzIGlzIGhwZ2x0b29scyBjb21taXQ6ICIsIGdldF9naXRfY29tbWl0KCkpKQogIG1lc3NhZ2UocGFzdGUwKCJTYXZpbmcgdG8gIiwgc2F2ZWZpbGUpKQogIHRtcCA8LSBzbShzYXZlbWUoZmlsZW5hbWU9c2F2ZWZpbGUpKQp9CmBgYAoKYGBge3IgbG9hZG1lX2FmdGVyLCBldmFsPUZBTFNFfQp0bXAgPC0gbG9hZG1lKGZpbGVuYW1lPXNhdmVmaWxlKQpgYGAK