diff --git a/code/gee_dynamic_world/03_Time_Series_Processing/04b_Time_Series_Charts_(complete) b/code/gee_dynamic_world/03_Time_Series_Processing/04b_Time_Series_Charts_(complete) index 3f5866ab..6c27b9fe 100644 --- a/code/gee_dynamic_world/03_Time_Series_Processing/04b_Time_Series_Charts_(complete) +++ b/code/gee_dynamic_world/03_Time_Series_Processing/04b_Time_Series_Charts_(complete) @@ -1,12 +1,12 @@ -/**** Start of imports. If edited, may not auto-convert in the playground. ****/ -var geometry = /* color: #00ff00 */ee.Geometry.Polygon( - [[[36.62513180012346, -1.2332928138897847], - [36.62499232525469, -1.2339685738967323], - [36.62524981732012, -1.234011479288199], - [36.62541074986101, -1.2334322564449516]]]); -/***** End of imports. If edited, may not auto-convert in the playground. *****/ var s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED'); +var geometry = ee.Geometry.Polygon([[ + [36.62513180012346, -1.2332928138897847], + [36.62499232525469, -1.2339685738967323], + [36.62524981732012, -1.234011479288199], + [36.62541074986101, -1.2334322564449516]] +]); + Map.addLayer(geometry, {color: 'red'}, 'Farm'); Map.centerObject(geometry); diff --git a/code/gee_dynamic_world/03_Time_Series_Processing/05b_Dynamic_World_Time_Series_Chart_(complete) b/code/gee_dynamic_world/03_Time_Series_Processing/05b_Dynamic_World_Time_Series_Chart_(complete) index fbfec4f4..b117a902 100644 --- a/code/gee_dynamic_world/03_Time_Series_Processing/05b_Dynamic_World_Time_Series_Chart_(complete) +++ b/code/gee_dynamic_world/03_Time_Series_Processing/05b_Dynamic_World_Time_Series_Chart_(complete) @@ -1,12 +1,12 @@ -/**** Start of imports. If edited, may not auto-convert in the playground. ****/ -var geometry = /* color: #00ff00 */ee.Geometry.Polygon( - [[[36.62513180012346, -1.2332928138897847], - [36.62499232525469, -1.2339685738967323], - [36.62524981732012, -1.234011479288199], - [36.62541074986101, -1.2334322564449516]]]); -/***** End of imports. If edited, may not auto-convert in the playground. *****/ // Charting Class Probabilities Over Time +var geometry = ee.Geometry.Polygon([[ + [36.62513180012346, -1.2332928138897847], + [36.62499232525469, -1.2339685738967323], + [36.62524981732012, -1.234011479288199], + [36.62541074986101, -1.2334322564449516]] +]); + Map.addLayer(geometry, {color: 'red'}, 'Selected Location') Map.centerObject(geometry, 16) @@ -60,7 +60,10 @@ var chart = ui.Chart.image.series({ hAxis: {title: '', format: 'YYYY-MMM'}, series: { 0: {color: 'green'}, - 1: {color: 'yellow'} + 1: {color: 'orange'} + }, + legend: { + position: 'top' } }); print(chart); diff --git a/docs/code/gee_dynamic_world/03_Time_Series_Processing/04b_Time_Series_Charts_(complete) b/docs/code/gee_dynamic_world/03_Time_Series_Processing/04b_Time_Series_Charts_(complete) index 3f5866ab..6c27b9fe 100644 --- a/docs/code/gee_dynamic_world/03_Time_Series_Processing/04b_Time_Series_Charts_(complete) +++ b/docs/code/gee_dynamic_world/03_Time_Series_Processing/04b_Time_Series_Charts_(complete) @@ -1,12 +1,12 @@ -/**** Start of imports. If edited, may not auto-convert in the playground. ****/ -var geometry = /* color: #00ff00 */ee.Geometry.Polygon( - [[[36.62513180012346, -1.2332928138897847], - [36.62499232525469, -1.2339685738967323], - [36.62524981732012, -1.234011479288199], - [36.62541074986101, -1.2334322564449516]]]); -/***** End of imports. If edited, may not auto-convert in the playground. *****/ var s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED'); +var geometry = ee.Geometry.Polygon([[ + [36.62513180012346, -1.2332928138897847], + [36.62499232525469, -1.2339685738967323], + [36.62524981732012, -1.234011479288199], + [36.62541074986101, -1.2334322564449516]] +]); + Map.addLayer(geometry, {color: 'red'}, 'Farm'); Map.centerObject(geometry); diff --git a/docs/code/gee_dynamic_world/03_Time_Series_Processing/05b_Dynamic_World_Time_Series_Chart_(complete) b/docs/code/gee_dynamic_world/03_Time_Series_Processing/05b_Dynamic_World_Time_Series_Chart_(complete) index fbfec4f4..b117a902 100644 --- a/docs/code/gee_dynamic_world/03_Time_Series_Processing/05b_Dynamic_World_Time_Series_Chart_(complete) +++ b/docs/code/gee_dynamic_world/03_Time_Series_Processing/05b_Dynamic_World_Time_Series_Chart_(complete) @@ -1,12 +1,12 @@ -/**** Start of imports. If edited, may not auto-convert in the playground. ****/ -var geometry = /* color: #00ff00 */ee.Geometry.Polygon( - [[[36.62513180012346, -1.2332928138897847], - [36.62499232525469, -1.2339685738967323], - [36.62524981732012, -1.234011479288199], - [36.62541074986101, -1.2334322564449516]]]); -/***** End of imports. If edited, may not auto-convert in the playground. *****/ // Charting Class Probabilities Over Time +var geometry = ee.Geometry.Polygon([[ + [36.62513180012346, -1.2332928138897847], + [36.62499232525469, -1.2339685738967323], + [36.62524981732012, -1.234011479288199], + [36.62541074986101, -1.2334322564449516]] +]); + Map.addLayer(geometry, {color: 'red'}, 'Selected Location') Map.centerObject(geometry, 16) @@ -60,7 +60,10 @@ var chart = ui.Chart.image.series({ hAxis: {title: '', format: 'YYYY-MMM'}, series: { 0: {color: 'green'}, - 1: {color: 'yellow'} + 1: {color: 'orange'} + }, + legend: { + position: 'top' } }); print(chart); diff --git a/docs/gee-dynamic-world.html b/docs/gee-dynamic-world.html index a86d5917..bec75413 100644 --- a/docs/gee-dynamic-world.html +++ b/docs/gee-dynamic-world.html @@ -476,6 +476,39 @@

Ujaval Gandhi

  • Quiz - Module 2
  • +
  • Module 3: Time Series +Processing +
  • Learning Resources
  • Data Credits
  • @@ -2119,6 +2152,440 @@

    Quiz - Module 2

    Quiz ↗.

    +
    +

    Module 3: Time Series Processing

    +

    View Presentation

    +

    View the Presentation ↗

    +
    +

    01. Mapping a Function

    +

    Open in Code Editor ↗

    +
    // Let's see how to take a list of numbers and add 1 to each element
    +var myList = ee.List.sequence(1, 10);
    +
    +// Define a function that takes a number and adds 1 to it
    +var myFunction = function(number) {
    +  return number + 1;
    +}
    +print(myFunction(1));
    +
    +//Re-Define a function using Earth Engine API
    +var myFunction = function(number) { 
    +  return ee.Number(number).add(1);
    +}
    +
    +// Map the function of the list
    +var newList = myList.map(myFunction);
    +print(newList); 
    +
    +// Let's write another function to square a number
    +var squareNumber = function(number) {
    +  return ee.Number(number).pow(2)
    +}
    +var squares = myList.map(squareNumber)
    +print(squares)
    +
    +// Extracting value from a list
    +
    +var value = newList.get(0)
    +print(value)
    +
    +// Casting
    +
    +// Let's try to do some computation on the extracted value
    +//var newValue = value.add(1)
    +//print(newValue)
    +
    +// You get an error because Earth Engine doesn't know what is the type of 'value'
    +// We need to cast it to appropriate type first
    +var value = ee.Number(value)
    +var newValue = value.add(1)
    +print(newValue)
    +
    +// Dates
    +// For any date computation, you should use ee.Date module
    +
    +var date = ee.Date.fromYMD(2019, 1, 1)
    +var futureDate = date.advance(1, 'year')
    +print(futureDate) 
    +
    +

    Exercise

    +

    Try in Code Editor ↗

    +
    var probabilityBands = ee.List([
    +    'water', 'trees', 'grass', 'flooded_vegetation', 'crops',
    +    'shrub_and_scrub', 'built', 'bare', 'snow_and_ice'
    +    ]);
    +print(probabilityBands);
    +
    +// Exercise
    +// Sort the list 'probabilityBands' in alphabetical order
    +// Hint: Look for the function under ee.List module
    +
    +
    +
    +

    02. Reducers

    +

    Open in Code Editor ↗

    +
    // Computing stats on a list
    +var myList = ee.List.sequence(1, 10);
    +print(myList)
    +
    +// Use a reducer to compute min and max in the list
    +var mean = myList.reduce(ee.Reducer.mean());
    +print(mean);
    +
    +var geometry = ee.Geometry.Polygon([[
    +  [36.62513180012346, -1.2332928138897847],
    +  [36.62499232525469, -1.2339685738967323],
    +  [36.62524981732012, -1.234011479288199],
    +  [36.62541074986101, -1.2334322564449516]
    +]]);
    +          
    +var s2 = ee.ImageCollection("COPERNICUS/S2_HARMONIZED");
    +Map.centerObject(geometry)
    +
    +// Apply a reducer on a image collection
    +var filtered = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30))
    +  .filter(ee.Filter.date('2019-01-01', '2020-01-01'))
    +  .filter(ee.Filter.bounds(geometry))
    +  .select('B.*')
    +
    +print(filtered.size())
    +var collMean = filtered.reduce(ee.Reducer.mean());
    +print('Reducer on Collection', collMean);
    +
    +var image = ee.Image('COPERNICUS/S2_HARMONIZED/20190109T074301_20190109T074303_T36MZD')
    +var rgbVis = {min: 0.0, max: 3000, bands: ['B4', 'B3', 'B2']};
    +Map.addLayer(image, rgbVis, 'Image')
    +Map.addLayer(geometry, {color: 'red'}, 'Farm')
    +// If we want to compute the average value in each band,
    +// we can use reduceRegion instead
    +var stats = image.reduceRegion({
    +  reducer: ee.Reducer.mean(),
    +  geometry: geometry,
    +  scale: 100,
    +  maxPixels: 1e10
    +  })
    +print(stats);
    +
    +// Result of reduceRegion is a dictionary. 
    +// We can extract the values using .get() function
    +print('Average value in B4', stats.get('B4'))
    +
    +

    Exercise

    +

    Try in Code Editor ↗

    +
    var geometry = ee.Geometry.Polygon([[
    +  [82.60642647743225, 27.16350437805251],
    +  [82.60984897613525, 27.1618529901377],
    +  [82.61088967323303, 27.163695288375266],
    +  [82.60757446289062, 27.16517483230927]
    +]]);
    +          
    +var cropVis = {min: 0, max: 1, bands: ['crops']};
    +var dwImage = ee.Image('GOOGLE/DYNAMICWORLD/V1/20190223T050811_20190223T051829_T44RPR')
    +var probabilityBands = [
    +    'water', 'trees', 'grass', 'flooded_vegetation', 'crops',
    +    'shrub_and_scrub', 'built', 'bare', 'snow_and_ice'
    +    ];
    +var image = dwImage.select(probabilityBands);
    +
    +Map.addLayer(image, cropVis, 'DW Crop Probabilities')
    +Map.addLayer(geometry, {color: 'red'}, 'Farm')
    +Map.centerObject(geometry)
    +
    +
    +// Exercise
    +// The following code calculates the average probability
    +// value of each band within the farm
    +// Change it to calculate the minimum and maximum values
    +var stats = image.reduceRegion({
    +  reducer: ee.Reducer.mean(),
    +  geometry: geometry,
    +  scale: 10,
    +  maxPixels: 1e10
    +  })
    +print(stats)
    +
    +
    +
    +

    03. Computation on ImageCollections

    +

    Open in Code Editor ↗

    +
    var s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED');
    +var lsib = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017');
    +    
    +var country = 'Kenya';
    +var selected = lsib.filter(ee.Filter.eq('country_na', country));
    +var geometry = selected.geometry();
    +Map.centerObject(geometry);
    +
    +var rgbVis = {min: 0.0, max: 3000, bands: ['B4', 'B3', 'B2']};
    +
    +var filtered = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30))
    +  .filter(ee.Filter.date('2019-01-01', '2020-01-01'))
    +  .filter(ee.Filter.bounds(geometry));
    +
    +var composite = filtered.median();
    +Map.addLayer(composite.clip(geometry), rgbVis, 'Kenya Composite');
    +
    +
    +// Write a function that computes NDVI for an image and adds it as a band
    +function addNDVI(image) {
    +  var ndvi = image.normalizedDifference(['B8', 'B4']).rename('ndvi');
    +  return image.addBands(ndvi);
    +}
    +
    +// Map the function over the collection
    +var withNdvi = filtered.map(addNDVI);
    +
    +var composite = withNdvi.median();
    +
    +var ndviComposite = composite.select('ndvi');
    +
    +var palette = [
    +  'FFFFFF', 'CE7E45', 'DF923D', 'F1B555', 'FCD163', '99B718',
    +  '74A901', '66A000', '529400', '3E8601', '207401', '056201',
    +  '004C00', '023B01', '012E01', '011D01', '011301'];
    +
    +var ndviVis = {min:0, max:0.5, palette: palette };
    +Map.addLayer(ndviComposite.clip(geometry), ndviVis, 'ndvi');
    +
    +

    Exercise

    +

    Try in Code Editor ↗

    +
    var s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED');
    +var lsib = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017');
    +    
    +var country = 'Kenya';
    +var selected = lsib.filter(ee.Filter.eq('country_na', country));
    +var geometry = selected.geometry();
    +Map.centerObject(geometry);
    +
    +var rgbVis = {min: 0.0, max: 3000, bands: ['B4', 'B3', 'B2']};
    +
    +var filtered = s2.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30))
    +  .filter(ee.Filter.date('2019-01-01', '2020-01-01'))
    +  .filter(ee.Filter.bounds(geometry));
    +
    +   
    +var composite = filtered.median();
    +Map.addLayer(composite.clip(geometry), rgbVis, 'Kenya Composite');
    +
    +// This function calculates both NDVI an d NDWI indices
    +// and returns an image with 2 new bands added to the original image.
    +function addIndices(image) {
    +  var ndvi = image.normalizedDifference(['B8', 'B4']).rename('ndvi');
    +  var ndwi = image.normalizedDifference(['B3', 'B8']).rename('ndwi');
    +  return image.addBands(ndvi).addBands(ndwi);
    +}
    +
    +// Map the function over the collection
    +var withIndices = filtered.map(addIndices);
    +
    +// Composite
    +var composite = withIndices.median();
    +print(composite);
    +
    +// Extract the 'ndwi' band
    +// Clip and display a NDWI map
    +// use the palette ['white', 'blue']
    +// Hint: Use .select() function to select a band
    +
    +
    +
    +

    04. Time-Series Charts

    +

    Open in Code Editor ↗

    +
    var s2 = ee.ImageCollection('COPERNICUS/S2_HARMONIZED');
    +
    +var geometry = ee.Geometry.Polygon([[
    +  [36.62513180012346, -1.2332928138897847],
    +  [36.62499232525469, -1.2339685738967323],
    +  [36.62524981732012, -1.234011479288199],
    +  [36.62541074986101, -1.2334322564449516]]
    +]);
    +          
    +Map.addLayer(geometry, {color: 'red'}, 'Farm');
    +Map.centerObject(geometry);
    +
    +var startDate = ee.Date.fromYMD(2019, 1, 1);
    +var endDate = startDate.advance(1, 'year');
    +
    +var filtered = s2
    +  .filter(ee.Filter.date(startDate, endDate))
    +  .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 35))
    +  .filter(ee.Filter.bounds(geometry));
    +  
    +// Write a function for Cloud masking
    +function maskS2clouds(image) {
    +  var qa = image.select('QA60');
    +  var cloudBitMask = 1 << 10;
    +  var cirrusBitMask = 1 << 11;
    +  var mask = qa.bitwiseAnd(cloudBitMask).eq(0).and(
    +             qa.bitwiseAnd(cirrusBitMask).eq(0));
    +  return image.updateMask(mask)
    +      .select('B.*')
    +      .copyProperties(image, ['system:time_start']);
    +}
    +
    +var filtered = filtered.map(maskS2clouds);
    +// Write a function that computes NDVI for an image and adds it as a band
    +function addNDVI(image) {
    +  var ndvi = image.normalizedDifference(['B8', 'B4']).rename('ndvi');
    +  return image.addBands(ndvi);
    +}
    +
    +// Map the function over the collection
    +var withNdvi = filtered.map(addNDVI);
    +
    +// Display a time-series chart
    +var chart = ui.Chart.image.series({
    +  imageCollection: withNdvi.select('ndvi'),
    +  region: geometry,
    +  reducer: ee.Reducer.mean(),
    +  scale: 10
    +}).setOptions({
    +      lineWidth: 0.5,
    +      pointSize: 1,
    +      title: 'NDVI Time Series',
    +      interpolateNulls: true,
    +      vAxis: {title: 'NDVI', viewWindow: {min:0, max:1}},
    +      hAxis: {title: '', format: 'YYYY-MMM'}
    +    })
    +print(chart);
    +
    +

    Exercise

    +

    Try in Code Editor ↗

    +
    // Delete the farm boundary and add another farm at a location of your choice
    +// Print the chart.
    +
    +
    +
    +

    05. Dynamic World Time-Series charts

    +
    +Dynamic World Time-Series +

    +Dynamic World Time-Series +

    +
    +

    Open in Code Editor ↗

    +
    // Charting Class Probabilities Over Time
    +
    +var geometry = ee.Geometry.Polygon([[
    +  [36.62513180012346, -1.2332928138897847],
    +  [36.62499232525469, -1.2339685738967323],
    +  [36.62524981732012, -1.234011479288199],
    +  [36.62541074986101, -1.2334322564449516]]
    +]);
    +
    +Map.addLayer(geometry, {color: 'red'}, 'Selected Location')
    +Map.centerObject(geometry, 16)
    +
    +// Filter the Dynamic World collection for the time period and
    +// location of interest.
    +var startDate = ee.Date.fromYMD(2019, 1, 1);
    +var endDate = startDate.advance(1, 'year');
    +
    +var dw = ee.ImageCollection('GOOGLE/DYNAMICWORLD/V1')
    +  .filter(ee.Filter.date(startDate, endDate))
    +  .filter(ee.Filter.bounds(geometry))
    +
    +var probabilityBands = [
    +    'water', 'trees', 'grass', 'flooded_vegetation', 'crops',
    +    'shrub_and_scrub', 'built', 'bare', 'snow_and_ice'
    +    ];
    +
    +// Select all probability bands
    +var dwTimeSeries = dw.select(probabilityBands)
    +
    +// Plot the time series for a single class
    +var chart = ui.Chart.image.series({
    +  imageCollection: dwTimeSeries.select('crops'),
    +  region: geometry,
    +  scale: 10
    +}).setOptions({
    +      lineWidth: 0.5,
    +      pointSize: 1,
    +      title: 'Dynamic World Class Probability (Crops)',
    +      interpolateNulls: true,
    +      vAxis: {title: 'Probability', viewWindow: {min:0, max:1}},
    +      hAxis: {title: '', format: 'YYYY-MMM'},
    +      series: {
    +        0: {color: 'green'}
    +      }
    +    })
    +print(chart)
    +
    +// Plot the time series for a multiple classes
    +
    +var chart = ui.Chart.image.series({
    +  imageCollection: dwTimeSeries.select(['crops', 'shrub_and_scrub']),
    +  region: geometry,
    +  scale: 10
    +}).setOptions({
    +      lineWidth: 0.5,
    +      pointSize: 1,
    +      title: 'Dynamic World Class Probabilities',
    +      interpolateNulls: true,
    +      vAxis: {title: 'Probability', viewWindow: {min:0, max:1}},
    +      hAxis: {title: '', format: 'YYYY-MMM'},
    +      series: {
    +        0: {color: 'green'},
    +        1: {color: 'orange'}
    +      },
    +      legend: {
    +        position: 'top'
    +      }
    +    });
    +print(chart);
    +
    +

    Exercise

    +

    Try in Code Editor ↗

    +
    // Delete the farm boundary and add another farm at a location of your choice
    +// Select the probability bands to those relevant to the location
    +// Update the series colors
    +// Print the chart.
    +
    +
    +
    +

    Quiz - Module 3

    +

    This is a short quiz to test your understanding of the Module 3 +concepts.

    +

    Launch +Quiz ↗.

    +
    +
    +

    Learning Resources