Last update: 2020-06-01 01:34:37

Intro

Our objective is to estimate the survival distribution of patients in the presence of censoring.

Time-to-event

In survival analysis the time until the occurrence of a well-defined event is recorded (time-to-event data). “Survival time”.

If everyone had an event, some of the methods we have already learned could be applied.

Often, not everyone has event (censoring) - Loss to follow-up - End of study

Censoring

Subjects are said to be censored if they are lost to follow up or drop out of the study, or if they die of unrelated causes or the study ends before they have the event of interest. They are counted as alive or disease-free for the time they were enrolled in the study. 10

Survival Analysis

Two-variable outcome:

Time variable \((T)\): is a random variable denoting the time of the event. \(t_i\) is the time at last event-free observation or just before the event, is a random variable having a probability distribution. Being this, the Survival function is the probability that the time of the event \((T)\) is later than some specified time \(t\). Formula 1.1

Censoring variable \((C)\): \(c_i\) = 1 if had the event; \(c_i\) = 0 no event by time \(t_i\)

Different models for survival data are distinguished by different choice of distribution for \(t_i\).

The object of primary interest is the survival function, conventionally denoted S, which is defined as

\[ S(t)=\Pr(T>t) \tag{1.1} \]

Let \(T\) be survival time, which is any positive number. A particular time is designated by the lower case letter \(t\). The cumulative distribution function (or lifetime distribution function) of \(T\) is the function, conventionally denoted \(F\), defined as the complement of the survival function.

\[ F(t)=\Pr(T \leq t)= 1 - S(t) \tag{2.1} \] If \(F\) is differentiable then the first derivative, which is the density function of the lifetime distribution, is conventionally denoted \(f\). The function \(f\) is sometimes called the event density; it is the rate of death or failure events per unit time.

\[f(t)=F'(t)={\frac{d}{dt}}F(t) \tag{3.1}\]

Back to the survival function (1.1), it can be expressed in terms of probability distribution and probability density functions

\[S(t)=\Pr(T>t)=\int _{t}^{{\infty }}f(u)\,du=1-F(t) \tag{4.1}\]

Similarly, a survival event density function can be defined as

\[s(t)=S'(t)={\frac {d}{dt}}S(t)={\frac {d}{dt}}\int _{t}^{{\infty }}f(u)\,du={\frac {d}{dt}}[1-F(t)]=-f(t) \tag{4.2}\]

Hazard function and cumulative hazard function

The hazard function, conventionally denoted , is defined as the event rate at time \(t\) conditional on survival until time \(t\) or later (that is, \(T ≥ t\)). Suppose that an item has survived for a time \(t\) and we desire the probability that it will not survive for an additional time \(dt\):

\[ {\lambda (t)=\lim _{dt\rightarrow 0}{\frac {\Pr(t\leq T<t+dt)}{dt\cdot S(t)}}={\frac {f(t)}{S(t)}}=-{\frac {S'(t)}{S(t)}}} \tag{4.1} \]

Example

library(readr)
library(tidyr)
library(splines2)
library(survival)
library(survminer)

Kaplan-Meier

data_test <- read_delim("data2.csv", ";",
  escape_double = FALSE,
  locale = locale(decimal_mark = ",", grouping_mark = "."),
  trim_ws = TRUE
)
Parsed with column specification:
cols(
  id = col_double(),
  fu = col_double(),
  event = col_double(),
  event_HD = col_double(),
  event_RT = col_double(),
  event_CR = col_double(),
  peritonitis = col_double(),
  sex = col_double(),
  age = col_double(),
  diab = col_double(),
  first = col_double()
)
km <- survfit(Surv(fu, event) ~ 1, data = data_test)
wb <- survreg(Surv(fu, event) ~ 1, data = data_test)

ggsurvplot(km, conf.int = TRUE, risk.table = "nrisk_cumevents", legend = "none", tables.height = 0.2)

km2 <- survfit(Surv(time, cens) ~ 1, data = GBSG2)
ggsurvplot(km2, palette = "blue", conf.int = TRUE, risk.table = "nrisk_cumevents", surv.median.line = "hv", tables.height = 0.3)

Weibull model

# weibull approximation
wb2 <- survreg(Surv(time, cens) ~ 1, data = GBSG2)
surv <- seq(.99, .01, by = -0.1)
t <- predict(wb2, type = "quantile", p = 1 - surv, newdata = data.frame(1))
surv_wb <- data.frame(time = t, surv = surv, upper = NA, lower = NA, std.err = NA)
ggsurvplot_df(fit = surv_wb, surv.geom = geom_line)



# weibull approximation with covariants
# Compute the Weibull model
wbmod <- survreg(Surv(time, cens) ~ horTh + tsize, data = GBSG2)

# Decide on "imaginary patients"
newdat <- expand.grid(
  horTh = levels(GBSG2$horTh),
  tsize = quantile(GBSG2$tsize, probs = c(0.25, 0.5, 0.75))
)

# Compute survival curves
surv <- seq(.99, .01, by = -0.1)
t <- predict(wbmod, type = "quantile", p = 1 - surv, newdata = newdat)
surv_wbmod_wide <- cbind(newdat, t)

# Create data.frame with survival curve information
surv_wbmod <- pivot_longer(surv_wbmod_wide, -(horTh:tsize), names_to = "surv_id", values_to = "time")
surv_wbmod$surv <- surv[as.numeric(surv_wbmod$surv_id)]
surv_wbmod[, c("upper", "lower", "std.err", "strata")] <- NA
surv_wbmod <- as.data.frame(surv_wbmod) # survplot bug

# plot
ggsurvplot_df(surv_wbmod, surv.geom = geom_line, linetype = "horTh", color = "tsize", legend.title = NULL)

Cox Model


# Compute the cox model
cxmod <- coxph(Surv(time, cens) ~ horTh + tsize, data = GBSG2)

# Decide on covariate combinations ("imaginary patients")
newdat <- expand.grid(
  horTh = levels(GBSG2$horTh),
  tsize = quantile(GBSG2$tsize, probs = c(0.25, 0.5, 0.75))
)
rownames(newdat) <- letters[1:6]

# Compute survival curves
cxsf <- survfit(cxmod, data = GBSG2, newdata = newdat, conf.type = "none")

# Create data.frame with survival curve information

surv_cxmod0 <- surv_summary(cxsf)
surv_cxmod <- cbind(surv_cxmod0, newdat[as.character(surv_cxmod0$strata), ])

# Plot
ggsurvplot_df(surv_cxmod, linetype = "horTh", color = "tsize",
              legend.title = NULL, censor = FALSE)

LS0tCnRpdGxlOiAiSEVBRFMgLSBISURBIC0gU1RBVFMgLSBTdXJ2aXZhbCBBbmFseXNpcyIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICBoaWdobGlnaHQ6IHB5Z21lbnRzCiAgICB0aGVtZTogdW5pdGVkCiAgICB0b2M6IHllcwphdXRob3I6IEZyYW5jaXNjbyBCaXNjaG9mZgotLS0KCkxhc3QgdXBkYXRlOiBgciBsdWJyaWRhdGU6Om5vdygpYAoKIyMgSW50cm8KCk91ciBvYmplY3RpdmUgaXMgdG8gZXN0aW1hdGUgdGhlIHN1cnZpdmFsIGRpc3RyaWJ1dGlvbiBvZiBwYXRpZW50cyBpbiB0aGUgcHJlc2VuY2Ugb2YgY2Vuc29yaW5nLgoKIC0gV2h5IG5vdCBjb21wYXJlIG1lYW4gdGltZS10by1ldmVudCBiZXR3ZWVuIGdyb3VwcyB1c2luZyBhIHQtdGVzdCBvciBsaW5lYXIgcmVncmVzc2lvbj8KICAgLSBJZ25vcmVzIGNlbnNvcmluZwoKIC0gV2h5IG5vdCBjb21wYXJlIHByb3BvcnRpb24gb2YgZXZlbnRzIGluIGdyb3VwcyB1c2luZyByaXNrL29kZHMgcmF0aW9zIG9yIGxvZ2lzdGljIHJlZ3Jlc3Npb24/CiAgIC0gSWdub3JlcyB0aW1lCgojIyBUaW1lLXRvLWV2ZW50CgpJbiBzdXJ2aXZhbCBhbmFseXNpcyB0aGUgdGltZSB1bnRpbCB0aGUgb2NjdXJyZW5jZSBvZiBhIHdlbGwtZGVmaW5lZCBldmVudCBpcyByZWNvcmRlZCAodGltZS10by1ldmVudCBkYXRhKS4gIlN1cnZpdmFsIHRpbWUiLgoKSWYgZXZlcnlvbmUgaGFkIGFuIGV2ZW50LCBzb21lIG9mIHRoZSBtZXRob2RzIHdlIGhhdmUgYWxyZWFkeSBsZWFybmVkIGNvdWxkIGJlIGFwcGxpZWQuCgpPZnRlbiwgbm90IGV2ZXJ5b25lIGhhcyBldmVudCAoY2Vuc29yaW5nKQogLSBMb3NzIHRvIGZvbGxvdy11cAogLSBFbmQgb2Ygc3R1ZHkKCiMjIENlbnNvcmluZwoKU3ViamVjdHMgYXJlIHNhaWQgdG8gYmUgY2Vuc29yZWQgaWYgdGhleSBhcmUgbG9zdCB0byBmb2xsb3cgdXAgb3IgZHJvcCBvdXQgb2YgdGhlIHN0dWR5LCBvciBpZiB0aGV5IGRpZSBvZiB1bnJlbGF0ZWQgY2F1c2VzIG9yIHRoZSBzdHVkeSBlbmRzIGJlZm9yZSB0aGV5IGhhdmUgdGhlIGV2ZW50IG9mIGludGVyZXN0LiBUaGV5IGFyZSBjb3VudGVkIGFzIGFsaXZlIG9yIGRpc2Vhc2UtZnJlZSBmb3IgdGhlIHRpbWUgdGhleSB3ZXJlIGVucm9sbGVkIGluIHRoZSBzdHVkeS4KMTAKCiMjIFN1cnZpdmFsIEFuYWx5c2lzCgpUd28tdmFyaWFibGUgb3V0Y29tZTogCgpUaW1lIHZhcmlhYmxlICQoVCkkOiBpcyBhICpyYW5kb20gdmFyaWFibGUqIGRlbm90aW5nIHRoZSB0aW1lIG9mIHRoZSBldmVudC4gJHRfaSQgaXMgdGhlIHRpbWUgYXQgbGFzdCBldmVudC1mcmVlIG9ic2VydmF0aW9uIG9yIGp1c3QgYmVmb3JlIHRoZSBldmVudCwgaXMgYSByYW5kb20gdmFyaWFibGUgaGF2aW5nIGEgcHJvYmFiaWxpdHkgZGlzdHJpYnV0aW9uLiBCZWluZyB0aGlzLCB0aGUgU3Vydml2YWwgZnVuY3Rpb24gaXMgdGhlIHByb2JhYmlsaXR5IHRoYXQgdGhlIHRpbWUgb2YgdGhlIGV2ZW50ICQoVCkkIGlzIGxhdGVyIHRoYW4gc29tZSBzcGVjaWZpZWQgdGltZSAkdCQuIEZvcm11bGEgWzEuMV0oKQoKQ2Vuc29yaW5nIHZhcmlhYmxlICQoQykkOiAkY19pJCA9IDEgaWYgaGFkIHRoZSBldmVudDsgJGNfaSQgPSAwIG5vIGV2ZW50IGJ5IHRpbWUgJHRfaSQKCgpEaWZmZXJlbnQgbW9kZWxzIGZvciBzdXJ2aXZhbCBkYXRhIGFyZSBkaXN0aW5ndWlzaGVkIGJ5IGRpZmZlcmVudCBjaG9pY2Ugb2YgZGlzdHJpYnV0aW9uIGZvciAkdF9pJC4KCgoKClRoZSBvYmplY3Qgb2YgcHJpbWFyeSBpbnRlcmVzdCBpcyB0aGUgc3Vydml2YWwgZnVuY3Rpb24sIGNvbnZlbnRpb25hbGx5IGRlbm90ZWQgUywgd2hpY2ggaXMgZGVmaW5lZCBhcwoKJCQKUyh0KT1cUHIoVD50KSBcdGFnezEuMX0KJCQKCkxldCAkVCQgYmUgc3Vydml2YWwgdGltZSwgd2hpY2ggaXMgYW55IHBvc2l0aXZlIG51bWJlci4gQSAqcGFydGljdWxhciB0aW1lKiBpcyBkZXNpZ25hdGVkIGJ5IHRoZSAqbG93ZXIgY2FzZSBsZXR0ZXIqICR0JC4gVGhlICoqY3VtdWxhdGl2ZSBkaXN0cmlidXRpb24gZnVuY3Rpb24qKiAob3IgKmxpZmV0aW1lIGRpc3RyaWJ1dGlvbiBmdW5jdGlvbiopIG9mICRUJCBpcyB0aGUgZnVuY3Rpb24sIGNvbnZlbnRpb25hbGx5IGRlbm90ZWQgJEYkLCBkZWZpbmVkIGFzIHRoZSBjb21wbGVtZW50IG9mIHRoZSBzdXJ2aXZhbCBmdW5jdGlvbi4KCi0gVGhlICoqY3VtdWxhdGl2ZSBkaXN0cmlidXRpb24gZnVuY3Rpb24qKiBvZiAkVCQKCiQkCkYodCk9XFByKFQgXGxlcSB0KT0gMSAtIFModCkgXHRhZ3syLjF9CiQkCklmICRGJCBpcyBkaWZmZXJlbnRpYWJsZSB0aGVuIHRoZSBmaXJzdCBkZXJpdmF0aXZlLCB3aGljaCBpcyB0aGUgKipkZW5zaXR5IGZ1bmN0aW9uIG9mIHRoZSBsaWZldGltZSBkaXN0cmlidXRpb24qKiwgaXMgY29udmVudGlvbmFsbHkgZGVub3RlZCAkZiQuClRoZSBmdW5jdGlvbiAkZiQgaXMgc29tZXRpbWVzIGNhbGxlZCB0aGUgKipldmVudCBkZW5zaXR5Kio7IGl0IGlzIHRoZSAqKnJhdGUgb2YgZGVhdGggb3IgZmFpbHVyZSBldmVudHMgcGVyIHVuaXQgdGltZSoqLgoKLSBEZW5zaXR5IGZ1bmN0aW9uIG9mIHRoZSAqKmN1bXVsYXRpdmUgZGlzdHJpYnV0aW9uIGZ1bmN0aW9uKiogb2YgJFQkCi0gUmF0ZSBvZiBkZWF0aCBvciBmYWlsdXJlIGV2ZW50cyBwZXIgdW5pdCB0aW1lCi0gVGhlIHByb2JhYmlsaXR5IG9mIHRoZSBldmVudCBvY2N1cnJpbmcgYXQgZXhhY3RseSB0aW1lICR0JAoKJCRmKHQpPUYnKHQpPXtcZnJhY3tkfXtkdH19Rih0KSBcdGFnezMuMX0kJAoKQmFjayB0byB0aGUgc3Vydml2YWwgZnVuY3Rpb24gKDEuMSksIGl0IGNhbiBiZSBleHByZXNzZWQgaW4gdGVybXMgb2YgKnByb2JhYmlsaXR5IGRpc3RyaWJ1dGlvbiogYW5kICpwcm9iYWJpbGl0eSBkZW5zaXR5IGZ1bmN0aW9ucyoKCgokJFModCk9XFByKFQ+dCk9XGludCBfe3R9Xnt7XGluZnR5IH19Zih1KVwsZHU9MS1GKHQpIFx0YWd7NC4xfSQkCgpTaW1pbGFybHksIGEgc3Vydml2YWwgKipldmVudCBkZW5zaXR5KiogZnVuY3Rpb24gY2FuIGJlIGRlZmluZWQgYXMKCiQkcyh0KT1TJyh0KT17XGZyYWMgIHtkfXtkdH19Uyh0KT17XGZyYWMgIHtkfXtkdH19XGludCBfe3R9Xnt7XGluZnR5IH19Zih1KVwsZHU9e1xmcmFjICB7ZH17ZHR9fVsxLUYodCldPS1mKHQpIFx0YWd7NC4yfSQkCgojIyBIYXphcmQgZnVuY3Rpb24gYW5kIGN1bXVsYXRpdmUgaGF6YXJkIGZ1bmN0aW9uCgotICRmKHQpJCAqKmV2ZW50IGRlbnNpdHkqKiwgaXMgcmF0ZSBvZiBkZWF0aCBvciBmYWlsdXJlIGV2ZW50cyBwZXIgdW5pdCB0aW1lLiBUaGUgcHJvYmFiaWxpdHkgb2YgdGhlIGV2ZW50IG9jY3VycmluZyBhdCBleGFjdGx5IHRpbWUgJHQkCiAgLSBFeGFtcGxlOiBhIHdvbWFuIGJvcm4gdG9kYXkgaGFzLCBzYXksIGEgMSUgY2hhbmNlIG9mIGR5aW5nIGF0IDgwIHllYXJzCi0gSGF6YXJkIHJhdGUgaXMgYW4gaW5zdGFudGFuZW91cyAqKmluY2lkZW5jZSByYXRlKiouIEl0IGlzIGNvbmRpdGlvbmFsIG9uIHN1cnZpdmFsIHVudGlsIHRpbWUgJHQkIG9yIGxhdGVyLgogIC0gRXhhbXBsZTogYSB3b21hbiB3aG8gaXMgNzkgdG9kYXkgaGFzLCBzYXksIGEgNSUgY2hhbmNlIG9mIGR5aW5nIGF0IDgwIHllYXJzCgoKVGhlIGhhemFyZCBmdW5jdGlvbiwgY29udmVudGlvbmFsbHkgZGVub3RlZCBcbGFtYmRhLCBpcyBkZWZpbmVkIGFzIHRoZSBldmVudCByYXRlIGF0IHRpbWUgJHQkIGNvbmRpdGlvbmFsIG9uIHN1cnZpdmFsIHVudGlsIHRpbWUgJHQkIG9yIGxhdGVyICh0aGF0IGlzLCAkVCDiiaUgdCQpLiBTdXBwb3NlIHRoYXQgYW4gaXRlbSBoYXMgc3Vydml2ZWQgZm9yIGEgdGltZSAkdCQgYW5kIHdlIGRlc2lyZSB0aGUgcHJvYmFiaWxpdHkgdGhhdCBpdCB3aWxsIG5vdCBzdXJ2aXZlIGZvciBhbiBhZGRpdGlvbmFsIHRpbWUgJGR0JDoKCiQkCntcbGFtYmRhICh0KT1cbGltIF97ZHRccmlnaHRhcnJvdyAwfXtcZnJhYyB7XFByKHRcbGVxIFQ8dCtkdCl9e2R0XGNkb3QgUyh0KX19PXtcZnJhYyB7Zih0KX17Uyh0KX19PS17XGZyYWMge1MnKHQpfXtTKHQpfX19Clx0YWd7NC4xfQokJAoKIyMgRXhhbXBsZQoKLSBXZSBuZWVkIHR3byB2YXJpYWJsZXM6IG9uZSBjb250aW51b3VzIGZvciB0aGUgdGltZSwgYW5kIG9uZSBjYXRlZ29yaWNhbCBmb3IgZmxhZ2dpbmcgdGhlIGV2ZW50CgoKYGBge3Igc2V0dXAsIG1lc3NhZ2UgPSBGQUxTRSwJd2FybmluZyA9IEZBTFNFfQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KHNwbGluZXMyKQpsaWJyYXJ5KHN1cnZpdmFsKQpsaWJyYXJ5KHN1cnZtaW5lcikKYGBgCgoKIyMjIEthcGxhbi1NZWllcgoKYGBge3J9CmRhdGFfdGVzdCA8LSByZWFkX2RlbGltKCJkYXRhMi5jc3YiLCAiOyIsCiAgZXNjYXBlX2RvdWJsZSA9IEZBTFNFLAogIGxvY2FsZSA9IGxvY2FsZShkZWNpbWFsX21hcmsgPSAiLCIsIGdyb3VwaW5nX21hcmsgPSAiLiIpLAogIHRyaW1fd3MgPSBUUlVFCikKCmttIDwtIHN1cnZmaXQoU3VydihmdSwgZXZlbnQpIH4gMSwgZGF0YSA9IGRhdGFfdGVzdCkKd2IgPC0gc3VydnJlZyhTdXJ2KGZ1LCBldmVudCkgfiAxLCBkYXRhID0gZGF0YV90ZXN0KQoKZ2dzdXJ2cGxvdChrbSwgY29uZi5pbnQgPSBUUlVFLCByaXNrLnRhYmxlID0gIm5yaXNrX2N1bWV2ZW50cyIsIGxlZ2VuZCA9ICJub25lIiwgdGFibGVzLmhlaWdodCA9IDAuMikKYGBgCgoKYGBge3J9CmttMiA8LSBzdXJ2Zml0KFN1cnYodGltZSwgY2VucykgfiAxLCBkYXRhID0gR0JTRzIpCmdnc3VydnBsb3Qoa20yLCBwYWxldHRlID0gImJsdWUiLCBjb25mLmludCA9IFRSVUUsIHJpc2sudGFibGUgPSAibnJpc2tfY3VtZXZlbnRzIiwgc3Vydi5tZWRpYW4ubGluZSA9ICJodiIsIHRhYmxlcy5oZWlnaHQgPSAwLjMpCmBgYAoKCiMjIyBXZWlidWxsIG1vZGVsCgpgYGB7cn0KIyB3ZWlidWxsIGFwcHJveGltYXRpb24Kd2IyIDwtIHN1cnZyZWcoU3Vydih0aW1lLCBjZW5zKSB+IDEsIGRhdGEgPSBHQlNHMikKc3VydiA8LSBzZXEoLjk5LCAuMDEsIGJ5ID0gLTAuMSkKdCA8LSBwcmVkaWN0KHdiMiwgdHlwZSA9ICJxdWFudGlsZSIsIHAgPSAxIC0gc3VydiwgbmV3ZGF0YSA9IGRhdGEuZnJhbWUoMSkpCnN1cnZfd2IgPC0gZGF0YS5mcmFtZSh0aW1lID0gdCwgc3VydiA9IHN1cnYsIHVwcGVyID0gTkEsIGxvd2VyID0gTkEsIHN0ZC5lcnIgPSBOQSkKZ2dzdXJ2cGxvdF9kZihmaXQgPSBzdXJ2X3diLCBzdXJ2Lmdlb20gPSBnZW9tX2xpbmUpCgoKIyB3ZWlidWxsIGFwcHJveGltYXRpb24gd2l0aCBjb3ZhcmlhbnRzCiMgQ29tcHV0ZSB0aGUgV2VpYnVsbCBtb2RlbAp3Ym1vZCA8LSBzdXJ2cmVnKFN1cnYodGltZSwgY2VucykgfiBob3JUaCArIHRzaXplLCBkYXRhID0gR0JTRzIpCgojIERlY2lkZSBvbiAiaW1hZ2luYXJ5IHBhdGllbnRzIgpuZXdkYXQgPC0gZXhwYW5kLmdyaWQoCiAgaG9yVGggPSBsZXZlbHMoR0JTRzIkaG9yVGgpLAogIHRzaXplID0gcXVhbnRpbGUoR0JTRzIkdHNpemUsIHByb2JzID0gYygwLjI1LCAwLjUsIDAuNzUpKQopCgojIENvbXB1dGUgc3Vydml2YWwgY3VydmVzCnN1cnYgPC0gc2VxKC45OSwgLjAxLCBieSA9IC0wLjEpCnQgPC0gcHJlZGljdCh3Ym1vZCwgdHlwZSA9ICJxdWFudGlsZSIsIHAgPSAxIC0gc3VydiwgbmV3ZGF0YSA9IG5ld2RhdCkKc3Vydl93Ym1vZF93aWRlIDwtIGNiaW5kKG5ld2RhdCwgdCkKCiMgQ3JlYXRlIGRhdGEuZnJhbWUgd2l0aCBzdXJ2aXZhbCBjdXJ2ZSBpbmZvcm1hdGlvbgpzdXJ2X3dibW9kIDwtIHBpdm90X2xvbmdlcihzdXJ2X3dibW9kX3dpZGUsIC0oaG9yVGg6dHNpemUpLCBuYW1lc190byA9ICJzdXJ2X2lkIiwgdmFsdWVzX3RvID0gInRpbWUiKQpzdXJ2X3dibW9kJHN1cnYgPC0gc3Vydlthcy5udW1lcmljKHN1cnZfd2Jtb2Qkc3Vydl9pZCldCnN1cnZfd2Jtb2RbLCBjKCJ1cHBlciIsICJsb3dlciIsICJzdGQuZXJyIiwgInN0cmF0YSIpXSA8LSBOQQpzdXJ2X3dibW9kIDwtIGFzLmRhdGEuZnJhbWUoc3Vydl93Ym1vZCkgIyBzdXJ2cGxvdCBidWcKCiMgcGxvdApnZ3N1cnZwbG90X2RmKHN1cnZfd2Jtb2QsIHN1cnYuZ2VvbSA9IGdlb21fbGluZSwgbGluZXR5cGUgPSAiaG9yVGgiLCBjb2xvciA9ICJ0c2l6ZSIsIGxlZ2VuZC50aXRsZSA9IE5VTEwpCmBgYAoKCiMjIyBDb3ggTW9kZWwKCgpgYGB7cn0KCiMgQ29tcHV0ZSB0aGUgY294IG1vZGVsCmN4bW9kIDwtIGNveHBoKFN1cnYodGltZSwgY2VucykgfiBob3JUaCArIHRzaXplLCBkYXRhID0gR0JTRzIpCgojIERlY2lkZSBvbiBjb3ZhcmlhdGUgY29tYmluYXRpb25zICgiaW1hZ2luYXJ5IHBhdGllbnRzIikKbmV3ZGF0IDwtIGV4cGFuZC5ncmlkKAogIGhvclRoID0gbGV2ZWxzKEdCU0cyJGhvclRoKSwKICB0c2l6ZSA9IHF1YW50aWxlKEdCU0cyJHRzaXplLCBwcm9icyA9IGMoMC4yNSwgMC41LCAwLjc1KSkKKQpyb3duYW1lcyhuZXdkYXQpIDwtIGxldHRlcnNbMTo2XQoKIyBDb21wdXRlIHN1cnZpdmFsIGN1cnZlcwpjeHNmIDwtIHN1cnZmaXQoY3htb2QsIGRhdGEgPSBHQlNHMiwgbmV3ZGF0YSA9IG5ld2RhdCwgY29uZi50eXBlID0gIm5vbmUiKQoKIyBDcmVhdGUgZGF0YS5mcmFtZSB3aXRoIHN1cnZpdmFsIGN1cnZlIGluZm9ybWF0aW9uCgpzdXJ2X2N4bW9kMCA8LSBzdXJ2X3N1bW1hcnkoY3hzZikKc3Vydl9jeG1vZCA8LSBjYmluZChzdXJ2X2N4bW9kMCwgbmV3ZGF0W2FzLmNoYXJhY3RlcihzdXJ2X2N4bW9kMCRzdHJhdGEpLCBdKQoKIyBQbG90Cmdnc3VydnBsb3RfZGYoc3Vydl9jeG1vZCwgbGluZXR5cGUgPSAiaG9yVGgiLCBjb2xvciA9ICJ0c2l6ZSIsCiAgICAgICAgICAgICAgbGVnZW5kLnRpdGxlID0gTlVMTCwgY2Vuc29yID0gRkFMU0UpCmBgYAo=