diff --git a/MAJA2THEIAFormat.py b/MAJA2THEIAFormat.py
index 89b1e241704b280cf19a9f937eff6fb9e0aa72a9..412060f7346cea140c0d426d1d7ecbdca8cafc4a 100644
--- a/MAJA2THEIAFormat.py
+++ b/MAJA2THEIAFormat.py
@@ -67,11 +67,11 @@ def maja2theia(infld,outfld):
     shutil.copyfile(clmin1, clmout1)
     shutil.copyfile(clmin2, clmout2)
 
-    mtd = open(outfld + os.sep + basename + '_MTD_ALL.xml','wb')
+    mtd = open(outfld + os.sep + basename + '_MTD_ALL.xml','w')
     mtd.write('*** Dummy metadata file for MAJA outcome to match THEIA format ***\n')
     mtd.close()
 
-    print 'Reformat complete!'
+    print('Reformat complete!')
 
 
 if __name__ == '__main__':
@@ -100,9 +100,9 @@ if __name__ == '__main__':
             if removing:
                 shutil.rmtree(fld)
     elif len(lst) > 0 :
-        print args[0].rstrip(os.sep)
+        print(args[0].rstrip(os.sep))
         maja2theia(args[0].rstrip(os.sep), ofld)
         if removing:
             shutil.rmtree(args[0])
     else:
-        print "No MAJA products found in folder " + args[0]
+        print("No MAJA products found in folder " + args[0])
diff --git a/TimeSeries_allpreprocess.py b/TimeSeries_allpreprocess.py
index 3389fff7c53806126a6006e6bb883829dd0e9bee..230d2d85ed6b651e4b337a9bb2d581f4f3cb7af7 100644
--- a/TimeSeries_allpreprocess.py
+++ b/TimeSeries_allpreprocess.py
@@ -84,8 +84,8 @@ def main(argv):
     if os.path.exists(download_folder) == True:
         skip = None
         while skip not in ['y','n'] :
-            print "%s already exists, do you want to skip download step ? (y/n)" % download_folder
-            skip = raw_input().lower()
+            print("%s already exists, do you want to skip download step ? (y/n)" % download_folder)
+            skip = input().lower()
         if skip == 'n':
             shutil.rmtree(download_folder)
             if download_platform == 'S2PEPS':
@@ -109,7 +109,7 @@ def main(argv):
 
     preprocess_folder = os.path.join(output_folder, pattern)
     if download_platform == 'S2PEPS':
-        print "Prepare S2PEPS files"
+        print("Prepare S2PEPS files")
         cmd = ['python', cmd_path + 'prepareS2PEPS.py', '-o', preprocess_folder, '-c', shp_file, download_folder]
         subprocess.call(cmd, shell=sh)
         cmd_list = []
@@ -120,7 +120,7 @@ def main(argv):
         # cmd = ['bash', cmd_path + 'S2PEPSPreparation.sh']
         # subprocess.call(cmd, shell=sh)
     elif download_platform == 'S2THEIA':
-        print "Prepare S2THEIA files"
+        print("Prepare S2THEIA files")
         cmd = ['python', cmd_path + 'prepareS2THEIA.py', '-o', preprocess_folder, '-c', shp_file, download_folder]
         subprocess.call(cmd, shell=sh)
         cmd_list = []
@@ -131,7 +131,7 @@ def main(argv):
         # cmd = ['bash', cmd_path + 'S2THEIAPreparation.sh']
         # subprocess.call(cmd, shell=sh)
     elif download_platform == 'VenusTHEIA':
-        print "Prepare VenusTHEIA files"
+        print("Prepare VenusTHEIA files")
         cmd = ['python', cmd_path + 'prepareVENUS.py', '-o', preprocess_folder, '-c', shp_file, download_folder]
         subprocess.call(cmd, shell=sh)
         cmd_list = []
@@ -144,7 +144,7 @@ def main(argv):
 
     if remove_src == True :
         shutil.rmtree(download_folder)
-    print "Preprocess %s files" % download_platform
+    print("Preprocess %s files" % download_platform)
     cmd = ['python', cmd_path + 'genProcessScript.py', '--cloudmask', preprocess_folder]
     subprocess.call(cmd, shell=sh)
     cmd_list = []
@@ -155,7 +155,7 @@ def main(argv):
     # cmd = ['bash', cmd_path + 'ProcessScript.sh']
     # subprocess.call(cmd, shell=sh)
 
-    print "Gapfilling %s files" % download_platform
+    print("Gapfilling %s files" % download_platform)
     gapf_folder = os.path.join(output_folder, pattern + '_GAPF')
     cmd = ['python', 'cloudfreeComposites.py', '-o', gapf_folder]
     if dates_file != None :
diff --git a/batchUnzip.py b/batchUnzip.py
index 26c58b2b0be39d43049905cd014b03d63a7fe15f..b1c52dbd159bbfac57dab613c423d273852fae72 100644
--- a/batchUnzip.py
+++ b/batchUnzip.py
@@ -9,7 +9,7 @@ def unzip(argv):
     try:
         opts, args = getopt.getopt(argv, 'ro:')
     except getopt.GetoptError as err:
-        print str(err)
+        print(str(err))
 
     od = args[-1]
     removeZip = False
diff --git a/classificationWorkflow.py b/classificationWorkflow.py
index 3249766e5c6f89389fe65a42983fbeadbcc95f24..d16e445bc935bf48843af9608e331279d06a6b34 100644
--- a/classificationWorkflow.py
+++ b/classificationWorkflow.py
@@ -311,12 +311,12 @@ def splitShapefileByClasses(shp,code):
     sep = {}
     for f in ly:
         cl = f.GetField(code)
-        if cl not in sep.keys():
+        if cl not in list(sep.keys()):
             sep[cl] = []
         sep[cl].append(f)
 
     ds_dict = {}
-    for cl in sep.keys():
+    for cl in list(sep.keys()):
         fn = shp.replace('.shp','_' + code + '_' + str(cl) + '.shp')
         ds_dict[cl] = fn
         dsi = cloneVectorDataStructure(ds,fn)
@@ -345,7 +345,7 @@ def retrieveClassHierarchy(shp,code_list):
             clist = list(np.unique(nomen[-1][np.where(nomen[i - 1] == cl)[0]]))
             h_dict[code_list[i]][1].append([ds_dict[x] for x in clist])
 
-    return h_dict,ds_dict.values()
+    return h_dict,list(ds_dict.values())
 
 def Htraining(shp,code_list,model_fld,params,feat,feat_mode = 'list'):
     '''
@@ -415,11 +415,11 @@ def Htraining(shp,code_list,model_fld,params,feat,feat_mode = 'list'):
     # Computes classes hierarchy in a dictionnary
     h_dict, ds_list = retrieveClassHierarchy(shp,code_list)
     # Create models for each level
-    with open(h_model_fld + '/h-model.csv',mode='wb') as h_model_file:
+    with open(h_model_fld + '/h-model.csv',mode='w') as h_model_file:
         writer = csv.writer(h_model_file)
         level = 'ROOT'
-        last = h_dict.keys()[-1]
-        for code in h_dict.keys():
+        last = list(h_dict.keys())[-1]
+        for code in list(h_dict.keys()):
             Nsb = len(h_dict[code][0])
             for i in range(Nsb):
                 model_file = h_model_fld + '/' + classifier + '_' + code + '_' + str(h_dict[code][0][i]) + '.model'
@@ -472,7 +472,7 @@ def Hclassify(shp_list,stat_file,h_model_fld,feat,out_fld,out_ext,feat_mode = 'l
 
     out_file_list = []
     for shp in shp_list:
-        with open(h_model_fld + '/h-model.csv', mode='rb') as h_model_file:
+        with open(h_model_fld + '/h-model.csv', mode='r') as h_model_file:
             toProcess = []
             toDelete = []
             toMerge = []
@@ -504,8 +504,8 @@ def Hclassify(shp_list,stat_file,h_model_fld,feat,out_fld,out_ext,feat_mode = 'l
                     #classification by classes to use as bases for next level 
                     if row[4] == 'True':
                         ds_dict = splitShapefileByClasses(split_shp,'p'+row[3])
-                        [toProcess.insert(0,x) for x in ds_dict.values()]
-                        toDelete.extend(ds_dict.values())
+                        [toProcess.insert(0,x) for x in list(ds_dict.values())]
+                        toDelete.extend(list(ds_dict.values()))
                     #last level of hierarchy classes, to merge
                     elif row[4] == 'False':
                         toMerge.append(in_shp)
diff --git a/cloudMask.py b/cloudMask.py
index 20bfcade8807e4fac31961f2f982f77ab59cb1fa..38b9f086c8b323fda1930da7beeb112d4692d7e8 100644
--- a/cloudMask.py
+++ b/cloudMask.py
@@ -38,7 +38,7 @@ def createMaskFromFmaskOutput(fin, fout):
 
 
 def L8_CloudMask(fld, hr):
-    print 'Computing cloud mask...'
+    print('Computing cloud mask...')
 
     if platform.system() == 'Linux':
         gdl_merge = ['gdal_merge.py', '-separate', '-of', 'GTiff', '-o']
@@ -153,7 +153,7 @@ def L8_CloudMask(fld, hr):
 
 
 def S2_CloudMask(fld, hr):
-    print 'Computing cloud mask...'
+    print('Computing cloud mask...')
 
     if hr:
         res = '10'
@@ -221,7 +221,7 @@ def main(argv):
     try:
         opts, args = getopt.getopt(argv, 'h', ['HR'])
     except getopt.GetoptError as err:
-        print str(err)
+        print(str(err))
 
     hr = False
 
diff --git a/cloudfreeComposites.py b/cloudfreeComposites.py
index 170b0de74a42930437e66268fc080ed47f4cda27..3e65a5f2190f01a15750f08186ca193a2d8219e0 100644
--- a/cloudfreeComposites.py
+++ b/cloudfreeComposites.py
@@ -104,7 +104,7 @@ def rebuildSeries(stack_fn, nc, od_fn, out_fld):
             fn = 'GAPF_MTL.txt'
         elif nm[0] == 'VENUS-L2A-THEIA':
             fn = 'GAPF_L2VALD.HDR'
-        with open(out_fld + '/' + onm + '/' + fn,'wb') as mf:
+        with open(out_fld + '/' + onm + '/' + fn,'w') as mf:
             mf.write('*** Dummy metadata file for ' + nm[0] + ' ***')
 
 
diff --git a/computeFeatures.py b/computeFeatures.py
index 66a950f4ad96906f49d361cb7542af20495362ca..c534f6b8905df08a7fdfe3cb611b1a69b8642234 100644
--- a/computeFeatures.py
+++ b/computeFeatures.py
@@ -1,4 +1,4 @@
-import ConfigParser
+import configparser
 import getopt
 import glob
 import json
@@ -14,7 +14,7 @@ from mtdUtils import setNoDataValue
 
 
 def readConfigFile(cfg_fn, section):
-    config = ConfigParser.ConfigParser()
+    config = configparser.ConfigParser()
     config.read(cfg_fn)
     out = {}
     options = config.options(section)
@@ -525,7 +525,7 @@ def featureComputation(fld, cfg, sensor, out_fld = None, extent = None):
         feat_tiles[t].append(out_name)
         if os.path.exists(envelope_fn):
             gmask_name = out_fld + os.path.basename(f) + '_GAPS.tif'
-            print envelope_fn, mask_name
+            print(envelope_fn, mask_name)
             cmd = ['otbcli_BandMathX', '-il', envelope_fn, mask_name, '-exp', '{im1b1 != 0 && im2b1 == 0}', '-out', gmask_name, 'uint8']
             subprocess.call(cmd, shell=sh)
         mask_tiles[t].append(gmask_name)
diff --git a/coregister.py b/coregister.py
index d3751aa982c8d7394224362d21eee78e4bb3693f..86782f4f0e27dde53a409797dc2e1387e95aead7 100644
--- a/coregister.py
+++ b/coregister.py
@@ -24,7 +24,7 @@ def main(argv):
     try:
         opts, args = getopt.getopt(argv, '', ['band-ref=', 'band-in=', 'step=', 'minstep=', 'minpoints=', 'maxpoints=', 'prec='])
     except getopt.GetoptError as err:
-        print str(err)
+        print(str(err))
 
     ref = args[0]
     src = args[1]
diff --git a/genL8DownloadScript.py b/genL8DownloadScript.py
index 3da0187b0a1dddb90a41df0ab0ec498fd85a5c42..c42ec4847468b9f66bb516a164b9259f8c206b9a 100644
--- a/genL8DownloadScript.py
+++ b/genL8DownloadScript.py
@@ -43,7 +43,7 @@ def findpathrows(shp):
                 else:
                     ovl[pathrows.index(pr)] += intsect.GetArea() / g.GetArea()
 
-    idx = sorted(range(len(ovl)), key=lambda k: ovl[k], reverse=True)
+    idx = sorted(list(range(len(ovl))), key=lambda k: ovl[k], reverse=True)
     tot = 0.0
     i = 0
     while i < len(ovl) and tot < 1.0:
@@ -103,7 +103,7 @@ def main(argv):
     subprocess.call(cmd,shell=sh)
     sl = gzip.open(scenelist)
     rdr = csv.reader(sl)
-    frdr = filter(lambda p: p[0][-2:] == 'T1' and p[2] >= sd and p[2] <= ed and p[4] == 'L1TP' and (str(int(p[5])).zfill(3) + str(int(p[6])).zfill(3)) in pathrows,rdr)
+    frdr = [p for p in rdr if p[0][-2:] == 'T1' and p[2] >= sd and p[2] <= ed and p[4] == 'L1TP' and (str(int(p[5])).zfill(3) + str(int(p[6])).zfill(3)) in pathrows]
     found_dates = []
     for im in frdr:
         dt = im[2][0:4]+im[2][5:7]+im[2][8:10]
@@ -124,8 +124,8 @@ def main(argv):
     subprocess.call(cmd, shell=sh)
     sl = gzip.open(scenelist)
     rdr = csv.reader(sl)
-    frdr = filter(lambda p: p[1] >= sd and p[1] <= ed and (str(int(p[4])).zfill(3) + str(
-        int(p[5])).zfill(3)) in pathrows, rdr)
+    frdr = [p for p in rdr if p[1] >= sd and p[1] <= ed and (str(int(p[4])).zfill(3) + str(
+        int(p[5])).zfill(3)) in pathrows]
     for im in frdr:
         dt = im[1][0:4] + im[1][5:7] + im[1][8:10]
         pathrow = (str(int(im[4])).zfill(3) + str(int(im[5])).zfill(3))
@@ -142,7 +142,7 @@ def main(argv):
     os.remove(scenelist)
 
     if len(found_dates) > 0:
-        print "Products have been found!"
+        print("Products have been found!")
 
     f.close()
     g.close()
diff --git a/genMosaicScript.py b/genMosaicScript.py
index 5d026ecaafcf9451fb1c2969a72f2f242918213e..f17c79490289a56f4ba4ae4cc4b33cf95a19a3e4 100644
--- a/genMosaicScript.py
+++ b/genMosaicScript.py
@@ -23,7 +23,7 @@ def main(argv):
     try:
         opts, args = getopt.getopt(argv, '', ['onstack','extent=','force'])
     except getopt.GetoptError as err:
-        print str(err)
+        print(str(err))
 
     imroot = args[0]
     dirs = [imroot + '/' + n for n in os.listdir(imroot) if os.path.isdir(imroot + '/' + n)]
diff --git a/genProcessScript.py b/genProcessScript.py
index 0bd338d5f7ed5dfea8b8192049640c058e11f9a1..7832b4befd3739ef03666f6e0b54aaac110a967d 100644
--- a/genProcessScript.py
+++ b/genProcessScript.py
@@ -10,7 +10,7 @@ def main(argv):
     try:
         opts, args = getopt.getopt(argv, '', ['cloudmask', 's2ref=', 's2bandlist=', 'makefile'])
     except getopt.GetoptError as err:
-        print str(err)
+        print(str(err))
 
     opt_str = ''
     opt_str_s2 = ''
diff --git a/genS2DownloadScript.py b/genS2DownloadScript.py
index c24ac35d338fa481ead04dbf8e282dc0409baf76..d14ca40255e7e9d3726c590c785d8958cb4b2681 100644
--- a/genS2DownloadScript.py
+++ b/genS2DownloadScript.py
@@ -48,7 +48,7 @@ def findtiles(shp):
 
     dovl = [covl[i] - covl[i - 1] for i in range(1, len(covl))]
 
-    idx = sorted(range(len(dovl)), key=lambda k: dovl[k], reverse=True)
+    idx = sorted(list(range(len(dovl))), key=lambda k: dovl[k], reverse=True)
     tot = 0.0
     i = 0
     while i < len(dovl) and tot < 1.0:
@@ -117,7 +117,7 @@ def main(argv):
         ed = datetime.date(int(args[2][0:4]), int(args[2][4:6]), int(args[2][6:8])) + datetime.timedelta(1)
         cd = sd
         valid_dates = []
-        print 'Scanning date interval for tile ' + tile + '...'
+        print('Scanning date interval for tile ' + tile + '...')
         while cd != ed:
             yy = str(cd.year)
             mm = str(cd.month)
@@ -193,7 +193,7 @@ def main(argv):
             cd += datetime.timedelta(1)
 
         if len(valid_dates) > 0:
-            print "Products have been found!"
+            print("Products have been found!")
             for dt in valid_dates:
                 f.write('python getSentinel2.py ' + opt_str + ' ' + '--sequence ' + str(dt[1]) + ' ' + dt[0] + ' ' + tile + '\n')
     f.close()
diff --git a/getLandsat8.py b/getLandsat8.py
index 704effcb1b68d992a2e1b301dac95c3c5b3ffd89..b6d878b18f3a4914fe142d33452b987d2c7d8d19 100644
--- a/getLandsat8.py
+++ b/getLandsat8.py
@@ -67,7 +67,7 @@ def main(argv):
     try:
         opts, args = getopt.getopt(argv, 'o:c:rtu:', ['url='])
     except getopt.GetoptError as err:
-        print str(err)
+        print(str(err))
 
     # Parse options
     od = os.getcwd()
@@ -102,7 +102,7 @@ def main(argv):
         print('Output directory already exists!')
     else:
         # DOWNLOAD COMMAND
-        print('Downloading ' + od + '...')
+        print(('Downloading ' + od + '...'))
         if byURL:
             out_fns = getLandsat8_AmazonAWS_byurl(url, od)
         else:
@@ -112,7 +112,7 @@ def main(argv):
         curdir = os.getcwd()
         os.chdir(od)
         ext = os.path.splitext(os.path.basename(clip_shp))[0]
-        print "Clipping..."
+        print("Clipping...")
         clip_shp_val = clip_shp
         clip_cmd = 'gdalwarp -q -of GTiff -ot UInt16 -dstnodata 0 -srcnodata 0 -cutline \"' + clip_shp_val + '\" -crop_to_cutline '
         '''
diff --git a/getS2PEPSFromShp.py b/getS2PEPSFromShp.py
index b1cdf3b413b358ab1ee8a8424d1920aee7c4520a..91930a4d3b99271adaacf24ace1635cca1901cda 100644
--- a/getS2PEPSFromShp.py
+++ b/getS2PEPSFromShp.py
@@ -24,7 +24,7 @@ def main(argv):
         sys.exit(err)
 
     shp_file = args[-2]
-    print shp_file
+    print(shp_file)
     if not os.path.exists(shp_file):
         sys.exit('%s does not exist'%shp_file)
     peps_folder = args[-1]
@@ -81,7 +81,7 @@ def main(argv):
         cmd += ['-m', sensor_mode]
     if sh == True :
         cmd += ['--windows']
-    print cmd
+    print(cmd)
     subprocess.call(cmd, shell=sh)
 
 if __name__ == '__main__':
diff --git a/getS2THEIAFromShp.py b/getS2THEIAFromShp.py
index 884b9f0b824c5cc7455691d7ad55c96be0b8f0ec..1f61cf141d15ab2d25bd8c23cbbec0dae31cc569 100644
--- a/getS2THEIAFromShp.py
+++ b/getS2THEIAFromShp.py
@@ -67,7 +67,7 @@ def main(argv):
         cmd += ['-f', date_end]
     if max_cloud != None:
         cmd += ['-m', max_cloud]
-    print cmd
+    print(cmd)
     subprocess.call(cmd, shell=sh)
 
 if __name__ == '__main__':
diff --git a/getSentinel2.py b/getSentinel2.py
index 140acf30cedf17a15d2736778cbc3c0e22f541dd..b924f7cf57c5b6bfa9ff64efaaa63fbc6c60c909 100644
--- a/getSentinel2.py
+++ b/getSentinel2.py
@@ -50,7 +50,7 @@ def readS2Metadata(mdf):
     # For each info, prepare iterator, read and store
     # 1 - CLOUDY_PIXEL_PERCENTAGE
     it = root.iter('CLOUDY_PIXEL_PERCENTAGE')
-    info = it.next()
+    info = next(it)
     out[info.tag] = float(info.text)
     # Return dictionary
     return out
@@ -72,7 +72,7 @@ def main(argv):
     try:
         opts, args = getopt.getopt(argv, 'o:c:rm:',['sequence='])
     except getopt.GetoptError as err:
-        print str(err)
+        print(str(err))
 
         # Parse options
     od = os.getcwd()
@@ -108,7 +108,7 @@ def main(argv):
         print('Output directory already exists!')
     else:
         # DOWNLOAD COMMAND
-        print('Downloading ' + od + '...')
+        print(('Downloading ' + od + '...'))
         out_fns, msk_fn = getSentinel2_AmazonAWS(args[0], args[1], od, seq)
 
         # Check if clouds exist (in tile info)
diff --git a/getVenusFromShp.py b/getVenusFromShp.py
index a59116764864af97694ce7119c03a1452cab19b4..1db2208e7d0c8df1269ffe5589c204f1fa40eca4 100644
--- a/getVenusFromShp.py
+++ b/getVenusFromShp.py
@@ -67,7 +67,7 @@ def main(argv):
         cmd += ['-f', date_end]
     if max_cloud != None:
         cmd += ['-m', max_cloud]
-    print cmd
+    print(cmd)
     subprocess.call(cmd, shell=sh)
 
 if __name__ == '__main__':
diff --git a/launchChain.py b/launchChain.py
index d540b5ad5e166dd4b49784d26c9da134a049ef63..3511c638b19d83066fca85bde8f16720681254aa 100644
--- a/launchChain.py
+++ b/launchChain.py
@@ -1,4 +1,4 @@
-import ConfigParser
+import configparser
 import fnmatch
 import getopt
 import glob
@@ -51,7 +51,7 @@ def main(argv):
     # Import config file #
     ######################
 
-    config = ConfigParser.ConfigParser()
+    config = configparser.ConfigParser()
     config.read(cfg_fn)
     base_fld = config.get('GENERAL CONFIGURATION', 'basefolder')
     # Search all Sentinel-2 and Landsat-8 images under base folder
@@ -284,7 +284,7 @@ def main(argv):
                         if not os.path.exists(ref_L8) or force_coreg:
                             cmd = ['otbcli_Superimpose', '-inr', refl, '-inm', ms_file, '-out', ref_L8, 'uint16']
                             subprocess.call(cmd, shell=sh)
-                    cmd = ['python', 'coregister.py', '--band-ref', vhrbnd, '--band-in', bnd, '--maxpoints', str(mxp), '--outsrs', dst_code_out, ref_L8, refl]
+                    cmd = ['python3', 'coregister.py', '--band-ref', vhrbnd, '--band-in', bnd, '--maxpoints', str(mxp), '--outsrs', dst_code_out, ref_L8, refl]
                     subprocess.call(cmd, shell=sh)
 
             # Sentinel-2
@@ -300,7 +300,7 @@ def main(argv):
                         if not os.path.exists(ref_S2) or force_coreg:
                             cmd = ['otbcli_Superimpose', '-inr', refl, '-inm', ms_file, '-out', ref_S2, 'uint16']
                             subprocess.call(cmd, shell=sh)
-                    cmd = ['python', 'coregister.py', '--band-ref', vhrbnd, '--band-in', bnd, '--maxpoints', str(mxp), ref_S2, refl]
+                    cmd = ['python3', 'coregister.py', '--band-ref', vhrbnd, '--band-in', bnd, '--maxpoints', str(mxp), ref_S2, refl]
                     subprocess.call(cmd, shell=sh)
 
             # Sentinel-2 THEIA
@@ -316,7 +316,7 @@ def main(argv):
                         if not os.path.exists(ref_S2THEIA) or force_coreg:
                             cmd = ['otbcli_Superimpose', '-inr', refl, '-inm', ms_file, '-out', ref_S2THEIA, 'uint16']
                             subprocess.call(cmd, shell=sh)
-                    cmd = ['python', 'coregister.py', '--band-ref', vhrbnd, '--band-in', bnd, '--maxpoints', str(mxp), ref_S2THEIA, refl]
+                    cmd = ['python3', 'coregister.py', '--band-ref', vhrbnd, '--band-in', bnd, '--maxpoints', str(mxp), ref_S2THEIA, refl]
                     subprocess.call(cmd, shell=sh)
 
             # Venus THEIA
@@ -332,7 +332,7 @@ def main(argv):
                         if not os.path.exists(ref_VenusTHEIA) or force_coreg:
                             cmd = ['otbcli_Superimpose', '-inr', refl, '-inm', ms_file, '-out', ref_VenusTHEIA, 'uint16']
                             subprocess.call(cmd, shell=sh)
-                    cmd = ['python', 'coregister.py', '--band-ref', vhrbnd, '--band-in', bnd, '--maxpoints', str(mxp), ref_VenusTHEIA, refl]
+                    cmd = ['python3', 'coregister.py', '--band-ref', vhrbnd, '--band-in', bnd, '--maxpoints', str(mxp), ref_VenusTHEIA, refl]
                     subprocess.call(cmd, shell=sh)
 
         if single_step:
@@ -387,10 +387,10 @@ def main(argv):
     cfg_S2 = readConfigFile(cfg_fn, 'SENTINEL-2 CONFIGURATION')
     cfg_S2THEIA = readConfigFile(cfg_fn, 'SENTINEL-2 THEIA CONFIGURATION')
     cfg_VenusTHEIA = readConfigFile(cfg_fn, 'VENUS THEIA CONFIGURATION')
-    n_feat_L8 = filter(lambda a: a != '', cfg_L8['feat'].split(','))
-    n_feat_S2 = filter(lambda a: a != '', cfg_S2['feat'].split(','))
-    n_feat_S2THEIA = filter(lambda a: a != '', cfg_S2THEIA['feat'].split(','))
-    n_feat_VenusTHEIA = filter(lambda a: a != '', cfg_VenusTHEIA['feat'].split(','))
+    n_feat_L8 = [a for a in cfg_L8['feat'].split(',') if a != '']
+    n_feat_S2 = [a for a in cfg_S2['feat'].split(',') if a != '']
+    n_feat_S2THEIA = [a for a in cfg_S2THEIA['feat'].split(',') if a != '']
+    n_feat_VenusTHEIA = [a for a in cfg_VenusTHEIA['feat'].split(',') if a != '']
 
     if len(n_feat_L8) > 0:
         with open(glob.glob(base_fld + '/FEAT/L8_FEAT/' + 'input_dates_*.txt')[0]) as df:
@@ -573,7 +573,7 @@ def main(argv):
                 otl = samples_fld + '/' + os.path.basename(tl)
                 ogttl.append(otl)
                 cmd_list.append(
-                    ['python', 'mrzonalstats.py', '--series-prefix', 'T', '--raster-prefix', 'F', '--band-prefix', 'D',
+                    ['python3', 'mrzonalstats.py', '--series-prefix', 'T', '--raster-prefix', 'F', '--band-prefix', 'D',
                      '--fix-nodata', '--overwrite', feat_groups_str, otl, "Segment_ID", 'mean'])
 
             queuedProcess(cmd_list, N_processes=1, shell=sh)
@@ -581,7 +581,7 @@ def main(argv):
 
             var_keys = [x for x in getFieldNames(ogttl[0]) if x not in ext_flds]
 
-            with open(samples_fld + '/field_names.csv', 'wb') as varfile:
+            with open(samples_fld + '/field_names.csv', 'w') as varfile:
                 vw = csv.writer(varfile)
                 for x in zip(var_keys, feat_to_vars):
                     vw.writerow(x)
@@ -614,7 +614,7 @@ def main(argv):
                 otl = val_fld + '/' + os.path.basename(tl)
                 ogttl.append(otl)
                 cmd_list.append(
-                    ['python', 'mrzonalstats.py', '--series-prefix', 'T', '--raster-prefix', 'F', '--band-prefix', 'D',
+                    ['python3', 'mrzonalstats.py', '--series-prefix', 'T', '--raster-prefix', 'F', '--band-prefix', 'D',
                      '--fix-nodata', '--overwrite', feat_groups_str, otl, "Segment_ID", 'mean'])
 
             queuedProcess(cmd_list, N_processes=1, shell=sh)
@@ -648,7 +648,7 @@ def main(argv):
                 otl = test_fld + '/' + os.path.basename(tl)
                 ogttl.append(otl)
                 cmd_list.append(
-                    ['python', 'mrzonalstats.py', '--series-prefix', 'T', '--raster-prefix', 'F', '--band-prefix', 'D',
+                    ['python3', 'mrzonalstats.py', '--series-prefix', 'T', '--raster-prefix', 'F', '--band-prefix', 'D',
                      '--fix-nodata', '--overwrite', feat_groups_str, otl, "Segment_ID", 'mean'])
 
             queuedProcess(cmd_list, N_processes=N_proc, shell=sh)
@@ -677,7 +677,7 @@ def main(argv):
         os.mkdir(model_fld)
 
     var_list = []
-    with open(samples_fld + '/field_names.csv', 'rb') as varfile:
+    with open(samples_fld + '/field_names.csv', 'r') as varfile:
         rdr = csv.reader(varfile)
         for row in rdr:
             if row[1] in feat_to_vars:
@@ -721,7 +721,7 @@ def main(argv):
                         accuracies.append(acc)
                         kappas.append(kappa)
                         for c,fs in zip(classes,prf[2]):
-                            if c not in fscores.keys():
+                            if c not in list(fscores.keys()):
                                 fscores[c] = []
                             fscores[c].append(fs)
 
@@ -777,7 +777,7 @@ def main(argv):
                         accuracies.append(acc)
                         kappas.append(kappa)
                         for c, fs in zip(classes, prf[2]):
-                            if c not in fscores.keys():
+                            if c not in list(fscores.keys()):
                                 fscores[c] = []
                             fscores[c].append(fs)
 
@@ -944,6 +944,6 @@ def main(argv):
 if __name__ == '__main__':
     if len(sys.argv) < 2:
         sys.exit(
-            'Usage: python launchChain.py [--runlevel < n >] [--single-step] <config-file>')
+            'Usage: python3 launchChain.py [--runlevel < n >] [--single-step] <config-file>')
     else:
         main(sys.argv[1:])
diff --git a/mrzonalstats.py b/mrzonalstats.py
index e43356d401f40757e9561c0c418e587ee1c88ef0..8cefe9ae6e6685f825dc1015632c1a1a1877072b 100644
--- a/mrzonalstats.py
+++ b/mrzonalstats.py
@@ -72,7 +72,7 @@ def generateGridBasedSubsets(in_vec, gridSize, epsg = None):
 
     #Hardcoded size of bins
     s_rect_bins = 100
-    rect_bins = [rect[t:t+s_rect_bins] for t in xrange(0,len(rect),s_rect_bins)]
+    rect_bins = [rect[t:t+s_rect_bins] for t in range(0,len(rect),s_rect_bins)]
 
     out_list = []
 
@@ -254,11 +254,11 @@ def multiZonalStatsAsArray(ras_lists, obj_vec, stats, series_prefix='T', ras_pre
                 allfields.append(ras_names[i] + bnd_names[k] + stats_fldn[cstats[s]])
 
         if i==0:
-            allobj = np.array(zstats.keys())
-            allstats = np.array(zstats.values())
+            allobj = np.array(list(zstats.keys()))
+            allstats = np.array(list(zstats.values()))
         else:
             if len(allstats) > 0:
-                allstats = np.append(allstats,np.array(zstats.values()),axis=1)
+                allstats = np.append(allstats,np.array(list(zstats.values())),axis=1)
 
         zstats = None
 
diff --git a/mtdUtils.py b/mtdUtils.py
index f4d6b15f2ecd8bb9a93777ef09167c10bf3104db..2c1303d229cb3ed384596d0ff82eedf9ee887cd4 100644
--- a/mtdUtils.py
+++ b/mtdUtils.py
@@ -358,7 +358,7 @@ def buffer(infile, outfile, buffdist):
         layer = ds_out.CreateLayer(lyr_in.GetLayerDefn().GetName(), \
                                    lyr_in.GetSpatialRef(), ogr.wkbPolygon)
         n_fields = lyr_in.GetLayerDefn().GetFieldCount()
-        for i in xrange(lyr_in.GetLayerDefn().GetFieldCount()):
+        for i in range(lyr_in.GetLayerDefn().GetFieldCount()):
             field_in = lyr_in.GetLayerDefn().GetFieldDefn(i)
             fielddef = ogr.FieldDefn(field_in.GetName(), field_in.GetType())
             layer.CreateField(fielddef)
@@ -449,7 +449,7 @@ def compactLabeledArray(arr, cnt=1, nodata=0):
     idx = np.arange(cnt, cnt + len(lbl))
     ass = {key: val for key, val in zip(lbl, idx)}
     out = convertLabels(arr, ass, nodata)
-    ass = {val: key for key, val in ass.items()}
+    ass = {val: key for key, val in list(ass.items())}
     return np.reshape(out, arr.shape), ass, cnt + len(lbl) - 1
 
 
@@ -491,13 +491,13 @@ def bufferedVectorDifference(fn1, fn2, fout, buf):
     f1 = driver.Open(fn1, 0)
 
     if f1 is None:
-        print "Could not open f1 file ", fn1
+        print("Could not open f1 file ", fn1)
         sys.exit(1)
 
     f2 = driver.Open(fn2, 0)
 
     if f2 is None:
-        print "Could not open f2 file ", fn2
+        print("Could not open f2 file ", fn2)
         sys.exit(1)
 
     layer1 = f1.GetLayer()
@@ -510,13 +510,13 @@ def bufferedVectorDifference(fn1, fn2, fout, buf):
     try:
         output = driver.CreateDataSource(outputFileName)
     except:
-        print 'Could not create output datasource ', outputFileName
+        print('Could not create output datasource ', outputFileName)
         sys.exit(1)
 
     newLayer = output.CreateLayer('SymmetricDifference', geom_type=ogr.wkbPolygon, srs=layer1.GetSpatialRef())
 
     if newLayer is None:
-        print "Could not create output layer"
+        print("Could not create output layer")
         sys.exit(1)
 
     newLayerDef = newLayer.GetLayerDefn()
@@ -691,7 +691,7 @@ def fieldsToArray(shp, flds, nodata=np.nan):
     ly = ds.GetLayer(0)
     N = ly.GetFeatureCount()
     out = np.empty((int(N), len(flds)))
-    print str(N) + ' features to read...'
+    print(str(N) + ' features to read...')
     i = 0
     for f in ly:
         j = 0
@@ -704,8 +704,8 @@ def fieldsToArray(shp, flds, nodata=np.nan):
             j += 1
         i += 1
         if i%100 == 0:
-            print str(i) + ' features read...'
-    print 'Finished!'
+            print(str(i) + ' features read...')
+    print('Finished!')
     ds = None
     return out
 
@@ -759,7 +759,7 @@ def shapefileToCsv(fn, out, fields, points=True):
     outRef.ImportFromEPSG(4326)
     ct = osr.CoordinateTransformation(inRef, outRef)
 
-    with open(out, 'wb') as csvout:
+    with open(out, 'w') as csvout:
 
         if points and ly.GetGeomType() == ogr.wkbPoint:
             row = fields + ['XCOORD', 'YCOORD']
diff --git a/prepareS2PEPS.py b/prepareS2PEPS.py
index 9638d99b1dcf03c3f7b425363af8f763271c070a..cd512e65a41fb477a4050765b17e853344d665a2 100644
--- a/prepareS2PEPS.py
+++ b/prepareS2PEPS.py
@@ -17,7 +17,7 @@ def genScript(argv):
     try:
         opts, args = getopt.getopt(argv, 'o:c:t:',['srs='])
     except getopt.GetoptError as err:
-        print str(err)
+        print(str(err))
 
     # Get sub-folders names
     dirs = [args[0] + os.sep + dn for dn in os.listdir(args[0]) if os.path.isdir(args[0] + os.sep + dn)]
@@ -73,7 +73,7 @@ def prepare(argv):
     try:
         opts, args = getopt.getopt(argv, 'o:c:', ['srs='])
     except getopt.GetoptError as err:
-        print str(err)
+        print(str(err))
 
     # Parse options
     od = os.getcwd()
@@ -97,7 +97,7 @@ def prepare(argv):
     if os.environ.get('GDAL_DATA') == None:
         sys.exit('Please set GDAL_DATA environment variable!')
 
-    print('Processing ' + src_dir + '...')
+    print(('Processing ' + src_dir + '...'))
 
     # Create output directories
     if not os.path.exists(od):
@@ -113,7 +113,7 @@ def prepare(argv):
     curdir = os.getcwd()
     os.chdir(od)
 
-    with open(od + '/tileInfo.json', 'wb') as mf:
+    with open(od + '/tileInfo.json', 'w') as mf:
         mf.write('*** Dummy metadata file for S2-L1C-PEPS_' + str(seqnum) + '_' + tile_date + '_' + tile_id + ' ***')
 
     # Prepare ROI (full extent if not clipping)
@@ -158,7 +158,7 @@ def prepare(argv):
     nbval = len(np.unique(ly.ReadAsArray()))
     ds = None
     if nbval == 1 :
-        print(" {}_{} doesn't cover requested area, deleting folder".format(tile_date,tile_id))
+        print((" {}_{} doesn't cover requested area, deleting folder".format(tile_date,tile_id)))
         shutil.rmtree(od)
 
     os.chdir(curdir)
diff --git a/prepareS2THEIA.py b/prepareS2THEIA.py
index 9f4f0ec9231aed43922ad12a99aac9eaa853a79e..77764f3ad66542423fb14373ed27ff5317691853 100644
--- a/prepareS2THEIA.py
+++ b/prepareS2THEIA.py
@@ -16,7 +16,7 @@ def genScript(argv):
     try:
         opts, args = getopt.getopt(argv, 'o:c:t:',['srs='])
     except getopt.GetoptError as err:
-        print str(err)
+        print(str(err))
 
     # Get sub-folders names
     dirs = [args[0] + '/' + dn for dn in os.listdir(args[0]) if os.path.isdir(args[0] + '/' + dn)]
@@ -74,7 +74,7 @@ def prepare(argv):
     try:
         opts, args = getopt.getopt(argv, 'o:c:', ['srs='])
     except getopt.GetoptError as err:
-        print str(err)
+        print(str(err))
 
     # Parse options
     od = os.getcwd()
@@ -98,7 +98,7 @@ def prepare(argv):
     if os.environ.get('GDAL_DATA') == None:
         sys.exit('Please set GDAL_DATA environment variable!')
 
-    print('Processing ' + src_dir + '...')
+    print(('Processing ' + src_dir + '...'))
 
     # Create output directories
     if not os.path.exists(od):
@@ -158,7 +158,7 @@ def prepare(argv):
     nbval = len(np.unique(ly.ReadAsArray()))
     ds = None
     if nbval == 1 :
-        print(" {}_{} doesn't cover requested area, deleting folder".format(tile_date,tile_id))
+        print((" {}_{} doesn't cover requested area, deleting folder".format(tile_date,tile_id)))
         shutil.rmtree(od)
 
     os.chdir(curdir)
diff --git a/prepareVENUS.py b/prepareVENUS.py
index 9e94eb58b0760452937c596a88dd9caabcdffb4d..86360dc11ee16196a42069bd4c6b90a3c2a776ab 100644
--- a/prepareVENUS.py
+++ b/prepareVENUS.py
@@ -16,7 +16,7 @@ def genScript(argv):
     try:
         opts, args = getopt.getopt(argv, 'o:c:t:',['srs='])
     except getopt.GetoptError as err:
-        print str(err)
+        print(str(err))
 
     # Get sub-folders names
     dirs = [os.path.join(args[0], dn) for dn in os.listdir(args[0])]
@@ -73,7 +73,7 @@ def prepare(argv):
     try:
         opts, args = getopt.getopt(argv, 'o:c:', ['srs='])
     except getopt.GetoptError as err:
-        print str(err)
+        print(str(err))
 
     # Parse options
     od = os.getcwd()
@@ -97,10 +97,10 @@ def prepare(argv):
     if os.environ.get('GDAL_DATA') == None:
         sys.exit('Please set GDAL_DATA environment variable!')
 
-    print('Processing ' + src_dir + '...')
+    print(('Processing ' + src_dir + '...'))
 
     # Create output directories
-    print od
+    print(od)
     if not os.path.exists(od):
         os.mkdir(od)
     seqnum = 0
@@ -153,7 +153,7 @@ def prepare(argv):
     nbval = len(np.unique(ly.ReadAsArray()))
     ds = None
     if nbval == 1 :
-        print(" {}_{} doesn't cover requested area, deleting folder".format(tile_date,tile_id))
+        print((" {}_{} doesn't cover requested area, deleting folder".format(tile_date,tile_id)))
         shutil.rmtree(od)
 
     os.chdir(curdir)
@@ -169,7 +169,7 @@ if __name__ == '__main__':
             dirs = [os.path.join(sys.argv[-1],dir) for dir in os.listdir(sys.argv[-1]) if os.path.isdir(os.path.join(sys.argv[-1],dir))]
             for dir_name in dirs:
                 hdr_file = dir_name.split('.')[0] + '.HDR'
-                print hdr_file
+                print(hdr_file)
                 os.rename(hdr_file,os.path.join(dir_name, os.path.basename(hdr_file)))
         mtd = glob.glob(os.path.join(sys.argv[-1], '*_L2VALD_*.HDR'))
         if len(mtd) > 0:
diff --git a/preprocess.py b/preprocess.py
index 4fc38a3248061c9b9f51ca46b520501fdff10af7..b5351a8c35ed65115d98056868860d6a5a26d3dc 100644
--- a/preprocess.py
+++ b/preprocess.py
@@ -285,7 +285,7 @@ def main(argv):
     try:
         opts, args = getopt.getopt(argv, '', ['cloudmask', 's2ref=', 's2bandlist='])
     except getopt.GetoptError as err:
-        print str(err)
+        print(str(err))
 
     cmask = None
     s2_ref = None
diff --git a/validationFramework.py b/validationFramework.py
index 890de2a5c54a3c53b63dadb93e15a815f421e1f5..a69b4e478b828e04921b18a10fabfa3feb873898 100644
--- a/validationFramework.py
+++ b/validationFramework.py
@@ -90,7 +90,7 @@ def surfaceValidation(ref_shp,val_shp,out,cfield,pfield=None):
                 y_pred.append(int(p))
                 y_wght.append(og.GetArea())
             elif og is None:
-                print vg.GetArea()
+                print(vg.GetArea())
 
     ref_ds = None
     val_ds = None
@@ -220,7 +220,7 @@ def kFoldRefToSamples(train_samples, test_samples, train_folds, test_folds):
 def kFoldReport(fscores,accs,kappas,txt_out):
     # Format text output
     tid = open(txt_out, "w")
-    classes = fscores.keys()
+    classes = list(fscores.keys())
     ndigit = int(math.ceil(math.log10(np.max(classes))))
     hd_fmt = '[ %' + str(15) + 'd ]'
 
@@ -251,8 +251,8 @@ def kFoldReport(fscores,accs,kappas,txt_out):
     tid.close()
 
 def readKFoldReport(fn,cln,tag = None):
-    fid = open(fn, 'rb')
-    cid = open(cln, 'rb')
+    fid = open(fn, 'r')
+    cid = open(cln, 'r')
     # read report
     classes = []
     fsc_mean = []
@@ -312,7 +312,7 @@ def kFoldReportToLatexTable(fn,cln,tag=None,ofn=None,mode='vertical'):
     dct = readKFoldReport(fn,cln,tag)
     if ofn == None:
         ofn = fn.replace('.txt','.tex')
-    oid = open(ofn,'wb')
+    oid = open(ofn,'w')
     oid.write('\\documentclass{standalone}\n')
     oid.write('\\usepackage[dvipsnames]{xcolor}\n')
     oid.write('\\renewcommand\\familydefault{\\sfdefault}\n')
@@ -403,10 +403,10 @@ def getVariableImportance(shp,fields,code,out_fn, nbtrees = 100, nodesize = 25,
         names_dict = {x:x for x in fields}
 
     imp_dict = {fields[i]:importance[i] for i in range(len(fields))}
-    with open(out_fn, mode='wb') as outfile:
+    with open(out_fn, mode='w') as outfile:
         outfile.write('#OOB Accuracy: %6.4f%%\n' % (100 * oob_score))
         writer = csv.writer(outfile)
-        for key,val in sorted(imp_dict.iteritems(), key=lambda (k,v):(v,k), reverse=True):
+        for key,val in sorted(iter(imp_dict.items()), key=lambda k_v:(k_v[1],k_v[0]), reverse=True):
             writer.writerow([key, names_dict[key],val])
 
     return oob_score
\ No newline at end of file
diff --git a/wthTreeIndex.py b/wthTreeIndex.py
index af74d08d8379fa155b867ccf55fd08990331905c..9383885a4240cd79f65fb497ba78c8fc5a1bb4dc 100644
--- a/wthTreeIndex.py
+++ b/wthTreeIndex.py
@@ -36,7 +36,7 @@ def treeIndex(img,red_band,nir_band,radius=2,tau=0.005):
     cmd = ['otbcli_BandMath', '-il', img, '-exp', '5000*(1+(im1b' + str(nir_band) + '-im1b' + str(red_band) + ')/(im1b' + str(nir_band) + '+im1b' + str(red_band) + '))', '-out', td + '/tmp_ndvi.tif', 'uint16']
     subprocess.call(cmd,shell=sh)
     th = getThreshold(td+'/tmp_ndvi.tif')
-    print 'Threshold = ' + str(th)
+    print('Threshold = ' + str(th))
     # Morphological opening
     cmd = ['otbcli_GrayScaleMorphologicalOperation', '-in', td + '/tmp_ndvi.tif', '-structype', 'ball', '-structype.ball.xradius', str(radius), '-structype.ball.yradius', str(radius), '-filter', 'opening', '-out', td + '/tmp_ndvi_open.tif', 'uint16']
     subprocess.call(cmd, shell=sh)
@@ -56,7 +56,7 @@ def main(argv):
     try:
         opts, args = getopt.getopt(argv, '', ['red=', 'nir=', 'radius=', 'tau='])
     except getopt.GetoptError as err:
-        print str(err)
+        print(str(err))
 
     red = None
     nir = None