Science/Health Science/Data Science Module

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


Example R code solutions for the Week 7 Science/Health Science/Data Science Computer Lab, 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

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

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

2.3

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

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

2.5

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.

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 removed one gene from contention.

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

4.1

No answer required

4.2

Example R code is provided below.

sars_data <- read.csv(file = "SARS_data_subset.csv", header = T)

4.3

# First, we select only the values in the 
# `pvalue.Alpha_8h_vs_VIC_8h` column that are less than 0.05
sars_data_8h_base <- sars_data[sars_data$pvalue.Alpha_8h_vs_VIC_8h < 0.05,]
# Then we assess the number of rows remaining - each row represents a gene
nrow(sars_data_8h_base)
## [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.4

sars_data$fdr_adjusted_pvalue_8h <- p.adjust(sars_data$pvalue.Alpha_8h_vs_VIC_8h, method = "fdr")

4.5

Example R code is provided below.

sars_sig_fdr_pvalue_genes_8h <- sars_data[sars_data$fdr_adjusted_pvalue_8h  < 0.05,]
nrow(sars_sig_fdr_pvalue_genes_8h)
## [1] 48

We can see that following FDR correction we now have 48 significant genes, a reduction of 655 genes.

4.6 Volcano Plots

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(sars_data$pvalue.Alpha_8h_vs_VIC_8h), 
     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(sars_data$pvalue.Alpha_8h_vs_VIC_8h <= 0.05) + 1)

plot(sars_data$log2FoldChange.Alpha_8h_vs_VIC_8h, 
     -log10(sars_data$fdr_adjusted_pvalue_8h), 
     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(sars_data$fdr_adjusted_pvalue_8h <= 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. The copyright for the material in these notes resides with the author 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.

LS0tDQp0aXRsZTogIlNUTTEwMDE6IENvbXB1dGVyIExhYiA3QiBTb2x1dGlvbnMiDQpvdXRwdXQ6DQogIGJvb2tkb3duOjpodG1sX2RvY3VtZW50MjogDQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIHRoZW1lOiByZWFkYWJsZQ0KICAgIGNvZGVfZm9sZGluZzogc2hvdw0KYmlibGlvZ3JhcGh5OiBTVE0xMDAxX0RTX0NMX3JlZmVyZW5jZXMuYmliIA0KbGluay1jaXRhdGlvbnM6IHllcw0KLS0tDQoNCjxzdHlsZT4NCiNUT0Mgew0KICBiYWNrZ3JvdW5kOiB1cmwoImh0dHBzOi8vd3d3LmxhdHJvYmUuZWR1LmF1L19tZWRpYS9sYS10cm9iZS1hcGkvdjUvaW1nL2xvZ28uc3ZnIik7DQogIGJhY2tncm91bmQtc2l6ZTogY29udGFpbjsNCiAgcGFkZGluZy10b3A6IDgwcHggIWltcG9ydGFudDsNCiAgYmFja2dyb3VuZC1yZXBlYXQ6IG5vLXJlcGVhdDsNCn0NCjwvc3R5bGU+DQoNCiMjIyBTY2llbmNlL0hlYWx0aCBTY2llbmNlL0RhdGEgU2NpZW5jZSBNb2R1bGUgey19DQoNCiMjIyBUb3BpYyA3QjogQmlnIERhdGEgSUkgKCRwJC12YWx1ZSBhZGp1c3RtZW50cykgey19DQoNCjxicj4NCg0KRXhhbXBsZSBSIGNvZGUgc29sdXRpb25zIGZvciB0aGUgW1dlZWsgNyBTY2llbmNlL0hlYWx0aCBTY2llbmNlL0RhdGEgU2NpZW5jZSBDb21wdXRlciBMYWJdKGh0dHBzOi8vcnB1YnMuY29tL0xUVV9TVE0xMDAxL1NNRFNNQ0w3X1QpLCB3aGljaCB1c2VzIGRhdGEgZnJvbSBbU2VyaWVzIEdTRTE4NDkzMiBvbiB0aGUgTkNCSSBHZW5lIEV4cHJlc3Npb24gT21uaWJ1cyB3ZWJzaXRlXShodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L2dlby9xdWVyeS9hY2MuY2dpP2FjYz1HU0UxODQ5MzIpIGFyZSBwcmVzZW50ZWQgYmVsb3cuDQoNClRoaXMgY29tcHV0ZXIgbGFiIGlzIGRlc2lnbmVkIHRvIHJ1biBhbG9uZ3NpZGUgdGhlIGNvbnRlbnQgaW4gdGhlIFtGb3VuZGF0aW9uYWwgQmlvbG9neSBmb3IgQW5hbHlzZXMgb2YgQmlvbG9naWNhbCBEYXRhIHN1cHBsZW1lbnRdKGh0dHBzOi8vYm9va2Rvd24ub3JnL3JlaGsvc3RtMTAwMV90MV9mb3VuZGF0aW9uYWxfYmlvbG9neV9mb3JfYW5hbHlzZXNfb2ZfYmlvbG9naWNhbF9kYXRhLykuIEl0IG1pZ2h0IGJlIGhlbHBmdWwgdG8gaGF2ZSB0aGlzIG1hdGVyaWFsIG9wZW4gYXMgeW91IGxvb2sgdGhyb3VnaCB0aGVzZSBzb2x1dGlvbnMuDQoNCiMgSW50cm9kdWN0aW9uDQogDQojIyBUeXBlIEkgZXJyb3IgcHJvYmFiaWxpdHkgZXhhbXBsZQ0KDQpObyBhbnN3ZXIgcmVxdWlyZWQuDQoNCiMgQWRqdXN0aW5nICRwJC12YWx1ZXMNCg0KIyMgDQoNCkV4YW1wbGUgUiBjb2RlIGlzIHByb3ZpZGVkIGJlbG93Lg0KDQpgYGAge3IsIGV2YWwgPSBULCBpbmNsdWRlID0gVH0NCmJhc2VfcF92YWx1ZXMgPC0gYygwLjAwMDMsIDAuMDA4NSwgMC4wMDEsIDAuMDAwMSwgMC4wNDUsIDAuNjIsIDAuMDA5LCAwLjE4LCAwLjkyLCAwLjAyKQ0KYGBgDQoNCiMjDQoNClRoZXJlIGFyZSA3ICRwJC12YWx1ZXMgYmVsb3cgMC4wNSwgc28gd2Ugd291bGQgZmluZCA3IGdlbmVzIHRvIGJlIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkLg0KDQoNCiMjIA0KDQpgYGAge3IsIGV2YWwgPSBULCBpbmNsdWRlID0gVCwgbWVzc2FnZSA9IEYsIHdhcm5pbmcgPSBGfQ0KcC5hZGp1c3QoYmFzZV9wX3ZhbHVlcywgbWV0aG9kID0gImJvbmZlcnJvbmkiKQ0KYGBgDQoNCiMjDQoNClVzaW5nIHRoZSBCb25mZXJyb25pIGNvcnJlY3Rpb24sIHdlIGZpbmQgdGhhdCBvbmx5IDMgb2YgdGhlICRwJC12YWx1ZXMgYXJlIG5vdyBiZWxvdyAwLjA1Lg0KDQojIw0KDQpFeGFtcGxlIFIgY29kZSBpcyBwcm92aWRlZCBiZWxvdy4NCg0KYGBgIHtyLCBldmFsID0gVCwgaW5jbHVkZSA9IFR9DQojIENoZWNrIGFsbCBwLXZhbHVlcw0KcC5hZGp1c3QoYmFzZV9wX3ZhbHVlcywgbWV0aG9kID0gImhvbG0iKQ0KcC5hZGp1c3QoYmFzZV9wX3ZhbHVlcywgbWV0aG9kID0gImhvY2hiZXJnIikNCnAuYWRqdXN0KGJhc2VfcF92YWx1ZXMsIG1ldGhvZCA9ICJob21tZWwiKQ0KDQojIENvbXB1dGUgbnVtYmVyIG9mIHNpZ25pZmljYW50IHAtdmFsdWVzDQpjKHN1bShwLmFkanVzdChiYXNlX3BfdmFsdWVzLCBtZXRob2QgPSAiaG9sbSIpIDwgLjA1KSwgDQogIHN1bShwLmFkanVzdChiYXNlX3BfdmFsdWVzLCBtZXRob2QgPSAiaG9jaGJlcmciKSA8IC4wNSksDQogIHN1bShwLmFkanVzdChiYXNlX3BfdmFsdWVzLCBtZXRob2QgPSAiaG9tbWVsIikgPCAuMDUpDQopDQpgYGANCg0KQWxsIHRocmVlIG1ldGhvZHMgcmVzdWx0IGluIDMgJHAkLXZhbHVlcyBiZWxvdyAwLjA1Lg0KVGhlIEhvY2hiZXJnIGFuZCBIb21tZWwgbWV0aG9kcyBwcm9kdWNlIG5lYXItaWRlbnRpY2FsIHJlc3VsdHMuDQoNCiMgRmFsc2UgRGlzY292ZXJ5IFJhdGUNCg0KIyMNCg0KRXhhbXBsZSBSIGNvZGUgaXMgcHJvdmlkZWQgYmVsb3cuDQoNCmBgYCB7ciwgZXZhbCA9IFQsIGluY2x1ZGUgPSBUfQ0KcC5hZGp1c3QoYmFzZV9wX3ZhbHVlcywgbWV0aG9kID0gImZkciIpDQpgYGANCg0KIyMNCg0KV2Ugc2VlIHRoYXQgdGhlcmUgYXJlIDYgJHAkLXZhbHVlcyBiZWxvdyAwLjA1LiBUaGUgRkRSIG1ldGhvZCBoYXMgYmVlbiBsZXNzIHN0cmluZ2VudCB0aGFuIHRoZSBGV0VSIG1ldGhvZHMsIGJ1dCBoYXMgc3RpbGwgcmVtb3ZlZCBvbmUgZ2VuZSBmcm9tIGNvbnRlbnRpb24uDQoNCiMgU0FSUy1Db1YtMiBTdHVkeSAkcCQtdmFsdWVzDQoNCiMjDQoNCk5vIGFuc3dlciByZXF1aXJlZA0KDQojIw0KDQpFeGFtcGxlIFIgY29kZSBpcyBwcm92aWRlZCBiZWxvdy4NCg0KYGBgIHtyLCBldmFsID0gRiwgaW5jbHVkZSA9IFR9DQpzYXJzX2RhdGEgPC0gcmVhZC5jc3YoZmlsZSA9ICJTQVJTX2RhdGFfc3Vic2V0LmNzdiIsIGhlYWRlciA9IFQpDQpgYGANCg0KYGBgIHtyLCBldmFsID0gVCwgaW5jbHVkZSA9IEZ9DQpzYXJzX2RhdGEgPC0gcmVhZC5jc3YoZmlsZSA9ICJTQVJTX2RhdGFfc3Vic2V0LmNzdiIsIGhlYWRlciA9IFQpDQpgYGANCg0KIyMNCg0KYGBgIHtyLCBldmFsID0gVCwgaW5jbHVkZSA9IFR9DQojIEZpcnN0LCB3ZSBzZWxlY3Qgb25seSB0aGUgdmFsdWVzIGluIHRoZSANCiMgYHB2YWx1ZS5BbHBoYV84aF92c19WSUNfOGhgIGNvbHVtbiB0aGF0IGFyZSBsZXNzIHRoYW4gMC4wNQ0Kc2Fyc19kYXRhXzhoX2Jhc2UgPC0gc2Fyc19kYXRhW3NhcnNfZGF0YSRwdmFsdWUuQWxwaGFfOGhfdnNfVklDXzhoIDwgMC4wNSxdDQojIFRoZW4gd2UgYXNzZXNzIHRoZSBudW1iZXIgb2Ygcm93cyByZW1haW5pbmcgLSBlYWNoIHJvdyByZXByZXNlbnRzIGEgZ2VuZQ0KbnJvdyhzYXJzX2RhdGFfOGhfYmFzZSkNCmBgYA0KDQpTbyBiYXNlZCBvbiB0aGUgaW5pdGlhbCAkcCQtdmFsdWVzLCB0aGVyZSBhcmUgNzAzIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyBhdCB0aGUgOCBob3VyIHBvc3QtaW5mZWN0aW9uIHRpbWUgcG9pbnQsIGJldHdlZW4gdGhlIHR3byBzdHJhaW5zLg0KDQojIw0KDQpgYGAge3IsIGV2YWwgPSBULCBpbmNsdWRlID0gVH0NCnNhcnNfZGF0YSRmZHJfYWRqdXN0ZWRfcHZhbHVlXzhoIDwtIHAuYWRqdXN0KHNhcnNfZGF0YSRwdmFsdWUuQWxwaGFfOGhfdnNfVklDXzhoLCBtZXRob2QgPSAiZmRyIikNCmBgYA0KDQojIw0KDQpFeGFtcGxlIFIgY29kZSBpcyBwcm92aWRlZCBiZWxvdy4NCg0KYGBgIHtyLCBldmFsID0gVCwgaW5jbHVkZSA9IFR9DQpzYXJzX3NpZ19mZHJfcHZhbHVlX2dlbmVzXzhoIDwtIHNhcnNfZGF0YVtzYXJzX2RhdGEkZmRyX2FkanVzdGVkX3B2YWx1ZV84aCAgPCAwLjA1LF0NCm5yb3coc2Fyc19zaWdfZmRyX3B2YWx1ZV9nZW5lc184aCkNCmBgYA0KDQpXZSBjYW4gc2VlIHRoYXQgZm9sbG93aW5nIEZEUiBjb3JyZWN0aW9uIHdlIG5vdyBoYXZlIGByIG5yb3coc2Fyc19zaWdfZmRyX3B2YWx1ZV9nZW5lc184aClgIHNpZ25pZmljYW50IGdlbmVzLCBhIHJlZHVjdGlvbiBvZiBgciBucm93KHNhcnNfZGF0YV84aF9iYXNlKS1ucm93KHNhcnNfc2lnX2Zkcl9wdmFsdWVfZ2VuZXNfOGgpYCBnZW5lcy4NCg0KIyMgVm9sY2FubyBQbG90cw0KDQpUaGUgdHdvIHZvbGNhbm8gcGxvdHMgYXJlIHNob3duIGJlbG93LiANCg0KTm90ZSB0aGF0IHRoZSB5LWF4aXMgc2hvd3MgdGhlIG5lZ2F0aXZlIG9mIHRoZSBsb2cgb2YgdGhlICRwJC12YWx1ZXMsIG1lYW5pbmcgdGhhdCBzbWFsbCAkcCQtdmFsdWVzIGFwcGVhciBoaWdoIG9uIHRoZSB5LWF4aXMsIHdoaWxlIGxhcmdlICRwJC12YWx1ZXMgYXJlIGNsb3NlIHRvIDAgb24gdGhlIHktYXhpcy4NCg0KUmVjYWxsIGFsc28gdGhhdCBvbiB0aGUgeC1heGlzLCBhIGxvZy1mb2xkIGNoYW5nZSBvZiAwIHNpZ25pZmllcyB0aGF0IGEgZ2VuZSdzIGV4cHJlc3Npb24gc3RhdHVzIGhhcyBub3QgY2hhbmdlZCBiZXR3ZWVuIHRoZSB0d28gZ3JvdXBzIChoZXJlIGBBbHBoYWAgYW5kIGBWSUNgKSwgd2hpbGUgYSBnZW5lIHdpdGggYSBsb2ctZm9sZCBjaGFuZ2Ugd2hpY2ggaXMgbGFyZ2UgaW4gbWFnbml0dWRlIGlzIGxpa2VseSB0byBiZSBiaW9sb2dpY2FsbHkgc2lnbmlmaWNhbnQuDQoNCmBgYCB7ciwgZXZhbCA9IFQsIGluY2x1ZGUgPSBULCBmaWcuZGltID0gYyg2LDYpLCBmaWcuYWxpZ24gPSAiY2VudGVyIn0NCnBsb3Qoc2Fyc19kYXRhJGxvZzJGb2xkQ2hhbmdlLkFscGhhXzhoX3ZzX1ZJQ184aCwgDQogICAgIC1sb2cxMChzYXJzX2RhdGEkcHZhbHVlLkFscGhhXzhoX3ZzX1ZJQ184aCksIA0KICAgICBtYWluID0gIlZvbGNhbm8gUGxvdCBmb3IgU0FSUy1Db1YtMiANCiAgICAgVklDIGFuZCBBbHBoYSBzdHJhaW5zDQogICAgIDhoIHBvc3QtaW5mZWN0aW9uLCB1c2luZyBpbml0aWFsIHAtdmFsdWVzIiwNCiAgICAgeGxhYiA9ICJsb2cgRkMiLCB5bGFiID0gIi1sb2cxMChwdmFsKSIsDQogICAgIGNleCA9IDAuNSwgY29sID0gYXMubnVtZXJpYyhzYXJzX2RhdGEkcHZhbHVlLkFscGhhXzhoX3ZzX1ZJQ184aCA8PSAwLjA1KSArIDEpDQpgYGANCg0KYGBgIHtyLCBldmFsID0gVCwgaW5jbHVkZSA9IFQsIGZpZy5kaW0gPSBjKDYsNiksIGZpZy5hbGlnbiA9ICJjZW50ZXIifQ0KcGxvdChzYXJzX2RhdGEkbG9nMkZvbGRDaGFuZ2UuQWxwaGFfOGhfdnNfVklDXzhoLCANCiAgICAgLWxvZzEwKHNhcnNfZGF0YSRmZHJfYWRqdXN0ZWRfcHZhbHVlXzhoKSwgDQogICAgIG1haW4gPSAiVm9sY2FubyBQbG90IGZvciBTQVJTLUNvVi0yIA0KICAgICBWSUMgYW5kIEFscGhhIHN0cmFpbnMNCiAgICAgOGggcG9zdC1pbmZlY3Rpb24sIHVzaW5nIEZEUi1jb3JyZWN0ZWQgcC12YWx1ZXMiLA0KICAgICB4bGFiID0gImxvZyBGQyIsIHlsYWIgPSAiLWxvZzEwKHB2YWwpIiwNCiAgICAgY2V4ID0gMC41LCBjb2wgPSBhcy5udW1lcmljKHNhcnNfZGF0YSRmZHJfYWRqdXN0ZWRfcHZhbHVlXzhoIDw9IDAuMDUpICsgMSkNCmBgYA0KDQpOb3RlIGhlcmUgaG93IG1hbnkgb2YgdGhlIEZEUi1jb3JyZWN0ZWQgJHAkLXZhbHVlcyBhcmUgbm8gbG9uZ2VyIGNvbnNpZGVyZWQgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudC4gSG93ZXZlciwgdGhlIGdlbmVzIHdpdGggbG93IEZEUi1jb3JyZWN0ZWQgJHAkLXZhbHVlcyAoYW5kIHRodXMgaGlnaCB5LWF4aXMgc2NvcmVzIGluIHRoZSB2b2xjYW5vIHBsb3QpIGFwcGVhciB0byBoYXZlIGxvZy1mb2xkIGNoYW5nZXMgaW4gZ2VuZSBleHByZXNzaW9uIHdoaWNoIGFyZSBub24temVybyBhbmQgcmVsYXRpdmVseSBsYXJnZSBpbiBtYWduaXR1ZGUuIFRoaXMgc3VnZ2VzdHMgdGhhdCB0aGUgZ2VuZXMgY29sb3VyZWQgcmVkIGluIHRoZSBzZWNvbmQgdm9sY2FubyBwbG90IGFyZSBib3RoIGJpb2xvZ2ljYWxseSBhbmQgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCAtIHNvIHRoZSBGRFItY29ycmVjdGlvbiBoYXMgYmVlbiBiZW5lZmljaWFsLCBhbmQgaGFzIGhlbHBlZCBmaWx0ZXIgb3V0IHNvbWUgZ2VuZXMgd2hpY2gsIHdoaWxlIGhhdmluZyBsb3cgaW5pdGlhbCAkcCQtdmFsdWVzLCB3ZXJlIG5vdCBiaW9sb2dpY2FsbHkgc2lnbmlmaWNhbnQgaW4gdGhpcyBjb250ZXh0Lg0KDQpGb3IgdGhpcyBleGFtcGxlLCBpdCBpcyB3b3J0aCBjb25zaWRlcmluZyB3aHkgaXQgbWlnaHQgYmUgaW1wb3J0YW50IHRvIGNvbXBhcmUgZ2VuZSBleHByZXNzaW9uIGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIHR3byBjb3JvbmF2aXJ1cyBzdHJhaW5zLiBGb3IgZXhhbXBsZSwgaWRlbnRpZnlpbmcgZ2VuZXMgd2hpY2ggYXJlIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgYmV0d2VlbiB0aGUgdHdvIHN0cmFpbnMgY291bGQgaGVscCByZXNlYXJjaGVycyBkZXZlbG9wIHRyZWF0bWVudHMgd2hpY2ggd2VyZSBwZXJzb25hbGlzZWQgdG8gdGhlIGRpZmZlcmVudCBzdHJhaW5zLiBTdWNoIHRyZWF0bWVudHMgY291bGQgYmUgbW9yZSBlZmZlY3RpdmUgdGhhbiB1c2luZyBhIGdlbmVyaWMgdHJlYXRtZW50IHdoaWNoIG1heSBoYXZlIHZhcnlpbmcgbGV2ZWxzIG9mIGVmZmljYWN5IGZvciBkaWZmZXJlbnQgc3RyYWlucy4gQ2FuIHlvdSB0aGluayBvZiBhbnkgb3RoZXIgcmVhc29ucz8NCg0KPGJyPg0KDQojIyMjIFRoYXQncyBldmVyeXRoaW5nIGNvdmVyZWQsIHdlbGwgZG9uZS4gIyMjIyB7LX0NCg0KPGJyPg0KDQojIFJlZmVyZW5jZXMgey0gI1JlZn0NCjxkaXYgaWQ9InJlZnMiPjwvZGl2Pg0KDQo8YnI+DQoNCjxmb250IGNvbG9yID0gImdyZXkiPg0KVGhlc2Ugbm90ZXMgaGF2ZSBiZWVuIHByZXBhcmVkIGJ5IFJ1cGVydCBLdXZla2UuIFRoZSBjb3B5cmlnaHQgZm9yIHRoZSBtYXRlcmlhbCBpbiB0aGVzZSBub3RlcyByZXNpZGVzIHdpdGggdGhlIGF1dGhvciBuYW1lZCBhYm92ZSwgd2l0aCB0aGUgRGVwYXJ0bWVudCBvZiBNYXRoZW1hdGljYWwgYW5kIFBoeXNpY2FsIFNjaWVuY2VzIGFuZCB3aXRoIExhIFRyb2JlIFVuaXZlcnNpdHkuIENvcHlyaWdodCBpbiB0aGlzIHdvcmsgaXMgdmVzdGVkIGluIExhIFRyb2JlIFVuaXZlcnNpdHkgaW5jbHVkaW5nIGFsbCBMYSBUcm9iZSBVbml2ZXJzaXR5IGJyYW5kaW5nIGFuZCBuYW1pbmcuIFVubGVzcyBvdGhlcndpc2Ugc3RhdGVkLCBtYXRlcmlhbCB3aXRoaW4gdGhpcyB3b3JrIGlzIGxpY2Vuc2VkIHVuZGVyIGEgQ3JlYXRpdmUgQ29tbW9ucyBBdHRyaWJ1dGlvbi1Ob24gQ29tbWVyY2lhbC1Ob24gRGVyaXZhdGl2ZXMgTGljZW5zZSANCjxhIGhyZWYgPSAiaHR0cHM6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLW5kLzQuMC9DQyIgdGFyZ2V0PSJfYmxhbmsiPiBCWS1OQy1ORC4gPC9hPg0KPC9mb250Pg==