TransWikia.com

Mapping ratio function over ImageCollection in Google Earth Engine

Geographic Information Systems Asked on June 19, 2021

I am trying to map a function over an ImageCollection to receive the ratio in a polygon, how it compares to a certain point (pt) for each image. So all pixels within the polygon divided by the value at point pt.
I keep on receiving the error message "Error in map, Image.constant: Invalid Image.constant type." and cannot find a way to solve it.

I tried different codes, e.g. this one:

var maskL8 = function(image) {
  var qa = image.select('BQA');

  var mask = qa.bitwiseAnd(1 << 4).eq(0);
  return image.updateMask(mask);
}

var start = '2020-07-01';
var finish = '2020-07-30';
var pt = ee.Geometry.Point([-49.31582,69.56833]);

var l8 = ee.ImageCollection('LANDSAT/LC08/C01/T1_TOA')
.filterDate (start,finish)
.filterBounds(pt)
.filter("WRS_ROW <= 122")
.map(maskL8);

var myB8 = l8.select("B8");

//receiving the values at pt for each image

var getB8 = function(image) {

  // Reducing region and getting value
  var value_B8 = ee.Image(image)
    .reduceRegion(ee.Reducer.first(), pt)
    .get('B8');

  return value_B8;
};

var count = myB8.size();

var B8_list = l8.toList(count).map(getB8);

print("B8 list", B8_list);

//Ratio function

function  calculateRatio (image) {
  var ratio1= image.clip(polygon)
  .divide(ee.Number(image.reduceRegion(ee.Reducer.first(), pt))
    );
    return ratio1;
}


var RatioALL = myB8.map(calculateRatio);
print (RatioALL);

So I would like to receive the ratio for each image so I can afterwards get the standard deviation and the mean for each clipped image as output. Maybe it would also make more sense to first do the function and clip afterwards but both showed the error for me.
I included the code for getting the values at pt for each image in case that helps for the function.

One Answer

As you calculated pixel values in each point and put them in B8_list, you don't need to use again 'ee.Reducer' in your function. You only need to map Image Collection as follows. I assumed an arbitrary point (pt) and polygon in Spain and an arbitrary range for start and finish dates.

var pt = ee.Geometry.Point([-1.869490554037725, 41.191353356841205]);

var polygon = ee.Geometry.Polygon(
        [[[-1.8966130515963187, 41.18786546760974],
          [-1.8736104270846, 41.173136775751885],
          [-1.8413380882174124, 41.176754656054],
          [-1.8389348289400687, 41.19974936510326],
          [-1.861250807943975, 41.207498570723196],
          [-1.8732671043306937, 41.19690775979286],
          [-1.8883733055025687, 41.2000076867413]]]);

Map.addLayer(pt);

var start = '2017-01-01';
var finish = '2017-06-01';

var l8 = ee.ImageCollection('LANDSAT/LC08/C01/T1_TOA')
  .filterDate (start,finish)
  .filterBounds(pt)
  .filter("WRS_ROW <= 122");
  //.map(maskL8);

var myB8 = l8.select("B8");

//receiving the values at pt for each image

var getB8 = function(image) {

  // Reducing region and getting value
  var value_B8 = ee.Image(image)
    .reduceRegion(ee.Reducer.first(), pt)
    .get('B8');

  return value_B8;
};

var count = myB8.size();

var listOfImages = l8.toList(count);

var B8_list = listOfImages.map(getB8);

print("B8 list", B8_list);

//Ratio function

function  calculateRatio (image) {
  
  var time = ee.Image(image).get('system:time_start');
  
  var idx = ee.List(listOfImages).indexOf(image);
  
  var ratio1 = ee.Image(image).select('B8')
                              .clip(polygon)
                              .divide(ee.Number(B8_list.get(idx)));
    
    return ratio1.set('system:time_start', time);

}

print("Original Image Collection", myB8);

var RatioALL = listOfImages.map(calculateRatio);

print ("Ratio All", RatioALL);

After running above code in GEE code editor, I got following result.

enter image description here

It can be observed that each obtained image was divided by its respective point pixel value and it also has a 'system:time_start'.

Editing Note:

For avoiding nulls in B8_list you can try following code. I used my initial parameters because when I implemented mask function in my code null values also appear.

var maskL8 = function(image) {
  var qa = image.select('BQA');

  var mask = qa.bitwiseAnd(1 << 4).eq(0);
  return image.updateMask(mask);
};

var pt = ee.Geometry.Point([-1.869490554037725, 41.191353356841205]);

var polygon = ee.Geometry.Polygon(
        [[[-1.8966130515963187, 41.18786546760974],
          [-1.8736104270846, 41.173136775751885],
          [-1.8413380882174124, 41.176754656054],
          [-1.8389348289400687, 41.19974936510326],
          [-1.861250807943975, 41.207498570723196],
          [-1.8732671043306937, 41.19690775979286],
          [-1.8883733055025687, 41.2000076867413]]]);

Map.addLayer(pt);

var start = '2017-01-01';
var finish = '2017-06-01';

var l8 = ee.ImageCollection('LANDSAT/LC08/C01/T1_TOA')
  .filterDate (start,finish)
  .filterBounds(pt)
  .filter("WRS_ROW <= 122")
  .map(maskL8);

var myB8 = l8.select("B8");

//receiving the values at pt for each image

var getB8 = function(image) {

  // Reducing region and getting value
  var value_B8 = ee.Image(image)
    .reduceRegion(ee.Reducer.first(), pt)
    .get('B8');

  return value_B8;
};

var count = myB8.size();

var listOfImages = l8.toList(count);

var B8_list = listOfImages.map(getB8);

print("B8 list", B8_list);

var nonNulls = B8_list.filter(ee.Filter.neq('item', null));

print("Non Null Values", nonNulls);

var idxList = nonNulls.map(function extract (ele) {
  
  var idx1 = nonNulls.indexOf(ele);
  
  var idx2 = B8_list.indexOf(nonNulls.get(idx1)); 
  
  return idx2;
  
});

print("Indices of Non Null Values", idxList);

//Ratio function

var RatioALL = idxList.map(function  calculateRatio (ele) {
  
  var idx = ele;

  var value = ee.Number(B8_list.get(idx));
  
  var image = listOfImages.get(idx);
  
  var ratio1 = ee.Image(image).select('B8')
                              .clip(polygon)
                              .divide(value);

  var time = ee.Image(image).get('system:time_start');

  return ratio1.set('system:time_start', time);
  
});

print("Original Image Collection", myB8);

print ("Ratio All for Non Null Values", RatioALL);

Correct answer by xunilk on June 19, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP