diff --git a/Documentation/html/Documentation/Api/Fortran/css/local.css b/Documentation/html/Documentation/Api/Fortran/css/local.css
index 8ab50bcaafa5878b1fc5e2440885d87aa94a70e9..44e3dec2a0085374d61777aa4ae8688a9aa6be15 100644
--- a/Documentation/html/Documentation/Api/Fortran/css/local.css
+++ b/Documentation/html/Documentation/Api/Fortran/css/local.css
@@ -101,9 +101,9 @@ body {
     }
 
     .hl pre a {
-	display: inline-block;
-	height: 4.5em;
-	margin: -4.5em 0 0;
+ display: inline-block;
+ height: 4.5em;
+ margin: -4.5em 0 0;
     }
     .codesum h3 {
       margin-top: 2px;
diff --git a/For_developers/Sphinx/Makefile b/For_developers/Sphinx/Makefile
index bf53c49044b0aecc72a6a5c9003041a86b879d54..47066bbf300cfcceb1bbbd678c676f38fcba92f8 100644
--- a/For_developers/Sphinx/Makefile
+++ b/For_developers/Sphinx/Makefile
@@ -1,4 +1,4 @@
-# Minimal makefile for Sphinx documentation
+# Makefile for Sphinx documentation
 #
 
 # You can set these variables from the command line.
diff --git a/For_developers/Sphinx/source/Documentation/Input/control.rst b/For_developers/Sphinx/source/Documentation/Input/control.rst
index 5f4ac424ed7cee480bb92a8a92f727ad3d47ad6a..cb9e500e744e6774e4d4a01b6d7691d3e32bf849 100644
--- a/For_developers/Sphinx/source/Documentation/Input/control.rst
+++ b/For_developers/Sphinx/source/Documentation/Input/control.rst
@@ -4,8 +4,8 @@ The CONTROL file
     
   
 
-.. MARS user documentation				https://confluence.ecmwf.int/display/UDOC/MARS+user+documentation
-.. MARS keywords and explanation				https://confluence.ecmwf.int/display/UDOC/MARS+keywords
+.. MARS user documentation https://confluence.ecmwf.int/display/UDOC/MARS+user+documentation
+.. MARS keywords and explanation https://confluence.ecmwf.int/display/UDOC/MARS+keywords
  
  
 This file is an input file for :literal:`flex_extract's` main script :literal:`submit.py`.
diff --git a/For_developers/Sphinx/source/Documentation/disagg.rst b/For_developers/Sphinx/source/Documentation/disagg.rst
index 113143d1eac2044150d8cfde1034516cbb14ea20..deb420864c82f618b2142df0a954e4816214136c 100644
--- a/For_developers/Sphinx/source/Documentation/disagg.rst
+++ b/For_developers/Sphinx/source/Documentation/disagg.rst
@@ -103,7 +103,7 @@ Figure 3 shows an overview of the new algorithm and its components.
 .. _ref-fig-IA3:                       
 
 .. figure:: ../_files/IA3.png         
-    :figclass: align-center		  
+    :figclass: align-center
    
     Fig. 3: Schematic overview of the basic notation in a precipitation interval with the original precipitation rate g (green) as a step function and the interpolated data :math:`f` (dark blue) as the piecewise linear function. The original time interval with fixed grid length :math:`\delta t` is split equidistantly in three subintervals denoted by :math:`I_i^{1,2,3}`, with the slopes in the subintervals as denoted by :math:`k_i^{1,2,3}` . The sub-grid function values :math:`f_i, f_i^{1,2}, f_{i+1}` are marked by red diamonds (Hittmeir et al. 2018).
    
@@ -184,4 +184,4 @@ This new point :math:`p` is used for linear interpolation of the complete timese
     :hidden:
     :maxdepth: 2
     
-    
\ No newline at end of file
+    
diff --git a/For_developers/Sphinx/source/evaluation.rst b/For_developers/Sphinx/source/evaluation.rst
index 48906d6fba7812702cd58fe0a0d66027d4394f90..a0d4d2a6aa7d8516b4420f448a168efcbf537dfc 100644
--- a/For_developers/Sphinx/source/evaluation.rst
+++ b/For_developers/Sphinx/source/evaluation.rst
@@ -29,11 +29,11 @@ Evaluation
     - radon
         
     Performance analysis:
-    -	Whole software
-    -	Disaggregation
-    -	Convert2
-    -   prepare_flexpart
-    -	Andere komponenten
+    - Whole software
+    - Disaggregation
+    - Convert2
+    - prepare_flexpart
+    - Andere komponenten
 
     
     
diff --git a/Source/Python/Classes/UioFiles.py b/Source/Python/Classes/UioFiles.py
index cff0ab4517686fdc0d52a81f0a2a47277697dafd..0fe9448a9b97d4192688f3ba21e14eb9236235dd 100644
--- a/Source/Python/Classes/UioFiles.py
+++ b/Source/Python/Classes/UioFiles.py
@@ -113,7 +113,7 @@ class UioFiles(object):
         path = os.path.abspath(path)
 
         # get all files in the dir and subdir as absolut path
-	    # pylint: disable=W0612
+        # pylint: disable=W0612
         for root, dirnames, filenames in os.walk(path):
             for filename in fnmatch.filter(filenames, self.pattern):
                 self.files.append(os.path.join(root, filename))
diff --git a/Source/Python/pylintrc b/Source/Python/pylintrc
index 75fc8ae8c78f7a6f2ae443791e1cdb6a3600c6dc..0101f44254abd52a0d6a8c9a0d4dadfb24cec707 100644
--- a/Source/Python/pylintrc
+++ b/Source/Python/pylintrc
@@ -127,10 +127,9 @@ disable=print-statement,
         dict-items-not-iterating,
         dict-keys-not-iterating,
         dict-values-not-iterating,
-	anomalous-backslash-in-string,
-	relative-import,
-	protected-access
-	
+        anomalous-backslash-in-string,
+        relative-import,
+        protected-access
 
 # Enable the message, report, category or checker with the given id(s). You can
 # either give multiple identifier separated by comma (,) or put this option
@@ -361,28 +360,28 @@ good-names=i,
            d,
            dd,
            v,
-	   ty,
-	   st,
-	   ti,
-	   MR,
-	   pk,
-	   pv,
-	   ni,
-	   nj,
-	   nt,
-	   ix,
-	   jy,
-	   it,
-	   parId,
-	   g,
-	   h,
-	   xa,
-	   xb,
-	   xc,
-	   xd,
-	   IA3,
-	   dt,
-	   fi
+           ty,
+           st,
+           ti,
+           MR,
+           pk,
+           pv,
+           ni,
+           nj,
+           nt,
+           ix,
+           jy,
+           it,
+           parId,
+           g,
+           h,
+           xa,
+           xb,
+           xc,
+           xd,
+           IA3,
+           dt,
+           fi
 
 # Include a hint for the correct naming format with invalid-name
 include-naming-hint=no
diff --git a/Source/Pythontest/TestPathes.py b/Source/Pythontest/TestPathes.py
index 6174484c5cf3ac819571553863869487edf5f8b1..f02e924bdfc0732e9f15b5dd74a675d2fab54084 100644
--- a/Source/Pythontest/TestPathes.py
+++ b/Source/Pythontest/TestPathes.py
@@ -1,35 +1,35 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-import os
-import sys
-import pytest
-
-sys.path.append("../python")
-import _config
-
-def test_path_localpython():
-    assert os.path.exists(_config.PATH_LOCAL_PYTHON) == 1
-
-def test_path_flexextract():
-    assert os.path.exists(_config.PATH_FLEXEXTRACT_DIR) == 1
-
-def test_path_flexextract_name():
-    version = _config._VERSION_STR
-    flexextract_name = 'flex_extract_v' + version
-    assert os.path.basename(_config.PATH_FLEXEXTRACT_DIR) == flexextract_name
-
-def test_path_templates():
-    assert os.path.exists(_config.PATH_TEMPLATES) == 1
-
-def test_path_vtable():
-    assert os.path.exists(_config.PATH_GRIBTABLE) == 1
-
-def test_file_vtable():
-    assert os.path.isfile(_config.PATH_GRIBTABLE) == 1
-
-def test_path_run():
-    assert os.path.exists(_config.PATH_RUN_DIR) == 1
-
-def test_path_control():
-    assert os.path.exists(_config.PATH_CONTROLFILES) == 1
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import os
+import sys
+import pytest
+
+sys.path.append("../python")
+import _config
+
+def test_path_localpython():
+    assert os.path.exists(_config.PATH_LOCAL_PYTHON) == 1
+
+def test_path_flexextract():
+    assert os.path.exists(_config.PATH_FLEXEXTRACT_DIR) == 1
+
+def test_path_flexextract_name():
+    version = _config._VERSION_STR
+    flexextract_name = 'flex_extract_v' + version
+    assert os.path.basename(_config.PATH_FLEXEXTRACT_DIR) == flexextract_name
+
+def test_path_templates():
+    assert os.path.exists(_config.PATH_TEMPLATES) == 1
+
+def test_path_vtable():
+    assert os.path.exists(_config.PATH_GRIBTABLE) == 1
+
+def test_file_vtable():
+    assert os.path.isfile(_config.PATH_GRIBTABLE) == 1
+
+def test_path_run():
+    assert os.path.exists(_config.PATH_RUN_DIR) == 1
+
+def test_path_control():
+    assert os.path.exists(_config.PATH_CONTROLFILES) == 1
diff --git a/Source/Pythontest/conftest.py b/Source/Pythontest/conftest.py
index 644c77ba557acb25c75694f0712ce58265a83e0b..f9c25511ac79cd96067729c90b5fc0e4daf6b47e 100644
--- a/Source/Pythontest/conftest.py
+++ b/Source/Pythontest/conftest.py
@@ -1,10 +1,10 @@
-import sys
-import pytest
-
-sys.path.append('../Python')
-import _config
-
-#@pytest.fixture
-#def prep_test_env():
-#    testdir = _config.PATH_TEST_DIR
-print('')
+import sys
+import pytest
+
+sys.path.append('../Python')
+import _config
+
+#@pytest.fixture
+#def prep_test_env():
+#    testdir = _config.PATH_TEST_DIR
+print('')
diff --git a/Source/Pythontest/pytest.ini b/Source/Pythontest/pytest.ini
index 66e850a3a99e0733c970b96198f1be78c415151d..7e7fce4c544fd5f10d5bd38ef83a9430018e94ee 100644
--- a/Source/Pythontest/pytest.ini
+++ b/Source/Pythontest/pytest.ini
@@ -1,5 +1,5 @@
-# content of pytest.ini
-[pytest]
-markers =
-    msuser_pw: Test that can be executed only as a member-state user. Password required.
-    gateway: Test that can be executed only in the gateway mode.
+# content of pytest.ini
+[pytest]
+markers =
+    msuser_pw: Test that can be executed only as a member-state user. Password required.
+    gateway: Test that can be executed only in the gateway mode.
diff --git a/Testing/Regression/Compare_gribfiles/test_cmp_grib_file.py b/Testing/Regression/Compare_gribfiles/test_cmp_grib_file.py
index 196131ca31700cf981e652ab2836f8e8549a9db5..96200daca0fe24483403082f46f6aa72dddfcfac 100644
--- a/Testing/Regression/Compare_gribfiles/test_cmp_grib_file.py
+++ b/Testing/Regression/Compare_gribfiles/test_cmp_grib_file.py
@@ -1,270 +1,270 @@
-#!/usr/bin/env python3
-# -*- coding: utf-8 -*-
-"""Comparison of resulting Grib files of two flex_extract versions.
-
-
-
-The script should be called like:
-
-    python test_cmp_grib_files.py -r <path-to-reference-files> -n <path-to-new-files>  -p <file-pattern>
-
-Note
-----
-
-Licence:
---------
-    (C) Copyright 2014-2019.
-
-    SPDX-License-Identifier: CC-BY-4.0
-
-    This work is licensed under the Creative Commons Attribution 4.0
-    International License. To view a copy of this license, visit
-    http://creativecommons.org/licenses/by/4.0/ or send a letter to
-    Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
-
-
-Example
--------
-    python test_cmp_grib_file.py -r 7.0.4/EA5/ -n 7.1/EA5/ -p 'EA*'
-"""
-
-# ------------------------------------------------------------------------------
-# MODULES
-# ------------------------------------------------------------------------------
-import os
-import sys
-from datetime import datetime
-from eccodes import GribFile, GribMessage
-
-# ------------------------------------------------------------------------------
-# FUNCTION
-# ------------------------------------------------------------------------------
-def get_cmdline_params(parlist, debug=True):
-
-    import getopt
-
-    iref_path = '' # e.g. Reference_files
-    inew_path = '' # e.g. New_files
-    smatch = '' # e.g. files matching pattern
-
-    try:
-        opts, pars = getopt.getopt(parlist,
-                                   "hr:n:p:",
-                                   ["ipref=", "ipnew=", "pattern="])
-    except getopt.GetoptError:
-        print('test_cmp_grib_file.py -r <ipref> -n <ipnew> -p <pattern>')
-        sys.exit(2)
-
-    for opt, par in opts:
-        if opt == '-h':
-            print('test_cmp_grib_file.py -r <ipref> -n <ipnew> -p <pattern>')
-            sys.exit()
-        elif opt in ("-r", "--ipref"):
-            iref_path = par
-        elif opt in ("-n", "--ipnew"):
-            inew_path = par
-        elif opt in ("-p", "--pattern"):
-            smatch = par
-
-    if iref_path == '':
-        sys.exit('NO REFERENCE INPUT PATH SET!')
-    if inew_path == '':
-        sys.exit('NO "NEW" COMPARISON INPUT PATH SET!')
-    if smatch == '':
-        sys.exit('NO MATCHING PATTERN FOR FILES SET!')
-
-    if debug:
-        print("\n\nWelcome!")
-        print('Reference path is: ', iref_path)
-        print('New path is: ', inew_path)
-        print('Filepattern is: ', smatch)
-
-    return iref_path, inew_path, smatch
-
-def get_files(ipath, matchingstring, debug=True):
-    """
-        @Description:
-            Get filenames from input path matching the
-            string or regular expression and return it.
-
-        @Input:
-            ipath: string
-                Path to the files.
-
-            matchingstring: string
-                A string defining the filenames,
-                with or without regular exprssion.
-
-        @Return
-            filename: list of strings
-                A list of all files matching the pattern of
-                matchingstring.
-    """
-    import fnmatch
-
-    files = []
-
-    for fn in os.listdir(ipath):
-        if fnmatch.fnmatch(fn, matchingstring):
-            files.append(fn)
-
-    filelist = sorted(files)
-    if debug:
-        print('The input files are: %s' %(filelist))
-
-    return filelist
-
-def cmp_files_list(flist1, flist2):
-    '''
-    '''
-
-    # 1. same length?
-    length = len(flist1) == len(flist2)
-    if not length:
-        print('There are not the same amount of files.')
-        sys.exit('Message 1')
-
-    # 2. same content?
-    content = [True for i, j in zip(flist1, flist2) if i == j]
-    if not len(content) == len(flist1):
-        print('Not the same file list')
-        sys.exit('Message 2')
-
-    return True
-
-
-def cmp_number_messages(iref, flist1, inew, flist2):
-
-    ref_dict = {}
-    new_dict = {}
-    res_dict = {}
-    for file in flist1:
-        with GribFile(os.path.join(iref,file)) as grib:
-            ref_dict[file] = len(grib)
-        with GribFile(os.path.join(inew,file)) as grib:
-            new_dict[file] = len(grib)
-
-        res_dict[file] = ref_dict[file] == new_dict[file]
-
-    for k, res in res_dict.items():
-        if not res == True:
-            print('LOG: Amount of messages in files {} are not the same!'.format(k))
-
-    return True
-
-
-def cmp_grib_msg_header(ipath_ref, ipath_new, filelist):
-    from subprocess import Popen, PIPE
-    # ref_dict = {}
-    # new_dict = {}
-    # for file in flist1:
-        # with GribFile(os.path.join(iref,file)) as grib:
-            # for i in range(len(grib)):
-                # msg = GribMessage(grib)
-                # ref_dict[file] = {}
-                # ref_dict[file][i] = [msg['shortName'],msg['level'],
-                                  # msg['editionNumber'],msg['dataDate'],
-                                  # msg['dataTime'],msg['marsClass'],
-                                  # msg['type'], msg['gridType'],
-                                  # msg['stepRange']]
-    error_flag = False
-    cmp_flag = False
-    for file in filelist:
-        try:
-            res = Popen(['grib_compare', '-H',
-                         ipath_ref + '/' + file,
-                         ipath_new + '/' + file],
-                        stdin=PIPE, stdout=PIPE, stderr=PIPE)
-            output, error = res.communicate()#.decode("utf-8"))
-            if error:
-                print('... ERROR: \n\t{}'.format(error.decode()))
-                error_flag = True
-            if output:
-                print('{}'.format(output.decode()))
-                cmp_flag = True
-        except ValueError as e:
-            print('... ERROR CODE: ' + str(e.returncode))
-            print('... ERROR MESSAGE:\n \t ' + str(res))
-            error_flag = True
-        except OSError as e:
-            print('... ERROR CODE: ' + str(e.errno))
-            print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
-            error_flag = True
-
-    if error_flag:
-        sys.exit('... ERROR IN GRIB MESSAGE COMPARISON!')
-    if cmp_flag:
-        sys.exit('... FILES HAVE DIFFERENCES IN GRIB MESSAGES!')
-
-    return True
-
-
-def cmp_grib_msg_statistics(ipath_ref, ipath_new, filelist):
-
-    from subprocess import Popen, PIPE
-
-    error_flag = False
-    cmp_flag = False
-    for file in filelist:
-        try:
-            res = Popen(['grib_compare', '-c', 'statistics:n',
-                         ipath_ref + '/' + file,
-                         ipath_new + '/' + file],
-                        stdin=PIPE, stdout=PIPE, stderr=PIPE)
-            output, error = res.communicate()#.decode("utf-8"))
-            if error:
-                print('... ERROR: \n\t{}'.format(error.decode()))
-                error_flag = True
-            if output:
-                print('\nIn File: {}'.format(file))
-                print('{}'.format(output.decode()))
-                cmp_flag = True
-        except ValueError as e:
-            print('... ERROR CODE: ' + str(e.returncode))
-            print('... ERROR MESSAGE:\n \t ' + str(res))
-            error_flag = True
-        except OSError as e:
-            print('... ERROR CODE: ' + str(e.errno))
-            print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
-            error_flag = True
-
-    if error_flag:
-        sys.exit('... ERROR IN GRIB MESSAGE COMPARISON!')
-    if cmp_flag:
-        sys.exit('... FILES HAVE DIFFERENT STATISTICS!')
-    return True
-
-if __name__ == '__main__':
-
-    # get the parameter list of program call
-    ref_path, new_path, fmatch = get_cmdline_params(sys.argv[1:])
-
-    # get the list of files of both cases
-    ref_files = get_files(ref_path, fmatch)
-    new_files = get_files(new_path, fmatch)
-
-    # flag to store successfull tests
-    suc = True
-
-    # 1. Does the 2 cases contain the same list of files?
-    suc = True if suc and cmp_files_list(ref_files, new_files) else False
-
-    # 2. Does each file in both cases contain the same amount of messages?
-    suc = True if suc and cmp_number_messages(ref_path, ref_files, new_path, new_files) else False
-
-    # 3. Does each file has the same parameters (in Header)?
-    # Since we can be sure that both cases have the same files,
-    # we just use 1 filelist
-    suc = True if suc and cmp_grib_msg_header(ref_path, new_path, new_files) else False
-
-    # 4. Are the statistics of each message the same?
-    # Since we can be sure that both cases have the same files,
-    # we just use 1 filelist
-    suc = True if suc and cmp_grib_msg_statistics(ref_path, new_path, new_files) else False
-
-    # If the program comes this far and flag "suc" = True,
-    # all tests were successful
-    if suc:
-        exit('GRIB_COMPARISON: SUCCESSFULL!')
-    else:
-        exit('GRIB_COMPARISON: FAILURE!')
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""Comparison of resulting Grib files of two flex_extract versions.
+
+
+
+The script should be called like:
+
+    python test_cmp_grib_files.py -r <path-to-reference-files> -n <path-to-new-files>  -p <file-pattern>
+
+Note
+----
+
+Licence:
+--------
+    (C) Copyright 2014-2019.
+
+    SPDX-License-Identifier: CC-BY-4.0
+
+    This work is licensed under the Creative Commons Attribution 4.0
+    International License. To view a copy of this license, visit
+    http://creativecommons.org/licenses/by/4.0/ or send a letter to
+    Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
+
+
+Example
+-------
+    python test_cmp_grib_file.py -r 7.0.4/EA5/ -n 7.1/EA5/ -p 'EA*'
+"""
+
+# ------------------------------------------------------------------------------
+# MODULES
+# ------------------------------------------------------------------------------
+import os
+import sys
+from datetime import datetime
+from eccodes import GribFile, GribMessage
+
+# ------------------------------------------------------------------------------
+# FUNCTION
+# ------------------------------------------------------------------------------
+def get_cmdline_params(parlist, debug=True):
+
+    import getopt
+
+    iref_path = '' # e.g. Reference_files
+    inew_path = '' # e.g. New_files
+    smatch = '' # e.g. files matching pattern
+
+    try:
+        opts, pars = getopt.getopt(parlist,
+                                   "hr:n:p:",
+                                   ["ipref=", "ipnew=", "pattern="])
+    except getopt.GetoptError:
+        print('test_cmp_grib_file.py -r <ipref> -n <ipnew> -p <pattern>')
+        sys.exit(2)
+
+    for opt, par in opts:
+        if opt == '-h':
+            print('test_cmp_grib_file.py -r <ipref> -n <ipnew> -p <pattern>')
+            sys.exit()
+        elif opt in ("-r", "--ipref"):
+            iref_path = par
+        elif opt in ("-n", "--ipnew"):
+            inew_path = par
+        elif opt in ("-p", "--pattern"):
+            smatch = par
+
+    if iref_path == '':
+        sys.exit('NO REFERENCE INPUT PATH SET!')
+    if inew_path == '':
+        sys.exit('NO "NEW" COMPARISON INPUT PATH SET!')
+    if smatch == '':
+        sys.exit('NO MATCHING PATTERN FOR FILES SET!')
+
+    if debug:
+        print("\n\nWelcome!")
+        print('Reference path is: ', iref_path)
+        print('New path is: ', inew_path)
+        print('Filepattern is: ', smatch)
+
+    return iref_path, inew_path, smatch
+
+def get_files(ipath, matchingstring, debug=True):
+    """
+        @Description:
+            Get filenames from input path matching the
+            string or regular expression and return it.
+
+        @Input:
+            ipath: string
+                Path to the files.
+
+            matchingstring: string
+                A string defining the filenames,
+                with or without regular exprssion.
+
+        @Return
+            filename: list of strings
+                A list of all files matching the pattern of
+                matchingstring.
+    """
+    import fnmatch
+
+    files = []
+
+    for fn in os.listdir(ipath):
+        if fnmatch.fnmatch(fn, matchingstring):
+            files.append(fn)
+
+    filelist = sorted(files)
+    if debug:
+        print('The input files are: %s' %(filelist))
+
+    return filelist
+
+def cmp_files_list(flist1, flist2):
+    '''
+    '''
+
+    # 1. same length?
+    length = len(flist1) == len(flist2)
+    if not length:
+        print('There are not the same amount of files.')
+        sys.exit('Message 1')
+
+    # 2. same content?
+    content = [True for i, j in zip(flist1, flist2) if i == j]
+    if not len(content) == len(flist1):
+        print('Not the same file list')
+        sys.exit('Message 2')
+
+    return True
+
+
+def cmp_number_messages(iref, flist1, inew, flist2):
+
+    ref_dict = {}
+    new_dict = {}
+    res_dict = {}
+    for file in flist1:
+        with GribFile(os.path.join(iref,file)) as grib:
+            ref_dict[file] = len(grib)
+        with GribFile(os.path.join(inew,file)) as grib:
+            new_dict[file] = len(grib)
+
+        res_dict[file] = ref_dict[file] == new_dict[file]
+
+    for k, res in res_dict.items():
+        if not res == True:
+            print('LOG: Amount of messages in files {} are not the same!'.format(k))
+
+    return True
+
+
+def cmp_grib_msg_header(ipath_ref, ipath_new, filelist):
+    from subprocess import Popen, PIPE
+    # ref_dict = {}
+    # new_dict = {}
+    # for file in flist1:
+        # with GribFile(os.path.join(iref,file)) as grib:
+            # for i in range(len(grib)):
+                # msg = GribMessage(grib)
+                # ref_dict[file] = {}
+                # ref_dict[file][i] = [msg['shortName'],msg['level'],
+                                  # msg['editionNumber'],msg['dataDate'],
+                                  # msg['dataTime'],msg['marsClass'],
+                                  # msg['type'], msg['gridType'],
+                                  # msg['stepRange']]
+    error_flag = False
+    cmp_flag = False
+    for file in filelist:
+        try:
+            res = Popen(['grib_compare', '-H',
+                         ipath_ref + '/' + file,
+                         ipath_new + '/' + file],
+                        stdin=PIPE, stdout=PIPE, stderr=PIPE)
+            output, error = res.communicate()#.decode("utf-8"))
+            if error:
+                print('... ERROR: \n\t{}'.format(error.decode()))
+                error_flag = True
+            if output:
+                print('{}'.format(output.decode()))
+                cmp_flag = True
+        except ValueError as e:
+            print('... ERROR CODE: ' + str(e.returncode))
+            print('... ERROR MESSAGE:\n \t ' + str(res))
+            error_flag = True
+        except OSError as e:
+            print('... ERROR CODE: ' + str(e.errno))
+            print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
+            error_flag = True
+
+    if error_flag:
+        sys.exit('... ERROR IN GRIB MESSAGE COMPARISON!')
+    if cmp_flag:
+        sys.exit('... FILES HAVE DIFFERENCES IN GRIB MESSAGES!')
+
+    return True
+
+
+def cmp_grib_msg_statistics(ipath_ref, ipath_new, filelist):
+
+    from subprocess import Popen, PIPE
+
+    error_flag = False
+    cmp_flag = False
+    for file in filelist:
+        try:
+            res = Popen(['grib_compare', '-c', 'statistics:n',
+                         ipath_ref + '/' + file,
+                         ipath_new + '/' + file],
+                        stdin=PIPE, stdout=PIPE, stderr=PIPE)
+            output, error = res.communicate()#.decode("utf-8"))
+            if error:
+                print('... ERROR: \n\t{}'.format(error.decode()))
+                error_flag = True
+            if output:
+                print('\nIn File: {}'.format(file))
+                print('{}'.format(output.decode()))
+                cmp_flag = True
+        except ValueError as e:
+            print('... ERROR CODE: ' + str(e.returncode))
+            print('... ERROR MESSAGE:\n \t ' + str(res))
+            error_flag = True
+        except OSError as e:
+            print('... ERROR CODE: ' + str(e.errno))
+            print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
+            error_flag = True
+
+    if error_flag:
+        sys.exit('... ERROR IN GRIB MESSAGE COMPARISON!')
+    if cmp_flag:
+        sys.exit('... FILES HAVE DIFFERENT STATISTICS!')
+    return True
+
+if __name__ == '__main__':
+
+    # get the parameter list of program call
+    ref_path, new_path, fmatch = get_cmdline_params(sys.argv[1:])
+
+    # get the list of files of both cases
+    ref_files = get_files(ref_path, fmatch)
+    new_files = get_files(new_path, fmatch)
+
+    # flag to store successfull tests
+    suc = True
+
+    # 1. Does the 2 cases contain the same list of files?
+    suc = True if suc and cmp_files_list(ref_files, new_files) else False
+
+    # 2. Does each file in both cases contain the same amount of messages?
+    suc = True if suc and cmp_number_messages(ref_path, ref_files, new_path, new_files) else False
+
+    # 3. Does each file has the same parameters (in Header)?
+    # Since we can be sure that both cases have the same files,
+    # we just use 1 filelist
+    suc = True if suc and cmp_grib_msg_header(ref_path, new_path, new_files) else False
+
+    # 4. Are the statistics of each message the same?
+    # Since we can be sure that both cases have the same files,
+    # we just use 1 filelist
+    suc = True if suc and cmp_grib_msg_statistics(ref_path, new_path, new_files) else False
+
+    # If the program comes this far and flag "suc" = True,
+    # all tests were successful
+    if suc:
+        exit('GRIB_COMPARISON: SUCCESSFULL!')
+    else:
+        exit('GRIB_COMPARISON: FAILURE!')
diff --git a/Testing/Regression/Mars_request/create_old_mars_requests.txt b/Testing/Regression/Mars_request/create_old_mars_requests.txt
index 9491396453a71d8705e84a648090bab5fb9823f7..84e000ee2b16ca9d13abeae63ad25e233c5e7a54 100644
--- a/Testing/Regression/Mars_request/create_old_mars_requests.txt
+++ b/Testing/Regression/Mars_request/create_old_mars_requests.txt
@@ -1,85 +1,85 @@
-#!/bin/bash
-#
-# @Author: Anne Philipp
-#
-# @Date: October, 10 2019
-#
-# @Description: Creates the mars request files with the older (7.0.4) 
-#               version of flex_extract and places them in the test directory
-#               of mars request  comparsion tests.
-#
-# @License:
-#    (C) Copyright 2014-2019.
-#
-#    SPDX-License-Identifier: CC-BY-4.0
-#
-#    This work is licensed under the Creative Commons Attribution 4.0
-#    International License. To view a copy of this license, visit
-#    http://creativecommons.org/licenses/by/4.0/ or send a letter to
-#    Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
-#               
-# @ChangeHistory:  
-#
-# @Usage: 
-#        start script within the old flex_extract python directory
-#        ./create_old_mars_request.txt  <path to mars request test directory of old version>
-#        e.g. ./create_old_mars_request.txt <local_path>/flex_extract_v7.1/Testing/Regression/Mars_request/7.0.4/
-#
-
-
-./submit.py --controlfile=CONTROL_CERA_mr --request=1
-mv ../work/mars_requests.csv ../work/CERA_mr.csv
-
-./submit.py --controlfile=CONTROL_CERA.public_mr --public=1 --request=1
-mv ../work/mars_requests.csv ../work/CERA.public_mr.csv
-   
-./submit.py --controlfile=CONTROL_CF_mr --request=1
-mv ../work/mars_requests.csv ../work/CF_mr.csv
-
-./submit.py --controlfile=CONTROL_CV_mr --request=1
-mv ../work/mars_requests.csv ../work/CV_mr.csv
-
-./submit.py --controlfile=CONTROL_EA5.highres_mr --request=1
-mv ../work/mars_requests.csv ../work/EA5.highres_mr.csv
-
-./submit.py --controlfile=CONTROL_EA5_mr --request=1
-mv ../work/mars_requests.csv ../work/EA5_mr.csv
-
-./submit.py --controlfile=CONTROL_EA5.public_mr --public=1 --request=1
-mv ../work/mars_requests.csv ../work/EA5.public_mr.csv
-
-./submit.py --controlfile=CONTROL_EI_mr --request=1 
-mv ../work/mars_requests.csv ../work/EI_mr.csv
-
-./submit.py --controlfile=CONTROL_EI.public_mr --request=1 --public=1
-mv ../work/mars_requests.csv ../work/EI.public_mr.csv
-
-./submit.py --controlfile=CONTROL_OD.ELDA.FC.eta.ens.double_mr --request=1
-mv ../work/mars_requests.csv ../work/OD.ELDA.FC.eta.ens.double_mr.csv
-
-./submit.py --controlfile=CONTROL_OD.ENFO.CF_mr --request=1
-mv ../work/mars_requests.csv ../work/OD.ENFO.CF_mr.csv
-
-./submit.py --controlfile=CONTROL_OD.ENFO.PF_mr --request=1
-mv ../work/mars_requests.csv ../work/OD.ENFO.PF_mr.csv
-
-./submit.py --controlfile=CONTROL_OD.OPER.4V.operational_mr --request=1
-mv ../work/mars_requests.csv ../work/OD.OPER.4V.operational_mr.csv
-
-./submit.py --controlfile=CONTROL_OD.OPER.FC.36hours_mr --request=1
-mv ../work/mars_requests.csv ../work/OD.OPER.FC.36hours_mr.csv
-
-./submit.py --controlfile=CONTROL_OD.OPER.FC.twiceaday_mr --request=1
-mv ../work/mars_requests.csv ../work/OD.OPER.FC.twiceaday_mr.csv
-
-./submit.py --controlfile=CONTROL_OD.OPER.global.025_mr --request=1
-mv ../work/mars_requests.csv ../work/OD.OPER.global.025_mr.csv
-
-./submit.py --controlfile=CONTROL_OD.OPER.highres.eta_mr --request=1
-mv ../work/mars_requests.csv ../work/OD.OPER.highres.eta_mr.csv
-
-./submit.py --controlfile=CONTROL_OD.OPER.highres.gauss_mr --request=1
-mv ../work/mars_requests.csv ../work/OD.OPER.highres.gauss_mr.csv
-
-
-mv ./work/*_mr.csv ${1}
+#!/bin/bash
+#
+# @Author: Anne Philipp
+#
+# @Date: October, 10 2019
+#
+# @Description: Creates the mars request files with the older (7.0.4) 
+#               version of flex_extract and places them in the test directory
+#               of mars request  comparsion tests.
+#
+# @License:
+#    (C) Copyright 2014-2019.
+#
+#    SPDX-License-Identifier: CC-BY-4.0
+#
+#    This work is licensed under the Creative Commons Attribution 4.0
+#    International License. To view a copy of this license, visit
+#    http://creativecommons.org/licenses/by/4.0/ or send a letter to
+#    Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
+#               
+# @ChangeHistory:  
+#
+# @Usage: 
+#        start script within the old flex_extract python directory
+#        ./create_old_mars_request.txt  <path to mars request test directory of old version>
+#        e.g. ./create_old_mars_request.txt <local_path>/flex_extract_v7.1/Testing/Regression/Mars_request/7.0.4/
+#
+
+
+./submit.py --controlfile=CONTROL_CERA_mr --request=1
+mv ../work/mars_requests.csv ../work/CERA_mr.csv
+
+./submit.py --controlfile=CONTROL_CERA.public_mr --public=1 --request=1
+mv ../work/mars_requests.csv ../work/CERA.public_mr.csv
+   
+./submit.py --controlfile=CONTROL_CF_mr --request=1
+mv ../work/mars_requests.csv ../work/CF_mr.csv
+
+./submit.py --controlfile=CONTROL_CV_mr --request=1
+mv ../work/mars_requests.csv ../work/CV_mr.csv
+
+./submit.py --controlfile=CONTROL_EA5.highres_mr --request=1
+mv ../work/mars_requests.csv ../work/EA5.highres_mr.csv
+
+./submit.py --controlfile=CONTROL_EA5_mr --request=1
+mv ../work/mars_requests.csv ../work/EA5_mr.csv
+
+./submit.py --controlfile=CONTROL_EA5.public_mr --public=1 --request=1
+mv ../work/mars_requests.csv ../work/EA5.public_mr.csv
+
+./submit.py --controlfile=CONTROL_EI_mr --request=1 
+mv ../work/mars_requests.csv ../work/EI_mr.csv
+
+./submit.py --controlfile=CONTROL_EI.public_mr --request=1 --public=1
+mv ../work/mars_requests.csv ../work/EI.public_mr.csv
+
+./submit.py --controlfile=CONTROL_OD.ELDA.FC.eta.ens.double_mr --request=1
+mv ../work/mars_requests.csv ../work/OD.ELDA.FC.eta.ens.double_mr.csv
+
+./submit.py --controlfile=CONTROL_OD.ENFO.CF_mr --request=1
+mv ../work/mars_requests.csv ../work/OD.ENFO.CF_mr.csv
+
+./submit.py --controlfile=CONTROL_OD.ENFO.PF_mr --request=1
+mv ../work/mars_requests.csv ../work/OD.ENFO.PF_mr.csv
+
+./submit.py --controlfile=CONTROL_OD.OPER.4V.operational_mr --request=1
+mv ../work/mars_requests.csv ../work/OD.OPER.4V.operational_mr.csv
+
+./submit.py --controlfile=CONTROL_OD.OPER.FC.36hours_mr --request=1
+mv ../work/mars_requests.csv ../work/OD.OPER.FC.36hours_mr.csv
+
+./submit.py --controlfile=CONTROL_OD.OPER.FC.twiceaday_mr --request=1
+mv ../work/mars_requests.csv ../work/OD.OPER.FC.twiceaday_mr.csv
+
+./submit.py --controlfile=CONTROL_OD.OPER.global.025_mr --request=1
+mv ../work/mars_requests.csv ../work/OD.OPER.global.025_mr.csv
+
+./submit.py --controlfile=CONTROL_OD.OPER.highres.eta_mr --request=1
+mv ../work/mars_requests.csv ../work/OD.OPER.highres.eta_mr.csv
+
+./submit.py --controlfile=CONTROL_OD.OPER.highres.gauss_mr --request=1
+mv ../work/mars_requests.csv ../work/OD.OPER.highres.gauss_mr.csv
+
+
+mv ./work/*_mr.csv ${1}
diff --git a/Testing/Regression/Mars_request/test_cmp_mars_requests.py b/Testing/Regression/Mars_request/test_cmp_mars_requests.py
index 9bfade9ef7bd4615e90b812c2d102d962fa83c45..13039c987b10c7f7b476eefe9956d27cffebdc75 100755
--- a/Testing/Regression/Mars_request/test_cmp_mars_requests.py
+++ b/Testing/Regression/Mars_request/test_cmp_mars_requests.py
@@ -1,331 +1,331 @@
-#!/usr/bin/env python3
-# -*- coding: utf-8 -*-
-"""Comparison of the created MARS requests of two flex_extract versions.
-
-There will be comparisons for the given standard control files in the
-"Controls" - directory. The result of the comparison is stored in the
-"Log" - directory with an individual timestamp in the format %Y-%m-%d_%H-%M-%S.
-(E.g. log_2018-11-23_12-42-29)
-The MARS request files are named such that it contains the name of the
-corresponding control files "<control-identifier>.csv" (e.g. EA5_mr.csv).
-They are stored in the corresponding version directory and have the same
-name in both versions.
-
-The script should be called like:
-
-    python test_cmp_mars_requests.py <old_version_number> <new_version_number>
-
-Note
-----
-The MARS request files from the older version have to be in place already.
-The request files of the new/current version will be generated automatically
-with the "run_local.sh" script.
-It is necessary to have a directory named after the version number of
-flex_extract. For example: "7.0.3" and "7.1".
-
-Licence:
---------
-    (C) Copyright 2014-2019.
-
-    SPDX-License-Identifier: CC-BY-4.0
-
-    This work is licensed under the Creative Commons Attribution 4.0
-    International License. To view a copy of this license, visit
-    http://creativecommons.org/licenses/by/4.0/ or send a letter to
-    Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
-
-Example
--------
-    python test_cmp_mars_requests.py 7.0.4 7.1
-"""
-
-# ------------------------------------------------------------------------------
-# MODULES
-# ------------------------------------------------------------------------------
-import os
-import sys
-import pandas as pd
-import subprocess
-import shutil
-from datetime import datetime
-
-sys.path.append('../../../Source/Python')
-import _config
-from  Mods.tools import init128
-
-# ------------------------------------------------------------------------------
-# FUNCTION
-# ------------------------------------------------------------------------------
-def test_mr_column_equality(mr_old, mr_new):
-    '''Check if old and new version of MARS requests have the same
-    amount of columns.
-
-    If the number is not equal and/or the column names are not equal
-    an error message is stored in global variable "err_msg".
-
-    Parameters
-    ----------
-    mr_old : :obj:`pandas DataFrame`
-        Contains the mars requests from the old version of
-        flex_extract.
-
-    mr_new : :obj:`pandas DataFrame`
-        Contains the mars requests from the new version of
-        flex_extract.
-
-    Return
-    ------
-    bool
-        True if successful, False otherwise.
-    '''
-    global err_msg
-    if (len(mr_old.columns.values) == len(mr_new.columns.values) and
-        sorted(mr_old.columns.values) == sorted(mr_new.columns.values)):
-        return True
-    else:
-        err_msg = 'Unequal number and/or column names!\n'
-        return False
-
-
-def test_mr_number_equality(mr_old, mr_new):
-    '''Check if old and new version have the same number of requests.
-
-    If the number is not equal an error message is stored in
-    global variable "err_msg".
-
-    Parameters
-    ----------
-    mr_old : :obj:`pandas DataFrame`
-        Contains the mars requests from the old version of
-        flex_extract.
-
-    mr_new : :obj:`pandas DataFrame`
-        Contains the mars requests from the new version of
-        flex_extract.
-
-    Return
-    ------
-    bool
-        True if successful, False otherwise.
-    '''
-    global err_msg
-    if len(mr_new.index) == len(mr_old.index):
-        return True
-    else:
-        err_msg = 'Unequal number of mars requests!\n'
-        return False
-
-def test_mr_content_equality(mr_old, mr_new):
-    '''Check if old and new version have the same request contents.
-
-    If the content in a column is not equal an error message is stored in
-    global variable "err_msg", recording the column.
-
-    Parameters
-    ----------
-    mr_old : :obj:`pandas DataFrame`
-        Contains the mars requests from the old version of
-        flex_extract.
-
-    mr_new : :obj:`pandas DataFrame`
-        Contains the mars requests from the new version of
-        flex_extract.
-
-    Return
-    ------
-    bool
-        True if successful, False otherwise.
-    '''
-    global err_msg
-    lresult = None
-    columns = list(mr_new.columns.values)
-    del columns[columns.index('target')]
-    mr_new = trim_all_columns(mr_new)
-    mr_old = trim_all_columns(mr_old)
-    for col in columns:
-        if mr_new[col].equals(mr_old[col]):
-            lresult = True
-        else:
-            err_msg += 'Unconsistency happend to be in column: ' + col + '\n'
-            print("THERE SEEMS TO BE AN ERROR:")
-            print("CONTENT OF NEW VERSION:")
-            print(mr_new[col])
-            print("CONTENT OF OLD VERSION:")
-            print(mr_old[col])
-            return False
-    return lresult
-
-
-def trim_all_columns(df):
-    """
-    Trim whitespace from ends of each value across all series in dataframe
-    """
-    trim_strings = lambda x: x.strip() if isinstance(x, str) else x
-    return df.applymap(trim_strings)
-
-def convert_param_numbers(mr_old):
-    """
-    Convert the numbers parameter into integers with 3 digits.
-    """
-
-    if str(mr_old).strip() != "OFF" and mr_old != None and '/' in str(mr_old) :
-        numbers = mr_old.split('/')
-        number = str(int(numbers[0])).zfill(3)+'/TO/'+str(int(numbers[2])).zfill(3)
-
-        return number
-
-    return mr_old
-
-def convert_param_step(mr_old):
-    """
-    For pure forecast with steps greater than 23 hours, the older versions 
-    writes out a list of steps instead with the syntax 'to' and 'by'. 
-    e.g. 000/003/006/009/012/015/018/021/024/027/030/033/036
-    
-    Convert this to 0/to/36/by/3
-    """
-
-    #if 'to' in str(mr_old) and 'by' in str(mr_old):
-    #    steps = mr_old.split('/')
-    #    step = []
-    #    for i in range(int(steps[0]),int(steps[2]),int(steps[4])):
-    #        step.append(str(int(i)).zfill(2))
-    #    return '/'.join(step)
-    
-    if not mr_old.isdigit() and 'to' not in mr_old.lower():
-        if int(mr_old.split('/')[-1]) > 23:
-    
-            steps = mr_old.split('/')
-            dtime = int(steps[1]) - int(steps[0])
-            
-            nsteps = str(int(steps[1]))+'/to/'+str(int(steps[-1]))+'/by/'+str(int(dtime))
-            return nsteps            
-    
-    return mr_old
-
-def to_param_id(pars, table):
-    '''Transform parameter names to parameter ids with ECMWF grib table 128.
-
-    Parameters
-    ----------
-    pars : str
-        Addpar argument from CONTROL file in the format of
-        parameter names instead of ids. The parameter short
-        names are sepearted with "/" and they are passed as
-        one single string.
-
-    table : dict
-        Contains the ECMWF grib table 128 information.
-        The key is the parameter number and the value is the
-        short name of the parameter.
-
-    Return
-    ------
-    ipar : list of int
-        List of addpar parameters from CONTROL file transformed to
-        parameter ids in the format of integer.
-    '''
-    if not pars:
-        return []
-    if not isinstance(pars, str):
-        pars=str(pars)
-
-    cpar = pars.upper().split('/')
-    spar = []
-    for par in cpar:
-        par = par.strip()
-        for k, v in table.items():
-            if par.isdigit():
-                par = str(int(par)).zfill(3)
-            if par == k or par == v:
-                spar.append(k + '.128')
-                break
-        else:
-            print('\n\Warning: par ' + par + ' not found in table 128\n\n”')
-
-    return '/'.join(str(l) for l in spar)
-
-
-
-if __name__ == '__main__':
-
-    # basic values for paths and versions
-    control_path = 'Controls'
-    log_path = 'Log'
-    old_dir = sys.argv[1] # e.g. '7.0.4'
-    new_dir = sys.argv[2] # e.g. '7.1'
-    mr_filename = 'mars_requests.csv'
-
-    # have to be set to "True" in the beginnning
-    # so it only fails if a test fails
-    lfinal = True
-
-    # prepare log file for this test run
-    currenttime = datetime.now()
-    time_str = currenttime.strftime('%Y-%m-%d_%H-%M-%S')
-    logfile = os.path.join(log_path, 'log_' + time_str)
-    with open(logfile, 'a') as f:
-        f.write('Compare mars requests between version ' + old_dir +
-                ' and version ' + new_dir + ' : \n')
-
-    # list all controlfiles
-    controls =  os.listdir(control_path)
-
-    # loop over controlfiles
-    for c in controls:
-        # empty error message for every controlfile
-        err_msg = ''
-
-        # start flex_extract with controlfiles to get mars_request files
-        shutil.copy(os.path.join(control_path,c), _config.PATH_CONTROLFILES)
-        subprocess.check_output(['run_local.sh', new_dir, c])
-        os.remove(os.path.join(_config.PATH_CONTROLFILES,c))
-
-        # cut-of "CONTROL_" string and mv mars_reqeust file
-        # to a name including control specific name
-        mr_name = c.split('CONTROL_')[1] + '.csv'
-        shutil.move(os.path.join(new_dir,mr_filename), os.path.join(new_dir,mr_name))
-
-        # read both mr files (old & new)
-        mr_old = pd.read_csv(os.path.join(old_dir, mr_name))
-        mr_new = pd.read_csv(os.path.join(new_dir, mr_name))
-
-        mr_old.columns = mr_old.columns.str.strip()
-        mr_new.columns = mr_new.columns.str.strip()
-
-        # convert names in old to ids
-        table128 = init128(_config.PATH_GRIBTABLE)
-        #print mr_old['param']
-
-        # some format corrections are necessary to compare older versions with 7.1
-        mr_old['param'] = mr_old['param'].apply(to_param_id, args=[table128])
-        mr_old['number'] = mr_old['number'].apply(convert_param_numbers)  
-        if '142' in mr_old.loc[0,'param']: # if flux request
-            mr_old.loc[0,'step'] = convert_param_step(mr_old.loc[0,'step'])
-
-        print('Results: ', c)
-
-        # do tests on mr files
-        lcoleq = test_mr_column_equality(mr_old, mr_new)
-        lnoeq = test_mr_number_equality(mr_old, mr_new)
-        lcoeq = test_mr_content_equality(mr_old, mr_new)
-
-        # check results for mr file
-        lfinal = lfinal and lcoleq and lnoeq and lcoeq
-
-        # write out result to logging file
-        with open(logfile, 'a') as f:
-            if lcoleq and lnoeq and lcoeq:
-                f.write('... ' + c + ' ... OK!' + '\n')
-            else:
-                f.write('... ' + c + ' ... FAILED!' + '\n')
-                if err_msg:
-                    f.write('... \t' + err_msg + '\n')
-
-        exit
-
-    # exit with success or error status
-    if lfinal:
-        sys.exit(0) # 'SUCCESS'
-    else:
-        sys.exit(1) # 'FAIL'
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""Comparison of the created MARS requests of two flex_extract versions.
+
+There will be comparisons for the given standard control files in the
+"Controls" - directory. The result of the comparison is stored in the
+"Log" - directory with an individual timestamp in the format %Y-%m-%d_%H-%M-%S.
+(E.g. log_2018-11-23_12-42-29)
+The MARS request files are named such that it contains the name of the
+corresponding control files "<control-identifier>.csv" (e.g. EA5_mr.csv).
+They are stored in the corresponding version directory and have the same
+name in both versions.
+
+The script should be called like:
+
+    python test_cmp_mars_requests.py <old_version_number> <new_version_number>
+
+Note
+----
+The MARS request files from the older version have to be in place already.
+The request files of the new/current version will be generated automatically
+with the "run_local.sh" script.
+It is necessary to have a directory named after the version number of
+flex_extract. For example: "7.0.3" and "7.1".
+
+Licence:
+--------
+    (C) Copyright 2014-2019.
+
+    SPDX-License-Identifier: CC-BY-4.0
+
+    This work is licensed under the Creative Commons Attribution 4.0
+    International License. To view a copy of this license, visit
+    http://creativecommons.org/licenses/by/4.0/ or send a letter to
+    Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
+
+Example
+-------
+    python test_cmp_mars_requests.py 7.0.4 7.1
+"""
+
+# ------------------------------------------------------------------------------
+# MODULES
+# ------------------------------------------------------------------------------
+import os
+import sys
+import pandas as pd
+import subprocess
+import shutil
+from datetime import datetime
+
+sys.path.append('../../../Source/Python')
+import _config
+from  Mods.tools import init128
+
+# ------------------------------------------------------------------------------
+# FUNCTION
+# ------------------------------------------------------------------------------
+def test_mr_column_equality(mr_old, mr_new):
+    '''Check if old and new version of MARS requests have the same
+    amount of columns.
+
+    If the number is not equal and/or the column names are not equal
+    an error message is stored in global variable "err_msg".
+
+    Parameters
+    ----------
+    mr_old : :obj:`pandas DataFrame`
+        Contains the mars requests from the old version of
+        flex_extract.
+
+    mr_new : :obj:`pandas DataFrame`
+        Contains the mars requests from the new version of
+        flex_extract.
+
+    Return
+    ------
+    bool
+        True if successful, False otherwise.
+    '''
+    global err_msg
+    if (len(mr_old.columns.values) == len(mr_new.columns.values) and
+        sorted(mr_old.columns.values) == sorted(mr_new.columns.values)):
+        return True
+    else:
+        err_msg = 'Unequal number and/or column names!\n'
+        return False
+
+
+def test_mr_number_equality(mr_old, mr_new):
+    '''Check if old and new version have the same number of requests.
+
+    If the number is not equal an error message is stored in
+    global variable "err_msg".
+
+    Parameters
+    ----------
+    mr_old : :obj:`pandas DataFrame`
+        Contains the mars requests from the old version of
+        flex_extract.
+
+    mr_new : :obj:`pandas DataFrame`
+        Contains the mars requests from the new version of
+        flex_extract.
+
+    Return
+    ------
+    bool
+        True if successful, False otherwise.
+    '''
+    global err_msg
+    if len(mr_new.index) == len(mr_old.index):
+        return True
+    else:
+        err_msg = 'Unequal number of mars requests!\n'
+        return False
+
+def test_mr_content_equality(mr_old, mr_new):
+    '''Check if old and new version have the same request contents.
+
+    If the content in a column is not equal an error message is stored in
+    global variable "err_msg", recording the column.
+
+    Parameters
+    ----------
+    mr_old : :obj:`pandas DataFrame`
+        Contains the mars requests from the old version of
+        flex_extract.
+
+    mr_new : :obj:`pandas DataFrame`
+        Contains the mars requests from the new version of
+        flex_extract.
+
+    Return
+    ------
+    bool
+        True if successful, False otherwise.
+    '''
+    global err_msg
+    lresult = None
+    columns = list(mr_new.columns.values)
+    del columns[columns.index('target')]
+    mr_new = trim_all_columns(mr_new)
+    mr_old = trim_all_columns(mr_old)
+    for col in columns:
+        if mr_new[col].equals(mr_old[col]):
+            lresult = True
+        else:
+            err_msg += 'Inconsistency in column: ' + col + '\n'
+            print("THERE SEEMS TO BE AN ERROR:")
+            print("CONTENT OF NEW VERSION:")
+            print(mr_new[col])
+            print("CONTENT OF OLD VERSION:")
+            print(mr_old[col])
+            return False
+    return lresult
+
+
+def trim_all_columns(df):
+    """
+    Trim whitespace from ends of each value across all series in dataframe
+    """
+    trim_strings = lambda x: x.strip() if isinstance(x, str) else x
+    return df.applymap(trim_strings)
+
+def convert_param_numbers(mr_old):
+    """
+    Convert the numbers parameter into integers with 3 digits.
+    """
+
+    if str(mr_old).strip() != "OFF" and mr_old != None and '/' in str(mr_old) :
+        numbers = mr_old.split('/')
+        number = str(int(numbers[0])).zfill(3)+'/TO/'+str(int(numbers[2])).zfill(3)
+
+        return number
+
+    return mr_old
+
+def convert_param_step(mr_old):
+    """
+    For pure forecast with steps greater than 23 hours, the older versions 
+    writes out a list of steps instead with the syntax 'to' and 'by'. 
+    e.g. 000/003/006/009/012/015/018/021/024/027/030/033/036
+    
+    Convert this to 0/to/36/by/3
+    """
+
+    #if 'to' in str(mr_old) and 'by' in str(mr_old):
+    #    steps = mr_old.split('/')
+    #    step = []
+    #    for i in range(int(steps[0]),int(steps[2]),int(steps[4])):
+    #        step.append(str(int(i)).zfill(2))
+    #    return '/'.join(step)
+    
+    if not mr_old.isdigit() and 'to' not in mr_old.lower():
+        if int(mr_old.split('/')[-1]) > 23:
+    
+            steps = mr_old.split('/')
+            dtime = int(steps[1]) - int(steps[0])
+            
+            nsteps = str(int(steps[1]))+'/to/'+str(int(steps[-1]))+'/by/'+str(int(dtime))
+            return nsteps            
+    
+    return mr_old
+
+def to_param_id(pars, table):
+    '''Transform parameter names to parameter ids with ECMWF grib table 128.
+
+    Parameters
+    ----------
+    pars : str
+        Addpar argument from CONTROL file in the format of
+        parameter names instead of ids. The parameter short
+        names are sepearted with "/" and they are passed as
+        one single string.
+
+    table : dict
+        Contains the ECMWF grib table 128 information.
+        The key is the parameter number and the value is the
+        short name of the parameter.
+
+    Return
+    ------
+    ipar : list of int
+        List of addpar parameters from CONTROL file transformed to
+        parameter ids in the format of integer.
+    '''
+    if not pars:
+        return []
+    if not isinstance(pars, str):
+        pars=str(pars)
+
+    cpar = pars.upper().split('/')
+    spar = []
+    for par in cpar:
+        par = par.strip()
+        for k, v in table.items():
+            if par.isdigit():
+                par = str(int(par)).zfill(3)
+            if par == k or par == v:
+                spar.append(k + '.128')
+                break
+        else:
+            print('\n\Warning: par ' + par + ' not found in table 128\n\n”')
+
+    return '/'.join(str(l) for l in spar)
+
+
+
+if __name__ == '__main__':
+
+    # basic values for paths and versions
+    control_path = 'Controls'
+    log_path = 'Log'
+    old_dir = sys.argv[1] # e.g. '7.0.4'
+    new_dir = sys.argv[2] # e.g. '7.1'
+    mr_filename = 'mars_requests.csv'
+
+    # have to be set to "True" in the beginnning
+    # so it only fails if a test fails
+    lfinal = True
+
+    # prepare log file for this test run
+    currenttime = datetime.now()
+    time_str = currenttime.strftime('%Y-%m-%d_%H-%M-%S')
+    logfile = os.path.join(log_path, 'log_' + time_str)
+    with open(logfile, 'a') as f:
+        f.write('Compare mars requests between version ' + old_dir +
+                ' and version ' + new_dir + ' : \n')
+
+    # list all controlfiles
+    controls =  os.listdir(control_path)
+
+    # loop over controlfiles
+    for c in controls:
+        # empty error message for every controlfile
+        err_msg = ''
+
+        # start flex_extract with controlfiles to get mars_request files
+        shutil.copy(os.path.join(control_path,c), _config.PATH_CONTROLFILES)
+        subprocess.check_output(['run_local.sh', new_dir, c])
+        os.remove(os.path.join(_config.PATH_CONTROLFILES,c))
+
+        # cut-of "CONTROL_" string and mv mars_reqeust file
+        # to a name including control specific name
+        mr_name = c.split('CONTROL_')[1] + '.csv'
+        shutil.move(os.path.join(new_dir,mr_filename), os.path.join(new_dir,mr_name))
+
+        # read both mr files (old & new)
+        mr_old = pd.read_csv(os.path.join(old_dir, mr_name))
+        mr_new = pd.read_csv(os.path.join(new_dir, mr_name))
+
+        mr_old.columns = mr_old.columns.str.strip()
+        mr_new.columns = mr_new.columns.str.strip()
+
+        # convert names in old to ids
+        table128 = init128(_config.PATH_GRIBTABLE)
+        #print mr_old['param']
+
+        # some format corrections are necessary to compare older versions with 7.1
+        mr_old['param'] = mr_old['param'].apply(to_param_id, args=[table128])
+        mr_old['number'] = mr_old['number'].apply(convert_param_numbers)  
+        if '142' in mr_old.loc[0,'param']: # if flux request
+            mr_old.loc[0,'step'] = convert_param_step(mr_old.loc[0,'step'])
+
+        print('Results: ', c)
+
+        # do tests on mr files
+        lcoleq = test_mr_column_equality(mr_old, mr_new)
+        lnoeq = test_mr_number_equality(mr_old, mr_new)
+        lcoeq = test_mr_content_equality(mr_old, mr_new)
+
+        # check results for mr file
+        lfinal = lfinal and lcoleq and lnoeq and lcoeq
+
+        # write out result to logging file
+        with open(logfile, 'a') as f:
+            if lcoleq and lnoeq and lcoeq:
+                f.write('... ' + c + ' ... OK!' + '\n')
+            else:
+                f.write('... ' + c + ' ... FAILED!' + '\n')
+                if err_msg:
+                    f.write('...    ' + err_msg + '\n')
+
+        exit
+
+    # exit with success or error status
+    if lfinal:
+        sys.exit(0) # 'SUCCESS'
+    else:
+        sys.exit(1) # 'FAIL'