-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSnow And Forest
138 lines (115 loc) · 4.96 KB
/
Snow And Forest
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/**** Start of imports. If edited, may not auto-convert in the playground. ****/
var waterImages = ee.Image("MODIS/MOD44W/MOD44W_005_2000_02_24"),
snowCover = ee.ImageCollection("MODIS/006/MOD10A1"),
dataset = ee.Image("UMD/hansen/global_forest_change_2022_v1_10"),
maps = ee.FeatureCollection("USDOS/LSIB_SIMPLE/2017");
/***** End of imports. If edited, may not auto-convert in the playground. *****/
var startDoy = 1;
var startYear = 2000;
var endYear = 2019;
var startDate;
var startYear;
function addDateBands(img) {
// Get image date.
var date = img.date();
// Get calendar day-of-year.
var calDoy = date.getRelative('day', 'year');
// Get relative day-of-year; enumerate from user-defined startDoy.
var relDoy = date.difference(startDate, 'day');
// Get the date as milliseconds from Unix epoch.
var millis = date.millis();
// Add all of the above date info as bands to the snow fraction image.
var dateBands = ee.Image.constant([calDoy, relDoy, millis, startYear])
.rename(['calDoy', 'relDoy', 'millis', 'year']);
// Cast bands to correct data type before returning the image.
return img.addBands(dateBands)
.cast({'calDoy': 'int', 'relDoy': 'int', 'millis': 'long', 'year': 'int'})
.set('millis', millis);
}
var waterMask = waterImages.select('water_mask').not();
var completeCol = snowCover.select('NDSI_Snow_Cover');
// Pixels must have been 10% snow covered for at least 2 weeks in 2018.
var snowCoverEphem = completeCol.filterDate('2018-01-01', '2019-01-01')
.map(function(img) {
return img.gte(10);
})
.sum()
.gte(14);
// Pixels must not be 10% snow covered more than 124 days in 2018.
var snowCoverConst = completeCol.filterDate('2018-01-01', '2019-01-01')
.map(function(img) {
return img.gte(10);
})
.sum()
.lte(124);
var analysisMask = waterMask.multiply(snowCoverEphem).multiply(snowCoverConst);
var years = ee.List.sequence(startYear, endYear);
var annualList = years.map(function(year) {
// Set the global startYear variable as the year being worked on so that
// it will be accessible to the addDateBands mapped to the collection below.
startYear = year;
// Get the first day-of-year for this year as an ee.Date object.
var firstDoy = ee.Date.fromYMD(year, 1, 1);
// Advance from the firstDoy to the user-defined startDay; subtract 1 since
// firstDoy is already 1. Set the result as the global startDate variable so
// that it is accessible to the addDateBands mapped to the collection below.
startDate = firstDoy.advance(startDoy-1, 'day');
// Get endDate for this year by advancing 1 year from startDate.
// Need to advance an extra day because end date of filterDate() function
// is exclusive.
var endDate = startDate.advance(1, 'year').advance(1, 'day');
// Filter the complete collection by the start and end dates just defined.
var yearCol = completeCol.filterDate(startDate, endDate);
// Construct an image where pixels represent the first day within the date
// range that the lowest snow fraction is observed.
var noSnowImg = yearCol
// Add date bands to all images in this particular collection.
.map(addDateBands)
// Sort the images by ascending time to identify the first day without
// snow. Alternatively, you can use .sort('millis', false) to
// reverse sort (find first day of snow in the fall).
.sort('millis')
// Make a mosaic composed of pixels from images that represent the
// observation with the minimum percent snow cover (defined by the
// NDSI_Snow_Cover band); include all associated bands for the selected
// image.
.reduce(ee.Reducer.min(5))
// Rename the bands - band names were altered by previous operation.
.rename(['snowCover', 'calDoy', 'relDoy', 'millis', 'year'])
// Apply the mask.
.updateMask(analysisMask)
// Set the year as a property for filtering by later.
.set('year', year);
// Mask by minimum snow fraction - only include pixels that reach 0
// percent cover. Return the resulting image.
return noSnowImg.updateMask(noSnowImg.select('snowCover').eq(0));
});
var annualCol = ee.ImageCollection.fromImages(annualList);
// Define the years to difference.
var firstYear = 2005;
var secondYear = 2015;
// Calculate difference image.
var firstImg = annualCol.filter(ee.Filter.eq('year', firstYear))
.first().select('calDoy');
var secondImg = annualCol.filter(ee.Filter.eq('year', secondYear))
.first().select('calDoy');
var dif = secondImg.subtract(firstImg);
// Define visualization arguments.
var visArgs = {
min: -15,
max: 15,
palette: ['b2182b', 'ef8a62', 'fddbc7', 'f7f7f7', 'd1e5f0', '67a9cf', '2166ac']};
// Map it.
var usa = maps.filter(ee.Filter.eq('country_co', 'US'));
Map.centerObject(usa, 6);
Map.addLayer(usa);
dif = dif.clip(usa);
Map.addLayer(dif, visArgs, '2015-2005 first day no snow dif');
var treeLossVisParam = {
bands: ['lossyear'],
min: 0,
max: 22,
palette: ['yellow', 'red']
};
dataset = dataset.clip(usa);
Map.addLayer(dataset, treeLossVisParam, 'tree loss year');