I wrote some code to calculate EVI2 from Sentinel2 imagery. But, I wasn't able to make it run as the .map() function seems to not work well with an image that has multiple bands.

Error Message: img.map is not a function


// Set Study Area
var country = ['ZA'];
var geometry = ee.FeatureCollection('USDOS/LSIB/2013')
                     .filter(ee.Filter.inList('cc', country));
Map.centerObject(geometry, 5);
// Set Study Period

var startDate = '2015-09-01';
var endDate = '2016-08-31';

// Use PALSAR Dataset as Mask

var palsar = ee.ImageCollection("JAXA/ALOS/PALSAR/YEARLY/FNF")
                 .filterDate('2017-01-01', '2017-12-31')

var mask = palsar.mean().eq(1).clip(geometry);

// Compute Seasonal Composites

var step = ee.Date(startDate).advance(3, 'month').millis().subtract(ee.Date(startDate).millis());
var listStartDates = ee.List.sequence(ee.Date(startDate).millis(), ee.Date(endDate).millis(), step);

function monthlyComposite(date) {
 var S2 = ee.ImageCollection('COPERNICUS/S2')
                 .filterDate(date, date.advance(3, 'month'))
                 .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 20))
 var composite = S2.median()
                 .set('system:time_start', date.millis(), 'dateYMD', date.format('YYYY-MM-dd'), 'numbImages', S2.size());

 var maskedComposite = composite.divide(10000).clip(geometry).updateMask(mask);
 return maskedComposite;

var col = ee.ImageCollection.fromImages(listStartDates.map(function(dateMillis){
 var date = ee.Date(dateMillis);
 return monthlyComposite(date);

// Calculate EVI2
var img = ee.Image(col.toList(5).get(0));

var EVI2 = function(image) {
 var NIR = image.select('B8');
 var RED = image.select('B4');
 var EVI2 = NIR.subtract(RED).divide(NIR.add(RED).add(1)).multiply(2.4).rename('EVI2');
 return image.addBands(EVI2);

var evi2Vis = {
 min: -1,
 max: 1,
 palette: ['FFFFFF', 'CE7E45', 'DF923D', 'F1B555', 'FCD163', '99B718', '74A901',
           '66A000', '529400', '3E8601', '207401', '056201', '004C00', '023B01',
           '012E01', '011D01', '011301']

var image = img.map(EVI2);
Map.addLayer(image.select('EVI2').median(), evi2Vis, 'EVI2');
  • 1
    Here's a small tip, in case you haven't seen it already. When you're having a bit more complicated expressions, like EVI2, it is usually easier and less error prone to use an ee.Image.expression(). Like this: img.expression('2.5 * (i.nir - i.red) / (i.nir + 2.4 * i.red + 1)', {i: img}) Apr 23 '20 at 14:10
  • 1
    With your band names: img.expression('2.5 * (i.B8 - i.B4) / (i.B8 + 2.4 * i.B4 + 1)', {i: img}) Apr 23 '20 at 14:16
  • Thanks for the tip @Daniel Wiell!
    – farhat
    Apr 23 '20 at 14:31

map() is for imageCollections. Since you're dealing with a single image here, you should instead use the image as an argument when applying the function. That also affects the plotting line: since you have just one image you can't map a median (you'd need an imageCollection from which to find a median). So, replace your last 2 lines with this:

var image = EVI2(img);
Map.addLayer(image.select('EVI2'), evi2Vis, 'EVI2');

And you should be good to go for a single image. If you want to apply the function to the imageCollection ‘col’ you’ll have to put the toList line inside your EVI2 function, then use col.map(), and then Map.addLayer() as you did in your original script.

  • Thank you.....!
    – farhat
    Apr 23 '20 at 14:28

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.