Science/Health/Data Science Streams

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


Example R code solutions for the Science/Health/Data Science Computer Lab 8, which uses data from Series GSE184932 on the NCBI Gene Expression Omnibus website are presented below.

This computer lab is designed to run alongside the content in the Foundational Biology for Analyses of Biological Data supplement. It might be helpful to have this material open as you look through these solutions.

1 Introduction

1.1 Type I error probability example

No answer required.

2 Adjusting \(p\)-values

2.1

No answer required.

2.2

Example R code is provided below.

base_p_values <- c(0.0003, 0.0085, 0.001, 0.0001, 0.045, 0.62, 0.009, 0.18, 0.92, 0.02)

2.3

There are 7 \(p\)-values below 0.05, so we would find 7 genes to be significantly differentially expressed.

2.4

p.adjust(base_p_values, method = "bonferroni")
##  [1] 0.003 0.085 0.010 0.001 0.450 1.000 0.090 1.000 1.000 0.200

2.5

Using the Bonferroni correction, we find that only 3 of the \(p\)-values are now below 0.05.

2.6

Example R code is provided below.

# Check all p-values
p.adjust(base_p_values, method = "holm")
##  [1] 0.0027 0.0595 0.0080 0.0010 0.1800 1.0000 0.0595 0.5400 1.0000 0.1000
p.adjust(base_p_values, method = "hochberg")
##  [1] 0.0027 0.0540 0.0080 0.0010 0.1800 0.9200 0.0540 0.5400 0.9200 0.1000
p.adjust(base_p_values, method = "hommel")
##  [1] 0.0027 0.0510 0.0080 0.0010 0.1800 0.9200 0.0540 0.5400 0.9200 0.1000
# Compute number of significant p-values
c(sum(p.adjust(base_p_values, method = "holm") < .05), 
  sum(p.adjust(base_p_values, method = "hochberg") < .05),
  sum(p.adjust(base_p_values, method = "hommel") < .05)
)
## [1] 3 3 3

All three methods result in 3 \(p\)-values below 0.05. The Hochberg and Hommel methods produce near-identical results.

2.7

Example R code is provided below.

# Compute number of significant p-values
c(sum(p.adjust(base_p_values, method = "holm") < .01), 
  sum(p.adjust(base_p_values, method = "hochberg") < .01),
  sum(p.adjust(base_p_values, method = "hommel") < .01)
)
## [1] 3 3 3

All three methods result in 3 \(p\)-values below 0.01. Note that the \(p\)-values themselves have not changed from 2.6, we are simply using a different threshold (level of significance) for determining if results are statistically significant or not.

3 False Discovery Rate

3.1

Example R code is provided below.

p.adjust(base_p_values, method = "fdr")
##  [1] 0.001500000 0.018000000 0.003333333 0.001000000 0.064285714 0.688888889
##  [7] 0.018000000 0.225000000 0.920000000 0.033333333

3.2

We see that there are 6 \(p\)-values below 0.05. The FDR method has been less stringent than the FWER methods, but has still reduced the number of genes considered to be statistically significant.

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

4.1

No answer required

4.2

For this question, you must have downloaded the SARS_data_subset.csv file from LMS, and either:

  • stored it in your working directory (RStudio users) or
  • loaded it into jamovi (jamovi users)

Example R code for the subsequent step is provided below.

# For RStudio, you would have run this code:
sars_data <- read.csv(file = "SARS_data_subset.csv", header = T)

# For jamovi, you would have run this code:
sars_data <- data

4.3

# Store base p-values
covid_base_p_values <- sars_data$pvalue.Alpha_8h_vs_VIC_8h

4.4

# Number of significant p-values
sum(covid_base_p_values < .05)
## [1] 703

So based on the initial \(p\)-values, there are 703 differentially expressed genes at the 8 hour post-infection time point, between the two strains.

4.5

Example R code is provided below.

covid_bonferroni_p_values <- p.adjust(covid_base_p_values, method = "bonferroni")

4.6

Example R code is provided below.

covid_fdr_p_values <- p.adjust(covid_base_p_values, method = "fdr")

4.7

sum(covid_bonferroni_p_values < 0.05)
## [1] 19
sum(covid_fdr_p_values < 0.05)
## [1] 48

Initially, we had 703 statistically significantly differentially expressed genes at the 8 hour post-infection time point, between the two strains.

We can see that following Bonferroni correction we have 19 statistically significantly differentially expressed genes, a reduction of 684 genes.

If we instead use FDR correction, we obtain 48 statistically significantly differentially expressed genes. This is a reduction of 655 genes compared to the initial un-adjusted \(p\)-values. FDR correction is more lenient than the Bonferroni correction approach, with 29 more genes considered statistically significantly differentially expressed.

4.8 Volcano Plots

No answer required.

4.9

The two volcano plots are shown below.

Note that the y-axis shows the negative of the log of the \(p\)-values, meaning that small \(p\)-values appear high on the y-axis, while large \(p\)-values are close to 0 on the y-axis.

Recall also that on the x-axis, a log-fold change of 0 signifies that a gene’s expression status has not changed between the two groups (here Alpha and VIC), while a gene with a log-fold change which is large in magnitude is likely to be biologically significant.

plot(sars_data$log2FoldChange.Alpha_8h_vs_VIC_8h, 
     -log10(covid_base_p_values), 
     main = "Volcano Plot for SARS-CoV-2 
     VIC and Alpha strains
     8h post-infection, using initial p-values",
     xlab = "log FC", ylab = "-log10(pval)",
     cex = 0.5, col = as.numeric(covid_base_p_values <= 0.05) + 1)

plot(sars_data$log2FoldChange.Alpha_8h_vs_VIC_8h, 
     -log10(covid_fdr_p_values), 
     main = "Volcano Plot for SARS-CoV-2 
     VIC and Alpha strains
     8h post-infection, using FDR-corrected p-values",
     xlab = "log FC", ylab = "-log10(pval)",
     cex = 0.5, col = as.numeric(covid_fdr_p_values <= 0.05) + 1)

Note here how many of the FDR-corrected \(p\)-values are no longer considered statistically significant. However, the genes with low FDR-corrected \(p\)-values (and thus high y-axis scores in the volcano plot) appear to have log-fold changes in gene expression which are non-zero and relatively large in magnitude. This suggests that the genes coloured red in the second volcano plot are both biologically and statistically significant - so the FDR-correction has been beneficial, and has helped filter out some genes which, while having low initial \(p\)-values, were not biologically significant in this context.

For this example, it is worth considering why it might be important to compare gene expression differences between the two coronavirus strains. For example, identifying genes which are statistically significantly differentially expressed between the two strains could help researchers develop treatments which were personalised to the different strains. Such treatments could be more effective than using a generic treatment which may have varying levels of efficacy for different strains. Can you think of any other reasons?


That’s everything covered, well done.


References


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 Mathematical and Physical Sciences 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.

LS0tDQp0aXRsZTogIlNUTTEwMDE6IENvbXB1dGVyIExhYiA4QiBTb2x1dGlvbnMiDQpvdXRwdXQ6DQogIGJvb2tkb3duOjpodG1sX2RvY3VtZW50MjogDQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIHRoZW1lOiByZWFkYWJsZQ0KICAgIGNvZGVfZm9sZGluZzogc2hvdw0KYmlibGlvZ3JhcGh5OiBTVE0xMDAxX0RTX0NMX3JlZmVyZW5jZXMuYmliIA0KbGluay1jaXRhdGlvbnM6IHllcw0KLS0tDQoNCjxzdHlsZT4NCiNUT0Mgew0KICBiYWNrZ3JvdW5kOiB1cmwoImh0dHBzOi8vd3d3LmxhdHJvYmUuZWR1LmF1L19tZWRpYS9sYS10cm9iZS1hcGkvdjUvaW1nL2xvZ28uc3ZnIik7DQogIGJhY2tncm91bmQtc2l6ZTogY29udGFpbjsNCiAgcGFkZGluZy10b3A6IDgwcHggIWltcG9ydGFudDsNCiAgYmFja2dyb3VuZC1yZXBlYXQ6IG5vLXJlcGVhdDsNCn0NCjwvc3R5bGU+DQoNCiMjIyBTY2llbmNlL0hlYWx0aC9EYXRhIFNjaWVuY2UgU3RyZWFtcyB7LX0NCg0KIyMjIFRvcGljIDhCOiBCaWcgRGF0YSBJSSAoJHAkLXZhbHVlIGFkanVzdG1lbnRzKSB7LX0NCg0KPGJyPg0KDQpFeGFtcGxlIFIgY29kZSBzb2x1dGlvbnMgZm9yIHRoZSBbU2NpZW5jZS9IZWFsdGgvRGF0YSBTY2llbmNlIENvbXB1dGVyIExhYiA4XShodHRwczovL3JwdWJzLmNvbS9MVFVfU1RNMTAwMS9TTURTTUNMOCksIHdoaWNoIHVzZXMgZGF0YSBmcm9tIFtTZXJpZXMgR1NFMTg0OTMyIG9uIHRoZSBOQ0JJIEdlbmUgRXhwcmVzc2lvbiBPbW5pYnVzIHdlYnNpdGVdKGh0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvZ2VvL3F1ZXJ5L2FjYy5jZ2k/YWNjPUdTRTE4NDkzMikgYXJlIHByZXNlbnRlZCBiZWxvdy4NCg0KVGhpcyBjb21wdXRlciBsYWIgaXMgZGVzaWduZWQgdG8gcnVuIGFsb25nc2lkZSB0aGUgY29udGVudCBpbiB0aGUgW0ZvdW5kYXRpb25hbCBCaW9sb2d5IGZvciBBbmFseXNlcyBvZiBCaW9sb2dpY2FsIERhdGEgc3VwcGxlbWVudF0oaHR0cHM6Ly9ib29rZG93bi5vcmcvcmVoay9zdG0xMDAxX2ZvdW5kYXRpb25hbF9iaW9sb2d5X2Zvcl9hbmFseXNlc19vZl9iaW9sb2dpY2FsX2RhdGEvKS4gSXQgbWlnaHQgYmUgaGVscGZ1bCB0byBoYXZlIHRoaXMgbWF0ZXJpYWwgb3BlbiBhcyB5b3UgbG9vayB0aHJvdWdoIHRoZXNlIHNvbHV0aW9ucy4NCg0KIyBJbnRyb2R1Y3Rpb24NCiANCiMjIFR5cGUgSSBlcnJvciBwcm9iYWJpbGl0eSBleGFtcGxlDQoNCk5vIGFuc3dlciByZXF1aXJlZC4NCg0KIyBBZGp1c3RpbmcgJHAkLXZhbHVlcw0KDQojIw0KDQpObyBhbnN3ZXIgcmVxdWlyZWQuDQoNCiMjIA0KDQpFeGFtcGxlIFIgY29kZSBpcyBwcm92aWRlZCBiZWxvdy4NCg0KYGBgIHtyLCBldmFsID0gVCwgaW5jbHVkZSA9IFR9DQpiYXNlX3BfdmFsdWVzIDwtIGMoMC4wMDAzLCAwLjAwODUsIDAuMDAxLCAwLjAwMDEsIDAuMDQ1LCAwLjYyLCAwLjAwOSwgMC4xOCwgMC45MiwgMC4wMikNCmBgYA0KDQojIw0KDQpUaGVyZSBhcmUgYHIgc3VtKGJhc2VfcF92YWx1ZXMgPDAuMDUpYCAkcCQtdmFsdWVzIGJlbG93IDAuMDUsIHNvIHdlIHdvdWxkIGZpbmQgYHIgc3VtKGJhc2VfcF92YWx1ZXMgPDAuMDUpYCBnZW5lcyB0byBiZSBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZC4NCg0KDQojIyANCg0KYGBgIHtyLCBldmFsID0gVCwgaW5jbHVkZSA9IFQsIG1lc3NhZ2UgPSBGLCB3YXJuaW5nID0gRn0NCnAuYWRqdXN0KGJhc2VfcF92YWx1ZXMsIG1ldGhvZCA9ICJib25mZXJyb25pIikNCmBgYA0KDQojIw0KDQpVc2luZyB0aGUgQm9uZmVycm9uaSBjb3JyZWN0aW9uLCB3ZSBmaW5kIHRoYXQgb25seSBgciBzdW0ocC5hZGp1c3QoYmFzZV9wX3ZhbHVlcywgbWV0aG9kID0gImJvbmZlcnJvbmkiKSA8MC4wNSlgIG9mIHRoZSAkcCQtdmFsdWVzIGFyZSBub3cgYmVsb3cgMC4wNS4NCg0KIyMgeyNob2xtfQ0KDQpFeGFtcGxlIFIgY29kZSBpcyBwcm92aWRlZCBiZWxvdy4NCg0KYGBgIHtyLCBldmFsID0gVCwgaW5jbHVkZSA9IFR9DQojIENoZWNrIGFsbCBwLXZhbHVlcw0KcC5hZGp1c3QoYmFzZV9wX3ZhbHVlcywgbWV0aG9kID0gImhvbG0iKQ0KcC5hZGp1c3QoYmFzZV9wX3ZhbHVlcywgbWV0aG9kID0gImhvY2hiZXJnIikNCnAuYWRqdXN0KGJhc2VfcF92YWx1ZXMsIG1ldGhvZCA9ICJob21tZWwiKQ0KDQojIENvbXB1dGUgbnVtYmVyIG9mIHNpZ25pZmljYW50IHAtdmFsdWVzDQpjKHN1bShwLmFkanVzdChiYXNlX3BfdmFsdWVzLCBtZXRob2QgPSAiaG9sbSIpIDwgLjA1KSwgDQogIHN1bShwLmFkanVzdChiYXNlX3BfdmFsdWVzLCBtZXRob2QgPSAiaG9jaGJlcmciKSA8IC4wNSksDQogIHN1bShwLmFkanVzdChiYXNlX3BfdmFsdWVzLCBtZXRob2QgPSAiaG9tbWVsIikgPCAuMDUpDQopDQpgYGANCg0KQWxsIHRocmVlIG1ldGhvZHMgcmVzdWx0IGluIDMgJHAkLXZhbHVlcyBiZWxvdyAwLjA1Lg0KVGhlIEhvY2hiZXJnIGFuZCBIb21tZWwgbWV0aG9kcyBwcm9kdWNlIG5lYXItaWRlbnRpY2FsIHJlc3VsdHMuDQoNCiMjDQoNCkV4YW1wbGUgUiBjb2RlIGlzIHByb3ZpZGVkIGJlbG93Lg0KDQpgYGAge3IsIGV2YWwgPSBULCBpbmNsdWRlID0gVH0NCiMgQ29tcHV0ZSBudW1iZXIgb2Ygc2lnbmlmaWNhbnQgcC12YWx1ZXMNCmMoc3VtKHAuYWRqdXN0KGJhc2VfcF92YWx1ZXMsIG1ldGhvZCA9ICJob2xtIikgPCAuMDEpLCANCiAgc3VtKHAuYWRqdXN0KGJhc2VfcF92YWx1ZXMsIG1ldGhvZCA9ICJob2NoYmVyZyIpIDwgLjAxKSwNCiAgc3VtKHAuYWRqdXN0KGJhc2VfcF92YWx1ZXMsIG1ldGhvZCA9ICJob21tZWwiKSA8IC4wMSkNCikNCmBgYA0KDQpBbGwgdGhyZWUgbWV0aG9kcyByZXN1bHQgaW4gMyAkcCQtdmFsdWVzIGJlbG93IDAuMDEuIE5vdGUgdGhhdCB0aGUgJHAkLXZhbHVlcyB0aGVtc2VsdmVzIGhhdmUgbm90IGNoYW5nZWQgZnJvbSBcQHJlZihob2xtKSwgd2UgYXJlIHNpbXBseSB1c2luZyBhIGRpZmZlcmVudCB0aHJlc2hvbGQgKGxldmVsIG9mIHNpZ25pZmljYW5jZSkgZm9yIGRldGVybWluaW5nIGlmIHJlc3VsdHMgYXJlIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgb3Igbm90Lg0KDQoNCiMgRmFsc2UgRGlzY292ZXJ5IFJhdGUNCg0KIyMNCg0KRXhhbXBsZSBSIGNvZGUgaXMgcHJvdmlkZWQgYmVsb3cuDQoNCmBgYCB7ciwgZXZhbCA9IFQsIGluY2x1ZGUgPSBUfQ0KcC5hZGp1c3QoYmFzZV9wX3ZhbHVlcywgbWV0aG9kID0gImZkciIpDQpgYGANCg0KIyMNCg0KV2Ugc2VlIHRoYXQgdGhlcmUgYXJlIGByIHN1bShwLmFkanVzdChiYXNlX3BfdmFsdWVzLCBtZXRob2QgPSAiZmRyIikgPCAwLjA1KWAgJHAkLXZhbHVlcyBiZWxvdyAwLjA1LiBUaGUgRkRSIG1ldGhvZCBoYXMgYmVlbiBsZXNzIHN0cmluZ2VudCB0aGFuIHRoZSBGV0VSIG1ldGhvZHMsIGJ1dCBoYXMgc3RpbGwgcmVkdWNlZCB0aGUgbnVtYmVyIG9mIGdlbmVzIGNvbnNpZGVyZWQgdG8gYmUgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudC4NCg0KIyBTQVJTLUNvVi0yIFN0dWR5ICRwJC12YWx1ZXMNCg0KIyMNCg0KTm8gYW5zd2VyIHJlcXVpcmVkDQoNCiMjDQoNCkZvciB0aGlzIHF1ZXN0aW9uLCB5b3UgbXVzdCBoYXZlIGRvd25sb2FkZWQgdGhlIGBTQVJTX2RhdGFfc3Vic2V0LmNzdmAgZmlsZSBmcm9tIExNUywgYW5kIGVpdGhlcjoNCg0KKiBzdG9yZWQgaXQgaW4geW91ciB3b3JraW5nIGRpcmVjdG9yeSAoUlN0dWRpbyB1c2Vycykgb3IgDQoqIGxvYWRlZCBpdCBpbnRvIGphbW92aSAoamFtb3ZpIHVzZXJzKQ0KDQpFeGFtcGxlIFIgY29kZSBmb3IgdGhlIHN1YnNlcXVlbnQgc3RlcCBpcyBwcm92aWRlZCBiZWxvdy4NCg0KYGBgIHtyLCBldmFsID0gRiwgaW5jbHVkZSA9IFR9DQojIEZvciBSU3R1ZGlvLCB5b3Ugd291bGQgaGF2ZSBydW4gdGhpcyBjb2RlOg0Kc2Fyc19kYXRhIDwtIHJlYWQuY3N2KGZpbGUgPSAiU0FSU19kYXRhX3N1YnNldC5jc3YiLCBoZWFkZXIgPSBUKQ0KDQojIEZvciBqYW1vdmksIHlvdSB3b3VsZCBoYXZlIHJ1biB0aGlzIGNvZGU6DQpzYXJzX2RhdGEgPC0gZGF0YQ0KYGBgDQoNCmBgYCB7ciwgZXZhbCA9IFQsIGluY2x1ZGUgPSBGfQ0Kc2Fyc19kYXRhIDwtIHJlYWQuY3N2KGZpbGUgPSAiU0FSU19kYXRhX3N1YnNldC5jc3YiLCBoZWFkZXIgPSBUKQ0KYGBgDQoNCiMjDQoNCg0KYGBgIHtyLCBldmFsID0gVCwgaW5jbHVkZSA9IFR9DQojIFN0b3JlIGJhc2UgcC12YWx1ZXMNCmNvdmlkX2Jhc2VfcF92YWx1ZXMgPC0gc2Fyc19kYXRhJHB2YWx1ZS5BbHBoYV84aF92c19WSUNfOGgNCmBgYA0KDQojIw0KDQpgYGAge3IsIGV2YWwgPSBULCBpbmNsdWRlID0gVH0NCiMgTnVtYmVyIG9mIHNpZ25pZmljYW50IHAtdmFsdWVzDQpzdW0oY292aWRfYmFzZV9wX3ZhbHVlcyA8IC4wNSkNCmBgYA0KDQpTbyBiYXNlZCBvbiB0aGUgaW5pdGlhbCAkcCQtdmFsdWVzLCB0aGVyZSBhcmUgYHIgc3VtKGNvdmlkX2Jhc2VfcF92YWx1ZXMgPCAuMDUpYCBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMgYXQgdGhlIDggaG91ciBwb3N0LWluZmVjdGlvbiB0aW1lIHBvaW50LCBiZXR3ZWVuIHRoZSB0d28gc3RyYWlucy4NCg0KIyMNCg0KRXhhbXBsZSBSIGNvZGUgaXMgcHJvdmlkZWQgYmVsb3cuDQoNCmBgYCB7ciwgZXZhbCA9IFQsIGluY2x1ZGUgPSBUfQ0KY292aWRfYm9uZmVycm9uaV9wX3ZhbHVlcyA8LSBwLmFkanVzdChjb3ZpZF9iYXNlX3BfdmFsdWVzLCBtZXRob2QgPSAiYm9uZmVycm9uaSIpDQpgYGANCg0KIyMNCg0KRXhhbXBsZSBSIGNvZGUgaXMgcHJvdmlkZWQgYmVsb3cuDQoNCmBgYCB7ciwgZXZhbCA9IFQsIGluY2x1ZGUgPSBUfQ0KY292aWRfZmRyX3BfdmFsdWVzIDwtIHAuYWRqdXN0KGNvdmlkX2Jhc2VfcF92YWx1ZXMsIG1ldGhvZCA9ICJmZHIiKQ0KYGBgDQoNCiMjDQoNCmBgYCB7ciwgZXZhbCA9IFQsIGluY2x1ZGUgPSBUfQ0Kc3VtKGNvdmlkX2JvbmZlcnJvbmlfcF92YWx1ZXMgPCAwLjA1KQ0Kc3VtKGNvdmlkX2Zkcl9wX3ZhbHVlcyA8IDAuMDUpDQpgYGANCg0KSW5pdGlhbGx5LCB3ZSBoYWQgYHIgc3VtKGNvdmlkX2Jhc2VfcF92YWx1ZXMgPCAuMDUpYCBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIGF0IHRoZSA4IGhvdXIgcG9zdC1pbmZlY3Rpb24gdGltZSBwb2ludCwgYmV0d2VlbiB0aGUgdHdvIHN0cmFpbnMuDQoNCldlIGNhbiBzZWUgdGhhdCBmb2xsb3dpbmcgQm9uZmVycm9uaSBjb3JyZWN0aW9uIHdlIGhhdmUgYHIgc3VtKGNvdmlkX2JvbmZlcnJvbmlfcF92YWx1ZXMgPCAwLjA1KWAgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcywgYSByZWR1Y3Rpb24gb2YgDQpgciBzdW0oY292aWRfYmFzZV9wX3ZhbHVlcyA8IC4wNSkgLSBzdW0oY292aWRfYm9uZmVycm9uaV9wX3ZhbHVlcyA8IDAuMDUpYCBnZW5lcy4NCg0KSWYgd2UgaW5zdGVhZCB1c2UgRkRSIGNvcnJlY3Rpb24sIHdlIG9idGFpbiBgciBzdW0oY292aWRfZmRyX3BfdmFsdWVzIDwgMC4wNSlgIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMuIFRoaXMgaXMgYSByZWR1Y3Rpb24gb2YgYHIgc3VtKGNvdmlkX2Jhc2VfcF92YWx1ZXMgPCAuMDUpIC0gc3VtKGNvdmlkX2Zkcl9wX3ZhbHVlcyA8IDAuMDUpYCBnZW5lcyBjb21wYXJlZCB0byB0aGUgaW5pdGlhbCB1bi1hZGp1c3RlZCAkcCQtdmFsdWVzLiBGRFIgY29ycmVjdGlvbiBpcyBtb3JlIGxlbmllbnQgdGhhbiB0aGUgQm9uZmVycm9uaSBjb3JyZWN0aW9uIGFwcHJvYWNoLCB3aXRoIGByIHN1bShjb3ZpZF9mZHJfcF92YWx1ZXMgPCAuMDUpIC0gc3VtKGNvdmlkX2JvbmZlcnJvbmlfcF92YWx1ZXMgPCAwLjA1KWAgbW9yZSBnZW5lcyBjb25zaWRlcmVkIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQuDQoNCiMjIFZvbGNhbm8gUGxvdHMNCg0KTm8gYW5zd2VyIHJlcXVpcmVkLg0KDQojIw0KDQpUaGUgdHdvIHZvbGNhbm8gcGxvdHMgYXJlIHNob3duIGJlbG93LiANCg0KTm90ZSB0aGF0IHRoZSB5LWF4aXMgc2hvd3MgdGhlIG5lZ2F0aXZlIG9mIHRoZSBsb2cgb2YgdGhlICRwJC12YWx1ZXMsIG1lYW5pbmcgdGhhdCBzbWFsbCAkcCQtdmFsdWVzIGFwcGVhciBoaWdoIG9uIHRoZSB5LWF4aXMsIHdoaWxlIGxhcmdlICRwJC12YWx1ZXMgYXJlIGNsb3NlIHRvIDAgb24gdGhlIHktYXhpcy4NCg0KUmVjYWxsIGFsc28gdGhhdCBvbiB0aGUgeC1heGlzLCBhIGxvZy1mb2xkIGNoYW5nZSBvZiAwIHNpZ25pZmllcyB0aGF0IGEgZ2VuZSdzIGV4cHJlc3Npb24gc3RhdHVzIGhhcyBub3QgY2hhbmdlZCBiZXR3ZWVuIHRoZSB0d28gZ3JvdXBzIChoZXJlIGBBbHBoYWAgYW5kIGBWSUNgKSwgd2hpbGUgYSBnZW5lIHdpdGggYSBsb2ctZm9sZCBjaGFuZ2Ugd2hpY2ggaXMgbGFyZ2UgaW4gbWFnbml0dWRlIGlzIGxpa2VseSB0byBiZSBiaW9sb2dpY2FsbHkgc2lnbmlmaWNhbnQuIA0KDQpgYGAge3IsIGV2YWwgPSBULCBpbmNsdWRlID0gVCwgZmlnLmRpbSA9IGMoNiw2KSwgZmlnLmFsaWduID0gImNlbnRlciJ9DQpwbG90KHNhcnNfZGF0YSRsb2cyRm9sZENoYW5nZS5BbHBoYV84aF92c19WSUNfOGgsIA0KICAgICAtbG9nMTAoY292aWRfYmFzZV9wX3ZhbHVlcyksIA0KICAgICBtYWluID0gIlZvbGNhbm8gUGxvdCBmb3IgU0FSUy1Db1YtMiANCiAgICAgVklDIGFuZCBBbHBoYSBzdHJhaW5zDQogICAgIDhoIHBvc3QtaW5mZWN0aW9uLCB1c2luZyBpbml0aWFsIHAtdmFsdWVzIiwNCiAgICAgeGxhYiA9ICJsb2cgRkMiLCB5bGFiID0gIi1sb2cxMChwdmFsKSIsDQogICAgIGNleCA9IDAuNSwgY29sID0gYXMubnVtZXJpYyhjb3ZpZF9iYXNlX3BfdmFsdWVzIDw9IDAuMDUpICsgMSkNCmBgYA0KDQpgYGAge3IsIGV2YWwgPSBULCBpbmNsdWRlID0gVCwgZmlnLmRpbSA9IGMoNiw2KSwgZmlnLmFsaWduID0gImNlbnRlciJ9DQpwbG90KHNhcnNfZGF0YSRsb2cyRm9sZENoYW5nZS5BbHBoYV84aF92c19WSUNfOGgsIA0KICAgICAtbG9nMTAoY292aWRfZmRyX3BfdmFsdWVzKSwgDQogICAgIG1haW4gPSAiVm9sY2FubyBQbG90IGZvciBTQVJTLUNvVi0yIA0KICAgICBWSUMgYW5kIEFscGhhIHN0cmFpbnMNCiAgICAgOGggcG9zdC1pbmZlY3Rpb24sIHVzaW5nIEZEUi1jb3JyZWN0ZWQgcC12YWx1ZXMiLA0KICAgICB4bGFiID0gImxvZyBGQyIsIHlsYWIgPSAiLWxvZzEwKHB2YWwpIiwNCiAgICAgY2V4ID0gMC41LCBjb2wgPSBhcy5udW1lcmljKGNvdmlkX2Zkcl9wX3ZhbHVlcyA8PSAwLjA1KSArIDEpDQpgYGANCg0KTm90ZSBoZXJlIGhvdyBtYW55IG9mIHRoZSBGRFItY29ycmVjdGVkICRwJC12YWx1ZXMgYXJlIG5vIGxvbmdlciBjb25zaWRlcmVkIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQuIEhvd2V2ZXIsIHRoZSBnZW5lcyB3aXRoIGxvdyBGRFItY29ycmVjdGVkICRwJC12YWx1ZXMgKGFuZCB0aHVzIGhpZ2ggeS1heGlzIHNjb3JlcyBpbiB0aGUgdm9sY2FubyBwbG90KSBhcHBlYXIgdG8gaGF2ZSBsb2ctZm9sZCBjaGFuZ2VzIGluIGdlbmUgZXhwcmVzc2lvbiB3aGljaCBhcmUgbm9uLXplcm8gYW5kIHJlbGF0aXZlbHkgbGFyZ2UgaW4gbWFnbml0dWRlLiBUaGlzIHN1Z2dlc3RzIHRoYXQgdGhlIGdlbmVzIGNvbG91cmVkIHJlZCBpbiB0aGUgc2Vjb25kIHZvbGNhbm8gcGxvdCBhcmUgYm90aCBiaW9sb2dpY2FsbHkgYW5kIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgLSBzbyB0aGUgRkRSLWNvcnJlY3Rpb24gaGFzIGJlZW4gYmVuZWZpY2lhbCwgYW5kIGhhcyBoZWxwZWQgZmlsdGVyIG91dCBzb21lIGdlbmVzIHdoaWNoLCB3aGlsZSBoYXZpbmcgbG93IGluaXRpYWwgJHAkLXZhbHVlcywgd2VyZSBub3QgYmlvbG9naWNhbGx5IHNpZ25pZmljYW50IGluIHRoaXMgY29udGV4dC4NCg0KRm9yIHRoaXMgZXhhbXBsZSwgaXQgaXMgd29ydGggY29uc2lkZXJpbmcgd2h5IGl0IG1pZ2h0IGJlIGltcG9ydGFudCB0byBjb21wYXJlIGdlbmUgZXhwcmVzc2lvbiBkaWZmZXJlbmNlcyBiZXR3ZWVuIHRoZSB0d28gY29yb25hdmlydXMgc3RyYWlucy4gRm9yIGV4YW1wbGUsIGlkZW50aWZ5aW5nIGdlbmVzIHdoaWNoIGFyZSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGJldHdlZW4gdGhlIHR3byBzdHJhaW5zIGNvdWxkIGhlbHAgcmVzZWFyY2hlcnMgZGV2ZWxvcCB0cmVhdG1lbnRzIHdoaWNoIHdlcmUgcGVyc29uYWxpc2VkIHRvIHRoZSBkaWZmZXJlbnQgc3RyYWlucy4gU3VjaCB0cmVhdG1lbnRzIGNvdWxkIGJlIG1vcmUgZWZmZWN0aXZlIHRoYW4gdXNpbmcgYSBnZW5lcmljIHRyZWF0bWVudCB3aGljaCBtYXkgaGF2ZSB2YXJ5aW5nIGxldmVscyBvZiBlZmZpY2FjeSBmb3IgZGlmZmVyZW50IHN0cmFpbnMuIENhbiB5b3UgdGhpbmsgb2YgYW55IG90aGVyIHJlYXNvbnM/DQoNCjxicj4NCg0KIyMjIyBUaGF0J3MgZXZlcnl0aGluZyBjb3ZlcmVkLCB3ZWxsIGRvbmUuICMjIyMgey19DQoNCjxicj4NCg0KIyBSZWZlcmVuY2VzIHstICNSZWZ9DQo8ZGl2IGlkPSJyZWZzIj48L2Rpdj4NCg0KPGJyPg0KDQo8Zm9udCBjb2xvciA9ICJncmV5Ij4NClRoZXNlIG5vdGVzIGhhdmUgYmVlbiBwcmVwYXJlZCBieSBSdXBlcnQgS3V2ZWtlIGFuZCBBbWFuZGEgU2hha2VyLiBUaGUgY29weXJpZ2h0IGZvciB0aGUgbWF0ZXJpYWwgaW4gdGhlc2Ugbm90ZXMgcmVzaWRlcyB3aXRoIHRoZSBhdXRob3JzIG5hbWVkIGFib3ZlLCB3aXRoIHRoZSBEZXBhcnRtZW50IG9mIE1hdGhlbWF0aWNhbCBhbmQgUGh5c2ljYWwgU2NpZW5jZXMgYW5kIHdpdGggTGEgVHJvYmUgVW5pdmVyc2l0eS4gQ29weXJpZ2h0IGluIHRoaXMgd29yayBpcyB2ZXN0ZWQgaW4gTGEgVHJvYmUgVW5pdmVyc2l0eSBpbmNsdWRpbmcgYWxsIExhIFRyb2JlIFVuaXZlcnNpdHkgYnJhbmRpbmcgYW5kIG5hbWluZy4gVW5sZXNzIG90aGVyd2lzZSBzdGF0ZWQsIG1hdGVyaWFsIHdpdGhpbiB0aGlzIHdvcmsgaXMgbGljZW5zZWQgdW5kZXIgYSBDcmVhdGl2ZSBDb21tb25zIEF0dHJpYnV0aW9uLU5vbiBDb21tZXJjaWFsLU5vbiBEZXJpdmF0aXZlcyBMaWNlbnNlIA0KPGEgaHJlZiA9ICJodHRwczovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMtbmQvNC4wL0NDIiB0YXJnZXQ9Il9ibGFuayI+IEJZLU5DLU5ELiA8L2E+DQo8L2ZvbnQ+