Creative Commons License

library(tidyverse)
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.1 ──
## ✔ ggplot2 3.3.5     ✔ purrr   0.3.4
## ✔ tibble  3.1.4     ✔ dplyr   1.0.7
## ✔ tidyr   1.1.4     ✔ stringr 1.4.0
## ✔ readr   2.0.2     ✔ forcats 0.5.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()

1 Power

The power of a test is defined as:

\[P(p < \alpha | H_1)\] This is the probability to reject the nulhypothesis at the significance level \(\alpha\) given that the alternative hypothesis is true.

The power depends on:

  • the real effect size in the population \(\mathbf{L}^T\boldsymbol{\beta}\).
  • the number of observations: SE and df.
  • Choice of designpoints
  • Choice of significance-level \(\alpha\).

We will evaluate the power using simulation.

2 Rodents

A biologist examined the effect of a fungal infection on the eating behavior of rodents. Infected apples were offered to a group of eight rodents, and sterile apples were offered to a group of 4 rodents. The amount of grams of apples consumed per kg body weight are given in the dataset below.

rodents <- data.frame(weight = c(11,33,48,34,112,369,64,44,177,80,141,332),
                      group = as.factor(c(rep("treat",8), rep("ctrl",4))))
rodents 

2.1 Data exploration

rodents %>% 
  ggplot(aes(x=group,y=weight)) +
  geom_boxplot(outlier.shape = NA) +
  geom_jitter()

rodents %>% 
  ggplot(aes(sample = weight)) +
  geom_qq() +
  geom_qq_line() +
  facet_wrap(~ group)

In the data exploration we do not have enough data to evaluate the assumptions.

Suppose that the assumptions are valid and that standard deviation in the population would be equal to the ones you observed in the experiment.

  1. What is the power of the experiment if the effect size and standard deviation in the population would be equal to the ones you observed in the experiment
  2. What would the power by if number of rodents would balanced in both groups
  3. How many observations would you need to pick up the treatment effect with a power of 90%?
  4. How many observations would you need to pick up the treatment effect of 60 g/kg with a power of 90%?

3 Analysis

We will model the data using a linear model with one dummy variable.

\[ y_i = \beta_0 + \beta_1 x_{t,i} + \epsilon_i \] with \(x_{p,i} = 0\) if the rodent is subjected the control treatment with sterile apples and \(x_{t,i} = 1\) if rodent receives the treatment with infected apples.

  • Estimated effect size?

The average difference in relative abundance of Staphylococcus of patients of the transplant and the placebo group.

\[ \hat \beta_1 = \bar y_t - \bar y_c \]

  • \(H_0\): rodents eat consume on average the same amount of apples per kg body weight when they are fed with sterile or with infected apples.
  • \(H_1\): the average amount of apples in g/kg body weight is different when rodents are fed with sterile then as when they are fed with infected apples.
lm1 <- lm(weight ~ group, rodents)
summary(lm1)
## 
## Call:
## lm(formula = weight ~ group, data = rodents)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -102.500  -55.625  -41.438    1.531  279.625 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)   
## (Intercept)   182.50      57.03   3.200  0.00949 **
## grouptreat    -93.12      69.85  -1.333  0.21204   
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 114.1 on 10 degrees of freedom
## Multiple R-squared:  0.1509, Adjusted R-squared:  0.06601 
## F-statistic: 1.777 on 1 and 10 DF,  p-value: 0.212

With the current study and when we assume that the assumptions of the model hold, we conclude that the amount of apples that rodents on average consume does not differ significantly between the group that was fed with sterile apples and the group that was fed with infected apples.

4 Power analyses

4.1 Question 1

What is the power of the experiment if the effect size and standard deviation in the population would be equal to the ones you observed in the experiment?

4.2 Simulation function

We provide you with a function to simulate data similar to that of our experiment under our model assumptions.

simFast <- function(form, data, betas, sd, contrasts, alpha = .05, nSim = 10000)
{
    ySim <- rnorm(nrow(data)*nSim,sd=sd)
    dim(ySim) <-c(nrow(data),nSim)
    design <- model.matrix(form, data)
    ySim <- ySim + c(design %*%betas)
    ySim <- t(ySim)
  
    ### Fitting
    fitAll <- limma::lmFit(ySim,design)
  
    ### Inference
    varUnscaled <- c(t(contrasts)%*%fitAll$cov.coefficients%*%contrasts)
    contrasts <- fitAll$coefficients %*%contrasts
    seContrasts <- varUnscaled^.5*fitAll$sigma
    tstats <- contrasts/seContrasts
    pvals <- pt(abs(tstats),fitAll$df.residual,lower.tail = FALSE)*2
    return(mean(pvals < alpha))
}

Without going into the full code details, this function allows us to simulate data similar to that of our experiment under our model assumptions, given the following inputs:

  • form: model formula for the experiment we want to simulate
  • data: the target dataset on which we want to base our simulations on
  • betas: the linear regression coefficients for the target dataset
  • sd: the residual standard errors from the linear regression model fit on the target dataset
  • contrasts: comparison of interest, i.e. which (combination of) model parameters we would like to assess
  • alpha: alpha-level at which to conduct the hypothesis testing
  • nSim: number of datasets we would like to simulate

To simulate new data based on our target dataset ç, we will need to fill in all the arguments to the simFast function.

Hint: for the betas and sd, we will need to fit a linear model first!

power1 <- simFast(form = ..., 
                  data = ..., 
                  betas = ..., 
                  sd = ..., 
                  contrasts = ..., 
                  alpha = ..., 
                  nSim = ...)
power1

Interpret the outcome.

4.3 Question 2

What would the power by if number of rodents would balanced in both groups? Again, we simulate a large number of new experiments. Adjust one more more of the inputs to the simFast to allow for addressing this question.

power2 <- simFast(form = ..., 
                  data = ..., 
                  betas = ..., 
                  sd = ..., 
                  contrasts = ..., 
                  alpha = ..., 
                  nSim = ...)
power2

4.4 Question 3

How many observations would you need to pick up the treatment effect with a power of 90%?

This will require us to establish a relationship between sample size and power. In turn, this will require us to perform a “parameter sweep” over different values of sample size and compute the power for each of them.

4.5 Question 4

Suppose that we would like to pick up an effect size of \(\beta_1 = 60 g/kg\). How many samples would be required in each group to obtain a power of 90%?

Note, that

  • we do a two-sided test so the sign of the effect size is arbitrary.
  • the intercept in the power analysis is also arbitrary so we could also set it at 0.
LS0tCnRpdGxlOiAiRXhwZXJpbWVudGFsIERlc2lnbiBJSTogcmVwbGljYXRpb24gYW5kIHBvd2VyIGV4ZXJjaXNlIDEiCmF1dGhvcjogIkxpZXZlbiBDbGVtZW50ICYgQWxleGFuZHJlIFNlZ2VycyIKZGF0ZTogInN0YXRPbWljcywgR2hlbnQgVW5pdmVyc2l0eSAoaHR0cHM6Ly9zdGF0b21pY3MuZ2l0aHViLmlvKSIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMKICAgIHRoZW1lOiBjb3NtbwogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDogeWVzCiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcwotLS0KCgo8YSByZWw9ImxpY2Vuc2UiIGhyZWY9Imh0dHBzOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy1zYS80LjAiPjxpbWcgYWx0PSJDcmVhdGl2ZSBDb21tb25zIExpY2Vuc2UiIHN0eWxlPSJib3JkZXItd2lkdGg6MCIgc3JjPSJodHRwczovL2kuY3JlYXRpdmVjb21tb25zLm9yZy9sL2J5LW5jLXNhLzQuMC84OHgzMS5wbmciIC8+PC9hPgoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpgYGAKCiMgUG93ZXIKClRoZSBwb3dlciBvZiBhIHRlc3QgaXMgZGVmaW5lZCBhczoKCiQkUChwIDwgClxhbHBoYSB8IEhfMSkkJApUaGlzIGlzIHRoZSBwcm9iYWJpbGl0eSB0byByZWplY3QgdGhlIG51bGh5cG90aGVzaXMgYXQgdGhlIHNpZ25pZmljYW5jZSBsZXZlbCAkXGFscGhhJCBnaXZlbiB0aGF0IHRoZSBhbHRlcm5hdGl2ZSBoeXBvdGhlc2lzIGlzIHRydWUuIAoKVGhlIHBvd2VyIGRlcGVuZHMgb246CgotIHRoZSByZWFsIGVmZmVjdCBzaXplIGluIHRoZSBwb3B1bGF0aW9uICRcbWF0aGJme0x9XlRcYm9sZHN5bWJvbHtcYmV0YX0kLgotIHRoZSBudW1iZXIgb2Ygb2JzZXJ2YXRpb25zOiBTRSBhbmQgZGYuCi0gQ2hvaWNlIG9mIGRlc2lnbnBvaW50cyAKLSBDaG9pY2Ugb2Ygc2lnbmlmaWNhbmNlLWxldmVsICRcYWxwaGEkLiAKCldlIHdpbGwgZXZhbHVhdGUgdGhlIHBvd2VyIHVzaW5nIHNpbXVsYXRpb24uCgojIFJvZGVudHMKCkEgYmlvbG9naXN0IGV4YW1pbmVkIHRoZSBlZmZlY3Qgb2YgYSBmdW5nYWwgaW5mZWN0aW9uIG9uIHRoZSBlYXRpbmcgYmVoYXZpb3Igb2Ygcm9kZW50cy4gCkluZmVjdGVkIGFwcGxlcyB3ZXJlIG9mZmVyZWQgdG8gYSBncm91cCBvZiBlaWdodCByb2RlbnRzLCBhbmQgc3RlcmlsZSBhcHBsZXMgd2VyZSBvZmZlcmVkIHRvIGEgZ3JvdXAgb2YgNCByb2RlbnRzLiBUaGUgYW1vdW50IG9mIGdyYW1zIG9mIGFwcGxlcyBjb25zdW1lZCBwZXIga2cgYm9keSB3ZWlnaHQgYXJlIGdpdmVuIGluIHRoZSBkYXRhc2V0IGJlbG93LiAKCmBgYHtyfQpyb2RlbnRzIDwtIGRhdGEuZnJhbWUod2VpZ2h0ID0gYygxMSwzMyw0OCwzNCwxMTIsMzY5LDY0LDQ0LDE3Nyw4MCwxNDEsMzMyKSwKICAgICAgICAgICAgICAgICAgICAgIGdyb3VwID0gYXMuZmFjdG9yKGMocmVwKCJ0cmVhdCIsOCksIHJlcCgiY3RybCIsNCkpKSkKcm9kZW50cyAKYGBgCgoKIyMgRGF0YSBleHBsb3JhdGlvbgoKYGBge3J9CnJvZGVudHMgJT4lIAogIGdncGxvdChhZXMoeD1ncm91cCx5PXdlaWdodCkpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZSA9IE5BKSArCiAgZ2VvbV9qaXR0ZXIoKQoKcm9kZW50cyAlPiUgCiAgZ2dwbG90KGFlcyhzYW1wbGUgPSB3ZWlnaHQpKSArCiAgZ2VvbV9xcSgpICsKICBnZW9tX3FxX2xpbmUoKSArCiAgZmFjZXRfd3JhcCh+IGdyb3VwKQpgYGAKCkluIHRoZSBkYXRhIGV4cGxvcmF0aW9uIHdlIGRvIG5vdCBoYXZlIGVub3VnaCBkYXRhIHRvIGV2YWx1YXRlIHRoZSBhc3N1bXB0aW9ucy4KClN1cHBvc2UgdGhhdCB0aGUgYXNzdW1wdGlvbnMgYXJlIHZhbGlkIGFuZCB0aGF0IHN0YW5kYXJkIGRldmlhdGlvbiBpbiB0aGUgcG9wdWxhdGlvbiB3b3VsZCBiZSBlcXVhbCB0byB0aGUgb25lcyB5b3Ugb2JzZXJ2ZWQgaW4gdGhlIGV4cGVyaW1lbnQuCgoxLiBXaGF0IGlzIHRoZSBwb3dlciBvZiB0aGUgZXhwZXJpbWVudCBpZiB0aGUgZWZmZWN0IHNpemUgYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBpbiB0aGUgcG9wdWxhdGlvbiB3b3VsZCBiZSBlcXVhbCB0byB0aGUgb25lcyB5b3Ugb2JzZXJ2ZWQgaW4gdGhlIGV4cGVyaW1lbnQKMi4gV2hhdCB3b3VsZCB0aGUgcG93ZXIgYnkgaWYgbnVtYmVyIG9mIHJvZGVudHMgd291bGQgIGJhbGFuY2VkIGluIGJvdGggZ3JvdXBzCjMuIEhvdyBtYW55IG9ic2VydmF0aW9ucyB3b3VsZCB5b3UgbmVlZCB0byBwaWNrIHVwIHRoZSB0cmVhdG1lbnQgZWZmZWN0IHdpdGggYSBwb3dlciBvZiA5MCU/CjQuIEhvdyBtYW55IG9ic2VydmF0aW9ucyB3b3VsZCB5b3UgbmVlZCB0byBwaWNrIHVwIHRoZSB0cmVhdG1lbnQgZWZmZWN0IG9mIDYwIGcva2cgd2l0aCBhIHBvd2VyIG9mIDkwJT8KCiMgQW5hbHlzaXMKCldlIHdpbGwgbW9kZWwgdGhlIGRhdGEgdXNpbmcgYSBsaW5lYXIgbW9kZWwgd2l0aCBvbmUgZHVtbXkgdmFyaWFibGUuIAoKJCQKeV9pID0gXGJldGFfMCArIFxiZXRhXzEgeF97dCxpfSArIApcZXBzaWxvbl9pCiQkCndpdGggJHhfe3AsaX0gPSAwJCBpZiB0aGUgcm9kZW50IGlzIHN1YmplY3RlZCB0aGUgY29udHJvbCB0cmVhdG1lbnQgd2l0aCBzdGVyaWxlIGFwcGxlcyBhbmQgJHhfe3QsaX0gPSAxJCBpZiByb2RlbnQgcmVjZWl2ZXMgdGhlIHRyZWF0bWVudCB3aXRoIGluZmVjdGVkIGFwcGxlcy4gCgotIEVzdGltYXRlZCBlZmZlY3Qgc2l6ZT8KClRoZSBhdmVyYWdlIGRpZmZlcmVuY2UgaW4gcmVsYXRpdmUgYWJ1bmRhbmNlIG9mIFN0YXBoeWxvY29jY3VzIG9mIHBhdGllbnRzIApvZiB0aGUgdHJhbnNwbGFudCBhbmQgdGhlIHBsYWNlYm8gZ3JvdXAuIAoKJCQKXGhhdCBcYmV0YV8xID0gXGJhciB5X3QgLSBcYmFyIHlfYwokJAoKLSAkSF8wJDogcm9kZW50cyBlYXQgY29uc3VtZSBvbiBhdmVyYWdlIHRoZSBzYW1lIGFtb3VudCBvZiBhcHBsZXMgcGVyIGtnIGJvZHkgd2VpZ2h0IHdoZW4gdGhleSBhcmUgZmVkIHdpdGggc3RlcmlsZSBvciB3aXRoIGluZmVjdGVkIGFwcGxlcy4gIAotICRIXzEkOiB0aGUgYXZlcmFnZSBhbW91bnQgb2YgYXBwbGVzIGluIGcva2cgYm9keSB3ZWlnaHQgaXMgZGlmZmVyZW50IHdoZW4gcm9kZW50cyBhcmUgZmVkIHdpdGggc3RlcmlsZSB0aGVuIGFzIHdoZW4gdGhleSBhcmUgZmVkIHdpdGggaW5mZWN0ZWQgYXBwbGVzLgoKYGBge3J9CmxtMSA8LSBsbSh3ZWlnaHQgfiBncm91cCwgcm9kZW50cykKc3VtbWFyeShsbTEpCmBgYAoKV2l0aCB0aGUgY3VycmVudCBzdHVkeSBhbmQgd2hlbiB3ZSBhc3N1bWUgdGhhdCB0aGUgYXNzdW1wdGlvbnMgb2YgdGhlIG1vZGVsIGhvbGQsIHdlIGNvbmNsdWRlIHRoYXQgdGhlIGFtb3VudCBvZiBhcHBsZXMgdGhhdCByb2RlbnRzIG9uIGF2ZXJhZ2UgY29uc3VtZSBkb2VzIG5vdCBkaWZmZXIgc2lnbmlmaWNhbnRseSBiZXR3ZWVuIHRoZSBncm91cCB0aGF0IHdhcyBmZWQgd2l0aCBzdGVyaWxlIGFwcGxlcyBhbmQgdGhlIGdyb3VwIHRoYXQgd2FzIGZlZCB3aXRoIGluZmVjdGVkIGFwcGxlcy4gCgojIFBvd2VyIGFuYWx5c2VzCgojIyBRdWVzdGlvbiAxCgpXaGF0IGlzIHRoZSBwb3dlciBvZiB0aGUgZXhwZXJpbWVudCBpZiB0aGUgZWZmZWN0IHNpemUgYW5kIHN0YW5kYXJkIGRldmlhdGlvbiAKaW4gdGhlIHBvcHVsYXRpb24gd291bGQgYmUgZXF1YWwgdG8gdGhlIG9uZXMgeW91IG9ic2VydmVkIGluIHRoZSBleHBlcmltZW50PwoKIyMgU2ltdWxhdGlvbiBmdW5jdGlvbgoKV2UgcHJvdmlkZSB5b3Ugd2l0aCBhIGZ1bmN0aW9uIHRvIHNpbXVsYXRlIGRhdGEgc2ltaWxhciB0byB0aGF0IG9mIG91ciAKZXhwZXJpbWVudCB1bmRlciBvdXIgbW9kZWwgYXNzdW1wdGlvbnMuIAoKYGBge3J9CnNpbUZhc3QgPC0gZnVuY3Rpb24oZm9ybSwgZGF0YSwgYmV0YXMsIHNkLCBjb250cmFzdHMsIGFscGhhID0gLjA1LCBuU2ltID0gMTAwMDApCnsKICAgIHlTaW0gPC0gcm5vcm0obnJvdyhkYXRhKSpuU2ltLHNkPXNkKQogICAgZGltKHlTaW0pIDwtYyhucm93KGRhdGEpLG5TaW0pCiAgICBkZXNpZ24gPC0gbW9kZWwubWF0cml4KGZvcm0sIGRhdGEpCiAgICB5U2ltIDwtIHlTaW0gKyBjKGRlc2lnbiAlKiViZXRhcykKICAgIHlTaW0gPC0gdCh5U2ltKQogIAogICAgIyMjIEZpdHRpbmcKICAgIGZpdEFsbCA8LSBsaW1tYTo6bG1GaXQoeVNpbSxkZXNpZ24pCiAgCiAgICAjIyMgSW5mZXJlbmNlCiAgICB2YXJVbnNjYWxlZCA8LSBjKHQoY29udHJhc3RzKSUqJWZpdEFsbCRjb3YuY29lZmZpY2llbnRzJSolY29udHJhc3RzKQogICAgY29udHJhc3RzIDwtIGZpdEFsbCRjb2VmZmljaWVudHMgJSolY29udHJhc3RzCiAgICBzZUNvbnRyYXN0cyA8LSB2YXJVbnNjYWxlZF4uNSpmaXRBbGwkc2lnbWEKICAgIHRzdGF0cyA8LSBjb250cmFzdHMvc2VDb250cmFzdHMKICAgIHB2YWxzIDwtIHB0KGFicyh0c3RhdHMpLGZpdEFsbCRkZi5yZXNpZHVhbCxsb3dlci50YWlsID0gRkFMU0UpKjIKICAgIHJldHVybihtZWFuKHB2YWxzIDwgYWxwaGEpKQp9CmBgYAoKV2l0aG91dCBnb2luZyBpbnRvIHRoZSBmdWxsIGNvZGUgZGV0YWlscywgdGhpcyBmdW5jdGlvbiBhbGxvd3MgdXMgdG8gc2ltdWxhdGUgCmRhdGEgc2ltaWxhciB0byB0aGF0IG9mIG91ciBleHBlcmltZW50IHVuZGVyIG91ciBtb2RlbCBhc3N1bXB0aW9ucywgZ2l2ZW4gdGhlIApmb2xsb3dpbmcgaW5wdXRzOgoKLSBgZm9ybWA6IG1vZGVsIGZvcm11bGEgZm9yIHRoZSBleHBlcmltZW50IHdlIHdhbnQgdG8gc2ltdWxhdGUKLSBgZGF0YWA6IHRoZSB0YXJnZXQgZGF0YXNldCBvbiB3aGljaCB3ZSB3YW50IHRvIGJhc2Ugb3VyIHNpbXVsYXRpb25zIG9uCi0gYGJldGFzYDogdGhlIGxpbmVhciByZWdyZXNzaW9uIGNvZWZmaWNpZW50cyBmb3IgdGhlIHRhcmdldCBkYXRhc2V0Ci0gYHNkYDogdGhlIHJlc2lkdWFsIHN0YW5kYXJkIGVycm9ycyBmcm9tIHRoZSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbCBmaXQgb24gCnRoZSB0YXJnZXQgZGF0YXNldAotIGBjb250cmFzdHNgOiBjb21wYXJpc29uIG9mIGludGVyZXN0LCBpLmUuIHdoaWNoIChjb21iaW5hdGlvbiBvZikgbW9kZWwgCnBhcmFtZXRlcnMgd2Ugd291bGQgbGlrZSB0byBhc3Nlc3MKLSBgYWxwaGFgOiBhbHBoYS1sZXZlbCBhdCB3aGljaCB0byBjb25kdWN0IHRoZSBoeXBvdGhlc2lzIHRlc3RpbmcKLSBgblNpbWA6IG51bWJlciBvZiBkYXRhc2V0cyB3ZSB3b3VsZCBsaWtlIHRvIHNpbXVsYXRlCgpUbyBzaW11bGF0ZSBuZXcgZGF0YSBiYXNlZCBvbiBvdXIgdGFyZ2V0IGRhdGFzZXQgYMOnYCwgd2Ugd2lsbCBuZWVkIHRvIApmaWxsIGluIGFsbCB0aGUgYXJndW1lbnRzIHRvIHRoZSBgc2ltRmFzdGAgZnVuY3Rpb24uCgoqKkhpbnQ6IGZvciB0aGUgYmV0YXMgYW5kIHNkLCB3ZSB3aWxsIG5lZWQgdG8gZml0IGEgbGluZWFyIG1vZGVsIGZpcnN0ISoqCgpgYGB7ciwgZXZhbD1GQUxTRX0KcG93ZXIxIDwtIHNpbUZhc3QoZm9ybSA9IC4uLiwgCiAgICAgICAgICAgICAgICAgIGRhdGEgPSAuLi4sIAogICAgICAgICAgICAgICAgICBiZXRhcyA9IC4uLiwgCiAgICAgICAgICAgICAgICAgIHNkID0gLi4uLCAKICAgICAgICAgICAgICAgICAgY29udHJhc3RzID0gLi4uLCAKICAgICAgICAgICAgICAgICAgYWxwaGEgPSAuLi4sIAogICAgICAgICAgICAgICAgICBuU2ltID0gLi4uKQpwb3dlcjEKYGBgCgpJbnRlcnByZXQgdGhlIG91dGNvbWUuCgojIyBRdWVzdGlvbiAyCgpXaGF0IHdvdWxkIHRoZSBwb3dlciBieSBpZiBudW1iZXIgb2Ygcm9kZW50cyB3b3VsZCAgYmFsYW5jZWQgaW4gYm90aCBncm91cHM/CkFnYWluLCB3ZSBzaW11bGF0ZSBhIGxhcmdlIG51bWJlciBvZiBuZXcgZXhwZXJpbWVudHMuIEFkanVzdCBvbmUgbW9yZSBtb3JlCm9mIHRoZSBpbnB1dHMgdG8gdGhlIGBzaW1GYXN0YCB0byBhbGxvdyBmb3IgYWRkcmVzc2luZyB0aGlzIHF1ZXN0aW9uLgoKYGBge3IsIGV2YWw9RkFMU0V9CnBvd2VyMiA8LSBzaW1GYXN0KGZvcm0gPSAuLi4sIAogICAgICAgICAgICAgICAgICBkYXRhID0gLi4uLCAKICAgICAgICAgICAgICAgICAgYmV0YXMgPSAuLi4sIAogICAgICAgICAgICAgICAgICBzZCA9IC4uLiwgCiAgICAgICAgICAgICAgICAgIGNvbnRyYXN0cyA9IC4uLiwgCiAgICAgICAgICAgICAgICAgIGFscGhhID0gLi4uLCAKICAgICAgICAgICAgICAgICAgblNpbSA9IC4uLikKcG93ZXIyCmBgYAoKIyMgUXVlc3Rpb24gMwoKSG93IG1hbnkgb2JzZXJ2YXRpb25zIHdvdWxkIHlvdSBuZWVkIHRvIHBpY2sgdXAgdGhlIHRyZWF0bWVudCBlZmZlY3Qgd2l0aCAKYSBwb3dlciBvZiA5MCU/CgpUaGlzIHdpbGwgcmVxdWlyZSB1cyB0byBlc3RhYmxpc2ggYSByZWxhdGlvbnNoaXAgYmV0d2VlbiBzYW1wbGUgc2l6ZSBhbmQgcG93ZXIuCkluIHR1cm4sIHRoaXMgd2lsbCByZXF1aXJlIHVzIHRvIHBlcmZvcm0gYSAicGFyYW1ldGVyIHN3ZWVwIiBvdmVyIGRpZmZlcmVudAp2YWx1ZXMgb2Ygc2FtcGxlIHNpemUgYW5kIGNvbXB1dGUgdGhlIHBvd2VyIGZvciBlYWNoIG9mIHRoZW0uCgpgYGB7cn0KCmBgYAoKIyMgUXVlc3Rpb24gNAoKU3VwcG9zZSB0aGF0IHdlIHdvdWxkIGxpa2UgdG8gcGljayB1cCBhbiBlZmZlY3Qgc2l6ZSBvZiAkXGJldGFfMSA9IDYwIGcva2ckLiAKSG93IG1hbnkgc2FtcGxlcyB3b3VsZCBiZSByZXF1aXJlZCBpbiBlYWNoIGdyb3VwIHRvIG9idGFpbiBhIHBvd2VyIG9mIDkwJT8KCk5vdGUsIHRoYXQgCgotIHdlIGRvIGEgdHdvLXNpZGVkIHRlc3Qgc28gdGhlIHNpZ24gb2YgdGhlIGVmZmVjdCBzaXplIGlzIGFyYml0cmFyeS4gCi0gdGhlIGludGVyY2VwdCBpbiB0aGUgcG93ZXIgYW5hbHlzaXMgaXMgYWxzbyBhcmJpdHJhcnkgc28gd2UgY291bGQgYWxzbyBzZXQgaXQgYXQgMC4gCgpgYGB7cn0KCmBgYAoK