Transición de clase de agua

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

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

  1. agregar una capa de mapa para visualizar la transición del agua,
  2. crear un reductor agrupado para sumar el área de cada clase de transición dentro de una región de interés especificada, y
  3. crear 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 sentencia 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 diseño a las clases de transición. Cuando se agregue la capa de transición al mapa, estos parámetros de visualización se usarán automáticamente.

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.

Surface Water Transition Classes
Figura 10. Captura de pantalla del delta del río Mekong, que muestra una amplia variación en las transiciones de clase 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 Estacionalidad perdida
7 De estacional a permanente
8 De permanente a estacional
9 Efímero permanente
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 quieres 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 polígono nuevo 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 que cubren las 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.pixelArea ) 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 actúa para sumar 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 el reduction_results. Ten en cuenta que deberás expandir el árbol algunos niveles para ver los datos de resumen del área.

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

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

Crea 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 declaraciones usan el método ee.Dictionary.get para extraer los resultados del reductor agrupado de ese diccionario y convierte los resultados en un tipo de datos ee.List, para que podamos acceder a los diccionarios individuales.

Para usar las funciones de gráficos del editor de código, crearemos una 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 de agua) y devuelve un objeto Feature adecuado para la creación de gráficos. La función createPieChartSliceDictionary crea una lista de colores que corresponden a las clases de transición, con el formato que espera el gráfico circular.

A continuación, aplicaremos la función createFeature en 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 una 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ó antes en la tabla de claves del mapa). La opción sliceVisibilityThreshold evita que las porciones pequeñas se agrupen en una categoría "Otros". 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 del agua.

Guion final

La secuencia de comandos completa para esta sección es la 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)',
});

Aquí 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 que están disponibles en la Guía del usuario de datos (v2).

Esperamos que disfrutes el análisis.