Google Earth Engine Error – User Memory Limit Exceeded When Generating Chart

google-earth-enginegoogle-earth-engine-javascript-apimemory

I want to make a scatter plot between a list of NDVI values and LST values. I've tried it all. I think is a lack of best practices in my code.

Here's my script:

var LST = ee.ImageCollection("MODIS/061/MOD11A1")
var NDVI_Unmasked = ee.ImageCollection("MODIS/061/MOD13A2")
var geometry = ee.Geometry.Polygon([[
      [-58.27563501908931, -16.339490377818237],
      [-58.27563501908931, -18.727789465180184],
      [-55.50708033158931, -18.727789465180184],
      [-55.50708033158931, -16.339490377818237]
]])

var NDVI_Unmasked = ee.ImageCollection("MODIS/061/MOD13A2")
  .select('NDVI')
  .filter(ee.Filter.date('2019-01-01', '2019-01-31'))
  .map(function(img) {
    return img.clip(geometry)
  })
  .mean()

var NDVI_mask = NDVI_Unmasked.gt(-32767)
var self_NDVI_Mask = NDVI_mask.selfMask()

var LST = ee.ImageCollection("MODIS/061/MOD11A1")
  .select('LST_Day_1km')
  .filter(ee.Filter.date('2019-01-01', '2019-01-31'))
  .map(function(img) {
    return img.clip(geometry)
      .multiply(0.02)
      .subtract(273.15)
      .copyProperties(img, ['system:time_start'])
  })
  .mean()
  .updateMask(self_NDVI_Mask)
var LST_mask = LST.gt(-273.14)

var self_LST_Mask = LST_mask.selfMask()

var NDVI = NDVI_Unmasked.updateMask(self_LST_Mask)
var pixelValsNDVI = NDVI.reduceRegion({
  reducer: ee.Reducer.toList(),
  geometry: geometry,
  scale: 0.02,
  maxPixels: 10e11,
  bestEffort: true
})

var pixelValsLST = LST.reduceRegion({
  reducer: ee.Reducer.toList(),
  geometry: geometry,
  scale: 0.02,
  maxPixels: 10e11,
  bestEffort: true
})
var x = ee.List(pixelValsNDVI.get('NDVI'))
var y = ee.List(pixelValsLST.get('LST_Day_1km'))

var zip = x.zip(y)
  .distinct()

var unzip = zip.unzip()

var x1 = unzip.get(0)
var y1 = unzip.get(1)

var chart = ui.Chart.array.values({
  array: y1,
  axis: 0,
  xLabels: x1
})
print(chart)

https://code.earthengine.google.com/a80f874d90cb03bebf3acea8e79ba23e

Best Answer

It runs out of memory because you run reduceRegion(), extracting a list of all pixels within an area of tens of thousands of square kilometers, at a scale of 2 cm. You are trying to put 10e11 (you end up with maxPixels since you use bestEffort) into a list and run out of memory as a result. Maybe you mixed up the unit of the scale parameter in reduceRegion()? It's in meters. Your imagery has a scale of 1km, so there's no need to have the scale smaller than that.

I would approach this differently, not try to chart all pixels, but a random sample?

var geometry = ee.Geometry.Polygon([[
      [-58.27563501908931, -16.339490377818237],
      [-58.27563501908931, -18.727789465180184],
      [-55.50708033158931, -18.727789465180184],
      [-55.50708033158931, -16.339490377818237]
]])

var NDVI = ee.ImageCollection("MODIS/061/MOD13A2")
  .select('NDVI')
  .filter(ee.Filter.date('2019-01-01', '2019-01-31'))
  .mean()
    
var LST = ee.ImageCollection("MODIS/061/MOD11A1")
  .select('LST_Day_1km')
  .filter(ee.Filter.date('2019-01-01', '2019-01-31'))
  .mean()
  .multiply(0.02)
  .subtract(273.15)

var means = NDVI.updateMask(NDVI.gt(-32767))
  .addBands(
    LST.updateMask(LST.gt(-273.14))
  )
  .clip(geometry)

var samples = means.sample({
  region: geometry, 
  scale: 1000, 
  numPixels: 1000 // Control how many pixels you want to sample
})


var chart = ui.Chart.feature.byFeature({
  features: samples, 
  xProperty: 'NDVI', 
  yProperties: 'LST_Day_1km'
}).setOptions({
  title: 'Temperature Vegetation Dryness Index',
  colors: ['cf513e'],
  hAxis: {
    title: 'NDVI',
    titleTextStyle: {italic: false, bold: true}
  },
  vAxis: {
    title: 'LST',
    titleTextStyle: {italic: false, bold: true}
  },
  pointSize: 4,
  lineSize: 0,
  dataOpacity: 0.4,
  legend: {position: 'none'}
})

https://code.earthengine.google.com/efdfab5de7d4c5ddb6d7baa4076f6301