diff --git a/python/ControlFile.py b/python/ControlFile.py
new file mode 100644
index 0000000000000000000000000000000000000000..89747570fa1550890e6c3d71bed2437a489252e3
--- /dev/null
+++ b/python/ControlFile.py
@@ -0,0 +1,266 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#************************************************************************
+# TODO AP
+# - write a test class
+#************************************************************************
+#*******************************************************************************
+# @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
+#
+# @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__
+#    - __str__
+#    - tolist
+#
+#*******************************************************************************
+
+# ------------------------------------------------------------------------------
+# MODULES
+# ------------------------------------------------------------------------------
+import os
+import inspect
+# software specific module from flex_extract
+import Tools
+
+# ------------------------------------------------------------------------------
+# CLASS
+# ------------------------------------------------------------------------------
+class ControlFile:
+    '''
+    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 and
+            assign all CONTROL file variables. Set default values if
+            parameter was not in CONTROL file.
+
+        @Input:
+            self: instance of ControlFile class
+                Description see class documentation.
+
+            filename: string
+                Name of CONTROL file.
+
+        @Return:
+            <nothing>
+        '''
+
+        # read whole CONTROL file
+        with open(filename) as f:
+            fdata = f.read().split('\n')
+
+        # go through every line and store parameter
+        # as class variable
+        for ldata in fdata:
+            data = ldata.split()
+            if len(data) > 1:
+                if 'm_' in data[0].lower():
+                    data[0] = data[0][2:]
+                if data[0].lower() == 'class':
+                    data[0] = 'marsclass'
+                if data[0].lower() == 'day1':
+                    data[0] = 'start_date'
+                if data[0].lower() == 'day2':
+                    data[0] = 'end_date'
+                if data[0].lower() == 'addpar':
+                    if '/' in data[1]:
+                        # remove leading '/' sign from addpar content
+                        if data[1][0] == '/':
+                            data[1] = data[1][1:]
+                        dd = data[1].split('/')
+                        data = [data[0]]
+                        for d in dd:
+                            data.append(d)
+                    pass
+                if len(data) == 2:
+                    if '$' in data[1]:
+                        setattr(self, data[0].lower(), data[1])
+                        while '$' in data[1]:
+                            i = data[1].index('$')
+                            j = data[1].find('{')
+                            k = data[1].find('}')
+                            var = os.getenv(data[1][j+1:k])
+                            if var is not None:
+                                data[1] = data[1][:i] + var + data[1][k+1:]
+                            else:
+                                Tools.myerror(None,
+                                              'Could not find variable ' +
+                                              data[1][j+1:k] +
+                                              ' while reading ' +
+                                              filename)
+                        setattr(self, data[0].lower() + '_expanded', data[1])
+                    else:
+                        if data[1].lower() != 'none':
+                            setattr(self, data[0].lower(), data[1])
+                        else:
+                            setattr(self, data[0].lower(), None)
+                elif len(data) > 2:
+                    setattr(self, data[0].lower(), (data[1:]))
+            else:
+                pass
+
+        # check a couple of necessary attributes if they contain values
+        # otherwise set default values
+        if not hasattr(self, 'start_date'):
+            self.start_date = None
+        if not hasattr(self, 'end_date'):
+            self.end_date = self.start_date
+        if not hasattr(self, 'accuracy'):
+            self.accuracy = 24
+        if not hasattr(self, 'omega'):
+            self.omega = '0'
+        if not hasattr(self, 'cwc'):
+            self.cwc = '0'
+        if not hasattr(self, 'omegadiff'):
+            self.omegadiff = '0'
+        if not hasattr(self, 'etadiff'):
+            self.etadiff = '0'
+        if not hasattr(self, 'levelist'):
+            if not hasattr(self, 'level'):
+                print('Warning: neither levelist nor level \
+                       specified in CONTROL file')
+            else:
+                self.levelist = '1/to/' + self.level
+        else:
+            if 'to' in self.levelist:
+                self.level = self.levelist.split('/')[2]
+            else:
+                self.level = self.levelist.split('/')[-1]
+
+        if not hasattr(self, 'maxstep'):
+            # find out maximum step
+            self.maxstep = 0
+            for s in self.step:
+                if int(s) > self.maxstep:
+                    self.maxstep = int(s)
+        else:
+            self.maxstep = int(self.maxstep)
+
+        if not hasattr(self, 'prefix'):
+            self.prefix = 'EN'
+        if not hasattr(self, 'makefile'):
+            self.makefile = None
+        if not hasattr(self, 'basetime'):
+            self.basetime = None
+        if not hasattr(self, 'date_chunk'):
+            self.date_chunk = '3'
+        if not hasattr(self, 'grib2flexpart'):
+            self.grib2flexpart = '0'
+
+        # script directory
+        self.ecmwfdatadir = os.path.dirname(os.path.abspath(inspect.getfile(
+            inspect.currentframe()))) + '/../'
+        # Fortran source directory
+        self.exedir = self.ecmwfdatadir + 'src/'
+
+        # FLEXPART directory
+        if not hasattr(self, 'flexpart_root_scripts'):
+            self.flexpart_root_scripts = self.ecmwfdatadir
+
+        return
+
+    def __str__(self):
+        '''
+        @Description:
+            Prepares a single string with all the comma seperated ControlFile
+            class attributes including their values.
+
+            Example:
+            {'kids': 0, 'name': 'Dog', 'color': 'Spotted',
+             'age': 10, 'legs': 2, 'smell': 'Alot'}
+
+        @Input:
+            self: instance of ControlFile class
+                Description see class documentation.
+
+        @Return:
+            string of ControlFile class attributes with their values
+        '''
+
+        attrs = vars(self)
+
+        return ', '.join("%s: %s" % item for item in attrs.items())
+
+    def tolist(self):
+        '''
+        @Description:
+            Just generates a list of strings containing the attributes and
+            assigned values except the attributes "_expanded", "exedir",
+            "ecmwfdatadir" and "flexpart_root_scripts".
+
+        @Input:
+            self: instance of 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".
+        '''
+
+        attrs = vars(self)
+        l = list()
+
+        for item in attrs.items():
+            if '_expanded' in item[0]:
+                pass
+            elif 'exedir' in item[0]:
+                pass
+            elif 'flexpart_root_scripts' in item[0]:
+                pass
+            elif 'ecmwfdatadir' in item[0]:
+                pass
+            else:
+                if type(item[1]) is list:
+                    stot = ''
+                    for s in item[1]:
+                        stot += s + ' '
+
+                    l.append("%s %s" % (item[0], stot))
+                else:
+                    l.append("%s %s" % item)
+
+        return sorted(l)