Revision e5cf164a
Added by Adam Wilson almost 11 years ago
climate/research/cloud/MOD09/2_bias.R | ||
---|---|---|
5 | 5 |
library(foreach) |
6 | 6 |
library(RcppOctave) |
7 | 7 |
library(rgdal) |
8 |
registerDoMC(7)
|
|
8 |
registerDoMC(15)
|
|
9 | 9 |
|
10 | 10 |
|
11 | 11 |
# final output will be written to data directory here: |
12 |
setwd("~/acrobates/adamw/projects/cloud")
|
|
12 |
setwd("/mnt/data/personal/adamw/projects/cloud")
|
|
13 | 13 |
|
14 | 14 |
# temporary files will be written here: |
15 | 15 |
datadir="/mnt/data2/projects/cloud/" |
16 | 16 |
|
17 | 17 |
|
18 | 18 |
## Specify path to VSNR souce code and add it to RcppOctave path |
19 |
mpath="/home/adamw/acrobates/adamw/projects/environmental-layers/climate/research/cloud/MOD09/vsnr/"
|
|
19 |
mpath="/mnt/data/personal/adamw/projects/environmental-layers/climate/research/cloud/MOD09/vsnr/"
|
|
20 | 20 |
.O$addpath(mpath) |
21 | 21 |
|
22 | 22 |
|
... | ... | |
46 | 46 |
d2=as.matrix(d) |
47 | 47 |
d2[is.na(d2)]=0 |
48 | 48 |
## Process with VSNR |
49 |
dt=.CallOctave("VSNR",d2,epsilon,p,as.matrix(gabor),alpha,maxit+1,prec,C1,argout ="u",verbose=T);
|
|
49 |
dt=.CallOctave("VSNR",d2,epsilon,p,as.matrix(gabor),alpha,maxit+1,prec,C1,argout ="u",verbose=F);
|
|
50 | 50 |
## Create spatial objects from VSNR output |
51 | 51 |
dc=d |
52 | 52 |
values(dc)=as.numeric(t(dt$u)) # Make 'corrected' version of data |
53 | 53 |
## Set NA values in original data back to NA |
54 | 54 |
dc[is.na(d)]=NA |
55 |
## remove temp files |
|
56 |
rm(d2) |
|
57 |
## return the corrected data |
|
55 | 58 |
return(dc) |
56 | 59 |
} |
57 | 60 |
|
... | ... | |
76 | 79 |
exts=expand.grid(xmin=xmins,ymin=ymins) |
77 | 80 |
exts$ymax=exts$ymin+size |
78 | 81 |
exts$xmax=exts$xmin+size |
82 |
exts$tile=1:nrow(exts) |
|
79 | 83 |
return(exts) |
80 | 84 |
} |
81 | 85 |
|
82 |
df2=list.files(paste(datadir,"/mcd09tif",sep=""),full=T,pattern="[0-9][.]tif$") |
|
86 |
|
|
83 | 87 |
i=1 |
84 | 88 |
ti=7 |
85 |
|
|
86 |
### Build the tiles |
|
89 |
### Build the tiles to process |
|
87 | 90 |
exts=extf(xmin=-180,xmax=180,ymin=-30,ymax=30,size=60,overlap=0) |
88 | 91 |
|
89 | 92 |
## add an extra tile to account for regions of reduced data availability for each sensor |
90 |
modexts=c(xmin=130,xmax=180,ymin=-50,ymax=0) |
|
91 |
mydexts=c(xmin=-170,xmax=-140,ymin=-30,ymax=55) |
|
93 |
modexts=cbind.data.frame(sensor="MOD09",rbind.data.frame( |
|
94 |
exts, |
|
95 |
c(xmin=130,ymin=-50,ymax=-25,xmax=180,tile=nrow(exts)+1), |
|
96 |
c(xmin=130,ymin=-25,ymax=0,xmax=180,tile=nrow(exts)+2))) |
|
97 |
mydexts=cbind.data.frame(sensor="MYD09",rbind.data.frame( |
|
98 |
exts, |
|
99 |
c(xmin=-170,ymin=-30,ymax=0,xmax=-140,tile=nrow(exts)+1), |
|
100 |
c(xmin=-170,ymin=0,ymax=55,xmax=-140,tile=nrow(exts)+2))) |
|
92 | 101 |
|
102 |
allexts=rbind.data.frame(modexts,mydexts) |
|
93 | 103 |
|
94 |
## loop over sensor-months to create full grid of corrected values |
|
95 |
for( i in 1:nrow(df2))){ |
|
96 |
file=df2[i] |
|
97 |
outfile=paste(datadir,"/mcd09ctif/",basename(file),sep="") |
|
98 |
# outfile2=paste("data/mcd09tif/",basename(file),sep="") |
|
99 |
# outfile2b=paste("data/mcd09tif/",sub("[.]tif","_sd.tif",basename(file)),sep="") |
|
104 |
### assemble list of files to process |
|
105 |
df2=data.frame(path=list.files(paste(datadir,"/mcd09tif",sep=""),full=T,pattern="[0-9][.]tif$"),stringsAsFactors=F) |
|
106 |
df2[,c("sensor","month")]=do.call(rbind.data.frame,strsplit(basename(df2$path),"_|[.]"))[,c(1,2)] |
|
107 |
|
|
108 |
## create a list of jobs to process |
|
109 |
jobs=data.frame(allexts,month=rep(sprintf("%02d",1:12),each=nrow(allexts))) |
|
110 |
jobs$path=df2$path[match(paste(jobs$sensor,jobs$month),paste(df2$sensor,df2$month))] |
|
100 | 111 |
|
101 |
## set sensor-specific parameters |
|
112 |
|
|
113 |
## loop over sensor-months to create full grid of corrected values |
|
114 |
foreach( i=1:nrow(jobs)) %dopar% { |
|
115 |
file=jobs$path[i] |
|
116 |
toutfile=paste(datadir,"mcd09bias/", sub(".tif","",basename(file)),"_",jobs$tile[i],".tif",sep="") |
|
117 |
if(file.exists(toutfile)) {writeLines(paste(toutfile,"Exists, moving on"));next} |
|
118 |
writeLines(paste("Starting: ",toutfile," tile:",jobs$tile[i]," ( ",i," out of ",nrow(jobs),")")) |
|
119 |
## set sensor-specific parameters |
|
102 | 120 |
## add extra region for correction depending on which sensor is being processed |
103 | 121 |
## set angle of orbital artefacts to be corrected |
104 |
sensor=ifelse(grepl("MOD",file),"MOD","MYD") |
|
105 |
if(sensor=="MOD") { |
|
106 |
exts=rbind(exts,modexts) |
|
107 |
scanangle=-15 |
|
108 |
} |
|
109 |
if(sensor=="MYD") { |
|
110 |
exts=rbind(exts,mydexts) |
|
111 |
scanangle=15 |
|
112 |
} |
|
113 |
|
|
122 |
sensor=jobs$sensor[i] |
|
123 |
if(sensor=="MOD09") scanangle=-15 |
|
124 |
if(sensor=="MYD09") scanangle=15 |
|
114 | 125 |
## Process the tiles |
115 |
foreach(ti=1:nrow(exts)) %dopar% { |
|
116 |
textent=extent(exts$xmin[ti],exts$xmax[ti],exts$ymin[ti],exts$ymax[ti]) |
|
117 |
## extract the tile |
|
118 |
toutfile=paste("tmp/", sub(".tif","",basename(file)),"_",sprintf("%03d",ti),".tif",sep="") |
|
119 |
writeLines(paste("Starting: ",toutfile," tile:",ti," ( out of ",nrow(exts),")")) |
|
120 |
d=crop(raster(file),textent) |
|
121 |
## acount for scale of data is 10000*CF |
|
122 |
d=d*.01 |
|
123 |
## skip null tiles - will only have this if tiles are quite small (<10 degrees) |
|
124 |
if(is.null(d@data@values)) return(NULL) |
|
125 |
## make the gabor kernel |
|
126 |
## this specifies the 'shape' of the noise we are trying to remove |
|
127 |
psi=fgabor(d,theta=scanangle,x=400,y=4) #3 |
|
128 |
# psi=stack(lapply(scanangle,function(a) fgabor(d,theta=a,x=400,y=4))) #3 |
|
129 |
|
|
130 |
## run the correction function. |
|
131 |
res=vsnr(d,gabor=psi,alpha=2,p=2,epsilon=1,prec=5e-6,maxit=50,C=1,full=F) |
|
132 |
## write the file |
|
133 |
if(!is.null(outfile)) writeRaster(res*100,file=toutfile,overwrite=T,datatype='INT2S',options=c("COMPRESS=LZW", "PREDICTOR=2"),NAvalue=-32768) |
|
134 |
## remove temporary files |
|
135 |
rmr(d);rmr(psi);rmr(res) |
|
136 |
print(paste("Finished Temporary File: ",toutfile)) |
|
137 |
} |
|
138 |
## create VRT of first band of the full image |
|
139 |
fvrt=sub("[.]tif","_cf.vrt",file) |
|
140 |
system(paste("gdalbuildvrt -b 1 ",fvrt," ",file)) |
|
141 |
## mosaic the tiles with the original data (keeping the new data when available) |
|
142 |
tfiles=paste(c(fvrt,list.files("tmp",pattern=paste(sub("[.]tif","",basename(outfile)),"_[0-9]*[.]tif",sep=""),full=T)),collapse=" ") |
|
143 |
system(paste("gdal_merge.py -init -32768 -n -32768 -co COMPRESS=LZW -co PREDICTOR=2 -co BIGTIFF=yes -o ",outfile," ",tfiles,sep="")) |
|
126 |
textent=extent(jobs$xmin[i],jobs$xmax[i],jobs$ymin[i],jobs$ymax[i]) |
|
127 |
## extract the tile |
|
128 |
## extract the data |
|
129 |
d=crop(raster(file),textent) |
|
130 |
## acount for scale of data is 10000*CF, so convert to 0-100 |
|
131 |
d2=d*.01 |
|
132 |
## skip null tiles - will only have this if tiles are quite small (<10 degrees) |
|
133 |
if(is.null(d2@data@values)) return(NULL) |
|
134 |
## make the gabor kernel |
|
135 |
## this specifies the 'shape' of the noise we are trying to remove |
|
136 |
psi=fgabor(d2,theta=scanangle,x=400,y=4) #3 |
|
137 |
## run the correction function. |
|
138 |
res=vsnr(d2,gabor=psi,alpha=2,p=2,epsilon=1,prec=5e-6,maxit=50,C=1,full=F) |
|
139 |
res2=res*100 |
|
140 |
## write the file |
|
141 |
writeRaster(res2,file=toutfile,overwrite=T,datatype='INT2S',options=c("COMPRESS=LZW", "PREDICTOR=2"),NAvalue=-32768) |
|
142 |
## remove temporary files |
|
143 |
rmr(d);rmr(d2);rmr(psi);rmr(res);rmr(res2) |
|
144 |
print(paste("Finished Temporary File: ",toutfile)) |
|
144 | 145 |
} |
145 | 146 |
|
146 | 147 |
|
147 |
################################################################################ |
|
148 |
### calculate monthly means of terra and aqua |
|
149 |
|
|
150 |
# Create combined (MOD+MYD) uncorrected mean CF |
|
151 |
foreach(i=1:12) %dopar% { |
|
152 |
## get files |
|
153 |
f=list.files(paste(datadir,"/mcd09ctif",sep=""),pattern=paste(".*[O|Y].*_",sprintf("%02d",i),"[.]tif$",sep=""),full=T) |
|
154 |
## Define output and check if it already exists |
|
155 |
tmcd=paste(datadir,"/mcd09ctif/MCD09_",sprintf("%02d", i),".tif",sep="") |
|
156 |
## check if output already exists |
|
157 |
ops=paste("-t_srs 'EPSG:4326' -multi -srcnodata -32768 -dstnodata -32768 -r bilinear -te -180 -90 180 90 -tr 0.008333333333333 -0.008333333333333", |
|
158 |
"-co BIGTIFF=YES --config GDAL_CACHEMAX 500 -wm 500 -wo NUM_THREADS:10 -wo SOURCE_EXTRA=5") |
|
159 |
system(paste("gdalwarp -overwrite -r average -co COMPRESS=LZW -co ZLEVEL=9 ",ops," ",paste(f,collapse=" ")," ",tmcd)) |
|
160 |
## update metadata |
|
161 |
tags=c(paste("TIFFTAG_IMAGEDESCRIPTION='Monthly Cloud Frequency for 2000-2013 extracted from C5 MODIS MOD09GA and MYD09GA PGE11 internal cloud mask algorithm (embedded in state_1km bit 10).", |
|
162 |
"The daily cloud mask time series were summarized to mean cloud frequency (CF) by calculating the proportion of cloudy days. ", |
|
163 |
"Band Descriptions: 1) Mean Monthly Cloud Frequency 2) Four Times the Standard Deviation of Mean Monthly Cloud Frequency"'"), |
|
164 |
"TIFFTAG_DOCUMENTNAME='Collection 5 MCD09 Cloud Frequency'", |
|
165 |
paste("TIFFTAG_DATETIME='2013",sprintf("%02d", i),"15'",sep=""), |
|
166 |
"TIFFTAG_ARTIST='Adam M. Wilson (adam.wilson@yale.edu)'") |
|
167 |
system(paste("/usr/local/src/gdal-1.10.0/swig/python/scripts/gdal_edit.py ",tmcd," ",paste("-mo ",tags,sep="",collapse=" "),sep="")) |
|
168 |
writeLines(paste("Finished month",i)) |
|
169 |
} |
|
148 |
|
|
149 |
############################################ |
|
150 |
## now mosaic the tiles with the original image to keep only the corrected data (when available) and the uncorrected data where there is no tile. |
|
151 |
## this relies on df2 created above |
|
152 |
|
|
153 |
foreach( i=1:nrow(df2)) %dopar% { |
|
154 |
ifile=df2$path[i] |
|
155 |
outfile=paste(datadir,"/mcd09ctif/",df2$sensor[i],"_",df2$month[i],".tif",sep="") |
|
156 |
if(file.exists(outfile)) next |
|
157 |
## create VRT of first band of the full image |
|
158 |
fvrt=sub("[.]tif",".vrt",ifile) |
|
159 |
system(paste("gdalbuildvrt -b 1 ",fvrt," ",ifile)) |
|
160 |
## mosaic the tiles with the original data (keeping the new data when available) |
|
161 |
tfiles=paste(c(fvrt,list.files(paste(datadir,"/mcd09bias",sep=""),pattern=paste(sub("[.]tif","",basename(outfile)),"_[0-9]*[.]tif",sep=""),full=T)),collapse=" ") |
|
162 |
if(file.exists(outfile)) file.remove(outfile) |
|
163 |
system(paste("gdal_merge.py --config GDAL_CACHEMAX 10000 -init -32768 -n -32768 -co COMPRESS=LZW -co PREDICTOR=2 -co BIGTIFF=yes -o ",outfile," ",tfiles,sep="")) |
|
164 |
writeLines(paste("Finished ",outfile)) |
|
165 |
} |
|
170 | 166 |
|
171 | 167 |
|
172 | 168 |
|
climate/research/cloud/MOD09/3_combine.R | ||
---|---|---|
4 | 4 |
datadir="/mnt/data2/projects/cloud/" |
5 | 5 |
|
6 | 6 |
# Create combined (MOD+MYD) corrected mean CF |
7 |
foreach(i=1:12) %dopar% {
|
|
7 |
foreach(i=1:2) %dopar% { |
|
8 | 8 |
|
9 | 9 |
f=list.files(paste(datadir,"/mcd09ctif",sep=""),pattern=paste(".*[O|Y].*_",sprintf("%02d",i),"[.]tif$",sep=""),full=T) |
10 | 10 |
## Define output and check if it already exists |
11 |
tmcd=paste(datadir,"/mcd09ctif/MCD09_",sprintf("%02d", i),".tif",sep="") |
|
11 |
tmcd=paste(datadir,"/mcd09ctif/MCD09_",sprintf("%02d", i),"_uncompressed.tif",sep="") |
|
12 |
tmcd2=paste(datadir,"/mcd09ctif/MCD09_",sprintf("%02d", i),".tif",sep="") |
|
12 | 13 |
## check if output already exists |
13 | 14 |
ops=paste("-t_srs 'EPSG:4326' -multi -srcnodata -32768 -dstnodata -32768 -r bilinear -te -180 -90 180 90 -tr 0.008333333333333 -0.008333333333333", |
14 | 15 |
"-co BIGTIFF=YES --config GDAL_CACHEMAX 500 -wm 500 -wo NUM_THREADS:10 -wo SOURCE_EXTRA=5") |
... | ... | |
22 | 23 |
paste("TIFFTAG_DATETIME='2013",sprintf("%02d", i),"15'",sep=""), |
23 | 24 |
"TIFFTAG_ARTIST='Adam M. Wilson (adam.wilson@yale.edu)'") |
24 | 25 |
system(paste("/usr/local/src/gdal-1.10.0/swig/python/scripts/gdal_edit.py ",tmcd," ",paste("-mo ",tags,sep="",collapse=" "),sep="")) |
26 |
# create final fixed image |
|
27 |
system(paste("gdal_translate -a_nodata -32768 -co COMPRESS=LZW -co ZLEVEL=9 -co PREDICTOR=2 ",tmcd," ",tmcd2,sep="")) |
|
25 | 28 |
writeLines(paste("Finished month",i)) |
26 | 29 |
} |
27 | 30 |
|
... | ... | |
29 | 32 |
|
30 | 33 |
################################################################################# |
31 | 34 |
###### convert to 8-bit compressed file, add colors and other details |
32 |
for( i in 1:12){ |
|
33 |
f2=list.files(paste(datadir,"/mcd09ctif",sep=""),pattern=paste(".*MCD09_",sprintf("%02d",i),"[.]tif$",sep=""),full=T) |
|
34 |
|
|
35 |
outfile=paste(datadir,"/mcd09ctif/",basename(file),sep="") |
|
36 |
outfile2=paste("data/mcd09tif/MCD09_",sprintf("%02d",i),".tif",sep="") |
|
37 |
outfile2b=paste("data/mcd09tif/MCD09_",sprintf("%02d",i),"_sd.tif",sep="") |
|
35 |
f2=list.files(paste(datadir,"/mcd09ctif",sep=""),pattern=paste(".*MCD09_[0-9].[.]tif$",sep=""),full=T) |
|
36 |
|
|
37 |
for( i in 1:length(f2)){ |
|
38 |
file=f2[i] |
|
39 |
outfilevrt=paste(datadir,"/mcd09ctif/",sub(".tif",".vrt",basename(file)),sep="") |
|
40 |
outfile=paste("data/mcd09tif/MCD09_",sprintf("%02d",i),".tif",sep="") |
|
41 |
outfilesd=paste("data/mcd09tif/MCD09_",sprintf("%02d",i),"_sd.tif",sep="") |
|
42 |
## create VRT and edit the color table |
|
43 |
## create the vrt to add a color table following https://trac.osgeo.org/gdal/wiki/FAQRaster#Howtocreateormodifyanimagecolortable |
|
44 |
system(paste("gdal_translate -scale 0 10000 0 100 -of VRT ",file," ",outfilevrt)) |
|
45 |
vrt=scan(outfilevrt,what="char") |
|
46 |
hd=c("<ColorInterp>Palette</ColorInterp>","<ColorTable>") |
|
47 |
ft="</ColorTable>" |
|
48 |
colR=colorRampPalette(c("#08306b","#0d57a1","#2878b8","#4997c9","#72b2d7","#a2cbe2","#c7dcef","#deebf7","#f7fbff")) |
|
49 |
cols=data.frame(t(col2rgb(colR(101)))) |
|
50 |
ct=paste("<Entry c1=\"",cols$red,"\" c2=\"",cols$green,"\" c3=\"",cols$blue,"\" c4=\"255\"/>") |
|
51 |
cti=grep("ColorInterp",vrt) # get index of current color table |
|
52 |
vrt2=c(vrt[1:(cti-1)],hd,ct,ft,vrt[(cti+1):length(vrt)]) |
|
53 |
## update missing data flag following http://lists.osgeo.org/pipermail/gdal-dev/2010-February/023541.html |
|
54 |
csi=grep("<ComplexSource>",vrt2) # get index of current color table |
|
55 |
vrt2=c(vrt2[1:csi],"<NODATA>-327.68</NODATA>",vrt2[(csi+1):length(vrt2)]) |
|
56 |
write.table(vrt2,file=outfilevrt,col.names=F,row.names=F,quote=F) |
|
57 |
|
|
58 |
#system(paste("gdal_translate -of VRT -scale 0 10000 0 100 ",outfilevrt," ",outfilevrt2)) |
|
38 | 59 |
|
39 | 60 |
## convert to 8-bit compressed file |
40 |
ops="-stats -scale 0 10000 0 100 -ot Byte -a_nodata 255 -co COMPRESS=LZW -co PREDICTOR=2 -co BIGTIFF=yes" |
|
61 |
## update vrt to correctly handle missing data |
|
62 |
#vrt3=scan(outfilevrt2,what="char") |
|
63 |
#csi=grep("<ComplexSource>",vrt3) # get index of current color table |
|
64 |
#vrt3=c(vrt[1:csi],"<NODATA>-32768</NODATA>",vrt[(csi+1):length(vrt)]) |
|
65 |
#write.table(vrt3,file=outfilevrt2,col.names=F,row.names=F,quote=F) |
|
66 |
|
|
67 |
# system(paste("pkreclass -i ",outfilevrt," ",paste("-mo ",tags,sep="",collapse=" ")," ",outfilevrt," ",outfile2)) |
|
41 | 68 |
tags=c(paste("TIFFTAG_IMAGEDESCRIPTION='Monthly Cloud Frequency for 2000-2013 extracted from C5 MODIS M*D09GA PGE11 internal cloud mask algorithm (embedded in state_1km bit 10).", |
42 | 69 |
"The daily cloud mask time series were summarized to mean cloud frequency (CF) by calculating the proportion of cloudy days. ", |
43 | 70 |
"Band Descriptions: 1) Mean Monthly Cloud Frequency'"), |
44 | 71 |
"TIFFTAG_DOCUMENTNAME='Collection 5 Cloud Frequency'", |
45 | 72 |
paste("TIFFTAG_DATETIME='2014'",sep=""), |
46 | 73 |
"TIFFTAG_ARTIST='Adam M. Wilson (adam.wilson@yale.edu)'") |
47 |
system(paste("gdal_translate ",ops," ",paste("-mo ",tags,sep="",collapse=" ")," ",outfile," ",outfile2)) |
|
74 |
system(paste("gdal_translate -ot Byte -co COMPRESS=LZW -co PREDICTOR=2 ",paste("-mo ",tags,sep="",collapse=" ")," ",outfilevrt," ",outfile)) |
|
75 |
|
|
48 | 76 |
## Convert SD to 8-bit |
49 |
system(paste("gdal_translate -b 2 ",ops," ",paste("-mo ",tags,sep="",collapse=" ")," ",file," ",outfile2b))
|
|
77 |
system(paste("gdal_translate -b 2 ",ops," ",paste("-mo ",tags,sep="",collapse=" ")," ",file," ",outfilesd))
|
|
50 | 78 |
} |
51 | 79 |
|
52 | 80 |
|
climate/research/cloud/MOD09/ee/ee_compile.R | ||
---|---|---|
18 | 18 |
|
19 | 19 |
|
20 | 20 |
### Download files from google drive |
21 |
## This only works if google-cli is installed and has already been authenticated |
|
21 | 22 |
download=T |
22 |
if(download) system(paste("google docs get 2014* ",datadir,"/mcd09ee",sep="")) |
|
23 |
if(download) system(paste("google docs get 2014*_g3_* ",datadir,"/mcd09ee",sep=""))
|
|
23 | 24 |
|
24 | 25 |
|
25 | 26 |
## Get list of available files |
... | ... | |
95 | 96 |
|
96 | 97 |
|
97 | 98 |
|
98 |
|
|
99 |
#### stuff below here is old junk..... |
|
100 |
|
|
101 |
## convert to netcdf, subset to mean/sd bands |
|
102 |
trans_ops=paste(" -co COMPRESS=DEFLATE -a_nodata 255 -stats -co FORMAT=NC4 -co ZLEVEL=9 -b 4 -b 2") |
|
103 |
system(paste("gdal_translate -of netCDF ",trans_ops," ",ttif2," ",ncfile)) |
|
104 |
## file.remove(temptffile) |
|
105 |
system(paste("ncecat -O -u time ",ncfile," ",ncfile,sep="")) |
|
106 |
## create temporary nc file with time information to append to CF data |
|
107 |
cat(paste(" |
|
108 |
netcdf time { |
|
109 |
dimensions: |
|
110 |
time = 1 ; |
|
111 |
variables: |
|
112 |
int time(time) ; |
|
113 |
time:units = \"days since 2000-01-01 ",ifelse(s=="MOD09","10:30:00","13:30:00"),"\" ; |
|
114 |
time:calendar = \"gregorian\"; |
|
115 |
time:long_name = \"time of observation\"; |
|
116 |
data: |
|
117 |
time=",as.integer(date-as.Date("2000-01-01")),"; |
|
118 |
}"),file=paste(tempdir(),"/",date,"_time.cdl",sep="")) |
|
119 |
system(paste("ncgen -o ",tempdir(),"/",date,"_time.nc ",tempdir(),"/",date,"_time.cdl",sep="")) |
|
120 |
## add time dimension to ncfile and compress (deflate) |
|
121 |
system(paste("ncks --fl_fmt=netcdf4 -L 9 -A ",tempdir(),"/",date,"_time.nc ",ncfile,sep="")) |
|
122 |
## add other attributes |
|
123 |
system(paste("ncrename -v Band1,CF ",ncfile,sep="")) |
|
124 |
system(paste("ncrename -v Band2,CFsd ",ncfile,sep="")) |
|
125 |
## build correction factor explanation |
|
126 |
system(paste("ncatted ", |
|
127 |
## CF Mean |
|
128 |
" -a units,CF,o,c,\"%\" ", |
|
129 |
" -a valid_range,CF,o,ub,\"0,100\" ", |
|
130 |
# " -a scale_factor,CF,o,b,\"0.1\" ", |
|
131 |
" -a _FillValue,CF,o,ub,\"255\" ", |
|
132 |
" -a missing_value,CF,o,ub,\"255\" ", |
|
133 |
" -a long_name,CF,o,c,\"Cloud Frequency (%)\" ", |
|
134 |
" -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\" ", |
|
135 |
" -a correction_factor,CF,o,f,\"",round(modbeta1,4),"\" ", |
|
136 |
" -a NETCDF_VARNAME,CF,o,c,\"Cloud Frequency (%)\" ", |
|
137 |
## CF Standard Deviation |
|
138 |
" -a units,CFsd,o,c,\"SD\" ", |
|
139 |
" -a valid_range,CFsd,o,ub,\"0,200\" ", |
|
140 |
" -a scale_factor,CFsd,o,f,\"0.25\" ", |
|
141 |
" -a _FillValue,CFsd,o,ub,\"255\" ", |
|
142 |
" -a missing_value,CFsd,o,ub,\"255\" ", |
|
143 |
" -a long_name,CFsd,o,c,\"Cloud Frequency (%) Intra-month (2000-2013) Standard Deviation\" ", |
|
144 |
" -a NETCDF_VARNAME,CFsd,o,c,\"Cloud Frequency (%) Intra-month (2000-2013) Standard Deviation\" ", |
|
145 |
## global |
|
146 |
" -a title,global,o,c,\"Cloud Climatology from MOD09 Cloud Mask\" ", |
|
147 |
" -a institution,global,o,c,\"Jetz Lab, EEB, Yale University, New Haven, CT\" ", |
|
148 |
" -a source,global,o,c,\"Derived from MOD09GA Daily Data\" ", |
|
149 |
" -a comment,global,o,c,\"Developed by Adam M. Wilson (adam.wilson@yale.edu / http://adamwilson.us)\" ", |
|
150 |
ncfile,sep="")) |
|
151 |
|
|
152 |
## add the fillvalue attribute back (without changing the actual values) |
|
153 |
#system(paste("ncatted -a _FillValue,CF,o,b,-32768 ",ncfile,sep="")) |
|
154 |
|
|
155 |
if(as.numeric(system(paste("cdo -s ntime ",ncfile),intern=T))<1) { |
|
156 |
print(paste(ncfile," has no time, deleting")) |
|
157 |
file.remove(ncfile) |
|
158 |
} |
|
159 |
print(paste(basename(ncfile)," Finished")) |
|
160 |
|
|
161 |
|
|
162 |
} |
|
163 |
|
|
164 |
if(ramdisk) { |
|
165 |
## unmount the ram disk |
|
166 |
system(paste("sudo umount ",tmpfs) |
|
167 |
} |
|
168 |
|
|
169 |
|
|
170 |
### merge all the tiles to a single global composite |
|
171 |
#system(paste("ncdump -h ",list.files(tempdir,pattern="mod09.*.nc$",full=T)[10])) |
|
172 |
file.remove("tmp/mod09_2000-01-15.nc") |
|
173 |
system(paste("cdo -O mergetime -setrtomiss,-32768,-1 ",paste(list.files(tempdir,pattern="mod09.*.nc$",full=T),collapse=" ")," data/cloud_monthly.nc")) |
|
174 |
|
|
175 |
# Overall mean |
|
176 |
system(paste("cdo -O timmean data/cloud_monthly.nc data/cloud_mean.nc")) |
|
177 |
|
|
178 |
### generate the monthly mean and sd |
|
179 |
#system(paste("cdo -P 10 -O merge -ymonmean data/mod09.nc -chname,CF,CF_sd -ymonstd data/mod09.nc data/mod09_clim.nc")) |
|
180 |
system(paste("cdo -f nc4c -O -ymonmean data/cloud_monthly.nc data/cloud_ymonmean.nc")) |
|
181 |
|
|
182 |
|
|
183 |
## Seasonal Means |
|
184 |
system(paste("cdo -f nc4c -O -yseasmean data/cloud_monthly.nc data/cloud_yseasmean.nc")) |
|
185 |
system(paste("cdo -f nc4c -O -yseasstd data/cloud_monthly.nc data/cloud_yseasstd.nc")) |
|
186 |
|
|
187 |
## standard deviations, had to break to limit memory usage |
|
188 |
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")) |
|
189 |
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")) |
|
190 |
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")) |
|
191 |
|
|
192 |
system("cdo -f nc4c -z zip timmin data/cloud_ymonmean.nc data/cloud_min.nc") |
|
193 |
system("cdo -f nc4c -z zip timmax data/cloud_ymonmean.nc data/cloud_max.nc") |
|
194 |
|
|
195 |
## standard deviation of mean monthly values give intra-annual variability |
|
196 |
system("cdo -f nc4c -z zip -chname,CF,CFsd -timstd data/cloud_ymonmean.nc data/cloud_std_intra.nc") |
|
197 |
## mean of monthly standard deviations give inter-annual variability |
|
198 |
system("cdo -f nc4c -z zip -chname,CF,CFsd -timmean data/cloud_ymonstd.nc data/cloud_std_inter.nc") |
|
199 |
|
|
200 |
|
|
201 |
# Regressions through time by season |
|
202 |
s=c("DJF","MAM","JJA","SON") |
|
203 |
|
|
204 |
system(paste("cdo -f nc4c -O regres -selseas,",s[1]," data/cloud_monthly.nc data/slope_",s[1],".nc",sep="")) |
|
205 |
system(paste("cdo -f nc4c -O regres -selseas,",s[2]," data/cloud_monthly.nc data/slope_",s[2],".nc",sep="")) |
|
206 |
system(paste("cdo -f nc4c -O regres -selseas,",s[3]," data/cloud_monthly.nc data/slope_",s[3],".nc",sep="")) |
|
207 |
system(paste("cdo -f nc4c -O regres -selseas,",s[4]," data/cloud_monthly.nc data/slope_",s[4],".nc",sep="")) |
|
208 |
|
|
209 |
|
|
210 |
|
|
211 |
## Daily animations |
|
212 |
regs=list( |
|
213 |
Venezuela=extent(c(-69,-59,0,7)), |
|
214 |
Cascades=extent(c(-122.8,-118,44.9,47)), |
|
215 |
Hawaii=extent(c(-156.5,-154,18.75,20.5)), |
|
216 |
Boliva=extent(c(-71,-63,-20,-15)), |
|
217 |
CFR=extent(c(17.75,22.5,-34.8,-32.6)), |
|
218 |
Madagascar=extent(c(46,52,-17,-12)) |
|
219 |
) |
|
220 |
|
|
221 |
r=1 |
|
222 |
|
|
223 |
system(paste("cdo -f nc4c -O inttime,2012-01-15,12:00:00,7day -sellonlatbox,", |
|
224 |
paste(regs[[r]]@xmin,regs[[r]]@xmax,regs[[r]]@ymin,regs[[r]]@ymax,sep=","), |
|
225 |
" data/cloud_monthly.nc data/daily_",names(regs[r]),".nc",sep="")) |
|
226 |
|
|
227 |
|
|
228 |
|
|
229 |
|
|
230 |
### Long term summaries |
|
231 |
seasconc <- function(x,return.Pc=T,return.thetat=F) { |
|
232 |
################################################################################################# |
|
233 |
## Precipitation Concentration function |
|
234 |
## This function calculates Precipitation Concentration based on Markham's (1970) technique as described in Schulze (1997) |
|
235 |
## South Africa Atlas of Agrohydology and Climatology - R E Schulze, M Maharaj, S D Lynch, B J Howe, and B Melvile-Thomson |
|
236 |
## Pages 37-38 |
|
237 |
################################################################################################# |
|
238 |
## x is a vector of precipitation quantities - the mean for each factor in "months" will be taken, |
|
239 |
## so it does not matter if the data are daily or monthly, as long as the "months" factor correctly |
|
240 |
## identifies them into 12 monthly bins, collapse indicates whether the data are already summarized as monthly means. |
|
241 |
################################################################################################# |
|
242 |
theta=seq(30,360,30)*(pi/180) # set up angles for each month & convert to radians |
|
243 |
if(sum(is.na(x))==12) { return(cbind(Pc=NA,thetat=NA)) ; stop} |
|
244 |
if(return.Pc) { |
|
245 |
rt=sqrt(sum(x * cos(theta))^2 + sum(x * sin(theta))^2) # the magnitude of the summation |
|
246 |
Pc=as.integer(round((rt/sum(x))*100))} |
|
247 |
if(return.thetat){ |
|
248 |
s1=sum(x*sin(theta),na.rm=T); s2=sum(x*cos(theta),na.rm=T) |
|
249 |
if(s1>=0 & s2>=0) {thetat=abs((180/pi)*(atan(sum(x*sin(theta),na.rm=T)/sum(x*cos(theta),na.rm=T))))} |
|
250 |
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))))} |
|
251 |
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))))} |
|
252 |
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))))} |
|
253 |
thetat=as.integer(round(thetat)) |
|
254 |
} |
|
255 |
if(return.thetat&return.Pc) return(c(conc=Pc,theta=thetat)) |
|
256 |
if(return.Pc) return(Pc) |
|
257 |
if(return.thetat) return(thetat) |
|
258 |
} |
|
259 |
|
|
260 |
|
|
261 |
|
|
262 |
## read in monthly dataset |
|
263 |
mod09=brick("data/cloud_ymonmean.nc",varname="CF") |
|
264 |
plot(mod09[1]) |
|
265 |
|
|
266 |
mod09_seas=calc(mod09,seasconc,return.Pc=T,return.thetat=F,overwrite=T,filename="data/mod09_seas.nc",NAflag=255,datatype="INT1U") |
|
267 |
mod09_seas2=calc(mod09,seasconc,return.Pc=F,return.thetat=T,overwrite=T,filename="data/mod09_seas_theta.nc",datatype="INT1U") |
|
268 |
|
|
269 |
plot(mod09_seas) |
Also available in: Unified diff
udpated 2_bias to add aqua processing window correction