2

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.

1

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);
4
  • Perfect thank you! That works well! I still have the same error for some periods of time and found out that that is because the value in B8 list is null for some dates because of a cloud mask. How could I solve it that it just skips that image or gives out the value null again? I do want to keep them in the data set so I know later that there was a cloudy image. – xdsccc Mar 26 at 14:51
  • Please, give me a point and dates where this occurs for exploring this issue. It should avoid with an If statement (By the way, I also need your mask function). – xunilk Mar 26 at 15:02
  • I added the information in the post :) – xdsccc Mar 26 at 15:16
  • I added a new code in my answer as an editing note. – xunilk Mar 27 at 0:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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