added ws202425 courses
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
////// Satellite images and RGB color presentation //////
|
||||
|
||||
/// Open a satellite image and create an RGB-Composite
|
||||
|
||||
// Load an image.
|
||||
var image = ee.Image('LANDSAT/LC08/C01/T1_TOA/LC08_044034_20140318');
|
||||
|
||||
// Define the visualization parameters.
|
||||
var visParams = {
|
||||
bands: ['B5', 'B4', 'B3'],
|
||||
min: 0,
|
||||
max: 0.5,
|
||||
};
|
||||
|
||||
// Center the map and set zoom level
|
||||
Map.setCenter(-122.1899, 37.5010, 10); // San Francisco Bay
|
||||
|
||||
// Visualize image
|
||||
Map.addLayer(image, visParams, 'false color composite');
|
||||
|
||||
//// Exercise 1a:
|
||||
// Play around with the visualization
|
||||
|
||||
|
||||
//// Clip the image to a feature:
|
||||
|
||||
// Create a circle by drawing a 20000 meter buffer around a point.
|
||||
//var roi = ee.Geometry.Point([-122.4481, 37.7599]).buffer(20000);
|
||||
|
||||
// Display a clipped version of the mosaic.
|
||||
// After the layers are visible in the Map view, please do only display the layer "buffer"
|
||||
//Map.addLayer(image.clip(roi), visParams, 'buffer');
|
||||
|
||||
//// Exercise 1b:
|
||||
// Create a polygon and clip the image to this feature
|
||||
// 1. Create a polygon with the available tool (freehand or rectangle)
|
||||
// 2. You will find the feature under imports at the beginning of your script
|
||||
// 3. Change the function image.clip accordingly
|
||||
// 4. Re-run the sript
|
||||
Map.addLayer(image.clip(Rechteck), visParams, 'Rechteck')
|
||||
@@ -0,0 +1,22 @@
|
||||
// Open SRTM image and visualize it
|
||||
|
||||
// Detailed description: https://developers.google.com/earth-engine/tutorial_api_02
|
||||
|
||||
// Instantiate an image with the Image constructor.
|
||||
var image = ee.Image('CGIAR/SRTM90_V4');
|
||||
|
||||
// Zoom to a location.
|
||||
Map.setCenter(12.978717025594149,47.55544193154224,11); // Center on Königssee - Berchtesgaden.
|
||||
|
||||
// datatype
|
||||
print('SRTM image', image);
|
||||
|
||||
// Display the image on the map.
|
||||
Map.addLayer(image);
|
||||
|
||||
// Customizing layer visualization
|
||||
Map.addLayer(image, {min: 0, max: 3000}, 'custom visualization');
|
||||
|
||||
// Customizing layer visualization - color palette
|
||||
Map.addLayer(image, {min: 0, max: 3000, palette: ['blue', 'green', 'red']},
|
||||
'custom palette');
|
||||
@@ -0,0 +1,65 @@
|
||||
////// Script 2: Calculate indices and apply a mask //////
|
||||
|
||||
// Load an image.
|
||||
var image = ee.Image('LANDSAT/LC08/C01/T1_TOA/LC08_044034_20140318');
|
||||
|
||||
// Center map view
|
||||
Map.centerObject(image,10)
|
||||
|
||||
// Create an NDWI image, define visualization parameters and display.
|
||||
var ndwi = image.normalizedDifference(['B3', 'B5']);
|
||||
var ndwiViz = {min: 0.5, max: 1, palette: ['00FFFF', '0000FF']};
|
||||
Map.addLayer(ndwi, ndwiViz, 'NDWI');
|
||||
Map.addLayer(ndwi, ndwiViz, 'NDWI false', false);
|
||||
|
||||
// Question 1: What's "false" doing?
|
||||
//Zeigt den Layer nicht an.
|
||||
|
||||
// Mask the non-watery parts of the image, where NDWI < 0.4.
|
||||
var ndwiMasked = ndwi.updateMask(ndwi.gte(0.4));
|
||||
Map.addLayer(ndwiMasked, ndwiViz, 'NDWI masked');
|
||||
|
||||
// Question 2: What does the function .gte actually do?
|
||||
//Maskiert alles wo der NDWI unter 0.4 ist.
|
||||
|
||||
//// Create visualization layers.
|
||||
// The .visualize function creates images that contain the visualisation parameters.
|
||||
var imageRGB = image.visualize({bands: ['B3', 'B2', 'B1'], max: 0.5});
|
||||
var ndwiRGB = ndwiMasked.visualize({min: 0.5, max: 1, palette: ['00FFFF', '0000FF']});
|
||||
Map.addLayer(imageRGB, {}, 'imageRGB');
|
||||
Map.addLayer(ndwiRGB, {}, 'NDWI masked - 2'); //looks the same than the fist visualization, just another layer
|
||||
|
||||
// Mosaic the visualization layers and display.
|
||||
var mosaic = ee.ImageCollection([imageRGB, ndwiRGB]).mosaic();
|
||||
Map.addLayer(mosaic, {}, 'mosaic');
|
||||
|
||||
//Question 3: What does the mosaic function do?
|
||||
//Fügt das RGB Image und das NDWI Image zusammen.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Exercise 2a:
|
||||
// Calculate the NDVI and visualize it
|
||||
var ndvi = image.normalizedDifference(['B4', 'B5']);
|
||||
|
||||
// Find a threshold for differentiating vegetated and non-vegetated areas
|
||||
var ndviViz = {min: -1, max: 1};
|
||||
Map.addLayer(ndvi, ndviViz, 'NDVI');
|
||||
|
||||
// Create a mask that masks non-vegetated areas
|
||||
// Mask the non-planty parts of the image, where NDVI < 0.
|
||||
var ndviMasked = ndvi.updateMask(ndvi.gte(0));
|
||||
|
||||
// Find a nice visualization
|
||||
var ndviRGB = ndviMasked.visualize({min: -1, max: 1, palette: ['00FFFF', '0000FF']});
|
||||
Map.addLayer(ndviRGB, {}, 'NDVI masked');
|
||||
|
||||
// Create a mosaic of the Landsat image and the NDVI data.
|
||||
var mosaic = ee.ImageCollection([imageRGB, ndviRGB]).mosaic();
|
||||
Map.addLayer(mosaic, {}, 'mosaic');
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
// Calculate slope and aspect
|
||||
// Calculate statistics
|
||||
|
||||
//Detailed description: https://developers.google.com/earth-engine/tutorial_api_03
|
||||
|
||||
// Load the SRTM image.
|
||||
var srtm = ee.Image('CGIAR/SRTM90_V4');
|
||||
|
||||
// Apply an algorithm to an image.
|
||||
var slope = ee.Terrain.slope(srtm);
|
||||
|
||||
print(slope)
|
||||
// Convert degree in percent
|
||||
|
||||
// Display the result.
|
||||
Map.setCenter(12.978717025594149,47.55544193154224,11); // Center on Königsee.
|
||||
Map.addLayer(srtm, {min: 0, max :2500}, 'srtm');
|
||||
Map.addLayer(slope, {min: 0, max :60}, 'slope');
|
||||
|
||||
|
||||
//Image math
|
||||
// Get the aspect (in degrees).
|
||||
var aspect = ee.Terrain.aspect(srtm);
|
||||
// Convert to radians, compute the sin of the aspect.
|
||||
var sinImage = aspect.divide(180).multiply(Math.PI).sin();
|
||||
// Display the result.
|
||||
Map.addLayer(sinImage, {min: -1, max: 1}, 'sin');
|
||||
|
||||
|
||||
|
||||
// Image statistics
|
||||
// Compute the mean elevation in the polygon.
|
||||
var stddevDict = srtm.reduceRegion({
|
||||
reducer: ee.Reducer.stdDev(),
|
||||
geometry: koenigsee,
|
||||
scale: 90
|
||||
});
|
||||
|
||||
// Print dictionary
|
||||
print("dict", stddevDict)
|
||||
|
||||
// Get the mean from the dictionary and print it.
|
||||
// In java a dictionary is a collection of different kinds of information.
|
||||
// In other languages such as R a dictionary is usally named 'object'.
|
||||
|
||||
var stddev = stddevDict.get('elevation');
|
||||
print('stdDev elevation', stddev);
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
|
||||
////// Skript 3: First Image Collection ///////
|
||||
|
||||
//// Open an image collection
|
||||
// An image collection refers to a set of Earth Engine images. For example, the collection of all Landsat 8
|
||||
// surface reflectance images is an ee.ImageCollection.
|
||||
|
||||
var l8 = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2');
|
||||
print('Landsat 8 collection', l8);
|
||||
|
||||
// Question 1: Which error occurs when printing the contents of the variable l8?
|
||||
// Before the second run, comment the line "print('Landsat 8 collection', l8);"
|
||||
|
||||
// No worries: we can still work with all the images…
|
||||
|
||||
|
||||
//// Filter the collection
|
||||
|
||||
// The way to limit the collection by time or space is by filtering it.
|
||||
// For example, to filter the collection to images that cover a particular location,
|
||||
// first define your area of interest with a point (or line or polygon) using the geometry drawing tools.
|
||||
|
||||
var spatialFiltered = l8.filterBounds(point);
|
||||
print('spatialFiltered', spatialFiltered);
|
||||
|
||||
var temporalFiltered = spatialFiltered.filterDate('2015-01-01', '2015-12-31');
|
||||
print('temporalFiltered', temporalFiltered);
|
||||
|
||||
//// Exercise 3a:
|
||||
// - Create a point somewhere and name it “point”. Of course you might give it another name,
|
||||
// but then you need to change the code accordingly.
|
||||
// - Have a look at another time period.
|
||||
|
||||
|
||||
//// How to work with the collection
|
||||
|
||||
// Alternative 1: Visualize the Image collection as is
|
||||
|
||||
// Note: You may directly visualize the image collection but then only the newest one will be
|
||||
// visualized (if you do not specify it otherwise)
|
||||
var visParams = {bands: ['SR_B4', 'SR_B3', 'SR_B2'], min: 0, max: 30000};
|
||||
Map.centerObject(temporalFiltered, 9);
|
||||
Map.addLayer(temporalFiltered, visParams, 'l8 collection');
|
||||
|
||||
|
||||
//// Alternative 2: How to use single images from the stack
|
||||
|
||||
// We may see and use the images that the collection contains.
|
||||
var listofimages = temporalFiltered.toList(temporalFiltered.size());
|
||||
print('List of images', listofimages);
|
||||
|
||||
// We may then assign the images to a variable. We start counting with 0.
|
||||
var firstimage = listofimages.get(0);
|
||||
var tenthimage = listofimages.get(9);
|
||||
var lastimage = listofimages.get(listofimages.length().subtract(1));
|
||||
print('tenth image', tenthimage);
|
||||
|
||||
// Visualize the 10th image
|
||||
Map.addLayer(ee.Image(tenthimage), visParams, '10th image');
|
||||
|
||||
|
||||
//// Alternative 3: Use the least cloudy image
|
||||
|
||||
// This will sort from least to most cloudy.
|
||||
var sorted = temporalFiltered.sort('CLOUD_COVER');
|
||||
print("sorted", sorted)
|
||||
|
||||
// Get the first (least cloudy) image.
|
||||
var scene = sorted.first();
|
||||
|
||||
// Visualize the least cloudy image print("cloudless", scene)
|
||||
Map.addLayer(scene, visParams, 'Least cloudy image');
|
||||
|
||||
//// Exercise 3a:
|
||||
// - Use the Landsat 5 collection (surface reflectance).
|
||||
// - Which images are available from the year of your birthday and your place of birth?
|
||||
// - Are there any images from your month of birth?
|
||||
// - Visualize the image that comes closest to your birthday
|
||||
// - Plot the least cloudy image
|
||||
|
||||
// Of course you may use any other event. In this case you need to see if the Landsat 5 collection
|
||||
// is the right one to use.
|
||||
@@ -0,0 +1,32 @@
|
||||
//// Script 4 - Additional Script Metadata
|
||||
|
||||
// Load an image.
|
||||
var image = ee.Image('LANDSAT/LC08/C01/T1/LC08_044034_20140318');
|
||||
|
||||
// Get a list of all metadata properties.
|
||||
var properties = image.propertyNames();
|
||||
print('Metadata properties: ', properties); // ee.List of metadata properties
|
||||
|
||||
// Get information about the bands as a list.
|
||||
var bandNames = image.bandNames();
|
||||
print('Band names: ', bandNames); // ee.List of band names
|
||||
|
||||
// Get projection information from band 1.
|
||||
var b1proj = image.select('B1').projection();
|
||||
print('Band 1 projection: ', b1proj); // ee.Projection object
|
||||
|
||||
// Get scale (in meters) information from band 1.
|
||||
var b1scale = image.select('B1').projection().nominalScale();
|
||||
print('Band 1 scale: ', b1scale); // ee.Number
|
||||
|
||||
// Note that different bands can have different projections and scale.
|
||||
var b8scale = image.select('B8').projection().nominalScale();
|
||||
print('Band 8 scale: ', b8scale); // ee.Number
|
||||
|
||||
// Get a specific metadata property.
|
||||
var cloudiness = image.get('CLOUD_COVER');
|
||||
print('CLOUD_COVER: ', cloudiness); // ee.Number
|
||||
|
||||
// Get the timestamp and convert it to a date.
|
||||
var date = ee.Date(image.get('system:time_start'));
|
||||
print('Timestamp: ', date); // ee.Date
|
||||
@@ -0,0 +1,32 @@
|
||||
// Assemble a collection of Sentinel-2 surface reflectance images for a given
|
||||
// region and date range.
|
||||
var s2col = ee.ImageCollection('COPERNICUS/S2_SR')
|
||||
.filterBounds(ee.Geometry.Point(-96.9037, 48.0395))
|
||||
.filterDate('2019-06-01', '2019-10-01');
|
||||
|
||||
// Define visualization arguments.
|
||||
var visArgs = {bands: ['B11', 'B8', 'B3'], min: 300, max: 3500};
|
||||
|
||||
// Define a function to convert an image to an RGB visualization image and copy
|
||||
// properties from the original image to the RGB image.
|
||||
var visFun = function(img) {
|
||||
return img.visualize(visArgs).copyProperties(img, img.propertyNames());
|
||||
};
|
||||
|
||||
// Map over the image collection to convert each image to an RGB visualization
|
||||
// using the previously defined visualization function.
|
||||
var s2colVis = s2col.map(visFun);
|
||||
|
||||
print("s2col", s2colVis)
|
||||
|
||||
|
||||
// Print the animation to the console as a ui.Thumbnail using the above defined
|
||||
// arguments. Note that ui.Thumbnail produces an animation when the first input
|
||||
// is an ee.ImageCollection instead of an ee.Image.
|
||||
print(ui.Thumbnail(s2colVis, visFun));
|
||||
|
||||
|
||||
// Zeigt den Median von allen Bildern
|
||||
var s2col_comp = s2col.median()
|
||||
Map.setCenter(-96.9037, 48.0395, 10)
|
||||
Map.addLayer(s2col_comp, visArgs, "composite")
|
||||
@@ -0,0 +1,29 @@
|
||||
// Metadata of image collections
|
||||
|
||||
// Load a Landsat 8 ImageCollection for a single path-row.
|
||||
var collection = ee.ImageCollection('LANDSAT/LC08/C01/T1_TOA')
|
||||
.filter(ee.Filter.eq('WRS_PATH', 44))
|
||||
.filter(ee.Filter.eq('WRS_ROW', 34))
|
||||
.filterDate('2014-03-01', '2014-08-01');
|
||||
print('Collection: ', collection);
|
||||
|
||||
// Get the number of images.
|
||||
var count = collection.size();
|
||||
print('Count: ', count);
|
||||
|
||||
// Get the date range of images in the collection.
|
||||
var range = collection.reduceColumns(ee.Reducer.minMax(), ["system:time_start"])
|
||||
print('Date range: ', ee.Date(range.get('min')), ee.Date(range.get('max')))
|
||||
|
||||
// Get statistics for a property of the images in the collection.
|
||||
var sunStats = collection.aggregate_stats('SUN_ELEVATION');
|
||||
print('Sun elevation statistics: ', sunStats);
|
||||
|
||||
// Sort by a cloud cover property, get the least cloudy image.
|
||||
var image = ee.Image(collection.sort('CLOUD_COVER').first());
|
||||
print('Least cloudy image: ', image);
|
||||
|
||||
// Limit the collection to the 10 most recent images.
|
||||
var recent = collection.sort('system:time_start', false).limit(10);
|
||||
print('Recent images: ', recent);
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
// Filter and first composites
|
||||
|
||||
// Load Landsat 5 data, filter by date and bounds.
|
||||
var collection = ee.ImageCollection('LANDSAT/LT05/C01/T1')
|
||||
.filterDate('1987-01-01', '1989-12-31')
|
||||
.filter(ee.Filter.calendarRange(6,8,'month'))
|
||||
.filterBounds(ee.Geometry.Point(13.41, 52.53));
|
||||
|
||||
// Also filter the collection by the CLOUD_COVER property.
|
||||
var filtered = collection
|
||||
.filterMetadata('CLOUD_COVER', 'equals', 0);
|
||||
|
||||
// Create two composites to check the effect of filtering by CLOUD_COVER.
|
||||
var unfilteredComposite = collection.mean()
|
||||
var cloudfreeComposite = filtered.mean()
|
||||
|
||||
// Display the composites.
|
||||
Map.setCenter(13.41, 52.53, 13);
|
||||
Map.addLayer(unfilteredComposite,
|
||||
{bands: ['B4', 'B3', 'B2'], gain: 3.5},
|
||||
'unfiltered composite');
|
||||
Map.addLayer(cloudfreeComposite,
|
||||
{bands: ['B4', 'B3', 'B2'], gain: 3.5},
|
||||
'cloudless composite');
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
// Simple composite
|
||||
|
||||
var landsat = ee.ImageCollection("LANDSAT/LC08/C01/T1")
|
||||
.filterDate('2016-01-01', '2017-01-01')
|
||||
.filterBounds(geometry)
|
||||
|
||||
Map.addLayer(landsat, {bands: ["B4", "B3", "B2"], min:0, max: 30000})
|
||||
|
||||
var composite = ee.Algorithms.Landsat.simpleComposite({
|
||||
collection: landsat,
|
||||
asFloat: true
|
||||
})
|
||||
|
||||
Map.addLayer(composite, {bands: ["B4", "B3", "B2"], min:0, max: 0.3})
|
||||
Map.centerObject(geometry, 11)
|
||||
@@ -0,0 +1,36 @@
|
||||
// Landsat 8 - Cloud masking
|
||||
|
||||
// This example demonstrates the use of the pixel QA band to mask
|
||||
// clouds in surface reflectance (SR) data. It is suitable
|
||||
// for use with any of the Landsat SR datasets.
|
||||
|
||||
// Function to cloud mask from the pixel_qa band of Landsat 8 SR data.
|
||||
function maskL8sr(image) {
|
||||
// Bits 3 and 4 are cloud shadow and cloud, respectively.
|
||||
var cloudShadowBitMask = 1 << 4;
|
||||
var cloudsBitMask = 1 << 3;
|
||||
|
||||
// Get the pixel QA band.
|
||||
var qa = image.select('QA_PIXEL');
|
||||
|
||||
// Both flags should be set to zero, indicating clear conditions.
|
||||
var mask = qa.bitwiseAnd(cloudShadowBitMask).eq(0)
|
||||
.and(qa.bitwiseAnd(cloudsBitMask).eq(0));
|
||||
|
||||
// Return the masked image, scaled to reflectance, without the QA bands.
|
||||
return image.updateMask(mask)
|
||||
.select("SR_B[0-9]*").multiply(0.0000275).add(-0.2)
|
||||
.copyProperties(image, ["system:time_start"]);
|
||||
}
|
||||
|
||||
// Map the function over one year of data.
|
||||
var collection = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2')
|
||||
.filterBounds(ee.Geometry.Point(13.4,52.5))
|
||||
.filterDate('2016-01-01', '2016-12-31')
|
||||
.map(maskL8sr)
|
||||
|
||||
var composite = collection.median();
|
||||
|
||||
// Display the results.
|
||||
Map.setCenter(13.4,52.5,10)
|
||||
Map.addLayer(composite, {bands: ['SR_B4', 'SR_B3', 'SR_B2'], min: 0, max: 0.5});
|
||||
@@ -0,0 +1,98 @@
|
||||
// Detailed information: https://docs.google.com/document/d/1mNIRB90jwLuASO1JYas1kuOXCLbOoy1Z4NlV1qIXM10/edit
|
||||
|
||||
var imageCollection = ee.ImageCollection("LANDSAT/LC08/C02/T1_L2");
|
||||
|
||||
var roi =
|
||||
ee.Geometry.Polygon(
|
||||
[[[120.34892531309845, 43.64119426062719],
|
||||
[120.34892531309845, 43.618332108842225],
|
||||
[120.39218398009064, 43.618332108842225],
|
||||
[120.39218398009064, 43.64119426062719]]], null, false);
|
||||
|
||||
Map.centerObject(roi, 12)
|
||||
|
||||
|
||||
|
||||
var l8sr = imageCollection
|
||||
.filterBounds(roi);
|
||||
|
||||
|
||||
// This field contains UNIX time in milliseconds.
|
||||
var timeField = 'system:time_start';
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// CLOUD MASKING
|
||||
|
||||
// Function to cloud mask from the pixel_qa band of Landsat 8 SR data.
|
||||
// (From the Code Editor Examples > Cloud Masking)
|
||||
function maskL8sr(image) {
|
||||
// Bit 0 - Fill
|
||||
// Bit 1 - Dilated Cloud
|
||||
// Bit 2 - Cirrus
|
||||
// Bit 3 - Cloud
|
||||
// Bit 4 - Cloud Shadow
|
||||
var qa = image.select('QA_PIXEL')
|
||||
|
||||
var cloud = qa.bitwiseAnd(1 << 1)
|
||||
.or(qa.bitwiseAnd(1 << 2))
|
||||
.or(qa.bitwiseAnd(1 << 3))
|
||||
.or(qa.bitwiseAnd(1 << 4))
|
||||
|
||||
|
||||
// The flags should equal zero, indicating clear conditions.
|
||||
var mask = cloud.eq(0);
|
||||
//var ndwiMasked = ndwi.updateMask(ndwi.gte(0.4));
|
||||
// Apply the scaling factors to the appropriate bands.
|
||||
var opticalBands = image.select('SR_B.').multiply(0.0000275).add(-0.2);
|
||||
|
||||
// Replace the original bands with the scaled ones and apply the masks.
|
||||
return image.addBands(opticalBands, null, true)
|
||||
.updateMask(mask)
|
||||
.copyProperties(image, ['system:time_start']);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// ADD BANDS
|
||||
|
||||
// Use this function to add variables for NDVI, time and a constant
|
||||
// to Landsat 8 imagery.
|
||||
var addVariables = function(image) {
|
||||
// Compute time in fractional years since the epoch.
|
||||
var date = ee.Date(image.get(timeField));
|
||||
var years = date.difference(ee.Date('1970-01-01'), 'year');
|
||||
// Return the image with the added bands.
|
||||
return image
|
||||
// Add an NDVI band.
|
||||
.addBands(image.normalizedDifference(['SR_B5', 'SR_B4']).rename('NDVI'))
|
||||
// Add a time band.
|
||||
.addBands(ee.Image(years).rename('t'))
|
||||
.float()
|
||||
// Add a constant band.
|
||||
.addBands(ee.Image.constant(1));
|
||||
};
|
||||
|
||||
// Remove clouds, add variables and filter to the area of interest.
|
||||
var filteredLandsat = l8sr
|
||||
.filterBounds(roi)
|
||||
.map(maskL8sr)
|
||||
.map(addVariables);
|
||||
|
||||
|
||||
// Plot a time series of NDVI at a single location.
|
||||
var l8Chart = ui.Chart.image.series(filteredLandsat.select('NDVI'), roi)
|
||||
.setChartType('ScatterChart')
|
||||
.setOptions({
|
||||
title: 'Landsat 8 NDVI time series at ROI',
|
||||
trendlines: {0: {
|
||||
color: 'CC0000'
|
||||
}},
|
||||
lineWidth: 1,
|
||||
pointSize: 3,
|
||||
});
|
||||
print(l8Chart);
|
||||
|
||||
// Display the NDVI of the time series (mean, first image, last image)
|
||||
Map.addLayer(filteredLandsat.select("NDVI").mean(),{min:0, max:1}, "Mean NDVI Landsat 8")
|
||||
Map.addLayer(filteredLandsat.select("NDVI").first(),{min:0, max:1}, "Oldest image within time series")
|
||||
Map.addLayer(filteredLandsat.sort("system:time_start",false).select("NDVI").first(),{min:0, max:1}, "Newest image within time series")
|
||||
@@ -0,0 +1,111 @@
|
||||
// Detailed information: https://docs.google.com/document/d/1mNIRB90jwLuASO1JYas1kuOXCLbOoy1Z4NlV1qIXM10/edit
|
||||
|
||||
var imageCollection = ee.ImageCollection("LANDSAT/LC08/C02/T1_L2");
|
||||
|
||||
var roi =
|
||||
ee.Geometry.Polygon(
|
||||
[[[120.34892531309845, 43.64119426062719],
|
||||
[120.34892531309845, 43.618332108842225],
|
||||
[120.39218398009064, 43.618332108842225],
|
||||
[120.39218398009064, 43.64119426062719]]], null, false);
|
||||
|
||||
Map.centerObject(roi, 12)
|
||||
|
||||
|
||||
var l8sr = imageCollection
|
||||
.filterBounds(roi);
|
||||
|
||||
// This field contains UNIX time in milliseconds.
|
||||
var timeField = 'system:time_start';
|
||||
|
||||
function maskL8sr(image) {
|
||||
// Bit 0 - Fill
|
||||
// Bit 1 - Dilated Cloud
|
||||
// Bit 2 - Cirrus
|
||||
// Bit 3 - Cloud
|
||||
// Bit 4 - Cloud Shadow
|
||||
var qa = image.select('QA_PIXEL')
|
||||
|
||||
var cloud = qa.bitwiseAnd(1 << 1)
|
||||
.or(qa.bitwiseAnd(1 << 2))
|
||||
.or(qa.bitwiseAnd(1 << 3))
|
||||
.or(qa.bitwiseAnd(1 << 4))
|
||||
|
||||
|
||||
// The flags should equal zero, indicating clear conditions.
|
||||
var mask = cloud.eq(0);
|
||||
//var ndwiMasked = ndwi.updateMask(ndwi.gte(0.4));
|
||||
// Apply the scaling factors to the appropriate bands.
|
||||
var opticalBands = image.select('SR_B.').multiply(0.0000275).add(-0.2);
|
||||
|
||||
// Replace the original bands with the scaled ones and apply the masks.
|
||||
return image.addBands(opticalBands, null, true)
|
||||
.updateMask(mask)
|
||||
.copyProperties(image, ['system:time_start']);
|
||||
}
|
||||
|
||||
// Use this function to add variables for NDVI, time and a constant
|
||||
// to Landsat 8 imagery.
|
||||
var addVariables = function(image) {
|
||||
// Compute time in fractional years since the epoch.
|
||||
var date = ee.Date(image.get(timeField));
|
||||
var years = date.difference(ee.Date('1970-01-01'), 'year');
|
||||
// Return the image with the added bands.
|
||||
return image
|
||||
// Add an NDVI band.
|
||||
.addBands(image.normalizedDifference(['SR_B5', 'SR_B4']).rename('NDVI'))
|
||||
// Add a time band.
|
||||
.addBands(ee.Image(years).rename('t'))
|
||||
.float()
|
||||
// Add a constant band.
|
||||
.addBands(ee.Image.constant(1));
|
||||
};
|
||||
|
||||
// Remove clouds, add variables and filter to the area of interest.
|
||||
var filteredLandsat = l8sr
|
||||
.filterBounds(roi)
|
||||
.filter(ee.Filter.calendarRange(8,8, 'month'))
|
||||
.map(maskL8sr)
|
||||
.map(addVariables);
|
||||
|
||||
|
||||
// Plot a time series of NDVI at a single location.
|
||||
var l8Chart = ui.Chart.image.series(filteredLandsat.select('NDVI'), roi)
|
||||
.setChartType('ScatterChart')
|
||||
.setOptions({
|
||||
title: 'Landsat 8 NDVI time series at ROI',
|
||||
trendlines: {0: {
|
||||
color: 'CC0000'
|
||||
}},
|
||||
lineWidth: 1,
|
||||
pointSize: 3,
|
||||
});
|
||||
print(l8Chart);
|
||||
|
||||
// Display the overall mean NDVI of the time series
|
||||
Map.addLayer(filteredLandsat.select('NDVI').first(), {min: 0, max: 1}, "Mean NDVI")
|
||||
|
||||
|
||||
// List of the independent variable names
|
||||
var independents = ee.List(['constant', 't']);
|
||||
|
||||
// Name of the dependent variable.
|
||||
var dependent = ee.String('NDVI');
|
||||
|
||||
// Compute a linear trend. This will have two bands: 'residuals' and
|
||||
// a 2x1 band called coefficients (columns are for dependent variables).
|
||||
var trend = filteredLandsat.select(independents.add(dependent))
|
||||
.reduce(ee.Reducer.linearRegression(independents.length(), 1));
|
||||
Map.addLayer(trend, {}, 'trend array image');
|
||||
|
||||
// Flatten the coefficients into a 2-band image
|
||||
var coefficients = trend.select('coefficients')
|
||||
.arrayProject([0])
|
||||
.arrayFlatten([independents]);
|
||||
|
||||
print(coefficients)
|
||||
|
||||
|
||||
Map.addLayer(coefficients.select('t'), {min: -0.05, max: 0.05}, "gain b")
|
||||
Map.addLayer(coefficients.select('constant'),{min: -0.1, max: 1}, "offset a")
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
/////// NDVI time series over Landsat 5,7 and 8
|
||||
|
||||
|
||||
// to be defined
|
||||
Map.centerObject(roi, 12)
|
||||
|
||||
var startyear = '1984-01-01'
|
||||
var endyear = '2021-12-31'
|
||||
|
||||
var startmonth = 9
|
||||
var endmonth = 9
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//// Functions that are applied to every image of a collection
|
||||
// Due to the specific sensor characteristics of TM and OLI, specific function are needed for the sensors
|
||||
|
||||
// 1) Cloud masking
|
||||
// 2) Rename Bands
|
||||
// 3) Add NDVI and two bands to save the result of the linear regression (gain and constant)
|
||||
|
||||
// 1) Cloud masking
|
||||
// Function to cloud mask from the pixel_qa band of Landsat 5 and 7 SR data.
|
||||
// (From the Code Editor Examples > Cloud Masking)
|
||||
function maskL457sr(image) {
|
||||
|
||||
// Bit 0 - Fill
|
||||
// Bit 1 - Dilated Cloud
|
||||
// Bit 2 - Cirrus
|
||||
// Bit 3 - Cloud
|
||||
// Bit 4 - Cloud Shadow
|
||||
var qa = image.select('QA_PIXEL');
|
||||
|
||||
var cloud = qa.bitwiseAnd(1 << 0)
|
||||
.or(qa.bitwiseAnd(1 << 1))
|
||||
.or(qa.bitwiseAnd(1 << 2))
|
||||
.or(qa.bitwiseAnd(1 << 3))
|
||||
.or(qa.bitwiseAnd(1 << 4));
|
||||
|
||||
|
||||
// The flags should equal zero, indicating clear conditions.
|
||||
var mask = cloud.eq(0);
|
||||
|
||||
// Apply the scaling factors to the appropriate bands.
|
||||
var opticalBands = image.select('SR_B1',"SR_B2", "SR_B3","SR_B4","SR_B5","SR_B7").multiply(0.0000275).add(-0.2);
|
||||
|
||||
// Replace the original bands with the scaled ones and apply the masks.
|
||||
return image.addBands(opticalBands, null, true)
|
||||
.updateMask(mask)
|
||||
.copyProperties(image, ['system:time_start']);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Function to cloud mask from the pixel_qa band of Landsat 8 SR data.
|
||||
|
||||
function maskL8sr(image) {
|
||||
// Bit 0 - Fill
|
||||
// Bit 1 - Dilated Cloud
|
||||
// Bit 2 - Cirrus
|
||||
// Bit 3 - Cloud
|
||||
// Bit 4 - Cloud Shadow
|
||||
var qa = image.select('QA_PIXEL');
|
||||
|
||||
var cloud = qa.bitwiseAnd(1 << 0)
|
||||
.or(qa.bitwiseAnd(1 << 1))
|
||||
.or(qa.bitwiseAnd(1 << 2))
|
||||
.or(qa.bitwiseAnd(1 << 3))
|
||||
.or(qa.bitwiseAnd(1 << 4));
|
||||
|
||||
|
||||
// The flags should equal zero, indicating clear conditions.
|
||||
var mask = cloud.eq(0);
|
||||
|
||||
// Apply the scaling factors to the appropriate bands.
|
||||
var opticalBands = image.select('SR_B.').multiply(0.0000275).add(-0.2);
|
||||
|
||||
// Replace the original bands with the scaled ones and apply the masks.
|
||||
return image.addBands(opticalBands, null, true)
|
||||
.updateMask(mask)
|
||||
.copyProperties(image, ['system:time_start']);
|
||||
}
|
||||
|
||||
|
||||
// 2) Rename Bands
|
||||
|
||||
// Function to rename bands of Landsat 5 and 7 to match Landsat 8
|
||||
function renameBandsTM(image) {
|
||||
var bands = ['SR_B1', 'SR_B2', 'SR_B3', 'SR_B4', 'SR_B5', 'SR_B7'];
|
||||
var new_bands = ['B', 'G', 'R', 'NIR', 'SWIR1', 'SWIR2'];
|
||||
return image.select(bands).rename(new_bands).copyProperties(image, ['system:time_start']);
|
||||
}
|
||||
|
||||
// Function to rename bands of Landsat 8 to match Landsat 5 and 8
|
||||
function renameBandsOLI(image){
|
||||
var bands = ['SR_B2', 'SR_B3', 'SR_B4', 'SR_B5', 'SR_B6', 'SR_B7'];
|
||||
var new_bands = ['B', 'G', 'R', 'NIR', 'SWIR1', 'SWIR2'];
|
||||
return image.select(bands).rename(new_bands).copyProperties(image, ['system:time_start']);
|
||||
}
|
||||
|
||||
|
||||
// 3) Add NDVI and two bands to save the result of the linear regression (gain and constant)
|
||||
|
||||
// This field contains UNIX time in milliseconds.
|
||||
var timeField = 'system:time_start';
|
||||
|
||||
|
||||
function addVariables(image) {
|
||||
// Compute time in fractional years since the epoch.
|
||||
var date = ee.Date(image.get(timeField));
|
||||
var years = date.difference(ee.Date('1970-01-01'), 'year');
|
||||
// Return the image with the added bands.
|
||||
return image
|
||||
// Add an NDVI band.
|
||||
.addBands(image.normalizedDifference(['NIR', 'R']).rename('NDVI'))
|
||||
// Add a time band.
|
||||
.addBands(ee.Image(years).rename('gain'))
|
||||
.float()
|
||||
// Add a constant band.
|
||||
.addBands(ee.Image.constant(1));
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Create collections of Landsat 5, 7 and 8
|
||||
|
||||
// a) using filters (calendar range and ROI)
|
||||
// b) using the three functions (cloud masking, rename bands, add NDVI)
|
||||
// c) Merge the collections --> combine the three collections to form a time series over the entire time span
|
||||
|
||||
// Landat 5 surface reflection data
|
||||
var L5coll = ee.ImageCollection('LANDSAT/LT05/C02/T1_L2')
|
||||
.filterBounds(roi)
|
||||
.filter(ee.Filter.calendarRange(startmonth,endmonth, 'month'))
|
||||
.filterDate(startyear, endyear)
|
||||
.map(maskL457sr)
|
||||
.map(renameBandsTM)
|
||||
.map(addVariables);
|
||||
|
||||
// Landat 7 surface reflection data
|
||||
var L7coll = ee.ImageCollection('LANDSAT/LE07/C02/T1_L2')
|
||||
.filter(ee.Filter.calendarRange(startmonth,endmonth, 'month'))
|
||||
.filterDate(startyear, endyear)
|
||||
.filterBounds(roi)
|
||||
.map(maskL457sr)
|
||||
.map(renameBandsTM)
|
||||
.map(addVariables);
|
||||
|
||||
|
||||
// Landat 8 surface reflection data, rename the band names. See USGS pages for more info
|
||||
var L8coll = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2')
|
||||
.filter(ee.Filter.calendarRange(startmonth,endmonth, 'month'))
|
||||
.filterDate(startyear, endyear)
|
||||
.filterBounds(roi)
|
||||
.map(maskL8sr)
|
||||
.map(renameBandsOLI)
|
||||
.map(addVariables)
|
||||
|
||||
|
||||
|
||||
// merge L5, L7 & L8
|
||||
var collection_merge = ee.ImageCollection(L5coll.merge(L7coll.merge(L8coll)));
|
||||
print (collection_merge)
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Plot time series for an ROI
|
||||
|
||||
// Plot a time series of NDVI at a single location.
|
||||
var l8Chart = ui.Chart.image.series(collection_merge.select('NDVI'), roi)
|
||||
.setChartType('ScatterChart')
|
||||
.setOptions({
|
||||
title: 'Landsat NDVI time series at ROI',
|
||||
trendlines: {0: {
|
||||
color: 'CC0000'
|
||||
}},
|
||||
lineWidth: 1,
|
||||
pointSize: 3,
|
||||
});
|
||||
print(l8Chart);
|
||||
|
||||
|
||||
// Display the NDVI of the time series (mean, first image, last image)
|
||||
Map.addLayer(collection_merge.select("NDVI").mean(),{min:0, max:1}, "Mean NDVI Landsat 8")
|
||||
Map.addLayer(collection_merge.select("NDVI").first(),{min:0, max:1}, "Oldest image within time series")
|
||||
Map.addLayer(collection_merge.sort("system:time_start",false).select("NDVI").first(),{min:0, max:1}, "Newest image within time series")
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Trend analysis
|
||||
// Calculate the constant and gain of the linear regression of the NDVI on a per-pixel basis
|
||||
|
||||
Map.centerObject(roi, 11)
|
||||
|
||||
// List of the independent variable names
|
||||
var independents = ee.List(['constant', 'gain']);
|
||||
|
||||
// Name of the dependent variable.
|
||||
var dependent = ee.String('NDVI');
|
||||
|
||||
// Compute a linear trend. This will have two bands: 'residuals' and
|
||||
// a 2x1 band called 'coefficients' (columns are for dependent variables).
|
||||
var trend = collection_merge.select(independents.add(dependent))
|
||||
.reduce(ee.Reducer.linearRegression(independents.length(), 1));
|
||||
// Map.addLayer(trend, {}, 'trend array image');
|
||||
|
||||
// Flatten the coefficients into a 2-band image
|
||||
var coefficients = trend.select('coefficients')
|
||||
.arrayProject([0])
|
||||
.arrayFlatten([independents]);
|
||||
|
||||
// Plot the two bands as gray scale
|
||||
Map.addLayer(coefficients.select('gain'), {min:-0.01, max: 0.01}, "gain")
|
||||
Map.addLayer(coefficients.select('constant'), {},"constant")
|
||||
|
||||
// Plot the two bands in a RGB-False colour Composite (positive trends = greenish, negative trends = reddish)
|
||||
Map.addLayer(coefficients,
|
||||
{min: 0, max: [-0.02, 0.02, 0.7], bands: ['gain', 'gain', 'constant']},
|
||||
'Trend analysis')
|
||||
@@ -0,0 +1,108 @@
|
||||
//The Hansen et al. (2013) Global Forest Change dataset in Earth Engine represents
|
||||
//forest change, at 30 meters resolution, globally, between 2000 and 2014. Let's start
|
||||
//by adding the Hansen et al. data to the map. Import the global forest change
|
||||
//data (learn more about searching and importing datasets) by searching for "Hansen forest"
|
||||
//and naming the import gfc2014:
|
||||
|
||||
//Recall that when a multi-band image is added to a map, the first three bands of the
|
||||
//image are chosen as red, green, and blue, respectively, and stretched according to the
|
||||
//data type of each band. The reason the image looks red is that the first three bands
|
||||
//are treecover2000, loss, and gain. The treecover2000 band is expressed as a percent
|
||||
//and has values much higher than loss (green) and gain (blue) which are binary ({0, 1}).
|
||||
//The image therefore displays as overwhelmingly red.
|
||||
|
||||
var gfc2014 = ee.Image("UMD/hansen/global_forest_change_2020_v1_8");
|
||||
Map.addLayer(gfc2014);
|
||||
|
||||
//To display forest cover in the year 2000 as a grayscale image,
|
||||
//you can use the treecover2000 band, specified in the second argument
|
||||
//to Map.addLayer():
|
||||
|
||||
Map.addLayer(gfc2014, {bands: ['treecover2000']}, 'treecover2000');
|
||||
|
||||
///
|
||||
//Display the band that differentiates land surface and permanent water bodies.
|
||||
// Set min and max in the display options!
|
||||
Map.addLayer(gfc2014, {bands: ['datamask'], min:0, max:2}, 'datamask');
|
||||
|
||||
|
||||
//Here's an image that uses 3 bands, Landsat bands 5, 4, and 3 for 2015.
|
||||
// This band combination shows healthy vegetation as green and soil as mauve:
|
||||
|
||||
Map.addLayer(
|
||||
gfc2014, {bands: ['last_b50', 'last_b40', 'last_b30']}, 'false color');
|
||||
|
||||
|
||||
//One nice visualization of the Global Forest Change dataset shows forest extent
|
||||
//in 2000 as green, forest loss as red, and forest gain as blue.
|
||||
//Specifically, make loss the first band (red), treecover2000 the second band (green),
|
||||
//and gain the third band (blue):
|
||||
Map.addLayer(gfc2014, {bands: ['loss', 'treecover2000', 'gain']}, 'green');
|
||||
|
||||
|
||||
//We'd like forest loss to show up as bright red and forest gain to show up as bright
|
||||
//blue. To fix this, we can use the visualization parameter max to set the range to
|
||||
//which the image data are stretched. Note that the max visualization parameter
|
||||
//takes a list of values, corresponding to maxima for each band:
|
||||
Map.addLayer(gfc2014, {
|
||||
bands: ['loss', 'treecover2000', 'gain'],
|
||||
max: [1, 255, 1]
|
||||
}, 'forest cover, loss, gain');
|
||||
|
||||
|
||||
/// Improve displaying tree cover (forest extent)
|
||||
|
||||
//Use a green palette to display the forest extent image:
|
||||
Map.addLayer(gfc2014, {
|
||||
bands: ['treecover2000'],
|
||||
palette: ['000000', '00FF00']
|
||||
}, 'forest cover palette');
|
||||
|
||||
//The image shown in Figure 8 is a bit dark. The problem is that the treecover2000
|
||||
//band has a byte data type ([0, 255]), when in fact the values are precentages ([0, 100]).
|
||||
//To brighten the image, you can set the min and/or max parameters accordingly.
|
||||
// The palette is then stretched between those extrema.
|
||||
Map.addLayer(gfc2014, {
|
||||
bands: ['treecover2000'],
|
||||
palette: ['000000', '00FF00'],
|
||||
max: 100
|
||||
}, 'forest cover percent');
|
||||
|
||||
//All of the images shown so far have had big black areas were there the data is zero.
|
||||
//For example, there are no trees in the ocean. To make these areas transparent,
|
||||
//you can mask their values. Every pixel in Earth Engine has both a value and a mask.
|
||||
//The image is rendered with transparency set by the mask, with zero being completely
|
||||
//transparent and one being completely opaque.
|
||||
|
||||
//You can mask an image with itself. For example, if you mask the treecover2000 band
|
||||
//with itself, all the areas in which forest cover is zero will be transparent:
|
||||
Map.addLayer(gfc2014.mask(gfc2014), {
|
||||
bands: ['treecover2000'],
|
||||
palette: ['000000', '00FF00'],
|
||||
max: 100
|
||||
}, 'forest cover masked');
|
||||
|
||||
//You can mask an image by a mask. For example, if you mask the treecover2000 band
|
||||
//where all the values are unter 10%, i.e. you want to keep the areas that have at
|
||||
//least 10% tree cover, all the areas in which forest cover is zero will be transparent:
|
||||
var mask10 = gfc2014.select("treecover2000").gte(10)
|
||||
|
||||
Map.addLayer(gfc2014.mask(mask10), {
|
||||
bands: ['treecover2000'],
|
||||
palette: ['000000', '00FF00'],
|
||||
min:0, max: 100
|
||||
}, 'forest cover masked - >10%');
|
||||
|
||||
|
||||
// The same as before but with a threshold of 30%.
|
||||
var mask30 = gfc2014.select("treecover2000").gte(30)
|
||||
|
||||
Map.addLayer(gfc2014.mask(mask30), {
|
||||
bands: ['treecover2000'],
|
||||
palette: ['000000', '00FF00'],
|
||||
min:0, max: 100
|
||||
}, 'forest cover masked - >30%');
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
//It's almost possible to make a visualization of the Hansen data like the one at the
|
||||
//beginning of the tutorial. In this example, we're putting everything together
|
||||
//with one small difference. Instead of specifying the bands parameter in the
|
||||
//Map.addLayer call, we're creating new images using select():
|
||||
var gfc2014 = ee.Image("UMD/hansen/global_forest_change_2020_v1_8");
|
||||
|
||||
|
||||
var treeCover = gfc2014.select(['treecover2000']);
|
||||
var lossImage = gfc2014.select(['loss']);
|
||||
var gainImage = gfc2014.select(['gain']);
|
||||
|
||||
// Add the tree cover layer in green.
|
||||
Map.addLayer(treeCover.updateMask(treeCover),
|
||||
{palette: ['000000', '00FF00'], max: 100}, 'Forest Cover');
|
||||
|
||||
// Add the loss layer in red.
|
||||
Map.addLayer(lossImage.updateMask(lossImage),
|
||||
{palette: ['FF0000']}, 'Loss');
|
||||
|
||||
// Add the gain layer in blue.
|
||||
Map.addLayer(gainImage.updateMask(gainImage),
|
||||
{palette: ['0000FF']}, 'Gain');
|
||||
@@ -0,0 +1,51 @@
|
||||
//Let's start with the calculation needed to create a band that shows pixels
|
||||
//where the Hansen et al. data show both loss and gain.
|
||||
|
||||
//The Hansen et al. dataset has a band whose pixels are 1 where loss occurred
|
||||
//and 0 otherwise (loss) and a band that is 1 where gain has occurred and a 0 otherwise (gain).
|
||||
//To create a band where pixels in both the loss and the gain bands have a 1,
|
||||
//you can use the and() logical method on images. The and() method is called
|
||||
//like image1.and(image2) and returns an image in which pixels are 1 where both
|
||||
//image1 and image2 are 1, and 0 elsewhere:
|
||||
// Load the data and select the bands of interest.
|
||||
|
||||
var gfc2014 = ee.Image("UMD/hansen/global_forest_change_2020_v1_8");
|
||||
var lossImage = gfc2014.select(['loss']);
|
||||
var gainImage = gfc2014.select(['gain']);
|
||||
|
||||
// Use the and() method to create the lossAndGain image.
|
||||
var gainAndLoss = gainImage.and(lossImage);
|
||||
|
||||
// Show the loss and gain image.
|
||||
Map.addLayer(gainAndLoss.updateMask(gainAndLoss),
|
||||
{palette: 'FF00FF'}, 'Gain and Loss');
|
||||
|
||||
|
||||
//Combining this example with the result from the previous section,
|
||||
//it's now possible to recreate the figure from the beginning of the tutorial:
|
||||
|
||||
// Displaying forest, loss, gain, and pixels where both loss and gain occur.
|
||||
var gfc2014 = ee.Image('UMD/hansen/global_forest_change_2015');
|
||||
var lossImage = gfc2014.select(['loss']);
|
||||
var gainImage = gfc2014.select(['gain']);
|
||||
var treeCover = gfc2014.select(['treecover2000']);
|
||||
|
||||
// Use the and() method to create the lossAndGain image.
|
||||
var gainAndLoss = gainImage.and(lossImage);
|
||||
|
||||
// Add the tree cover layer in green.
|
||||
Map.addLayer(treeCover.updateMask(treeCover),
|
||||
{palette: ['000000', '00FF00'], max: 100}, 'Forest Cover');
|
||||
|
||||
// Add the loss layer in red.
|
||||
Map.addLayer(lossImage.updateMask(lossImage),
|
||||
{palette: ['FF0000']}, 'Loss');
|
||||
|
||||
// Add the gain layer in blue.
|
||||
Map.addLayer(gainImage.updateMask(gainImage),
|
||||
{palette: ['0000FF']}, 'Gain');
|
||||
|
||||
// Show the loss and gain image.
|
||||
Map.addLayer(gainAndLoss.updateMask(gainAndLoss),
|
||||
{palette: 'FF00FF'}, 'Gain and Loss');
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
//Now that you're more familiar with the bands in the Hansen et al. dataset,
|
||||
//we can use concepts learned so far to compute statistics about forest gain
|
||||
//and loss in a region of interest. For this we'll need to use vector data
|
||||
//(points, lines, and polygons). A vector dataset is represented as a
|
||||
//FeatureCollection in Earth Engine. (Learn more about feature collections
|
||||
//and how to import vector data.)
|
||||
|
||||
//In this section, we'll compare the total amount of forest loss that happened
|
||||
//within the Republic of the Congo in the year 2012 to the amount of forest loss that
|
||||
//happened within the country's protected areas at the same time.
|
||||
|
||||
//As you learned in the Earth Engine API tutorial, the key method for calculating
|
||||
//statistics in an image region is reduceRegion(). (Learn more about reducing image
|
||||
//regions.) For example, suppose we want to calculate the number of pixels estimated
|
||||
//to represent forest loss during the study period. For that purpose, consider the
|
||||
//following code.
|
||||
|
||||
|
||||
//The example uses the ee.Reducer.sum() reducer to sum the values of the
|
||||
//pixels in lossImage within the Republic of the Congo feature. Because lossImage consists
|
||||
//of pixels that have a value of 1 or 0 (for loss or not loss, respectively),
|
||||
//the sum of these values is equivalent to the number of pixels of loss in the
|
||||
//region.
|
||||
|
||||
|
||||
// Load country features from Large Scale International Boundary (LSIB) dataset.
|
||||
var countries = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017');
|
||||
|
||||
// Subset the Republic of the Canada feature from countries.
|
||||
var germany = countries.filter(ee.Filter.eq('country_na', 'Germany'));
|
||||
|
||||
// Get the forest loss image.
|
||||
var gfc2014 = ee.Image("UMD/hansen/global_forest_change_2020_v1_8");
|
||||
var lossImage = gfc2014.select(['loss']);
|
||||
|
||||
// Sum the values of forest loss pixels in Canada.
|
||||
var stats = lossImage.reduceRegion({
|
||||
reducer: ee.Reducer.sum(),
|
||||
geometry: germany,
|
||||
scale: 30,
|
||||
maxPixels: 2e9
|
||||
});
|
||||
print(stats);
|
||||
|
||||
|
||||
//By expanding the object printed to the console, observe that the
|
||||
//result is 4897933 (in the original example!) pixels of forest lost. You can
|
||||
//clean up the printout in the console a bit by labeling the output
|
||||
//and getting the result of interest from the dictionary returned
|
||||
//by reduceRegion():
|
||||
|
||||
print('pixels representing loss: ', stats.get('loss'));
|
||||
|
||||
|
||||
//You're almost ready to answer the question of how much area was lost in
|
||||
//the Republic of the Congo.
|
||||
//The remaining part is to convert pixels into actual area. This conversion
|
||||
//is important because we don't necessarily know the size of the pixels input
|
||||
//to reduceRegion(). To help compute areas, Earth Engine has the ee.Image.pixelArea()
|
||||
//method which generates an image in which the value of each pixel is the pixel's
|
||||
//area in square meters. Multiplying the loss image with this area image and then
|
||||
//summing over the result gives us a measure of area:
|
||||
// Load country features from Large Scale International Boundary (LSIB) dataset.
|
||||
var countries = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017');
|
||||
|
||||
// Subset Republic of the Congo feature from countries.
|
||||
var germany = countries.filter(ee.Filter.eq('country_na', 'Germany'));
|
||||
|
||||
// Get the forest loss image.
|
||||
//var gfc2014 = ee.Image('UMD/hansen/global_forest_change_2015'); //we did already open that one
|
||||
var lossImage = gfc2014.select(['loss']);
|
||||
var areaImage = lossImage.multiply(ee.Image.pixelArea()).divide(1000000);
|
||||
|
||||
|
||||
// Sum the values of forest loss pixels in Canada.
|
||||
var stats = areaImage.reduceRegion({
|
||||
reducer: ee.Reducer.sum(),
|
||||
geometry: germany,
|
||||
scale: 30,
|
||||
maxPixels: 2e9
|
||||
});
|
||||
|
||||
print('pixels representing loss: ', stats.get('loss'), 'square km');
|
||||
|
||||
|
||||
//You are now ready to answer the question at the start of this section - how
|
||||
//much forest area was lost in the Republic of the Congo in 2012, and how much of that
|
||||
//was in protected areas? Have a look in the next script.
|
||||
@@ -0,0 +1,67 @@
|
||||
//You are now ready to answer the question at the start of this
|
||||
//section - how much forest area was lost in the Republic of the Congo in
|
||||
//2012, and how much of that was in protected areas?
|
||||
|
||||
// Load country features from Large Scale International Boundary (LSIB) dataset.
|
||||
var countries = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017');
|
||||
|
||||
// Subset the Congo Republic feature from countries.
|
||||
var congo = ee.Feature(
|
||||
countries
|
||||
.filter(ee.Filter.eq('country_na', 'Rep of the Congo'))
|
||||
.first()
|
||||
);
|
||||
|
||||
// Subset protected areas to the bounds of the feature of the Republic of the Congo
|
||||
// and other criteria. Clip to the intersection with the Republic of the Congo.
|
||||
var protectedAreas = ee.FeatureCollection('WCMC/WDPA/current/polygons')
|
||||
.filter(ee.Filter.and(
|
||||
ee.Filter.bounds(congo.geometry()),
|
||||
ee.Filter.neq('IUCN_CAT', 'VI'),
|
||||
ee.Filter.neq('STATUS', 'proposed'),
|
||||
ee.Filter.lt('STATUS_YR', 2010)
|
||||
))
|
||||
.map(function(feat){
|
||||
return congo.intersection(feat);
|
||||
});
|
||||
|
||||
// Get the loss image.
|
||||
var gfc2014 = ee.Image('UMD/hansen/global_forest_change_2015');
|
||||
var lossIn2012 = gfc2014.select(['lossyear']).eq(12);
|
||||
var areaImage = lossIn2012.multiply(ee.Image.pixelArea());
|
||||
|
||||
// Calculate the area of loss pixels in the Republic of the Congo.
|
||||
var stats = areaImage.reduceRegion({
|
||||
reducer: ee.Reducer.sum(),
|
||||
geometry: congo.geometry(),
|
||||
scale: 30,
|
||||
maxPixels: 1e9
|
||||
});
|
||||
|
||||
print(
|
||||
'Area lost in the Republic of the Congo:',
|
||||
stats.get('lossyear'),
|
||||
'square meters'
|
||||
);
|
||||
|
||||
// Calculate the area of loss pixels in the protected areas.
|
||||
var stats2 = areaImage.reduceRegion({
|
||||
reducer: ee.Reducer.sum(),
|
||||
geometry: protectedAreas.geometry(),
|
||||
scale: 30,
|
||||
maxPixels: 2e9
|
||||
});
|
||||
|
||||
print(
|
||||
'Area lost in protected areas:',
|
||||
stats2.get('lossyear'),
|
||||
'square meters'
|
||||
);
|
||||
|
||||
|
||||
//The only changes between this script and the one just prior are the
|
||||
//addition of the protected area information and changing the script
|
||||
//from looking at overall loss to looking at loss in 2012. This required
|
||||
//two changes. First, there's a new lossIn2012 image which has a 1 where loss
|
||||
//was recorded in 2012, 0 otherwise. Second, because the name of the band is different
|
||||
//(lossyear instead of loss) the property name had to change in the print statement.
|
||||
@@ -0,0 +1,70 @@
|
||||
//In the previous section you learned how to calculate total forest area lost in
|
||||
//the given region of interest using the reduceRegion method. Instead of
|
||||
//calculating the total loss, it would be helpful to compute the loss for
|
||||
//each year. The way to achieve this in Earth Engine is using a Grouped Reducer.
|
||||
|
||||
//To group output of reduceRegion(), you can specify a grouping band that
|
||||
//defines groups by integer pixel values. In the following example, we
|
||||
//slightly modify the previous code and add the lossYear band to the original
|
||||
//image. Each pixel in the lossYear band contain values from 0 to 14 - indicating
|
||||
//the year in which the loss occurred. We also change the reducer to a grouped
|
||||
//reducer, specifying the band index of the grouping band (1) so the pixel
|
||||
//areas will be summed and grouped according to the value in the lossYear band.
|
||||
|
||||
// Load country boundaries from LSIB.
|
||||
var countries = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017');
|
||||
// Get a feature collection with just the feature of the Republic of the Congo.
|
||||
var congo = countries.filter(ee.Filter.eq('country_na', 'Germany'));
|
||||
|
||||
// Get the loss image.
|
||||
// This dataset is updated yearly, so we get the latest version.
|
||||
var gfc2017 = ee.Image("UMD/hansen/global_forest_change_2020_v1_8");
|
||||
var lossImage = gfc2017.select(['loss']);
|
||||
var lossAreaImage = lossImage.multiply(ee.Image.pixelArea());
|
||||
|
||||
var lossYear = gfc2017.select(['lossyear']);
|
||||
var lossByYear = lossAreaImage.addBands(lossYear).reduceRegion({
|
||||
reducer: ee.Reducer.sum().group({
|
||||
groupField: 1
|
||||
}),
|
||||
geometry: congo,
|
||||
scale: 30,
|
||||
maxPixels: 1e10
|
||||
});
|
||||
print(lossByYear);
|
||||
|
||||
//Once you run the above code, you will see the yearly forest
|
||||
//loss area printed out in a nested list called groups. We can format
|
||||
//the output a little to make the result a dictionary, with year as the
|
||||
//key and loss area as the value. Notice that we are using the format()
|
||||
//method to convert the year values from 0-14 to 2000-2014.
|
||||
|
||||
var statsFormatted = ee.List(lossByYear.get('groups'))
|
||||
.map(function(el) {
|
||||
var d = ee.Dictionary(el);
|
||||
return [ee.Number(d.get('group')).format("20%02d"), d.get('sum')];
|
||||
});
|
||||
var statsDictionary = ee.Dictionary(statsFormatted.flatten());
|
||||
print(statsDictionary);
|
||||
|
||||
//Now that we have yearly loss numbers, we are ready to prepare a chart.
|
||||
//We will use the ui.Chart.array.values() method. This method takes an array
|
||||
//(or list) of input values and an array (or list) of labels for the X-axis.
|
||||
var chart = ui.Chart.array.values({
|
||||
array: statsDictionary.values(),
|
||||
axis: 0,
|
||||
xLabels: statsDictionary.keys()
|
||||
}).setChartType('ColumnChart')
|
||||
.setOptions({
|
||||
title: 'Yearly Forest Loss in Germany',
|
||||
hAxis: {title: 'Year', format: '####'},
|
||||
vAxis: {title: 'Area (square meters)'},
|
||||
legend: { position: "none" },
|
||||
lineWidth: 1,
|
||||
pointSize: 3
|
||||
});
|
||||
print(chart);
|
||||
|
||||
// This is how you can add a vector layer to the map view.
|
||||
Map.addLayer(congo, {color: 'FF0000'}, 'Germany');
|
||||
|
||||
Reference in New Issue
Block a user