1

I'm looking to clip the cloud mask function (top of my code) to the AOI. For some reason, my other layers (dNDVI and RGB) work for the AOI, but my cloud mask doesn't apply to it. I've tried putting in the ee.Image.clip function but I couldn't get it to work.

I would love to have some insight as to why it won't apply for this specific layer. Very new to coding!

// --------- Cloud mask: -----------------

var mask_all = function(image) {
      var hollstein_mask = cld.hollstein_S2(['shadow', 'cloud', 'cirrus'])(image);
      return hollstein_mask;
    };

var color = "#98ff00";
var AOI =  ee.Geometry.Polygon(
 [[[140.88237590701584,-37.896469860299604],
 [140.96546001346115,-37.896469860299604],
 [140.96546001346115,-37.83819826191272],
 [140.88237590701584,-37.83819826191272],
 [140.88237590701584,-37.896469860299604]]], null, false);
/*        [[[140.5710269570096,-37.669974265519755],
          [140.64037815329866,-37.669974265519755],
          [140.64037815329866,-37.60037237657578],
          [140.5710269570096,-37.60037237657578],
          [140.5710269570096,-37.669974265519755]       */

//load images for composite
var Sen2mosaic = ee.ImageCollection("COPERNICUS/S2_SR");
ee.Geometry.Polygon(140.88237590701584,-37.896469860299604);


var getQABits = function(image, start, end, newName) {
    // Compute the bits we need to extract.
    var pattern = 0;
    for (var i = start; i <= end; i++) {
       pattern += Math.pow(2, i);
    }
    // Return a single band image of the extracted QA bits, giving the band
    // a new name.
    return image.select([0], [newName])
                  .bitwiseAnd(pattern)
                  .rightShift(start);
};

// A function to mask out cloudy pixels.
var cloud_shadows = function(image) {
  // Select the QA band.
  var QA = image.select(['B8', 'B11', 'B4']);
  // Get the internal_cloud_algorithm_flag bit.
  return getQABits(QA, 3,3, 'cloud_shadows').eq(0);
  // Return an image masking out cloudy areas.
};

// A function to mask out cloudy pixels.
var clouds = function(image) {
  // Select the QA band.
  var QA = image.select(['B8', 'B11', 'B4']);
  // Get the internal_cloud_algorithm_flag bit.
  return getQABits(QA, 5,5, 'Cloud').eq(0);
  // Return an image masking out cloudy areas.
};

var maskClouds = function(image) {
  var cs = cloud_shadows(image);
  var c = clouds(image);
  image = image.updateMask(cs);
  return image.updateMask(c);
};



// --------- Input: ------------------------------------

var startDate = ee.Date('2018-12-31') //2016-09-15');
var endDate = ee.Date('2021-06-01');


var AOI = 
    ee.Geometry.Polygon(
 [[[140.88237590701584,-37.896469860299604],
 [140.96546001346115,-37.896469860299604],
 [140.96546001346115,-37.83819826191272],
 [140.88237590701584,-37.83819826191272],
 [140.88237590701584,-37.896469860299604]]], null, false);
/*        [[[140.5710269570096,-37.669974265519755],
          [140.64037815329866,-37.669974265519755],
          [140.64037815329866,-37.60037237657578],
          [140.5710269570096,-37.60037237657578],
          [140.5710269570096,-37.669974265519755]       */
          
          
//Map.addLayer(AOI, {}, 'AOI', true);  
Map.centerObject(AOI, 13);

var imageStartDate1 = startDate.advance(-30,"day");
var imageStartDate2 = startDate.advance(30,"day");
var imageEndDate1   = endDate.advance(-30,"day");
var imageEndDate2   = endDate.advance(30,"day");

var imagery = ee.ImageCollection("COPERNICUS/S2_SR"); 
//S2-SR: COPERNICUS/S2_SR //LANDSAT/LC08/C01/T1_SR
var Sen2 = ee.ImageCollection(imagery
    // Filter by dates.
    .filterDate(imageStartDate1, imageStartDate2)
    // Filter by location.
    .filterBounds(AOI));  

var Sen2end = ee.ImageCollection(imagery
    // Filter by dates.
    .filterDate(imageEndDate1, imageEndDate2)
    // Filter by location.
    .filterBounds(AOI)); 

var Sen2mosaic = Sen2.mosaic().clip(AOI);
var Sen2mosaicEnd = Sen2end.mosaic().clip(AOI);

//print("Sen2mosaic", Sen2mosaic);
var composite_free = Sen2end.map(maskClouds);
var visParams = {bands:['B8', 'B11', 'B4'], min:0, max:5000};
Map.addLayer(composite_free.first(), visParams, 'cloud mask');

// Create the NDVI and NDWI spectral indices.
var ndvi = Sen2mosaic.normalizedDifference(['B8', 'B4']);
var ndwi = Sen2mosaic.normalizedDifference(['B3', 'B8']);
var ndviEnd = Sen2mosaicEnd.normalizedDifference(['B8', 'B4']);
var ndwiEnd = Sen2mosaicEnd.normalizedDifference(['B3', 'B8']);

// Create some binary images from thresholds on the indices.
// This threshold is designed to detect bare land.
var bare1 = ndvi.lt(0.2).and(ndwi.lt(0.3));
var bare1End = ndviEnd.lt(0.2).and(ndwiEnd.lt(0.3));
// This detects bare land with lower sensitivity. It also detects shadows.
var bare2 = ndvi.lt(0.2).and(ndwi.lt(0.8));
var bare2End = ndviEnd.lt(0.2).and(ndwiEnd.lt(0.8));

// Define visualization parameters for the spectral indices.
var ndviViz = {min: -1, max: 1, palette: ['FF0000', '00FF00']};
var ndwiViz = {min: 0.5, max: 1, palette: ['00FFFF', '0000FF']};

// Mask and mosaic visualization images.  The last layer is on top.
var thematic = ee.ImageCollection([
  // NDWI > 0.5 is water.  Visualize it with a blue palette.
  ndwi.updateMask(ndwi.gte(0.5)).visualize(ndwiViz),
  // NDVI > 0.2 is vegetation.  Visualize it with a green palette.
  ndvi.updateMask(ndvi.gte(0.2)).visualize(ndviViz),
  // Visualize bare areas with shadow (bare2 but not bare1) as gray.
  bare2.updateMask(bare2.and(bare1.not())).visualize({palette: ['AAAAAA']}),
  // Visualize the other bare areas as white.
  bare1.updateMask(bare1).visualize({palette: ['FFFFFF']}),
]).mosaic();

var thematicEnd = ee.ImageCollection([
  ndwiEnd.updateMask(ndwiEnd.gte(0.5)).visualize(ndwiViz),
  ndviEnd.updateMask(ndviEnd.gte(0.2)).visualize(ndviViz),
  bare2End.updateMask(bare2End.and(bare1.not())).visualize({palette: ['AAAAAA']}),
  bare1End.updateMask(bare1End).visualize({palette: ['FFFFFF']}),
]).mosaic();

//Map.addLayer(thematic, {}, 'thematic', false);
//Map.addLayer(thematicEnd, {}, 'thematic end', false);
//Map.addLayer(ndvi, {}, 'NDVI', false);
//Map.addLayer(ndviEnd, {}, 'NDVI end', false);


var Band_R = Sen2mosaic.expression('RED / count',   {'RED': Sen2mosaic.select('B4'),   count : Sen2.size()});
var Band_G = Sen2mosaic.expression('GREEN / count', {'GREEN': Sen2mosaic.select('B3'), count : Sen2.size()});
var Band_B = Sen2mosaic.expression('BLUE / count', {'BLUE': Sen2mosaic.select('B2'),   count : Sen2.size()});

var Band_Rend = Sen2mosaicEnd.expression('RED / count',   {'RED': Sen2mosaicEnd.select('B4'),   count : Sen2.size()});
var Band_Gend = Sen2mosaicEnd.expression('GREEN / count', {'GREEN': Sen2mosaicEnd.select('B3'), count : Sen2.size()});
var Band_Bend = Sen2mosaicEnd.expression('BLUE / count', {'BLUE': Sen2mosaicEnd.select('B2'),   count : Sen2.size()});

var image_RGB = Band_R.addBands(Band_G).addBands(Band_B);
var image_RGBend = Band_Rend.addBands(Band_Gend).addBands(Band_Bend);

var image_viz_params = {
    //'bands': ['B5', 'B4', 'B3'],
    'min': 2,
    'max': 240,
    gamma: 1.5,
    //'gamma': [0.95, 1.1, 1]
};

Map.addLayer(image_RGB, image_viz_params, 'RGB 12/2018', false);
Map.addLayer(image_RGBend, image_viz_params, 'RGB 12/2020', false);

var dNDVI = ndviEnd.subtract(ndvi);

// Scale product to USGS standards
var dNDVIscaled = dNDVI.multiply(1000);

// Add the difference image to the console on the right
print("Difference Normalized Difference Vegetation Index: ", dNDVI);

//--------------------------- NDVI Product - classified -------------------------------

// Define an SLD style of discrete intervals to apply to the image.
var sld_intervals =
  '<RasterSymbolizer>' +
    '<ColorMap type="intervals" extended="false" >' +
      '<ColorMapEntry color="#ff1b1b" quantity="-250" label="-250" />' +
      '<ColorMapEntry color="#ffa81b" quantity="-100" label="-100" />' +
      '<ColorMapEntry color="#f5ff1b" quantity="250" label="250" />' +
      '<ColorMapEntry color="#1bff2f" quantity="500" label="500" />' +
      '<ColorMapEntry color="#099b16" quantity="1000" label="1000" />' +
    '</ColorMap>' +
  '</RasterSymbolizer>';

Map.addLayer(dNDVIscaled.sldStyle(sld_intervals), {}, 'dNDVI classified');

//==========================================================================================
//                                    ADD A LEGEND

// set position of panel
var legend = ui.Panel({
  style: {
    position: 'bottom-left',
    padding: '8px 15px'
  }});
 
// Create legend title
var legendTitle = ui.Label({
  value: 'dNDVI Classes',
  style: {fontWeight: 'bold',
    fontSize: '18px',
    margin: '0 0 4px 0',
    padding: '0'
    }});
 
// Add the title to the panel
legend.add(legendTitle);
 
// Creates and styles 1 row of the legend.
var makeRow = function(color, name) {
 
      // Create the label that is actually the colored box.
      var colorBox = ui.Label({
        style: {
          backgroundColor: '#' + color,
          // Use padding to give the box height and width.
          padding: '8px',
          margin: '0 0 4px 0'
        }});
 
      // Create the label filled with the description text.
      var description = ui.Label({
        value: name,
        style: {margin: '0 0 4px 6px'}
      });
 
      // return the panel
      return ui.Panel({
        widgets: [colorBox, description],
        layout: ui.Panel.Layout.Flow('horizontal')
      })};
 
//  Palette with the colors
var palette =['ff1b1b', 'ffa81b', 'f5ff1b', '1bff2f', '099b16', 'ffffff'];
 
// name of the legend
var names = ['Forest Loss, High Probability', 'Forest Loss', 'Unchanged', 'Forest Gain, Low', 'Forest Gain, High Probability'];
 
// Add color and and names
for (var i = 0; i < 5; i++) {
  legend.add(makeRow(palette[i], names[i]));
  }  
 
// add legend to map (alternatively you can also print the legend to the console)
Map.add(legend);


// Export a cloud-optimized GeoTIFF.
Export.image.toDrive({
  image: dNDVIscaled,
  description: 'imageToCOGeoTiffExample',
  scale: 10,
  region: AOI,
  fileFormat: 'GeoTIFF',
  formatOptions: {
    cloudOptimized: true
  }
});

https://code.earthengine.google.com/586a1c0df85e74d4df8871618a965f6a

Kevin Reid
  • 37,492
  • 13
  • 80
  • 108
Allison M
  • 21
  • 2
  • 1
    Welcome! On this site, it's _required_ that your question include the code itself, not just a link — I've edited that for you. Also, I'd recommend that you try to make your code samples smaller — producing a **small, yet still runnable** example whose results are wrong/surprising to you helps other people understand your problem with less effort, but it's also an exercise that can lead *you* to better understanding the problem. – Kevin Reid Aug 03 '21 at 19:19
  • What exactly do you want to clip and where (in the function, afterwards)? What have you tried and what error do you get? - A shortened example would be helpful indeed! – malin-fischer Aug 18 '21 at 16:40

0 Answers0