Creative Commons License

1 ANOVA: Kuikentjes

In deze studie (1948) werd de invloed van verschillende soorten voeding op het gewicht van kuikentjes onderzocht. De kuikentjes werden na geboorte willekeurig in één van zes groepen toegekend, waarna deze groepen elk een andere voeding kregen. Het gewicht van deze kuikentjes werd gemeten na zes weken. Wij zullen ons beperken tot drie groepen van voeding: caseïne (casein), lijnzaad (linseed) en sojabonen (soybean).

suppressPackageStartupMessages({
library(tidyverse)
library(ggplot2)})

2 Data exploratie

data("chickwts")

2.1 Datastructuur bekijken

#Bekijk de structuur van dataset chickwts
head(chickwts)

2.2 Data filteren

We gaan de analyse beperken tot het vergelijken van voeding caseïne (casein), lijnzaad (linseed) en sojabonen (soybean).

#Filter de dataset zodat enkel datapunten van de relevante voeding (feed) aanwezig zijn.
chickwts <- chickwts %>% filter(feed %in% c("casein","linseed","soybean"))

2.3 Figuur van de data

We gaan eerst de data bekijken zodat we een idee hebben waarmee we te maken hebben.

#Maak een boxplot van het gewicht voor elke groep van voeding. Plot ook de individuele observaties.
chickwts %>% ggplot(aes(x=feed,y=weight)) + 
  geom_boxplot() +
  geom_jitter() +
  ggtitle("Gewicht van kuikentjes na zes weken per soort voeding")

3 Statische test:

3.2 Geef de assumpties voor dit model en ga deze na:

Zoals beschreven in de cursus, veronderstelt ANOVA een locatie-shift. Dit wil zeggen dat elke groep een gelijke variantie heeft en er enkel shifts in gemiddelde kunnen optreden. Een andere assumptie is dat de data van elke groep normaal verdeeld is, en dat de observaties onafhankelijk van elkaar zijn.

Er zijn dus drie assumpties die moeten voldaan zijn. Aangezien we in de data niet kunnen waarnemen of de observaties onafhankelijk zijn van elkaar, moeten we dit veronderstellen dat de onderzoeker dit correct heeft uitgevoerd. Daarnaast moeten we controleren dat:

  • elke groep normaal is.

  • de groepen een gelijke variantie hebben. (homoscedasticiteit)

We gaan gelijkheid van varianties na met boxplots. Dit lijkt alvast in orde te zijn.

We zullen nu de assumptie van normale verdeling binnen elke groep nagaan.

#Maak een QQplot voor het gewicht per voedingssoort.
chickwts %>%
  ggplot(aes(sample = weight)) +
  geom_qq() +
  geom_qq_line() +
  facet_grid(.~feed) +
  ylab("Relatieve abundantie")

De afwijkingen die we in onze qqplot zien lijken niet zeer uitzonderlijk. Daarom kunnen we stellen dat elke groep een normale verdeling lijkt te volgen.

Indien men veel groepen moet vergelijken, kan het makkelijker zijn om slechts één plot te moeten beoordelen. In dat geval kan men ervoor kiezen om niet voor elke groep apart een QQ-plot te maken, maar kan men de residuen van het lineair model checken. Merk op dat men dan checkt voor een normale distributie van alle residuen van het gewicht ten opzichte van hun groepsgemiddelde, en dus niet voor een normale distributie binnen elke groep apart.

model_lm <- lm(weight ~ feed, data = chickwts)
par(mfrow=c(2,2))
plot(model_lm) # Enkel figuur rechts boven is relevant

par(mfrow=c(1,1))

De QQ-plot vertoont geen systematische afwijkingen van een normale distributie. Dit is geen garantie dat de data normaal verdeeld is binnen elke groep, maar het is een benadering die we kunnen gebruiken in het geval dat:

  • er te veel groepen zijn om de assumpties te checken binnen elke groep;
  • er te weinig observaties zijn per groep om binnen elke groep de assumpties na te gaan.

Merk op dat je in principe de assumptie van gelijke varianties ook op basis van de plot linksboven zou kunnen checken: elke ‘kolom’ van punten stelt een soort voor (1 soort heeft 1 geschat gemiddelde) en de punten stellen de residuen voor ten opzichte van hun groepsgemiddelde. Men kan deze plot dus ook gebruiken om te kijken of er groepen (soorten) zijn die een verschillende variantie hebben ten opzichte van andere groepen.

3.3 Modelleer de data met het lineair model:

summary(model_lm)
## 
## Call:
## lm(formula = weight ~ feed, data = chickwts)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -107.583  -45.717    2.571   40.500   90.250 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   323.58      16.46  19.660  < 2e-16 ***
## feedlinseed  -104.83      23.28  -4.504 7.11e-05 ***
## feedsoybean   -77.15      22.43  -3.440  0.00152 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 57.01 on 35 degrees of freedom
## Multiple R-squared:  0.3854, Adjusted R-squared:  0.3503 
## F-statistic: 10.97 on 2 and 35 DF,  p-value: 0.0001996

De p-waarden die we hier krijgen voor de parameters komen niet overeen met de ANOVA-test die we willen uitvoeren. De p-waarde bij de F-statistic is wel de juiste p-waarde. We kunnen dit ook verkrijgen door de volgende code:

#Voer de ANOVA uit op het lineare model.
anova(model_lm)

We voerden de ANOVA test uit aan de hand van het lineair regressiemodel. In principe testen we dan volgende nulhypothese:

\[ H_0: \beta_1 = \beta_2 = 0 \]

Merk op dat deze nulhypothese evenwaardig is aan de nulhypothese die we eerder formuleerden. Als alle gemiddelden \(\mu_1, \mu_2, \mu_3 = 0\), betekent dit dat beide regressieparameters \(\beta_1\) en \(\beta_1\) gelijk zijn aan 0.

De p-waarde van deze ANOVA test is bijzonder klein. We besluiten dat we de nulhypothese kunnen verwerpen (\(p<<0.001\)) en dat het gemiddelde gewicht van kuikens verschilt tussen minstens twee van de voedingspatronen op het 5% significantieniveau.

Aan de hand van dit resultaat weten we echter niet tussen welke voedingen er een verschil optreedt, en hiervoor zullen we een post-hoc analyse moeten uitvoeren. Een post-hoc analyse voert men enkel uit indien de ANOVA test significant was, en bestaat erin om paarsgewijze vergelijkingen uit te voeren tussen de groepen. In dit geval komt dit overeen met het vergelijken of er een verschil is tussen groep 1 en 2, tussen groep 1 en 3 en tussen groep 2 en 3.

3.4 Post-hoc analyse

De post-hoc analyse bestaat eruit om paarsgewijze testen uit te voeren. Indien men over \(k\) groepen beschikt is het totaal aantal paarsgewijze vergelijkingen gelijk aan \(k(k-1)/2\). Bij ons is \(k=3\) waardoor we \(3\) paarsgewijze vergelijkingen zullen uitvoeren. We kunnen echter niet elke test op het 5% significantieniveau uitvoeren vanwege het meervoudig toetsen probleem. Indien we 3 vergelijkingen zouden testen elk op het 5% significantieniveau, dan is de kans dat we minstens één nulhypothese onterecht zouden verwerpen niet langer gelijk aan ons significantieniveau (5%). In ons geval, zou deze kans gelijk zijn aan:

alpha <- 0.05
nComparisons <- 3
1-(1-alpha)^nComparisons
## [1] 0.142625

Dus indien we elke test op het 5% significantieniveau zouden uitvoeren hebben we, als alle nulhypotheses waar zouden zijn, een kans van 14.3% dat we minstens één nulhypothese verkeerd zouden verwerpen. Om deze kans globaal gezien (dit is, over alle paarsgewijze vergelijkingen) op 5% te houden, kunnen we bijvoorbeeld de Bonferroni correctie uitvoeren.

In R kunnen we de post-hoc analyse uitvoeren met behulp van het multcomp package aan de hand van de glht functie. We specifiëren hier in het linfct argument dat we multiple comparisons (mcp) willen uitvoeren waarbij we alle paarsgewijze vergelijkingen voor de feed variabele willen testen aan de hand van de "Tukey" methode. De multcomp package zorgt ervoor dat deze p-waarden automatisch gecorrigeerd worden voor meervoudig toetsen.

suppressPackageStartupMessages(library(multcomp))
mcp <- glht(model_lm,linfct=mcp(feed="Tukey"))
summary <- summary(mcp)
summary
## 
##   Simultaneous Tests for General Linear Hypotheses
## 
## Multiple Comparisons of Means: Tukey Contrasts
## 
## 
## Fit: lm(formula = weight ~ feed, data = chickwts)
## 
## Linear Hypotheses:
##                        Estimate Std. Error t value Pr(>|t|)    
## linseed - casein == 0   -104.83      23.28  -4.504   <0.001 ***
## soybean - casein == 0    -77.15      22.43  -3.440   0.0042 ** 
## soybean - linseed == 0    27.68      22.43   1.234   0.4414    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## (Adjusted p values reported -- single-step method)

In de output hiervan zien we de verschillende paarsgewijze vergelijkingen die werden uitvoerd. Bijvoorbeeld linseed - casein == 0 duidt erop dat voor dit contrast wordt getest of het gemiddelde gewicht voor voeding linseed min het gemiddelde gewicht voor soort casein verschillend is van nul. In de tweede kolom wordt het verschil in gemiddelden weergegeven, met hun standaard error en teststatistiek in de respectievelijk derde en vierde kolom. De laatste kolom geeft aangepaste p-waarden weer op een globaal significantieniveau van 5%. Aan de hand van de aangepaste p-waarden zien we dat het gemiddelde gewicht bij casein verschilt van zowel linseed en soybean (p < 0.001 en p = 0.004) op het 5% significantieniveau. We zien ook dat er geen significant verschil is in gemiddeld gewicht bij voeding soybean en linseed op het 5% significantieniveau. De effectgrootte is voor bij zowel linseed als soybean negatief, wat erop duidt dat het gemiddelde gewicht van kuikens hoger is bij voedingspatroon casein.

De betrouwbaarheidsintervallen van elke paarsgewijze test kunnen we ook makkelijk grafisch voorstellen aan de hand van de plot functie die zo op een glht object kan toegepast worden.

confint(mcp)
## 
##   Simultaneous Confidence Intervals
## 
## Multiple Comparisons of Means: Tukey Contrasts
## 
## 
## Fit: lm(formula = weight ~ feed, data = chickwts)
## 
## Quantile = 2.4475
## 95% family-wise confidence level
##  
## 
## Linear Hypotheses:
##                        Estimate  lwr       upr      
## linseed - casein == 0  -104.8333 -161.8019  -47.8648
## soybean - casein == 0   -77.1548 -132.0511  -22.2585
## soybean - linseed == 0   27.6786  -27.2177   82.5749
plot(mcp)

4 Conclusie

We kunnen concluderen dat er een significant verschil in gewicht is tussen het gewicht van kuikentjes met voeding caseine tegenover de andere voedingen op het 5% significantieniveau. Tussen linseed en soybean is er geen significant verschil in gewicht van de kuikentjes.

LS0tCnRpdGxlOiAiUHJhY3RpY3VtIDE6IE9lZmVuaW5nIGFub3ZhIgphdXRob3I6ICJBbGV4YW5kcmUgU2VnZXJzICYgTGlldmVuIENsZW1lbnQiCmRhdGU6ICJzdGF0T21pY3MsIEdoZW50IFVuaXZlcnNpdHkgKGh0dHBzOi8vc3RhdG9taWNzLmdpdGh1Yi5pbykiCm91dHB1dDoKICAgIGh0bWxfZG9jdW1lbnQ6CiAgICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgICAgdGhlbWU6IGNvc21vCiAgICAgIHRvYzogdHJ1ZQogICAgICB0b2NfZmxvYXQ6IHRydWUKICAgICAgaGlnaGxpZ2h0OiB0YW5nbwogICAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHBkZl9kb2N1bWVudDoKICAgICAgdG9jOiB0cnVlCiAgICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgICBsYXRleF9lbmdpbmU6IHhlbGF0ZXgKbGlua2NvbG9yOiBibHVlCnVybGNvbG9yOiBibHVlCmNpdGVjb2xvcjogYmx1ZQoKLS0tCgo8YSByZWw9ImxpY2Vuc2UiIGhyZWY9Imh0dHBzOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy1zYS80LjAiPjxpbWcgYWx0PSJDcmVhdGl2ZSBDb21tb25zIExpY2Vuc2UiIHN0eWxlPSJib3JkZXItd2lkdGg6MCIgc3JjPSJodHRwczovL2kuY3JlYXRpdmVjb21tb25zLm9yZy9sL2J5LW5jLXNhLzQuMC84OHgzMS5wbmciIC8+PC9hPgoKCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpgYGAKCiMgQU5PVkE6IEt1aWtlbnRqZXMKCkluIGRlemUgc3R1ZGllICgxOTQ4KSB3ZXJkIGRlIGludmxvZWQgdmFuIHZlcnNjaGlsbGVuZGUgc29vcnRlbiB2b2VkaW5nIG9wIGhldCBnZXdpY2h0IHZhbiBrdWlrZW50amVzIG9uZGVyem9jaHQuIERlIGt1aWtlbnRqZXMgd2VyZGVuIG5hIGdlYm9vcnRlIHdpbGxla2V1cmlnIGluIMOpw6luIHZhbiB6ZXMgZ3JvZXBlbiB0b2VnZWtlbmQsIHdhYXJuYSBkZXplIGdyb2VwZW4gZWxrIGVlbiBhbmRlcmUgdm9lZGluZyBrcmVnZW4uIEhldCBnZXdpY2h0IHZhbiBkZXplIGt1aWtlbnRqZXMgd2VyZCBnZW1ldGVuIG5hIHplcyB3ZWtlbi4gV2lqIHp1bGxlbiBvbnMgYmVwZXJrZW4gdG90IGRyaWUgZ3JvZXBlbiB2YW4gdm9lZGluZzogY2FzZcOvbmUgKGNhc2VpbiksIGxpam56YWFkIChsaW5zZWVkKSBlbiBzb2phYm9uZW4gKHNveWJlYW4pLgoKCgpgYGB7cn0Kc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKHsKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZ2dwbG90Mil9KQpgYGAKCiMgRGF0YSBleHBsb3JhdGllCmBgYHtyfQpkYXRhKCJjaGlja3d0cyIpCmBgYAoKIyMgRGF0YXN0cnVjdHV1ciBiZWtpamtlbgoKYGBge3J9CiNCZWtpamsgZGUgc3RydWN0dXVyIHZhbiBkYXRhc2V0IGNoaWNrd3RzCmhlYWQoY2hpY2t3dHMpCmBgYAoKIyMgRGF0YSBmaWx0ZXJlbgoKV2UgZ2FhbiBkZSBhbmFseXNlIGJlcGVya2VuIHRvdCBoZXQgdmVyZ2VsaWprZW4gdmFuIHZvZWRpbmcgY2FzZcOvbmUgKGNhc2VpbiksIGxpam56YWFkIChsaW5zZWVkKSBlbiBzb2phYm9uZW4gKHNveWJlYW4pLiAKCmBgYHtyfQojRmlsdGVyIGRlIGRhdGFzZXQgem9kYXQgZW5rZWwgZGF0YXB1bnRlbiB2YW4gZGUgcmVsZXZhbnRlIHZvZWRpbmcgKGZlZWQpIGFhbndlemlnIHppam4uCmNoaWNrd3RzIDwtIGNoaWNrd3RzICU+JSBmaWx0ZXIoZmVlZCAlaW4lIGMoImNhc2VpbiIsImxpbnNlZWQiLCJzb3liZWFuIikpCmBgYAoKIyMgRmlndXVyIHZhbiBkZSBkYXRhCgpXZSBnYWFuIGVlcnN0IGRlIGRhdGEgYmVraWprZW4gem9kYXQgd2UgZWVuIGlkZWUgaGViYmVuIHdhYXJtZWUgd2UgdGUgbWFrZW4gaGViYmVuLgoKYGBge3J9CiNNYWFrIGVlbiBib3hwbG90IHZhbiBoZXQgZ2V3aWNodCB2b29yIGVsa2UgZ3JvZXAgdmFuIHZvZWRpbmcuIFBsb3Qgb29rIGRlIGluZGl2aWR1ZWxlIG9ic2VydmF0aWVzLgpjaGlja3d0cyAlPiUgZ2dwbG90KGFlcyh4PWZlZWQseT13ZWlnaHQpKSArIAogIGdlb21fYm94cGxvdCgpICsKICBnZW9tX2ppdHRlcigpICsKICBnZ3RpdGxlKCJHZXdpY2h0IHZhbiBrdWlrZW50amVzIG5hIHplcyB3ZWtlbiBwZXIgc29vcnQgdm9lZGluZyIpCmBgYAoKCiMgU3RhdGlzY2hlIHRlc3Q6CgojIyBXZWxrZSB0ZXN0IGthbiBtZW4gdWl0dm9lcmVuIG9tIGhldCBnZW1pZGRlbGRlIGdld2ljaHQgc2ltdWx0YWFuIHRlIHZlcmdlbGlqa2VuIHR1c3NlbiBhbGxlIHNvb3J0ZW4gdm9lZGluZz8gV2F0IGlzIGRlIGxpbmsgbWV0IGhldCBsaW5lYWlyIG1vZGVsPyBHZWVmIGRlIG51bC0gZW4gYWx0ZXJuYXRpZXZlIGh5cG90aGVzZSB2YW4gZGV6ZSB0ZXN0LgoKSW4gdm9yaWdlIG9lZmVuaW5nIHphZ2VuIHdlIGVua2VsIGRlIHR3by1zYW1wbGUgdC10ZXN0IG9tIHR3ZWUgZ2VtaWRkZWxkZW4gbWV0IGVsa2FhciB2ZXJnZWxpamtlbi4KV2UgaGViYmVuIGVjaHRlciBvb2sgcmVlZHMgZ2V6aWVuIGRhdCBkZSB0d28tc2FtcGxlIHQtdGVzdCBlZW4gc3BlY2lmaWVrZSB2ZXJzaWUgaXMgdmFuIGVlbiBsaW5lYWlyIG1vZGVsLCBuYW1lbGlqayB2YW4gZWVuIGxpbmVhaXIgbW9kZWwgd2FhcmJpaiBkZSBjb3ZhcmlhYXQgZWVuIGNhdGVnb3Jpc2NoZSB2YXJpYWJlbGUgJFgkIGlzIG1ldCAkMiQgbGV2ZWxzLCBpLmUuClxbIEVbWV9pXSA9IFxiZXRhXzAgKyBcYmV0YV8xIFhfaSBcXQoKRGl0IGxpbmVhaXIgbW9kZWwga2FuIGVjaHRlciBvb2sgbWFra2VsaWprIHZlcmFsZ2VtZWVuZCB3b3JkZW4gbmFhciBmYWN0b3JlbiBtZXQgbWVlcmRlcmUgbGV2ZWxzLiAKClxbIEVbWV9pXSA9IFxiZXRhXzAgKyBcYmV0YV8xIFhfezFpfSArIFxiZXRhXzIgWF97Mml9IFxdCgpXYWFyYmlqICRYX3sxaX0kIGdlbGlqayBpcyBhYW4gMSB3YW5uZWVyIGRlIHZvZWRpbmcgbGluc2VlZCBpcyBlbiBhbmRlcnMgMC4gQW5kZXJ6aWpkcyBpcyAkWF97Mml9JCBnZWxpamsgYWFuIDEgYmlqIHNveWJlYW5zIGVuIGdlbGlqayBhYW4gMCBiaWogZGUgYW5kZXJlIHZvZWRpbmdlbi4gCgpFciBiZXN0YWF0IGVlbiBtYW5pZXIgd2FhcmJpaiB3ZSAqKmFsbGUgbGV2ZWxzIHNpbXVsdGFhbiBrdW5uZW4gdGVzdGVuKiosIG1lbiB6YWwgbmFtZWxpamsgdGVzdGVuIG9mIGRlIGdlaGVsZSBjYXRlZ29yaXNjaGUgdmFyaWFiZWxlIGVlbiBpbnZsb2VkIGhlZWZ0IG9wIGRlIHJlc3BvbnMgdmFyaWFiZWxlLgpJbiBkZSBjb250ZXh0IHZhbiBvbnMgdm9vcmJlZWxkLCB6YWwgbWVuIGt1bm5lbiB0ZXN0ZW4gb2YgZGUgdm9lZGluZy1zb29ydCDDvGJlcmhhdXB0IGVlbiBlZmZlY3QgaGVlZnQgb3AgaGV0IGdlbWlkZGVsZGUgZ2V3aWNodCB2YW4ga3Vpa2VudGplcy4KWm8nbiBlZW4gdGVzdCBoZWV0IGVlbiBvbmUtd2F5IEFOT1ZBLgoKU3RlbCBkYXQgJFxtdV8xJCBoZXQgZ2VtaWRkZWxkZSBnZXdpY2h0IHZhbiBrdWlrZW5zIHZvb3IgY2FzZcOvbmUgdm9vcnN0ZWx0LCBlbiBpZGVtIHZvb3IgJFxtdV8yJCBlbiAkXG11XzMkLgpEZSBudWwtIGVuIGFsdGVybmF0aWV2ZSBoeXBvdGhlc2Ugdm9vciBlZW4gQU5PVkEga2FuIG1lbiBkYW4gdm9vcnN0ZWxsZW4gYWxzCgokSF8wJDogJFxtdV8xPVxtdV8yPVxtdV8zJAoKJEhfQSQ6IFZvb3IgbWluc3RlbnMgw6nDqW4gJGkgXG5lIGokIGlzICRcbXVfaSBcbmVxIFxtdV9qJDogbWV0IGFuZGVyZSB3b29yZGVuICRcbXVfMSBcbmUgXG11XzIkIG9mICRcbXVfMSBcbmUgXG11XzMkIG9mICRcbXVfMiBcbmUgXG11XzMkCgpJbiB3b29yZGVuLCB6ZWd0IGRlIG51bGh5cG90aGVzZSBkYXQgaGV0IGdlbWlkZGVsZGUgZ2V3aWNodCB2YW4ga3Vpa2VucyBvbmFmaGFua2VsaWprIGlzIHZhbiBkZSB2b2VkaW5nOiBlciBpcyBnZWVuIHN5c3RlbWF0aXNjaCB2ZXJzY2hpbCBpbiBnZW1pZGRlbGQgZ2V3aWNodCB2YW4gaGV0IGt1aWtlbi4KRGUgYWx0ZXJuYXRpZXZlIGh5cG90aGVzZSB6ZWd0IGRhdCBoZXQgZ2VtaWRkZWxkZSBnZXdpY2h0IHZlcnNjaGlsdCB0dXNzZW4gKiptaW5zdGVucyB0d2VlIHZvZWRpbmctc29vcnRlbioqLiBNZXJrIG9wIGRhdCBtZW4gYmlqIGhldCB2ZXJ3ZXJwZW4gdmFuIGRlIG51bGh5cG90aGVzZSAqKm5pZXQgd2VldCB0dXNzZW4gd2Vsa2Ugc29vcnRlbioqIGVyIGVlbiB2ZXJzY2hpbCBpcyEKCkluZGllbiB3ZSBkZSBBTk9WQSB0ZXN0ZW4gb3AgYmFzaXMgdmFuIGhldCBsaW5lYWlyIG1vZGVsIGt1bm5lbiB3ZSBvb2sgZGUgdm9sZ2VuZGUgbnVsLSBlbiBhbHRlcm5hdGlldmUgaHlwb3RoZXNlIG9wc3RlbGxlbjoKCiRIXzAkOiAkXGJldGFfMSA9IFxiZXRhXzIgPSAwJAogCiRIX0EkOiAkXGJldGFfMSBcbmUgMCQgb2YgJFxiZXRhXzIgXG5lIDAkCgojIyBHZWVmIGRlIGFzc3VtcHRpZXMgdm9vciBkaXQgbW9kZWwgZW4gZ2EgZGV6ZSBuYToKClpvYWxzIGJlc2NocmV2ZW4gaW4gZGUgY3Vyc3VzLCB2ZXJvbmRlcnN0ZWx0IEFOT1ZBIGVlbiBsb2NhdGllLXNoaWZ0LgpEaXQgd2lsIHplZ2dlbiBkYXQgZWxrZSBncm9lcCBlZW4gZ2VsaWprZSB2YXJpYW50aWUgaGVlZnQgZW4gZXIgZW5rZWwgc2hpZnRzIGluIGdlbWlkZGVsZGUga3VubmVuIG9wdHJlZGVuLiBFZW4gYW5kZXJlIGFzc3VtcHRpZSBpcyBkYXQgZGUgZGF0YSB2YW4gZWxrZSBncm9lcCBub3JtYWFsIHZlcmRlZWxkIGlzLCBlbiBkYXQgZGUgb2JzZXJ2YXRpZXMgb25hZmhhbmtlbGlqayB2YW4gZWxrYWFyIHppam4uIAoKRXIgemlqbiBkdXMgZHJpZSBhc3N1bXB0aWVzIGRpZSBtb2V0ZW4gdm9sZGFhbiB6aWpuLiBBYW5nZXppZW4gd2UgaW4gZGUgZGF0YSBuaWV0IGt1bm5lbiB3YWFybmVtZW4gb2YgZGUgb2JzZXJ2YXRpZXMgb25hZmhhbmtlbGlqayB6aWpuIHZhbiBlbGthYXIsIG1vZXRlbiB3ZSBkaXQgdmVyb25kZXJzdGVsbGVuIGRhdCBkZSBvbmRlcnpvZWtlciBkaXQgY29ycmVjdCBoZWVmdCB1aXRnZXZvZXJkLiBEYWFybmFhc3QgbW9ldGVuIHdlIGNvbnRyb2xlcmVuIGRhdDoKCiAtIGVsa2UgZ3JvZXAgbm9ybWFhbCBpcy4KIAogLSBkZSBncm9lcGVuIGVlbiBnZWxpamtlIHZhcmlhbnRpZSBoZWJiZW4uIChob21vc2NlZGFzdGljaXRlaXQpCgpXZSBnYWFuIGdlbGlqa2hlaWQgdmFuIHZhcmlhbnRpZXMgbmEgbWV0IGJveHBsb3RzLiBEaXQgbGlqa3QgYWx2YXN0IGluIG9yZGUgdGUgemlqbi4KCldlIHp1bGxlbiBudSBkZSBhc3N1bXB0aWUgdmFuIG5vcm1hbGUgdmVyZGVsaW5nIGJpbm5lbiBlbGtlIGdyb2VwIG5hZ2Fhbi4gCgpgYGB7cn0KI01hYWsgZWVuIFFRcGxvdCB2b29yIGhldCBnZXdpY2h0IHBlciB2b2VkaW5nc3Nvb3J0LgpjaGlja3d0cyAlPiUKICBnZ3Bsb3QoYWVzKHNhbXBsZSA9IHdlaWdodCkpICsKICBnZW9tX3FxKCkgKwogIGdlb21fcXFfbGluZSgpICsKICBmYWNldF9ncmlkKC5+ZmVlZCkgKwogIHlsYWIoIlJlbGF0aWV2ZSBhYnVuZGFudGllIikKCmBgYAoKCkRlIGFmd2lqa2luZ2VuIGRpZSB3ZSBpbiBvbnplIHFxcGxvdCB6aWVuIGxpamtlbiBuaWV0IHplZXIgdWl0em9uZGVybGlqay4gRGFhcm9tIGt1bm5lbiB3ZSBzdGVsbGVuIGRhdCBlbGtlIGdyb2VwIGVlbiBub3JtYWxlIHZlcmRlbGluZyBsaWprdCB0ZSB2b2xnZW4uCgpJbmRpZW4gbWVuIHZlZWwgZ3JvZXBlbiBtb2V0IHZlcmdlbGlqa2VuLCBrYW4gaGV0IG1ha2tlbGlqa2VyIHppam4gb20gc2xlY2h0cyDDqcOpbiBwbG90IHRlIG1vZXRlbiBiZW9vcmRlbGVuLiBJbiBkYXQgZ2V2YWwga2FuIG1lbiBlcnZvb3Iga2llemVuIG9tIG5pZXQgdm9vciBlbGtlIGdyb2VwIGFwYXJ0IGVlbiBRUS1wbG90IHRlIG1ha2VuLCBtYWFyIGthbiBtZW4gZGUgcmVzaWR1ZW4gdmFuIGhldCBsaW5lYWlyIG1vZGVsIGNoZWNrZW4uIApNZXJrIG9wIGRhdCBtZW4gZGFuIGNoZWNrdCB2b29yIGVlbiBub3JtYWxlIGRpc3RyaWJ1dGllIHZhbiAqKiphbGxlKioqIHJlc2lkdWVuIHZhbiBoZXQgZ2V3aWNodCB0ZW4gb3B6aWNodGUgdmFuIGh1biBncm9lcHNnZW1pZGRlbGRlLCBlbiBkdXMgbmlldCB2b29yIGVlbiBub3JtYWxlIGRpc3RyaWJ1dGllIGJpbm5lbiBlbGtlIGdyb2VwIGFwYXJ0LgoKYGBge3J9Cm1vZGVsX2xtIDwtIGxtKHdlaWdodCB+IGZlZWQsIGRhdGEgPSBjaGlja3d0cykKcGFyKG1mcm93PWMoMiwyKSkKcGxvdChtb2RlbF9sbSkgIyBFbmtlbCBmaWd1dXIgcmVjaHRzIGJvdmVuIGlzIHJlbGV2YW50CnBhcihtZnJvdz1jKDEsMSkpCmBgYAoKRGUgUVEtcGxvdCB2ZXJ0b29udCBnZWVuIHN5c3RlbWF0aXNjaGUgYWZ3aWpraW5nZW4gdmFuIGVlbiBub3JtYWxlIGRpc3RyaWJ1dGllLiBEaXQgaXMgZ2VlbiBnYXJhbnRpZSBkYXQgZGUgZGF0YSBub3JtYWFsIHZlcmRlZWxkIGlzIGJpbm5lbiBlbGtlIGdyb2VwLCBtYWFyIGhldCBpcyBlZW4gYmVuYWRlcmluZyBkaWUgd2Uga3VubmVuIGdlYnJ1aWtlbiBpbiBoZXQgZ2V2YWwgZGF0OgoKIC0gZXIgdGUgdmVlbCBncm9lcGVuIHppam4gb20gZGUgYXNzdW1wdGllcyB0ZSBjaGVja2VuIGJpbm5lbiBlbGtlIGdyb2VwOwogLSBlciB0ZSB3ZWluaWcgb2JzZXJ2YXRpZXMgemlqbiBwZXIgZ3JvZXAgb20gYmlubmVuIGVsa2UgZ3JvZXAgZGUgYXNzdW1wdGllcyBuYSB0ZSBnYWFuLgoKTWVyayBvcCBkYXQgamUgaW4gcHJpbmNpcGUgZGUgYXNzdW1wdGllIHZhbiBnZWxpamtlIHZhcmlhbnRpZXMgb29rIG9wIGJhc2lzIHZhbiBkZSBwbG90IGxpbmtzYm92ZW4gem91IGt1bm5lbiBjaGVja2VuOiBlbGtlICdrb2xvbScgdmFuIHB1bnRlbiBzdGVsdCBlZW4gc29vcnQgdm9vciAoMSBzb29ydCBoZWVmdCAxIGdlc2NoYXQgZ2VtaWRkZWxkZSkgZW4gZGUgcHVudGVuIHN0ZWxsZW4gZGUgcmVzaWR1ZW4gdm9vciB0ZW4gb3B6aWNodGUgdmFuIGh1biBncm9lcHNnZW1pZGRlbGRlLiBNZW4ga2FuIGRlemUgcGxvdCBkdXMgb29rIGdlYnJ1aWtlbiBvbSB0ZSBraWprZW4gb2YgZXIgZ3JvZXBlbiAoc29vcnRlbikgemlqbiBkaWUgZWVuIHZlcnNjaGlsbGVuZGUgdmFyaWFudGllIGhlYmJlbiB0ZW4gb3B6aWNodGUgdmFuIGFuZGVyZSBncm9lcGVuLgoKCgojIyBNb2RlbGxlZXIgZGUgZGF0YSBtZXQgaGV0IGxpbmVhaXIgbW9kZWw6CgpgYGB7cn0Kc3VtbWFyeShtb2RlbF9sbSkKYGBgCgpEZSBwLXdhYXJkZW4gZGllIHdlIGhpZXIga3JpamdlbiB2b29yIGRlIHBhcmFtZXRlcnMga29tZW4gbmlldCBvdmVyZWVuIG1ldCBkZSBBTk9WQS10ZXN0IGRpZSB3ZSB3aWxsZW4gdWl0dm9lcmVuLiBEZSBwLXdhYXJkZSBiaWogZGUgRi1zdGF0aXN0aWMgaXMgd2VsIGRlIGp1aXN0ZSBwLXdhYXJkZS4gV2Uga3VubmVuIGRpdCBvb2sgdmVya3JpamdlbiBkb29yIGRlIHZvbGdlbmRlIGNvZGU6CgpgYGB7cn0KI1ZvZXIgZGUgQU5PVkEgdWl0IG9wIGhldCBsaW5lYXJlIG1vZGVsLgphbm92YShtb2RlbF9sbSkKYGBgCgpXZSB2b2VyZGVuIGRlIEFOT1ZBIHRlc3QgdWl0IGFhbiBkZSBoYW5kIHZhbiBoZXQgbGluZWFpciByZWdyZXNzaWVtb2RlbC4gSW4gcHJpbmNpcGUgdGVzdGVuIHdlIGRhbiB2b2xnZW5kZSBudWxoeXBvdGhlc2U6CgpcWyBIXzA6IFxiZXRhXzEgPSBcYmV0YV8yID0gMCAgXF0KCgpNZXJrIG9wIGRhdCBkZXplIG51bGh5cG90aGVzZSBldmVud2FhcmRpZyBpcyBhYW4gZGUgbnVsaHlwb3RoZXNlIGRpZSB3ZSBlZXJkZXIgZm9ybXVsZWVyZGVuLiBBbHMgYWxsZSBnZW1pZGRlbGRlbiAkXG11XzEsIFxtdV8yLCBcbXVfMyA9IDAkLCBiZXRla2VudCBkaXQgZGF0IGJlaWRlIHJlZ3Jlc3NpZXBhcmFtZXRlcnMgJFxiZXRhXzEkIGVuICRcYmV0YV8xJCBnZWxpamsgemlqbiBhYW4gMC4KCgpEZSBwLXdhYXJkZSB2YW4gZGV6ZSBBTk9WQSB0ZXN0IGlzIGJpanpvbmRlciBrbGVpbi4gV2UgYmVzbHVpdGVuIGRhdCB3ZSBkZSBudWxoeXBvdGhlc2Uga3VubmVuIHZlcndlcnBlbiAoJHA8PDAuMDAxJCkgZW4gZGF0IGhldCBnZW1pZGRlbGRlIGdld2ljaHQgdmFuIGt1aWtlbnMgdmVyc2NoaWx0IHR1c3NlbiBtaW5zdGVucyB0d2VlIHZhbiBkZSB2b2VkaW5nc3BhdHJvbmVuIG9wIGhldCA1JSBzaWduaWZpY2FudGllbml2ZWF1LgoKQWFuIGRlIGhhbmQgdmFuIGRpdCByZXN1bHRhYXQgd2V0ZW4gd2UgZWNodGVyIG5pZXQgdHVzc2VuIHdlbGtlIHZvZWRpbmdlbiBlciBlZW4gdmVyc2NoaWwgb3B0cmVlZHQsIGVuIGhpZXJ2b29yIHp1bGxlbiB3ZSBlZW4gKipwb3N0LWhvYyBhbmFseXNlKiogbW9ldGVuIHVpdHZvZXJlbi4gRWVuIHBvc3QtaG9jIGFuYWx5c2Ugdm9lcnQgbWVuIGVua2VsIHVpdCBpbmRpZW4gZGUgQU5PVkEgdGVzdCBzaWduaWZpY2FudCB3YXMsIGVuIGJlc3RhYXQgZXJpbiBvbSBwYWFyc2dld2lqemUgdmVyZ2VsaWpraW5nZW4gdWl0IHRlIHZvZXJlbiB0dXNzZW4gZGUgZ3JvZXBlbi4gSW4gZGl0IGdldmFsIGtvbXQgZGl0IG92ZXJlZW4gbWV0IGhldCB2ZXJnZWxpamtlbiBvZiBlciBlZW4gdmVyc2NoaWwgaXMgdHVzc2VuIGdyb2VwIDEgZW4gMiwgdHVzc2VuIGdyb2VwIDEgZW4gMyBlbiB0dXNzZW4gZ3JvZXAgMiBlbiAzLiAKCgojIyBQb3N0LWhvYyBhbmFseXNlCgpEZSBwb3N0LWhvYyBhbmFseXNlIGJlc3RhYXQgZXJ1aXQgb20gcGFhcnNnZXdpanplIHRlc3RlbiB1aXQgdGUgdm9lcmVuLiBJbmRpZW4gbWVuIG92ZXIgJGskIGdyb2VwZW4gYmVzY2hpa3QgaXMgaGV0IHRvdGFhbCBhYW50YWwgcGFhcnNnZXdpanplIHZlcmdlbGlqa2luZ2VuIGdlbGlqayBhYW4gJGsoay0xKS8yJC4gQmlqIG9ucyBpcyAkaz0zJCB3YWFyZG9vciB3ZSAkMyQgcGFhcnNnZXdpanplIHZlcmdlbGlqa2luZ2VuIHp1bGxlbiB1aXR2b2VyZW4uCldlIGt1bm5lbiBlY2h0ZXIgbmlldCBlbGtlIHRlc3Qgb3AgaGV0IDUlIHNpZ25pZmljYW50aWVuaXZlYXUgdWl0dm9lcmVuIHZhbndlZ2UgaGV0IG1lZXJ2b3VkaWcgdG9ldHNlbiBwcm9ibGVlbS4gCkluZGllbiB3ZSAzIHZlcmdlbGlqa2luZ2VuIHpvdWRlbiB0ZXN0ZW4gZWxrIG9wIGhldCA1JSBzaWduaWZpY2FudGllbml2ZWF1LCBkYW4gaXMgZGUga2FucyBkYXQgd2UgbWluc3RlbnMgw6nDqW4gbnVsaHlwb3RoZXNlIG9udGVyZWNodCB6b3VkZW4gdmVyd2VycGVuIG5pZXQgbGFuZ2VyIGdlbGlqayBhYW4gb25zIHNpZ25pZmljYW50aWVuaXZlYXUgKDUlKS4KSW4gb25zIGdldmFsLCB6b3UgZGV6ZSBrYW5zIGdlbGlqayB6aWpuIGFhbjoKCmBgYHtSfQphbHBoYSA8LSAwLjA1Cm5Db21wYXJpc29ucyA8LSAzCjEtKDEtYWxwaGEpXm5Db21wYXJpc29ucwpgYGAKCkR1cyBpbmRpZW4gd2UgZWxrZSB0ZXN0IG9wIGhldCA1JSBzaWduaWZpY2FudGllbml2ZWF1IHpvdWRlbiB1aXR2b2VyZW4gaGViYmVuIHdlLCBhbHMgYWxsZSBudWxoeXBvdGhlc2VzIHdhYXIgem91ZGVuIHppam4sIGVlbiBrYW5zIHZhbiBgciByb3VuZCgxLSgxLWFscGhhKV5uQ29tcGFyaXNvbnMsMykqMTAwYCUgZGF0IHdlIG1pbnN0ZW5zIMOpw6luIG51bGh5cG90aGVzZSB2ZXJrZWVyZCB6b3VkZW4gdmVyd2VycGVuLgpPbSBkZXplIGthbnMgZ2xvYmFhbCBnZXppZW4gKGRpdCBpcywgb3ZlciBhbGxlIHBhYXJzZ2V3aWp6ZSB2ZXJnZWxpamtpbmdlbikgb3AgNSUgdGUgaG91ZGVuLCBrdW5uZW4gd2UgYmlqdm9vcmJlZWxkIGRlIEJvbmZlcnJvbmkgY29ycmVjdGllIHVpdHZvZXJlbi4KCkluIGBSYCBrdW5uZW4gd2UgZGUgcG9zdC1ob2MgYW5hbHlzZSB1aXR2b2VyZW4gbWV0IGJlaHVscCB2YW4gaGV0IGBtdWx0Y29tcGAgcGFja2FnZSBhYW4gZGUgaGFuZCB2YW4gZGUgYGdsaHRgIGZ1bmN0aWUuIFdlIHNwZWNpZmnDq3JlbiBoaWVyIGluIGhldCBgbGluZmN0YCBhcmd1bWVudCBkYXQgd2UgKm11bHRpcGxlIGNvbXBhcmlzb25zKiAoYG1jcGApIHdpbGxlbiB1aXR2b2VyZW4gd2FhcmJpaiB3ZSBhbGxlIHBhYXJzZ2V3aWp6ZSB2ZXJnZWxpamtpbmdlbiB2b29yIGRlIGBmZWVkYCB2YXJpYWJlbGUgd2lsbGVuIHRlc3RlbiBhYW4gZGUgaGFuZCB2YW4gZGUgYCJUdWtleSJgIG1ldGhvZGUuIERlIGBtdWx0Y29tcGAgcGFja2FnZSB6b3JndCBlcnZvb3IgZGF0IGRlemUgcC13YWFyZGVuIGF1dG9tYXRpc2NoIGdlY29ycmlnZWVyZCB3b3JkZW4gdm9vciBtZWVydm91ZGlnIHRvZXRzZW4uCgpgYGB7cn0Kc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKGxpYnJhcnkobXVsdGNvbXApKQptY3AgPC0gZ2xodChtb2RlbF9sbSxsaW5mY3Q9bWNwKGZlZWQ9IlR1a2V5IikpCnN1bW1hcnkgPC0gc3VtbWFyeShtY3ApCnN1bW1hcnkKYGBgCgpJbiBkZSBvdXRwdXQgaGllcnZhbiB6aWVuIHdlIGRlIHZlcnNjaGlsbGVuZGUgcGFhcnNnZXdpanplIHZlcmdlbGlqa2luZ2VuIGRpZSB3ZXJkZW4gdWl0dm9lcmQuIEJpanZvb3JiZWVsZCBgbGluc2VlZCAtIGNhc2VpbiA9PSAwYCBkdWlkdCBlcm9wIGRhdCB2b29yIGRpdCBjb250cmFzdCB3b3JkdCBnZXRlc3Qgb2YgaGV0IGdlbWlkZGVsZGUgZ2V3aWNodCB2b29yIHZvZWRpbmcgYGxpbnNlZWRgIG1pbiBoZXQgZ2VtaWRkZWxkZSBnZXdpY2h0IHZvb3Igc29vcnQgYGNhc2VpbmAgdmVyc2NoaWxsZW5kIGlzIHZhbiBudWwuCkluIGRlIHR3ZWVkZSBrb2xvbSB3b3JkdCBoZXQgdmVyc2NoaWwgaW4gZ2VtaWRkZWxkZW4gd2VlcmdlZ2V2ZW4sIG1ldCBodW4gc3RhbmRhYXJkIGVycm9yIGVuIHRlc3RzdGF0aXN0aWVrIGluIGRlIHJlc3BlY3RpZXZlbGlqayBkZXJkZSBlbiB2aWVyZGUga29sb20uCkRlIGxhYXRzdGUga29sb20gZ2VlZnQgYWFuZ2VwYXN0ZSBwLXdhYXJkZW4gd2VlciBvcCBlZW4gZ2xvYmFhbCBzaWduaWZpY2FudGllbml2ZWF1IHZhbiA1JS4KQWFuIGRlIGhhbmQgdmFuIGRlIGFhbmdlcGFzdGUgcC13YWFyZGVuIHppZW4gd2UgZGF0IGhldCBnZW1pZGRlbGRlIGdld2ljaHQgYmlqIGBjYXNlaW5gIHZlcnNjaGlsdCB2YW4gem93ZWwgYGxpbnNlZWRgIGVuIGBzb3liZWFuYCAocCA8IDAuMDAxIGVuIHAgPSAwLjAwNCkgb3AgaGV0IDUlIHNpZ25pZmljYW50aWVuaXZlYXUuIFdlIHppZW4gb29rIGRhdCBlciBnZWVuIHNpZ25pZmljYW50IHZlcnNjaGlsIGlzIGluIGdlbWlkZGVsZCBnZXdpY2h0IGJpaiB2b2VkaW5nIGBzb3liZWFuYCBlbiBgbGluc2VlZGAgb3AgaGV0IDUlIHNpZ25pZmljYW50aWVuaXZlYXUuCkRlIGVmZmVjdGdyb290dGUgaXMgdm9vciBiaWogem93ZWwgYGxpbnNlZWRgIGFscyBgc295YmVhbmAgbmVnYXRpZWYsIHdhdCBlcm9wIGR1aWR0IGRhdCBoZXQgZ2VtaWRkZWxkZSBnZXdpY2h0IHZhbiBrdWlrZW5zIGhvZ2VyIGlzIGJpaiB2b2VkaW5nc3BhdHJvb24gYGNhc2VpbmAuCgpEZSBiZXRyb3V3YmFhcmhlaWRzaW50ZXJ2YWxsZW4gdmFuIGVsa2UgcGFhcnNnZXdpanplIHRlc3Qga3VubmVuIHdlIG9vayBtYWtrZWxpamsgZ3JhZmlzY2ggdm9vcnN0ZWxsZW4gYWFuIGRlIGhhbmQgdmFuIGRlIGBwbG90YCBmdW5jdGllIGRpZSB6byBvcCBlZW4gYGdsaHRgIG9iamVjdCBrYW4gdG9lZ2VwYXN0IHdvcmRlbi4KCmBgYHtyfQpjb25maW50KG1jcCkKYGBgCgpgYGB7cn0KcGxvdChtY3ApCmBgYAoKCiMgQ29uY2x1c2llCgpXZSBrdW5uZW4gY29uY2x1ZGVyZW4gZGF0IGVyIGVlbiBzaWduaWZpY2FudCB2ZXJzY2hpbCBpbiBnZXdpY2h0IGlzIHR1c3NlbiBoZXQgZ2V3aWNodCB2YW4ga3Vpa2VudGplcyBtZXQgdm9lZGluZyBjYXNlaW5lIHRlZ2Vub3ZlciBkZSBhbmRlcmUgdm9lZGluZ2VuIG9wIGhldCA1JSBzaWduaWZpY2FudGllbml2ZWF1LiBUdXNzZW4gbGluc2VlZCBlbiBzb3liZWFuIGlzIGVyIGdlZW4gc2lnbmlmaWNhbnQgdmVyc2NoaWwgaW4gZ2V3aWNodCB2YW4gZGUga3Vpa2VudGplcy4KCg==