Transición de clase de agua

La capa de transición del agua captura los cambios entre tres clases de ocurrencia de agua (sin agua, agua estacional y agua permanente), junto con dos clases adicionales para el agua efímera (efímera permanente y efímera estacional).

En esta sección del instructivo, se hará lo siguiente:

  1. Agrega una capa de mapa para visualizar la transición del agua.
  2. crea un reductor agrupado para sumar el área de cada clase de transición dentro de una región de interés especificada, y
  3. Crea un gráfico que resuma el área por clase de transición.

Visualización básica

En la sección Asset List de la secuencia de comandos, agrega la siguiente instrucción que crea un objeto de imagen de una sola banda llamado transition:

Editor de código (JavaScript)

var transition = gsw.select('transition');

Las imágenes de GSW contienen metadatos sobre los números y nombres de las clases de transición, y una paleta predeterminada para aplicar estilo a las clases de transición. Cuando se agrega la capa de transición al mapa, se usarán automáticamente estos parámetros de visualización.

En la parte inferior de la sección Map Layers de tu secuencia de comandos, agrega la siguiente declaración que agrega una nueva capa del mapa que muestra las clases de transición:

Editor de código (JavaScript)

Map.setCenter(105.26, 11.2134, 9);     // Mekong River Basin, SouthEast Asia
Map.addLayer({
  eeObject: transition,
  name: 'Transition classes (1984-2015)',
});

Cuando ejecutes la secuencia de comandos, se mostrará la capa de transición.

Clases de transición de aguas superficiales
Figura 10. Captura de pantalla del delta del río Mekong, que muestra una gran variación en las transiciones de clases de agua superficial.

La clave del mapa para las clases de transición es la siguiente:

Valor Símbolo Etiqueta
0 No es agua
1 Permanente
2 Nuevo permanente
3 Pérdida permanente
4 Estacional
5 Nueva temporada
6 Pérdida estacional
7 De temporal a permanente
8 De permanente a estacional
9 Permanente efímero
10 Estacional efímero

Resumen del área por clase de transición

En esta sección, volveremos a usar la herramienta de polígono de geometría para definir una región de interés. Si deseas analizar una ubicación nueva, primero debes seleccionar y borrar el polígono original que dibujaste para no obtener resultados de las áreas combinadas. Consulta la sección Herramientas de geometría de la documentación del Editor de código para obtener información sobre cómo modificar geometrías.

En este ejemplo, dibujaremos un nuevo polígono dentro del delta del río Mekong.

Clases de transición con ROI
Figura 11. El delta del río Mekong en Vietnam, con una región de interés creada con la herramienta de dibujo de polígonos del editor de código.

Para calcular el área cubierta por partes de una imagen, agregaremos una banda adicional al objeto de imagen de transición que identifica el tamaño de cada píxel en metros cuadrados con el método ee.Image.pixelArea.

Editor de código (JavaScript)

var area_image_with_transition_class = ee.Image.pixelArea().addBands(transition);

El objeto de imagen resultante (area_image_with_transition_class) es una imagen de dos bandas en la que la primera banda contiene la información del área en unidades de metros cuadrados (producida por el método ee.Image.pixelAreacode> ) y la segunda banda contiene la información de la clase de transición.

Luego, resumimos las transiciones de clase dentro de una región de interés (roi) con el método ee.Image.reduceRegion y un reductor agrupado que suma el área dentro de cada clase de transición:

Editor de código (JavaScript)

var reduction_results = area_image_with_transition_class.reduceRegion({
  reducer: ee.Reducer.sum().group({
    groupField: 1,
    groupName: 'transition_class_value',
  }),
  geometry: roi,
  scale: 30,
  bestEffort: true,
});
print('reduction_results', reduction_results);

El resultado de la pestaña de la consola ahora muestra reduction_results. Ten en cuenta que deberás expandir el árbol unos cuantos niveles para ver los datos de resumen del área.

Resultados de reducción agrupados
Figura 12. Resultado de la pestaña Consola, que muestra los resultados de la reducción agrupada.

Si bien el objeto reduction_results contiene información sobre el área cubierta por cada clase de transición, no es particularmente fácil de leer. En la siguiente sección, facilitaremos la visualización de los resultados.

Cómo crear un gráfico de resumen

En esta sección, crearemos un gráfico para resumir mejor los resultados. Para comenzar, primero extraemos la lista de clases de transición con áreas de la siguiente manera:

Editor de código (JavaScript)

var roi_stats = ee.List(reduction_results.get('groups'));

El resultado del reductor agrupado (reduction_results) es un diccionario que contiene una lista de diccionarios. Hay un diccionario en la lista para cada clase de transición. Estas instrucciones usan el método ee.Dictionary.get para extraer los resultados del reductor agrupado de ese diccionario y convertir los resultados en un tipo de datos ee.List, de modo que podamos acceder a los diccionarios individuales.

Para usar las funciones de gráficos del Editor de código, compilaremos un FeatureCollection que contenga la información necesaria. Para ello, primero creamos dos diccionarios de búsqueda y dos funciones auxiliares. El código que crea los diccionarios de búsqueda se puede colocar en la parte superior de la sección "Cálculos" de la siguiente manera:

Editor de código (JavaScript)

//////////////////////////////////////////////////////////////
// Calculations
//////////////////////////////////////////////////////////////

// Create a dictionary for looking up names of transition classes.
var lookup_names = ee.Dictionary.fromLists(
    ee.List(gsw.get('transition_class_values')).map(numToString),
    gsw.get('transition_class_names')
);
// Create a dictionary for looking up colors of transition classes.
var lookup_palette = ee.Dictionary.fromLists(
    ee.List(gsw.get('transition_class_values')).map(numToString),
    gsw.get('transition_class_palette')
);

El diccionario lookup_names asocia los valores de la clase de transición con sus nombres, mientras que el diccionario lookup_palette asocia los valores de la clase de transición con las definiciones de color.

Las dos funciones auxiliares se pueden colocar en una nueva sección de código llamada "Funciones auxiliares".

Editor de código (JavaScript)

//////////////////////////////////////////////////////////////
// Helper functions
//////////////////////////////////////////////////////////////

// Create a feature for a transition class that includes the area covered.
function createFeature(transition_class_stats) {
  transition_class_stats = ee.Dictionary(transition_class_stats);
  var class_number = transition_class_stats.get('transition_class_value');
  var result = {
      transition_class_number: class_number,
      transition_class_name: lookup_names.get(class_number),
      transition_class_palette: lookup_palette.get(class_number),
      area_m2: transition_class_stats.get('sum')
  };
  return ee.Feature(null, result);   // Creates a feature without a geometry.
}

// Create a JSON dictionary that defines piechart colors based on the
// transition class palette.
// https://developers.google.com/chart/interactive/docs/gallery/piechart
function createPieChartSliceDictionary(fc) {
  return ee.List(fc.aggregate_array("transition_class_palette"))
    .map(function(p) { return {'color': p}; }).getInfo();
}

// Convert a number to a string. Used for constructing dictionary key lists
// from computed number objects.
function numToString(num) {
  return ee.Number(num).format();
}

La función createFeature toma un diccionario (que contiene el área y la clase de transición del agua) y devuelve un objeto Feature adecuado para generar gráficos. La función createPieChartSliceDictionary crea una lista de colores que corresponden a las clases de transición, con el formato esperado por el gráfico circular.

A continuación, aplicaremos la función createFeature a cada diccionario de la lista (roi_stats) con ee.List.map para aplicar la función auxiliar a cada elemento de la lista.

Editor de código (JavaScript)

var transition_fc = ee.FeatureCollection(roi_stats.map(createFeature));
print('transition_fc', transition_fc);

Ahora que tenemos un FeatureCollection que contiene los atributos que queremos mostrar en el gráfico, podemos crear un objeto de gráfico y mostrarlo en la consola.

Editor de código (JavaScript)

// Add a summary chart.
var transition_summary_chart = ui.Chart.feature.byFeature({
    features: transition_fc,
    xProperty: 'transition_class_name',
    yProperties: ['area_m2', 'transition_class_number']
  })
  .setChartType('PieChart')
  .setOptions({
    title: 'Summary of transition class areas',
    slices: createPieChartSliceDictionary(transition_fc),
    sliceVisibilityThreshold: 0  // Don't group small slices.
  });
print(transition_summary_chart);

La opción slices colorea las porciones del gráfico circular para que usen la paleta predeterminada definida para las clases de transición (que se mostró anteriormente en la tabla de la leyenda del mapa). La opción sliceVisibilityThreshold evita que las porciones pequeñas se agrupen en una categoría "otro". El gráfico resultante debería ser similar al que se muestra en la figura 13.

Gráfico de resumen de la clase de transición de agua
Figura 13. Gráfico que resume el tamaño relativo de las clases de transición de agua.

Guion final

El script completo de esta sección es el siguiente:

Editor de código (JavaScript)

//////////////////////////////////////////////////////////////
// Asset List
//////////////////////////////////////////////////////////////

var gsw = ee.Image('JRC/GSW1_0/GlobalSurfaceWater');
var occurrence = gsw.select('occurrence');
var change = gsw.select("change_abs");
var transition = gsw.select('transition');
var roi = ee.Geometry.Polygon(
        [[[105.531921, 10.412183],
          [105.652770, 10.285193],
          [105.949401, 10.520218],
          [105.809326, 10.666006]]]);
//////////////////////////////////////////////////////////////
// Constants
//////////////////////////////////////////////////////////////

var VIS_OCCURRENCE = {
    min: 0,
    max: 100,
    palette: ['red', 'blue']
};
var VIS_CHANGE = {
    min: -50,
    max: 50,
    palette: ['red', 'black', 'limegreen']
};
var VIS_WATER_MASK = {
  palette: ['white', 'black']
};

//////////////////////////////////////////////////////////////
// Helper functions
//////////////////////////////////////////////////////////////

// Create a feature for a transition class that includes the area covered.
function createFeature(transition_class_stats) {
  transition_class_stats = ee.Dictionary(transition_class_stats);
  var class_number = transition_class_stats.get('transition_class_value');
  var result = {
      transition_class_number: class_number,
      transition_class_name: lookup_names.get(class_number),
      transition_class_palette: lookup_palette.get(class_number),
      area_m2: transition_class_stats.get('sum')
  };
  return ee.Feature(null, result);   // Creates a feature without a geometry.
}

// Create a JSON dictionary that defines piechart colors based on the
// transition class palette.
// https://developers.google.com/chart/interactive/docs/gallery/piechart
function createPieChartSliceDictionary(fc) {
  return ee.List(fc.aggregate_array("transition_class_palette"))
    .map(function(p) { return {'color': p}; }).getInfo();
}

// Convert a number to a string. Used for constructing dictionary key lists
// from computed number objects.
function numToString(num) {
  return ee.Number(num).format();
}

//////////////////////////////////////////////////////////////
// Calculations
//////////////////////////////////////////////////////////////

// Create a dictionary for looking up names of transition classes.
var lookup_names = ee.Dictionary.fromLists(
    ee.List(gsw.get('transition_class_values')).map(numToString),
    gsw.get('transition_class_names')
);
// Create a dictionary for looking up colors of transition classes.
var lookup_palette = ee.Dictionary.fromLists(
    ee.List(gsw.get('transition_class_values')).map(numToString),
    gsw.get('transition_class_palette')
);

// Create a water mask layer, and set the image mask so that non-water areas
// are transparent.
var water_mask = occurrence.gt(90).mask(1);

// Generate a histogram object and print it to the console tab.
var histogram = ui.Chart.image.histogram({
  image: change,
  region: roi,
  scale: 30,
  minBucketWidth: 10
});
histogram.setOptions({
  title: 'Histogram of surface water change intensity.'
});
print(histogram);

// Summarize transition classes in a region of interest.
var area_image_with_transition_class = ee.Image.pixelArea().addBands(transition);
var reduction_results = area_image_with_transition_class.reduceRegion({
  reducer: ee.Reducer.sum().group({
    groupField: 1,
    groupName: 'transition_class_value',
  }),
  geometry: roi,
  scale: 30,
  bestEffort: true,
});
print('reduction_results', reduction_results);

var roi_stats = ee.List(reduction_results.get('groups'));

var transition_fc = ee.FeatureCollection(roi_stats.map(createFeature));
print('transition_fc', transition_fc);

// Add a summary chart.
var transition_summary_chart = ui.Chart.feature.byFeature({
    features: transition_fc,
    xProperty: 'transition_class_name',
    yProperties: ['area_m2', 'transition_class_number']
  })
  .setChartType('PieChart')
  .setOptions({
    title: 'Summary of transition class areas',
    slices: createPieChartSliceDictionary(transition_fc),
    sliceVisibilityThreshold: 0  // Don't group small slices.
  });
print(transition_summary_chart);

//////////////////////////////////////////////////////////////
// Initialize Map Location
//////////////////////////////////////////////////////////////

// Uncomment one of the following statements to center the map on
// a particular location.
// Map.setCenter(-90.162, 29.8597, 10);   // New Orleans, USA
// Map.setCenter(-114.9774, 31.9254, 10); // Mouth of the Colorado River, Mexico
// Map.setCenter(-111.1871, 37.0963, 11); // Lake Powell, USA
// Map.setCenter(149.412, -35.0789, 11);  // Lake George, Australia
Map.setCenter(105.26, 11.2134, 9);     // Mekong River Basin, SouthEast Asia
// Map.setCenter(90.6743, 22.7382, 10);   // Meghna River, Bangladesh
// Map.setCenter(81.2714, 16.5079, 11);   // Godavari River Basin Irrigation Project, India
// Map.setCenter(14.7035, 52.0985, 12);   // River Oder, Germany & Poland
// Map.setCenter(-59.1696, -33.8111, 9);  // Buenos Aires, Argentina
// Map.setCenter(-74.4557, -8.4289, 11);  // Ucayali River, Peru

//////////////////////////////////////////////////////////////
// Map Layers
//////////////////////////////////////////////////////////////

Map.addLayer({
  eeObject: water_mask,
  visParams: VIS_WATER_MASK,
  name: '90% occurrence water mask',
  shown: false
});
Map.addLayer({
  eeObject: occurrence.updateMask(occurrence.divide(100)),
  name: "Water Occurrence (1984-2015)",
  visParams: VIS_OCCURRENCE,
  shown: false
});
Map.addLayer({
  eeObject: change,
  visParams: VIS_CHANGE,
  name: 'occurrence change intensity',
  shown: false
});
Map.addLayer({
  eeObject: transition,
  name: 'Transition classes (1984-2015)',
});

Con esto, concluye el instructivo sobre el conjunto de datos de Global Surface Water. Ten en cuenta que en este instructivo se mostró cómo trabajar con solo tres de las capas de datos (ocurrencia, intensidad del cambio y transición) que están disponibles en el conjunto de datos de Global Surface Water. Puedes leer sobre las otras capas de datos disponibles en la Guía del usuario de datos (versión 2).

¡Que disfrutes el análisis!