1. ¿Por qué este cuaderno?

Este es un R Notebook que ilustra varias funcionalidades para obtener, procesar y visualizar modelos digitales de elevación en R. Tiene como objetivo respondera las activides del curso de Geomatica BÔsica de la Universidad Nacional durante este tiempo de distanciamiento social.

2. Introducción a elevatr

Los datos de elevación se utilizan para una amplia gama de aplicaciones, que incluyen, por ejemplo, visualización, hidrología y modelado ecológico. Obtener acceso a estos datos en R no ha tenido una sola interfaz, estÔ disponible a través de funciones en muchos paquetes o requiere acceso local a los datos. Esto ya no es necesario, ya que existe una variedad de API que brindan acceso programÔtico a los datos de elevación. El paquete elevatr se escribió para estandarizar el acceso a los datos de elevación desde las API web.

Para acceder a los datos de elevación rÔster (por ejemplo, un DEM), el paquete elevatr utiliza los mosaicos de terreno de Amazon Web Services. Utilizaremos esta funcionalidad en este cuaderno.

instalaremos la siguientes librerias: ā€œrgdalā€, ā€œrasterā€, ā€œelevatrā€, ā€œrasterVisā€, ā€œrglā€. Descomentar el siguiente comando

# install.packages("rgdal")
# install.packages("raster")
# install.packages("elevatr")
# install.packages("rasterVis")
# install.packages("rgl")

Ahora correremos las librerias instaladas

library(rasterVis)
Loading required package: raster
Loading required package: sp
Loading required package: lattice
Loading required package: latticeExtra
library(raster)
library(rgl)
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio
library(rgdal)
rgdal: version: 1.5-16, (SVN revision 1050)
Geospatial Data Abstraction Library extensions to R successfully loaded
Loaded GDAL runtime: GDAL 3.0.4, released 2020/01/28
Path to GDAL shared files: C:/Users/rojas/OneDrive/Documentos/R/win-library/4.0/rgdal/gdal
GDAL binary built with GEOS: TRUE 
Loaded PROJ runtime: Rel. 6.3.1, February 10th, 2020, [PJ_VERSION: 631]
Path to PROJ shared files: C:/Users/rojas/OneDrive/Documentos/R/win-library/4.0/rgdal/proj
Linking to sp version:1.4-2
To mute warnings of possible GDAL/OSR exportToProj4() degradation,
use options("rgdal_show_exportToProj4_warnings"="none") before loading rgdal.
library(elevatr)

3. Obtener datos de elevación rÔster

Hay varias fuentes de modelos digitales de elevación, como Shuttle Radar Topography Mission (SRTM), USGS National Elevation Dataset (NED), Global DEM (GDEM) y otras. Cada uno de estos DEM tiene ventajas y desventajas para su uso. Antes de su cierre en enero de 2018, Mapzen combinó varias de estas fuentes para crear un producto de elevación de síntesis que utiliza los mejores datos de elevación disponibles para una región determinada a un nivel de zoom determinado. Aunque cerrados, estos datos compilados por Mapzen son actualmente accesibles a través de Terrain Tiles en Amazon Web Services (AWS).

La entrada para get_elev_raster () es un data.frame con ubicaciones x (longitud) e y (latitud) como las dos primeras columnas, cualquier objeto sp o cualquier objeto rƔster y devuelve un RasterLayer de los mosaicos que se superponen al cuadro delimitador de la entrada. Si se recuperan varios mosaicos, la salida resultante es una capa rƔster combinada.

Usando get_elev_raster () para acceder a Terrain Tiles en AWS.

Como se mencionó, un marco de datos con columnas x e y, un objeto sp o un objeto raster debe ser la entrada y src debe establecerse en ā€œmapzenā€ (este es el valor predeterminado).

No hay diferencia en el uso de los tipos de datos de entrada sp y rƔster. El marco de datos requiere un prj. MostrarƩ ejemplos usando un SpatialPolygonsDataFrame.

Primero, necesitamos cargar un shapefile que represente a los municipios del departamento de Cauca, revisemos estos datos.

list.files("C:/Users/rojas/OneDrive/Escritorio/R estudio/Geomatica/Departamento/19_CAUCA/Cauca/ADMINISTRATIVO")
 [1] "MGN_DPTO_POLITICO.cpg"     "MGN_DPTO_POLITICO.dbf"    
 [3] "MGN_DPTO_POLITICO.prj"     "MGN_DPTO_POLITICO.sbn"    
 [5] "MGN_DPTO_POLITICO.sbx"     "MGN_DPTO_POLITICO.shp"    
 [7] "MGN_DPTO_POLITICO.shp.xml" "MGN_DPTO_POLITICO.shx"    
 [9] "MGN_MPIO_POLITICO.cpg"     "MGN_MPIO_POLITICO.dbf"    
[11] "MGN_MPIO_POLITICO.prj"     "MGN_MPIO_POLITICO.sbn"    
[13] "MGN_MPIO_POLITICO.sbx"     "MGN_MPIO_POLITICO.shp"    
[15] "MGN_MPIO_POLITICO.shp.xml" "MGN_MPIO_POLITICO.shx"    

Ahora, leamos el shapefile usando una función proporcionada por el paquete raster

(munic <-  shapefile("C:/Users/rojas/OneDrive/Escritorio/R estudio/Geomatica/Departamento/19_CAUCA/Cauca/ADMINISTRATIVO/MGN_MPIO_POLITICO.shp"))
class       : SpatialPolygonsDataFrame 
features    : 42 
extent      : -77.92834, -75.74782, 0.9580285, 3.328941  (xmin, xmax, ymin, ymax)
crs         : +proj=longlat +datum=WGS84 +no_defs 
variables   : 9
names       : DPTO_CCDGO, MPIO_CCDGO, MPIO_CNMBR,           MPIO_CRSLC,    MPIO_NAREA, MPIO_NANO, DPTO_CNMBR,     Shape_Leng,       Shape_Area 
min values  :         19,      19001,   ALMAGUER,                 1535,   56.65263628,      2017,      CAUCA, 0.367595051566, 0.00459170058711 
max values  :         19,      19845, VILLA RICA, Ordenanza 45 de 1914, 3619.37102503,      2017,      CAUCA,  3.67422122731,    0.29359453607 

Reviemos los atribusto del obejto munic

head(munic)

Seleccionemos solo la ciudad capital de este departamento.

## para entender el codigo se recomiendo revisar la documentación
##https://www.neonscience.org/dc-shapefile-attributes-r
Popay <- munic[munic$MPIO_CNMBR=="POPAYƃ\201N",]
plot(Popay, main="PopayƔn.", axes=TRUE)
plot(munic, add=TRUE)
invisible(text(coordinates(munic), labels=as.character(munic$MPIO_CNMBR), cex=0.8))

Con el siguiente comando descargaremos los datos de elevación:

elevation <- get_elev_raster(Popay, z = 8)
CRS object has comment, which is lost in outputCRS object has comment, which is lost in outputCRS object has comment, which is lost in outputDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definition
Downloading DEMs [=============>-------------]  50% eta:  3sDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definition
Downloading DEMs [===================>-------]  75% eta:  1sDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definition
Downloading DEMs [===========================] 100% eta:  0s
Discarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionDiscarded ellps WGS 84 in CRS definition: +proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defsDiscarded datum WGS_1984 in CRS definitionMerging DEMs
Reprojecting DEM to original projection
Note: Elevation units are in meters.
Note: The coordinate reference system is:
 +proj=longlat +datum=WGS84 +no_defs

Ahora, vamos a revisar qué hay dentro del objeto de elevación:

elevation
class      : RasterLayer 
dimensions : 1032, 1033, 1066056  (nrow, ncol, ncell)
resolution : 0.00275, 0.00275  (x, y)
extent     : -77.3575, -74.51675, -0.01287881, 2.825121  (xmin, xmax, ymin, ymax)
crs        : +proj=longlat +datum=WGS84 +no_defs 
source     : memory
names      : layer 
values     : -120.551, 4591.825  (min, max)

Observe algunas cosas sobre este DEM:

°dimensiones: el ā€œtamaƱoā€ del archivo en pĆ­xeles

°nrow, ncol: el número de filas y columnas en los datos (imagine una hoja de cÔlculo o una matriz).

°ncells: el número total de píxeles o celdas que componen el rÔster.

°resolución: el tamaño de cada píxel (en grados decimales en este caso). Recordemos que 1 grado decimal representa aproximadamente 111,11 km.

°extensión: la extensión espacial del rÔster. Este valor estarÔ en las mismas unidades de coordenadas que el sistema de referencia de coordenadas del rÔster.

°crs: la cadena del sistema de referencia de coordenadas para el rÔster. Este rÔster estÔ en coordenadas geogrÔficas con un datum de WGS 84.

plot(elevation, main="Este es el DEM descargado [metros]")
plot(Popay, add=TRUE)

4. Recorta los datos de elevación para que coincidan con la extensión del Ôrea de estudio

Note que el DEM cubre una extensión mayor que la que necesitamos. Esto se debe a la disposición espacial de los mosaicos de elevación en AWS.

De todos modos, es una buena idea guardar el DEM para el futuro.

writeRaster(elevation, filename="Popay", datatype='INT4S', overwrite=TRUE)
class      : RasterLayer 
dimensions : 1032, 1033, 1066056  (nrow, ncol, ncell)
resolution : 0.00275, 0.00275  (x, y)
extent     : -77.3575, -74.51675, -0.01287881, 2.825121  (xmin, xmax, ymin, ymax)
crs        : +proj=longlat +datum=WGS84 +no_defs 
source     : C:/Users/rojas/OneDrive/Escritorio/R estudio/Geomatica/Popay.grd 
names      : layer 
values     : -121, 4592  (min, max)

Ahora, recortemos los datos de elevación correspondientes a Cauca:

elev_crop = crop(elevation, Popay)
plot(elev_crop, main="Modelo de elevación digital recortado")
plot(Popay, add=TRUE)

Revisemos el nuevo objeto:

elev_crop
class      : RasterLayer 
dimensions : 95, 142, 13490  (nrow, ncol, ncell)
resolution : 0.00275, 0.00275  (x, y)
extent     : -76.7745, -76.384, 2.310871, 2.572121  (xmin, xmax, ymin, ymax)
crs        : +proj=longlat +datum=WGS84 +no_defs 
source     : memory
names      : layer 
values     : 1194.329, 4563.661  (min, max)

5. Vuelva a proyectar los datos de elevación

Al trabajar con DEM, siempre es una buena idea utilizar coordenadas de mapa en lugar de coordenadas geogrÔficas. Esto se debe al hecho de que, en coordenadas geogrÔficas, las unidades de dimensiones horizontales son grados decimales PERO la unidad de dimensión vertical son metros. Reproyectemos los datos de elevación.

Podemos ir a epsg.io y buscar la proyección de la zona MAGNA Colombia BogotÔ. Necesitamos obtener la definición de esta referencia espacial en formato PROJ.4 (el que se usa para las bibliotecas sp y rÔster. Copiemos el texto PROJ.4 y guÔrdelo.)

spatialref <- "+proj=tmerc +lat_0=4.596200416666666 +lon_0=-74.07750791666666 +k=1 +x_0=1000000 +y_0=1000000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs"

Ahora, podemos reproyectar los datos de elevación de las coordenadas geogrÔficas WGS84 en la zona MAGNA Colombia BogotÔ.

pr3 <- projectExtent(elev_crop, spatialref)

res(pr3) <- 100

rep_elev <- projectRaster(elev_crop, pr3)

¿Qué tenemos?

rep_elev
class      : RasterLayer 
dimensions : 290, 435, 126150  (nrow, ncol, ncell)
resolution : 100, 100  (x, y)
extent     : 699903.5, 743403.5, 747497, 776497  (xmin, xmax, ymin, ymax)
crs        : +proj=tmerc +lat_0=4.59620041666667 +lon_0=-74.0775079166667 +k=1 +x_0=1000000 +y_0=1000000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs 
source     : memory
names      : layer 
values     : 1179.856, 4566.843  (min, max)

Ahora, volvamos a proyectar el SpatialPolygonsDataFrame que representa la capital de nuestro departamento:

(rep_Popay = spTransform(Popay,spatialref))
Discarded datum Unknown based on GRS80 ellipsoid in CRS definition,
 but +towgs84= values preserved
class       : SpatialPolygonsDataFrame 
features    : 1 
extent      : 700089, 743251.7, 747584.8, 776638.3  (xmin, xmax, ymin, ymax)
crs         : +proj=tmerc +lat_0=4.59620041666667 +lon_0=-74.0775079166667 +k=1 +x_0=1000000 +y_0=1000000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs 
variables   : 9
names       : DPTO_CCDGO, MPIO_CCDGO, MPIO_CNMBR, MPIO_CRSLC,   MPIO_NAREA, MPIO_NANO, DPTO_CNMBR,    Shape_Leng,     Shape_Area 
value       :         19,      19001,   POPAYÁN,       1537, 480.17981672,      2017,      CAUCA, 1.37293710691, 0.038969995214 

Es tiempo de trazar:

plot(rep_elev, main="Reprojected Digital elevation model")
plot(rep_Popay, add=TRUE)

Para evitar perder lo que llevamos, guardemos nuestro DEM:

writeRaster(rep_elev, filename="dem_rep_Popay_eleve.tif", datatype='INT4S', overwrite=TRUE)
Discarded datum Unknown_based_on_GRS80_ellipsoid in CRS definition: +proj=tmerc +lat_0=4.59620041666667 +lon_0=-74.0775079166667 +k=1 +x_0=1000000 +y_0=1000000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs,
 but +towgs84= values preservedDiscarded datum Unknown based on GRS80 ellipsoid in CRS definition,
 but +towgs84= values preserved

5. Estadísticas bÔsicas de datos de elevación

Una exploración rÔpida de las estadísticas de DEM:

hist(rep_elev)

promedio <- cellStats(rep_elev, 'mean')
minimo <- cellStats(rep_elev, 'min')
maximo <- cellStats(rep_elev, 'max')
desviacion  <- cellStats(rep_elev, 'sd')
# crear vector unidimensional
metricas <- c('mean', 'min', 'max', 'std')
valores <- c(promedio, minimo, maximo, desviacion)
# creacion de data frame con estadisticas de elevacion [metros]
# el parƩntesis externo sirve para "imprimir" el contenido de un objeto
 (df_estadisticas <- data.frame(metricas, valores))

6. Obtención de variables geomorfométricas

Primero, calcule la pendiente, el aspecto y el sombreado:

slope = terrain(rep_elev,opt='slope', unit='degrees')
aspect = terrain(rep_elev,opt='aspect',unit='degrees')
hill = hillShade(slope,aspect,40,315)

Elevación de la parcela. Tenga en cuenta la paleta de colores utilizada aquí.

plot(rep_elev,main="DEM para PopayƔn [metros]", col=terrain.colors(25,alpha=0.8))

Pendiente de la parcela. Tenga en cuenta la paleta de colores utilizada aquĆ­.

plot(slope,main="Pendiente para PopayƔn [grados]", col=topo.colors(25,alpha=0.7))

Aspecto de la parcela. Tenga en cuenta la paleta de colores utilizada aquĆ­.

plot(aspect,main="Aspecto para PopayƔn [grados]", col=rainbow(25,alpha=0.7))

Una trama combinada:

plot(hill,
        col=grey(1:100/100), # crea una rampa de color de colores grises para sombreado  
        legend=FALSE,  # sin leyenda, no nos importa el gris de la sombra       
        main="DEM para PopayƔn",
        axes=FALSE) # hace una trama mƔs limpia, si las coordenadas no son necesarias

plot(rep_elev, 
        axes=FALSE,
        col=terrain.colors(12, alpha=0.35), add=TRUE) 

7. Mapeo de datos de elevación con rayshader

La biblioteca rayshader es un paquete de código abierto para producir visualizaciones de datos 2D y 3D en R. rayshader usa datos de elevación en una matriz R base y una combinación de trazado de rayos, mapeo de textura esférica, superposiciones y oclusión ambiental para generar hermosos mapas topogrÔficos 2D y 3D . AdemÔs de los mapas, rayshader también permite al usuario traducir objetos ggplot2 en hermosas visualizaciones de datos en 3D.

# install.packages ("rayshader")
library(rayshader)

Convierta el DEM en una matriz:

elmat = raster_to_matrix(rep_elev)
[1] "Dimensions of matrix are: 435x290."

Usamos otra de las texturas integradas de rayshader:

elmat %>%
  sphere_shade(texture = "imhof2") %>%
  plot_map()

detect_water y add_water agregan una capa de agua al mapa:

elmat %>%
  sphere_shade(texture = "desert") %>%
  add_water(detect_water(elmat), color = "desert") %>%
  plot_map()

Y también podemos agregar una capa con trazado de rayos desde esa dirección del sol:

elmat %>%
  sphere_shade(texture = "desert") %>%
  add_water(detect_water(elmat), color = "desert") %>%
  add_shadow(ray_shade(elmat), 0.5) %>%
  plot_map()

8. Otra forma de visualización

Un experto en R sugiere aquí otra forma de visualización.

Vamos a intentarlo:

# install.packages("jpeg")
library(jpeg)

Función de sombreado de mapeo de entorno esférico

getv=function(i,a,s){
  ct = dim(i)[1:2]/2
  sx = values(s)/90 * ct[1]
  sy = values(s)/90 * ct[2]
  a = values(a) * 0.01745
  px = floor(ct[1] + sx * -sin(a))
  py = floor(ct[2] + sy * cos(a))
  
  
  template = brick(s,s,s)
  values(template)=NA
  
  cellr = px + py * ct[1]*2
  cellg = px + py * ct[1]*2 + (ct[1]*2*ct[2]*2)
  cellb = px + py * ct[1]*2 + 2*(ct[1]*2*ct[2]*2)
  
  template[[1]] = i[cellr]
  template[[2]] = i[cellg]
  template[[3]] = i[cellb]
  
  template = template * 256
  
  template
}

Cargar una imagen de mapa del entorno Se puede encontrar un ejemplo en http://i.imgur.com/9pvbHjN.jpg

map=readJPEG("C:/Users/rojas/OneDrive/Escritorio/R estudio/Geomatica/9pvbHjN.jpg")

# Hacer el mapeo
out = getv(map, aspect, slope)
ning昼㹔n argumento finito para min; retornando Infningun argumento finito para max; retornando -Infning昼㹔n argumento finito para min; retornando Infningun argumento finito para max; retornando -Infning昼㹔n argumento finito para min; retornando Infningun argumento finito para max; retornando -Infning昼㹔n argumento finito para min; retornando Infningun argumento finito para max; retornando -Infning昼㹔n argumento finito para min; retornando Infningun argumento finito para max; retornando -Infning昼㹔n argumento finito para min; retornando Infningun argumento finito para max; retornando -Inf
# Traza montaƱas
plotRGB(out, main = "MontaƱas supuestamente bonitas en el PopayƔn")

sessionInfo()
R version 4.0.2 (2020-06-22)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 18363)

Matrix products: default

locale:
[1] LC_COLLATE=Spanish_Mexico.1252  LC_CTYPE=Spanish_Mexico.1252   
[3] LC_MONETARY=Spanish_Mexico.1252 LC_NUMERIC=C                   
[5] LC_TIME=Spanish_Mexico.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] jpeg_0.1-8.1  raster_3.3-13 sp_1.4-2     

loaded via a namespace (and not attached):
 [1] Rcpp_1.0.5        lattice_0.20-41   codetools_0.2-16 
 [4] digest_0.6.25     grid_4.0.2        jsonlite_1.7.0   
 [7] magrittr_1.5      evaluate_0.14     stringi_1.4.6    
[10] rlang_0.4.7       rmarkdown_2.3     tools_4.0.2      
[13] stringr_1.4.0     htmlwidgets_1.5.1 xfun_0.16        
[16] yaml_2.2.1        compiler_4.0.2    base64enc_0.1-3  
[19] htmltools_0.5.0   knitr_1.29       
LS0tDQp0aXRsZTogIkRhdG9zIGRlIGVsZXZhY2nDs24gZW4gUiINCmF1dGhvcjogIkpvaGFuIFMuIFJvamFzIENoLiINCmRhdGU6ICIyOS8wOS8yMDIwIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQoNCg0KLS0tDQojIyAxLiDCv1BvciBxdcOpIGVzdGUgY3VhZGVybm8/DQpFc3RlIGVzIHVuIFIgTm90ZWJvb2sgcXVlIGlsdXN0cmEgdmFyaWFzIGZ1bmNpb25hbGlkYWRlcyBwYXJhIG9idGVuZXIsIHByb2Nlc2FyIHkgdmlzdWFsaXphciBtb2RlbG9zIGRpZ2l0YWxlcyBkZSBlbGV2YWNpw7NuIGVuIFIuIFRpZW5lIGNvbW8gb2JqZXRpdm8gcmVzcG9uZGVyYSBsYXMgYWN0aXZpZGVzIGRlbCBjdXJzbyBkZSAgR2VvbWF0aWNhIELDoXNpY2EgZGUgbGEgVW5pdmVyc2lkYWQgTmFjaW9uYWwgZHVyYW50ZSBlc3RlIHRpZW1wbyBkZSBkaXN0YW5jaWFtaWVudG8gc29jaWFsLiANCg0KIyMgMi4gSW50cm9kdWNjacOzbiBhIGVsZXZhdHINCkxvcyBkYXRvcyBkZSBlbGV2YWNpw7NuIHNlIHV0aWxpemFuIHBhcmEgdW5hIGFtcGxpYSBnYW1hIGRlIGFwbGljYWNpb25lcywgcXVlIGluY2x1eWVuLCBwb3IgZWplbXBsbywgdmlzdWFsaXphY2nDs24sIGhpZHJvbG9nw61hIHkgbW9kZWxhZG8gZWNvbMOzZ2ljby4gT2J0ZW5lciBhY2Nlc28gYSBlc3RvcyBkYXRvcyBlbiBSIG5vIGhhIHRlbmlkbyB1bmEgc29sYSBpbnRlcmZheiwgZXN0w6EgZGlzcG9uaWJsZSBhIHRyYXbDqXMgZGUgZnVuY2lvbmVzIGVuIG11Y2hvcyBwYXF1ZXRlcyBvIHJlcXVpZXJlIGFjY2VzbyBsb2NhbCBhIGxvcyBkYXRvcy4gRXN0byB5YSBubyBlcyBuZWNlc2FyaW8sIHlhIHF1ZSBleGlzdGUgdW5hIHZhcmllZGFkIGRlIEFQSSBxdWUgYnJpbmRhbiBhY2Nlc28gcHJvZ3JhbcOhdGljbyBhIGxvcyBkYXRvcyBkZSBlbGV2YWNpw7NuLiBFbCBwYXF1ZXRlIGVsZXZhdHIgc2UgZXNjcmliacOzIHBhcmEgZXN0YW5kYXJpemFyIGVsIGFjY2VzbyBhIGxvcyBkYXRvcyBkZSBlbGV2YWNpw7NuIGRlc2RlIGxhcyBBUEkgd2ViLg0KDQpQYXJhIGFjY2VkZXIgYSBsb3MgZGF0b3MgZGUgZWxldmFjacOzbiByw6FzdGVyIChwb3IgZWplbXBsbywgdW4gREVNKSwgZWwgcGFxdWV0ZSBlbGV2YXRyIHV0aWxpemEgbG9zIG1vc2FpY29zIGRlIHRlcnJlbm8gZGUgQW1hem9uIFdlYiBTZXJ2aWNlcy4gVXRpbGl6YXJlbW9zIGVzdGEgZnVuY2lvbmFsaWRhZCBlbiBlc3RlIGN1YWRlcm5vLg0KDQppbnN0YWxhcmVtb3MgbGEgc2lndWllbnRlcyBsaWJyZXJpYXM6ICJyZ2RhbCIsICJyYXN0ZXIiLCAiZWxldmF0ciIsICJyYXN0ZXJWaXMiLCAicmdsIi4gRGVzY29tZW50YXIgZWwgc2lndWllbnRlIGNvbWFuZG8NCmBgYHtyfQ0KIyBpbnN0YWxsLnBhY2thZ2VzKCJyZ2RhbCIpDQojIGluc3RhbGwucGFja2FnZXMoInJhc3RlciIpDQojIGluc3RhbGwucGFja2FnZXMoImVsZXZhdHIiKQ0KIyBpbnN0YWxsLnBhY2thZ2VzKCJyYXN0ZXJWaXMiKQ0KIyBpbnN0YWxsLnBhY2thZ2VzKCJyZ2wiKQ0KYGBgDQpBaG9yYSBjb3JyZXJlbW9zIGxhcyBsaWJyZXJpYXMgaW5zdGFsYWRhcyANCmBgYHtyfQ0KbGlicmFyeShyYXN0ZXJWaXMpDQpsaWJyYXJ5KHJhc3RlcikNCmxpYnJhcnkocmdsKQ0KbGlicmFyeShyZ2RhbCkNCmxpYnJhcnkoZWxldmF0cikNCmBgYA0KIyMgMy4gT2J0ZW5lciBkYXRvcyBkZSBlbGV2YWNpw7NuIHLDoXN0ZXINCkhheSB2YXJpYXMgZnVlbnRlcyBkZSBtb2RlbG9zIGRpZ2l0YWxlcyBkZSBlbGV2YWNpw7NuLCBjb21vIFNodXR0bGUgUmFkYXIgVG9wb2dyYXBoeSBNaXNzaW9uIChTUlRNKSwgVVNHUyBOYXRpb25hbCBFbGV2YXRpb24gRGF0YXNldCAoTkVEKSwgR2xvYmFsIERFTSAoR0RFTSkgeSBvdHJhcy4gQ2FkYSB1bm8gZGUgZXN0b3MgREVNIHRpZW5lIHZlbnRhamFzIHkgZGVzdmVudGFqYXMgcGFyYSBzdSB1c28uIEFudGVzIGRlIHN1IGNpZXJyZSBlbiBlbmVybyBkZSAyMDE4LCBNYXB6ZW4gY29tYmluw7MgdmFyaWFzIGRlIGVzdGFzIGZ1ZW50ZXMgcGFyYSBjcmVhciB1biBwcm9kdWN0byBkZSBlbGV2YWNpw7NuIGRlIHPDrW50ZXNpcyBxdWUgdXRpbGl6YSBsb3MgbWVqb3JlcyBkYXRvcyBkZSBlbGV2YWNpw7NuIGRpc3BvbmlibGVzIHBhcmEgdW5hIHJlZ2nDs24gZGV0ZXJtaW5hZGEgYSB1biBuaXZlbCBkZSB6b29tIGRldGVybWluYWRvLiBBdW5xdWUgY2VycmFkb3MsIGVzdG9zIGRhdG9zIGNvbXBpbGFkb3MgcG9yIE1hcHplbiBzb24gYWN0dWFsbWVudGUgYWNjZXNpYmxlcyBhIHRyYXbDqXMgZGUgVGVycmFpbiBUaWxlcyBlbiBBbWF6b24gV2ViIFNlcnZpY2VzIChBV1MpLg0KDQpMYSBlbnRyYWRhIHBhcmEgZ2V0X2VsZXZfcmFzdGVyICgpIGVzIHVuIGRhdGEuZnJhbWUgY29uIHViaWNhY2lvbmVzIHggKGxvbmdpdHVkKSBlIHkgKGxhdGl0dWQpIGNvbW8gbGFzIGRvcyBwcmltZXJhcyBjb2x1bW5hcywgY3VhbHF1aWVyIG9iamV0byBzcCBvIGN1YWxxdWllciBvYmpldG8gcsOhc3RlciB5IGRldnVlbHZlIHVuIFJhc3RlckxheWVyIGRlIGxvcyBtb3NhaWNvcyBxdWUgc2Ugc3VwZXJwb25lbiBhbCBjdWFkcm8gZGVsaW1pdGFkb3IgZGUgbGEgZW50cmFkYS4gU2kgc2UgcmVjdXBlcmFuIHZhcmlvcyBtb3NhaWNvcywgbGEgc2FsaWRhIHJlc3VsdGFudGUgZXMgdW5hIGNhcGEgcsOhc3RlciBjb21iaW5hZGEuDQoNCiMjIFVzYW5kbyBnZXRfZWxldl9yYXN0ZXIgKCkgcGFyYSBhY2NlZGVyIGEgVGVycmFpbiBUaWxlcyBlbiBBV1MuDQoNCkNvbW8gc2UgbWVuY2lvbsOzLCB1biBtYXJjbyBkZSBkYXRvcyBjb24gY29sdW1uYXMgeCBlIHksIHVuIG9iamV0byBzcCBvIHVuIG9iamV0byByYXN0ZXIgZGViZSBzZXIgbGEgZW50cmFkYSB5IHNyYyBkZWJlIGVzdGFibGVjZXJzZSBlbiDigJxtYXB6ZW7igJ0gKGVzdGUgZXMgZWwgdmFsb3IgcHJlZGV0ZXJtaW5hZG8pLg0KDQpObyBoYXkgZGlmZXJlbmNpYSBlbiBlbCB1c28gZGUgbG9zIHRpcG9zIGRlIGRhdG9zIGRlIGVudHJhZGEgc3AgeSByw6FzdGVyLiBFbCBtYXJjbyBkZSBkYXRvcyByZXF1aWVyZSB1biBwcmouIE1vc3RyYXLDqSBlamVtcGxvcyB1c2FuZG8gdW4gU3BhdGlhbFBvbHlnb25zRGF0YUZyYW1lLg0KDQpQcmltZXJvLCBuZWNlc2l0YW1vcyBjYXJnYXIgdW4gc2hhcGVmaWxlIHF1ZSByZXByZXNlbnRlIGEgbG9zIG11bmljaXBpb3MgZGVsIGRlcGFydGFtZW50byBkZSBDYXVjYSwgcmV2aXNlbW9zIGVzdG9zIGRhdG9zLg0KYGBge3J9DQpsaXN0LmZpbGVzKCJDOi9Vc2Vycy9yb2phcy9PbmVEcml2ZS9Fc2NyaXRvcmlvL1IgZXN0dWRpby9HZW9tYXRpY2EvRGVwYXJ0YW1lbnRvLzE5X0NBVUNBL0NhdWNhL0FETUlOSVNUUkFUSVZPIikNCmBgYA0KQWhvcmEsIGxlYW1vcyBlbCBzaGFwZWZpbGUgdXNhbmRvIHVuYSBmdW5jacOzbiBwcm9wb3JjaW9uYWRhIHBvciBlbCBwYXF1ZXRlIHJhc3Rlcg0KYGBge3J9DQoobXVuaWMgPC0gIHNoYXBlZmlsZSgiQzovVXNlcnMvcm9qYXMvT25lRHJpdmUvRXNjcml0b3Jpby9SIGVzdHVkaW8vR2VvbWF0aWNhL0RlcGFydGFtZW50by8xOV9DQVVDQS9DYXVjYS9BRE1JTklTVFJBVElWTy9NR05fTVBJT19QT0xJVElDTy5zaHAiKSkNCmBgYA0KUmV2aWVtb3MgbG9zIGF0cmlidXN0byBkZWwgb2JlanRvIG11bmljDQpgYGB7cn0NCmhlYWQobXVuaWMpDQpgYGANClNlbGVjY2lvbmVtb3Mgc29sbyBsYSBjaXVkYWQgY2FwaXRhbCBkZSBlc3RlIGRlcGFydGFtZW50by4NCmBgYHtyfQ0KIyMgcGFyYSBlbnRlbmRlciBlbCBjb2RpZ28gc2UgcmVjb21pZW5kbyByZXZpc2FyIGxhIGRvY3VtZW50YWNpw7NuDQojI2h0dHBzOi8vd3d3Lm5lb25zY2llbmNlLm9yZy9kYy1zaGFwZWZpbGUtYXR0cmlidXRlcy1yDQpQb3BheSA8LSBtdW5pY1ttdW5pYyRNUElPX0NOTUJSPT0iUE9QQVnDg1wyMDFOIixdDQpwbG90KFBvcGF5LCBtYWluPSJQb3BhecOhbi4iLCBheGVzPVRSVUUpDQpwbG90KG11bmljLCBhZGQ9VFJVRSkNCmludmlzaWJsZSh0ZXh0KGNvb3JkaW5hdGVzKG11bmljKSwgbGFiZWxzPWFzLmNoYXJhY3RlcihtdW5pYyRNUElPX0NOTUJSKSwgY2V4PTAuOCkpDQpgYGANCkNvbiBlbCBzaWd1aWVudGUgY29tYW5kbyBkZXNjYXJnYXJlbW9zIGxvcyBkYXRvcyBkZSBlbGV2YWNpw7NuOg0KYGBge3J9DQplbGV2YXRpb24gPC0gZ2V0X2VsZXZfcmFzdGVyKFBvcGF5LCB6ID0gOCkNCmBgYA0KDQpBaG9yYSwgdmFtb3MgYSByZXZpc2FyIHF1w6kgaGF5IGRlbnRybyBkZWwgb2JqZXRvIGRlIGVsZXZhY2nDs246DQpgYGB7cn0NCmVsZXZhdGlvbg0KYGBgDQpPYnNlcnZlIGFsZ3VuYXMgY29zYXMgc29icmUgZXN0ZSBERU06DQoNCsKwZGltZW5zaW9uZXM6IGVsIOKAnHRhbWHDsW/igJ0gZGVsIGFyY2hpdm8gZW4gcMOteGVsZXMNCg0KwrBucm93LCBuY29sOiBlbCBuw7ptZXJvIGRlIGZpbGFzIHkgY29sdW1uYXMgZW4gbG9zIGRhdG9zIChpbWFnaW5lIHVuYSBob2phIGRlIGPDoWxjdWxvIG8gdW5hIG1hdHJpeikuDQoNCsKwbmNlbGxzOiBlbCBuw7ptZXJvIHRvdGFsIGRlIHDDrXhlbGVzIG8gY2VsZGFzIHF1ZSBjb21wb25lbiBlbCByw6FzdGVyLg0KDQrCsHJlc29sdWNpw7NuOiBlbCB0YW1hw7FvIGRlIGNhZGEgcMOteGVsIChlbiBncmFkb3MgZGVjaW1hbGVzIGVuIGVzdGUgY2FzbykuIFJlY29yZGVtb3MgcXVlIDEgZ3JhZG8gZGVjaW1hbCByZXByZXNlbnRhIGFwcm94aW1hZGFtZW50ZSAxMTEsMTEga20uDQoNCsKwZXh0ZW5zacOzbjogbGEgZXh0ZW5zacOzbiBlc3BhY2lhbCBkZWwgcsOhc3Rlci4gRXN0ZSB2YWxvciBlc3RhcsOhIGVuIGxhcyBtaXNtYXMgdW5pZGFkZXMgZGUgY29vcmRlbmFkYXMgcXVlIGVsIHNpc3RlbWEgZGUgcmVmZXJlbmNpYSBkZSBjb29yZGVuYWRhcyBkZWwgcsOhc3Rlci4NCg0KwrBjcnM6IGxhIGNhZGVuYSBkZWwgc2lzdGVtYSBkZSByZWZlcmVuY2lhIGRlIGNvb3JkZW5hZGFzIHBhcmEgZWwgcsOhc3Rlci4gRXN0ZSByw6FzdGVyIGVzdMOhIGVuIGNvb3JkZW5hZGFzIGdlb2dyw6FmaWNhcyBjb24gdW4gZGF0dW0gZGUgV0dTIDg0Lg0KYGBge3J9DQpwbG90KGVsZXZhdGlvbiwgbWFpbj0iRXN0ZSBlcyBlbCBERU0gZGVzY2FyZ2FkbyBbbWV0cm9zXSIpDQpwbG90KFBvcGF5LCBhZGQ9VFJVRSkNCmBgYA0KIyMgNC4gUmVjb3J0YSBsb3MgZGF0b3MgZGUgZWxldmFjacOzbiBwYXJhIHF1ZSBjb2luY2lkYW4gY29uIGxhIGV4dGVuc2nDs24gZGVsIMOhcmVhIGRlIGVzdHVkaW8NCk5vdGUgcXVlIGVsIERFTSBjdWJyZSB1bmEgZXh0ZW5zacOzbiBtYXlvciBxdWUgbGEgcXVlIG5lY2VzaXRhbW9zLiBFc3RvIHNlIGRlYmUgYSBsYSBkaXNwb3NpY2nDs24gZXNwYWNpYWwgZGUgbG9zIG1vc2FpY29zIGRlIGVsZXZhY2nDs24gZW4gQVdTLg0KDQpEZSB0b2RvcyBtb2RvcywgZXMgdW5hIGJ1ZW5hIGlkZWEgZ3VhcmRhciBlbCBERU0gcGFyYSBlbCBmdXR1cm8uDQpgYGB7cn0NCndyaXRlUmFzdGVyKGVsZXZhdGlvbiwgZmlsZW5hbWU9IlBvcGF5IiwgZGF0YXR5cGU9J0lOVDRTJywgb3ZlcndyaXRlPVRSVUUpDQpgYGANCkFob3JhLCByZWNvcnRlbW9zIGxvcyBkYXRvcyBkZSBlbGV2YWNpw7NuIGNvcnJlc3BvbmRpZW50ZXMgYSBDYXVjYToNCmBgYHtyfQ0KZWxldl9jcm9wID0gY3JvcChlbGV2YXRpb24sIFBvcGF5KQ0KcGxvdChlbGV2X2Nyb3AsIG1haW49Ik1vZGVsbyBkZSBlbGV2YWNpw7NuIGRpZ2l0YWwgcmVjb3J0YWRvIikNCnBsb3QoUG9wYXksIGFkZD1UUlVFKQ0KYGBgDQpSZXZpc2Vtb3MgZWwgbnVldm8gb2JqZXRvOg0KYGBge3J9DQplbGV2X2Nyb3ANCmBgYA0KIyMgNS4gVnVlbHZhIGEgcHJveWVjdGFyIGxvcyBkYXRvcyBkZSBlbGV2YWNpw7NuDQpBbCB0cmFiYWphciBjb24gREVNLCBzaWVtcHJlIGVzIHVuYSBidWVuYSBpZGVhIHV0aWxpemFyIGNvb3JkZW5hZGFzIGRlIG1hcGEgZW4gbHVnYXIgZGUgY29vcmRlbmFkYXMgZ2VvZ3LDoWZpY2FzLiBFc3RvIHNlIGRlYmUgYWwgaGVjaG8gZGUgcXVlLCBlbiBjb29yZGVuYWRhcyBnZW9ncsOhZmljYXMsIGxhcyB1bmlkYWRlcyBkZSBkaW1lbnNpb25lcyBob3Jpem9udGFsZXMgc29uIGdyYWRvcyBkZWNpbWFsZXMgUEVSTyBsYSB1bmlkYWQgZGUgZGltZW5zacOzbiB2ZXJ0aWNhbCBzb24gbWV0cm9zLiBSZXByb3llY3RlbW9zIGxvcyBkYXRvcyBkZSBlbGV2YWNpw7NuLg0KDQpQb2RlbW9zIGlyIGEgZXBzZy5pbyB5IGJ1c2NhciBsYSBwcm95ZWNjacOzbiBkZSBsYSB6b25hIE1BR05BIENvbG9tYmlhIEJvZ290w6EuIE5lY2VzaXRhbW9zIG9idGVuZXIgbGEgZGVmaW5pY2nDs24gZGUgZXN0YSByZWZlcmVuY2lhIGVzcGFjaWFsIGVuIGZvcm1hdG8gUFJPSi40IChlbCBxdWUgc2UgdXNhIHBhcmEgbGFzIGJpYmxpb3RlY2FzIHNwIHkgcsOhc3Rlci4gQ29waWVtb3MgZWwgdGV4dG8gUFJPSi40IHkgZ3XDoXJkZWxvLikNCmBgYHtyfQ0Kc3BhdGlhbHJlZiA8LSAiK3Byb2o9dG1lcmMgK2xhdF8wPTQuNTk2MjAwNDE2NjY2NjY2ICtsb25fMD0tNzQuMDc3NTA3OTE2NjY2NjYgK2s9MSAreF8wPTEwMDAwMDAgK3lfMD0xMDAwMDAwICtlbGxwcz1HUlM4MCArdG93Z3M4ND0wLDAsMCwwLDAsMCwwICt1bml0cz1tICtub19kZWZzIg0KYGBgDQpBaG9yYSwgcG9kZW1vcyByZXByb3llY3RhciBsb3MgZGF0b3MgZGUgZWxldmFjacOzbiBkZSBsYXMgY29vcmRlbmFkYXMgZ2VvZ3LDoWZpY2FzIFdHUzg0IGVuIGxhIHpvbmEgTUFHTkEgQ29sb21iaWEgQm9nb3TDoS4NCmBgYHtyfQ0KcHIzIDwtIHByb2plY3RFeHRlbnQoZWxldl9jcm9wLCBzcGF0aWFscmVmKQ0KDQpyZXMocHIzKSA8LSAxMDANCg0KcmVwX2VsZXYgPC0gcHJvamVjdFJhc3RlcihlbGV2X2Nyb3AsIHByMykNCmBgYA0Kwr9RdcOpIHRlbmVtb3M/DQpgYGB7cn0NCnJlcF9lbGV2DQpgYGANCkFob3JhLCB2b2x2YW1vcyBhIHByb3llY3RhciBlbCBTcGF0aWFsUG9seWdvbnNEYXRhRnJhbWUgcXVlIHJlcHJlc2VudGEgbGEgY2FwaXRhbCBkZSBudWVzdHJvIGRlcGFydGFtZW50bzoNCmBgYHtyfQ0KKHJlcF9Qb3BheSA9IHNwVHJhbnNmb3JtKFBvcGF5LHNwYXRpYWxyZWYpKQ0KYGBgDQpFcyB0aWVtcG8gZGUgdHJhemFyOg0KYGBge3J9DQpwbG90KHJlcF9lbGV2LCBtYWluPSJSZXByb2plY3RlZCBEaWdpdGFsIGVsZXZhdGlvbiBtb2RlbCIpDQpwbG90KHJlcF9Qb3BheSwgYWRkPVRSVUUpDQpgYGANClBhcmEgZXZpdGFyIHBlcmRlciBsbyBxdWUgbGxldmFtb3MsIGd1YXJkZW1vcyBudWVzdHJvIERFTToNCmBgYHtyfQ0Kd3JpdGVSYXN0ZXIocmVwX2VsZXYsIGZpbGVuYW1lPSJkZW1fcmVwX1BvcGF5X2VsZXZlLnRpZiIsIGRhdGF0eXBlPSdJTlQ0UycsIG92ZXJ3cml0ZT1UUlVFKQ0KYGBgDQojIyA1LiBFc3RhZMOtc3RpY2FzIGLDoXNpY2FzIGRlIGRhdG9zIGRlIGVsZXZhY2nDs24NCg0KVW5hIGV4cGxvcmFjacOzbiByw6FwaWRhIGRlIGxhcyBlc3RhZMOtc3RpY2FzIGRlIERFTToNCmBgYHtyfQ0KaGlzdChyZXBfZWxldikNCmBgYA0KYGBge3J9DQpwcm9tZWRpbyA8LSBjZWxsU3RhdHMocmVwX2VsZXYsICdtZWFuJykNCm1pbmltbyA8LSBjZWxsU3RhdHMocmVwX2VsZXYsICdtaW4nKQ0KbWF4aW1vIDwtIGNlbGxTdGF0cyhyZXBfZWxldiwgJ21heCcpDQpkZXN2aWFjaW9uICA8LSBjZWxsU3RhdHMocmVwX2VsZXYsICdzZCcpDQpgYGANCg0KYGBge3J9DQojIGNyZWFyIHZlY3RvciB1bmlkaW1lbnNpb25hbA0KbWV0cmljYXMgPC0gYygnbWVhbicsICdtaW4nLCAnbWF4JywgJ3N0ZCcpDQp2YWxvcmVzIDwtIGMocHJvbWVkaW8sIG1pbmltbywgbWF4aW1vLCBkZXN2aWFjaW9uKQ0KYGBgDQoNCmBgYHtyfQ0KIyBjcmVhY2lvbiBkZSBkYXRhIGZyYW1lIGNvbiBlc3RhZGlzdGljYXMgZGUgZWxldmFjaW9uIFttZXRyb3NdDQojIGVsIHBhcsOpbnRlc2lzIGV4dGVybm8gc2lydmUgcGFyYSAiaW1wcmltaXIiIGVsIGNvbnRlbmlkbyBkZSB1biBvYmpldG8NCiAoZGZfZXN0YWRpc3RpY2FzIDwtIGRhdGEuZnJhbWUobWV0cmljYXMsIHZhbG9yZXMpKQ0KYGBgDQojIyA2LiBPYnRlbmNpw7NuIGRlIHZhcmlhYmxlcyBnZW9tb3Jmb23DqXRyaWNhcw0KUHJpbWVybywgY2FsY3VsZSBsYSBwZW5kaWVudGUsIGVsIGFzcGVjdG8geSBlbCBzb21icmVhZG86DQpgYGB7cn0NCnNsb3BlID0gdGVycmFpbihyZXBfZWxldixvcHQ9J3Nsb3BlJywgdW5pdD0nZGVncmVlcycpDQphc3BlY3QgPSB0ZXJyYWluKHJlcF9lbGV2LG9wdD0nYXNwZWN0Jyx1bml0PSdkZWdyZWVzJykNCmhpbGwgPSBoaWxsU2hhZGUoc2xvcGUsYXNwZWN0LDQwLDMxNSkNCmBgYA0KRWxldmFjacOzbiBkZSBsYSBwYXJjZWxhLiBUZW5nYSBlbiBjdWVudGEgbGEgcGFsZXRhIGRlIGNvbG9yZXMgdXRpbGl6YWRhIGFxdcOtLg0KYGBge3J9DQpwbG90KHJlcF9lbGV2LG1haW49IkRFTSBwYXJhIFBvcGF5w6FuIFttZXRyb3NdIiwgY29sPXRlcnJhaW4uY29sb3JzKDI1LGFscGhhPTAuOCkpDQpgYGANClBlbmRpZW50ZSBkZSBsYSBwYXJjZWxhLiBUZW5nYSBlbiBjdWVudGEgbGEgcGFsZXRhIGRlIGNvbG9yZXMgdXRpbGl6YWRhIGFxdcOtLg0KYGBge3J9DQpwbG90KHNsb3BlLG1haW49IlBlbmRpZW50ZSBwYXJhIFBvcGF5w6FuIFtncmFkb3NdIiwgY29sPXRvcG8uY29sb3JzKDI1LGFscGhhPTAuNykpDQpgYGANCkFzcGVjdG8gZGUgbGEgcGFyY2VsYS4gVGVuZ2EgZW4gY3VlbnRhIGxhIHBhbGV0YSBkZSBjb2xvcmVzIHV0aWxpemFkYSBhcXXDrS4NCmBgYHtyfQ0KcGxvdChhc3BlY3QsbWFpbj0iQXNwZWN0byBwYXJhIFBvcGF5w6FuIFtncmFkb3NdIiwgY29sPXJhaW5ib3coMjUsYWxwaGE9MC43KSkNCmBgYA0KVW5hIHRyYW1hIGNvbWJpbmFkYToNCmBgYHtyfQ0KcGxvdChoaWxsLA0KICAgICAgICBjb2w9Z3JleSgxOjEwMC8xMDApLCAjIGNyZWEgdW5hIHJhbXBhIGRlIGNvbG9yIGRlIGNvbG9yZXMgZ3Jpc2VzIHBhcmEgc29tYnJlYWRvICANCiAgICAgICAgbGVnZW5kPUZBTFNFLCAgIyBzaW4gbGV5ZW5kYSwgbm8gbm9zIGltcG9ydGEgZWwgZ3JpcyBkZSBsYSBzb21icmEgICAgICAgDQogICAgICAgIG1haW49IkRFTSBwYXJhIFBvcGF5w6FuIiwNCiAgICAgICAgYXhlcz1GQUxTRSkgIyBoYWNlIHVuYSB0cmFtYSBtw6FzIGxpbXBpYSwgc2kgbGFzIGNvb3JkZW5hZGFzIG5vIHNvbiBuZWNlc2FyaWFzDQoNCnBsb3QocmVwX2VsZXYsIA0KICAgICAgICBheGVzPUZBTFNFLA0KICAgICAgICBjb2w9dGVycmFpbi5jb2xvcnMoMTIsIGFscGhhPTAuMzUpLCBhZGQ9VFJVRSkgDQpgYGANCiMjIDcuIE1hcGVvIGRlIGRhdG9zIGRlIGVsZXZhY2nDs24gY29uIHJheXNoYWRlcg0KTGEgYmlibGlvdGVjYSByYXlzaGFkZXIgZXMgdW4gcGFxdWV0ZSBkZSBjw7NkaWdvIGFiaWVydG8gcGFyYSBwcm9kdWNpciB2aXN1YWxpemFjaW9uZXMgZGUgZGF0b3MgMkQgeSAzRCBlbiBSLiByYXlzaGFkZXIgdXNhIGRhdG9zIGRlIGVsZXZhY2nDs24gZW4gdW5hIG1hdHJpeiBSIGJhc2UgeSB1bmEgY29tYmluYWNpw7NuIGRlIHRyYXphZG8gZGUgcmF5b3MsIG1hcGVvIGRlIHRleHR1cmEgZXNmw6lyaWNhLCBzdXBlcnBvc2ljaW9uZXMgeSBvY2x1c2nDs24gYW1iaWVudGFsIHBhcmEgZ2VuZXJhciBoZXJtb3NvcyBtYXBhcyB0b3BvZ3LDoWZpY29zIDJEIHkgM0QgLiBBZGVtw6FzIGRlIGxvcyBtYXBhcywgcmF5c2hhZGVyIHRhbWJpw6luIHBlcm1pdGUgYWwgdXN1YXJpbyB0cmFkdWNpciBvYmpldG9zIGdncGxvdDIgZW4gaGVybW9zYXMgdmlzdWFsaXphY2lvbmVzIGRlIGRhdG9zIGVuIDNELg0KYGBge3J9DQojIGluc3RhbGwucGFja2FnZXMgKCJyYXlzaGFkZXIiKQ0KbGlicmFyeShyYXlzaGFkZXIpDQpgYGANCg0KQ29udmllcnRhIGVsIERFTSBlbiB1bmEgbWF0cml6Og0KYGBge3J9DQplbG1hdCA9IHJhc3Rlcl90b19tYXRyaXgocmVwX2VsZXYpDQpgYGANCiBVc2Ftb3Mgb3RyYSBkZSBsYXMgdGV4dHVyYXMgaW50ZWdyYWRhcyBkZSByYXlzaGFkZXI6DQpgYGB7cn0NCmVsbWF0ICU+JQ0KICBzcGhlcmVfc2hhZGUodGV4dHVyZSA9ICJpbWhvZjIiKSAlPiUNCiAgcGxvdF9tYXAoKQ0KYGBgDQogZGV0ZWN0X3dhdGVyIHkgYWRkX3dhdGVyIGFncmVnYW4gdW5hIGNhcGEgZGUgYWd1YSBhbCBtYXBhOg0KYGBge3J9DQplbG1hdCAlPiUNCiAgc3BoZXJlX3NoYWRlKHRleHR1cmUgPSAiZGVzZXJ0IikgJT4lDQogIGFkZF93YXRlcihkZXRlY3Rfd2F0ZXIoZWxtYXQpLCBjb2xvciA9ICJkZXNlcnQiKSAlPiUNCiAgcGxvdF9tYXAoKQ0KYGBgDQogWSB0YW1iacOpbiBwb2RlbW9zIGFncmVnYXIgdW5hIGNhcGEgY29uIHRyYXphZG8gZGUgcmF5b3MgZGVzZGUgZXNhIGRpcmVjY2nDs24gZGVsIHNvbDoNCmBgYHtyfQ0KZWxtYXQgJT4lDQogIHNwaGVyZV9zaGFkZSh0ZXh0dXJlID0gImRlc2VydCIpICU+JQ0KICBhZGRfd2F0ZXIoZGV0ZWN0X3dhdGVyKGVsbWF0KSwgY29sb3IgPSAiZGVzZXJ0IikgJT4lDQogIGFkZF9zaGFkb3cocmF5X3NoYWRlKGVsbWF0KSwgMC41KSAlPiUNCiAgcGxvdF9tYXAoKQ0KYGBgDQoNCiMjIDguIE90cmEgZm9ybWEgZGUgdmlzdWFsaXphY2nDs24NClVuIGV4cGVydG8gZW4gUiBzdWdpZXJlIGFxdcOtIG90cmEgZm9ybWEgZGUgdmlzdWFsaXphY2nDs24uDQoNClZhbW9zIGEgaW50ZW50YXJsbzoNCg0KDQpgYGB7cn0NCiMgaW5zdGFsbC5wYWNrYWdlcygianBlZyIpDQpsaWJyYXJ5KGpwZWcpDQpgYGANCg0KRnVuY2nDs24gZGUgc29tYnJlYWRvIGRlIG1hcGVvIGRlIGVudG9ybm8gZXNmw6lyaWNvDQpgYGB7cn0NCmdldHY9ZnVuY3Rpb24oaSxhLHMpew0KICBjdCA9IGRpbShpKVsxOjJdLzINCiAgc3ggPSB2YWx1ZXMocykvOTAgKiBjdFsxXQ0KICBzeSA9IHZhbHVlcyhzKS85MCAqIGN0WzJdDQogIGEgPSB2YWx1ZXMoYSkgKiAwLjAxNzQ1DQogIHB4ID0gZmxvb3IoY3RbMV0gKyBzeCAqIC1zaW4oYSkpDQogIHB5ID0gZmxvb3IoY3RbMl0gKyBzeSAqIGNvcyhhKSkNCiAgDQogIA0KICB0ZW1wbGF0ZSA9IGJyaWNrKHMscyxzKQ0KICB2YWx1ZXModGVtcGxhdGUpPU5BDQogIA0KICBjZWxsciA9IHB4ICsgcHkgKiBjdFsxXSoyDQogIGNlbGxnID0gcHggKyBweSAqIGN0WzFdKjIgKyAoY3RbMV0qMipjdFsyXSoyKQ0KICBjZWxsYiA9IHB4ICsgcHkgKiBjdFsxXSoyICsgMiooY3RbMV0qMipjdFsyXSoyKQ0KICANCiAgdGVtcGxhdGVbWzFdXSA9IGlbY2VsbHJdDQogIHRlbXBsYXRlW1syXV0gPSBpW2NlbGxnXQ0KICB0ZW1wbGF0ZVtbM11dID0gaVtjZWxsYl0NCiAgDQogIHRlbXBsYXRlID0gdGVtcGxhdGUgKiAyNTYNCiAgDQogIHRlbXBsYXRlDQp9DQpgYGANCg0KQ2FyZ2FyIHVuYSBpbWFnZW4gZGUgbWFwYSBkZWwgZW50b3Jubw0KU2UgcHVlZGUgZW5jb250cmFyIHVuIGVqZW1wbG8gZW4gaHR0cDovL2kuaW1ndXIuY29tLzlwdmJIak4uanBnDQpgYGB7cn0NCm1hcD1yZWFkSlBFRygiQzovVXNlcnMvcm9qYXMvT25lRHJpdmUvRXNjcml0b3Jpby9SIGVzdHVkaW8vR2VvbWF0aWNhLzlwdmJIak4uanBnIikNCg0KIyBIYWNlciBlbCBtYXBlbw0Kb3V0ID0gZ2V0dihtYXAsIGFzcGVjdCwgc2xvcGUpDQoNCiMgVHJhemEgbW9udGHDsWFzDQpwbG90UkdCKG91dCwgbWFpbiA9ICJNb250YcOxYXMgc3VwdWVzdGFtZW50ZSBib25pdGFzIGVuIGVsIFBvcGF5w6FuIikNCmBgYA0KYGBge3J9DQpzZXNzaW9uSW5mbygpDQpgYGANCg0KDQoNCg0KDQoNCg==