Paquete spapstat
Caja de herramientas integral de código abierto para analizar patrones de puntos espaciales. Centrado principalmente en patrones de puntos bidimensionales, incluidos puntos marcados/multitipo, en cualquier región espacial. También admite patrones de puntos tridimensionales, patrones de puntos de espacio-tiempo en cualquier número de dimensiones, patrones de puntos en una red lineal y patrones de otros objetos geométricos. Admite datos covariables espaciales, como imágenes de píxeles. Documentación
library(spatstat)
library(maptools)
Datos
Datos de pinos suecos de Strand-Ripley
swedishpines
Planar point pattern: 71 points
window: rectangle = [0, 96] x [0, 100] units (one unit = 0.1
metres)
class(swedishpines)
[1] "ppp"
summary(swedishpines)
Planar point pattern: 71 points
Average intensity 0.007395833 points per square unit (one unit
= 0.1 metres)
Coordinates are integers
i.e. rounded to the nearest unit (one unit = 0.1 metres)
Window: rectangle = [0, 96] x [0, 100] units
Window area = 9600 square units
Unit of length: 0.1 metres
plot(swedishpines)

Más documentación
Para una introducción rápida a Spatstat, lea la viñeta del paquete Getting started with spatstat instalado con Spatstat. Para leer ese documento, puede:
vignette("datasets")
Generando coordenadas aleatorias
La función runiff obtiene números decimales aleatorios de 0 a 1. Esta función está incluida dentro del paquete de R llamado stats.
x <- runif(20)
y <- runif(20)
Creando patrón de puntos
ppp: Crea un patrón de puntos a partir de \((x, y)\) y la información de la ventana:
ppp (x, y, xlim, ylim) para ventana rectangular
ppp (x, y, poly) para ventana poligonal
ppp (x, y, máscara) para la ventana de imagen binaria
X <- ppp(x, y, c(0,1), c(0,1))
X <- ppp(x, y)
X <- ppp(x, y, window=owin(c(0,1),c(0,1)))
class(X)
[1] "ppp"
summary(X)
Planar point pattern: 20 points
Average intensity 20 points per square unit
Coordinates are given to 8 decimal places
Window: rectangle = [0, 1] x [0, 1] units
Window area = 1 square unit
plot(X)

Datos-vesicles
Convirtiendo DataFrame a PPP
Patrón de puntos de vesículas sinápticas observado en tejido cerebral de rata.
# Estableciendo nueva ubicacion
setwd("C:/Users/EQUIPO/Documents/EstadisticaEspacial/data/vesicles/")
Error in setwd("C:/Users/EQUIPO/Documents/EstadisticaEspacial/data/vesicles/") :
cannot change working directory
class(df)
[1] "data.frame"
head(df)
x y
1 467.0168 776.0189
2 445.3418 827.4970
3 364.0606 911.4876
4 323.4200 914.1969
5 339.6762 957.5469
6 345.0950 873.5563
Y1 <- ppp(df$x, df$y, c(22,587), c(11,1031))
class(Y1)
[1] "ppp"
plot(Y1)

summary(df)
x y
Min. :277.4 Min. : 55.33
1st Qu.:347.8 1st Qu.:440.06
Median :399.3 Median :637.84
Mean :403.9 Mean :597.57
3rd Qu.:461.6 3rd Qu.:762.47
Max. :548.3 Max. :957.55
Datos-finpines
Editando un PPP
Datos de pinos filandenses.
class(df1)
[1] "data.frame"
head(df1)
x y diameter height
1 -1.993875 0.9297642 1 1.7
2 -1.019901 0.4120694 1 1.7
3 -4.914071 1.9854250 1 1.6
4 -4.469962 1.4523900 5 4.1
5 -4.303847 0.9148214 3 3.1
6 -3.814774 0.8108644 4 4.3
Y2 = as.ppp(df1, owin(c(-5,5), c(-8,2)))
plot(Y2)

edit(Y2)
Marked planar point pattern: 126 points
Mark variables: diameter, height
window: rectangle = [-5, 5] x [-8, 2] units
** Removiendo punto fuera de la cuadrícula o ventana**
S = ppp(x=c(-0.2, runif(10)),y=c(0.3, runif(10)),
window=square(1))
1 point was rejected as lying outside the specified window
plot(S)

# Agregando punto
as.ppp(S)
Planar point pattern: 10 points
window: rectangle = [0, 1] x [0, 1] units
plot(as.ppp(S))

Graficando y editando punto fuera de la cuadrícula o ventana
# Grafica los puntos rechazados por estar fuera de la ventana
# de observacion
plot(attr(S, "rejects"))

edit(attr(S, "rejects"))
Planar point pattern: 1 point
window: polygonal boundary
enclosing rectangle: [-0.3665029, 1] x [0, 1.1536944] units
Verificando existencia de puntos duplicados
Simulación de Procesos Poisson no-homogéneos
Un Proceso puntual Poisson homogéneo son caracterizados por las siguientes propiedades: Homogeneidad e Independencia. Además, se le llama “Proceso Poisson” porque el número de puntos que caen en cualquier región sigue una distribución de Poisson. En muchas pruebas estadísticas, el CSR sirve como hipótesis nula.
- La intensidad puede ser una constante
pp <- rpoispp(5)
pp
Planar point pattern: 9 points
window: rectangle = [0, 1] x [0, 1] units
plot(pp)

summary(pp)
Planar point pattern: 9 points
Average intensity 9 points per square unit
Coordinates are given to 8 decimal places
Window: rectangle = [0, 1] x [0, 1] units
Window area = 1 square unit
- La intensidad puede ser una función (x,y) o una imagen pixelada
lambda = function(x,y) { 100 *(x^2+y)}
X = rpoispp(lambda, win = square(1))
X
Planar point pattern: 78 points
window: rectangle = [0, 1] x [0, 1] units
plot(X)

summary(X)
Planar point pattern: 78 points
Average intensity 78 points per square unit
Coordinates are given to 8 decimal places
Window: rectangle = [0, 1] x [0, 1] units
Window area = 1 square unit
Tarea 1
Consultar las clases de objetos que se pueden obtener en el paquete spatstat.
Los principales tipos de datos espaciales admitidos por Spatstat son:
ppp: patrón de puntos ppp
Para crear un patrón de puntos: Crea un patrón de puntos a partir de (x, y) y la información de la ventana.
owin: ventana propia (región espacial)
Para crear una ventana: Un objeto de clase “owin” describe una región espacial (una ventana de observación).
im: imagen de píxeles
Imágenes de píxeles: un objeto de la clase “im” representa una imagen de píxeles.
psp:patrón de segmento de línea
Patrones de segmento de línea Un objeto de la clase “psp” representa un patrón de segmentos de línea recta.
tess: teselación
Teselaciones: Un objeto de la clase “tess” representa una teselación.
pp3: patrón de puntos tridimensional
Patrones de puntos tridimensionales Un objeto de clase “pp3” representa un patrón de puntos tridimensional en una caja rectangular. La caja está representada por un objeto de clase “caja3”.
ppx: patrón de puntos en cualquier número de dimensiones.
Patrones de puntos de espacio-tiempo multidimensionales Un objeto de clase “ppx” representa un patrón de puntos en un espacio y / o tiempo multidimensional.
lpp: patrón de puntos en una red lineal
Patrones de puntos en una red lineal: un objeto de clase “lpp” representa un patrón de puntos en una red lineal (por ejemplo, accidentes de tráfico en una red de carreteras).
Tarea 2
Leer sección 3.1, 3.2 posiblemente 3.3
Libro PDF
3.1 ENCUESTAS Y EXPERIMENTOS
3.1.1 Diseño de un experimento o encuesta
- El consejo más importante sobre el diseño de un experimento es planificar todo el experimento, incluido el análisis de datos
3.1.2 Qué se necesita registrar
- Además de las coordenadas de los puntos en sí, es necesario registrar otros elementos, como la ventana de observación, covariables espacilaes.
- Es una buena práctica registrar la hora a la que se realizó cada observación y buscar cualquier tendencia aparente a lo largo del tiempo
3.1.3 Riesgos y buenas prácticas
- El mayor riesgo al registrar observaciones es que se omita o se pierda información importante.
- ¿Qué información resultará retrospectivamente relevante para nuestro análisis?
- No confunda estas dos ideas: “faltante” o “inobservable” (NA) es un concepto completamente diferente concepto de “ausente” (0).
- Registre la secuencia de operaciones aplicadas a los datos, explique los nombres de las variables, indique las unidades en el que se expresan, etc.
3.2 MANEJO DE DATOS
3.2.1 Formatos de archivo de datos
- formato de tabla: los datos se organizan en filas y columna
- Valores separados por comas (csv): el software de hoja de cálculo.
- shapefiles: Un shapefile es un formato de archivo popular para compartir datos vectoriales entre paquetes de software del sistema de información geográfica (GIS).
3.2.2 Lectura de datos en R
- Los datos en un archivo de texto en formato de tabla se pueden leer en R usando el comando read.table.
- Los archivos de datos originales para el conjunto de datos de vesículas se instalan en Spatstat como ejemplo práctico.
3.3. INGRESAS DATOS DE PATRONES DE PUNTOS EN Spatstat
- 3.3.1 Crear un objeto “ppp”
- 3.3.2 Marcas
Marcas categóricas, marcas multivariadas
- 3.3.3 Unidades
Tarea 3
¿Cuáles serían los argumentos a considerar en la función PPP cuando la ventana de observación es un polígono?
# Librerias
library(GWmodel)
library(ggplot2)
# Leyendo coordenadas de los bordes
borde = readShapeSpatial(file.choose()) # Borde.shp
# Encontrando coordenadas
Borde = fortify(borde)
# Longitud y latitud
Borde$long = (Borde$long)/1000
Borde$lat = (Borde$lat)/1000
head(Borde)
# Leyendo coordenadas desde los datos
datos = read.csv(file.choose(), header=T) # Indicador.csv
datos$x = (datos$x)/1000
datos$y = (datos$y)/1000
La función rev() coloca las componentes de un vector en orden inverso a como han sido introducidas
# Matriz de coordenadas
Bor = cbind(Borde$long,Borde$lat)
colnames(Bor) = c("Long","Lat") # Matriz de coordenadas
# Reversa
lon = rev(Bor[,1])
lat = rev(Bor[,2])
# Poligono
p=list(x=lon, y=lat)
Z = owin(poly=p)
# Formamos objeto PPP
S = ppp(datos$x, datos$y, window=Z)
S
plot(S)
Tarea 4
Usando la función clickpoly crear una ventana de observación (ver sesión 3.9).
#-------------------------------------------------------------
# Dibuja manualmente ventana de graficacion
# clickpoly()
plot(S) # mapa de Medellín (ventana de observación)
prueba = clickpoly(add=TRUE) # crear otra ventana de observación
class(prueba)

# Convierte a objeto poligono espacial
library(rgdal)
plot(prueba)
pruebaSp = as(prueba, "SpatialPolygons")
pruebaSp1 = as(pruebaSp, "SpatialPolygonsDataFrame")
class(pruebaSp)
writePolyShape(pruebaSp1,'pruebaSp.shp') # guardar
LS0tDQp0aXRsZTogIioqUHJvY2Vzb3MgZGUgcGF0cm9uZXMgcHVudHVhbGVzKioiDQphdXRob3I6ICJFaWxpbiBMdW5hIE0uIg0KZGF0ZTogIjAyL01heW8vMjAyMSINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCiMjICoqUGFxdWV0ZSBzcGFwc3RhdCoqDQoNCkNhamEgZGUgaGVycmFtaWVudGFzIGludGVncmFsIGRlIGPDs2RpZ28gYWJpZXJ0byBwYXJhIGFuYWxpemFyIHBhdHJvbmVzIGRlIHB1bnRvcyBlc3BhY2lhbGVzLiBDZW50cmFkbyBwcmluY2lwYWxtZW50ZSBlbiBwYXRyb25lcyBkZSBwdW50b3MgYmlkaW1lbnNpb25hbGVzLCBpbmNsdWlkb3MgcHVudG9zIG1hcmNhZG9zL211bHRpdGlwbywgZW4gY3VhbHF1aWVyIHJlZ2nDs24gZXNwYWNpYWwuIFRhbWJpw6luIGFkbWl0ZSBwYXRyb25lcyBkZSBwdW50b3MgdHJpZGltZW5zaW9uYWxlcywgcGF0cm9uZXMgZGUgcHVudG9zIGRlIGVzcGFjaW8tdGllbXBvIGVuIGN1YWxxdWllciBuw7ptZXJvIGRlIGRpbWVuc2lvbmVzLCBwYXRyb25lcyBkZSBwdW50b3MgZW4gdW5hIHJlZCBsaW5lYWwgeSBwYXRyb25lcyBkZSBvdHJvcyBvYmpldG9zIGdlb23DqXRyaWNvcy4gQWRtaXRlIGRhdG9zIGNvdmFyaWFibGVzIGVzcGFjaWFsZXMsIGNvbW8gaW3DoWdlbmVzIGRlIHDDrXhlbGVzLiBbRG9jdW1lbnRhY2nDs25dKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9zcGF0c3RhdC9zcGF0c3RhdC5wZGYpDQoNCmBgYHtyfQ0KbGlicmFyeShzcGF0c3RhdCkNCmxpYnJhcnkobWFwdG9vbHMpDQpgYGANCg0KDQojIyAqKkRhdG9zKioNCg0KRGF0b3MgZGUgcGlub3Mgc3VlY29zIGRlIFN0cmFuZC1SaXBsZXkNCmBgYHtyfQ0Kc3dlZGlzaHBpbmVzDQpjbGFzcyhzd2VkaXNocGluZXMpDQpzdW1tYXJ5KHN3ZWRpc2hwaW5lcykNCnBsb3Qoc3dlZGlzaHBpbmVzKQ0KYGBgDQoNCiMjICoqTcOhcyBkb2N1bWVudGFjacOzbioqICANClBhcmEgdW5hIGludHJvZHVjY2nDs24gcsOhcGlkYSBhIFNwYXRzdGF0LCBsZWEgbGEgdmnDsWV0YSBkZWwgcGFxdWV0ZSAqR2V0dGluZyBzdGFydGVkIHdpdGggc3BhdHN0YXQqIGluc3RhbGFkbyBjb24gU3BhdHN0YXQuIFBhcmEgbGVlciBlc2UgZG9jdW1lbnRvLCBwdWVkZToNCg0KYGBge3J9DQp2aWduZXR0ZSgiZGF0YXNldHMiKQ0KYGBgDQoNCiMjICoqR2VuZXJhbmRvIGNvb3JkZW5hZGFzIGFsZWF0b3JpYXMqKg0KDQpMYSBmdW5jacOzbiBgcnVuaWZmYCBvYnRpZW5lIG7Dum1lcm9zIGRlY2ltYWxlcyBhbGVhdG9yaW9zIGRlIDAgYSAxLiBFc3RhIGZ1bmNpw7NuIGVzdMOhIGluY2x1aWRhIGRlbnRybyBkZWwgcGFxdWV0ZSBkZSBSIGxsYW1hZG8gc3RhdHMuDQoNCmBgYHtyfQ0KeCA8LSBydW5pZigyMCkNCnkgPC0gcnVuaWYoMjApDQpgYGANCg0KIyMgKipDcmVhbmRvIHBhdHLDs24gZGUgcHVudG9zKioNCg0KYHBwcGA6IENyZWEgdW4gcGF0csOzbiBkZSBwdW50b3MgYSBwYXJ0aXIgZGUgJCh4LCB5KSQgeSBsYSBpbmZvcm1hY2nDs24gZGUgbGEgdmVudGFuYTogIA0KDQoqIGBwcHAgKHgsIHksIHhsaW0sIHlsaW0pYCBwYXJhIHZlbnRhbmEgcmVjdGFuZ3VsYXINCiogYHBwcCAoeCwgeSwgcG9seSlgIHBhcmEgdmVudGFuYSBwb2xpZ29uYWwNCiogYHBwcCAoeCwgeSwgbcOhc2NhcmEpYCBwYXJhIGxhIHZlbnRhbmEgZGUgaW1hZ2VuIGJpbmFyaWENCg0KYGBge3J9DQpYIDwtIHBwcCh4LCB5LCBjKDAsMSksIGMoMCwxKSkNClggPC0gcHBwKHgsIHkpDQpYIDwtIHBwcCh4LCB5LCB3aW5kb3c9b3dpbihjKDAsMSksYygwLDEpKSkNCmBgYA0KDQpgYGB7cn0NCmNsYXNzKFgpDQpzdW1tYXJ5KFgpDQpwbG90KFgpDQpgYGANCg0KIyMgKipEYXRvcy12ZXNpY2xlcyoqDQojIyMgKipDb252aXJ0aWVuZG8gRGF0YUZyYW1lIGEgUFBQKioNCg0KUGF0csOzbiBkZSBwdW50b3MgZGUgdmVzw61jdWxhcyBzaW7DoXB0aWNhcyBvYnNlcnZhZG8gZW4gdGVqaWRvIGNlcmVicmFsIGRlIHJhdGEuDQoNCmBgYHtyfQ0KIyBFc3RhYmxlY2llbmRvIG51ZXZhIHViaWNhY2lvbg0Kc2V0d2QoIkM6L1VzZXJzL0VRVUlQTy9Eb2N1bWVudHMvRXN0YWRpc3RpY2FFc3BhY2lhbC9kYXRhL3Zlc2ljbGVzLyIpIA0KY29weUV4YW1wbGVGaWxlcygidmVzaWNsZXMiKQ0KZGYgPSByZWFkLnRhYmxlKCJ2ZXNpY2xlcy50eHQiLCBoZWFkZXI9VFJVRSkNCmBgYA0KDQpgYGB7ciBwYWdlZC5wcmludD1GQUxTRX0NCmNsYXNzKGRmKQ0KaGVhZChkZikNCmBgYA0KDQoNCmBgYHtyfQ0KIyBDb252aXJ0aWVuZG8gYSBwYXRyb25lcyBkZSBwdW50b3MgZXNwYWNpYWxlcw0KWTEgPC0gcHBwKGRmJHgsIGRmJHksICBjKDIyLDU4NyksIGMoMTEsMTAzMSkpDQpjbGFzcyhZMSkNCnBsb3QoWTEpDQpzdW1tYXJ5KGRmKQ0KYGBgDQojIyAqKkRhdG9zLWZpbnBpbmVzKioNCiMjIyAqKkVkaXRhbmRvIHVuIFBQUCoqDQoNCkRhdG9zIGRlIHBpbm9zIGZpbGFuZGVuc2VzLg0KDQpgYGB7cn0NCmNvcHlFeGFtcGxlRmlsZXMoJ2ZpbnBpbmVzJykNCmRmMSA9IHJlYWQudGFibGUoImZpbnBpbmVzLnR4dCIsIGhlYWRlcj1UUlVFKQ0KYGBgDQoNCmBgYHtyIHBhZ2VkLnByaW50PUZBTFNFfQ0KY2xhc3MoZGYxKQ0KaGVhZChkZjEpDQpZMiA9IGFzLnBwcChkZjEsIG93aW4oYygtNSw1KSwgYygtOCwyKSkpDQpwbG90KFkyKQ0KZWRpdChZMikNCmBgYA0KDQojIyAqKiBSZW1vdmllbmRvIHB1bnRvIGZ1ZXJhIGRlIGxhIGN1YWRyw61jdWxhIG8gdmVudGFuYSoqDQoNCmBgYHtyfQ0KUyA9IHBwcCh4PWMoLTAuMiwgcnVuaWYoMTApKSx5PWMoMC4zLCBydW5pZigxMCkpLA0KICAgICAgICB3aW5kb3c9c3F1YXJlKDEpKQ0KcGxvdChTKQ0KDQojIFJlbW92aWVuZG8gcHVudG8NCmFzLnBwcChTKQ0KcGxvdChhcy5wcHAoUykpDQpgYGANCg0KIyMjICoqR3JhZmljYW5kbyB5IGVkaXRhbmRvIHB1bnRvIGZ1ZXJhIGRlIGxhIGN1YWRyw61jdWxhIG8gdmVudGFuYSoqDQoNCmBgYHtyfQ0KIyBHcmFmaWNhIGxvcyBwdW50b3MgcmVjaGF6YWRvcyBwb3IgZXN0YXIgZnVlcmEgZGUgbGEgdmVudGFuYQ0KIyBkZSBvYnNlcnZhY2lvbg0KcGxvdChhdHRyKFMsICJyZWplY3RzIikpDQplZGl0KGF0dHIoUywgInJlamVjdHMiKSkNCmBgYA0KDQojIyMgKipWZXJpZmljYW5kbyBleGlzdGVuY2lhIGRlIHB1bnRvcyBkdXBsaWNhZG9zKioNCg0KYGBge3J9DQojIFZlcmlmaWNhIHNpIGhheSBleGlzdGVuY2lhIGRlIHB1bnRvcyBkdXBsaWNhZG9zDQpkdXBsaWNhdGVkKFMpDQp0YWJsZShkdXBsaWNhdGVkKFMpKQ0KDQptdWx0aXBsaWNpdHkoUykNCnRhYmxlKG11bHRpcGxpY2l0eShTKSkNCmBgYA0KDQojIyMgKipTaW11bGFjacOzbiBkZSBQcm9jZXNvcyBQb2lzc29uIG5vLWhvbW9nw6luZW9zKioNCg0KVW4gUHJvY2VzbyBwdW50dWFsIFBvaXNzb24gaG9tb2fDqW5lbyBzb24gY2FyYWN0ZXJpemFkb3MgcG9yIGxhcyBzaWd1aWVudGVzIHByb3BpZWRhZGVzOiBIb21vZ2VuZWlkYWQgZSBJbmRlcGVuZGVuY2lhLiBBZGVtw6FzLCBzZSBsZSBsbGFtYSDigJxQcm9jZXNvIFBvaXNzb27igJ0gcG9ycXVlIGVsIG7Dum1lcm8gZGUgcHVudG9zIHF1ZSBjYWVuIGVuIGN1YWxxdWllciByZWdpw7NuIHNpZ3VlIHVuYSBkaXN0cmlidWNpw7NuIGRlIFBvaXNzb24uIEVuIG11Y2hhcyBwcnVlYmFzIGVzdGFkw61zdGljYXMsIGVsIENTUiBzaXJ2ZSBjb21vIGhpcMOzdGVzaXMgbnVsYS4NCg0KKiBMYSBpbnRlbnNpZGFkIHB1ZWRlIHNlciB1bmEgY29uc3RhbnRlDQoNCmBgYHtyfQ0KcHAgPC0gcnBvaXNwcCg1KQ0KcHANCnBsb3QocHApDQpzdW1tYXJ5KHBwKQ0KYGBgDQoNCiogTGEgaW50ZW5zaWRhZCBwdWVkZSBzZXIgdW5hIGZ1bmNpw7NuICh4LHkpIG8gdW5hIGltYWdlbiBwaXhlbGFkYQ0KYGBge3J9DQpsYW1iZGEgPSBmdW5jdGlvbih4LHkpIHsxMDAgKih4XjIreSl9DQpYID0gcnBvaXNwcChsYW1iZGEsIHdpbiA9IHNxdWFyZSgxKSkNClgNCnBsb3QoWCkNCnN1bW1hcnkoWCkNCmBgYA0KDQoNCg0KDQoNCg0KDQojICoqVGFyZWEgMSoqDQoqKkNvbnN1bHRhciBsYXMgY2xhc2VzIGRlIG9iamV0b3MgcXVlIHNlIHB1ZWRlbiBvYnRlbmVyIGVuIGVsIHBhcXVldGUgc3BhdHN0YXQuKioNCg0KTG9zIHByaW5jaXBhbGVzIHRpcG9zIGRlIGRhdG9zIGVzcGFjaWFsZXMgYWRtaXRpZG9zIHBvciBTcGF0c3RhdCBzb246DQoNCisgYHBwcGA6IHBhdHLDs24gZGUgcHVudG9zIHBwcCAgDQogICoqUGFyYSBjcmVhciB1biBwYXRyw7NuIGRlIHB1bnRvczoqKiBDcmVhIHVuIHBhdHLDs24gZGUgcHVudG9zIGEgcGFydGlyIGRlICh4LCB5KSB5IGxhIGluZm9ybWFjacOzbiBkZSBsYSB2ZW50YW5hLg0KICANCisgYG93aW5gOiB2ZW50YW5hIHByb3BpYSAocmVnacOzbiBlc3BhY2lhbCkgIA0KICAqKlBhcmEgY3JlYXIgdW5hIHZlbnRhbmE6KiogVW4gb2JqZXRvIGRlIGNsYXNlICJvd2luIiBkZXNjcmliZSB1bmEgcmVnacOzbiBlc3BhY2lhbCAodW5hIHZlbnRhbmEgZGUgb2JzZXJ2YWNpw7NuKS4NCiAgDQorIGBpbWA6IGltYWdlbiBkZSBww614ZWxlcyAgDQogICoqSW3DoWdlbmVzIGRlIHDDrXhlbGVzOioqIHVuIG9iamV0byBkZSBsYSBjbGFzZSAiaW0iIHJlcHJlc2VudGEgdW5hIGltYWdlbiBkZSBww614ZWxlcy4gDQogIA0KKyBgcHNwYDpwYXRyw7NuIGRlIHNlZ21lbnRvIGRlIGzDrW5lYSAgDQogICoqUGF0cm9uZXMgZGUgc2VnbWVudG8gZGUgbMOtbmVhKiogVW4gb2JqZXRvIGRlIGxhIGNsYXNlICJwc3AiIHJlcHJlc2VudGEgdW4gcGF0csOzbiBkZSBzZWdtZW50b3MgZGUgbMOtbmVhIHJlY3RhLg0KDQorIGB0ZXNzYDogdGVzZWxhY2nDs24gIA0KICAqKlRlc2VsYWNpb25lczoqKiBVbiBvYmpldG8gZGUgbGEgY2xhc2UgInRlc3MiIHJlcHJlc2VudGEgdW5hIHRlc2VsYWNpw7NuLg0KICANCisgYHBwM2A6IHBhdHLDs24gZGUgcHVudG9zIHRyaWRpbWVuc2lvbmFsICANCiAgKipQYXRyb25lcyBkZSBwdW50b3MgdHJpZGltZW5zaW9uYWxlcyoqIFVuIG9iamV0byBkZSBjbGFzZSAicHAzIiByZXByZXNlbnRhIHVuIHBhdHLDs24gZGUgcHVudG9zIHRyaWRpbWVuc2lvbmFsIGVuIHVuYSBjYWphIHJlY3Rhbmd1bGFyLiBMYSBjYWphIGVzdMOhIHJlcHJlc2VudGFkYSBwb3IgdW4gb2JqZXRvIGRlIGNsYXNlICJjYWphMyIuDQogIA0KKyBgcHB4YDogcGF0csOzbiBkZSBwdW50b3MgZW4gY3VhbHF1aWVyIG7Dum1lcm8gZGUgZGltZW5zaW9uZXMuICANCiAgKipQYXRyb25lcyBkZSBwdW50b3MgZGUgZXNwYWNpby10aWVtcG8gbXVsdGlkaW1lbnNpb25hbGVzKioNClVuIG9iamV0byBkZSBjbGFzZSAicHB4IiByZXByZXNlbnRhIHVuIHBhdHLDs24gZGUgcHVudG9zIGVuIHVuIGVzcGFjaW8geSAvIG8gdGllbXBvIG11bHRpZGltZW5zaW9uYWwuICANCg0KKyBgbHBwYDogcGF0csOzbiBkZSBwdW50b3MgZW4gdW5hIHJlZCBsaW5lYWwgIA0KICAqKlBhdHJvbmVzIGRlIHB1bnRvcyBlbiB1bmEgcmVkIGxpbmVhbDoqKiB1biBvYmpldG8gZGUgY2xhc2UgImxwcCIgcmVwcmVzZW50YSB1biBwYXRyw7NuIGRlIHB1bnRvcyBlbiB1bmEgcmVkIGxpbmVhbCAocG9yIGVqZW1wbG8sIGFjY2lkZW50ZXMgZGUgdHLDoWZpY28gZW4gdW5hIHJlZCBkZSBjYXJyZXRlcmFzKS4NCiAgDQojICoqVGFyZWEgMioqDQoqKkxlZXIgc2VjY2nDs24gMy4xLCAzLjIgcG9zaWJsZW1lbnRlIDMuMyoqICANCltMaWJybyBQREZdKGh0dHBzOi8vYXphaWV6bm90ZXNibG9nLmZpbGVzLndvcmRwcmVzcy5jb20vMjAxNy8wOC9zcGF0aWFsLXBvaW50LXBhdHRlcm5zX2NoYXBtYW4taGFsbC1jcmMtMjAxNi5wZGYpDQoNCiogKiozLjEgRU5DVUVTVEFTIFkgRVhQRVJJTUVOVE9TKiogIA0KKiozLjEuMSBEaXNlw7FvIGRlIHVuIGV4cGVyaW1lbnRvIG8gZW5jdWVzdGEqKiAgDQogICogRWwgY29uc2VqbyBtw6FzIGltcG9ydGFudGUgc29icmUgZWwgZGlzZcOxbyBkZSB1biBleHBlcmltZW50byBlcyBwbGFuaWZpY2FyIHRvZG8gZWwgZXhwZXJpbWVudG8sIGluY2x1aWRvIGVsIGFuw6FsaXNpcyBkZSBkYXRvcyAgDQoNCiAgKiozLjEuMiBRdcOpIHNlIG5lY2VzaXRhIHJlZ2lzdHJhcioqICANCiAgICAqIEFkZW3DoXMgZGUgbGFzIGNvb3JkZW5hZGFzIGRlIGxvcyBwdW50b3MgZW4gc8OtLCBlcyBuZWNlc2FyaW8gcmVnaXN0cmFyIG90cm9zIGVsZW1lbnRvcywgY29tbyBsYSB2ZW50YW5hIGRlIG9ic2VydmFjacOzbiwgY292YXJpYWJsZXMgZXNwYWNpbGFlcy4gIA0KICAgICogRXMgdW5hIGJ1ZW5hIHByw6FjdGljYSByZWdpc3RyYXIgbGEgaG9yYSBhIGxhIHF1ZSBzZSByZWFsaXrDsyBjYWRhIG9ic2VydmFjacOzbiB5IGJ1c2NhciBjdWFscXVpZXIgdGVuZGVuY2lhIGFwYXJlbnRlIGEgbG8gbGFyZ28gZGVsIHRpZW1wbyAgDQogICAgDQogICoqMy4xLjMgUmllc2dvcyB5IGJ1ZW5hcyBwcsOhY3RpY2FzKiogICAgDQogICAgKiBFbCBtYXlvciByaWVzZ28gYWwgcmVnaXN0cmFyIG9ic2VydmFjaW9uZXMgZXMgcXVlIHNlIG9taXRhIG8gc2UgcGllcmRhIGluZm9ybWFjacOzbiBpbXBvcnRhbnRlLiAgDQogICAgKiDCv1F1w6kgaW5mb3JtYWNpw7NuIHJlc3VsdGFyw6EgcmV0cm9zcGVjdGl2YW1lbnRlIHJlbGV2YW50ZSBwYXJhIG51ZXN0cm8gYW7DoWxpc2lzPyAgIA0KICAgICogTm8gY29uZnVuZGEgZXN0YXMgZG9zIGlkZWFzOiAiZmFsdGFudGUiIG8gImlub2JzZXJ2YWJsZSIgKE5BKSBlcyB1biBjb25jZXB0byBjb21wbGV0YW1lbnRlIGRpZmVyZW50ZSBjb25jZXB0byBkZSAiYXVzZW50ZSIgKDApLiAgIA0KICAgICogUmVnaXN0cmUgbGEgc2VjdWVuY2lhIGRlIG9wZXJhY2lvbmVzIGFwbGljYWRhcyBhIGxvcyBkYXRvcywgZXhwbGlxdWUgbG9zIG5vbWJyZXMgZGUgbGFzIHZhcmlhYmxlcywgaW5kaXF1ZSBsYXMgdW5pZGFkZXMgZW4gZWwgcXVlIHNlIGV4cHJlc2FuLCBldGMuICANCiAgDQoqICoqMy4yIE1BTkVKTyBERSBEQVRPUyoqIA0KDQogICoqMy4yLjEgRm9ybWF0b3MgZGUgYXJjaGl2byBkZSBkYXRvcyoqICANCiAgKiBmb3JtYXRvIGRlIHRhYmxhOiBsb3MgZGF0b3Mgc2Ugb3JnYW5pemFuIGVuIGZpbGFzIHkgY29sdW1uYSAgDQogICogVmFsb3JlcyBzZXBhcmFkb3MgcG9yIGNvbWFzIChjc3YpOiBlbCBzb2Z0d2FyZSBkZSBob2phIGRlIGPDoWxjdWxvLiAgDQogICogc2hhcGVmaWxlczogVW4gc2hhcGVmaWxlIGVzIHVuIGZvcm1hdG8gZGUgYXJjaGl2byBwb3B1bGFyIHBhcmEgY29tcGFydGlyIGRhdG9zIHZlY3RvcmlhbGVzIGVudHJlIHBhcXVldGVzIGRlIHNvZnR3YXJlIGRlbCBzaXN0ZW1hIGRlIGluZm9ybWFjacOzbiBnZW9ncsOhZmljYSAoR0lTKS4gICANCiAgDQogICoqMy4yLjIgTGVjdHVyYSBkZSBkYXRvcyBlbiBSKiogIA0KICAqIExvcyBkYXRvcyBlbiB1biBhcmNoaXZvIGRlIHRleHRvIGVuIGZvcm1hdG8gZGUgdGFibGEgc2UgcHVlZGVuIGxlZXIgZW4gUiB1c2FuZG8gZWwgY29tYW5kbyByZWFkLnRhYmxlLiAgDQogICogTG9zIGFyY2hpdm9zIGRlIGRhdG9zIG9yaWdpbmFsZXMgcGFyYSBlbCBjb25qdW50byBkZSBkYXRvcyBkZSB2ZXPDrWN1bGFzIHNlIGluc3RhbGFuIGVuIFNwYXRzdGF0IGNvbW8gZWplbXBsbyBwcsOhY3RpY28uICANCiAgDQoqICoqMy4zLiBJTkdSRVNBUyBEQVRPUyBERSBQQVRST05FUyBERSBQVU5UT1MgRU4gU3BhdHN0YXQqKiAgDQogICogMy4zLjEgQ3JlYXIgdW4gb2JqZXRvICJwcHAiICANCiAgKiAzLjMuMiBNYXJjYXMgIA0KICAgIE1hcmNhcyBjYXRlZ8OzcmljYXMsIG1hcmNhcyBtdWx0aXZhcmlhZGFzICANCiAgKiAzLjMuMyBVbmlkYWRlcyAgDQogIA0KIyAqKlRhcmVhIDMqKg0KKirCv0N1w6FsZXMgc2Vyw61hbiBsb3MgYXJndW1lbnRvcyBhIGNvbnNpZGVyYXIgZW4gbGEgZnVuY2nDs24gUFBQIGN1YW5kbyBsYSB2ZW50YW5hIGRlIG9ic2VydmFjacOzbiBlcyB1biBwb2zDrWdvbm8/KioNCg0KDQpgYGB7cn0NCiMgTGlicmVyaWFzDQpsaWJyYXJ5KEdXbW9kZWwpDQpsaWJyYXJ5KGdncGxvdDIpDQoNCiMgTGV5ZW5kbyBjb29yZGVuYWRhcyBkZSBsb3MgYm9yZGVzDQpib3JkZSA9IHJlYWRTaGFwZVNwYXRpYWwoZmlsZS5jaG9vc2UoKSkgIyBCb3JkZS5zaHAgDQoNCiMgRW5jb250cmFuZG8gY29vcmRlbmFkYXMNCkJvcmRlID0gZm9ydGlmeShib3JkZSkNCg0KIyBMb25naXR1ZCB5IGxhdGl0dWQNCkJvcmRlJGxvbmcgPSAoQm9yZGUkbG9uZykvMTAwMA0KQm9yZGUkbGF0ID0gKEJvcmRlJGxhdCkvMTAwMA0KaGVhZChCb3JkZSkNCg0KIyBMZXllbmRvIGNvb3JkZW5hZGFzIGRlc2RlIGxvcyBkYXRvcw0KZGF0b3MgPSByZWFkLmNzdihmaWxlLmNob29zZSgpLCBoZWFkZXI9VCkgIyBJbmRpY2Fkb3IuY3N2DQpkYXRvcyR4ID0gKGRhdG9zJHgpLzEwMDANCmRhdG9zJHkgPSAoZGF0b3MkeSkvMTAwMA0KYGBgDQoNCkxhIGZ1bmNpw7NuIHJldigpIGNvbG9jYSBsYXMgY29tcG9uZW50ZXMgZGUgdW4gdmVjdG9yIGVuIG9yZGVuIGludmVyc28gYSBjb21vIGhhbiBzaWRvIGludHJvZHVjaWRhcyANCg0KYGBge3IgcGFnZWQucHJpbnQ9RkFMU0V9DQojIE1hdHJpeiBkZSBjb29yZGVuYWRhcw0KQm9yID0gY2JpbmQoQm9yZGUkbG9uZyxCb3JkZSRsYXQpDQpjb2xuYW1lcyhCb3IpID0gYygiTG9uZyIsIkxhdCIpICMgTWF0cml6IGRlIGNvb3JkZW5hZGFzDQoNCiMgUmV2ZXJzYQ0KbG9uID0gcmV2KEJvclssMV0pDQpsYXQgPSByZXYoQm9yWywyXSkNCg0KIyBQb2xpZ29ubw0KcD1saXN0KHg9bG9uLCB5PWxhdCkNClogPSBvd2luKHBvbHk9cCkNCmBgYA0KDQpgYGB7cn0NCiMgRm9ybWFtb3Mgb2JqZXRvIFBQUA0KUyA9IHBwcChkYXRvcyR4LCBkYXRvcyR5LCB3aW5kb3c9WikNClMNCmBgYA0KDQpgYGB7cn0NCnBsb3QoUykNCmBgYA0KDQojICoqVGFyZWEgNCoqDQoNCioqVXNhbmRvIGxhIGZ1bmNpw7NuIGNsaWNrcG9seSBjcmVhciB1bmEgdmVudGFuYSBkZSBvYnNlcnZhY2nDs24gKHZlciBzZXNpw7NuIDMuOSkuKioNCg0KYGBge3Igd2FybmluZz1GQUxTRSwgcGFnZWQucHJpbnQ9RkFMU0V9DQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyBEaWJ1amEgbWFudWFsbWVudGUgdmVudGFuYSBkZSBncmFmaWNhY2lvbg0KIyBjbGlja3BvbHkoKQ0KcGxvdChTKSAjIG1hcGEgZGUgTWVkZWxsw61uICh2ZW50YW5hIGRlIG9ic2VydmFjacOzbikNCnBydWViYSA9IGNsaWNrcG9seShhZGQ9VFJVRSkgIyBjcmVhciBvdHJhIHZlbnRhbmEgZGUgb2JzZXJ2YWNpw7NuIA0KY2xhc3MocHJ1ZWJhKQ0KYGBgDQoNCiFbXShDOlxVc2Vyc1xFUVVJUE9cRG9jdW1lbnRzXEdpdEh1YlxFc3RhZGlzdGljYUVzcGFjaWFsXGltYWdlc1xtZWRlbGxpbi5wbmcpDQoNCmBgYHtyfQ0KIyBDb252aWVydGUgYSBvYmpldG8gcG9saWdvbm8gZXNwYWNpYWwNCmxpYnJhcnkocmdkYWwpDQpwbG90KHBydWViYSkNCnBydWViYVNwID0gYXMocHJ1ZWJhLCAiU3BhdGlhbFBvbHlnb25zIikNCnBydWViYVNwMSA9IGFzKHBydWViYVNwLCAiU3BhdGlhbFBvbHlnb25zRGF0YUZyYW1lIikNCmNsYXNzKHBydWViYVNwKQ0Kd3JpdGVQb2x5U2hhcGUocHJ1ZWJhU3AxLCdwcnVlYmFTcC5zaHAnKSAjIGd1YXJkYXIgDQpgYGANCg0KDQoNCg0KDQoNCg0KDQo=