0

I am working on creating a tool that computes a number of different vegetation indices from Landsat across the state of Montana in order to allow users to examine time series charts for user-specified regions of interest. The time series charts that I produce will sometimes contain gaps depending on the area of interest. I finally discovered that the root of the problem is that the scene footprints for Landsat 8 scenes seem to have a buffer, such that when using filterBounds() on the Landsat Collection, scenes are selected that do not actually intersect the ROI.

I know that I could ask the time series chart to interpolateNulls and resolve the gap issue but I am looking for a different solution that will filter the image collection correctly. Is there a way to adapt the filterBounds() or something else, or is my only option to use interploateNulls in the time series chart, and add a disclaimer that the number of items in the filtered collection may not be the number of items used to create the chart, as some scenes were incorrectly selected?

The code below should provide two example scenes (not shown) and footprints (shown) that were selected incorrectly from the same path/row but are not in the exact same position.


var focal = ee.Geometry.Point([-113.73000021508153,47.74518351973251])

var ROI = ee.Geometry.Polygon([
  [[-113.87208186611228,47.745204340758626],
  [-113.73097621425681,47.745204340758626],
  [-113.73097621425681,47.91023776436756],
  [-113.87208186611228,47.91023776436756],
  [-113.87208186611228,47.745204340758626]]
]);

Map.addLayer(ROI)
Map.centerObject(focal, 14)
// // to download imagery with this script simply create an ROI using the GEE geometry tools and rename it 'ROI'

var startDate = '2017-01-01' // set start date
var endDate = '2018-12-31' // set end date
var cloudMax = 15 // set max percentage of clouds per scene

var addNDVI = function(image) {
  var ndvi = image.normalizedDifference(['B5', 'B4']).rename('NDVI');
  return image.addBands(ndvi);
};

var ndvi_toa = ee.ImageCollection("LANDSAT/LC08/C01/T1_TOA")
  .filter(ee.Filter.lt('CLOUD_COVER', cloudMax))
  .filterBounds(ee.Geometry(ROI))
  .filterDate(startDate,endDate)
  .sort('system:time_start')
  .map(addNDVI)
  .select('NDVI');

print(ndvi_toa);

var chart_toa = ui.Chart.image
                      .series({
                        imageCollection:ndvi_toa,
                        region: ROI,
                        reducer: ee.Reducer.mean(),
                        scale: 30,
                        xProperty: 'system:time_start'
                      })
                      .setOptions({
                        titlePostion: 'none',
                        legend: {position: 'middle-right'},
                        hAxis: {title: 'Date'},
                        vAxis: {title: 'TOA'},
                        series: {0: {color: '23cba7'}},
                        interpolateNulls: false
                      });

print(chart_toa);

// incorrectly selected image from 2018-07-07
var badImage = ndvi_toa.filterDate('2018-07-07','2018-07-08').first()
print(badImage)
Map.addLayer({eeObject: badImage, name: 'badImage 2018-07-07', shown: false});
// image footprint which shows the reason for selection
var fp = ee.Geometry(badImage.get('system:footprint'))
Map.addLayer({eeObject: fp, name: 'fp 2018-07-07'})

var badImage2 = ndvi_toa.filterDate('2017-07-20','2017-07-21').first()
print(badImage2)
Map.addLayer({eeObject: badImage2, name: 'badImage2 2017-07-20', shown: false})

var fp2 = ee.Geometry(badImage2.get('system:footprint'))
Map.addLayer({eeObject: fp2, name: 'fp2 2017-07-20'})

1 Answer 1

2

You can manually process the chart data to remove missing values using the following approach:

  1. Convert the image collection to a set of features (which may contain null values for the property of interest);
  2. Filter the list to remove elements (features) that have null values for the property of interest;
  3. Create a feature collection, and use a ui.Chart helper function to construct a chart

Here is the additional code:

// Copyright 2020 Google LLC.
// SPDX-License-Identifier: Apache-2.0

// Convert the image collection to a list of features.
var maxFeatures = 1000;
var data = ndvi_toa.toList(maxFeatures).map(
  function (img) {
    img = ee.Image(img);
    var meanValues = img.reduceRegion({
      reducer: ee.Reducer.mean(),
      geometry: ROI,
      scale: 30
    });
    return ee.Feature(img).select(['system:time_start']).set(meanValues);
  }
);

// Define a property
var prop='NDVI'

// Remove features with missing NDVI values.
data = data.filter(ee.Filter.notNull([prop]));



// Display the time series chart.
var chart_toa_new = ui.Chart.feature.byFeature({
  features: ee.FeatureCollection(data),
  xProperty: 'system:time_start',
  yProperties: prop
});
print(chart_toa_new);

Here is an example of the chart output:

Example chart with missing values removed

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.