Before starting, make sure you understand these terms. They appear throughout all code blocks in this course.
| Term | Full Name | What it means in simple words |
|---|---|---|
| Spatial Epidemiology | Spatial Epidemiology | The study of spatial patterns in disease distribution and their relationship with environmental risk factors. |
| Environmental Exposure | Environmental Exposure | The presence of physical or climatic conditions that facilitate pathogen transmission or vector survival. |
| Ecological Niche Modeling | Ecological Niche Modeling | GeoAI techniques used to predict the spatial distribution of vector species based on environmental variables. |
| Spatial Autocorrelation | Spatial Autocorrelation | The tendency for geographical locations close to one another to exhibit more similar health outcomes than distant points. |
| Moran's I | Moran's I Statistic | A statistical index used to quantify spatial autocorrelation and cluster intensity in epidemiological data. |
| Random Forest | Random Forest Classifier | An ensemble machine learning method that trains multiple decision trees for spatial prediction and classification. |
| MAUP | Modifiable Areal Unit Problem | Statistical bias introduced when spatial point observations are aggregated into administrative boundaries. |
| Confounding Variable | Confounding Variable | An unmeasured factor that correlates with both the environmental predictor and the health outcome, potentially distorting causal conclusions. |
| Geographic Re-identification | Geographic Re-identification Risk | The privacy vulnerability of linking spatial health data to personal identity using fine-grained coordinates. |
| Vector Transmission Envelope | Vector Transmission Climate Envelope | The specific range of temperature, humidity, and rainfall required for pathogen vectors to survive and reproduce. |
| Population Exposure Masking | Population Exposure Masking | Overlapping predicted environmental risk grids with population count datasets to quantify affected communities. |
| Relative Risk Ratio | Relative Risk Ratio | A ratio comparing disease probability in exposed spatial units relative to unexposed reference zones. |
Climate-sensitive vector-borne diseases pose a critical global public health threat under accelerating environmental change. This advanced course demonstrates how to leverage Earth Observation datasets and GeoAI machine learning inside Google Earth Engine to model environmental suitability and human exposure. Students will harmonize ERA5-Land climate reanalysis, MODIS vegetation indices, and WorldPop population grids to build predictive spatial models while rigorously accounting for spatial autocorrelation, causal limits, and patient privacy.
ECMWF/ERA5_LAND/MONTHLY_AGGRYou need two browser tabs open side by side throughout this course.
Course32_Global Spatial Epidemiology: GeoAI Machine Learning for Environmental Disease Risk Mapping
The prompt is the core skill of this course. A good prompt includes the exact dataset ID, band names, study area coordinates, dates, preprocessing steps, and desired outputs.
Paste the following code into your GEE code editor and click Run. Read the beginner notes below to understand what each line does.
// Define study bounding box for sample regional analysis
var roi = ee.Geometry.Polygon([[
[-82.0, -18.0], [-82.0, 12.0], [-34.0, 12.0], [-34.0, -18.0]
]], null, false);
// Filter ERA5-Land Monthly Climate Data for 2022
var era5 = ee.ImageCollection('ECMWF/ERA5_LAND/MONTHLY_AGGR')
.filterDate('2022-01-01', '2022-12-31')
.filterBounds(roi);
// Calculate mean temperature (convert Kelvin to Celsius) and total annual precipitation
var meanTemp = era5.select('temperature_2m_mean')
.mean()
.subtract(273.15)
.rename('mean_temp_c');
var totalPrecip = era5.select('total_precipitation_sum')
.sum()
.multiply(1000)
.rename('total_precip_mm');
// Load MODIS 16-Day NDVI for 2022 and compute annual mean
var modisNdvi = ee.ImageCollection('MODIS/061/MOD13A2')
.filterDate('2022-01-01', '2022-12-31')
.select('NDVI')
.mean()
.multiply(0.0001)
.rename('mean_ndvi');
// Load WorldPop 2020 Global Population Grid
var population = ee.ImageCollection('WORLDPOP/GP/100m/pop')
.filterDate('2020-01-01', '2020-12-31')
.mosaic()
.rename('population_count');
// Concatenate environmental predictor variables into a single multi-band image
var predictors = ee.Image.cat([meanTemp, totalPrecip, modisNdvi]).clip(roi);
// Set Map visualization settings
Map.centerObject(roi, 4);
Map.addLayer(meanTemp, {min: 15, max: 35, palette: ['blue', 'yellow', 'red']}, 'Mean Temp (C)');
Map.addLayer(totalPrecip, {min: 0, max: 3000, palette: ['white', 'blue', 'darkblue']}, 'Precipitation (mm)');
Map.addLayer(modisNdvi, {min: 0, max: 0.8, palette: ['brown', 'yellow', 'green']}, 'Mean NDVI');
Add this block after the previous code. It continues the analysis with additional processing and visualization.
// Generate pseudo-presence and absence sampling locations for suitability training
// Note: Real disease incidence or vector presence coordinates should be imported securely
var presencePoints = ee.FeatureCollection.randomPoints(roi, 100, 42)
.map(function(f) { return f.set('class', 1); });
var absencePoints = ee.FeatureCollection.randomPoints(roi, 100, 99)
.map(function(f) { return f.set('class', 0); });
var trainingSample = presencePoints.merge(absencePoints);
// Sample spatial covariates at point locations
var trainingData = predictors.sampleRegions({
collection: trainingSample,
properties: ['class'],
scale: 1000,
geometries: false
});
// Train Random Forest classifier for vector niche modeling
var classifier = ee.Classifier.smileRandomForest(50).train({
features: trainingData,
classProperty: 'class',
inputProperties: ['mean_temp_c', 'total_precip_mm', 'mean_ndvi']
});
// Predict spatial environmental suitability
var suitabilityMap = predictors.classify(classifier).rename('suitability');
// Overlay suitability prediction with WorldPop to isolate exposed population
var highRiskPop = population.updateMask(suitabilityMap.eq(1)).clip(roi);
// Visualization
Map.addLayer(suitabilityMap, {min: 0, max: 1, palette: ['lightgray', 'darkred']}, 'Predicted Risk Class');
Map.addLayer(highRiskPop, {min: 0, max: 500, palette: ['yellow', 'orange', 'purple']}, 'Exposed Population Density');
// Calculate total exposed population across the region
var totalExposed = highRiskPop.reduceRegion({
reducer: ee.Reducer.sum(),
geometry: roi,
scale: 1000,
maxPixels: 1e9
});
print('Estimated High-Risk Exposed Population:', totalExposed);
Add this block at the end of your script to export the final map as a GeoTIFF to your Google Drive. After clicking Run, go to the Tasks tab in GEE and click Run next to each export task.
// Export the continuous predicted disease suitability map to Google Drive
Export.image.toDrive({
image: suitabilityMap,
description: 'Vector_Disease_Suitability_Map_2022',
folder: 'GEE_Spatial_Epidemiology',
fileNamePrefix: 'suitability_risk_map_1km',
region: roi,
scale: 1000,
maxPixels: 1e9,
crs: 'EPSG:4326'
});
Use DeepSeek to extend the script for each exercise below. Write a follow-up prompt describing what you want to add, then copy the generated code and paste it into your GEE script.
To get the best results from DeepSeek for GEE tasks, always include these elements in your prompts:
| Element | Example |
|---|---|
| Exact dataset ID | ECMWF/ERA5_LAND/MONTHLY_AGGR |
| Band names | "select band 'B4' for red, 'B8' for NIR" |
| Study area | "rectangle [-6.5, 33.0, -1.5, 36.0] North Morocco" |
| Date range | "filter from 2020-01-01 to 2023-12-31" |
| Output format | "print area in hectares, add a legend, export to Drive" |
| Error fixing | "The code gives error X. Please fix it." |
| Iteration | "Add a time series chart for each year 2018-2023" |