Librerias aplicadas
library(caret)
library(raster)
Carga de las bandas de imágenes satelitales.
band1 <- raster("/Users/elianaalizchuquillanquijulcapari/Documents/workspace-r/demos/capturas-landsat/roma/LC81910312013208LGN00/LC81910312013208LGN00_B1.TIF")
band2 <- raster("/Users/elianaalizchuquillanquijulcapari/Documents/workspace-r/demos/capturas-landsat/roma/LC81910312013208LGN00/LC81910312013208LGN00_B2.TIF")
band3 <- raster("/Users/elianaalizchuquillanquijulcapari/Documents/workspace-r/demos/capturas-landsat/roma/LC81910312013208LGN00/LC81910312013208LGN00_B3.TIF")
band4 <- raster("/Users/elianaalizchuquillanquijulcapari/Documents/workspace-r/demos/capturas-landsat/roma/LC81910312013208LGN00/LC81910312013208LGN00_B4.TIF")
band5 <- raster("/Users/elianaalizchuquillanquijulcapari/Documents/workspace-r/demos/capturas-landsat/roma/LC81910312013208LGN00/LC81910312013208LGN00_B5.TIF")
band6 <- raster("/Users/elianaalizchuquillanquijulcapari/Documents/workspace-r/demos/capturas-landsat/roma/LC81910312013208LGN00/LC81910312013208LGN00_B6.TIF")
band7 <- raster("/Users/elianaalizchuquillanquijulcapari/Documents/workspace-r/demos/capturas-landsat/roma/LC81910312013208LGN00/LC81910312013208LGN00_B7.TIF")
band10 <- raster("/Users/elianaalizchuquillanquijulcapari/Documents/workspace-r/demos/capturas-landsat/roma/LC81910312013208LGN00/LC81910312013208LGN00_B10.TIF")
band11 <- raster("/Users/elianaalizchuquillanquijulcapari/Documents/workspace-r/demos/capturas-landsat/roma/LC81910312013208LGN00/LC81910312013208LGN00_B11.TIF")
roma_rst_lan <- brick(band1,band2,band3,band4,band5,band6,band7,band10,band11)
names(roma_rst_lan) <- c(paste("Banda",1:7,sep=""),"Banda10","Banda11")
Procesado de datos
#Carga de muestras de entrenamiento
rstTrainroma <- raster("/Users/elianaalizchuquillanquijulcapari/Documents/workspace-r/demos/DataTraining/rome_lcz_GT.tif")
# Remover ceros (fondo NA)
rstTrainroma[rstTrainroma==0] <- NA
# Convertir a tipo discreto
rstTrainroma <- ratify(rstTrainroma)
# Cambiamos el nombre
names(rstTrainroma) <- "layer"
#Muestras de valores
table(values(rstTrainroma))
2 3 5 6 8 10 11 12 14 17
1551 104 1495 480 435 51 284 555 984 500
# Eliminación de NAs
rstDFlanroma.df <- na.omit(values(stack(rstTrainroma, roma_rst_lan)))
cols <- c("#fde725","#b5de2b", "#6ece58","#35b779", "#1f9e89","#26828e", "#31688e", "#3e4989", "#482878", "#440154")
plot(rstTrainroma, main="Muestras de entrenamiento de Roma", col = cols)

Fase de Clasificación
#Si es la primera vez se ejecuta, sino ya esta guardado los datos del dataframe.
#write.csv(rstDFlanroma.df,"rstDFRoma.csv", row.names = FALSE)
#Leemos los datos
samplesLanroma = read.csv("rstDFRoma.csv")
# Se divide las muestras en 70 y 30
trainx = list(0)
evalx = list(0)
for (i in 1:17){ # se itera en todas las posibles categorÃas
cls = samplesLanroma[samplesLanroma$layer == i,]
smpl <- floor(0.70 * nrow(cls))
tt <- sample(seq_len(nrow(cls)), size = smpl)
trainx[[i]] <- cls[tt,]
evalx[[i]] <- cls[-tt,]
}
# Se combina en dataframe referenciados s entrenamiento y evaluación
trn = do.call(rbind, trainx)
eva = do.call(rbind, evalx)
Algoritmo SVM
# Definiendo el control del entrenamiento
fitControl2 <- trainControl(method = "cv", # repeated cross-validation of the training data
number = 10)
# Entrenamiento con svm
svm_model1<- caret::train(x = trn[,(2:ncol(trn))], y = as.factor(trn$layer),
method = "svmRadial", metric="Accuracy",
trControl = fitControl2,
preProcess = c("center", "scale"),
tuneLength = 10)
# Entrenamiento modelo 2
svm_grid <- expand.grid(sigma=seq(from = 0.01, to = 0.10, by = 0.02),
C=seq(from = 2, to = 10, by = 2))
svm_model2<- caret::train(x = trn[,(2:ncol(trn))], y = as.factor(trn$layer),
method = "svmRadialSigma", metric="Accuracy",
trControl = fitControl2,
preProcess = c("center", "scale"),
tuneGrid = svm_grid)
Exploración del modelo
#Información modelo svm
print(svm_model1)
Support Vector Machines with Radial Basis Function Kernel
4502 samples
9 predictor
10 classes: '2', '3', '5', '6', '8', '10', '11', '12', '14', '17'
Pre-processing: centered (9), scaled (9)
Resampling: Cross-Validated (10 fold)
Summary of sample sizes: 4051, 4052, 4053, 4053, 4051, 4051, ...
Resampling results across tuning parameters:
C Accuracy Kappa
0.25 0.7587714 0.7092347
0.50 0.7734297 0.7271917
1.00 0.7825404 0.7382531
2.00 0.7945404 0.7528460
4.00 0.8034259 0.7635539
8.00 0.8109760 0.7730634
16.00 0.8187538 0.7828206
32.00 0.8274191 0.7935093
64.00 0.8296378 0.7962199
128.00 0.8247529 0.7903756
Tuning parameter 'sigma' was held constant at a value of 0.3604227
Accuracy was used to select the optimal model using the largest value.
The final values used for the model were sigma = 0.3604227 and C = 64.
print(svm_model2) #modelo 2
Support Vector Machines with Radial Basis Function Kernel
4502 samples
9 predictor
10 classes: '2', '3', '5', '6', '8', '10', '11', '12', '14', '17'
Pre-processing: centered (9), scaled (9)
Resampling: Cross-Validated (10 fold)
Summary of sample sizes: 4051, 4051, 4050, 4054, 4053, 4052, ...
Resampling results across tuning parameters:
sigma C Accuracy Kappa
0.01 2 0.7425466 0.6887106
0.01 4 0.7536667 0.7026741
0.01 6 0.7581023 0.7081204
0.01 8 0.7583260 0.7084588
0.01 10 0.7616618 0.7125652
0.03 2 0.7585497 0.7087512
0.03 4 0.7645433 0.7162499
0.03 6 0.7729819 0.7265514
0.03 8 0.7798758 0.7349210
0.03 10 0.7834408 0.7393069
0.05 2 0.7638771 0.7154095
0.05 4 0.7789864 0.7338853
0.05 6 0.7845485 0.7407388
0.05 8 0.7912068 0.7487595
0.05 10 0.7960883 0.7546275
0.07 2 0.7761000 0.7303001
0.07 4 0.7843252 0.7405191
0.07 6 0.7925387 0.7503611
0.07 8 0.7967565 0.7555402
0.07 10 0.8003101 0.7598150
0.09 2 0.7798852 0.7350146
0.09 4 0.7889885 0.7461249
0.09 6 0.7956468 0.7542104
0.09 8 0.7989767 0.7582768
0.09 10 0.8000943 0.7596269
Accuracy was used to select the optimal model using the largest value.
The final values used for the model were sigma = 0.07 and C = 10.
#Gráfica del modelo svm
plot(svm_model1)

plot(svm_model2) #modelo 2

Evaluación del modelo 1.
pred_svm_model1<- predict(svm_model1,newdata = eva[,-1])
cm <- confusionMatrix(data = pred_svm_model1, as.factor(eva$layer))
cm
Confusion Matrix and Statistics
Reference
Prediction 2 3 5 6 8 10 11 12 14 17
2 398 6 72 1 3 2 0 0 0 0
3 5 24 3 1 0 0 0 0 0 0
5 58 2 345 20 11 7 1 4 1 0
6 4 0 11 107 0 1 1 5 4 0
8 1 0 7 0 117 0 0 0 0 0
10 0 0 0 0 0 5 0 0 0 0
11 0 0 1 0 0 0 83 3 0 0
12 0 0 8 10 0 0 1 150 2 0
14 0 0 2 5 0 1 0 5 289 0
17 0 0 0 0 0 0 0 0 0 150
Overall Statistics
Accuracy : 0.8611
95% CI : (0.8449, 0.8762)
No Information Rate : 0.2406
P-Value [Acc > NIR] : < 2.2e-16
Kappa : 0.8341
Mcnemar's Test P-Value : NA
Statistics by Class:
Class: 2 Class: 3 Class: 5 Class: 6 Class: 8 Class: 10
Sensitivity 0.8541 0.75000 0.7684 0.74306 0.89313 0.312500
Specificity 0.9429 0.99528 0.9301 0.98550 0.99557 1.000000
Pos Pred Value 0.8257 0.72727 0.7684 0.80451 0.93600 1.000000
Neg Pred Value 0.9533 0.99580 0.9301 0.97949 0.99227 0.994306
Prevalence 0.2406 0.01652 0.2318 0.07434 0.06763 0.008260
Detection Rate 0.2055 0.01239 0.1781 0.05524 0.06040 0.002581
Detection Prevalence 0.2488 0.01704 0.2318 0.06866 0.06453 0.002581
Balanced Accuracy 0.8985 0.87264 0.8492 0.86428 0.94435 0.656250
Class: 11 Class: 12 Class: 14 Class: 17
Sensitivity 0.96512 0.89820 0.9764 1.00000
Specificity 0.99784 0.98814 0.9921 1.00000
Pos Pred Value 0.95402 0.87719 0.9570 1.00000
Neg Pred Value 0.99838 0.99037 0.9957 1.00000
Prevalence 0.04440 0.08622 0.1528 0.07744
Detection Rate 0.04285 0.07744 0.1492 0.07744
Detection Prevalence 0.04491 0.08828 0.1559 0.07744
Balanced Accuracy 0.98148 0.94317 0.9842 1.00000
Representación de Matriz de confusión
cm_d <- as.data.frame(cm$table)
cm_st <-data.frame(cm$overall)
cm_st$cm.overall <- round(cm_st$cm.overall,2)
cm_p <- as.data.frame(prop.table(cm$table))
cm_d$Perc <- round(cm_p$Freq*100,2)
# dibujando la matriz
ggplot(data = cm_d, aes(x = Prediction , y = Reference, fill = Freq))+
geom_tile(color = "white", lwd = 0.5) +
geom_text(aes(label = paste("",Freq)), color = 'white', size = 3.5)+
theme_minimal() +
ggtitle("Matriz de Confusión")

Evaluación del modelo 2.
pred_svm_model2<- predict(svm_model2,newdata = eva[,-1])
cm <- confusionMatrix(data = pred_svm_model2, as.factor(eva$layer))
cm
Confusion Matrix and Statistics
Reference
Prediction 2 3 5 6 8 10 11 12 14 17
2 377 26 74 2 6 5 0 0 0 0
3 0 0 0 0 0 0 0 0 0 0
5 80 4 336 25 19 10 0 18 6 0
6 5 2 19 98 0 0 0 2 2 0
8 4 0 7 0 106 0 0 0 0 0
10 0 0 0 0 0 1 0 0 0 0
11 0 0 1 0 0 0 82 3 0 0
12 0 0 10 15 0 0 3 131 12 0
14 0 0 2 4 0 0 1 13 276 0
17 0 0 0 0 0 0 0 0 0 150
Overall Statistics
Accuracy : 0.8038
95% CI : (0.7854, 0.8213)
No Information Rate : 0.2406
P-Value [Acc > NIR] : < 2.2e-16
Kappa : 0.7641
Mcnemar's Test P-Value : NA
Statistics by Class:
Class: 2 Class: 3 Class: 5 Class: 6 Class: 8 Class: 10
Sensitivity 0.8090 0.00000 0.7483 0.68056 0.80916 0.0625000
Specificity 0.9232 1.00000 0.8911 0.98327 0.99391 1.0000000
Pos Pred Value 0.7694 NaN 0.6747 0.76562 0.90598 1.0000000
Neg Pred Value 0.9385 0.98348 0.9215 0.97457 0.98626 0.9922521
Prevalence 0.2406 0.01652 0.2318 0.07434 0.06763 0.0082602
Detection Rate 0.1946 0.00000 0.1735 0.05059 0.05472 0.0005163
Detection Prevalence 0.2530 0.00000 0.2571 0.06608 0.06040 0.0005163
Balanced Accuracy 0.8661 0.50000 0.8197 0.83191 0.90153 0.5312500
Class: 11 Class: 12 Class: 14 Class: 17
Sensitivity 0.95349 0.78443 0.9324 1.00000
Specificity 0.99784 0.97740 0.9878 1.00000
Pos Pred Value 0.95349 0.76608 0.9324 1.00000
Neg Pred Value 0.99784 0.97961 0.9878 1.00000
Prevalence 0.04440 0.08622 0.1528 0.07744
Detection Rate 0.04233 0.06763 0.1425 0.07744
Detection Prevalence 0.04440 0.08828 0.1528 0.07744
Balanced Accuracy 0.97566 0.88092 0.9601 1.00000
Representación de Matriz de confusión
cm_d <- as.data.frame(cm$table)
cm_st <-data.frame(cm$overall)
cm_st$cm.overall <- round(cm_st$cm.overall,2)
cm_p <- as.data.frame(prop.table(cm$table))
cm_d$Perc <- round(cm_p$Freq*100,2)
# dibujando la matriz
ggplot(data = cm_d, aes(x = Prediction , y = Reference, fill = Freq))+
geom_tile(color = "white", lwd = 0.5) +
geom_text(aes(label = paste("",Freq)), color = 'white', size = 3.5)+
theme_minimal() +
ggtitle("Matriz de Confusión")

Predicción y visualización del modelo 1.
classi_svm_model1 <- raster::predict(roma_rst_lan, model=svm_model1)
plot(classi_svm_model1, main="Clasificación SVM Modelo 1",col = cols)

Predicción y visualización del modelo 2.
classi_svm_model2 <- raster::predict(roma_rst_lan, model=svm_model2)
plot(classi_svm_model2, main="Clasificación SVM Modelo 2",col = cols)

LS0tCnRpdGxlOiAiQ2xhc2lmaWNhY2nDs24gZGUgaW3DoWdlbmVzIGNvbiBTVk0iCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCiMgTGlicmVyaWFzIGFwbGljYWRhcwoKYGBge3J9CmxpYnJhcnkoY2FyZXQpCmxpYnJhcnkocmFzdGVyKQpgYGAKCiMgQ2FyZ2EgZGUgbGFzIGJhbmRhcyBkZSBpbcOhZ2VuZXMgc2F0ZWxpdGFsZXMuCgpgYGB7cn0KYmFuZDEgPC0gcmFzdGVyKCIvVXNlcnMvZWxpYW5hYWxpemNodXF1aWxsYW5xdWlqdWxjYXBhcmkvRG9jdW1lbnRzL3dvcmtzcGFjZS1yL2RlbW9zL2NhcHR1cmFzLWxhbmRzYXQvcm9tYS9MQzgxOTEwMzEyMDEzMjA4TEdOMDAvTEM4MTkxMDMxMjAxMzIwOExHTjAwX0IxLlRJRiIpCmJhbmQyIDwtIHJhc3RlcigiL1VzZXJzL2VsaWFuYWFsaXpjaHVxdWlsbGFucXVpanVsY2FwYXJpL0RvY3VtZW50cy93b3Jrc3BhY2Utci9kZW1vcy9jYXB0dXJhcy1sYW5kc2F0L3JvbWEvTEM4MTkxMDMxMjAxMzIwOExHTjAwL0xDODE5MTAzMTIwMTMyMDhMR04wMF9CMi5USUYiKQpiYW5kMyA8LSByYXN0ZXIoIi9Vc2Vycy9lbGlhbmFhbGl6Y2h1cXVpbGxhbnF1aWp1bGNhcGFyaS9Eb2N1bWVudHMvd29ya3NwYWNlLXIvZGVtb3MvY2FwdHVyYXMtbGFuZHNhdC9yb21hL0xDODE5MTAzMTIwMTMyMDhMR04wMC9MQzgxOTEwMzEyMDEzMjA4TEdOMDBfQjMuVElGIikKYmFuZDQgPC0gcmFzdGVyKCIvVXNlcnMvZWxpYW5hYWxpemNodXF1aWxsYW5xdWlqdWxjYXBhcmkvRG9jdW1lbnRzL3dvcmtzcGFjZS1yL2RlbW9zL2NhcHR1cmFzLWxhbmRzYXQvcm9tYS9MQzgxOTEwMzEyMDEzMjA4TEdOMDAvTEM4MTkxMDMxMjAxMzIwOExHTjAwX0I0LlRJRiIpCmJhbmQ1IDwtIHJhc3RlcigiL1VzZXJzL2VsaWFuYWFsaXpjaHVxdWlsbGFucXVpanVsY2FwYXJpL0RvY3VtZW50cy93b3Jrc3BhY2Utci9kZW1vcy9jYXB0dXJhcy1sYW5kc2F0L3JvbWEvTEM4MTkxMDMxMjAxMzIwOExHTjAwL0xDODE5MTAzMTIwMTMyMDhMR04wMF9CNS5USUYiKQpiYW5kNiA8LSByYXN0ZXIoIi9Vc2Vycy9lbGlhbmFhbGl6Y2h1cXVpbGxhbnF1aWp1bGNhcGFyaS9Eb2N1bWVudHMvd29ya3NwYWNlLXIvZGVtb3MvY2FwdHVyYXMtbGFuZHNhdC9yb21hL0xDODE5MTAzMTIwMTMyMDhMR04wMC9MQzgxOTEwMzEyMDEzMjA4TEdOMDBfQjYuVElGIikKYmFuZDcgPC0gcmFzdGVyKCIvVXNlcnMvZWxpYW5hYWxpemNodXF1aWxsYW5xdWlqdWxjYXBhcmkvRG9jdW1lbnRzL3dvcmtzcGFjZS1yL2RlbW9zL2NhcHR1cmFzLWxhbmRzYXQvcm9tYS9MQzgxOTEwMzEyMDEzMjA4TEdOMDAvTEM4MTkxMDMxMjAxMzIwOExHTjAwX0I3LlRJRiIpCmJhbmQxMCA8LSByYXN0ZXIoIi9Vc2Vycy9lbGlhbmFhbGl6Y2h1cXVpbGxhbnF1aWp1bGNhcGFyaS9Eb2N1bWVudHMvd29ya3NwYWNlLXIvZGVtb3MvY2FwdHVyYXMtbGFuZHNhdC9yb21hL0xDODE5MTAzMTIwMTMyMDhMR04wMC9MQzgxOTEwMzEyMDEzMjA4TEdOMDBfQjEwLlRJRiIpCmJhbmQxMSA8LSByYXN0ZXIoIi9Vc2Vycy9lbGlhbmFhbGl6Y2h1cXVpbGxhbnF1aWp1bGNhcGFyaS9Eb2N1bWVudHMvd29ya3NwYWNlLXIvZGVtb3MvY2FwdHVyYXMtbGFuZHNhdC9yb21hL0xDODE5MTAzMTIwMTMyMDhMR04wMC9MQzgxOTEwMzEyMDEzMjA4TEdOMDBfQjExLlRJRiIpCgpyb21hX3JzdF9sYW4gPC0gYnJpY2soYmFuZDEsYmFuZDIsYmFuZDMsYmFuZDQsYmFuZDUsYmFuZDYsYmFuZDcsYmFuZDEwLGJhbmQxMSkKbmFtZXMocm9tYV9yc3RfbGFuKSA8LSBjKHBhc3RlKCJCYW5kYSIsMTo3LHNlcD0iIiksIkJhbmRhMTAiLCJCYW5kYTExIikKYGBgCgojIFByb2Nlc2FkbyBkZSBkYXRvcwoKYGBge3J9CiNDYXJnYSBkZSBtdWVzdHJhcyBkZSBlbnRyZW5hbWllbnRvCnJzdFRyYWlucm9tYSA8LSByYXN0ZXIoIi9Vc2Vycy9lbGlhbmFhbGl6Y2h1cXVpbGxhbnF1aWp1bGNhcGFyaS9Eb2N1bWVudHMvd29ya3NwYWNlLXIvZGVtb3MvRGF0YVRyYWluaW5nL3JvbWVfbGN6X0dULnRpZiIpCgojIFJlbW92ZXIgY2Vyb3MgKGZvbmRvIE5BKQpyc3RUcmFpbnJvbWFbcnN0VHJhaW5yb21hPT0wXSA8LSBOQQoKIyBDb252ZXJ0aXIgYSB0aXBvIGRpc2NyZXRvCnJzdFRyYWlucm9tYSA8LSByYXRpZnkocnN0VHJhaW5yb21hKQoKIyBDYW1iaWFtb3MgZWwgbm9tYnJlCm5hbWVzKHJzdFRyYWlucm9tYSkgPC0gImxheWVyIgoKI011ZXN0cmFzIGRlIHZhbG9yZXMKdGFibGUodmFsdWVzKHJzdFRyYWlucm9tYSkpCgojIEVsaW1pbmFjacOzbiBkZSBOQXMgCnJzdERGbGFucm9tYS5kZiA8LSBuYS5vbWl0KHZhbHVlcyhzdGFjayhyc3RUcmFpbnJvbWEsIHJvbWFfcnN0X2xhbikpKQoKY29scyA8LSBjKCIjZmRlNzI1IiwiI2I1ZGUyYiIsICIjNmVjZTU4IiwiIzM1Yjc3OSIsICIjMWY5ZTg5IiwiIzI2ODI4ZSIsICIjMzE2ODhlIiwgIiMzZTQ5ODkiLCAiIzQ4Mjg3OCIsICIjNDQwMTU0IikKcGxvdChyc3RUcmFpbnJvbWEsIG1haW49Ik11ZXN0cmFzIGRlIGVudHJlbmFtaWVudG8gZGUgUm9tYSIsIGNvbCA9IGNvbHMpCgpgYGAKCiMgRmFzZSBkZSBDbGFzaWZpY2FjacOzbgoKYGBge3J9CiNTaSBlcyBsYSBwcmltZXJhIHZleiBzZSBlamVjdXRhLCBzaW5vIHlhIGVzdGEgZ3VhcmRhZG8gbG9zIGRhdG9zIGRlbCBkYXRhZnJhbWUuCiN3cml0ZS5jc3YocnN0REZsYW5yb21hLmRmLCJyc3RERlJvbWEuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCgojTGVlbW9zIGxvcyBkYXRvcwpzYW1wbGVzTGFucm9tYSA9IHJlYWQuY3N2KCJyc3RERlJvbWEuY3N2IikKCiMgU2UgZGl2aWRlIGxhcyBtdWVzdHJhcyBlbiA3MCB5IDMwCnRyYWlueCA9IGxpc3QoMCkKZXZhbHggPSBsaXN0KDApCmZvciAoaSBpbiAxOjE3KXsgIyBzZSBpdGVyYSBlbiB0b2RhcyBsYXMgcG9zaWJsZXMgY2F0ZWdvcsOtYXMKICBjbHMgPSBzYW1wbGVzTGFucm9tYVtzYW1wbGVzTGFucm9tYSRsYXllciA9PSBpLF0KICBzbXBsIDwtIGZsb29yKDAuNzAgKiBucm93KGNscykpCiAgdHQgPC0gc2FtcGxlKHNlcV9sZW4obnJvdyhjbHMpKSwgc2l6ZSA9IHNtcGwpCiAgdHJhaW54W1tpXV0gPC0gY2xzW3R0LF0KICBldmFseFtbaV1dIDwtIGNsc1stdHQsXQp9CgoKIyBTZSBjb21iaW5hIGVuIGRhdGFmcmFtZSByZWZlcmVuY2lhZG9zIHMgZW50cmVuYW1pZW50byB5IGV2YWx1YWNpw7NuCnRybiA9IGRvLmNhbGwocmJpbmQsIHRyYWlueCkgCmV2YSA9IGRvLmNhbGwocmJpbmQsIGV2YWx4KQpgYGAKCiMgQWxnb3JpdG1vIFNWTQoKYGBge3J9CiMgRGVmaW5pZW5kbyBlbCBjb250cm9sIGRlbCBlbnRyZW5hbWllbnRvCmZpdENvbnRyb2wyIDwtIHRyYWluQ29udHJvbChtZXRob2QgPSAiY3YiLCAjIHJlcGVhdGVkIGNyb3NzLXZhbGlkYXRpb24gb2YgdGhlIHRyYWluaW5nIGRhdGEKICAgICAgICAgICAgICAgICAgIG51bWJlciA9IDEwKSAKCgojIEVudHJlbmFtaWVudG8gY29uIHN2bQpzdm1fbW9kZWwxPC0gY2FyZXQ6OnRyYWluKHggPSB0cm5bLCgyOm5jb2wodHJuKSldLCB5ID0gYXMuZmFjdG9yKHRybiRsYXllciksCiAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgPSAic3ZtUmFkaWFsIiwgbWV0cmljPSJBY2N1cmFjeSIsIAogICAgICAgICAgICAgICAgICAgICAgdHJDb250cm9sID0gZml0Q29udHJvbDIsIAogICAgICAgICAgICAgICAgICAgICAgcHJlUHJvY2VzcyA9IGMoImNlbnRlciIsICJzY2FsZSIpLAogICAgICAgICAgICAgICAgICAgICAgdHVuZUxlbmd0aCA9IDEwKQojIEVudHJlbmFtaWVudG8gbW9kZWxvIDIKc3ZtX2dyaWQgPC0gZXhwYW5kLmdyaWQoc2lnbWE9c2VxKGZyb20gPSAwLjAxLCB0byA9IDAuMTAsIGJ5ID0gMC4wMiksCiAgICAgICAgICAgICAgICAgICAgICAgIEM9c2VxKGZyb20gPSAyLCB0byA9IDEwLCBieSA9IDIpKQoKc3ZtX21vZGVsMjwtIGNhcmV0Ojp0cmFpbih4ID0gdHJuWywoMjpuY29sKHRybikpXSwgeSA9IGFzLmZhY3Rvcih0cm4kbGF5ZXIpLAogICAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gInN2bVJhZGlhbFNpZ21hIiwgbWV0cmljPSJBY2N1cmFjeSIsIAogICAgICAgICAgICAgICAgICAgICAgdHJDb250cm9sID0gZml0Q29udHJvbDIsCiAgICAgICAgICAgICAgICAgICAgICBwcmVQcm9jZXNzID0gYygiY2VudGVyIiwgInNjYWxlIiksCiAgICAgICAgICAgICAgICAgICAgICB0dW5lR3JpZCA9IHN2bV9ncmlkKQoKYGBgCgojIEV4cGxvcmFjacOzbiBkZWwgbW9kZWxvCgpgYGB7cn0KI0luZm9ybWFjacOzbiBtb2RlbG8gc3ZtCnByaW50KHN2bV9tb2RlbDEpCgpwcmludChzdm1fbW9kZWwyKSAjbW9kZWxvIDIKCiNHcsOhZmljYSBkZWwgbW9kZWxvIHN2bQpwbG90KHN2bV9tb2RlbDEpCgpwbG90KHN2bV9tb2RlbDIpICNtb2RlbG8gMgpgYGAKCgojIEV2YWx1YWNpw7NuIGRlbCBtb2RlbG8gMS4KCmBgYHtyfQpwcmVkX3N2bV9tb2RlbDE8LSBwcmVkaWN0KHN2bV9tb2RlbDEsbmV3ZGF0YSA9IGV2YVssLTFdKQoKY20gPC0gY29uZnVzaW9uTWF0cml4KGRhdGEgPSBwcmVkX3N2bV9tb2RlbDEsIGFzLmZhY3RvcihldmEkbGF5ZXIpKQpjbQpgYGAKCiMgUmVwcmVzZW50YWNpw7NuIGRlIE1hdHJpeiBkZSBjb25mdXNpw7NuCgpgYGB7cn0KY21fZCA8LSBhcy5kYXRhLmZyYW1lKGNtJHRhYmxlKQoKY21fc3QgPC1kYXRhLmZyYW1lKGNtJG92ZXJhbGwpCgpjbV9zdCRjbS5vdmVyYWxsIDwtIHJvdW5kKGNtX3N0JGNtLm92ZXJhbGwsMikKCmNtX3AgPC0gYXMuZGF0YS5mcmFtZShwcm9wLnRhYmxlKGNtJHRhYmxlKSkKY21fZCRQZXJjIDwtIHJvdW5kKGNtX3AkRnJlcSoxMDAsMikKCiMgZGlidWphbmRvIGxhIG1hdHJpegpnZ3Bsb3QoZGF0YSA9IGNtX2QsIGFlcyh4ID0gUHJlZGljdGlvbiAsIHkgPSAgUmVmZXJlbmNlLCBmaWxsID0gRnJlcSkpKwogIGdlb21fdGlsZShjb2xvciA9ICJ3aGl0ZSIsIGx3ZCA9IDAuNSkgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSBwYXN0ZSgiIixGcmVxKSksIGNvbG9yID0gJ3doaXRlJywgc2l6ZSA9IDMuNSkrIAogIHRoZW1lX21pbmltYWwoKSArCiAgZ2d0aXRsZSgiTWF0cml6IGRlIENvbmZ1c2nDs24iKQpgYGAKCiMgRXZhbHVhY2nDs24gZGVsIG1vZGVsbyAyLgoKYGBge3J9CnByZWRfc3ZtX21vZGVsMjwtIHByZWRpY3Qoc3ZtX21vZGVsMixuZXdkYXRhID0gZXZhWywtMV0pCgpjbSA8LSBjb25mdXNpb25NYXRyaXgoZGF0YSA9IHByZWRfc3ZtX21vZGVsMiwgYXMuZmFjdG9yKGV2YSRsYXllcikpCmNtCmBgYAoKIyBSZXByZXNlbnRhY2nDs24gZGUgTWF0cml6IGRlIGNvbmZ1c2nDs24KCmBgYHtyfQpjbV9kIDwtIGFzLmRhdGEuZnJhbWUoY20kdGFibGUpCgpjbV9zdCA8LWRhdGEuZnJhbWUoY20kb3ZlcmFsbCkKCmNtX3N0JGNtLm92ZXJhbGwgPC0gcm91bmQoY21fc3QkY20ub3ZlcmFsbCwyKQoKY21fcCA8LSBhcy5kYXRhLmZyYW1lKHByb3AudGFibGUoY20kdGFibGUpKQpjbV9kJFBlcmMgPC0gcm91bmQoY21fcCRGcmVxKjEwMCwyKQoKIyBkaWJ1amFuZG8gbGEgbWF0cml6CmdncGxvdChkYXRhID0gY21fZCwgYWVzKHggPSBQcmVkaWN0aW9uICwgeSA9ICBSZWZlcmVuY2UsIGZpbGwgPSBGcmVxKSkrCiAgZ2VvbV90aWxlKGNvbG9yID0gIndoaXRlIiwgbHdkID0gMC41KSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBhc3RlKCIiLEZyZXEpKSwgY29sb3IgPSAnd2hpdGUnLCBzaXplID0gMy41KSsgCiAgdGhlbWVfbWluaW1hbCgpICsKICBnZ3RpdGxlKCJNYXRyaXogZGUgQ29uZnVzacOzbiIpCmBgYAoKIyBQcmVkaWNjacOzbiB5IHZpc3VhbGl6YWNpw7NuIGRlbCBtb2RlbG8gMS4KCmBgYHtyfQpjbGFzc2lfc3ZtX21vZGVsMSA8LSByYXN0ZXI6OnByZWRpY3Qocm9tYV9yc3RfbGFuLCBtb2RlbD1zdm1fbW9kZWwxKQpwbG90KGNsYXNzaV9zdm1fbW9kZWwxLCBtYWluPSJDbGFzaWZpY2FjacOzbiBTVk0gTW9kZWxvIDEiLGNvbCA9IGNvbHMpCmBgYAoKIyBQcmVkaWNjacOzbiB5IHZpc3VhbGl6YWNpw7NuIGRlbCBtb2RlbG8gMi4KCmBgYHtyfQpjbGFzc2lfc3ZtX21vZGVsMiA8LSByYXN0ZXI6OnByZWRpY3Qocm9tYV9yc3RfbGFuLCBtb2RlbD1zdm1fbW9kZWwyKQpwbG90KGNsYXNzaV9zdm1fbW9kZWwyLCBtYWluPSJDbGFzaWZpY2FjacOzbiBTVk0gTW9kZWxvIDIiLGNvbCA9IGNvbHMpCmBgYAoKCgo=