1 Introduction

The set of analyses performed in tmrc3 sample estimation has become unorganized and difficult to follow. This is intended to start at the level of broad organization before stepping into the analyses.

1.1 Goals

These samples are from patients who either successfully cleared a Leishmania panamensis infection following treatment, or did not. They include biopsies from each patient along with purifications for Monocytes, Neutrophils, and Eosinophils. When possible, this process was repeated over three visits; but some patients did not return for the second or third visit.

The over-arching goal is to look for attributes(most likely genes) which distinguish patients who do and do not cure the infection after treatment. If possible, these will be apparent on the first visit.

1.2 Relevant Metadata

The metadata factors (in no particular order) of the experiment are:

  1. Visit. 1, 2, or 3.
  2. Patient.
  3. Clinical outcome: cure or fail. This includes the population of patients who did not return and are labeled ‘lost’. This is, by definition, confounded with patient.
  4. Drug treatment. Most of the patients were treated with an antimonial, but a few were treated with miltefosine.
  5. Cell type or biopsy.

Metadata was also collected for the patients and there are many factors which have potential to affect the outcome. These analyses will generally remain agnostic for these factors, which include (among other things):

  1. sex
  2. ethnicity
  3. age
  4. ulcer/lesion attributes (by visit)
  5. amount of time spent with infection
  6. Adherence to treatment, which is a metric of how much of the prescribed dosage was actually received by the patient.

1.3 Libraries, sequencing, mapping, quantification

The samples used in these analyses were all collected, purified, and libraries generated by the scientists/doctors at CIDEIM. The sequencing libraries were generated via the TruSeq non-stranded library kit and sequenced either at JHU or UMD; earlier samples were single-ended, but most were paired.

All samples were trimmed with trimomatic using the same set of parameters. All mapping was performed with hisat2 version 2.2.1. Quantifications were also performed with salmon version 1.2.0. The reference genome used was hg38 100 (released 202004). When samples were mapped against L.panamensis, the TriTrypDB version 36 reference was used. The set of annotations were therefore limited to ensembl’s 2020 release. The early samples were actually first mapped with hg38 91 and later redone.

1.4 Types of analyses included

This document will limit itself to a set of canonical RNAseq analyses:

  • Create files containing the raw data to facilitate sharing the data.
  • Plot metrics of the data to demonstrate the sequencing quality and clustering of the samples under the various conditions examined and normalizations employed.
  • Perform differential expression analyses for the metadata factors of interest alongside likelihood ratio tests for factors like celltype and time.
  • Given the sets of over/under expressed genes observed in the various DE methods, it will perform the likely gene set tests for over represented gene ontology groups, reactome, etc.
  • The raw data will be passed to gene set variance analyses to see if there are groups of genes overrepresented in other experiments.

1.5 Metadata collection

There are two metadata sources:

  1. The online sample sheet, which I periodically update and download into the ‘sample_sheets/’ directory.
  2. The crf metadata, describing the individual patients.
samplesheet <- "sample_sheets/tmrc3_samples_202205.xlsx"
crf_metadata <- "sample_sheets/20220509_EXP_ESPECIAL_TMRC3_V2.xlsx"

2 Random notes

  1. Note from Maria Adelaida: Some chemokines are suggestive of Eosinophil recruitment.

3 Annotation Collection

The primary annotation sources are:

  1. Ensembl’s biomart archive from 2020 for human annotations.
  2. The TriTrypDB release 36 for parasite annotations.

Both provide GO data. They also provide helpful links to other data sources. For the moment, we are focusing on the human annotations.

3.1 Gene annotations

These analyses have focused on gene-level abundances/differences. Thus, when htseq-count was invoked against the hisat2-based mappings, parameters were chosen to count genes rather than transcripts. Similarly, when salmon counts were used via tximport, a mapping of genes to transcripts was used to collapse the matrix to gene-level abundances. This decision may be revisited.

hs_annot <- load_biomart_annotations(year="2020", month="jan")
## The biomart annotations file already exists, loading from it.
hs_annot <- hs_annot[["annotation"]]
hs_annot[["transcript"]] <- paste0(rownames(hs_annot), ".", hs_annot[["version"]])
rownames(hs_annot) <- make.names(hs_annot[["ensembl_gene_id"]], unique=TRUE)
tx_gene_map <- hs_annot[, c("transcript", "ensembl_gene_id")]
summary(hs_annot)
##  ensembl_transcript_id ensembl_gene_id       version     transcript_version
##  Length:227784         Length:227784      Min.   : 1.0   Min.   : 1.00     
##  Class :character      Class :character   1st Qu.: 6.0   1st Qu.: 1.00     
##  Mode  :character      Mode  :character   Median :12.0   Median : 1.00     
##                                           Mean   :10.7   Mean   : 3.08     
##                                           3rd Qu.:15.0   3rd Qu.: 5.00     
##                                           Max.   :28.0   Max.   :17.00     
##                                                                            
##  hgnc_symbol        description        gene_biotype         cds_length    
##  Length:227784      Length:227784      Length:227784      Min.   :     3  
##  Class :character   Class :character   Class :character   1st Qu.:   357  
##  Mode  :character   Mode  :character   Mode  :character   Median :   694  
##                                                           Mean   :  1140  
##                                                           3rd Qu.:  1446  
##                                                           Max.   :107976  
##                                                           NA's   :127222  
##  chromosome_name       strand          start_position      end_position     
##  Length:227784      Length:227784      Min.   :5.77e+02   Min.   :6.47e+02  
##  Class :character   Class :character   1st Qu.:3.11e+07   1st Qu.:3.12e+07  
##  Mode  :character   Mode  :character   Median :6.04e+07   Median :6.06e+07  
##                                        Mean   :7.41e+07   Mean   :7.42e+07  
##                                        3rd Qu.:1.09e+08   3rd Qu.:1.09e+08  
##                                        Max.   :2.49e+08   Max.   :2.49e+08  
##                                                                             
##   transcript       
##  Length:227784     
##  Class :character  
##  Mode  :character  
##                    
##                    
##                    
## 

3.2 Gene ontology data

The set of GO categories has not been limited to the 2020 data at the time of this writing. The GO categories is collected along with lengths for goseq. The other methods either have built-in databases of human data (gProfiler) or support orgDB data (org.Hs.eg.db) (clusterProfiler/topGO/gostats).

hs_go <- load_biomart_go()[["go"]]
## The biomart annotations file already exists, loading from it.
hs_length <- hs_annot[, c("ensembl_gene_id", "cds_length")]
colnames(hs_length) <- c("ID", "length")

4 Dataset: Create the parent data structure of all samples

Before we do any of the following subsets/analyses of the data, we need to collect it all in one place. Let’s do that here and name it ‘hs_expt’, it will comprise the full set of human data. When we cull some samples it will be renamed to ‘hs_valid’.

sanitize_columns <- c("visitnumber", "clinicaloutcome", "donor",
                      "typeofcells", "clinicalpresentation", "drug",
                      "condition", "batch")
hs_expt <- create_expt(samplesheet,
                       file_column="hg38100hisatfile",
                       savefile=glue::glue("rda/hs_expt_all-v{ver}.rda"),
                       gene_info=hs_annot) %>%
  exclude_genes_expt(column="gene_biotype", method="keep",
                     pattern="protein_coding", meta_column="ncrna_lost") %>%
  sanitize_expt_metadata(columns=sanitize_columns) %>%
  set_expt_factors(columns=sanitize_columns, class="factor") %>%
  set_expt_conditions(fact="clinicaloutcome") %>%
  set_expt_batches(fact="visitnumber")
## Reading the sample metadata.
## Dropped 69 rows from the sample metadata because the sample ID is blank.
## The sample definitions comprises: 254 rows(samples) and 84 columns(metadata fields).
## Warning in create_expt(samplesheet, file_column = "hg38100hisatfile", savefile =
## glue::glue("rda/hs_expt_all-v{ver}.rda"), : Some samples were removed when cross
## referencing the samples against the count data.
## Matched 21447 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 21481 features and 246 samples.
## remove_genes_expt(), before removal, there were 21481 genes, now there are 19923.
## There are 8 samples which kept less than 90 percent counts.
## TMRC30015 TMRC30017 TMRC30019 TMRC30044 TMRC30045 TMRC30154 TMRC30269 TMRC30241 
##     79.19     85.66     89.69     80.29     73.28     83.16     89.18     89.37
## The following should make visit 1 the largest if one uses that column as a size factor when plotting.
meta <- pData(hs_expt) %>%
  mutate(visitnumber = fct_relevel(visitnumber, c("notapplicable", "3", "2", "1")))
pData(hs_expt) <- meta

The above block did the following:

  1. Creates an expressionset using the ‘hg38100hisatfile’ column from the most recently downloaded sample sheet (the column’s name has any punctuation/spaces/capitals/etc removed) and the set of human annotations downloaded above.
  2. This expressionset is passed to a filter which pulls out only the protein_coding genes and uses the information from that process to add a new metadata column called ‘ncrna_lost’. Thus it keeps a tally of the number of reads lost in the filter and adds it to the sample sheet.
  3. It is passed to a function which sanitizes the metadata (there were a couple of entries which said ‘cure’ instead of ‘Cure’ or vice versa) and similarly removes problematic characters (in a few instances spaces follow important metadata ‘failure’).
  4. Passed to a function which sets some columns explicitly to factors instead of characters.
  5. Sets the experimental ‘condition’ to the factor of cure vs. fail.
  6. Sets the experimental ‘batch’ to visit number.
  7. Resets the levels of the visit number so that the samples which were ‘notapplicable’ are logically before visit 1 which is before 2 before 3 (Thus if we plot with visits as the size of a glyph, visit 1 will be the largest).

4.1 Add the CRF patient metadata

Merge in the clinician’s metadata. I worry a little that this might not be allowed for dbGap data, but if it is a problem I suspect we can just remove the bad columns from it. Also note that I rarely use the join function, but it is somewhat required here because I do not want to risk shuffling the metadata when I add the new metadata, which comes from a spreadsheet sorted by patient, not sample. In doing this I therefore just created a new column ‘join’ which contains the shared information, e.g. the patient ID from the existing metadata and the same ID from the CRF file which has been coerced into lowercase.

hs_pd <- pData(hs_expt)
start <- rownames(hs_pd)
hs_crf <- openxlsx::read.xlsx(crf_metadata)
hs_crf[["join"]] <- tolower(hs_crf[["codigo_paciente"]])
hs_pd[["join"]] <- hs_pd[["tubelabelorigin"]]
test <- plyr::join(hs_pd, hs_crf, by="join")
test[["join"]] <- NULL
rownames(test) <- rownames(hs_pd)
na_idx <- is.na(test)
test[na_idx] <- "undefined"
pData(hs_expt) <- test

The above block did the following:

  1. Extract the metadata and made a character vector of the rownames (e.g. the sample IDs).
  2. Created a table of the clinical metadata from the file I downloaded.
  3. Created a ‘join’ column from both the existing metadata and the clinical metadata which is the patient code, using whatever the column names were in each sheet.
  4. Joined the two tables using this information. The join function is explicitly used in this context to make sure that the row-order of the entries does not change.
  5. Got rid of any entries in the new table which are NA.
  6. Replaced the metadata of the expressionset with this new, larger table.

4.2 Sanity check, clinical outcome vs. CRF data

In our shared online sample sheet there is a clinical outcome column which should match the final CRF column ‘ef_lc_estado_final_estudio’ with the caveat that the CRF data is numeric:

0: curacion definitiva 1: fail terapeutica 2: perdida druante el seguimiento 3: excludio durante el estudio

two_columns <- pData(hs_expt)[, c("clinicaloutcome", "ef_lc_estado_final_estudio")]
undef_idx <- two_columns[[2]] == "undefined"
two_columns <- two_columns[!undef_idx, ]
two_columns[["rewritten"]] <- "undef"
cure_idx <- two_columns[[2]] == 0
two_columns[cure_idx, "rewritten"] <- "cure"
fail_idx <- two_columns[[2]] == 1
two_columns[fail_idx, "rewritten"] <- "failure"
lost_idx <- two_columns[[2]] == 2
two_columns[lost_idx, "rewritten"] <- "lost"
same_idx <- two_columns[["clinicaloutcome"]] == two_columns[["rewritten"]]
broken <- two_columns[!same_idx, ]
broken
##           clinicaloutcome ef_lc_estado_final_estudio rewritten
## TMRC30237            cure                          1   failure
## TMRC30238            cure                          1   failure

4.3 Summarize: Collect sample numbers before filtering

There are some metadata factors for which I think it will be nice to see the numbers before and after our filters. The following shows how many samples we have of the primary types before filtering.

dim(pData(hs_expt))
## [1] 246 144
table(pData(hs_expt)$drug)
## 
##    antimony miltefosine        none 
##         216           8          22
table(pData(hs_expt)$clinic)
## 
##      Cali    Tumaco undefined 
##        75       143        28
table(pData(hs_expt)$typeofcells)
## 
##      biopsy eosinophils macrophages   monocytes neutrophils       pbmcs 
##          21          45          28          74          72           6
table(pData(hs_expt)$visit)
## 
## notapplicable             3             2             1 
##            28            54            56           108
summary(as.numeric(pData(hs_expt)$eb_lc_tiempo_evolucion))
## Warning in summary(as.numeric(pData(hs_expt)$eb_lc_tiempo_evolucion)): NAs
## introduced by coercion
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##    2.00    4.00    6.00    8.25   12.00   21.00      36
summary(as.numeric(pData(hs_expt)$eb_lc_tto_mcto_glucan_dosis))
## Warning in summary(as.numeric(pData(hs_expt)$eb_lc_tto_mcto_glucan_dosis)): NAs
## introduced by coercion
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##    13.0    14.0    19.0    54.6    20.0   999.0      36
summary(as.numeric(pData(hs_expt)$v3_lc_ejey_lesion_mm_1))
## Warning in summary(as.numeric(pData(hs_expt)$v3_lc_ejey_lesion_mm_1)): NAs
## introduced by coercion
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##     0.0     7.4    32.0   269.5   771.8   999.0      36
summary(as.numeric(pData(hs_expt)$v3_lc_lesion_area_1))
## Warning in summary(as.numeric(pData(hs_expt)$v3_lc_lesion_area_1)): NAs
## introduced by coercion
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##       0     226     999    2412    3016   16965      36
summary(as.numeric(pData(hs_expt)$v3_lc_ejex_ulcera_mm_1))
## Warning in summary(as.numeric(pData(hs_expt)$v3_lc_ejex_ulcera_mm_1)): NAs
## introduced by coercion
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##     0.0     0.0     9.1   259.6   761.7   999.0      36
table(pData(hs_expt)$eb_lc_sexo)
## 
##         1         2 undefined 
##       173        37        36
table(pData(hs_expt)$eb_lc_etnia)
## 
##         1         2         3 undefined 
##       101        62        47        36
summary(as.numeric(pData(hs_expt)$edad))
## Warning in summary(as.numeric(pData(hs_expt)$edad)): NAs introduced by coercion
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##    18.0    25.0    28.5    30.7    36.0    51.0      36
table(pData(hs_expt)$eb_lc_peso)
## 
##       100     100.8      53.9      55.9      57.9        58      58.1      58.3 
##         5         2         9         2         2         6         7        10 
##      58.6        59      59.6        62        63        67      69.4        72 
##        13        14         1         8         6         6        10         9 
##      74.7        75      75.6      76.5        77        78      79.2        82 
##         3         2         3         3        18        10        10         9 
##      83.3      83.4      86.4        87        89      93.3 undefined 
##         4        10         9         3         9         7        36
table(pData(hs_expt)$eb_lc_estatura)
## 
##       145       152       154       155       156       158       159       160 
##         6         1        10         9         6        17         2         6 
##       162       163       164       165       166       167       169       172 
##        10         9        15        12        19         3         2        10 
##       173       174       175       176       177       182       183 undefined 
##         9        32         2         1        10         9        10        36
table(pData(hs_expt)$ef_lc_estado_final_estudio)
## 
##         0         1         2 undefined 
##       130        64        16        36
table(pData(hs_expt)$clinicaloutcome)
## 
##          cure       failure          lost notapplicable 
##           132            62            16            36

4.4 Define desired colors for the various subsets

There are lots of ways which we will categorize the data, here are some potential color choices for them.

cf_colors <- list(
    "cure" = "#998EC3",
    "failure" = "#F1A340")
type_visit_colors <- list(
    "monocytes_v1" = "#DD1C77",
    "monocytes_v2" = "#C994C7",
    "monocytes_v3" = "#E7E1EF",
    "eosinophils_v1" = "#31A354",
    "eosinophils_v2" = "#ADDD8E",
    "eosinophils_v3" = "#F7FCD9",
    "neutrophils_v1" = "#3182BD",
    "neutrophils_v2" = "#9ECAE1",
    "neutrophils_v3" = "#DEEBF7",
    "biopsy_v1" = "#D95F0E")
type_colors <- list(
    "monocytes" = "#DD1C77",
    "eosinophils" = "#31A354",
    "neutrophils" = "#3182BD",
    "biopsy" = "#D95F0E")
visit_colors <- list()
cf_type_colors <- list(
    cure_biopsy = "#D95F0E",
    failure_biopsy = "#FEC44F",
    cure_monocytes = "#DD1C77",
    failure_monocytes = "#C994C7",
    cure_eosinophils = "#31A354",
    failure_eosinophils = "#ADDD8E",
    cure_neutrophils = "#3182BD",
    failure_neutrophils = "#9ECAE1")

5 Define the starting data

The following block creates the primary dataset, which is the parent of everything which follows.

5.1 Set our initial coverage goal

There exists a baseline coverage below which we do not wish to fall. One likely way to approach it heuristically is to assume we should observe some number of genes. With that in mind, I arbitrarily chose 11,000 non-zero genes as the minimum.

With this in mind, here is a non-zero plot before a cutoff of 11,000 genes.

5.2 Figure XX: Non-zero genes before sample filtering

One of the likely early (supplemental?)figures in a publication includes the view of observed genes with respect to coverage. I think we will want to include this for both before and after sample filtering.

I am not certain why, but my legend plotter is throwing an error!

orange: biopsy samples green: eosinophils pink: monocytes blue: neutrophils

all_nz <- plot_nonzero(hs_expt)
all_nz$plot
## Warning: ggrepel: 229 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

5.3 Subset: Filter out problematic samples

To my eyes, there are 3 or 4 samples which are likely candidates for removal. In addition, we will remove samples which were lost during the treatment and/or ones which were used in other experiments but included in the TMRC3 sample sheet (thus the ‘notapplicable’ or ‘null’).

hs_valid <- subset_expt(hs_expt, nonzero=11000) %>%
  subset_expt(subset="clinicaloutcome!='lost'") %>%
  subset_expt(subset="clinicaloutcome!='notapplicable'") %>%
  subset_expt(subset="clinicaloutcome!='null'") %>%
  set_expt_colors(cf_colors)
## The samples (and read coverage) removed when filtering 11000 non-zero genes are:
## TMRC30010 TMRC30050 TMRC30052 
##     52429    807571   3086349
## subset_expt(): There were 246, now there are 243 samples.
## subset_expt(): There were 243, now there are 228 samples.
## subset_expt(): There were 228, now there are 192 samples.
## subset_expt(): There were 192, now there are 192 samples.

5.4 Figure XX + 1: Non-zero genes after sample filtering

The following plot is essentially identical to the previous with two exceptions:

  1. The samples with too few genes (11,000 currently) are gone.
  2. The samples are colored by cure(purple)/fail(yellow)
nz_post <- plot_nonzero(hs_valid)
nz_post$plot
## Warning: ggrepel: 171 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

5.5 Summarize: Tally samples after filtering

We need to keep track of how many of each sample type is lost when we do our various filters. Thus I am repeating the same set of tallies. This will likely happen one more time, following the removal of samples which came from Cali.

table(pData(hs_valid)$drug)
## 
##    antimony miltefosine 
##         184           8
table(pData(hs_valid)$clinic)
## 
##   Cali Tumaco 
##     61    131
table(pData(hs_valid)$clinicaloutcome)
## 
##    cure failure 
##     132      60
table(pData(hs_valid)$typeofcells)
## 
##      biopsy eosinophils   monocytes neutrophils 
##          19          42          66          65
table(pData(hs_valid)$visit)
## 
##  3  2  1 
## 51 50 91
summary(as.numeric(pData(hs_valid)$eb_lc_tiempo_evolucion))
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    2.00    4.00    6.00    8.12   12.00   21.00
summary(as.numeric(pData(hs_valid)$eb_lc_tto_mcto_glucan_dosis))
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    13.0    15.0    19.0    58.4    20.0   999.0
summary(as.numeric(pData(hs_valid)$v3_lc_ejey_lesion_mm_1))
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##     0.0     7.2    30.7   291.6   999.0   999.0
summary(as.numeric(pData(hs_valid)$v3_lc_lesion_area_1))
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##       0     226     999    2299    2393   16965
summary(as.numeric(pData(hs_valid)$v3_lc_ejex_ulcera_mm_1))
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##     0.0     0.0    12.5   283.9   999.0   999.0
table(pData(hs_valid)$eb_lc_sexo)
## 
##   1   2 
## 161  31
table(pData(hs_valid)$eb_lc_etnia)
## 
##  1  2  3 
## 99 46 47
summary(as.numeric(pData(hs_valid)$edad))
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    18.0    25.0    28.0    30.6    36.0    51.0
table(pData(hs_valid)$eb_lc_peso)
## 
##   100 100.8  53.9  55.9  57.9    58  58.1  58.3  58.6    59  59.6    62    63 
##     5     2     9     2     2     6     7    10     3     8     1     6     6 
##    67  69.4    72  74.7    75  75.6  76.5    77    78  79.2    82  83.3  83.4 
##     6    10     9     3     2     3     3    18    10    10     9     4    10 
##  86.4    87    89  93.3 
##     9     3     9     7
table(pData(hs_valid)$eb_lc_estatura)
## 
## 152 154 155 156 158 159 160 163 164 165 166 167 169 172 173 174 175 176 177 182 
##   1  10   9   6  15   2   6   9  15  12  19   3   2  10   9  32   2   1  10   9 
## 183 
##  10

6 Subset: Separate samples by cell type and visit

Give our population of ~ 190 samples, there are a few ways we are most likely to want to mix and match them.

The following block performed many subset operations to create separate data structures on a per-celltype and per-visit basis. Ergo, our large data structure is now joined by ~21 new, smaller data structures which will hopefully provide ways to compare the samples across visit and cell type.

all_types <- table(pData(hs_valid)[["typeofcells"]])
all_types
## 
##      biopsy eosinophils   monocytes neutrophils 
##          19          42          66          65
all_times <- table(pData(hs_valid)[["visitnumber"]])
all_times
## 
##  3  2  1 
## 51 50 91
biopsy_samples <- subset_expt(hs_valid, subset="typeofcells=='biopsy'")
## subset_expt(): There were 192, now there are 19 samples.
eosinophil_samples <- subset_expt(hs_valid, subset="typeofcells=='eosinophils'")
## subset_expt(): There were 192, now there are 42 samples.
monocyte_samples <- subset_expt(hs_valid, subset="typeofcells=='monocytes'")
## subset_expt(): There were 192, now there are 66 samples.
neutrophil_samples <- subset_expt(hs_valid, subset="typeofcells=='neutrophils'")
## subset_expt(): There were 192, now there are 65 samples.
## Currently, these are not used, but instead I pulled the samples from the hs_clinical
## which means the biopsies are not included.
v1_samples <- subset_expt(hs_valid, subset="visitnumber=='1'")
## subset_expt(): There were 192, now there are 91 samples.
v1_monocytes <- subset_expt(v1_samples, subset="typeofcells=='monocytes'")
## subset_expt(): There were 91, now there are 29 samples.
v1_neutrophils <- subset_expt(v1_samples, subset="typeofcells=='neutrophils'")
## subset_expt(): There were 91, now there are 28 samples.
v1_eosinophils <- subset_expt(v1_samples, subset="typeofcells=='eosinophils'")
## subset_expt(): There were 91, now there are 15 samples.
v2_samples <- subset_expt(hs_valid, subset="visitnumber=='2'")
## subset_expt(): There were 192, now there are 50 samples.
v2_monocytes <- subset_expt(v2_samples, subset="typeofcells=='monocytes'")
## subset_expt(): There were 50, now there are 18 samples.
v2_neutrophils <- subset_expt(v2_samples, subset="typeofcells=='neutrophils'")
## subset_expt(): There were 50, now there are 18 samples.
v2_eosinophils <- subset_expt(v2_samples, subset="typeofcells=='eosinophils'")
## subset_expt(): There were 50, now there are 14 samples.
v3_samples <- subset_expt(hs_valid, subset="visitnumber=='3'")
## subset_expt(): There were 192, now there are 51 samples.
v3_monocytes <- subset_expt(v3_samples, subset="typeofcells=='monocytes'")
## subset_expt(): There were 51, now there are 19 samples.
v3_neutrophils <- subset_expt(v3_samples, subset="typeofcells=='neutrophils'")
## subset_expt(): There were 51, now there are 19 samples.
v3_eosinophils <- subset_expt(v3_samples, subset="typeofcells=='eosinophils'")
## subset_expt(): There were 51, now there are 13 samples.

7 Summarize: Tabulate sample numbers

Here is an outline of the samples in their current state:

  • By type: ncol(exprs(hs_valid)), Cure: sum(pData(hs_valid)[["clinicaloutcome"]] == "cure"), Fail: sum(pData(hs_valid)[["clinicaloutcome"]] == "failure")
    • Biopsy: all_types[["biopsy"]], Cure: sum(pData(biopsy_samples)[["clinicaloutcome"]] == "cure"), Fail: sum(pData(biopsy_samples)[["clinicaloutcome"]] == "failure")
      • All biopsy samples are visit 1.
    • Eosinophils: all_types[["eosinophils"]], Cure: sum(pData(eosinophil_samples)[["clinicaloutcome"]] == "cure"), Fail: sum(pData(eosinophil_samples)[["clinicaloutcome"]] == "failure")
      • V1 Eosinophils: nrow(pData(v1_eosinophils)), Cure: sum(pData(v1_eosinophils)[["clinicaloutcome"]] == "cure"), Fail: sum(pData(v1_eosinophils)[["clinicaloutcome"]] == "failure")
      • V2 Eosinophils: nrow(pData(v2_eosinophils)), Cure: sum(pData(v2_eosinophils)[["clinicaloutcome"]] == "cure"), Fail: sum(pData(v2_eosinophils)[["clinicaloutcome"]] == "failure")
      • V3 Eosinophils: nrow(pData(v3_eosinophils)), Cure: sum(pData(v3_eosinophils)[["clinicaloutcome"]] == "cure"), Fail: sum(pData(v3_eosinophils)[["clinicaloutcome"]] == "failure")
    • Monocytes: all_types[["monocytes"]], Cure: sum(pData(monocyte_samples)[["clinicaloutcome"]] == "cure"), Fail: sum(pData(monocyte_samples)[["clinicaloutcome"]] == "failure")
      • V1 Monocytes: nrow(pData(v1_monocytes)), Cure: sum(pData(v1_monocytes)[["clinicaloutcome"]] == "cure"), Fail: sum(pData(v1_monocytes)[["clinicaloutcome"]] == "failure")
      • V2 Monocytes: nrow(pData(v2_monocytes)), Cure: sum(pData(v2_monocytes)[["clinicaloutcome"]] == "cure"), Fail: sum(pData(v2_monocytes)[["clinicaloutcome"]] == "failure")
      • V3 Monocytes: nrow(pData(v3_monocytes)), Cure: sum(pData(v3_monocytes)[["clinicaloutcome"]] == "cure"), Fail: sum(pData(v3_monocytes)[["clinicaloutcome"]] == "failure")
    • Neutrophils: all_types[["neutrophils"]], Cure: sum(pData(neutrophil_samples)[["clinicaloutcome"]] == "cure"), Fail: sum(pData(neutrophil_samples)[["clinicaloutcome"]] == "failure")
      • V1 Neutrophils: nrow(pData(v1_neutrophils)), Cure: sum(pData(v1_neutrophils)[["clinicaloutcome"]] == "cure"), Fail: sum(pData(v1_neutrophils)[["clinicaloutcome"]] == "failure")
      • V2 Neutrophils: nrow(pData(v2_monocytes)), Cure: sum(pData(v2_neutrophils)[["clinicaloutcome"]] == "cure"), Fail: sum(pData(v2_neutrophils)[["clinicaloutcome"]] == "failure")
      • V3 Neutrophils: nrow(pData(v3_neutrophils)), Cure: sum(pData(v3_neutrophils)[["clinicaloutcome"]] == "cure"), Fail: sum(pData(v3_neutrophils)[["clinicaloutcome"]] == "failure")

8 Dataset: Parasite reads

Make an expressionset of the parasite reads in the TMRC3 samples and distinguish between the faux and real reads. E.g: Are there samples which definitively contain parasites?

Later, I manually went through the mappings of samples with a significant number of parasite reads in IGV with some TMRC2 known zymodeme samples. In many cases it is possible to state definitively the classification of the parasite which infected an individual.

lp_expt <- sm(create_expt(samplesheet,
                       file_column="lpanamensisv36hisatfile", gene_info = NULL)) %>%
  subset_expt(coverage=1000) %>%
  set_expt_conditions(fact="typeofcells")
## The samples removed (and read coverage) when filtering samples with less than 1000 reads are:
## TMRC30001 TMRC30002 TMRC30003 TMRC30004 TMRC30005 TMRC30006 TMRC30007 TMRC30008 
##        12         8         9        16        25        29         3        16 
## TMRC30009 TMRC30010 TMRC30011 TMRC30012 TMRC30013 TMRC30050 TMRC30018 TMRC30118 
##        16         0         5         9        13       345       110       747 
## TMRC30119 TMRC30014 TMRC30021 TMRC30038 TMRC30023 TMRC30025 TMRC30165 TMRC30166 
##       419         4        88       208       120       954       433       496 
## TMRC30030 TMRC30031 TMRC30032 TMRC30024 TMRC30040 TMRC30033 TMRC30194 TMRC30195 
##         3         8        22        49       896        36       198       458 
## TMRC30196 TMRC30164 TMRC30037 TMRC30027 TMRC30028 TMRC30034 TMRC30035 TMRC30036 
##       687       424         9       108        93        21       153        11 
## TMRC30192 TMRC30041 TMRC30042 TMRC30043 TMRC30045 TMRC30171 TMRC30158 TMRC30159 
##       384       264       545       571       334       370       284       405 
## TMRC30189 TMRC30190 TMRC30139 TMRC30160 TMRC30161 TMRC30152 TMRC30123 TMRC30181 
##       307       537       140       296       300       495       304       613 
## TMRC30182 TMRC30155 TMRC30129 TMRC30137 TMRC30174 TMRC30154 TMRC30172 TMRC30173 
##       468       508       353       389       644       398       383       898 
## TMRC30142 TMRC30143 TMRC30144 TMRC30145 TMRC30146 TMRC30147 TMRC30185 TMRC30186 
##         4         1         0         0         0         1         0       852 
## TMRC30148 TMRC30138 TMRC30150 TMRC30140 TMRC30151 TMRC30178 TMRC30179 TMRC30197 
##       706       156       470       153       480       420       515       202 
## TMRC30198 TMRC30200 TMRC30201 TMRC30202 TMRC30203 TMRC30205 TMRC30206 TMRC30207 
##       158        96       149       145       104       169       125         0 
## TMRC30208 TMRC30217 TMRC30218 TMRC30219 TMRC30220 TMRC30209 TMRC30210 TMRC30211 
##         1         0         2         0         0         0         0         0 
## TMRC30212 TMRC30213 TMRC30214 TMRC30215 TMRC30216 TMRC30221 TMRC30222 TMRC30223 
##         0         0         0         1         0         0         0         0 
## TMRC30224 TMRC30225 TMRC30226 TMRC30227 TMRC30228 TMRC30229 TMRC30230 TMRC30231 
##         2         0         0         0         0         0         0         0 
## TMRC30232 TMRC30233 TMRC30234 TMRC30235 TMRC30238 TMRC30266 TMRC30260 TMRC30261 
##         1         0         0         0       335       822       291       500 
## TMRC30262 TMRC30263 TMRC30264 TMRC30265 TMRC30269 TMRC30270 TMRC30273 TMRC30275 
##       905       431       309       596        58        21         2         2 
## TMRC30271 TMRC30274 TMRC30276 TMRC30272 TMRC30254 TMRC30257 TMRC30239 TMRC30240 
##         4         0         1         0       208       427       209       314 
## TMRC30283 TMRC30284 TMRC30281 TMRC30277 TMRC30279 TMRC30280 TMRC30278 TMRC30282 
##        18         4       548         6         0         3         0         1 
## TMRC30285 
##         0
## subset_expt(): There were 244, now there are 99 samples.
visit_fact <- pData(lp_expt)[["visitnumber"]]
batch_na <- is.na(visit_fact)
visit_fact[batch_na] <- "undefined"
lp_expt <- set_expt_batches(lp_expt, fact = visit_fact)

lp_norm <- normalize_expt(lp_expt, filter="simple", norm="quant",
                          convert="cpm", transform="log2")
## Removing 66 low-count genes (8712 remaining).
## transform_counts: Found 404 values equal to 0, adding 1 to the matrix.
plotted <- plot_pca(lp_norm, plot_labels=FALSE)
plotted$plot

plotted_3d <- plot_3d_pca(plotted)

The above block is similar in concept to the previous expressionset creation. It uses a different column and currently ignores the gene annotations. Given that many of the samples have essentially 0 reads, I set a cutoff of only 20 observed genes. Finally, I did a quick and dirty PCA plot of this peculiar data structure in the hopes of being able to ‘see’ the difference between what are assumed to be ‘real’ samples with a significant number of ‘real’ parasite reads vs. those samples which just have a couple of potentially spurious reads.

9 Host Distributions/Visualizations of interest

The sets of samples used to visualize the data will also comprise the sets used when later performing the various differential expression analyses.

9.1 Global metrics

Start out with some initial metrics of all samples. The most obvious are plots of the numbers of non-zero genes observed, heatmaps showing the relative relationships among the samples, the relative library sizes, and some PCA. It might be smart to split the library sizes up across subsets of the data, because they have expanded too far to see well on a computer screen.

The most likely factors to query when considering the entire dataset are cure/fail, visit, and cell type. This is the level at which we will choose samples to exclude from future analyses.

plot_legend(biopsy_samples)$plot

plot_libsize(biopsy_samples)$plot

plot_nonzero(biopsy_samples)$plot

biopsy_prepost <- plot_libsize_prepost(biopsy_samples)
biopsy_prepost$count_plot

biopsy_prepost$lowgene_plot
## Warning: Using alpha for a discrete variable is not advised.

## Minimum number of biopsy genes: ~ 14,000

plot_libsize(eosinophil_samples)$plot

plot_nonzero(eosinophil_samples)$plot
## Warning: ggrepel: 23 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

eosinophil_prepost <- plot_libsize_prepost(eosinophil_samples)
eosinophil_prepost$count_plot

eosinophil_prepost$lowgene_plot
## Warning: Using alpha for a discrete variable is not advised.

## Minimum number of eosinophil genes: ~ 13,500

plot_libsize(monocyte_samples)$plot

plot_nonzero(monocyte_samples)$plot
## Warning: ggrepel: 51 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

monocyte_prepost <- plot_libsize_prepost(monocyte_samples)
monocyte_prepost$count_plot

monocyte_prepost$lowgene_plot
## Warning: Using alpha for a discrete variable is not advised.

## Minimum number of monocyte genes: ~ 7,500 before setting the minimum.

plot_libsize(neutrophil_samples)$plot

plot_nonzero(neutrophil_samples)$plot
## Warning: ggrepel: 48 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

neutrophil_prepost <- plot_libsize_prepost(neutrophil_samples)
neutrophil_prepost$count_plot

neutrophil_prepost$lowgene_plot
## Warning: Using alpha for a discrete variable is not advised.

## Minimum number of neutrophil genes: ~ 10,000 before setting minimum coverage.

The above block just repeats the same two plots on a per-celltype basis: the number of reads observed / sample and a plot of observed genes with respect to coverage. I made some comments with my observations about the number of genes.

9.2 PCA: Global views of all cell types

Now that those ‘global’ metrics are out of the way, lets look at some global metrics of the data following normalization; the most likely plots are of course PCA but also a couple of heatmaps.

9.2.1 Figure 1

In the google doc TMRC3_Aug18_2021, there is an example of an image for the first figure:

“Transcriptomic profiles of primary innate cells of CL patients show unique transcriptional signatures - Remove PBMCs and M0, maybe biopsies as well (but Remove WT samples)”

While we were talking in a meeting however, it sounded like there was some desire to keep all cell types. Therefore the following block has one image with everything and one following the above.

type_valid <- set_expt_conditions(hs_valid, fact="typeofcells") %>%
  set_expt_batches(fact="clinicaloutcome") %>%
  set_expt_colors(type_colors)

all_norm <- sm(normalize_expt(type_valid, transform="log2", norm="quant",
                              convert="cpm", filter=TRUE))

all_pca <- plot_pca(all_norm, plot_labels=FALSE,
                    plot_title="PCA - Cell type", size_column="visitnumber")
dev <- pp(file=glue("images/tmrc3_pca_nolabels-v{ver}.png"))
all_pca$plot
closed <- dev.off()
all_pca$plot

all_pca_nosize <- plot_pca(all_norm, plot_labels=FALSE)
all_pca_nosize$plot

write.csv(all_pca$table, file="coords/hs_donor_pca_coords.csv")
all_cf_norm <- set_expt_batches(all_norm,
                                fact="visitnumber")
all_cf_corheat <- plot_corheat(all_cf_norm, plot_title="Heirarchical clustering:
         cell types")

dev <- pp(file=glue("images/tmrc3_corheat_cf-v{ver}.png"))
all_cf_corheat$plot
closed <- dev.off()
all_cf_corheat$plot

all_cf_disheat <- plot_disheat(all_cf_norm, plot_title="Heirarchical clustering:
         cell types")
dev <- pp(file=glue("images/tmrc3_disheat_cf-v{ver}.png"))
all_cf_disheat$plot
closed <- dev.off()
all_cf_disheat$plot

9.3 Figure 1B: Transcriptomic profiles of primary innate cells

A potential figure legend for the following images might include:

The observed counts per gene for all of the clinical samples were filtered, log transformed, cpm converted, and quantile normalized. The colors were defined by cell types and shapes by patient visit. When the first two principle components were plotted, clustering was observed by cell type. The biopsy samples were significantly different from the innate immune cell types.

fig1v2_norm <- normalize_expt(type_valid, transform="log2",
                              convert="cpm", norm="quant", filter=TRUE)
## Removing 5601 low-count genes (14322 remaining).
## transform_counts: Found 502 values equal to 0, adding 1 to the matrix.
fig1v2_pca <- plot_pca(fig1v2_norm, cis=FALSE)
## plot labels was not set and there are more than 100 samples, disabling it.
dev <- pp(file=glue("images/tmrc3_fig1v2.png"))
fig1v2_pca$plot
closed <- dev.off()
fig1v2_pca$plot

fig1v3_samples <- subset_expt(type_valid, subset="condition!='biopsy'")
## subset_expt(): There were 192, now there are 173 samples.
fig1v3_norm <- normalize_expt(fig1v3_samples, transform="log2",
                              convert="cpm", norm="quant", filter=TRUE)
## Removing 7749 low-count genes (12174 remaining).
## transform_counts: Found 124 values equal to 0, adding 1 to the matrix.
fig1v3_pca <- plot_pca(fig1v3_norm, cis=FALSE)
## plot labels was not set and there are more than 100 samples, disabling it.
dev <- pp(file="images/tmrc3_fig1v3.png")
fig1v3_pca$plot
closed <- dev.off()
fig1v3_pca$plot

10 Dataset: Clinical samples

The following block defines an explicit separation between the biopsy and other clinical samples (Monocyte, Neutrophil, Eosinophil). This was done for two reasons: we are only using visit 1 samples for the biopsies, and we have a relatively strong hypothesis that the biopsy samples will not prove to be informative for cure/fail questions.

hs_clinical <- hs_valid %>%
  set_expt_conditions(fact="clinicaloutcome") %>%
  set_expt_batches(fact="typeofcells") %>%
  set_expt_colors(cf_colors)

hs_clinical_nobiop <- subset_expt(hs_clinical, subset="typeofcells!='biopsy'")
## subset_expt(): There were 192, now there are 173 samples.

11 Compare samples by clinic

Spoiler alert: This section will eventually suggest pretty strongly that we will not easily be able to use the Cali samples. Thus, after finishing it, we will likely exclude those samples.

Take a moment to view the biopsy samples. We separated them by clinic (Cali or Tumaco), and this view of the samples is the only one which does not suggest a strong difference between the two clinics. However, it also suggests that the biopsy samples will not prove very helpful.

11.1 Subset: Biopsies by clinic

We somewhat expect biopsy samples to be something of a mess in pretty much any context, since they are large-scale hetergeneous collections of cell types. The following block will illustrate this problem in pretty stark terms.

clinic_biopsy <- hs_valid %>%
  set_expt_conditions(fact="clinic") %>%
  set_expt_batches(fact="clinicaloutcome") %>%
  subset_expt(subset="typeofcells=='biopsy'")
## subset_expt(): There were 192, now there are 19 samples.
clinic_cf <- paste0(pData(clinic_biopsy)$condition, "_",
                    pData(clinic_biopsy)$batch)
table(clinic_cf)
## clinic_cf
##      Cali_cure    Tumaco_cure Tumaco_failure 
##              4             10              5
clinic_biopsy <- set_expt_conditions(clinic_biopsy, fact=clinic_cf) %>%
  set_expt_batches(fact="visitnumber")

clinic_biopsy_norm <- normalize_expt(clinic_biopsy, transform="log2",
                                     convert="cpm", norm="quant", filter=TRUE)
## Removing 6278 low-count genes (13645 remaining).
## transform_counts: Found 212 values equal to 0, adding 1 to the matrix.
clinic_biopsy_pca <- plot_pca(clinic_biopsy_norm, plot_labels=FALSE)
dev <- pp(file="images/biopsy_place.png")
clinic_biopsy_pca$plot
closed <- dev.off()
clinic_biopsy_pca$plot

clinic_biopsy_nb <- normalize_expt(clinic_biopsy, transform="log2",
                                   convert="cpm", batch="svaseq", filter=TRUE)
## Removing 6278 low-count genes (13645 remaining).
## Setting 320 low elements to zero.
## transform_counts: Found 320 values equal to 0, adding 1 to the matrix.
clinic_biopsy_nb_pca <- plot_pca(clinic_biopsy_nb, plot_labels=FALSE)
dev <- pp(file="images/biopsy_place_nb.png")
clinic_biopsy_nb_pca$plot
closed <- dev.off()
clinic_biopsy_nb_pca$plot

11.2 Subset: Eosinophils by clinic

In contrast, the Eosinophil samples do have significant amounts of variance which discriminates the two clinics. At the time of this writing, there are fewer eosinophil samples than monocytes nor neutrophils; as a result there are no samples which failed from Cali. This is somewhat limiting is we wish to look for differences between the cure and fail samples which came from the two clinics.

clinic_eosinophil <- hs_valid %>%
  set_expt_conditions(fact="clinic") %>%
  set_expt_batches(fact="clinicaloutcome") %>%
  subset_expt(subset="typeofcells=='eosinophils'")
## subset_expt(): There were 192, now there are 42 samples.
clinic_cf <- paste0(pData(clinic_eosinophil)$condition, "_",
                    pData(clinic_eosinophil)$batch)
table(clinic_cf)
## clinic_cf
##      Cali_cure    Tumaco_cure Tumaco_failure 
##             15             18              9
clinic_eosinophil <- set_expt_conditions(clinic_eosinophil, fact=clinic_cf) %>%
    set_expt_batches(fact="visitnumber")

clinic_eosinophil_norm <- normalize_expt(clinic_eosinophil, transform="log2",
                                         convert="cpm", norm="quant", filter=TRUE)
## Removing 9049 low-count genes (10874 remaining).
## transform_counts: Found 5 values equal to 0, adding 1 to the matrix.
clinic_eosinophil_pca <- plot_pca(clinic_eosinophil_norm, plot_labels=FALSE)
dev <- pp(file="images/eosinophil_place.png")
clinic_eosinophil_pca$plot
closed <- dev.off()
clinic_eosinophil_pca$plot

clinic_eosinophil_nb <- normalize_expt(clinic_eosinophil, transform="log2",
                                       convert="cpm", batch="svaseq", filter=TRUE)
## Removing 9049 low-count genes (10874 remaining).
## Setting 1033 low elements to zero.
## transform_counts: Found 1033 values equal to 0, adding 1 to the matrix.
clinic_eosinophil_nb_pca <- plot_pca(clinic_eosinophil_nb, plot_labels=FALSE)
dev <- pp(file="images/eosinophil_place_nb.png")
clinic_eosinophil_nb_pca$plot
closed <- dev.off()
clinic_eosinophil_nb_pca$plot

11.3 Subset: Monocytes by clinic

In contrast with the eosinophil samples, we have one patient’s monocyte and neutrophil samples which did not cure. As we will see, there is one person from Cali who did not cure, this person is not different with respect to tracscriptome than the other people from Cali.

clinic_monocyte <- hs_valid %>%
  set_expt_conditions(fact="clinic") %>%
  set_expt_batches(fact="clinicaloutcome") %>%
  subset_expt(subset="typeofcells=='monocytes'")
## subset_expt(): There were 192, now there are 66 samples.
clinic_cf <- paste0(pData(clinic_monocyte)$condition, "_",
                    pData(clinic_monocyte)$batch)
table(clinic_cf)
## clinic_cf
##      Cali_cure   Cali_failure    Tumaco_cure Tumaco_failure 
##             18              3             25             20
clinic_monocyte <- set_expt_conditions(clinic_monocyte, fact=clinic_cf) %>%
    set_expt_batches(fact="visitnumber")

clinic_monocyte_norm <- normalize_expt(clinic_monocyte, transform="log2",
                                       convert="cpm", norm="quant", filter=TRUE)
## Removing 8797 low-count genes (11126 remaining).
## transform_counts: Found 12 values equal to 0, adding 1 to the matrix.
clinic_monocyte_pca <- plot_pca(clinic_monocyte_norm, plot_labels=FALSE)
dev <- pp(file="images/monocytes_place.png")
clinic_monocyte_pca$plot
closed <- dev.off()
clinic_monocyte_pca$plot

clinic_monocyte_nb <- normalize_expt(clinic_monocyte, transform="log2",
                                     convert="cpm", batch="svaseq", filter=TRUE)
## Removing 8797 low-count genes (11126 remaining).
## Setting 1626 low elements to zero.
## transform_counts: Found 1626 values equal to 0, adding 1 to the matrix.
clinic_monocyte_nb_pca <- plot_pca(clinic_monocyte_nb, plot_labels=FALSE)
dev <- pp(file="images/monocytes_place_nb.png")
clinic_monocyte_nb_pca$plot
closed <- dev.off()
clinic_monocyte_nb_pca$plot

11.4 Subset: Neutrophils by clinic

Finally, that same one person does appear to be different than the others from Cali.

clinic_neutrophil <- hs_valid %>%
  set_expt_conditions(fact="clinic") %>%
  set_expt_batches(fact="clinicaloutcome") %>%
  subset_expt(subset="typeofcells=='neutrophils'")
## subset_expt(): There were 192, now there are 65 samples.
clinic_cf <- paste0(pData(clinic_neutrophil)$condition, "_",
                    pData(clinic_neutrophil)$batch)
table(clinic_cf)
## clinic_cf
##      Cali_cure   Cali_failure    Tumaco_cure Tumaco_failure 
##             18              3             24             20
clinic_neutrophil <- set_expt_conditions(clinic_neutrophil, fact=clinic_cf) %>%
    set_expt_batches(fact="visitnumber")

clinic_neutrophil_norm <- normalize_expt(clinic_neutrophil, transform="log2",
                                         convert="cpm", norm="quant", filter=TRUE)
## Removing 10634 low-count genes (9289 remaining).
## transform_counts: Found 1 values equal to 0, adding 1 to the matrix.
clinic_neutrophil_pca <- plot_pca(clinic_neutrophil_norm, plot_labels=FALSE)
dev <- pp(file="images/neutrophil_place.png")
clinic_neutrophil_pca$plot
closed <- dev.off()
clinic_neutrophil_pca$plot

clinic_neutrophil_nb <- normalize_expt(clinic_neutrophil, transform="log2",
                                       convert="cpm", batch="svaseq", filter=TRUE)
## Removing 10634 low-count genes (9289 remaining).
## Setting 1462 low elements to zero.
## transform_counts: Found 1462 values equal to 0, adding 1 to the matrix.
clinic_neutrophil_nb_pca <- plot_pca(clinic_neutrophil_nb, plot_labels=FALSE)
dev <- pp(file="images/neutrophil_place_nb.png")
clinic_neutrophil_nb_pca$plot
closed <- dev.off()
clinic_neutrophil_nb_pca$plot

11.5 PCA: Compare clinics

Now that we have these various subsets, perform an explicit comparison of the samples which came from the two clinics.

hs_clinic <- hs_valid %>%
  set_expt_conditions(fact="clinic") %>%
  set_expt_batches(fact="typeofcells")

hs_clinic_norm <- normalize_expt(hs_clinic, transform="log2", convert="cpm",
                                 norm="quant", filter=TRUE)
## Removing 5601 low-count genes (14322 remaining).
## transform_counts: Found 502 values equal to 0, adding 1 to the matrix.
hs_clinic_pca <- plot_pca(hs_clinic_norm)
## plot labels was not set and there are more than 100 samples, disabling it.
hs_clinic_pca$plot

hs_clinic_nb <- normalize_expt(hs_clinic, transform="log2", convert="cpm",
                               batch="svaseq", filter=TRUE)
## Removing 5601 low-count genes (14322 remaining).
## Setting 33229 low elements to zero.
## transform_counts: Found 33229 values equal to 0, adding 1 to the matrix.
hs_clinic_nb_pca <- plot_pca(hs_clinic_nb)
## plot labels was not set and there are more than 100 samples, disabling it.
hs_clinic_nb_pca$plot

11.6 DE: Compare clinics, all samples

Perform a svaseq-guided comparison of the two clinics. Ideally this will give some clue about just how strong the clinic-based batch effect really is and what its causes are.

clinic_contrasts <- list(
    "clinics" = c("Cali", "Tumaco"))
hs_clinic_de <- all_pairwise(hs_clinic, model_batch="svaseq", filter=TRUE)
## Removing 0 low-count genes (14322 remaining).
## Setting 33229 low elements to zero.
## transform_counts: Found 33229 values equal to 0, adding 1 to the matrix.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.
hs_clinic_table <- combine_de_tables(
    hs_clinic_de, keepers=clinic_contrasts,
    excel=glue::glue("excel/hs_clinic_table-v{ver}.xlsx"))
## Deleting the file excel/hs_clinic_table-v202205.xlsx before writing the tables.
hs_clinic_sig <- extract_significant_genes(
    hs_clinic_table,
    excel=glue::glue("excel/hs_clinic_sig-v{ver}.xlsx"))
## Deleting the file excel/hs_clinic_sig-v202205.xlsx before writing the tables.

11.7 DE: Compare clinics, biopsy samples

Interestingly to me, the biopsy samples appear to have the least location-based variance. But we can perform an explicit DE and see how well that hypothesis holds up.

clinic_biopsy_de <- all_pairwise(clinic_biopsy, model_batch="svaseq", filter=TRUE)
## Removing 0 low-count genes (13645 remaining).
## Setting 320 low elements to zero.
## transform_counts: Found 320 values equal to 0, adding 1 to the matrix.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.

clinic_biopsy_table <- combine_de_tables(
    clinic_biopsy_de,
    excel=glue::glue("excel/clinic_biopsy_table-v{ver}.xlsx"))
## Deleting the file excel/clinic_biopsy_table-v202205.xlsx before writing the tables.
clinic_biopsy_sig <- extract_significant_genes(
    clinic_biopsy_table,
    excel=glue::glue("excel/clinic_biopsy_sig-v{ver}.xlsx"))
## Deleting the file excel/clinic_biopsy_sig-v202205.xlsx before writing the tables.

11.8 DE: Compare clinics, eosinophil samples

The remaining cell types all have pretty strong clinic-based variance; but I am not certain if it is consistent across cell types.

clinic_eosinophil_de <- all_pairwise(clinic_eosinophil, model_batch=FALSE, filter=TRUE)
## Finished running DE analyses, collecting outputs.
## Comparing analyses.

clinic_eosinophil_table <- combine_de_tables(
    clinic_eosinophil_de,
    excel=glue::glue("excel/clinic_eosinophil_table-v{ver}.xlsx"))
## Deleting the file excel/clinic_eosinophil_table-v202205.xlsx before writing the tables.
clinic_eosinophil_sig <- extract_significant_genes(
    clinic_eosinophil_table,
    excel=glue::glue("excel/clinic_eosinophil_sig-v{ver}.xlsx"))
## Deleting the file excel/clinic_eosinophil_sig-v202205.xlsx before writing the tables.

11.9 DE: Compare clinics, monocyte samples

At least for the moment, I am only looking at the differences between no-batch vs. sva across clinics for the monocyte samples. This was chosen mostly arbitrarily.

11.9.1 DE: Compare clinics, monocytes with batch estimation

Our baseline is the comparison of the monocytes samples without batch in the model or surrogate estimation. In theory at least, this should correspond to the PCA plot above when no batch estimation was performed.

clinic_monocyte_de <- all_pairwise(clinic_monocyte, model_batch=FALSE, filter=TRUE)
## Finished running DE analyses, collecting outputs.
## Comparing analyses.

clinic_monocyte_table <- combine_de_tables(
    clinic_monocyte_de,
    excel=glue::glue("excel/clinic_monocyte_table-v{ver}.xlsx"))
## Deleting the file excel/clinic_monocyte_table-v202205.xlsx before writing the tables.
clinic_monocyte_sig <- extract_significant_genes(
    clinic_monocyte_table,
    excel=glue::glue("excel/clinic_monocyte_sig-v{ver}.xlsx"))
## Deleting the file excel/clinic_monocyte_sig-v202205.xlsx before writing the tables.

11.9.2 DE: Compare clinics, monocytes with svaseq

In contrast, the following comparison should give a view of the data corresponding to the svaseq PCA plot above. In the best case scenario, we should therefore be able to see some significane differences between the Tumaco cure and fail samples.

clinic_monocyte_sva_de <- all_pairwise(clinic_monocyte, model_batch="svaseq", filter=TRUE)
## Removing 0 low-count genes (11126 remaining).
## Setting 1626 low elements to zero.
## transform_counts: Found 1626 values equal to 0, adding 1 to the matrix.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.

clinic_monocyte_sva_table <- combine_de_tables(
    clinic_monocyte_sva_de,
    excel=glue::glue("excel/clinic_monocyte_table_sva-v{ver}.xlsx"))
## Deleting the file excel/clinic_monocyte_table_sva-v202205.xlsx before writing the tables.
clinic_monocyte_sva_sig <- extract_significant_genes(
    clinic_monocyte_sva_table,
    excel=glue::glue("excel/clinic_monocyte_sig_sva-v{ver}.xlsx"))
## Deleting the file excel/clinic_monocyte_sig_sva-v202205.xlsx before writing the tables.

11.9.3 DE Compare: How similar are the no-batch vs. SVA results?

The following block shows that these two results are exceedingly different, sugesting that the Cali cure/fail and Tumaco cure/fail cannot easily be considered in the same analysis. I did some playing around with my calculate_aucc function in this block and found that it is in some important way broken, at least if one expands the top-n genes to more than 20% of the number of genes in the data.

cali_table <- clinic_monocyte_table[["data"]][["Califailure_vs_Calicure"]]
table <- clinic_monocyte_table[["data"]][["Tumacofailure_vs_Tumacocure"]]

cali_merged <- merge(cali_table, table, by="row.names")
cor.test(cali_merged[, "deseq_logfc.x"], cali_merged[, "deseq_logfc.y"])
## 
##  Pearson's product-moment correlation
## 
## data:  cali_merged[, "deseq_logfc.x"] and cali_merged[, "deseq_logfc.y"]
## t = 1.9, df = 11124, p-value = 0.05
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  -0.0002483  0.0369027
## sample estimates:
##     cor 
## 0.01833
cali_aucc <- calculate_aucc(cali_table, table, px="deseq_adjp", py="deseq_adjp",
                                   lx="deseq_logfc", ly="deseq_logfc")
cali_aucc$plot

cali_sva_table <- clinic_monocyte_sva_table[["data"]][["Califailure_vs_Calicure"]]
sva_table <- clinic_monocyte_sva_table[["data"]][["Tumacofailure_vs_Tumacocure"]]

cali_sva_merged <- merge(cali_sva_table, sva_table, by="row.names")
cor.test(cali_sva_merged[, "deseq_logfc.x"], cali_sva_merged[, "deseq_logfc.y"])
## 
##  Pearson's product-moment correlation
## 
## data:  cali_sva_merged[, "deseq_logfc.x"] and cali_sva_merged[, "deseq_logfc.y"]
## t = 13, df = 11124, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.1070 0.1436
## sample estimates:
##    cor 
## 0.1253
cali_sva_aucc <- calculate_aucc(cali_sva_table, sva_table, px="deseq_adjp", py="deseq_adjp",
                                   lx="deseq_logfc", ly="deseq_logfc")
cali_sva_aucc$plot

11.10 DE: Compare clinics, neutrophil samples

clinic_neutrophil_de <- all_pairwise(clinic_neutrophil, model_batch=FALSE, filter=TRUE)
## Finished running DE analyses, collecting outputs.
## Comparing analyses.

clinic_neutrophil_table <- combine_de_tables(
    clinic_neutrophil_de,
    excel=glue::glue("excel/clinic_neutrophil_table-v{ver}.xlsx"))
## Deleting the file excel/clinic_neutrophil_table-v202205.xlsx before writing the tables.
clinic_neutrophil_sig <- extract_significant_genes(
    clinic_neutrophil_table,
    excel=glue::glue("excel/clinic_neutrophil_sig-v{ver}.xlsx"))
## Deleting the file excel/clinic_neutrophil_sig-v202205.xlsx before writing the tables.

12 Compare DE: How similar are Tumaco C/F vs. Cali C/F

The following expands the cross-clinic query above to also test the neutrophils. Once again, I think it will pretty strongly support the hypothesis that the two clinics are not compatible.

We are concerned that the clinic-based batch effect may make our results essentially useless. One way to test this concern is to compare the set of genes observed different between the Cali Cure/Fail vs. the Tumaco Cure/Fail.

cali_table <- clinic_neutrophil_table[["data"]][["Califailure_vs_Calicure"]]
table <- clinic_neutrophil_table[["data"]][["Tumacofailure_vs_Tumacocure"]]

cali_merged <- merge(cali_table, table, by="row.names")
cor.test(cali_merged[, "deseq_logfc.x"], cali_merged[, "deseq_logfc.y"])
## 
##  Pearson's product-moment correlation
## 
## data:  cali_merged[, "deseq_logfc.x"] and cali_merged[, "deseq_logfc.y"]
## t = -19, df = 9287, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  -0.2105 -0.1713
## sample estimates:
##    cor 
## -0.191
cali_aucc <- calculate_aucc(cali_table, table, px="deseq_adjp", py="deseq_adjp",
                                   lx="deseq_logfc", ly="deseq_logfc")
cali_aucc$plot

12.1 GSEA: Extract clinic-specific genes

Given the above comparisons, we can extract some gene sets which resulted from those DE analyses and eventually perform some ontology/KEGG/reactome/etc searches. This reminds me, I want to make my extract_significant_ functions to return gene-set data structures and my various ontology searches to take them as inputs. This should help avoid potential errors when extracting up/down genes.

clinic_sigenes_up <- rownames(hs_clinic_sig[["deseq"]][["ups"]][[1]])
clinic_sigenes_down <- rownames(hs_clinic_sig[["deseq"]][["downs"]][[1]])
clinic_sigenes <- c(clinic_sigenes_up, clinic_sigenes_down)

contrast <- "Tumacocure_vs_Calicure"
clinic_biopsy_sigenes <- c(rownames(clinic_biopsy_sig[["deseq"]][["ups"]][[contrast]]),
                           rownames(clinic_biopsy_sig[["deseq"]][["downs"]][[contrast]]))
clinic_eosinophil_sigenes_up <- rownames(clinic_eosinophil_sig[["deseq"]][["ups"]][[contrast]])
clinic_eosinophil_sigenes_down <- rownames(clinic_eosinophil_sig[["deseq"]][["downs"]][[contrast]])
clinic_monocyte_sigenes_up <- rownames(clinic_monocyte_sig[["deseq"]][["ups"]][[contrast]])
clinic_monocyte_sigenes_down <- rownames(clinic_monocyte_sig[["deseq"]][["downs"]][[contrast]])
clinic_neutrophil_sigenes_up <- rownames(clinic_neutrophil_sig[["deseq"]][["ups"]][[contrast]])
clinic_neutrophil_sigenes_down <- rownames(clinic_neutrophil_sig[["deseq"]][["downs"]][[contrast]])

clinic_eosinophil_sigenes <- c(clinic_eosinophil_sigenes_up,
                               clinic_eosinophil_sigenes_down)
clinic_monocyte_sigenes <- c(clinic_monocyte_sigenes_up,
                             clinic_monocyte_sigenes_down)
clinic_neutrophil_sigenes <- c(clinic_neutrophil_sigenes_up,
                               clinic_neutrophil_sigenes_down)

12.2 GSEA: gProfiler of genes deemed up/down when comparing Cali and Tumaco

I was curious to try to understand why the two clinics appear to be so different vis a vis their PCA/DE; so I thought that gProfiler might help boil those results down to something more digestible.

clinic_gp <- simple_gprofiler(clinic_sigenes)
## Performing gProfiler GO search of 964 genes against hsapiens.
## GO search found 167 hits.
## Performing gProfiler KEGG search of 964 genes against hsapiens.
## KEGG search found 12 hits.
## Performing gProfiler REAC search of 964 genes against hsapiens.
## REAC search found 13 hits.
## Performing gProfiler MI search of 964 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 964 genes against hsapiens.
## TF search found 17 hits.
## Performing gProfiler CORUM search of 964 genes against hsapiens.
## CORUM search found 1 hits.
## Performing gProfiler HP search of 964 genes against hsapiens.
## HP search found 17 hits.
clinic_gp$pvalue_plots$kegg_plot_over

clinic_gp$pvalue_plots$reactome_plot_over

clinic_gp <- simple_gprofiler(clinic_sigenes)
## Performing gProfiler GO search of 964 genes against hsapiens.
## GO search found 167 hits.
## Performing gProfiler KEGG search of 964 genes against hsapiens.
## KEGG search found 12 hits.
## Performing gProfiler REAC search of 964 genes against hsapiens.
## REAC search found 13 hits.
## Performing gProfiler MI search of 964 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 964 genes against hsapiens.
## TF search found 17 hits.
## Performing gProfiler CORUM search of 964 genes against hsapiens.
## CORUM search found 1 hits.
## Performing gProfiler HP search of 964 genes against hsapiens.
## HP search found 17 hits.
clinic_gp$pvalue_plots$kegg_plot_over

clinic_gp$pvalue_plots$reactome_plot_over

clinic_gp <- simple_gprofiler(clinic_sigenes)
## Performing gProfiler GO search of 964 genes against hsapiens.
## GO search found 167 hits.
## Performing gProfiler KEGG search of 964 genes against hsapiens.
## KEGG search found 12 hits.
## Performing gProfiler REAC search of 964 genes against hsapiens.
## REAC search found 13 hits.
## Performing gProfiler MI search of 964 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 964 genes against hsapiens.
## TF search found 17 hits.
## Performing gProfiler CORUM search of 964 genes against hsapiens.
## CORUM search found 1 hits.
## Performing gProfiler HP search of 964 genes against hsapiens.
## HP search found 17 hits.
clinic_gp$pvalue_plots$kegg_plot_over

clinic_gp$pvalue_plots$reactome_plot_over

clinic_eosinophil_gp <- simple_gprofiler(clinic_eosinophil_sigenes)
## Performing gProfiler GO search of 1397 genes against hsapiens.
## GO search found 329 hits.
## Performing gProfiler KEGG search of 1397 genes against hsapiens.
## KEGG search found 32 hits.
## Performing gProfiler REAC search of 1397 genes against hsapiens.
## REAC search found 17 hits.
## Performing gProfiler MI search of 1397 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 1397 genes against hsapiens.
## TF search found 371 hits.
## Performing gProfiler CORUM search of 1397 genes against hsapiens.
## CORUM search found 10 hits.
## Performing gProfiler HP search of 1397 genes against hsapiens.
## HP search found 2 hits.
clinic_eosinophil_gp$pvalue_plots$kegg_plot_over

clinic_eosinophil_gp$pvalue_plots$reactome_plot_over

clinic_eosinophil_up_gp <- simple_gprofiler(clinic_eosinophil_sigenes_up)
## Performing gProfiler GO search of 705 genes against hsapiens.
## GO search found 234 hits.
## Performing gProfiler KEGG search of 705 genes against hsapiens.
## KEGG search found 28 hits.
## Performing gProfiler REAC search of 705 genes against hsapiens.
## REAC search found 9 hits.
## Performing gProfiler MI search of 705 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 705 genes against hsapiens.
## TF search found 341 hits.
## Performing gProfiler CORUM search of 705 genes against hsapiens.
## CORUM search found 7 hits.
## Performing gProfiler HP search of 705 genes against hsapiens.
## HP search found 2 hits.
clinic_eosinophil_up_gp$pvalue_plots$kegg_plot_over

clinic_eosinophil_up_gp$pvalue_plots$reactome_plot_over

clinic_eosinophil_down_gp <- simple_gprofiler(clinic_eosinophil_sigenes_down)
## Performing gProfiler GO search of 692 genes against hsapiens.
## GO search found 184 hits.
## Performing gProfiler KEGG search of 692 genes against hsapiens.
## KEGG search found 4 hits.
## Performing gProfiler REAC search of 692 genes against hsapiens.
## REAC search found 11 hits.
## Performing gProfiler MI search of 692 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 692 genes against hsapiens.
## TF search found 39 hits.
## Performing gProfiler CORUM search of 692 genes against hsapiens.
## CORUM search found 3 hits.
## Performing gProfiler HP search of 692 genes against hsapiens.
## HP search found 1 hits.
clinic_eosinophil_down_gp$pvalue_plots$kegg_plot_over

clinic_eosinophil_down_gp$pvalue_plots$reactome_plot_over

clinic_monocyte_gp <- simple_gprofiler(clinic_monocyte_sigenes)
## Performing gProfiler GO search of 1244 genes against hsapiens.
## GO search found 417 hits.
## Performing gProfiler KEGG search of 1244 genes against hsapiens.
## KEGG search found 21 hits.
## Performing gProfiler REAC search of 1244 genes against hsapiens.
## REAC search found 13 hits.
## Performing gProfiler MI search of 1244 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 1244 genes against hsapiens.
## TF search found 403 hits.
## Performing gProfiler CORUM search of 1244 genes against hsapiens.
## CORUM search found 7 hits.
## Performing gProfiler HP search of 1244 genes against hsapiens.
## HP search found 22 hits.
clinic_monocyte_gp$pvalue_plots$kegg_plot_over

clinic_monocyte_gp$pvalue_plots$reactome_plot_over

clinic_monocyte_up_gp <- simple_gprofiler(clinic_monocyte_sigenes_up)
## Performing gProfiler GO search of 586 genes against hsapiens.
## GO search found 382 hits.
## Performing gProfiler KEGG search of 586 genes against hsapiens.
## KEGG search found 19 hits.
## Performing gProfiler REAC search of 586 genes against hsapiens.
## REAC search found 10 hits.
## Performing gProfiler MI search of 586 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 586 genes against hsapiens.
## TF search found 385 hits.
## Performing gProfiler CORUM search of 586 genes against hsapiens.
## CORUM search found 6 hits.
## Performing gProfiler HP search of 586 genes against hsapiens.
## HP search found 13 hits.
clinic_monocyte_up_gp$pvalue_plots$kegg_plot_over

clinic_monocyte_up_gp$pvalue_plots$reactome_plot_over

clinic_monocyte_down_gp <- simple_gprofiler(clinic_monocyte_sigenes_down)
## Performing gProfiler GO search of 658 genes against hsapiens.
## GO search found 60 hits.
## Performing gProfiler KEGG search of 658 genes against hsapiens.
## KEGG search found 3 hits.
## Performing gProfiler REAC search of 658 genes against hsapiens.
## REAC search found 4 hits.
## Performing gProfiler MI search of 658 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 658 genes against hsapiens.
## TF search found 241 hits.
## Performing gProfiler CORUM search of 658 genes against hsapiens.
## CORUM search found 0 hits.
## Performing gProfiler HP search of 658 genes against hsapiens.
## HP search found 10 hits.
clinic_monocyte_down_gp$pvalue_plots$kegg_plot_over

clinic_monocyte_down_gp$pvalue_plots$reactome_plot_over

clinic_neutrophil_gp <- simple_gprofiler(clinic_neutrophil_sigenes)
## Performing gProfiler GO search of 1042 genes against hsapiens.
## GO search found 153 hits.
## Performing gProfiler KEGG search of 1042 genes against hsapiens.
## KEGG search found 10 hits.
## Performing gProfiler REAC search of 1042 genes against hsapiens.
## REAC search found 20 hits.
## Performing gProfiler MI search of 1042 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 1042 genes against hsapiens.
## TF search found 416 hits.
## Performing gProfiler CORUM search of 1042 genes against hsapiens.
## CORUM search found 1 hits.
## Performing gProfiler HP search of 1042 genes against hsapiens.
## HP search found 1 hits.
clinic_neutrophil_gp$pvalue_plots$kegg_plot_over

clinic_neutrophil_gp$pvalue_plots$reactome_plot_over

clinic_neutrophil_up_gp <- simple_gprofiler(clinic_neutrophil_sigenes_up)
## Performing gProfiler GO search of 572 genes against hsapiens.
## GO search found 134 hits.
## Performing gProfiler KEGG search of 572 genes against hsapiens.
## KEGG search found 5 hits.
## Performing gProfiler REAC search of 572 genes against hsapiens.
## REAC search found 3 hits.
## Performing gProfiler MI search of 572 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 572 genes against hsapiens.
## TF search found 388 hits.
## Performing gProfiler CORUM search of 572 genes against hsapiens.
## CORUM search found 0 hits.
## Performing gProfiler HP search of 572 genes against hsapiens.
## HP search found 0 hits.
clinic_neutrophil_up_gp$pvalue_plots$kegg_plot_over

clinic_neutrophil_up_gp$pvalue_plots$reactome_plot_over

clinic_neutrophil_down_gp <- simple_gprofiler(clinic_neutrophil_sigenes_down)
## Performing gProfiler GO search of 470 genes against hsapiens.
## GO search found 62 hits.
## Performing gProfiler KEGG search of 470 genes against hsapiens.
## KEGG search found 12 hits.
## Performing gProfiler REAC search of 470 genes against hsapiens.
## REAC search found 77 hits.
## Performing gProfiler MI search of 470 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 470 genes against hsapiens.
## TF search found 21 hits.
## Performing gProfiler CORUM search of 470 genes against hsapiens.
## CORUM search found 9 hits.
## Performing gProfiler HP search of 470 genes against hsapiens.
## HP search found 7 hits.
clinic_neutrophil_down_gp$pvalue_plots$kegg_plot_over

clinic_neutrophil_down_gp$pvalue_plots$reactome_plot_over

13 Visualize: Plot the clinical samples by cure/fail

Let us recolor the same plot by cure/fail followed by a concatenation of the cell type and cure/fail. In the following block, the clinical samples are plotted once with the most common normalization (log,cpm,quant,filtered) method followed by a plot of the data using svaseq adjusted values and without quantile normalization.

Thus, the following block switches the colors of the groups to the clinical state (cure/fail) and shapes by cell type.

hs_clinical_norm <- sm(normalize_expt(hs_clinical, filter="simple", transform="log2",
                                      norm="quant", convert="cpm"))
clinical_pca <- plot_pca(hs_clinical_norm, plot_labels=FALSE,
                         cis=NULL,
                         plot_title="PCA - clinical samples")
dev <- pp(file=glue("images/all_clinical_nobatch_pca-v{ver}.png"), height=8, width=16)
clinical_pca$plot
closed <- dev.off()
clinical_pca$plot

hs_clinical_nb <- normalize_expt(hs_clinical, filter="simple", transform="log2",
                                 batch="svaseq", convert="cpm")
## Removing 1865 low-count genes (18058 remaining).
## Setting 158794 low elements to zero.
## transform_counts: Found 158794 values equal to 0, adding 1 to the matrix.
hs_clinical_nb_pca <- plot_pca(hs_clinical_nb)
## plot labels was not set and there are more than 100 samples, disabling it.
dev <- pp(file=glue("images/all_clinical_svaseqbatch_pca-v{ver}.png"), height=6, width=8)
hs_clinical_nb_pca$plot
closed <- dev.off()
hs_clinical_nb_pca$plot

clinical_pca_info <- pca_information(
    hs_clinical_norm, plot_pcas=TRUE, num_components = 30,
    expt_factors=c("visitnumber", "typeofcells", "clinicaloutcome",
                   "clinic", "donor"))
## plot labels was not set and there are more than 100 samples, disabling it.
dev <- pp(file="images/clinical_samples_neglogp_pcs.png")
clinical_pca_info$anova_neglogp_heatmap
closed <- dev.off()
clinical_pca_info$anova_neglogp_heatmap

clinical_pca_info$pca_plots$PC20_PC29
## Warning: ggrepel: 138 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

clinical_scores <- pca_highscores(hs_clinical_norm)
clinical_scores[["highest"]][,"Comp.20"]
##  [1] "14.03:ENSG00000266302" "9.344:ENSG00000163993" "6.935:ENSG00000129824"
##  [4] "6.362:ENSG00000067048" "5.933:ENSG00000171860" "5.535:ENSG00000196526"
##  [7] "5.304:ENSG00000198692" "5.088:ENSG00000099725" "4.65:ENSG00000185897" 
## [10] "4.499:ENSG00000106565" "4.471:ENSG00000144681" "4.422:ENSG00000012817"
## [13] "4.381:ENSG00000176834" "4.354:ENSG00000118432" "4.285:ENSG00000073464"
## [16] "4.145:ENSG00000129295" "4.134:ENSG00000178538" "3.972:ENSG00000198178"
## [19] "3.944:ENSG00000134460" "3.93:ENSG00000152766"
clinical_scores[["highest"]][,"Comp.27"]
##  [1] "13.72:ENSG00000244734" "11.84:ENSG00000188536" "9.716:ENSG00000206172"
##  [4] "5.305:ENSG00000266302" "4.884:ENSG00000183570" "4.333:ENSG00000277632"
##  [7] "3.539:ENSG00000130766" "3.435:ENSG00000198848" "3.419:ENSG00000158578"
## [10] "3.401:ENSG00000136732" "3.168:ENSG00000134824" "3.142:ENSG00000101220"
## [13] "3.069:ENSG00000237541" "3.023:ENSG00000122877" "2.958:ENSG00000120738"
## [16] "2.957:ENSG00000123358" "2.948:ENSG00000223609" "2.937:ENSG00000142583"
## [19] "2.919:ENSG00000133048" "2.913:ENSG00000153283"

13.1 Iterative SVA followed by PCA

Another way to explore the effect of SVA is to iteratively increase the number of SVs removed by it and look at some simple plots of the resulting data. Ideally, this should complement the methods employed by Theresa.

first <- normalize_expt(hs_clinical, transform="log2", convert="cpm",
                        filter = TRUE, batch="svaseq", surrogates=1)
## Removing 5601 low-count genes (14322 remaining).
## Setting 206667 low elements to zero.
## transform_counts: Found 206667 values equal to 0, adding 1 to the matrix.
first_info <- pca_information(
    first, plot_pcas=TRUE, num_components = 30,
    expt_factors=c("visitnumber", "typeofcells", "clinicaloutcome",
                   "clinic"))
## plot labels was not set and there are more than 100 samples, disabling it.
first_info$anova_neglogp_heatmap

first_info$pca_plots[["PC1_PC2"]]
## Warning in MASS::cov.trob(data[, vars]): Probable convergence failure

## Warning in MASS::cov.trob(data[, vars]): Probable convergence failure
## Warning: ggrepel: 187 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

second <- normalize_expt(hs_clinical, transform="log2", convert="cpm",
                         filter = TRUE, batch="svaseq", surrogates=2) %>%
  set_expt_batches(fact="clinic")
## Removing 5601 low-count genes (14322 remaining).
## Setting 33691 low elements to zero.
## transform_counts: Found 33691 values equal to 0, adding 1 to the matrix.
second_info <- pca_information(
    second, plot_pcas=TRUE, num_components = 30,
    expt_factors=c("visitnumber", "typeofcells", "clinicaloutcome",
                   "clinic"))
## plot labels was not set and there are more than 100 samples, disabling it.
second_info$anova_neglogp_heatmap

third <- normalize_expt(hs_clinical, transform="log2", convert="cpm",
                        filter = TRUE, batch="svaseq", surrogates=3) %>%
  set_expt_batches(fact="clinic")
## Removing 5601 low-count genes (14322 remaining).
## Setting 28785 low elements to zero.
## transform_counts: Found 28785 values equal to 0, adding 1 to the matrix.
third_info <- pca_information(
    third, plot_pcas=TRUE, num_components = 30,
    expt_factors=c("visitnumber", "typeofcells", "clinicaloutcome",
                   "clinic"))
## plot labels was not set and there are more than 100 samples, disabling it.
third_info$anova_neglogp_heatmap

fourth <- normalize_expt(hs_clinical, transform="log2", convert="cpm",
                         filter = TRUE, batch="svaseq", surrogates=4) %>%
  set_expt_batches(fact="clinic")
## Removing 5601 low-count genes (14322 remaining).
## Setting 27785 low elements to zero.
## transform_counts: Found 27785 values equal to 0, adding 1 to the matrix.
fourth_info <- pca_information(
    fourth, plot_pcas=TRUE, num_components = 30,
    expt_factors=c("visitnumber", "typeofcells", "clinicaloutcome",
                   "clinic"))
## plot labels was not set and there are more than 100 samples, disabling it.
fourth_info$anova_neglogp_heatmap

fourth_info[["pca_plots"]][["PC1_PC2"]]
## Warning: ggrepel: 111 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

fifth <- normalize_expt(hs_clinical, transform="log2", convert="cpm",
                        filter = TRUE, batch="svaseq", surrogates=5) %>%
  set_expt_batches(fact="clinic")
## Removing 5601 low-count genes (14322 remaining).
## Setting 28885 low elements to zero.
## transform_counts: Found 28885 values equal to 0, adding 1 to the matrix.
fifth_info <- pca_information(
    fifth, plot_pcas=TRUE, num_components = 30,
    expt_factors=c("visitnumber", "typeofcells", "clinicaloutcome",
                   "clinic"))
## plot labels was not set and there are more than 100 samples, disabling it.
fifth_info$anova_neglogp_heatmap

fifth_info[["pca_plots"]][["PC1_PC12"]]
## Warning: ggrepel: 126 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

sixth <- normalize_expt(hs_clinical, transform="log2", convert="cpm",
                        filter = TRUE, batch="svaseq", surrogates=6) %>%
  set_expt_batches(fact="clinic")
## Removing 5601 low-count genes (14322 remaining).
## Setting 25457 low elements to zero.
## transform_counts: Found 25457 values equal to 0, adding 1 to the matrix.
sixth_info <- pca_information(
    sixth, plot_pcas=TRUE, num_components = 30,
    expt_factors=c("visitnumber", "typeofcells", "clinicaloutcome",
                   "clinic"))
## plot labels was not set and there are more than 100 samples, disabling it.
sixth_info$anova_neglogp_heatmap

seventh <- normalize_expt(hs_clinical, transform="log2", convert="cpm",
                          filter = TRUE, batch="svaseq", surrogates=7) %>%
  set_expt_batches(fact="clinic")
## Removing 5601 low-count genes (14322 remaining).
## Setting 25447 low elements to zero.
## transform_counts: Found 25447 values equal to 0, adding 1 to the matrix.
seventh_info <- pca_information(
    seventh, plot_pcas=TRUE, num_components = 30,
    expt_factors=c("visitnumber", "typeofcells", "clinicaloutcome",
                   "clinic"))
## plot labels was not set and there are more than 100 samples, disabling it.
seventh_info$anova_neglogp_heatmap

eighth <- normalize_expt(hs_clinical, transform="log2", convert="cpm",
                        filter = TRUE, batch="svaseq", surrogates=8)
## Removing 5601 low-count genes (14322 remaining).
## Setting 25130 low elements to zero.
## transform_counts: Found 25130 values equal to 0, adding 1 to the matrix.
eighth_info <- pca_information(
    eighth, plot_pcas=TRUE, num_components = 30,
    expt_factors=c("visitnumber", "typeofcells", "clinicaloutcome",
                   "clinic"))
## plot labels was not set and there are more than 100 samples, disabling it.
eighth_info$anova_neglogp_heatmap

14 Dataset: Only Tumaco samples

Our recent discussions have settled one big question regarding which samples to use: We will limit our analyses to only those samples from Tumaco.

The following block will therefore set that group as our default for future analyses.

clinical <- hs_clinical %>%
  subset_expt(subset="clinic=='Tumaco'")
## subset_expt(): There were 192, now there are 131 samples.
clinical_nobiop <- subset_expt(clinical, subset="typeofcells!='biopsy'")
## subset_expt(): There were 131, now there are 116 samples.

14.1 Summarize: Collect Tumaco sample numbers.

At least in theory, everything which follows will be using the above ‘clinical’ data structure. Thus, let us count it up and get a sense of what we will work with.

table(pData(clinical)$drug)
## 
##    antimony miltefosine 
##         123           8
table(pData(clinical)$clinic)
## 
## Tumaco 
##    131
table(pData(clinical)$clinicaloutcome)
## 
##    cure failure 
##      77      54
table(pData(clinical)$typeofcells)
## 
##      biopsy eosinophils   monocytes neutrophils 
##          15          27          45          44
table(pData(clinical)$visit)
## 
##  3  2  1 
## 34 35 62
summary(as.numeric(pData(clinical)$eb_lc_tiempo_evolucion))
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    2.00    4.00    4.00    7.01    8.00   21.00
summary(as.numeric(pData(clinical)$eb_lc_tto_mcto_glucan_dosis))
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##      13      14      19      77      20     999
summary(as.numeric(pData(clinical)$v3_lc_ejey_lesion_mm_1))
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##     3.0     7.2    25.3   367.1   999.0   999.0
summary(as.numeric(pData(clinical)$v3_lc_lesion_area_1))
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##      46     222     999    1122     999    5055
summary(as.numeric(pData(clinical)$v3_lc_ejex_ulcera_mm_1))
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##     0.0     0.0     9.1   360.4   999.0   999.0
table(pData(clinical)$eb_lc_sexo)
## 
##   1   2 
## 106  25
table(pData(clinical)$eb_lc_etnia)
## 
##  1  2  3 
## 84 19 28
summary(as.numeric(pData(clinical)$edad))
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    18.0    23.0    25.0    28.4    34.0    51.0
table(pData(clinical)$eb_lc_peso)
## 
## 100.8  53.9  55.9  57.9  58.1  58.3  58.6    59  59.6    62    63  69.4  74.7 
##     2     9     2     2     7    10     3     8     1     6     6    10     3 
##  75.6    77    78  79.2  83.3  83.4  86.4  93.3 
##     3     9    10    10     4    10     9     7
table(pData(clinical)$eb_lc_estatura)
## 
## 152 154 158 159 160 163 164 165 166 172 173 174 175 176 177 182 183 
##   1  10  15   2   3   9  15  12  10  10   4   8   2   1  10   9  10

14.2 Subset: Overwrite previous data structures with Tumaco-specific versions

I previously made a bunch of data subsets by visit, cell type, etc. So let us overwrite them all with versions which contain only the Tumaco samples.

There is no going back to the Cali samples after this block unless we regenerate the data from the original expressionsets.

biopsy_samples <- biopsy_samples %>%
  subset_expt(subset="clinic=='Tumaco'")
## subset_expt(): There were 19, now there are 15 samples.
eosinophil_samples <- eosinophil_samples %>%
  subset_expt(subset="clinic=='Tumaco'")
## subset_expt(): There were 42, now there are 27 samples.
monocyte_samples <- monocyte_samples %>%
  subset_expt(subset="clinic=='Tumaco'")
## subset_expt(): There were 66, now there are 45 samples.
neutrophil_samples <- neutrophil_samples %>%
  subset_expt(subset="clinic=='Tumaco'")
## subset_expt(): There were 65, now there are 44 samples.
v1_samples <- v1_samples %>%
  subset_expt(subset="clinic=='Tumaco'")
## subset_expt(): There were 91, now there are 62 samples.
v2_samples <- v2_samples %>%
  subset_expt(subset="clinic=='Tumaco'")
## subset_expt(): There were 50, now there are 35 samples.
v3_samples <- v3_samples %>%
  subset_expt(subset="clinic=='Tumaco'")
## subset_expt(): There were 51, now there are 34 samples.
v1_eosinophils <- v1_eosinophils %>%
  subset_expt(subset="clinic=='Tumaco'")
## subset_expt(): There were 15, now there are 9 samples.
v2_eosinophils <- v2_eosinophils %>%
  subset_expt(subset="clinic=='Tumaco'")
## subset_expt(): There were 14, now there are 9 samples.
v3_eosinophils <- v3_eosinophils %>%
  subset_expt(subset="clinic=='Tumaco'")
## subset_expt(): There were 13, now there are 9 samples.
v1_monocytes <- v1_monocytes %>%
  subset_expt(subset="clinic=='Tumaco'")
## subset_expt(): There were 29, now there are 19 samples.
v2_monocytes <- v2_monocytes %>%
  subset_expt(subset="clinic=='Tumaco'")
## subset_expt(): There were 18, now there are 13 samples.
v3_monocytes <- v3_monocytes %>%
  subset_expt(subset="clinic=='Tumaco'")
## subset_expt(): There were 19, now there are 13 samples.
v1_neutrophils <- v1_neutrophils %>%
  subset_expt(subset="clinic=='Tumaco'")
## subset_expt(): There were 28, now there are 19 samples.
v2_neutrophils <- v2_neutrophils %>%
  subset_expt(subset="clinic=='Tumaco'")
## subset_expt(): There were 18, now there are 13 samples.
v3_neutrophils <- v3_neutrophils %>%
  subset_expt(subset="clinic=='Tumaco'")
## subset_expt(): There were 19, now there are 12 samples.

14.3 Visualize: Repeat plots using only the Tumaco samples

Now we have a new, smaller set of primary samples which are categorized by cell type.

14.3.1 Visualize: Biopsy samples only Tumaco

Sadly, the biopsy samples remain basically impenetrable. This makes me sad, I think it would be particularly nice if we could judge cure/fail from a visit 1 biopsy.

biopsy_norm <- normalize_expt(biopsy_samples, transform="log2", convert="cpm",
  norm="quant", filter=TRUE)
## Removing 6368 low-count genes (13555 remaining).
## transform_counts: Found 141 values equal to 0, adding 1 to the matrix.
biopsy_pca <- plot_pca(biopsy_norm,
  plot_labels=FALSE)
dev <- pp(file="images/biopsys_tumaco_norm.png")
biopsy_pca$plot
closed <- dev.off()
biopsy_pca$plot

biopsy_nb <- normalize_expt(biopsy_samples, transform="log2", convert="cpm",
                                     batch="svaseq", filter=TRUE)
## Removing 6368 low-count genes (13555 remaining).
## Setting 168 low elements to zero.
## transform_counts: Found 168 values equal to 0, adding 1 to the matrix.
biopsy_nb_pca <- plot_pca(biopsy_nb, plot_labels=FALSE)
dev <- pp(file="images/biopsys_tumaco_norm_sva.png")
biopsy_nb_pca$plot
closed <- dev.off()
biopsy_nb_pca$plot

14.3.2 Visualize: Monocyte samples only Tumaco

In contrast, I suspect that we can get meaningful data from the other cell types. The monocyte samples are still a bit messy.

monocyte_norm <- normalize_expt(monocyte_samples, transform="log2", convert="cpm",
  norm="quant", filter=TRUE)
## Removing 9025 low-count genes (10898 remaining).
## transform_counts: Found 5 values equal to 0, adding 1 to the matrix.
monocyte_pca <- plot_pca(monocyte_norm,
  plot_labels=FALSE)
dev <- pp(file="images/monocytes_tumaco_norm.png")
monocyte_pca$plot
closed <- dev.off()
monocyte_pca$plot

monocyte_nb <- normalize_expt(monocyte_samples, transform="log2", convert="cpm",
                                     batch="svaseq", filter=TRUE)
## Removing 9025 low-count genes (10898 remaining).
## Setting 799 low elements to zero.
## transform_counts: Found 799 values equal to 0, adding 1 to the matrix.
monocyte_nb_pca <- plot_pca(monocyte_nb, plot_labels=FALSE)
dev <- pp(file="images/monocytes_tumaco_norm_sva.png")
monocyte_nb_pca$plot
closed <- dev.off()
monocyte_nb_pca$plot

14.3.3 Visualize: Neutrophil samples only Tumaco

Well, really all the cell types remain pretty messy. There is always at least one person in one visit or another who really does not fit well with the rest of the cohort.

neutrophil_norm <- normalize_expt(neutrophil_samples, transform="log2", convert="cpm",
  norm="quant", filter=TRUE)
## Removing 10762 low-count genes (9161 remaining).
## transform_counts: Found 1 values equal to 0, adding 1 to the matrix.
neutrophil_pca <- plot_pca(neutrophil_norm,
                           plot_labels=FALSE)
dev <- pp(file="images/neutrophils_tumaco_norm.png")
neutrophil_pca$plot
closed <- dev.off()
neutrophil_pca$plot

neutrophil_nb <- normalize_expt(neutrophil_samples, transform="log2", convert="cpm",
                                     batch="svaseq", filter=TRUE)
## Removing 10762 low-count genes (9161 remaining).
## Setting 831 low elements to zero.
## transform_counts: Found 831 values equal to 0, adding 1 to the matrix.
neutrophil_nb_pca <- plot_pca(neutrophil_nb, plot_labels=FALSE)
dev <- pp(file="images/neutrophils_tumaco_norm_sva.png")
neutrophil_nb_pca$plot
closed <- dev.off()
neutrophil_nb_pca$plot

14.3.4 Visualize: Eosinophil samples only Tumaco

eosinophil_norm <- normalize_expt(eosinophil_samples, transform="log2", convert="cpm",
  norm="quant", filter=TRUE)
## Removing 9379 low-count genes (10544 remaining).
## transform_counts: Found 1 values equal to 0, adding 1 to the matrix.
eosinophil_pca <- plot_pca(eosinophil_norm,
  plot_labels=FALSE)
dev <- pp(file="images/eosinophils_tumaco_norm.png")
eosinophil_pca$plot
closed <- dev.off()
eosinophil_pca$plot

eosinophil_nb <- normalize_expt(eosinophil_samples, transform="log2", convert="cpm",
                                     batch="svaseq", filter=TRUE)
## Removing 9379 low-count genes (10544 remaining).
## Setting 374 low elements to zero.
## transform_counts: Found 374 values equal to 0, adding 1 to the matrix.
eosinophil_nb_pca <- plot_pca(eosinophil_nb, plot_labels=FALSE)
dev <- pp(file="images/eosinophils_tumaco_norm_sva.png")
eosinophil_nb_pca$plot
closed <- dev.off()
eosinophil_nb_pca$plot

14.3.5 Visualize: Look at Cell types C/F by visit

14.3.5.1 Monocytes, Visit 1

monocyte_v1 <- subset_expt(monocyte_samples, subset = "visitnumber=='1'")
## subset_expt(): There were 45, now there are 19 samples.
monocyte_v1_norm <- normalize_expt(monocyte_v1, norm = "quant", convert = "cpm",
                                   transform = "log2", filter = TRUE)
## Removing 9321 low-count genes (10602 remaining).
## transform_counts: Found 1 values equal to 0, adding 1 to the matrix.
monocyte_v1_pca <- plot_pca(monocyte_v1_norm, plot_labels = FALSE)
dev <- pp(file="images/monocytes_v1_cf_norm_pca.png")
monocyte_v1_pca$plot
closed <- dev.off()
monocyte_v1_pca$plot

monocyte_v1_nb <- normalize_expt(monocyte_v1, convert = "cpm",
                            transform = "log2", filter = TRUE, batch = "svaseq")
## Removing 9321 low-count genes (10602 remaining).
## Setting 206 low elements to zero.
## transform_counts: Found 206 values equal to 0, adding 1 to the matrix.
monocyte_v1_nb_pca <- plot_pca(monocyte_v1_nb, plot_labels = FALSE)
dev <- pp(file="images/monocytes_v1_cf_norm_sva_pca.png")
monocyte_v1_nb_pca$plot
closed <- dev.off()
monocyte_v1_nb_pca$plot

14.3.5.2 Monocytes Visit 2

monocyte_v2 <- subset_expt(monocyte_samples, subset = "visitnumber=='2'")
## subset_expt(): There were 45, now there are 13 samples.
monocyte_v2_norm <- normalize_expt(monocyte_v2, norm = "quant", convert = "cpm",
                                   transform = "log2", filter = TRUE)
## Removing 9403 low-count genes (10520 remaining).
## transform_counts: Found 1 values equal to 0, adding 1 to the matrix.
monocyte_v2_pca <- plot_pca(monocyte_v2_norm, plot_labels = FALSE)
dev <- pp(file="images/monocytes_v2_cf_norm_pca.png")
monocyte_v2_pca$plot
closed <- dev.off()
monocyte_v2_pca$plot

monocyte_v2_nb <- normalize_expt(monocyte_v2, convert = "cpm",
                            transform = "log2", filter = TRUE, batch = "svaseq")
## Removing 9403 low-count genes (10520 remaining).
## Setting 115 low elements to zero.
## transform_counts: Found 115 values equal to 0, adding 1 to the matrix.
monocyte_v2_nb_pca <- plot_pca(monocyte_v2_nb, plot_labels = FALSE)
dev <- pp(file="images/monocytes_v2_cf_norm_sva_pca.png")
monocyte_v2_nb_pca$plot
closed <- dev.off()
monocyte_v2_nb_pca$plot

14.3.5.3 Monocytes Visit 3

monocyte_v3 <- subset_expt(monocyte_samples, subset = "visitnumber=='3'")
## subset_expt(): There were 45, now there are 13 samples.
monocyte_v3_norm <- normalize_expt(monocyte_v3, norm = "quant", convert = "cpm",
                                   transform = "log2", filter = TRUE)
## Removing 9549 low-count genes (10374 remaining).
## transform_counts: Found 16 values equal to 0, adding 1 to the matrix.
monocyte_v3_pca <- plot_pca(monocyte_v3_norm, plot_labels = FALSE)
dev <- pp(file="images/monocytes_v3_cf_norm_pca.png")
monocyte_v3_pca$plot
closed <- dev.off()
monocyte_v3_pca$plot

monocyte_v3_nb <- normalize_expt(monocyte_v3, convert = "cpm",
                                 transform = "log2", filter = TRUE, batch = "svaseq")
## Removing 9549 low-count genes (10374 remaining).
## Setting 55 low elements to zero.
## transform_counts: Found 55 values equal to 0, adding 1 to the matrix.
monocyte_v3_nb_pca <- plot_pca(monocyte_v3_nb, plot_labels = FALSE)
dev <- pp(file="images/monocytes_v3_cf_norm_sva_pca.png")
monocyte_v3_nb_pca$plot
closed <- dev.off()
monocyte_v3_nb_pca$plot

14.3.5.4 Neutrophils, Visit 1

neutrophil_v1 <- subset_expt(neutrophil_samples, subset = "visitnumber=='1'")
## subset_expt(): There were 44, now there are 19 samples.
neutrophil_v1_norm <- normalize_expt(neutrophil_v1, norm = "quant", convert = "cpm",
                                   transform = "log2", filter = TRUE)
## Removing 11091 low-count genes (8832 remaining).
## transform_counts: Found 2 values equal to 0, adding 1 to the matrix.
neutrophil_v1_pca <- plot_pca(neutrophil_v1_norm, plot_labels = FALSE)
dev <- pp(file="images/neutrophils_v1_cf_norm_pca.png")
neutrophil_v1_pca$plot
closed <- dev.off()
neutrophil_v1_pca$plot

neutrophil_v1_nb <- normalize_expt(neutrophil_v1, convert = "cpm",
                            transform = "log2", filter = TRUE, batch = "ruvg")
## Removing 11091 low-count genes (8832 remaining).
## Warning in RUVSeq::RUVg(linear_mtrx, ruv_controls, k = chosen_surrogates): The expression matrix does not contain counts.
## Please, pass a matrix of counts (not logged) or set isLog to TRUE to skip the log transformation
## Setting 251 low elements to zero.
## transform_counts: Found 251 values equal to 0, adding 1 to the matrix.
neutrophil_v1_nb_pca <- plot_pca(neutrophil_v1_nb, plot_labels = FALSE)
dev <- pp(file="images/neutrophils_v1_cf_norm_sva_pca.png")
neutrophil_v1_nb_pca$plot
closed <- dev.off()
neutrophil_v1_nb_pca$plot

14.3.5.5 Neutrophils Visit 2

neutrophil_v2 <- subset_expt(neutrophil_samples, subset = "visitnumber=='2'")
## subset_expt(): There were 44, now there are 13 samples.
neutrophil_v2_norm <- normalize_expt(neutrophil_v2, norm = "quant", convert = "cpm",
                                   transform = "log2", filter = TRUE)
## Removing 11473 low-count genes (8450 remaining).
## transform_counts: Found 2 values equal to 0, adding 1 to the matrix.
neutrophil_v2_pca <- plot_pca(neutrophil_v2_norm, plot_labels = FALSE)
dev <- pp(file="images/neutrophils_v2_cf_norm_pca.png")
neutrophil_v2_pca$plot
closed <- dev.off()
neutrophil_v2_pca$plot

neutrophil_v2_nb <- normalize_expt(neutrophil_v2, convert = "cpm",
                            transform = "log2", filter = TRUE, batch = "svaseq")
## Removing 11473 low-count genes (8450 remaining).
## Setting 78 low elements to zero.
## transform_counts: Found 78 values equal to 0, adding 1 to the matrix.
neutrophil_v2_nb_pca <- plot_pca(neutrophil_v2_nb, plot_labels = FALSE)
dev <- pp(file="images/neutrophils_v2_cf_norm_sva_pca.png")
neutrophil_v2_nb_pca$plot
closed <- dev.off()
neutrophil_v2_nb_pca$plot

14.3.5.6 Neutrophils Visit 3

neutrophil_v3 <- subset_expt(neutrophil_samples, subset = "visitnumber=='3'")
## subset_expt(): There were 44, now there are 12 samples.
neutrophil_v3_norm <- normalize_expt(neutrophil_v3, norm = "quant", convert = "cpm",
                                   transform = "log3", filter = TRUE)
## Removing 11420 low-count genes (8503 remaining).
## transform_counts: Found 2 values equal to 0, adding 1 to the matrix.
## Did not recognize the transformation, leaving the table.
##  Recognized transformations include: 'log2', 'log10', 'log'
neutrophil_v3_pca <- plot_pca(neutrophil_v3_norm, plot_labels = FALSE)
dev <- pp(file="images/neutrophils_v3_cf_norm_pca.png")
neutrophil_v3_pca$plot
closed <- dev.off()
neutrophil_v3_pca$plot

neutrophil_v3_nb <- normalize_expt(neutrophil_v3, convert = "cpm",
                            transform = "log2", filter = TRUE, batch = "svaseq")
## Removing 11420 low-count genes (8503 remaining).
## Setting 83 low elements to zero.
## transform_counts: Found 83 values equal to 0, adding 1 to the matrix.
neutrophil_v3_nb_pca <- plot_pca(neutrophil_v3_nb, plot_labels = FALSE)
dev <- pp(file="images/neutrophils_v3_cf_norm_sva_pca.png")
neutrophil_v3_nb_pca$plot
closed <- dev.off()
neutrophil_v3_nb_pca$plot

14.3.5.7 Eosinophils, Visit 1

eosinophil_v1 <- subset_expt(eosinophil_samples, subset = "visitnumber=='1'")
## subset_expt(): There were 27, now there are 9 samples.
eosinophil_v1_norm <- normalize_expt(eosinophil_v1, norm = "quant", convert = "cpm",
                                   transform = "log2", filter = TRUE)
## Removing 9886 low-count genes (10037 remaining).
## transform_counts: Found 1 values equal to 0, adding 1 to the matrix.
eosinophil_v1_pca <- plot_pca(eosinophil_v1_norm, plot_labels = FALSE)
dev <- pp(file="images/eosinophils_v1_cf_norm_pca.png")
eosinophil_v1_pca$plot
closed <- dev.off()
eosinophil_v1_pca$plot

eosinophil_v1_nb <- normalize_expt(eosinophil_v1, convert = "cpm",
                            transform = "log2", filter = TRUE, batch = "svaseq")
## Removing 9886 low-count genes (10037 remaining).
## Setting 53 low elements to zero.
## transform_counts: Found 53 values equal to 0, adding 1 to the matrix.
eosinophil_v1_nb_pca <- plot_pca(eosinophil_v1_nb, plot_labels = FALSE)
dev <- pp(file="images/eosinophils_v1_cf_norm_sva_pca.png")
eosinophil_v1_nb_pca$plot
closed <- dev.off()
eosinophil_v1_nb_pca$plot

14.3.5.8 Eosinophils Visit 2

eosinophil_v2 <- subset_expt(eosinophil_samples, subset = "visitnumber=='2'")
## subset_expt(): There were 27, now there are 9 samples.
eosinophil_v2_norm <- normalize_expt(eosinophil_v2, norm = "quant", convert = "cpm",
                                   transform = "log2", filter = TRUE)
## Removing 9808 low-count genes (10115 remaining).
## transform_counts: Found 1 values equal to 0, adding 1 to the matrix.
eosinophil_v2_pca <- plot_pca(eosinophil_v2_norm, plot_labels = FALSE)
dev <- pp(file="images/eosinophils_v2_cf_norm_pca.png")
eosinophil_v2_pca$plot
closed <- dev.off()
eosinophil_v2_pca$plot

eosinophil_v2_nb <- normalize_expt(eosinophil_v2, convert = "cpm",
                            transform = "log2", filter = TRUE, batch = "svaseq")
## Removing 9808 low-count genes (10115 remaining).
## Setting 90 low elements to zero.
## transform_counts: Found 90 values equal to 0, adding 1 to the matrix.
eosinophil_v2_nb_pca <- plot_pca(eosinophil_v2_nb, plot_labels = FALSE)
dev <- pp(file="images/eosinophils_v2_cf_norm_sva_pca.png")
eosinophil_v2_nb_pca$plot
closed <- dev.off()
eosinophil_v2_nb_pca$plot

14.3.5.9 Eosinophils Visit 3

eosinophil_v3 <- subset_expt(eosinophil_samples, subset = "visitnumber=='3'")
## subset_expt(): There were 27, now there are 9 samples.
eosinophil_v3_norm <- normalize_expt(eosinophil_v3, norm = "quant", convert = "cpm",
                                   transform = "log3", filter = TRUE)
## Removing 9845 low-count genes (10078 remaining).
## transform_counts: Found 1 values equal to 0, adding 1 to the matrix.
## Did not recognize the transformation, leaving the table.
##  Recognized transformations include: 'log2', 'log10', 'log'
eosinophil_v3_pca <- plot_pca(eosinophil_v3_norm, plot_labels = FALSE)
dev <- pp(file="images/eosinophils_v3_cf_norm_pca.png")
eosinophil_v3_pca$plot
closed <- dev.off()
eosinophil_v3_pca$plot

eosinophil_v3_nb <- normalize_expt(eosinophil_v3, convert = "cpm",
                            transform = "log2", filter = TRUE, batch = "svaseq")
## Removing 9845 low-count genes (10078 remaining).
## Setting 48 low elements to zero.
## transform_counts: Found 48 values equal to 0, adding 1 to the matrix.
eosinophil_v3_nb_pca <- plot_pca(eosinophil_v3_nb, plot_labels = FALSE)
dev <- pp(file="images/eosinophils_v3_cf_norm_sva_pca.png")
eosinophil_v3_nb_pca$plot
closed <- dev.off()
eosinophil_v3_nb_pca$plot

14.4 Recategorize: Concatenate cure/fail and cell type

In the following block the experimental condition was reset to the concatenation of clinical outcome and type of cells. There are an insufficient number of biopsy samples for them to be useful in this visualization, so they are ignored.

desired_levels <- c("cure_biopsy", "failure_biopsy", "cure_eosinophils", "failure_eosinophils",
                    "cure_monocytes", "failure_monocytes", "cure_neutrophils", "failure_neutrophils")
new_fact <- factor(
    paste0(pData(clinical)[["condition"]], "_",
           pData(clinical)[["batch"]]),
    levels=desired_levels)

clinical_concat <- set_expt_conditions(clinical, fact = new_fact) %>%
  set_expt_batches(fact = "visitnumber") %>%
  set_expt_colors(cf_type_colors) %>%
  subset_expt(subset="typeofcells!='biopsy'")
## subset_expt(): There were 131, now there are 116 samples.
## Try to ensure that the levels stay in the order I want
meta <- pData(clinical_concat) %>%
  mutate(condition = fct_relevel(condition, desired_levels))
## Warning: Unknown levels in `f`: cure_biopsy, failure_biopsy
pData(clinical_concat) <- meta

14.4.1 Visualize: Look at Tumaco-only samples by cell type and cure/fail

The following block is pretty wild to my eyes; it seems to me that the variances introduced by cell type basically wipe out the apparent differences between cure/fail that we were able to see previously.

I suppose this is not entirely surprising, but when we had the Cali samples it at least looked like there were differences which were explicitly between cure/fail across cell types. I suppose this means those differences were actually coming from the unbalanced state of the two clinics from the perspective of clinic.

clinical_concat_norm <- normalize_expt(clinical_concat, transform = "log2", convert = "cpm",
                                       norm = "quant", filter = TRUE)
## Removing 7985 low-count genes (11938 remaining).
## transform_counts: Found 95 values equal to 0, adding 1 to the matrix.
clinical_concat_norm_pca <- plot_pca(clinical_concat_norm)
## plot labels was not set and there are more than 100 samples, disabling it.
dev <- pp(file=glue("images/clinical_concatenated_normalized_pca-v{ver}.png"), height=6, width=10)
clinical_concat_norm_pca$plot
closed <- dev.off()
clinical_concat_norm_pca$plot

clinical_concat_nb <- normalize_expt(clinical_concat, transform = "log2", convert = "cpm",
                                     batch = "svaseq", filter = TRUE)
## Removing 7985 low-count genes (11938 remaining).
## Setting 32996 low elements to zero.
## transform_counts: Found 32996 values equal to 0, adding 1 to the matrix.
clinical_concat_nb_pca <- plot_pca(clinical_concat_nb)
## plot labels was not set and there are more than 100 samples, disabling it.
dev <- pp(file=glue("images/clinical_concatenated_svaseqbatch_pca-v{ver}.png"), height=6, width=12)
clinical_concat_nb_pca$plot
closed <- dev.off()
clinical_concat_nb_pca$plot

15 Visit comparisons

Let us shift the focus from cell type and/or Cure/Fail to the visit number. As you are likely aware, the three visits are significantly spread apart according to the clinical treatment of each patient. Thus we will now separate the samples by visit in order to more easily see what new patterns emerge.

15.1 Recategorize: All visits together

Now let us shift the view slightly to focus on changes observed over time.

visit_expt <- set_expt_conditions(clinical, fact = "visitnumber") %>%
  set_expt_batches(fact = "clinicaloutcome") %>%
  subset_expt(subset="typeofcells!='biopsy'")
## subset_expt(): There were 131, now there are 116 samples.
visit_norm <- normalize_expt(visit_expt, transform="log2", convert="cpm",
                             norm="quant", filter=TRUE)
## Removing 7985 low-count genes (11938 remaining).
## transform_counts: Found 95 values equal to 0, adding 1 to the matrix.
plot_pca(visit_norm)$plot
## plot labels was not set and there are more than 100 samples, disabling it.

visit_nb <- normalize_expt(visit_expt, transform = "log2", convert="cpm",
                           filter = TRUE, batch = "svaseq")
## Removing 7985 low-count genes (11938 remaining).
## Setting 10370 low elements to zero.
## transform_counts: Found 10370 values equal to 0, adding 1 to the matrix.
visit_nb_pca <- plot_pca(visit_nb)
## plot labels was not set and there are more than 100 samples, disabling it.
dev <- pp(file=glue("images/visit_svaseqbatch_pca-v{ver}.png"), height=7, width=9)
visit_nb_pca$plot
closed <- dev.off()
visit_nb_pca$plot

When looking at all cell types, it is quite difficult to see differences among the three visits.

15.2 Subset: Visits by individual cell types

In the previous block, the data was recategorized by visit, now let us split that data by cell type and see if differences across visit become more evident.

visit_monocyte <- subset_expt(visit_expt, subset = "typeofcells=='monocytes'")
## subset_expt(): There were 116, now there are 45 samples.
visit_neutrophil <- subset_expt(visit_expt, subset = "typeofcells=='neutrophils'")
## subset_expt(): There were 116, now there are 44 samples.
visit_eosinophil <- subset_expt(visit_expt, subset = "typeofcells=='eosinophils'")
## subset_expt(): There were 116, now there are 27 samples.

15.3 Visualize: C/F for only the visit 1 samples

Wen we had both Cali and Tumaco samples, it looked like there was variance suggesting differences between cure and fail for visit 1. I think the following block will suggest pretty strongly that this was not true.

v1_norm <- normalize_expt(v1_samples, transform="log2", convert="cpm",
                          norm="quant", filter=TRUE)
## Removing 5849 low-count genes (14074 remaining).
## transform_counts: Found 281 values equal to 0, adding 1 to the matrix.
plot_pca(v1_norm)$plot
## Warning: ggrepel: 47 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

v1_nb <- normalize_expt(v1_samples, transform = "log2", convert = "cpm",
                        filter = TRUE, batch = "svaseq")
## Removing 5849 low-count genes (14074 remaining).
## Setting 8974 low elements to zero.
## transform_counts: Found 8974 values equal to 0, adding 1 to the matrix.
plot_pca(v1_nb, plot_labels = FALSE)$plot

15.4 Visualize: C/F for only the visit 2 samples

v2_clinical <- subset_expt(v2_samples, subset="visitnumber=='2'") %>%
  set_expt_conditions(fact = "clinicaloutcome") %>%
  set_expt_batches(fact = "typeofcells")
## subset_expt(): There were 35, now there are 35 samples.
v2_nb <- normalize_expt(v2_clinical, transform = "log2", convert = "cpm", norm = "quant",
                        filter = TRUE, batch = "svaseq")
## Warning in normalize_expt(v2_clinical, transform = "log2", convert = "cpm", :
## Quantile normalization and sva do not always play well together.
## Removing 8364 low-count genes (11559 remaining).
## Setting 1786 low elements to zero.
## transform_counts: Found 1786 values equal to 0, adding 1 to the matrix.
plot_pca(v2_nb, plot_labels = FALSE)$plot

15.5 Visualize: C/F for only the visit 3 samples

v3_clinical <- subset_expt(v3_samples, subset="visitnumber=='3'") %>%
  set_expt_conditions(fact = "clinicaloutcome") %>%
  set_expt_batches(fact = "typeofcells")
## subset_expt(): There were 34, now there are 34 samples.
v3_nb <- normalize_expt(v3_clinical, transform = "log2", convert = "cpm", norm = "quant",
                        filter = TRUE, batch = "svaseq")
## Warning in normalize_expt(v3_clinical, transform = "log2", convert = "cpm", :
## Quantile normalization and sva do not always play well together.
## Removing 8474 low-count genes (11449 remaining).
## Setting 1481 low elements to zero.
## transform_counts: Found 1481 values equal to 0, adding 1 to the matrix.
plot_pca(v3_nb, plot_labels = FALSE)$plot

15.5.1 Visualize: Comparing 3 visits by cell type

Separate the samples by cell type in order to more easily observe patterns with respect to visit and clinical outcome.

15.5.1.1 Monocytes across visits

visit_monocyte_norm <- normalize_expt(visit_monocyte, norm = "quant", convert = "cpm",
                                transform = "log2", filter = TRUE)
## Removing 9025 low-count genes (10898 remaining).
## transform_counts: Found 5 values equal to 0, adding 1 to the matrix.
visit_monocyte_pca <- plot_pca(visit_monocyte_norm, plot_labels = FALSE)
dev <- pp(file="images/visit_monocytes_cf_norm_pca.png")
visit_monocyte_pca$plot
closed <- dev.off()
visit_monocyte_pca$plot

visit_monocyte_disheat <- plot_disheat(visit_monocyte_norm)
dev <- pp(file="images/visit_monocytes_cf_norm_disheat.png")
visit_monocyte_disheat$plot
closed <- dev.off()
visit_monocyte_disheat$plot

visit_monocyte_nb <- normalize_expt(visit_monocyte, convert = "cpm",
                                    transform = "log2", filter = TRUE, batch = "svaseq")
## Removing 9025 low-count genes (10898 remaining).
## Setting 741 low elements to zero.
## transform_counts: Found 741 values equal to 0, adding 1 to the matrix.
visit_monocyte_nb_pca <- plot_pca(visit_monocyte_nb, plot_labels = FALSE)
dev <- pp(file="images/monocytes_cf_norm_sva_pca.png")
visit_monocyte_nb_pca$plot
closed <- dev.off()
monocyte_nb_pca$plot

16 Contrasts and colors of interest

cf_contrasts <- list(
    "fail_vs_cure" = c("failure", "cure"))
visit_contrasts <- list(
    "v2v1" = c("c2", "c1"),
    "v3v1" = c("c3", "c1"),
    "v3v2" = c("c3", "c2"))
type_contrasts <- list(
    "mono_biopsy" = c("monocytes", "biopsy"),
    "eosinophil_biopsy" = c("eosinophils", "biopsy"),
    "neutrophil_biopsy" = c("neutrophils", "biopsy"))
visit_cf_contrasts <- list(
    "v1fail_vs_cure" = c("v1failure", "v1cure"),
    "v2fail_vs_cure" = c("v2failure", "v2cure"),
    "v3fail_vs_cure" = c("v3failure", "v3cure"))

Sample IDs starting with 1: Cali IDs starting with 2: Tumaco

17 Differential expression analyses

The primary goal is to learn about cure vs. fail.

17.1 Cure/Fail, all samples

Now let us start performing the various differential expression analyses, starting with the set of all/most clinical samples.

cf_clinical_de <- all_pairwise(clinical, model_batch = "svaseq", filter = TRUE)
## Removing 0 low-count genes (14195 remaining).
## Setting 18912 low elements to zero.
## transform_counts: Found 18912 values equal to 0, adding 1 to the matrix.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.
cf_clinical_tables <- combine_de_tables(
    cf_clinical_de,
    keepers = cf_contrasts,
    excel = glue::glue("excel/cf_clinical_tables-v{ver}.xlsx"))
## Deleting the file excel/cf_clinical_tables-v202205.xlsx before writing the tables.
cf_clinical_sig <- extract_significant_genes(
    cf_clinical_tables,
    excel = glue::glue("excel/cf_clinical_sig-v{ver}.xlsx"))
## Deleting the file excel/cf_clinical_sig-v202205.xlsx before writing the tables.

17.1.1 By cell type

17.1.1.1 Cure/Fail, Biopsies

cf_biopsy_de <- all_pairwise(biopsy_samples, model_batch = "svaseq", filter = TRUE)
## Removing 0 low-count genes (13555 remaining).
## Setting 168 low elements to zero.
## transform_counts: Found 168 values equal to 0, adding 1 to the matrix.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.
cf_biopsy_tables <- combine_de_tables(
    cf_biopsy_de,
    keepers = cf_contrasts,
    excel = glue::glue("excel/cf_biopsy_tables-v{ver}.xlsx"))
## Deleting the file excel/cf_biopsy_tables-v202205.xlsx before writing the tables.
cf_biopsy_sig <- extract_significant_genes(
    cf_biopsy_tables,
    excel = glue::glue("excel/cf_biopsy_sig-v{ver}.xlsx"))
## Deleting the file excel/cf_biopsy_sig-v202205.xlsx before writing the tables.

17.1.1.2 Cure/Fail, Monocytes

cf_monocyte_sva_de <- all_pairwise(monocyte_samples, model_batch = "svaseq", filter = TRUE)
## Removing 0 low-count genes (10898 remaining).
## Setting 799 low elements to zero.
## transform_counts: Found 799 values equal to 0, adding 1 to the matrix.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.
cf_monocyte_sva_tables <- combine_de_tables(
    cf_monocyte_sva_de,
    keepers = cf_contrasts,
    excel = glue::glue("excel/cf_monocyte_sva_tables-v{ver}.xlsx"))
## Deleting the file excel/cf_monocyte_sva_tables-v202205.xlsx before writing the tables.
cf_monocyte_sva_sig <- extract_significant_genes(
    cf_monocyte_sva_tables,
    excel = glue::glue("excel/cf_monocyte_sva_sig-v{ver}.xlsx"))
## Deleting the file excel/cf_monocyte_sva_sig-v202205.xlsx before writing the tables.
cf_monocyte_batchvisit_de <- all_pairwise(monocyte_samples, model_batch = TRUE, filter = TRUE)
## Using limma's removeBatchEffect to visualize with(out) batch inclusion.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.
cf_monocyte_batchvisit_tables <- combine_de_tables(
    cf_monocyte_batchvisit_de,
    keepers = cf_contrasts,
    excel = glue::glue("excel/cf_monocyte_batchvisit_tables-v{ver}.xlsx"))
## Deleting the file excel/cf_monocyte_batchvisit_tables-v202205.xlsx before writing the tables.
cf_monocyte_batchvisit_sig <- extract_significant_genes(
    cf_monocyte_batchvisit_tables,
    excel = glue::glue("excel/cf_monocyte_batchvisit_sig-v{ver}.xlsx"))
## Deleting the file excel/cf_monocyte_batchvisit_sig-v202205.xlsx before writing the tables.

17.1.1.3 Cure/Fail, only the Tumaco samples

cf_monocyte_sva_de <- all_pairwise(monocyte, model_batch = "svaseq", filter = TRUE)
## Error in normalize_expt(input, filter = filter): object 'monocyte' not found
cf_monocyte_sva_tables <- combine_de_tables(
    cf_monocyte_sva_de,
    keepers = cf_contrasts,
    excel = glue::glue("excel/cf_monocyte_tables_sva_tumaco-v{ver}.xlsx"))
## Deleting the file excel/cf_monocyte_tables_sva_tumaco-v202205.xlsx before writing the tables.
cf_monocyte_sva_sig <- extract_significant_genes(
    cf_monocyte_sva_tables,
    excel = glue::glue("excel/cf_monocyte_sva_sig-v{ver}.xlsx"))
## Deleting the file excel/cf_monocyte_sva_sig-v202205.xlsx before writing the tables.
cf_monocyte_batchvisit_de <- all_pairwise(monocyte, model_batch = TRUE, filter = TRUE)
## Error in normalize_expt(input, filter = filter): object 'monocyte' not found
cf_monocyte_batchvisit_tables <- combine_de_tables(
    cf_monocyte_batchvisit_de,
    keepers = cf_contrasts,
    excel = glue::glue("excel/cf_monocyte_tables_batchvisit_tumaco-v{ver}.xlsx"))
## Deleting the file excel/cf_monocyte_tables_batchvisit_tumaco-v202205.xlsx before writing the tables.
cf_monocyte_batchvisit_sig <- extract_significant_genes(
    cf_monocyte_batchvisit_tables,
    excel = glue::glue("excel/cf_monocyte_batchvisit_sig-v{ver}.xlsx"))
## Deleting the file excel/cf_monocyte_batchvisit_sig-v202205.xlsx before writing the tables.
sva_aucc <- calculate_aucc(cf_monocyte_sva_tables[["data"]][["fail_vs_cure"]],
                            tbl2=cf_monocyte_sva_tables[["data"]][["fail_vs_cure"]],
                            py="deseq_adjp", ly="deseq_logfc")
sva_aucc
## $aucc
## [1] 1
## 
## $plot

shared_ids <- rownames(cf_monocyte_sva_tables[["data"]][["fail_vs_cure"]]) %in%
  rownames(cf_monocyte_sva_tables[["data"]][["fail_vs_cure"]])
first <- cf_monocyte_sva_tables[["data"]][["fail_vs_cure"]][shared_ids, ]
second <- cf_monocyte_sva_tables[["data"]][["fail_vs_cure"]][rownames(first), ]
cor.test(first[["deseq_logfc"]], second[["deseq_logfc"]])
## 
##  Pearson's product-moment correlation
## 
## data:  first[["deseq_logfc"]] and second[["deseq_logfc"]]
## t = Inf, df = 10896, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  1 1
## sample estimates:
## cor 
##   1
batch_aucc <- calculate_aucc(cf_monocyte_batchvisit_tables[["data"]][["fail_vs_cure"]],
                            tbl2=cf_monocyte_batchvisit_tables[["data"]][["fail_vs_cure"]],
                            py="deseq_adjp", ly="deseq_logfc")
batch_aucc
## $aucc
## [1] 1
## 
## $plot

shared_ids <- rownames(cf_monocyte_batchvisit_tables[["data"]][["fail_vs_cure"]]) %in%
  rownames(cf_monocyte_batchvisit_tables[["data"]][["fail_vs_cure"]])
first <- cf_monocyte_batchvisit_tables[["data"]][["fail_vs_cure"]][shared_ids, ]
second <- cf_monocyte_batchvisit_tables[["data"]][["fail_vs_cure"]][rownames(first), ]
cor.test(first[["deseq_logfc"]], second[["deseq_logfc"]])
## 
##  Pearson's product-moment correlation
## 
## data:  first[["deseq_logfc"]] and second[["deseq_logfc"]]
## t = 5e+09, df = 10896, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  1 1
## sample estimates:
## cor 
##   1
first_sig_names <- rownames(cf_monocyte_batchvisit_sig[["deseq"]][["ups"]][["fail_vs_cure"]])
second_sig_names <- rownames(cf_monocyte_batchvisit_sig[["deseq"]][["ups"]][["fail_vs_cure"]])
batch_venn_lst <- list(all_batch = first_sig_names, batch = second_sig_names)
batch_venn <- Vennerable::Venn(batch_venn_lst)
Vennerable::plot(batch_venn)

cf_neutrophil_sva_de <- all_pairwise(neutrophil, model_batch = "svaseq", filter = TRUE)
## Error in normalize_expt(input, filter = filter): object 'neutrophil' not found
cf_neutrophil_sva_tables <- combine_de_tables(
    cf_neutrophil_sva_de,
    keepers = cf_contrasts,
    excel = glue::glue("excel/cf_neutrophil_tables_sva_tumaco-v{ver}.xlsx"))
## Error in combine_de_tables(cf_neutrophil_sva_de, keepers = cf_contrasts, : object 'cf_neutrophil_sva_de' not found
cf_neutrophil_sva_sig <- extract_significant_genes(
    cf_neutrophil_sva_tables,
    excel = glue::glue("excel/cf_neutrophil_sva_sig-v{ver}.xlsx"))
## Error in extract_significant_genes(cf_neutrophil_sva_tables, excel = glue::glue("excel/cf_neutrophil_sva_sig-v{ver}.xlsx")): object 'cf_neutrophil_sva_tables' not found
cf_neutrophil_batchvisit_de <- all_pairwise(neutrophil, model_batch = TRUE, filter = TRUE)
## Error in normalize_expt(input, filter = filter): object 'neutrophil' not found
cf_neutrophil_batchvisit_tables <- combine_de_tables(
    cf_neutrophil_batchvisit_de,
    keepers = cf_contrasts,
    excel = glue::glue("excel/cf_neutrophil_tables_batchvisit_tumaco-v{ver}.xlsx"))
## Error in combine_de_tables(cf_neutrophil_batchvisit_de, keepers = cf_contrasts, : object 'cf_neutrophil_batchvisit_de' not found
cf_neutrophil_batchvisit_sig <- extract_significant_genes(
    cf_neutrophil_batchvisit_tables,
    excel = glue::glue("excel/cf_neutrophil_batchvisit_sig-v{ver}.xlsx"))
## Error in extract_significant_genes(cf_neutrophil_batchvisit_tables, excel = glue::glue("excel/cf_neutrophil_batchvisit_sig-v{ver}.xlsx")): object 'cf_neutrophil_batchvisit_tables' not found
sva_aucc <- calculate_aucc(cf_neutrophil_sva_tables[["data"]][["fail_vs_cure"]],
                            tbl2=cf_neutrophil_sva_tables[["data"]][["fail_vs_cure"]],
                            py="deseq_adjp", ly="deseq_logfc")
## Error in nrow(tbl): object 'cf_neutrophil_sva_tables' not found
sva_aucc
## $aucc
## [1] 1
## 
## $plot

shared_ids <- rownames(cf_neutrophil_sva_tables[["data"]][["fail_vs_cure"]]) %in%
  rownames(cf_neutrophil_sva_tables[["data"]][["fail_vs_cure"]])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function '%in%': error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'cf_neutrophil_sva_tables' not found
first <- cf_neutrophil_sva_tables[["data"]][["fail_vs_cure"]][shared_ids, ]
## Error in eval(expr, envir, enclos): object 'cf_neutrophil_sva_tables' not found
second <- cf_neutrophil_sva_tables[["data"]][["fail_vs_cure"]][rownames(first), ]
## Error in eval(expr, envir, enclos): object 'cf_neutrophil_sva_tables' not found
cor.test(first[["deseq_logfc"]], second[["deseq_logfc"]])
## 
##  Pearson's product-moment correlation
## 
## data:  first[["deseq_logfc"]] and second[["deseq_logfc"]]
## t = 5e+09, df = 10896, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  1 1
## sample estimates:
## cor 
##   1
batch_aucc <- calculate_aucc(cf_neutrophil_batchvisit_tables[["data"]][["fail_vs_cure"]],
                            tbl2=cf_neutrophil_batchvisit_tables[["data"]][["fail_vs_cure"]],
                            py="deseq_adjp", ly="deseq_logfc")
## Error in nrow(tbl): object 'cf_neutrophil_batchvisit_tables' not found
batch_aucc
## $aucc
## [1] 1
## 
## $plot

shared_ids <- rownames(cf_neutrophil_batchvisit_tables[["data"]][["fail_vs_cure"]]) %in%
  rownames(cf_neutrophil_batchvisit_tables[["data"]][["fail_vs_cure"]])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function '%in%': error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'cf_neutrophil_batchvisit_tables' not found
first <- cf_neutrophil_batchvisit_tables[["data"]][["fail_vs_cure"]][shared_ids, ]
## Error in eval(expr, envir, enclos): object 'cf_neutrophil_batchvisit_tables' not found
second <- cf_neutrophil_batchvisit_tables[["data"]][["fail_vs_cure"]][rownames(first), ]
## Error in eval(expr, envir, enclos): object 'cf_neutrophil_batchvisit_tables' not found
cor.test(first[["deseq_logfc"]], second[["deseq_logfc"]])
## 
##  Pearson's product-moment correlation
## 
## data:  first[["deseq_logfc"]] and second[["deseq_logfc"]]
## t = 5e+09, df = 10896, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  1 1
## sample estimates:
## cor 
##   1
first_sig_names <- rownames(cf_neutrophil_batchvisit_sig[["deseq"]][["ups"]][["fail_vs_cure"]])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'cf_neutrophil_batchvisit_sig' not found
second_sig_names <- rownames(cf_neutrophil_batchvisit_sig[["deseq"]][["ups"]][["fail_vs_cure"]])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'cf_neutrophil_batchvisit_sig' not found
batch_venn_lst <- list(all_batch = first_sig_names, batch = second_sig_names)
batch_venn <- Vennerable::Venn(batch_venn_lst)
Vennerable::plot(batch_venn)

cf_eosinophil_sva_de <- all_pairwise(eosinophil, model_batch = "svaseq", filter = TRUE)
## Error in normalize_expt(input, filter = filter): object 'eosinophil' not found
cf_eosinophil_sva_tables <- combine_de_tables(
    cf_eosinophil_sva_de,
    keepers = cf_contrasts,
    excel = glue::glue("excel/cf_eosinophil_tables_sva_tumaco-v{ver}.xlsx"))
## Error in combine_de_tables(cf_eosinophil_sva_de, keepers = cf_contrasts, : object 'cf_eosinophil_sva_de' not found
cf_eosinophil_sva_sig <- extract_significant_genes(
    cf_eosinophil_sva_tables,
    excel = glue::glue("excel/cf_eosinophil_sva_sig-v{ver}.xlsx"))
## Error in extract_significant_genes(cf_eosinophil_sva_tables, excel = glue::glue("excel/cf_eosinophil_sva_sig-v{ver}.xlsx")): object 'cf_eosinophil_sva_tables' not found
cf_eosinophil_batchvisit_de <- all_pairwise(eosinophil, model_batch = TRUE, filter = TRUE)
## Error in normalize_expt(input, filter = filter): object 'eosinophil' not found
cf_eosinophil_batchvisit_tables <- combine_de_tables(
    cf_eosinophil_batchvisit_de,
    keepers = cf_contrasts,
    excel = glue::glue("excel/cf_eosinophil_tables_batchvisit_tumaco-v{ver}.xlsx"))
## Error in combine_de_tables(cf_eosinophil_batchvisit_de, keepers = cf_contrasts, : object 'cf_eosinophil_batchvisit_de' not found
cf_eosinophil_batchvisit_sig <- extract_significant_genes(
    cf_eosinophil_batchvisit_tables,
    excel = glue::glue("excel/cf_eosinophil_batchvisit_sig-v{ver}.xlsx"))
## Error in extract_significant_genes(cf_eosinophil_batchvisit_tables, excel = glue::glue("excel/cf_eosinophil_batchvisit_sig-v{ver}.xlsx")): object 'cf_eosinophil_batchvisit_tables' not found
sva_aucc <- calculate_aucc(cf_eosinophil_sva_tables[["data"]][["fail_vs_cure"]],
                            tbl2=cf_eosinophil_sva_tables[["data"]][["fail_vs_cure"]],
                            py="deseq_adjp", ly="deseq_logfc")
## Error in nrow(tbl): object 'cf_eosinophil_sva_tables' not found
sva_aucc
## $aucc
## [1] 1
## 
## $plot

shared_ids <- rownames(cf_eosinophil_sva_tables[["data"]][["fail_vs_cure"]]) %in%
  rownames(cf_eosinophil_sva_tables[["data"]][["fail_vs_cure"]])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function '%in%': error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'cf_eosinophil_sva_tables' not found
first <- cf_eosinophil_sva_tables[["data"]][["fail_vs_cure"]][shared_ids, ]
## Error in eval(expr, envir, enclos): object 'cf_eosinophil_sva_tables' not found
second <- cf_eosinophil_sva_tables[["data"]][["fail_vs_cure"]][rownames(first), ]
## Error in eval(expr, envir, enclos): object 'cf_eosinophil_sva_tables' not found
cor.test(first[["deseq_logfc"]], second[["deseq_logfc"]])
## 
##  Pearson's product-moment correlation
## 
## data:  first[["deseq_logfc"]] and second[["deseq_logfc"]]
## t = 5e+09, df = 10896, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  1 1
## sample estimates:
## cor 
##   1
batch_aucc <- calculate_aucc(cf_eosinophil_batchvisit_tables[["data"]][["fail_vs_cure"]],
                            tbl2=cf_eosinophil_batchvisit_tables[["data"]][["fail_vs_cure"]],
                            py="deseq_adjp", ly="deseq_logfc")
## Error in nrow(tbl): object 'cf_eosinophil_batchvisit_tables' not found
batch_aucc
## $aucc
## [1] 1
## 
## $plot

shared_ids <- rownames(cf_eosinophil_batchvisit_tables[["data"]][["fail_vs_cure"]]) %in%
  rownames(cf_eosinophil_batchvisit_tables[["data"]][["fail_vs_cure"]])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function '%in%': error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'cf_eosinophil_batchvisit_tables' not found
first <- cf_eosinophil_batchvisit_tables[["data"]][["fail_vs_cure"]][shared_ids, ]
## Error in eval(expr, envir, enclos): object 'cf_eosinophil_batchvisit_tables' not found
second <- cf_eosinophil_batchvisit_tables[["data"]][["fail_vs_cure"]][rownames(first), ]
## Error in eval(expr, envir, enclos): object 'cf_eosinophil_batchvisit_tables' not found
cor.test(first[["deseq_logfc"]], second[["deseq_logfc"]])
## 
##  Pearson's product-moment correlation
## 
## data:  first[["deseq_logfc"]] and second[["deseq_logfc"]]
## t = 5e+09, df = 10896, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  1 1
## sample estimates:
## cor 
##   1
first_sig_names <- rownames(cf_eosinophil_batchvisit_sig[["deseq"]][["ups"]][["fail_vs_cure"]])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'cf_eosinophil_batchvisit_sig' not found
second_sig_names <- rownames(cf_eosinophil_batchvisit_sig[["deseq"]][["ups"]][["fail_vs_cure"]])
## Error in h(simpleError(msg, call)): error in evaluating the argument 'x' in selecting a method for function 'rownames': object 'cf_eosinophil_batchvisit_sig' not found
batch_venn_lst <- list(all_batch = first_sig_names, batch = second_sig_names)
batch_venn <- Vennerable::Venn(batch_venn_lst)
Vennerable::plot(batch_venn)

17.1.1.4 Compare monocyte CF, neutrophil CF, eosinophil CF

17.1.1.5 Cure/Fail, Neutrophils

cf_neutrophil_de <- all_pairwise(neutrophil_samples, model_batch = "svaseq", filter = TRUE)
## Removing 0 low-count genes (9161 remaining).
## Setting 831 low elements to zero.
## transform_counts: Found 831 values equal to 0, adding 1 to the matrix.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.
cf_neutrophil_tables <- combine_de_tables(
    cf_neutrophil_de,
    keepers = cf_contrasts,
    excel = glue::glue("excel/cf_neutrophil_tables-v{ver}.xlsx"))
## Deleting the file excel/cf_neutrophil_tables-v202205.xlsx before writing the tables.
cf_neutrophil_sig <- extract_significant_genes(
    cf_neutrophil_tables,
    excel = glue::glue("excel/cf_neutrophil_sig-v{ver}.xlsx"))
## Deleting the file excel/cf_neutrophil_sig-v202205.xlsx before writing the tables.

17.1.1.6 Cure/Fail, Eosinophils

cf_eosinophil_de <- all_pairwise(eosinophil_samples, model_batch = "svaseq", filter = TRUE)
## Removing 0 low-count genes (10544 remaining).
## Setting 374 low elements to zero.
## transform_counts: Found 374 values equal to 0, adding 1 to the matrix.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.
cf_eosinophil_tables <- combine_de_tables(
    cf_eosinophil_de,
    keepers = cf_contrasts,
    excel = glue::glue("excel/cf_eosinophil_tables-v{ver}.xlsx"))
## Deleting the file excel/cf_eosinophil_tables-v202205.xlsx before writing the tables.
cf_eosinophil_sig <- extract_significant_genes(
    cf_eosinophil_tables,
    excel = glue::glue("excel/cf_eosinophil_sig-v{ver}.xlsx"))
## Deleting the file excel/cf_eosinophil_sig-v202205.xlsx before writing the tables.

17.1.1.7 Cure/Fail clinical (Not biopsies)

cf_nobiopsy_de <- all_pairwise(clinical_nobiop, model_batch = "svaseq", filter = TRUE)
## Removing 0 low-count genes (11938 remaining).
## Setting 10310 low elements to zero.
## transform_counts: Found 10310 values equal to 0, adding 1 to the matrix.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.
cf_nobiopsy_tables <- combine_de_tables(
    cf_nobiopsy_de,
    keepers = cf_contrasts,
    excel = glue::glue("excel/cf_nobiopsy_tables-v{ver}.xlsx"))
## Deleting the file excel/cf_nobiopsy_tables-v202205.xlsx before writing the tables.
cf_nobiopsy_sig <- extract_significant_genes(
    cf_nobiopsy_tables,
    excel = glue::glue("excel/cf_nobiopsy_sig-v{ver}.xlsx"))
## Deleting the file excel/cf_nobiopsy_sig-v202205.xlsx before writing the tables.

17.1.2 By visit

For these contrasts, we want to see fail_v1 vs. cure_v1, fail_v2 vs. cure_v2 etc. As a result, we will need to juggle the data slightly and add another set of contrasts.

17.1.3 Setting up

visit_cf_expt_factor <- paste0("v", pData(clinical)[["visitnumber"]],
                               pData(clinical)[["condition"]])
visit_cf_expt <- set_expt_conditions(clinical, fact = visit_cf_expt_factor)

visit_cf_eosinophil <- subset_expt(visit_cf_expt, subset="typeofcells=='eosinophils'")
## subset_expt(): There were 131, now there are 27 samples.
visit_cf_eosinophil <- subset_expt(visit_cf_eosinophil, subset="clinic=='Tumaco'")
## subset_expt(): There were 27, now there are 27 samples.
visit_cf_monocyte <- subset_expt(visit_cf_expt, subset="typeofcells=='monocytes'")
## subset_expt(): There were 131, now there are 45 samples.
visit_cf_monocyte <- subset_expt(visit_cf_monocyte, subset="clinic=='Tumaco'")
## subset_expt(): There were 45, now there are 45 samples.
visit_cf_neutrophil <- subset_expt(visit_cf_expt, subset="typeofcells=='neutrophils'")
## subset_expt(): There were 131, now there are 44 samples.
visit_cf_neutrophil <- subset_expt(visit_cf_neutrophil, subset="clinic=='Tumaco'")
## subset_expt(): There were 44, now there are 44 samples.

17.1.3.1 Cure/Fail by visits, all cell types

visit_cf_all_de <- all_pairwise(visit_cf_expt, model_batch = "svaseq", filter = TRUE)
## Removing 0 low-count genes (14195 remaining).
## Setting 19310 low elements to zero.
## transform_counts: Found 19310 values equal to 0, adding 1 to the matrix.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.

visit_cf_all_tables <- combine_de_tables(
    visit_cf_all_de,
    keepers = visit_cf_contrasts,
    excel = glue::glue("excel/visit_cf_all_tables-v{ver}.xlsx"))
## Deleting the file excel/visit_cf_all_tables-v202205.xlsx before writing the tables.
visit_cf_all_sig <- extract_significant_genes(
    visit_cf_all_tables,
    excel = glue::glue("excel/visit_cf_all_sig-v{ver}.xlsx"))
## Deleting the file excel/visit_cf_all_sig-v202205.xlsx before writing the tables.

17.1.3.2 Cure/Fail by visit, Monocytes

visit_cf_monocyte_de <- all_pairwise(visit_cf_monocyte, model_batch = "svaseq", filter = TRUE)
## Removing 0 low-count genes (10898 remaining).
## Setting 782 low elements to zero.
## transform_counts: Found 782 values equal to 0, adding 1 to the matrix.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.

visit_cf_monocyte_tables <- combine_de_tables(
    visit_cf_monocyte_de,
    keepers = visit_cf_contrasts,
    excel = glue::glue("excel/visit_cf_monocyte_tables-v{ver}.xlsx"))
## Deleting the file excel/visit_cf_monocyte_tables-v202205.xlsx before writing the tables.
visit_cf_monocyte_sig <- extract_significant_genes(
    visit_cf_monocyte_tables,
    excel = glue::glue("excel/visit_cf_monocyte_sig-v{ver}.xlsx"))
## Deleting the file excel/visit_cf_monocyte_sig-v202205.xlsx before writing the tables.
v1fc_deseq_ma <- visit_cf_monocyte_tables[["plots"]][["v1fail_vs_cure"]][["deseq_ma_plots"]][["plot"]]
dev <- pp(file="images/monocyte_cf_de_v1_maplot.png")
v1fc_deseq_ma
closed <- dev.off()
v1fc_deseq_ma

v2fc_deseq_ma <- visit_cf_monocyte_tables[["plots"]][["v2fail_vs_cure"]][["deseq_ma_plots"]][["plot"]]
dev <- pp(file="images/monocyte_cf_de_v2_maplot.png")
v2fc_deseq_ma
closed <- dev.off()
v2fc_deseq_ma

v3fc_deseq_ma <- visit_cf_monocyte_tables[["plots"]][["v3fail_vs_cure"]][["deseq_ma_plots"]][["plot"]]
dev <- pp(file="images/monocyte_cf_de_v3_maplot.png")
v3fc_deseq_ma
closed <- dev.off()
v3fc_deseq_ma

## Repeat for the tumaco subset
visit_cf_monocyte_de <- all_pairwise(visit_cf_monocyte,
                                          model_batch = "svaseq", filter = TRUE)
## Removing 0 low-count genes (10898 remaining).
## Setting 782 low elements to zero.
## transform_counts: Found 782 values equal to 0, adding 1 to the matrix.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.

visit_cf_monocyte_tables <- combine_de_tables(
    visit_cf_monocyte_de,
    keepers = visit_cf_contrasts,
    excel = glue::glue("excel/visit_cf_monocyte_tables-v{ver}.xlsx"))
## Deleting the file excel/visit_cf_monocyte_tables-v202205.xlsx before writing the tables.
visit_cf_monocyte_sig <- extract_significant_genes(
    visit_cf_monocyte_tables,
    excel = glue::glue("excel/visit_cf_monocyte_sig-v{ver}.xlsx"))
## Deleting the file excel/visit_cf_monocyte_sig-v202205.xlsx before writing the tables.

One query from Alejandro is to look at the genes shared up/down across visits. I am not entirely certain we have enough samples for this to work, but let us find out.

I am thinking this is a good place to use the AUCC curves I learned about thanks to Julie Cridland.

Note that the following is all monocyte samples, this should therefore potentially be moved up and a version of this with only the Tumaco samples put here?

v1fc <- visit_cf_monocyte_tables[["data"]][["v1fail_vs_cure"]]
v2fc <- visit_cf_monocyte_tables[["data"]][["v2fail_vs_cure"]]
v3fc <- visit_cf_monocyte_tables[["data"]][["v3fail_vs_cure"]]

v1_sig <- c(
    rownames(visit_cf_monocyte_sig[["deseq"]][["ups"]][["v1fail_vs_cure"]]),
    rownames(visit_cf_monocyte_sig[["deseq"]][["downs"]][["v1fail_vs_cure"]]))
v2_sig <- c(
    rownames(visit_cf_monocyte_sig[["deseq"]][["ups"]][["v2fail_vs_cure"]]),
    rownames(visit_cf_monocyte_sig[["deseq"]][["downs"]][["v2fail_vs_cure"]]))
v3_sig <- c(
    rownames(visit_cf_monocyte_sig[["deseq"]][["ups"]][["v2fail_vs_cure"]]),
    rownames(visit_cf_monocyte_sig[["deseq"]][["downs"]][["v2fail_vs_cure"]]))

monocyte_visit_aucc_v2v1 <- calculate_aucc(v1fc, tbl2=v2fc, py="deseq_adjp", ly="deseq_logfc")
dev <- pp(file="images/monocyte_visit_v2v1_aucc.png")
monocyte_visit_aucc_v2v1[["plot"]]
closed <- dev.off()
monocyte_visit_aucc_v2v1[["plot"]]

monocyte_visit_aucc_v3v1 <- calculate_aucc(v1fc, tbl2=v3fc, py="deseq_adjp", ly="deseq_logfc")
dev <- pp(file="images/monocyte_visit_v3v1_aucc.png")
monocyte_visit_aucc_v3v1[["plot"]]
closed <- dev.off()
monocyte_visit_aucc_v3v1[["plot"]]

17.1.3.3 Repeat for only the Tumaco samples

v1fc_tumaco <- visit_cf_monocyte_tables[["data"]][["v1fail_vs_cure"]]
v2fc_tumaco <- visit_cf_monocyte_tables[["data"]][["v2fail_vs_cure"]]
v3fc_tumaco <- visit_cf_monocyte_tables[["data"]][["v3fail_vs_cure"]]

v1_sig <- c(
    rownames(visit_cf_monocyte_sig[["deseq"]][["ups"]][["v1fail_vs_cure"]]),
    rownames(visit_cf_monocyte_sig[["deseq"]][["downs"]][["v1fail_vs_cure"]]))
v2_sig <- c(
    rownames(visit_cf_monocyte_sig[["deseq"]][["ups"]][["v2fail_vs_cure"]]),
    rownames(visit_cf_monocyte_sig[["deseq"]][["downs"]][["v2fail_vs_cure"]]))
v3_sig <- c(
    rownames(visit_cf_monocyte_sig[["deseq"]][["ups"]][["v2fail_vs_cure"]]),
    rownames(visit_cf_monocyte_sig[["deseq"]][["downs"]][["v2fail_vs_cure"]]))

monocyte_visit_aucc_v2v1 <- calculate_aucc(v1fc_tumaco, tbl2=v2fc_tumaco,
                                                  py="deseq_adjp", ly="deseq_logfc")
dev <- pp(file="images/monocyte_visit_v2v1_aucc.png")
monocyte_visit_aucc_v2v1[["plot"]]
closed <- dev.off()
monocyte_visit_aucc_v2v1[["plot"]]

monocyte_visit_aucc_v3v1 <- calculate_aucc(v1fc_tumaco, tbl2=v3fc_tumaco,
                                                  py="deseq_adjp", ly="deseq_logfc")
dev <- pp(file="images/monocyte_visit_v3v1_aucc.png")
monocyte_visit_aucc_v3v1[["plot"]]
closed <- dev.off()
monocyte_visit_aucc_v3v1[["plot"]]

monocyte_visit_aucc_v3v2 <- calculate_aucc(v3fc_tumaco, tbl2=v2fc_tumaco,
                                                  py="deseq_adjp", ly="deseq_logfc")
dev <- pp(file="images/monocyte_visit_v3v2_aucc.png")
monocyte_visit_aucc_v3v2[["plot"]]
closed <- dev.off()
monocyte_visit_aucc_v3v2[["plot"]]

17.1.3.4 Cure/Fail by visit, Neutrophils

a

visit_cf_neutrophil_de <- all_pairwise(visit_cf_neutrophil, model_batch = "svaseq", filter = TRUE)
## Removing 0 low-count genes (9161 remaining).
## Setting 743 low elements to zero.
## transform_counts: Found 743 values equal to 0, adding 1 to the matrix.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.

visit_cf_neutrophil_tables <- combine_de_tables(
    visit_cf_neutrophil_de,
    keepers = visit_cf_contrasts,
    excel = glue::glue("excel/visit_cf_neutrophil_tables-v{ver}.xlsx"))
## Deleting the file excel/visit_cf_neutrophil_tables-v202205.xlsx before writing the tables.
visit_cf_neutrophil_sig <- extract_significant_genes(
    visit_cf_neutrophil_tables,
    excel = glue::glue("excel/visit_cf_neutrophil_sig-v{ver}.xlsx"))
## Deleting the file excel/visit_cf_neutrophil_sig-v202205.xlsx before writing the tables.

17.1.3.5 Cure/Fail by visit, Eosinophils

visit_cf_eosinophil_de <- all_pairwise(visit_cf_eosinophil, model_batch = "svaseq", filter = TRUE)
## Removing 0 low-count genes (10544 remaining).
## Setting 406 low elements to zero.
## transform_counts: Found 406 values equal to 0, adding 1 to the matrix.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.

visit_cf_eosinophil_tables <- combine_de_tables(
    visit_cf_eosinophil_de,
    keepers = visit_cf_contrasts,
    excel = glue::glue("excel/visit_cf_eosinophil_tables-v{ver}.xlsx"))
## Deleting the file excel/visit_cf_eosinophil_tables-v202205.xlsx before writing the tables.
visit_cf_eosinophil_sig <- extract_significant_genes(
    visit_cf_eosinophil_tables,
    excel = glue::glue("excel/visit_cf_eosinophil_sig-v{ver}.xlsx"))
## Deleting the file excel/visit_cf_eosinophil_sig-v202205.xlsx before writing the tables.

17.2 Persistence in visit 3

Having put some SL read mapping information in the sample sheet, Maria Adelaida added a new column using it with the putative persistence state on a per-sample basis. One question which arised from that: what differences are observable between the persistent yes vs. no samples on a per-cell-type basis among the visit 3 samples.

17.2.1 Setting up

First things first, create the datasets.

persistence_expt <- subset_expt(clinical, subset = "persistence=='Y'|persistence=='N'") %>%
  subset_expt(subset = 'visitnumber==3') %>%
  set_expt_conditions(fact = 'persistence')
## subset_expt(): There were 131, now there are 83 samples.
## subset_expt(): There were 83, now there are 30 samples.
## persistence_biopsy <- subset_expt(persistence_expt, subset = "typeofcells=='biopsy'")
persistence_monocyte <- subset_expt(persistence_expt, subset = "typeofcells=='monocytes'")
## subset_expt(): There were 30, now there are 12 samples.
persistence_neutrophil <- subset_expt(persistence_expt, subset = "typeofcells=='neutrophils'")
## subset_expt(): There were 30, now there are 10 samples.
persistence_eosinophil <- subset_expt(persistence_expt, subset = "typeofcells=='eosinophils'")
## subset_expt(): There were 30, now there are 8 samples.

17.2.2 Take a look

See if there are any patterns which look usable.

## All
persistence_norm <- normalize_expt(persistence_expt, transform = "log2", convert = "cpm",
                                   norm = "quant", filter = TRUE)
## Removing 8537 low-count genes (11386 remaining).
## transform_counts: Found 15 values equal to 0, adding 1 to the matrix.
plot_pca(persistence_norm)$plot
## Warning: ggrepel: 6 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps

persistence_nb <- normalize_expt(persistence_expt, transform = "log2", convert = "cpm",
                                 batch = "svaseq", filter = TRUE)
## Removing 8537 low-count genes (11386 remaining).
## Setting 1538 low elements to zero.
## transform_counts: Found 1538 values equal to 0, adding 1 to the matrix.
plot_pca(persistence_nb)$plot

## Biopsies
##persistence_biopsy_norm <- normalize_expt(persistence_biopsy, transform = "log2", convert = "cpm",
##                                   norm = "quant", filter = TRUE)
##plot_pca(persistence_biopsy_norm)$plot
## Insufficient data

## Monocytes
persistence_monocyte_norm <- normalize_expt(persistence_monocyte, transform = "log2", convert = "cpm",
                                   norm = "quant", filter = TRUE)
## Removing 9597 low-count genes (10326 remaining).
## transform_counts: Found 1 values equal to 0, adding 1 to the matrix.
plot_pca(persistence_monocyte_norm)$plot

persistence_monocyte_nb <- normalize_expt(persistence_monocyte, transform = "log2", convert = "cpm",
                                 batch = "svaseq", filter = TRUE)
## Removing 9597 low-count genes (10326 remaining).
## Setting 46 low elements to zero.
## transform_counts: Found 46 values equal to 0, adding 1 to the matrix.
plot_pca(persistence_monocyte_nb)$plot

## Neutrophils
persistence_neutrophil_norm <- normalize_expt(persistence_neutrophil, transform = "log2", convert = "cpm",
                                   norm = "quant", filter = TRUE)
## Removing 11531 low-count genes (8392 remaining).
## transform_counts: Found 2 values equal to 0, adding 1 to the matrix.
plot_pca(persistence_neutrophil_norm)$plot

persistence_neutrophil_nb <- normalize_expt(persistence_neutrophil, transform = "log2", convert = "cpm",
                                 batch = "svaseq", filter = TRUE)
## Removing 11531 low-count genes (8392 remaining).
## Setting 46 low elements to zero.
## transform_counts: Found 46 values equal to 0, adding 1 to the matrix.
plot_pca(persistence_neutrophil_nb)$plot

## Eosinophils
persistence_eosinophil_norm <- normalize_expt(persistence_eosinophil, transform = "log2", convert = "cpm",
                                   norm = "quant", filter = TRUE)
## Removing 9895 low-count genes (10028 remaining).
## transform_counts: Found 1 values equal to 0, adding 1 to the matrix.
plot_pca(persistence_eosinophil_norm)$plot

persistence_eosinophil_nb <- normalize_expt(persistence_eosinophil, transform = "log2", convert = "cpm",
                                 batch = "svaseq", filter = TRUE)
## Removing 9895 low-count genes (10028 remaining).
## Setting 25 low elements to zero.
## transform_counts: Found 25 values equal to 0, adding 1 to the matrix.
plot_pca(persistence_eosinophil_nb)$plot

17.2.3 persistence DE

persistence_de <- all_pairwise(persistence_expt, filter = TRUE, model_batch = "svaseq")
## Removing 0 low-count genes (11386 remaining).
## Setting 1538 low elements to zero.
## transform_counts: Found 1538 values equal to 0, adding 1 to the matrix.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.
persistence_table <- combine_de_tables(
    persistence_de,
    excel = glue::glue("excel/persistence_all_de-v{ver}.xlsx"))
## Deleting the file excel/persistence_all_de-v202205.xlsx before writing the tables.
persistence_monocyte_de <- all_pairwise(persistence_monocyte, filter = TRUE, model_batch = "svaseq")
## Removing 0 low-count genes (10326 remaining).
## Setting 46 low elements to zero.
## transform_counts: Found 46 values equal to 0, adding 1 to the matrix.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.
persistence_monocyte_table <- combine_de_tables(
    persistence_monocyte_de,
    excel = glue::glue("excel/persistence_monocyte_de-v{ver}.xlsx"))
## Deleting the file excel/persistence_monocyte_de-v202205.xlsx before writing the tables.
persistence_neutrophil_de <- all_pairwise(persistence_neutrophil, filter = TRUE, model_batch = "svaseq")
## Removing 0 low-count genes (8392 remaining).
## Setting 46 low elements to zero.
## transform_counts: Found 46 values equal to 0, adding 1 to the matrix.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.
persistence_neutrophil_table <- combine_de_tables(
    persistence_neutrophil_de,
    excel = glue::glue("excel/persistence_neutrophil_de-v{ver}.xlsx"))
## Deleting the file excel/persistence_neutrophil_de-v202205.xlsx before writing the tables.
persistence_eosinophil_de <- all_pairwise(persistence_eosinophil, filter = TRUE, model_batch = "svaseq")
## Removing 0 low-count genes (10028 remaining).
## Setting 25 low elements to zero.
## transform_counts: Found 25 values equal to 0, adding 1 to the matrix.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.
persistence_eosinophil_table <- combine_de_tables(
    persistence_eosinophil_de,
    excel = glue::glue("excel/persistence_eosinophil_de-v{ver}.xlsx"))
## Deleting the file excel/persistence_eosinophil_de-v202205.xlsx before writing the tables.

17.3 Comparing visits without regard to cure/fail

17.3.1 All cell types

visit_all_de <- all_pairwise(visit_expt, filter = TRUE, model_batch = "svaseq")
## Removing 0 low-count genes (11938 remaining).
## Setting 10370 low elements to zero.
## transform_counts: Found 10370 values equal to 0, adding 1 to the matrix.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.

visit_all_table <- combine_de_tables(
    visit_all_de,
    keepers = visit_contrasts,
    excel = glue::glue("excel/visit_all_de-v{ver}.xlsx"))
## Deleting the file excel/visit_all_de-v202205.xlsx before writing the tables.
visit_all_sig <- extract_significant_genes(
    visit_all_table,
    excel = glue::glue("excel/visit_all_sig-v{ver}.xlsx"))
## Deleting the file excel/visit_all_sig-v202205.xlsx before writing the tables.
visit_all_saved <- save(list = "visit_all_table",
                        file = glue::glue("rda/visit_all_table-v{ver}.rda"))

17.3.2 Monocyte samples

visit_monocyte_de <- all_pairwise(visit_monocyte, filter = TRUE, model_batch = "svaseq")
## Removing 0 low-count genes (10898 remaining).
## Setting 741 low elements to zero.
## transform_counts: Found 741 values equal to 0, adding 1 to the matrix.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.

visit_monocyte_table <- combine_de_tables(
    visit_monocyte_de,
    keepers = visit_contrasts,
    excel = glue::glue("excel/visit_monocyte_de-v{ver}.xlsx"))
## Deleting the file excel/visit_monocyte_de-v202205.xlsx before writing the tables.
visit_monocyte_sig <- extract_significant_genes(
    visit_monocyte_table,
    excel = glue::glue("excel/visit_monocyte_sig-v{ver}.xlsx"))
## Deleting the file excel/visit_monocyte_sig-v202205.xlsx before writing the tables.

17.3.3 Neutrophil samples

visit_neutrophil_de <- all_pairwise(visit_neutrophil, filter = TRUE, model_batch = "svaseq")
## Removing 0 low-count genes (9161 remaining).
## Setting 746 low elements to zero.
## transform_counts: Found 746 values equal to 0, adding 1 to the matrix.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.

visit_neutrophil_table <- combine_de_tables(
    visit_neutrophil_de,
    keepers = visit_contrasts,
    excel = glue::glue("excel/visit_neutrophil_de-v{ver}.xlsx"))
## Deleting the file excel/visit_neutrophil_de-v202205.xlsx before writing the tables.
visit_neutrophil_sig <- extract_significant_genes(
    visit_neutrophil_table,
    excel = glue::glue("excel/visit_neutrophil_sig-v{ver}.xlsx"))
## Deleting the file excel/visit_neutrophil_sig-v202205.xlsx before writing the tables.
visit_neutrophil_saved <- save(list = "visit_neutrophil_table",
                               file = glue::glue("rda/visit_neutrophil_table-v{ver}.rda"))

17.3.4 Eosinophil samples

visit_eosinophil_de <- all_pairwise(visit_eosinophil, filter = TRUE, model_batch = "svaseq")
## Removing 0 low-count genes (10544 remaining).
## Setting 297 low elements to zero.
## transform_counts: Found 297 values equal to 0, adding 1 to the matrix.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.

visit_eosinophil_table <- combine_de_tables(
    visit_eosinophil_de,
    keepers = visit_contrasts,
    excel = glue::glue("excel/visit_eosinophil_de-v{ver}.xlsx"))
## Deleting the file excel/visit_eosinophil_de-v202205.xlsx before writing the tables.
visit_eosinophil_sig <- extract_significant_genes(
    visit_eosinophil_table,
    excel = glue::glue("excel/visit_eosinophil_sig-v{ver}.xlsx"))
## Deleting the file excel/visit_eosinophil_sig-v202205.xlsx before writing the tables.
visit_eosinophil_saved <- save(list = "visit_eosinophil_table",
                               file = glue::glue("rda/visit_eosinophil_table-v{ver}.rda"))

18 Compare the two clinics directly

monocytes_by_place <- set_expt_conditions(monocyte_samples, fact="clinic")
eosinophils_by_place <- set_expt_conditions(eosinophil_samples, fact="clinic")
neutrophils_by_place <- set_expt_conditions(neutrophil_samples, fact="clinic")
biopsies_by_place <- set_expt_conditions(biopsy_samples, fact="clinic")

monocyte_place_de <- all_pairwise(monocytes_by_place, model_batch=TRUE)
## Using limma's removeBatchEffect to visualize with(out) batch inclusion.
## Error in `contrasts<-`(`*tmp*`, value = contr.funs[1 + isOF[nn]]) : 
##   contrasts can be applied only to factors with 2 or more levels
## Error in all_pairwise(monocytes_by_place, model_batch = TRUE): Unable to find the number of conditions in the data.
monocyte_table <- combine_de_tables(
    monocyte_place_de,
    excel="excel/monocytes_by_place-table.xlsx")
## Error in combine_de_tables(monocyte_place_de, excel = "excel/monocytes_by_place-table.xlsx"): object 'monocyte_place_de' not found
monocyte_sig <- extract_significant_genes(
    monocyte_table,
    excel="excel/monocytes_by_place-sig.xlsx")
## Error in extract_significant_genes(monocyte_table, excel = "excel/monocytes_by_place-sig.xlsx"): object 'monocyte_table' not found
eosinophil_place_de <- all_pairwise(eosinophils_by_place, model_batch=TRUE)
## Using limma's removeBatchEffect to visualize with(out) batch inclusion.
## Error in `contrasts<-`(`*tmp*`, value = contr.funs[1 + isOF[nn]]) : 
##   contrasts can be applied only to factors with 2 or more levels
## Error in all_pairwise(eosinophils_by_place, model_batch = TRUE): Unable to find the number of conditions in the data.
eosinophil_table <- combine_de_tables(
    eosinophil_place_de,
    excel="excel/eosinophils_by_place-table.xlsx")
## Error in combine_de_tables(eosinophil_place_de, excel = "excel/eosinophils_by_place-table.xlsx"): object 'eosinophil_place_de' not found
eosinophil_sig <- extract_significant_genes(
    eosinophil_table,
    excel="excel/eosinophils_by_place-sig.xlsx")
## Error in extract_significant_genes(eosinophil_table, excel = "excel/eosinophils_by_place-sig.xlsx"): object 'eosinophil_table' not found
neutrophil_place_de <- all_pairwise(neutrophils_by_place, model_batch=TRUE)
## Using limma's removeBatchEffect to visualize with(out) batch inclusion.
## Error in `contrasts<-`(`*tmp*`, value = contr.funs[1 + isOF[nn]]) : 
##   contrasts can be applied only to factors with 2 or more levels
## Error in all_pairwise(neutrophils_by_place, model_batch = TRUE): Unable to find the number of conditions in the data.
neutrophil_table <- combine_de_tables(
    neutrophil_place_de,
    excel="excel/neutrophils_by_place-table.xlsx")
## Error in combine_de_tables(neutrophil_place_de, excel = "excel/neutrophils_by_place-table.xlsx"): object 'neutrophil_place_de' not found
neutrophil_sig <- extract_significant_genes(
    neutrophil_table,
    excel="excel/neutrophils_by_place-sig.xlsx")
## Error in extract_significant_genes(neutrophil_table, excel = "excel/neutrophils_by_place-sig.xlsx"): object 'neutrophil_table' not found
biopsy_place_de <- all_pairwise(biopsies_by_place, model_batch=TRUE)
## Using limma's removeBatchEffect to visualize with(out) batch inclusion.
## Error in `contrasts<-`(`*tmp*`, value = contr.funs[1 + isOF[nn]]) : 
##   contrasts can be applied only to factors with 2 or more levels
## Error in all_pairwise(biopsies_by_place, model_batch = TRUE): Unable to find the number of conditions in the data.
biopsy_table <- combine_de_tables(
    biopsy_place_de,
    excel="biopsies_by_place-table.xlsx")
## Error in combine_de_tables(biopsy_place_de, excel = "biopsies_by_place-table.xlsx"): object 'biopsy_place_de' not found
biopsy_sig <- extract_significant_genes(
    biopsy_table,
    excel="biopsies_by_place-sig.xlsx")
## Error in extract_significant_genes(biopsy_table, excel = "biopsies_by_place-sig.xlsx"): object 'biopsy_table' not found

19 Likelihood Ratio Testing (LRT)

19.1 Shared patterns across visits

clinical_filt <- normalize_expt(clinical, filter = TRUE)
## Removing 5728 low-count genes (14195 remaining).
lrt_visit <- deseq_lrt(clinical_filt, transform = "vst", interaction = FALSE,
                       interactor_column = "visitnumber",
                       interest_column = "clinicaloutcome")
## converting counts to integer mode
## estimating size factors
## estimating dispersions
## gene-wise dispersion estimates
## mean-dispersion relationship
## final dispersion estimates
## fitting model and testing
## -- replacing outliers and refitting for 256 genes
## -- DESeq argument 'minReplicatesForReplace' = 7 
## -- original counts are preserved in counts(dds)
## estimating dispersions
## fitting model and testing
## A large number of genes was given-- please, make sure this is not an error. Normally, only DE genes will be useful for this function.
## Working with 5303 genes.
## Working with 5303 genes after filtering: minc > 3
## Joining, by = "merge"
## Joining, by = "merge"
## Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.

summary(lrt_visit[["favorite_genes"]])
## Length  Class   Mode 
##      0   NULL   NULL
written <- write_xlsx(data=as.data.frame(lrt_visit[["deseq_table"]]),
                      excel=glue::glue("excel/lrt_clinical_visit-v{ver}.xlsx"))

lrt_monocyte_visit <- deseq_lrt(visit_monocyte, transform = "vst",
                                interaction = FALSE,
                                interactor_column = "visitnumber",
                                interest_column = "clinicaloutcome")
## converting counts to integer mode
## estimating size factors
## estimating dispersions
## gene-wise dispersion estimates
## mean-dispersion relationship
## final dispersion estimates
## fitting model and testing
## -- replacing outliers and refitting for 58 genes
## -- DESeq argument 'minReplicatesForReplace' = 7 
## -- original counts are preserved in counts(dds)
## estimating dispersions
## fitting model and testing
## Working with 17 genes.
## Working with 14 genes after filtering: minc > 3
## Joining, by = "merge"Joining, by = "merge"
## Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.

lrt_monocyte_visit$cluster_data$plot
## NULL
lrt_monocyte_visit <- deseq_lrt(monocyte, transform = "vst",
                                       interaction = FALSE, minc = 1,
                                       interactor_column = "visitnumber",
                                       interest_column = "clinicaloutcome")
## Error in h(simpleError(msg, call)): error in evaluating the argument 'object' in selecting a method for function 'pData': object 'monocyte' not found

19.2 Shared patterns across cell types

lrt_celltype_clinical_test <- deseq_lrt(clinical, transform = "vst",
                                        interactor_column = "typeofcells",
                                        interest_column = "clinicaloutcome")
## converting counts to integer mode
## estimating size factors
## estimating dispersions
## gene-wise dispersion estimates
## mean-dispersion relationship
## final dispersion estimates
## fitting model and testing
## -- replacing outliers and refitting for 18 genes
## -- DESeq argument 'minReplicatesForReplace' = 7 
## -- original counts are preserved in counts(dds)
## estimating dispersions
## fitting model and testing
## Working with 133 genes.
## Working with 130 genes after filtering: minc > 3
## Joining, by = "merge"
## Joining, by = "merge"
## Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
## `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.

deseq_lrt_df <- merge(hs_annot, as.data.frame(lrt_celltype_clinical_test[["deseq_table"]]), all.y=TRUE,
                      by="row.names")
rownames(deseq_lrt_df) <- deseq_lrt_df[["Row.names"]]
deseq_lrt_df[["Row.names"]] <- NULL
written <- write_xlsx(data=deseq_lrt_df,
                      excel=glue::glue("excel/lrt_clinical_celltype-v{ver}.xlsx"))

20 Gene Set Analyses

The gene sets we are most likely to consider are the results of the various preceding differential expression analyses.

20.1 GSEA

20.1.1 Cure/Fail groups

In the context of cure vs. fail, we have mixed and matched the data in quite a few different ways.

20.1.1.1 Cure/Fail, all samples

For the moment, let us assume that the default definition of ‘significant’ is sufficient for these analyses, with the knowledge that is not likely to remain true.

The resulting data structures are organized as:

thing[[“deseq”]][[ups"]][[contrast]]

In addition, we have a few ontology-esque tools available, so let us mix and match and see what pops out.

cf_all_up <- cf_clinical_sig[["deseq"]][["ups"]][["fail_vs_cure"]]
dim(cf_all_up)
## [1] 52 58
cf_all_down <- cf_clinical_sig[["deseq"]][["downs"]][["fail_vs_cure"]]
dim(cf_all_down)
## [1] 19 58
cf_all_up_gp <- simple_gprofiler(cf_all_up)
## Performing gProfiler GO search of 52 genes against hsapiens.
## GO search found 21 hits.
## Performing gProfiler KEGG search of 52 genes against hsapiens.
## KEGG search found 2 hits.
## Performing gProfiler REAC search of 52 genes against hsapiens.
## REAC search found 6 hits.
## Performing gProfiler MI search of 52 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 52 genes against hsapiens.
## TF search found 21 hits.
## Performing gProfiler CORUM search of 52 genes against hsapiens.
## CORUM search found 0 hits.
## Performing gProfiler HP search of 52 genes against hsapiens.
## HP search found 0 hits.
cf_all_up_gp[["pvalue_plots"]][["reactome_plot_over"]]

cf_all_up_gp[["pvalue_plots"]][["kegg_plot_over"]]

cf_all_up_gp[["pvalue_plots"]][["mfp_plot_over"]]
## NULL
cf_all_up_gp[["pvalue_plots"]][["bpp_plot_over"]]

cf_all_down_gp <- simple_gprofiler(cf_all_down)
## Performing gProfiler GO search of 19 genes against hsapiens.
## GO search found 1 hits.
## Performing gProfiler KEGG search of 19 genes against hsapiens.
## KEGG search found 7 hits.
## Performing gProfiler REAC search of 19 genes against hsapiens.
## REAC search found 2 hits.
## Performing gProfiler MI search of 19 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 19 genes against hsapiens.
## TF search found 0 hits.
## Performing gProfiler CORUM search of 19 genes against hsapiens.
## CORUM search found 4 hits.
## Performing gProfiler HP search of 19 genes against hsapiens.
## HP search found 2 hits.
cf_all_down_gp[["pvalue_plots"]][["reactome_plot_over"]]

cf_all_down_gp[["pvalue_plots"]][["kegg_plot_over"]]

cf_all_down_gp[["pvalue_plots"]][["mfp_plot_over"]]
## NULL
cf_all_down_gp[["pvalue_plots"]][["bpp_plot_over"]]

## The following lines are intended to test if I can corerce my
## various  ontology outputs to the enrichResult data structure
## provided by clusterProfiler.
## cf_all_up_go <- simple_goseq(cf_all_up, go_db=hs_go, length_db=hs_length)
## cf_all_up_cp <- simple_clusterprofiler(cf_all_up, orgdb="org.Hs.eg.db")
## cf_all_up_tp <- simple_topgo(cf_all_up, go_db=hs_go)

20.1.1.2 Cure/Fail, Biopsies

There are no genes deemed significant in the biopsy comparisons of cure/fail. Oddly, when I looked manually, I thought I saw one candidate gene. In addition, when I stepped through the function manually I got the same gene…

20.1.1.3 Cure/Fail, Monocytes

Try again with monocytes.

cf_monocyte_up <- cf_monocyte_sva_sig[["deseq"]][["ups"]][["fail_vs_cure"]]
dim(cf_monocyte_up)
## [1]  8 58
cf_monocyte_down <- cf_monocyte_sva_sig[["deseq"]][["downs"]][["fail_vs_cure"]]
dim(cf_monocyte_down)
## [1] 16 58
cf_monocyte_up_gp <- simple_gprofiler(cf_monocyte_up)
## Performing gProfiler GO search of 8 genes against hsapiens.
## GO search found 5 hits.
## Performing gProfiler KEGG search of 8 genes against hsapiens.
## KEGG search found 0 hits.
## Performing gProfiler REAC search of 8 genes against hsapiens.
## REAC search found 5 hits.
## Performing gProfiler MI search of 8 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 8 genes against hsapiens.
## TF search found 4 hits.
## Performing gProfiler CORUM search of 8 genes against hsapiens.
## CORUM search found 0 hits.
## Performing gProfiler HP search of 8 genes against hsapiens.
## HP search found 0 hits.
cf_monocyte_up_gp[["pvalue_plots"]][["reactome_plot_over"]]

cf_monocyte_up_gp[["pvalue_plots"]][["kegg_plot_over"]]
## NULL
cf_monocyte_up_gp[["pvalue_plots"]][["bpp_plot_over"]]
## NULL
cf_monocyte_down_gp <- simple_gprofiler(cf_monocyte_down)
## Performing gProfiler GO search of 16 genes against hsapiens.
## GO search found 0 hits.
## Performing gProfiler KEGG search of 16 genes against hsapiens.
## KEGG search found 0 hits.
## Performing gProfiler REAC search of 16 genes against hsapiens.
## REAC search found 0 hits.
## Performing gProfiler MI search of 16 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 16 genes against hsapiens.
## TF search found 0 hits.
## Performing gProfiler CORUM search of 16 genes against hsapiens.
## CORUM search found 1 hits.
## Performing gProfiler HP search of 16 genes against hsapiens.
## HP search found 0 hits.
cf_monocyte_down_gp[["pvalue_plots"]][["reactome_plot_over"]]
## NULL
cf_monocyte_down_gp[["pvalue_plots"]][["kegg_plot_over"]]
## NULL

20.1.1.4 Cure/Fail, Neutrophils

cf_neutrophil_up <- cf_neutrophil_sig[["deseq"]][["ups"]][["fail_vs_cure"]]
dim(cf_neutrophil_up)
## [1]  7 58
cf_neutrophil_down <- cf_neutrophil_sig[["deseq"]][["downs"]][["fail_vs_cure"]]
dim(cf_neutrophil_down)
## [1]  4 58
cf_neutrophil_up_gp <- simple_gprofiler(cf_neutrophil_up)
## Performing gProfiler GO search of 7 genes against hsapiens.
## GO search found 0 hits.
## Performing gProfiler KEGG search of 7 genes against hsapiens.
## KEGG search found 0 hits.
## Performing gProfiler REAC search of 7 genes against hsapiens.
## REAC search found 0 hits.
## Performing gProfiler MI search of 7 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 7 genes against hsapiens.
## TF search found 6 hits.
## Performing gProfiler CORUM search of 7 genes against hsapiens.
## CORUM search found 0 hits.
## Performing gProfiler HP search of 7 genes against hsapiens.
## HP search found 0 hits.
cf_neutrophil_down_gp <- simple_gprofiler(cf_neutrophil_down)
## Performing gProfiler GO search of 4 genes against hsapiens.
## GO search found 0 hits.
## Performing gProfiler KEGG search of 4 genes against hsapiens.
## KEGG search found 0 hits.
## Performing gProfiler REAC search of 4 genes against hsapiens.
## REAC search found 2 hits.
## Performing gProfiler MI search of 4 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 4 genes against hsapiens.
## TF search found 0 hits.
## Performing gProfiler CORUM search of 4 genes against hsapiens.
## CORUM search found 0 hits.
## Performing gProfiler HP search of 4 genes against hsapiens.
## HP search found 0 hits.
cf_neutrophil_down_gp[["pvalue_plots"]][["kegg_plot_over"]]
## NULL

20.1.1.5 Cure/Fail, Eosinophils

cf_eosinophil_up <- cf_eosinophil_sig[["deseq"]][["ups"]][["fail_vs_cure"]]
dim(cf_eosinophil_up)
## [1] 39 58
cf_eosinophil_down <- cf_eosinophil_sig[["deseq"]][["downs"]][["fail_vs_cure"]]
dim(cf_eosinophil_down)
## [1] 16 58
cf_eosinophil_up_gp <- simple_gprofiler(cf_eosinophil_up)
## Performing gProfiler GO search of 39 genes against hsapiens.
## GO search found 11 hits.
## Performing gProfiler KEGG search of 39 genes against hsapiens.
## KEGG search found 1 hits.
## Performing gProfiler REAC search of 39 genes against hsapiens.
## REAC search found 4 hits.
## Performing gProfiler MI search of 39 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 39 genes against hsapiens.
## TF search found 21 hits.
## Performing gProfiler CORUM search of 39 genes against hsapiens.
## CORUM search found 1 hits.
## Performing gProfiler HP search of 39 genes against hsapiens.
## HP search found 0 hits.
cf_eosinophil_up_gp[["pvalue_plots"]][["kegg_plot_over"]]

cf_eosinophil_up_gp[["pvalue_plots"]][["reactome_plot_over"]]

cf_eosinophil_up_gp[["pvalue_plots"]][["mfp_plot_over"]]
## NULL
cf_eosinophil_up_gp[["pvalue_plots"]][["bpp_plot_over"]]

cf_eosinophil_down_gp <- simple_gprofiler(cf_eosinophil_down)
## Performing gProfiler GO search of 16 genes against hsapiens.
## GO search found 0 hits.
## Performing gProfiler KEGG search of 16 genes against hsapiens.
## KEGG search found 10 hits.
## Performing gProfiler REAC search of 16 genes against hsapiens.
## REAC search found 3 hits.
## Performing gProfiler MI search of 16 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 16 genes against hsapiens.
## TF search found 11 hits.
## Performing gProfiler CORUM search of 16 genes against hsapiens.
## CORUM search found 0 hits.
## Performing gProfiler HP search of 16 genes against hsapiens.
## HP search found 6 hits.
cf_eosinophil_down_gp[["pvalue_plots"]][["reactome_plot_over"]]

cf_eosinophil_down_gp[["pvalue_plots"]][["mfp_plot_over"]]
## NULL
cf_eosinophil_down_gp[["pvalue_plots"]][["bpp_plot_over"]]
## NULL

20.1.1.6 Clinical samples

cf_nobiopsy_up <- cf_nobiopsy_sig[["deseq"]][["ups"]][["fail_vs_cure"]]
dim(cf_nobiopsy_up)
## [1] 63 58
cf_nobiopsy_down <- cf_nobiopsy_sig[["deseq"]][["downs"]][["fail_vs_cure"]]
dim(cf_nobiopsy_down)
## [1] 34 58
cf_nobiopsy_up_gp <- simple_gprofiler(cf_nobiopsy_up)
## Performing gProfiler GO search of 63 genes against hsapiens.
## GO search found 32 hits.
## Performing gProfiler KEGG search of 63 genes against hsapiens.
## KEGG search found 4 hits.
## Performing gProfiler REAC search of 63 genes against hsapiens.
## REAC search found 6 hits.
## Performing gProfiler MI search of 63 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 63 genes against hsapiens.
## TF search found 35 hits.
## Performing gProfiler CORUM search of 63 genes against hsapiens.
## CORUM search found 0 hits.
## Performing gProfiler HP search of 63 genes against hsapiens.
## HP search found 0 hits.
cf_nobiopsy_up_gp[["pvalue_plots"]][["kegg_plot_over"]]

cf_nobiopsy_up_gp[["pvalue_plots"]][["reactome_plot_over"]]

cf_nobiopsy_up_gp[["pvalue_plots"]][["mfp_plot_over"]]

cf_nobiopsy_up_gp[["pvalue_plots"]][["bpp_plot_over"]]

cf_nobiopsy_down_gp <- simple_gprofiler(cf_nobiopsy_down)
## Performing gProfiler GO search of 34 genes against hsapiens.
## GO search found 9 hits.
## Performing gProfiler KEGG search of 34 genes against hsapiens.
## KEGG search found 1 hits.
## Performing gProfiler REAC search of 34 genes against hsapiens.
## REAC search found 1 hits.
## Performing gProfiler MI search of 34 genes against hsapiens.
## MI search found 0 hits.
## Performing gProfiler TF search of 34 genes against hsapiens.
## TF search found 1 hits.
## Performing gProfiler CORUM search of 34 genes against hsapiens.
## CORUM search found 4 hits.
## Performing gProfiler HP search of 34 genes against hsapiens.
## HP search found 0 hits.
cf_nobiopsy_down_gp[["pvalue_plots"]][["reactome_plot_over"]]

cf_nobiopsy_down_gp[["pvalue_plots"]][["mfp_plot_over"]]
## NULL
cf_nobiopsy_down_gp[["pvalue_plots"]][["bpp_plot_over"]]

20.1.2 Cell type groups

20.1.3 Visit groups

20.2 GSVA

20.2.1 Clinical samples

hs_celltype_gsva_c2 <- simple_gsva(hs_valid)
## Converting the rownames() of the expressionset to ENTREZID.
## 588 ENSEMBL ID's didn't have a matching ENTEREZ ID. Dropping them now.
## Before conversion, the expressionset has 19923 entries.
## After conversion, the expressionset has 19495 entries.
hs_celltype_gsva_c2_sig <- get_sig_gsva_categories(
    hs_celltype_gsva_c2,
    excel="excel/individual_celltypes_gsva_c2.xlsx")
## Starting limma pairwise comparison.
## libsize was not specified, this parameter has profound effects on limma's result.
## Using the libsize from expt$libsize.
## Limma step 1/6: choosing model.
## Choosing the non-intercept containing model.
## Assuming this data is similar to a micro array and not performign voom.
## Limma step 3/6: running lmFit with method: ls.
## Limma step 4/6: making and fitting contrasts with no intercept. (~ 0 + factors)
## Limma step 5/6: Running eBayes with robust = FALSE and trend = FALSE.
## Limma step 6/6: Writing limma outputs.
## Limma step 6/6: 1/1: Creating table: failure_vs_cure.  Adjust = BH
## Limma step 6/6: 1/2: Creating table: cure.  Adjust = BH
## Limma step 6/6: 2/2: Creating table: failure.  Adjust = BH
## The factor cure has 132 rows.
## The factor failure has 60 rows.
## plot labels was not set and there are more than 100 samples, disabling it.
## Testing each factor against the others.
## Scoring cure against everything else.
## Scoring failure against everything else.
## Deleting the file excel/individual_celltypes_gsva_c2.xlsx before writing the tables.
hs_celltype_gsva_c2_sig$subset_plot
hs_celltype_gsva_c2_sig$score_plot
broad_c7 <- load_gmt_signatures(signatures="reference/msigdb/c7.all.v7.2.entrez.gmt",
                                signature_category="c7")
hs_celltype_gsva_c7 <- simple_gsva(hs_valid,
                                   signatures="reference/msigdb/c7.all.v7.2.entrez.gmt",
                                   signature_category="c7",
                                   msig_xml="reference/msigdb_v7.2.xml",
                                   cores=10)
## Converting the rownames() of the expressionset to ENTREZID.
## 588 ENSEMBL ID's didn't have a matching ENTEREZ ID. Dropping them now.
## Before conversion, the expressionset has 19923 entries.
## After conversion, the expressionset has 19495 entries.
## Adding annotations from reference/msigdb_v7.2.xml.
hs_celltype_gsva_c7_sig <- get_sig_gsva_categories(
    hs_celltype_gsva_c7,
    excel="excel/individual_celltypes_gsva_c7.xlsx")
## Starting limma pairwise comparison.
## libsize was not specified, this parameter has profound effects on limma's result.
## Using the libsize from expt$libsize.
## Limma step 1/6: choosing model.
## Choosing the non-intercept containing model.
## Assuming this data is similar to a micro array and not performign voom.
## Limma step 3/6: running lmFit with method: ls.
## Limma step 4/6: making and fitting contrasts with no intercept. (~ 0 + factors)
## Limma step 5/6: Running eBayes with robust = FALSE and trend = FALSE.
## Limma step 6/6: Writing limma outputs.
## Limma step 6/6: 1/1: Creating table: failure_vs_cure.  Adjust = BH
## Limma step 6/6: 1/2: Creating table: cure.  Adjust = BH
## Limma step 6/6: 2/2: Creating table: failure.  Adjust = BH
## The factor cure has 132 rows.
## The factor failure has 60 rows.
## plot labels was not set and there are more than 100 samples, disabling it.
## Testing each factor against the others.
## Scoring cure against everything else.
## Scoring failure against everything else.
## Deleting the file excel/individual_celltypes_gsva_c7.xlsx before writing the tables.

21 Concordance

Let us compare various results to see how well they agreed

monocyte_cor_subset <- cf_monocyte_sva_tables[["data"]][["fail_vs_cure"]][, c("deseq_logfc", "deseq_adjp")]
neutrophil_cor_subset <- cf_neutrophil_tables[["data"]][["fail_vs_cure"]][, c("deseq_logfc", "deseq_adjp")]
eosinophil_cor_subset <- cf_eosinophil_tables[["data"]][["fail_vs_cure"]][, c("deseq_logfc", "deseq_adjp")]
mono_neut_cor <- merge(monocyte_cor_subset, neutrophil_cor_subset, by="row.names")
mono_eo_cor <- merge(monocyte_cor_subset, eosinophil_cor_subset, by="row.names")
neut_eo_cor <- merge(neutrophil_cor_subset, eosinophil_cor_subset, by="row.names")

cor.test(mono_neut_cor[["deseq_logfc.x"]], mono_neut_cor[["deseq_logfc.y"]])
## 
##  Pearson's product-moment correlation
## 
## data:  mono_neut_cor[["deseq_logfc.x"]] and mono_neut_cor[["deseq_logfc.y"]]
## t = 41, df = 8638, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.3821 0.4175
## sample estimates:
##    cor 
## 0.3999
monocyte_neutrophil_aucc <- calculate_aucc(cf_monocyte_sva_tables[["data"]][["fail_vs_cure"]],
                                           cf_neutrophil_tables[["data"]][["fail_vs_cure"]],
                                           px="deseq_p", py="deseq_p", ly="deseq_logfc", lx="deseq_logfc")
monocyte_neutrophil_aucc$plot

cor.test(mono_eo_cor[["deseq_logfc.x"]], mono_eo_cor[["deseq_logfc.y"]])
## 
##  Pearson's product-moment correlation
## 
## data:  mono_eo_cor[["deseq_logfc.x"]] and mono_eo_cor[["deseq_logfc.y"]]
## t = 18, df = 9797, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.1607 0.1990
## sample estimates:
##    cor 
## 0.1799
monocyte_eosinophil_aucc <- calculate_aucc(cf_monocyte_sva_tables[["data"]][["fail_vs_cure"]],
                                           cf_eosinophil_tables[["data"]][["fail_vs_cure"]],
                                           px="deseq_p", py="deseq_p", ly="deseq_logfc", lx="deseq_logfc")
monocyte_eosinophil_aucc$plot

cor.test(neut_eo_cor[["deseq_logfc.x"]], neut_eo_cor[["deseq_logfc.y"]])
## 
##  Pearson's product-moment correlation
## 
## data:  neut_eo_cor[["deseq_logfc.x"]] and neut_eo_cor[["deseq_logfc.y"]]
## t = 36, df = 8620, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.3429 0.3796
## sample estimates:
##    cor 
## 0.3614
neutrophil_eosinophil_aucc <- calculate_aucc(cf_neutrophil_tables[["data"]][["fail_vs_cure"]],
                                           cf_eosinophil_tables[["data"]][["fail_vs_cure"]],
                                           px="deseq_p", py="deseq_p", ly="deseq_logfc", lx="deseq_logfc")
neutrophil_eosinophil_aucc$plot

22 Classify me!

I wrote out all the z2.2 and z2.3 specific variants to a couple files, I want to see if I can classify a human sample as infected with 2.2 or 2.3.

z22 <- read.csv("csv/variants_22.csv")
z23 <- read.csv("csv/variants_23.csv")
cure <- read.csv("csv/cure_variants.txt")
fail <- read.csv("csv/fail_variants.txt")
z22_vec <- gsub(pattern="\\-", replacement="_", x=z22[["x"]])
z23_vec <- gsub(pattern="\\-", replacement="_", x=z23[["x"]])
cure_vec <- gsub(pattern="\\-", replacement="_", x=cure)
fail_vec <- gsub(pattern="\\-", replacement="_", x=fail)

classify_zymo <- function(sample) {
  arbitrary_tags <- sm(readr::read_tsv(sample))
  arbitrary_ids <- arbitrary_tags[["position"]]
  message("Length: ", length(arbitrary_ids), ", z22: ",
          sum(arbitrary_ids %in% z22_vec) / (length(z22_vec)), " z23: ",
          sum(arbitrary_ids %in% z23_vec) / (length(z23_vec)))
}

arbitrary_sample <- "preprocessing/TMRC30156/outputs/40freebayes_lpanamensis_v36/all_tags.txt.xz"
classify_zymo(arbitrary_sample)
if (!isTRUE(get0("skip_load"))) {
  pander::pander(sessionInfo())
  message(paste0("This is hpgltools commit: ", get_git_commit()))
  message(paste0("Saving to ", savefile))
  tmp <- sm(saveme(filename=savefile))
}
tmp <- loadme(filename=savefile)
LS0tCnRpdGxlOiAiTC4gcGFuYW1lbnNpcyAyMDIyMDU6IFJlb3JnYW5pemluZyBUTVJDMyBBbmFseXNlcyIKYXV0aG9yOiAiYXRiIGFiZWxld0BnbWFpbC5jb20iCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogaHRtbF9kb2N1bWVudDoKICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgY29kZV9mb2xkaW5nOiBzaG93CiAgZmlnX2NhcHRpb246IHRydWUKICBmaWdfaGVpZ2h0OiA3CiAgZmlnX3dpZHRoOiA3CiAgaGlnaGxpZ2h0OiBkZWZhdWx0CiAga2VlcF9tZDogZmFsc2UKICBtb2RlOiBzZWxmY29udGFpbmVkCiAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgc2VsZl9jb250YWluZWQ6IHRydWUKICB0aGVtZTogcmVhZGFibGUKICB0b2M6IHRydWUKICB0b2NfZmxvYXQ6CiAgIGNvbGxhcHNlZDogZmFsc2UKICAgc21vb3RoX3Njcm9sbDogZmFsc2UKLS0tCgo8c3R5bGU+CiAgYm9keSAubWFpbi1jb250YWluZXIgewogICAgbWF4LXdpZHRoOiAxNjAwcHg7CiAgfQo8L3N0eWxlPgoKYGBge3Igb3B0aW9ucywgaW5jbHVkZT1GQUxTRX0KbGlicmFyeShocGdsdG9vbHMpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZm9yY2F0cykKdHQgPC0gc20oZGV2dG9vbHM6OmxvYWRfYWxsKCJ+L2hwZ2x0b29scyIpKQprbml0cjo6b3B0c19rbml0JHNldChwcm9ncmVzcz1UUlVFLAogICAgICAgICAgICAgICAgICAgICB2ZXJib3NlPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgIHdpZHRoPTkwLAogICAgICAgICAgICAgICAgICAgICBlY2hvPVRSVUUpCmtuaXRyOjpvcHRzX2NodW5rJHNldChlcnJvcj1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgZmlnLndpZHRoPTgsCiAgICAgICAgICAgICAgICAgICAgICBmaWcuaGVpZ2h0PTgsCiAgICAgICAgICAgICAgICAgICAgICBkcGk9OTYpCm9sZF9vcHRpb25zIDwtIG9wdGlvbnMoZGlnaXRzPTQsCiAgICAgICAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycz1GQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICBrbml0ci5kdXBsaWNhdGUubGFiZWw9ImFsbG93IikKZ2dwbG90Mjo6dGhlbWVfc2V0KGdncGxvdDI6OnRoZW1lX2J3KGJhc2Vfc2l6ZT0xMikpCnZlciA8LSAiMjAyMjA1IgpwcmV2aW91c19maWxlIDwtIHBhc3RlMCgiMDFfYW5ub3RhdGlvbl92IiwgdmVyLCAiLlJtZCIpCnJ1bmRhdGUgPC0gZm9ybWF0KFN5cy5EYXRlKCksIGZvcm1hdD0iJVklbSVkIikKCiMjdG1wIDwtIHRyeShzbShsb2FkbWUoZmlsZW5hbWU9Z3N1YihwYXR0ZXJuPSJcXC5SbWQiLCByZXBsYWNlPSJcXC5yZGFcXC54eiIsIHg9cHJldmlvdXNfZmlsZSkpKSkKcm1kX2ZpbGUgPC0gInRtcmMzX3Jlb3JnYW5pemVkXzIwMjIwNS5SbWQiCnNhdmVmaWxlIDwtIGdzdWIocGF0dGVybj0iXFwuUm1kIiwgcmVwbGFjZT0iXFwucmRhXFwueHoiLCB4PXJtZF9maWxlKQpgYGAKCiMgSW50cm9kdWN0aW9uCgpUaGUgc2V0IG9mIGFuYWx5c2VzIHBlcmZvcm1lZCBpbiB0bXJjMyBzYW1wbGUgZXN0aW1hdGlvbiBoYXMgYmVjb21lCnVub3JnYW5pemVkIGFuZCBkaWZmaWN1bHQgdG8gZm9sbG93LiAgVGhpcyBpcyBpbnRlbmRlZCB0byBzdGFydCBhdCB0aGUKbGV2ZWwgb2YgYnJvYWQgb3JnYW5pemF0aW9uIGJlZm9yZSBzdGVwcGluZyBpbnRvIHRoZSBhbmFseXNlcy4KCiMjIEdvYWxzCgpUaGVzZSBzYW1wbGVzIGFyZSBmcm9tIHBhdGllbnRzIHdobyBlaXRoZXIgc3VjY2Vzc2Z1bGx5IGNsZWFyZWQgYQpMZWlzaG1hbmlhIHBhbmFtZW5zaXMgaW5mZWN0aW9uIGZvbGxvd2luZyB0cmVhdG1lbnQsIG9yIGRpZCBub3QuICBUaGV5CmluY2x1ZGUgYmlvcHNpZXMgZnJvbSBlYWNoIHBhdGllbnQgYWxvbmcgd2l0aCBwdXJpZmljYXRpb25zIGZvcgpNb25vY3l0ZXMsIE5ldXRyb3BoaWxzLCBhbmQgRW9zaW5vcGhpbHMuICBXaGVuIHBvc3NpYmxlLCB0aGlzIHByb2Nlc3MKd2FzIHJlcGVhdGVkIG92ZXIgdGhyZWUgdmlzaXRzOyBidXQgc29tZSBwYXRpZW50cyBkaWQgbm90IHJldHVybgpmb3IgdGhlIHNlY29uZCBvciB0aGlyZCB2aXNpdC4KClRoZSBvdmVyLWFyY2hpbmcgZ29hbCBpcyB0byBsb29rIGZvciBhdHRyaWJ1dGVzKG1vc3QgbGlrZWx5IGdlbmVzKQp3aGljaCBkaXN0aW5ndWlzaCBwYXRpZW50cyB3aG8gZG8gYW5kIGRvIG5vdCBjdXJlIHRoZSBpbmZlY3Rpb24gYWZ0ZXIKdHJlYXRtZW50LiAgSWYgcG9zc2libGUsIHRoZXNlIHdpbGwgYmUgYXBwYXJlbnQgb24gdGhlIGZpcnN0IHZpc2l0LgoKIyMgUmVsZXZhbnQgTWV0YWRhdGEKClRoZSBtZXRhZGF0YSBmYWN0b3JzIChpbiBubyBwYXJ0aWN1bGFyIG9yZGVyKSBvZiB0aGUgZXhwZXJpbWVudCBhcmU6CgoxLiAgVmlzaXQuICAxLCAyLCBvciAzLgoyLiAgUGF0aWVudC4KMy4gIENsaW5pY2FsIG91dGNvbWU6IGN1cmUgb3IgZmFpbC4gIFRoaXMgaW5jbHVkZXMgdGhlIHBvcHVsYXRpb24gb2YKICAgIHBhdGllbnRzIHdobyBkaWQgbm90IHJldHVybiBhbmQgYXJlIGxhYmVsZWQgJ2xvc3QnLiAgVGhpcyBpcywgYnkKICAgIGRlZmluaXRpb24sIGNvbmZvdW5kZWQgd2l0aCBwYXRpZW50Lgo0LiAgRHJ1ZyB0cmVhdG1lbnQuICBNb3N0IG9mIHRoZSBwYXRpZW50cyB3ZXJlIHRyZWF0ZWQgd2l0aCBhbgogICAgYW50aW1vbmlhbCwgYnV0IGEgZmV3IHdlcmUgdHJlYXRlZCB3aXRoIG1pbHRlZm9zaW5lLgo1LiAgQ2VsbCB0eXBlIG9yIGJpb3BzeS4KCk1ldGFkYXRhIHdhcyBhbHNvIGNvbGxlY3RlZCBmb3IgdGhlIHBhdGllbnRzIGFuZCB0aGVyZSBhcmUgbWFueQpmYWN0b3JzIHdoaWNoIGhhdmUgcG90ZW50aWFsIHRvIGFmZmVjdCB0aGUgb3V0Y29tZS4gIFRoZXNlIGFuYWx5c2VzCndpbGwgZ2VuZXJhbGx5IHJlbWFpbiBhZ25vc3RpYyBmb3IgdGhlc2UgZmFjdG9ycywgd2hpY2ggaW5jbHVkZSAoYW1vbmcKb3RoZXIgdGhpbmdzKToKCjEuICBzZXgKMi4gIGV0aG5pY2l0eQo0LiAgYWdlCjUuICB1bGNlci9sZXNpb24gYXR0cmlidXRlcyAoYnkgdmlzaXQpCjYuICBhbW91bnQgb2YgdGltZSBzcGVudCB3aXRoIGluZmVjdGlvbgo3LiAgQWRoZXJlbmNlIHRvIHRyZWF0bWVudCwgd2hpY2ggaXMgYSBtZXRyaWMgb2YgaG93IG11Y2ggb2YgdGhlCiAgICBwcmVzY3JpYmVkIGRvc2FnZSB3YXMgYWN0dWFsbHkgcmVjZWl2ZWQgYnkgdGhlIHBhdGllbnQuCgojIyBMaWJyYXJpZXMsIHNlcXVlbmNpbmcsIG1hcHBpbmcsIHF1YW50aWZpY2F0aW9uCgpUaGUgc2FtcGxlcyB1c2VkIGluIHRoZXNlIGFuYWx5c2VzIHdlcmUgYWxsIGNvbGxlY3RlZCwgcHVyaWZpZWQsIGFuZApsaWJyYXJpZXMgZ2VuZXJhdGVkIGJ5IHRoZSBzY2llbnRpc3RzL2RvY3RvcnMgYXQgQ0lERUlNLiAgVGhlCnNlcXVlbmNpbmcgbGlicmFyaWVzIHdlcmUgZ2VuZXJhdGVkIHZpYSB0aGUgVHJ1U2VxIG5vbi1zdHJhbmRlZApsaWJyYXJ5IGtpdCBhbmQgc2VxdWVuY2VkIGVpdGhlciBhdCBKSFUgb3IgVU1EOyBlYXJsaWVyIHNhbXBsZXMgd2VyZQpzaW5nbGUtZW5kZWQsIGJ1dCBtb3N0IHdlcmUgcGFpcmVkLgoKQWxsIHNhbXBsZXMgd2VyZSB0cmltbWVkIHdpdGggdHJpbW9tYXRpYyB1c2luZyB0aGUgc2FtZSBzZXQgb2YKcGFyYW1ldGVycy4gIEFsbCBtYXBwaW5nIHdhcyBwZXJmb3JtZWQgd2l0aCBoaXNhdDIgdmVyc2lvbiAyLjIuMS4KUXVhbnRpZmljYXRpb25zIHdlcmUgYWxzbyBwZXJmb3JtZWQgd2l0aCBzYWxtb24gdmVyc2lvbiAxLjIuMC4gIFRoZQpyZWZlcmVuY2UgZ2Vub21lIHVzZWQgd2FzIGhnMzggMTAwIChyZWxlYXNlZCAyMDIwMDQpLiAgV2hlbiBzYW1wbGVzCndlcmUgbWFwcGVkIGFnYWluc3QgTC5wYW5hbWVuc2lzLCB0aGUgVHJpVHJ5cERCIHZlcnNpb24gMzYgcmVmZXJlbmNlCndhcyB1c2VkLiAgVGhlIHNldCBvZiBhbm5vdGF0aW9ucyB3ZXJlIHRoZXJlZm9yZSBsaW1pdGVkIHRvIGVuc2VtYmwncwoyMDIwIHJlbGVhc2UuICBUaGUgZWFybHkgc2FtcGxlcyB3ZXJlIGFjdHVhbGx5IGZpcnN0IG1hcHBlZCB3aXRoCmhnMzggOTEgYW5kIGxhdGVyIHJlZG9uZS4KCiMjIFR5cGVzIG9mIGFuYWx5c2VzIGluY2x1ZGVkCgpUaGlzIGRvY3VtZW50IHdpbGwgbGltaXQgaXRzZWxmIHRvIGEgc2V0IG9mIGNhbm9uaWNhbCBSTkFzZXEKYW5hbHlzZXM6CgoqICBDcmVhdGUgZmlsZXMgY29udGFpbmluZyB0aGUgcmF3IGRhdGEgdG8gZmFjaWxpdGF0ZSBzaGFyaW5nIHRoZSBkYXRhLgoqICBQbG90IG1ldHJpY3Mgb2YgdGhlIGRhdGEgdG8gZGVtb25zdHJhdGUgdGhlIHNlcXVlbmNpbmcgcXVhbGl0eSBhbmQKICAgY2x1c3RlcmluZyBvZiB0aGUgc2FtcGxlcyB1bmRlciB0aGUgdmFyaW91cyBjb25kaXRpb25zIGV4YW1pbmVkIGFuZAogICBub3JtYWxpemF0aW9ucyBlbXBsb3llZC4KKiAgUGVyZm9ybSBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhbmFseXNlcyBmb3IgdGhlIG1ldGFkYXRhIGZhY3RvcnMgb2YKICAgaW50ZXJlc3QgYWxvbmdzaWRlIGxpa2VsaWhvb2QgcmF0aW8gdGVzdHMgZm9yIGZhY3RvcnMgbGlrZSBjZWxsdHlwZQogICBhbmQgdGltZS4KKiAgR2l2ZW4gdGhlIHNldHMgb2Ygb3Zlci91bmRlciBleHByZXNzZWQgZ2VuZXMgb2JzZXJ2ZWQgaW4gdGhlCiAgIHZhcmlvdXMgREUgbWV0aG9kcywgaXQgd2lsbCBwZXJmb3JtIHRoZSBsaWtlbHkgZ2VuZSBzZXQgdGVzdHMgZm9yCiAgIG92ZXIgcmVwcmVzZW50ZWQgZ2VuZSBvbnRvbG9neSBncm91cHMsIHJlYWN0b21lLCBldGMuCiogIFRoZSByYXcgZGF0YSB3aWxsIGJlIHBhc3NlZCB0byBnZW5lIHNldCB2YXJpYW5jZSBhbmFseXNlcyB0byBzZWUgaWYKICAgdGhlcmUgYXJlIGdyb3VwcyBvZiBnZW5lcyBvdmVycmVwcmVzZW50ZWQgaW4gb3RoZXIgZXhwZXJpbWVudHMuCgojIyBNZXRhZGF0YSBjb2xsZWN0aW9uCgpUaGVyZSBhcmUgdHdvIG1ldGFkYXRhIHNvdXJjZXM6CgoxLiAgVGhlIG9ubGluZSBzYW1wbGUgc2hlZXQsIHdoaWNoIEkgcGVyaW9kaWNhbGx5IHVwZGF0ZSBhbmQgZG93bmxvYWQKICAgIGludG8gdGhlICdzYW1wbGVfc2hlZXRzLycgZGlyZWN0b3J5LgoyLiAgVGhlIGNyZiBtZXRhZGF0YSwgZGVzY3JpYmluZyB0aGUgaW5kaXZpZHVhbCBwYXRpZW50cy4KCmBgYHtyIG1ldGFkYXRhX3NvdXJjZXN9CnNhbXBsZXNoZWV0IDwtICJzYW1wbGVfc2hlZXRzL3RtcmMzX3NhbXBsZXNfMjAyMjA1Lnhsc3giCmNyZl9tZXRhZGF0YSA8LSAic2FtcGxlX3NoZWV0cy8yMDIyMDUwOV9FWFBfRVNQRUNJQUxfVE1SQzNfVjIueGxzeCIKYGBgCgojIFJhbmRvbSBub3RlcwoKMS4gTm90ZSBmcm9tIE1hcmlhIEFkZWxhaWRhOiBTb21lIGNoZW1va2luZXMgYXJlIHN1Z2dlc3RpdmUgb2YgRW9zaW5vcGhpbCByZWNydWl0bWVudC4KCiMgQW5ub3RhdGlvbiBDb2xsZWN0aW9uCgpUaGUgcHJpbWFyeSBhbm5vdGF0aW9uIHNvdXJjZXMgYXJlOgoKMS4gIEVuc2VtYmwncyBiaW9tYXJ0IGFyY2hpdmUgZnJvbSAyMDIwIGZvciBodW1hbiBhbm5vdGF0aW9ucy4KMi4gIFRoZSBUcmlUcnlwREIgcmVsZWFzZSAzNiBmb3IgcGFyYXNpdGUgYW5ub3RhdGlvbnMuCgpCb3RoIHByb3ZpZGUgR08gZGF0YS4gIFRoZXkgYWxzbyBwcm92aWRlIGhlbHBmdWwgbGlua3MgdG8gb3RoZXIgZGF0YQpzb3VyY2VzLiAgRm9yIHRoZSBtb21lbnQsIHdlIGFyZSBmb2N1c2luZyBvbiB0aGUgaHVtYW4gYW5ub3RhdGlvbnMuCgojIyBHZW5lIGFubm90YXRpb25zCgpUaGVzZSBhbmFseXNlcyBoYXZlIGZvY3VzZWQgb24gZ2VuZS1sZXZlbCBhYnVuZGFuY2VzL2RpZmZlcmVuY2VzLgpUaHVzLCB3aGVuIGh0c2VxLWNvdW50IHdhcyBpbnZva2VkIGFnYWluc3QgdGhlIGhpc2F0Mi1iYXNlZCBtYXBwaW5ncywKcGFyYW1ldGVycyB3ZXJlIGNob3NlbiB0byBjb3VudCBnZW5lcyByYXRoZXIgdGhhbiB0cmFuc2NyaXB0cy4KU2ltaWxhcmx5LCB3aGVuIHNhbG1vbiBjb3VudHMgd2VyZSB1c2VkIHZpYSB0eGltcG9ydCwgYSBtYXBwaW5nIG9mCmdlbmVzIHRvIHRyYW5zY3JpcHRzIHdhcyB1c2VkIHRvIGNvbGxhcHNlIHRoZSBtYXRyaXggdG8gZ2VuZS1sZXZlbAphYnVuZGFuY2VzLiAgVGhpcyBkZWNpc2lvbiBtYXkgYmUgcmV2aXNpdGVkLgoKYGBge3IgY29sbGVjdF9hbm5vdGF0aW9uc30KaHNfYW5ub3QgPC0gbG9hZF9iaW9tYXJ0X2Fubm90YXRpb25zKHllYXI9IjIwMjAiLCBtb250aD0iamFuIikKaHNfYW5ub3QgPC0gaHNfYW5ub3RbWyJhbm5vdGF0aW9uIl1dCmhzX2Fubm90W1sidHJhbnNjcmlwdCJdXSA8LSBwYXN0ZTAocm93bmFtZXMoaHNfYW5ub3QpLCAiLiIsIGhzX2Fubm90W1sidmVyc2lvbiJdXSkKcm93bmFtZXMoaHNfYW5ub3QpIDwtIG1ha2UubmFtZXMoaHNfYW5ub3RbWyJlbnNlbWJsX2dlbmVfaWQiXV0sIHVuaXF1ZT1UUlVFKQp0eF9nZW5lX21hcCA8LSBoc19hbm5vdFssIGMoInRyYW5zY3JpcHQiLCAiZW5zZW1ibF9nZW5lX2lkIildCnN1bW1hcnkoaHNfYW5ub3QpCmBgYAoKIyMgR2VuZSBvbnRvbG9neSBkYXRhCgpUaGUgc2V0IG9mIEdPIGNhdGVnb3JpZXMgaGFzIG5vdCBiZWVuIGxpbWl0ZWQgdG8gdGhlIDIwMjAgZGF0YSBhdCB0aGUKdGltZSBvZiB0aGlzIHdyaXRpbmcuICBUaGUgR08gY2F0ZWdvcmllcyBpcyBjb2xsZWN0ZWQgYWxvbmcgd2l0aApsZW5ndGhzIGZvciBnb3NlcS4gIFRoZSBvdGhlciBtZXRob2RzIGVpdGhlciBoYXZlIGJ1aWx0LWluIGRhdGFiYXNlcwpvZiBodW1hbiBkYXRhIChnUHJvZmlsZXIpIG9yIHN1cHBvcnQgb3JnREIgZGF0YSAob3JnLkhzLmVnLmRiKQooY2x1c3RlclByb2ZpbGVyL3RvcEdPL2dvc3RhdHMpLgoKYGBge3IgaHNfZ299CmhzX2dvIDwtIGxvYWRfYmlvbWFydF9nbygpW1siZ28iXV0KaHNfbGVuZ3RoIDwtIGhzX2Fubm90WywgYygiZW5zZW1ibF9nZW5lX2lkIiwgImNkc19sZW5ndGgiKV0KY29sbmFtZXMoaHNfbGVuZ3RoKSA8LSBjKCJJRCIsICJsZW5ndGgiKQpgYGAKCiMgRGF0YXNldDogQ3JlYXRlIHRoZSBwYXJlbnQgZGF0YSBzdHJ1Y3R1cmUgb2YgYWxsIHNhbXBsZXMKCkJlZm9yZSB3ZSBkbyBhbnkgb2YgdGhlIGZvbGxvd2luZyBzdWJzZXRzL2FuYWx5c2VzIG9mIHRoZSBkYXRhLCB3ZQpuZWVkIHRvIGNvbGxlY3QgaXQgYWxsIGluIG9uZSBwbGFjZS4gIExldCdzIGRvIHRoYXQgaGVyZSBhbmQgbmFtZSBpdAonaHNfZXhwdCcsIGl0IHdpbGwgY29tcHJpc2UgdGhlIGZ1bGwgc2V0IG9mIGh1bWFuIGRhdGEuICBXaGVuIHdlIGN1bGwKc29tZSBzYW1wbGVzIGl0IHdpbGwgYmUgcmVuYW1lZCB0byAnaHNfdmFsaWQnLgoKYGBge3IgYWxsX2RhdGF9CnNhbml0aXplX2NvbHVtbnMgPC0gYygidmlzaXRudW1iZXIiLCAiY2xpbmljYWxvdXRjb21lIiwgImRvbm9yIiwKICAgICAgICAgICAgICAgICAgICAgICJ0eXBlb2ZjZWxscyIsICJjbGluaWNhbHByZXNlbnRhdGlvbiIsICJkcnVnIiwKICAgICAgICAgICAgICAgICAgICAgICJjb25kaXRpb24iLCAiYmF0Y2giKQpoc19leHB0IDwtIGNyZWF0ZV9leHB0KHNhbXBsZXNoZWV0LAogICAgICAgICAgICAgICAgICAgICAgIGZpbGVfY29sdW1uPSJoZzM4MTAwaGlzYXRmaWxlIiwKICAgICAgICAgICAgICAgICAgICAgICBzYXZlZmlsZT1nbHVlOjpnbHVlKCJyZGEvaHNfZXhwdF9hbGwtdnt2ZXJ9LnJkYSIpLAogICAgICAgICAgICAgICAgICAgICAgIGdlbmVfaW5mbz1oc19hbm5vdCkgJT4lCiAgZXhjbHVkZV9nZW5lc19leHB0KGNvbHVtbj0iZ2VuZV9iaW90eXBlIiwgbWV0aG9kPSJrZWVwIiwKICAgICAgICAgICAgICAgICAgICAgcGF0dGVybj0icHJvdGVpbl9jb2RpbmciLCBtZXRhX2NvbHVtbj0ibmNybmFfbG9zdCIpICU+JQogIHNhbml0aXplX2V4cHRfbWV0YWRhdGEoY29sdW1ucz1zYW5pdGl6ZV9jb2x1bW5zKSAlPiUKICBzZXRfZXhwdF9mYWN0b3JzKGNvbHVtbnM9c2FuaXRpemVfY29sdW1ucywgY2xhc3M9ImZhY3RvciIpICU+JQogIHNldF9leHB0X2NvbmRpdGlvbnMoZmFjdD0iY2xpbmljYWxvdXRjb21lIikgJT4lCiAgc2V0X2V4cHRfYmF0Y2hlcyhmYWN0PSJ2aXNpdG51bWJlciIpCgojIyBUaGUgZm9sbG93aW5nIHNob3VsZCBtYWtlIHZpc2l0IDEgdGhlIGxhcmdlc3QgaWYgb25lIHVzZXMgdGhhdCBjb2x1bW4gYXMgYSBzaXplIGZhY3RvciB3aGVuIHBsb3R0aW5nLgptZXRhIDwtIHBEYXRhKGhzX2V4cHQpICU+JQogIG11dGF0ZSh2aXNpdG51bWJlciA9IGZjdF9yZWxldmVsKHZpc2l0bnVtYmVyLCBjKCJub3RhcHBsaWNhYmxlIiwgIjMiLCAiMiIsICIxIikpKQpwRGF0YShoc19leHB0KSA8LSBtZXRhCmBgYAoKVGhlIGFib3ZlIGJsb2NrIGRpZCB0aGUgZm9sbG93aW5nOgoKMS4gIENyZWF0ZXMgYW4gZXhwcmVzc2lvbnNldCB1c2luZyB0aGUgJ2hnMzgxMDBoaXNhdGZpbGUnIGNvbHVtbiBmcm9tCiAgICB0aGUgbW9zdCByZWNlbnRseSBkb3dubG9hZGVkIHNhbXBsZSBzaGVldCAodGhlIGNvbHVtbidzIG5hbWUgaGFzCiAgICBhbnkgcHVuY3R1YXRpb24vc3BhY2VzL2NhcGl0YWxzL2V0YyByZW1vdmVkKSBhbmQgdGhlIHNldCBvZiBodW1hbgogICAgYW5ub3RhdGlvbnMgZG93bmxvYWRlZCBhYm92ZS4KMi4gIFRoaXMgZXhwcmVzc2lvbnNldCBpcyBwYXNzZWQgdG8gYSBmaWx0ZXIgd2hpY2ggcHVsbHMgb3V0IG9ubHkgdGhlCiAgICBwcm90ZWluX2NvZGluZyBnZW5lcyBhbmQgdXNlcyB0aGUgaW5mb3JtYXRpb24gZnJvbSB0aGF0IHByb2Nlc3MgdG8KICAgIGFkZCBhIG5ldyBtZXRhZGF0YSBjb2x1bW4gY2FsbGVkICduY3JuYV9sb3N0Jy4gVGh1cyBpdCBrZWVwcyBhCiAgICB0YWxseSBvZiB0aGUgbnVtYmVyIG9mIHJlYWRzIGxvc3QgaW4gdGhlIGZpbHRlciBhbmQgYWRkcyBpdCB0byB0aGUKICAgIHNhbXBsZSBzaGVldC4KMy4gIEl0IGlzIHBhc3NlZCB0byBhIGZ1bmN0aW9uIHdoaWNoIHNhbml0aXplcyB0aGUgbWV0YWRhdGEKICAgICh0aGVyZSB3ZXJlIGEgY291cGxlIG9mIGVudHJpZXMgd2hpY2ggc2FpZCAnY3VyZScgaW5zdGVhZCBvZgogICAgJ0N1cmUnIG9yIHZpY2UgdmVyc2EpIGFuZCBzaW1pbGFybHkgcmVtb3ZlcyBwcm9ibGVtYXRpYwogICAgY2hhcmFjdGVycyAoaW4gYSBmZXcgaW5zdGFuY2VzIHNwYWNlcyBmb2xsb3cgaW1wb3J0YW50IG1ldGFkYXRhCiAgICAnZmFpbHVyZSAnKS4KNC4gIFBhc3NlZCB0byBhIGZ1bmN0aW9uIHdoaWNoIHNldHMgc29tZSBjb2x1bW5zIGV4cGxpY2l0bHkgdG8gZmFjdG9ycwogICAgaW5zdGVhZCBvZiBjaGFyYWN0ZXJzLgo1LiAgU2V0cyB0aGUgZXhwZXJpbWVudGFsICdjb25kaXRpb24nIHRvIHRoZSBmYWN0b3Igb2YgY3VyZSB2cy4gZmFpbC4KNi4gIFNldHMgdGhlIGV4cGVyaW1lbnRhbCAnYmF0Y2gnIHRvIHZpc2l0IG51bWJlci4KNy4gIFJlc2V0cyB0aGUgbGV2ZWxzIG9mIHRoZSB2aXNpdCBudW1iZXIgc28gdGhhdCB0aGUgc2FtcGxlcyB3aGljaAogICAgd2VyZSAnbm90YXBwbGljYWJsZScgYXJlIGxvZ2ljYWxseSBiZWZvcmUgdmlzaXQgMSB3aGljaCBpcyBiZWZvcmUKICAgIDIgYmVmb3JlIDMgKFRodXMgaWYgd2UgcGxvdCB3aXRoIHZpc2l0cyBhcyB0aGUgc2l6ZSBvZiBhIGdseXBoLAogICAgdmlzaXQgMSB3aWxsIGJlIHRoZSBsYXJnZXN0KS4KCiMjIEFkZCB0aGUgQ1JGIHBhdGllbnQgbWV0YWRhdGEKCk1lcmdlIGluIHRoZSBjbGluaWNpYW4ncyBtZXRhZGF0YS4gIEkgd29ycnkgYSBsaXR0bGUgdGhhdCB0aGlzIG1pZ2h0Cm5vdCBiZSBhbGxvd2VkIGZvciBkYkdhcCBkYXRhLCBidXQgaWYgaXQgaXMgYSBwcm9ibGVtIEkgc3VzcGVjdCB3ZSBjYW4KanVzdCByZW1vdmUgdGhlIGJhZCBjb2x1bW5zIGZyb20gaXQuICBBbHNvIG5vdGUgdGhhdCBJIHJhcmVseSB1c2UgdGhlCmpvaW4gZnVuY3Rpb24sIGJ1dCBpdCBpcyBzb21ld2hhdCByZXF1aXJlZCBoZXJlIGJlY2F1c2UgSSBkbyBub3Qgd2FudAp0byByaXNrIHNodWZmbGluZyB0aGUgbWV0YWRhdGEgd2hlbiBJIGFkZCB0aGUgbmV3IG1ldGFkYXRhLCB3aGljaApjb21lcyBmcm9tIGEgc3ByZWFkc2hlZXQgc29ydGVkIGJ5IHBhdGllbnQsIG5vdCBzYW1wbGUuICBJbiBkb2luZyB0aGlzCkkgdGhlcmVmb3JlIGp1c3QgY3JlYXRlZCBhIG5ldyBjb2x1bW4gJ2pvaW4nIHdoaWNoIGNvbnRhaW5zIHRoZSBzaGFyZWQKaW5mb3JtYXRpb24sIGUuZy4gdGhlIHBhdGllbnQgSUQgZnJvbSB0aGUgZXhpc3RpbmcgbWV0YWRhdGEgYW5kIHRoZQpzYW1lIElEIGZyb20gdGhlIENSRiBmaWxlIHdoaWNoIGhhcyBiZWVuIGNvZXJjZWQgaW50byBsb3dlcmNhc2UuCgpgYGB7ciBtZXJnZV9jcmZ9CmhzX3BkIDwtIHBEYXRhKGhzX2V4cHQpCnN0YXJ0IDwtIHJvd25hbWVzKGhzX3BkKQpoc19jcmYgPC0gb3Blbnhsc3g6OnJlYWQueGxzeChjcmZfbWV0YWRhdGEpCmhzX2NyZltbImpvaW4iXV0gPC0gdG9sb3dlcihoc19jcmZbWyJjb2RpZ29fcGFjaWVudGUiXV0pCmhzX3BkW1siam9pbiJdXSA8LSBoc19wZFtbInR1YmVsYWJlbG9yaWdpbiJdXQp0ZXN0IDwtIHBseXI6OmpvaW4oaHNfcGQsIGhzX2NyZiwgYnk9ImpvaW4iKQp0ZXN0W1siam9pbiJdXSA8LSBOVUxMCnJvd25hbWVzKHRlc3QpIDwtIHJvd25hbWVzKGhzX3BkKQpuYV9pZHggPC0gaXMubmEodGVzdCkKdGVzdFtuYV9pZHhdIDwtICJ1bmRlZmluZWQiCnBEYXRhKGhzX2V4cHQpIDwtIHRlc3QKYGBgCgpUaGUgYWJvdmUgYmxvY2sgZGlkIHRoZSBmb2xsb3dpbmc6CgoxLiAgRXh0cmFjdCB0aGUgbWV0YWRhdGEgYW5kIG1hZGUgYSBjaGFyYWN0ZXIgdmVjdG9yIG9mIHRoZSByb3duYW1lcwogICAgKGUuZy4gdGhlIHNhbXBsZSBJRHMpLgoyLiAgQ3JlYXRlZCBhIHRhYmxlIG9mIHRoZSBjbGluaWNhbCBtZXRhZGF0YSBmcm9tIHRoZSBmaWxlIEkKICAgIGRvd25sb2FkZWQuCjMuICBDcmVhdGVkIGEgJ2pvaW4nIGNvbHVtbiBmcm9tIGJvdGggdGhlIGV4aXN0aW5nIG1ldGFkYXRhIGFuZCB0aGUgY2xpbmljYWwKICAgIG1ldGFkYXRhIHdoaWNoIGlzIHRoZSBwYXRpZW50IGNvZGUsIHVzaW5nIHdoYXRldmVyIHRoZSBjb2x1bW4KICAgIG5hbWVzIHdlcmUgaW4gZWFjaCBzaGVldC4KNC4gIEpvaW5lZCB0aGUgdHdvIHRhYmxlcyB1c2luZyB0aGlzIGluZm9ybWF0aW9uLiAgVGhlIGpvaW4gZnVuY3Rpb24gaXMKICAgIGV4cGxpY2l0bHkgdXNlZCBpbiB0aGlzIGNvbnRleHQgdG8gbWFrZSBzdXJlIHRoYXQgdGhlIHJvdy1vcmRlciBvZgogICAgdGhlIGVudHJpZXMgZG9lcyBub3QgY2hhbmdlLgo1LiAgR290IHJpZCBvZiBhbnkgZW50cmllcyBpbiB0aGUgbmV3IHRhYmxlIHdoaWNoIGFyZSBOQS4KNi4gIFJlcGxhY2VkIHRoZSBtZXRhZGF0YSBvZiB0aGUgZXhwcmVzc2lvbnNldCB3aXRoIHRoaXMgbmV3LCBsYXJnZXIgdGFibGUuCgojIyBTYW5pdHkgY2hlY2ssIGNsaW5pY2FsIG91dGNvbWUgdnMuIENSRiBkYXRhCgpJbiBvdXIgc2hhcmVkIG9ubGluZSBzYW1wbGUgc2hlZXQgdGhlcmUgaXMgYSBjbGluaWNhbCBvdXRjb21lIGNvbHVtbgp3aGljaCBzaG91bGQgbWF0Y2ggdGhlIGZpbmFsIENSRiBjb2x1bW4gJ2VmX2xjX2VzdGFkb19maW5hbF9lc3R1ZGlvJwp3aXRoIHRoZSBjYXZlYXQgdGhhdCB0aGUgQ1JGIGRhdGEgaXMgbnVtZXJpYzoKCjA6IGN1cmFjaW9uIGRlZmluaXRpdmEKMTogZmFpbCB0ZXJhcGV1dGljYQoyOiBwZXJkaWRhIGRydWFudGUgZWwgc2VndWltaWVudG8KMzogZXhjbHVkaW8gZHVyYW50ZSBlbCBlc3R1ZGlvCgpgYGB7ciBjZl9zYW5pdHl9CnR3b19jb2x1bW5zIDwtIHBEYXRhKGhzX2V4cHQpWywgYygiY2xpbmljYWxvdXRjb21lIiwgImVmX2xjX2VzdGFkb19maW5hbF9lc3R1ZGlvIildCnVuZGVmX2lkeCA8LSB0d29fY29sdW1uc1tbMl1dID09ICJ1bmRlZmluZWQiCnR3b19jb2x1bW5zIDwtIHR3b19jb2x1bW5zWyF1bmRlZl9pZHgsIF0KdHdvX2NvbHVtbnNbWyJyZXdyaXR0ZW4iXV0gPC0gInVuZGVmIgpjdXJlX2lkeCA8LSB0d29fY29sdW1uc1tbMl1dID09IDAKdHdvX2NvbHVtbnNbY3VyZV9pZHgsICJyZXdyaXR0ZW4iXSA8LSAiY3VyZSIKZmFpbF9pZHggPC0gdHdvX2NvbHVtbnNbWzJdXSA9PSAxCnR3b19jb2x1bW5zW2ZhaWxfaWR4LCAicmV3cml0dGVuIl0gPC0gImZhaWx1cmUiCmxvc3RfaWR4IDwtIHR3b19jb2x1bW5zW1syXV0gPT0gMgp0d29fY29sdW1uc1tsb3N0X2lkeCwgInJld3JpdHRlbiJdIDwtICJsb3N0IgpzYW1lX2lkeCA8LSB0d29fY29sdW1uc1tbImNsaW5pY2Fsb3V0Y29tZSJdXSA9PSB0d29fY29sdW1uc1tbInJld3JpdHRlbiJdXQpicm9rZW4gPC0gdHdvX2NvbHVtbnNbIXNhbWVfaWR4LCBdCmJyb2tlbgpgYGAKCiMjIFN1bW1hcml6ZTogQ29sbGVjdCBzYW1wbGUgbnVtYmVycyBiZWZvcmUgZmlsdGVyaW5nCgpUaGVyZSBhcmUgc29tZSBtZXRhZGF0YSBmYWN0b3JzIGZvciB3aGljaCBJIHRoaW5rIGl0IHdpbGwgYmUgbmljZSB0bwpzZWUgdGhlIG51bWJlcnMgYmVmb3JlIGFuZCBhZnRlciBvdXIgZmlsdGVycy4gIFRoZSBmb2xsb3dpbmcgc2hvd3MgaG93Cm1hbnkgc2FtcGxlcyB3ZSBoYXZlIG9mIHRoZSBwcmltYXJ5IHR5cGVzIGJlZm9yZSBmaWx0ZXJpbmcuCgpgYGB7ciB0YWJsZV92YWxpZF9wcmV9CmRpbShwRGF0YShoc19leHB0KSkKdGFibGUocERhdGEoaHNfZXhwdCkkZHJ1ZykKdGFibGUocERhdGEoaHNfZXhwdCkkY2xpbmljKQp0YWJsZShwRGF0YShoc19leHB0KSR0eXBlb2ZjZWxscykKdGFibGUocERhdGEoaHNfZXhwdCkkdmlzaXQpCnN1bW1hcnkoYXMubnVtZXJpYyhwRGF0YShoc19leHB0KSRlYl9sY190aWVtcG9fZXZvbHVjaW9uKSkKc3VtbWFyeShhcy5udW1lcmljKHBEYXRhKGhzX2V4cHQpJGViX2xjX3R0b19tY3RvX2dsdWNhbl9kb3NpcykpCnN1bW1hcnkoYXMubnVtZXJpYyhwRGF0YShoc19leHB0KSR2M19sY19lamV5X2xlc2lvbl9tbV8xKSkKc3VtbWFyeShhcy5udW1lcmljKHBEYXRhKGhzX2V4cHQpJHYzX2xjX2xlc2lvbl9hcmVhXzEpKQpzdW1tYXJ5KGFzLm51bWVyaWMocERhdGEoaHNfZXhwdCkkdjNfbGNfZWpleF91bGNlcmFfbW1fMSkpCnRhYmxlKHBEYXRhKGhzX2V4cHQpJGViX2xjX3NleG8pCnRhYmxlKHBEYXRhKGhzX2V4cHQpJGViX2xjX2V0bmlhKQpzdW1tYXJ5KGFzLm51bWVyaWMocERhdGEoaHNfZXhwdCkkZWRhZCkpCnRhYmxlKHBEYXRhKGhzX2V4cHQpJGViX2xjX3Blc28pCnRhYmxlKHBEYXRhKGhzX2V4cHQpJGViX2xjX2VzdGF0dXJhKQp0YWJsZShwRGF0YShoc19leHB0KSRlZl9sY19lc3RhZG9fZmluYWxfZXN0dWRpbykKdGFibGUocERhdGEoaHNfZXhwdCkkY2xpbmljYWxvdXRjb21lKQpgYGAKCiMjIERlZmluZSBkZXNpcmVkIGNvbG9ycyBmb3IgdGhlIHZhcmlvdXMgc3Vic2V0cwoKVGhlcmUgYXJlIGxvdHMgb2Ygd2F5cyB3aGljaCB3ZSB3aWxsIGNhdGVnb3JpemUgdGhlIGRhdGEsIGhlcmUgYXJlCnNvbWUgcG90ZW50aWFsIGNvbG9yIGNob2ljZXMgZm9yIHRoZW0uCgpgYGB7ciBjb2xvcl9jaG9pY2VzfQpjZl9jb2xvcnMgPC0gbGlzdCgKICAgICJjdXJlIiA9ICIjOTk4RUMzIiwKICAgICJmYWlsdXJlIiA9ICIjRjFBMzQwIikKdHlwZV92aXNpdF9jb2xvcnMgPC0gbGlzdCgKICAgICJtb25vY3l0ZXNfdjEiID0gIiNERDFDNzciLAogICAgIm1vbm9jeXRlc192MiIgPSAiI0M5OTRDNyIsCiAgICAibW9ub2N5dGVzX3YzIiA9ICIjRTdFMUVGIiwKICAgICJlb3Npbm9waGlsc192MSIgPSAiIzMxQTM1NCIsCiAgICAiZW9zaW5vcGhpbHNfdjIiID0gIiNBREREOEUiLAogICAgImVvc2lub3BoaWxzX3YzIiA9ICIjRjdGQ0Q5IiwKICAgICJuZXV0cm9waGlsc192MSIgPSAiIzMxODJCRCIsCiAgICAibmV1dHJvcGhpbHNfdjIiID0gIiM5RUNBRTEiLAogICAgIm5ldXRyb3BoaWxzX3YzIiA9ICIjREVFQkY3IiwKICAgICJiaW9wc3lfdjEiID0gIiNEOTVGMEUiKQp0eXBlX2NvbG9ycyA8LSBsaXN0KAogICAgIm1vbm9jeXRlcyIgPSAiI0REMUM3NyIsCiAgICAiZW9zaW5vcGhpbHMiID0gIiMzMUEzNTQiLAogICAgIm5ldXRyb3BoaWxzIiA9ICIjMzE4MkJEIiwKICAgICJiaW9wc3kiID0gIiNEOTVGMEUiKQp2aXNpdF9jb2xvcnMgPC0gbGlzdCgpCmNmX3R5cGVfY29sb3JzIDwtIGxpc3QoCiAgICBjdXJlX2Jpb3BzeSA9ICIjRDk1RjBFIiwKICAgIGZhaWx1cmVfYmlvcHN5ID0gIiNGRUM0NEYiLAogICAgY3VyZV9tb25vY3l0ZXMgPSAiI0REMUM3NyIsCiAgICBmYWlsdXJlX21vbm9jeXRlcyA9ICIjQzk5NEM3IiwKICAgIGN1cmVfZW9zaW5vcGhpbHMgPSAiIzMxQTM1NCIsCiAgICBmYWlsdXJlX2Vvc2lub3BoaWxzID0gIiNBREREOEUiLAogICAgY3VyZV9uZXV0cm9waGlscyA9ICIjMzE4MkJEIiwKICAgIGZhaWx1cmVfbmV1dHJvcGhpbHMgPSAiIzlFQ0FFMSIpCmBgYAoKIyBEZWZpbmUgdGhlIHN0YXJ0aW5nIGRhdGEKClRoZSBmb2xsb3dpbmcgYmxvY2sgY3JlYXRlcyB0aGUgcHJpbWFyeSBkYXRhc2V0LCB3aGljaCBpcyB0aGUgcGFyZW50Cm9mIGV2ZXJ5dGhpbmcgd2hpY2ggZm9sbG93cy4KCiMjIFNldCBvdXIgaW5pdGlhbCBjb3ZlcmFnZSBnb2FsCgpUaGVyZSBleGlzdHMgYSBiYXNlbGluZSBjb3ZlcmFnZSBiZWxvdyB3aGljaCB3ZSBkbyBub3Qgd2lzaCB0byBmYWxsLgpPbmUgbGlrZWx5IHdheSB0byBhcHByb2FjaCBpdCBoZXVyaXN0aWNhbGx5IGlzIHRvIGFzc3VtZSB3ZSBzaG91bGQKb2JzZXJ2ZSBzb21lIG51bWJlciBvZiBnZW5lcy4gIFdpdGggdGhhdCBpbiBtaW5kLCBJIGFyYml0cmFyaWx5IGNob3NlCjExLDAwMCBub24temVybyBnZW5lcyBhcyB0aGUgbWluaW11bS4KCldpdGggdGhpcyBpbiBtaW5kLCBoZXJlIGlzIGEgbm9uLXplcm8gcGxvdCBiZWZvcmUgYSBjdXRvZmYgb2YgMTEsMDAwCmdlbmVzLgoKIyMgRmlndXJlIFhYOiBOb24temVybyBnZW5lcyBiZWZvcmUgc2FtcGxlIGZpbHRlcmluZwoKT25lIG9mIHRoZSBsaWtlbHkgZWFybHkgKHN1cHBsZW1lbnRhbD8pZmlndXJlcyBpbiBhIHB1YmxpY2F0aW9uCmluY2x1ZGVzIHRoZSB2aWV3IG9mIG9ic2VydmVkIGdlbmVzIHdpdGggcmVzcGVjdCB0byBjb3ZlcmFnZS4gIEkgdGhpbmsKd2Ugd2lsbCB3YW50IHRvIGluY2x1ZGUgdGhpcyBmb3IgYm90aCBiZWZvcmUgYW5kIGFmdGVyIHNhbXBsZSBmaWx0ZXJpbmcuCgpJIGFtIG5vdCBjZXJ0YWluIHdoeSwgYnV0IG15IGxlZ2VuZCBwbG90dGVyIGlzIHRocm93aW5nIGFuIGVycm9yIQoKb3JhbmdlOiBiaW9wc3kgc2FtcGxlcwpncmVlbjogZW9zaW5vcGhpbHMKcGluazogbW9ub2N5dGVzCmJsdWU6IG5ldXRyb3BoaWxzCgpgYGB7ciBoc19wcmVfbnp9CmFsbF9ueiA8LSBwbG90X25vbnplcm8oaHNfZXhwdCkKYWxsX256JHBsb3QKYGBgCgojIyBTdWJzZXQ6IEZpbHRlciBvdXQgcHJvYmxlbWF0aWMgc2FtcGxlcwoKVG8gbXkgZXllcywgdGhlcmUgYXJlIDMgb3IgNCBzYW1wbGVzIHdoaWNoIGFyZSBsaWtlbHkgY2FuZGlkYXRlcyBmb3IKcmVtb3ZhbC4gIEluIGFkZGl0aW9uLCB3ZSB3aWxsIHJlbW92ZSBzYW1wbGVzIHdoaWNoIHdlcmUgbG9zdCBkdXJpbmcKdGhlIHRyZWF0bWVudCBhbmQvb3Igb25lcyB3aGljaCB3ZXJlIHVzZWQgaW4gb3RoZXIgZXhwZXJpbWVudHMgYnV0CmluY2x1ZGVkIGluIHRoZSBUTVJDMyBzYW1wbGUgc2hlZXQgKHRodXMgdGhlICdub3RhcHBsaWNhYmxlJyBvcgonbnVsbCcpLgoKYGBge3IgaHNfdmFsaWR9CmhzX3ZhbGlkIDwtIHN1YnNldF9leHB0KGhzX2V4cHQsIG5vbnplcm89MTEwMDApICU+JQogIHN1YnNldF9leHB0KHN1YnNldD0iY2xpbmljYWxvdXRjb21lIT0nbG9zdCciKSAlPiUKICBzdWJzZXRfZXhwdChzdWJzZXQ9ImNsaW5pY2Fsb3V0Y29tZSE9J25vdGFwcGxpY2FibGUnIikgJT4lCiAgc3Vic2V0X2V4cHQoc3Vic2V0PSJjbGluaWNhbG91dGNvbWUhPSdudWxsJyIpICU+JQogIHNldF9leHB0X2NvbG9ycyhjZl9jb2xvcnMpCmBgYAoKIyMgRmlndXJlIFhYICsgMTogTm9uLXplcm8gZ2VuZXMgYWZ0ZXIgc2FtcGxlIGZpbHRlcmluZwoKVGhlIGZvbGxvd2luZyBwbG90IGlzIGVzc2VudGlhbGx5IGlkZW50aWNhbCB0byB0aGUgcHJldmlvdXMgd2l0aCB0d28KZXhjZXB0aW9uczoKCjEuICBUaGUgc2FtcGxlcyB3aXRoIHRvbyBmZXcgZ2VuZXMgKDExLDAwMCBjdXJyZW50bHkpIGFyZSBnb25lLgoyLiAgVGhlIHNhbXBsZXMgYXJlIGNvbG9yZWQgYnkgY3VyZShwdXJwbGUpL2ZhaWwoeWVsbG93KQoKYGBge3IgbnpfcG9zdH0KbnpfcG9zdCA8LSBwbG90X25vbnplcm8oaHNfdmFsaWQpCm56X3Bvc3QkcGxvdApgYGAKCiMjIFN1bW1hcml6ZTogVGFsbHkgc2FtcGxlcyBhZnRlciBmaWx0ZXJpbmcKCldlIG5lZWQgdG8ga2VlcCB0cmFjayBvZiBob3cgbWFueSBvZiBlYWNoIHNhbXBsZSB0eXBlIGlzIGxvc3Qgd2hlbiB3ZQpkbyBvdXIgdmFyaW91cyBmaWx0ZXJzLiAgVGh1cyBJIGFtIHJlcGVhdGluZyB0aGUgc2FtZSBzZXQgb2YgdGFsbGllcy4KVGhpcyB3aWxsIGxpa2VseSBoYXBwZW4gb25lIG1vcmUgdGltZSwgZm9sbG93aW5nIHRoZSByZW1vdmFsIG9mCnNhbXBsZXMgd2hpY2ggY2FtZSBmcm9tIENhbGkuCgpgYGB7ciB0YWJsZV92YWxpZH0KdGFibGUocERhdGEoaHNfdmFsaWQpJGRydWcpCnRhYmxlKHBEYXRhKGhzX3ZhbGlkKSRjbGluaWMpCnRhYmxlKHBEYXRhKGhzX3ZhbGlkKSRjbGluaWNhbG91dGNvbWUpCnRhYmxlKHBEYXRhKGhzX3ZhbGlkKSR0eXBlb2ZjZWxscykKdGFibGUocERhdGEoaHNfdmFsaWQpJHZpc2l0KQpzdW1tYXJ5KGFzLm51bWVyaWMocERhdGEoaHNfdmFsaWQpJGViX2xjX3RpZW1wb19ldm9sdWNpb24pKQpzdW1tYXJ5KGFzLm51bWVyaWMocERhdGEoaHNfdmFsaWQpJGViX2xjX3R0b19tY3RvX2dsdWNhbl9kb3NpcykpCnN1bW1hcnkoYXMubnVtZXJpYyhwRGF0YShoc192YWxpZCkkdjNfbGNfZWpleV9sZXNpb25fbW1fMSkpCnN1bW1hcnkoYXMubnVtZXJpYyhwRGF0YShoc192YWxpZCkkdjNfbGNfbGVzaW9uX2FyZWFfMSkpCnN1bW1hcnkoYXMubnVtZXJpYyhwRGF0YShoc192YWxpZCkkdjNfbGNfZWpleF91bGNlcmFfbW1fMSkpCnRhYmxlKHBEYXRhKGhzX3ZhbGlkKSRlYl9sY19zZXhvKQp0YWJsZShwRGF0YShoc192YWxpZCkkZWJfbGNfZXRuaWEpCnN1bW1hcnkoYXMubnVtZXJpYyhwRGF0YShoc192YWxpZCkkZWRhZCkpCnRhYmxlKHBEYXRhKGhzX3ZhbGlkKSRlYl9sY19wZXNvKQp0YWJsZShwRGF0YShoc192YWxpZCkkZWJfbGNfZXN0YXR1cmEpCmBgYAoKIyBTdWJzZXQ6IFNlcGFyYXRlIHNhbXBsZXMgYnkgY2VsbCB0eXBlIGFuZCB2aXNpdAoKR2l2ZSBvdXIgcG9wdWxhdGlvbiBvZiB+IDE5MCBzYW1wbGVzLCB0aGVyZSBhcmUgYSBmZXcgd2F5cyB3ZSBhcmUgbW9zdApsaWtlbHkgdG8gd2FudCB0byBtaXggYW5kIG1hdGNoIHRoZW0uCgpUaGUgZm9sbG93aW5nIGJsb2NrIHBlcmZvcm1lZCBtYW55IHN1YnNldCBvcGVyYXRpb25zIHRvIGNyZWF0ZSBzZXBhcmF0ZQpkYXRhIHN0cnVjdHVyZXMgb24gYSBwZXItY2VsbHR5cGUgYW5kIHBlci12aXNpdCBiYXNpcy4gIEVyZ28sIG91cgpsYXJnZSBkYXRhIHN0cnVjdHVyZSBpcyBub3cgam9pbmVkIGJ5IH4yMSBuZXcsIHNtYWxsZXIgZGF0YQpzdHJ1Y3R1cmVzIHdoaWNoIHdpbGwgaG9wZWZ1bGx5IHByb3ZpZGUgd2F5cyB0byBjb21wYXJlIHRoZSBzYW1wbGVzCmFjcm9zcyB2aXNpdCBhbmQgY2VsbCB0eXBlLgoKYGBge3IgaW5pdGlhbF9zdWJzZXRzfQphbGxfdHlwZXMgPC0gdGFibGUocERhdGEoaHNfdmFsaWQpW1sidHlwZW9mY2VsbHMiXV0pCmFsbF90eXBlcwphbGxfdGltZXMgPC0gdGFibGUocERhdGEoaHNfdmFsaWQpW1sidmlzaXRudW1iZXIiXV0pCmFsbF90aW1lcwoKYmlvcHN5X3NhbXBsZXMgPC0gc3Vic2V0X2V4cHQoaHNfdmFsaWQsIHN1YnNldD0idHlwZW9mY2VsbHM9PSdiaW9wc3knIikKZW9zaW5vcGhpbF9zYW1wbGVzIDwtIHN1YnNldF9leHB0KGhzX3ZhbGlkLCBzdWJzZXQ9InR5cGVvZmNlbGxzPT0nZW9zaW5vcGhpbHMnIikKbW9ub2N5dGVfc2FtcGxlcyA8LSBzdWJzZXRfZXhwdChoc192YWxpZCwgc3Vic2V0PSJ0eXBlb2ZjZWxscz09J21vbm9jeXRlcyciKQpuZXV0cm9waGlsX3NhbXBsZXMgPC0gc3Vic2V0X2V4cHQoaHNfdmFsaWQsIHN1YnNldD0idHlwZW9mY2VsbHM9PSduZXV0cm9waGlscyciKQoKIyMgQ3VycmVudGx5LCB0aGVzZSBhcmUgbm90IHVzZWQsIGJ1dCBpbnN0ZWFkIEkgcHVsbGVkIHRoZSBzYW1wbGVzIGZyb20gdGhlIGhzX2NsaW5pY2FsCiMjIHdoaWNoIG1lYW5zIHRoZSBiaW9wc2llcyBhcmUgbm90IGluY2x1ZGVkLgp2MV9zYW1wbGVzIDwtIHN1YnNldF9leHB0KGhzX3ZhbGlkLCBzdWJzZXQ9InZpc2l0bnVtYmVyPT0nMSciKQp2MV9tb25vY3l0ZXMgPC0gc3Vic2V0X2V4cHQodjFfc2FtcGxlcywgc3Vic2V0PSJ0eXBlb2ZjZWxscz09J21vbm9jeXRlcyciKQp2MV9uZXV0cm9waGlscyA8LSBzdWJzZXRfZXhwdCh2MV9zYW1wbGVzLCBzdWJzZXQ9InR5cGVvZmNlbGxzPT0nbmV1dHJvcGhpbHMnIikKdjFfZW9zaW5vcGhpbHMgPC0gc3Vic2V0X2V4cHQodjFfc2FtcGxlcywgc3Vic2V0PSJ0eXBlb2ZjZWxscz09J2Vvc2lub3BoaWxzJyIpCgp2Ml9zYW1wbGVzIDwtIHN1YnNldF9leHB0KGhzX3ZhbGlkLCBzdWJzZXQ9InZpc2l0bnVtYmVyPT0nMiciKQp2Ml9tb25vY3l0ZXMgPC0gc3Vic2V0X2V4cHQodjJfc2FtcGxlcywgc3Vic2V0PSJ0eXBlb2ZjZWxscz09J21vbm9jeXRlcyciKQp2Ml9uZXV0cm9waGlscyA8LSBzdWJzZXRfZXhwdCh2Ml9zYW1wbGVzLCBzdWJzZXQ9InR5cGVvZmNlbGxzPT0nbmV1dHJvcGhpbHMnIikKdjJfZW9zaW5vcGhpbHMgPC0gc3Vic2V0X2V4cHQodjJfc2FtcGxlcywgc3Vic2V0PSJ0eXBlb2ZjZWxscz09J2Vvc2lub3BoaWxzJyIpCgp2M19zYW1wbGVzIDwtIHN1YnNldF9leHB0KGhzX3ZhbGlkLCBzdWJzZXQ9InZpc2l0bnVtYmVyPT0nMyciKQp2M19tb25vY3l0ZXMgPC0gc3Vic2V0X2V4cHQodjNfc2FtcGxlcywgc3Vic2V0PSJ0eXBlb2ZjZWxscz09J21vbm9jeXRlcyciKQp2M19uZXV0cm9waGlscyA8LSBzdWJzZXRfZXhwdCh2M19zYW1wbGVzLCBzdWJzZXQ9InR5cGVvZmNlbGxzPT0nbmV1dHJvcGhpbHMnIikKdjNfZW9zaW5vcGhpbHMgPC0gc3Vic2V0X2V4cHQodjNfc2FtcGxlcywgc3Vic2V0PSJ0eXBlb2ZjZWxscz09J2Vvc2lub3BoaWxzJyIpCmBgYAoKIyBTdW1tYXJpemU6IFRhYnVsYXRlIHNhbXBsZSBudW1iZXJzCgpIZXJlIGlzIGFuIG91dGxpbmUgb2YgdGhlIHNhbXBsZXMgaW4gdGhlaXIgY3VycmVudCBzdGF0ZToKCiogQnkgdHlwZTogYG5jb2woZXhwcnMoaHNfdmFsaWQpKWAsIEN1cmU6IGBzdW0ocERhdGEoaHNfdmFsaWQpW1siY2xpbmljYWxvdXRjb21lIl1dID09ICJjdXJlIilgLCBGYWlsOiBgc3VtKHBEYXRhKGhzX3ZhbGlkKVtbImNsaW5pY2Fsb3V0Y29tZSJdXSA9PSAiZmFpbHVyZSIpYAogICAgKiAgQmlvcHN5OiBgYWxsX3R5cGVzW1siYmlvcHN5Il1dYCwgQ3VyZTogYHN1bShwRGF0YShiaW9wc3lfc2FtcGxlcylbWyJjbGluaWNhbG91dGNvbWUiXV0gPT0gImN1cmUiKWAsIEZhaWw6IGBzdW0ocERhdGEoYmlvcHN5X3NhbXBsZXMpW1siY2xpbmljYWxvdXRjb21lIl1dID09ICJmYWlsdXJlIilgCiAgICAgICAgKiBBbGwgYmlvcHN5IHNhbXBsZXMgYXJlIHZpc2l0IDEuCiAgICAqICBFb3Npbm9waGlsczogYGFsbF90eXBlc1tbImVvc2lub3BoaWxzIl1dYCwgQ3VyZTogYHN1bShwRGF0YShlb3Npbm9waGlsX3NhbXBsZXMpW1siY2xpbmljYWxvdXRjb21lIl1dID09ICJjdXJlIilgLCBGYWlsOiBgc3VtKHBEYXRhKGVvc2lub3BoaWxfc2FtcGxlcylbWyJjbGluaWNhbG91dGNvbWUiXV0gPT0gImZhaWx1cmUiKWAKICAgICAgICAqIFYxIEVvc2lub3BoaWxzOiBgbnJvdyhwRGF0YSh2MV9lb3Npbm9waGlscykpYCwgQ3VyZTogYHN1bShwRGF0YSh2MV9lb3Npbm9waGlscylbWyJjbGluaWNhbG91dGNvbWUiXV0gPT0gImN1cmUiKWAsIEZhaWw6IGBzdW0ocERhdGEodjFfZW9zaW5vcGhpbHMpW1siY2xpbmljYWxvdXRjb21lIl1dID09ICJmYWlsdXJlIilgCiAgICAgICAgKiBWMiBFb3Npbm9waGlsczogYG5yb3cocERhdGEodjJfZW9zaW5vcGhpbHMpKWAsIEN1cmU6IGBzdW0ocERhdGEodjJfZW9zaW5vcGhpbHMpW1siY2xpbmljYWxvdXRjb21lIl1dID09ICJjdXJlIilgLCBGYWlsOiBgc3VtKHBEYXRhKHYyX2Vvc2lub3BoaWxzKVtbImNsaW5pY2Fsb3V0Y29tZSJdXSA9PSAiZmFpbHVyZSIpYAogICAgICAgICogVjMgRW9zaW5vcGhpbHM6IGBucm93KHBEYXRhKHYzX2Vvc2lub3BoaWxzKSlgLCBDdXJlOiBgc3VtKHBEYXRhKHYzX2Vvc2lub3BoaWxzKVtbImNsaW5pY2Fsb3V0Y29tZSJdXSA9PSAiY3VyZSIpYCwgRmFpbDogYHN1bShwRGF0YSh2M19lb3Npbm9waGlscylbWyJjbGluaWNhbG91dGNvbWUiXV0gPT0gImZhaWx1cmUiKWAKICAgICogIE1vbm9jeXRlczogYGFsbF90eXBlc1tbIm1vbm9jeXRlcyJdXWAsIEN1cmU6IGBzdW0ocERhdGEobW9ub2N5dGVfc2FtcGxlcylbWyJjbGluaWNhbG91dGNvbWUiXV0gPT0gImN1cmUiKWAsIEZhaWw6IGBzdW0ocERhdGEobW9ub2N5dGVfc2FtcGxlcylbWyJjbGluaWNhbG91dGNvbWUiXV0gPT0gImZhaWx1cmUiKWAKICAgICAgICAqIFYxIE1vbm9jeXRlczogYG5yb3cocERhdGEodjFfbW9ub2N5dGVzKSlgLCBDdXJlOiBgc3VtKHBEYXRhKHYxX21vbm9jeXRlcylbWyJjbGluaWNhbG91dGNvbWUiXV0gPT0gImN1cmUiKWAsIEZhaWw6IGBzdW0ocERhdGEodjFfbW9ub2N5dGVzKVtbImNsaW5pY2Fsb3V0Y29tZSJdXSA9PSAiZmFpbHVyZSIpYAogICAgICAgICogVjIgTW9ub2N5dGVzOiBgbnJvdyhwRGF0YSh2Ml9tb25vY3l0ZXMpKWAsIEN1cmU6IGBzdW0ocERhdGEodjJfbW9ub2N5dGVzKVtbImNsaW5pY2Fsb3V0Y29tZSJdXSA9PSAiY3VyZSIpYCwgRmFpbDogYHN1bShwRGF0YSh2Ml9tb25vY3l0ZXMpW1siY2xpbmljYWxvdXRjb21lIl1dID09ICJmYWlsdXJlIilgCiAgICAgICAgKiBWMyBNb25vY3l0ZXM6IGBucm93KHBEYXRhKHYzX21vbm9jeXRlcykpYCwgQ3VyZTogYHN1bShwRGF0YSh2M19tb25vY3l0ZXMpW1siY2xpbmljYWxvdXRjb21lIl1dID09ICJjdXJlIilgLCBGYWlsOiBgc3VtKHBEYXRhKHYzX21vbm9jeXRlcylbWyJjbGluaWNhbG91dGNvbWUiXV0gPT0gImZhaWx1cmUiKWAKICAgICogIE5ldXRyb3BoaWxzOiBgYWxsX3R5cGVzW1sibmV1dHJvcGhpbHMiXV1gLCBDdXJlOiBgc3VtKHBEYXRhKG5ldXRyb3BoaWxfc2FtcGxlcylbWyJjbGluaWNhbG91dGNvbWUiXV0gPT0gImN1cmUiKWAsIEZhaWw6IGBzdW0ocERhdGEobmV1dHJvcGhpbF9zYW1wbGVzKVtbImNsaW5pY2Fsb3V0Y29tZSJdXSA9PSAiZmFpbHVyZSIpYAogICAgICAgICogVjEgTmV1dHJvcGhpbHM6IGBucm93KHBEYXRhKHYxX25ldXRyb3BoaWxzKSlgLCBDdXJlOiBgc3VtKHBEYXRhKHYxX25ldXRyb3BoaWxzKVtbImNsaW5pY2Fsb3V0Y29tZSJdXSA9PSAiY3VyZSIpYCwgRmFpbDogYHN1bShwRGF0YSh2MV9uZXV0cm9waGlscylbWyJjbGluaWNhbG91dGNvbWUiXV0gPT0gImZhaWx1cmUiKWAKICAgICAgICAqIFYyIE5ldXRyb3BoaWxzOiBgbnJvdyhwRGF0YSh2Ml9tb25vY3l0ZXMpKWAsIEN1cmU6IGBzdW0ocERhdGEodjJfbmV1dHJvcGhpbHMpW1siY2xpbmljYWxvdXRjb21lIl1dID09ICJjdXJlIilgLCBGYWlsOiBgc3VtKHBEYXRhKHYyX25ldXRyb3BoaWxzKVtbImNsaW5pY2Fsb3V0Y29tZSJdXSA9PSAiZmFpbHVyZSIpYAogICAgICAgICogVjMgTmV1dHJvcGhpbHM6IGBucm93KHBEYXRhKHYzX25ldXRyb3BoaWxzKSlgLCBDdXJlOiBgc3VtKHBEYXRhKHYzX25ldXRyb3BoaWxzKVtbImNsaW5pY2Fsb3V0Y29tZSJdXSA9PSAiY3VyZSIpYCwgRmFpbDogYHN1bShwRGF0YSh2M19uZXV0cm9waGlscylbWyJjbGluaWNhbG91dGNvbWUiXV0gPT0gImZhaWx1cmUiKWAKCiMgRGF0YXNldDogUGFyYXNpdGUgcmVhZHMKCk1ha2UgYW4gZXhwcmVzc2lvbnNldCBvZiB0aGUgcGFyYXNpdGUgcmVhZHMgaW4gdGhlIFRNUkMzIHNhbXBsZXMgYW5kCmRpc3Rpbmd1aXNoIGJldHdlZW4gdGhlIGZhdXggYW5kIHJlYWwgcmVhZHMuCkUuZzogQXJlIHRoZXJlIHNhbXBsZXMgd2hpY2ggZGVmaW5pdGl2ZWx5IGNvbnRhaW4gcGFyYXNpdGVzPwoKTGF0ZXIsIEkgbWFudWFsbHkgd2VudCB0aHJvdWdoIHRoZSBtYXBwaW5ncyBvZiBzYW1wbGVzIHdpdGggYQpzaWduaWZpY2FudCBudW1iZXIgb2YgcGFyYXNpdGUgcmVhZHMgaW4gSUdWIHdpdGggc29tZSBUTVJDMiBrbm93bgp6eW1vZGVtZSBzYW1wbGVzLiAgSW4gbWFueSBjYXNlcyBpdCBpcyBwb3NzaWJsZSB0byBzdGF0ZSBkZWZpbml0aXZlbHkKdGhlIGNsYXNzaWZpY2F0aW9uIG9mIHRoZSBwYXJhc2l0ZSB3aGljaCBpbmZlY3RlZCBhbiBpbmRpdmlkdWFsLgoKYGBge3IgcGFyYXNpdGVfZXhwdH0KbHBfZXhwdCA8LSBzbShjcmVhdGVfZXhwdChzYW1wbGVzaGVldCwKICAgICAgICAgICAgICAgICAgICAgICBmaWxlX2NvbHVtbj0ibHBhbmFtZW5zaXN2MzZoaXNhdGZpbGUiLCBnZW5lX2luZm8gPSBOVUxMKSkgJT4lCiAgc3Vic2V0X2V4cHQoY292ZXJhZ2U9MTAwMCkgJT4lCiAgc2V0X2V4cHRfY29uZGl0aW9ucyhmYWN0PSJ0eXBlb2ZjZWxscyIpCnZpc2l0X2ZhY3QgPC0gcERhdGEobHBfZXhwdClbWyJ2aXNpdG51bWJlciJdXQpiYXRjaF9uYSA8LSBpcy5uYSh2aXNpdF9mYWN0KQp2aXNpdF9mYWN0W2JhdGNoX25hXSA8LSAidW5kZWZpbmVkIgpscF9leHB0IDwtIHNldF9leHB0X2JhdGNoZXMobHBfZXhwdCwgZmFjdCA9IHZpc2l0X2ZhY3QpCgpscF9ub3JtIDwtIG5vcm1hbGl6ZV9leHB0KGxwX2V4cHQsIGZpbHRlcj0ic2ltcGxlIiwgbm9ybT0icXVhbnQiLAogICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnZlcnQ9ImNwbSIsIHRyYW5zZm9ybT0ibG9nMiIpCnBsb3R0ZWQgPC0gcGxvdF9wY2EobHBfbm9ybSwgcGxvdF9sYWJlbHM9RkFMU0UpCnBsb3R0ZWQkcGxvdApwbG90dGVkXzNkIDwtIHBsb3RfM2RfcGNhKHBsb3R0ZWQpCmBgYAoKVGhlIGFib3ZlIGJsb2NrIGlzIHNpbWlsYXIgaW4gY29uY2VwdCB0byB0aGUgcHJldmlvdXMgZXhwcmVzc2lvbnNldApjcmVhdGlvbi4gIEl0IHVzZXMgYSBkaWZmZXJlbnQgY29sdW1uIGFuZCBjdXJyZW50bHkgaWdub3JlcyB0aGUgZ2VuZQphbm5vdGF0aW9ucy4gIEdpdmVuIHRoYXQgbWFueSBvZiB0aGUgc2FtcGxlcyBoYXZlIGVzc2VudGlhbGx5IDAgcmVhZHMsCkkgc2V0IGEgY3V0b2ZmIG9mIG9ubHkgMjAgb2JzZXJ2ZWQgZ2VuZXMuICBGaW5hbGx5LCBJIGRpZCBhIHF1aWNrIGFuZApkaXJ0eSBQQ0EgcGxvdCBvZiB0aGlzIHBlY3VsaWFyIGRhdGEgc3RydWN0dXJlIGluIHRoZSBob3BlcyBvZiBiZWluZwphYmxlIHRvICdzZWUnIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gd2hhdCBhcmUgYXNzdW1lZCB0byBiZSAncmVhbCcKc2FtcGxlcyB3aXRoIGEgc2lnbmlmaWNhbnQgbnVtYmVyIG9mICdyZWFsJyBwYXJhc2l0ZSByZWFkcyB2cy4gdGhvc2UKc2FtcGxlcyB3aGljaCBqdXN0IGhhdmUgYSBjb3VwbGUgb2YgcG90ZW50aWFsbHkgc3B1cmlvdXMgcmVhZHMuCgojIEhvc3QgRGlzdHJpYnV0aW9ucy9WaXN1YWxpemF0aW9ucyBvZiBpbnRlcmVzdAoKVGhlIHNldHMgb2Ygc2FtcGxlcyB1c2VkIHRvIHZpc3VhbGl6ZSB0aGUgZGF0YSB3aWxsIGFsc28gY29tcHJpc2UgdGhlCnNldHMgdXNlZCB3aGVuIGxhdGVyIHBlcmZvcm1pbmcgdGhlIHZhcmlvdXMgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24KYW5hbHlzZXMuCgojIyBHbG9iYWwgbWV0cmljcwoKU3RhcnQgb3V0IHdpdGggc29tZSBpbml0aWFsIG1ldHJpY3Mgb2YgYWxsIHNhbXBsZXMuICBUaGUgbW9zdCBvYnZpb3VzCmFyZSBwbG90cyBvZiB0aGUgbnVtYmVycyBvZiBub24temVybyBnZW5lcyBvYnNlcnZlZCwgaGVhdG1hcHMgc2hvd2luZwp0aGUgcmVsYXRpdmUgcmVsYXRpb25zaGlwcyBhbW9uZyB0aGUgc2FtcGxlcywgdGhlIHJlbGF0aXZlIGxpYnJhcnkKc2l6ZXMsIGFuZCBzb21lIFBDQS4gIEl0IG1pZ2h0IGJlIHNtYXJ0IHRvIHNwbGl0IHRoZSBsaWJyYXJ5IHNpemVzIHVwCmFjcm9zcyBzdWJzZXRzIG9mIHRoZSBkYXRhLCBiZWNhdXNlIHRoZXkgaGF2ZSBleHBhbmRlZCB0b28gZmFyIHRvIHNlZQp3ZWxsIG9uIGEgY29tcHV0ZXIgc2NyZWVuLgoKVGhlIG1vc3QgbGlrZWx5IGZhY3RvcnMgdG8gcXVlcnkgd2hlbiBjb25zaWRlcmluZyB0aGUgZW50aXJlIGRhdGFzZXQKYXJlIGN1cmUvZmFpbCwgdmlzaXQsIGFuZCBjZWxsIHR5cGUuICBUaGlzIGlzIHRoZSBsZXZlbCBhdCB3aGljaCB3ZQp3aWxsIGNob29zZSBzYW1wbGVzIHRvIGV4Y2x1ZGUgZnJvbSBmdXR1cmUgYW5hbHlzZXMuCgpgYGB7ciBnbG9iYWxfZGlzdHJpYnV0aW9uc30KcGxvdF9sZWdlbmQoYmlvcHN5X3NhbXBsZXMpJHBsb3QKcGxvdF9saWJzaXplKGJpb3BzeV9zYW1wbGVzKSRwbG90CnBsb3Rfbm9uemVybyhiaW9wc3lfc2FtcGxlcykkcGxvdApiaW9wc3lfcHJlcG9zdCA8LSBwbG90X2xpYnNpemVfcHJlcG9zdChiaW9wc3lfc2FtcGxlcykKYmlvcHN5X3ByZXBvc3QkY291bnRfcGxvdApiaW9wc3lfcHJlcG9zdCRsb3dnZW5lX3Bsb3QKIyMgTWluaW11bSBudW1iZXIgb2YgYmlvcHN5IGdlbmVzOiB+IDE0LDAwMAoKcGxvdF9saWJzaXplKGVvc2lub3BoaWxfc2FtcGxlcykkcGxvdApwbG90X25vbnplcm8oZW9zaW5vcGhpbF9zYW1wbGVzKSRwbG90CmVvc2lub3BoaWxfcHJlcG9zdCA8LSBwbG90X2xpYnNpemVfcHJlcG9zdChlb3Npbm9waGlsX3NhbXBsZXMpCmVvc2lub3BoaWxfcHJlcG9zdCRjb3VudF9wbG90CmVvc2lub3BoaWxfcHJlcG9zdCRsb3dnZW5lX3Bsb3QKIyMgTWluaW11bSBudW1iZXIgb2YgZW9zaW5vcGhpbCBnZW5lczogfiAxMyw1MDAKCnBsb3RfbGlic2l6ZShtb25vY3l0ZV9zYW1wbGVzKSRwbG90CnBsb3Rfbm9uemVybyhtb25vY3l0ZV9zYW1wbGVzKSRwbG90Cm1vbm9jeXRlX3ByZXBvc3QgPC0gcGxvdF9saWJzaXplX3ByZXBvc3QobW9ub2N5dGVfc2FtcGxlcykKbW9ub2N5dGVfcHJlcG9zdCRjb3VudF9wbG90Cm1vbm9jeXRlX3ByZXBvc3QkbG93Z2VuZV9wbG90CiMjIE1pbmltdW0gbnVtYmVyIG9mIG1vbm9jeXRlIGdlbmVzOiB+IDcsNTAwIGJlZm9yZSBzZXR0aW5nIHRoZSBtaW5pbXVtLgoKcGxvdF9saWJzaXplKG5ldXRyb3BoaWxfc2FtcGxlcykkcGxvdApwbG90X25vbnplcm8obmV1dHJvcGhpbF9zYW1wbGVzKSRwbG90Cm5ldXRyb3BoaWxfcHJlcG9zdCA8LSBwbG90X2xpYnNpemVfcHJlcG9zdChuZXV0cm9waGlsX3NhbXBsZXMpCm5ldXRyb3BoaWxfcHJlcG9zdCRjb3VudF9wbG90Cm5ldXRyb3BoaWxfcHJlcG9zdCRsb3dnZW5lX3Bsb3QKIyMgTWluaW11bSBudW1iZXIgb2YgbmV1dHJvcGhpbCBnZW5lczogfiAxMCwwMDAgYmVmb3JlIHNldHRpbmcgbWluaW11bSBjb3ZlcmFnZS4KYGBgCgpUaGUgYWJvdmUgYmxvY2sganVzdCByZXBlYXRzIHRoZSBzYW1lIHR3byBwbG90cyBvbiBhIHBlci1jZWxsdHlwZQpiYXNpczogdGhlIG51bWJlciBvZiByZWFkcyBvYnNlcnZlZCAvIHNhbXBsZSBhbmQgYSBwbG90IG9mIG9ic2VydmVkCmdlbmVzIHdpdGggcmVzcGVjdCB0byBjb3ZlcmFnZS4gIEkgbWFkZSBzb21lIGNvbW1lbnRzIHdpdGggbXkKb2JzZXJ2YXRpb25zIGFib3V0IHRoZSBudW1iZXIgb2YgZ2VuZXMuCgojIyBQQ0E6IEdsb2JhbCB2aWV3cyBvZiBhbGwgY2VsbCB0eXBlcwoKTm93IHRoYXQgdGhvc2UgJ2dsb2JhbCcgbWV0cmljcyBhcmUgb3V0IG9mIHRoZSB3YXksIGxldHMgbG9vayBhdCBzb21lCmdsb2JhbCBtZXRyaWNzIG9mIHRoZSBkYXRhIGZvbGxvd2luZyBub3JtYWxpemF0aW9uOyB0aGUgbW9zdCBsaWtlbHkKcGxvdHMgYXJlIG9mIGNvdXJzZSBQQ0EgYnV0IGFsc28gYSBjb3VwbGUgb2YgaGVhdG1hcHMuCgojIyMgRmlndXJlIDEKCkluIHRoZSBnb29nbGUgZG9jIFRNUkMzX0F1ZzE4XzIwMjEsIHRoZXJlIGlzIGFuIGV4YW1wbGUgb2YgYW4gaW1hZ2UKZm9yIHRoZSBmaXJzdCBmaWd1cmU6CgoiVHJhbnNjcmlwdG9taWMgcHJvZmlsZXMgb2YgcHJpbWFyeSBpbm5hdGUgY2VsbHMgb2YgQ0wgcGF0aWVudHMgc2hvdwp1bmlxdWUgdHJhbnNjcmlwdGlvbmFsIHNpZ25hdHVyZXMgLSBSZW1vdmUgUEJNQ3MgYW5kIE0wLCBtYXliZQpiaW9wc2llcyBhcyB3ZWxsIChidXQgUmVtb3ZlIFdUIHNhbXBsZXMpIgoKV2hpbGUgd2Ugd2VyZSB0YWxraW5nIGluIGEgbWVldGluZyBob3dldmVyLCBpdCBzb3VuZGVkIGxpa2UgdGhlcmUgd2FzCnNvbWUgZGVzaXJlIHRvIGtlZXAgYWxsIGNlbGwgdHlwZXMuICBUaGVyZWZvcmUgdGhlIGZvbGxvd2luZyBibG9jawpoYXMgb25lIGltYWdlIHdpdGggZXZlcnl0aGluZyBhbmQgb25lIGZvbGxvd2luZyB0aGUgYWJvdmUuCgpgYGB7ciBnbG9iYWxfcGNhfQp0eXBlX3ZhbGlkIDwtIHNldF9leHB0X2NvbmRpdGlvbnMoaHNfdmFsaWQsIGZhY3Q9InR5cGVvZmNlbGxzIikgJT4lCiAgc2V0X2V4cHRfYmF0Y2hlcyhmYWN0PSJjbGluaWNhbG91dGNvbWUiKSAlPiUKICBzZXRfZXhwdF9jb2xvcnModHlwZV9jb2xvcnMpCgphbGxfbm9ybSA8LSBzbShub3JtYWxpemVfZXhwdCh0eXBlX3ZhbGlkLCB0cmFuc2Zvcm09ImxvZzIiLCBub3JtPSJxdWFudCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnZlcnQ9ImNwbSIsIGZpbHRlcj1UUlVFKSkKCmFsbF9wY2EgPC0gcGxvdF9wY2EoYWxsX25vcm0sIHBsb3RfbGFiZWxzPUZBTFNFLAogICAgICAgICAgICAgICAgICAgIHBsb3RfdGl0bGU9IlBDQSAtIENlbGwgdHlwZSIsIHNpemVfY29sdW1uPSJ2aXNpdG51bWJlciIpCmRldiA8LSBwcChmaWxlPWdsdWUoImltYWdlcy90bXJjM19wY2Ffbm9sYWJlbHMtdnt2ZXJ9LnBuZyIpKQphbGxfcGNhJHBsb3QKY2xvc2VkIDwtIGRldi5vZmYoKQphbGxfcGNhJHBsb3QKCmFsbF9wY2Ffbm9zaXplIDwtIHBsb3RfcGNhKGFsbF9ub3JtLCBwbG90X2xhYmVscz1GQUxTRSkKYWxsX3BjYV9ub3NpemUkcGxvdAoKd3JpdGUuY3N2KGFsbF9wY2EkdGFibGUsIGZpbGU9ImNvb3Jkcy9oc19kb25vcl9wY2FfY29vcmRzLmNzdiIpCmFsbF9jZl9ub3JtIDwtIHNldF9leHB0X2JhdGNoZXMoYWxsX25vcm0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFjdD0idmlzaXRudW1iZXIiKQphbGxfY2ZfY29yaGVhdCA8LSBwbG90X2NvcmhlYXQoYWxsX2NmX25vcm0sIHBsb3RfdGl0bGU9IkhlaXJhcmNoaWNhbCBjbHVzdGVyaW5nOgogICAgICAgICBjZWxsIHR5cGVzIikKCmRldiA8LSBwcChmaWxlPWdsdWUoImltYWdlcy90bXJjM19jb3JoZWF0X2NmLXZ7dmVyfS5wbmciKSkKYWxsX2NmX2NvcmhlYXQkcGxvdApjbG9zZWQgPC0gZGV2Lm9mZigpCmFsbF9jZl9jb3JoZWF0JHBsb3QKCmFsbF9jZl9kaXNoZWF0IDwtIHBsb3RfZGlzaGVhdChhbGxfY2Zfbm9ybSwgcGxvdF90aXRsZT0iSGVpcmFyY2hpY2FsIGNsdXN0ZXJpbmc6CiAgICAgICAgIGNlbGwgdHlwZXMiKQpkZXYgPC0gcHAoZmlsZT1nbHVlKCJpbWFnZXMvdG1yYzNfZGlzaGVhdF9jZi12e3Zlcn0ucG5nIikpCmFsbF9jZl9kaXNoZWF0JHBsb3QKY2xvc2VkIDwtIGRldi5vZmYoKQphbGxfY2ZfZGlzaGVhdCRwbG90CmBgYAoKIyMgRmlndXJlIDFCOiBUcmFuc2NyaXB0b21pYyBwcm9maWxlcyBvZiBwcmltYXJ5IGlubmF0ZSBjZWxscwoKQSBwb3RlbnRpYWwgZmlndXJlIGxlZ2VuZCBmb3IgdGhlIGZvbGxvd2luZyBpbWFnZXMgbWlnaHQgaW5jbHVkZToKClRoZSBvYnNlcnZlZCBjb3VudHMgcGVyIGdlbmUgZm9yIGFsbCBvZiB0aGUgY2xpbmljYWwgc2FtcGxlcyB3ZXJlCmZpbHRlcmVkLCBsb2cgdHJhbnNmb3JtZWQsIGNwbSBjb252ZXJ0ZWQsIGFuZCBxdWFudGlsZSBub3JtYWxpemVkLgpUaGUgY29sb3JzIHdlcmUgZGVmaW5lZCBieSBjZWxsIHR5cGVzIGFuZCBzaGFwZXMgYnkgcGF0aWVudCB2aXNpdC4KV2hlbiB0aGUgZmlyc3QgdHdvIHByaW5jaXBsZSBjb21wb25lbnRzIHdlcmUgcGxvdHRlZCwgY2x1c3RlcmluZyB3YXMKb2JzZXJ2ZWQgYnkgY2VsbCB0eXBlLiAgVGhlIGJpb3BzeSBzYW1wbGVzIHdlcmUgc2lnbmlmaWNhbnRseQpkaWZmZXJlbnQgZnJvbSB0aGUgaW5uYXRlIGltbXVuZSBjZWxsIHR5cGVzLgoKYGBge3IgZmlnMWJfdHJhbnNjcmlwdG9taWNfcHJvZmlsZXN9CmZpZzF2Ml9ub3JtIDwtIG5vcm1hbGl6ZV9leHB0KHR5cGVfdmFsaWQsIHRyYW5zZm9ybT0ibG9nMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnZlcnQ9ImNwbSIsIG5vcm09InF1YW50IiwgZmlsdGVyPVRSVUUpCmZpZzF2Ml9wY2EgPC0gcGxvdF9wY2EoZmlnMXYyX25vcm0sIGNpcz1GQUxTRSkKZGV2IDwtIHBwKGZpbGU9Z2x1ZSgiaW1hZ2VzL3RtcmMzX2ZpZzF2Mi5wbmciKSkKZmlnMXYyX3BjYSRwbG90CmNsb3NlZCA8LSBkZXYub2ZmKCkKZmlnMXYyX3BjYSRwbG90CgpmaWcxdjNfc2FtcGxlcyA8LSBzdWJzZXRfZXhwdCh0eXBlX3ZhbGlkLCBzdWJzZXQ9ImNvbmRpdGlvbiE9J2Jpb3BzeSciKQpmaWcxdjNfbm9ybSA8LSBub3JtYWxpemVfZXhwdChmaWcxdjNfc2FtcGxlcywgdHJhbnNmb3JtPSJsb2cyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udmVydD0iY3BtIiwgbm9ybT0icXVhbnQiLCBmaWx0ZXI9VFJVRSkKZmlnMXYzX3BjYSA8LSBwbG90X3BjYShmaWcxdjNfbm9ybSwgY2lzPUZBTFNFKQpkZXYgPC0gcHAoZmlsZT0iaW1hZ2VzL3RtcmMzX2ZpZzF2My5wbmciKQpmaWcxdjNfcGNhJHBsb3QKY2xvc2VkIDwtIGRldi5vZmYoKQpmaWcxdjNfcGNhJHBsb3QKYGBgCgojIERhdGFzZXQ6IENsaW5pY2FsIHNhbXBsZXMKClRoZSBmb2xsb3dpbmcgYmxvY2sgZGVmaW5lcyBhbiBleHBsaWNpdCBzZXBhcmF0aW9uIGJldHdlZW4gdGhlCmJpb3BzeSBhbmQgb3RoZXIgY2xpbmljYWwgc2FtcGxlcyAoTW9ub2N5dGUsIE5ldXRyb3BoaWwsIEVvc2lub3BoaWwpLgpUaGlzIHdhcyBkb25lIGZvciB0d28gcmVhc29uczogd2UgYXJlIG9ubHkgdXNpbmcgdmlzaXQgMSBzYW1wbGVzIGZvcgp0aGUgYmlvcHNpZXMsIGFuZCB3ZSBoYXZlIGEgcmVsYXRpdmVseSBzdHJvbmcgaHlwb3RoZXNpcyB0aGF0IHRoZQpiaW9wc3kgc2FtcGxlcyB3aWxsIG5vdCBwcm92ZSB0byBiZSBpbmZvcm1hdGl2ZSBmb3IgY3VyZS9mYWlsCnF1ZXN0aW9ucy4KCmBgYHtyIGNsaW5pY2FsX2hzfQpoc19jbGluaWNhbCA8LSBoc192YWxpZCAlPiUKICBzZXRfZXhwdF9jb25kaXRpb25zKGZhY3Q9ImNsaW5pY2Fsb3V0Y29tZSIpICU+JQogIHNldF9leHB0X2JhdGNoZXMoZmFjdD0idHlwZW9mY2VsbHMiKSAlPiUKICBzZXRfZXhwdF9jb2xvcnMoY2ZfY29sb3JzKQoKaHNfY2xpbmljYWxfbm9iaW9wIDwtIHN1YnNldF9leHB0KGhzX2NsaW5pY2FsLCBzdWJzZXQ9InR5cGVvZmNlbGxzIT0nYmlvcHN5JyIpCmBgYAoKIyBDb21wYXJlIHNhbXBsZXMgYnkgY2xpbmljCgpTcG9pbGVyIGFsZXJ0OiAgVGhpcyBzZWN0aW9uIHdpbGwgZXZlbnR1YWxseSBzdWdnZXN0IHByZXR0eSBzdHJvbmdseQp0aGF0IHdlIHdpbGwgbm90IGVhc2lseSBiZSBhYmxlIHRvIHVzZSB0aGUgQ2FsaSBzYW1wbGVzLiAgVGh1cywgYWZ0ZXIKZmluaXNoaW5nIGl0LCB3ZSB3aWxsIGxpa2VseSBleGNsdWRlIHRob3NlIHNhbXBsZXMuCgpUYWtlIGEgbW9tZW50IHRvIHZpZXcgdGhlIGJpb3BzeSBzYW1wbGVzLiAgV2Ugc2VwYXJhdGVkIHRoZW0gYnkgY2xpbmljCihDYWxpIG9yIFR1bWFjbyksIGFuZCB0aGlzIHZpZXcgb2YgdGhlIHNhbXBsZXMgaXMgdGhlIG9ubHkgb25lIHdoaWNoCmRvZXMgbm90IHN1Z2dlc3QgYSBzdHJvbmcgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSB0d28gY2xpbmljcy4KSG93ZXZlciwgaXQgYWxzbyBzdWdnZXN0cyB0aGF0IHRoZSBiaW9wc3kgc2FtcGxlcyB3aWxsIG5vdCBwcm92ZSB2ZXJ5IGhlbHBmdWwuCgojIyBTdWJzZXQ6IEJpb3BzaWVzIGJ5IGNsaW5pYwoKV2Ugc29tZXdoYXQgZXhwZWN0IGJpb3BzeSBzYW1wbGVzIHRvIGJlIHNvbWV0aGluZyBvZiBhIG1lc3MgaW4gcHJldHR5Cm11Y2ggYW55IGNvbnRleHQsIHNpbmNlIHRoZXkgYXJlIGxhcmdlLXNjYWxlIGhldGVyZ2VuZW91cyBjb2xsZWN0aW9ucwpvZiBjZWxsIHR5cGVzLiAgVGhlIGZvbGxvd2luZyBibG9jayB3aWxsIGlsbHVzdHJhdGUgdGhpcyBwcm9ibGVtIGluCnByZXR0eSBzdGFyayB0ZXJtcy4KCmBgYHtyIGNsaW5pY19iaW9wc2llc19wY2F9CmNsaW5pY19iaW9wc3kgPC0gaHNfdmFsaWQgJT4lCiAgc2V0X2V4cHRfY29uZGl0aW9ucyhmYWN0PSJjbGluaWMiKSAlPiUKICBzZXRfZXhwdF9iYXRjaGVzKGZhY3Q9ImNsaW5pY2Fsb3V0Y29tZSIpICU+JQogIHN1YnNldF9leHB0KHN1YnNldD0idHlwZW9mY2VsbHM9PSdiaW9wc3knIikKY2xpbmljX2NmIDwtIHBhc3RlMChwRGF0YShjbGluaWNfYmlvcHN5KSRjb25kaXRpb24sICJfIiwKICAgICAgICAgICAgICAgICAgICBwRGF0YShjbGluaWNfYmlvcHN5KSRiYXRjaCkKdGFibGUoY2xpbmljX2NmKQpjbGluaWNfYmlvcHN5IDwtIHNldF9leHB0X2NvbmRpdGlvbnMoY2xpbmljX2Jpb3BzeSwgZmFjdD1jbGluaWNfY2YpICU+JQogIHNldF9leHB0X2JhdGNoZXMoZmFjdD0idmlzaXRudW1iZXIiKQoKY2xpbmljX2Jpb3BzeV9ub3JtIDwtIG5vcm1hbGl6ZV9leHB0KGNsaW5pY19iaW9wc3ksIHRyYW5zZm9ybT0ibG9nMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb252ZXJ0PSJjcG0iLCBub3JtPSJxdWFudCIsIGZpbHRlcj1UUlVFKQpjbGluaWNfYmlvcHN5X3BjYSA8LSBwbG90X3BjYShjbGluaWNfYmlvcHN5X25vcm0sIHBsb3RfbGFiZWxzPUZBTFNFKQpkZXYgPC0gcHAoZmlsZT0iaW1hZ2VzL2Jpb3BzeV9wbGFjZS5wbmciKQpjbGluaWNfYmlvcHN5X3BjYSRwbG90CmNsb3NlZCA8LSBkZXYub2ZmKCkKY2xpbmljX2Jpb3BzeV9wY2EkcGxvdAoKY2xpbmljX2Jpb3BzeV9uYiA8LSBub3JtYWxpemVfZXhwdChjbGluaWNfYmlvcHN5LCB0cmFuc2Zvcm09ImxvZzIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnZlcnQ9ImNwbSIsIGJhdGNoPSJzdmFzZXEiLCBmaWx0ZXI9VFJVRSkKY2xpbmljX2Jpb3BzeV9uYl9wY2EgPC0gcGxvdF9wY2EoY2xpbmljX2Jpb3BzeV9uYiwgcGxvdF9sYWJlbHM9RkFMU0UpCmRldiA8LSBwcChmaWxlPSJpbWFnZXMvYmlvcHN5X3BsYWNlX25iLnBuZyIpCmNsaW5pY19iaW9wc3lfbmJfcGNhJHBsb3QKY2xvc2VkIDwtIGRldi5vZmYoKQpjbGluaWNfYmlvcHN5X25iX3BjYSRwbG90CmBgYAoKIyMgU3Vic2V0OiBFb3Npbm9waGlscyBieSBjbGluaWMKCkluIGNvbnRyYXN0LCB0aGUgRW9zaW5vcGhpbCBzYW1wbGVzIGRvIGhhdmUgc2lnbmlmaWNhbnQgYW1vdW50cyBvZgp2YXJpYW5jZSB3aGljaCBkaXNjcmltaW5hdGVzIHRoZSB0d28gY2xpbmljcy4gIEF0IHRoZSB0aW1lIG9mIHRoaXMKd3JpdGluZywgdGhlcmUgYXJlIGZld2VyIGVvc2lub3BoaWwgc2FtcGxlcyB0aGFuIG1vbm9jeXRlcyBub3IKbmV1dHJvcGhpbHM7IGFzIGEgcmVzdWx0IHRoZXJlIGFyZSBubyBzYW1wbGVzIHdoaWNoIGZhaWxlZCBmcm9tIENhbGkuClRoaXMgaXMgc29tZXdoYXQgbGltaXRpbmcgaXMgd2Ugd2lzaCB0byBsb29rIGZvciBkaWZmZXJlbmNlcyBiZXR3ZWVuCnRoZSBjdXJlIGFuZCBmYWlsIHNhbXBsZXMgd2hpY2ggY2FtZSBmcm9tIHRoZSB0d28gY2xpbmljcy4KCmBgYHtyIGNsaW5pY19lb3Npbm9waGlsX3BjYX0KY2xpbmljX2Vvc2lub3BoaWwgPC0gaHNfdmFsaWQgJT4lCiAgc2V0X2V4cHRfY29uZGl0aW9ucyhmYWN0PSJjbGluaWMiKSAlPiUKICBzZXRfZXhwdF9iYXRjaGVzKGZhY3Q9ImNsaW5pY2Fsb3V0Y29tZSIpICU+JQogIHN1YnNldF9leHB0KHN1YnNldD0idHlwZW9mY2VsbHM9PSdlb3Npbm9waGlscyciKQpjbGluaWNfY2YgPC0gcGFzdGUwKHBEYXRhKGNsaW5pY19lb3Npbm9waGlsKSRjb25kaXRpb24sICJfIiwKICAgICAgICAgICAgICAgICAgICBwRGF0YShjbGluaWNfZW9zaW5vcGhpbCkkYmF0Y2gpCnRhYmxlKGNsaW5pY19jZikKY2xpbmljX2Vvc2lub3BoaWwgPC0gc2V0X2V4cHRfY29uZGl0aW9ucyhjbGluaWNfZW9zaW5vcGhpbCwgZmFjdD1jbGluaWNfY2YpICU+JQogICAgc2V0X2V4cHRfYmF0Y2hlcyhmYWN0PSJ2aXNpdG51bWJlciIpCgpjbGluaWNfZW9zaW5vcGhpbF9ub3JtIDwtIG5vcm1hbGl6ZV9leHB0KGNsaW5pY19lb3Npbm9waGlsLCB0cmFuc2Zvcm09ImxvZzIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnZlcnQ9ImNwbSIsIG5vcm09InF1YW50IiwgZmlsdGVyPVRSVUUpCmNsaW5pY19lb3Npbm9waGlsX3BjYSA8LSBwbG90X3BjYShjbGluaWNfZW9zaW5vcGhpbF9ub3JtLCBwbG90X2xhYmVscz1GQUxTRSkKZGV2IDwtIHBwKGZpbGU9ImltYWdlcy9lb3Npbm9waGlsX3BsYWNlLnBuZyIpCmNsaW5pY19lb3Npbm9waGlsX3BjYSRwbG90CmNsb3NlZCA8LSBkZXYub2ZmKCkKY2xpbmljX2Vvc2lub3BoaWxfcGNhJHBsb3QKCmNsaW5pY19lb3Npbm9waGlsX25iIDwtIG5vcm1hbGl6ZV9leHB0KGNsaW5pY19lb3Npbm9waGlsLCB0cmFuc2Zvcm09ImxvZzIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb252ZXJ0PSJjcG0iLCBiYXRjaD0ic3Zhc2VxIiwgZmlsdGVyPVRSVUUpCmNsaW5pY19lb3Npbm9waGlsX25iX3BjYSA8LSBwbG90X3BjYShjbGluaWNfZW9zaW5vcGhpbF9uYiwgcGxvdF9sYWJlbHM9RkFMU0UpCmRldiA8LSBwcChmaWxlPSJpbWFnZXMvZW9zaW5vcGhpbF9wbGFjZV9uYi5wbmciKQpjbGluaWNfZW9zaW5vcGhpbF9uYl9wY2EkcGxvdApjbG9zZWQgPC0gZGV2Lm9mZigpCmNsaW5pY19lb3Npbm9waGlsX25iX3BjYSRwbG90CmBgYAoKIyMgU3Vic2V0OiBNb25vY3l0ZXMgYnkgY2xpbmljCgpJbiBjb250cmFzdCB3aXRoIHRoZSBlb3Npbm9waGlsIHNhbXBsZXMsIHdlIGhhdmUgb25lIHBhdGllbnQncwptb25vY3l0ZSBhbmQgbmV1dHJvcGhpbCBzYW1wbGVzIHdoaWNoIGRpZCBub3QgY3VyZS4gIEFzIHdlIHdpbGwgc2VlLAp0aGVyZSBpcyBvbmUgcGVyc29uIGZyb20gQ2FsaSB3aG8gZGlkIG5vdCBjdXJlLCB0aGlzIHBlcnNvbiBpcyBub3QKZGlmZmVyZW50IHdpdGggcmVzcGVjdCB0byB0cmFjc2NyaXB0b21lIHRoYW4gdGhlIG90aGVyIHBlb3BsZSBmcm9tIENhbGkuCgpgYGB7ciBjbGluaWNfbW9ub2N5dGVfcGNhfQpjbGluaWNfbW9ub2N5dGUgPC0gaHNfdmFsaWQgJT4lCiAgc2V0X2V4cHRfY29uZGl0aW9ucyhmYWN0PSJjbGluaWMiKSAlPiUKICBzZXRfZXhwdF9iYXRjaGVzKGZhY3Q9ImNsaW5pY2Fsb3V0Y29tZSIpICU+JQogIHN1YnNldF9leHB0KHN1YnNldD0idHlwZW9mY2VsbHM9PSdtb25vY3l0ZXMnIikKY2xpbmljX2NmIDwtIHBhc3RlMChwRGF0YShjbGluaWNfbW9ub2N5dGUpJGNvbmRpdGlvbiwgIl8iLAogICAgICAgICAgICAgICAgICAgIHBEYXRhKGNsaW5pY19tb25vY3l0ZSkkYmF0Y2gpCnRhYmxlKGNsaW5pY19jZikKY2xpbmljX21vbm9jeXRlIDwtIHNldF9leHB0X2NvbmRpdGlvbnMoY2xpbmljX21vbm9jeXRlLCBmYWN0PWNsaW5pY19jZikgJT4lCiAgICBzZXRfZXhwdF9iYXRjaGVzKGZhY3Q9InZpc2l0bnVtYmVyIikKCmNsaW5pY19tb25vY3l0ZV9ub3JtIDwtIG5vcm1hbGl6ZV9leHB0KGNsaW5pY19tb25vY3l0ZSwgdHJhbnNmb3JtPSJsb2cyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udmVydD0iY3BtIiwgbm9ybT0icXVhbnQiLCBmaWx0ZXI9VFJVRSkKY2xpbmljX21vbm9jeXRlX3BjYSA8LSBwbG90X3BjYShjbGluaWNfbW9ub2N5dGVfbm9ybSwgcGxvdF9sYWJlbHM9RkFMU0UpCmRldiA8LSBwcChmaWxlPSJpbWFnZXMvbW9ub2N5dGVzX3BsYWNlLnBuZyIpCmNsaW5pY19tb25vY3l0ZV9wY2EkcGxvdApjbG9zZWQgPC0gZGV2Lm9mZigpCmNsaW5pY19tb25vY3l0ZV9wY2EkcGxvdAoKY2xpbmljX21vbm9jeXRlX25iIDwtIG5vcm1hbGl6ZV9leHB0KGNsaW5pY19tb25vY3l0ZSwgdHJhbnNmb3JtPSJsb2cyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnZlcnQ9ImNwbSIsIGJhdGNoPSJzdmFzZXEiLCBmaWx0ZXI9VFJVRSkKY2xpbmljX21vbm9jeXRlX25iX3BjYSA8LSBwbG90X3BjYShjbGluaWNfbW9ub2N5dGVfbmIsIHBsb3RfbGFiZWxzPUZBTFNFKQpkZXYgPC0gcHAoZmlsZT0iaW1hZ2VzL21vbm9jeXRlc19wbGFjZV9uYi5wbmciKQpjbGluaWNfbW9ub2N5dGVfbmJfcGNhJHBsb3QKY2xvc2VkIDwtIGRldi5vZmYoKQpjbGluaWNfbW9ub2N5dGVfbmJfcGNhJHBsb3QKYGBgCgojIyBTdWJzZXQ6IE5ldXRyb3BoaWxzIGJ5IGNsaW5pYwoKRmluYWxseSwgdGhhdCBzYW1lIG9uZSBwZXJzb24gZG9lcyBhcHBlYXIgdG8gYmUgZGlmZmVyZW50IHRoYW4gdGhlCm90aGVycyBmcm9tIENhbGkuCgpgYGB7ciBjbGluaWNfbmV1dHJvcGhpbF9wY2F9CmNsaW5pY19uZXV0cm9waGlsIDwtIGhzX3ZhbGlkICU+JQogIHNldF9leHB0X2NvbmRpdGlvbnMoZmFjdD0iY2xpbmljIikgJT4lCiAgc2V0X2V4cHRfYmF0Y2hlcyhmYWN0PSJjbGluaWNhbG91dGNvbWUiKSAlPiUKICBzdWJzZXRfZXhwdChzdWJzZXQ9InR5cGVvZmNlbGxzPT0nbmV1dHJvcGhpbHMnIikKY2xpbmljX2NmIDwtIHBhc3RlMChwRGF0YShjbGluaWNfbmV1dHJvcGhpbCkkY29uZGl0aW9uLCAiXyIsCiAgICAgICAgICAgICAgICAgICAgcERhdGEoY2xpbmljX25ldXRyb3BoaWwpJGJhdGNoKQp0YWJsZShjbGluaWNfY2YpCmNsaW5pY19uZXV0cm9waGlsIDwtIHNldF9leHB0X2NvbmRpdGlvbnMoY2xpbmljX25ldXRyb3BoaWwsIGZhY3Q9Y2xpbmljX2NmKSAlPiUKICAgIHNldF9leHB0X2JhdGNoZXMoZmFjdD0idmlzaXRudW1iZXIiKQoKY2xpbmljX25ldXRyb3BoaWxfbm9ybSA8LSBub3JtYWxpemVfZXhwdChjbGluaWNfbmV1dHJvcGhpbCwgdHJhbnNmb3JtPSJsb2cyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb252ZXJ0PSJjcG0iLCBub3JtPSJxdWFudCIsIGZpbHRlcj1UUlVFKQpjbGluaWNfbmV1dHJvcGhpbF9wY2EgPC0gcGxvdF9wY2EoY2xpbmljX25ldXRyb3BoaWxfbm9ybSwgcGxvdF9sYWJlbHM9RkFMU0UpCmRldiA8LSBwcChmaWxlPSJpbWFnZXMvbmV1dHJvcGhpbF9wbGFjZS5wbmciKQpjbGluaWNfbmV1dHJvcGhpbF9wY2EkcGxvdApjbG9zZWQgPC0gZGV2Lm9mZigpCmNsaW5pY19uZXV0cm9waGlsX3BjYSRwbG90CgpjbGluaWNfbmV1dHJvcGhpbF9uYiA8LSBub3JtYWxpemVfZXhwdChjbGluaWNfbmV1dHJvcGhpbCwgdHJhbnNmb3JtPSJsb2cyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udmVydD0iY3BtIiwgYmF0Y2g9InN2YXNlcSIsIGZpbHRlcj1UUlVFKQpjbGluaWNfbmV1dHJvcGhpbF9uYl9wY2EgPC0gcGxvdF9wY2EoY2xpbmljX25ldXRyb3BoaWxfbmIsIHBsb3RfbGFiZWxzPUZBTFNFKQpkZXYgPC0gcHAoZmlsZT0iaW1hZ2VzL25ldXRyb3BoaWxfcGxhY2VfbmIucG5nIikKY2xpbmljX25ldXRyb3BoaWxfbmJfcGNhJHBsb3QKY2xvc2VkIDwtIGRldi5vZmYoKQpjbGluaWNfbmV1dHJvcGhpbF9uYl9wY2EkcGxvdApgYGAKCiMjIFBDQTogQ29tcGFyZSBjbGluaWNzCgpOb3cgdGhhdCB3ZSBoYXZlIHRoZXNlIHZhcmlvdXMgc3Vic2V0cywgcGVyZm9ybSBhbiBleHBsaWNpdCBjb21wYXJpc29uCm9mIHRoZSBzYW1wbGVzIHdoaWNoIGNhbWUgZnJvbSB0aGUgdHdvIGNsaW5pY3MuCgpgYGB7ciBjbGluaWNfY29tcGFyaXNvbjF9CmhzX2NsaW5pYyA8LSBoc192YWxpZCAlPiUKICBzZXRfZXhwdF9jb25kaXRpb25zKGZhY3Q9ImNsaW5pYyIpICU+JQogIHNldF9leHB0X2JhdGNoZXMoZmFjdD0idHlwZW9mY2VsbHMiKQoKaHNfY2xpbmljX25vcm0gPC0gbm9ybWFsaXplX2V4cHQoaHNfY2xpbmljLCB0cmFuc2Zvcm09ImxvZzIiLCBjb252ZXJ0PSJjcG0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3JtPSJxdWFudCIsIGZpbHRlcj1UUlVFKQpoc19jbGluaWNfcGNhIDwtIHBsb3RfcGNhKGhzX2NsaW5pY19ub3JtKQpoc19jbGluaWNfcGNhJHBsb3QKaHNfY2xpbmljX25iIDwtIG5vcm1hbGl6ZV9leHB0KGhzX2NsaW5pYywgdHJhbnNmb3JtPSJsb2cyIiwgY29udmVydD0iY3BtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhdGNoPSJzdmFzZXEiLCBmaWx0ZXI9VFJVRSkKaHNfY2xpbmljX25iX3BjYSA8LSBwbG90X3BjYShoc19jbGluaWNfbmIpCmhzX2NsaW5pY19uYl9wY2EkcGxvdApgYGAKCiMjIERFOiBDb21wYXJlIGNsaW5pY3MsIGFsbCBzYW1wbGVzCgpQZXJmb3JtIGEgc3Zhc2VxLWd1aWRlZCBjb21wYXJpc29uIG9mIHRoZSB0d28gY2xpbmljcy4gIElkZWFsbHkgdGhpcwp3aWxsIGdpdmUgc29tZSBjbHVlIGFib3V0IGp1c3QgaG93IHN0cm9uZyB0aGUgY2xpbmljLWJhc2VkIGJhdGNoCmVmZmVjdCByZWFsbHkgaXMgYW5kIHdoYXQgaXRzIGNhdXNlcyBhcmUuCgpgYGB7ciBjbGluaWNfY29tcGFyaXNvbnNfYWxsfQpjbGluaWNfY29udHJhc3RzIDwtIGxpc3QoCiAgICAiY2xpbmljcyIgPSBjKCJDYWxpIiwgIlR1bWFjbyIpKQpoc19jbGluaWNfZGUgPC0gYWxsX3BhaXJ3aXNlKGhzX2NsaW5pYywgbW9kZWxfYmF0Y2g9InN2YXNlcSIsIGZpbHRlcj1UUlVFKQpoc19jbGluaWNfdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgICBoc19jbGluaWNfZGUsIGtlZXBlcnM9Y2xpbmljX2NvbnRyYXN0cywKICAgIGV4Y2VsPWdsdWU6OmdsdWUoImV4Y2VsL2hzX2NsaW5pY190YWJsZS12e3Zlcn0ueGxzeCIpKQpoc19jbGluaWNfc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgICBoc19jbGluaWNfdGFibGUsCiAgICBleGNlbD1nbHVlOjpnbHVlKCJleGNlbC9oc19jbGluaWNfc2lnLXZ7dmVyfS54bHN4IikpCmBgYAoKIyMgREU6IENvbXBhcmUgY2xpbmljcywgYmlvcHN5IHNhbXBsZXMKCkludGVyZXN0aW5nbHkgdG8gbWUsIHRoZSBiaW9wc3kgc2FtcGxlcyBhcHBlYXIgdG8gaGF2ZSB0aGUgbGVhc3QKbG9jYXRpb24tYmFzZWQgdmFyaWFuY2UuICBCdXQgd2UgY2FuIHBlcmZvcm0gYW4gZXhwbGljaXQgREUgYW5kIHNlZQpob3cgd2VsbCB0aGF0IGh5cG90aGVzaXMgaG9sZHMgdXAuCgpgYGB7ciBjbGluaWNfYmlvcHN5X2RlfQpjbGluaWNfYmlvcHN5X2RlIDwtIGFsbF9wYWlyd2lzZShjbGluaWNfYmlvcHN5LCBtb2RlbF9iYXRjaD0ic3Zhc2VxIiwgZmlsdGVyPVRSVUUpCmNsaW5pY19iaW9wc3lfdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgICBjbGluaWNfYmlvcHN5X2RlLAogICAgZXhjZWw9Z2x1ZTo6Z2x1ZSgiZXhjZWwvY2xpbmljX2Jpb3BzeV90YWJsZS12e3Zlcn0ueGxzeCIpKQpjbGluaWNfYmlvcHN5X3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogICAgY2xpbmljX2Jpb3BzeV90YWJsZSwKICAgIGV4Y2VsPWdsdWU6OmdsdWUoImV4Y2VsL2NsaW5pY19iaW9wc3lfc2lnLXZ7dmVyfS54bHN4IikpCmBgYAoKIyMgREU6IENvbXBhcmUgY2xpbmljcywgZW9zaW5vcGhpbCBzYW1wbGVzCgpUaGUgcmVtYWluaW5nIGNlbGwgdHlwZXMgYWxsIGhhdmUgcHJldHR5IHN0cm9uZyBjbGluaWMtYmFzZWQgdmFyaWFuY2U7CmJ1dCBJIGFtIG5vdCBjZXJ0YWluIGlmIGl0IGlzIGNvbnNpc3RlbnQgYWNyb3NzIGNlbGwgdHlwZXMuCgpgYGB7ciBjbGluaWNfZW9zaW5vcGhpbF9kZX0KY2xpbmljX2Vvc2lub3BoaWxfZGUgPC0gYWxsX3BhaXJ3aXNlKGNsaW5pY19lb3Npbm9waGlsLCBtb2RlbF9iYXRjaD1GQUxTRSwgZmlsdGVyPVRSVUUpCmNsaW5pY19lb3Npbm9waGlsX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogICAgY2xpbmljX2Vvc2lub3BoaWxfZGUsCiAgICBleGNlbD1nbHVlOjpnbHVlKCJleGNlbC9jbGluaWNfZW9zaW5vcGhpbF90YWJsZS12e3Zlcn0ueGxzeCIpKQpjbGluaWNfZW9zaW5vcGhpbF9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICAgIGNsaW5pY19lb3Npbm9waGlsX3RhYmxlLAogICAgZXhjZWw9Z2x1ZTo6Z2x1ZSgiZXhjZWwvY2xpbmljX2Vvc2lub3BoaWxfc2lnLXZ7dmVyfS54bHN4IikpCmBgYAoKIyMgREU6IENvbXBhcmUgY2xpbmljcywgbW9ub2N5dGUgc2FtcGxlcwoKQXQgbGVhc3QgZm9yIHRoZSBtb21lbnQsIEkgYW0gb25seSBsb29raW5nIGF0IHRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVuCm5vLWJhdGNoIHZzLiBzdmEgYWNyb3NzIGNsaW5pY3MgZm9yIHRoZSBtb25vY3l0ZSBzYW1wbGVzLiAgVGhpcwp3YXMgY2hvc2VuIG1vc3RseSBhcmJpdHJhcmlseS4KCiMjIyBERTogQ29tcGFyZSBjbGluaWNzLCBtb25vY3l0ZXMgd2l0aCBiYXRjaCBlc3RpbWF0aW9uCgpPdXIgYmFzZWxpbmUgaXMgdGhlIGNvbXBhcmlzb24gb2YgdGhlIG1vbm9jeXRlcyBzYW1wbGVzIHdpdGhvdXQgYmF0Y2gKaW4gdGhlIG1vZGVsIG9yIHN1cnJvZ2F0ZSBlc3RpbWF0aW9uLiAgSW4gdGhlb3J5IGF0IGxlYXN0LCB0aGlzIHNob3VsZApjb3JyZXNwb25kIHRvIHRoZSBQQ0EgcGxvdCBhYm92ZSB3aGVuIG5vIGJhdGNoIGVzdGltYXRpb24gd2FzIHBlcmZvcm1lZC4KCmBgYHtyIGNsaW5pY19tb25vY3l0ZV9kZX0KY2xpbmljX21vbm9jeXRlX2RlIDwtIGFsbF9wYWlyd2lzZShjbGluaWNfbW9ub2N5dGUsIG1vZGVsX2JhdGNoPUZBTFNFLCBmaWx0ZXI9VFJVRSkKY2xpbmljX21vbm9jeXRlX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogICAgY2xpbmljX21vbm9jeXRlX2RlLAogICAgZXhjZWw9Z2x1ZTo6Z2x1ZSgiZXhjZWwvY2xpbmljX21vbm9jeXRlX3RhYmxlLXZ7dmVyfS54bHN4IikpCmNsaW5pY19tb25vY3l0ZV9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICAgIGNsaW5pY19tb25vY3l0ZV90YWJsZSwKICAgIGV4Y2VsPWdsdWU6OmdsdWUoImV4Y2VsL2NsaW5pY19tb25vY3l0ZV9zaWctdnt2ZXJ9Lnhsc3giKSkKYGBgCgojIyMgREU6IENvbXBhcmUgY2xpbmljcywgbW9ub2N5dGVzIHdpdGggc3Zhc2VxCgpJbiBjb250cmFzdCwgdGhlIGZvbGxvd2luZyBjb21wYXJpc29uIHNob3VsZCBnaXZlIGEgdmlldyBvZiB0aGUgZGF0YQpjb3JyZXNwb25kaW5nIHRvIHRoZSBzdmFzZXEgUENBIHBsb3QgYWJvdmUuICBJbiB0aGUgYmVzdCBjYXNlCnNjZW5hcmlvLCB3ZSBzaG91bGQgdGhlcmVmb3JlIGJlIGFibGUgdG8gc2VlIHNvbWUgc2lnbmlmaWNhbmUKZGlmZmVyZW5jZXMgYmV0d2VlbiB0aGUgVHVtYWNvIGN1cmUgYW5kIGZhaWwgc2FtcGxlcy4KCmBgYHtyIGNsaW5pY19tb25vY3l0ZV9kZV9zdmF9CmNsaW5pY19tb25vY3l0ZV9zdmFfZGUgPC0gYWxsX3BhaXJ3aXNlKGNsaW5pY19tb25vY3l0ZSwgbW9kZWxfYmF0Y2g9InN2YXNlcSIsIGZpbHRlcj1UUlVFKQpjbGluaWNfbW9ub2N5dGVfc3ZhX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogICAgY2xpbmljX21vbm9jeXRlX3N2YV9kZSwKICAgIGV4Y2VsPWdsdWU6OmdsdWUoImV4Y2VsL2NsaW5pY19tb25vY3l0ZV90YWJsZV9zdmEtdnt2ZXJ9Lnhsc3giKSkKY2xpbmljX21vbm9jeXRlX3N2YV9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICAgIGNsaW5pY19tb25vY3l0ZV9zdmFfdGFibGUsCiAgICBleGNlbD1nbHVlOjpnbHVlKCJleGNlbC9jbGluaWNfbW9ub2N5dGVfc2lnX3N2YS12e3Zlcn0ueGxzeCIpKQpgYGAKCiMjIyBERSBDb21wYXJlOiBIb3cgc2ltaWxhciBhcmUgdGhlIG5vLWJhdGNoIHZzLiBTVkEgcmVzdWx0cz8KClRoZSBmb2xsb3dpbmcgYmxvY2sgc2hvd3MgdGhhdCB0aGVzZSB0d28gcmVzdWx0cyBhcmUgZXhjZWVkaW5nbHkKZGlmZmVyZW50LCBzdWdlc3RpbmcgdGhhdCB0aGUgQ2FsaSBjdXJlL2ZhaWwgYW5kIFR1bWFjbyBjdXJlL2ZhaWwKY2Fubm90IGVhc2lseSBiZSBjb25zaWRlcmVkIGluIHRoZSBzYW1lIGFuYWx5c2lzLiAgSSBkaWQgc29tZSBwbGF5aW5nCmFyb3VuZCB3aXRoIG15IGNhbGN1bGF0ZV9hdWNjIGZ1bmN0aW9uIGluIHRoaXMgYmxvY2sgYW5kIGZvdW5kIHRoYXQgaXQKaXMgaW4gc29tZSBpbXBvcnRhbnQgd2F5IGJyb2tlbiwgYXQgbGVhc3QgaWYgb25lIGV4cGFuZHMgdGhlIHRvcC1uCmdlbmVzIHRvIG1vcmUgdGhhbiAyMCUgb2YgdGhlIG51bWJlciBvZiBnZW5lcyBpbiB0aGUgZGF0YS4KCmBgYHtyIHZzX2NhbGlfbW9ub2N5dGV9CmNhbGlfdGFibGUgPC0gY2xpbmljX21vbm9jeXRlX3RhYmxlW1siZGF0YSJdXVtbIkNhbGlmYWlsdXJlX3ZzX0NhbGljdXJlIl1dCnRhYmxlIDwtIGNsaW5pY19tb25vY3l0ZV90YWJsZVtbImRhdGEiXV1bWyJUdW1hY29mYWlsdXJlX3ZzX1R1bWFjb2N1cmUiXV0KCmNhbGlfbWVyZ2VkIDwtIG1lcmdlKGNhbGlfdGFibGUsIHRhYmxlLCBieT0icm93Lm5hbWVzIikKY29yLnRlc3QoY2FsaV9tZXJnZWRbLCAiZGVzZXFfbG9nZmMueCJdLCBjYWxpX21lcmdlZFssICJkZXNlcV9sb2dmYy55Il0pCmNhbGlfYXVjYyA8LSBjYWxjdWxhdGVfYXVjYyhjYWxpX3RhYmxlLCB0YWJsZSwgcHg9ImRlc2VxX2FkanAiLCBweT0iZGVzZXFfYWRqcCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbHg9ImRlc2VxX2xvZ2ZjIiwgbHk9ImRlc2VxX2xvZ2ZjIikKY2FsaV9hdWNjJHBsb3QKCmNhbGlfc3ZhX3RhYmxlIDwtIGNsaW5pY19tb25vY3l0ZV9zdmFfdGFibGVbWyJkYXRhIl1dW1siQ2FsaWZhaWx1cmVfdnNfQ2FsaWN1cmUiXV0Kc3ZhX3RhYmxlIDwtIGNsaW5pY19tb25vY3l0ZV9zdmFfdGFibGVbWyJkYXRhIl1dW1siVHVtYWNvZmFpbHVyZV92c19UdW1hY29jdXJlIl1dCgpjYWxpX3N2YV9tZXJnZWQgPC0gbWVyZ2UoY2FsaV9zdmFfdGFibGUsIHN2YV90YWJsZSwgYnk9InJvdy5uYW1lcyIpCmNvci50ZXN0KGNhbGlfc3ZhX21lcmdlZFssICJkZXNlcV9sb2dmYy54Il0sIGNhbGlfc3ZhX21lcmdlZFssICJkZXNlcV9sb2dmYy55Il0pCmNhbGlfc3ZhX2F1Y2MgPC0gY2FsY3VsYXRlX2F1Y2MoY2FsaV9zdmFfdGFibGUsIHN2YV90YWJsZSwgcHg9ImRlc2VxX2FkanAiLCBweT0iZGVzZXFfYWRqcCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbHg9ImRlc2VxX2xvZ2ZjIiwgbHk9ImRlc2VxX2xvZ2ZjIikKY2FsaV9zdmFfYXVjYyRwbG90CmBgYAoKIyMgREU6IENvbXBhcmUgY2xpbmljcywgbmV1dHJvcGhpbCBzYW1wbGVzCgpgYGB7ciBjbGluaWNfbmV1dHJvcGhpbF9kZX0KY2xpbmljX25ldXRyb3BoaWxfZGUgPC0gYWxsX3BhaXJ3aXNlKGNsaW5pY19uZXV0cm9waGlsLCBtb2RlbF9iYXRjaD1GQUxTRSwgZmlsdGVyPVRSVUUpCmNsaW5pY19uZXV0cm9waGlsX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogICAgY2xpbmljX25ldXRyb3BoaWxfZGUsCiAgICBleGNlbD1nbHVlOjpnbHVlKCJleGNlbC9jbGluaWNfbmV1dHJvcGhpbF90YWJsZS12e3Zlcn0ueGxzeCIpKQpjbGluaWNfbmV1dHJvcGhpbF9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICAgIGNsaW5pY19uZXV0cm9waGlsX3RhYmxlLAogICAgZXhjZWw9Z2x1ZTo6Z2x1ZSgiZXhjZWwvY2xpbmljX25ldXRyb3BoaWxfc2lnLXZ7dmVyfS54bHN4IikpCmBgYAoKIyBDb21wYXJlIERFOiBIb3cgc2ltaWxhciBhcmUgVHVtYWNvIEMvRiB2cy4gQ2FsaSBDL0YKClRoZSBmb2xsb3dpbmcgZXhwYW5kcyB0aGUgY3Jvc3MtY2xpbmljIHF1ZXJ5IGFib3ZlIHRvIGFsc28gdGVzdCB0aGUKbmV1dHJvcGhpbHMuICBPbmNlIGFnYWluLCBJIHRoaW5rIGl0IHdpbGwgcHJldHR5IHN0cm9uZ2x5IHN1cHBvcnQgdGhlCmh5cG90aGVzaXMgdGhhdCB0aGUgdHdvIGNsaW5pY3MgYXJlIG5vdCBjb21wYXRpYmxlLgoKV2UgYXJlIGNvbmNlcm5lZCB0aGF0IHRoZSBjbGluaWMtYmFzZWQgYmF0Y2ggZWZmZWN0IG1heSBtYWtlIG91cgpyZXN1bHRzIGVzc2VudGlhbGx5IHVzZWxlc3MuICBPbmUgd2F5IHRvIHRlc3QgdGhpcyBjb25jZXJuIGlzIHRvCmNvbXBhcmUgdGhlIHNldCBvZiBnZW5lcyBvYnNlcnZlZCBkaWZmZXJlbnQgYmV0d2VlbiB0aGUgQ2FsaSBDdXJlL0ZhaWwKdnMuIHRoZSBUdW1hY28gQ3VyZS9GYWlsLgoKYGBge3IgdnNfY2FsaV9uZXV0cm9waGlsc30KY2FsaV90YWJsZSA8LSBjbGluaWNfbmV1dHJvcGhpbF90YWJsZVtbImRhdGEiXV1bWyJDYWxpZmFpbHVyZV92c19DYWxpY3VyZSJdXQp0YWJsZSA8LSBjbGluaWNfbmV1dHJvcGhpbF90YWJsZVtbImRhdGEiXV1bWyJUdW1hY29mYWlsdXJlX3ZzX1R1bWFjb2N1cmUiXV0KCmNhbGlfbWVyZ2VkIDwtIG1lcmdlKGNhbGlfdGFibGUsIHRhYmxlLCBieT0icm93Lm5hbWVzIikKY29yLnRlc3QoY2FsaV9tZXJnZWRbLCAiZGVzZXFfbG9nZmMueCJdLCBjYWxpX21lcmdlZFssICJkZXNlcV9sb2dmYy55Il0pCmNhbGlfYXVjYyA8LSBjYWxjdWxhdGVfYXVjYyhjYWxpX3RhYmxlLCB0YWJsZSwgcHg9ImRlc2VxX2FkanAiLCBweT0iZGVzZXFfYWRqcCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbHg9ImRlc2VxX2xvZ2ZjIiwgbHk9ImRlc2VxX2xvZ2ZjIikKY2FsaV9hdWNjJHBsb3QKYGBgCgojIyBHU0VBOiBFeHRyYWN0IGNsaW5pYy1zcGVjaWZpYyBnZW5lcwoKR2l2ZW4gdGhlIGFib3ZlIGNvbXBhcmlzb25zLCB3ZSBjYW4gZXh0cmFjdCBzb21lIGdlbmUgc2V0cyB3aGljaApyZXN1bHRlZCBmcm9tIHRob3NlIERFIGFuYWx5c2VzIGFuZCBldmVudHVhbGx5IHBlcmZvcm0gc29tZQpvbnRvbG9neS9LRUdHL3JlYWN0b21lL2V0YyBzZWFyY2hlcy4gIFRoaXMgcmVtaW5kcyBtZSwgSSB3YW50IHRvIG1ha2UKbXkgZXh0cmFjdF9zaWduaWZpY2FudF8gZnVuY3Rpb25zIHRvIHJldHVybiBnZW5lLXNldCBkYXRhIHN0cnVjdHVyZXMKYW5kIG15IHZhcmlvdXMgb250b2xvZ3kgc2VhcmNoZXMgdG8gdGFrZSB0aGVtIGFzIGlucHV0cy4gIFRoaXMgc2hvdWxkCmhlbHAgYXZvaWQgcG90ZW50aWFsIGVycm9ycyB3aGVuIGV4dHJhY3RpbmcgdXAvZG93biBnZW5lcy4KCmBgYHtyIGNvbXBhcmVfY2xpbmljX2dlbmVzfQpjbGluaWNfc2lnZW5lc191cCA8LSByb3duYW1lcyhoc19jbGluaWNfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWzFdXSkKY2xpbmljX3NpZ2VuZXNfZG93biA8LSByb3duYW1lcyhoc19jbGluaWNfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbMV1dKQpjbGluaWNfc2lnZW5lcyA8LSBjKGNsaW5pY19zaWdlbmVzX3VwLCBjbGluaWNfc2lnZW5lc19kb3duKQoKY29udHJhc3QgPC0gIlR1bWFjb2N1cmVfdnNfQ2FsaWN1cmUiCmNsaW5pY19iaW9wc3lfc2lnZW5lcyA8LSBjKHJvd25hbWVzKGNsaW5pY19iaW9wc3lfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bW2NvbnRyYXN0XV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICByb3duYW1lcyhjbGluaWNfYmlvcHN5X3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV1bW2NvbnRyYXN0XV0pKQpjbGluaWNfZW9zaW5vcGhpbF9zaWdlbmVzX3VwIDwtIHJvd25hbWVzKGNsaW5pY19lb3Npbm9waGlsX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1tjb250cmFzdF1dKQpjbGluaWNfZW9zaW5vcGhpbF9zaWdlbmVzX2Rvd24gPC0gcm93bmFtZXMoY2xpbmljX2Vvc2lub3BoaWxfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbY29udHJhc3RdXSkKY2xpbmljX21vbm9jeXRlX3NpZ2VuZXNfdXAgPC0gcm93bmFtZXMoY2xpbmljX21vbm9jeXRlX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1tjb250cmFzdF1dKQpjbGluaWNfbW9ub2N5dGVfc2lnZW5lc19kb3duIDwtIHJvd25hbWVzKGNsaW5pY19tb25vY3l0ZV9zaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dW1tjb250cmFzdF1dKQpjbGluaWNfbmV1dHJvcGhpbF9zaWdlbmVzX3VwIDwtIHJvd25hbWVzKGNsaW5pY19uZXV0cm9waGlsX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1tjb250cmFzdF1dKQpjbGluaWNfbmV1dHJvcGhpbF9zaWdlbmVzX2Rvd24gPC0gcm93bmFtZXMoY2xpbmljX25ldXRyb3BoaWxfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbY29udHJhc3RdXSkKCmNsaW5pY19lb3Npbm9waGlsX3NpZ2VuZXMgPC0gYyhjbGluaWNfZW9zaW5vcGhpbF9zaWdlbmVzX3VwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xpbmljX2Vvc2lub3BoaWxfc2lnZW5lc19kb3duKQpjbGluaWNfbW9ub2N5dGVfc2lnZW5lcyA8LSBjKGNsaW5pY19tb25vY3l0ZV9zaWdlbmVzX3VwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsaW5pY19tb25vY3l0ZV9zaWdlbmVzX2Rvd24pCmNsaW5pY19uZXV0cm9waGlsX3NpZ2VuZXMgPC0gYyhjbGluaWNfbmV1dHJvcGhpbF9zaWdlbmVzX3VwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xpbmljX25ldXRyb3BoaWxfc2lnZW5lc19kb3duKQpgYGAKCiMjIEdTRUE6IGdQcm9maWxlciBvZiBnZW5lcyBkZWVtZWQgdXAvZG93biB3aGVuIGNvbXBhcmluZyBDYWxpIGFuZCBUdW1hY28KCkkgd2FzIGN1cmlvdXMgdG8gdHJ5IHRvIHVuZGVyc3RhbmQgd2h5IHRoZSB0d28gY2xpbmljcyBhcHBlYXIgdG8gYmUgc28KZGlmZmVyZW50IHZpcyBhIHZpcyB0aGVpciBQQ0EvREU7IHNvIEkgdGhvdWdodCB0aGF0IGdQcm9maWxlciBtaWdodApoZWxwIGJvaWwgdGhvc2UgcmVzdWx0cyBkb3duIHRvIHNvbWV0aGluZyBtb3JlIGRpZ2VzdGlibGUuCgpgYGB7ciBjbGluaWNfZ3Byb2ZpbGVyfQpjbGluaWNfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihjbGluaWNfc2lnZW5lcykKY2xpbmljX2dwJHB2YWx1ZV9wbG90cyRrZWdnX3Bsb3Rfb3ZlcgpjbGluaWNfZ3AkcHZhbHVlX3Bsb3RzJHJlYWN0b21lX3Bsb3Rfb3ZlcgpjbGluaWNfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihjbGluaWNfc2lnZW5lcykKY2xpbmljX2dwJHB2YWx1ZV9wbG90cyRrZWdnX3Bsb3Rfb3ZlcgpjbGluaWNfZ3AkcHZhbHVlX3Bsb3RzJHJlYWN0b21lX3Bsb3Rfb3ZlcgpjbGluaWNfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihjbGluaWNfc2lnZW5lcykKY2xpbmljX2dwJHB2YWx1ZV9wbG90cyRrZWdnX3Bsb3Rfb3ZlcgpjbGluaWNfZ3AkcHZhbHVlX3Bsb3RzJHJlYWN0b21lX3Bsb3Rfb3ZlcgoKCmNsaW5pY19lb3Npbm9waGlsX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIoY2xpbmljX2Vvc2lub3BoaWxfc2lnZW5lcykKY2xpbmljX2Vvc2lub3BoaWxfZ3AkcHZhbHVlX3Bsb3RzJGtlZ2dfcGxvdF9vdmVyCmNsaW5pY19lb3Npbm9waGlsX2dwJHB2YWx1ZV9wbG90cyRyZWFjdG9tZV9wbG90X292ZXIKCmNsaW5pY19lb3Npbm9waGlsX3VwX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIoY2xpbmljX2Vvc2lub3BoaWxfc2lnZW5lc191cCkKY2xpbmljX2Vvc2lub3BoaWxfdXBfZ3AkcHZhbHVlX3Bsb3RzJGtlZ2dfcGxvdF9vdmVyCmNsaW5pY19lb3Npbm9waGlsX3VwX2dwJHB2YWx1ZV9wbG90cyRyZWFjdG9tZV9wbG90X292ZXIKCmNsaW5pY19lb3Npbm9waGlsX2Rvd25fZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihjbGluaWNfZW9zaW5vcGhpbF9zaWdlbmVzX2Rvd24pCmNsaW5pY19lb3Npbm9waGlsX2Rvd25fZ3AkcHZhbHVlX3Bsb3RzJGtlZ2dfcGxvdF9vdmVyCmNsaW5pY19lb3Npbm9waGlsX2Rvd25fZ3AkcHZhbHVlX3Bsb3RzJHJlYWN0b21lX3Bsb3Rfb3ZlcgoKCmNsaW5pY19tb25vY3l0ZV9ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKGNsaW5pY19tb25vY3l0ZV9zaWdlbmVzKQpjbGluaWNfbW9ub2N5dGVfZ3AkcHZhbHVlX3Bsb3RzJGtlZ2dfcGxvdF9vdmVyCmNsaW5pY19tb25vY3l0ZV9ncCRwdmFsdWVfcGxvdHMkcmVhY3RvbWVfcGxvdF9vdmVyCgpjbGluaWNfbW9ub2N5dGVfdXBfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihjbGluaWNfbW9ub2N5dGVfc2lnZW5lc191cCkKY2xpbmljX21vbm9jeXRlX3VwX2dwJHB2YWx1ZV9wbG90cyRrZWdnX3Bsb3Rfb3ZlcgpjbGluaWNfbW9ub2N5dGVfdXBfZ3AkcHZhbHVlX3Bsb3RzJHJlYWN0b21lX3Bsb3Rfb3ZlcgoKY2xpbmljX21vbm9jeXRlX2Rvd25fZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihjbGluaWNfbW9ub2N5dGVfc2lnZW5lc19kb3duKQpjbGluaWNfbW9ub2N5dGVfZG93bl9ncCRwdmFsdWVfcGxvdHMka2VnZ19wbG90X292ZXIKY2xpbmljX21vbm9jeXRlX2Rvd25fZ3AkcHZhbHVlX3Bsb3RzJHJlYWN0b21lX3Bsb3Rfb3ZlcgoKCmNsaW5pY19uZXV0cm9waGlsX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIoY2xpbmljX25ldXRyb3BoaWxfc2lnZW5lcykKY2xpbmljX25ldXRyb3BoaWxfZ3AkcHZhbHVlX3Bsb3RzJGtlZ2dfcGxvdF9vdmVyCmNsaW5pY19uZXV0cm9waGlsX2dwJHB2YWx1ZV9wbG90cyRyZWFjdG9tZV9wbG90X292ZXIKCmNsaW5pY19uZXV0cm9waGlsX3VwX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIoY2xpbmljX25ldXRyb3BoaWxfc2lnZW5lc191cCkKY2xpbmljX25ldXRyb3BoaWxfdXBfZ3AkcHZhbHVlX3Bsb3RzJGtlZ2dfcGxvdF9vdmVyCmNsaW5pY19uZXV0cm9waGlsX3VwX2dwJHB2YWx1ZV9wbG90cyRyZWFjdG9tZV9wbG90X292ZXIKCmNsaW5pY19uZXV0cm9waGlsX2Rvd25fZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihjbGluaWNfbmV1dHJvcGhpbF9zaWdlbmVzX2Rvd24pCmNsaW5pY19uZXV0cm9waGlsX2Rvd25fZ3AkcHZhbHVlX3Bsb3RzJGtlZ2dfcGxvdF9vdmVyCmNsaW5pY19uZXV0cm9waGlsX2Rvd25fZ3AkcHZhbHVlX3Bsb3RzJHJlYWN0b21lX3Bsb3Rfb3ZlcgpgYGAKCiMgVmlzdWFsaXplOiBQbG90IHRoZSBjbGluaWNhbCBzYW1wbGVzIGJ5IGN1cmUvZmFpbAoKTGV0IHVzIHJlY29sb3IgdGhlIHNhbWUgcGxvdCBieSBjdXJlL2ZhaWwgZm9sbG93ZWQgYnkgYSBjb25jYXRlbmF0aW9uCm9mIHRoZSBjZWxsIHR5cGUgYW5kIGN1cmUvZmFpbC4gIEluIHRoZSBmb2xsb3dpbmcgYmxvY2ssIHRoZSBjbGluaWNhbApzYW1wbGVzIGFyZSBwbG90dGVkIG9uY2Ugd2l0aCB0aGUgbW9zdCBjb21tb24gbm9ybWFsaXphdGlvbgoobG9nLGNwbSxxdWFudCxmaWx0ZXJlZCkgbWV0aG9kIGZvbGxvd2VkIGJ5IGEgcGxvdCBvZiB0aGUgZGF0YSB1c2luZwpzdmFzZXEgYWRqdXN0ZWQgdmFsdWVzIGFuZCB3aXRob3V0IHF1YW50aWxlIG5vcm1hbGl6YXRpb24uCgpUaHVzLCB0aGUgZm9sbG93aW5nIGJsb2NrIHN3aXRjaGVzIHRoZSBjb2xvcnMgb2YgdGhlIGdyb3VwcyB0byB0aGUgY2xpbmljYWwKc3RhdGUgKGN1cmUvZmFpbCkgYW5kIHNoYXBlcyBieSBjZWxsIHR5cGUuCgpgYGB7ciBoc19jbGluaWNhbF9wbG90fQpoc19jbGluaWNhbF9ub3JtIDwtIHNtKG5vcm1hbGl6ZV9leHB0KGhzX2NsaW5pY2FsLCBmaWx0ZXI9InNpbXBsZSIsIHRyYW5zZm9ybT0ibG9nMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9ybT0icXVhbnQiLCBjb252ZXJ0PSJjcG0iKSkKY2xpbmljYWxfcGNhIDwtIHBsb3RfcGNhKGhzX2NsaW5pY2FsX25vcm0sIHBsb3RfbGFiZWxzPUZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgY2lzPU5VTEwsCiAgICAgICAgICAgICAgICAgICAgICAgICBwbG90X3RpdGxlPSJQQ0EgLSBjbGluaWNhbCBzYW1wbGVzIikKZGV2IDwtIHBwKGZpbGU9Z2x1ZSgiaW1hZ2VzL2FsbF9jbGluaWNhbF9ub2JhdGNoX3BjYS12e3Zlcn0ucG5nIiksIGhlaWdodD04LCB3aWR0aD0xNikKY2xpbmljYWxfcGNhJHBsb3QKY2xvc2VkIDwtIGRldi5vZmYoKQpjbGluaWNhbF9wY2EkcGxvdAoKaHNfY2xpbmljYWxfbmIgPC0gbm9ybWFsaXplX2V4cHQoaHNfY2xpbmljYWwsIGZpbHRlcj0ic2ltcGxlIiwgdHJhbnNmb3JtPSJsb2cyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmF0Y2g9InN2YXNlcSIsIGNvbnZlcnQ9ImNwbSIpCmhzX2NsaW5pY2FsX25iX3BjYSA8LSBwbG90X3BjYShoc19jbGluaWNhbF9uYikKZGV2IDwtIHBwKGZpbGU9Z2x1ZSgiaW1hZ2VzL2FsbF9jbGluaWNhbF9zdmFzZXFiYXRjaF9wY2Etdnt2ZXJ9LnBuZyIpLCBoZWlnaHQ9Niwgd2lkdGg9OCkKaHNfY2xpbmljYWxfbmJfcGNhJHBsb3QKY2xvc2VkIDwtIGRldi5vZmYoKQpoc19jbGluaWNhbF9uYl9wY2EkcGxvdAoKY2xpbmljYWxfcGNhX2luZm8gPC0gcGNhX2luZm9ybWF0aW9uKAogICAgaHNfY2xpbmljYWxfbm9ybSwgcGxvdF9wY2FzPVRSVUUsIG51bV9jb21wb25lbnRzID0gMzAsCiAgICBleHB0X2ZhY3RvcnM9YygidmlzaXRudW1iZXIiLCAidHlwZW9mY2VsbHMiLCAiY2xpbmljYWxvdXRjb21lIiwKICAgICAgICAgICAgICAgICAgICJjbGluaWMiLCAiZG9ub3IiKSkKZGV2IDwtIHBwKGZpbGU9ImltYWdlcy9jbGluaWNhbF9zYW1wbGVzX25lZ2xvZ3BfcGNzLnBuZyIpCmNsaW5pY2FsX3BjYV9pbmZvJGFub3ZhX25lZ2xvZ3BfaGVhdG1hcApjbG9zZWQgPC0gZGV2Lm9mZigpCmNsaW5pY2FsX3BjYV9pbmZvJGFub3ZhX25lZ2xvZ3BfaGVhdG1hcApjbGluaWNhbF9wY2FfaW5mbyRwY2FfcGxvdHMkUEMyMF9QQzI5CgpjbGluaWNhbF9zY29yZXMgPC0gcGNhX2hpZ2hzY29yZXMoaHNfY2xpbmljYWxfbm9ybSkKY2xpbmljYWxfc2NvcmVzW1siaGlnaGVzdCJdXVssIkNvbXAuMjAiXQpjbGluaWNhbF9zY29yZXNbWyJoaWdoZXN0Il1dWywiQ29tcC4yNyJdCmBgYAoKIyMgSXRlcmF0aXZlIFNWQSBmb2xsb3dlZCBieSBQQ0EKCkFub3RoZXIgd2F5IHRvIGV4cGxvcmUgdGhlIGVmZmVjdCBvZiBTVkEgaXMgdG8gaXRlcmF0aXZlbHkgaW5jcmVhc2UKdGhlIG51bWJlciBvZiBTVnMgcmVtb3ZlZCBieSBpdCBhbmQgbG9vayBhdCBzb21lIHNpbXBsZSBwbG90cyBvZiB0aGUKcmVzdWx0aW5nIGRhdGEuICBJZGVhbGx5LCB0aGlzIHNob3VsZCBjb21wbGVtZW50IHRoZSBtZXRob2RzIGVtcGxveWVkCmJ5IFRoZXJlc2EuCgpgYGB7ciBpdGVyYXRpdmVfc3ZfcmVtb3ZhbH0KZmlyc3QgPC0gbm9ybWFsaXplX2V4cHQoaHNfY2xpbmljYWwsIHRyYW5zZm9ybT0ibG9nMiIsIGNvbnZlcnQ9ImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlciA9IFRSVUUsIGJhdGNoPSJzdmFzZXEiLCBzdXJyb2dhdGVzPTEpCmZpcnN0X2luZm8gPC0gcGNhX2luZm9ybWF0aW9uKAogICAgZmlyc3QsIHBsb3RfcGNhcz1UUlVFLCBudW1fY29tcG9uZW50cyA9IDMwLAogICAgZXhwdF9mYWN0b3JzPWMoInZpc2l0bnVtYmVyIiwgInR5cGVvZmNlbGxzIiwgImNsaW5pY2Fsb3V0Y29tZSIsCiAgICAgICAgICAgICAgICAgICAiY2xpbmljIikpCmZpcnN0X2luZm8kYW5vdmFfbmVnbG9ncF9oZWF0bWFwCmZpcnN0X2luZm8kcGNhX3Bsb3RzW1siUEMxX1BDMiJdXQoKc2Vjb25kIDwtIG5vcm1hbGl6ZV9leHB0KGhzX2NsaW5pY2FsLCB0cmFuc2Zvcm09ImxvZzIiLCBjb252ZXJ0PSJjcG0iLAogICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyID0gVFJVRSwgYmF0Y2g9InN2YXNlcSIsIHN1cnJvZ2F0ZXM9MikgJT4lCiAgc2V0X2V4cHRfYmF0Y2hlcyhmYWN0PSJjbGluaWMiKQpzZWNvbmRfaW5mbyA8LSBwY2FfaW5mb3JtYXRpb24oCiAgICBzZWNvbmQsIHBsb3RfcGNhcz1UUlVFLCBudW1fY29tcG9uZW50cyA9IDMwLAogICAgZXhwdF9mYWN0b3JzPWMoInZpc2l0bnVtYmVyIiwgInR5cGVvZmNlbGxzIiwgImNsaW5pY2Fsb3V0Y29tZSIsCiAgICAgICAgICAgICAgICAgICAiY2xpbmljIikpCnNlY29uZF9pbmZvJGFub3ZhX25lZ2xvZ3BfaGVhdG1hcAoKdGhpcmQgPC0gbm9ybWFsaXplX2V4cHQoaHNfY2xpbmljYWwsIHRyYW5zZm9ybT0ibG9nMiIsIGNvbnZlcnQ9ImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlciA9IFRSVUUsIGJhdGNoPSJzdmFzZXEiLCBzdXJyb2dhdGVzPTMpICU+JQogIHNldF9leHB0X2JhdGNoZXMoZmFjdD0iY2xpbmljIikKdGhpcmRfaW5mbyA8LSBwY2FfaW5mb3JtYXRpb24oCiAgICB0aGlyZCwgcGxvdF9wY2FzPVRSVUUsIG51bV9jb21wb25lbnRzID0gMzAsCiAgICBleHB0X2ZhY3RvcnM9YygidmlzaXRudW1iZXIiLCAidHlwZW9mY2VsbHMiLCAiY2xpbmljYWxvdXRjb21lIiwKICAgICAgICAgICAgICAgICAgICJjbGluaWMiKSkKdGhpcmRfaW5mbyRhbm92YV9uZWdsb2dwX2hlYXRtYXAKCmZvdXJ0aCA8LSBub3JtYWxpemVfZXhwdChoc19jbGluaWNhbCwgdHJhbnNmb3JtPSJsb2cyIiwgY29udmVydD0iY3BtIiwKICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlciA9IFRSVUUsIGJhdGNoPSJzdmFzZXEiLCBzdXJyb2dhdGVzPTQpICU+JQogIHNldF9leHB0X2JhdGNoZXMoZmFjdD0iY2xpbmljIikKZm91cnRoX2luZm8gPC0gcGNhX2luZm9ybWF0aW9uKAogICAgZm91cnRoLCBwbG90X3BjYXM9VFJVRSwgbnVtX2NvbXBvbmVudHMgPSAzMCwKICAgIGV4cHRfZmFjdG9ycz1jKCJ2aXNpdG51bWJlciIsICJ0eXBlb2ZjZWxscyIsICJjbGluaWNhbG91dGNvbWUiLAogICAgICAgICAgICAgICAgICAgImNsaW5pYyIpKQpmb3VydGhfaW5mbyRhbm92YV9uZWdsb2dwX2hlYXRtYXAKZm91cnRoX2luZm9bWyJwY2FfcGxvdHMiXV1bWyJQQzFfUEMyIl1dCgpmaWZ0aCA8LSBub3JtYWxpemVfZXhwdChoc19jbGluaWNhbCwgdHJhbnNmb3JtPSJsb2cyIiwgY29udmVydD0iY3BtIiwKICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyID0gVFJVRSwgYmF0Y2g9InN2YXNlcSIsIHN1cnJvZ2F0ZXM9NSkgJT4lCiAgc2V0X2V4cHRfYmF0Y2hlcyhmYWN0PSJjbGluaWMiKQpmaWZ0aF9pbmZvIDwtIHBjYV9pbmZvcm1hdGlvbigKICAgIGZpZnRoLCBwbG90X3BjYXM9VFJVRSwgbnVtX2NvbXBvbmVudHMgPSAzMCwKICAgIGV4cHRfZmFjdG9ycz1jKCJ2aXNpdG51bWJlciIsICJ0eXBlb2ZjZWxscyIsICJjbGluaWNhbG91dGNvbWUiLAogICAgICAgICAgICAgICAgICAgImNsaW5pYyIpKQpmaWZ0aF9pbmZvJGFub3ZhX25lZ2xvZ3BfaGVhdG1hcApmaWZ0aF9pbmZvW1sicGNhX3Bsb3RzIl1dW1siUEMxX1BDMTIiXV0KCnNpeHRoIDwtIG5vcm1hbGl6ZV9leHB0KGhzX2NsaW5pY2FsLCB0cmFuc2Zvcm09ImxvZzIiLCBjb252ZXJ0PSJjcG0iLAogICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXIgPSBUUlVFLCBiYXRjaD0ic3Zhc2VxIiwgc3Vycm9nYXRlcz02KSAlPiUKICBzZXRfZXhwdF9iYXRjaGVzKGZhY3Q9ImNsaW5pYyIpCnNpeHRoX2luZm8gPC0gcGNhX2luZm9ybWF0aW9uKAogICAgc2l4dGgsIHBsb3RfcGNhcz1UUlVFLCBudW1fY29tcG9uZW50cyA9IDMwLAogICAgZXhwdF9mYWN0b3JzPWMoInZpc2l0bnVtYmVyIiwgInR5cGVvZmNlbGxzIiwgImNsaW5pY2Fsb3V0Y29tZSIsCiAgICAgICAgICAgICAgICAgICAiY2xpbmljIikpCnNpeHRoX2luZm8kYW5vdmFfbmVnbG9ncF9oZWF0bWFwCgpzZXZlbnRoIDwtIG5vcm1hbGl6ZV9leHB0KGhzX2NsaW5pY2FsLCB0cmFuc2Zvcm09ImxvZzIiLCBjb252ZXJ0PSJjcG0iLAogICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlciA9IFRSVUUsIGJhdGNoPSJzdmFzZXEiLCBzdXJyb2dhdGVzPTcpICU+JQogIHNldF9leHB0X2JhdGNoZXMoZmFjdD0iY2xpbmljIikKc2V2ZW50aF9pbmZvIDwtIHBjYV9pbmZvcm1hdGlvbigKICAgIHNldmVudGgsIHBsb3RfcGNhcz1UUlVFLCBudW1fY29tcG9uZW50cyA9IDMwLAogICAgZXhwdF9mYWN0b3JzPWMoInZpc2l0bnVtYmVyIiwgInR5cGVvZmNlbGxzIiwgImNsaW5pY2Fsb3V0Y29tZSIsCiAgICAgICAgICAgICAgICAgICAiY2xpbmljIikpCnNldmVudGhfaW5mbyRhbm92YV9uZWdsb2dwX2hlYXRtYXAKCmVpZ2h0aCA8LSBub3JtYWxpemVfZXhwdChoc19jbGluaWNhbCwgdHJhbnNmb3JtPSJsb2cyIiwgY29udmVydD0iY3BtIiwKICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyID0gVFJVRSwgYmF0Y2g9InN2YXNlcSIsIHN1cnJvZ2F0ZXM9OCkKZWlnaHRoX2luZm8gPC0gcGNhX2luZm9ybWF0aW9uKAogICAgZWlnaHRoLCBwbG90X3BjYXM9VFJVRSwgbnVtX2NvbXBvbmVudHMgPSAzMCwKICAgIGV4cHRfZmFjdG9ycz1jKCJ2aXNpdG51bWJlciIsICJ0eXBlb2ZjZWxscyIsICJjbGluaWNhbG91dGNvbWUiLAogICAgICAgICAgICAgICAgICAgImNsaW5pYyIpKQplaWdodGhfaW5mbyRhbm92YV9uZWdsb2dwX2hlYXRtYXAKYGBgCgojIERhdGFzZXQ6IE9ubHkgVHVtYWNvIHNhbXBsZXMKCk91ciByZWNlbnQgZGlzY3Vzc2lvbnMgaGF2ZSBzZXR0bGVkIG9uZSBiaWcgcXVlc3Rpb24gcmVnYXJkaW5nIHdoaWNoCnNhbXBsZXMgdG8gdXNlOiAgV2Ugd2lsbCBsaW1pdCBvdXIgYW5hbHlzZXMgdG8gb25seSB0aG9zZSBzYW1wbGVzIGZyb20KVHVtYWNvLgoKVGhlIGZvbGxvd2luZyBibG9jayB3aWxsIHRoZXJlZm9yZSBzZXQgdGhhdCBncm91cCBhcyBvdXIgZGVmYXVsdCBmb3IKZnV0dXJlIGFuYWx5c2VzLgoKYGBge3IgdHVtYWNvX29ubHl9CmNsaW5pY2FsIDwtIGhzX2NsaW5pY2FsICU+JQogIHN1YnNldF9leHB0KHN1YnNldD0iY2xpbmljPT0nVHVtYWNvJyIpCmNsaW5pY2FsX25vYmlvcCA8LSBzdWJzZXRfZXhwdChjbGluaWNhbCwgc3Vic2V0PSJ0eXBlb2ZjZWxscyE9J2Jpb3BzeSciKQpgYGAKCiMjIFN1bW1hcml6ZTogQ29sbGVjdCBUdW1hY28gc2FtcGxlIG51bWJlcnMuCgpBdCBsZWFzdCBpbiB0aGVvcnksIGV2ZXJ5dGhpbmcgd2hpY2ggZm9sbG93cyB3aWxsIGJlIHVzaW5nIHRoZSBhYm92ZQonY2xpbmljYWwnIGRhdGEgc3RydWN0dXJlLiAgVGh1cywgbGV0IHVzIGNvdW50IGl0IHVwIGFuZCBnZXQgYSBzZW5zZQpvZiB3aGF0IHdlIHdpbGwgd29yayB3aXRoLgoKYGBge3IgY291bnRfdHVtYWNvfQp0YWJsZShwRGF0YShjbGluaWNhbCkkZHJ1ZykKdGFibGUocERhdGEoY2xpbmljYWwpJGNsaW5pYykKdGFibGUocERhdGEoY2xpbmljYWwpJGNsaW5pY2Fsb3V0Y29tZSkKdGFibGUocERhdGEoY2xpbmljYWwpJHR5cGVvZmNlbGxzKQp0YWJsZShwRGF0YShjbGluaWNhbCkkdmlzaXQpCnN1bW1hcnkoYXMubnVtZXJpYyhwRGF0YShjbGluaWNhbCkkZWJfbGNfdGllbXBvX2V2b2x1Y2lvbikpCnN1bW1hcnkoYXMubnVtZXJpYyhwRGF0YShjbGluaWNhbCkkZWJfbGNfdHRvX21jdG9fZ2x1Y2FuX2Rvc2lzKSkKc3VtbWFyeShhcy5udW1lcmljKHBEYXRhKGNsaW5pY2FsKSR2M19sY19lamV5X2xlc2lvbl9tbV8xKSkKc3VtbWFyeShhcy5udW1lcmljKHBEYXRhKGNsaW5pY2FsKSR2M19sY19sZXNpb25fYXJlYV8xKSkKc3VtbWFyeShhcy5udW1lcmljKHBEYXRhKGNsaW5pY2FsKSR2M19sY19lamV4X3VsY2VyYV9tbV8xKSkKdGFibGUocERhdGEoY2xpbmljYWwpJGViX2xjX3NleG8pCnRhYmxlKHBEYXRhKGNsaW5pY2FsKSRlYl9sY19ldG5pYSkKc3VtbWFyeShhcy5udW1lcmljKHBEYXRhKGNsaW5pY2FsKSRlZGFkKSkKdGFibGUocERhdGEoY2xpbmljYWwpJGViX2xjX3Blc28pCnRhYmxlKHBEYXRhKGNsaW5pY2FsKSRlYl9sY19lc3RhdHVyYSkKYGBgCgojIyBTdWJzZXQ6IE92ZXJ3cml0ZSBwcmV2aW91cyBkYXRhIHN0cnVjdHVyZXMgd2l0aCBUdW1hY28tc3BlY2lmaWMgdmVyc2lvbnMKCkkgcHJldmlvdXNseSBtYWRlIGEgYnVuY2ggb2YgZGF0YSBzdWJzZXRzIGJ5IHZpc2l0LCBjZWxsIHR5cGUsIGV0Yy4KU28gbGV0IHVzIG92ZXJ3cml0ZSB0aGVtIGFsbCB3aXRoIHZlcnNpb25zIHdoaWNoIGNvbnRhaW4gb25seSB0aGUKVHVtYWNvIHNhbXBsZXMuCgpUaGVyZSBpcyBubyBnb2luZyBiYWNrIHRvIHRoZSBDYWxpIHNhbXBsZXMgYWZ0ZXIgdGhpcyBibG9jayB1bmxlc3Mgd2UKcmVnZW5lcmF0ZSB0aGUgZGF0YSBmcm9tIHRoZSBvcmlnaW5hbCBleHByZXNzaW9uc2V0cy4KCmBgYHtyIHR1bWFjb19zdWJzZXRzfQpiaW9wc3lfc2FtcGxlcyA8LSBiaW9wc3lfc2FtcGxlcyAlPiUKICBzdWJzZXRfZXhwdChzdWJzZXQ9ImNsaW5pYz09J1R1bWFjbyciKQplb3Npbm9waGlsX3NhbXBsZXMgPC0gZW9zaW5vcGhpbF9zYW1wbGVzICU+JQogIHN1YnNldF9leHB0KHN1YnNldD0iY2xpbmljPT0nVHVtYWNvJyIpCm1vbm9jeXRlX3NhbXBsZXMgPC0gbW9ub2N5dGVfc2FtcGxlcyAlPiUKICBzdWJzZXRfZXhwdChzdWJzZXQ9ImNsaW5pYz09J1R1bWFjbyciKQpuZXV0cm9waGlsX3NhbXBsZXMgPC0gbmV1dHJvcGhpbF9zYW1wbGVzICU+JQogIHN1YnNldF9leHB0KHN1YnNldD0iY2xpbmljPT0nVHVtYWNvJyIpCgp2MV9zYW1wbGVzIDwtIHYxX3NhbXBsZXMgJT4lCiAgc3Vic2V0X2V4cHQoc3Vic2V0PSJjbGluaWM9PSdUdW1hY28nIikKdjJfc2FtcGxlcyA8LSB2Ml9zYW1wbGVzICU+JQogIHN1YnNldF9leHB0KHN1YnNldD0iY2xpbmljPT0nVHVtYWNvJyIpCnYzX3NhbXBsZXMgPC0gdjNfc2FtcGxlcyAlPiUKICBzdWJzZXRfZXhwdChzdWJzZXQ9ImNsaW5pYz09J1R1bWFjbyciKQoKdjFfZW9zaW5vcGhpbHMgPC0gdjFfZW9zaW5vcGhpbHMgJT4lCiAgc3Vic2V0X2V4cHQoc3Vic2V0PSJjbGluaWM9PSdUdW1hY28nIikKdjJfZW9zaW5vcGhpbHMgPC0gdjJfZW9zaW5vcGhpbHMgJT4lCiAgc3Vic2V0X2V4cHQoc3Vic2V0PSJjbGluaWM9PSdUdW1hY28nIikKdjNfZW9zaW5vcGhpbHMgPC0gdjNfZW9zaW5vcGhpbHMgJT4lCiAgc3Vic2V0X2V4cHQoc3Vic2V0PSJjbGluaWM9PSdUdW1hY28nIikKCnYxX21vbm9jeXRlcyA8LSB2MV9tb25vY3l0ZXMgJT4lCiAgc3Vic2V0X2V4cHQoc3Vic2V0PSJjbGluaWM9PSdUdW1hY28nIikKdjJfbW9ub2N5dGVzIDwtIHYyX21vbm9jeXRlcyAlPiUKICBzdWJzZXRfZXhwdChzdWJzZXQ9ImNsaW5pYz09J1R1bWFjbyciKQp2M19tb25vY3l0ZXMgPC0gdjNfbW9ub2N5dGVzICU+JQogIHN1YnNldF9leHB0KHN1YnNldD0iY2xpbmljPT0nVHVtYWNvJyIpCgp2MV9uZXV0cm9waGlscyA8LSB2MV9uZXV0cm9waGlscyAlPiUKICBzdWJzZXRfZXhwdChzdWJzZXQ9ImNsaW5pYz09J1R1bWFjbyciKQp2Ml9uZXV0cm9waGlscyA8LSB2Ml9uZXV0cm9waGlscyAlPiUKICBzdWJzZXRfZXhwdChzdWJzZXQ9ImNsaW5pYz09J1R1bWFjbyciKQp2M19uZXV0cm9waGlscyA8LSB2M19uZXV0cm9waGlscyAlPiUKICBzdWJzZXRfZXhwdChzdWJzZXQ9ImNsaW5pYz09J1R1bWFjbyciKQpgYGAKCiMjIFZpc3VhbGl6ZTogUmVwZWF0IHBsb3RzIHVzaW5nIG9ubHkgdGhlIFR1bWFjbyBzYW1wbGVzCgpOb3cgd2UgaGF2ZSBhIG5ldywgc21hbGxlciBzZXQgb2YgcHJpbWFyeSBzYW1wbGVzIHdoaWNoIGFyZQpjYXRlZ29yaXplZCBieSBjZWxsIHR5cGUuCgojIyMgVmlzdWFsaXplOiBCaW9wc3kgc2FtcGxlcyBvbmx5IFR1bWFjbwoKU2FkbHksIHRoZSBiaW9wc3kgc2FtcGxlcyByZW1haW4gYmFzaWNhbGx5IGltcGVuZXRyYWJsZS4gIFRoaXMgbWFrZXMKbWUgc2FkLCBJIHRoaW5rIGl0IHdvdWxkIGJlIHBhcnRpY3VsYXJseSBuaWNlIGlmIHdlIGNvdWxkIGp1ZGdlCmN1cmUvZmFpbCBmcm9tIGEgdmlzaXQgMSBiaW9wc3kuCgpgYGB7ciBub3JtYWxpemVfYmlvcHN5X3R1bWFjb19zYW1wbGVzfQpiaW9wc3lfbm9ybSA8LSBub3JtYWxpemVfZXhwdChiaW9wc3lfc2FtcGxlcywgdHJhbnNmb3JtPSJsb2cyIiwgY29udmVydD0iY3BtIiwKICBub3JtPSJxdWFudCIsIGZpbHRlcj1UUlVFKQoKYmlvcHN5X3BjYSA8LSBwbG90X3BjYShiaW9wc3lfbm9ybSwKICBwbG90X2xhYmVscz1GQUxTRSkKZGV2IDwtIHBwKGZpbGU9ImltYWdlcy9iaW9wc3lzX3R1bWFjb19ub3JtLnBuZyIpCmJpb3BzeV9wY2EkcGxvdApjbG9zZWQgPC0gZGV2Lm9mZigpCmJpb3BzeV9wY2EkcGxvdAoKYmlvcHN5X25iIDwtIG5vcm1hbGl6ZV9leHB0KGJpb3BzeV9zYW1wbGVzLCB0cmFuc2Zvcm09ImxvZzIiLCBjb252ZXJ0PSJjcG0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmF0Y2g9InN2YXNlcSIsIGZpbHRlcj1UUlVFKQpiaW9wc3lfbmJfcGNhIDwtIHBsb3RfcGNhKGJpb3BzeV9uYiwgcGxvdF9sYWJlbHM9RkFMU0UpCmRldiA8LSBwcChmaWxlPSJpbWFnZXMvYmlvcHN5c190dW1hY29fbm9ybV9zdmEucG5nIikKYmlvcHN5X25iX3BjYSRwbG90CmNsb3NlZCA8LSBkZXYub2ZmKCkKYmlvcHN5X25iX3BjYSRwbG90CmBgYAoKIyMjIFZpc3VhbGl6ZTogTW9ub2N5dGUgc2FtcGxlcyBvbmx5IFR1bWFjbwoKSW4gY29udHJhc3QsIEkgc3VzcGVjdCB0aGF0IHdlIGNhbiBnZXQgbWVhbmluZ2Z1bCBkYXRhIGZyb20gdGhlCm90aGVyIGNlbGwgdHlwZXMuICBUaGUgbW9ub2N5dGUgc2FtcGxlcyBhcmUgc3RpbGwgYSBiaXQgbWVzc3kuCgpgYGB7ciBub3JtYWxpemVfbW9ub2N5dGVfdHVtYWNvX3NhbXBsZXN9Cm1vbm9jeXRlX25vcm0gPC0gbm9ybWFsaXplX2V4cHQobW9ub2N5dGVfc2FtcGxlcywgdHJhbnNmb3JtPSJsb2cyIiwgY29udmVydD0iY3BtIiwKICBub3JtPSJxdWFudCIsIGZpbHRlcj1UUlVFKQoKbW9ub2N5dGVfcGNhIDwtIHBsb3RfcGNhKG1vbm9jeXRlX25vcm0sCiAgcGxvdF9sYWJlbHM9RkFMU0UpCmRldiA8LSBwcChmaWxlPSJpbWFnZXMvbW9ub2N5dGVzX3R1bWFjb19ub3JtLnBuZyIpCm1vbm9jeXRlX3BjYSRwbG90CmNsb3NlZCA8LSBkZXYub2ZmKCkKbW9ub2N5dGVfcGNhJHBsb3QKCm1vbm9jeXRlX25iIDwtIG5vcm1hbGl6ZV9leHB0KG1vbm9jeXRlX3NhbXBsZXMsIHRyYW5zZm9ybT0ibG9nMiIsIGNvbnZlcnQ9ImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYXRjaD0ic3Zhc2VxIiwgZmlsdGVyPVRSVUUpCm1vbm9jeXRlX25iX3BjYSA8LSBwbG90X3BjYShtb25vY3l0ZV9uYiwgcGxvdF9sYWJlbHM9RkFMU0UpCmRldiA8LSBwcChmaWxlPSJpbWFnZXMvbW9ub2N5dGVzX3R1bWFjb19ub3JtX3N2YS5wbmciKQptb25vY3l0ZV9uYl9wY2EkcGxvdApjbG9zZWQgPC0gZGV2Lm9mZigpCm1vbm9jeXRlX25iX3BjYSRwbG90CmBgYAoKIyMjIFZpc3VhbGl6ZTogTmV1dHJvcGhpbCBzYW1wbGVzIG9ubHkgVHVtYWNvCgpXZWxsLCByZWFsbHkgYWxsIHRoZSBjZWxsIHR5cGVzIHJlbWFpbiBwcmV0dHkgbWVzc3kuICBUaGVyZSBpcyBhbHdheXMKYXQgbGVhc3Qgb25lIHBlcnNvbiBpbiBvbmUgdmlzaXQgb3IgYW5vdGhlciB3aG8gcmVhbGx5IGRvZXMgbm90IGZpdAp3ZWxsIHdpdGggdGhlIHJlc3Qgb2YgdGhlIGNvaG9ydC4KCmBgYHtyIG5vcm1hbGl6ZV9uZXV0cm9waGlsX3R1bWFjb19zYW1wbGVzfQpuZXV0cm9waGlsX25vcm0gPC0gbm9ybWFsaXplX2V4cHQobmV1dHJvcGhpbF9zYW1wbGVzLCB0cmFuc2Zvcm09ImxvZzIiLCBjb252ZXJ0PSJjcG0iLAogIG5vcm09InF1YW50IiwgZmlsdGVyPVRSVUUpCgpuZXV0cm9waGlsX3BjYSA8LSBwbG90X3BjYShuZXV0cm9waGlsX25vcm0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3RfbGFiZWxzPUZBTFNFKQpkZXYgPC0gcHAoZmlsZT0iaW1hZ2VzL25ldXRyb3BoaWxzX3R1bWFjb19ub3JtLnBuZyIpCm5ldXRyb3BoaWxfcGNhJHBsb3QKY2xvc2VkIDwtIGRldi5vZmYoKQpuZXV0cm9waGlsX3BjYSRwbG90CgpuZXV0cm9waGlsX25iIDwtIG5vcm1hbGl6ZV9leHB0KG5ldXRyb3BoaWxfc2FtcGxlcywgdHJhbnNmb3JtPSJsb2cyIiwgY29udmVydD0iY3BtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhdGNoPSJzdmFzZXEiLCBmaWx0ZXI9VFJVRSkKbmV1dHJvcGhpbF9uYl9wY2EgPC0gcGxvdF9wY2EobmV1dHJvcGhpbF9uYiwgcGxvdF9sYWJlbHM9RkFMU0UpCmRldiA8LSBwcChmaWxlPSJpbWFnZXMvbmV1dHJvcGhpbHNfdHVtYWNvX25vcm1fc3ZhLnBuZyIpCm5ldXRyb3BoaWxfbmJfcGNhJHBsb3QKY2xvc2VkIDwtIGRldi5vZmYoKQpuZXV0cm9waGlsX25iX3BjYSRwbG90CmBgYAoKIyMjIFZpc3VhbGl6ZTogRW9zaW5vcGhpbCBzYW1wbGVzIG9ubHkgVHVtYWNvCgpgYGB7ciBub3JtYWxpemVfZW9zaW5vcGhpbF90dW1hY29fc2FtcGxlc30KZW9zaW5vcGhpbF9ub3JtIDwtIG5vcm1hbGl6ZV9leHB0KGVvc2lub3BoaWxfc2FtcGxlcywgdHJhbnNmb3JtPSJsb2cyIiwgY29udmVydD0iY3BtIiwKICBub3JtPSJxdWFudCIsIGZpbHRlcj1UUlVFKQoKZW9zaW5vcGhpbF9wY2EgPC0gcGxvdF9wY2EoZW9zaW5vcGhpbF9ub3JtLAogIHBsb3RfbGFiZWxzPUZBTFNFKQpkZXYgPC0gcHAoZmlsZT0iaW1hZ2VzL2Vvc2lub3BoaWxzX3R1bWFjb19ub3JtLnBuZyIpCmVvc2lub3BoaWxfcGNhJHBsb3QKY2xvc2VkIDwtIGRldi5vZmYoKQplb3Npbm9waGlsX3BjYSRwbG90Cgplb3Npbm9waGlsX25iIDwtIG5vcm1hbGl6ZV9leHB0KGVvc2lub3BoaWxfc2FtcGxlcywgdHJhbnNmb3JtPSJsb2cyIiwgY29udmVydD0iY3BtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhdGNoPSJzdmFzZXEiLCBmaWx0ZXI9VFJVRSkKZW9zaW5vcGhpbF9uYl9wY2EgPC0gcGxvdF9wY2EoZW9zaW5vcGhpbF9uYiwgcGxvdF9sYWJlbHM9RkFMU0UpCmRldiA8LSBwcChmaWxlPSJpbWFnZXMvZW9zaW5vcGhpbHNfdHVtYWNvX25vcm1fc3ZhLnBuZyIpCmVvc2lub3BoaWxfbmJfcGNhJHBsb3QKY2xvc2VkIDwtIGRldi5vZmYoKQplb3Npbm9waGlsX25iX3BjYSRwbG90CmBgYAoKIyMjIFZpc3VhbGl6ZTogTG9vayBhdCBDZWxsIHR5cGVzIEMvRiBieSB2aXNpdAoKIyMjIyBNb25vY3l0ZXMsIFZpc2l0IDEKCmBgYHtyIG1vbm9jeXRlc19ieV92aXNpdF92MX0KbW9ub2N5dGVfdjEgPC0gc3Vic2V0X2V4cHQobW9ub2N5dGVfc2FtcGxlcywgc3Vic2V0ID0gInZpc2l0bnVtYmVyPT0nMSciKQptb25vY3l0ZV92MV9ub3JtIDwtIG5vcm1hbGl6ZV9leHB0KG1vbm9jeXRlX3YxLCBub3JtID0gInF1YW50IiwgY29udmVydCA9ICJjcG0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybSA9ICJsb2cyIiwgZmlsdGVyID0gVFJVRSkKbW9ub2N5dGVfdjFfcGNhIDwtIHBsb3RfcGNhKG1vbm9jeXRlX3YxX25vcm0sIHBsb3RfbGFiZWxzID0gRkFMU0UpCmRldiA8LSBwcChmaWxlPSJpbWFnZXMvbW9ub2N5dGVzX3YxX2NmX25vcm1fcGNhLnBuZyIpCm1vbm9jeXRlX3YxX3BjYSRwbG90CmNsb3NlZCA8LSBkZXYub2ZmKCkKbW9ub2N5dGVfdjFfcGNhJHBsb3QKCm1vbm9jeXRlX3YxX25iIDwtIG5vcm1hbGl6ZV9leHB0KG1vbm9jeXRlX3YxLCBjb252ZXJ0ID0gImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0gPSAibG9nMiIsIGZpbHRlciA9IFRSVUUsIGJhdGNoID0gInN2YXNlcSIpCm1vbm9jeXRlX3YxX25iX3BjYSA8LSBwbG90X3BjYShtb25vY3l0ZV92MV9uYiwgcGxvdF9sYWJlbHMgPSBGQUxTRSkKZGV2IDwtIHBwKGZpbGU9ImltYWdlcy9tb25vY3l0ZXNfdjFfY2Zfbm9ybV9zdmFfcGNhLnBuZyIpCm1vbm9jeXRlX3YxX25iX3BjYSRwbG90CmNsb3NlZCA8LSBkZXYub2ZmKCkKbW9ub2N5dGVfdjFfbmJfcGNhJHBsb3QKYGBgCgojIyMjIE1vbm9jeXRlcyBWaXNpdCAyCgpgYGB7ciBtb25vY3l0ZXNfYnlfdmlzaXRfMn0KbW9ub2N5dGVfdjIgPC0gc3Vic2V0X2V4cHQobW9ub2N5dGVfc2FtcGxlcywgc3Vic2V0ID0gInZpc2l0bnVtYmVyPT0nMiciKQptb25vY3l0ZV92Ml9ub3JtIDwtIG5vcm1hbGl6ZV9leHB0KG1vbm9jeXRlX3YyLCBub3JtID0gInF1YW50IiwgY29udmVydCA9ICJjcG0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybSA9ICJsb2cyIiwgZmlsdGVyID0gVFJVRSkKbW9ub2N5dGVfdjJfcGNhIDwtIHBsb3RfcGNhKG1vbm9jeXRlX3YyX25vcm0sIHBsb3RfbGFiZWxzID0gRkFMU0UpCmRldiA8LSBwcChmaWxlPSJpbWFnZXMvbW9ub2N5dGVzX3YyX2NmX25vcm1fcGNhLnBuZyIpCm1vbm9jeXRlX3YyX3BjYSRwbG90CmNsb3NlZCA8LSBkZXYub2ZmKCkKbW9ub2N5dGVfdjJfcGNhJHBsb3QKCm1vbm9jeXRlX3YyX25iIDwtIG5vcm1hbGl6ZV9leHB0KG1vbm9jeXRlX3YyLCBjb252ZXJ0ID0gImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0gPSAibG9nMiIsIGZpbHRlciA9IFRSVUUsIGJhdGNoID0gInN2YXNlcSIpCm1vbm9jeXRlX3YyX25iX3BjYSA8LSBwbG90X3BjYShtb25vY3l0ZV92Ml9uYiwgcGxvdF9sYWJlbHMgPSBGQUxTRSkKZGV2IDwtIHBwKGZpbGU9ImltYWdlcy9tb25vY3l0ZXNfdjJfY2Zfbm9ybV9zdmFfcGNhLnBuZyIpCm1vbm9jeXRlX3YyX25iX3BjYSRwbG90CmNsb3NlZCA8LSBkZXYub2ZmKCkKbW9ub2N5dGVfdjJfbmJfcGNhJHBsb3QKYGBgCgojIyMjIE1vbm9jeXRlcyBWaXNpdCAzCgpgYGB7ciBtb25vY3l0ZXNfYnlfdmlzaXRfM30KbW9ub2N5dGVfdjMgPC0gc3Vic2V0X2V4cHQobW9ub2N5dGVfc2FtcGxlcywgc3Vic2V0ID0gInZpc2l0bnVtYmVyPT0nMyciKQptb25vY3l0ZV92M19ub3JtIDwtIG5vcm1hbGl6ZV9leHB0KG1vbm9jeXRlX3YzLCBub3JtID0gInF1YW50IiwgY29udmVydCA9ICJjcG0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybSA9ICJsb2cyIiwgZmlsdGVyID0gVFJVRSkKbW9ub2N5dGVfdjNfcGNhIDwtIHBsb3RfcGNhKG1vbm9jeXRlX3YzX25vcm0sIHBsb3RfbGFiZWxzID0gRkFMU0UpCmRldiA8LSBwcChmaWxlPSJpbWFnZXMvbW9ub2N5dGVzX3YzX2NmX25vcm1fcGNhLnBuZyIpCm1vbm9jeXRlX3YzX3BjYSRwbG90CmNsb3NlZCA8LSBkZXYub2ZmKCkKbW9ub2N5dGVfdjNfcGNhJHBsb3QKCm1vbm9jeXRlX3YzX25iIDwtIG5vcm1hbGl6ZV9leHB0KG1vbm9jeXRlX3YzLCBjb252ZXJ0ID0gImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybSA9ICJsb2cyIiwgZmlsdGVyID0gVFJVRSwgYmF0Y2ggPSAic3Zhc2VxIikKbW9ub2N5dGVfdjNfbmJfcGNhIDwtIHBsb3RfcGNhKG1vbm9jeXRlX3YzX25iLCBwbG90X2xhYmVscyA9IEZBTFNFKQpkZXYgPC0gcHAoZmlsZT0iaW1hZ2VzL21vbm9jeXRlc192M19jZl9ub3JtX3N2YV9wY2EucG5nIikKbW9ub2N5dGVfdjNfbmJfcGNhJHBsb3QKY2xvc2VkIDwtIGRldi5vZmYoKQptb25vY3l0ZV92M19uYl9wY2EkcGxvdApgYGAKCiMjIyMgTmV1dHJvcGhpbHMsIFZpc2l0IDEKCmBgYHtyIG5ldXRyb3BoaWxzX2J5X3Zpc2l0X3YxfQpuZXV0cm9waGlsX3YxIDwtIHN1YnNldF9leHB0KG5ldXRyb3BoaWxfc2FtcGxlcywgc3Vic2V0ID0gInZpc2l0bnVtYmVyPT0nMSciKQpuZXV0cm9waGlsX3YxX25vcm0gPC0gbm9ybWFsaXplX2V4cHQobmV1dHJvcGhpbF92MSwgbm9ybSA9ICJxdWFudCIsIGNvbnZlcnQgPSAiY3BtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0gPSAibG9nMiIsIGZpbHRlciA9IFRSVUUpCm5ldXRyb3BoaWxfdjFfcGNhIDwtIHBsb3RfcGNhKG5ldXRyb3BoaWxfdjFfbm9ybSwgcGxvdF9sYWJlbHMgPSBGQUxTRSkKZGV2IDwtIHBwKGZpbGU9ImltYWdlcy9uZXV0cm9waGlsc192MV9jZl9ub3JtX3BjYS5wbmciKQpuZXV0cm9waGlsX3YxX3BjYSRwbG90CmNsb3NlZCA8LSBkZXYub2ZmKCkKbmV1dHJvcGhpbF92MV9wY2EkcGxvdAoKbmV1dHJvcGhpbF92MV9uYiA8LSBub3JtYWxpemVfZXhwdChuZXV0cm9waGlsX3YxLCBjb252ZXJ0ID0gImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0gPSAibG9nMiIsIGZpbHRlciA9IFRSVUUsIGJhdGNoID0gInJ1dmciKQpuZXV0cm9waGlsX3YxX25iX3BjYSA8LSBwbG90X3BjYShuZXV0cm9waGlsX3YxX25iLCBwbG90X2xhYmVscyA9IEZBTFNFKQpkZXYgPC0gcHAoZmlsZT0iaW1hZ2VzL25ldXRyb3BoaWxzX3YxX2NmX25vcm1fc3ZhX3BjYS5wbmciKQpuZXV0cm9waGlsX3YxX25iX3BjYSRwbG90CmNsb3NlZCA8LSBkZXYub2ZmKCkKbmV1dHJvcGhpbF92MV9uYl9wY2EkcGxvdApgYGAKCiMjIyMgTmV1dHJvcGhpbHMgVmlzaXQgMgoKYGBge3IgbmV1dHJvcGhpbHNfYnlfdmlzaXRfMn0KbmV1dHJvcGhpbF92MiA8LSBzdWJzZXRfZXhwdChuZXV0cm9waGlsX3NhbXBsZXMsIHN1YnNldCA9ICJ2aXNpdG51bWJlcj09JzInIikKbmV1dHJvcGhpbF92Ml9ub3JtIDwtIG5vcm1hbGl6ZV9leHB0KG5ldXRyb3BoaWxfdjIsIG5vcm0gPSAicXVhbnQiLCBjb252ZXJ0ID0gImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtID0gImxvZzIiLCBmaWx0ZXIgPSBUUlVFKQpuZXV0cm9waGlsX3YyX3BjYSA8LSBwbG90X3BjYShuZXV0cm9waGlsX3YyX25vcm0sIHBsb3RfbGFiZWxzID0gRkFMU0UpCmRldiA8LSBwcChmaWxlPSJpbWFnZXMvbmV1dHJvcGhpbHNfdjJfY2Zfbm9ybV9wY2EucG5nIikKbmV1dHJvcGhpbF92Ml9wY2EkcGxvdApjbG9zZWQgPC0gZGV2Lm9mZigpCm5ldXRyb3BoaWxfdjJfcGNhJHBsb3QKCm5ldXRyb3BoaWxfdjJfbmIgPC0gbm9ybWFsaXplX2V4cHQobmV1dHJvcGhpbF92MiwgY29udmVydCA9ICJjcG0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtID0gImxvZzIiLCBmaWx0ZXIgPSBUUlVFLCBiYXRjaCA9ICJzdmFzZXEiKQpuZXV0cm9waGlsX3YyX25iX3BjYSA8LSBwbG90X3BjYShuZXV0cm9waGlsX3YyX25iLCBwbG90X2xhYmVscyA9IEZBTFNFKQpkZXYgPC0gcHAoZmlsZT0iaW1hZ2VzL25ldXRyb3BoaWxzX3YyX2NmX25vcm1fc3ZhX3BjYS5wbmciKQpuZXV0cm9waGlsX3YyX25iX3BjYSRwbG90CmNsb3NlZCA8LSBkZXYub2ZmKCkKbmV1dHJvcGhpbF92Ml9uYl9wY2EkcGxvdApgYGAKCiMjIyMgTmV1dHJvcGhpbHMgVmlzaXQgMwoKYGBge3IgbmV1dHJvcGhpbHNfYnlfdmlzaXRfM30KbmV1dHJvcGhpbF92MyA8LSBzdWJzZXRfZXhwdChuZXV0cm9waGlsX3NhbXBsZXMsIHN1YnNldCA9ICJ2aXNpdG51bWJlcj09JzMnIikKbmV1dHJvcGhpbF92M19ub3JtIDwtIG5vcm1hbGl6ZV9leHB0KG5ldXRyb3BoaWxfdjMsIG5vcm0gPSAicXVhbnQiLCBjb252ZXJ0ID0gImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtID0gImxvZzMiLCBmaWx0ZXIgPSBUUlVFKQpuZXV0cm9waGlsX3YzX3BjYSA8LSBwbG90X3BjYShuZXV0cm9waGlsX3YzX25vcm0sIHBsb3RfbGFiZWxzID0gRkFMU0UpCmRldiA8LSBwcChmaWxlPSJpbWFnZXMvbmV1dHJvcGhpbHNfdjNfY2Zfbm9ybV9wY2EucG5nIikKbmV1dHJvcGhpbF92M19wY2EkcGxvdApjbG9zZWQgPC0gZGV2Lm9mZigpCm5ldXRyb3BoaWxfdjNfcGNhJHBsb3QKCm5ldXRyb3BoaWxfdjNfbmIgPC0gbm9ybWFsaXplX2V4cHQobmV1dHJvcGhpbF92MywgY29udmVydCA9ICJjcG0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtID0gImxvZzIiLCBmaWx0ZXIgPSBUUlVFLCBiYXRjaCA9ICJzdmFzZXEiKQpuZXV0cm9waGlsX3YzX25iX3BjYSA8LSBwbG90X3BjYShuZXV0cm9waGlsX3YzX25iLCBwbG90X2xhYmVscyA9IEZBTFNFKQpkZXYgPC0gcHAoZmlsZT0iaW1hZ2VzL25ldXRyb3BoaWxzX3YzX2NmX25vcm1fc3ZhX3BjYS5wbmciKQpuZXV0cm9waGlsX3YzX25iX3BjYSRwbG90CmNsb3NlZCA8LSBkZXYub2ZmKCkKbmV1dHJvcGhpbF92M19uYl9wY2EkcGxvdApgYGAKCiMjIyMgRW9zaW5vcGhpbHMsIFZpc2l0IDEKCmBgYHtyIGVvc2lub3BoaWxzX2J5X3Zpc2l0X3YxfQplb3Npbm9waGlsX3YxIDwtIHN1YnNldF9leHB0KGVvc2lub3BoaWxfc2FtcGxlcywgc3Vic2V0ID0gInZpc2l0bnVtYmVyPT0nMSciKQplb3Npbm9waGlsX3YxX25vcm0gPC0gbm9ybWFsaXplX2V4cHQoZW9zaW5vcGhpbF92MSwgbm9ybSA9ICJxdWFudCIsIGNvbnZlcnQgPSAiY3BtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0gPSAibG9nMiIsIGZpbHRlciA9IFRSVUUpCmVvc2lub3BoaWxfdjFfcGNhIDwtIHBsb3RfcGNhKGVvc2lub3BoaWxfdjFfbm9ybSwgcGxvdF9sYWJlbHMgPSBGQUxTRSkKZGV2IDwtIHBwKGZpbGU9ImltYWdlcy9lb3Npbm9waGlsc192MV9jZl9ub3JtX3BjYS5wbmciKQplb3Npbm9waGlsX3YxX3BjYSRwbG90CmNsb3NlZCA8LSBkZXYub2ZmKCkKZW9zaW5vcGhpbF92MV9wY2EkcGxvdAoKZW9zaW5vcGhpbF92MV9uYiA8LSBub3JtYWxpemVfZXhwdChlb3Npbm9waGlsX3YxLCBjb252ZXJ0ID0gImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0gPSAibG9nMiIsIGZpbHRlciA9IFRSVUUsIGJhdGNoID0gInN2YXNlcSIpCmVvc2lub3BoaWxfdjFfbmJfcGNhIDwtIHBsb3RfcGNhKGVvc2lub3BoaWxfdjFfbmIsIHBsb3RfbGFiZWxzID0gRkFMU0UpCmRldiA8LSBwcChmaWxlPSJpbWFnZXMvZW9zaW5vcGhpbHNfdjFfY2Zfbm9ybV9zdmFfcGNhLnBuZyIpCmVvc2lub3BoaWxfdjFfbmJfcGNhJHBsb3QKY2xvc2VkIDwtIGRldi5vZmYoKQplb3Npbm9waGlsX3YxX25iX3BjYSRwbG90CmBgYAoKIyMjIyBFb3Npbm9waGlscyBWaXNpdCAyCgpgYGB7ciBlb3Npbm9waGlsc19ieV92aXNpdF8yfQplb3Npbm9waGlsX3YyIDwtIHN1YnNldF9leHB0KGVvc2lub3BoaWxfc2FtcGxlcywgc3Vic2V0ID0gInZpc2l0bnVtYmVyPT0nMiciKQplb3Npbm9waGlsX3YyX25vcm0gPC0gbm9ybWFsaXplX2V4cHQoZW9zaW5vcGhpbF92Miwgbm9ybSA9ICJxdWFudCIsIGNvbnZlcnQgPSAiY3BtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0gPSAibG9nMiIsIGZpbHRlciA9IFRSVUUpCmVvc2lub3BoaWxfdjJfcGNhIDwtIHBsb3RfcGNhKGVvc2lub3BoaWxfdjJfbm9ybSwgcGxvdF9sYWJlbHMgPSBGQUxTRSkKZGV2IDwtIHBwKGZpbGU9ImltYWdlcy9lb3Npbm9waGlsc192Ml9jZl9ub3JtX3BjYS5wbmciKQplb3Npbm9waGlsX3YyX3BjYSRwbG90CmNsb3NlZCA8LSBkZXYub2ZmKCkKZW9zaW5vcGhpbF92Ml9wY2EkcGxvdAoKZW9zaW5vcGhpbF92Ml9uYiA8LSBub3JtYWxpemVfZXhwdChlb3Npbm9waGlsX3YyLCBjb252ZXJ0ID0gImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0gPSAibG9nMiIsIGZpbHRlciA9IFRSVUUsIGJhdGNoID0gInN2YXNlcSIpCmVvc2lub3BoaWxfdjJfbmJfcGNhIDwtIHBsb3RfcGNhKGVvc2lub3BoaWxfdjJfbmIsIHBsb3RfbGFiZWxzID0gRkFMU0UpCmRldiA8LSBwcChmaWxlPSJpbWFnZXMvZW9zaW5vcGhpbHNfdjJfY2Zfbm9ybV9zdmFfcGNhLnBuZyIpCmVvc2lub3BoaWxfdjJfbmJfcGNhJHBsb3QKY2xvc2VkIDwtIGRldi5vZmYoKQplb3Npbm9waGlsX3YyX25iX3BjYSRwbG90CmBgYAoKIyMjIyBFb3Npbm9waGlscyBWaXNpdCAzCgpgYGB7ciBlb3Npbm9waGlsc19ieV92aXNpdF8zfQplb3Npbm9waGlsX3YzIDwtIHN1YnNldF9leHB0KGVvc2lub3BoaWxfc2FtcGxlcywgc3Vic2V0ID0gInZpc2l0bnVtYmVyPT0nMyciKQplb3Npbm9waGlsX3YzX25vcm0gPC0gbm9ybWFsaXplX2V4cHQoZW9zaW5vcGhpbF92Mywgbm9ybSA9ICJxdWFudCIsIGNvbnZlcnQgPSAiY3BtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0gPSAibG9nMyIsIGZpbHRlciA9IFRSVUUpCmVvc2lub3BoaWxfdjNfcGNhIDwtIHBsb3RfcGNhKGVvc2lub3BoaWxfdjNfbm9ybSwgcGxvdF9sYWJlbHMgPSBGQUxTRSkKZGV2IDwtIHBwKGZpbGU9ImltYWdlcy9lb3Npbm9waGlsc192M19jZl9ub3JtX3BjYS5wbmciKQplb3Npbm9waGlsX3YzX3BjYSRwbG90CmNsb3NlZCA8LSBkZXYub2ZmKCkKZW9zaW5vcGhpbF92M19wY2EkcGxvdAoKZW9zaW5vcGhpbF92M19uYiA8LSBub3JtYWxpemVfZXhwdChlb3Npbm9waGlsX3YzLCBjb252ZXJ0ID0gImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0gPSAibG9nMiIsIGZpbHRlciA9IFRSVUUsIGJhdGNoID0gInN2YXNlcSIpCmVvc2lub3BoaWxfdjNfbmJfcGNhIDwtIHBsb3RfcGNhKGVvc2lub3BoaWxfdjNfbmIsIHBsb3RfbGFiZWxzID0gRkFMU0UpCmRldiA8LSBwcChmaWxlPSJpbWFnZXMvZW9zaW5vcGhpbHNfdjNfY2Zfbm9ybV9zdmFfcGNhLnBuZyIpCmVvc2lub3BoaWxfdjNfbmJfcGNhJHBsb3QKY2xvc2VkIDwtIGRldi5vZmYoKQplb3Npbm9waGlsX3YzX25iX3BjYSRwbG90CmBgYAoKIyMgUmVjYXRlZ29yaXplOiBDb25jYXRlbmF0ZSBjdXJlL2ZhaWwgYW5kIGNlbGwgdHlwZQoKSW4gdGhlIGZvbGxvd2luZyBibG9jayB0aGUgZXhwZXJpbWVudGFsIGNvbmRpdGlvbiB3YXMgcmVzZXQgdG8gdGhlCmNvbmNhdGVuYXRpb24gb2YgY2xpbmljYWwgb3V0Y29tZSBhbmQgdHlwZSBvZiBjZWxscy4gIFRoZXJlIGFyZSBhbgppbnN1ZmZpY2llbnQgbnVtYmVyIG9mIGJpb3BzeSBzYW1wbGVzIGZvciB0aGVtIHRvIGJlIHVzZWZ1bCBpbiB0aGlzCnZpc3VhbGl6YXRpb24sIHNvIHRoZXkgYXJlIGlnbm9yZWQuCgpgYGB7ciBjZl9hbmRfdHlwZX0KZGVzaXJlZF9sZXZlbHMgPC0gYygiY3VyZV9iaW9wc3kiLCAiZmFpbHVyZV9iaW9wc3kiLCAiY3VyZV9lb3Npbm9waGlscyIsICJmYWlsdXJlX2Vvc2lub3BoaWxzIiwKICAgICAgICAgICAgICAgICAgICAiY3VyZV9tb25vY3l0ZXMiLCAiZmFpbHVyZV9tb25vY3l0ZXMiLCAiY3VyZV9uZXV0cm9waGlscyIsICJmYWlsdXJlX25ldXRyb3BoaWxzIikKbmV3X2ZhY3QgPC0gZmFjdG9yKAogICAgcGFzdGUwKHBEYXRhKGNsaW5pY2FsKVtbImNvbmRpdGlvbiJdXSwgIl8iLAogICAgICAgICAgIHBEYXRhKGNsaW5pY2FsKVtbImJhdGNoIl1dKSwKICAgIGxldmVscz1kZXNpcmVkX2xldmVscykKCmNsaW5pY2FsX2NvbmNhdCA8LSBzZXRfZXhwdF9jb25kaXRpb25zKGNsaW5pY2FsLCBmYWN0ID0gbmV3X2ZhY3QpICU+JQogIHNldF9leHB0X2JhdGNoZXMoZmFjdCA9ICJ2aXNpdG51bWJlciIpICU+JQogIHNldF9leHB0X2NvbG9ycyhjZl90eXBlX2NvbG9ycykgJT4lCiAgc3Vic2V0X2V4cHQoc3Vic2V0PSJ0eXBlb2ZjZWxscyE9J2Jpb3BzeSciKQoKIyMgVHJ5IHRvIGVuc3VyZSB0aGF0IHRoZSBsZXZlbHMgc3RheSBpbiB0aGUgb3JkZXIgSSB3YW50Cm1ldGEgPC0gcERhdGEoY2xpbmljYWxfY29uY2F0KSAlPiUKICBtdXRhdGUoY29uZGl0aW9uID0gZmN0X3JlbGV2ZWwoY29uZGl0aW9uLCBkZXNpcmVkX2xldmVscykpCnBEYXRhKGNsaW5pY2FsX2NvbmNhdCkgPC0gbWV0YQpgYGAKCiMjIyBWaXN1YWxpemU6IExvb2sgYXQgVHVtYWNvLW9ubHkgc2FtcGxlcyBieSBjZWxsIHR5cGUgYW5kIGN1cmUvZmFpbAoKVGhlIGZvbGxvd2luZyBibG9jayBpcyBwcmV0dHkgd2lsZCB0byBteSBleWVzOyBpdCBzZWVtcyB0byBtZSB0aGF0IHRoZQp2YXJpYW5jZXMgaW50cm9kdWNlZCBieSBjZWxsIHR5cGUgYmFzaWNhbGx5IHdpcGUgb3V0IHRoZSBhcHBhcmVudApkaWZmZXJlbmNlcyBiZXR3ZWVuIGN1cmUvZmFpbCB0aGF0IHdlIHdlcmUgYWJsZSB0byBzZWUgcHJldmlvdXNseS4KCkkgc3VwcG9zZSB0aGlzIGlzIG5vdCBlbnRpcmVseSBzdXJwcmlzaW5nLCBidXQgd2hlbiB3ZSBoYWQgdGhlIENhbGkKc2FtcGxlcyBpdCBhdCBsZWFzdCBsb29rZWQgbGlrZSB0aGVyZSB3ZXJlIGRpZmZlcmVuY2VzIHdoaWNoIHdlcmUKZXhwbGljaXRseSBiZXR3ZWVuIGN1cmUvZmFpbCBhY3Jvc3MgY2VsbCB0eXBlcy4gIEkgc3VwcG9zZSB0aGlzIG1lYW5zCnRob3NlIGRpZmZlcmVuY2VzIHdlcmUgYWN0dWFsbHkgY29taW5nIGZyb20gdGhlIHVuYmFsYW5jZWQgc3RhdGUgb2YKdGhlIHR3byBjbGluaWNzIGZyb20gdGhlIHBlcnNwZWN0aXZlIG9mIGNsaW5pYy4KCmBgYHtyIHZpZXdfY2xpbmljYWxfY2VsbF90eXBlX2NmfQpjbGluaWNhbF9jb25jYXRfbm9ybSA8LSBub3JtYWxpemVfZXhwdChjbGluaWNhbF9jb25jYXQsIHRyYW5zZm9ybSA9ICJsb2cyIiwgY29udmVydCA9ICJjcG0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3JtID0gInF1YW50IiwgZmlsdGVyID0gVFJVRSkKY2xpbmljYWxfY29uY2F0X25vcm1fcGNhIDwtIHBsb3RfcGNhKGNsaW5pY2FsX2NvbmNhdF9ub3JtKQpkZXYgPC0gcHAoZmlsZT1nbHVlKCJpbWFnZXMvY2xpbmljYWxfY29uY2F0ZW5hdGVkX25vcm1hbGl6ZWRfcGNhLXZ7dmVyfS5wbmciKSwgaGVpZ2h0PTYsIHdpZHRoPTEwKQpjbGluaWNhbF9jb25jYXRfbm9ybV9wY2EkcGxvdApjbG9zZWQgPC0gZGV2Lm9mZigpCmNsaW5pY2FsX2NvbmNhdF9ub3JtX3BjYSRwbG90CgpjbGluaWNhbF9jb25jYXRfbmIgPC0gbm9ybWFsaXplX2V4cHQoY2xpbmljYWxfY29uY2F0LCB0cmFuc2Zvcm0gPSAibG9nMiIsIGNvbnZlcnQgPSAiY3BtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhdGNoID0gInN2YXNlcSIsIGZpbHRlciA9IFRSVUUpCmNsaW5pY2FsX2NvbmNhdF9uYl9wY2EgPC0gcGxvdF9wY2EoY2xpbmljYWxfY29uY2F0X25iKQpkZXYgPC0gcHAoZmlsZT1nbHVlKCJpbWFnZXMvY2xpbmljYWxfY29uY2F0ZW5hdGVkX3N2YXNlcWJhdGNoX3BjYS12e3Zlcn0ucG5nIiksIGhlaWdodD02LCB3aWR0aD0xMikKY2xpbmljYWxfY29uY2F0X25iX3BjYSRwbG90CmNsb3NlZCA8LSBkZXYub2ZmKCkKY2xpbmljYWxfY29uY2F0X25iX3BjYSRwbG90CmBgYAoKIyBWaXNpdCBjb21wYXJpc29ucwoKTGV0IHVzIHNoaWZ0IHRoZSBmb2N1cyBmcm9tIGNlbGwgdHlwZSBhbmQvb3IgQ3VyZS9GYWlsIHRvIHRoZSB2aXNpdApudW1iZXIuICBBcyB5b3UgYXJlIGxpa2VseSBhd2FyZSwgdGhlIHRocmVlIHZpc2l0cyBhcmUgc2lnbmlmaWNhbnRseQpzcHJlYWQgYXBhcnQgYWNjb3JkaW5nIHRvIHRoZSBjbGluaWNhbCB0cmVhdG1lbnQgb2YgZWFjaCBwYXRpZW50LgpUaHVzIHdlIHdpbGwgbm93IHNlcGFyYXRlIHRoZSBzYW1wbGVzIGJ5IHZpc2l0IGluIG9yZGVyIHRvIG1vcmUgZWFzaWx5CnNlZSB3aGF0IG5ldyBwYXR0ZXJucyBlbWVyZ2UuCgojIyBSZWNhdGVnb3JpemU6IEFsbCB2aXNpdHMgdG9nZXRoZXIKCk5vdyBsZXQgdXMgc2hpZnQgdGhlIHZpZXcgc2xpZ2h0bHkgdG8gZm9jdXMgb24gY2hhbmdlcyBvYnNlcnZlZCBvdmVyIHRpbWUuCgpgYGB7ciBjb21wYXJlX2FsbF92aXNpdHN9CnZpc2l0X2V4cHQgPC0gc2V0X2V4cHRfY29uZGl0aW9ucyhjbGluaWNhbCwgZmFjdCA9ICJ2aXNpdG51bWJlciIpICU+JQogIHNldF9leHB0X2JhdGNoZXMoZmFjdCA9ICJjbGluaWNhbG91dGNvbWUiKSAlPiUKICBzdWJzZXRfZXhwdChzdWJzZXQ9InR5cGVvZmNlbGxzIT0nYmlvcHN5JyIpCgp2aXNpdF9ub3JtIDwtIG5vcm1hbGl6ZV9leHB0KHZpc2l0X2V4cHQsIHRyYW5zZm9ybT0ibG9nMiIsIGNvbnZlcnQ9ImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9ybT0icXVhbnQiLCBmaWx0ZXI9VFJVRSkKcGxvdF9wY2EodmlzaXRfbm9ybSkkcGxvdAp2aXNpdF9uYiA8LSBub3JtYWxpemVfZXhwdCh2aXNpdF9leHB0LCB0cmFuc2Zvcm0gPSAibG9nMiIsIGNvbnZlcnQ9ImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlciA9IFRSVUUsIGJhdGNoID0gInN2YXNlcSIpCnZpc2l0X25iX3BjYSA8LSBwbG90X3BjYSh2aXNpdF9uYikKZGV2IDwtIHBwKGZpbGU9Z2x1ZSgiaW1hZ2VzL3Zpc2l0X3N2YXNlcWJhdGNoX3BjYS12e3Zlcn0ucG5nIiksIGhlaWdodD03LCB3aWR0aD05KQp2aXNpdF9uYl9wY2EkcGxvdApjbG9zZWQgPC0gZGV2Lm9mZigpCnZpc2l0X25iX3BjYSRwbG90CmBgYAoKV2hlbiBsb29raW5nIGF0IGFsbCBjZWxsIHR5cGVzLCBpdCBpcyBxdWl0ZSBkaWZmaWN1bHQgdG8gc2VlCmRpZmZlcmVuY2VzIGFtb25nIHRoZSB0aHJlZSB2aXNpdHMuCgojIyBTdWJzZXQ6IFZpc2l0cyBieSBpbmRpdmlkdWFsIGNlbGwgdHlwZXMKCkluIHRoZSBwcmV2aW91cyBibG9jaywgdGhlIGRhdGEgd2FzIHJlY2F0ZWdvcml6ZWQgYnkgdmlzaXQsIG5vdyBsZXQgdXMKc3BsaXQgdGhhdCBkYXRhIGJ5IGNlbGwgdHlwZSBhbmQgc2VlIGlmIGRpZmZlcmVuY2VzIGFjcm9zcyB2aXNpdApiZWNvbWUgbW9yZSBldmlkZW50LgoKYGBge3IgY2VsbF90eXBlX3Zpc2l0c30KdmlzaXRfbW9ub2N5dGUgPC0gc3Vic2V0X2V4cHQodmlzaXRfZXhwdCwgc3Vic2V0ID0gInR5cGVvZmNlbGxzPT0nbW9ub2N5dGVzJyIpCnZpc2l0X25ldXRyb3BoaWwgPC0gc3Vic2V0X2V4cHQodmlzaXRfZXhwdCwgc3Vic2V0ID0gInR5cGVvZmNlbGxzPT0nbmV1dHJvcGhpbHMnIikKdmlzaXRfZW9zaW5vcGhpbCA8LSBzdWJzZXRfZXhwdCh2aXNpdF9leHB0LCBzdWJzZXQgPSAidHlwZW9mY2VsbHM9PSdlb3Npbm9waGlscyciKQpgYGAKCiMjIFZpc3VhbGl6ZTogQy9GIGZvciBvbmx5IHRoZSB2aXNpdCAxIHNhbXBsZXMKCldlbiB3ZSBoYWQgYm90aCBDYWxpIGFuZCBUdW1hY28gc2FtcGxlcywgaXQgbG9va2VkIGxpa2UgdGhlcmUgd2FzCnZhcmlhbmNlIHN1Z2dlc3RpbmcgZGlmZmVyZW5jZXMgYmV0d2VlbiBjdXJlIGFuZCBmYWlsIGZvciB2aXNpdCAxLiAgSQp0aGluayB0aGUgZm9sbG93aW5nIGJsb2NrIHdpbGwgc3VnZ2VzdCBwcmV0dHkgc3Ryb25nbHkgdGhhdCB0aGlzIHdhcwpub3QgdHJ1ZS4KCmBgYHtyIHZpc2l0MV9kYXRhfQp2MV9ub3JtIDwtIG5vcm1hbGl6ZV9leHB0KHYxX3NhbXBsZXMsIHRyYW5zZm9ybT0ibG9nMiIsIGNvbnZlcnQ9ImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgbm9ybT0icXVhbnQiLCBmaWx0ZXI9VFJVRSkKcGxvdF9wY2EodjFfbm9ybSkkcGxvdAp2MV9uYiA8LSBub3JtYWxpemVfZXhwdCh2MV9zYW1wbGVzLCB0cmFuc2Zvcm0gPSAibG9nMiIsIGNvbnZlcnQgPSAiY3BtIiwKICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyID0gVFJVRSwgYmF0Y2ggPSAic3Zhc2VxIikKcGxvdF9wY2EodjFfbmIsIHBsb3RfbGFiZWxzID0gRkFMU0UpJHBsb3QKYGBgCgojIyBWaXN1YWxpemU6IEMvRiBmb3Igb25seSB0aGUgdmlzaXQgMiBzYW1wbGVzCgpgYGB7ciB2aXNpdDJfZGF0YX0KdjJfY2xpbmljYWwgPC0gc3Vic2V0X2V4cHQodjJfc2FtcGxlcywgc3Vic2V0PSJ2aXNpdG51bWJlcj09JzInIikgJT4lCiAgc2V0X2V4cHRfY29uZGl0aW9ucyhmYWN0ID0gImNsaW5pY2Fsb3V0Y29tZSIpICU+JQogIHNldF9leHB0X2JhdGNoZXMoZmFjdCA9ICJ0eXBlb2ZjZWxscyIpCgp2Ml9uYiA8LSBub3JtYWxpemVfZXhwdCh2Ml9jbGluaWNhbCwgdHJhbnNmb3JtID0gImxvZzIiLCBjb252ZXJ0ID0gImNwbSIsIG5vcm0gPSAicXVhbnQiLAogICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXIgPSBUUlVFLCBiYXRjaCA9ICJzdmFzZXEiKQpwbG90X3BjYSh2Ml9uYiwgcGxvdF9sYWJlbHMgPSBGQUxTRSkkcGxvdApgYGAKCiMjIFZpc3VhbGl6ZTogQy9GIGZvciBvbmx5IHRoZSB2aXNpdCAzIHNhbXBsZXMKCmBgYHtyIHZpc2l0M19kYXRhfQp2M19jbGluaWNhbCA8LSBzdWJzZXRfZXhwdCh2M19zYW1wbGVzLCBzdWJzZXQ9InZpc2l0bnVtYmVyPT0nMyciKSAlPiUKICBzZXRfZXhwdF9jb25kaXRpb25zKGZhY3QgPSAiY2xpbmljYWxvdXRjb21lIikgJT4lCiAgc2V0X2V4cHRfYmF0Y2hlcyhmYWN0ID0gInR5cGVvZmNlbGxzIikKCnYzX25iIDwtIG5vcm1hbGl6ZV9leHB0KHYzX2NsaW5pY2FsLCB0cmFuc2Zvcm0gPSAibG9nMiIsIGNvbnZlcnQgPSAiY3BtIiwgbm9ybSA9ICJxdWFudCIsCiAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlciA9IFRSVUUsIGJhdGNoID0gInN2YXNlcSIpCnBsb3RfcGNhKHYzX25iLCBwbG90X2xhYmVscyA9IEZBTFNFKSRwbG90CmBgYAoKIyMjIFZpc3VhbGl6ZTogQ29tcGFyaW5nIDMgdmlzaXRzIGJ5IGNlbGwgdHlwZQoKU2VwYXJhdGUgdGhlIHNhbXBsZXMgYnkgY2VsbCB0eXBlIGluIG9yZGVyIHRvIG1vcmUgZWFzaWx5IG9ic2VydmUKcGF0dGVybnMgd2l0aCByZXNwZWN0IHRvIHZpc2l0IGFuZCBjbGluaWNhbCBvdXRjb21lLgoKIyMjIyBNb25vY3l0ZXMgYWNyb3NzIHZpc2l0cwoKYGBge3IgbW9ub2N5dGVfdmlzaXRfc2VwYXJhdGV9CnZpc2l0X21vbm9jeXRlX25vcm0gPC0gbm9ybWFsaXplX2V4cHQodmlzaXRfbW9ub2N5dGUsIG5vcm0gPSAicXVhbnQiLCBjb252ZXJ0ID0gImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtID0gImxvZzIiLCBmaWx0ZXIgPSBUUlVFKQp2aXNpdF9tb25vY3l0ZV9wY2EgPC0gcGxvdF9wY2EodmlzaXRfbW9ub2N5dGVfbm9ybSwgcGxvdF9sYWJlbHMgPSBGQUxTRSkKZGV2IDwtIHBwKGZpbGU9ImltYWdlcy92aXNpdF9tb25vY3l0ZXNfY2Zfbm9ybV9wY2EucG5nIikKdmlzaXRfbW9ub2N5dGVfcGNhJHBsb3QKY2xvc2VkIDwtIGRldi5vZmYoKQp2aXNpdF9tb25vY3l0ZV9wY2EkcGxvdAoKdmlzaXRfbW9ub2N5dGVfZGlzaGVhdCA8LSBwbG90X2Rpc2hlYXQodmlzaXRfbW9ub2N5dGVfbm9ybSkKZGV2IDwtIHBwKGZpbGU9ImltYWdlcy92aXNpdF9tb25vY3l0ZXNfY2Zfbm9ybV9kaXNoZWF0LnBuZyIpCnZpc2l0X21vbm9jeXRlX2Rpc2hlYXQkcGxvdApjbG9zZWQgPC0gZGV2Lm9mZigpCnZpc2l0X21vbm9jeXRlX2Rpc2hlYXQkcGxvdAoKdmlzaXRfbW9ub2N5dGVfbmIgPC0gbm9ybWFsaXplX2V4cHQodmlzaXRfbW9ub2N5dGUsIGNvbnZlcnQgPSAiY3BtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtID0gImxvZzIiLCBmaWx0ZXIgPSBUUlVFLCBiYXRjaCA9ICJzdmFzZXEiKQp2aXNpdF9tb25vY3l0ZV9uYl9wY2EgPC0gcGxvdF9wY2EodmlzaXRfbW9ub2N5dGVfbmIsIHBsb3RfbGFiZWxzID0gRkFMU0UpCmRldiA8LSBwcChmaWxlPSJpbWFnZXMvbW9ub2N5dGVzX2NmX25vcm1fc3ZhX3BjYS5wbmciKQp2aXNpdF9tb25vY3l0ZV9uYl9wY2EkcGxvdApjbG9zZWQgPC0gZGV2Lm9mZigpCm1vbm9jeXRlX25iX3BjYSRwbG90CmBgYAoKIyBDb250cmFzdHMgYW5kIGNvbG9ycyBvZiBpbnRlcmVzdAoKCmBgYHtyIGRlZmluZV9jb250cmFzdHN9CmNmX2NvbnRyYXN0cyA8LSBsaXN0KAogICAgImZhaWxfdnNfY3VyZSIgPSBjKCJmYWlsdXJlIiwgImN1cmUiKSkKdmlzaXRfY29udHJhc3RzIDwtIGxpc3QoCiAgICAidjJ2MSIgPSBjKCJjMiIsICJjMSIpLAogICAgInYzdjEiID0gYygiYzMiLCAiYzEiKSwKICAgICJ2M3YyIiA9IGMoImMzIiwgImMyIikpCnR5cGVfY29udHJhc3RzIDwtIGxpc3QoCiAgICAibW9ub19iaW9wc3kiID0gYygibW9ub2N5dGVzIiwgImJpb3BzeSIpLAogICAgImVvc2lub3BoaWxfYmlvcHN5IiA9IGMoImVvc2lub3BoaWxzIiwgImJpb3BzeSIpLAogICAgIm5ldXRyb3BoaWxfYmlvcHN5IiA9IGMoIm5ldXRyb3BoaWxzIiwgImJpb3BzeSIpKQp2aXNpdF9jZl9jb250cmFzdHMgPC0gbGlzdCgKICAgICJ2MWZhaWxfdnNfY3VyZSIgPSBjKCJ2MWZhaWx1cmUiLCAidjFjdXJlIiksCiAgICAidjJmYWlsX3ZzX2N1cmUiID0gYygidjJmYWlsdXJlIiwgInYyY3VyZSIpLAogICAgInYzZmFpbF92c19jdXJlIiA9IGMoInYzZmFpbHVyZSIsICJ2M2N1cmUiKSkKYGBgCgpTYW1wbGUgSURzIHN0YXJ0aW5nIHdpdGggMTogQ2FsaQogICAgICAgSURzIHN0YXJ0aW5nIHdpdGggMjogVHVtYWNvCgojIERpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2VzCgpUaGUgcHJpbWFyeSBnb2FsIGlzIHRvIGxlYXJuIGFib3V0IGN1cmUgdnMuIGZhaWwuCgojIyBDdXJlL0ZhaWwsIGFsbCBzYW1wbGVzCgpOb3cgbGV0IHVzIHN0YXJ0IHBlcmZvcm1pbmcgdGhlIHZhcmlvdXMgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24KYW5hbHlzZXMsIHN0YXJ0aW5nIHdpdGggdGhlIHNldCBvZiBhbGwvbW9zdCBjbGluaWNhbCBzYW1wbGVzLgoKYGBge3IgY2ZfYWxsX2RlfQpjZl9jbGluaWNhbF9kZSA8LSBhbGxfcGFpcndpc2UoY2xpbmljYWwsIG1vZGVsX2JhdGNoID0gInN2YXNlcSIsIGZpbHRlciA9IFRSVUUpCmNmX2NsaW5pY2FsX3RhYmxlcyA8LSBjb21iaW5lX2RlX3RhYmxlcygKICAgIGNmX2NsaW5pY2FsX2RlLAogICAga2VlcGVycyA9IGNmX2NvbnRyYXN0cywKICAgIGV4Y2VsID0gZ2x1ZTo6Z2x1ZSgiZXhjZWwvY2ZfY2xpbmljYWxfdGFibGVzLXZ7dmVyfS54bHN4IikpCmNmX2NsaW5pY2FsX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogICAgY2ZfY2xpbmljYWxfdGFibGVzLAogICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC9jZl9jbGluaWNhbF9zaWctdnt2ZXJ9Lnhsc3giKSkKYGBgCgojIyMgQnkgY2VsbCB0eXBlCgojIyMjIEN1cmUvRmFpbCwgQmlvcHNpZXMKCmBgYHtyIGNmX2Jpb3BzeV9kZX0KY2ZfYmlvcHN5X2RlIDwtIGFsbF9wYWlyd2lzZShiaW9wc3lfc2FtcGxlcywgbW9kZWxfYmF0Y2ggPSAic3Zhc2VxIiwgZmlsdGVyID0gVFJVRSkKY2ZfYmlvcHN5X3RhYmxlcyA8LSBjb21iaW5lX2RlX3RhYmxlcygKICAgIGNmX2Jpb3BzeV9kZSwKICAgIGtlZXBlcnMgPSBjZl9jb250cmFzdHMsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL2NmX2Jpb3BzeV90YWJsZXMtdnt2ZXJ9Lnhsc3giKSkKY2ZfYmlvcHN5X3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogICAgY2ZfYmlvcHN5X3RhYmxlcywKICAgIGV4Y2VsID0gZ2x1ZTo6Z2x1ZSgiZXhjZWwvY2ZfYmlvcHN5X3NpZy12e3Zlcn0ueGxzeCIpKQpgYGAKCiMjIyMgQ3VyZS9GYWlsLCBNb25vY3l0ZXMKCmBgYHtyIGNmX21vbm9jeXRlX2RlfQpjZl9tb25vY3l0ZV9zdmFfZGUgPC0gYWxsX3BhaXJ3aXNlKG1vbm9jeXRlX3NhbXBsZXMsIG1vZGVsX2JhdGNoID0gInN2YXNlcSIsIGZpbHRlciA9IFRSVUUpCmNmX21vbm9jeXRlX3N2YV90YWJsZXMgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgICBjZl9tb25vY3l0ZV9zdmFfZGUsCiAgICBrZWVwZXJzID0gY2ZfY29udHJhc3RzLAogICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC9jZl9tb25vY3l0ZV9zdmFfdGFibGVzLXZ7dmVyfS54bHN4IikpCmNmX21vbm9jeXRlX3N2YV9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICAgIGNmX21vbm9jeXRlX3N2YV90YWJsZXMsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL2NmX21vbm9jeXRlX3N2YV9zaWctdnt2ZXJ9Lnhsc3giKSkKCmNmX21vbm9jeXRlX2JhdGNodmlzaXRfZGUgPC0gYWxsX3BhaXJ3aXNlKG1vbm9jeXRlX3NhbXBsZXMsIG1vZGVsX2JhdGNoID0gVFJVRSwgZmlsdGVyID0gVFJVRSkKY2ZfbW9ub2N5dGVfYmF0Y2h2aXNpdF90YWJsZXMgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgICBjZl9tb25vY3l0ZV9iYXRjaHZpc2l0X2RlLAogICAga2VlcGVycyA9IGNmX2NvbnRyYXN0cywKICAgIGV4Y2VsID0gZ2x1ZTo6Z2x1ZSgiZXhjZWwvY2ZfbW9ub2N5dGVfYmF0Y2h2aXNpdF90YWJsZXMtdnt2ZXJ9Lnhsc3giKSkKY2ZfbW9ub2N5dGVfYmF0Y2h2aXNpdF9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICAgIGNmX21vbm9jeXRlX2JhdGNodmlzaXRfdGFibGVzLAogICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC9jZl9tb25vY3l0ZV9iYXRjaHZpc2l0X3NpZy12e3Zlcn0ueGxzeCIpKQpgYGAKCiMjIyMgQ3VyZS9GYWlsLCBvbmx5IHRoZSBUdW1hY28gc2FtcGxlcwoKYGBge3IgY2Zfb25seV9tb25vY3l0ZX0KY2ZfbW9ub2N5dGVfc3ZhX2RlIDwtIGFsbF9wYWlyd2lzZShtb25vY3l0ZSwgbW9kZWxfYmF0Y2ggPSAic3Zhc2VxIiwgZmlsdGVyID0gVFJVRSkKY2ZfbW9ub2N5dGVfc3ZhX3RhYmxlcyA8LSBjb21iaW5lX2RlX3RhYmxlcygKICAgIGNmX21vbm9jeXRlX3N2YV9kZSwKICAgIGtlZXBlcnMgPSBjZl9jb250cmFzdHMsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL2NmX21vbm9jeXRlX3RhYmxlc19zdmFfdHVtYWNvLXZ7dmVyfS54bHN4IikpCmNmX21vbm9jeXRlX3N2YV9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICAgIGNmX21vbm9jeXRlX3N2YV90YWJsZXMsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL2NmX21vbm9jeXRlX3N2YV9zaWctdnt2ZXJ9Lnhsc3giKSkKCmNmX21vbm9jeXRlX2JhdGNodmlzaXRfZGUgPC0gYWxsX3BhaXJ3aXNlKG1vbm9jeXRlLCBtb2RlbF9iYXRjaCA9IFRSVUUsIGZpbHRlciA9IFRSVUUpCmNmX21vbm9jeXRlX2JhdGNodmlzaXRfdGFibGVzIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogICAgY2ZfbW9ub2N5dGVfYmF0Y2h2aXNpdF9kZSwKICAgIGtlZXBlcnMgPSBjZl9jb250cmFzdHMsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL2NmX21vbm9jeXRlX3RhYmxlc19iYXRjaHZpc2l0X3R1bWFjby12e3Zlcn0ueGxzeCIpKQpjZl9tb25vY3l0ZV9iYXRjaHZpc2l0X3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogICAgY2ZfbW9ub2N5dGVfYmF0Y2h2aXNpdF90YWJsZXMsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL2NmX21vbm9jeXRlX2JhdGNodmlzaXRfc2lnLXZ7dmVyfS54bHN4IikpCgpzdmFfYXVjYyA8LSBjYWxjdWxhdGVfYXVjYyhjZl9tb25vY3l0ZV9zdmFfdGFibGVzW1siZGF0YSJdXVtbImZhaWxfdnNfY3VyZSJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRibDI9Y2ZfbW9ub2N5dGVfc3ZhX3RhYmxlc1tbImRhdGEiXV1bWyJmYWlsX3ZzX2N1cmUiXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBweT0iZGVzZXFfYWRqcCIsIGx5PSJkZXNlcV9sb2dmYyIpCnN2YV9hdWNjCgpzaGFyZWRfaWRzIDwtIHJvd25hbWVzKGNmX21vbm9jeXRlX3N2YV90YWJsZXNbWyJkYXRhIl1dW1siZmFpbF92c19jdXJlIl1dKSAlaW4lCiAgcm93bmFtZXMoY2ZfbW9ub2N5dGVfc3ZhX3RhYmxlc1tbImRhdGEiXV1bWyJmYWlsX3ZzX2N1cmUiXV0pCmZpcnN0IDwtIGNmX21vbm9jeXRlX3N2YV90YWJsZXNbWyJkYXRhIl1dW1siZmFpbF92c19jdXJlIl1dW3NoYXJlZF9pZHMsIF0Kc2Vjb25kIDwtIGNmX21vbm9jeXRlX3N2YV90YWJsZXNbWyJkYXRhIl1dW1siZmFpbF92c19jdXJlIl1dW3Jvd25hbWVzKGZpcnN0KSwgXQpjb3IudGVzdChmaXJzdFtbImRlc2VxX2xvZ2ZjIl1dLCBzZWNvbmRbWyJkZXNlcV9sb2dmYyJdXSkKCmJhdGNoX2F1Y2MgPC0gY2FsY3VsYXRlX2F1Y2MoY2ZfbW9ub2N5dGVfYmF0Y2h2aXNpdF90YWJsZXNbWyJkYXRhIl1dW1siZmFpbF92c19jdXJlIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGJsMj1jZl9tb25vY3l0ZV9iYXRjaHZpc2l0X3RhYmxlc1tbImRhdGEiXV1bWyJmYWlsX3ZzX2N1cmUiXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBweT0iZGVzZXFfYWRqcCIsIGx5PSJkZXNlcV9sb2dmYyIpCmJhdGNoX2F1Y2MKCnNoYXJlZF9pZHMgPC0gcm93bmFtZXMoY2ZfbW9ub2N5dGVfYmF0Y2h2aXNpdF90YWJsZXNbWyJkYXRhIl1dW1siZmFpbF92c19jdXJlIl1dKSAlaW4lCiAgcm93bmFtZXMoY2ZfbW9ub2N5dGVfYmF0Y2h2aXNpdF90YWJsZXNbWyJkYXRhIl1dW1siZmFpbF92c19jdXJlIl1dKQpmaXJzdCA8LSBjZl9tb25vY3l0ZV9iYXRjaHZpc2l0X3RhYmxlc1tbImRhdGEiXV1bWyJmYWlsX3ZzX2N1cmUiXV1bc2hhcmVkX2lkcywgXQpzZWNvbmQgPC0gY2ZfbW9ub2N5dGVfYmF0Y2h2aXNpdF90YWJsZXNbWyJkYXRhIl1dW1siZmFpbF92c19jdXJlIl1dW3Jvd25hbWVzKGZpcnN0KSwgXQpjb3IudGVzdChmaXJzdFtbImRlc2VxX2xvZ2ZjIl1dLCBzZWNvbmRbWyJkZXNlcV9sb2dmYyJdXSkKCmZpcnN0X3NpZ19uYW1lcyA8LSByb3duYW1lcyhjZl9tb25vY3l0ZV9iYXRjaHZpc2l0X3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1siZmFpbF92c19jdXJlIl1dKQpzZWNvbmRfc2lnX25hbWVzIDwtIHJvd25hbWVzKGNmX21vbm9jeXRlX2JhdGNodmlzaXRfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJmYWlsX3ZzX2N1cmUiXV0pCmJhdGNoX3Zlbm5fbHN0IDwtIGxpc3QoYWxsX2JhdGNoID0gZmlyc3Rfc2lnX25hbWVzLCBiYXRjaCA9IHNlY29uZF9zaWdfbmFtZXMpCmJhdGNoX3Zlbm4gPC0gVmVubmVyYWJsZTo6VmVubihiYXRjaF92ZW5uX2xzdCkKVmVubmVyYWJsZTo6cGxvdChiYXRjaF92ZW5uKQpgYGAKCmBgYHtyIG5ldXRyb3BoaWxfb25seX0KY2ZfbmV1dHJvcGhpbF9zdmFfZGUgPC0gYWxsX3BhaXJ3aXNlKG5ldXRyb3BoaWwsIG1vZGVsX2JhdGNoID0gInN2YXNlcSIsIGZpbHRlciA9IFRSVUUpCmNmX25ldXRyb3BoaWxfc3ZhX3RhYmxlcyA8LSBjb21iaW5lX2RlX3RhYmxlcygKICAgIGNmX25ldXRyb3BoaWxfc3ZhX2RlLAogICAga2VlcGVycyA9IGNmX2NvbnRyYXN0cywKICAgIGV4Y2VsID0gZ2x1ZTo6Z2x1ZSgiZXhjZWwvY2ZfbmV1dHJvcGhpbF90YWJsZXNfc3ZhX3R1bWFjby12e3Zlcn0ueGxzeCIpKQpjZl9uZXV0cm9waGlsX3N2YV9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICAgIGNmX25ldXRyb3BoaWxfc3ZhX3RhYmxlcywKICAgIGV4Y2VsID0gZ2x1ZTo6Z2x1ZSgiZXhjZWwvY2ZfbmV1dHJvcGhpbF9zdmFfc2lnLXZ7dmVyfS54bHN4IikpCgpjZl9uZXV0cm9waGlsX2JhdGNodmlzaXRfZGUgPC0gYWxsX3BhaXJ3aXNlKG5ldXRyb3BoaWwsIG1vZGVsX2JhdGNoID0gVFJVRSwgZmlsdGVyID0gVFJVRSkKY2ZfbmV1dHJvcGhpbF9iYXRjaHZpc2l0X3RhYmxlcyA8LSBjb21iaW5lX2RlX3RhYmxlcygKICAgIGNmX25ldXRyb3BoaWxfYmF0Y2h2aXNpdF9kZSwKICAgIGtlZXBlcnMgPSBjZl9jb250cmFzdHMsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL2NmX25ldXRyb3BoaWxfdGFibGVzX2JhdGNodmlzaXRfdHVtYWNvLXZ7dmVyfS54bHN4IikpCmNmX25ldXRyb3BoaWxfYmF0Y2h2aXNpdF9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICAgIGNmX25ldXRyb3BoaWxfYmF0Y2h2aXNpdF90YWJsZXMsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL2NmX25ldXRyb3BoaWxfYmF0Y2h2aXNpdF9zaWctdnt2ZXJ9Lnhsc3giKSkKCnN2YV9hdWNjIDwtIGNhbGN1bGF0ZV9hdWNjKGNmX25ldXRyb3BoaWxfc3ZhX3RhYmxlc1tbImRhdGEiXV1bWyJmYWlsX3ZzX2N1cmUiXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YmwyPWNmX25ldXRyb3BoaWxfc3ZhX3RhYmxlc1tbImRhdGEiXV1bWyJmYWlsX3ZzX2N1cmUiXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBweT0iZGVzZXFfYWRqcCIsIGx5PSJkZXNlcV9sb2dmYyIpCnN2YV9hdWNjCgpzaGFyZWRfaWRzIDwtIHJvd25hbWVzKGNmX25ldXRyb3BoaWxfc3ZhX3RhYmxlc1tbImRhdGEiXV1bWyJmYWlsX3ZzX2N1cmUiXV0pICVpbiUKICByb3duYW1lcyhjZl9uZXV0cm9waGlsX3N2YV90YWJsZXNbWyJkYXRhIl1dW1siZmFpbF92c19jdXJlIl1dKQpmaXJzdCA8LSBjZl9uZXV0cm9waGlsX3N2YV90YWJsZXNbWyJkYXRhIl1dW1siZmFpbF92c19jdXJlIl1dW3NoYXJlZF9pZHMsIF0Kc2Vjb25kIDwtIGNmX25ldXRyb3BoaWxfc3ZhX3RhYmxlc1tbImRhdGEiXV1bWyJmYWlsX3ZzX2N1cmUiXV1bcm93bmFtZXMoZmlyc3QpLCBdCmNvci50ZXN0KGZpcnN0W1siZGVzZXFfbG9nZmMiXV0sIHNlY29uZFtbImRlc2VxX2xvZ2ZjIl1dKQoKYmF0Y2hfYXVjYyA8LSBjYWxjdWxhdGVfYXVjYyhjZl9uZXV0cm9waGlsX2JhdGNodmlzaXRfdGFibGVzW1siZGF0YSJdXVtbImZhaWxfdnNfY3VyZSJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRibDI9Y2ZfbmV1dHJvcGhpbF9iYXRjaHZpc2l0X3RhYmxlc1tbImRhdGEiXV1bWyJmYWlsX3ZzX2N1cmUiXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBweT0iZGVzZXFfYWRqcCIsIGx5PSJkZXNlcV9sb2dmYyIpCmJhdGNoX2F1Y2MKCnNoYXJlZF9pZHMgPC0gcm93bmFtZXMoY2ZfbmV1dHJvcGhpbF9iYXRjaHZpc2l0X3RhYmxlc1tbImRhdGEiXV1bWyJmYWlsX3ZzX2N1cmUiXV0pICVpbiUKICByb3duYW1lcyhjZl9uZXV0cm9waGlsX2JhdGNodmlzaXRfdGFibGVzW1siZGF0YSJdXVtbImZhaWxfdnNfY3VyZSJdXSkKZmlyc3QgPC0gY2ZfbmV1dHJvcGhpbF9iYXRjaHZpc2l0X3RhYmxlc1tbImRhdGEiXV1bWyJmYWlsX3ZzX2N1cmUiXV1bc2hhcmVkX2lkcywgXQpzZWNvbmQgPC0gY2ZfbmV1dHJvcGhpbF9iYXRjaHZpc2l0X3RhYmxlc1tbImRhdGEiXV1bWyJmYWlsX3ZzX2N1cmUiXV1bcm93bmFtZXMoZmlyc3QpLCBdCmNvci50ZXN0KGZpcnN0W1siZGVzZXFfbG9nZmMiXV0sIHNlY29uZFtbImRlc2VxX2xvZ2ZjIl1dKQoKZmlyc3Rfc2lnX25hbWVzIDwtIHJvd25hbWVzKGNmX25ldXRyb3BoaWxfYmF0Y2h2aXNpdF9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbImZhaWxfdnNfY3VyZSJdXSkKc2Vjb25kX3NpZ19uYW1lcyA8LSByb3duYW1lcyhjZl9uZXV0cm9waGlsX2JhdGNodmlzaXRfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJmYWlsX3ZzX2N1cmUiXV0pCmJhdGNoX3Zlbm5fbHN0IDwtIGxpc3QoYWxsX2JhdGNoID0gZmlyc3Rfc2lnX25hbWVzLCBiYXRjaCA9IHNlY29uZF9zaWdfbmFtZXMpCmJhdGNoX3Zlbm4gPC0gVmVubmVyYWJsZTo6VmVubihiYXRjaF92ZW5uX2xzdCkKVmVubmVyYWJsZTo6cGxvdChiYXRjaF92ZW5uKQpgYGAKCmBgYHtyIGVvc2lub3BoaWxfb25seX0KY2ZfZW9zaW5vcGhpbF9zdmFfZGUgPC0gYWxsX3BhaXJ3aXNlKGVvc2lub3BoaWwsIG1vZGVsX2JhdGNoID0gInN2YXNlcSIsIGZpbHRlciA9IFRSVUUpCmNmX2Vvc2lub3BoaWxfc3ZhX3RhYmxlcyA8LSBjb21iaW5lX2RlX3RhYmxlcygKICAgIGNmX2Vvc2lub3BoaWxfc3ZhX2RlLAogICAga2VlcGVycyA9IGNmX2NvbnRyYXN0cywKICAgIGV4Y2VsID0gZ2x1ZTo6Z2x1ZSgiZXhjZWwvY2ZfZW9zaW5vcGhpbF90YWJsZXNfc3ZhX3R1bWFjby12e3Zlcn0ueGxzeCIpKQpjZl9lb3Npbm9waGlsX3N2YV9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICAgIGNmX2Vvc2lub3BoaWxfc3ZhX3RhYmxlcywKICAgIGV4Y2VsID0gZ2x1ZTo6Z2x1ZSgiZXhjZWwvY2ZfZW9zaW5vcGhpbF9zdmFfc2lnLXZ7dmVyfS54bHN4IikpCgpjZl9lb3Npbm9waGlsX2JhdGNodmlzaXRfZGUgPC0gYWxsX3BhaXJ3aXNlKGVvc2lub3BoaWwsIG1vZGVsX2JhdGNoID0gVFJVRSwgZmlsdGVyID0gVFJVRSkKY2ZfZW9zaW5vcGhpbF9iYXRjaHZpc2l0X3RhYmxlcyA8LSBjb21iaW5lX2RlX3RhYmxlcygKICAgIGNmX2Vvc2lub3BoaWxfYmF0Y2h2aXNpdF9kZSwKICAgIGtlZXBlcnMgPSBjZl9jb250cmFzdHMsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL2NmX2Vvc2lub3BoaWxfdGFibGVzX2JhdGNodmlzaXRfdHVtYWNvLXZ7dmVyfS54bHN4IikpCmNmX2Vvc2lub3BoaWxfYmF0Y2h2aXNpdF9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICAgIGNmX2Vvc2lub3BoaWxfYmF0Y2h2aXNpdF90YWJsZXMsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL2NmX2Vvc2lub3BoaWxfYmF0Y2h2aXNpdF9zaWctdnt2ZXJ9Lnhsc3giKSkKCnN2YV9hdWNjIDwtIGNhbGN1bGF0ZV9hdWNjKGNmX2Vvc2lub3BoaWxfc3ZhX3RhYmxlc1tbImRhdGEiXV1bWyJmYWlsX3ZzX2N1cmUiXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YmwyPWNmX2Vvc2lub3BoaWxfc3ZhX3RhYmxlc1tbImRhdGEiXV1bWyJmYWlsX3ZzX2N1cmUiXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBweT0iZGVzZXFfYWRqcCIsIGx5PSJkZXNlcV9sb2dmYyIpCnN2YV9hdWNjCgpzaGFyZWRfaWRzIDwtIHJvd25hbWVzKGNmX2Vvc2lub3BoaWxfc3ZhX3RhYmxlc1tbImRhdGEiXV1bWyJmYWlsX3ZzX2N1cmUiXV0pICVpbiUKICByb3duYW1lcyhjZl9lb3Npbm9waGlsX3N2YV90YWJsZXNbWyJkYXRhIl1dW1siZmFpbF92c19jdXJlIl1dKQpmaXJzdCA8LSBjZl9lb3Npbm9waGlsX3N2YV90YWJsZXNbWyJkYXRhIl1dW1siZmFpbF92c19jdXJlIl1dW3NoYXJlZF9pZHMsIF0Kc2Vjb25kIDwtIGNmX2Vvc2lub3BoaWxfc3ZhX3RhYmxlc1tbImRhdGEiXV1bWyJmYWlsX3ZzX2N1cmUiXV1bcm93bmFtZXMoZmlyc3QpLCBdCmNvci50ZXN0KGZpcnN0W1siZGVzZXFfbG9nZmMiXV0sIHNlY29uZFtbImRlc2VxX2xvZ2ZjIl1dKQoKYmF0Y2hfYXVjYyA8LSBjYWxjdWxhdGVfYXVjYyhjZl9lb3Npbm9waGlsX2JhdGNodmlzaXRfdGFibGVzW1siZGF0YSJdXVtbImZhaWxfdnNfY3VyZSJdXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRibDI9Y2ZfZW9zaW5vcGhpbF9iYXRjaHZpc2l0X3RhYmxlc1tbImRhdGEiXV1bWyJmYWlsX3ZzX2N1cmUiXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBweT0iZGVzZXFfYWRqcCIsIGx5PSJkZXNlcV9sb2dmYyIpCmJhdGNoX2F1Y2MKCnNoYXJlZF9pZHMgPC0gcm93bmFtZXMoY2ZfZW9zaW5vcGhpbF9iYXRjaHZpc2l0X3RhYmxlc1tbImRhdGEiXV1bWyJmYWlsX3ZzX2N1cmUiXV0pICVpbiUKICByb3duYW1lcyhjZl9lb3Npbm9waGlsX2JhdGNodmlzaXRfdGFibGVzW1siZGF0YSJdXVtbImZhaWxfdnNfY3VyZSJdXSkKZmlyc3QgPC0gY2ZfZW9zaW5vcGhpbF9iYXRjaHZpc2l0X3RhYmxlc1tbImRhdGEiXV1bWyJmYWlsX3ZzX2N1cmUiXV1bc2hhcmVkX2lkcywgXQpzZWNvbmQgPC0gY2ZfZW9zaW5vcGhpbF9iYXRjaHZpc2l0X3RhYmxlc1tbImRhdGEiXV1bWyJmYWlsX3ZzX2N1cmUiXV1bcm93bmFtZXMoZmlyc3QpLCBdCmNvci50ZXN0KGZpcnN0W1siZGVzZXFfbG9nZmMiXV0sIHNlY29uZFtbImRlc2VxX2xvZ2ZjIl1dKQoKZmlyc3Rfc2lnX25hbWVzIDwtIHJvd25hbWVzKGNmX2Vvc2lub3BoaWxfYmF0Y2h2aXNpdF9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbImZhaWxfdnNfY3VyZSJdXSkKc2Vjb25kX3NpZ19uYW1lcyA8LSByb3duYW1lcyhjZl9lb3Npbm9waGlsX2JhdGNodmlzaXRfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJmYWlsX3ZzX2N1cmUiXV0pCmJhdGNoX3Zlbm5fbHN0IDwtIGxpc3QoYWxsX2JhdGNoID0gZmlyc3Rfc2lnX25hbWVzLCBiYXRjaCA9IHNlY29uZF9zaWdfbmFtZXMpCmJhdGNoX3Zlbm4gPC0gVmVubmVyYWJsZTo6VmVubihiYXRjaF92ZW5uX2xzdCkKVmVubmVyYWJsZTo6cGxvdChiYXRjaF92ZW5uKQpgYGAKCiMjIyMgQ29tcGFyZSBtb25vY3l0ZSBDRiwgbmV1dHJvcGhpbCBDRiwgZW9zaW5vcGhpbCBDRgoKYGBge3IgY29tcGFyZV9tb25vX25ldXRfZW99CgpgYGAKCiMjIyMgQ3VyZS9GYWlsLCBOZXV0cm9waGlscwoKYGBge3IgY2ZfbmV1dHJvcGhpbF9kZX0KY2ZfbmV1dHJvcGhpbF9kZSA8LSBhbGxfcGFpcndpc2UobmV1dHJvcGhpbF9zYW1wbGVzLCBtb2RlbF9iYXRjaCA9ICJzdmFzZXEiLCBmaWx0ZXIgPSBUUlVFKQpjZl9uZXV0cm9waGlsX3RhYmxlcyA8LSBjb21iaW5lX2RlX3RhYmxlcygKICAgIGNmX25ldXRyb3BoaWxfZGUsCiAgICBrZWVwZXJzID0gY2ZfY29udHJhc3RzLAogICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC9jZl9uZXV0cm9waGlsX3RhYmxlcy12e3Zlcn0ueGxzeCIpKQpjZl9uZXV0cm9waGlsX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogICAgY2ZfbmV1dHJvcGhpbF90YWJsZXMsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL2NmX25ldXRyb3BoaWxfc2lnLXZ7dmVyfS54bHN4IikpCmBgYAoKIyMjIyBDdXJlL0ZhaWwsIEVvc2lub3BoaWxzCgpgYGB7ciBjZl9lb3Npbm9waGlsX2RlfQpjZl9lb3Npbm9waGlsX2RlIDwtIGFsbF9wYWlyd2lzZShlb3Npbm9waGlsX3NhbXBsZXMsIG1vZGVsX2JhdGNoID0gInN2YXNlcSIsIGZpbHRlciA9IFRSVUUpCmNmX2Vvc2lub3BoaWxfdGFibGVzIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogICAgY2ZfZW9zaW5vcGhpbF9kZSwKICAgIGtlZXBlcnMgPSBjZl9jb250cmFzdHMsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL2NmX2Vvc2lub3BoaWxfdGFibGVzLXZ7dmVyfS54bHN4IikpCmNmX2Vvc2lub3BoaWxfc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgICBjZl9lb3Npbm9waGlsX3RhYmxlcywKICAgIGV4Y2VsID0gZ2x1ZTo6Z2x1ZSgiZXhjZWwvY2ZfZW9zaW5vcGhpbF9zaWctdnt2ZXJ9Lnhsc3giKSkKYGBgCgojIyMjIEN1cmUvRmFpbCBjbGluaWNhbCAoTm90IGJpb3BzaWVzKQoKYGBge3IgY2Zfbm9iaW9wc3lfZGV9CmNmX25vYmlvcHN5X2RlIDwtIGFsbF9wYWlyd2lzZShjbGluaWNhbF9ub2Jpb3AsIG1vZGVsX2JhdGNoID0gInN2YXNlcSIsIGZpbHRlciA9IFRSVUUpCmNmX25vYmlvcHN5X3RhYmxlcyA8LSBjb21iaW5lX2RlX3RhYmxlcygKICAgIGNmX25vYmlvcHN5X2RlLAogICAga2VlcGVycyA9IGNmX2NvbnRyYXN0cywKICAgIGV4Y2VsID0gZ2x1ZTo6Z2x1ZSgiZXhjZWwvY2Zfbm9iaW9wc3lfdGFibGVzLXZ7dmVyfS54bHN4IikpCmNmX25vYmlvcHN5X3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogICAgY2Zfbm9iaW9wc3lfdGFibGVzLAogICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC9jZl9ub2Jpb3BzeV9zaWctdnt2ZXJ9Lnhsc3giKSkKYGBgCgojIyMgQnkgdmlzaXQKCkZvciB0aGVzZSBjb250cmFzdHMsIHdlIHdhbnQgdG8gc2VlIGZhaWxfdjEgdnMuIGN1cmVfdjEsIGZhaWxfdjIKdnMuIGN1cmVfdjIgZXRjLiAgQXMgYSByZXN1bHQsIHdlIHdpbGwgbmVlZCB0byBqdWdnbGUgdGhlIGRhdGEKc2xpZ2h0bHkgYW5kIGFkZCBhbm90aGVyIHNldCBvZiBjb250cmFzdHMuCgojIyMgU2V0dGluZyB1cAoKYGBge3Igc2V0dXBfdmlzaXRfY2ZfZGF0YV9jb250cmFzdHN9CnZpc2l0X2NmX2V4cHRfZmFjdG9yIDwtIHBhc3RlMCgidiIsIHBEYXRhKGNsaW5pY2FsKVtbInZpc2l0bnVtYmVyIl1dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcERhdGEoY2xpbmljYWwpW1siY29uZGl0aW9uIl1dKQp2aXNpdF9jZl9leHB0IDwtIHNldF9leHB0X2NvbmRpdGlvbnMoY2xpbmljYWwsIGZhY3QgPSB2aXNpdF9jZl9leHB0X2ZhY3RvcikKCnZpc2l0X2NmX2Vvc2lub3BoaWwgPC0gc3Vic2V0X2V4cHQodmlzaXRfY2ZfZXhwdCwgc3Vic2V0PSJ0eXBlb2ZjZWxscz09J2Vvc2lub3BoaWxzJyIpCnZpc2l0X2NmX2Vvc2lub3BoaWwgPC0gc3Vic2V0X2V4cHQodmlzaXRfY2ZfZW9zaW5vcGhpbCwgc3Vic2V0PSJjbGluaWM9PSdUdW1hY28nIikKdmlzaXRfY2ZfbW9ub2N5dGUgPC0gc3Vic2V0X2V4cHQodmlzaXRfY2ZfZXhwdCwgc3Vic2V0PSJ0eXBlb2ZjZWxscz09J21vbm9jeXRlcyciKQp2aXNpdF9jZl9tb25vY3l0ZSA8LSBzdWJzZXRfZXhwdCh2aXNpdF9jZl9tb25vY3l0ZSwgc3Vic2V0PSJjbGluaWM9PSdUdW1hY28nIikKdmlzaXRfY2ZfbmV1dHJvcGhpbCA8LSBzdWJzZXRfZXhwdCh2aXNpdF9jZl9leHB0LCBzdWJzZXQ9InR5cGVvZmNlbGxzPT0nbmV1dHJvcGhpbHMnIikKdmlzaXRfY2ZfbmV1dHJvcGhpbCA8LSBzdWJzZXRfZXhwdCh2aXNpdF9jZl9uZXV0cm9waGlsLCBzdWJzZXQ9ImNsaW5pYz09J1R1bWFjbyciKQpgYGAKCiMjIyMgQ3VyZS9GYWlsIGJ5IHZpc2l0cywgYWxsIGNlbGwgdHlwZXMKCmBgYHtyIHZpc2l0X2NmX2FsbF9kZX0KdmlzaXRfY2ZfYWxsX2RlIDwtIGFsbF9wYWlyd2lzZSh2aXNpdF9jZl9leHB0LCBtb2RlbF9iYXRjaCA9ICJzdmFzZXEiLCBmaWx0ZXIgPSBUUlVFKQp2aXNpdF9jZl9hbGxfdGFibGVzIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogICAgdmlzaXRfY2ZfYWxsX2RlLAogICAga2VlcGVycyA9IHZpc2l0X2NmX2NvbnRyYXN0cywKICAgIGV4Y2VsID0gZ2x1ZTo6Z2x1ZSgiZXhjZWwvdmlzaXRfY2ZfYWxsX3RhYmxlcy12e3Zlcn0ueGxzeCIpKQp2aXNpdF9jZl9hbGxfc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgICB2aXNpdF9jZl9hbGxfdGFibGVzLAogICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC92aXNpdF9jZl9hbGxfc2lnLXZ7dmVyfS54bHN4IikpCmBgYAoKIyMjIyBDdXJlL0ZhaWwgYnkgdmlzaXQsIE1vbm9jeXRlcwoKYGBge3IgdmlzaXRfY2ZfbW9ub2N5dGVfZGV9CnZpc2l0X2NmX21vbm9jeXRlX2RlIDwtIGFsbF9wYWlyd2lzZSh2aXNpdF9jZl9tb25vY3l0ZSwgbW9kZWxfYmF0Y2ggPSAic3Zhc2VxIiwgZmlsdGVyID0gVFJVRSkKdmlzaXRfY2ZfbW9ub2N5dGVfdGFibGVzIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogICAgdmlzaXRfY2ZfbW9ub2N5dGVfZGUsCiAgICBrZWVwZXJzID0gdmlzaXRfY2ZfY29udHJhc3RzLAogICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC92aXNpdF9jZl9tb25vY3l0ZV90YWJsZXMtdnt2ZXJ9Lnhsc3giKSkKdmlzaXRfY2ZfbW9ub2N5dGVfc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgICB2aXNpdF9jZl9tb25vY3l0ZV90YWJsZXMsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL3Zpc2l0X2NmX21vbm9jeXRlX3NpZy12e3Zlcn0ueGxzeCIpKQoKdjFmY19kZXNlcV9tYSA8LSB2aXNpdF9jZl9tb25vY3l0ZV90YWJsZXNbWyJwbG90cyJdXVtbInYxZmFpbF92c19jdXJlIl1dW1siZGVzZXFfbWFfcGxvdHMiXV1bWyJwbG90Il1dCmRldiA8LSBwcChmaWxlPSJpbWFnZXMvbW9ub2N5dGVfY2ZfZGVfdjFfbWFwbG90LnBuZyIpCnYxZmNfZGVzZXFfbWEKY2xvc2VkIDwtIGRldi5vZmYoKQp2MWZjX2Rlc2VxX21hCgp2MmZjX2Rlc2VxX21hIDwtIHZpc2l0X2NmX21vbm9jeXRlX3RhYmxlc1tbInBsb3RzIl1dW1sidjJmYWlsX3ZzX2N1cmUiXV1bWyJkZXNlcV9tYV9wbG90cyJdXVtbInBsb3QiXV0KZGV2IDwtIHBwKGZpbGU9ImltYWdlcy9tb25vY3l0ZV9jZl9kZV92Ml9tYXBsb3QucG5nIikKdjJmY19kZXNlcV9tYQpjbG9zZWQgPC0gZGV2Lm9mZigpCnYyZmNfZGVzZXFfbWEKCnYzZmNfZGVzZXFfbWEgPC0gdmlzaXRfY2ZfbW9ub2N5dGVfdGFibGVzW1sicGxvdHMiXV1bWyJ2M2ZhaWxfdnNfY3VyZSJdXVtbImRlc2VxX21hX3Bsb3RzIl1dW1sicGxvdCJdXQpkZXYgPC0gcHAoZmlsZT0iaW1hZ2VzL21vbm9jeXRlX2NmX2RlX3YzX21hcGxvdC5wbmciKQp2M2ZjX2Rlc2VxX21hCmNsb3NlZCA8LSBkZXYub2ZmKCkKdjNmY19kZXNlcV9tYQoKIyMgUmVwZWF0IGZvciB0aGUgdHVtYWNvIHN1YnNldAp2aXNpdF9jZl9tb25vY3l0ZV9kZSA8LSBhbGxfcGFpcndpc2UodmlzaXRfY2ZfbW9ub2N5dGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGVsX2JhdGNoID0gInN2YXNlcSIsIGZpbHRlciA9IFRSVUUpCnZpc2l0X2NmX21vbm9jeXRlX3RhYmxlcyA8LSBjb21iaW5lX2RlX3RhYmxlcygKICAgIHZpc2l0X2NmX21vbm9jeXRlX2RlLAogICAga2VlcGVycyA9IHZpc2l0X2NmX2NvbnRyYXN0cywKICAgIGV4Y2VsID0gZ2x1ZTo6Z2x1ZSgiZXhjZWwvdmlzaXRfY2ZfbW9ub2N5dGVfdGFibGVzLXZ7dmVyfS54bHN4IikpCnZpc2l0X2NmX21vbm9jeXRlX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogICAgdmlzaXRfY2ZfbW9ub2N5dGVfdGFibGVzLAogICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC92aXNpdF9jZl9tb25vY3l0ZV9zaWctdnt2ZXJ9Lnhsc3giKSkKYGBgCgpPbmUgcXVlcnkgZnJvbSBBbGVqYW5kcm8gaXMgdG8gbG9vayBhdCB0aGUgZ2VuZXMgc2hhcmVkIHVwL2Rvd24gYWNyb3NzCnZpc2l0cy4gIEkgYW0gbm90IGVudGlyZWx5IGNlcnRhaW4gd2UgaGF2ZSBlbm91Z2ggc2FtcGxlcyBmb3IgdGhpcyB0bwp3b3JrLCBidXQgbGV0IHVzIGZpbmQgb3V0LgoKSSBhbSB0aGlua2luZyB0aGlzIGlzIGEgZ29vZCBwbGFjZSB0byB1c2UgdGhlIEFVQ0MgY3VydmVzIEkgbGVhcm5lZAphYm91dCB0aGFua3MgdG8gSnVsaWUgQ3JpZGxhbmQuCgpOb3RlIHRoYXQgdGhlIGZvbGxvd2luZyBpcyBhbGwgbW9ub2N5dGUgc2FtcGxlcywgdGhpcyBzaG91bGQgdGhlcmVmb3JlCnBvdGVudGlhbGx5IGJlIG1vdmVkIHVwIGFuZCBhIHZlcnNpb24gb2YgdGhpcyB3aXRoIG9ubHkgdGhlIFR1bWFjbwpzYW1wbGVzIHB1dCBoZXJlPwoKYGBge3IgbW9ub2N5dGVfc2hhcmVkX2RlX2dlbmVzfQp2MWZjIDwtIHZpc2l0X2NmX21vbm9jeXRlX3RhYmxlc1tbImRhdGEiXV1bWyJ2MWZhaWxfdnNfY3VyZSJdXQp2MmZjIDwtIHZpc2l0X2NmX21vbm9jeXRlX3RhYmxlc1tbImRhdGEiXV1bWyJ2MmZhaWxfdnNfY3VyZSJdXQp2M2ZjIDwtIHZpc2l0X2NmX21vbm9jeXRlX3RhYmxlc1tbImRhdGEiXV1bWyJ2M2ZhaWxfdnNfY3VyZSJdXQoKdjFfc2lnIDwtIGMoCiAgICByb3duYW1lcyh2aXNpdF9jZl9tb25vY3l0ZV9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbInYxZmFpbF92c19jdXJlIl1dKSwKICAgIHJvd25hbWVzKHZpc2l0X2NmX21vbm9jeXRlX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV1bWyJ2MWZhaWxfdnNfY3VyZSJdXSkpCnYyX3NpZyA8LSBjKAogICAgcm93bmFtZXModmlzaXRfY2ZfbW9ub2N5dGVfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJ2MmZhaWxfdnNfY3VyZSJdXSksCiAgICByb3duYW1lcyh2aXNpdF9jZl9tb25vY3l0ZV9zaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dW1sidjJmYWlsX3ZzX2N1cmUiXV0pKQp2M19zaWcgPC0gYygKICAgIHJvd25hbWVzKHZpc2l0X2NmX21vbm9jeXRlX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1sidjJmYWlsX3ZzX2N1cmUiXV0pLAogICAgcm93bmFtZXModmlzaXRfY2ZfbW9ub2N5dGVfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbInYyZmFpbF92c19jdXJlIl1dKSkKCm1vbm9jeXRlX3Zpc2l0X2F1Y2NfdjJ2MSA8LSBjYWxjdWxhdGVfYXVjYyh2MWZjLCB0YmwyPXYyZmMsIHB5PSJkZXNlcV9hZGpwIiwgbHk9ImRlc2VxX2xvZ2ZjIikKZGV2IDwtIHBwKGZpbGU9ImltYWdlcy9tb25vY3l0ZV92aXNpdF92MnYxX2F1Y2MucG5nIikKbW9ub2N5dGVfdmlzaXRfYXVjY192MnYxW1sicGxvdCJdXQpjbG9zZWQgPC0gZGV2Lm9mZigpCm1vbm9jeXRlX3Zpc2l0X2F1Y2NfdjJ2MVtbInBsb3QiXV0KCm1vbm9jeXRlX3Zpc2l0X2F1Y2NfdjN2MSA8LSBjYWxjdWxhdGVfYXVjYyh2MWZjLCB0YmwyPXYzZmMsIHB5PSJkZXNlcV9hZGpwIiwgbHk9ImRlc2VxX2xvZ2ZjIikKZGV2IDwtIHBwKGZpbGU9ImltYWdlcy9tb25vY3l0ZV92aXNpdF92M3YxX2F1Y2MucG5nIikKbW9ub2N5dGVfdmlzaXRfYXVjY192M3YxW1sicGxvdCJdXQpjbG9zZWQgPC0gZGV2Lm9mZigpCm1vbm9jeXRlX3Zpc2l0X2F1Y2NfdjN2MVtbInBsb3QiXV0KYGBgCgojIyMjIFJlcGVhdCBmb3Igb25seSB0aGUgVHVtYWNvIHNhbXBsZXMKCmBgYHtyIGF1Y2NfdXBzZXRfdHVtYWNvfQp2MWZjX3R1bWFjbyA8LSB2aXNpdF9jZl9tb25vY3l0ZV90YWJsZXNbWyJkYXRhIl1dW1sidjFmYWlsX3ZzX2N1cmUiXV0KdjJmY190dW1hY28gPC0gdmlzaXRfY2ZfbW9ub2N5dGVfdGFibGVzW1siZGF0YSJdXVtbInYyZmFpbF92c19jdXJlIl1dCnYzZmNfdHVtYWNvIDwtIHZpc2l0X2NmX21vbm9jeXRlX3RhYmxlc1tbImRhdGEiXV1bWyJ2M2ZhaWxfdnNfY3VyZSJdXQoKdjFfc2lnIDwtIGMoCiAgICByb3duYW1lcyh2aXNpdF9jZl9tb25vY3l0ZV9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbInYxZmFpbF92c19jdXJlIl1dKSwKICAgIHJvd25hbWVzKHZpc2l0X2NmX21vbm9jeXRlX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV1bWyJ2MWZhaWxfdnNfY3VyZSJdXSkpCnYyX3NpZyA8LSBjKAogICAgcm93bmFtZXModmlzaXRfY2ZfbW9ub2N5dGVfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJ2MmZhaWxfdnNfY3VyZSJdXSksCiAgICByb3duYW1lcyh2aXNpdF9jZl9tb25vY3l0ZV9zaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dW1sidjJmYWlsX3ZzX2N1cmUiXV0pKQp2M19zaWcgPC0gYygKICAgIHJvd25hbWVzKHZpc2l0X2NmX21vbm9jeXRlX3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1sidjJmYWlsX3ZzX2N1cmUiXV0pLAogICAgcm93bmFtZXModmlzaXRfY2ZfbW9ub2N5dGVfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbInYyZmFpbF92c19jdXJlIl1dKSkKCm1vbm9jeXRlX3Zpc2l0X2F1Y2NfdjJ2MSA8LSBjYWxjdWxhdGVfYXVjYyh2MWZjX3R1bWFjbywgdGJsMj12MmZjX3R1bWFjbywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBweT0iZGVzZXFfYWRqcCIsIGx5PSJkZXNlcV9sb2dmYyIpCmRldiA8LSBwcChmaWxlPSJpbWFnZXMvbW9ub2N5dGVfdmlzaXRfdjJ2MV9hdWNjLnBuZyIpCm1vbm9jeXRlX3Zpc2l0X2F1Y2NfdjJ2MVtbInBsb3QiXV0KY2xvc2VkIDwtIGRldi5vZmYoKQptb25vY3l0ZV92aXNpdF9hdWNjX3YydjFbWyJwbG90Il1dCgptb25vY3l0ZV92aXNpdF9hdWNjX3YzdjEgPC0gY2FsY3VsYXRlX2F1Y2ModjFmY190dW1hY28sIHRibDI9djNmY190dW1hY28sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHk9ImRlc2VxX2FkanAiLCBseT0iZGVzZXFfbG9nZmMiKQpkZXYgPC0gcHAoZmlsZT0iaW1hZ2VzL21vbm9jeXRlX3Zpc2l0X3YzdjFfYXVjYy5wbmciKQptb25vY3l0ZV92aXNpdF9hdWNjX3YzdjFbWyJwbG90Il1dCmNsb3NlZCA8LSBkZXYub2ZmKCkKbW9ub2N5dGVfdmlzaXRfYXVjY192M3YxW1sicGxvdCJdXQoKbW9ub2N5dGVfdmlzaXRfYXVjY192M3YyIDwtIGNhbGN1bGF0ZV9hdWNjKHYzZmNfdHVtYWNvLCB0YmwyPXYyZmNfdHVtYWNvLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB5PSJkZXNlcV9hZGpwIiwgbHk9ImRlc2VxX2xvZ2ZjIikKZGV2IDwtIHBwKGZpbGU9ImltYWdlcy9tb25vY3l0ZV92aXNpdF92M3YyX2F1Y2MucG5nIikKbW9ub2N5dGVfdmlzaXRfYXVjY192M3YyW1sicGxvdCJdXQpjbG9zZWQgPC0gZGV2Lm9mZigpCm1vbm9jeXRlX3Zpc2l0X2F1Y2NfdjN2MltbInBsb3QiXV0KYGBgCgojIyMjIEN1cmUvRmFpbCBieSB2aXNpdCwgTmV1dHJvcGhpbHMKYQpgYGB7ciB2aXNpdF9jZl9uZXV0cm9waGlsX2RlfQp2aXNpdF9jZl9uZXV0cm9waGlsX2RlIDwtIGFsbF9wYWlyd2lzZSh2aXNpdF9jZl9uZXV0cm9waGlsLCBtb2RlbF9iYXRjaCA9ICJzdmFzZXEiLCBmaWx0ZXIgPSBUUlVFKQp2aXNpdF9jZl9uZXV0cm9waGlsX3RhYmxlcyA8LSBjb21iaW5lX2RlX3RhYmxlcygKICAgIHZpc2l0X2NmX25ldXRyb3BoaWxfZGUsCiAgICBrZWVwZXJzID0gdmlzaXRfY2ZfY29udHJhc3RzLAogICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC92aXNpdF9jZl9uZXV0cm9waGlsX3RhYmxlcy12e3Zlcn0ueGxzeCIpKQp2aXNpdF9jZl9uZXV0cm9waGlsX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogICAgdmlzaXRfY2ZfbmV1dHJvcGhpbF90YWJsZXMsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL3Zpc2l0X2NmX25ldXRyb3BoaWxfc2lnLXZ7dmVyfS54bHN4IikpCmBgYAoKIyMjIyBDdXJlL0ZhaWwgYnkgdmlzaXQsIEVvc2lub3BoaWxzCgpgYGB7ciB2aXNpdF9jZl9lb3Npbm9waGlsX2RlfQp2aXNpdF9jZl9lb3Npbm9waGlsX2RlIDwtIGFsbF9wYWlyd2lzZSh2aXNpdF9jZl9lb3Npbm9waGlsLCBtb2RlbF9iYXRjaCA9ICJzdmFzZXEiLCBmaWx0ZXIgPSBUUlVFKQp2aXNpdF9jZl9lb3Npbm9waGlsX3RhYmxlcyA8LSBjb21iaW5lX2RlX3RhYmxlcygKICAgIHZpc2l0X2NmX2Vvc2lub3BoaWxfZGUsCiAgICBrZWVwZXJzID0gdmlzaXRfY2ZfY29udHJhc3RzLAogICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC92aXNpdF9jZl9lb3Npbm9waGlsX3RhYmxlcy12e3Zlcn0ueGxzeCIpKQp2aXNpdF9jZl9lb3Npbm9waGlsX3NpZyA8LSBleHRyYWN0X3NpZ25pZmljYW50X2dlbmVzKAogICAgdmlzaXRfY2ZfZW9zaW5vcGhpbF90YWJsZXMsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL3Zpc2l0X2NmX2Vvc2lub3BoaWxfc2lnLXZ7dmVyfS54bHN4IikpCmBgYAoKIyMgUGVyc2lzdGVuY2UgaW4gdmlzaXQgMwoKSGF2aW5nIHB1dCBzb21lIFNMIHJlYWQgbWFwcGluZyBpbmZvcm1hdGlvbiBpbiB0aGUgc2FtcGxlIHNoZWV0LCBNYXJpYQpBZGVsYWlkYSBhZGRlZCBhIG5ldyBjb2x1bW4gdXNpbmcgaXQgd2l0aCB0aGUgcHV0YXRpdmUgcGVyc2lzdGVuY2UKc3RhdGUgb24gYSBwZXItc2FtcGxlIGJhc2lzLiAgT25lIHF1ZXN0aW9uIHdoaWNoIGFyaXNlZCBmcm9tIHRoYXQ6CndoYXQgZGlmZmVyZW5jZXMgYXJlIG9ic2VydmFibGUgYmV0d2VlbiB0aGUgcGVyc2lzdGVudCB5ZXMgdnMuIG5vCnNhbXBsZXMgb24gYSBwZXItY2VsbC10eXBlIGJhc2lzIGFtb25nIHRoZSB2aXNpdCAzIHNhbXBsZXMuCgojIyMgU2V0dGluZyB1cAoKRmlyc3QgdGhpbmdzIGZpcnN0LCBjcmVhdGUgdGhlIGRhdGFzZXRzLgoKYGBge3IgcGVyc2lzdGVuY2Vfc2V0dXB9CnBlcnNpc3RlbmNlX2V4cHQgPC0gc3Vic2V0X2V4cHQoY2xpbmljYWwsIHN1YnNldCA9ICJwZXJzaXN0ZW5jZT09J1knfHBlcnNpc3RlbmNlPT0nTiciKSAlPiUKICBzdWJzZXRfZXhwdChzdWJzZXQgPSAndmlzaXRudW1iZXI9PTMnKSAlPiUKICBzZXRfZXhwdF9jb25kaXRpb25zKGZhY3QgPSAncGVyc2lzdGVuY2UnKQoKIyMgcGVyc2lzdGVuY2VfYmlvcHN5IDwtIHN1YnNldF9leHB0KHBlcnNpc3RlbmNlX2V4cHQsIHN1YnNldCA9ICJ0eXBlb2ZjZWxscz09J2Jpb3BzeSciKQpwZXJzaXN0ZW5jZV9tb25vY3l0ZSA8LSBzdWJzZXRfZXhwdChwZXJzaXN0ZW5jZV9leHB0LCBzdWJzZXQgPSAidHlwZW9mY2VsbHM9PSdtb25vY3l0ZXMnIikKcGVyc2lzdGVuY2VfbmV1dHJvcGhpbCA8LSBzdWJzZXRfZXhwdChwZXJzaXN0ZW5jZV9leHB0LCBzdWJzZXQgPSAidHlwZW9mY2VsbHM9PSduZXV0cm9waGlscyciKQpwZXJzaXN0ZW5jZV9lb3Npbm9waGlsIDwtIHN1YnNldF9leHB0KHBlcnNpc3RlbmNlX2V4cHQsIHN1YnNldCA9ICJ0eXBlb2ZjZWxscz09J2Vvc2lub3BoaWxzJyIpCmBgYAoKIyMjIFRha2UgYSBsb29rCgpTZWUgaWYgdGhlcmUgYXJlIGFueSBwYXR0ZXJucyB3aGljaCBsb29rIHVzYWJsZS4KCmBgYHtyIHBlcnNpc3RlbmNlX3Bsb3R9CiMjIEFsbApwZXJzaXN0ZW5jZV9ub3JtIDwtIG5vcm1hbGl6ZV9leHB0KHBlcnNpc3RlbmNlX2V4cHQsIHRyYW5zZm9ybSA9ICJsb2cyIiwgY29udmVydCA9ICJjcG0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vcm0gPSAicXVhbnQiLCBmaWx0ZXIgPSBUUlVFKQpwbG90X3BjYShwZXJzaXN0ZW5jZV9ub3JtKSRwbG90CnBlcnNpc3RlbmNlX25iIDwtIG5vcm1hbGl6ZV9leHB0KHBlcnNpc3RlbmNlX2V4cHQsIHRyYW5zZm9ybSA9ICJsb2cyIiwgY29udmVydCA9ICJjcG0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYXRjaCA9ICJzdmFzZXEiLCBmaWx0ZXIgPSBUUlVFKQpwbG90X3BjYShwZXJzaXN0ZW5jZV9uYikkcGxvdAoKIyMgQmlvcHNpZXMKIyNwZXJzaXN0ZW5jZV9iaW9wc3lfbm9ybSA8LSBub3JtYWxpemVfZXhwdChwZXJzaXN0ZW5jZV9iaW9wc3ksIHRyYW5zZm9ybSA9ICJsb2cyIiwgY29udmVydCA9ICJjcG0iLAojIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9ybSA9ICJxdWFudCIsIGZpbHRlciA9IFRSVUUpCiMjcGxvdF9wY2EocGVyc2lzdGVuY2VfYmlvcHN5X25vcm0pJHBsb3QKIyMgSW5zdWZmaWNpZW50IGRhdGEKCiMjIE1vbm9jeXRlcwpwZXJzaXN0ZW5jZV9tb25vY3l0ZV9ub3JtIDwtIG5vcm1hbGl6ZV9leHB0KHBlcnNpc3RlbmNlX21vbm9jeXRlLCB0cmFuc2Zvcm0gPSAibG9nMiIsIGNvbnZlcnQgPSAiY3BtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3JtID0gInF1YW50IiwgZmlsdGVyID0gVFJVRSkKcGxvdF9wY2EocGVyc2lzdGVuY2VfbW9ub2N5dGVfbm9ybSkkcGxvdApwZXJzaXN0ZW5jZV9tb25vY3l0ZV9uYiA8LSBub3JtYWxpemVfZXhwdChwZXJzaXN0ZW5jZV9tb25vY3l0ZSwgdHJhbnNmb3JtID0gImxvZzIiLCBjb252ZXJ0ID0gImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhdGNoID0gInN2YXNlcSIsIGZpbHRlciA9IFRSVUUpCnBsb3RfcGNhKHBlcnNpc3RlbmNlX21vbm9jeXRlX25iKSRwbG90CgojIyBOZXV0cm9waGlscwpwZXJzaXN0ZW5jZV9uZXV0cm9waGlsX25vcm0gPC0gbm9ybWFsaXplX2V4cHQocGVyc2lzdGVuY2VfbmV1dHJvcGhpbCwgdHJhbnNmb3JtID0gImxvZzIiLCBjb252ZXJ0ID0gImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9ybSA9ICJxdWFudCIsIGZpbHRlciA9IFRSVUUpCnBsb3RfcGNhKHBlcnNpc3RlbmNlX25ldXRyb3BoaWxfbm9ybSkkcGxvdApwZXJzaXN0ZW5jZV9uZXV0cm9waGlsX25iIDwtIG5vcm1hbGl6ZV9leHB0KHBlcnNpc3RlbmNlX25ldXRyb3BoaWwsIHRyYW5zZm9ybSA9ICJsb2cyIiwgY29udmVydCA9ICJjcG0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYXRjaCA9ICJzdmFzZXEiLCBmaWx0ZXIgPSBUUlVFKQpwbG90X3BjYShwZXJzaXN0ZW5jZV9uZXV0cm9waGlsX25iKSRwbG90CgojIyBFb3Npbm9waGlscwpwZXJzaXN0ZW5jZV9lb3Npbm9waGlsX25vcm0gPC0gbm9ybWFsaXplX2V4cHQocGVyc2lzdGVuY2VfZW9zaW5vcGhpbCwgdHJhbnNmb3JtID0gImxvZzIiLCBjb252ZXJ0ID0gImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9ybSA9ICJxdWFudCIsIGZpbHRlciA9IFRSVUUpCnBsb3RfcGNhKHBlcnNpc3RlbmNlX2Vvc2lub3BoaWxfbm9ybSkkcGxvdApwZXJzaXN0ZW5jZV9lb3Npbm9waGlsX25iIDwtIG5vcm1hbGl6ZV9leHB0KHBlcnNpc3RlbmNlX2Vvc2lub3BoaWwsIHRyYW5zZm9ybSA9ICJsb2cyIiwgY29udmVydCA9ICJjcG0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYXRjaCA9ICJzdmFzZXEiLCBmaWx0ZXIgPSBUUlVFKQpwbG90X3BjYShwZXJzaXN0ZW5jZV9lb3Npbm9waGlsX25iKSRwbG90CmBgYAoKIyMjIHBlcnNpc3RlbmNlIERFCgpgYGB7ciBwZXJzaXN0ZW5jZV9kZX0KcGVyc2lzdGVuY2VfZGUgPC0gYWxsX3BhaXJ3aXNlKHBlcnNpc3RlbmNlX2V4cHQsIGZpbHRlciA9IFRSVUUsIG1vZGVsX2JhdGNoID0gInN2YXNlcSIpCnBlcnNpc3RlbmNlX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogICAgcGVyc2lzdGVuY2VfZGUsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL3BlcnNpc3RlbmNlX2FsbF9kZS12e3Zlcn0ueGxzeCIpKQpwZXJzaXN0ZW5jZV9tb25vY3l0ZV9kZSA8LSBhbGxfcGFpcndpc2UocGVyc2lzdGVuY2VfbW9ub2N5dGUsIGZpbHRlciA9IFRSVUUsIG1vZGVsX2JhdGNoID0gInN2YXNlcSIpCnBlcnNpc3RlbmNlX21vbm9jeXRlX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogICAgcGVyc2lzdGVuY2VfbW9ub2N5dGVfZGUsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL3BlcnNpc3RlbmNlX21vbm9jeXRlX2RlLXZ7dmVyfS54bHN4IikpCnBlcnNpc3RlbmNlX25ldXRyb3BoaWxfZGUgPC0gYWxsX3BhaXJ3aXNlKHBlcnNpc3RlbmNlX25ldXRyb3BoaWwsIGZpbHRlciA9IFRSVUUsIG1vZGVsX2JhdGNoID0gInN2YXNlcSIpCnBlcnNpc3RlbmNlX25ldXRyb3BoaWxfdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgICBwZXJzaXN0ZW5jZV9uZXV0cm9waGlsX2RlLAogICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC9wZXJzaXN0ZW5jZV9uZXV0cm9waGlsX2RlLXZ7dmVyfS54bHN4IikpCnBlcnNpc3RlbmNlX2Vvc2lub3BoaWxfZGUgPC0gYWxsX3BhaXJ3aXNlKHBlcnNpc3RlbmNlX2Vvc2lub3BoaWwsIGZpbHRlciA9IFRSVUUsIG1vZGVsX2JhdGNoID0gInN2YXNlcSIpCnBlcnNpc3RlbmNlX2Vvc2lub3BoaWxfdGFibGUgPC0gY29tYmluZV9kZV90YWJsZXMoCiAgICBwZXJzaXN0ZW5jZV9lb3Npbm9waGlsX2RlLAogICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC9wZXJzaXN0ZW5jZV9lb3Npbm9waGlsX2RlLXZ7dmVyfS54bHN4IikpCmBgYAoKIyMgQ29tcGFyaW5nIHZpc2l0cyB3aXRob3V0IHJlZ2FyZCB0byBjdXJlL2ZhaWwKCiMjIyBBbGwgY2VsbCB0eXBlcwoKYGBge3IgZGVfY2ZfdmlzaXRfYWxsfQp2aXNpdF9hbGxfZGUgPC0gYWxsX3BhaXJ3aXNlKHZpc2l0X2V4cHQsIGZpbHRlciA9IFRSVUUsIG1vZGVsX2JhdGNoID0gInN2YXNlcSIpCnZpc2l0X2FsbF90YWJsZSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICAgIHZpc2l0X2FsbF9kZSwKICAgIGtlZXBlcnMgPSB2aXNpdF9jb250cmFzdHMsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL3Zpc2l0X2FsbF9kZS12e3Zlcn0ueGxzeCIpKQp2aXNpdF9hbGxfc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgICB2aXNpdF9hbGxfdGFibGUsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL3Zpc2l0X2FsbF9zaWctdnt2ZXJ9Lnhsc3giKSkKdmlzaXRfYWxsX3NhdmVkIDwtIHNhdmUobGlzdCA9ICJ2aXNpdF9hbGxfdGFibGUiLAogICAgICAgICAgICAgICAgICAgICAgICBmaWxlID0gZ2x1ZTo6Z2x1ZSgicmRhL3Zpc2l0X2FsbF90YWJsZS12e3Zlcn0ucmRhIikpCmBgYAoKIyMjIE1vbm9jeXRlIHNhbXBsZXMKCmBgYHtyIGRlX2NmX3Zpc2l0X21vbm9jeXRlfQp2aXNpdF9tb25vY3l0ZV9kZSA8LSBhbGxfcGFpcndpc2UodmlzaXRfbW9ub2N5dGUsIGZpbHRlciA9IFRSVUUsIG1vZGVsX2JhdGNoID0gInN2YXNlcSIpCnZpc2l0X21vbm9jeXRlX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogICAgdmlzaXRfbW9ub2N5dGVfZGUsCiAgICBrZWVwZXJzID0gdmlzaXRfY29udHJhc3RzLAogICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC92aXNpdF9tb25vY3l0ZV9kZS12e3Zlcn0ueGxzeCIpKQp2aXNpdF9tb25vY3l0ZV9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICAgIHZpc2l0X21vbm9jeXRlX3RhYmxlLAogICAgZXhjZWwgPSBnbHVlOjpnbHVlKCJleGNlbC92aXNpdF9tb25vY3l0ZV9zaWctdnt2ZXJ9Lnhsc3giKSkKYGBgCgojIyMgTmV1dHJvcGhpbCBzYW1wbGVzCgpgYGB7ciBkZV9jZl92aXNpdF9uZXV0cm9waGlsfQp2aXNpdF9uZXV0cm9waGlsX2RlIDwtIGFsbF9wYWlyd2lzZSh2aXNpdF9uZXV0cm9waGlsLCBmaWx0ZXIgPSBUUlVFLCBtb2RlbF9iYXRjaCA9ICJzdmFzZXEiKQp2aXNpdF9uZXV0cm9waGlsX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogICAgdmlzaXRfbmV1dHJvcGhpbF9kZSwKICAgIGtlZXBlcnMgPSB2aXNpdF9jb250cmFzdHMsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL3Zpc2l0X25ldXRyb3BoaWxfZGUtdnt2ZXJ9Lnhsc3giKSkKdmlzaXRfbmV1dHJvcGhpbF9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICAgIHZpc2l0X25ldXRyb3BoaWxfdGFibGUsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL3Zpc2l0X25ldXRyb3BoaWxfc2lnLXZ7dmVyfS54bHN4IikpCnZpc2l0X25ldXRyb3BoaWxfc2F2ZWQgPC0gc2F2ZShsaXN0ID0gInZpc2l0X25ldXRyb3BoaWxfdGFibGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZSA9IGdsdWU6OmdsdWUoInJkYS92aXNpdF9uZXV0cm9waGlsX3RhYmxlLXZ7dmVyfS5yZGEiKSkKYGBgCgojIyMgRW9zaW5vcGhpbCBzYW1wbGVzCgpgYGB7ciBkZV9jZl92aXNpdF9lb3Npbm9waGlsfQp2aXNpdF9lb3Npbm9waGlsX2RlIDwtIGFsbF9wYWlyd2lzZSh2aXNpdF9lb3Npbm9waGlsLCBmaWx0ZXIgPSBUUlVFLCBtb2RlbF9iYXRjaCA9ICJzdmFzZXEiKQp2aXNpdF9lb3Npbm9waGlsX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogICAgdmlzaXRfZW9zaW5vcGhpbF9kZSwKICAgIGtlZXBlcnMgPSB2aXNpdF9jb250cmFzdHMsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL3Zpc2l0X2Vvc2lub3BoaWxfZGUtdnt2ZXJ9Lnhsc3giKSkKdmlzaXRfZW9zaW5vcGhpbF9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICAgIHZpc2l0X2Vvc2lub3BoaWxfdGFibGUsCiAgICBleGNlbCA9IGdsdWU6OmdsdWUoImV4Y2VsL3Zpc2l0X2Vvc2lub3BoaWxfc2lnLXZ7dmVyfS54bHN4IikpCnZpc2l0X2Vvc2lub3BoaWxfc2F2ZWQgPC0gc2F2ZShsaXN0ID0gInZpc2l0X2Vvc2lub3BoaWxfdGFibGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZSA9IGdsdWU6OmdsdWUoInJkYS92aXNpdF9lb3Npbm9waGlsX3RhYmxlLXZ7dmVyfS5yZGEiKSkKYGBgCgojIENvbXBhcmUgdGhlIHR3byBjbGluaWNzIGRpcmVjdGx5CgpgYGB7ciBjbGluaWNfY29tcGFyaXNvbjJ9Cm1vbm9jeXRlc19ieV9wbGFjZSA8LSBzZXRfZXhwdF9jb25kaXRpb25zKG1vbm9jeXRlX3NhbXBsZXMsIGZhY3Q9ImNsaW5pYyIpCmVvc2lub3BoaWxzX2J5X3BsYWNlIDwtIHNldF9leHB0X2NvbmRpdGlvbnMoZW9zaW5vcGhpbF9zYW1wbGVzLCBmYWN0PSJjbGluaWMiKQpuZXV0cm9waGlsc19ieV9wbGFjZSA8LSBzZXRfZXhwdF9jb25kaXRpb25zKG5ldXRyb3BoaWxfc2FtcGxlcywgZmFjdD0iY2xpbmljIikKYmlvcHNpZXNfYnlfcGxhY2UgPC0gc2V0X2V4cHRfY29uZGl0aW9ucyhiaW9wc3lfc2FtcGxlcywgZmFjdD0iY2xpbmljIikKCm1vbm9jeXRlX3BsYWNlX2RlIDwtIGFsbF9wYWlyd2lzZShtb25vY3l0ZXNfYnlfcGxhY2UsIG1vZGVsX2JhdGNoPVRSVUUpCm1vbm9jeXRlX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogICAgbW9ub2N5dGVfcGxhY2VfZGUsCiAgICBleGNlbD0iZXhjZWwvbW9ub2N5dGVzX2J5X3BsYWNlLXRhYmxlLnhsc3giKQptb25vY3l0ZV9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICAgIG1vbm9jeXRlX3RhYmxlLAogICAgZXhjZWw9ImV4Y2VsL21vbm9jeXRlc19ieV9wbGFjZS1zaWcueGxzeCIpCmVvc2lub3BoaWxfcGxhY2VfZGUgPC0gYWxsX3BhaXJ3aXNlKGVvc2lub3BoaWxzX2J5X3BsYWNlLCBtb2RlbF9iYXRjaD1UUlVFKQplb3Npbm9waGlsX3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogICAgZW9zaW5vcGhpbF9wbGFjZV9kZSwKICAgIGV4Y2VsPSJleGNlbC9lb3Npbm9waGlsc19ieV9wbGFjZS10YWJsZS54bHN4IikKZW9zaW5vcGhpbF9zaWcgPC0gZXh0cmFjdF9zaWduaWZpY2FudF9nZW5lcygKICAgIGVvc2lub3BoaWxfdGFibGUsCiAgICBleGNlbD0iZXhjZWwvZW9zaW5vcGhpbHNfYnlfcGxhY2Utc2lnLnhsc3giKQpuZXV0cm9waGlsX3BsYWNlX2RlIDwtIGFsbF9wYWlyd2lzZShuZXV0cm9waGlsc19ieV9wbGFjZSwgbW9kZWxfYmF0Y2g9VFJVRSkKbmV1dHJvcGhpbF90YWJsZSA8LSBjb21iaW5lX2RlX3RhYmxlcygKICAgIG5ldXRyb3BoaWxfcGxhY2VfZGUsCiAgICBleGNlbD0iZXhjZWwvbmV1dHJvcGhpbHNfYnlfcGxhY2UtdGFibGUueGxzeCIpCm5ldXRyb3BoaWxfc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgICBuZXV0cm9waGlsX3RhYmxlLAogICAgZXhjZWw9ImV4Y2VsL25ldXRyb3BoaWxzX2J5X3BsYWNlLXNpZy54bHN4IikKYmlvcHN5X3BsYWNlX2RlIDwtIGFsbF9wYWlyd2lzZShiaW9wc2llc19ieV9wbGFjZSwgbW9kZWxfYmF0Y2g9VFJVRSkKYmlvcHN5X3RhYmxlIDwtIGNvbWJpbmVfZGVfdGFibGVzKAogICAgYmlvcHN5X3BsYWNlX2RlLAogICAgZXhjZWw9ImJpb3BzaWVzX2J5X3BsYWNlLXRhYmxlLnhsc3giKQpiaW9wc3lfc2lnIDwtIGV4dHJhY3Rfc2lnbmlmaWNhbnRfZ2VuZXMoCiAgICBiaW9wc3lfdGFibGUsCiAgICBleGNlbD0iYmlvcHNpZXNfYnlfcGxhY2Utc2lnLnhsc3giKQpgYGAKCiMgTGlrZWxpaG9vZCBSYXRpbyBUZXN0aW5nIChMUlQpCgojIyBTaGFyZWQgcGF0dGVybnMgYWNyb3NzIHZpc2l0cwoKYGBge3IgbHJ0X3Zpc2l0fQpjbGluaWNhbF9maWx0IDwtIG5vcm1hbGl6ZV9leHB0KGNsaW5pY2FsLCBmaWx0ZXIgPSBUUlVFKQpscnRfdmlzaXQgPC0gZGVzZXFfbHJ0KGNsaW5pY2FsX2ZpbHQsIHRyYW5zZm9ybSA9ICJ2c3QiLCBpbnRlcmFjdGlvbiA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgIGludGVyYWN0b3JfY29sdW1uID0gInZpc2l0bnVtYmVyIiwKICAgICAgICAgICAgICAgICAgICAgICBpbnRlcmVzdF9jb2x1bW4gPSAiY2xpbmljYWxvdXRjb21lIikKc3VtbWFyeShscnRfdmlzaXRbWyJmYXZvcml0ZV9nZW5lcyJdXSkKd3JpdHRlbiA8LSB3cml0ZV94bHN4KGRhdGE9YXMuZGF0YS5mcmFtZShscnRfdmlzaXRbWyJkZXNlcV90YWJsZSJdXSksCiAgICAgICAgICAgICAgICAgICAgICBleGNlbD1nbHVlOjpnbHVlKCJleGNlbC9scnRfY2xpbmljYWxfdmlzaXQtdnt2ZXJ9Lnhsc3giKSkKCmxydF9tb25vY3l0ZV92aXNpdCA8LSBkZXNlcV9scnQodmlzaXRfbW9ub2N5dGUsIHRyYW5zZm9ybSA9ICJ2c3QiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludGVyYWN0aW9uID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50ZXJhY3Rvcl9jb2x1bW4gPSAidmlzaXRudW1iZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludGVyZXN0X2NvbHVtbiA9ICJjbGluaWNhbG91dGNvbWUiKQpscnRfbW9ub2N5dGVfdmlzaXQkY2x1c3Rlcl9kYXRhJHBsb3QKCmxydF9tb25vY3l0ZV92aXNpdCA8LSBkZXNlcV9scnQobW9ub2N5dGUsIHRyYW5zZm9ybSA9ICJ2c3QiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRlcmFjdGlvbiA9IEZBTFNFLCBtaW5jID0gMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50ZXJhY3Rvcl9jb2x1bW4gPSAidmlzaXRudW1iZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRlcmVzdF9jb2x1bW4gPSAiY2xpbmljYWxvdXRjb21lIikKYGBgCgojIyBTaGFyZWQgcGF0dGVybnMgYWNyb3NzIGNlbGwgdHlwZXMKCmBgYHtyIGxydF9jZWxsdHlwZX0KbHJ0X2NlbGx0eXBlX2NsaW5pY2FsX3Rlc3QgPC0gZGVzZXFfbHJ0KGNsaW5pY2FsLCB0cmFuc2Zvcm0gPSAidnN0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludGVyYWN0b3JfY29sdW1uID0gInR5cGVvZmNlbGxzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludGVyZXN0X2NvbHVtbiA9ICJjbGluaWNhbG91dGNvbWUiKQoKZGVzZXFfbHJ0X2RmIDwtIG1lcmdlKGhzX2Fubm90LCBhcy5kYXRhLmZyYW1lKGxydF9jZWxsdHlwZV9jbGluaWNhbF90ZXN0W1siZGVzZXFfdGFibGUiXV0pLCBhbGwueT1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgYnk9InJvdy5uYW1lcyIpCnJvd25hbWVzKGRlc2VxX2xydF9kZikgPC0gZGVzZXFfbHJ0X2RmW1siUm93Lm5hbWVzIl1dCmRlc2VxX2xydF9kZltbIlJvdy5uYW1lcyJdXSA8LSBOVUxMCndyaXR0ZW4gPC0gd3JpdGVfeGxzeChkYXRhPWRlc2VxX2xydF9kZiwKICAgICAgICAgICAgICAgICAgICAgIGV4Y2VsPWdsdWU6OmdsdWUoImV4Y2VsL2xydF9jbGluaWNhbF9jZWxsdHlwZS12e3Zlcn0ueGxzeCIpKQpgYGAKCiMgR2VuZSBTZXQgQW5hbHlzZXMKClRoZSBnZW5lIHNldHMgd2UgYXJlIG1vc3QgbGlrZWx5IHRvIGNvbnNpZGVyIGFyZSB0aGUgcmVzdWx0cyBvZiB0aGUKdmFyaW91cyBwcmVjZWRpbmcgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYW5hbHlzZXMuCgojIyBHU0VBCgojIyMgQ3VyZS9GYWlsIGdyb3VwcwoKSW4gdGhlIGNvbnRleHQgb2YgY3VyZSB2cy4gZmFpbCwgd2UgaGF2ZSBtaXhlZCBhbmQgbWF0Y2hlZCB0aGUgZGF0YSBpbgpxdWl0ZSBhIGZldyBkaWZmZXJlbnQgd2F5cy4KCiMjIyMgQ3VyZS9GYWlsLCBhbGwgc2FtcGxlcwoKRm9yIHRoZSBtb21lbnQsIGxldCB1cyBhc3N1bWUgdGhhdCB0aGUgZGVmYXVsdCBkZWZpbml0aW9uIG9mCidzaWduaWZpY2FudCcgaXMgc3VmZmljaWVudCBmb3IgdGhlc2UgYW5hbHlzZXMsIHdpdGggdGhlIGtub3dsZWRnZQp0aGF0IGlzIG5vdCBsaWtlbHkgdG8gcmVtYWluIHRydWUuCgpUaGUgcmVzdWx0aW5nIGRhdGEgc3RydWN0dXJlcyBhcmUgb3JnYW5pemVkIGFzOgoKdGhpbmdbWyJkZXNlcSJdXVtbdXBzIl1dW1tjb250cmFzdF1dCgpJbiBhZGRpdGlvbiwgd2UgaGF2ZSBhIGZldyBvbnRvbG9neS1lc3F1ZSB0b29scyBhdmFpbGFibGUsIHNvIGxldCB1cwptaXggYW5kIG1hdGNoIGFuZCBzZWUgd2hhdCBwb3BzIG91dC4KCmBgYHtyIGdzZWFfY2ZfYWxsfQpjZl9hbGxfdXAgPC0gY2ZfY2xpbmljYWxfc2lnW1siZGVzZXEiXV1bWyJ1cHMiXV1bWyJmYWlsX3ZzX2N1cmUiXV0KZGltKGNmX2FsbF91cCkKY2ZfYWxsX2Rvd24gPC0gY2ZfY2xpbmljYWxfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbImZhaWxfdnNfY3VyZSJdXQpkaW0oY2ZfYWxsX2Rvd24pCgpjZl9hbGxfdXBfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihjZl9hbGxfdXApCmNmX2FsbF91cF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbInJlYWN0b21lX3Bsb3Rfb3ZlciJdXQpjZl9hbGxfdXBfZ3BbWyJwdmFsdWVfcGxvdHMiXV1bWyJrZWdnX3Bsb3Rfb3ZlciJdXQpjZl9hbGxfdXBfZ3BbWyJwdmFsdWVfcGxvdHMiXV1bWyJtZnBfcGxvdF9vdmVyIl1dCmNmX2FsbF91cF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbImJwcF9wbG90X292ZXIiXV0KCmNmX2FsbF9kb3duX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIoY2ZfYWxsX2Rvd24pCmNmX2FsbF9kb3duX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1sicmVhY3RvbWVfcGxvdF9vdmVyIl1dCmNmX2FsbF9kb3duX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1sia2VnZ19wbG90X292ZXIiXV0KY2ZfYWxsX2Rvd25fZ3BbWyJwdmFsdWVfcGxvdHMiXV1bWyJtZnBfcGxvdF9vdmVyIl1dCmNmX2FsbF9kb3duX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siYnBwX3Bsb3Rfb3ZlciJdXQoKIyMgVGhlIGZvbGxvd2luZyBsaW5lcyBhcmUgaW50ZW5kZWQgdG8gdGVzdCBpZiBJIGNhbiBjb3JlcmNlIG15CiMjIHZhcmlvdXMgIG9udG9sb2d5IG91dHB1dHMgdG8gdGhlIGVucmljaFJlc3VsdCBkYXRhIHN0cnVjdHVyZQojIyBwcm92aWRlZCBieSBjbHVzdGVyUHJvZmlsZXIuCiMjIGNmX2FsbF91cF9nbyA8LSBzaW1wbGVfZ29zZXEoY2ZfYWxsX3VwLCBnb19kYj1oc19nbywgbGVuZ3RoX2RiPWhzX2xlbmd0aCkKIyMgY2ZfYWxsX3VwX2NwIDwtIHNpbXBsZV9jbHVzdGVycHJvZmlsZXIoY2ZfYWxsX3VwLCBvcmdkYj0ib3JnLkhzLmVnLmRiIikKIyMgY2ZfYWxsX3VwX3RwIDwtIHNpbXBsZV90b3BnbyhjZl9hbGxfdXAsIGdvX2RiPWhzX2dvKQpgYGAKCiMjIyMgQ3VyZS9GYWlsLCBCaW9wc2llcwoKVGhlcmUgYXJlIG5vIGdlbmVzIGRlZW1lZCBzaWduaWZpY2FudCBpbiB0aGUgYmlvcHN5IGNvbXBhcmlzb25zIG9mCmN1cmUvZmFpbC4gIE9kZGx5LCB3aGVuIEkgbG9va2VkIG1hbnVhbGx5LCBJIHRob3VnaHQgSSBzYXcgb25lCmNhbmRpZGF0ZSBnZW5lLiAgSW4gYWRkaXRpb24sIHdoZW4gSSBzdGVwcGVkIHRocm91Z2ggdGhlIGZ1bmN0aW9uCm1hbnVhbGx5IEkgZ290IHRoZSBzYW1lIGdlbmUuLi4KCiMjIyMgQ3VyZS9GYWlsLCBNb25vY3l0ZXMKClRyeSBhZ2FpbiB3aXRoIG1vbm9jeXRlcy4KCmBgYHtyIGdzZWFfY2ZfbW9ub2N5dGV9CmNmX21vbm9jeXRlX3VwIDwtIGNmX21vbm9jeXRlX3N2YV9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbImZhaWxfdnNfY3VyZSJdXQpkaW0oY2ZfbW9ub2N5dGVfdXApCmNmX21vbm9jeXRlX2Rvd24gPC0gY2ZfbW9ub2N5dGVfc3ZhX3NpZ1tbImRlc2VxIl1dW1siZG93bnMiXV1bWyJmYWlsX3ZzX2N1cmUiXV0KZGltKGNmX21vbm9jeXRlX2Rvd24pCgpjZl9tb25vY3l0ZV91cF9ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKGNmX21vbm9jeXRlX3VwKQpjZl9tb25vY3l0ZV91cF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbInJlYWN0b21lX3Bsb3Rfb3ZlciJdXQpjZl9tb25vY3l0ZV91cF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbImtlZ2dfcGxvdF9vdmVyIl1dCmNmX21vbm9jeXRlX3VwX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siYnBwX3Bsb3Rfb3ZlciJdXQoKY2ZfbW9ub2N5dGVfZG93bl9ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKGNmX21vbm9jeXRlX2Rvd24pCmNmX21vbm9jeXRlX2Rvd25fZ3BbWyJwdmFsdWVfcGxvdHMiXV1bWyJyZWFjdG9tZV9wbG90X292ZXIiXV0KY2ZfbW9ub2N5dGVfZG93bl9ncFtbInB2YWx1ZV9wbG90cyJdXVtbImtlZ2dfcGxvdF9vdmVyIl1dCmBgYAoKIyMjIyBDdXJlL0ZhaWwsIE5ldXRyb3BoaWxzCgpgYGB7ciBnc2VhX2NmX25ldXRyb3BoaWx9CmNmX25ldXRyb3BoaWxfdXAgPC0gY2ZfbmV1dHJvcGhpbF9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbImZhaWxfdnNfY3VyZSJdXQpkaW0oY2ZfbmV1dHJvcGhpbF91cCkKY2ZfbmV1dHJvcGhpbF9kb3duIDwtIGNmX25ldXRyb3BoaWxfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbImZhaWxfdnNfY3VyZSJdXQpkaW0oY2ZfbmV1dHJvcGhpbF9kb3duKQoKY2ZfbmV1dHJvcGhpbF91cF9ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKGNmX25ldXRyb3BoaWxfdXApCgpjZl9uZXV0cm9waGlsX2Rvd25fZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihjZl9uZXV0cm9waGlsX2Rvd24pCmNmX25ldXRyb3BoaWxfZG93bl9ncFtbInB2YWx1ZV9wbG90cyJdXVtbImtlZ2dfcGxvdF9vdmVyIl1dCmBgYAoKIyMjIyBDdXJlL0ZhaWwsIEVvc2lub3BoaWxzCgpgYGB7ciBnc2VhX2NmX2Vvc2lub3BoaWx9CmNmX2Vvc2lub3BoaWxfdXAgPC0gY2ZfZW9zaW5vcGhpbF9zaWdbWyJkZXNlcSJdXVtbInVwcyJdXVtbImZhaWxfdnNfY3VyZSJdXQpkaW0oY2ZfZW9zaW5vcGhpbF91cCkKY2ZfZW9zaW5vcGhpbF9kb3duIDwtIGNmX2Vvc2lub3BoaWxfc2lnW1siZGVzZXEiXV1bWyJkb3ducyJdXVtbImZhaWxfdnNfY3VyZSJdXQpkaW0oY2ZfZW9zaW5vcGhpbF9kb3duKQoKY2ZfZW9zaW5vcGhpbF91cF9ncCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKGNmX2Vvc2lub3BoaWxfdXApCmNmX2Vvc2lub3BoaWxfdXBfZ3BbWyJwdmFsdWVfcGxvdHMiXV1bWyJrZWdnX3Bsb3Rfb3ZlciJdXQpjZl9lb3Npbm9waGlsX3VwX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1sicmVhY3RvbWVfcGxvdF9vdmVyIl1dCmNmX2Vvc2lub3BoaWxfdXBfZ3BbWyJwdmFsdWVfcGxvdHMiXV1bWyJtZnBfcGxvdF9vdmVyIl1dCmNmX2Vvc2lub3BoaWxfdXBfZ3BbWyJwdmFsdWVfcGxvdHMiXV1bWyJicHBfcGxvdF9vdmVyIl1dCgpjZl9lb3Npbm9waGlsX2Rvd25fZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihjZl9lb3Npbm9waGlsX2Rvd24pCmNmX2Vvc2lub3BoaWxfZG93bl9ncFtbInB2YWx1ZV9wbG90cyJdXVtbInJlYWN0b21lX3Bsb3Rfb3ZlciJdXQpjZl9lb3Npbm9waGlsX2Rvd25fZ3BbWyJwdmFsdWVfcGxvdHMiXV1bWyJtZnBfcGxvdF9vdmVyIl1dCmNmX2Vvc2lub3BoaWxfZG93bl9ncFtbInB2YWx1ZV9wbG90cyJdXVtbImJwcF9wbG90X292ZXIiXV0KYGBgCgojIyMjIENsaW5pY2FsIHNhbXBsZXMKCmBgYHtyIGdzZWFfY2ZfY2xpbmljYWx9CmNmX25vYmlvcHN5X3VwIDwtIGNmX25vYmlvcHN5X3NpZ1tbImRlc2VxIl1dW1sidXBzIl1dW1siZmFpbF92c19jdXJlIl1dCmRpbShjZl9ub2Jpb3BzeV91cCkKY2Zfbm9iaW9wc3lfZG93biA8LSBjZl9ub2Jpb3BzeV9zaWdbWyJkZXNlcSJdXVtbImRvd25zIl1dW1siZmFpbF92c19jdXJlIl1dCmRpbShjZl9ub2Jpb3BzeV9kb3duKQoKY2Zfbm9iaW9wc3lfdXBfZ3AgPC0gc2ltcGxlX2dwcm9maWxlcihjZl9ub2Jpb3BzeV91cCkKY2Zfbm9iaW9wc3lfdXBfZ3BbWyJwdmFsdWVfcGxvdHMiXV1bWyJrZWdnX3Bsb3Rfb3ZlciJdXQpjZl9ub2Jpb3BzeV91cF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbInJlYWN0b21lX3Bsb3Rfb3ZlciJdXQpjZl9ub2Jpb3BzeV91cF9ncFtbInB2YWx1ZV9wbG90cyJdXVtbIm1mcF9wbG90X292ZXIiXV0KY2Zfbm9iaW9wc3lfdXBfZ3BbWyJwdmFsdWVfcGxvdHMiXV1bWyJicHBfcGxvdF9vdmVyIl1dCgpjZl9ub2Jpb3BzeV9kb3duX2dwIDwtIHNpbXBsZV9ncHJvZmlsZXIoY2Zfbm9iaW9wc3lfZG93bikKY2Zfbm9iaW9wc3lfZG93bl9ncFtbInB2YWx1ZV9wbG90cyJdXVtbInJlYWN0b21lX3Bsb3Rfb3ZlciJdXQpjZl9ub2Jpb3BzeV9kb3duX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1sibWZwX3Bsb3Rfb3ZlciJdXQpjZl9ub2Jpb3BzeV9kb3duX2dwW1sicHZhbHVlX3Bsb3RzIl1dW1siYnBwX3Bsb3Rfb3ZlciJdXQpgYGAKCiMjIyBDZWxsIHR5cGUgZ3JvdXBzCgojIyMgVmlzaXQgZ3JvdXBzCgojIyBHU1ZBCgojIyMgQ2xpbmljYWwgc2FtcGxlcwoKYGBge3IgZ3N2YSwgZmlnLnNob3c9ImhpZGUifQpoc19jZWxsdHlwZV9nc3ZhX2MyIDwtIHNpbXBsZV9nc3ZhKGhzX3ZhbGlkKQpoc19jZWxsdHlwZV9nc3ZhX2MyX3NpZyA8LSBnZXRfc2lnX2dzdmFfY2F0ZWdvcmllcygKICAgIGhzX2NlbGx0eXBlX2dzdmFfYzIsCiAgICBleGNlbD0iZXhjZWwvaW5kaXZpZHVhbF9jZWxsdHlwZXNfZ3N2YV9jMi54bHN4IikKaHNfY2VsbHR5cGVfZ3N2YV9jMl9zaWckc3Vic2V0X3Bsb3QKaHNfY2VsbHR5cGVfZ3N2YV9jMl9zaWckc2NvcmVfcGxvdAoKYnJvYWRfYzcgPC0gbG9hZF9nbXRfc2lnbmF0dXJlcyhzaWduYXR1cmVzPSJyZWZlcmVuY2UvbXNpZ2RiL2M3LmFsbC52Ny4yLmVudHJlei5nbXQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpZ25hdHVyZV9jYXRlZ29yeT0iYzciKQpoc19jZWxsdHlwZV9nc3ZhX2M3IDwtIHNpbXBsZV9nc3ZhKGhzX3ZhbGlkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpZ25hdHVyZXM9InJlZmVyZW5jZS9tc2lnZGIvYzcuYWxsLnY3LjIuZW50cmV6LmdtdCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2lnbmF0dXJlX2NhdGVnb3J5PSJjNyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbXNpZ194bWw9InJlZmVyZW5jZS9tc2lnZGJfdjcuMi54bWwiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcmVzPTEwKQpoc19jZWxsdHlwZV9nc3ZhX2M3X3NpZyA8LSBnZXRfc2lnX2dzdmFfY2F0ZWdvcmllcygKICAgIGhzX2NlbGx0eXBlX2dzdmFfYzcsCiAgICBleGNlbD0iZXhjZWwvaW5kaXZpZHVhbF9jZWxsdHlwZXNfZ3N2YV9jNy54bHN4IikKYGBgCgojIyMgUHJpbnQgc29tZSBwbG90cyBvZiB0aGUgR1NWQSBvdXRwdXRzCgpgYGB7ciBnc3ZhX3Bsb3RzfQojIyBUaGUgcmF3IGhlYXRtYXAgb2YgdGhlIEMyIHZhbHVlcwpoc19jZWxsdHlwZV9nc3ZhX2MyX3NpZ1tbInJhd19wbG90Il1dCiMjIFRoZSAnc2lnbmlmaWNhbmNlJyBzY29yZXMgb2YgdGhlIEMyIHZhbHVlcwpoc19jZWxsdHlwZV9nc3ZhX2MyX3NpZ1tbInNjb3JlX3Bsb3QiXV0KIyMgVGhlIHN1YnNldCBvZiBzY29yZXMgZm9yIGNhdGVnb3JpZXMgZGVlbWVkIHNpZ25pZmljYW50bHkgZGlmZmVyZW50Lgpoc19jZWxsdHlwZV9nc3ZhX2MyX3NpZ1tbInN1YnNldF9wbG90Il1dCgojIyBUaGUgcmF3IGhlYXRtYXAgb2YgdGhlIEM3IHZhbHVlcwpoc19jZWxsdHlwZV9nc3ZhX2M3X3NpZ1tbInJhd19wbG90Il1dCiMjIFRoZSAnc2lnbmlmaWNhbmNlJyBzY29yZXMgb2YgdGhlIEM3IHZhbHVlcwpoc19jZWxsdHlwZV9nc3ZhX2M3X3NpZ1tbInNjb3JlX3Bsb3QiXV0KIyMgVGhlIHN1YnNldCBvZiBzY29yZXMgZm9yIGNhdGVnb3JpZXMgZGVlbWVkIHNpZ25pZmljYW50bHkgZGlmZmVyZW50Lgpoc19jZWxsdHlwZV9nc3ZhX2M3X3NpZ1tbInN1YnNldF9wbG90Il1dCmBgYAoKIyBDb25jb3JkYW5jZQoKTGV0IHVzIGNvbXBhcmUgdmFyaW91cyByZXN1bHRzIHRvIHNlZSBob3cgd2VsbCB0aGV5IGFncmVlZAoKYGBge3IgY29uY29yZGFuY2V9Cm1vbm9jeXRlX2Nvcl9zdWJzZXQgPC0gY2ZfbW9ub2N5dGVfc3ZhX3RhYmxlc1tbImRhdGEiXV1bWyJmYWlsX3ZzX2N1cmUiXV1bLCBjKCJkZXNlcV9sb2dmYyIsICJkZXNlcV9hZGpwIildCm5ldXRyb3BoaWxfY29yX3N1YnNldCA8LSBjZl9uZXV0cm9waGlsX3RhYmxlc1tbImRhdGEiXV1bWyJmYWlsX3ZzX2N1cmUiXV1bLCBjKCJkZXNlcV9sb2dmYyIsICJkZXNlcV9hZGpwIildCmVvc2lub3BoaWxfY29yX3N1YnNldCA8LSBjZl9lb3Npbm9waGlsX3RhYmxlc1tbImRhdGEiXV1bWyJmYWlsX3ZzX2N1cmUiXV1bLCBjKCJkZXNlcV9sb2dmYyIsICJkZXNlcV9hZGpwIildCm1vbm9fbmV1dF9jb3IgPC0gbWVyZ2UobW9ub2N5dGVfY29yX3N1YnNldCwgbmV1dHJvcGhpbF9jb3Jfc3Vic2V0LCBieT0icm93Lm5hbWVzIikKbW9ub19lb19jb3IgPC0gbWVyZ2UobW9ub2N5dGVfY29yX3N1YnNldCwgZW9zaW5vcGhpbF9jb3Jfc3Vic2V0LCBieT0icm93Lm5hbWVzIikKbmV1dF9lb19jb3IgPC0gbWVyZ2UobmV1dHJvcGhpbF9jb3Jfc3Vic2V0LCBlb3Npbm9waGlsX2Nvcl9zdWJzZXQsIGJ5PSJyb3cubmFtZXMiKQoKY29yLnRlc3QobW9ub19uZXV0X2NvcltbImRlc2VxX2xvZ2ZjLngiXV0sIG1vbm9fbmV1dF9jb3JbWyJkZXNlcV9sb2dmYy55Il1dKQptb25vY3l0ZV9uZXV0cm9waGlsX2F1Y2MgPC0gY2FsY3VsYXRlX2F1Y2MoY2ZfbW9ub2N5dGVfc3ZhX3RhYmxlc1tbImRhdGEiXV1bWyJmYWlsX3ZzX2N1cmUiXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjZl9uZXV0cm9waGlsX3RhYmxlc1tbImRhdGEiXV1bWyJmYWlsX3ZzX2N1cmUiXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBweD0iZGVzZXFfcCIsIHB5PSJkZXNlcV9wIiwgbHk9ImRlc2VxX2xvZ2ZjIiwgbHg9ImRlc2VxX2xvZ2ZjIikKbW9ub2N5dGVfbmV1dHJvcGhpbF9hdWNjJHBsb3QKCmNvci50ZXN0KG1vbm9fZW9fY29yW1siZGVzZXFfbG9nZmMueCJdXSwgbW9ub19lb19jb3JbWyJkZXNlcV9sb2dmYy55Il1dKQptb25vY3l0ZV9lb3Npbm9waGlsX2F1Y2MgPC0gY2FsY3VsYXRlX2F1Y2MoY2ZfbW9ub2N5dGVfc3ZhX3RhYmxlc1tbImRhdGEiXV1bWyJmYWlsX3ZzX2N1cmUiXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjZl9lb3Npbm9waGlsX3RhYmxlc1tbImRhdGEiXV1bWyJmYWlsX3ZzX2N1cmUiXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBweD0iZGVzZXFfcCIsIHB5PSJkZXNlcV9wIiwgbHk9ImRlc2VxX2xvZ2ZjIiwgbHg9ImRlc2VxX2xvZ2ZjIikKbW9ub2N5dGVfZW9zaW5vcGhpbF9hdWNjJHBsb3QKCmNvci50ZXN0KG5ldXRfZW9fY29yW1siZGVzZXFfbG9nZmMueCJdXSwgbmV1dF9lb19jb3JbWyJkZXNlcV9sb2dmYy55Il1dKQpuZXV0cm9waGlsX2Vvc2lub3BoaWxfYXVjYyA8LSBjYWxjdWxhdGVfYXVjYyhjZl9uZXV0cm9waGlsX3RhYmxlc1tbImRhdGEiXV1bWyJmYWlsX3ZzX2N1cmUiXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjZl9lb3Npbm9waGlsX3RhYmxlc1tbImRhdGEiXV1bWyJmYWlsX3ZzX2N1cmUiXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBweD0iZGVzZXFfcCIsIHB5PSJkZXNlcV9wIiwgbHk9ImRlc2VxX2xvZ2ZjIiwgbHg9ImRlc2VxX2xvZ2ZjIikKbmV1dHJvcGhpbF9lb3Npbm9waGlsX2F1Y2MkcGxvdApgYGAKCiMgQ2xhc3NpZnkgbWUhCgpJIHdyb3RlIG91dCBhbGwgdGhlIHoyLjIgYW5kIHoyLjMgc3BlY2lmaWMgdmFyaWFudHMgdG8gYSBjb3VwbGUgZmlsZXMsCkkgd2FudCB0byBzZWUgaWYgSSBjYW4gY2xhc3NpZnkgYSBodW1hbiBzYW1wbGUgYXMgaW5mZWN0ZWQgd2l0aCAyLjIgb3IKMi4zLgoKYGBge3IgY2xhc3NpZnltZSwgZXZhbD1GQUxTRX0KejIyIDwtIHJlYWQuY3N2KCJjc3YvdmFyaWFudHNfMjIuY3N2IikKejIzIDwtIHJlYWQuY3N2KCJjc3YvdmFyaWFudHNfMjMuY3N2IikKY3VyZSA8LSByZWFkLmNzdigiY3N2L2N1cmVfdmFyaWFudHMudHh0IikKZmFpbCA8LSByZWFkLmNzdigiY3N2L2ZhaWxfdmFyaWFudHMudHh0IikKejIyX3ZlYyA8LSBnc3ViKHBhdHRlcm49IlxcLSIsIHJlcGxhY2VtZW50PSJfIiwgeD16MjJbWyJ4Il1dKQp6MjNfdmVjIDwtIGdzdWIocGF0dGVybj0iXFwtIiwgcmVwbGFjZW1lbnQ9Il8iLCB4PXoyM1tbIngiXV0pCmN1cmVfdmVjIDwtIGdzdWIocGF0dGVybj0iXFwtIiwgcmVwbGFjZW1lbnQ9Il8iLCB4PWN1cmUpCmZhaWxfdmVjIDwtIGdzdWIocGF0dGVybj0iXFwtIiwgcmVwbGFjZW1lbnQ9Il8iLCB4PWZhaWwpCgpjbGFzc2lmeV96eW1vIDwtIGZ1bmN0aW9uKHNhbXBsZSkgewogIGFyYml0cmFyeV90YWdzIDwtIHNtKHJlYWRyOjpyZWFkX3RzdihzYW1wbGUpKQogIGFyYml0cmFyeV9pZHMgPC0gYXJiaXRyYXJ5X3RhZ3NbWyJwb3NpdGlvbiJdXQogIG1lc3NhZ2UoIkxlbmd0aDogIiwgbGVuZ3RoKGFyYml0cmFyeV9pZHMpLCAiLCB6MjI6ICIsCiAgICAgICAgICBzdW0oYXJiaXRyYXJ5X2lkcyAlaW4lIHoyMl92ZWMpIC8gKGxlbmd0aCh6MjJfdmVjKSksICIgejIzOiAiLAogICAgICAgICAgc3VtKGFyYml0cmFyeV9pZHMgJWluJSB6MjNfdmVjKSAvIChsZW5ndGgoejIzX3ZlYykpKQp9CgphcmJpdHJhcnlfc2FtcGxlIDwtICJwcmVwcm9jZXNzaW5nL1RNUkMzMDE1Ni9vdXRwdXRzLzQwZnJlZWJheWVzX2xwYW5hbWVuc2lzX3YzNi9hbGxfdGFncy50eHQueHoiCmNsYXNzaWZ5X3p5bW8oYXJiaXRyYXJ5X3NhbXBsZSkKYGBgCgpgYGB7ciBzYXZlbWUsIGV2YWw9RkFMU0V9CmlmICghaXNUUlVFKGdldDAoInNraXBfbG9hZCIpKSkgewogIHBhbmRlcjo6cGFuZGVyKHNlc3Npb25JbmZvKCkpCiAgbWVzc2FnZShwYXN0ZTAoIlRoaXMgaXMgaHBnbHRvb2xzIGNvbW1pdDogIiwgZ2V0X2dpdF9jb21taXQoKSkpCiAgbWVzc2FnZShwYXN0ZTAoIlNhdmluZyB0byAiLCBzYXZlZmlsZSkpCiAgdG1wIDwtIHNtKHNhdmVtZShmaWxlbmFtZT1zYXZlZmlsZSkpCn0KYGBgCgpgYGB7ciBsb2FkbWVfYWZ0ZXIsIGV2YWw9RkFMU0V9CnRtcCA8LSBsb2FkbWUoZmlsZW5hbWU9c2F2ZWZpbGUpCmBgYAo=