Revision f1cd9046
Added by Benoit Parmentier over 11 years ago
climate/research/oregon/modis-lst/LST_modis_downloading.py | ||
---|---|---|
1 |
# -*- coding: utf-8 -*- |
|
2 |
""" |
|
3 |
Created on Mon May 13 10:02:02 2013 |
|
4 |
|
|
5 |
@author: parmentier |
|
6 |
""" |
|
7 |
|
|
8 |
#!/usr/bin/python |
|
9 |
# |
|
10 |
# Early version of assorted Python code to download MODIS 11A1 (daily) |
|
11 |
# data associated with specified dates and tiles, then interface with |
|
12 |
# GRASS to calculate temporally averaged LST in a way that accounts for |
|
13 |
# QC flags. |
|
14 |
# |
|
15 |
# TODO: |
|
16 |
# - functionalize to encapsulate high level procedural steps |
|
17 |
# - create a 'main' function to allow script to be run as a command |
|
18 |
# that can accept arguments? |
|
19 |
# - put downloaded data somewhere other than working directory? |
|
20 |
# - record all downloads to a log file? |
|
21 |
# |
|
22 |
# Created by Jim Regetz |
|
23 |
# NCEAS on 16-May-2012 |
|
24 |
# Modified by Benoit Parmentier |
|
25 |
#NCEAS on 18-October-2012 |
|
26 |
#NCEAS on 19-January-2013 |
|
27 |
#NCEAS on 14-May-2013 |
|
28 |
# |
|
29 |
|
|
30 |
import os, glob |
|
31 |
import datetime, calendar |
|
32 |
import ftplib |
|
33 |
#import grass.script as gs |
|
34 |
import argparse |
|
35 |
|
|
36 |
#from datetime import date |
|
37 |
#from datetime import datetime |
|
38 |
|
|
39 |
|
|
40 |
#------------------ |
|
41 |
# helper functions |
|
42 |
#------------------ |
|
43 |
|
|
44 |
def yj_to_ymd(year, doy): |
|
45 |
"""Return date as e.g. '2000.03.05' based on specified year and |
|
46 |
numeric day-of-year (doy) """ |
|
47 |
date = datetime.datetime.strptime('%d%03d' % (year, doy), '%Y%j') |
|
48 |
return date.strftime('%Y.%m.%d') |
|
49 |
|
|
50 |
def get_doy_range(year, month): |
|
51 |
"""Determine starting and ending numeric day-of-year (doy) |
|
52 |
asscociated with the specified month and year. |
|
53 |
|
|
54 |
Arguments: |
|
55 |
year -- four-digit integer year |
|
56 |
month -- integer month (1-12) |
|
57 |
|
|
58 |
Returns tuple of start and end doy for that month/year. |
|
59 |
""" |
|
60 |
last_day_of_month = calendar.monthrange(year, month)[1] |
|
61 |
start_doy = int(datetime.datetime.strptime('%d.%02d.%02d' % (year, |
|
62 |
month, 1), '%Y.%m.%d').strftime('%j')) |
|
63 |
end_doy = int(datetime.datetime.strptime('%d.%02d.%02d' % (year, |
|
64 |
month, last_day_of_month), '%Y.%m.%d').strftime('%j')) |
|
65 |
return (int(start_doy), int(end_doy)) |
|
66 |
|
|
67 |
#added by Benoit, to create a list of raster images for particular month (2001-2010) |
|
68 |
|
|
69 |
def date_sequence(year_start,month_start,day_start,year_end,month_end,day_end): |
|
70 |
"""Create a date sequence for a start date and end date defined by year, month, date |
|
71 |
Arguments: |
|
72 |
year_start -- starting year |
|
73 |
|
|
74 |
Returns list of absolute paths to the downloaded HDF files.Note the format yyyydoy |
|
75 |
""" |
|
76 |
from datetime import date |
|
77 |
from dateutil.rrule import rrule, DAILY |
|
78 |
|
|
79 |
a = date(year_start, month_start,day_start) |
|
80 |
b = date(year_end, month_end, day_end) |
|
81 |
date_seq=list() |
|
82 |
for dt in rrule(DAILY, dtstart=a, until=b): |
|
83 |
print dt.strftime("%Y%j") |
|
84 |
date_seq.append(dt.strftime("%Y%j")) |
|
85 |
|
|
86 |
return(date_seq) |
|
87 |
|
|
88 |
# quick function to return list of dirs in wd |
|
89 |
def list_contents(ftp): |
|
90 |
"""Parse ftp directory listing into list of names of the files |
|
91 |
and/or directories contained therein. May or may not be robust in |
|
92 |
general, but seems to work fine for LP DAAP ftp server.""" |
|
93 |
listing = [] |
|
94 |
ftp.dir(listing.append) |
|
95 |
contents = [item.split()[-1] for item in listing[1:]] |
|
96 |
return contents |
|
97 |
|
|
98 |
def download_mod11a1(destdir, tile, start_doy, end_doy, year, ver=5): |
|
99 |
"""Download into destination directory the MODIS 11A1 HDF files |
|
100 |
matching a given tile, year, and day range. If for some unexpected |
|
101 |
reason there are multiple matches for a given day, only the first is |
|
102 |
used. If no matches, the day is skipped with a warning message. |
|
103 |
|
|
104 |
Arguments: |
|
105 |
destdir -- path to local destination directory |
|
106 |
tile -- tile identifier (e.g., 'h08v04') |
|
107 |
start_doy -- integer start of day range (0-366) |
|
108 |
end_doy -- integer end of day range (0-366) |
|
109 |
year -- integer year (>=2000) |
|
110 |
ver -- MODIS version (4 or 5) |
|
111 |
|
|
112 |
Returns list of absolute paths to the downloaded HDF files. |
|
113 |
""" |
|
114 |
# connect to data pool and change to the right directory |
|
115 |
ftp = ftplib.FTP('e4ftl01.cr.usgs.gov') |
|
116 |
ftp.login('anonymous', '') |
|
117 |
ftp.cwd('MOLT/MOD11A1.%03d' % ver) |
|
118 |
# make list of daily directories to traverse |
|
119 |
available_days = list_contents(ftp) |
|
120 |
desired_days = [yj_to_ymd(year, x) for x in range(start_doy, end_doy+1)] |
|
121 |
days_to_get = filter(lambda day: day in desired_days, available_days) |
|
122 |
if len(days_to_get) < len(desired_days): |
|
123 |
missing_days = [day for day in desired_days if day not in days_to_get] |
|
124 |
print 'skipping %d day(s) not found on server:' % len(missing_days) |
|
125 |
print '\n'.join(missing_days) |
|
126 |
# get each tile in turn |
|
127 |
hdfs = list() |
|
128 |
for day in days_to_get: |
|
129 |
ftp.cwd(day) |
|
130 |
files_to_get = [file for file in list_contents(ftp) |
|
131 |
if tile in file and file[-3:]=='hdf'] |
|
132 |
if len(files_to_get)==0: |
|
133 |
# no file found -- print message and move on |
|
134 |
print 'no hdf found on server for tile', tile, 'on', day |
|
135 |
ftp.cwd('..') #added by Benoit |
|
136 |
continue |
|
137 |
elif 1<len(files_to_get): |
|
138 |
# multiple files found! -- just use the first... |
|
139 |
print 'multiple hdfs found on server for tile', tile, 'on', day |
|
140 |
file = files_to_get[0] |
|
141 |
local_file = os.path.join(destdir, file) |
|
142 |
ftp.retrbinary('RETR %s' % file, open(local_file, 'wb').write) |
|
143 |
hdfs.append(os.path.abspath(local_file)) |
|
144 |
ftp.cwd('..') |
|
145 |
# politely disconnect |
|
146 |
ftp.quit() |
|
147 |
# return list of downloaded paths |
|
148 |
return hdfs |
|
149 |
|
|
150 |
def get_hdf_paths(hdfdir, tile, start_doy, end_doy, year): |
|
151 |
"""Look in supplied directory to find the MODIS 11A1 HDF files |
|
152 |
matching a given tile, year, and day range. If for some unexpected |
|
153 |
reason there are multiple matches for a given day, only the first is |
|
154 |
used. If no matches, the day is skipped with a warning message. |
|
155 |
|
|
156 |
Arguments: |
|
157 |
hdfdir -- path to directory containing the desired HDFs |
|
158 |
tile -- tile identifier (e.g., 'h08v04') |
|
159 |
start_doy -- integer start of day range (0-366) |
|
160 |
end_doy -- integer end of day range (0-366) |
|
161 |
year -- integer year (>=2000) |
|
162 |
|
|
163 |
Returns list of absolute paths to the located HDF files. |
|
164 |
""" |
|
165 |
hdfs = list() |
|
166 |
for doy in range(start_doy, end_doy+1): |
|
167 |
fileglob = 'MOD11A1.A%d%03d.%s*hdf' % (year, doy, tile) |
|
168 |
pathglob = os.path.join(hdfdir, fileglob) |
|
169 |
files = glob.glob(pathglob) |
|
170 |
if len(files)==0: |
|
171 |
# no file found -- print message and move on |
|
172 |
print 'cannot access %s: no such file' % pathglob |
|
173 |
continue |
|
174 |
elif 1<len(files): |
|
175 |
# multiple files found! -- just use the first... |
|
176 |
print 'multiple hdfs found for tile', tile, 'on', day |
|
177 |
hdfs.append(os.path.abspath(files[0])) |
|
178 |
return hdfs |
|
179 |
|
|
180 |
|
|
181 |
def main(): |
|
182 |
#from sys import argv # example client code |
|
183 |
#myargs = getopts(argv) |
|
184 |
|
|
185 |
import argparse |
|
186 |
parser = argparse.ArgumentParser() |
|
187 |
parser.add_argument("tiles", type=str, help="list of Modis tiles") |
|
188 |
parser.add_argument("start_year", type=int, help="start year") |
|
189 |
parser.add_argument("end_year", type=int, help="end year") |
|
190 |
parser.add_argument("start_month", type=int, help="start month") |
|
191 |
parser.add_argument("end_month", type=int, help="end month") |
|
192 |
parser.add_argument("hdfdir", type=str, help="destination/source directory for hdf file") |
|
193 |
parser.add_argument("night", type=int, help="night") |
|
194 |
parser.add_argument("download", type=int, help="out_suffix") |
|
195 |
parser.add_argument("out_suffix", type=str, help="out_suffix") |
|
196 |
|
|
197 |
myargs = parser.parse_args() |
|
198 |
|
|
199 |
tiles = myargs.tiles #These tiles correspond to Venezuela. |
|
200 |
start_year = myargs.start_year |
|
201 |
end_year = myargs.start_year |
|
202 |
end_month = myargs.end_month |
|
203 |
start_month= myargs.start_month |
|
204 |
hdfdir = myargs.hdfdir |
|
205 |
night= myargs.night # if 1 then produce night climatology |
|
206 |
out_suffix= myargs.out_suffix #"_03192013" |
|
207 |
download=myargs.download# if 1 then download files |
|
208 |
|
|
209 |
################## First step: download data ################### |
|
210 |
# Added tile loop |
|
211 |
year_list=range(start_year,end_year+1) #list of year to loop through |
|
212 |
#print 'Number of arguments:', len(myargs), 'arguments.' |
|
213 |
#print 'Argument List:', str(myargs) |
|
214 |
|
|
215 |
tiles =tiles.split(",") #Create a list from string |
|
216 |
print 'this is the result',str(year_list) |
|
217 |
print(myargs) |
|
218 |
print(tiles) |
|
219 |
|
|
220 |
#tiles = ['h11v08','h11v07','h12v07','h12v08','h10v07','h10v08'] #These tiles correspond to Venezuela. |
|
221 |
#start_year = 2001 |
|
222 |
#end_year = 2010 |
|
223 |
#end_month=12 |
|
224 |
#start_month=1 |
|
225 |
#hdfdir = '/home/parmentier/Data/benoit_test' #destination file where hdf files are stored locally after download. |
|
226 |
#night=1 # if 1 then produce night climatology |
|
227 |
#out_suffix="_03192013" |
|
228 |
#download=1 # if 1 then download files |
|
229 |
|
|
230 |
################## First step: download data ################### |
|
231 |
# Added tile loop |
|
232 |
year_list=range(start_year,end_year+1) #list of year to loop through |
|
233 |
#for testing... |
|
234 |
#year_list=[2001,2002] |
|
235 |
#hdfdir = '/home/parmentier/Data/benoit_test2' |
|
236 |
#tiles = ['h10v07','h10v08','h12v07'] |
|
237 |
if download==1: |
|
238 |
for tile in tiles: |
|
239 |
for year in year_list: |
|
240 |
start_doy = 1 |
|
241 |
end_doy = 365 |
|
242 |
if calendar.isleap(year): |
|
243 |
end_doy=366 |
|
244 |
|
|
245 |
hdfs = download_mod11a1(hdfdir, tile, start_doy, end_doy, year) |
|
246 |
|
|
247 |
if __name__ == '__main__': |
|
248 |
main() |
|
249 |
# from sys import argv # example client code |
|
250 |
# myargs = getopts(argv) |
|
251 |
# if '-a' in myargs: |
|
252 |
# print(myargs['-a']) |
|
253 |
# if '-b' in myargs: |
|
254 |
# print(myargs['-b']) |
|
255 |
# print(myargs) |
|
256 |
|
|
257 |
#i = 1 |
|
258 |
#while i < arg_length: |
|
259 |
# arg = argv[i] |
|
260 |
# if arg =='-a': |
|
261 |
# a = argv[i] |
|
262 |
# elif arg =='-b': |
|
263 |
# b = argv[i] |
|
264 |
|
|
265 |
#x = a + b |
|
266 |
|
|
267 |
#print x |
Also available in: Unified diff
splitting LST climatology script - downloading of modis tiles