0

I am trying to calculate SAVI vegetation index using MODIS data. But I am getting an error showing:

Image.select: Pattern 'B2' did not match any bands.

Code:

countries = ee.FeatureCollection("USDOS/LSIB_SIMPLE/2017")
canada = countries.filter(ee.Filter.eq("country_na", "Canada"))
image = ee.ImageCollection("MODIS/061/MOD09A1")\
            .filterDate('2017-01-01','2017-12-31')\
            .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE',10))\
            .filterBounds(canada)\
            .median()\
            .clip(canada)

savi = image.expression(
    '1.5*((NIR-RED)/(NIR+RED+0.5))',{
        'NIR':image.select('B2'),
        'RED':image.select('B1')
    }).rename('savi')

saviVis = {'min':0.0, 'max':1, 'palette':['yellow', 'green']}
Map = geemap.Map()
Map.addLayer(savi, saviVis, 'SAVI')
Map

Why am I getting this error? Isn't B1 designated to Red and B2 to NIR?

user14
  • 59
  • 1
  • 10

1 Answers1

2

The general thing to do when you hit this type of problem is to start examining the dataset for what is actually there — how many images are you matching, what properties and bands those images have, etc. I found two problems:

  1. Your filter criteria matched zero images. Therefore the collection is empty, and therefore the median() image from that collection has no bands at all. (You can check this by putting the collection in a variable and printing the size() of it.) You will need to adjust the criteria.

    It seems that the main reason they didn't match is that the images in MODIS/061/MOD09A1 do not have a CLOUDY_PIXEL_PERCENTAGE property.

  2. The band names for MODIS/061/MOD09A1 are not B1, B2, ... but sur_refl_b01, sur_refl_b02 and so on. You can see this with the Inspector in the Earth Engine Code Editor, or on the dataset description page.

Perhaps you were working from information about a different dataset?

With the two problems above fixed, your code produces some results. This is the (JS) version I produced while testing (Code Editor link):

var countries = ee.FeatureCollection("USDOS/LSIB_SIMPLE/2017");
var canada = countries.filter(ee.Filter.eq("country_na", "Canada"));
var images = ee.ImageCollection("MODIS/061/MOD09A1")
            .filterDate('2017-01-01','2017-12-31')
            // .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE',10))
            .filterBounds(canada);
// print(images);
var image = images.median().clip(canada);

Map.addLayer(canada);
Map.addLayer(image);

var savi = image.expression(
    '1.5*((NIR-RED)/(NIR+RED+0.5))',{
        'NIR':image.select('sur_refl_b02'),
        'RED':image.select('sur_refl_b01')
    }).rename('savi');

var saviVis = {'min':0.0, 'max':1, 'palette':['yellow', 'green']};
Map.addLayer(savi, saviVis, 'SAVI')
Kevin Reid
  • 37,492
  • 13
  • 80
  • 108
  • I was working with Sentinel dataset then I shifted to MODIS for some reason. I did not have any idea that MODIS does not have CLOUDY_PIXEL_PERCENTAGE property. This was causing issues and yes the band names too. I have fixed these two and now it's working fine. How do we specify the Cloud percentage in MODIS then? – user14 Nov 27 '22 at 19:06
  • @user14 Every individual data set has its own provided properties. Cloudiness isn't an inherently known fact — it's something the data provider chooses to provide an _estimate_ of, or not. If there isn't such data then you have to build something to compute it yourself. Detecting clouds can be a quite hard problem — there is no simple solution that works everywhere. – Kevin Reid Nov 27 '22 at 23:32