1 TODO

  1. Have a set where we merge 2.1/2.2, 2.3/2.4.
  2. Represent the transition from a global view of the samples without any classification, then state the subpopulations/zymodemes, then add sensitivity/resistance, then cure/fail.
  3. Perhaps make an explicit plot where all samples are one color excepting a relatively small number of previously assayed set? The samples which would be colored in this view would be from Olga’s 2014 paper I think.
  4. Make a flow diagram going from s/r -> subpopulation -> c/f/u. (sankey)
  5. Make a table similar to the TMRC3 containing the statuses of the samples.
  6. Explicitly consider metadata column ‘P’ for reference strains – make an all grey plot with a few samples colored taken from this column.

2 Changelog

2.1 20230524/20230628

  • Frozen metadata, now using sample sheet ‘ClinicalStrains_TMRC2_Frozen 21062023.xlsx’

2.2 20230410

  • Updating the version number due to some moderately intrusive changes I made in order to more carefully create plots of the differential expresison data. I don’t think anything I did should actually change any of the data, but some of the analyses are definitely affected (note that the only change in results is due to a mistake I made in defining one of the contrasts, all other changes are just plot aesthetic improvements)

2.3 20230205

  • Did the stuff on this morning’s TODO which came out of this morning’s meeting: do a PCA without the oddball strains (already done in the worksheet), highlight reference strains, and add L.major IDs and Descriptions (done by appending a collapsed version of the ortholog data to the all_lp_annot data).

  • Fixed human IDs for the macrophage data.

  • Changed input metadata sheets: primarily because I only remembered yesterday to finish the SL search for samples >TMRC20095. They are running now and will be added momentarily (I will have to redownload the sheet).

  • Setting up to make a hclust/phylogenetic tree of strains, use these are reference: 2168(2.3), 2272(2.2), for other 2.x choose arbitrarily (lower numbers are better).

  • Added another sanitize columns call for Antimony vs. antimony and None vs. none in the TMRC2 macrophage samples.

3 Introduction

This document is intended to create the data structures used to evaluate our TMRC2 samples. 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.
  5. The freebayes variant estimation tool was used in addition to #4 to search for variant positions in a more robust fashion.
  6. The trimmed reads were passed to kraken2 using a viral database in order to look for samples with potential LRV sequence.
  7. An explicit, grep-based search for spliced leader reads was used against all human-derived samples. The results from this were copy/pasted into the sample sheet.

4 Notes 20221206 meeting

I am thinking that this meeting will bring Maria Adelaida fully back into the analyses of the parasite data, and therefore may focus primarily on the goals rather than the analyses?

  • Maria Adelaida meeting with Olgla/Mariana: integrating transcriptomics/genomics question.
  • Paper on relationship btwn primary metadata factors via transcriptome/genome.
  • Second on drug susceptibility without those factors (I think this means the macrophages)
  • Definition of species? MAG: Define consensus sequences for various strains/species. We effectively have this on hand, though the quality may be a little less good for 2.3.
  • Resulting goal: Create a tree of the strains (I am just going to call zymodemes strains from now on). ** What organisms would we include in a tree to describe these relationships: guyanensis, braziliensis 2904, 2.2, 2.3, 2.1, 2.4, panamensis reference, peruviania(sp? I have not seen this genome), panama, 2903; actually this may be tricky because we have always done this with a specific reference strain (panamensis col) which is one of the strains in the comparison. hmm… ** Check the most variant strains for identity (Luc) ** Methods for creating tree, traditional phylogeny vs. variant hclust?
  • PCR queries, works well if one performs sanger sequencing.

4.1 Multiple datasets

In a couple of important ways the TMRC2 data is much more complex than the TMRC3:

  1. It comprises multiple, completely separate queries:
    1. Sequencing the parasite samples
    2. Sequencing a set of human macrophage samples which were infected with specific parasite samples.
  2. The parasite transcriptomic samples comprise multiple different types of queries:
    1. Differential expression to look at strain, susceptibility, and clinical outcomes.
    2. Individual variant searches to look for potentially useful SNPs for classification of parasite samples.
  3. The human macrophage samples may be used to query both the host and parasite transcriptomes because (at least when not drug treated) there is a tremendous population of parasite reads in them.

4.2 Sample sheet(s)

Our shared online sample sheet is nearly static at the time of this writing (202209), I expect at this point the only likely updates will be to annotate some strains as more or less susceptible to drug treatment.

sample_sheet <- "sample_sheets/ClinicalStrains_TMRC2.xlsx"
macrophage_sheet <- "sample_sheets/tmrc2_macrophage_samples.xlsx"

4.2.1 Modify the sample sheet

The following block provides an example invocation of how I automatically extract things like percent reads mapped/trimmed/etc from the logs produced by trimomatic/cutadapt/hisat/salmon/etc. The caveat is that this container only has a small portion of the material available in the main working tree, as a result the new columns added to the sample sheet are relatively sparse compared to what I get on my computer.

In addition, because these samples have gone through ~ 3 different versions of my pipeline, and the code which extracts the numbers explicitly assumes only the most recent version (because it is the best!), it does not get out the data for all the samples.

modified <- gather_preprocessing_metadata(sample_sheet, species = "lpanamensis_v36")
## Checking the state of the condition column.
## Checking the state of the batch column.
## Checking the condition factor.
## preprocessing/TMRC20001/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20002/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20065/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20004/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20005/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20066/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20039/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20037/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20038/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20067/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20068/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20041/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20015/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20009/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20010/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20016/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20011/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20012/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20013/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20017/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20014/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20018/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20019/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20070/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20020/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20021/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20022/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20024/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20036/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20069/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20033/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20026/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20031/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20076/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20073/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20055/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20079/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20071/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20078/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20094/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20042/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20058/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20072/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20059/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20048/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20057/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20088/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20056/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20060/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20077/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20074/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20063/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20053/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20052/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20064/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20075/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20051/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20050/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20049/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20062/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20110/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20080/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20043/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20083/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20054/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20085/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20046/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20093/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20089/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20047/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20090/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20044/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20045/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20105/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20108/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20109/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20098/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20096/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20101/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20092/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20082/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20102/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20099/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20100/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20091/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20084/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20087/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20103/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20104/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20086/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20107/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20081/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## preprocessing/TMRC20095/outputs/*hisat*_lpanamensis_v36/lpanamensis_v36_*genome*_gene_ID_fcounts.csv.xz
## Writing new metadata to: sample_sheets/ClinicalStrains_TMRC2_modified.xlsx

5 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.

The same database of annotations also provides mappings to the set of annotated GO categories for the L.panamensis genome along with gene lengths.

The following block assumes one has access to tritrypdb.org, which is no currently guaranteed. Thus I bundled a pre-generated copy of the genome, Txdb, and annotations.

## meta <- download_eupath_metadata(webservice = "tritrypdb", eu_version = "v46")
meta <- download_eupath_metadata(webservice = "tritrypdb")
panamensis_entry <- get_eupath_entry("MHOM", metadata = meta[["valid"]])
panamensis_db <- make_eupath_orgdb(panamensis_entry)
panamensis_pkg <- panamensis_db[["pkgname"]]
package_name <- panamensis_db[["pkgname"]]
if (is.null(panamensis_pkg)) {
  panamensis_pkg <- panamensis_db[["orgdb_name"]]
  package_name <- panamensis_pkg
}
tt <- library(panamensis_pkg, character.only = TRUE)
panamensis_pkg <- get0(panamensis_pkg)
all_fields <- columns(panamensis_pkg)
all_lp_annot <- sm(load_orgdb_annotations(
    panamensis_pkg,
    keytype = "gid",
    fields = c("annot_gene_entrez_id", "annot_gene_name",
               "annot_strand", "annot_chromosome", "annot_cds_length",
               "annot_gene_product")))$genes

lp_go <- load_orgdb_go(package_name)
lp_go <- lp_go[, c("GID", "GO")]
lp_lengths <- all_lp_annot[, c("gid", "annot_cds_length")]
colnames(lp_lengths)  <- c("ID", "length")
all_lp_annot[["annot_gene_product"]] <- tolower(all_lp_annot[["annot_gene_product"]])
orthos <- sm(extract_eupath_orthologs(db = panamensis_pkg))
data_structures <- c(data_structures, "lp_lengths", "lp_go", "all_lp_annot", "meta")
all_installed <- rownames(installed.packages())
candidates <- grepl(pattern = "^org.Lpanamensis.MHOM.*v68.eg.db", x = all_installed)
orgdb_pkg_name <- all_installed[candidates]

tt <- library(orgdb_pkg_name, character.only = TRUE)
## Loading required package: AnnotationDbi
## Loading required package: stats4
## Loading required package: BiocGenerics
## Loading required package: generics
## 
## Attaching package: 'generics'
## The following object is masked from 'package:dplyr':
## 
##     explain
## The following objects are masked from 'package:base':
## 
##     as.difftime, as.factor, as.ordered, intersect, is.element, setdiff,
##     setequal, union
## 
## Attaching package: 'BiocGenerics'
## The following objects are masked from 'package:hpgltools':
## 
##     annotation, annotation<-, conditions, conditions<-, normalize
## The following object is masked from 'package:dplyr':
## 
##     combine
## The following objects are masked from 'package:stats':
## 
##     IQR, mad, sd, var, xtabs
## The following objects are masked from 'package:base':
## 
##     Filter, Find, Map, Position, Reduce, anyDuplicated, aperm, append,
##     as.data.frame, basename, cbind, colnames, dirname, do.call,
##     duplicated, eval, evalq, get, grep, grepl, is.unsorted, lapply,
##     mapply, match, mget, order, paste, pmax, pmax.int, pmin, pmin.int,
##     rank, rbind, rownames, sapply, saveRDS, table, tapply, unique,
##     unsplit, which.max, which.min
## Loading required package: Biobase
## Welcome to Bioconductor
## 
##     Vignettes contain introductory material; view with
##     'browseVignettes()'. To cite Bioconductor, see
##     'citation("Biobase")', and for packages 'citation("pkgname")'.
## Loading required package: IRanges
## Loading required package: S4Vectors
## 
## Attaching package: 'S4Vectors'
## The following objects are masked from 'package:dplyr':
## 
##     first, rename
## The following object is masked from 'package:utils':
## 
##     findMatches
## The following objects are masked from 'package:base':
## 
##     I, expand.grid, unname
## 
## Attaching package: 'IRanges'
## The following object is masked from 'package:glue':
## 
##     trim
## The following objects are masked from 'package:dplyr':
## 
##     collapse, desc, slice
## 
## Attaching package: 'AnnotationDbi'
## The following object is masked from 'package:dplyr':
## 
##     select
## 
panamensis_pkg <- get0(orgdb_pkg_name)
all_fields <- columns(panamensis_pkg)
all_lp_annot <- sm(load_orgdb_annotations(
    panamensis_pkg,
    keytype = "gid",
    fields = c("annot_gene_entrez_id", "annot_gene_name", "annot_gene_location_text",
               "annot_strand", "annot_chromosome", "annot_cds_length",
               "annot_gene_product")))$genes

lp_go <- load_orgdb_go(panamensis_pkg)
## The chosen keytype was not available.  Using 'GID'.
## This is an orgdb, good.
## 'select()' returned 1:many mapping between keys and columns
## 'select()' returned 1:many mapping between keys and columns
lp_go <- lp_go[, c("GID", "GO")]
lp_lengths <- all_lp_annot[, c("gid", "annot_cds_length")]
colnames(lp_lengths)  <- c("ID", "length")
all_lp_annot[["annot_gene_product"]] <- tolower(all_lp_annot[["annot_gene_product"]])
data_structures <- c(data_structures, "lp_lengths", "lp_go", "all_lp_annot", "meta")

5.1 Repeat for the L.major annotations

Recently there was a request to include the Leishmania major gene IDs and descriptions. Thus I will extract them along with the orthologs and append that to the annotations used.

Having spent the time to run the following code, I realized that the orthologs data structure above actually already has the gene IDs and descriptions.

Thus I will leave my query in place to extract the major annotations, but follow it up with a collapse of the major orthologs and appending of that to the panamensis annotations.

orgdb <- "org.Lmajor.Friedlin.v49.eg.db"
tt <- sm(library(orgdb, character.only = TRUE))
major_db <- org.Lmajor.Friedlin.v49.eg.db
all_fields <- columns(pan_db)
all_lm_annot <- sm(load_orgdb_annotations(
    major_db,
    keytype = "gid",
    fields = c("annot_gene_entrez_id", "annot_gene_name",
               "annot_strand", "annot_chromosome", "annot_cds_length",
               "annot_gene_product")))$genes

wanted_orthos_idx <- orthos[["ORTHOLOGS_SPECIES"]] == "Leishmania major strain Friedlin"
sum(wanted_orthos_idx)
wanted_orthos <- orthos[wanted_orthos_idx, ]
wanted_orthos <- wanted_orthos[, c("GID", "ORTHOLOGS_ID", "ORTHOLOGS_NAME")]

collapsed_orthos <- wanted_orthos %>%
  group_by(GID) %>%
  summarise(collapsed_id = stringr::str_c(ORTHOLOGS_ID, collapse = " ; "),
            collapsed_name = stringr::str_c(ORTHOLOGS_NAME, collapse = " ; "))
all_lp_annot <- merge(all_lp_annot, collapsed_orthos, by.x = "row.names",
                      by.y = "GID", all.x = TRUE)
rownames(all_lp_annot) <- all_lp_annot[["Row.names"]]
all_lp_annot[["Row.names"]] <- NULL
data_structures <- c(data_structures, "lp_lengths", "lp_go", "all_lp_annot")

6 Load a genome

The following block loads the full genome sequence for panamensis. We may use this later to attempt to estimate PCR primers to discern strains.

I am not sure how to increase the number of open files in a container, as a result this does not work.

## testing_panamensis <- make_eupath_bsgenome(entry = panamensis_entry, eu_version = "v46")
pkg_candidates <- grepl(x = all_installed, pattern = "BSGenome\\.Leishmania\\.panamensis.*")
pkg_name <- all_installed[pkg_candidates][1]
library(as.character(pkg_name), character.only = TRUE)
## Loading required package: GenomeInfoDb
## Loading required package: BSgenome
## Loading required package: GenomicRanges
## Loading required package: Biostrings
## Loading required package: XVector
## 
## Attaching package: 'Biostrings'
## The following object is masked from 'package:base':
## 
##     strsplit
## Loading required package: BiocIO
## Loading required package: rtracklayer
lp_genome <- get0(as.character(pkg_name))
data_structures <- c(data_structures, "lp_genome")

7 Generate Expressionsets and 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(or summarizedExperiment) is a 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.

7.1 Notes

The following samples are much lower coverage:

  • TMRC20002
  • TMRC20006
  • TMRC20007
  • TMRC20008

There is a set of strains which acquired resistance in vitro. These are included in the dataset, but there are not likely enough of them to query that question explicitly.

7.2 Define colors

The following list contains the colors we have chosen to use when plotting the various ways of discerning the data.

color_choices <- list(
    "strain" = list(
        ## "z1.0" = "#333333", ## Changed this to 'braz' to make it easier to find them.
        "z2.0" = "#555555",
        "z3.0" = "#777777",
        "z2.1" = "#874400",
        "z2.2" = "#0000cc",
        "z2.3" = "#cc0000",
        "z2.4" = "#df7000",
        "z3.2" = "#888888",
        "z1.0" = "#cc00cc",
        "z1.5" = "#cc00cc",
        "b2904" = "#cc00cc",
        "unknown" = "#cbcbcb"),
    ## "null" = "#000000"),
    "zymo" = list(
      "z22" = "#0000cc",
      "z23" = "#cc0000"),
    "cf" = list(
        "cure" = "#006f00",
        "fail" = "#9dffa0",
        "unknown" = "#cbcbcb",
        "notapplicable" = "#000000"),
    "susceptibility" = list(
        "resistant" = "#8563a7",
        "sensitive" = "#8d0000",
        "ambiguous" = "#cbcbcb",
        "unknown" = "#555555"))
data_structures <- c(data_structures, "color_choices")

8 Parasite-only data structure

The data structure ‘lp_se’ contains the data for all samples which have hisat2 count tables, and which pass a few initial quality tests (e.g. they must have more than 8550 genes with >0 counts and >5e6 reads which mapped to a gene); genes which are annotated with a few key redundant categories (leishmanolysin for example) are also culled.

8.1 All (almost) samples

There are a few metadata columns which we really want to make certain are standardized.

Note: I changed this to print both the number of reads and genes for removed samples.

202510: Commenting out the semantic filter and will either not apply it or move it to somewhere after the visualization of the data.

sanitize_columns <- c("passagenumber", "clinicalresponse", "clinicalcategorical",
                      "zymodemecategorical", "included")
lp_se <- create_se(sample_sheet,
                   gene_info = all_lp_annot,
                   annotation_name = orgdb_pkg_name,
                   savefile = glue("rda/tmrc2_lp_se_all_raw-v{ver}.rda"),
                   id_column = "hpglidentifier",
                   file_column = "lpanamensisv36hisatfile") %>%
  set_conditions(fact = "zymodemecategorical", colors = color_choices[["strain"]]) %>%
##  semantic_filter(semantic = c("amastin", "gp63", "leishmanolysin"),
##                       semantic_column = "annot_gene_product") %>%
  sanitize_metadata(columns = sanitize_columns) %>%
  subset_se(subset = "included=='yes'") %>%
  set_factors(columns = sanitize_columns, class = "factor")
## Reading the sample metadata.
## Did not find the column: hpglidentifier.
## Setting the ID column to the first column.
## Checking the state of the condition column.
## Checking the state of the batch column.
## Checking the condition factor.
## The sample definitions comprises: 93 rows(samples) and 74 columns(metadata fields).
## Matched 8778 annotations and counts.
## The final summarized experiment has 8778 rows and 74 columns.
## The numbers of samples by condition are:
## 
## z2.1 z2.2 z2.3 z2.4 
##    7   43   41    2
## Warning in set_se_colors(new_se, colors = colors): Colors for the following
## categories are not being used: z2.0, z3.0, z3.2, z1.0, z1.5, b2904, unknown.
## Recasting the data.frame to DataFrame.
##    rownames           sampleid         tubelabelorigin    included
##  Length:93          Length:93          Length:93          yes:93  
##  Class :character   Class :character   Class :character           
##  Mode  :character   Mode  :character   Mode  :character           
##                                                                   
##                                                                   
##                                                                   
##                                                                   
##   sourcelab          expperson           pathogen         pathogenstrain    
##  Length:93          Length:93          Length:93          Length:93         
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##                                                                             
##      host           parasitestage         phase           passagenumber
##  Length:93          Length:93          Length:93          2:89         
##  Class :character   Class :character   Class :character   3: 3         
##  Mode  :character   Mode  :character   Mode  :character   4: 1         
##                                                                        
##                                                                        
##                                                                        
##                                                                        
##  parasitenumber     clinicalresponse clinicalcategorical zymodemeanalysis  
##  Length:93          cure   :41       cure   :41          Length:93         
##  Class :character   failure:34       fail   :34          Class :character  
##  Mode  :character   nd     :18       unknown:18          Mode  :character  
##                                                                            
##                                                                            
##                                                                            
##                                                                            
##  zymodemecategorical phenotypiccharacteristics
##  z21: 7              Min.   :2.10             
##  z22:43              1st Qu.:2.20             
##  z23:41              Median :2.20             
##  z24: 2              Mean   :2.24             
##                      3rd Qu.:2.30             
##                      Max.   :2.40             
##                                               
##  susceptibilityinfectionreduction32ugmlsbvhistoricaldata
##  Length:93                                              
##  Class :character                                       
##  Mode  :character                                       
##                                                         
##                                                         
##                                                         
##                                                         
##  susceptibilityinfectionreduction32ugmlsbvcurrentdata
##  Length:93                                           
##  Class :character                                    
##  Mode  :character                                    
##                                                      
##                                                      
##                                                      
##                                                      
##  qualitativeclassificationofdrugsusceptibility rnapreservation   
##  Length:93                                     Length:93         
##  Class :character                              Class :character  
##  Mode  :character                              Mode  :character  
##                                                                  
##                                                                  
##                                                                  
##                                                                  
##  rnaextractiondate  rnaqctesteddate      rnangul          rnaqcpassed       
##  Min.   :20181024   Min.   :20181024   Length:93          Length:93         
##  1st Qu.:20200918   1st Qu.:20200921   Class :character   Class :character  
##  Median :20210211   Median :20210217   Mode  :character   Mode  :character  
##  Mean   :20202867   Mean   :20204528                                        
##  3rd Qu.:20210913   3rd Qu.:20210914                                        
##  Max.   :20211112   Max.   :20211116                                        
##                     NA's   :1                                               
##    rnangul1           x260280            x260230           rnavolumeul  
##  Length:93          Length:93          Length:93          Min.   :24.1  
##  Class :character   Class :character   Class :character   1st Qu.:30.0  
##  Mode  :character   Mode  :character   Mode  :character   Median :30.0  
##                                                           Mean   :29.8  
##                                                           3rd Qu.:30.0  
##                                                           Max.   :30.0  
##                                                           NA's   :8     
##  rnaavailableul libraryconstdate   libraryqcdate     
##  Min.   :17.1   Min.   :20181025   Min.   :20181029  
##  1st Qu.:26.2   1st Qu.:20200922   1st Qu.:20200564  
##  Median :27.4   Median :20210303   Median :20201223  
##  Mean   :26.6   Mean   :20204976   Mean   :20203133  
##  3rd Qu.:27.7   3rd Qu.:20210923   3rd Qu.:20210317  
##  Max.   :28.5   Max.   :20211223   Max.   :20211223  
##  NA's   :8                         NA's   :22        
##  rnausedtoconstructlibrariesul rnausedtoconstructlibrariesug libqcpassed       
##  Min.   :0.410                 Length:93                     Length:93         
##  1st Qu.:0.797                 Class :character              Class :character  
##  Median :1.060                 Mode  :character              Mode  :character  
##  Mean   :1.614                                                                 
##  3rd Qu.:2.318                                                                 
##  Max.   :8.010                                                                 
##  NA's   :9                                                                     
##      index      indexsequence      libraryvolumeul
##  Min.   : 1.0   Length:93          Min.   :27.0   
##  1st Qu.: 7.0   Class :character   1st Qu.:28.0   
##  Median :12.0   Mode  :character   Median :28.0   
##  Mean   :13.3                      Mean   :27.9   
##  3rd Qu.:20.0                      3rd Qu.:28.0   
##  Max.   :27.0                      Max.   :28.0   
##                                                   
##  libraryvolumesenttonajibu00b4slabul shipmentu00a0date  descriptonandremarks
##  Min.   :15.0                        Min.   :20200217   Length:93           
##  1st Qu.:15.0                        1st Qu.:20210104   Class :character    
##  Median :15.0                        Median :20210427   Mode  :character    
##  Mean   :15.1                        Mean   :20209109                       
##  3rd Qu.:15.0                        3rd Qu.:20211012                       
##  Max.   :28.0                        Max.   :20220103                       
##                                      NA's   :8                              
##  librarybioanalyzerprofileelsayedlabfilenamewelllane libraryconcnm 
##  Length:93                                           Min.   : 1.7  
##  Class :character                                    1st Qu.:25.4  
##  Mode  :character                                    Median :36.6  
##                                                      Mean   :38.8  
##                                                      3rd Qu.:54.1  
##                                                      Max.   :82.9  
##                                                      NA's   :50    
##  samplefor100ul2or4nmsequencing waterfor100ul2nmsequencing sequencingorderno 
##  Min.   : 2.51                  Min.   :-1.76              Length:93         
##  1st Qu.: 3.56                  1st Qu.:89.33              Class :character  
##  Median : 7.34                  Median :92.55              Mode  :character  
##  Mean   : 8.93                  Mean   :84.40                                
##  3rd Qu.:10.38                  3rd Qu.:95.77                                
##  Max.   :41.67                  Max.   :97.49                                
##  NA's   :66                     NA's   :66                                   
##   seqorderdate      seqcompletedate      totalreads        trimmedreads     
##  Min.   :20191107   Length:93          Min.   :1.76e+06   Min.   :1.44e+06  
##  1st Qu.:20191107   Class :character   1st Qu.:2.63e+07   1st Qu.:2.13e+07  
##  Median :20210427   Mode  :character   Median :3.13e+07   Median :2.64e+07  
##  Mean   :20201840                      Mean   :4.25e+07   Mean   :3.59e+07  
##  3rd Qu.:20210427                      3rd Qu.:4.59e+07   3rd Qu.:3.59e+07  
##  Max.   :20210427                      Max.   :1.60e+08   Max.   :1.47e+08  
##  NA's   :84                            NA's   :22         NA's   :22        
##   percentkept    lpanamensisv36salmonfile lpanamensisv36hisatfile
##  Min.   :0.588   Length:93                Length:93              
##  1st Qu.:0.796   Class :character         Class :character       
##  Median :0.854   Mode  :character         Mode  :character       
##  Mean   :0.834                                                   
##  3rd Qu.:0.902                                                   
##  Max.   :0.932                                                   
##  NA's   :25                                                      
##  hisatsinglemappedconcordant hisatmultimappedconcordant
##  Min.   :1.85e+05            Min.   :  19166           
##  1st Qu.:1.82e+07            1st Qu.:1080740           
##  Median :2.22e+07            Median :1354729           
##  Mean   :3.02e+07            Mean   :1936290           
##  3rd Qu.:3.05e+07            3rd Qu.:2092224           
##  Max.   :1.21e+08            Max.   :7648225           
##  NA's   :22                  NA's   :22                
##  hisatconcordantmappingrate hisatdiscordantsingle hisatdiscordantmulti
##  Min.   :0.00659            Min.   :  319672      Min.   :  47820     
##  1st Qu.:0.88420            1st Qu.:  558865      1st Qu.:  67872     
##  Median :0.90733            Median :  788489      Median :  76361     
##  Mean   :0.89400            Mean   : 4281951      Mean   : 963850     
##  3rd Qu.:0.92829            3rd Qu.:  850646      3rd Qu.: 102498     
##  Max.   :0.97614            Max.   :22441366      Max.   :5406308     
##  NA's   :22                 NA's   :87            NA's   :87          
##  hisattotalrate   bcftable         freebayessummary    r1slforward   
##  Min.   :0.9    Length:93          Length:93          Min.   :  0.0  
##  1st Qu.:0.9    Class :character   Class :character   1st Qu.: 13.0  
##  Median :0.9    Mode  :character   Mode  :character   Median : 24.0  
##  Mean   :0.9                                          Mean   : 29.2  
##  3rd Qu.:0.9                                          3rd Qu.: 37.0  
##  Max.   :0.9                                          Max.   :111.0  
##  NA's   :92                                           NA's   :32     
##   r1slrevcomp     r2slforward       r2slrevcomp      zymodemereference 
##  Min.   :   38   Min.   : 101616   Min.   :    0.0   Length:93         
##  1st Qu.:  226   1st Qu.: 237498   1st Qu.:    2.0   Class :character  
##  Median :  479   Median : 328730   Median :    4.5   Mode  :character  
##  Mean   : 4168   Mean   : 453401   Mean   :  907.5                     
##  3rd Qu.: 1360   3rd Qu.: 552578   3rd Qu.:    9.0                     
##  Max.   :51878   Max.   :1450388   Max.   :47191.0                     
##  NA's   :32      NA's   :39        NA's   :39                          
##  knnv2classification  knnv2notes        hclustclade        hclustnotes       
##  Length:93           Length:93          Length:93          Length:93         
##  Class :character    Class :character   Class :character   Class :character  
##  Mode  :character    Mode  :character   Mode  :character   Mode  :character  
##                                                                              
##                                                                              
##                                                                              
##                                                                              
##  knnhclusttogethercall  condition               batch   
##  Length:93             Length:93          undefined:93  
##  Class :character      Class :character                 
##  Mode  :character      Mode  :character                 
##                                                         
##                                                         
##                                                         
## 
data_structures <- c(data_structures, "lp_se")
save(list = "lp_se", file = glue("rda/tmrc2_lp_se_all_sanitized-v{ver}.rda"))

table(colData(lp_se)[["zymodemecategorical"]])
## 
## z21 z22 z23 z24 
##   7  43  41   2
table(colData(lp_se)[["clinicalresponse"]])
## 
##    cure failure      nd 
##      41      34      18
table(colData(lp_se)[["clinicalcategorical"]])
## 
##    cure    fail unknown 
##      41      34      18
ncol(assay(lp_se))
## [1] 93

8.3 Extract samples from only the two ‘canonical’ strains

8.3.1 Quick divergence

Here is a table of my current classifier’s interpretation of the strains.

table(colData(lp_se)[["knnv2classification"]])
## 
## unknown     z21     z22     z23     z24 
##       2       5      43      41       2

8.3.2 Merge 2.1/2.2 and 2.4/2.3

merged_zymo <- lp_se
colData(merged_zymo)[["zymodeme"]] <- as.character(colData(merged_zymo)[["zymodemecategorical"]])
z21_idx <- colData(merged_zymo)[["zymodeme"]] == "z21"
colData(merged_zymo)[z21_idx, "zymodeme"] <- "z22"

z24_idx <- colData(merged_zymo)[["zymodeme"]] == "z24"
colData(merged_zymo)[z24_idx, "zymodeme"] <- "z23"

keepers <- colData(merged_zymo)[["zymodeme"]] == "z22" |
  colData(merged_zymo)[["zymodeme"]] == "z23"
merged_zymo <- merged_zymo[, keepers] %>%
  set_conditions(fact = "zymodeme", colors = color_choices[["zymo"]])
## The numbers of samples by condition are:
## 
## z22 z23 
##  50  43

9 Add library sizes before filtering

table(colData(lp_se)[["clinicalcategorical"]])
## 
##    cure    fail unknown 
##      41      34      18
unknown_ids <- colData(lp_se)[["clinicalcategorical"]] == "unknown"
rownames(colData(lp_se))[unknown_ids]
##  [1] "TMRC20005" "TMRC20066" "TMRC20037" "TMRC20038" "TMRC20077" "TMRC20074"
##  [7] "TMRC20063" "TMRC20053" "TMRC20052" "TMRC20064" "TMRC20075" "TMRC20051"
## [13] "TMRC20050" "TMRC20049" "TMRC20062" "TMRC20110" "TMRC20080" "TMRC20054"
failed_ids <- colData(lp_se)[["clinicalcategorical"]] == "fail"
rownames(colData(lp_se))[failed_ids]
##  [1] "TMRC20001" "TMRC20065" "TMRC20039" "TMRC20010" "TMRC20012" "TMRC20013"
##  [7] "TMRC20014" "TMRC20018" "TMRC20070" "TMRC20020" "TMRC20021" "TMRC20022"
## [13] "TMRC20026" "TMRC20076" "TMRC20073" "TMRC20079" "TMRC20071" "TMRC20060"
## [19] "TMRC20083" "TMRC20085" "TMRC20105" "TMRC20109" "TMRC20098" "TMRC20082"
## [25] "TMRC20102" "TMRC20099" "TMRC20100" "TMRC20084" "TMRC20087" "TMRC20103"
## [31] "TMRC20104" "TMRC20086" "TMRC20107" "TMRC20081"
pre_libsize <- plot_libsize(lp_se)
## Warning in fortify(data, ...): Arguments in `...` must be used.
## x Problematic argument:
## * colour = colors
## i Did you misspell an argument name?
pre_libsize
## Library sizes of 93 samples, 
## ranging from 564,812 to 1.37e+08.

pdf(file = "figures/library_size_pre_filter.pdf", width = 24, height = 12)
pre_libsize$plot
dev.off()
## png 
##   2
pre_nonzero <- plot_nonzero(lp_se, y_intercept = 0.99)
## Scale for colour is already present.
## Adding another scale for colour, which will replace the existing scale.
## Scale for fill is already present.
## Adding another scale for fill, which will replace the existing scale.
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## i Please use `linewidth` instead.
## i The deprecated feature was likely used in the hpgltools package.
##   Please report the issue to the authors.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
pre_nonzero
## A non-zero genes plot of 93 samples.
## These samples have an average 28.6 CPM coverage and 8691 genes observed, ranging from 8452 to
## 8749.
## Warning: ggrepel: 77 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

pdf(file = "figures/nonzero_pre_filter.pdf")
pre_nonzero$plot
## Warning: ggrepel: 82 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps
dev.off()
## png 
##   2
lp_se_pre <- lp_se
lp_se <- subset_se(lp_se, nonzero = 8550)
## The samples (and read coverage) removed when filtering 8550 non-zero genes are:
## TMRC20002 
##  11681227 
## TMRC20002 
##      8452
## Samples removed: 8452
post_nonzero <- plot_nonzero(lp_se, y_intercept = 0.99)
## Scale for colour is already present.
## Adding another scale for colour, which will replace the existing scale.
## Scale for fill is already present.
## Adding another scale for fill, which will replace the existing scale.
post_nonzero
## A non-zero genes plot of 92 samples.
## These samples have an average 28.78 CPM coverage and 8694 genes observed, ranging from 8554 to
## 8749.
## Warning: ggrepel: 76 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

9.1 Extract historical susceptibility data

Column ‘Q’ in the sample sheet, make a categorical version of it with these parameters:

  • 0 <= x <= 35 is resistant
  • 36 <= x <= 48 is ambiguous
  • 49 <= x is sensitive

Note that these cutoffs are only valid for the historical data. The newer susceptibility data uses a cutoff of 0.78 for sensitive. I will set ambiguous to 0.5 to 0.78?

max_resist_historical <- 0.35
min_sensitive_historical <- 0.49

## 202305: Removed ambiguous category for the current set.
max_resist_current <- 0.77
min_sensitive_current <- 0.77

The sanitize_percent() function seeks to make the percentage values recorded by excel more reliable. Unfortunately, sometimes excel displays the value ‘49%’ when the information recorded in the worksheet is any one of the following:

  • ’49%
  • 0.49
  • “0.49”

Thus, the following block will sanitize these percentage values into a single decimal number and make a categorical variable from it using pre-defined values for resistant/ambiguous/sensitive. This categorical variable will be stored in a new column: ‘sus_category_historical’.

st <- colData(lp_se)[["susceptibilityinfectionreduction32ugmlsbvhistoricaldata"]]
starting <- sanitize_percent(st)
st
##  [1] "0.45"    "0.14"    "0.99"    "0.97"    "0"       "0.97"    "0"      
##  [8] "0"       "0.46"    "0.45"    "0.97"    "0.56"    "0.99"    "0.46"   
## [15] "0.7"     "0.99"    "0.99"    "0.45"    "0.98"    "0.99"    "0.49"   
## [22] "No data" "No data" "0.99"    "0.66"    "0.99"    "0.99"    "1"      
## [29] "1"       "0.94"    "0.94"    "No data" "No data" "No data" "No data"
## [36] "No data" "No data" "No data" "No data" "No data" "No data" "No data"
## [43] "No data" "No data" "No data" "0.99"    "0.99"    "No data" "0.98"   
## [50] "0.97"    "0.96"    "0.96"    "0"       "0"       "0"       "0.06"   
## [57] "0.94"    "0.94"    "0.03"    "0.94"    "0"       "0.25"    "0.95"   
## [64] "0.27"    "No data" "No data" "No data" "No data" "No data" "No data"
## [71] "No data" "No data" "No data" "No data" "No data" "No data" "No data"
## [78] "No data" "No data" "No data" "No data" "No data" "No data" "No data"
## [85] "No data" "No data" "No data" "No data" "No data" "No data" "No data"
## [92] "No data"
starting
##  [1] 0.45 0.14 0.99 0.97 0.00 0.97 0.00 0.00 0.46 0.45 0.97 0.56 0.99 0.46 0.70
## [16] 0.99 0.99 0.45 0.98 0.99 0.49   NA   NA 0.99 0.66 0.99 0.99 1.00 1.00 0.94
## [31] 0.94   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA
## [46] 0.99 0.99   NA 0.98 0.97 0.96 0.96 0.00 0.00 0.00 0.06 0.94 0.94 0.03 0.94
## [61] 0.00 0.25 0.95 0.27   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA
## [76]   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA
## [91]   NA   NA
sus_categorical <- starting
na_idx <- is.na(starting)
sum(na_idx)
## [1] 45
sus_categorical[na_idx] <- "unknown"

resist_idx <- starting <= max_resist_historical
sus_categorical[resist_idx] <- "resistant"
indeterminant_idx <- starting > max_resist_historical &
  starting < min_sensitive_historical
sus_categorical[indeterminant_idx] <- "ambiguous"
susceptible_idx <- starting >= min_sensitive_historical
sus_categorical[susceptible_idx] <- "sensitive"

sus_categorical <- as.factor(sus_categorical)
colData(lp_se)[["sus_category_historical"]] <- sus_categorical
table(sus_categorical)
## sus_categorical
## ambiguous resistant sensitive   unknown 
##         5        12        30        45
two_sankey <- plot_meta_sankey(
  merged_zymo, factors = c("zymodeme", "clinicalcategorical", "susceptibility"),
  drill_down = TRUE, color_choices = color_choices)
## These columns are not in the metadata: susceptibility
## Warning: attributes are not identical across measure variables; they will be
## dropped
## Warning: The `size` argument of `element_rect()` is deprecated as of ggplot2 3.4.0.
## i Please use the `linewidth` argument instead.
## i The deprecated feature was likely used in the ggsankey package.
##   Please report the issue at <https://github.com/davidsjoberg/ggsankey/issues>.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
two_sankey
## A sankey plot describing the metadata of 93 samples,
## including 8 out of 0 nodes and traversing metadata factors:
## zymodeme, clinicalcategorical.

9.2 Extract current susceptibility data

The same process will be repeated for the current iteration of the sensitivity assay and stored in the ‘sus_category_current’ column.

starting_current <- sanitize_percent(colData(lp_se)[["susceptibilityinfectionreduction32ugmlsbvcurrentdata"]])
sus_categorical_current <- starting_current
na_idx <- is.na(starting_current)
sum(na_idx)
## [1] 0
sus_categorical_current[na_idx] <- "unknown"

## The following is only valid when we had three categories, resistant/ambiguous/sensitive
## The new cutoffs drop ambiguous.
#resist_idx <- starting_current <= max_resist_current
#sus_categorical_current[resist_idx] <- "resistant"
#indeterminant_idx <- starting_current > max_resist_current &
#  starting_current < min_sensitive_current
#sus_categorical_current[indeterminant_idx] <- "ambiguous"
#susceptible_idx <- starting_current >= min_sensitive_current
#sus_categorical_current[susceptible_idx] <- "sensitive"
#sus_categorical_current <- as.factor(sus_categorical_current)
resist_idx <- starting_current <= max_resist_current
sensitive_idx <- !resist_idx
sus_categorical_current[resist_idx] <- "resistant"
sus_categorical_current[sensitive_idx] <- "sensitive"
sus_categorical_current <- as.factor(sus_categorical_current)

colData(lp_se)[["sus_category_current"]] <- sus_categorical_current
colData(lp_se)[["susceptibility"]] <- sus_categorical_current
table(sus_categorical_current)
## sus_categorical_current
## resistant sensitive 
##        46        46
lp_sankey <- plot_meta_sankey(
  lp_se, factors = c("zymodemecategorical", "clinicalcategorical", "susceptibility"),
  drill_down = TRUE, color_choices = color_choices)
## Warning: attributes are not identical across measure variables; they will be
## dropped
lp_sankey
## A sankey plot describing the metadata of 92 samples,
## including 23 out of 0 nodes and traversing metadata factors:
## zymodemecategorical, clinicalcategorical, susceptibility.

In many queries, we will seek to compare only the two primary strains, zymodeme 2.2 and 2.3. The following block will extract only those samples.

Note: IMPORTANT Maria Adelaida prefers not to use lp_two_strains. We should not at this time use the merged 2.1/2.2 and 2.4/2.3 categories.

lp_strain <- lp_se %>%
  set_batches(fact = sus_categorical_current) %>%
  set_colors(color_choices[["strain"]])
## The number of samples by batch are:
## 
## resistant sensitive 
##        46        46
## Warning in set_se_colors(exp, ...): Colors for the following categories are not
## being used: z2.0, z3.0, z3.2, z1.0, z1.5, b2904, unknown.
table(colData(lp_strain)[["condition"]])
## 
## z2.1 z2.2 z2.3 z2.4 
##    7   42   41    2
save(list = "lp_strain", file = glue("rda/tmrc2_lp_strain-v{ver}.rda"))
data_structures <- c(data_structures, "lp_strain")

lp_two_strains <- merged_zymo
save(list = "lp_two_strains",
     file = glue("rda/tmrc2_lp_two_strains-v{ver}.rda"))
data_structures <- c(data_structures, "lp_two_strains")

9.3 Clinical outcome

Clinical outcome is by far the most problematic comparison in this data, but here is the recategorization of the data using it:

lp_cf <- set_conditions(lp_se, fact = "clinicalcategorical",
                             colors = color_choices[["cf"]]) %>%
  set_batches(fact = sus_categorical_current)
## The numbers of samples by condition are:
## 
##    cure    fail unknown 
##      40      34      18
## Warning in set_se_colors(new_se, colors = colors): Colors for the following
## categories are not being used: notapplicable.
## The number of samples by batch are:
## 
## resistant sensitive 
##        46        46
table(colData(lp_cf)[["condition"]])
## 
##    cure    fail unknown 
##      40      34      18
data_structures <- c(data_structures, "lp_cf")
save(list = "lp_cf", file = glue("rda/tmrc2_lp_cf-v{ver}.rda"))

lp_cf_known <- subset_se(lp_cf, subset = "condition!='unknown'")
data_structures <- c(data_structures, "lp_cf_known")
save(list = "lp_cf_known", file = glue("rda/tmrc2_lp_cf_known-v{ver}.rda"))
data_structures <- c(data_structures, "lp_cf_known")
save(list = "lp_cf_known", file = glue("rda/tmrc2_lp_cf_known-v{ver}.rda"))

9.4 Create a historical susceptibility dataset

Use the factorized version of susceptibility to categorize the samples by the historical data.

lp_susceptibility_historical <- set_conditions(
  lp_se, fact = "sus_category_historical", colors = color_choices[["susceptibility"]]) %>%
  set_batches(fact = "clinicalcategorical")
## The numbers of samples by condition are:
## 
## ambiguous resistant sensitive   unknown 
##         5        12        30        45
## The number of samples by batch are:
## 
##    cure    fail unknown 
##      40      34      18
save(list = "lp_susceptibility_historical",
     file = glue("rda/tmrc2_lp_susceptibility_historical-v{ver}.rda"))
data_structures <- c(data_structures, "lp_susceptibility_historical")

9.5 Create a current susceptibility dataset

Use the factorized version of susceptibility to categorize the samples by the historical data.

This will likely be our canonical susceptibility dataset, so I will remove the suffix and just call it ‘lp_susceptibility’.

lp_susceptibility <- set_conditions(
  lp_se, fact = "sus_category_current", colors = color_choices[["susceptibility"]]) %>%
  set_batches(fact = "clinicalcategorical")
## The numbers of samples by condition are:
## 
## resistant sensitive 
##        46        46
## Warning in set_se_colors(new_se, colors = colors): Colors for the following
## categories are not being used: ambiguous, unknown.
## The number of samples by batch are:
## 
##    cure    fail unknown 
##      40      34      18
save(list = "lp_susceptibility",
     file = glue("rda/tmrc2_lp_susceptibility-v{ver}.rda"))
data_structures <- c(data_structures, "lp_susceptibility")

9.6 Pull out only the samples with two zymodemes

I think this is redundant with a previous block, but I am leaving it until I am certain that it is not required in a following document.

Note: IMPORTANT This is the set Maria Adeliada prefers to use.

lp_zymo <- subset_se(lp_se, subset = "condition=='z2.2'|condition=='z2.3'")
data_structures <- c(data_structures, "lp_zymo")
save(list = "lp_zymo", file = glue("rda/tmrc2_lp_zymo-v{ver}.rda"))

10 Variant data using parasite RNASeq reads

The following section will create some initial data structures of the observed variants in the parasite samples. This will include some of our 2016 samples for some classification queries.

10.1 The 2016 variant data

I changed and improved the mapping and variant detection methods from what we used for the 2016 data. So some small changes will be required to merge them.

lp_previous <- create_se("sample_sheets/tmrc2_samples_20191203.xlsx",
                           file_column = "tophat2file",
                           savefile = glue("rda/lp_previous-v{ver}.rda"))
tt <- lp_previous$expressionset
rownames(tt) <- gsub(pattern = "^exon_", replacement = "", x = rownames(tt))
rownames(tt) <- gsub(pattern = "\\.1$", replacement = "", x = rownames(tt))
rownames(tt) <- gsub(pattern = "\\-1$", replacement = "", x = rownames(tt))
lp_previous$expressionset <- tt
rm(tt)
data_structures <- c(data_structures, "lp_previous")

10.2 Create the SNP expressionset

The count_se_snps() function uses our expressionset data and a metadata column in order to extract the mpileup or freebayes-based variant calls and create matrices of the likelihood that each position-per-sample is in fact a variant.

There is an important caveat here which changed on 202301: I was interpreting using the PAIRED tag, which is only used for, unsurprisingly, paired-end samples. A couple samples are not paired and so were failing silently. The QA tag looks like it is more appropriate and should work across both types. One way to find out, I am setting it here and will look to see if the results make more sense for my test samples (TMRC2001, TMRC2005, TMRC2007).

## The next line drops the samples which are missing the SNP pipeline.
lp_snp <- subset_se(lp_se, subset = "!is.na(colData(lp_se)[['freebayessummary']])")

lp_snp_sufficient <- subset_se(lp_snp, subset = "rownames!='TMRC20082'")
lp_snp_only22_23_ref <- subset_se(lp_snp, subset = "zymodemereference=='z2.2'|zymodemereference=='z2.3'") %>%
  subset_se(subset = "rownames!='TMRC20082'")
lp_snp_22_23_ml <- subset_se(lp_snp, subset = "knnv2classification=='z22'|knnv2classification=='z23'") %>%
  subset_se(subset = "rownames!='TMRC20082'")

new_snps_sufficient <- count_snps(lp_snp_sufficient, annot_column = "freebayessummary",
                                  snp_column = "QA", reader = "readr")
## Using the snp column: QA from the sample annotations.
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## New names:
## * `DP` -> `DP...3`
## * `RO` -> `RO...8`
## * `AO` -> `AO...9`
## * `QR` -> `QR...12`
## * `QA` -> `QA...13`
## * `DP` -> `DP...42`
## * `RO` -> `RO...43`
## * `QR` -> `QR...44`
## * `AO` -> `AO...45`
## * `QA` -> `QA...46`
new_snps_only22_23_ref_suf <- count_snps(lp_snp_only22_23_ref, annot_column = "freebayessummary",
                                         snp_column = "QA", reader = "readr")
## Using the snp column: QA from the sample annotations.
## New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:
new_snps_22_23_ml_suf <- count_snps(lp_snp_22_23_ml, annot_column = "freebayessummary",
                                    snp_column = "QA", reader = "readr")
## Using the snp column: QA from the sample annotations.
## New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:New names:
## Lets see if we get numbers which make sense.
summary(assay(new_snps_sufficient)[["TMRC20001"]])  ## My weirdo sample
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##     0.0     0.0     0.0    22.8     0.0  2217.0
summary(assay(new_snps_sufficient)[["TMRC20072"]])  ## Another sample chosen at random
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##       0       0       0     104       0  247568
summary(assay(new_snps_sufficient)[["TMRC20021"]])  ## Another sample chosen at random
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##       0       0       0    1121       0 1708458
## Now that we are reasonably confident that things make more sense, lets save and move on...
data_structures <- c(data_structures, "new_snps_sufficient", "lp_snp")

## Most of the time I just run normalize() and assume it will dispatch to normalize_se()
sufficient_norm <- normalize(new_snps_sufficient, transform = "log2")
## Error: unable to find an inherited method for function 'normalize' for signature 'object = "SummarizedExperiment"'
plot_boxplot(sufficient_norm)
## Error in h(simpleError(msg, call)): error in evaluating the argument 'data' in selecting a method for function 'plot_boxplot': object 'sufficient_norm' not found

Now let us pull in the 2016 data.

old_snps <- count_snps(lp_previous, annot_column = "bcftable", snp_column = 2)
data_structures <- c(data_structures, "old_snps")

save(list = "lp_snp", file = glue("rda/lp_snp-v{ver}.rda"))
data_structures <- c(data_structures, "lp_snp")
save(list = "new_snps", file = glue("rda/new_snps-v{ver}.rda"))
data_structures <- c(data_structures, "new_snps")
save(list = "old_snps", file = glue("rda/old_snps-v{ver}.rda"))
data_structures <- c(data_structures, "old_snps")

nonzero_snps <- assay(new_snps) != 0
colSums(nonzero_snps)

10.3 Combine the previous and current data

As far as I can tell, freebayes and mpileup are reasonably similar in their sensitivity/specificity; so combining the two datasets like this is expected to work with minimal problems. The most likely problem is that my mpileup-based pipeline is unable to handle indels.

## My old_snps is using an older annotation incorrectly, so fix it here:
#annotation(old_snps) <- annotation(new_snps)
both_snps <- combine_ses(new_snps, old_snps)
save(list = "both_snps",
     file = glue("rda/both_snps-v{ver}.rda"))
data_structures <- c(data_structures, "both_snps")

11 Subclade manual interpretation

I am taking a heatmap from our variant data and manually identifying sample groups.

  • A: TMRC20025, TMRC20027, TMRC20028
  • B: hpgl0641, hpgl0247, hpgl0631, hpgl0658, close to A
  • C: TMRC20008, TMRC20007, TMRC20001, TMRC20005, hpgl0318, TMRC20012
  • D: hpgl0643, hpgl0316, hpgl0320, hpgl0641, close to C
  • E: TMRC20032, TMRC20061
  • F: TMRC20040, TMRC20036, hpgl0245, TMRC20103, TMRC20093, TMRC20045, TMRC20041, TMRC20072, TMRC20046, TMRC20057, TMRC20097, TMRC20084, close to E
  • G: hpgl0632, hpgl0652, hpgl0248, hpgl0659
  • H: hpgl0654, hpgl0634, hpgl0243, hpgl0243, closest to G
  • I: hpgl0242, hpgl0322, hpgl0636, hpgl0663, hpgl0638, close to H
  • J: TMRC20017, TMRC20033, TMRC20053, TMRC20063, TMRC20056, TMRC20074, TMRC20055, TMRC20022, TMRC20026, TMRC20083, TMRC20077, TMRC20060
  • K: TMRC20050, TMRC20042, TMRC20078, TMRC20049, TMRC20069, TMRC20044, close to J
  • L: TMRC20076, TMRC20024, TMRC2009
  • M: TMRC20019, TMRC20020, TMRC20031, TMRC20014, TMRC20011, close to L
  • N: TMRC20096, TMRC20081, TMRC20110, TMRC20092, TMRC20088, TMRC20101, TMRC20106, TMRC20091, TMRC20109, TMRC20087, TMRC20086, closeish to M
  • O: TMRC20095, TMRC20016, TMRC20018, quite far from everyone
  • P: TMRC20082, TMRC20075, pretty separate too
  • Q: hpgl0246, hpgl0653, hpgl0633, hpgl0244, hpgl0635, hpgl0655, hpgl0639, hpgl0662
  • R: TMRC20059, TMRC20089, TMRC20021, TMRC20048, TMRC20067
  • S: TMRC20013, TMRC20010, TMRC20037, TMRC20066, TMRC20062, TMRC20038, close to R
  • T: TMRC20015, TMRC20108, TMRC20099, TMRC20102, TMRC20085, TMRC20090, TMRC20104, TMRC20098, TMRC20100, TMRC20107
  • U: TMRC20047, TMRC20068, TMRC20080, TMRC20105, TMRC20094, TMRC20065, TMRC20071, TMRC20064, TMRC20043, TMRC20070, TMRC20062, TMRC20051, TMRC20079, TMRC20073, TMRC20058, TMRC20054

12 Macrophage data

All of the above focused entire on the parasite samples, now let us pull up the macrophage infected samples. This will comprise two datasets, one of the human and one of the parasite.

12.1 Macrophage host data

The metadata for the macrophage samples contains a couple of columns for mapped human and parasite reads. We will therefore use them separately to create two expressionsets, one for each species.

hs_annot <- load_biomart_annotations(year = "2020", month = 4)
## Using mart: ENSEMBL_MART_ENSEMBL from host: apr2020.archive.ensembl.org.
## Successfully connected to the hsapiens_gene_ensembl database.
## Finished downloading ensembl gene annotations.
## Finished downloading ensembl structure annotations.
## symbol columns is null, pattern matching 'symbol' and taking the first.
## Including symbols, there are 67149 vs the 249740 gene annotations.
## Not dropping haplotype chromosome annotations, set drop_haplotypes = TRUE if this is bad.
## Saving annotations to hsapiens_biomart_annotations.rda.
## Finished save().
hs_annot <- hs_annot[["annotation"]]
hs_annot[["transcript"]] <- paste0(rownames(hs_annot), ".", hs_annot[["transcript_version"]])
rownames(hs_annot) <- make.names(hs_annot[["ensembl_gene_id"]], unique = TRUE)
rownames(hs_annot) <- paste0("gene:", rownames(hs_annot))
tx_gene_map <- hs_annot[, c("transcript", "ensembl_gene_id")]

sanitize_columns <- c("drug", "macrophagetreatment", "macrophagezymodeme")
macr_annot <- hs_annot
rownames(macr_annot) <- gsub(x = rownames(macr_annot),
                             pattern = "^gene:",
                             replacement = "")
hs_macrophage <- create_se(macrophage_sheet, gene_info = macr_annot,
                           file_column = "hg38100hisatfile") %>%
  set_conditions(fact = "macrophagetreatment") %>%
  set_batches(fact = "macrophagezymodeme") %>%
  sanitize_metadata(columns = sanitize_columns) %>%
  subset_se(nonzero = 12000)
## Reading the sample metadata.
## Did not find the column: sampleid.
## Setting the ID column to the first column.
## Did not find the condition column in the sample sheet.
## Filling it in as undefined.
## Did not find the batch column in the sample sheet.
## Filling it in as undefined.
## Checking the state of the condition column.
## Checking the state of the batch column.
## Checking the condition factor.
## The sample definitions comprises: 69 rows(samples) and 80 columns(metadata fields).
## Matched 21481 annotations and counts.
## Some annotations were lost in merging, setting them to 'undefined'.
## The final summarized experiment has 21481 rows and 80 columns.
## The numbers of samples by condition are:
## 
##      inf   inf_sb    uninf uninf_sb 
##       30       29        5        5
## The number of samples by batch are:
## 
## none z2.2 z2.3 
##   10   30   29
## Recasting the data.frame to DataFrame.
##    rownames         tubelabelorigin     samplename        numberofvials
##  Length:69          Length:69          Length:69          Min.   :1    
##  Class :character   Class :character   Class :character   1st Qu.:1    
##  Mode  :character   Mode  :character   Mode  :character   Median :1    
##                                                           Mean   :1    
##                                                           3rd Qu.:1    
##                                                           Max.   :1    
##                                                                        
##   sourcelab          expperson         cellssource        samplecollectiondate
##  Length:69          Length:69          Length:69          Min.   :20190629    
##  Class :character   Class :character   Class :character   1st Qu.:20210813    
##  Mode  :character   Mode  :character   Mode  :character   Median :20220827    
##                                                           Mean   :20212685    
##                                                           3rd Qu.:20220827    
##                                                           Max.   :20220916    
##                                                                               
##  typeofcells           donor           isolationmethod   
##  Length:69          Length:69          Length:69         
##  Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character  
##                                                          
##                                                          
##                                                          
##                                                          
##  cellspurificationmethod selectionmethod    rnapreservation   
##  Length:69               Length:69          Length:69         
##  Class :character        Class :character   Class :character  
##  Mode  :character        Mode  :character   Mode  :character  
##                                                               
##                                                               
##                                                               
##                                                               
##  rnaextractiondate   rnavolumeul rnaavailableul rnaqctesteddate   
##  Length:69          Min.   :30   Min.   : 5.2   Min.   :   42382  
##  Class :character   1st Qu.:30   1st Qu.:22.2   1st Qu.:20200114  
##  Mode  :character   Median :30   Median :23.3   Median :20205521  
##                     Mean   :30   Mean   :23.1   Mean   :19485696  
##                     3rd Qu.:30   3rd Qu.:25.6   3rd Qu.:20211111  
##                     Max.   :30   Max.   :26.2   Max.   :20211221  
##                     NA's   :41   NA's   :41     NA's   :41        
##  bioanalyzerrnangul rnaqcpassed            rin            nanodroprnangul   
##  Length:69          Length:69          Length:69          Length:69         
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##                                                                             
##    x260280            x260230          rnausedtoconstructlibrariesul
##  Length:69          Length:69          Min.   : 2.20                
##  Class :character   Class :character   1st Qu.: 2.80                
##  Mode  :character   Mode  :character   Median : 3.41                
##                                        Mean   : 4.61                
##                                        3rd Qu.: 4.83                
##                                        Max.   :23.30                
##                                        NA's   :41                   
##  rnausedtoconstructlibrariesng libraryqctesteddate libqcpassed       
##  Min.   :  0.5                 Min.   :20200115    Length:69         
##  1st Qu.:  0.5                 1st Qu.:20200115    Class :character  
##  Median :250.3                 Median :20201221    Mode  :character  
##  Mean   :275.3                 Mean   :20205505                      
##  3rd Qu.:500.0                 3rd Qu.:20211219                      
##  Max.   :800.0                 Max.   :20211223                      
##  NA's   :41                    NA's   :42                            
##      index      libraryvolumeul libraryvolumesenttonajibslabul
##  Min.   : 1.0   Min.   :28      Min.   :15                    
##  1st Qu.: 7.0   1st Qu.:28      1st Qu.:15                    
##  Median :14.5   Median :28      Median :15                    
##  Mean   :13.9   Mean   :28      Mean   :15                    
##  3rd Qu.:20.2   3rd Qu.:28      3rd Qu.:15                    
##  Max.   :27.0   Max.   :28      Max.   :15                    
##  NA's   :41     NA's   :41      NA's   :41                    
##   shipmentdate         oldnew          countersampleatcideimul       drug   
##  Min.   :20200217   Length:69          Min.   :13              antimony:34  
##  1st Qu.:20200217   Class :character   1st Qu.:13              none    :35  
##  Median :20210558   Mode  :character   Median :13                           
##  Mean   :20210188                      Mean   :13                           
##  3rd Qu.:20220103                      3rd Qu.:13                           
##  Max.   :20220103                      Max.   :13                           
##  NA's   :41                            NA's   :56                           
##  descriptonandremarks observation       
##  Length:69            Length:69         
##  Class :character     Class :character  
##  Mode  :character     Mode  :character  
##                                         
##                                         
##                                         
##                                         
##  librarybioanalyzerprofileelsayedlabfilenamewelllane libraryconcnm  
##  Length:69                                           Min.   : 22.1  
##  Class :character                                    1st Qu.: 57.8  
##  Mode  :character                                    Median : 98.7  
##                                                      Mean   : 96.2  
##                                                      3rd Qu.:112.8  
##                                                      Max.   :218.0  
##                                                      NA's   :55     
##  samplefor100ul2or4nmsequencing waterfor100ul2or4nmsequencing
##  Min.   :0.917                  Min.   :92.0                 
##  1st Qu.:1.754                  1st Qu.:96.9                 
##  Median :1.942                  Median :98.1                 
##  Mean   :2.995                  Mean   :97.0                 
##  3rd Qu.:3.082                  3rd Qu.:98.2                 
##  Max.   :8.000                  Max.   :99.1                 
##  NA's   :56                     NA's   :56                   
##  sequencingorderno   seqorderdate      seqcompletedate      totalreads      
##  Length:69          Min.   :20200901   Min.   :20200910   Min.   :12254196  
##  Class :character   1st Qu.:20200901   1st Qu.:20200910   1st Qu.:21496945  
##  Mode  :character   Median :20200901   Median :20200910   Median :23391483  
##                     Mean   :20202287   Mean   :20202296   Mean   :29119440  
##                     3rd Qu.:20200901   3rd Qu.:20200910   3rd Qu.:27612540  
##                     Max.   :20210601   Max.   :20210610   Max.   :86048061  
##                     NA's   :55         NA's   :55                           
##   trimmedreads       percentkept    hg38100salmonfile  hg38100hisatfile  
##  Min.   :10400801   Min.   :0.735   Length:69          Length:69         
##  1st Qu.:19375511   1st Qu.:0.887   Class :character   Class :character  
##  Median :21401552   Median :0.902   Mode  :character   Mode  :character  
##  Mean   :26367248   Mean   :0.903                                        
##  3rd Qu.:25048428   3rd Qu.:0.940                                        
##  Max.   :79775170   Max.   :0.945                                        
##                                                                          
##  hisatsinglemappedhg38 hisatmultimappedhg38 hisatmappingratehg38
##  Min.   :  501881      Min.   : 328180      Min.   :0.0418      
##  1st Qu.:17620997      1st Qu.: 605198      1st Qu.:0.9114      
##  Median :18986346      Median : 682134      Median :0.9606      
##  Mean   :23074608      Mean   :1339401      Mean   :0.9223      
##  3rd Qu.:22472518      3rd Qu.: 830271      3rd Qu.:0.9787      
##  Max.   :70100660      Max.   :7030835      Max.   :0.9885      
##                                                                 
##  lpanamensisv36hisatfile hisatlpsinglemapped hisatlpmultimapped
##  Length:69               Min.   :    199     Min.   :    14    
##  Class :character        1st Qu.:  11504     1st Qu.:   770    
##  Mode  :character        Median : 284271     Median : 17386    
##                          Mean   : 909574     Mean   : 70729    
##                          3rd Qu.:1006681     3rd Qu.: 81008    
##                          Max.   :7086371     Max.   :620799    
##                                                                
##  parasitemappingrate parasitehostratio      x68            macrophagetreatment
##  Min.   :0.000011    Min.   :0.000204   Length:69          inf     :30        
##  1st Qu.:0.000487    1st Qu.:0.003393   Class :character   inf_sb  :29        
##  Median :0.010078    Median :0.003393   Mode  :character   uninf   : 5        
##  Mean   :0.036938    Mean   :0.010336                      uninf_sb: 5        
##  3rd Qu.:0.048453    3rd Qu.:0.003393                                         
##  Max.   :0.292395    Max.   :0.155351                                         
##                                                                               
##  macrophagezymodeme   strainid            slr1fwd          slr1rc   
##  none:10            Length:69          Min.   : 0.00   Min.   :  0  
##  z22 :30            Class :character   1st Qu.: 0.00   1st Qu.:  0  
##  z23 :29            Mode  :character   Median : 0.00   Median :  6  
##                                        Mean   : 1.16   Mean   : 31  
##                                        3rd Qu.: 1.00   3rd Qu.: 27  
##                                        Max.   :11.00   Max.   :641  
##                                                                     
##     slr2fwd           slr2rc           slsum          slvsreads       
##  Min.   :     2   Min.   : 0.000   Min.   :     2   Min.   :1.03e-07  
##  1st Qu.:   224   1st Qu.: 0.000   1st Qu.:   225   1st Qu.:7.81e-06  
##  Median :  4249   Median : 0.000   Median :  4300   Median :1.83e-04  
##  Mean   : 17256   Mean   : 0.667   Mean   : 17289   Mean   :6.68e-04  
##  3rd Qu.: 22089   3rd Qu.: 0.000   3rd Qu.: 22188   3rd Qu.:8.17e-04  
##  Max.   :168826   Max.   :13.000   Max.   :169487   Max.   :6.57e-03  
##                                                                       
##    slvshuman        trimomatic_input   trimomatic_output  trimomatic_percent
##  Min.   :1.05e-07   Length:69          Length:69          Length:69         
##  1st Qu.:1.06e-05   Class :character   Class :character   Class :character  
##  Median :1.87e-04   Mode  :character   Mode  :character   Mode  :character  
##  Mean   :8.21e-04                                                           
##  3rd Qu.:8.79e-04                                                           
##  Max.   :1.02e-02                                                           
##                                                                             
##  fastqc_pct_gc      hisat_genome_single_concordant
##  Length:69          Length:69                     
##  Class :character   Class :character              
##  Mode  :character   Mode  :character              
##                                                   
##                                                   
##                                                   
##                                                   
##  hisat_genome_multi_concordant hisat_genome_single_all hisat_genome_multi_all
##  Length:69                     Length:69               Length:69             
##  Class :character              Class :character        Class :character      
##  Mode  :character              Mode  :character        Mode  :character      
##                                                                              
##                                                                              
##                                                                              
##                                                                              
##  hisat_genome_percent hisat_count_table   condition            batch          
##  Length:69            Length:69          Length:69          Length:69         
##  Class :character     Class :character   Class :character   Class :character  
##  Mode  :character     Mode  :character   Mode  :character   Mode  :character  
##                                                                               
##                                                                               
##                                                                               
## 
## The samples (and read coverage) removed when filtering 12000 non-zero genes are:
## TMRC30162 
##    521145 
## TMRC30162 
##     10208
## Samples removed: 10208
fixed_genenames <- gsub(x = rownames(assay(hs_macrophage)), pattern = "^gene:",
                        replacement = "")
hs_macrophage <- set_genenames(hs_macrophage, ids = fixed_genenames)
table(colData(hs_macrophage)$condition)
## 
##      inf   inf_sb    uninf uninf_sb 
##       29       29        5        5
## The following 3 lines were copy/pasted to datastructures and should be removed soon.
nostrain <- is.na(colData(hs_macrophage)[["strainid"]])
colData(hs_macrophage)[nostrain, "strainid"] <- "none"

colData(hs_macrophage)[["strain_zymo"]] <- paste0("s", colData(hs_macrophage)[["strainid"]],
                                                "_", colData(hs_macrophage)[["macrophagezymodeme"]])
uninfected <- colData(hs_macrophage)[["strain_zymo"]] == "snone_none"
colData(hs_macrophage)[uninfected, "strain_zymo"] <- "uninfected"

data_structures <- c(data_structures, "hs_macrophage")

Finally, split off the U937 samples.

hs_u937 <- subset_se(hs_macrophage, subset = "typeofcells!='Macrophages'")
data_structures <- c(data_structures, "hs_u937")

12.2 Macrophage parasite data

In the previous block, we used a new invocation of ensembl-derived annotation data, this time we can just use our existing parasite gene annotations.

lp_macrophage <- create_se(macrophage_sheet, file_column = "lpanamensisv36hisatfile",
                           gene_info = all_lp_annot,
                           savefile = glue("rda/lp_macrophage-v{ver}.rda"),
                           annotation = "org.Lpanamensis.MHOMCOL81L13.v46.eg.db") %>%
  set_conditions(fact = "macrophagezymodeme") %>%
  set_batches(fact = "macrophagetreatment")
## Reading the sample metadata.
## Did not find the column: sampleid.
## Setting the ID column to the first column.
## Did not find the condition column in the sample sheet.
## Filling it in as undefined.
## Did not find the batch column in the sample sheet.
## Filling it in as undefined.
## Checking the state of the condition column.
## Checking the state of the batch column.
## Checking the condition factor.
## The sample definitions comprises: 69 rows(samples) and 80 columns(metadata fields).
## Warning in create_se(macrophage_sheet, file_column = "lpanamensisv36hisatfile",
## : Some samples were removed when cross referencing the samples against the
## count data.
## Matched 8778 annotations and counts.
## The final summarized experiment has 8778 rows and 80 columns.
## The numbers of samples by condition are:
## 
## none z2.2 z2.3 
##    8   29   29
## The number of samples by batch are:
## 
##      inf   inf_sb    uninf uninf_sb 
##       29       29        4        4
unfilt_written <- write_se(
  lp_macrophage,
  excel = glue("analyses/macrophage_de/{ver}/read_counts/lp_macrophage_reads_unfiltered-v{ver}.xlsx"))
## Writing the first sheet, containing a legend and some summary data.
## Warning in .local(x, row.names, optional, ...): arguments in '...' ignored
## The following samples have less than 5705.7 genes.
##  [1] "TMRC30066" "TMRC30117" "TMRC30244" "TMRC30246" "TMRC30249" "TMRC30266"
##  [7] "TMRC30268" "TMRC30326" "TMRC30323" "TMRC30319" "TMRC30325" "TMRC30327"
## [13] "TMRC30312" "TMRC30300" "TMRC30304" "TMRC30302" "TMRC30313" "TMRC30309"
## [19] "TMRC30292" "TMRC30331" "TMRC30332" "TMRC30330"
## Scale for colour is already present.
## Adding another scale for colour, which will replace the existing scale.
## Scale for fill is already present.
## Adding another scale for fill, which will replace the existing scale.
## Warning in fortify(data, ...): Arguments in `...` must be used.
## x Problematic argument:
## * colour = colors
## i Did you misspell an argument name?
## 175550 entries are 0.  We are on a log scale, adding 1 to the data.
## Naively calculating coefficient of variation/dispersion with respect to condition.
## Finished calculating dispersion estimates.
## `geom_smooth()` using formula = 'y ~ x'This dataset does not support lmer with condition+batch
## Removing 0 low-count genes (8778 remaining).
## transform_counts: Found 175550 values equal to 0, adding 1 to the matrix.
## `geom_smooth()` using formula = 'y ~ x'The factor none has 8 rows.
## The factor z2.2 has 29 rows.
## The factor z2.3 has 29 rows.
lp_macrophage_filt <- subset_se(lp_macrophage, nonzero = 2500)
## The samples (and read coverage) removed when filtering 2500 non-zero genes are:
## TMRC30066 TMRC30117 TMRC30244 TMRC30246 TMRC30266 TMRC30268 TMRC30326 TMRC30323 
##      3080      1147      1662      2834       822      3444       375        84 
## TMRC30319 TMRC30325 TMRC30327 TMRC30312 TMRC30304 TMRC30313 TMRC30309 TMRC30330 
##       374       356       129        76       289        96       188       181 
## TMRC30066 TMRC30117 TMRC30244 TMRC30246 TMRC30266 TMRC30268 TMRC30326 TMRC30323 
##      1890       888      1135      1796       649      1915       303        74 
## TMRC30319 TMRC30325 TMRC30327 TMRC30312 TMRC30304 TMRC30313 TMRC30309 TMRC30330 
##       270       279       123        76       207        84       166       135
## Samples removed: 1890, 888, 1135, 1796, 649, 1915, 303, 74, 270, 279, 123, 76, 207, 84, 166, 135
##  semantic_filter(semantic = c("amastin", "gp63", "leishmanolysin"),
##                  semantic_column = "annot_gene_product")
data_structures <- c(data_structures, "lp_macrophage", "lp_macrophage_filt")
filt_written <- write_se(lp_macrophage_filt,
  excel = glue("analyses/macrophage_de/{ver}/read_counts/lp_macrophage_reads_filtered-v{ver}.xlsx"))
## Writing the first sheet, containing a legend and some summary data.
## Warning in .local(x, row.names, optional, ...): arguments in '...' ignored
## The following samples have less than 5705.7 genes.
## [1] "TMRC30249" "TMRC30300" "TMRC30302" "TMRC30292" "TMRC30331" "TMRC30332"
## Scale for colour is already present.
## Adding another scale for colour, which will replace the existing scale.
## Scale for fill is already present.
## Adding another scale for fill, which will replace the existing scale.
## Warning in fortify(data, ...): Arguments in `...` must be used.
## x Problematic argument:
## * colour = colors
## i Did you misspell an argument name?
## 45092 entries are 0.  We are on a log scale, adding 1 to the data.
## Naively calculating coefficient of variation/dispersion with respect to condition.
## Finished calculating dispersion estimates.
## `geom_smooth()` using formula = 'y ~ x'Removing 0 low-count genes (8778 remaining).
## transform_counts: Found 45092 values equal to 0, adding 1 to the matrix.
## `geom_smooth()` using formula = 'y ~ x'The factor z2.2 has 21 rows.
## The factor z2.3 has 29 rows.
lp_macrophage <- lp_macrophage_filt

lp_macrophage_nosb <- subset_se(lp_macrophage, subset = "batch!='inf_sb'")
lp_nosb_write <- write_se(
  lp_macrophage_nosb,
  excel = glue("analyses/macrophage_de/{ver}/read_counts/lp_macrophage_nosb_reads-v{ver}.xlsx"))
## Writing the first sheet, containing a legend and some summary data.
## Warning in .local(x, row.names, optional, ...): arguments in '...' ignored
## Scale for colour is already present.
## Adding another scale for colour, which will replace the existing scale.
## Scale for fill is already present.
## Adding another scale for fill, which will replace the existing scale.
## Warning in fortify(data, ...): Arguments in `...` must be used.
## x Problematic argument:
## * colour = colors
## i Did you misspell an argument name?
## 6545 entries are 0.  We are on a log scale, adding 1 to the data.
## Warning: `aes_string()` was deprecated in ggplot2 3.0.0.
## i Please use tidy evaluation idioms with `aes()`.
## i See also `vignette("ggplot2-in-packages")` for more information.
## i The deprecated feature was likely used in the directlabels package.
##   Please report the issue at <https://github.com/tdhock/directlabels/issues>.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## Naively calculating coefficient of variation/dispersion with respect to condition.
## Finished calculating dispersion estimates.
## `geom_smooth()` using formula = 'y ~ x'The dataset has a minimal or missing set of conditions/batches.
## Removing 120 low-count genes (8658 remaining).
## transform_counts: Found 3286 values equal to 0, adding 1 to the matrix.
## `geom_smooth()` using formula = 'y ~ x'The factor z2.2 has 14 rows.
## The factor z2.3 has 15 rows.
data_structures <- c(data_structures, "lp_macrophage_nosb")

spec <- make_rnaseq_spec()
test <- sm(gather_preprocessing_metadata(macrophage_sheet, specification = spec))

13 Plot SL Reads on a per condition basis

lp_meta <- colData(lp_macrophage)
lp_meta[["slvsreads_log"]] <- log10(lp_meta[["slvsreads"]])
inf_values <- is.infinite(lp_meta[["slvsreads_log"]])
lp_meta[inf_values, "slvsreads_log"] <- -10

color_vector <- as.character(color_choices[["strain"]])
names(color_vector) <- names(color_choices[["strain"]])
color_vector <- color_vector[c("z2.2", "z2.3", "unknown")]
names(color_vector) <- c("z2.2", "z2.3", "none")
sl_violin <- ggplot(lp_meta,
                    aes(x = .data[["condition"]], y = .data[["slvsreads_log"]],
                        fill = .data[["condition"]])) +
  geom_violin() +
  geom_point() +
  scale_fill_manual(values = color_vector)
sl_violin

ggstatsplot::ggbetweenstats(as.data.frame(lp_meta), x = "condition", y = "slvsreads_log")

14 Make a silly ploidy plot

I want to make an estimate of ploidy using transcriptomic data. This is by definition a foold’s errand, but I think it might work.

lp_rpkm <- normalize(lp_se, convert = "rpkm", filter = TRUE,
                     length_column = "annot_cds_length", na_to_zero = TRUE)
## Error: unable to find an inherited method for function 'normalize' for signature 'object = "SummarizedExperiment"'
## Exclude scaffolds
unwanted <- grepl(pattern = "SCAF", x = rowData(lp_rpkm)[["annot_gene_location_text"]])
## 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 'rowData': object 'lp_rpkm' not found
## I think my subset logic is bacwards...
lp_wanted <- lp_rpkm[!unwanted, ]
## Error: object 'lp_rpkm' not found
summary_df <- as.data.frame(assay(lp_wanted))
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'as.data.frame': error in evaluating the argument 'x' in selecting a method for function 'assay': object 'lp_wanted' not found
summary_df[["gene_mean"]] <- rowMeans(summary_df, na.rm = TRUE)
## Error: object 'summary_df' not found
summary_df[["chromosome"]] <- rowData(lp_wanted)[["annot_chromosome"]]
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'rowData': object 'lp_wanted' not found
summary_df[["chromosome"]] <- as.factor(summary_df[["chromosome"]])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'as.factor': object 'summary_df' not found
levels(summary_df[["chromosome"]]) <- c(seq_len(19), "20.1", "20.2", 21:35)
## Error: object 'summary_df' not found
summary_df <- summary_df[, c("gene_mean", "chromosome")] %>%
  group_by(chromosome) %>%
  summarize(chr_mean = mean(gene_mean, na.rm = TRUE))
## Error: object 'summary_df' not found
min_rpkm <- min(summary_df[["chr_mean"]])
## Error: object 'summary_df' not found
summary_df[["chr_mean"]] <- summary_df[["chr_mean"]] / min_rpkm
## Error: object 'summary_df' not found
ggplot(summary_df, aes(y = chromosome, x = chr_mean)) +
  geom_col()
## Error: object 'summary_df' not found
wanted <- colData(lp_wanted)[["knnv2classification"]] == "z22" | colData(lp_wanted)[["knnv2classification"]] == "z23"
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'colData': object 'lp_wanted' not found
lp_z <- lp_wanted[, wanted]
## Error: object 'lp_wanted' not found
z22_samples <- colData(lp_z)[["knnv2classification"]] == "z22"
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'colData': object 'lp_z' not found
z23_samples <- colData(lp_z)[["knnv2classification"]] == "z23"
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'colData': object 'lp_z' not found
lp_z_assay <- as.data.frame(assay(lp_z))
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'as.data.frame': error in evaluating the argument 'x' in selecting a method for function 'assay': object 'lp_z' not found
lp_z_assay[["z22_gene_mean"]] <- rowMeans(lp_z_assay[, z22_samples], na.rm = TRUE)
## Error: object 'lp_z_assay' not found
lp_z_assay[["z23_gene_mean"]] <- rowMeans(lp_z_assay[, z23_samples], na.rm = TRUE)
## Error: object 'lp_z_assay' not found
lp_z_assay[["chromosome"]] <- rowData(lp_z)[["annot_chromosome"]]
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'rowData': object 'lp_z' not found
lp_z_means <- lp_z_assay[, c("z22_gene_mean", "z23_gene_mean", "chromosome")] %>%
  group_by(chromosome) %>%
  summarize(z22_mean = mean(z22_gene_mean, na.rm = TRUE),
            z23_mean = mean(z23_gene_mean, na.rm = TRUE))
## Error: object 'lp_z_assay' not found
chr_reshaped <- reshape2::melt(lp_z_means, id.vars = "chromosome")
## Error: object 'lp_z_means' not found
chr_reshaped[["chromosome"]] <- factor(chr_reshaped[["chromosome"]],
                                       levels = c(as.character(1:19), "20.1", "20.2",
                                                  as.character(21:35)))
## Error: object 'chr_reshaped' not found
putative_aneuploid <- ggplot(chr_reshaped, aes(x = value, y = chromosome)) +
  geom_bar(aes(fill = variable), position = "dodge", stat = "identity")
## Error: object 'chr_reshaped' not found
pp(file = "images/putative_aneuploid.svg")
putative_aneuploid
## Error: object 'putative_aneuploid' not found
dev.off()
## png 
##   2
putative_aneuploid
## Error: object 'putative_aneuploid' not found

15 Save all data structures into one rda

found_idx <- data_structures %in% ls()
if (sum(!found_idx) > 0) {
  not_found <- data_structures[!found_idx]
  warning("Some datastructures were not generated: ", toString(not_found), ".")
  data_structures <- data_structures[found_idx]
}
## Warning: Some datastructures were not generated: meta.
save(list = data_structures, file = glue("rda/tmrc2_data_structures-v{ver}.rda"))
pander::pander(sessionInfo())
## Warning: Your system is mis-configured: '/etc/localtime' is not a symlink
## Warning: It is strongly recommended to set envionment variable TZ to
## 'America/New_York' (or equivalent)

R version 4.5.0 (2025-04-11)

Platform: x86_64-pc-linux-gnu

locale: C

attached base packages: stats4, stats, graphics, grDevices, utils, datasets, methods and base

other attached packages: ruv(v.0.9.7.1), BiocParallel(v.1.42.1), variancePartition(v.1.38.1), BSGenome.Leishmania.panamensis.MHOMCOL81L13.v68(v.2024.09), BSgenome(v.1.76.0), rtracklayer(v.1.68.0), BiocIO(v.1.18.0), Biostrings(v.2.76.0), XVector(v.0.48.0), GenomicRanges(v.1.60.0), GenomeInfoDb(v.1.44.2), org.Lpanamensis.MHOMCOL81L13.v68.eg.db(v.2024.09), AnnotationDbi(v.1.70.0), IRanges(v.2.42.0), S4Vectors(v.0.46.0), Biobase(v.2.68.0), BiocGenerics(v.0.54.0), generics(v.0.1.4), hpgltools(v.1.2), Heatplus(v.3.16.0), ggplot2(v.4.0.0), glue(v.1.8.0) and dplyr(v.1.1.4)

loaded via a namespace (and not attached): fs(v.1.6.6), matrixStats(v.1.5.0), bitops(v.1.0-9), httr(v.1.4.7), RColorBrewer(v.1.1-3), insight(v.1.4.2), doParallel(v.1.0.17), numDeriv(v.2016.8-1.1), tools(v.4.5.0), backports(v.1.5.0), R6(v.2.6.1), statsExpressions(v.1.7.1), lazyeval(v.0.2.2), mgcv(v.1.9-3), withr(v.3.0.2), prettyunits(v.1.2.0), gridExtra(v.2.3), cli(v.3.6.5), prismatic(v.1.1.2), labeling(v.0.4.3), sass(v.0.4.10), mvtnorm(v.1.3-3), S7(v.0.2.0), readr(v.2.1.5), genefilter(v.1.90.0), pbapply(v.1.7-4), Rsamtools(v.2.24.0), yulab.utils(v.0.2.1), DOSE(v.4.2.0), R.utils(v.2.13.0), dichromat(v.2.0-0.1), limma(v.3.64.3), RSQLite(v.2.4.3), gtools(v.3.9.5), vroom(v.1.6.5), zip(v.2.3.3), GO.db(v.3.21.0), Matrix(v.1.7-3), abind(v.1.4-8), R.methodsS3(v.1.8.2), lifecycle(v.1.0.4), yaml(v.2.3.10), edgeR(v.4.6.3), SummarizedExperiment(v.1.38.1), gplots(v.3.2.0), qvalue(v.2.40.0), SparseArray(v.1.8.1), BiocFileCache(v.2.16.1), Rtsne(v.0.17), paletteer(v.1.6.0), grid(v.4.5.0), blob(v.1.2.4), promises(v.1.3.3), crayon(v.1.5.3), lattice(v.0.22-7), cowplot(v.1.2.0), GenomicFeatures(v.1.60.0), annotate(v.1.86.1), KEGGREST(v.1.48.1), zeallot(v.0.2.0), pillar(v.1.11.0), knitr(v.1.50), varhandle(v.2.0.6), fgsea(v.1.34.2), rjson(v.0.2.23), boot(v.1.3-31), corpcor(v.1.6.10), codetools(v.0.2-20), fastmatch(v.1.1-6), data.table(v.1.17.8), vctrs(v.0.6.5), png(v.0.1-8), Rdpack(v.2.6.4), gtable(v.0.3.6), rematch2(v.2.1.2), datawizard(v.1.2.0), cachem(v.1.1.0), xfun(v.0.53), openxlsx(v.4.2.8), rbibutils(v.2.3), S4Arrays(v.1.8.1), mime(v.0.13), correlation(v.0.8.8), coda(v.0.19-4.1), reformulas(v.0.4.1), survival(v.3.8-3), iterators(v.1.0.14), statmod(v.1.5.0), directlabels(v.2025.6.24), nlme(v.3.1-168), pbkrtest(v.0.5.5), bit64(v.4.6.0-1), progress(v.1.2.3), EnvStats(v.3.1.0), filelock(v.1.0.3), bslib(v.0.9.0), KernSmooth(v.2.23-26), DBI(v.1.2.3), tidyselect(v.1.2.1), bit(v.4.6.0), compiler(v.4.5.0), curl(v.7.0.0), httr2(v.1.2.1), graph(v.1.86.0), xml2(v.1.4.0), DelayedArray(v.0.34.1), plotly(v.4.11.0), bayestestR(v.0.17.0), scales(v.1.4.0), caTools(v.1.18.3), remaCor(v.0.0.20), quadprog(v.1.5-8), rappdirs(v.0.3.3), stringr(v.1.5.1), digest(v.0.6.37), ggsankey(v.0.0.99999), minqa(v.1.2.8), rmarkdown(v.2.29), aod(v.1.3.3), RhpcBLASctl(v.0.23-42), htmltools(v.0.5.8.1), pkgconfig(v.2.0.3), lme4(v.1.1-37), MatrixGenerics(v.1.20.0), dbplyr(v.2.5.0), fastmap(v.1.2.0), rlang(v.1.1.6), htmlwidgets(v.1.6.4), UCSC.utils(v.1.4.0), shiny(v.1.11.1), farver(v.2.1.2), jquerylib(v.0.1.4), jsonlite(v.2.0.0), GOSemSim(v.2.34.0), R.oo(v.1.27.1), RCurl(v.1.98-1.17), magrittr(v.2.0.4), GenomeInfoDbData(v.1.2.14), patchwork(v.1.3.2), parameters(v.0.28.2), Rcpp(v.1.1.0), stringi(v.1.8.7), MASS(v.7.3-65), plyr(v.1.8.9), parallel(v.4.5.0), ggrepel(v.0.9.6), splines(v.4.5.0), pander(v.0.6.6), hms(v.1.1.3), locfit(v.1.5-9.12), fastcluster(v.1.3.0), effectsize(v.1.0.1), reshape2(v.1.4.4), biomaRt(v.2.64.0), rstantools(v.2.5.0), XML(v.3.99-0.19), evaluate(v.1.0.4), RcppParallel(v.5.1.11-1), nloptr(v.2.2.1), tzdb(v.0.5.0), foreach(v.1.5.2), httpuv(v.1.6.16), MatrixModels(v.0.5-4), BayesFactor(v.0.9.12-4.7), tidyr(v.1.3.1), purrr(v.1.1.0), broom(v.1.0.10), xtable(v.1.8-4), restfulr(v.0.0.16), fANCOVA(v.0.6-1), later(v.1.4.3), viridisLite(v.0.4.2), tibble(v.3.3.0), lmerTest(v.3.1-3), ggstatsplot(v.0.13.3), memoise(v.2.0.1), GenomicAlignments(v.1.44.0), sva(v.3.56.0) and GSEABase(v.1.70.0)

message("This is hpgltools commit: ", get_git_commit())
## If you wish to reproduce this exact build of hpgltools, invoke the following:
## > git clone http://github.com/abelew/hpgltools.git
## > git reset b479ad4aea5c11ece084c588c57777c08d864a5a
## This is hpgltools commit: Thu Oct 9 17:14:10 2025 -0400: b479ad4aea5c11ece084c588c57777c08d864a5a
message("Saving to ", savefile)
## Saving to 01datasets.rda.xz
# tmp <- sm(saveme(filename = savefile))
tmp <- loadme(filename = savefile)
LS0tCnRpdGxlOiAiVE1SQzIgYHIgU3lzLmdldGVudignVkVSU0lPTicpYDogRGF0YSBTZXQgQ3JlYXRpb24iCmF1dGhvcjogImF0YiBhYmVsZXdAZ21haWwuY29tIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCmJpYmxpb2dyYXBoeTogYXRiLmJpYgpvdXRwdXQ6CiBodG1sX2RvY3VtZW50OgogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgZmlnX2hlaWdodDogNwogICAgZmlnX3dpZHRoOiA3CiAgICBoaWdobGlnaHQ6IHplbmJ1cm4KICAgIGtlZXBfbWQ6IGZhbHNlCiAgICBtb2RlOiBzZWxmY29udGFpbmVkCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgICB0aGVtZTogcmVhZGFibGUKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICAgIHNtb290aF9zY3JvbGw6IGZhbHNlCi0tLQoKPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KYm9keSAubWFpbi1jb250YWluZXIgewogIG1heC13aWR0aDogMTYwMHB4Owp9CmJvZHksIHRkIHsKICBmb250LXNpemU6IDE2cHg7Cn0KY29kZS5yewogIGZvbnQtc2l6ZTogMTZweDsKfQpwcmUgewogIGZvbnQtc2l6ZTogMTZweAp9Cjwvc3R5bGU+CgpgYGB7ciBvcHRpb25zLCBpbmNsdWRlID0gRkFMU0V9CmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2x1ZSkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KEhlYXRwbHVzKQpsaWJyYXJ5KGhwZ2x0b29scykKCmtuaXRyOjpvcHRzX2tuaXQkc2V0KHByb2dyZXNzID0gVFJVRSwgdmVyYm9zZSA9IFRSVUUsIHdpZHRoID0gOTAsIGVjaG8gPSBUUlVFKQprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgZXJyb3IgPSBUUlVFLCBmaWcud2lkdGggPSA5LCBmaWcuaGVpZ2h0ID0gOSwgZmlnLnJldGluYSA9IDIsCiAgb3V0LndpZHRoID0gIjEwMCUiLCBkZXYgPSAicG5nIiwKICBkZXYuYXJncyA9IGxpc3QocG5nID0gbGlzdCh0eXBlID0gImNhaXJvLXBuZyIpKSkKb2xkX29wdGlvbnMgPC0gb3B0aW9ucyhkaWdpdHMgPSA0LCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsIGtuaXRyLmR1cGxpY2F0ZS5sYWJlbCA9ICJhbGxvdyIpCmdncGxvdDI6OnRoZW1lX3NldChnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemUgPSAxMikpCnZlciA8LSBTeXMuZ2V0ZW52KCJWRVJTSU9OIikKcHJldmlvdXNfZmlsZSA8LSAiIgpydW5kYXRlIDwtIGZvcm1hdChTeXMuRGF0ZSgpLCBmb3JtYXQgPSAiJVklbSVkIikKCnJtZF9maWxlIDwtICIwMWRhdGFzZXRzLlJtZCIKc2F2ZWZpbGUgPC0gZ3N1YihwYXR0ZXJuID0gIlxcLlJtZCIsIHJlcGxhY2UgPSAiXFwucmRhXFwueHoiLCB4ID0gcm1kX2ZpbGUpCmRhdGFfc3RydWN0dXJlcyA8LSBjKCkKYGBgCgojIFRPRE8KCjEuICBIYXZlIGEgc2V0IHdoZXJlIHdlIG1lcmdlIDIuMS8yLjIsIDIuMy8yLjQuCjIuICBSZXByZXNlbnQgdGhlIHRyYW5zaXRpb24gZnJvbSBhIGdsb2JhbCB2aWV3IG9mIHRoZSBzYW1wbGVzIHdpdGhvdXQKICAgIGFueSBjbGFzc2lmaWNhdGlvbiwgdGhlbiBzdGF0ZSB0aGUgc3VicG9wdWxhdGlvbnMvenltb2RlbWVzLCB0aGVuCiAgICBhZGQgc2Vuc2l0aXZpdHkvcmVzaXN0YW5jZSwgdGhlbiBjdXJlL2ZhaWwuCjMuICBQZXJoYXBzIG1ha2UgYW4gZXhwbGljaXQgcGxvdCB3aGVyZSBhbGwgc2FtcGxlcyBhcmUgb25lIGNvbG9yCiAgICBleGNlcHRpbmcgYSByZWxhdGl2ZWx5IHNtYWxsIG51bWJlciBvZiBwcmV2aW91c2x5IGFzc2F5ZWQgc2V0PwogICAgVGhlIHNhbXBsZXMgd2hpY2ggd291bGQgYmUgY29sb3JlZCBpbiB0aGlzIHZpZXcgd291bGQgYmUgZnJvbQogICAgT2xnYSdzIDIwMTQgcGFwZXIgSSB0aGluay4KNC4gIE1ha2UgYSBmbG93IGRpYWdyYW0gZ29pbmcgZnJvbSBzL3IgLT4gc3VicG9wdWxhdGlvbiAtPgogICAgYy9mL3UuIChzYW5rZXkpCjUuICBNYWtlIGEgdGFibGUgc2ltaWxhciB0byB0aGUgVE1SQzMgY29udGFpbmluZyB0aGUgc3RhdHVzZXMgb2YgdGhlCiAgICBzYW1wbGVzLgo2LiAgRXhwbGljaXRseSBjb25zaWRlciBtZXRhZGF0YSBjb2x1bW4gJ1AnIGZvciByZWZlcmVuY2Ugc3RyYWlucyAtLQogICAgbWFrZSBhbiBhbGwgZ3JleSBwbG90IHdpdGggYSBmZXcgc2FtcGxlcyBjb2xvcmVkIHRha2VuIGZyb20gdGhpcwogICAgY29sdW1uLgoKIyBDaGFuZ2Vsb2cKCiMjIDIwMjMwNTI0LzIwMjMwNjI4CgoqIEZyb3plbiBtZXRhZGF0YSwgbm93IHVzaW5nIHNhbXBsZSBzaGVldCAnQ2xpbmljYWxTdHJhaW5zX1RNUkMyX0Zyb3plblwgMjEwNjIwMjMueGxzeCcKCiMjIDIwMjMwNDEwCgoqIFVwZGF0aW5nIHRoZSB2ZXJzaW9uIG51bWJlciBkdWUgdG8gc29tZSBtb2RlcmF0ZWx5IGludHJ1c2l2ZSBjaGFuZ2VzCiAgSSBtYWRlIGluIG9yZGVyIHRvIG1vcmUgY2FyZWZ1bGx5IGNyZWF0ZSBwbG90cyBvZiB0aGUgZGlmZmVyZW50aWFsCiAgZXhwcmVzaXNvbiBkYXRhLiAgSSBkb24ndCB0aGluayBhbnl0aGluZyBJIGRpZCBzaG91bGQgYWN0dWFsbHkKICBjaGFuZ2UgYW55IG9mIHRoZSBkYXRhLCBidXQgc29tZSBvZiB0aGUgYW5hbHlzZXMgYXJlIGRlZmluaXRlbHkKICBhZmZlY3RlZCAobm90ZSB0aGF0IHRoZSBvbmx5IGNoYW5nZSBpbiByZXN1bHRzIGlzIGR1ZSB0byBhIG1pc3Rha2UgSQogIG1hZGUgaW4gZGVmaW5pbmcgb25lIG9mIHRoZSBjb250cmFzdHMsIGFsbCBvdGhlciBjaGFuZ2VzIGFyZSBqdXN0CiAgcGxvdCBhZXN0aGV0aWMgaW1wcm92ZW1lbnRzKQoKIyMgMjAyMzAyMDUKCiogRGlkIHRoZSBzdHVmZiBvbiB0aGlzIG1vcm5pbmcncyBUT0RPIHdoaWNoIGNhbWUgb3V0IG9mIHRoaXMKICBtb3JuaW5nJ3MgbWVldGluZzogZG8gYSBQQ0Egd2l0aG91dCB0aGUgb2RkYmFsbCBzdHJhaW5zIChhbHJlYWR5CiAgZG9uZSBpbiB0aGUgd29ya3NoZWV0KSwgaGlnaGxpZ2h0IHJlZmVyZW5jZSBzdHJhaW5zLCBhbmQgYWRkIEwubWFqb3IKICBJRHMgYW5kIERlc2NyaXB0aW9ucyAoZG9uZSBieSBhcHBlbmRpbmcgYSBjb2xsYXBzZWQgdmVyc2lvbiBvZiB0aGUKICBvcnRob2xvZyBkYXRhIHRvIHRoZSBhbGxfbHBfYW5ub3QgZGF0YSkuCgoqIEZpeGVkIGh1bWFuIElEcyBmb3IgdGhlIG1hY3JvcGhhZ2UgZGF0YS4KKiBDaGFuZ2VkIGlucHV0IG1ldGFkYXRhIHNoZWV0czogcHJpbWFyaWx5IGJlY2F1c2UgSSBvbmx5IHJlbWVtYmVyZWQKICB5ZXN0ZXJkYXkgdG8gZmluaXNoIHRoZSBTTCBzZWFyY2ggZm9yIHNhbXBsZXMgPlRNUkMyMDA5NS4gIFRoZXkgYXJlCiAgcnVubmluZyBub3cgYW5kIHdpbGwgYmUgYWRkZWQgbW9tZW50YXJpbHkgKEkgd2lsbCBoYXZlIHRvIHJlZG93bmxvYWQKICB0aGUgc2hlZXQpLgoqIFNldHRpbmcgdXAgdG8gbWFrZSBhIGhjbHVzdC9waHlsb2dlbmV0aWMgdHJlZSBvZiBzdHJhaW5zLCB1c2UgdGhlc2UKICBhcmUgcmVmZXJlbmNlOiAyMTY4KDIuMyksIDIyNzIoMi4yKSwgZm9yIG90aGVyIDIueCBjaG9vc2UKICBhcmJpdHJhcmlseSAobG93ZXIgbnVtYmVycyBhcmUgYmV0dGVyKS4KKiBBZGRlZCBhbm90aGVyIHNhbml0aXplIGNvbHVtbnMgY2FsbCBmb3IgQW50aW1vbnkgdnMuIGFudGltb255IGFuZCBOb25lIHZzLgogIG5vbmUgaW4gdGhlIFRNUkMyIG1hY3JvcGhhZ2Ugc2FtcGxlcy4KCiMgSW50cm9kdWN0aW9uCgpUaGlzIGRvY3VtZW50IGlzIGludGVuZGVkIHRvIGNyZWF0ZSB0aGUgZGF0YSBzdHJ1Y3R1cmVzIHVzZWQgdG8KZXZhbHVhdGUgb3VyIFRNUkMyIHNhbXBsZXMuICBJbiBzb21lIGNhc2VzLCB0aGlzIGluY2x1ZGVzIG9ubHkgdGhvc2UKc2FtcGxlcyBzdGFydGluZyBpbiAyMDE5OyBpbiBvdGhlciBpbnN0YW5jZXMgSSBhbSBpbmNsdWRpbmcgb3VyCnByZXZpb3VzICgyMDE1LTIwMTYpIHNhbXBsZXMuCgpJbiBhbGwgY2FzZXMgdGhlIHByb2Nlc3NpbmcgcGVyZm9ybWVkIHdhczoKCjEuICBEZWZhdWx0IHRyaW1taW5nIHdhcyBwZXJmb3JtZWQuCjIuICBIaXNhdDIgd2FzIHVzZWQgdG8gbWFwIHRoZSByZW1haW5pbmcgcmVhZHMgYWdhaW5zdCB0aGUgTGVpc2htYW5pYQogICAgcGFuYW1lbnNpcyBnZW5vbWUgcmV2aXNpb24gMzYuCjMuICBUaGUgYWxpZ25tZW50cyBmcm9tIGhpc2F0MiB3ZXJlIHVzZWQgdG8gY291bnQgcmVhZHMvZ2VuZSBhZ2FpbnN0IHRoZQogICAgcmV2aXNpb24gMzYgYW5ub3RhdGlvbnMgd2l0aCBodHNlcS4KNC4gIFRoZXNlIGFsaWdubWVudHMgd2VyZSBhbHNvIHBhc3NlZCB0byB0aGUgcGlsZXVwIGZ1bmN0aW9uYWxpdHkgb2Ygc2FtdG9vbHMKICAgIGFuZCB0aGUgdmNmL2JjZiB1dGlsaXRpZXMgaW4gb3JkZXIgdG8gbWFrZSBhIG1hdHJpeCBvZiBhbGwgb2JzZXJ2ZWQKICAgIGRpZmZlcmVuY2VzIGJldHdlZW4gZWFjaCBzYW1wbGUgd2l0aCByZXNwZWN0IHRvIHRoZSByZWZlcmVuY2UuCjUuICBUaGUgZnJlZWJheWVzIHZhcmlhbnQgZXN0aW1hdGlvbiB0b29sIHdhcyB1c2VkIGluIGFkZGl0aW9uIHRvICM0CiAgICB0byBzZWFyY2ggZm9yIHZhcmlhbnQgcG9zaXRpb25zIGluIGEgbW9yZSByb2J1c3QgZmFzaGlvbi4KNi4gIFRoZSB0cmltbWVkIHJlYWRzIHdlcmUgcGFzc2VkIHRvIGtyYWtlbjIgdXNpbmcgYSB2aXJhbCBkYXRhYmFzZSBpbgogICAgb3JkZXIgdG8gbG9vayBmb3Igc2FtcGxlcyB3aXRoIHBvdGVudGlhbCBMUlYgc2VxdWVuY2UuCjcuICBBbiBleHBsaWNpdCwgZ3JlcC1iYXNlZCBzZWFyY2ggZm9yIHNwbGljZWQgbGVhZGVyIHJlYWRzIHdhcyB1c2VkCiAgICBhZ2FpbnN0IGFsbCBodW1hbi1kZXJpdmVkIHNhbXBsZXMuICBUaGUgcmVzdWx0cyBmcm9tIHRoaXMgd2VyZQogICAgY29weS9wYXN0ZWQgaW50byB0aGUgc2FtcGxlIHNoZWV0LgoKIyBOb3RlcyAyMDIyMTIwNiBtZWV0aW5nCgpJIGFtIHRoaW5raW5nIHRoYXQgdGhpcyBtZWV0aW5nIHdpbGwgYnJpbmcgTWFyaWEgQWRlbGFpZGEgZnVsbHkgYmFjawppbnRvIHRoZSBhbmFseXNlcyBvZiB0aGUgcGFyYXNpdGUgZGF0YSwgYW5kIHRoZXJlZm9yZSBtYXkgZm9jdXMKcHJpbWFyaWx5IG9uIHRoZSBnb2FscyByYXRoZXIgdGhhbiB0aGUgYW5hbHlzZXM/CgoqIE1hcmlhIEFkZWxhaWRhIG1lZXRpbmcgd2l0aCBPbGdsYS9NYXJpYW5hOiBpbnRlZ3JhdGluZwogIHRyYW5zY3JpcHRvbWljcy9nZW5vbWljcyBxdWVzdGlvbi4KKiBQYXBlciBvbiByZWxhdGlvbnNoaXAgYnR3biBwcmltYXJ5IG1ldGFkYXRhIGZhY3RvcnMgdmlhIHRyYW5zY3JpcHRvbWUvZ2Vub21lLgoqIFNlY29uZCBvbiBkcnVnIHN1c2NlcHRpYmlsaXR5IHdpdGhvdXQgdGhvc2UgZmFjdG9ycyAoSSB0aGluayB0aGlzCiAgbWVhbnMgdGhlIG1hY3JvcGhhZ2VzKQoqIERlZmluaXRpb24gb2Ygc3BlY2llcz8gIE1BRzogRGVmaW5lIGNvbnNlbnN1cyBzZXF1ZW5jZXMgZm9yIHZhcmlvdXMKICBzdHJhaW5zL3NwZWNpZXMuICBXZSBlZmZlY3RpdmVseSBoYXZlIHRoaXMgb24gaGFuZCwgdGhvdWdoIHRoZQogIHF1YWxpdHkgbWF5IGJlIGEgbGl0dGxlIGxlc3MgZ29vZCBmb3IgMi4zLgoqIFJlc3VsdGluZyBnb2FsOiBDcmVhdGUgYSB0cmVlIG9mIHRoZSBzdHJhaW5zIChJIGFtIGp1c3QgZ29pbmcgdG8KICBjYWxsIHp5bW9kZW1lcyBzdHJhaW5zIGZyb20gbm93IG9uKS4KKiogIFdoYXQgb3JnYW5pc21zIHdvdWxkIHdlIGluY2x1ZGUgaW4gYSB0cmVlIHRvIGRlc2NyaWJlIHRoZXNlCiAgICByZWxhdGlvbnNoaXBzOiBndXlhbmVuc2lzLCBicmF6aWxpZW5zaXMgMjkwNCwgMi4yLCAyLjMsIDIuMSwgMi40LAogICAgcGFuYW1lbnNpcyByZWZlcmVuY2UsIHBlcnV2aWFuaWEoc3A/IEkgaGF2ZSBub3Qgc2VlbiB0aGlzIGdlbm9tZSksCiAgICBwYW5hbWEsIDI5MDM7IGFjdHVhbGx5IHRoaXMgbWF5IGJlIHRyaWNreSBiZWNhdXNlIHdlIGhhdmUgYWx3YXlzCiAgICBkb25lIHRoaXMgd2l0aCBhIHNwZWNpZmljIHJlZmVyZW5jZSBzdHJhaW4gKHBhbmFtZW5zaXMgY29sKSB3aGljaCBpcwogICAgb25lIG9mIHRoZSBzdHJhaW5zIGluIHRoZSBjb21wYXJpc29uLiAgaG1tLi4uCioqICBDaGVjayB0aGUgbW9zdCB2YXJpYW50IHN0cmFpbnMgZm9yIGlkZW50aXR5IChMdWMpCioqICBNZXRob2RzIGZvciBjcmVhdGluZyB0cmVlLCB0cmFkaXRpb25hbCBwaHlsb2dlbnkgdnMuIHZhcmlhbnQKICAgIGhjbHVzdD8KKiBQQ1IgcXVlcmllcywgd29ya3Mgd2VsbCBpZiBvbmUgcGVyZm9ybXMgc2FuZ2VyIHNlcXVlbmNpbmcuCgojIyBNdWx0aXBsZSBkYXRhc2V0cwoKSW4gYSBjb3VwbGUgb2YgaW1wb3J0YW50IHdheXMgdGhlIFRNUkMyIGRhdGEgaXMgbXVjaCBtb3JlIGNvbXBsZXggdGhhbiB0aGUKVE1SQzM6CgoxLiAgSXQgY29tcHJpc2VzIG11bHRpcGxlLCBjb21wbGV0ZWx5IHNlcGFyYXRlIHF1ZXJpZXM6CiAgICBhLiAgU2VxdWVuY2luZyB0aGUgcGFyYXNpdGUgc2FtcGxlcwogICAgYi4gIFNlcXVlbmNpbmcgYSBzZXQgb2YgaHVtYW4gbWFjcm9waGFnZSBzYW1wbGVzIHdoaWNoIHdlcmUgaW5mZWN0ZWQKICAgICAgICB3aXRoIHNwZWNpZmljIHBhcmFzaXRlIHNhbXBsZXMuCjIuICBUaGUgcGFyYXNpdGUgdHJhbnNjcmlwdG9taWMgc2FtcGxlcyBjb21wcmlzZSBtdWx0aXBsZSBkaWZmZXJlbnQKICAgIHR5cGVzIG9mIHF1ZXJpZXM6CiAgICBhLiAgRGlmZmVyZW50aWFsIGV4cHJlc3Npb24gdG8gbG9vayBhdCBzdHJhaW4sIHN1c2NlcHRpYmlsaXR5LCBhbmQKICAgIGNsaW5pY2FsIG91dGNvbWVzLgogICAgYi4gIEluZGl2aWR1YWwgdmFyaWFudCBzZWFyY2hlcyB0byBsb29rIGZvciBwb3RlbnRpYWxseSB1c2VmdWwKICAgIFNOUHMgZm9yIGNsYXNzaWZpY2F0aW9uIG9mIHBhcmFzaXRlIHNhbXBsZXMuCjMuICBUaGUgaHVtYW4gbWFjcm9waGFnZSBzYW1wbGVzIG1heSBiZSB1c2VkIHRvIHF1ZXJ5IGJvdGggdGhlIGhvc3QKICAgIGFuZCBwYXJhc2l0ZSB0cmFuc2NyaXB0b21lcyBiZWNhdXNlIChhdCBsZWFzdCB3aGVuIG5vdCBkcnVnCiAgICB0cmVhdGVkKSB0aGVyZSBpcyBhIHRyZW1lbmRvdXMgcG9wdWxhdGlvbiBvZiBwYXJhc2l0ZSByZWFkcyBpbgogICAgdGhlbS4KCiMjIFNhbXBsZSBzaGVldChzKQoKT3VyIHNoYXJlZCBvbmxpbmUgc2FtcGxlIHNoZWV0IGlzIG5lYXJseSBzdGF0aWMgYXQgdGhlIHRpbWUgb2YgdGhpcwp3cml0aW5nICgyMDIyMDkpLCBJIGV4cGVjdCBhdCB0aGlzIHBvaW50IHRoZSBvbmx5IGxpa2VseSB1cGRhdGVzIHdpbGwKYmUgdG8gYW5ub3RhdGUgc29tZSBzdHJhaW5zIGFzIG1vcmUgb3IgbGVzcyBzdXNjZXB0aWJsZSB0byBkcnVnCnRyZWF0bWVudC4KCmBgYHtyfQpzYW1wbGVfc2hlZXQgPC0gInNhbXBsZV9zaGVldHMvQ2xpbmljYWxTdHJhaW5zX1RNUkMyLnhsc3giCm1hY3JvcGhhZ2Vfc2hlZXQgPC0gInNhbXBsZV9zaGVldHMvdG1yYzJfbWFjcm9waGFnZV9zYW1wbGVzLnhsc3giCmBgYAoKIyMjIE1vZGlmeSB0aGUgc2FtcGxlIHNoZWV0CgpUaGUgZm9sbG93aW5nIGJsb2NrIHByb3ZpZGVzIGFuIGV4YW1wbGUgaW52b2NhdGlvbiBvZiBob3cgSQphdXRvbWF0aWNhbGx5IGV4dHJhY3QgdGhpbmdzIGxpa2UgcGVyY2VudCByZWFkcyBtYXBwZWQvdHJpbW1lZC9ldGMKZnJvbSB0aGUgbG9ncyBwcm9kdWNlZCBieSB0cmltb21hdGljL2N1dGFkYXB0L2hpc2F0L3NhbG1vbi9ldGMuICBUaGUKY2F2ZWF0IGlzIHRoYXQgdGhpcyBjb250YWluZXIgb25seSBoYXMgYSBzbWFsbCBwb3J0aW9uIG9mIHRoZSBtYXRlcmlhbAphdmFpbGFibGUgaW4gdGhlIG1haW4gd29ya2luZyB0cmVlLCBhcyBhIHJlc3VsdCB0aGUgbmV3IGNvbHVtbnMgYWRkZWQKdG8gdGhlIHNhbXBsZSBzaGVldCBhcmUgcmVsYXRpdmVseSBzcGFyc2UgY29tcGFyZWQgdG8gd2hhdCBJIGdldCBvbiBteQpjb21wdXRlci4KCkluIGFkZGl0aW9uLCBiZWNhdXNlIHRoZXNlIHNhbXBsZXMgaGF2ZSBnb25lIHRocm91Z2ggfiAzIGRpZmZlcmVudAp2ZXJzaW9ucyBvZiBteSBwaXBlbGluZSwgYW5kIHRoZSBjb2RlIHdoaWNoIGV4dHJhY3RzIHRoZSBudW1iZXJzCmV4cGxpY2l0bHkgYXNzdW1lcyBvbmx5IHRoZSBtb3N0IHJlY2VudCB2ZXJzaW9uIChiZWNhdXNlIGl0IGlzIHRoZQpiZXN0ISksIGl0IGRvZXMgbm90IGdldCBvdXQgdGhlIGRhdGEgZm9yIGFsbCB0aGUgc2FtcGxlcy4KCmBgYHtyfQptb2RpZmllZCA8LSBnYXRoZXJfcHJlcHJvY2Vzc2luZ19tZXRhZGF0YShzYW1wbGVfc2hlZXQsIHNwZWNpZXMgPSAibHBhbmFtZW5zaXNfdjM2IikKYGBgCgojIEFubm90YXRpb25zCgpFdmVyeXRoaW5nIHdoaWNoIGZvbGxvd3MgZGVwZW5kcyBvbiB0aGUgRXhpc3RpbmcgVHJpVHJ5cERCIGFubm90YXRpb25zIHJldmlzaW9uCjQ2LCBjaXJjYSAyMDE5LiAgVGhlIGZvbGxvd2luZyBibG9jayBsb2FkcyBhIGRhdGFiYXNlIG9mIHRoZXNlIGFubm90YXRpb25zIGFuZAp0dXJucyBpdCBpbnRvIGEgbWF0cml4IHdoZXJlIHRoZSByb3dzIGFyZSBnZW5lcyBhbmQgY29sdW1ucyBhcmUgYWxsIHRoZQphbm5vdGF0aW9uIHR5cGVzIHByb3ZpZGVkIGJ5IFRyaVRyeXBEQi4KClRoZSBzYW1lIGRhdGFiYXNlIHdhcyB1c2VkIHRvIGNyZWF0ZSBhIG1hdHJpeCBvZiBvcnRob2xvZ291cyBnZW5lcyBiZXR3ZWVuCkwucGFuYW1lbnNpcyBhbmQgYWxsIG9mIHRoZSBvdGhlciBzcGVjaWVzIGluIHRoZSBUcmlUcnlwREIuCgpUaGUgc2FtZSBkYXRhYmFzZSBvZiBhbm5vdGF0aW9ucyBhbHNvIHByb3ZpZGVzIG1hcHBpbmdzIHRvIHRoZSBzZXQgb2YKYW5ub3RhdGVkIEdPIGNhdGVnb3JpZXMgZm9yIHRoZSBMLnBhbmFtZW5zaXMgZ2Vub21lIGFsb25nIHdpdGggZ2VuZQpsZW5ndGhzLgoKVGhlIGZvbGxvd2luZyBibG9jayBhc3N1bWVzIG9uZSBoYXMgYWNjZXNzIHRvIHRyaXRyeXBkYi5vcmcsIHdoaWNoIGlzCm5vIGN1cnJlbnRseSBndWFyYW50ZWVkLiAgVGh1cyBJIGJ1bmRsZWQgYSBwcmUtZ2VuZXJhdGVkIGNvcHkgb2YgdGhlCmdlbm9tZSwgVHhkYiwgYW5kIGFubm90YXRpb25zLgoKYGBge3IsIGV2YWw9RkFMU0V9CiMjIG1ldGEgPC0gZG93bmxvYWRfZXVwYXRoX21ldGFkYXRhKHdlYnNlcnZpY2UgPSAidHJpdHJ5cGRiIiwgZXVfdmVyc2lvbiA9ICJ2NDYiKQptZXRhIDwtIGRvd25sb2FkX2V1cGF0aF9tZXRhZGF0YSh3ZWJzZXJ2aWNlID0gInRyaXRyeXBkYiIpCnBhbmFtZW5zaXNfZW50cnkgPC0gZ2V0X2V1cGF0aF9lbnRyeSgiTUhPTSIsIG1ldGFkYXRhID0gbWV0YVtbInZhbGlkIl1dKQpwYW5hbWVuc2lzX2RiIDwtIG1ha2VfZXVwYXRoX29yZ2RiKHBhbmFtZW5zaXNfZW50cnkpCnBhbmFtZW5zaXNfcGtnIDwtIHBhbmFtZW5zaXNfZGJbWyJwa2duYW1lIl1dCnBhY2thZ2VfbmFtZSA8LSBwYW5hbWVuc2lzX2RiW1sicGtnbmFtZSJdXQppZiAoaXMubnVsbChwYW5hbWVuc2lzX3BrZykpIHsKICBwYW5hbWVuc2lzX3BrZyA8LSBwYW5hbWVuc2lzX2RiW1sib3JnZGJfbmFtZSJdXQogIHBhY2thZ2VfbmFtZSA8LSBwYW5hbWVuc2lzX3BrZwp9CnR0IDwtIGxpYnJhcnkocGFuYW1lbnNpc19wa2csIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkKcGFuYW1lbnNpc19wa2cgPC0gZ2V0MChwYW5hbWVuc2lzX3BrZykKYWxsX2ZpZWxkcyA8LSBjb2x1bW5zKHBhbmFtZW5zaXNfcGtnKQphbGxfbHBfYW5ub3QgPC0gc20obG9hZF9vcmdkYl9hbm5vdGF0aW9ucygKICAgIHBhbmFtZW5zaXNfcGtnLAogICAga2V5dHlwZSA9ICJnaWQiLAogICAgZmllbGRzID0gYygiYW5ub3RfZ2VuZV9lbnRyZXpfaWQiLCAiYW5ub3RfZ2VuZV9uYW1lIiwKICAgICAgICAgICAgICAgImFubm90X3N0cmFuZCIsICJhbm5vdF9jaHJvbW9zb21lIiwgImFubm90X2Nkc19sZW5ndGgiLAogICAgICAgICAgICAgICAiYW5ub3RfZ2VuZV9wcm9kdWN0IikpKSRnZW5lcwoKbHBfZ28gPC0gbG9hZF9vcmdkYl9nbyhwYWNrYWdlX25hbWUpCmxwX2dvIDwtIGxwX2dvWywgYygiR0lEIiwgIkdPIildCmxwX2xlbmd0aHMgPC0gYWxsX2xwX2Fubm90WywgYygiZ2lkIiwgImFubm90X2Nkc19sZW5ndGgiKV0KY29sbmFtZXMobHBfbGVuZ3RocykgIDwtIGMoIklEIiwgImxlbmd0aCIpCmFsbF9scF9hbm5vdFtbImFubm90X2dlbmVfcHJvZHVjdCJdXSA8LSB0b2xvd2VyKGFsbF9scF9hbm5vdFtbImFubm90X2dlbmVfcHJvZHVjdCJdXSkKb3J0aG9zIDwtIHNtKGV4dHJhY3RfZXVwYXRoX29ydGhvbG9ncyhkYiA9IHBhbmFtZW5zaXNfcGtnKSkKZGF0YV9zdHJ1Y3R1cmVzIDwtIGMoZGF0YV9zdHJ1Y3R1cmVzLCAibHBfbGVuZ3RocyIsICJscF9nbyIsICJhbGxfbHBfYW5ub3QiLCAibWV0YSIpCmBgYAoKYGBge3J9CmFsbF9pbnN0YWxsZWQgPC0gcm93bmFtZXMoaW5zdGFsbGVkLnBhY2thZ2VzKCkpCmNhbmRpZGF0ZXMgPC0gZ3JlcGwocGF0dGVybiA9ICJeb3JnLkxwYW5hbWVuc2lzLk1IT00uKnY2OC5lZy5kYiIsIHggPSBhbGxfaW5zdGFsbGVkKQpvcmdkYl9wa2dfbmFtZSA8LSBhbGxfaW5zdGFsbGVkW2NhbmRpZGF0ZXNdCgp0dCA8LSBsaWJyYXJ5KG9yZ2RiX3BrZ19uYW1lLCBjaGFyYWN0ZXIub25seSA9IFRSVUUpCnBhbmFtZW5zaXNfcGtnIDwtIGdldDAob3JnZGJfcGtnX25hbWUpCmFsbF9maWVsZHMgPC0gY29sdW1ucyhwYW5hbWVuc2lzX3BrZykKYWxsX2xwX2Fubm90IDwtIHNtKGxvYWRfb3JnZGJfYW5ub3RhdGlvbnMoCiAgICBwYW5hbWVuc2lzX3BrZywKICAgIGtleXR5cGUgPSAiZ2lkIiwKICAgIGZpZWxkcyA9IGMoImFubm90X2dlbmVfZW50cmV6X2lkIiwgImFubm90X2dlbmVfbmFtZSIsICJhbm5vdF9nZW5lX2xvY2F0aW9uX3RleHQiLAogICAgICAgICAgICAgICAiYW5ub3Rfc3RyYW5kIiwgImFubm90X2Nocm9tb3NvbWUiLCAiYW5ub3RfY2RzX2xlbmd0aCIsCiAgICAgICAgICAgICAgICJhbm5vdF9nZW5lX3Byb2R1Y3QiKSkpJGdlbmVzCgpscF9nbyA8LSBsb2FkX29yZ2RiX2dvKHBhbmFtZW5zaXNfcGtnKQpscF9nbyA8LSBscF9nb1ssIGMoIkdJRCIsICJHTyIpXQpscF9sZW5ndGhzIDwtIGFsbF9scF9hbm5vdFssIGMoImdpZCIsICJhbm5vdF9jZHNfbGVuZ3RoIildCmNvbG5hbWVzKGxwX2xlbmd0aHMpICA8LSBjKCJJRCIsICJsZW5ndGgiKQphbGxfbHBfYW5ub3RbWyJhbm5vdF9nZW5lX3Byb2R1Y3QiXV0gPC0gdG9sb3dlcihhbGxfbHBfYW5ub3RbWyJhbm5vdF9nZW5lX3Byb2R1Y3QiXV0pCmRhdGFfc3RydWN0dXJlcyA8LSBjKGRhdGFfc3RydWN0dXJlcywgImxwX2xlbmd0aHMiLCAibHBfZ28iLCAiYWxsX2xwX2Fubm90IiwgIm1ldGEiKQpgYGAKCiMjIFJlcGVhdCBmb3IgdGhlIEwubWFqb3IgYW5ub3RhdGlvbnMKClJlY2VudGx5IHRoZXJlIHdhcyBhIHJlcXVlc3QgdG8gaW5jbHVkZSB0aGUgTGVpc2htYW5pYSBtYWpvciBnZW5lIElEcwphbmQgZGVzY3JpcHRpb25zLiAgVGh1cyBJIHdpbGwgZXh0cmFjdCB0aGVtIGFsb25nIHdpdGggdGhlIG9ydGhvbG9ncwphbmQgYXBwZW5kIHRoYXQgdG8gdGhlIGFubm90YXRpb25zIHVzZWQuCgpIYXZpbmcgc3BlbnQgdGhlIHRpbWUgdG8gcnVuIHRoZSBmb2xsb3dpbmcgY29kZSwgSSByZWFsaXplZCB0aGF0IHRoZQpvcnRob2xvZ3MgZGF0YSBzdHJ1Y3R1cmUgYWJvdmUgYWN0dWFsbHkgYWxyZWFkeSBoYXMgdGhlIGdlbmUgSURzIGFuZApkZXNjcmlwdGlvbnMuCgpUaHVzIEkgd2lsbCBsZWF2ZSBteSBxdWVyeSBpbiBwbGFjZSB0byBleHRyYWN0IHRoZSBtYWpvciBhbm5vdGF0aW9ucywKYnV0IGZvbGxvdyBpdCB1cCB3aXRoIGEgY29sbGFwc2Ugb2YgdGhlIG1ham9yIG9ydGhvbG9ncyBhbmQgYXBwZW5kaW5nCm9mIHRoYXQgdG8gdGhlIHBhbmFtZW5zaXMgYW5ub3RhdGlvbnMuCgpgYGB7ciBldXBhdGhkYl9sbWFqb3IsIGV2YWw9RkFMU0V9Cm9yZ2RiIDwtICJvcmcuTG1ham9yLkZyaWVkbGluLnY0OS5lZy5kYiIKdHQgPC0gc20obGlicmFyeShvcmdkYiwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKSkKbWFqb3JfZGIgPC0gb3JnLkxtYWpvci5GcmllZGxpbi52NDkuZWcuZGIKYWxsX2ZpZWxkcyA8LSBjb2x1bW5zKHBhbl9kYikKYWxsX2xtX2Fubm90IDwtIHNtKGxvYWRfb3JnZGJfYW5ub3RhdGlvbnMoCiAgICBtYWpvcl9kYiwKICAgIGtleXR5cGUgPSAiZ2lkIiwKICAgIGZpZWxkcyA9IGMoImFubm90X2dlbmVfZW50cmV6X2lkIiwgImFubm90X2dlbmVfbmFtZSIsCiAgICAgICAgICAgICAgICJhbm5vdF9zdHJhbmQiLCAiYW5ub3RfY2hyb21vc29tZSIsICJhbm5vdF9jZHNfbGVuZ3RoIiwKICAgICAgICAgICAgICAgImFubm90X2dlbmVfcHJvZHVjdCIpKSkkZ2VuZXMKCndhbnRlZF9vcnRob3NfaWR4IDwtIG9ydGhvc1tbIk9SVEhPTE9HU19TUEVDSUVTIl1dID09ICJMZWlzaG1hbmlhIG1ham9yIHN0cmFpbiBGcmllZGxpbiIKc3VtKHdhbnRlZF9vcnRob3NfaWR4KQp3YW50ZWRfb3J0aG9zIDwtIG9ydGhvc1t3YW50ZWRfb3J0aG9zX2lkeCwgXQp3YW50ZWRfb3J0aG9zIDwtIHdhbnRlZF9vcnRob3NbLCBjKCJHSUQiLCAiT1JUSE9MT0dTX0lEIiwgIk9SVEhPTE9HU19OQU1FIildCgpjb2xsYXBzZWRfb3J0aG9zIDwtIHdhbnRlZF9vcnRob3MgJT4lCiAgZ3JvdXBfYnkoR0lEKSAlPiUKICBzdW1tYXJpc2UoY29sbGFwc2VkX2lkID0gc3RyaW5ncjo6c3RyX2MoT1JUSE9MT0dTX0lELCBjb2xsYXBzZSA9ICIgOyAiKSwKICAgICAgICAgICAgY29sbGFwc2VkX25hbWUgPSBzdHJpbmdyOjpzdHJfYyhPUlRIT0xPR1NfTkFNRSwgY29sbGFwc2UgPSAiIDsgIikpCmFsbF9scF9hbm5vdCA8LSBtZXJnZShhbGxfbHBfYW5ub3QsIGNvbGxhcHNlZF9vcnRob3MsIGJ5LnggPSAicm93Lm5hbWVzIiwKICAgICAgICAgICAgICAgICAgICAgIGJ5LnkgPSAiR0lEIiwgYWxsLnggPSBUUlVFKQpyb3duYW1lcyhhbGxfbHBfYW5ub3QpIDwtIGFsbF9scF9hbm5vdFtbIlJvdy5uYW1lcyJdXQphbGxfbHBfYW5ub3RbWyJSb3cubmFtZXMiXV0gPC0gTlVMTApkYXRhX3N0cnVjdHVyZXMgPC0gYyhkYXRhX3N0cnVjdHVyZXMsICJscF9sZW5ndGhzIiwgImxwX2dvIiwgImFsbF9scF9hbm5vdCIpCmBgYAoKIyBMb2FkIGEgZ2Vub21lCgpUaGUgZm9sbG93aW5nIGJsb2NrIGxvYWRzIHRoZSBmdWxsIGdlbm9tZSBzZXF1ZW5jZSBmb3IgcGFuYW1lbnNpcy4gIFdlCm1heSB1c2UgdGhpcyBsYXRlciB0byBhdHRlbXB0IHRvIGVzdGltYXRlIFBDUiBwcmltZXJzIHRvIGRpc2Nlcm4gc3RyYWlucy4KCkkgYW0gbm90IHN1cmUgaG93IHRvIGluY3JlYXNlIHRoZSBudW1iZXIgb2Ygb3BlbiBmaWxlcyBpbiBhIGNvbnRhaW5lciwKYXMgYSByZXN1bHQgdGhpcyBkb2VzIG5vdCB3b3JrLgoKYGBge3J9CiMjIHRlc3RpbmdfcGFuYW1lbnNpcyA8LSBtYWtlX2V1cGF0aF9ic2dlbm9tZShlbnRyeSA9IHBhbmFtZW5zaXNfZW50cnksIGV1X3ZlcnNpb24gPSAidjQ2IikKcGtnX2NhbmRpZGF0ZXMgPC0gZ3JlcGwoeCA9IGFsbF9pbnN0YWxsZWQsIHBhdHRlcm4gPSAiQlNHZW5vbWVcXC5MZWlzaG1hbmlhXFwucGFuYW1lbnNpcy4qIikKcGtnX25hbWUgPC0gYWxsX2luc3RhbGxlZFtwa2dfY2FuZGlkYXRlc11bMV0KbGlicmFyeShhcy5jaGFyYWN0ZXIocGtnX25hbWUpLCBjaGFyYWN0ZXIub25seSA9IFRSVUUpCmxwX2dlbm9tZSA8LSBnZXQwKGFzLmNoYXJhY3Rlcihwa2dfbmFtZSkpCmRhdGFfc3RydWN0dXJlcyA8LSBjKGRhdGFfc3RydWN0dXJlcywgImxwX2dlbm9tZSIpCmBgYAoKIyBHZW5lcmF0ZSBFeHByZXNzaW9uc2V0cyBhbmQgU2FtcGxlIEVzdGltYXRpb24KClRoZSBwcm9jZXNzIG9mIHNhbXBsZSBlc3RpbWF0aW9uIHRha2VzIHR3byBwcmltYXJ5IGlucHV0czoKCjEuICBUaGUgc2FtcGxlIHNoZWV0LCB3aGljaCBjb250YWlucyBhbGwgdGhlIG1ldGFkYXRhIHdlIGN1cnJlbnRseSBoYXZlIG9uIGhhbmQsCiAgICBpbmNsdWRpbmcgZmlsZW5hbWVzIGZvciB0aGUgb3V0cHV0cyBvZiAjMyBhbmQgIzQgYWJvdmUuCjIuICBUaGUgZ2VuZSBhbm5vdGF0aW9ucy4KCkFuIGV4cHJlc3Npb25TZXQob3Igc3VtbWFyaXplZEV4cGVyaW1lbnQpIGlzIGEgZGF0YSBzdHJ1Y3R1cmUgdXNlZCBpbgpSIHRvIGV4YW1pbmUgUk5BU2VxIGRhdGEuICBJdCBpcyBjb21wcmlzZWQgb2YgYW5ub3RhdGlvbnMsIG1ldGFkYXRhLAphbmQgZXhwcmVzc2lvbiBkYXRhLiAgSW4gdGhlIGNhc2Ugb2Ygb3VyIHByb2Nlc3NpbmcgcGlwZWxpbmUsIHRoZQpsb2NhdGlvbiBvZiB0aGUgZXhwcmVzc2lvbiBkYXRhIGlzIHByb3ZpZGVkIGJ5IHRoZSBmaWxlbmFtZXMgaW4gdGhlIG1ldGFkYXRhLgoKIyMgTm90ZXMKClRoZSBmb2xsb3dpbmcgc2FtcGxlcyBhcmUgbXVjaCBsb3dlciBjb3ZlcmFnZToKCiogVE1SQzIwMDAyCiogVE1SQzIwMDA2CiogVE1SQzIwMDA3CiogVE1SQzIwMDA4CgpUaGVyZSBpcyBhIHNldCBvZiBzdHJhaW5zIHdoaWNoIGFjcXVpcmVkIHJlc2lzdGFuY2UgaW4gdml0cm8uICBUaGVzZQphcmUgaW5jbHVkZWQgaW4gdGhlIGRhdGFzZXQsIGJ1dCB0aGVyZSBhcmUgbm90IGxpa2VseSBlbm91Z2ggb2YgdGhlbQp0byBxdWVyeSB0aGF0IHF1ZXN0aW9uIGV4cGxpY2l0bHkuCgojIyBEZWZpbmUgY29sb3JzCgpUaGUgZm9sbG93aW5nIGxpc3QgY29udGFpbnMgdGhlIGNvbG9ycyB3ZSBoYXZlIGNob3NlbiB0byB1c2Ugd2hlbgpwbG90dGluZyB0aGUgdmFyaW91cyB3YXlzIG9mIGRpc2Nlcm5pbmcgdGhlIGRhdGEuCgpgYGB7cn0KY29sb3JfY2hvaWNlcyA8LSBsaXN0KAogICAgInN0cmFpbiIgPSBsaXN0KAogICAgICAgICMjICJ6MS4wIiA9ICIjMzMzMzMzIiwgIyMgQ2hhbmdlZCB0aGlzIHRvICdicmF6JyB0byBtYWtlIGl0IGVhc2llciB0byBmaW5kIHRoZW0uCiAgICAgICAgInoyLjAiID0gIiM1NTU1NTUiLAogICAgICAgICJ6My4wIiA9ICIjNzc3Nzc3IiwKICAgICAgICAiejIuMSIgPSAiIzg3NDQwMCIsCiAgICAgICAgInoyLjIiID0gIiMwMDAwY2MiLAogICAgICAgICJ6Mi4zIiA9ICIjY2MwMDAwIiwKICAgICAgICAiejIuNCIgPSAiI2RmNzAwMCIsCiAgICAgICAgInozLjIiID0gIiM4ODg4ODgiLAogICAgICAgICJ6MS4wIiA9ICIjY2MwMGNjIiwKICAgICAgICAiejEuNSIgPSAiI2NjMDBjYyIsCiAgICAgICAgImIyOTA0IiA9ICIjY2MwMGNjIiwKICAgICAgICAidW5rbm93biIgPSAiI2NiY2JjYiIpLAogICAgIyMgIm51bGwiID0gIiMwMDAwMDAiKSwKICAgICJ6eW1vIiA9IGxpc3QoCiAgICAgICJ6MjIiID0gIiMwMDAwY2MiLAogICAgICAiejIzIiA9ICIjY2MwMDAwIiksCiAgICAiY2YiID0gbGlzdCgKICAgICAgICAiY3VyZSIgPSAiIzAwNmYwMCIsCiAgICAgICAgImZhaWwiID0gIiM5ZGZmYTAiLAogICAgICAgICJ1bmtub3duIiA9ICIjY2JjYmNiIiwKICAgICAgICAibm90YXBwbGljYWJsZSIgPSAiIzAwMDAwMCIpLAogICAgInN1c2NlcHRpYmlsaXR5IiA9IGxpc3QoCiAgICAgICAgInJlc2lzdGFudCIgPSAiIzg1NjNhNyIsCiAgICAgICAgInNlbnNpdGl2ZSIgPSAiIzhkMDAwMCIsCiAgICAgICAgImFtYmlndW91cyIgPSAiI2NiY2JjYiIsCiAgICAgICAgInVua25vd24iID0gIiM1NTU1NTUiKSkKZGF0YV9zdHJ1Y3R1cmVzIDwtIGMoZGF0YV9zdHJ1Y3R1cmVzLCAiY29sb3JfY2hvaWNlcyIpCmBgYAoKIyBQYXJhc2l0ZS1vbmx5IGRhdGEgc3RydWN0dXJlCgpUaGUgZGF0YSBzdHJ1Y3R1cmUgJ2xwX3NlJyBjb250YWlucyB0aGUgZGF0YSBmb3IgYWxsIHNhbXBsZXMgd2hpY2gKaGF2ZSBoaXNhdDIgY291bnQgdGFibGVzLCBhbmQgd2hpY2ggcGFzcyBhIGZldyBpbml0aWFsIHF1YWxpdHkgdGVzdHMKKGUuZy4gdGhleSBtdXN0IGhhdmUgbW9yZSB0aGFuIDg1NTAgZ2VuZXMgd2l0aCA+MCBjb3VudHMgYW5kID41ZTYKcmVhZHMgd2hpY2ggbWFwcGVkIHRvIGEgZ2VuZSk7IGdlbmVzIHdoaWNoIGFyZSBhbm5vdGF0ZWQgd2l0aCBhIGZldwprZXkgcmVkdW5kYW50IGNhdGVnb3JpZXMgKGxlaXNobWFub2x5c2luIGZvciBleGFtcGxlKSBhcmUgYWxzbyBjdWxsZWQuCgojIyBBbGwgKGFsbW9zdCkgc2FtcGxlcwoKVGhlcmUgYXJlIGEgZmV3IG1ldGFkYXRhIGNvbHVtbnMgd2hpY2ggd2UgcmVhbGx5IHdhbnQgdG8gbWFrZSBjZXJ0YWluCmFyZSBzdGFuZGFyZGl6ZWQuCgpOb3RlOiBJIGNoYW5nZWQgdGhpcyB0byBwcmludCBib3RoIHRoZSBudW1iZXIgb2YgcmVhZHMgYW5kIGdlbmVzIGZvciByZW1vdmVkIHNhbXBsZXMuCgoyMDI1MTA6IENvbW1lbnRpbmcgb3V0IHRoZSBzZW1hbnRpYyBmaWx0ZXIgYW5kIHdpbGwgZWl0aGVyIG5vdCBhcHBseQppdCBvciBtb3ZlIGl0IHRvIHNvbWV3aGVyZSBhZnRlciB0aGUgdmlzdWFsaXphdGlvbiBvZiB0aGUgZGF0YS4KCmBgYHtyfQpzYW5pdGl6ZV9jb2x1bW5zIDwtIGMoInBhc3NhZ2VudW1iZXIiLCAiY2xpbmljYWxyZXNwb25zZSIsICJjbGluaWNhbGNhdGVnb3JpY2FsIiwKICAgICAgICAgICAgICAgICAgICAgICJ6eW1vZGVtZWNhdGVnb3JpY2FsIiwgImluY2x1ZGVkIikKbHBfc2UgPC0gY3JlYXRlX3NlKHNhbXBsZV9zaGVldCwKICAgICAgICAgICAgICAgICAgIGdlbmVfaW5mbyA9IGFsbF9scF9hbm5vdCwKICAgICAgICAgICAgICAgICAgIGFubm90YXRpb25fbmFtZSA9IG9yZ2RiX3BrZ19uYW1lLAogICAgICAgICAgICAgICAgICAgc2F2ZWZpbGUgPSBnbHVlKCJyZGEvdG1yYzJfbHBfc2VfYWxsX3Jhdy12e3Zlcn0ucmRhIiksCiAgICAgICAgICAgICAgICAgICBpZF9jb2x1bW4gPSAiaHBnbGlkZW50aWZpZXIiLAogICAgICAgICAgICAgICAgICAgZmlsZV9jb2x1bW4gPSAibHBhbmFtZW5zaXN2MzZoaXNhdGZpbGUiKSAlPiUKICBzZXRfY29uZGl0aW9ucyhmYWN0ID0gInp5bW9kZW1lY2F0ZWdvcmljYWwiLCBjb2xvcnMgPSBjb2xvcl9jaG9pY2VzW1sic3RyYWluIl1dKSAlPiUKIyMgIHNlbWFudGljX2ZpbHRlcihzZW1hbnRpYyA9IGMoImFtYXN0aW4iLCAiZ3A2MyIsICJsZWlzaG1hbm9seXNpbiIpLAojIyAgICAgICAgICAgICAgICAgICAgICAgc2VtYW50aWNfY29sdW1uID0gImFubm90X2dlbmVfcHJvZHVjdCIpICU+JQogIHNhbml0aXplX21ldGFkYXRhKGNvbHVtbnMgPSBzYW5pdGl6ZV9jb2x1bW5zKSAlPiUKICBzdWJzZXRfc2Uoc3Vic2V0ID0gImluY2x1ZGVkPT0neWVzJyIpICU+JQogIHNldF9mYWN0b3JzKGNvbHVtbnMgPSBzYW5pdGl6ZV9jb2x1bW5zLCBjbGFzcyA9ICJmYWN0b3IiKQpkYXRhX3N0cnVjdHVyZXMgPC0gYyhkYXRhX3N0cnVjdHVyZXMsICJscF9zZSIpCnNhdmUobGlzdCA9ICJscF9zZSIsIGZpbGUgPSBnbHVlKCJyZGEvdG1yYzJfbHBfc2VfYWxsX3Nhbml0aXplZC12e3Zlcn0ucmRhIikpCgp0YWJsZShjb2xEYXRhKGxwX3NlKVtbInp5bW9kZW1lY2F0ZWdvcmljYWwiXV0pCnRhYmxlKGNvbERhdGEobHBfc2UpW1siY2xpbmljYWxyZXNwb25zZSJdXSkKdGFibGUoY29sRGF0YShscF9zZSlbWyJjbGluaWNhbGNhdGVnb3JpY2FsIl1dKQpuY29sKGFzc2F5KGxwX3NlKSkKYGBgCgojIyBQcmludCBzYW1wbGUgSURzIGJ5IHN0YXR1cwoKIyMjIEN1cmUKCmBgYHtyfQpjdXJlX2lkcyA8LSBjb2xEYXRhKGxwX3NlKVtbImNsaW5pY2FsY2F0ZWdvcmljYWwiXV0gPT0gImN1cmUiCnJvd25hbWVzKGNvbERhdGEobHBfc2UpKVtjdXJlX2lkc10KYGBgCgojIyMgRmFpbAoKYGBge3J9CmZhaWxfaWRzIDwtIGNvbERhdGEobHBfc2UpW1siY2xpbmljYWxjYXRlZ29yaWNhbCJdXSA9PSAiZmFpbCIKcm93bmFtZXMoY29sRGF0YShscF9zZSkpW2ZhaWxfaWRzXQpgYGAKCiMjIyBVbmtub3duCgpgYGB7cn0KdW5rbm93bl9pZHMgPC0gY29sRGF0YShscF9zZSlbWyJjbGluaWNhbGNhdGVnb3JpY2FsIl1dID09ICJ1bmtub3duIgpyb3duYW1lcyhjb2xEYXRhKGxwX3NlKSlbdW5rbm93bl9pZHNdCmBgYAoKIyMjIFN1c2NlcHRpYmxlIGFuZCBzdHJhaW4KCmBgYHtyfQphbGxfc2Vuc2l0aXZlX2lkcyA8LSBjb2xEYXRhKGxwX3NlKVtbInF1YWxpdGF0aXZlY2xhc3NpZmljYXRpb25vZmRydWdzdXNjZXB0aWJpbGl0eSJdXSA9PSAiU2Vuc2l0aXZlIgpzZW5zaXRpdmVfaWRzIDwtIHJvd25hbWVzKGNvbERhdGEobHBfc2UpKVthbGxfc2Vuc2l0aXZlX2lkc10Kc2Vuc2l0aXZlX2lkcwoKYWxsX3Jlc2lzdGFudF9pZHMgPC0gY29sRGF0YShscF9zZSlbWyJxdWFsaXRhdGl2ZWNsYXNzaWZpY2F0aW9ub2ZkcnVnc3VzY2VwdGliaWxpdHkiXV0gPT0gIlJlc2lzdGFudCIKcmVzaXN0YW50X2lkcyA8LSByb3duYW1lcyhjb2xEYXRhKGxwX3NlKSlbYWxsX3Jlc2lzdGFudF9pZHNdCnJlc2lzdGFudF9pZHMKCmFsbF96MjMgPC0gY29sRGF0YShscF9zZSlbWyJ6eW1vZGVtZWNhdGVnb3JpY2FsIl1dID09ICJ6MjMiCnoyM19pZHMgPC0gcm93bmFtZXMoY29sRGF0YShscF9zZSkpW2FsbF96MjNdCnoyM19pZHMKCmFsbF96MjIgPC0gY29sRGF0YShscF9zZSlbWyJ6eW1vZGVtZWNhdGVnb3JpY2FsIl1dID09ICJ6MjIiCnoyMl9pZHMgPC0gcm93bmFtZXMoY29sRGF0YShscF9zZSkpW2FsbF96MjJdCnoyMl9pZHMKCmJvdGhfaWRzIDwtIHoyMl9pZHMgJWluJSByZXNpc3RhbnRfaWRzCnN1bW1hcnkoYm90aF9pZHMpCnJvd25hbWVzKGNvbERhdGEobHBfc2UpKVtib3RoX2lkc10KCmJvdGhfaWRzIDwtIHoyM19pZHMgJWluJSBzZW5zaXRpdmVfaWRzCnN1bW1hcnkoYm90aF9pZHMpCmBgYAoKQWxsIHRoZSBmb2xsb3dpbmcgZGF0YSB3aWxsIGRlcml2ZSBmcm9tIHRoaXMgc3RhcnRpbmcgcG9pbnQuCgojIyBFeHRyYWN0IHNhbXBsZXMgZnJvbSBvbmx5IHRoZSB0d28gJ2Nhbm9uaWNhbCcgc3RyYWlucwoKIyMjIFF1aWNrIGRpdmVyZ2VuY2UKCkhlcmUgaXMgYSB0YWJsZSBvZiBteSBjdXJyZW50IGNsYXNzaWZpZXIncyBpbnRlcnByZXRhdGlvbiBvZiB0aGUgc3RyYWlucy4KCmBgYHtyfQp0YWJsZShjb2xEYXRhKGxwX3NlKVtbImtubnYyY2xhc3NpZmljYXRpb24iXV0pCmBgYAoKIyMjIE1lcmdlIDIuMS8yLjIgYW5kIDIuNC8yLjMKCmBgYHtyfQptZXJnZWRfenltbyA8LSBscF9zZQpjb2xEYXRhKG1lcmdlZF96eW1vKVtbInp5bW9kZW1lIl1dIDwtIGFzLmNoYXJhY3Rlcihjb2xEYXRhKG1lcmdlZF96eW1vKVtbInp5bW9kZW1lY2F0ZWdvcmljYWwiXV0pCnoyMV9pZHggPC0gY29sRGF0YShtZXJnZWRfenltbylbWyJ6eW1vZGVtZSJdXSA9PSAiejIxIgpjb2xEYXRhKG1lcmdlZF96eW1vKVt6MjFfaWR4LCAienltb2RlbWUiXSA8LSAiejIyIgoKejI0X2lkeCA8LSBjb2xEYXRhKG1lcmdlZF96eW1vKVtbInp5bW9kZW1lIl1dID09ICJ6MjQiCmNvbERhdGEobWVyZ2VkX3p5bW8pW3oyNF9pZHgsICJ6eW1vZGVtZSJdIDwtICJ6MjMiCgprZWVwZXJzIDwtIGNvbERhdGEobWVyZ2VkX3p5bW8pW1sienltb2RlbWUiXV0gPT0gInoyMiIgfAogIGNvbERhdGEobWVyZ2VkX3p5bW8pW1sienltb2RlbWUiXV0gPT0gInoyMyIKbWVyZ2VkX3p5bW8gPC0gbWVyZ2VkX3p5bW9bLCBrZWVwZXJzXSAlPiUKICBzZXRfY29uZGl0aW9ucyhmYWN0ID0gInp5bW9kZW1lIiwgY29sb3JzID0gY29sb3JfY2hvaWNlc1tbInp5bW8iXV0pCmBgYAoKIyBBZGQgbGlicmFyeSBzaXplcyBiZWZvcmUgZmlsdGVyaW5nCgpgYGB7cn0KdGFibGUoY29sRGF0YShscF9zZSlbWyJjbGluaWNhbGNhdGVnb3JpY2FsIl1dKQp1bmtub3duX2lkcyA8LSBjb2xEYXRhKGxwX3NlKVtbImNsaW5pY2FsY2F0ZWdvcmljYWwiXV0gPT0gInVua25vd24iCnJvd25hbWVzKGNvbERhdGEobHBfc2UpKVt1bmtub3duX2lkc10KZmFpbGVkX2lkcyA8LSBjb2xEYXRhKGxwX3NlKVtbImNsaW5pY2FsY2F0ZWdvcmljYWwiXV0gPT0gImZhaWwiCnJvd25hbWVzKGNvbERhdGEobHBfc2UpKVtmYWlsZWRfaWRzXQoKcHJlX2xpYnNpemUgPC0gcGxvdF9saWJzaXplKGxwX3NlKQpwcmVfbGlic2l6ZQoKcGRmKGZpbGUgPSAiZmlndXJlcy9saWJyYXJ5X3NpemVfcHJlX2ZpbHRlci5wZGYiLCB3aWR0aCA9IDI0LCBoZWlnaHQgPSAxMikKcHJlX2xpYnNpemUkcGxvdApkZXYub2ZmKCkKCnByZV9ub256ZXJvIDwtIHBsb3Rfbm9uemVybyhscF9zZSwgeV9pbnRlcmNlcHQgPSAwLjk5KQpwcmVfbm9uemVybwpwZGYoZmlsZSA9ICJmaWd1cmVzL25vbnplcm9fcHJlX2ZpbHRlci5wZGYiKQpwcmVfbm9uemVybyRwbG90CmRldi5vZmYoKQoKbHBfc2VfcHJlIDwtIGxwX3NlCmxwX3NlIDwtIHN1YnNldF9zZShscF9zZSwgbm9uemVybyA9IDg1NTApCgpwb3N0X25vbnplcm8gPC0gcGxvdF9ub256ZXJvKGxwX3NlLCB5X2ludGVyY2VwdCA9IDAuOTkpCnBvc3Rfbm9uemVybwpgYGAKCiMjIEV4dHJhY3QgaGlzdG9yaWNhbCBzdXNjZXB0aWJpbGl0eSBkYXRhCgpDb2x1bW4gJ1EnIGluIHRoZSBzYW1wbGUgc2hlZXQsIG1ha2UgYSBjYXRlZ29yaWNhbCB2ZXJzaW9uIG9mIGl0IHdpdGggdGhlc2UgcGFyYW1ldGVyczoKCiogMCA8PSB4IDw9IDM1IGlzIHJlc2lzdGFudAoqIDM2IDw9IHggPD0gNDggaXMgYW1iaWd1b3VzCiogNDkgPD0geCBpcyBzZW5zaXRpdmUKCk5vdGUgdGhhdCB0aGVzZSBjdXRvZmZzIGFyZSBvbmx5IHZhbGlkIGZvciB0aGUgaGlzdG9yaWNhbCBkYXRhLiAgVGhlCm5ld2VyIHN1c2NlcHRpYmlsaXR5IGRhdGEgdXNlcyBhIGN1dG9mZiBvZiAwLjc4IGZvciBzZW5zaXRpdmUuICBJIHdpbGwKc2V0IGFtYmlndW91cyB0byAwLjUgdG8gMC43OD8KCmBgYHtyfQptYXhfcmVzaXN0X2hpc3RvcmljYWwgPC0gMC4zNQptaW5fc2Vuc2l0aXZlX2hpc3RvcmljYWwgPC0gMC40OQoKIyMgMjAyMzA1OiBSZW1vdmVkIGFtYmlndW91cyBjYXRlZ29yeSBmb3IgdGhlIGN1cnJlbnQgc2V0LgptYXhfcmVzaXN0X2N1cnJlbnQgPC0gMC43NwptaW5fc2Vuc2l0aXZlX2N1cnJlbnQgPC0gMC43NwpgYGAKClRoZSBzYW5pdGl6ZV9wZXJjZW50KCkgZnVuY3Rpb24gc2Vla3MgdG8gbWFrZSB0aGUgcGVyY2VudGFnZSB2YWx1ZXMKcmVjb3JkZWQgYnkgZXhjZWwgbW9yZSByZWxpYWJsZS4gIFVuZm9ydHVuYXRlbHksIHNvbWV0aW1lcyBleGNlbApkaXNwbGF5cyB0aGUgdmFsdWUgJzQ5JScgd2hlbiB0aGUgaW5mb3JtYXRpb24gcmVjb3JkZWQgaW4gdGhlCndvcmtzaGVldCBpcyBhbnkgb25lIG9mIHRoZSBmb2xsb3dpbmc6CgoqICc0OSUKKiAwLjQ5CiogIjAuNDkiCgpUaHVzLCB0aGUgZm9sbG93aW5nIGJsb2NrIHdpbGwgc2FuaXRpemUgdGhlc2UgcGVyY2VudGFnZSB2YWx1ZXMgaW50byBhCnNpbmdsZSBkZWNpbWFsIG51bWJlciBhbmQgbWFrZSBhIGNhdGVnb3JpY2FsIHZhcmlhYmxlIGZyb20gaXQgdXNpbmcKcHJlLWRlZmluZWQgdmFsdWVzIGZvciByZXNpc3RhbnQvYW1iaWd1b3VzL3NlbnNpdGl2ZS4gIFRoaXMKY2F0ZWdvcmljYWwgdmFyaWFibGUgd2lsbCBiZSBzdG9yZWQgaW4gYSBuZXcgY29sdW1uOiAnc3VzX2NhdGVnb3J5X2hpc3RvcmljYWwnLgoKYGBge3J9CnN0IDwtIGNvbERhdGEobHBfc2UpW1sic3VzY2VwdGliaWxpdHlpbmZlY3Rpb25yZWR1Y3Rpb24zMnVnbWxzYnZoaXN0b3JpY2FsZGF0YSJdXQpzdGFydGluZyA8LSBzYW5pdGl6ZV9wZXJjZW50KHN0KQpzdApzdGFydGluZwpzdXNfY2F0ZWdvcmljYWwgPC0gc3RhcnRpbmcKbmFfaWR4IDwtIGlzLm5hKHN0YXJ0aW5nKQpzdW0obmFfaWR4KQpzdXNfY2F0ZWdvcmljYWxbbmFfaWR4XSA8LSAidW5rbm93biIKCnJlc2lzdF9pZHggPC0gc3RhcnRpbmcgPD0gbWF4X3Jlc2lzdF9oaXN0b3JpY2FsCnN1c19jYXRlZ29yaWNhbFtyZXNpc3RfaWR4XSA8LSAicmVzaXN0YW50IgppbmRldGVybWluYW50X2lkeCA8LSBzdGFydGluZyA+IG1heF9yZXNpc3RfaGlzdG9yaWNhbCAmCiAgc3RhcnRpbmcgPCBtaW5fc2Vuc2l0aXZlX2hpc3RvcmljYWwKc3VzX2NhdGVnb3JpY2FsW2luZGV0ZXJtaW5hbnRfaWR4XSA8LSAiYW1iaWd1b3VzIgpzdXNjZXB0aWJsZV9pZHggPC0gc3RhcnRpbmcgPj0gbWluX3NlbnNpdGl2ZV9oaXN0b3JpY2FsCnN1c19jYXRlZ29yaWNhbFtzdXNjZXB0aWJsZV9pZHhdIDwtICJzZW5zaXRpdmUiCgpzdXNfY2F0ZWdvcmljYWwgPC0gYXMuZmFjdG9yKHN1c19jYXRlZ29yaWNhbCkKY29sRGF0YShscF9zZSlbWyJzdXNfY2F0ZWdvcnlfaGlzdG9yaWNhbCJdXSA8LSBzdXNfY2F0ZWdvcmljYWwKdGFibGUoc3VzX2NhdGVnb3JpY2FsKQoKdHdvX3NhbmtleSA8LSBwbG90X21ldGFfc2Fua2V5KAogIG1lcmdlZF96eW1vLCBmYWN0b3JzID0gYygienltb2RlbWUiLCAiY2xpbmljYWxjYXRlZ29yaWNhbCIsICJzdXNjZXB0aWJpbGl0eSIpLAogIGRyaWxsX2Rvd24gPSBUUlVFLCBjb2xvcl9jaG9pY2VzID0gY29sb3JfY2hvaWNlcykKdHdvX3NhbmtleQpgYGAKCiMjIEV4dHJhY3QgY3VycmVudCBzdXNjZXB0aWJpbGl0eSBkYXRhCgpUaGUgc2FtZSBwcm9jZXNzIHdpbGwgYmUgcmVwZWF0ZWQgZm9yIHRoZSBjdXJyZW50IGl0ZXJhdGlvbiBvZiB0aGUKc2Vuc2l0aXZpdHkgYXNzYXkgYW5kIHN0b3JlZCBpbiB0aGUgJ3N1c19jYXRlZ29yeV9jdXJyZW50JyBjb2x1bW4uCgpgYGB7cn0Kc3RhcnRpbmdfY3VycmVudCA8LSBzYW5pdGl6ZV9wZXJjZW50KGNvbERhdGEobHBfc2UpW1sic3VzY2VwdGliaWxpdHlpbmZlY3Rpb25yZWR1Y3Rpb24zMnVnbWxzYnZjdXJyZW50ZGF0YSJdXSkKc3VzX2NhdGVnb3JpY2FsX2N1cnJlbnQgPC0gc3RhcnRpbmdfY3VycmVudApuYV9pZHggPC0gaXMubmEoc3RhcnRpbmdfY3VycmVudCkKc3VtKG5hX2lkeCkKc3VzX2NhdGVnb3JpY2FsX2N1cnJlbnRbbmFfaWR4XSA8LSAidW5rbm93biIKCiMjIFRoZSBmb2xsb3dpbmcgaXMgb25seSB2YWxpZCB3aGVuIHdlIGhhZCB0aHJlZSBjYXRlZ29yaWVzLCByZXNpc3RhbnQvYW1iaWd1b3VzL3NlbnNpdGl2ZQojIyBUaGUgbmV3IGN1dG9mZnMgZHJvcCBhbWJpZ3VvdXMuCiNyZXNpc3RfaWR4IDwtIHN0YXJ0aW5nX2N1cnJlbnQgPD0gbWF4X3Jlc2lzdF9jdXJyZW50CiNzdXNfY2F0ZWdvcmljYWxfY3VycmVudFtyZXNpc3RfaWR4XSA8LSAicmVzaXN0YW50IgojaW5kZXRlcm1pbmFudF9pZHggPC0gc3RhcnRpbmdfY3VycmVudCA+IG1heF9yZXNpc3RfY3VycmVudCAmCiMgIHN0YXJ0aW5nX2N1cnJlbnQgPCBtaW5fc2Vuc2l0aXZlX2N1cnJlbnQKI3N1c19jYXRlZ29yaWNhbF9jdXJyZW50W2luZGV0ZXJtaW5hbnRfaWR4XSA8LSAiYW1iaWd1b3VzIgojc3VzY2VwdGlibGVfaWR4IDwtIHN0YXJ0aW5nX2N1cnJlbnQgPj0gbWluX3NlbnNpdGl2ZV9jdXJyZW50CiNzdXNfY2F0ZWdvcmljYWxfY3VycmVudFtzdXNjZXB0aWJsZV9pZHhdIDwtICJzZW5zaXRpdmUiCiNzdXNfY2F0ZWdvcmljYWxfY3VycmVudCA8LSBhcy5mYWN0b3Ioc3VzX2NhdGVnb3JpY2FsX2N1cnJlbnQpCnJlc2lzdF9pZHggPC0gc3RhcnRpbmdfY3VycmVudCA8PSBtYXhfcmVzaXN0X2N1cnJlbnQKc2Vuc2l0aXZlX2lkeCA8LSAhcmVzaXN0X2lkeApzdXNfY2F0ZWdvcmljYWxfY3VycmVudFtyZXNpc3RfaWR4XSA8LSAicmVzaXN0YW50IgpzdXNfY2F0ZWdvcmljYWxfY3VycmVudFtzZW5zaXRpdmVfaWR4XSA8LSAic2Vuc2l0aXZlIgpzdXNfY2F0ZWdvcmljYWxfY3VycmVudCA8LSBhcy5mYWN0b3Ioc3VzX2NhdGVnb3JpY2FsX2N1cnJlbnQpCgpjb2xEYXRhKGxwX3NlKVtbInN1c19jYXRlZ29yeV9jdXJyZW50Il1dIDwtIHN1c19jYXRlZ29yaWNhbF9jdXJyZW50CmNvbERhdGEobHBfc2UpW1sic3VzY2VwdGliaWxpdHkiXV0gPC0gc3VzX2NhdGVnb3JpY2FsX2N1cnJlbnQKdGFibGUoc3VzX2NhdGVnb3JpY2FsX2N1cnJlbnQpCgpscF9zYW5rZXkgPC0gcGxvdF9tZXRhX3NhbmtleSgKICBscF9zZSwgZmFjdG9ycyA9IGMoInp5bW9kZW1lY2F0ZWdvcmljYWwiLCAiY2xpbmljYWxjYXRlZ29yaWNhbCIsICJzdXNjZXB0aWJpbGl0eSIpLAogIGRyaWxsX2Rvd24gPSBUUlVFLCBjb2xvcl9jaG9pY2VzID0gY29sb3JfY2hvaWNlcykKbHBfc2Fua2V5CmBgYAoKSW4gbWFueSBxdWVyaWVzLCB3ZSB3aWxsIHNlZWsgdG8gY29tcGFyZSBvbmx5IHRoZSB0d28gcHJpbWFyeSBzdHJhaW5zLAp6eW1vZGVtZSAyLjIgYW5kIDIuMy4gIFRoZSBmb2xsb3dpbmcgYmxvY2sgd2lsbCBleHRyYWN0IG9ubHkgdGhvc2UKc2FtcGxlcy4KCk5vdGU6ICpJTVBPUlRBTlQqIE1hcmlhIEFkZWxhaWRhIHByZWZlcnMgbm90IHRvIHVzZSBscF90d29fc3RyYWlucy4gIFdlIHNob3VsZCBub3QgYXQgdGhpcyB0aW1lCnVzZSB0aGUgbWVyZ2VkIDIuMS8yLjIgYW5kIDIuNC8yLjMgY2F0ZWdvcmllcy4KCmBgYHtyfQpscF9zdHJhaW4gPC0gbHBfc2UgJT4lCiAgc2V0X2JhdGNoZXMoZmFjdCA9IHN1c19jYXRlZ29yaWNhbF9jdXJyZW50KSAlPiUKICBzZXRfY29sb3JzKGNvbG9yX2Nob2ljZXNbWyJzdHJhaW4iXV0pCnRhYmxlKGNvbERhdGEobHBfc3RyYWluKVtbImNvbmRpdGlvbiJdXSkKc2F2ZShsaXN0ID0gImxwX3N0cmFpbiIsIGZpbGUgPSBnbHVlKCJyZGEvdG1yYzJfbHBfc3RyYWluLXZ7dmVyfS5yZGEiKSkKZGF0YV9zdHJ1Y3R1cmVzIDwtIGMoZGF0YV9zdHJ1Y3R1cmVzLCAibHBfc3RyYWluIikKCmxwX3R3b19zdHJhaW5zIDwtIG1lcmdlZF96eW1vCnNhdmUobGlzdCA9ICJscF90d29fc3RyYWlucyIsCiAgICAgZmlsZSA9IGdsdWUoInJkYS90bXJjMl9scF90d29fc3RyYWlucy12e3Zlcn0ucmRhIikpCmRhdGFfc3RydWN0dXJlcyA8LSBjKGRhdGFfc3RydWN0dXJlcywgImxwX3R3b19zdHJhaW5zIikKYGBgCgojIyBDbGluaWNhbCBvdXRjb21lCgpDbGluaWNhbCBvdXRjb21lIGlzIGJ5IGZhciB0aGUgbW9zdCBwcm9ibGVtYXRpYyBjb21wYXJpc29uIGluIHRoaXMKZGF0YSwgYnV0IGhlcmUgaXMgdGhlIHJlY2F0ZWdvcml6YXRpb24gb2YgdGhlIGRhdGEgdXNpbmcgaXQ6CgpgYGB7cn0KbHBfY2YgPC0gc2V0X2NvbmRpdGlvbnMobHBfc2UsIGZhY3QgPSAiY2xpbmljYWxjYXRlZ29yaWNhbCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3JzID0gY29sb3JfY2hvaWNlc1tbImNmIl1dKSAlPiUKICBzZXRfYmF0Y2hlcyhmYWN0ID0gc3VzX2NhdGVnb3JpY2FsX2N1cnJlbnQpCnRhYmxlKGNvbERhdGEobHBfY2YpW1siY29uZGl0aW9uIl1dKQpkYXRhX3N0cnVjdHVyZXMgPC0gYyhkYXRhX3N0cnVjdHVyZXMsICJscF9jZiIpCnNhdmUobGlzdCA9ICJscF9jZiIsIGZpbGUgPSBnbHVlKCJyZGEvdG1yYzJfbHBfY2Ytdnt2ZXJ9LnJkYSIpKQoKbHBfY2Zfa25vd24gPC0gc3Vic2V0X3NlKGxwX2NmLCBzdWJzZXQgPSAiY29uZGl0aW9uIT0ndW5rbm93biciKQpkYXRhX3N0cnVjdHVyZXMgPC0gYyhkYXRhX3N0cnVjdHVyZXMsICJscF9jZl9rbm93biIpCnNhdmUobGlzdCA9ICJscF9jZl9rbm93biIsIGZpbGUgPSBnbHVlKCJyZGEvdG1yYzJfbHBfY2Zfa25vd24tdnt2ZXJ9LnJkYSIpKQpkYXRhX3N0cnVjdHVyZXMgPC0gYyhkYXRhX3N0cnVjdHVyZXMsICJscF9jZl9rbm93biIpCnNhdmUobGlzdCA9ICJscF9jZl9rbm93biIsIGZpbGUgPSBnbHVlKCJyZGEvdG1yYzJfbHBfY2Zfa25vd24tdnt2ZXJ9LnJkYSIpKQpgYGAKCiMjIENyZWF0ZSBhIGhpc3RvcmljYWwgc3VzY2VwdGliaWxpdHkgZGF0YXNldAoKVXNlIHRoZSBmYWN0b3JpemVkIHZlcnNpb24gb2Ygc3VzY2VwdGliaWxpdHkgdG8gY2F0ZWdvcml6ZSB0aGUgc2FtcGxlcwpieSB0aGUgaGlzdG9yaWNhbCBkYXRhLgoKYGBge3J9CmxwX3N1c2NlcHRpYmlsaXR5X2hpc3RvcmljYWwgPC0gc2V0X2NvbmRpdGlvbnMoCiAgbHBfc2UsIGZhY3QgPSAic3VzX2NhdGVnb3J5X2hpc3RvcmljYWwiLCBjb2xvcnMgPSBjb2xvcl9jaG9pY2VzW1sic3VzY2VwdGliaWxpdHkiXV0pICU+JQogIHNldF9iYXRjaGVzKGZhY3QgPSAiY2xpbmljYWxjYXRlZ29yaWNhbCIpCnNhdmUobGlzdCA9ICJscF9zdXNjZXB0aWJpbGl0eV9oaXN0b3JpY2FsIiwKICAgICBmaWxlID0gZ2x1ZSgicmRhL3RtcmMyX2xwX3N1c2NlcHRpYmlsaXR5X2hpc3RvcmljYWwtdnt2ZXJ9LnJkYSIpKQpkYXRhX3N0cnVjdHVyZXMgPC0gYyhkYXRhX3N0cnVjdHVyZXMsICJscF9zdXNjZXB0aWJpbGl0eV9oaXN0b3JpY2FsIikKYGBgCgojIyBDcmVhdGUgYSBjdXJyZW50IHN1c2NlcHRpYmlsaXR5IGRhdGFzZXQKClVzZSB0aGUgZmFjdG9yaXplZCB2ZXJzaW9uIG9mIHN1c2NlcHRpYmlsaXR5IHRvIGNhdGVnb3JpemUgdGhlIHNhbXBsZXMKYnkgdGhlIGhpc3RvcmljYWwgZGF0YS4KClRoaXMgd2lsbCBsaWtlbHkgYmUgb3VyIGNhbm9uaWNhbCBzdXNjZXB0aWJpbGl0eSBkYXRhc2V0LCBzbyBJIHdpbGwKcmVtb3ZlIHRoZSBzdWZmaXggYW5kIGp1c3QgY2FsbCBpdCAnbHBfc3VzY2VwdGliaWxpdHknLgoKYGBge3J9CmxwX3N1c2NlcHRpYmlsaXR5IDwtIHNldF9jb25kaXRpb25zKAogIGxwX3NlLCBmYWN0ID0gInN1c19jYXRlZ29yeV9jdXJyZW50IiwgY29sb3JzID0gY29sb3JfY2hvaWNlc1tbInN1c2NlcHRpYmlsaXR5Il1dKSAlPiUKICBzZXRfYmF0Y2hlcyhmYWN0ID0gImNsaW5pY2FsY2F0ZWdvcmljYWwiKQpzYXZlKGxpc3QgPSAibHBfc3VzY2VwdGliaWxpdHkiLAogICAgIGZpbGUgPSBnbHVlKCJyZGEvdG1yYzJfbHBfc3VzY2VwdGliaWxpdHktdnt2ZXJ9LnJkYSIpKQpkYXRhX3N0cnVjdHVyZXMgPC0gYyhkYXRhX3N0cnVjdHVyZXMsICJscF9zdXNjZXB0aWJpbGl0eSIpCmBgYAoKIyMgUHVsbCBvdXQgb25seSB0aGUgc2FtcGxlcyB3aXRoIHR3byB6eW1vZGVtZXMKCkkgdGhpbmsgdGhpcyBpcyByZWR1bmRhbnQgd2l0aCBhIHByZXZpb3VzIGJsb2NrLCBidXQgSSBhbSBsZWF2aW5nIGl0CnVudGlsIEkgYW0gY2VydGFpbiB0aGF0IGl0IGlzIG5vdCByZXF1aXJlZCBpbiBhIGZvbGxvd2luZyBkb2N1bWVudC4KCk5vdGU6ICpJTVBPUlRBTlQqIFRoaXMgaXMgdGhlIHNldCBNYXJpYSBBZGVsaWFkYSBwcmVmZXJzIHRvIHVzZS4KCmBgYHtyfQpscF96eW1vIDwtIHN1YnNldF9zZShscF9zZSwgc3Vic2V0ID0gImNvbmRpdGlvbj09J3oyLjInfGNvbmRpdGlvbj09J3oyLjMnIikKZGF0YV9zdHJ1Y3R1cmVzIDwtIGMoZGF0YV9zdHJ1Y3R1cmVzLCAibHBfenltbyIpCnNhdmUobGlzdCA9ICJscF96eW1vIiwgZmlsZSA9IGdsdWUoInJkYS90bXJjMl9scF96eW1vLXZ7dmVyfS5yZGEiKSkKYGBgCgojIFZhcmlhbnQgZGF0YSB1c2luZyBwYXJhc2l0ZSBSTkFTZXEgcmVhZHMKClRoZSBmb2xsb3dpbmcgc2VjdGlvbiB3aWxsIGNyZWF0ZSBzb21lIGluaXRpYWwgZGF0YSBzdHJ1Y3R1cmVzIG9mIHRoZQpvYnNlcnZlZCB2YXJpYW50cyBpbiB0aGUgcGFyYXNpdGUgc2FtcGxlcy4gIFRoaXMgd2lsbCBpbmNsdWRlIHNvbWUgb2YKb3VyIDIwMTYgc2FtcGxlcyBmb3Igc29tZSBjbGFzc2lmaWNhdGlvbiBxdWVyaWVzLgoKIyMgVGhlIDIwMTYgdmFyaWFudCBkYXRhCgpJIGNoYW5nZWQgYW5kIGltcHJvdmVkIHRoZSBtYXBwaW5nIGFuZCB2YXJpYW50IGRldGVjdGlvbiBtZXRob2RzIGZyb20Kd2hhdCB3ZSB1c2VkIGZvciB0aGUgMjAxNiBkYXRhLiAgU28gc29tZSBzbWFsbCBjaGFuZ2VzIHdpbGwgYmUKcmVxdWlyZWQgdG8gbWVyZ2UgdGhlbS4KCmBgYHtyIG9sZG5ld192YXJpYW50cywgZXZhbD1GQUxTRX0KbHBfcHJldmlvdXMgPC0gY3JlYXRlX3NlKCJzYW1wbGVfc2hlZXRzL3RtcmMyX3NhbXBsZXNfMjAxOTEyMDMueGxzeCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGVfY29sdW1uID0gInRvcGhhdDJmaWxlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgc2F2ZWZpbGUgPSBnbHVlKCJyZGEvbHBfcHJldmlvdXMtdnt2ZXJ9LnJkYSIpKQp0dCA8LSBscF9wcmV2aW91cyRleHByZXNzaW9uc2V0CnJvd25hbWVzKHR0KSA8LSBnc3ViKHBhdHRlcm4gPSAiXmV4b25fIiwgcmVwbGFjZW1lbnQgPSAiIiwgeCA9IHJvd25hbWVzKHR0KSkKcm93bmFtZXModHQpIDwtIGdzdWIocGF0dGVybiA9ICJcXC4xJCIsIHJlcGxhY2VtZW50ID0gIiIsIHggPSByb3duYW1lcyh0dCkpCnJvd25hbWVzKHR0KSA8LSBnc3ViKHBhdHRlcm4gPSAiXFwtMSQiLCByZXBsYWNlbWVudCA9ICIiLCB4ID0gcm93bmFtZXModHQpKQpscF9wcmV2aW91cyRleHByZXNzaW9uc2V0IDwtIHR0CnJtKHR0KQpkYXRhX3N0cnVjdHVyZXMgPC0gYyhkYXRhX3N0cnVjdHVyZXMsICJscF9wcmV2aW91cyIpCmBgYAoKIyMgQ3JlYXRlIHRoZSBTTlAgZXhwcmVzc2lvbnNldAoKVGhlIGNvdW50X3NlX3NucHMoKSBmdW5jdGlvbiB1c2VzIG91ciBleHByZXNzaW9uc2V0IGRhdGEgYW5kIGEKbWV0YWRhdGEgY29sdW1uIGluIG9yZGVyIHRvIGV4dHJhY3QgdGhlIG1waWxldXAgb3IgZnJlZWJheWVzLWJhc2VkCnZhcmlhbnQgY2FsbHMgYW5kIGNyZWF0ZSBtYXRyaWNlcyBvZiB0aGUgbGlrZWxpaG9vZCB0aGF0IGVhY2gKcG9zaXRpb24tcGVyLXNhbXBsZSBpcyBpbiBmYWN0IGEgdmFyaWFudC4KClRoZXJlIGlzIGFuIGltcG9ydGFudCBjYXZlYXQgaGVyZSB3aGljaCBjaGFuZ2VkIG9uIDIwMjMwMTogIEkgd2FzCmludGVycHJldGluZyB1c2luZyB0aGUgUEFJUkVEIHRhZywgd2hpY2ggaXMgb25seSB1c2VkIGZvciwKdW5zdXJwcmlzaW5nbHksIHBhaXJlZC1lbmQgc2FtcGxlcy4gIEEgY291cGxlIHNhbXBsZXMgYXJlIG5vdCBwYWlyZWQKYW5kIHNvIHdlcmUgZmFpbGluZyBzaWxlbnRseS4gIFRoZSBRQSB0YWcgbG9va3MgbGlrZSBpdCBpcyBtb3JlCmFwcHJvcHJpYXRlIGFuZCBzaG91bGQgd29yayBhY3Jvc3MgYm90aCB0eXBlcy4gIE9uZSB3YXkgdG8gZmluZCBvdXQsIEkKYW0gc2V0dGluZyBpdCBoZXJlIGFuZCB3aWxsIGxvb2sgdG8gc2VlIGlmIHRoZSByZXN1bHRzIG1ha2UgbW9yZSBzZW5zZQpmb3IgbXkgdGVzdCBzYW1wbGVzIChUTVJDMjAwMSwgVE1SQzIwMDUsIFRNUkMyMDA3KS4KCmBgYHtyfQojIyBUaGUgbmV4dCBsaW5lIGRyb3BzIHRoZSBzYW1wbGVzIHdoaWNoIGFyZSBtaXNzaW5nIHRoZSBTTlAgcGlwZWxpbmUuCmxwX3NucCA8LSBzdWJzZXRfc2UobHBfc2UsIHN1YnNldCA9ICIhaXMubmEoY29sRGF0YShscF9zZSlbWydmcmVlYmF5ZXNzdW1tYXJ5J11dKSIpCgpscF9zbnBfc3VmZmljaWVudCA8LSBzdWJzZXRfc2UobHBfc25wLCBzdWJzZXQgPSAicm93bmFtZXMhPSdUTVJDMjAwODInIikKbHBfc25wX29ubHkyMl8yM19yZWYgPC0gc3Vic2V0X3NlKGxwX3NucCwgc3Vic2V0ID0gInp5bW9kZW1lcmVmZXJlbmNlPT0nejIuMid8enltb2RlbWVyZWZlcmVuY2U9PSd6Mi4zJyIpICU+JQogIHN1YnNldF9zZShzdWJzZXQgPSAicm93bmFtZXMhPSdUTVJDMjAwODInIikKbHBfc25wXzIyXzIzX21sIDwtIHN1YnNldF9zZShscF9zbnAsIHN1YnNldCA9ICJrbm52MmNsYXNzaWZpY2F0aW9uPT0nejIyJ3xrbm52MmNsYXNzaWZpY2F0aW9uPT0nejIzJyIpICU+JQogIHN1YnNldF9zZShzdWJzZXQgPSAicm93bmFtZXMhPSdUTVJDMjAwODInIikKCm5ld19zbnBzX3N1ZmZpY2llbnQgPC0gY291bnRfc25wcyhscF9zbnBfc3VmZmljaWVudCwgYW5ub3RfY29sdW1uID0gImZyZWViYXllc3N1bW1hcnkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc25wX2NvbHVtbiA9ICJRQSIsIHJlYWRlciA9ICJyZWFkciIpCm5ld19zbnBzX29ubHkyMl8yM19yZWZfc3VmIDwtIGNvdW50X3NucHMobHBfc25wX29ubHkyMl8yM19yZWYsIGFubm90X2NvbHVtbiA9ICJmcmVlYmF5ZXNzdW1tYXJ5IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbnBfY29sdW1uID0gIlFBIiwgcmVhZGVyID0gInJlYWRyIikKbmV3X3NucHNfMjJfMjNfbWxfc3VmIDwtIGNvdW50X3NucHMobHBfc25wXzIyXzIzX21sLCBhbm5vdF9jb2x1bW4gPSAiZnJlZWJheWVzc3VtbWFyeSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNucF9jb2x1bW4gPSAiUUEiLCByZWFkZXIgPSAicmVhZHIiKQoKIyMgTGV0cyBzZWUgaWYgd2UgZ2V0IG51bWJlcnMgd2hpY2ggbWFrZSBzZW5zZS4Kc3VtbWFyeShhc3NheShuZXdfc25wc19zdWZmaWNpZW50KVtbIlRNUkMyMDAwMSJdXSkgICMjIE15IHdlaXJkbyBzYW1wbGUKc3VtbWFyeShhc3NheShuZXdfc25wc19zdWZmaWNpZW50KVtbIlRNUkMyMDA3MiJdXSkgICMjIEFub3RoZXIgc2FtcGxlIGNob3NlbiBhdCByYW5kb20Kc3VtbWFyeShhc3NheShuZXdfc25wc19zdWZmaWNpZW50KVtbIlRNUkMyMDAyMSJdXSkgICMjIEFub3RoZXIgc2FtcGxlIGNob3NlbiBhdCByYW5kb20KIyMgTm93IHRoYXQgd2UgYXJlIHJlYXNvbmFibHkgY29uZmlkZW50IHRoYXQgdGhpbmdzIG1ha2UgbW9yZSBzZW5zZSwgbGV0cyBzYXZlIGFuZCBtb3ZlIG9uLi4uCmRhdGFfc3RydWN0dXJlcyA8LSBjKGRhdGFfc3RydWN0dXJlcywgIm5ld19zbnBzX3N1ZmZpY2llbnQiLCAibHBfc25wIikKCiMjIE1vc3Qgb2YgdGhlIHRpbWUgSSBqdXN0IHJ1biBub3JtYWxpemUoKSBhbmQgYXNzdW1lIGl0IHdpbGwgZGlzcGF0Y2ggdG8gbm9ybWFsaXplX3NlKCkKc3VmZmljaWVudF9ub3JtIDwtIG5vcm1hbGl6ZShuZXdfc25wc19zdWZmaWNpZW50LCB0cmFuc2Zvcm0gPSAibG9nMiIpCnBsb3RfYm94cGxvdChzdWZmaWNpZW50X25vcm0pCmBgYAoKTm93IGxldCB1cyBwdWxsIGluIHRoZSAyMDE2IGRhdGEuCgpgYGB7ciBtZXJnZV9uZXdfb2xkLCBldmFsPUZBTFNFfQpvbGRfc25wcyA8LSBjb3VudF9zbnBzKGxwX3ByZXZpb3VzLCBhbm5vdF9jb2x1bW4gPSAiYmNmdGFibGUiLCBzbnBfY29sdW1uID0gMikKZGF0YV9zdHJ1Y3R1cmVzIDwtIGMoZGF0YV9zdHJ1Y3R1cmVzLCAib2xkX3NucHMiKQoKc2F2ZShsaXN0ID0gImxwX3NucCIsIGZpbGUgPSBnbHVlKCJyZGEvbHBfc25wLXZ7dmVyfS5yZGEiKSkKZGF0YV9zdHJ1Y3R1cmVzIDwtIGMoZGF0YV9zdHJ1Y3R1cmVzLCAibHBfc25wIikKc2F2ZShsaXN0ID0gIm5ld19zbnBzIiwgZmlsZSA9IGdsdWUoInJkYS9uZXdfc25wcy12e3Zlcn0ucmRhIikpCmRhdGFfc3RydWN0dXJlcyA8LSBjKGRhdGFfc3RydWN0dXJlcywgIm5ld19zbnBzIikKc2F2ZShsaXN0ID0gIm9sZF9zbnBzIiwgZmlsZSA9IGdsdWUoInJkYS9vbGRfc25wcy12e3Zlcn0ucmRhIikpCmRhdGFfc3RydWN0dXJlcyA8LSBjKGRhdGFfc3RydWN0dXJlcywgIm9sZF9zbnBzIikKCm5vbnplcm9fc25wcyA8LSBhc3NheShuZXdfc25wcykgIT0gMApjb2xTdW1zKG5vbnplcm9fc25wcykKYGBgCgojIyBDb21iaW5lIHRoZSBwcmV2aW91cyBhbmQgY3VycmVudCBkYXRhCgpBcyBmYXIgYXMgSSBjYW4gdGVsbCwgZnJlZWJheWVzIGFuZCBtcGlsZXVwIGFyZSByZWFzb25hYmx5IHNpbWlsYXIgaW4KdGhlaXIgc2Vuc2l0aXZpdHkvc3BlY2lmaWNpdHk7IHNvIGNvbWJpbmluZyB0aGUgdHdvIGRhdGFzZXRzIGxpa2UgdGhpcwppcyBleHBlY3RlZCB0byB3b3JrIHdpdGggbWluaW1hbCBwcm9ibGVtcy4gIFRoZSBtb3N0IGxpa2VseSBwcm9ibGVtIGlzCnRoYXQgbXkgbXBpbGV1cC1iYXNlZCBwaXBlbGluZSBpcyB1bmFibGUgdG8gaGFuZGxlIGluZGVscy4KCmBgYHtyIGNvbWJpbmVfb2xkX3NucHMsIGV2YWw9RkFMU0V9CiMjIE15IG9sZF9zbnBzIGlzIHVzaW5nIGFuIG9sZGVyIGFubm90YXRpb24gaW5jb3JyZWN0bHksIHNvIGZpeCBpdCBoZXJlOgojYW5ub3RhdGlvbihvbGRfc25wcykgPC0gYW5ub3RhdGlvbihuZXdfc25wcykKYm90aF9zbnBzIDwtIGNvbWJpbmVfc2VzKG5ld19zbnBzLCBvbGRfc25wcykKc2F2ZShsaXN0ID0gImJvdGhfc25wcyIsCiAgICAgZmlsZSA9IGdsdWUoInJkYS9ib3RoX3NucHMtdnt2ZXJ9LnJkYSIpKQpkYXRhX3N0cnVjdHVyZXMgPC0gYyhkYXRhX3N0cnVjdHVyZXMsICJib3RoX3NucHMiKQpgYGAKCiMgU3ViY2xhZGUgbWFudWFsIGludGVycHJldGF0aW9uCgpJIGFtIHRha2luZyBhIGhlYXRtYXAgZnJvbSBvdXIgdmFyaWFudCBkYXRhIGFuZCBtYW51YWxseSBpZGVudGlmeWluZyBzYW1wbGUgZ3JvdXBzLgoKKiBBOiBUTVJDMjAwMjUsIFRNUkMyMDAyNywgVE1SQzIwMDI4CiogQjogaHBnbDA2NDEsIGhwZ2wwMjQ3LCBocGdsMDYzMSwgaHBnbDA2NTgsIGNsb3NlIHRvIEEKKiBDOiBUTVJDMjAwMDgsIFRNUkMyMDAwNywgVE1SQzIwMDAxLCBUTVJDMjAwMDUsIGhwZ2wwMzE4LCBUTVJDMjAwMTIKKiBEOiBocGdsMDY0MywgaHBnbDAzMTYsIGhwZ2wwMzIwLCBocGdsMDY0MSwgY2xvc2UgdG8gQwoqIEU6IFRNUkMyMDAzMiwgVE1SQzIwMDYxCiogRjogVE1SQzIwMDQwLCBUTVJDMjAwMzYsIGhwZ2wwMjQ1LCBUTVJDMjAxMDMsIFRNUkMyMDA5MywgVE1SQzIwMDQ1LAogICAgIFRNUkMyMDA0MSwgVE1SQzIwMDcyLCBUTVJDMjAwNDYsIFRNUkMyMDA1NywgVE1SQzIwMDk3LCBUTVJDMjAwODQsCiAgICAgY2xvc2UgdG8gRQoqIEc6IGhwZ2wwNjMyLCBocGdsMDY1MiwgaHBnbDAyNDgsIGhwZ2wwNjU5CiogSDogaHBnbDA2NTQsIGhwZ2wwNjM0LCBocGdsMDI0MywgaHBnbDAyNDMsIGNsb3Nlc3QgdG8gRwoqIEk6IGhwZ2wwMjQyLCBocGdsMDMyMiwgaHBnbDA2MzYsIGhwZ2wwNjYzLCBocGdsMDYzOCwgY2xvc2UgdG8gSAoqIEo6IFRNUkMyMDAxNywgVE1SQzIwMDMzLCBUTVJDMjAwNTMsIFRNUkMyMDA2MywgVE1SQzIwMDU2LCBUTVJDMjAwNzQsCiAgICAgVE1SQzIwMDU1LCBUTVJDMjAwMjIsIFRNUkMyMDAyNiwgVE1SQzIwMDgzLCBUTVJDMjAwNzcsIFRNUkMyMDA2MAoqIEs6IFRNUkMyMDA1MCwgVE1SQzIwMDQyLCBUTVJDMjAwNzgsIFRNUkMyMDA0OSwgVE1SQzIwMDY5LCBUTVJDMjAwNDQsCiAgICAgY2xvc2UgdG8gSgoqIEw6IFRNUkMyMDA3NiwgVE1SQzIwMDI0LCBUTVJDMjAwOQoqIE06IFRNUkMyMDAxOSwgVE1SQzIwMDIwLCBUTVJDMjAwMzEsIFRNUkMyMDAxNCwgVE1SQzIwMDExLCBjbG9zZSB0byBMCiogTjogVE1SQzIwMDk2LCBUTVJDMjAwODEsIFRNUkMyMDExMCwgVE1SQzIwMDkyLCBUTVJDMjAwODgsIFRNUkMyMDEwMSwKICAgICBUTVJDMjAxMDYsIFRNUkMyMDA5MSwgVE1SQzIwMTA5LCBUTVJDMjAwODcsIFRNUkMyMDA4NiwgY2xvc2Vpc2gKICAgICB0byBNCiogTzogVE1SQzIwMDk1LCBUTVJDMjAwMTYsIFRNUkMyMDAxOCwgcXVpdGUgZmFyIGZyb20gZXZlcnlvbmUKKiBQOiBUTVJDMjAwODIsIFRNUkMyMDA3NSwgcHJldHR5IHNlcGFyYXRlIHRvbwoqIFE6IGhwZ2wwMjQ2LCBocGdsMDY1MywgaHBnbDA2MzMsIGhwZ2wwMjQ0LCBocGdsMDYzNSwgaHBnbDA2NTUsCiAgICAgaHBnbDA2MzksIGhwZ2wwNjYyCiogUjogVE1SQzIwMDU5LCBUTVJDMjAwODksIFRNUkMyMDAyMSwgVE1SQzIwMDQ4LCBUTVJDMjAwNjcKKiBTOiBUTVJDMjAwMTMsIFRNUkMyMDAxMCwgVE1SQzIwMDM3LCBUTVJDMjAwNjYsIFRNUkMyMDA2MiwgVE1SQzIwMDM4LAogICAgIGNsb3NlIHRvIFIKKiBUOiBUTVJDMjAwMTUsIFRNUkMyMDEwOCwgVE1SQzIwMDk5LCBUTVJDMjAxMDIsIFRNUkMyMDA4NSwgVE1SQzIwMDkwLAogICAgIFRNUkMyMDEwNCwgVE1SQzIwMDk4LCBUTVJDMjAxMDAsIFRNUkMyMDEwNwoqIFU6IFRNUkMyMDA0NywgVE1SQzIwMDY4LCBUTVJDMjAwODAsIFRNUkMyMDEwNSwgVE1SQzIwMDk0LCBUTVJDMjAwNjUsCiAgICAgVE1SQzIwMDcxLCBUTVJDMjAwNjQsIFRNUkMyMDA0MywgVE1SQzIwMDcwLCBUTVJDMjAwNjIsIFRNUkMyMDA1MSwKICAgICBUTVJDMjAwNzksIFRNUkMyMDA3MywgVE1SQzIwMDU4LCBUTVJDMjAwNTQKCiMgTWFjcm9waGFnZSBkYXRhCgpBbGwgb2YgdGhlIGFib3ZlIGZvY3VzZWQgZW50aXJlIG9uIHRoZSBwYXJhc2l0ZSBzYW1wbGVzLCBub3cgbGV0IHVzCnB1bGwgdXAgdGhlIG1hY3JvcGhhZ2UgaW5mZWN0ZWQgc2FtcGxlcy4gIFRoaXMgd2lsbCBjb21wcmlzZSB0d28KZGF0YXNldHMsIG9uZSBvZiB0aGUgaHVtYW4gYW5kIG9uZSBvZiB0aGUgcGFyYXNpdGUuCgojIyBNYWNyb3BoYWdlIGhvc3QgZGF0YQoKVGhlIG1ldGFkYXRhIGZvciB0aGUgbWFjcm9waGFnZSBzYW1wbGVzIGNvbnRhaW5zIGEgY291cGxlIG9mIGNvbHVtbnMKZm9yIG1hcHBlZCBodW1hbiBhbmQgcGFyYXNpdGUgcmVhZHMuICBXZSB3aWxsIHRoZXJlZm9yZSB1c2UgdGhlbQpzZXBhcmF0ZWx5IHRvIGNyZWF0ZSB0d28gZXhwcmVzc2lvbnNldHMsIG9uZSBmb3IgZWFjaCBzcGVjaWVzLgoKYGBge3J9CmhzX2Fubm90IDwtIGxvYWRfYmlvbWFydF9hbm5vdGF0aW9ucyh5ZWFyID0gIjIwMjAiLCBtb250aCA9IDQpCmhzX2Fubm90IDwtIGhzX2Fubm90W1siYW5ub3RhdGlvbiJdXQpoc19hbm5vdFtbInRyYW5zY3JpcHQiXV0gPC0gcGFzdGUwKHJvd25hbWVzKGhzX2Fubm90KSwgIi4iLCBoc19hbm5vdFtbInRyYW5zY3JpcHRfdmVyc2lvbiJdXSkKcm93bmFtZXMoaHNfYW5ub3QpIDwtIG1ha2UubmFtZXMoaHNfYW5ub3RbWyJlbnNlbWJsX2dlbmVfaWQiXV0sIHVuaXF1ZSA9IFRSVUUpCnJvd25hbWVzKGhzX2Fubm90KSA8LSBwYXN0ZTAoImdlbmU6Iiwgcm93bmFtZXMoaHNfYW5ub3QpKQp0eF9nZW5lX21hcCA8LSBoc19hbm5vdFssIGMoInRyYW5zY3JpcHQiLCAiZW5zZW1ibF9nZW5lX2lkIildCgpzYW5pdGl6ZV9jb2x1bW5zIDwtIGMoImRydWciLCAibWFjcm9waGFnZXRyZWF0bWVudCIsICJtYWNyb3BoYWdlenltb2RlbWUiKQptYWNyX2Fubm90IDwtIGhzX2Fubm90CnJvd25hbWVzKG1hY3JfYW5ub3QpIDwtIGdzdWIoeCA9IHJvd25hbWVzKG1hY3JfYW5ub3QpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAiXmdlbmU6IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXBsYWNlbWVudCA9ICIiKQpoc19tYWNyb3BoYWdlIDwtIGNyZWF0ZV9zZShtYWNyb3BoYWdlX3NoZWV0LCBnZW5lX2luZm8gPSBtYWNyX2Fubm90LAogICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlX2NvbHVtbiA9ICJoZzM4MTAwaGlzYXRmaWxlIikgJT4lCiAgc2V0X2NvbmRpdGlvbnMoZmFjdCA9ICJtYWNyb3BoYWdldHJlYXRtZW50IikgJT4lCiAgc2V0X2JhdGNoZXMoZmFjdCA9ICJtYWNyb3BoYWdlenltb2RlbWUiKSAlPiUKICBzYW5pdGl6ZV9tZXRhZGF0YShjb2x1bW5zID0gc2FuaXRpemVfY29sdW1ucykgJT4lCiAgc3Vic2V0X3NlKG5vbnplcm8gPSAxMjAwMCkKZml4ZWRfZ2VuZW5hbWVzIDwtIGdzdWIoeCA9IHJvd25hbWVzKGFzc2F5KGhzX21hY3JvcGhhZ2UpKSwgcGF0dGVybiA9ICJeZ2VuZToiLAogICAgICAgICAgICAgICAgICAgICAgICByZXBsYWNlbWVudCA9ICIiKQpoc19tYWNyb3BoYWdlIDwtIHNldF9nZW5lbmFtZXMoaHNfbWFjcm9waGFnZSwgaWRzID0gZml4ZWRfZ2VuZW5hbWVzKQp0YWJsZShjb2xEYXRhKGhzX21hY3JvcGhhZ2UpJGNvbmRpdGlvbikKCiMjIFRoZSBmb2xsb3dpbmcgMyBsaW5lcyB3ZXJlIGNvcHkvcGFzdGVkIHRvIGRhdGFzdHJ1Y3R1cmVzIGFuZCBzaG91bGQgYmUgcmVtb3ZlZCBzb29uLgpub3N0cmFpbiA8LSBpcy5uYShjb2xEYXRhKGhzX21hY3JvcGhhZ2UpW1sic3RyYWluaWQiXV0pCmNvbERhdGEoaHNfbWFjcm9waGFnZSlbbm9zdHJhaW4sICJzdHJhaW5pZCJdIDwtICJub25lIgoKY29sRGF0YShoc19tYWNyb3BoYWdlKVtbInN0cmFpbl96eW1vIl1dIDwtIHBhc3RlMCgicyIsIGNvbERhdGEoaHNfbWFjcm9waGFnZSlbWyJzdHJhaW5pZCJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIl8iLCBjb2xEYXRhKGhzX21hY3JvcGhhZ2UpW1sibWFjcm9waGFnZXp5bW9kZW1lIl1dKQp1bmluZmVjdGVkIDwtIGNvbERhdGEoaHNfbWFjcm9waGFnZSlbWyJzdHJhaW5fenltbyJdXSA9PSAic25vbmVfbm9uZSIKY29sRGF0YShoc19tYWNyb3BoYWdlKVt1bmluZmVjdGVkLCAic3RyYWluX3p5bW8iXSA8LSAidW5pbmZlY3RlZCIKCmRhdGFfc3RydWN0dXJlcyA8LSBjKGRhdGFfc3RydWN0dXJlcywgImhzX21hY3JvcGhhZ2UiKQpgYGAKCkZpbmFsbHksIHNwbGl0IG9mZiB0aGUgVTkzNyBzYW1wbGVzLgoKYGBge3J9CmhzX3U5MzcgPC0gc3Vic2V0X3NlKGhzX21hY3JvcGhhZ2UsIHN1YnNldCA9ICJ0eXBlb2ZjZWxscyE9J01hY3JvcGhhZ2VzJyIpCmRhdGFfc3RydWN0dXJlcyA8LSBjKGRhdGFfc3RydWN0dXJlcywgImhzX3U5MzciKQpgYGAKCiMjIE1hY3JvcGhhZ2UgcGFyYXNpdGUgZGF0YQoKSW4gdGhlIHByZXZpb3VzIGJsb2NrLCB3ZSB1c2VkIGEgbmV3IGludm9jYXRpb24gb2YgZW5zZW1ibC1kZXJpdmVkCmFubm90YXRpb24gZGF0YSwgdGhpcyB0aW1lIHdlIGNhbiBqdXN0IHVzZSBvdXIgZXhpc3RpbmcgcGFyYXNpdGUgZ2VuZQphbm5vdGF0aW9ucy4KCmBgYHtyfQpscF9tYWNyb3BoYWdlIDwtIGNyZWF0ZV9zZShtYWNyb3BoYWdlX3NoZWV0LCBmaWxlX2NvbHVtbiA9ICJscGFuYW1lbnNpc3YzNmhpc2F0ZmlsZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlbmVfaW5mbyA9IGFsbF9scF9hbm5vdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgc2F2ZWZpbGUgPSBnbHVlKCJyZGEvbHBfbWFjcm9waGFnZS12e3Zlcn0ucmRhIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGFubm90YXRpb24gPSAib3JnLkxwYW5hbWVuc2lzLk1IT01DT0w4MUwxMy52NDYuZWcuZGIiKSAlPiUKICBzZXRfY29uZGl0aW9ucyhmYWN0ID0gIm1hY3JvcGhhZ2V6eW1vZGVtZSIpICU+JQogIHNldF9iYXRjaGVzKGZhY3QgPSAibWFjcm9waGFnZXRyZWF0bWVudCIpCgp1bmZpbHRfd3JpdHRlbiA8LSB3cml0ZV9zZSgKICBscF9tYWNyb3BoYWdlLAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS97dmVyfS9yZWFkX2NvdW50cy9scF9tYWNyb3BoYWdlX3JlYWRzX3VuZmlsdGVyZWQtdnt2ZXJ9Lnhsc3giKSkKCmxwX21hY3JvcGhhZ2VfZmlsdCA8LSBzdWJzZXRfc2UobHBfbWFjcm9waGFnZSwgbm9uemVybyA9IDI1MDApCiMjICBzZW1hbnRpY19maWx0ZXIoc2VtYW50aWMgPSBjKCJhbWFzdGluIiwgImdwNjMiLCAibGVpc2htYW5vbHlzaW4iKSwKIyMgICAgICAgICAgICAgICAgICBzZW1hbnRpY19jb2x1bW4gPSAiYW5ub3RfZ2VuZV9wcm9kdWN0IikKZGF0YV9zdHJ1Y3R1cmVzIDwtIGMoZGF0YV9zdHJ1Y3R1cmVzLCAibHBfbWFjcm9waGFnZSIsICJscF9tYWNyb3BoYWdlX2ZpbHQiKQpmaWx0X3dyaXR0ZW4gPC0gd3JpdGVfc2UobHBfbWFjcm9waGFnZV9maWx0LAogIGV4Y2VsID0gZ2x1ZSgiYW5hbHlzZXMvbWFjcm9waGFnZV9kZS97dmVyfS9yZWFkX2NvdW50cy9scF9tYWNyb3BoYWdlX3JlYWRzX2ZpbHRlcmVkLXZ7dmVyfS54bHN4IikpCmxwX21hY3JvcGhhZ2UgPC0gbHBfbWFjcm9waGFnZV9maWx0CgpscF9tYWNyb3BoYWdlX25vc2IgPC0gc3Vic2V0X3NlKGxwX21hY3JvcGhhZ2UsIHN1YnNldCA9ICJiYXRjaCE9J2luZl9zYiciKQpscF9ub3NiX3dyaXRlIDwtIHdyaXRlX3NlKAogIGxwX21hY3JvcGhhZ2Vfbm9zYiwKICBleGNlbCA9IGdsdWUoImFuYWx5c2VzL21hY3JvcGhhZ2VfZGUve3Zlcn0vcmVhZF9jb3VudHMvbHBfbWFjcm9waGFnZV9ub3NiX3JlYWRzLXZ7dmVyfS54bHN4IikpCmRhdGFfc3RydWN0dXJlcyA8LSBjKGRhdGFfc3RydWN0dXJlcywgImxwX21hY3JvcGhhZ2Vfbm9zYiIpCgpzcGVjIDwtIG1ha2Vfcm5hc2VxX3NwZWMoKQp0ZXN0IDwtIHNtKGdhdGhlcl9wcmVwcm9jZXNzaW5nX21ldGFkYXRhKG1hY3JvcGhhZ2Vfc2hlZXQsIHNwZWNpZmljYXRpb24gPSBzcGVjKSkKYGBgCgojIFBsb3QgU0wgUmVhZHMgb24gYSBwZXIgY29uZGl0aW9uIGJhc2lzCgpgYGB7cn0KbHBfbWV0YSA8LSBjb2xEYXRhKGxwX21hY3JvcGhhZ2UpCmxwX21ldGFbWyJzbHZzcmVhZHNfbG9nIl1dIDwtIGxvZzEwKGxwX21ldGFbWyJzbHZzcmVhZHMiXV0pCmluZl92YWx1ZXMgPC0gaXMuaW5maW5pdGUobHBfbWV0YVtbInNsdnNyZWFkc19sb2ciXV0pCmxwX21ldGFbaW5mX3ZhbHVlcywgInNsdnNyZWFkc19sb2ciXSA8LSAtMTAKCmNvbG9yX3ZlY3RvciA8LSBhcy5jaGFyYWN0ZXIoY29sb3JfY2hvaWNlc1tbInN0cmFpbiJdXSkKbmFtZXMoY29sb3JfdmVjdG9yKSA8LSBuYW1lcyhjb2xvcl9jaG9pY2VzW1sic3RyYWluIl1dKQpjb2xvcl92ZWN0b3IgPC0gY29sb3JfdmVjdG9yW2MoInoyLjIiLCAiejIuMyIsICJ1bmtub3duIildCm5hbWVzKGNvbG9yX3ZlY3RvcikgPC0gYygiejIuMiIsICJ6Mi4zIiwgIm5vbmUiKQpzbF92aW9saW4gPC0gZ2dwbG90KGxwX21ldGEsCiAgICAgICAgICAgICAgICAgICAgYWVzKHggPSAuZGF0YVtbImNvbmRpdGlvbiJdXSwgeSA9IC5kYXRhW1sic2x2c3JlYWRzX2xvZyJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IC5kYXRhW1siY29uZGl0aW9uIl1dKSkgKwogIGdlb21fdmlvbGluKCkgKwogIGdlb21fcG9pbnQoKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sb3JfdmVjdG9yKQpzbF92aW9saW4KCmdnc3RhdHNwbG90OjpnZ2JldHdlZW5zdGF0cyhhcy5kYXRhLmZyYW1lKGxwX21ldGEpLCB4ID0gImNvbmRpdGlvbiIsIHkgPSAic2x2c3JlYWRzX2xvZyIpCmBgYAoKIyBNYWtlIGEgc2lsbHkgcGxvaWR5IHBsb3QKCkkgd2FudCB0byBtYWtlIGFuIGVzdGltYXRlIG9mIHBsb2lkeSB1c2luZyB0cmFuc2NyaXB0b21pYyBkYXRhLiAgVGhpcwppcyBieSBkZWZpbml0aW9uIGEgZm9vbGQncyBlcnJhbmQsIGJ1dCBJIHRoaW5rIGl0IG1pZ2h0IHdvcmsuCgpgYGB7cn0KbHBfcnBrbSA8LSBub3JtYWxpemUobHBfc2UsIGNvbnZlcnQgPSAicnBrbSIsIGZpbHRlciA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgIGxlbmd0aF9jb2x1bW4gPSAiYW5ub3RfY2RzX2xlbmd0aCIsIG5hX3RvX3plcm8gPSBUUlVFKQoKIyMgRXhjbHVkZSBzY2FmZm9sZHMKdW53YW50ZWQgPC0gZ3JlcGwocGF0dGVybiA9ICJTQ0FGIiwgeCA9IHJvd0RhdGEobHBfcnBrbSlbWyJhbm5vdF9nZW5lX2xvY2F0aW9uX3RleHQiXV0pCiMjIEkgdGhpbmsgbXkgc3Vic2V0IGxvZ2ljIGlzIGJhY3dhcmRzLi4uCmxwX3dhbnRlZCA8LSBscF9ycGttWyF1bndhbnRlZCwgXQoKc3VtbWFyeV9kZiA8LSBhcy5kYXRhLmZyYW1lKGFzc2F5KGxwX3dhbnRlZCkpCnN1bW1hcnlfZGZbWyJnZW5lX21lYW4iXV0gPC0gcm93TWVhbnMoc3VtbWFyeV9kZiwgbmEucm0gPSBUUlVFKQpzdW1tYXJ5X2RmW1siY2hyb21vc29tZSJdXSA8LSByb3dEYXRhKGxwX3dhbnRlZClbWyJhbm5vdF9jaHJvbW9zb21lIl1dCnN1bW1hcnlfZGZbWyJjaHJvbW9zb21lIl1dIDwtIGFzLmZhY3RvcihzdW1tYXJ5X2RmW1siY2hyb21vc29tZSJdXSkKbGV2ZWxzKHN1bW1hcnlfZGZbWyJjaHJvbW9zb21lIl1dKSA8LSBjKHNlcV9sZW4oMTkpLCAiMjAuMSIsICIyMC4yIiwgMjE6MzUpCgpzdW1tYXJ5X2RmIDwtIHN1bW1hcnlfZGZbLCBjKCJnZW5lX21lYW4iLCAiY2hyb21vc29tZSIpXSAlPiUKICBncm91cF9ieShjaHJvbW9zb21lKSAlPiUKICBzdW1tYXJpemUoY2hyX21lYW4gPSBtZWFuKGdlbmVfbWVhbiwgbmEucm0gPSBUUlVFKSkKCm1pbl9ycGttIDwtIG1pbihzdW1tYXJ5X2RmW1siY2hyX21lYW4iXV0pCnN1bW1hcnlfZGZbWyJjaHJfbWVhbiJdXSA8LSBzdW1tYXJ5X2RmW1siY2hyX21lYW4iXV0gLyBtaW5fcnBrbQoKZ2dwbG90KHN1bW1hcnlfZGYsIGFlcyh5ID0gY2hyb21vc29tZSwgeCA9IGNocl9tZWFuKSkgKwogIGdlb21fY29sKCkKCndhbnRlZCA8LSBjb2xEYXRhKGxwX3dhbnRlZClbWyJrbm52MmNsYXNzaWZpY2F0aW9uIl1dID09ICJ6MjIiIHwgY29sRGF0YShscF93YW50ZWQpW1sia25udjJjbGFzc2lmaWNhdGlvbiJdXSA9PSAiejIzIgpscF96IDwtIGxwX3dhbnRlZFssIHdhbnRlZF0KejIyX3NhbXBsZXMgPC0gY29sRGF0YShscF96KVtbImtubnYyY2xhc3NpZmljYXRpb24iXV0gPT0gInoyMiIKejIzX3NhbXBsZXMgPC0gY29sRGF0YShscF96KVtbImtubnYyY2xhc3NpZmljYXRpb24iXV0gPT0gInoyMyIKbHBfel9hc3NheSA8LSBhcy5kYXRhLmZyYW1lKGFzc2F5KGxwX3opKQpscF96X2Fzc2F5W1siejIyX2dlbmVfbWVhbiJdXSA8LSByb3dNZWFucyhscF96X2Fzc2F5WywgejIyX3NhbXBsZXNdLCBuYS5ybSA9IFRSVUUpCmxwX3pfYXNzYXlbWyJ6MjNfZ2VuZV9tZWFuIl1dIDwtIHJvd01lYW5zKGxwX3pfYXNzYXlbLCB6MjNfc2FtcGxlc10sIG5hLnJtID0gVFJVRSkKbHBfel9hc3NheVtbImNocm9tb3NvbWUiXV0gPC0gcm93RGF0YShscF96KVtbImFubm90X2Nocm9tb3NvbWUiXV0KbHBfel9tZWFucyA8LSBscF96X2Fzc2F5WywgYygiejIyX2dlbmVfbWVhbiIsICJ6MjNfZ2VuZV9tZWFuIiwgImNocm9tb3NvbWUiKV0gJT4lCiAgZ3JvdXBfYnkoY2hyb21vc29tZSkgJT4lCiAgc3VtbWFyaXplKHoyMl9tZWFuID0gbWVhbih6MjJfZ2VuZV9tZWFuLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICB6MjNfbWVhbiA9IG1lYW4oejIzX2dlbmVfbWVhbiwgbmEucm0gPSBUUlVFKSkKCmNocl9yZXNoYXBlZCA8LSByZXNoYXBlMjo6bWVsdChscF96X21lYW5zLCBpZC52YXJzID0gImNocm9tb3NvbWUiKQpjaHJfcmVzaGFwZWRbWyJjaHJvbW9zb21lIl1dIDwtIGZhY3RvcihjaHJfcmVzaGFwZWRbWyJjaHJvbW9zb21lIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKGFzLmNoYXJhY3RlcigxOjE5KSwgIjIwLjEiLCAiMjAuMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXMuY2hhcmFjdGVyKDIxOjM1KSkpCgpwdXRhdGl2ZV9hbmV1cGxvaWQgPC0gZ2dwbG90KGNocl9yZXNoYXBlZCwgYWVzKHggPSB2YWx1ZSwgeSA9IGNocm9tb3NvbWUpKSArCiAgZ2VvbV9iYXIoYWVzKGZpbGwgPSB2YXJpYWJsZSksIHBvc2l0aW9uID0gImRvZGdlIiwgc3RhdCA9ICJpZGVudGl0eSIpCnBwKGZpbGUgPSAiaW1hZ2VzL3B1dGF0aXZlX2FuZXVwbG9pZC5zdmciKQpwdXRhdGl2ZV9hbmV1cGxvaWQKZGV2Lm9mZigpCnB1dGF0aXZlX2FuZXVwbG9pZApgYGAKCiMgU2F2ZSBhbGwgZGF0YSBzdHJ1Y3R1cmVzIGludG8gb25lIHJkYQoKYGBge3J9CmZvdW5kX2lkeCA8LSBkYXRhX3N0cnVjdHVyZXMgJWluJSBscygpCmlmIChzdW0oIWZvdW5kX2lkeCkgPiAwKSB7CiAgbm90X2ZvdW5kIDwtIGRhdGFfc3RydWN0dXJlc1shZm91bmRfaWR4XQogIHdhcm5pbmcoIlNvbWUgZGF0YXN0cnVjdHVyZXMgd2VyZSBub3QgZ2VuZXJhdGVkOiAiLCB0b1N0cmluZyhub3RfZm91bmQpLCAiLiIpCiAgZGF0YV9zdHJ1Y3R1cmVzIDwtIGRhdGFfc3RydWN0dXJlc1tmb3VuZF9pZHhdCn0Kc2F2ZShsaXN0ID0gZGF0YV9zdHJ1Y3R1cmVzLCBmaWxlID0gZ2x1ZSgicmRhL3RtcmMyX2RhdGFfc3RydWN0dXJlcy12e3Zlcn0ucmRhIikpCmBgYAoKYGBge3J9CnBhbmRlcjo6cGFuZGVyKHNlc3Npb25JbmZvKCkpCm1lc3NhZ2UoIlRoaXMgaXMgaHBnbHRvb2xzIGNvbW1pdDogIiwgZ2V0X2dpdF9jb21taXQoKSkKbWVzc2FnZSgiU2F2aW5nIHRvICIsIHNhdmVmaWxlKQojIHRtcCA8LSBzbShzYXZlbWUoZmlsZW5hbWUgPSBzYXZlZmlsZSkpCmBgYAoKYGBge3IgbG9hZG1lX2FmdGVyLCBldmFsPUZBTFNFfQp0bXAgPC0gbG9hZG1lKGZpbGVuYW1lID0gc2F2ZWZpbGUpCmBgYAo=