Tutoriel 6.2

Site: OpenCourseWare for GIS
Cours: Google Earth Engine pour les applications agrohydrologiques
Livre: Tutoriel 6.2
Imprimé par: Guest user
Date: samedi 21 décembre 2024, 21:38

Description

Ce tutoriel explique les extraits de script à développer pour la première application Web

1. Introduction

Dans ce tutoriel, nous développerons un script qui sera ensuite utilisé pour développer une application web avec les fonctionnalités suivantes:

  • Arrière-plan par défaut de données satellites à très haute résolution
  • Carte d'élévation dans la liste des couches, afficher la légende de la carte d'élévation
  • Limiter la région de l'application web à une zone d'étude (dans ce cas ci, ulb)
  • Créez un panneau UX sur le côté gauche pour afficher les graphiques et le texte
  • Sur clic - afficher les graphiques montrant la variation mensuelle des précipitations et de l'ET de ce pixel
  • Sur clic - afficher la valeur d'élévation de ce pixel
  • Possibilité d'exporter les valeurs des graphiques au format csv

L'interface de l'application Web doit ressembler à l'image ci-dessous lorsque l'utilisateur clique dessus:


Principaux éléments (blocs) constitutifs d'une application Web:

Il y a trois blocs de construction majeurs pour une application web à partir de GEE

  1. Conception - les fonctionnalités et les caractéristiques de conception dont nous avons besoin dans notre application finale
  2. Scriptage - Scripter à l'aide de l'éditeur de code java script de GEE pour développer un script répondant à vos besoins
  3. Déploiement - Utilisez la section "Apps" de GEE pour déployer votre script en tant qu'application dans Google Cloud. Une url publique basée sur votre compte utilisateur sera fournie et sera accessible au public

2. Structure du script

Dans les sous-chapitres suivants - 2.1 à 2.6, le script final utilisé pour l'application web est divisé en sections majeures basées sur les fonctionnalités pour une meilleure compréhension.

Vous pouvez créer un nouveau script vide dans votre répertoire, et copier les extraits de code de chaque chapitre, l'exécuter pour voir ce que chaque extrait de code ajoute au script global et à l'application web finale.

2.1. Importer les données

Le extrait ci-dessous permet d'importer des données à partir de plusieurs sources. Notez que les textes en vert sont des commentaires expliquant les commandes.

// Importer les ensembles de données suivants

// Les trois premiers sont publics - données de précipitations GPM, données d'élévation ALOS et données ET de WaPOR

// La quatrième donnée est la limite de la zone d'étude qui devrait être disponible dans vos ressources (assets).

var GPM = ee.ImageCollection("NASA/GPM_L3/IMERG_MONTHLY_V06");

var dsm = ee.ImageCollection("JAXA/ALOS/AW3D30/V3_2");

var ETIa = ee.ImageCollection("FAO/WAPOR/2/L1_AETI_D");

var ulb = ee.FeatureCollection("users/spareeth/Module11/urmia_bdry");

2.2. Afficher les propriétés

L'extrait de code ci-dessous définit certains paramètres d'affichage pour l'application Web

  • Définir l'arrière-plan par défaut en tant que Satellite
  • Définir une palette pour les données d'élévation
  • Centrer la carte de la page d'accueil au centre de votre zone d'étude
  • Mosaïque et clip de la couche d'élévation (dsm) sur votre zone d'étude
  • Ajoutez la couche d'élévation à la liste des couches de l'application finale.

// La ligne ci-dessous définit la carte d'arrière-plan par défaut comme étant Google Satellite

Map.setOptions('HYBRID');

// A la ligne ci-dessous, définissez le style de curseur par défaut à crosshair (pour mieux pointer le pixel)

Map.style().set('cursor''crosshair');

 

// Ce qui nous intéresse est la première bande - DSM

// Définissons une palette pour visualiser cette élévation

var elevPalette = ['yellow''green''Brown'];

var elev = {min: 1000max: 3000palette: elevPalette};

 

// Mais nous sommes seulement intéressés à voir notre zone d'étude

// Voir si la limite de l'ULB est déjà importée ci-dessus comme variable 'ulb'

Map.centerObject(ulb,8);

 

//Maintenant, sélectionnons la première bande 'DSM' et mosaïque puis clip le DSM à la limite de l'ULB

var dsm_ulb = dsm.select('DSM').filterBounds(ulb).mosaic().clip(ulb);

print(dsm_ulb);

 

// La commande suivante ajoutera le DSM découpé à la vue de la carte

Map.addLayer(dsm_ulbelev'Elevation (ALOS)');

2.3. Fonctions définies

L'extrait de code ci-dessous définit deux fonctions

  • Pour obtenir le nombre de jours dans un mois
  • Pour convertir mm/heure en mm/mois


//////FONCTIONS DEFINIES////////

 

//Lafonction ci-dessous retourne le nombre de jours dans le mois

function getDaysInMonth(y,m) {

  var dt = ee.Date.fromYMD(y,m,1);

  var n = dt.advance(1,"month").difference(dt,'day');

  return n;

}

 

//La fonction ci-dessous convertira les mm/hr en mm/mois pour

// les données GPM

var monthly = function(image) {

  var dt = ee.Date(image.get("system:time_end"));

  var y = dt.get('year');

  var m = dt.get('month');

  var days = getDaysInMonth(y,m);

  return image.multiply(days).multiply(24).copyProperties(image, ["system:time_start""system:time_end"]);

};

 

//////FONCTIONS DEFINIES FINISSENT ICI////////

2.4. Filtrer les collections d'images

L'extrait de code ci-dessous filtre les collections d'images (GPM et AETI de WaPOR) sur deux ans, d'octobre 2018 à septembre 2020

En outre, les collections d'images sont affinées au périmètre de la zone d'étude (ulb)

// selectionner la bande avec l'information sur la précipitation

// Filtrer à deux ans d'octobre 2018 à septembre 2020 (2 ans)

var pcp = GPM.filterDate('2018-10-01''2020-09-30')

              .filterBounds(ulb)

              .select('precipitation');

              

// Appliquer la fonction monthly à la collection d'images 'pcp' pour

// convertir mm/hr à mm/mois

var pcp_monthly = pcp.map(monthly);

 

// Filtrer ETIa à ulb

// Filtrer à deux ans d'octobre 2018 à septembre 2020 (2 ans)

var ETIa_filt = ETIa.filterDate('2018-10-01''2020-09-30')

                    .filterBounds(ulb);


 

2.5. Ajouter une légende à l'élevation

L'extrait de code ci-dessous définit une fonction permettant d'ajouter une légende à la carte d'altitude (ALOS) en bas à droite des cartes de l'application web finale.

//////////////////ajout de la fonction de la légende DEBUTE ici///////////////////

// Pour l'application web, afficher la légende de l'élévation

// La fonction ce dessous créune légend en tant que vignette insérée à l'IU au panneau (interface utilisateur)

function makeLegend(elev) {

  var lon = ee.Image.pixelLonLat().select('longitude');

  var gradient = lon.multiply((elev.max-elev.min)/100.0).add(elev.min);

  var legendImage = gradient.visualize(elev);

  var panel = ui.Panel({

    layout: ui.Panel.Layout.flow('horizontal'),

    style: {

          position: 'bottom-right',

          padding: '5x 5px',

          color: '000000'

    },

    

    widgets: [

      ui.Label(String(elev.min)), 

      ui.Label({style: {stretch: 'horizontal'}}),

      ui.Label(String(1500)), 

      ui.Label({style: {stretch: 'horizontal'}}),

      ui.Label(String(2000)),

      ui.Label({style: {stretch: 'horizontal'}}),

      ui.Label(String(2500)), 

      ui.Label({style: {stretch: 'horizontal'}}),

      ui.Label(elev.max)

    ]

  });

  // Créer le titre de la légende //

  var legendTitle = ui.Label({

    value: 'Elevation (m)',

    style: {

      stretch: 'horizontal',

      textAlign: 'center',

      fontWeight: 'bold',

      fontSize: '14px',

    }

  });

  var thumb = ui.Thumbnail({

    image: legendImage

    params: {bbox:'0,10,100,8'dimensions:'356x15'}, 

    style: {padding: '0.5px'}

  });

  return ui.Panel({style:{position: 'bottom-right'}}).add(legendTitle).add(thumb).add(panel);

}

Map.add(makeLegend(elev));

////////////Ajout de la fonction de la légende FIN ici////////////

2.6. Add Panel for displaying charts

L'extrait de code ci-dessous ajoute un panneau dans le côté gauche de l'application Web pour afficher du texte et des résultats de clics comme des valeurs et des graphiques.


// Maintenant, pour l'application web, nous voulons créer un panneau gauche qui affichera

// graphique des séries temporelles en cliquant sur la carte à l'intérieur de l'ulb

// Créons deux graphiques : i) les précipitations mensuelles et ii) l'ETIa décadaire de deux années

// Affiche également la valeur d'élévation lors d'un clic sur un pixel

 

///////////////////Insérer des panneaux pour afficher les graphiques et les résultats/////////

// Créons un panneau vide et ajoutons les autres panneaux en tant que sous-panneaux à celui-ci

var panel = ui.Panel({

    style: {fontSize: '20px'color: '114982'}

});

 

// Créez un panneau pour afficher des labels comme du texte

var text = ui.Panel([

  ui.Label({

    value: 'My first App',

    style: {fontSize: '30px'fontWeight: 'bold'color: '#2F4F4F'}

  }),

  ui.Label({

    value:'Click a point on the map to explore the variable over time',

    style: {fontSize: '14px'fontWeight: 'bold'maxWidth: '400px'color: '#2F4F4F'}

  }),

]);

// Ajoutez le nouveau panneau de texte au panneau de base.

panel.add(text);

 

// Créer un panneau pour afficher la valeur de l'élévation au clic

var inspector = ui.Panel([ui.Label('Click to get Elevation')]);

panel.add(inspector);

 

// Nous allons définir ci-dessous des panneaux pour afficher des objets dynamiques -

// Valeurs d'élévation, carte des précipitations, carte ETIa

 

Map.onClick(function(coords) {

   // Ajouter un graphe pour mettre le tableau des précipitations mensuelles

  var point = ee.Geometry.Point(coords.loncoords.lat);

  var dot = ui.Map.Layer(point, {color: 'FF0000'});

  Map.layers().set(1dot);

  var sample = dsm_ulb.sample(point30);

  var computedValue = sample.first().get('DSM');

  // Demander la valeur au serveur.

  computedValue.evaluate(function(result) {

  // Lorsque le serveur renvoie la valeur, l'afficher.

  inspector.widgets().set(0ui.Label({

  value: 'Elevation: ' + result,

    }));

  });

    var chart1 = ui.Chart.image.series({

    imageCollection: pcp_monthly.select(['precipitation']),

    region: point

    reducer: ee.Reducer.mean(), 

    scale: 30

  });

  chart1.setOptions({

    title: 'Monthly Precipitation 2019',

    vAxis: {title: 'P (mm)'gridlines: {count: 10}},

    hAxis: {title: 'month'format: 'MM-yy'gridlines: {count: 10}},

    label: 'ETa',

    width: 250,

    height: 250,

    //interpolateNulls: true,

    //curveType: 'function'

  });

  chart1.setChartType('ColumnChart');

  panel.widgets().set(2chart1);

       //////second graph

    var chart2 = ui.Chart.image.series({

    imageCollection: ETIa_filt.select('L1_AETI_D'),

    region: point

    reducer: ee.Reducer.mean(), 

    scale: 250

  });

  chart2.setOptions({

    title: 'Dekadal ETIa',

    vAxis: {title: 'ETIa'gridlines: {count: 10}, maxValue: 0.5minValue: 0 },

    hAxis: {title: 'month'format: 'MM-yy'gridlines: {count: 10}},

    width: 250,

    height: 250,

    colors: ['#09F310'],

    interpolateNulls: true,

    curveType: 'function'

  });

  panel.widgets().set(3chart2);

});

 

// Ajouter le panneau défini ci-dessus à la racine

ui.root.insert(0panel);

3. Script Final

Le code ci-dessous est le script complet que vous pouvez sauvegarder comme un nouveau script dans votre éditeur de script java GEE. Une fois enregistré, vous pouvez suivre le tutoriel vidéo de l'exercice 6.1, pour développer une application web à partir de ce script.

Notez que vous devez modifier la ligne 7 pour adapter le script à votre zone d'étude ou à la ressources ulb de votre répertoire.

// Import the following datasets

// First three are public - GPM precipitation data, ALOS Elevation data and WaPOR ET data

// The fourth data is study area boundary which shoulld be available in your assets.

var GPM = ee.ImageCollection("NASA/GPM_L3/IMERG_MONTHLY_V06");

var dsm = ee.ImageCollection("JAXA/ALOS/AW3D30/V3_2");

var ETIa = ee.ImageCollection("FAO/WAPOR/2/L1_AETI_D");

var ulb = ee.FeatureCollection("users/spareeth/Module11/urmia_bdry");

 

// Below line set the default background map to Google satellite

Map.setOptions('HYBRID');

// Below line set the default cursor style to crosshair (better to pin point pixel)

Map.style().set('cursor''crosshair');

 

// What we are interested is the first band - DSM

// Let us set a palette to visualize this elevation

var elevPalette = ['yellow''green''Brown'];

var elev = {min: 1000max: 3000palette: elevPalette};

 

// But we are only interested to see our study area

// See above that the ULB boundary is aleady imported above as variable 'ulb'

Map.centerObject(ulb,8);

 

//Now let us select the first band 'DSM' and mosaic & clip the DSM to ULB boundary

var dsm_ulb = dsm.select('DSM').filterBounds(ulb).mosaic().clip(ulb);

print(dsm_ulb);

 

// The below command will add clipped DSM to the map view

Map.addLayer(dsm_ulbelev'Elevation (ALOS)');

 

//////FUNCTIONS DEFINED////////

 

//below function return number of days in a month

function getDaysInMonth(y,m) {

  var dt = ee.Date.fromYMD(y,m,1);

  var n = dt.advance(1,"month").difference(dt,'day');

  return n;

}

 

//below function will convert mm/hr to mm/month for the 

// GPM data

var monthly = function(image) {

  var dt = ee.Date(image.get("system:time_end"));

  var y = dt.get('year');

  var m = dt.get('month');

  var days = getDaysInMonth(y,m);

  return image.multiply(days).multiply(24).copyProperties(image, ["system:time_start""system:time_end"]);

};

 

//////FUNCTIONS DEFINED END HERE////////

 

// select the band with precipitation information

// Filter to 2 years from October 2018 to September 2020 (2 years)

var pcp = GPM.filterDate('2018-10-01''2020-09-30')

              .filterBounds(ulb)

              .select('precipitation');

              

// Apply the monthly function to image collection 'pcp' to

// convert mm/hr to mm/month

var pcp_monthly = pcp.map(monthly);

 

// Filter ETIa to ulb

// Filter to 2 years from October 2018 to September 2020 (2 years)

var ETIa_filt = ETIa.filterDate('2018-10-01''2020-09-30')

                    .filterBounds(ulb);

print(ETIa_filt.size());

 

//////////////////Add Legend function STARTS here///////////////////////

// For the web application, to display the legend of elevation

// Below function create a legend as a thumbnail inserted to UI (user interface) panel

function makeLegend(elev) {

  var lon = ee.Image.pixelLonLat().select('longitude');

  var gradient = lon.multiply((elev.max-elev.min)/100.0).add(elev.min);

  var legendImage = gradient.visualize(elev);

  var panel = ui.Panel({

    layout: ui.Panel.Layout.flow('horizontal'),

    style: {

          position: 'bottom-right',

          padding: '5x 5px',

          color: '000000'

    },

    

    widgets: [

      ui.Label(String(elev.min)), 

      ui.Label({style: {stretch: 'horizontal'}}),

      ui.Label(String(1500)), 

      ui.Label({style: {stretch: 'horizontal'}}),

      ui.Label(String(2000)),

      ui.Label({style: {stretch: 'horizontal'}}),

      ui.Label(String(2500)), 

      ui.Label({style: {stretch: 'horizontal'}}),

      ui.Label(elev.max)

    ]

  });

  // Create legend title //

  var legendTitle = ui.Label({

    value: 'Elevation (m)',

    style: {

      stretch: 'horizontal',

      textAlign: 'center',

      fontWeight: 'bold',

      fontSize: '14px',

    }

  });

  var thumb = ui.Thumbnail({

    image: legendImage

    params: {bbox:'0,10,100,8'dimensions:'356x15'}, 

    style: {padding: '0.5px'}

  });

  return ui.Panel({style:{position: 'bottom-right'}}).add(legendTitle).add(thumb).add(panel);

}

Map.add(makeLegend(elev));

//////////////////Add Legend function ENDS here///////////////////////

 

// Now For the web application we want to create a left panel which will display

// time series plots on click on map inside ulb

// Let us create two charts i) monthly precipitation and ii) dekadal ETIa of two years

// Also display elevation value on click on a pixel

 

///////////////////Insert Panels to display charts and results ///////////////

// Create an empty panel and let us add the remaining panels as sub panels to this one

var panel = ui.Panel({

    style: {fontSize: '20px'color: '114982'}

});

 

// Create a panel to display some labels like text

var text = ui.Panel([

  ui.Label({

    value: 'My first App',

    style: {fontSize: '30px'fontWeight: 'bold'color: '#2F4F4F'}

  }),

  ui.Label({

    value:'Click a point on the map to explore the variable over time',

    style: {fontSize: '14px'fontWeight: 'bold'maxWidth: '400px'color: '#2F4F4F'}

  }),

]);

// Add the new text panel to the root panel.

panel.add(text);

 

// Create a panel to display elevation value on click

var inspector = ui.Panel([ui.Label('Click to get Elevation')]);

panel.add(inspector);

 

// Below we are going to define panels to display dynamic objects -

// Elevation values, precipitation chart, ETIa chart

 

Map.onClick(function(coords) {

   // Add a chart to put monthly precipitation chart

  var point = ee.Geometry.Point(coords.loncoords.lat);

  var dot = ui.Map.Layer(point, {color: 'FF0000'});

  Map.layers().set(1dot);

  var sample = dsm_ulb.sample(point30);

  var computedValue = sample.first().get('DSM');

  // Request the value from the server.

  computedValue.evaluate(function(result) {

  // When the server returns the value, show it.

  inspector.widgets().set(0ui.Label({

  value: 'Elevation: ' + result,

    }));

  });

    var chart1 = ui.Chart.image.series({

    imageCollection: pcp_monthly.select(['precipitation']),

    region: point

    reducer: ee.Reducer.mean(), 

    scale: 30

  });

  chart1.setOptions({

    title: 'Monthly Precipitation 2019',

    vAxis: {title: 'P (mm)'gridlines: {count: 10}},

    hAxis: {title: 'month'format: 'MM-yy'gridlines: {count: 10}},

    label: 'ETa',

    width: 250,

    height: 250,

    //interpolateNulls: true,

    //curveType: 'function'

  });

  chart1.setChartType('ColumnChart');

  panel.widgets().set(2chart1);

       //////Second chart

    var chart2 = ui.Chart.image.series({

    imageCollection: ETIa_filt.select('L1_AETI_D'),

    region: point

    reducer: ee.Reducer.mean(), 

    scale: 250

  });

  chart2.setOptions({

    title: 'Dekadal ETIa',

    vAxis: {title: 'ETIa'gridlines: {count: 10}, maxValue: 0.5minValue: 0 },

    hAxis: {title: 'month'format: 'MM-yy'gridlines: {count: 10}},

    width: 250,

    height: 250,

    colors: ['#09F310'],

    interpolateNulls: true,

    curveType: 'function'

  });

  panel.widgets().set(3chart2);

});

 

// Add the above defined panel to root

ui.root.insert(0panel);