1 M. musculus

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

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!

## Reading the sample metadata.
## The sample definitions comprises: 8 rows(samples) and 8 columns(metadata fields).
## Reading count tables.
## Reading count tables with read.table().
## /mnt/sshfs/cbcbsub/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/cbcbsub/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/cbcbsub/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/cbcbsub/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/cbcbsub/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/cbcbsub/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/cbcbsub/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/cbcbsub/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.
## Finished reading count tables.
## Matched 25554 annotations and counts.
## Bringing together the count matrix and gene information.
## Some annotations were lost in merging, setting them to 'undefined'.
## The final expressionset has 25783 rows and 8 columns.

1.4 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.4.1 Initial salmon plots

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

1.4.2 Initial hisat2 plots

## 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 12233 low-count genes (13550 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 19 values equal to 0, adding 1 to the matrix.
## Step 5: not doing batch correction.

1.5 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.5.1 With salmon

## 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.
## Plotting a PCA before surrogates/batch inclusion.
## Not putting labels on the plot.
## Assuming no batch in model for testing pca.
## Not putting labels on the plot.
## Finished running DE analyses, collecting outputs.
## Comparing analyses.

1.6 Set up for initial analysis

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

1.6.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:

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.

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.

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

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.

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

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

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

{r{r add_matrix_de, fig.show=“hide”} mm_tables <- sm(combine_de_tables( mm_de_sa, extra_annot=pair_mtrx, excel=glue::glue(“excel/{rundate}mm_salmon_tables-v{ver}.xlsx”))) ```

2 Plots of interesting comparisons

## Warning: Removed 37 rows containing missing values (geom_point).

## Warning: Removed 37 rows containing missing values (geom_point).

3 Translatome level comparisons

3.1 Make a generic plotter for this stuff.

  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.

## No fc/lfc was provided, defaulting to 10 fold.
## Warning: Removed 1 rows containing missing values (geom_point).

## Performing gProfiler GO search of 70 genes against mmusculus.
## GO search found 0 hits.
## Performing gProfiler KEGG search of 70 genes against mmusculus.
## KEGG search found 0 hits.
## Performing gProfiler REAC search of 70 genes against mmusculus.
## REAC search found 0 hits.
## Performing gProfiler MI search of 70 genes against mmusculus.
## MI search found 0 hits.
## Performing gProfiler TF search of 70 genes against mmusculus.
## TF search found 0 hits.
## Performing gProfiler CORUM search of 70 genes against mmusculus.
## CORUM search found 0 hits.
## Performing gProfiler HP search of 70 genes against mmusculus.
## HP search found 0 hits.
## Performing gProfiler GO search of 42 genes against mmusculus.
## GO search found 2 hits.
## Performing gProfiler KEGG search of 42 genes against mmusculus.
## KEGG search found 1 hits.
## Performing gProfiler REAC search of 42 genes against mmusculus.
## REAC search found 0 hits.
## Performing gProfiler MI search of 42 genes against mmusculus.
## MI search found 0 hits.
## Performing gProfiler TF search of 42 genes against mmusculus.
## TF search found 10 hits.
## Performing gProfiler CORUM search of 42 genes against mmusculus.
## CORUM search found 1 hits.
## Performing gProfiler HP search of 42 genes against mmusculus.
## HP search found 0 hits.
## No fc/lfc was provided, defaulting to 10 fold.
## Warning: Removed 1 rows containing missing values (geom_point).

## Performing gProfiler GO search of 59 genes against mmusculus.
## GO search found 3 hits.
## Performing gProfiler KEGG search of 59 genes against mmusculus.
## KEGG search found 0 hits.
## Performing gProfiler REAC search of 59 genes against mmusculus.
## REAC search found 2 hits.
## Performing gProfiler MI search of 59 genes against mmusculus.
## MI search found 0 hits.
## Performing gProfiler TF search of 59 genes against mmusculus.
## TF search found 0 hits.
## Performing gProfiler CORUM search of 59 genes against mmusculus.
## CORUM search found 1 hits.
## Performing gProfiler HP search of 59 genes against mmusculus.
## HP search found 0 hits.
## Performing gProfiler GO search of 69 genes against mmusculus.
## GO search found 14 hits.
## Performing gProfiler KEGG search of 69 genes against mmusculus.
## KEGG search found 1 hits.
## Performing gProfiler REAC search of 69 genes against mmusculus.
## REAC search found 3 hits.
## Performing gProfiler MI search of 69 genes against mmusculus.
## MI search found 0 hits.
## Performing gProfiler TF search of 69 genes against mmusculus.
## TF search found 4 hits.
## Performing gProfiler CORUM search of 69 genes against mmusculus.
## CORUM search found 1 hits.
## Performing gProfiler HP search of 69 genes against mmusculus.
## HP search found 47 hits.
##    query.number significant  p.value term.size query.size overlap.size
## 1             1        TRUE 1.39e-02       115         23            4
## 2             1        TRUE 1.34e-02       114         23            4
## 3             1        TRUE 3.77e-04        47         23            4
## 4             1        TRUE 1.67e-02        36         23            3
## 5             1        TRUE 2.11e-02       366         45            7
## 6             1        TRUE 1.97e-02       362         45            7
## 7             1        TRUE 1.97e-02       362         45            7
## 8             1        TRUE 2.65e-08       142         45            9
## 9             1        TRUE 2.04e-08       138         45            9
## 10            1        TRUE 1.32e-03       148         45            6
## 11            1        TRUE 1.39e-02       126         45            5
## 12            1        TRUE 3.64e-03        96         45            5
## 13            1        TRUE 3.45e-03        95         45            5
## 14            1        TRUE 8.05e-04        71         45            5
##    precision recall    term.id domain subgraph.number
## 1      0.174  0.035 GO:0009581     BP               2
## 2      0.174  0.035 GO:0009582     BP               2
## 3      0.174  0.085 GO:0009583     BP               2
## 4      0.130  0.083 GO:0009584     BP               2
## 5      0.156  0.019 GO:0048880     BP               4
## 6      0.156  0.019 GO:0150063     BP               4
## 7      0.156  0.019 GO:0001654     BP               4
## 8      0.200  0.063 GO:0050953     BP               5
## 9      0.200  0.065 GO:0007601     BP               5
## 10     0.133  0.041 GO:0060041     BP               3
## 11     0.111  0.040 GO:0097730     CC               1
## 12     0.111  0.052 GO:0097731     CC               1
## 13     0.111  0.053 GO:0097733     CC               1
## 14     0.111  0.070 GO:0001750     CC               1
##                                term.name relative.depth
## 1         detection of external stimulus              1
## 2          detection of abiotic stimulus              1
## 3            detection of light stimulus              2
## 4             detection of visible light              3
## 5             sensory system development              1
## 6              visual system development              2
## 7                        eye development              1
## 8   sensory perception of light stimulus              1
## 9                      visual perception              2
## 10 retina development in camera-type eye              1
## 11                     non-motile cilium              1
## 12                 9+0 non-motile cilium              2
## 13             photoreceptor cell cilium              3
## 14           photoreceptor outer segment              4
##                                                                                                                                                                  intersection
## 1                                                                                                 ENSMUSG00000021804,ENSMUSG00000029491,ENSMUSG00000031293,ENSMUSG00000037446
## 2                                                                                                 ENSMUSG00000021804,ENSMUSG00000029491,ENSMUSG00000031293,ENSMUSG00000037446
## 3                                                                                                 ENSMUSG00000021804,ENSMUSG00000029491,ENSMUSG00000031293,ENSMUSG00000037446
## 4                                                                                                                    ENSMUSG00000021804,ENSMUSG00000031293,ENSMUSG00000037446
## 5                                        ENSMUSG00000021099,ENSMUSG00000023978,ENSMUSG00000029491,ENSMUSG00000031293,ENSMUSG00000037446,ENSMUSG00000048015,ENSMUSG00000071648
## 6                                        ENSMUSG00000021099,ENSMUSG00000023978,ENSMUSG00000029491,ENSMUSG00000031293,ENSMUSG00000037446,ENSMUSG00000048015,ENSMUSG00000071648
## 7                                        ENSMUSG00000021099,ENSMUSG00000023978,ENSMUSG00000029491,ENSMUSG00000031293,ENSMUSG00000037446,ENSMUSG00000048015,ENSMUSG00000071648
## 8  ENSMUSG00000021804,ENSMUSG00000023978,ENSMUSG00000025386,ENSMUSG00000029491,ENSMUSG00000031293,ENSMUSG00000037446,ENSMUSG00000041534,ENSMUSG00000053773,ENSMUSG00000071648
## 9  ENSMUSG00000021804,ENSMUSG00000023978,ENSMUSG00000025386,ENSMUSG00000029491,ENSMUSG00000031293,ENSMUSG00000037446,ENSMUSG00000041534,ENSMUSG00000053773,ENSMUSG00000071648
## 10                                                          ENSMUSG00000023978,ENSMUSG00000029491,ENSMUSG00000031293,ENSMUSG00000037446,ENSMUSG00000048015,ENSMUSG00000071648
## 11                                                                             ENSMUSG00000023978,ENSMUSG00000028777,ENSMUSG00000029491,ENSMUSG00000037446,ENSMUSG00000071648
## 12                                                                             ENSMUSG00000023978,ENSMUSG00000028777,ENSMUSG00000029491,ENSMUSG00000037446,ENSMUSG00000071648
## 13                                                                             ENSMUSG00000023978,ENSMUSG00000028777,ENSMUSG00000029491,ENSMUSG00000037446,ENSMUSG00000071648
## 14                                                                             ENSMUSG00000023978,ENSMUSG00000028777,ENSMUSG00000029491,ENSMUSG00000037446,ENSMUSG00000071648

## No fc/lfc was provided, defaulting to 10 fold.

## Performing gProfiler GO search of 78 genes against mmusculus.
## GO search found 2 hits.
## Performing gProfiler KEGG search of 78 genes against mmusculus.
## KEGG search found 3 hits.
## Performing gProfiler REAC search of 78 genes against mmusculus.
## REAC search found 2 hits.
## Performing gProfiler MI search of 78 genes against mmusculus.
## MI search found 0 hits.
## Performing gProfiler TF search of 78 genes against mmusculus.
## TF search found 2 hits.
## Performing gProfiler CORUM search of 78 genes against mmusculus.
## CORUM search found 2 hits.
## Performing gProfiler HP search of 78 genes against mmusculus.
## HP search found 0 hits.
## Performing gProfiler GO search of 51 genes against mmusculus.
## GO search found 4 hits.
## Performing gProfiler KEGG search of 51 genes against mmusculus.
## KEGG search found 9 hits.
## Performing gProfiler REAC search of 51 genes against mmusculus.
## REAC search found 2 hits.
## Performing gProfiler MI search of 51 genes against mmusculus.
## MI search found 0 hits.
## Performing gProfiler TF search of 51 genes against mmusculus.
## TF search found 0 hits.
## Performing gProfiler CORUM search of 51 genes against mmusculus.
## CORUM search found 0 hits.
## Performing gProfiler HP search of 51 genes against mmusculus.
## HP search found 0 hits.
##   query.number significant p.value term.size query.size overlap.size precision
## 1            1        TRUE 0.04480       319         12            4     0.333
## 2            1        TRUE 0.01250       194         14            4     0.286
## 3            1        TRUE 0.00675       166         14            4     0.286
## 4            1        TRUE 0.00161       116         14            4     0.286
##   recall    term.id domain subgraph.number
## 1  0.013 GO:0071496     BP               2
## 2  0.021 GO:0007249     BP               1
## 3  0.024 GO:0043122     BP               1
## 4  0.034 GO:0043123     BP               1
##                                                    term.name relative.depth
## 1                     cellular response to external stimulus              1
## 2                        I-kappaB kinase/NF-kappaB signaling              1
## 3          regulation of I-kappaB kinase/NF-kappaB signaling              1
## 4 positive regulation of I-kappaB kinase/NF-kappaB signaling              2
##                                                                  intersection
## 1 ENSMUSG00000026029,ENSMUSG00000026989,ENSMUSG00000027398,ENSMUSG00000032009
## 2 ENSMUSG00000026029,ENSMUSG00000027398,ENSMUSG00000032496,ENSMUSG00000035186
## 3 ENSMUSG00000026029,ENSMUSG00000027398,ENSMUSG00000032496,ENSMUSG00000035186
## 4 ENSMUSG00000026029,ENSMUSG00000027398,ENSMUSG00000032496,ENSMUSG00000035186
## No fc/lfc was provided, defaulting to 10 fold.

## Performing gProfiler GO search of 14 genes against mmusculus.
## GO search found 0 hits.
## Performing gProfiler KEGG search of 14 genes against mmusculus.
## KEGG search found 0 hits.
## Performing gProfiler REAC search of 14 genes against mmusculus.
## REAC search found 1 hits.
## Performing gProfiler MI search of 14 genes against mmusculus.
## MI search found 0 hits.
## Performing gProfiler TF search of 14 genes against mmusculus.
## TF search found 0 hits.
## Performing gProfiler CORUM search of 14 genes against mmusculus.
## CORUM search found 0 hits.
## Performing gProfiler HP search of 14 genes against mmusculus.
## HP search found 0 hits.
## Performing gProfiler GO search of 17 genes against mmusculus.
## GO search found 3 hits.
## Performing gProfiler KEGG search of 17 genes against mmusculus.
## KEGG search found 0 hits.
## Performing gProfiler REAC search of 17 genes against mmusculus.
## REAC search found 0 hits.
## Performing gProfiler MI search of 17 genes against mmusculus.
## MI search found 0 hits.
## Performing gProfiler TF search of 17 genes against mmusculus.
## TF search found 0 hits.
## Performing gProfiler CORUM search of 17 genes against mmusculus.
## CORUM search found 1 hits.
## Performing gProfiler HP search of 17 genes against mmusculus.
## HP search found 0 hits.
## No fc/lfc was provided, defaulting to 10 fold.
## Warning: Removed 1 rows containing missing values (geom_point).

## Performing gProfiler GO search of 69 genes against mmusculus.
## GO search found 18 hits.
## Performing gProfiler KEGG search of 69 genes against mmusculus.
## KEGG search found 1 hits.
## Performing gProfiler REAC search of 69 genes against mmusculus.
## REAC search found 1 hits.
## Performing gProfiler MI search of 69 genes against mmusculus.
## MI search found 0 hits.
## Performing gProfiler TF search of 69 genes against mmusculus.
## TF search found 0 hits.
## Performing gProfiler CORUM search of 69 genes against mmusculus.
## CORUM search found 1 hits.
## Performing gProfiler HP search of 69 genes against mmusculus.
## HP search found 0 hits.
## Performing gProfiler GO search of 67 genes against mmusculus.
## GO search found 2 hits.
## Performing gProfiler KEGG search of 67 genes against mmusculus.
## KEGG search found 0 hits.
## Performing gProfiler REAC search of 67 genes against mmusculus.
## REAC search found 1 hits.
## Performing gProfiler MI search of 67 genes against mmusculus.
## MI search found 0 hits.
## Performing gProfiler TF search of 67 genes against mmusculus.
## TF search found 0 hits.
## Performing gProfiler CORUM search of 67 genes against mmusculus.
## CORUM search found 3 hits.
## Performing gProfiler HP search of 67 genes against mmusculus.
## HP search found 0 hits.

4 Some pictures

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

## [1] 1877
## [1] 476
## 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/20200115mm_ror_gpfoiler_up-v20200114.xlsx.
## Error in `levels<-`(`*tmp*`, value = as.character(levels)) : 
##   factor level [28] is duplicated
## Error in `levels<-`(`*tmp*`, value = as.character(levels)) : 
##   factor level [28] is duplicated
## Error in `levels<-`(`*tmp*`, value = as.character(levels)) : 
##   factor level [28] is duplicated
## Error in `levels<-`(`*tmp*`, value = as.character(levels)) : 
##   factor level [28] is duplicated
## Finished writing data.

## Error in `levels<-`(`*tmp*`, value = as.character(levels)): factor level [28] is duplicated

## 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/20200115mm_ror_gpfoiler_down-v20200114.xlsx.
## Finished writing data.

LS0tCnRpdGxlOiAiTS4gbXVzY3VsdXMgMyBjZWxsIHR5cGVzLCAxIHRpbWVwb2ludCwgMyBnZW5vdHlwZXMsIGFuZCAxIHJlcGxpY2F0ZS4iCmF1dGhvcjogImF0YiBhYmVsZXdAZ21haWwuY29tIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgZmlnX2hlaWdodDogNwogICAgZmlnX3dpZHRoOiA3CiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICBrZWVwX21kOiBmYWxzZQogICAgbW9kZTogc2VsZmNvbnRhaW5lZAogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQogICAgdGhlbWU6IHJlYWRhYmxlCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDoKICAgICAgY29sbGFwc2VkOiBmYWxzZQogICAgICBzbW9vdGhfc2Nyb2xsOiBmYWxzZQogIHJtZGZvcm1hdHM6OnJlYWR0aGVkb3duOgogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBkZl9wcmludDogcGFnZWQKICAgIGZpZ19jYXB0aW9uOiB0cnVlCiAgICBmaWdfaGVpZ2h0OiA3CiAgICBmaWdfd2lkdGg6IDcKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIHdpZHRoOiAzMDAKICAgIGtlZXBfbWQ6IGZhbHNlCiAgICBtb2RlOiBzZWxmY29udGFpbmVkCiAgICB0b2NfZmxvYXQ6IHRydWUKICBCaW9jU3R5bGU6Omh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGZpZ19jYXB0aW9uOiB0cnVlCiAgICBmaWdfaGVpZ2h0OiA3CiAgICBmaWdfd2lkdGg6IDcKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIGtlZXBfbWQ6IGZhbHNlCiAgICBtb2RlOiBzZWxmY29udGFpbmVkCiAgICB0b2NfZmxvYXQ6IHRydWUKLS0tCgo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgpib2R5LCB0ZCB7CiAgZm9udC1zaXplOiAxNnB4Owp9CmNvZGUucnsKICBmb250LXNpemU6IDE2cHg7Cn0KcHJlIHsKIGZvbnQtc2l6ZTogMTZweAp9Cjwvc3R5bGU+CgpgYGB7ciBvcHRpb25zLCBpbmNsdWRlPUZBTFNFfQpsaWJyYXJ5KCJocGdsdG9vbHMiKQp0dCA8LSBkZXZ0b29sczo6bG9hZF9hbGwoIi9kYXRhL2hwZ2x0b29scyIpCmtuaXRyOjpvcHRzX2tuaXQkc2V0KHdpZHRoPTEyMCwKICAgICAgICAgICAgICAgICAgICAgcHJvZ3Jlc3M9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgdmVyYm9zZT1UUlVFLAogICAgICAgICAgICAgICAgICAgICBlY2hvPVRSVUUpCmtuaXRyOjpvcHRzX2NodW5rJHNldChlcnJvcj1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgZHBpPTk2KQpvbGRfb3B0aW9ucyA8LSBvcHRpb25zKGRpZ2l0cz00LAogICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAga25pdHIuZHVwbGljYXRlLmxhYmVsPSJhbGxvdyIpCmdncGxvdDI6OnRoZW1lX3NldChnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemU9MTApKQpydW5kYXRlIDwtIGZvcm1hdChTeXMuRGF0ZSgpLCBmb3JtYXQ9IiVZJW0lZCIpCnByZXZpb3VzX2ZpbGUgPC0gInVuZGVmaW5lZC5SbWQiCnZlciA8LSAiMjAyMDAxMTQiCgojI3RtcCA8LSBzbShsb2FkbWUoZmlsZW5hbWU9cGFzdGUwKGdzdWIocGF0dGVybj0iXFwuUm1kIiwgcmVwbGFjZT0iIiwgeD1wcmV2aW91c19maWxlKSwgIi12IiwgdmVyLCAiLnJkYS54eiIpKSkKcm1kX2ZpbGUgPC0gImluZGV4LlJtZCIKYGBgCgojIE0uIG11c2N1bHVzCgpUaGlzIHdpbGwgYmUgYSB2ZXJ5IG1pbmltYWwgYW5hbHlzaXMgdW50aWwgd2UgZ2V0IHNvbWUgcmVwbGljYXRlcy4KCiMjIEFubm90YXRpb25zCgpJIGFtIHVzaW5nIG1tMzhfOTUuCgpgYGB7ciBhbm5vdGF0aW9uc30KIyMgTXkgbG9hZF9iaW9tYXJ0X2Fubm90YXRpb25zKCkgZnVuY3Rpb24gZGVmYXVsdHMgdG8gaHVtYW4sIHNvIHRoYXQgd2lsbCBiZSBxdWljay4KbW1fYW5ub3QgPC0gbG9hZF9iaW9tYXJ0X2Fubm90YXRpb25zKHNwZWNpZXM9Im1tdXNjdWx1cyIpCm1tX2Fubm90IDwtIG1tX2Fubm90W1siYW5ub3RhdGlvbiJdXQptbV9hbm5vdFtbInR4aWQiXV0gPC0gcGFzdGUwKG1tX2Fubm90W1siZW5zZW1ibF90cmFuc2NyaXB0X2lkIl1dLCAiLiIsIG1tX2Fubm90W1sidmVyc2lvbiJdXSkKcm93bmFtZXMobW1fYW5ub3QpIDwtIG1ha2UubmFtZXMobW1fYW5ub3RbWyJlbnNlbWJsX2dlbmVfaWQiXV0sIHVuaXF1ZT1UUlVFKQoKdHhfZ2VuZV9tYXAgPC0gbW1fYW5ub3RbLCBjKCJ0eGlkIiwgImVuc2VtYmxfZ2VuZV9pZCIpXQpgYGAKClNvLCBJIG5vdyBoYXZlIDIgZGF0YSBmcmFtZXMgb2YgcGFyYXNpdGUgYW5ub3RhdGlvbnMgYW5kIDEgaHVtYW4uCgojIyBNZXRhZGF0YQoKSSBhbSBnb2luZyB0byB3cml0ZSBhIHF1aWNrIHNhbXBsZSBzaGVldCBpbiB0aGUgY3VycmVudCB3b3JraW5nIGRpcmVjdG9yeSBjYWxsZWQKJ2FsbF9zYW1wbGVzLnhsc3gnIGFuZCBwdXQgdGhlIG5hbWVzIG9mIHRoZSBjb3VudCB0YWJsZXMgaW4gaXQuCgojIyBDcmVhdGUgZXhwcmVzc2lvbnNldHMKCkhlcmUgSSBjb21iaW5lIHRoZSBtZXRhZGF0YSwgY291bnQgZGF0YSwgYW5kIGFubm90YXRpb25zLgoKSXQgaXMgd29ydGggbm90aW5nIHRoYXQgdGhlIGdlbmUgSURzIGZyb20gaHRzZXEtY291bnQgcHJvYmFibHkgZG8gbm90IG1hdGNoIHRoZQphbm5vdGF0aW9ucyByZXRyaWV2ZWQgYmVjYXVzZSB0aGV5IGFyZSBsaWtlbHkgZXhvbi1iYXNlZCByYXRoZXIgdGhhbiBnZW5lCmJhc2VkLiAgVGhpcyBpcyBub3QgcmVhbGx5IGEgcHJvYmxlbSwgYnV0IGRvbid0IGZvcmdldCBpdCEKCmBgYHtyIGV4cHR9Cm1tMzhfc2FsbW9uIDwtIHNtKGNyZWF0ZV9leHB0KCJzYW1wbGVfc2hlZXRzL2FsbF9zYW1wbGVzLnhsc3giLCB0eF9nZW5lX21hcD10eF9nZW5lX21hcCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VuZV9pbmZvPW1tX2Fubm90LCBmaWxlX2NvbHVtbj0ic2FsbW9uZmlsZSIpKQoKbW10eF9hbm5vdCA8LSBtbV9hbm5vdApyb3duYW1lcyhtbXR4X2Fubm90KSA8LSBtbV9hbm5vdFtbInR4aWQiXV0KbW0zOF9zYWx0eCA8LSBzbShjcmVhdGVfZXhwdCgic2FtcGxlX3NoZWV0cy9hbGxfc2FtcGxlcy54bHN4IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW5lX2luZm89bW10eF9hbm5vdCwgZmlsZV9jb2x1bW49InNhbG1vbmZpbGUiKSkKCmhpc2F0X2Fubm90IDwtIG1tX2Fubm90CnJvd25hbWVzKGhpc2F0X2Fubm90KSA8LSBwYXN0ZTAoImdlbmUuIiwgcm93bmFtZXMoaGlzYXRfYW5ub3QpKQptbTM4X2hpc2F0IDwtIGNyZWF0ZV9leHB0KCJzYW1wbGVfc2hlZXRzL2FsbF9zYW1wbGVzLnhsc3giLAogICAgICAgICAgICAgICAgICAgICAgICAgIGdlbmVfaW5mbz1oaXNhdF9hbm5vdCkKYGBgCgojIyBRdWVyeSBleHByZXNzaW9uc2V0cwoKSW4gdGhpcyBibG9jayBJIHdpbGwgY2FsY3VsYXRlIGFsbCB0aGUgZGlhZ25vc3RpYyBwbG90cywgYnV0IG5vdCBzaG93IHRoZW0uICBJCndpbGwgc2hvdyB0aGVtIG5leHQgd2l0aCBhIGxpdHRsZSBhbm5vdGF0aW9uLgoKSSB3aWxsIGxlYXZlIHRoZSBvdXRwdXQgZm9yIHRoZSBmaXJzdCBvZiBlYWNoIGludm9jYXRpb24gYW5kIHNpbGVuY2UgaXQgZm9yIHRoZSBzZWNvbmQuCgojIyMgSW5pdGlhbCBzYWxtb24gcGxvdHMKCmBgYHtyIHF1ZXJ5X3NhbG1vbiwgZmlnLnNob3c9ImhpZGUifQptbTM4X3Bsb3RzX3NhIDwtIHNtKGdyYXBoX21ldHJpY3MobW0zOF9zYWxtb24pKQoKbW0zOF9ub3JtX3NhIDwtIG5vcm1hbGl6ZV9leHB0KG1tMzhfc2FsbW9uLCBub3JtPSJxdWFudCIsIGNvbnZlcnQ9ImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm09ImxvZzIiLCBmaWx0ZXI9VFJVRSkKCm1tMzhuX3Bsb3RzX3NhIDwtIHNtKGdyYXBoX21ldHJpY3MobW0zOF9ub3JtX3NhKSkKYGBgCgpgYGB7ciBzaG93X3Bsb3RzX3NhbG1vbn0KbW0zOF9wbG90c19zYSRsZWdlbmQKbW0zOF9wbG90c19zYSRsaWJzaXplCm1tMzhfcGxvdHNfc2Ekbm9uemVybwptbTM4bl9wbG90c19zYSRkZW5zaXR5Cm1tMzhuX3Bsb3RzX3NhJHBjX3Bsb3QKYGBgCgojIyMgSW5pdGlhbCBoaXNhdDIgcGxvdHMKCmBgYHtyIHF1ZXJ5X2hpc2F0LCBmaWcuc2hvdz0iaGlkZSJ9Cm1tMzhfcGxvdHNfaGkgPC0gc20oZ3JhcGhfbWV0cmljcyhtbTM4X2hpc2F0KSkKCm1tMzhfbm9ybV9oaSA8LSBub3JtYWxpemVfZXhwdChtbTM4X2hpc2F0LCBub3JtPSJxdWFudCIsIGNvbnZlcnQ9ImNwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm09ImxvZzIiLCBmaWx0ZXI9VFJVRSkKCm1tMzhuX3Bsb3RzX2hpIDwtIHNtKGdyYXBoX21ldHJpY3MobW0zOF9ub3JtX2hpKSkKYGBgCgpgYGB7ciBzaG93X3Bsb3RzX2hpc2F0fQptbTM4X3Bsb3RzX2hpJGxpYnNpemUKbW0zOF9wbG90c19oaSRub256ZXJvCm1tMzhuX3Bsb3RzX2hpJGRlbnNpdHkKbW0zOG5fcGxvdHNfaGkkcGNfcGxvdApgYGAKCiMjIERvIGEgc2ltcGxlIERFCgpUaGUgb25seSBpbnRlcmVzdGluZyBERSBJIHNlZSBpbiB0aGlzIGlzIHRvIGNvbXBhcmUgdGhlIHJldGluYXMgdG8gdGhlIGRsZ25zLgpJIGNhbiB0cmVhdCB0aGVtIGFzIHJlcGxpY2F0ZXMgYW5kIGNvbXBhcmUuCgpUaGVzZSBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhbmFseXNlcyBhcmUgX0VYUExJQ0lUTFlfIF9OT1RfIHdoYXQgeW91IGNhcmUKYWJvdXQuICBIb3dldmVyLCB0aGV5IGFyZSB1c2VmdWwgZm9yIHR3byBwdXJwb3NlczoKCjEuICBTZWVpbmcgdGhhdCB0aGUgdGhyZWUgdGlzc3VlIHR5cGVzIGFyZSBpbmRlZWQgZGlmZmVyZW50LgoyLiAgU2V0dGluZyB1cCB0aGUgdGFibGUgb2YgcmVzdWx0cyB3aXRoIGFwcHJvcHJpYXRlIHJvd3MvY29sdW1ucyBvZiAocm93cylnZW5lcwogICAgYW5kIChjb2x1bW5zKSBhbm5vdGF0aW9ucy4gIFdlIHdpbGwgdGhlcmVmb3JlIGFkZCB0byB0aGVzZSB0YWJsZXMgdGhlCiAgICByZXN1bHRzIG9mIHRoZSBleHByZXNzaW9uIGFuYWx5c2VzIHRoYXQgeW91IGFjdHVhbGx5IGRvIGNhcmUgYWJvdXQuCgpXaGVuIHdlIHJlY2VpdmUgZnVsbCByZXBsaWNhdGUgc2V0cywgdGhpcyBjaGVhdGVyIG1ldGhvZCBvZiBlbmNhcHN1bGF0aW5nIHRoZQpkYXRhIHdpbGwgbm90IGxvbmdlciBiZSByZXF1aXJlZC4KCiMjIyBXaXRoIHNhbG1vbgoKYGBge3IgZGVfc2EsIGZpZy5zaG93PSJoaWRlIn0KbW1fc2EgPC0gc2V0X2V4cHRfY29uZGl0aW9ucyhtbTM4X3NhbG1vbiwgZmFjdD0iY2VsbHR5cGUiKQptbV9ub3JtX3NhIDwtIHNtKG5vcm1hbGl6ZV9leHB0KG1tX3NhLCBjb252ZXJ0PSJycGttIiwgdHJhbnNmb3JtPSJsb2cyIiwgY29sdW1uPSJjZHNfbGVuZ3RoIikpCnBsb3RfcGNhKG1tX25vcm1fc2EpJHBsb3QKCm1tX2RlX3NhIDwtIGFsbF9wYWlyd2lzZShtbV9zYSwgbW9kZWxfYmF0Y2g9RkFMU0UpCmBgYAoKIyMjIFdpdGggaGlzYXQyCgpgYGB7ciBkZV9oaSwgZmlnLnNob3c9ImhpZGUifQptbV9oaSA8LSBzZXRfZXhwdF9jb25kaXRpb25zKG1tMzhfaGlzYXQsIGZhY3Q9ImNlbGx0eXBlIikKbW1fbm9ybV9oaSA8LSBzbShub3JtYWxpemVfZXhwdChtbV9oaSwgY29udmVydD0icnBrbSIsIHRyYW5zZm9ybT0ibG9nMiIsIGNvbHVtbj0iY2RzX2xlbmd0aCIpKQpwbG90X3BjYShtbV9ub3JtX2hpKSRwbG90CgptbV9kZV9oaSA8LSBzbShhbGxfcGFpcndpc2UobW1faGksIG1vZGVsX2JhdGNoPUZBTFNFKSkKYGBgCgojIyBTZXQgdXAgZm9yIGluaXRpYWwgYW5hbHlzaXMKClVudGlsIHdlIGdldCBmdWxsIHJlcGxpY2F0ZXMsIEkgd2lsbCBkbyBzaW1wbGUgc3VidHJhY3Rpb25zLgoKIyMjIFRlcm0gZGVmaW5pdGlvbgoKSW4gYW4gYXR0ZW1wdCB0byBrZWVwIHNvbWUgY2xhcml0eSBpbiB0aGUgdGVybXMgdXNlZCwgSSB3YW50IHRvIGRlZmluZSB0aGVtCm5vdy4gIFRoZXJlIGFyZSB0aHJlZSBjb250ZXh0cyBpbiB3aGljaCB3ZSB3aWxsIGNvbnNpZGVyIHRoZSBkYXRhOgoKMS4gIFRoZSBpbmRpdmlkdWFsIHNhbXBsZSB0eXBlLiAgV2hlbiBjb25zaWRlcmluZyBpbmRpdmlkdWFsIHNhbXBsZXMsIEkgd2lsbCB1c2UKICAgIHRocmVlIHRlcm1zIGluIHRoaXMgYW5kIG9ubHkgdGhpcyBjb250ZXh0OiB3aWxkLXR5cGUgKHd0KSwgaGV0LCBhbmQgbXV0LgoKMi4gIFRoZSBpbmRpdmlkdWFsIHRyYW5zbGF0b21lLiAgVGhlc2UgYXJlIGRlZmluZXMgYXMgc29tZXRoaW5nIC8gYmFzZWxpbmUuICBJCiAgICB3aWxsIGV4Y2x1c2l2ZWx5IGNhbGwgdGhlIHd0IHNhbXBsZXMgJ2Jhc2VsaW5lJyB3aGVuIHNwZWFraW5nIGluIHRoaXMKICAgIGNvbnRleHQuICBJIHdpbGwgZXhjbHVzaXZlbHkgc3RhdGUgJ25vcm1hbCcgd2hlbiByZWZlcnJpbmcgdG8gaGV0IC8gd3QKICAgIHNhbXBsZXMsIGFuZCBJIHdpbGwgc3RhdGUgJ2tvJyB3aGVuIHJlZmVycmluZyB0byBtdXQgLyB3dCBzYW1wbGVzIGluIHRoZQogICAgdHJhbnNsYXRvbWUgY29udGV4dC4KCjMuICBUcmFuc2xhdG9tZSB2cy4gdHJhbnNsYXRvbWUuICBXaGVuZXZlciBjb21wYXJpbmcgdHJhbnNsYXRvbWVzLCBJIHdpbGwgdXNlCiAgICB0aGUgbmFtZXMgYXMgaW4gIzIgYW5kIGFsd2F5cyBwdXQgdGhlIG51bWVyYXRvciBmaXJzdCB3aGVuIHdyaXRpbmcgdGhlIG5hbWUKICAgIG9mIGEgY29tcGFyaXNvbi4KClRoZSBtb3N0IGNvbXBsZXggZXhhbXBsZSBvZiB0aGUgYWJvdmUgbm9tZW5jbGF0dXJlIGlzOgoKIm5vcm1rb19yZXRkbGduIGlzIGRlZmluZWQgYXMgbm9ybXJldF92c19ub3JtZGxnbiAtIGtvcmV0X3ZzX2tvZGxnbiIKClRoaXMgc3RhdGVzIHdlIGFyZSBleGFtaW5pbmcgYXQgdGhlIHRyYW5zbGF0b21lIGNvbnRleHQ6CiAgIChub3JtKHJldGluYSB0cmFuc2xhdG9tZSkgLSBub3JtKGRsZ24gdHJhbnNsYXRvbWUpKSAtCiAgIChrbyhyZXRpbmEgdHJhbnNsYXRvbWUpIC0ga28oZGxnbiB0cmFuc2xhdG9tZSkpCgpXaGljaCBpbiB0dXJuIGlzIHN5bm9ueW1vdXMgdG8gdGhlIGZvbGxvd2luZyBhdCB0aGUgc2FtcGxlIGNvbnRleHQ6CiAgKChyZXRoZXQgLSByZXR3dCkgIC0gIChkbGduaGV0IC0gZGxnbnd0KSkgIC0KICAoKHJldGtvIC0gcmV0d3QpICAtICAoZGxnbmtvIC0gZGxnbnd0KSkKCk5vdyBsZXQgdXMgYXNzb2NpYXRlIHRoZSB2YXJpb3VzIHZhcmlhYmxlIG5hbWVzIHdpdGggdGhlIGFwcHJvcHJpYXRlIHNhbXBsZXM6CgpgYGB7ciBzYW1wbGVfbmFtZXN9CmRsZ253dCA8LSAiaXByZ2NfMDEiCnJldHd0IDwtICJpcHJnY18wMiIKc2Nud3QgPC0gImlwcmdjXzAzIgoKZGxnbmhldCA8LSAiaXByZ2NfMDQiCnJldGhldCA8LSAiaXByZ2NfMDUiCnNjbmhldCA8LSBOVUxMICAjIyBEb2VzIG5vdCB5ZXQgZXhpc3QuCgpkbGdubXV0IDwtICJpcHJnY18wNiIKcmV0bXV0IDwtICJpcHJnY18wNyIKc2NubXV0IDwtICJpcHJnY18wOCIKYGBgCgpHaXZlIHRoZXNlIHZhcmlhYmxlIG5hbWVzLCBub3cgbGV0cyBhc3NvY2lhdGUgY29sdW1ucyBvZiB0aGUgZXhwcmVzc2lvbiBkYXRhCndpdGggdGhlbS4gIFRoZXNlIGFyZSBhdCB0aGUgc2FtcGxlIGNvbnRleHQsIHNvIHRoZSBhcHByb3ByaWF0ZSBuYW1lcyBhcmU6Cid3dCcsICdoZXQnLCBhbmQgJ211dCcuICBJbiBlYWNoIGNhc2UgSSB3aWxsIHByZWZpeCB0aGUgZ2Vub3R5cGUgd2l0aCB0aGUgdGlzc3VlCnR5cGU6ICdyZXQnLCAnZGxnbicsIGFuZCAnc2NuJy4gIFRodXMgJ3JldHd0JyByZWZlcnMgdG8gdGhlIHNhbXBsZSB1c2VkCnRvIGNhbGN1bGF0ZSB0aGUgdHJhbnNsYXRvbWUgcmV0aW5hIGJhc2VsaW5lOyBpbiBjb250cmFzdCAnZGxnbm11dCcgaXMgdGhlCnNhbXBsZSB3aGljaCBwcm92aWRlcyB0aGUgZGxnbiBrbm9ja291dC4KCmBgYHtyIHNhbXBsZV9jb2x1bW5zfQojIyBTYW1wbGUgY29udGV4dAptbTM4X25vcm0gPC0gbW1fbm9ybV9zYQpkbGdud3QgPC0gZXhwcnMobW0zOF9ub3JtKVssIGRsZ253dF0KcmV0d3QgPC0gZXhwcnMobW0zOF9ub3JtKVssIHJldHd0XQpzY253dCA8LSBleHBycyhtbTM4X25vcm0pWywgc2Nud3RdCmRsZ25oZXQgPC0gZXhwcnMobW0zOF9ub3JtKVssIGRsZ25oZXRdCnJldGhldCA8LSBleHBycyhtbTM4X25vcm0pWywgcmV0aGV0XQpkbGdubXV0IDwtIGV4cHJzKG1tMzhfbm9ybSlbLCBkbGdubXV0XQpyZXRtdXQgPC0gZXhwcnMobW0zOF9ub3JtKVssIHJldG11dF0Kc2NubXV0IDwtIGV4cHJzKG1tMzhfbm9ybSlbLCBzY25tdXRdCmBgYAoKRWFjaCBvZiB0aGUgYWJvdmUgOCB2YXJpYWJsZXMgcHJvdmlkZXMgMSBjb2x1bW4gb2YgaW5mb3JtYXRpb24uIFdlIGhhdmUgMwpiYXNlbGluZSBjb21wYXJpc29ucyBhdmFpbGFibGUgdG8gdXMuICBJbiBlYWNoIG9mIHRoZXNlIHdlIGNvbXBhcmUgb25lIHd0CnNhbXBsZSB0byBhbm90aGVyLgoKYGBge3IgYmFzZWxpbmVfY29tcGFyaXNvbnN9CiMjIEJhc2VsaW5lIGNvbXBhcmlzb25zCnd0X2RsZ25yZXQgPC0gZGxnbnd0IC0gcmV0d3QKd3Rfc2NucmV0IDwtIHNjbnd0IC0gcmV0d3QKd3RfZGxnbnNjbiA8LSBkbGdud3QgLSBzY253dApgYGAKClNpbXVsdGFuZW91c2x5LCB3ZSBoYXZlIDUgYXZhaWxhYmxlIHRyYW5zbGF0b21lcy4gIFRoaXMgYXJlIHByb3ZpZGVkIGJ5CmNvbXBhcmluZyBlYWNoIGhldCBvciBtdXQgdG8gdGhlIGFzc29jaWF0ZWQgd3QuICBUaGVzZSB3aWxsIHRoZXJlZm9yZSByZWNlaXZlCm5hbWVzOiAnbm9ybScgYW5kICdrbycgaW5zdGVhZCBvZiAnaGV0JyBhbmQgJ211dCcuCgpgYGB7ciB0cmFuc2xhdG9tZXN9CiMjIFRyYW5zbGF0b21lIGNvbnRleHQKbm9ybXJldCA8LSByZXRoZXQgLSByZXR3dAprb3JldCA8LSByZXRtdXQgLSByZXR3dAprb3NjbiA8LSBzY25tdXQgLSBzY253dApub3JtZGxnbiA8LSBkbGduaGV0IC0gZGxnbnd0CmtvZGxnbiA8LSBkbGdubXV0IC0gZGxnbnd0CmBgYAoKR2l2ZW4gdGhlc2UgdHJhbnNsYXRvbWVzLCB0aGVyZSBhcmUgYSBmZXcgY29udHJhc3RzIG9mIGxpa2VseSBpbnRlcmVzdC4gIFRoZXNlCmFyZSBwZXJmb3JtZWQgYnkgY29tcGFyaW5nIHRoZSByZWxldmFudCB0cmFuc2xhdG9tZXMuCgpXaWxsIHdpbGwgc3BsaXQgdGhlc2UgaW50byA0IHNlcGFyYXRlIGNhdGVnb3JpZXM6CmhldCB2cyBoZXQsIGtvIHZzIGtvLCBrbyB2cyBoZXQsIGFuZCByYXRpbyB2cyByYXRpby4KCkZpbmFsbHksIG5vdGUgdGhhdCB3ZSBhcmUgYmVpbmcgZXhwbGljaXRseSByZWR1bmRhbnQgaW4gdGhlc2UgZGVmaW5pdGlvbnMuICBJIGFtCm1ha2luZyB2YXJpYWJsZSBuYW1lcyBmb3IgYm90aCB0aGUgYS9iIHJhdGlvIGFuZCB0aGUgYi9hIHJhdGlvLiAgVGh1cyB3ZSBoYXZlCnNvbWUgcmVkdW5kYW50bHkgcmVkdW5kYW50IChoYWhhKSBmbGV4aWJpbGl0eSB3aGVuIGRlY2lkaW5nIG9uIHdoYXQgd2Ugd2FudCB0byBwbG90LgoKYGBge3Igbm9ybV92c19ub3JtfQojIyBub3JtIHZzIG5vcm0Kbm9ybWRsZ25fdnNfbm9ybXJldCA8LSBub3JtZGxnbiAtIG5vcm1yZXQKbm9ybXJldF92c19ub3JtZGxnbiA8LSBub3JtcmV0IC0gbm9ybWRsZ24KYGBgCgpgYGB7ciBrb192c19rb30KIyMga28gdnMga28Ka29yZXRfdnNfa29kbGduIDwtIGtvcmV0IC0ga29kbGduCmtvZGxnbl92c19rb3JldCA8LSBrb2RsZ24gLSBrb3JldAoKa29yZXRfdnNfa29zY24gPC0ga29yZXQgLSBrb3Njbgprb3Njbl92c19rb3JldCA8LSBrb3NjbiAtIGtvcmV0Cgprb2RsZ25fdnNfa29zY24gPC0ga29kbGduIC0ga29zY24Ka29zY25fdnNfa29kbGduIDwtIGtvc2NuIC0ga29kbGduCmBgYAoKT24gdGhlIG90aGVyIGhhbmQsIEkgYW0gYXNzdW1pbmcgd2UgYWx3YXlzIHdhbnQgdGhlIG5vcm1hbHMgYXMgZGVub21pbmF0b3JzIGFuZAprb3MgYXMgbnVtZXJhdG9ycy4KCmBgYHtyIGtvX3ZzX25vcm19CiMjIGtvIHZzIG5vcm0Ka29yZXRfdnNfbm9ybXJldCA8LSBrb3JldCAtIG5vcm1yZXQKCmtvZGxnbl92c19ub3JtZGxnbiA8LSBrb2RsZ24gLSBub3JtZGxnbgpgYGAKCkZpbmFsbHksIGhlcmUgaXMgdGhlIHJhdGlvIG9mIHJhdGlvcyBleGFtcGxlIEkgcHJpbnRlZCBhYm92ZToKCkkgbmFtZWQgaXQgJ25vcm1rb19yZXRkbGduJyBpbiBhbiBhdHRlbXB0IHRvIG1ha2UgY2xlYXIgdGhhdCBpdCBpcyBhY3R1YWxseToKIChub3JtcmV0L25vcm1kbGduKS8oa29yZXQva29kbGduKQoKb3Igc3RhdGVkIGRpZmZlcmVudGx5OiAibm9ybSBkaXZpZGVkIGJ5IGtvIGZvciByZXQgZGl2aWRlZCBieSBkbGduLiIKCmBgYHtyIHJvcn0KIyMgcmF0aW8gb2YgcmF0aW9zCm5vcm1rb19yZXRkbGduIDwtIG5vcm1yZXRfdnNfbm9ybWRsZ24gLSBrb3JldF92c19rb2RsZ24KYGBgCgojIyBEZWZpbmUgYSBtYXRyaXggb2YgdGhlc2UgdmFsdWVzLgoKTXkgbWF0cml4IG9mIGRhdGEgd2lsbCBub3cgY29udGFpbiAxIGNvbHVtbiBmb3IgZWFjaCBvZiB0aGUgYWJvdmUgMjcKc2FtcGxlcy9jb21wYXJpc29ucy4KCmBgYHtyIG1hdHJpeF9vZl92YWx1ZXN9CnBhaXJfbXRyeCA8LSBjYmluZCgKICAjIyBJbmRpdmlkdWFsIHNhbXBsZXMKICBkbGdud3QsIHJldHd0LCBzY253dCwgZGxnbmhldCwgcmV0aGV0LCBkbGdubXV0LCByZXRtdXQsIHNjbm11dCwKICAjIyBCYXNlbGluZSBjb21wYXJpc29ucwogIHd0X2RsZ25yZXQsIHd0X3NjbnJldCwgd3RfZGxnbnNjbiwKICAjIyBCYXNlbGluZSBzdWJ0cmFjdGlvbnMKICBub3JtZGxnbiwgbm9ybXJldCwga29kbGduLCBrb3JldCwga29zY24sCiAgIyMgaGV0X3ZzX2hldCwgb2Ygd2hpY2ggdGhlcmUgaXMgb25seSAxIGJlY2F1c2Ugd2UgZG8gbm90IGhhdmUgaGV0c2NuCiAgbm9ybWRsZ25fdnNfbm9ybXJldCwgbm9ybXJldF92c19ub3JtZGxnbiwKICAjIyBrb192c19rbywgb2Ygd2hpY2ggd2UgaGF2ZSAzCiAga29yZXRfdnNfa29kbGduLCBrb2RsZ25fdnNfa29yZXQsCiAga29yZXRfdnNfa29zY24sIGtvc2NuX3ZzX2tvcmV0LAogIGtvZGxnbl92c19rb3Njbiwga29zY25fdnNfa29kbGduLAogICMjIGtvX3ZzX2hldCwgMyBpbmNsdWRpbmcgb25lIGdldHRpbmcgYXJvdW5kIG1pc3NpbmcgaGV0c2NuCiAga29yZXRfdnNfbm9ybXJldCwga29kbGduX3ZzX25vcm1kbGduLAogICMjIHJhdGlvIG9mIHJhdGlvcwogIG5vcm1rb19yZXRkbGduKQpgYGAKCiMjIEN1dG9mZnMKCkkgYW0gbm90IHN1cmUgaWYgd2Ugd2lsbCB1c2UgdGhlc2UgaW5kZXhlcywgYnV0IEkgYW0gd3JpdGluZyB0aGVzZSBvdXQgYXMKc3Vic2V0cyBvZiBnZW5lcyB0byBsb29rIGF0LiAgVGhlc2UgaW5kZXhlcyBhcmUgc3RhdGluZyB0aGF0LCBnaXZlbiBhIGN1dG9mZgooMCksIHdlIHdhbnQgdG8gbG9vayBhdCBvbmx5IHRoZSBnZW5lcyB3aGljaCBoYXZlIGhpZ2hlciB4IC8gYmFzZWxpbmUgdmFsdWVzCnRoYW4gdGhlIGN1dG9mZi4KCgpgYGB7ciBjdXRvZmZzfQojIyBRdWVyaWVzIGFib3V0IGdlbmUgc3Vic2V0cy4KIyMgVGhlc2UgYXJlIGFsbCBpbiB0aGUgY29udGV4dCBvZiB0cmFuc2xhdG9tZXMuCmN1dG9mZiA8LSAwCnJldF9rZXB0X2lkeCA8LSBub3JtcmV0ID4gY3V0b2ZmICYga29yZXQgPiBjdXRvZmYKc2NuX2tlcHRfaWR4IDwtIGtvc2NuID4gY3V0b2ZmCmRsZ25fa2VwdF9pZHggPC0gbm9ybWRsZ24gPiBjdXRvZmYgJiBrb2RsZ24gPiBjdXRvZmYKcmV0X2RsZ25fa2VwdF9pZHggPC0gcmV0X2tlcHRfaWR4ICYgZGxnbl9rZXB0X2lkeApyZXRfc2NuX2tlcHRfaWR4IDwtIHJldF9rZXB0X2lkeCAmIHNjbl9rZXB0X2lkeApkbGduX3Njbl9rZXB0X2lkeCA8LSBkbGduX2tlcHRfaWR4ICYgc2NuX2tlcHRfaWR4CgojI25vcm1kbGduX3ZzX25vcm1yZXRbIXJldF9kbGduX2tlcHRfaWR4XSA8LSBOQQojI25vcm1yZXRfdnNfbm9ybWRsZ25bIXJldF9kbGduX2tlcHRfaWR4XSA8LSBOQQojI2tvcmV0X3ZzX2tvZGxnblshcmV0X2RsZ25fa2VwdF9pZHhdIDwtIE5BCiMja29kbGduX3ZzX2tvcmV0WyFyZXRfZGxnbl9rZXB0X2lkeF0gPC0gTkEKIyNrb3JldF92c19rb3NjblshcmV0X3Njbl9rZXB0X2lkeF0gPC0gTkEKIyNrb3Njbl92c19rb3JldFshcmV0X3Njbl9rZXB0X2lkeF0gPC0gTkEKIyNrb2RsZ25fdnNfa29zY25bIWRsZ25fc2NuX2tlcHRfaWR4XSA8LSBOQQojI2tvc2NuX3ZzX2tvZGxnblshZGxnbl9zY25fa2VwdF9pZHhdIDwtIE5BCiMja29yZXRfdnNfbm9ybXJldFshcmV0X2tlcHRfaWR4XSA8LSBOQQojI2tvZGxnbl92c19ub3JtZGxnblshZGxnbl9rZXB0X2lkeF0gPC0gTkEKIyNub3Jta29fcmV0ZGxnbiA8LSBub3Jta29fcmV0ZGxnblshcmV0X2RsZ25fa2VwdF9pZHhdIDwtIE5BCmBgYAoKIyMgQWRkIHRoZSBtYXRyaXggdG8gdGhlIGRpZmZlcmVudGlhbCBleHByZXNzaW9uCgpJIHdpbGwgdXNlIG15IGZ1bmN0aW9uIGNvbWJpbmVfZGVfdGFibGVzKCkgdG8gYWRkIHRoaXMgaW5mb3JtYXRpb24gdG8gbXkKZXhpc3RpbmcgYW5ub3RhdGlvbiBkYXRhIGFsb25nIHdpdGggdGhlIHJlc3VsdHMgZnJvbSB0aGUgc3RhdGlzdGljYWxseSB2YWxpZApjb21wYXJpc29uIG9mIHRoZSB0aHJlZSB0aXNzdWUgdHlwZXMuCgpgYGB7cmBgYHtyIGFkZF9tYXRyaXhfZGUsIGZpZy5zaG93PSJoaWRlIn0KbW1fdGFibGVzIDwtIHNtKGNvbWJpbmVfZGVfdGFibGVzKAogIG1tX2RlX3NhLCBleHRyYV9hbm5vdD1wYWlyX210cngsCiAgZXhjZWw9Z2x1ZTo6Z2x1ZSgiZXhjZWwve3J1bmRhdGV9bW1fc2FsbW9uX3RhYmxlcy12e3Zlcn0ueGxzeCIpKSkKYGBgCgojIFBsb3RzIG9mIGludGVyZXN0aW5nIGNvbXBhcmlzb25zCgpgYGB7ciBpbnRlcmVzdGluZ19jb21wYXJpc29uX3Bsb3RzfQojIyBQdXQgcmV0aW5hIGJhc2VsaW5lIG9uIHkgYXhpcyBhcyBibGFjaywgcmV0aW5hIGhldCBvbiB4IGF4aXMgYXMgYmxhY2suCiMjIFRoZW4gcmVjb2xvciBhIHN1YnNldCBvZiB0aGVzZSBhcyByZWQsIHRoZSByZWRzIGFyZSB3aGVuIG5vcm1yZXQgPiAwCmxpYnJhcnkoZ2dwbG90MikKcGxvdHRlZCA8LSBhcy5kYXRhLmZyYW1lKHBhaXJfbXRyeFssIGMoInJldGhldCIsICJyZXR3dCIpXSkKcmVkX2lkeCA8LSBub3JtcmV0ID4gMApwbG90dGVkWywgImNvbG9yIl0gPC0gaWZlbHNlKHJlZF9pZHgsICJyZWQiLCAiYmxhY2siKQpyZXRfaGV0d3QgPC0gZ2dwbG90Mjo6Z2dwbG90KHBsb3R0ZWQsIGFlc19zdHJpbmcoeD0icmV0aGV0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHk9InJldHd0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yPSJjb2xvciIpKSArCiAgZ2VvbV9wb2ludChhbHBoYT0wLjUpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoImJsYWNrIiwgInJlZCIpKQpyZXRfaGV0d3QKCnBsb3R0ZWQgPC0gcGFpcl9tdHJ4WywgYygicmV0bXV0IiwgInJldHd0IildCnJldF9tdXR3dCA8LSBwbG90X3NjYXR0ZXIocGxvdHRlZCkKcmV0X211dHd0CgpwbG90dGVkIDwtIHBhaXJfbXRyeFssIGMoImRsZ25oZXQiLCAiZGxnbnd0IildCmRsZ25faGV0d3QgPC0gcGxvdF9zY2F0dGVyKHBsb3R0ZWQpCmRsZ25faGV0d3QKcGxvdHRlZCA8LSBwYWlyX210cnhbLCBjKCJkbGdubXV0IiwgImRsZ253dCIpXQpkbGduX211dHd0IDwtIHBsb3Rfc2NhdHRlcihwbG90dGVkKQpkbGduX211dHd0CgpwbG90dGVkIDwtIHBhaXJfbXRyeFssIGMoInNjbm11dCIsICJzY253dCIpXQpzY25fbXV0d3QgPC0gcGxvdF9zY2F0dGVyKHBsb3R0ZWQpCnNjbl9tdXR3dAoKIyMgQXhvbiB0cmFuc2xhdG9tZSBzcGVjaWZpYwojIyAgeC1heGlzOiBub3JtZGxnbl92c19ub3JtcmV0IG9yIG5vcm1yZXRfdnNfbm9ybWRsZ24sCiMjICAgICAgICAgICAgICBeXl5eCiMjICB5LWF4aXM6IGRsZ253dC1yZXR3dCAoYmFzZWxpbmUgZGxnbiAtIGJhc2VsaW5lIHJldGluYSkKcGxvdHRlZCA8LSBhcy5kYXRhLmZyYW1lKHBhaXJfbXRyeFssIGMoIm5vcm1kbGduX3ZzX25vcm1yZXQiLCAid3RfZGxnbnJldCIpXSkKcmVkX2lkeCA8LSBub3JtcmV0ID4gMAojIyBOb3RlIHRoYXQgdGhpcyBvcmRlciBpcyBvcHBvc2l0ZSBvZiBhYm92ZS4KcGxvdHRlZFssICJjb2xvciJdIDwtIGlmZWxzZShyZWRfaWR4LCAiYmxhY2siLCAicmVkIikKYXhvbl90cmFuc19yZXRfdGFyZ2V0IDwtIGdncGxvdDI6OmdncGxvdChwbG90dGVkLCBhZXNfc3RyaW5nKHg9Im5vcm1kbGduX3ZzX25vcm1yZXQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeT0id3RfZGxnbnJldCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvcj0iY29sb3IiKSkgKwogIGdlb21fcG9pbnQoYWxwaGE9MC41KSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCJibGFjayIsICJyZWQiKSkKYXhvbl90cmFuc19yZXRfdGFyZ2V0CgojIyBETEdOIHRyYW5zbGF0b21lIHdydC4gUmV0aW5hIHRyYW5zbGF0b21lCnBsb3R0ZWQgPC0gcGFpcl9tdHJ4WywgYygibm9ybXJldCIsICJub3JtZGxnbiIpXQpub3JtcmV0X25vcm1kbGduIDwtIHBsb3Rfc2NhdHRlcihwbG90dGVkKQpub3JtcmV0X25vcm1kbGduCgpwbG90dGVkIDwtIHBhaXJfbXRyeFssIGMoImtvcmV0IiwgImtvZGxnbiIpXQprb3JldF9rb2RsZ24gPC0gcGxvdF9zY2F0dGVyKHBsb3R0ZWQpCmtvcmV0X2tvZGxnbgoKcGxvdHRlZCA8LSBwYWlyX210cnhbLCBjKCJrb3JldCIsICJrb3NjbiIpXQprb3JldF9rb3Njbl9wbG90IDwtIHBsb3Rfc2NhdHRlcihwbG90dGVkKQprb3JldF9rb3Njbl9wbG90CgpwbG90dGVkIDwtIHBhaXJfbXRyeFssIGMoIm5vcm1kbGduIiwgImtvZGxnbiIpXQpub3JtZGxnbl9rb2RsZ25fcGxvdCA8LSBwbG90X3NjYXR0ZXIocGxvdHRlZCkKbm9ybWRsZ25fa29kbGduX3Bsb3QKCnBsb3R0ZWQgPC0gcGFpcl9tdHJ4WywgYygibm9ybXJldCIsICJrb3JldCIpXQpub3JtcmV0X2tvcmV0X3Bsb3QgPC0gcGxvdF9zY2F0dGVyKHBsb3R0ZWQpCm5vcm1yZXRfa29yZXRfcGxvdAoKcGxvdHRlZCA8LSBwYWlyX210cnhbLCBjKCJub3JtcmV0X3ZzX25vcm1kbGduIiwgImtvcmV0X3ZzX2tvZGxnbiIpXQpub3JtYWxfa29fYXhvbl90cmFuc2xhdG9tZSA8LSBwbG90X3NjYXR0ZXIocGxvdHRlZCkKbm9ybWFsX2tvX2F4b25fdHJhbnNsYXRvbWUKYGBgCgojIFRyYW5zbGF0b21lIGxldmVsIGNvbXBhcmlzb25zCgojIyBNYWtlIGEgZ2VuZXJpYyBwbG90dGVyIGZvciB0aGlzIHN0dWZmLgoKYGBge3IgZ2VuZXJpY19wbG90dGVyfQp0cmFuc2xhdG9tZV9wbG90dGVyIDwtIGZ1bmN0aW9uKHBhaXJfbXRyeCwgeF9heGlzPSJrb3JldCIsIHlfYXhpcz0ia29zY24iLCBsZmM9TlVMTCwgZmM9TlVMTCwgbGluZXdpZHRoPTEuNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cF9jb2xvcj0icmVkIiwgZG93bl9jb2xvcj0iIzA5ODUzNCIsIGxpbmVfY29sb3I9IiNmY2JhMDMiLCBhbHBoYT0wLjUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeF9saW1pdD1jKC03LCA3KSwgeV9saW1pdD1jKC03LCA3KSkgewogIGlmIChpcy5udWxsKGZjKSAmIGlzLm51bGwobGZjKSkgewogICAgbWVzc2FnZSgiTm8gZmMvbGZjIHdhcyBwcm92aWRlZCwgZGVmYXVsdGluZyB0byAxMCBmb2xkLiIpCiAgICBsZmMgPC0gbG9nMigxMCkKICB9IGVsc2UgaWYgKGlzLm51bGwobGZjKSkgewogICAgbGZjIDwtIGxvZzIoZmMpCiAgfQogIHBsb3R0ZWQgPC0gYXMuZGF0YS5mcmFtZShwYWlyX210cnhbLCBjKHhfYXhpcywgeV9heGlzKV0pCiAgbmFfaWR4IDwtIGlzLm5hKHBsb3R0ZWQpCiAgcGxvdHRlZFtuYV9pZHhdIDwtIDAKICB1cF9pZHggPC0gcGxvdHRlZFssIHlfYXhpc10gLSBwbG90dGVkWywgeF9heGlzXSA+PSBsZmMKICBkb3duX2lkeCA8LSBwbG90dGVkWywgeV9heGlzXSAtIHBsb3R0ZWRbLCB4X2F4aXNdIDw9IChsZmMgKiAtMSkKICB1cF9nZW5lcyA8LSByb3duYW1lcyhwbG90dGVkKVt1cF9pZHhdCiAgZG93bl9nZW5lcyA8LSByb3duYW1lcyhwbG90dGVkKVtkb3duX2lkeF0KICAjIyBOb3RlIHRoYXQgdGhpcyBvcmRlciBpcyBvcHBvc2l0ZSBvZiBhYm92ZS4KICBwbG90dGVkW1siY29sb3IiXV0gPC0gImJsYWNrIgogIHBsb3R0ZWRbdXBfaWR4LCAiY29sb3IiXSA8LSB1cF9jb2xvcgogIHBsb3R0ZWRbZG93bl9pZHgsICJjb2xvciJdIDwtIGRvd25fY29sb3IKICBwbG90dGVkW1siY29sb3IiXV0gPC0gYXMuZmFjdG9yKHBsb3R0ZWRbWyJjb2xvciJdXSkKICBsZXZlbHMocGxvdHRlZFtbImNvbG9yIl1dKSA8LSBjKCJibGFjayIsIHVwX2NvbG9yLCBkb3duX2NvbG9yKQogIHBsdCA8LSBnZ3Bsb3QyOjpnZ3Bsb3QocGxvdHRlZCwgYWVzX3N0cmluZyh4PXhfYXhpcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeT15X2F4aXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yPSJjb2xvciIpKSArCiAgICBnZW9tX2FibGluZShzaXplPTEuMSwgc2xvcGU9MSwgaW50ZXJjZXB0PWxmYywgY29sb3I9Im9yYW5nZSIpICsKICAgIGdlb21fYWJsaW5lKHNpemU9MS4xLCBzbG9wZT0xLCBpbnRlcmNlcHQ9KC0xICogbGZjKSwgY29sb3I9Im9yYW5nZSIpICsKICAgIHNjYWxlX3hfY29udGludW91cyhsaW1pdHM9Yyh4X2xpbWl0KSkgKwogICAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cz1jKHlfbGltaXQpKSArCiAgICBnZW9tX3BvaW50KGFscGhhPWFscGhhKSArCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoZG93bl9jb2xvciwgImJsYWNrIiwgdXBfY29sb3IpKQogIHJldGxpc3QgPC0gbGlzdCgKICAgICJtdHJ4IiA9IHBsb3R0ZWQsCiAgICAidXBzIiA9IHVwX2dlbmVzLAogICAgImRvd25zIiA9IGRvd25fZ2VuZXMsCiAgICAicGxvdCIgPSBwbHQpCiAgcmV0dXJuKHJldGxpc3QpCn0KYGBgCgoxLiBYLWF4aXM6IEFsd2F5cyByZXRpbmEuCjIuIFktYXhpczogQWx3YXlzIGEgdGFyZ2V0IHRpc3N1ZS4KCkZpcnN0IHBsb3Q6IEtPIHNjbiB0cmFuc2xhdG9tZSBvbiB5IGF4aXMgdnMuIEtPIHJldGluYSB0cmFuc2xhdG9tZSBvbiB4IGF4aXMuCgpgYGB7ciBzY25fa29fd3J0X3JldGluYV9rb190cmFuc2xhdG9tZX0KIyMgU2NuIGtub2Nrb3V0IHRyYW5zbGF0b21lIHZzIHJldGluYSBrbm9ja291dCB0cmFuc2xhdG9tZS4Kc2Nua29fd3J0X3JldGtvX3RyYW5zbGF0b21lIDwtIHRyYW5zbGF0b21lX3Bsb3R0ZXIocGFpcl9tdHJ4KQpzY25rb193cnRfcmV0a29fdHJhbnNsYXRvbWUkcGxvdAp1cF9nbyA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHNpZ19nZW5lcz1zY25rb193cnRfcmV0a29fdHJhbnNsYXRvbWUkdXBzLCBzcGVjaWVzPSJtbXVzY3VsdXMiKQpkb3duX2dvIDwtIHNpbXBsZV9ncHJvZmlsZXIoc2lnX2dlbmVzPXNjbmtvX3dydF9yZXRrb190cmFuc2xhdG9tZSRkb3ducywgc3BlY2llcz0ibW11c2N1bHVzIikKCiMjIGRsZ24gbm9ybWFsIHRyYW5zbGF0b21lIHZzIHJldGluYSBub3JtYWwgdHJhbnNsYXRvbWUuCmRsZ25ub3JtX3dydF9yZXRub3JtX3RyYW5zbGF0b21lIDwtIHRyYW5zbGF0b21lX3Bsb3R0ZXIocGFpcl9tdHJ4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhfYXhpcz0ibm9ybXJldCIsIHlfYXhpcz0ibm9ybWRsZ24iKQpkbGdubm9ybV93cnRfcmV0bm9ybV90cmFuc2xhdG9tZSRwbG90CnVwX2dvIDwtIHNpbXBsZV9ncHJvZmlsZXIoc2lnX2dlbmVzPWRsZ25ub3JtX3dydF9yZXRub3JtX3RyYW5zbGF0b21lJHVwcywgc3BlY2llcz0ibW11c2N1bHVzIikKZG93bl9nbyA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHNpZ19nZW5lcz1kbGdubm9ybV93cnRfcmV0bm9ybV90cmFuc2xhdG9tZSRkb3ducywgc3BlY2llcz0ibW11c2N1bHVzIikKZG93bl9nbyRnbwpkb3duX2dvJHB2YWx1ZV9wbG90cyRicHBfcGxvdF9vdmVyCgojIyBkbGduIGtub2Nrb3V0IHRyYW5zbGF0b21lIHZzIHJldGluYSBrbm9ja291dCB0cmFuc2xhdG9tZS4KZGxnbmtvX3dydF9yZXRrb190cmFuc2xhdG9tZSA8LSB0cmFuc2xhdG9tZV9wbG90dGVyKHBhaXJfbXRyeCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhfYXhpcz0ia29yZXQiLCB5X2F4aXM9ImtvZGxnbiIpCmRsZ25rb193cnRfcmV0a29fdHJhbnNsYXRvbWUkcGxvdAp1cF9nbyA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHNpZ19nZW5lcz1kbGdua29fd3J0X3JldGtvX3RyYW5zbGF0b21lJHVwcywgc3BlY2llcz0ibW11c2N1bHVzIikKZG93bl9nbyA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHNpZ19nZW5lcz1kbGdua29fd3J0X3JldGtvX3RyYW5zbGF0b21lJGRvd25zLCBzcGVjaWVzPSJtbXVzY3VsdXMiKQpkb3duX2dvJGdvCgojIyBOb3JtYWwgZGxnbiB0cmFuc2xhdG9tZSB2cyBrbm9ja291dCBkbGduIHRyYW5zbGF0b21lLgpkbGdubm9ybV93cnRfZGxnbmtvX3RyYW5zbGF0b21lIDwtIHRyYW5zbGF0b21lX3Bsb3R0ZXIocGFpcl9tdHJ4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeF9heGlzPSJub3JtZGxnbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5X2F4aXM9ImtvZGxnbiIpCmRsZ25ub3JtX3dydF9kbGdua29fdHJhbnNsYXRvbWUkcGxvdAp1cF9nbyA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHNpZ19nZW5lcz1kbGdubm9ybV93cnRfZGxnbmtvX3RyYW5zbGF0b21lJHVwcywgc3BlY2llcz0ibW11c2N1bHVzIikKZG93bl9nbyA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHNpZ19nZW5lcz1kbGdubm9ybV93cnRfZGxnbmtvX3RyYW5zbGF0b21lJGRvd25zLCBzcGVjaWVzPSJtbXVzY3VsdXMiKQoKCiMjIGRsZ24ga25vY2tvdXQgdHJhbnNsYXRvbWUgdnMuIHNjbiBrbm9ja291dCB0cmFuc2xhdG9tZS4KZGxnbmtvX3dydF9zY25rb190cmFuc2xhdG9tZSA8LSB0cmFuc2xhdG9tZV9wbG90dGVyKHBhaXJfbXRyeCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhfYXhpcz0ia29kbGduIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHlfYXhpcz0ia29zY24iKQpkbGdua29fd3J0X3NjbmtvX3RyYW5zbGF0b21lJHBsb3QKdXBfZ28gPC0gc2ltcGxlX2dwcm9maWxlcihzaWdfZ2VuZXM9ZGxnbmtvX3dydF9zY25rb190cmFuc2xhdG9tZSR1cHMsIHNwZWNpZXM9Im1tdXNjdWx1cyIpCmRvd25fZ28gPC0gc2ltcGxlX2dwcm9maWxlcihzaWdfZ2VuZXM9ZGxnbmtvX3dydF9zY25rb190cmFuc2xhdG9tZSRkb3ducywgc3BlY2llcz0ibW11c2N1bHVzIikKdXBfZ28kcHZhbHVlX3Bsb3RzJGJwcF9wbG90X292ZXIKYGBgCgojIFNvbWUgcGljdHVyZXMKCkFzIEkgdW5kZXJzdGFuZCBpdCwgdGhlcmUgaXMgc29tZSBpbnRlcmVzdCBpbiBhbiBvbnRvbG9neSBzZWFyY2ggdXNpbmcgdGhlIHJhdGlvIG9mIHJhdGlvcy4KCmBgYHtyIG90aGVyX2NvbnRyYXN0c30Kcm9yIDwtIG5vcm1rb19yZXRkbGduCnVwX2lkeCA8LSByb3IgPj0gMQpkb3duX2lkeCA8LSByb3IgPD0gLTEKcm9yX3VwIDwtIHJvclt1cF9pZHhdCmxlbmd0aChyb3JfdXApCnJvcl9kb3duIDwtIHJvcltkb3duX2lkeF0KbGVuZ3RoKHJvcl9kb3duKQoKcm9yX2dwcm9maWxlcl91cCA8LSBzaW1wbGVfZ3Byb2ZpbGVyKHNpZ19nZW5lcz1yb3JfdXAsIHNwZWNpZXM9Im1tdXNjdWx1cyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGNlbD1nbHVlOjpnbHVlKCJleGNlbC97cnVuZGF0ZX1tbV9yb3JfZ3Bmb2lsZXJfdXAtdnt2ZXJ9Lnhsc3giKSkKcm9yX2dwcm9maWxlcl91cCRwdmFsdWVfcGxvdHMkbWZwX3Bsb3Rfb3Zlcgpyb3JfZ3Byb2ZpbGVyX3VwJHB2YWx1ZV9wbG90cyRicHBfcGxvdF9vdmVyCnJvcl9ncHJvZmlsZXJfdXAkcHZhbHVlX3Bsb3RzJGNjcF9wbG90X292ZXIKcm9yX2dwcm9maWxlcl91cCRwdmFsdWVfcGxvdHMkdGZfcGxvdF9vdmVyCnJvcl9ncHJvZmlsZXJfdXAkcHZhbHVlX3Bsb3RzJGhwX3Bsb3Rfb3ZlcgoKcm9yX2dwcm9maWxlcl9kb3duIDwtIHNpbXBsZV9ncHJvZmlsZXIoc2lnX2dlbmVzPXJvcl9kb3duLCBzcGVjaWVzPSJtbXVzY3VsdXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGNlbD1nbHVlOjpnbHVlKCJleGNlbC97cnVuZGF0ZX1tbV9yb3JfZ3Bmb2lsZXJfZG93bi12e3Zlcn0ueGxzeCIpKQpyb3JfZ3Byb2ZpbGVyX2Rvd24kcHZhbHVlX3Bsb3RzJG1mcF9wbG90X292ZXIKcm9yX2dwcm9maWxlcl9kb3duJHB2YWx1ZV9wbG90cyRicHBfcGxvdF9vdmVyCnJvcl9ncHJvZmlsZXJfZG93biRwdmFsdWVfcGxvdHMkcmVhY3RvbWVfcGxvdF9vdmVyCnJvcl9ncHJvZmlsZXJfZG93biRwdmFsdWVfcGxvdHMkY2NwX3Bsb3Rfb3Zlcgpyb3JfZ3Byb2ZpbGVyX2Rvd24kcHZhbHVlX3Bsb3RzJHRmX3Bsb3Rfb3ZlcgpgYGAKCmBgYHtyIHNhdmVtZSwgZXZhbD1GQUxTRX0KcGFuZGVyOjpwYW5kZXIoc2Vzc2lvbkluZm8oKSkKbWVzc2FnZShwYXN0ZTAoIlRoaXMgaXMgaHBnbHRvb2xzIGNvbW1pdDogIiwgZ2V0X2dpdF9jb21taXQoKSkpCnRoaXNfc2F2ZSA8LSBwYXN0ZTAoZ3N1YihwYXR0ZXJuPSJcXC5SbWQiLCByZXBsYWNlPSIiLCB4PXJtZF9maWxlKSwgIi12IiwgdmVyLCAiLnJkYS54eiIpCm1lc3NhZ2UocGFzdGUwKCJTYXZpbmcgdG8gIiwgdGhpc19zYXZlKSkKdG1wIDwtIHNtKHNhdmVtZShmaWxlbmFtZT10aGlzX3NhdmUpKQpgYGAKCmBgYHtyIGxvYWRtZSwgZXZhbD1GQUxTRX0KbG9hZG1lKGZpbGVuYW1lPXRoaXNfc2F2ZSkKYGBgCg==