FpInputMetMkavail: mkAVAIL_v7.py

File mkAVAIL_v7.py, 7.3 KB (added by pesei, 5 years ago)

Version 7 of python script to create the AVAILABLE file

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