1 M. musculus

This will be a very minimal analysis until we get some replicates.

1.1 Annotations

I am using mm38_100.

## My load_biomart_annotations() function defaults to human, so that will be quick.
mm_annot <- load_biomart_annotations(species="mmusculus")
## The biomart annotations file already exists, loading from it.
mm_annot <- mm_annot[["annotation"]]
mm_annot[["txid"]] <- paste0(mm_annot[["ensembl_transcript_id"]], ".", mm_annot[["version"]])
rownames(mm_annot) <- make.names(mm_annot[["ensembl_gene_id"]], unique=TRUE)

tx_gene_map <- mm_annot[, c("txid", "ensembl_gene_id")]

So, I now have a table of mouse annotations.

1.2 Metadata

I am going to write a quick sample sheet in the current working directory called ‘all_samples.xlsx’ and put the names of the count tables in it.

1.3 Create expressionsets

Here I combine the metadata, count data, and annotations.

It is worth noting that the gene IDs from htseq-count probably do not match the annotations retrieved because they are likely exon-based rather than gene based. This is not really a problem, but don’t forget it!

1.4 Hisat2 expressionset

hisat_annot <- mm_annot
rownames(hisat_annot) <- paste0("gene:", rownames(hisat_annot))
mm38_hisat <- create_expt("sample_sheets/all_samples.xlsx",
                          gene_info=hisat_annot)
## Reading the sample metadata.
## Dropped 1 rows from the sample metadata because they were blank.
## The sample definitions comprises: 23 rows(samples) and 24 columns(metadata fields).
## Reading count tables.
## Reading count files with read.table().
## /mnt/sshfs/cbcbsub01/fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/mmusculus_iprgc_2019/preprocessing/iprgc_01/outputs/hisat2_mm38_95/r1_trimmed.count.xz contains 25788 rows.
## /mnt/sshfs/cbcbsub01/fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/mmusculus_iprgc_2019/preprocessing/iprgc_02/outputs/hisat2_mm38_95/r1_trimmed.count.xz contains 25788 rows and merges to 25788 rows.
## /mnt/sshfs/cbcbsub01/fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/mmusculus_iprgc_2019/preprocessing/iprgc_03/outputs/hisat2_mm38_95/r1_trimmed.count.xz contains 25788 rows and merges to 25788 rows.
## /mnt/sshfs/cbcbsub01/fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/mmusculus_iprgc_2019/preprocessing/iprgc_04/outputs/hisat2_mm38_95/r1_trimmed.count.xz contains 25788 rows and merges to 25788 rows.
## /mnt/sshfs/cbcbsub01/fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/mmusculus_iprgc_2019/preprocessing/iprgc_05/outputs/hisat2_mm38_95/r1_trimmed.count.xz contains 25788 rows and merges to 25788 rows.
## /mnt/sshfs/cbcbsub01/fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/mmusculus_iprgc_2019/preprocessing/iprgc_06/outputs/hisat2_mm38_95/r1_trimmed.count.xz contains 25788 rows and merges to 25788 rows.
## /mnt/sshfs/cbcbsub01/fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/mmusculus_iprgc_2019/preprocessing/iprgc_07/outputs/hisat2_mm38_95/r1_trimmed.count.xz contains 25788 rows and merges to 25788 rows.
## /mnt/sshfs/cbcbsub01/fs/cbcb-lab/nelsayed/scratch/atb/rnaseq/mmusculus_iprgc_2019/preprocessing/iprgc_08/outputs/hisat2_mm38_95/r1_trimmed.count.xz contains 25788 rows and merges to 25788 rows.
## preprocessing/202009/01_wt_retina/outputs/hisat2_mm38_100/r1_ca.count_mm38_100_sno_gene_ID.count.xz contains 25765 rows and merges to 25788 rows.
## preprocessing/202009/02_wt_scn/outputs/hisat2_mm38_100/r1_ca.count_mm38_100_sno_gene_ID.count.xz contains 25765 rows and merges to 25788 rows.
## preprocessing/202009/03_wt_dlgn/outputs/hisat2_mm38_100/r1_ca.count_mm38_100_sno_gene_ID.count.xz contains 25765 rows and merges to 25788 rows.
## preprocessing/202009/04_ko_retina/outputs/hisat2_mm38_100/r1_ca.count_mm38_100_sno_gene_ID.count.xz contains 25765 rows and merges to 25788 rows.
## preprocessing/202009/05_ko_scn/outputs/hisat2_mm38_100/r1_ca.count_mm38_100_sno_gene_ID.count.xz contains 25765 rows and merges to 25788 rows.
## preprocessing/202009/06_ko_dlgn/outputs/hisat2_mm38_100/r1_ca.count_mm38_100_sno_gene_ID.count.xz contains 25765 rows and merges to 25788 rows.
## preprocessing/202009/07_het1_retina/outputs/hisat2_mm38_100/r1_ca.count_mm38_100_sno_gene_ID.count.xz contains 25765 rows and merges to 25788 rows.
## preprocessing/202009/08_het2_retina/outputs/hisat2_mm38_100/r1_ca.count_mm38_100_sno_gene_ID.count.xz contains 25765 rows and merges to 25788 rows.
## preprocessing/202009/09_het3_retina/outputs/hisat2_mm38_100/r1_ca.count_mm38_100_sno_gene_ID.count.xz contains 25765 rows and merges to 25788 rows.
## preprocessing/202009/10_het1_scn/outputs/hisat2_mm38_100/r1_ca.count_mm38_100_sno_gene_ID.count.xz contains 25765 rows and merges to 25788 rows.
## preprocessing/202009/11_het2_scn/outputs/hisat2_mm38_100/r1_ca.count_mm38_100_sno_gene_ID.count.xz contains 25765 rows and merges to 25788 rows.
## preprocessing/202009/12_het3_scn/outputs/hisat2_mm38_100/r1_ca.count_mm38_100_sno_gene_ID.count.xz contains 25765 rows and merges to 25788 rows.
## preprocessing/202009/13_het1_dlgn/outputs/hisat2_mm38_100/r1_ca.count_mm38_100_sno_gene_ID.count.xz contains 25765 rows and merges to 25788 rows.
## preprocessing/202009/14_het2_dlgn/outputs/hisat2_mm38_100/r1_ca.count_mm38_100_sno_gene_ID.count.xz contains 25765 rows and merges to 25788 rows.
## preprocessing/202009/15_het3_dlgn/outputs/hisat2_mm38_100/r1_ca.count_mm38_100_sno_gene_ID.count.xz contains 25765 rows and merges to 25788 rows.
## Finished reading count data.
## Matched 25371 annotations and counts.
## Bringing together the count matrix and gene information.
## Some annotations were lost in merging, setting them to 'undefined'.
## Saving the expressionset to 'expt.rda'.
## The final expressionset has 25598 rows and 23 columns.
plot_libsize(mm38_hisat)$plot

mm38_first <- normalize_expt(mm38_hisat, filter=TRUE, convert="cpm", norm="quant", transform="log2")
## This function will replace the expt$expressionset slot with:
## log2(cpm(quant(cbcb(data))))
## It will save copies of each step along the way
##  in expt$normalized with the corresponding libsizes. Keep libsizes in mind
##  when invoking limma.  The appropriate libsize is non-log(cpm(normalized)).
##  This is most likely kept at:
##  'new_expt$normalized$intermediate_counts$normalization$libsizes'
##  A copy of this may also be found at:
##  new_expt$best_libsize
## Not correcting the count-data for batch effects.  If batch is
##  included in EdgerR/limma's model, then this is probably wise; but in extreme
##  batch effects this is a good parameter to play with.
## Step 1: performing count filter with option: cbcb
## Removing 11029 low-count genes (14569 remaining).
## Step 2: normalizing the data with quant.
## Step 3: converting the data with cpm.
## Step 4: transforming the data with log2.
## transform_counts: Found 192 values equal to 0, adding 1 to the matrix.
## Step 5: not doing batch correction.
pp(file="pca_norm.png", image=plot_pca(mm38_first)$plot)
## Writing the image to: pca_norm.png and calling dev.off().

mm38_norm <- normalize_expt(mm38_hisat, filter=TRUE, convert="cpm", batch="svaseq")
## This function will replace the expt$expressionset slot with:
## svaseq(cpm(cbcb(data)))
## It will save copies of each step along the way
##  in expt$normalized with the corresponding libsizes. Keep libsizes in mind
##  when invoking limma.  The appropriate libsize is non-log(cpm(normalized)).
##  This is most likely kept at:
##  'new_expt$normalized$intermediate_counts$normalization$libsizes'
##  A copy of this may also be found at:
##  new_expt$best_libsize
## Leaving the data in its current base format, keep in mind that
##  some metrics are easier to see when the data is log2 transformed, but
##  EdgeR/DESeq do not accept transformed data.
## Leaving the data unnormalized.  This is necessary for DESeq, but
##  EdgeR/limma might benefit from normalization.  Good choices include quantile,
##  size-factor, tmm, etc.
## Step 1: performing count filter with option: cbcb
## Removing 11029 low-count genes (14569 remaining).
## Step 2: not normalizing the data.
## Step 3: converting the data with cpm.
## Step 4: not transforming the data.
## Step 5: doing batch correction with svaseq.
## Using the current state of normalization.
## Passing the data to all_adjusters using the svaseq estimate type.
## batch_counts: Before batch/surrogate estimation, 306878 entries are x>1: 92%.
## batch_counts: Before batch/surrogate estimation, 3404 entries are x==0: 1%.
## batch_counts: Before batch/surrogate estimation, 24805 entries are 0<x<1: 7%.
## The be method chose 2 surrogate variables.
## Attempting svaseq estimation with 2 surrogates.
## There are 2286 (1%) elements which are < 0 after batch correction.
## Setting low elements to zero.
mm38_norm <- normalize_expt(mm38_norm, transform="log2")
## This function will replace the expt$expressionset slot with:
## log2(data)
## It will save copies of each step along the way
##  in expt$normalized with the corresponding libsizes. Keep libsizes in mind
##  when invoking limma.  The appropriate libsize is non-log(cpm(normalized)).
##  This is most likely kept at:
##  'new_expt$normalized$intermediate_counts$normalization$libsizes'
##  A copy of this may also be found at:
##  new_expt$best_libsize
## Filter is false, this should likely be set to something, good
##  choices include cbcb, kofa, pofa (anything but FALSE).  If you want this to
##  stay FALSE, keep in mind that if other normalizations are performed, then the
##  resulting libsizes are likely to be strange (potentially negative!)
## Leaving the data unconverted.  It is often advisable to cpm/rpkm
##  the data to normalize for sampling differences, keep in mind though that rpkm
##  has some annoying biases, and voom() by default does a cpm (though hpgl_voom()
##  will try to detect this).
## Leaving the data unnormalized.  This is necessary for DESeq, but
##  EdgeR/limma might benefit from normalization.  Good choices include quantile,
##  size-factor, tmm, etc.
## Not correcting the count-data for batch effects.  If batch is
##  included in EdgerR/limma's model, then this is probably wise; but in extreme
##  batch effects this is a good parameter to play with.
## Step 1: not doing count filtering.
## Step 2: not normalizing the data.
## Step 3: not converting the data.
## Step 4: transforming the data with log2.
## transform_counts: Found 2286 values equal to 0, adding 1 to the matrix.
## Step 5: not doing batch correction.
pp(file="pca_sva.png", image=plot_pca(mm38_norm)$plot)
## Writing the image to: pca_sva.png and calling dev.off().

new <- subset_expt(mm38_hisat, subset="batch=='b202009'")
## Using a subset expression.
## There were 23, now there are 15 samples.
new_norm <- normalize_expt(new, filter=TRUE, convert="cpm", norm="quant", transform="log2")
## This function will replace the expt$expressionset slot with:
## log2(cpm(quant(cbcb(data))))
## It will save copies of each step along the way
##  in expt$normalized with the corresponding libsizes. Keep libsizes in mind
##  when invoking limma.  The appropriate libsize is non-log(cpm(normalized)).
##  This is most likely kept at:
##  'new_expt$normalized$intermediate_counts$normalization$libsizes'
##  A copy of this may also be found at:
##  new_expt$best_libsize
## Not correcting the count-data for batch effects.  If batch is
##  included in EdgerR/limma's model, then this is probably wise; but in extreme
##  batch effects this is a good parameter to play with.
## Step 1: performing count filter with option: cbcb
## Removing 11363 low-count genes (14235 remaining).
## Step 2: normalizing the data with quant.
## Step 3: converting the data with cpm.
## Step 4: transforming the data with log2.
## transform_counts: Found 551 values equal to 0, adding 1 to the matrix.
## Step 5: not doing batch correction.
plot_pca(new_norm)$plot

mm38_salmon <- sm(create_expt("sample_sheets/all_samples.xlsx", tx_gene_map=tx_gene_map,
                              gene_info=mm_annot, file_column="salmonfile"))

mmtx_annot <- mm_annot
rownames(mmtx_annot) <- mm_annot[["txid"]]
mm38_saltx <- sm(create_expt("sample_sheets/all_samples.xlsx",
                             gene_info=mmtx_annot, file_column="salmonfile"))

1.5 Query expressionsets

In this block I will calculate all the diagnostic plots, but not show them. I will show them next with a little annotation.

I will leave the output for the first of each invocation and silence it for the second.

1.5.1 Initial salmon plots

mm38_plots_sa <- sm(graph_metrics(mm38_salmon))
mm38_norm_sa <- normalize_expt(mm38_salmon, norm="quant", convert="cpm",
                            transform="log2", filter=TRUE)
## This function will replace the expt$expressionset slot with:
## log2(cpm(quant(cbcb(data))))
## It will save copies of each step along the way
##  in expt$normalized with the corresponding libsizes. Keep libsizes in mind
##  when invoking limma.  The appropriate libsize is non-log(cpm(normalized)).
##  This is most likely kept at:
##  'new_expt$normalized$intermediate_counts$normalization$libsizes'
##  A copy of this may also be found at:
##  new_expt$best_libsize
## Not correcting the count-data for batch effects.  If batch is
##  included in EdgerR/limma's model, then this is probably wise; but in extreme
##  batch effects this is a good parameter to play with.
## Step 1: performing count filter with option: cbcb
## Removing 2794 low-count genes (3970 remaining).
## Step 2: normalizing the data with quant.
## Step 3: converting the data with cpm.
## Step 4: transforming the data with log2.
## transform_counts: Found 1105 values equal to 0, adding 1 to the matrix.
## Step 5: not doing batch correction.
mm38n_plots_sa <- sm(graph_metrics(mm38_norm_sa))
mm38_plots_sa$legend

mm38_plots_sa$libsize

mm38_plots_sa$nonzero

mm38n_plots_sa$density

mm38n_plots_sa$pc_plot

1.5.2 Initial hisat2 plots

mm38_plots_hi <- sm(graph_metrics(mm38_hisat))
mm38_norm_hi <- normalize_expt(mm38_hisat, norm="quant", convert="cpm",
                               transform="log2", filter=TRUE)
## This function will replace the expt$expressionset slot with:
## log2(cpm(quant(cbcb(data))))
## It will save copies of each step along the way
##  in expt$normalized with the corresponding libsizes. Keep libsizes in mind
##  when invoking limma.  The appropriate libsize is non-log(cpm(normalized)).
##  This is most likely kept at:
##  'new_expt$normalized$intermediate_counts$normalization$libsizes'
##  A copy of this may also be found at:
##  new_expt$best_libsize
## Not correcting the count-data for batch effects.  If batch is
##  included in EdgerR/limma's model, then this is probably wise; but in extreme
##  batch effects this is a good parameter to play with.
## Step 1: performing count filter with option: cbcb
## Removing 11029 low-count genes (14569 remaining).
## Step 2: normalizing the data with quant.
## Step 3: converting the data with cpm.
## Step 4: transforming the data with log2.
## transform_counts: Found 192 values equal to 0, adding 1 to the matrix.
## Step 5: not doing batch correction.
mm38n_plots_hi <- sm(graph_metrics(mm38_norm_hi))
mm38_plots_hi$libsize

mm38_plots_hi$nonzero

mm38n_plots_hi$density

mm38n_plots_hi$pc_plot

1.6 Do a simple DE

The only interesting DE I see in this is to compare the retinas to the dlgns. I can treat them as replicates and compare.

These differential expression analyses are EXPLICITLY NOT what you care about. However, they are useful for two purposes:

  1. Seeing that the three tissue types are indeed different.
  2. Setting up the table of results with appropriate rows/columns of (rows)genes and (columns) annotations. We will therefore add to these tables the results of the expression analyses that you actually do care about.

When we receive full replicate sets, this cheater method of encapsulating the data will not longer be required.

1.6.1 With salmon

mm_sa <- set_expt_conditions(mm38_salmon, fact="celltype")
mm_norm_sa <- sm(normalize_expt(mm_sa, convert="rpkm", transform="log2", column="cds_length"))
plot_pca(mm_norm_sa)$plot
mm_de_sa <- all_pairwise(mm_sa, model_batch=FALSE)
## Plotting a PCA before surrogate/batch inclusion.
## Not putting labels on the PC plot.
## Assuming no batch in model for testing pca.
## Not putting labels on the PC plot.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.

1.6.2 With hisat2

## mm_hi <- set_expt_conditions(mm38_hisat, fact="celltype")
mm_hi <- mm38_hisat
mm_norm_hi <- sm(normalize_expt(mm_hi, convert="rpkm", transform="log2", filter=TRUE,
                                column="cds_length", batch="svaseq"))
## Error in density.default(x, adjust = adj) : 'x' contains missing values
## Error in density.default(x, adjust = adj) : 'x' contains missing values
plot_pca(mm_norm_hi)$plot
keepers <- list(
  "wt_dlgnret" = c("wt_dlgn", "wt_retina"),
  "wt_scnret" = c("wt_scn", "wt_retina"),
  "wt_dlgnscn" = c("wt_dlgn", "wt_scn"),
  "normret" = c("het_retina", "wt_retina"),
  "koret" = c("ko_retina", "wt_retina"),
  "normscn" = c("het_scn", "wt_scn"),
  "koscn" = c("ko_scn", "wt_scn"),
  "normdlgn" = c("het_dlgn", "wt_dlgn"),
  "kodlgn" = c("ko_dlgn", "wt_dlgn"),
  "normdlgn_vs_normret" = c("normdlgn", "normret"),
  "normscn_vs_normret" = c("normscn", "normret"),
  "kodlgn_vs_koret" = c("kodlgn", "koret"),
  "koscn_vs_koret" = c("koscn", "koret"),
  "koscn_vs_kodlgn" = c("koscn", "kodlgn"),
  "koret_vs_normret" = c("ko_retina", "het_retina"),
  "koscn_vs_normscn" = c("ko_scn", "het_scn"),
  "kodlgn_vs_normdlgn" = c("ko_dlgn", "het_dlgn"),
  "normko_retdlgn" = c("normdlgn_vs_normret", "kodlgn_vs_koret"),
  "normko_retscn" = c("normscn_vs_normret", "koscn_vs_koret"))
extras <- "normdlgn_vs_normret = (het_dlgn-wt_dlgn)-(het_retina-wt_retina),
           normscn_vs_normret = (het_scn-wt_scn)-(het_retina-wt_retina),
           kodlgn_vs_koret = (ko_dlgn-wt_dlgn)-(ko_retina-wt_retina),
           koscn_vs_koret = (ko_scn-wt_scn)-(ko_retina-wt_retina),
           koscn_vs_kodlgn = (ko_scn-wt_scn)-(ko_dlgn-wt_dlgn),
           normko_retdlgn = ((het_dlgn-wt_dlgn)-(het_retina-wt_retina)) - ((ko_dlgn-wt_dlgn)-(ko_retina-wt_retina)),
           normko_retscn = ((het_scn-wt_scn)-(het_retina-wt_retina)) - ((ko_scn-wt_scn)-(ko_retina-wt_retina))"
mm_filt <- normalize_expt(mm_hi, filter=TRUE)
## This function will replace the expt$expressionset slot with:
## cbcb(data)
## It will save copies of each step along the way
##  in expt$normalized with the corresponding libsizes. Keep libsizes in mind
##  when invoking limma.  The appropriate libsize is non-log(cpm(normalized)).
##  This is most likely kept at:
##  'new_expt$normalized$intermediate_counts$normalization$libsizes'
##  A copy of this may also be found at:
##  new_expt$best_libsize
## Leaving the data in its current base format, keep in mind that
##  some metrics are easier to see when the data is log2 transformed, but
##  EdgeR/DESeq do not accept transformed data.
## Leaving the data unconverted.  It is often advisable to cpm/rpkm
##  the data to normalize for sampling differences, keep in mind though that rpkm
##  has some annoying biases, and voom() by default does a cpm (though hpgl_voom()
##  will try to detect this).
## Leaving the data unnormalized.  This is necessary for DESeq, but
##  EdgeR/limma might benefit from normalization.  Good choices include quantile,
##  size-factor, tmm, etc.
## Not correcting the count-data for batch effects.  If batch is
##  included in EdgerR/limma's model, then this is probably wise; but in extreme
##  batch effects this is a good parameter to play with.
## Step 1: performing count filter with option: cbcb
## Removing 11029 low-count genes (14569 remaining).
## Step 2: not normalizing the data.
## Step 3: not converting the data.
## Step 4: not transforming the data.
## Step 5: not doing batch correction.
mm_test <- limma_pairwise(mm_filt, model_batch="svaseq", extra_contrasts=extras)
## Starting limma pairwise comparison.
## libsize was not specified, this parameter has profound effects on limma's result.
## Using the libsize from expt$best_libsize.
## Limma step 1/6: choosing model.
## Extracting surrogate estimates from svaseq and adding them to the model.
## batch_counts: Before batch/surrogate estimation, 329826 entries are x>1: 98%.
## batch_counts: Before batch/surrogate estimation, 3404 entries are x==0: 1%.
## The be method chose 2 surrogate variables.
## Attempting svaseq estimation with 2 surrogates.
## Choosing the non-intercept containing model.
## Limma step 2/6: running limma::voom(), switch with the argument 'which_voom'.
## Using normalize.method=quantile for voom.
## Limma step 3/6: running lmFit with method: ls.
## Limma step 4/6: making and fitting contrasts with no intercept. (~ 0 + factors)
## Limma step 5/6: Running eBayes with robust=FALSE and trend=FALSE.
## Limma step 6/6: Writing limma outputs.
## Limma step 6/6: 1/43: Creating table: het_retina_vs_het_dlgn.  Adjust=BH
## Limma step 6/6: 2/43: Creating table: het_scn_vs_het_dlgn.  Adjust=BH
## Limma step 6/6: 3/43: Creating table: ko_dlgn_vs_het_dlgn.  Adjust=BH
## Limma step 6/6: 4/43: Creating table: ko_retina_vs_het_dlgn.  Adjust=BH
## Limma step 6/6: 5/43: Creating table: ko_scn_vs_het_dlgn.  Adjust=BH
## Limma step 6/6: 6/43: Creating table: wt_dlgn_vs_het_dlgn.  Adjust=BH
## Limma step 6/6: 7/43: Creating table: wt_retina_vs_het_dlgn.  Adjust=BH
## Limma step 6/6: 8/43: Creating table: wt_scn_vs_het_dlgn.  Adjust=BH
## Limma step 6/6: 9/43: Creating table: het_scn_vs_het_retina.  Adjust=BH
## Limma step 6/6: 10/43: Creating table: ko_dlgn_vs_het_retina.  Adjust=BH
## Limma step 6/6: 11/43: Creating table: ko_retina_vs_het_retina.  Adjust=BH
## Limma step 6/6: 12/43: Creating table: ko_scn_vs_het_retina.  Adjust=BH
## Limma step 6/6: 13/43: Creating table: wt_dlgn_vs_het_retina.  Adjust=BH
## Limma step 6/6: 14/43: Creating table: wt_retina_vs_het_retina.  Adjust=BH
## Limma step 6/6: 15/43: Creating table: wt_scn_vs_het_retina.  Adjust=BH
## Limma step 6/6: 16/43: Creating table: ko_dlgn_vs_het_scn.  Adjust=BH
## Limma step 6/6: 17/43: Creating table: ko_retina_vs_het_scn.  Adjust=BH
## Limma step 6/6: 18/43: Creating table: ko_scn_vs_het_scn.  Adjust=BH
## Limma step 6/6: 19/43: Creating table: wt_dlgn_vs_het_scn.  Adjust=BH
## Limma step 6/6: 20/43: Creating table: wt_retina_vs_het_scn.  Adjust=BH
## Limma step 6/6: 21/43: Creating table: wt_scn_vs_het_scn.  Adjust=BH
## Limma step 6/6: 22/43: Creating table: ko_retina_vs_ko_dlgn.  Adjust=BH
## Limma step 6/6: 23/43: Creating table: ko_scn_vs_ko_dlgn.  Adjust=BH
## Limma step 6/6: 24/43: Creating table: wt_dlgn_vs_ko_dlgn.  Adjust=BH
## Limma step 6/6: 25/43: Creating table: wt_retina_vs_ko_dlgn.  Adjust=BH
## Limma step 6/6: 26/43: Creating table: wt_scn_vs_ko_dlgn.  Adjust=BH
## Limma step 6/6: 27/43: Creating table: ko_scn_vs_ko_retina.  Adjust=BH
## Limma step 6/6: 28/43: Creating table: wt_dlgn_vs_ko_retina.  Adjust=BH
## Limma step 6/6: 29/43: Creating table: wt_retina_vs_ko_retina.  Adjust=BH
## Limma step 6/6: 30/43: Creating table: wt_scn_vs_ko_retina.  Adjust=BH
## Limma step 6/6: 31/43: Creating table: wt_dlgn_vs_ko_scn.  Adjust=BH
## Limma step 6/6: 32/43: Creating table: wt_retina_vs_ko_scn.  Adjust=BH
## Limma step 6/6: 33/43: Creating table: wt_scn_vs_ko_scn.  Adjust=BH
## Limma step 6/6: 34/43: Creating table: wt_retina_vs_wt_dlgn.  Adjust=BH
## Limma step 6/6: 35/43: Creating table: wt_scn_vs_wt_dlgn.  Adjust=BH
## Limma step 6/6: 36/43: Creating table: wt_scn_vs_wt_retina.  Adjust=BH
## Limma step 6/6: 37/43: Creating table: normdlgn_vs_normret.  Adjust=BH
## Limma step 6/6: 38/43: Creating table: normscn_vs_normret.  Adjust=BH
## Limma step 6/6: 39/43: Creating table: kodlgn_vs_koret.  Adjust=BH
## Limma step 6/6: 40/43: Creating table: koscn_vs_koret.  Adjust=BH
## Limma step 6/6: 41/43: Creating table: koscn_vs_kodlgn.  Adjust=BH
## Limma step 6/6: 42/43: Creating table: normko_retdlgn.  Adjust=BH
## Limma step 6/6: 43/43: Creating table: normko_retscn.  Adjust=BH
## Limma step 6/6: 1/9: Creating table: het_dlgn.  Adjust=BH
## Limma step 6/6: 2/9: Creating table: het_retina.  Adjust=BH
## Limma step 6/6: 3/9: Creating table: het_scn.  Adjust=BH
## Limma step 6/6: 4/9: Creating table: ko_dlgn.  Adjust=BH
## Limma step 6/6: 5/9: Creating table: ko_retina.  Adjust=BH
## Limma step 6/6: 6/9: Creating table: ko_scn.  Adjust=BH
## Limma step 6/6: 7/9: Creating table: wt_dlgn.  Adjust=BH
## Limma step 6/6: 8/9: Creating table: wt_retina.  Adjust=BH
## Limma step 6/6: 9/9: Creating table: wt_scn.  Adjust=BH
mm_test <- deseq_pairwise(mm_filt, model_batch="svaseq", extra_contrasts=extras)
## Hey you, use deseq2 pairwise.
## Starting DESeq2 pairwise comparisons.
## The data should be suitable for EdgeR/DESeq/EBSeq. If they freak out, check the state of the count table and ensure that it is in integer counts.
## Extracting surrogate estimates from svaseq and adding them to the model.
## batch_counts: Before batch/surrogate estimation, 329826 entries are x>1: 98%.
## batch_counts: Before batch/surrogate estimation, 3404 entries are x==0: 1%.
## The be method chose 2 surrogate variables.
## Attempting svaseq estimation with 2 surrogates.
## Choosing the non-intercept containing model.
## DESeq2 step 1/5: Including a matrix of batch estimates in the deseq model.
## converting counts to integer mode
## DESeq2 step 2/5: Estimate size factors.
## DESeq2 step 3/5: Estimate dispersions.
## gene-wise dispersion estimates
## mean-dispersion relationship
## final dispersion estimates
## Using a parametric fitting seems to have worked.
## DESeq2 step 4/5: nbinomWaldTest.
## The contrast normdlgn is not in the results.
## If this is not an extra contrast, then this is an error.
## The contrast normscn is not in the results.
## If this is not an extra contrast, then this is an error.
## The contrast kodlgn is not in the results.
## If this is not an extra contrast, then this is an error.
## The contrast koscn is not in the results.
## If this is not an extra contrast, then this is an error.
## The contrast koscn is not in the results.
## If this is not an extra contrast, then this is an error.
## The contrast normko_retdlgn is not in the results.
## If this is not an extra contrast, then this is an error.
## The contrast normko_retscn is not in the results.
## If this is not an extra contrast, then this is an error.
mm_test <- edger_pairwise(mm_filt, model_batch="svaseq", extra_contrasts=extras)
## Starting edgeR pairwise comparisons.
## The data should be suitable for EdgeR/DESeq/EBSeq. If they freak out, check the state of the count table and ensure that it is in integer counts.
## Extracting surrogate estimates from svaseq and adding them to the model.
## batch_counts: Before batch/surrogate estimation, 329826 entries are x>1: 98%.
## batch_counts: Before batch/surrogate estimation, 3404 entries are x==0: 1%.
## The be method chose 2 surrogate variables.
## Attempting svaseq estimation with 2 surrogates.
## Choosing the non-intercept containing model.
## EdgeR step 1/9: Importing and normalizing data.
## EdgeR step 2/9: Estimating the common dispersion.
## EdgeR step 3/9: Estimating dispersion across genes.
## EdgeR step 4/9: Estimating GLM Common dispersion.
## EdgeR step 5/9: Estimating GLM Trended dispersion.
## EdgeR step 6/9: Estimating GLM Tagged dispersion.
## EdgeR step 7/9: Running glmFit, switch to glmQLFit by changing the argument 'edger_test'.
## EdgeR step 8/9: Making pairwise contrasts.
mm_test <- ebseq_pairwise(mm_filt, model_batch="svaseq", extra_contrasts=extras)
## The data should be suitable for EdgeR/DESeq/EBSeq. If they freak out, check the state of the count table and ensure that it is in integer counts.
## Starting EBSeq pairwise subset.
## Choosing the non-intercept containing model.
## Starting EBTest of het_dlgn vs. het_retina.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of het_dlgn vs. het_scn.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of het_dlgn vs. ko_dlgn.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of het_dlgn vs. ko_retina.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of het_dlgn vs. ko_scn.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of het_dlgn vs. wt_dlgn.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of het_dlgn vs. wt_retina.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of het_dlgn vs. wt_scn.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of het_retina vs. het_scn.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of het_retina vs. ko_dlgn.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of het_retina vs. ko_retina.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of het_retina vs. ko_scn.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of het_retina vs. wt_dlgn.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of het_retina vs. wt_retina.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of het_retina vs. wt_scn.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of het_scn vs. ko_dlgn.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of het_scn vs. ko_retina.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of het_scn vs. ko_scn.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of het_scn vs. wt_dlgn.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of het_scn vs. wt_retina.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of het_scn vs. wt_scn.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of ko_dlgn vs. ko_retina.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of ko_dlgn vs. ko_scn.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of ko_dlgn vs. wt_dlgn.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of ko_dlgn vs. wt_retina.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of ko_dlgn vs. wt_scn.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of ko_retina vs. ko_scn.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of ko_retina vs. wt_dlgn.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of ko_retina vs. wt_retina.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of ko_retina vs. wt_scn.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of ko_scn vs. wt_dlgn.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of ko_scn vs. wt_retina.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of ko_scn vs. wt_scn.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of wt_dlgn vs. wt_retina.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of wt_dlgn vs. wt_scn.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
## Starting EBTest of wt_retina vs. wt_scn.
## Copying ppee values as ajusted p-values until I figure out how to deal with them.
mm_de_hi <- sm(all_pairwise(mm_filt, model_batch="svaseq", parallel=FALSE, extra_contrasts=extras))
## Error in dimnames(x) <- dn: length of 'dimnames' [2] not equal to array extent
mm_de_tables <- combine_de_tables(mm_de_hi, excel="excel/testing_202010.xlsx")
## Error in combine_de_tables(mm_de_hi, excel = "excel/testing_202010.xlsx"): object 'mm_de_hi' not found

1.7 Set up for initial analysis

Until we get full replicates, I will do simple subtractions.

1.7.1 Term definition

In an attempt to keep some clarity in the terms used, I want to define them now. There are three contexts in which we will consider the data:

  1. The individual sample type. When considering individual samples, I will use three terms in this and only this context: wild-type (wt), het, and mut.

  2. The individual translatome. These are defines as something / baseline. I will exclusively call the wt samples ‘baseline’ when speaking in this context. I will exclusively state ‘normal’ when referring to het / wt samples, and I will state ‘ko’ when referring to mut / wt samples in the translatome context.

  3. Translatome vs. translatome. Whenever comparing translatomes, I will use the names as in #2 and always put the numerator first when writing the name of a comparison.

The most complex example of the above nomenclature is:

“normko_retdlgn is defined as normret_vs_normdlgn - koret_vs_kodlgn”

This states we are examining at the translatome context: (norm(retina translatome) - norm(dlgn translatome)) - (ko(retina translatome) - ko(dlgn translatome))

Which in turn is synonymous to the following at the sample context: ((rethet - retwt) - (dlgnhet - dlgnwt)) - ((retko - retwt) - (dlgnko - dlgnwt))

Now let us associate the various variable names with the appropriate samples:

dlgnwt <- "iprgc_01"
retwt <- "iprgc_02"
scnwt <- "iprgc_03"

dlgnhet <- "iprgc_04"
rethet <- "iprgc_05"
scnhet <- NULL  ## Does not yet exist.

dlgnmut <- "iprgc_06"
retmut <- "iprgc_07"
scnmut <- "iprgc_08"

Give these variable names, now lets associate columns of the expression data with them. These are at the sample context, so the appropriate names are: ‘wt’, ‘het’, and ‘mut’. In each case I will prefix the genotype with the tissue type: ‘ret’, ‘dlgn’, and ‘scn’. Thus ‘retwt’ refers to the sample used to calculate the translatome retina baseline; in contrast ‘dlgnmut’ is the sample which provides the dlgn knockout.

## Sample context
mm38_norm <- mm_norm_sa
dlgnwt <- exprs(mm38_norm)[, dlgnwt]
retwt <- exprs(mm38_norm)[, retwt]
scnwt <- exprs(mm38_norm)[, scnwt]
dlgnhet <- exprs(mm38_norm)[, dlgnhet]
rethet <- exprs(mm38_norm)[, rethet]
dlgnmut <- exprs(mm38_norm)[, dlgnmut]
retmut <- exprs(mm38_norm)[, retmut]
scnmut <- exprs(mm38_norm)[, scnmut]

Each of the above 8 variables provides 1 column of information. We have 3 baseline comparisons available to us. In each of these we compare one wt sample to another.

## Baseline comparisons
wt_dlgnret <- dlgnwt - retwt
wt_scnret <- scnwt - retwt
wt_dlgnscn <- dlgnwt - scnwt

Simultaneously, we have 5 available translatomes. This are provided by comparing each het or mut to the associated wt. These will therefore receive names: ‘norm’ and ‘ko’ instead of ‘het’ and ‘mut’.

## Translatome context
normret <- rethet - retwt
koret <- retmut - retwt
koscn <- scnmut - scnwt
normdlgn <- dlgnhet - dlgnwt
kodlgn <- dlgnmut - dlgnwt

Given these translatomes, there are a few contrasts of likely interest. These are performed by comparing the relevant translatomes.

Will will split these into 4 separate categories: het vs het, ko vs ko, ko vs het, and ratio vs ratio.

Finally, note that we are being explicitly redundant in these definitions. I am making variable names for both the a/b ratio and the b/a ratio. Thus we have some redundantly redundant (haha) flexibility when deciding on what we want to plot.

## norm vs norm
normdlgn_vs_normret <- normdlgn - normret
normret_vs_normdlgn <- normret - normdlgn
## ko vs ko
koret_vs_kodlgn <- koret - kodlgn
kodlgn_vs_koret <- kodlgn - koret

koret_vs_koscn <- koret - koscn
koscn_vs_koret <- koscn - koret

kodlgn_vs_koscn <- kodlgn - koscn
koscn_vs_kodlgn <- koscn - kodlgn

On the other hand, I am assuming we always want the normals as denominators and kos as numerators.

## ko vs norm
koret_vs_normret <- koret - normret

kodlgn_vs_normdlgn <- kodlgn - normdlgn

Finally, here is the ratio of ratios example I printed above:

I named it ‘normko_retdlgn’ in an attempt to make clear that it is actually: (normret/normdlgn)/(koret/kodlgn)

or stated differently: “norm divided by ko for ret divided by dlgn.”

## ratio of ratios
normko_retdlgn <- normret_vs_normdlgn - koret_vs_kodlgn

1.8 Define a matrix of these values.

My matrix of data will now contain 1 column for each of the above 27 samples/comparisons.

pair_mtrx <- cbind(
  ## Individual samples
  dlgnwt, retwt, scnwt, dlgnhet, rethet, dlgnmut, retmut, scnmut,
  ## Baseline comparisons
  wt_dlgnret, wt_scnret, wt_dlgnscn,
  ## Baseline subtractions
  normdlgn, normret, kodlgn, koret, koscn,
  ## het_vs_het, of which there is only 1 because we do not have hetscn
  normdlgn_vs_normret, normret_vs_normdlgn,
  ## ko_vs_ko, of which we have 3
  koret_vs_kodlgn, kodlgn_vs_koret,
  koret_vs_koscn, koscn_vs_koret,
  kodlgn_vs_koscn, koscn_vs_kodlgn,
  ## ko_vs_het, 3 including one getting around missing hetscn
  koret_vs_normret, kodlgn_vs_normdlgn,
  ## ratio of ratios
  normko_retdlgn)

  ## Baseline subtractions
  normdlgn, normret, kodlgn, koret, koscn,
  ## het_vs_het, of which there is only 1 because we do not have hetscn
  normdlgn_vs_normret, normret_vs_normdlgn,
  ## ko_vs_ko, of which we have 3
  koret_vs_kodlgn, kodlgn_vs_koret,
  koret_vs_koscn, koscn_vs_koret,
  kodlgn_vs_koscn, koscn_vs_kodlgn,
  ## ko_vs_het, 3 including one getting around missing hetscn
  koret_vs_normret, kodlgn_vs_normdlgn,
  ## ratio of ratios
  normko_retdlgn)
  )
## Error: <text>:20:11: unexpected ','
## 19:   ## Baseline subtractions
## 20:   normdlgn,
##               ^

1.9 Cutoffs

I am not sure if we will use these indexes, but I am writing these out as subsets of genes to look at. These indexes are stating that, given a cutoff (0), we want to look at only the genes which have higher x / baseline values than the cutoff.

## Queries about gene subsets.
## These are all in the context of translatomes.
cutoff <- 0
ret_kept_idx <- normret > cutoff & koret > cutoff
scn_kept_idx <- koscn > cutoff
dlgn_kept_idx <- normdlgn > cutoff & kodlgn > cutoff
ret_dlgn_kept_idx <- ret_kept_idx & dlgn_kept_idx
ret_scn_kept_idx <- ret_kept_idx & scn_kept_idx
dlgn_scn_kept_idx <- dlgn_kept_idx & scn_kept_idx

##normdlgn_vs_normret[!ret_dlgn_kept_idx] <- NA
##normret_vs_normdlgn[!ret_dlgn_kept_idx] <- NA
##koret_vs_kodlgn[!ret_dlgn_kept_idx] <- NA
##kodlgn_vs_koret[!ret_dlgn_kept_idx] <- NA
##koret_vs_koscn[!ret_scn_kept_idx] <- NA
##koscn_vs_koret[!ret_scn_kept_idx] <- NA
##kodlgn_vs_koscn[!dlgn_scn_kept_idx] <- NA
##koscn_vs_kodlgn[!dlgn_scn_kept_idx] <- NA
##koret_vs_normret[!ret_kept_idx] <- NA
##kodlgn_vs_normdlgn[!dlgn_kept_idx] <- NA
##normko_retdlgn <- normko_retdlgn[!ret_dlgn_kept_idx] <- NA

1.10 Add the matrix to the differential expression

I will use my function combine_de_tables() to add this information to my existing annotation data along with the results from the statistically valid comparison of the three tissue types.

mm_tables <- sm(combine_de_tables(
  mm_de_sa, extra_annot=pair_mtrx,
  excel=glue::glue("excel/{rundate}mm_salmon_tables-v{ver}.xlsx")))
## Error in combine_de_tables(mm_de_sa, extra_annot = pair_mtrx, excel = glue::glue("excel/{rundate}mm_salmon_tables-v{ver}.xlsx")): object 'pair_mtrx' not found

2 Plots of interesting comparisons

2.1 Retina, het vs. wt.

## Put retina baseline on y axis as black, retina het on x axis as black.
## Then recolor a subset of these as red, the reds are when normret > 0
library(ggplot2)

plotted <- as.data.frame(pair_mtrx[, c("rethet", "retwt")])
## Error in as.data.frame(pair_mtrx[, c("rethet", "retwt")]): object 'pair_mtrx' not found
red_idx <- normret > 0
plotted[, "color"] <- ifelse(red_idx, "red", "black")
## Error in plotted[, "color"] <- ifelse(red_idx, "red", "black"): object 'plotted' not found
plotted[["label"]] <- rownames(plotted)
## Error in rownames(plotted): object 'plotted' not found
ret_hetwt <- ggplot(
  plotted,
  aes_string(x="rethet", y="retwt", label="label", color="color")) +
  geom_point(alpha=0.5) +
  scale_color_manual(values=c("black", "red"))
## Error in ggplot(plotted, aes_string(x = "rethet", y = "retwt", label = "label", : object 'plotted' not found
ret_hetwt
## Error in eval(expr, envir, enclos): object 'ret_hetwt' not found
ret_hetwt_clicky <- ggplotly_url(
  ret_hetwt, "ret_hetwt.html", title="Retina expression, het vs. wt.",
  url_data="http://useast.ensembl.org/Mus_musculus/Gene/Summary?g={ids}")
## Error in ggplotly_url(ret_hetwt, "ret_hetwt.html", title = "Retina expression, het vs. wt.", : object 'ret_hetwt' not found

2.2 Retina, mut vs wt.

plotted <- as.data.frame(pair_mtrx[, c("retmut", "retwt")])
## Error in as.data.frame(pair_mtrx[, c("retmut", "retwt")]): object 'pair_mtrx' not found
plotted[["label"]] <- rownames(plotted)
## Error in rownames(plotted): object 'plotted' not found
plotted[["color"]] <- "black"
## Error in plotted[["color"]] <- "black": object 'plotted' not found
ret_mutwt <- ggplot(
  plotted,
  aes_string(x="retmut", y="retwt", label="label", color="color")) +
  geom_point(alpha=0.5) +
  scale_color_manual(values=c("black", "red"))
## Error in ggplot(plotted, aes_string(x = "retmut", y = "retwt", label = "label", : object 'plotted' not found
ret_mutwt
## Error in eval(expr, envir, enclos): object 'ret_mutwt' not found
ret_mutwt_clicky <- ggplotly_url(
  ret_mutwt, "ret_mutwt.html", title="Retina expression, mutant vs. wt.",
  url_data="http://useast.ensembl.org/Mus_musculus/Gene/Summary?g={ids}")
## Error in ggplotly_url(ret_mutwt, "ret_mutwt.html", title = "Retina expression, mutant vs. wt.", : object 'ret_mutwt' not found

2.3 dlgn, het vs. wt.

plotted <- as.data.frame(pair_mtrx[, c("dlgnhet", "dlgnwt")])
## Error in as.data.frame(pair_mtrx[, c("dlgnhet", "dlgnwt")]): object 'pair_mtrx' not found
plotted[["label"]] <- rownames(plotted)
## Error in rownames(plotted): object 'plotted' not found
plotted[["color"]] <- "black"
## Error in plotted[["color"]] <- "black": object 'plotted' not found
dlgn_hetwt <- ggplot(
  plotted,
  aes_string(x="dlgnhet", y="dlgnwt", label="label", color="color")) +
  geom_point(alpha=0.5) +
  scale_color_manual(values=c("black", "red"))
## Error in ggplot(plotted, aes_string(x = "dlgnhet", y = "dlgnwt", label = "label", : object 'plotted' not found
dlgn_hetwt
## Error in eval(expr, envir, enclos): object 'dlgn_hetwt' not found
dlgn_hetwt_clicky <- ggplotly_url(
  dlgn_hetwt, "dlgn_hetwt.html", title="dlgn expression, het vs. wt.",
  url_data="http://useast.ensembl.org/Mus_musculus/Gene/Summary?g={ids}")
## Error in ggplotly_url(dlgn_hetwt, "dlgn_hetwt.html", title = "dlgn expression, het vs. wt.", : object 'dlgn_hetwt' not found

2.4 dlgn, mut vs. wt.

plotted <- as.data.frame(pair_mtrx[, c("dlgnmut", "dlgnwt")])
## Error in as.data.frame(pair_mtrx[, c("dlgnmut", "dlgnwt")]): object 'pair_mtrx' not found
plotted[["label"]] <- rownames(plotted)
## Error in rownames(plotted): object 'plotted' not found
plotted[["color"]] <- "black"
## Error in plotted[["color"]] <- "black": object 'plotted' not found
dlgn_mutwt <- ggplot(
  plotted,
  aes_string(x="dlgnmut", y="dlgnwt", label="label", color="color")) +
  geom_point(alpha=0.5) +
  scale_color_manual(values=c("black", "red"))
## Error in ggplot(plotted, aes_string(x = "dlgnmut", y = "dlgnwt", label = "label", : object 'plotted' not found
dlgn_mutwt
## Error in eval(expr, envir, enclos): object 'dlgn_mutwt' not found
dlgn_mutwt_clicky <- ggplotly_url(
  dlgn_mutwt, "dlgn_mutwt.html", title="dlgn expression, mut vs. wt.",
  url_data="http://useast.ensembl.org/Mus_musculus/Gene/Summary?g={ids}")
## Error in ggplotly_url(dlgn_mutwt, "dlgn_mutwt.html", title = "dlgn expression, mut vs. wt.", : object 'dlgn_mutwt' not found

2.5 scn, mut vs. wt.

plotted <- as.data.frame(pair_mtrx[, c("scnmut", "scnwt")])
## Error in as.data.frame(pair_mtrx[, c("scnmut", "scnwt")]): object 'pair_mtrx' not found
plotted[["label"]] <- rownames(plotted)
## Error in rownames(plotted): object 'plotted' not found
plotted[["color"]] <- "black"
## Error in plotted[["color"]] <- "black": object 'plotted' not found
scn_mutwt <- ggplot(
  plotted,
  aes_string(x="scnmut", y="scnwt", label="label", color="color")) +
  geom_point(alpha=0.5) +
  scale_color_manual(values=c("black", "red"))
## Error in ggplot(plotted, aes_string(x = "scnmut", y = "scnwt", label = "label", : object 'plotted' not found
scn_mutwt
## Error in eval(expr, envir, enclos): object 'scn_mutwt' not found
scn_mutwt_clicky <- ggplotly_url(
  scn_mutwt, "scn_mutwt.html", title="scn expression, mut vs. wt.",
  url_data="http://useast.ensembl.org/Mus_musculus/Gene/Summary?g={ids}")
## Error in ggplotly_url(scn_mutwt, "scn_mutwt.html", title = "scn expression, mut vs. wt.", : object 'scn_mutwt' not found

2.6 Axon translatome specific

##  x-axis: normdlgn_vs_normret or normret_vs_normdlgn,
##              ^^^^
##  y-axis: dlgnwt-retwt (baseline dlgn - baseline retina)
plotted <- as.data.frame(pair_mtrx[, c("normdlgn_vs_normret", "wt_dlgnret")])
## Error in as.data.frame(pair_mtrx[, c("normdlgn_vs_normret", "wt_dlgnret")]): object 'pair_mtrx' not found
red_idx <- normret > 0
## Note that this order is opposite of above.
plotted[, "color"] <- ifelse(red_idx, "black", "red")
## Error in plotted[, "color"] <- ifelse(red_idx, "black", "red"): object 'plotted' not found
plotted[["label"]] <- rownames(plotted)
## Error in rownames(plotted): object 'plotted' not found
axon_trans_ret_target <- ggplot(
  plotted,
  aes_string(x="normdlgn_vs_normret", y="wt_dlgnret", label="label", color="color")) +
  geom_point(alpha=0.5) +
  scale_color_manual(values=c("black", "red"))
## Error in ggplot(plotted, aes_string(x = "normdlgn_vs_normret", y = "wt_dlgnret", : object 'plotted' not found
axon_trans_ret_target
## Error in eval(expr, envir, enclos): object 'axon_trans_ret_target' not found
axon_trans_ret_target_clicky <- ggplotly_url(
  axon_trans_ret_target, "axon_trans_ret_target.html", title="Axon translatome, retina target.",
  url_data="http://useast.ensembl.org/Mus_musculus/Gene/Summary?g={ids}")
## Error in ggplotly_url(axon_trans_ret_target, "axon_trans_ret_target.html", : object 'axon_trans_ret_target' not found

2.7 DLGN translatome wrt. Retina translatome

plotted <- as.data.frame(pair_mtrx[, c("normret", "normdlgn")])
## Error in as.data.frame(pair_mtrx[, c("normret", "normdlgn")]): object 'pair_mtrx' not found
plotted[["label"]] <- rownames(plotted)
## Error in rownames(plotted): object 'plotted' not found
plotted[["color"]] <- "black"
## Error in plotted[["color"]] <- "black": object 'plotted' not found
normret_normdlgn <- ggplot(
  plotted,
  aes_string(x="normret", y="normdlgn", label="label", color="color")) +
  geom_point(alpha=0.5) +
  scale_color_manual(values=c("black", "red"))
## Error in ggplot(plotted, aes_string(x = "normret", y = "normdlgn", label = "label", : object 'plotted' not found
normret_normdlgn
## Error in eval(expr, envir, enclos): object 'normret_normdlgn' not found
normret_normdlgn_clicky <- ggplotly_url(
  normret_normdlgn, "normret_normdlgn.html", title="Normal retina translatome vs normal dlgn translatome.",
  url_data="http://useast.ensembl.org/Mus_musculus/Gene/Summary?g={ids}")
## Error in ggplotly_url(normret_normdlgn, "normret_normdlgn.html", title = "Normal retina translatome vs normal dlgn translatome.", : object 'normret_normdlgn' not found

2.8 koret kodlgn

plotted <- as.data.frame(pair_mtrx[, c("koret", "kodlgn")])
plotted[["label"]] <- rownames(plotted)
plotted[["color"]] <- "black"
koret_kodlgn <- ggplot(
  plotted,
  aes_string(x="koret", y="kodlgn", label="label", color="color")) +
  geom_point(alpha=0.5) +
  scale_color_manual(values=c("black", "red"))
koret_kodlgn
koret_kodlgn_clicky <- ggplotly_url(
  koret_kodlgn, "koret_kodlgn.html", title="KO retina translatome vs KO dlgn translatome.",
  url_data="http://useast.ensembl.org/Mus_musculus/Gene/Summary?g={ids}")
``

## KO Retina vs KO SCN
## Error: attempt to use zero-length variable name
plotted <- as.data.frame(pair_mtrx[, c("koret", "koscn")])
## Error in as.data.frame(pair_mtrx[, c("koret", "koscn")]): object 'pair_mtrx' not found
plotted[["label"]] <- rownames(plotted)
## Error in rownames(plotted): object 'plotted' not found
plotted[["color"]] <- "black"
## Error in plotted[["color"]] <- "black": object 'plotted' not found
koret_koscn <- ggplot(
  plotted,
  aes_string(x="koret", y="koscn", label="label", color="color")) +
  geom_point(alpha=0.5) +
  scale_color_manual(values=c("black", "red"))
## Error in ggplot(plotted, aes_string(x = "koret", y = "koscn", label = "label", : object 'plotted' not found
koret_koscn
## Error in eval(expr, envir, enclos): object 'koret_koscn' not found
koret_koscn_clicky <- ggplotly_url(
  koret_koscn, "koret_koscn.html", title="KO retina translatome vs KO scn translatome.",
  url_data="http://useast.ensembl.org/Mus_musculus/Gene/Summary?g={ids}")
## Error in ggplotly_url(koret_koscn, "koret_koscn.html", title = "KO retina translatome vs KO scn translatome.", : object 'koret_koscn' not found

2.9 Norm dlgn ko dlgn

plotted <- as.data.frame(pair_mtrx[, c("normdlgn", "kodlgn")])
## Error in as.data.frame(pair_mtrx[, c("normdlgn", "kodlgn")]): object 'pair_mtrx' not found
plotted[["label"]] <- rownames(plotted)
## Error in rownames(plotted): object 'plotted' not found
plotted[["color"]] <- "black"
## Error in plotted[["color"]] <- "black": object 'plotted' not found
normdlgn_kodlgn <- ggplot(
  plotted,
  aes_string(x="normdlgn", y="kodlgn", label="label", color="color")) +
  geom_point(alpha=0.5) +
  scale_color_manual(values=c("black", "red"))
## Error in ggplot(plotted, aes_string(x = "normdlgn", y = "kodlgn", label = "label", : object 'plotted' not found
normdlgn_kodlgn
## Error in eval(expr, envir, enclos): object 'normdlgn_kodlgn' not found
normdlgn_kodlgn_clicky <- ggplotly_url(
  normdlgn_kodlgn, "normdlgn_kodlgn.html", title="Normal dlgn translatome vs KO dlgn translatome.",
  url_data="http://useast.ensembl.org/Mus_musculus/Gene/Summary?g={ids}")
## Error in ggplotly_url(normdlgn_kodlgn, "normdlgn_kodlgn.html", title = "Normal dlgn translatome vs KO dlgn translatome.", : object 'normdlgn_kodlgn' not found

2.10 Norm ret vs ko ret

plotted <- as.data.frame(pair_mtrx[, c("normret", "koret")])
## Error in as.data.frame(pair_mtrx[, c("normret", "koret")]): object 'pair_mtrx' not found
plotted[["label"]] <- rownames(plotted)
## Error in rownames(plotted): object 'plotted' not found
plotted[["color"]] <- "black"
## Error in plotted[["color"]] <- "black": object 'plotted' not found
normret_koret <- ggplot(
  plotted,
  aes_string(x="normret", y="koret", label="label", color="color")) +
  geom_point(alpha=0.5) +
  scale_color_manual(values=c("black", "red"))
## Error in ggplot(plotted, aes_string(x = "normret", y = "koret", label = "label", : object 'plotted' not found
normret_koret
## Error in eval(expr, envir, enclos): object 'normret_koret' not found
normret_koret_clicky <- ggplotly_url(
  normret_koret, "normret_koret.html", title="Normal retina translatome vs KO retina translatome.",
  url_data="http://useast.ensembl.org/Mus_musculus/Gene/Summary?g={ids}")
## Error in ggplotly_url(normret_koret, "normret_koret.html", title = "Normal retina translatome vs KO retina translatome.", : object 'normret_koret' not found

2.11 ror

plotted <- as.data.frame(pair_mtrx[, c("normret_vs_normdlgn", "koret_vs_kodlgn")])
## Error in as.data.frame(pair_mtrx[, c("normret_vs_normdlgn", "koret_vs_kodlgn")]): object 'pair_mtrx' not found
plotted[["label"]] <- rownames(plotted)
## Error in rownames(plotted): object 'plotted' not found
plotted[["color"]] <- "black"
## Error in plotted[["color"]] <- "black": object 'plotted' not found
normal_ko_axon_translatome <- ggplot(
  plotted,
  aes_string(x="normret_vs_normdlgn", y="koret_vs_kodlgn", label="label", color="color")) +
  geom_point(alpha=0.5) +
  scale_color_manual(values=c("black", "red"))
## Error in ggplot(plotted, aes_string(x = "normret_vs_normdlgn", y = "koret_vs_kodlgn", : object 'plotted' not found
normal_ko_axon_translatome
## Error in eval(expr, envir, enclos): object 'normal_ko_axon_translatome' not found
normal_ko_axon_translatome_clicky <- ggplotly_url(
  normal_ko_axon_translatome, "normal_ko_axon_translatome.html",
  title="Normal retina ko axon translatome.",
  url_data="http://useast.ensembl.org/Mus_musculus/Gene/Summary?g={ids}")
## Error in ggplotly_url(normal_ko_axon_translatome, "normal_ko_axon_translatome.html", : object 'normal_ko_axon_translatome' not found

3 Translatome level comparisons

3.1 Make a generic plotter for this stuff.

translatome_plotter <- function(pair_mtrx, x_axis="koret", y_axis="koscn", lfc=NULL, fc=NULL, linewidth=1.5,
                                up_color="red", down_color="#098534", line_color="#fcba03", alpha=0.5,
                                x_limit=c(-7, 7), y_limit=c(-7, 7)) {
  if (is.null(fc) & is.null(lfc)) {
    message("No fc/lfc was provided, defaulting to 10 fold.")
    lfc <- log2(10)
  } else if (is.null(lfc)) {
    lfc <- log2(fc)
  }
  plotted <- as.data.frame(pair_mtrx[, c(x_axis, y_axis)])
  na_idx <- is.na(plotted)
  plotted[na_idx] <- 0
  up_idx <- plotted[, y_axis] - plotted[, x_axis] >= lfc
  down_idx <- plotted[, y_axis] - plotted[, x_axis] <= (lfc * -1)
  up_genes <- rownames(plotted)[up_idx]
  down_genes <- rownames(plotted)[down_idx]
  ## Note that this order is opposite of above.
  plotted[["color"]] <- "black"
  plotted[up_idx, "color"] <- up_color
  plotted[down_idx, "color"] <- down_color
  plotted[["color"]] <- as.factor(plotted[["color"]])
  levels(plotted[["color"]]) <- c("black", up_color, down_color)
  plt <- ggplot2::ggplot(plotted, aes_string(x=x_axis,
                                             y=y_axis,
                                             color="color")) +
    geom_abline(size=1.1, slope=1, intercept=lfc, color="orange") +
    geom_abline(size=1.1, slope=1, intercept=(-1 * lfc), color="orange") +
    scale_x_continuous(limits=c(x_limit)) +
    scale_y_continuous(limits=c(y_limit)) +
    geom_point(alpha=alpha) +
    scale_color_manual(values=c(down_color, "black", up_color))
  retlist <- list(
    "mtrx" = plotted,
    "ups" = up_genes,
    "downs" = down_genes,
    "plot" = plt)
  return(retlist)
}
  1. X-axis: Always retina.
  2. Y-axis: Always a target tissue.

First plot: KO scn translatome on y axis vs. KO retina translatome on x axis.

3.2 Scn knockout translatome vs retina knockout translatome.

scnko_wrt_retko_translatome <- translatome_plotter(pair_mtrx)
## No fc/lfc was provided, defaulting to 10 fold.
## Error in as.data.frame(pair_mtrx[, c(x_axis, y_axis)]): object 'pair_mtrx' not found
scnko_wrt_retko_translatome$plot
## Error in eval(expr, envir, enclos): object 'scnko_wrt_retko_translatome' not found
scnko_wrt_retko_up_go <- simple_gprofiler(sig_genes=scnko_wrt_retko_translatome$ups,
                                          species="mmusculus")
## Error in simple_gprofiler(sig_genes = scnko_wrt_retko_translatome$ups, : object 'scnko_wrt_retko_translatome' not found
scnko_wrt_retko_down_go <- simple_gprofiler(sig_genes=scnko_wrt_retko_translatome$downs,
                                            species="mmusculus")
## Error in simple_gprofiler(sig_genes = scnko_wrt_retko_translatome$downs, : object 'scnko_wrt_retko_translatome' not found
scnko_wrt_retko_down_go$go
## Error in eval(expr, envir, enclos): object 'scnko_wrt_retko_down_go' not found
scnko_wrt_retko_down_go$kegg
## Error in eval(expr, envir, enclos): object 'scnko_wrt_retko_down_go' not found
scnko_wrt_retko_down_go$corum
## Error in eval(expr, envir, enclos): object 'scnko_wrt_retko_down_go' not found

3.3 dlgn normal translatome vs retina normal translatome.

dlgnnorm_wrt_retnorm_translatome <- translatome_plotter(pair_mtrx,
                                                        x_axis="normret", y_axis="normdlgn")
## No fc/lfc was provided, defaulting to 10 fold.
## Error in as.data.frame(pair_mtrx[, c(x_axis, y_axis)]): object 'pair_mtrx' not found
dlgnnorm_wrt_retnorm_translatome$plot
## Error in eval(expr, envir, enclos): object 'dlgnnorm_wrt_retnorm_translatome' not found
dlgnnorm_wrt_retnorm_up_go <- simple_gprofiler(sig_genes=dlgnnorm_wrt_retnorm_translatome$ups,
                                               species="mmusculus")
## Error in simple_gprofiler(sig_genes = dlgnnorm_wrt_retnorm_translatome$ups, : object 'dlgnnorm_wrt_retnorm_translatome' not found
dlgnnorm_wrt_retnorm_down_go <- simple_gprofiler(sig_genes=dlgnnorm_wrt_retnorm_translatome$downs,
                                                 species="mmusculus")
## Error in simple_gprofiler(sig_genes = dlgnnorm_wrt_retnorm_translatome$downs, : object 'dlgnnorm_wrt_retnorm_translatome' not found
dlgnnorm_wrt_retnorm_down_go$go
## Error in eval(expr, envir, enclos): object 'dlgnnorm_wrt_retnorm_down_go' not found
dlgnnorm_wrt_retnorm_down_go$pvalue_plots$bpp_plot_over
## Error in eval(expr, envir, enclos): object 'dlgnnorm_wrt_retnorm_down_go' not found
dlgnnorm_wrt_retnorm_down_go$pvalue_plots$ccp_plot_over
## Error in eval(expr, envir, enclos): object 'dlgnnorm_wrt_retnorm_down_go' not found

3.4 dlgn knockout translatome vs retina knockout translatome.

dlgnko_wrt_retko_translatome <- translatome_plotter(pair_mtrx,
                                                    x_axis="koret", y_axis="kodlgn")
## No fc/lfc was provided, defaulting to 10 fold.
## Error in as.data.frame(pair_mtrx[, c(x_axis, y_axis)]): object 'pair_mtrx' not found
dlgnko_wrt_retko_translatome$plot
## Error in eval(expr, envir, enclos): object 'dlgnko_wrt_retko_translatome' not found
dlgnko_wrt_retko_up_go <- simple_gprofiler(sig_genes=dlgnko_wrt_retko_translatome$ups,
                                           species="mmusculus")
## Error in simple_gprofiler(sig_genes = dlgnko_wrt_retko_translatome$ups, : object 'dlgnko_wrt_retko_translatome' not found
dlgnko_wrt_retko_up_go$go
## Error in eval(expr, envir, enclos): object 'dlgnko_wrt_retko_up_go' not found
dlgnko_wrt_retko_up_go$kegg
## Error in eval(expr, envir, enclos): object 'dlgnko_wrt_retko_up_go' not found
dlgnko_wrt_retko_up_go$reac
## Error in eval(expr, envir, enclos): object 'dlgnko_wrt_retko_up_go' not found
dlgnko_wrt_retko_down_go <- simple_gprofiler(sig_genes=dlgnko_wrt_retko_translatome$downs,
                                             species="mmusculus")
## Error in simple_gprofiler(sig_genes = dlgnko_wrt_retko_translatome$downs, : object 'dlgnko_wrt_retko_translatome' not found
dlgnko_wrt_retko_down_go$go
## Error in eval(expr, envir, enclos): object 'dlgnko_wrt_retko_down_go' not found
dlgnko_wrt_retko_down_go$kegg
## Error in eval(expr, envir, enclos): object 'dlgnko_wrt_retko_down_go' not found
dlgnko_wrt_retko_down_go$reac
## Error in eval(expr, envir, enclos): object 'dlgnko_wrt_retko_down_go' not found

3.5 Normal dlgn translatome vs knockout dlgn translatome.

dlgnnorm_wrt_dlgnko_translatome <- translatome_plotter(pair_mtrx,
                                                       x_axis="normdlgn",
                                                       y_axis="kodlgn")
## No fc/lfc was provided, defaulting to 10 fold.
## Error in as.data.frame(pair_mtrx[, c(x_axis, y_axis)]): object 'pair_mtrx' not found
dlgnnorm_wrt_dlgnko_translatome$plot
## Error in eval(expr, envir, enclos): object 'dlgnnorm_wrt_dlgnko_translatome' not found
dlgnnorm_wrt_dlgnko_up_go <- simple_gprofiler(sig_genes=dlgnnorm_wrt_dlgnko_translatome$ups,
                                              species="mmusculus")
## Error in simple_gprofiler(sig_genes = dlgnnorm_wrt_dlgnko_translatome$ups, : object 'dlgnnorm_wrt_dlgnko_translatome' not found
dlgnnorm_wrt_dlgnko_down_go <- simple_gprofiler(sig_genes=dlgnnorm_wrt_dlgnko_translatome$downs,
                                                species="mmusculus")
## Error in simple_gprofiler(sig_genes = dlgnnorm_wrt_dlgnko_translatome$downs, : object 'dlgnnorm_wrt_dlgnko_translatome' not found
dlgnnorm_wrt_dlgnko_down_go$go
## Error in eval(expr, envir, enclos): object 'dlgnnorm_wrt_dlgnko_down_go' not found

3.6 dlgn knockout translatome vs. scn knockout translatome.

dlgnko_wrt_scnko_translatome <- translatome_plotter(pair_mtrx,
                                                    x_axis="kodlgn",
                                                    y_axis="koscn")
## No fc/lfc was provided, defaulting to 10 fold.
## Error in as.data.frame(pair_mtrx[, c(x_axis, y_axis)]): object 'pair_mtrx' not found
dlgnko_wrt_scnko_translatome$plot
## Error in eval(expr, envir, enclos): object 'dlgnko_wrt_scnko_translatome' not found
dlgnko_wrt_scnko_up_go <- simple_gprofiler(sig_genes=dlgnko_wrt_scnko_translatome$ups,
                                           species="mmusculus")
## Error in simple_gprofiler(sig_genes = dlgnko_wrt_scnko_translatome$ups, : object 'dlgnko_wrt_scnko_translatome' not found
dlgnko_wrt_scnko_up_go$go
## Error in eval(expr, envir, enclos): object 'dlgnko_wrt_scnko_up_go' not found
dlgnko_wrt_scnko_up_go$pvalue_plots$bpp_plot_over
## Error in eval(expr, envir, enclos): object 'dlgnko_wrt_scnko_up_go' not found
dlgnko_wrt_scnko_down_go <- simple_gprofiler(sig_genes=dlgnko_wrt_scnko_translatome$downs,
                                             species="mmusculus")
## Error in simple_gprofiler(sig_genes = dlgnko_wrt_scnko_translatome$downs, : object 'dlgnko_wrt_scnko_translatome' not found
dlgnko_wrt_scnko_down_go$go
## Error in eval(expr, envir, enclos): object 'dlgnko_wrt_scnko_down_go' not found

4 Some pictures

As I understand it, there is some interest in an ontology search using the ratio of ratios.

ror <- normko_retdlgn
up_idx <- ror >= 1
down_idx <- ror <= -1
ror_up <- ror[up_idx]
length(ror_up)
## [1] 1877
ror_down <- ror[down_idx]
length(ror_down)
## [1] 476
ror_gprofiler_up <- simple_gprofiler(
  sig_genes=ror_up, species="mmusculus",
  excel=glue::glue("excel/{rundate}mm_ror_gpfoiler_up-v{ver}.xlsx"))
## Performing gProfiler GO search of 1877 genes against mmusculus.
## GO search found 271 hits.
## Performing gProfiler KEGG search of 1877 genes against mmusculus.
## KEGG search found 8 hits.
## Performing gProfiler REAC search of 1877 genes against mmusculus.
## REAC search found 11 hits.
## Performing gProfiler MI search of 1877 genes against mmusculus.
## MI search found 0 hits.
## Performing gProfiler TF search of 1877 genes against mmusculus.
## TF search found 376 hits.
## Performing gProfiler CORUM search of 1877 genes against mmusculus.
## CORUM search found 1 hits.
## Performing gProfiler HP search of 1877 genes against mmusculus.
## HP search found 5 hits.
## Writing data to: excel/20201008mm_ror_gpfoiler_up-v20200114.xlsx.
## Finished writing data.
ror_gprofiler_up$pvalue_plots$mfp_plot_over

ror_gprofiler_up$pvalue_plots$bpp_plot_over

ror_gprofiler_up$pvalue_plots$ccp_plot_over

ror_gprofiler_up$pvalue_plots$tf_plot_over
## Warning: Removed 1 rows containing missing values (geom_col).

ror_gprofiler_up$pvalue_plots$hp_plot_over

ror_gprofiler_down <- simple_gprofiler(
  sig_genes=ror_down, species="mmusculus",
  excel=glue::glue("excel/{rundate}mm_ror_gpfoiler_down-v{ver}.xlsx"))
## Performing gProfiler GO search of 476 genes against mmusculus.
## GO search found 82 hits.
## Performing gProfiler KEGG search of 476 genes against mmusculus.
## KEGG search found 7 hits.
## Performing gProfiler REAC search of 476 genes against mmusculus.
## REAC search found 2 hits.
## Performing gProfiler MI search of 476 genes against mmusculus.
## MI search found 0 hits.
## Performing gProfiler TF search of 476 genes against mmusculus.
## TF search found 6 hits.
## Performing gProfiler CORUM search of 476 genes against mmusculus.
## CORUM search found 0 hits.
## Performing gProfiler HP search of 476 genes against mmusculus.
## HP search found 0 hits.
## Writing data to: excel/20201008mm_ror_gpfoiler_down-v20200114.xlsx.
## Finished writing data.
ror_gprofiler_down$pvalue_plots$mfp_plot_over

ror_gprofiler_down$pvalue_plots$bpp_plot_over

ror_gprofiler_down$pvalue_plots$reactome_plot_over

ror_gprofiler_down$pvalue_plots$ccp_plot_over

ror_gprofiler_down$pvalue_plots$tf_plot_over

pander::pander(sessionInfo())
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))
loadme(filename=this_save)
LS0tCnRpdGxlOiAiTS4gbXVzY3VsdXMgMyBjZWxsIHR5cGVzLCAxIHRpbWVwb2ludCwgMyBnZW5vdHlwZXMsIGFuZCAxIHJlcGxpY2F0ZS4iCmF1dGhvcjogImF0YiBhYmVsZXdAZ21haWwuY29tIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgZmlnX2hlaWdodDogNwogICAgZmlnX3dpZHRoOiA3CiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICBrZWVwX21kOiBmYWxzZQogICAgbW9kZTogc2VsZmNvbnRhaW5lZAogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQogICAgdGhlbWU6IHJlYWRhYmxlCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDoKICAgICAgY29sbGFwc2VkOiBmYWxzZQogICAgICBzbW9vdGhfc2Nyb2xsOiBmYWxzZQogIHJtZGZvcm1hdHM6OnJlYWR0aGVkb3duOgogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBkZl9wcmludDogcGFnZWQKICAgIGZpZ19jYXB0aW9uOiB0cnVlCiAgICBmaWdfaGVpZ2h0OiA3CiAgICBmaWdfd2lkdGg6IDcKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIHdpZHRoOiAzMDAKICAgIGtlZXBfbWQ6IGZhbHNlCiAgICBtb2RlOiBzZWxmY29udGFpbmVkCiAgICB0b2NfZmxvYXQ6IHRydWUKICBCaW9jU3R5bGU6Omh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGZpZ19jYXB0aW9uOiB0cnVlCiAgICBmaWdfaGVpZ2h0OiA3CiAgICBmaWdfd2lkdGg6IDcKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIGtlZXBfbWQ6IGZhbHNlCiAgICBtb2RlOiBzZWxmY29udGFpbmVkCiAgICB0b2NfZmxvYXQ6IHRydWUKLS0tCgo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgpib2R5LCB0ZCB7CiAgZm9udC1zaXplOiAxNnB4Owp9CmNvZGUucnsKICBmb250LXNpemU6IDE2cHg7Cn0KcHJlIHsKIGZvbnQtc2l6ZTogMTZweAp9Cjwvc3R5bGU+CgpgYGB7ciBvcHRpb25zLCBpbmNsdWRlPUZBTFNFfQpsaWJyYXJ5KCJocGdsdG9vbHMiKQp0dCA8LSBkZXZ0b29sczo6bG9hZF9hbGwoIi9kYXRhL2hwZ2x0b29scyIpCmtuaXRyOjpvcHRzX2tuaXQkc2V0KHdpZHRoPTEyMCwKICAgICAgICAgICAgICAgICAgICAgcHJvZ3Jlc3M9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgdmVyYm9zZT1UUlVFLAogICAgICAgICAgICAgICAgICAgICBlY2hvPVRSVUUpCmtuaXRyOjpvcHRzX2NodW5rJHNldChlcnJvcj1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgZHBpPTk2KQpvbGRfb3B0aW9ucyA8LSBvcHRpb25zKGRpZ2l0cz00LAogICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAga25pdHIuZHVwbGljYXRlLmxhYmVsPSJhbGxvdyIpCmdncGxvdDI6OnRoZW1lX3NldChnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemU9MTApKQpydW5kYXRlIDwtIGZvcm1hdChTeXMuRGF0ZSgpLCBmb3JtYXQ9IiVZJW0lZCIpCnByZXZpb3VzX2ZpbGUgPC0gInVuZGVmaW5lZC5SbWQiCnZlciA8LSAiMjAyMDAxMTQiCgojI3RtcCA8LSBzbShsb2FkbWUoZmlsZW5hbWU9cGFzdGUwKGdzdWIocGF0dGVybj0iXFwuUm1kIiwgcmVwbGFjZT0iIiwgeD1wcmV2aW91c19maWxlKSwgIi12IiwgdmVyLCAiLnJkYS54eiIpKSkKcm1kX2ZpbGUgPC0gImluZGV4LlJtZCIKYGBgCgojIE0uIG11c2N1bHVzCgpUaGlzIHdpbGwgYmUgYSB2ZXJ5IG1pbmltYWwgYW5hbHlzaXMgdW50aWwgd2UgZ2V0IHNvbWUgcmVwbGljYXRlcy4KCiMjIEFubm90YXRpb25zCgpJIGFtIHVzaW5nIG1tMzhfMTAwLgoKYGBge3IgYW5ub3RhdGlvbnN9CiMjIE15IGxvYWRfYmlvbWFydF9hbm5vdGF0aW9ucygpIGZ1bmN0aW9uIGRlZmF1bHRzIHRvIGh1bWFuLCBzbyB0aGF0IHdpbGwgYmUgcXVpY2suCm1tX2Fubm90IDwtIGxvYWRfYmlvbWFydF9hbm5vdGF0aW9ucyhzcGVjaWVzPSJtbXVzY3VsdXMiKQptbV9hbm5vdCA8LSBtbV9hbm5vdFtbImFubm90YXRpb24iXV0KbW1fYW5ub3RbWyJ0eGlkIl1dIDwtIHBhc3RlMChtbV9hbm5vdFtbImVuc2VtYmxfdHJhbnNjcmlwdF9pZCJdXSwgIi4iLCBtbV9hbm5vdFtbInZlcnNpb24iXV0pCnJvd25hbWVzKG1tX2Fubm90KSA8LSBtYWtlLm5hbWVzKG1tX2Fubm90W1siZW5zZW1ibF9nZW5lX2lkIl1dLCB1bmlxdWU9VFJVRSkKCnR4X2dlbmVfbWFwIDwtIG1tX2Fubm90WywgYygidHhpZCIsICJlbnNlbWJsX2dlbmVfaWQiKV0KYGBgCgpTbywgSSBub3cgaGF2ZSBhIHRhYmxlIG9mIG1vdXNlIGFubm90YXRpb25zLgoKIyMgTWV0YWRhdGEKCkkgYW0gZ29pbmcgdG8gd3JpdGUgYSBxdWljayBzYW1wbGUgc2hlZXQgaW4gdGhlIGN1cnJlbnQgd29ya2luZyBkaXJlY3RvcnkgY2FsbGVkCidhbGxfc2FtcGxlcy54bHN4JyBhbmQgcHV0IHRoZSBuYW1lcyBvZiB0aGUgY291bnQgdGFibGVzIGluIGl0LgoKIyMgQ3JlYXRlIGV4cHJlc3Npb25zZXRzCgpIZXJlIEkgY29tYmluZSB0aGUgbWV0YWRhdGEsIGNvdW50IGRhdGEsIGFuZCBhbm5vdGF0aW9ucy4KCkl0IGlzIHdvcnRoIG5vdGluZyB0aGF0IHRoZSBnZW5lIElEcyBmcm9tIGh0c2VxLWNvdW50IHByb2JhYmx5IGRvIG5vdCBtYXRjaCB0aGUKYW5ub3RhdGlvbnMgcmV0cmlldmVkIGJlY2F1c2UgdGhleSBhcmUgbGlrZWx5IGV4b24tYmFzZWQgcmF0aGVyIHRoYW4gZ2VuZQpiYXNlZC4gIFRoaXMgaXMgbm90IHJlYWxseSBhIHByb2JsZW0sIGJ1dCBkb24ndCBmb3JnZXQgaXQhCgojIyBIaXNhdDIgZXhwcmVzc2lvbnNldAoKYGBge3IgaGlzYXQyfQpoaXNhdF9hbm5vdCA8LSBtbV9hbm5vdApyb3duYW1lcyhoaXNhdF9hbm5vdCkgPC0gcGFzdGUwKCJnZW5lOiIsIHJvd25hbWVzKGhpc2F0X2Fubm90KSkKbW0zOF9oaXNhdCA8LSBjcmVhdGVfZXhwdCgic2FtcGxlX3NoZWV0cy9hbGxfc2FtcGxlcy54bHN4IiwKICAgICAgICAgICAgICAgICAgICAgICAgICBnZW5lX2luZm89aGlzYXRfYW5ub3QpCgpwbG90X2xpYnNpemUobW0zOF9oaXNhdCkkcGxvdAptbTM4X2ZpcnN0IDwtIG5vcm1hbGl6ZV9leHB0KG1tMzhfaGlzYXQsIGZpbHRlcj1UUlVFLCBjb252ZXJ0PSJjcG0iLCBub3JtPSJxdWFudCIsIHRyYW5zZm9ybT0ibG9nMiIpCnBwKGZpbGU9InBjYV9ub3JtLnBuZyIsIGltYWdlPXBsb3RfcGNhKG1tMzhfZmlyc3QpJHBsb3QpCgptbTM4X25vcm0gPC0gbm9ybWFsaXplX2V4cHQobW0zOF9oaXNhdCwgZmlsdGVyPVRSVUUsIGNvbnZlcnQ9ImNwbSIsIGJhdGNoPSJzdmFzZXEiKQptbTM4X25vcm0gPC0gbm9ybWFsaXplX2V4cHQobW0zOF9ub3JtLCB0cmFuc2Zvcm09ImxvZzIiKQpwcChmaWxlPSJwY2Ffc3ZhLnBuZyIsIGltYWdlPXBsb3RfcGNhKG1tMzhfbm9ybSkkcGxvdCkKCm5ldyA8LSBzdWJzZXRfZXhwdChtbTM4X2hpc2F0LCBzdWJzZXQ9ImJhdGNoPT0nYjIwMjAwOSciKQpuZXdfbm9ybSA8LSBub3JtYWxpemVfZXhwdChuZXcsIGZpbHRlcj1UUlVFLCBjb252ZXJ0PSJjcG0iLCBub3JtPSJxdWFudCIsIHRyYW5zZm9ybT0ibG9nMiIpCnBsb3RfcGNhKG5ld19ub3JtKSRwbG90CmBgYAoKYGBge3IgZXhwdH0KbW0zOF9zYWxtb24gPC0gc20oY3JlYXRlX2V4cHQoInNhbXBsZV9zaGVldHMvYWxsX3NhbXBsZXMueGxzeCIsIHR4X2dlbmVfbWFwPXR4X2dlbmVfbWFwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW5lX2luZm89bW1fYW5ub3QsIGZpbGVfY29sdW1uPSJzYWxtb25maWxlIikpCgptbXR4X2Fubm90IDwtIG1tX2Fubm90CnJvd25hbWVzKG1tdHhfYW5ub3QpIDwtIG1tX2Fubm90W1sidHhpZCJdXQptbTM4X3NhbHR4IDwtIHNtKGNyZWF0ZV9leHB0KCJzYW1wbGVfc2hlZXRzL2FsbF9zYW1wbGVzLnhsc3giLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlbmVfaW5mbz1tbXR4X2Fubm90LCBmaWxlX2NvbHVtbj0ic2FsbW9uZmlsZSIpKQpgYGAKCiMjIFF1ZXJ5IGV4cHJlc3Npb25zZXRzCgpJbiB0aGlzIGJsb2NrIEkgd2lsbCBjYWxjdWxhdGUgYWxsIHRoZSBkaWFnbm9zdGljIHBsb3RzLCBidXQgbm90IHNob3cgdGhlbS4gIEkKd2lsbCBzaG93IHRoZW0gbmV4dCB3aXRoIGEgbGl0dGxlIGFubm90YXRpb24uCgpJIHdpbGwgbGVhdmUgdGhlIG91dHB1dCBmb3IgdGhlIGZpcnN0IG9mIGVhY2ggaW52b2NhdGlvbiBhbmQgc2lsZW5jZSBpdCBmb3IgdGhlIHNlY29uZC4KCiMjIyBJbml0aWFsIHNhbG1vbiBwbG90cwoKYGBge3IgcXVlcnlfc2FsbW9uLCBmaWcuc2hvdz0iaGlkZSJ9Cm1tMzhfcGxvdHNfc2EgPC0gc20oZ3JhcGhfbWV0cmljcyhtbTM4X3NhbG1vbikpCgptbTM4X25vcm1fc2EgPC0gbm9ybWFsaXplX2V4cHQobW0zOF9zYWxtb24sIG5vcm09InF1YW50IiwgY29udmVydD0iY3BtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybT0ibG9nMiIsIGZpbHRlcj1UUlVFKQoKbW0zOG5fcGxvdHNfc2EgPC0gc20oZ3JhcGhfbWV0cmljcyhtbTM4X25vcm1fc2EpKQpgYGAKCmBgYHtyIHNob3dfcGxvdHNfc2FsbW9ufQptbTM4X3Bsb3RzX3NhJGxlZ2VuZAptbTM4X3Bsb3RzX3NhJGxpYnNpemUKbW0zOF9wbG90c19zYSRub256ZXJvCm1tMzhuX3Bsb3RzX3NhJGRlbnNpdHkKbW0zOG5fcGxvdHNfc2EkcGNfcGxvdApgYGAKCiMjIyBJbml0aWFsIGhpc2F0MiBwbG90cwoKYGBge3IgcXVlcnlfaGlzYXQsIGZpZy5zaG93PSJoaWRlIn0KbW0zOF9wbG90c19oaSA8LSBzbShncmFwaF9tZXRyaWNzKG1tMzhfaGlzYXQpKQoKbW0zOF9ub3JtX2hpIDwtIG5vcm1hbGl6ZV9leHB0KG1tMzhfaGlzYXQsIG5vcm09InF1YW50IiwgY29udmVydD0iY3BtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybT0ibG9nMiIsIGZpbHRlcj1UUlVFKQoKbW0zOG5fcGxvdHNfaGkgPC0gc20oZ3JhcGhfbWV0cmljcyhtbTM4X25vcm1faGkpKQpgYGAKCmBgYHtyIHNob3dfcGxvdHNfaGlzYXR9Cm1tMzhfcGxvdHNfaGkkbGlic2l6ZQptbTM4X3Bsb3RzX2hpJG5vbnplcm8KbW0zOG5fcGxvdHNfaGkkZGVuc2l0eQptbTM4bl9wbG90c19oaSRwY19wbG90CmBgYAoKIyMgRG8gYSBzaW1wbGUgREUKClRoZSBvbmx5IGludGVyZXN0aW5nIERFIEkgc2VlIGluIHRoaXMgaXMgdG8gY29tcGFyZSB0aGUgcmV0aW5hcyB0byB0aGUgZGxnbnMuCkkgY2FuIHRyZWF0IHRoZW0gYXMgcmVwbGljYXRlcyBhbmQgY29tcGFyZS4KClRoZXNlIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2VzIGFyZSBfRVhQTElDSVRMWV8gX05PVF8gd2hhdCB5b3UgY2FyZQphYm91dC4gIEhvd2V2ZXIsIHRoZXkgYXJlIHVzZWZ1bCBmb3IgdHdvIHB1cnBvc2VzOgoKMS4gIFNlZWluZyB0aGF0IHRoZSB0aHJlZSB0aXNzdWUgdHlwZXMgYXJlIGluZGVlZCBkaWZmZXJlbnQuCjIuICBTZXR0aW5nIHVwIHRoZSB0YWJsZSBvZiByZXN1bHRzIHdpdGggYXBwcm9wcmlhdGUgcm93cy9jb2x1bW5zIG9mIChyb3dzKWdlbmVzCiAgICBhbmQgKGNvbHVtbnMpIGFubm90YXRpb25zLiAgV2Ugd2lsbCB0aGVyZWZvcmUgYWRkIHRvIHRoZXNlIHRhYmxlcyB0aGUKICAgIHJlc3VsdHMgb2YgdGhlIGV4cHJlc3Npb24gYW5hbHlzZXMgdGhhdCB5b3UgYWN0dWFsbHkgZG8gY2FyZSBhYm91dC4KCldoZW4gd2UgcmVjZWl2ZSBmdWxsIHJlcGxpY2F0ZSBzZXRzLCB0aGlzIGNoZWF0ZXIgbWV0aG9kIG9mIGVuY2Fwc3VsYXRpbmcgdGhlCmRhdGEgd2lsbCBub3QgbG9uZ2VyIGJlIHJlcXVpcmVkLgoKIyMjIFdpdGggc2FsbW9uCgpgYGB7ciBkZV9zYSwgZmlnLnNob3c9ImhpZGUifQptbV9zYSA8LSBzZXRfZXhwdF9jb25kaXRpb25zKG1tMzhfc2FsbW9uLCBmYWN0PSJjZWxsdHlwZSIpCm1tX25vcm1fc2EgPC0gc20obm9ybWFsaXplX2V4cHQobW1fc2EsIGNvbnZlcnQ9InJwa20iLCB0cmFuc2Zvcm09ImxvZzIiLCBjb2x1bW49ImNkc19sZW5ndGgiKSkKcGxvdF9wY2EobW1fbm9ybV9zYSkkcGxvdAoKbW1fZGVfc2EgPC0gYWxsX3BhaXJ3aXNlKG1tX3NhLCBtb2RlbF9iYXRjaD1GQUxTRSkKYGBgCgojIyMgV2l0aCBoaXNhdDIKCmBgYHtyIGRlX2hpLCBmaWcuc2hvdz0iaGlkZSJ9CiMjIG1tX2hpIDwtIHNldF9leHB0X2NvbmRpdGlvbnMobW0zOF9oaXNhdCwgZmFjdD0iY2VsbHR5cGUiKQptbV9oaSA8LSBtbTM4X2hpc2F0Cm1tX25vcm1faGkgPC0gc20obm9ybWFsaXplX2V4cHQobW1faGksIGNvbnZlcnQ9InJwa20iLCB0cmFuc2Zvcm09ImxvZzIiLCBmaWx0ZXI9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2x1bW49ImNkc19sZW5ndGgiLCBiYXRjaD0ic3Zhc2VxIikpCnBsb3RfcGNhKG1tX25vcm1faGkpJHBsb3QKCmtlZXBlcnMgPC0gbGlzdCgKICAid3RfZGxnbnJldCIgPSBjKCJ3dF9kbGduIiwgInd0X3JldGluYSIpLAogICJ3dF9zY25yZXQiID0gYygid3Rfc2NuIiwgInd0X3JldGluYSIpLAogICJ3dF9kbGduc2NuIiA9IGMoInd0X2RsZ24iLCAid3Rfc2NuIiksCiAgIm5vcm1yZXQiID0gYygiaGV0X3JldGluYSIsICJ3dF9yZXRpbmEiKSwKICAia29yZXQiID0gYygia29fcmV0aW5hIiwgInd0X3JldGluYSIpLAogICJub3Jtc2NuIiA9IGMoImhldF9zY24iLCAid3Rfc2NuIiksCiAgImtvc2NuIiA9IGMoImtvX3NjbiIsICJ3dF9zY24iKSwKICAibm9ybWRsZ24iID0gYygiaGV0X2RsZ24iLCAid3RfZGxnbiIpLAogICJrb2RsZ24iID0gYygia29fZGxnbiIsICJ3dF9kbGduIiksCiAgIm5vcm1kbGduX3ZzX25vcm1yZXQiID0gYygibm9ybWRsZ24iLCAibm9ybXJldCIpLAogICJub3Jtc2NuX3ZzX25vcm1yZXQiID0gYygibm9ybXNjbiIsICJub3JtcmV0IiksCiAgImtvZGxnbl92c19rb3JldCIgPSBjKCJrb2RsZ24iLCAia29yZXQiKSwKICAia29zY25fdnNfa29yZXQiID0gYygia29zY24iLCAia29yZXQiKSwKICAia29zY25fdnNfa29kbGduIiA9IGMoImtvc2NuIiwgImtvZGxnbiIpLAogICJrb3JldF92c19ub3JtcmV0IiA9IGMoImtvX3JldGluYSIsICJoZXRfcmV0aW5hIiksCiAgImtvc2NuX3ZzX25vcm1zY24iID0gYygia29fc2NuIiwgImhldF9zY24iKSwKICAia29kbGduX3ZzX25vcm1kbGduIiA9IGMoImtvX2RsZ24iLCAiaGV0X2RsZ24iKSwKICAibm9ybWtvX3JldGRsZ24iID0gYygibm9ybWRsZ25fdnNfbm9ybXJldCIsICJrb2RsZ25fdnNfa29yZXQiKSwKICAibm9ybWtvX3JldHNjbiIgPSBjKCJub3Jtc2NuX3ZzX25vcm1yZXQiLCAia29zY25fdnNfa29yZXQiKSkKZXh0cmFzIDwtICJub3JtZGxnbl92c19ub3JtcmV0ID0gKGhldF9kbGduLXd0X2RsZ24pLShoZXRfcmV0aW5hLXd0X3JldGluYSksCiAgICAgICAgICAgbm9ybXNjbl92c19ub3JtcmV0ID0gKGhldF9zY24td3Rfc2NuKS0oaGV0X3JldGluYS13dF9yZXRpbmEpLAogICAgICAgICAgIGtvZGxnbl92c19rb3JldCA9IChrb19kbGduLXd0X2RsZ24pLShrb19yZXRpbmEtd3RfcmV0aW5hKSwKICAgICAgICAgICBrb3Njbl92c19rb3JldCA9IChrb19zY24td3Rfc2NuKS0oa29fcmV0aW5hLXd0X3JldGluYSksCiAgICAgICAgICAga29zY25fdnNfa29kbGduID0gKGtvX3Njbi13dF9zY24pLShrb19kbGduLXd0X2RsZ24pLAogICAgICAgICAgIG5vcm1rb19yZXRkbGduID0gKChoZXRfZGxnbi13dF9kbGduKS0oaGV0X3JldGluYS13dF9yZXRpbmEpKSAtICgoa29fZGxnbi13dF9kbGduKS0oa29fcmV0aW5hLXd0X3JldGluYSkpLAogICAgICAgICAgIG5vcm1rb19yZXRzY24gPSAoKGhldF9zY24td3Rfc2NuKS0oaGV0X3JldGluYS13dF9yZXRpbmEpKSAtICgoa29fc2NuLXd0X3NjbiktKGtvX3JldGluYS13dF9yZXRpbmEpKSIKbW1fZmlsdCA8LSBub3JtYWxpemVfZXhwdChtbV9oaSwgZmlsdGVyPVRSVUUpCm1tX3Rlc3QgPC0gbGltbWFfcGFpcndpc2UobW1fZmlsdCwgbW9kZWxfYmF0Y2g9InN2YXNlcSIsIGV4dHJhX2NvbnRyYXN0cz1leHRyYXMpCm1tX3Rlc3QgPC0gZGVzZXFfcGFpcndpc2UobW1fZmlsdCwgbW9kZWxfYmF0Y2g9InN2YXNlcSIsIGV4dHJhX2NvbnRyYXN0cz1leHRyYXMpCm1tX3Rlc3QgPC0gZWRnZXJfcGFpcndpc2UobW1fZmlsdCwgbW9kZWxfYmF0Y2g9InN2YXNlcSIsIGV4dHJhX2NvbnRyYXN0cz1leHRyYXMpCm1tX3Rlc3QgPC0gZWJzZXFfcGFpcndpc2UobW1fZmlsdCwgbW9kZWxfYmF0Y2g9InN2YXNlcSIsIGV4dHJhX2NvbnRyYXN0cz1leHRyYXMpCm1tX2RlX2hpIDwtIHNtKGFsbF9wYWlyd2lzZShtbV9maWx0LCBtb2RlbF9iYXRjaD0ic3Zhc2VxIiwgcGFyYWxsZWw9RkFMU0UsIGV4dHJhX2NvbnRyYXN0cz1leHRyYXMpKQptbV9kZV90YWJsZXMgPC0gY29tYmluZV9kZV90YWJsZXMobW1fZGVfaGksIGV4Y2VsPSJleGNlbC90ZXN0aW5nXzIwMjAxMC54bHN4IikKYGBgCgojIyBTZXQgdXAgZm9yIGluaXRpYWwgYW5hbHlzaXMKClVudGlsIHdlIGdldCBmdWxsIHJlcGxpY2F0ZXMsIEkgd2lsbCBkbyBzaW1wbGUgc3VidHJhY3Rpb25zLgoKIyMjIFRlcm0gZGVmaW5pdGlvbgoKSW4gYW4gYXR0ZW1wdCB0byBrZWVwIHNvbWUgY2xhcml0eSBpbiB0aGUgdGVybXMgdXNlZCwgSSB3YW50IHRvIGRlZmluZSB0aGVtCm5vdy4gIFRoZXJlIGFyZSB0aHJlZSBjb250ZXh0cyBpbiB3aGljaCB3ZSB3aWxsIGNvbnNpZGVyIHRoZSBkYXRhOgoKMS4gIFRoZSBpbmRpdmlkdWFsIHNhbXBsZSB0eXBlLiAgV2hlbiBjb25zaWRlcmluZyBpbmRpdmlkdWFsIHNhbXBsZXMsIEkgd2lsbCB1c2UKICAgIHRocmVlIHRlcm1zIGluIHRoaXMgYW5kIG9ubHkgdGhpcyBjb250ZXh0OiB3aWxkLXR5cGUgKHd0KSwgaGV0LCBhbmQgbXV0LgoKMi4gIFRoZSBpbmRpdmlkdWFsIHRyYW5zbGF0b21lLiAgVGhlc2UgYXJlIGRlZmluZXMgYXMgc29tZXRoaW5nIC8gYmFzZWxpbmUuICBJCiAgICB3aWxsIGV4Y2x1c2l2ZWx5IGNhbGwgdGhlIHd0IHNhbXBsZXMgJ2Jhc2VsaW5lJyB3aGVuIHNwZWFraW5nIGluIHRoaXMKICAgIGNvbnRleHQuICBJIHdpbGwgZXhjbHVzaXZlbHkgc3RhdGUgJ25vcm1hbCcgd2hlbiByZWZlcnJpbmcgdG8gaGV0IC8gd3QKICAgIHNhbXBsZXMsIGFuZCBJIHdpbGwgc3RhdGUgJ2tvJyB3aGVuIHJlZmVycmluZyB0byBtdXQgLyB3dCBzYW1wbGVzIGluIHRoZQogICAgdHJhbnNsYXRvbWUgY29udGV4dC4KCjMuICBUcmFuc2xhdG9tZSB2cy4gdHJhbnNsYXRvbWUuICBXaGVuZXZlciBjb21wYXJpbmcgdHJhbnNsYXRvbWVzLCBJIHdpbGwgdXNlCiAgICB0aGUgbmFtZXMgYXMgaW4gIzIgYW5kIGFsd2F5cyBwdXQgdGhlIG51bWVyYXRvciBmaXJzdCB3aGVuIHdyaXRpbmcgdGhlIG5hbWUKICAgIG9mIGEgY29tcGFyaXNvbi4KClRoZSBtb3N0IGNvbXBsZXggZXhhbXBsZSBvZiB0aGUgYWJvdmUgbm9tZW5jbGF0dXJlIGlzOgoKIm5vcm1rb19yZXRkbGduIGlzIGRlZmluZWQgYXMgbm9ybXJldF92c19ub3JtZGxnbiAtIGtvcmV0X3ZzX2tvZGxnbiIKClRoaXMgc3RhdGVzIHdlIGFyZSBleGFtaW5pbmcgYXQgdGhlIHRyYW5zbGF0b21lIGNvbnRleHQ6CiAgIChub3JtKHJldGluYSB0cmFuc2xhdG9tZSkgLSBub3JtKGRsZ24gdHJhbnNsYXRvbWUpKSAtCiAgIChrbyhyZXRpbmEgdHJhbnNsYXRvbWUpIC0ga28oZGxnbiB0cmFuc2xhdG9tZSkpCgpXaGljaCBpbiB0dXJuIGlzIHN5bm9ueW1vdXMgdG8gdGhlIGZvbGxvd2luZyBhdCB0aGUgc2FtcGxlIGNvbnRleHQ6CiAgKChyZXRoZXQgLSByZXR3dCkgIC0gIChkbGduaGV0IC0gZGxnbnd0KSkgIC0KICAoKHJldGtvIC0gcmV0d3QpICAtICAoZGxnbmtvIC0gZGxnbnd0KSkKCk5vdyBsZXQgdXMgYXNzb2NpYXRlIHRoZSB2YXJpb3VzIHZhcmlhYmxlIG5hbWVzIHdpdGggdGhlIGFwcHJvcHJpYXRlIHNhbXBsZXM6CgpgYGB7ciBzYW1wbGVfbmFtZXN9CmRsZ253dCA8LSAiaXByZ2NfMDEiCnJldHd0IDwtICJpcHJnY18wMiIKc2Nud3QgPC0gImlwcmdjXzAzIgoKZGxnbmhldCA8LSAiaXByZ2NfMDQiCnJldGhldCA8LSAiaXByZ2NfMDUiCnNjbmhldCA8LSBOVUxMICAjIyBEb2VzIG5vdCB5ZXQgZXhpc3QuCgpkbGdubXV0IDwtICJpcHJnY18wNiIKcmV0bXV0IDwtICJpcHJnY18wNyIKc2NubXV0IDwtICJpcHJnY18wOCIKYGBgCgpHaXZlIHRoZXNlIHZhcmlhYmxlIG5hbWVzLCBub3cgbGV0cyBhc3NvY2lhdGUgY29sdW1ucyBvZiB0aGUgZXhwcmVzc2lvbiBkYXRhCndpdGggdGhlbS4gIFRoZXNlIGFyZSBhdCB0aGUgc2FtcGxlIGNvbnRleHQsIHNvIHRoZSBhcHByb3ByaWF0ZSBuYW1lcyBhcmU6Cid3dCcsICdoZXQnLCBhbmQgJ211dCcuICBJbiBlYWNoIGNhc2UgSSB3aWxsIHByZWZpeCB0aGUgZ2Vub3R5cGUgd2l0aCB0aGUgdGlzc3VlCnR5cGU6ICdyZXQnLCAnZGxnbicsIGFuZCAnc2NuJy4gIFRodXMgJ3JldHd0JyByZWZlcnMgdG8gdGhlIHNhbXBsZSB1c2VkCnRvIGNhbGN1bGF0ZSB0aGUgdHJhbnNsYXRvbWUgcmV0aW5hIGJhc2VsaW5lOyBpbiBjb250cmFzdCAnZGxnbm11dCcgaXMgdGhlCnNhbXBsZSB3aGljaCBwcm92aWRlcyB0aGUgZGxnbiBrbm9ja291dC4KCmBgYHtyIHNhbXBsZV9jb2x1bW5zfQojIyBTYW1wbGUgY29udGV4dAptbTM4X25vcm0gPC0gbW1fbm9ybV9zYQpkbGdud3QgPC0gZXhwcnMobW0zOF9ub3JtKVssIGRsZ253dF0KcmV0d3QgPC0gZXhwcnMobW0zOF9ub3JtKVssIHJldHd0XQpzY253dCA8LSBleHBycyhtbTM4X25vcm0pWywgc2Nud3RdCmRsZ25oZXQgPC0gZXhwcnMobW0zOF9ub3JtKVssIGRsZ25oZXRdCnJldGhldCA8LSBleHBycyhtbTM4X25vcm0pWywgcmV0aGV0XQpkbGdubXV0IDwtIGV4cHJzKG1tMzhfbm9ybSlbLCBkbGdubXV0XQpyZXRtdXQgPC0gZXhwcnMobW0zOF9ub3JtKVssIHJldG11dF0Kc2NubXV0IDwtIGV4cHJzKG1tMzhfbm9ybSlbLCBzY25tdXRdCmBgYAoKRWFjaCBvZiB0aGUgYWJvdmUgOCB2YXJpYWJsZXMgcHJvdmlkZXMgMSBjb2x1bW4gb2YgaW5mb3JtYXRpb24uIFdlIGhhdmUgMwpiYXNlbGluZSBjb21wYXJpc29ucyBhdmFpbGFibGUgdG8gdXMuICBJbiBlYWNoIG9mIHRoZXNlIHdlIGNvbXBhcmUgb25lIHd0CnNhbXBsZSB0byBhbm90aGVyLgoKYGBge3IgYmFzZWxpbmVfY29tcGFyaXNvbnN9CiMjIEJhc2VsaW5lIGNvbXBhcmlzb25zCnd0X2RsZ25yZXQgPC0gZGxnbnd0IC0gcmV0d3QKd3Rfc2NucmV0IDwtIHNjbnd0IC0gcmV0d3QKd3RfZGxnbnNjbiA8LSBkbGdud3QgLSBzY253dApgYGAKClNpbXVsdGFuZW91c2x5LCB3ZSBoYXZlIDUgYXZhaWxhYmxlIHRyYW5zbGF0b21lcy4gIFRoaXMgYXJlIHByb3ZpZGVkIGJ5CmNvbXBhcmluZyBlYWNoIGhldCBvciBtdXQgdG8gdGhlIGFzc29jaWF0ZWQgd3QuICBUaGVzZSB3aWxsIHRoZXJlZm9yZSByZWNlaXZlCm5hbWVzOiAnbm9ybScgYW5kICdrbycgaW5zdGVhZCBvZiAnaGV0JyBhbmQgJ211dCcuCgpgYGB7ciB0cmFuc2xhdG9tZXN9CiMjIFRyYW5zbGF0b21lIGNvbnRleHQKbm9ybXJldCA8LSByZXRoZXQgLSByZXR3dAprb3JldCA8LSByZXRtdXQgLSByZXR3dAprb3NjbiA8LSBzY25tdXQgLSBzY253dApub3JtZGxnbiA8LSBkbGduaGV0IC0gZGxnbnd0CmtvZGxnbiA8LSBkbGdubXV0IC0gZGxnbnd0CmBgYAoKR2l2ZW4gdGhlc2UgdHJhbnNsYXRvbWVzLCB0aGVyZSBhcmUgYSBmZXcgY29udHJhc3RzIG9mIGxpa2VseSBpbnRlcmVzdC4gIFRoZXNlCmFyZSBwZXJmb3JtZWQgYnkgY29tcGFyaW5nIHRoZSByZWxldmFudCB0cmFuc2xhdG9tZXMuCgpXaWxsIHdpbGwgc3BsaXQgdGhlc2UgaW50byA0IHNlcGFyYXRlIGNhdGVnb3JpZXM6CmhldCB2cyBoZXQsIGtvIHZzIGtvLCBrbyB2cyBoZXQsIGFuZCByYXRpbyB2cyByYXRpby4KCkZpbmFsbHksIG5vdGUgdGhhdCB3ZSBhcmUgYmVpbmcgZXhwbGljaXRseSByZWR1bmRhbnQgaW4gdGhlc2UgZGVmaW5pdGlvbnMuICBJIGFtCm1ha2luZyB2YXJpYWJsZSBuYW1lcyBmb3IgYm90aCB0aGUgYS9iIHJhdGlvIGFuZCB0aGUgYi9hIHJhdGlvLiAgVGh1cyB3ZSBoYXZlCnNvbWUgcmVkdW5kYW50bHkgcmVkdW5kYW50IChoYWhhKSBmbGV4aWJpbGl0eSB3aGVuIGRlY2lkaW5nIG9uIHdoYXQgd2Ugd2FudCB0byBwbG90LgoKYGBge3Igbm9ybV92c19ub3JtfQojIyBub3JtIHZzIG5vcm0Kbm9ybWRsZ25fdnNfbm9ybXJldCA8LSBub3JtZGxnbiAtIG5vcm1yZXQKbm9ybXJldF92c19ub3JtZGxnbiA8LSBub3JtcmV0IC0gbm9ybWRsZ24KYGBgCgpgYGB7ciBrb192c19rb30KIyMga28gdnMga28Ka29yZXRfdnNfa29kbGduIDwtIGtvcmV0IC0ga29kbGduCmtvZGxnbl92c19rb3JldCA8LSBrb2RsZ24gLSBrb3JldAoKa29yZXRfdnNfa29zY24gPC0ga29yZXQgLSBrb3Njbgprb3Njbl92c19rb3JldCA8LSBrb3NjbiAtIGtvcmV0Cgprb2RsZ25fdnNfa29zY24gPC0ga29kbGduIC0ga29zY24Ka29zY25fdnNfa29kbGduIDwtIGtvc2NuIC0ga29kbGduCmBgYAoKT24gdGhlIG90aGVyIGhhbmQsIEkgYW0gYXNzdW1pbmcgd2UgYWx3YXlzIHdhbnQgdGhlIG5vcm1hbHMgYXMgZGVub21pbmF0b3JzIGFuZAprb3MgYXMgbnVtZXJhdG9ycy4KCmBgYHtyIGtvX3ZzX25vcm19CiMjIGtvIHZzIG5vcm0Ka29yZXRfdnNfbm9ybXJldCA8LSBrb3JldCAtIG5vcm1yZXQKCmtvZGxnbl92c19ub3JtZGxnbiA8LSBrb2RsZ24gLSBub3JtZGxnbgpgYGAKCkZpbmFsbHksIGhlcmUgaXMgdGhlIHJhdGlvIG9mIHJhdGlvcyBleGFtcGxlIEkgcHJpbnRlZCBhYm92ZToKCkkgbmFtZWQgaXQgJ25vcm1rb19yZXRkbGduJyBpbiBhbiBhdHRlbXB0IHRvIG1ha2UgY2xlYXIgdGhhdCBpdCBpcyBhY3R1YWxseToKIChub3JtcmV0L25vcm1kbGduKS8oa29yZXQva29kbGduKQoKb3Igc3RhdGVkIGRpZmZlcmVudGx5OiAibm9ybSBkaXZpZGVkIGJ5IGtvIGZvciByZXQgZGl2aWRlZCBieSBkbGduLiIKCmBgYHtyIHJvcn0KIyMgcmF0aW8gb2YgcmF0aW9zCm5vcm1rb19yZXRkbGduIDwtIG5vcm1yZXRfdnNfbm9ybWRsZ24gLSBrb3JldF92c19rb2RsZ24KYGBgCgojIyBEZWZpbmUgYSBtYXRyaXggb2YgdGhlc2UgdmFsdWVzLgoKTXkgbWF0cml4IG9mIGRhdGEgd2lsbCBub3cgY29udGFpbiAxIGNvbHVtbiBmb3IgZWFjaCBvZiB0aGUgYWJvdmUgMjcKc2FtcGxlcy9jb21wYXJpc29ucy4KCmBgYHtyIG1hdHJpeF9vZl92YWx1ZXN9CnBhaXJfbXRyeCA8LSBjYmluZCgKICAjIyBJbmRpdmlkdWFsIHNhbXBsZXMKICBkbGdud3QsIHJldHd0LCBzY253dCwgZGxnbmhldCwgcmV0aGV0LCBkbGdubXV0LCByZXRtdXQsIHNjbm11dCwKICAjIyBCYXNlbGluZSBjb21wYXJpc29ucwogIHd0X2RsZ25yZXQsIHd0X3NjbnJldCwgd3RfZGxnbnNjbiwKICAjIyBCYXNlbGluZSBzdWJ0cmFjdGlvbnMKICBub3JtZGxnbiwgbm9ybXJldCwga29kbGduLCBrb3JldCwga29zY24sCiAgIyMgaGV0X3ZzX2hldCwgb2Ygd2hpY2ggdGhlcmUgaXMgb25seSAxIGJlY2F1c2Ugd2UgZG8gbm90IGhhdmUgaGV0c2NuCiAgbm9ybWRsZ25fdnNfbm9ybXJldCwgbm9ybXJldF92c19ub3JtZGxnbiwKICAjIyBrb192c19rbywgb2Ygd2hpY2ggd2UgaGF2ZSAzCiAga29yZXRfdnNfa29kbGduLCBrb2RsZ25fdnNfa29yZXQsCiAga29yZXRfdnNfa29zY24sIGtvc2NuX3ZzX2tvcmV0LAogIGtvZGxnbl92c19rb3Njbiwga29zY25fdnNfa29kbGduLAogICMjIGtvX3ZzX2hldCwgMyBpbmNsdWRpbmcgb25lIGdldHRpbmcgYXJvdW5kIG1pc3NpbmcgaGV0c2NuCiAga29yZXRfdnNfbm9ybXJldCwga29kbGduX3ZzX25vcm1kbGduLAogICMjIHJhdGlvIG9mIHJhdGlvcwogIG5vcm1rb19yZXRkbGduKQoKICAjIyBCYXNlbGluZSBzdWJ0cmFjdGlvbnMKICBub3JtZGxnbiwgbm9ybXJldCwga29kbGduLCBrb3JldCwga29zY24sCiAgIyMgaGV0X3ZzX2hldCwgb2Ygd2hpY2ggdGhlcmUgaXMgb25seSAxIGJlY2F1c2Ugd2UgZG8gbm90IGhhdmUgaGV0c2NuCiAgbm9ybWRsZ25fdnNfbm9ybXJldCwgbm9ybXJldF92c19ub3JtZGxnbiwKICAjIyBrb192c19rbywgb2Ygd2hpY2ggd2UgaGF2ZSAzCiAga29yZXRfdnNfa29kbGduLCBrb2RsZ25fdnNfa29yZXQsCiAga29yZXRfdnNfa29zY24sIGtvc2NuX3ZzX2tvcmV0LAogIGtvZGxnbl92c19rb3Njbiwga29zY25fdnNfa29kbGduLAogICMjIGtvX3ZzX2hldCwgMyBpbmNsdWRpbmcgb25lIGdldHRpbmcgYXJvdW5kIG1pc3NpbmcgaGV0c2NuCiAga29yZXRfdnNfbm9ybXJldCwga29kbGduX3ZzX25vcm1kbGduLAogICMjIHJhdGlvIG9mIHJhdGlvcwogIG5vcm1rb19yZXRkbGduKQogICkKYGBgCgojIyBDdXRvZmZzCgpJIGFtIG5vdCBzdXJlIGlmIHdlIHdpbGwgdXNlIHRoZXNlIGluZGV4ZXMsIGJ1dCBJIGFtIHdyaXRpbmcgdGhlc2Ugb3V0IGFzCnN1YnNldHMgb2YgZ2VuZXMgdG8gbG9vayBhdC4gIFRoZXNlIGluZGV4ZXMgYXJlIHN0YXRpbmcgdGhhdCwgZ2l2ZW4gYSBjdXRvZmYKKDApLCB3ZSB3YW50IHRvIGxvb2sgYXQgb25seSB0aGUgZ2VuZXMgd2hpY2ggaGF2ZSBoaWdoZXIgeCAvIGJhc2VsaW5lIHZhbHVlcwp0aGFuIHRoZSBjdXRvZmYuCgoKYGBge3IgY3V0b2Zmc30KIyMgUXVlcmllcyBhYm91dCBnZW5lIHN1YnNldHMuCiMjIFRoZXNlIGFyZSBhbGwgaW4gdGhlIGNvbnRleHQgb2YgdHJhbnNsYXRvbWVzLgpjdXRvZmYgPC0gMApyZXRfa2VwdF9pZHggPC0gbm9ybXJldCA+IGN1dG9mZiAmIGtvcmV0ID4gY3V0b2ZmCnNjbl9rZXB0X2lkeCA8LSBrb3NjbiA+IGN1dG9mZgpkbGduX2tlcHRfaWR4IDwtIG5vcm1kbGduID4gY3V0b2ZmICYga29kbGduID4gY3V0b2ZmCnJldF9kbGduX2tlcHRfaWR4IDwtIHJldF9rZXB0X2lkeCAmIGRsZ25fa2VwdF9pZHgKcmV0X3Njbl9rZXB0X2lkeCA8LSByZXRfa2VwdF9pZHggJiBzY25fa2VwdF9pZHgKZGxnbl9zY25fa2VwdF9pZHggPC0gZGxnbl9rZXB0X2lkeCAmIHNjbl9rZXB0X2lkeAoKIyNub3JtZGxnbl92c19ub3JtcmV0WyFyZXRfZGxnbl9rZXB0X2lkeF0gPC0gTkEKIyNub3JtcmV0X3ZzX25vcm1kbGduWyFyZXRfZGxnbl9rZXB0X2lkeF0gPC0gTkEKIyNrb3JldF92c19rb2RsZ25bIXJldF9kbGduX2tlcHRfaWR4XSA8LSBOQQojI2tvZGxnbl92c19rb3JldFshcmV0X2RsZ25fa2VwdF9pZHhdIDwtIE5BCiMja29yZXRfdnNfa29zY25bIXJldF9zY25fa2VwdF9pZHhdIDwtIE5BCiMja29zY25fdnNfa29yZXRbIXJldF9zY25fa2VwdF9pZHhdIDwtIE5BCiMja29kbGduX3ZzX2tvc2NuWyFkbGduX3Njbl9rZXB0X2lkeF0gPC0gTkEKIyNrb3Njbl92c19rb2RsZ25bIWRsZ25fc2NuX2tlcHRfaWR4XSA8LSBOQQojI2tvcmV0X3ZzX25vcm1yZXRbIXJldF9rZXB0X2lkeF0gPC0gTkEKIyNrb2RsZ25fdnNfbm9ybWRsZ25bIWRsZ25fa2VwdF9pZHhdIDwtIE5BCiMjbm9ybWtvX3JldGRsZ24gPC0gbm9ybWtvX3JldGRsZ25bIXJldF9kbGduX2tlcHRfaWR4XSA8LSBOQQpgYGAKCiMjIEFkZCB0aGUgbWF0cml4IHRvIHRoZSBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbgoKSSB3aWxsIHVzZSBteSBmdW5jdGlvbiBjb21iaW5lX2RlX3RhYmxlcygpIHRvIGFkZCB0aGlzIGluZm9ybWF0aW9uIHRvIG15CmV4aXN0aW5nIGFubm90YXRpb24gZGF0YSBhbG9uZyB3aXRoIHRoZSByZXN1bHRzIGZyb20gdGhlIHN0YXRpc3RpY2FsbHkgdmFsaWQKY29tcGFyaXNvbiBvZiB0aGUgdGhyZWUgdGlzc3VlIHR5cGVzLgoKYGBge3IgYWRkX21hdHJpeF9kZSwgZmlnLnNob3c9ImhpZGUifQptbV90YWJsZXMgPC0gc20oY29tYmluZV9kZV90YWJsZXMoCiAgbW1fZGVfc2EsIGV4dHJhX2Fubm90PXBhaXJfbXRyeCwKICBleGNlbD1nbHVlOjpnbHVlKCJleGNlbC97cnVuZGF0ZX1tbV9zYWxtb25fdGFibGVzLXZ7dmVyfS54bHN4IikpKQpgYGAKCiMgUGxvdHMgb2YgaW50ZXJlc3RpbmcgY29tcGFyaXNvbnMKCiMjIFJldGluYSwgaGV0IHZzLiB3dC4KCmBgYHtyIHJldF9oZXR3dF9wbG90fQojIyBQdXQgcmV0aW5hIGJhc2VsaW5lIG9uIHkgYXhpcyBhcyBibGFjaywgcmV0aW5hIGhldCBvbiB4IGF4aXMgYXMgYmxhY2suCiMjIFRoZW4gcmVjb2xvciBhIHN1YnNldCBvZiB0aGVzZSBhcyByZWQsIHRoZSByZWRzIGFyZSB3aGVuIG5vcm1yZXQgPiAwCmxpYnJhcnkoZ2dwbG90MikKCnBsb3R0ZWQgPC0gYXMuZGF0YS5mcmFtZShwYWlyX210cnhbLCBjKCJyZXRoZXQiLCAicmV0d3QiKV0pCnJlZF9pZHggPC0gbm9ybXJldCA+IDAKcGxvdHRlZFssICJjb2xvciJdIDwtIGlmZWxzZShyZWRfaWR4LCAicmVkIiwgImJsYWNrIikKcGxvdHRlZFtbImxhYmVsIl1dIDwtIHJvd25hbWVzKHBsb3R0ZWQpCnJldF9oZXR3dCA8LSBnZ3Bsb3QoCiAgcGxvdHRlZCwKICBhZXNfc3RyaW5nKHg9InJldGhldCIsIHk9InJldHd0IiwgbGFiZWw9ImxhYmVsIiwgY29sb3I9ImNvbG9yIikpICsKICBnZW9tX3BvaW50KGFscGhhPTAuNSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygiYmxhY2siLCAicmVkIikpCnJldF9oZXR3dApyZXRfaGV0d3RfY2xpY2t5IDwtIGdncGxvdGx5X3VybCgKICByZXRfaGV0d3QsICJyZXRfaGV0d3QuaHRtbCIsIHRpdGxlPSJSZXRpbmEgZXhwcmVzc2lvbiwgaGV0IHZzLiB3dC4iLAogIHVybF9kYXRhPSJodHRwOi8vdXNlYXN0LmVuc2VtYmwub3JnL011c19tdXNjdWx1cy9HZW5lL1N1bW1hcnk/Zz17aWRzfSIpCmBgYAoKIyMgUmV0aW5hLCBtdXQgdnMgd3QuCgpgYGB7ciByZXRfaGV0bXV0X3Bsb3R9CnBsb3R0ZWQgPC0gYXMuZGF0YS5mcmFtZShwYWlyX210cnhbLCBjKCJyZXRtdXQiLCAicmV0d3QiKV0pCnBsb3R0ZWRbWyJsYWJlbCJdXSA8LSByb3duYW1lcyhwbG90dGVkKQpwbG90dGVkW1siY29sb3IiXV0gPC0gImJsYWNrIgpyZXRfbXV0d3QgPC0gZ2dwbG90KAogIHBsb3R0ZWQsCiAgYWVzX3N0cmluZyh4PSJyZXRtdXQiLCB5PSJyZXR3dCIsIGxhYmVsPSJsYWJlbCIsIGNvbG9yPSJjb2xvciIpKSArCiAgZ2VvbV9wb2ludChhbHBoYT0wLjUpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoImJsYWNrIiwgInJlZCIpKQpyZXRfbXV0d3QKcmV0X211dHd0X2NsaWNreSA8LSBnZ3Bsb3RseV91cmwoCiAgcmV0X211dHd0LCAicmV0X211dHd0Lmh0bWwiLCB0aXRsZT0iUmV0aW5hIGV4cHJlc3Npb24sIG11dGFudCB2cy4gd3QuIiwKICB1cmxfZGF0YT0iaHR0cDovL3VzZWFzdC5lbnNlbWJsLm9yZy9NdXNfbXVzY3VsdXMvR2VuZS9TdW1tYXJ5P2c9e2lkc30iKQpgYGAKCiMjIGRsZ24sIGhldCB2cy4gd3QuCgpgYGB7ciBkbGduX2hldF93dF9wbG90fQpwbG90dGVkIDwtIGFzLmRhdGEuZnJhbWUocGFpcl9tdHJ4WywgYygiZGxnbmhldCIsICJkbGdud3QiKV0pCnBsb3R0ZWRbWyJsYWJlbCJdXSA8LSByb3duYW1lcyhwbG90dGVkKQpwbG90dGVkW1siY29sb3IiXV0gPC0gImJsYWNrIgpkbGduX2hldHd0IDwtIGdncGxvdCgKICBwbG90dGVkLAogIGFlc19zdHJpbmcoeD0iZGxnbmhldCIsIHk9ImRsZ253dCIsIGxhYmVsPSJsYWJlbCIsIGNvbG9yPSJjb2xvciIpKSArCiAgZ2VvbV9wb2ludChhbHBoYT0wLjUpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoImJsYWNrIiwgInJlZCIpKQpkbGduX2hldHd0CmRsZ25faGV0d3RfY2xpY2t5IDwtIGdncGxvdGx5X3VybCgKICBkbGduX2hldHd0LCAiZGxnbl9oZXR3dC5odG1sIiwgdGl0bGU9ImRsZ24gZXhwcmVzc2lvbiwgaGV0IHZzLiB3dC4iLAogIHVybF9kYXRhPSJodHRwOi8vdXNlYXN0LmVuc2VtYmwub3JnL011c19tdXNjdWx1cy9HZW5lL1N1bW1hcnk/Zz17aWRzfSIpCmBgYAoKIyMgZGxnbiwgbXV0IHZzLiB3dC4KCmBgYHtyIGRsZ25fbXV0X3d0X3Bsb3R9CnBsb3R0ZWQgPC0gYXMuZGF0YS5mcmFtZShwYWlyX210cnhbLCBjKCJkbGdubXV0IiwgImRsZ253dCIpXSkKcGxvdHRlZFtbImxhYmVsIl1dIDwtIHJvd25hbWVzKHBsb3R0ZWQpCnBsb3R0ZWRbWyJjb2xvciJdXSA8LSAiYmxhY2siCmRsZ25fbXV0d3QgPC0gZ2dwbG90KAogIHBsb3R0ZWQsCiAgYWVzX3N0cmluZyh4PSJkbGdubXV0IiwgeT0iZGxnbnd0IiwgbGFiZWw9ImxhYmVsIiwgY29sb3I9ImNvbG9yIikpICsKICBnZW9tX3BvaW50KGFscGhhPTAuNSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygiYmxhY2siLCAicmVkIikpCmRsZ25fbXV0d3QKZGxnbl9tdXR3dF9jbGlja3kgPC0gZ2dwbG90bHlfdXJsKAogIGRsZ25fbXV0d3QsICJkbGduX211dHd0Lmh0bWwiLCB0aXRsZT0iZGxnbiBleHByZXNzaW9uLCBtdXQgdnMuIHd0LiIsCiAgdXJsX2RhdGE9Imh0dHA6Ly91c2Vhc3QuZW5zZW1ibC5vcmcvTXVzX211c2N1bHVzL0dlbmUvU3VtbWFyeT9nPXtpZHN9IikKYGBgCgojIyBzY24sIG11dCB2cy4gd3QuCgpgYGB7ciBzY25fbXV0X3d0X3Bsb3R9CnBsb3R0ZWQgPC0gYXMuZGF0YS5mcmFtZShwYWlyX210cnhbLCBjKCJzY25tdXQiLCAic2Nud3QiKV0pCnBsb3R0ZWRbWyJsYWJlbCJdXSA8LSByb3duYW1lcyhwbG90dGVkKQpwbG90dGVkW1siY29sb3IiXV0gPC0gImJsYWNrIgpzY25fbXV0d3QgPC0gZ2dwbG90KAogIHBsb3R0ZWQsCiAgYWVzX3N0cmluZyh4PSJzY25tdXQiLCB5PSJzY253dCIsIGxhYmVsPSJsYWJlbCIsIGNvbG9yPSJjb2xvciIpKSArCiAgZ2VvbV9wb2ludChhbHBoYT0wLjUpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoImJsYWNrIiwgInJlZCIpKQpzY25fbXV0d3QKc2NuX211dHd0X2NsaWNreSA8LSBnZ3Bsb3RseV91cmwoCiAgc2NuX211dHd0LCAic2NuX211dHd0Lmh0bWwiLCB0aXRsZT0ic2NuIGV4cHJlc3Npb24sIG11dCB2cy4gd3QuIiwKICB1cmxfZGF0YT0iaHR0cDovL3VzZWFzdC5lbnNlbWJsLm9yZy9NdXNfbXVzY3VsdXMvR2VuZS9TdW1tYXJ5P2c9e2lkc30iKQpgYGAKCiMjIEF4b24gdHJhbnNsYXRvbWUgc3BlY2lmaWMKCmBgYHtyIGF4b25fdHJhbnNsYXRvbWVfcGxvdH0KIyMgIHgtYXhpczogbm9ybWRsZ25fdnNfbm9ybXJldCBvciBub3JtcmV0X3ZzX25vcm1kbGduLAojIyAgICAgICAgICAgICAgXl5eXgojIyAgeS1heGlzOiBkbGdud3QtcmV0d3QgKGJhc2VsaW5lIGRsZ24gLSBiYXNlbGluZSByZXRpbmEpCnBsb3R0ZWQgPC0gYXMuZGF0YS5mcmFtZShwYWlyX210cnhbLCBjKCJub3JtZGxnbl92c19ub3JtcmV0IiwgInd0X2RsZ25yZXQiKV0pCnJlZF9pZHggPC0gbm9ybXJldCA+IDAKIyMgTm90ZSB0aGF0IHRoaXMgb3JkZXIgaXMgb3Bwb3NpdGUgb2YgYWJvdmUuCnBsb3R0ZWRbLCAiY29sb3IiXSA8LSBpZmVsc2UocmVkX2lkeCwgImJsYWNrIiwgInJlZCIpCnBsb3R0ZWRbWyJsYWJlbCJdXSA8LSByb3duYW1lcyhwbG90dGVkKQpheG9uX3RyYW5zX3JldF90YXJnZXQgPC0gZ2dwbG90KAogIHBsb3R0ZWQsCiAgYWVzX3N0cmluZyh4PSJub3JtZGxnbl92c19ub3JtcmV0IiwgeT0id3RfZGxnbnJldCIsIGxhYmVsPSJsYWJlbCIsIGNvbG9yPSJjb2xvciIpKSArCiAgZ2VvbV9wb2ludChhbHBoYT0wLjUpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoImJsYWNrIiwgInJlZCIpKQpheG9uX3RyYW5zX3JldF90YXJnZXQKYXhvbl90cmFuc19yZXRfdGFyZ2V0X2NsaWNreSA8LSBnZ3Bsb3RseV91cmwoCiAgYXhvbl90cmFuc19yZXRfdGFyZ2V0LCAiYXhvbl90cmFuc19yZXRfdGFyZ2V0Lmh0bWwiLCB0aXRsZT0iQXhvbiB0cmFuc2xhdG9tZSwgcmV0aW5hIHRhcmdldC4iLAogIHVybF9kYXRhPSJodHRwOi8vdXNlYXN0LmVuc2VtYmwub3JnL011c19tdXNjdWx1cy9HZW5lL1N1bW1hcnk/Zz17aWRzfSIpCmBgYAoKIyMgRExHTiB0cmFuc2xhdG9tZSB3cnQuIFJldGluYSB0cmFuc2xhdG9tZQoKYGBge3IgZGxnbl90cmFuc2xhdG9tZV9wbG90fQpwbG90dGVkIDwtIGFzLmRhdGEuZnJhbWUocGFpcl9tdHJ4WywgYygibm9ybXJldCIsICJub3JtZGxnbiIpXSkKcGxvdHRlZFtbImxhYmVsIl1dIDwtIHJvd25hbWVzKHBsb3R0ZWQpCnBsb3R0ZWRbWyJjb2xvciJdXSA8LSAiYmxhY2siCm5vcm1yZXRfbm9ybWRsZ24gPC0gZ2dwbG90KAogIHBsb3R0ZWQsCiAgYWVzX3N0cmluZyh4PSJub3JtcmV0IiwgeT0ibm9ybWRsZ24iLCBsYWJlbD0ibGFiZWwiLCBjb2xvcj0iY29sb3IiKSkgKwogIGdlb21fcG9pbnQoYWxwaGE9MC41KSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCJibGFjayIsICJyZWQiKSkKbm9ybXJldF9ub3JtZGxnbgpub3JtcmV0X25vcm1kbGduX2NsaWNreSA8LSBnZ3Bsb3RseV91cmwoCiAgbm9ybXJldF9ub3JtZGxnbiwgIm5vcm1yZXRfbm9ybWRsZ24uaHRtbCIsIHRpdGxlPSJOb3JtYWwgcmV0aW5hIHRyYW5zbGF0b21lIHZzIG5vcm1hbCBkbGduIHRyYW5zbGF0b21lLiIsCiAgdXJsX2RhdGE9Imh0dHA6Ly91c2Vhc3QuZW5zZW1ibC5vcmcvTXVzX211c2N1bHVzL0dlbmUvU3VtbWFyeT9nPXtpZHN9IikKYGBgCgojIyBrb3JldCBrb2RsZ24KCmBgYHtyIGtvcmV0X2tvZGxnbl9zb21ldGhpbmdzb21ldGhpbmdwbG90fQpwbG90dGVkIDwtIGFzLmRhdGEuZnJhbWUocGFpcl9tdHJ4WywgYygia29yZXQiLCAia29kbGduIildKQpwbG90dGVkW1sibGFiZWwiXV0gPC0gcm93bmFtZXMocGxvdHRlZCkKcGxvdHRlZFtbImNvbG9yIl1dIDwtICJibGFjayIKa29yZXRfa29kbGduIDwtIGdncGxvdCgKICBwbG90dGVkLAogIGFlc19zdHJpbmcoeD0ia29yZXQiLCB5PSJrb2RsZ24iLCBsYWJlbD0ibGFiZWwiLCBjb2xvcj0iY29sb3IiKSkgKwogIGdlb21fcG9pbnQoYWxwaGE9MC41KSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCJibGFjayIsICJyZWQiKSkKa29yZXRfa29kbGduCmtvcmV0X2tvZGxnbl9jbGlja3kgPC0gZ2dwbG90bHlfdXJsKAogIGtvcmV0X2tvZGxnbiwgImtvcmV0X2tvZGxnbi5odG1sIiwgdGl0bGU9IktPIHJldGluYSB0cmFuc2xhdG9tZSB2cyBLTyBkbGduIHRyYW5zbGF0b21lLiIsCiAgdXJsX2RhdGE9Imh0dHA6Ly91c2Vhc3QuZW5zZW1ibC5vcmcvTXVzX211c2N1bHVzL0dlbmUvU3VtbWFyeT9nPXtpZHN9IikKYGAKCiMjIEtPIFJldGluYSB2cyBLTyBTQ04KCmBgYHtyIGtvcmV0X2tvc2NuX3Bsb3RfcmF3cn0KcGxvdHRlZCA8LSBhcy5kYXRhLmZyYW1lKHBhaXJfbXRyeFssIGMoImtvcmV0IiwgImtvc2NuIildKQpwbG90dGVkW1sibGFiZWwiXV0gPC0gcm93bmFtZXMocGxvdHRlZCkKcGxvdHRlZFtbImNvbG9yIl1dIDwtICJibGFjayIKa29yZXRfa29zY24gPC0gZ2dwbG90KAogIHBsb3R0ZWQsCiAgYWVzX3N0cmluZyh4PSJrb3JldCIsIHk9Imtvc2NuIiwgbGFiZWw9ImxhYmVsIiwgY29sb3I9ImNvbG9yIikpICsKICBnZW9tX3BvaW50KGFscGhhPTAuNSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygiYmxhY2siLCAicmVkIikpCmtvcmV0X2tvc2NuCmtvcmV0X2tvc2NuX2NsaWNreSA8LSBnZ3Bsb3RseV91cmwoCiAga29yZXRfa29zY24sICJrb3JldF9rb3Njbi5odG1sIiwgdGl0bGU9IktPIHJldGluYSB0cmFuc2xhdG9tZSB2cyBLTyBzY24gdHJhbnNsYXRvbWUuIiwKICB1cmxfZGF0YT0iaHR0cDovL3VzZWFzdC5lbnNlbWJsLm9yZy9NdXNfbXVzY3VsdXMvR2VuZS9TdW1tYXJ5P2c9e2lkc30iKQpgYGAKCiMjIE5vcm0gZGxnbiBrbyBkbGduCgpgYGB7ciBub3JtZGxnbl9rb2RsZ25fcGxvdH0KcGxvdHRlZCA8LSBhcy5kYXRhLmZyYW1lKHBhaXJfbXRyeFssIGMoIm5vcm1kbGduIiwgImtvZGxnbiIpXSkKcGxvdHRlZFtbImxhYmVsIl1dIDwtIHJvd25hbWVzKHBsb3R0ZWQpCnBsb3R0ZWRbWyJjb2xvciJdXSA8LSAiYmxhY2siCm5vcm1kbGduX2tvZGxnbiA8LSBnZ3Bsb3QoCiAgcGxvdHRlZCwKICBhZXNfc3RyaW5nKHg9Im5vcm1kbGduIiwgeT0ia29kbGduIiwgbGFiZWw9ImxhYmVsIiwgY29sb3I9ImNvbG9yIikpICsKICBnZW9tX3BvaW50KGFscGhhPTAuNSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygiYmxhY2siLCAicmVkIikpCm5vcm1kbGduX2tvZGxnbgpub3JtZGxnbl9rb2RsZ25fY2xpY2t5IDwtIGdncGxvdGx5X3VybCgKICBub3JtZGxnbl9rb2RsZ24sICJub3JtZGxnbl9rb2RsZ24uaHRtbCIsIHRpdGxlPSJOb3JtYWwgZGxnbiB0cmFuc2xhdG9tZSB2cyBLTyBkbGduIHRyYW5zbGF0b21lLiIsCiAgdXJsX2RhdGE9Imh0dHA6Ly91c2Vhc3QuZW5zZW1ibC5vcmcvTXVzX211c2N1bHVzL0dlbmUvU3VtbWFyeT9nPXtpZHN9IikKYGBgCgojIyBOb3JtIHJldCB2cyBrbyByZXQKCmBgYHtyIG5vcm1fcmV0X2tvX3JldF9wbG90fQpwbG90dGVkIDwtIGFzLmRhdGEuZnJhbWUocGFpcl9tdHJ4WywgYygibm9ybXJldCIsICJrb3JldCIpXSkKcGxvdHRlZFtbImxhYmVsIl1dIDwtIHJvd25hbWVzKHBsb3R0ZWQpCnBsb3R0ZWRbWyJjb2xvciJdXSA8LSAiYmxhY2siCm5vcm1yZXRfa29yZXQgPC0gZ2dwbG90KAogIHBsb3R0ZWQsCiAgYWVzX3N0cmluZyh4PSJub3JtcmV0IiwgeT0ia29yZXQiLCBsYWJlbD0ibGFiZWwiLCBjb2xvcj0iY29sb3IiKSkgKwogIGdlb21fcG9pbnQoYWxwaGE9MC41KSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCJibGFjayIsICJyZWQiKSkKbm9ybXJldF9rb3JldApub3JtcmV0X2tvcmV0X2NsaWNreSA8LSBnZ3Bsb3RseV91cmwoCiAgbm9ybXJldF9rb3JldCwgIm5vcm1yZXRfa29yZXQuaHRtbCIsIHRpdGxlPSJOb3JtYWwgcmV0aW5hIHRyYW5zbGF0b21lIHZzIEtPIHJldGluYSB0cmFuc2xhdG9tZS4iLAogIHVybF9kYXRhPSJodHRwOi8vdXNlYXN0LmVuc2VtYmwub3JnL011c19tdXNjdWx1cy9HZW5lL1N1bW1hcnk/Zz17aWRzfSIpCmBgYAoKIyMgcm9yCgpgYGB7ciByb3JfcGxvdH0KcGxvdHRlZCA8LSBhcy5kYXRhLmZyYW1lKHBhaXJfbXRyeFssIGMoIm5vcm1yZXRfdnNfbm9ybWRsZ24iLCAia29yZXRfdnNfa29kbGduIildKQpwbG90dGVkW1sibGFiZWwiXV0gPC0gcm93bmFtZXMocGxvdHRlZCkKcGxvdHRlZFtbImNvbG9yIl1dIDwtICJibGFjayIKbm9ybWFsX2tvX2F4b25fdHJhbnNsYXRvbWUgPC0gZ2dwbG90KAogIHBsb3R0ZWQsCiAgYWVzX3N0cmluZyh4PSJub3JtcmV0X3ZzX25vcm1kbGduIiwgeT0ia29yZXRfdnNfa29kbGduIiwgbGFiZWw9ImxhYmVsIiwgY29sb3I9ImNvbG9yIikpICsKICBnZW9tX3BvaW50KGFscGhhPTAuNSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygiYmxhY2siLCAicmVkIikpCm5vcm1hbF9rb19heG9uX3RyYW5zbGF0b21lCm5vcm1hbF9rb19heG9uX3RyYW5zbGF0b21lX2NsaWNreSA8LSBnZ3Bsb3RseV91cmwoCiAgbm9ybWFsX2tvX2F4b25fdHJhbnNsYXRvbWUsICJub3JtYWxfa29fYXhvbl90cmFuc2xhdG9tZS5odG1sIiwKICB0aXRsZT0iTm9ybWFsIHJldGluYSBrbyBheG9uIHRyYW5zbGF0b21lLiIsCiAgdXJsX2RhdGE9Imh0dHA6Ly91c2Vhc3QuZW5zZW1ibC5vcmcvTXVzX211c2N1bHVzL0dlbmUvU3VtbWFyeT9nPXtpZHN9IikKYGBgCgojIFRyYW5zbGF0b21lIGxldmVsIGNvbXBhcmlzb25zCgojIyBNYWtlIGEgZ2VuZXJpYyBwbG90dGVyIGZvciB0aGlzIHN0dWZmLgoKYGBge3IgZ2VuZXJpY19wbG90dGVyfQp0cmFuc2xhdG9tZV9wbG90dGVyIDwtIGZ1bmN0aW9uKHBhaXJfbXRyeCwgeF9heGlzPSJrb3JldCIsIHlfYXhpcz0ia29zY24iLCBsZmM9TlVMTCwgZmM9TlVMTCwgbGluZXdpZHRoPTEuNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cF9jb2xvcj0icmVkIiwgZG93bl9jb2xvcj0iIzA5ODUzNCIsIGxpbmVfY29sb3I9IiNmY2JhMDMiLCBhbHBoYT0wLjUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeF9saW1pdD1jKC03LCA3KSwgeV9saW1pdD1jKC03LCA3KSkgewogIGlmIChpcy5udWxsKGZjKSAmIGlzLm51bGwobGZjKSkgewogICAgbWVzc2FnZSgiTm8gZmMvbGZjIHdhcyBwcm92aWRlZCwgZGVmYXVsdGluZyB0byAxMCBmb2xkLiIpCiAgICBsZmMgPC0gbG9nMigxMCkKICB9IGVsc2UgaWYgKGlzLm51bGwobGZjKSkgewogICAgbGZjIDwtIGxvZzIoZmMpCiAgfQogIHBsb3R0ZWQgPC0gYXMuZGF0YS5mcmFtZShwYWlyX210cnhbLCBjKHhfYXhpcywgeV9heGlzKV0pCiAgbmFfaWR4IDwtIGlzLm5hKHBsb3R0ZWQpCiAgcGxvdHRlZFtuYV9pZHhdIDwtIDAKICB1cF9pZHggPC0gcGxvdHRlZFssIHlfYXhpc10gLSBwbG90dGVkWywgeF9heGlzXSA+PSBsZmMKICBkb3duX2lkeCA8LSBwbG90dGVkWywgeV9heGlzXSAtIHBsb3R0ZWRbLCB4X2F4aXNdIDw9IChsZmMgKiAtMSkKICB1cF9nZW5lcyA8LSByb3duYW1lcyhwbG90dGVkKVt1cF9pZHhdCiAgZG93bl9nZW5lcyA8LSByb3duYW1lcyhwbG90dGVkKVtkb3duX2lkeF0KICAjIyBOb3RlIHRoYXQgdGhpcyBvcmRlciBpcyBvcHBvc2l0ZSBvZiBhYm92ZS4KICBwbG90dGVkW1siY29sb3IiXV0gPC0gImJsYWNrIgogIHBsb3R0ZWRbdXBfaWR4LCAiY29sb3IiXSA8LSB1cF9jb2xvcgogIHBsb3R0ZWRbZG93bl9pZHgsICJjb2xvciJdIDwtIGRvd25fY29sb3IKICBwbG90dGVkW1siY29sb3IiXV0gPC0gYXMuZmFjdG9yKHBsb3R0ZWRbWyJjb2xvciJdXSkKICBsZXZlbHMocGxvdHRlZFtbImNvbG9yIl1dKSA8LSBjKCJibGFjayIsIHVwX2NvbG9yLCBkb3duX2NvbG9yKQogIHBsdCA8LSBnZ3Bsb3QyOjpnZ3Bsb3QocGxvdHRlZCwgYWVzX3N0cmluZyh4PXhfYXhpcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeT15X2F4aXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yPSJjb2xvciIpKSArCiAgICBnZW9tX2FibGluZShzaXplPTEuMSwgc2xvcGU9MSwgaW50ZXJjZXB0PWxmYywgY29sb3I9Im9yYW5nZSIpICsKICAgIGdlb21fYWJsaW5lKHNpemU9MS4xLCBzbG9wZT0xLCBpbnRlcmNlcHQ9KC0xICogbGZjKSwgY29sb3I9Im9yYW5nZSIpICsKICAgIHNjYWxlX3hfY29udGludW91cyhsaW1pdHM9Yyh4X2xpbWl0KSkgKwogICAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cz1jKHlfbGltaXQpKSArCiAgICBnZW9tX3BvaW50KGFscGhhPWFscGhhKSArCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoZG93bl9jb2xvciwgImJsYWNrIiwgdXBfY29sb3IpKQogIHJldGxpc3QgPC0gbGlzdCgKICAgICJtdHJ4IiA9IHBsb3R0ZWQsCiAgICAidXBzIiA9IHVwX2dlbmVzLAogICAgImRvd25zIiA9IGRvd25fZ2VuZXMsCiAgICAicGxvdCIgPSBwbHQpCiAgcmV0dXJuKHJldGxpc3QpCn0KYGBgCgoxLiBYLWF4aXM6IEFsd2F5cyByZXRpbmEuCjIuIFktYXhpczogQWx3YXlzIGEgdGFyZ2V0IHRpc3N1ZS4KCkZpcnN0IHBsb3Q6IEtPIHNjbiB0cmFuc2xhdG9tZSBvbiB5IGF4aXMgdnMuIEtPIHJldGluYSB0cmFuc2xhdG9tZSBvbiB4IGF4aXMuCgojIyBTY24ga25vY2tvdXQgdHJhbnNsYXRvbWUgdnMgcmV0aW5hIGtub2Nrb3V0IHRyYW5zbGF0b21lLgoKYGBge3Igc2NuX2tvX3dydF9yZXRpbmFfa29fdHJhbnNsYXRvbWVfZ3Byb2ZpbGVyfQpzY25rb193cnRfcmV0a29fdHJhbnNsYXRvbWUgPC0gdHJhbnNsYXRvbWVfcGxvdHRlcihwYWlyX210cngpCnNjbmtvX3dydF9yZXRrb190cmFuc2xhdG9tZSRwbG90CnNjbmtvX3dydF9yZXRrb191cF9nbyA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHNpZ19nZW5lcz1zY25rb193cnRfcmV0a29fdHJhbnNsYXRvbWUkdXBzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcGVjaWVzPSJtbXVzY3VsdXMiKQpzY25rb193cnRfcmV0a29fZG93bl9nbyA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHNpZ19nZW5lcz1zY25rb193cnRfcmV0a29fdHJhbnNsYXRvbWUkZG93bnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BlY2llcz0ibW11c2N1bHVzIikKc2Nua29fd3J0X3JldGtvX2Rvd25fZ28kZ28Kc2Nua29fd3J0X3JldGtvX2Rvd25fZ28ka2VnZwpzY25rb193cnRfcmV0a29fZG93bl9nbyRjb3J1bQpgYGAKCiMjIGRsZ24gbm9ybWFsIHRyYW5zbGF0b21lIHZzIHJldGluYSBub3JtYWwgdHJhbnNsYXRvbWUuCgpgYGB7ciBkbGduX25vcm1fdHJhbnNsYXRvbWVfdnNfcmV0X25vcm1hbF90cmFuc2xhdG9tZV9ncHJvZmlsZXJ9CmRsZ25ub3JtX3dydF9yZXRub3JtX3RyYW5zbGF0b21lIDwtIHRyYW5zbGF0b21lX3Bsb3R0ZXIocGFpcl9tdHJ4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhfYXhpcz0ibm9ybXJldCIsIHlfYXhpcz0ibm9ybWRsZ24iKQpkbGdubm9ybV93cnRfcmV0bm9ybV90cmFuc2xhdG9tZSRwbG90CmRsZ25ub3JtX3dydF9yZXRub3JtX3VwX2dvIDwtIHNpbXBsZV9ncHJvZmlsZXIoc2lnX2dlbmVzPWRsZ25ub3JtX3dydF9yZXRub3JtX3RyYW5zbGF0b21lJHVwcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcGVjaWVzPSJtbXVzY3VsdXMiKQpkbGdubm9ybV93cnRfcmV0bm9ybV9kb3duX2dvIDwtIHNpbXBsZV9ncHJvZmlsZXIoc2lnX2dlbmVzPWRsZ25ub3JtX3dydF9yZXRub3JtX3RyYW5zbGF0b21lJGRvd25zLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BlY2llcz0ibW11c2N1bHVzIikKZGxnbm5vcm1fd3J0X3JldG5vcm1fZG93bl9nbyRnbwpkbGdubm9ybV93cnRfcmV0bm9ybV9kb3duX2dvJHB2YWx1ZV9wbG90cyRicHBfcGxvdF9vdmVyCmRsZ25ub3JtX3dydF9yZXRub3JtX2Rvd25fZ28kcHZhbHVlX3Bsb3RzJGNjcF9wbG90X292ZXIKYGBgCgojIyBkbGduIGtub2Nrb3V0IHRyYW5zbGF0b21lIHZzIHJldGluYSBrbm9ja291dCB0cmFuc2xhdG9tZS4KCmBgYHtyIGRsZ25fa29fdHJhbnNsYXRvbWVfdnNfcmV0aW5hX2tvX3RyYW5zbGF0b21lX2dwcm9maWxlcn0KZGxnbmtvX3dydF9yZXRrb190cmFuc2xhdG9tZSA8LSB0cmFuc2xhdG9tZV9wbG90dGVyKHBhaXJfbXRyeCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhfYXhpcz0ia29yZXQiLCB5X2F4aXM9ImtvZGxnbiIpCmRsZ25rb193cnRfcmV0a29fdHJhbnNsYXRvbWUkcGxvdApkbGdua29fd3J0X3JldGtvX3VwX2dvIDwtIHNpbXBsZV9ncHJvZmlsZXIoc2lnX2dlbmVzPWRsZ25rb193cnRfcmV0a29fdHJhbnNsYXRvbWUkdXBzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BlY2llcz0ibW11c2N1bHVzIikKZGxnbmtvX3dydF9yZXRrb191cF9nbyRnbwpkbGdua29fd3J0X3JldGtvX3VwX2dvJGtlZ2cKZGxnbmtvX3dydF9yZXRrb191cF9nbyRyZWFjCmRsZ25rb193cnRfcmV0a29fZG93bl9nbyA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHNpZ19nZW5lcz1kbGdua29fd3J0X3JldGtvX3RyYW5zbGF0b21lJGRvd25zLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcGVjaWVzPSJtbXVzY3VsdXMiKQpkbGdua29fd3J0X3JldGtvX2Rvd25fZ28kZ28KZGxnbmtvX3dydF9yZXRrb19kb3duX2dvJGtlZ2cKZGxnbmtvX3dydF9yZXRrb19kb3duX2dvJHJlYWMKYGBgCgojIyBOb3JtYWwgZGxnbiB0cmFuc2xhdG9tZSB2cyBrbm9ja291dCBkbGduIHRyYW5zbGF0b21lLgoKYGBge3Igbm9ybV9kbGduX3RyYW5zbGF0b21lX3ZzX2tvX2RsZ25fdHJhbnNsYXRvbWVfZ2Zwcm9maWxlcn0KZGxnbm5vcm1fd3J0X2RsZ25rb190cmFuc2xhdG9tZSA8LSB0cmFuc2xhdG9tZV9wbG90dGVyKHBhaXJfbXRyeCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhfYXhpcz0ibm9ybWRsZ24iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeV9heGlzPSJrb2RsZ24iKQpkbGdubm9ybV93cnRfZGxnbmtvX3RyYW5zbGF0b21lJHBsb3QKZGxnbm5vcm1fd3J0X2RsZ25rb191cF9nbyA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHNpZ19nZW5lcz1kbGdubm9ybV93cnRfZGxnbmtvX3RyYW5zbGF0b21lJHVwcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwZWNpZXM9Im1tdXNjdWx1cyIpCmRsZ25ub3JtX3dydF9kbGdua29fZG93bl9nbyA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHNpZ19nZW5lcz1kbGdubm9ybV93cnRfZGxnbmtvX3RyYW5zbGF0b21lJGRvd25zLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcGVjaWVzPSJtbXVzY3VsdXMiKQpkbGdubm9ybV93cnRfZGxnbmtvX2Rvd25fZ28kZ28KYGBgCgojIyBkbGduIGtub2Nrb3V0IHRyYW5zbGF0b21lIHZzLiBzY24ga25vY2tvdXQgdHJhbnNsYXRvbWUuCgpgYGB7ciBkbGduX2tvX3RyYW5zbGF0b21lX3ZzX3Njbl9rb190cmFuc2xhdG9tZV9ncHJvZmlsZXJ9CmRsZ25rb193cnRfc2Nua29fdHJhbnNsYXRvbWUgPC0gdHJhbnNsYXRvbWVfcGxvdHRlcihwYWlyX210cngsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4X2F4aXM9ImtvZGxnbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5X2F4aXM9Imtvc2NuIikKZGxnbmtvX3dydF9zY25rb190cmFuc2xhdG9tZSRwbG90CmRsZ25rb193cnRfc2Nua29fdXBfZ28gPC0gc2ltcGxlX2dwcm9maWxlcihzaWdfZ2VuZXM9ZGxnbmtvX3dydF9zY25rb190cmFuc2xhdG9tZSR1cHMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcGVjaWVzPSJtbXVzY3VsdXMiKQpkbGdua29fd3J0X3NjbmtvX3VwX2dvJGdvCmRsZ25rb193cnRfc2Nua29fdXBfZ28kcHZhbHVlX3Bsb3RzJGJwcF9wbG90X292ZXIKZGxnbmtvX3dydF9zY25rb19kb3duX2dvIDwtIHNpbXBsZV9ncHJvZmlsZXIoc2lnX2dlbmVzPWRsZ25rb193cnRfc2Nua29fdHJhbnNsYXRvbWUkZG93bnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwZWNpZXM9Im1tdXNjdWx1cyIpCmRsZ25rb193cnRfc2Nua29fZG93bl9nbyRnbwpgYGAKCiMgU29tZSBwaWN0dXJlcwoKQXMgSSB1bmRlcnN0YW5kIGl0LCB0aGVyZSBpcyBzb21lIGludGVyZXN0IGluIGFuIG9udG9sb2d5IHNlYXJjaCB1c2luZyB0aGUgcmF0aW8gb2YgcmF0aW9zLgoKYGBge3Igb3RoZXJfY29udHJhc3RzfQpyb3IgPC0gbm9ybWtvX3JldGRsZ24KdXBfaWR4IDwtIHJvciA+PSAxCmRvd25faWR4IDwtIHJvciA8PSAtMQpyb3JfdXAgPC0gcm9yW3VwX2lkeF0KbGVuZ3RoKHJvcl91cCkKcm9yX2Rvd24gPC0gcm9yW2Rvd25faWR4XQpsZW5ndGgocm9yX2Rvd24pCgpyb3JfZ3Byb2ZpbGVyX3VwIDwtIHNpbXBsZV9ncHJvZmlsZXIoCiAgc2lnX2dlbmVzPXJvcl91cCwgc3BlY2llcz0ibW11c2N1bHVzIiwKICBleGNlbD1nbHVlOjpnbHVlKCJleGNlbC97cnVuZGF0ZX1tbV9yb3JfZ3Bmb2lsZXJfdXAtdnt2ZXJ9Lnhsc3giKSkKcm9yX2dwcm9maWxlcl91cCRwdmFsdWVfcGxvdHMkbWZwX3Bsb3Rfb3Zlcgpyb3JfZ3Byb2ZpbGVyX3VwJHB2YWx1ZV9wbG90cyRicHBfcGxvdF9vdmVyCnJvcl9ncHJvZmlsZXJfdXAkcHZhbHVlX3Bsb3RzJGNjcF9wbG90X292ZXIKcm9yX2dwcm9maWxlcl91cCRwdmFsdWVfcGxvdHMkdGZfcGxvdF9vdmVyCnJvcl9ncHJvZmlsZXJfdXAkcHZhbHVlX3Bsb3RzJGhwX3Bsb3Rfb3ZlcgoKcm9yX2dwcm9maWxlcl9kb3duIDwtIHNpbXBsZV9ncHJvZmlsZXIoCiAgc2lnX2dlbmVzPXJvcl9kb3duLCBzcGVjaWVzPSJtbXVzY3VsdXMiLAogIGV4Y2VsPWdsdWU6OmdsdWUoImV4Y2VsL3tydW5kYXRlfW1tX3Jvcl9ncGZvaWxlcl9kb3duLXZ7dmVyfS54bHN4IikpCnJvcl9ncHJvZmlsZXJfZG93biRwdmFsdWVfcGxvdHMkbWZwX3Bsb3Rfb3Zlcgpyb3JfZ3Byb2ZpbGVyX2Rvd24kcHZhbHVlX3Bsb3RzJGJwcF9wbG90X292ZXIKcm9yX2dwcm9maWxlcl9kb3duJHB2YWx1ZV9wbG90cyRyZWFjdG9tZV9wbG90X292ZXIKcm9yX2dwcm9maWxlcl9kb3duJHB2YWx1ZV9wbG90cyRjY3BfcGxvdF9vdmVyCnJvcl9ncHJvZmlsZXJfZG93biRwdmFsdWVfcGxvdHMkdGZfcGxvdF9vdmVyCmBgYAoKYGBge3Igc2F2ZW1lLCBldmFsPUZBTFNFfQpwYW5kZXI6OnBhbmRlcihzZXNzaW9uSW5mbygpKQptZXNzYWdlKHBhc3RlMCgiVGhpcyBpcyBocGdsdG9vbHMgY29tbWl0OiAiLCBnZXRfZ2l0X2NvbW1pdCgpKSkKdGhpc19zYXZlIDwtIHBhc3RlMChnc3ViKHBhdHRlcm49IlxcLlJtZCIsIHJlcGxhY2U9IiIsIHg9cm1kX2ZpbGUpLCAiLXYiLCB2ZXIsICIucmRhLnh6IikKbWVzc2FnZShwYXN0ZTAoIlNhdmluZyB0byAiLCB0aGlzX3NhdmUpKQp0bXAgPC0gc20oc2F2ZW1lKGZpbGVuYW1lPXRoaXNfc2F2ZSkpCmBgYAoKCmBgYHtyIGxvYWRtZSwgZXZhbD1GQUxTRX0KbG9hZG1lKGZpbGVuYW1lPXRoaXNfc2F2ZSkKYGBgCg==