1 The poison dataset

In this experiment, 96 fish (dojofish, goldfish and zebrafish) were placed separately in a tank with two liters of water and a certain dose (in mg) of the poison EI-43,064. The resistance of the fish against the poison was measured as the amount of minutes the fish survived after being exposed to the poison (Surv_time, in minutes). Additionally, the weight of each fish was measured.

2 Goal

In this tutorial session we will focus on Dojofish, and we will model the survival time in function of the poison dose while correcting for the weight of the fish.

  1. We will first analyse the survival data by only considering the dose as an explanatory variable for survival time

  2. Next we will model the survival data with and additive model for dose and weight

Load libraries

# install.packages("GGally")
library(GGally)
library(car)
library(multcomp)

library(tidyverse)
theme_set(theme_bw())

3 Import the data

poison <- read_csv("https://raw.githubusercontent.com/statOmics/PSLSData/main/poison.csv")

4 Data tidying

We can see a couple of things in the data that can be improved:

  1. Capitalise the fist column name

  2. Set the Species column as a factor

  3. Change the species factor levels from “0” to Dojofish. Hint: use the fct_recode function.

  4. In the previous analysis on this dataset (Simple linear regression session), we performed a log-transformation on the response variable Surv_time to meet the normality and homoscedasticity assumptions of the linear model. Here, we will immediately work with log-transformed survival times; store these in the new variable log2Surv_time and remove the non-transformed values.

  5. Subset the data to only retain Dojofish.

poison <- poison %>%
  rename("Species" = "species") %>%
  mutate(Species = as.factor(Species)) %>%
  mutate(Species = fct_recode(Species,
    Dojofish = "0", Goldfish = "1", Zebrafish = "2"
  )) %>%
  mutate(log2Surv_time = log2(Surv_time)) %>%
  select(-Surv_time) %>%
  filter(Species == "Dojofish")

poison

5 Data exploration

Prior to the analysis, we should explore our data. To start our data exploration, we will make use of the ggpairs function of the GGally R package. This function will generate a visualization containing multiple panels, which display (1) univariate plots of the different variables in our dataset, (2) bivariate plots and (3) correlation coefficients between the different variables.

ggpairs(poison, columns = 2:4)

Based on these plots, we observe that:

  • The survival time seems to be associated with dose and fish weight.

From the tutorial of H6 we have seen that the fish weights were not nicely uniform across the different poison dosages due to the randomisation.

poison %>%
  ggplot(aes(x = Dose, y = Weight)) +
  geom_point() +
  ggtitle("Association between dose and weight") +
  theme_bw() +
  stat_summary(
    fun = mean, geom = "point",
    col = "black", size = 4,
    shape = 24, fill = "red"
  )

6 Simple linear regression

This is the same regression model that we have already fit in the exercise session on simple linear regression, with Dose as the only explanatory variable for log2Surv_time.

# fit a linear regression model with 'Surv_time' as response variable and
# 'Dose' as predictor variabele
lm_simple <- lm(log2Surv_time ~ Dose, data = poison)

## display the diagnostic plots of the model
par(mfrow = c(2, 2))
plot(lm_simple)

  1. The independence assumption was met because the fish were randomized to the dose.
  2. The linearity assumption is met.
  3. The normality assumption is met.
  4. The homoscedasticity assumption is met.

Finally, we look at the output of the model.

summary(lm_simple)
## 
## Call:
## lm(formula = log2Surv_time ~ Dose, data = poison)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -0.6891 -0.3804 -0.1076  0.3452  1.0856 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   3.0469     0.3462   8.800 1.33e-10 ***
## Dose         -0.9063     0.2208  -4.104 0.000215 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.4828 on 37 degrees of freedom
## Multiple R-squared:  0.3128, Adjusted R-squared:  0.2942 
## F-statistic: 16.84 on 1 and 37 DF,  p-value: 0.0002146

Or for an interpretation at the original scale (minutes in stead of log2 minutes):

2^(coef(lm_simple))["Dose"]
##      Dose 
## 0.5335551
2^(confint(lm_simple))[2, ]
##     2.5 %    97.5 % 
## 0.3912681 0.7275855

There is a very significant effect of the poison on survival of Dojofish (p< 0.001). Dojofish that are exposed to a higher dose of the poison will have a survival time that decrease on average with a factor 0.53 per gram of poison that is added (95% CI [0.39, 0.73]).

7 Analysis with additive effect for weight

7.1 Model specification

Here, we will estimate the effect of the poison while correcting for weight and we will add it as an additional covariate to our linear regression model, such that

\[ y_i=\beta_0+\beta_d x_d + \beta_g x_g + \epsilon_i, \]

with \(\epsilon_i \text{ i.i.d. } N(0,\sigma^2)\).

7.2 Assumptions

The model will again be fit to allow for assessing the model assumptions

lm_additive <- lm(log2Surv_time ~ Dose + Weight, data = poison)
par(mfrow = c(2, 2))
plot(lm_additive)

The assumption of independence, linearity and homoscedasticity are met.

The QQ-plot suggest that there might be some deviation from normality in the left tail of the,distribution. However, when we would simulate data under the normality assumption, it seems that deviations of this size may be expected when normality is met. We will use simulation to assess if we can observe similar residual plots if all assumptions for the linear model hold.

set.seed(1031)
sigma <- sigma(lm_additive)

dataHlp <- poison

par(mfrow = c(3, 3))
for (i in 1:9) {
  nobs <- nrow(poison)
  dataHlp$ySim <- fitted.values(lm_additive) + rnorm(nobs, sd = sigma)
  simModel <- lm(ySim ~ Dose + Weight, dataHlp)
  plot(simModel, which = 2)
}

It seems that deviations of the size that we see in our real data may be expected even when normality is met. As such, all assumptions for linear regression seem to be valid.

7.3 Inference

We then inspect the results.

summary(lm_additive)
## 
## Call:
## lm(formula = log2Surv_time ~ Dose + Weight, data = poison)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -0.59629 -0.33110 -0.06836  0.32507  0.83315 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   0.8294     0.6457   1.285 0.207119    
## Dose         -0.9590     0.1888  -5.081 1.17e-05 ***
## Weight        1.0783     0.2792   3.862 0.000451 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.4116 on 36 degrees of freedom
## Multiple R-squared:  0.5141, Adjusted R-squared:  0.4871 
## F-statistic: 19.04 on 2 and 36 DF,  p-value: 2.282e-06

7.4 Interpretation of model parameters

We see that the effect of dose on survival time remains similar, however, it has become more significant after we have incorporated weight in our model. Indeed, from the data exploration, we learned that weight is associated with survival.

  1. As such, by incorporating weight in our model, we are able to explain a larger part of the variability in the response variable survival time. As a consequence, the variability in the residuals of the model will decrease, which in turn will lead to smaller standard error estimates for the different parameter estimates in the model.

  2. From the data exploration, we additionally found that the dojo-fish weights were not uniform across the different poison dosages due to the randomisation. Therefore, we can estimate the effect between dose and survival time better while accounting for the weight.

In this model, the effect of Dose can be interpreted as the average change in the log2 survival time between two groups of dojofish with the same weight that are exposed to a poison dosage that differs 1 mg/L. In symbols:

\[\begin{eqnarray} \hat{\mu_1}&=& \beta_0 + \beta_d x_{1d} + \beta_g x_g \text{ (average log2-survival time for dose 1 for a certain weight)}\\ \hat{\mu_2}&=& \beta_0 + \beta_d x_{2d} + \beta_g x_g \text{ (average log2-survival time for dose 2 for that same weight)}\\ \hat \mu_2- \hat \mu_1&=&\beta_0 + \beta_d x_{2d} + \beta_g x_g - (\beta_0 + \beta_d x_{1d} + \beta_g x_g) \text{ (difference in average log2-survival time between dose 2 en dose 1)}\\ \hat \mu_2-\hat \mu_1&=&\beta_d (x_{2d}-x_{1d}) \end{eqnarray}\]

7.5 Conclusion

2^(coef(lm_additive))
## (Intercept)        Dose      Weight 
##    1.777004    0.514402    2.111484
2^(confint(lm_additive))
##                 2.5 %    97.5 %
## (Intercept) 0.7169728 4.4042734
## Dose        0.3945101 0.6707292
## Weight      1.4259918 3.1265018

The dose of the poison has an extremely significant effect on the log2 transformed survival time of dojofish (p-value = 1e-05). The geometric average of the survival time for dojofish that are exposed to a poison dose that is 1mg/L larger is approximately halved (factor = \(2^{\beta_d}=\) 0.51) .

The effect of weight on the survival time of dojofish is also extremely significant (p-value = 5e-04). The geometric average of the survival time of a dojofish that weighs 1 gram more than another dojofish is approximately twice as long (factor = \(2^{ \beta_g}\)= 2.1, 95% BI [1.4,3.1]).

7.6 Remarks

In the lm_additive model, we included only a main effect for weight. However, there could also be an interaction effect between weight and dose. An interaction between weight and dose implies that the dose effect on the survival time changes according to the weight of the fish.

LS0tCnRpdGxlOiAiRXhlcmNpc2UgOC4xOiBBZGRpdGl2ZSBsaW5lYXIgbW9kZWwgb24gdGhlIHBvaXNvbiBkYXRhc2V0IC0gc29sdXRpb24iCmF1dGhvcjogIkxpZXZlbiBDbGVtZW50LCBKZXJvZW4gR2lsaXMgYW5kIE1pbGFuIE1hbGZhaXQiCmRhdGU6ICJzdGF0T21pY3MsIEdoZW50IFVuaXZlcnNpdHkgKGh0dHBzOi8vc3RhdG9taWNzLmdpdGh1Yi5pbykiCi0tLQoKIyBUaGUgcG9pc29uIGRhdGFzZXQKCkluIHRoaXMgZXhwZXJpbWVudCwgOTYgZmlzaCAoZG9qb2Zpc2gsIGdvbGRmaXNoIGFuZCB6ZWJyYWZpc2gpCndlcmUgcGxhY2VkIHNlcGFyYXRlbHkgaW4gYSB0YW5rIHdpdGggdHdvIGxpdGVycyBvZiB3YXRlciBhbmQKYSBjZXJ0YWluIGRvc2UgKGluIG1nKSBvZiB0aGUgcG9pc29uIEVJLTQzLDA2NC4gVGhlIHJlc2lzdGFuY2UKb2YgdGhlIGZpc2ggYWdhaW5zdCB0aGUgcG9pc29uIHdhcyBtZWFzdXJlZCBhcyB0aGUgYW1vdW50IG9mCm1pbnV0ZXMgdGhlIGZpc2ggc3Vydml2ZWQgYWZ0ZXIgYmVpbmcgZXhwb3NlZCB0byB0aGUgcG9pc29uIChgU3Vydl90aW1lYCwgaW4KbWludXRlcykuIEFkZGl0aW9uYWxseSwgdGhlIHdlaWdodCBvZiBlYWNoIGZpc2ggd2FzIG1lYXN1cmVkLgoKIyBHb2FsCgpJbiB0aGlzIHR1dG9yaWFsIHNlc3Npb24gd2Ugd2lsbCBmb2N1cyBvbiAqKkRvam9maXNoKiosIGFuZCB3ZSB3aWxsIG1vZGVsIHRoZQpzdXJ2aXZhbCB0aW1lIGluIGZ1bmN0aW9uIG9mIHRoZSBwb2lzb24gZG9zZSB3aGlsZSBjb3JyZWN0aW5nIGZvciB0aGUgd2VpZ2h0IG9mCnRoZSBmaXNoLgoKMS4gV2Ugd2lsbCBmaXJzdCBhbmFseXNlIHRoZSBzdXJ2aXZhbCBkYXRhIGJ5IG9ubHkgY29uc2lkZXJpbmcgdGhlIGRvc2UgYXMgYW4KZXhwbGFuYXRvcnkgdmFyaWFibGUgZm9yIHN1cnZpdmFsIHRpbWUKCjIuIE5leHQgd2Ugd2lsbCBtb2RlbCB0aGUgc3Vydml2YWwgZGF0YSB3aXRoIGFuZCBhZGRpdGl2ZSBtb2RlbCBmb3IgZG9zZSBhbmQKd2VpZ2h0CgpMb2FkIGxpYnJhcmllcwoKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMgaW5zdGFsbC5wYWNrYWdlcygiR0dhbGx5IikKbGlicmFyeShHR2FsbHkpCmxpYnJhcnkoY2FyKQpsaWJyYXJ5KG11bHRjb21wKQoKbGlicmFyeSh0aWR5dmVyc2UpCnRoZW1lX3NldCh0aGVtZV9idygpKQpgYGAKCiMgSW1wb3J0IHRoZSBkYXRhCgpgYGB7ciwgbWVzc2FnZT1GQUxTRX0KcG9pc29uIDwtIHJlYWRfY3N2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vc3RhdE9taWNzL1BTTFNEYXRhL21haW4vcG9pc29uLmNzdiIpCmBgYAoKIyBEYXRhIHRpZHlpbmcKCldlIGNhbiBzZWUgYSBjb3VwbGUgb2YgdGhpbmdzIGluIHRoZSBkYXRhIHRoYXQgY2FuIGJlIGltcHJvdmVkOgoKMS4gQ2FwaXRhbGlzZSB0aGUgZmlzdCBjb2x1bW4gbmFtZQoKMy4gU2V0IHRoZSBTcGVjaWVzIGNvbHVtbiBhcyBhIGZhY3RvcgoKNC4gQ2hhbmdlIHRoZSBzcGVjaWVzIGZhY3RvciBsZXZlbHMgZnJvbSAiMCIgdG8gRG9qb2Zpc2guCipIaW50KjogdXNlIHRoZSBgZmN0X3JlY29kZWAgZnVuY3Rpb24uCgo0LiBJbiB0aGUgcHJldmlvdXMgYW5hbHlzaXMgb24gdGhpcyBkYXRhc2V0CihgU2ltcGxlIGxpbmVhciByZWdyZXNzaW9uIHNlc3Npb25gKSwgd2UgcGVyZm9ybWVkIGEgbG9nLXRyYW5zZm9ybWF0aW9uIG9uIHRoZQpyZXNwb25zZSB2YXJpYWJsZSBgU3Vydl90aW1lYCB0byBtZWV0IHRoZSBub3JtYWxpdHkgYW5kIGhvbW9zY2VkYXN0aWNpdHkKYXNzdW1wdGlvbnMgb2YgdGhlIGxpbmVhciBtb2RlbC4gSGVyZSwgd2Ugd2lsbCBpbW1lZGlhdGVseSB3b3JrIHdpdGgKbG9nLXRyYW5zZm9ybWVkIHN1cnZpdmFsIHRpbWVzOyBzdG9yZSB0aGVzZSBpbiB0aGUgbmV3ICB2YXJpYWJsZSBgbG9nMlN1cnZfdGltZWAKYW5kIHJlbW92ZSB0aGUgbm9uLXRyYW5zZm9ybWVkIHZhbHVlcy4KCjUuIFN1YnNldCB0aGUgZGF0YSB0byBvbmx5IHJldGFpbiAqKkRvam9maXNoKiouCgpgYGB7cn0KcG9pc29uIDwtIHBvaXNvbiAlPiUKICByZW5hbWUoIlNwZWNpZXMiID0gInNwZWNpZXMiKSAlPiUKICBtdXRhdGUoU3BlY2llcyA9IGFzLmZhY3RvcihTcGVjaWVzKSkgJT4lCiAgbXV0YXRlKFNwZWNpZXMgPSBmY3RfcmVjb2RlKFNwZWNpZXMsCiAgICBEb2pvZmlzaCA9ICIwIiwgR29sZGZpc2ggPSAiMSIsIFplYnJhZmlzaCA9ICIyIgogICkpICU+JQogIG11dGF0ZShsb2cyU3Vydl90aW1lID0gbG9nMihTdXJ2X3RpbWUpKSAlPiUKICBzZWxlY3QoLVN1cnZfdGltZSkgJT4lCiAgZmlsdGVyKFNwZWNpZXMgPT0gIkRvam9maXNoIikKCnBvaXNvbgpgYGAKCiMgRGF0YSBleHBsb3JhdGlvbgoKUHJpb3IgdG8gdGhlIGFuYWx5c2lzLCB3ZSBzaG91bGQgZXhwbG9yZSBvdXIgZGF0YS4gVG8gc3RhcnQgb3VyIGRhdGEKZXhwbG9yYXRpb24sIHdlIHdpbGwgbWFrZSB1c2Ugb2YgdGhlIGBnZ3BhaXJzYCBmdW5jdGlvbiBvZiB0aGUKYEdHYWxseWAgUiBwYWNrYWdlLiBUaGlzIGZ1bmN0aW9uIHdpbGwgZ2VuZXJhdGUgYSB2aXN1YWxpemF0aW9uIGNvbnRhaW5pbmcKbXVsdGlwbGUgcGFuZWxzLCB3aGljaCBkaXNwbGF5ICgxKSB1bml2YXJpYXRlIHBsb3RzIG9mIHRoZSBkaWZmZXJlbnQgdmFyaWFibGVzCmluIG91ciBkYXRhc2V0LCAoMikgYml2YXJpYXRlIHBsb3RzIGFuZCAoMykgY29ycmVsYXRpb24gY29lZmZpY2llbnRzIGJldHdlZW4KdGhlIGRpZmZlcmVudCB2YXJpYWJsZXMuCgpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgZmlnLndpZHRoPTEyfQpnZ3BhaXJzKHBvaXNvbiwgY29sdW1ucyA9IDI6NCkKYGBgCgpCYXNlZCBvbiB0aGVzZSBwbG90cywgd2Ugb2JzZXJ2ZSB0aGF0OgoKLSBUaGUgc3Vydml2YWwgdGltZSBzZWVtcyB0byBiZSBhc3NvY2lhdGVkIHdpdGggZG9zZSBhbmQgZmlzaCB3ZWlnaHQuCgpGcm9tIHRoZSB0dXRvcmlhbCBvZiBINiB3ZSBoYXZlIHNlZW4gdGhhdCB0aGUgZmlzaCB3ZWlnaHRzIHdlcmUgbm90IG5pY2VseQp1bmlmb3JtIGFjcm9zcyB0aGUgZGlmZmVyZW50IHBvaXNvbiBkb3NhZ2VzIGR1ZSB0byB0aGUgcmFuZG9taXNhdGlvbi4KCmBgYHtyLCBtZXNzYWdlPUZBTFNFfQpwb2lzb24gJT4lCiAgZ2dwbG90KGFlcyh4ID0gRG9zZSwgeSA9IFdlaWdodCkpICsKICBnZW9tX3BvaW50KCkgKwogIGdndGl0bGUoIkFzc29jaWF0aW9uIGJldHdlZW4gZG9zZSBhbmQgd2VpZ2h0IikgKwogIHRoZW1lX2J3KCkgKwogIHN0YXRfc3VtbWFyeSgKICAgIGZ1biA9IG1lYW4sIGdlb20gPSAicG9pbnQiLAogICAgY29sID0gImJsYWNrIiwgc2l6ZSA9IDQsCiAgICBzaGFwZSA9IDI0LCBmaWxsID0gInJlZCIKICApCmBgYAoKIyBTaW1wbGUgbGluZWFyIHJlZ3Jlc3Npb24KClRoaXMgaXMgdGhlIHNhbWUgcmVncmVzc2lvbiBtb2RlbCB0aGF0IHdlIGhhdmUgYWxyZWFkeSBmaXQgaW4gdGhlIGV4ZXJjaXNlCnNlc3Npb24gb24gc2ltcGxlIGxpbmVhciByZWdyZXNzaW9uLCB3aXRoIGBEb3NlYCBhcyB0aGUgb25seSBleHBsYW5hdG9yeQp2YXJpYWJsZSBmb3IgYGxvZzJTdXJ2X3RpbWVgLgoKYGBge3J9CiMgZml0IGEgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgd2l0aCAnU3Vydl90aW1lJyBhcyByZXNwb25zZSB2YXJpYWJsZSBhbmQKIyAnRG9zZScgYXMgcHJlZGljdG9yIHZhcmlhYmVsZQpsbV9zaW1wbGUgPC0gbG0obG9nMlN1cnZfdGltZSB+IERvc2UsIGRhdGEgPSBwb2lzb24pCgojIyBkaXNwbGF5IHRoZSBkaWFnbm9zdGljIHBsb3RzIG9mIHRoZSBtb2RlbApwYXIobWZyb3cgPSBjKDIsIDIpKQpwbG90KGxtX3NpbXBsZSkKYGBgCgoxLiBUaGUgaW5kZXBlbmRlbmNlIGFzc3VtcHRpb24gd2FzICoqbWV0KiogYmVjYXVzZSB0aGUgZmlzaCB3ZXJlIHJhbmRvbWl6ZWQgdG8KdGhlIGRvc2UuCjIuIFRoZSBsaW5lYXJpdHkgYXNzdW1wdGlvbiBpcyAqKm1ldCoqLgozLiBUaGUgbm9ybWFsaXR5IGFzc3VtcHRpb24gaXMgKiptZXQqKi4KNC4gVGhlIGhvbW9zY2VkYXN0aWNpdHkgYXNzdW1wdGlvbiBpcyAqKm1ldCoqLgoKRmluYWxseSwgd2UgbG9vayBhdCB0aGUgb3V0cHV0IG9mIHRoZSBtb2RlbC4KCmBgYHtyfQpzdW1tYXJ5KGxtX3NpbXBsZSkKYGBgCgpPciBmb3IgYW4gaW50ZXJwcmV0YXRpb24gYXQgdGhlIG9yaWdpbmFsIHNjYWxlIChtaW51dGVzIGluIHN0ZWFkIG9mIGxvZzIKbWludXRlcyk6CgpgYGB7cn0KMl4oY29lZihsbV9zaW1wbGUpKVsiRG9zZSJdCjJeKGNvbmZpbnQobG1fc2ltcGxlKSlbMiwgXQpgYGAKClRoZXJlIGlzIGEgdmVyeSBzaWduaWZpY2FudCBlZmZlY3Qgb2YgdGhlIHBvaXNvbiBvbiBzdXJ2aXZhbCBvZiBEb2pvZmlzaAoocDwgMC4wMDEpLiBEb2pvZmlzaCB0aGF0IGFyZSBleHBvc2VkIHRvIGEgaGlnaGVyIGRvc2Ugb2YgdGhlIHBvaXNvbiB3aWxsCmhhdmUgYSBzdXJ2aXZhbCB0aW1lIHRoYXQgZGVjcmVhc2Ugb24gYXZlcmFnZSB3aXRoIGEgZmFjdG9yCmByIGxtX3NpbXBsZSRjb2VmWzJdICU+JSAyXi4gJT4lIHJvdW5kKC4sMilgIHBlciBncmFtIG9mIHBvaXNvbiB0aGF0CmlzIGFkZGVkICg5NSUgQ0kgW2ByIGNvbmZpbnQobG1fc2ltcGxlKVsyLF0gJT4lIDJeLiAlPiUgcm91bmQoLiwyKWBdKS4KCiMgQW5hbHlzaXMgd2l0aCBhZGRpdGl2ZSBlZmZlY3QgZm9yIHdlaWdodAoKIyMgTW9kZWwgc3BlY2lmaWNhdGlvbgoKSGVyZSwgd2Ugd2lsbCBlc3RpbWF0ZSB0aGUgZWZmZWN0IG9mIHRoZSBwb2lzb24gd2hpbGUgY29ycmVjdGluZyBmb3IgYHdlaWdodGAKYW5kIHdlIHdpbGwgYWRkIGl0IGFzIGFuIGFkZGl0aW9uYWwgY292YXJpYXRlIHRvIG91ciBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbCwKc3VjaCB0aGF0CgokJAp5X2k9XGJldGFfMCtcYmV0YV9kIHhfZCArIFxiZXRhX2cgeF9nICsgXGVwc2lsb25faSwKJCQKCndpdGggJFxlcHNpbG9uX2kgXHRleHR7IGkuaS5kLiB9IE4oMCxcc2lnbWFeMikkLgoKIyMgQXNzdW1wdGlvbnMKClRoZSBtb2RlbCB3aWxsIGFnYWluIGJlIGZpdCB0byBhbGxvdyBmb3IgYXNzZXNzaW5nIHRoZSBtb2RlbCBhc3N1bXB0aW9ucwoKYGBge3J9CmxtX2FkZGl0aXZlIDwtIGxtKGxvZzJTdXJ2X3RpbWUgfiBEb3NlICsgV2VpZ2h0LCBkYXRhID0gcG9pc29uKQpwYXIobWZyb3cgPSBjKDIsIDIpKQpwbG90KGxtX2FkZGl0aXZlKQpgYGAKClRoZSBhc3N1bXB0aW9uIG9mIGluZGVwZW5kZW5jZSwgbGluZWFyaXR5IGFuZCBob21vc2NlZGFzdGljaXR5IGFyZSBtZXQuCgpUaGUgUVEtcGxvdCBzdWdnZXN0IHRoYXQgdGhlcmUgbWlnaHQgYmUgc29tZSBkZXZpYXRpb24gZnJvbSBub3JtYWxpdHkgaW4gdGhlCmxlZnQgdGFpbCBvZiB0aGUsZGlzdHJpYnV0aW9uLiBIb3dldmVyLCB3aGVuIHdlIHdvdWxkIHNpbXVsYXRlIGRhdGEgdW5kZXIgdGhlCm5vcm1hbGl0eSBhc3N1bXB0aW9uLCBpdCBzZWVtcyB0aGF0IGRldmlhdGlvbnMgb2YgdGhpcyBzaXplIG1heSBiZSBleHBlY3RlZCB3aGVuCm5vcm1hbGl0eSBpcyBtZXQuIFdlIHdpbGwgdXNlIHNpbXVsYXRpb24gdG8gYXNzZXNzIGlmIHdlIGNhbiBvYnNlcnZlIHNpbWlsYXIKcmVzaWR1YWwgcGxvdHMgaWYgYWxsIGFzc3VtcHRpb25zIGZvciB0aGUgbGluZWFyIG1vZGVsIGhvbGQuCgpgYGB7cn0Kc2V0LnNlZWQoMTAzMSkKc2lnbWEgPC0gc2lnbWEobG1fYWRkaXRpdmUpCgpkYXRhSGxwIDwtIHBvaXNvbgoKcGFyKG1mcm93ID0gYygzLCAzKSkKZm9yIChpIGluIDE6OSkgewogIG5vYnMgPC0gbnJvdyhwb2lzb24pCiAgZGF0YUhscCR5U2ltIDwtIGZpdHRlZC52YWx1ZXMobG1fYWRkaXRpdmUpICsgcm5vcm0obm9icywgc2QgPSBzaWdtYSkKICBzaW1Nb2RlbCA8LSBsbSh5U2ltIH4gRG9zZSArIFdlaWdodCwgZGF0YUhscCkKICBwbG90KHNpbU1vZGVsLCB3aGljaCA9IDIpCn0KYGBgCgpJdCBzZWVtcyB0aGF0IGRldmlhdGlvbnMgb2YgdGhlIHNpemUgdGhhdCB3ZSBzZWUgaW4gb3VyIHJlYWwgZGF0YSBtYXkgYmUKZXhwZWN0ZWQgZXZlbiB3aGVuIG5vcm1hbGl0eSBpcyBtZXQuIEFzIHN1Y2gsIGFsbCBhc3N1bXB0aW9ucyBmb3IgbGluZWFyCnJlZ3Jlc3Npb24gc2VlbSB0byBiZSB2YWxpZC4KCiMjIEluZmVyZW5jZQoKV2UgdGhlbiBpbnNwZWN0IHRoZSByZXN1bHRzLgoKYGBge3J9CnN1bW1hcnkobG1fYWRkaXRpdmUpCmBgYAoKIyMgSW50ZXJwcmV0YXRpb24gb2YgbW9kZWwgcGFyYW1ldGVycwoKV2Ugc2VlIHRoYXQgdGhlIGVmZmVjdCBvZiBkb3NlIG9uIHN1cnZpdmFsIHRpbWUgcmVtYWlucyBzaW1pbGFyLCBob3dldmVyLCBpdApoYXMgYmVjb21lIG1vcmUgc2lnbmlmaWNhbnQgYWZ0ZXIgd2UgaGF2ZSBpbmNvcnBvcmF0ZWQgd2VpZ2h0IGluIG91ciBtb2RlbC4KSW5kZWVkLCBmcm9tIHRoZSBkYXRhIGV4cGxvcmF0aW9uLCB3ZSBsZWFybmVkIHRoYXQgd2VpZ2h0IGlzIGFzc29jaWF0ZWQgd2l0aApzdXJ2aXZhbC4KCjEuIEFzIHN1Y2gsIGJ5IGluY29ycG9yYXRpbmcgd2VpZ2h0IGluIG91ciBtb2RlbCwgd2UgYXJlIGFibGUgdG8KZXhwbGFpbiBhIGxhcmdlciBwYXJ0IG9mIHRoZSB2YXJpYWJpbGl0eSBpbiB0aGUgcmVzcG9uc2UgdmFyaWFibGUgc3Vydml2YWwgdGltZS4KQXMgYSBjb25zZXF1ZW5jZSwgdGhlIHZhcmlhYmlsaXR5IGluIHRoZSByZXNpZHVhbHMgb2YgdGhlIG1vZGVsIHdpbGwgZGVjcmVhc2UsCndoaWNoIGluIHR1cm4gd2lsbCBsZWFkIHRvIHNtYWxsZXIgc3RhbmRhcmQgZXJyb3IgZXN0aW1hdGVzIGZvciB0aGUgZGlmZmVyZW50CnBhcmFtZXRlciBlc3RpbWF0ZXMgaW4gdGhlIG1vZGVsLgoKMi4gRnJvbSB0aGUgZGF0YSBleHBsb3JhdGlvbiwgd2UgYWRkaXRpb25hbGx5IGZvdW5kIHRoYXQgdGhlIGRvam8tZmlzaCB3ZWlnaHRzCndlcmUgbm90IHVuaWZvcm0gYWNyb3NzIHRoZSBkaWZmZXJlbnQgcG9pc29uIGRvc2FnZXMgZHVlIHRvIHRoZSByYW5kb21pc2F0aW9uLgpUaGVyZWZvcmUsIHdlIGNhbiBlc3RpbWF0ZSB0aGUgZWZmZWN0IGJldHdlZW4gZG9zZSBhbmQgc3Vydml2YWwgdGltZSBiZXR0ZXIKd2hpbGUgYWNjb3VudGluZyBmb3IgdGhlIHdlaWdodC4KCkluIHRoaXMgbW9kZWwsIHRoZSBlZmZlY3Qgb2YgYERvc2VgIGNhbiBiZSBpbnRlcnByZXRlZCBhcyB0aGUgYXZlcmFnZSBjaGFuZ2UgaW4KdGhlIGxvZzIgc3Vydml2YWwgdGltZSBiZXR3ZWVuIHR3byBncm91cHMgb2YgZG9qb2Zpc2ggKip3aXRoIHRoZSBzYW1lIHdlaWdodCoqCnRoYXQgYXJlIGV4cG9zZWQgdG8gYSBwb2lzb24gZG9zYWdlIHRoYXQgZGlmZmVycyAxIG1nL0wuIEluIHN5bWJvbHM6CgpcYmVnaW57ZXFuYXJyYXl9ClxoYXR7XG11XzF9Jj0mIFxiZXRhXzAgKyBcYmV0YV9kIHhfezFkfSArIFxiZXRhX2cgeF9nIFx0ZXh0eyAoYXZlcmFnZSBsb2cyLXN1cnZpdmFsIHRpbWUgZm9yIGRvc2UgMSBmb3IgYSBjZXJ0YWluIHdlaWdodCl9XFwKXGhhdHtcbXVfMn0mPSYgXGJldGFfMCArIFxiZXRhX2QgeF97MmR9ICsgXGJldGFfZyB4X2cgXHRleHR7IChhdmVyYWdlIGxvZzItc3Vydml2YWwgdGltZSBmb3IgZG9zZSAyIGZvciB0aGF0IHNhbWUgd2VpZ2h0KX1cXApcaGF0IFxtdV8yLSBcaGF0IFxtdV8xJj0mXGJldGFfMCArIFxiZXRhX2QgeF97MmR9ICsgXGJldGFfZyB4X2cgLSAoXGJldGFfMCArIFxiZXRhX2QgeF97MWR9ICsgXGJldGFfZyB4X2cpIFx0ZXh0eyAoZGlmZmVyZW5jZSBpbiBhdmVyYWdlIGxvZzItc3Vydml2YWwgdGltZSBiZXR3ZWVuIGRvc2UgMiBlbiBkb3NlIDEpfVxcClxoYXQgXG11XzItXGhhdCBcbXVfMSY9JlxiZXRhX2QgKHhfezJkfS14X3sxZH0pClxlbmR7ZXFuYXJyYXl9CgojIyBDb25jbHVzaW9uCgpgYGB7cn0KMl4oY29lZihsbV9hZGRpdGl2ZSkpCjJeKGNvbmZpbnQobG1fYWRkaXRpdmUpKQpgYGAKClRoZSBkb3NlIG9mIHRoZSBwb2lzb24gaGFzIGFuIGV4dHJlbWVseSBzaWduaWZpY2FudCBlZmZlY3Qgb24gdGhlIGxvZzIKdHJhbnNmb3JtZWQgc3Vydml2YWwgdGltZSBvZiBkb2pvZmlzaAoocC12YWx1ZSA9IGByIGZvcm1hdChzdW1tYXJ5KGxtX2FkZGl0aXZlKSRjb2VmZmljaWVudHNbMiw0XSxkaWdpdHM9MSlgKS4gVGhlCmdlb21ldHJpYyBhdmVyYWdlIG9mIHRoZSBzdXJ2aXZhbCB0aW1lIGZvciBkb2pvZmlzaCB0aGF0IGFyZSBleHBvc2VkIHRvIGEKcG9pc29uIGRvc2UgdGhhdCBpcyAxbWcvTCBsYXJnZXIgaXMgYXBwcm94aW1hdGVseSBoYWx2ZWQgKGZhY3RvciA9ICQyXntcYmV0YV9kfT0kIGByIGZvcm1hdCgyXihsbV9hZGRpdGl2ZSRjb2VmWyJEb3NlIl0pLGRpZ2l0cz0yKWApIC4KClRoZSBlZmZlY3Qgb2Ygd2VpZ2h0IG9uIHRoZSBzdXJ2aXZhbCB0aW1lIG9mIGRvam9maXNoIGlzIGFsc28gZXh0cmVtZWx5CnNpZ25pZmljYW50CihwLXZhbHVlID0gYHIgZm9ybWF0KHN1bW1hcnkobG1fYWRkaXRpdmUpJGNvZWZmaWNpZW50c1szLDRdLGRpZ2l0cz0xKWApLiBUaGUKZ2VvbWV0cmljIGF2ZXJhZ2Ugb2YgdGhlIHN1cnZpdmFsIHRpbWUgb2YgYSBkb2pvZmlzaCB0aGF0IHdlaWdocyAxIGdyYW0gbW9yZQp0aGFuIGFub3RoZXIgZG9qb2Zpc2ggaXMgYXBwcm94aW1hdGVseSB0d2ljZSBhcyBsb25nCihmYWN0b3IgPSAkMl57IFxiZXRhX2d9JD0gYHIgZm9ybWF0KDJeKGxtX2FkZGl0aXZlJGNvZWZbIldlaWdodCJdKSxkaWdpdHM9MilgLAo5NSUgQkkgW2ByIHBhc3RlKGZvcm1hdCgyXihjb25maW50KGxtX2FkZGl0aXZlKVsiV2VpZ2h0IixdKSxkaWdpdHM9MiksY29sbGFwc2U9IiwiKWBdKS4KCiMjIFJlbWFya3MKCkluIHRoZSBgbG1fYWRkaXRpdmVgIG1vZGVsLCB3ZSBpbmNsdWRlZCBvbmx5IGEgKm1haW4gZWZmZWN0KiBmb3Igd2VpZ2h0LgpIb3dldmVyLCB0aGVyZSBjb3VsZCBhbHNvIGJlIGFuICppbnRlcmFjdGlvbiBlZmZlY3QqIGJldHdlZW4gd2VpZ2h0IGFuZApkb3NlLiBBbiBpbnRlcmFjdGlvbiBiZXR3ZWVuIHdlaWdodCBhbmQgZG9zZSBpbXBsaWVzIHRoYXQgdGhlIGRvc2UgZWZmZWN0IG9uCnRoZSBzdXJ2aXZhbCB0aW1lIGNoYW5nZXMgYWNjb3JkaW5nIHRvIHRoZSB3ZWlnaHQgb2YgdGhlIGZpc2guCg==