Este Notebook está diseñado para ejecutar mispitools y evaluar
el poder estadístico de una base de datos de frecuencias alélicas.
Primero, instalamos las herramientas necesarias:
#install.packages("mispitools")
#install.packages("pedtools")
rmarkdown::render("~/Escritorio/mispitools4refs.Rmd")
Ahora cargamos las bibliotecas.
library(mispitools)
library(pedtools)
library(forrel)
Ahora configuramos nuestros sistemas de prueba. En este caso, vamos a
analizar los siguientes parentescos:
- Paternidad.
- Tío.
- Hermanos.
- Medio hermanos.
- Abuelos.
paternity <-linearPed(1)
uncle <- avuncularPed()
sibling <- nuclearPed(2)
halfSib <- halfSibPed()
grandparent <-linearPed(2)
par(mfrow = c(2, 3))
plot(paternity, main = "Paternity", hatched = 1, fill = c(`3` = "2"))
plot(uncle, main = "Avuncular", hatched = 3, fill = c(`6` = "2"))
plot(sibling, main = "Sibling", hatched = 3, fill = c(`4` = "2"))
plot(halfSib, main = "Half Sibling", hatched = 4, fill = c(`5` = "2"))
plot(grandparent, main = "Grandparent", hatched = 1, fill = c(`5` = "2"))

Tenga en cuenta que los individuos representados con líneas
discontinuas serán los genotipados, y los individuos en rojo serán las
Personas de Interés.
Trabajando con la base de datos
Primero, debemos proporcionar una base de datos de frecuencias
alélicas. Por defecto, mispitools cuenta con bases de datos de todo el
mundo. Además, si es necesario agregar una nueva base de datos, debemos
tener en cuenta el formato. Veamos la base de datos de frecuencias
alélicas de Argentina:
Argentina
La primera columna (“Allele”) es obligatoria y debe tener ese nombre.
Contiene todos los alelos observados (en todos los marcadores). Luego,
cada columna representa un marcador, y los valores de frecuencia deben
sumar 1 en todos ellos. La siguiente función reorganiza la base de datos
a un formato más amigable (desde el punto de vista computacional). Dicho
esto, se puede agregar una nueva base de datos usando, por ejemplo,
read_csv, teniendo en cuenta estos detalles de formato. Después de
leerla, deberíamos poder visualizarla de la misma manera que vemos la
base de datos argentina.
Arg <- getfreqs(Argentina)
head(Arg, 1) # showing one marker
$D8S1179
2.2 3.2 4 4.2 5 6 7 8 8.3 9 9.1 9.2
0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00898 0.00000 0.00762 0.00000 0.00000
9.3 10 10.2 10.3 11 11.2 11.3 12 12.1 12.2 12.3 13
0.00000 0.06872 0.00000 0.00000 0.07247 0.00000 0.00000 0.14353 0.00000 0.00000 0.00000 0.30446
13.2 13.3 14 14.2 14.3 15 15.2 15.3 16 16.2 16.3 16.4
0.00000 0.00000 0.22236 0.00000 0.00000 0.13732 0.00000 0.00000 0.03047 0.00000 0.00000 0.00000
17 17.1 17.3 18 18.1 18.2 18.3 19 19.1 19.2 19.3 20
0.00337 0.00000 0.00000 0.00065 0.00000 0.00000 0.00000 0.00005 0.00000 0.00000 0.00000 0.00000
20.1 20.2 20.3 21 21.2 21.3 22 22.2 22.3 23 23.2 23.3
0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
24 24.2 24.3 25 25.2 25.3 26 26.2 27 27.2 28 28.2
0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
29 29.2 30 30.2 31 31.2 32 32.1 32.2 33 33.1 33.2
0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
33.3 34 34.2 35 35.1 35.2 36 36.2 37
0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
paternity <-setMarkers(paternity, locusAttributes = Arg[1:22]) # Database Arg, after processing, with 22 markers
uncle <- setMarkers(uncle, locusAttributes = Arg[1:22])
sibling <- setMarkers(sibling, locusAttributes = Arg[1:22])
halfSib <- setMarkers(halfSib, locusAttributes = Arg[1:22])
grandparent <-setMarkers(grandparent, locusAttributes = Arg[1:22])
Ahora podemos simular nuestros genotipos. Comenzamos simulando los
individuos de referencia (representados con líneas discontinuas en el
árbol genealógico).
numsims = 50 # Here put the number of pairs to be simulated
paternity <-profileSim(paternity, N = numsims, ids = 1)
uncle <- profileSim(uncle, N = numsims, ids = 3)
sibling <- profileSim(sibling, N = numsims, ids = 3)
halfSib <- profileSim(halfSib, N = numsims, ids = 4)
grandparent <-profileSim(grandparent, N = numsims, ids = 1)
Bucle Importante - Permite simular LRs a partir de pares de
individuos.
Para cada individuo de referencia, simulamos una Persona de Interés
(ten en cuenta que podemos modificar el código fácilmente para simular
varias Personas de Interés por cada individuo de referencia; en este
caso, estamos simulando 2 por referencia, por lo que con 50 referencias
obtenemos 100 LRs).
NOTA IMPORTANTE: Después de ejecutar, si deseas volver a realizar la
simulación, necesitarás re-ejecutar desde el bloque de gráfico del árbol
genealógico (esto se debe a que es necesario limpiar el objeto ped).
Y ahora podemos extraer los resultados utilizando algunas funciones
personalizadas:
# Función para aplicar simLR2dataframe a cada simulación dentro de la lista y combinar los resultados
combine_sim_results <- function(sim_list) {
# Crear una lista vacía para almacenar los dataframes de cada simulación
df_list <- list()
# Iterar sobre cada simulación dentro de la lista sim_list
for (i in 1:length(sim_list)) {
# Aplicar la función simLR2dataframe a cada simulación
df <- simLR2dataframe(sim_list[[i]])
df_list[[i]] <- df # Guardar el dataframe en la lista
}
# Combinar todos los dataframes en uno solo
combined_df <- do.call(rbind, df_list)
return(combined_df)
}
# Crear dataframes combinados para cada relación de parentesco
df_patsim_combined <- combine_sim_results(patsim)
df_unclesim_combined <- combine_sim_results(unclesim)
df_sibsim_combined <- combine_sim_results(sibsim)
df_halfsim_combined <- combine_sim_results(halfsim)
df_grandsim_combined <- combine_sim_results(grandsim)
Ahora puedes visualizar y analizar fácilmente los datos obtenidos
:)
Los Related son los LRs obtenidos bajo H1, y los Unrelated son los
LRs obtenidos bajo H2.
head(df_patsim_combined)
Contamos con varias métricas para evaluar el rendimiento. Por favor,
consulta ITpaper
y Decisions
para obtener más información.
Conclusiones
En este análisis, hemos evaluado el poder estadístico de una base de
datos de frecuencias alélicas utilizando diferentes relaciones de
parentesco. Los resultados obtenidos nos permiten comprender mejor cómo
los marcadores genéticos seleccionados contribuyen a la discriminación
entre hipótesis de parentesco y no parentesco.
Este enfoque puede ser extendido y adaptado para incorporar nuevas
bases de datos, diferentes marcadores genéticos y otras relaciones de
parentesco, proporcionando una herramienta flexible para la genética
forense y estudios de parentesco.
LS0tCnRpdGxlOiAiRXZhbHVhY2nDs24gZXN0YWTDrXN0aWNhIGRlIGxhcyBiYXNlcyBkZSBkYXRvcyBkZSBmcmVjdWVuY2lhcyIKYXV0aG9yOiAiRnJhbmNvIEwuIE1hcnNpY28iCmFmZmlsaWF0aW9uOiAiVW5pdmVyc2lkYWQgZGUgQnVlbm9zIEFpcmVzLCBBcmdlbnRpbmEiCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0Ci0tLQoKRXN0ZSBOb3RlYm9vayBlc3TDoSBkaXNlw7FhZG8gcGFyYSBlamVjdXRhciBbbWlzcGl0b29sc10oaHR0cHM6Ly9naXRodWIuY29tL01hcnNpY29GTC9taXNwaXRvb2xzKSB5IGV2YWx1YXIgZWwgcG9kZXIgZXN0YWTDrXN0aWNvIGRlIHVuYSBiYXNlIGRlIGRhdG9zIGRlIGZyZWN1ZW5jaWFzIGFsw6lsaWNhcy4gUHJpbWVybywgaW5zdGFsYW1vcyBsYXMgaGVycmFtaWVudGFzIG5lY2VzYXJpYXM6CgoKCgoKCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30KI2luc3RhbGwucGFja2FnZXMoIm1pc3BpdG9vbHMiKQojaW5zdGFsbC5wYWNrYWdlcygicGVkdG9vbHMiKQpybWFya2Rvd246OnJlbmRlcigifi9Fc2NyaXRvcmlvL21pc3BpdG9vbHM0cmVmcy5SbWQiKQoKYGBgCgpBaG9yYSBjYXJnYW1vcyBsYXMgYmlibGlvdGVjYXMuCgoKYGBge3J9CmxpYnJhcnkobWlzcGl0b29scykKbGlicmFyeShwZWR0b29scykKbGlicmFyeShmb3JyZWwpCmBgYAoKQWhvcmEgY29uZmlndXJhbW9zIG51ZXN0cm9zIHNpc3RlbWFzIGRlIHBydWViYS4gRW4gZXN0ZSBjYXNvLCB2YW1vcyBhIGFuYWxpemFyIGxvcyBzaWd1aWVudGVzIHBhcmVudGVzY29zOgoKLSBQYXRlcm5pZGFkLgotIFTDrW8uCi0gSGVybWFub3MuCi0gTWVkaW8gaGVybWFub3MuCi0gQWJ1ZWxvcy4KIApgYGB7ciwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9NH0KcGF0ZXJuaXR5IDwtbGluZWFyUGVkKDEpCnVuY2xlIDwtIGF2dW5jdWxhclBlZCgpCnNpYmxpbmcgPC0gbnVjbGVhclBlZCgyKQpoYWxmU2liIDwtIGhhbGZTaWJQZWQoKQpncmFuZHBhcmVudCA8LWxpbmVhclBlZCgyKQoKcGFyKG1mcm93ID0gYygyLCAzKSkKcGxvdChwYXRlcm5pdHksIG1haW4gPSAiUGF0ZXJuaXR5IiwgaGF0Y2hlZCA9IDEsICBmaWxsID0gYyhgM2AgPSAiMiIpKQpwbG90KHVuY2xlLCBtYWluID0gIkF2dW5jdWxhciIsIGhhdGNoZWQgPSAzLCAgZmlsbCA9IGMoYDZgID0gIjIiKSkKcGxvdChzaWJsaW5nLCBtYWluID0gIlNpYmxpbmciLCBoYXRjaGVkID0gMywgIGZpbGwgPSBjKGA0YCA9ICIyIikpCnBsb3QoaGFsZlNpYiwgbWFpbiA9ICJIYWxmIFNpYmxpbmciLCBoYXRjaGVkID0gNCwgIGZpbGwgPSBjKGA1YCA9ICIyIikpCnBsb3QoZ3JhbmRwYXJlbnQsIG1haW4gPSAiR3JhbmRwYXJlbnQiLCBoYXRjaGVkID0gMSwgIGZpbGwgPSBjKGA1YCA9ICIyIikpCmBgYAoKVGVuZ2EgZW4gY3VlbnRhIHF1ZSBsb3MgaW5kaXZpZHVvcyByZXByZXNlbnRhZG9zIGNvbiBsw61uZWFzIGRpc2NvbnRpbnVhcyBzZXLDoW4gbG9zIGdlbm90aXBhZG9zLCB5IGxvcyBpbmRpdmlkdW9zIGVuIHJvam8gc2Vyw6FuIGxhcyBQZXJzb25hcyBkZSBJbnRlcsOpcy4KCiMjIyBUcmFiYWphbmRvIGNvbiBsYSBiYXNlIGRlIGRhdG9zClByaW1lcm8sIGRlYmVtb3MgcHJvcG9yY2lvbmFyIHVuYSBiYXNlIGRlIGRhdG9zIGRlIGZyZWN1ZW5jaWFzIGFsw6lsaWNhcy4gUG9yIGRlZmVjdG8sIG1pc3BpdG9vbHMgY3VlbnRhIGNvbiBiYXNlcyBkZSBkYXRvcyBkZSB0b2RvIGVsIG11bmRvLiBBZGVtw6FzLCBzaSBlcyBuZWNlc2FyaW8gYWdyZWdhciB1bmEgbnVldmEgYmFzZSBkZSBkYXRvcywgZGViZW1vcyB0ZW5lciBlbiBjdWVudGEgZWwgZm9ybWF0by4gVmVhbW9zIGxhIGJhc2UgZGUgZGF0b3MgZGUgZnJlY3VlbmNpYXMgYWzDqWxpY2FzIGRlIEFyZ2VudGluYToKCgpgYGB7cn0KQXJnZW50aW5hCmBgYAoKTGEgcHJpbWVyYSBjb2x1bW5hICgiQWxsZWxlIikgZXMgb2JsaWdhdG9yaWEgeSBkZWJlIHRlbmVyIGVzZSBub21icmUuIENvbnRpZW5lIHRvZG9zIGxvcyBhbGVsb3Mgb2JzZXJ2YWRvcyAoZW4gdG9kb3MgbG9zIG1hcmNhZG9yZXMpLiBMdWVnbywgY2FkYSBjb2x1bW5hIHJlcHJlc2VudGEgdW4gbWFyY2Fkb3IsIHkgbG9zIHZhbG9yZXMgZGUgZnJlY3VlbmNpYSBkZWJlbiBzdW1hciAxIGVuIHRvZG9zIGVsbG9zLiBMYSBzaWd1aWVudGUgZnVuY2nDs24gcmVvcmdhbml6YSBsYSBiYXNlIGRlIGRhdG9zIGEgdW4gZm9ybWF0byBtw6FzIGFtaWdhYmxlIChkZXNkZSBlbCBwdW50byBkZSB2aXN0YSBjb21wdXRhY2lvbmFsKS4gRGljaG8gZXN0bywgc2UgcHVlZGUgYWdyZWdhciB1bmEgbnVldmEgYmFzZSBkZSBkYXRvcyB1c2FuZG8sIHBvciBlamVtcGxvLCByZWFkX2NzdiwgdGVuaWVuZG8gZW4gY3VlbnRhIGVzdG9zIGRldGFsbGVzIGRlIGZvcm1hdG8uIERlc3B1w6lzIGRlIGxlZXJsYSwgZGViZXLDrWFtb3MgcG9kZXIgdmlzdWFsaXphcmxhIGRlIGxhIG1pc21hIG1hbmVyYSBxdWUgdmVtb3MgbGEgYmFzZSBkZSBkYXRvcyBhcmdlbnRpbmEuCgoKYGBge3J9CkFyZyA8LSBnZXRmcmVxcyhBcmdlbnRpbmEpCmhlYWQoQXJnLCAxKSAjIHNob3dpbmcgb25lIG1hcmtlcgpgYGAKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQpwYXRlcm5pdHkgPC1zZXRNYXJrZXJzKHBhdGVybml0eSwgbG9jdXNBdHRyaWJ1dGVzID0gQXJnWzE6MjJdKSAjIERhdGFiYXNlIEFyZywgYWZ0ZXIgcHJvY2Vzc2luZywgd2l0aCAyMiBtYXJrZXJzCnVuY2xlIDwtIHNldE1hcmtlcnModW5jbGUsIGxvY3VzQXR0cmlidXRlcyA9IEFyZ1sxOjIyXSkgCnNpYmxpbmcgPC0gc2V0TWFya2VycyhzaWJsaW5nLCBsb2N1c0F0dHJpYnV0ZXMgPSBBcmdbMToyMl0pIApoYWxmU2liIDwtIHNldE1hcmtlcnMoaGFsZlNpYiwgbG9jdXNBdHRyaWJ1dGVzID0gQXJnWzE6MjJdKSAKZ3JhbmRwYXJlbnQgPC1zZXRNYXJrZXJzKGdyYW5kcGFyZW50LCBsb2N1c0F0dHJpYnV0ZXMgPSBBcmdbMToyMl0pIApgYGAKCkFob3JhIHBvZGVtb3Mgc2ltdWxhciBudWVzdHJvcyBnZW5vdGlwb3MuIENvbWVuemFtb3Mgc2ltdWxhbmRvIGxvcyBpbmRpdmlkdW9zIGRlIHJlZmVyZW5jaWEgKHJlcHJlc2VudGFkb3MgY29uIGzDrW5lYXMgZGlzY29udGludWFzIGVuIGVsIMOhcmJvbCBnZW5lYWzDs2dpY28pLgoKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQpudW1zaW1zID0gNTAgIyBIZXJlIHB1dCB0aGUgbnVtYmVyIG9mIHBhaXJzIHRvIGJlIHNpbXVsYXRlZApwYXRlcm5pdHkgPC1wcm9maWxlU2ltKHBhdGVybml0eSwgTiA9IG51bXNpbXMsIGlkcyA9IDEpCnVuY2xlIDwtIHByb2ZpbGVTaW0odW5jbGUsIE4gPSBudW1zaW1zLCBpZHMgPSAzKQpzaWJsaW5nIDwtIHByb2ZpbGVTaW0oc2libGluZywgTiA9IG51bXNpbXMsIGlkcyA9IDMpCmhhbGZTaWIgPC0gcHJvZmlsZVNpbShoYWxmU2liLCBOID0gbnVtc2ltcywgaWRzID0gNCkKZ3JhbmRwYXJlbnQgPC1wcm9maWxlU2ltKGdyYW5kcGFyZW50LCBOID0gbnVtc2ltcywgaWRzID0gMSkKYGBgCgojIyMgQnVjbGUgSW1wb3J0YW50ZSAtIFBlcm1pdGUgc2ltdWxhciBMUnMgYSBwYXJ0aXIgZGUgcGFyZXMgZGUgaW5kaXZpZHVvcy4KUGFyYSBjYWRhIGluZGl2aWR1byBkZSByZWZlcmVuY2lhLCBzaW11bGFtb3MgdW5hIFBlcnNvbmEgZGUgSW50ZXLDqXMgKHRlbiBlbiBjdWVudGEgcXVlIHBvZGVtb3MgbW9kaWZpY2FyIGVsIGPDs2RpZ28gZsOhY2lsbWVudGUgcGFyYSBzaW11bGFyIHZhcmlhcyBQZXJzb25hcyBkZSBJbnRlcsOpcyBwb3IgY2FkYSBpbmRpdmlkdW8gZGUgcmVmZXJlbmNpYTsgZW4gZXN0ZSBjYXNvLCBlc3RhbW9zIHNpbXVsYW5kbyAyIHBvciByZWZlcmVuY2lhLCBwb3IgbG8gcXVlIGNvbiA1MCByZWZlcmVuY2lhcyBvYnRlbmVtb3MgMTAwIExScykuCgpOT1RBIElNUE9SVEFOVEU6IERlc3B1w6lzIGRlIGVqZWN1dGFyLCBzaSBkZXNlYXMgdm9sdmVyIGEgcmVhbGl6YXIgbGEgc2ltdWxhY2nDs24sIG5lY2VzaXRhcsOhcyByZS1lamVjdXRhciBkZXNkZSBlbCBibG9xdWUgZGUgZ3LDoWZpY28gZGVsIMOhcmJvbCBnZW5lYWzDs2dpY28gKGVzdG8gc2UgZGViZSBhIHF1ZSBlcyBuZWNlc2FyaW8gbGltcGlhciBlbCBvYmpldG8gcGVkKS4KCgoKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQpwYXRzaW0gPC0gdmVjdG9yKCJsaXN0IiwgbnVtc2ltcykKdW5jbGVzaW0gPC0gdmVjdG9yKCJsaXN0IiwgbnVtc2ltcykKc2lic2ltIDwtIHZlY3RvcigibGlzdCIsIG51bXNpbXMpCmhhbGZzaW0gPC0gdmVjdG9yKCJsaXN0IiwgbnVtc2ltcykKZ3JhbmRzaW0gPC0gdmVjdG9yKCJsaXN0IiwgbnVtc2ltcykKCmZvciAoaSBpbiAxOm51bXNpbXMpIHsKICBwYXRzaW1bW2ldXSA8LSBzaW1MUmdlbihwYXRlcm5pdHlbW2ldXSwgbWlzc2luZyA9IDMsIG51bXNpbXMgPSAyLCBzZWVkID0gaSkKICB1bmNsZXNpbVtbaV1dIDwtIHNpbUxSZ2VuKHVuY2xlW1tpXV0sIG1pc3NpbmcgPSA2LCBudW1zaW1zID0gMiwgc2VlZCA9IGkpCiAgc2lic2ltW1tpXV0gPC0gc2ltTFJnZW4oc2libGluZ1tbaV1dLCBtaXNzaW5nID0gNCwgbnVtc2ltcyA9IDIsIHNlZWQgPSBpKQogIGhhbGZzaW1bW2ldXSA8LSBzaW1MUmdlbihoYWxmU2liW1tpXV0sIG1pc3NpbmcgPSA1LCBudW1zaW1zID0gMiwgc2VlZCA9IGkpCiAgZ3JhbmRzaW1bW2ldXSA8LSBzaW1MUmdlbihncmFuZHBhcmVudFtbaV1dLCBtaXNzaW5nID0gNSwgbnVtc2ltcyA9IDIsIHNlZWQgPSBpKQp9CmBgYAoKClkgYWhvcmEgcG9kZW1vcyBleHRyYWVyIGxvcyByZXN1bHRhZG9zIHV0aWxpemFuZG8gYWxndW5hcyBmdW5jaW9uZXMgcGVyc29uYWxpemFkYXM6CgoKYGBge3J9CiMgRnVuY2nDs24gcGFyYSBhcGxpY2FyIHNpbUxSMmRhdGFmcmFtZSBhIGNhZGEgc2ltdWxhY2nDs24gZGVudHJvIGRlIGxhIGxpc3RhIHkgY29tYmluYXIgbG9zIHJlc3VsdGFkb3MKY29tYmluZV9zaW1fcmVzdWx0cyA8LSBmdW5jdGlvbihzaW1fbGlzdCkgewogICMgQ3JlYXIgdW5hIGxpc3RhIHZhY8OtYSBwYXJhIGFsbWFjZW5hciBsb3MgZGF0YWZyYW1lcyBkZSBjYWRhIHNpbXVsYWNpw7NuCiAgZGZfbGlzdCA8LSBsaXN0KCkKICAKICAjIEl0ZXJhciBzb2JyZSBjYWRhIHNpbXVsYWNpw7NuIGRlbnRybyBkZSBsYSBsaXN0YSBzaW1fbGlzdAogIGZvciAoaSBpbiAxOmxlbmd0aChzaW1fbGlzdCkpIHsKICAgICMgQXBsaWNhciBsYSBmdW5jacOzbiBzaW1MUjJkYXRhZnJhbWUgYSBjYWRhIHNpbXVsYWNpw7NuCiAgICBkZiA8LSBzaW1MUjJkYXRhZnJhbWUoc2ltX2xpc3RbW2ldXSkKICAgIGRmX2xpc3RbW2ldXSA8LSBkZiAgIyBHdWFyZGFyIGVsIGRhdGFmcmFtZSBlbiBsYSBsaXN0YQogIH0KICAKICAjIENvbWJpbmFyIHRvZG9zIGxvcyBkYXRhZnJhbWVzIGVuIHVubyBzb2xvCiAgY29tYmluZWRfZGYgPC0gZG8uY2FsbChyYmluZCwgZGZfbGlzdCkKICAKICByZXR1cm4oY29tYmluZWRfZGYpCn0KCiMgQ3JlYXIgZGF0YWZyYW1lcyBjb21iaW5hZG9zIHBhcmEgY2FkYSByZWxhY2nDs24gZGUgcGFyZW50ZXNjbwpkZl9wYXRzaW1fY29tYmluZWQgPC0gY29tYmluZV9zaW1fcmVzdWx0cyhwYXRzaW0pCmRmX3VuY2xlc2ltX2NvbWJpbmVkIDwtIGNvbWJpbmVfc2ltX3Jlc3VsdHModW5jbGVzaW0pCmRmX3NpYnNpbV9jb21iaW5lZCA8LSBjb21iaW5lX3NpbV9yZXN1bHRzKHNpYnNpbSkKZGZfaGFsZnNpbV9jb21iaW5lZCA8LSBjb21iaW5lX3NpbV9yZXN1bHRzKGhhbGZzaW0pCmRmX2dyYW5kc2ltX2NvbWJpbmVkIDwtIGNvbWJpbmVfc2ltX3Jlc3VsdHMoZ3JhbmRzaW0pCmBgYAoKQWhvcmEgcHVlZGVzIHZpc3VhbGl6YXIgeSBhbmFsaXphciBmw6FjaWxtZW50ZSBsb3MgZGF0b3Mgb2J0ZW5pZG9zIDopCgpMb3MgUmVsYXRlZCBzb24gbG9zIExScyBvYnRlbmlkb3MgYmFqbyBIMSwgeSBsb3MgVW5yZWxhdGVkIHNvbiBsb3MgTFJzIG9idGVuaWRvcyBiYWpvIEgyLgoKCmBgYHtyfQpoZWFkKGRmX3BhdHNpbV9jb21iaW5lZCkKYGBgCgpDb250YW1vcyBjb24gdmFyaWFzIG3DqXRyaWNhcyBwYXJhIGV2YWx1YXIgZWwgcmVuZGltaWVudG8uIFBvciBmYXZvciwgY29uc3VsdGEgW0lUcGFwZXJdKGh0dHBzOi8vcHVibWVkLm5jYmkubmxtLm5paC5nb3YvMzgzODIyNDgvKSB5IFtEZWNpc2lvbnNdKGh0dHBzOi8vd3d3LnNjaWVuY2VkaXJlY3QuY29tL3NjaWVuY2UvYXJ0aWNsZS9hYnMvcGlpL1MxODcyNDk3MzIxMDAwNTcwKSBwYXJhIG9idGVuZXIgbcOhcyBpbmZvcm1hY2nDs24uCgoKIyMjIENvbmNsdXNpb25lcwpFbiBlc3RlIGFuw6FsaXNpcywgaGVtb3MgZXZhbHVhZG8gZWwgcG9kZXIgZXN0YWTDrXN0aWNvIGRlIHVuYSBiYXNlIGRlIGRhdG9zIGRlIGZyZWN1ZW5jaWFzIGFsw6lsaWNhcyB1dGlsaXphbmRvIGRpZmVyZW50ZXMgcmVsYWNpb25lcyBkZSBwYXJlbnRlc2NvLiBMb3MgcmVzdWx0YWRvcyBvYnRlbmlkb3Mgbm9zIHBlcm1pdGVuIGNvbXByZW5kZXIgbWVqb3IgY8OzbW8gbG9zIG1hcmNhZG9yZXMgZ2Vuw6l0aWNvcyBzZWxlY2Npb25hZG9zIGNvbnRyaWJ1eWVuIGEgbGEgZGlzY3JpbWluYWNpw7NuIGVudHJlIGhpcMOzdGVzaXMgZGUgcGFyZW50ZXNjbyB5IG5vIHBhcmVudGVzY28uCgpFc3RlIGVuZm9xdWUgcHVlZGUgc2VyIGV4dGVuZGlkbyB5IGFkYXB0YWRvIHBhcmEgaW5jb3Jwb3JhciBudWV2YXMgYmFzZXMgZGUgZGF0b3MsIGRpZmVyZW50ZXMgbWFyY2Fkb3JlcyBnZW7DqXRpY29zIHkgb3RyYXMgcmVsYWNpb25lcyBkZSBwYXJlbnRlc2NvLCBwcm9wb3JjaW9uYW5kbyB1bmEgaGVycmFtaWVudGEgZmxleGlibGUgcGFyYSBsYSBnZW7DqXRpY2EgZm9yZW5zZSB5IGVzdHVkaW9zIGRlIHBhcmVudGVzY28uCgo=