Project

General

Profile

« Previous | Next » 

Revision 9b802e31

Added by Alberto Guzman about 11 years ago

Adding modis_LST_mean.py. Python alternative to grass version. Outputs geotif or flt.

View differences:

climate/research/oregon/modis-lst/modis_LST_mean.py
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()

Also available in: Unified diff