source: flex_extract.git/source/python/classes/ControlFile.py @ 5c0a578

ctbtodev
Last change on this file since 5c0a578 was 5c0a578, checked in by Anne Philipp <anne.philipp@…>, 5 years ago

renamed read controlfile function

  • Property mode set to 100644
File size: 13.6 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#*******************************************************************************
4# @Author: Leopold Haimberger (University of Vienna)
5#
6# @Date: November 2015
7#
8# @Change History:
9#
10#   February 2018 - Anne Philipp (University of Vienna):
11#        - applied PEP8 style guide
12#        - added documentation
13#        - applied some minor modifications in programming style/structure
14#        - changed name of class Control to ControlFile for more
15#          self-explanation naming
16#        - outsource of class ControlFile
17#        - initialisation of class attributes ( to avoid high number of
18#          conditional statements and set default values )
19#        - divided assignment of attributes and the check of conditions
20#        - outsourced the commandline argument assignments to control attributes
21#
22# @License:
23#    (C) Copyright 2015-2018.
24#
25#    This software is licensed under the terms of the Apache Licence Version 2.0
26#    which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
27#
28# @Class Description:
29#    The CONTROL file is the steering part of the FLEXPART extraction
30#    software. All necessary parameters needed to retrieve the data fields
31#    from the MARS archive for driving FLEXPART are set in a CONTROL file.
32#    Some specific parameters like the start and end dates can be overwritten
33#    by the command line parameters, but in generel all parameters needed
34#    for a complete set of fields for FLEXPART can be set in the CONTROL file.
35#
36# @Class Content:
37#    - __init__
38#    - __read_controlfile__
39#    - __str__
40#    - assign_args_to_control
41#    - assign_envs_to_control
42#    - check_conditions
43#    - check_install_conditions
44#    - to_list
45#
46# @Class Attributes:
47#
48#
49#*******************************************************************************
50
51# ------------------------------------------------------------------------------
52# MODULES
53# ------------------------------------------------------------------------------
54import os
55import re
56import sys
57import inspect
58import numpy as np
59
60# software specific classes and modules from flex_extract
61sys.path.append('../')
62import _config
63from mods.tools import my_error, silent_remove
64from mods.checks import (check_grid, check_area, check_levels, check_purefc,
65                         check_step, check_mail, check_queue, check_pathes,
66                         check_dates, check_maxstep, check_type, check_request,
67                         check_basetime, check_public, check_acctype,
68                         check_acctime, check_accmaxstep, check_time,
69                         check_logicals_type, check_len_type_time_step,
70                         check_addpar)
71
72# ------------------------------------------------------------------------------
73# CLASS
74# ------------------------------------------------------------------------------
75class ControlFile(object):
76    '''
77    Contains the information which are stored in the CONTROL files.
78    '''
79
80    def __init__(self, filename):
81        '''Initialises the instance of ControlFile class and defines
82        all class attributes with default values. Afterwards calls
83        function __read_controlfile__ to read parameter from Control file.
84
85        Parameters
86        ----------
87        filename : :obj:`string`
88            Name of CONTROL file.
89
90        Return
91        ------
92
93        '''
94
95        # list of all possible class attributes and their default values
96        self.controlfile = filename
97        self.start_date = None
98        self.end_date = None
99        self.date_chunk = 3
100        self.dtime = None
101        self.basetime = None
102        self.maxstep = None
103        self.type = None
104        self.time = None
105        self.step = None
106        self.acctype = None
107        self.acctime = None
108        self.accmaxstep = None
109        self.marsclass = None
110        self.dataset = None
111        self.stream = None
112        self.number = 'OFF'
113        self.expver = '1'
114        self.gaussian = ''
115        self.grid = None
116        self.area = ''
117        self.left = None
118        self.lower = None
119        self.upper = None
120        self.right = None
121        self.level = None
122        self.levelist = None
123        self.resol = None
124        self.gauss = 0
125        self.accuracy = 24
126        self.omega = 0
127        self.omegadiff = 0
128        self.eta = 0
129        self.etadiff = 0
130        self.etapar = 77
131        self.dpdeta = 1
132        self.smooth = 0
133        self.format = 'GRIB1'
134        self.addpar = None
135        self.prefix = 'EN'
136        self.cwc = 0
137        self.wrf = 0
138        self.ecfsdir = 'ectmp:/${USER}/econdemand/'
139        self.mailfail = ['${USER}']
140        self.mailops = ['${USER}']
141        self.grib2flexpart = 0
142        self.ecstorage = 0
143        self.ectrans = 0
144        self.inputdir = _config.PATH_INPUT_DIR
145        self.outputdir = None
146        self.flexextractdir = _config.PATH_FLEXEXTRACT_DIR
147        self.exedir = _config.PATH_FORTRAN_SRC
148        self.flexpartdir = None
149        self.makefile = 'Makefile.gfortran'
150        self.destination = None
151        self.gateway = None
152        self.ecuid = None
153        self.ecgid = None
154        self.install_target = None
155        self.debug = 0
156        self.request = 0
157        self.public = 0
158        self.ecapi = None
159        self.purefc = 0
160        self.rrint = 0
161
162        self.logicals = ['gauss', 'omega', 'omegadiff', 'eta', 'etadiff',
163                         'dpdeta', 'cwc', 'wrf', 'grib2flexpart', 'ecstorage',
164                         'ectrans', 'debug', 'request', 'public', 'purefc',
165                         'rrint']
166
167        self._read_controlfile()
168
169        return
170
171    def _read_controlfile(self):
172        '''Read CONTROL file and assign all CONTROL file variables.
173
174        Parameters
175        ----------
176
177        Return
178        ------
179
180        '''
181
182        try:
183            cfile = os.path.join(_config.PATH_CONTROLFILES, self.controlfile)
184            with open(cfile) as f:
185                fdata = f.read().split('\n')
186        except IOError:
187            print('Could not read CONTROL file "' + cfile + '"')
188            print('Either it does not exist or its syntax is wrong.')
189            print('Try "' + sys.argv[0].split('/')[-1] + \
190                      ' -h" to print usage information')
191            sys.exit(1)
192
193        # go through every line and store parameter
194        for ldata in fdata:
195            data = ldata.split()
196            if len(data) > 1:
197                if 'm_' in data[0].lower():
198                    data[0] = data[0][2:]
199                if data[0].lower() == 'class':
200                    data[0] = 'marsclass'
201                if data[0].lower() == 'day1':
202                    data[0] = 'start_date'
203                if data[0].lower() == 'day2':
204                    data[0] = 'end_date'
205                if len(data) == 2:
206                    if '$' in data[1]:
207                        setattr(self, data[0].lower(), data[1])
208                        while '$' in data[1]:
209                            i = data[1].index('$')
210                            j = data[1].find('{')
211                            k = data[1].find('}')
212                            var = os.getenv(data[1][j+1:k])
213                            if var is not None:
214                                data[1] = data[1][:i] + var + data[1][k+1:]
215                            else:
216                                my_error(self.mailfail,
217                                         'Could not find variable '
218                                         + data[1][j+1:k] + ' while reading ' +
219                                         self.controlfile)
220                        setattr(self, data[0].lower() + '_expanded', data[1])
221                    else:
222                        if data[1].lower() != 'none':
223                            setattr(self, data[0].lower(), data[1])
224                        else:
225                            setattr(self, data[0].lower(), None)
226                elif len(data) > 2:
227                    setattr(self, data[0].lower(), (data[1:]))
228            else:
229                pass
230
231        return
232
233    def __str__(self):
234        '''Prepares a string which have all the ControlFile class attributes
235        with its associated values. Each attribute is printed in one line and
236        in alphabetical order.
237
238        Example
239        -------
240        'age': 10
241        'color': 'Spotted'
242        'kids': 0
243        'legs': 2
244        'name': 'Dog'
245        'smell': 'Alot'
246
247        Parameters
248        ----------
249
250        Return
251        ------
252        string
253            Single string of concatenated ControlFile class attributes
254            with their values
255        '''
256        import collections
257
258        attrs = vars(self).copy()
259        attrs = collections.OrderedDict(sorted(attrs.items()))
260
261        return '\n'.join("%s: %s" % item for item in attrs.items())
262
263    def assign_args_to_control(self, args):
264        '''Overwrites the existing ControlFile instance attributes with
265        the command line arguments.
266
267        Parameters
268        ----------
269        args : :obj:`Namespace`
270            Contains the commandline arguments from script/program call.
271
272        Return
273        ------
274
275        '''
276
277        # get dictionary of command line parameters and eliminate all
278        # parameters which are None (were not specified)
279        args_dict = vars(args)
280        arguments = {k : args_dict[k] for k in args_dict
281                     if args_dict[k] != None}
282
283        # assign all passed command line arguments to ControlFile instance
284        for k, v in arguments.iteritems():
285            setattr(self, str(k), v)
286
287        return
288
289    def assign_envs_to_control(self, envs):
290        '''Assigns the ECMWF environment parameter.
291
292        Parameters
293        ----------
294        envs : :obj:`dictionary` of :obj:`strings`
295            Contains the ECMWF environment parameternames "ECUID", "ECGID",
296            "DESTINATION" and "GATEWAY" with its corresponding values.
297            They were read from the file "ECMWF_ENV".
298
299        Return
300        ------
301
302        '''
303
304        for k, v in envs.iteritems():
305            setattr(self, str(k).lower(), str(v))
306
307        return
308
309    def check_conditions(self, queue):
310        '''Checks a couple of necessary attributes and conditions,
311        such as if they exist and contain values.
312        Otherwise set default values.
313
314        Parameters
315        ----------
316        queue : :obj:`string`
317            Name of the queue if submitted to the ECMWF servers.
318            Used to check if ecuid, ecgid, gateway and destination
319            are set correctly and are not empty.
320
321        Return
322        ------
323
324        '''
325        check_logicals_type(self, self.logicals)
326
327        self.mailfail = check_mail(self.mailfail)
328
329        self.mailops = check_mail(self.mailops)
330
331        check_queue(queue, self.gateway, self.destination,
332                    self.ecuid, self.ecgid)
333
334        self.outputdir, self.flexpartdir = check_pathes(self.inputdir,
335             self.outputdir, self.flexpartdir, self.flexextractdir)
336
337        self.start_date, self.end_date = check_dates(self.start_date,
338                                                     self.end_date)
339
340        check_basetime(self.basetime)
341
342        self.levelist, self.level = check_levels(self.levelist, self.level)
343
344        self.step = check_step(self.step, self.mailfail)
345
346        self.maxstep = check_maxstep(self.maxstep, self.step)
347
348        check_request(self.request,
349                      os.path.join(self.inputdir, _config.FILE_MARS_REQUESTS))
350
351        check_public(self.public, self.dataset)
352
353        self.type = check_type(self.type, self.step)
354
355        self.time = check_time(self.time)
356
357        self.type, self.time, self.step = check_len_type_time_step(self.type,
358                                                                   self.time,
359                                                                   self.step,
360                                                                   self.maxstep,
361                                                                   self.purefc)
362
363        self.acctype = check_acctype(self.acctype, self.type)
364
365        self.acctime = check_acctime(self.acctime, self.acctype, self.purefc)
366
367        self.accmaxstep = check_accmaxstep(self.accmaxstep, self.acctype,
368                                           self.purefc, self.maxstep)
369
370        self.purefc = check_purefc(self.type)
371
372        self.grid = check_grid(self.grid)
373
374        self.area = check_area(self.grid, self.area, self.upper, self.lower,
375                               self.left, self.right)
376
377        self.addpar = check_addpar(self.addpar)
378
379
380        return
381
382    def to_list(self):
383        '''Just generates a list of strings containing the attributes and
384        assigned values except the attributes "_expanded", "exedir",
385        "flexextractdir" and "flexpartdir".
386
387        Parameters
388        ----------
389
390        Return
391        ------
392        l : :obj:`list`
393            A sorted list of the all ControlFile class attributes with
394            their values except the attributes "_expanded", "exedir",
395            "flexextractdir" and "flexpartdir".
396        '''
397
398        import collections
399
400        attrs = collections.OrderedDict(sorted(vars(self).copy().items()))
401
402        l = list()
403
404        for item in attrs.items():
405            if '_expanded' in item[0]:
406                pass
407            elif 'exedir' in item[0]:
408                pass
409            elif 'flexpartdir' in item[0]:
410                pass
411            elif 'flexextractdir' in item[0]:
412                pass
413            else:
414                if isinstance(item[1], list):
415                    stot = ''
416                    for s in item[1]:
417                        stot += s + ' '
418
419                    l.append("%s %s\n" % (item[0], stot))
420                else:
421                    l.append("%s %s\n" % item)
422
423        return sorted(l)
424
Note: See TracBrowser for help on using the repository browser.
hosted by ZAMG