4 |
4 |
library(doMC)
|
5 |
5 |
library(multicore)
|
6 |
6 |
library(foreach)
|
7 |
|
registerDoMC(4)
|
|
7 |
library(mgcv)
|
|
8 |
registerDoMC(2)
|
|
9 |
|
|
10 |
|
|
11 |
## start raster cluster
|
|
12 |
#beginCluster(10)
|
8 |
13 |
|
9 |
14 |
setwd("~/acrobates/adamw/projects/cloud")
|
10 |
15 |
|
... | ... | |
15 |
20 |
|
16 |
21 |
|
17 |
22 |
## use ramdisk?
|
18 |
|
tmpfs=tempdir()
|
|
23 |
tmpfs="tmp/"#tempdir()
|
19 |
24 |
|
20 |
|
ramdisk=T
|
|
25 |
|
|
26 |
ramdisk=F
|
21 |
27 |
if(ramdisk) {
|
22 |
28 |
system("sudo mkdir -p /mnt/ram")
|
23 |
29 |
system("sudo mount -t ramfs -o size=30g ramfs /mnt/ram")
|
... | ... | |
25 |
31 |
tmpfs="/mnt/ram"
|
26 |
32 |
}
|
27 |
33 |
|
|
34 |
rasterOptions(tmpdir=tmpfs,overwrite=T, format="GTiff",maxmemory=1e9)
|
|
35 |
|
28 |
36 |
|
29 |
37 |
rerun=T # set to true to recalculate all dates even if file already exists
|
30 |
38 |
|
31 |
|
## Loop over existing months to build composite netcdf files
|
32 |
|
foreach(i=1:nrow(df)) %dopar% {
|
33 |
|
## get date
|
34 |
|
date=df$date[i]
|
|
39 |
|
|
40 |
jobs=expand.grid(month=1:12,sensor=c("MOD09","MYD09"))
|
|
41 |
## Loop over existing months to build composite netcdf files
|
|
42 |
foreach(i=1:nrow(jobs)) %dopar% {
|
|
43 |
## get month
|
|
44 |
m=jobs$month[i]
|
|
45 |
date=df$date[df$month==m][1]
|
35 |
46 |
print(date)
|
|
47 |
## get sensor
|
|
48 |
s=jobs$sensor[i]
|
36 |
49 |
## Define output and check if it already exists
|
37 |
|
# vrtfile=paste(tmpfs,"/modcf_",df$month[i],".vrt",sep="")
|
38 |
|
temptffile=paste(tmpfs,"/modcf_",df$month[i],".tif",sep="")
|
39 |
|
temptffile2=paste(tmpfs,"/modcf_",df$month[i],".tif",sep="")
|
40 |
|
ncfile=paste("data/mod09cloud2/modcf_",df$month[i],".nc",sep="")
|
|
50 |
tvrt=paste(tmpfs,"/",s,"_",m,".vrt",sep="")
|
|
51 |
ttif1=paste(tmpfs,"/",s,"_",m,".tif",sep="")
|
|
52 |
ttif2=paste(tmpfs,"/",s,"_",m,"_wgs84.tif",sep="")
|
|
53 |
ncfile=paste("data/mcd09nc/",s,"_",m,".nc",sep="")
|
|
54 |
|
41 |
55 |
## check if output already exists
|
42 |
56 |
if(!rerun&file.exists(ncfile)) return(NA)
|
43 |
|
## Develop mask
|
44 |
|
# nObs=
|
45 |
|
# system(paste("pksetmask -i ",temptffile," -m ",nObs," --operator='<' --msknodata 1 --nodata 255 --operator='>' --msknodata 10 --nodata 10 -o ",temptiffile2,sep=""))
|
|
57 |
## build VRT to merge tiles
|
|
58 |
system(paste("gdalbuildvrt ",tvrt," ",paste(df$path[df$month==m&df$sensor==s],collapse=" ")))
|
|
59 |
|
|
60 |
##
|
|
61 |
mod=stack(tvrt)
|
|
62 |
names(mod)=c("cf","cfsd","nobs","pobs")
|
|
63 |
#################################
|
|
64 |
## correct for orbital artifacts
|
|
65 |
|
|
66 |
## sample points to fit correction model
|
|
67 |
reg=extent(-20016036,20016036, -4295789.46149, 4134293.61707) #banding region
|
|
68 |
cmod=crop(mod,reg)
|
|
69 |
names(cmod)=c("cf","cfsd","nobs","pobs")
|
|
70 |
modpts=sampleRandom(cmod, size=10000, na.rm=TRUE, xy=T, sp=T)
|
|
71 |
modpts=modpts[modpts$nobs>0,] #drop data from missing tiles
|
|
72 |
### fit popbs correctionmodel (accounting for spatial variation in cf)
|
|
73 |
modlm1=bam(cf~s(x,y)+pobs,data=modpts@data)
|
|
74 |
summary(modlm1)
|
|
75 |
modbeta1=coef(modlm1)["pobs"]
|
|
76 |
|
|
77 |
|
|
78 |
#modlm2=bam(cf~s(x,y),data=modpts@data)
|
|
79 |
#resid=residuals(modlm2)#,newdata=data.frame(x=modpts$x,y=modpts$y,pobs=100))
|
|
80 |
#pred=predict(modlm1,newdata=data.frame(x=modpts$x,y=modpts$y,pobs=100))
|
|
81 |
#plot(resid~pobs,data=modpts@data);abline(lm(resid~modpts$pobs))
|
|
82 |
#plot(modlm1);points(modpts)
|
|
83 |
|
|
84 |
#writeLines(paste(date," slope:",round(modbeta1,4)))
|
|
85 |
|
|
86 |
## mask no data regions (with less than 1 observation per day within that month)
|
|
87 |
## use model above to correct for orbital artifacts
|
|
88 |
biasf=function(cf,cfsd,nobs,pobs) {
|
|
89 |
## drop data in areass with nobs<1
|
|
90 |
drop=nobs<0|pobs<=50
|
|
91 |
cf[drop]=NA
|
|
92 |
cfsd[drop]=NA
|
|
93 |
nobs[drop]=NA
|
|
94 |
pobs[drop]=NA
|
|
95 |
bias=round((100-pobs)*modbeta1)
|
|
96 |
cfc=cf+bias
|
|
97 |
return(c(cf=cf,cfsd=cfsd,bias=bias,cfc=cfc,nobs=nobs,pobs=pobs))}
|
|
98 |
|
|
99 |
# treg=extent(c(-1434564.00523,1784892.95369, 564861.173869, 1880991.3772))
|
|
100 |
# treg=extent(c(-2187230.72881, 4017838.07688, -339907.592509, 3589340.63805)) #all sahara
|
|
101 |
|
|
102 |
mod2=overlay(cmod,fun=biasf,unstack=TRUE,filename=ttif1,format="GTiff",
|
|
103 |
dataType="INT1U",overwrite=T,NAflag=255, options=c("COMPRESS=LZW", "BIGTIFF=YES"))
|
|
104 |
|
|
105 |
# system(paste("pksetmask -i ",modvrt," -m ",nObs,
|
|
106 |
# " --operator='<' --msknodata 1 --nodata 255 --operator='>' --msknodata 10 --nodata 10 -o ",modtif1,sep=""))
|
46 |
107 |
|
47 |
108 |
## warp to wgs84
|
48 |
|
ops=paste("-t_srs 'EPSG:4326' -multi -r bilinear -te -180 -90 180 90 -tr 0.008333333333333 -0.008333333333333",
|
49 |
|
"-co BIGTIFF=YES -ot Byte --config GDAL_CACHEMAX 300000 -wm 300000 -wo NUM_THREADS:10 -wo SOURCE_EXTRA=5")
|
50 |
|
system(paste("gdalwarp -overwrite ",ops," ",df$path[i]," ",temptffile))
|
|
109 |
ops=paste("-t_srs 'EPSG:4326' -multi -srcnodata 255 -dstnodata 255 -r bilinear -te -180 -90 180 90 -tr 0.008333333333333 -0.008333333333333",
|
|
110 |
"-co BIGTIFF=YES -ot Byte --config GDAL_CACHEMAX 500 -wm 500 -wo NUM_THREADS:10 -wo SOURCE_EXTRA=5")
|
|
111 |
# ops=paste("-t_srs 'EPSG:4326' -srcnodata 255 -dstnodata 255 -multi -r bilinear -tr 0.008333333333333 -0.008333333333333",
|
|
112 |
# "-co BIGTIFF=YES -ot Byte --config GDAL_CACHEMAX 300000 -wm 300000 -wo NUM_THREADS:10 -wo SOURCE_EXTRA=5")
|
|
113 |
system(paste("gdalwarp -overwrite ",ops," ",ttif1," ",ttif2))
|
51 |
114 |
|
52 |
|
## Warp to WGS84 grid and convert to netcdf
|
53 |
|
trans_ops=paste(" -co COMPRESS=DEFLATE -stats -co FORMAT=NC4C -co ZLEVEL=9")
|
54 |
|
system(paste("gdal_translate -of netCDF ",trans_ops," ",temptffile," ",ncfile))
|
|
115 |
## convert to netcdf, subset to mean/sd bands
|
|
116 |
trans_ops=paste(" -co COMPRESS=DEFLATE -a_nodata 255 -stats -co FORMAT=NC4 -co ZLEVEL=9 -b 4 -b 2")
|
|
117 |
system(paste("gdal_translate -of netCDF ",trans_ops," ",ttif2," ",ncfile))
|
55 |
118 |
## file.remove(temptffile)
|
56 |
119 |
system(paste("ncecat -O -u time ",ncfile," ",ncfile,sep=""))
|
57 |
120 |
## create temporary nc file with time information to append to CF data
|
... | ... | |
61 |
124 |
time = 1 ;
|
62 |
125 |
variables:
|
63 |
126 |
int time(time) ;
|
64 |
|
time:units = \"days since 2000-01-01 00:00:00\" ;
|
|
127 |
time:units = \"days since 2000-01-01 ",ifelse(s=="MOD09","10:30:00","13:30:00"),"\" ;
|
65 |
128 |
time:calendar = \"gregorian\";
|
66 |
129 |
time:long_name = \"time of observation\";
|
67 |
130 |
data:
|
... | ... | |
69 |
132 |
}"),file=paste(tempdir(),"/",date,"_time.cdl",sep=""))
|
70 |
133 |
system(paste("ncgen -o ",tempdir(),"/",date,"_time.nc ",tempdir(),"/",date,"_time.cdl",sep=""))
|
71 |
134 |
## add time dimension to ncfile and compress (deflate)
|
72 |
|
system(paste("ncks --fl_fmt=netcdf4_classic -L 9 -A ",tempdir(),"/",date,"_time.nc ",ncfile,sep=""))
|
|
135 |
system(paste("ncks --fl_fmt=netcdf4 -L 9 -A ",tempdir(),"/",date,"_time.nc ",ncfile,sep=""))
|
73 |
136 |
## add other attributes
|
74 |
137 |
system(paste("ncrename -v Band1,CF ",ncfile,sep=""))
|
75 |
138 |
system(paste("ncrename -v Band2,CFsd ",ncfile,sep=""))
|
|
139 |
## build correction factor explanation
|
76 |
140 |
system(paste("ncatted ",
|
77 |
141 |
## CF Mean
|
78 |
142 |
" -a units,CF,o,c,\"%\" ",
|
79 |
|
" -a valid_range,CF,o,b,\"0,100\" ",
|
|
143 |
" -a valid_range,CF,o,ub,\"0,100\" ",
|
80 |
144 |
# " -a scale_factor,CF,o,b,\"0.1\" ",
|
81 |
|
" -a _FillValue,CF,o,b,\"255\" ",
|
82 |
|
" -a missing_value,CF,o,b,\"255\" ",
|
|
145 |
" -a _FillValue,CF,o,ub,\"255\" ",
|
|
146 |
" -a missing_value,CF,o,ub,\"255\" ",
|
83 |
147 |
" -a long_name,CF,o,c,\"Cloud Frequency (%)\" ",
|
|
148 |
" -a correction_factor_description,CF,o,c,\"To account for variable observation frequency, CF in each pixel was adjusted by the proportion of days with at least one MODIS observation\" ",
|
|
149 |
" -a correction_factor,CF,o,f,\"",round(modbeta1,4),"\" ",
|
84 |
150 |
" -a NETCDF_VARNAME,CF,o,c,\"Cloud Frequency (%)\" ",
|
85 |
151 |
## CF Standard Deviation
|
86 |
152 |
" -a units,CFsd,o,c,\"SD\" ",
|
87 |
|
" -a valid_range,CFsd,o,b,\"0,200\" ",
|
|
153 |
" -a valid_range,CFsd,o,ub,\"0,200\" ",
|
88 |
154 |
" -a scale_factor,CFsd,o,f,\"0.25\" ",
|
89 |
|
" -a _FillValue,CFsd,o,b,\"255\" ",
|
90 |
|
" -a missing_value,CFsd,o,b,\"255\" ",
|
|
155 |
" -a _FillValue,CFsd,o,ub,\"255\" ",
|
|
156 |
" -a missing_value,CFsd,o,ub,\"255\" ",
|
91 |
157 |
" -a long_name,CFsd,o,c,\"Cloud Frequency (%) Intra-month (2000-2013) Standard Deviation\" ",
|
92 |
158 |
" -a NETCDF_VARNAME,CFsd,o,c,\"Cloud Frequency (%) Intra-month (2000-2013) Standard Deviation\" ",
|
93 |
159 |
## global
|
GAM with global slope overcorrects in many areas, will now explore focal gam with spatial params