La idea de este pequeño tutorial es hacer unos gráficos dentro junto a un mapa donde nos muestren que es lo que pasa dentro de las imágenes satelitáles u otro tipo de imágenes que se encuentran dentro de GEE. Para empezar hacer anáslisis o mostrar diversos comportamientos dentro de las ciencias la forma más común para mostrar las relaciones entre datos es presentarlos a través de gráficas. Entonces es de nuestro interes poder mostrar resultados o la relación entre datos para mejorar lo que se muestra dentro de un mapa.
Que es lo que vamos a hacer dentro de estye pequeño tutorial :
- Hacer un mapa que muestre los datos de sentinel 2 en todo el estado de Yucatan México.
- Hacer una selección de un municipio dentro de Yucatan.
- Cuando se selecciona el municipio en el mapa se mostrará el promedio de las imagenes de las bandas 11 y 12 de Sentinel 2 en un intervalo especifico del tiempo.
- Mostrar como se estan comportando las bandas 11 y 12 tomando el promedio diario en un intervalo especifico de tiempo.
Sentinel 2 en Yucatan
Para tal motivo vamos a utilizar las colecciones de imágenes armonizádas de Sentinel 2. A este conjunto de imágenes vamos a seleccionar
El conjunto de imágenes se filtra primero por fecha (de 2020-01-01 a 2020-12-31), y haciendo uso de la metadata original nos quedamos unicamente con aquellas imágenes que tienen menos del \(10\%\) de pixeles con nubes. Y nos quedamos únicamente con las bandas de mediciones (‘B1’,‘B2’,‘B3’,‘B4’,‘B5’,‘B6’,‘B7’,‘B8’,‘B8A’,‘B9’, ‘B11’,‘B12’)
El siguiente script muestra la selección del conjunto de imágenes.
var s2a_cloudfree = ee.ImageCollection(
'COPERNICUS/S2_SR_HARMONIZED')
.filterDate('2020-01-01', '2020-12-31')
.filter(
.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 10)
ee
).select(
'B1','B2','B3','B4','B5','B6','B7','B8','B8A','B9', 'B11','B12'
; )
Para mostrar el conjunto de imágenes en un mapa podemos añadimos la colección al mapa usando Map.addLayer
, como son muchas bandas es complicado ver todas por tal motivo vamos a seleccionar las bandas B4, B8, B3 para hacer su vizualización como si fuera una imagen RGB. Esto lo entiende por defecto GEE sólo cuando haecmos uso de tres bandas.
Para la vizualización es necesario pasar los páramentros de la visualización a la fuinción Map.addLayer
de la siguiente forma.
var visParams = {'min': 400,'max': [4000,3000,3000], 'bands':'B8,B4,B3'};
Aquí se muestra que los valores mínimos a vizualizar son 400 y los máximos van a depender de cada banda. Para la banda 8 (B8) el máximo es 4000, 3000 para la banda 4 (B4) y 3000 para la banda 3 (B3).
Para mostrar las imagenes el código quedaria como
Map.addLayer(s2a_cloudfree, visParams ,'Sentinel2 B8 B4 B3');
Si corremos nuestro código lo que nos mostrará es una visualización a nivel global pues no se ha selecciónado la region que nos interesa. con la intención de seleccionar nuestra región vamos hacer uso de base de datos Global Administrative Unit Layers la cual contiene los distintos niveles de administración de los distintos paises. La base de datos es recopilada por la organizacción de las Naciones Unidas para la alimentación y la Agricultura. (Food and Agriculture Organization (FAO)).
= ee.FeatureCollection('FAO/GAUL/2015/level1')
dataset_2 .filter(ee.Filter.eq('ADM0_NAME', 'Mexico'))
.filter(ee.Filter.eq('ADM1_NAME', 'Yucatan'));
Primero deseamos mostrar como son las imágenes sobre Yucatan, seleccionamos a todos los estados en Mexico y despues a Yucatan. Cabe observar que lo que seguimos teniendo es una collección de “Features” (ee.FeatureCollection
) de un sólo elemento. Por tal motivo si lo queremos añadir de forma directa esto nos generara un error.
Para añadirlo al mapa lo que nos interesa en esta ocasión es el polígono de Yucatan, es decir, la geometría del elemento que se encuentra dentro de nuestra collección de “Features”. Para seleccionar dicho elemento hacemos uso de .first()
el cual toma al primer elemento de la colección y a dicho elemento tomamos la geometría con .geometry()
. Para desplegarlo dentro del mapa utilizamos un color rojizo intenso.
Map.addLayer(dataset_2.first().geometry(), {color: 'FF1500'}, 'Yucatan');
Como queremos mostrar lo que hemos hecho hasta ahorita centramos el mapa sobre la geometría de Yucatan usando Map.CenterObject
.
Map.centerObject(dataset_2.first().geometry(), 7);
Al correr el código nos debe de mostrar un mapa como el que se muestra en la imagen Figure 1

Municipio y bandas
El segundo paso de nuestra lista es hacer la selección de un municipio dentro del estado de Yucatan y poder obtener el valor promedio de las bandas 11 y 12 para ese municipio de forma diaria. Con esos datos hacer una serie de tiempo y mostrarla dentro de un gráfico. De lo anterior es necesario saber los municipios en Yucatan y poderlos desplegar dentro de un boton de selección junto al mapa. La lista de los municipios la podemos obtener usando el conjunto de datos de la FAO en su nivel 2.
var dataset_3 = ee.FeatureCollection('FAO/GAUL/2015/level2')
.filter(ee.Filter.eq('ADM0_NAME', 'Mexico'))
.filter(ee.Filter.eq('ADM1_NAME', 'Yucatan'));
El boton generado con ui.Select
necesita una lista con los elemento que se pueden seleccionar para obtener esta lista de la collección de “Features” la agregamos con el método .aggregate_array
y lo almacenamos dentro de una variable. Tambien vamos a generar un panel en donde poner el boton de selección.
var key_mun = dataset_3.aggregate_array('ADM2_NAME');
var panel_select = ui.Panel({
layout: ui.Panel.Layout.flow('vertical'),
style: {width: '500px'}
.add(ui.Label('Seleccione Municipio')); })
En la variable key_mun
se encuentra la lista con todos los municipios del estado de Yucatan, el cual vamos a utilizar para crear el boton para hacer la selección de los municipios. Es necesario construir la función que se ejecuta cuando se hace la selección, dentro de la función es necesario restringir la imágenes al municipio seleccionado obtener el promedielephanto del periodo y restringir las imágenes sólo a la geometría seleccionada. Todo lo anterior depende de la geometría del municipio. Es necesario obtener la geometría, la cual se obtiene haciendo uso del conjunto de municipios filtrados anteriormente donde sólo se encuentran los municipios de Yucatan.
La función va a recibir un parámetro key
que es el string que identifica al municipio, a partir de este se tienen que hacer todos los procedimientos detallados en el párrafo anterior.
var elemet_selected= dataset_3.filter(ee.Filter.eq('ADM2_NAME', key));
El código anterior hace la selección del “Feature” que contiene la geometría del municipio. La cual vamos a añadir en una capa haciendo uso de ui.Map.Layer
, pero como ya tenemos muchas cosas dentro del mapa es necesario eliminar lo que tenemos actualmente en el mapa haciendo uso de Map.layers().reset()
y despues podemos añadir la capa que contiene a la geometría del municipio con un color gris. Como la selección del municipio puede cambiar, vamos a fijar que la capa que contiene al municipio se mantenga en un nivel específico fijando dicha capa. Como nos interesa nuestro municipio seleccionado vamos a centrar el mapa con el método .centerObject()
.
var lay_muni = ui.Map.Layer(elemet_selected,{color:'gray', opacity:0.3}, 'Municipio');
Map.layers().reset();
Map.layers().set(0, lay_muni);
Map.centerObject(elemet_selected.geometry(), 10);
Si se añade una función con los elementos descritos y se añade al boton selector que la hacer una selección con esdte entonces tendremos un mapa con un boton selector como se muestra en la siguiente imagen (Figure 2)

Pero como queremos hacer más cosas vamos a continuar añadiendo funcionalidades, a la función que se activa cuando se selecciona un municipio. Nos falta obtener la imagen del promedio en el intervalo de tiempo para las bandas 11 y 12 para el municipio seleccionado. Adicionalmente esta imagen nos servirá para hacer la gráfica de serie de tiempo.
Vamos a filtrar el conjunto de imágenes obteniendo únicamante las imagenes que estan en “contacto” con la geometría del municipio seleccionado y solo las bandas 11 y 12, esto ya es una colección de imagenes que se pueden visualizar pero al estar dentro de una misma area las imagenes se sobrepondrian una sobre otra, por tal motivo para poder desplegarlas tomamos el promedio de toda la colección de imágenes con el método .mean()
y las restingimos a la geometría del municipio con el método .clip()
.
var select_collection = s2a_cloudfree
.filterBounds(elemet_selected)
.select( ['B11', 'B12']);
Para añadir los promedios vamos hace uso de palletas de colores ya pre-hechas las cual se pueden obtener usando el paquete users/gena/packages:palettes
. Este paquete tiene distintas paletas de colores las cuales vamos a utilizar para la vizualización de las bandas 11 y 12, para la banda 11 se utiliza la colorbrewer.YlOrRd
y para la banda 12 kovesi.linear_blue_5_95_c73
. Para ver la paletas disponible estas se encuentran en el siguiente link.
var palettes = require('users/gena/packages:palettes');
var palettes = require('users/gena/packages:palettes');
var palette_b11 = palettes.colorbrewer.YlOrRd[7];
var palette_b12 = palettes.kovesi.linear_blue_5_95_c73[7];
Ya con las imágenes seleccionadas podemos mostrar en el mapa las bandas en el municipio seleccionado con el siguiente código.
= ui.Map.Layer(
lay_filtered_11 .mean().select('B11').clip(elemet_selected),
select_collectionmin:1000,
{max:3000,
palette: palette_b11,
opacity:0.4},
'En Municipio B11');
= ui.Map.Layer(
lay_filtered_12 .select('B12').mean().clip(elemet_selected),
select_collectionmin:1000,
{max:2600,
palette: palette_b12,
opacity:0.4},
'En Municipio B12');
Map.layers().set(1, lay_filtered_11);
Map.layers().set(2, lay_filtered_12);
De igual forma que al añadir la geometría del municipio, fijamos las capas para que cada banda se despliegue una sobre otra. El resultado mostraría el siguiente mapa

Si se estaba atento a la generación del mapa se puede observar que la banda 11 se encuentra por debajo de la banda 12, para poder mostrar la banda 11 en el boton Layers
y se deselacciona la banda capa llamada ‘En Municipio B12’ donde mostrará la siguiente imagen.

La función hasta el momento sería la siguiente, se pone para que si se sigue este tutorial pueda ver que lo que hemos hecho hasta el momento coincide con lo explicado.
var b11_b12_mun = function(key) {
var elemet_selected= dataset_3.filter(ee.Filter.eq('ADM2_NAME', key));
///Add municipal layer
var lay_muni = ui.Map.Layer(elemet_selected,{color:'gray', opacity:0.3}, 'Municipio');
Map.layers().reset();
Map.layers().set(0, lay_muni);
Map.centerObject(elemet_selected.geometry(), 10);
var select_collection = s2a_cloudfree
.filterBounds(elemet_selected)
.select( ['B11', 'B12']);
= ui.Map.Layer(
lay_filtered_11 .mean().select('B11').clip(elemet_selected),
select_collectionmin:1000,
{max:3000,
palette: palette_b11,
opacity:0.4},
'En Municipio B11');
= ui.Map.Layer(
lay_filtered_12 .select('B12').mean().clip(elemet_selected),
select_collectionmin:1000,
{max:2600,
palette: palette_b12,
opacity:0.4},
'En Municipio B12');
Map.layers().set(1, lay_filtered_11);
Map.layers().set(2, lay_filtered_12);
return;
}
Para añadir el boton selector y este añadirlo a el panel se utiliza el siguiente código.
var selector = ui.Select({
items: key_mun.getInfo(),
onChange: b11_b12_mun
})
.add(selector) panel_select
Añadir gráfico
Ya tenemos determinado tanto la región como la selección de imágenes que nos interesan para poder obtener nuestra serie de tiempo, estas se encuentran dentro de la variable select_collection
. La idea es modificar la función que ya hicimos para generar nuestro gráfico cuando se hace la selección de un municipio.
Antes de modificar nuestra función, es necesario tener un lugar donde vamoa a añadir el gráfico que vamos a generar.
Como se ve en la imagen Figure 2, ya hemos hecho un panel donde se encuentra el boton para seleccionar el municipio, entonces podemos poner el gráfico dentro del mismo. Para tal motivo, vamos a hacer un panel que contenga al gráfico este se añade al panel despues de nuestro boton selector.
var chartPanel = ui.Panel({
layout: ui.Panel.Layout.flow('vertical'),
style: {width: '450px'}
; })
Vamos hacer nuestro gráfico con la serie de tiempo dentro de nuestra función con ui.Chart.image.series
, se seleccionan las bandas ‘B11’ y ‘B12’, se toma como región al municipio selecionado que se encuentra dentro de la variable element_selected
, y para tomar el promedio en la región se utiliza como reductor (“reducer”) ee.Reducer.mean()
.
Ya seleccionamos el tipo de gráfico (LineChart
) y los párametros del gráfico como el ancho de linea el tamaño del punto y el color de las series.
var tempTimeSeries = ui.Chart.image.series({
imageCollection: select_collection.select( ['B11', 'B12']),
region: elemet_selected,
reducer: ee.Reducer.mean()
}).setChartType('LineChart')
.setOptions({
title: 'Bands 11 y 12',
vAxis: {
title: 'nm'
,
}lineWidth: 1,
pointSize: 4,
series: {
0: {color: 'red'},
1: {color: 'blue'}
}; })
Ya con el grafico lo añadimos al panel que creamos para tal efecto, como la idea es poder seleccionar a distintos municipios (no de forma simultanea), entonces borramos el gráfico anterior dentro del panel y lo sustituimos con el nuevo gráfico.
.widgets().reset([tempTimeSeries]); chartPanel
El selector queda de la siguiente forma
var select = ui.Select({
items: key_mun.getInfo(),
onChange: function(key) {
var elemet_selected= dataset_3.filter(ee.Filter.eq('ADM2_NAME', key));
///Add municipal layer
var lay_muni = ui.Map.Layer(elemet_selected,{color:'gray', opacity:0.3}, 'Municipio');
Map.layers().reset();
Map.layers().set(0, lay_muni);
Map.centerObject(elemet_selected.geometry(), 10);
var select_collection = s2a_cloudfree
.filterBounds(elemet_selected)
.select( ['B11', 'B12']);
///Add B11, B12 mean bands ror the region
= ui.Map.Layer(
lay_filtered_11 .mean().select('B11').clip(elemet_selected),
select_collectionmin:1000,
{max:3000,
palette: palette_b11,
opacity:0.4},
'En Municipio B11');
= ui.Map.Layer(
lay_filtered_12 .select('B12').mean().clip(elemet_selected),
select_collectionmin:1000,
{max:2600,
palette: palette_b12,
opacity:0.4},
'En Municipio B12');
Map.layers().set(1, lay_filtered_11);
Map.layers().set(2, lay_filtered_12);
////get the time series
var tempTimeSeries = ui.Chart.image.series({
imageCollection: select_collection.select( ['B11', 'B12']),
region: elemet_selected,
reducer: ee.Reducer.mean()
}).setChartType('LineChart')
.setOptions({
title: 'Bands 11 y 12',
vAxis: {
title: 'nm'
,
}lineWidth: 1,
pointSize: 4,
series: {
0: {color: 'red'},
1: {color: 'blue'}
};
})
///Add to panel
.widgets().reset([tempTimeSeries]);
chartPanelreturn;
}; })
Al final la aplicación queda como se muestra en la imagen Figure 5

El código de todo lo podemos encontrar en el siguiente link