getwd()
list.files(path = ".")
library(raster)
library(sp)
# Blue
b2 <- raster('C:\\Users\\USS\\Desktop\\Pedro\\2019 - 2020\\Percepcion remota\\P2\\Practica\\rsdata\\rs\\LC08_044034_20170614_B2.TIF') #con \\ en vez de /, importante poner ' en la ruta
b2
# Green
b3 <- raster("C:/Users/USS/Desktop/Pedro/2019 - 2020/Percepcion remota/P2/Practica/rsdata/rs/LC08_044034_20170614_B3.TIF") #con / en vez de \\
b3
# Red
b4 <- raster("C:/Users/USS/Desktop/Pedro/2019 - 2020/Percepcion remota/P2/Practica/rsdata/rs/LC08_044034_20170614_B4.TIF")
b4
# Near Infrared (NIR)
b5 <- raster("C:/Users/USS/Desktop/Pedro/2019 - 2020/Percepcion remota/P2/Practica/rsdata/rs/LC08_044034_20170614_B5.TIF")
b5
crs(b2) #Para ver sistema de coordenadas de referencia
ncell(b2) #Para ver el número de celdas
nrow(b2) #Para ver el número de filas
ncol(b2) #Para ver el número de columnas
dim(b2) #Para ver la dimension
res(b2) #Para ver la resolución espacial
nlayers(b2) #Número de bandas
compareRaster(b2,b3) #Compara si las bandas tienen la misma extensión, número de filas y columnas, proyección, resolución y origen
s <- stack(b5, b4, b3) #Crear RasterStack con múltiples bandas a través de RasterLayers (bandas simples) existentes
s
class : RasterStack
dimensions : 1245, 1497, 1863765, 3 (nrow, ncol, ncell, nlayers)
resolution : 30, 30 (x, y)
extent : 594090, 639000, 4190190, 4227540 (xmin, xmax, ymin, ymax)
crs : +proj=utm +zone=10 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0
names : LC08_044034_20170614_B5, LC08_044034_20170614_B4, LC08_044034_20170614_B3
min values : 0.0008457669, 0.0208406653, 0.0425921641
max values : 1.0124315, 0.7861769, 0.6924697
#Otra forma de crear RasterStack
filenames <- paste0("C:/Users/USS/Desktop/Pedro/2019 - 2020/Percepcion remota/P2/Practica/rsdata/rs/LC08_044034_20170614_B", 1:11, ".TIF") #crear una lista de RastersLayers para usar
filenames
[1] "C:/Users/USS/Desktop/Pedro/2019 - 2020/Percepcion remota/P2/Practica/rsdata/rs/LC08_044034_20170614_B1.TIF"
[2] "C:/Users/USS/Desktop/Pedro/2019 - 2020/Percepcion remota/P2/Practica/rsdata/rs/LC08_044034_20170614_B2.TIF"
[3] "C:/Users/USS/Desktop/Pedro/2019 - 2020/Percepcion remota/P2/Practica/rsdata/rs/LC08_044034_20170614_B3.TIF"
[4] "C:/Users/USS/Desktop/Pedro/2019 - 2020/Percepcion remota/P2/Practica/rsdata/rs/LC08_044034_20170614_B4.TIF"
[5] "C:/Users/USS/Desktop/Pedro/2019 - 2020/Percepcion remota/P2/Practica/rsdata/rs/LC08_044034_20170614_B5.TIF"
[6] "C:/Users/USS/Desktop/Pedro/2019 - 2020/Percepcion remota/P2/Practica/rsdata/rs/LC08_044034_20170614_B6.TIF"
[7] "C:/Users/USS/Desktop/Pedro/2019 - 2020/Percepcion remota/P2/Practica/rsdata/rs/LC08_044034_20170614_B7.TIF"
[8] "C:/Users/USS/Desktop/Pedro/2019 - 2020/Percepcion remota/P2/Practica/rsdata/rs/LC08_044034_20170614_B8.TIF"
[9] "C:/Users/USS/Desktop/Pedro/2019 - 2020/Percepcion remota/P2/Practica/rsdata/rs/LC08_044034_20170614_B9.TIF"
[10] "C:/Users/USS/Desktop/Pedro/2019 - 2020/Percepcion remota/P2/Practica/rsdata/rs/LC08_044034_20170614_B10.TIF"
[11] "C:/Users/USS/Desktop/Pedro/2019 - 2020/Percepcion remota/P2/Practica/rsdata/rs/LC08_044034_20170614_B11.TIF"
landsat <- stack(filenames) #Crear RasterStack a través de los nombres de los archivos
landsat
class : RasterStack
dimensions : 1245, 1497, 1863765, 11 (nrow, ncol, ncell, nlayers)
resolution : 30, 30 (x, y)
extent : 594090, 639000, 4190190, 4227540 (xmin, xmax, ymin, ymax)
crs : +proj=utm +zone=10 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0
names : LC08_044034_20170614_B1, LC08_044034_20170614_B2, LC08_044034_20170614_B3, LC08_044034_20170614_B4, LC08_044034_20170614_B5, LC08_044034_20170614_B6, LC08_044034_20170614_B7, LC08_044034_20170614_B8, LC08_044034_20170614_B9, LC08_044034_20170614_B10, LC08_044034_20170614_B11
min values : 9.641791e-02, 7.483990e-02, 4.259216e-02, 2.084067e-02, 8.457669e-04, -7.872183e-03, -5.052945e-03, 3.931751e-02, -4.337332e-04, 2.897978e+02, 2.885000e+02
max values : 0.73462820, 0.71775615, 0.69246972, 0.78617686, 1.01243150, 1.04320455, 1.11793602, 0.82673049, 0.03547901, 322.43139648, 317.99530029
compareRaster(s,landsat)
[1] TRUE
par(mfrow = c(2,2)) #Para dividir la pantalla plot en 2 filas y 2 columnas
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))

plot(b2, main = "Blue", col = gray(0:100 / 100)) #Se ve mejor si se grafica solo una banda

landsatRGB <- stack(b4, b3, b2)
plotRGB(landsatRGB, axes = TRUE, stretch = "lin", main = "Landsat True Color Composite")

landsatFCC <- stack(b5, b4, b3) #Imagen de "color falso" en la que se combinan las bandas NIR, rojo y verde, se aprecia bien la vegetación en rojo
plotRGB(landsatFCC, axes=TRUE, stretch="lin", main="Landsat False Color Composite")

landsatsub1 <- subset(landsat, 1:3) # Para crear un objeto con 3 bandas de otro objeto (landsat)
landsatsub1
landsatsub2 <- landsat[[1:3]] # Otro metodo
landsatsub2
# Comprobacion de numero de bandas de los objetos
nlayers(landsat)
nlayers(landsatsub1)
nlayers(landsatsub2)
landsat <- subset(landsat, 1:7) # Se crea un objeto con las primeras siete bandas de landsat
nlayers(landsat)
names(landsat) # Para ver los nombres de las bandas de landsat
[1] "LC08_044034_20170614_B1" "LC08_044034_20170614_B2" "LC08_044034_20170614_B3"
[4] "LC08_044034_20170614_B4" "LC08_044034_20170614_B5" "LC08_044034_20170614_B6"
[7] "LC08_044034_20170614_B7"
names(landsat) <- c('ultra-blue', 'blue', 'green', 'red', 'NIR', 'SWIR1', 'SWIR2') #Para cambiar los nombres de las bandas
names(landsat)
[1] "ultra.blue" "blue" "green" "red" "NIR" "SWIR1" "SWIR2"
extent(landsat) # Funcion extent
class : Extent
xmin : 594090
xmax : 639000
ymin : 4190190
ymax : 4227540
e <- extent(624387, 635752, 4200047, 4210939) #Se crea un objeto extent para cortar
e
class : Extent
xmin : 624387
xmax : 635752
ymin : 4200047
ymax : 4210939
landsatcrop <- crop(landsat, e) # Se corta landsat con la zona delimitada por e
landsatcrop
class : RasterBrick
dimensions : 363, 379, 137577, 7 (nrow, ncol, ncell, nlayers)
resolution : 30, 30 (x, y)
extent : 624390, 635760, 4200060, 4210950 (xmin, xmax, ymin, ymax)
crs : +proj=utm +zone=10 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0
source : memory
names : ultra.blue, blue, green, red, NIR, SWIR1, SWIR2
min values : 0.101796150, 0.075989284, 0.044045158, 0.030556191, 0.007243267, 0.001865030, 0.003144530
max values : 0.4548080, 0.4746728, 0.5034941, 0.5592065, 0.7013395, 0.9038041, 0.9750224
x <- writeRaster(landsatcrop, filename="cropped-landsat.tif", overwrite=TRUE) # Para guardar el raster recortado en formato .tif
y <-writeRaster(landsatcrop, filename="cropped-landsat.grd", overwrite=TRUE) # Para guardar el raster recortado en formato .grd (formato raster-grd)
pairs(landsatcrop[[1:2]], main = "Ultra-blue versus Blue")

pairs(landsatcrop[[4:5]], main = "Red versus NIR")

# Se cargan los poligonos con información sobre uso del suelo y cobertura del suelo
samp <- readRDS("C:/Users/USS/Desktop/Pedro/2019 - 2020/Percepcion remota/P2/Practica/rsdata/rs/samples.rds")
samp
class : SpatialPolygonsDataFrame
features : 49
extent : 594416.7, 638822.2, 4190232, 4224228 (xmin, xmax, ymin, ymax)
crs : +proj=utm +zone=10 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0
variables : 2
names : id, class
min values : 1, built
max values : 5, water
plot(samp)

# Se generan muestras de 300 puntos de los polígonos
ptsamp <- spsample(samp, 300, type='regular')
ptsamp
class : SpatialPoints
features : 286
extent : 594996.8, 638799.8, 4190289, 4223952 (xmin, xmax, ymin, ymax)
crs : +proj=utm +zone=10 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0
# Para agregar la clase de samp a ptsamp
ptsamp$class <- over(ptsamp, samp)$class
list(ptsamp$class)
[[1]]
[1] "fallow" "fallow" "fallow" "open" "open" "open" "fallow" "fallow"
[9] "fallow" "open" "open" "open" "open" "cropland" "fallow" "fallow"
[17] "open" "open" "open" "open" "open" "cropland" "cropland" "fallow"
[25] "fallow" "open" "open" "open" "open" "open" "open" "open"
[33] "open" "open" "open" "open" "open" "open" "open" "open"
[41] "open" "open" "open" "open" "open" "open" "open" "open"
[49] "cropland" "cropland" "open" "open" "open" "open" "open" "open"
[57] "open" "open" "open" "cropland" "cropland" "open" "open" "open"
[65] "open" "open" "open" "open" "open" "open" "open" "cropland"
[73] "cropland" "cropland" "fallow" "open" "cropland" "cropland" "cropland" "fallow"
[81] "fallow" "open" "open" "open" "open" "cropland" "fallow" "open"
[89] "open" "open" "open" "open" "fallow" "fallow" "open" "open"
[97] "fallow" "fallow" "fallow" "fallow" "fallow" "fallow" "fallow" "fallow"
[105] "built" "built" "built" "built" "open" "built" "fallow" "open"
[113] "fallow" "fallow" "fallow" "fallow" "open" "fallow" "fallow" "open"
[121] "open" "fallow" "open" "open" "open" "built" "built" "built"
[129] "built" "built" "built" "built" "built" "cropland" "cropland" "cropland"
[137] "cropland" "built" "built" "built" "built" "built" "built" "built"
[145] "cropland" "water" "cropland" "cropland" "cropland" "water" "water" "water"
[153] "water" "built" "built" "water" "water" "water" "water" "water"
[161] "water" "water" "water" "water" "water" "water" "water" "cropland"
[169] "water" "water" "water" "water" "water" "water" "water" "water"
[177] "water" "cropland" "cropland" "water" "water" "water" "water" "water"
[185] "water" "water" "water" "water" "water" "water" "water" "water"
[193] "water" "cropland" "cropland" "water" "water" "water" "water" "water"
[201] "water" "water" "water" "water" "water" "water" "water" "water"
[209] "cropland" "water" "water" "water" "water" "water" "water" "water"
[217] "water" "water" "water" "water" "water" "water" "water" "water"
[225] "water" "water" "water" "water" "water" "water" "water" "water"
[233] "water" "water" "water" "water" "water" "water" "water" "water"
[241] "water" "water" "water" "water" "water" "water" "cropland" "cropland"
[249] "cropland" "cropland" "water" "water" "cropland" "water" "water" "water"
[257] "water" "water" "water" "water" "water" "cropland" "cropland" "water"
[265] "water" "water" "water" "water" "water" "water" "water" "water"
[273] "water" "water" "water" "water" "water" "water" "water" "water"
[281] "water" "water" "water" "water" "water" "water"
# Para extraer los valores donde hay puntos
df <- extract(landsat, ptsamp)
head(df) #Para visualizar los primeros valores
ultra.blue blue green red NIR SWIR1 SWIR2
[1,] 0.1410052 0.1248705 0.1113816 0.1148080 0.1793469 0.2322618 0.1928575
[2,] 0.1346511 0.1186031 0.1097117 0.1124225 0.2006646 0.2405243 0.2032236
[3,] 0.1372535 0.1197959 0.1036178 0.1024034 0.1818842 0.2088187 0.1686338
[4,] 0.1298801 0.1218344 0.1257163 0.1667470 0.3061041 0.3189208 0.1924455
[5,] 0.1289693 0.1201212 0.1211838 0.1598074 0.2862176 0.3166437 0.1924021
[6,] 0.1480100 0.1449739 0.1573568 0.2008598 0.3047379 0.3821368 0.2652685
ms <- aggregate(df, list(ptsamp$class), mean) # Se calculan los valores medios de reflectancia para cada clase y cada banda.
ms
# Ponemos los nombres de fila de ms con los valores de la primera columna de ms
rownames(ms) <- ms[,1]
rownames(ms)
[1] "built" "cropland" "fallow" "open" "water"
ms <- ms[,-1] # Quitamos la primera columna de ms
ms
# Se crea un vector de color para las clases de cubierta de tierra para usar en el plot
mycolor <- c('darkred', 'yellow', 'burlywood', 'cyan', 'blue')
# Trasformamos ms de data.frame a matriz
ms <- as.matrix(ms)
# Primero se crea un plot vacío
plot(0, ylim=c(0,0.6), xlim = c(1,7), type='n', xlab="Bands", ylab = "Reflectance")
# Se añaden las diferentes clases
for (i in 1:nrow(ms)){
lines(ms[i,], type = "l", lwd = 3, lty = 1, col = mycolor[i])
}
# Título
title(main="Spectral Profile from Landsat", font.main = 2)
# Leyenda
legend("topleft", rownames(ms),
cex=0.8, col=mycolor, lty = 1, lwd =3, bty = "n")

#Si no se ejecuta todo el código junto da error
LS0tDQp0aXRsZTogIlByYWN0aWNhIDIgcGVyY2VwY2nDs24gcmVtb3RhIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KYGBge3J9DQpnZXR3ZCgpDQpgYGANCg0KYGBge3J9DQpsaXN0LmZpbGVzKHBhdGggPSAiLiIpDQpgYGANCg0KYGBge3J9DQpsaWJyYXJ5KHJhc3RlcikNCmBgYA0KYGBge3J9DQpsaWJyYXJ5KHNwKQ0KYGBgDQoNCmBgYHtyfQ0KIyBCbHVlDQpiMiA8LSByYXN0ZXIoJ0M6XFxVc2Vyc1xcVVNTXFxEZXNrdG9wXFxQZWRyb1xcMjAxOSAtIDIwMjBcXFBlcmNlcGNpb24gcmVtb3RhXFxQMlxcUHJhY3RpY2FcXHJzZGF0YVxccnNcXExDMDhfMDQ0MDM0XzIwMTcwNjE0X0IyLlRJRicpICNjb24gXFwgZW4gdmV6IGRlIC8sIGltcG9ydGFudGUgcG9uZXIgJyBlbiBsYSBydXRhDQpiMg0KYGBgDQoNCmBgYHtyfQ0KIyBHcmVlbg0KYjMgPC0gcmFzdGVyKCJDOi9Vc2Vycy9VU1MvRGVza3RvcC9QZWRyby8yMDE5IC0gMjAyMC9QZXJjZXBjaW9uIHJlbW90YS9QMi9QcmFjdGljYS9yc2RhdGEvcnMvTEMwOF8wNDQwMzRfMjAxNzA2MTRfQjMuVElGIikgI2NvbiAvIGVuIHZleiBkZSBcXA0KYjMNCmBgYA0KDQpgYGB7cn0NCiMgUmVkDQpiNCA8LSByYXN0ZXIoIkM6L1VzZXJzL1VTUy9EZXNrdG9wL1BlZHJvLzIwMTkgLSAyMDIwL1BlcmNlcGNpb24gcmVtb3RhL1AyL1ByYWN0aWNhL3JzZGF0YS9ycy9MQzA4XzA0NDAzNF8yMDE3MDYxNF9CNC5USUYiKQ0KYjQNCmBgYA0KDQpgYGB7cn0NCiMgTmVhciBJbmZyYXJlZCAoTklSKQ0KYjUgPC0gcmFzdGVyKCJDOi9Vc2Vycy9VU1MvRGVza3RvcC9QZWRyby8yMDE5IC0gMjAyMC9QZXJjZXBjaW9uIHJlbW90YS9QMi9QcmFjdGljYS9yc2RhdGEvcnMvTEMwOF8wNDQwMzRfMjAxNzA2MTRfQjUuVElGIikNCmI1DQpgYGANCg0KYGBge3J9DQpjcnMoYjIpICNQYXJhIHZlciBzaXN0ZW1hIGRlIGNvb3JkZW5hZGFzIGRlIHJlZmVyZW5jaWENCmBgYA0KDQpgYGB7cn0NCm5jZWxsKGIyKSAjUGFyYSB2ZXIgZWwgbsO6bWVybyBkZSBjZWxkYXMNCmBgYA0KDQpgYGB7cn0NCm5yb3coYjIpICNQYXJhIHZlciBlbCBuw7ptZXJvIGRlIGZpbGFzDQpgYGANCg0KYGBge3J9DQpuY29sKGIyKSAjUGFyYSB2ZXIgZWwgbsO6bWVybyBkZSBjb2x1bW5hcw0KYGBgDQoNCmBgYHtyfQ0KZGltKGIyKSAjUGFyYSB2ZXIgbGEgZGltZW5zaW9uDQpgYGANCg0KYGBge3J9DQpyZXMoYjIpICNQYXJhIHZlciBsYSByZXNvbHVjacOzbiBlc3BhY2lhbA0KYGBgDQoNCmBgYHtyfQ0KbmxheWVycyhiMikgI07Dum1lcm8gZGUgYmFuZGFzDQpgYGANCg0KYGBge3J9DQpjb21wYXJlUmFzdGVyKGIyLGIzKSAjQ29tcGFyYSBzaSBsYXMgYmFuZGFzIHRpZW5lbiBsYSBtaXNtYSBleHRlbnNpw7NuLCBuw7ptZXJvIGRlIGZpbGFzIHkgY29sdW1uYXMsIHByb3llY2Npw7NuLCByZXNvbHVjacOzbiB5IG9yaWdlbg0KYGBgDQoNCmBgYHtyfQ0KcyA8LSBzdGFjayhiNSwgYjQsIGIzKSAjQ3JlYXIgUmFzdGVyU3RhY2sgY29uIG3Dumx0aXBsZXMgYmFuZGFzIGEgdHJhdsOpcyBkZSBSYXN0ZXJMYXllcnMgKGJhbmRhcyBzaW1wbGVzKSBleGlzdGVudGVzIA0Kcw0KYGBgDQoNCmBgYHtyfQ0KI090cmEgZm9ybWEgZGUgY3JlYXIgUmFzdGVyU3RhY2sNCg0KZmlsZW5hbWVzIDwtIHBhc3RlMCgiQzovVXNlcnMvVVNTL0Rlc2t0b3AvUGVkcm8vMjAxOSAtIDIwMjAvUGVyY2VwY2lvbiByZW1vdGEvUDIvUHJhY3RpY2EvcnNkYXRhL3JzL0xDMDhfMDQ0MDM0XzIwMTcwNjE0X0IiLCAxOjExLCAiLlRJRiIpICNjcmVhciB1bmEgbGlzdGEgZGUgUmFzdGVyc0xheWVycyBwYXJhIHVzYXIgDQpmaWxlbmFtZXMNCmBgYA0KDQpgYGB7cn0NCmxhbmRzYXQgPC0gc3RhY2soZmlsZW5hbWVzKSAjQ3JlYXIgUmFzdGVyU3RhY2sgYSB0cmF2w6lzIGRlIGxvcyBub21icmVzIGRlIGxvcyBhcmNoaXZvcw0KbGFuZHNhdA0KYGBgDQoNCmBgYHtyfQ0KY29tcGFyZVJhc3RlcihzLGxhbmRzYXQpDQpgYGANCg0KYGBge3J9DQpwYXIobWZyb3cgPSBjKDIsMikpICNQYXJhIGRpdmlkaXIgbGEgcGFudGFsbGEgcGxvdCBlbiAyIGZpbGFzIHkgMiBjb2x1bW5hcw0KcGxvdChiMiwgbWFpbiA9ICJCbHVlIiwgY29sID0gZ3JheSgwOjEwMCAvIDEwMCkpDQpwbG90KGIzLCBtYWluID0gIkdyZWVuIiwgY29sID0gZ3JheSgwOjEwMCAvIDEwMCkpDQpwbG90KGI0LCBtYWluID0gIlJlZCIsIGNvbCA9IGdyYXkoMDoxMDAgLyAxMDApKQ0KcGxvdChiNSwgbWFpbiA9ICJOSVIiLCBjb2wgPSBncmF5KDA6MTAwIC8gMTAwKSkNCmBgYA0KDQpgYGB7cn0NCnBsb3QoYjIsIG1haW4gPSAiQmx1ZSIsIGNvbCA9IGdyYXkoMDoxMDAgLyAxMDApKSAjU2UgdmUgbWVqb3Igc2kgc2UgZ3JhZmljYSBzb2xvIHVuYSBiYW5kYQ0KYGBgDQoNCmBgYHtyfQ0KbGFuZHNhdFJHQiA8LSBzdGFjayhiNCwgYjMsIGIyKSAjUGFyYSB0ZW5lciB1biBjb2xvciBuYXR1cmFsIGRlYmVtb3MgcGxvdGVhciBsYXMgYmFuZGFzIFJHQg0KcGxvdFJHQihsYW5kc2F0UkdCLCBheGVzID0gVFJVRSwgc3RyZXRjaCA9ICJsaW4iLCBtYWluID0gIkxhbmRzYXQgVHJ1ZSBDb2xvciBDb21wb3NpdGUiKQ0KYGBgDQoNCmBgYHtyfQ0KbGFuZHNhdEZDQyA8LSBzdGFjayhiNSwgYjQsIGIzKSAjSW1hZ2VuIGRlICJjb2xvciBmYWxzbyIgZW4gbGEgcXVlIHNlIGNvbWJpbmFuIGxhcyBiYW5kYXMgTklSLCByb2pvIHkgdmVyZGUsIHNlIGFwcmVjaWEgYmllbiBsYSB2ZWdldGFjacOzbiBlbiByb2pvDQpwbG90UkdCKGxhbmRzYXRGQ0MsIGF4ZXM9VFJVRSwgc3RyZXRjaD0ibGluIiwgbWFpbj0iTGFuZHNhdCBGYWxzZSBDb2xvciBDb21wb3NpdGUiKQ0KYGBgDQoNCmBgYHtyfQ0KbGFuZHNhdHN1YjEgPC0gc3Vic2V0KGxhbmRzYXQsIDE6MykgIyBQYXJhIGNyZWFyIHVuIG9iamV0byBjb24gMyBiYW5kYXMgZGUgb3RybyBvYmpldG8gKGxhbmRzYXQpDQpsYW5kc2F0c3ViMQ0KYGBgDQoNCmBgYHtyfQ0KbGFuZHNhdHN1YjIgPC0gbGFuZHNhdFtbMTozXV0gIyBPdHJvIG1ldG9kbw0KbGFuZHNhdHN1YjINCmBgYA0KDQpgYGB7cn0NCiMgQ29tcHJvYmFjaW9uIGRlIG51bWVybyBkZSBiYW5kYXMgZGUgbG9zIG9iamV0b3MNCm5sYXllcnMobGFuZHNhdCkgDQpubGF5ZXJzKGxhbmRzYXRzdWIxKQ0KbmxheWVycyhsYW5kc2F0c3ViMikNCmBgYA0KDQpgYGB7cn0NCmxhbmRzYXQgPC0gc3Vic2V0KGxhbmRzYXQsIDE6NykgIyBTZSBjcmVhIHVuIG9iamV0byBjb24gbGFzIHByaW1lcmFzIHNpZXRlIGJhbmRhcyBkZSBsYW5kc2F0DQpgYGANCg0KYGBge3J9DQpubGF5ZXJzKGxhbmRzYXQpDQpgYGANCg0KYGBge3J9DQpuYW1lcyhsYW5kc2F0KSAjIFBhcmEgdmVyIGxvcyBub21icmVzIGRlIGxhcyBiYW5kYXMgZGUgbGFuZHNhdA0KYGBgDQoNCmBgYHtyfQ0KbmFtZXMobGFuZHNhdCkgPC0gYygndWx0cmEtYmx1ZScsICdibHVlJywgJ2dyZWVuJywgJ3JlZCcsICdOSVInLCAnU1dJUjEnLCAnU1dJUjInKSAjUGFyYSBjYW1iaWFyIGxvcyBub21icmVzIGRlIGxhcyBiYW5kYXMNCm5hbWVzKGxhbmRzYXQpDQpgYGANCg0KYGBge3J9DQpleHRlbnQobGFuZHNhdCkgIyBGdW5jaW9uIGV4dGVudA0KYGBgDQoNCmBgYHtyfQ0KZSA8LSBleHRlbnQoNjI0Mzg3LCA2MzU3NTIsIDQyMDAwNDcsIDQyMTA5MzkpICNTZSBjcmVhIHVuIG9iamV0byBleHRlbnQgcGFyYSBjb3J0YXINCmUNCmBgYA0KDQpgYGB7cn0NCmxhbmRzYXRjcm9wIDwtIGNyb3AobGFuZHNhdCwgZSkgIyBTZSBjb3J0YSBsYW5kc2F0IGNvbiBsYSB6b25hIGRlbGltaXRhZGEgcG9yIGUNCmxhbmRzYXRjcm9wDQpgYGANCg0KYGBge3J9DQp4IDwtIHdyaXRlUmFzdGVyKGxhbmRzYXRjcm9wLCBmaWxlbmFtZT0iY3JvcHBlZC1sYW5kc2F0LnRpZiIsIG92ZXJ3cml0ZT1UUlVFKSAjIFBhcmEgZ3VhcmRhciBlbCByYXN0ZXIgcmVjb3J0YWRvIGVuIGZvcm1hdG8gLnRpZg0KYGBgDQoNCmBgYHtyfQ0KeSA8LXdyaXRlUmFzdGVyKGxhbmRzYXRjcm9wLCBmaWxlbmFtZT0iY3JvcHBlZC1sYW5kc2F0LmdyZCIsIG92ZXJ3cml0ZT1UUlVFKSAjIFBhcmEgZ3VhcmRhciBlbCByYXN0ZXIgcmVjb3J0YWRvIGVuIGZvcm1hdG8gLmdyZCAoZm9ybWF0byByYXN0ZXItZ3JkKQ0KYGBgDQoNCmBgYHtyfQ0KcGFpcnMobGFuZHNhdGNyb3BbWzE6Ml1dLCBtYWluID0gIlVsdHJhLWJsdWUgdmVyc3VzIEJsdWUiKSAjIExhIGZ1bmNpb24gcGFpcnMoKSAoZGVsIHBhcXVldGUgcmFzdGVyKSByZXByZXNlbnRhIHVuIGRpYWdyYW1hIGRlIGRpc3BlcnNpw7NuIGVudHJlIGRvcyBjYXBhcw0KYGBgDQoNCmBgYHtyfQ0KcGFpcnMobGFuZHNhdGNyb3BbWzQ6NV1dLCBtYWluID0gIlJlZCB2ZXJzdXMgTklSIikNCmBgYA0KDQpgYGB7cn0NCiMgU2UgY2FyZ2FuIGxvcyBwb2xpZ29ub3MgY29uIGluZm9ybWFjacOzbiBzb2JyZSB1c28gZGVsIHN1ZWxvIHkgY29iZXJ0dXJhIGRlbCBzdWVsbw0Kc2FtcCA8LSByZWFkUkRTKCJDOi9Vc2Vycy9VU1MvRGVza3RvcC9QZWRyby8yMDE5IC0gMjAyMC9QZXJjZXBjaW9uIHJlbW90YS9QMi9QcmFjdGljYS9yc2RhdGEvcnMvc2FtcGxlcy5yZHMiKQ0Kc2FtcA0KYGBgDQoNCmBgYHtyfQ0KcGxvdChzYW1wKQ0KYGBgDQoNCmBgYHtyfQ0KIyBTZSBnZW5lcmFuIG11ZXN0cmFzIGRlIDMwMCBwdW50b3MgZGUgbG9zIHBvbMOtZ29ub3MNCnB0c2FtcCA8LSBzcHNhbXBsZShzYW1wLCAzMDAsIHR5cGU9J3JlZ3VsYXInKQ0KcHRzYW1wDQpgYGANCg0KYGBge3J9DQojIFBhcmEgYWdyZWdhciBsYSBjbGFzZSBkZSBzYW1wIGEgcHRzYW1wDQpwdHNhbXAkY2xhc3MgPC0gb3ZlcihwdHNhbXAsIHNhbXApJGNsYXNzDQpsaXN0KHB0c2FtcCRjbGFzcykNCmBgYA0KDQpgYGB7cn0NCiMgUGFyYSBleHRyYWVyIGxvcyB2YWxvcmVzIGRvbmRlIGhheSBwdW50b3MNCmRmIDwtIGV4dHJhY3QobGFuZHNhdCwgcHRzYW1wKQ0KaGVhZChkZikgI1BhcmEgdmlzdWFsaXphciBsb3MgcHJpbWVyb3MgdmFsb3Jlcw0KYGBgDQoNCmBgYHtyfQ0KbXMgPC0gYWdncmVnYXRlKGRmLCBsaXN0KHB0c2FtcCRjbGFzcyksIG1lYW4pICMgU2UgY2FsY3VsYW4gbG9zIHZhbG9yZXMgbWVkaW9zIGRlIHJlZmxlY3RhbmNpYSBwYXJhIGNhZGEgY2xhc2UgeSBjYWRhIGJhbmRhLg0KbXMNCmBgYA0KDQpgYGB7cn0NCiMgUG9uZW1vcyBsb3Mgbm9tYnJlcyBkZSBmaWxhIGRlIG1zIGNvbiBsb3MgdmFsb3JlcyBkZSBsYSBwcmltZXJhIGNvbHVtbmEgZGUgbXMNCnJvd25hbWVzKG1zKSA8LSBtc1ssMV0NCnJvd25hbWVzKG1zKQ0KYGBgDQoNCmBgYHtyfQ0KbXMgPC0gbXNbLC0xXSAjIFF1aXRhbW9zIGxhIHByaW1lcmEgY29sdW1uYSBkZSBtcw0KbXMNCmBgYA0KDQpgYGB7cn0NCiMgU2UgY3JlYSB1biB2ZWN0b3IgZGUgY29sb3IgcGFyYSBsYXMgY2xhc2VzIGRlIGN1YmllcnRhIGRlIHRpZXJyYSBwYXJhIHVzYXIgZW4gZWwgcGxvdA0KbXljb2xvciA8LSBjKCdkYXJrcmVkJywgJ3llbGxvdycsICdidXJseXdvb2QnLCAnY3lhbicsICdibHVlJykNCg0KIyBUcmFzZm9ybWFtb3MgbXMgZGUgZGF0YS5mcmFtZSBhIG1hdHJpeg0KbXMgPC0gYXMubWF0cml4KG1zKQ0KDQojIFByaW1lcm8gc2UgY3JlYSB1biBwbG90IHZhY8Otbw0KcGxvdCgwLCB5bGltPWMoMCwwLjYpLCB4bGltID0gYygxLDcpLCB0eXBlPSduJywgeGxhYj0iQmFuZHMiLCB5bGFiID0gIlJlZmxlY3RhbmNlIikNCg0KIyBTZSBhw7FhZGVuIGxhcyBkaWZlcmVudGVzIGNsYXNlcw0KZm9yIChpIGluIDE6bnJvdyhtcykpew0KICBsaW5lcyhtc1tpLF0sIHR5cGUgPSAibCIsIGx3ZCA9IDMsIGx0eSA9IDEsIGNvbCA9IG15Y29sb3JbaV0pDQp9DQoNCiMgVMOtdHVsbw0KdGl0bGUobWFpbj0iU3BlY3RyYWwgUHJvZmlsZSBmcm9tIExhbmRzYXQiLCBmb250Lm1haW4gPSAyKQ0KDQojIExleWVuZGENCmxlZ2VuZCgidG9wbGVmdCIsIHJvd25hbWVzKG1zKSwNCiAgICAgICBjZXg9MC44LCBjb2w9bXljb2xvciwgbHR5ID0gMSwgbHdkID0zLCBidHkgPSAibiIpDQoNCiNTaSBubyBzZSBlamVjdXRhIHRvZG8gZWwgY8OzZGlnbyBqdW50byBkYSBlcnJvcg0KYGBgDQoNCg0KDQoNCg0KDQo=