12 | | #!/usr/bin/env python |
13 | | |
14 | | """ |
15 | | SYNOPSIS |
16 | | |
17 | | mk_AVAILABLE.py: [-s,--startdate] [-e,--enddate] [-m,--model /ECWMF/ERAI/EI/E5/EA/GFS] [-p, --path] [-a, --avpath] [-i, --interval] [-h] [-v,--verbose] [--version] |
18 | | |
19 | | DESCRIPTION |
20 | | |
21 | | mk_AVAIL is a script to create AVAILABLE files for FLEXPART windfields. |
22 | | |
23 | | Example usage: |
24 | | %mk_AVAIL.py -s 200601 -e 200701 -m ECMWF -p . -h |
25 | | |
26 | | would create a file: AVAIALABLE that contained paths |
27 | | of all files available in the current directory between 200601 and 200701. |
28 | | The default start date is 197001 and the default end date is TODAY. |
29 | | |
30 | | adapted and simplified version / Petra Seibert |
31 | | v.004: add ERA-Interim with EI as model, proper sorting of dates if year 2000 included, option to define a path for AVAILABLE / Petra Seibert 2015-10-21 |
32 | | v.005: check whether any files are found before opening AVAILABLE, if not issue warning and stop. / Petra Seibert 2015-12-07 |
33 | | v.006 PS 2018-04-24: add ERA5 as model option |
34 | | |
35 | | QUESTIONS to |
36 | | |
37 | | JFB: <jfb@nilu.no> |
38 | | version>=003: petra.seibert at boku.ac.at |
39 | | |
40 | | LICENSE |
41 | | |
42 | | This script follows creative commons usage. |
43 | | Valid-License-Identifier: CC-BY-4.0 |
44 | | |
45 | | VERSION |
46 | | |
47 | | $Id: 0.006 $ |
48 | | |
49 | | """ |
50 | | |
51 | | import sys |
52 | | import os |
53 | | import traceback |
54 | | import optparse |
55 | | import time |
56 | | import datetime |
57 | | import socket |
58 | | import glob |
59 | | import string |
60 | | |
61 | | |
62 | | def main (): |
63 | | |
64 | | global options, args, models |
65 | | version = '$Id: 0.006 $' |
66 | | |
67 | | WIND_dir = '/xnilu_wrk/flex_wrk/WIND_FIELDS' |
68 | | |
69 | | # dict of dicts with model information |
70 | | # timeindex: index in the filne name string where the time information starts |
71 | | print MODEL.keys() |
72 | | |
73 | | AVAIL_head = """DATE TIME FILENAME SPECIFICATIONS\ |
74 | | \nYYYYMMDD HHMISS\ |
75 | | \n________ ______ __________________ __________________\n""" |
76 | | start_date = options.startdate |
77 | | sy = int(start_date[0:4]) |
78 | | sm = int(start_date[4:6]) |
79 | | end_date = options.enddate |
80 | | ey = int(end_date[0:4]) |
81 | | em = int(end_date[4:6]) |
82 | | |
83 | | #Get the directory information |
84 | | M = MODEL[options.model] |
85 | | prfx = M['prefix'] |
86 | | t = options.path |
87 | | avpath = options.avpath |
88 | | |
89 | | |
90 | | #Loop through the files in the directories |
91 | | |
92 | | warned = False |
93 | | d = t #directory |
94 | | |
95 | | tind = M['timeindex'] #timestamp index |
96 | | searchstr = os.path.join(t,prfx) |
97 | | print 'searchstring:',searchstr |
98 | | files = glob.glob(searchstr + '*') |
99 | | if options.verbose: print len(files), ' wind-field files found' |
100 | | dict_dates={} |
101 | | for f in files: |
102 | | if (f[0:2] == './'): f = f[2:] # PS - remove this part if present |
103 | | fn = os.path.basename(f) |
104 | | if fn[-1] != '*': |
105 | | timestamp = fn[tind:] |
106 | | year = int(timestamp[0:2]) |
107 | | if year < 58: |
108 | | year += 2000 |
109 | | else: |
110 | | year += 1900 |
111 | | dtstring = str(year)+' '+timestamp[2:9] |
112 | | dict_dates[dtstring] = f |
113 | | dates = sorted(dict_dates.items()) |
114 | | if len(dates) == 0: |
115 | | print 'no files found with this search string' |
116 | | print 'aborting. ' |
117 | | sys.exit(0) |
118 | | else: |
119 | | print 'found ',len(dates),'files' |
120 | | #Prepare output files |
121 | | fout = file(os.path.join(avpath,'AVAILABLE'),'w') |
122 | | fout.write(AVAIL_head) |
123 | | |
124 | | for i,date in enumerate(dates): # go through dates in ascending order |
125 | | f = date[1] # now we have the filename+path |
126 | | fn = os.path.basename(f) |
127 | | if fn[-1]!='*': |
128 | | timestamp = fn[tind:] |
129 | | year = int(timestamp[0:2]) |
130 | | if year < 58: |
131 | | year += 2000 |
132 | | else: |
133 | | year += 1900 |
134 | | month = int(timestamp[2:4]) |
135 | | day = int(timestamp[4:6]) |
136 | | hour = int(timestamp[6:8]) |
137 | | fileT = year*100 + int(month) |
138 | | # PS: now check for irregular intervals |
139 | | date = datetime.datetime(year,month,day,hour) |
140 | | if i == 2: |
141 | | if options.timeint == '': |
142 | | timeint = date - date1 |
143 | | else: |
144 | | timeint = datetime.timedelta(0,3600*int(options.timeint)) |
145 | | if timeint != date - date1: |
146 | | print 'WARNING - irregular interval',date - date1 |
147 | | print date1,f1,'\n',date, f,'\n' |
148 | | elif i > 2: |
149 | | if timeint != date - date1: |
150 | | print 'WARNING - irregular interval',date - date1 |
151 | | print date1,f1,'\n',date, f,'\n' |
152 | | if options.timeint == '': timeint = date - date1 |
153 | | date1 = date |
154 | | f1 = f |
155 | | |
156 | | if i%5000 == 0: print 'progress:', i, 'of', len(dates), f |
157 | | |
158 | | if fileT >= sy*100 + sm and fileT <= ey*100 + em : |
159 | | |
160 | | relpath = os.path.relpath( os.path.dirname(f), avpath ) |
161 | | f = os.path.join(relpath,fn) |
162 | | |
163 | | if (f[0:2] == './'): f = f[2:] # remove this part if present |
164 | | |
165 | | if len(f) > 18: #PS |
166 | | if not warned: |
167 | | print 'WARNING: Flexpart can only read 18 chars in WF-name' |
168 | | print f, ' has ', len(f), ' characters!\n' |
169 | | warned = True |
170 | | |
171 | | #This is the fortran format: (i8,1x,i6,2(6x,a18)) |
172 | | string = "%s%s%s %s0000 %s ON DISC\n" %\ |
173 | | (year,str(month).zfill(2),str(day).zfill(2),str(hour).zfill(2),f.ljust(18)) |
174 | | fout.write(string) |
175 | | |
176 | | print 'Done: ',i+1 # as i starts with 0 |
177 | | print 'Written:', os.path.join(avpath,'AVAILABLE') |
178 | | fout.close() |
179 | | |
180 | | if __name__ == '__main__': |
181 | | MODEL = {} |
182 | | MODEL['ECMWF'] = {'prefix':'EN', 'timeindex':2} |
183 | | MODEL['ERAI'] = {'prefix':'EI', 'timeindex':2} |
184 | | MODEL['EI'] = {'prefix':'EI', 'timeindex':2} |
185 | | MODEL['E5'] = {'prefix':'E5', 'timeindex':2} |
186 | | MODEL['EA'] = {'prefix':'EA', 'timeindex':2} |
187 | | MODEL['GFS'] = {'prefix':'GF', 'timeindex':2} |
188 | | |
189 | | models = '/'.join(MODEL.keys()) |
190 | | |
191 | | try: |
192 | | start_time = time.time() |
193 | | today = datetime.datetime.now() |
194 | | |
195 | | parser = optparse.OptionParser( |
196 | | formatter = optparse.TitledHelpFormatter(), |
197 | | usage = globals()['__doc__']) |
198 | | |
199 | | parser.add_option ('-v', '--verbose', action = 'store_true', |
200 | | default = False, help = 'verbose output') |
201 | | |
202 | | parser.add_option ('-s', '--startdate', |
203 | | dest = 'startdate', |
204 | | default = '197001', |
205 | | help = 'startdate YYYYMM integer') |
206 | | |
207 | | parser.add_option ('-e', '--enddate', |
208 | | # setting default as TODAY |
209 | | dest = 'enddate', |
210 | | default = str(today.year) + str(today.month).zfill(2), |
211 | | #default = '200712', |
212 | | help = 'enddate YYYYMM integer') |
213 | | |
214 | | parser.add_option ('-m', '--model', |
215 | | dest = 'model', |
216 | | default = 'ECMWF', help = models) |
217 | | |
218 | | parser.add_option ('-p', '--path', |
219 | | dest = 'path', |
220 | | default = '.', help = 'path to be searched for windfields. Escape or quote * and ? ') |
221 | | |
222 | | parser.add_option ('-a', '--avpath', |
223 | | dest = 'avpath', |
224 | | default = '.', help = 'path for AVAILABLE file ') |
225 | | |
226 | | parser.add_option ('-i', '--interval', |
227 | | dest = 'timeint', |
228 | | default = '', help = 'expected time interval in h. If omitted, show every change') |
229 | | |
230 | | (options, args) = parser.parse_args() |
231 | | |
232 | | #QUERY['modelType'] = options.model |
233 | | #QUERY['start_date'] = options.startdate |
234 | | #QUERY['end_date'] = options.enddate |
235 | | |
236 | | #if len(args) < 1: |
237 | | # parser.error ('missing argument') |
238 | | |
239 | | if options.verbose: print time.asctime() |
240 | | exit_code = main() |
241 | | if exit_code is None: |
242 | | exit_code = 0 |
243 | | if options.verbose: print time.asctime() |
244 | | if options.verbose: print 'TOTAL TIME IN MINUTES:', |
245 | | if options.verbose: print (time.time() - start_time) / 60.0 |
246 | | sys.exit(exit_code) |
247 | | except KeyboardInterrupt, e: # Ctrl-C |
248 | | raise e |
249 | | except SystemExit, e: # sys.exit() |
250 | | raise e |
251 | | except Exception, e: |
252 | | print 'ERROR, UNEXPECTED EXCEPTION' |
253 | | print str(e) |
254 | | traceback.print_exc() |
255 | | os._exit(1) |
256 | | |
257 | | |
258 | | |
259 | | # vim:set sr et ts=4 sw=4 ft=python fenc=utf-8: // See Vim, :help 'modeline' |
| 12 | 2 |
| 13 | 3 """ |
| 14 | 4 SYNOPSIS |
| 15 | 5 |
| 16 | 6 mk_AVAILABLE.py: [-s,--startdate] [-e,--enddate] [-m,--model /ECWMF/ERAI/EI/E5/EA/GFS] [-p, --path] [-a, --avpath] [-i, --interval] [-h] [-v,--verbose] [--version] |
| 17 | 7 |
| 18 | 8 DESCRIPTION |
| 19 | 9 |
| 20 | 10 mk_AVAIL is a script to create AVAILABLE files for FLEXPART windfields. |
| 21 | 11 |
| 22 | 12 Example usage: |
| 23 | 13 %mk_AVAIL.py -s 200601 -e 200701 -m ECMWF -p . -h |
| 24 | 14 |
| 25 | 15 would create a file: AVAIALABLE that contained paths |
| 26 | 16 of all files available in the current directory between 200601 and 200701. |
| 27 | 17 The default start date is 197001 and the default end date is TODAY. |
| 28 | 18 |
| 29 | 19 adapted and simplified version / Petra Seibert |
| 30 | 20 v.004: add ERA-Interim with EI as model, proper sorting of dates if year 2000 included, option to define a path for AVAILABLE / Petra Seibert 2015-10-21 |
| 31 | 21 v.005: check whether any files are found before opening AVAILABLE, if not issue warning and stop. / Petra Seibert 2015-12-07 |
| 32 | 22 v.006 PS 2018-04-24: add ERA5 as model option |
| 33 | 23 v.007 PS 2018-06-25: correct bug introduced in v006: 2 spaces missing in output format |
| 34 | 24 |
| 35 | 25 QUESTIONS to |
| 36 | 26 |
| 37 | 27 JFB: <jfb@nilu.no> |
| 38 | 28 version>=003: petra.seibert at boku.ac.at |
| 39 | 29 |
| 40 | 30 LICENSE |
| 41 | 31 |
| 42 | 32 This script follows creative commons usage. |
| 43 | 33 Valid-License-Identifier: CC-BY-4.0 |
| 44 | 34 |
| 45 | 35 VERSION |
| 46 | 36 |
| 47 | 37 $Id: 0.006 $ |
| 48 | 38 |
| 49 | 39 """ |
| 50 | 40 |
| 51 | 41 import sys |
| 52 | 42 import os |
| 53 | 43 import traceback |
| 54 | 44 import optparse |
| 55 | 45 import time |
| 56 | 46 import datetime |
| 57 | 47 import socket |
| 58 | 48 import glob |
| 59 | 49 import string |
| 60 | 50 |
| 61 | 51 |
| 62 | 52 def main (): |
| 63 | 53 |
| 64 | 54 global options, args, models |
| 65 | 55 version = '$Id: 0.006 $' |
| 66 | 56 |
| 67 | 57 WIND_dir = '/xnilu_wrk/flex_wrk/WIND_FIELDS' |
| 68 | 58 |
| 69 | 59 # dict of dicts with model information |
| 70 | 60 # timeindex: index in the filne name string where the time information starts |
| 71 | 61 print MODEL.keys() |
| 72 | 62 |
| 73 | 63 AVAIL_head = \ |
| 74 | 64 """DATE TIME FILENAME SPECIFICATIONS\ |
| 75 | 65 \nYYYYMMDD HHMISS\ |
| 76 | 66 \n________ ______ __________________ __________________\n""" |
| 77 | 67 start_date = options.startdate |
| 78 | 68 sy = int(start_date[0:4]) |
| 79 | 69 sm = int(start_date[4:6]) |
| 80 | 70 end_date = options.enddate |
| 81 | 71 ey = int(end_date[0:4]) |
| 82 | 72 em = int(end_date[4:6]) |
| 83 | 73 |
| 84 | 74 #Get the directory information |
| 85 | 75 M = MODEL[options.model] |
| 86 | 76 prfx = M['prefix'] |
| 87 | 77 t = options.path |
| 88 | 78 avpath = options.avpath |
| 89 | 79 |
| 90 | 80 |
| 91 | 81 #Loop through the files in the directories |
| 92 | 82 |
| 93 | 83 warned = False |
| 94 | 84 d = t #directory |
| 95 | 85 |
| 96 | 86 tind = M['timeindex'] #timestamp index |
| 97 | 87 searchstr = os.path.join(t,prfx) |
| 98 | 88 print 'searchstring:',searchstr |
| 99 | 89 files = glob.glob(searchstr + '*') |
| 100 | 90 if options.verbose: print len(files), ' wind-field files found' |
| 101 | 91 dict_dates={} |
| 102 | 92 for f in files: |
| 103 | 93 if (f[0:2] == './'): f = f[2:] # PS - remove this part if present |
| 104 | 94 fn = os.path.basename(f) |
| 105 | 95 if fn[-1] != '*': |
| 106 | 96 timestamp = fn[tind:] |
| 107 | 97 year = int(timestamp[0:2]) |
| 108 | 98 if year < 58: |
| 109 | 99 year += 2000 |
| 110 | 100 else: |
| 111 | 101 year += 1900 |
| 112 | 102 dtstring = str(year)+' '+timestamp[2:9] |
| 113 | 103 dict_dates[dtstring] = f |
| 114 | 104 dates = sorted(dict_dates.items()) |
| 115 | 105 if len(dates) == 0: |
| 116 | 106 print 'no files found with this search string' |
| 117 | 107 print 'aborting. ' |
| 118 | 108 sys.exit(0) |
| 119 | 109 else: |
| 120 | 110 print 'found ',len(dates),'files' |
| 121 | 111 #Prepare output files |
| 122 | 112 fout = file(os.path.join(avpath,'AVAILABLE'),'w') |
| 123 | 113 fout.write(AVAIL_head) |
| 124 | 114 |
| 125 | 115 for i,date in enumerate(dates): # go through dates in ascending order |
| 126 | 116 f = date[1] # now we have the filename+path |
| 127 | 117 fn = os.path.basename(f) |
| 128 | 118 if fn[-1]!='*': |
| 129 | 119 timestamp = fn[tind:] |
| 130 | 120 year = int(timestamp[0:2]) |
| 131 | 121 if year < 58: |
| 132 | 122 year += 2000 |
| 133 | 123 else: |
| 134 | 124 year += 1900 |
| 135 | 125 month = int(timestamp[2:4]) |
| 136 | 126 day = int(timestamp[4:6]) |
| 137 | 127 hour = int(timestamp[6:8]) |
| 138 | 128 fileT = year*100 + int(month) |
| 139 | 129 # PS: now check for irregular intervals |
| 140 | 130 date = datetime.datetime(year,month,day,hour) |
| 141 | 131 if i == 2: |
| 142 | 132 if options.timeint == '': |
| 143 | 133 timeint = date - date1 |
| 144 | 134 else: |
| 145 | 135 timeint = datetime.timedelta(0,3600*int(options.timeint)) |
| 146 | 136 if timeint != date - date1: |
| 147 | 137 print 'WARNING - irregular interval',date - date1 |
| 148 | 138 print date1,f1,'\n',date, f,'\n' |
| 149 | 139 elif i > 2: |
| 150 | 140 if timeint != date - date1: |
| 151 | 141 print 'WARNING - irregular interval',date - date1 |
| 152 | 142 print date1,f1,'\n',date, f,'\n' |
| 153 | 143 if options.timeint == '': timeint = date - date1 |
| 154 | 144 date1 = date |
| 155 | 145 f1 = f |
| 156 | 146 |
| 157 | 147 if i%5000 == 0: print 'progress:', i, 'of', len(dates), f |
| 158 | 148 |
| 159 | 149 if fileT >= sy*100 + sm and fileT <= ey*100 + em : |
| 160 | 150 |
| 161 | 151 relpath = os.path.relpath( os.path.dirname(f), avpath ) |
| 162 | 152 f = os.path.join(relpath,fn) |
| 163 | 153 |
| 164 | 154 if (f[0:2] == './'): f = f[2:] # remove this part if present |
| 165 | 155 |
| 166 | 156 if len(f) > 18: #PS |
| 167 | 157 if not warned: |
| 168 | 158 print 'WARNING: Flexpart can only read 18 chars in WF-name' |
| 169 | 159 print f, ' has ', len(f), ' characters!\n' |
| 170 | 160 warned = True |
| 171 | 161 |
| 172 | 162 #This is the fortran format: (i8,1x,i6,2(6x,a18)) |
| 173 | 163 string = "%s%s%s %s0000 %s ON DISC\n" %\ |
| 174 | 164 (year,str(month).zfill(2),str(day).zfill(2),str(hour).zfill(2),f.ljust(18)) |
| 175 | 165 fout.write(string) |
| 176 | 166 |
| 177 | 167 print 'Done: ',i+1 # as i starts with 0 |
| 178 | 168 print 'Written:', os.path.join(avpath,'AVAILABLE') |
| 179 | 169 fout.close() |
| 180 | 170 |
| 181 | 171 if __name__ == '__main__': |
| 182 | 172 MODEL = {} |
| 183 | 173 MODEL['ECMWF'] = {'prefix':'EN', 'timeindex':2} |
| 184 | 174 MODEL['ERAI'] = {'prefix':'EI', 'timeindex':2} |
| 185 | 175 MODEL['EI'] = {'prefix':'EI', 'timeindex':2} |
| 186 | 176 MODEL['E5'] = {'prefix':'E5', 'timeindex':2} |
| 187 | 177 MODEL['EA'] = {'prefix':'EA', 'timeindex':2} |
| 188 | 178 MODEL['GFS'] = {'prefix':'GF', 'timeindex':2} |
| 189 | 179 |
| 190 | 180 models = '/'.join(MODEL.keys()) |
| 191 | 181 |
| 192 | 182 try: |
| 193 | 183 start_time = time.time() |
| 194 | 184 today = datetime.datetime.now() |
| 195 | 185 |
| 196 | 186 parser = optparse.OptionParser( |
| 197 | 187 formatter = optparse.TitledHelpFormatter(), |
| 198 | 188 usage = globals()['__doc__']) |
| 199 | 189 |
| 200 | 190 parser.add_option ('-v', '--verbose', action = 'store_true', |
| 201 | 191 default = False, help = 'verbose output') |
| 202 | 192 |
| 203 | 193 parser.add_option ('-s', '--startdate', |
| 204 | 194 dest = 'startdate', |
| 205 | 195 default = '197001', |
| 206 | 196 help = 'startdate YYYYMM integer') |
| 207 | 197 |
| 208 | 198 parser.add_option ('-e', '--enddate', |
| 209 | 199 # setting default as TODAY |
| 210 | 200 dest = 'enddate', |
| 211 | 201 default = str(today.year) + str(today.month).zfill(2), |
| 212 | 202 #default = '200712', |
| 213 | 203 help = 'enddate YYYYMM integer') |
| 214 | 204 |
| 215 | 205 parser.add_option ('-m', '--model', |
| 216 | 206 dest = 'model', |
| 217 | 207 default = 'ECMWF', help = models) |
| 218 | 208 |
| 219 | 209 parser.add_option ('-p', '--path', |
| 220 | 210 dest = 'path', |
| 221 | 211 default = '.', help = 'path to be searched for windfields. Escape or quote * and ? ') |
| 222 | 212 |
| 223 | 213 parser.add_option ('-a', '--avpath', |
| 224 | 214 dest = 'avpath', |
| 225 | 215 default = '.', help = 'path for AVAILABLE file ') |
| 226 | 216 |
| 227 | 217 parser.add_option ('-i', '--interval', |
| 228 | 218 dest = 'timeint', |
| 229 | 219 default = '', help = 'expected time interval in h. If omitted, show every change') |
| 230 | 220 |
| 231 | 221 (options, args) = parser.parse_args() |
| 232 | 222 |
| 233 | 223 #QUERY['modelType'] = options.model |
| 234 | 224 #QUERY['start_date'] = options.startdate |
| 235 | 225 #QUERY['end_date'] = options.enddate |
| 236 | 226 |
| 237 | 227 #if len(args) < 1: |
| 238 | 228 # parser.error ('missing argument') |
| 239 | 229 |
| 240 | 230 if options.verbose: print time.asctime() |
| 241 | 231 exit_code = main() |
| 242 | 232 if exit_code is None: |
| 243 | 233 exit_code = 0 |
| 244 | 234 if options.verbose: print time.asctime() |
| 245 | 235 if options.verbose: print 'TOTAL TIME IN MINUTES:', |
| 246 | 236 if options.verbose: print (time.time() - start_time) / 60.0 |
| 247 | 237 sys.exit(exit_code) |
| 248 | 238 except KeyboardInterrupt, e: # Ctrl-C |
| 249 | 239 raise e |
| 250 | 240 except SystemExit, e: # sys.exit() |
| 251 | 241 raise e |
| 252 | 242 except Exception, e: |
| 253 | 243 print 'ERROR, UNEXPECTED EXCEPTION' |
| 254 | 244 print str(e) |
| 255 | 245 traceback.print_exc() |
| 256 | 246 os._exit(1) |
| 257 | 247 |
| 258 | 248 |
| 259 | 249 |
| 260 | 250 # vim:set sr et |