Science/Health Science/Data Science Module

Topic 7B: Big Data II (\(p\)-value adjustments)


Welcome to the seventh computer lab for the Science, Health Science and Data Science modules. In this computer lab we will look at methods for adjusting \(p\)-values obtained when conducting multiple inferences.

This computer lab introduces some biology terminology. Therefore, it is recommended that you read over sections 2.1 to 2.3 of the Introduction to Bioinformatics in R supplement. The material in this supplement provides all the background information you will need.

By the end of this lab, you should understand how to adjust \(p\)-values to counteract the effects of conducting multiple tests simultaneously. Let’s get started!

1 Introduction

By now, you should be familiar with the concept of a hypothesis test. You should also feel comfortable conducting a statistical test that involves computing a \(p\)-value to compare a null hypothesis against an alternative hypothesis (a simple example would be an independent samples \(t\)-test to assess the difference in the mean value of a variable between two groups).

In many situations however, we may be interested in performing a hypothesis test on multiple features simultaneously. For example, in biology, it is now common for thousands of features to be tested against a null hypothesis (where the expectation is that a number of features will be statistically significant).

Unfortunately, when we conduct multiple tests, the probability of obtaining a false positive aka Type I error will become inflated, meaning that the original significance level of \(\alpha\) designated for a single test does not hold.

1.1 Example

As a simple example, suppose that we set \(\alpha = 0.05\) for a single test. Therefore, the probability of not observing a Type I error for this test is \(1-\alpha = 0.95\). So far, so good.

However, if we use this level of significance, and carry out 10 tests, then actually the probability of not observing a Type I error in these 10 tests is \((1 - \alpha)^{10} \approx 0.6\). In other words, by carrying out multiple testing, our probability of Type I error has increased from \(5\%\) to \(40\%\)! As the number of tests increases, this error rate will continue to rise.

2 The p.adjust function

Fortunately, there are several methods we can use in R to adjust \(p\)-values obtained from performing multiple tests. We have already come across one such adjustment in the Topic 7 Readings: the Tukey adjustment, which was used to carry out post-hoc tests after carrying out a One-way ANOVA.

In this computer lab, we will learn about other types of adjustments which may be more appropriate in different settings. Most of these adjustments can be applied using the R function p.adjust. Let’s take a look.

2.1

Suppose that we have compared gene expression levels between two groups of individuals (cases and controls) for 10 key genes of interest. As a result, we have obtained a set of 10 \(p\)-values (one for each gene). These \(p\)-values are presented below:

\(0.0003, 0.0085, 0.001, 0.0001, 0.045, 0.62, 0.009, 0.18, 0.92, 0.02.\)

Store these values in a vector called base_p_values.

2.2

If we assessed these \(p\)-values based on an \(\alpha\) value of \(0.05\), how many genes would we find to have significant differential expression between the cases and controls?

2.3

A simple way to adjust our initial \(p\)-values is to multiply each \(p\)-value by the number of \(p\)-values we have (with any resultant values over 1 scaled back to 1). This is known as the Bonferroni correction method.

Run the code below to conduct this adjustment:

p.adjust(base_p_values, method = "bonferroni")

2.4

Assessing the adjusted \(p\)-values, how many of the genes remain significantly differentially expressed, at the \(\alpha = 0.05\) level of significance?

2.5

As you will have noticed, the Bonferroni correction is quite conservative, and in practice can often lead to rejecting true positives (especially when dealing with larger numbers of tests). This is because the adjustment method focuses on controlling the probability of making one or more Type I errors when conducting multiple tests. This probability is known as the family-wise error rate (FWER).

2.6

The p.adjust function contains options for several other methods which focus on controlling the FWER. Take a look at the help file for the p.adjust function, and try using the other three FWER-control methods.

Compare and contrast your results, using the R code below as a guide:

# We can compute the number of significant results obtained by a method via:
sum(p.adjust(base_p_values, method = "holm") < .05)
# Note here we use the `holm` method

3 False Discovery Rate

A more flexible and more powerful alternative to controlling the FWER is to control the False Discovery Rate (FDR) when conducting multiple tests. When dealing with Big Data, using the FDR is generally preferred over more conservative adjustments such as Bonferonni correction. FDR control is also typically favoured over FWER control in biological studies involving Big Data1.

The FDR can be defined as the expected proportion of errors (i.e. false discoveries) among the rejected hypotheses2. Controlling the FDR helps to reduce false positives, but also helps minimise false negatives.

3.1

We can apply FDR correction to \(p\)-values using the R function p.adjust - just specify the method fdr.

Try this now, on our base_p_values vector of \(p\)-values.

3.2

Compare your FDR results from 3.1 to your Bonferroni correction results in 2.3. What do you notice?

4 SARS-CoV-2 Study \(p\)-values

To conclude this computer lab, let’s take a look at a real-world application of \(p\)-value adjustment.

For this example, we will look at \(p\)-values computed as part of an Oxford University expression profiling study relating to SARS-CoV-2 (Coronavirus). Information on the study can be found here3.

We won’t go into all the details of the study. Suffice to say that as part of the study, \(p\)-values were computed when comparing gene expression differences over time, for human cells infected with the VIC or B.1.1.7 (Alpha) strain of SARS-CoV-2.

We have collected a sample of the \(p\)-values from this data set, and these are available on the LMS in the file sars_data.csv. This data has been sourced from publicly available data on the NCBI Gene Expression Omnibus website4.

4.1

Download the file sars_data.csv now, and store it in your working directory.

4.2

Read the sars_data.csv file into R, and store it in the object sars_data.

Use the head and summary R commands to take a quick look at this data.

Hint: Recall that you can use the function read.csv to load a .csv file into R.

4.3

The \(p\)-values samples we have selected are computed for gene expression comparisons made between cases and controls at 2 hours, 8 hours, and 24 hours post-infection. For example, the column pvalue.Mock_vs_VIC_2h contains \(p\)-values for the differences between the cases and controls at 2 hours post-infection.

To begin, we will focus on the pvalue.Mock_vs_VIC_2h column.

Run the R code below to determine the number of genes that are considered significantly differentially expressed at the \(\alpha = 0.01\) level of significance (at the 2 hour post-infection mark).

# First, we select only the values in the 
# `pvalue.Mock_vs_VIC_2h` column that are less than 0.01
sars_data_2h_base <- sars_data[sars_data$pvalue.Mock_vs_VIC_2h < 0.01,]
# Then we assess the number of rows remaining - each row represents a gene
nrow(sars_data_2h_base)

4.4

Use the p.adjust function to perform FDR correction on the pvalue.Mock_vs_VIC_2h \(p\)-values, and store your results in a new column in the sars_data object. You can use the R code below as a starting point - just fill in the missing ...’s.

sars_data$pvalue_VIC_2h_fdr <- ...

4.5

Determine the number of genes at the 2 hour post-infection mark that are, according to your FDR results, significantly differentially expressed at the \(\alpha = 0.01\) level of significance. Compare this with your initial results.

Hint: Use the R code in 4.3 as a guide.

4.6

Repeat the process conducted in 4.3 to 4.5 for the other two time points, and record your findings. Why do you think it is important in this example to be able to determine gene expression differences at different time points?


Great job, that’s everything for today.

This was a shorter lab, so you might like to use any remaining time to work on your assessments, or take a look at the reading material for the next Topic.

If you have any questions about Assignment 2, please ask for help.


References

Benjamini, Y., and Y. Hochberg. 1995. “Controlling the False Discovery Rate: A Practical and Powerful Approach to Multiple Testing.” J. R. Statist. Soc. B 57 (1): 289–300.
Storey, J. D., and R. Tibshirani. 2003. “Statistical Significance for Genomewide Studies.” PNAS 100 (16): 9440–45.


These notes have been prepared by Rupert Kuveke and Amanda Shaker. The copyright for the material in these notes resides with the authors named above, with the Department of Mathematics and Statistics and with La Trobe University. Copyright in this work is vested in La Trobe University including all La Trobe University branding and naming. Unless otherwise stated, material within this work is licensed under a Creative Commons Attribution-Non Commercial-Non Derivatives License BY-NC-ND.


  1. See e.g. Storey and Tibshirani (2003).↩︎

  2. See Benjamini and Hochberg (1995).↩︎

  3. Please note that at the time of writing, this research has not been published as an academic research paper.↩︎

  4. Series GSE184932.↩︎

LS0tDQp0aXRsZTogIlNUTTEwMDE6IENvbXB1dGVyIExhYiA3QiINCm91dHB1dDoNCiAgYm9va2Rvd246Omh0bWxfZG9jdW1lbnQyOiANCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZmxvYXQ6IHRydWUNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgdGhlbWU6IHJlYWRhYmxlDQogICAgY29kZV9mb2xkaW5nOiBzaG93DQpiaWJsaW9ncmFwaHk6IFNUTTEwMDFfRFNfQ0xfcmVmZXJlbmNlcy5iaWIgDQpsaW5rLWNpdGF0aW9uczogeWVzDQotLS0NCg0KPHN0eWxlPg0KI1RPQyB7DQogIGJhY2tncm91bmQ6IHVybCgiaHR0cHM6Ly93d3cubGF0cm9iZS5lZHUuYXUvX21lZGlhL2xhLXRyb2JlLWFwaS92NS9pbWcvbG9nby5zdmciKTsNCiAgYmFja2dyb3VuZC1zaXplOiBjb250YWluOw0KICBwYWRkaW5nLXRvcDogODBweCAhaW1wb3J0YW50Ow0KICBiYWNrZ3JvdW5kLXJlcGVhdDogbm8tcmVwZWF0Ow0KfQ0KPC9zdHlsZT4NCg0KIyMjIFNjaWVuY2UvSGVhbHRoIFNjaWVuY2UvRGF0YSBTY2llbmNlIE1vZHVsZSB7LX0NCg0KIyMjIFRvcGljIDdCOiBCaWcgRGF0YSBJSSAoJHAkLXZhbHVlIGFkanVzdG1lbnRzKSB7LX0NCg0KPGJyPg0KDQpXZWxjb21lIHRvIHRoZSBzZXZlbnRoIGNvbXB1dGVyIGxhYiBmb3IgdGhlIFNjaWVuY2UsIEhlYWx0aCBTY2llbmNlIGFuZCBEYXRhIFNjaWVuY2UgbW9kdWxlcy4NCkluIHRoaXMgY29tcHV0ZXIgbGFiIHdlIHdpbGwgbG9vayBhdCBtZXRob2RzIGZvciBhZGp1c3RpbmcgJHAkLXZhbHVlcyBvYnRhaW5lZCB3aGVuIGNvbmR1Y3RpbmcgbXVsdGlwbGUgaW5mZXJlbmNlcy4NCg0KVGhpcyBjb21wdXRlciBsYWIgaW50cm9kdWNlcyBzb21lIGJpb2xvZ3kgdGVybWlub2xvZ3kuIFRoZXJlZm9yZSwgaXQgaXMgcmVjb21tZW5kZWQgdGhhdCB5b3UgcmVhZCBvdmVyIHNlY3Rpb25zIDIuMSB0byAyLjMgb2YgdGhlIFtJbnRyb2R1Y3Rpb24gdG8gQmlvaW5mb3JtYXRpY3MgaW4gUiBzdXBwbGVtZW50XShodHRwczovL2Jvb2tkb3duLm9yZy9yZWhrL3N0bTEwMDFfZHNtX2ludHJvZHVjdGlvbl90b19iaW9pbmZvcm1hdGljc19pbl9yLykuIFRoZSBtYXRlcmlhbCBpbiB0aGlzIHN1cHBsZW1lbnQgcHJvdmlkZXMgYWxsIHRoZSBiYWNrZ3JvdW5kIGluZm9ybWF0aW9uIHlvdSB3aWxsIG5lZWQuIA0KDQpCeSB0aGUgZW5kIG9mIHRoaXMgbGFiLCB5b3Ugc2hvdWxkIHVuZGVyc3RhbmQgaG93IHRvIGFkanVzdCAkcCQtdmFsdWVzIHRvIGNvdW50ZXJhY3QgdGhlIGVmZmVjdHMgb2YgY29uZHVjdGluZyBtdWx0aXBsZSB0ZXN0cyBzaW11bHRhbmVvdXNseS4gTGV0J3MgZ2V0IHN0YXJ0ZWQhDQoNCiMgSW50cm9kdWN0aW9uDQoNCkJ5IG5vdywgeW91IHNob3VsZCBiZSBmYW1pbGlhciB3aXRoIHRoZSBjb25jZXB0IG9mIGEgaHlwb3RoZXNpcyB0ZXN0LiBZb3Ugc2hvdWxkIGFsc28gZmVlbCBjb21mb3J0YWJsZSBjb25kdWN0aW5nIGEgc3RhdGlzdGljYWwgdGVzdCB0aGF0IGludm9sdmVzIGNvbXB1dGluZyBhICRwJC12YWx1ZSB0byBjb21wYXJlIGEgbnVsbCBoeXBvdGhlc2lzIGFnYWluc3QgYW4gYWx0ZXJuYXRpdmUgaHlwb3RoZXNpcyAoYSBzaW1wbGUgZXhhbXBsZSB3b3VsZCBiZSBhbiBpbmRlcGVuZGVudCBzYW1wbGVzICR0JC10ZXN0IHRvIGFzc2VzcyB0aGUgZGlmZmVyZW5jZSBpbiB0aGUgbWVhbiB2YWx1ZSBvZiBhIHZhcmlhYmxlIGJldHdlZW4gdHdvIGdyb3VwcykuDQoNCkluIG1hbnkgc2l0dWF0aW9ucyBob3dldmVyLCB3ZSBtYXkgYmUgaW50ZXJlc3RlZCBpbiBwZXJmb3JtaW5nIGEgaHlwb3RoZXNpcyB0ZXN0IG9uIG11bHRpcGxlIGZlYXR1cmVzIHNpbXVsdGFuZW91c2x5LiBGb3IgZXhhbXBsZSwgaW4gYmlvbG9neSwgaXQgaXMgbm93IGNvbW1vbiBmb3IgdGhvdXNhbmRzIG9mIGZlYXR1cmVzIHRvIGJlIHRlc3RlZCBhZ2FpbnN0IGEgbnVsbCBoeXBvdGhlc2lzICh3aGVyZSB0aGUgZXhwZWN0YXRpb24gaXMgdGhhdCBhIG51bWJlciBvZiBmZWF0dXJlcyB3aWxsIGJlIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQpLg0KDQpVbmZvcnR1bmF0ZWx5LCB3aGVuIHdlIGNvbmR1Y3QgbXVsdGlwbGUgdGVzdHMsIHRoZSBwcm9iYWJpbGl0eSBvZiBvYnRhaW5pbmcgYSBmYWxzZSBwb3NpdGl2ZSBha2EgVHlwZSBJIGVycm9yIHdpbGwgYmVjb21lIGluZmxhdGVkLCBtZWFuaW5nIHRoYXQgdGhlIG9yaWdpbmFsIHNpZ25pZmljYW5jZSBsZXZlbCBvZiAkXGFscGhhJCBkZXNpZ25hdGVkIGZvciBhIHNpbmdsZSB0ZXN0IGRvZXMgbm90IGhvbGQuDQoNCiMjIEV4YW1wbGUNCg0KQXMgYSBzaW1wbGUgZXhhbXBsZSwgc3VwcG9zZSB0aGF0IHdlIHNldCAkXGFscGhhID0gMC4wNSQgZm9yIGEgc2luZ2xlIHRlc3QuIFRoZXJlZm9yZSwgdGhlIHByb2JhYmlsaXR5IG9mIG5vdCBvYnNlcnZpbmcgYSBUeXBlIEkgZXJyb3IgZm9yIHRoaXMgdGVzdCBpcyAkMS1cYWxwaGEgPSAwLjk1JC4gU28gZmFyLCBzbyBnb29kLg0KDQpIb3dldmVyLCBpZiB3ZSB1c2UgdGhpcyBsZXZlbCBvZiBzaWduaWZpY2FuY2UsIGFuZCBjYXJyeSBvdXQgMTAgdGVzdHMsIHRoZW4gYWN0dWFsbHkgdGhlIHByb2JhYmlsaXR5IG9mIG5vdCBvYnNlcnZpbmcgYSBUeXBlIEkgZXJyb3IgaW4gdGhlc2UgMTAgdGVzdHMgaXMgJCgxIC0gXGFscGhhKV57MTB9IFxhcHByb3ggMC42JC4gSW4gb3RoZXIgd29yZHMsIGJ5IGNhcnJ5aW5nIG91dCBtdWx0aXBsZSB0ZXN0aW5nLCBvdXIgcHJvYmFiaWxpdHkgb2YgVHlwZSBJIGVycm9yIGhhcyBpbmNyZWFzZWQgZnJvbSAkNVwlJCB0byAkNDBcJSQhIEFzIHRoZSBudW1iZXIgb2YgdGVzdHMgaW5jcmVhc2VzLCB0aGlzIGVycm9yIHJhdGUgd2lsbCBjb250aW51ZSB0byByaXNlLg0KDQojIFRoZSBgcC5hZGp1c3RgIGZ1bmN0aW9uDQoNCkZvcnR1bmF0ZWx5LCB0aGVyZSBhcmUgc2V2ZXJhbCBtZXRob2RzIHdlIGNhbiB1c2UgaW4gUiB0byBhZGp1c3QgJHAkLXZhbHVlcyBvYnRhaW5lZCBmcm9tIHBlcmZvcm1pbmcgbXVsdGlwbGUgdGVzdHMuDQpXZSBoYXZlIGFscmVhZHkgY29tZSBhY3Jvc3Mgb25lIHN1Y2ggYWRqdXN0bWVudCBpbiB0aGUgW1RvcGljIDcgUmVhZGluZ3NdKGh0dHBzOi8vYm9va2Rvd24ub3JnL2Ffc2hha2VyL1NUTTEwMDFfVG9waWNfNy81LXBvc3QtaG9jLXRlc3RzLmh0bWwpOiB0aGUgVHVrZXkgYWRqdXN0bWVudCwgd2hpY2ggd2FzIHVzZWQgdG8gY2Fycnkgb3V0IHBvc3QtaG9jIHRlc3RzIGFmdGVyIGNhcnJ5aW5nIG91dCBhIE9uZS13YXkgQU5PVkEuIA0KDQpJbiB0aGlzIGNvbXB1dGVyIGxhYiwgd2Ugd2lsbCBsZWFybiBhYm91dCBvdGhlciB0eXBlcyBvZiBhZGp1c3RtZW50cyB3aGljaCBtYXkgYmUgbW9yZSBhcHByb3ByaWF0ZSBpbiBkaWZmZXJlbnQgc2V0dGluZ3MuIA0KTW9zdCBvZiB0aGVzZSBhZGp1c3RtZW50cyBjYW4gYmUgYXBwbGllZCB1c2luZyB0aGUgUiBmdW5jdGlvbiBgcC5hZGp1c3RgLiBMZXQncyB0YWtlIGEgbG9vay4NCg0KIyMNCg0KU3VwcG9zZSB0aGF0IHdlIGhhdmUgY29tcGFyZWQgZ2VuZSBleHByZXNzaW9uIGxldmVscyBiZXR3ZWVuIHR3byBncm91cHMgb2YgaW5kaXZpZHVhbHMgKGNhc2VzIGFuZCBjb250cm9scykgZm9yIDEwIGtleSBnZW5lcyBvZiBpbnRlcmVzdC4gQXMgYSByZXN1bHQsIHdlIGhhdmUgb2J0YWluZWQgYSBzZXQgb2YgMTAgJHAkLXZhbHVlcyAob25lIGZvciBlYWNoIGdlbmUpLiBUaGVzZSAkcCQtdmFsdWVzIGFyZSBwcmVzZW50ZWQgYmVsb3c6DQoNCiQwLjAwMDMsIDAuMDA4NSwgMC4wMDEsIDAuMDAwMSwgMC4wNDUsIDAuNjIsIDAuMDA5LCAwLjE4LCAwLjkyLCAwLjAyLiQNCg0KU3RvcmUgdGhlc2UgdmFsdWVzIGluIGEgdmVjdG9yIGNhbGxlZCBgYmFzZV9wX3ZhbHVlc2AuDQoNCiMjDQoNCklmIHdlIGFzc2Vzc2VkIHRoZXNlICRwJC12YWx1ZXMgYmFzZWQgb24gYW4gJFxhbHBoYSQgdmFsdWUgb2YgJDAuMDUkLCBob3cgbWFueSBnZW5lcyB3b3VsZCB3ZSBmaW5kIHRvIGhhdmUgc2lnbmlmaWNhbnQgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYmV0d2VlbiB0aGUgY2FzZXMgYW5kIGNvbnRyb2xzPw0KDQojIyB7I2JvbmZlcnJvbml9DQoNCkEgc2ltcGxlIHdheSB0byBhZGp1c3Qgb3VyIGluaXRpYWwgJHAkLXZhbHVlcyBpcyB0byBtdWx0aXBseSBlYWNoICRwJC12YWx1ZSBieSB0aGUgbnVtYmVyIG9mICRwJC12YWx1ZXMgd2UgaGF2ZSAod2l0aCBhbnkgcmVzdWx0YW50IHZhbHVlcyBvdmVyIDEgc2NhbGVkIGJhY2sgdG8gMSkuIFRoaXMgaXMga25vd24gYXMgdGhlICpCb25mZXJyb25pIGNvcnJlY3Rpb24qICBtZXRob2QuDQoNClJ1biB0aGUgY29kZSBiZWxvdyB0byBjb25kdWN0IHRoaXMgYWRqdXN0bWVudDoNCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBGLCBlY2hvID0gVCwgd2FybmluZyA9IEYsIG1lc3NhZ2UgPSBGfQ0KcC5hZGp1c3QoYmFzZV9wX3ZhbHVlcywgbWV0aG9kID0gImJvbmZlcnJvbmkiKQ0KYGBgDQoNCiMjDQoNCkFzc2Vzc2luZyB0aGUgYWRqdXN0ZWQgJHAkLXZhbHVlcywgaG93IG1hbnkgb2YgdGhlIGdlbmVzIHJlbWFpbiBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCwgYXQgdGhlICRcYWxwaGEgPSAwLjA1JCBsZXZlbCBvZiBzaWduaWZpY2FuY2U/DQoNCiMjDQoNCkFzIHlvdSB3aWxsIGhhdmUgbm90aWNlZCwgdGhlIEJvbmZlcnJvbmkgY29ycmVjdGlvbiBpcyBxdWl0ZSBjb25zZXJ2YXRpdmUsIGFuZCBpbiBwcmFjdGljZSBjYW4gb2Z0ZW4gbGVhZCB0byByZWplY3RpbmcgdHJ1ZSBwb3NpdGl2ZXMgKGVzcGVjaWFsbHkgd2hlbiBkZWFsaW5nIHdpdGggbGFyZ2VyIG51bWJlcnMgb2YgdGVzdHMpLg0KVGhpcyBpcyBiZWNhdXNlIHRoZSBhZGp1c3RtZW50IG1ldGhvZCBmb2N1c2VzIG9uIGNvbnRyb2xsaW5nIHRoZSBwcm9iYWJpbGl0eSBvZiBtYWtpbmcgb25lIG9yIG1vcmUgVHlwZSBJIGVycm9ycyB3aGVuIGNvbmR1Y3RpbmcgbXVsdGlwbGUgdGVzdHMuIFRoaXMgcHJvYmFiaWxpdHkgaXMga25vd24gYXMgdGhlIGZhbWlseS13aXNlIGVycm9yIHJhdGUgKEZXRVIpLg0KDQojIw0KDQpUaGUgYHAuYWRqdXN0YCBmdW5jdGlvbiBjb250YWlucyBvcHRpb25zIGZvciBzZXZlcmFsIG90aGVyIG1ldGhvZHMgd2hpY2ggZm9jdXMgb24gY29udHJvbGxpbmcgdGhlIEZXRVIuIFRha2UgYSBsb29rIGF0IHRoZSBoZWxwIGZpbGUgZm9yIHRoZSBgcC5hZGp1c3RgIGZ1bmN0aW9uLCBhbmQgdHJ5IHVzaW5nIHRoZSBvdGhlciB0aHJlZSBGV0VSLWNvbnRyb2wgbWV0aG9kcy4gDQoNCkNvbXBhcmUgYW5kIGNvbnRyYXN0IHlvdXIgcmVzdWx0cywgdXNpbmcgdGhlIFIgY29kZSBiZWxvdyBhcyBhIGd1aWRlOg0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1zaG93IiwgZXZhbCA9IEYsIGVjaG8gPSBULCB3YXJuaW5nID0gRiwgbWVzc2FnZSA9IEZ9DQojIFdlIGNhbiBjb21wdXRlIHRoZSBudW1iZXIgb2Ygc2lnbmlmaWNhbnQgcmVzdWx0cyBvYnRhaW5lZCBieSBhIG1ldGhvZCB2aWE6DQpzdW0ocC5hZGp1c3QoYmFzZV9wX3ZhbHVlcywgbWV0aG9kID0gImhvbG0iKSA8IC4wNSkNCiMgTm90ZSBoZXJlIHdlIHVzZSB0aGUgYGhvbG1gIG1ldGhvZA0KYGBgDQoNCiMgRmFsc2UgRGlzY292ZXJ5IFJhdGUNCg0KQSBtb3JlIGZsZXhpYmxlIGFuZCBtb3JlIHBvd2VyZnVsIGFsdGVybmF0aXZlIHRvIGNvbnRyb2xsaW5nIHRoZSBGV0VSIGlzIHRvIGNvbnRyb2wgdGhlICpGYWxzZSBEaXNjb3ZlcnkgUmF0ZSogKEZEUikgd2hlbiBjb25kdWN0aW5nIG11bHRpcGxlIHRlc3RzLiBXaGVuIGRlYWxpbmcgd2l0aCBCaWcgRGF0YSwgdXNpbmcgdGhlIEZEUiBpcyBnZW5lcmFsbHkgcHJlZmVycmVkIG92ZXIgbW9yZSBjb25zZXJ2YXRpdmUgYWRqdXN0bWVudHMgc3VjaCBhcyBCb25mZXJvbm5pIGNvcnJlY3Rpb24uIEZEUiBjb250cm9sIGlzIGFsc28gdHlwaWNhbGx5IGZhdm91cmVkIG92ZXIgRldFUiBjb250cm9sIGluIGJpb2xvZ2ljYWwgc3R1ZGllcyBpbnZvbHZpbmcgQmlnIERhdGFeW1NlZSBlLmcuIEBTdG9yZXkuXS4NCg0KVGhlIEZEUiBjYW4gYmUgZGVmaW5lZCBhcyB0aGUgZXhwZWN0ZWQgcHJvcG9ydGlvbiBvZiBlcnJvcnMgKGkuZS4gZmFsc2UgZGlzY292ZXJpZXMpIGFtb25nIHRoZSByZWplY3RlZCBoeXBvdGhlc2VzXltTZWUgQGNvbnRyb2xGRFIuXS4gQ29udHJvbGxpbmcgdGhlIEZEUiBoZWxwcyB0byByZWR1Y2UgZmFsc2UgcG9zaXRpdmVzLCBidXQgYWxzbyBoZWxwcyBtaW5pbWlzZSBmYWxzZSBuZWdhdGl2ZXMuIA0KDQojIyB7I2Zkcn0NCg0KV2UgY2FuIGFwcGx5IEZEUiBjb3JyZWN0aW9uIHRvICRwJC12YWx1ZXMgdXNpbmcgdGhlIFIgZnVuY3Rpb24gYHAuYWRqdXN0YCAtIGp1c3Qgc3BlY2lmeSB0aGUgbWV0aG9kIGBmZHJgLiANCg0KVHJ5IHRoaXMgbm93LCBvbiBvdXIgYGJhc2VfcF92YWx1ZXNgIHZlY3RvciBvZiAkcCQtdmFsdWVzLg0KDQojIw0KDQpDb21wYXJlIHlvdXIgRkRSIHJlc3VsdHMgZnJvbSBcQHJlZihmZHIpIHRvIHlvdXIgQm9uZmVycm9uaSBjb3JyZWN0aW9uIHJlc3VsdHMgaW4gXEByZWYoYm9uZmVycm9uaSkuIFdoYXQgZG8geW91IG5vdGljZT8NCg0KIyBTQVJTLUNvVi0yIFN0dWR5ICRwJC12YWx1ZXMNCg0KVG8gY29uY2x1ZGUgdGhpcyBjb21wdXRlciBsYWIsIGxldCdzIHRha2UgYSBsb29rIGF0IGEgcmVhbC13b3JsZCBhcHBsaWNhdGlvbiBvZiAkcCQtdmFsdWUgYWRqdXN0bWVudC4gDQoNCkZvciB0aGlzIGV4YW1wbGUsIHdlIHdpbGwgbG9vayBhdCAkcCQtdmFsdWVzIGNvbXB1dGVkIGFzIHBhcnQgb2YgYW4gT3hmb3JkIFVuaXZlcnNpdHkgZXhwcmVzc2lvbiBwcm9maWxpbmcgc3R1ZHkgcmVsYXRpbmcgdG8gU0FSUy1Db1YtMiAoQ29yb25hdmlydXMpLiBJbmZvcm1hdGlvbiBvbiB0aGUgc3R1ZHkgY2FuIGJlIGZvdW5kIFtoZXJlXShodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L2dlby9xdWVyeS9hY2MuY2dpP2FjYz1HU0UxODQ5MzIpXltQbGVhc2Ugbm90ZSB0aGF0IGF0IHRoZSB0aW1lIG9mIHdyaXRpbmcsIHRoaXMgcmVzZWFyY2ggaGFzIG5vdCBiZWVuIHB1Ymxpc2hlZCBhcyBhbiBhY2FkZW1pYyByZXNlYXJjaCBwYXBlci5dLiANCg0KV2Ugd29uJ3QgZ28gaW50byBhbGwgdGhlIGRldGFpbHMgb2YgdGhlIHN0dWR5LiBTdWZmaWNlIHRvIHNheSB0aGF0IGFzIHBhcnQgb2YgdGhlIHN0dWR5LCAkcCQtdmFsdWVzIHdlcmUgY29tcHV0ZWQgd2hlbiBjb21wYXJpbmcgZ2VuZSBleHByZXNzaW9uIGRpZmZlcmVuY2VzIG92ZXIgdGltZSwgZm9yIGh1bWFuIGNlbGxzIGluZmVjdGVkIHdpdGggdGhlIFZJQyBvciBCLjEuMS43IChBbHBoYSkgc3RyYWluIG9mIFNBUlMtQ29WLTIuIA0KDQpXZSBoYXZlIGNvbGxlY3RlZCBhIHNhbXBsZSBvZiB0aGUgJHAkLXZhbHVlcyBmcm9tIHRoaXMgZGF0YSBzZXQsIGFuZCB0aGVzZSBhcmUgYXZhaWxhYmxlIG9uIHRoZSBMTVMgaW4gdGhlIGZpbGUgYHNhcnNfZGF0YS5jc3ZgLiBUaGlzIGRhdGEgaGFzIGJlZW4gc291cmNlZCBmcm9tIHB1YmxpY2x5IGF2YWlsYWJsZSBkYXRhIG9uIHRoZSBOQ0JJIEdlbmUgRXhwcmVzc2lvbiBPbW5pYnVzIHdlYnNpdGVeW1NlcmllcyBHU0UxODQ5MzIuXS4NCg0KIyMNCg0KRG93bmxvYWQgdGhlIGZpbGUgYHNhcnNfZGF0YS5jc3ZgIG5vdywgYW5kIHN0b3JlIGl0IGluIHlvdXIgd29ya2luZyBkaXJlY3RvcnkuDQoNCiMjDQoNClJlYWQgdGhlIGBzYXJzX2RhdGEuY3N2YCBmaWxlIGludG8gUiwgYW5kIHN0b3JlIGl0IGluIHRoZSBvYmplY3QgYHNhcnNfZGF0YWAuDQoNClVzZSB0aGUgYGhlYWRgIGFuZCBgc3VtbWFyeWAgUiBjb21tYW5kcyB0byB0YWtlIGEgcXVpY2sgbG9vayBhdCB0aGlzIGRhdGEuDQoNCipIaW50OiBSZWNhbGwgdGhhdCB5b3UgY2FuIHVzZSB0aGUgZnVuY3Rpb24gYHJlYWQuY3N2YCB0byBsb2FkIGEgLmNzdiBmaWxlIGludG8gUi4qDQoNCiMjIHsjc3RhcnR9DQoNClRoZSAkcCQtdmFsdWVzIHNhbXBsZXMgd2UgaGF2ZSBzZWxlY3RlZCBhcmUgY29tcHV0ZWQgZm9yIGdlbmUgZXhwcmVzc2lvbiBjb21wYXJpc29ucyBtYWRlIGJldHdlZW4gY2FzZXMgYW5kIGNvbnRyb2xzIGF0IDIgaG91cnMsIDggaG91cnMsIGFuZCAyNCBob3VycyBwb3N0LWluZmVjdGlvbi4gRm9yIGV4YW1wbGUsIHRoZSBjb2x1bW4gYHB2YWx1ZS5Nb2NrX3ZzX1ZJQ18yaGAgY29udGFpbnMgJHAkLXZhbHVlcyBmb3IgdGhlIGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIGNhc2VzIGFuZCBjb250cm9scyBhdCAyIGhvdXJzIHBvc3QtaW5mZWN0aW9uLg0KDQpUbyBiZWdpbiwgd2Ugd2lsbCBmb2N1cyBvbiB0aGUgYHB2YWx1ZS5Nb2NrX3ZzX1ZJQ18yaGAgY29sdW1uLg0KDQpSdW4gdGhlIFIgY29kZSBiZWxvdyB0byBkZXRlcm1pbmUgdGhlIG51bWJlciBvZiBnZW5lcyB0aGF0IGFyZSBjb25zaWRlcmVkIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGF0IHRoZSAkXGFscGhhID0gMC4wMSQgbGV2ZWwgb2Ygc2lnbmlmaWNhbmNlIChhdCB0aGUgMiBob3VyIHBvc3QtaW5mZWN0aW9uIG1hcmspLg0KDQoNCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBGLCBlY2hvID0gVCwgd2FybmluZyA9IEYsIG1lc3NhZ2UgPSBGfQ0KIyBGaXJzdCwgd2Ugc2VsZWN0IG9ubHkgdGhlIHZhbHVlcyBpbiB0aGUgDQojIGBwdmFsdWUuTW9ja192c19WSUNfMmhgIGNvbHVtbiB0aGF0IGFyZSBsZXNzIHRoYW4gMC4wMQ0Kc2Fyc19kYXRhXzJoX2Jhc2UgPC0gc2Fyc19kYXRhW3NhcnNfZGF0YSRwdmFsdWUuTW9ja192c19WSUNfMmggPCAwLjAxLF0NCiMgVGhlbiB3ZSBhc3Nlc3MgdGhlIG51bWJlciBvZiByb3dzIHJlbWFpbmluZyAtIGVhY2ggcm93IHJlcHJlc2VudHMgYSBnZW5lDQpucm93KHNhcnNfZGF0YV8yaF9iYXNlKQ0KYGBgDQoNCiMjDQoNClVzZSB0aGUgYHAuYWRqdXN0YCBmdW5jdGlvbiB0byBwZXJmb3JtIEZEUiBjb3JyZWN0aW9uIG9uIHRoZSBgcHZhbHVlLk1vY2tfdnNfVklDXzJoYCAkcCQtdmFsdWVzLCBhbmQgc3RvcmUgeW91ciByZXN1bHRzIGluIGEgbmV3IGNvbHVtbiBpbiB0aGUgYHNhcnNfZGF0YWAgb2JqZWN0Lg0KWW91IGNhbiB1c2UgdGhlIFIgY29kZSBiZWxvdyBhcyBhIHN0YXJ0aW5nIHBvaW50IC0ganVzdCBmaWxsIGluIHRoZSBtaXNzaW5nIGAuLi5gJ3MuDQoNCmBgYHtyIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gRiwgZWNobyA9IFQsIHdhcm5pbmcgPSBGLCBtZXNzYWdlID0gRn0NCnNhcnNfZGF0YSRwdmFsdWVfVklDXzJoX2ZkciA8LSAuLi4NCmBgYA0KDQojIyB7I2VuZH0NCg0KRGV0ZXJtaW5lIHRoZSBudW1iZXIgb2YgZ2VuZXMgYXQgdGhlIDIgaG91ciBwb3N0LWluZmVjdGlvbiBtYXJrIHRoYXQgYXJlLCBhY2NvcmRpbmcgdG8geW91ciBGRFIgcmVzdWx0cywgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgYXQgdGhlICRcYWxwaGEgPSAwLjAxJCBsZXZlbCBvZiBzaWduaWZpY2FuY2UuIENvbXBhcmUgdGhpcyB3aXRoIHlvdXIgaW5pdGlhbCByZXN1bHRzLg0KDQoqSGludDogVXNlIHRoZSBSIGNvZGUgaW4gXEByZWYoc3RhcnQpIGFzIGEgZ3VpZGUuKg0KDQojIw0KDQpSZXBlYXQgdGhlIHByb2Nlc3MgY29uZHVjdGVkIGluIFxAcmVmKHN0YXJ0KSB0byBcQHJlZihlbmQpIGZvciB0aGUgb3RoZXIgdHdvIHRpbWUgcG9pbnRzLCBhbmQgcmVjb3JkIHlvdXIgZmluZGluZ3MuIFdoeSBkbyB5b3UgdGhpbmsgaXQgaXMgaW1wb3J0YW50IGluIHRoaXMgZXhhbXBsZSB0byBiZSBhYmxlIHRvIGRldGVybWluZSBnZW5lIGV4cHJlc3Npb24gZGlmZmVyZW5jZXMgYXQgZGlmZmVyZW50IHRpbWUgcG9pbnRzPw0KDQoNCjxicj4NCg0KIyMjIyBHcmVhdCBqb2IsIHRoYXQncyBldmVyeXRoaW5nIGZvciB0b2RheS4gIyMjIyB7LX0NCg0KIyMjIyBUaGlzIHdhcyBhIHNob3J0ZXIgbGFiLCBzbyB5b3UgbWlnaHQgbGlrZSB0byB1c2UgYW55IHJlbWFpbmluZyB0aW1lIHRvIHdvcmsgb24geW91ciBhc3Nlc3NtZW50cywgb3IgdGFrZSBhIGxvb2sgYXQgdGhlIHJlYWRpbmcgbWF0ZXJpYWwgZm9yIHRoZSBuZXh0IFRvcGljLiAjIyMjIHstfQ0KDQojIyMjIElmIHlvdSBoYXZlIGFueSBxdWVzdGlvbnMgYWJvdXQgQXNzaWdubWVudCAyLCBwbGVhc2UgYXNrIGZvciBoZWxwLiAjIyMjIHstfQ0KDQo8YnI+DQoNCiMgUmVmZXJlbmNlcyB7LSAjUmVmfQ0KPGRpdiBpZD0icmVmcyI+PC9kaXY+DQoNCjxicj4NCg0KPGZvbnQgY29sb3IgPSAiZ3JleSI+DQpUaGVzZSBub3RlcyBoYXZlIGJlZW4gcHJlcGFyZWQgYnkgUnVwZXJ0IEt1dmVrZSBhbmQgQW1hbmRhIFNoYWtlci4gVGhlIGNvcHlyaWdodCBmb3IgdGhlIG1hdGVyaWFsIGluIHRoZXNlIG5vdGVzIHJlc2lkZXMgd2l0aCB0aGUgYXV0aG9ycyBuYW1lZCBhYm92ZSwgd2l0aCB0aGUgRGVwYXJ0bWVudCBvZiBNYXRoZW1hdGljcyBhbmQgU3RhdGlzdGljcyBhbmQgd2l0aCBMYSBUcm9iZSBVbml2ZXJzaXR5LiBDb3B5cmlnaHQgaW4gdGhpcyB3b3JrIGlzIHZlc3RlZCBpbiBMYSBUcm9iZSBVbml2ZXJzaXR5IGluY2x1ZGluZyBhbGwgTGEgVHJvYmUgVW5pdmVyc2l0eSBicmFuZGluZyBhbmQgbmFtaW5nLiBVbmxlc3Mgb3RoZXJ3aXNlIHN0YXRlZCwgbWF0ZXJpYWwgd2l0aGluIHRoaXMgd29yayBpcyBsaWNlbnNlZCB1bmRlciBhIENyZWF0aXZlIENvbW1vbnMgQXR0cmlidXRpb24tTm9uIENvbW1lcmNpYWwtTm9uIERlcml2YXRpdmVzIExpY2Vuc2UgDQo8YSBocmVmID0gImh0dHBzOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy1uZC80LjAvQ0MiIHRhcmdldD0iX2JsYW5rIj4gQlktTkMtTkQuIDwvYT4NCjwvZm9udD4=