Creative Commons License

1 Invloed concentratie op reactiesnelheid

De reactiesnelheid van een proces met een enzyme als katalysator wordt opgemeten door het aantal radioactieve reactieproducten te tellen in functie van de substraatconcentratie. Dat wordt gedaan voor een reactiemengsel met Puromycine en zonder Puromycine.

We willen nagaan of er een lineair verband is tussen de gemiddelde reactiesnelheid en de substraatconcentratie voor zowel de groep die behandeld is met Puromycine als voor de controlegroep zonder Puromicine. Aangezien we de data zouden moeten analyseren met een meervoudige lineaire regressiemodel die het effect van de concentratie en de behandeling kan modelleren, beperken we ons voorlopig tot de data van de groep die behandeld is met Puromycine.

library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ ggplot2   3.5.1     ✔ tibble    3.2.1
## ✔ lubridate 1.9.3     ✔ tidyr     1.3.1
## ✔ purrr     1.0.2     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(ggplot2)
data(Puromycin)
Puromycin <- Puromycin %>% filter(state=="treated")

2 Data exploratie

We plotten de reactiesnelheid tegenover de concentratie om de data te exploreren.

Puromycin  %>%
  ggplot(aes(x=conc,y=rate)) +
  geom_point() + 
  stat_smooth(method = "loess",col="red") + # fit een kromme door de punten (rode lijn)
  stat_smooth(method='lm',col="black") + # fit een rechte door de punten aan de hand van de kleinstekwadratenmethode
  ylab("Reactiesnelheid (counts/min)") +
  xlab("Substraatconcentratie (ppm)") +
  theme_bw()
## `geom_smooth()` using formula = 'y ~ x'
## `geom_smooth()` using formula = 'y ~ x'

Het ziet ernaar uit dat de data geen lineaire trend volgt. We gaan nu het verband na log-transformatie van de substraatconcentratie. Gezien de substraat concentratie in ppm is gemeten zullen we een log\(_{10}\) transformatie gebruiken (een waarde van -2,-1,0 op log schaal is dan 0.01ppm, 0.1 ppm, 1 ppm).

Puromycin  %>%
  ggplot(aes(x=conc %>% log10,y=rate)) +
  geom_point() + 
  stat_smooth(method = "loess",col="red") + # fit een kromme door de punten (rode lijn)
  stat_smooth(method='lm',col="black") + # fit een rechte door de punten aan de hand van de kleinstekwadratenmethode
  ylab("Reactiesnelheid (counts/min)") +
  xlab("log10(Substraatconcentratie (ppm))") +
  theme_bw()
## `geom_smooth()` using formula = 'y ~ x'
## `geom_smooth()` using formula = 'y ~ x'

Het verband tussen de reactiesnelheid en het logaritme van de substraatconcentratie lijkt lineair. We zullen de reactiesnelheid dus verder modelleren in functie van de log\(_{10}\)-substraatconcentratie.

3 Enkelvoudige lineaire regressie

Enkelvoudige lineaire regressie is een regressie waarbij een variabele gemodelleerd wordt in functie van slechts 1 variabele. De verwachtte reactiesnelheid wordt dus \(E[Y_i] = \beta_0 + \beta_1X_i\). In dit geval is \(Y\) de reactiesnelheid en \(X\) de log10-substraatconcentratie.

Het model wordt dan als volgt: \(reactiesnelheid_i = \beta_0 + \beta_1 log_{10}(concentratie_i) + \epsilon_i\)

met \(\beta_0\) het (werkelijke) intercept, \(\beta_1\) de (werkelijke) helling of meer specifiek het (werkelijk) effect van log10(concentratie) op de gemiddelde reactiesnelheid. Deze parameters gaan we schatten.

\(\epsilon_i\) is een foutterm (“error term”), waarbij \(\epsilon_i\) i.i.d. normaal verdeeld zijn met gemiddelde 0 en (constante) variantie \(\sigma^2\).

3.1 Assumpties

Voordat we conclusies kunnen trekken uit het lineaire regressiemodel moeten we nagaan of er aan de assumpties voldaan zijn. Voor de lineaire regressie zijn dat volgende assumpties:

  1. Onafhankelijke gegevens
  2. Lineariteit tussen respons en predictor (impliceert dat residuen rond nul verdeeld zijn, zonder merkbaar resterend patroon tussen de residuen en de geschatte respons variabele)
  3. Normaal verdeelde residuen
  4. Gelijke variantie (homoscedasticiteit)

Onafhankelijke gegevens moeten we veronderstellen uit het experimenteel design. De andere assumpties moeten we controleren.

3.1.1 Lineariteit tussen reactiesnelheid en log\(_{10}\)(substraatconcentratie):

Zoals hierboven besproken lijkt het dat er een lineaire trend is tussen reactiesnelheid en log\(_{10}\)(substraatconcentratie) in het volledige bereik van de data.

De lineariteitsassumptie impliceert dat de residuen willekeurig rond nul verdeeld zijn, onafhankelijk van waar we ons op de rechte bevinden. Dit kunnen we weergeven door een lineair model te fitten op de data en de residuen met een smoother weer te geven in functie van de gefitte responswaarden.

model <- lm(rate~log10(conc),data = Puromycin) 
model
## 
## Call:
## lm(formula = rate ~ log10(conc), data = Puromycin)
## 
## Coefficients:
## (Intercept)  log10(conc)  
##      209.19        85.45
plot(model,which=1)

Er lijken kleine afwijkingen te zijn bij de residuen van hogere gefitted waarden. Er zijn echter niet zoveel observaties opgenomen in de studie en de smoother geeft sowieso onnauwkeurig schattingen op de eindpunten van het bereik.

Om na te gaan of de afwijkingen die we zien inderdaad plaucibel zijn en kunnen worden veroorzaakt door random variabiliteit kunnen we gebruik maken van simulaties waaruit we de data genereren onder de voorwaarden van het lineaire model.

We simuleren 9 datasets met hetzelfde aantal observaties, predictorwaarden, intercept, helling en standaarddeviatie. We fitten de modellen en maken de residuplot.

set.seed(1031)
betas <- model %>% coefficients
sigma <- model %>% sigma 

simModels <- list()

par(mfrow=c(3,3))
for (i in 1:9)
{
  x <- Puromycin %>% pull("conc") %>% log10
  nobs <- Puromycin %>% nrow
  y <- betas[1] + betas[2] * x + rnorm(nobs, sd = sigma)
  simModels[[i]] <- lm(y~x)
  plot(simModels[[i]], which = 1)
}

3.1.2 Normaal verdeelde residuen

We gaan via een qq-plot na of de residuen normaal verdeeld zijn.

plot(model,which=2)

We zien dat er geen systematische afwijkingen zijn van normaliteit, en kunnen veronderstellen dat de kleine afwijkingen door toevallige steekproefvariabiliteit komen.

3.1.3 Gelijke variantie (homoscedasticiteit)

Bij lineaire regressie wil de assumptie van gelijkheid van variantie zeggen dat de variantie van de residuen rond de regressierechte hetzelfde is voor elke waarde van de predictor (predictorpatroon).

We kunnen dit opnieuw nagaan met de residu-plot. De spreiding van de residuen zou min of meer gelijk moeten zijn voor elke gefitte waarde.

Een andere plot die we hiervoor kunnen gebruiken is een plot waar we de vierkantswortel van de absolute waarde van de gestandaardiseerde residuen plotten in functie van de gefitte waarden. Als we hier een smoother door trekken, zou de smoother een horizontaal verloop moeten hebben. Indien er afwijkingen zouden zijn, bv. er is een systematische trend waarbij de gestandaardiseerde residuen hoger/lager worden naarmate de fitted values hoger/lager worden, dan betekent het dat de variantie van de residuen hoger/lager wordt naarmate de geschatte respons hoger/lager wordt.

plot(model,which=3)

Hier zien we kleine afwijkingen van een horizontale lijn bij de uiterste waarden. Via simulatie zien we opnieuw dat deze afwijkingen plaucibel zijn in een experiment met ons design wanneer alle aannames geldig zijn.

par(mfrow = c(3,3))
for (i in 1:9)
  plot(simModels[[i]], which = 3)

We kunnen dus veronderstellen dus dat de varianties gelijk zijn.

3.2 Nul- en alternatieve hypothese:

We willen weten of er een lineaire associatie is tussen de reactiesnelheid en de log\(_{10}\) getransformeerde concentratie.

De nul- en alternatieve hypothese van het lineair model worden dus:

\(H_0\): \(\beta_1 = 0\)

\(H_A\): \(\beta_1 \ne 0\)

Met andere woorden stelt de nulhypothese dat er geen associatie is tussen de reactiesnelheid en de log\(_{10}\) concentratie, terwijl de alternatieve hypothese stelt dat er juist wel een associatie is.

3.3 Fit het lineair model en bespreek beide parameters, ga na of de nulhypothese verworpen wordt en maak een interpretatie van het betrouwbaarheidsinterval.

summaryModel <- summary(model)
summaryModel
## 
## Call:
## lm(formula = rate ~ log10(conc), data = Puromycin)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -17.0176  -6.2455   0.6039   7.4262  13.3228 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  209.194      5.045   41.47 1.59e-12 ***
## log10(conc)   85.450      5.133   16.65 1.28e-08 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 10.37 on 10 degrees of freedom
## Multiple R-squared:  0.9652, Adjusted R-squared:  0.9617 
## F-statistic: 277.1 on 1 and 10 DF,  p-value: 1.28e-08
confintModel <- confint(model)
confintModel
##                 2.5 %    97.5 %
## (Intercept) 197.95335 220.43564
## log10(conc)  74.01255  96.88732

3.3.1 Conclusie

Er is een extreem significante lineaire associatie tussen de substraatconcentratie op logschaal en de reactiesnelheid (p << 0.001). Wanneer we de reactie laten doorgaan bij een substraatconcentratie die 10 keer hoger is, is de reactiesnelheid gemiddeld met 85.4 counts/min hoger (95% betrouwbaarheidsinterval [74, 96.9] counts/min).

3.3.2 Interpretatie

  1. Het intercept is de geschatte gemiddelde reactiesnelheid bij een log\(_{10}\)-concentratie van 0/een substraat concentratie van 1 ppm en is gelijk aan 209.2 counts/min.

  2. Helling

  • Log schaal: Wanneer we de reactie laten doorgaan bij een substraatconcentratie die 1 eenheid op log\(_{10}\) schaal hoger is, is de reactiesnelheid gemiddeld met 85.4 counts/min hoger.

  • Originele schaal: Wanneer we de reactie laten doorgaan bij een substraatconcentratie die 10 keer hoger is, is de reactiesnelheid gemiddeld met 85.4 counts/min hoger.

  1. 95% betrouwbaarheidsinterval: We hebben dus geschat dat het werkelijke verschil in reactiesnelheid tussen twee reacties die doorgaan onder een substraatconcentratie die een factor 10 verschillen met 95% kans ligt tussen [74, 96.9] counts/min; merk op dat de reactie sneller doorgaat in de reactie met de hoogste substraatconcentratie.

3.4 Schat de gemiddelde reactiesnelheid bij een substraat concentratie van 0.2ppm en geef een bijhorend 95%-betrouwbaarheidsinterval.

pred <- predict(model, newdata=data.frame(conc=0.2), interval="confidence")
pred
##        fit      lwr      upr
## 1 149.4676 142.7162 156.2189

De geschatte gemiddelde reactiesnelheid bij een substraatconcentratie van 10 ppm is 149.5 counts/min (95% betrouwbaarheidsinterval [142.7, 156.2] counts/min).

4 Algemene conclusie

Er is een extreem significante lineaire associatie tussen de substraatconcentratie op logschaal en de reactiesnelheid (p << 0.001). Wanneer we de reactie laten doorgaan bij een substraatconcentratie die 10 keer hoger is, is de reactiesnelheid gemiddeld met 85.4 counts/min hoger (95% betrouwbaarheidsinterval [74, 96.9] counts/min).

LS0tCnRpdGxlOiAiUHJhY3RpY3VtIDE6IE9lZmVuaW5nIDQiCmF1dGhvcjogIkFsZXhhbmRyZSBTZWdlcnMgJiBMaWV2ZW4gQ2xlbWVudCIKZGF0ZTogInN0YXRPbWljcywgR2hlbnQgVW5pdmVyc2l0eSAoaHR0cHM6Ly9zdGF0b21pY3MuZ2l0aHViLmlvKSIKb3V0cHV0OgogICAgaHRtbF9kb2N1bWVudDoKICAgICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgICB0aGVtZTogY29zbW8KICAgICAgdG9jOiB0cnVlCiAgICAgIHRvY19mbG9hdDogdHJ1ZQogICAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgcGRmX2RvY3VtZW50OgogICAgICB0b2M6IHRydWUKICAgICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICAgIGxhdGV4X2VuZ2luZTogeGVsYXRleApsaW5rY29sb3I6IGJsdWUKdXJsY29sb3I6IGJsdWUKY2l0ZWNvbG9yOiBibHVlCgotLS0KCjxhIHJlbD0ibGljZW5zZSIgaHJlZj0iaHR0cHM6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLXNhLzQuMCI+PGltZyBhbHQ9IkNyZWF0aXZlIENvbW1vbnMgTGljZW5zZSIgc3R5bGU9ImJvcmRlci13aWR0aDowIiBzcmM9Imh0dHBzOi8vaS5jcmVhdGl2ZWNvbW1vbnMub3JnL2wvYnktbmMtc2EvNC4wLzg4eDMxLnBuZyIgLz48L2E+CgoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkKYGBgCgojIEludmxvZWQgY29uY2VudHJhdGllIG9wIHJlYWN0aWVzbmVsaGVpZCAKCkRlIHJlYWN0aWVzbmVsaGVpZCB2YW4gZWVuIHByb2NlcyBtZXQgZWVuIGVuenltZSBhbHMga2F0YWx5c2F0b3Igd29yZHQgb3BnZW1ldGVuIGRvb3IgaGV0IGFhbnRhbCByYWRpb2FjdGlldmUgcmVhY3RpZXByb2R1Y3RlbiB0ZSB0ZWxsZW4gaW4gZnVuY3RpZSB2YW4gZGUgc3Vic3RyYWF0Y29uY2VudHJhdGllLiBEYXQgd29yZHQgZ2VkYWFuIHZvb3IgZWVuIHJlYWN0aWVtZW5nc2VsIG1ldCBQdXJvbXljaW5lIGVuIHpvbmRlciBQdXJvbXljaW5lLgoKV2Ugd2lsbGVuIG5hZ2FhbiBvZiBlciBlZW4gbGluZWFpciB2ZXJiYW5kIGlzIHR1c3NlbiBkZSBnZW1pZGRlbGRlIHJlYWN0aWVzbmVsaGVpZCBlbiBkZSBzdWJzdHJhYXRjb25jZW50cmF0aWUgdm9vciB6b3dlbCBkZSBncm9lcCBkaWUgYmVoYW5kZWxkIGlzIG1ldCBQdXJvbXljaW5lIGFscyB2b29yIGRlIGNvbnRyb2xlZ3JvZXAgem9uZGVyIFB1cm9taWNpbmUuIEFhbmdlemllbiB3ZSBkZSBkYXRhIHpvdWRlbiBtb2V0ZW4gYW5hbHlzZXJlbiBtZXQgZWVuIG1lZXJ2b3VkaWdlIGxpbmVhaXJlIHJlZ3Jlc3NpZW1vZGVsIGRpZSBoZXQgZWZmZWN0IHZhbiBkZSBjb25jZW50cmF0aWUgZW4gZGUgYmVoYW5kZWxpbmcga2FuIG1vZGVsbGVyZW4sIGJlcGVya2VuIHdlIG9ucyB2b29ybG9waWcgdG90IGRlIGRhdGEgdmFuIGRlIGdyb2VwIGRpZSBiZWhhbmRlbGQgaXMgbWV0IFB1cm9teWNpbmUuCgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZ2dwbG90MikKYGBgCgpgYGB7cn0KZGF0YShQdXJvbXljaW4pClB1cm9teWNpbiA8LSBQdXJvbXljaW4gJT4lIGZpbHRlcihzdGF0ZT09InRyZWF0ZWQiKQoKYGBgCgojIERhdGEgZXhwbG9yYXRpZQoKV2UgcGxvdHRlbiBkZSByZWFjdGllc25lbGhlaWQgdGVnZW5vdmVyIGRlIGNvbmNlbnRyYXRpZSBvbSBkZSBkYXRhIHRlIGV4cGxvcmVyZW4uCmBgYHtyfQpQdXJvbXljaW4gICU+JQogIGdncGxvdChhZXMoeD1jb25jLHk9cmF0ZSkpICsKICBnZW9tX3BvaW50KCkgKyAKICBzdGF0X3Ntb290aChtZXRob2QgPSAibG9lc3MiLGNvbD0icmVkIikgKyAjIGZpdCBlZW4ga3JvbW1lIGRvb3IgZGUgcHVudGVuIChyb2RlIGxpam4pCiAgc3RhdF9zbW9vdGgobWV0aG9kPSdsbScsY29sPSJibGFjayIpICsgIyBmaXQgZWVuIHJlY2h0ZSBkb29yIGRlIHB1bnRlbiBhYW4gZGUgaGFuZCB2YW4gZGUga2xlaW5zdGVrd2FkcmF0ZW5tZXRob2RlCiAgeWxhYigiUmVhY3RpZXNuZWxoZWlkIChjb3VudHMvbWluKSIpICsKICB4bGFiKCJTdWJzdHJhYXRjb25jZW50cmF0aWUgKHBwbSkiKSArCiAgdGhlbWVfYncoKQpgYGAKCkhldCB6aWV0IGVybmFhciB1aXQgZGF0IGRlIGRhdGEgZ2VlbiBsaW5lYWlyZSB0cmVuZCB2b2xndC4gV2UgZ2FhbiBudSBoZXQgdmVyYmFuZCBuYSBsb2ctdHJhbnNmb3JtYXRpZSB2YW4gZGUgc3Vic3RyYWF0Y29uY2VudHJhdGllLiBHZXppZW4gZGUgc3Vic3RyYWF0IGNvbmNlbnRyYXRpZSBpbiBwcG0gaXMgZ2VtZXRlbiB6dWxsZW4gd2UgZWVuIGxvZyRfezEwfSQgdHJhbnNmb3JtYXRpZSBnZWJydWlrZW4gKGVlbiB3YWFyZGUgdmFuIC0yLC0xLDAgb3AgbG9nIHNjaGFhbCBpcyBkYW4gMC4wMXBwbSwgMC4xIHBwbSwgMSBwcG0pLiAKCgpgYGB7cn0KUHVyb215Y2luICAlPiUKICBnZ3Bsb3QoYWVzKHg9Y29uYyAlPiUgbG9nMTAseT1yYXRlKSkgKwogIGdlb21fcG9pbnQoKSArIAogIHN0YXRfc21vb3RoKG1ldGhvZCA9ICJsb2VzcyIsY29sPSJyZWQiKSArICMgZml0IGVlbiBrcm9tbWUgZG9vciBkZSBwdW50ZW4gKHJvZGUgbGlqbikKICBzdGF0X3Ntb290aChtZXRob2Q9J2xtJyxjb2w9ImJsYWNrIikgKyAjIGZpdCBlZW4gcmVjaHRlIGRvb3IgZGUgcHVudGVuIGFhbiBkZSBoYW5kIHZhbiBkZSBrbGVpbnN0ZWt3YWRyYXRlbm1ldGhvZGUKICB5bGFiKCJSZWFjdGllc25lbGhlaWQgKGNvdW50cy9taW4pIikgKwogIHhsYWIoImxvZzEwKFN1YnN0cmFhdGNvbmNlbnRyYXRpZSAocHBtKSkiKSArCiAgdGhlbWVfYncoKQpgYGAKCkhldCB2ZXJiYW5kIHR1c3NlbiBkZSByZWFjdGllc25lbGhlaWQgZW4gaGV0IGxvZ2FyaXRtZSB2YW4gZGUgc3Vic3RyYWF0Y29uY2VudHJhdGllIGxpamt0IGxpbmVhaXIuIFdlIHp1bGxlbiBkZSByZWFjdGllc25lbGhlaWQgZHVzIHZlcmRlciBtb2RlbGxlcmVuIGluIGZ1bmN0aWUgdmFuIGRlIGxvZyRfezEwfSQtc3Vic3RyYWF0Y29uY2VudHJhdGllLgoKIyBFbmtlbHZvdWRpZ2UgbGluZWFpcmUgcmVncmVzc2llCgpFbmtlbHZvdWRpZ2UgbGluZWFpcmUgcmVncmVzc2llIGlzIGVlbiByZWdyZXNzaWUgd2FhcmJpaiBlZW4gdmFyaWFiZWxlIGdlbW9kZWxsZWVyZCB3b3JkdCBpbiBmdW5jdGllIHZhbiBzbGVjaHRzIDEgdmFyaWFiZWxlLiBEZSB2ZXJ3YWNodHRlIHJlYWN0aWVzbmVsaGVpZCB3b3JkdCBkdXMgJEVbWV9pXSA9IFxiZXRhXzAgKyBcYmV0YV8xWF9pJC4gSW4gZGl0IGdldmFsIGlzICRZJCBkZSByZWFjdGllc25lbGhlaWQgZW4gJFgkIGRlIGxvZzEwLXN1YnN0cmFhdGNvbmNlbnRyYXRpZS4KCkhldCBtb2RlbCB3b3JkdCBkYW4gYWxzIHZvbGd0OgokcmVhY3RpZXNuZWxoZWlkX2kgPSBcYmV0YV8wICsgXGJldGFfMSBsb2dfezEwfShjb25jZW50cmF0aWVfaSkgKyBcZXBzaWxvbl9pJAoKbWV0ICRcYmV0YV8wJCBoZXQgKHdlcmtlbGlqa2UpICoqaW50ZXJjZXB0KiosICRcYmV0YV8xJCBkZSAod2Vya2VsaWprZSkgKipoZWxsaW5nKiogb2YgbWVlciBzcGVjaWZpZWsgaGV0ICh3ZXJrZWxpamspICoqZWZmZWN0IHZhbiBsb2cxMChjb25jZW50cmF0aWUpIG9wIGRlIGdlbWlkZGVsZGUgcmVhY3RpZXNuZWxoZWlkKiouIERlemUgcGFyYW1ldGVycyBnYWFuIHdlIHNjaGF0dGVuLgoKJFxlcHNpbG9uX2kkIGlzIGVlbiBmb3V0dGVybSAoImVycm9yIHRlcm0iKSwgd2FhcmJpaiAkXGVwc2lsb25faSQgaS5pLmQuIG5vcm1hYWwgdmVyZGVlbGQgemlqbiBtZXQgZ2VtaWRkZWxkZSAwIGVuIChjb25zdGFudGUpIHZhcmlhbnRpZSAkXHNpZ21hXjIkLgoKIyMgQXNzdW1wdGllcwoKVm9vcmRhdCB3ZSBjb25jbHVzaWVzIGt1bm5lbiB0cmVra2VuIHVpdCBoZXQgbGluZWFpcmUgcmVncmVzc2llbW9kZWwgbW9ldGVuIHdlIG5hZ2FhbiBvZiBlciBhYW4gZGUgYXNzdW1wdGllcyB2b2xkYWFuIHppam4uIFZvb3IgZGUgbGluZWFpcmUgcmVncmVzc2llIHppam4gZGF0IHZvbGdlbmRlIGFzc3VtcHRpZXM6CgogMS4gT25hZmhhbmtlbGlqa2UgZ2VnZXZlbnMKIDIuIExpbmVhcml0ZWl0IHR1c3NlbiByZXNwb25zIGVuIHByZWRpY3RvciAoaW1wbGljZWVydCBkYXQgcmVzaWR1ZW4gcm9uZCBudWwgdmVyZGVlbGQgemlqbiwgem9uZGVyIG1lcmtiYWFyIHJlc3RlcmVuZCBwYXRyb29uIHR1c3NlbiBkZSByZXNpZHVlbiBlbiBkZSBnZXNjaGF0dGUgcmVzcG9ucyB2YXJpYWJlbGUpCiAzLiBOb3JtYWFsIHZlcmRlZWxkZSByZXNpZHVlbgogNC4gR2VsaWprZSB2YXJpYW50aWUgKGhvbW9zY2VkYXN0aWNpdGVpdCkKIAogT25hZmhhbmtlbGlqa2UgZ2VnZXZlbnMgbW9ldGVuIHdlIHZlcm9uZGVyc3RlbGxlbiB1aXQgaGV0IGV4cGVyaW1lbnRlZWwgZGVzaWduLiBEZSBhbmRlcmUgYXNzdW1wdGllcyBtb2V0ZW4gd2UgY29udHJvbGVyZW4uCiAKIyMjIExpbmVhcml0ZWl0IHR1c3NlbiByZWFjdGllc25lbGhlaWQgZW4gbG9nJF97MTB9JChzdWJzdHJhYXRjb25jZW50cmF0aWUpOgoKWm9hbHMgaGllcmJvdmVuIGJlc3Byb2tlbiBsaWprdCBoZXQgZGF0IGVyIGVlbiBsaW5lYWlyZSB0cmVuZCBpcyB0dXNzZW4gcmVhY3RpZXNuZWxoZWlkIGVuIGxvZyRfezEwfSQoc3Vic3RyYWF0Y29uY2VudHJhdGllKSBpbiBoZXQgdm9sbGVkaWdlIGJlcmVpayB2YW4gZGUgZGF0YS4gCgpEZSBsaW5lYXJpdGVpdHNhc3N1bXB0aWUgaW1wbGljZWVydCBkYXQgZGUgcmVzaWR1ZW4gd2lsbGVrZXVyaWcgcm9uZCBudWwgdmVyZGVlbGQgemlqbiwgb25hZmhhbmtlbGlqayB2YW4gd2FhciB3ZSBvbnMgb3AgZGUgcmVjaHRlIGJldmluZGVuLiBEaXQga3VubmVuIHdlIHdlZXJnZXZlbiBkb29yIGVlbiBsaW5lYWlyIG1vZGVsIHRlIGZpdHRlbiBvcCBkZSBkYXRhIGVuIGRlIHJlc2lkdWVuIG1ldCBlZW4gc21vb3RoZXIgd2VlciB0ZSBnZXZlbiBpbiBmdW5jdGllIHZhbiBkZSBnZWZpdHRlIHJlc3BvbnN3YWFyZGVuLiAKCmBgYHtyfQptb2RlbCA8LSBsbShyYXRlfmxvZzEwKGNvbmMpLGRhdGEgPSBQdXJvbXljaW4pIAptb2RlbApwbG90KG1vZGVsLHdoaWNoPTEpCmBgYCAKCkVyIGxpamtlbiBrbGVpbmUgYWZ3aWpraW5nZW4gdGUgemlqbiBiaWogZGUgcmVzaWR1ZW4gdmFuIGhvZ2VyZSBnZWZpdHRlZCB3YWFyZGVuLiBFciB6aWpuIGVjaHRlciBuaWV0IHpvdmVlbCBvYnNlcnZhdGllcyBvcGdlbm9tZW4gaW4gZGUgc3R1ZGllIGVuIGRlIHNtb290aGVyIGdlZWZ0IHNvd2llc28gb25uYXV3a2V1cmlnIHNjaGF0dGluZ2VuIG9wIGRlIGVpbmRwdW50ZW4gdmFuIGhldCBiZXJlaWsuIAoKT20gbmEgdGUgZ2FhbiBvZiBkZSBhZndpamtpbmdlbiBkaWUgd2UgemllbiBpbmRlcmRhYWQgcGxhdWNpYmVsIHppam4gZW4ga3VubmVuIHdvcmRlbiB2ZXJvb3J6YWFrdCBkb29yIHJhbmRvbSB2YXJpYWJpbGl0ZWl0IGt1bm5lbiB3ZSBnZWJydWlrIG1ha2VuIHZhbiBzaW11bGF0aWVzIHdhYXJ1aXQgd2UgZGUgZGF0YSBnZW5lcmVyZW4gb25kZXIgZGUgdm9vcndhYXJkZW4gdmFuIGhldCBsaW5lYWlyZSBtb2RlbC4gCgpXZSBzaW11bGVyZW4gOSBkYXRhc2V0cyBtZXQgaGV0emVsZmRlIGFhbnRhbCBvYnNlcnZhdGllcywgcHJlZGljdG9yd2FhcmRlbiwgaW50ZXJjZXB0LCBoZWxsaW5nIGVuIHN0YW5kYWFyZGRldmlhdGllLiAKV2UgZml0dGVuIGRlIG1vZGVsbGVuIGVuIG1ha2VuIGRlIHJlc2lkdXBsb3QuIAoKYGBge3J9CnNldC5zZWVkKDEwMzEpCmJldGFzIDwtIG1vZGVsICU+JSBjb2VmZmljaWVudHMKc2lnbWEgPC0gbW9kZWwgJT4lIHNpZ21hIAoKc2ltTW9kZWxzIDwtIGxpc3QoKQoKcGFyKG1mcm93PWMoMywzKSkKZm9yIChpIGluIDE6OSkKewogIHggPC0gUHVyb215Y2luICU+JSBwdWxsKCJjb25jIikgJT4lIGxvZzEwCiAgbm9icyA8LSBQdXJvbXljaW4gJT4lIG5yb3cKICB5IDwtIGJldGFzWzFdICsgYmV0YXNbMl0gKiB4ICsgcm5vcm0obm9icywgc2QgPSBzaWdtYSkKICBzaW1Nb2RlbHNbW2ldXSA8LSBsbSh5fngpCiAgcGxvdChzaW1Nb2RlbHNbW2ldXSwgd2hpY2ggPSAxKQp9CmBgYAoKIyMjIE5vcm1hYWwgdmVyZGVlbGRlIHJlc2lkdWVuCgpXZSBnYWFuIHZpYSBlZW4gcXEtcGxvdCBuYSBvZiBkZSByZXNpZHVlbiBub3JtYWFsIHZlcmRlZWxkIHppam4uCgpgYGB7cn0KcGxvdChtb2RlbCx3aGljaD0yKQpgYGAKCldlIHppZW4gZGF0IGVyIGdlZW4gc3lzdGVtYXRpc2NoZSBhZndpamtpbmdlbiB6aWpuIHZhbiBub3JtYWxpdGVpdCwgZW4ga3VubmVuIHZlcm9uZGVyc3RlbGxlbiBkYXQgZGUga2xlaW5lIGFmd2lqa2luZ2VuIGRvb3IgdG9ldmFsbGlnZSBzdGVla3Byb2VmdmFyaWFiaWxpdGVpdCBrb21lbi4KCiMjIyBHZWxpamtlIHZhcmlhbnRpZSAoaG9tb3NjZWRhc3RpY2l0ZWl0KQoKQmlqIGxpbmVhaXJlIHJlZ3Jlc3NpZSB3aWwgZGUgYXNzdW1wdGllIHZhbiBnZWxpamtoZWlkIHZhbiB2YXJpYW50aWUgemVnZ2VuIGRhdCBkZSB2YXJpYW50aWUgdmFuIGRlIHJlc2lkdWVuIHJvbmQgZGUgcmVncmVzc2llcmVjaHRlIGhldHplbGZkZSBpcyB2b29yIGVsa2Ugd2FhcmRlIHZhbiBkZSBwcmVkaWN0b3IgKHByZWRpY3RvcnBhdHJvb24pLiAKCldlIGt1bm5lbiBkaXQgb3BuaWV1dyBuYWdhYW4gbWV0IGRlIHJlc2lkdS1wbG90LiBEZSBzcHJlaWRpbmcgdmFuIGRlIHJlc2lkdWVuIHpvdSBtaW4gb2YgbWVlciBnZWxpamsgbW9ldGVuIHppam4gdm9vciBlbGtlIGdlZml0dGUgd2FhcmRlLiAKCkVlbiBhbmRlcmUgcGxvdCBkaWUgd2UgaGllcnZvb3Iga3VubmVuIGdlYnJ1aWtlbiBpcyBlZW4gcGxvdCB3YWFyIHdlIGRlIHZpZXJrYW50c3dvcnRlbCB2YW4gZGUgYWJzb2x1dGUgd2FhcmRlIHZhbiBkZSBnZXN0YW5kYWFyZGlzZWVyZGUgcmVzaWR1ZW4gcGxvdHRlbiBpbiBmdW5jdGllIHZhbiBkZSBnZWZpdHRlIHdhYXJkZW4uIEFscyB3ZSBoaWVyIGVlbiBzbW9vdGhlciBkb29yIHRyZWtrZW4sIHpvdSBkZSBzbW9vdGhlciBlZW4gaG9yaXpvbnRhYWwgdmVybG9vcCBtb2V0ZW4gaGViYmVuLiBJbmRpZW4gZXIgYWZ3aWpraW5nZW4gem91ZGVuIHppam4sIGJ2LiBlciBpcyBlZW4gc3lzdGVtYXRpc2NoZSB0cmVuZCB3YWFyYmlqIGRlIGdlc3RhbmRhYXJkaXNlZXJkZSByZXNpZHVlbiBob2dlci9sYWdlciB3b3JkZW4gbmFhcm1hdGUgZGUgKmZpdHRlZCB2YWx1ZXMqIGhvZ2VyL2xhZ2VyIHdvcmRlbiwgZGFuIGJldGVrZW50IGhldCBkYXQgZGUgdmFyaWFudGllIHZhbiBkZSByZXNpZHVlbiBob2dlci9sYWdlciB3b3JkdCBuYWFybWF0ZSBkZSBnZXNjaGF0dGUgcmVzcG9ucyBob2dlci9sYWdlciB3b3JkdC4KCmBgYHtyfQpwbG90KG1vZGVsLHdoaWNoPTMpCmBgYAoKSGllciB6aWVuIHdlIGtsZWluZSBhZndpamtpbmdlbiB2YW4gZWVuIGhvcml6b250YWxlIGxpam4gYmlqIGRlIHVpdGVyc3RlIHdhYXJkZW4uIFZpYSBzaW11bGF0aWUgemllbiB3ZSBvcG5pZXV3IGRhdCBkZXplIGFmd2lqa2luZ2VuIHBsYXVjaWJlbCB6aWpuIGluIGVlbiBleHBlcmltZW50IG1ldCBvbnMgZGVzaWduIHdhbm5lZXIgYWxsZSBhYW5uYW1lcyBnZWxkaWcgemlqbi4gCgpgYGB7cn0KcGFyKG1mcm93ID0gYygzLDMpKQpmb3IgKGkgaW4gMTo5KQogIHBsb3Qoc2ltTW9kZWxzW1tpXV0sIHdoaWNoID0gMykKYGBgCgpXZSBrdW5uZW4gZHVzIHZlcm9uZGVyc3RlbGxlbiBkdXMgZGF0IGRlIHZhcmlhbnRpZXMgZ2VsaWprIHppam4uCgoKCgojIyBOdWwtIGVuIGFsdGVybmF0aWV2ZSBoeXBvdGhlc2U6CgpXZSB3aWxsZW4gd2V0ZW4gb2YgZXIgZWVuIGxpbmVhaXJlIGFzc29jaWF0aWUgaXMgdHVzc2VuIGRlIHJlYWN0aWVzbmVsaGVpZCBlbiBkZSBsb2ckX3sxMH0kIGdldHJhbnNmb3JtZWVyZGUgY29uY2VudHJhdGllLiAKCkRlIG51bC0gZW4gYWx0ZXJuYXRpZXZlIGh5cG90aGVzZSB2YW4gaGV0IGxpbmVhaXIgbW9kZWwgd29yZGVuIGR1czoKCiRIXzAkOiAkXGJldGFfMSA9IDAkCiAKJEhfQSQ6ICRcYmV0YV8xIFxuZSAwJCAKCk1ldCBhbmRlcmUgd29vcmRlbiBzdGVsdCBkZSBudWxoeXBvdGhlc2UgZGF0IGVyIGdlZW4gYXNzb2NpYXRpZSBpcyB0dXNzZW4gZGUgcmVhY3RpZXNuZWxoZWlkIGVuIGRlIGxvZyRfezEwfSQgY29uY2VudHJhdGllLCB0ZXJ3aWpsIGRlIGFsdGVybmF0aWV2ZSBoeXBvdGhlc2Ugc3RlbHQgZGF0IGVyIGp1aXN0IHdlbCBlZW4gYXNzb2NpYXRpZSBpcy4KCiMjIEZpdCBoZXQgbGluZWFpciBtb2RlbCBlbiBiZXNwcmVlayBiZWlkZSBwYXJhbWV0ZXJzLCBnYSBuYSBvZiBkZSBudWxoeXBvdGhlc2UgdmVyd29ycGVuIHdvcmR0IGVuIG1hYWsgZWVuIGludGVycHJldGF0aWUgdmFuIGhldCBiZXRyb3V3YmFhcmhlaWRzaW50ZXJ2YWwuCgpgYGB7cn0Kc3VtbWFyeU1vZGVsIDwtIHN1bW1hcnkobW9kZWwpCnN1bW1hcnlNb2RlbAoKYGBgCgpgYGB7cn0KY29uZmludE1vZGVsIDwtIGNvbmZpbnQobW9kZWwpCmNvbmZpbnRNb2RlbApgYGAKCiMjIyBDb25jbHVzaWUgCgpFciBpcyBlZW4gZXh0cmVlbSBzaWduaWZpY2FudGUgbGluZWFpcmUgYXNzb2NpYXRpZSB0dXNzZW4gZGUgc3Vic3RyYWF0Y29uY2VudHJhdGllIG9wIGxvZ3NjaGFhbCBlbiBkZSByZWFjdGllc25lbGhlaWQgKHAgPDwgMC4wMDEpLiBXYW5uZWVyIHdlIGRlIHJlYWN0aWUgbGF0ZW4gZG9vcmdhYW4gYmlqIGVlbiBzdWJzdHJhYXRjb25jZW50cmF0aWUgZGllIDEwIGtlZXIgaG9nZXIgaXMsIGlzICBkZSByZWFjdGllc25lbGhlaWQgZ2VtaWRkZWxkIG1ldCBgciByb3VuZChtb2RlbCRjb2VmWzJdLDEpYCBjb3VudHMvbWluIGhvZ2VyICg5NSUgYmV0cm91d2JhYXJoZWlkc2ludGVydmFsIFtgciByb3VuZChjb25maW50TW9kZWxbMl0sMSlgLCBgciByb3VuZChjb25maW50TW9kZWxbNF0sMSlgXSBjb3VudHMvbWluKS4gCgoKIyMjIEludGVycHJldGF0aWUgCgoxLiBIZXQgaW50ZXJjZXB0IGlzIGRlIGdlc2NoYXR0ZSBnZW1pZGRlbGRlIHJlYWN0aWVzbmVsaGVpZCBiaWogZWVuIGxvZyRfezEwfSQtY29uY2VudHJhdGllIHZhbiAwL2VlbiBzdWJzdHJhYXQgY29uY2VudHJhdGllIHZhbiAxIHBwbSBlbiBpcyBnZWxpamsgYWFuIGByIHJvdW5kKG1vZGVsJGNvZWZmaWNpZW50c1sxXSwxKWAgY291bnRzL21pbi4KCjIuIEhlbGxpbmcKICAKICAtIExvZyBzY2hhYWw6ICBXYW5uZWVyIHdlIGRlIHJlYWN0aWUgbGF0ZW4gZG9vcmdhYW4gYmlqIGVlbiBzdWJzdHJhYXRjb25jZW50cmF0aWUgZGllIDEgZWVuaGVpZCBvcCBsb2ckX3sxMH0kIHNjaGFhbCBob2dlciBpcywgaXMgIGRlIHJlYWN0aWVzbmVsaGVpZCBnZW1pZGRlbGQgbWV0IGByIHJvdW5kKG1vZGVsJGNvZWZbMl0sMSlgIGNvdW50cy9taW4gaG9nZXIuCiAgCiAgLSBPcmlnaW5lbGUgc2NoYWFsOiBXYW5uZWVyIHdlIGRlIHJlYWN0aWUgbGF0ZW4gZG9vcmdhYW4gYmlqIGVlbiBzdWJzdHJhYXRjb25jZW50cmF0aWUgZGllIDEwIGtlZXIgaG9nZXIgaXMsIGlzICBkZSByZWFjdGllc25lbGhlaWQgZ2VtaWRkZWxkIG1ldCBgciByb3VuZChtb2RlbCRjb2VmWzJdLDEpYCBjb3VudHMvbWluIGhvZ2VyLgoKMy4gOTUlIGJldHJvdXdiYWFyaGVpZHNpbnRlcnZhbDogV2UgaGViYmVuIGR1cyBnZXNjaGF0IGRhdCBoZXQgd2Vya2VsaWprZSB2ZXJzY2hpbCBpbiByZWFjdGllc25lbGhlaWQgdHVzc2VuIHR3ZWUgcmVhY3RpZXMgZGllIGRvb3JnYWFuIG9uZGVyIGVlbiBzdWJzdHJhYXRjb25jZW50cmF0aWUgZGllIGVlbiBmYWN0b3IgMTAgdmVyc2NoaWxsZW4gbWV0IDk1JSBrYW5zIGxpZ3QgdHVzc2VuICBbYHIgcm91bmQoY29uZmludE1vZGVsWzJdLDEpYCwgYHIgcm91bmQoY29uZmludE1vZGVsWzRdLDEpYF0gY291bnRzL21pbjsgbWVyayBvcCBkYXQgZGUgcmVhY3RpZSBzbmVsbGVyIGRvb3JnYWF0IGluIGRlIHJlYWN0aWUgbWV0IGRlIGhvb2dzdGUgc3Vic3RyYWF0Y29uY2VudHJhdGllLiAKIAojIyBTY2hhdCBkZSBnZW1pZGRlbGRlIHJlYWN0aWVzbmVsaGVpZCBiaWogZWVuIHN1YnN0cmFhdCBjb25jZW50cmF0aWUgdmFuIDAuMnBwbSBlbiBnZWVmIGVlbiBiaWpob3JlbmQgOTUlLWJldHJvdXdiYWFyaGVpZHNpbnRlcnZhbC4KCmBgYHtyfQpwcmVkIDwtIHByZWRpY3QobW9kZWwsIG5ld2RhdGE9ZGF0YS5mcmFtZShjb25jPTAuMiksIGludGVydmFsPSJjb25maWRlbmNlIikKcHJlZApgYGAKCkRlIGdlc2NoYXR0ZSBnZW1pZGRlbGRlIHJlYWN0aWVzbmVsaGVpZCBiaWogZWVuIHN1YnN0cmFhdGNvbmNlbnRyYXRpZSB2YW4gMTAgcHBtICBpcyBgciByb3VuZChwcmVkWzFdLDEpYCBjb3VudHMvbWluICg5NSUgYmV0cm91d2JhYXJoZWlkc2ludGVydmFsIFtgciByb3VuZChwcmVkWzI6M10sMSlgXSBjb3VudHMvbWluKS4KCiMgQWxnZW1lbmUgY29uY2x1c2llCgpFciBpcyBlZW4gZXh0cmVlbSBzaWduaWZpY2FudGUgbGluZWFpcmUgYXNzb2NpYXRpZSB0dXNzZW4gZGUgc3Vic3RyYWF0Y29uY2VudHJhdGllIG9wIGxvZ3NjaGFhbCBlbiBkZSByZWFjdGllc25lbGhlaWQgKHAgPDwgMC4wMDEpLiBXYW5uZWVyIHdlIGRlIHJlYWN0aWUgbGF0ZW4gZG9vcmdhYW4gYmlqIGVlbiBzdWJzdHJhYXRjb25jZW50cmF0aWUgZGllIDEwIGtlZXIgaG9nZXIgaXMsIGlzICBkZSByZWFjdGllc25lbGhlaWQgZ2VtaWRkZWxkIG1ldCBgciByb3VuZChtb2RlbCRjb2VmWzJdLDEpYCBjb3VudHMvbWluIGhvZ2VyICg5NSUgYmV0cm91d2JhYXJoZWlkc2ludGVydmFsIFtgciByb3VuZChjb25maW50TW9kZWxbMl0sMSlgLCBgciByb3VuZChjb25maW50TW9kZWxbNF0sMSlgXSBjb3VudHMvbWluKS4gCgoKCg==