As an exercise on linear regression, we will analyse the FEV dataset.

1 The FEV dataset

The FEV, which is an acronym for forced expiratory volume, is a measure of how much air a person can exhale (in liters) during a forced breath. In this dataset, the FEV of 606 children, between the ages of 6 and 17, were measured. The dataset also provides additional information on these children: their age, their height, their gender and, most importantly, whether the child is a smoker or a non-smoker.

The goal of this experiment was to find out whether or not smoking has an effect on the FEV of children.

Note: to analyse this dataset properly, we will need some relatively advanced modeling techniques. At the end of this week, you will have seen all three required steps to analyse such a dataset! For now, we will limit ourselves to exploring the data.

Load the required libraries

library(tidyverse)

2 Import data

fev <- read_tsv("https://raw.githubusercontent.com/GTPB/PSLS20/master/data/fev.txt")
## Parsed with column specification:
## cols(
##   age = col_double(),
##   fev = col_double(),
##   height = col_double(),
##   gender = col_character(),
##   smoking = col_double()
## )
head(fev)
## # A tibble: 6 x 5
##     age   fev height gender smoking
##   <dbl> <dbl>  <dbl> <chr>    <dbl>
## 1     9  1.71   57   f            0
## 2     8  1.72   67.5 f            0
## 3     7  1.72   54.5 f            0
## 4     9  1.56   53   m            0
## 5     9  1.90   57   m            0
## 6     8  2.34   61   f            0

There are a few things in the formatting of the data that can be improved upon:

  1. Both the gender and smoking can be transformed to factors.
  2. The height variable is written in inches. Assuming that this audience is mainly Portuguese/Belgian, inches are hard to interpret. Let’s add a new column, height_cm, with the values converted to centimeter using the mutate function.
fev <- fev %>%
  mutate(gender = as.factor(gender)) %>%
  mutate(smoking = as.factor(smoking)) %>%
  mutate(height_cm = height*2.54)

head(fev)
## # A tibble: 6 x 6
##     age   fev height gender smoking height_cm
##   <dbl> <dbl>  <dbl> <fct>  <fct>       <dbl>
## 1     9  1.71   57   f      0            145.
## 2     8  1.72   67.5 f      0            171.
## 3     7  1.72   54.5 f      0            138.
## 4     9  1.56   53   m      0            135.
## 5     9  1.90   57   m      0            145.
## 6     8  2.34   61   f      0            155.

3 Data Exploration

Now, let’s make a first explorative boxplot, showing only the FEV for both smoking categories.

fev %>%
  ggplot(aes(x=smoking,y=fev,fill=smoking)) +
  scale_fill_manual(values=c("dimgrey","firebrick")) +
  theme_bw() +
  geom_boxplot(outlier.shape=NA) + 
  geom_jitter(width = 0.2, size=0.1) +
  ggtitle("Boxplot of FEV versus smoking") +
  ylab("fev (l)") +
  xlab("smoking status")

Did you expect these results?

It appears that children that smoke have a higher median FEV than children that do not smoke. Should we change legislations worldwide and make smoking obligatory for children?

Maybe there is something else going on in the data. Now, we will generate a similar plot, but we will stratify the data based on age (age as factor).

fev %>%
  ggplot(aes(x=as.factor(age),y=fev,fill=smoking)) +
  geom_boxplot(outlier.shape=NA) +
  geom_point(width = 0.2, size = 0.1, position = position_jitterdodge()) +
  theme_bw() +
  scale_fill_manual(values=c("dimgrey","firebrick")) +
  ggtitle("Boxplot of FEV versus smoking, stratified on age") +
  ylab("fev (l)") +
  xlab("smoking status")
## Warning: Ignoring unknown parameters: width

This plot seems to already give us a more plausible picture. First, it seems that we do not have any smoking children of ages 6, 7 or 8. Second, when looking at the results per age “category”, it seems no longer the case that smokers have a much higher FEV than non-smokers; for the higher ages, the contrary seems true.

This shows that taking into account confounders (in this case) is crucial! If we simply analyse the dataset based on the smoking status and FEV values only, our inference might be incorrect.

Can we provide an even better visualization of the data, taking into account more useful explanatory variables with respect to the FEV?

fev %>%
  ggplot(aes(x=as.factor(age),y=fev,fill=smoking)) +
  geom_boxplot(outlier.shape=NA) +
  geom_point(width = 0.2, size = 0.1, position = position_jitterdodge()) +
  theme_bw() +
  scale_fill_manual(values=c("dimgrey","firebrick")) +
  ggtitle("Boxplot of FEV versus smoking, stratified on age and gender") +
  ylab("fev (l)") +
  xlab("smoking status") + 
  facet_grid(rows = vars(gender))
## Warning: Ignoring unknown parameters: width

This plot holds one extra level of information, the gender of the child. Especially for higher ages, the median FEV is higher for males as compared to females.

The only source of information that is lacking is height. To look at the effect of height, we could simply make a scatterplot displaying the FEV in function of a child’s height (in cm). Additionally, we could color the dots based on gender.

fev %>%
  ggplot(aes(x=height_cm,y=fev,color=gender)) +
  geom_point() +
  scale_color_manual(values=c("darkorchid","olivedrab4")) +
  theme_bw() +
  ggtitle("Boxplot of FEV versus height") +
  ylab("fev (l)") +
  xlab("height (cm)")

There is a clear relationship between height and FEV. In addition, we see that for the large height values (>175cm), we mainly find male subjects.

4 Analysis

4.1 Assumptions of linear regression

List the 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

4.1.1 Independence

The first assumption is not met. There are patterns of relatedness in the data. Indeed, we expect that fish of the same species 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.

model <- lm(fev~smoking, data=fev) 

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

We have four diagnostic plots:

4.1.2 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. Based on the first diagnostic plot, the linearity assumption is met.

4.1.3 Normal Q-Q

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

The residuals of the linear regression model should be normally distributed. Based on the second diagnostic plot, the normality assumption is not met.

4.1.4 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 is clearly not the case here; based on the third diagnostic plot, the homosccedasticity assumption is met.

4.2 Log transformation

The normality assumption was not met, so we cannot continue with performing a linear regression analysis.

One possibility 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.

fev <- fev %>%
  mutate(log.fev = log(fev))

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

log.model <- lm(log.fev~smoking,data=fev)
plot(log.model)

Upon log-transformation, all the required assumption (except the one for independence, see above) are met.

Look at the output of the log-linear model:

summary(log.model)
## 
## Call:
## lm(formula = log.fev ~ smoking, data = fev)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -0.7701 -0.1958  0.0048  0.1953  0.8338 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  0.92286    0.01270  72.649  < 2e-16 ***
## smoking1     0.22591    0.04004   5.642 2.58e-08 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.2966 on 604 degrees of freedom
## Multiple R-squared:  0.05007,    Adjusted R-squared:  0.0485 
## F-statistic: 31.84 on 1 and 604 DF,  p-value: 2.582e-08

Compute the 95% confidence interval on the model parameters:

confint(log.model)
##                 2.5 %    97.5 %
## (Intercept) 0.8979164 0.9478117
## smoking1    0.1472777 0.3045423

5 Conclusion

5.1 Interpretation on the log scale

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

We may interpret the output as follows:

  • The slope:

If the smoking status changes from 0 (non-smoking) to 1 (smoking), the natural logarithm of FEV will increase, on average, by 0.22591 units (95% CI [0.1472777,0.3045423]). This increase is significant on the 5% significance level (p=2.58e-08).

  • The intercept:

The average natural logarithm of FEV for children that have smoking status 0 is 0.92286 (95% CI [0.1472777; 0.3045423]). This value is significantly different from 0 on the 5% significance level (< 2e-16).

5.2 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)    smoking1 
##    2.516487    1.253463

and of their confidence intervals:

exp(confint(log.model))
##                2.5 %   97.5 %
## (Intercept) 2.454484 2.580058
## smoking1    1.158676 1.356004

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

  • The slope:

If the smoking status changes from 0 (non-smoking) to 1 (smoking), the geometric mean of the FEV will increase, on average, by 1.253463 liters (95% CI [1.158676; 1.356004]). This increase is significant on the 5% significance level (p=2.58e-08).

  • The intercept:

The geometric mean of the FEV for children that have smoking status 0 is 2.516487 liters (95% CI [2.454484; 2.580058]). This value is significantly different from 0 on the 5% significance level (< 2e-16).

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 smoking and FEV while accounting for differences in the age, height and gender of the children.


LS0tCnRpdGxlOiAiVHV0b3JpYWwgNi4zOiBMaW5lYXIgcmVncmVzc2lvbiBvbiB0aGUgRkVWIGRhdGFzZXQiICAgCm91dHB1dDoKICAgIGh0bWxfZG9jdW1lbnQ6CiAgICAgIGNvZGVfZG93bmxvYWQ6IHRydWUgICAgCiAgICAgIHRoZW1lOiBjb3NtbwogICAgICB0b2M6IHRydWUKICAgICAgdG9jX2Zsb2F0OiB0cnVlCiAgICAgIGhpZ2hsaWdodDogdGFuZ28KICAgICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCi0tLQoKQXMgYW4gZXhlcmNpc2Ugb24gbGluZWFyIHJlZ3Jlc3Npb24sIHdlIHdpbGwgYW5hbHlzZSB0aGUgRkVWIGRhdGFzZXQuCgojIFRoZSBGRVYgZGF0YXNldAoKVGhlIEZFViwgd2hpY2ggaXMgYW4gYWNyb255bSBmb3IgZm9yY2VkIGV4cGlyYXRvcnkgdm9sdW1lLAppcyBhIG1lYXN1cmUgb2YgaG93IG11Y2ggYWlyIGEgcGVyc29uIGNhbiBleGhhbGUgKGluIGxpdGVycykgCmR1cmluZyAgYSBmb3JjZWQgYnJlYXRoLiBJbiB0aGlzIGRhdGFzZXQsIHRoZSBGRVYgb2YgNjA2IGNoaWxkcmVuLApiZXR3ZWVuIHRoZSBhZ2VzIG9mIDYgYW5kIDE3LCB3ZXJlIG1lYXN1cmVkLiBUaGUgZGF0YXNldAphbHNvIHByb3ZpZGVzIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gb24gdGhlc2UgY2hpbGRyZW46CnRoZWlyIGBhZ2VgLCB0aGVpciBgaGVpZ2h0YCwgdGhlaXIgYGdlbmRlcmAgYW5kLCBtb3N0CmltcG9ydGFudGx5LCB3aGV0aGVyIHRoZSBjaGlsZCBpcyBhIHNtb2tlciBvciBhIG5vbi1zbW9rZXIuCgpUaGUgZ29hbCBvZiB0aGlzIGV4cGVyaW1lbnQgd2FzIHRvIGZpbmQgb3V0IHdoZXRoZXIgb3Igbm90CnNtb2tpbmcgaGFzIGFuIGVmZmVjdCBvbiB0aGUgRkVWIG9mIGNoaWxkcmVuLgoKTm90ZTogdG8gYW5hbHlzZSB0aGlzIGRhdGFzZXQgcHJvcGVybHksIHdlIHdpbGwgbmVlZCBzb21lCnJlbGF0aXZlbHkgYWR2YW5jZWQgbW9kZWxpbmcgdGVjaG5pcXVlcy4gQXQgdGhlIGVuZCBvZiB0aGlzIAp3ZWVrLCB5b3Ugd2lsbCBoYXZlIHNlZW4gYWxsIHRocmVlIHJlcXVpcmVkIHN0ZXBzIHRvIGFuYWx5c2UKc3VjaCBhIGRhdGFzZXQhIEZvciBub3csIHdlIHdpbGwgbGltaXQgb3Vyc2VsdmVzIHRvIGV4cGxvcmluZwp0aGUgZGF0YS4KCkxvYWQgdGhlIHJlcXVpcmVkIGxpYnJhcmllcwoKYGBge3IsIG1lc3NhZ2UgPSBGQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmBgYAoKIyBJbXBvcnQgZGF0YQoKYGBge3J9CmZldiA8LSByZWFkX3RzdigiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL0dUUEIvUFNMUzIwL21hc3Rlci9kYXRhL2Zldi50eHQiKQpoZWFkKGZldikKYGBgCgpUaGVyZSBhcmUgYSBmZXcgdGhpbmdzIGluIHRoZSBmb3JtYXR0aW5nIG9mIHRoZQpkYXRhIHRoYXQgY2FuIGJlIGltcHJvdmVkIHVwb246CgoxLiBCb3RoIHRoZSBgZ2VuZGVyYCBhbmQgYHNtb2tpbmdgIGNhbiBiZSB0cmFuc2Zvcm1lZCB0bwpmYWN0b3JzLgoyLiBUaGUgYGhlaWdodGAgdmFyaWFibGUgaXMgd3JpdHRlbiBpbiBpbmNoZXMuIEFzc3VtaW5nIHRoYXQKdGhpcyBhdWRpZW5jZSBpcyBtYWlubHkgUG9ydHVndWVzZS9CZWxnaWFuLCBpbmNoZXMgYXJlIGhhcmQgdG8KaW50ZXJwcmV0LiBMZXQncyBhZGQgYSBuZXcgY29sdW1uLCBgaGVpZ2h0X2NtYCwgd2l0aCB0aGUgdmFsdWVzCmNvbnZlcnRlZCB0byBjZW50aW1ldGVyIHVzaW5nIHRoZSBgbXV0YXRlYCBmdW5jdGlvbi4gCgpgYGB7cn0KZmV2IDwtIGZldiAlPiUKICBtdXRhdGUoZ2VuZGVyID0gYXMuZmFjdG9yKGdlbmRlcikpICU+JQogIG11dGF0ZShzbW9raW5nID0gYXMuZmFjdG9yKHNtb2tpbmcpKSAlPiUKICBtdXRhdGUoaGVpZ2h0X2NtID0gaGVpZ2h0KjIuNTQpCgpoZWFkKGZldikKYGBgCgoKIyBEYXRhIEV4cGxvcmF0aW9uCgpOb3csIGxldCdzIG1ha2UgYSBmaXJzdCBleHBsb3JhdGl2ZSBib3hwbG90LCBzaG93aW5nCm9ubHkgdGhlIEZFViBmb3IgYm90aCBzbW9raW5nIGNhdGVnb3JpZXMuCgpgYGB7cn0KZmV2ICU+JQogIGdncGxvdChhZXMoeD1zbW9raW5nLHk9ZmV2LGZpbGw9c21va2luZykpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YygiZGltZ3JleSIsImZpcmVicmljayIpKSArCiAgdGhlbWVfYncoKSArCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuc2hhcGU9TkEpICsgCiAgZ2VvbV9qaXR0ZXIod2lkdGggPSAwLjIsIHNpemU9MC4xKSArCiAgZ2d0aXRsZSgiQm94cGxvdCBvZiBGRVYgdmVyc3VzIHNtb2tpbmciKSArCiAgeWxhYigiZmV2IChsKSIpICsKICB4bGFiKCJzbW9raW5nIHN0YXR1cyIpCmBgYAoKRGlkIHlvdSBleHBlY3QgdGhlc2UgcmVzdWx0cz8KCkl0IGFwcGVhcnMgdGhhdCBjaGlsZHJlbiB0aGF0IHNtb2tlIGhhdmUgYSBoaWdoZXIKbWVkaWFuIEZFViB0aGFuIGNoaWxkcmVuIHRoYXQgZG8gbm90IHNtb2tlLiAKU2hvdWxkIHdlIGNoYW5nZSBsZWdpc2xhdGlvbnMgd29ybGR3aWRlIGFuZCBtYWtlIApzbW9raW5nIG9ibGlnYXRvcnkgZm9yIGNoaWxkcmVuPwoKTWF5YmUgdGhlcmUgaXMgc29tZXRoaW5nIGVsc2UgZ29pbmcgb24gaW4gdGhlIGRhdGEuCk5vdywgd2Ugd2lsbCBnZW5lcmF0ZSBhIHNpbWlsYXIgcGxvdCwgYnV0IHdlIHdpbGwKc3RyYXRpZnkgdGhlIGRhdGEgYmFzZWQgb24gYWdlIChhZ2UgYXMgZmFjdG9yKS4KCmBgYHtyfQpmZXYgJT4lCiAgZ2dwbG90KGFlcyh4PWFzLmZhY3RvcihhZ2UpLHk9ZmV2LGZpbGw9c21va2luZykpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZT1OQSkgKwogIGdlb21fcG9pbnQod2lkdGggPSAwLjIsIHNpemUgPSAwLjEsIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyZG9kZ2UoKSkgKwogIHRoZW1lX2J3KCkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCJkaW1ncmV5IiwiZmlyZWJyaWNrIikpICsKICBnZ3RpdGxlKCJCb3hwbG90IG9mIEZFViB2ZXJzdXMgc21va2luZywgc3RyYXRpZmllZCBvbiBhZ2UiKSArCiAgeWxhYigiZmV2IChsKSIpICsKICB4bGFiKCJzbW9raW5nIHN0YXR1cyIpCmBgYAoKVGhpcyBwbG90IHNlZW1zIHRvIGFscmVhZHkgZ2l2ZSB1cyBhIG1vcmUKcGxhdXNpYmxlIHBpY3R1cmUuIEZpcnN0LCBpdCBzZWVtcyB0aGF0IHdlIGRvIG5vdCBoYXZlCmFueSBzbW9raW5nIGNoaWxkcmVuIG9mIGFnZXMgNiwgNyBvciA4LiBTZWNvbmQsIHdoZW4KbG9va2luZyBhdCB0aGUgcmVzdWx0cyBwZXIgYWdlICJjYXRlZ29yeSIsIGl0IHNlZW1zCm5vIGxvbmdlciB0aGUgY2FzZSB0aGF0IHNtb2tlcnMgaGF2ZSBhIG11Y2ggaGlnaGVyIEZFVgp0aGFuIG5vbi1zbW9rZXJzOyBmb3IgdGhlIGhpZ2hlciBhZ2VzLCB0aGUgY29udHJhcnkKc2VlbXMgdHJ1ZS4KClRoaXMgc2hvd3MgdGhhdCB0YWtpbmcgaW50byBhY2NvdW50IGNvbmZvdW5kZXJzCihpbiB0aGlzIGNhc2UpIGlzIGNydWNpYWwhIElmIHdlIHNpbXBseSBhbmFseXNlIHRoZSBkYXRhc2V0IGJhc2VkIG9uCnRoZSBzbW9raW5nIHN0YXR1cyBhbmQgRkVWIHZhbHVlcyBvbmx5LCBvdXIgaW5mZXJlbmNlIG1pZ2h0CmJlIGluY29ycmVjdC4KCkNhbiB3ZSBwcm92aWRlIGFuIGV2ZW4gYmV0dGVyIHZpc3VhbGl6YXRpb24gb2YgdGhlIGRhdGEsIHRha2luZwppbnRvIGFjY291bnQgbW9yZSB1c2VmdWwgZXhwbGFuYXRvcnkgdmFyaWFibGVzIHdpdGggcmVzcGVjdAp0byB0aGUgRkVWPwoKYGBge3J9CmZldiAlPiUKICBnZ3Bsb3QoYWVzKHg9YXMuZmFjdG9yKGFnZSkseT1mZXYsZmlsbD1zbW9raW5nKSkgKwogIGdlb21fYm94cGxvdChvdXRsaWVyLnNoYXBlPU5BKSArCiAgZ2VvbV9wb2ludCh3aWR0aCA9IDAuMiwgc2l6ZSA9IDAuMSwgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXJkb2RnZSgpKSArCiAgdGhlbWVfYncoKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoImRpbWdyZXkiLCJmaXJlYnJpY2siKSkgKwogIGdndGl0bGUoIkJveHBsb3Qgb2YgRkVWIHZlcnN1cyBzbW9raW5nLCBzdHJhdGlmaWVkIG9uIGFnZSBhbmQgZ2VuZGVyIikgKwogIHlsYWIoImZldiAobCkiKSArCiAgeGxhYigic21va2luZyBzdGF0dXMiKSArIAogIGZhY2V0X2dyaWQocm93cyA9IHZhcnMoZ2VuZGVyKSkKYGBgCgpUaGlzIHBsb3QgaG9sZHMgb25lIGV4dHJhIGxldmVsIG9mIGluZm9ybWF0aW9uLCB0aGUgZ2VuZGVyIApvZiB0aGUgY2hpbGQuIEVzcGVjaWFsbHkgZm9yIGhpZ2hlciBhZ2VzLCB0aGUgbWVkaWFuIEZFVgppcyBoaWdoZXIgZm9yIG1hbGVzIGFzIGNvbXBhcmVkIHRvIGZlbWFsZXMuCgpUaGUgb25seSBzb3VyY2Ugb2YgaW5mb3JtYXRpb24gdGhhdCBpcyBsYWNraW5nIGlzIGBoZWlnaHRgLgpUbyBsb29rIGF0IHRoZSBlZmZlY3Qgb2YgaGVpZ2h0LCB3ZSBjb3VsZCBzaW1wbHkgbWFrZSBhCnNjYXR0ZXJwbG90IGRpc3BsYXlpbmcgdGhlIEZFViBpbiBmdW5jdGlvbiBvZiBhIGNoaWxkJ3MKaGVpZ2h0IChpbiBjbSkuIEFkZGl0aW9uYWxseSwgd2UgY291bGQgY29sb3IgdGhlIGRvdHMgYmFzZWQKb24gZ2VuZGVyLgoKYGBge3J9CmZldiAlPiUKICBnZ3Bsb3QoYWVzKHg9aGVpZ2h0X2NtLHk9ZmV2LGNvbG9yPWdlbmRlcikpICsKICBnZW9tX3BvaW50KCkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygiZGFya29yY2hpZCIsIm9saXZlZHJhYjQiKSkgKwogIHRoZW1lX2J3KCkgKwogIGdndGl0bGUoIkJveHBsb3Qgb2YgRkVWIHZlcnN1cyBoZWlnaHQiKSArCiAgeWxhYigiZmV2IChsKSIpICsKICB4bGFiKCJoZWlnaHQgKGNtKSIpCmBgYAoKVGhlcmUgaXMgYSBjbGVhciByZWxhdGlvbnNoaXAgYmV0d2VlbiBoZWlnaHQgYW5kIEZFVi4KSW4gYWRkaXRpb24sIHdlIHNlZSB0aGF0IGZvciB0aGUgbGFyZ2UgaGVpZ2h0IHZhbHVlcwooPjE3NWNtKSwgd2UgbWFpbmx5IGZpbmQgbWFsZSBzdWJqZWN0cy4KCiMgQW5hbHlzaXMKCiMjIEFzc3VtcHRpb25zIG9mIGxpbmVhciByZWdyZXNzaW9uCgpMaXN0IHRoZSBhc3N1bXB0aW9uczoKCjEuIFRoZSBvYnNlcnZhdGlvbnMgYXJlIGluZGVwZW5kZW50IG9mIGVhY2ggb3RoZXIKMi4gTGluZWFyaXR5IGJldHdlZW4gdGhlIHJlc3BvbnNlIGFuZCBwcmVkaWN0b3IgdmFyaWFibGUKMy4gVGhlIHJlc2lkdWVzIG9mIHRoZSBtb2RlbCBtdXN0IGJlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkCjQuIEhvbW9zY2VkYXN0aWNpdHkgb2YgdGhlIGRhdGEKCiMjIyBJbmRlcGVuZGVuY2UKClRoZSBmaXJzdCBhc3N1bXB0aW9uIGlzICoqbm90IG1ldCoqLiBUaGVyZSBhcmUgcGF0dGVybnMKb2YgcmVsYXRlZG5lc3MgaW4gdGhlIGRhdGEuIEluZGVlZCwgd2UgZXhwZWN0IHRoYXQKZmlzaCBvZiB0aGUgc2FtZSBzcGVjaWVzIGhhdmUgYSBtb3JlIHNpbWlsYXIgcmVzcG9uc2UgdG8KdGhlIHBvaXNvbiBhcyBjb21wYXJlZCB0byBmaXNoIG9mIGFub3RoZXIgc3BlY2llcy4KRXF1aXZhbGVudGx5LCB3ZSBleHBlY3QgdGhhdCBmaXNoIG9mIHRoZSBzYW1lIHdlaWdodCBoYXZlIAphIG1vcmUgc2ltaWxhciByZXNwb25zZSB0byB0aGUgcG9pc29uIGFzIGNvbXBhcmVkIHRvIGZpc2ggCm9mIGRpZmZlcmVudCB3ZWlnaHQuIAoKKipGb3Igbm93LCB3ZSB3aWxsIGlnbm9yZSB0aGlzIHByb2JsZW0qKi4gSW4gYSBsYXRlciAKdHV0b3JpYWwsIHdlIHdpbGwgc2VlIGhvdyB3ZSBjYW4gYWNjb3VudCBmb3IgdGhpcyBkZXBlbmRlbmNlCmJ5IGluY2x1ZGluZyB0aGUgc3BlY2llcyBkYXRhIGFuZCB3ZWlndGggZGF0YSBpbiB0aGUgbGluZWFyIG1vZGVsCihjbGFzcyBvbiBtdWx0aXBsZSByZWdyZXNzaW9uKS4gQXMgc3VjaCwgKip5b3UgbWF5IGFzc3VtZSoqCioqdGhlIGFzc3VtcHRpb24gaXMgbWV0LioqCgpXZSB3aWxsIGNoZWNrIHRoZSBvdGhlciBhc3N1bXB0aW9ucyBieSBmaXJzdCBmaXR0aW5nIHRoZSBsaW5lYXIKbW9kZWwgYW5kIHBsb3R0aW5nIHRoZSBvdXRwdXQuIEFzIHN1Y2gsIHdlIHdpbGwgZ2V0IGFsbCB0aGUKcmVxdWlyZWQgZGlhZ25vc3RpYyBwbG90cy4KCmBgYHtyfQptb2RlbCA8LSBsbShmZXZ+c21va2luZywgZGF0YT1mZXYpIAoKIyMgZGlzcGxheSB0aGUgZGlhZ25vc3RpYyBwbG90cyBvZiB0aGUgbW9kZWwKcGxvdChtb2RlbCkKYGBgCgpXZSBoYXZlIGZvdXIgZGlhZ25vc3RpYyBwbG90czoKCiMjIyBMaW5lYXJpdHkgd2l0aCB0aGUgUmVzaWR1YWxzIHZzIGZpdHRlZCBwbG90CgotIHByZWRpY3RvciBvZiBwcmVkaWN0aW9ucyAkXGhhdFxiZXRhXzArXGhhdFxiZXRhXzEgeCQgb24gJFgkLWF4aXMKLSAqcmVzaWR1YWxzKiBvbiAkWSQtYXMKJCRlX2k9eV9pLVxoYXR7Z30oeF9pKT15X2ktXGhhdFxiZXRhXzAtXGhhdFxiZXRhXzFcdGltZXMgeF9pLCQkCgpJZiB0aGVyZSB3b3VsZCBiZSBhIGxpbmVhciByZWxhdGlvbnNoaXAgaW4gdGhlIGRhdGEsCnRoZSByZXNpZHVhbHMgYXJlIGV4cGVjdGVkIHRvIGxpZSBvbiB0aGUgeT0wIGxpbmUgZm9yCnRoZSBlbnRpcmUgcmFuZ2Ugb2YgcHJlZGljdGVkIHZhbHVlcy4gQmFzZWQgb24gdGhlIGZpcnN0CmRpYWdub3N0aWMgcGxvdCwgdGhlIGxpbmVhcml0eSBhc3N1bXB0aW9uIGlzIG1ldC4KCiMjIyBOb3JtYWwgUS1RCgotIFFRLXBsb3Qgb2YgdGhlIHJlc2lkdWFscyAkZV9pJC4KClRoZSByZXNpZHVhbHMgb2YgdGhlIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsIHNob3VsZCBiZSBub3JtYWxseQpkaXN0cmlidXRlZC4gQmFzZWQgb24gdGhlIHNlY29uZCBkaWFnbm9zdGljIHBsb3QsIHRoZSBub3JtYWxpdHkKYXNzdW1wdGlvbiBpcyBub3QgbWV0LgoKIyMjIEhvbW9zY2VkYXN0aWNpdHkKCi0gU3F1YXJlLXJvb3Qgb2YgdGhlIGFic29sdXRlIHZhbHVlIG9mIHN0YW5kYXJkaXplZCByZXNpZHVhbHMKaW4gZnVuY3Rpb24gb2YgdGhlIGZpdHRlZCB2YWx1ZXMKClRvIG1lZXQgdGhlIHRoaXJkIGFzc3VtcHRpb24gb2YgbGluZWFyIHJlZ3Jlc3Npb24sIHRoZSB2YXJpYW5jZQpvbiB0aGUgX1NxdWFyZS1yb290IG9mIHRoZSBhYnNvbHV0ZSB2YWx1ZSBvZiBzdGFuZGFyZGl6ZWQgcmVzaWR1YWxzXwptdXN0IGJlIHNpbWlsYXIgb3ZlciB0aGUgZW50aXJlIHJhbmdlIG9mIGZpdHRlZCB2YWx1ZXMuIFRoZSBzbW9vdGhlcgppbiB0aGUgcGxvdCBoZWxwcyB1cyB3aXRoIGxvb2tpbmcgYXQgdGhpczsgaXQgc2hvdWxkIGJlIG5pY2VseQpob3Jpem9udGFsIG92ZXIgdGhlIGVudGlyZSByYW5nZSBvZiBmaXR0ZWQgdmFsdWVzLiBUaGlzIGlzIGNsZWFybHkKbm90IHRoZSBjYXNlIGhlcmU7IGJhc2VkIG9uIHRoZSB0aGlyZCBkaWFnbm9zdGljIHBsb3QsIHRoZSBob21vc2NjZWRhc3RpY2l0eQphc3N1bXB0aW9uIGlzIG1ldC4KCiMjIExvZyB0cmFuc2Zvcm1hdGlvbgoKVGhlIG5vcm1hbGl0eSBhc3N1bXB0aW9uIHdhcyBub3QgbWV0LCBzbyB3ZSBjYW5ub3QgY29udGludWUgd2l0aCAKcGVyZm9ybWluZyBhIGxpbmVhciByZWdyZXNzaW9uIGFuYWx5c2lzLgoKT25lIHBvc3NpYmlsaXR5IGlzIHRvIGxvZy10cmFuc2Zvcm0gdGhlIGRhdGEuIEluZGVlZCwgZGF0YSB3aXRoIGhlYXZ5CnJpZ2h0IHRhaWxzIGNhbiBvZnRlbiBiZSBub3JtYWxpemVkIGJ5IGFwcGx5aW5nIHRoaXMgc3RyYXRlZ3kKCkdlbmVyYXRlIGEgbmV3IGNvbHVtbiBpbiB0aGUgcG9pc29uIGRhdGFzZXQsIGNvbnRhaW5pbmcgdGhlIApsb2ctdHJhbnNmb3JtZWQgc3Vydml2YWwgdGltZXMuCgpgYGB7cn0KZmV2IDwtIGZldiAlPiUKICBtdXRhdGUobG9nLmZldiA9IGxvZyhmZXYpKQpgYGAKClJlZml0IHRoZSAobG9nLSlsaW5lYXIgbW9kZWwuIEdlbmVyYXRlIGRpYWdub3N0aWMgcGxvdHMuCkFzc2VzcyB0aGUgYXNzdW1wdGlvbnMuCgpgYGB7cn0KbG9nLm1vZGVsIDwtIGxtKGxvZy5mZXZ+c21va2luZyxkYXRhPWZldikKcGxvdChsb2cubW9kZWwpCmBgYAoKVXBvbiBsb2ctdHJhbnNmb3JtYXRpb24sIGFsbCB0aGUgcmVxdWlyZWQgYXNzdW1wdGlvbiAoZXhjZXB0IHRoZSBvbmUgCmZvciBpbmRlcGVuZGVuY2UsIHNlZSBhYm92ZSkgYXJlIG1ldC4KCkxvb2sgYXQgdGhlIG91dHB1dCBvZiB0aGUgbG9nLWxpbmVhciBtb2RlbDoKCmBgYHtyfQpzdW1tYXJ5KGxvZy5tb2RlbCkKYGBgCgpDb21wdXRlIHRoZSA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbCBvbiB0aGUgbW9kZWwgcGFyYW1ldGVyczoKCmBgYHtyfQpjb25maW50KGxvZy5tb2RlbCkKYGBgCgojIENvbmNsdXNpb24KCiMjIEludGVycHJldGF0aW9uIG9uIHRoZSBsb2cgc2NhbGUgCgpDdXJyZW50bHksIGFsbCB0aGUgb3V0Y29tZXMgc2hvdWxkIGJlIGludGVycHJldGVkIG9uIHRoZSBsb2ctc2NhbGUuCkluZGVlZCwgc2luY2Ugd2UgYXJlIG5vdyBtb2RlbGxpbmcgIF90aGUgbG9nIEZFVl8sIHdlIGRvbid0IGhhdmUgZGlyZWN0IAppbmZlcmVuY2Ugb24gdGhlIEZFViBhcyBzdWNoCgpXZSBtYXkgaW50ZXJwcmV0IHRoZSBvdXRwdXQgYXMgZm9sbG93czoKCi0gVGhlIHNsb3BlOgoKSWYgdGhlIHNtb2tpbmcgc3RhdHVzIGNoYW5nZXMgZnJvbSAwIChub24tc21va2luZykgdG8gMSAoc21va2luZyksCnRoZSBuYXR1cmFsIGxvZ2FyaXRobSBvZiBGRVYgd2lsbCBpbmNyZWFzZSwgb24gYXZlcmFnZSwKYnkgMC4yMjU5MSB1bml0cyAoOTUlIENJIFswLjE0NzI3NzcsMC4zMDQ1NDIzXSkuIFRoaXMgaW5jcmVhc2UgaXMgc2lnbmlmaWNhbnQKb24gdGhlIDUlIHNpZ25pZmljYW5jZSBsZXZlbCAocD0yLjU4ZS0wOCkuCgotIFRoZSBpbnRlcmNlcHQ6CgpUaGUgYXZlcmFnZSBuYXR1cmFsIGxvZ2FyaXRobSBvZiBGRVYgZm9yIGNoaWxkcmVuIHRoYXQKaGF2ZSBzbW9raW5nIHN0YXR1cyAwIGlzIDAuOTIyODYgKDk1JSBDSSBbMC4xNDcyNzc3OyAwLjMwNDU0MjNdKS4gVGhpcwp2YWx1ZSBpcyBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBmcm9tIDAgb24gdGhlIDUlIHNpZ25pZmljYW5jZSBsZXZlbAooPCAyZS0xNikuCgojIyBJbnRlcnByZXRhdGlvbiBvbiB0aGUgb3JpZ2luYWwgc2NhbGUgCgpUaGUgaW50ZXJwcmV0YXRpb24gdGhlIGxvZy1zY2FsZSBpcyBxdWl0ZSBkaWZmaWN1bHQ6IHRoZSBuYXR1cmFsIApsb2dhcml0aG0gc3Vydml2YWwgdGltZSBpcyBub3QgZXhhY3RseSBhIGNhc3VhbCBtZWFzdXJlLiBUbyBlYXNlIAp0aGUgaW50ZXJwZXRhdGlvbiwgd2UgbWF5IGJhY2t0cmFuc2Zvcm0gdGhlIHJlc3VsdHMgdG8gdGhlIG9yaWdpbmFsCnNjYWxlICh0aW1lIGluIG1pbnV0ZXMpLiBUaGlzIHdlIGNhbiBkbyBieSB0YWtpbmcgdGhlIGV4cG9uZW50IG9mCnRoZSBvdXRjb21lczoKCmBgYHtyfQpleHAoc3VtbWFyeShsb2cubW9kZWwpJGNvZWZmaWNpZW50c1ssIkVzdGltYXRlIl0pCmBgYAoKYW5kIG9mIHRoZWlyIGNvbmZpZGVuY2UgaW50ZXJ2YWxzOgoKYGBge3J9CmV4cChjb25maW50KGxvZy5tb2RlbCkpCmBgYAoKTm93LCB3ZSBjYW4gaW50ZXJwcmV0IHRoZSByZXN1bHRzIGluIHRlcm1zIG9mIHRoZSBnZW9tZXRyaWMgbWVhbjoKCi0gVGhlIHNsb3BlOgoKSWYgdGhlIHNtb2tpbmcgc3RhdHVzIGNoYW5nZXMgZnJvbSAwIChub24tc21va2luZykgdG8gMSAoc21va2luZyksCnRoZSBnZW9tZXRyaWMgbWVhbiBvZiB0aGUgRkVWIHdpbGwgaW5jcmVhc2UsIG9uIGF2ZXJhZ2UsCmJ5IDEuMjUzNDYzIGxpdGVycyAoOTUlIENJIFsxLjE1ODY3NjsgMS4zNTYwMDRdKS4gVGhpcyBpbmNyZWFzZSBpcyAKc2lnbmlmaWNhbnQgb24gdGhlIDUlIHNpZ25pZmljYW5jZSBsZXZlbCAocD0yLjU4ZS0wOCkuCgotIFRoZSBpbnRlcmNlcHQ6CgpUaGUgZ2VvbWV0cmljIG1lYW4gb2YgdGhlIEZFViBmb3IgY2hpbGRyZW4gdGhhdCBoYXZlIHNtb2tpbmcgc3RhdHVzIDAgCmlzIDIuNTE2NDg3IGxpdGVycyAoOTUlIENJIFsyLjQ1NDQ4NDsgMi41ODAwNThdKS4gClRoaXMgdmFsdWUgaXMgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgZnJvbSAwIG9uIHRoZSA1JSBzaWduaWZpY2FuY2UgbGV2ZWwKKDwgMmUtMTYpLgoKQWdhaW4sIG5vdGUgdGhhdCBpbiB0aGlzIGRhdGFzZXQgdGhlIGFzc3VtcHRpb24gb2YgKippbmRlcGVuZGVuY2UqKgppcyBhY3R1YWxseSAqKm5vdCBtZXQqKi4gSW4gdGhlIHR1dG9yaWFsIG9mIG11bHRpcGxlIHJlZ3Jlc3Npb24sCndlIHdpbGwgcmV2aXNpdCB0aGlzIGV4ZXJjaXNlLiBNb3JlIHNwZWNpZmljYWxseSwgd2Ugd2lsbCB0aGVyZSBzdHVkeSAKdGhlIGFzc29jaWF0aW9uIGJldHdlZW4gc21va2luZyBhbmQgRkVWIHdoaWxlIGFjY291bnRpbmcgZm9yCmRpZmZlcmVuY2VzIGluIHRoZSBhZ2UsIGhlaWdodCBhbmQgZ2VuZGVyIG9mIHRoZSBjaGlsZHJlbi4KCi0tLQoKIyBbSG9tZV0oaHR0cHM6Ly9ndHBiLmdpdGh1Yi5pby9QU0xTMjAvKSB7LX0KCgoKCgoKCgo=