FpInputMetMkavail: mkAVAIL_v6.py

File mkAVAIL_v6.py, 7.2 KB (added by pesei, 3 years ago)

mkAVAIL.py

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