Transizione della classe di acqua

Il livello di transizione dell'acqua acquisisce le variazioni tra tre classi di presenza di acqua (non acqua, acqua stagionale e acqua permanente) insieme a due classi aggiuntive per l'acqua effimera (effimera permanente ed effimera stagionale).

Questa sezione del tutorial:

  1. aggiungere un livello della mappa per visualizzare la transizione dell'acqua,
  2. crea un riduttore raggruppato per sommare l'area di ogni classe di transizione all'interno di una regione di interesse specificata e
  3. crea un grafico che riepiloghi l'area in base alla classe di transizione.

Visualizzazione di base

Nella sezione Elenco asset dello script, aggiungi la seguente istruzione che crea un oggetto immagine a banda singola chiamato transition:

Editor di codice (JavaScript)

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

Le immagini GSW contengono metadati sui numeri e sui nomi delle classi di transizione e una tavolozza predefinita per lo stile delle classi di transizione. Quando il livello di transizione viene aggiunto alla mappa, questi parametri di visualizzazione verranno utilizzati automaticamente.

Nella parte inferiore della sezione Livelli della mappa dello script, aggiungi la seguente istruzione che aggiunge un nuovo livello della mappa che mostra le classi di transizione:

Editor di codice (JavaScript)

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

Quando esegui lo script, viene visualizzato il livello di transizione.

Classi di transizione delle acque superficiali
Figura 10. Screenshot del delta del fiume Mekong, che mostra un'ampia variazione nelle transizioni della classe di acqua di superficie.

La chiave della mappa per le classi di transizione è:

Valore Simbolo Etichetta
0 Non acqua
1 Permanente
2 Nuovo permanente
3 Lost permanent
4 Stagionale
5 Nuovo stagionale
6 Lost seasonal
7 Da stagionale a permanente
8 Da permanente a stagionale
9 Temporaneo permanente
10 Temporaneo stagionale

Riepilogo dell'area per classe di transizione

In questa sezione utilizzeremo di nuovo lo strumento poligono di geometria per definire una regione di interesse. Se vuoi analizzare una nuova posizione, devi prima selezionare ed eliminare il poligono originale che hai disegnato, in modo da non ottenere risultati dalle aree combinate. Consulta la sezione Strumenti di geometria della documentazione dell'editor di codice per informazioni su come modificare le geometrie.

Per questo esempio disegneremo un nuovo poligono all'interno del delta del fiume Mekong.

Transizione delle classi con ROI
Figura 11. Il delta del fiume Mekong in Vietnam, con una regione di interesse creata utilizzando lo strumento di disegno di poligoni dell'editor di codice.

Per calcolare l'area coperta da parti di un'immagine, aggiungeremo una banda aggiuntiva all'oggetto immagine di transizione che identifica le dimensioni di ogni pixel in metri quadrati utilizzando il metodo ee.Image.pixelArea.

Editor di codice (JavaScript)

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

L'oggetto immagine risultante (area_image_with_transition_class) è un'immagine a due bande in cui la prima banda contiene le informazioni sull'area in unità di metri quadrati (prodotte dal metodo ee.Image.pixelAreacode> ) e la seconda banda contiene le informazioni sulla classe di transizione.

Riassumiamo quindi le transizioni di classe all'interno di una regione di interesse (roi) utilizzando il metodo ee.Image.reduceRegion e un reducer raggruppato che somma l'area all'interno di ogni classe di transizione:

Editor di codice (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);

L'output della scheda Console ora mostra reduction_results. Tieni presente che dovrai espandere l'albero di alcuni livelli per visualizzare i dati di riepilogo dell'area.

Risultati della riduzione raggruppati
Figura 12. Output della scheda Console, che mostra i risultati della riduzione raggruppata.

Sebbene l'oggetto reduction_results contenga informazioni sull'area coperta da ogni classe di transizione, non è particolarmente facile da leggere. Nella sezione successiva semplificheremo la visualizzazione dei risultati.

Creazione di un grafico riepilogativo

In questa sezione creeremo un grafico per riassumere meglio i risultati. Per iniziare, estraiamo l'elenco delle classi di transizione con le aree nel seguente modo:

Editor di codice (JavaScript)

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

Il risultato del riduttore raggruppato (reduction_results) è un dizionario contenente un elenco di dizionari. Nell'elenco è presente un dizionario per ogni classe di transizione. Queste istruzioni utilizzano il metodo ee.Dictionary.get per estrarre i risultati del reducer raggruppati dal dizionario e li convertono in un tipo di dati ee.List, in modo da poter accedere ai singoli dizionari.

Per utilizzare le funzioni di creazione di grafici dell'editor di codice, creeremo un FeatureCollection che contiene le informazioni necessarie. Per farlo, creiamo prima due dizionari di ricerca e due funzioni helper. Il codice che crea i dizionari di ricerca può essere inserito all'inizio della sezione "Calcoli" nel seguente modo:

Editor di codice (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')
);

Il dizionario lookup_names associa i valori della classe di transizione ai relativi nomi, mentre il dizionario lookup_palette associa i valori della classe di transizione alle definizioni dei colori.

Le due funzioni di supporto possono essere inserite in una nuova sezione di codice denominata "Funzioni di supporto".

Editor di codice (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 funzione createFeature accetta un dizionario (contenente l'area e la classe di transizione dell'acqua) e restituisce una funzionalità adatta alla creazione di grafici. La funzione createPieChartSliceDictionary crea un elenco di colori che corrispondono alle classi di transizione, utilizzando il formato previsto dal grafico a torta.

Successivamente, applicheremo la funzione createFeature a ogni dizionario nell'elenco (roi_stats), utilizzando ee.List.map per applicare la funzione helper a ogni elemento dell'elenco.

Editor di codice (JavaScript)

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

Ora che abbiamo una FeatureCollection contenente gli attributi che vogliamo visualizzare nel grafico, possiamo creare un oggetto grafico e stamparlo nella console.

Editor di codice (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);

L'opzione slices colora le sezioni del grafico a torta in modo che utilizzino la tavolozza predefinita definita per le classi di transizione (mostrata in precedenza nella tabella della legenda della mappa). L'opzione sliceVisibilityThreshold impedisce il raggruppamento delle piccole sezioni in una categoria "Altro". Il grafico risultante dovrebbe essere simile a quello mostrato nella Figura 13.

Grafico di riepilogo della classe di transizione idrica
Figura 13. Grafico che riepiloga le dimensioni relative delle classi di transizione dell'acqua.

Script finale

L'intero script per questa sezione è:

Editor di codice (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)',
});

Il tutorial sul set di dati Global Surface Water termina qui. Tieni presente che questo tutorial ha mostrato come lavorare solo con tre dei livelli dati (occorrenza, intensità del cambiamento e transizione) disponibili nel set di dati Global Surface Water. Puoi leggere informazioni sugli altri livelli di dati disponibili nella Guida per gli utenti dei dati (v2).

Buona analisi dei dati!