Project

General

Profile

Download (13.5 KB) Statistics
| Branch: | Revision:
1
###################################################################################
2
###  R code to aquire and process MOD35_L2 cloud data from the MODIS platform
3

    
4

    
5
# Redirect all warnings to stderr()
6
#options(warn = -1)
7
#write("2) write() to stderr", stderr())
8
#write("2) write() to stdout", stdout())
9
#warning("2) warning()")
10

    
11

    
12
## import commandline arguments
13
library(getopt)
14
## load libraries
15
require(reshape)
16
require(geosphere)
17
require(raster)
18
require(rgdal)
19
require(spgrass6)
20

    
21
## get options
22
opta <- getopt(matrix(c(
23
                        'date', 'd', 1, 'character',
24
                        'tile', 't', 1, 'character',
25
                        'verbose','v',1,'logical',
26
                        'help', 'h', 0, 'logical'
27
                        ), ncol=4, byrow=TRUE))
28
if ( !is.null(opta$help) )
29
  {
30
       prg <- commandArgs()[1];
31
          cat(paste("Usage: ", prg,  " --date | -d <file> :: The date to process\n", sep=""));
32
          q(status=1);
33
     }
34

    
35
testing=T
36
platform="pleiades" 
37

    
38
## default date and tile to play with  (will be overwritten below when running in batch)
39
if(testing){
40
  date="20090129"
41
  tile="h11v08"
42
  tile="h17v00"
43
  verbose=T
44
}
45

    
46
## now update using options if given
47
if(!testing){
48
  date=opta$date  
49
  tile=opta$tile 
50
  verbose=opta$verbose  #print out extensive information for debugging?
51
}
52
## get year and doy from date
53
year=format(as.Date(date,"%Y%m%d"),"%Y")
54
doy=format(as.Date(date,"%Y%m%d"),"%j")
55

    
56
if(platform=="pleiades"){
57
  ## location of MOD35 files
58
  datadir=paste("/nobackupp4/datapool/modis/MOD09GA.005/",year,"/",doy,"/",sep="")
59
  ## path to some executables
60
  ncopath="/nasa/sles11/nco/4.0.8/gcc/mpt/bin/"
61
  ## specify working directory
62
  outdir=paste("/nobackupp1/awilso10/mod09/daily/",tile,"/",sep="")  #directory for separate daily files
63
  basedir="/nobackupp1/awilso10/mod09/" #directory to hold files temporarily before transferring to lou
64
  setwd(tempdir())
65
  ## grass database
66
  gisBase="/u/armichae/pr/grass-6.4.2/"
67
  ## path to MOD11A1 file for this tile to align grid/extent
68
  gridfile=list.files("/nobackupp1/awilso10/mod35/MODTILES/",pattern=tile,full=T)[1]
69
  td=raster(gridfile)
70
  projection(td)="+proj=sinu +lon_0=0 +x_0=0 +y_0=0 +a=6371007.181 +b=6371007.181 +units=m +no_defs +datum=WGS84 +ellps=WGS84 "
71
}
72

    
73
### print some status messages
74
if(verbose) print(paste("Processing tile",tile," for date",date))
75

    
76
## load tile information and get bounding box
77
load(file="/nobackupp1/awilso10/mod35/modlandTiles.Rdata")
78
tile_bb=tb[tb$tile==tile,] ## identify tile of interest
79

    
80
#####################################################
81
  
82
## function to convert binary to decimal to assist in identifying correct values
83
## this is helpful when defining QA handling below, but isn't used in processing
84
## b2d=function(x) sum(x * 2^(rev(seq_along(x)) - 1)) #http://tolstoy.newcastle.edu.au/R/e2/help/07/02/10596.html
85
## for example:
86
## b2d(c(T,T))
87

    
88
  ## set Grass to overwrite
89
  Sys.setenv(GRASS_OVERWRITE=1)
90
  Sys.setenv(DEBUG=1)
91
  Sys.setenv(GRASS_GUI="txt")
92

    
93
### Extract various SDSs from a single gridded HDF file and use QA data to throw out 'bad' observations
94
## make temporary working directory
95
  tf=paste(tempdir(),"/grass", Sys.getpid(),"/", sep="")  #temporar
96
  if(!file.exists(tf)) dir.create(tf)
97
  ## create output directory if needed
98
  ## Identify output file
99
  ncfile=paste(outdir,"MOD09cloud_",tile,"_",date,".nc",sep="")  #this is the 'final' daily output file
100
  if(!file.exists(dirname(ncfile))) dir.create(dirname(ncfile),recursive=T)
101
 
102
  ## set up temporary grass instance for this PID
103
  if(verbose) print(paste("Set up temporary grass session in",tf))
104
  initGRASS(gisBase=gisBase,gisDbase=tf,SG=as(td,"SpatialGridDataFrame"),override=T,location="mod09",mapset="PERMANENT",home=tf,pid=Sys.getpid())
105
  system(paste("g.proj -c proj4=\"",projection(td),"\"",sep=""),ignore.stdout=T,ignore.stderr=T)
106

    
107
  ## Define region by importing one MOD11A1 raster.
108
  print("Import one MOD11A1 raster to define grid")
109
  if(platform=="pleiades") {
110
    execGRASS("r.in.gdal",input=td@file@name,output="modisgrid",flags=c("quiet","overwrite","o"))
111
    system("g.region rast=modisgrid save=roi --overwrite",ignore.stdout=F,ignore.stderr=F)
112
  }
113

    
114
if(platform=="litoria"){
115
  execGRASS("r.in.gdal",input=paste("NETCDF:\"/home/adamw/acrobates/adamw/projects/interp/data/modis/mod06/summary/MOD06_",tile,".nc\":CER",sep=""),
116
            output="modisgrid",flags=c("overwrite","o"))
117
  system("g.region rast=modisgrid.1 save=roi --overwrite",ignore.stdout=F,ignore.stderr=F)
118
}
119

    
120
## Identify which files to process
121
tfs=unique(sub("CM_|QA_|SenZen_|SolZen_","",basename(outfiles)))
122
#tfs=list.files(tempdir(),pattern="temp.*hdf")
123
nfs=length(tfs)
124
if(verbose) print(paste(nfs,"swaths available for processing"))
125

    
126
## loop through scenes and process QA flags
127
  for(i in 1:nfs){
128
     bfile=tfs[i]
129
     ## Read in the data from the HDFs
130
     ## Cloud Mask
131
     execGRASS("r.in.gdal",input=paste("CM_",bfile,sep=""),
132
              output=paste("CM1_",i,sep=""),flags=c("overwrite","o")) ; print("")
133
     ## QA      ## extract first bit to keep only "useful" values of cloud mask
134
     execGRASS("r.in.gdal",input=paste("QA_",bfile,sep=""),
135
             output=paste("QA_",i,sep=""),flags=c("overwrite","o")) ; print("")
136
     ## Sensor Zenith      ## extract first bit to keep only "low angle" observations
137
     execGRASS("r.in.gdal",input=paste("SenZen_",bfile,sep=""),
138
             output=paste("SZ_",i,sep=""),flags=c("overwrite","o")) ; print("")
139
   
140
     ## check for interpolation artefacts
141
#     execGRASS("r.stats",input=paste("SZ_",i,sep=""),output=paste("SZ_",i,".txt",sep=""),flags=c("c"))
142
#     execGRASS("r.clump",input=paste("SZ_",i,sep=""),output=paste("SZ_",i,"_clump",sep=""))
143
#     execGRASS("r.stats",input=paste("SZ_",i,"_clump",sep=""),output="-",flags=c("c"))
144

    
145
     ## write out the table of weights for use in the neighborhood analysis to identify bad pixels from swtif
146
     p=75  #must be odd
147
     mat=matrix(rep(0,p*p),nrow=p)
148
     mat[0.5+p/2,]=1
149
     cat(mat,file="weights.txt")
150
     execGRASS("r.neighbors",input=paste("SZ_",i,sep=""),output=paste("SZ_",i,"clump",sep=""),method="range",size=p,weight="weights.txt")  # too slow!
151
     system(paste("r.mapcalc \"SZ_",i,"_clump2=SZ_",i,"clump==0\"",sep=""))
152

    
153
#     p=-50:50
154
#     system(paste("r.mapcalc \"SZ_",i,"_clump=if(min(",paste("SZ_",i,"[0,",p,"]",sep="",collapse=","),")==max(",paste("SZ_",i,"[0,",p,"]",sep="",collapse=","),"),1,0)\"",sep=""))
155
#     system(paste("r.mapcalc \"SZ_",i,"_clump=if(min(",paste("SZ_",i,"[0,",min(p,"]",sep="",collapse=","),")==max(",paste("SZ_",i,"[0,",p,"]",sep="",collapse=","),"),1,0)\"",sep=""))
156
#     vals=do.call(rbind.data.frame,strsplit(execGRASS("r.stats",input=paste("SZ_",i,"_clump",sep=""),output="-",flags=c("c"),intern=T),split=" "))
157
#     colnames(vals)=c("value","count")
158
#     vals$count=as.numeric(as.character(vals$count))
159
#     vals$value=as.numeric(as.character(vals$value))
160
#     vals=na.omit(vals)
161
#     vals$count[vals$value==1&vals$count>10]
162
                                            #
163
     #plot(p~value,data=vals)
164
#     print(sum(vals$p[vals$p>.1]))
165
     
166
     ## Solar Zenith      ## extract first bit to keep only "low angle" observations
167
     execGRASS("r.in.gdal",input=paste("SolZen_",bfile,sep=""),
168
             output=paste("SoZ_",i,sep=""),flags=c("overwrite","o")) ; print("")
169
     ## produce the summaries
170
     system(paste("r.mapcalc <<EOF
171
                CM_fill_",i," =  if(isnull(CM1_",i,"),1,0)
172
                QA_useful_",i," =  if((QA_",i," / 2^0) % 2==1,1,0)
173
                SZ_low_",i," =  if(SZ_",i,"_clump2==0&SZ_",i,"<6000,1,0)
174
                SoZ_low_",i," =  if(SoZ_",i,"<8500,1,0)
175
                CM_dayflag_",i," =  if((CM1_",i," / 2^3) % 2==1,1,0)
176
                CM_cloud_",i," =  if((CM1_",i," / 2^0) % 2==1,(CM1_",i," / 2^1) % 2^2,null())
177
                SZday_",i," = if(SZ_",i,"_clump2==0&CM_dayflag_",i,"==1,SZ_",i,",null())
178
                SZnight_",i," = if(SZ_",i,"_clump2==0&CM_dayflag_",i,"==0,SZ_",i,",null())
179
                CMday_",i," = if(SoZ_low_",i,"==1&SZ_low_",i,"==1&QA_useful_",i,"==1&CM_dayflag_",i,"==1,CM_cloud_",i,",null())
180
                CMnight_",i," = if(SZ_low_",i,"==1&QA_useful_",i,"==1&CM_dayflag_",i,"==0,CM_cloud_",i,",null())
181
EOF",sep=""))
182

    
183
#     CM_dayflag_",i," =  if((CM1_",i," / 2^3) % 2==1,1,0)
184
#     CM_dscore_",i," =  if((CM_dayflag_",i,"==0|isnull(CM1_",i,")),0,if(QA_useful_",i,"==0,1,if(SZ_",i,">=6000,2,if(SoZ_",i,">=8500,3,4))))
185
#     CM_nscore_",i," =  if((CM_dayflag_",i,"==1|isnull(CM1_",i,")),0,if(QA_useful_",i,"==0,1,if(SZ_",i,">=6000,2,4)))
186

    
187
     drawplot=F
188
     if(drawplot){
189
       d2=stack(
190
#         raster(readRAST6(paste("QA_useful_",i,sep=""))),
191
         raster(readRAST6(paste("CM1_",i,sep=""))),
192
#         raster(readRAST6(paste("CM_cloud_",i,sep=""))),
193
#         raster(readRAST6(paste("CM_dayflag_",i,sep=""))),
194
#         raster(readRAST6(paste("CMday_",i,sep=""))),
195
#         raster(readRAST6(paste("CMnight_",i,sep=""))),
196
#         raster(readRAST6(paste("CM_fill_",i,sep=""))),
197
#         raster(readRAST6(paste("SoZ_",i,sep=""))),
198
         raster(readRAST6(paste("SZ_",i,sep=""))),
199
         raster(readRAST6(paste("SZ_",i,"_clump",sep=""))),
200
         raster(readRAST6(paste("SZ_",i,"_clump2",sep="")))
201
         )
202
       plot(d2,add=F)
203
     }
204
       
205
     
206
 } #end loop through sub daily files
207

    
208
## select lowest view angle
209
## use r.series to find minimum
210
system(paste("r.series input=",paste("SZnight_",1:nfs,sep="",collapse=",")," output=SZnight_min method=min_raster",sep=""))
211
system(paste("r.series input=",paste("SZday_",1:nfs,sep="",collapse=",")," output=SZday_min method=min_raster",sep=""))
212

    
213
## select cloud observation with lowest sensor zenith for day and night
214
system(
215
paste("r.mapcalc <<EOF
216
              CMday_daily=",paste(paste("if((SZday_min+1)==",1:nfs,",CMday_",1:nfs,",",sep="",collapse=" "),"null()",paste(rep(")",times=nfs),sep="",collapse="")),"
217
              CMnight_daily=",paste(paste("if((SZnight_min+1)==",1:nfs,",CMnight_",1:nfs,",",sep="",collapse=" "),"null()",paste(rep(")",times=nfs),sep="",collapse=""))
218
))
219

    
220
if(plot){
221
  ps=1:nfs
222
  ps=c(12,14,17)
223
  sz1=brick(lapply(ps,function(i) raster(readRAST6(paste("SZnight_",i,sep="")))))
224
  sz_clump=brick(lapply(ps,function(i) raster(readRAST6(paste("SZ_",i,"_clump2",sep="")))))
225
  d=brick(lapply(ps,function(i) raster(readRAST6(paste("CMnight_",i,sep="")))))
226
  d2=brick(list(raster(readRAST6("SZday_min")),raster(readRAST6("SZnight_min")),raster(readRAST6("CMday_daily")),raster(readRAST6("CMnight_daily"))))
227
  library(rasterVis)
228
  levelplot(sz1,col.regions=rainbow(100),at=seq(min(sz1@data@min),max(sz1@data@max),len=100))
229
  levelplot(sz_clump)
230
  levelplot(d)
231
  levelplot(d2)
232
}
233

    
234

    
235
  ### Write the files to a netcdf file
236
  ## create image group to facilitate export as multiband netcdf
237
    execGRASS("i.group",group="mod35",input=c("CMday_daily","CMnight_daily")) ; print("")
238

    
239
if(file.exists(ncfile)) file.remove(ncfile)  #if it exists already, delete it
240
  execGRASS("r.out.gdal",input="mod35",output=ncfile,type="Byte",nodata=255,flags=c("quiet"),
241
#      createopt=c("FORMAT=NC4","ZLEVEL=5","COMPRESS=DEFLATE","WRITE_GDAL_TAGS=YES","WRITE_LONLAT=NO"),format="netCDF")  #for compressed netcdf
242
      createopt=c("FORMAT=NC","WRITE_GDAL_TAGS=YES","WRITE_LONLAT=NO"),format="netCDF")
243

    
244
  system(paste(ncopath,"ncecat -O -u time ",ncfile," ",ncfile,sep=""))
245
## create temporary nc file with time information to append to MOD06 data
246
  cat(paste("
247
    netcdf time {
248
      dimensions:
249
        time = 1 ;
250
      variables:
251
        int time(time) ;
252
      time:units = \"days since 2000-01-01 00:00:00\" ;
253
      time:calendar = \"gregorian\";
254
      time:long_name = \"time of observation\"; 
255
    data:
256
      time=",as.integer(as.Date(date,"%Y%m%d")-as.Date("2000-01-01")),";
257
    }"),file=paste(tempdir(),"/time.cdl",sep=""))
258
system(paste("ncgen -o ",tempdir(),"/time.nc ",tempdir(),"/time.cdl",sep=""))
259
system(paste(ncopath,"ncks -A ",tempdir(),"/time.nc ",ncfile,sep=""))
260
## add other attributes
261
  system(paste(ncopath,"ncrename -v Band1,CMday -v Band2,CMnight ",ncfile,sep=""))
262
  system(paste(ncopath,"ncatted ",
263
" -a units,CMday,o,c,\"Cloud Flag (0-3)\" ",
264
" -a missing_value,CMday,o,b,255 ",
265
" -a _FillValue,CMday,o,b,255 ",
266
" -a valid_range,CMday,o,b,\"0,3\" ",
267
" -a long_name,CMday,o,c,\"Cloud Flag from day pixels\" ",
268
" -a units,CMnight,o,c,\"Cloud Flag (0-3)\" ",
269
" -a missing_value,CMnight,o,b,255 ",
270
" -a _FillValue,CMnight,o,b,255 ",
271
" -a valid_range,CMnight,o,b,\"0,3\" ",
272
" -a long_name,CMnight,o,c,\"Cloud Flag from night pixels\" ",
273
ncfile,sep=""))
274
#system(paste(ncopath,"ncatted -a sourcecode,global,o,c,",script," ",ncfile,sep=""))
275
   
276

    
277
## Confirm that the file has the correct attributes, otherwise delete it
278
ntime=as.numeric(system(paste("cdo -s ntime ",ncfile),intern=T))
279
## confirm it has all 'final variables as specified above"
280
fvar=all(finalvars%in%strsplit(system(paste("cdo -s showvar ",ncfile),intern=T)," ")[[1]])
281

    
282
  if(ntime!=1|!fvar) {
283
      print(paste("FILE ERROR:  tile ",tile," and date ",date," was not outputted correctly, deleting... "))
284
      file.remove(ncfile)
285
    }
286
############  copy files to lou
287
#if(platform=="pleiades"){
288
#  archivedir=paste("MOD35/",outdir,"/",sep="")  #directory to create on lou
289
#  system(paste("ssh -q bridge2 \"ssh -q lou mkdir -p ",archivedir,"\"",sep=""))
290
#  system(paste("ssh -q bridge2 \"scp -q ",ncfile," lou:",archivedir,"\"",sep=""))
291
#  file.remove(ncfile)
292
#  file.remove(paste(ncfile,".aux.xml",sep=""))
293
#}
294

    
295
  
296
### delete the temporary files 
297
#  unlink_.gislock()
298
#  system(paste("rm -frR ",tempdir(),sep=""))
299

    
300

    
301
  ## print out some info
302
print(paste("#######################               Finished ",tile,"-",date, "###################################"))
303

    
304
## delete old files
305
#system("cleartemp")
306

    
307
## quit
308
q("no",status=0)
(23-23/52)