0

In GEE I'm using Awesome GEE's ESRI LULC Dataset to map out and mask water areas for the years 2017 to 2022. Due to it being an Image Collection of multiple dynamic years, I had to filter, mosaic, and remap the layers and create multiple variables of the same Image Collection to have annual layers, e.g. 'ESRI LULC 2017', '...2018', etc.

/* Geometry is unimportant for this example, just draw a box somewhere with land inside */

var ESRLULCdictPalette = {
  "names": [
    "Water","Trees","Flooded Vegetation","Crops","Built Area","Bare Ground","Snow/Ice",
    "Clouds","Rangeland"
  ],
  "colors": [
    "#1A5BAB","#358221","#87D19E","#FFDB5C","#ED022A","#EDE9E4","#F2FAFF","#C8C8C8","#C6AD8D"
  ]};
  
function Crop(image) {
  return image.clip(geometry);
  }
// ESRI LULC 2017-22 - Water is 1

var ESRI_LULC17 = ee.ImageCollection("projects/sat-io/open-datasets/landcover/ESRI_Global-LULC_10m_TS")
.filterDate('2017-01-01','2017-12-31');
var LULC17_mosaic = ESRI_LULC17.mosaic()
.remap([1,2,4,5,7,8,9,10,11],[1,2,3,4,5,6,7,8,9])
.clip(geometry);

var ESRI_LULC18 =ee.ImageCollection("projects/sat-io/open-datasets/landcover/ESRI_Global-LULC_10m_TS")
.filterDate('2018-01-01','2018-12-31');
var LULC18_mosaic = ESRI_LULC18.mosaic()
.remap([1,2,4,5,7,8,9,10,11],[1,2,3,4,5,6,7,8,9])
.clip(geometry);

var ESRI_LULC19 = ee.ImageCollection("projects/sat-io/open-datasets/landcover/ESRI_Global-LULC_10m_TS")
.filterDate('2019-01-01','2019-12-31');
var LULC19_mosaic = ESRI_LULC19.mosaic()
.remap([1,2,4,5,7,8,9,10,11],[1,2,3,4,5,6,7,8,9])
.clip(geometry);

var ESRI_LULC20 = ee.ImageCollection("projects/sat-io/open-datasets/landcover/ESRI_Global-LULC_10m_TS")
.filterDate('2020-01-01','2020-12-31');
var LULC20_mosaic = ESRI_LULC20.mosaic()
.remap([1,2,4,5,7,8,9,10,11],[1,2,3,4,5,6,7,8,9])
.clip(geometry);

var ESRI_LULC21 = ee.ImageCollection("projects/sat-io/open-datasets/landcover/ESRI_Global-LULC_10m_TS")
.filterDate('2021-01-01','2021-12-31');
var LULC21_mosaic = ESRI_LULC21.mosaic()
.remap([1,2,4,5,7,8,9,10,11],[1,2,3,4,5,6,7,8,9])
.clip(geometry);

var ESRI_LULC22 = ee.ImageCollection("projects/sat-io/open-datasets/landcover/ESRI_Global-LULC_10m_TS")
.filterDate('2022-01-01','2022-12-31');
var LULC22_mosaic = ESRI_LULC22.mosaic()
.remap([1,2,4,5,7,8,9,10,11],[1,2,3,4,5,6,7,8,9])
.clip(geometry);

var ESRILULCMaskWater17 = LULC17_mosaic.eq(1); // Only Water
  var ESRILULCMaskWater17 = LULC17_mosaic.updateMask(ESRILULCMaskWater17).clip(geometry);
  var WCMask = function(image) {
     return image.updateMask(ESRILULCMaskWater17);
  };

var ESRILULCMaskWater18 = LULC18_mosaic.eq(1); // Only Water
  var ESRILULCMaskWater18 = LULC18_mosaic.updateMask(ESRILULCMaskWater18).clip(geometry);
  var LULCMask = function(image) {
     return image.updateMask(ESRILULCMaskWater18);
  };

var ESRILULCMaskWater19 = LULC19_mosaic.eq(1); // Only Water
  var ESRILULCMaskWater19 = LULC19_mosaic.updateMask(ESRILULCMaskWater19).clip(geometry);
  var LULCMask = function(image) {
     return image.updateMask(ESRILULCMaskWater19);
  };

var ESRILULCMaskWater20 = LULC20_mosaic.eq(1); // Only Water
  var ESRILULCMaskWater20 = LULC20_mosaic.updateMask(ESRILULCMaskWater20).clip(geometry);
  var LULCMask = function(image) {
     return image.updateMask(ESRILULCMaskWater20);
  };

var ESRILULCMaskWater21 = LULC21_mosaic.eq(1); // Only Water
  var ESRILULCMaskWater21 = LULC21_mosaic.updateMask(ESRILULCMaskWater21).clip(geometry);
  var LULCMask = function(image) {
     return image.updateMask(ESRILULCMaskWater21);
  };

var ESRILULCMaskWater22 = LULC22_mosaic.eq(1); // Only Water
  var ESRILULCMaskWater22 = LULC22_mosaic.updateMask(ESRILULCMaskWater22).clip(geometry);
  var LULCMask = function(image) {
     return image.updateMask(ESRILULCMaskWater22);
  };
  
// Landcover with no masking
Map.addLayer(LULC17_mosaic, {min:1, max:9, palette:ESRLULCdictPalette['colors']}, 'ESRI LULC 2017', false);
Map.addLayer(LULC18_mosaic, {min:1, max:9, palette:ESRLULCdictPalette['colors']}, 'ESRI LULC 2018', false);
Map.addLayer(LULC19_mosaic, {min:1, max:9, palette:ESRLULCdictPalette['colors']}, 'ESRI LULC 2019', false);
Map.addLayer(LULC20_mosaic, {min:1, max:9, palette:ESRLULCdictPalette['colors']}, 'ESRI LULC 2020', false);
Map.addLayer(LULC21_mosaic, {min:1, max:9, palette:ESRLULCdictPalette['colors']}, 'ESRI LULC 2021', false);
Map.addLayer(LULC22_mosaic, {min:1, max:9, palette:ESRLULCdictPalette['colors']}, 'ESRI LULC 2022', false);

// Landcover with masking (only Water)
Map.addLayer(ESRILULCMaskWater17, {"opacity":1,"bands":["remapped"],"palette":["002bff"]}, 'ESRI LULC 2017 Water Mask', false);
Map.addLayer(ESRILULCMaskWater18, {"opacity":1,"bands":["remapped"],"palette":["002bff"]}, 'ESRI LULC 2018 Water Mask', false);
Map.addLayer(ESRILULCMaskWater19, {"opacity":1,"bands":["remapped"],"palette":["002bff"]}, 'ESRI LULC 2019 Water Mask', false);
Map.addLayer(ESRILULCMaskWater20, {"opacity":1,"bands":["remapped"],"palette":["002bff"]}, 'ESRI LULC 2020 Water Mask', false);
Map.addLayer(ESRILULCMaskWater21, {"opacity":1,"bands":["remapped"],"palette":["002bff"]}, 'ESRI LULC 2021 Water Mask', false);
Map.addLayer(ESRILULCMaskWater22, {"opacity":1,"bands":["remapped"],"palette":["ff0000"]}, 'ESRI LULC 2022 Water Mask', false);

Map.centerObject(geometry, 7);

I'm also using a native GEE Dataset, ESA Worldcover 2021 for a similar project and uses a similar workflow. The code is a bit simpler however since it's only one layer of one year;

/* Geometry is unimportant for this example, just draw a box somewhere with land inside */

var WCdictPalette = {
  "names": [
    "Trees", "Shrubland", "Grassland", "Cropland", "Built-Up",
    "Barren/Sparse", "Snow/Ice", "Open Water", "Herbaceous Wetland", "Mangroves",
    "Moss/Lichen"
  ],
  "colours": [
    '#006400', '#ffbb22', '#ffff4c', '#f096ff', '#fa0000',
    '#b4b4b4', '#f0f0f0', '#0064c8', '#0096a0', '#00cf75',
    '#fae6a0'
  ]};

function Crop(image) {
  return image.clip(geometry);
  }

// ESA Worldcover - Water is 7
var WCv2021 = ee.ImageCollection("ESA/WorldCover/v200");

var WCmosaic = WCv2021.mosaic()
.remap([10,20,30,40,50,60,70,80,90,95,100],[0,1,2,3,4,5,6,7,8,9,10])
.clip(geometry);

var ESAWCMaskWater = WCmosaic.eq(7); // Only Water
  var ESAWCMaskWater = WCmosaic.updateMask(ESAWCMaskWater).clip(geometry);
  var WCMask = function(image) {
     return image.updateMask(ESAWCMaskWater);
  };

// Land cover without Masking
Map.addLayer(WCmosaic, {min:0, max:10, palette:WCdictPalette['colours']}, 'ESA WorldCover 2021', false);

// Landcover with Masking (only water)
Map.addLayer(ESAWCMaskWater, {"opacity":1,"bands":["remapped"],"palette":["002bff"]}, 'ESA Worldcover Water Mask', false);

Map.centerObject(geometry, 7);

I want to try to reduce the amount of code I'm entering for the ESRI LULC Dataset annual Layers, and I think I could reduce it at the ESAWCMaskWater/ESRILULCMaskWaterxx variable ad WCMaskWater/LULCMask function because the function is repeated 5 times, it's just the year changes (17,18,19,20,21,22).

I found on the GEE Devhelp page that you can use Regular Expressions to select Image bands within Image Collections, but can you do something similar with Variables?

i.e.

/* This will not work but I can't think of the 'correct' way to use regexp in this manner for Variables */

var ESRILULCMaskWater = image.select('LULC[17-22]_mosaic').eq(1); // Only Water
  var ESRILULCMaskWater = 'LULC[17-22]_mosaic'.updateMask(ESRILULCMaskWater).clip(geometry);
  var LULCMask = function(image) {
     return image.updateMask('ESRILULCMaskWater[17-22]');
  };

My script works fine as it stands if it isn't possible, but I'd just like to have less Variables to edit and think about if I need to change the Mask later from Water to Built-up Areas, for example.

2
  • When you say your regexp attempt "will not work," what exactly to you mean? Are you getting an error, what is the error and any traceback? Are you getting unexpected results? If so, what are you getting and what are you expecting?
    – bixb0012
    Commented May 2 at 14:41
  • My regexp 'attempt' isn't an attempt, it is illustrating what I want to do, if that is possible in GEE. I want to, if it's possible, to condense the repeated functions of the ESRILULCMask; var ESRILULCMaskWater17 = LULC17_mosaic.eq(1); // Only Water var ESRILULCMaskWater17 = LULC17_mosaic.updateMask(ESRILULCMaskWater17).clip(geometry); var WCMask = function(image) { return image.updateMask(ESRILULCMaskWater17); }; ...to cover all years instead of each year individually. At the moment I get nothing and expect nothing, but don't know if it's possible with GEE. Commented May 2 at 15:31

1 Answer 1

2

This isn't exactly answering the question you asked, but you can massively reduce the amount of code involved here by mapping a function over the collection:

var years = ee.List.sequence(2017, 2022)
var results = ee.ImageCollection(years.map(function(year) {
  var start = ee.Date.fromYMD(year, 1, 1)
  var end = start.advance(1, 'year')
  var c = ee.ImageCollection("projects/sat-io/open-datasets/landcover/ESRI_Global-LULC_10m_TS")
    .filterDate(start, end)
    .mosaic()
    .remap([1,2,4,5,7,8,9,10,11],[1,2,3,4,5,6,7,8,9])
    .clip(geometry)
    .set("system:time_start", start)
}))

I can't quite tell what the functions you built are supposed to do, but you can then just map over that collection to similarly get the water masks and do whatever masking you mean to do with them.

Then, when you want to use one, you can just filter THAT collection by year.

1
  • That would cut back a lot of the code which is way better then I envisioned, thank you very much! Commented May 3 at 10:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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