1 New samples!

This worksheet is a copy of 20180726 but this time with feeling! (or new samples) A minor caveat: I had some difficulties converting the new data to a openMS suitable format. I am not certain if I messed up a priori, or if a change in the version of the software on the spec caused the problem, but for future reference:

To properly convert the data to mzXML, make sure to use the TPP MSConvert utility and have ‘TPP’ compatibility on.

2 Analyzing data from openMS and friends.

2.1 SWATH2stats preprocessing

I am using my slightly modified copy of SWATH2stats. This seeks to ensure that changes in the case of columns in the metadata from one version of OpenMS to another do not trouble me.

I am separately performing the analysis for our home-grown libraries and the publicly available ones (documented in the 201806 worksheets).

2.1.1 Creating a swath2stats experiment using our comet-derived library data

our_tric_data <- read.csv(paste0("results/tric/", ver, "/whole_8mz/comet_HCD.tsv"), sep="\t")

sample_annot <- extract_metadata(paste0("sample_sheets/Mtb_dia_samples_", ver, ".xlsx"))
kept <- ! grepl(x=rownames(sample_annot), pattern="^s\\.\\.")
sample_annot <- sample_annot[kept, ]

##sample_annot <- openxlsx::read.xlsx("sample_sheets/Mtb_dia_samples_20180611.xlsx")
##rownames(sample_annot) <- make.names(paste0("s", sample_annot[["sampleid"]]), unique=TRUE)
## Drop samples starting with comments
##keep_idx <- ! grepl(pattern="##", x=sample_annot[["sampleid"]])
##sample_annot <- sample_annot[keep_idx, ]
##colnames(sample_annot) <- gsub(x=colnames(sample_annot), pattern="\\.", replacement="")
## Set the mzXML column to match the filename column in the data.
loaded <- sm(devtools::load_all("~/scratch/git/SWATH2stats"))
## s2s, my witty way of shortening SWATH2stats...
our_s2s_exp <- sample_annotation(data=our_tric_data,
                                 sample_annotation=sample_annot,
                                 run_column="run", check_files=FALSE,
                                 fullpeptidename_column="fullunimodpeptidename")
## Not checking that the files are identical between the annotation and data.
## Warning in sample_annotation(data = our_tric_data, sample_annotation =
## sample_annot, : No measurement value found for sample 'results/01mzXML/dia/
## 20180806/2018_0726Briken03.mzXML' in the data file.
## Warning in sample_annotation(data = our_tric_data, sample_annotation =
## sample_annot, : No measurement value found for sample 'results/01mzXML/dia/
## 20180806/2018_0726Briken11.mzXML' in the data file.
## Warning in sample_annotation(data = our_tric_data, sample_annotation =
## sample_annot, : No measurement value found for sample 'results/mzXML/dia/
## 20180611/2018_0315Briken01.mzXML' in the data file.
## Warning in sample_annotation(data = our_tric_data, sample_annotation =
## sample_annot, : No measurement value found for sample 'results/mzXML/dia/
## 20180611/2018_0315Briken02.mzXML' in the data file.
## Warning in sample_annotation(data = our_tric_data, sample_annotation =
## sample_annot, : No measurement value found for sample 'results/mzXML/dia/
## 20180611/2018_0315Briken03.mzXML' in the data file.
## Warning in sample_annotation(data = our_tric_data, sample_annotation =
## sample_annot, : No measurement value found for sample 'results/mzXML/dia/
## 20180611/2018_0315Briken04.mzXML' in the data file.
## Warning in sample_annotation(data = our_tric_data, sample_annotation =
## sample_annot, : No measurement value found for sample 'results/mzXML/dia/
## 20180611/2018_0315Briken05.mzXML' in the data file.
## Warning in sample_annotation(data = our_tric_data, sample_annotation =
## sample_annot, : No measurement value found for sample 'results/mzXML/dia/
## 20180611/2018_0315Briken06.mzXML' in the data file.
## Warning in sample_annotation(data = our_tric_data, sample_annotation =
## sample_annot, : No measurement value found for sample 'results/mzXML/dia/
## 20180611/2018_0315Briken21.mzXML' in the data file.
## Warning in sample_annotation(data = our_tric_data, sample_annotation =
## sample_annot, : No measurement value found for sample 'results/mzXML/dia/
## 20180611/2018_0315Briken22.mzXML' in the data file.
## Warning in sample_annotation(data = our_tric_data, sample_annotation =
## sample_annot, : No measurement value found for sample 'results/mzXML/dia/
## 20180611/2018_0315Briken23.mzXML' in the data file.
## Warning in sample_annotation(data = our_tric_data, sample_annotation =
## sample_annot, : No measurement value found for sample 'results/mzXML/dia/
## 20180611/2018_0315Briken24.mzXML' in the data file.
## Warning in sample_annotation(data = our_tric_data, sample_annotation =
## sample_annot, : No measurement value found for sample 'results/mzXML/dia/
## 20180611/2018_0315Briken25.mzXML' in the data file.
## Warning in sample_annotation(data = our_tric_data, sample_annotation =
## sample_annot, : No measurement value found for sample 'results/mzXML/dia/
## 20180611/2018_0315Briken26.mzXML' in the data file.
## Warning in sample_annotation(data = our_tric_data, sample_annotation =
## sample_annot, : No measurement value found for sample 'results/mzXML/dia/
## 20180611/2018_0502BrikenDIA01.mzXML' in the data file.
## Warning in sample_annotation(data = our_tric_data, sample_annotation =
## sample_annot, : No measurement value found for sample 'results/mzXML/dia/
## 20180611/2018_0502BrikenDIA02.mzXML' in the data file.
## Warning in sample_annotation(data = our_tric_data, sample_annotation =
## sample_annot, : No measurement value found for sample 'results/mzXML/dia/
## 20180611/2018_0502BrikenDIA03.mzXML' in the data file.
## Warning in sample_annotation(data = our_tric_data, sample_annotation =
## sample_annot, : No measurement value found for sample 'results/mzXML/dia/
## 20180611/2018_0502BrikenDIA04.mzXML' in the data file.
## Warning in sample_annotation(data = our_tric_data, sample_annotation =
## sample_annot, : No measurement value found for sample 'results/mzXML/dia/
## 20180611/2018_0502BrikenDIA05.mzXML' in the data file.
## Warning in sample_annotation(data = our_tric_data, sample_annotation =
## sample_annot, : No measurement value found for sample 'results/mzXML/dia/
## 20180611/2018_0502BrikenDIA06.mzXML' in the data file.
## Warning in sample_annotation(data = our_tric_data, sample_annotation =
## sample_annot, : No measurement value found for sample 'results/mzXML/dia/
## 20180611/2018_0502BrikenDIA07.mzXML' in the data file.
## Warning in sample_annotation(data = our_tric_data, sample_annotation =
## sample_annot, : No measurement value found for sample 'results/mzXML/dia/
## 20180611/2018_0502BrikenDIA08.mzXML' in the data file.
## Warning in sample_annotation(data = our_tric_data, sample_annotation =
## sample_annot, : No measurement value found for sample 'results/mzXML/dia/
## 20180611/2018_0502BrikenDIA09.mzXML' in the data file.
## Warning in sample_annotation(data = our_tric_data, sample_annotation =
## sample_annot, : No measurement value found for sample 'results/mzXML/dia/
## 20180611/2018_0502BrikenDIA11.mzXML' in the data file.
## Warning in sample_annotation(data = our_tric_data, sample_annotation =
## sample_annot, : No measurement value found for sample 'results/mzXML/dia/
## 20180611/2018_0502BrikenDIA12.mzXML' in the data file.

2.1.2 Creating a swath2stats experiment using the tuberculist-derived library data

This just repeats the previous stanza, but uses the tuberculist transition-library swath data as its input rather than our own comet data.

There is one important caveat in the following block: I used a regex to remove the second half of geneID_geneName so that later when I merge in the annotation data I have it will match.

tb_tric_data <- read.csv(paste0("results/tric/", ver, "/whole_8mz_tuberculist/comet_HCD.tsv"),
                         sep="\t")
tb_tric_data[["ProteinName"]] <- gsub(pattern="^(.*)_.*$", replacement="\\1",
                                      x=tb_tric_data[["ProteinName"]])
tb_s2s_exp <- sample_annotation(data=tb_tric_data, check_files=FALSE,
                                sample_annotation=sample_annot,
                                fullpeptidename_column="fullunimodpeptidename")
## Not checking that the files are identical between the annotation and data.
## Warning in sample_annotation(data = tb_tric_data, check_files = FALSE,
## sample_annotation = sample_annot, : No measurement value found for sample
## 'results/01mzXML/dia/20180806/2018_0726Briken03.mzXML' in the data file.
## Warning in sample_annotation(data = tb_tric_data, check_files = FALSE,
## sample_annotation = sample_annot, : No measurement value found for sample
## 'results/01mzXML/dia/20180806/2018_0726Briken11.mzXML' in the data file.

Now I have a couple data structures which should prove useful for the metrics provided by SWATH2stats, MSstats, and my own hpgltools.

3 SWATH2stats continued

The various metrics and filters provided by SWATH2stats seem quite reasonable to me. The only thing that really bothers me is that they are all case sensitive and I found that the most recent tric changed the capitalization of a column, causing these to all fall down. Therefore I went in and made everything case insensitive in a fashion similar to that done by MSstats (except I hate capital letters, so I used tolower() rather than toupper()).

3.1 Run filters on our comet data

## Get correlations on a sample by sample basis
pp(file="images/20180611_our_swath2stats_sample_cor.png")
## Going to write the image to: images/20180611_our_swath2stats_sample_cor.png when dev.off() is called.
sample_cor <- plot_correlation_between_samples(our_s2s_exp, size=2,
                                               fun.aggregate=sum,
                                               column.values="intensity")
dev.off()
## png 
##   2
sample_cond_rep_cor <- plot_correlation_between_samples(our_s2s_exp, size=2,
                                                        comparison=transition_group_id ~
                                                          condition + bioreplicate + run,
                                                        fun.aggregate=sum,
                                                        column.values="intensity")

decoy_lists <- assess_decoy_rate(our_s2s_exp)
## Number of non-decoy peptides: 3105
## Number of decoy peptides: 258
## Decoy rate: 0.0831
## This seems a bit high to me, yesno?
fdr_overall <- assess_fdr_overall(our_s2s_exp, output="Rconsole", plot=TRUE)

byrun_fdr <- assess_fdr_byrun(our_s2s_exp, FFT=0.7, plot=TRUE, output="Rconsole")
## The average FDR by run on assay level is 0.014
## The average FDR by run on peptide level is 0.015
## The average FDR by run on protein level is 0.037

chosen_mscore <- mscore4assayfdr(our_s2s_exp, FFT=0.7, fdr_target=0.02)
## Target assay FDR: 0.02
## Required overall m-score cutoff: 0.0035481
## achieving assay FDR: 0.0196
prot_score <- mscore4protfdr(our_s2s_exp, FFT=0.7, fdr_target=0.02)
## Target protein FDR: 0.02
## Required overall m-score cutoff: 0.001
## achieving protein FDR: 0.0186
our_mscore_filtered <- filter_mscore(our_s2s_exp, chosen_mscore)
## Original dimension: 24787, new dimension: 23309, difference: 1478.
our_freq_mscore <- filter_mscore_freqobs(our_s2s_exp, 0.01, 0.8, rm.decoy=FALSE)
## Peptides need to have been quantified in more conditions than: 12.8 in order to pass this percentage-based threshold.
## Fraction of peptides selected: 0.16
## Original dimension: 25349, new dimension: 8014, difference: 17335.
our_data_filtered_fdr <- filter_mscore_fdr(our_mscore_filtered, FFT=0.7,
                                           overall_protein_fdr_target=prot_score,
                                           upper_overall_peptide_fdr_limit=0.05)
## Target protein FDR: 0.001
## Required overall m-score cutoff: 0.01
## achieving protein FDR: 0
## filter_mscore_fdr is filtering the data...
## finding m-score cutoff to achieve desired protein FDR in protein master list..
## finding m-score cutoff to achieve desired global peptide FDR..
## Target peptide FDR: 0.05
## Required overall m-score cutoff: 0.01
## Achieving peptide FDR: 0
## Proteins selected: 
## Total proteins selected: 927
## Final target proteins: 927
## Final decoy proteins: 0
## Peptides mapping to these protein entries selected:
## Total mapping peptides: 3008
## Final target peptides: 3008
## Final decoy peptides: 0
## Total peptides selected from:
## Total peptides: 3008
## Final target peptides: 3008
## Final decoy peptides: 0
## Individual run FDR quality of the peptides was not calculated
## as not every run contains a decoy.
## The decoys have been removed from the returned data.
our_only_proteotypic <- filter_proteotypic_peptides(our_data_filtered_fdr)
## Number of proteins detected: 931
## Protein identifiers: Rv3036c, Rv1133c, Rv1098c, Rv2241, Rv2799, Rv0652
## Number of proteins detected that are supported by a proteotypic peptide: 911
## Number of proteotypic peptides detected: 2965
our_all_filtered <- filter_all_peptides(our_only_proteotypic)
## Number of proteins detected: 911
## First 6 protein identifiers: Rv3036c, Rv1133c, Rv1098c, Rv2241, Rv2799, Rv0652
our_only_strong <- filter_on_max_peptides(data=our_all_filtered, n_peptides=10)
## Before filtering:
##   Number of proteins: 911
##   Number of peptides: 2965
## 
## Percentage of peptides removed: 8.67%
## 
## After filtering:
##   Number of proteins: 908
##   Number of peptides: 2708
our_only_minimum <- filter_on_min_peptides(data=our_only_strong, n_peptides=3)
## Before filtering:
##   Number of proteins: 908
##   Number of peptides: 2708
## 
## Percentage of peptides removed: 0.07%
## 
## After filtering:
##   Number of proteins: 820
##   Number of peptides: 2706
## I think these matrixes are probably smarter to use than the raw outmatrix from tric.
## But I am not a fan of rerwriting the sample column names.
matrix_prefix <- file.path("results", "swath2stats", ver)
if (!file.exists(matrix_prefix)) {
  dir.create(matrix_prefix)
}
protein_matrix_all <- write_matrix_proteins(
  our_s2s_exp, write.csv=TRUE,
  filename=file.path(matrix_prefix, "our_protein_all.csv"))
## Protein overview matrix results/swath2stats/20180806/our_protein_all.csv written to working folder.
dim(protein_matrix_all)
## [1] 1156   17
protein_matrix_mscore <- write_matrix_proteins(
  our_mscore_filtered, write.csv=TRUE,
  filename=file.path(matrix_prefix, "our_protein_matrix_mscore.csv"))
## Protein overview matrix results/swath2stats/20180806/our_protein_matrix_mscore.csv written to working folder.
dim(protein_matrix_mscore)
## [1] 927  17
peptide_matrix_mscore <- write_matrix_peptides(
  our_mscore_filtered, write.csv=TRUE,
  filename=file.path(matrix_prefix, "our_peptide_matrix_mscore.csv"))
## Peptide overview matrix results/swath2stats/20180806/our_peptide_matrix_mscore.csv written to working folder.
dim(peptide_matrix_mscore)
## [1] 3008   17
protein_matrix_minimum <- write_matrix_proteins(
  our_only_minimum, write.csv=TRUE,
  filename=file.path(matrix_prefix, "our_protein_matrix_minimum.csv"))
## Protein overview matrix results/swath2stats/20180806/our_protein_matrix_minimum.csv written to working folder.
dim(protein_matrix_minimum)
## [1] 820  17
peptide_matrix_minimum <- write_matrix_peptides(
  our_only_minimum, write.csv=TRUE,
  filename=file.path(matrix_prefix, "our_peptide_matrix_minimum.csv"))
## Peptide overview matrix results/swath2stats/20180806/our_peptide_matrix_minimum.csv written to working folder.
dim(peptide_matrix_minimum)
## [1] 19837    17
rt_cor <- plot_correlation_between_samples(
  our_all_filtered, column.values="intensity", fun.aggregate=sum, size=2)

## I have no effing clue what this plot means.
variation <- plot_variation(our_all_filtered, fun.aggregate=sum)

cols <- colnames(our_all_filtered)
our_disaggregated <- disaggregate(our_all_filtered, all.columns=TRUE)
## The library contains6transitions per precursor.
## The data table was transformed into a table containing one row per transition.
our_msstats_input <- convert_MSstats(our_disaggregated)
## One or several columns required by MSstats were not in the data. The columns were created and filled with NAs.
## Missing columns: productcharge, isotopelabeltype
## isotopelabeltype was filled with light.
summary(our_msstats_input)
##  proteinname        peptidesequence    precursorcharge fragmention       
##  Length:137316      Length:137316      Min.   :2.00    Length:137316     
##  Class :character   Class :character   1st Qu.:2.00    Class :character  
##  Mode  :character   Mode  :character   Median :2.00    Mode  :character  
##                                        Mean   :2.19                      
##                                        3rd Qu.:2.00                      
##                                        Max.   :4.00                      
##  productcharge  isotopelabeltype     intensity        bioreplicate      
##  Mode:logical   Length:137316      Min.   :1.20e+04   Length:137316     
##  NA's:137316    Class :character   1st Qu.:2.08e+06   Class :character  
##                 Mode  :character   Median :7.88e+06   Mode  :character  
##                                    Mean   :5.49e+07                     
##                                    3rd Qu.:3.12e+07                     
##                                    Max.   :1.57e+10                     
##           condition         run           
##  wt_filtrate   :24384   Length:137316     
##  wt_whole      :38442   Class :character  
##  delta_whole   :19704   Mode  :character  
##  comp_whole    :29286                     
##  delta_filtrate: 9756                     
##  comp_filtrate :15744

3.2 Run filters on the tuberculist

Repeat the above stanza using the tuberculist data.

## Get correlations on a sample by sample basis
pp(file="images/20180611_tb_swath2stats_sample_cor.png")
## Going to write the image to: images/20180611_tb_swath2stats_sample_cor.png when dev.off() is called.
sample_cor <- plot_correlation_between_samples(tb_s2s_exp, size=2,
                                               fun.aggregate=sum,
                                               column.values="intensity")
dev.off()
## png 
##   2
sample_cond_rep_cor <- plot_correlation_between_samples(tb_s2s_exp, size=2,
                                                        comparison=transition_group_id ~
                                                          condition + bioreplicate + run,
                                                        fun.aggregate=sum,
                                                        column.values="intensity")

decoy_lists <- assess_decoy_rate(tb_s2s_exp)
## Number of non-decoy peptides: 24166
## Number of decoy peptides: 1626
## Decoy rate: 0.0673
## This seems a bit high to me, yesno?
fdr_overall <- assess_fdr_overall(tb_s2s_exp, output="Rconsole", plot=TRUE)

byrun_fdr <- assess_fdr_byrun(tb_s2s_exp, FFT=0.7, plot=TRUE, output="Rconsole")
## The average FDR by run on assay level is 0.007
## The average FDR by run on peptide level is 0.008
## The average FDR by run on protein level is 0.035

chosen_mscore <- mscore4assayfdr(tb_s2s_exp, FFT=0.7, fdr_target=0.02)
## Target assay FDR: 0.02
## Required overall m-score cutoff: 0.0050119
## achieving assay FDR: 0.0186
prot_score <- mscore4protfdr(tb_s2s_exp, FFT=0.7, fdr_target=0.02)
## Target protein FDR: 0.02
## Required overall m-score cutoff: 0.00056234
## achieving protein FDR: 0.0177
tb_mscore_filtered <- filter_mscore(tb_s2s_exp, chosen_mscore)
## Original dimension: 329180, new dimension: 305033, difference: 24147.
tb_freq_mscore <- filter_mscore_freqobs(tb_s2s_exp, 0.01, 0.8, rm.decoy=FALSE)
## Peptides need to have been quantified in more conditions than: 31.2 in order to pass this percentage-based threshold.
## Fraction of peptides selected: 0.036
## Original dimension: 333450, new dimension: 39657, difference: 293793.
tb_data_filtered_fdr <- filter_mscore_fdr(tb_mscore_filtered, FFT=0.7,
                                           overall_protein_fdr_target=prot_score,
                                           upper_overall_peptide_fdr_limit=0.05)
## Target protein FDR: 0.000562341325190349
## Required overall m-score cutoff: 0.01
## achieving protein FDR: 0
## filter_mscore_fdr is filtering the data...
## finding m-score cutoff to achieve desired protein FDR in protein master list..
## finding m-score cutoff to achieve desired global peptide FDR..
## Target peptide FDR: 0.05
## Required overall m-score cutoff: 0.01
## Achieving peptide FDR: 0
## Proteins selected: 
## Total proteins selected: 3091
## Final target proteins: 3091
## Final decoy proteins: 0
## Peptides mapping to these protein entries selected:
## Total mapping peptides: 22927
## Final target peptides: 22927
## Final decoy peptides: 0
## Total peptides selected from:
## Total peptides: 22927
## Final target peptides: 22927
## Final decoy peptides: 0
## Individual run FDR quality of the peptides was not calculated
## as not every run contains a decoy.
## The decoys have been removed from the returned data.
tb_only_proteotypic <- filter_proteotypic_peptides(tb_data_filtered_fdr)
## Number of proteins detected: 3104
## Protein identifiers: Rv1270c, Rv0161, Rv1613, Rv2540c, Rv0440, Rv1327c
## Number of proteins detected that are supported by a proteotypic peptide: 2966
## Number of proteotypic peptides detected: 22765
tb_all_filtered <- filter_all_peptides(tb_only_proteotypic)
## Number of proteins detected: 2968
## First 6 protein identifiers: Rv1270c, Rv0161, Rv1613, Rv2540c, Rv0440, Rv1327c
tb_only_strong <- filter_on_max_peptides(data=tb_all_filtered, n_peptides=10)
## Before filtering:
##   Number of proteins: 2966
##   Number of peptides: 22765
## 
## Percentage of peptides removed: 23.31%
## 
## After filtering:
##   Number of proteins: 2941
##   Number of peptides: 17459
tb_only_minimum <- filter_on_min_peptides(data=tb_only_strong, n_peptides=3)
## Before filtering:
##   Number of proteins: 2941
##   Number of peptides: 17459
## 
## Percentage of peptides removed: 0.02%
## 
## After filtering:
##   Number of proteins: 2701
##   Number of peptides: 17455
## I think these matrixes are probably smarter to use than the raw outmatrix from tric.
## But I am not a fan of rerwriting the sample column names.
matrix_prefix <- file.path("results", "swath2stats", ver)
if (!file.exists(matrix_prefix)) {
  dir.create(matrix_prefix)
}
protein_matrix_all <- write_matrix_proteins(
  tb_s2s_exp, write.csv=TRUE,
  filename=file.path(matrix_prefix, "tb_protein_all.csv"))
## Protein overview matrix results/swath2stats/20180806/tb_protein_all.csv written to working folder.
dim(protein_matrix_all)
## [1] 4488   40
protein_matrix_mscore <- write_matrix_proteins(
  tb_mscore_filtered, write.csv=TRUE,
  filename=file.path(matrix_prefix, "tb_protein_matrix_mscore.csv"))
## Protein overview matrix results/swath2stats/20180806/tb_protein_matrix_mscore.csv written to working folder.
dim(protein_matrix_mscore)
## [1] 3091   40
peptide_matrix_mscore <- write_matrix_peptides(
  tb_mscore_filtered, write.csv=TRUE,
  filename=file.path(matrix_prefix, "tb_peptide_matrix_mscore.csv"))
## Peptide overview matrix results/swath2stats/20180806/tb_peptide_matrix_mscore.csv written to working folder.
dim(peptide_matrix_mscore)
## [1] 22927    40
protein_matrix_minimum <- write_matrix_proteins(
  tb_only_minimum, write.csv=TRUE,
  filename=file.path(matrix_prefix, "tb_protein_matrix_minimum.csv"))
## Protein overview matrix results/swath2stats/20180806/tb_protein_matrix_minimum.csv written to working folder.
dim(protein_matrix_minimum)
## [1] 2701   40
peptide_matrix_minimum <- write_matrix_peptides(
  tb_only_minimum, write.csv=TRUE,
  filename=file.path(matrix_prefix, "tb_peptide_matrix_minimum.csv"))
## Peptide overview matrix results/swath2stats/20180806/tb_peptide_matrix_minimum.csv written to working folder.
dim(peptide_matrix_minimum)
## [1] 221200     40
rt_cor <- plot_correlation_between_samples(
  tb_only_minimum, column.values="intensity", fun.aggregate=sum, size=2)

## I have no effing clue what this plot means.
variation <- plot_variation(tb_only_minimum, fun.aggregate=sum)

cols <- colnames(tb_all_filtered)
tb_disaggregated <- disaggregate(tb_all_filtered, all.columns=TRUE)
## The library contains5transitions per precursor.
## The data table was transformed into a table containing one row per transition.
tb_msstats_input <- convert_MSstats(tb_disaggregated)
## One or several columns required by MSstats were not in the data. The columns were created and filled with NAs.
## Missing columns: productcharge, isotopelabeltype
## isotopelabeltype was filled with light.

3.3 Some new plots

In response to some interesting queries from Yan, I made a few little functions which query and plot data from the scored data provided by openswath/pyprophet. Let us look at their results here.

3.3.1 Using the comet data

our_pyprophet_fun <- extract_pyprophet_data(
  metadata=paste0("sample_sheets/Mtb_dia_samples_", ver, ".xlsx"))
## Warning in extract_pyprophet_data(metadata = paste0("sample_sheets/
## Mtb_dia_samples_", : It appears that some files are missing in the
## metadata.
## Attempting to read the tsv file for: 2018_0315Briken01: results/pyprophet/20180611/whole_8mz_comet/2018_0315Briken01_vs_20180611_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0315Briken02: results/pyprophet/20180611/whole_8mz_comet/2018_0315Briken02_vs_20180611_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0315Briken03: results/pyprophet/20180611/whole_8mz_comet/2018_0315Briken03_vs_20180611_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0315Briken04: results/pyprophet/20180611/whole_8mz_comet/2018_0315Briken04_vs_20180611_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0315Briken05: results/pyprophet/20180611/whole_8mz_comet/2018_0315Briken05_vs_20180611_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0315Briken06: results/pyprophet/20180611/whole_8mz_comet/2018_0315Briken06_vs_20180611_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0315Briken21: results/pyprophet/20180611/whole_8mz_comet/2018_0315Briken21_vs_20180611_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0315Briken22: results/pyprophet/20180611/whole_8mz_comet/2018_0315Briken22_vs_20180611_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0315Briken23: results/pyprophet/20180611/whole_8mz_comet/2018_0315Briken23_vs_20180611_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0315Briken24: results/pyprophet/20180611/whole_8mz_comet/2018_0315Briken24_vs_20180611_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0315Briken25: results/pyprophet/20180611/whole_8mz_comet/2018_0315Briken25_vs_20180611_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0315Briken26: results/pyprophet/20180611/whole_8mz_comet/2018_0315Briken26_vs_20180611_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0502BrikenDIA07: results/pyprophet/20180611/whole_8mz_comet/2018_0502BrikenDIA07_vs_20180611_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0502BrikenDIA08: results/pyprophet/20180611/whole_8mz_comet/2018_0502BrikenDIA08_vs_20180611_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0502BrikenDIA09: results/pyprophet/20180611/whole_8mz_comet/2018_0502BrikenDIA09_vs_20180611_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0502BrikenDIA11: results/pyprophet/20180611/whole_8mz_comet/2018_0502BrikenDIA11_vs_20180611_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0502BrikenDIA12: results/pyprophet/20180611/whole_8mz_comet/2018_0502BrikenDIA12_vs_20180611_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0502BrikenDIA01: results/pyprophet/20180611/whole_8mz_comet/2018_0502BrikenDIA01_vs_20180611_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0502BrikenDIA02: results/pyprophet/20180611/whole_8mz_comet/2018_0502BrikenDIA02_vs_20180611_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0502BrikenDIA03: results/pyprophet/20180611/whole_8mz_comet/2018_0502BrikenDIA03_vs_20180611_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0502BrikenDIA04: results/pyprophet/20180611/whole_8mz_comet/2018_0502BrikenDIA04_vs_20180611_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0502BrikenDIA05: results/pyprophet/20180611/whole_8mz_comet/2018_0502BrikenDIA05_vs_20180611_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0502BrikenDIA06: results/pyprophet/20180611/whole_8mz_comet/2018_0502BrikenDIA06_vs_20180611_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0726Briken01: results/08pyprophet/20180806/whole_8mz/2018_0726Briken01_vs_20180806_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0726Briken02: results/08pyprophet/20180806/whole_8mz/2018_0726Briken02_vs_20180806_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0726Briken04: results/08pyprophet/20180806/whole_8mz/2018_0726Briken04_vs_20180806_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0726Briken05: results/08pyprophet/20180806/whole_8mz/2018_0726Briken05_vs_20180806_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0726Briken06: results/08pyprophet/20180806/whole_8mz/2018_0726Briken06_vs_20180806_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0726Briken07: results/08pyprophet/20180806/whole_8mz/2018_0726Briken07_vs_20180806_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0726Briken08: results/08pyprophet/20180806/whole_8mz/2018_0726Briken08_vs_20180806_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0726Briken09: results/08pyprophet/20180806/whole_8mz/2018_0726Briken09_vs_20180806_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0726Briken12: results/08pyprophet/20180806/whole_8mz/2018_0726Briken12_vs_20180806_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0726Briken13: results/08pyprophet/20180806/whole_8mz/2018_0726Briken13_vs_20180806_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0726Briken14: results/08pyprophet/20180806/whole_8mz/2018_0726Briken14_vs_20180806_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0726Briken15: results/08pyprophet/20180806/whole_8mz/2018_0726Briken15_vs_20180806_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0726Briken16: results/08pyprophet/20180806/whole_8mz/2018_0726Briken16_vs_20180806_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0726Briken17: results/08pyprophet/20180806/whole_8mz/2018_0726Briken17_vs_20180806_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0726Briken18: results/08pyprophet/20180806/whole_8mz/2018_0726Briken18_vs_20180806_whole_HCD_dia_scored.tsv.
## Attempting to read the tsv file for: 2018_0726Briken19: results/08pyprophet/20180806/whole_8mz/2018_0726Briken19_vs_20180806_whole_HCD_dia_scored.tsv.
our_mass_plot <- sm(plot_pyprophet_distribution(our_pyprophet_fun, column="mass"))
our_mass_plot[["violin"]]

our_deltart_plot_all <- sm(plot_pyprophet_distribution(
  our_pyprophet_fun, column="delta_rt"))
our_deltart_plot_all[["violin"]]

our_deltart_plot_real <- sm(plot_pyprophet_distribution(
  our_pyprophet_fun,
  column="delta_rt", keep_decoys=FALSE))
our_deltart_plot_real[["violin"]]

our_deltart_plot_decoys <- sm(plot_pyprophet_distribution(
  our_pyprophet_fun,
  column="delta_rt", keep_real=FALSE))
our_deltart_plot_decoys[["violin"]]

our_dscore_plot <- sm(plot_pyprophet_distribution(
  our_pyprophet_fun,
  column="d_score"))
our_dscore_plot[["violin"]]

our_mscore_plot <- sm(plot_pyprophet_distribution(
  our_pyprophet_fun,
  column="m_score"))
our_mscore_plot[["violin"]]

our_widthvsmass <- sm(plot_pyprophet_data(our_pyprophet_fun, legend=FALSE))
our_widthvsmass$plot

3.3.2 The tuberculist data

tb_pyprophet_fun <- sm(extract_pyprophet_data(
  metadata=paste0("sample_sheets/Mtb_dia_samples_", ver, ".xlsx"),
  pyprophet_column="tuberculistscored"))

tb_mass_plot <- sm(plot_pyprophet_distribution(tb_pyprophet_fun, column="mass"))
tb_mass_plot[["violin"]]

tb_deltart_plot_all <- sm(plot_pyprophet_distribution(
  tb_pyprophet_fun, column="delta_rt"))
tb_deltart_plot_all[["violin"]]

tb_deltart_plot_real <- sm(plot_pyprophet_distribution(
  tb_pyprophet_fun,
  column="delta_rt", keep_decoys=FALSE))
tb_deltart_plot_real[["violin"]]

tb_deltart_plot_decoys <- sm(plot_pyprophet_distribution(
  tb_pyprophet_fun,
  column="delta_rt", keep_real=FALSE))
tb_deltart_plot_decoys[["violin"]]

3.4 MSstats

msstats.org seems to provide a complete solution for performing reasonable metrics of this data.

I am currently reading: http://msstats.org/wp-content/uploads/2017/01/MSstats_v3.7.3_manual.pdf

I made some moderately intrusive changes to MSstats to make it clearer, as well.

3.4.1 Comet derived msstats

Let us invoke MSstats with the SWATH2stats derived data.

tt <- sm(devtools::load_all("~/scratch/git/MSstats"))
checkpoint <- "our_dataprocess.rda"
if (file.exists(checkpoint)) {
  load(file=checkpoint)
} else {
  our_msstats_quant <- sm(dataProcess(our_msstats_input))
  save(file=checkpoint, list=c("our_msstats_quant"))
}
checkpoint <- "our_plots.rda"
if (file.exists(checkpoint)) {
  load(file=checkpoint)
} else {
  our_msstats_plots <- sm(dataProcessPlots(our_msstats_quant, type="QCPLOT"))
  save(file=checkpoint, list=c("our_msstats_plots"))
}

my_levels <- levels(as.factor(our_msstats_input$condition))
my_levels
## [1] "wt_filtrate"    "wt_whole"       "delta_whole"    "comp_whole"    
## [5] "delta_filtrate" "comp_filtrate"
comparisons <- ghetto_contrast_matrix(
  numerators=c("wt_filtrate", "delta_filtrate", "comp_filtrate",
               "delta_filtrate", "comp_filtrate", "delta_whole",
               "comp_whole"),
  denominators=c("wt_whole", "delta_whole", "comp_whole",
                 "wt_filtrate", "wt_filtrate", "wt_whole",
                 "wt_whole"))

our_results <- list()
checkpoint <- "our_group.rda"
if (file.exists(checkpoint)) {
  load(file=checkpoint)
} else {
  for (c in 1:length(rownames(comparisons))) {
    name <- rownames(comparisons)[c]
    message("Starting ", name)
    comp <- comparisons[c, ]
    comp <- t(as.matrix(comp))
    rownames(comp) <- name
    result <- sm(MSstats::groupComparison(contrast.matrix=comp,
                                          data=our_msstats_quant))
    our_results[[name]] <- result
  }
  save(file=checkpoint, list=c("our_results"))
}

3.4.2 Tuberculist derived msstats

checkpoint <- "tb_dataprocess.rda"
if (file.exists(checkpoint)) {
  load(file=checkpoint)
} else {
  tb_msstats_quant <- sm(dataProcess(tb_msstats_input))
  save(file=checkpoint, list=c("tb_msstats_quant"))
}
checkpoint <- "tb_plots.rda"
if (file.exists(checkpoint)) {
  load(file=checkpoint)
} else {
  tb_msstats_plots <- sm(dataProcessPlots(tb_msstats_quant, type="QCPLOT"))
  save(file=checkpoint, list=c("tb_msstats_plots"))
}

my_levels <- levels(as.factor(tb_msstats_input$condition))
my_levels
## [1] "wt_filtrate"    "wt_whole"       "delta_whole"    "comp_whole"    
## [5] "delta_filtrate" "comp_filtrate"
comparisons <- ghetto_contrast_matrix(
  numerators=c("wt_filtrate", "delta_filtrate", "comp_filtrate",
               "delta_filtrate", "comp_filtrate", "delta_whole",
               "comp_whole"),
  denominators=c("wt_whole", "delta_whole", "comp_whole",
                 "wt_filtrate", "wt_filtrate", "wt_whole",
                 "wt_whole"))

tb_results <- list()
checkpoint <- "tb_group.rda"
if (file.exists(checkpoint)) {
  load(file=checkpoint)
} else {
  for (c in 1:length(rownames(comparisons))) {
    name <- rownames(comparisons)[c]
    message("Starting ", name)
    comp <- comparisons[c, ]
    comp <- t(as.matrix(comp))
    rownames(comp) <- name
    tb_results[[name]] <- sm(MSstats::groupComparison(contrast.matrix=comp,
                                                      data=tb_msstats_quant))
    message("Finished ", name)
  }
  save(file=checkpoint, list=c("tb_results"))
}

3.4.3 P/PE protein QC plots for Yan

Yan asked for the p/pe protein qc plots. ok. I changed the dataProcessPlots to return something useful, so that should be possible now.

pe_genes <- read.table("reference/annotated_pe_genes.txt")[[1]]

## Unfortunately, the names did not get set in my changed version of dataProcessPlots...
plotlst <- our_msstats_plots$QCPLOT
available_plots <- gsub(pattern="^1/", replacement="",
                        x=levels(our_msstats_quant$ProcessedData$PROTEIN))
names(plotlst) <- available_plots

pe_in_avail_idx <- pe_genes %in% available_plots
pe_in_avail <- pe_genes[pe_in_avail_idx]
pe_plots <- plotlst[pe_in_avail]
pdf(file="pe_qc_plots.pdf")
for (p in 1:length(pe_plots)) {
  plot(pe_plots[[p]])
}
## Warning: Removed 102 rows containing non-finite values (stat_boxplot).
## Warning: Removed 78 rows containing non-finite values (stat_boxplot).
## Warning: Removed 162 rows containing non-finite values (stat_boxplot).
## Warning: Removed 36 rows containing non-finite values (stat_boxplot).
## Warning: Removed 102 rows containing non-finite values (stat_boxplot).
## Warning: Removed 252 rows containing non-finite values (stat_boxplot).
## Warning: Removed 114 rows containing non-finite values (stat_boxplot).
## Warning: Removed 18 rows containing non-finite values (stat_boxplot).
## Warning: Removed 54 rows containing non-finite values (stat_boxplot).
## Warning: Removed 228 rows containing non-finite values (stat_boxplot).
## Warning: Removed 96 rows containing non-finite values (stat_boxplot).
## Warning: Removed 174 rows containing non-finite values (stat_boxplot).
## Warning: Removed 108 rows containing non-finite values (stat_boxplot).
## Warning: Removed 342 rows containing non-finite values (stat_boxplot).
## Warning: Removed 396 rows containing non-finite values (stat_boxplot).
## Warning: Removed 180 rows containing non-finite values (stat_boxplot).
## Warning: Removed 66 rows containing non-finite values (stat_boxplot).
dev.off()
## png 
##   2
length(pe_plots)
## [1] 19

4 Create hpgltools expressionset

Since I am not certain I understand these data, I will take the intensities from SWATH2stats, metadata, and annotation data; attempt to create a ‘normal’ expressionset; poke at it to see what I can learn.

4.1 Massaging the metadata

I want to use the same metadata as were used for MSstats. It has a few important differences from the requirements of hpgltools: pretty much only that I do not allow rownames/sampleIDs to start with a number.

4.2 Massaging the intensity matrix

I do not want the \1 before the protein names, I already merged them into one entry per gene vis SWATH2stats.

4.2.1 Make matrices with our libraries

our_prot_mtrx <- read.csv(file.path("results", "swath2stats", ver, "our_protein_matrix_minimum.csv"))
rownames(our_prot_mtrx) <- gsub(pattern="^1\\/", replacement="", x=our_prot_mtrx[["proteinname"]])
our_prot_mtrx <- our_prot_mtrx[, -1]
## Important question: Did SWATH2stats reorder my data?
colnames(our_prot_mtrx) <- gsub(pattern="^(.*)(2018.*)$", replacement="s\\2", x=colnames(our_prot_mtrx))

4.2.2 Make matrices with the tb libraries

tb_prot_mtrx <- read.csv(file.path("results", "swath2stats", ver, "tb_protein_matrix_minimum.csv"))
rownames(tb_prot_mtrx) <- gsub(pattern="^1\\/", replacement="", x=tb_prot_mtrx[["proteinname"]])
tb_prot_mtrx <- tb_prot_mtrx[, -1]
## Important question: Did SWATH2stats reorder my data?
colnames(tb_prot_mtrx) <- gsub(pattern="^(.*)(2018.*)$", replacement="s\\2", x=colnames(tb_prot_mtrx))

4.3 Merge the pieces

Now we should have sufficient pieces to make an expressionset.

While here, I will also split the data into a cf and whole-cell pair of data structures.

4.3.1 Our data

## Drop the metadata not in the protein matrix:
## And ensure that they are the same order.
reordered <- colnames(our_prot_mtrx)
metadata <- sample_annot[reordered, ]

our_protein_expt <- create_expt(metadata=metadata,
                                count_dataframe=our_prot_mtrx,
                                gene_info=mtb_annotations)
## Reading the sample metadata.
## The sample definitions comprises: 16 rows(samples) and 27 columns(metadata fields).
## Matched 817 annotations and counts.
## Bringing together the count matrix and gene information.
## Some annotations were lost in merging, setting them to 'undefined'.
our_whole_expt <- subset_expt(our_protein_expt, subset="collectiontype=='whole'")
## There were 16, now there are 8 samples.
our_cf_expt <- subset_expt(our_protein_expt, subset="collectiontype=='filtrate'")
## There were 16, now there are 8 samples.

4.3.2 Tb data

## Drop the metadata not in the protein matrix:
## And ensure that they are the same order.
reordered <- colnames(tb_prot_mtrx)
metadata <- sample_annot[reordered, ]

tb_protein_expt <- sm(create_expt(metadata,
                                  count_dataframe=tb_prot_mtrx,
                                  gene_info=mtb_annotations))
tb_whole_expt <- subset_expt(tb_protein_expt, subset="collectiontype=='whole'")
## There were 39, now there are 19 samples.
tb_cf_expt <- subset_expt(tb_protein_expt, subset="collectiontype=='filtrate'")
## There were 39, now there are 20 samples.

4.4 Metrics of the full data set

4.4.1 Our libraries

our_protein_metrics <- sm(graph_metrics(our_protein_expt))
our_protein_norm <- sm(normalize_expt(our_protein_expt, transform="log2", convert="cpm",
                                      norm="quant", filter=TRUE))
our_protein_norm_metrics <- sm(graph_metrics(our_protein_norm))
our_protein_fsva <- sm(normalize_expt(our_protein_expt, transform="log2",
                                   batch="fsva", filter=TRUE))
our_protein_fsva_metrics <- sm(graph_metrics(our_protein_fsva))

4.4.2 Tb libraries

tb_protein_metrics <- sm(graph_metrics(tb_protein_expt))
tb_protein_norm <- sm(normalize_expt(tb_protein_expt, transform="log2", convert="cpm",
                                      norm="quant", filter=TRUE))
tb_protein_norm_metrics <- sm(graph_metrics(tb_protein_norm))
tb_protein_fsva <- sm(normalize_expt(tb_protein_expt, transform="log2", convert="cpm",
                                      batch="fsva", filter=TRUE))
tb_protein_fsva_metrics <- sm(graph_metrics(tb_protein_fsva))

4.5 Metrics of the whole-cell data set

4.5.1 Our libraries

our_whole_metrics <- sm(graph_metrics(our_whole_expt))
our_whole_norm <- sm(normalize_expt(our_whole_expt, transform="log2", convert="cpm",
                                    norm="quant", filter=TRUE))
our_whole_norm_metrics <- sm(graph_metrics(our_whole_norm))
our_whole_fsva <- sm(normalize_expt(our_whole_expt, transform="log2", convert="cpm",
                                    batch="fsva", filter=TRUE))
our_whole_fsva_metrics <- sm(graph_metrics(our_whole_fsva))
our_whole_varpart <- varpart(our_whole_expt)
## varpart sees only 1 batch, adjusting the model accordingly.
## Attempting mixed linear model with: ~  (1|condition)
## Fitting the expressionset to the model, this is slow.
## Projected run time: ~ 0.04 min
## Placing factor: condition at the beginning of the model.
our_whole_varpart$partition_plot

our_whole_cv <- plot_variance_coefficients(our_protein_expt)
## Naively calculating coefficient of variation and quartile dispersion with respect to condition.
## Finished calculating dispersion estimates.
our_whole_cv$disp

our_batch_cv <- plot_variance_coefficients(our_protein_expt, x_axis="batch")
## Naively calculating coefficient of variation and quartile dispersion with respect to batch.
## Finished calculating dispersion estimates.
our_batch_cv$disp

our_genotype_cv <- plot_variance_coefficients(our_protein_expt, x_axis="genotype")
## Naively calculating coefficient of variation and quartile dispersion with respect to genotype.
## Finished calculating dispersion estimates.
our_genotype_cv$disp

our_prep_cv <- plot_variance_coefficients(our_protein_expt, x_axis="prepdate")
## Naively calculating coefficient of variation and quartile dispersion with respect to prepdate.
## Finished calculating dispersion estimates.
our_prep_cv$disp

4.5.2 Tb libraries

tb_whole_metrics <- sm(graph_metrics(tb_whole_expt))
tb_whole_norm <- sm(normalize_expt(tb_whole_expt, transform="log2", convert="cpm",
                                    norm="quant", filter=TRUE))
tb_whole_norm_metrics <- sm(graph_metrics(tb_whole_norm))
tb_whole_fsva <- sm(normalize_expt(tb_whole_expt, transform="log2", convert="cpm",
                                    batch="fsva", filter=TRUE))
tb_whole_fsva_metrics <- sm(graph_metrics(tb_whole_fsva))
tb_whole_varpart <- varpart(tb_whole_expt)
## Attempting mixed linear model with: ~  (1|condition) + (1|batch)
## Fitting the expressionset to the model, this is slow.
## Projected run time: ~ 0.2 min
## Placing factor: condition at the beginning of the model.
tb_whole_varpart$partition_plot

tb_whole_cv <- plot_variance_coefficients(tb_protein_expt)
## Naively calculating coefficient of variation and quartile dispersion with respect to condition.
## Finished calculating dispersion estimates.
tb_whole_cv$disp

tb_batch_cv <- plot_variance_coefficients(tb_protein_expt, x_axis="batch")
## Naively calculating coefficient of variation and quartile dispersion with respect to batch.
## Finished calculating dispersion estimates.
tb_batch_cv$disp

tb_genotype_cv <- plot_variance_coefficients(tb_protein_expt, x_axis="genotype")
## Naively calculating coefficient of variation and quartile dispersion with respect to genotype.
## Finished calculating dispersion estimates.
tb_genotype_cv$disp

tb_prep_cv <- plot_variance_coefficients(tb_protein_expt, x_axis="prepdate")
## Naively calculating coefficient of variation and quartile dispersion with respect to prepdate.
## Finished calculating dispersion estimates.
tb_prep_cv$disp

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

4.6 Metrics of the filtrate data set

4.6.1 Our libraries

our_cf_metrics <- sm(graph_metrics(our_cf_expt))
our_cf_norm <- sm(normalize_expt(our_cf_expt, transform="log2", convert="cpm",
                                 norm="quant", filter=TRUE))
our_cf_norm_metrics <- sm(graph_metrics(our_cf_norm))
our_cf_fsva <- sm(normalize_expt(our_cf_expt, transform="log2", convert="cpm",
                                 batch="fsva", filter=TRUE))
our_cf_fsva_metrics <- sm(graph_metrics(our_cf_fsva))

4.6.2 Tb libraries

tb_cf_metrics <- sm(graph_metrics(tb_cf_expt))
tb_cf_norm <- sm(normalize_expt(tb_cf_expt, transform="log2", convert="cpm",
                                 norm="quant", filter=TRUE))
tb_cf_norm_metrics <- sm(graph_metrics(tb_cf_norm))
tb_cf_fsva <- sm(normalize_expt(tb_cf_expt, transform="log2", convert="cpm",
                                 batch="fsva", filter=TRUE))
tb_cf_fsva_metrics <- sm(graph_metrics(tb_cf_fsva))

4.7 plot some metrics

4.7.1 Our libraries

pp(image=our_protein_metrics$libsize,
   file=file.path("images", paste0(ver, "_our_libsize.png")))
## Writing the image to: images/20180806_our_libsize.png and calling dev.off().

## It seems to me that the scale of the data is all within an order of magnitude or two.
## I cannot get used to these absurdly large numbers though.
pp(image=our_protein_norm_metrics$pcaplot,
   file=file.path("images", paste0(ver, "_our_norm_pca.png")))
## Writing the image to: images/20180806_our_norm_pca.png and calling dev.off().
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse

## There appears to be a nice split in the data, however the un-assayable batch
## effect is a problem.
pp(image=our_protein_fsva_metrics$pcaplot,
   file=file.path("images", paste0(ver, "_fsva_pca.png")))
## Writing the image to: images/20180806_fsva_pca.png and calling dev.off().
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse

## fsva seems to get some handle on the data, but I don't think we should rely
## upon it.
pp(image=our_protein_norm_metrics$corheat,
   file=file.path("images", paste0(ver, "_norm_corheat.png")))
## Writing the image to: images/20180806_norm_corheat.png and calling dev.off().

## Once again, the whole-cell/culture-filtrate split is very large.
pp(image=our_protein_metrics$density,
   file=file.path("images", paste0(ver, "_raw_density.png")))
## Writing the image to: images/20180806_raw_density.png and calling dev.off().

## There are two obvious distributions in the data, once again split between types.
pp(image=our_protein_metrics$boxplot,
   file=file.path("images", paste0(ver, "_boxplot.png")))
## Writing the image to: images/20180806_boxplot.png and calling dev.off().

## This recapitulates the previous plot.

pp(image=our_whole_metrics$libsize,
   file=file.path("images", paste0(ver, "_whole_libsize.png")))
## Writing the image to: images/20180806_whole_libsize.png and calling dev.off().

pp(image=our_whole_norm_metrics$pcaplot,
   file=file.path("images", paste0(ver, "_whole_norm_pca.png")))
## Writing the image to: images/20180806_whole_norm_pca.png and calling dev.off().
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse

pp(image=our_whole_fsva_metrics$pcaplot,
   file=file.path("images", paste0(ver, "_whole_fsva_pca.png")))
## Writing the image to: images/20180806_whole_fsva_pca.png and calling dev.off().
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse

pp(image=our_whole_norm_metrics$corheat,
   file=file.path("images", paste0(ver, "_whole_norm_corheat.png")))
## Writing the image to: images/20180806_whole_norm_corheat.png and calling dev.off().

pp(image=our_whole_metrics$density,
   file=file.path("images", paste0(ver, "_whole_raw_density.png")))
## Writing the image to: images/20180806_whole_raw_density.png and calling dev.off().

pp(image=our_whole_metrics$boxplot,
   file=file.path("images", paste0(ver, "_whole_boxplot.png")))
## Writing the image to: images/20180806_whole_boxplot.png and calling dev.off().

pp(image=our_cf_metrics$libsize,
   file=file.path("images", paste0(ver, "_libsize.png")))
## Writing the image to: images/20180806_libsize.png and calling dev.off().

pp(image=our_cf_norm_metrics$pcaplot,
   file=file.path("images", paste0(ver, "_norm_pca.png")))
## Writing the image to: images/20180806_norm_pca.png and calling dev.off().
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse

pp(image=our_cf_fsva_metrics$pcaplot,
   file=file.path("images", paste0(ver, "_fsva_pca.png")))
## Writing the image to: images/20180806_fsva_pca.png and calling dev.off().
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse

pp(image=our_cf_norm_metrics$corheat,
   file=file.path("images", paste0(ver, "_norm_corheat.png")))
## Writing the image to: images/20180806_norm_corheat.png and calling dev.off().

pp(image=our_cf_metrics$density,
   file=file.path("images", paste0(ver, "_raw_density.png")))
## Writing the image to: images/20180806_raw_density.png and calling dev.off().

pp(image=our_cf_metrics$boxplot,
   file=file.path("images", paste0(ver, "_boxplot.png")))
## Writing the image to: images/20180806_boxplot.png and calling dev.off().

4.7.2 Tb libraries

pp(image=tb_protein_metrics$libsize,
   file=file.path("images", paste0(ver, "_tb_libsize.png")))
## Writing the image to: images/20180806_tb_libsize.png and calling dev.off().

## It seems to me that the scale of the data is all within an order of magnitude or two.
## I cannot get used to these absurdly large numbers though.
pp(image=tb_protein_norm_metrics$pcaplot,
   file=file.path("images", paste0(ver, "_tb_norm_pca.png")))
## Writing the image to: images/20180806_tb_norm_pca.png and calling dev.off().

## There appears to be a nice split in the data, however the un-assayable batch
## effect is a problem.
pp(image=tb_protein_fsva_metrics$pcaplot,
   file=file.path("images", paste0(ver, "_fsva_pca.png")))
## Writing the image to: images/20180806_fsva_pca.png and calling dev.off().

## fsva seems to get some handle on the data, but I don't think we should rely
## upon it.
pp(image=tb_protein_norm_metrics$corheat,
   file=file.path("images", paste0(ver, "_norm_corheat.png")))
## Writing the image to: images/20180806_norm_corheat.png and calling dev.off().

## Once again, the whole-cell/culture-filtrate split is very large.
pp(image=tb_protein_metrics$density,
   file=file.path("images", paste0(ver, "_raw_density.png")))
## Writing the image to: images/20180806_raw_density.png and calling dev.off().

## There are two obvious distributions in the data, once again split between types.
pp(image=tb_protein_metrics$boxplot,
   file=file.path("images", paste0(ver, "_boxplot.png")))
## Writing the image to: images/20180806_boxplot.png and calling dev.off().

## This recapitulates the previous plot.

pp(image=tb_whole_metrics$libsize,
   file=file.path("images", paste0(ver, "_whole_libsize.png")))
## Writing the image to: images/20180806_whole_libsize.png and calling dev.off().

pp(image=tb_whole_norm_metrics$pcaplot,
   file=file.path("images", paste0(ver, "_whole_norm_pca.png")))
## Writing the image to: images/20180806_whole_norm_pca.png and calling dev.off().

pp(image=tb_whole_fsva_metrics$pcaplot,
   file=file.path("images", paste0(ver, "_whole_fsva_pca.png")))
## Writing the image to: images/20180806_whole_fsva_pca.png and calling dev.off().

pp(image=tb_whole_norm_metrics$corheat,
   file=file.path("images", paste0(ver, "_whole_norm_corheat.png")))
## Writing the image to: images/20180806_whole_norm_corheat.png and calling dev.off().

pp(image=tb_whole_metrics$density,
   file=file.path("images", paste0(ver, "_whole_raw_density.png")))
## Writing the image to: images/20180806_whole_raw_density.png and calling dev.off().

pp(image=tb_whole_metrics$boxplot,
   file=file.path("images", paste0(ver, "_whole_boxplot.png")))
## Writing the image to: images/20180806_whole_boxplot.png and calling dev.off().

pp(image=tb_cf_metrics$libsize,
   file=file.path("images", paste0(ver, "_libsize.png")))
## Writing the image to: images/20180806_libsize.png and calling dev.off().

pp(image=tb_cf_norm_metrics$pcaplot,
   file=file.path("images", paste0(ver, "_norm_pca.png")))
## Writing the image to: images/20180806_norm_pca.png and calling dev.off().

pp(image=tb_cf_fsva_metrics$pcaplot,
   file=file.path("images", paste0(ver, "_fsva_pca.png")))
## Writing the image to: images/20180806_fsva_pca.png and calling dev.off().

pp(image=tb_cf_norm_metrics$corheat,
   file=file.path("images", paste0(ver, "_norm_corheat.png")))
## Writing the image to: images/20180806_norm_corheat.png and calling dev.off().

pp(image=tb_cf_metrics$density,
   file=file.path("images", paste0(ver, "_raw_density.png")))
## Writing the image to: images/20180806_raw_density.png and calling dev.off().

pp(image=tb_cf_metrics$boxplot,
   file=file.path("images", paste0(ver, "_boxplot.png")))
## Writing the image to: images/20180806_boxplot.png and calling dev.off().

5 Collapse technical replicates

I am thinking that a simple sum of the data in the technical replicates should be sufficient.

our_compressed <- concatenate_runs(our_protein_expt, column="bioreplicate")
## The original expressionset has 16 samples.
## The final expressionset has 16 samples.
tb_compressed <- concatenate_runs(tb_protein_expt, column="bioreplicate")
## The original expressionset has 39 samples.
## The final expressionset has 18 samples.
our_whole_compressed <- concatenate_runs(our_whole_expt, column="bioreplicate")
## The original expressionset has 8 samples.
## The final expressionset has 8 samples.
our_cf_compressed <- concatenate_runs(our_cf_expt, column="bioreplicate")
## The original expressionset has 8 samples.
## The final expressionset has 8 samples.
tb_whole_compressed <- concatenate_runs(tb_whole_expt, column="bioreplicate")
## The original expressionset has 19 samples.
## The final expressionset has 9 samples.
tb_cf_compressed <- concatenate_runs(tb_cf_expt, column="bioreplicate")
## The original expressionset has 20 samples.
## The final expressionset has 9 samples.

5.1 Reperform metrics with the technical replicates removed.

our_compressed_metrics <- sm(graph_metrics(our_compressed))
our_compressed_norm <- sm(normalize_expt(our_compressed, transform="log2", convert="cpm",
                                         norm="quant", filter=TRUE))
our_compressed_norm_metrics <- sm(graph_metrics(our_compressed_norm))
tb_compressed_metrics <- sm(graph_metrics(tb_compressed))
tb_compressed_norm <- sm(normalize_expt(tb_compressed, transform="log2", convert="cpm",
                                         norm="quant", filter=TRUE))
tb_compressed_norm_metrics <- sm(graph_metrics(tb_compressed_norm))
our_compressed_norm_metrics$pcaplot
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse

tb_compressed_norm_metrics$pcaplot
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse
## Too few points to calculate an ellipse

our_compressed_de <- all_pairwise(our_compressed, model_batch=FALSE, force=TRUE)
## There is just one batch in this data.
## Assuming no batch in model for testing pca.
## There is just one batch in this data.
## Finished running DE analyses, collecting outputs.
## Comparing analyses 1/15: comp_whole_vs_comp_filtrate
## Comparing analyses 2/15: delta_filtrate_vs_comp_filtrate
## Comparing analyses 3/15: delta_whole_vs_comp_filtrate
## Comparing analyses 4/15: wt_filtrate_vs_comp_filtrate
## Comparing analyses 5/15: wt_whole_vs_comp_filtrate
## Comparing analyses 6/15: delta_filtrate_vs_comp_whole
## Comparing analyses 7/15: delta_whole_vs_comp_whole
## Comparing analyses 8/15: wt_filtrate_vs_comp_whole
## Comparing analyses 9/15: wt_whole_vs_comp_whole
## Comparing analyses 10/15: delta_whole_vs_delta_filtrate
## Comparing analyses 11/15: wt_filtrate_vs_delta_filtrate
## Comparing analyses 12/15: wt_whole_vs_delta_filtrate
## Comparing analyses 13/15: wt_filtrate_vs_delta_whole
## Comparing analyses 14/15: wt_whole_vs_delta_whole
## Comparing analyses 15/15: wt_whole_vs_wt_filtrate

tb_compressed_de <- all_pairwise(tb_compressed, model_batch=FALSE, force=TRUE)
## Assuming no batch in model for testing pca.
## Finished running DE analyses, collecting outputs.
## Comparing analyses 1/15: comp_whole_vs_comp_filtrate
## Comparing analyses 2/15: delta_filtrate_vs_comp_filtrate
## Comparing analyses 3/15: delta_whole_vs_comp_filtrate
## Comparing analyses 4/15: wt_filtrate_vs_comp_filtrate
## Comparing analyses 5/15: wt_whole_vs_comp_filtrate
## Comparing analyses 6/15: delta_filtrate_vs_comp_whole
## Comparing analyses 7/15: delta_whole_vs_comp_whole
## Comparing analyses 8/15: wt_filtrate_vs_comp_whole
## Comparing analyses 9/15: wt_whole_vs_comp_whole
## Comparing analyses 10/15: delta_whole_vs_delta_filtrate
## Comparing analyses 11/15: wt_filtrate_vs_delta_filtrate
## Comparing analyses 12/15: wt_whole_vs_delta_filtrate
## Comparing analyses 13/15: wt_filtrate_vs_delta_whole
## Comparing analyses 14/15: wt_whole_vs_delta_whole
## Comparing analyses 15/15: wt_whole_vs_wt_filtrate

6 Attempt some quantification comparisons?

6.1 Our libraries

our_pairwise_filt <- sm(normalize_expt(our_compressed, filter=TRUE))
our_pairwise_comp <- sm(all_pairwise(our_pairwise_filt, model_batch="fsva", force=TRUE))
our_pairwise_nobatch <- sm(all_pairwise(our_pairwise_filt, model_batch=FALSE, force=TRUE))

6.2 Tb libraries

tb_pairwise_filt <- sm(normalize_expt(tb_compressed, filter=TRUE))
tb_pairwise_comp <- sm(all_pairwise(tb_pairwise_filt, model_batch="fsva", force=TRUE))
tb_pairwise_nobatch <- sm(all_pairwise(tb_pairwise_filt, model_batch=FALSE, force=TRUE))

6.2.1 Show a few metrics from the hpgltools pairwise comparisons

our_compressed_de$comparison$heat

tb_compressed_de$comparison$heat

7 For each msstats run, do a DE table

7.1 wt_cf vs wt_whole

7.1.1 Our libraries

keepers <- list(
  "wtcf_vs_wtwhole" = c("wt_filtrate", "wt_whole"))

set_name <- "wt_filtrate_vs_wt_whole"
msstats_result <- our_results[[set_name]][["ComparisonResult"]]
droppers <- c("undefined")
names(droppers) <- "log2fc"
## Make sure to set the rownames so it will merge into the excel file.
rownames(msstats_result) <- msstats_result[["Protein"]]

our_wtcf_wtwhole_tables <- sm(combine_de_tables(
  our_compressed_de, keepers=keepers, extra_annot=msstats_result,
  excludes=droppers,
  excel=paste0("excel/our_wtcf_vs_wtwhole_tables-v", ver, ".xlsx")))
our_wtcf_nobatch_wtwhole_tables <- sm(combine_de_tables(
  our_pairwise_nobatch, keepers=keepers, extra_annot=msstats_result,
  excludes=droppers,
  excel=paste0("excel/our_wtcf_vs_wtwhole_nobatch_tables-v", ver, ".xlsx")))
comp_table <- our_wtcf_wtwhole_tables$data[[set_name]]
cor.test(comp_table$log2fc, comp_table$limma_logfc, method="spearman")
## Warning in cor.test.default(comp_table$log2fc, comp_table$limma_logfc,
## method = "spearman"): Cannot compute exact p-value with ties
## 
##  Spearman's rank correlation rho
## 
## data:  comp_table$log2fc and comp_table$limma_logfc
## S = 3.6e+07, p-value <2e-16
## alternative hypothesis: true rho is not equal to 0
## sample estimates:
##    rho 
## 0.5859
comp_table <- our_wtcf_nobatch_wtwhole_tables$data[[set_name]]
cor.test(comp_table$log2fc, comp_table$limma_logfc, method="spearman")
## Warning in cor.test.default(comp_table$log2fc, comp_table$limma_logfc,
## method = "spearman"): Cannot compute exact p-value with ties
## 
##  Spearman's rank correlation rho
## 
## data:  comp_table$log2fc and comp_table$limma_logfc
## S = 3.6e+07, p-value <2e-16
## alternative hypothesis: true rho is not equal to 0
## sample estimates:
##    rho 
## 0.5883

7.1.2 Tb libraries

msstats_result <- tb_results[[set_name]][["ComparisonResult"]]
droppers <- c("undefined")
names(droppers) <- "log2fc"
## Make sure to set the rownames so it will merge into the excel file.
rownames(msstats_result) <- msstats_result[["Protein"]]

tb_wtcf_wtwhole_tables <- sm(combine_de_tables(
  tb_pairwise_comp, keepers=keepers, extra_annot=msstats_result,
  excludes=droppers,
  excel=paste0("excel/tb_wtcf_vs_wtwhole_tables-v", ver, ".xlsx")))
tb_wtcf_nobatch_wtwhole_tables <- sm(combine_de_tables(
  tb_pairwise_nobatch, keepers=keepers, extra_annot=msstats_result,
  excludes=droppers,
  excel=paste0("excel/tb_wtcf_vs_wtwhole_nobatch_tables-v", ver, ".xlsx")))
comp_table <- tb_wtcf_wtwhole_tables$data[[set_name]]
cor.test(comp_table$log2fc, comp_table$limma_logfc, method="spearman")
## Warning in cor.test.default(comp_table$log2fc, comp_table$limma_logfc,
## method = "spearman"): Cannot compute exact p-value with ties
## 
##  Spearman's rank correlation rho
## 
## data:  comp_table$log2fc and comp_table$limma_logfc
## S = 1.8e+09, p-value <2e-16
## alternative hypothesis: true rho is not equal to 0
## sample estimates:
##    rho 
## 0.3503
comp_table <- tb_wtcf_nobatch_wtwhole_tables$data[[set_name]]
cor.test(comp_table$log2fc, comp_table$limma_logfc, method="spearman")
## Warning in cor.test.default(comp_table$log2fc, comp_table$limma_logfc,
## method = "spearman"): Cannot compute exact p-value with ties
## 
##  Spearman's rank correlation rho
## 
## data:  comp_table$log2fc and comp_table$limma_logfc
## S = 1.8e+09, p-value <2e-16
## alternative hypothesis: true rho is not equal to 0
## sample estimates:
##    rho 
## 0.3437

7.2 delta_cf vs delta_whole

7.2.1 Our libraries

keepers <- list(
  "deltacf_vs_deltawhole" = c("delta_filtrate", "delta_whole"))

set_name <- "delta_filtrate_vs_delta_whole"
msstats_result <- our_results[[set_name]][["ComparisonResult"]]
## Make sure to set the rownames so it will merge into the excel file.
rownames(msstats_result) <- msstats_result[["Protein"]]

our_deltacf_deltawhole_tables <- sm(combine_de_tables(
  our_pairwise_comp, keepers=keepers, extra_annot=msstats_result,
  excel=paste0("excel/our_deltacf_vs_deltawhole_tables-v", ver, ".xlsx")))

7.2.2 Tb libraries

msstats_result <- tb_results[[set_name]][["ComparisonResult"]]
## Make sure to set the rownames so it will merge into the excel file.
rownames(msstats_result) <- msstats_result[["Protein"]]

tb_deltacf_deltawhole_tables <- sm(combine_de_tables(
  tb_pairwise_comp, keepers=keepers, extra_annot=msstats_result,
  excel=paste0("excel/tb_deltacf_vs_deltawhole_tables-v", ver, ".xlsx")))

7.3 comp_cf vs comp_whole

7.3.1 Our libraries

keepers <- list(
  "compcf_vs_compwhole" = c("comp_filtrate", "comp_whole"))

set_name <- "comp_filtrate_vs_comp_whole"
msstats_result <- our_results[[set_name]][["ComparisonResult"]]
## Make sure to set the rownames so it will merge into the excel file.
rownames(msstats_result) <- msstats_result[["Protein"]]

compcf_compwhole_tables <- sm(combine_de_tables(
  our_pairwise_comp, keepers=keepers, extra_annot=msstats_result,
  excel=paste0("excel/our_compcf_vs_compwhole_tables-v", ver, ".xlsx")))

7.3.2 Tb libraries

msstats_result <- tb_results[[set_name]][["ComparisonResult"]]
## Make sure to set the rownames so it will merge into the excel file.
rownames(msstats_result) <- msstats_result[["Protein"]]

compcf_compwhole_tables <- sm(combine_de_tables(
  tb_pairwise_comp, keepers=keepers, extra_annot=msstats_result,
  excel=paste0("excel/tb_compcf_vs_compwhole_tables-v", ver, ".xlsx")))

7.4 delta_cf vs wt_cf

7.4.1 Our libraries

keepers <- list(
  "deltacf_vs_wtcf" = c("delta_filtrate", "wt_filtrate"))

set_name <- "delta_filtrate_vs_wt_filtrate"
msstats_result <- our_results[[set_name]][["ComparisonResult"]]
## Make sure to set the rownames so it will merge into the excel file.
rownames(msstats_result) <- msstats_result[["Protein"]]

deltacf_wtcf_tables <- sm(combine_de_tables(
  our_pairwise_comp, keepers=keepers, extra_annot=msstats_result,
  excel=paste0("excel/our_deltacf_vs_wtcf_tables-v", ver, ".xlsx")))

7.4.2 Tb libraries

msstats_result <- tb_results[[set_name]][["ComparisonResult"]]
rownames(msstats_result) <- msstats_result[["Protein"]]

deltacf_wtcf_tables <- sm(combine_de_tables(
  tb_pairwise_comp, keepers=keepers, extra_annot=msstats_result,
  excel=paste0("excel/tb_deltacf_vs_wtcf_tables-v", ver, ".xlsx")))
comp_table <- deltacf_wtcf_tables$data[[set_name]]
cor.test(tail(comp_table$log2fc, n=50), tail(comp_table$limma_logfc, n=50), method="spearman")
## Warning in cor.test.default(tail(comp_table$log2fc, n = 50),
## tail(comp_table$limma_logfc, : Cannot compute exact p-value with ties
## 
##  Spearman's rank correlation rho
## 
## data:  tail(comp_table$log2fc, n = 50) and tail(comp_table$limma_logfc, n = 50)
## S = 27000, p-value = 0.008
## alternative hypothesis: true rho is not equal to 0
## sample estimates:
##     rho 
## -0.3741

7.5 comp_cf vs wt_cf

7.5.1 Our libraries

keepers <- list(
  "compcf_vs_wtcf" = c("comp_filtrate", "wt_filtrate"))
set_name <- "comp_filtrate_vs_wt_filtrate"
msstats_result <- our_results[[set_name]][["ComparisonResult"]]
rownames(msstats_result) <- msstats_result[["Protein"]]

compcf_wtcf_tables <- sm(combine_de_tables(
  our_pairwise_comp, keepers=keepers, extra_annot=msstats_result,
  excel=paste0("excel/our_compcf_vs_wtcf_tables-v", ver, ".xlsx")))

7.5.2 Tb libraries

msstats_result <- tb_results[[set_name]][["ComparisonResult"]]
rownames(msstats_result) <- msstats_result[["Protein"]]

compcf_wtcf_tables <- sm(combine_de_tables(
  tb_pairwise_comp, keepers=keepers, extra_annot=msstats_result,
  excel=paste0("excel/tb_compcf_vs_wtcf_tables-v", ver, ".xlsx")))

7.6 delta_whole vs wt_whole

7.6.1 Our libraries

keepers <- list(
  "wtcf_vs_wtwhole" = c("delta_whole", "wt_whole"))
set_name <- "delta_whole_vs_wt_whole"
msstats_result <- our_results[[set_name]][["ComparisonResult"]]
rownames(msstats_result) <- msstats_result[["Protein"]]

wtcf_wtwhole_tables <- sm(combine_de_tables(
  our_pairwise_comp, keepers=keepers, extra_annot=msstats_result,
  excel=paste0("excel/our_deltawhole_vs_wtwhole_tables-v", ver, ".xlsx")))

7.6.2 Tb libraries

msstats_result <- tb_results[[set_name]][["ComparisonResult"]]
rownames(msstats_result) <- msstats_result[["Protein"]]

wtcf_wtwhole_tables <- sm(combine_de_tables(
  tb_pairwise_comp, keepers=keepers, extra_annot=msstats_result,
  excel=paste0("excel/tb_deltawhole_vs_wtwhole_tables-v", ver, ".xlsx")))

7.7 comp_whole vs wt_whole

7.7.1 Our libraries

keepers <- list(
  "compwhole_vs_wtwhole" = c("comp_whole", "wt_whole"))
set_name <- "comp_whole_vs_wt_whole"
msstats_result <- our_results[[set_name]][["ComparisonResult"]]
rownames(msstats_result) <- msstats_result[["Protein"]]

compwhole_wtwhole_tables <- sm(combine_de_tables(
  our_pairwise_comp, keepers=keepers, extra_annot=msstats_result,
  excel=paste0("excel/our_compwhole_vs_wtwhole_tables-v", ver, ".xlsx")))

7.7.2 Tb libraries

msstats_result <- tb_results[[set_name]][["ComparisonResult"]]
rownames(msstats_result) <- msstats_result[["Protein"]]

compwhole_wtwhole_tables <- sm(combine_de_tables(
  tb_pairwise_comp, keepers=keepers, extra_annot=msstats_result,
  excel=paste0("excel/tb_compwhole_vs_wtwhole_tables-v", ver, ".xlsx")))
our_table <- our_pairwise_comp$deseq$all_tables$wt_whole_vs_wt_filtrate
tb_table <- tb_pairwise_comp$deseq$all_tables$wt_whole_vs_wt_filtrate
rownames(tb_table) <- gsub(pattern="^(.*)_.*", replacement="\\1", x=rownames(tb_table))

test_table <- merge(our_table, tb_table, by="row.names")
cor.test(test_table$logFC.x, test_table$logFC.y)
## 
##  Pearson's product-moment correlation
## 
## data:  test_table$logFC.x and test_table$logFC.y
## t = 13, df = 820, p-value <2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.3472 0.4618
## sample estimates:
##    cor 
## 0.4061

8 TODO

  • 2018-04-10: Make sure my invocations of SWATH2stats/MSstats are correct.
if (!isTRUE(get0("skip_load"))) {
  message(paste0("This is hpgltools commit: ", get_git_commit()))
  this_save <- paste0(gsub(pattern="\\.Rmd", replace="", x=rmd_file), "-v", ver, ".rda.xz")
  message(paste0("Saving to ", this_save))
  tmp <- sm(saveme(filename=this_save))
  pander::pander(sessionInfo())
}
LS0tCnRpdGxlOiAiTS50dWJlcmN1bG9zaXMgMjAxODA4MDY6IE5ldyBzYW1wbGVzISBBbmFseXppbmcgZGF0YSBmcm9tIE9wZW5Td2F0aFdvcmtGbG93L1RSSUMuIgphdXRob3I6ICJhdGIgYWJlbGV3QGdtYWlsLmNvbSIKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6CiBodG1sX2RvY3VtZW50OgogIGNvZGVfZG93bmxvYWQ6IHRydWUKICBjb2RlX2ZvbGRpbmc6IHNob3cKICBmaWdfY2FwdGlvbjogdHJ1ZQogIGZpZ19oZWlnaHQ6IDcKICBmaWdfd2lkdGg6IDcKICBoaWdobGlnaHQ6IGRlZmF1bHQKICBrZWVwX21kOiBmYWxzZQogIG1vZGU6IHNlbGZjb250YWluZWQKICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQogIHRoZW1lOiByZWFkYWJsZQogIHRvYzogdHJ1ZQogIHRvY19mbG9hdDoKICAgIGNvbGxhcHNlZDogZmFsc2UKICAgIHNtb290aF9zY3JvbGw6IGZhbHNlCi0tLQoKPHN0eWxlPgogIGJvZHkgLm1haW4tY29udGFpbmVyIHsKICAgIG1heC13aWR0aDogMTYwMHB4OwogIH0KPC9zdHlsZT4KCmBgYHtyIG9wdGlvbnMsIGluY2x1ZGU9RkFMU0V9CmlmICghaXNUUlVFKGdldDAoInNraXBfbG9hZCIpKSkgewogIGxpYnJhcnkoaHBnbHRvb2xzKQogIHR0IDwtIGRldnRvb2xzOjpsb2FkX2FsbCgifi9ocGdsdG9vbHMiKQogIGtuaXRyOjpvcHRzX2tuaXQkc2V0KHByb2dyZXNzPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgdmVyYm9zZT1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgIHdpZHRoPTkwLAogICAgICAgICAgICAgICAgICAgICAgIGVjaG89VFJVRSkKICBrbml0cjo6b3B0c19jaHVuayRzZXQoZXJyb3I9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgZmlnLndpZHRoPTgsCiAgICAgICAgICAgICAgICAgICAgICAgIGZpZy5oZWlnaHQ9OCwKICAgICAgICAgICAgICAgICAgICAgICAgZHBpPTk2KQogIG9sZF9vcHRpb25zIDwtIG9wdGlvbnMoZGlnaXRzPTQsCiAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzPUZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAga25pdHIuZHVwbGljYXRlLmxhYmVsPSJhbGxvdyIpCiAgZ2dwbG90Mjo6dGhlbWVfc2V0KGdncGxvdDI6OnRoZW1lX2J3KGJhc2Vfc2l6ZT0xMCkpCiAgdmVyIDwtICIyMDE4MDYxMSIKICBwcmV2aW91c19maWxlIDwtICIwMV9wcmVwcm9jZXNzaW5nX2NvbWV0X2hpZ2hyZXMuUm1kIgoKICB0bXAgPC0gdHJ5KHNtKGxvYWRtZShmaWxlbmFtZT1wYXN0ZTAoZ3N1YihwYXR0ZXJuPSJcXC5SbWQiLCByZXBsYWNlPSIiLCB4PXByZXZpb3VzX2ZpbGUpLCAiLXYiLCB2ZXIsICIucmRhLnh6IikpKSkKICBwcmV2aW91c19maWxlIDwtICIwMV9hbm5vdGF0aW9uXzIwMTgwNjExLlJtZCIKICB0bXAgPC0gdHJ5KHNtKGxvYWRtZShmaWxlbmFtZT1wYXN0ZTAoZ3N1YihwYXR0ZXJuPSJcXC5SbWQiLCByZXBsYWNlPSIiLCB4PXByZXZpb3VzX2ZpbGUpLCAiLXYiLCB2ZXIsICIucmRhLnh6IikpKSkKCiAgcm1kX2ZpbGUgPC0gcGFzdGUwKCIwMl9zd2F0aDJzdGF0c18iLCB2ZXIsICIuUm1kIikKICB2ZXIgPC0gIjIwMTgwODA2Igp9CmBgYAoKIyBOZXcgc2FtcGxlcyEKClRoaXMgd29ya3NoZWV0IGlzIGEgY29weSBvZiAyMDE4MDcyNiBidXQgdGhpcyB0aW1lIHdpdGggZmVlbGluZyEgKG9yIG5ldyBzYW1wbGVzKQpBIG1pbm9yIGNhdmVhdDogSSBoYWQgc29tZSBkaWZmaWN1bHRpZXMgY29udmVydGluZyB0aGUgbmV3IGRhdGEgdG8gYSBvcGVuTVMKc3VpdGFibGUgZm9ybWF0LiAgSSBhbSBub3QgY2VydGFpbiBpZiBJIG1lc3NlZCB1cCBhIHByaW9yaSwgb3IgaWYgYSBjaGFuZ2UgaW4KdGhlIHZlcnNpb24gb2YgdGhlIHNvZnR3YXJlIG9uIHRoZSBzcGVjIGNhdXNlZCB0aGUgcHJvYmxlbSwgYnV0IGZvciBmdXR1cmUKcmVmZXJlbmNlOgoKVG8gcHJvcGVybHkgY29udmVydCB0aGUgZGF0YSB0byBtelhNTCwgbWFrZSBzdXJlIHRvIHVzZSB0aGUgVFBQIE1TQ29udmVydAp1dGlsaXR5IGFuZCBoYXZlICdUUFAnIGNvbXBhdGliaWxpdHkgb24uCgpBbmFseXppbmcgZGF0YSBmcm9tIG9wZW5NUyBhbmQgZnJpZW5kcy4KPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgojIyBTV0FUSDJzdGF0cyBwcmVwcm9jZXNzaW5nCgpJIGFtIHVzaW5nIG15IHNsaWdodGx5IG1vZGlmaWVkIGNvcHkgb2YgU1dBVEgyc3RhdHMuICBUaGlzIHNlZWtzIHRvIGVuc3VyZSB0aGF0CmNoYW5nZXMgaW4gdGhlIGNhc2Ugb2YgY29sdW1ucyBpbiB0aGUgbWV0YWRhdGEgZnJvbSBvbmUgdmVyc2lvbiBvZiBPcGVuTVMgdG8KYW5vdGhlciBkbyBub3QgdHJvdWJsZSBtZS4KCkkgYW0gc2VwYXJhdGVseSBwZXJmb3JtaW5nIHRoZSBhbmFseXNpcyBmb3Igb3VyIGhvbWUtZ3Jvd24gbGlicmFyaWVzIGFuZCB0aGUKcHVibGljbHkgYXZhaWxhYmxlIG9uZXMgKGRvY3VtZW50ZWQgaW4gdGhlIDIwMTgwNiB3b3Jrc2hlZXRzKS4KCiMjIyBDcmVhdGluZyBhIHN3YXRoMnN0YXRzIGV4cGVyaW1lbnQgdXNpbmcgb3VyIGNvbWV0LWRlcml2ZWQgbGlicmFyeSBkYXRhCgpgYGB7ciBvdXJfc3dhdGgyc3RhdHNfaW5pdGlhbH0Kb3VyX3RyaWNfZGF0YSA8LSByZWFkLmNzdihwYXN0ZTAoInJlc3VsdHMvdHJpYy8iLCB2ZXIsICIvd2hvbGVfOG16L2NvbWV0X0hDRC50c3YiKSwgc2VwPSJcdCIpCgpzYW1wbGVfYW5ub3QgPC0gZXh0cmFjdF9tZXRhZGF0YShwYXN0ZTAoInNhbXBsZV9zaGVldHMvTXRiX2RpYV9zYW1wbGVzXyIsIHZlciwgIi54bHN4IikpCmtlcHQgPC0gISBncmVwbCh4PXJvd25hbWVzKHNhbXBsZV9hbm5vdCksIHBhdHRlcm49Il5zXFwuXFwuIikKc2FtcGxlX2Fubm90IDwtIHNhbXBsZV9hbm5vdFtrZXB0LCBdCgojI3NhbXBsZV9hbm5vdCA8LSBvcGVueGxzeDo6cmVhZC54bHN4KCJzYW1wbGVfc2hlZXRzL010Yl9kaWFfc2FtcGxlc18yMDE4MDYxMS54bHN4IikKIyNyb3duYW1lcyhzYW1wbGVfYW5ub3QpIDwtIG1ha2UubmFtZXMocGFzdGUwKCJzIiwgc2FtcGxlX2Fubm90W1sic2FtcGxlaWQiXV0pLCB1bmlxdWU9VFJVRSkKIyMgRHJvcCBzYW1wbGVzIHN0YXJ0aW5nIHdpdGggY29tbWVudHMKIyNrZWVwX2lkeCA8LSAhIGdyZXBsKHBhdHRlcm49IiMjIiwgeD1zYW1wbGVfYW5ub3RbWyJzYW1wbGVpZCJdXSkKIyNzYW1wbGVfYW5ub3QgPC0gc2FtcGxlX2Fubm90W2tlZXBfaWR4LCBdCiMjY29sbmFtZXMoc2FtcGxlX2Fubm90KSA8LSBnc3ViKHg9Y29sbmFtZXMoc2FtcGxlX2Fubm90KSwgcGF0dGVybj0iXFwuIiwgcmVwbGFjZW1lbnQ9IiIpCiMjIFNldCB0aGUgbXpYTUwgY29sdW1uIHRvIG1hdGNoIHRoZSBmaWxlbmFtZSBjb2x1bW4gaW4gdGhlIGRhdGEuCmxvYWRlZCA8LSBzbShkZXZ0b29sczo6bG9hZF9hbGwoIn4vc2NyYXRjaC9naXQvU1dBVEgyc3RhdHMiKSkKIyMgczJzLCBteSB3aXR0eSB3YXkgb2Ygc2hvcnRlbmluZyBTV0FUSDJzdGF0cy4uLgpvdXJfczJzX2V4cCA8LSBzYW1wbGVfYW5ub3RhdGlvbihkYXRhPW91cl90cmljX2RhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9hbm5vdGF0aW9uPXNhbXBsZV9hbm5vdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcnVuX2NvbHVtbj0icnVuIiwgY2hlY2tfZmlsZXM9RkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bGxwZXB0aWRlbmFtZV9jb2x1bW49ImZ1bGx1bmltb2RwZXB0aWRlbmFtZSIpCmBgYAoKIyMjIENyZWF0aW5nIGEgc3dhdGgyc3RhdHMgZXhwZXJpbWVudCB1c2luZyB0aGUgdHViZXJjdWxpc3QtZGVyaXZlZCBsaWJyYXJ5IGRhdGEKClRoaXMganVzdCByZXBlYXRzIHRoZSBwcmV2aW91cyBzdGFuemEsIGJ1dCB1c2VzIHRoZSB0dWJlcmN1bGlzdAp0cmFuc2l0aW9uLWxpYnJhcnkgc3dhdGggZGF0YSBhcyBpdHMgaW5wdXQgcmF0aGVyIHRoYW4gb3VyIG93biBjb21ldApkYXRhLgoKVGhlcmUgaXMgb25lIGltcG9ydGFudCBjYXZlYXQgaW4gdGhlIGZvbGxvd2luZyBibG9jazogSSB1c2VkIGEgcmVnZXggdG8gcmVtb3ZlCnRoZSBzZWNvbmQgaGFsZiBvZiBnZW5lSURfZ2VuZU5hbWUgc28gdGhhdCBsYXRlciB3aGVuIEkgbWVyZ2UgaW4gdGhlIGFubm90YXRpb24KZGF0YSBJIGhhdmUgaXQgd2lsbCBtYXRjaC4KCmBgYHtyIHRiX3N3YXRoMnN0YXRzX2luaXRpYWx9CnRiX3RyaWNfZGF0YSA8LSByZWFkLmNzdihwYXN0ZTAoInJlc3VsdHMvdHJpYy8iLCB2ZXIsICIvd2hvbGVfOG16X3R1YmVyY3VsaXN0L2NvbWV0X0hDRC50c3YiKSwKICAgICAgICAgICAgICAgICAgICAgICAgIHNlcD0iXHQiKQp0Yl90cmljX2RhdGFbWyJQcm90ZWluTmFtZSJdXSA8LSBnc3ViKHBhdHRlcm49Il4oLiopXy4qJCIsIHJlcGxhY2VtZW50PSJcXDEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHg9dGJfdHJpY19kYXRhW1siUHJvdGVpbk5hbWUiXV0pCnRiX3Myc19leHAgPC0gc2FtcGxlX2Fubm90YXRpb24oZGF0YT10Yl90cmljX2RhdGEsIGNoZWNrX2ZpbGVzPUZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9hbm5vdGF0aW9uPXNhbXBsZV9hbm5vdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdWxscGVwdGlkZW5hbWVfY29sdW1uPSJmdWxsdW5pbW9kcGVwdGlkZW5hbWUiKQpgYGAKCk5vdyBJIGhhdmUgYSBjb3VwbGUgZGF0YSBzdHJ1Y3R1cmVzIHdoaWNoIHNob3VsZCBwcm92ZSB1c2VmdWwgZm9yIHRoZSBtZXRyaWNzCnByb3ZpZGVkIGJ5IFNXQVRIMnN0YXRzLCBNU3N0YXRzLCBhbmQgbXkgb3duIGhwZ2x0b29scy4KCiMgU1dBVEgyc3RhdHMgY29udGludWVkCgpUaGUgdmFyaW91cyBtZXRyaWNzIGFuZCBmaWx0ZXJzIHByb3ZpZGVkIGJ5IFNXQVRIMnN0YXRzIHNlZW0gcXVpdGUgcmVhc29uYWJsZSB0bwptZS4gIFRoZSBvbmx5IHRoaW5nIHRoYXQgcmVhbGx5IGJvdGhlcnMgbWUgaXMgdGhhdCB0aGV5IGFyZSBhbGwgY2FzZSBzZW5zaXRpdmUKYW5kIEkgZm91bmQgdGhhdCB0aGUgbW9zdCByZWNlbnQgdHJpYyBjaGFuZ2VkIHRoZSBjYXBpdGFsaXphdGlvbiBvZiBhIGNvbHVtbiwKY2F1c2luZyB0aGVzZSB0byBhbGwgZmFsbCBkb3duLiAgVGhlcmVmb3JlIEkgd2VudCBpbiBhbmQgbWFkZSBldmVyeXRoaW5nIGNhc2UKaW5zZW5zaXRpdmUgaW4gYSBmYXNoaW9uIHNpbWlsYXIgdG8gdGhhdCBkb25lIGJ5IE1Tc3RhdHMgKGV4Y2VwdCBJIGhhdGUgY2FwaXRhbApsZXR0ZXJzLCBzbyBJIHVzZWQgdG9sb3dlcigpIHJhdGhlciB0aGFuIHRvdXBwZXIoKSkuCgojIyBSdW4gZmlsdGVycyBvbiBvdXIgY29tZXQgZGF0YQoKYGBge3Igb3VyX3N3YXRoMnN0YXRzX3Byb2Nlc3Npbmd9CiMjIEdldCBjb3JyZWxhdGlvbnMgb24gYSBzYW1wbGUgYnkgc2FtcGxlIGJhc2lzCnBwKGZpbGU9ImltYWdlcy8yMDE4MDYxMV9vdXJfc3dhdGgyc3RhdHNfc2FtcGxlX2Nvci5wbmciKQpzYW1wbGVfY29yIDwtIHBsb3RfY29ycmVsYXRpb25fYmV0d2Vlbl9zYW1wbGVzKG91cl9zMnNfZXhwLCBzaXplPTIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVuLmFnZ3JlZ2F0ZT1zdW0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sdW1uLnZhbHVlcz0iaW50ZW5zaXR5IikKZGV2Lm9mZigpCnNhbXBsZV9jb25kX3JlcF9jb3IgPC0gcGxvdF9jb3JyZWxhdGlvbl9iZXR3ZWVuX3NhbXBsZXMob3VyX3Myc19leHAsIHNpemU9MiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21wYXJpc29uPXRyYW5zaXRpb25fZ3JvdXBfaWQgfgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uZGl0aW9uICsgYmlvcmVwbGljYXRlICsgcnVuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bi5hZ2dyZWdhdGU9c3VtLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbHVtbi52YWx1ZXM9ImludGVuc2l0eSIpCgpkZWNveV9saXN0cyA8LSBhc3Nlc3NfZGVjb3lfcmF0ZShvdXJfczJzX2V4cCkKIyMgVGhpcyBzZWVtcyBhIGJpdCBoaWdoIHRvIG1lLCB5ZXNubz8KZmRyX292ZXJhbGwgPC0gYXNzZXNzX2Zkcl9vdmVyYWxsKG91cl9zMnNfZXhwLCBvdXRwdXQ9IlJjb25zb2xlIiwgcGxvdD1UUlVFKQoKYnlydW5fZmRyIDwtIGFzc2Vzc19mZHJfYnlydW4ob3VyX3Myc19leHAsIEZGVD0wLjcsIHBsb3Q9VFJVRSwgb3V0cHV0PSJSY29uc29sZSIpCmNob3Nlbl9tc2NvcmUgPC0gbXNjb3JlNGFzc2F5ZmRyKG91cl9zMnNfZXhwLCBGRlQ9MC43LCBmZHJfdGFyZ2V0PTAuMDIpCnByb3Rfc2NvcmUgPC0gbXNjb3JlNHByb3RmZHIob3VyX3Myc19leHAsIEZGVD0wLjcsIGZkcl90YXJnZXQ9MC4wMikKCm91cl9tc2NvcmVfZmlsdGVyZWQgPC0gZmlsdGVyX21zY29yZShvdXJfczJzX2V4cCwgY2hvc2VuX21zY29yZSkKb3VyX2ZyZXFfbXNjb3JlIDwtIGZpbHRlcl9tc2NvcmVfZnJlcW9icyhvdXJfczJzX2V4cCwgMC4wMSwgMC44LCBybS5kZWNveT1GQUxTRSkKb3VyX2RhdGFfZmlsdGVyZWRfZmRyIDwtIGZpbHRlcl9tc2NvcmVfZmRyKG91cl9tc2NvcmVfZmlsdGVyZWQsIEZGVD0wLjcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdmVyYWxsX3Byb3RlaW5fZmRyX3RhcmdldD1wcm90X3Njb3JlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXBwZXJfb3ZlcmFsbF9wZXB0aWRlX2Zkcl9saW1pdD0wLjA1KQpvdXJfb25seV9wcm90ZW90eXBpYyA8LSBmaWx0ZXJfcHJvdGVvdHlwaWNfcGVwdGlkZXMob3VyX2RhdGFfZmlsdGVyZWRfZmRyKQpvdXJfYWxsX2ZpbHRlcmVkIDwtIGZpbHRlcl9hbGxfcGVwdGlkZXMob3VyX29ubHlfcHJvdGVvdHlwaWMpCm91cl9vbmx5X3N0cm9uZyA8LSBmaWx0ZXJfb25fbWF4X3BlcHRpZGVzKGRhdGE9b3VyX2FsbF9maWx0ZXJlZCwgbl9wZXB0aWRlcz0xMCkKb3VyX29ubHlfbWluaW11bSA8LSBmaWx0ZXJfb25fbWluX3BlcHRpZGVzKGRhdGE9b3VyX29ubHlfc3Ryb25nLCBuX3BlcHRpZGVzPTMpCgojIyBJIHRoaW5rIHRoZXNlIG1hdHJpeGVzIGFyZSBwcm9iYWJseSBzbWFydGVyIHRvIHVzZSB0aGFuIHRoZSByYXcgb3V0bWF0cml4IGZyb20gdHJpYy4KIyMgQnV0IEkgYW0gbm90IGEgZmFuIG9mIHJlcndyaXRpbmcgdGhlIHNhbXBsZSBjb2x1bW4gbmFtZXMuCm1hdHJpeF9wcmVmaXggPC0gZmlsZS5wYXRoKCJyZXN1bHRzIiwgInN3YXRoMnN0YXRzIiwgdmVyKQppZiAoIWZpbGUuZXhpc3RzKG1hdHJpeF9wcmVmaXgpKSB7CiAgZGlyLmNyZWF0ZShtYXRyaXhfcHJlZml4KQp9CnByb3RlaW5fbWF0cml4X2FsbCA8LSB3cml0ZV9tYXRyaXhfcHJvdGVpbnMoCiAgb3VyX3Myc19leHAsIHdyaXRlLmNzdj1UUlVFLAogIGZpbGVuYW1lPWZpbGUucGF0aChtYXRyaXhfcHJlZml4LCAib3VyX3Byb3RlaW5fYWxsLmNzdiIpKQpkaW0ocHJvdGVpbl9tYXRyaXhfYWxsKQpwcm90ZWluX21hdHJpeF9tc2NvcmUgPC0gd3JpdGVfbWF0cml4X3Byb3RlaW5zKAogIG91cl9tc2NvcmVfZmlsdGVyZWQsIHdyaXRlLmNzdj1UUlVFLAogIGZpbGVuYW1lPWZpbGUucGF0aChtYXRyaXhfcHJlZml4LCAib3VyX3Byb3RlaW5fbWF0cml4X21zY29yZS5jc3YiKSkKZGltKHByb3RlaW5fbWF0cml4X21zY29yZSkKcGVwdGlkZV9tYXRyaXhfbXNjb3JlIDwtIHdyaXRlX21hdHJpeF9wZXB0aWRlcygKICBvdXJfbXNjb3JlX2ZpbHRlcmVkLCB3cml0ZS5jc3Y9VFJVRSwKICBmaWxlbmFtZT1maWxlLnBhdGgobWF0cml4X3ByZWZpeCwgIm91cl9wZXB0aWRlX21hdHJpeF9tc2NvcmUuY3N2IikpCmRpbShwZXB0aWRlX21hdHJpeF9tc2NvcmUpCnByb3RlaW5fbWF0cml4X21pbmltdW0gPC0gd3JpdGVfbWF0cml4X3Byb3RlaW5zKAogIG91cl9vbmx5X21pbmltdW0sIHdyaXRlLmNzdj1UUlVFLAogIGZpbGVuYW1lPWZpbGUucGF0aChtYXRyaXhfcHJlZml4LCAib3VyX3Byb3RlaW5fbWF0cml4X21pbmltdW0uY3N2IikpCmRpbShwcm90ZWluX21hdHJpeF9taW5pbXVtKQpwZXB0aWRlX21hdHJpeF9taW5pbXVtIDwtIHdyaXRlX21hdHJpeF9wZXB0aWRlcygKICBvdXJfb25seV9taW5pbXVtLCB3cml0ZS5jc3Y9VFJVRSwKICBmaWxlbmFtZT1maWxlLnBhdGgobWF0cml4X3ByZWZpeCwgIm91cl9wZXB0aWRlX21hdHJpeF9taW5pbXVtLmNzdiIpKQpkaW0ocGVwdGlkZV9tYXRyaXhfbWluaW11bSkKCnJ0X2NvciA8LSBwbG90X2NvcnJlbGF0aW9uX2JldHdlZW5fc2FtcGxlcygKICBvdXJfYWxsX2ZpbHRlcmVkLCBjb2x1bW4udmFsdWVzPSJpbnRlbnNpdHkiLCBmdW4uYWdncmVnYXRlPXN1bSwgc2l6ZT0yKQojIyBJIGhhdmUgbm8gZWZmaW5nIGNsdWUgd2hhdCB0aGlzIHBsb3QgbWVhbnMuCnZhcmlhdGlvbiA8LSBwbG90X3ZhcmlhdGlvbihvdXJfYWxsX2ZpbHRlcmVkLCBmdW4uYWdncmVnYXRlPXN1bSkKCmNvbHMgPC0gY29sbmFtZXMob3VyX2FsbF9maWx0ZXJlZCkKb3VyX2Rpc2FnZ3JlZ2F0ZWQgPC0gZGlzYWdncmVnYXRlKG91cl9hbGxfZmlsdGVyZWQsIGFsbC5jb2x1bW5zPVRSVUUpCm91cl9tc3N0YXRzX2lucHV0IDwtIGNvbnZlcnRfTVNzdGF0cyhvdXJfZGlzYWdncmVnYXRlZCkKc3VtbWFyeShvdXJfbXNzdGF0c19pbnB1dCkKYGBgCgojIyBSdW4gZmlsdGVycyBvbiB0aGUgdHViZXJjdWxpc3QKClJlcGVhdCB0aGUgYWJvdmUgc3RhbnphIHVzaW5nIHRoZSB0dWJlcmN1bGlzdCBkYXRhLgoKYGBge3IgdGJfc3dhdGgyc3RhdHNfcHJvY2Vzc2luZ30KIyMgR2V0IGNvcnJlbGF0aW9ucyBvbiBhIHNhbXBsZSBieSBzYW1wbGUgYmFzaXMKcHAoZmlsZT0iaW1hZ2VzLzIwMTgwNjExX3RiX3N3YXRoMnN0YXRzX3NhbXBsZV9jb3IucG5nIikKc2FtcGxlX2NvciA8LSBwbG90X2NvcnJlbGF0aW9uX2JldHdlZW5fc2FtcGxlcyh0Yl9zMnNfZXhwLCBzaXplPTIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVuLmFnZ3JlZ2F0ZT1zdW0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sdW1uLnZhbHVlcz0iaW50ZW5zaXR5IikKZGV2Lm9mZigpCnNhbXBsZV9jb25kX3JlcF9jb3IgPC0gcGxvdF9jb3JyZWxhdGlvbl9iZXR3ZWVuX3NhbXBsZXModGJfczJzX2V4cCwgc2l6ZT0yLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBhcmlzb249dHJhbnNpdGlvbl9ncm91cF9pZCB+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25kaXRpb24gKyBiaW9yZXBsaWNhdGUgKyBydW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVuLmFnZ3JlZ2F0ZT1zdW0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sdW1uLnZhbHVlcz0iaW50ZW5zaXR5IikKCmRlY295X2xpc3RzIDwtIGFzc2Vzc19kZWNveV9yYXRlKHRiX3Myc19leHApCiMjIFRoaXMgc2VlbXMgYSBiaXQgaGlnaCB0byBtZSwgeWVzbm8/CmZkcl9vdmVyYWxsIDwtIGFzc2Vzc19mZHJfb3ZlcmFsbCh0Yl9zMnNfZXhwLCBvdXRwdXQ9IlJjb25zb2xlIiwgcGxvdD1UUlVFKQoKYnlydW5fZmRyIDwtIGFzc2Vzc19mZHJfYnlydW4odGJfczJzX2V4cCwgRkZUPTAuNywgcGxvdD1UUlVFLCBvdXRwdXQ9IlJjb25zb2xlIikKY2hvc2VuX21zY29yZSA8LSBtc2NvcmU0YXNzYXlmZHIodGJfczJzX2V4cCwgRkZUPTAuNywgZmRyX3RhcmdldD0wLjAyKQpwcm90X3Njb3JlIDwtIG1zY29yZTRwcm90ZmRyKHRiX3Myc19leHAsIEZGVD0wLjcsIGZkcl90YXJnZXQ9MC4wMikKCnRiX21zY29yZV9maWx0ZXJlZCA8LSBmaWx0ZXJfbXNjb3JlKHRiX3Myc19leHAsIGNob3Nlbl9tc2NvcmUpCnRiX2ZyZXFfbXNjb3JlIDwtIGZpbHRlcl9tc2NvcmVfZnJlcW9icyh0Yl9zMnNfZXhwLCAwLjAxLCAwLjgsIHJtLmRlY295PUZBTFNFKQp0Yl9kYXRhX2ZpbHRlcmVkX2ZkciA8LSBmaWx0ZXJfbXNjb3JlX2Zkcih0Yl9tc2NvcmVfZmlsdGVyZWQsIEZGVD0wLjcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdmVyYWxsX3Byb3RlaW5fZmRyX3RhcmdldD1wcm90X3Njb3JlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXBwZXJfb3ZlcmFsbF9wZXB0aWRlX2Zkcl9saW1pdD0wLjA1KQp0Yl9vbmx5X3Byb3Rlb3R5cGljIDwtIGZpbHRlcl9wcm90ZW90eXBpY19wZXB0aWRlcyh0Yl9kYXRhX2ZpbHRlcmVkX2ZkcikKdGJfYWxsX2ZpbHRlcmVkIDwtIGZpbHRlcl9hbGxfcGVwdGlkZXModGJfb25seV9wcm90ZW90eXBpYykKdGJfb25seV9zdHJvbmcgPC0gZmlsdGVyX29uX21heF9wZXB0aWRlcyhkYXRhPXRiX2FsbF9maWx0ZXJlZCwgbl9wZXB0aWRlcz0xMCkKdGJfb25seV9taW5pbXVtIDwtIGZpbHRlcl9vbl9taW5fcGVwdGlkZXMoZGF0YT10Yl9vbmx5X3N0cm9uZywgbl9wZXB0aWRlcz0zKQoKIyMgSSB0aGluayB0aGVzZSBtYXRyaXhlcyBhcmUgcHJvYmFibHkgc21hcnRlciB0byB1c2UgdGhhbiB0aGUgcmF3IG91dG1hdHJpeCBmcm9tIHRyaWMuCiMjIEJ1dCBJIGFtIG5vdCBhIGZhbiBvZiByZXJ3cml0aW5nIHRoZSBzYW1wbGUgY29sdW1uIG5hbWVzLgptYXRyaXhfcHJlZml4IDwtIGZpbGUucGF0aCgicmVzdWx0cyIsICJzd2F0aDJzdGF0cyIsIHZlcikKaWYgKCFmaWxlLmV4aXN0cyhtYXRyaXhfcHJlZml4KSkgewogIGRpci5jcmVhdGUobWF0cml4X3ByZWZpeCkKfQpwcm90ZWluX21hdHJpeF9hbGwgPC0gd3JpdGVfbWF0cml4X3Byb3RlaW5zKAogIHRiX3Myc19leHAsIHdyaXRlLmNzdj1UUlVFLAogIGZpbGVuYW1lPWZpbGUucGF0aChtYXRyaXhfcHJlZml4LCAidGJfcHJvdGVpbl9hbGwuY3N2IikpCmRpbShwcm90ZWluX21hdHJpeF9hbGwpCnByb3RlaW5fbWF0cml4X21zY29yZSA8LSB3cml0ZV9tYXRyaXhfcHJvdGVpbnMoCiAgdGJfbXNjb3JlX2ZpbHRlcmVkLCB3cml0ZS5jc3Y9VFJVRSwKICBmaWxlbmFtZT1maWxlLnBhdGgobWF0cml4X3ByZWZpeCwgInRiX3Byb3RlaW5fbWF0cml4X21zY29yZS5jc3YiKSkKZGltKHByb3RlaW5fbWF0cml4X21zY29yZSkKcGVwdGlkZV9tYXRyaXhfbXNjb3JlIDwtIHdyaXRlX21hdHJpeF9wZXB0aWRlcygKICB0Yl9tc2NvcmVfZmlsdGVyZWQsIHdyaXRlLmNzdj1UUlVFLAogIGZpbGVuYW1lPWZpbGUucGF0aChtYXRyaXhfcHJlZml4LCAidGJfcGVwdGlkZV9tYXRyaXhfbXNjb3JlLmNzdiIpKQpkaW0ocGVwdGlkZV9tYXRyaXhfbXNjb3JlKQpwcm90ZWluX21hdHJpeF9taW5pbXVtIDwtIHdyaXRlX21hdHJpeF9wcm90ZWlucygKICB0Yl9vbmx5X21pbmltdW0sIHdyaXRlLmNzdj1UUlVFLAogIGZpbGVuYW1lPWZpbGUucGF0aChtYXRyaXhfcHJlZml4LCAidGJfcHJvdGVpbl9tYXRyaXhfbWluaW11bS5jc3YiKSkKZGltKHByb3RlaW5fbWF0cml4X21pbmltdW0pCnBlcHRpZGVfbWF0cml4X21pbmltdW0gPC0gd3JpdGVfbWF0cml4X3BlcHRpZGVzKAogIHRiX29ubHlfbWluaW11bSwgd3JpdGUuY3N2PVRSVUUsCiAgZmlsZW5hbWU9ZmlsZS5wYXRoKG1hdHJpeF9wcmVmaXgsICJ0Yl9wZXB0aWRlX21hdHJpeF9taW5pbXVtLmNzdiIpKQpkaW0ocGVwdGlkZV9tYXRyaXhfbWluaW11bSkKCnJ0X2NvciA8LSBwbG90X2NvcnJlbGF0aW9uX2JldHdlZW5fc2FtcGxlcygKICB0Yl9vbmx5X21pbmltdW0sIGNvbHVtbi52YWx1ZXM9ImludGVuc2l0eSIsIGZ1bi5hZ2dyZWdhdGU9c3VtLCBzaXplPTIpCiMjIEkgaGF2ZSBubyBlZmZpbmcgY2x1ZSB3aGF0IHRoaXMgcGxvdCBtZWFucy4KdmFyaWF0aW9uIDwtIHBsb3RfdmFyaWF0aW9uKHRiX29ubHlfbWluaW11bSwgZnVuLmFnZ3JlZ2F0ZT1zdW0pCgpjb2xzIDwtIGNvbG5hbWVzKHRiX2FsbF9maWx0ZXJlZCkKdGJfZGlzYWdncmVnYXRlZCA8LSBkaXNhZ2dyZWdhdGUodGJfYWxsX2ZpbHRlcmVkLCBhbGwuY29sdW1ucz1UUlVFKQp0Yl9tc3N0YXRzX2lucHV0IDwtIGNvbnZlcnRfTVNzdGF0cyh0Yl9kaXNhZ2dyZWdhdGVkKQpgYGAKCiMjIFNvbWUgbmV3IHBsb3RzCgpJbiByZXNwb25zZSB0byBzb21lIGludGVyZXN0aW5nIHF1ZXJpZXMgZnJvbSBZYW4sIEkgbWFkZSBhIGZldyBsaXR0bGUgZnVuY3Rpb25zCndoaWNoIHF1ZXJ5IGFuZCBwbG90IGRhdGEgZnJvbSB0aGUgc2NvcmVkIGRhdGEgcHJvdmlkZWQgYnkgb3BlbnN3YXRoL3B5cHJvcGhldC4KTGV0IHVzIGxvb2sgYXQgdGhlaXIgcmVzdWx0cyBoZXJlLgoKIyMjIFVzaW5nIHRoZSBjb21ldCBkYXRhCgpgYGB7ciBvdXJfcHlwcm9waGV0X3Bsb3RzfQpvdXJfcHlwcm9waGV0X2Z1biA8LSBleHRyYWN0X3B5cHJvcGhldF9kYXRhKAogIG1ldGFkYXRhPXBhc3RlMCgic2FtcGxlX3NoZWV0cy9NdGJfZGlhX3NhbXBsZXNfIiwgdmVyLCAiLnhsc3giKSkKCm91cl9tYXNzX3Bsb3QgPC0gc20ocGxvdF9weXByb3BoZXRfZGlzdHJpYnV0aW9uKG91cl9weXByb3BoZXRfZnVuLCBjb2x1bW49Im1hc3MiKSkKb3VyX21hc3NfcGxvdFtbInZpb2xpbiJdXQoKb3VyX2RlbHRhcnRfcGxvdF9hbGwgPC0gc20ocGxvdF9weXByb3BoZXRfZGlzdHJpYnV0aW9uKAogIG91cl9weXByb3BoZXRfZnVuLCBjb2x1bW49ImRlbHRhX3J0IikpCm91cl9kZWx0YXJ0X3Bsb3RfYWxsW1sidmlvbGluIl1dCgpvdXJfZGVsdGFydF9wbG90X3JlYWwgPC0gc20ocGxvdF9weXByb3BoZXRfZGlzdHJpYnV0aW9uKAogIG91cl9weXByb3BoZXRfZnVuLAogIGNvbHVtbj0iZGVsdGFfcnQiLCBrZWVwX2RlY295cz1GQUxTRSkpCm91cl9kZWx0YXJ0X3Bsb3RfcmVhbFtbInZpb2xpbiJdXQoKb3VyX2RlbHRhcnRfcGxvdF9kZWNveXMgPC0gc20ocGxvdF9weXByb3BoZXRfZGlzdHJpYnV0aW9uKAogIG91cl9weXByb3BoZXRfZnVuLAogIGNvbHVtbj0iZGVsdGFfcnQiLCBrZWVwX3JlYWw9RkFMU0UpKQpvdXJfZGVsdGFydF9wbG90X2RlY295c1tbInZpb2xpbiJdXQoKb3VyX2RzY29yZV9wbG90IDwtIHNtKHBsb3RfcHlwcm9waGV0X2Rpc3RyaWJ1dGlvbigKICBvdXJfcHlwcm9waGV0X2Z1biwKICBjb2x1bW49ImRfc2NvcmUiKSkKb3VyX2RzY29yZV9wbG90W1sidmlvbGluIl1dCgpvdXJfbXNjb3JlX3Bsb3QgPC0gc20ocGxvdF9weXByb3BoZXRfZGlzdHJpYnV0aW9uKAogIG91cl9weXByb3BoZXRfZnVuLAogIGNvbHVtbj0ibV9zY29yZSIpKQpvdXJfbXNjb3JlX3Bsb3RbWyJ2aW9saW4iXV0KCm91cl93aWR0aHZzbWFzcyA8LSBzbShwbG90X3B5cHJvcGhldF9kYXRhKG91cl9weXByb3BoZXRfZnVuLCBsZWdlbmQ9RkFMU0UpKQpvdXJfd2lkdGh2c21hc3MkcGxvdApgYGAKCiMjIyBUaGUgdHViZXJjdWxpc3QgZGF0YQoKYGBge3IgdGJfcHlwcm9waGV0X3Bsb3RzfQp0Yl9weXByb3BoZXRfZnVuIDwtIHNtKGV4dHJhY3RfcHlwcm9waGV0X2RhdGEoCiAgbWV0YWRhdGE9cGFzdGUwKCJzYW1wbGVfc2hlZXRzL010Yl9kaWFfc2FtcGxlc18iLCB2ZXIsICIueGxzeCIpLAogIHB5cHJvcGhldF9jb2x1bW49InR1YmVyY3VsaXN0c2NvcmVkIikpCgp0Yl9tYXNzX3Bsb3QgPC0gc20ocGxvdF9weXByb3BoZXRfZGlzdHJpYnV0aW9uKHRiX3B5cHJvcGhldF9mdW4sIGNvbHVtbj0ibWFzcyIpKQp0Yl9tYXNzX3Bsb3RbWyJ2aW9saW4iXV0KCnRiX2RlbHRhcnRfcGxvdF9hbGwgPC0gc20ocGxvdF9weXByb3BoZXRfZGlzdHJpYnV0aW9uKAogIHRiX3B5cHJvcGhldF9mdW4sIGNvbHVtbj0iZGVsdGFfcnQiKSkKdGJfZGVsdGFydF9wbG90X2FsbFtbInZpb2xpbiJdXQoKdGJfZGVsdGFydF9wbG90X3JlYWwgPC0gc20ocGxvdF9weXByb3BoZXRfZGlzdHJpYnV0aW9uKAogIHRiX3B5cHJvcGhldF9mdW4sCiAgY29sdW1uPSJkZWx0YV9ydCIsIGtlZXBfZGVjb3lzPUZBTFNFKSkKdGJfZGVsdGFydF9wbG90X3JlYWxbWyJ2aW9saW4iXV0KCnRiX2RlbHRhcnRfcGxvdF9kZWNveXMgPC0gc20ocGxvdF9weXByb3BoZXRfZGlzdHJpYnV0aW9uKAogIHRiX3B5cHJvcGhldF9mdW4sCiAgY29sdW1uPSJkZWx0YV9ydCIsIGtlZXBfcmVhbD1GQUxTRSkpCnRiX2RlbHRhcnRfcGxvdF9kZWNveXNbWyJ2aW9saW4iXV0KYGBgCgojIyBNU3N0YXRzCgptc3N0YXRzLm9yZyBzZWVtcyB0byBwcm92aWRlIGEgY29tcGxldGUgc29sdXRpb24gZm9yIHBlcmZvcm1pbmcgcmVhc29uYWJsZSBtZXRyaWNzIG9mIHRoaXMgZGF0YS4KCkkgYW0gY3VycmVudGx5IHJlYWRpbmc6IGh0dHA6Ly9tc3N0YXRzLm9yZy93cC1jb250ZW50L3VwbG9hZHMvMjAxNy8wMS9NU3N0YXRzX3YzLjcuM19tYW51YWwucGRmCgpJIG1hZGUgc29tZSBtb2RlcmF0ZWx5IGludHJ1c2l2ZSBjaGFuZ2VzIHRvIE1Tc3RhdHMgdG8gbWFrZSBpdCBjbGVhcmVyLCBhcyB3ZWxsLgoKIyMjIENvbWV0IGRlcml2ZWQgbXNzdGF0cwoKTGV0IHVzIGludm9rZSBNU3N0YXRzIHdpdGggdGhlIFNXQVRIMnN0YXRzIGRlcml2ZWQgZGF0YS4KCmBgYHtyIG91cl9tc3N0YXRzX3F1YW50fQp0dCA8LSBzbShkZXZ0b29sczo6bG9hZF9hbGwoIn4vc2NyYXRjaC9naXQvTVNzdGF0cyIpKQpjaGVja3BvaW50IDwtICJvdXJfZGF0YXByb2Nlc3MucmRhIgppZiAoZmlsZS5leGlzdHMoY2hlY2twb2ludCkpIHsKICBsb2FkKGZpbGU9Y2hlY2twb2ludCkKfSBlbHNlIHsKICBvdXJfbXNzdGF0c19xdWFudCA8LSBzbShkYXRhUHJvY2VzcyhvdXJfbXNzdGF0c19pbnB1dCkpCiAgc2F2ZShmaWxlPWNoZWNrcG9pbnQsIGxpc3Q9Yygib3VyX21zc3RhdHNfcXVhbnQiKSkKfQpjaGVja3BvaW50IDwtICJvdXJfcGxvdHMucmRhIgppZiAoZmlsZS5leGlzdHMoY2hlY2twb2ludCkpIHsKICBsb2FkKGZpbGU9Y2hlY2twb2ludCkKfSBlbHNlIHsKICBvdXJfbXNzdGF0c19wbG90cyA8LSBzbShkYXRhUHJvY2Vzc1Bsb3RzKG91cl9tc3N0YXRzX3F1YW50LCB0eXBlPSJRQ1BMT1QiKSkKICBzYXZlKGZpbGU9Y2hlY2twb2ludCwgbGlzdD1jKCJvdXJfbXNzdGF0c19wbG90cyIpKQp9CgpteV9sZXZlbHMgPC0gbGV2ZWxzKGFzLmZhY3RvcihvdXJfbXNzdGF0c19pbnB1dCRjb25kaXRpb24pKQpteV9sZXZlbHMKY29tcGFyaXNvbnMgPC0gZ2hldHRvX2NvbnRyYXN0X21hdHJpeCgKICBudW1lcmF0b3JzPWMoInd0X2ZpbHRyYXRlIiwgImRlbHRhX2ZpbHRyYXRlIiwgImNvbXBfZmlsdHJhdGUiLAogICAgICAgICAgICAgICAiZGVsdGFfZmlsdHJhdGUiLCAiY29tcF9maWx0cmF0ZSIsICJkZWx0YV93aG9sZSIsCiAgICAgICAgICAgICAgICJjb21wX3dob2xlIiksCiAgZGVub21pbmF0b3JzPWMoInd0X3dob2xlIiwgImRlbHRhX3dob2xlIiwgImNvbXBfd2hvbGUiLAogICAgICAgICAgICAgICAgICJ3dF9maWx0cmF0ZSIsICJ3dF9maWx0cmF0ZSIsICJ3dF93aG9sZSIsCiAgICAgICAgICAgICAgICAgInd0X3dob2xlIikpCgpvdXJfcmVzdWx0cyA8LSBsaXN0KCkKY2hlY2twb2ludCA8LSAib3VyX2dyb3VwLnJkYSIKaWYgKGZpbGUuZXhpc3RzKGNoZWNrcG9pbnQpKSB7CiAgbG9hZChmaWxlPWNoZWNrcG9pbnQpCn0gZWxzZSB7CiAgZm9yIChjIGluIDE6bGVuZ3RoKHJvd25hbWVzKGNvbXBhcmlzb25zKSkpIHsKICAgIG5hbWUgPC0gcm93bmFtZXMoY29tcGFyaXNvbnMpW2NdCiAgICBtZXNzYWdlKCJTdGFydGluZyAiLCBuYW1lKQogICAgY29tcCA8LSBjb21wYXJpc29uc1tjLCBdCiAgICBjb21wIDwtIHQoYXMubWF0cml4KGNvbXApKQogICAgcm93bmFtZXMoY29tcCkgPC0gbmFtZQogICAgcmVzdWx0IDwtIHNtKE1Tc3RhdHM6Omdyb3VwQ29tcGFyaXNvbihjb250cmFzdC5tYXRyaXg9Y29tcCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YT1vdXJfbXNzdGF0c19xdWFudCkpCiAgICBvdXJfcmVzdWx0c1tbbmFtZV1dIDwtIHJlc3VsdAogIH0KICBzYXZlKGZpbGU9Y2hlY2twb2ludCwgbGlzdD1jKCJvdXJfcmVzdWx0cyIpKQp9CmBgYAoKIyMjIFR1YmVyY3VsaXN0IGRlcml2ZWQgbXNzdGF0cwoKYGBge3IgdGJfbXNzdGF0c19xdWFudH0KY2hlY2twb2ludCA8LSAidGJfZGF0YXByb2Nlc3MucmRhIgppZiAoZmlsZS5leGlzdHMoY2hlY2twb2ludCkpIHsKICBsb2FkKGZpbGU9Y2hlY2twb2ludCkKfSBlbHNlIHsKICB0Yl9tc3N0YXRzX3F1YW50IDwtIHNtKGRhdGFQcm9jZXNzKHRiX21zc3RhdHNfaW5wdXQpKQogIHNhdmUoZmlsZT1jaGVja3BvaW50LCBsaXN0PWMoInRiX21zc3RhdHNfcXVhbnQiKSkKfQpjaGVja3BvaW50IDwtICJ0Yl9wbG90cy5yZGEiCmlmIChmaWxlLmV4aXN0cyhjaGVja3BvaW50KSkgewogIGxvYWQoZmlsZT1jaGVja3BvaW50KQp9IGVsc2UgewogIHRiX21zc3RhdHNfcGxvdHMgPC0gc20oZGF0YVByb2Nlc3NQbG90cyh0Yl9tc3N0YXRzX3F1YW50LCB0eXBlPSJRQ1BMT1QiKSkKICBzYXZlKGZpbGU9Y2hlY2twb2ludCwgbGlzdD1jKCJ0Yl9tc3N0YXRzX3Bsb3RzIikpCn0KCm15X2xldmVscyA8LSBsZXZlbHMoYXMuZmFjdG9yKHRiX21zc3RhdHNfaW5wdXQkY29uZGl0aW9uKSkKbXlfbGV2ZWxzCmNvbXBhcmlzb25zIDwtIGdoZXR0b19jb250cmFzdF9tYXRyaXgoCiAgbnVtZXJhdG9ycz1jKCJ3dF9maWx0cmF0ZSIsICJkZWx0YV9maWx0cmF0ZSIsICJjb21wX2ZpbHRyYXRlIiwKICAgICAgICAgICAgICAgImRlbHRhX2ZpbHRyYXRlIiwgImNvbXBfZmlsdHJhdGUiLCAiZGVsdGFfd2hvbGUiLAogICAgICAgICAgICAgICAiY29tcF93aG9sZSIpLAogIGRlbm9taW5hdG9ycz1jKCJ3dF93aG9sZSIsICJkZWx0YV93aG9sZSIsICJjb21wX3dob2xlIiwKICAgICAgICAgICAgICAgICAid3RfZmlsdHJhdGUiLCAid3RfZmlsdHJhdGUiLCAid3Rfd2hvbGUiLAogICAgICAgICAgICAgICAgICJ3dF93aG9sZSIpKQoKdGJfcmVzdWx0cyA8LSBsaXN0KCkKY2hlY2twb2ludCA8LSAidGJfZ3JvdXAucmRhIgppZiAoZmlsZS5leGlzdHMoY2hlY2twb2ludCkpIHsKICBsb2FkKGZpbGU9Y2hlY2twb2ludCkKfSBlbHNlIHsKICBmb3IgKGMgaW4gMTpsZW5ndGgocm93bmFtZXMoY29tcGFyaXNvbnMpKSkgewogICAgbmFtZSA8LSByb3duYW1lcyhjb21wYXJpc29ucylbY10KICAgIG1lc3NhZ2UoIlN0YXJ0aW5nICIsIG5hbWUpCiAgICBjb21wIDwtIGNvbXBhcmlzb25zW2MsIF0KICAgIGNvbXAgPC0gdChhcy5tYXRyaXgoY29tcCkpCiAgICByb3duYW1lcyhjb21wKSA8LSBuYW1lCiAgICB0Yl9yZXN1bHRzW1tuYW1lXV0gPC0gc20oTVNzdGF0czo6Z3JvdXBDb21wYXJpc29uKGNvbnRyYXN0Lm1hdHJpeD1jb21wLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhPXRiX21zc3RhdHNfcXVhbnQpKQogICAgbWVzc2FnZSgiRmluaXNoZWQgIiwgbmFtZSkKICB9CiAgc2F2ZShmaWxlPWNoZWNrcG9pbnQsIGxpc3Q9YygidGJfcmVzdWx0cyIpKQp9CmBgYAoKIyMjIFAvUEUgcHJvdGVpbiBRQyBwbG90cyBmb3IgWWFuCgpZYW4gYXNrZWQgZm9yIHRoZSBwL3BlIHByb3RlaW4gcWMgcGxvdHMuIG9rLiAgSSBjaGFuZ2VkIHRoZSBkYXRhUHJvY2Vzc1Bsb3RzIHRvCnJldHVybiBzb21ldGhpbmcgdXNlZnVsLCBzbyB0aGF0IHNob3VsZCBiZSBwb3NzaWJsZSBub3cuCgpgYGB7ciBwZX0KcGVfZ2VuZXMgPC0gcmVhZC50YWJsZSgicmVmZXJlbmNlL2Fubm90YXRlZF9wZV9nZW5lcy50eHQiKVtbMV1dCgojIyBVbmZvcnR1bmF0ZWx5LCB0aGUgbmFtZXMgZGlkIG5vdCBnZXQgc2V0IGluIG15IGNoYW5nZWQgdmVyc2lvbiBvZiBkYXRhUHJvY2Vzc1Bsb3RzLi4uCnBsb3Rsc3QgPC0gb3VyX21zc3RhdHNfcGxvdHMkUUNQTE9UCmF2YWlsYWJsZV9wbG90cyA8LSBnc3ViKHBhdHRlcm49Il4xLyIsIHJlcGxhY2VtZW50PSIiLAogICAgICAgICAgICAgICAgICAgICAgICB4PWxldmVscyhvdXJfbXNzdGF0c19xdWFudCRQcm9jZXNzZWREYXRhJFBST1RFSU4pKQpuYW1lcyhwbG90bHN0KSA8LSBhdmFpbGFibGVfcGxvdHMKCnBlX2luX2F2YWlsX2lkeCA8LSBwZV9nZW5lcyAlaW4lIGF2YWlsYWJsZV9wbG90cwpwZV9pbl9hdmFpbCA8LSBwZV9nZW5lc1twZV9pbl9hdmFpbF9pZHhdCnBlX3Bsb3RzIDwtIHBsb3Rsc3RbcGVfaW5fYXZhaWxdCnBkZihmaWxlPSJwZV9xY19wbG90cy5wZGYiKQpmb3IgKHAgaW4gMTpsZW5ndGgocGVfcGxvdHMpKSB7CiAgcGxvdChwZV9wbG90c1tbcF1dKQp9CmRldi5vZmYoKQpsZW5ndGgocGVfcGxvdHMpCmBgYAoKIyBDcmVhdGUgaHBnbHRvb2xzIGV4cHJlc3Npb25zZXQKClNpbmNlIEkgYW0gbm90IGNlcnRhaW4gSSB1bmRlcnN0YW5kIHRoZXNlIGRhdGEsIEkgd2lsbCB0YWtlIHRoZSBpbnRlbnNpdGllcyBmcm9tClNXQVRIMnN0YXRzLCBtZXRhZGF0YSwgYW5kIGFubm90YXRpb24gZGF0YTsgIGF0dGVtcHQgdG8gY3JlYXRlIGEgJ25vcm1hbCcKZXhwcmVzc2lvbnNldDsgcG9rZSBhdCBpdCB0byBzZWUgd2hhdCBJIGNhbiBsZWFybi4KCiMjIE1hc3NhZ2luZyB0aGUgbWV0YWRhdGEKCkkgd2FudCB0byB1c2UgdGhlIHNhbWUgbWV0YWRhdGEgYXMgd2VyZSB1c2VkIGZvciBNU3N0YXRzLiAgSXQgaGFzIGEgZmV3CmltcG9ydGFudCBkaWZmZXJlbmNlcyBmcm9tIHRoZSByZXF1aXJlbWVudHMgb2YgaHBnbHRvb2xzOiBwcmV0dHkgbXVjaCBvbmx5IHRoYXQKSSBkbyBub3QgYWxsb3cgcm93bmFtZXMvc2FtcGxlSURzIHRvIHN0YXJ0IHdpdGggYSBudW1iZXIuCgojIyBNYXNzYWdpbmcgdGhlIGludGVuc2l0eSBtYXRyaXgKCkkgZG8gbm90IHdhbnQgdGhlIFwxIGJlZm9yZSB0aGUgcHJvdGVpbiBuYW1lcywgSSBhbHJlYWR5IG1lcmdlZCB0aGVtIGludG8gb25lCmVudHJ5IHBlciBnZW5lIHZpcyBTV0FUSDJzdGF0cy4KCiMjIyBNYWtlIG1hdHJpY2VzIHdpdGggb3VyIGxpYnJhcmllcwoKYGBge3Igb3VyX3Byb3RlaW5fbWF0cml4fQpvdXJfcHJvdF9tdHJ4IDwtIHJlYWQuY3N2KGZpbGUucGF0aCgicmVzdWx0cyIsICJzd2F0aDJzdGF0cyIsIHZlciwgIm91cl9wcm90ZWluX21hdHJpeF9taW5pbXVtLmNzdiIpKQpyb3duYW1lcyhvdXJfcHJvdF9tdHJ4KSA8LSBnc3ViKHBhdHRlcm49Il4xXFwvIiwgcmVwbGFjZW1lbnQ9IiIsIHg9b3VyX3Byb3RfbXRyeFtbInByb3RlaW5uYW1lIl1dKQpvdXJfcHJvdF9tdHJ4IDwtIG91cl9wcm90X210cnhbLCAtMV0KIyMgSW1wb3J0YW50IHF1ZXN0aW9uOiBEaWQgU1dBVEgyc3RhdHMgcmVvcmRlciBteSBkYXRhPwpjb2xuYW1lcyhvdXJfcHJvdF9tdHJ4KSA8LSBnc3ViKHBhdHRlcm49Il4oLiopKDIwMTguKikkIiwgcmVwbGFjZW1lbnQ9InNcXDIiLCB4PWNvbG5hbWVzKG91cl9wcm90X210cngpKQpgYGAKCiMjIyBNYWtlIG1hdHJpY2VzIHdpdGggdGhlIHRiIGxpYnJhcmllcwoKYGBge3IgdGJfcHJvdGVpbl9tYXRyaXh9CnRiX3Byb3RfbXRyeCA8LSByZWFkLmNzdihmaWxlLnBhdGgoInJlc3VsdHMiLCAic3dhdGgyc3RhdHMiLCB2ZXIsICJ0Yl9wcm90ZWluX21hdHJpeF9taW5pbXVtLmNzdiIpKQpyb3duYW1lcyh0Yl9wcm90X210cngpIDwtIGdzdWIocGF0dGVybj0iXjFcXC8iLCByZXBsYWNlbWVudD0iIiwgeD10Yl9wcm90X210cnhbWyJwcm90ZWlubmFtZSJdXSkKdGJfcHJvdF9tdHJ4IDwtIHRiX3Byb3RfbXRyeFssIC0xXQojIyBJbXBvcnRhbnQgcXVlc3Rpb246IERpZCBTV0FUSDJzdGF0cyByZW9yZGVyIG15IGRhdGE/CmNvbG5hbWVzKHRiX3Byb3RfbXRyeCkgPC0gZ3N1YihwYXR0ZXJuPSJeKC4qKSgyMDE4LiopJCIsIHJlcGxhY2VtZW50PSJzXFwyIiwgeD1jb2xuYW1lcyh0Yl9wcm90X210cngpKQpgYGAKCiMjIE1lcmdlIHRoZSBwaWVjZXMKCk5vdyB3ZSBzaG91bGQgaGF2ZSBzdWZmaWNpZW50IHBpZWNlcyB0byBtYWtlIGFuIGV4cHJlc3Npb25zZXQuCgpXaGlsZSBoZXJlLCBJIHdpbGwgYWxzbyBzcGxpdCB0aGUgZGF0YSBpbnRvIGEgY2YgYW5kIHdob2xlLWNlbGwgcGFpciBvZiBkYXRhIHN0cnVjdHVyZXMuCgojIyMgT3VyIGRhdGEKCmBgYHtyIG91cl9leHB0fQojIyBEcm9wIHRoZSBtZXRhZGF0YSBub3QgaW4gdGhlIHByb3RlaW4gbWF0cml4OgojIyBBbmQgZW5zdXJlIHRoYXQgdGhleSBhcmUgdGhlIHNhbWUgb3JkZXIuCnJlb3JkZXJlZCA8LSBjb2xuYW1lcyhvdXJfcHJvdF9tdHJ4KQptZXRhZGF0YSA8LSBzYW1wbGVfYW5ub3RbcmVvcmRlcmVkLCBdCgpvdXJfcHJvdGVpbl9leHB0IDwtIGNyZWF0ZV9leHB0KG1ldGFkYXRhPW1ldGFkYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50X2RhdGFmcmFtZT1vdXJfcHJvdF9tdHJ4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlbmVfaW5mbz1tdGJfYW5ub3RhdGlvbnMpCgpvdXJfd2hvbGVfZXhwdCA8LSBzdWJzZXRfZXhwdChvdXJfcHJvdGVpbl9leHB0LCBzdWJzZXQ9ImNvbGxlY3Rpb250eXBlPT0nd2hvbGUnIikKb3VyX2NmX2V4cHQgPC0gc3Vic2V0X2V4cHQob3VyX3Byb3RlaW5fZXhwdCwgc3Vic2V0PSJjb2xsZWN0aW9udHlwZT09J2ZpbHRyYXRlJyIpCmBgYAoKIyMjIFRiIGRhdGEKCmBgYHtyIHRiX2V4cHR9CiMjIERyb3AgdGhlIG1ldGFkYXRhIG5vdCBpbiB0aGUgcHJvdGVpbiBtYXRyaXg6CiMjIEFuZCBlbnN1cmUgdGhhdCB0aGV5IGFyZSB0aGUgc2FtZSBvcmRlci4KcmVvcmRlcmVkIDwtIGNvbG5hbWVzKHRiX3Byb3RfbXRyeCkKbWV0YWRhdGEgPC0gc2FtcGxlX2Fubm90W3Jlb3JkZXJlZCwgXQoKdGJfcHJvdGVpbl9leHB0IDwtIHNtKGNyZWF0ZV9leHB0KG1ldGFkYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY291bnRfZGF0YWZyYW1lPXRiX3Byb3RfbXRyeCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlbmVfaW5mbz1tdGJfYW5ub3RhdGlvbnMpKQp0Yl93aG9sZV9leHB0IDwtIHN1YnNldF9leHB0KHRiX3Byb3RlaW5fZXhwdCwgc3Vic2V0PSJjb2xsZWN0aW9udHlwZT09J3dob2xlJyIpCnRiX2NmX2V4cHQgPC0gc3Vic2V0X2V4cHQodGJfcHJvdGVpbl9leHB0LCBzdWJzZXQ9ImNvbGxlY3Rpb250eXBlPT0nZmlsdHJhdGUnIikKYGBgCgojIyBNZXRyaWNzIG9mIHRoZSBmdWxsIGRhdGEgc2V0CgojIyMgT3VyIGxpYnJhcmllcwoKYGBge3Igb3VyX3Byb3RlaW5fbWV0cmljcywgZmlnLnNob3c9J2hpZGUnfQpvdXJfcHJvdGVpbl9tZXRyaWNzIDwtIHNtKGdyYXBoX21ldHJpY3Mob3VyX3Byb3RlaW5fZXhwdCkpCm91cl9wcm90ZWluX25vcm0gPC0gc20obm9ybWFsaXplX2V4cHQob3VyX3Byb3RlaW5fZXhwdCwgdHJhbnNmb3JtPSJsb2cyIiwgY29udmVydD0iY3BtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3JtPSJxdWFudCIsIGZpbHRlcj1UUlVFKSkKb3VyX3Byb3RlaW5fbm9ybV9tZXRyaWNzIDwtIHNtKGdyYXBoX21ldHJpY3Mob3VyX3Byb3RlaW5fbm9ybSkpCm91cl9wcm90ZWluX2ZzdmEgPC0gc20obm9ybWFsaXplX2V4cHQob3VyX3Byb3RlaW5fZXhwdCwgdHJhbnNmb3JtPSJsb2cyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYXRjaD0iZnN2YSIsIGZpbHRlcj1UUlVFKSkKb3VyX3Byb3RlaW5fZnN2YV9tZXRyaWNzIDwtIHNtKGdyYXBoX21ldHJpY3Mob3VyX3Byb3RlaW5fZnN2YSkpCmBgYAoKIyMjIFRiIGxpYnJhcmllcwoKYGBge3IgdGJfcHJvdGVpbl9tZXRyaWNzLCBmaWcuc2hvdz0naGlkZSd9CnRiX3Byb3RlaW5fbWV0cmljcyA8LSBzbShncmFwaF9tZXRyaWNzKHRiX3Byb3RlaW5fZXhwdCkpCnRiX3Byb3RlaW5fbm9ybSA8LSBzbShub3JtYWxpemVfZXhwdCh0Yl9wcm90ZWluX2V4cHQsIHRyYW5zZm9ybT0ibG9nMiIsIGNvbnZlcnQ9ImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9ybT0icXVhbnQiLCBmaWx0ZXI9VFJVRSkpCnRiX3Byb3RlaW5fbm9ybV9tZXRyaWNzIDwtIHNtKGdyYXBoX21ldHJpY3ModGJfcHJvdGVpbl9ub3JtKSkKdGJfcHJvdGVpbl9mc3ZhIDwtIHNtKG5vcm1hbGl6ZV9leHB0KHRiX3Byb3RlaW5fZXhwdCwgdHJhbnNmb3JtPSJsb2cyIiwgY29udmVydD0iY3BtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYXRjaD0iZnN2YSIsIGZpbHRlcj1UUlVFKSkKdGJfcHJvdGVpbl9mc3ZhX21ldHJpY3MgPC0gc20oZ3JhcGhfbWV0cmljcyh0Yl9wcm90ZWluX2ZzdmEpKQpgYGAKCiMjIE1ldHJpY3Mgb2YgdGhlIHdob2xlLWNlbGwgZGF0YSBzZXQKCiMjIyBPdXIgbGlicmFyaWVzCgpgYGB7ciBvdXJfd2hvbGVfbWV0cmljcywgZmlnLnNob3c9J2hpZGUnfQpvdXJfd2hvbGVfbWV0cmljcyA8LSBzbShncmFwaF9tZXRyaWNzKG91cl93aG9sZV9leHB0KSkKb3VyX3dob2xlX25vcm0gPC0gc20obm9ybWFsaXplX2V4cHQob3VyX3dob2xlX2V4cHQsIHRyYW5zZm9ybT0ibG9nMiIsIGNvbnZlcnQ9ImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vcm09InF1YW50IiwgZmlsdGVyPVRSVUUpKQpvdXJfd2hvbGVfbm9ybV9tZXRyaWNzIDwtIHNtKGdyYXBoX21ldHJpY3Mob3VyX3dob2xlX25vcm0pKQpvdXJfd2hvbGVfZnN2YSA8LSBzbShub3JtYWxpemVfZXhwdChvdXJfd2hvbGVfZXhwdCwgdHJhbnNmb3JtPSJsb2cyIiwgY29udmVydD0iY3BtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmF0Y2g9ImZzdmEiLCBmaWx0ZXI9VFJVRSkpCm91cl93aG9sZV9mc3ZhX21ldHJpY3MgPC0gc20oZ3JhcGhfbWV0cmljcyhvdXJfd2hvbGVfZnN2YSkpCmBgYAoKYGBge3Igb3VyX3ZhcmlhbmNlX3Bsb3RzfQpvdXJfd2hvbGVfdmFycGFydCA8LSB2YXJwYXJ0KG91cl93aG9sZV9leHB0KQpvdXJfd2hvbGVfdmFycGFydCRwYXJ0aXRpb25fcGxvdApvdXJfd2hvbGVfY3YgPC0gcGxvdF92YXJpYW5jZV9jb2VmZmljaWVudHMob3VyX3Byb3RlaW5fZXhwdCkKb3VyX3dob2xlX2N2JGRpc3AKb3VyX2JhdGNoX2N2IDwtIHBsb3RfdmFyaWFuY2VfY29lZmZpY2llbnRzKG91cl9wcm90ZWluX2V4cHQsIHhfYXhpcz0iYmF0Y2giKQpvdXJfYmF0Y2hfY3YkZGlzcApvdXJfZ2Vub3R5cGVfY3YgPC0gcGxvdF92YXJpYW5jZV9jb2VmZmljaWVudHMob3VyX3Byb3RlaW5fZXhwdCwgeF9heGlzPSJnZW5vdHlwZSIpCm91cl9nZW5vdHlwZV9jdiRkaXNwCm91cl9wcmVwX2N2IDwtIHBsb3RfdmFyaWFuY2VfY29lZmZpY2llbnRzKG91cl9wcm90ZWluX2V4cHQsIHhfYXhpcz0icHJlcGRhdGUiKQpvdXJfcHJlcF9jdiRkaXNwCmBgYAoKIyMjIFRiIGxpYnJhcmllcwoKYGBge3IgdGJfd2hvbGVfbWV0cmljcywgZmlnLnNob3c9J2hpZGUnfQp0Yl93aG9sZV9tZXRyaWNzIDwtIHNtKGdyYXBoX21ldHJpY3ModGJfd2hvbGVfZXhwdCkpCnRiX3dob2xlX25vcm0gPC0gc20obm9ybWFsaXplX2V4cHQodGJfd2hvbGVfZXhwdCwgdHJhbnNmb3JtPSJsb2cyIiwgY29udmVydD0iY3BtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9ybT0icXVhbnQiLCBmaWx0ZXI9VFJVRSkpCnRiX3dob2xlX25vcm1fbWV0cmljcyA8LSBzbShncmFwaF9tZXRyaWNzKHRiX3dob2xlX25vcm0pKQp0Yl93aG9sZV9mc3ZhIDwtIHNtKG5vcm1hbGl6ZV9leHB0KHRiX3dob2xlX2V4cHQsIHRyYW5zZm9ybT0ibG9nMiIsIGNvbnZlcnQ9ImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhdGNoPSJmc3ZhIiwgZmlsdGVyPVRSVUUpKQp0Yl93aG9sZV9mc3ZhX21ldHJpY3MgPC0gc20oZ3JhcGhfbWV0cmljcyh0Yl93aG9sZV9mc3ZhKSkKYGBgCgpgYGB7ciB0Yl92YXJpYW5jZX0KdGJfd2hvbGVfdmFycGFydCA8LSB2YXJwYXJ0KHRiX3dob2xlX2V4cHQpCnRiX3dob2xlX3ZhcnBhcnQkcGFydGl0aW9uX3Bsb3QKdGJfd2hvbGVfY3YgPC0gcGxvdF92YXJpYW5jZV9jb2VmZmljaWVudHModGJfcHJvdGVpbl9leHB0KQp0Yl93aG9sZV9jdiRkaXNwCnRiX2JhdGNoX2N2IDwtIHBsb3RfdmFyaWFuY2VfY29lZmZpY2llbnRzKHRiX3Byb3RlaW5fZXhwdCwgeF9heGlzPSJiYXRjaCIpCnRiX2JhdGNoX2N2JGRpc3AKdGJfZ2Vub3R5cGVfY3YgPC0gcGxvdF92YXJpYW5jZV9jb2VmZmljaWVudHModGJfcHJvdGVpbl9leHB0LCB4X2F4aXM9Imdlbm90eXBlIikKdGJfZ2Vub3R5cGVfY3YkZGlzcAp0Yl9wcmVwX2N2IDwtIHBsb3RfdmFyaWFuY2VfY29lZmZpY2llbnRzKHRiX3Byb3RlaW5fZXhwdCwgeF9heGlzPSJwcmVwZGF0ZSIpCnRiX3ByZXBfY3YkZGlzcAoKdmlvIDwtIHBsb3RfYm94cGxvdCh0Yl9wcm90ZWluX2V4cHQsIHZpb2xpbj1UUlVFKQpgYGAKCiMjIE1ldHJpY3Mgb2YgdGhlIGZpbHRyYXRlIGRhdGEgc2V0CgojIyMgT3VyIGxpYnJhcmllcwoKYGBge3Igb3VyX2NmX21ldHJpY3MsIGZpZy5zaG93PSdoaWRlJ30Kb3VyX2NmX21ldHJpY3MgPC0gc20oZ3JhcGhfbWV0cmljcyhvdXJfY2ZfZXhwdCkpCm91cl9jZl9ub3JtIDwtIHNtKG5vcm1hbGl6ZV9leHB0KG91cl9jZl9leHB0LCB0cmFuc2Zvcm09ImxvZzIiLCBjb252ZXJ0PSJjcG0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3JtPSJxdWFudCIsIGZpbHRlcj1UUlVFKSkKb3VyX2NmX25vcm1fbWV0cmljcyA8LSBzbShncmFwaF9tZXRyaWNzKG91cl9jZl9ub3JtKSkKb3VyX2NmX2ZzdmEgPC0gc20obm9ybWFsaXplX2V4cHQob3VyX2NmX2V4cHQsIHRyYW5zZm9ybT0ibG9nMiIsIGNvbnZlcnQ9ImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhdGNoPSJmc3ZhIiwgZmlsdGVyPVRSVUUpKQpvdXJfY2ZfZnN2YV9tZXRyaWNzIDwtIHNtKGdyYXBoX21ldHJpY3Mob3VyX2NmX2ZzdmEpKQpgYGAKCiMjIyBUYiBsaWJyYXJpZXMKCmBgYHtyIHRiX2NmX21ldHJpY3MsIGZpZy5zaG93PSdoaWRlJ30KdGJfY2ZfbWV0cmljcyA8LSBzbShncmFwaF9tZXRyaWNzKHRiX2NmX2V4cHQpKQp0Yl9jZl9ub3JtIDwtIHNtKG5vcm1hbGl6ZV9leHB0KHRiX2NmX2V4cHQsIHRyYW5zZm9ybT0ibG9nMiIsIGNvbnZlcnQ9ImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vcm09InF1YW50IiwgZmlsdGVyPVRSVUUpKQp0Yl9jZl9ub3JtX21ldHJpY3MgPC0gc20oZ3JhcGhfbWV0cmljcyh0Yl9jZl9ub3JtKSkKdGJfY2ZfZnN2YSA8LSBzbShub3JtYWxpemVfZXhwdCh0Yl9jZl9leHB0LCB0cmFuc2Zvcm09ImxvZzIiLCBjb252ZXJ0PSJjcG0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYXRjaD0iZnN2YSIsIGZpbHRlcj1UUlVFKSkKdGJfY2ZfZnN2YV9tZXRyaWNzIDwtIHNtKGdyYXBoX21ldHJpY3ModGJfY2ZfZnN2YSkpCmBgYAoKIyMgcGxvdCBzb21lIG1ldHJpY3MKCiMjIyBPdXIgbGlicmFyaWVzCgpgYGB7ciBvdXJfcHJpbnRfbWV0cmljc30KcHAoaW1hZ2U9b3VyX3Byb3RlaW5fbWV0cmljcyRsaWJzaXplLAogICBmaWxlPWZpbGUucGF0aCgiaW1hZ2VzIiwgcGFzdGUwKHZlciwgIl9vdXJfbGlic2l6ZS5wbmciKSkpCiMjIEl0IHNlZW1zIHRvIG1lIHRoYXQgdGhlIHNjYWxlIG9mIHRoZSBkYXRhIGlzIGFsbCB3aXRoaW4gYW4gb3JkZXIgb2YgbWFnbml0dWRlIG9yIHR3by4KIyMgSSBjYW5ub3QgZ2V0IHVzZWQgdG8gdGhlc2UgYWJzdXJkbHkgbGFyZ2UgbnVtYmVycyB0aG91Z2guCnBwKGltYWdlPW91cl9wcm90ZWluX25vcm1fbWV0cmljcyRwY2FwbG90LAogICBmaWxlPWZpbGUucGF0aCgiaW1hZ2VzIiwgcGFzdGUwKHZlciwgIl9vdXJfbm9ybV9wY2EucG5nIikpKQojIyBUaGVyZSBhcHBlYXJzIHRvIGJlIGEgbmljZSBzcGxpdCBpbiB0aGUgZGF0YSwgaG93ZXZlciB0aGUgdW4tYXNzYXlhYmxlIGJhdGNoCiMjIGVmZmVjdCBpcyBhIHByb2JsZW0uCnBwKGltYWdlPW91cl9wcm90ZWluX2ZzdmFfbWV0cmljcyRwY2FwbG90LAogICBmaWxlPWZpbGUucGF0aCgiaW1hZ2VzIiwgcGFzdGUwKHZlciwgIl9mc3ZhX3BjYS5wbmciKSkpCiMjIGZzdmEgc2VlbXMgdG8gZ2V0IHNvbWUgaGFuZGxlIG9uIHRoZSBkYXRhLCBidXQgSSBkb24ndCB0aGluayB3ZSBzaG91bGQgcmVseQojIyB1cG9uIGl0LgpwcChpbWFnZT1vdXJfcHJvdGVpbl9ub3JtX21ldHJpY3MkY29yaGVhdCwKICAgZmlsZT1maWxlLnBhdGgoImltYWdlcyIsIHBhc3RlMCh2ZXIsICJfbm9ybV9jb3JoZWF0LnBuZyIpKSkKIyMgT25jZSBhZ2FpbiwgdGhlIHdob2xlLWNlbGwvY3VsdHVyZS1maWx0cmF0ZSBzcGxpdCBpcyB2ZXJ5IGxhcmdlLgpwcChpbWFnZT1vdXJfcHJvdGVpbl9tZXRyaWNzJGRlbnNpdHksCiAgIGZpbGU9ZmlsZS5wYXRoKCJpbWFnZXMiLCBwYXN0ZTAodmVyLCAiX3Jhd19kZW5zaXR5LnBuZyIpKSkKIyMgVGhlcmUgYXJlIHR3byBvYnZpb3VzIGRpc3RyaWJ1dGlvbnMgaW4gdGhlIGRhdGEsIG9uY2UgYWdhaW4gc3BsaXQgYmV0d2VlbiB0eXBlcy4KcHAoaW1hZ2U9b3VyX3Byb3RlaW5fbWV0cmljcyRib3hwbG90LAogICBmaWxlPWZpbGUucGF0aCgiaW1hZ2VzIiwgcGFzdGUwKHZlciwgIl9ib3hwbG90LnBuZyIpKSkKIyMgVGhpcyByZWNhcGl0dWxhdGVzIHRoZSBwcmV2aW91cyBwbG90LgoKcHAoaW1hZ2U9b3VyX3dob2xlX21ldHJpY3MkbGlic2l6ZSwKICAgZmlsZT1maWxlLnBhdGgoImltYWdlcyIsIHBhc3RlMCh2ZXIsICJfd2hvbGVfbGlic2l6ZS5wbmciKSkpCnBwKGltYWdlPW91cl93aG9sZV9ub3JtX21ldHJpY3MkcGNhcGxvdCwKICAgZmlsZT1maWxlLnBhdGgoImltYWdlcyIsIHBhc3RlMCh2ZXIsICJfd2hvbGVfbm9ybV9wY2EucG5nIikpKQpwcChpbWFnZT1vdXJfd2hvbGVfZnN2YV9tZXRyaWNzJHBjYXBsb3QsCiAgIGZpbGU9ZmlsZS5wYXRoKCJpbWFnZXMiLCBwYXN0ZTAodmVyLCAiX3dob2xlX2ZzdmFfcGNhLnBuZyIpKSkKcHAoaW1hZ2U9b3VyX3dob2xlX25vcm1fbWV0cmljcyRjb3JoZWF0LAogICBmaWxlPWZpbGUucGF0aCgiaW1hZ2VzIiwgcGFzdGUwKHZlciwgIl93aG9sZV9ub3JtX2NvcmhlYXQucG5nIikpKQpwcChpbWFnZT1vdXJfd2hvbGVfbWV0cmljcyRkZW5zaXR5LAogICBmaWxlPWZpbGUucGF0aCgiaW1hZ2VzIiwgcGFzdGUwKHZlciwgIl93aG9sZV9yYXdfZGVuc2l0eS5wbmciKSkpCnBwKGltYWdlPW91cl93aG9sZV9tZXRyaWNzJGJveHBsb3QsCiAgIGZpbGU9ZmlsZS5wYXRoKCJpbWFnZXMiLCBwYXN0ZTAodmVyLCAiX3dob2xlX2JveHBsb3QucG5nIikpKQoKcHAoaW1hZ2U9b3VyX2NmX21ldHJpY3MkbGlic2l6ZSwKICAgZmlsZT1maWxlLnBhdGgoImltYWdlcyIsIHBhc3RlMCh2ZXIsICJfbGlic2l6ZS5wbmciKSkpCnBwKGltYWdlPW91cl9jZl9ub3JtX21ldHJpY3MkcGNhcGxvdCwKICAgZmlsZT1maWxlLnBhdGgoImltYWdlcyIsIHBhc3RlMCh2ZXIsICJfbm9ybV9wY2EucG5nIikpKQpwcChpbWFnZT1vdXJfY2ZfZnN2YV9tZXRyaWNzJHBjYXBsb3QsCiAgIGZpbGU9ZmlsZS5wYXRoKCJpbWFnZXMiLCBwYXN0ZTAodmVyLCAiX2ZzdmFfcGNhLnBuZyIpKSkKcHAoaW1hZ2U9b3VyX2NmX25vcm1fbWV0cmljcyRjb3JoZWF0LAogICBmaWxlPWZpbGUucGF0aCgiaW1hZ2VzIiwgcGFzdGUwKHZlciwgIl9ub3JtX2NvcmhlYXQucG5nIikpKQpwcChpbWFnZT1vdXJfY2ZfbWV0cmljcyRkZW5zaXR5LAogICBmaWxlPWZpbGUucGF0aCgiaW1hZ2VzIiwgcGFzdGUwKHZlciwgIl9yYXdfZGVuc2l0eS5wbmciKSkpCnBwKGltYWdlPW91cl9jZl9tZXRyaWNzJGJveHBsb3QsCiAgIGZpbGU9ZmlsZS5wYXRoKCJpbWFnZXMiLCBwYXN0ZTAodmVyLCAiX2JveHBsb3QucG5nIikpKQpgYGAKCiMjIyBUYiBsaWJyYXJpZXMKCmBgYHtyIHRiX3ByaW50X21ldHJpY3N9CnBwKGltYWdlPXRiX3Byb3RlaW5fbWV0cmljcyRsaWJzaXplLAogICBmaWxlPWZpbGUucGF0aCgiaW1hZ2VzIiwgcGFzdGUwKHZlciwgIl90Yl9saWJzaXplLnBuZyIpKSkKIyMgSXQgc2VlbXMgdG8gbWUgdGhhdCB0aGUgc2NhbGUgb2YgdGhlIGRhdGEgaXMgYWxsIHdpdGhpbiBhbiBvcmRlciBvZiBtYWduaXR1ZGUgb3IgdHdvLgojIyBJIGNhbm5vdCBnZXQgdXNlZCB0byB0aGVzZSBhYnN1cmRseSBsYXJnZSBudW1iZXJzIHRob3VnaC4KcHAoaW1hZ2U9dGJfcHJvdGVpbl9ub3JtX21ldHJpY3MkcGNhcGxvdCwKICAgZmlsZT1maWxlLnBhdGgoImltYWdlcyIsIHBhc3RlMCh2ZXIsICJfdGJfbm9ybV9wY2EucG5nIikpKQojIyBUaGVyZSBhcHBlYXJzIHRvIGJlIGEgbmljZSBzcGxpdCBpbiB0aGUgZGF0YSwgaG93ZXZlciB0aGUgdW4tYXNzYXlhYmxlIGJhdGNoCiMjIGVmZmVjdCBpcyBhIHByb2JsZW0uCnBwKGltYWdlPXRiX3Byb3RlaW5fZnN2YV9tZXRyaWNzJHBjYXBsb3QsCiAgIGZpbGU9ZmlsZS5wYXRoKCJpbWFnZXMiLCBwYXN0ZTAodmVyLCAiX2ZzdmFfcGNhLnBuZyIpKSkKIyMgZnN2YSBzZWVtcyB0byBnZXQgc29tZSBoYW5kbGUgb24gdGhlIGRhdGEsIGJ1dCBJIGRvbid0IHRoaW5rIHdlIHNob3VsZCByZWx5CiMjIHVwb24gaXQuCnBwKGltYWdlPXRiX3Byb3RlaW5fbm9ybV9tZXRyaWNzJGNvcmhlYXQsCiAgIGZpbGU9ZmlsZS5wYXRoKCJpbWFnZXMiLCBwYXN0ZTAodmVyLCAiX25vcm1fY29yaGVhdC5wbmciKSkpCiMjIE9uY2UgYWdhaW4sIHRoZSB3aG9sZS1jZWxsL2N1bHR1cmUtZmlsdHJhdGUgc3BsaXQgaXMgdmVyeSBsYXJnZS4KcHAoaW1hZ2U9dGJfcHJvdGVpbl9tZXRyaWNzJGRlbnNpdHksCiAgIGZpbGU9ZmlsZS5wYXRoKCJpbWFnZXMiLCBwYXN0ZTAodmVyLCAiX3Jhd19kZW5zaXR5LnBuZyIpKSkKIyMgVGhlcmUgYXJlIHR3byBvYnZpb3VzIGRpc3RyaWJ1dGlvbnMgaW4gdGhlIGRhdGEsIG9uY2UgYWdhaW4gc3BsaXQgYmV0d2VlbiB0eXBlcy4KcHAoaW1hZ2U9dGJfcHJvdGVpbl9tZXRyaWNzJGJveHBsb3QsCiAgIGZpbGU9ZmlsZS5wYXRoKCJpbWFnZXMiLCBwYXN0ZTAodmVyLCAiX2JveHBsb3QucG5nIikpKQojIyBUaGlzIHJlY2FwaXR1bGF0ZXMgdGhlIHByZXZpb3VzIHBsb3QuCgpwcChpbWFnZT10Yl93aG9sZV9tZXRyaWNzJGxpYnNpemUsCiAgIGZpbGU9ZmlsZS5wYXRoKCJpbWFnZXMiLCBwYXN0ZTAodmVyLCAiX3dob2xlX2xpYnNpemUucG5nIikpKQpwcChpbWFnZT10Yl93aG9sZV9ub3JtX21ldHJpY3MkcGNhcGxvdCwKICAgZmlsZT1maWxlLnBhdGgoImltYWdlcyIsIHBhc3RlMCh2ZXIsICJfd2hvbGVfbm9ybV9wY2EucG5nIikpKQpwcChpbWFnZT10Yl93aG9sZV9mc3ZhX21ldHJpY3MkcGNhcGxvdCwKICAgZmlsZT1maWxlLnBhdGgoImltYWdlcyIsIHBhc3RlMCh2ZXIsICJfd2hvbGVfZnN2YV9wY2EucG5nIikpKQpwcChpbWFnZT10Yl93aG9sZV9ub3JtX21ldHJpY3MkY29yaGVhdCwKICAgZmlsZT1maWxlLnBhdGgoImltYWdlcyIsIHBhc3RlMCh2ZXIsICJfd2hvbGVfbm9ybV9jb3JoZWF0LnBuZyIpKSkKcHAoaW1hZ2U9dGJfd2hvbGVfbWV0cmljcyRkZW5zaXR5LAogICBmaWxlPWZpbGUucGF0aCgiaW1hZ2VzIiwgcGFzdGUwKHZlciwgIl93aG9sZV9yYXdfZGVuc2l0eS5wbmciKSkpCnBwKGltYWdlPXRiX3dob2xlX21ldHJpY3MkYm94cGxvdCwKICAgZmlsZT1maWxlLnBhdGgoImltYWdlcyIsIHBhc3RlMCh2ZXIsICJfd2hvbGVfYm94cGxvdC5wbmciKSkpCgpwcChpbWFnZT10Yl9jZl9tZXRyaWNzJGxpYnNpemUsCiAgIGZpbGU9ZmlsZS5wYXRoKCJpbWFnZXMiLCBwYXN0ZTAodmVyLCAiX2xpYnNpemUucG5nIikpKQpwcChpbWFnZT10Yl9jZl9ub3JtX21ldHJpY3MkcGNhcGxvdCwKICAgZmlsZT1maWxlLnBhdGgoImltYWdlcyIsIHBhc3RlMCh2ZXIsICJfbm9ybV9wY2EucG5nIikpKQpwcChpbWFnZT10Yl9jZl9mc3ZhX21ldHJpY3MkcGNhcGxvdCwKICAgZmlsZT1maWxlLnBhdGgoImltYWdlcyIsIHBhc3RlMCh2ZXIsICJfZnN2YV9wY2EucG5nIikpKQpwcChpbWFnZT10Yl9jZl9ub3JtX21ldHJpY3MkY29yaGVhdCwKICAgZmlsZT1maWxlLnBhdGgoImltYWdlcyIsIHBhc3RlMCh2ZXIsICJfbm9ybV9jb3JoZWF0LnBuZyIpKSkKcHAoaW1hZ2U9dGJfY2ZfbWV0cmljcyRkZW5zaXR5LAogICBmaWxlPWZpbGUucGF0aCgiaW1hZ2VzIiwgcGFzdGUwKHZlciwgIl9yYXdfZGVuc2l0eS5wbmciKSkpCnBwKGltYWdlPXRiX2NmX21ldHJpY3MkYm94cGxvdCwKICAgZmlsZT1maWxlLnBhdGgoImltYWdlcyIsIHBhc3RlMCh2ZXIsICJfYm94cGxvdC5wbmciKSkpCmBgYAoKIyBDb2xsYXBzZSB0ZWNobmljYWwgcmVwbGljYXRlcwoKSSBhbSB0aGlua2luZyB0aGF0IGEgc2ltcGxlIHN1bSBvZiB0aGUgZGF0YSBpbiB0aGUgdGVjaG5pY2FsIHJlcGxpY2F0ZXMgc2hvdWxkIGJlIHN1ZmZpY2llbnQuCgpgYGB7ciBvdXJfY29sbGFwc2V9Cm91cl9jb21wcmVzc2VkIDwtIGNvbmNhdGVuYXRlX3J1bnMob3VyX3Byb3RlaW5fZXhwdCwgY29sdW1uPSJiaW9yZXBsaWNhdGUiKQp0Yl9jb21wcmVzc2VkIDwtIGNvbmNhdGVuYXRlX3J1bnModGJfcHJvdGVpbl9leHB0LCBjb2x1bW49ImJpb3JlcGxpY2F0ZSIpCgpvdXJfd2hvbGVfY29tcHJlc3NlZCA8LSBjb25jYXRlbmF0ZV9ydW5zKG91cl93aG9sZV9leHB0LCBjb2x1bW49ImJpb3JlcGxpY2F0ZSIpCm91cl9jZl9jb21wcmVzc2VkIDwtIGNvbmNhdGVuYXRlX3J1bnMob3VyX2NmX2V4cHQsIGNvbHVtbj0iYmlvcmVwbGljYXRlIikKdGJfd2hvbGVfY29tcHJlc3NlZCA8LSBjb25jYXRlbmF0ZV9ydW5zKHRiX3dob2xlX2V4cHQsIGNvbHVtbj0iYmlvcmVwbGljYXRlIikKdGJfY2ZfY29tcHJlc3NlZCA8LSBjb25jYXRlbmF0ZV9ydW5zKHRiX2NmX2V4cHQsIGNvbHVtbj0iYmlvcmVwbGljYXRlIikKYGBgCgojIyBSZXBlcmZvcm0gbWV0cmljcyB3aXRoIHRoZSB0ZWNobmljYWwgcmVwbGljYXRlcyByZW1vdmVkLgoKYGBge3IgY29tcHJlc3NlZF9tZXRyaWNzLCBmaWcuc2hvdz0iaGlkZSJ9Cm91cl9jb21wcmVzc2VkX21ldHJpY3MgPC0gc20oZ3JhcGhfbWV0cmljcyhvdXJfY29tcHJlc3NlZCkpCm91cl9jb21wcmVzc2VkX25vcm0gPC0gc20obm9ybWFsaXplX2V4cHQob3VyX2NvbXByZXNzZWQsIHRyYW5zZm9ybT0ibG9nMiIsIGNvbnZlcnQ9ImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9ybT0icXVhbnQiLCBmaWx0ZXI9VFJVRSkpCm91cl9jb21wcmVzc2VkX25vcm1fbWV0cmljcyA8LSBzbShncmFwaF9tZXRyaWNzKG91cl9jb21wcmVzc2VkX25vcm0pKQoKdGJfY29tcHJlc3NlZF9tZXRyaWNzIDwtIHNtKGdyYXBoX21ldHJpY3ModGJfY29tcHJlc3NlZCkpCnRiX2NvbXByZXNzZWRfbm9ybSA8LSBzbShub3JtYWxpemVfZXhwdCh0Yl9jb21wcmVzc2VkLCB0cmFuc2Zvcm09ImxvZzIiLCBjb252ZXJ0PSJjcG0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vcm09InF1YW50IiwgZmlsdGVyPVRSVUUpKQp0Yl9jb21wcmVzc2VkX25vcm1fbWV0cmljcyA8LSBzbShncmFwaF9tZXRyaWNzKHRiX2NvbXByZXNzZWRfbm9ybSkpCmBgYAoKYGBge3Igc2hvd19jb21wcmVzc2VkfQpvdXJfY29tcHJlc3NlZF9ub3JtX21ldHJpY3MkcGNhcGxvdAp0Yl9jb21wcmVzc2VkX25vcm1fbWV0cmljcyRwY2FwbG90CmBgYAoKYGBge3IgY29tcHJlc3NlZF9kZX0Kb3VyX2NvbXByZXNzZWRfZGUgPC0gYWxsX3BhaXJ3aXNlKG91cl9jb21wcmVzc2VkLCBtb2RlbF9iYXRjaD1GQUxTRSwgZm9yY2U9VFJVRSkKdGJfY29tcHJlc3NlZF9kZSA8LSBhbGxfcGFpcndpc2UodGJfY29tcHJlc3NlZCwgbW9kZWxfYmF0Y2g9RkFMU0UsIGZvcmNlPVRSVUUpCmBgYAoKIyBBdHRlbXB0IHNvbWUgcXVhbnRpZmljYXRpb24gY29tcGFyaXNvbnM/CgojIyBPdXIgbGlicmFyaWVzCgpgYGB7ciBvdXJfZGVfdGVzdGluZywgZmlnLnNob3c9J2hpZGUnfQpvdXJfcGFpcndpc2VfZmlsdCA8LSBzbShub3JtYWxpemVfZXhwdChvdXJfY29tcHJlc3NlZCwgZmlsdGVyPVRSVUUpKQpvdXJfcGFpcndpc2VfY29tcCA8LSBzbShhbGxfcGFpcndpc2Uob3VyX3BhaXJ3aXNlX2ZpbHQsIG1vZGVsX2JhdGNoPSJmc3ZhIiwgZm9yY2U9VFJVRSkpCm91cl9wYWlyd2lzZV9ub2JhdGNoIDwtIHNtKGFsbF9wYWlyd2lzZShvdXJfcGFpcndpc2VfZmlsdCwgbW9kZWxfYmF0Y2g9RkFMU0UsIGZvcmNlPVRSVUUpKQpgYGAKCiMjIFRiIGxpYnJhcmllcwoKYGBge3IgdGJfZGVfdGVzdGluZywgZmlnLnNob3c9J2hpZGUnfQp0Yl9wYWlyd2lzZV9maWx0IDwtIHNtKG5vcm1hbGl6ZV9leHB0KHRiX2NvbXByZXNzZWQsIGZpbHRlcj1UUlVFKSkKdGJfcGFpcndpc2VfY29tcCA8LSBzbShhbGxfcGFpcndpc2UodGJfcGFpcndpc2VfZmlsdCwgbW9kZWxfYmF0Y2g9ImZzdmEiLCBmb3JjZT1UUlVFKSkKdGJfcGFpcndpc2Vfbm9iYXRjaCA8LSBzbShhbGxfcGFpcndpc2UodGJfcGFpcndpc2VfZmlsdCwgbW9kZWxfYmF0Y2g9RkFMU0UsIGZvcmNlPVRSVUUpKQpgYGAKCiMjIyBTaG93IGEgZmV3IG1ldHJpY3MgZnJvbSB0aGUgaHBnbHRvb2xzIHBhaXJ3aXNlIGNvbXBhcmlzb25zCgpgYGB7ciBzaG93X2RlX3Rlc3Rpbmd9Cm91cl9jb21wcmVzc2VkX2RlJGNvbXBhcmlzb24kaGVhdAp0Yl9jb21wcmVzc2VkX2RlJGNvbXBhcmlzb24kaGVhdApgYGAKCiMgRm9yIGVhY2ggbXNzdGF0cyBydW4sIGRvIGEgREUgdGFibGUKCiMjIHd0X2NmIHZzIHd0X3dob2xlCgojIyMgT3VyIGxpYnJhcmllcwoKYGBge3Igb3VyX2NvbWJpbmVfd3RjZl93dHdob2xlLCBmaWcuc2hvdz0naGlkZSd9CmtlZXBlcnMgPC0gbGlzdCgKICAid3RjZl92c193dHdob2xlIiA9IGMoInd0X2ZpbHRyYXRlIiwgInd0X3dob2xlIikpCgpzZXRfbmFtZSA8LSAid3RfZmlsdHJhdGVfdnNfd3Rfd2hvbGUiCm1zc3RhdHNfcmVzdWx0IDwtIG91cl9yZXN1bHRzW1tzZXRfbmFtZV1dW1siQ29tcGFyaXNvblJlc3VsdCJdXQpkcm9wcGVycyA8LSBjKCJ1bmRlZmluZWQiKQpuYW1lcyhkcm9wcGVycykgPC0gImxvZzJmYyIKIyMgTWFrZSBzdXJlIHRvIHNldCB0aGUgcm93bmFtZXMgc28gaXQgd2lsbCBtZXJnZSBpbnRvIHRoZSBleGNlbCBmaWxlLgpyb3duYW1lcyhtc3N0YXRzX3Jlc3VsdCkgPC0gbXNzdGF0c19yZXN1bHRbWyJQcm90ZWluIl1dCgpvdXJfd3RjZl93dHdob2xlX3RhYmxlcyA8LSBzbShjb21iaW5lX2RlX3RhYmxlcygKICBvdXJfY29tcHJlc3NlZF9kZSwga2VlcGVycz1rZWVwZXJzLCBleHRyYV9hbm5vdD1tc3N0YXRzX3Jlc3VsdCwKICBleGNsdWRlcz1kcm9wcGVycywKICBleGNlbD1wYXN0ZTAoImV4Y2VsL291cl93dGNmX3ZzX3d0d2hvbGVfdGFibGVzLXYiLCB2ZXIsICIueGxzeCIpKSkKCm91cl93dGNmX25vYmF0Y2hfd3R3aG9sZV90YWJsZXMgPC0gc20oY29tYmluZV9kZV90YWJsZXMoCiAgb3VyX3BhaXJ3aXNlX25vYmF0Y2gsIGtlZXBlcnM9a2VlcGVycywgZXh0cmFfYW5ub3Q9bXNzdGF0c19yZXN1bHQsCiAgZXhjbHVkZXM9ZHJvcHBlcnMsCiAgZXhjZWw9cGFzdGUwKCJleGNlbC9vdXJfd3RjZl92c193dHdob2xlX25vYmF0Y2hfdGFibGVzLXYiLCB2ZXIsICIueGxzeCIpKSkKCmNvbXBfdGFibGUgPC0gb3VyX3d0Y2Zfd3R3aG9sZV90YWJsZXMkZGF0YVtbc2V0X25hbWVdXQpjb3IudGVzdChjb21wX3RhYmxlJGxvZzJmYywgY29tcF90YWJsZSRsaW1tYV9sb2dmYywgbWV0aG9kPSJzcGVhcm1hbiIpCgpjb21wX3RhYmxlIDwtIG91cl93dGNmX25vYmF0Y2hfd3R3aG9sZV90YWJsZXMkZGF0YVtbc2V0X25hbWVdXQpjb3IudGVzdChjb21wX3RhYmxlJGxvZzJmYywgY29tcF90YWJsZSRsaW1tYV9sb2dmYywgbWV0aG9kPSJzcGVhcm1hbiIpCmBgYAoKIyMjIFRiIGxpYnJhcmllcwoKYGBge3IgdGJfY29tYmluZV93dGNmX3d0d2hvbGUsIGZpZy5zaG93PSdoaWRlJ30KbXNzdGF0c19yZXN1bHQgPC0gdGJfcmVzdWx0c1tbc2V0X25hbWVdXVtbIkNvbXBhcmlzb25SZXN1bHQiXV0KZHJvcHBlcnMgPC0gYygidW5kZWZpbmVkIikKbmFtZXMoZHJvcHBlcnMpIDwtICJsb2cyZmMiCiMjIE1ha2Ugc3VyZSB0byBzZXQgdGhlIHJvd25hbWVzIHNvIGl0IHdpbGwgbWVyZ2UgaW50byB0aGUgZXhjZWwgZmlsZS4Kcm93bmFtZXMobXNzdGF0c19yZXN1bHQpIDwtIG1zc3RhdHNfcmVzdWx0W1siUHJvdGVpbiJdXQoKdGJfd3RjZl93dHdob2xlX3RhYmxlcyA8LSBzbShjb21iaW5lX2RlX3RhYmxlcygKICB0Yl9wYWlyd2lzZV9jb21wLCBrZWVwZXJzPWtlZXBlcnMsIGV4dHJhX2Fubm90PW1zc3RhdHNfcmVzdWx0LAogIGV4Y2x1ZGVzPWRyb3BwZXJzLAogIGV4Y2VsPXBhc3RlMCgiZXhjZWwvdGJfd3RjZl92c193dHdob2xlX3RhYmxlcy12IiwgdmVyLCAiLnhsc3giKSkpCgp0Yl93dGNmX25vYmF0Y2hfd3R3aG9sZV90YWJsZXMgPC0gc20oY29tYmluZV9kZV90YWJsZXMoCiAgdGJfcGFpcndpc2Vfbm9iYXRjaCwga2VlcGVycz1rZWVwZXJzLCBleHRyYV9hbm5vdD1tc3N0YXRzX3Jlc3VsdCwKICBleGNsdWRlcz1kcm9wcGVycywKICBleGNlbD1wYXN0ZTAoImV4Y2VsL3RiX3d0Y2ZfdnNfd3R3aG9sZV9ub2JhdGNoX3RhYmxlcy12IiwgdmVyLCAiLnhsc3giKSkpCgpjb21wX3RhYmxlIDwtIHRiX3d0Y2Zfd3R3aG9sZV90YWJsZXMkZGF0YVtbc2V0X25hbWVdXQpjb3IudGVzdChjb21wX3RhYmxlJGxvZzJmYywgY29tcF90YWJsZSRsaW1tYV9sb2dmYywgbWV0aG9kPSJzcGVhcm1hbiIpCgpjb21wX3RhYmxlIDwtIHRiX3d0Y2Zfbm9iYXRjaF93dHdob2xlX3RhYmxlcyRkYXRhW1tzZXRfbmFtZV1dCmNvci50ZXN0KGNvbXBfdGFibGUkbG9nMmZjLCBjb21wX3RhYmxlJGxpbW1hX2xvZ2ZjLCBtZXRob2Q9InNwZWFybWFuIikKYGBgCgojIyBkZWx0YV9jZiB2cyBkZWx0YV93aG9sZQoKIyMjIE91ciBsaWJyYXJpZXMKCmBgYHtyIG91cl9jb21iaW5lX2RlbHRhY2ZfZGVsdGF3aG9sZSwgZmlnLnNob3c9J2hpZGUnfQprZWVwZXJzIDwtIGxpc3QoCiAgImRlbHRhY2ZfdnNfZGVsdGF3aG9sZSIgPSBjKCJkZWx0YV9maWx0cmF0ZSIsICJkZWx0YV93aG9sZSIpKQoKc2V0X25hbWUgPC0gImRlbHRhX2ZpbHRyYXRlX3ZzX2RlbHRhX3dob2xlIgptc3N0YXRzX3Jlc3VsdCA8LSBvdXJfcmVzdWx0c1tbc2V0X25hbWVdXVtbIkNvbXBhcmlzb25SZXN1bHQiXV0KIyMgTWFrZSBzdXJlIHRvIHNldCB0aGUgcm93bmFtZXMgc28gaXQgd2lsbCBtZXJnZSBpbnRvIHRoZSBleGNlbCBmaWxlLgpyb3duYW1lcyhtc3N0YXRzX3Jlc3VsdCkgPC0gbXNzdGF0c19yZXN1bHRbWyJQcm90ZWluIl1dCgpvdXJfZGVsdGFjZl9kZWx0YXdob2xlX3RhYmxlcyA8LSBzbShjb21iaW5lX2RlX3RhYmxlcygKICBvdXJfcGFpcndpc2VfY29tcCwga2VlcGVycz1rZWVwZXJzLCBleHRyYV9hbm5vdD1tc3N0YXRzX3Jlc3VsdCwKICBleGNlbD1wYXN0ZTAoImV4Y2VsL291cl9kZWx0YWNmX3ZzX2RlbHRhd2hvbGVfdGFibGVzLXYiLCB2ZXIsICIueGxzeCIpKSkKYGBgCgojIyMgVGIgbGlicmFyaWVzCgpgYGB7ciB0Yl9jb21iaW5lX2RlbHRhY2ZfZGVsdGF3aG9sZSwgZmlnLnNob3c9J2hpZGUnfQptc3N0YXRzX3Jlc3VsdCA8LSB0Yl9yZXN1bHRzW1tzZXRfbmFtZV1dW1siQ29tcGFyaXNvblJlc3VsdCJdXQojIyBNYWtlIHN1cmUgdG8gc2V0IHRoZSByb3duYW1lcyBzbyBpdCB3aWxsIG1lcmdlIGludG8gdGhlIGV4Y2VsIGZpbGUuCnJvd25hbWVzKG1zc3RhdHNfcmVzdWx0KSA8LSBtc3N0YXRzX3Jlc3VsdFtbIlByb3RlaW4iXV0KCnRiX2RlbHRhY2ZfZGVsdGF3aG9sZV90YWJsZXMgPC0gc20oY29tYmluZV9kZV90YWJsZXMoCiAgdGJfcGFpcndpc2VfY29tcCwga2VlcGVycz1rZWVwZXJzLCBleHRyYV9hbm5vdD1tc3N0YXRzX3Jlc3VsdCwKICBleGNlbD1wYXN0ZTAoImV4Y2VsL3RiX2RlbHRhY2ZfdnNfZGVsdGF3aG9sZV90YWJsZXMtdiIsIHZlciwgIi54bHN4IikpKQpgYGAKCiMjIGNvbXBfY2YgdnMgY29tcF93aG9sZQoKIyMjIE91ciBsaWJyYXJpZXMKCmBgYHtyIG91cl9jb21iaW5lX2NvbXBjZl9jb21wd2hvbGUsIGZpZy5zaG93PSdoaWRlJ30Ka2VlcGVycyA8LSBsaXN0KAogICJjb21wY2ZfdnNfY29tcHdob2xlIiA9IGMoImNvbXBfZmlsdHJhdGUiLCAiY29tcF93aG9sZSIpKQoKc2V0X25hbWUgPC0gImNvbXBfZmlsdHJhdGVfdnNfY29tcF93aG9sZSIKbXNzdGF0c19yZXN1bHQgPC0gb3VyX3Jlc3VsdHNbW3NldF9uYW1lXV1bWyJDb21wYXJpc29uUmVzdWx0Il1dCiMjIE1ha2Ugc3VyZSB0byBzZXQgdGhlIHJvd25hbWVzIHNvIGl0IHdpbGwgbWVyZ2UgaW50byB0aGUgZXhjZWwgZmlsZS4Kcm93bmFtZXMobXNzdGF0c19yZXN1bHQpIDwtIG1zc3RhdHNfcmVzdWx0W1siUHJvdGVpbiJdXQoKY29tcGNmX2NvbXB3aG9sZV90YWJsZXMgPC0gc20oY29tYmluZV9kZV90YWJsZXMoCiAgb3VyX3BhaXJ3aXNlX2NvbXAsIGtlZXBlcnM9a2VlcGVycywgZXh0cmFfYW5ub3Q9bXNzdGF0c19yZXN1bHQsCiAgZXhjZWw9cGFzdGUwKCJleGNlbC9vdXJfY29tcGNmX3ZzX2NvbXB3aG9sZV90YWJsZXMtdiIsIHZlciwgIi54bHN4IikpKQpgYGAKCiMjIyBUYiBsaWJyYXJpZXMKCmBgYHtyIHRiX2NvbWJpbmVfY29tcGNmX2NvbXB3aG9sZSwgZmlnLnNob3c9J2hpZGUnfQptc3N0YXRzX3Jlc3VsdCA8LSB0Yl9yZXN1bHRzW1tzZXRfbmFtZV1dW1siQ29tcGFyaXNvblJlc3VsdCJdXQojIyBNYWtlIHN1cmUgdG8gc2V0IHRoZSByb3duYW1lcyBzbyBpdCB3aWxsIG1lcmdlIGludG8gdGhlIGV4Y2VsIGZpbGUuCnJvd25hbWVzKG1zc3RhdHNfcmVzdWx0KSA8LSBtc3N0YXRzX3Jlc3VsdFtbIlByb3RlaW4iXV0KCmNvbXBjZl9jb21wd2hvbGVfdGFibGVzIDwtIHNtKGNvbWJpbmVfZGVfdGFibGVzKAogIHRiX3BhaXJ3aXNlX2NvbXAsIGtlZXBlcnM9a2VlcGVycywgZXh0cmFfYW5ub3Q9bXNzdGF0c19yZXN1bHQsCiAgZXhjZWw9cGFzdGUwKCJleGNlbC90Yl9jb21wY2ZfdnNfY29tcHdob2xlX3RhYmxlcy12IiwgdmVyLCAiLnhsc3giKSkpCmBgYAoKIyMgZGVsdGFfY2YgdnMgd3RfY2YKCiMjIyBPdXIgbGlicmFyaWVzCgpgYGB7ciBvdXJfY29tYmluZV9kZWx0YWNmX3d0Y2YsIGZpZy5zaG93PSdoaWRlJ30Ka2VlcGVycyA8LSBsaXN0KAogICJkZWx0YWNmX3ZzX3d0Y2YiID0gYygiZGVsdGFfZmlsdHJhdGUiLCAid3RfZmlsdHJhdGUiKSkKCnNldF9uYW1lIDwtICJkZWx0YV9maWx0cmF0ZV92c193dF9maWx0cmF0ZSIKbXNzdGF0c19yZXN1bHQgPC0gb3VyX3Jlc3VsdHNbW3NldF9uYW1lXV1bWyJDb21wYXJpc29uUmVzdWx0Il1dCiMjIE1ha2Ugc3VyZSB0byBzZXQgdGhlIHJvd25hbWVzIHNvIGl0IHdpbGwgbWVyZ2UgaW50byB0aGUgZXhjZWwgZmlsZS4Kcm93bmFtZXMobXNzdGF0c19yZXN1bHQpIDwtIG1zc3RhdHNfcmVzdWx0W1siUHJvdGVpbiJdXQoKZGVsdGFjZl93dGNmX3RhYmxlcyA8LSBzbShjb21iaW5lX2RlX3RhYmxlcygKICBvdXJfcGFpcndpc2VfY29tcCwga2VlcGVycz1rZWVwZXJzLCBleHRyYV9hbm5vdD1tc3N0YXRzX3Jlc3VsdCwKICBleGNlbD1wYXN0ZTAoImV4Y2VsL291cl9kZWx0YWNmX3ZzX3d0Y2ZfdGFibGVzLXYiLCB2ZXIsICIueGxzeCIpKSkKYGBgCgojIyMgVGIgbGlicmFyaWVzCgpgYGB7ciB0Yl9jb21iaW5lX2RlbHRhY2Zfd3RjZiwgZmlnLnNob3c9J2hpZGUnfQptc3N0YXRzX3Jlc3VsdCA8LSB0Yl9yZXN1bHRzW1tzZXRfbmFtZV1dW1siQ29tcGFyaXNvblJlc3VsdCJdXQpyb3duYW1lcyhtc3N0YXRzX3Jlc3VsdCkgPC0gbXNzdGF0c19yZXN1bHRbWyJQcm90ZWluIl1dCgpkZWx0YWNmX3d0Y2ZfdGFibGVzIDwtIHNtKGNvbWJpbmVfZGVfdGFibGVzKAogIHRiX3BhaXJ3aXNlX2NvbXAsIGtlZXBlcnM9a2VlcGVycywgZXh0cmFfYW5ub3Q9bXNzdGF0c19yZXN1bHQsCiAgZXhjZWw9cGFzdGUwKCJleGNlbC90Yl9kZWx0YWNmX3ZzX3d0Y2ZfdGFibGVzLXYiLCB2ZXIsICIueGxzeCIpKSkKCmNvbXBfdGFibGUgPC0gZGVsdGFjZl93dGNmX3RhYmxlcyRkYXRhW1tzZXRfbmFtZV1dCmNvci50ZXN0KHRhaWwoY29tcF90YWJsZSRsb2cyZmMsIG49NTApLCB0YWlsKGNvbXBfdGFibGUkbGltbWFfbG9nZmMsIG49NTApLCBtZXRob2Q9InNwZWFybWFuIikKYGBgCgojIyBjb21wX2NmIHZzIHd0X2NmCgojIyMgT3VyIGxpYnJhcmllcwoKYGBge3Igb3VyX2NvbWJpbmVfY29tcGNmX3d0Y2YsIGZpZy5zaG93PSdoaWRlJ30Ka2VlcGVycyA8LSBsaXN0KAogICJjb21wY2ZfdnNfd3RjZiIgPSBjKCJjb21wX2ZpbHRyYXRlIiwgInd0X2ZpbHRyYXRlIikpCnNldF9uYW1lIDwtICJjb21wX2ZpbHRyYXRlX3ZzX3d0X2ZpbHRyYXRlIgptc3N0YXRzX3Jlc3VsdCA8LSBvdXJfcmVzdWx0c1tbc2V0X25hbWVdXVtbIkNvbXBhcmlzb25SZXN1bHQiXV0Kcm93bmFtZXMobXNzdGF0c19yZXN1bHQpIDwtIG1zc3RhdHNfcmVzdWx0W1siUHJvdGVpbiJdXQoKY29tcGNmX3d0Y2ZfdGFibGVzIDwtIHNtKGNvbWJpbmVfZGVfdGFibGVzKAogIG91cl9wYWlyd2lzZV9jb21wLCBrZWVwZXJzPWtlZXBlcnMsIGV4dHJhX2Fubm90PW1zc3RhdHNfcmVzdWx0LAogIGV4Y2VsPXBhc3RlMCgiZXhjZWwvb3VyX2NvbXBjZl92c193dGNmX3RhYmxlcy12IiwgdmVyLCAiLnhsc3giKSkpCmBgYAoKIyMjIFRiIGxpYnJhcmllcwoKYGBge3IgdGJfY29tYmluZV9jb21wY2Zfd3RjZiwgZmlnLnNob3c9J2hpZGUnfQptc3N0YXRzX3Jlc3VsdCA8LSB0Yl9yZXN1bHRzW1tzZXRfbmFtZV1dW1siQ29tcGFyaXNvblJlc3VsdCJdXQpyb3duYW1lcyhtc3N0YXRzX3Jlc3VsdCkgPC0gbXNzdGF0c19yZXN1bHRbWyJQcm90ZWluIl1dCgpjb21wY2Zfd3RjZl90YWJsZXMgPC0gc20oY29tYmluZV9kZV90YWJsZXMoCiAgdGJfcGFpcndpc2VfY29tcCwga2VlcGVycz1rZWVwZXJzLCBleHRyYV9hbm5vdD1tc3N0YXRzX3Jlc3VsdCwKICBleGNlbD1wYXN0ZTAoImV4Y2VsL3RiX2NvbXBjZl92c193dGNmX3RhYmxlcy12IiwgdmVyLCAiLnhsc3giKSkpCmBgYAoKIyMgZGVsdGFfd2hvbGUgdnMgd3Rfd2hvbGUKCiMjIyBPdXIgbGlicmFyaWVzCgpgYGB7ciBvdXJfY29tYmluZV9kZWxhd2hvbGVfd3R3aG9sZSwgZmlnLnNob3c9J2hpZGUnfQprZWVwZXJzIDwtIGxpc3QoCiAgInd0Y2ZfdnNfd3R3aG9sZSIgPSBjKCJkZWx0YV93aG9sZSIsICJ3dF93aG9sZSIpKQpzZXRfbmFtZSA8LSAiZGVsdGFfd2hvbGVfdnNfd3Rfd2hvbGUiCm1zc3RhdHNfcmVzdWx0IDwtIG91cl9yZXN1bHRzW1tzZXRfbmFtZV1dW1siQ29tcGFyaXNvblJlc3VsdCJdXQpyb3duYW1lcyhtc3N0YXRzX3Jlc3VsdCkgPC0gbXNzdGF0c19yZXN1bHRbWyJQcm90ZWluIl1dCgp3dGNmX3d0d2hvbGVfdGFibGVzIDwtIHNtKGNvbWJpbmVfZGVfdGFibGVzKAogIG91cl9wYWlyd2lzZV9jb21wLCBrZWVwZXJzPWtlZXBlcnMsIGV4dHJhX2Fubm90PW1zc3RhdHNfcmVzdWx0LAogIGV4Y2VsPXBhc3RlMCgiZXhjZWwvb3VyX2RlbHRhd2hvbGVfdnNfd3R3aG9sZV90YWJsZXMtdiIsIHZlciwgIi54bHN4IikpKQpgYGAKCiMjIyBUYiBsaWJyYXJpZXMKCmBgYHtyIHRiX2NvbWJpbmVfZGVsYXdob2xlX3d0d2hvbGUsIGZpZy5zaG93PSdoaWRlJ30KbXNzdGF0c19yZXN1bHQgPC0gdGJfcmVzdWx0c1tbc2V0X25hbWVdXVtbIkNvbXBhcmlzb25SZXN1bHQiXV0Kcm93bmFtZXMobXNzdGF0c19yZXN1bHQpIDwtIG1zc3RhdHNfcmVzdWx0W1siUHJvdGVpbiJdXQoKd3RjZl93dHdob2xlX3RhYmxlcyA8LSBzbShjb21iaW5lX2RlX3RhYmxlcygKICB0Yl9wYWlyd2lzZV9jb21wLCBrZWVwZXJzPWtlZXBlcnMsIGV4dHJhX2Fubm90PW1zc3RhdHNfcmVzdWx0LAogIGV4Y2VsPXBhc3RlMCgiZXhjZWwvdGJfZGVsdGF3aG9sZV92c193dHdob2xlX3RhYmxlcy12IiwgdmVyLCAiLnhsc3giKSkpCmBgYAoKIyMgY29tcF93aG9sZSB2cyB3dF93aG9sZQoKIyMjIE91ciBsaWJyYXJpZXMKCmBgYHtyIG91cl9jb21iaW5lX2NvbXB3aG9sZV93dHdob2xlLCBmaWcuc2hvdz0naGlkZSd9CmtlZXBlcnMgPC0gbGlzdCgKICAiY29tcHdob2xlX3ZzX3d0d2hvbGUiID0gYygiY29tcF93aG9sZSIsICJ3dF93aG9sZSIpKQpzZXRfbmFtZSA8LSAiY29tcF93aG9sZV92c193dF93aG9sZSIKbXNzdGF0c19yZXN1bHQgPC0gb3VyX3Jlc3VsdHNbW3NldF9uYW1lXV1bWyJDb21wYXJpc29uUmVzdWx0Il1dCnJvd25hbWVzKG1zc3RhdHNfcmVzdWx0KSA8LSBtc3N0YXRzX3Jlc3VsdFtbIlByb3RlaW4iXV0KCmNvbXB3aG9sZV93dHdob2xlX3RhYmxlcyA8LSBzbShjb21iaW5lX2RlX3RhYmxlcygKICBvdXJfcGFpcndpc2VfY29tcCwga2VlcGVycz1rZWVwZXJzLCBleHRyYV9hbm5vdD1tc3N0YXRzX3Jlc3VsdCwKICBleGNlbD1wYXN0ZTAoImV4Y2VsL291cl9jb21wd2hvbGVfdnNfd3R3aG9sZV90YWJsZXMtdiIsIHZlciwgIi54bHN4IikpKQpgYGAKCiMjIyBUYiBsaWJyYXJpZXMKCmBgYHtyIHRiX2NvbWJpbmVfY29tcHdob2xlX3d0d2hvbGUsIGZpZy5zaG93PSdoaWRlJ30KbXNzdGF0c19yZXN1bHQgPC0gdGJfcmVzdWx0c1tbc2V0X25hbWVdXVtbIkNvbXBhcmlzb25SZXN1bHQiXV0Kcm93bmFtZXMobXNzdGF0c19yZXN1bHQpIDwtIG1zc3RhdHNfcmVzdWx0W1siUHJvdGVpbiJdXQoKY29tcHdob2xlX3d0d2hvbGVfdGFibGVzIDwtIHNtKGNvbWJpbmVfZGVfdGFibGVzKAogIHRiX3BhaXJ3aXNlX2NvbXAsIGtlZXBlcnM9a2VlcGVycywgZXh0cmFfYW5ub3Q9bXNzdGF0c19yZXN1bHQsCiAgZXhjZWw9cGFzdGUwKCJleGNlbC90Yl9jb21wd2hvbGVfdnNfd3R3aG9sZV90YWJsZXMtdiIsIHZlciwgIi54bHN4IikpKQpgYGAKCmBgYHtyIGNvbXBhcmVfb3VyX3RifQpvdXJfdGFibGUgPC0gb3VyX3BhaXJ3aXNlX2NvbXAkZGVzZXEkYWxsX3RhYmxlcyR3dF93aG9sZV92c193dF9maWx0cmF0ZQp0Yl90YWJsZSA8LSB0Yl9wYWlyd2lzZV9jb21wJGRlc2VxJGFsbF90YWJsZXMkd3Rfd2hvbGVfdnNfd3RfZmlsdHJhdGUKcm93bmFtZXModGJfdGFibGUpIDwtIGdzdWIocGF0dGVybj0iXiguKilfLioiLCByZXBsYWNlbWVudD0iXFwxIiwgeD1yb3duYW1lcyh0Yl90YWJsZSkpCgp0ZXN0X3RhYmxlIDwtIG1lcmdlKG91cl90YWJsZSwgdGJfdGFibGUsIGJ5PSJyb3cubmFtZXMiKQpjb3IudGVzdCh0ZXN0X3RhYmxlJGxvZ0ZDLngsIHRlc3RfdGFibGUkbG9nRkMueSkKYGBgCgojIFRPRE8KCiogMjAxOC0wNC0xMDogIE1ha2Ugc3VyZSBteSBpbnZvY2F0aW9ucyBvZiBTV0FUSDJzdGF0cy9NU3N0YXRzIGFyZSBjb3JyZWN0LgoKYGBge3Igc2F2ZW1lLCBldmFsPUZBTFNFfQppZiAoIWlzVFJVRShnZXQwKCJza2lwX2xvYWQiKSkpIHsKICBtZXNzYWdlKHBhc3RlMCgiVGhpcyBpcyBocGdsdG9vbHMgY29tbWl0OiAiLCBnZXRfZ2l0X2NvbW1pdCgpKSkKICB0aGlzX3NhdmUgPC0gcGFzdGUwKGdzdWIocGF0dGVybj0iXFwuUm1kIiwgcmVwbGFjZT0iIiwgeD1ybWRfZmlsZSksICItdiIsIHZlciwgIi5yZGEueHoiKQogIG1lc3NhZ2UocGFzdGUwKCJTYXZpbmcgdG8gIiwgdGhpc19zYXZlKSkKICB0bXAgPC0gc20oc2F2ZW1lKGZpbGVuYW1lPXRoaXNfc2F2ZSkpCiAgcGFuZGVyOjpwYW5kZXIoc2Vzc2lvbkluZm8oKSkKfQpgYGAK