Landsat 8 recopilada el 04 de enero de 2015. El subconjunto cubre el area de Sibate, departamento de Cundinamarca, en Colombia

This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

Seleccionar la carpeta de destino
#C:/Users/David/Desktop/IMAGENES LANDSAT SIBATE
getwd()
[1] "C:/Users/David/Desktop/Landsat_procesamiento"

Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Ctrl+Shift+Enter.

Crear objetos RasterLayer para capas individuales Landsat (bandas) y las llamamos enrutandolas como por ejemplo (‘./data/LC08_L1TP_008057_20180317_20180403_01_T1_B2.tif’)
IMPORTANTE: instalar paquetes: raster, sp, rgdal
En este capitulo se describe la forma de acceder y explorar por satelite datos de teledeteccion con R . Tambien mostramos como usarlos para hacer mapas.
Utilizaremos principalmente un subconjunto espacial de una escena Landsat 8 recopilada el 14 de junio de 2017. El subconjunto cubre el area entre Concord y Stockton , en California, EE. UU.
Todas las escenas de imagenes de Landsat tienen una identificacion de producto y metadatos unicos. Puede encontrar la informacion sobre el sensor Landsat, el satelite, la ubicacion en la Tierra (ruta WRS, fila WRS) y la fecha de adquisicion a partir de la ID del producto. Por ejemplo, el identificador de producto de los datos que utilizaremos es ‘LC08_044034_20170614’. Con base en esta guia , puede ver que el Sensor-Satelite es OLI / TIRS combinados Landsat 8, WRS Path 44, WRS Row 34 y recopilados el 14 de junio de 2017. Las escenas de Landsat se entregan mas comunmente como un archivo comprimido, que contiene archivos separados para cada banda
Comenzaremos explorando y visualizando los datos (consulte las instrucciones en el Capitulo 1 para obtener instrucciones de descarga de datos si aun no lo ha hecho).

TITULO: PROPIEDADES DE IMAGEN

Crear objetos RasterLayer para capas individuales Landsat (bandas)
library(raster)
b1 = raster('./data2015/LC08_L1TP_008057_20150104_20170415_01_T1_B1.tif')
# azul
b2 = raster('./data2015/LC08_L1TP_008057_20150104_20170415_01_T1_B2.tif')
# verde
b3 = raster('./data2015/LC08_L1TP_008057_20150104_20170415_01_T1_B3.tif')
# rojo
b4 = raster('./data2015/LC08_L1TP_008057_20150104_20170415_01_T1_B4.tif')
# Infrarojo cercano (NIR)
b5 = raster('./data2015/LC08_L1TP_008057_20150104_20170415_01_T1_B5.tif')
b6 = raster('./data2015/LC08_L1TP_008057_20150104_20170415_01_T1_B6.tif')
b7 = raster('./data2015/LC08_L1TP_008057_20150104_20170415_01_T1_B7.tif')
b8 = raster('./data2015/LC08_L1TP_008057_20150104_20170415_01_T1_B8.tif')
b9 = raster('./data2015/LC08_L1TP_008057_20150104_20170415_01_T1_B9.tif')
b10 = raster('./data2015/LC08_L1TP_008057_20150104_20170415_01_T1_B10.tif')
b11 = raster('./data2015/LC08_L1TP_008057_20150104_20170415_01_T1_B11.tif')
se inserta un nuevo bloque de codigo ctrl+alt+i: imprimir las variables para verificar, por ejemplo:
b2
class      : RasterLayer 
dimensions : 7741, 7581, 58684521  (nrow, ncol, ncell)
resolution : 30, 30  (x, y)
extent     : 446085, 673515, 362985, 595215  (xmin, xmax, ymin, ymax)
crs        : +proj=utm +zone=18 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0 
source     : C:/Users/David/Desktop/Landsat_procesamiento/data2015/LC08_L1TP_008057_20150104_20170415_01_T1_B2.tif 
names      : LC08_L1TP_008057_20150104_20170415_01_T1_B2 
values     : 0, 65535  (min, max)
Puede ver la resolucion espacial, la extension, el numero de capas, el sistema de referencia de coordenadas y mas.

TITULO: INFORMACION DE IMAGEN Y ESTADISTICAS

A continuacion se muestra como puede acceder a varias propiedades desde un objeto Raster * (esto es lo mismo para cualquier conjunto de datos raster).

# coordinate reference system (CRS)
crs(b2)
CRS arguments:
 +proj=utm +zone=18 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0 
## CRS arguments:
## +proj=utm +zone=18 +datum=WGS84 +units=m +no_defs +ellps=WGS84
## +towgs84=0,0,0
# Number of cells, rows, columns
ncell(b2)
[1] 58684521
## [1] 58684521
dim(b2)
[1] 7741 7581    1
## [1] 7741 7581    1
# spatial resolution
res(b2)
[1] 30 30
## [1] 30 30
# Number of bands
nlayers(b2)
[1] 1
## [1] 1
# Do the bands have the same extent, number of rows and columns, projection, resolution, and origin
compareRaster(b2,b3)
[1] TRUE
## [1] TRUE
Puede crear un RasterStack (un objeto con varias capas) a partir de los objetos RasterLayer (banda unica) existentes
Las bandas que llamos son las mismas que hemos llamadodo arriba como RasterLayer
s2015 = stack(b5, b4, b3)
# Check the properties of the RasterStack
s2015
class      : RasterStack 
dimensions : 7741, 7581, 58684521, 3  (nrow, ncol, ncell, nlayers)
resolution : 30, 30  (x, y)
extent     : 446085, 673515, 362985, 595215  (xmin, xmax, ymin, ymax)
crs        : +proj=utm +zone=18 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0 
names      : LC08_L1TP_008057_20150104_20170415_01_T1_B5, LC08_L1TP_008057_20150104_20170415_01_T1_B4, LC08_L1TP_008057_20150104_20170415_01_T1_B3 
min values :                                           0,                                           0,                                           0 
max values :                                       65535,                                       65535,                                       65535 
## class      : RasterStack
## dimensions : 7741, 7581, 58684521, 3  (nrow, ncol, ncell, nlayers)
## resolution : 30, 30  (x, y)
## extent     : 446085, 673515, 362985, 595215  (xmin, xmax, ymin, ymax)
## crs        : ++proj=utm +zone=18 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0
## names      : LC08_L1TP_008057_20180317_20180403_01_T1_B5, LC08_L1TP_008057_20180317_20180403_01_T1_B4,     LC08_L1TP_008057_20180317_20180403_01_T1_B3
## min values :  0, 0, 0 
## max values :  65535, 65535, 65535
Tambien puede crear el RasterStack usando los nombres de archivo
# first create a list of raster layers to use
filenames = paste0('./data2015/LC08_L1TP_008057_20150104_20170415_01_T1_B', 1:7, ".tif")
filenames
[1] "./data2015/LC08_L1TP_008057_20150104_20170415_01_T1_B1.tif"
[2] "./data2015/LC08_L1TP_008057_20150104_20170415_01_T1_B2.tif"
[3] "./data2015/LC08_L1TP_008057_20150104_20170415_01_T1_B3.tif"
[4] "./data2015/LC08_L1TP_008057_20150104_20170415_01_T1_B4.tif"
[5] "./data2015/LC08_L1TP_008057_20150104_20170415_01_T1_B5.tif"
[6] "./data2015/LC08_L1TP_008057_20150104_20170415_01_T1_B6.tif"
[7] "./data2015/LC08_L1TP_008057_20150104_20170415_01_T1_B7.tif"
## [1] "./data2015/LC08_L1TP_008057_20150104_20170415_01_T1_B1.tif" 
## [2] "./data2015/LC08_L1TP_008057_20150104_20170415_01_T1_B2.tif" 
## [3] "./data2015/LC08_L1TP_008057_20150104_20170415_01_T1_B3.tif" 
## [4] "./data2015/LC08_L1TP_008057_20150104_20170415_01_T1_B4.tif" 
## [5] "./data2015/LC08_L1TP_008057_20150104_20170415_01_T1_B5.tif" 
## [6] "./data2015/LC08_L1TP_008057_20150104_20170415_01_T1_B6.tif" 
## [7] "./data2015/LC08_L1TP_008057_20150104_20170415_01_T1_B7.tif" 
###### no lee la banda 8 porque tiene diferente extension
## [8] "./data2015/LC08_L1TP_008057_20150104_20170415_01_T1_B8.tif" 
## [9] "./data2015/LC08_L1TP_008057_20150104_20170415_01_T1_B9.tif" 
## [10] "./data2015/LC08_L1TP_008057_20150104_20170415_01_T1_B10.tif"
## [11] "./data2015/LC08_L1TP_008057_20150104_20170415_01_T1_B11.tif"
landsat2015= stack(filenames)
landsat2015
class      : RasterStack 
dimensions : 7741, 7581, 58684521, 7  (nrow, ncol, ncell, nlayers)
resolution : 30, 30  (x, y)
extent     : 446085, 673515, 362985, 595215  (xmin, xmax, ymin, ymax)
crs        : +proj=utm +zone=18 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0 
names      : LC08_L1TP//5_01_T1_B1, LC08_L1TP//5_01_T1_B2, LC08_L1TP//5_01_T1_B3, LC08_L1TP//5_01_T1_B4, LC08_L1TP//5_01_T1_B5, LC08_L1TP//5_01_T1_B6, LC08_L1TP//5_01_T1_B7 
min values :                     0,                     0,                     0,                     0,                     0,                     0,                     0 
max values :                 65535,                 65535,                 65535,                 65535,                 65535,                 65535,                 65535 
## class      : RasterStack
## dimensions : 7741, 7581, 58684521, 7  (nrow, ncol, ncell, nlayers)
## resolution : 30, 30  (x, y)
## extent     : 446085, 673515, 362985, 595215  (xmin, xmax, ymin, ymax)
## crs        : +proj=utm +zone=10 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0
## names      : LC08_L1TP//5_01_T1_B1, LC08_L1TP//5_01_T1_B2, LC08_L1TP//5_01_T1_B3, LC08_L1TP//5_01_T1_B4, LC08_L1TP//5_01_T1_B5, LC08_L1TP//5_01_T1_B6, LC08_L1TP//5_01_T1_B7
## min values :                     0,                     0,                     0,                     0,                     0,                     0,                     0 
## max values :                 65535,                 65535,                 65535,                 65535,                 65535,                 65535,                 65535 
Arriba creamos un RasterStack con 11 capas. Las capas representan la intensidad de la reflexion en las siguientes longitudes de onda: Ultra azul, azul, verde, rojo, infrarrojo cercano (NIR), infrarrojo de onda corta (SWIR) 1, infrarrojo de onda corta (SWIR) 2, pancromatico, cirro, infrarrojo termico (TIRS) 1, Infrarrojo termico (TIRS) 2. No utilizaremos las ultimas cuatro capas y vera como eliminarlas en las siguientes secciones.

TITULO: BANDA UNICA Y MAPAS COMPUESTOS

Puede trazar capas individuales de un RasterStack de una imagen multiespectral.
par(mfrow = c(2,2))
plot(b2, main = "Blue", col = gray(0:100 / 100))
plot(b3, main = "Green", col = gray(0:100 / 100))
plot(b4, main = "Red", col = gray(0:100 / 100))
plot(b5, main = "NIR", col = gray(0:100 / 100))

Echa un vistazo a las leyendas de los mapas creados anteriormente. Pueden variar entre 0 y 1. Observe la diferencia en el sombreado y el rango de leyendas entre las diferentes bandas. Esto se debe a que las diferentes caracteristicas de la superficie reflejan la radiacion solar incidente de manera diferente. Cada capa representa la cantidad de radiacion solar incidente que se refleja para un rango de longitud de onda particular. Por ejemplo, la vegetacion refleja mas energia en NIR que otras longitudes de onda y, por lo tanto, parece mas brillante. Por el contrario, el agua absorbe la mayor parte de la energia en la longitud de onda NIR y parece oscura.
No obtenemos tanta informacion de estas parcelas en escala de grises; a menudo se combinan en un “compuesto” para crear tramas mas interesantes. Puede obtener mas informacion sobre los compuestos de color en la teledeteccion aqui y tambien en la seccion a continuacion.
Para hacer una imagen de “color verdadero (o natural)”, es decir, algo que se parece a una fotografia normal (vegetacion en verde, azul agua, etc.), necesitamos bandas en las regiones roja, verde y azul. Para esta imagen Landsat, se pueden usar las bandas 4 (rojo), 3 (verde) y 2 (azul). El - plotRGB - metodo se puede utilizar para combinarlos en un solo compuesto. Tambien puede proporcionar argumentos adicionales - plotRGB - para mejorar la visualizacion (por ejemplo, un estiramiento lineal de los valores, utilizando ).- strecth = “lin” -
landsatRGB2015 = stack(b4, b3, b2)
plotRGB(landsatRGB2015, axes = TRUE, stretch = "lin", main = "Landsat True Color Composite")

Nota : Compruebe siempre la documentacion del paquete (- help(plotRGB) -) para ver otros argumentos que se pueden agregar (como la escala) para mejorar o modificar la imagen.
Pregunta 1 : Use la funcion plotRGB con RasterStack `` landsat ’’ para crear un compuesto de color verdadero y falso (recuerde la posicion de las bandas en la pila).

TITULO: SUBCONJUNTO Y RENOMBRAR BANDAS

Puede seleccionar capas (bandas) especificas mediante la - subset - funcion o mediante indexacion.
# select first 3 bands only
landsat2015sub01 = subset(landsat2015, 1:3)
# same
landsat2015sub02 = landsat2015[[1:3]]
# Number of bands in the original and new data
nlayers(landsat2015)
[1] 7
## [1] 7
nlayers(landsat2015sub01)
[1] 3
## [1] 3
nlayers(landsat2015sub02)
[1] 3
## [1] 3
No usaremos las ultimas cuatro bandas - landsat -. Puedes eliminar aquellos usando:
landsat2015 = subset(landsat2015, 1:7)
plot(landsat2015)

Para mayor claridad, es util establecer los nombres de las bandas.
names(landsat2015)
[1] "LC08_L1TP_008057_20150104_20170415_01_T1_B1" "LC08_L1TP_008057_20150104_20170415_01_T1_B2"
[3] "LC08_L1TP_008057_20150104_20170415_01_T1_B3" "LC08_L1TP_008057_20150104_20170415_01_T1_B4"
[5] "LC08_L1TP_008057_20150104_20170415_01_T1_B5" "LC08_L1TP_008057_20150104_20170415_01_T1_B6"
[7] "LC08_L1TP_008057_20150104_20170415_01_T1_B7"
## [1] "LC08_L1TP_008057_20180317_20180403_01_T1_B1" "LC08_L1TP_008057_20180317_20180403_01_T1_B2"
## [3] "LC08_L1TP_008057_20180317_20180403_01_T1_B3" "LC08_L1TP_008057_20180317_20180403_01_T1_B4"
## [5] "LC08_L1TP_008057_20180317_20180403_01_T1_B5" "LC08_L1TP_008057_20180317_20180403_01_T1_B6"
## [7] "LC08_L1TP_008057_20180317_20180403_01_T1_B7"
names(landsat2015) = c('ultra-blue', 'blue', 'green', 'red', 'NIR', 'SWIR1', 'SWIR2')
names(landsat2015)
[1] "ultra.blue" "blue"       "green"      "red"        "NIR"        "SWIR1"      "SWIR2"     
## [1] "ultra.blue" "blue"       "green"      "red"        "NIR"
## [6] "SWIR1"      "SWIR2"

TITULO: SUBCONJUNTO ESPACIAL O RECORTE

El subconjunto espacial se puede usar para limitar el analisis a un subconjunto geografico de la imagen. Los subconjuntos espaciales se pueden crear con la - crop - funcion, utilizando un - extent - objeto u otro objeto espacial del que se puede extraer una Extension.
# Using extent
extent(landsat2015)
class      : Extent 
xmin       : 446085 
xmax       : 673515 
ymin       : 362985 
ymax       : 595215 
## class      : Extent
## xmin       : 446085 
## xmax       : 673515
## ymin       : 362985
## ymax       : 595215
sibate2015 = shapefile('C:/Users/David/Desktop/SIBATE_RURAL/rural.shp')
e = extent(sibate2015)
# crop landsat by the extent
landsatcrop2015 = crop(landsat2015, e)
plotRGB(landsatcrop2015, axes = TRUE, stretch = "lin", main = "Landsat True Color Composite")

Pregunta 2 : Tambien es posible la seleccion interactiva de la imagen. Use drawExtent y drawPoly para seleccionar un area de interes
Pregunta 3 : Use el `` Landsatcrop ’’ de RasterStack para crear un compuesto de color verdadero y falso

TITULO: GUARDANDO RESULTADOS EN EL DISCO

En esta etapa, es posible que queramos guardar el raster en el disco usando la funcion - writeRaster -. Se admiten multiples tipos de archivos. Utilizaremos el formato GeoTiff de uso comun. Mientras se conserva el orden de las capas, los nombres de las capas se pierden desafortunadamente en el formato GeoTiff
x = writeRaster(landsatcrop2015, filename="cropped-landsat.tif", overwrite=TRUE)
plot(x)

Alternativamente, puede utilizar el formato ‘raster-grd’.
writeRaster(landsatcrop2015, filename="cropped-landsat.grd", overwrite=TRUE)
Una ventaja de este formato es que guarda los nombres de las capas. La desventaja de este formato es que no muchos otros programas pueden leer los datos, en contraste con el formato GeoTiff.
Nota: Consulte la documentacion del paquete (- help(writeRaster) -) para ver argumentos utiles adicionales que se pueden agregar

TITULO: RELACION ENTRE BANDAS

Una matriz de diagrama de dispersion puede ser util para explorar las relaciones entre capas raster. Esto se puede hacer con la funcion pares () del paquete raster.
Trazado de reflejo en la longitud de onda ultra azul contra el reflejo en la longitud de onda azul.
pairs(landsatcrop2015[[1:2]], main = "Ultra-blue versus Blue")

Trazado de reflejo en la longitud de onda roja contra reflejo en la longitud de onda NIR.
pairs(landsatcrop2015[[4:5]], main = "Red versus NIR")

La primera grafica revela altas correlaciones entre las regiones de longitud de onda azul. Debido a la alta correlacion, podemos usar una de las bandas azules sin perder mucha informacion.
Esta distribucion de puntos en la segunda grafica (entre NIR y rojo) es unica debido a su forma triangular. La vegetacion se refleja muy bien en el rango NIR que el rojo y crea la esquina superior cerca del eje NIR (y). El agua absorbe energia de todas las bandas y ocupa el lugar cercano al origen. El rincon mas alejado se crea debido a las caracteristicas superficiales altamente reflectantes, como el suelo brillante o el hormigon.

TITULO: EXTRAER VALORES DE PIXELES

A menudo, queremos obtener los valores de las celdas raster para ubicaciones geograficas o areas especificas. La - extract - funcion se utiliza para obtener valores raster en las ubicaciones de otros datos espaciales. Puede usar puntos, lineas, poligonos o un objeto de extension (rectangulo). Tambien puede usar numeros de celda para extraer valores. Al usar puntos, - extract - devuelve los valores de un - Raster* - objeto para las celdas en las que se ubica un conjunto de puntos.
# load the polygons with land use land cover information
sibatecobert = shapefile ('C:/Users/David/Desktop/PERCEPCION REMOTA/TRABAJO_COBERTURAS/cobertu.shp')
Z-dimension discarded
    # samp = readRDS('data/rs/samples.rds')              **en la guia esta asi**
# generate 300 point samples from the polygons
ptsibatecobert2015 = spsample(sibatecobert,300, type='regular')
    # ptsamp = spsample(samp, 300, type='regular')       **en la guia esta asi**
# add the land cover class to the points
ptsibatecobert$Name = over(ptsibatecobert, sibatecobert)$Name
    # ptsamp$class = over(ptsamp, samp)$class            **en la guia esta asi**
# extract values with points
df = extract(landsat2015, ptsibatecobert2015)
   # df = extract(landsat1, ptsamp)                      **en la guia esta asi**
# To see some of the reflectance values
head(df)
     ultra.blue blue green  red   NIR SWIR1 SWIR2
[1,]       8484 7800  7528 6931 14777 10879  8167
[2,]       8395 7782  7532 6774 14395 10388  7847
[3,]       8816 8265  8694 8181 21024 16753 11313
[4,]       8302 7651  7959 6534 25737 11668  7696
[5,]       8419 7791  8206 6847 24761 11801  7962
[6,]       8554 7902  8054 6912 21716 11099  7867
#     ultra.blue blue green  red   NIR SWIR1 SWIR2
#[1,]       8484 7800  7528 6931 14777 10879  8167
#[2,]       8816 8265  8694 8181 21024 16753 11313
#[3,]       8419 7791  8206 6847 24761 11801  7962
#[4,]       8399 7745  8087 6775 24775 12160  8012
#[5,]       8072 7394  6904 6273 11207  8098  6621
#[6,]       8072 7380  6827 6231 10728  8084  6654

TITULO: PERFILES ESPECTRALES

Una grafica del espectro (todas las bandas) para los pixeles que representan ciertas caracteristicas de la superficie terrestre (p. Ej. Agua) se conoce como perfil espectral. Dichos perfiles demuestran las diferencias en las propiedades espectrales de varias caracteristicas de la superficie terrestre y constituyen la base para el analisis de imagenes. Los valores espectrales se pueden extraer de cualquier conjunto de datos multiespectrales utilizando la - extract - funcion. En el ejemplo anterior, extrajimos valores de datos de Landsat para las muestras. Estas muestras incluyen: tierras de cultivo, agua, barbecho, construido y abierto. Primero calculamos los valores medios de reflectancia para cada clase y cada banda.
numero= length(ptsibatecobert)
numero
[1] 297
df_samples = as (ptsibatecobert, "SpatialPointsDataFrame")
df_samples
class       : SpatialPointsDataFrame 
features    : 297 
extent      : 577356.4, 585717, 493599.1, 501108.2  (xmin, xmax, ymin, ymax)
crs         : +proj=utm +zone=18 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0 
variables   : 1
names       :         Name 
min values  :         Agua 
max values  : zona desnuda 
df_samples@data=data.frame(ID=1:numero,size=1)
df_samples
class       : SpatialPointsDataFrame 
features    : 297 
extent      : 577356.4, 585717, 493599.1, 501108.2  (xmin, xmax, ymin, ymax)
crs         : +proj=utm +zone=18 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0 
variables   : 2
names       :  ID, size 
min values  :   1,    1 
max values  : 297,    1 
plot(landsatcrop2015)
plot(sibatecobert, add= TRUE)
plot(df_samples,pch=1, cex=(df_samples$size)/4, add=TRUE)

df_samples$Name =over(df_samples,sibatecobert)$Name
df_samples
class       : SpatialPointsDataFrame 
features    : 297 
extent      : 577356.4, 585717, 493599.1, 501108.2  (xmin, xmax, ymin, ymax)
crs         : +proj=utm +zone=18 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0 
variables   : 3
names       :  ID, size,         Name 
min values  :   1,    1,         Agua 
max values  : 297,    1, zona desnuda 
df1=raster::extract(landsatcrop2015, df_samples)
ms = aggregate(df1, list(ptsibatecobert$Name), mean)
## ms = aggregate(df, list(ptsamp$class), mean)         ** asi esta en la guia**
# instead of the first column, we use row names
rownames(ms) = ms[,1]
ms = ms[,-1]
ms
##          ultra.blue      blue      green       red        NIR      SWIR1
## built     0.1864925 0.1795371 0.17953317 0.1958414 0.25448447 0.24850197
## cropland  0.1129813 0.0909645 0.08596722 0.0550344 0.48335462 0.16142085
## fallow    0.1319198 0.1164869 0.10453764 0.1151243 0.18012962 0.23139228
## open      0.1388014 0.1375235 0.15273163 0.2066425 0.34476670 0.35820877
## water     0.1336242 0.1165728 0.09922726 0.0785947 0.04909201 0.03360047
##               SWIR2
## built    0.20001306
## cropland 0.07314186
## fallow   0.19143030
## open     0.21346343
## water    0.02723398
Ahora trazamos el espectro medio de estas caracteristicas.
# Create a vector of color for the land cover classes for use in plotting
mycolor = c('darkred', 'yellow', 'burlywood', 'cyan', 'blue', 'green','pink')
#transform ms from a data.frame to a matrix
ms = as.matrix(ms)
# First create an empty plot
plot(0, ylim=c(0,25000), xlim = c(1,7), type='n', xlab="Bands", ylab = "Reflectance")
# add the different classes
for (i in 1:nrow(ms)){
  lines(ms[i,], type = "l", lwd = 3, lty = 1, col = mycolor[i])
}
# Title
title(main="Spectral Profile from Landsat", font.main = 2)
# Legend
legend("topleft", rownames(ms),
       cex=0.8, col=mycolor, lty = 1, lwd =3, bty = "n")

El perfil espectral muestra (des) similitud en la reflectancia de diferentes caracteristicas en la superficie de la tierra (o por encima de ella). ‘Agua’ muestra una reflexion relativamente baja en todas las longitudes de onda, y ‘construido’, ‘en barbecho’ y ‘abierto’ tienen una reflectancia relativamente alta en las longitudes de onda mas largas.

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Ctrl+Alt+I.

When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Ctrl+Shift+K to preview the HTML file).

The preview shows you a rendered HTML copy of the contents of the editor. Consequently, unlike Knit, Preview does not run any R code chunks. Instead, the output of the chunk when it was last run in the editor is displayed.

LS0tDQp0aXRsZTogIioqSW1hZ2VuIExhbmRTYXQgOCwgU2liYXRlIDIwMTUqKiINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQNCi0tLQ0KDQoNCiMjIyMjICoqTGFuZHNhdCA4IHJlY29waWxhZGEgZWwgMDQgZGUgZW5lcm8gZGUgMjAxNS4gRWwgc3ViY29uanVudG8gY3VicmUgZWwgYXJlYSBkZSBTaWJhdGUsIGRlcGFydGFtZW50byBkZSBDdW5kaW5hbWFyY2EsIGVuIENvbG9tYmlhKioNCg0KDQpUaGlzIGlzIGFuIFtSIE1hcmtkb3duXShodHRwOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tKSBOb3RlYm9vay4gV2hlbiB5b3UgZXhlY3V0ZSBjb2RlIHdpdGhpbiB0aGUgbm90ZWJvb2ssIHRoZSByZXN1bHRzIGFwcGVhciBiZW5lYXRoIHRoZSBjb2RlLiANCg0KDQojIyMjIyBTZWxlY2Npb25hciBsYSBjYXJwZXRhIGRlIGRlc3Rpbm8gDQoNCg0KYGBge3J9DQojIkM6L1VzZXJzL0RhdmlkL0Rlc2t0b3AvTGFuZHNhdF9wcm9jZXNhbWllbnRvIg0KZ2V0d2QoKQ0KYGBgDQoNCg0KVHJ5IGV4ZWN1dGluZyB0aGlzIGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqUnVuKiBidXR0b24gd2l0aGluIHRoZSBjaHVuayBvciBieSBwbGFjaW5nIHlvdXIgY3Vyc29yIGluc2lkZSBpdCBhbmQgcHJlc3NpbmcgKkN0cmwrU2hpZnQrRW50ZXIqLiANCg0KDQojIyMjIyBDcmVhciBvYmpldG9zIFJhc3RlckxheWVyIHBhcmEgY2FwYXMgaW5kaXZpZHVhbGVzIExhbmRzYXQgKGJhbmRhcykgeSBsYXMgbGxhbWFtb3MgZW5ydXRhbmRvbGFzIGNvbW8gcG9yIGVqZW1wbG8gKCcuL2RhdGEvTEMwOF9MMVRQXzAwODA1N18yMDE4MDMxN18yMDE4MDQwM18wMV9UMV9CMi50aWYnKQ0KDQojIyMjIypJTVBPUlRBTlRFOiBpbnN0YWxhciBwYXF1ZXRlczogcmFzdGVyLCBzcCwgcmdkYWwqDQoNCiMjIyMjIEVuIGVzdGUgY2FwaXR1bG8gc2UgZGVzY3JpYmUgbGEgZm9ybWEgZGUgYWNjZWRlciB5IGV4cGxvcmFyIHBvciBzYXRlbGl0ZSBkYXRvcyBkZSB0ZWxlZGV0ZWNjaW9uIGNvbiBSIC4gVGFtYmllbiBtb3N0cmFtb3MgY29tbyB1c2FybG9zIHBhcmEgaGFjZXIgbWFwYXMuDQoNCiMjIyMjIFV0aWxpemFyZW1vcyBwcmluY2lwYWxtZW50ZSB1biBzdWJjb25qdW50byBlc3BhY2lhbCBkZSB1bmEgZXNjZW5hIExhbmRzYXQgOCByZWNvcGlsYWRhIGVsIDE0IGRlIGp1bmlvIGRlIDIwMTcuIEVsIHN1YmNvbmp1bnRvIGN1YnJlIGVsIGFyZWEgZW50cmUgQ29uY29yZCB5IFN0b2NrdG9uICwgZW4gQ2FsaWZvcm5pYSwgRUUuIFVVLg0KDQojIyMjIyBUb2RhcyBsYXMgZXNjZW5hcyBkZSBpbWFnZW5lcyBkZSBMYW5kc2F0IHRpZW5lbiB1bmEgaWRlbnRpZmljYWNpb24gZGUgcHJvZHVjdG8geSBtZXRhZGF0b3MgdW5pY29zLiBQdWVkZSBlbmNvbnRyYXIgbGEgaW5mb3JtYWNpb24gc29icmUgZWwgc2Vuc29yIExhbmRzYXQsIGVsIHNhdGVsaXRlLCBsYSB1YmljYWNpb24gZW4gbGEgVGllcnJhIChydXRhIFdSUywgZmlsYSBXUlMpIHkgbGEgZmVjaGEgZGUgYWRxdWlzaWNpb24gYSBwYXJ0aXIgZGUgbGEgSUQgZGVsIHByb2R1Y3RvLiBQb3IgZWplbXBsbywgZWwgaWRlbnRpZmljYWRvciBkZSBwcm9kdWN0byBkZSBsb3MgZGF0b3MgcXVlIHV0aWxpemFyZW1vcyBlcyAnTEMwOF8wNDQwMzRfMjAxNzA2MTQnLiBDb24gYmFzZSBlbiBlc3RhIGd1aWEgLCBwdWVkZSB2ZXIgcXVlIGVsIFNlbnNvci1TYXRlbGl0ZSBlcyBPTEkgLyBUSVJTIGNvbWJpbmFkb3MgTGFuZHNhdCA4LCBXUlMgUGF0aCA0NCwgV1JTIFJvdyAzNCB5IHJlY29waWxhZG9zIGVsIDE0IGRlIGp1bmlvIGRlIDIwMTcuIExhcyBlc2NlbmFzIGRlIExhbmRzYXQgc2UgZW50cmVnYW4gbWFzIGNvbXVubWVudGUgY29tbyB1biBhcmNoaXZvIGNvbXByaW1pZG8sIHF1ZSBjb250aWVuZSBhcmNoaXZvcyBzZXBhcmFkb3MgcGFyYSBjYWRhIGJhbmRhDQoNCiMjIyMjIENvbWVuemFyZW1vcyBleHBsb3JhbmRvIHkgdmlzdWFsaXphbmRvIGxvcyBkYXRvcyAoY29uc3VsdGUgbGFzIGluc3RydWNjaW9uZXMgZW4gZWwgQ2FwaXR1bG8gMSBwYXJhIG9idGVuZXIgaW5zdHJ1Y2Npb25lcyBkZSBkZXNjYXJnYSBkZSBkYXRvcyBzaSBhdW4gbm8gbG8gaGEgaGVjaG8pLg0KDQoNCg0KIyMjICoqVElUVUxPOiBQUk9QSUVEQURFUyBERSBJTUFHRU4qKg0KDQojIyMjIyBDcmVhciBvYmpldG9zIFJhc3RlckxheWVyIHBhcmEgY2FwYXMgaW5kaXZpZHVhbGVzIExhbmRzYXQgKGJhbmRhcykNCg0KYGBge3J9DQpsaWJyYXJ5KHJhc3RlcikNCg0KYjEgPSByYXN0ZXIoJy4vZGF0YTIwMTUvTEMwOF9MMVRQXzAwODA1N18yMDE1MDEwNF8yMDE3MDQxNV8wMV9UMV9CMS50aWYnKQ0KDQoNCiMgYXp1bA0KYjIgPSByYXN0ZXIoJy4vZGF0YTIwMTUvTEMwOF9MMVRQXzAwODA1N18yMDE1MDEwNF8yMDE3MDQxNV8wMV9UMV9CMi50aWYnKQ0KIyB2ZXJkZQ0KYjMgPSByYXN0ZXIoJy4vZGF0YTIwMTUvTEMwOF9MMVRQXzAwODA1N18yMDE1MDEwNF8yMDE3MDQxNV8wMV9UMV9CMy50aWYnKQ0KIyByb2pvDQpiNCA9IHJhc3RlcignLi9kYXRhMjAxNS9MQzA4X0wxVFBfMDA4MDU3XzIwMTUwMTA0XzIwMTcwNDE1XzAxX1QxX0I0LnRpZicpDQojIEluZnJhcm9qbyBjZXJjYW5vIChOSVIpDQpiNSA9IHJhc3RlcignLi9kYXRhMjAxNS9MQzA4X0wxVFBfMDA4MDU3XzIwMTUwMTA0XzIwMTcwNDE1XzAxX1QxX0I1LnRpZicpDQoNCg0KYjYgPSByYXN0ZXIoJy4vZGF0YTIwMTUvTEMwOF9MMVRQXzAwODA1N18yMDE1MDEwNF8yMDE3MDQxNV8wMV9UMV9CNi50aWYnKQ0KYjcgPSByYXN0ZXIoJy4vZGF0YTIwMTUvTEMwOF9MMVRQXzAwODA1N18yMDE1MDEwNF8yMDE3MDQxNV8wMV9UMV9CNy50aWYnKQ0KYjggPSByYXN0ZXIoJy4vZGF0YTIwMTUvTEMwOF9MMVRQXzAwODA1N18yMDE1MDEwNF8yMDE3MDQxNV8wMV9UMV9COC50aWYnKQ0KYjkgPSByYXN0ZXIoJy4vZGF0YTIwMTUvTEMwOF9MMVRQXzAwODA1N18yMDE1MDEwNF8yMDE3MDQxNV8wMV9UMV9COS50aWYnKQ0KYjEwID0gcmFzdGVyKCcuL2RhdGEyMDE1L0xDMDhfTDFUUF8wMDgwNTdfMjAxNTAxMDRfMjAxNzA0MTVfMDFfVDFfQjEwLnRpZicpDQpiMTEgPSByYXN0ZXIoJy4vZGF0YTIwMTUvTEMwOF9MMVRQXzAwODA1N18yMDE1MDEwNF8yMDE3MDQxNV8wMV9UMV9CMTEudGlmJykNCg0KYGBgDQoNCg0KIyMjIyMgc2UgaW5zZXJ0YSB1biBudWV2byBibG9xdWUgZGUgY29kaWdvIGN0cmwrYWx0K2k6IGltcHJpbWlyIGxhcyB2YXJpYWJsZXMgcGFyYSB2ZXJpZmljYXIsIHBvciBlamVtcGxvOg0KDQoNCmBgYHtyfQ0KYjINCmBgYA0KDQoNCiMjIyMjIFB1ZWRlIHZlciBsYSByZXNvbHVjaW9uIGVzcGFjaWFsLCBsYSBleHRlbnNpb24sIGVsIG51bWVybyBkZSBjYXBhcywgZWwgc2lzdGVtYSBkZSByZWZlcmVuY2lhIGRlIGNvb3JkZW5hZGFzIHkgbWFzLg0KDQoNCg0KIyMjICoqVElUVUxPOiBJTkZPUk1BQ0lPTiBERSBJTUFHRU4gWSBFU1RBRElTVElDQVMqKg0KDQoNCiMjIyBBIGNvbnRpbnVhY2lvbiBzZSBtdWVzdHJhIGNvbW8gcHVlZGUgYWNjZWRlciBhIHZhcmlhcyBwcm9waWVkYWRlcyBkZXNkZSB1biBvYmpldG8gUmFzdGVyICogKGVzdG8gZXMgbG8gbWlzbW8gcGFyYSBjdWFscXVpZXIgY29uanVudG8gZGUgZGF0b3MgcmFzdGVyKS4NCg0KDQpgYGB7cn0NCiMgY29vcmRpbmF0ZSByZWZlcmVuY2Ugc3lzdGVtIChDUlMpDQpjcnMoYjIpDQojIyBDUlMgYXJndW1lbnRzOg0KIyMgK3Byb2o9dXRtICt6b25lPTE4ICtkYXR1bT1XR1M4NCArdW5pdHM9bSArbm9fZGVmcyArZWxscHM9V0dTODQNCiMjICt0b3dnczg0PTAsMCwwDQojIE51bWJlciBvZiBjZWxscywgcm93cywgY29sdW1ucw0KbmNlbGwoYjIpDQojIyBbMV0gNTg2ODQ1MjENCmRpbShiMikNCiMjIFsxXSA3NzQxIDc1ODEgICAgMQ0KIyBzcGF0aWFsIHJlc29sdXRpb24NCnJlcyhiMikNCiMjIFsxXSAzMCAzMA0KIyBOdW1iZXIgb2YgYmFuZHMNCm5sYXllcnMoYjIpDQojIyBbMV0gMQ0KIyBEbyB0aGUgYmFuZHMgaGF2ZSB0aGUgc2FtZSBleHRlbnQsIG51bWJlciBvZiByb3dzIGFuZCBjb2x1bW5zLCBwcm9qZWN0aW9uLCByZXNvbHV0aW9uLCBhbmQgb3JpZ2luDQpjb21wYXJlUmFzdGVyKGIyLGIzKQ0KIyMgWzFdIFRSVUUNCmBgYA0KDQoNCiMjIyMjIFB1ZWRlIGNyZWFyIHVuIFJhc3RlclN0YWNrICh1biBvYmpldG8gY29uIHZhcmlhcyBjYXBhcykgYSBwYXJ0aXIgZGUgbG9zIG9iamV0b3MgUmFzdGVyTGF5ZXIgKGJhbmRhIHVuaWNhKSBleGlzdGVudGVzIA0KDQoNCiMjIyMjIExhcyBiYW5kYXMgcXVlIGxsYW1vcyBzb24gbGFzIG1pc21hcyBxdWUgaGVtb3MgbGxhbWFkb2RvIGFycmliYSBjb21vIFJhc3RlckxheWVyDQoNCmBgYHtyfQ0KczIwMTUgPSBzdGFjayhiNSwgYjQsIGIzKQ0KDQojIENoZWNrIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBSYXN0ZXJTdGFjaw0KczIwMTUNCiMjIGNsYXNzICAgICAgOiBSYXN0ZXJTdGFjaw0KIyMgZGltZW5zaW9ucyA6IDc3NDEsIDc1ODEsIDU4Njg0NTIxLCAzICAobnJvdywgbmNvbCwgbmNlbGwsIG5sYXllcnMpDQojIyByZXNvbHV0aW9uIDogMzAsIDMwICAoeCwgeSkNCiMjIGV4dGVudCAgICAgOiA0NDYwODUsIDY3MzUxNSwgMzYyOTg1LCA1OTUyMTUgICh4bWluLCB4bWF4LCB5bWluLCB5bWF4KQ0KIyMgY3JzICAgICAgICA6ICsrcHJvaj11dG0gK3pvbmU9MTggK2RhdHVtPVdHUzg0ICt1bml0cz1tICtub19kZWZzICtlbGxwcz1XR1M4NCArdG93Z3M4ND0wLDAsMA0KIyMgbmFtZXMgICAgICA6IExDMDhfTDFUUF8wMDgwNTdfMjAxODAzMTdfMjAxODA0MDNfMDFfVDFfQjUsIExDMDhfTDFUUF8wMDgwNTdfMjAxODAzMTdfMjAxODA0MDNfMDFfVDFfQjQsICAgICBMQzA4X0wxVFBfMDA4MDU3XzIwMTgwMzE3XzIwMTgwNDAzXzAxX1QxX0IzDQojIyBtaW4gdmFsdWVzIDogIDAsIDAsIDAgDQojIyBtYXggdmFsdWVzIDogIDY1NTM1LCA2NTUzNSwgNjU1MzUNCmBgYA0KDQoNCiMjIyMjIFRhbWJpZW4gcHVlZGUgY3JlYXIgZWwgUmFzdGVyU3RhY2sgdXNhbmRvIGxvcyBub21icmVzIGRlIGFyY2hpdm8gDQoNCg0KYGBge3J9DQoNCiMgZmlyc3QgY3JlYXRlIGEgbGlzdCBvZiByYXN0ZXIgbGF5ZXJzIHRvIHVzZQ0KZmlsZW5hbWVzID0gcGFzdGUwKCcuL2RhdGEyMDE1L0xDMDhfTDFUUF8wMDgwNTdfMjAxNTAxMDRfMjAxNzA0MTVfMDFfVDFfQicsIDE6NywgIi50aWYiKQ0KZmlsZW5hbWVzDQoNCiMjIFsxXSAiLi9kYXRhMjAxNS9MQzA4X0wxVFBfMDA4MDU3XzIwMTUwMTA0XzIwMTcwNDE1XzAxX1QxX0IxLnRpZiIgDQojIyBbMl0gIi4vZGF0YTIwMTUvTEMwOF9MMVRQXzAwODA1N18yMDE1MDEwNF8yMDE3MDQxNV8wMV9UMV9CMi50aWYiIA0KIyMgWzNdICIuL2RhdGEyMDE1L0xDMDhfTDFUUF8wMDgwNTdfMjAxNTAxMDRfMjAxNzA0MTVfMDFfVDFfQjMudGlmIiANCiMjIFs0XSAiLi9kYXRhMjAxNS9MQzA4X0wxVFBfMDA4MDU3XzIwMTUwMTA0XzIwMTcwNDE1XzAxX1QxX0I0LnRpZiIgDQojIyBbNV0gIi4vZGF0YTIwMTUvTEMwOF9MMVRQXzAwODA1N18yMDE1MDEwNF8yMDE3MDQxNV8wMV9UMV9CNS50aWYiIA0KIyMgWzZdICIuL2RhdGEyMDE1L0xDMDhfTDFUUF8wMDgwNTdfMjAxNTAxMDRfMjAxNzA0MTVfMDFfVDFfQjYudGlmIiANCiMjIFs3XSAiLi9kYXRhMjAxNS9MQzA4X0wxVFBfMDA4MDU3XzIwMTUwMTA0XzIwMTcwNDE1XzAxX1QxX0I3LnRpZiIgDQoNCiMjIyMjIyBubyBsZWUgbGEgYmFuZGEgOCBwb3JxdWUgdGllbmUgZGlmZXJlbnRlIGV4dGVuc2lvbg0KDQojIyBbOF0gIi4vZGF0YTIwMTUvTEMwOF9MMVRQXzAwODA1N18yMDE1MDEwNF8yMDE3MDQxNV8wMV9UMV9COC50aWYiIA0KIyMgWzldICIuL2RhdGEyMDE1L0xDMDhfTDFUUF8wMDgwNTdfMjAxNTAxMDRfMjAxNzA0MTVfMDFfVDFfQjkudGlmIiANCiMjIFsxMF0gIi4vZGF0YTIwMTUvTEMwOF9MMVRQXzAwODA1N18yMDE1MDEwNF8yMDE3MDQxNV8wMV9UMV9CMTAudGlmIg0KIyMgWzExXSAiLi9kYXRhMjAxNS9MQzA4X0wxVFBfMDA4MDU3XzIwMTUwMTA0XzIwMTcwNDE1XzAxX1QxX0IxMS50aWYiDQoNCg0KbGFuZHNhdDIwMTU9IHN0YWNrKGZpbGVuYW1lcykNCmxhbmRzYXQyMDE1DQoNCiMjIGNsYXNzICAgICAgOiBSYXN0ZXJTdGFjaw0KIyMgZGltZW5zaW9ucyA6IDc3NDEsIDc1ODEsIDU4Njg0NTIxLCA3ICAobnJvdywgbmNvbCwgbmNlbGwsIG5sYXllcnMpDQojIyByZXNvbHV0aW9uIDogMzAsIDMwICAoeCwgeSkNCiMjIGV4dGVudCAgICAgOiA0NDYwODUsIDY3MzUxNSwgMzYyOTg1LCA1OTUyMTUgICh4bWluLCB4bWF4LCB5bWluLCB5bWF4KQ0KIyMgY3JzICAgICAgICA6ICtwcm9qPXV0bSArem9uZT0xMCArZGF0dW09V0dTODQgK3VuaXRzPW0gK25vX2RlZnMgK2VsbHBzPVdHUzg0ICt0b3dnczg0PTAsMCwwDQojIyBuYW1lcyAgICAgIDogTEMwOF9MMVRQLy81XzAxX1QxX0IxLCBMQzA4X0wxVFAvLzVfMDFfVDFfQjIsIExDMDhfTDFUUC8vNV8wMV9UMV9CMywgTEMwOF9MMVRQLy81XzAxX1QxX0I0LCBMQzA4X0wxVFAvLzVfMDFfVDFfQjUsIExDMDhfTDFUUC8vNV8wMV9UMV9CNiwgTEMwOF9MMVRQLy81XzAxX1QxX0I3DQojIyBtaW4gdmFsdWVzIDogICAgICAgICAgICAgICAgICAgICAwLCAgICAgICAgICAgICAgICAgICAgIDAsICAgICAgICAgICAgICAgICAgICAgMCwgICAgICAgICAgICAgICAgICAgICAwLCAgICAgICAgICAgICAgICAgICAgIDAsICAgICAgICAgICAgICAgICAgICAgMCwgICAgICAgICAgICAgICAgICAgICAwIA0KIyMgbWF4IHZhbHVlcyA6ICAgICAgICAgICAgICAgICA2NTUzNSwgICAgICAgICAgICAgICAgIDY1NTM1LCAgICAgICAgICAgICAgICAgNjU1MzUsICAgICAgICAgICAgICAgICA2NTUzNSwgICAgICAgICAgICAgICAgIDY1NTM1LCAgICAgICAgICAgICAgICAgNjU1MzUsICAgICAgICAgICAgICAgICA2NTUzNSANCg0KDQpgYGANCg0KDQojIyMjIyBBcnJpYmEgY3JlYW1vcyB1biBSYXN0ZXJTdGFjayBjb24gMTEgY2FwYXMuIExhcyBjYXBhcyByZXByZXNlbnRhbiBsYSBpbnRlbnNpZGFkIGRlIGxhIHJlZmxleGlvbiBlbiBsYXMgc2lndWllbnRlcyBsb25naXR1ZGVzIGRlIG9uZGE6IFVsdHJhIGF6dWwsIGF6dWwsIHZlcmRlLCByb2pvLCBpbmZyYXJyb2pvIGNlcmNhbm8gKE5JUiksIGluZnJhcnJvam8gZGUgb25kYSBjb3J0YSAoU1dJUikgMSwgaW5mcmFycm9qbyBkZSBvbmRhIGNvcnRhIChTV0lSKSAyLCBwYW5jcm9tYXRpY28sIGNpcnJvLCBpbmZyYXJyb2pvIHRlcm1pY28gKFRJUlMpIDEsIEluZnJhcnJvam8gdGVybWljbyAoVElSUykgMi4gTm8gdXRpbGl6YXJlbW9zIGxhcyB1bHRpbWFzIGN1YXRybyBjYXBhcyB5IHZlcmEgY29tbyBlbGltaW5hcmxhcyBlbiBsYXMgc2lndWllbnRlcyBzZWNjaW9uZXMuDQoNCg0KDQojIyMgKipUSVRVTE86IEJBTkRBIFVOSUNBIFkgTUFQQVMgQ09NUFVFU1RPUyoqDQoNCg0KIyMjIyMgUHVlZGUgdHJhemFyIGNhcGFzIGluZGl2aWR1YWxlcyBkZSB1biBSYXN0ZXJTdGFjayBkZSB1bmEgaW1hZ2VuIG11bHRpZXNwZWN0cmFsLg0KDQoNCmBgYHtyfQ0KDQpwYXIobWZyb3cgPSBjKDIsMikpDQpwbG90KGIyLCBtYWluID0gIkJsdWUiLCBjb2wgPSBncmF5KDA6MTAwIC8gMTAwKSkNCnBsb3QoYjMsIG1haW4gPSAiR3JlZW4iLCBjb2wgPSBncmF5KDA6MTAwIC8gMTAwKSkNCnBsb3QoYjQsIG1haW4gPSAiUmVkIiwgY29sID0gZ3JheSgwOjEwMCAvIDEwMCkpDQpwbG90KGI1LCBtYWluID0gIk5JUiIsIGNvbCA9IGdyYXkoMDoxMDAgLyAxMDApKQ0KDQpgYGANCg0KIyMjIyMgRWNoYSB1biB2aXN0YXpvIGEgbGFzIGxleWVuZGFzIGRlIGxvcyBtYXBhcyBjcmVhZG9zIGFudGVyaW9ybWVudGUuIFB1ZWRlbiB2YXJpYXIgZW50cmUgMCB5IDEuIE9ic2VydmUgbGEgZGlmZXJlbmNpYSBlbiBlbCBzb21icmVhZG8geSBlbCByYW5nbyBkZSBsZXllbmRhcyBlbnRyZSBsYXMgZGlmZXJlbnRlcyBiYW5kYXMuIEVzdG8gc2UgZGViZSBhIHF1ZSBsYXMgZGlmZXJlbnRlcyBjYXJhY3RlcmlzdGljYXMgZGUgbGEgc3VwZXJmaWNpZSByZWZsZWphbiBsYSByYWRpYWNpb24gc29sYXIgaW5jaWRlbnRlIGRlIG1hbmVyYSBkaWZlcmVudGUuIENhZGEgY2FwYSByZXByZXNlbnRhIGxhIGNhbnRpZGFkIGRlIHJhZGlhY2lvbiBzb2xhciBpbmNpZGVudGUgcXVlIHNlIHJlZmxlamEgcGFyYSB1biByYW5nbyBkZSBsb25naXR1ZCBkZSBvbmRhIHBhcnRpY3VsYXIuIFBvciBlamVtcGxvLCBsYSB2ZWdldGFjaW9uIHJlZmxlamEgbWFzIGVuZXJnaWEgZW4gTklSIHF1ZSBvdHJhcyBsb25naXR1ZGVzIGRlIG9uZGEgeSwgcG9yIGxvIHRhbnRvLCBwYXJlY2UgbWFzIGJyaWxsYW50ZS4gUG9yIGVsIGNvbnRyYXJpbywgZWwgYWd1YSBhYnNvcmJlIGxhIG1heW9yIHBhcnRlIGRlIGxhIGVuZXJnaWEgZW4gbGEgbG9uZ2l0dWQgZGUgb25kYSBOSVIgeSBwYXJlY2Ugb3NjdXJhLg0KDQoNCiMjIyMjIE5vIG9idGVuZW1vcyB0YW50YSBpbmZvcm1hY2lvbiBkZSBlc3RhcyBwYXJjZWxhcyBlbiBlc2NhbGEgZGUgZ3Jpc2VzOyBhIG1lbnVkbyBzZSBjb21iaW5hbiBlbiB1biAiY29tcHVlc3RvIiBwYXJhIGNyZWFyIHRyYW1hcyBtYXMgaW50ZXJlc2FudGVzLiBQdWVkZSBvYnRlbmVyIG1hcyBpbmZvcm1hY2lvbiBzb2JyZSBsb3MgY29tcHVlc3RvcyBkZSBjb2xvciBlbiBsYSB0ZWxlZGV0ZWNjaW9uIGFxdWkgeSB0YW1iaWVuIGVuIGxhIHNlY2Npb24gYSBjb250aW51YWNpb24uDQoNCg0KIyMjIyMgUGFyYSBoYWNlciB1bmEgaW1hZ2VuIGRlICJjb2xvciB2ZXJkYWRlcm8gKG8gbmF0dXJhbCkiLCBlcyBkZWNpciwgYWxnbyBxdWUgc2UgcGFyZWNlIGEgdW5hIGZvdG9ncmFmaWEgbm9ybWFsICh2ZWdldGFjaW9uIGVuIHZlcmRlLCBhenVsIGFndWEsIGV0Yy4pLCBuZWNlc2l0YW1vcyBiYW5kYXMgZW4gbGFzIHJlZ2lvbmVzIHJvamEsIHZlcmRlIHkgYXp1bC4gUGFyYSBlc3RhIGltYWdlbiBMYW5kc2F0LCBzZSBwdWVkZW4gdXNhciBsYXMgYmFuZGFzIDQgKHJvam8pLCAzICh2ZXJkZSkgeSAyIChhenVsKS4gRWwgLSBwbG90UkdCIC0gbWV0b2RvIHNlIHB1ZWRlIHV0aWxpemFyIHBhcmEgY29tYmluYXJsb3MgZW4gdW4gc29sbyBjb21wdWVzdG8uIFRhbWJpZW4gcHVlZGUgcHJvcG9yY2lvbmFyIGFyZ3VtZW50b3MgYWRpY2lvbmFsZXMgLSBwbG90UkdCIC0gcGFyYSBtZWpvcmFyIGxhIHZpc3VhbGl6YWNpb24gKHBvciBlamVtcGxvLCB1biBlc3RpcmFtaWVudG8gbGluZWFsIGRlIGxvcyB2YWxvcmVzLCB1dGlsaXphbmRvICkuLSBzdHJlY3RoID0gImxpbiIgLQ0KDQoNCmBgYHtyfQ0KbGFuZHNhdFJHQjIwMTUgPSBzdGFjayhiNCwgYjMsIGIyKQ0KcGxvdFJHQihsYW5kc2F0UkdCMjAxNSwgYXhlcyA9IFRSVUUsIHN0cmV0Y2ggPSAibGluIiwgbWFpbiA9ICJMYW5kc2F0IFRydWUgQ29sb3IgQ29tcG9zaXRlIikNCg0KYGBgDQoNCg0KIyMjIyMgRWwgY29tcHVlc3RvIGRlIGNvbG9yIHZlcmRhZGVybyByZXZlbGEgbXVjaG8gbWFzIHNvYnJlIGVsIHBhaXNhamUgcXVlIGxhcyBpbWFnZW5lcyBncmlzZXMgYW50ZXJpb3Jlcy4gT3RybyBtZXRvZG8gcG9wdWxhciBkZSB2aXN1YWxpemFjaW9uIGRlIGltYWdlbmVzIGVuIGxhIHRlbGVkZXRlY2Npb24gZXMgbGEgaW1hZ2VuIGNvbm9jaWRhIGRlICJjb2xvciBmYWxzbyIgZW4gbGEgcXVlIHNlIGNvbWJpbmFuIGxhcyBiYW5kYXMgTklSLCByb2pvIHkgdmVyZGUuIEVzdGEgcmVwcmVzZW50YWNpb24gZXMgcG9wdWxhciB5YSBxdWUgaGFjZSBxdWUgc2VhIGZhY2lsIHZlciBsYSB2ZWdldGFjaW9uIChlbiByb2pvKS4NCg0KDQpgYGB7cn0NCg0KcGFyKG1mcm93ID0gYygxLDIpKQ0KcGxvdFJHQihsYW5kc2F0UkdCMjAxNSwgYXhlcz1UUlVFLCBzdHJldGNoPSJsaW4iLCBtYWluPSJMYW5kc2F0IFRydWUgQ29sb3IgQ29tcG9zaXRlIikNCmxhbmRzYXRGQ0MyMDE1ID0gc3RhY2soYjUsIGI0LCBiMykNCnBsb3RSR0IobGFuZHNhdEZDQzIwMTUsIGF4ZXM9VFJVRSwgc3RyZXRjaD0ibGluIiwgbWFpbj0iTGFuZHNhdCBGYWxzZSBDb2xvciBDb21wb3NpdGUiKQ0KDQpgYGANCg0KIyMjIyMgKk5vdGEgOiBDb21wcnVlYmUgc2llbXByZSBsYSBkb2N1bWVudGFjaW9uIGRlbCBwYXF1ZXRlICgtIGhlbHAocGxvdFJHQikgLSkgcGFyYSB2ZXIgb3Ryb3MgYXJndW1lbnRvcyBxdWUgc2UgcHVlZGVuIGFncmVnYXIgKGNvbW8gbGEgZXNjYWxhKSBwYXJhIG1lam9yYXIgbyBtb2RpZmljYXIgbGEgaW1hZ2VuLioNCg0KIyMjIyMgKlByZWd1bnRhIDEgOiBVc2UgbGEgZnVuY2lvbiBwbG90UkdCIGNvbiBSYXN0ZXJTdGFjayBgYCBsYW5kc2F0ICcnIHBhcmEgY3JlYXIgdW4gY29tcHVlc3RvIGRlIGNvbG9yIHZlcmRhZGVybyB5IGZhbHNvIChyZWN1ZXJkZSBsYSBwb3NpY2lvbiBkZSBsYXMgYmFuZGFzIGVuIGxhIHBpbGEpLioNCg0KDQoNCiMjIyAqKlRJVFVMTzogU1VCQ09OSlVOVE8gWSBSRU5PTUJSQVIgQkFOREFTKioNCg0KDQojIyMjIyBQdWVkZSBzZWxlY2Npb25hciBjYXBhcyAoYmFuZGFzKSBlc3BlY2lmaWNhcyBtZWRpYW50ZSBsYSAtIHN1YnNldCAtIGZ1bmNpb24gbyBtZWRpYW50ZSBpbmRleGFjaW9uLg0KDQoNCmBgYHtyfQ0KDQojIHNlbGVjdCBmaXJzdCAzIGJhbmRzIG9ubHkNCmxhbmRzYXQyMDE1c3ViMDEgPSBzdWJzZXQobGFuZHNhdDIwMTUsIDE6MykNCiMgc2FtZQ0KbGFuZHNhdDIwMTVzdWIwMiA9IGxhbmRzYXQyMDE1W1sxOjNdXQ0KIyBOdW1iZXIgb2YgYmFuZHMgaW4gdGhlIG9yaWdpbmFsIGFuZCBuZXcgZGF0YQ0KbmxheWVycyhsYW5kc2F0MjAxNSkNCiMjIFsxXSA3DQpubGF5ZXJzKGxhbmRzYXQyMDE1c3ViMDEpDQojIyBbMV0gMw0KbmxheWVycyhsYW5kc2F0MjAxNXN1YjAyKQ0KIyMgWzFdIDMNCg0KYGBgDQoNCg0KIyMjIyMgTm8gdXNhcmVtb3MgbGFzIHVsdGltYXMgY3VhdHJvIGJhbmRhcyAtIGxhbmRzYXQgLS4gUHVlZGVzIGVsaW1pbmFyIGFxdWVsbG9zIHVzYW5kbzoNCg0KDQpgYGB7cn0NCg0KbGFuZHNhdDIwMTUgPSBzdWJzZXQobGFuZHNhdDIwMTUsIDE6NykNCnBsb3QobGFuZHNhdDIwMTUpDQpgYGANCg0KDQojIyMjIyBQYXJhIG1heW9yIGNsYXJpZGFkLCBlcyB1dGlsIGVzdGFibGVjZXIgbG9zIG5vbWJyZXMgZGUgbGFzIGJhbmRhcy4NCg0KDQpgYGB7cn0NCg0KbmFtZXMobGFuZHNhdDIwMTUpDQoNCiMjIFsxXSAiTEMwOF9MMVRQXzAwODA1N18yMDE4MDMxN18yMDE4MDQwM18wMV9UMV9CMSIgIkxDMDhfTDFUUF8wMDgwNTdfMjAxODAzMTdfMjAxODA0MDNfMDFfVDFfQjIiDQojIyBbM10gIkxDMDhfTDFUUF8wMDgwNTdfMjAxODAzMTdfMjAxODA0MDNfMDFfVDFfQjMiICJMQzA4X0wxVFBfMDA4MDU3XzIwMTgwMzE3XzIwMTgwNDAzXzAxX1QxX0I0Ig0KIyMgWzVdICJMQzA4X0wxVFBfMDA4MDU3XzIwMTgwMzE3XzIwMTgwNDAzXzAxX1QxX0I1IiAiTEMwOF9MMVRQXzAwODA1N18yMDE4MDMxN18yMDE4MDQwM18wMV9UMV9CNiINCiMjIFs3XSAiTEMwOF9MMVRQXzAwODA1N18yMDE4MDMxN18yMDE4MDQwM18wMV9UMV9CNyINCm5hbWVzKGxhbmRzYXQyMDE1KSA9IGMoJ3VsdHJhLWJsdWUnLCAnYmx1ZScsICdncmVlbicsICdyZWQnLCAnTklSJywgJ1NXSVIxJywgJ1NXSVIyJykNCm5hbWVzKGxhbmRzYXQyMDE1KQ0KIyMgWzFdICJ1bHRyYS5ibHVlIiAiYmx1ZSIgICAgICAgImdyZWVuIiAgICAgICJyZWQiICAgICAgICAiTklSIg0KIyMgWzZdICJTV0lSMSIgICAgICAiU1dJUjIiDQoNCmBgYA0KDQoNCg0KIyMjICoqVElUVUxPOiBTVUJDT05KVU5UTyBFU1BBQ0lBTCBPIFJFQ09SVEUqKg0KDQoNCiMjIyMjIEVsIHN1YmNvbmp1bnRvIGVzcGFjaWFsIHNlIHB1ZWRlIHVzYXIgcGFyYSBsaW1pdGFyIGVsIGFuYWxpc2lzIGEgdW4gc3ViY29uanVudG8gZ2VvZ3JhZmljbyBkZSBsYSBpbWFnZW4uIExvcyBzdWJjb25qdW50b3MgZXNwYWNpYWxlcyBzZSBwdWVkZW4gY3JlYXIgY29uIGxhIC0gY3JvcCAtIGZ1bmNpb24sIHV0aWxpemFuZG8gdW4gLSBleHRlbnQgLSBvYmpldG8gdSBvdHJvIG9iamV0byBlc3BhY2lhbCBkZWwgcXVlIHNlIHB1ZWRlIGV4dHJhZXIgdW5hIEV4dGVuc2lvbi4NCg0KYGBge3J9DQoNCiMgVXNpbmcgZXh0ZW50DQpleHRlbnQobGFuZHNhdDIwMTUpDQojIyBjbGFzcyAgICAgIDogRXh0ZW50DQojIyB4bWluICAgICAgIDogNDQ2MDg1IA0KIyMgeG1heCAgICAgICA6IDY3MzUxNQ0KIyMgeW1pbiAgICAgICA6IDM2Mjk4NQ0KIyMgeW1heCAgICAgICA6IDU5NTIxNQ0KDQpzaWJhdGUyMDE1ID0gc2hhcGVmaWxlKCdDOi9Vc2Vycy9EYXZpZC9EZXNrdG9wL1NJQkFURV9SVVJBTC9ydXJhbC5zaHAnKQ0KDQplID0gZXh0ZW50KHNpYmF0ZTIwMTUpDQojIGNyb3AgbGFuZHNhdCBieSB0aGUgZXh0ZW50DQoNCmxhbmRzYXRjcm9wMjAxNSA9IGNyb3AobGFuZHNhdDIwMTUsIGUpDQoNCg0KcGxvdFJHQihsYW5kc2F0Y3JvcDIwMTUsIGF4ZXMgPSBUUlVFLCBzdHJldGNoID0gImxpbiIsIG1haW4gPSAiTGFuZHNhdCBUcnVlIENvbG9yIENvbXBvc2l0ZSIpDQoNCg0KDQpgYGANCg0KDQojIyMjIyAqUHJlZ3VudGEgMiA6IFRhbWJpZW4gZXMgcG9zaWJsZSBsYSBzZWxlY2Npb24gaW50ZXJhY3RpdmEgZGUgbGEgaW1hZ2VuLiBVc2UgYGAgZHJhd0V4dGVudGBgIHkgYGAgZHJhd1BvbHlgYCBwYXJhIHNlbGVjY2lvbmFyIHVuIGFyZWEgZGUgaW50ZXJlcyoNCg0KIyMjIyMgKlByZWd1bnRhIDMgOiBVc2UgZWwgYGAgTGFuZHNhdGNyb3AgJycgZGUgUmFzdGVyU3RhY2sgcGFyYSBjcmVhciB1biBjb21wdWVzdG8gZGUgY29sb3IgdmVyZGFkZXJvIHkgZmFsc28qDQoNCg0KDQojIyMgKipUSVRVTE86IEdVQVJEQU5ETyBSRVNVTFRBRE9TIEVOIEVMIERJU0NPKioNCg0KDQojIyMjIyBFbiBlc3RhIGV0YXBhLCBlcyBwb3NpYmxlIHF1ZSBxdWVyYW1vcyBndWFyZGFyIGVsIHJhc3RlciBlbiBlbCBkaXNjbyB1c2FuZG8gbGEgZnVuY2lvbiAtIHdyaXRlUmFzdGVyIC0uIFNlIGFkbWl0ZW4gbXVsdGlwbGVzIHRpcG9zIGRlIGFyY2hpdm9zLiBVdGlsaXphcmVtb3MgZWwgZm9ybWF0byBHZW9UaWZmIGRlIHVzbyBjb211bi4gTWllbnRyYXMgc2UgY29uc2VydmEgZWwgb3JkZW4gZGUgbGFzIGNhcGFzLCBsb3Mgbm9tYnJlcyBkZSBsYXMgY2FwYXMgc2UgcGllcmRlbiBkZXNhZm9ydHVuYWRhbWVudGUgZW4gZWwgZm9ybWF0byBHZW9UaWZmDQoNCmBgYHtyfQ0KDQp4ID0gd3JpdGVSYXN0ZXIobGFuZHNhdGNyb3AyMDE1LCBmaWxlbmFtZT0iY3JvcHBlZC1sYW5kc2F0LnRpZiIsIG92ZXJ3cml0ZT1UUlVFKQ0KcGxvdCh4KQ0KDQpgYGANCg0KDQojIyMjIyBBbHRlcm5hdGl2YW1lbnRlLCBwdWVkZSB1dGlsaXphciBlbCBmb3JtYXRvICdyYXN0ZXItZ3JkJy4NCg0KDQpgYGB7cn0NCg0Kd3JpdGVSYXN0ZXIobGFuZHNhdGNyb3AyMDE1LCBmaWxlbmFtZT0iY3JvcHBlZC1sYW5kc2F0LmdyZCIsIG92ZXJ3cml0ZT1UUlVFKQ0KDQpgYGANCg0KDQojIyMjIyBVbmEgdmVudGFqYSBkZSBlc3RlIGZvcm1hdG8gZXMgcXVlIGd1YXJkYSBsb3Mgbm9tYnJlcyBkZSBsYXMgY2FwYXMuIExhIGRlc3ZlbnRhamEgZGUgZXN0ZSBmb3JtYXRvIGVzIHF1ZSBubyBtdWNob3Mgb3Ryb3MgcHJvZ3JhbWFzIHB1ZWRlbiBsZWVyIGxvcyBkYXRvcywgZW4gY29udHJhc3RlIGNvbiBlbCBmb3JtYXRvIEdlb1RpZmYuDQoNCiMjIyMjICpOb3RhOiBDb25zdWx0ZSBsYSBkb2N1bWVudGFjaW9uIGRlbCBwYXF1ZXRlICgtIGhlbHAod3JpdGVSYXN0ZXIpIC0pIHBhcmEgdmVyIGFyZ3VtZW50b3MgdXRpbGVzIGFkaWNpb25hbGVzIHF1ZSBzZSBwdWVkZW4gYWdyZWdhcioNCg0KDQoNCiMjIyAqKlRJVFVMTzogUkVMQUNJT04gRU5UUkUgQkFOREFTKioNCg0KDQojIyMjIyBVbmEgbWF0cml6IGRlIGRpYWdyYW1hIGRlIGRpc3BlcnNpb24gcHVlZGUgc2VyIHV0aWwgcGFyYSBleHBsb3JhciBsYXMgcmVsYWNpb25lcyBlbnRyZSBjYXBhcyByYXN0ZXIuIEVzdG8gc2UgcHVlZGUgaGFjZXIgY29uIGxhIGZ1bmNpb24gcGFyZXMgKCkgZGVsIHBhcXVldGUgcmFzdGVyLg0KDQoNCiMjIyMjIFRyYXphZG8gZGUgcmVmbGVqbyBlbiBsYSBsb25naXR1ZCBkZSBvbmRhIHVsdHJhIGF6dWwgY29udHJhIGVsIHJlZmxlam8gZW4gbGEgbG9uZ2l0dWQgZGUgb25kYSBhenVsLg0KDQoNCmBgYHtyfQ0KcGFpcnMobGFuZHNhdGNyb3AyMDE1W1sxOjJdXSwgbWFpbiA9ICJVbHRyYS1ibHVlIHZlcnN1cyBCbHVlIikNCmBgYA0KDQoNCiMjIyMjIFRyYXphZG8gZGUgcmVmbGVqbyBlbiBsYSBsb25naXR1ZCBkZSBvbmRhIHJvamEgY29udHJhIHJlZmxlam8gZW4gbGEgbG9uZ2l0dWQgZGUgb25kYSBOSVIuDQoNCg0KYGBge3J9DQpwYWlycyhsYW5kc2F0Y3JvcDIwMTVbWzQ6NV1dLCBtYWluID0gIlJlZCB2ZXJzdXMgTklSIikNCmBgYA0KDQoNCiMjIyMjIExhIHByaW1lcmEgZ3JhZmljYSByZXZlbGEgYWx0YXMgY29ycmVsYWNpb25lcyBlbnRyZSBsYXMgcmVnaW9uZXMgZGUgbG9uZ2l0dWQgZGUgb25kYSBhenVsLiBEZWJpZG8gYSBsYSBhbHRhIGNvcnJlbGFjaW9uLCBwb2RlbW9zIHVzYXIgdW5hIGRlIGxhcyBiYW5kYXMgYXp1bGVzIHNpbiBwZXJkZXIgbXVjaGEgaW5mb3JtYWNpb24uDQoNCiMjIyMjIEVzdGEgZGlzdHJpYnVjaW9uIGRlIHB1bnRvcyBlbiBsYSBzZWd1bmRhIGdyYWZpY2EgKGVudHJlIE5JUiB5IHJvam8pIGVzIHVuaWNhIGRlYmlkbyBhIHN1IGZvcm1hIHRyaWFuZ3VsYXIuIExhIHZlZ2V0YWNpb24gc2UgcmVmbGVqYSBtdXkgYmllbiBlbiBlbCByYW5nbyBOSVIgcXVlIGVsIHJvam8geSBjcmVhIGxhIGVzcXVpbmEgc3VwZXJpb3IgY2VyY2EgZGVsIGVqZSBOSVIgKHkpLiBFbCBhZ3VhIGFic29yYmUgZW5lcmdpYSBkZSB0b2RhcyBsYXMgYmFuZGFzIHkgb2N1cGEgZWwgbHVnYXIgY2VyY2FubyBhbCBvcmlnZW4uIEVsIHJpbmNvbiBtYXMgYWxlamFkbyBzZSBjcmVhIGRlYmlkbyBhIGxhcyBjYXJhY3RlcmlzdGljYXMgc3VwZXJmaWNpYWxlcyBhbHRhbWVudGUgcmVmbGVjdGFudGVzLCBjb21vIGVsIHN1ZWxvIGJyaWxsYW50ZSBvIGVsIGhvcm1pZ29uLg0KDQoNCiMjIyAqKlRJVFVMTzogRVhUUkFFUiBWQUxPUkVTIERFIFBJWEVMRVMgKioNCg0KDQojIyMjIyBBIG1lbnVkbywgcXVlcmVtb3Mgb2J0ZW5lciBsb3MgdmFsb3JlcyBkZSBsYXMgY2VsZGFzIHJhc3RlciBwYXJhIHViaWNhY2lvbmVzIGdlb2dyYWZpY2FzIG8gYXJlYXMgZXNwZWNpZmljYXMuIExhIC0gZXh0cmFjdCAtIGZ1bmNpb24gc2UgdXRpbGl6YSBwYXJhIG9idGVuZXIgdmFsb3JlcyByYXN0ZXIgZW4gbGFzIHViaWNhY2lvbmVzIGRlIG90cm9zIGRhdG9zIGVzcGFjaWFsZXMuIFB1ZWRlIHVzYXIgcHVudG9zLCBsaW5lYXMsIHBvbGlnb25vcyBvIHVuIG9iamV0byBkZSBleHRlbnNpb24gKHJlY3Rhbmd1bG8pLiBUYW1iaWVuIHB1ZWRlIHVzYXIgbnVtZXJvcyBkZSBjZWxkYSBwYXJhIGV4dHJhZXIgdmFsb3Jlcy4gQWwgdXNhciBwdW50b3MsIC0gZXh0cmFjdCAtIGRldnVlbHZlIGxvcyB2YWxvcmVzIGRlIHVuIC0gUmFzdGVyKiAtIG9iamV0byBwYXJhIGxhcyBjZWxkYXMgZW4gbGFzIHF1ZSBzZSB1YmljYSB1biBjb25qdW50byBkZSBwdW50b3MuDQoNCg0KDQpgYGB7cn0NCiMgbG9hZCB0aGUgcG9seWdvbnMgd2l0aCBsYW5kIHVzZSBsYW5kIGNvdmVyIGluZm9ybWF0aW9uDQoNCnNpYmF0ZWNvYmVydCA9IHNoYXBlZmlsZSAoJ0M6L1VzZXJzL0RhdmlkL0Rlc2t0b3AvUEVSQ0VQQ0lPTiBSRU1PVEEvVFJBQkFKT19DT0JFUlRVUkFTL2NvYmVydHUuc2hwJykNCiAgICAjIHNhbXAgPSByZWFkUkRTKCdkYXRhL3JzL3NhbXBsZXMucmRzJykgICAgICAgICAgICAgICoqZW4gbGEgZ3VpYSBlc3RhIGFzaSoqDQoNCiMgZ2VuZXJhdGUgMzAwIHBvaW50IHNhbXBsZXMgZnJvbSB0aGUgcG9seWdvbnMNCg0KcHRzaWJhdGVjb2JlcnQyMDE1ID0gc3BzYW1wbGUoc2liYXRlY29iZXJ0LDMwMCwgdHlwZT0ncmVndWxhcicpDQogICAgIyBwdHNhbXAgPSBzcHNhbXBsZShzYW1wLCAzMDAsIHR5cGU9J3JlZ3VsYXInKSAgICAgICAqKmVuIGxhIGd1aWEgZXN0YSBhc2kqKg0KDQojIGFkZCB0aGUgbGFuZCBjb3ZlciBjbGFzcyB0byB0aGUgcG9pbnRzDQpwdHNpYmF0ZWNvYmVydCROYW1lID0gb3ZlcihwdHNpYmF0ZWNvYmVydCwgc2liYXRlY29iZXJ0KSROYW1lDQogICAgIyBwdHNhbXAkY2xhc3MgPSBvdmVyKHB0c2FtcCwgc2FtcCkkY2xhc3MgICAgICAgICAgICAqKmVuIGxhIGd1aWEgZXN0YSBhc2kqKg0KDQoNCiMgZXh0cmFjdCB2YWx1ZXMgd2l0aCBwb2ludHMNCmRmID0gZXh0cmFjdChsYW5kc2F0MjAxNSwgcHRzaWJhdGVjb2JlcnQyMDE1KQ0KICAgIyBkZiA9IGV4dHJhY3QobGFuZHNhdDEsIHB0c2FtcCkgICAgICAgICAgICAgICAgICAgICAgKiplbiBsYSBndWlhIGVzdGEgYXNpKioNCg0KIyBUbyBzZWUgc29tZSBvZiB0aGUgcmVmbGVjdGFuY2UgdmFsdWVzDQpoZWFkKGRmKQ0KDQojICAgICB1bHRyYS5ibHVlIGJsdWUgZ3JlZW4gIHJlZCAgIE5JUiBTV0lSMSBTV0lSMg0KI1sxLF0gICAgICAgODQ4NCA3ODAwICA3NTI4IDY5MzEgMTQ3NzcgMTA4NzkgIDgxNjcNCiNbMixdICAgICAgIDg4MTYgODI2NSAgODY5NCA4MTgxIDIxMDI0IDE2NzUzIDExMzEzDQojWzMsXSAgICAgICA4NDE5IDc3OTEgIDgyMDYgNjg0NyAyNDc2MSAxMTgwMSAgNzk2Mg0KI1s0LF0gICAgICAgODM5OSA3NzQ1ICA4MDg3IDY3NzUgMjQ3NzUgMTIxNjAgIDgwMTINCiNbNSxdICAgICAgIDgwNzIgNzM5NCAgNjkwNCA2MjczIDExMjA3ICA4MDk4ICA2NjIxDQojWzYsXSAgICAgICA4MDcyIDczODAgIDY4MjcgNjIzMSAxMDcyOCAgODA4NCAgNjY1NA0KYGBgDQoNCg0KDQojIyMgKipUSVRVTE86IFBFUkZJTEVTIEVTUEVDVFJBTEVTKioNCg0KDQojIyMjIyBVbmEgZ3JhZmljYSBkZWwgZXNwZWN0cm8gKHRvZGFzIGxhcyBiYW5kYXMpIHBhcmEgbG9zIHBpeGVsZXMgcXVlIHJlcHJlc2VudGFuIGNpZXJ0YXMgY2FyYWN0ZXJpc3RpY2FzIGRlIGxhIHN1cGVyZmljaWUgdGVycmVzdHJlIChwLiBFai4gQWd1YSkgc2UgY29ub2NlIGNvbW8gcGVyZmlsIGVzcGVjdHJhbC4gRGljaG9zIHBlcmZpbGVzIGRlbXVlc3RyYW4gbGFzIGRpZmVyZW5jaWFzIGVuIGxhcyBwcm9waWVkYWRlcyBlc3BlY3RyYWxlcyBkZSB2YXJpYXMgY2FyYWN0ZXJpc3RpY2FzIGRlIGxhIHN1cGVyZmljaWUgdGVycmVzdHJlIHkgY29uc3RpdHV5ZW4gbGEgYmFzZSBwYXJhIGVsIGFuYWxpc2lzIGRlIGltYWdlbmVzLiBMb3MgdmFsb3JlcyBlc3BlY3RyYWxlcyBzZSBwdWVkZW4gZXh0cmFlciBkZSBjdWFscXVpZXIgY29uanVudG8gZGUgZGF0b3MgbXVsdGllc3BlY3RyYWxlcyB1dGlsaXphbmRvIGxhIC0gZXh0cmFjdCAtIGZ1bmNpb24uIEVuIGVsIGVqZW1wbG8gYW50ZXJpb3IsIGV4dHJhamltb3MgdmFsb3JlcyBkZSBkYXRvcyBkZSBMYW5kc2F0IHBhcmEgbGFzIG11ZXN0cmFzLiBFc3RhcyBtdWVzdHJhcyBpbmNsdXllbjogdGllcnJhcyBkZSBjdWx0aXZvLCBhZ3VhLCBiYXJiZWNobywgY29uc3RydWlkbyB5IGFiaWVydG8uIFByaW1lcm8gY2FsY3VsYW1vcyBsb3MgdmFsb3JlcyBtZWRpb3MgZGUgcmVmbGVjdGFuY2lhIHBhcmEgY2FkYSBjbGFzZSB5IGNhZGEgYmFuZGEuDQoNCg0KYGBge3J9DQoNCm51bWVybz0gbGVuZ3RoKHB0c2liYXRlY29iZXJ0KQ0KbnVtZXJvDQoNCmRmX3NhbXBsZXMgPSBhcyAocHRzaWJhdGVjb2JlcnQsICJTcGF0aWFsUG9pbnRzRGF0YUZyYW1lIikNCmRmX3NhbXBsZXMNCmRmX3NhbXBsZXNAZGF0YT1kYXRhLmZyYW1lKElEPTE6bnVtZXJvLHNpemU9MSkNCmRmX3NhbXBsZXMNCg0KDQpwbG90KGxhbmRzYXRjcm9wMjAxNSkNCnBsb3Qoc2liYXRlY29iZXJ0LCBhZGQ9IFRSVUUpDQpwbG90KGRmX3NhbXBsZXMscGNoPTEsIGNleD0oZGZfc2FtcGxlcyRzaXplKS80LCBhZGQ9VFJVRSkNCg0KDQpkZl9zYW1wbGVzJE5hbWUgPW92ZXIoZGZfc2FtcGxlcyxzaWJhdGVjb2JlcnQpJE5hbWUNCmRmX3NhbXBsZXMNCmRmMT1yYXN0ZXI6OmV4dHJhY3QobGFuZHNhdGNyb3AyMDE1LCBkZl9zYW1wbGVzKQ0KDQoNCm1zID0gYWdncmVnYXRlKGRmMSwgbGlzdChwdHNpYmF0ZWNvYmVydCROYW1lKSwgbWVhbikNCiMjIG1zID0gYWdncmVnYXRlKGRmLCBsaXN0KHB0c2FtcCRjbGFzcyksIG1lYW4pICAgICAgICAgKiogYXNpIGVzdGEgZW4gbGEgZ3VpYSoqDQoNCiMgaW5zdGVhZCBvZiB0aGUgZmlyc3QgY29sdW1uLCB3ZSB1c2Ugcm93IG5hbWVzDQpyb3duYW1lcyhtcykgPSBtc1ssMV0NCm1zID0gbXNbLC0xXQ0KbXMNCg0KDQojIyAgICAgICAgICB1bHRyYS5ibHVlICAgICAgYmx1ZSAgICAgIGdyZWVuICAgICAgIHJlZCAgICAgICAgTklSICAgICAgU1dJUjENCiMjIGJ1aWx0ICAgICAwLjE4NjQ5MjUgMC4xNzk1MzcxIDAuMTc5NTMzMTcgMC4xOTU4NDE0IDAuMjU0NDg0NDcgMC4yNDg1MDE5Nw0KIyMgY3JvcGxhbmQgIDAuMTEyOTgxMyAwLjA5MDk2NDUgMC4wODU5NjcyMiAwLjA1NTAzNDQgMC40ODMzNTQ2MiAwLjE2MTQyMDg1DQojIyBmYWxsb3cgICAgMC4xMzE5MTk4IDAuMTE2NDg2OSAwLjEwNDUzNzY0IDAuMTE1MTI0MyAwLjE4MDEyOTYyIDAuMjMxMzkyMjgNCiMjIG9wZW4gICAgICAwLjEzODgwMTQgMC4xMzc1MjM1IDAuMTUyNzMxNjMgMC4yMDY2NDI1IDAuMzQ0NzY2NzAgMC4zNTgyMDg3Nw0KIyMgd2F0ZXIgICAgIDAuMTMzNjI0MiAwLjExNjU3MjggMC4wOTkyMjcyNiAwLjA3ODU5NDcgMC4wNDkwOTIwMSAwLjAzMzYwMDQ3DQojIyAgICAgICAgICAgICAgIFNXSVIyDQojIyBidWlsdCAgICAwLjIwMDAxMzA2DQojIyBjcm9wbGFuZCAwLjA3MzE0MTg2DQojIyBmYWxsb3cgICAwLjE5MTQzMDMwDQojIyBvcGVuICAgICAwLjIxMzQ2MzQzDQojIyB3YXRlciAgICAwLjAyNzIzMzk4DQoNCmBgYA0KDQoNCiMjIyMjIEFob3JhIHRyYXphbW9zIGVsIGVzcGVjdHJvIG1lZGlvIGRlIGVzdGFzIGNhcmFjdGVyaXN0aWNhcy4NCg0KDQpgYGB7cn0NCiMgQ3JlYXRlIGEgdmVjdG9yIG9mIGNvbG9yIGZvciB0aGUgbGFuZCBjb3ZlciBjbGFzc2VzIGZvciB1c2UgaW4gcGxvdHRpbmcNCm15Y29sb3IgPSBjKCdkYXJrcmVkJywgJ3llbGxvdycsICdidXJseXdvb2QnLCAnY3lhbicsICdibHVlJywgJ2dyZWVuJywncGluaycpDQojdHJhbnNmb3JtIG1zIGZyb20gYSBkYXRhLmZyYW1lIHRvIGEgbWF0cml4DQptcyA9IGFzLm1hdHJpeChtcykNCiMgRmlyc3QgY3JlYXRlIGFuIGVtcHR5IHBsb3QNCnBsb3QoMCwgeWxpbT1jKDAsMjUwMDApLCB4bGltID0gYygxLDcpLCB0eXBlPSduJywgeGxhYj0iQmFuZHMiLCB5bGFiID0gIlJlZmxlY3RhbmNlIikNCiMgYWRkIHRoZSBkaWZmZXJlbnQgY2xhc3Nlcw0KZm9yIChpIGluIDE6bnJvdyhtcykpew0KICBsaW5lcyhtc1tpLF0sIHR5cGUgPSAibCIsIGx3ZCA9IDMsIGx0eSA9IDEsIGNvbCA9IG15Y29sb3JbaV0pDQp9DQojIFRpdGxlDQp0aXRsZShtYWluPSJTcGVjdHJhbCBQcm9maWxlIGZyb20gTGFuZHNhdCIsIGZvbnQubWFpbiA9IDIpDQojIExlZ2VuZA0KbGVnZW5kKCJ0b3BsZWZ0Iiwgcm93bmFtZXMobXMpLA0KICAgICAgIGNleD0wLjgsIGNvbD1teWNvbG9yLCBsdHkgPSAxLCBsd2QgPTMsIGJ0eSA9ICJuIikNCmBgYA0KDQoNCiMjIyMjIEVsIHBlcmZpbCBlc3BlY3RyYWwgbXVlc3RyYSAoZGVzKSBzaW1pbGl0dWQgZW4gbGEgcmVmbGVjdGFuY2lhIGRlIGRpZmVyZW50ZXMgY2FyYWN0ZXJpc3RpY2FzIGVuIGxhIHN1cGVyZmljaWUgZGUgbGEgdGllcnJhIChvIHBvciBlbmNpbWEgZGUgZWxsYSkuICdBZ3VhJyBtdWVzdHJhIHVuYSByZWZsZXhpb24gcmVsYXRpdmFtZW50ZSBiYWphIGVuIHRvZGFzIGxhcyBsb25naXR1ZGVzIGRlIG9uZGEsIHkgJ2NvbnN0cnVpZG8nLCAnZW4gYmFyYmVjaG8nIHkgJ2FiaWVydG8nIHRpZW5lbiB1bmEgcmVmbGVjdGFuY2lhIHJlbGF0aXZhbWVudGUgYWx0YSBlbiBsYXMgbG9uZ2l0dWRlcyBkZSBvbmRhIG1hcyBsYXJnYXMuDQoNCg0KQWRkIGEgbmV3IGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqSW5zZXJ0IENodW5rKiBidXR0b24gb24gdGhlIHRvb2xiYXIgb3IgYnkgcHJlc3NpbmcgKkN0cmwrQWx0K0kqLg0KDQpXaGVuIHlvdSBzYXZlIHRoZSBub3RlYm9vaywgYW4gSFRNTCBmaWxlIGNvbnRhaW5pbmcgdGhlIGNvZGUgYW5kIG91dHB1dCB3aWxsIGJlIHNhdmVkIGFsb25nc2lkZSBpdCAoY2xpY2sgdGhlICpQcmV2aWV3KiBidXR0b24gb3IgcHJlc3MgKkN0cmwrU2hpZnQrSyogdG8gcHJldmlldyB0aGUgSFRNTCBmaWxlKS4NCg0KVGhlIHByZXZpZXcgc2hvd3MgeW91IGEgcmVuZGVyZWQgSFRNTCBjb3B5IG9mIHRoZSBjb250ZW50cyBvZiB0aGUgZWRpdG9yLiBDb25zZXF1ZW50bHksIHVubGlrZSAqS25pdCosICpQcmV2aWV3KiBkb2VzIG5vdCBydW4gYW55IFIgY29kZSBjaHVua3MuIEluc3RlYWQsIHRoZSBvdXRwdXQgb2YgdGhlIGNodW5rIHdoZW4gaXQgd2FzIGxhc3QgcnVuIGluIHRoZSBlZGl0b3IgaXMgZGlzcGxheWVkLg0K