#!/usr/bin/env python
# -*- coding: utf-8 -*-
#************************************************************************
# TODO AP
# - write a test class
# - check documentation
#************************************************************************
"""
@Author: Leopold Haimberger (University of Vienna)
@Date: November 2015
@ChangeHistory:
February 2018 - Anne Philipp (University of Vienna):
- applied PEP8 style guide
- added documentation
- applied some minor modifications in programming style/structure
- moved Control class in a file for its own
@License:
(C) Copyright 2015-2018.
This software is licensed under the terms of the Apache Licence Version 2.0
which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
@Requirements:
A standard python 2.6 or 2.7 installation
@Description:
The Control files are the steering part of the FLEXPART extraction
software. All necessary parameters needed to retrieve the data fields
from the MARS archive for driving FLEXPART are set in a Control file.
Some specific parameters like the start and end dates can be overwritten
by the command line parameters, but in generel all parameters needed
for a complete set of fields for FLEXPART can be set in the Control files.
"""
# ------------------------------------------------------------------------------
# MODULES
# ------------------------------------------------------------------------------
import os
import inspect
import Tools
# ------------------------------------------------------------------------------
# CLASS
# ------------------------------------------------------------------------------
class Control:
'''
Class containing the information of the ECMWFDATA control file.
Contains all the parameters of control files, which are e.g.:
DAY1(start_date), DAY2(end_date), DTIME, MAXSTEP, TYPE, TIME,
STEP, CLASS(marsclass), STREAM, NUMBER, EXPVER, GRID, LEFT,
LOWER, UPPER, RIGHT, LEVEL, LEVELIST, RESOL, GAUSS, ACCURACY,
OMEGA, OMEGADIFF, ETA, ETADIFF, DPDETA, SMOOTH, FORMAT,
ADDPAR, WRF, CWC, PREFIX, ECSTORAGE, ECTRANS, ECFSDIR,
MAILOPS, MAILFAIL, GRIB2FLEXPART, FLEXPARTDIR,
BASETIME, DATE_CHUNK, DEBUG, INPUTDIR, OUTPUTDIR, FLEXPART_ROOT_SCRIPTS
For more information about format and content of the parameter
see documentation.
'''
def __init__(self, filename):
'''
@Description:
Initialises the instance of Control class and defines and
assign all controlfile variables. Set default values if
parameter was not in CONTROL file.
@Input:
self: instance of Control class
Description see class documentation.
filename: string
Name of control file.
@Return:
<nothing>
'''
# read whole CONTROL file
with open(filename) as f:
fdata = f.read().split('\n')
# go through every line and store parameter
# as class variable
for ldata in fdata:
data = ldata.split()
if len(data) > 1:
if 'm_' in data[0].lower():
data[0] = data[0][2:]
if data[0].lower() == 'class':
data[0] = 'marsclass'
if data[0].lower() == 'day1':
data[0] = 'start_date'
if data[0].lower() == 'day2':
data[0] = 'end_date'
if data[0].lower() == 'addpar':
if '/' in data[1]:
# remove leading '/' sign from addpar content
if data[1][0] == '/':
data[1] = data[1][1:]
dd = data[1].split('/')
data = [data[0]]
for d in dd:
data.append(d)
pass
if len(data) == 2:
if '$' in data[1]:
setattr(self, data[0].lower(), data[1])
while '$' in data[1]:
i = data[1].index('$')
j = data[1].find('{')
k = data[1].find('}')
var = os.getenv(data[1][j+1:k])
if var is not None:
data[1] = data[1][:i] + var + data[1][k+1:]
else:
Tools.myerror(None,
'Could not find variable ' +
data[1][j+1:k] +
' while reading ' +
filename)
setattr(self, data[0].lower() + '_expanded', data[1])
else:
if data[1].lower() != 'none':
setattr(self, data[0].lower(), data[1])
else:
setattr(self, data[0].lower(), None)
elif len(data) > 2:
setattr(self, data[0].lower(), (data[1:]))
else:
pass
# check a couple of necessary attributes if they contain values
# otherwise set default values
if not hasattr(self, 'start_date'):
self.start_date = None
if not hasattr(self, 'end_date'):
self.end_date = self.start_date
if not hasattr(self, 'accuracy'):
self.accuracy = 24
if not hasattr(self, 'omega'):
self.omega = '0'
if not hasattr(self, 'cwc'):
self.cwc = '0'
if not hasattr(self, 'omegadiff'):
self.omegadiff = '0'
if not hasattr(self, 'etadiff'):
self.etadiff = '0'
if not hasattr(self, 'levelist'):
if not hasattr(self, 'level'):
print 'Warning: neither levelist nor level \
specified in CONTROL file'
else:
self.levelist = '1/to/' + self.level
else:
if 'to' in self.levelist:
self.level = self.levelist.split('/')[2]
else:
self.level = self.levelist.split('/')[-1]
if not hasattr(self, 'maxstep'):
# find out maximum step
self.maxstep = 0
for s in self.step:
if int(s) > self.maxstep:
self.maxstep = int(s)
else:
self.maxstep = int(self.maxstep)
if not hasattr(self, 'prefix'):
self.prefix = 'EN'
if not hasattr(self, 'makefile'):
self.makefile = None
if not hasattr(self, 'basetime'):
self.basetime = None
if not hasattr(self, 'date_chunk'):
self.date_chunk = '3'
if not hasattr(self, 'grib2flexpart'):
self.grib2flexpart = '0'
# script directory
self.ecmwfdatadir = os.path.dirname(os.path.abspath(inspect.getfile(
inspect.currentframe()))) + '/../'
# Fortran source directory
self.exedir = self.ecmwfdatadir + 'src/'
# FLEXPART directory
if not hasattr(self, 'flexpart_root_scripts'):
self.flexpart_root_scripts = self.ecmwfdatadir
return
def __str__(self):
'''
@Description:
Prepares a single string with all the comma seperated Control
class attributes including their values.
Example:
{'kids': 0, 'name': 'Dog', 'color': 'Spotted',
'age': 10, 'legs': 2, 'smell': 'Alot'}
@Input:
self: instance of Control class
Description see class documentation.
@Return:
string of Control class attributes with their values
'''
attrs = vars(self)
return ', '.join("%s: %s" % item for item in attrs.items())
def tolist(self):
'''
@Description:
Just generates a list of strings containing the attributes and
assigned values except the attributes "_expanded", "exedir",
"ecmwfdatadir" and "flexpart_root_scripts".
@Input:
self: instance of Control class
Description see class documentation.
@Return:
l: list
A sorted list of the all Control class attributes with
their values except the attributes "_expanded", "exedir",
"ecmwfdatadir" and "flexpart_root_scripts".
'''
attrs = vars(self)
l = list()
for item in attrs.items():
if '_expanded' in item[0]:
pass
elif 'exedir' in item[0]:
pass
elif 'flexpart_root_scripts' in item[0]:
pass
elif 'ecmwfdatadir' in item[0]:
pass
else:
if type(item[1]) is list:
stot = ''
for s in item[1]:
stot += s + ' '
l.append("%s %s" % (item[0], stot))
else:
#AP syntax error with doubled %s ???
l.append("%s %s" % item)
return sorted(l)