sample_sheet <- glue::glue("sample_sheets/tmrc2_samples_202206.xlsx")

1 Introduction

This is mostly just a run of this worksheet to reacquaint myself with it.

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

In all cases the processing performed was:

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

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

2 Annotations

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

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

tt <- sm(library(EuPathDB))
orgdb <- "org.Lpanamensis.MHOMCOL81L13.v46.eg.db"
tt <- sm(library(orgdb, character.only=TRUE))
pan_db <- org.Lpanamensis.MHOMCOL81L13.v46.eg.db
all_fields <- columns(pan_db)

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

lp_go <- sm(load_orgdb_go(pan_db))
lp_lengths <- all_lp_annot[, c("gid", "annot_cds_length")]
colnames(lp_lengths)  <- c("ID", "length")
all_lp_annot[["annot_gene_product"]] <- tolower(all_lp_annot[["annot_gene_product"]])
orthos <- sm(EuPathDB::extract_eupath_orthologs(db = pan_db))

3 Load a genome

meta <- sm(EuPathDB::download_eupath_metadata(webservice="tritrypdb"))
lp_entry <- EuPathDB::get_eupath_entry(species="Leishmania panamensis", metadata=meta)
## Found the following hits: Leishmania panamensis MHOM/COL/81/L13, Leishmania panamensis strain MHOM/PA/94/PSC-1, choosing the first.
## Using: Leishmania panamensis MHOM/COL/81/L13.
colnames(lp_entry)
##  [1] "AnnotationVersion"  "AnnotationSource"   "BiocVersion"       
##  [4] "DataProvider"       "Genome"             "GenomeSource"      
##  [7] "GenomeVersion"      "NumArrayGene"       "NumChipChipGene"   
## [10] "NumChromosome"      "NumCodingGene"      "NumCommunity"      
## [13] "NumContig"          "NumEC"              "NumEST"            
## [16] "NumGene"            "NumGO"              "NumOrtholog"       
## [19] "NumOtherGene"       "NumPopSet"          "NumProteomics"     
## [22] "NumPseudogene"      "NumRNASeq"          "NumRTPCR"          
## [25] "NumSNP"             "NumTFBS"            "Organellar"        
## [28] "ReferenceStrain"    "MegaBP"             "PrimaryKey"        
## [31] "ProjectID"          "RecordClassName"    "SourceID"          
## [34] "SourceVersion"      "TaxonomyID"         "TaxonomyName"      
## [37] "URLGenome"          "URLGFF"             "URLProtein"        
## [40] "Coordinate_1_based" "Maintainer"         "SourceUrl"         
## [43] "Tags"               "BsgenomePkg"        "GrangesPkg"        
## [46] "OrganismdbiPkg"     "OrgdbPkg"           "TxdbPkg"           
## [49] "Taxon"              "Genus"              "Species"           
## [52] "Strain"             "BsgenomeFile"       "GrangesFile"       
## [55] "OrganismdbiFile"    "OrgdbFile"          "TxdbFile"          
## [58] "GenusSpecies"       "TaxonUnmodified"    "TaxonCanonical"    
## [61] "TaxonXref"
testing_panamensis <- "BSGenome.Leishmania.panamensis.MHOMCOL81L13.v53"
## testing_panamensis <- EuPathDB::make_eupath_bsgenome(entry=lp_entry, eu_version="v46")
library(as.character(testing_panamensis), character.only=TRUE)
## Loading required package: BSgenome
## Loading required package: Biostrings
## Loading required package: XVector
## 
## Attaching package: 'Biostrings'
## The following object is masked from 'package:base':
## 
##     strsplit
## Loading required package: rtracklayer
genome <- get0(as.character(testing_panamensis))

4 TODO:

Resequence samples: TMRC20002, TMRC20006, TMRC20004 (maybe TMRC20008 and TMRC20029)

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

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

5.1 Notes

The following samples are much lower coverage:

  • TMRC20002
  • TMRC20006
  • TMRC20007
  • TMRC20008

20210610: I made some manual changes to the sample sheet which I downloaded, filling in some zymodeme with ‘unknown’

5.2 TODO:

  1. Do the multi-gene family removal right here instead of way down at the bottom
  2. Add zymodeme snps to the annotation later.
  3. Start phylogenetic analysis of variant table.
data_structures <- c()

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",
        "braz" = "#cc00cc",
        "unknown" = "#cbcbcb",
        "null" = "#000000"),
    "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")
sanitize_columns <- c("passagenumber", "clinicalresponse", "clinicalcategorical",
                      "zymodemecategorical")
lp_expt <- create_expt(sample_sheet,
                       gene_info = all_lp_annot,
                       annotation_name = orgdb,
                       savefile = glue::glue("rda/tmrc2_lp_expt_all_raw-v{ver}.rda"),
                       id_column = "hpglidentifier",
                       file_column = "lpanamensisv36hisatfile") %>%
  set_expt_conditions(fact = "zymodemecategorical") %>%
  subset_expt(nonzero = 8550) %>%
  subset_expt(coverage = 5000000) %>%
  set_expt_colors(color_choices[["strain"]]) %>%
  semantic_expt_filter(semantic = c("amastin", "gp63", "leishmanolysin"),
                       semantic_column = "annot_gene_product") %>%
  sanitize_expt_metadata(columns = sanitize_columns) %>%
  set_expt_factors(columns = sanitize_columns, class = "factor")
## Reading the sample metadata.
## Dropped 11 rows from the sample metadata because the sample ID is blank.
## 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.
## The sample definitions comprises: 110 rows(samples) and 66 columns(metadata fields).
## Warning in create_expt(sample_sheet, gene_info = all_lp_annot, annotation_name
## = orgdb, : Some samples were removed when cross referencing the samples against
## the count data.
## Matched 8778 annotations and counts.
## Bringing together the count matrix and gene information.
## Some annotations were lost in merging, setting them to 'undefined'.
## The final expressionset has 8778 features and 105 samples.
## The samples (and read coverage) removed when filtering 8550 non-zero genes are:
## TMRC20002 TMRC20006 
##  11681227   6670348
## subset_expt(): There were 105, now there are 103 samples.
## The samples removed (and read coverage) when filtering samples with less than 5e+06 reads are:
## TMRC20004 TMRC20029 
##    564812   1658096
## subset_expt(): There were 103, now there are 101 samples.
## semantic_expt_filter(): Removed 68 genes.
data_structures <- c(data_structures, "lp_expt")
save(list = "lp_expt", file = glue::glue("rda/tmrc2_lp_expt_all_sanitized-v{ver}.rda"))

table(pData(lp_expt)[["zymodemecategorical"]])
## 
##          braz notapplicable       unknown           z20           z21 
##             2             2             3             1             7 
##           z22           z23           z24           z30 
##            43            40             2             1
table(pData(lp_expt)[["clinicalresponse"]])
## 
##                                  cure                               failure 
##                                    38                                    38 
##                       laboratory line laboratory line miltefosine resistant 
##                                     1                                     1 
##                                    nd                      reference strain 
##                                    19                                     4

5.3 By Susceptilibity

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

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”
st <- pData(lp_expt)[["susceptibilityinfectionreduction32ugmlsbvhistoricaldata"]]
starting <- sanitize_percent(st)
st
##   [1] "0.45"    "0.14"    "0.97"    NA        NA        NA        NA       
##   [8] NA        NA        "0"       "0.97"    "0"       "0"       "0.46"   
##  [15] "0.45"    "0.97"    "0.56"    "0.99"    "0.46"    "0.7"     "0.99"   
##  [22] "0.99"    "0.45"    "0.98"    "0.99"    "0.49"    "0.99"    "0.53"   
##  [29] "0.99"    "0.66"    "0.99"    "0.5"     "0.89"    "1"       "1"      
##  [36] "0.94"    "0.94"    "95%"     "No data" "No data" "No data" "No data"
##  [43] "No data" "No data" "No data" "No data" "No data" "No data" "No data"
##  [50] "No data" "No data" "0.99"    "0.99"    "No data" "0.98"    "0.97"   
##  [57] "0.96"    "0.96"    "0"       "0"       "0"       "0.06"    "0.94"   
##  [64] "0.94"    "0.03"    "0.94"    "0"       "0.25"    "0.95"    "0.27"   
##  [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" "No data" "No data" "No data" "No data" "No data" "No data"
##  [99] "No data" "No data" "No data"
starting
##   [1] 0.45 0.14 0.97   NA   NA   NA   NA   NA   NA 0.00 0.97 0.00 0.00 0.46 0.45
##  [16] 0.97 0.56 0.99 0.46 0.70 0.99 0.99 0.45 0.98 0.99 0.49 0.99 0.53 0.99 0.66
##  [31] 0.99 0.50 0.89 1.00 1.00 0.94 0.94 0.95   NA   NA   NA   NA   NA   NA   NA
##  [46]   NA   NA   NA   NA   NA   NA 0.99 0.99   NA 0.98 0.97 0.96 0.96 0.00 0.00
##  [61] 0.00 0.06 0.94 0.94 0.03 0.94 0.00 0.25 0.95 0.27   NA   NA   NA   NA   NA
##  [76]   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA
##  [91]   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA   NA
sus_categorical <- starting
na_idx <- is.na(starting)
sum(na_idx)
## [1] 51
sus_categorical[na_idx] <- "unknown"

resist_idx <- starting <= 0.35
sus_categorical[resist_idx] <- "resistant"
indeterminant_idx <- starting >= 0.36 & starting <= 0.48
sus_categorical[indeterminant_idx] <- "ambiguous"
susceptible_idx <- starting >= 0.49
sus_categorical[susceptible_idx] <- "sensitive"

sus_categorical <- as.factor(sus_categorical)
pData(lp_expt)[["sus_category_historical"]] <- sus_categorical
table(sus_categorical)
## sus_categorical
## ambiguous resistant sensitive   unknown 
##         5        12        33        51
starting_current <- sanitize_percent(pData(lp_expt)[["susceptibilityinfectionreduction32ugmlsbvcurrentdata"]])
sus_categorical_current <- starting_current
na_idx <- is.na(starting_current)
sum(na_idx)
## [1] 54
sus_categorical_current[na_idx] <- "unknown"

resist_idx <- starting_current <= 0.35
sus_categorical_current[resist_idx] <- "resistant"
indeterminant_idx <- starting_current >= 0.36 & starting_current <= 0.48
sus_categorical_current[indeterminant_idx] <- "ambiguous"
susceptible_idx <- starting_current >= 0.49
sus_categorical_current[susceptible_idx] <- "sensitive"
sus_categorical_current <- as.factor(sus_categorical_current)

pData(lp_expt)[["sus_category_current"]] <- sus_categorical_current
table(sus_categorical_current)
## sus_categorical_current
## ambiguous resistant sensitive   unknown 
##         9         6        32        54
lp_strain <- lp_expt %>%
  set_expt_batches(fact = sus_categorical_current) %>%
  set_expt_colors(color_choices[["strain"]])
table(pData(lp_strain)[["condition"]])
## 
##    braz    null unknown    z2.0    z2.1    z2.2    z2.3    z2.4    z3.0 
##       2       2       3       1       7      43      40       2       1
save(list = "lp_strain", file = glue::glue("rda/tmrc2_lp_strain-v{ver}.rda"))
data_structures <- c(data_structures, "lp_strain")

lp_two_strains <- subset_expt(lp_strain, subset = "condition=='z2.3'|condition=='z2.2'")
## subset_expt(): There were 101, now there are 83 samples.
save(list = "lp_two_strains",
     file = glue::glue("rda/tmrc2_lp_two_strains-v{ver}.rda"))
data_structures <- c(data_structures, "lp_two_strains")

5.4 By Cure/Fail status

lp_cf <- set_expt_conditions(lp_expt, fact = "clinicalcategorical") %>%
  set_expt_batches(fact = sus_categorical_current) %>%
  set_expt_colors(color_choices[["cf"]])
## Warning in set_expt_colors(., color_choices[["cf"]]): Colors for the following
## categories are not being used: notapplicable.
table(pData(lp_cf)[["condition"]])
## 
##    cure    fail unknown 
##      38      38      25
data_structures <- c(data_structures, "lp_cf")
save(list = "lp_cf",
     file = glue::glue("rda/tmrc2_lp_cf-v{ver}.rda"))

lp_cf_known <- subset_expt(lp_cf, subset="condition!='unknown'")
## subset_expt(): There were 101, now there are 76 samples.
data_structures <- c(data_structures, "lp_cf_known")
save(list = "lp_cf_known",
     file = glue::glue("rda/tmrc2_lp_cf_known-v{ver}.rda"))
lp_susceptibility <- set_expt_conditions(lp_expt, fact = "sus_category_current") %>%
  set_expt_batches(fact = "clinicalcategorical") %>%
  set_expt_colors(colors = color_choices[["susceptibility"]])
save(list = "lp_susceptibility",
     file = glue::glue("rda/tmrc2_lp_susceptibility-v{ver}.rda"))
data_structures <- c(data_structures, "lp_susceptibility")

TODO: Do this with and without sva and compare the results.

lp_zymo <- subset_expt(lp_expt, subset = "condition=='z2.2'|condition=='z2.3'")
## subset_expt(): There were 101, now there are 83 samples.
data_structures <- c(data_structures, "lp_zymo")
save(list = "lp_zymo",
     file = glue::glue("rda/tmrc2_lp_zymo-v{ver}.rda"))
macrophage_sheet <- "sample_sheets/tmrc2_macrophage_samples_202203.xlsx"
hs_macrophage <- create_expt(macrophage_sheet,
                             file_column="lpanamensisv36hisatfile",
                             gene_info=all_lp_annot,
                             savefile = glue::glue("rda/hs_macrophage-v{ver}.rda"),
                             annotation="org.Lpanamensis.MHOMCOL81L13.v46.eg.db") %>%
  set_expt_conditions(fact="macrophagezymodeme") %>%
  set_expt_batches(fact="macrophagetreatment")
## Reading the sample metadata.
## The sample definitions comprises: 28 rows(samples) and 68 columns(metadata fields).
## Warning in create_expt(macrophage_sheet, file_column =
## "lpanamensisv36hisatfile", : Some samples were removed when cross referencing
## the samples against the count data.
## Matched 8778 annotations and counts.
## Bringing together the count matrix and gene information.
## Some annotations were lost in merging, setting them to 'undefined'.
## The final expressionset has 8778 features and 23 samples.
data_structures <- c(data_structures, "hs_macrophage")
lp_previous <- create_expt("sample_sheets/tmrc2_samples_20191203.xlsx",
                           file_column = "tophat2file",
                           savefile = glue::glue("rda/lp_previous-v{ver}.rda"))
## Reading the sample metadata.
## Dropped 13 rows from the sample metadata because the sample ID is blank.
## The sample definitions comprises: 50 rows(samples) and 38 columns(metadata fields).
## Warning in create_expt("sample_sheets/tmrc2_samples_20191203.xlsx", file_column
## = "tophat2file", : Some samples were removed when cross referencing the samples
## against the count data.
## Matched 8841 annotations and counts.
## Bringing together the count matrix and gene information.
## The final expressionset has 8841 features and 33 samples.
data_structures <- c(data_structures, "lp_previous")
tt <- lp_previous$expressionset
rownames(tt) <- gsub(pattern = "^exon_", replacement = "", x = rownames(tt))
rownames(tt) <- gsub(pattern = "\\.1$", replacement = "", x = rownames(tt))
lp_previous$expressionset <- tt
rm(tt)

5.5 Create the SNP expressionset

## The next line drops the samples which are missing the SNP pipeline.
lp_snp <- subset_expt(lp_expt, subset="!is.na(pData(lp_expt)[['freebayessummary']])")
## subset_expt(): There were 101, now there are 101 samples.
new_snps <- count_expt_snps(lp_snp, annot_column = "freebayessummary", snp_column="PAIRED")
## 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 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`
## Warning: NAs introduced by coercion
## 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`
old_snps <- count_expt_snps(lp_previous, annot_column = "bcftable", snp_column = 2)
## The rownames are missing the chromosome identifier,
## they probably came from an older version of this method.
save(list = "lp_snp",
     file = glue::glue("rda/lp_snp-v{ver}.rda"))
data_structures <- c(data_structures, "lp_snp")
save(list = "new_snps",
     file = glue::glue("rda/new_snps-v{ver}.rda"))
data_structures <- c(data_structures, "new_snps")
save(list = "old_snps",
     file = glue::glue("rda/old_snps-v{ver}.rda"))
data_structures <- c(data_structures, "old_snps")

nonzero_snps <- exprs(new_snps) != 0
colSums(nonzero_snps)
## tmrc20001 tmrc20065 tmrc20005 tmrc20007 tmrc20008 tmrc20027 tmrc20028 tmrc20032 
##         0     93649         0         0         0    351343    338580    146302 
## tmrc20040 tmrc20066 tmrc20039 tmrc20037 tmrc20038 tmrc20067 tmrc20068 tmrc20041 
##     58753     93615     25115     98958     97676     93954     96583     53184 
## tmrc20015 tmrc20009 tmrc20010 tmrc20016 tmrc20011 tmrc20012 tmrc20013 tmrc20017 
##     96398     15890     93816    146124     13914       456     94766     48288 
## tmrc20014 tmrc20018 tmrc20019 tmrc20070 tmrc20020 tmrc20021 tmrc20022 tmrc20025 
##     17245    140438     14829     97336     15484    101127     18143    364240 
## tmrc20024 tmrc20036 tmrc20069 tmrc20033 tmrc20026 tmrc20031 tmrc20076 tmrc20073 
##     18471     60087     18792     33663     15074     19139     18385     96169 
## tmrc20055 tmrc20079 tmrc20071 tmrc20078 tmrc20094 tmrc20042 tmrc20058 tmrc20072 
##     22246     96224     94353     18836     87878     19734     94524     50292 
## tmrc20059 tmrc20048 tmrc20057 tmrc20088 tmrc20056 tmrc20060 tmrc20077 tmrc20074 
##     94091     97164     48944     15594     22683     21506     18773     22132 
## tmrc20063 tmrc20053 tmrc20052 tmrc20064 tmrc20075 tmrc20051 tmrc20050 tmrc20049 
##     28254     20181    100709     93173     97982     94125     17200     16168 
## tmrc20062 tmrc20110 tmrc20080 tmrc20043 tmrc20083 tmrc20054 tmrc20085 tmrc20046 
##     93677     16997     96528     95623     21167     93603     89765     48608 
## tmrc20093 tmrc20089 tmrc20047 tmrc20090 tmrc20044 tmrc20045 tmrc20061 tmrc20105 
##     48254     90421     92637     91564     14861     50403    116906     86758 
## tmrc20108 tmrc20109 tmrc20098 tmrc20096 tmrc20097 tmrc20101 tmrc20092 tmrc20082 
##     97005     17932     92927     17534     46863     17753     16578    108121 
## tmrc20102 tmrc20099 tmrc20100 tmrc20091 tmrc20084 tmrc20087 tmrc20103 tmrc20104 
##     92380     91383     94381     15059     46548     14947     49368     94237 
## tmrc20086 tmrc20107 tmrc20081 tmrc20106 tmrc20095 
##     15813     95370     19533     18830     81200
## My old_snps is using an older annotation incorrectly, so fix it here:
Biobase::annotation(old_snps$expressionset) <- Biobase::annotation(new_snps$expressionset)
both_snps <- combine_expts(new_snps, old_snps)
save(list = "both_snps",
     file = glue::glue("rda/both_snps-v{ver}.rda"))
data_structures <- c(data_structures, "both_snps")

6 Save all data structures into one big pile

save(list = data_structures, file = glue::glue("rda/tmrc2_data_structures-v{ver}.rda"))
pander::pander(sessionInfo())

R version 4.2.1 (2022-06-23)

Platform: x86_64-pc-linux-gnu (64-bit)

locale: LC_CTYPE=en_US.UTF-8, LC_NUMERIC=C, LC_TIME=en_US.UTF-8, LC_COLLATE=en_US.UTF-8, LC_MONETARY=en_US.UTF-8, LC_MESSAGES=en_US.UTF-8, LC_PAPER=en_US.UTF-8, LC_NAME=C, LC_ADDRESS=C, LC_TELEPHONE=C, LC_MEASUREMENT=en_US.UTF-8 and LC_IDENTIFICATION=C

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

other attached packages: BSGenome.Leishmania.panamensis.MHOMCOL81L13.v53(v.2021.07), BSgenome(v.1.64.0), rtracklayer(v.1.56.1), Biostrings(v.2.64.0), XVector(v.0.36.0), futile.logger(v.1.4.3), org.Lpanamensis.MHOMCOL81L13.v46.eg.db(v.2020.07), AnnotationDbi(v.1.58.0), EuPathDB(v.1.6.0), GenomeInfoDbData(v.1.2.8), Heatplus(v.3.4.0), hpgltools(v.1.0), testthat(v.3.1.4), SummarizedExperiment(v.1.26.1), GenomicRanges(v.1.48.0), GenomeInfoDb(v.1.32.2), IRanges(v.2.30.0), S4Vectors(v.0.34.0), MatrixGenerics(v.1.8.1), matrixStats(v.0.62.0), Biobase(v.2.56.0) and BiocGenerics(v.0.42.0)

loaded via a namespace (and not attached): rappdirs(v.0.3.3), AnnotationForge(v.1.38.0), tidyr(v.1.2.0), ggplot2(v.3.3.6), bit64(v.4.0.5), knitr(v.1.39), DelayedArray(v.0.22.0), data.table(v.1.14.2), KEGGREST(v.1.36.3), RCurl(v.1.98-1.7), doParallel(v.1.0.17), generics(v.0.1.3), GenomicFeatures(v.1.48.3), lambda.r(v.1.2.4), callr(v.3.7.1), RhpcBLASctl(v.0.21-247.1), usethis(v.2.1.6), RSQLite(v.2.2.15), shadowtext(v.0.1.2), tzdb(v.0.3.0), bit(v.4.0.4), enrichplot(v.1.16.1), xml2(v.1.3.3), httpuv(v.1.6.5), assertthat(v.0.2.1), viridis(v.0.6.2), xfun(v.0.31), hms(v.1.1.1), jquerylib(v.0.1.4), evaluate(v.0.15), promises(v.1.2.0.1), fansi(v.1.0.3), restfulr(v.0.0.15), progress(v.1.2.2), caTools(v.1.18.2), dbplyr(v.2.2.1), igraph(v.1.3.4), DBI(v.1.1.3), htmlwidgets(v.1.5.4), stringdist(v.0.9.8), purrr(v.0.3.4), ellipsis(v.0.3.2), dplyr(v.1.0.9), backports(v.1.4.1), annotate(v.1.74.0), aod(v.1.3.2), biomaRt(v.2.52.0), vctrs(v.0.4.1), remotes(v.2.4.2), cachem(v.1.0.6), withr(v.2.5.0), ggforce(v.0.3.3), vroom(v.1.5.7), AnnotationHubData(v.1.26.1), GenomicAlignments(v.1.32.1), treeio(v.1.20.1), prettyunits(v.1.1.1), DOSE(v.3.22.0), ape(v.5.6-2), lazyeval(v.0.2.2), crayon(v.1.5.1), genefilter(v.1.78.0), edgeR(v.3.38.1), pkgconfig(v.2.0.3), tweenr(v.1.0.2), nlme(v.3.1-158), pkgload(v.1.3.0), devtools(v.2.4.4), rlang(v.1.0.4), lifecycle(v.1.0.1), miniUI(v.0.1.1.1), downloader(v.0.4), filelock(v.1.0.2), BiocFileCache(v.2.4.0), AnnotationHub(v.3.4.0), rprojroot(v.2.0.3), polyclip(v.1.10-0), graph(v.1.74.0), Matrix(v.1.4-1), aplot(v.0.1.6), boot(v.1.3-28), processx(v.3.7.0), png(v.0.1-7), viridisLite(v.0.4.0), rjson(v.0.2.21), bitops(v.1.0-7), KernSmooth(v.2.23-20), pander(v.0.6.5), blob(v.1.2.3), stringr(v.1.4.0), qvalue(v.2.28.0), readr(v.2.1.2), gridGraphics(v.0.5-1), scales(v.1.2.0), memoise(v.2.0.1), magrittr(v.2.0.3), plyr(v.1.8.7), gplots(v.3.1.3), zlibbioc(v.1.42.0), compiler(v.4.2.1), scatterpie(v.0.1.7), BiocIO(v.1.6.0), RColorBrewer(v.1.1-3), lme4(v.1.1-30), Rsamtools(v.2.12.0), cli(v.3.3.0), urlchecker(v.1.0.1), patchwork(v.1.1.1), ps(v.1.7.1), formatR(v.1.12), MASS(v.7.3-58), mgcv(v.1.8-40), tidyselect(v.1.1.2), stringi(v.1.7.8), yaml(v.2.3.5), GOSemSim(v.2.22.0), locfit(v.1.5-9.6), ggrepel(v.0.9.1), biocViews(v.1.64.1), grid(v.4.2.1), sass(v.0.4.2), fastmatch(v.1.1-3), tools(v.4.2.1), parallel(v.4.2.1), rstudioapi(v.0.13), foreach(v.1.5.2), gridExtra(v.2.3), farver(v.2.1.1), ggraph(v.2.0.5), digest(v.0.6.29), BiocManager(v.1.30.18), shiny(v.1.7.2), Rcpp(v.1.0.9), broom(v.1.0.0), BiocVersion(v.3.15.2), later(v.1.3.0), OrganismDbi(v.1.38.1), httr(v.1.4.3), Rdpack(v.2.4), colorspace(v.2.0-3), rvest(v.1.0.2), brio(v.1.1.3), XML(v.3.99-0.10), fs(v.1.5.2), splines(v.4.2.1), BiocCheck(v.1.32.0), yulab.utils(v.0.0.5), RBGL(v.1.72.0), PROPER(v.1.28.0), tidytree(v.0.3.9), graphlayouts(v.0.8.0), ggplotify(v.0.1.0), plotly(v.4.10.0), sessioninfo(v.1.2.2), xtable(v.1.8-4), futile.options(v.1.0.1), jsonlite(v.1.8.0), nloptr(v.2.0.3), ggtree(v.3.4.1), tidygraph(v.1.2.1), ggfun(v.0.0.6), R6(v.2.5.1), RUnit(v.0.4.32), profvis(v.0.3.7), pillar(v.1.8.0), htmltools(v.0.5.3), mime(v.0.12), glue(v.1.6.2), fastmap(v.1.1.0), minqa(v.1.2.4), clusterProfiler(v.4.4.4), BiocParallel(v.1.30.3), interactiveDisplayBase(v.1.34.0), codetools(v.0.2-18), fgsea(v.1.22.0), pkgbuild(v.1.3.1), utf8(v.1.2.2), lattice(v.0.20-45), bslib(v.0.4.0), tibble(v.3.1.8), sva(v.3.44.0), pbkrtest(v.0.5.1), curl(v.4.3.2), gtools(v.3.9.3), zip(v.2.2.0), openxlsx(v.4.2.5), GO.db(v.3.15.0), survival(v.3.3-1), limma(v.3.52.2), rmarkdown(v.2.14), desc(v.1.4.1), munsell(v.0.5.0), DO.db(v.2.9), iterators(v.1.0.14), variancePartition(v.1.26.0), reshape2(v.1.4.4), gtable(v.0.3.0) and rbibutils(v.2.2.8)

message(paste0("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 86f725d3ee8482b45960e3a4541f1d4ade97a406
## This is hpgltools commit: Thu Jul 21 11:08:25 2022 -0400: 86f725d3ee8482b45960e3a4541f1d4ade97a406
message(paste0("Saving to ", savefile))
## Saving to tmrc2_02sample_estimation_v202207.rda.xz
tmp <- sm(saveme(filename = savefile))
tmp <- loadme(filename = savefile)
LS0tCnRpdGxlOiAiVE1SQzIgQ29tcHJlaGVuc2l2ZSBEYXRhIEFuYWx5c2lzOiAyMDIyMDQiCmF1dGhvcjogImF0YiBhYmVsZXdAZ21haWwuY29tIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKIGh0bWxfZG9jdW1lbnQ6CiAgY29kZV9kb3dubG9hZDogdHJ1ZQogIGNvZGVfZm9sZGluZzogc2hvdwogIGZpZ19jYXB0aW9uOiB0cnVlCiAgZmlnX2hlaWdodDogNwogIGZpZ193aWR0aDogNwogIGhpZ2hsaWdodDogZGVmYXVsdAogIGtlZXBfbWQ6IGZhbHNlCiAgbW9kZTogc2VsZmNvbnRhaW5lZAogIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgdGhlbWU6IHJlYWRhYmxlCiAgdG9jOiB0cnVlCiAgdG9jX2Zsb2F0OgogICBjb2xsYXBzZWQ6IGZhbHNlCiAgIHNtb290aF9zY3JvbGw6IGZhbHNlCi0tLQoKPHN0eWxlPgogIGJvZHkgLm1haW4tY29udGFpbmVyIHsKICAgIG1heC13aWR0aDogMTYwMHB4OwogIH0KPC9zdHlsZT4KCmBgYHtyIG9wdGlvbnMsIGluY2x1ZGUgPSBGQUxTRX0KbGlicmFyeShocGdsdG9vbHMpCnR0IDwtIGRldnRvb2xzOjpsb2FkX2FsbCgifi9ocGdsdG9vbHMiKQprbml0cjo6b3B0c19rbml0JHNldChwcm9ncmVzcyA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgIHZlcmJvc2UgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICB3aWR0aCA9IDkwLAogICAgICAgICAgICAgICAgICAgICBlY2hvID0gVFJVRSkKa25pdHI6Om9wdHNfY2h1bmskc2V0KGVycm9yID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgIGZpZy53aWR0aCA9IDgsCiAgICAgICAgICAgICAgICAgICAgICBmaWcuaGVpZ2h0ID0gOCwKICAgICAgICAgICAgICAgICAgICAgIGRwaSA9IDk2KQpvbGRfb3B0aW9ucyA8LSBvcHRpb25zKGRpZ2l0cyA9IDQsCiAgICAgICAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgIGtuaXRyLmR1cGxpY2F0ZS5sYWJlbCA9ICJhbGxvdyIpCmdncGxvdDI6OnRoZW1lX3NldChnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemUgPSAxMikpCnZlciA8LSAiMjAyMjA3IgpydW5kYXRlIDwtIGZvcm1hdChTeXMuRGF0ZSgpLCBmb3JtYXQgPSAiJVklbSVkIikKCiMjIHRtcCA8LSB0cnkoc20obG9hZG1lKGZpbGVuYW1lID0gZ3N1YihwYXR0ZXJuID0gIlxcLlJtZCIsIHJlcGxhY2UgPSAiXFwucmRhXFwueHoiLCB4ID0gcHJldmlvdXNfZmlsZSkpKSkKcm1kX2ZpbGUgPC0gZ2x1ZTo6Z2x1ZSgidG1yYzJfMDJzYW1wbGVfZXN0aW1hdGlvbl92e3Zlcn0uUm1kIikKc2F2ZWZpbGUgPC0gZ3N1YihwYXR0ZXJuID0gIlxcLlJtZCIsIHJlcGxhY2UgPSAiXFwucmRhXFwueHoiLCB4ID0gcm1kX2ZpbGUpCgpsaWJyYXJ5KEhlYXRwbHVzKQpgYGAKCmBgYHtyIGN1cnJlbnRfc2FtcGxlc2hlZXR9CnNhbXBsZV9zaGVldCA8LSBnbHVlOjpnbHVlKCJzYW1wbGVfc2hlZXRzL3RtcmMyX3NhbXBsZXNfMjAyMjA2Lnhsc3giKQpgYGAKCiMgSW50cm9kdWN0aW9uCgpUaGlzIGlzIG1vc3RseSBqdXN0IGEgcnVuIG9mIHRoaXMgd29ya3NoZWV0IHRvIHJlYWNxdWFpbnQgbXlzZWxmIHdpdGggaXQuCgpUaGlzIGRvY3VtZW50IGlzIGludGVuZGVkIHRvIHByb3ZpZGUgYSBnZW5lcmFsIG92ZXJ2aWV3IG9mIHRoZSBUTVJDMiBzYW1wbGVzCndoaWNoIGhhdmUgdGh1cyBmYXIgYmVlbiBzZXF1ZW5jZWQuICBJbiBzb21lIGNhc2VzLCB0aGlzIGluY2x1ZGVzIG9ubHkgdGhvc2UKc2FtcGxlcyBzdGFydGluZyBpbiAyMDE5OyBpbiBvdGhlciBpbnN0YW5jZXMgSSBhbSBpbmNsdWRpbmcgb3VyIHByZXZpb3VzCigyMDE1LTIwMTYpIHNhbXBsZXMuCgpJbiBhbGwgY2FzZXMgdGhlIHByb2Nlc3NpbmcgcGVyZm9ybWVkIHdhczoKCjEuICBEZWZhdWx0IHRyaW1taW5nIHdhcyBwZXJmb3JtZWQuCjIuICBIaXNhdDIgd2FzIHVzZWQgdG8gbWFwIHRoZSByZW1haW5pbmcgcmVhZHMgYWdhaW5zdCB0aGUgTGVpc2htYW5pYQogICAgcGFuYW1lbnNpcyBnZW5vbWUgcmV2aXNpb24gMzYuCjMuICBUaGUgYWxpZ25tZW50cyBmcm9tIGhpc2F0MiB3ZXJlIHVzZWQgdG8gY291bnQgcmVhZHMvZ2VuZSBhZ2FpbnN0IHRoZQogICAgcmV2aXNpb24gMzYgYW5ub3RhdGlvbnMgd2l0aCBodHNlcS4KNC4gIFRoZXNlIGFsaWdubWVudHMgd2VyZSBhbHNvIHBhc3NlZCB0byB0aGUgcGlsZXVwIGZ1bmN0aW9uYWxpdHkgb2Ygc2FtdG9vbHMKICAgIGFuZCB0aGUgdmNmL2JjZiB1dGlsaXRpZXMgaW4gb3JkZXIgdG8gbWFrZSBhIG1hdHJpeCBvZiBhbGwgb2JzZXJ2ZWQKICAgIGRpZmZlcmVuY2VzIGJldHdlZW4gZWFjaCBzYW1wbGUgd2l0aCByZXNwZWN0IHRvIHRoZSByZWZlcmVuY2UuCgpUaGUgYW5hbHlzZXMgaW4gdGhpcyBkb2N1bWVudCB1c2UgdGhlIG1hdHJpY2VzIG9mIGNvdW50cy9nZW5lIGZyb20gIzMgYW5kCnZhcmlhbnRzL3Bvc2l0aW9uIGZyb20gIzQgaW4gb3JkZXIgdG8gcHJvdmlkZSBzb21lIGltYWdlcyBhbmQgbWV0cmljcyBkZXNjcmliaW5nCnRoZSBzYW1wbGVzIHdlIGhhdmUgc2VxdWVuY2VkIHNvIGZhci4KCiMgQW5ub3RhdGlvbnMKCkV2ZXJ5dGhpbmcgd2hpY2ggZm9sbG93cyBkZXBlbmRzIG9uIHRoZSBFeGlzdGluZyBUcmlUcnlwREIgYW5ub3RhdGlvbnMgcmV2aXNpb24KNDYsIGNpcmNhIDIwMTkuICBUaGUgZm9sbG93aW5nIGJsb2NrIGxvYWRzIGEgZGF0YWJhc2Ugb2YgdGhlc2UgYW5ub3RhdGlvbnMgYW5kCnR1cm5zIGl0IGludG8gYSBtYXRyaXggd2hlcmUgdGhlIHJvd3MgYXJlIGdlbmVzIGFuZCBjb2x1bW5zIGFyZSBhbGwgdGhlCmFubm90YXRpb24gdHlwZXMgcHJvdmlkZWQgYnkgVHJpVHJ5cERCLgoKVGhlIHNhbWUgZGF0YWJhc2Ugd2FzIHVzZWQgdG8gY3JlYXRlIGEgbWF0cml4IG9mIG9ydGhvbG9nb3VzIGdlbmVzIGJldHdlZW4KTC5wYW5hbWVuc2lzIGFuZCBhbGwgb2YgdGhlIG90aGVyIHNwZWNpZXMgaW4gdGhlIFRyaVRyeXBEQi4KCmBgYHtyIGFubm90fQp0dCA8LSBzbShsaWJyYXJ5KEV1UGF0aERCKSkKb3JnZGIgPC0gIm9yZy5McGFuYW1lbnNpcy5NSE9NQ09MODFMMTMudjQ2LmVnLmRiIgp0dCA8LSBzbShsaWJyYXJ5KG9yZ2RiLCBjaGFyYWN0ZXIub25seT1UUlVFKSkKcGFuX2RiIDwtIG9yZy5McGFuYW1lbnNpcy5NSE9NQ09MODFMMTMudjQ2LmVnLmRiCmFsbF9maWVsZHMgPC0gY29sdW1ucyhwYW5fZGIpCgphbGxfbHBfYW5ub3QgPC0gc20obG9hZF9vcmdkYl9hbm5vdGF0aW9ucygKICAgIHBhbl9kYiwKICAgIGtleXR5cGUgPSAiZ2lkIiwKICAgIGZpZWxkcyA9IGMoImFubm90X2dlbmVfZW50cmV6X2lkIiwgImFubm90X2dlbmVfbmFtZSIsCiAgICAgICAgICAgICAgICJhbm5vdF9zdHJhbmQiLCAiYW5ub3RfY2hyb21vc29tZSIsICJhbm5vdF9jZHNfbGVuZ3RoIiwKICAgICAgICAgICAgICAgImFubm90X2dlbmVfcHJvZHVjdCIpKSkkZ2VuZXMKCmxwX2dvIDwtIHNtKGxvYWRfb3JnZGJfZ28ocGFuX2RiKSkKbHBfbGVuZ3RocyA8LSBhbGxfbHBfYW5ub3RbLCBjKCJnaWQiLCAiYW5ub3RfY2RzX2xlbmd0aCIpXQpjb2xuYW1lcyhscF9sZW5ndGhzKSAgPC0gYygiSUQiLCAibGVuZ3RoIikKYWxsX2xwX2Fubm90W1siYW5ub3RfZ2VuZV9wcm9kdWN0Il1dIDwtIHRvbG93ZXIoYWxsX2xwX2Fubm90W1siYW5ub3RfZ2VuZV9wcm9kdWN0Il1dKQpvcnRob3MgPC0gc20oRXVQYXRoREI6OmV4dHJhY3RfZXVwYXRoX29ydGhvbG9ncyhkYiA9IHBhbl9kYikpCmBgYAoKIyBMb2FkIGEgZ2Vub21lCgpgYGB7ciBnZW5vbWV9Cm1ldGEgPC0gc20oRXVQYXRoREI6OmRvd25sb2FkX2V1cGF0aF9tZXRhZGF0YSh3ZWJzZXJ2aWNlPSJ0cml0cnlwZGIiKSkKbHBfZW50cnkgPC0gRXVQYXRoREI6OmdldF9ldXBhdGhfZW50cnkoc3BlY2llcz0iTGVpc2htYW5pYSBwYW5hbWVuc2lzIiwgbWV0YWRhdGE9bWV0YSkKY29sbmFtZXMobHBfZW50cnkpCnRlc3RpbmdfcGFuYW1lbnNpcyA8LSAiQlNHZW5vbWUuTGVpc2htYW5pYS5wYW5hbWVuc2lzLk1IT01DT0w4MUwxMy52NTMiCiMjIHRlc3RpbmdfcGFuYW1lbnNpcyA8LSBFdVBhdGhEQjo6bWFrZV9ldXBhdGhfYnNnZW5vbWUoZW50cnk9bHBfZW50cnksIGV1X3ZlcnNpb249InY0NiIpCmxpYnJhcnkoYXMuY2hhcmFjdGVyKHRlc3RpbmdfcGFuYW1lbnNpcyksIGNoYXJhY3Rlci5vbmx5PVRSVUUpCmdlbm9tZSA8LSBnZXQwKGFzLmNoYXJhY3Rlcih0ZXN0aW5nX3BhbmFtZW5zaXMpKQpgYGAKCiMgVE9ETzoKClJlc2VxdWVuY2Ugc2FtcGxlczogVE1SQzIwMDAyLCBUTVJDMjAwMDYsIFRNUkMyMDAwNCAobWF5YmUgVE1SQzIwMDA4IGFuZCBUTVJDMjAwMjkpCgojIEdlbmVyYXRlIEV4cHJlc3Npb25zZXRzIGFuZCBTYW1wbGUgRXN0aW1hdGlvbgoKVGhlIHByb2Nlc3Mgb2Ygc2FtcGxlIGVzdGltYXRpb24gdGFrZXMgdHdvIHByaW1hcnkgaW5wdXRzOgoKMS4gIFRoZSBzYW1wbGUgc2hlZXQsIHdoaWNoIGNvbnRhaW5zIGFsbCB0aGUgbWV0YWRhdGEgd2UgY3VycmVudGx5IGhhdmUgb24gaGFuZCwKICAgIGluY2x1ZGluZyBmaWxlbmFtZXMgZm9yIHRoZSBvdXRwdXRzIG9mICMzIGFuZCAjNCBhYm92ZS4KMi4gIFRoZSBnZW5lIGFubm90YXRpb25zLgoKQW4gZXhwcmVzc2lvbnNldCBpcyBhIGRhdGEgc3RydWN0dXJlIHVzZWQgaW4gUiB0byBleGFtaW5lIFJOQVNlcSBkYXRhLiAgSXQKaXMgY29tcHJpc2VkIG9mIGFubm90YXRpb25zLCBtZXRhZGF0YSwgYW5kIGV4cHJlc3Npb24gZGF0YS4gIEluIHRoZSBjYXNlIG9mIG91cgpwcm9jZXNzaW5nIHBpcGVsaW5lLCB0aGUgbG9jYXRpb24gb2YgdGhlIGV4cHJlc3Npb24gZGF0YSBpcyBwcm92aWRlZCBieSB0aGUKZmlsZW5hbWVzIGluIHRoZSBtZXRhZGF0YS4KClRoZSBmaXJzdCBsaW5lcyBvZiB0aGUgZm9sbG93aW5nIGJsb2NrIGNyZWF0ZSB0aGUgRXhwcmVzc2lvbnNldC4gIEFsbCBvZiB0aGUKZm9sbG93aW5nIGxpbmVzIHBlcmZvcm0gdmFyaW91cyBub3JtYWxpemF0aW9ucyBhbmQgZ2VuZXJhdGUgcGxvdHMgZnJvbSBpdC4KCiMjIE5vdGVzCgpUaGUgZm9sbG93aW5nIHNhbXBsZXMgYXJlIG11Y2ggbG93ZXIgY292ZXJhZ2U6CgoqIFRNUkMyMDAwMgoqIFRNUkMyMDAwNgoqIFRNUkMyMDAwNwoqIFRNUkMyMDAwOAoKMjAyMTA2MTA6IEkgbWFkZSBzb21lIG1hbnVhbCBjaGFuZ2VzIHRvIHRoZSBzYW1wbGUgc2hlZXQgd2hpY2ggSQpkb3dubG9hZGVkLCBmaWxsaW5nIGluIHNvbWUgenltb2RlbWUgd2l0aCAndW5rbm93bicKCiMjIFRPRE86CgoxLiAgRG8gdGhlIG11bHRpLWdlbmUgZmFtaWx5IHJlbW92YWwgcmlnaHQgaGVyZSBpbnN0ZWFkIG9mIHdheSBkb3duIGF0IHRoZSBib3R0b20KMi4gIEFkZCB6eW1vZGVtZSBzbnBzIHRvIHRoZSBhbm5vdGF0aW9uIGxhdGVyLgozLiAgU3RhcnQgcGh5bG9nZW5ldGljIGFuYWx5c2lzIG9mIHZhcmlhbnQgdGFibGUuCgpgYGB7ciBuZXdfc2FtcGxlc19oaXNhdH0KZGF0YV9zdHJ1Y3R1cmVzIDwtIGMoKQoKY29sb3JfY2hvaWNlcyA8LSBsaXN0KAogICAgInN0cmFpbiIgPSBsaXN0KAogICAgICAgICMjICJ6MS4wIiA9ICIjMzMzMzMzIiwgIyMgQ2hhbmdlZCB0aGlzIHRvICdicmF6JyB0byBtYWtlIGl0IGVhc2llciB0byBmaW5kIHRoZW0uCiAgICAgICAgInoyLjAiID0gIiM1NTU1NTUiLAogICAgICAgICJ6My4wIiA9ICIjNzc3Nzc3IiwKICAgICAgICAiejIuMSIgPSAiIzg3NDQwMCIsCiAgICAgICAgInoyLjIiID0gIiMwMDAwY2MiLAogICAgICAgICJ6Mi4zIiA9ICIjY2MwMDAwIiwKICAgICAgICAiejIuNCIgPSAiI2RmNzAwMCIsCiAgICAgICAgImJyYXoiID0gIiNjYzAwY2MiLAogICAgICAgICJ1bmtub3duIiA9ICIjY2JjYmNiIiwKICAgICAgICAibnVsbCIgPSAiIzAwMDAwMCIpLAogICAgImNmIiA9IGxpc3QoCiAgICAgICAgImN1cmUiID0gIiMwMDZmMDAiLAogICAgICAgICJmYWlsIiA9ICIjOWRmZmEwIiwKICAgICAgICAidW5rbm93biIgPSAiI2NiY2JjYiIsCiAgICAgICAgIm5vdGFwcGxpY2FibGUiID0gIiMwMDAwMDAiKSwKICAgICJzdXNjZXB0aWJpbGl0eSIgPSBsaXN0KAogICAgICAgICJyZXNpc3RhbnQiID0gIiM4NTYzYTciLAogICAgICAgICJzZW5zaXRpdmUiID0gIiM4ZDAwMDAiLAogICAgICAgICJhbWJpZ3VvdXMiID0gIiNjYmNiY2IiLAogICAgICAgICJ1bmtub3duIiA9ICIjNTU1NTU1IikpCmRhdGFfc3RydWN0dXJlcyA8LSBjKGRhdGFfc3RydWN0dXJlcywgImNvbG9yX2Nob2ljZXMiKQpgYGAKCmBgYHtyIGFsbF9kYXRhfQpzYW5pdGl6ZV9jb2x1bW5zIDwtIGMoInBhc3NhZ2VudW1iZXIiLCAiY2xpbmljYWxyZXNwb25zZSIsICJjbGluaWNhbGNhdGVnb3JpY2FsIiwKICAgICAgICAgICAgICAgICAgICAgICJ6eW1vZGVtZWNhdGVnb3JpY2FsIikKbHBfZXhwdCA8LSBjcmVhdGVfZXhwdChzYW1wbGVfc2hlZXQsCiAgICAgICAgICAgICAgICAgICAgICAgZ2VuZV9pbmZvID0gYWxsX2xwX2Fubm90LAogICAgICAgICAgICAgICAgICAgICAgIGFubm90YXRpb25fbmFtZSA9IG9yZ2RiLAogICAgICAgICAgICAgICAgICAgICAgIHNhdmVmaWxlID0gZ2x1ZTo6Z2x1ZSgicmRhL3RtcmMyX2xwX2V4cHRfYWxsX3Jhdy12e3Zlcn0ucmRhIiksCiAgICAgICAgICAgICAgICAgICAgICAgaWRfY29sdW1uID0gImhwZ2xpZGVudGlmaWVyIiwKICAgICAgICAgICAgICAgICAgICAgICBmaWxlX2NvbHVtbiA9ICJscGFuYW1lbnNpc3YzNmhpc2F0ZmlsZSIpICU+JQogIHNldF9leHB0X2NvbmRpdGlvbnMoZmFjdCA9ICJ6eW1vZGVtZWNhdGVnb3JpY2FsIikgJT4lCiAgc3Vic2V0X2V4cHQobm9uemVybyA9IDg1NTApICU+JQogIHN1YnNldF9leHB0KGNvdmVyYWdlID0gNTAwMDAwMCkgJT4lCiAgc2V0X2V4cHRfY29sb3JzKGNvbG9yX2Nob2ljZXNbWyJzdHJhaW4iXV0pICU+JQogIHNlbWFudGljX2V4cHRfZmlsdGVyKHNlbWFudGljID0gYygiYW1hc3RpbiIsICJncDYzIiwgImxlaXNobWFub2x5c2luIiksCiAgICAgICAgICAgICAgICAgICAgICAgc2VtYW50aWNfY29sdW1uID0gImFubm90X2dlbmVfcHJvZHVjdCIpICU+JQogIHNhbml0aXplX2V4cHRfbWV0YWRhdGEoY29sdW1ucyA9IHNhbml0aXplX2NvbHVtbnMpICU+JQogIHNldF9leHB0X2ZhY3RvcnMoY29sdW1ucyA9IHNhbml0aXplX2NvbHVtbnMsIGNsYXNzID0gImZhY3RvciIpCmRhdGFfc3RydWN0dXJlcyA8LSBjKGRhdGFfc3RydWN0dXJlcywgImxwX2V4cHQiKQpzYXZlKGxpc3QgPSAibHBfZXhwdCIsIGZpbGUgPSBnbHVlOjpnbHVlKCJyZGEvdG1yYzJfbHBfZXhwdF9hbGxfc2FuaXRpemVkLXZ7dmVyfS5yZGEiKSkKCnRhYmxlKHBEYXRhKGxwX2V4cHQpW1sienltb2RlbWVjYXRlZ29yaWNhbCJdXSkKdGFibGUocERhdGEobHBfZXhwdClbWyJjbGluaWNhbHJlc3BvbnNlIl1dKQpgYGAKCiMjIEJ5IFN1c2NlcHRpbGliaXR5CgpDb2x1bW4gJ1EnIGluIHRoZSBzYW1wbGUgc2hlZXQsIG1ha2UgYSBjYXRlZ29yaWNhbCB2ZXJzaW9uIG9mIGl0IHdpdGggdGhlc2UgcGFyYW1ldGVyczoKCiogMCA8PSB4IDw9IDM1IGlzIHJlc2lzdGFudAoqIDM2IDw9IHggPD0gNDggaXMgYW1iaWd1b3VzCiogNDkgPD0geCBpcyBzZW5zaXRpdmUKClRoZSBzYW5pdGl6ZV9wZXJjZW50KCkgZnVuY3Rpb24gc2Vla3MgdG8gbWFrZSB0aGUgcGVyY2VudGFnZSB2YWx1ZXMKcmVjb3JkZWQgYnkgZXhjZWwgbW9yZSByZWxpYWJsZS4gIFVuZm9ydHVuYXRlbHksIHNvbWV0aW1lcyBleGNlbApkaXNwbGF5cyB0aGUgdmFsdWUgJzQ5JScgd2hlbiB0aGUgaW5mb3JtYXRpb24gcmVjb3JkZWQgaW4gdGhlCndvcmtzaGVldCBpcyBhbnkgb25lIG9mIHRoZSBmb2xsb3dpbmc6CgoqICc0OSUKKiAwLjQ5CiogIjAuNDkiCgpgYGB7ciBzdXNjZXB0aWJpbGl0eV9oaXN0b3JpY2FsfQpzdCA8LSBwRGF0YShscF9leHB0KVtbInN1c2NlcHRpYmlsaXR5aW5mZWN0aW9ucmVkdWN0aW9uMzJ1Z21sc2J2aGlzdG9yaWNhbGRhdGEiXV0Kc3RhcnRpbmcgPC0gc2FuaXRpemVfcGVyY2VudChzdCkKc3QKc3RhcnRpbmcKc3VzX2NhdGVnb3JpY2FsIDwtIHN0YXJ0aW5nCm5hX2lkeCA8LSBpcy5uYShzdGFydGluZykKc3VtKG5hX2lkeCkKc3VzX2NhdGVnb3JpY2FsW25hX2lkeF0gPC0gInVua25vd24iCgpyZXNpc3RfaWR4IDwtIHN0YXJ0aW5nIDw9IDAuMzUKc3VzX2NhdGVnb3JpY2FsW3Jlc2lzdF9pZHhdIDwtICJyZXNpc3RhbnQiCmluZGV0ZXJtaW5hbnRfaWR4IDwtIHN0YXJ0aW5nID49IDAuMzYgJiBzdGFydGluZyA8PSAwLjQ4CnN1c19jYXRlZ29yaWNhbFtpbmRldGVybWluYW50X2lkeF0gPC0gImFtYmlndW91cyIKc3VzY2VwdGlibGVfaWR4IDwtIHN0YXJ0aW5nID49IDAuNDkKc3VzX2NhdGVnb3JpY2FsW3N1c2NlcHRpYmxlX2lkeF0gPC0gInNlbnNpdGl2ZSIKCnN1c19jYXRlZ29yaWNhbCA8LSBhcy5mYWN0b3Ioc3VzX2NhdGVnb3JpY2FsKQpwRGF0YShscF9leHB0KVtbInN1c19jYXRlZ29yeV9oaXN0b3JpY2FsIl1dIDwtIHN1c19jYXRlZ29yaWNhbAp0YWJsZShzdXNfY2F0ZWdvcmljYWwpCmBgYAoKYGBge3Igc3VzY2VwdGliaWxpdHlfY3VycmVudH0Kc3RhcnRpbmdfY3VycmVudCA8LSBzYW5pdGl6ZV9wZXJjZW50KHBEYXRhKGxwX2V4cHQpW1sic3VzY2VwdGliaWxpdHlpbmZlY3Rpb25yZWR1Y3Rpb24zMnVnbWxzYnZjdXJyZW50ZGF0YSJdXSkKc3VzX2NhdGVnb3JpY2FsX2N1cnJlbnQgPC0gc3RhcnRpbmdfY3VycmVudApuYV9pZHggPC0gaXMubmEoc3RhcnRpbmdfY3VycmVudCkKc3VtKG5hX2lkeCkKc3VzX2NhdGVnb3JpY2FsX2N1cnJlbnRbbmFfaWR4XSA8LSAidW5rbm93biIKCnJlc2lzdF9pZHggPC0gc3RhcnRpbmdfY3VycmVudCA8PSAwLjM1CnN1c19jYXRlZ29yaWNhbF9jdXJyZW50W3Jlc2lzdF9pZHhdIDwtICJyZXNpc3RhbnQiCmluZGV0ZXJtaW5hbnRfaWR4IDwtIHN0YXJ0aW5nX2N1cnJlbnQgPj0gMC4zNiAmIHN0YXJ0aW5nX2N1cnJlbnQgPD0gMC40OApzdXNfY2F0ZWdvcmljYWxfY3VycmVudFtpbmRldGVybWluYW50X2lkeF0gPC0gImFtYmlndW91cyIKc3VzY2VwdGlibGVfaWR4IDwtIHN0YXJ0aW5nX2N1cnJlbnQgPj0gMC40OQpzdXNfY2F0ZWdvcmljYWxfY3VycmVudFtzdXNjZXB0aWJsZV9pZHhdIDwtICJzZW5zaXRpdmUiCnN1c19jYXRlZ29yaWNhbF9jdXJyZW50IDwtIGFzLmZhY3RvcihzdXNfY2F0ZWdvcmljYWxfY3VycmVudCkKCnBEYXRhKGxwX2V4cHQpW1sic3VzX2NhdGVnb3J5X2N1cnJlbnQiXV0gPC0gc3VzX2NhdGVnb3JpY2FsX2N1cnJlbnQKdGFibGUoc3VzX2NhdGVnb3JpY2FsX2N1cnJlbnQpCmBgYAoKYGBge3IgcHJlX3F1ZXN0aW9uc30KbHBfc3RyYWluIDwtIGxwX2V4cHQgJT4lCiAgc2V0X2V4cHRfYmF0Y2hlcyhmYWN0ID0gc3VzX2NhdGVnb3JpY2FsX2N1cnJlbnQpICU+JQogIHNldF9leHB0X2NvbG9ycyhjb2xvcl9jaG9pY2VzW1sic3RyYWluIl1dKQp0YWJsZShwRGF0YShscF9zdHJhaW4pW1siY29uZGl0aW9uIl1dKQpzYXZlKGxpc3QgPSAibHBfc3RyYWluIiwgZmlsZSA9IGdsdWU6OmdsdWUoInJkYS90bXJjMl9scF9zdHJhaW4tdnt2ZXJ9LnJkYSIpKQpkYXRhX3N0cnVjdHVyZXMgPC0gYyhkYXRhX3N0cnVjdHVyZXMsICJscF9zdHJhaW4iKQoKbHBfdHdvX3N0cmFpbnMgPC0gc3Vic2V0X2V4cHQobHBfc3RyYWluLCBzdWJzZXQgPSAiY29uZGl0aW9uPT0nejIuMyd8Y29uZGl0aW9uPT0nejIuMiciKQpzYXZlKGxpc3QgPSAibHBfdHdvX3N0cmFpbnMiLAogICAgIGZpbGUgPSBnbHVlOjpnbHVlKCJyZGEvdG1yYzJfbHBfdHdvX3N0cmFpbnMtdnt2ZXJ9LnJkYSIpKQpkYXRhX3N0cnVjdHVyZXMgPC0gYyhkYXRhX3N0cnVjdHVyZXMsICJscF90d29fc3RyYWlucyIpCmBgYAoKIyMgQnkgQ3VyZS9GYWlsIHN0YXR1cwoKYGBge3IgY2Zfc3RhdHVzfQpscF9jZiA8LSBzZXRfZXhwdF9jb25kaXRpb25zKGxwX2V4cHQsIGZhY3QgPSAiY2xpbmljYWxjYXRlZ29yaWNhbCIpICU+JQogIHNldF9leHB0X2JhdGNoZXMoZmFjdCA9IHN1c19jYXRlZ29yaWNhbF9jdXJyZW50KSAlPiUKICBzZXRfZXhwdF9jb2xvcnMoY29sb3JfY2hvaWNlc1tbImNmIl1dKQp0YWJsZShwRGF0YShscF9jZilbWyJjb25kaXRpb24iXV0pCmRhdGFfc3RydWN0dXJlcyA8LSBjKGRhdGFfc3RydWN0dXJlcywgImxwX2NmIikKc2F2ZShsaXN0ID0gImxwX2NmIiwKICAgICBmaWxlID0gZ2x1ZTo6Z2x1ZSgicmRhL3RtcmMyX2xwX2NmLXZ7dmVyfS5yZGEiKSkKCmxwX2NmX2tub3duIDwtIHN1YnNldF9leHB0KGxwX2NmLCBzdWJzZXQ9ImNvbmRpdGlvbiE9J3Vua25vd24nIikKZGF0YV9zdHJ1Y3R1cmVzIDwtIGMoZGF0YV9zdHJ1Y3R1cmVzLCAibHBfY2Zfa25vd24iKQpzYXZlKGxpc3QgPSAibHBfY2Zfa25vd24iLAogICAgIGZpbGUgPSBnbHVlOjpnbHVlKCJyZGEvdG1yYzJfbHBfY2Zfa25vd24tdnt2ZXJ9LnJkYSIpKQpgYGAKCmBgYHtyIHN1c2NlcHRpYmlsaXR5X3BjYX0KbHBfc3VzY2VwdGliaWxpdHkgPC0gc2V0X2V4cHRfY29uZGl0aW9ucyhscF9leHB0LCBmYWN0ID0gInN1c19jYXRlZ29yeV9jdXJyZW50IikgJT4lCiAgc2V0X2V4cHRfYmF0Y2hlcyhmYWN0ID0gImNsaW5pY2FsY2F0ZWdvcmljYWwiKSAlPiUKICBzZXRfZXhwdF9jb2xvcnMoY29sb3JzID0gY29sb3JfY2hvaWNlc1tbInN1c2NlcHRpYmlsaXR5Il1dKQpzYXZlKGxpc3QgPSAibHBfc3VzY2VwdGliaWxpdHkiLAogICAgIGZpbGUgPSBnbHVlOjpnbHVlKCJyZGEvdG1yYzJfbHBfc3VzY2VwdGliaWxpdHktdnt2ZXJ9LnJkYSIpKQpkYXRhX3N0cnVjdHVyZXMgPC0gYyhkYXRhX3N0cnVjdHVyZXMsICJscF9zdXNjZXB0aWJpbGl0eSIpCmBgYAoKVE9ETzogRG8gdGhpcyB3aXRoIGFuZCB3aXRob3V0IHN2YSBhbmQgY29tcGFyZSB0aGUgcmVzdWx0cy4KCmBgYHtyIHp5bW9fZGUsIGZpZy5zaG93ID0gImhpZGUifQpscF96eW1vIDwtIHN1YnNldF9leHB0KGxwX2V4cHQsIHN1YnNldCA9ICJjb25kaXRpb249PSd6Mi4yJ3xjb25kaXRpb249PSd6Mi4zJyIpCmRhdGFfc3RydWN0dXJlcyA8LSBjKGRhdGFfc3RydWN0dXJlcywgImxwX3p5bW8iKQpzYXZlKGxpc3QgPSAibHBfenltbyIsCiAgICAgZmlsZSA9IGdsdWU6OmdsdWUoInJkYS90bXJjMl9scF96eW1vLXZ7dmVyfS5yZGEiKSkKYGBgCgpgYGB7ciBjb21iaW5lX21hY3JvcGhhZ2V9Cm1hY3JvcGhhZ2Vfc2hlZXQgPC0gInNhbXBsZV9zaGVldHMvdG1yYzJfbWFjcm9waGFnZV9zYW1wbGVzXzIwMjIwMy54bHN4Igpoc19tYWNyb3BoYWdlIDwtIGNyZWF0ZV9leHB0KG1hY3JvcGhhZ2Vfc2hlZXQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZV9jb2x1bW49ImxwYW5hbWVuc2lzdjM2aGlzYXRmaWxlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW5lX2luZm89YWxsX2xwX2Fubm90LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhdmVmaWxlID0gZ2x1ZTo6Z2x1ZSgicmRhL2hzX21hY3JvcGhhZ2Utdnt2ZXJ9LnJkYSIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFubm90YXRpb249Im9yZy5McGFuYW1lbnNpcy5NSE9NQ09MODFMMTMudjQ2LmVnLmRiIikgJT4lCiAgc2V0X2V4cHRfY29uZGl0aW9ucyhmYWN0PSJtYWNyb3BoYWdlenltb2RlbWUiKSAlPiUKICBzZXRfZXhwdF9iYXRjaGVzKGZhY3Q9Im1hY3JvcGhhZ2V0cmVhdG1lbnQiKQpkYXRhX3N0cnVjdHVyZXMgPC0gYyhkYXRhX3N0cnVjdHVyZXMsICJoc19tYWNyb3BoYWdlIikKYGBgCgpgYGB7ciBvbGRuZXdfdmFyaWFudHMsIGV2YWw9VFJVRX0KbHBfcHJldmlvdXMgPC0gY3JlYXRlX2V4cHQoInNhbXBsZV9zaGVldHMvdG1yYzJfc2FtcGxlc18yMDE5MTIwMy54bHN4IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZV9jb2x1bW4gPSAidG9waGF0MmZpbGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBzYXZlZmlsZSA9IGdsdWU6OmdsdWUoInJkYS9scF9wcmV2aW91cy12e3Zlcn0ucmRhIikpCmRhdGFfc3RydWN0dXJlcyA8LSBjKGRhdGFfc3RydWN0dXJlcywgImxwX3ByZXZpb3VzIikKdHQgPC0gbHBfcHJldmlvdXMkZXhwcmVzc2lvbnNldApyb3duYW1lcyh0dCkgPC0gZ3N1YihwYXR0ZXJuID0gIl5leG9uXyIsIHJlcGxhY2VtZW50ID0gIiIsIHggPSByb3duYW1lcyh0dCkpCnJvd25hbWVzKHR0KSA8LSBnc3ViKHBhdHRlcm4gPSAiXFwuMSQiLCByZXBsYWNlbWVudCA9ICIiLCB4ID0gcm93bmFtZXModHQpKQpscF9wcmV2aW91cyRleHByZXNzaW9uc2V0IDwtIHR0CnJtKHR0KQpgYGAKCiMjIENyZWF0ZSB0aGUgU05QIGV4cHJlc3Npb25zZXQKCmBgYHtyIGNvdW50X2V4cHRfb2xkX25ld30KIyMgVGhlIG5leHQgbGluZSBkcm9wcyB0aGUgc2FtcGxlcyB3aGljaCBhcmUgbWlzc2luZyB0aGUgU05QIHBpcGVsaW5lLgpscF9zbnAgPC0gc3Vic2V0X2V4cHQobHBfZXhwdCwgc3Vic2V0PSIhaXMubmEocERhdGEobHBfZXhwdClbWydmcmVlYmF5ZXNzdW1tYXJ5J11dKSIpCm5ld19zbnBzIDwtIGNvdW50X2V4cHRfc25wcyhscF9zbnAsIGFubm90X2NvbHVtbiA9ICJmcmVlYmF5ZXNzdW1tYXJ5Iiwgc25wX2NvbHVtbj0iUEFJUkVEIikKb2xkX3NucHMgPC0gY291bnRfZXhwdF9zbnBzKGxwX3ByZXZpb3VzLCBhbm5vdF9jb2x1bW4gPSAiYmNmdGFibGUiLCBzbnBfY29sdW1uID0gMikKCnNhdmUobGlzdCA9ICJscF9zbnAiLAogICAgIGZpbGUgPSBnbHVlOjpnbHVlKCJyZGEvbHBfc25wLXZ7dmVyfS5yZGEiKSkKZGF0YV9zdHJ1Y3R1cmVzIDwtIGMoZGF0YV9zdHJ1Y3R1cmVzLCAibHBfc25wIikKc2F2ZShsaXN0ID0gIm5ld19zbnBzIiwKICAgICBmaWxlID0gZ2x1ZTo6Z2x1ZSgicmRhL25ld19zbnBzLXZ7dmVyfS5yZGEiKSkKZGF0YV9zdHJ1Y3R1cmVzIDwtIGMoZGF0YV9zdHJ1Y3R1cmVzLCAibmV3X3NucHMiKQpzYXZlKGxpc3QgPSAib2xkX3NucHMiLAogICAgIGZpbGUgPSBnbHVlOjpnbHVlKCJyZGEvb2xkX3NucHMtdnt2ZXJ9LnJkYSIpKQpkYXRhX3N0cnVjdHVyZXMgPC0gYyhkYXRhX3N0cnVjdHVyZXMsICJvbGRfc25wcyIpCgpub256ZXJvX3NucHMgPC0gZXhwcnMobmV3X3NucHMpICE9IDAKY29sU3Vtcyhub256ZXJvX3NucHMpCmBgYAoKYGBge3IgY29tYmluZV9vbGRfc25wcywgZXZhbD1UUlVFfQojIyBNeSBvbGRfc25wcyBpcyB1c2luZyBhbiBvbGRlciBhbm5vdGF0aW9uIGluY29ycmVjdGx5LCBzbyBmaXggaXQgaGVyZToKQmlvYmFzZTo6YW5ub3RhdGlvbihvbGRfc25wcyRleHByZXNzaW9uc2V0KSA8LSBCaW9iYXNlOjphbm5vdGF0aW9uKG5ld19zbnBzJGV4cHJlc3Npb25zZXQpCmJvdGhfc25wcyA8LSBjb21iaW5lX2V4cHRzKG5ld19zbnBzLCBvbGRfc25wcykKc2F2ZShsaXN0ID0gImJvdGhfc25wcyIsCiAgICAgZmlsZSA9IGdsdWU6OmdsdWUoInJkYS9ib3RoX3NucHMtdnt2ZXJ9LnJkYSIpKQpkYXRhX3N0cnVjdHVyZXMgPC0gYyhkYXRhX3N0cnVjdHVyZXMsICJib3RoX3NucHMiKQpgYGAKCiMgU2F2ZSBhbGwgZGF0YSBzdHJ1Y3R1cmVzIGludG8gb25lIGJpZyBwaWxlCgpgYGB7ciBzYXZlX2FsbF9kYXRhfQpzYXZlKGxpc3QgPSBkYXRhX3N0cnVjdHVyZXMsIGZpbGUgPSBnbHVlOjpnbHVlKCJyZGEvdG1yYzJfZGF0YV9zdHJ1Y3R1cmVzLXZ7dmVyfS5yZGEiKSkKYGBgCgpgYGB7ciBzYXZlbWV9CnBhbmRlcjo6cGFuZGVyKHNlc3Npb25JbmZvKCkpCm1lc3NhZ2UocGFzdGUwKCJUaGlzIGlzIGhwZ2x0b29scyBjb21taXQ6ICIsIGdldF9naXRfY29tbWl0KCkpKQptZXNzYWdlKHBhc3RlMCgiU2F2aW5nIHRvICIsIHNhdmVmaWxlKSkKdG1wIDwtIHNtKHNhdmVtZShmaWxlbmFtZSA9IHNhdmVmaWxlKSkKYGBgCgpgYGB7ciBsb2FkbWVfYWZ0ZXIsIGV2YWwgPSBGQUxTRX0KdG1wIDwtIGxvYWRtZShmaWxlbmFtZSA9IHNhdmVmaWxlKQpgYGAK