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:

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=