library(raster)
landsat5 <- stack('data/rs/centralvalley-2011LT5.tif')
names(landsat5) <- c('blue','green','red','NIR','SWIR1','SWIR2')
landsat5
class : RasterStack
dimensions : 1230, 1877, 2308710, 6 (nrow, ncol, ncell, nlayers)
resolution : 0.0002694946, 0.0002694946 (x, y)
extent : -121.9258, -121.42, 37.85402, 38.1855 (xmin, xmax, ymin, ymax)
crs : +proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0
names : blue, green, red, NIR, SWIR1, SWIR2
plotRGB (landsat5[[c('red','green','blue')]], axes =TRUE, stretch = "lin", main = "Landsat True Color Composite-croped")

plotRGB (landsat5[[c('NIR','red','green')]], axes =TRUE, stretch = "lin", main = "Landsat True Color Composite-croped")

ndvi <- (landsat5[['NIR']] - landsat5[['red']]) / (landsat5[['NIR']] + landsat5[['red']])
e <- extent(-121.807,-121.725,38.004,38.072)
ndvi <- crop(ndvi,e)
ndvi
class : RasterLayer
dimensions : 252, 304, 76608 (nrow, ncol, ncell)
resolution : 0.0002694946, 0.0002694946 (x, y)
extent : -121.807, -121.725, 38.00413, 38.07204 (xmin, xmax, ymin, ymax)
crs : +proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0
source : memory
names : layer
values : -0.3360085, 0.7756007 (min, max)
#Convirtiendo el raster a un vector
nr <- getValues(ndvi)
str(nr)
num [1:76608] 0.245 0.236 0.272 0.277 0.277 ...
#La importancia de que los valores iniciales sean configurados radica en que de forma automática *kmeans* los centra aleatoreamente
set.seed(99)
#seran creados 10 grupos con 500 iteraciones máximas, iniciando con 5 conjuntos aleatorios, empleando el algoritmo 'Lloyd'
kmncluster <- kmeans(na.omit(nr), centers = 10, iter.max = 500, nstart = 5, algorithm = "Lloyd")
#la función 'kmeans' retornará un objeto de tipo "kmeans"
str(kmncluster)
List of 9
$ cluster : int [1:76608] 4 4 3 3 3 3 3 4 4 4 ...
$ centers : num [1:10, 1] 0.55425 0.00498 0.29997 0.20892 -0.20902 ...
..- attr(*, "dimnames")=List of 2
.. ..$ : chr [1:10] "1" "2" "3" "4" ...
.. ..$ : NULL
$ totss : num 6459
$ withinss : num [1:10] 5.69 6.13 4.91 4.9 5.75 ...
$ tot.withinss: num 55.8
$ betweenss : num 6403
$ size : int [1:10] 8932 4550 7156 6807 11672 8624 8736 5040 9893 5198
$ iter : int 108
$ ifault : NULL
- attr(*, "class")= chr "kmeans"
kmncluster
K-means clustering with 10 clusters of sizes 8932, 4550, 7156, 6807, 11672, 8624, 8736, 5040, 9893, 5198
Cluster means:
[,1]
1 0.55424794
2 0.00498429
3 0.29997047
4 0.20892299
5 -0.20901839
6 -0.14263451
7 0.38985922
8 0.64951387
9 0.47100012
10 0.11189216
Clustering vector:
[1] 4 4 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 10 10 10 4 10 10 10 10 4 10 10 4 4 4 4 4 4 4 4 4 4 4 4
[49] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 4 6
[97] 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
[145] 5 5 5 5 5 5 5 6 5 5 5 5 2 3 9 9 9 9 9 9 9 9 7 3 4 4 3 3 3 3 3 3 4 3 3 7 7 7 9 9 1 1 1 1 1 9 9 7
[193] 7 7 7 9 9 9 1 1 1 1 1 9 7 9 1 1 8 1 8 8 8 8 1 8 8 1 1 9 7 7 3 3 3 3 7 7 7 7 7 7 7 7 3 3 3 3 7 7
[241] 7 7 7 3 3 4 4 4 4 4 4 4 4 3 3 7 9 9 9 7 3 3 3 3 3 3 3 3 3 3 4 3 3 3 7 7 7 7 7 7 3 3 3 3 3 4 3 3
[289] 7 3 3 3 3 3 3 3 3 3 7 3 3 3 4 7 4 4 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 10 10 10 10 10 10 10 10 10 10
[337] 10 10 10 10 10 10 10 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
[385] 4 4 4 4 4 4 4 4 4 4 4 3 3 3 2 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
[433] 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 6 6 5 5 6 10 10 7 9 9 7 7 7 9 7 7 7 7 3 3 3 3 3 7 9 9 9
[481] 3 3 3 7 7 9 1 1 1 1 1 1 1 7 7 7 7 7 9 1 8 8 8 1 1 1 1 9 9 9 1 1 8 8 8 8 1 1 1 1 1 9 9 9 3 3 4 3
[529] 3 3 3 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 3 3 3 3 4 4 4 4 4 4 4 3 3 7 9 9 1 1 9 9 7 7 3 3 3 3 3 3 3 3
[577] 3 3 7 7 7 7 7 7 3 3 3 3 3 3 3 3 7 3 3 7 7 7 3 7 7 3 3 3 3 3 3 9 4 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4
[625] 4 4 4 10 10 10 10 10 10 10 4 4 4 10 10 4 4 10 10 10 10 10 10 10 4 4 4 4 4 4 4 4 4 4 4 4 4 4 10 4 4 4 4 4 4 4 4 4
[673] 4 4 4 4 4 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 7 2 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
[721] 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 6 5 5 5 5 6 4 7 7 1 7 7 1
[769] 1 1 7 4 4 10 4 3 9 9 9 9 1 9 9 9 7 3 3 9 1 1 1 1 1 1 1 9 9 3 3 7 9 9 9 1 1 1 1 1 1 1 1 9 9 1 8 8
[817] 8 1 1 1 1 1 1 1 1 1 1 9 3 3 4 3 3 3 3 3 3 3 3 7 7 3 7 7 7 7 7 7 7 7 7 3 3 3 4 4 4 4 4 4 4 3 3 7
[865] 9 1 1 1 9 9 7 7 3 3 3 3 3 3 4 3 3 3 3 3 7 7 7 7 3 3 3 3 7 3 3 3 7 3 3 7 7 3 7 7 7 3 3 7 9 9 1 1
[913] 3 3 3 3 3 3 3 4 4 4 4 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 10 10 10 4 4 4 10 10 4 10 10 10 10 10 4 4 4 4 4 4 4
[961] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4
[ reached getOption("max.print") -- omitted 75608 entries ]
Within cluster sum of squares by cluster:
[1] 5.693691 6.126246 4.914637 4.904445 5.754583 6.106546 5.180387 6.942609 5.528454 4.664211
(between_SS / total_SS = 99.1 %)
Available components:
[1] "cluster" "centers" "totss" "withinss" "tot.withinss" "betweenss" "size" "iter" "ifault"
#Mediante el objeto ndvi, se establecen los valores del clúster en el ráster nuevo
knr <- setValues(ndvi, kmncluster$cluster)
#Forma alternativa:
knr <- raster(ndvi)
values(knr) <-kmncluster$cluster
knr
class : RasterLayer
dimensions : 252, 304, 76608 (nrow, ncol, ncell)
resolution : 0.0002694946, 0.0002694946 (x, y)
extent : -121.807, -121.725, 38.00413, 38.07204 (xmin, xmax, ymin, ymax)
crs : +proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0
source : memory
names : layer
values : 1, 10 (min, max)
head(knr)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
1 4 4 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4
2 4 4 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4
3 4 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 10
4 3 3 3 3 3 3 3 4 4 4 4 3 4 4 4 4 4 4 4 4
5 3 3 4 4 4 3 3 4 4 4 4 3 4 4 4 4 4 4 4 4
6 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 4 4 4 4
7 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 3 3 4
8 4 4 4 4 4 4 4 4 4 4 3 3 3 7 7 7 7 7 7 7
9 3 3 3 4 4 4 4 4 3 3 3 3 7 9 9 9 9 7 7 7
10 3 3 3 3 3 3 3 4 3 3 3 7 7 9 9 9 9 9 7 7
#Definiendoi un vector de color para los cluster
mycolor <- c("#fef65b","#ff0000", "#daa520","#0000ff","#0000ff","#00ff00","#cbbeb5",
"#c3ff5b", "#ff7373", "#00ff00", "#808080")
#Se representa el NDVI y la clasificación supervisada para comprobar los grupos que han sido creados.
par(mfrow=c(1,2))
plot(ndvi, col = rev(terrain.colors(10)), main='Landsat-NDVI')
plot(knr, main = 'Unsupervised classification', col =mycolor)

landsatcrop <- crop(landsat5, e)
landsatcrop
class : RasterBrick
dimensions : 252, 304, 76608, 6 (nrow, ncol, ncell, nlayers)
resolution : 0.0002694946, 0.0002694946 (x, y)
extent : -121.807, -121.725, 38.00413, 38.07204 (xmin, xmax, ymin, ymax)
crs : +proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0
source : memory
names : blue, green, red, NIR, SWIR1, SWIR2
min values : 0.084590562, 0.055765331, 0.040395390, 0.034050025, 0.010290771, 0.006807715
max values : 0.3684652, 0.5407562, 0.5847761, 0.5988820, 0.5135725, 0.5523322
kmncluster
K-means clustering with 10 clusters of sizes 8932, 4550, 7156, 6807, 11672, 8624, 8736, 5040, 9893, 5198
Cluster means:
[,1]
1 0.55424794
2 0.00498429
3 0.29997047
4 0.20892299
5 -0.20901839
6 -0.14263451
7 0.38985922
8 0.64951387
9 0.47100012
10 0.11189216
Clustering vector:
[1] 4 4 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 10 10 10 4 10 10 10 10 4 10 10 4 4 4 4 4 4 4 4 4 4 4 4
[49] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 4 6
[97] 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
[145] 5 5 5 5 5 5 5 6 5 5 5 5 2 3 9 9 9 9 9 9 9 9 7 3 4 4 3 3 3 3 3 3 4 3 3 7 7 7 9 9 1 1 1 1 1 9 9 7
[193] 7 7 7 9 9 9 1 1 1 1 1 9 7 9 1 1 8 1 8 8 8 8 1 8 8 1 1 9 7 7 3 3 3 3 7 7 7 7 7 7 7 7 3 3 3 3 7 7
[241] 7 7 7 3 3 4 4 4 4 4 4 4 4 3 3 7 9 9 9 7 3 3 3 3 3 3 3 3 3 3 4 3 3 3 7 7 7 7 7 7 3 3 3 3 3 4 3 3
[289] 7 3 3 3 3 3 3 3 3 3 7 3 3 3 4 7 4 4 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 10 10 10 10 10 10 10 10 10 10
[337] 10 10 10 10 10 10 10 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
[385] 4 4 4 4 4 4 4 4 4 4 4 3 3 3 2 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
[433] 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 6 6 5 5 6 10 10 7 9 9 7 7 7 9 7 7 7 7 3 3 3 3 3 7 9 9 9
[481] 3 3 3 7 7 9 1 1 1 1 1 1 1 7 7 7 7 7 9 1 8 8 8 1 1 1 1 9 9 9 1 1 8 8 8 8 1 1 1 1 1 9 9 9 3 3 4 3
[529] 3 3 3 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 3 3 3 3 4 4 4 4 4 4 4 3 3 7 9 9 1 1 9 9 7 7 3 3 3 3 3 3 3 3
[577] 3 3 7 7 7 7 7 7 3 3 3 3 3 3 3 3 7 3 3 7 7 7 3 7 7 3 3 3 3 3 3 9 4 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4
[625] 4 4 4 10 10 10 10 10 10 10 4 4 4 10 10 4 4 10 10 10 10 10 10 10 4 4 4 4 4 4 4 4 4 4 4 4 4 4 10 4 4 4 4 4 4 4 4 4
[673] 4 4 4 4 4 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 7 2 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
[721] 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 6 5 5 5 5 6 4 7 7 1 7 7 1
[769] 1 1 7 4 4 10 4 3 9 9 9 9 1 9 9 9 7 3 3 9 1 1 1 1 1 1 1 9 9 3 3 7 9 9 9 1 1 1 1 1 1 1 1 9 9 1 8 8
[817] 8 1 1 1 1 1 1 1 1 1 1 9 3 3 4 3 3 3 3 3 3 3 3 7 7 3 7 7 7 7 7 7 7 7 7 3 3 3 4 4 4 4 4 4 4 3 3 7
[865] 9 1 1 1 9 9 7 7 3 3 3 3 3 3 4 3 3 3 3 3 7 7 7 7 3 3 3 3 7 3 3 3 7 3 3 7 7 3 7 7 7 3 3 7 9 9 1 1
[913] 3 3 3 3 3 3 3 4 4 4 4 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 10 10 10 4 4 4 10 10 4 10 10 10 10 10 4 4 4 4 4 4 4
[961] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4
[ reached getOption("max.print") -- omitted 75608 entries ]
Within cluster sum of squares by cluster:
[1] 5.693691 6.126246 4.914637 4.904445 5.754583 6.106546 5.180387 6.942609 5.528454 4.664211
(between_SS / total_SS = 99.1 %)
Available components:
[1] "cluster" "centers" "totss" "withinss" "tot.withinss" "betweenss" "size" "iter" "ifault"
#Definiendoi un vector de color para los cluster
mycolor <- c("magenta","black", "red","steelblue","blue","yellow","deepskyblue",
"orange", "green", "pink", "grey")
plot(knr, main = 'Unsupervised classification', col =mycolor)

| 1 |
0.55424794 |
Agrícola |
| 2 |
0.00498429 |
Urbano y bancos de arena |
| 3 |
0.29997047 |
Calles, Urbano |
| 4 |
0.20892299 |
Suelo descubierto |
| 5 |
-0.20901839 |
Agua |
| 6 |
-0.14263451 |
Agua |
| 7 |
0.38985922 |
Suelo descubierto |
| 8 |
0.64951387 |
Vegetación turgente |
| 9 |
0.47100012 |
Barbecho (baja cobertura vegetal) |
| 10 |
0.11189216 |
Urbano |
par(mfrow=c(1,2))
plotRGB(landsatcrop[[c('red','green','blue')]], axes =TRUE, stretch = "lin", main = "Landsat True Color Composite")
plot(knr, main = 'Unsupervised classification', col =mycolor)

LS0tDQp0aXRsZTogIlByYWN0aWNhcyA0IC0gUGVyY2VwY2nDs24gUmVtb3RhIg0KYXV0aG9yOiBFbGtpbiBBbGJlcnRvIEFwb250ZSBHw7NtZXoNCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCmBgYHtyfQ0KbGlicmFyeShyYXN0ZXIpDQpsYW5kc2F0NSA8LSBzdGFjaygnZGF0YS9ycy9jZW50cmFsdmFsbGV5LTIwMTFMVDUudGlmJykNCm5hbWVzKGxhbmRzYXQ1KSA8LSBjKCdibHVlJywnZ3JlZW4nLCdyZWQnLCdOSVInLCdTV0lSMScsJ1NXSVIyJykNCmxhbmRzYXQ1DQpgYGANCg0KDQpgYGB7cn0NCnBsb3RSR0IgKGxhbmRzYXQ1W1tjKCdyZWQnLCdncmVlbicsJ2JsdWUnKV1dLCBheGVzID1UUlVFLCBzdHJldGNoID0gImxpbiIsIG1haW4gPSAiTGFuZHNhdCBUcnVlIENvbG9yIENvbXBvc2l0ZS1jcm9wZWQiKQ0KYGBgDQoNCg0KYGBge3J9DQpwbG90UkdCIChsYW5kc2F0NVtbYygnTklSJywncmVkJywnZ3JlZW4nKV1dLCBheGVzID1UUlVFLCBzdHJldGNoID0gImxpbiIsIG1haW4gPSAiTGFuZHNhdCBUcnVlIENvbG9yIENvbXBvc2l0ZS1jcm9wZWQiKQ0KYGBgDQoNCmBgYHtyfQ0KbmR2aSA8LSAobGFuZHNhdDVbWydOSVInXV0gLSBsYW5kc2F0NVtbJ3JlZCddXSkgLyAobGFuZHNhdDVbWydOSVInXV0gKyBsYW5kc2F0NVtbJ3JlZCddXSkNCmBgYA0KDQoNCmBgYHtyfQ0KZSA8LSBleHRlbnQoLTEyMS44MDcsLTEyMS43MjUsMzguMDA0LDM4LjA3MikNCg0KbmR2aSA8LSBjcm9wKG5kdmksZSkNCm5kdmkNCmBgYA0KDQpgYGB7cn0NCiNDb252aXJ0aWVuZG8gZWwgcmFzdGVyIGEgdW4gdmVjdG9yDQpuciA8LSBnZXRWYWx1ZXMobmR2aSkNCnN0cihucikNCmBgYA0KDQpgYGB7cn0NCiNMYSBpbXBvcnRhbmNpYSBkZSBxdWUgbG9zIHZhbG9yZXMgaW5pY2lhbGVzICBzZWFuIGNvbmZpZ3VyYWRvcyByYWRpY2EgZW4gcXVlIGRlIGZvcm1hIGF1dG9tw6F0aWNhICprbWVhbnMqIGxvcyBjZW50cmEgYWxlYXRvcmVhbWVudGUNCnNldC5zZWVkKDk5KQ0KI3NlcmFuIGNyZWFkb3MgMTAgZ3J1cG9zICBjb24gNTAwIGl0ZXJhY2lvbmVzIG3DoXhpbWFzLCBpbmljaWFuZG8gY29uIDUgY29uanVudG9zIGFsZWF0b3Jpb3MsIGVtcGxlYW5kbyBlbCBhbGdvcml0bW8gJ0xsb3lkJw0Ka21uY2x1c3RlciA8LSBrbWVhbnMobmEub21pdChuciksIGNlbnRlcnMgPSAxMCwgaXRlci5tYXggPSA1MDAsIG5zdGFydCA9IDUsIGFsZ29yaXRobSA9ICJMbG95ZCIpDQojbGEgZnVuY2nDs24gJ2ttZWFucycgcmV0b3JuYXLDoSB1biBvYmpldG8gZGUgdGlwbyAia21lYW5zIg0Kc3RyKGttbmNsdXN0ZXIpDQpgYGANCmBgYHtyfQ0Ka21uY2x1c3Rlcg0KDQpgYGANCg0KDQpgYGB7cn0NCiNNZWRpYW50ZSBlbCBvYmpldG8gbmR2aSwgc2UgZXN0YWJsZWNlbiBsb3MgdmFsb3JlcyBkZWwgY2zDunN0ZXIgZW4gZWwgcsOhc3RlciBudWV2bw0Ka25yIDwtIHNldFZhbHVlcyhuZHZpLCBrbW5jbHVzdGVyJGNsdXN0ZXIpDQpgYGANCg0KYGBge3J9DQojRm9ybWEgYWx0ZXJuYXRpdmE6DQprbnIgPC0gcmFzdGVyKG5kdmkpDQp2YWx1ZXMoa25yKSA8LWttbmNsdXN0ZXIkY2x1c3Rlcg0KYGBgDQoNCmBgYHtyfQ0Ka25yDQpgYGANCg0KYGBge3J9DQpoZWFkKGtucikNCmBgYA0KDQpgYGB7cn0NCiNEZWZpbmllbmRvaSB1biB2ZWN0b3IgZGUgY29sb3IgcGFyYSBsb3MgY2x1c3Rlcg0KbXljb2xvciA8LSBjKCIjZmVmNjViIiwiI2ZmMDAwMCIsICIjZGFhNTIwIiwiIzAwMDBmZiIsIiMwMDAwZmYiLCIjMDBmZjAwIiwiI2NiYmViNSIsDQogICAgICAgICAgICAgIiNjM2ZmNWIiLCAiI2ZmNzM3MyIsICIjMDBmZjAwIiwgIiM4MDgwODAiKQ0KDQpgYGANCg0KYGBge3J9DQojU2UgcmVwcmVzZW50YSBlbCBORFZJIHkgbGEgY2xhc2lmaWNhY2nDs24gc3VwZXJ2aXNhZGEgcGFyYSBjb21wcm9iYXIgbG9zIGdydXBvcyBxdWUgaGFuIHNpZG8gY3JlYWRvcy4NCg0KcGFyKG1mcm93PWMoMSwyKSkNCnBsb3QobmR2aSwgY29sID0gcmV2KHRlcnJhaW4uY29sb3JzKDEwKSksIG1haW49J0xhbmRzYXQtTkRWSScpDQpwbG90KGtuciwgbWFpbiA9ICdVbnN1cGVydmlzZWQgY2xhc3NpZmljYXRpb24nLCBjb2wgPW15Y29sb3IpDQpgYGANCg0KDQoNCmBgYHtyfQ0KbGFuZHNhdGNyb3AgPC0gY3JvcChsYW5kc2F0NSwgZSkNCmxhbmRzYXRjcm9wDQpgYGANCg0KYGBge3J9DQprbW5jbHVzdGVyDQpgYGANCg0KDQpgYGB7cn0NCiNEZWZpbmllbmRvaSB1biB2ZWN0b3IgZGUgY29sb3IgcGFyYSBsb3MgY2x1c3Rlcg0KbXljb2xvciA8LSBjKCJtYWdlbnRhIiwiYmxhY2siLCAicmVkIiwic3RlZWxibHVlIiwiYmx1ZSIsInllbGxvdyIsImRlZXBza3libHVlIiwNCiAgICAgICAgICAgICAib3JhbmdlIiwgImdyZWVuIiwgInBpbmsiLCAiZ3JleSIpDQoNCmBgYA0KDQpgYGB7cn0NCnBsb3Qoa25yLCBtYWluID0gJ1Vuc3VwZXJ2aXNlZCBjbGFzc2lmaWNhdGlvbicsIGNvbCA9bXljb2xvcikNCmBgYA0KDQp8KipOdW1iZXIgb2YgQ2x1c3RlcioqIHwgKipDbHVzdGVyIG1lYW5zKiogfCAqKkNsYXNzKiogfA0KfDotLS0tLS0tLS0tLS0tLTp8Oi0tLS0tLS0tLS0tLTp8Oi0tLS0tLS0tLS0tLTp8DQp8IDEgfCAwLjU1NDI0Nzk0IHwgQWdyw61jb2xhIHwNCnwgMiB8IDAuMDA0OTg0MjkgfCBVcmJhbm8geSBiYW5jb3MgZGUgYXJlbmEgfA0KfCAzIHwgMC4yOTk5NzA0NyB8IENhbGxlcywgVXJiYW5vIHwNCnwgNCB8IDAuMjA4OTIyOTkgfCBTdWVsbyBkZXNjdWJpZXJ0byB8DQp8IDUgfCAtMC4yMDkwMTgzOSB8IEFndWEgfA0KfCA2IHwgLTAuMTQyNjM0NTEgfCBBZ3VhIHwNCnwgNyB8IDAuMzg5ODU5MjIgfCBTdWVsbyBkZXNjdWJpZXJ0byB8DQp8IDggfCAwLjY0OTUxMzg3IHwgVmVnZXRhY2nDs24gdHVyZ2VudGUgfA0KfCA5IHwgMC40NzEwMDAxMiB8IEJhcmJlY2hvIChiYWphIGNvYmVydHVyYSB2ZWdldGFsKSB8DQp8IDEwIHwgMC4xMTE4OTIxNiB8IFVyYmFubyB8DQoNCg0KYGBge3J9DQpwYXIobWZyb3c9YygxLDIpKQ0KcGxvdFJHQihsYW5kc2F0Y3JvcFtbYygncmVkJywnZ3JlZW4nLCdibHVlJyldXSwgYXhlcyA9VFJVRSwgc3RyZXRjaCA9ICJsaW4iLCBtYWluID0gIkxhbmRzYXQgVHJ1ZSBDb2xvciBDb21wb3NpdGUiKQ0KcGxvdChrbnIsIG1haW4gPSAnVW5zdXBlcnZpc2VkIGNsYXNzaWZpY2F0aW9uJywgY29sID1teWNvbG9yKQ0KYGBgDQoNCg0KDQo=