Librerías

library(ncdf4)
library(fields)
library(maps)
library(raster)
library(sp)
library(sf)
library(animation)
library(terra)

Rutina para extraer base de datos NetCDF

Se imprime la Metadata del archivo

#Se especifica la direccion de la base de datos NetCDF
dirsemanal = "A:/CICIMAR/Bases de datos/Output file of weekly climatology simulated with the ROMS model (NetCDF standard).nc"
#se le asigna a una variable la lectura de esos datos
semanal = nc_open(dirsemanal)
#Se muestra en pantalla las variables que presenta la base de datos,
#y sus dimensiones
print(semanal) #consultando metadatos del fichero
File A:/CICIMAR/Bases de datos/Output file of weekly climatology simulated with the ROMS model (NetCDF standard).nc (NC_FORMAT_CLASSIC):

     9 variables (excluding dimension variables):
        double h[lon,lat]   
            standard_name: Bathymetry
            long_name: Bathymetry
            units: m
            missing_value: NaN
            FillValue: NaN
        double ssh[lon,lat,time]   
            standard_name: SSH
            long_name: Sea Surface Height
            units: m
            missing_value: NaN
            FillValue: NaN
        double temp[lon,lat,depth,time]   
            standard_name: temp
            long_name: Potential temperature
            units: degreeC
            missing_value: NaN
            FillValue: NaN
        double salt[lon,lat,depth,time]   
            standard_name: salt
            long_name: Salinity
            units: PSU
            missing_value: NaN
            FillValue: NaN
        double swd[lon,lat,depth,time]   
            standard_name: Density
            long_name: Seawater density
            units: Kg m^-3
            missing_value: NaN
            FillValue: NaN
        double ucurr[lon,lat,depth,time]   
            standard_name: ucurr
            long_name: Zonal component
            units: m s^-1
            missing_value: NaN
            FillValue: NaN
        double vcurr[lon,lat,depth,time]   
            standard_name: vcurr
            long_name: Meridional component
            units: m s^-1
            missing_value: NaN
            FillValue: NaN
        double vort[lon,lat,depth,time]   
            standard_name: vort
            long_name: Vorticity
            units: s^-1
            missing_value: NaN
            FillValue: NaN
        double cspd[lon,lat,depth,time]   
            standard_name: cspd
            long_name: Current speed
            units: m s^-1
            missing_value: NaN
            FillValue: NaN

     4 dimensions:
        lon  Size:183 
            standard_name: logitude
            long_name: logitude
            units: degrees_east
            axis: X
        lat  Size:159 
            standard_name: latitude
            long_name: latitude
            units: degrees_north
            axis: Y
        depth  Size:61 
            standard_name: Depth
            long_name: Vertical axis
            units: m
            axis: Z
        time  Size:48   *** is unlimited *** 
            standard_name: time
            long_name: time
            calendar: standard
            axis: T
            comment: 

    5 global attributes:
        creation_date: 05-Aug-2022 01:24:56
        Producer: DOCEAN/UFPE/Recife/PE/Brasil
        dataType: 2D Grid
        Comment: ArpHDv2 datasets (standard NetCDF files)
        Author: H. L. Varona & M. Araujo

Asignación de variables

lat_variable = 'lat'
lon_variable = 'lon'
time_variable ='time'
latssem = ncvar_get(semanal,lat_variable) 
lonssem = ncvar_get(semanal,lon_variable)
timessem = ncvar_get(semanal,time_variable)



batimetria=ncvar_get(semanal,"h")
nivelmarsem = ncvar_get(semanal,'ssh') 
tempsem = ncvar_get(semanal,'temp')
salisem = ncvar_get(semanal,"salt") 
densisem = ncvar_get(semanal,"swd") 
zonalcomsem=ncvar_get(semanal,"ucurr")
meridionalcomsem=ncvar_get(semanal,"vcurr")
vorticidadsem=ncvar_get(semanal,"vort")
velocidadsem = ncvar_get(semanal,'cspd') 

Manejo de datos raster

Se rota cada elemento semanal de salinidad correctamente y se le asigna a cada elemento de la lista vacía creada. Se le agragan las coordenadas a cada elemento de la lista

#Se le asigna a borrador para no modificar la variable de origen
borrador=salisem

# Lista vacía

# Creando una lista vacía con 48 elementos
lista_vacia <- vector("list", length = 48)




# Se rota cada elemento semanal de salinidad correctamente y se le asigna a 
# cada elemento de la lista vacía creada 
# Se le agragan las coordenadas a cada elemento de la lista 
# 
for(i in 1:48){
  #Se rota cada elemento 
 temporal <- apply(t(borrador[,,1,i]),2,rev)
 lista_vacia[[i]]=temporal 
  # Se convierte a raster cada elemento de la lista
 lista_vacia[[i]]=raster(lista_vacia[[i]])
 extent(lista_vacia[[i]]) <- extent(c(min(lonssem),max(lonssem),min(latssem),max(latssem)))
 
}

Animación de verificación de imagenes

meses=c("Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre","Diciembre")
(meses=rep(meses, each=4))
 [1] "Enero"      "Enero"      "Enero"      "Enero"      "Febrero"    "Febrero"   
 [7] "Febrero"    "Febrero"    "Marzo"      "Marzo"      "Marzo"      "Marzo"     
[13] "Abril"      "Abril"      "Abril"      "Abril"      "Mayo"       "Mayo"      
[19] "Mayo"       "Mayo"       "Junio"      "Junio"      "Junio"      "Junio"     
[25] "Julio"      "Julio"      "Julio"      "Julio"      "Agosto"     "Agosto"    
[31] "Agosto"     "Agosto"     "Septiembre" "Septiembre" "Septiembre" "Septiembre"
[37] "Octubre"    "Octubre"    "Octubre"    "Octubre"    "Noviembre"  "Noviembre" 
[43] "Noviembre"  "Noviembre"  "Diciembre"  "Diciembre"  "Diciembre"  "Diciembre" 
saveGIF({
for (i in 1:48) {

#plotea
ColorRamp = colorRampPalette(c("yellow", "#ead379", "#df7a3a","blue"))#, "red4"))
image.plot(lonssem,latssem,salisem[,,1,i],
           main = paste("Salinidad (PSU) del mes " ,meses[i], "semana ",i,"/48"), xlab = 'Longitude',ylab = 'Latitude',col = ColorRamp(20))
#añade un mapa
map(add=TRUE,fill = TRUE,col = "green",resolution = 0)

}
},movie.name = "Salinidad(PSU).gif", interval = 0.2, nmax = 2)
animation option 'nmax' changed: 50 --> 2
[1] TRUE

En el entorno de trabajo de R se obtendrá el siguiente gift

Figura 1: Secuencia de valores de salinidad (PSU) a lo largo de 48 semanas por imágen, a profundidad de 1 metro
Figura 1: Secuencia de valores de salinidad (PSU) a lo largo de 48 semanas por imágen, a profundidad de 1 metro

Tabla de reclasificación

Se crea una tabla de reclasificación que usará posteriormente para asginar a los valore de salinidad (PSU) que esten en el rango de 0 <= x <35 como 1, y a los valores que estén en 35 <=x <40 como 0.

# Tabla de reclasificación (rangos)
m <- c(1, 35, 1, 35, 40,0)
tabla_reclas <- matrix(m, ncol=3, byrow=TRUE)
print(tabla_reclas)
     [,1] [,2] [,3]
[1,]    1   35    1
[2,]   35   40    0

Binarización

Se crea una secuencia de imagenes (48), una para cada semana correspondiente a la binarizacion de acuerdo al nivel de salinidad


saveGIF({
for (i in 1:48) {
#reclasificación  
reclas <- reclassify(lista_vacia[[i]], tabla_reclas)
#plotea
plot(reclas, ylim=c(min(latssem),max(latssem)), main=paste("Pluma binarizada (<35 psu) \n en el mes" ,meses[i]," semana ",i,"/48"))
#añade un mapa
map(add=TRUE,fill = TRUE,col = "green",resolution = 0)

}
},movie.name = "PlumaGIF1.gif", interval = 0.2, nmax = 2)
animation option 'nmax' changed: 50 --> 2
[1] TRUE

En el entorno de trabajo de R se obtendrá el siguiente gift

Figura 2: Secuencia de imagenes raster binarizadas según el proceso de reclasificación
Figura 2: Secuencia de imagenes raster binarizadas según el proceso de reclasificación

Superposición de imágenes binarizadas

#Área de influencia de la pluma delimitada
#Binarizacion de cada imagen y superposicion lógica de cada imagen en una sola
#######################
inicial <- reclassify(lista_vacia[[1]], tabla_reclas)

superpo=inicial
for (i in 2:48) {
  
  
  #reclasificación  
  temp <- reclassify(lista_vacia[[i]], tabla_reclas)
  #plotea
  superpo <- overlay(superpo,temp, fun = function(x,y)
  {ifelse( x == 1 | y == 1, 1, 0)})
  
}

plot(superpo,axes=T)
title(main ="Superposición de valores binarizados",font.main=2, adj=0.5, cex.main=1)
map(add=TRUE,fill = TRUE,col = "green",resolution = 0)

Figura 3: Superposición de todos las imagenes binarizadas de la pluma ## Vectorización

#Se convierte a formato raster del paquete terra con la funcion rast,
#El producto de la superposicion para que pueda ser vectorizado con una funcion del mismo paquete


torast=rast(superpo)

#Se vectoriza
supervect = as.polygons(torast)|> 
  st_as_sf()

#Se proyecta la imagen vectorizada
# plot(supervect,axes=T,add=T)
# map(add=TRUE,fill = TRUE,col = "green",resolution = 0)

plot(supervect[2,],axes=T,main="")
title(main ="Vectorización de la Imagen 3",font.main=2, adj=0.5, cex.main=1)

Figura 4: Vector de resultante de la vectorización de la imagen de la figura 3.

Referencias

Echevarría-Rubio, J. M. (2022). Detección y monitoreo de sargazo en el Mar Caribe. Tesis de Maestía en Ciencias en Manejo de Recursos Marinos, CICIMAR-IPN.

Hu, C., Montgomery, E., Schmitt, R., & Mullerkarger, F. (2004). The dispersal of the Amazon and Orinoco River water in the tropical Atlantic and Caribbean Sea: Observation from space and S-PALACE floats. Deep Sea Research Part II: Topical Studies in Oceanography, 51(10–11), 1151–1171. https://doi.org/10.1016/S0967-0645(04)00105-5

Park, E., & Latrubesse, E. M. (2014). Modeling suspended sediment distribution patterns of the Amazon River using MODIS data. Remote Sensing of Environment, 147, 232-242. https://doi.org/10.1016/j.rse.2014.03.013

Varona, H. L., & Araujo, M. (2022). Hydro-thermodynamic dataset of the Amazon River Plume and North Brazil Current retroflection. Data in Brief, 40. https://doi.org/10.17882/82958

Varona, H. L., Veleda, D., Silva, M., Cintra, M., & Araujo, M. (2019). Amazon River plume influence on Western Tropical Atlantic dynamic variability. Dynamics of Atmospheres and Oceans, 85, 1-15. https://doi.org/10.1016/j.dynatmoce.2018.10.002

LS0tDQp0aXRsZTogIkF2YW5jZXMgUmVsYWNpb25hZG9zIGNvbiBHSVMgcGFyYSBlc3R1ZGlvIGRlIFBsdW1hIGRlbCBSw61vIEFtYXpvbmFzIg0KYXV0aG9yOiAiUmFtw7NuIERhdmlkIFDDqXJleiBMYW55YXUiDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCBkZSAlQiBkZSAlWScpYCINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KICBodG1sX2RvY3VtZW50Og0KICAgIGRmX3ByaW50OiBwYWdlZA0Kc3VidGl0bGU6IE1hbmVqbyBjb24gZGF0b3MgUmFzdGVyIHkgTmV0Q0RGDQotLS0NCg0KDQojIyMgTGlicmVyw61hcw0KYGBge3IgUGFxdWV0ZXMsIG1lc3NhZ2U9VFJVRSwgaW5jbHVkZT1UUlVFfQ0KbGlicmFyeShuY2RmNCkNCmxpYnJhcnkoZmllbGRzKQ0KbGlicmFyeShtYXBzKQ0KbGlicmFyeShyYXN0ZXIpDQpsaWJyYXJ5KHNwKQ0KbGlicmFyeShzZikNCmxpYnJhcnkoYW5pbWF0aW9uKQ0KbGlicmFyeSh0ZXJyYSkNCmBgYA0KDQojIyBSdXRpbmEgcGFyYSBleHRyYWVyIGJhc2UgZGUgZGF0b3MgTmV0Q0RGDQoNClNlIGltcHJpbWUgbGEgTWV0YWRhdGEgZGVsIGFyY2hpdm8NCmBgYHtyfQ0KI1NlIGVzcGVjaWZpY2EgbGEgZGlyZWNjaW9uIGRlIGxhIGJhc2UgZGUgZGF0b3MgTmV0Q0RGDQpkaXJzZW1hbmFsID0gIkE6L0NJQ0lNQVIvQmFzZXMgZGUgZGF0b3MvT3V0cHV0IGZpbGUgb2Ygd2Vla2x5IGNsaW1hdG9sb2d5IHNpbXVsYXRlZCB3aXRoIHRoZSBST01TIG1vZGVsIChOZXRDREYgc3RhbmRhcmQpLm5jIg0KI3NlIGxlIGFzaWduYSBhIHVuYSB2YXJpYWJsZSBsYSBsZWN0dXJhIGRlIGVzb3MgZGF0b3MNCnNlbWFuYWwgPSBuY19vcGVuKGRpcnNlbWFuYWwpDQojU2UgbXVlc3RyYSBlbiBwYW50YWxsYSBsYXMgdmFyaWFibGVzIHF1ZSBwcmVzZW50YSBsYSBiYXNlIGRlIGRhdG9zLA0KI3kgc3VzIGRpbWVuc2lvbmVzDQpwcmludChzZW1hbmFsKSAjY29uc3VsdGFuZG8gbWV0YWRhdG9zIGRlbCBmaWNoZXJvDQpgYGANCg0KIyMgQXNpZ25hY2nDs24gZGUgdmFyaWFibGVzDQpgYGB7ciBBZ2luYWNpw7NuIGRlIHZhcmlhYmxlc30NCmxhdF92YXJpYWJsZSA9ICdsYXQnDQpsb25fdmFyaWFibGUgPSAnbG9uJw0KdGltZV92YXJpYWJsZSA9J3RpbWUnDQpsYXRzc2VtID0gbmN2YXJfZ2V0KHNlbWFuYWwsbGF0X3ZhcmlhYmxlKSANCmxvbnNzZW0gPSBuY3Zhcl9nZXQoc2VtYW5hbCxsb25fdmFyaWFibGUpDQp0aW1lc3NlbSA9IG5jdmFyX2dldChzZW1hbmFsLHRpbWVfdmFyaWFibGUpDQoNCg0KDQpiYXRpbWV0cmlhPW5jdmFyX2dldChzZW1hbmFsLCJoIikNCm5pdmVsbWFyc2VtID0gbmN2YXJfZ2V0KHNlbWFuYWwsJ3NzaCcpIA0KdGVtcHNlbSA9IG5jdmFyX2dldChzZW1hbmFsLCd0ZW1wJykNCnNhbGlzZW0gPSBuY3Zhcl9nZXQoc2VtYW5hbCwic2FsdCIpIA0KZGVuc2lzZW0gPSBuY3Zhcl9nZXQoc2VtYW5hbCwic3dkIikgDQp6b25hbGNvbXNlbT1uY3Zhcl9nZXQoc2VtYW5hbCwidWN1cnIiKQ0KbWVyaWRpb25hbGNvbXNlbT1uY3Zhcl9nZXQoc2VtYW5hbCwidmN1cnIiKQ0Kdm9ydGljaWRhZHNlbT1uY3Zhcl9nZXQoc2VtYW5hbCwidm9ydCIpDQp2ZWxvY2lkYWRzZW0gPSBuY3Zhcl9nZXQoc2VtYW5hbCwnY3NwZCcpIA0KYGBgDQoNCiMjIE1hbmVqbyBkZSBkYXRvcyByYXN0ZXIgDQpTZSByb3RhIGNhZGEgZWxlbWVudG8gc2VtYW5hbCBkZSBzYWxpbmlkYWQgY29ycmVjdGFtZW50ZSB5IHNlIGxlIGFzaWduYSBhICBjYWRhIGVsZW1lbnRvIGRlIGxhIGxpc3RhIHZhY8OtYSBjcmVhZGEuIFNlIGxlIGFncmFnYW4gbGFzIGNvb3JkZW5hZGFzIGEgY2FkYSBlbGVtZW50byBkZSBsYSBsaXN0YSANCmBgYHtyIHJvdGFjacOzbn0NCiNTZSBsZSBhc2lnbmEgYSBib3JyYWRvciBwYXJhIG5vIG1vZGlmaWNhciBsYSB2YXJpYWJsZSBkZSBvcmlnZW4NCmJvcnJhZG9yPXNhbGlzZW0NCg0KIyBMaXN0YSB2YWPDrWENCg0KIyBDcmVhbmRvIHVuYSBsaXN0YSB2YWPDrWEgY29uIDQ4IGVsZW1lbnRvcw0KbGlzdGFfdmFjaWEgPC0gdmVjdG9yKCJsaXN0IiwgbGVuZ3RoID0gNDgpDQoNCg0KDQoNCiMgU2Ugcm90YSBjYWRhIGVsZW1lbnRvIHNlbWFuYWwgZGUgc2FsaW5pZGFkIGNvcnJlY3RhbWVudGUgeSBzZSBsZSBhc2lnbmEgYSANCiMgY2FkYSBlbGVtZW50byBkZSBsYSBsaXN0YSB2YWPDrWEgY3JlYWRhIA0KIyBTZSBsZSBhZ3JhZ2FuIGxhcyBjb29yZGVuYWRhcyBhIGNhZGEgZWxlbWVudG8gZGUgbGEgbGlzdGEgDQojIA0KZm9yKGkgaW4gMTo0OCl7DQogICNTZSByb3RhIGNhZGEgZWxlbWVudG8gDQogdGVtcG9yYWwgPC0gYXBwbHkodChib3JyYWRvclssLDEsaV0pLDIscmV2KQ0KIGxpc3RhX3ZhY2lhW1tpXV09dGVtcG9yYWwgDQogICMgU2UgY29udmllcnRlIGEgcmFzdGVyIGNhZGEgZWxlbWVudG8gZGUgbGEgbGlzdGENCiBsaXN0YV92YWNpYVtbaV1dPXJhc3RlcihsaXN0YV92YWNpYVtbaV1dKQ0KIGV4dGVudChsaXN0YV92YWNpYVtbaV1dKSA8LSBleHRlbnQoYyhtaW4obG9uc3NlbSksbWF4KGxvbnNzZW0pLG1pbihsYXRzc2VtKSxtYXgobGF0c3NlbSkpKQ0KIA0KfQ0KDQpgYGANCg0KIyMgQW5pbWFjacOzbiBkZSB2ZXJpZmljYWNpw7NuIGRlIGltYWdlbmVzDQpgYGB7ciB2ZXJpZmljYWNpw7NufQ0KbWVzZXM9YygiRW5lcm8iLCJGZWJyZXJvIiwiTWFyem8iLCJBYnJpbCIsIk1heW8iLCJKdW5pbyIsIkp1bGlvIiwiQWdvc3RvIiwiU2VwdGllbWJyZSIsIk9jdHVicmUiLCJOb3ZpZW1icmUiLCJEaWNpZW1icmUiKQ0KKG1lc2VzPXJlcChtZXNlcywgZWFjaD00KSkNCg0Kc2F2ZUdJRih7DQpmb3IgKGkgaW4gMTo0OCkgew0KDQojcGxvdGVhDQpDb2xvclJhbXAgPSBjb2xvclJhbXBQYWxldHRlKGMoInllbGxvdyIsICIjZWFkMzc5IiwgIiNkZjdhM2EiLCJibHVlIikpIywgInJlZDQiKSkNCmltYWdlLnBsb3QobG9uc3NlbSxsYXRzc2VtLHNhbGlzZW1bLCwxLGldLA0KICAgICAgICAgICBtYWluID0gcGFzdGUoIlNhbGluaWRhZCAoUFNVKSBkZWwgbWVzICIgLG1lc2VzW2ldLCAic2VtYW5hICIsaSwiLzQ4IiksIHhsYWIgPSAnTG9uZ2l0dWRlJyx5bGFiID0gJ0xhdGl0dWRlJyxjb2wgPSBDb2xvclJhbXAoMjApKQ0KI2HDsWFkZSB1biBtYXBhDQptYXAoYWRkPVRSVUUsZmlsbCA9IFRSVUUsY29sID0gImdyZWVuIixyZXNvbHV0aW9uID0gMCkNCg0KfQ0KfSxtb3ZpZS5uYW1lID0gIlNhbGluaWRhZChQU1UpLmdpZiIsIGludGVydmFsID0gMC4yLCBubWF4ID0gMikNCmBgYA0KRW4gZWwgZW50b3JubyBkZSB0cmFiYWpvIGRlIFIgc2Ugb2J0ZW5kcsOhIGVsIHNpZ3VpZW50ZSBnaWZ0DQoNCiFbKipGaWd1cmEgMSoqOiBTZWN1ZW5jaWEgZGUgdmFsb3JlcyBkZSBzYWxpbmlkYWQgKFBTVSkgYSBsbyBsYXJnbyBkZSA0OCBzZW1hbmFzIHBvciBpbcOhZ2VuLCBhIHByb2Z1bmRpZGFkIGRlIDEgbWV0cm8gXShTYWxpbmlkYWQoUFNVKS5naWYpDQoNCg0KDQojIyBUYWJsYSBkZSByZWNsYXNpZmljYWNpw7NuIA0KDQpTZSBjcmVhIHVuYSB0YWJsYSBkZSByZWNsYXNpZmljYWNpw7NuIHF1ZSB1c2Fyw6EgcG9zdGVyaW9ybWVudGUgcGFyYSBhc2dpbmFyIGEgbG9zIHZhbG9yZSBkZSBzYWxpbmlkYWQgKFBTVSkgcXVlIGVzdGVuIGVuIGVsIHJhbmdvIGRlIDAgPD0geCA8MzUgY29tbyAxLCB5IGEgbG9zIHZhbG9yZXMgcXVlIGVzdMOpbiBlbiAzNSA8PXggPDQwIGNvbW8gMC4gIA0KDQpgYGB7ciBUYWJsYSBkZSByZWNsYXNpZmljYWNpw7NufQ0KIyBUYWJsYSBkZSByZWNsYXNpZmljYWNpw7NuIChyYW5nb3MpDQptIDwtIGMoMSwgMzUsIDEsIDM1LCA0MCwwKQ0KdGFibGFfcmVjbGFzIDwtIG1hdHJpeChtLCBuY29sPTMsIGJ5cm93PVRSVUUpDQpwcmludCh0YWJsYV9yZWNsYXMpDQpgYGANCg0KDQoNCiMjIEJpbmFyaXphY2nDs24NClNlIGNyZWEgdW5hIHNlY3VlbmNpYSBkZSBpbWFnZW5lcyAoNDgpLCB1bmEgcGFyYSBjYWRhIHNlbWFuYSBjb3JyZXNwb25kaWVudGUgYSBsYSBiaW5hcml6YWNpb24gZGUgYWN1ZXJkbyBhbCBuaXZlbCBkZSBzYWxpbmlkYWQNCg0KYGBge3IgYmluYXJpemFjacOzbn0NCg0Kc2F2ZUdJRih7DQpmb3IgKGkgaW4gMTo0OCkgew0KI3JlY2xhc2lmaWNhY2nDs24gIA0KcmVjbGFzIDwtIHJlY2xhc3NpZnkobGlzdGFfdmFjaWFbW2ldXSwgdGFibGFfcmVjbGFzKQ0KI3Bsb3RlYQ0KcGxvdChyZWNsYXMsIHlsaW09YyhtaW4obGF0c3NlbSksbWF4KGxhdHNzZW0pKSwgbWFpbj1wYXN0ZSgiUGx1bWEgYmluYXJpemFkYSAoPDM1IHBzdSkgXG4gZW4gZWwgbWVzIiAsbWVzZXNbaV0sIiBzZW1hbmEgIixpLCIvNDgiKSkNCiNhw7FhZGUgdW4gbWFwYQ0KbWFwKGFkZD1UUlVFLGZpbGwgPSBUUlVFLGNvbCA9ICJncmVlbiIscmVzb2x1dGlvbiA9IDApDQoNCn0NCn0sbW92aWUubmFtZSA9ICJQbHVtYUdJRjEuZ2lmIiwgaW50ZXJ2YWwgPSAwLjIsIG5tYXggPSAyKQ0KDQpgYGANCkVuIGVsIGVudG9ybm8gZGUgdHJhYmFqbyBkZSBSIHNlIG9idGVuZHLDoSBlbCBzaWd1aWVudGUgZ2lmdA0KDQoNCiFbKipGaWd1cmEgMioqOiBTZWN1ZW5jaWEgZGUgaW1hZ2VuZXMgcmFzdGVyIGJpbmFyaXphZGFzIHNlZ8O6biBlbCBwcm9jZXNvIGRlIHJlY2xhc2lmaWNhY2nDs24gXShQbHVtYUdJRjEuZ2lmKQ0KDQojIyBTdXBlcnBvc2ljacOzbiBkZSBpbcOhZ2VuZXMgYmluYXJpemFkYXMNCg0KYGBge3IgU3VwZXJwb3NpY2nDs24gZGUgaW3DoWdlbmVzIGJpbmFyaXphZGFzfQ0KI8OBcmVhIGRlIGluZmx1ZW5jaWEgZGUgbGEgcGx1bWEgZGVsaW1pdGFkYQ0KI0JpbmFyaXphY2lvbiBkZSBjYWRhIGltYWdlbiB5IHN1cGVycG9zaWNpb24gbMOzZ2ljYSBkZSBjYWRhIGltYWdlbiBlbiB1bmEgc29sYQ0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCmluaWNpYWwgPC0gcmVjbGFzc2lmeShsaXN0YV92YWNpYVtbMV1dLCB0YWJsYV9yZWNsYXMpDQoNCnN1cGVycG89aW5pY2lhbA0KZm9yIChpIGluIDI6NDgpIHsNCiAgDQogIA0KICAjcmVjbGFzaWZpY2FjacOzbiAgDQogIHRlbXAgPC0gcmVjbGFzc2lmeShsaXN0YV92YWNpYVtbaV1dLCB0YWJsYV9yZWNsYXMpDQogICNwbG90ZWENCiAgc3VwZXJwbyA8LSBvdmVybGF5KHN1cGVycG8sdGVtcCwgZnVuID0gZnVuY3Rpb24oeCx5KQ0KICB7aWZlbHNlKCB4ID09IDEgfCB5ID09IDEsIDEsIDApfSkNCiAgDQp9DQoNCnBsb3Qoc3VwZXJwbyxheGVzPVQpDQp0aXRsZShtYWluID0iU3VwZXJwb3NpY2nDs24gZGUgdmFsb3JlcyBiaW5hcml6YWRvcyIsZm9udC5tYWluPTIsIGFkaj0wLjUsIGNleC5tYWluPTEpDQptYXAoYWRkPVRSVUUsZmlsbCA9IFRSVUUsY29sID0gImdyZWVuIixyZXNvbHV0aW9uID0gMCkNCmBgYA0KKipGaWd1cmEgMyoqOiBTdXBlcnBvc2ljacOzbiBkZSB0b2RvcyBsYXMgaW1hZ2VuZXMgYmluYXJpemFkYXMgZGUgbGEgcGx1bWENCiMjIFZlY3Rvcml6YWNpw7NuDQoNCmBgYHtyfQ0KI1NlIGNvbnZpZXJ0ZSBhIGZvcm1hdG8gcmFzdGVyIGRlbCBwYXF1ZXRlIHRlcnJhIGNvbiBsYSBmdW5jaW9uIHJhc3QsDQojRWwgcHJvZHVjdG8gZGUgbGEgc3VwZXJwb3NpY2lvbiBwYXJhIHF1ZSBwdWVkYSBzZXIgdmVjdG9yaXphZG8gY29uIHVuYSBmdW5jaW9uIGRlbCBtaXNtbyBwYXF1ZXRlDQoNCg0KdG9yYXN0PXJhc3Qoc3VwZXJwbykNCg0KI1NlIHZlY3Rvcml6YQ0Kc3VwZXJ2ZWN0ID0gYXMucG9seWdvbnModG9yYXN0KXw+IA0KICBzdF9hc19zZigpDQoNCiNTZSBwcm95ZWN0YSBsYSBpbWFnZW4gdmVjdG9yaXphZGENCiMgcGxvdChzdXBlcnZlY3QsYXhlcz1ULGFkZD1UKQ0KIyBtYXAoYWRkPVRSVUUsZmlsbCA9IFRSVUUsY29sID0gImdyZWVuIixyZXNvbHV0aW9uID0gMCkNCg0KcGxvdChzdXBlcnZlY3RbMixdLGF4ZXM9VCxtYWluPSIiKQ0KdGl0bGUobWFpbiA9IlZlY3Rvcml6YWNpw7NuIGRlIGxhIEltYWdlbiAzIixmb250Lm1haW49MiwgYWRqPTAuNSwgY2V4Lm1haW49MSkNCg0KYGBgDQoqKkZpZ3VyYSA0Kio6IFZlY3RvciBkZSByZXN1bHRhbnRlIGRlIGxhIHZlY3Rvcml6YWNpw7NuIGRlIGxhIGltYWdlbiBkZSBsYSBmaWd1cmEgMy4NCg0KIyMjIFJlZmVyZW5jaWFzIA0KDQpFY2hldmFycsOtYS1SdWJpbywgSi4gTS4gKDIwMjIpLiBEZXRlY2Npw7NuIHkgbW9uaXRvcmVvIGRlIHNhcmdhem8gZW4gZWwgTWFyIENhcmliZS4gVGVzaXMgZGUgTWFlc3TDrWEgZW4gDQpDaWVuY2lhcyBlbiBNYW5lam8gZGUgUmVjdXJzb3MgTWFyaW5vcywgQ0lDSU1BUi1JUE4uDQoNCkh1LCBDLiwgTW9udGdvbWVyeSwgRS4sIFNjaG1pdHQsIFIuLCAmIE11bGxlcmthcmdlciwgRi4gKDIwMDQpLiBUaGUgZGlzcGVyc2FsIG9mIHRoZSBBbWF6b24gYW5kIE9yaW5vY28gUml2ZXIgDQp3YXRlciBpbiB0aGUgdHJvcGljYWwgQXRsYW50aWMgYW5kIENhcmliYmVhbiBTZWE6IE9ic2VydmF0aW9uIGZyb20gc3BhY2UgYW5kIFMtUEFMQUNFIGZsb2F0cy4gRGVlcCBTZWEgDQpSZXNlYXJjaCBQYXJ0IElJOiBUb3BpY2FsIFN0dWRpZXMgaW4gT2NlYW5vZ3JhcGh5LCA1MSgxMOKAkzExKSwgMTE1MeKAkzExNzEuIGh0dHBzOi8vZG9pLm9yZy8xMC4xMDE2L1MwOTY3LTA2NDUoMDQpMDAxMDUtNQ0KDQpQYXJrLCBFLiwgJiBMYXRydWJlc3NlLCBFLiBNLiAoMjAxNCkuIE1vZGVsaW5nIHN1c3BlbmRlZCBzZWRpbWVudCBkaXN0cmlidXRpb24gcGF0dGVybnMgb2YgdGhlIEFtYXpvbiBSaXZlciB1c2luZyBNT0RJUyBkYXRhLiBSZW1vdGUgU2Vuc2luZyBvZiBFbnZpcm9ubWVudCwgMTQ3LCAyMzItMjQyLiBodHRwczovL2RvaS5vcmcvMTAuMTAxNi9qLnJzZS4yMDE0LjAzLjAxMw0KDQpWYXJvbmEsIEguIEwuLCAmIEFyYXVqbywgTS4gKDIwMjIpLiBIeWRyby10aGVybW9keW5hbWljIGRhdGFzZXQgb2YgdGhlIEFtYXpvbiBSaXZlciBQbHVtZSBhbmQgTm9ydGggQnJhemlsIEN1cnJlbnQgcmV0cm9mbGVjdGlvbi4gRGF0YSBpbiBCcmllZiwgNDAuIGh0dHBzOi8vZG9pLm9yZy8xMC4xNzg4Mi84Mjk1OA0KDQpWYXJvbmEsIEguIEwuLCBWZWxlZGEsIEQuLCBTaWx2YSwgTS4sIENpbnRyYSwgTS4sICYgQXJhdWpvLCBNLiAoMjAxOSkuIEFtYXpvbiBSaXZlciBwbHVtZSBpbmZsdWVuY2Ugb24gV2VzdGVybiBUcm9waWNhbCBBdGxhbnRpYyBkeW5hbWljIHZhcmlhYmlsaXR5LiBEeW5hbWljcyBvZiBBdG1vc3BoZXJlcyBhbmQgT2NlYW5zLCA4NSwgMS0xNS4gaHR0cHM6Ly9kb2kub3JnLzEwLjEwMTYvai5keW5hdG1vY2UuMjAxOC4xMC4wMDINCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg==