Generating DE results
[Question]: Before we start, what do you think is the most challenging part of a differential expression analysis? (Post in thread below or raise zoom ‘hand’ to answer)
Now that we have reviewed the plots by sample and determined that our data passed our quality control checks, specifically that the patterns we observe are likely due to our experimental treatments over technical or other confounding factors, we can focus on differential expression testing.
This illustration from the HCB training materials illustrates the basis of the differential expression procedure, where our goal is to compare the distribution of an expressed gene across samples in each treatment groups. Image credit: Paul Pavlidis, UBC
Only where the distributions of each group are sufficiently separated will a gene be considered differentially expressed.
This is where having sufficient replicates to overcome within group variance is important, as the more replicates we have in each group the better we can determine the distributions of expression for each group.
DESeq2 statistical testing
We have already fit our DESeq2 model, specifying our model as ~ Gtype.Tx
and our next step is to identify genes with significantly different expression between our contrasts of interest. To determine significance, a statistical test is required.
The first step for any statistical test is to define the null hypothesis. In this case, the null hypothesis would be that there is no difference in the expression of a gene between two groups of samples, such as illustrated at the bottom of the first figure in this module. The next step is to use a statistical test to determine if, based on the observed data, the null hypothesis can be rejected.
To do this, DESeq2 applies the Wald test to compare between two groups. A Wald test statistic is computed as well as the probability that the observed value or more extreme test statistic would be observed. This probability is called the p-value of the test.
If the p-value is smaller than a pre-defined threshold, we would reject the null hypothesis and state that there is evidence against the null, i.e. the gene is differentially expressed. However, if the p-value is larger than our threshold, we would fail to reject the null hypothesis, meaning that we lack evidence that the expression of this gene is different NOT that we have evidence that the expression is indeed the same in both groups.
For a more detailed overview of the statistical comparisons , please refer to this HBC tutorial or the DESeq2 vignette.
Optional - Dispersion estimates
Click for code for customized PCA plot of raw data
We can visualize the dispersion estimates with the plotDispEsts
function. This plot shows the the DESeq2 normalization results for our data, which centers on shrinking the variance across all genes to better fit the expected spread at a given expression level.
plotDispEsts(dds)
If we ran the command above, we would see the raw data plotted in black, the fitted (or expected) dispersion in red, and the normalized data with scaled variance in blue. Since we have fairly small sample sizes for each condition, we see shrinkage for many genes but a reasonable correlation between the expression level and dispersions. This HBC tutorial has a more detailed overview of estimating size factors, estimating gene dispersion, and the shrinkage procedure, as well as examples of concerning dispersion plots that may suggest reassessing quality of the experimental data.
Generating results
We can check what comparisons were automatically generated during fitting using the resultsNames()
function.
resultsNames(dds)
## [1] "Intercept" "Gtype.Tx_ko.Tx_vs_wt.Tx" "Gtype.Tx_ko.control_vs_wt.Tx"
## [4] "Gtype.Tx_wt.control_vs_wt.Tx"
Since we are interested in comparing each knockout versus its corresponding wild-type control, one of the automatically generated comparisons is relevant. We can pull the Tx_ko.Tx_vs_wt.Tx
comparison results using the results
function and assign those result to a new object.
Comparison <- "Gtype.Tx_ko.Tx_vs_wt.Tx"
res_Tx <- results(dds, name=Comparison)
[Question]: How would we look at our results?(Post in thread below or raise zoom ‘hand’ to answer)
In the results table we’ll generate, the row name will ve gene symbols and there will be six columns of values that are described in more detail in an Illumina post.
head(res_Tx)
## log2 fold change (MLE): Gtype.Tx ko.Tx vs wt.Tx
## Wald test p-value: Gtype.Tx ko.Tx vs wt.Tx
## DataFrame with 6 rows and 6 columns
## baseMean log2FoldChange lfcSE stat pvalue padj
## <numeric> <numeric> <numeric> <numeric> <numeric> <numeric>
## ENSMUSG00000000001 6255.63216 0.0788788 0.0932593 0.845801 3.97664e-01 6.66997e-01
## ENSMUSG00000000028 1337.87447 0.2255095 0.1162034 1.940646 5.23013e-02 2.18232e-01
## ENSMUSG00000000031 3.77357 0.5790922 1.1623210 0.498221 6.18329e-01 NA
## ENSMUSG00000000037 27.56328 -0.5559172 0.4306882 -1.290765 1.96785e-01 4.66052e-01
## ENSMUSG00000000049 2.25635 0.1863568 1.6951707 0.109934 9.12462e-01 NA
## ENSMUSG00000000056 2194.25131 -1.3070196 0.1777579 -7.352809 1.94084e-13 3.04422e-11
Results table output
The first column, ‘baseMean’ is the average of the normalized count values, divided by size factors and taken over all samples, and can be interpreted as the relative expression level of that gene across all samples.
The second column, ‘log2FoldChange’, is the log2 transformed ratio of the expression of the numerator group (first group) over the denominator group (second group after “vs”).
Note that in our comparison,the log2FoldChange column compares the expression of the numerator group (ko.Tx
) over the denominator group (wt.Tx
). If the value is positive, that means the expression of that gene is greater across the ko.Tx
samples than across the wt.Tx
samples. If the value is negative, that means the expression of that gene is greater across the wt.Tx
samples.
The third column, ‘lfcSE’ is the standard error for the log2 fold change estimate.
The fourth column, ‘stat’, is the calculated Wald statistic for that gene, while the fifth column ‘pvalue’ is the nominal significance for that gene.
Multiple hypothesis testing and FDR correction
The sixth column, ‘padj’, is the adjusted p-value and is what we use for determining significantly differently expressed genes.
[Question]: Why should we use values from this column instead of the ‘pvalue’ column? (Post in thread below or raise zoom ‘hand’ to answer)
Each p-value is the result of a single test for a single gene. If we used the p-value directly from the Wald test with a significance cut-off of p < 0.05, that means there is a 5% chance it is a false positives.
The more genes we test, the greater chance we have of seeing a significant results. So if we are testing 20,000 genes for differential expression, we would expect to see ~1,000 significant genes just by chance.
This is the multiple testing problem and is problematic because we would need to sift through our “significant” genes to identify which ones are true positives.
To address hthis we need to correct for multiple hypothesis testing to reduce the number of false positives, and while there are a few common approaches, the default method is False Discovery Rate(FDR) (aka: Benjamini-Hochberg correction) which is symbolized as ‘BH’ in DESeq2.
Benjamini and Hochberg (1995) defined the concept of FDR and created an algorithm to control it below a specified level. An interpretation of the BH method is implemented in DESeq2 in which genes are ranked by p-value, then each ranked p-value is multiplied by the number of total tests divided by rank.
Note: From the results
function help page and HBC tutorial that includes overview of multiple hypothesis correction, we can change the multiple hypothesis correction method to an alternative option using the pAdjustMethod =
argument.
The default FDR rate cutoff for DESeq2 is alpha = 0.05
. By setting the cutoff to < 0.05, we expect that the proportion of false positives amongst our differentially expressed genes is now controlled to 5%. For example, if we call 500 genes as differentially expressed with this FDR cutoff, we expect only 25 of them to be false positives. DESeq2 vignette’s includes a further discussion of filtering and multiple testing
Note on ‘padj’ values set to NA
As discussed in the HBC tutorial as well as the DESeq2 vignette, DESeq2 reduces the number of genes that will be tested by removing genes with low number of counts and outlier samples.
- If within a row, all samples have zero counts, the baseMean column will be zero, and the log2 fold change estimates, p-value and adjusted p-value will all be set to NA.
- If a row contains a sample with an extreme count outlier then the p-value and adjusted p-value will be set to NA. These outlier counts are detected by Cook’s distance.
- If a row is filtered by automatic independent filtering, for having a low mean normalized count, then only the adjusted p-value will be set to NA.
How to generate additional contrasts
Since our dds object already has the fitted data, if there are comparisons that are not included in the resultsName
, we can generate Wald test results by specifying those comparisons as an additional argument to the results function.
?results
As the function description specifies, we need to provide a list of three elements: the name of the factor in the model design, the name of the numerator for the fold-change, and the name of denominator.
res_WT <- results(dds, contrast=c("Gtype.Tx", "ko.control", "wt.control"))
head(res_WT)
## log2 fold change (MLE): Gtype.Tx ko.control vs wt.control
## Wald test p-value: Gtype.Tx ko.control vs wt.control
## DataFrame with 6 rows and 6 columns
## baseMean log2FoldChange lfcSE stat pvalue padj
## <numeric> <numeric> <numeric> <numeric> <numeric> <numeric>
## ENSMUSG00000000001 6255.63216 -0.01402432 0.0930159 -0.1507734 0.880154464 0.96070256
## ENSMUSG00000000028 1337.87447 0.52242173 0.1359947 3.8414873 0.000122291 0.00394869
## ENSMUSG00000000031 3.77357 -1.15659729 1.6008026 -0.7225109 0.469980436 NA
## ENSMUSG00000000037 27.56328 -0.27961187 0.4765512 -0.5867405 0.557378029 0.80464714
## ENSMUSG00000000049 2.25635 4.01071833 1.8891229 2.1230585 0.033748953 NA
## ENSMUSG00000000056 2194.25131 -0.00854409 0.1772220 -0.0482112 0.961547909 0.98788873
Now that we’ve generated our differential comparisons and have an understanding of our results, including multiple hypothesis correction, we can proceed with generating summary figures and tables for our differential expression analysis.
LS0tCnRpdGxlOiAiRGF5IDMgLSBNb2R1bGUgMTA6IERFIENvbXBhcmlzb25zIFJlc3VsdHMiCmF1dGhvcjogIlVNIEJpb2luZm9ybWF0aWNzIENvcmUiCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogICAgICAgIGh0bWxfZG9jdW1lbnQ6CiAgICAgICAgICAgIGluY2x1ZGVzOgogICAgICAgICAgICAgICAgaW5faGVhZGVyOiBoZWFkZXIuaHRtbAogICAgICAgICAgICB0aGVtZTogcGFwZXIKICAgICAgICAgICAgdG9jOiB0cnVlCiAgICAgICAgICAgIHRvY19kZXB0aDogNAogICAgICAgICAgICB0b2NfZmxvYXQ6IHRydWUKICAgICAgICAgICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICAgICAgICAgIGZpZ19jYXB0aW9uOiB0cnVlCiAgICAgICAgICAgIG1hcmtkb3duOiBHRk0KICAgICAgICAgICAgY29kZV9kb3dubG9hZDogdHJ1ZQotLS0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KYm9keXsgLyogTm9ybWFsICAqLwogICAgICBmb250LXNpemU6IDE0cHQ7CiAgfQpwcmUgewogIGZvbnQtc2l6ZTogMTJwdAp9CmNvZGUucnsKICBmb250LXNpemU6IDEycHQ7Cn0KPC9zdHlsZT4KCjwhLS0tIEFsbG93IHRoZSBwYWdlIHRvIGJlIHdpZGVyIC0tLT4KPHN0eWxlPgogICAgYm9keSAubWFpbi1jb250YWluZXIgewogICAgICAgIG1heC13aWR0aDogMTIwMHB4OwogICAgfQo8L3N0eWxlPgoKPiAjIE9iamVjdGl2ZXMgCj4gKiBHZW5lcmF0ZSB0YWJsZXMgb2YgREUgcmVzdWx0cwo+ICogVW5kZXJzdGFuZCB3aGF0IGEgcC12YWx1ZSByZXByZXNlbnRzLiAgIAo+ICogVW5kZXJzdGFuZCBtdWx0aXBsZSBoeXBvdGhlc2lzIGNvcnJlY3Rpb24gYXBwbGljYXRpb24gYW5kIGltcG9ydGFuY2UgICAgCgoKYGBge3IgTW9kdWxlcywgZXZhbD1UUlVFLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KERFU2VxMikKbGlicmFyeSh0aWR5cikKbGlicmFyeShkcGx5cikKbG9hZCgicmRhdGEvUnVubmluZ0RhdGEuUkRhdGEiKQpgYGAKCiMgRGlmZmVyZW50aWFsIEV4cHJlc3Npb24gV29ya2Zsb3cKCkhlcmUgd2Ugd2lsbCBmaW5hbGx5IHRlc3QgZm9yIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGJldHdlZW4gb3VyIGNvbXBhcmlzb25zIG9mIGludGVyZXN0LgoKIVtdKC4vaW1hZ2VzL3dheWZpbmRlci93YXlmaW5kZXItMDYucG5nKXt3aWR0aD03NSV9CgoKLS0tCgojIEdlbmVyYXRpbmcgREUgcmVzdWx0cwoKKltRdWVzdGlvbl06IEJlZm9yZSB3ZSBzdGFydCwgd2hhdCBkbyB5b3UgdGhpbmsgaXMgdGhlIG1vc3QgY2hhbGxlbmdpbmcgcGFydCBvZiBhIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2lzPyAoUG9zdCBpbiB0aHJlYWQgYmVsb3cgb3IgcmFpc2Ugem9vbSAnaGFuZCcgdG8gYW5zd2VyKSoKCk5vdyB0aGF0IHdlIGhhdmUgcmV2aWV3ZWQgdGhlIHBsb3RzIGJ5IHNhbXBsZSBhbmQgZGV0ZXJtaW5lZCB0aGF0IG91ciBkYXRhIHBhc3NlZCBvdXIgcXVhbGl0eSBjb250cm9sIGNoZWNrcywgc3BlY2lmaWNhbGx5IHRoYXQgdGhlIHBhdHRlcm5zIHdlIG9ic2VydmUgYXJlIGxpa2VseSBkdWUgdG8gb3VyIGV4cGVyaW1lbnRhbCB0cmVhdG1lbnRzIG92ZXIgdGVjaG5pY2FsIG9yIG90aGVyIGNvbmZvdW5kaW5nIGZhY3RvcnMsIHdlIGNhbiBmb2N1cyBvbiBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiB0ZXN0aW5nLgoKVGhpcyBpbGx1c3RyYXRpb24gZnJvbSB0aGUgSENCIHRyYWluaW5nIG1hdGVyaWFscyBpbGx1c3RyYXRlcyB0aGUgYmFzaXMgb2YgdGhlIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIHByb2NlZHVyZSwgd2hlcmUgb3VyIGdvYWwgaXMgdG8gY29tcGFyZSB0aGUgZGlzdHJpYnV0aW9uIG9mIGFuIGV4cHJlc3NlZCBnZW5lIGFjcm9zcyBzYW1wbGVzIGluIGVhY2ggdHJlYXRtZW50IGdyb3Vwcy4KIVtdKC4vaW1hZ2VzL2RlX3RoZW9yeV9jb3JyZWN0ZWQucG5nKQoqSW1hZ2UgY3JlZGl0OiBQYXVsIFBhdmxpZGlzLCBVQkMqCgpPbmx5IHdoZXJlIHRoZSBkaXN0cmlidXRpb25zIG9mIGVhY2ggZ3JvdXAgYXJlIHN1ZmZpY2llbnRseSBzZXBhcmF0ZWQgd2lsbCBhIGdlbmUgYmUgY29uc2lkZXJlZCBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQuIAoKVGhpcyBpcyB3aGVyZSBoYXZpbmcgc3VmZmljaWVudCByZXBsaWNhdGVzIHRvIG92ZXJjb21lIHdpdGhpbiBncm91cCB2YXJpYW5jZSBpcyBpbXBvcnRhbnQsIGFzIHRoZSBtb3JlIHJlcGxpY2F0ZXMgd2UgaGF2ZSBpbiBlYWNoIGdyb3VwIHRoZSBiZXR0ZXIgd2UgY2FuIGRldGVybWluZSB0aGUgZGlzdHJpYnV0aW9ucyBvZiBleHByZXNzaW9uIGZvciBlYWNoIGdyb3VwLgoKIyMgREVTZXEyIHN0YXRpc3RpY2FsIHRlc3RpbmcKCldlIGhhdmUgYWxyZWFkeSBmaXQgb3VyIERFU2VxMiBtb2RlbCwgc3BlY2lmeWluZyBvdXIgbW9kZWwgYXMgYH4gR3R5cGUuVHhgIGFuZCBvdXIgbmV4dCBzdGVwIGlzIHRvIGlkZW50aWZ5IGdlbmVzIHdpdGggc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgZXhwcmVzc2lvbiBiZXR3ZWVuIG91ciBjb250cmFzdHMgb2YgaW50ZXJlc3QuIFRvIGRldGVybWluZSBzaWduaWZpY2FuY2UsIGEgc3RhdGlzdGljYWwgdGVzdCBpcyByZXF1aXJlZC4KClRoZSBmaXJzdCBzdGVwIGZvciBhbnkgc3RhdGlzdGljYWwgdGVzdCBpcyB0byBkZWZpbmUgdGhlICpudWxsIGh5cG90aGVzaXMqLiBJbiB0aGlzIGNhc2UsIHRoZSBudWxsIGh5cG90aGVzaXMgd291bGQgYmUgdGhhdCB0aGVyZSBpcyBubyBkaWZmZXJlbmNlIGluIHRoZSBleHByZXNzaW9uIG9mIGEgZ2VuZSBiZXR3ZWVuIHR3byBncm91cHMgb2Ygc2FtcGxlcywgc3VjaCBhcyBpbGx1c3RyYXRlZCBhdCB0aGUgYm90dG9tIG9mIHRoZSBmaXJzdCBmaWd1cmUgaW4gdGhpcyBtb2R1bGUuIFRoZSBuZXh0IHN0ZXAgaXMgdG8gdXNlIGEgc3RhdGlzdGljYWwgdGVzdCB0byBkZXRlcm1pbmUgaWYsIGJhc2VkIG9uIHRoZSBvYnNlcnZlZCBkYXRhLCB0aGUgbnVsbCBoeXBvdGhlc2lzIGNhbiBiZSByZWplY3RlZC4KClRvIGRvIHRoaXMsIFtERVNlcTIgYXBwbGllcyB0aGUgV2FsZCB0ZXN0XShodHRwOi8vYmlvY29uZHVjdG9yLm9yZy9wYWNrYWdlcy9kZXZlbC9iaW9jL3ZpZ25ldHRlcy9ERVNlcTIvaW5zdC9kb2MvREVTZXEyLmh0bWwjdGhlb3J5LWJlaGluZC1kZXNlcTIpIHRvIGNvbXBhcmUgYmV0d2VlbiB0d28gZ3JvdXBzLiBBIFdhbGQgdGVzdCBzdGF0aXN0aWMgaXMgY29tcHV0ZWQgYXMgd2VsbCBhcyB0aGUgcHJvYmFiaWxpdHkgdGhhdCB0aGUgb2JzZXJ2ZWQgdmFsdWUgb3IgbW9yZSBleHRyZW1lIHRlc3Qgc3RhdGlzdGljIHdvdWxkIGJlIG9ic2VydmVkLiBUaGlzIHByb2JhYmlsaXR5IGlzIGNhbGxlZCB0aGUgcC12YWx1ZSBvZiB0aGUgdGVzdC4gCgpJZiB0aGUgcC12YWx1ZSBpcyBzbWFsbGVyIHRoYW4gYSBwcmUtZGVmaW5lZCB0aHJlc2hvbGQsIHdlIHdvdWxkIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzIGFuZCBzdGF0ZSB0aGF0IHRoZXJlIGlzIGV2aWRlbmNlIGFnYWluc3QgdGhlIG51bGwsIGkuZS4gdGhlIGdlbmUgaXMgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkLiBIb3dldmVyLCBpZiB0aGUgcC12YWx1ZSBpcyBsYXJnZXIgdGhhbiBvdXIgdGhyZXNob2xkLCB3ZSB3b3VsZCAqZmFpbCB0byByZWplY3QqIHRoZSBudWxsIGh5cG90aGVzaXMsIG1lYW5pbmcgdGhhdCB3ZSBsYWNrIGV2aWRlbmNlIHRoYXQgdGhlIGV4cHJlc3Npb24gb2YgdGhpcyBnZW5lIGlzIGRpZmZlcmVudCAqTk9UKiB0aGF0IHdlIGhhdmUgZXZpZGVuY2UgdGhhdCB0aGUgZXhwcmVzc2lvbiBpcyBpbmRlZWQgdGhlIHNhbWUgaW4gYm90aCBncm91cHMuIAoKCkZvciBhIG1vcmUgZGV0YWlsZWQgb3ZlcnZpZXcgb2YgdGhlIHN0YXRpc3RpY2FsIGNvbXBhcmlzb25zICwgcGxlYXNlIHJlZmVyIHRvIFt0aGlzIEhCQyB0dXRvcmlhbF0oaHR0cHM6Ly9oYmN0cmFpbmluZy5naXRodWIuaW8vREdFX3dvcmtzaG9wL2xlc3NvbnMvMDVfREdFX0RFU2VxMl9hbmFseXNpczIuaHRtbCkgb3IgdGhlIFtERVNlcTIgdmlnbmV0dGVdKGh0dHA6Ly9iaW9jb25kdWN0b3Iub3JnL3BhY2thZ2VzL2RldmVsL2Jpb2MvdmlnbmV0dGVzL0RFU2VxMi9pbnN0L2RvYy9ERVNlcTIuaHRtbCN0aGVvcnktYmVoaW5kLWRlc2VxMikuCgoKIyMgT3B0aW9uYWwgLSBEaXNwZXJzaW9uIGVzdGltYXRlcwoKPGRldGFpbHM+CiAgICA8c3VtbWFyeT4qQ2xpY2sgZm9yIGNvZGUgZm9yIGN1c3RvbWl6ZWQgUENBIHBsb3Qgb2YgcmF3IGRhdGEqPC9zdW1tYXJ5PgogICAgV2UgY2FuIHZpc3VhbGl6ZSB0aGUgKipkaXNwZXJzaW9uIGVzdGltYXRlcyoqIHdpdGggdGhlIGBwbG90RGlzcEVzdHNgIGZ1bmN0aW9uLiBUaGlzIHBsb3Qgc2hvd3MgdGhlIHRoZSBERVNlcTIgbm9ybWFsaXphdGlvbiByZXN1bHRzIGZvciBvdXIgZGF0YSwgd2hpY2ggY2VudGVycyBvbiBzaHJpbmtpbmcgdGhlIHZhcmlhbmNlIGFjcm9zcyBhbGwgZ2VuZXMgdG8gYmV0dGVyIGZpdCB0aGUgZXhwZWN0ZWQgc3ByZWFkIGF0IGEgZ2l2ZW4gZXhwcmVzc2lvbiBsZXZlbC4KYGBge3IgQ2hlY2tEaXNwZXJzaW9ucywgZXZhbD1GQUxTRX0KcGxvdERpc3BFc3RzKGRkcykKYGBgCiAgICBJZiB3ZSByYW4gdGhlIGNvbW1hbmQgYWJvdmUsIHdlIHdvdWxkIHNlZSB0aGUgcmF3IGRhdGEgcGxvdHRlZCBpbiBibGFjaywgdGhlIGZpdHRlZCAob3IgZXhwZWN0ZWQpIGRpc3BlcnNpb24gaW4gcmVkLCBhbmQgdGhlIG5vcm1hbGl6ZWQgZGF0YSB3aXRoIHNjYWxlZCB2YXJpYW5jZSBpbiBibHVlLiBTaW5jZSB3ZSBoYXZlIGZhaXJseSBzbWFsbCBzYW1wbGUgc2l6ZXMgZm9yIGVhY2ggY29uZGl0aW9uLCB3ZSBzZWUgc2hyaW5rYWdlIGZvciBtYW55IGdlbmVzIGJ1dCBhIHJlYXNvbmFibGUgY29ycmVsYXRpb24gYmV0d2VlbiB0aGUgZXhwcmVzc2lvbiBsZXZlbCBhbmQgZGlzcGVyc2lvbnMuCiAgICBUaGlzIFtIQkMgdHV0b3JpYWxdKGh0dHBzOi8vaGJjdHJhaW5pbmcuZ2l0aHViLmlvL0RHRV93b3Jrc2hvcC9sZXNzb25zLzA0X0RHRV9ERVNlcTJfYW5hbHlzaXMuaHRtbCkgaGFzIGEgbW9yZSBkZXRhaWxlZCBvdmVydmlldyBvZiBlc3RpbWF0aW5nIHNpemUgZmFjdG9ycywgZXN0aW1hdGluZyBnZW5lIGRpc3BlcnNpb24sIGFuZCB0aGUgc2hyaW5rYWdlIHByb2NlZHVyZSwgYXMgd2VsbCBhcyBleGFtcGxlcyBvZiBjb25jZXJuaW5nIGRpc3BlcnNpb24gcGxvdHMgdGhhdCBtYXkgc3VnZ2VzdCByZWFzc2Vzc2luZyBxdWFsaXR5IG9mIHRoZSBleHBlcmltZW50YWwgZGF0YS4gCjwvZGV0YWlscz4KCjxicj4KCiMjIEdlbmVyYXRpbmcgcmVzdWx0cwoKV2UgY2FuIGNoZWNrIHdoYXQgY29tcGFyaXNvbnMgd2VyZSBhdXRvbWF0aWNhbGx5IGdlbmVyYXRlZCBkdXJpbmcgZml0dGluZyB1c2luZyB0aGUgYHJlc3VsdHNOYW1lcygpYCBmdW5jdGlvbi4gCmBgYHtyIFJlc3VsdHMxfQpyZXN1bHRzTmFtZXMoZGRzKQpgYGAKClNpbmNlIHdlIGFyZSBpbnRlcmVzdGVkIGluIGNvbXBhcmluZyBlYWNoIGtub2Nrb3V0IHZlcnN1cyBpdHMgY29ycmVzcG9uZGluZyB3aWxkLXR5cGUgY29udHJvbCwgb25lIG9mIHRoZSBhdXRvbWF0aWNhbGx5IGdlbmVyYXRlZCBjb21wYXJpc29ucyBpcyByZWxldmFudC4gV2UgY2FuIHB1bGwgdGhlIGBUeF9rby5UeF92c193dC5UeGAgY29tcGFyaXNvbiByZXN1bHRzIHVzaW5nIHRoZSBgcmVzdWx0c2AgZnVuY3Rpb24gYW5kIGFzc2lnbiB0aG9zZSByZXN1bHQgdG8gYSBuZXcgb2JqZWN0LgpgYGB7ciBTZXRzUmVzdWx0fQpDb21wYXJpc29uIDwtICJHdHlwZS5UeF9rby5UeF92c193dC5UeCIKcmVzX1R4IDwtIHJlc3VsdHMoZGRzLCBuYW1lPUNvbXBhcmlzb24pCmBgYAoKKltRdWVzdGlvbl06IEhvdyB3b3VsZCB3ZSBsb29rIGF0IG91ciByZXN1bHRzPyhQb3N0IGluIHRocmVhZCBiZWxvdyBvciByYWlzZSB6b29tICdoYW5kJyB0byBhbnN3ZXIpKgoKSW4gdGhlIHJlc3VsdHMgdGFibGUgd2UnbGwgZ2VuZXJhdGUsIHRoZSByb3cgbmFtZSB3aWxsIHZlIGdlbmUgc3ltYm9scyBhbmQgdGhlcmUgd2lsbCBiZSBzaXggY29sdW1ucyBvZiB2YWx1ZXMgdGhhdCBhcmUgW2Rlc2NyaWJlZCBpbiBtb3JlIGRldGFpbCBpbiBhbiBJbGx1bWluYSBwb3N0XShodHRwczovL3N1cHBvcnQuaWxsdW1pbmEuY29tL2hlbHAvQlNfQXBwX1JOQVNlcV9ERV9PTEhfMTAwMDAwMDA3MTkzOS9Db250ZW50L1NvdXJjZS9JbmZvcm1hdGljcy9BcHBzL0RFU2VxMlJlc3VsdEZpbGVfc3dCUy5odG0jOn46dGV4dD1iYXNlTWVhbiVFMiU4MCU5NFRoZSUyMGF2ZXJhZ2UlMjBvZiUyMHRoZSxmYWN0b3JzJTJDJTIwdGFrZW4lMjBvdmVyJTIwYWxsJTIwc2FtcGxlcy4mdGV4dD1sb2cyRm9sZENoYW5nZSVFMiU4MCU5M1RoZSUyMGVmZmVjdCUyMHNpemUlMjBlc3RpbWF0ZSx0aGUlMjBjb21wYXJpc29uJTIwYW5kJTIwY29udHJvbCUyMGdyb3VwcykuIAoKYGBge3IgUmVzdWx0c0tEfQpoZWFkKHJlc19UeCkKYGBgCgoKIyMgUmVzdWx0cyB0YWJsZSBvdXRwdXQKClRoZSBmaXJzdCBjb2x1bW4sICoqJ2Jhc2VNZWFuJyoqIGlzIHRoZSBhdmVyYWdlIG9mIHRoZSBub3JtYWxpemVkIGNvdW50IHZhbHVlcywgZGl2aWRlZCBieSBzaXplIGZhY3RvcnMgYW5kIHRha2VuIG92ZXIgYWxsIHNhbXBsZXMsIGFuZCBjYW4gYmUgaW50ZXJwcmV0ZWQgYXMgdGhlIHJlbGF0aXZlIGV4cHJlc3Npb24gbGV2ZWwgb2YgdGhhdCBnZW5lIGFjcm9zcyBhbGwgc2FtcGxlcy4gCgpUaGUgc2Vjb25kIGNvbHVtbiwgKionbG9nMkZvbGRDaGFuZ2UnKiosIGlzIHRoZSBsb2cyIHRyYW5zZm9ybWVkIHJhdGlvIG9mIHRoZSBleHByZXNzaW9uIG9mIHRoZSBudW1lcmF0b3IgZ3JvdXAgKGZpcnN0IGdyb3VwKSBvdmVyIHRoZSBkZW5vbWluYXRvciBncm91cCAoc2Vjb25kIGdyb3VwIGFmdGVyICJ2cyIpLgoKTm90ZSB0aGF0IGluIG91ciBjb21wYXJpc29uLHRoZSAqKmxvZzJGb2xkQ2hhbmdlKiogY29sdW1uIGNvbXBhcmVzIHRoZSBleHByZXNzaW9uIG9mIHRoZSBudW1lcmF0b3IgZ3JvdXAgKGBrby5UeGApIG92ZXIgdGhlIGRlbm9taW5hdG9yIGdyb3VwIChgd3QuVHhgKS4gSWYgdGhlIHZhbHVlIGlzIHBvc2l0aXZlLCB0aGF0IG1lYW5zIHRoZSBleHByZXNzaW9uIG9mIHRoYXQgZ2VuZSBpcyBncmVhdGVyIGFjcm9zcyB0aGUgYGtvLlR4YCBzYW1wbGVzIHRoYW4gYWNyb3NzIHRoZSBgd3QuVHhgIHNhbXBsZXMuIElmIHRoZSB2YWx1ZSBpcyBuZWdhdGl2ZSwgdGhhdCBtZWFucyB0aGUgZXhwcmVzc2lvbiBvZiB0aGF0IGdlbmUgaXMgZ3JlYXRlciBhY3Jvc3MgdGhlIGB3dC5UeGAgc2FtcGxlcy4gCgpUaGUgdGhpcmQgY29sdW1uLCAqKidsZmNTRScqKiBpcyB0aGUgc3RhbmRhcmQgZXJyb3IgZm9yIHRoZSBsb2cyIGZvbGQgY2hhbmdlIGVzdGltYXRlLiAKClRoZSBmb3VydGggY29sdW1uLCAqKidzdGF0JyoqLCBpcyB0aGUgY2FsY3VsYXRlZCBXYWxkIHN0YXRpc3RpYyBmb3IgdGhhdCBnZW5lLCB3aGlsZSB0aGUgZmlmdGggY29sdW1uICdwdmFsdWUnIGlzIHRoZSAqbm9taW5hbCogc2lnbmlmaWNhbmNlIGZvciB0aGF0IGdlbmUuCgojIyMgTXVsdGlwbGUgaHlwb3RoZXNpcyB0ZXN0aW5nIGFuZCBGRFIgY29ycmVjdGlvbgoKVGhlIHNpeHRoIGNvbHVtbiwgKioncGFkaicqKiwgaXMgdGhlICphZGp1c3RlZCBwLXZhbHVlKiBhbmQgaXMgd2hhdCB3ZSB1c2UgZm9yIGRldGVybWluaW5nIHNpZ25pZmljYW50bHkgZGlmZmVyZW50bHkgZXhwcmVzc2VkIGdlbmVzLiAKCipbUXVlc3Rpb25dOiBXaHkgc2hvdWxkIHdlIHVzZSB2YWx1ZXMgZnJvbSB0aGlzIGNvbHVtbiBpbnN0ZWFkIG9mIHRoZSAncHZhbHVlJyBjb2x1bW4/IChQb3N0IGluIHRocmVhZCBiZWxvdyBvciByYWlzZSB6b29tICdoYW5kJyB0byBhbnN3ZXIpKgoKRWFjaCBwLXZhbHVlIGlzIHRoZSByZXN1bHQgb2YgYSBzaW5nbGUgdGVzdCBmb3IgYSBzaW5nbGUgZ2VuZS4gSWYgd2UgdXNlZCB0aGUgcC12YWx1ZSBkaXJlY3RseSBmcm9tIHRoZSBXYWxkIHRlc3Qgd2l0aCBhIHNpZ25pZmljYW5jZSBjdXQtb2ZmIG9mIHAgPCAwLjA1LCB0aGF0IG1lYW5zIHRoZXJlIGlzIGEgNSUgY2hhbmNlIGl0IGlzIGEgZmFsc2UgcG9zaXRpdmVzLiAKClRoZSBtb3JlIGdlbmVzIHdlIHRlc3QsIHRoZSBncmVhdGVyIGNoYW5jZSB3ZSBoYXZlIG9mIHNlZWluZyBhIHNpZ25pZmljYW50IHJlc3VsdHMuIFNvIGlmIHdlIGFyZSB0ZXN0aW5nIDIwLDAwMCBnZW5lcyBmb3IgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24sIHdlIHdvdWxkIGV4cGVjdCB0byBzZWUgfjEsMDAwIHNpZ25pZmljYW50IGdlbmVzIGp1c3QgYnkgY2hhbmNlLiAKClRoaXMgaXMgdGhlIG11bHRpcGxlIHRlc3RpbmcgcHJvYmxlbSBhbmQgaXMgcHJvYmxlbWF0aWMgYmVjYXVzZSB3ZSB3b3VsZCBuZWVkIHRvIHNpZnQgdGhyb3VnaCBvdXIg4oCcc2lnbmlmaWNhbnTigJ0gZ2VuZXMgdG8gaWRlbnRpZnkgd2hpY2ggb25lcyBhcmUgdHJ1ZSBwb3NpdGl2ZXMuCgpUbyBhZGRyZXNzIGh0aGlzIHdlIG5lZWQgdG8gY29ycmVjdCBmb3IgW211bHRpcGxlIGh5cG90aGVzaXMgdGVzdGluZ10oaHR0cHM6Ly9tdWx0aXRocmVhZGVkLnN0aXRjaGZpeC5jb20vYmxvZy8yMDE1LzEwLzE1L211bHRpcGxlLWh5cG90aGVzaXMtdGVzdGluZy8pIHRvIHJlZHVjZSB0aGUgbnVtYmVyIG9mIGZhbHNlIHBvc2l0aXZlcywgYW5kIHdoaWxlIHRoZXJlIGFyZSBhIGZldyBjb21tb24gYXBwcm9hY2hlcywgdGhlIGRlZmF1bHQgbWV0aG9kIGlzIEZhbHNlIERpc2NvdmVyeSBSYXRlKEZEUikgKGFrYTogQmVuamFtaW5pLUhvY2hiZXJnIGNvcnJlY3Rpb24pIHdoaWNoIGlzIHN5bWJvbGl6ZWQgYXMgJ0JIJyBpbiBERVNlcTIuIAoKW0JlbmphbWluaSBhbmQgSG9jaGJlcmcgKDE5OTUpXShodHRwczovL3Jzcy5vbmxpbmVsaWJyYXJ5LndpbGV5LmNvbS9kb2kvMTAuMTExMS9qLjI1MTctNjE2MS4xOTk1LnRiMDIwMzEueCkgZGVmaW5lZCB0aGUgY29uY2VwdCBvZiBGRFIgYW5kIGNyZWF0ZWQgYW4gYWxnb3JpdGhtIHRvIGNvbnRyb2wgaXQgYmVsb3cgYSBzcGVjaWZpZWQgbGV2ZWwuIEFuIGludGVycHJldGF0aW9uIG9mIHRoZSBCSCBtZXRob2QgaXMgaW1wbGVtZW50ZWQgaW4gREVTZXEyIGluIHdoaWNoIGdlbmVzIGFyZSByYW5rZWQgYnkgcC12YWx1ZSwgdGhlbiBlYWNoIHJhbmtlZCBwLXZhbHVlIGlzIG11bHRpcGxpZWQgYnkgdGhlIG51bWJlciBvZiB0b3RhbCB0ZXN0cyBkaXZpZGVkIGJ5IHJhbmsuCgoqKk5vdGUqKjogRnJvbSB0aGUgYHJlc3VsdHNgIGZ1bmN0aW9uIGhlbHAgcGFnZSBhbmQgW0hCQyB0dXRvcmlhbCB0aGF0IGluY2x1ZGVzIG92ZXJ2aWV3IG9mIG11bHRpcGxlIGh5cG90aGVzaXMgY29ycmVjdGlvbl0oaHR0cHM6Ly9oYmN0cmFpbmluZy5naXRodWIuaW8vREdFX3dvcmtzaG9wL2xlc3NvbnMvMDVfREdFX0RFU2VxMl9hbmFseXNpczIuaHRtbCksIHdlIGNhbiBjaGFuZ2UgdGhlIG11bHRpcGxlIGh5cG90aGVzaXMgY29ycmVjdGlvbiBtZXRob2QgdG8gYW4gYWx0ZXJuYXRpdmUgb3B0aW9uIHVzaW5nIHRoZSBgcEFkanVzdE1ldGhvZCA9YCBhcmd1bWVudC4KClRoZSBkZWZhdWx0IEZEUiByYXRlIGN1dG9mZiBmb3IgREVTZXEyIGlzIGBhbHBoYSA9IDAuMDVgLiBCeSBzZXR0aW5nIHRoZSBjdXRvZmYgdG8gPCAwLjA1LCB3ZSBleHBlY3QgdGhhdCB0aGUgcHJvcG9ydGlvbiBvZiBmYWxzZSBwb3NpdGl2ZXMgYW1vbmdzdCBvdXIgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIGlzIG5vdyBjb250cm9sbGVkIHRvIDUlLiBGb3IgZXhhbXBsZSwgaWYgd2UgY2FsbCA1MDAgZ2VuZXMgYXMgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIHdpdGggdGhpcyBGRFIgY3V0b2ZmLCB3ZSBleHBlY3Qgb25seSAyNSBvZiB0aGVtIHRvIGJlIGZhbHNlIHBvc2l0aXZlcy4gREVTZXEyIHZpZ25ldHRlJ3MgaW5jbHVkZXMgYSBbZnVydGhlciBkaXNjdXNzaW9uIG9mIGZpbHRlcmluZyBhbmQgbXVsdGlwbGUgdGVzdGluZ10oaHR0cDovL2Jpb2NvbmR1Y3Rvci5vcmcvcGFja2FnZXMvZGV2ZWwvYmlvYy92aWduZXR0ZXMvREVTZXEyL2luc3QvZG9jL0RFU2VxMi5odG1sI2luZGVwZW5kZW50LWZpbHRlcmluZy1hbmQtbXVsdGlwbGUtdGVzdGluZykKCiMjIyMgTm90ZSBvbiAncGFkaicgdmFsdWVzIHNldCB0byBOQQoKQXMgZGlzY3Vzc2VkIGluIHRoZSBbSEJDIHR1dG9yaWFsXShodHRwczovL2hiY3RyYWluaW5nLmdpdGh1Yi5pby9ER0Vfd29ya3Nob3AvbGVzc29ucy8wNV9ER0VfREVTZXEyX2FuYWx5c2lzMi5odG1sKSBhcyB3ZWxsIGFzIHRoZSBbREVTZXEyIHZpZ25ldHRlXShodHRwOi8vYmlvY29uZHVjdG9yLm9yZy9wYWNrYWdlcy9kZXZlbC9iaW9jL3ZpZ25ldHRlcy9ERVNlcTIvaW5zdC9kb2MvREVTZXEyLmh0bWwjaS13YW50LXRvLWJlbmNobWFyay1kZXNlcTItY29tcGFyaW5nLXRvLW90aGVyLWRlLXRvb2xzLiksIERFU2VxMiByZWR1Y2VzIHRoZSBudW1iZXIgb2YgZ2VuZXMgdGhhdCB3aWxsIGJlIHRlc3RlZCBieSByZW1vdmluZyBnZW5lcyB3aXRoIGxvdyBudW1iZXIgb2YgY291bnRzIGFuZCBvdXRsaWVyIHNhbXBsZXMuIAoKKiBJZiB3aXRoaW4gYSByb3csIGFsbCBzYW1wbGVzIGhhdmUgemVybyBjb3VudHMsIHRoZSBiYXNlTWVhbiBjb2x1bW4gd2lsbCBiZSB6ZXJvLCBhbmQgdGhlIGxvZzIgZm9sZCBjaGFuZ2UgZXN0aW1hdGVzLCBwLXZhbHVlIGFuZCBhZGp1c3RlZCBwLXZhbHVlIHdpbGwgYWxsIGJlIHNldCB0byBOQS4gICAgCiogSWYgYSByb3cgY29udGFpbnMgYSBzYW1wbGUgd2l0aCBhbiBleHRyZW1lIGNvdW50IG91dGxpZXIgdGhlbiB0aGUgcC12YWx1ZSBhbmQgYWRqdXN0ZWQgcC12YWx1ZSB3aWxsIGJlIHNldCB0byBOQS4gVGhlc2Ugb3V0bGllciBjb3VudHMgYXJlIGRldGVjdGVkIGJ5IENvb2vigJlzIGRpc3RhbmNlLiAgICAgCiogSWYgYSByb3cgaXMgZmlsdGVyZWQgYnkgYXV0b21hdGljIGluZGVwZW5kZW50IGZpbHRlcmluZywgZm9yIGhhdmluZyBhIGxvdyBtZWFuIG5vcm1hbGl6ZWQgY291bnQsIHRoZW4gb25seSB0aGUgYWRqdXN0ZWQgcC12YWx1ZSB3aWxsIGJlIHNldCB0byBOQS4gICAKCiMjIEhvdyB0byBnZW5lcmF0ZSBhZGRpdGlvbmFsIGNvbnRyYXN0cwoKU2luY2Ugb3VyIGRkcyBvYmplY3QgYWxyZWFkeSBoYXMgdGhlIGZpdHRlZCBkYXRhLCBpZiB0aGVyZSBhcmUgY29tcGFyaXNvbnMgdGhhdCBhcmUgbm90IGluY2x1ZGVkIGluIHRoZSBgcmVzdWx0c05hbWVgLCB3ZSBjYW4gZ2VuZXJhdGUgV2FsZCB0ZXN0IHJlc3VsdHMgYnkgc3BlY2lmeWluZyB0aG9zZSBjb21wYXJpc29ucyBhcyBhbiBhZGRpdGlvbmFsIGFyZ3VtZW50IHRvIHRoZSByZXN1bHRzIGZ1bmN0aW9uLiAKYGBge3IgUmVzdWx0c0Z1bmN0aW9ufQo/cmVzdWx0cwpgYGAKCkFzIHRoZSBmdW5jdGlvbiBkZXNjcmlwdGlvbiBzcGVjaWZpZXMsIHdlIG5lZWQgdG8gcHJvdmlkZSBhIGxpc3Qgb2YgdGhyZWUgZWxlbWVudHM6IHRoZSBuYW1lIG9mIHRoZSBmYWN0b3IgaW4gdGhlIG1vZGVsIGRlc2lnbiwgdGhlIG5hbWUgb2YgdGhlIG51bWVyYXRvciBmb3IgdGhlIGZvbGQtY2hhbmdlLCBhbmQgdGhlIG5hbWUgb2YgZGVub21pbmF0b3IuIApgYGB7ciBBZGRpdGlvbmFsQ29tcGFyaXNvbnN9CnJlc19XVCA8LSByZXN1bHRzKGRkcywgY29udHJhc3Q9YygiR3R5cGUuVHgiLCAia28uY29udHJvbCIsICJ3dC5jb250cm9sIikpIApoZWFkKHJlc19XVCkKYGBgCgoKTm93IHRoYXQgd2UndmUgZ2VuZXJhdGVkIG91ciBkaWZmZXJlbnRpYWwgY29tcGFyaXNvbnMgYW5kIGhhdmUgYW4gdW5kZXJzdGFuZGluZyBvZiBvdXIgcmVzdWx0cywgaW5jbHVkaW5nIG11bHRpcGxlIGh5cG90aGVzaXMgY29ycmVjdGlvbiwgd2UgY2FuIHByb2NlZWQgd2l0aCBnZW5lcmF0aW5nIHN1bW1hcnkgZmlndXJlcyBhbmQgdGFibGVzIGZvciBvdXIgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYW5hbHlzaXMuCgotLS0KCiMgU3VtbWFyeSAKCkluIHRoaXMgc2VjdGlvbiwgd2U6ICAgIAoKKiBQZXJmb3JtZWQgc3RhdGlzdGljYWwgdGVzdHMgZm9yIGNvbXBhcmlzb25zIG9mIGludGVyZXN0ICAgICAKKiBHZW5lcmF0ZWQgdGFibGVzIG9mIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIHJlc3VsdHMgLSBpLmUuIGZvbGQgY2hhbmdlcyBhbmQgYWRqdXN0ZWQgcHZhbHVlcyBmb3IgZWFjaCBnZW5lIGluIGRhdGFzZXQgICAgICAKKiBEaXNjdXNzZWQgaW1wb3J0YW5jZSBhbmQgYXBwbGljYXRpb24gb2YgbXVsdGlwbGUgaHlwb3RoZXNpcyBjb3JyZWN0aW9uICAgICAgCgoKTm93IHRoYXQgd2UndmUgZ2VuZXJhdGVkIG91ciBkaWZmZXJlbnRpYWwgY29tcGFyaXNvbnMgYW5kIGhhdmUgYW4gdW5kZXJzdGFuZGluZyBvZiBvdXIgcmVzdWx0cywgaW5jbHVkaW5nIG11bHRpcGxlIGh5cG90aGVzaXMgY29ycmVjdGlvbiwgd2UgY2FuIHByb2NlZWQgd2l0aCBnZW5lcmF0aW5nIHN1bW1hcnkgZmlndXJlcyBhbmQgdGFibGVzIGZvciBvdXIgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYW5hbHlzaXMuCgoKLS0tCgoKIyBTb3VyY2VzIFVzZWQKKiBIQkMgREdFIHRyYWluaW5nIG1vZHVsZSwgcGFydCAxOiBodHRwczovL2hiY3RyYWluaW5nLmdpdGh1Yi5pby9ER0Vfd29ya3Nob3AvbGVzc29ucy8wNF9ER0VfREVTZXEyX2FuYWx5c2lzLmh0bWwKKiBIQkMgREdFIHRyYWluaW5nIG1vZHVsZSwgcGFydCAyOiBodHRwczovL2hiY3RyYWluaW5nLmdpdGh1Yi5pby9ER0Vfd29ya3Nob3AvbGVzc29ucy8wNV9ER0VfREVTZXEyX2FuYWx5c2lzMi5odG1sCiogREVTZXEyIHZpZ25ldHRlOiBodHRwOi8vYmlvY29uZHVjdG9yLm9yZy9wYWNrYWdlcy9kZXZlbC9iaW9jL3ZpZ25ldHRlcy9ERVNlcTIvaW5zdC9kb2MvREVTZXEyLmh0bWwjZGlmZmVyZW50aWFsLWV4cHJlc3Npb24tYW5hbHlzaXMKCi0tLQoKIVtdKC4vaW1hZ2VzL3NpZ25pZmljYW50X3hrY2QucG5nKQoKCmBgYHtyIFdyaXRlT3V0LlJEYXRhLCBldmFsPVRSVUUsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiNIaWRkZW4gY29kZSBibG9jayB0byB3cml0ZSBvdXQgZGF0YSBmb3Iga25pdHRpbmcKc2F2ZS5pbWFnZShmaWxlID0gInJkYXRhL1J1bm5pbmdEYXRhLlJEYXRhIikKYGBgCgoKLS0tCgoKVGhlc2UgbWF0ZXJpYWxzIGhhdmUgYmVlbiBhZGFwdGVkIGFuZCBleHRlbmRlZCBmcm9tIG1hdGVyaWFscyBsaXN0ZWQgYWJvdmUuIFRoZXNlIGFyZSBvcGVuIGFjY2VzcyBtYXRlcmlhbHMgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBbQ3JlYXRpdmUgQ29tbW9ucyBBdHRyaWJ1dGlvbiBsaWNlbnNlIChDQyBCWSA0LjApXShodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS80LjAvKSwgd2hpY2ggcGVybWl0cyB1bnJlc3RyaWN0ZWQgdXNlLCBkaXN0cmlidXRpb24sIGFuZCByZXByb2R1Y3Rpb24gaW4gYW55IG1lZGl1bSwgcHJvdmlkZWQgdGhlIG9yaWdpbmFsIGF1dGhvciBhbmQgc291cmNlIGFyZSBjcmVkaXRlZC4K