El procedimiento de Kaplan-Meier.
De acuerdo a [2], con el método de Kaplan-Meier, también llamadao el método del producto límite, podemos usar los datos que se recoletan para analizar y estimar la probabilidad de sobrevivir por un tiempo determinado. Este método es una técnica no parametrica, es decir, no se hacen suposiciones sobre la distribución de los tiempos se sobrevivencia.
Para este método, consideramos lo siguiente:
\(n=\) número total de sujetos de los que conocemos el tiempo de sobrevivencia.
\(\hat{p}_1=\) Estimación de la proporción de sujetos que sobreviven el primer periodo de tiempo.
\(\hat{p}_k=\) Estimación de la proporción se sujetos que sobreviven el periodo de tiempo \(k\) después de haber sobrevivido el periodo anterior \(k-1\).
A partir de estas estimaciónes de las proporciones \(\hat{p}_k\) podemos calcular la probabilidad estimada de sobrevivir en un tiempo \(t\), la cual está dada por:
\[\hat{S}(t) = \prod_{i = 1}^{t}\hat{p}_i\]
Es importante mencionar que podemos entender las proporciones \(\hat{p}_k\) como probabilidades condicionales: la probabilidad de sobrevivir otro periodo de tiempo dado que ya sobreviví los \((k-1)\) anteriores.
Ejemplo.
Este ejemplo es presentado y desarrollado en [2]. En este ejemplo 14.3.1, haciendo referencia al estudio de Martini et al [1], se analiza el tiempo de supervivencia de personas que tuvieron tumores. En específico, se tienen dos tipos de tumores (y dos datasets en consecuencia), los de grado bajo (con 25 personas en esta categoria) y los de grado alto (con 14 personas). Nuestro objetivo es comparar el tiempo de supervivencia entre ambos grupos, para lo que usaremos el método de Kaplan-Meier.
Primeramente, importamos y mostramos la estructura de los datos:
df <- read.csv('EXA_C14_S03_01.csv')
head(df)
Podemos observar que tenemos información del tiempo de supervivencia, y el tipo de tomor (L ⮕ grado bajo, H⮕g rado alto). Además, tenemos tres tipos de evento:
- dod: Muerte por enfermedad (dead of disease).
- ned: Sin evidencia de de enfermedad (no evidence of dsiease).
- dpo: Muerte después del estudio (dead postoperation).
Ahora, es necesario operar estos datos para obtener las proporciones \(\hat{p}_k\), así como la función de supervivencia \(\hat{S}(t)\).
# Separamos por tipo de tumor
df_l <- df[ which(df$TUMOR=='L'), ]
df_h <- df[ which(df$TUMOR=='H'), ]
# Función para conocer estatus:
get.status <- function(x){
if(x == 'ned'){
return(0)
}
else{
return(1)
}
}
# Definimos función que realiza kaplan-meier
kaplan.meier <- function(df){
time <- c() # Arreglo para guardar parte temporal
risk <- c() # Pacientes en riesgo (aun vivos)
alive <- c() # Pacientes vivos al final del periodo
proportion <- c() # Proporcions (vivos/riesgo)
cumulative <- c() # Función cumulativa de proporciones S(t)
# Intervalo de tiempo de interés
max <- max(df$TIME)
min <- min(df$TIME)
# Número total de pacientes
n <- length(df$SUBJ)
# Obtenemos proporciones en orden
for (k in min:max){
# Obtenemos pacientes con ese tiempo
aux = df[which(df$TIME==k),]
# En caso de tener paciente
if(length(aux$VITAL) > 0){
# Lista para estatus de pacientes
stat <- c()
for(j in 1:length(aux$VITAL)){
stat <- append(stat, get.status(aux$VITAL[j]))
}
# Si sucedió algo, calculamos todo
if(is.element(1, stat)){
time <- append(time, k)
die <- sum(stat == 1)
survive <- sum(stat == 0)
risk <- append(risk, n)
n <- n - die
alive <- append(alive, n)
prop <- n/(n+die)
proportion<- append(proportion, prop)
if(length(cumulative) == 0){
cumulative <- proportion[1]
}
else{
cumulative <- append(cumulative,prop*cumulative[length(cumulative)])
}
n <- n - survive
}
else{
# Quitamos pacientes que no mueren
n <- n-length(aux$VITAL)
}
}
}
df_ans <- data.frame(time, risk, alive, proportion, cumulative)
return(df_ans)
}
Con esta función, obtenemos la información relevante para ambos tumores. Primero, para el grado bajo:
ans_l <- kaplan.meier(df_l)
ans_l
Y ahora, el grado alto:
ans_h <- kaplan.meier(df_h)
ans_h
Finalmente, graficamos:
plot(x = append(ans_l$time, 212), y = append(1, ans_l$cumulative),
type = 'S',
col = 'blue',
main = 'Curva de supervivencia de Kaplan-Meier',
xlab = 'Tiempo (meses)',
ylab = 'Probabilidad',
ylim = c(0, 1),
xlim = c(0, 120))
lines(append(ans_h$time, 140), append(1, ans_h$cumulative), type = 'S', col = 'red')
# Etiquetas de líneas.
legend("topright", c("Grado bajo", "Grado alto"), fill=c("blue", "red"))
abline(v = 60)
abline(h = 0.5, col = 'gray')
# Agregamos una cuadrícula.
grid()

Algunas métricas importantes:
Mediana del tiempo de supervivencia: Corresponde con el punto donde la función cumulativa de supervivencia toda \(0.5\).
En el caso del grupo de grado bajo, esto es 212 meses, y en el grupo de grado alto es de tan solo 9 meses.
Proporción de supervivencia a 5 años: Observamos a la función a los 12 años (60 meses).
Para el grupo de grado bajo, esto es de \(0.73\) y el grado alto es de \(0.07\).
Tiempo promedio se supervivencia: Corresponde a dividir el tiempo total de vida entre todos los sujetos (sumado), dividido entre el número de sujetos.
Para el grupo de grado bajo:
total <- sum(df_l$TIME)
print(total/length(df_l$VITAL))
[1] 88.04
Y para el grupo de grado alto:
total <- sum(df_h$TIME)
print(total/length(df_h$VITAL))
[1] 18.35714
LS0tDQp0aXRsZTogIlByb3llY3RvIDIgLSBUZXJjZXIgcGFyY2lhbCAtIEVzdGFkw61zdGljYSBhdmFuemFkYS4iDQphdXRob3I6ICJHYWJyaWVsIE1pc3NhZWwgQmFyY28uIE5VQTogNDI3MDcxIHwgTGF1cmEgZGVsIENhcm1lbiBDYWJhbCBQYXJhbW8uIE5VQTogMzkxNTgwIg0KZGF0ZTogIjI5IGRlIE5vdmllbWJyZSBkZSAyMDIxIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KPHN0eWxlPg0KYm9keSB7dGV4dC1hbGlnbjoganVzdGlmeTsgZm9udC1zaXplOiAxMnB0fQ0KPC9zdHlsZT4NCg0KPGNlbnRlcj4NCiAgICA8aW1nIHdpZHRoPSI2MCUiIHNyYz0iaHR0cHM6Ly9pLmltZ3VyLmNvbS9VYW85Q0l5LnBuZyI+DQo8L2NlbnRlcj4NCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIyBFbCBwcm9jZWRpbWllbnRvIGRlIEthcGxhbi1NZWllci4NCg0KRGUgYWN1ZXJkbyBhIFsyXSwgY29uIGVsIG3DqXRvZG8gZGUgS2FwbGFuLU1laWVyLCB0YW1iacOpbiBsbGFtYWRhbyBlbCBtw6l0b2RvIGRlbCBwcm9kdWN0byBsw61taXRlLCBwb2RlbW9zIHVzYXIgbG9zIGRhdG9zIHF1ZSBzZSByZWNvbGV0YW4gcGFyYSBhbmFsaXphciB5IGVzdGltYXIgbGEgcHJvYmFiaWxpZGFkIGRlIHNvYnJldml2aXIgcG9yIHVuIHRpZW1wbyBkZXRlcm1pbmFkby4gRXN0ZSBtw6l0b2RvIGVzIHVuYSB0w6ljbmljYSBubyBwYXJhbWV0cmljYSwgZXMgZGVjaXIsIG5vIHNlIGhhY2VuIHN1cG9zaWNpb25lcyBzb2JyZSBsYSBkaXN0cmlidWNpw7NuIGRlIGxvcyB0aWVtcG9zIHNlIHNvYnJldml2ZW5jaWEuDQoNClBhcmEgZXN0ZSBtw6l0b2RvLCBjb25zaWRlcmFtb3MgbG8gc2lndWllbnRlOiANCg0KLSAkbj0kIG7Dum1lcm8gdG90YWwgZGUgc3VqZXRvcyBkZSBsb3MgcXVlIGNvbm9jZW1vcyBlbCB0aWVtcG8gZGUgc29icmV2aXZlbmNpYS4NCg0KLSAkXGhhdHtwfV8xPSQgRXN0aW1hY2nDs24gZGUgbGEgcHJvcG9yY2nDs24gZGUgc3VqZXRvcyBxdWUgc29icmV2aXZlbiBlbCBwcmltZXIgcGVyaW9kbyBkZSB0aWVtcG8uDQoNCi0gJFxoYXR7cH1faz0kIEVzdGltYWNpw7NuIGRlIGxhIHByb3BvcmNpw7NuIHNlIHN1amV0b3MgcXVlIHNvYnJldml2ZW4gZWwgcGVyaW9kbyBkZSB0aWVtcG8gJGskIGRlc3B1w6lzIGRlIGhhYmVyIHNvYnJldml2aWRvIGVsIHBlcmlvZG8gYW50ZXJpb3IgJGstMSQuDQoNCkEgcGFydGlyIGRlIGVzdGFzIGVzdGltYWNpw7NuZXMgZGUgbGFzIHByb3BvcmNpb25lcyAkXGhhdHtwfV9rJCBwb2RlbW9zIGNhbGN1bGFyIGxhIHByb2JhYmlsaWRhZCBlc3RpbWFkYSBkZSBzb2JyZXZpdmlyIGVuIHVuIHRpZW1wbyAkdCQsIGxhIGN1YWwgZXN0w6EgZGFkYSBwb3I6DQoNCiQkXGhhdHtTfSh0KSA9IFxwcm9kX3tpID0gMX1ee3R9XGhhdHtwfV9pJCQNCg0KRXMgaW1wb3J0YW50ZSBtZW5jaW9uYXIgcXVlIHBvZGVtb3MgZW50ZW5kZXIgbGFzIHByb3BvcmNpb25lcyAkXGhhdHtwfV9rJCBjb21vIHByb2JhYmlsaWRhZGVzIGNvbmRpY2lvbmFsZXM6IGxhIHByb2JhYmlsaWRhZCBkZSBzb2JyZXZpdmlyIG90cm8gcGVyaW9kbyBkZSB0aWVtcG8gZGFkbyBxdWUgeWEgc29icmV2aXbDrSBsb3MgJChrLTEpJCBhbnRlcmlvcmVzLg0KDQojIyBFamVtcGxvLg0KDQpFc3RlIGVqZW1wbG8gZXMgcHJlc2VudGFkbyB5IGRlc2Fycm9sbGFkbyBlbiBbMl0uIEVuIGVzdGUgZWplbXBsbyAxNC4zLjEsIGhhY2llbmRvIHJlZmVyZW5jaWEgYWwgZXN0dWRpbyBkZSBNYXJ0aW5pIGV0IGFsIFsxXSwgc2UgYW5hbGl6YSBlbCB0aWVtcG8gZGUgc3VwZXJ2aXZlbmNpYSBkZSBwZXJzb25hcyBxdWUgdHV2aWVyb24gdHVtb3Jlcy4gRW4gZXNwZWPDrWZpY28sIHNlIHRpZW5lbiBkb3MgdGlwb3MgZGUgdHVtb3JlcyAoeSBkb3MgZGF0YXNldHMgZW4gY29uc2VjdWVuY2lhKSwgbG9zIGRlIGdyYWRvIGJham8gKGNvbiAyNSBwZXJzb25hcyBlbiBlc3RhIGNhdGVnb3JpYSkgeSBsb3MgZGUgZ3JhZG8gYWx0byAoY29uIDE0IHBlcnNvbmFzKS4gTnVlc3RybyBvYmpldGl2byBlcyBjb21wYXJhciBlbCB0aWVtcG8gZGUgc3VwZXJ2aXZlbmNpYSBlbnRyZSBhbWJvcyBncnVwb3MsIHBhcmEgbG8gcXVlIHVzYXJlbW9zIGVsIG3DqXRvZG8gZGUgS2FwbGFuLU1laWVyLg0KDQpQcmltZXJhbWVudGUsIGltcG9ydGFtb3MgeSBtb3N0cmFtb3MgbGEgZXN0cnVjdHVyYSBkZSBsb3MgZGF0b3M6IA0KDQpgYGB7cn0NCmRmIDwtIHJlYWQuY3N2KCdFWEFfQzE0X1MwM18wMS5jc3YnKQ0KaGVhZChkZikNCmBgYA0KUG9kZW1vcyBvYnNlcnZhciBxdWUgdGVuZW1vcyBpbmZvcm1hY2nDs24gZGVsIHRpZW1wbyBkZSBzdXBlcnZpdmVuY2lhLCB5IGVsIHRpcG8gZGUgdG9tb3IgKCpMKiDirpUgZ3JhZG8gYmFqbywgKkgq4q6VZyByYWRvIGFsdG8pLiBBZGVtw6FzLCB0ZW5lbW9zIHRyZXMgdGlwb3MgZGUgZXZlbnRvOiANCg0KLSAqZG9kKjogTXVlcnRlIHBvciBlbmZlcm1lZGFkIChkZWFkIG9mIGRpc2Vhc2UpLg0KLSAqbmVkKjogU2luIGV2aWRlbmNpYSBkZSBkZSBlbmZlcm1lZGFkIChubyBldmlkZW5jZSBvZiBkc2llYXNlKS4NCi0gKmRwbyo6IE11ZXJ0ZSBkZXNwdcOpcyBkZWwgZXN0dWRpbyAoZGVhZCBwb3N0b3BlcmF0aW9uKS4NCg0KQWhvcmEsIGVzIG5lY2VzYXJpbyBvcGVyYXIgZXN0b3MgZGF0b3MgcGFyYSBvYnRlbmVyIGxhcyBwcm9wb3JjaW9uZXMgJFxoYXR7cH1fayQsIGFzw60gY29tbyBsYSBmdW5jacOzbiBkZSBzdXBlcnZpdmVuY2lhICRcaGF0e1N9KHQpJC4NCg0KYGBge3J9DQojIFNlcGFyYW1vcyBwb3IgdGlwbyBkZSB0dW1vcg0KZGZfbCA8LSBkZlsgd2hpY2goZGYkVFVNT1I9PSdMJyksIF0NCmRmX2ggPC0gZGZbIHdoaWNoKGRmJFRVTU9SPT0nSCcpLCBdDQoNCiMgRnVuY2nDs24gcGFyYSBjb25vY2VyIGVzdGF0dXM6DQpnZXQuc3RhdHVzIDwtIGZ1bmN0aW9uKHgpew0KICBpZih4ID09ICduZWQnKXsNCiAgICByZXR1cm4oMCkNCiAgfQ0KICBlbHNlew0KICAgIHJldHVybigxKQ0KICB9DQp9DQoNCiMgRGVmaW5pbW9zIGZ1bmNpw7NuIHF1ZSByZWFsaXphIGthcGxhbi1tZWllcg0Ka2FwbGFuLm1laWVyIDwtIGZ1bmN0aW9uKGRmKXsNCiAgdGltZSA8LSBjKCkgIyBBcnJlZ2xvIHBhcmEgZ3VhcmRhciBwYXJ0ZSB0ZW1wb3JhbA0KICByaXNrIDwtIGMoKSAjIFBhY2llbnRlcyBlbiByaWVzZ28gKGF1biB2aXZvcykNCiAgYWxpdmUgPC0gYygpICMgUGFjaWVudGVzIHZpdm9zIGFsIGZpbmFsIGRlbCBwZXJpb2RvDQogIHByb3BvcnRpb24gPC0gYygpICMgUHJvcG9yY2lvbnMgKHZpdm9zL3JpZXNnbykNCiAgY3VtdWxhdGl2ZSA8LSBjKCkgIyBGdW5jacOzbiBjdW11bGF0aXZhIGRlIHByb3BvcmNpb25lcyBTKHQpDQogIA0KICAjIEludGVydmFsbyBkZSB0aWVtcG8gZGUgaW50ZXLDqXMNCiAgbWF4IDwtIG1heChkZiRUSU1FKQ0KICBtaW4gPC0gbWluKGRmJFRJTUUpDQogIA0KICAjIE7Dum1lcm8gdG90YWwgZGUgcGFjaWVudGVzDQogIG4gPC0gbGVuZ3RoKGRmJFNVQkopDQoNCiAgIyBPYnRlbmVtb3MgcHJvcG9yY2lvbmVzIGVuIG9yZGVuDQogIGZvciAoayBpbiBtaW46bWF4KXsNCiAgICANCiAgICAjIE9idGVuZW1vcyBwYWNpZW50ZXMgY29uIGVzZSB0aWVtcG8NCiAgICBhdXggPSBkZlt3aGljaChkZiRUSU1FPT1rKSxdDQogICAgDQogICAgIyBFbiBjYXNvIGRlIHRlbmVyIHBhY2llbnRlDQogICAgaWYobGVuZ3RoKGF1eCRWSVRBTCkgPiAwKXsNCiAgICAgICMgTGlzdGEgcGFyYSBlc3RhdHVzIGRlIHBhY2llbnRlcw0KICAgICAgc3RhdCA8LSBjKCkNCiAgICAgIGZvcihqIGluIDE6bGVuZ3RoKGF1eCRWSVRBTCkpew0KICAgICAgICBzdGF0IDwtIGFwcGVuZChzdGF0LCBnZXQuc3RhdHVzKGF1eCRWSVRBTFtqXSkpDQogICAgICB9DQogICAgICANCiAgICAgICMgU2kgc3VjZWRpw7MgYWxnbywgY2FsY3VsYW1vcyB0b2RvDQogICAgICBpZihpcy5lbGVtZW50KDEsIHN0YXQpKXsNCiAgICAgICAgdGltZSA8LSBhcHBlbmQodGltZSwgaykNCiAgICAgICAgZGllIDwtIHN1bShzdGF0ID09IDEpDQogICAgICAgIHN1cnZpdmUgPC0gc3VtKHN0YXQgPT0gMCkNCiAgICAgICAgDQogICAgICAgIHJpc2sgPC0gYXBwZW5kKHJpc2ssIG4pDQogICAgICAgIG4gPC0gbiAtIGRpZQ0KICAgICAgICBhbGl2ZSA8LSBhcHBlbmQoYWxpdmUsIG4pDQogICAgICAgIHByb3AgPC0gbi8obitkaWUpDQogICAgICAgIHByb3BvcnRpb248LSBhcHBlbmQocHJvcG9ydGlvbiwgcHJvcCkNCiAgICAgICAgaWYobGVuZ3RoKGN1bXVsYXRpdmUpID09IDApew0KICAgICAgICAgIGN1bXVsYXRpdmUgPC0gcHJvcG9ydGlvblsxXQ0KICAgICAgICB9DQogICAgICAgIGVsc2V7DQogICAgICAgICAgY3VtdWxhdGl2ZSA8LSBhcHBlbmQoY3VtdWxhdGl2ZSxwcm9wKmN1bXVsYXRpdmVbbGVuZ3RoKGN1bXVsYXRpdmUpXSkNCiAgICAgICAgfQ0KICAgICAgICBuIDwtIG4gLSBzdXJ2aXZlDQogICAgICB9DQogICAgICBlbHNlew0KICAgICAgICAjIFF1aXRhbW9zIHBhY2llbnRlcyBxdWUgbm8gbXVlcmVuDQogICAgICAgIG4gPC0gbi1sZW5ndGgoYXV4JFZJVEFMKQ0KICAgICAgfQ0KICAgIH0NCiAgDQogICAgfQ0KICBkZl9hbnMgPC0gZGF0YS5mcmFtZSh0aW1lLCByaXNrLCBhbGl2ZSwgcHJvcG9ydGlvbiwgY3VtdWxhdGl2ZSkNCiAgcmV0dXJuKGRmX2FucykNCn0NCiAgDQpgYGANCg0KQ29uIGVzdGEgZnVuY2nDs24sIG9idGVuZW1vcyBsYSBpbmZvcm1hY2nDs24gcmVsZXZhbnRlIHBhcmEgYW1ib3MgdHVtb3Jlcy4gUHJpbWVybywgcGFyYSBlbCBncmFkbyBiYWpvOg0KDQpgYGB7cn0NCmFuc19sIDwtIGthcGxhbi5tZWllcihkZl9sKQ0KYW5zX2wNCmBgYA0KDQpZIGFob3JhLCBlbCBncmFkbyBhbHRvOiANCg0KYGBge3J9DQphbnNfaCA8LSBrYXBsYW4ubWVpZXIoZGZfaCkNCmFuc19oDQpgYGANCg0KRmluYWxtZW50ZSwgZ3JhZmljYW1vczogDQoNCmBgYHtyfQ0KcGxvdCh4ID0gYXBwZW5kKGFuc19sJHRpbWUsIDIxMiksIHkgPSBhcHBlbmQoMSwgYW5zX2wkY3VtdWxhdGl2ZSksDQogICAgIHR5cGUgPSAnUycsDQogICAgIGNvbCA9ICdibHVlJywNCiAgICAgbWFpbiA9ICdDdXJ2YSBkZSBzdXBlcnZpdmVuY2lhIGRlIEthcGxhbi1NZWllcicsIA0KICAgICB4bGFiID0gJ1RpZW1wbyAobWVzZXMpJywNCiAgICAgeWxhYiA9ICdQcm9iYWJpbGlkYWQnLA0KICAgICB5bGltID0gYygwLCAxKSwgDQogICAgIHhsaW0gPSBjKDAsIDEyMCkpDQpsaW5lcyhhcHBlbmQoYW5zX2gkdGltZSwgMTQwKSwgYXBwZW5kKDEsIGFuc19oJGN1bXVsYXRpdmUpLCB0eXBlID0gJ1MnLCBjb2wgPSAncmVkJykNCg0KIyBFdGlxdWV0YXMgZGUgbMOtbmVhcy4NCmxlZ2VuZCgidG9wcmlnaHQiLCBjKCJHcmFkbyBiYWpvIiwgIkdyYWRvIGFsdG8iKSwgZmlsbD1jKCJibHVlIiwgInJlZCIpKQ0KYWJsaW5lKHYgPSA2MCkNCmFibGluZShoID0gMC41LCBjb2wgPSAnZ3JheScpDQoNCiMgQWdyZWdhbW9zIHVuYSBjdWFkcsOtY3VsYS4NCmdyaWQoKQ0KYGBgDQoNCkFsZ3VuYXMgbcOpdHJpY2FzIGltcG9ydGFudGVzOg0KDQoxLiAqTWVkaWFuYSBkZWwgdGllbXBvIGRlIHN1cGVydml2ZW5jaWE6KiBDb3JyZXNwb25kZSBjb24gZWwgcHVudG8gZG9uZGUgbGEgZnVuY2nDs24gY3VtdWxhdGl2YSBkZSBzdXBlcnZpdmVuY2lhIHRvZGEgJDAuNSQuDQoNCiAgICBFbiBlbCBjYXNvIGRlbCBncnVwbyBkZSBncmFkbyBiYWpvLCBlc3RvIGVzIDIxMiBtZXNlcywgeSBlbiBlbCBncnVwbyBkZSBncmFkbyBhbHRvIGVzIGRlIHRhbiBzb2xvIDkgbWVzZXMuDQoNCjIuICpQcm9wb3JjacOzbiBkZSBzdXBlcnZpdmVuY2lhIGEgNSBhw7Fvcyo6IE9ic2VydmFtb3MgYSBsYSBmdW5jacOzbiBhIGxvcyAxMiBhw7FvcyAoNjAgbWVzZXMpLg0KDQogICAgUGFyYSBlbCBncnVwbyBkZSBncmFkbyBiYWpvLCBlc3RvIGVzIGRlICQwLjczJCB5IGVsIGdyYWRvIGFsdG8gZXMgZGUgJDAuMDckLg0KDQozLiAqVGllbXBvIHByb21lZGlvIHNlIHN1cGVydml2ZW5jaWE6KiBDb3JyZXNwb25kZSBhIGRpdmlkaXIgZWwgdGllbXBvIHRvdGFsIGRlIHZpZGEgZW50cmUgdG9kb3MgbG9zIHN1amV0b3MgKHN1bWFkbyksIGRpdmlkaWRvIGVudHJlIGVsIG7Dum1lcm8gZGUgc3VqZXRvcy4NCg0KICAgIFBhcmEgZWwgZ3J1cG8gZGUgZ3JhZG8gYmFqbzoNCiAgICANCmBgYHtyfQ0KdG90YWwgPC0gc3VtKGRmX2wkVElNRSkNCnByaW50KHRvdGFsL2xlbmd0aChkZl9sJFZJVEFMKSkNCmBgYA0KICAgIA0KICAgIFkgcGFyYSBlbCBncnVwbyBkZSBncmFkbyBhbHRvOiANCiAgDQpgYGB7cn0NCnRvdGFsIDwtIHN1bShkZl9oJFRJTUUpDQpwcmludCh0b3RhbC9sZW5ndGgoZGZfaCRWSVRBTCkpDQpgYGANCg0KIyMgUmVmZXJlbmNpYXMuDQoNCjEuICoqTmFlbCBNYXJ0aW5pLCBBbmRyZXcgTWljaGFlbCBFLiBCdXJ0LCBSb2JlcnQgVC4gaGVlbGFuLCBNYW5qaXQgUy4gQmFpbnMsIFBhdHJpY2lhIE0uIE1jQ29ybWFjaywgVmxlcmllIFcuIFJzY2gsIE1pY2hhZWwgV2ViZXIsIFJvYmVydCBKLiBEb3duZXkgeSBSb2JlcnQgSi4gR2luc2JlcmcqKiwgKlByZWRpY3Rpb25zIG9mIFN1cnZpdmFsIGluIE1hbGlnbmFudCBUdW1vcnMgb2YgdGhlIFN0ZXJudW0qLCBKb3VybmFsIG9mIFRob3JhY2ljIGFuZCBDYXJkaW92YXN2dWxhciBTdXJnZXJ5LCAxMTEgKDE5OTYpLCA5NS0xMDYNCjIuICoqV2F5bmUgVy4gRGFuaWVsIHkgQ2hhZCBMLiBDcm9zcyoqLCAqQmlvc3RhdGlzdGljczogQSBGb3VuZGF0aW9uIGZvciBBbmFseXNpcyBpbiB0aGUgSGVhbHRoIFNjaWVuY2VzKiwgMTDCsCBlZGl0aW9uLCBXaWxleS4NCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQoNCiMjIEFuZXhvcy4NCg0KIyMjIERpYXBvc2l0aXZhcyBkZSBwcmVzZW50YWNpw7NuIGRlIHByb3llY3RvLiANCg0KU2UgcHVlZGVuIGVuY29udHJhciBlbiBlc3RlIFtsaW5rXShodHRwczovL2RvY3MuZ29vZ2xlLmNvbS9wcmVzZW50YXRpb24vZC9lLzJQQUNYLTF2VHdrN0lzMXdwSk0xc1RKT0VhY3NaMGN3VFY1VkktNGRVOEk5bldXSGl6bDF0NElRc2Rtd1ZPTnY4el9BLVNRYWRUWmRrYzlnQ2ZpeHI3L3B1Yj9zdGFydD1mYWxzZSZsb29wPWZhbHNlJmRlbGF5bXM9MTAwMDApLg0KDQo=