1 |
555815c9
|
Adam M. Wilson
|
Systematic landcover bias in Collection 5 MODIS cloud mask and derived products – a global overview
|
2 |
|
|
__________
|
3 |
|
|
|
4 |
|
|
|
5 |
|
|
```r
|
6 |
|
|
opts_chunk$set(eval = F)
|
7 |
|
|
```
|
8 |
|
|
|
9 |
|
|
|
10 |
|
|
This document describes the analysis of the Collection 5 MOD35 data.
|
11 |
|
|
|
12 |
|
|
# Google Earth Engine Processing
|
13 |
|
|
The following code produces the annual (2009) summaries of cloud frequency from MOD09, MOD35, and MOD11 using the Google Earth Engine 'playground' API [http://ee-api.appspot.com/](http://ee-api.appspot.com/).
|
14 |
|
|
|
15 |
|
|
```coffee
|
16 |
|
|
var startdate="2009-01-01"
|
17 |
|
|
var stopdate="2009-12-31"
|
18 |
|
|
|
19 |
|
|
// MOD11 MODIS LST
|
20 |
|
|
var mod11 = ee.ImageCollection("MOD11A2").map(function(img){
|
21 |
|
|
return img.select(['LST_Day_1km'])});
|
22 |
|
|
// MOD09 internal cloud flag
|
23 |
|
|
var mod09 = ee.ImageCollection("MOD09GA").filterDate(new Date(startdate),new Date(stopdate)).map(function(img) {
|
24 |
|
|
return img.select(['state_1km']).expression("((b(0)/1024)%2)");
|
25 |
|
|
});
|
26 |
|
|
// MOD35 cloud flag
|
27 |
|
|
var mod35 = ee.ImageCollection("MOD09GA").filterDate(new Date(startdate),new Date(stopdate)).map(function(img) {
|
28 |
|
|
return img.select(['state_1km']).expression("((b(0))%4)==1|((b(0))%4)==2");
|
29 |
|
|
});
|
30 |
|
|
|
31 |
|
|
//define reducers
|
32 |
|
|
var COUNT = ee.call("Reducer.count");
|
33 |
|
|
var MEAN = ee.call("Reducer.mean");
|
34 |
|
|
|
35 |
|
|
//a few maps of constants
|
36 |
|
|
c100=ee.Image(100); //to multiply by 100
|
37 |
|
|
c02=ee.Image(0.02); //to scale LST data
|
38 |
|
|
c272=ee.Image(272.15); // to convert K->C
|
39 |
|
|
|
40 |
|
|
//calculate mean cloudiness (%), rename, and convert to integer
|
41 |
|
|
mod09a=mod09.reduce(MEAN).select([0], ['MOD09']).multiply(c100).int8();
|
42 |
|
|
mod35a=mod35.reduce(MEAN).select([0], ['MOD35']).multiply(c100).int8();
|
43 |
|
|
|
44 |
|
|
/////////////////////////////////////////////////
|
45 |
|
|
// Generate the cloud frequency surface:
|
46 |
|
|
getMiss = function(collection) {
|
47 |
|
|
//filter by date
|
48 |
|
|
i2=collection.filterDate(new Date(startdate),new Date(stopdate));
|
49 |
|
|
// number of layers in collection
|
50 |
|
|
i2_n=i2.getInfo().features.length;
|
51 |
|
|
//get means
|
52 |
|
|
// image of -1s to convert to % missing
|
53 |
|
|
c1=ee.Image(-1);
|
54 |
|
|
// 1 Calculate the number of days with measurements
|
55 |
|
|
// 2 divide by the total number of layers
|
56 |
|
|
i2_c=ee.Image(i2_n).float()
|
57 |
|
|
// 3 Add -1 and multiply by -1 to invert to % cloudy
|
58 |
|
|
// 4 Rename to "Percent_Cloudy"
|
59 |
|
|
// 5 multiply by 100 and convert to 8-bit integer to decrease file size
|
60 |
|
|
i2_miss=i2.reduce(COUNT).divide(i2_c).add(c1).multiply(c1).multiply(c100).int8();
|
61 |
|
|
return (i2_miss);
|
62 |
|
|
};
|
63 |
|
|
|
64 |
|
|
// run the function
|
65 |
|
|
mod11a=getMiss(mod11).select([0], ['MOD11_LST_PMiss']);
|
66 |
|
|
|
67 |
|
|
// get long-term mean
|
68 |
|
|
mod11b=mod11.reduce(MEAN).multiply(c02).subtract(c272).int8().select([0], ['MOD11_LST_MEAN']);
|
69 |
|
|
|
70 |
|
|
// summary object with all layers
|
71 |
|
|
summary=mod11a.addBands(mod11b).addBands(mod35a).addBands(mod09a)
|
72 |
|
|
|
73 |
|
|
var region='[[-180, -60], [-180, 90], [180, 90], [180, -60]]' //global
|
74 |
|
|
|
75 |
|
|
// get download link
|
76 |
|
|
print("All")
|
77 |
|
|
var path = summary.getDownloadURL({
|
78 |
|
|
'scale': 1000,
|
79 |
|
|
'crs': 'EPSG:4326',
|
80 |
|
|
'region': region
|
81 |
|
|
});
|
82 |
|
|
print('https://earthengine.sandbox.google.com' + path);
|
83 |
|
|
```
|
84 |
|
|
|
85 |
|
|
|
86 |
|
|
# Data Processing
|
87 |
|
|
|
88 |
|
|
|
89 |
|
|
```r
|
90 |
|
|
setwd("~/acrobates/adamw/projects/MOD35C5")
|
91 |
|
|
library(raster)
|
92 |
|
|
```
|
93 |
|
|
|
94 |
|
|
```
|
95 |
|
|
## Loading required package: sp
|
96 |
|
|
```
|
97 |
|
|
|
98 |
|
|
```r
|
99 |
|
|
beginCluster(10)
|
100 |
|
|
```
|
101 |
|
|
|
102 |
|
|
```
|
103 |
|
|
## Loading required package: snow
|
104 |
|
|
```
|
105 |
|
|
|
106 |
|
|
```r
|
107 |
|
|
library(rasterVis)
|
108 |
|
|
```
|
109 |
|
|
|
110 |
|
|
```
|
111 |
|
|
## Loading required package: lattice Loading required package: latticeExtra
|
112 |
|
|
## Loading required package: RColorBrewer Loading required package: hexbin
|
113 |
|
|
## Loading required package: grid
|
114 |
|
|
```
|
115 |
|
|
|
116 |
|
|
```r
|
117 |
|
|
library(rgdal)
|
118 |
|
|
```
|
119 |
|
|
|
120 |
|
|
```
|
121 |
|
|
## rgdal: version: 0.8-10, (SVN revision 478) Geospatial Data Abstraction
|
122 |
|
|
## Library extensions to R successfully loaded Loaded GDAL runtime: GDAL
|
123 |
|
|
## 1.9.2, released 2012/10/08 but rgdal build and GDAL runtime not in sync:
|
124 |
|
|
## ... consider re-installing rgdal!! Path to GDAL shared files:
|
125 |
|
|
## /usr/share/gdal/1.9 Loaded PROJ.4 runtime: Rel. 4.8.0, 6 March 2012,
|
126 |
|
|
## [PJ_VERSION: 480] Path to PROJ.4 shared files: (autodetected)
|
127 |
|
|
```
|
128 |
|
|
|
129 |
|
|
```r
|
130 |
|
|
library(plotKML)
|
131 |
|
|
```
|
132 |
|
|
|
133 |
|
|
```
|
134 |
|
|
## plotKML version 0.3-5 (2013-05-16) URL:
|
135 |
|
|
## http://plotkml.r-forge.r-project.org/
|
136 |
|
|
##
|
137 |
|
|
## Attaching package: 'plotKML'
|
138 |
|
|
##
|
139 |
|
|
## The following object is masked from 'package:raster':
|
140 |
|
|
##
|
141 |
|
|
## count
|
142 |
|
|
```
|
143 |
|
|
|
144 |
|
|
```r
|
145 |
|
|
library(Cairo)
|
146 |
|
|
library(reshape)
|
147 |
|
|
```
|
148 |
|
|
|
149 |
|
|
```
|
150 |
|
|
## Loading required package: plyr
|
151 |
|
|
##
|
152 |
|
|
## Attaching package: 'plyr'
|
153 |
|
|
##
|
154 |
|
|
## The following object is masked from 'package:plotKML':
|
155 |
|
|
##
|
156 |
|
|
## count
|
157 |
|
|
##
|
158 |
|
|
## The following object is masked from 'package:raster':
|
159 |
|
|
##
|
160 |
|
|
## count
|
161 |
|
|
##
|
162 |
|
|
## Attaching package: 'reshape'
|
163 |
|
|
##
|
164 |
|
|
## The following object is masked from 'package:plyr':
|
165 |
|
|
##
|
166 |
|
|
## rename, round_any
|
167 |
|
|
##
|
168 |
|
|
## The following object is masked from 'package:raster':
|
169 |
|
|
##
|
170 |
|
|
## expand
|
171 |
|
|
```
|
172 |
|
|
|
173 |
|
|
```r
|
174 |
|
|
library(rgeos)
|
175 |
|
|
```
|
176 |
|
|
|
177 |
|
|
```
|
178 |
|
|
## rgeos version: 0.2-19, (SVN revision 394) GEOS runtime version:
|
179 |
|
|
## 3.3.3-CAPI-1.7.4 Polygon checking: TRUE
|
180 |
|
|
```
|
181 |
|
|
|
182 |
|
|
```r
|
183 |
|
|
library(splancs)
|
184 |
|
|
```
|
185 |
|
|
|
186 |
|
|
```
|
187 |
|
|
## Spatial Point Pattern Analysis Code in S-Plus
|
188 |
|
|
##
|
189 |
|
|
## Version 2 - Spatial and Space-Time analysis
|
190 |
|
|
##
|
191 |
|
|
## Attaching package: 'splancs'
|
192 |
|
|
##
|
193 |
|
|
## The following object is masked from 'package:raster':
|
194 |
|
|
##
|
195 |
|
|
## zoom
|
196 |
|
|
```
|
197 |
|
|
|
198 |
|
|
```r
|
199 |
|
|
|
200 |
|
|
## get % cloudy
|
201 |
|
|
mod09 = raster("data/MOD09_2009.tif")
|
202 |
|
|
names(mod09) = "C5MOD09CF"
|
203 |
|
|
NAvalue(mod09) = 0
|
204 |
|
|
|
205 |
|
|
mod35c5 = raster("data/MOD35_2009.tif")
|
206 |
|
|
names(mod35c5) = "C5MOD35CF"
|
207 |
|
|
NAvalue(mod35c5) = 0
|
208 |
|
|
|
209 |
|
|
## mod35C6 annual
|
210 |
|
|
mod35c6 = raster("data/MOD35C6_2009.tif")
|
211 |
|
|
names(mod35c6) = "C6MOD35CF"
|
212 |
|
|
NAvalue(mod35c6) = 255
|
213 |
|
|
|
214 |
|
|
## landcover
|
215 |
|
|
lulc = raster("data/MCD12Q1_IGBP_2009_051_wgs84_1km.tif")
|
216 |
|
|
|
217 |
|
|
# lulc=ratify(lulc)
|
218 |
|
|
data(worldgrids_pal) #load palette
|
219 |
|
|
IGBP = data.frame(ID = 0:16, col = worldgrids_pal$IGBP[-c(18, 19)], lulc_levels2 = c("Water",
|
220 |
|
|
"Forest", "Forest", "Forest", "Forest", "Forest", "Shrublands", "Shrublands",
|
221 |
|
|
"Savannas", "Savannas", "Grasslands", "Permanent wetlands", "Croplands",
|
222 |
|
|
"Urban and built-up", "Cropland/Natural vegetation mosaic", "Snow and ice",
|
223 |
|
|
"Barren or sparsely vegetated"), stringsAsFactors = F)
|
224 |
|
|
IGBP$class = rownames(IGBP)
|
225 |
|
|
rownames(IGBP) = 1:nrow(IGBP)
|
226 |
|
|
levels(lulc) = list(IGBP)
|
227 |
|
|
names(lulc) = "MCD12Q1"
|
228 |
|
|
|
229 |
|
|
## MOD17
|
230 |
|
|
mod17 = raster("data/MOD17.tif", format = "GTiff")
|
231 |
|
|
NAvalue(mod17) = 65535
|
232 |
|
|
names(mod17) = "MOD17_unscaled"
|
233 |
|
|
|
234 |
|
|
mod17qc = raster("data/MOD17qc.tif", format = "GTiff")
|
235 |
|
|
NAvalue(mod17qc) = 255
|
236 |
|
|
names(mod17qc) = "MOD17CF"
|
237 |
|
|
|
238 |
|
|
## MOD11 via earth engine
|
239 |
|
|
mod11 = raster("data/MOD11_2009.tif", format = "GTiff")
|
240 |
|
|
names(mod11) = "MOD11_unscaled"
|
241 |
|
|
NAvalue(mod11) = 0
|
242 |
|
|
|
243 |
|
|
mod11qc = raster("data/MOD11qc_2009.tif", format = "GTiff")
|
244 |
|
|
names(mod11qc) = "MOD11CF"
|
245 |
|
|
```
|
246 |
|
|
|
247 |
|
|
|
248 |
|
|
Import the Collection 5 MOD35 processing path:
|
249 |
|
|
|
250 |
|
|
```r
|
251 |
|
|
pp = raster("data/MOD35pp.tif")
|
252 |
|
|
NAvalue(pp) = 255
|
253 |
|
|
names(pp) = "MOD35pp"
|
254 |
|
|
```
|
255 |
|
|
|
256 |
|
|
|
257 |
|
|
Define transects to illustrate the fine-grain relationship between MOD35 cloud frequency and both landcover and processing path.
|
258 |
|
|
|
259 |
|
|
```r
|
260 |
|
|
r1 = Lines(list(Line(matrix(c(-61.688, 4.098, -59.251, 3.43), ncol = 2, byrow = T))),
|
261 |
|
|
"Venezuela")
|
262 |
|
|
r2 = Lines(list(Line(matrix(c(133.746, -31.834, 134.226, -32.143), ncol = 2,
|
263 |
|
|
byrow = T))), "Australia")
|
264 |
|
|
r3 = Lines(list(Line(matrix(c(73.943, 27.419, 74.369, 26.877), ncol = 2, byrow = T))),
|
265 |
|
|
"India")
|
266 |
|
|
r4 = Lines(list(Line(matrix(c(33.195, 12.512, 33.802, 12.894), ncol = 2, byrow = T))),
|
267 |
|
|
"Sudan")
|
268 |
|
|
|
269 |
|
|
trans = SpatialLines(list(r1, r2, r3, r4), CRS("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs "))
|
270 |
|
|
### write out shapefiles of transects
|
271 |
|
|
writeOGR(SpatialLinesDataFrame(trans, data = data.frame(ID = names(trans)),
|
272 |
|
|
match.ID = F), "output", layer = "transects", driver = "ESRI Shapefile",
|
273 |
|
|
overwrite = T)
|
274 |
|
|
```
|
275 |
|
|
|
276 |
|
|
|
277 |
|
|
Buffer transects to identify a small region around each transect for comparison and plotting
|
278 |
|
|
|
279 |
|
|
```r
|
280 |
|
|
transb = gBuffer(trans, byid = T, width = 0.4)
|
281 |
|
|
## make polygons of bounding boxes
|
282 |
|
|
bb0 <- lapply(slot(transb, "polygons"), bbox)
|
283 |
|
|
bb1 <- lapply(bb0, bboxx)
|
284 |
|
|
# turn these into matrices using a helper function in splancs
|
285 |
|
|
bb2 <- lapply(bb1, function(x) rbind(x, x[1, ]))
|
286 |
|
|
# close the matrix rings by appending the first coordinate
|
287 |
|
|
rn <- row.names(transb)
|
288 |
|
|
# get the IDs
|
289 |
|
|
bb3 <- vector(mode = "list", length = length(bb2))
|
290 |
|
|
# make somewhere to keep the output
|
291 |
|
|
for (i in seq(along = bb3)) bb3[[i]] <- Polygons(list(Polygon(bb2[[i]])), ID = rn[i])
|
292 |
|
|
# loop over the closed matrix rings, adding the IDs
|
293 |
|
|
bbs <- SpatialPolygons(bb3, proj4string = CRS(proj4string(transb)))
|
294 |
|
|
```
|
295 |
|
|
|
296 |
|
|
|
297 |
|
|
Extract the CF and mean values from each raster of interest.
|
298 |
|
|
|
299 |
|
|
```r
|
300 |
|
|
trd1 = lapply(1:length(transb), function(x) {
|
301 |
|
|
td = crop(mod11, transb[x])
|
302 |
|
|
tdd = lapply(list(mod35c5, mod35c6, mod09, mod17, mod17qc, mod11, mod11qc,
|
303 |
|
|
lulc, pp), function(l) resample(crop(l, transb[x]), td, method = "ngb"))
|
304 |
|
|
## normalize MOD11 and MOD17
|
305 |
|
|
for (j in which(do.call(c, lapply(tdd, function(i) names(i))) %in% c("MOD11_unscaled",
|
306 |
|
|
"MOD17_unscaled"))) {
|
307 |
|
|
trange = cellStats(tdd[[j]], range)
|
308 |
|
|
tscaled = 100 * (tdd[[j]] - trange[1])/(trange[2] - trange[1])
|
309 |
|
|
tscaled@history = list(range = trange)
|
310 |
|
|
names(tscaled) = sub("_unscaled", "", names(tdd[[j]]))
|
311 |
|
|
tdd = c(tdd, tscaled)
|
312 |
|
|
}
|
313 |
|
|
return(brick(tdd))
|
314 |
|
|
})
|
315 |
|
|
## bind all subregions into single dataframe for plotting
|
316 |
|
|
trd = do.call(rbind.data.frame, lapply(1:length(trd1), function(i) {
|
317 |
|
|
d = as.data.frame(as.matrix(trd1[[i]]))
|
318 |
|
|
d[, c("x", "y")] = coordinates(trd1[[i]])
|
319 |
|
|
d$trans = names(trans)[i]
|
320 |
|
|
d = melt(d, id.vars = c("trans", "x", "y"))
|
321 |
|
|
return(d)
|
322 |
|
|
}))
|
323 |
|
|
transd = do.call(rbind.data.frame, lapply(1:length(trans), function(l) {
|
324 |
|
|
td = as.data.frame(extract(trd1[[l]], trans[l], along = T, cellnumbers = F)[[1]])
|
325 |
|
|
td$loc = extract(trd1[[l]], trans[l], along = T, cellnumbers = T)[[1]][,
|
326 |
|
|
1]
|
327 |
|
|
td[, c("x", "y")] = xyFromCell(trd1[[l]], td$loc)
|
328 |
|
|
td$dist = spDistsN1(as.matrix(td[, c("x", "y")]), as.matrix(td[1, c("x",
|
329 |
|
|
"y")]), longlat = T)
|
330 |
|
|
td$transect = names(trans[l])
|
331 |
|
|
td2 = melt(td, id.vars = c("loc", "x", "y", "dist", "transect"))
|
332 |
|
|
td2 = td2[order(td2$variable, td2$dist), ]
|
333 |
|
|
# get per variable ranges to normalize
|
334 |
|
|
tr = cast(melt.list(tapply(td2$value, td2$variable, function(x) data.frame(min = min(x,
|
335 |
|
|
na.rm = T), max = max(x, na.rm = T)))), L1 ~ variable)
|
336 |
|
|
td2$min = tr$min[match(td2$variable, tr$L1)]
|
337 |
|
|
td2$max = tr$max[match(td2$variable, tr$L1)]
|
338 |
|
|
print(paste("Finished ", names(trans[l])))
|
339 |
|
|
return(td2)
|
340 |
|
|
}))
|
341 |
|
|
|
342 |
|
|
transd$type = ifelse(grepl("MOD35|MOD09|CF", transd$variable), "CF", "Data")
|
343 |
|
|
```
|
344 |
|
|
|
345 |
|
|
|
346 |
|
|
Compute difference between MOD09 and MOD35 cloud masks
|
347 |
|
|
|
348 |
|
|
```r
|
349 |
|
|
## comparison of % cloudy days
|
350 |
|
|
dif_c5_09 = raster("data/dif_c5_09.tif", format = "GTiff")
|
351 |
|
|
```
|
352 |
|
|
|
353 |
|
|
|
354 |
|
|
Define a color scheme
|
355 |
|
|
|
356 |
|
|
```r
|
357 |
|
|
n = 100
|
358 |
|
|
at = seq(0, 100, len = n)
|
359 |
|
|
bgyr = colorRampPalette(c("purple", "blue", "green", "yellow", "orange", "red",
|
360 |
|
|
"red"))
|
361 |
|
|
bgrayr = colorRampPalette(c("purple", "blue", "grey", "red", "red"))
|
362 |
|
|
cols = bgyr(n)
|
363 |
|
|
```
|
364 |
|
|
|
365 |
|
|
|
366 |
|
|
Import a global coastline map for overlay
|
367 |
|
|
|
368 |
|
|
```r
|
369 |
|
|
library(maptools)
|
370 |
|
|
coast = map2SpatialLines(map("world", interior = FALSE, plot = FALSE), proj4string = CRS("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"))
|
371 |
|
|
```
|
372 |
|
|
|
373 |
|
|
|
374 |
|
|
Draw the global cloud frequencies
|
375 |
|
|
|
376 |
|
|
```r
|
377 |
|
|
g1 = levelplot(stack(mod35c5, mod09), xlab = " ", scales = list(x = list(draw = F),
|
378 |
|
|
y = list(alternating = 1)), col.regions = cols, at = at) + layer(sp.polygons(bbs[1:4],
|
379 |
|
|
lwd = 2)) + layer(sp.lines(coast, lwd = 0.5))
|
380 |
|
|
|
381 |
|
|
g2 = levelplot(dif_c5_09, col.regions = bgrayr(100), at = seq(-70, 70, len = 100),
|
382 |
|
|
margin = F, ylab = " ", colorkey = list("right")) + layer(sp.polygons(bbs[1:4],
|
383 |
|
|
lwd = 2)) + layer(sp.lines(coast, lwd = 0.5))
|
384 |
|
|
g2$strip = strip.custom(var.name = "Difference (C5MOD35-C5MOD09)", style = 1,
|
385 |
|
|
strip.names = T, strip.levels = F)
|
386 |
|
|
```
|
387 |
|
|
|
388 |
|
|
|
389 |
|
|
Now illustrate the fine-grain regions
|
390 |
|
|
|
391 |
|
|
```r
|
392 |
|
|
p1=useOuterStrips(levelplot(value~x*y|variable+trans,data=trd[!trd$variable%in%c("MOD17_unscaled","MOD11_unscaled","MCD12Q1","MOD35pp"),],asp=1,scales=list(draw=F,rot=0,relation="free"),
|
393 |
|
|
at=at,col.regions=cols,maxpixels=7e6,
|
394 |
|
|
ylab="Latitude",xlab="Longitude"),strip = strip.custom(par.strip.text=list(cex=.7)))+layer(sp.lines(trans,lwd=2))
|
395 |
|
|
|
396 |
|
|
p2=useOuterStrips(
|
397 |
|
|
levelplot(value~x*y|variable+trans,data=trd[trd$variable%in%c("MCD12Q1"),],
|
398 |
|
|
asp=1,scales=list(draw=F,rot=0,relation="free"),colorkey=F,
|
399 |
|
|
at=c(-1,IGBP$ID),col.regions=IGBP$col,maxpixels=7e7,
|
400 |
|
|
legend=list(
|
401 |
|
|
right=list(fun=draw.key(list(columns=1,#title="MCD12Q1 \n IGBP Land \n Cover",
|
402 |
|
|
rectangles=list(col=IGBP$col,size=1),
|
403 |
|
|
text=list(as.character(IGBP$ID),at=IGBP$ID-.5))))),
|
404 |
|
|
ylab="",xlab=" "),strip = strip.custom(par.strip.text=list(cex=.7)),strip.left=F)+layer(sp.lines(trans,lwd=2))
|
405 |
|
|
p3=useOuterStrips(
|
406 |
|
|
levelplot(value~x*y|variable+trans,data=trd[trd$variable%in%c("MOD35pp"),],
|
407 |
|
|
asp=1,scales=list(draw=F,rot=0,relation="free"),colorkey=F,
|
408 |
|
|
at=c(-1:4),col.regions=c("blue","cyan","tan","darkgreen"),maxpixels=7e7,
|
409 |
|
|
legend=list(
|
410 |
|
|
right=list(fun=draw.key(list(columns=1,#title="MOD35 \n Processing \n Path",
|
411 |
|
|
rectangles=list(col=c("blue","cyan","tan","darkgreen"),size=1),
|
412 |
|
|
text=list(c("Water","Coast","Desert","Land")))))),
|
413 |
|
|
ylab="",xlab=" "),strip = strip.custom(par.strip.text=list(cex=.7)),strip.left=F)+layer(sp.lines(trans,lwd=2))
|
414 |
|
|
```
|
415 |
|
|
|
416 |
|
|
|
417 |
|
|
Now draw the profile plots for each transect.
|
418 |
|
|
|
419 |
|
|
```r
|
420 |
|
|
## transects
|
421 |
|
|
p4=xyplot(value~dist|transect,groups=variable,type=c("smooth","p"),
|
422 |
|
|
data=transd,panel=function(...,subscripts=subscripts) {
|
423 |
|
|
td=transd[subscripts,]
|
424 |
|
|
## mod09
|
425 |
|
|
imod09=td$variable=="C5MOD09CF"
|
426 |
|
|
panel.xyplot(td$dist[imod09],td$value[imod09],type=c("p","smooth"),span=0.2,subscripts=1:sum(imod09),col="red",pch=16,cex=.25)
|
427 |
|
|
## mod35C5
|
428 |
|
|
imod35=td$variable=="C5MOD35CF"
|
429 |
|
|
panel.xyplot(td$dist[imod35],td$value[imod35],type=c("p","smooth"),span=0.09,subscripts=1:sum(imod35),col="blue",pch=16,cex=.25)
|
430 |
|
|
## mod35C6
|
431 |
|
|
imod35c6=td$variable=="C6MOD35CF"
|
432 |
|
|
panel.xyplot(td$dist[imod35c6],td$value[imod35c6],type=c("p","smooth"),span=0.09,subscripts=1:sum(imod35c6),col="black",pch=16,cex=.25)
|
433 |
|
|
## mod17
|
434 |
|
|
imod17=td$variable=="MOD17"
|
435 |
|
|
panel.xyplot(td$dist[imod17],100*((td$value[imod17]-td$min[imod17][1])/(td$max[imod17][1]-td$min[imod17][1])),
|
436 |
|
|
type=c("smooth"),span=0.09,subscripts=1:sum(imod17),col="darkgreen",lty=5,pch=1,cex=.25)
|
437 |
|
|
imod17qc=td$variable=="MOD17CF"
|
438 |
|
|
panel.xyplot(td$dist[imod17qc],td$value[imod17qc],type=c("p","smooth"),span=0.09,subscripts=1:sum(imod17qc),col="darkgreen",pch=16,cex=.25)
|
439 |
|
|
## mod11
|
440 |
|
|
imod11=td$variable=="MOD11"
|
441 |
|
|
panel.xyplot(td$dist[imod11],100*((td$value[imod11]-td$min[imod11][1])/(td$max[imod11][1]-td$min[imod11][1])),
|
442 |
|
|
type=c("smooth"),span=0.09,subscripts=1:sum(imod17),col="orange",lty="dashed",pch=1,cex=.25)
|
443 |
|
|
imod11qc=td$variable=="MOD11CF"
|
444 |
|
|
qcspan=ifelse(td$transect[1]=="Australia",0.2,0.05)
|
445 |
|
|
panel.xyplot(td$dist[imod11qc],td$value[imod11qc],type=c("p","smooth"),npoints=100,span=qcspan,subscripts=1:sum(imod11qc),col="orange",pch=16,cex=.25)
|
446 |
|
|
## land
|
447 |
|
|
path=td[td$variable=="MOD35pp",]
|
448 |
|
|
panel.segments(path$dist,-10,c(path$dist[-1],max(path$dist,na.rm=T)),-10,col=c("blue","cyan","tan","darkgreen")[path$value+1],subscripts=1:nrow(path),lwd=10,type="l")
|
449 |
|
|
land=td[td$variable=="MCD12Q1",]
|
450 |
|
|
panel.segments(land$dist,-20,c(land$dist[-1],max(land$dist,na.rm=T)),-20,col=IGBP$col[land$value+1],subscripts=1:nrow(land),lwd=10,type="l")
|
451 |
|
|
},subscripts=T,par.settings = list(grid.pars = list(lineend = "butt")),
|
452 |
|
|
scales=list(
|
453 |
|
|
x=list(alternating=1,relation="free"),#, lim=c(0,70)),
|
454 |
|
|
y=list(at=c(-18,-10,seq(0,100,len=5)),
|
455 |
|
|
labels=c("MCD12Q1 IGBP","MOD35 path",seq(0,100,len=5)),
|
456 |
|
|
lim=c(-25,100)),
|
457 |
|
|
alternating=F),
|
458 |
|
|
xlab="Distance Along Transect (km)", ylab="% Missing Data / % of Maximum Value",
|
459 |
|
|
legend=list(
|
460 |
|
|
bottom=list(fun=draw.key(list( rep=FALSE,columns=1,title=" ",
|
461 |
|
|
lines=list(type=c("b","b","b","b","b","l","b","l"),pch=16,cex=.5,
|
462 |
|
|
lty=c(0,1,1,1,1,5,1,5),
|
463 |
|
|
col=c("transparent","red","blue","black","darkgreen","darkgreen","orange","orange")),
|
464 |
|
|
text=list(
|
465 |
|
|
c("MODIS Products","C5 MOD09 % Cloudy","C5 MOD35 % Cloudy","C6 MOD35 % Cloudy","MOD17 % Missing","MOD17 (scaled)","MOD11 % Missing","MOD11 (scaled)")),
|
466 |
|
|
rectangles=list(border=NA,col=c(NA,"tan","darkgreen")),
|
467 |
|
|
text=list(c("C5 MOD35 Processing Path","Desert","Land")),
|
468 |
|
|
rectangles=list(border=NA,col=c(NA,IGBP$col[sort(unique(transd$value[transd$variable=="MCD12Q1"]+1))])),
|
469 |
|
|
text=list(c("MCD12Q1 IGBP Land Cover",IGBP$class[sort(unique(transd$value[transd$variable=="MCD12Q1"]+1))])))))),
|
470 |
|
|
strip = strip.custom(par.strip.text=list(cex=.75)))
|
471 |
|
|
print(p4)
|
472 |
|
|
```
|
473 |
|
|
|
474 |
|
|
|
475 |
|
|
Compile the PDF:
|
476 |
|
|
|
477 |
|
|
```r
|
478 |
|
|
CairoPDF("output/mod35compare.pdf", width = 11, height = 7)
|
479 |
|
|
### Global Comparison
|
480 |
|
|
print(g1, position = c(0, 0.35, 1, 1), more = T)
|
481 |
|
|
print(g2, position = c(0, 0, 1, 0.415), more = F)
|
482 |
|
|
|
483 |
|
|
### MOD35 Desert Processing path
|
484 |
|
|
levelplot(pp, asp = 1, scales = list(draw = T, rot = 0), maxpixels = 1e+06,
|
485 |
|
|
at = c(-1:3), col.regions = c("blue", "cyan", "tan", "darkgreen"), margin = F,
|
486 |
|
|
colorkey = list(space = "bottom", title = "MOD35 Processing Path", labels = list(labels = c("Water",
|
487 |
|
|
"Coast", "Desert", "Land"), at = 0:4 - 0.5))) + layer(sp.polygons(bbs,
|
488 |
|
|
lwd = 2)) + layer(sp.lines(coast, lwd = 0.5))
|
489 |
|
|
### levelplot of regions
|
490 |
|
|
print(p1, position = c(0, 0, 0.62, 1), more = T)
|
491 |
|
|
print(p2, position = c(0.6, 0.21, 0.78, 0.79), more = T)
|
492 |
|
|
print(p3, position = c(0.76, 0.21, 1, 0.79))
|
493 |
|
|
### profile plots
|
494 |
|
|
print(p4)
|
495 |
|
|
dev.off()
|
496 |
|
|
```
|
497 |
|
|
|
498 |
|
|
|
499 |
|
|
Derive summary statistics for manuscript
|
500 |
|
|
|
501 |
|
|
```r
|
502 |
|
|
td = cast(transect + loc + dist ~ variable, value = "value", data = transd)
|
503 |
|
|
td2 = melt.data.frame(td, id.vars = c("transect", "dist", "loc", "MOD35pp",
|
504 |
|
|
"MCD12Q1"))
|
505 |
|
|
|
506 |
|
|
## function to prettyprint mean/sd's
|
507 |
|
|
msd = function(x) paste(round(mean(x, na.rm = T), 1), "% ±", round(sd(x, na.rm = T),
|
508 |
|
|
1), sep = "")
|
509 |
|
|
|
510 |
|
|
cast(td2, transect + variable ~ MOD35pp, value = "value", fun = msd)
|
511 |
|
|
cast(td2, transect + variable ~ MOD35pp + MCD12Q1, value = "value", fun = msd)
|
512 |
|
|
cast(td2, transect + variable ~ ., value = "value", fun = msd)
|
513 |
|
|
|
514 |
|
|
cast(td2, transect + variable ~ ., value = "value", fun = msd)
|
515 |
|
|
|
516 |
|
|
cast(td2, variable ~ MOD35pp, value = "value", fun = msd)
|
517 |
|
|
cast(td2, variable ~ ., value = "value", fun = msd)
|
518 |
|
|
|
519 |
|
|
td[td$transect == "Venezuela", ]
|
520 |
|
|
```
|
521 |
|
|
|
522 |
|
|
|
523 |
|
|
Export regional areas as KML for inclusion on website
|
524 |
|
|
|
525 |
|
|
```r
|
526 |
|
|
library(plotKML)
|
527 |
|
|
|
528 |
|
|
kml_open("output/modiscloud.kml")
|
529 |
|
|
|
530 |
|
|
readAll(mod35c5)
|
531 |
|
|
|
532 |
|
|
kml_layer.Raster(mod35c5,
|
533 |
|
|
plot.legend = TRUE,raster_name="Collection 5 MOD35 Cloud Frequency",
|
534 |
|
|
z.lim = c(0,100),colour_scale = get("colour_scale_numeric", envir = plotKML.opts),
|
535 |
|
|
# home_url = get("home_url", envir = plotKML.opts),
|
536 |
|
|
# metadata = NULL, html.table = NULL,
|
537 |
|
|
altitudeMode = "clampToGround", balloon = FALSE
|
538 |
|
|
)
|
539 |
|
|
|
540 |
|
|
system(paste("gdal_translate -of KMLSUPEROVERLAY ",mod35c5@file@name," output/mod35c5.kmz -co FORMAT=JPEG"))
|
541 |
|
|
|
542 |
|
|
logo = "http://static.tumblr.com/t0afs9f/KWTm94tpm/yale_logo.png"
|
543 |
|
|
kml_screen(image.file = logo, position = "UL", sname = "YALE logo",size=c(.1,.1))
|
544 |
|
|
kml_close("modiscloud.kml")
|
545 |
|
|
kml_compress("modiscloud.kml",files=c(paste(month.name,".png",sep=""),"obj_legend.png"),zip="/usr/bin/zip")
|
546 |
|
|
```
|