Module Programming Concept in Google Earth Engine Code Editor

Module Programming Concept in Google Earth Engine Code Editor

Google Earth Engine (GEE) introduced a module system to simplify the organization, reuse, and sharing of code. In this article, I will build a complete example workflow in Code Editor for NDVI and EVI analysis with Landsat 8 Collection 2 data, drawing parallels to Python principles such as modularization, encapsulation, and reusability.

What Are GEE Modules?

Modules in GEE work much like Python modules: they allow you to group related functions and variables into reusable components. Here’s a breakdown of why modules are such a powerful addition:

  • Encapsulation: Keep specific tasks, like preprocessing or visualization, confined to distinct modules.
  • Reusability: Use the same code across different scripts, eliminating redundancy.
  • Shareability: Easily share modules with collaborators by organizing them into GEE repositories.

With these advantages in mind, let’s dive into building a GEE workflow that mimics Pythonic modularity.

Case Study: Landsat 8 Collection 2 Workflow

Imagine you’re building a script to analyze vegetation changes using Landsat 8 Collection 2 data. This pipeline has three main steps:

  1. Preprocessing: Mask clouds and scale the reflectance values.
  2. Feature Extraction: Calculate vegetation indices like NDVI and EVI.
  3. Visualization: Define color schemes to visualize indices on a map.

Instead of putting all this code in a single script, we’ll create three modules, each corresponding to a step in the pipeline. Then, we’ll use a main script to bring it all together.

Step 1: Preprocessing Module

Our preprocessing module will handle two main tasks: masking clouds and scaling reflectance values. In GEE, LANDSAT/LC08/C02/T1_L2 data requires specific cloud masking and reflectance scaling operations, so encapsulating these functions in a module will make it easy to reuse them in future workflows.

Save File to the Path with Name preprocessing:

Path: users/username/repositoryname/filename

Example: users/username/remote-sensing/preprocessing

// Cloud masking for Landsat 8 Collection 2 Level 2 data
var applyCloudMask = function(image) {
  if (image.bandNames().contains('QA_PIXEL')) {
    var cloudMask = image.select('QA_PIXEL').bitwiseAnd(1 << 3).eq(0)
                         .and(image.select('QA_PIXEL').bitwiseAnd(1 << 4).eq(0));
    return image.updateMask(cloudMask);
  }
  return image;  // Return original image if 'QA_PIXEL' is missing
};

// Reflectance scaling for Landsat 8 Collection 2 Level 2 data
var scaleReflectance = function(image) {
  var requiredBands = ee.List(['SR_B2', 'SR_B3', 'SR_B4', 'SR_B5', 'SR_B6', 'SR_B7']);
  var availableBands = image.bandNames();
  
  // Check if required bands are available
  var hasAllBands = requiredBands.map(function(band) {
    return availableBands.contains(band);
  }).reduce(ee.Reducer.min());
  
  if (hasAllBands) {
    var opticalBands = image.select(['SR_B2', 'SR_B3', 'SR_B4', 'SR_B5', 'SR_B6', 'SR_B7'])
                            .multiply(0.0000275).add(-0.2);
    return image.addBands(opticalBands, null, true);
  }
  return image;  // Return original image if any band is missing
};

// Export functions
exports.applyCloudMask = applyCloudMask;
exports.scaleReflectance = scaleReflectance;        

Step 2: Feature Extraction Module

Feature extraction calculates indices that highlight specific land features — here, NDVI and EVI, which help in studying vegetation. In Python, a module like this might rely on libraries like numpy for array calculations. In GEE, we achieve a similar effect using built-in methods.

File: users/username/remote-sensing/featureExtraction

// Calculate NDVI
var calculateNDVI = function(image) {
  return image.addBands(image.normalizedDifference(['SR_B5', 'SR_B4']).rename('NDVI')).copyProperties(image, ['system:time_start']);
};

// Calculate EVI
var calculateEVI = function(image) {
  var nir = image.select('SR_B5');
  var red = image.select('SR_B4');
  var blue = image.select('SR_B2');
  var evi = nir.subtract(red)
               .divide(nir.add(red.multiply(6)).subtract(blue.multiply(7.5)).add(1))
               .multiply(2.5)
               .rename('EVI');
  return image.addBands(evi).copyProperties(image, ['system:time_start']);
};

// Export functions
exports.calculateNDVI = calculateNDVI;
exports.calculateEVI = calculateEVI;        

Step 3: Visualization Module

Visualization parameters control how NDVI and EVI are displayed on the map. This module defines these parameters, similar to how you might set matplotlib styles in Python.

File: users/username/remote-sensing/visualization

// Visualization parameters for NDVI and EVI
var ndviVisParams = {min: -1, max: 1, palette: ['blue', 'white', 'green']};
var eviVisParams = {min: 0, max: 1, palette: ['white', 'purple', 'green']};

// Display functions
var displayNDVI = function(image) {
  Map.addLayer(image.select('NDVI'), ndviVisParams, 'NDVI');
};

var displayEVI = function(image) {
  Map.addLayer(image.select('EVI'), eviVisParams, 'EVI');
};

// Export visualization functions
exports.displayNDVI = displayNDVI;
exports.displayEVI = displayEVI;
exports.ndviVisParams = ndviVisParams;
exports.eviVisParams = eviVisParams;        

Main Script: Bringing It All Together

Now that we’ve defined each component, we’ll bring them together in a main script. This is like the main.py file in a Python project, where we import all our functions and execute them.

// Import modules
var preprocessing = require('users/username/remote-sensing:preprocessing');
var featureExtraction = require('users/username/remote-sensing:featureExtraction');
var visualization = require('users/username/remote-sensing:visualization');

// Load a sample image collection (e.g., Landsat 8 Collection 2 Level 2)
var landsat = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2')
                 .filterDate('2021-01-01', '2021-12-31')
                 .filterBounds(ee.Geometry.Point([85.89527, 20.46246]));

// Apply preprocessing (e.g., cloud masking and reflectance scaling)
var preprocessed = landsat.map(preprocessing.applyCloudMask)
                          .map(preprocessing.scaleReflectance);



// Calculate NDVI and EVI
var withNDVI = preprocessed.map(featureExtraction.calculateNDVI);
var withEVI = withNDVI.map(featureExtraction.calculateEVI);

print(withEVI)


// Select a single image for display
var sampleImage = withEVI.median();

// Display results
visualization.displayNDVI(sampleImage);
visualization.displayEVI(sampleImage);        

Pythonic Concepts at Play

  1. Modularization: Each script handles a single responsibility, similar to functions in separate .py files. This modular setup keeps code manageable and allows for reuse.
  2. Encapsulation: Each module exposes only essential functions, hiding internal details from the main script. In Python, this is akin to using private methods with an underscore prefix.
  3. Reusability: By keeping tasks like NDVI calculation in modules, we can reuse them in multiple workflows without rewriting code.

Conclusion

With GEE modules, Earth Engine developers can organize their code much like Python projects, making it simpler, more readable, and maintainable. As you work with increasingly complex geospatial workflows, consider using GEE modules to structure your code effectively, following Pythonic principles for clean, reusable, and collaborative scripts.



?? More insights & projects: pulakeshpradhan.github.io


要查看或添加评论,请登录

Pulakesh Pradhan的更多文章

社区洞察

其他会员也浏览了