1
|
### Script to compile the monthly cloud data from earth engine into a netcdf file for further processing
|
2
|
|
3
|
library(raster)
|
4
|
library(doMC)
|
5
|
library(multicore)
|
6
|
library(foreach)
|
7
|
registerDoMC(4)
|
8
|
|
9
|
setwd("~/acrobates/adamw/projects/cloud")
|
10
|
|
11
|
## Get list of available files
|
12
|
df=data.frame(path=list.files("data/mod09cloud",pattern="*.tif$",full=T,recur=T),stringsAsFactors=F)
|
13
|
df[,c("month")]=do.call(rbind,strsplit(basename(df$path),"_|[.]|-"))[,c(6)]
|
14
|
df$date=as.Date(paste(2013,"_",df$month,"_15",sep=""),"%Y_%m_%d")
|
15
|
|
16
|
## use ramdisk?
|
17
|
tmpfs=tempdir()
|
18
|
|
19
|
ramdisk=T
|
20
|
if(ramdisk) {
|
21
|
system("sudo mkdir -p /mnt/ram")
|
22
|
system("sudo mount -t ramfs -o size=30g ramfs /mnt/ram")
|
23
|
system("sudo chmod a+w /mnt/ram")
|
24
|
tmpfs="/mnt/ram"
|
25
|
}
|
26
|
|
27
|
#i=2
|
28
|
for(i in 1:nrow(df)){
|
29
|
## Define output and check if it already exists
|
30
|
temptffile=paste(tmpfs,"/modcf_",df$month[i],".tif",sep="")
|
31
|
tffile=paste("data/mod09cloud2/modcf_",df$month[i],".tif",sep="")
|
32
|
ncfile=paste("data/mod09cloud2/modcf_",df$month[i],".nc",sep="")
|
33
|
|
34
|
# if(file.exists(tffile)) next
|
35
|
## warp to wgs84
|
36
|
ops=paste("-t_srs 'EPSG:4326' -multi -r bilinear -te -180 -90 180 90 -tr 0.008333333333333 -0.008333333333333",
|
37
|
"-co BIGTIFF=YES -ot Byte --config GDAL_CACHEMAX 300000 -wm 300000 -wo NUM_THREADS:10 -wo SOURCE_EXTRA=5")
|
38
|
system(paste("gdalwarp -overwrite ",ops," ",df$path[i]," ",temptffile))
|
39
|
## update metadata
|
40
|
tags=c(paste("TIFFTAG_IMAGEDESCRIPTION='Cloud Frequency extracted from Collection 5 MYD09GA and MOD09GA (PGE11) internal cloud mask algorithm (embedded in M*D09GA state_1km bit 10).",
|
41
|
" Band 1 represents the overall 2000-2013 mean cloud frequency for month ",df$month[i],
|
42
|
". Band 2 is the four times the standard deviation of the mean monthly cloud frequencies over 2000-2013.'",sep=""),
|
43
|
"TIFFTAG_DOCUMENTNAME='MODCF: MODIS Cloud Frequency'",
|
44
|
paste("TIFFTAG_DATETIME='2013-",df$month[i],"-15'",sep=""),
|
45
|
"TIFFTAG_ARTIST='Adam M. Wilson (adam.wilson@yale.edu)'")
|
46
|
## compress
|
47
|
# trans_ops=paste(" -co COMPRESS=LZW -stats -co BLOCKXSIZE=256 -co BLOCKYSIZE=256 -co PREDICTOR=2 -co FORMAT=NC4C")
|
48
|
# system(paste("gdal_translate ",trans_ops," ",paste("-mo ",tags,sep="",collapse=" ")," ",temptffile," ",tffile," ",sep=""))
|
49
|
|
50
|
trans_ops=paste(" -co COMPRESS=DEFLATE -stats -co PREDICTOR=2 -co FORMAT=NC4C -co ZLEVEL=9")
|
51
|
system(paste("gdal_translate ",trans_ops," ",temptffile," ",ncfile," ",sep=""))
|
52
|
file.remove(temptffile)
|
53
|
}
|
54
|
|
55
|
|
56
|
if(ramdisk) {
|
57
|
## unmount the ram disk
|
58
|
system(paste("sudo umount ",tmpfs)
|
59
|
}
|
60
|
|
61
|
|
62
|
rerun=F # set to true to recalculate all dates even if file already exists
|
63
|
|
64
|
## Loop over existing months to build composite netcdf files
|
65
|
foreach(date=unique(df$date)) %dopar% {
|
66
|
## get date
|
67
|
print(date)
|
68
|
## Define output and check if it already exists
|
69
|
temptffile=paste(tmpfs,"/modcf_",df$month[i],".tif",sep="")
|
70
|
ncfile=paste("data/mod09cloud2/modcf_",df$month[i],".nc",sep="")
|
71
|
## check if output already exists
|
72
|
if(!rerun&file.exists(ncfile)) return(NA)
|
73
|
|
74
|
## warp to wgs84
|
75
|
ops=paste("-t_srs 'EPSG:4326' -multi -r bilinear -te -180 -90 180 90 -tr 0.008333333333333 -0.008333333333333",
|
76
|
"-co BIGTIFF=YES -ot Byte --config GDAL_CACHEMAX 300000 -wm 300000 -wo NUM_THREADS:10 -wo SOURCE_EXTRA=5")
|
77
|
system(paste("gdalwarp -overwrite ",ops," ",df$path[i]," ",temptffile))
|
78
|
|
79
|
## Warp to WGS84 grid and convert to netcdf
|
80
|
trans_ops=paste(" -co COMPRESS=DEFLATE -stats -co FORMAT=NC4C -co ZLEVEL=9")
|
81
|
system(paste("gdal_translate -of netCDF ",trans_ops," ",temptffile," ",ncfile))
|
82
|
## file.remove(temptffile)
|
83
|
system(paste("ncecat -O -u time ",ncfile," ",ncfile,sep=""))
|
84
|
## create temporary nc file with time information to append to CF data
|
85
|
cat(paste("
|
86
|
netcdf time {
|
87
|
dimensions:
|
88
|
time = 1 ;
|
89
|
variables:
|
90
|
int time(time) ;
|
91
|
time:units = \"days since 2000-01-01 00:00:00\" ;
|
92
|
time:calendar = \"gregorian\";
|
93
|
time:long_name = \"time of observation\";
|
94
|
data:
|
95
|
time=",as.integer(date-as.Date("2000-01-01")),";
|
96
|
}"),file=paste(tempdir(),"/",date,"_time.cdl",sep=""))
|
97
|
system(paste("ncgen -o ",tempdir(),"/",date,"_time.nc ",tempdir(),"/",date,"_time.cdl",sep=""))
|
98
|
## add time dimension to ncfile and compress (deflate)
|
99
|
system(paste("ncks --fl_fmt=netcdf4_classic -L 9 -A ",tempdir(),"/",date,"_time.nc ",ncfile,sep=""))
|
100
|
## add other attributes
|
101
|
system(paste("ncrename -v Band1,CF ",ncfile,sep=""))
|
102
|
system(paste("ncrename -v Band2,CFsd ",ncfile,sep=""))
|
103
|
system(paste("ncatted ",
|
104
|
## CF Mean
|
105
|
" -a units,CF,o,c,\"%\" ",
|
106
|
" -a valid_range,CF,o,b,\"0,100\" ",
|
107
|
# " -a scale_factor,CF,o,b,\"0.1\" ",
|
108
|
" -a _FillValue,CF,o,b,\"255\" ",
|
109
|
" -a missing_value,CF,o,b,\"255\" ",
|
110
|
" -a long_name,CF,o,c,\"Cloud Frequency (%)\" ",
|
111
|
" -a NETCDF_VARNAME,CF,o,c,\"Cloud Frequency (%)\" ",
|
112
|
## CF Standard Deviation
|
113
|
" -a units,CFsd,o,c,\"SD\" ",
|
114
|
" -a valid_range,CFsd,o,b,\"0,200\" ",
|
115
|
" -a scale_factor,CFsd,o,f,\"0.25\" ",
|
116
|
" -a _FillValue,CFsd,o,b,\"255\" ",
|
117
|
" -a missing_value,CFsd,o,b,\"255\" ",
|
118
|
" -a long_name,CFsd,o,c,\"Cloud Frequency (%) Intra-month (2000-2013) Standard Deviation\" ",
|
119
|
" -a NETCDF_VARNAME,CFsd,o,c,\"Cloud Frequency (%) Intra-month (2000-2013) Standard Deviation\" ",
|
120
|
## global
|
121
|
" -a title,global,o,c,\"Cloud Climatology from MOD09 Cloud Mask\" ",
|
122
|
" -a institution,global,o,c,\"Jetz Lab, EEB, Yale University, New Haven, CT\" ",
|
123
|
" -a source,global,o,c,\"Derived from MOD09GA Daily Data\" ",
|
124
|
" -a comment,global,o,c,\"Developed by Adam M. Wilson (adam.wilson@yale.edu / http://adamwilson.us)\" ",
|
125
|
ncfile,sep=""))
|
126
|
|
127
|
## add the fillvalue attribute back (without changing the actual values)
|
128
|
#system(paste("ncatted -a _FillValue,CF,o,b,-32768 ",ncfile,sep=""))
|
129
|
|
130
|
if(as.numeric(system(paste("cdo -s ntime ",ncfile),intern=T))<1) {
|
131
|
print(paste(ncfile," has no time, deleting"))
|
132
|
file.remove(ncfile)
|
133
|
}
|
134
|
print(paste(basename(ncfile)," Finished"))
|
135
|
|
136
|
|
137
|
}
|
138
|
|
139
|
|
140
|
### merge all the tiles to a single global composite
|
141
|
#system(paste("ncdump -h ",list.files(tempdir,pattern="mod09.*.nc$",full=T)[10]))
|
142
|
file.remove("tmp/mod09_2000-01-15.nc")
|
143
|
system(paste("cdo -O mergetime -setrtomiss,-32768,-1 ",paste(list.files(tempdir,pattern="mod09.*.nc$",full=T),collapse=" ")," data/cloud_monthly.nc"))
|
144
|
|
145
|
# Overall mean
|
146
|
system(paste("cdo -O timmean data/cloud_monthly.nc data/cloud_mean.nc"))
|
147
|
|
148
|
### generate the monthly mean and sd
|
149
|
#system(paste("cdo -P 10 -O merge -ymonmean data/mod09.nc -chname,CF,CF_sd -ymonstd data/mod09.nc data/mod09_clim.nc"))
|
150
|
system(paste("cdo -f nc4c -O -ymonmean data/cloud_monthly.nc data/cloud_ymonmean.nc"))
|
151
|
|
152
|
|
153
|
## Seasonal Means
|
154
|
system(paste("cdo -f nc4c -O -yseasmean data/cloud_monthly.nc data/cloud_yseasmean.nc"))
|
155
|
system(paste("cdo -f nc4c -O -yseasstd data/cloud_monthly.nc data/cloud_yseasstd.nc"))
|
156
|
|
157
|
## standard deviations, had to break to limit memory usage
|
158
|
system(paste("cdo -f nc4c -z zip -O -chname,CF,CF_sd -ymonstd -selmon,1,2,3,4,5,6 data/cloud_monthly.nc data/cloud_ymonsd_1-6.nc"))
|
159
|
system(paste("cdo -f nc4c -z zip -O -chname,CF,CF_sd -ymonstd -selmon,7,8,9,10,11,12 data/cloud_monthly.nc data/cloud_ymonsd_7-12.nc"))
|
160
|
system(paste("cdo -f nc4c -z zip -O mergetime data/cloud_ymonsd_1-6.nc data/cloud_ymonsd_7-12.nc data/cloud_ymonstd.nc"))
|
161
|
|
162
|
system("cdo -f nc4c -z zip timmin data/cloud_ymonmean.nc data/cloud_min.nc")
|
163
|
system("cdo -f nc4c -z zip timmax data/cloud_ymonmean.nc data/cloud_max.nc")
|
164
|
|
165
|
## standard deviation of mean monthly values give intra-annual variability
|
166
|
system("cdo -f nc4c -z zip -chname,CF,CFsd -timstd data/cloud_ymonmean.nc data/cloud_std_intra.nc")
|
167
|
## mean of monthly standard deviations give inter-annual variability
|
168
|
system("cdo -f nc4c -z zip -chname,CF,CFsd -timmean data/cloud_ymonstd.nc data/cloud_std_inter.nc")
|
169
|
|
170
|
|
171
|
# Regressions through time by season
|
172
|
s=c("DJF","MAM","JJA","SON")
|
173
|
|
174
|
system(paste("cdo -f nc4c -O regres -selseas,",s[1]," data/cloud_monthly.nc data/slope_",s[1],".nc",sep=""))
|
175
|
system(paste("cdo -f nc4c -O regres -selseas,",s[2]," data/cloud_monthly.nc data/slope_",s[2],".nc",sep=""))
|
176
|
system(paste("cdo -f nc4c -O regres -selseas,",s[3]," data/cloud_monthly.nc data/slope_",s[3],".nc",sep=""))
|
177
|
system(paste("cdo -f nc4c -O regres -selseas,",s[4]," data/cloud_monthly.nc data/slope_",s[4],".nc",sep=""))
|
178
|
|
179
|
|
180
|
|
181
|
## Daily animations
|
182
|
regs=list(
|
183
|
Venezuela=extent(c(-69,-59,0,7)),
|
184
|
Cascades=extent(c(-122.8,-118,44.9,47)),
|
185
|
Hawaii=extent(c(-156.5,-154,18.75,20.5)),
|
186
|
Boliva=extent(c(-71,-63,-20,-15)),
|
187
|
CFR=extent(c(17.75,22.5,-34.8,-32.6)),
|
188
|
Madagascar=extent(c(46,52,-17,-12))
|
189
|
)
|
190
|
|
191
|
r=1
|
192
|
|
193
|
system(paste("cdo -f nc4c -O inttime,2012-01-15,12:00:00,7day -sellonlatbox,",
|
194
|
paste(regs[[r]]@xmin,regs[[r]]@xmax,regs[[r]]@ymin,regs[[r]]@ymax,sep=","),
|
195
|
" data/cloud_monthly.nc data/daily_",names(regs[r]),".nc",sep=""))
|
196
|
|
197
|
|
198
|
|
199
|
|
200
|
### Long term summaries
|
201
|
seasconc <- function(x,return.Pc=T,return.thetat=F) {
|
202
|
#################################################################################################
|
203
|
## Precipitation Concentration function
|
204
|
## This function calculates Precipitation Concentration based on Markham's (1970) technique as described in Schulze (1997)
|
205
|
## South Africa Atlas of Agrohydology and Climatology - R E Schulze, M Maharaj, S D Lynch, B J Howe, and B Melvile-Thomson
|
206
|
## Pages 37-38
|
207
|
#################################################################################################
|
208
|
## x is a vector of precipitation quantities - the mean for each factor in "months" will be taken,
|
209
|
## so it does not matter if the data are daily or monthly, as long as the "months" factor correctly
|
210
|
## identifies them into 12 monthly bins, collapse indicates whether the data are already summarized as monthly means.
|
211
|
#################################################################################################
|
212
|
theta=seq(30,360,30)*(pi/180) # set up angles for each month & convert to radians
|
213
|
if(sum(is.na(x))==12) { return(cbind(Pc=NA,thetat=NA)) ; stop}
|
214
|
if(return.Pc) {
|
215
|
rt=sqrt(sum(x * cos(theta))^2 + sum(x * sin(theta))^2) # the magnitude of the summation
|
216
|
Pc=as.integer(round((rt/sum(x))*100))}
|
217
|
if(return.thetat){
|
218
|
s1=sum(x*sin(theta),na.rm=T); s2=sum(x*cos(theta),na.rm=T)
|
219
|
if(s1>=0 & s2>=0) {thetat=abs((180/pi)*(atan(sum(x*sin(theta),na.rm=T)/sum(x*cos(theta),na.rm=T))))}
|
220
|
if(s1>0 & s2<0) {thetat=180-abs((180/pi)*(atan(sum(x*sin(theta),na.rm=T)/sum(x*cos(theta),na.rm=T))))}
|
221
|
if(s1<0 & s2<0) {thetat=180+abs((180/pi)*(atan(sum(x*sin(theta),na.rm=T)/sum(x*cos(theta),na.rm=T))))}
|
222
|
if(s1<0 & s2>0) {thetat=360-abs((180/pi)*(atan(sum(x*sin(theta),na.rm=T)/sum(x*cos(theta),na.rm=T))))}
|
223
|
thetat=as.integer(round(thetat))
|
224
|
}
|
225
|
if(return.thetat&return.Pc) return(c(conc=Pc,theta=thetat))
|
226
|
if(return.Pc) return(Pc)
|
227
|
if(return.thetat) return(thetat)
|
228
|
}
|
229
|
|
230
|
|
231
|
|
232
|
## read in monthly dataset
|
233
|
mod09=brick("data/cloud_ymonmean.nc",varname="CF")
|
234
|
plot(mod09[1])
|
235
|
|
236
|
mod09_seas=calc(mod09,seasconc,return.Pc=T,return.thetat=F,overwrite=T,filename="data/mod09_seas.nc",NAflag=255,datatype="INT1U")
|
237
|
mod09_seas2=calc(mod09,seasconc,return.Pc=F,return.thetat=T,overwrite=T,filename="data/mod09_seas_theta.nc",datatype="INT1U")
|
238
|
|
239
|
plot(mod09_seas)
|