1
|
#Calculates monthly mean for date range. Uses MOD11A1 tiles in specified directory
|
2
|
#Assumes MOD11A1.005/2000.03.05/MOD11A1.A2000065.h08v04.005.2007176143143.hdf directory structure
|
3
|
#Non optimized version. Could use Cython to compile C++ fuctions to make it faster.
|
4
|
#Can do single tile or read list from file.
|
5
|
#---------------------------------------------------------------------------
|
6
|
# Developed by Alberto Guzman
|
7
|
# 09/15/2013
|
8
|
|
9
|
import sys, numpy
|
10
|
import netCDF4, datetime,os
|
11
|
import glob
|
12
|
from optparse import OptionParser
|
13
|
from pyhdf.SD import SD
|
14
|
import gdal
|
15
|
|
16
|
def main():
|
17
|
usage = "usage: %prog [options] <indDir> <outDir> \n"+\
|
18
|
"Calculates monthly mean for MOD11A1 tiles in specified directory"
|
19
|
parser = OptionParser(usage=usage)
|
20
|
parser.add_option("-s","--yStart",dest="yStart",default=2000,
|
21
|
help="Start year to process")
|
22
|
parser.add_option("-e","--yEnd",dest="yEnd",default=2010,
|
23
|
help="End year to process")
|
24
|
parser.add_option("-m","--months",dest="months",default='1,2,3,4,5,6,7,8,9,10,11,12',
|
25
|
help="Comma separated list of months to process (1,2,3...12),default all")
|
26
|
parser.add_option("-f","--outputFormat",dest="outF",default="flt",
|
27
|
help="Format of output, currently flt(no projection info) and geotif supported")
|
28
|
parser.add_option("-d","--daynight",dest="dn",default="0",
|
29
|
help="Use 0 for both(default),1 for day only,2 for night only")
|
30
|
parser.add_option("-t","--tile",dest="tile",default="h08v04",
|
31
|
help="Which modis tile to process by default uses h08v04")
|
32
|
parser.add_option("-l","--tileList",dest="tiles",default=None,
|
33
|
help="Get tiles list from file(one per line), overwrites option 't'")
|
34
|
opts,args=parser.parse_args()
|
35
|
if len(args)<2:
|
36
|
sys.exit(parser.print_help())
|
37
|
|
38
|
inDir = args[0]
|
39
|
outDir = args[1]
|
40
|
|
41
|
yStart = int(opts.yStart)
|
42
|
yEnd = int(opts.yEnd)
|
43
|
months = opts.months.split(',')
|
44
|
outFormat = opts.outF
|
45
|
if (outFormat != "flt") & (outFormat != "tif"):
|
46
|
print "Error: Only flt or tif output formats supported"
|
47
|
sys.exit(1)
|
48
|
|
49
|
if int(opts.dn) == 0:
|
50
|
dayNight = ["Day","Night"]
|
51
|
elif int(opts.dn) == 1:
|
52
|
dayNight = ["Day"]
|
53
|
elif int(opts.dn) == 2:
|
54
|
dayNight = ["Night"]
|
55
|
else:
|
56
|
print "Error: Only 0(both),1(day),2(night) options supported"
|
57
|
sys.exit(1)
|
58
|
|
59
|
#Check if in and out directory exist, create out if it doesn't
|
60
|
if os.path.exists(inDir) is False:
|
61
|
print "Error: %s directory doesn't exists" % inDir
|
62
|
sys.exit(1)
|
63
|
if os.path.exists(outDir) is False:
|
64
|
print "Warning: %s directory doesn't exists, creating directory" % outDir
|
65
|
|
66
|
if opts.tiles is not None:
|
67
|
if os.path.exists(opts.tiles) is False:
|
68
|
print "Error: file %s doesn't exists" % opts.tiles
|
69
|
sys.exit(1)
|
70
|
else:
|
71
|
fPtr = open(opts.tiles)
|
72
|
if fPtr is None:
|
73
|
print "Error: Opening file %s" % opts.tiles
|
74
|
sys.exit(1)
|
75
|
else:
|
76
|
tiles = []
|
77
|
for t in fPtr.readlines():
|
78
|
tiles.append(t.rstrip())
|
79
|
fPtr.close()
|
80
|
else:
|
81
|
tiles = [opts.tile]
|
82
|
|
83
|
#TEST
|
84
|
#tile = 'h08v04'
|
85
|
#dayNight = 'day'
|
86
|
|
87
|
print tiles
|
88
|
for tile in tiles:
|
89
|
#One log file per tile, it only logs errors messages
|
90
|
logFn = outDir+'/outlog_'+tile+'.log'
|
91
|
logPtr = open(logFn,"w+")
|
92
|
if logPtr is None:
|
93
|
print "Error: couldn't create log file %s" % logFn
|
94
|
print "Continuing without log" #should we just exit?
|
95
|
|
96
|
#Use a tile to create out tif if option selected
|
97
|
tmpFn = ''
|
98
|
|
99
|
print "Processing months %s and years %d-%d for tile %s" % (opts.months,yStart,yEnd,tile)
|
100
|
for dN in dayNight:
|
101
|
for m in months:
|
102
|
#Temp monthly arrays
|
103
|
meanTotal = numpy.zeros((1200,1200),dtype=numpy.float32)
|
104
|
nobsTotal = numpy.zeros((1200,1200),dtype=numpy.int32)
|
105
|
|
106
|
mSrc = '%0*d' % (2,int(m)) #setting to two digit format for months < 10
|
107
|
for y in range(yStart,yEnd+1):
|
108
|
#Get list of files assumes MOD11A1.005/2000.03.05/MOD11A1.A2000065.h08v04.005.2007176143143.hdf format
|
109
|
inFilesSrch = "%s/%d.%s.*/MOD11A1.*.%s.*.hdf" % (inDir,y,mSrc,tile)
|
110
|
inFiles = glob.glob(inFilesSrch)
|
111
|
|
112
|
if len(inFiles) < 1:
|
113
|
print "No files found"
|
114
|
else:
|
115
|
print "Found %d files" % len(inFiles)
|
116
|
for f in inFiles:
|
117
|
print "Processing %s %s" % (f,dN)
|
118
|
try:
|
119
|
ds = SD(f)
|
120
|
dayTemp = ds.select('LST_'+dN+'_1km').get()
|
121
|
dayTemp = numpy.where(dayTemp > 0,(dayTemp * 0.02) - 273.15,0) # K to C degrees
|
122
|
|
123
|
#We want highest quality so check last two bits for [00]
|
124
|
qa = ds.select('QC_'+dN).get() & 0b00000011
|
125
|
meanTotal = numpy.where((qa == 0) & (dayTemp > 0),meanTotal+dayTemp,meanTotal)
|
126
|
nobsTotal = numpy.where((qa == 0) & (dayTemp > 0),nobsTotal+1,nobsTotal)
|
127
|
ds.end()
|
128
|
|
129
|
meanTotal = numpy.where((nobsTotal != 0) & (meanTotal != 0),meanTotal/nobsTotal,0)
|
130
|
meanTotal = numpy.nan_to_num(meanTotal)
|
131
|
tmpFn = f
|
132
|
if logPtr is not None:
|
133
|
logPtr.write("Processed: "+f+"\n")
|
134
|
except Exception:
|
135
|
print "Error reading or accessing file, adding to log"
|
136
|
if logPtr is not None:
|
137
|
logPtr.write("Error: "+f+"\n")
|
138
|
pass
|
139
|
|
140
|
if outFormat == "flt":
|
141
|
#Save to file, outputs to same grid as original tile
|
142
|
outFn = "%s/mean_LST_%s_1km_%s_%s.flt32" % (outDir,tile,m,dN)
|
143
|
meanTotal.tofile(outFn)
|
144
|
outFn = "%s/nobs_LST_%s_1km_%s_%s.int32" % (outDir,tile,m,dN)
|
145
|
nobsTotal.tofile(outFn)
|
146
|
elif outFormat == "tif":
|
147
|
outFn = "%s/mean_LST_%s_1km_%s_%s.tif" % (outDir,tile,m,dN)
|
148
|
print "Outputing to", outFn
|
149
|
out2Tif(meanTotal,outFn,tmpFn)
|
150
|
outFn = "%s/nobs_LST_%s_1km_%s_%s.tif" % (outDir,tile,m,dN)
|
151
|
out2Tif(nobsTotal,outFn,tmpFn,1,gdal.GDT_UInt32)
|
152
|
logPtr.close()
|
153
|
sys.exit(0)
|
154
|
|
155
|
def out2Tif(outData,outFn,inFn,bands=1,format=gdal.GDT_Float32):
|
156
|
dims = 1200
|
157
|
inDsFn = "HDF4_EOS:EOS_GRID:%s:MODIS_Grid_Daily_1km_LST:LST_Day_1km" % inFn
|
158
|
inDs = gdal.Open(inDsFn,gdal.GA_ReadOnly)
|
159
|
if inDs is None:
|
160
|
print "Error opening %s " % inDsFn
|
161
|
return None
|
162
|
|
163
|
driver = gdal.GetDriverByName("GTiff")
|
164
|
metadata = driver.GetMetadata()
|
165
|
if metadata.has_key(gdal.DCAP_CREATE) and metadata[gdal.DCAP_CREATE] == 'YES':
|
166
|
d = 1
|
167
|
#print 'Driver GTiff supports Create() method.'
|
168
|
else:
|
169
|
print 'Driver GTIFF does not support Create()'
|
170
|
return None
|
171
|
|
172
|
geoTrans = inDs.GetGeoTransform()
|
173
|
geoProj = inDs.GetProjection()
|
174
|
|
175
|
outDs = driver.Create(outFn,dims,dims,bands,format)
|
176
|
|
177
|
if outDs is None:
|
178
|
print "Error creating output file %s" % outFn
|
179
|
sys.exit(1)
|
180
|
outDs.SetGeoTransform(geoTrans)
|
181
|
outDs.SetProjection(geoProj)
|
182
|
|
183
|
b1 = outDs.GetRasterBand(1)
|
184
|
b1.WriteArray(outData)
|
185
|
|
186
|
inDs = None
|
187
|
outDs = None
|
188
|
|
189
|
return None
|
190
|
|
191
|
if __name__ == '__main__':
|
192
|
main()
|