As a short exercise on linear regression, we will analyse the fish tank dataset.

1 The fish tank 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 poison EI-43,064. The resistance of the fish against the poison was measured as the amount of minutes the fish survived upon adding the poison (Surv_time, in minutes). Additionally, the weight of each fish was measured.

2 Goal

In this tutorial, we will study the association between dose and survival time by using a linear regression model.

Read the required libraries

library(tidyverse)

3 Import data

poison <- read_csv("poison.csv")

4 Data Exploration

head(poison)
## # A tibble: 6 x 4
##   species Weight  Dose Surv_time
##     <dbl>  <dbl> <dbl>     <dbl>
## 1       0   1.88   1        3.46
## 2       2   1.73   1.1      2.11
## 3       1   2.83   1.2     11.4 
## 4       2   1.75   1.3      1.82
## 5       0   2.11   1.4      3.28
## 6       0   1.85   1.5      2.96

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

  1. Capitalize the fist column name
  2. Set the Species column as a factor
  3. Change the speciec factor levels from 0, 1 and 2 to Dojofish, Goldfish and Zebrafish. Hint: use the fct_recode function.
poison <- poison %>%
  rename("Species" = "species") %>%
  mutate(Species = as.factor(Species)) %>%
  mutate(Species = fct_recode(Species, Dojofish = "0", Goldfish = "1", Zebrafish = "2"))

poison
## # A tibble: 96 x 4
##    Species   Weight  Dose Surv_time
##    <fct>      <dbl> <dbl>     <dbl>
##  1 Dojofish    1.88   1        3.46
##  2 Zebrafish   1.73   1.1      2.11
##  3 Goldfish    2.83   1.2     11.4 
##  4 Zebrafish   1.75   1.3      1.82
##  5 Dojofish    2.11   1.4      3.28
##  6 Dojofish    1.85   1.5      2.96
##  7 Zebrafish   1.22   1.6      1.85
##  8 Goldfish    2.05   1.7      8.05
##  9 Dojofish    1.80   1.8      1.65
## 10 Goldfish    2.50   1.9      7.95
## # … with 86 more rows

How many fish do we have per species?

poison %>%
  count(Species)
## # A tibble: 3 x 2
##   Species       n
##   <fct>     <int>
## 1 Dojofish     39
## 2 Goldfish     38
## 3 Zebrafish    19

Make a suitable visualization of the association between the dose and the survival time. Additionally, add the fish species as a color to the plot.

poison %>%
  ggplot(aes(x=Dose,y=Surv_time)) +
  geom_point() + 
  stat_smooth(method = "loess") +
  geom_smooth(method='lm',col="black") + 
  ylab("Survival time (min)") +
  xlab("Dose (mg)") +
  geom_point(aes(col=Species)) + ## not necessary, additional layer of information
  scale_color_manual(values = c("red","darkgoldenrod","black")) +
  theme_bw()

The linear regression line (black) is a good approximation of the best fitting smooth line (blue) through the data. Based on this figure, it seems realistic to suggest a linear relationship between dose and survival, where higher doses have lower survival times (as expected). However, before we start with the regression analyis we must check if all required assumptions are met.

5 Analysis

5.1 Assumptions of linear regression

List assumptions:

  1. The observations are independent of each other
  2. Linearity between the response and predictor variable
  3. The residues of the model must be normally distributed
  4. Homoscedasticity of the data

The first assumption is not met. There are patterns of relatedness in the data. Indeed, we expect fish of the same species to have a more similar response to the poison as compared to fish of another species. Equivalently, we expect that fish of the same weight have a more similar response to the poison as compared to fish of different weight.

** For now, we will ignore this problem . In a later tutorial, we will see how we can account for this dependence by including the species data and weigth data in the linear model (class on multiple regression). As such, you may assume the assumption is met. **

We will check the other assumptions by first fitting the linear model and plotting the output. As such, we will get all the required diagnostic plots.

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

## display the diagnostic plots of the model
plot(model)

We have four diagnostic plots:

  1. Linearity with the Residuals vs fitted plot
  • predictor of predictions \(\hat\beta_0+\hat\beta_1 x\) on \(X\)-axis
  • residuals on \(Y\)-as \[e_i=y_i-\hat{g}(x_i)=y_i-\hat\beta_0-\hat\beta_1\times x_i,\]

If there would be a linear relationship in the data, the residuals are expected to lie on the y=0 line for the entire range of predicted values. This is clearly the case: the assumption of linearity is met.

  1. Normal Q-Q
  • QQ-plot of the residuals \(e_i\).

The residuals of the linear regression model should be normally distributed. Given the second diagnostic plot, this seems not to be the case. In stead, we observe a short left tail and a long right tail. The assumption of normal residues is ** not met. **

  1. Homoscedasticity
  • Square-root of the absolute value of standardized residuals in function of the fitted values

To meet the third assumption of linear regression, the variance on the Square-root of the absolute value of standardized residuals must be similar over the entire range of fitted values. The smoother in the plot helps us with looking at this; it should be nicely horizontal over the entire range of fitted values. This seems not to be the case: for larger fitted values, the variance increase slightly. The assumption of homoscedasticity is ** not met. **

Multiple assumptions are not met, so way not continue by performing a linear regression.

One “trick” is to log-transform the data. Indeed, data with heavy right tails can often be normalized by applying this strategy

Generate a new column in the poison dataset, containing the log-transformed survival times.

poison <- poison %>%
  mutate(log.Surv_time = log(Surv_time))

Refit the (log-)linear model. Generate diagnostic plots. Assess the assumptions.

log.model <- lm(log.Surv_time~Dose, data=poison) 
plot(log.model)

  1. The independence assumption is nott met, but for this exercise, we will assume it is met (see above).
  2. Upon log-transformation, the linearity assumption is still met.
  3. Upon log-transformation, the normality assumption is also met.
  4. Upon log-transformation, the homoscedasticity assumption is also met.

Look at the output of the log-linear model:

summary(log.model)
## 
## Call:
## lm(formula = log.Surv_time ~ Dose, data = poison)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1.14507 -0.38506 -0.06518  0.37175  1.09357 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   2.1046     0.2396   8.782 7.13e-14 ***
## Dose         -0.5112     0.1509  -3.387  0.00103 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.5104 on 94 degrees of freedom
## Multiple R-squared:  0.1088, Adjusted R-squared:  0.0993 
## F-statistic: 11.47 on 1 and 94 DF,  p-value: 0.001032

Compute the 95% confidence interval on the model parameters:

confint(log.model)
##                 2.5 %     97.5 %
## (Intercept)  1.628792  2.5804330
## Dose        -0.810830 -0.2115505

5.2 Interpretation on the log scale

Currently, all the outcomes should be interpreted on the log-scale. Indeed, since we are now modelling the log of survival time, we don’t have direct inference on survival time.

As such, we may interpret the output as follows:

  • The slope:

If the dose at which the poison is administered increases with 1 mg, then the mean of the natural logarithm of survival time will decrease by 0.5112 units (95% CI [-0.8109,-0.2116]). This decrease is significant on the 5% significance level (p=0.00103).

  • The intercept:

The average of the natural logarithm of survival time for fish that were given a dose of 0 mg is 2.1046 (95% CI [1.6288, 2.5804]). This value is significantly different from 0 on the 5% significance level (7.13e-14). This conclusion will be discussed in more detail below.

5.3 Interpretation on the original scale

The interpretation the log-scale is quite difficult: the natural logarithm survival time is not exactly a casual measure. To ease the interpetation, we may backtransform the results to the original scale (time in minutes). This we can do by taking the exponent of the outcomes:

exp(summary(log.model)$coefficients[,"Estimate"])
## (Intercept)        Dose 
##   8.2039216   0.5997813

and of their confidence intervals:

exp(confint(log.model))
##                2.5 %     97.5 %
## (Intercept) 5.097711 13.2028535
## Dose        0.444489  0.8093284

Now, we can interpret the results in terms of the geometric mean:

  • The slope:

If the dose at which the poison is administered increases with 1 mg, then the geometric mean of survival time will decrease by a factor of 0.5998 (95% CI [0.4445,0.8093]). This decrease is significant on the 5% significance level (p=0.00103).

  • The intercept:

The geometric mean of the survival time for fish that were given a dose of 0 mg is 8.2039 minutes (95% CI [5.0977, 13.2029]). This value is significantly different from 0 on the 5% significance level (7.13e-14).

To go a little further on the latter interpretation, our analysis seems to suggest that fish in uncontaminated water would only suvive for about 8 minutes! This seems a little bit fishy

Here, we make a diagnostic plot to explain this behavior:

plot(x=poison$Dose, y=poison$Surv_time, xlab="Dose (mg)", ylab="Survival time (min)", xlim=c(0,2.2))

abline(lsfit(poison$Dose,poison$Surv_time), lty=2) ## lty=2 draws a dashed line

## add the intercept as a point
summary_model <- summary(model)
points(0,summary_model$coefficients["(Intercept)","Estimate"],col="red", pch=16)

We can see that the dose value of 0 mg does not fall within the same range as our data. As such, it is unlikely that we can assume this model to have correct inference on the intercept: we expect that the linearity assumption will not be met for these low values. The model will only be trustworthy on the range of data that we use to build the model on!

This is not really a problem: we are mainly interested in the slope parameter in the given range of datapoints.

6 Conclusion

  • On the log scale:

If the dose at which the poison is administered increases with 1 mg, then the mean of the natural logarithm of survival time will decrease by 0.5112 units (95% CI [-0.8109,-0.2116]). This decrease is highly significant on the 5% significance level (p=0.00103).

  • On the original scale:

If the dose at which the poison is administered increases with 1 mg, then the geometric mean of survival time will decrease by a factor of 0.5998 (95% CI [0.4445,0.8093]). This decrease is highly significant on the 5% significance level (p=0.00103).

Again, note that in this dataset the assumption of independence is actually not met. In the tutorial of multiple regression, we will revisit this exercise. More specifically, we will there study the association between dose and survival while accounting for differences between species and fish of different weight.


LS0tCnRpdGxlOiAiVHV0b3JpYWwgNi4yOiBMaW5lYXIgcmVncmVzc2lvbiBvbiB0aGUgZmlzaCB0YW5rIGRhdGFzZXQiICAgCm91dHB1dDoKICAgIGh0bWxfZG9jdW1lbnQ6CiAgICAgIGNvZGVfZG93bmxvYWQ6IHRydWUgICAgCiAgICAgIHRoZW1lOiBjb3NtbwogICAgICB0b2M6IHRydWUKICAgICAgdG9jX2Zsb2F0OiB0cnVlCiAgICAgIGhpZ2hsaWdodDogdGFuZ28KICAgICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCi0tLQoKQXMgYSBzaG9ydCBleGVyY2lzZSBvbiBsaW5lYXIgcmVncmVzc2lvbiwgd2Ugd2lsbCBhbmFseXNlCnRoZSBmaXNoIHRhbmsgZGF0YXNldC4KCiMgVGhlIGZpc2ggdGFuayBkYXRhc2V0CgpJbiB0aGlzIGV4cGVyaW1lbnQsIDk2IGZpc2ggKGRvam9maXNoLCBnb2xkZmlzaCBhbmQgemVicmFmaXNoKQp3ZXJlIHBsYWNlZCBzZXBhcmF0ZWx5IGluIGEgdGFuayB3aXRoIHR3byBsaXRlcnMgb2Ygd2F0ZXIgYW5kCmEgY2VydGFpbiBkb3NlIChpbiBtZykgb2YgcG9pc29uIEVJLTQzLDA2NC4gVGhlIHJlc2lzdGFuY2UKb2YgdGhlIGZpc2ggYWdhaW5zdCB0aGUgcG9pc29uIHdhcyBtZWFzdXJlZCBhcyB0aGUgYW1vdW50IG9mCm1pbnV0ZXMgdGhlIGZpc2ggc3Vydml2ZWQgdXBvbiBhZGRpbmcgdGhlIHBvaXNvbiAoU3Vydl90aW1lLCBpbgptaW51dGVzKS4gQWRkaXRpb25hbGx5LCB0aGUgd2VpZ2h0IG9mIGVhY2ggZmlzaCB3YXMgbWVhc3VyZWQuCgojIEdvYWwKCkluIHRoaXMgdHV0b3JpYWwsIHdlIHdpbGwgc3R1ZHkgdGhlIGFzc29jaWF0aW9uIGJldHdlZW4gZG9zZSBhbmQKc3Vydml2YWwgdGltZSBieSB1c2luZyBhIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsLgoKUmVhZCB0aGUgcmVxdWlyZWQgbGlicmFyaWVzCgpgYGB7ciwgbWVzc2FnZSA9IEZBTFNFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKYGBgCgojIEltcG9ydCBkYXRhCgpgYGB7ciwgbWVzc2FnZT1GQUxTRX0KcG9pc29uIDwtIHJlYWRfY3N2KCJwb2lzb24uY3N2IikKYGBgCgojIERhdGEgRXhwbG9yYXRpb24KCmBgYHtyfQpoZWFkKHBvaXNvbikKYGBgCgpXZSBjYW4gc2VlIGEgY291cGxlIG9mIHRoaW5ncyBpbiB0aGUgZGF0YSB0aGF0IGNhbgpiZSBpbXByb3ZlZCB1cG9uOgoKMS4gQ2FwaXRhbGl6ZSB0aGUgZmlzdCBjb2x1bW4gbmFtZSAKMi4gU2V0IHRoZSBTcGVjaWVzIGNvbHVtbiBhcyBhIGZhY3RvcgozLiBDaGFuZ2UgdGhlIHNwZWNpZWMgZmFjdG9yIGxldmVscyBmcm9tIDAsIDEgYW5kIDIgdG8KRG9qb2Zpc2gsIEdvbGRmaXNoIGFuZCBaZWJyYWZpc2guIEhpbnQ6IHVzZSB0aGUgZmN0X3JlY29kZQpmdW5jdGlvbi4KCmBgYHtyfQpwb2lzb24gPC0gcG9pc29uICU+JQogIHJlbmFtZSgiU3BlY2llcyIgPSAic3BlY2llcyIpICU+JQogIG11dGF0ZShTcGVjaWVzID0gYXMuZmFjdG9yKFNwZWNpZXMpKSAlPiUKICBtdXRhdGUoU3BlY2llcyA9IGZjdF9yZWNvZGUoU3BlY2llcywgRG9qb2Zpc2ggPSAiMCIsIEdvbGRmaXNoID0gIjEiLCBaZWJyYWZpc2ggPSAiMiIpKQoKcG9pc29uCmBgYAoKSG93IG1hbnkgZmlzaCBkbyB3ZSBoYXZlIHBlciBzcGVjaWVzPwoKYGBge3J9CnBvaXNvbiAlPiUKICBjb3VudChTcGVjaWVzKQpgYGAKCk1ha2UgYSBzdWl0YWJsZSB2aXN1YWxpemF0aW9uIG9mIHRoZSBhc3NvY2lhdGlvbiBiZXR3ZWVuCnRoZSBkb3NlIGFuZCB0aGUgc3Vydml2YWwgdGltZS4gQWRkaXRpb25hbGx5LCBhZGQgdGhlIGZpc2ggc3BlY2llcwphcyBhIGNvbG9yIHRvIHRoZSBwbG90LgoKYGBge3J9CnBvaXNvbiAlPiUKICBnZ3Bsb3QoYWVzKHg9RG9zZSx5PVN1cnZfdGltZSkpICsKICBnZW9tX3BvaW50KCkgKyAKICBzdGF0X3Ntb290aChtZXRob2QgPSAibG9lc3MiKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kPSdsbScsY29sPSJibGFjayIpICsgCiAgeWxhYigiU3Vydml2YWwgdGltZSAobWluKSIpICsKICB4bGFiKCJEb3NlIChtZykiKSArCiAgZ2VvbV9wb2ludChhZXMoY29sPVNwZWNpZXMpKSArICMjIG5vdCBuZWNlc3NhcnksIGFkZGl0aW9uYWwgbGF5ZXIgb2YgaW5mb3JtYXRpb24KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygicmVkIiwiZGFya2dvbGRlbnJvZCIsImJsYWNrIikpICsKICB0aGVtZV9idygpCmBgYAoKVGhlIGxpbmVhciByZWdyZXNzaW9uIGxpbmUgKGJsYWNrKSBpcyBhIGdvb2QgYXBwcm94aW1hdGlvbgpvZiB0aGUgYmVzdCBmaXR0aW5nIHNtb290aCBsaW5lIChibHVlKSB0aHJvdWdoIHRoZSBkYXRhLgpCYXNlZCBvbiB0aGlzIGZpZ3VyZSwgaXQgc2VlbXMgcmVhbGlzdGljIHRvIHN1Z2dlc3QgYSBsaW5lYXIKcmVsYXRpb25zaGlwIGJldHdlZW4gZG9zZSBhbmQgc3Vydml2YWwsIHdoZXJlIGhpZ2hlciBkb3NlcwpoYXZlIGxvd2VyIHN1cnZpdmFsIHRpbWVzIChhcyBleHBlY3RlZCkuIEhvd2V2ZXIsIGJlZm9yZSB3ZQpzdGFydCB3aXRoIHRoZSByZWdyZXNzaW9uIGFuYWx5aXMgd2UgbXVzdCBjaGVjayBpZiBhbGwgcmVxdWlyZWQKYXNzdW1wdGlvbnMgYXJlIG1ldC4KCiMgQW5hbHlzaXMKCiMjIEFzc3VtcHRpb25zIG9mIGxpbmVhciByZWdyZXNzaW9uCgpMaXN0IGFzc3VtcHRpb25zOgoKMS4gVGhlIG9ic2VydmF0aW9ucyBhcmUgaW5kZXBlbmRlbnQgb2YgZWFjaCBvdGhlcgoyLiBMaW5lYXJpdHkgYmV0d2VlbiB0aGUgcmVzcG9uc2UgYW5kIHByZWRpY3RvciB2YXJpYWJsZQozLiBUaGUgcmVzaWR1ZXMgb2YgdGhlIG1vZGVsIG11c3QgYmUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQKNC4gSG9tb3NjZWRhc3RpY2l0eSBvZiB0aGUgZGF0YQoKVGhlIGZpcnN0IGFzc3VtcHRpb24gaXMgKipub3QgbWV0KiouIFRoZXJlIGFyZSBwYXR0ZXJucwpvZiByZWxhdGVkbmVzcyBpbiB0aGUgZGF0YS4gSW5kZWVkLCB3ZSBleHBlY3QKZmlzaCBvZiB0aGUgc2FtZSBzcGVjaWVzIHRvIGhhdmUgYSBtb3JlIHNpbWlsYXIgcmVzcG9uc2UgdG8KdGhlIHBvaXNvbiBhcyBjb21wYXJlZCB0byBmaXNoIG9mIGFub3RoZXIgc3BlY2llcy4KRXF1aXZhbGVudGx5LCB3ZSBleHBlY3QgdGhhdCBmaXNoIG9mIHRoZSBzYW1lIHdlaWdodCBoYXZlIAphIG1vcmUgc2ltaWxhciByZXNwb25zZSB0byB0aGUgcG9pc29uIGFzIGNvbXBhcmVkIHRvIGZpc2ggCm9mIGRpZmZlcmVudCB3ZWlnaHQuIAoKKiogRm9yIG5vdywgd2Ugd2lsbCBpZ25vcmUgdGhpcyBwcm9ibGVtICoqLiBJbiBhIGxhdGVyIAp0dXRvcmlhbCwgd2Ugd2lsbCBzZWUgaG93IHdlIGNhbiBhY2NvdW50IGZvciB0aGlzIGRlcGVuZGVuY2UKYnkgaW5jbHVkaW5nIHRoZSBzcGVjaWVzIGRhdGEgYW5kIHdlaWd0aCBkYXRhIGluIHRoZSBsaW5lYXIgbW9kZWwKKGNsYXNzIG9uIG11bHRpcGxlIHJlZ3Jlc3Npb24pLiBBcyBzdWNoLCAqKiB5b3UgbWF5IGFzc3VtZSAqKgoqKiB0aGUgYXNzdW1wdGlvbiBpcyBtZXQuICoqCgpXZSB3aWxsIGNoZWNrIHRoZSBvdGhlciBhc3N1bXB0aW9ucyBieSBmaXJzdCBmaXR0aW5nIHRoZSBsaW5lYXIKbW9kZWwgYW5kIHBsb3R0aW5nIHRoZSBvdXRwdXQuIEFzIHN1Y2gsIHdlIHdpbGwgZ2V0IGFsbCB0aGUKcmVxdWlyZWQgZGlhZ25vc3RpYyBwbG90cy4KCmBgYHtyfQojIyBmaXQgYSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbCB3aXRoICdTdXJ2X3RpbWUnIGFzIHJlc3BvbnNlIHZhcmlhYmxlIGFuZCAnRG9zZScgYXMgcHJlZGljdG9yIHZhcmlhYmVsZQptb2RlbCA8LSBsbShTdXJ2X3RpbWV+RG9zZSwgZGF0YT1wb2lzb24pIAoKIyMgZGlzcGxheSB0aGUgZGlhZ25vc3RpYyBwbG90cyBvZiB0aGUgbW9kZWwKcGxvdChtb2RlbCkKYGBgCgpXZSBoYXZlIGZvdXIgZGlhZ25vc3RpYyBwbG90czoKCjIuIExpbmVhcml0eSB3aXRoIHRoZSBSZXNpZHVhbHMgdnMgZml0dGVkIHBsb3QKCi0gcHJlZGljdG9yIG9mIHByZWRpY3Rpb25zICRcaGF0XGJldGFfMCtcaGF0XGJldGFfMSB4JCBvbiAkWCQtYXhpcwotICpyZXNpZHVhbHMqIG9uICRZJC1hcwokJGVfaT15X2ktXGhhdHtnfSh4X2kpPXlfaS1caGF0XGJldGFfMC1caGF0XGJldGFfMVx0aW1lcyB4X2ksJCQKCklmIHRoZXJlIHdvdWxkIGJlIGEgbGluZWFyIHJlbGF0aW9uc2hpcCBpbiB0aGUgZGF0YSwKdGhlIHJlc2lkdWFscyBhcmUgZXhwZWN0ZWQgdG8gbGllIG9uIHRoZSB5PTAgbGluZSBmb3IKdGhlIGVudGlyZSByYW5nZSBvZiBwcmVkaWN0ZWQgdmFsdWVzLiBUaGlzIGlzIGNsZWFybHkKdGhlIGNhc2U6IHRoZSBhc3N1bXB0aW9uIG9mIGxpbmVhcml0eSBpcyBtZXQuCgozLiBOb3JtYWwgUS1RCgotIFFRLXBsb3Qgb2YgdGhlIHJlc2lkdWFscyAkZV9pJC4KClRoZSByZXNpZHVhbHMgb2YgdGhlIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsIHNob3VsZCBiZSBub3JtYWxseQpkaXN0cmlidXRlZC4gR2l2ZW4gdGhlIHNlY29uZCBkaWFnbm9zdGljIHBsb3QsIHRoaXMgc2VlbXMgbm90CnRvIGJlIHRoZSBjYXNlLiBJbiBzdGVhZCwgd2Ugb2JzZXJ2ZSBhIHNob3J0IGxlZnQgdGFpbCBhbmQgYQpsb25nIHJpZ2h0IHRhaWwuIFRoZSBhc3N1bXB0aW9uIG9mIG5vcm1hbCByZXNpZHVlcyBpcyAqKiBub3QgbWV0LiAqKgoKNC4gSG9tb3NjZWRhc3RpY2l0eQoKLSBTcXVhcmUtcm9vdCBvZiB0aGUgYWJzb2x1dGUgdmFsdWUgb2Ygc3RhbmRhcmRpemVkIHJlc2lkdWFscwppbiBmdW5jdGlvbiBvZiB0aGUgZml0dGVkIHZhbHVlcwoKVG8gbWVldCB0aGUgdGhpcmQgYXNzdW1wdGlvbiBvZiBsaW5lYXIgcmVncmVzc2lvbiwgdGhlIHZhcmlhbmNlCm9uIHRoZSBfU3F1YXJlLXJvb3Qgb2YgdGhlIGFic29sdXRlIHZhbHVlIG9mIHN0YW5kYXJkaXplZCByZXNpZHVhbHNfCm11c3QgYmUgc2ltaWxhciBvdmVyIHRoZSBlbnRpcmUgcmFuZ2Ugb2YgZml0dGVkIHZhbHVlcy4gVGhlIHNtb290aGVyCmluIHRoZSBwbG90IGhlbHBzIHVzIHdpdGggbG9va2luZyBhdCB0aGlzOyBpdCBzaG91bGQgYmUgbmljZWx5Cmhvcml6b250YWwgb3ZlciB0aGUgZW50aXJlIHJhbmdlIG9mIGZpdHRlZCB2YWx1ZXMuIFRoaXMgc2VlbXMgbm90CnRvIGJlIHRoZSBjYXNlOiBmb3IgbGFyZ2VyIGZpdHRlZCB2YWx1ZXMsIHRoZSB2YXJpYW5jZSBpbmNyZWFzZSBzbGlnaHRseS4KVGhlIGFzc3VtcHRpb24gb2YgaG9tb3NjZWRhc3RpY2l0eSBpcyAqKiBub3QgbWV0LiAqKgoKTXVsdGlwbGUgYXNzdW1wdGlvbnMgYXJlIG5vdCBtZXQsIHNvIHdheSBub3QgY29udGludWUgYnkgcGVyZm9ybWluZwphIGxpbmVhciByZWdyZXNzaW9uLgoKT25lICJ0cmljayIgaXMgdG8gbG9nLXRyYW5zZm9ybSB0aGUgZGF0YS4gSW5kZWVkLCBkYXRhIHdpdGggaGVhdnkKcmlnaHQgdGFpbHMgY2FuIG9mdGVuIGJlIG5vcm1hbGl6ZWQgYnkgYXBwbHlpbmcgdGhpcyBzdHJhdGVneQoKR2VuZXJhdGUgYSBuZXcgY29sdW1uIGluIHRoZSBwb2lzb24gZGF0YXNldCwgY29udGFpbmluZyB0aGUgCmxvZy10cmFuc2Zvcm1lZCBzdXJ2aXZhbCB0aW1lcy4KCmBgYHtyfQpwb2lzb24gPC0gcG9pc29uICU+JQogIG11dGF0ZShsb2cuU3Vydl90aW1lID0gbG9nKFN1cnZfdGltZSkpCmBgYAoKUmVmaXQgdGhlIChsb2ctKWxpbmVhciBtb2RlbC4gR2VuZXJhdGUgZGlhZ25vc3RpYyBwbG90cy4KQXNzZXNzIHRoZSBhc3N1bXB0aW9ucy4KCmBgYHtyfQpsb2cubW9kZWwgPC0gbG0obG9nLlN1cnZfdGltZX5Eb3NlLCBkYXRhPXBvaXNvbikgCnBsb3QobG9nLm1vZGVsKQpgYGAKCjEuIFRoZSBpbmRlcGVuZGVuY2UgYXNzdW1wdGlvbiBpcyBub3R0IG1ldCwgYnV0IGZvciB0aGlzIGV4ZXJjaXNlLAp3ZSB3aWxsIGFzc3VtZSBpdCAqKmlzIG1ldCoqIChzZWUgYWJvdmUpLgoyLiBVcG9uIGxvZy10cmFuc2Zvcm1hdGlvbiwgdGhlIGxpbmVhcml0eSBhc3N1bXB0aW9uIGlzIHN0aWxsICoqbWV0KiouCjMuIFVwb24gbG9nLXRyYW5zZm9ybWF0aW9uLCB0aGUgbm9ybWFsaXR5IGFzc3VtcHRpb24gaXMgYWxzbyAqKm1ldCoqLgo0LiBVcG9uIGxvZy10cmFuc2Zvcm1hdGlvbiwgdGhlIGhvbW9zY2VkYXN0aWNpdHkgYXNzdW1wdGlvbiBpcyBhbHNvICoqbWV0KiouCgpMb29rIGF0IHRoZSBvdXRwdXQgb2YgdGhlIGxvZy1saW5lYXIgbW9kZWw6CgpgYGB7cn0Kc3VtbWFyeShsb2cubW9kZWwpCmBgYAoKQ29tcHV0ZSB0aGUgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgb24gdGhlIG1vZGVsIHBhcmFtZXRlcnM6CgpgYGB7cn0KY29uZmludChsb2cubW9kZWwpCmBgYAoKIyMgSW50ZXJwcmV0YXRpb24gb24gdGhlIGxvZyBzY2FsZSAKCkN1cnJlbnRseSwgYWxsIHRoZSBvdXRjb21lcyBzaG91bGQgYmUgaW50ZXJwcmV0ZWQgb24gdGhlIGxvZy1zY2FsZS4KSW5kZWVkLCBzaW5jZSB3ZSBhcmUgbm93IG1vZGVsbGluZyAgX3RoZSBsb2cgb2Ygc3Vydml2YWwgdGltZV8sIHdlIApkb24ndCBoYXZlIGRpcmVjdCBpbmZlcmVuY2Ugb24gc3Vydml2YWwgdGltZS4KCkFzIHN1Y2gsIHdlIG1heSBpbnRlcnByZXQgdGhlIG91dHB1dCBhcyBmb2xsb3dzOgoKLSBUaGUgc2xvcGU6CgpJZiB0aGUgZG9zZSBhdCB3aGljaCB0aGUgcG9pc29uIGlzIGFkbWluaXN0ZXJlZCBpbmNyZWFzZXMgd2l0aCAxIG1nLAp0aGVuIHRoZSBtZWFuIG9mIHRoZSBuYXR1cmFsIGxvZ2FyaXRobSBvZiBzdXJ2aXZhbCB0aW1lIHdpbGwgZGVjcmVhc2UKYnkgMC41MTEyIHVuaXRzICg5NSUgQ0kgWy0wLjgxMDksLTAuMjExNl0pLiBUaGlzIGRlY3JlYXNlIGlzIHNpZ25pZmljYW50Cm9uIHRoZSA1JSBzaWduaWZpY2FuY2UgbGV2ZWwgKHA9MC4wMDEwMykuCgotIFRoZSBpbnRlcmNlcHQ6CgpUaGUgYXZlcmFnZSBvZiB0aGUgbmF0dXJhbCBsb2dhcml0aG0gb2Ygc3Vydml2YWwgdGltZSBmb3IgZmlzaCB0aGF0CndlcmUgZ2l2ZW4gYSBkb3NlIG9mIDAgbWcgaXMgMi4xMDQ2ICg5NSUgQ0kgWzEuNjI4OCwgMi41ODA0XSkuIFRoaXMKdmFsdWUgaXMgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgZnJvbSAwIG9uIHRoZSA1JSBzaWduaWZpY2FuY2UgbGV2ZWwKKDcuMTNlLTE0KS4gVGhpcyBjb25jbHVzaW9uIHdpbGwgYmUgZGlzY3Vzc2VkIGluIG1vcmUgZGV0YWlsIGJlbG93LgoKIyMgSW50ZXJwcmV0YXRpb24gb24gdGhlIG9yaWdpbmFsIHNjYWxlIAoKVGhlIGludGVycHJldGF0aW9uIHRoZSBsb2ctc2NhbGUgaXMgcXVpdGUgZGlmZmljdWx0OiB0aGUgbmF0dXJhbCAKbG9nYXJpdGhtIHN1cnZpdmFsIHRpbWUgaXMgbm90IGV4YWN0bHkgYSBjYXN1YWwgbWVhc3VyZS4gVG8gZWFzZSAKdGhlIGludGVycGV0YXRpb24sIHdlIG1heSBiYWNrdHJhbnNmb3JtIHRoZSByZXN1bHRzIHRvIHRoZSBvcmlnaW5hbApzY2FsZSAodGltZSBpbiBtaW51dGVzKS4gVGhpcyB3ZSBjYW4gZG8gYnkgdGFraW5nIHRoZSBleHBvbmVudCBvZgp0aGUgb3V0Y29tZXM6CgpgYGB7cn0KZXhwKHN1bW1hcnkobG9nLm1vZGVsKSRjb2VmZmljaWVudHNbLCJFc3RpbWF0ZSJdKQpgYGAKCmFuZCBvZiB0aGVpciBjb25maWRlbmNlIGludGVydmFsczoKCmBgYHtyfQpleHAoY29uZmludChsb2cubW9kZWwpKQpgYGAKCk5vdywgd2UgY2FuIGludGVycHJldCB0aGUgcmVzdWx0cyBpbiB0ZXJtcyBvZiB0aGUgZ2VvbWV0cmljIG1lYW46CgotIFRoZSBzbG9wZToKCklmIHRoZSBkb3NlIGF0IHdoaWNoIHRoZSBwb2lzb24gaXMgYWRtaW5pc3RlcmVkIGluY3JlYXNlcyB3aXRoIDEgbWcsCnRoZW4gdGhlIGdlb21ldHJpYyBtZWFuIG9mIHN1cnZpdmFsIHRpbWUgd2lsbCBkZWNyZWFzZSBieSBhIGZhY3RvcgpvZiAwLjU5OTggKDk1JSBDSSBbMC40NDQ1LDAuODA5M10pLiBUaGlzIGRlY3JlYXNlIGlzIHNpZ25pZmljYW50Cm9uIHRoZSA1JSBzaWduaWZpY2FuY2UgbGV2ZWwgKHA9MC4wMDEwMykuCgotIFRoZSBpbnRlcmNlcHQ6CgpUaGUgZ2VvbWV0cmljIG1lYW4gb2YgdGhlIHN1cnZpdmFsIHRpbWUgZm9yIGZpc2ggdGhhdCB3ZXJlIGdpdmVuIGEgCmRvc2Ugb2YgMCBtZyBpcyA4LjIwMzkgbWludXRlcyAoOTUlIENJIFs1LjA5NzcsIDEzLjIwMjldKS4gVGhpcwp2YWx1ZSBpcyBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBmcm9tIDAgb24gdGhlIDUlIHNpZ25pZmljYW5jZSBsZXZlbAooNy4xM2UtMTQpLgoKVG8gZ28gYSBsaXR0bGUgZnVydGhlciBvbiB0aGUgbGF0dGVyIGludGVycHJldGF0aW9uLCBvdXIgYW5hbHlzaXMgc2VlbXMKdG8gc3VnZ2VzdCB0aGF0IGZpc2ggaW4gdW5jb250YW1pbmF0ZWQgd2F0ZXIgd291bGQgb25seSBzdXZpdmUgZm9yIGFib3V0CjggbWludXRlcyEgVGhpcyBzZWVtcyBhIGxpdHRsZSBiaXQgX2Zpc2h5Xy4uLgoKSGVyZSwgd2UgbWFrZSBhIGRpYWdub3N0aWMgcGxvdCB0byBleHBsYWluIHRoaXMgYmVoYXZpb3I6CgpgYGB7cn0KcGxvdCh4PXBvaXNvbiREb3NlLCB5PXBvaXNvbiRTdXJ2X3RpbWUsIHhsYWI9IkRvc2UgKG1nKSIsIHlsYWI9IlN1cnZpdmFsIHRpbWUgKG1pbikiLCB4bGltPWMoMCwyLjIpKQoKYWJsaW5lKGxzZml0KHBvaXNvbiREb3NlLHBvaXNvbiRTdXJ2X3RpbWUpLCBsdHk9MikgIyMgbHR5PTIgZHJhd3MgYSBkYXNoZWQgbGluZQoKIyMgYWRkIHRoZSBpbnRlcmNlcHQgYXMgYSBwb2ludApzdW1tYXJ5X21vZGVsIDwtIHN1bW1hcnkobW9kZWwpCnBvaW50cygwLHN1bW1hcnlfbW9kZWwkY29lZmZpY2llbnRzWyIoSW50ZXJjZXB0KSIsIkVzdGltYXRlIl0sY29sPSJyZWQiLCBwY2g9MTYpCmBgYAoKV2UgY2FuIHNlZSB0aGF0IHRoZSBkb3NlIHZhbHVlIG9mIDAgbWcgZG9lcyBub3QgZmFsbCB3aXRoaW4KdGhlIHNhbWUgcmFuZ2UgYXMgb3VyIGRhdGEuIEFzIHN1Y2gsIGl0IGlzIHVubGlrZWx5IHRoYXQgd2UKY2FuIGFzc3VtZSB0aGlzIG1vZGVsIHRvIGhhdmUgY29ycmVjdCBpbmZlcmVuY2Ugb24gdGhlIGludGVyY2VwdDoKd2UgZXhwZWN0IHRoYXQgdGhlIGxpbmVhcml0eSBhc3N1bXB0aW9uIHdpbGwgbm90IGJlIG1ldCBmb3IgdGhlc2UKbG93IHZhbHVlcy4gVGhlIG1vZGVsIHdpbGwgb25seSBiZSB0cnVzdHdvcnRoeSBvbiB0aGUgcmFuZ2Ugb2YKZGF0YSB0aGF0IHdlIHVzZSB0byBidWlsZCB0aGUgbW9kZWwgb24hCgpUaGlzIGlzIG5vdCByZWFsbHkgYSBwcm9ibGVtOiB3ZSBhcmUgbWFpbmx5IGludGVyZXN0ZWQgaW4gdGhlIHNsb3BlCnBhcmFtZXRlciBpbiB0aGUgZ2l2ZW4gcmFuZ2Ugb2YgZGF0YXBvaW50cy4KCiMgQ29uY2x1c2lvbgoKLSBPbiB0aGUgbG9nIHNjYWxlOgoKSWYgdGhlIGRvc2UgYXQgd2hpY2ggdGhlIHBvaXNvbiBpcyBhZG1pbmlzdGVyZWQgaW5jcmVhc2VzIHdpdGggMSBtZywKdGhlbiB0aGUgbWVhbiBvZiB0aGUgbmF0dXJhbCBsb2dhcml0aG0gb2Ygc3Vydml2YWwgdGltZSB3aWxsIGRlY3JlYXNlCmJ5IDAuNTExMiB1bml0cyAoOTUlIENJIFstMC44MTA5LC0wLjIxMTZdKS4gVGhpcyBkZWNyZWFzZSBpcyBoaWdobHkKc2lnbmlmaWNhbnQgb24gdGhlIDUlIHNpZ25pZmljYW5jZSBsZXZlbCAocD0wLjAwMTAzKS4KCi0gT24gdGhlIG9yaWdpbmFsIHNjYWxlOgoKSWYgdGhlIGRvc2UgYXQgd2hpY2ggdGhlIHBvaXNvbiBpcyBhZG1pbmlzdGVyZWQgaW5jcmVhc2VzIHdpdGggMSBtZywKdGhlbiB0aGUgZ2VvbWV0cmljIG1lYW4gb2Ygc3Vydml2YWwgdGltZSB3aWxsIGRlY3JlYXNlIGJ5IGEgZmFjdG9yCm9mIDAuNTk5OCAoOTUlIENJIFswLjQ0NDUsMC44MDkzXSkuIFRoaXMgZGVjcmVhc2UgaXMgaGlnaGx5IHNpZ25pZmljYW50Cm9uIHRoZSA1JSBzaWduaWZpY2FuY2UgbGV2ZWwgKHA9MC4wMDEwMykuCgpBZ2Fpbiwgbm90ZSB0aGF0IGluIHRoaXMgZGF0YXNldCB0aGUgYXNzdW1wdGlvbiBvZiAqKmluZGVwZW5kZW5jZSoqCmlzIGFjdHVhbGx5ICoqbm90IG1ldCoqLiBJbiB0aGUgdHV0b3JpYWwgb2YgbXVsdGlwbGUgcmVncmVzc2lvbiwKd2Ugd2lsbCByZXZpc2l0IHRoaXMgZXhlcmNpc2UuIE1vcmUgc3BlY2lmaWNhbGx5LCB3ZSB3aWxsIHRoZXJlIHN0dWR5IAp0aGUgYXNzb2NpYXRpb24gYmV0d2VlbiBkb3NlIGFuZCBzdXJ2aXZhbCB3aGlsZSBhY2NvdW50aW5nIGZvcgpkaWZmZXJlbmNlcyBiZXR3ZWVuIHNwZWNpZXMgYW5kIGZpc2ggb2YgZGlmZmVyZW50IHdlaWdodC4KCi0tLQoKIyBbSG9tZV0oaHR0cHM6Ly9ndHBiLmdpdGh1Yi5pby9QU0xTMjAvKSB7LX0KCgoKCgoKCgoK