1

I am trying to composite S2 images by different technique but the composites for the 25 and 33 percentiles (ee.Reducer.percentile([XX])) its giving an error :

p33: Layer error: Image.select: Pattern 'B2' did not match any bands.
p25: Layer error: Image.select: Pattern 'B2' did not match any bands.

This is the code I'm using:

//Se define la variable del CPC determinado y extent
var fires = table
//********************************************************************************************************//
//Extensión del raster en que se desea descargar los indices (metros a partir del CPC)
var extent_raster = 10000 ;
var b5km_fires = fires.geometry().buffer(extent_raster); 
    b5km_fires = b5km_fires.bounds();

//1.- Indicar Zona UTM a la que corresponde el CPC
var Zona_utm = '13'; // ---> INDICAR ZONA UTM EN DOS DIGITOS (p.e. 11,12,13,14,15,16)
//2.- Fechas de inicio y término en AAAA-MM-DD (AAAA = 4 digitos año, MM = 2 para el mes y DD = 2 para el dia)
var FECHA_INICIO =  ee.Date(fires.aggregate_first('FECHA_INI'));// ---> INDICAR FECHA DE **INICIO** DEL INCENDIO
var FECHA_TERMINO = ee.Date(fires.aggregate_first('FECHA_TER')); // ---> INDICAR FECHA DE **TERMINO** DEL INCENDIO
//3.- Se define el periodo de análisis entre pre y post
var dw = 30; // ---> INDICAR NÚMERO DE DÍAS del COMPUESTO PRE Y POST (30,60,90)
//4.- Indicar el nombre de la carpeta donde se van a guardar los raster (se debe crear primero en su drive) (L204)
var carpeta = 'incendios';

  //Fecha del periodo PRE a partir del atributo "FECHA_INI" en el CPC
var prefire_end = ee.Date(FECHA_INICIO); 
var prefire_start = prefire_end.advance(-dw,'day');
  //Fecha del periodo POST a partir del atributo "FECHA_TER" en el CPC
var postfire_start = ee.Date(FECHA_TERMINO);
var postfire_end =  postfire_start.advance(dw,'day');
  //Nombre del incendio
  print(ee.String('Incendio: ').cat(ee.String(fires.aggregate_first("ID_CPC"))));
  print(ee.String('Zona UTM seleccionada: ').cat(ee.String(Zona_utm)));
  //Fechas en que ocurrio el incendio y días de los periodos pre y post
  print(ee.String('Ocurrió entre: ').cat(prefire_end.format('YYYY-MM-dd', null)).cat(' y ').cat(postfire_start.format('YYYY-MM-dd', null)));
  print(ee.String('Ventana de días (pre y post): ').cat(ee.Number(dw)).cat(' días'));
  print(ee.String('Periodo pre: ').cat(prefire_start.format('YYYY-MM-dd', null)).cat(' a ').cat(prefire_end.format('YYYY-MM-dd', null)));
  print(ee.String('Periodo post: ').cat(postfire_start.format('YYYY-MM-dd', null)).cat(' a ').cat(postfire_end.format('YYYY-MM-dd', null)));
//========================================================================================================
//Function to mask clouds using the Sentinel-2 QA band
function maskS2clouds(image) {
  var qa = image.select('QA60');

  // Bits 10 and 11 are clouds and cirrus, respectively.
  var cloudBitMask = 1 << 10;
  var cirrusBitMask = 1 << 11;

  // Both flags should be set to zero, indicating clear conditions.
  var mask = qa.bitwiseAnd(cloudBitMask).eq(0)
      .and(qa.bitwiseAnd(cirrusBitMask).eq(0));

  return image.updateMask(mask).divide(10000)
  .copyProperties(image, ['system:time_start']);
}

var s2_clear_sky = function(image){
  // 1.Locate SCL product
  var B1Band = image.select('B1');
  var scl = image.select('SCL');
  // 2.Apply mask to the image
  // Select values: 
  var wantedPixels = scl.eq(4)        //Vegetation
                 .or(scl.eq(5))       //Not vegetated
                 .or(scl.eq(7))       //Unclassified    
                 .or(B1Band.lt(2000))
  ;
  return image.updateMask(wantedPixels)
   .copyProperties(image, ['system:time_start']);
};

// This is the Sentinel 2 collection (all the possible available Sentinel-2 imagery)
var S2SR = ee.ImageCollection('COPERNICUS/S2_SR_HARMONIZED')
            .filterBounds(b5km_fires)
            .filterDate(prefire_start, postfire_end)
            .map(maskS2clouds);

var S2_collection = S2SR.map(s2_clear_sky);

// Bands that we want to be displayed
var S2_bands = ['B2','B3','B4','B5','B6','B7','B8','B8A','B11','B12'];

// This turns the whole S2 collection into one image, finding the middle value for each pixel
var S2pr_min = S2_collection.filterDate(prefire_start, prefire_end).sort('GENERATION_TIME', false)
          .min().select(S2_bands).clip(b5km_fires);
var S2pr_ave = S2_collection.filterDate(prefire_start, prefire_end).sort('GENERATION_TIME', false)
          .mean().select(S2_bands).clip(b5km_fires);
var S2pr_p33 = S2_collection.filterDate(prefire_start, prefire_end).sort('GENERATION_TIME', false).reduce(ee.Reducer
          .percentile([33])).select(S2_bands).clip(b5km_fires);
var S2pr_p25 = S2_collection.filterDate(prefire_start, prefire_end).sort('GENERATION_TIME', false).reduce(ee.Reducer
          .percentile([25])).select(S2_bands).clip(b5km_fires);


// This controls how we want the S2 image to be displayed
var visualization = {
  min: 0.0,
  max: 0.3,
  bands: ['B8', 'B4', 'B3'],
};

Map.addLayer(S2pr_min, visualization,'min');
Map.addLayer(S2pr_ave, visualization,'ave', false);
Map.addLayer(S2pr_p33, visualization,'p33', false);
Map.addLayer(S2pr_p25, visualization,'p25', false);

//Establecer parametros de simbología para el CPC
var cpcVis = fires.style({
  color: '0000FF',
  width: 5,
  fillColor: '00000000',  // relleno transparente
  lineType: 'solid'
});

// This automatically pans the map to the middle of our area of interest
Map.centerObject(b5km_fires);
Map.addLayer(cpcVis, null, 'CPC'); //Agregar a "layers" en el visualizador el CPC (var "fires")

2 Answers 2

0

Please, include a link to your script in the code editor in future questions (using the Get Link button). Here, we're missing table, and that required some useless effort on my part to get this running.

The error message is pretty spot on - the problem is that you're selecting band names that doesn't exist. The percentile reducer appends _p33 and _p25 to your band names.

print(
  S2_collection
    .filterDate(prefire_start, prefire_end).sort('GENERATION_TIME', false)
    .reduce(ee.Reducer.percentile([33]))
    .bandNames()
)

Another improvement you could make is to combine the reducers and have the collection reduced in a single operation. Performance will be better. It could look something like this:

var reduced = S2_collection
  .filterDate(prefire_start, prefire_end)
  .select(S2_bands)
  .reduce(
    ee.Reducer.min()
      .combine(ee.Reducer.mean(), null, true)
      .combine(ee.Reducer.percentile([25, 33]), null, true)
  )

var S2pr_min = reduced.select('.*_min').rename(S2_bands)
var S2pr_ave = reduced.select('.*_mean').rename(S2_bands)
var S2pr_p33 = reduced.select('.*_p33').rename(S2_bands)
var S2pr_p25 = reduced.select('.*_p25').rename(S2_bands)

https://code.earthengine.google.com/7f4102a5d2ebeb1458a70fd73d8cb9b4

2
0

That is the error you get if select after a reducer.

After a reducer, the layers change the name. i.e. a mean reducer may turn B8 to B8_mean.

So select before the reducer, and you will be good!

For example, in your code:

var S2pr_min = S2_collection.filterDate(prefire_start, prefire_end).sort('GENERATION_TIME', false)
          .min().select(S2_bands).clip(b5km_fires);

After .min() the select(S2_bands) will give you an error. Maybe define a new S2_bands_min and it should have _min after all the elements in S2_bands.

I hope it helps!

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.