Index: source/python/classes/ControlFile.py
===================================================================
--- source/python/classes/ControlFile.py	(revision 25b14bea5de21f28364c210382513c1c9b792d61)
+++ source/python/classes/ControlFile.py	(revision 25b14bea5de21f28364c210382513c1c9b792d61)
@@ -0,0 +1,532 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#*******************************************************************************
+# @Author: Leopold Haimberger (University of Vienna)
+#
+# @Date: November 2015
+#
+# @Change History:
+#
+#   February 2018 - Anne Philipp (University of Vienna):
+#        - applied PEP8 style guide
+#        - added documentation
+#        - applied some minor modifications in programming style/structure
+#        - changed name of class Control to ControlFile for more
+#          self-explanation naming
+#        - outsource of class ControlFile
+#        - initialisation of class attributes ( to avoid high number of
+#          conditional statements and set default values )
+#        - divided assignment of attributes and the check of conditions
+#        - outsourced the commandline argument assignments to control attributes
+#
+# @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.
+#
+# @Class Description:
+#    The CONTROL file is 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 file.
+#
+# @Class Content:
+#    - __init__
+#    - __read_controlfile__
+#    - __str__
+#    - assign_args_to_control
+#    - assign_envs_to_control
+#    - check_conditions
+#    - check_install_conditions
+#    - to_list
+#
+# @Class Attributes:
+#
+#
+#*******************************************************************************
+
+# ------------------------------------------------------------------------------
+# MODULES
+# ------------------------------------------------------------------------------
+import os
+import re
+import sys
+import inspect
+
+import _config
+
+# ------------------------------------------------------------------------------
+# CLASS
+# ------------------------------------------------------------------------------
+class ControlFile(object):
+    '''
+    Class containing the information of the flex_extract CONTROL file.
+
+    Contains all the parameters of CONTROL file, 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 ControlFile class and defines
+            all class attributes with default values. Afterwards calls
+            function __read_controlfile__ to read parameter from
+            Control file.
+
+        @Input:
+            self: instance of ControlFile class
+                Description see class documentation.
+
+            filename: string
+                Name of CONTROL file.
+
+        @Return:
+            <nothing>
+        '''
+
+        # list of all possible class attributes and their default values
+        self.controlfile = filename
+        self.start_date = None
+        self.end_date = None
+        self.date_chunk = 3
+        self.dtime = None
+        self.basetime = None
+        self.maxstep = None
+        self.type = None
+        self.time = None
+        self.step = None
+        self.marsclass = None
+        self.stream = None
+        self.number = 'OFF'
+        self.expver = '1'
+        self.grid = None
+        self.area = ''
+        self.left = None
+        self.lower = None
+        self.upper = None
+        self.right = None
+        self.level = None
+        self.levelist = None
+        self.resol = None
+        self.gauss = 0
+        self.accuracy = 24
+        self.omega = 0
+        self.omegadiff = 0
+        self.eta = 0
+        self.etadiff = 0
+        self.etapar = 77
+        self.dpdeta = 1
+        self.smooth = 0
+        self.format = 'GRIB1'
+        self.addpar = None
+        self.prefix = 'EN'
+        self.cwc = 0
+        self.wrf = 0
+        self.ecfsdir = 'ectmp:/${USER}/econdemand/'
+        self.mailfail = ['${USER}']
+        self.mailops = ['${USER}']
+        self.grib2flexpart = 0
+        self.ecstorage = 0
+        self.ectrans = 0
+        self.inputdir = _config.PATH_INPUT_DIR
+        self.outputdir = self.inputdir
+        self.ecmwfdatadir = _config.PATH_FLEXEXTRACT_DIR
+        self.exedir = _config.PATH_FORTRAN_SRC
+        self.flexpart_root_scripts = None
+        self.makefile = 'Makefile.gfortran'
+        self.destination = None
+        self.gateway = None
+        self.ecuid = None
+        self.ecgid = None
+        self.install_target = None
+        self.debug = 0
+        self.request = 0
+
+        self.logicals = ['gauss', 'omega', 'omegadiff', 'eta', 'etadiff',
+                         'dpdeta', 'cwc', 'wrf', 'grib2flexpart', 'ecstorage',
+                         'ectrans', 'debug', 'request']
+
+        self.__read_controlfile__()
+
+        return
+
+    def __read_controlfile__(self):
+        '''
+        @Description:
+            Read CONTROL file and assign all CONTROL file variables.
+
+        @Input:
+            self: instance of ControlFile class
+                Description see class documentation.
+
+        @Return:
+            <nothing>
+        '''
+        from mods.tools import my_error
+
+        # read whole CONTROL file
+        with open(os.path.join(_config.PATH_CONTROLFILES,
+                               self.controlfile)) as f:
+            fdata = f.read().split('\n')
+
+        # go through every line and store parameter
+        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)
+                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:
+                                my_error(self.mailfail,
+                                         'Could not find variable '
+                                         + data[1][j+1:k] + ' while reading ' +
+                                         self.controlfile)
+                        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
+
+        return
+
+    def __str__(self):
+        '''
+        @Description:
+            Prepares a string which have all the ControlFile
+            class attributes with its associated values.
+            Each attribute is printed in one line and in
+            alphabetical order.
+
+            Example:
+            'age': 10
+            'color': 'Spotted'
+            'kids': 0
+            'legs': 2
+            'name': 'Dog'
+            'smell': 'Alot'
+
+        @Input:
+            self: instance of ControlFile class
+                Description see class documentation.
+
+        @Return:
+            string of ControlFile class attributes with their values
+        '''
+        import collections
+
+        attrs = vars(self)
+        attrs = collections.OrderedDict(sorted(attrs.items()))
+
+        return '\n'.join("%s: %s" % item for item in attrs.items())
+
+    def assign_args_to_control(self, args):
+        '''
+        @Description:
+            Overwrites the existing ControlFile instance attributes with
+            the command line arguments.
+
+        @Input:
+            self: instance of ControlFile class
+                Description see class documentation.
+
+            args: instance of ArgumentParser
+                Contains the commandline arguments from script/program call.
+
+        @Return:
+            <nothing>
+        '''
+
+        # get dictionary of command line parameters and eliminate all
+        # parameters which are None (were not specified)
+        args_dict = vars(args)
+        arguments = {k : args_dict[k] for k in args_dict
+                     if args_dict[k] != None}
+
+        # assign all passed command line arguments to ControlFile instance
+        for k, v in arguments.iteritems():
+            setattr(self, str(k), v)
+
+        return
+
+    def assign_envs_to_control(self, envs):
+        '''
+        @Description:
+            Assigns the ECMWF environment parameter.
+
+        @Input:
+            envs: dict of strings
+                Contains the ECMWF environment parameternames "ECUID", "ECGID",
+                "DESTINATION" and "GATEWAY" with its corresponding values.
+                They were read from the file "ECMWF_ENV".
+
+        @Return:
+            <nothing>
+        '''
+
+        for k, v in envs.iteritems():
+            setattr(self, str(k).lower(), str(v))
+
+        return
+
+    def check_conditions(self, queue):
+        '''
+        @Description:
+            Checks a couple of necessary attributes and conditions,
+            such as if they exist and contain values.
+            Otherwise set default values.
+
+        @Input:
+            self: instance of ControlFile class
+                Description see class documentation.
+
+            queue: string
+                Name of the queue if submitted to the ECMWF servers.
+                Used to check if ecuid, ecgid, gateway and destination
+                are set correctly and are not empty.
+
+        @Return:
+            <nothing>
+        '''
+        from mods.tools import my_error
+        import numpy as np
+
+        # check for having at least a starting date
+        # otherwise program is not allowed to run
+        if self.start_date is None:
+            print('start_date specified neither in command line nor \
+                   in CONTROL file ' +  self.controlfile)
+            print('Try "' + sys.argv[0].split('/')[-1] +
+                  ' -h" to print usage information')
+            sys.exit(1)
+
+        # retrieve just one day if end_date isn't set
+        if self.end_date is None:
+            self.end_date = self.start_date
+
+        # assure consistency of levelist and level
+        if self.levelist is None and self.level is None:
+            print('Warning: neither levelist nor level \
+                               specified in CONTROL file')
+            sys.exit(1)
+        elif self.levelist is None and self.level:
+            self.levelist = '1/to/' + self.level
+        elif (self.levelist and self.level is None) or \
+             (self.levelist[-1] != self.level[-1]):
+            self.level = self.levelist.split('/')[-1]
+        else:
+            pass
+
+        # if area was provided (only from commandline)
+        # decompose area into its 4 components
+        if self.area:
+            components = self.area.split('/')
+            # convert float to integer coordinates
+            if '.' in self.area:
+                components = [str(int(float(item) * 1000))
+                              for i, item in enumerate(components)]
+            self.upper, self.left, self.lower, self.right = components
+
+        # prepare step list if "/" signs are found
+        if '/' in self.step:
+            steps = self.step.split('/')
+            if 'to' in self.step.lower() and 'by' in self.step.lower():
+                ilist = np.arange(int(steps[0]),
+                                  int(steps[2]) + 1,
+                                  int(steps[4]))
+                self.step = ['{:0>3}'.format(i) for i in ilist]
+            elif 'to' in self.step.lower() and 'by' not in self.step.lower():
+                my_error(self.mailfail, self.step + ':\n' +
+                         'if "to" is used in steps parameter, \
+                         please use "by" as well')
+            else:
+                self.step = steps
+
+        # if maxstep wasn't provided
+        # search for it in the "step" parameter
+        if self.maxstep is None:
+            self.maxstep = 0
+            for s in self.step:
+                if int(s) > self.maxstep:
+                    self.maxstep = int(s)
+        else:
+            self.maxstep = int(self.maxstep)
+
+        # set root scripts since it is needed later on
+        if not self.flexpart_root_scripts:
+            self.flexpart_root_scripts = self.ecmwfdatadir
+
+        if not isinstance(self.mailfail, list):
+            if ',' in self.mailfail:
+                self.mailfail = self.mailfail.split(',')
+            elif ' ' in self.mailfail:
+                self.mailfail = self.mailfail.split()
+            else:
+                self.mailfail = [self.mailfail]
+
+        if not isinstance(self.mailops, list):
+            if ',' in self.mailops:
+                self.mailops = self.mailops.split(',')
+            elif ' ' in self.mailops:
+                self.mailops = self.mailops.split()
+            else:
+                self.mailops = [self.mailops]
+
+        if queue in ['ecgate', 'cca'] and \
+           not self.gateway or not self.destination or \
+           not self.ecuid or not self.ecgid:
+            print('\nEnvironment variables GATEWAY, DESTINATION, ECUID and \
+                   ECGID were not set properly!')
+            print('Please check for existence of file "ECMWF_ENV" in the \
+                   python directory!')
+            sys.exit(1)
+
+        if self.request != 0:
+            marsfile = os.path.join(self.inputdir,
+                                    _config.FILE_MARS_REQUESTS)
+            if os.path.isfile(marsfile):
+                os.remove(marsfile)
+
+        # check all logical variables for data type
+        # if its a string change to integer
+        for var in self.logicals:
+            if not isinstance(getattr(self, var), int):
+                setattr(self, var, int(getattr(self, var)))
+
+        return
+
+    def check_install_conditions(self):
+        '''
+        @Description:
+            Checks a couple of necessary attributes and conditions
+            for the installation such as if they exist and contain values.
+            Otherwise set default values.
+
+        @Input:
+            self: instance of ControlFile class
+                Description see class documentation.
+
+        @Return:
+            <nothing>
+        '''
+
+        if self.install_target and \
+           self.install_target not in ['local', 'ecgate', 'cca']:
+            print('ERROR: unknown or missing installation target ')
+            print('target: ', self.install_target)
+            print('please specify correct installation target ' +
+                  '(local | ecgate | cca)')
+            print('use -h or --help for help')
+            sys.exit(1)
+
+        if self.install_target and self.install_target != 'local':
+            if not self.ecgid or not self.ecuid or \
+               not self.gateway or not self.destination:
+                print('Please enter your ECMWF user id and group id as well ' +
+                      'as the \nname of the local gateway and the ectrans ' +
+                      'destination ')
+                print('with command line options --ecuid --ecgid \
+                       --gateway --destination')
+                print('Try "' + sys.argv[0].split('/')[-1] + \
+                      ' -h" to print usage information')
+                print('Please consult ecaccess documentation or ECMWF user \
+                       support for further details')
+                sys.exit(1)
+
+            if not self.flexpart_root_scripts:
+                self.flexpart_root_scripts = '${HOME}'
+            else:
+                self.flexpart_root_scripts = self.flexpart_root_scripts
+        else: # local
+            if not self.flexpart_root_scripts:
+                self.flexpart_root_scripts = _config.PATH_FLEXEXTRACT_DIR
+
+        return
+
+    def to_list(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 ControlFile class
+                Description see class documentation.
+
+        @Return:
+            l: list
+                A sorted list of the all ControlFile class attributes with
+                their values except the attributes "_expanded", "exedir",
+                "ecmwfdatadir" and "flexpart_root_scripts".
+        '''
+
+        import collections
+
+        attrs = collections.OrderedDict(sorted(vars(self).items()))
+
+        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 isinstance(item[1], list):
+                    stot = ''
+                    for s in item[1]:
+                        stot += s + ' '
+
+                    l.append("%s %s" % (item[0], stot))
+                else:
+                    l.append("%s %s" % item)
+
+        return sorted(l)
+
Index: source/python/classes/EcFlexpart.py
===================================================================
--- source/python/classes/EcFlexpart.py	(revision 25b14bea5de21f28364c210382513c1c9b792d61)
+++ source/python/classes/EcFlexpart.py	(revision 25b14bea5de21f28364c210382513c1c9b792d61)
@@ -0,0 +1,1296 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#*******************************************************************************
+# @Author: Anne Fouilloux (University of Oslo)
+#
+# @Date: October 2014
+#
+# @Change History:
+#
+#    November 2015 - Leopold Haimberger (University of Vienna):
+#        - extended with class Control
+#        - removed functions mkdir_p, daterange, years_between, months_between
+#        - added functions darain, dapoly, to_param_id, init128, normal_exit,
+#          my_error, clean_up, install_args_and_control,
+#          interpret_args_and_control,
+#        - removed function __del__ in class EIFLexpart
+#        - added the following functions in EIFlexpart:
+#            - create_namelist
+#            - process_output
+#            - deacc_fluxes
+#        - modified existing EIFlexpart - functions for the use in
+#          flex_extract
+#        - retrieve also longer term forecasts, not only analyses and
+#          short term forecast data
+#        - added conversion into GRIB2
+#        - added conversion into .fp format for faster execution of FLEXPART
+#          (see https://www.flexpart.eu/wiki/FpCtbtoWo4FpFormat)
+#
+#    February 2018 - Anne Philipp (University of Vienna):
+#        - applied PEP8 style guide
+#        - added documentation
+#        - removed function getFlexpartTime in class EcFlexpart
+#        - outsourced class ControlFile
+#        - outsourced class MarsRetrieval
+#        - changed class name from EIFlexpart to EcFlexpart
+#        - applied minor code changes (style)
+#        - removed "dead code" , e.g. retrieval of Q since it is not needed
+#        - removed "times" parameter from retrieve-method since it is not used
+#
+# @License:
+#    (C) Copyright 2014-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.
+#
+# @Class Description:
+#    FLEXPART needs grib files in a specifc format. All necessary data fields
+#    for one time step are stored in a single file. The class represents an
+#    instance with all the parameter and settings necessary for retrieving
+#    MARS data and modifing them so they are fitting FLEXPART need. The class
+#    is able to disaggregate the fluxes and convert grid types to the one needed
+#    by FLEXPART, therefore using the FORTRAN program.
+#
+# @Class Content:
+#    - __init__
+#    - write_namelist
+#    - retrieve
+#    - process_output
+#    - create
+#    - deacc_fluxes
+#
+# @Class Attributes:
+#
+#  TODO
+#
+#*******************************************************************************
+#pylint: disable=unsupported-assignment-operation
+# this is disabled because for this specific case its an error in pylint
+#pylint: disable=consider-using-enumerate
+# this is not useful in this case
+# ------------------------------------------------------------------------------
+# MODULES
+# ------------------------------------------------------------------------------
+import subprocess
+import shutil
+import os
+import glob
+from datetime import datetime, timedelta
+import numpy as np
+from gribapi import grib_set, grib_index_select, grib_new_from_index, grib_get,\
+                    grib_write, grib_get_values, grib_set_values, grib_release,\
+                    grib_index_release, grib_index_get
+
+# software specific classes and modules from flex_extract
+import _config
+from GribTools import GribTools
+from mods.tools import init128, to_param_id, silent_remove, product, my_error
+from MarsRetrieval import MarsRetrieval
+import mods.disaggregation
+
+# ------------------------------------------------------------------------------
+# CLASS
+# ------------------------------------------------------------------------------
+class EcFlexpart(object):
+    '''
+    Class to retrieve FLEXPART specific ECMWF data.
+    '''
+    # --------------------------------------------------------------------------
+    # CLASS FUNCTIONS
+    # --------------------------------------------------------------------------
+    def __init__(self, c, fluxes=False):
+        '''
+        @Description:
+            Creates an object/instance of EcFlexpart with the
+            associated settings of its attributes for the retrieval.
+
+        @Input:
+            self: instance of EcFlexpart
+                The current object of the class.
+
+            c: instance of class ControlFile
+                Contains all the parameters of CONTROL file, 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.
+
+            fluxes: boolean, optional
+                Decides if the flux parameter settings are stored or
+                the rest of the parameter list.
+                Default value is False.
+
+        @Return:
+            <nothing>
+        '''
+
+        # different mars types for retrieving data for flexpart
+        self.types = dict()
+
+        if c.maxstep > len(c.type):    # Pure forecast mode
+            c.type = [c.type[1]]
+            c.step = ['{:0>3}'.format(int(c.step[0]))]
+            c.time = [c.time[0]]
+            for i in range(1, c.maxstep + 1):
+                c.type.append(c.type[0])
+                c.step.append('{:0>3}'.format(i))
+                c.time.append(c.time[0])
+
+        self.inputdir = c.inputdir
+        self.basetime = c.basetime
+        self.dtime = c.dtime
+        i = 0
+        if fluxes and c.maxstep <= 24:
+            # no forecast beyond one day is needed!
+            # Thus, prepare flux data manually as usual
+            # with only forecast fields with start times at 00/12
+            # (but without 00/12 fields since these are
+            # the initialisation times of the flux fields
+            # and therefore are zero all the time)
+            self.types[c.type[1]] = {'times': '00/12', 'steps':
+                                     '{}/to/12/by/{}'.format(c.dtime, c.dtime)}
+        else:
+            for ty, st, ti in zip(c.type, c.step, c.time):
+                btlist = range(24)
+                if c.basetime == '12':
+                    btlist = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
+                if c.basetime == '00':
+                    btlist = [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 0]
+
+                if i % int(c.dtime) == 0 and (i in btlist or c.maxstep > 24):
+
+                    if ty not in self.types.keys():
+                        self.types[ty] = {'times': '', 'steps': ''}
+
+                    if ti not in self.types[ty]['times']:
+                        if self.types[ty]['times']:
+                            self.types[ty]['times'] += '/'
+                        self.types[ty]['times'] += ti
+
+                    if st not in self.types[ty]['steps']:
+                        if self.types[ty]['steps']:
+                            self.types[ty]['steps'] += '/'
+                        self.types[ty]['steps'] += st
+                i += 1
+
+        self.marsclass = c.marsclass
+        self.stream = c.stream
+        self.number = c.number
+        self.resol = c.resol
+        self.accuracy = c.accuracy
+        self.level = c.level
+        self.expver = c.expver
+        self.levelist = c.levelist
+        # for gaussian grid retrieval
+        self.glevelist = '1/to/' + c.level
+
+        if hasattr(c, 'gaussian') and c.gaussian:
+            self.gaussian = c.gaussian
+        else:
+            self.gaussian = ''
+
+        if 'N' in c.grid:  # Gaussian output grid
+            self.grid = c.grid
+            self.area = 'G'
+        else:
+            self.grid = '{}/{}'.format(int(c.grid) / 1000., int(c.grid) / 1000.)
+            self.area = '{}/{}/{}/{}'.format(int(c.upper) / 1000.,
+                                             int(c.left) / 1000.,
+                                             int(c.lower) / 1000.,
+                                             int(c.right) / 1000.)
+
+        self.outputfilelist = []
+
+
+        # Now comes the nasty part that deals with the different
+        # scenarios we have:
+        # 1) Calculation of etadot on
+        #    a) Gaussian grid
+        #    b) Output grid
+        #    c) Output grid using parameter 77 retrieved from MARS
+        # 3) Calculation/Retrieval of omega
+        # 4) Download also data for WRF
+
+        # Different grids need different retrievals
+        # SH = Spherical Harmonics, GG = Gaussian Grid,
+        # OG = Output Grid, ML = MultiLevel, SL = SingleLevel
+        self.params = {'SH__ML': '', 'SH__SL': '',
+                       'GG__ML': '', 'GG__SL': '',
+                       'OG__ML': '', 'OG__SL': '',
+                       'OG_OROLSM_SL': '', 'OG_acc_SL': ''}
+
+        if fluxes is False:
+            self.params['SH__SL'] = ['LNSP', 'ML', '1', 'OFF']
+            #                        "SD/MSL/TCC/10U/10V/2T/2D/129/172"
+            self.params['OG__SL'] = ["141/151/164/165/166/167/168/129/172", \
+                                     'SFC', '1', self.grid]
+            if c.addpar:
+                if c.addpar[0] == '/':
+                    c.addpar = c.addpar[1:]
+                self.params['OG__SL'][0] += '/' + '/'.join(c.addpar)
+
+            self.params['OG_OROLSM__SL'] = ["160/27/28/173", \
+                                            'SFC', '1', self.grid]
+
+            self.params['OG__ML'] = ['T/Q', 'ML', self.levelist, self.grid]
+
+            #if c.gauss == '0' and c.eta == '1':
+            if not c.gauss and c.eta:
+                # the simplest case
+                self.params['OG__ML'][0] += '/U/V/77'
+            #elif c.gauss == '0' and c.eta == '0':
+            elif not c.gauss and not c.eta:
+            # this is not recommended (inaccurate)
+                self.params['OG__ML'][0] += '/U/V'
+            #elif c.gauss == '1' and c.eta == '0':
+            elif c.gauss and not c.eta:
+                # this is needed for data before 2008, or for reanalysis data
+                self.params['GG__SL'] = ['Q', 'ML', '1', \
+                                         '{}'.format((int(self.resol) + 1) / 2)]
+                self.params['SH__ML'] = ['U/V/D', 'ML', self.glevelist, 'OFF']
+            else:
+                print('Warning: This is a very costly parameter combination, \
+                      use only for debugging!')
+                self.params['GG__SL'] = ['Q', 'ML', '1', \
+                                         '{}'.format((int(self.resol) + 1) / 2)]
+                self.params['GG__ML'] = ['U/V/D/77', 'ML', self.glevelist, \
+                                         '{}'.format((int(self.resol) + 1) / 2)]
+
+            if c.omega:
+                self.params['OG__ML'][0] += '/W'
+
+            # add cloud water content if necessary
+            if c.cwc:
+                self.params['OG__ML'][0] += '/CLWC/CIWC'
+
+            # add vorticity and geopotential height for WRF if necessary
+            if c.wrf:
+                self.params['OG__ML'][0] += '/Z/VO'
+                if '/D' not in self.params['OG__ML'][0]:
+                    self.params['OG__ML'][0] += '/D'
+                #wrf_sfc = 'sp/msl/skt/2t/10u/10v/2d/z/lsm/sst/ci/sd/stl1/ /
+                #           stl2/stl3/stl4/swvl1/swvl2/swvl3/swvl4'.upper()
+                wrf_sfc = '134/235/167/165/166/168/129/172/34/31/141/ \
+                           139/170/183/236/39/40/41/42'.upper()
+                lwrt_sfc = wrf_sfc.split('/')
+                for par in lwrt_sfc:
+                    if par not in self.params['OG__SL'][0]:
+                        self.params['OG__SL'][0] += '/' + par
+
+        else:
+            self.params['OG_acc_SL'] = ["LSP/CP/SSHF/EWSS/NSSS/SSR", \
+                                        'SFC', '1', self.grid]
+
+        # if needed, add additional WRF specific parameters here
+
+        return
+
+
+    def write_namelist(self, c, filename):
+        '''
+        @Description:
+            Creates a namelist file in the temporary directory and writes
+            the following values to it: maxl, maxb, mlevel,
+            mlevelist, mnauf, metapar, rlo0, rlo1, rla0, rla1,
+            momega, momegadiff, mgauss, msmooth, meta, metadiff, mdpdeta
+
+        @Input:
+            self: instance of EcFlexpart
+                The current object of the class.
+
+            c: instance of class ControlFile
+                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.
+
+            filename: string
+                Name of the namelist file.
+
+        @Return:
+            <nothing>
+        '''
+
+        self.inputdir = c.inputdir
+        area = np.asarray(self.area.split('/')).astype(float)
+        grid = np.asarray(self.grid.split('/')).astype(float)
+
+        if area[1] > area[3]:
+            area[1] -= 360
+        maxl = int((area[3] - area[1]) / grid[1]) + 1
+        maxb = int((area[0] - area[2]) / grid[0]) + 1
+
+        with open(self.inputdir + '/' + filename, 'w') as f:
+            f.write('&NAMGEN\n')
+            f.write(',\n  '.join(['maxl = ' + str(maxl), 'maxb = ' + str(maxb),
+                                  'mlevel = ' + str(self.level),
+                                  'mlevelist = ' + '"' + str(self.levelist)
+                                                 + '"',
+                                  'mnauf = ' + str(self.resol),
+                                  'metapar = ' + '77',
+                                  'rlo0 = ' + str(area[1]),
+                                  'rlo1 = ' + str(area[3]),
+                                  'rla0 = ' + str(area[2]),
+                                  'rla1 = ' + str(area[0]),
+                                  'momega = ' + str(c.omega),
+                                  'momegadiff = ' + str(c.omegadiff),
+                                  'mgauss = ' + str(c.gauss),
+                                  'msmooth = ' + str(c.smooth),
+                                  'meta = ' + str(c.eta),
+                                  'metadiff = ' + str(c.etadiff),
+                                  'mdpdeta = ' + str(c.dpdeta)]))
+
+            f.write('\n/\n')
+
+        return
+
+    def retrieve(self, server, dates, request, inputdir='.'):
+        '''
+        @Description:
+            Finalizing the retrieval information by setting final details
+            depending on grid type.
+            Prepares MARS retrievals per grid type and submits them.
+
+        @Input:
+            self: instance of EcFlexpart
+                The current object of the class.
+
+            server: instance of ECMWFService or ECMWFDataServer
+                The connection to the ECMWF server. This is different
+                for member state users which have full access and non
+                member state users which have only access to the public
+                data sets. The decision is made from command line argument
+                "public"; for public access its True (ECMWFDataServer)
+                for member state users its False (ECMWFService)
+
+            dates: string
+                Contains start and end date of the retrieval in the format
+                "YYYYMMDD/to/YYYYMMDD"
+
+            inputdir: string, optional
+                Path to the directory where the retrieved data is about
+                to be stored. The default is the current directory ('.').
+
+        @Return:
+            <nothing>
+        '''
+        self.dates = dates
+        self.server = server
+        self.inputdir = inputdir
+        oro = False
+
+        for ftype in self.types:
+            for pk, pv in self.params.iteritems():
+                if isinstance(pv, str):
+                    continue
+                mftype = '' + ftype
+                mftime = self.types[ftype]['times']
+                mfstep = self.types[ftype]['steps']
+                mfdate = self.dates
+                mfstream = self.stream
+                mftarget = self.inputdir + "/" + ftype + pk + '.' + \
+                           self.dates.split('/')[0] + '.' + str(os.getppid()) +\
+                           '.' + str(os.getpid()) + ".grb"
+                if pk == 'OG__SL':
+                    pass
+                if pk == 'OG_OROLSM__SL':
+                    if not oro:
+                        mfstream = 'OPER'
+                        mftype = 'AN'
+                        mftime = '00'
+                        mfstep = '000'
+                        mfdate = self.dates.split('/')[0]
+                        mftarget = self.inputdir + "/" + pk + '.' + mfdate + \
+                                   '.' + str(os.getppid()) + '.' + \
+                                   str(os.getpid()) + ".grb"
+                        oro = True
+                    else:
+                        continue
+                if pk == 'GG__SL' and pv[0] == 'Q':
+                    area = ""
+                    gaussian = 'reduced'
+                else:
+                    area = self.area
+                    gaussian = self.gaussian
+
+    # ------  on demand path  --------------------------------------------------
+                if not self.basetime:
+                    MR = MarsRetrieval(self.server,
+                                       marsclass=self.marsclass,
+                                       stream=mfstream,
+                                       type=mftype,
+                                       levtype=pv[1],
+                                       levelist=pv[2],
+                                       resol=self.resol,
+                                       gaussian=gaussian,
+                                       accuracy=self.accuracy,
+                                       grid=pv[3],
+                                       target=mftarget,
+                                       area=area,
+                                       date=mfdate,
+                                       time=mftime,
+                                       number=self.number,
+                                       step=mfstep,
+                                       expver=self.expver,
+                                       param=pv[0])
+
+                    if request == 0:
+                        MR.display_info()
+                        MR.data_retrieve()
+                    elif request == 1:
+                        MR.print_info(self.inputdir)
+                    elif request == 2:
+                        MR.print_info(self.inputdir)
+                        MR.display_info()
+                        MR.data_retrieve()
+                    else:
+                        print('Failure')
+    # ------  operational path  ------------------------------------------------
+                else:
+                    # check if mars job requests fields beyond basetime.
+                    # If yes eliminate those fields since they may not
+                    # be accessible with user's credentials
+                    if 'by' in mfstep:
+                        sm1 = 2
+                    else:
+                        sm1 = -1
+
+                    if 'by' in mftime:
+                        tm1 = 2
+                    else:
+                        tm1 = -1
+
+                    maxdate = datetime.strptime(mfdate.split('/')[-1] +
+                                                mftime.split('/')[tm1],
+                                                '%Y%m%d%H')
+                    istep = int(mfstep.split('/')[sm1])
+                    maxtime = maxdate + timedelta(hours=istep)
+
+                    elimit = datetime.strptime(mfdate.split('/')[-1] +
+                                               self.basetime, '%Y%m%d%H')
+
+                    if self.basetime == '12':
+                        # --------------  flux data ----------------------------
+                        if 'acc' in pk:
+
+                        # Strategy:
+                        # if maxtime-elimit >= 24h reduce date by 1,
+                        # if 12h <= maxtime-elimit<12h reduce time for last date
+                        # if maxtime-elimit<12h reduce step for last time
+                        # A split of the MARS job into 2 is likely necessary.
+                            maxtime = elimit - timedelta(hours=24)
+                            mfdate = '/'.join(['/'.join(mfdate.split('/')[:-1]),
+                                               datetime.strftime(maxtime,
+                                                                 '%Y%m%d')])
+
+                            MR = MarsRetrieval(self.server,
+                                               marsclass=self.marsclass,
+                                               stream=self.stream,
+                                               type=mftype,
+                                               levtype=pv[1],
+                                               levelist=pv[2],
+                                               resol=self.resol,
+                                               gaussian=gaussian,
+                                               accuracy=self.accuracy,
+                                               grid=pv[3],
+                                               target=mftarget,
+                                               area=area,
+                                               date=mfdate,
+                                               time=mftime,
+                                               number=self.number,
+                                               step=mfstep,
+                                               expver=self.expver,
+                                               param=pv[0])
+
+                            MR.display_info()
+                            MR.data_retrieve()
+
+                            maxtime = elimit - timedelta(hours=12)
+                            mfdate = datetime.strftime(maxtime, '%Y%m%d')
+                            mftime = '00'
+                            mftarget = self.inputdir + "/" + ftype + pk + \
+                                       '.' + mfdate + '.' + str(os.getppid()) +\
+                                       '.' + str(os.getpid()) + ".grb"
+
+                            MR = MarsRetrieval(self.server,
+                                               marsclass=self.marsclass,
+                                               stream=self.stream,
+                                               type=mftype,
+                                               levtype=pv[1],
+                                               levelist=pv[2],
+                                               resol=self.resol,
+                                               gaussian=gaussian,
+                                               accuracy=self.accuracy,
+                                               grid=pv[3],
+                                               target=mftarget,
+                                               area=area,
+                                               date=mfdate,
+                                               time=mftime,
+                                               number=self.number,
+                                               step=mfstep,
+                                               expver=self.expver,
+                                               param=pv[0])
+
+                            MR.display_info()
+
+                            MR.data_retrieve()
+                        # --------------  non flux data ------------------------
+                        else:
+                            MR = MarsRetrieval(self.server,
+                                               marsclass=self.marsclass,
+                                               stream=self.stream,
+                                               type=mftype,
+                                               levtype=pv[1],
+                                               levelist=pv[2],
+                                               resol=self.resol,
+                                               gaussian=gaussian,
+                                               accuracy=self.accuracy,
+                                               grid=pv[3],
+                                               target=mftarget,
+                                               area=area,
+                                               date=mfdate,
+                                               time=mftime,
+                                               number=self.number,
+                                               step=mfstep,
+                                               expver=self.expver,
+                                               param=pv[0])
+
+                            MR.display_info()
+                            MR.data_retrieve()
+                    else: # basetime == 0 ??? #AP
+
+                        maxtime = elimit - timedelta(hours=24)
+                        mfdate = datetime.strftime(maxtime, '%Y%m%d')
+                        mftimesave = ''.join(mftime)
+
+                        if '/' in mftime:
+                            times = mftime.split('/')
+                            while ((int(times[0]) +
+                                    int(mfstep.split('/')[0]) <= 12) and
+                                   (pk != 'OG_OROLSM__SL') and 'acc' not in pk):
+                                times = times[1:]
+                            if len(times) > 1:
+                                mftime = '/'.join(times)
+                            else:
+                                mftime = times[0]
+
+                        MR = MarsRetrieval(self.server,
+                                           marsclass=self.marsclass,
+                                           stream=self.stream,
+                                           type=mftype,
+                                           levtype=pv[1],
+                                           levelist=pv[2],
+                                           resol=self.resol,
+                                           gaussian=gaussian,
+                                           accuracy=self.accuracy,
+                                           grid=pv[3],
+                                           target=mftarget,
+                                           area=area,
+                                           date=mfdate,
+                                           time=mftime,
+                                           number=self.number,
+                                           step=mfstep,
+                                           expver=self.expver,
+                                           param=pv[0])
+
+                        MR.display_info()
+                        MR.data_retrieve()
+
+                        if (int(mftimesave.split('/')[0]) == 0 and
+                                int(mfstep.split('/')[0]) == 0 and
+                                pk != 'OG_OROLSM__SL'):
+
+                            mfdate = datetime.strftime(elimit, '%Y%m%d')
+                            mftime = '00'
+                            mfstep = '000'
+                            mftarget = self.inputdir + "/" + ftype + pk + \
+                                       '.' + mfdate + '.' + str(os.getppid()) +\
+                                       '.' + str(os.getpid()) + ".grb"
+
+                            MR = MarsRetrieval(self.server,
+                                               marsclass=self.marsclass,
+                                               stream=self.stream,
+                                               type=mftype,
+                                               levtype=pv[1],
+                                               levelist=pv[2],
+                                               resol=self.resol,
+                                               gaussian=gaussian,
+                                               accuracy=self.accuracy,
+                                               grid=pv[3],
+                                               target=mftarget,
+                                               area=area,
+                                               date=mfdate,
+                                               time=mftime,
+                                               number=self.number,
+                                               step=mfstep,
+                                               expver=self.expver,
+                                               param=pv[0])
+
+                            MR.display_info()
+                            MR.data_retrieve()
+
+        if request == 0 or request == 2:
+            print('MARS retrieve done ... ')
+        elif request == 1:
+            print('MARS request printed ...')
+
+        return
+
+
+    def process_output(self, c):
+        '''
+        @Description:
+            The grib files are postprocessed depending on the selection in
+            CONTROL file. The resulting files are moved to the output
+            directory if its not equla to the input directory.
+            The following modifications might be done if
+            properly switched in CONTROL file:
+            GRIB2 - Conversion to GRIB2
+            ECTRANS - Transfer of files to gateway server
+            ECSTORAGE - Storage at ECMWF server
+            GRIB2FLEXPART - Conversion of GRIB files to FLEXPART binary format
+
+        @Input:
+            self: instance of EcFlexpart
+                The current object of the class.
+
+            c: instance of class ControlFile
+                Contains all the parameters of CONTROL file, 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.
+
+        @Return:
+            <nothing>
+
+        '''
+
+        print('\n\nPostprocessing:\n Format: {}\n'.format(c.format))
+
+        if not c.ecapi:
+            print('ecstorage: {}\n ecfsdir: {}\n'.
+                  format(c.ecstorage, c.ecfsdir))
+            #if not hasattr(c, 'gateway'):
+            #    c.gateway = os.getenv('GATEWAY')
+            #if not hasattr(c, 'destination'):
+            #    c.destination = os.getenv('DESTINATION')
+            print('ectrans: {}\n gateway: {}\n destination: {}\n '
+                  .format(c.ectrans, c.gateway, c.destination))
+
+        print('Output filelist: \n')
+        print(self.outputfilelist)
+
+        if c.format.lower() == 'grib2':
+            for ofile in self.outputfilelist:
+                p = subprocess.check_call(['grib_set', '-s', 'edition=2, \
+                                           productDefinitionTemplateNumber=8',
+                                           ofile, ofile + '_2'])
+                p = subprocess.check_call(['mv', ofile + '_2', ofile])
+
+        if c.ectrans and not c.ecapi:
+            for ofile in self.outputfilelist:
+                p = subprocess.check_call(['ectrans', '-overwrite', '-gateway',
+                                           c.gateway, '-remote', c.destination,
+                                           '-source', ofile])
+                #print('ectrans:', p)
+
+        if c.ecstorage and not c.ecapi:
+            for ofile in self.outputfilelist:
+                p = subprocess.check_call(['ecp', '-o', ofile,
+                                           os.path.expandvars(c.ecfsdir)])
+
+        if c.outputdir != c.inputdir:
+            for ofile in self.outputfilelist:
+                p = subprocess.check_call(['mv', ofile, c.outputdir])
+
+        # prepare environment for the grib2flexpart run
+        # to convert grib to flexpart binary
+        if c.grib2flexpart:
+
+            # generate AVAILABLE file
+            # Example of AVAILABLE file data:
+            # 20131107 000000      EN13110700              ON DISC
+            clist = []
+            for ofile in self.outputfilelist:
+                fname = ofile.split('/')
+                if '.' in fname[-1]:
+                    l = fname[-1].split('.')
+                    timestamp = datetime.strptime(l[0][-6:] + l[1],
+                                                  '%y%m%d%H')
+                    timestamp += timedelta(hours=int(l[2]))
+                    cdate = datetime.strftime(timestamp, '%Y%m%d')
+                    chms = datetime.strftime(timestamp, '%H%M%S')
+                else:
+                    cdate = '20' + fname[-1][-8:-2]
+                    chms = fname[-1][-2:] + '0000'
+                clist.append(cdate + ' ' + chms + ' '*6 +
+                             fname[-1] + ' '*14 + 'ON DISC')
+            clist.sort()
+            with open(c.outputdir + '/' + 'AVAILABLE', 'w') as f:
+                f.write('\n'.join(clist) + '\n')
+
+            # generate pathnames file
+            pwd = os.path.abspath(c.outputdir)
+            with open(pwd + '/pathnames', 'w') as f:
+                f.write(pwd + '/Options/\n')
+                f.write(pwd + '/\n')
+                f.write(pwd + '/\n')
+                f.write(pwd + '/AVAILABLE\n')
+                f.write(' = == = == = == = == = == ==  = \n')
+
+            # create Options dir if necessary
+            if not os.path.exists(pwd + '/Options'):
+                os.makedirs(pwd+'/Options')
+
+            # read template COMMAND file
+            with open(os.path.expandvars(os.path.expanduser(
+                c.flexpart_root_scripts)) + '/../Options/COMMAND', 'r') as f:
+                lflist = f.read().split('\n')
+
+            # find index of list where to put in the
+            # date and time information
+            # usually after the LDIRECT parameter
+            i = 0
+            for l in lflist:
+                if 'LDIRECT' in l.upper():
+                    break
+                i += 1
+
+            # insert the date and time information of run start and end
+            # into the list of lines of COMMAND file
+            lflist = lflist[:i+1] + \
+                     [clist[0][:16], clist[-1][:16]] + \
+                     lflist[i+3:]
+
+            # write the new COMMAND file
+            with open(pwd + '/Options/COMMAND', 'w') as g:
+                g.write('\n'.join(lflist) + '\n')
+
+            # change to outputdir and start the grib2flexpart run
+            # afterwards switch back to the working dir
+            os.chdir(c.outputdir)
+            p = subprocess.check_call([
+                os.path.expandvars(os.path.expanduser(c.flexpart_root_scripts))
+                + '/../FLEXPART_PROGRAM/grib2flexpart', 'useAvailable', '.'])
+            os.chdir(pwd)
+
+        return
+
+    def create(self, inputfiles, c):
+        '''
+        @Description:
+            This method is based on the ECMWF example index.py
+            https://software.ecmwf.int/wiki/display/GRIB/index.py
+
+            An index file will be created which depends on the combination
+            of "date", "time" and "stepRange" values. This is used to iterate
+            over all messages in each grib file which were passed through the
+            parameter "inputfiles" to seperate specific parameters into fort.*
+            files. Afterwards the FORTRAN program Convert2 is called to convert
+            the data fields all to the same grid and put them in one file
+            per unique time step (combination of "date", "time" and
+            "stepRange").
+
+        @Input:
+            self: instance of EcFlexpart
+                The current object of the class.
+
+            inputfiles: instance of UioFiles
+                Contains a list of files.
+
+            c: instance of class ControlFile
+                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.
+
+        @Return:
+            <nothing>
+        '''
+
+        table128 = init128(_config.PATH_GRIBTABLE)
+        wrfpars = to_param_id('sp/mslp/skt/2t/10u/10v/2d/z/lsm/sst/ci/sd/\
+                            stl1/stl2/stl3/stl4/swvl1/swvl2/swvl3/swvl4',
+                            table128)
+
+        index_keys = ["date", "time", "step"]
+        indexfile = os.path.join(c.inputdir, _config.FILE_GRIB_INDEX)
+        silent_remove(indexfile)
+        grib = GribTools(inputfiles.files)
+        # creates new index file
+        iid = grib.index(index_keys=index_keys, index_file=indexfile)
+
+        # read values of index keys
+        index_vals = []
+        for key in index_keys:
+            index_vals.append(grib_index_get(iid, key))
+            print(index_vals[-1])
+            # index_vals looks for example like:
+            # index_vals[0]: ('20171106', '20171107', '20171108') ; date
+            # index_vals[1]: ('0', '1200', '1800', '600') ; time
+            # index_vals[2]: ('0', '12', '3', '6', '9') ; stepRange
+
+        fdict = {'10':None, '11':None, '12':None, '13':None, '16':None,
+                 '17':None, '19':None, '21':None, '22':None, '20':None}
+
+        for prod in product(*index_vals):
+            # e.g. prod = ('20170505', '0', '12')
+            #             (  date    ,time, step)
+            # per date e.g. time = 0, 1200
+            # per time e.g. step = 3, 6, 9, 12
+            # flag for Fortran program CONVERT2 and file merging
+            convertFlag = False
+            print('current prod: ', prod)
+            # e.g. prod = ('20170505', '0', '12')
+            #             (  date    ,time, step)
+            # per date e.g. time = 0, 600, 1200, 1800
+            # per time e.g. step = 0, 3, 6, 9, 12
+            for i in range(len(index_keys)):
+                grib_index_select(iid, index_keys[i], prod[i])
+
+            # get first id from current product
+            gid = grib_new_from_index(iid)
+
+            # if there is data for this product combination
+            # prepare some date and time parameter before reading the data
+            if gid is not None:
+                # Combine all temporary data files into final grib file if
+                # gid is at least one time not None. Therefore set convertFlag
+                # to save information. The fortran program CONVERT2 is also
+                # only done if convertFlag is True
+                convertFlag = True
+                # remove old fort.* files and open new ones
+                # they are just valid for a single product
+                for k, f in fdict.iteritems():
+                    fortfile = os.path.join(c.inputdir, 'fort.' + k)
+                    silent_remove(fortfile)
+                    fdict[k] = open(fortfile, 'w')
+
+                cdate = str(grib_get(gid, 'date'))
+                time = grib_get(gid, 'time')
+                step = grib_get(gid, 'step')
+                # create correct timestamp from the three time informations
+                # date, time, step
+                timestamp = datetime.strptime(cdate + '{:0>2}'.format(time/100),
+                                              '%Y%m%d%H')
+                timestamp += timedelta(hours=int(step))
+                cdateH = datetime.strftime(timestamp, '%Y%m%d%H')
+
+                if c.basetime is not None:
+                    slimit = datetime.strptime(c.start_date + '00', '%Y%m%d%H')
+                    bt = '23'
+                    if c.basetime == '00':
+                        bt = '00'
+                        slimit = datetime.strptime(c.end_date + bt, '%Y%m%d%H')\
+                            - timedelta(hours=12-int(c.dtime))
+                    if c.basetime == '12':
+                        bt = '12'
+                        slimit = datetime.strptime(c.end_date + bt, '%Y%m%d%H')\
+                            - timedelta(hours=12-int(c.dtime))
+
+                    elimit = datetime.strptime(c.end_date + bt, '%Y%m%d%H')
+
+                    if timestamp < slimit or timestamp > elimit:
+                        continue
+            else:
+                pass
+
+            try:
+                if c.wrf:
+                    if 'olddate' not in locals() or cdate != olddate:
+                        fwrf = open(os.path.join(c.outputdir,
+                                    'WRF' + cdate + '.{:0>2}'.format(time) +
+                                    '.000.grb2'), 'w')
+                        olddate = cdate[:]
+            except AttributeError:
+                pass
+
+            # helper variable to remember which fields were already used.
+            savedfields = []
+            while 1:
+                if gid is None:
+                    break
+                paramId = grib_get(gid, 'paramId')
+                gridtype = grib_get(gid, 'gridType')
+                levtype = grib_get(gid, 'typeOfLevel')
+                if paramId == 133 and gridtype == 'reduced_gg':
+                # Specific humidity (Q.grb) is used as a template only
+                # so we need the first we "meet"
+                    with open(os.path.join(c.inputdir, 'fort.18'), 'w') as fout:
+                        grib_write(gid, fout)
+                elif paramId == 131 or paramId == 132:
+                    grib_write(gid, fdict['10'])
+                elif paramId == 130:
+                    grib_write(gid, fdict['11'])
+                elif paramId == 133 and gridtype != 'reduced_gg':
+                    grib_write(gid, fdict['17'])
+                elif paramId == 152:
+                    grib_write(gid, fdict['12'])
+                elif paramId == 155 and gridtype == 'sh':
+                    grib_write(gid, fdict['13'])
+                elif  paramId in [129, 138, 155] and levtype == 'hybrid' \
+                        and c.wrf:
+                    pass
+                elif paramId == 246 or paramId == 247:
+                    # cloud liquid water and ice
+                    if paramId == 246:
+                        clwc = grib_get_values(gid)
+                    else:
+                        clwc += grib_get_values(gid)
+                        grib_set_values(gid, clwc)
+                        grib_set(gid, 'paramId', 201031)
+                        grib_write(gid, fdict['22'])
+                elif paramId == 135:
+                    grib_write(gid, fdict['19'])
+                elif paramId == 77:
+                    grib_write(gid, fdict['21'])
+                else:
+                    if paramId not in savedfields:
+                        grib_write(gid, fdict['16'])
+                        savedfields.append(paramId)
+                    else:
+                        print('duplicate ' + str(paramId) + ' not written')
+
+                try:
+                    if c.wrf:
+                        # model layer
+                        if levtype == 'hybrid' and \
+                           paramId in [129, 130, 131, 132, 133, 138, 155]:
+                            grib_write(gid, fwrf)
+                        # sfc layer
+                        elif paramId in wrfpars:
+                            grib_write(gid, fwrf)
+                except AttributeError:
+                    pass
+
+                grib_release(gid)
+                gid = grib_new_from_index(iid)
+
+            for f in fdict.values():
+                f.close()
+
+            # call for CONVERT2 if flag is True
+            if convertFlag:
+                pwd = os.getcwd()
+                os.chdir(c.inputdir)
+                if os.stat('fort.21').st_size == 0 and c.eta:
+                    print('Parameter 77 (etadot) is missing, most likely it is \
+                           not available for this type or date/time\n')
+                    print('Check parameters CLASS, TYPE, STREAM, START_DATE\n')
+                    my_error(c.mailfail, 'fort.21 is empty while parameter eta \
+                             is set to 1 in CONTROL file')
+
+                # create the corresponding output file fort.15
+                # (generated by CONVERT2) + fort.16 (paramId 167 and 168)
+                p = subprocess.check_call([os.path.join(c.exedir, 'CONVERT2')],
+                                          shell=True)
+                os.chdir(pwd)
+
+                # create final output filename, e.g. EN13040500 (ENYYMMDDHH)
+                fnout = os.path.join(c.inputdir, c.prefix)
+                if c.maxstep > 12:
+                    suffix = cdate[2:8] + '.{:0>2}'.format(time/100) + \
+                             '.{:0>3}'.format(step)
+                else:
+                    suffix = cdateH[2:10]
+                fnout += suffix
+                print("outputfile = " + fnout)
+                self.outputfilelist.append(fnout) # needed for final processing
+
+                # create outputfile and copy all data from intermediate files
+                # to the outputfile (final GRIB files)
+                orolsm = os.path.basename(glob.glob(
+                    c.inputdir + '/OG_OROLSM__SL.*.' + c.ppid + '*')[0])
+                fluxfile = 'flux' + cdate[0:2] + suffix
+                if not c.cwc:
+                    flist = ['fort.15', fluxfile, 'fort.16', orolsm]
+                else:
+                    flist = ['fort.15', 'fort.22', fluxfile, 'fort.16', orolsm]
+
+                with open(fnout, 'wb') as fout:
+                    for f in flist:
+                        shutil.copyfileobj(open(os.path.join(c.inputdir, f),
+                                                'rb'), fout)
+
+                if c.omega:
+                    with open(os.path.join(c.outputdir, 'OMEGA'), 'wb') as fout:
+                        shutil.copyfileobj(
+                            open(os.path.join(c.inputdir, 'fort.25'),
+                                 'rb'), fout)
+            else:
+                pass
+
+        if c.wrf:
+            fwrf.close()
+
+        grib_index_release(iid)
+
+        return
+
+    def deacc_fluxes(self, inputfiles, c):
+        '''
+        @Description:
+            Goes through all flux fields in ordered time and de-accumulate
+            the fields. Afterwards the fields are disaggregated in time.
+            Different versions of disaggregation is provided for rainfall
+            data (darain, modified linear) and the surface fluxes and
+            stress data (dapoly, cubic polynomial).
+
+        @Input:
+            self: instance of EcFlexpart
+                The current object of the class.
+
+            inputfiles: instance of UioFiles
+                Contains a list of files.
+
+            c: instance of class ControlFile
+                Contains all the parameters of CONTROL file, 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.
+
+        @Return:
+            <nothing>
+        '''
+
+        table128 = init128(_config.PATH_GRIBTABLE)
+        pars = to_param_id(self.params['OG_acc_SL'][0], table128)
+        index_keys = ["date", "time", "step"]
+        indexfile = os.path.join(c.inputdir, _config.FILE_GRIB_INDEX)
+        silent_remove(indexfile)
+        grib = GribTools(inputfiles.files)
+        # creates new index file
+        iid = grib.index(index_keys=index_keys, index_file=indexfile)
+
+        # read values of index keys
+        index_vals = []
+        for key in index_keys:
+            key_vals = grib_index_get(iid, key)
+            print(key_vals)
+            # have to sort the steps for disaggregation,
+            # therefore convert to int first
+            if key == 'step':
+                key_vals = [int(k) for k in key_vals]
+                key_vals.sort()
+                key_vals = [str(k) for k in key_vals]
+            index_vals.append(key_vals)
+            # index_vals looks for example like:
+            # index_vals[0]: ('20171106', '20171107', '20171108') ; date
+            # index_vals[1]: ('0', '1200') ; time
+            # index_vals[2]: (3', '6', '9', '12') ; stepRange
+
+        valsdict = {}
+        svalsdict = {}
+        stepsdict = {}
+        for p in pars:
+            valsdict[str(p)] = []
+            svalsdict[str(p)] = []
+            stepsdict[str(p)] = []
+
+        print('maxstep: ', c.maxstep)
+
+        for prod in product(*index_vals):
+            # e.g. prod = ('20170505', '0', '12')
+            #             (  date    ,time, step)
+            # per date e.g. time = 0, 1200
+            # per time e.g. step = 3, 6, 9, 12
+            print('current prod: ', prod)
+            for i in range(len(index_keys)):
+                grib_index_select(iid, index_keys[i], prod[i])
+
+            # get first id from current product
+            gid = grib_new_from_index(iid)
+
+            # if there is data for this product combination
+            # prepare some date and time parameter before reading the data
+            if gid is not None:
+                cdate = grib_get(gid, 'date')
+                time = grib_get(gid, 'time')
+                step = grib_get(gid, 'step')
+                # date+time+step-2*dtime
+                # (since interpolated value valid for step-2*dtime)
+                sdate = datetime(year=cdate/10000,
+                                 month=(cdate % 10000)/100,
+                                 day=(cdate % 100),
+                                 hour=time/100)
+                fdate = sdate + timedelta(hours=step-2*int(c.dtime))
+                sdates = sdate + timedelta(hours=step)
+                elimit = None
+            else:
+                break
+
+            if c.maxstep > 12:
+                fnout = os.path.join(c.inputdir, 'flux' +
+                                     sdate.strftime('%Y%m%d') +
+                                     '.{:0>2}'.format(time/100) +
+                                     '.{:0>3}'.format(step-2*int(c.dtime)))
+                gnout = os.path.join(c.inputdir, 'flux' +
+                                     sdate.strftime('%Y%m%d') +
+                                     '.{:0>2}'.format(time/100) +
+                                     '.{:0>3}'.format(step-int(c.dtime)))
+                hnout = os.path.join(c.inputdir, 'flux' +
+                                     sdate.strftime('%Y%m%d') +
+                                     '.{:0>2}'.format(time/100) +
+                                     '.{:0>3}'.format(step))
+            else:
+                fnout = os.path.join(c.inputdir, 'flux' +
+                                     fdate.strftime('%Y%m%d%H'))
+                gnout = os.path.join(c.inputdir, 'flux' +
+                                     (fdate + timedelta(hours=int(c.dtime))).
+                                     strftime('%Y%m%d%H'))
+                hnout = os.path.join(c.inputdir, 'flux' +
+                                     sdates.strftime('%Y%m%d%H'))
+
+            print("outputfile = " + fnout)
+            f_handle = open(fnout, 'w')
+            g_handle = open(gnout, 'w')
+            h_handle = open(hnout, 'w')
+
+            # read message for message and store relevant data fields
+            # data keywords are stored in pars
+            while 1:
+                if gid is None:
+                    break
+                cparamId = str(grib_get(gid, 'paramId'))
+                step = grib_get(gid, 'step')
+                atime = grib_get(gid, 'time')
+                ni = grib_get(gid, 'Ni')
+                nj = grib_get(gid, 'Nj')
+                if cparamId in valsdict.keys():
+                    values = grib_get_values(gid)
+                    vdp = valsdict[cparamId]
+                    svdp = svalsdict[cparamId]
+                    sd = stepsdict[cparamId]
+
+                    if cparamId == '142' or cparamId == '143':
+                        fak = 1. / 1000.
+                    else:
+                        fak = 3600.
+
+                    values = (np.reshape(values, (nj, ni))).flatten() / fak
+                    vdp.append(values[:])  # save the accumulated values
+                    if step <= int(c.dtime):
+                        svdp.append(values[:] / int(c.dtime))
+                    else:  # deaccumulate values
+                        svdp.append((vdp[-1] - vdp[-2]) / int(c.dtime))
+
+                    print(cparamId, atime, step, len(values),
+                          values[0], np.std(values))
+                    # save the 1/3-hourly or specific values
+                    # svdp.append(values[:])
+                    sd.append(step)
+                    # len(svdp) correspond to the time
+                    if len(svdp) >= 3:
+                        if len(svdp) > 3:
+                            if cparamId == '142' or cparamId == '143':
+                                values = disaggregation.darain(svdp)
+                            else:
+                                values = disaggregation.dapoly(svdp)
+
+                            if not (step == c.maxstep and c.maxstep > 12 \
+                                    or sdates == elimit):
+                                vdp.pop(0)
+                                svdp.pop(0)
+                        else:
+                            if c.maxstep > 12:
+                                values = svdp[1]
+                            else:
+                                values = svdp[0]
+
+                        grib_set_values(gid, values)
+                        if c.maxstep > 12:
+                            grib_set(gid, 'step', max(0, step-2*int(c.dtime)))
+                        else:
+                            grib_set(gid, 'step', 0)
+                            grib_set(gid, 'time', fdate.hour*100)
+                            grib_set(gid, 'date', fdate.year*10000 +
+                                     fdate.month*100+fdate.day)
+                        grib_write(gid, f_handle)
+
+                        if c.basetime is not None:
+                            elimit = datetime.strptime(c.end_date +
+                                                       c.basetime, '%Y%m%d%H')
+                        else:
+                            elimit = sdate + timedelta(2*int(c.dtime))
+
+                        # squeeze out information of last two steps contained
+                        # in svdp
+                        # if step+int(c.dtime) == c.maxstep and c.maxstep>12
+                        # or sdates+timedelta(hours = int(c.dtime))
+                        # >= elimit:
+                        # Note that svdp[0] has not been popped in this case
+
+                        if step == c.maxstep and c.maxstep > 12 or \
+                           sdates == elimit:
+
+                            values = svdp[3]
+                            grib_set_values(gid, values)
+                            grib_set(gid, 'step', 0)
+                            truedatetime = fdate + timedelta(hours=
+                                                             2*int(c.dtime))
+                            grib_set(gid, 'time', truedatetime.hour * 100)
+                            grib_set(gid, 'date', truedatetime.year * 10000 +
+                                     truedatetime.month * 100 +
+                                     truedatetime.day)
+                            grib_write(gid, h_handle)
+
+                            #values = (svdp[1]+svdp[2])/2.
+                            if cparamId == '142' or cparamId == '143':
+                                values = disaggregation.darain(list(reversed(svdp)))
+                            else:
+                                values = disaggregation.dapoly(list(reversed(svdp)))
+
+                            grib_set(gid, 'step', 0)
+                            truedatetime = fdate + timedelta(hours=int(c.dtime))
+                            grib_set(gid, 'time', truedatetime.hour * 100)
+                            grib_set(gid, 'date', truedatetime.year * 10000 +
+                                     truedatetime.month * 100 +
+                                     truedatetime.day)
+                            grib_set_values(gid, values)
+                            grib_write(gid, g_handle)
+
+                    grib_release(gid)
+
+                    gid = grib_new_from_index(iid)
+
+            f_handle.close()
+            g_handle.close()
+            h_handle.close()
+
+        grib_index_release(iid)
+
+        return
Index: source/python/classes/GribTools.py
===================================================================
--- source/python/classes/GribTools.py	(revision 25b14bea5de21f28364c210382513c1c9b792d61)
+++ source/python/classes/GribTools.py	(revision 25b14bea5de21f28364c210382513c1c9b792d61)
@@ -0,0 +1,318 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#*******************************************************************************
+# @Author: Anne Fouilloux (University of Oslo)
+#
+# @Date: July 2014
+#
+# @Change History:
+#   February 2018 - Anne Philipp (University of Vienna):
+#        - applied PEP8 style guide
+#        - added documentation
+#        - changed some naming
+#
+# @License:
+#    (C) Copyright 2014-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.
+#
+# @Class Description:
+#    The GRIB API provides all necessary tools to work directly with the
+#    grib files. Nevertheless, the GRIB API tools are very basic and are in
+#    direct connection with the grib files. This class provides some higher
+#    functions which apply a set of GRIB API tools together in the respective
+#    context. So, the class initially contains a list of grib files (their
+#    names) and the using program then applies the methods directly on the
+#    class objects without having to think about how the actual GRIB API
+#    tools have to be arranged.
+#
+# @Class Content:
+#    - __init__
+#    - get_keys
+#    - set_keys
+#    - copy
+#    - index
+#
+# @Class Attributes:
+#    - filenames
+#
+#*******************************************************************************
+
+# ------------------------------------------------------------------------------
+# MODULES
+# ------------------------------------------------------------------------------
+import os
+from gribapi import grib_new_from_file, grib_is_defined, grib_get, \
+                    grib_release, grib_set, grib_write, grib_index_read, \
+                    grib_index_new_from_file, grib_index_add_file,  \
+                    grib_index_write
+
+# ------------------------------------------------------------------------------
+# CLASS
+# ------------------------------------------------------------------------------
+class GribTools(object):
+    '''
+    Class for GRIB utilities (new methods) based on GRIB API
+    '''
+    # --------------------------------------------------------------------------
+    # CLASS FUNCTIONS
+    # --------------------------------------------------------------------------
+    def __init__(self, filenames):
+        '''
+        @Description:
+            Initialise an object of GribTools and assign a list
+            of filenames.
+
+        @Input:
+            filenames: list of strings
+                A list of filenames.
+
+        @Return:
+            <nothing>
+        '''
+
+        self.filenames = filenames
+
+        return
+
+
+    def get_keys(self, keynames, wherekeynames=[], wherekeyvalues=[]):
+        '''
+        @Description:
+            get keyvalues for a given list of keynames
+            a where statement can be given (list of key and list of values)
+
+        @Input:
+            keynames: list of strings
+                List of keynames.
+
+            wherekeynames: list of strings, optional
+                Default value is an empty list.
+
+            wherekeyvalues: list of strings, optional
+                Default value is an empty list.
+
+        @Return:
+            return_list: list of strings
+                List of keyvalues for given keynames.
+        '''
+
+        fileid = open(self.filenames, 'r')
+
+        return_list = []
+
+        while 1:
+            gid_in = grib_new_from_file(fileid)
+
+            if gid_in is None:
+                break
+
+            if len(wherekeynames) != len(wherekeyvalues):
+                raise Exception("Number of key values and key names must be \
+                                 the same. Give a value for each keyname!")
+
+            select = True
+            i = 0
+            for wherekey in wherekeynames:
+                if not grib_is_defined(gid_in, wherekey):
+                    raise Exception("where key was not defined")
+
+                select = (select and (str(wherekeyvalues[i]) ==
+                                      str(grib_get(gid_in, wherekey))))
+                i += 1
+
+            if select:
+                llist = []
+                for key in keynames:
+                    llist.extend([str(grib_get(gid_in, key))])
+                return_list.append(llist)
+
+            grib_release(gid_in)
+
+        fileid.close()
+
+        return return_list
+
+
+    def set_keys(self, fromfile, keynames, keyvalues, wherekeynames=[],
+                 wherekeyvalues=[], strict=False, filemode='w'):
+        '''
+        @Description:
+            Opens the file to read the grib messages and then write
+            them to a new output file. By default all messages are
+            written out. Also, the keyvalues of the passed list of
+            keynames are set or only those meeting the where statement.
+            (list of key and list of values).
+
+        @Input:
+            fromfile: string
+                Filename of the input file to read the grib messages from.
+
+            keynames: list of strings
+                List of keynames. Default is an empty list.
+
+            keyvalues: list of strings
+                List of keynames. Default is an empty list.
+
+            wherekeynames: list of strings, optional
+                Default value is an empty list.
+
+            wherekeyvalues: list of strings, optional
+                Default value is an empty list.
+
+            strict: boolean, optional
+                Decides if everything from keynames and keyvalues
+                is written out the grib file (False) or only those
+                meeting the where statement (True). Default is False.
+
+            filemode: string, optional
+                Sets the mode for the output file. Default is "w".
+
+        @Return:
+            <nothing>
+
+        '''
+        fout = open(self.filenames, filemode)
+        fin = open(fromfile)
+
+        while 1:
+            gid_in = grib_new_from_file(fin)
+
+            if gid_in is None:
+                break
+
+            if len(wherekeynames) != len(wherekeyvalues):
+                raise Exception("Give a value for each keyname!")
+
+            select = True
+            i = 0
+            for wherekey in wherekeynames:
+                if not grib_is_defined(gid_in, wherekey):
+                    raise Exception("where Key was not defined")
+
+                select = (select and (str(wherekeyvalues[i]) ==
+                                      str(grib_get(gid_in, wherekey))))
+                i += 1
+
+            if select:
+                i = 0
+                for key in keynames:
+                    grib_set(gid_in, key, keyvalues[i])
+                    i += 1
+
+            grib_write(gid_in, fout)
+
+            grib_release(gid_in)
+
+        fin.close()
+        fout.close()
+
+        return
+
+    def copy(self, filename_in, selectWhere=True,
+             keynames=[], keyvalues=[], filemode='w'):
+        '''
+        Add the content of another input grib file to the objects file but
+        only messages corresponding to keys/values passed to the function.
+        The selectWhere switch decides if to copy the keys equal to (True) or
+        different to (False) the keynames/keyvalues list passed to the function.
+
+        @Input:
+            filename_in: string
+                Filename of the input file to read the grib messages from.
+
+            selectWhere: boolean, optional
+                Decides if to copy the keynames and values equal to (True) or
+                different to (False) the keynames/keyvalues list passed to the
+                function. Default is True.
+
+            keynames: list of strings, optional
+                List of keynames. Default is an empty list.
+
+            keyvalues: list of strings, optional
+                List of keynames. Default is an empty list.
+
+            filemode: string, optional
+                Sets the mode for the output file. Default is "w".
+
+        @Return:
+            <nothing>
+        '''
+
+        fin = open(filename_in)
+        fout = open(self.filenames, filemode)
+
+        while 1:
+            gid_in = grib_new_from_file(fin)
+
+            if gid_in is None:
+                break
+
+            if len(keynames) != len(keyvalues):
+                raise Exception("Give a value for each keyname!")
+
+            select = True
+            i = 0
+            for key in keynames:
+                if not grib_is_defined(gid_in, key):
+                    raise Exception("Key was not defined")
+
+                if selectWhere:
+                    select = (select and (str(keyvalues[i]) ==
+                                          str(grib_get(gid_in, key))))
+                else:
+                    select = (select and (str(keyvalues[i]) !=
+                                          str(grib_get(gid_in, key))))
+                i += 1
+
+            if select:
+                grib_write(gid_in, fout)
+
+            grib_release(gid_in)
+
+        fin.close()
+        fout.close()
+
+        return
+
+    def index(self, index_keys=["mars"], index_file="my.idx"):
+        '''
+        @Description:
+            Create index file from a list of files if it does not exist or
+            read an index file.
+
+        @Input:
+            index_keys: list of strings, optional
+                Contains the list of key parameter names from
+                which the index is to be created.
+                Default is a list with a single entry string "mars".
+
+            index_file: string, optional
+                Filename where the indices are stored.
+                Default is "my.idx".
+
+        @Return:
+            iid: integer
+                Grib index id.
+        '''
+        print("... index will be done")
+        iid = None
+
+        if os.path.exists(index_file):
+            iid = grib_index_read(index_file)
+            print("Use existing index file: %s " % (index_file))
+        else:
+            for filename in self.filenames:
+                print("Inputfile: %s " % (filename))
+                if iid is None:
+                    iid = grib_index_new_from_file(filename, index_keys)
+                else:
+                    grib_index_add_file(iid, filename)
+
+            if iid is not None:
+                grib_index_write(iid, index_file)
+
+        print('... index done')
+
+        return iid
Index: source/python/classes/MarsRetrieval.py
===================================================================
--- source/python/classes/MarsRetrieval.py	(revision 25b14bea5de21f28364c210382513c1c9b792d61)
+++ source/python/classes/MarsRetrieval.py	(revision 25b14bea5de21f28364c210382513c1c9b792d61)
@@ -0,0 +1,433 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#*******************************************************************************
+# @Author: Anne Fouilloux (University of Oslo)
+#
+# @Date: October 2014
+#
+# @Change History:
+#
+#   November 2015 - Leopold Haimberger (University of Vienna):
+#        - optimized display_info
+#        - optimized data_retrieve and seperate between python and shell
+#          script call
+#
+#   February 2018 - Anne Philipp (University of Vienna):
+#        - applied PEP8 style guide
+#        - added documentation
+#        - applied some minor modifications in programming style/structure
+#
+# @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.
+#
+# @Class Description:
+#    A MARS revtrieval has a specific syntax with a selection of keywords and
+#    their corresponding values. This class provides the necessary functions
+#    by displaying the selected parameters and their values and the actual
+#    retrievement of the data through a mars request or a Python web api
+#    interface. The initialization already expects all the keyword values.
+#
+# @Class Content:
+#    - __init__
+#    - display_info
+#    - data_retrieve
+#
+# @Class Attributes:
+#    - server
+#    - marsclass
+#    - dtype
+#    - levtype
+#    - levelist
+#    - repres
+#    - date
+#    - resol
+#    - stream
+#    - area
+#    - time
+#    - step
+#    - expver
+#    - number
+#    - accuracy
+#    - grid
+#    - gaussian
+#    - target
+#    - param
+#
+#*******************************************************************************
+
+# ------------------------------------------------------------------------------
+# MODULES
+# ------------------------------------------------------------------------------
+import subprocess
+import os
+
+import _config
+# ------------------------------------------------------------------------------
+# CLASS
+# ------------------------------------------------------------------------------
+class MarsRetrieval(object):
+    '''
+    Class for submitting MARS retrievals.
+
+    A description of MARS keywords/arguments and examples of their
+    values can be found here:
+    https://software.ecmwf.int/wiki/display/UDOC/\
+                   Identification+keywords#Identificationkeywords-class
+
+    '''
+
+    def __init__(self, server, marsclass="ei", type="", levtype="",
+                 levelist="", repres="", date="", resol="", stream="",
+                 area="", time="", step="", expver="1", number="",
+                 accuracy="", grid="", gaussian="", target="",
+                 param=""):
+        '''
+        @Description:
+            Initialises the instance of the MarsRetrieval class and
+            defines and assigns a set of the necessary retrieval parameters
+            for the FLEXPART input data.
+            A description of MARS keywords/arguments, their dependencies
+            on each other and examples of their values can be found here:
+
+            https://software.ecmwf.int/wiki/display/UDOC/MARS+keywords
+
+        @Input:
+            self: instance of MarsRetrieval
+                For description see class documentation.
+
+            server: instance of ECMWFService (from ECMWF Web-API)
+                This is the connection to the ECMWF data servers.
+                It is needed for the pythonic access of ECMWF data.
+
+            marsclass: string, optional
+                Characterisation of dataset. E.g. EI (ERA-Interim),
+                E4 (ERA40), OD (Operational archive), ea (ERA5).
+                Default is the ERA-Interim dataset "ei".
+
+            type: string, optional
+                Determines the type of fields to be retrieved.
+                Selects between observations, images or fields.
+                Examples for fields: Analysis (an), Forecast (fc),
+                Perturbed Forecast (pf), Control Forecast (cf) and so on.
+                Default is an empty string.
+
+            levtype: string, optional
+                Denotes type of level. Has a direct implication on valid
+                levelist values!
+                E.g. model level (ml), pressure level (pl), surface (sfc),
+                potential vorticity (pv), potential temperature (pt)
+                and depth (dp).
+                Default is an empty string.
+
+            levelist: string, optional
+                Specifies the required levels. It has to have a valid
+                correspondence to the selected levtype.
+                Examples: model level: 1/to/137, pressure levels: 500/to/1000
+                Default is an empty string.
+
+            repres: string, optional
+                Selects the representation of the archived data.
+                E.g. sh - spherical harmonics, gg - Gaussian grid,
+                ll - latitude/longitude, ...
+                Default is an empty string.
+
+            date: string, optional
+                Specifies the Analysis date, the Forecast base date or
+                Observations date. Valid formats are:
+                Absolute as YYYY-MM-DD or YYYYMMDD.
+                Default is an empty string.
+
+            resol: string, optional
+                Specifies the desired triangular truncation of retrieved data,
+                before carrying out any other selected post-processing.
+                The default is automatic truncation (auto), by which the lowest
+                resolution compatible with the value specified in grid is
+                automatically selected for the retrieval.
+                Users wanting to perform post-processing from full spectral
+                resolution should specify Archived Value (av).
+                The following are examples of existing resolutions found in
+                the archive: 63, 106, 159, 213, 255, 319, 399, 511, 799 or 1279.
+                This keyword has no meaning/effect if the archived data is
+                not in spherical harmonics representation.
+                The best selection can be found here:
+                https://software.ecmwf.int/wiki/display/UDOC/\
+                      Retrieve#Retrieve-Truncationbeforeinterpolation
+                Default is an empty string.
+
+            stream: string, optional
+                Identifies the forecasting system used to generate the data.
+                E.g. oper (Atmospheric model), enfo (Ensemble forecats), ...
+                Default is an empty string.
+
+            area: string, optional
+                Specifies the desired sub-area of data to be extracted.
+                Areas can be defined to wrap around the globe.
+
+                Latitude values must be given as signed numbers, with:
+                    north latitudes (i.e. north of the equator)
+                        being positive (e.g: 40.5)
+                    south latitutes (i.e. south of the equator)
+                        being negative (e.g: -50.5)
+                Longtitude values must be given as signed numbers, with:
+                    east longitudes (i.e. east of the 0 degree meridian)
+                        being positive (e.g: 35.0)
+                    west longitudes (i.e. west of the 0 degree meridian)
+                        being negative (e.g: -20.5)
+
+                E.g.: North/West/South/East
+                Default is an empty string.
+
+            time: string, optional
+                Specifies the time of the data in hours and minutes.
+                Valid values depend on the type of data: Analysis time,
+                Forecast base time or First guess verification time
+                (all usually at synoptic hours: 00, 06, 12 and 18 ).
+                Observation time (any combination in hours and minutes is valid,
+                subject to data availability in the archive).
+                The syntax is HHMM or HH:MM. If MM is omitted it defaults to 00.
+                Default is an empty string.
+
+            step: string, optional
+                Specifies the forecast time step from forecast base time.
+                Valid values are hours (HH) from forecast base time. It also
+                specifies the length of the forecast which verifies at
+                First Guess time.
+                E.g. 1/3/6-hourly
+                Default is an empty string.
+
+            expver: string, optional
+                The version of the dataset. Each experiment is assigned a
+                unique code (version). Production data is assigned 1 or 2,
+                and experimental data in Operations 11, 12 ,...
+                Research or Member State's experiments have a four letter
+                experiment identifier.
+                Default is "1".
+
+            number: string, optional
+                Selects the member in ensemble forecast run. (Only then it
+                is necessary.) It has a different meaning depending on
+                the type of data.
+                E.g. Perturbed Forecasts: specifies the Ensemble forecast member
+                Default is an empty string.
+
+            accuracy: string, optional
+                Specifies the number of bits per value to be used in the
+                generated GRIB coded fields.
+                A positive integer may be given to specify the preferred number
+                of bits per packed value. This must not be greater than the
+                number of bits normally used for a Fortran integer on the
+                processor handling the request (typically 32 or 64 bit).
+                Within a compute request the accuracy of the original fields
+                can be passed to the result field by specifying accuracy=av.
+                Default is an empty string.
+
+            grid: string, optional
+                Specifies the output grid which can be either a Gaussian grid
+                or a Latitude/Longitude grid. MARS requests specifying
+                grid=av will return the archived model grid.
+
+                Lat/Lon grid: The grid spacing needs to be an integer
+                fraction of 90 degrees e.g. grid = 0.5/0.5
+
+                Gaussian grid: specified by a letter denoting the type of
+                Gaussian grid followed by an integer (the grid number)
+                representing the number of lines between the Pole and Equator,
+                e.g.
+                grid = F160 - full (or regular) Gaussian grid with
+                       160 latitude lines between the pole and equator
+                grid = N320 - ECMWF original reduced Gaussian grid with
+                       320 latitude lines between the pole and equator,
+                       see Reduced Gaussian Grids for grid numbers used at ECMWF
+                grid = O640 - ECMWF octahedral (reduced) Gaussian grid with
+                       640 latitude lines between the pole and equator
+                Default is an empty string.
+
+            gaussian: string, optional
+                This parameter is deprecated and should no longer be used.
+                Specifies the desired type of Gaussian grid for the output.
+                Valid Gaussian grids are quasi-regular (reduced) or regular.
+                Keyword gaussian can only be specified together with
+                keyword grid. Gaussian without grid has no effect.
+                Default is an empty string.
+
+            target: string, optional
+                Specifies a file into which data is to be written after
+                retrieval or manipulation. Path names should always be
+                enclosed in double quotes. The MARS client supports automatic
+                generation of multiple target files using MARS keywords
+                enclosed in square brackets [ ].  If the environment variable
+                MARS_MULTITARGET_STRICT_FORMAT is set to 1 before calling mars,
+                the keyword values will be used in the filename as shown by
+                the ecCodes GRIB tool grib_ls -m, e.g. with
+                MARS_MULTITARGET_STRICT_FORMAT set to 1 the keywords time,
+                expver and param will be formatted as 0600, 0001 and 129.128
+                rather than 600, 1 and 129.
+                Default is an empty string.
+
+            param: string, optional
+                Specifies the meteorological parameter.
+                The list of meteorological parameters in MARS is extensive.
+                Their availability is directly related to their meteorological
+                meaning and, therefore, the rest of directives specified
+                in the MARS request.
+                Meteorological parameters can be specified by their
+                GRIB code (param=130), their mnemonic (param=t) or
+                full name (param=temperature).
+                The list of parameter should be seperated by a "/"-sign.
+                E.g. 130/131/133
+                Default is an empty string.
+
+        @Return:
+            <nothing>
+        '''
+
+        self.server = server
+        self.marsclass = marsclass
+        self.type = type
+        self.levtype = levtype
+        self.levelist = levelist
+        self.repres = repres
+        self.date = date
+        self.resol = resol
+        self.stream = stream
+        self.area = area
+        self.time = time
+        self.step = step
+        self.expver = expver
+        self.number = number
+        self.accuracy = accuracy
+        self.grid = grid
+        self.gaussian = gaussian
+        self.target = target
+        self.param = param
+
+        return
+
+
+    def display_info(self):
+        '''
+        @Description:
+            Prints all class attributes and their values to the
+            standard output.
+
+        @Input:
+            self: instance of MarsRetrieval
+                For description see class documentation.
+
+        @Return:
+            <nothing>
+        '''
+        # Get all class attributes and their values as a dictionary
+        attrs = vars(self)
+
+        # iterate through all attributes and print them
+        # with their corresponding values
+        for item in attrs.items():
+            if item[0] in 'server':
+                pass
+            else:
+                print(item[0] + ': ' + str(item[1]))
+
+        return
+
+
+    def print_info(self, inputdir):
+        '''
+        @Description:
+            Prints all mars requests to an extra file for debugging and
+            information.
+
+        @Input:
+            self: instance of MarsRetrieval
+                For description see class documentation.
+
+            inputdir: string
+                The path where all data from the retrievals are stored.
+
+        @Return:
+            <nothing>
+        '''
+        # Get all class attributes and their values as a dictionary
+        attrs = vars(self)
+
+        # open a file to store all requests to
+        with open(os.path.join(inputdir,
+                               _config.FILE_MARS_REQUESTS), 'a') as f:
+            f.write('mars\n')
+            # iterate through all attributes and print them
+            # with their corresponding values
+            for item in attrs.items():
+                if item[0] in 'server':
+                    pass
+                else:
+                    f.write(item[0] + ': ' + str(item[1]) + '\n')
+            f.write('\n\n')
+
+        return
+
+    def data_retrieve(self):
+        '''
+        @Description:
+            Submits a MARS retrieval. Depending on the existence of
+            ECMWF Web-API it is submitted via Python or a
+            subprocess in the Shell. The parameter for the mars retrieval
+            are taken from the defined class attributes.
+
+        @Input:
+            self: instance of MarsRetrieval
+                For description see class documentation.
+
+        @Return:
+            <nothing>
+        '''
+        # Get all class attributes and their values as a dictionary
+        attrs = vars(self)
+
+        # convert the dictionary of attributes into a comma
+        # seperated list of attributes with their values
+        # needed for the retrieval call
+        s = 'ret'
+        for k, v in attrs.iteritems():
+            if k in 'server':
+                continue
+            if k == 'marsclass':
+                k = 'class'
+            if v == '':
+                continue
+            if k.lower() == 'target':
+                target = v
+            else:
+                s = s + ',' + k + '=' + str(v)
+
+        # MARS request via Python script
+        if self.server is not False:
+            try:
+                self.server.execute(s, target)
+            except:
+                print('MARS Request failed, \
+                      have you already registered at apps.ecmwf.int?')
+                raise IOError
+            if os.stat(target).st_size == 0:
+                print('MARS Request returned no data - please check request')
+                raise IOError
+        # MARS request via extra process in shell
+        else:
+            s += ',target = "' + target + '"'
+            p = subprocess.Popen(['mars'], stdin=subprocess.PIPE,
+                                 stdout=subprocess.PIPE,
+                                 stderr=subprocess.PIPE, bufsize=1)
+            pout = p.communicate(input=s)[0]
+            print(pout.decode())
+
+            if 'Some errors reported' in pout.decode():
+                print('MARS Request failed - please check request')
+                raise IOError
+
+            if os.stat(target).st_size == 0:
+                print('MARS Request returned no data - please check request')
+                raise IOError
+
+        return
Index: source/python/classes/UioFiles.py
===================================================================
--- source/python/classes/UioFiles.py	(revision 25b14bea5de21f28364c210382513c1c9b792d61)
+++ source/python/classes/UioFiles.py	(revision 25b14bea5de21f28364c210382513c1c9b792d61)
@@ -0,0 +1,159 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#*******************************************************************************
+# @Author: Anne Fouilloux (University of Oslo)
+#
+# @Date: October 2014
+#
+# @Change History:
+#
+#    November 2015 - Leopold Haimberger (University of Vienna):
+#        - modified method list_files to work with glob instead of listdir
+#        - added pattern search in method list_files
+#
+#    February 2018 - Anne Philipp (University of Vienna):
+#        - applied PEP8 style guide
+#        - added documentation
+#        - optimisation of method list_files since it didn't work correctly
+#          for sub directories
+#        - additional speed up of method list_files
+#        - modified the class so that it is initiated with a pattern instead
+#          of suffixes. Gives more precision in selection of files.
+#
+# @License:
+#    (C) Copyright 2014-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.
+#
+# @Class Decription:
+#    The class is for file manipulation. It is initiated with a regular
+#    expression pattern for this instance and can produce a list of Files
+#    from the given file pattern. These files can be deleted.
+#
+# @Class Content:
+#    - __init__
+#    - __str__
+#    - __list_files__
+#    - delete_files
+#
+# @Class Attributes:
+#    - pattern
+#    - files
+#
+#*******************************************************************************
+
+# ------------------------------------------------------------------------------
+# MODULES
+# ------------------------------------------------------------------------------
+import os
+import fnmatch
+
+# software specific module from flex_extract
+#import profiling
+from mods.tools import silent_remove, get_list_as_string
+
+# ------------------------------------------------------------------------------
+# CLASS
+# ------------------------------------------------------------------------------
+
+class UioFiles(object):
+    '''
+    Class to manipulate files. At initialisation it has the pattern
+    which stores a regular expression pattern for the files, the path
+    to the files and the files already.
+    '''
+    # --------------------------------------------------------------------------
+    # CLASS FUNCTIONS
+    # --------------------------------------------------------------------------
+    def __init__(self, path, pattern):
+        '''
+        @Description:
+            Assignes a specific pattern for these files.
+
+        @Input:
+            self: instance of UioFiles
+                Description see class documentation.
+
+            path: string
+                Directory where to list the files.
+
+            pattern: string
+                Regular expression pattern. For example: '*.grb'
+
+        @Return:
+            <nothing>
+        '''
+
+        self.path = path
+        self.pattern = pattern
+        self.files = []
+
+        self.__list_files__(self.path)
+
+        return
+
+    #@profiling.timefn
+    def __list_files__(self, path):
+        '''
+        @Description:
+            Lists all files in the directory with the matching
+            regular expression pattern.
+
+        @Input:
+            self: instance of UioFiles
+                Description see class documentation.
+
+            path: string
+                Path to the files.
+
+        @Return:
+            <nothing>
+        '''
+        # Get the absolute path
+        path = os.path.abspath(path)
+
+        # get all files in the dir and subdir as absolut path
+        for root, dirnames, filenames in os.walk(path):
+            for filename in fnmatch.filter(filenames, self.pattern):
+                self.files.append(os.path.join(root, filename))
+
+        return
+
+    def __str__(self):
+        '''
+        @Description:
+            Converts the list of files into a single string.
+            The entries are sepereated by "," sign.
+
+        @Input:
+            self: instance of UioFiles
+                Description see class documentation.
+
+        @Return:
+            files_string: string
+                The content of the list as a single string.
+        '''
+
+        filenames = [os.path.basename(f) for f in self.files]
+        files_string = get_list_as_string(filenames, concatenate_sign=', ')
+
+        return files_string
+
+    def delete_files(self):
+        '''
+        @Description:
+            Deletes the files.
+
+        @Input:
+            self: instance of UioFiles
+                Description see class documentation.
+
+        @Return:
+            <nothing>
+        '''
+
+        for old_file in self.files:
+            silent_remove(old_file)
+
+        return
Index: source/python/classes/__init__.py
===================================================================
--- source/python/classes/__init__.py	(revision 25b14bea5de21f28364c210382513c1c9b792d61)
+++ source/python/classes/__init__.py	(revision 25b14bea5de21f28364c210382513c1c9b792d61)
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#*******************************************************************************
+# @Author: Anne Philipp (University of Vienna)
+#
+# @Date: September 2018
+#
+# @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.
+#
+#*******************************************************************************
