From 0f89116d0fc1de9b182758abd84208eb9c6933b5 Mon Sep 17 00:00:00 2001
From: Anne Philipp <anne.philipp@univie.ac.at>
Date: Thu, 19 Dec 2019 21:07:12 +0100
Subject: [PATCH] diverse changes due to PEP8 style guide and eliminating
 grib2flexpart; removed unused parameter

---
 Source/Python/Classes/ControlFile.py   |  27 ++--
 Source/Python/Classes/EcFlexpart.py    | 192 +++++++++++++------------
 Source/Python/Classes/GribUtil.py      |  46 +++---
 Source/Python/Classes/MarsRetrieval.py |   5 +-
 Source/Python/Classes/UioFiles.py      |  27 ++--
 Source/Python/Mods/checks.py           |  51 +++----
 Source/Python/Mods/disaggregation.py   |  40 +++---
 Source/Python/Mods/get_mars_data.py    |  27 +++-
 Source/Python/Mods/prepare_flexpart.py |  21 ++-
 Source/Python/Mods/profiling.py        |  13 +-
 Source/Python/Mods/tools.py            |  24 ++--
 Source/Python/_config.py               |   4 +-
 Source/Python/install.py               | 113 +++++++--------
 Source/Python/submit.py                |   9 +-
 14 files changed, 295 insertions(+), 304 deletions(-)

diff --git a/Source/Python/Classes/ControlFile.py b/Source/Python/Classes/ControlFile.py
index 96e901e..ba795f2 100644
--- a/Source/Python/Classes/ControlFile.py
+++ b/Source/Python/Classes/ControlFile.py
@@ -37,14 +37,13 @@
 from __future__ import print_function
 
 import os
-import re
 import sys
-import inspect
 
 # software specific classes and modules from flex_extract
+#pylint: disable=wrong-import-position
 sys.path.append('../')
 import _config
-from Mods.tools import my_error, silent_remove
+from Mods.tools import my_error
 from Mods.checks import (check_grid, check_area, check_levels, check_purefc,
                          check_step, check_mail, check_queue, check_pathes,
                          check_dates, check_maxstep, check_type, check_request,
@@ -52,6 +51,7 @@ from Mods.checks import (check_grid, check_area, check_levels, check_purefc,
                          check_acctime, check_accmaxstep, check_time,
                          check_logicals_type, check_len_type_time_step,
                          check_addpar, check_job_chunk, check_number)
+#pylint: enable=wrong-import-position
 
 # ------------------------------------------------------------------------------
 # CLASS
@@ -64,7 +64,7 @@ class ControlFile(object):
     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
+    by the command line parameters, but in generall all parameters needed
     for a complete set of fields for FLEXPART can be set in the CONTROL file.
 
     Attributes
@@ -237,11 +237,6 @@ class ControlFile(object):
         The email addresses should be seperated by a comma.
         Default value is ['${USER}'].
 
-    grib2flexpart : int 0
-        Switch to select generation of preprocessed FLEXPART files ".fp".
-        If it is selected, the program grib2flexpart will try
-        to convert the flex_extract output files into ".fp" format.
-
     ecstorage : int
         Switch to select storage of FLEXPART ready output files
         in the ECFS file system. Default value is 0.
@@ -333,7 +328,7 @@ class ControlFile(object):
     logicals : list of str
         List of the names of logical switches which controls the flow
         of the program. Default list is ['gauss', 'omega', 'omegadiff', 'eta',
-        'etadiff', 'dpdeta', 'cwc', 'wrf', 'grib2flexpart', 'ecstorage',
+        'etadiff', 'dpdeta', 'cwc', 'wrf', 'ecstorage',
         'ectrans', 'debug', 'request', 'public', 'purefc', 'rrint', 'doubleelda']
     '''
 
@@ -399,7 +394,6 @@ class ControlFile(object):
         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
@@ -424,7 +418,7 @@ class ControlFile(object):
         self.doubleelda = 0
 
         self.logicals = ['gauss', 'omega', 'omegadiff', 'eta', 'etadiff',
-                         'dpdeta', 'cwc', 'wrf', 'grib2flexpart', 'ecstorage',
+                         'dpdeta', 'cwc', 'wrf', 'ecstorage',
                          'ectrans', 'debug', 'oper', 'request', 'public',
                          'purefc', 'rrint', 'doubleelda']
 
@@ -601,7 +595,9 @@ class ControlFile(object):
                     self.ecuid, self.ecgid)
 
         self.outputdir, self.installdir = check_pathes(self.inputdir,
-             self.outputdir, self.installdir, self.flexextractdir)
+                                                       self.outputdir,
+                                                       self.installdir,
+                                                       self.flexextractdir)
 
         self.start_date, self.end_date = check_dates(self.start_date,
                                                      self.end_date)
@@ -610,7 +606,7 @@ class ControlFile(object):
 
         self.levelist, self.level = check_levels(self.levelist, self.level)
 
-        self.step = check_step(self.step, self.mailfail)
+        self.step = check_step(self.step)
 
         self.maxstep = check_maxstep(self.maxstep, self.step)
 
@@ -648,7 +644,7 @@ class ControlFile(object):
 
         self.job_chunk = check_job_chunk(self.job_chunk)
 
-        self.number = check_number(self.number, self.mailfail)
+        self.number = check_number(self.number)
 
         return
 
@@ -694,4 +690,3 @@ class ControlFile(object):
                     l.append("%s %s\n" % item)
 
         return sorted(l)
-
diff --git a/Source/Python/Classes/EcFlexpart.py b/Source/Python/Classes/EcFlexpart.py
index 85c458c..360cbfa 100644
--- a/Source/Python/Classes/EcFlexpart.py
+++ b/Source/Python/Classes/EcFlexpart.py
@@ -52,6 +52,10 @@
 # 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
+#pylint: disable=unsubscriptable-object
+# this error is a bug
+#pylint: disable=ungrouped-imports
+# not necessary that we group the imports
 # ------------------------------------------------------------------------------
 # MODULES
 # ------------------------------------------------------------------------------
@@ -61,21 +65,21 @@ import os
 import sys
 import glob
 import shutil
-import subprocess
 from datetime import datetime, timedelta
 
 # software specific classes and modules from flex_extract
+#pylint: disable=wrong-import-position
 sys.path.append('../')
 import _config
 from Classes.GribUtil import GribUtil
 from Mods.tools import (init128, to_param_id, silent_remove, product,
-                        my_error, make_dir, get_informations, get_dimensions,
+                        my_error, get_informations, get_dimensions,
                         execute_subprocess, to_param_id_with_tablenumber,
                         generate_retrieval_period_boundary)
 from Classes.MarsRetrieval import MarsRetrieval
 from Classes.UioFiles import UioFiles
 import Mods.disaggregation as disaggregation
-
+#pylint: enable=wrong-import-position
 # ------------------------------------------------------------------------------
 # CLASS
 # ------------------------------------------------------------------------------
@@ -400,8 +404,8 @@ class EcFlexpart(object):
             self.params['OG__ML'][0] += '/U/V'
         else:  # GAUSS and ETA
             print('Warning: Collecting etadot and parameters for gaussian grid '
-                           'is a very costly parameter combination, '
-                           'use this combination only for debugging!')
+                  'is a very costly parameter combination, '
+                  'use this combination only for debugging!')
             self.params['GG__SL'] = ['Q', 'ML', '1',
                                      '{}'.format((int(self.resol) + 1) // 2)]
             self.params['GG__ML'] = ['U/V/D/ETADOT', 'ML', self.glevelist,
@@ -414,7 +418,7 @@ class EcFlexpart(object):
             self.params['OG__ML'][0] += '/CLWC/CIWC'
 
         # ADDITIONAL FIELDS FOR FLEXPART-WRF MODEL (IF QUESTIONED)
-        # -----------------------------------------------------------------------
+        # ----------------------------------------------------------------------
         if wrf:
             # @WRF
             # THIS IS NOT YET CORRECTLY IMPLEMENTED !!!
@@ -709,7 +713,8 @@ class EcFlexpart(object):
                     retr_param_dict['step'] = '000'
                     retr_param_dict['date'] = self.dates.split('/')[0]
                     retr_param_dict['target'] = self._mk_targetname('',
-                                            pk, retr_param_dict['date'])
+                                                                    pk,
+                                                                    retr_param_dict['date'])
                 elif pk == 'OG_OROLSM__SL' and oro:
                     continue
                 if pk == 'GG__SL' and pv[0] == 'Q':
@@ -751,7 +756,7 @@ class EcFlexpart(object):
                         # --------------  flux data ----------------------------
                         if 'acc' in pk:
                             startdate = retr_param_dict['date'].split('/')[0]
-                            enddate = datetime.strftime(elimit - t24h,'%Y%m%d')
+                            enddate = datetime.strftime(elimit - t24h, '%Y%m%d')
                             retr_param_dict['date'] = '/'.join([startdate,
                                                                 'to',
                                                                 enddate])
@@ -780,9 +785,9 @@ class EcFlexpart(object):
 
                         timesave = ''.join(retr_param_dict['time'])
 
-                        if ('/' in retr_param_dict['time'] and
-                            pk != 'OG_OROLSM__SL' and
-                            'acc' not in pk ) :
+                        if all(['/' in retr_param_dict['time'],
+                                pk != 'OG_OROLSM__SL',
+                                'acc' not in pk]):
                             times = retr_param_dict['time'].split('/')
                             steps = retr_param_dict['step'].split('/')
 
@@ -793,9 +798,9 @@ class EcFlexpart(object):
                                 else:
                                     retr_param_dict['time'] = times[0]
 
-                        if (pk != 'OG_OROLSM__SL' and
-                            int(retr_param_dict['step'].split('/')[0]) == 0 and
-                            int(timesave.split('/')[0]) == 0):
+                        if all([pk != 'OG_OROLSM__SL',
+                                int(retr_param_dict['step'].split('/')[0]) == 0,
+                                int(timesave.split('/')[0]) == 0]):
 
                             retr_param_dict['date'] = \
                                 datetime.strftime(elimit, '%Y%m%d')
@@ -809,7 +814,7 @@ class EcFlexpart(object):
                         self._start_retrievement(request, retr_param_dict)
                     else:
                         raise ValueError('ERROR: Basetime has an invalid value '
-                                                 '-> {}'.format(str(basetime)))
+                                         '-> {}'.format(str(self.basetime)))
 
         if request == 0 or request == 2:
             print('MARS retrieve done ... ')
@@ -859,23 +864,23 @@ class EcFlexpart(object):
             maxb = int(round((area[0] - area[2]) / grid[0])) + 1
 
             stream = namelist_template.generate(
-                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)
+                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)
             )
         except UndefinedError as e:
             print('... ERROR ' + str(e))
@@ -927,7 +932,7 @@ class EcFlexpart(object):
 
         '''
         import numpy as np
-        from eccodes import (codes_index_select, codes_new_from_index, codes_get,
+        from eccodes import (codes_index_select, codes_get,
                              codes_get_values, codes_set_values, codes_set,
                              codes_write, codes_release, codes_new_from_index,
                              codes_index_release)
@@ -1052,7 +1057,6 @@ class EcFlexpart(object):
             time = codes_get(gid, 'time') // 100  # integer
             step = codes_get(gid, 'step') # integer
             ctime = '{:0>2}'.format(time)
-            cstep = '{:0>3}'.format(step)
 
             t_date = datetime.strptime(cdate + ctime, '%Y%m%d%H')
             t_dt = t_date + timedelta(hours=step)
@@ -1131,7 +1135,7 @@ class EcFlexpart(object):
                     # do de-accumulation
                     deac_vals[parId].append(
                         (orig_vals[parId][-1] - orig_vals[parId][-2]) /
-                         int(c.dtime))
+                        int(c.dtime))
 
                 # store precipitation if new disaggregation method is selected
                 # only the exact days are needed
@@ -1331,12 +1335,12 @@ class EcFlexpart(object):
         if maxnum:
             for inum in range(maxnum):
                 for ix in range(ni*nj):
-                    lsp_new_np[inum,ix,:] = disaggregation.IA3(lsp_np[inum,ix,:])[:-1]
-                    cp_new_np[inum,ix,:] = disaggregation.IA3(cp_np[inum,ix,:])[:-1]
+                    lsp_new_np[inum, ix, :] = disaggregation.IA3(lsp_np[inum, ix, :])[:-1]
+                    cp_new_np[inum, ix, :] = disaggregation.IA3(cp_np[inum, ix, :])[:-1]
         else:
             for ix in range(ni*nj):
-                lsp_new_np[0,ix,:] = disaggregation.IA3(lsp_np[ix,:])[:-1]
-                cp_new_np[0,ix,:] = disaggregation.IA3(cp_np[ix,:])[:-1]
+                lsp_new_np[0, ix, :] = disaggregation.IA3(lsp_np[ix, :])[:-1]
+                cp_new_np[0, ix, :] = disaggregation.IA3(cp_np[ix, :])[:-1]
 
         # write to grib files (full/orig times to flux file and inbetween
         # times with step 1 and 2, respectively)
@@ -1401,46 +1405,52 @@ class EcFlexpart(object):
 
             # write original time step to flux file as usual
             fluxfile = GribUtil(os.path.join(c.inputdir, fluxfilename))
-            fluxfile.set_keys(tmpfile, filemode='ab', strict=True,
+            fluxfile.set_keys(tmpfile, filemode='ab',
                               wherekeynames=['paramId'], wherekeyvalues=[142],
-                              keynames=['perturbationNumber','date','time','stepRange','values'],
+                              keynames=['perturbationNumber', 'date', 'time',
+                                        'stepRange', 'values'],
                               keyvalues=[inumb, int(date.strftime('%Y%m%d')),
-                                         date.hour*100, 0, lsp_new_np[inumb,:,it]],
+                                         date.hour*100, 0, lsp_new_np[inumb, :, it]],
                              )
-            fluxfile.set_keys(tmpfile, filemode='ab', strict=True,
+            fluxfile.set_keys(tmpfile, filemode='ab',
                               wherekeynames=['paramId'], wherekeyvalues=[143],
-                              keynames=['perturbationNumber','date','time','stepRange','values'],
-                              keyvalues=[inumb,int(date.strftime('%Y%m%d')),
-                                         date.hour*100, 0, cp_new_np[inumb,:,it]]
+                              keynames=['perturbationNumber', 'date', 'time',
+                                        'stepRange', 'values'],
+                              keyvalues=[inumb, int(date.strftime('%Y%m%d')),
+                                         date.hour*100, 0, cp_new_np[inumb, :, it]]
                              )
 
             # rr for first subgrid point is identified by step = 1
-            fluxfile.set_keys(tmpfile, filemode='ab', strict=True,
+            fluxfile.set_keys(tmpfile, filemode='ab',
                               wherekeynames=['paramId'], wherekeyvalues=[142],
-                              keynames=['perturbationNumber','date','time','stepRange','values'],
-                              keyvalues=[inumb,int(date.strftime('%Y%m%d')),
-                                         date.hour*100, '1', lsp_new_np[inumb,:,it+1]]
-                              )
-            fluxfile.set_keys(tmpfile, filemode='ab', strict=True,
+                              keynames=['perturbationNumber', 'date', 'time',
+                                        'stepRange', 'values'],
+                              keyvalues=[inumb, int(date.strftime('%Y%m%d')),
+                                         date.hour*100, '1', lsp_new_np[inumb, :, it+1]]
+                             )
+            fluxfile.set_keys(tmpfile, filemode='ab',
                               wherekeynames=['paramId'], wherekeyvalues=[143],
-                              keynames=['perturbationNumber','date','time','stepRange','values'],
-                              keyvalues=[inumb,int(date.strftime('%Y%m%d')),
-                                         date.hour*100, '1', cp_new_np[inumb,:,it+1]]
-                              )
+                              keynames=['perturbationNumber', 'date', 'time',
+                                        'stepRange', 'values'],
+                              keyvalues=[inumb, int(date.strftime('%Y%m%d')),
+                                         date.hour*100, '1', cp_new_np[inumb, :, it+1]]
+                             )
 
             # rr for second subgrid point is identified by step = 2
-            fluxfile.set_keys(tmpfile, filemode='ab', strict=True,
+            fluxfile.set_keys(tmpfile, filemode='ab',
                               wherekeynames=['paramId'], wherekeyvalues=[142],
-                              keynames=['perturbationNumber','date','time','stepRange','values'],
-                              keyvalues=[inumb,int(date.strftime('%Y%m%d')),
-                                         date.hour*100, '2', lsp_new_np[inumb,:,it+2]]
-                              )
-            fluxfile.set_keys(tmpfile, filemode='ab', strict=True,
+                              keynames=['perturbationNumber', 'date', 'time',
+                                        'stepRange', 'values'],
+                              keyvalues=[inumb, int(date.strftime('%Y%m%d')),
+                                         date.hour*100, '2', lsp_new_np[inumb, :, it+2]]
+                             )
+            fluxfile.set_keys(tmpfile, filemode='ab',
                               wherekeynames=['paramId'], wherekeyvalues=[143],
-                              keynames=['perturbationNumber','date','time','stepRange','values'],
-                              keyvalues=[inumb,int(date.strftime('%Y%m%d')),
-                                         date.hour*100, '2', cp_new_np[inumb,:,it+2]]
-                              )
+                              keynames=['perturbationNumber', 'date', 'time',
+                                        'stepRange', 'values'],
+                              keyvalues=[inumb, int(date.strftime('%Y%m%d')),
+                                         date.hour*100, '2', cp_new_np[inumb, :, it+2]]
+                             )
 
             it = it + 3 # jump to next original time step in rr fields
         return
@@ -1462,13 +1472,13 @@ class EcFlexpart(object):
 
         '''
 
-        gribfile = GribUtil(os.path.join(inputdir,'rr_grib_dummy.grb'))
+        gribfile = GribUtil(os.path.join(inputdir, 'rr_grib_dummy.grb'))
 
         gribfile.copy_dummy_msg(ifile, keynames=['paramId'],
-                      keyvalues=[142], filemode='wb')
+                                keyvalues=[142], filemode='wb')
 
         gribfile.copy_dummy_msg(ifile, keynames=['paramId'],
-                      keyvalues=[143], filemode='ab')
+                                keyvalues=[143], filemode='ab')
 
         return
 
@@ -1500,7 +1510,7 @@ class EcFlexpart(object):
         ------
 
         '''
-        from eccodes import (codes_index_select, codes_new_from_index, codes_get,
+        from eccodes import (codes_index_select, codes_get,
                              codes_get_values, codes_set_values, codes_set,
                              codes_write, codes_release, codes_new_from_index,
                              codes_index_release)
@@ -1582,22 +1592,20 @@ class EcFlexpart(object):
             timestamp += timedelta(hours=int(cstep))
             cdate_hour = datetime.strftime(timestamp, '%Y%m%d%H')
 
+            # if basetime is used, adapt start/end date period
+            if c.basetime is not None:
+                time_delta = timedelta(hours=12-int(c.dtime))
+                start_period = datetime.strptime(c.end_date + str(c.basetime),
+                                               '%Y%m%d%H') - time_delta
+                end_period = datetime.strptime(c.end_date + str(c.basetime),
+                                             '%Y%m%d%H')
+
             # skip all temporary times
-            # which are outside the retrieval period
+            # which are outside the retrieval period                
             if timestamp < start_period or \
                timestamp > end_period:
                 continue
-
-            # if the timestamp is out of basetime start/end date period,
-            # skip this specific product
-            if c.basetime is not None:
-                time_delta = timedelta(hours=12-int(c.dtime))
-                start_time = datetime.strptime(c.end_date + str(c.basetime),
-                                                '%Y%m%d%H') - time_delta
-                end_time = datetime.strptime(c.end_date + str(c.basetime),
-                                             '%Y%m%d%H')
-                if timestamp < start_time or timestamp > end_time:
-                    continue
+                
 
             # @WRF
             # THIS IS NOT YET CORRECTLY IMPLEMENTED !!!
@@ -1619,7 +1627,6 @@ class EcFlexpart(object):
                     break
                 paramId = codes_get(gid, 'paramId')
                 gridtype = codes_get(gid, 'gridType')
-                levtype = codes_get(gid, 'typeOfLevel')
                 if paramId == 77: # ETADOT
                     codes_write(gid, fdict['21'])
                 elif paramId == 130: # T
@@ -1703,7 +1710,7 @@ class EcFlexpart(object):
 
             # Fortran program creates file fort.15 (with u,v,etadot,t,sp,q)
             execute_subprocess([os.path.join(c.exedir,
-                                _config.FORTRAN_EXECUTABLE)],
+                                             _config.FORTRAN_EXECUTABLE)],
                                error_msg='FORTRAN PROGRAM FAILED!')#shell=True)
 
             os.chdir(pwd)
@@ -1732,7 +1739,9 @@ class EcFlexpart(object):
             # create outputfile and copy all data from intermediate files
             # to the outputfile (final GRIB input files for FLEXPART)
             orolsm = os.path.basename(glob.glob(c.inputdir +
-                                        '/OG_OROLSM__SL.*.' + c.ppid + '*')[0])
+                                                '/OG_OROLSM__SL.*.' +
+                                                c.ppid +
+                                                '*')[0])
             fluxfile = 'flux' + cdate[0:2] + suffix
             if not c.cwc:
                 flist = ['fort.15', fluxfile, 'fort.16', orolsm]
@@ -1782,19 +1791,19 @@ class EcFlexpart(object):
 
         '''
         from eccodes import (codes_grib_new_from_file, codes_get_array,
-                             codes_set_array, codes_release, codes_set_values,
-                             codes_set, codes_write, codes_release)
+                             codes_set_array, codes_release,
+                             codes_set, codes_write)
 
         # max number
         maxnum = int(self.number.split('/')[-1])
 
         # get a list of all prepared output files with control forecast (CF)
-        CF_filelist = UioFiles(path, prefix + '*.N000')
-        CF_filelist.files = sorted(CF_filelist.files)
+        cf_filelist = UioFiles(path, prefix + '*.N000')
+        cf_filelist.files = sorted(cf_filelist.files)
 
-        for cffile in CF_filelist.files:
+        for cffile in cf_filelist.files:
             with open(cffile, 'rb') as f:
-                cfvalues=[]
+                cfvalues = []
                 while True:
                     fid = codes_grib_new_from_file(f)
                     if fid is None:
@@ -1899,4 +1908,3 @@ class EcFlexpart(object):
                                    'TO OUTPUTDIR FAILED!')
 
         return
-
diff --git a/Source/Python/Classes/GribUtil.py b/Source/Python/Classes/GribUtil.py
index 2a895d6..809544e 100644
--- a/Source/Python/Classes/GribUtil.py
+++ b/Source/Python/Classes/GribUtil.py
@@ -67,7 +67,7 @@ class GribUtil(object):
         return
 
 
-    def get_keys(self, keynames, wherekeynames=[], wherekeyvalues=[]):
+    def get_keys(self, keynames, wherekeynames, wherekeyvalues):
         '''Get keyvalues for a given list of keynames a where statement
         can be given (list of key and list of values)
 
@@ -76,11 +76,11 @@ class GribUtil(object):
         keynames : :obj:`list` of :obj:`string`
             List of keynames.
 
-        wherekeynames : :obj:`list` of :obj:`string`, optional
-            Default value is an empty list.
+        wherekeynames : :obj:`list` of :obj:`string`
+            List of key names for indexing grib message parameter.
 
-        wherekeyvalues : :obj:`list` of :obj:`string`, optional
-            Default value is an empty list.
+        wherekeyvalues : :obj:`list` of :obj:`string`
+            List of key values corresponding the key names.
 
         Return
         ------
@@ -121,8 +121,8 @@ class GribUtil(object):
         return return_list
 
 
-    def set_keys(self, fromfile, keynames, keyvalues, wherekeynames=[],
-                 wherekeyvalues=[], strict=False, filemode='wb'):
+    def set_keys(self, fromfile, keynames, keyvalues, wherekeynames,
+                 wherekeyvalues, filemode='wb'):
         '''Opens the file to read the grib messages and then write
         the selected messages (with wherekeys) to a new output file.
         Also, the keyvalues of the passed list of keynames are set.
@@ -140,18 +140,11 @@ class GribUtil(object):
             List of keyvalues to set in the selected messages.
             Default is an empty list.
 
-        wherekeynames : :obj:`list` of :obj:`string`, optional
+        wherekeynames : :obj:`list` of :obj:`string`
             List of keynames to select correct message.
-            Default value is an empty list.
 
-        wherekeyvalues : :obj:`list` of :obj:`string`, optional
+        wherekeyvalues : :obj:`list` of :obj:`string`
             List of keyvalues for keynames to select correct message.
-            Default value is an empty list.
-
-        strict : :obj:`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 : :obj:`string`, optional
             Sets the mode for the output file. Default is "wb".
@@ -199,8 +192,8 @@ class GribUtil(object):
 
         return
 
-    def copy_dummy_msg(self, filename_in, selectWhere=True,
-                 keynames=[], keyvalues=[], filemode='wb'):
+    def copy_dummy_msg(self, filename_in, keynames, keyvalues,
+                       selectwhere=True, filemode='wb'):
         '''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
@@ -211,16 +204,16 @@ class GribUtil(object):
         filename_in : :obj:`string`
             Filename of the input file to read the grib messages from.
 
-        selectWhere : :obj:`boolean`, optional
+        selectwhere : :obj:`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 : :obj:`list` of :obj:`string`, optional
-            List of keynames. Default is an empty list.
+        keynames : :obj:`list` of :obj:`string`
+            List of keynames.
 
-        keyvalues : :obj:`list` of :obj:`string`, optional
-            List of keyvalues. Default is an empty list.
+        keyvalues : :obj:`list` of :obj:`string`
+            List of keyvalues.
 
         filemode : :obj:`string`, optional
             Sets the mode for the output file. Default is "wb".
@@ -253,7 +246,7 @@ class GribUtil(object):
                 if not codes_is_defined(gid, key):
                     raise Exception("Key was not defined")
 
-                if selectWhere:
+                if selectwhere:
                     select = (select and (str(keyvalues[i]) ==
                                           str(codes_get(gid, key))))
                 else:
@@ -271,16 +264,15 @@ class GribUtil(object):
 
         return
 
-    def index(self, index_keys=["mars"], index_file="my.idx"):
+    def index(self, index_keys, index_file="my.idx"):
         '''Create index file from a list of files if it does not exist or
         read an index file.
 
         Parameters
         ----------
-        index_keys: :obj:`list` of :obj:`string`, optional
+        index_keys: :obj:`list` of :obj:`string`
             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: :obj:`string`, optional
             Filename where the indices are stored.
diff --git a/Source/Python/Classes/MarsRetrieval.py b/Source/Python/Classes/MarsRetrieval.py
index d68c183..105f9b9 100644
--- a/Source/Python/Classes/MarsRetrieval.py
+++ b/Source/Python/Classes/MarsRetrieval.py
@@ -41,8 +41,10 @@ import subprocess
 import traceback
 
 # software specific classes and modules from flex_extract
+#pylint: disable=wrong-import-position
 sys.path.append('../')
 import _config
+#pylint: disable=invalid-name
 try:
     ec_api = True
     import ecmwfapi
@@ -54,6 +56,8 @@ try:
     import cdsapi
 except ImportError:
     cds_api = False
+#pylint: enable=invalid-name
+#pylint: enable=wrong-import-position
 # ------------------------------------------------------------------------------
 # CLASS
 # ------------------------------------------------------------------------------
@@ -509,7 +513,6 @@ class MarsRetrieval(object):
             except Exception as e:
                 print('\n\nMARS Request failed!')
                 print(e)
-                tb = sys.exc_info()[2]
                 print(traceback.format_exc())
                 sys.exit()
 
diff --git a/Source/Python/Classes/UioFiles.py b/Source/Python/Classes/UioFiles.py
index 10bcfb1..cff0ab4 100644
--- a/Source/Python/Classes/UioFiles.py
+++ b/Source/Python/Classes/UioFiles.py
@@ -41,15 +41,17 @@ import sys
 import fnmatch
 
 # software specific modules from flex_extract
+#pylint: disable=wrong-import-position
 sys.path.append('../')
 from Mods.tools import silent_remove, get_list_as_string
+#pylint: enable=wrong-import-position
 
 # ------------------------------------------------------------------------------
 # CLASS
 # ------------------------------------------------------------------------------
 
 class UioFiles(object):
-    '''Collection of files matching a specific pattern.
+    """Collection of files matching a specific pattern.
 
     The pattern can contain regular expressions for the files.
     The files are listed and can be transformed to a single string or
@@ -61,16 +63,16 @@ class UioFiles(object):
         Directory where to list the files.
 
     pattern : str
-        Regular expression pattern. For example: '\*.grb'
+        Regular expression pattern. For example: '*.grb'
 
     files : list of str
         List of files matching the pattern in the path.
-    '''
+    """
     # --------------------------------------------------------------------------
     # CLASS METHODS
     # --------------------------------------------------------------------------
     def __init__(self, path, pattern):
-        '''Assignes a specific pattern for these files.
+        """Assignes a specific pattern for these files.
 
         Parameters
         ----------
@@ -78,12 +80,12 @@ class UioFiles(object):
             Directory where to list the files.
 
         pattern : str
-            Regular expression pattern. For example: '\*.grb'
+            Regular expression pattern. For example: '*.grb'
 
         Return
         ------
 
-        '''
+        """
 
         self.path = path
         self.pattern = pattern
@@ -95,7 +97,7 @@ class UioFiles(object):
 
 
     def _list_files(self, path):
-        '''Lists all files in the directory with the matching
+        """Lists all files in the directory with the matching
         regular expression pattern.
 
         Parameters
@@ -106,11 +108,12 @@ class UioFiles(object):
         Return
         ------
 
-        '''
+        """
         # Get the absolute path
         path = os.path.abspath(path)
 
         # get all files in the dir and subdir as absolut path
+	    # 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))
@@ -119,7 +122,7 @@ class UioFiles(object):
 
 
     def __str__(self):
-        '''Converts the list of files into a single string.
+        """Converts the list of files into a single string.
         The entries are sepereated by "," sign.
 
         Parameters
@@ -129,7 +132,7 @@ class UioFiles(object):
         ------
         files_string : str
             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=', ')
@@ -138,7 +141,7 @@ class UioFiles(object):
 
 
     def delete_files(self):
-        '''Deletes the files.
+        """Deletes the files.
 
         Parameters
         ----------
@@ -146,7 +149,7 @@ class UioFiles(object):
         Return
         ------
 
-        '''
+        """
 
         for old_file in self.files:
             silent_remove(old_file)
diff --git a/Source/Python/Mods/checks.py b/Source/Python/Mods/checks.py
index 74e7ba6..e9bc5e0 100644
--- a/Source/Python/Mods/checks.py
+++ b/Source/Python/Mods/checks.py
@@ -28,13 +28,16 @@
 from __future__ import print_function
 import os
 import sys
-
-import _config
+from datetime import datetime
+# pylint: disable=unused-import
 try:
     import exceptions
 except ImportError:
     import builtins as exceptions
-from datetime import datetime
+# pylint: enable=unused-import
+
+# software specific classes and modules from flex_extract
+import _config
 from Mods.tools import my_error, silent_remove
 # ------------------------------------------------------------------------------
 # FUNCTIONS
@@ -112,7 +115,7 @@ def check_grid(grid):
 
     return grid
 
-def check_area(grid, area, upper, lower, left , right):
+def check_area(grid, area, upper, lower, left, right):
     '''Defines the correct area string.
 
     Checks on the format of the four area components. Wether it is of
@@ -157,19 +160,19 @@ def check_area(grid, area, upper, lower, left , right):
         upper, left, lower, right = components
 
     # determine area format
-    if ((abs(float(upper) / 10000.) >= 0.01 or float(upper) / 1000. == 0. ) and
-        (abs(float(lower) / 10000.) >= 0.01 or float(lower) / 1000. == 0. ) and
-        (abs(float(left) / 10000.) >= 0.01 or float(left) / 1000. == 0. ) and
-        (abs(float(right) / 10000.) >= 0.01 or float(right) / 1000. == 0.)):
+    if all([(abs(float(upper) / 10000.) >= 0.01 or float(upper) / 1000. == 0.),
+            (abs(float(lower) / 10000.) >= 0.01 or float(lower) / 1000. == 0.),
+            (abs(float(left) / 10000.) >= 0.01 or float(left) / 1000. == 0.),
+            (abs(float(right) / 10000.) >= 0.01 or float(right) / 1000. == 0.)]):
         # area is defined in 1/1000 degrees; old format
         area = '{}/{}/{}/{}'.format(float(upper) / 1000.,
                                     float(left) / 1000.,
                                     float(lower) / 1000.,
                                     float(right) / 1000.)
-    elif (abs(float(upper) / 10000.) < 0.05 and
-          abs(float(lower) / 10000.) < 0.05 and
-          abs(float(left) / 10000.) < 0.05 and
-          abs(float(right) / 10000.) < 0.05):
+    elif all([abs(float(upper) / 10000.) < 0.05,
+              abs(float(lower) / 10000.) < 0.05,
+              abs(float(left) / 10000.) < 0.05,
+              abs(float(right) / 10000.) < 0.05]):
         # area is already in new format
         area = '{}/{}/{}/{}'.format(float(upper),
                                     float(left),
@@ -179,7 +182,7 @@ def check_area(grid, area, upper, lower, left , right):
         raise ValueError('The area components have different '
                          'formats (upper, lower, left, right): '
                          '{}/{}/{}/{}'.format(str(upper), str(lower),
-                                              str(left) , str(right)))
+                                              str(left), str(right)))
 
     return area
 
@@ -280,7 +283,7 @@ def check_purefc(ftype):
     return 0
 
 
-def check_step(step, mailfail):
+def check_step(step):
     '''Checks on step format and convert into a list of steps.
 
     If the steps were defined with "to" and "by" they are converted into
@@ -293,11 +296,6 @@ def check_step(step, mailfail):
         Specifies the forecast time step from forecast base time.
         Valid values are hours (HH) from forecast base time.
 
-    mailfail : list of str
-        Contains all email addresses which should be notified.
-        It might also contain just the ecmwf user name which will trigger
-        mailing to the associated email address for this user.
-
     Return
     ------
     step : list of str
@@ -404,7 +402,7 @@ def check_len_type_time_step(ftype, ftime, steps, maxstep, purefc):
         Specifies the forecast time step from forecast base time.
         Valid values are hours (HH) from forecast base time.
     '''
-    if not (len(ftype) == len(ftime) == len(steps)):
+    if not len(ftype) == len(ftime) == len(steps):
         raise ValueError('ERROR: The number of field types, times and steps '
                          'are not the same! Please check the setting in the '
                          'CONTROL file!')
@@ -552,7 +550,7 @@ def check_dates(start, end):
         raise ValueError('start_date was neither specified in command line nor '
                          'in CONTROL file.\n'
                          'Try "{} -h" to print usage information'
-                         .format(sys.argv[0].split('/')[-1]) )
+                         .format(sys.argv[0].split('/')[-1]))
 
     # retrieve just one day if end_date isn't set
     if not end:
@@ -789,8 +787,8 @@ def check_accmaxstep(accmaxstep, marsclass, purefc, maxstep):
         if purefc and int(accmaxstep) != int(maxstep):
             accmaxstep = maxstep
             print('... For pure forecast mode, the accumulated forecast must '
-                          'have the same maxstep as the normal forecast fields!\n'
-                          '\t\t Accmaxstep was set to maxstep!')
+                  'have the same maxstep as the normal forecast fields!\n'
+                  '\t\t Accmaxstep was set to maxstep!')
     return accmaxstep
 
 def check_addpar(addpar):
@@ -850,7 +848,7 @@ def check_job_chunk(job_chunk):
     return job_chunk
 
 
-def check_number(number, mailfail):
+def check_number(number):
     '''Check for correct string format of ensemble member numbers.
 
     Parameters
@@ -858,11 +856,6 @@ def check_number(number, mailfail):
     number : str
         List of ensemble member forecast runs.
 
-    mailfail : list of str
-        Contains all email addresses which should be notified.
-        It might also contain just the ecmwf user name which will trigger
-        mailing to the associated email address for this user.
-
     Return
     ------
     number : str
diff --git a/Source/Python/Mods/disaggregation.py b/Source/Python/Mods/disaggregation.py
index 07c593b..5a35619 100644
--- a/Source/Python/Mods/disaggregation.py
+++ b/Source/Python/Mods/disaggregation.py
@@ -246,7 +246,7 @@ def IA3(g):
             # the value at the end of the interval (fip1) is prescribed by the
             # geometric mean, restricted such that non-negativity is guaranteed
             # according to Eq. (25)
-            fip1=min( 3.*g[i] , 3.*g[i+1] , np.sqrt(g[i+1]*g[i]) )
+            fip1 = min(3. * g[i], 3. * g[i + 1], np.sqrt(g[i + 1] * g[i]))
 
             # the function value at the first sub-grid point (fi1) is determined
             # according to the equal area condition with Eq. (19)
@@ -280,10 +280,10 @@ def IA3(g):
 
                 # the monotonicity filter corrects the value at (fim1) by
                 # substituting (fim1) with (fmon), see Eq. (27), (28) and (29)
-                fmon = min(3.*g[i-2], \
-                           3.*g[i-1], \
-                           np.sqrt(max(0,(18./13.*g[i-2] - 5./13.*f[-7]) *
-                                         (18./13.*g[i-1] - 5./13.*f[-1]))))
+                fmon = min(3. * g[i - 2],
+                           3. * g[i - 1],
+                           np.sqrt(max(0, (18. / 13. * g[i - 2] - 5. / 13. * f[-7]) *
+                                       (18. / 13. * g[i - 1] - 5. / 13. * f[-1]))))
 
                 # recomputation of the sub-grid interval values while the
                 # interval boundaries (fi) and (fip2) remains unchanged
@@ -294,7 +294,7 @@ def IA3(g):
                 f[-3] = 3./2.*g[i-1]-5./12.*f[-1]-1./12.*fmon
                 f[-2] = f[-3]+(f[-1]-fmon)/3.
 
-            f.extend([0.,0.,0.])
+            f.extend([0., 0., 0.])
 
         # otherwise the sub-grid values are calculated and added to the list
         else:
@@ -305,7 +305,7 @@ def IA3(g):
             # the value at the end of the interval (fip1) is prescribed by the
             # geometric mean, restricted such that non-negativity is guaranteed
             # according to Eq. (25)
-            fip1 = min( 3.*g[i] , 3.*g[i+1] , np.sqrt(g[i+1]*g[i]) )
+            fip1 = min(3. * g[i], 3. * g[i + 1], np.sqrt(g[i + 1] * g[i]))
 
             # the function value at the first sub-grid point (fi1) is determined
             # according to the equal area condition with Eq. (19)
@@ -323,10 +323,10 @@ def IA3(g):
 
                 # the monotonicity filter corrects the value at (fim1) by
                 # substituting (fim1) with fmon, see Eq. (27), (28) and (29)
-                fmon = min(3.*g[i-2], \
-                           3.*g[i-1], \
-                           np.sqrt(max(0,(18./13.*g[i-2] - 5./13.*f[-7]) *
-                                         (18./13.*g[i-1] - 5./13.*f[-1]))))
+                fmon = min(3. * g[i - 2],
+                           3. * g[i - 1],
+                           np.sqrt(max(0, (18. / 13. * g[i - 2] - 5. / 13. * f[-7]) *
+                                       (18. / 13. * g[i - 1] - 5. / 13. * f[-1]))))
 
                 # recomputation of the sub-grid interval values while the
                 # interval boundaries (fi) and (fip2) remains unchanged
@@ -357,10 +357,10 @@ def IA3(g):
 
             # the monotonicity filter corrects the value at (fim1) by
             # substituting (fim1) with (fmon), see Eq. (27), (28) and (29)
-            fmon = min(3.*g[-3], \
-                       3.*g[-2], \
-                       np.sqrt(max(0,(18./13.*g[-3] - 5./13.*f[-7]) *
-                                     (18./13.*g[-2] - 5./13.*f[-1]))))
+            fmon = min(3. * g[-3],
+                       3. * g[-2],
+                       np.sqrt(max(0, (18. / 13. * g[-3] - 5. / 13. * f[-7]) *
+                                   (18. / 13. * g[-2] - 5. / 13. * f[-1]))))
 
             # recomputation of the sub-grid interval values while the
             # interval boundaries (fi) and (fip2) remains unchanged
@@ -371,7 +371,7 @@ def IA3(g):
             f[-3] = 3./2.*g[-2]-5./12.*f[-1]-1./12.*fmon
             f[-2] = f[-3]+(f[-1]-fmon)/3.
 
-        f.extend([0.,0.,0.])
+        f.extend([0., 0., 0.])
 
     # otherwise the sub-grid values are calculated and added to the list
     # using the persistence hypothesis as boundary condition
@@ -396,10 +396,10 @@ def IA3(g):
 
             # the monotonicity filter corrects the value at (fim1) by
             # substituting (fim1) with (fmon), see Eq. (27), (28) and (29)
-            fmon = min(3.*g[-3], \
-                       3.*g[-2], \
-                       np.sqrt(max(0,(18./13.*g[-3] - 5./13.*f[-7]) *
-                                     (18./13.*g[-2] - 5./13.*f[-1]))))
+            fmon = min(3. * g[-3],
+                       3. * g[-2],
+                       np.sqrt(max(0, (18. / 13. * g[-3] - 5. / 13. * f[-7]) *
+                                   (18. / 13. * g[-2] - 5. / 13. * f[-1]))))
 
             # recomputation of the sub-grid interval values while the
             # interval boundaries (fi) and (fip2) remains unchanged
diff --git a/Source/Python/Mods/get_mars_data.py b/Source/Python/Mods/get_mars_data.py
index 48a1d36..ecdb311 100755
--- a/Source/Python/Mods/get_mars_data.py
+++ b/Source/Python/Mods/get_mars_data.py
@@ -69,13 +69,14 @@ from datetime import datetime, timedelta
 # add path to local main python path for flex_extract to get full access
 sys.path.append(os.path.dirname(os.path.abspath(
     inspect.getfile(inspect.currentframe()))) + '/../')
+# pylint: disable=wrong-import-position
 import _config
-from Mods.tools import (setup_controldata, my_error, normal_exit, get_cmdline_args,
-                   read_ecenv, make_dir)
+from Mods.tools import (setup_controldata, my_error, normal_exit, make_dir)
 from Classes.EcFlexpart import EcFlexpart
 from Classes.UioFiles import UioFiles
 from Classes.MarsRetrieval import MarsRetrieval
-
+# pylint: enable=wrong-import-position
+# pylint: disable=invalid-name
 try:
     ec_api = True
     import ecmwfapi
@@ -87,6 +88,7 @@ try:
     import cdsapi
 except ImportError:
     cds_api = False
+# pylint: enable=invalid-name
 # ------------------------------------------------------------------------------
 # FUNCTION
 # ------------------------------------------------------------------------------
@@ -222,9 +224,22 @@ def mk_server(c):
 
 
 def check_dates_for_nonflux_fc_times(types, times):
+    '''Checks if the time 18UTC corresponds to forecast field.
+
+    Parameters
+    ----------
+    types : list of str
+        List of field types.
+
+    times : list of str or str
+        The time in hours of the field.
+
+    Return
+    ------
+    True or False
+
     '''
-    '''
-    for ty, ti in zip(types,times):
+    for ty, ti in zip(types, times):
         if ty.upper() == 'FC' and int(ti) == 18:
             return True
     return False
@@ -244,7 +259,7 @@ def mk_dates(c, fluxes):
     boundary conditions)
 
     Since for basetime the extraction contains the 12 hours upfront,
-    if basetime is 0, the starting date has to be the day before and
+    if basetime is 0, the starting date has to be the day before
 
     Parameters
     ----------
diff --git a/Source/Python/Mods/prepare_flexpart.py b/Source/Python/Mods/prepare_flexpart.py
index 5c1fd47..5732324 100755
--- a/Source/Python/Mods/prepare_flexpart.py
+++ b/Source/Python/Mods/prepare_flexpart.py
@@ -37,7 +37,9 @@
 #    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.
-#*******************************************************************************
+# *******************************************************************************
+# pylint: disable=ungrouped-imports
+# not necessary that we group the imports
 '''This script prepares the final version of the grib files which are
 then used by FLEXPART.
 
@@ -67,19 +69,19 @@ import datetime
 import os
 import inspect
 import sys
-import socket
 
 # software specific classes and modules from flex_extract
 # add path to local main python path for flex_extract to get full access
 sys.path.append(os.path.dirname(os.path.abspath(
     inspect.getfile(inspect.currentframe()))) + '/../')
-import _config
+# pylint: disable=wrong-import-position
+#import _config
 from Mods.checks import check_ppid
 from Classes.UioFiles import UioFiles
-from Classes.ControlFile import ControlFile
-from Mods.tools import (setup_controldata, clean_up, get_cmdline_args,
-                        read_ecenv, make_dir, normal_exit)
+#from Classes.ControlFile import ControlFile
+from Mods.tools import (setup_controldata, clean_up, make_dir, normal_exit)
 from Classes.EcFlexpart import EcFlexpart
+# pylint: enable=wrong-import-position
 
 # ------------------------------------------------------------------------------
 # FUNCTION
@@ -145,7 +147,7 @@ def prepare_flexpart(ppid, c):
         start = start - datetime.timedelta(days=1)
 
     print('Prepare ' + start.strftime("%Y%m%d") +
-           "/to/" + end.strftime("%Y%m%d"))
+          '/to/' + end.strftime("%Y%m%d"))
 
     # create output dir if necessary
     if not os.path.exists(c.outputdir):
@@ -170,11 +172,6 @@ def prepare_flexpart(ppid, c):
         flexpart.calc_extra_elda(c.inputdir, c.prefix)
     flexpart.process_output(c)
 
-    # make use of a possible conversion to a
-    # specific flexpart binary format
-    if c.grib2flexpart:
-        flexpart.prepare_fp_files(c)
-
     # check if in debugging mode, then store all files
     # otherwise delete temporary files
     if c.debug:
diff --git a/Source/Python/Mods/profiling.py b/Source/Python/Mods/profiling.py
index c95e4e0..0439377 100644
--- a/Source/Python/Mods/profiling.py
+++ b/Source/Python/Mods/profiling.py
@@ -36,12 +36,12 @@ import time
 # ------------------------------------------------------------------------------
 # FUNCTION
 # ------------------------------------------------------------------------------
-def timefn(fn):
+def timefn(func):
     '''
     @Description:
         Decorator function. It takes the inner function as an argument.
     '''
-    @wraps(fn)
+    @wraps(func)
     def measure_time(*args, **kwargs):
         '''
         @Descripton:
@@ -64,10 +64,11 @@ def timefn(fn):
             <nothing>
         '''
 
-        t1 = time.time()
-        result = fn(*args, **kwargs)
-        t2 = time.time()
-        print("@timefn:" + fn.__name__ + " took " + str(t2 - t1) + " seconds")
+        time1 = time.time()
+        result = func(*args, **kwargs)
+        time2 = time.time()
+        print("@timefn:" + func.__name__ + " took " +
+              str(time2 - time1) + " seconds")
 
         return result
 
diff --git a/Source/Python/Mods/tools.py b/Source/Python/Mods/tools.py
index 078c77e..32c865c 100644
--- a/Source/Python/Mods/tools.py
+++ b/Source/Python/Mods/tools.py
@@ -68,10 +68,12 @@ import sys
 import glob
 import subprocess
 import traceback
+# pylint: disable=unused-import
 try:
     import exceptions
 except ImportError:
     import builtins as exceptions
+# pylint: enable=unused-import
 from datetime import datetime, timedelta
 from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
 
@@ -267,7 +269,7 @@ def read_ecenv(filepath):
         Contains the environment parameter ecuid, ecgid, gateway
         and destination for ECMWF server environments.
     '''
-    envs= {}
+    envs = {}
     try:
         with open(filepath, 'r') as f:
             for line in f:
@@ -278,7 +280,7 @@ def read_ecenv(filepath):
         print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
 
         sys.exit('\n... Error occured while trying to read ECMWF_ENV '
-                     'file: ' + str(filepath))
+                 'file: ' + str(filepath))
 
     return envs
 
@@ -301,8 +303,9 @@ def clean_up(c):
 
     print("... clean inputdir!")
 
-    cleanlist = [file for file in glob.glob(os.path.join(c.inputdir, "*"))
-                 if not os.path.basename(file).startswith(c.prefix)]
+    cleanlist = [filename for filename in
+                 glob.glob(os.path.join(c.inputdir, "*"))
+                 if not os.path.basename(filename).startswith(c.prefix)]
 
     if cleanlist:
         for element in cleanlist:
@@ -370,7 +373,7 @@ def send_mail(users, success_mode, message):
                                  stdout=subprocess.PIPE,
                                  stderr=subprocess.PIPE,
                                  bufsize=1)
-            pout = p.communicate(input=message.encode() + '\n\n')[0]
+            pout = p.communicate(input=message + '\n\n')[0]
         except ValueError as e:
             print('... ERROR: ' + str(e))
             sys.exit('... Email could not be sent!')
@@ -530,7 +533,7 @@ def to_param_id(pars, table):
     if not pars:
         return []
     if not isinstance(pars, str):
-        pars=str(pars)
+        pars = str(pars)
 
     cpar = pars.upper().split('/')
     ipar = []
@@ -574,7 +577,7 @@ def to_param_id_with_tablenumber(pars, table):
     if not pars:
         return []
     if not isinstance(pars, str):
-        pars=str(pars)
+        pars = str(pars)
 
     cpar = pars.upper().split('/')
     spar = []
@@ -767,8 +770,7 @@ def get_informations(filename):
         gid = codes_grib_new_from_file(f)
 
         # information needed from grib message
-        keys = [
-                'Ni',
+        keys = ['Ni',
                 'Nj',
                 'latitudeOfFirstGridPointInDegrees',
                 'longitudeOfFirstGridPointInDegrees',
@@ -782,8 +784,8 @@ def get_informations(filename):
         print('\nInformations are: ')
         for key in keys:
             # Get the value of the key in a grib message.
-            data[key] = codes_get(gid,key)
-            print("%s = %s" % (key,data[key]))
+            data[key] = codes_get(gid, key)
+            print("%s = %s" % (key, data[key]))
 
         # Free the memory for the message referred as gribid.
         codes_release(gid)
diff --git a/Source/Python/_config.py b/Source/Python/_config.py
index 03126f7..82b7bc0 100644
--- a/Source/Python/_config.py
+++ b/Source/Python/_config.py
@@ -53,7 +53,7 @@ MAX_LEVEL_LIST = [16, 19, 31, 40, 50, 60, 62, 91, 137]
 # ------------------------------------------------------------------------------
 
 FILE_MARS_REQUESTS = 'mars_requests.csv'
-FORTRAN_EXECUTABLE = 'CONVERT2'
+FORTRAN_EXECUTABLE = 'calc_etadot'
 TEMPFILE_USER_ENVVARS = 'ECMWF_ENV.template'
 FILE_USER_ENVVARS = 'ECMWF_ENV'
 TEMPFILE_INSTALL_COMPILEJOB = 'compilejob.template'
@@ -96,7 +96,7 @@ PATH_JOBSCRIPTS = os.path.join(PATH_RUN_DIR, 'Jobscripts')
 PATH_FORTRAN_SRC = os.path.join(PATH_SOURCES, 'Fortran')
 PATH_PYTHONTEST_SRC = os.path.join(PATH_SOURCES, 'Pythontest')
 PATH_INPUT_DIR = os.path.join(PATH_RUN_DIR, INPUT_DIRNAME_DEFAULT)
-PATH_TEST = os.path.join(PATH_FLEXEXTRACT_DIR, 'Test')
+PATH_TEST = os.path.join(PATH_FLEXEXTRACT_DIR, 'Testing')
 if os.getenv('CONTROL'):
     # this is only needed if (gateway) version with job script is used!
     # because job is directly submitted from SCRATCH and because the
diff --git a/Source/Python/install.py b/Source/Python/install.py
index db8c736..9a3e17a 100755
--- a/Source/Python/install.py
+++ b/Source/Python/install.py
@@ -67,9 +67,7 @@ from __future__ import print_function
 
 import os
 import sys
-import glob
 import subprocess
-import inspect
 import tarfile
 from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
 
@@ -178,16 +176,13 @@ def install_via_gateway(c):
     ------
 
     '''
-    import tarfile
 
     tarball_name = _config.FLEXEXTRACT_DIRNAME + '.tar'
     tar_file = os.path.join(_config.PATH_FLEXEXTRACT_DIR, tarball_name)
 
-    mk_compilejob(c.makefile, c.install_target, c.ecuid, c.ecgid,
-                  c.installdir)
+    mk_compilejob(c.makefile, c.ecuid, c.ecgid, c.installdir)
 
-    mk_job_template(c.ecuid, c.ecgid, c.gateway,
-                    c.destination, c.installdir)
+    mk_job_template(c.ecuid, c.ecgid, c.installdir)
 
     mk_env_vars(c.ecuid, c.ecgid, c.gateway, c.destination)
 
@@ -204,7 +199,7 @@ def install_via_gateway(c):
 
     print('Job compilation script has been submitted to ecgate for ' +
           'installation in ' + c.installdir +
-           '/' + _config.FLEXEXTRACT_DIRNAME)
+          '/' + _config.FLEXEXTRACT_DIRNAME)
     print('You should get an email with subject "flexcompile" within ' +
           'the next few minutes!')
 
@@ -223,12 +218,11 @@ def install_local(c):
     ------
 
     '''
-    import tarfile
 
     tar_file = os.path.join(_config.PATH_FLEXEXTRACT_DIR,
                             _config.FLEXEXTRACT_DIRNAME + '.tar')
 
-    if c.installdir == _config.PATH_FLEXEXTRACT_DIR :
+    if c.installdir == _config.PATH_FLEXEXTRACT_DIR:
         print('WARNING: installdir has not been specified')
         print('flex_extract will be installed in here by compiling the ' +
               'Fortran source in ' + _config.PATH_FORTRAN_SRC)
@@ -240,12 +234,12 @@ def install_local(c):
            os.path.abspath(c.installdir):
             mk_tarball(tar_file, c.install_target)
             make_dir(os.path.join(c.installdir,
-                                   _config.FLEXEXTRACT_DIRNAME))
+                                  _config.FLEXEXTRACT_DIRNAME))
             os.chdir(os.path.join(c.installdir,
-                                   _config.FLEXEXTRACT_DIRNAME))
+                                  _config.FLEXEXTRACT_DIRNAME))
             un_tarball(tar_file)
             os.chdir(os.path.join(c.installdir,
-                                   _config.FLEXEXTRACT_DIRNAME,
+                                  _config.FLEXEXTRACT_DIRNAME,
                                   _config.PATH_REL_FORTRAN_SRC))
 
     # Create Fortran executable - CONVERT2
@@ -285,7 +279,7 @@ def check_install_conditions(c):
         print('ERROR: unknown or missing installation target ')
         print('target: ', c.install_target)
         print('please specify correct installation target ' +
-              str(INSTALL_TARGETS))
+              str(_config.INSTALL_TARGETS))
         print('use -h or --help for help')
         sys.exit(1)
 
@@ -333,7 +327,6 @@ def mk_tarball(tarball_path, target):
     ------
 
     '''
-    from glob import glob
 
     print('Create tarball ...')
 
@@ -344,33 +337,33 @@ def mk_tarball(tarball_path, target):
 
     # get lists of the files to be added to the tar file
     if target == 'local':
-        ECMWF_ENV_FILE = []
+        ecmwf_env_file = []
         runfile = [os.path.relpath(x, ecd)
                    for x in UioFiles(_config.PATH_REL_RUN_DIR,
                                      'run_local.sh').files]
     else:
-        ECMWF_ENV_FILE = [_config.PATH_REL_ECMWF_ENV]
+        ecmwf_env_file = [_config.PATH_REL_ECMWF_ENV]
         runfile = [os.path.relpath(x, ecd)
-                       for x in UioFiles(_config.PATH_REL_RUN_DIR,
-                                         'run.sh').files]
+                   for x in UioFiles(_config.PATH_REL_RUN_DIR,
+                                     'run.sh').files]
 
     pyfiles = [os.path.relpath(x, ecd)
                for x in UioFiles(_config.PATH_REL_PYTHON_SRC, '*py').files]
     pytestfiles = [os.path.relpath(x, ecd)
-               for x in UioFiles(_config.PATH_REL_PYTHONTEST_SRC, '*py').files]
+                   for x in UioFiles(_config.PATH_REL_PYTHONTEST_SRC, '*py').files]
     controlfiles = [os.path.relpath(x, ecd)
                     for x in UioFiles(_config.PATH_REL_CONTROLFILES,
                                       'CONTROL*').files]
     testfiles = [os.path.relpath(x, ecd)
-                 for x in UioFiles(_config.PATH_REL_TEST , '*').files]
+                 for x in UioFiles(_config.PATH_REL_TEST, '*').files]
     tempfiles = [os.path.relpath(x, ecd)
-                 for x in UioFiles(_config.PATH_REL_TEMPLATES , '*.temp').files]
+                 for x in UioFiles(_config.PATH_REL_TEMPLATES, '*.temp').files]
     nlfiles = [os.path.relpath(x, ecd)
-                 for x in UioFiles(_config.PATH_REL_TEMPLATES , '*.nl').files]
+               for x in UioFiles(_config.PATH_REL_TEMPLATES, '*.nl').files]
     gribtable = [os.path.relpath(x, ecd)
-                 for x in UioFiles(_config.PATH_REL_TEMPLATES , '*grib*').files]
+                 for x in UioFiles(_config.PATH_REL_TEMPLATES, '*grib*').files]
     ffiles = [os.path.relpath(x, ecd)
-              for x in UioFiles(_config.PATH_REL_FORTRAN_SRC, '*.f*').files]
+              for x in UioFiles(_config.PATH_REL_FORTRAN_SRC, '*.f90').files]
     hfiles = [os.path.relpath(x, ecd)
               for x in UioFiles(_config.PATH_REL_FORTRAN_SRC, '*.h').files]
     makefiles = [os.path.relpath(x, ecd)
@@ -379,23 +372,25 @@ def mk_tarball(tarball_path, target):
 
     # concatenate single lists to one for a better looping
     filelist = pyfiles + pytestfiles + controlfiles + tempfiles + nlfiles + \
-               ffiles + gribtable + hfiles + makefiles + ECMWF_ENV_FILE + \
+               ffiles + gribtable + hfiles + makefiles + ecmwf_env_file + \
                runfile + jobdir + testfiles +\
                ['CODE_OF_CONDUCT.md', 'LICENSE.md', 'README.md']
 
     # create installation tar-file
-    exclude_files = [".ksh"]
+    exclude_files = [".ksh", ".tar"]
     try:
         with tarfile.open(tarball_path, "w:gz") as tar_handle:
-            for file in filelist:
-                tar_handle.add(file, recursive=False,
+            for filename in filelist:
+                tar_handle.add(filename, recursive=False,
                                filter=lambda tarinfo: None
-                                      if os.path.splitext(tarinfo.name)[1]
-                                         in exclude_files
-                                      else tarinfo)
+                               if os.path.splitext(tarinfo.name)[1]
+                               in exclude_files
+                               else tarinfo)
     except tarfile.TarError as e:
+        print('... ERROR: ' + str(e))
+
         sys.exit('\n... error occured while trying to create the tar-file ' +
-                     str(tarball_path))
+                 str(tarball_path))
 
     return
 
@@ -421,7 +416,7 @@ def un_tarball(tarball_path):
             tar_handle.extractall()
     except tarfile.TarError as e:
         sys.exit('\n... error occured while trying to read tar-file ' +
-                     str(tarball_path))
+                 str(tarball_path))
     except OSError as e:
         print('... ERROR CODE: ' + str(e.errno))
         print('... ERROR MESSAGE:\n \t ' + str(e.strerror))
@@ -464,11 +459,11 @@ def mk_env_vars(ecuid, ecgid, gateway, destination):
         ecmwfvars_template = loader.load(_config.TEMPFILE_USER_ENVVARS,
                                          cls=NewTextTemplate)
 
-        stream = ecmwfvars_template.generate(user_name = ecuid,
-                                             user_group = ecgid,
-                                             gateway_name = gateway,
-                                             destination_name = destination
-                                             )
+        stream = ecmwfvars_template.generate(user_name=ecuid,
+                                             user_group=ecgid,
+                                             gateway_name=gateway,
+                                             destination_name=destination
+                                            )
     except UndefinedError as e:
         print('... ERROR ' + str(e))
 
@@ -493,7 +488,7 @@ def mk_env_vars(ecuid, ecgid, gateway, destination):
 
     return
 
-def mk_compilejob(makefile, target, ecuid, ecgid, fp_root):
+def mk_compilejob(makefile, ecuid, ecgid, fp_root):
     '''Modifies the original job template file so that it is specified
     for the user and the environment were it will be applied. Result
     is stored in a new file "job.temp" in the python directory.
@@ -504,9 +499,6 @@ def mk_compilejob(makefile, target, ecuid, ecgid, fp_root):
         Name of the makefile which should be used to compile FORTRAN
         CONVERT2 program.
 
-    target : str
-        The target where the installation should be done, e.g. the queue.
-
     ecuid : str
         The user id on ECMWF server.
 
@@ -534,12 +526,12 @@ def mk_compilejob(makefile, target, ecuid, ecgid, fp_root):
                                        cls=NewTextTemplate)
 
         stream = compile_template.generate(
-            usergroup = ecgid,
-            username = ecuid,
-            version_number = _config._VERSION_STR,
-            fp_root_scripts = fp_root,
-            makefile = makefile,
-            fortran_program = _config.FORTRAN_EXECUTABLE
+            usergroup=ecgid,
+            username=ecuid,
+            version_number=_config._VERSION_STR,
+            fp_root_scripts=fp_root,
+            makefile=makefile,
+            fortran_program=_config.FORTRAN_EXECUTABLE
         )
     except UndefinedError as e:
         print('... ERROR ' + str(e))
@@ -568,7 +560,7 @@ def mk_compilejob(makefile, target, ecuid, ecgid, fp_root):
 
     return
 
-def mk_job_template(ecuid, ecgid, gateway, destination, fp_root):
+def mk_job_template(ecuid, ecgid, fp_root):
     '''Modifies the original job template file so that it is specified
     for the user and the environment were it will be applied. Result
     is stored in a new file.
@@ -581,13 +573,6 @@ def mk_job_template(ecuid, ecgid, gateway, destination, fp_root):
     ecgid : str
         The group id on ECMWF server.
 
-    gateway : str
-        The gateway server the user is using.
-
-    destination : str
-        The remote destination which is used to transfer files
-        from ECMWF server to local gateway server.
-
     fp_root : str
        Path to the root directory of FLEXPART environment or flex_extract
        environment.
@@ -614,10 +599,10 @@ def mk_job_template(ecuid, ecgid, gateway, destination, fp_root):
                                        cls=NewTextTemplate)
 
         stream = compile_template.generate(
-            usergroup = ecgid,
-            username = ecuid,
-            version_number = _config._VERSION_STR,
-            fp_root_path = fp_root_path_to_python,
+            usergroup=ecgid,
+            username=ecuid,
+            version_number=_config._VERSION_STR,
+            fp_root_path=fp_root_path_to_python,
         )
     except UndefinedError as e:
         print('... ERROR ' + str(e))
@@ -710,9 +695,9 @@ def mk_convert_build(src_path, makefile):
         print('ERROR: Makefile call failed:')
         print(e)
     else:
-        execute_subprocess(['ls', '-l', os.path.join(src_path,
-                            _config.FORTRAN_EXECUTABLE)], error_msg=
-                           'FORTRAN EXECUTABLE COULD NOT BE FOUND!')
+        execute_subprocess(['ls', '-l',
+                            os.path.join(src_path, _config.FORTRAN_EXECUTABLE)],
+                           error_msg='FORTRAN EXECUTABLE COULD NOT BE FOUND!')
 
     return
 
diff --git a/Source/Python/submit.py b/Source/Python/submit.py
index 62a042a..885c030 100755
--- a/Source/Python/submit.py
+++ b/Source/Python/submit.py
@@ -63,18 +63,15 @@ from __future__ import print_function
 
 import os
 import sys
-import subprocess
-import inspect
-import collections
 from datetime import datetime, timedelta
 
 # software specific classes and modules from flex_extract
 import _config
-from Mods.tools import (setup_controldata, normal_exit, get_cmdline_args,
-                         submit_job_to_ecserver, read_ecenv)
+from Mods.tools import (setup_controldata, normal_exit,
+                        submit_job_to_ecserver)
 from Mods.get_mars_data import get_mars_data
 from Mods.prepare_flexpart import prepare_flexpart
-from Classes.ControlFile import ControlFile
+#from Classes.ControlFile import ControlFile
 
 
 # ------------------------------------------------------------------------------
-- 
GitLab