1

I'm not an expert in GEE so I'm relying on pre-compiled scripts that I modify a little at a time. My goal is this: to make a plot in which I compare the time series of agricultural areas and natural grasslands. With the attached script I produce only a plot of a single polygon that I draw. But how can I insert more polygons and differentiate the plots?

        // Apply negative buffer to geometry
var geometryBuff = geometry.buffer(-20)
// Add plot and buffer to the map
// and specify fill color and layer name
Map.addLayer(geometry,{color:'green'},'Border');
Map.addLayer(geometryBuff,{color:'red'},'Buffer');

// Center map on the plot
Map.centerObject(geometry);
// Load image collection of Sentinel-2 imagery
// (choose SR for atmospheric corrections to surface reflectance)
var S2 = ee.ImageCollection('COPERNICUS/S2_SR') 
  // Remove cloudy images from the collection
  .filterMetadata('CLOUDY_PIXEL_PERCENTAGE', 'less_than', 20)
  // Filter to study period
  .filterDate('2019-09-01', '2020-10-01')
  // Filter to plot boundaries
  .filterBounds(geometryBuff);
  // Function to keep only vegetation and soil pixels
function keepFieldPixel(image) {
  // Select SCL layer
  var scl = image.select('SCL'); 
  // Select vegetation and soil pixels
  var veg = scl.eq(4); // 4 = Vegetation
  var soil = scl.eq(5); // 5 = Bare soils
  // Mask if not veg or soil
  var mask = (veg.neq(1)).or(soil.neq(1));
  return image.updateMask(mask);
}

// Apply custom filter to S2 collection
var S2 = S2.map(keepFieldPixel);
// Filter defined here: 
// https://developers.google.com/earth-engine/datasets/catalog/COPERNICUS_S2_SR#description

function maskS2clouds(image) {
  var qa = image.select('QA60');

  // Bits 10 and 11 are clouds and cirrus, respectively.
  var cloudBitMask = 1 << 10;
  var cirrusBitMask = 1 << 11;

  // Both flags should be set to zero, indicating clear conditions.
  var mask = qa.bitwiseAnd(cloudBitMask).eq(0)
      .and(qa.bitwiseAnd(cirrusBitMask).eq(0));

  return image.updateMask(mask);
}

  
  // Function to compute NDVI and add result as new band
var addNDVI = function(image) {
return image.addBands(image.normalizedDifference(['B8', 'B4']));
};

// Add NDVI band to image collection
var S2 = S2.map(addNDVI);
var evoNDVI = ui.Chart.image.seriesByRegion(
  S2,                // Image collection
  geometryBuff,      // Region
  ee.Reducer.mean(), // Type of reducer to apply
  'nd',              // Band
  10);               // Scale
var plotNDVI = evoNDVI                    // Data
    .setChartType('LineChart')            // Type of plot
    .setSeriesNames(['SCL filter only'])
    .setOptions({                         // Plot customization
      interpolateNulls: true,
      lineWidth: 1,
      pointSize: 3,
      title: 'NDVI annual evolution',
      hAxis: {title: 'Date'},
      vAxis: {title: 'NDVI'}
});
// Apply second filter
var S2 = S2.map(maskS2clouds);

// Plot results
var plotNDVI = ui.Chart.image.seriesByRegion(
  S2, 
  geometryBuff,
  ee.Reducer.mean(),
  'nd',10)
  .setChartType('LineChart')
  .setSeriesNames(['After cloud filter'])
  .setOptions({
    interpolateNulls: true,
    lineWidth: 1,
    pointSize: 3,
    title: 'NDVI annual evolution',
    hAxis: {title: 'Date'},
    vAxis: {title: 'NDVI'},
    series: {0:{color: 'red'}}
  });
  
print(plotNDVI)
3

1 Answer 1

0

You can plot NDVI time series data by turning multiple geometries into a feature collection and using that feature collection in your "regions" section of the ui.Chart.image.seriesByRegion function instead of calling geometryBuff.

Main modifications are as follows:

//Convert gometries into Feature Collection
var regions = ee.FeatureCollection([
  ee.Feature(g1,{label : 'g1'}), // geometry 1
  ee.Feature(g2,{label : 'g2'}), // geometry 2
  ee.Feature(g3,{label : 'g3'})] // geometry 3
  );

AND

// Plot results
var plotNDVI = ui.Chart.image.seriesByRegion(
  S2, 
  regions, //use the regions feature collection here instead of geometryBuff
  ee.Reducer.mean(),
  'nd',10)
  .setChartType('LineChart')
  .setSeriesNames(['geometry 1', 'geometry 2', 'geometry 3'])
  .setOptions({
    interpolateNulls: true,
    lineWidth: 1,
    pointSize: 3,
    title: 'NDVI annual evolution',
    hAxis: {title: 'Date'},
    vAxis: {title: 'NDVI'},
    series: {0:{color: 'red'}
    }
  });

Here is a link to example code where I modified your script to include two more geometries in nearby areas: https://code.earthengine.google.com/6b58cf2fe3a7b247f7a2c1ac7cdb6736

1
  • In your code editor, line 36 "var mask = (veg.neq(1)).or(soil.neq(1));". Shouldn't it be "var mask = (veg.eq(1)).or(soil.eq(1));"? So that pixels are either veg or soil have mask value of 1 and others have 0 (become transparent in updateMask)?
    – dgg32
    Aug 6, 2022 at 7:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.