Creative Commons License

library(tidyverse)

1 Puromycin data

Data on the velocity of an enzymatic reaction were obtained by Treloar (1974).
The number of counts per minute of radioactive product from the reaction was measured as a function of substrate concentration in parts per million (ppm) and from these counts the initial rate (or velocity) of the reaction was calculated (counts/min/min). The experiment was conducted once with the enzyme treated with Puromycin, and once with the enzyme untreated.

Assess if there is an association between the substrate concentration and rate for both the treated and untreated enzymes.

2 Import data

data(Puromycin)

3 Data wrangling

For a clearer interpretation of the model parameters later on, we will make the untreated state enzymes the reference category.

Puromycin <- Puromycin %>%
    mutate(state =fct_relevel(state,c("untreated","treated")))

3.1 Data Exploration

First, we visualize the association between the concentration and the enzyme rate, for both of the enzyme states.

Puromycin  %>%
  ggplot(aes(x=conc,y=rate)) +
  geom_point() + 
  stat_smooth(method = "loess",col="red") + # fit een kromme door de punten (rode lijn)
  stat_smooth(method='lm',col="black") + # fit een rechte door de punten aan de hand van de kleinstekwadratenmethode
  ylab("Reaction rate (counts/min)") +
  xlab("Substrate concentratie (ppm)") +
  facet_grid(~state)
## `geom_smooth()` using formula 'y ~ x'
## `geom_smooth()` using formula 'y ~ x'

The plot shows that there is a relation between the velocity and the concentration, however, the relation does not seem to be linear.

We will assess the impact of log-transforming the concentration. Because the concentration is measured in ppm we will log\(_{10}\) transform the data.

Puromycin  %>%
  ggplot(aes(x=conc %>% log10,y=rate)) +
  geom_point() + 
  stat_smooth(method = "loess",col="red") + 
  stat_smooth(method='lm',col="black") +
  ylab("Reaction Rate (counts/min)") +
  xlab("log10(Substrate concentration) (log10 ppm)") +
  facet_grid(~state)
## `geom_smooth()` using formula 'y ~ x'
## `geom_smooth()` using formula 'y ~ x'

The relation between the velocity and the log\(_{10}\) transformed concentration seems to be linear.

4 Linear regression

We will fit the following model to the data

\(Y_i = \beta_0 + \beta_c x_c+ \beta_s x_s +\beta_{c:s}x_{c}x_{s} + \epsilon_i\)

with

  • \(Y_i\) the reaction rate,

  • \(\beta_0\) the intercept,

  • \(\beta_{c}\) the main effect for log10 concentration,

  • \(x_c\) the log10 concentration,

  • \(\beta_{p}\) the main effect for treatment ,

  • \(x_s\) a dummy variable for โ€œstateโ€ that is 0 if the enzymes that are untreated and 1 if the enzymes are treated with Puromycin,

  • \(\beta_{c:s}\) the interaction effect between concentration and treatment state,

  • \(\epsilon_i\) i.i.d. normally distributed with mean 0 and variance \(\sigma^2\).

Note, that we write the substrate concentration with a small letter because the predictor is not random. The researchers have chosen the substrate concentrations in the design phase and it is thus no random variable.

The model implies two different regression lines

  • no treatment (\(x_s = 0\)) \[ Y_i = \beta_0 + \beta_c x_c + \epsilon \]
  • treatment (x_s = 1)

\[ Y_i = (\beta_0 + \beta_s) + (\beta_c+\beta_{c:s}) x_c + \epsilon \]

So the main effect for treatment has the interpretation as the change in intercept between treated and untreated samples.

The interaction term has the interpretation as the change in slope between treated and untreated samples.

Puromycin <-Puromycin %>% 
  mutate(log10conc = conc %>% log10)
mod1 <- lm(rate ~ log10conc * state, Puromycin)
summary(mod1)
## 
## Call:
## lm(formula = rate ~ log10conc * state, data = Puromycin)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -17.018  -6.381  -1.005   7.616  13.323 
## 
## Coefficients:
##                        Estimate Std. Error t value Pr(>|t|)    
## (Intercept)             164.588      5.153  31.938  < 2e-16 ***
## log10conc                62.129      5.020  12.375 1.54e-10 ***
## statetreated             44.606      6.811   6.549 2.85e-06 ***
## log10conc:statetreated   23.321      6.763   3.448  0.00269 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 9.151 on 19 degrees of freedom
## Multiple R-squared:  0.968,  Adjusted R-squared:  0.9629 
## F-statistic: 191.3 on 3 and 19 DF,  p-value: 2.267e-14

Before we perform inference we will first assess the assumptions

4.1 Assumptions

  1. Independence
  2. Linearity
  3. Normal distribution of the residuals
  4. Homoscedasticity

We assume that the experiment was well designed and that the different reactions that were use in the experiment are independent.

4.2 Linearity

We assess linearity in a residual analysis

plot(mod1, which=1)

The assumption of linearity is met.

4.2.1 Normality

plot(mod1,which=2)

The QQ-plot does not show large deviations from normality.

4.2.2 Homoscedasticity: equality of the variance

We can again use the residual plot for assessing this assumption or the plot were we plot the square root of the standardized residuals in function of the fit.

plot(mod1, which=3)

We see that the spread of the majority of the residuals is more or less similar. As such, we may assume homoscedasticity of the data.

4.3 Inference

4.3.1 hypotheses

We first do an omnibus test to assess is there is an effect of the log10 concentration on the velocity.

mod0 <- lm(rate ~ state, data = Puromycin)
anova(mod0,mod1)

Next, we assess the interaction.

car::Anova(mod1)

We cannot remove the interaction of the model.

Hence, we cannot study the effect of the concentration without accounting for the treatment and have to assess following research questions.

  1. the association between velocity and the concentration is significant in the untreated group

\[ H_0: \beta_c = 0 \text{ vs } H_1: \beta_c \neq 0 \]

  1. the association between velocity and the concentration is significant in the treated group

$$

H_0: c + {c:s}= 0 H_1: c + {c:s}0 $$

  1. the association between velocity and the concentration is different between treated and untreated group

\[ H_0: \beta_{c:s}= 0\text{ vs }H_1: \beta_{c:s}\neq 0 \]

We can assess all these hypotheses using multcomp while correcting for multiple testing.

library(multcomp)
## Loading required package: mvtnorm
## Loading required package: survival
## Loading required package: TH.data
## Loading required package: MASS
## 
## Attaching package: 'MASS'
## The following object is masked from 'package:dplyr':
## 
##     select
## 
## Attaching package: 'TH.data'
## The following object is masked from 'package:MASS':
## 
##     geyser
mcp1 <- glht(mod1, linfct = c("log10conc = 0", "log10conc + log10conc:statetreated = 0", "log10conc:statetreated = 0"))
summary(mcp1)
## 
##   Simultaneous Tests for General Linear Hypotheses
## 
## Fit: lm(formula = rate ~ log10conc * state, data = Puromycin)
## 
## Linear Hypotheses:
##                                         Estimate Std. Error t value Pr(>|t|)
## log10conc == 0                            62.129      5.020  12.375  < 0.001
## log10conc + log10conc:statetreated == 0   85.450      4.531  18.858  < 0.001
## log10conc:statetreated == 0               23.321      6.763   3.448  0.00672
##                                            
## log10conc == 0                          ***
## log10conc + log10conc:statetreated == 0 ***
## log10conc:statetreated == 0             ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## (Adjusted p values reported -- single-step method)
confint(mcp1)
## 
##   Simultaneous Confidence Intervals
## 
## Fit: lm(formula = rate ~ log10conc * state, data = Puromycin)
## 
## Quantile = 2.5093
## 95% family-wise confidence level
##  
## 
## Linear Hypotheses:
##                                         Estimate lwr     upr    
## log10conc == 0                          62.1285  49.5307 74.7263
## log10conc + log10conc:statetreated == 0 85.4499  74.0798 96.8201
## log10conc:statetreated == 0             23.3214   6.3513 40.2916

4.3.2 Conclusion

There is an extremely significant effect of the substrate concentration on the reaction rate (p<<0.001). The effect of the substrate concentration on the reaction rate is extremely significant for reactions catalysed with untreated enzymes. A reaction at a substrate concentration that is 10 times higher will have a reaction speed that is on average 62.1 counts/min higher (95% CI [49.6, 74.7] counts/min) (p << 0.001). The effect of the substrate concentration on the reaction rate is extremely significant for reactions catalysed puromycin treated enzymes (p << 0.001). A reaction at a substrate concentration that is 10 times higher will have a reaction speed that is on average 85.4 counts/min higher (95% CI [74.1, 96.8] counts/min). The effect of the substrate concentration on the reaction rate is very significantly higher for reactions catalysed with Puromycin treated enzymes than when catalysed with non-treated enzymes (p = 0.007). A reaction at a substrate concentration that is 10 times higher will have a reaction speed that is on average 23.3 counts/min higher for reactions that are catalysed with Puromycin treated enzymes than with untreated enzymes (95% CI [6.4, 40.3] counts/min).

LS0tCnRpdGxlOiAiOC4zLiBNdWx0aXBsZSByZWdyZXNzaW9uIHdpdGggaW50ZXJhY3Rpb246IHB1cm9teWNpbiBleGFtcGxlIC0gc29sdXRpb24iCmF1dGhvcjogIkxpZXZlbiBDbGVtZW50ICYgSmVyb2VuIEdpbGlzIgpkYXRlOiAic3RhdE9taWNzLCBHaGVudCBVbml2ZXJzaXR5IChodHRwczovL3N0YXRvbWljcy5naXRodWIuaW8pIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGNvZGVfZG93bmxvYWQ6IHllcwogICAgdGhlbWU6IGNvc21vCiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIG51bWJlcl9zZWN0aW9uczogeWVzCi0tLQoKPGEgcmVsPSJsaWNlbnNlIiBocmVmPSJodHRwczovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMtc2EvNC4wIj48aW1nIGFsdD0iQ3JlYXRpdmUgQ29tbW9ucyBMaWNlbnNlIiBzdHlsZT0iYm9yZGVyLXdpZHRoOjAiIHNyYz0iaHR0cHM6Ly9pLmNyZWF0aXZlY29tbW9ucy5vcmcvbC9ieS1uYy1zYS80LjAvODh4MzEucG5nIiAvPjwvYT4KCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKYGBgCgojIFB1cm9teWNpbiBkYXRhCgpEYXRhIG9uIHRoZSB2ZWxvY2l0eSBvZiBhbiBlbnp5bWF0aWMgcmVhY3Rpb24gd2VyZSBvYnRhaW5lZCBieSBUcmVsb2FyICgxOTc0KS4gIApUaGUgbnVtYmVyIG9mIGNvdW50cyBwZXIgbWludXRlIG9mIHJhZGlvYWN0aXZlIHByb2R1Y3QgZnJvbSB0aGUgcmVhY3Rpb24gd2FzIAptZWFzdXJlZCBhcyBhIGZ1bmN0aW9uIG9mIHN1YnN0cmF0ZSBjb25jZW50cmF0aW9uIGluIHBhcnRzIHBlciBtaWxsaW9uIChwcG0pIGFuZApmcm9tIHRoZXNlIGNvdW50cyB0aGUgaW5pdGlhbCByYXRlIChvciB2ZWxvY2l0eSkgb2YgdGhlIHJlYWN0aW9uIHdhcyBjYWxjdWxhdGVkIChjb3VudHMvbWluL21pbikuIFRoZSBleHBlcmltZW50IHdhcyBjb25kdWN0ZWQgb25jZSB3aXRoIHRoZSBlbnp5bWUgdHJlYXRlZAp3aXRoIFB1cm9teWNpbiwgYW5kIG9uY2Ugd2l0aCB0aGUgZW56eW1lIHVudHJlYXRlZC4KCkFzc2VzcyBpZiB0aGVyZSBpcyBhbiBhc3NvY2lhdGlvbiBiZXR3ZWVuIHRoZSBzdWJzdHJhdGUgY29uY2VudHJhdGlvbiBhbmQgcmF0ZSAKKipmb3IgYm90aCB0aGUgdHJlYXRlZCBhbmQgdW50cmVhdGVkIGVuenltZXMuKioKCiMgSW1wb3J0IGRhdGEKCmBgYHtyfQpkYXRhKFB1cm9teWNpbikKYGBgCgojIERhdGEgd3JhbmdsaW5nCgpGb3IgYSBjbGVhcmVyIGludGVycHJldGF0aW9uIG9mIHRoZSBtb2RlbCBwYXJhbWV0ZXJzIGxhdGVyIG9uLCB3ZSB3aWxsIG1ha2UKdGhlIHVudHJlYXRlZCBzdGF0ZSBlbnp5bWVzIHRoZSByZWZlcmVuY2UgY2F0ZWdvcnkuCgpgYGB7cn0KUHVyb215Y2luIDwtIFB1cm9teWNpbiAlPiUKICAgIG11dGF0ZShzdGF0ZSA9ZmN0X3JlbGV2ZWwoc3RhdGUsYygidW50cmVhdGVkIiwidHJlYXRlZCIpKSkKYGBgCgojIyBEYXRhIEV4cGxvcmF0aW9uCgpGaXJzdCwgd2UgdmlzdWFsaXplIHRoZSBhc3NvY2lhdGlvbiBiZXR3ZWVuIHRoZSBjb25jZW50cmF0aW9uIGFuZCB0aGUgZW56eW1lIApyYXRlLCBmb3IgYm90aCBvZiB0aGUgZW56eW1lIHN0YXRlcy4gCgpgYGB7cn0KUHVyb215Y2luICAlPiUKICBnZ3Bsb3QoYWVzKHg9Y29uYyx5PXJhdGUpKSArCiAgZ2VvbV9wb2ludCgpICsgCiAgc3RhdF9zbW9vdGgobWV0aG9kID0gImxvZXNzIixjb2w9InJlZCIpICsgIyBmaXQgZWVuIGtyb21tZSBkb29yIGRlIHB1bnRlbiAocm9kZSBsaWpuKQogIHN0YXRfc21vb3RoKG1ldGhvZD0nbG0nLGNvbD0iYmxhY2siKSArICMgZml0IGVlbiByZWNodGUgZG9vciBkZSBwdW50ZW4gYWFuIGRlIGhhbmQgdmFuIGRlIGtsZWluc3Rla3dhZHJhdGVubWV0aG9kZQogIHlsYWIoIlJlYWN0aW9uIHJhdGUgKGNvdW50cy9taW4pIikgKwogIHhsYWIoIlN1YnN0cmF0ZSBjb25jZW50cmF0aWUgKHBwbSkiKSArCiAgZmFjZXRfZ3JpZCh+c3RhdGUpCmBgYAoKVGhlIHBsb3Qgc2hvd3MgdGhhdCB0aGVyZSBpcyBhIHJlbGF0aW9uIGJldHdlZW4gdGhlIHZlbG9jaXR5IGFuZCB0aGUgCmNvbmNlbnRyYXRpb24sIGhvd2V2ZXIsIHRoZSByZWxhdGlvbiBkb2VzIG5vdCBzZWVtIHRvIGJlIGxpbmVhci4gCgpXZSB3aWxsIGFzc2VzcyB0aGUgaW1wYWN0IG9mIGxvZy10cmFuc2Zvcm1pbmcgdGhlIGNvbmNlbnRyYXRpb24uIEJlY2F1c2UgdGhlIApjb25jZW50cmF0aW9uIGlzIG1lYXN1cmVkIGluIHBwbSB3ZSB3aWxsIGxvZyRfezEwfSQgdHJhbnNmb3JtIHRoZSBkYXRhLiAKCmBgYHtyfQpQdXJvbXljaW4gICU+JQogIGdncGxvdChhZXMoeD1jb25jICU+JSBsb2cxMCx5PXJhdGUpKSArCiAgZ2VvbV9wb2ludCgpICsgCiAgc3RhdF9zbW9vdGgobWV0aG9kID0gImxvZXNzIixjb2w9InJlZCIpICsgCiAgc3RhdF9zbW9vdGgobWV0aG9kPSdsbScsY29sPSJibGFjayIpICsKICB5bGFiKCJSZWFjdGlvbiBSYXRlIChjb3VudHMvbWluKSIpICsKICB4bGFiKCJsb2cxMChTdWJzdHJhdGUgY29uY2VudHJhdGlvbikgKGxvZzEwIHBwbSkiKSArCiAgZmFjZXRfZ3JpZCh+c3RhdGUpCmBgYAoKVGhlIHJlbGF0aW9uIGJldHdlZW4gdGhlIHZlbG9jaXR5IGFuZCB0aGUgbG9nJF97MTB9JCB0cmFuc2Zvcm1lZCBjb25jZW50cmF0aW9uIApzZWVtcyB0byBiZSBsaW5lYXIuIAoKIyBMaW5lYXIgcmVncmVzc2lvbiAKCldlIHdpbGwgZml0IHRoZSBmb2xsb3dpbmcgbW9kZWwgdG8gdGhlIGRhdGEgCgokWV9pID0gXGJldGFfMCArIFxiZXRhX2MgeF9jKyBcYmV0YV9zIHhfcyArXGJldGFfe2M6c314X3tjfXhfe3N9ICsgXGVwc2lsb25faSQKCndpdGggCgotICRZX2kkIHRoZSByZWFjdGlvbiByYXRlLAoKLSAkXGJldGFfMCQgdGhlIGludGVyY2VwdCwKCi0gJFxiZXRhX3tjfSQgdGhlIG1haW4gZWZmZWN0IGZvciBsb2cxMCBjb25jZW50cmF0aW9uLAoKLSAkeF9jJCB0aGUgbG9nMTAgY29uY2VudHJhdGlvbiwKCi0gJFxiZXRhX3twfSQgdGhlIG1haW4gZWZmZWN0IGZvciB0cmVhdG1lbnQgLAoKLSAkeF9zJCBhIGR1bW15IHZhcmlhYmxlIGZvciAic3RhdGUiIHRoYXQgaXMgMCBpZiB0aGUgZW56eW1lcyB0aGF0IGFyZSB1bnRyZWF0ZWQgYW5kIDEgaWYKdGhlIGVuenltZXMgYXJlIHRyZWF0ZWQgd2l0aCBQdXJvbXljaW4sCgotICRcYmV0YV97YzpzfSQgdGhlIGludGVyYWN0aW9uIGVmZmVjdCBiZXR3ZWVuIGNvbmNlbnRyYXRpb24gYW5kIHRyZWF0bWVudCBzdGF0ZSwKCi0gJFxlcHNpbG9uX2kkIGkuaS5kLiBub3JtYWxseSBkaXN0cmlidXRlZCB3aXRoIG1lYW4gMCBhbmQgdmFyaWFuY2UgJFxzaWdtYV4yJC4KCk5vdGUsIHRoYXQgd2Ugd3JpdGUgdGhlIHN1YnN0cmF0ZSBjb25jZW50cmF0aW9uIHdpdGggYSBzbWFsbCBsZXR0ZXIgYmVjYXVzZSAKdGhlIHByZWRpY3RvciBpcyBub3QgcmFuZG9tLiBUaGUgcmVzZWFyY2hlcnMgaGF2ZSBjaG9zZW4gdGhlIHN1YnN0cmF0ZSAKY29uY2VudHJhdGlvbnMgaW4gdGhlIGRlc2lnbiBwaGFzZSBhbmQgaXQgaXMgdGh1cyBubyByYW5kb20gdmFyaWFibGUuCgpUaGUgbW9kZWwgaW1wbGllcyB0d28gZGlmZmVyZW50IHJlZ3Jlc3Npb24gbGluZXMKCi0gbm8gdHJlYXRtZW50ICgkeF9zID0gMCQpIAokJApZX2kgPSBcYmV0YV8wICsgXGJldGFfYyB4X2MgKyBcZXBzaWxvbiAgCiQkCi0gdHJlYXRtZW50ICh4X3MgPSAxKQoKJCQKWV9pID0gKFxiZXRhXzAgKyBcYmV0YV9zKSAgKyAoXGJldGFfYytcYmV0YV97YzpzfSkgeF9jICsgXGVwc2lsb24gIAokJAoKU28gdGhlIG1haW4gZWZmZWN0IGZvciB0cmVhdG1lbnQgaGFzIHRoZSBpbnRlcnByZXRhdGlvbiBhcyB0aGUgY2hhbmdlIGluIGludGVyY2VwdCBiZXR3ZWVuIHRyZWF0ZWQgYW5kIHVudHJlYXRlZCBzYW1wbGVzLiAKClRoZSBpbnRlcmFjdGlvbiB0ZXJtIGhhcyB0aGUgaW50ZXJwcmV0YXRpb24gYXMgdGhlIGNoYW5nZSBpbiBzbG9wZSBiZXR3ZWVuIHRyZWF0ZWQgYW5kIHVudHJlYXRlZCBzYW1wbGVzLiAKCmBgYHtyfQpQdXJvbXljaW4gPC1QdXJvbXljaW4gJT4lIAogIG11dGF0ZShsb2cxMGNvbmMgPSBjb25jICU+JSBsb2cxMCkKbW9kMSA8LSBsbShyYXRlIH4gbG9nMTBjb25jICogc3RhdGUsIFB1cm9teWNpbikKc3VtbWFyeShtb2QxKQpgYGAKCkJlZm9yZSB3ZSBwZXJmb3JtIGluZmVyZW5jZSB3ZSB3aWxsIGZpcnN0IGFzc2VzcyB0aGUgYXNzdW1wdGlvbnMKCiMjIEFzc3VtcHRpb25zIAoKMS4gSW5kZXBlbmRlbmNlIAoyLiBMaW5lYXJpdHkKMy4gTm9ybWFsIGRpc3RyaWJ1dGlvbiBvZiB0aGUgcmVzaWR1YWxzCjQuIEhvbW9zY2VkYXN0aWNpdHkgCgpXZSBhc3N1bWUgdGhhdCB0aGUgZXhwZXJpbWVudCB3YXMgd2VsbCBkZXNpZ25lZCBhbmQgdGhhdCB0aGUgZGlmZmVyZW50IHJlYWN0aW9ucyB0aGF0IHdlcmUgdXNlIGluIHRoZSBleHBlcmltZW50IGFyZSBpbmRlcGVuZGVudC4KCiMjIExpbmVhcml0eSAKCldlIGFzc2VzcyBsaW5lYXJpdHkgaW4gYSByZXNpZHVhbCBhbmFseXNpcyAKCmBgYHtyfQpwbG90KG1vZDEsIHdoaWNoPTEpCmBgYAoKVGhlIGFzc3VtcHRpb24gb2YgbGluZWFyaXR5IGlzIG1ldC4KCiMjIyBOb3JtYWxpdHkgCgpgYGB7cn0KcGxvdChtb2QxLHdoaWNoPTIpCmBgYAoKVGhlIFFRLXBsb3QgZG9lcyBub3Qgc2hvdyBsYXJnZSBkZXZpYXRpb25zIGZyb20gbm9ybWFsaXR5LiAKCiMjIyBIb21vc2NlZGFzdGljaXR5OiBlcXVhbGl0eSBvZiB0aGUgdmFyaWFuY2UKCldlIGNhbiBhZ2FpbiB1c2UgdGhlIHJlc2lkdWFsIHBsb3QgZm9yIGFzc2Vzc2luZyB0aGlzIGFzc3VtcHRpb24gb3IgdGhlIHBsb3QgCndlcmUgd2UgcGxvdCB0aGUgc3F1YXJlIHJvb3Qgb2YgdGhlIHN0YW5kYXJkaXplZCByZXNpZHVhbHMgaW4gZnVuY3Rpb24gb2YgCnRoZSBmaXQuIAoKYGBge3J9CnBsb3QobW9kMSwgd2hpY2g9MykKYGBgCgpXZSBzZWUgdGhhdCB0aGUgc3ByZWFkIG9mIHRoZSBtYWpvcml0eSBvZiB0aGUgcmVzaWR1YWxzIGlzIG1vcmUgb3IgbGVzcyBzaW1pbGFyLgpBcyBzdWNoLCB3ZSBtYXkgYXNzdW1lIGhvbW9zY2VkYXN0aWNpdHkgb2YgdGhlIGRhdGEuCgojIyBJbmZlcmVuY2UgCgojIyMgaHlwb3RoZXNlcyAKCldlIGZpcnN0IGRvIGFuIG9tbmlidXMgdGVzdCB0byBhc3Nlc3MgaXMgdGhlcmUgaXMgYW4gZWZmZWN0IG9mIHRoZSBsb2cxMCBjb25jZW50cmF0aW9uIG9uIHRoZSB2ZWxvY2l0eS4gCgpgYGB7cn0KbW9kMCA8LSBsbShyYXRlIH4gc3RhdGUsIGRhdGEgPSBQdXJvbXljaW4pCmFub3ZhKG1vZDAsbW9kMSkKYGBgCgpOZXh0LCB3ZSBhc3Nlc3MgdGhlIGludGVyYWN0aW9uLiAKCmBgYHtyfQpjYXI6OkFub3ZhKG1vZDEpCmBgYAoKV2UgY2Fubm90IHJlbW92ZSB0aGUgaW50ZXJhY3Rpb24gb2YgdGhlIG1vZGVsLiAKCkhlbmNlLCB3ZSBjYW5ub3Qgc3R1ZHkgdGhlIGVmZmVjdCBvZiB0aGUgY29uY2VudHJhdGlvbiB3aXRob3V0IGFjY291bnRpbmcgZm9yIHRoZSB0cmVhdG1lbnQgYW5kIGhhdmUgdG8gYXNzZXNzIGZvbGxvd2luZyByZXNlYXJjaCBxdWVzdGlvbnMuICAKCjEuIHRoZSBhc3NvY2lhdGlvbiBiZXR3ZWVuIHZlbG9jaXR5IGFuZCB0aGUgY29uY2VudHJhdGlvbiBpcyBzaWduaWZpY2FudCBpbiB0aGUgdW50cmVhdGVkIGdyb3VwIAoKJCQKSF8wOiBcYmV0YV9jID0gMCBcdGV4dHsgdnMgfSBIXzE6IFxiZXRhX2MgXG5lcSAwCiQkCgoyLiB0aGUgYXNzb2NpYXRpb24gYmV0d2VlbiB2ZWxvY2l0eSBhbmQgdGhlIGNvbmNlbnRyYXRpb24gaXMgc2lnbmlmaWNhbnQgaW4gdGhlIHRyZWF0ZWQgZ3JvdXAKCiQkCgpIXzA6IFxiZXRhX2MgKyBcYmV0YV97YzpzfT0gMCBcdGV4dCB7IHZzIH0gSF8xOiBcYmV0YV9jICsgXGJldGFfe2M6c31cbmVxIDAKJCQKCjMuIHRoZSBhc3NvY2lhdGlvbiBiZXR3ZWVuIHZlbG9jaXR5IGFuZCB0aGUgY29uY2VudHJhdGlvbiBpcyBkaWZmZXJlbnQgYmV0d2VlbiB0cmVhdGVkIGFuZCB1bnRyZWF0ZWQgZ3JvdXAgCgokJApIXzA6IFxiZXRhX3tjOnN9PSAwXHRleHR7IHZzIH1IXzE6IFxiZXRhX3tjOnN9XG5lcSAwCiQkCgpXZSBjYW4gYXNzZXNzIGFsbCB0aGVzZSBoeXBvdGhlc2VzIHVzaW5nIG11bHRjb21wIHdoaWxlIGNvcnJlY3RpbmcgZm9yIG11bHRpcGxlIHRlc3RpbmcuIAoKYGBge3J9CmxpYnJhcnkobXVsdGNvbXApCm1jcDEgPC0gZ2xodChtb2QxLCBsaW5mY3QgPSBjKCJsb2cxMGNvbmMgPSAwIiwgImxvZzEwY29uYyArIGxvZzEwY29uYzpzdGF0ZXRyZWF0ZWQgPSAwIiwgImxvZzEwY29uYzpzdGF0ZXRyZWF0ZWQgPSAwIikpCnN1bW1hcnkobWNwMSkKY29uZmludChtY3AxKQpgYGAKCgojIyMgQ29uY2x1c2lvbgoKVGhlcmUgaXMgYW4gZXh0cmVtZWx5IHNpZ25pZmljYW50IGVmZmVjdCBvZiB0aGUgc3Vic3RyYXRlIGNvbmNlbnRyYXRpb24gb24gdGhlIHJlYWN0aW9uIHJhdGUgKHA8PDAuMDAxKS4gClRoZSBlZmZlY3Qgb2YgdGhlIHN1YnN0cmF0ZSBjb25jZW50cmF0aW9uIG9uIHRoZSByZWFjdGlvbiByYXRlIGlzIGV4dHJlbWVseSBzaWduaWZpY2FudCBmb3IgcmVhY3Rpb25zIGNhdGFseXNlZCB3aXRoIHVudHJlYXRlZCBlbnp5bWVzLiBBIHJlYWN0aW9uIGF0IGEgc3Vic3RyYXRlIGNvbmNlbnRyYXRpb24gdGhhdCBpcyAxMCB0aW1lcyBoaWdoZXIgd2lsbCBoYXZlIGEgcmVhY3Rpb24gc3BlZWQgdGhhdCBpcyBvbiBhdmVyYWdlICBgciByb3VuZChjb25maW50KG1jcDEpJGNvbmZpbnRbMSwxXSwxKWAgY291bnRzL21pbiBoaWdoZXIgKDk1JSBDSSBbYHIgcm91bmQoY29uZmludChtY3AxKSRjb25maW50WzEsLTFdLDEpYF0gY291bnRzL21pbikgKHAgPDwgMC4wMDEpLiAKVGhlIGVmZmVjdCBvZiB0aGUgc3Vic3RyYXRlIGNvbmNlbnRyYXRpb24gb24gdGhlIHJlYWN0aW9uIHJhdGUgaXMgZXh0cmVtZWx5IHNpZ25pZmljYW50IGZvciByZWFjdGlvbnMgY2F0YWx5c2VkIHB1cm9teWNpbiB0cmVhdGVkIGVuenltZXMgIChwIDw8IDAuMDAxKS4gQSByZWFjdGlvbiBhdCBhIHN1YnN0cmF0ZSBjb25jZW50cmF0aW9uIHRoYXQgaXMgMTAgdGltZXMgaGlnaGVyIHdpbGwgaGF2ZSBhIHJlYWN0aW9uIHNwZWVkIHRoYXQgaXMgb24gYXZlcmFnZSAgYHIgcm91bmQoY29uZmludChtY3AxKSRjb25maW50WzIsMV0sMSlgIGNvdW50cy9taW4gaGlnaGVyICg5NSUgQ0kgW2ByIHJvdW5kKGNvbmZpbnQobWNwMSkkY29uZmludFsyLC0xXSwxKWBdIGNvdW50cy9taW4pLgpUaGUgZWZmZWN0IG9mIHRoZSBzdWJzdHJhdGUgY29uY2VudHJhdGlvbiBvbiB0aGUgcmVhY3Rpb24gcmF0ZSBpcyB2ZXJ5IHNpZ25pZmljYW50bHkgaGlnaGVyIGZvciByZWFjdGlvbnMgY2F0YWx5c2VkIHdpdGggUHVyb215Y2luIHRyZWF0ZWQgZW56eW1lcyB0aGFuIHdoZW4gY2F0YWx5c2VkIHdpdGggbm9uLXRyZWF0ZWQgZW56eW1lcyAgKHAgPSBgciByb3VuZChzdW1tYXJ5KG1jcDEpJHRlc3QkcHZhbHVlWzNdLDMpYCkuIEEgcmVhY3Rpb24gYXQgYSBzdWJzdHJhdGUgY29uY2VudHJhdGlvbiB0aGF0IGlzIDEwIHRpbWVzIGhpZ2hlciB3aWxsIGhhdmUgYSByZWFjdGlvbiBzcGVlZCB0aGF0IGlzIG9uIGF2ZXJhZ2UgYHIgcm91bmQoY29uZmludChtY3AxKSRjb25maW50WzMsMV0sMSlgIGNvdW50cy9taW4gaGlnaGVyIGZvciByZWFjdGlvbnMgdGhhdCBhcmUgY2F0YWx5c2VkIHdpdGggUHVyb215Y2luIHRyZWF0ZWQgZW56eW1lcyB0aGFuIHdpdGggdW50cmVhdGVkIGVuenltZXMgKDk1JSBDSSBbYHIgcm91bmQoY29uZmludChtY3AxKSRjb25maW50WzMsLTFdLDEpYF0gY291bnRzL21pbikuIAoKCgoKCg==